0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/kernel.h>
0017 #include <linux/init.h>
0018 #include <linux/io.h>
0019 #include <linux/irq.h>
0020 #include <linux/irqchip.h>
0021 #include <linux/irqdomain.h>
0022 #include <linux/of_address.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/cpu.h>
0025 #include <linux/notifier.h>
0026 #include <linux/cpu_pm.h>
0027
0028 #include "omap-wakeupgen.h"
0029 #include "omap-secure.h"
0030
0031 #include "soc.h"
0032 #include "omap4-sar-layout.h"
0033 #include "common.h"
0034 #include "pm.h"
0035
0036 #define AM43XX_NR_REG_BANKS 7
0037 #define AM43XX_IRQS 224
0038 #define MAX_NR_REG_BANKS AM43XX_NR_REG_BANKS
0039 #define MAX_IRQS AM43XX_IRQS
0040 #define DEFAULT_NR_REG_BANKS 5
0041 #define DEFAULT_IRQS 160
0042 #define WKG_MASK_ALL 0x00000000
0043 #define WKG_UNMASK_ALL 0xffffffff
0044 #define CPU_ENA_OFFSET 0x400
0045 #define CPU0_ID 0x0
0046 #define CPU1_ID 0x1
0047 #define OMAP4_NR_BANKS 4
0048 #define OMAP4_NR_IRQS 128
0049
0050 #define SYS_NIRQ1_EXT_SYS_IRQ_1 7
0051 #define SYS_NIRQ2_EXT_SYS_IRQ_2 119
0052
0053 static void __iomem *wakeupgen_base;
0054 static void __iomem *sar_base;
0055 static DEFINE_RAW_SPINLOCK(wakeupgen_lock);
0056 static unsigned int irq_target_cpu[MAX_IRQS];
0057 static unsigned int irq_banks = DEFAULT_NR_REG_BANKS;
0058 static unsigned int max_irqs = DEFAULT_IRQS;
0059 static unsigned int omap_secure_apis;
0060
0061 #ifdef CONFIG_CPU_PM
0062 static unsigned int wakeupgen_context[MAX_NR_REG_BANKS];
0063 #endif
0064
0065 struct omap_wakeupgen_ops {
0066 void (*save_context)(void);
0067 void (*restore_context)(void);
0068 };
0069
0070 static struct omap_wakeupgen_ops *wakeupgen_ops;
0071
0072
0073
0074
0075 static inline u32 wakeupgen_readl(u8 idx, u32 cpu)
0076 {
0077 return readl_relaxed(wakeupgen_base + OMAP_WKG_ENB_A_0 +
0078 (cpu * CPU_ENA_OFFSET) + (idx * 4));
0079 }
0080
0081 static inline void wakeupgen_writel(u32 val, u8 idx, u32 cpu)
0082 {
0083 writel_relaxed(val, wakeupgen_base + OMAP_WKG_ENB_A_0 +
0084 (cpu * CPU_ENA_OFFSET) + (idx * 4));
0085 }
0086
0087 static inline void sar_writel(u32 val, u32 offset, u8 idx)
0088 {
0089 writel_relaxed(val, sar_base + offset + (idx * 4));
0090 }
0091
0092 static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index)
0093 {
0094
0095
0096
0097
0098 *reg_index = irq >> 5;
0099 *bit_posn = irq %= 32;
0100
0101 return 0;
0102 }
0103
0104 static void _wakeupgen_clear(unsigned int irq, unsigned int cpu)
0105 {
0106 u32 val, bit_number;
0107 u8 i;
0108
0109 if (_wakeupgen_get_irq_info(irq, &bit_number, &i))
0110 return;
0111
0112 val = wakeupgen_readl(i, cpu);
0113 val &= ~BIT(bit_number);
0114 wakeupgen_writel(val, i, cpu);
0115 }
0116
0117 static void _wakeupgen_set(unsigned int irq, unsigned int cpu)
0118 {
0119 u32 val, bit_number;
0120 u8 i;
0121
0122 if (_wakeupgen_get_irq_info(irq, &bit_number, &i))
0123 return;
0124
0125 val = wakeupgen_readl(i, cpu);
0126 val |= BIT(bit_number);
0127 wakeupgen_writel(val, i, cpu);
0128 }
0129
0130
0131
0132
0133 static void wakeupgen_mask(struct irq_data *d)
0134 {
0135 unsigned long flags;
0136
0137 raw_spin_lock_irqsave(&wakeupgen_lock, flags);
0138 _wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]);
0139 raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
0140 irq_chip_mask_parent(d);
0141 }
0142
0143
0144
0145
0146 static void wakeupgen_unmask(struct irq_data *d)
0147 {
0148 unsigned long flags;
0149
0150 raw_spin_lock_irqsave(&wakeupgen_lock, flags);
0151 _wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]);
0152 raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
0153 irq_chip_unmask_parent(d);
0154 }
0155
0156
0157
0158
0159
0160 static int wakeupgen_irq_set_type(struct irq_data *d, unsigned int type)
0161 {
0162 bool inverted = false;
0163
0164 switch (type) {
0165 case IRQ_TYPE_LEVEL_LOW:
0166 type &= ~IRQ_TYPE_LEVEL_MASK;
0167 type |= IRQ_TYPE_LEVEL_HIGH;
0168 inverted = true;
0169 break;
0170 case IRQ_TYPE_EDGE_FALLING:
0171 type &= ~IRQ_TYPE_EDGE_BOTH;
0172 type |= IRQ_TYPE_EDGE_RISING;
0173 inverted = true;
0174 break;
0175 default:
0176 break;
0177 }
0178
0179 if (inverted && d->hwirq != SYS_NIRQ1_EXT_SYS_IRQ_1 &&
0180 d->hwirq != SYS_NIRQ2_EXT_SYS_IRQ_2)
0181 pr_warn("wakeupgen: irq%li polarity inverted in dts\n",
0182 d->hwirq);
0183
0184 return irq_chip_set_type_parent(d, type);
0185 }
0186
0187 #ifdef CONFIG_HOTPLUG_CPU
0188 static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
0189
0190 static void _wakeupgen_save_masks(unsigned int cpu)
0191 {
0192 u8 i;
0193
0194 for (i = 0; i < irq_banks; i++)
0195 per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu);
0196 }
0197
0198 static void _wakeupgen_restore_masks(unsigned int cpu)
0199 {
0200 u8 i;
0201
0202 for (i = 0; i < irq_banks; i++)
0203 wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu);
0204 }
0205
0206 static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
0207 {
0208 u8 i;
0209
0210 for (i = 0; i < irq_banks; i++)
0211 wakeupgen_writel(reg, i, cpu);
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221 static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
0222 {
0223 unsigned long flags;
0224
0225 raw_spin_lock_irqsave(&wakeupgen_lock, flags);
0226 if (set) {
0227 _wakeupgen_save_masks(cpu);
0228 _wakeupgen_set_all(cpu, WKG_MASK_ALL);
0229 } else {
0230 _wakeupgen_set_all(cpu, WKG_UNMASK_ALL);
0231 _wakeupgen_restore_masks(cpu);
0232 }
0233 raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
0234 }
0235 #endif
0236
0237 #ifdef CONFIG_CPU_PM
0238 static inline void omap4_irq_save_context(void)
0239 {
0240 u32 i, val;
0241
0242 if (omap_rev() == OMAP4430_REV_ES1_0)
0243 return;
0244
0245 for (i = 0; i < irq_banks; i++) {
0246
0247 val = wakeupgen_readl(i, 0);
0248 sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
0249 val = wakeupgen_readl(i, 1);
0250 sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i);
0251
0252
0253
0254
0255
0256
0257
0258
0259 sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
0260 sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
0261 }
0262
0263
0264 val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
0265 writel_relaxed(val, sar_base + AUXCOREBOOT0_OFFSET);
0266 val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_1);
0267 writel_relaxed(val, sar_base + AUXCOREBOOT1_OFFSET);
0268
0269
0270 val = readl_relaxed(wakeupgen_base + OMAP_PTMSYNCREQ_MASK);
0271 writel_relaxed(val, sar_base + PTMSYNCREQ_MASK_OFFSET);
0272 val = readl_relaxed(wakeupgen_base + OMAP_PTMSYNCREQ_EN);
0273 writel_relaxed(val, sar_base + PTMSYNCREQ_EN_OFFSET);
0274
0275
0276 val = readl_relaxed(sar_base + SAR_BACKUP_STATUS_OFFSET);
0277 val |= SAR_BACKUP_STATUS_WAKEUPGEN;
0278 writel_relaxed(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
0279
0280 }
0281
0282 static inline void omap5_irq_save_context(void)
0283 {
0284 u32 i, val;
0285
0286 for (i = 0; i < irq_banks; i++) {
0287
0288 val = wakeupgen_readl(i, 0);
0289 sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU0, i);
0290 val = wakeupgen_readl(i, 1);
0291 sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU1, i);
0292 sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
0293 sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
0294 }
0295
0296
0297 val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
0298 writel_relaxed(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET);
0299 val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
0300 writel_relaxed(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET);
0301
0302
0303 val = readl_relaxed(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
0304 val |= SAR_BACKUP_STATUS_WAKEUPGEN;
0305 writel_relaxed(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
0306
0307 }
0308
0309 static inline void am43xx_irq_save_context(void)
0310 {
0311 u32 i;
0312
0313 for (i = 0; i < irq_banks; i++) {
0314 wakeupgen_context[i] = wakeupgen_readl(i, 0);
0315 wakeupgen_writel(0, i, CPU0_ID);
0316 }
0317 }
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327 static void irq_save_context(void)
0328 {
0329
0330 if (soc_is_dra7xx())
0331 return;
0332
0333 if (wakeupgen_ops && wakeupgen_ops->save_context)
0334 wakeupgen_ops->save_context();
0335 }
0336
0337
0338
0339
0340 static void irq_sar_clear(void)
0341 {
0342 u32 val;
0343 u32 offset = SAR_BACKUP_STATUS_OFFSET;
0344
0345 if (soc_is_dra7xx())
0346 return;
0347
0348 if (soc_is_omap54xx())
0349 offset = OMAP5_SAR_BACKUP_STATUS_OFFSET;
0350
0351 val = readl_relaxed(sar_base + offset);
0352 val &= ~SAR_BACKUP_STATUS_WAKEUPGEN;
0353 writel_relaxed(val, sar_base + offset);
0354 }
0355
0356 static void am43xx_irq_restore_context(void)
0357 {
0358 u32 i;
0359
0360 for (i = 0; i < irq_banks; i++)
0361 wakeupgen_writel(wakeupgen_context[i], i, CPU0_ID);
0362 }
0363
0364 static void irq_restore_context(void)
0365 {
0366 if (wakeupgen_ops && wakeupgen_ops->restore_context)
0367 wakeupgen_ops->restore_context();
0368 }
0369
0370
0371
0372
0373
0374 static void irq_save_secure_context(void)
0375 {
0376 u32 ret;
0377 ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,
0378 FLAG_START_CRITICAL,
0379 0, 0, 0, 0, 0);
0380 if (ret != API_HAL_RET_VALUE_OK)
0381 pr_err("GIC and Wakeupgen context save failed\n");
0382 }
0383
0384
0385 static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {
0386 .save_context = omap4_irq_save_context,
0387 .restore_context = irq_sar_clear,
0388 };
0389
0390 static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {
0391 .save_context = omap5_irq_save_context,
0392 .restore_context = irq_sar_clear,
0393 };
0394
0395 static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {
0396 .save_context = am43xx_irq_save_context,
0397 .restore_context = am43xx_irq_restore_context,
0398 };
0399 #else
0400 static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {};
0401 static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {};
0402 static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {};
0403 #endif
0404
0405 #ifdef CONFIG_HOTPLUG_CPU
0406 static int omap_wakeupgen_cpu_online(unsigned int cpu)
0407 {
0408 wakeupgen_irqmask_all(cpu, 0);
0409 return 0;
0410 }
0411
0412 static int omap_wakeupgen_cpu_dead(unsigned int cpu)
0413 {
0414 wakeupgen_irqmask_all(cpu, 1);
0415 return 0;
0416 }
0417
0418 static void __init irq_hotplug_init(void)
0419 {
0420 cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "arm/omap-wake:online",
0421 omap_wakeupgen_cpu_online, NULL);
0422 cpuhp_setup_state_nocalls(CPUHP_ARM_OMAP_WAKE_DEAD,
0423 "arm/omap-wake:dead", NULL,
0424 omap_wakeupgen_cpu_dead);
0425 }
0426 #else
0427 static void __init irq_hotplug_init(void)
0428 {}
0429 #endif
0430
0431 #ifdef CONFIG_CPU_PM
0432 static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v)
0433 {
0434 switch (cmd) {
0435 case CPU_CLUSTER_PM_ENTER:
0436 if (omap_type() == OMAP2_DEVICE_TYPE_GP || soc_is_am43xx())
0437 irq_save_context();
0438 else
0439 irq_save_secure_context();
0440 break;
0441 case CPU_CLUSTER_PM_EXIT:
0442 if (omap_type() == OMAP2_DEVICE_TYPE_GP || soc_is_am43xx())
0443 irq_restore_context();
0444 break;
0445 }
0446 return NOTIFY_OK;
0447 }
0448
0449 static struct notifier_block irq_notifier_block = {
0450 .notifier_call = irq_notifier,
0451 };
0452
0453 static void __init irq_pm_init(void)
0454 {
0455
0456 if (!IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
0457 cpu_pm_register_notifier(&irq_notifier_block);
0458 }
0459 #else
0460 static void __init irq_pm_init(void)
0461 {}
0462 #endif
0463
0464 void __iomem *omap_get_wakeupgen_base(void)
0465 {
0466 return wakeupgen_base;
0467 }
0468
0469 int omap_secure_apis_support(void)
0470 {
0471 return omap_secure_apis;
0472 }
0473
0474 static struct irq_chip wakeupgen_chip = {
0475 .name = "WUGEN",
0476 .irq_eoi = irq_chip_eoi_parent,
0477 .irq_mask = wakeupgen_mask,
0478 .irq_unmask = wakeupgen_unmask,
0479 .irq_retrigger = irq_chip_retrigger_hierarchy,
0480 .irq_set_type = wakeupgen_irq_set_type,
0481 .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
0482 #ifdef CONFIG_SMP
0483 .irq_set_affinity = irq_chip_set_affinity_parent,
0484 #endif
0485 };
0486
0487 static int wakeupgen_domain_translate(struct irq_domain *d,
0488 struct irq_fwspec *fwspec,
0489 unsigned long *hwirq,
0490 unsigned int *type)
0491 {
0492 if (is_of_node(fwspec->fwnode)) {
0493 if (fwspec->param_count != 3)
0494 return -EINVAL;
0495
0496
0497 if (fwspec->param[0] != 0)
0498 return -EINVAL;
0499
0500 *hwirq = fwspec->param[1];
0501 *type = fwspec->param[2];
0502 return 0;
0503 }
0504
0505 return -EINVAL;
0506 }
0507
0508 static int wakeupgen_domain_alloc(struct irq_domain *domain,
0509 unsigned int virq,
0510 unsigned int nr_irqs, void *data)
0511 {
0512 struct irq_fwspec *fwspec = data;
0513 struct irq_fwspec parent_fwspec;
0514 irq_hw_number_t hwirq;
0515 int i;
0516
0517 if (fwspec->param_count != 3)
0518 return -EINVAL;
0519 if (fwspec->param[0] != 0)
0520 return -EINVAL;
0521
0522 hwirq = fwspec->param[1];
0523 if (hwirq >= MAX_IRQS)
0524 return -EINVAL;
0525
0526 for (i = 0; i < nr_irqs; i++)
0527 irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
0528 &wakeupgen_chip, NULL);
0529
0530 parent_fwspec = *fwspec;
0531 parent_fwspec.fwnode = domain->parent->fwnode;
0532 return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
0533 &parent_fwspec);
0534 }
0535
0536 static const struct irq_domain_ops wakeupgen_domain_ops = {
0537 .translate = wakeupgen_domain_translate,
0538 .alloc = wakeupgen_domain_alloc,
0539 .free = irq_domain_free_irqs_common,
0540 };
0541
0542
0543
0544
0545 static int __init wakeupgen_init(struct device_node *node,
0546 struct device_node *parent)
0547 {
0548 struct irq_domain *parent_domain, *domain;
0549 int i;
0550 unsigned int boot_cpu = smp_processor_id();
0551 u32 val;
0552
0553 if (!parent) {
0554 pr_err("%pOF: no parent, giving up\n", node);
0555 return -ENODEV;
0556 }
0557
0558 parent_domain = irq_find_host(parent);
0559 if (!parent_domain) {
0560 pr_err("%pOF: unable to obtain parent domain\n", node);
0561 return -ENXIO;
0562 }
0563
0564 if (omap_rev() == OMAP4430_REV_ES1_0) {
0565 WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
0566 return -EPERM;
0567 }
0568
0569
0570 wakeupgen_base = of_iomap(node, 0);
0571 if (WARN_ON(!wakeupgen_base))
0572 return -ENOMEM;
0573
0574 if (cpu_is_omap44xx()) {
0575 irq_banks = OMAP4_NR_BANKS;
0576 max_irqs = OMAP4_NR_IRQS;
0577 omap_secure_apis = 1;
0578 wakeupgen_ops = &omap4_wakeupgen_ops;
0579 } else if (soc_is_omap54xx()) {
0580 wakeupgen_ops = &omap5_wakeupgen_ops;
0581 } else if (soc_is_am43xx()) {
0582 irq_banks = AM43XX_NR_REG_BANKS;
0583 max_irqs = AM43XX_IRQS;
0584 wakeupgen_ops = &am43xx_wakeupgen_ops;
0585 }
0586
0587 domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
0588 node, &wakeupgen_domain_ops,
0589 NULL);
0590 if (!domain) {
0591 iounmap(wakeupgen_base);
0592 return -ENOMEM;
0593 }
0594
0595
0596 for (i = 0; i < irq_banks; i++) {
0597 wakeupgen_writel(0, i, CPU0_ID);
0598 if (!soc_is_am43xx())
0599 wakeupgen_writel(0, i, CPU1_ID);
0600 }
0601
0602
0603
0604
0605
0606
0607
0608 for (i = 0; i < max_irqs; i++)
0609 irq_target_cpu[i] = boot_cpu;
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621 if (soc_is_omap54xx() || soc_is_dra7xx()) {
0622 val = __raw_readl(wakeupgen_base + OMAP_AMBA_IF_MODE);
0623 val |= BIT(5);
0624 omap_smc1(OMAP5_MON_AMBA_IF_INDEX, val);
0625 }
0626
0627 irq_hotplug_init();
0628 irq_pm_init();
0629
0630 sar_base = omap4_get_sar_ram_base();
0631
0632 return 0;
0633 }
0634 IRQCHIP_DECLARE(ti_wakeupgen, "ti,omap4-wugen-mpu", wakeupgen_init);