diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap-wakeupgen.c')
-rw-r--r-- | arch/arm/mach-omap2/omap-wakeupgen.c | 114 |
1 files changed, 89 insertions, 25 deletions
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index d811c77..05fdebf 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -33,18 +33,23 @@ #include "omap4-sar-layout.h" #include "common.h" -#define NR_REG_BANKS 4 -#define MAX_IRQS 128 +#define MAX_NR_REG_BANKS 5 +#define MAX_IRQS 160 #define WKG_MASK_ALL 0x00000000 #define WKG_UNMASK_ALL 0xffffffff #define CPU_ENA_OFFSET 0x400 #define CPU0_ID 0x0 #define CPU1_ID 0x1 +#define OMAP4_NR_BANKS 4 +#define OMAP4_NR_IRQS 128 static void __iomem *wakeupgen_base; static void __iomem *sar_base; static DEFINE_SPINLOCK(wakeupgen_lock); static unsigned int irq_target_cpu[NR_IRQS]; +static unsigned int irq_banks = MAX_NR_REG_BANKS; +static unsigned int max_irqs = MAX_IRQS; +static unsigned int omap_secure_apis; /* * Static helper functions. @@ -146,13 +151,13 @@ static void wakeupgen_unmask(struct irq_data *d) } #ifdef CONFIG_HOTPLUG_CPU -static DEFINE_PER_CPU(u32 [NR_REG_BANKS], irqmasks); +static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks); static void _wakeupgen_save_masks(unsigned int cpu) { u8 i; - for (i = 0; i < NR_REG_BANKS; i++) + for (i = 0; i < irq_banks; i++) per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu); } @@ -160,7 +165,7 @@ static void _wakeupgen_restore_masks(unsigned int cpu) { u8 i; - for (i = 0; i < NR_REG_BANKS; i++) + for (i = 0; i < irq_banks; i++) wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu); } @@ -168,7 +173,7 @@ static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg) { u8 i; - for (i = 0; i < NR_REG_BANKS; i++) + for (i = 0; i < irq_banks; i++) wakeupgen_writel(reg, i, cpu); } @@ -196,25 +201,14 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set) #endif #ifdef CONFIG_CPU_PM -/* - * Save WakeupGen interrupt context in SAR BANK3. Restore is done by - * ROM code. WakeupGen IP is integrated along with GIC to manage the - * interrupt wakeups from CPU low power states. It manages - * masking/unmasking of Shared peripheral interrupts(SPI). So the - * interrupt enable/disable control should be in sync and consistent - * at WakeupGen and GIC so that interrupts are not lost. - */ -static void irq_save_context(void) +static inline void omap4_irq_save_context(void) { u32 i, val; if (omap_rev() == OMAP4430_REV_ES1_0) return; - if (!sar_base) - sar_base = omap4_get_sar_ram_base(); - - for (i = 0; i < NR_REG_BANKS; i++) { + for (i = 0; i < irq_banks; i++) { /* Save the CPUx interrupt mask for IRQ 0 to 127 */ val = wakeupgen_readl(i, 0); sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i); @@ -254,6 +248,53 @@ static void irq_save_context(void) val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); val |= SAR_BACKUP_STATUS_WAKEUPGEN; __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); + +} + +static inline void omap5_irq_save_context(void) +{ + u32 i, val; + + for (i = 0; i < irq_banks; i++) { + /* Save the CPUx interrupt mask for IRQ 0 to 159 */ + val = wakeupgen_readl(i, 0); + sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU0, i); + val = wakeupgen_readl(i, 1); + sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU1, i); + sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0, i); + sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1, i); + } + + /* Save AuxBoot* registers */ + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET); + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET); + + /* Set the Backup Bit Mask status */ + val = __raw_readl(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); + val |= SAR_BACKUP_STATUS_WAKEUPGEN; + __raw_writel(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); + +} + +/* + * Save WakeupGen interrupt context in SAR BANK3. Restore is done by + * ROM code. WakeupGen IP is integrated along with GIC to manage the + * interrupt wakeups from CPU low power states. It manages + * masking/unmasking of Shared peripheral interrupts(SPI). So the + * interrupt enable/disable control should be in sync and consistent + * at WakeupGen and GIC so that interrupts are not lost. + */ +static void irq_save_context(void) +{ + if (!sar_base) + sar_base = omap4_get_sar_ram_base(); + + if (soc_is_omap54xx()) + omap5_irq_save_context(); + else + omap4_irq_save_context(); } /* @@ -262,9 +303,14 @@ static void irq_save_context(void) static void irq_sar_clear(void) { u32 val; - val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); + u32 offset = SAR_BACKUP_STATUS_OFFSET; + + if (soc_is_omap54xx()) + offset = OMAP5_SAR_BACKUP_STATUS_OFFSET; + + val = __raw_readl(sar_base + offset); val &= ~SAR_BACKUP_STATUS_WAKEUPGEN; - __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); + __raw_writel(val, sar_base + offset); } /* @@ -336,13 +382,25 @@ static struct notifier_block irq_notifier_block = { static void __init irq_pm_init(void) { - cpu_pm_register_notifier(&irq_notifier_block); + /* FIXME: Remove this when MPU OSWR support is added */ + if (!soc_is_omap54xx()) + cpu_pm_register_notifier(&irq_notifier_block); } #else static void __init irq_pm_init(void) {} #endif +void __iomem *omap_get_wakeupgen_base(void) +{ + return wakeupgen_base; +} + +int omap_secure_apis_support(void) +{ + return omap_secure_apis; +} + /* * Initialise the wakeupgen module. */ @@ -358,12 +416,18 @@ int __init omap_wakeupgen_init(void) } /* Static mapping, never released */ - wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K); + wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K); if (WARN_ON(!wakeupgen_base)) return -ENOMEM; + if (cpu_is_omap44xx()) { + irq_banks = OMAP4_NR_BANKS; + max_irqs = OMAP4_NR_IRQS; + omap_secure_apis = 1; + } + /* Clear all IRQ bitmasks at wakeupGen level */ - for (i = 0; i < NR_REG_BANKS; i++) { + for (i = 0; i < irq_banks; i++) { wakeupgen_writel(0, i, CPU0_ID); wakeupgen_writel(0, i, CPU1_ID); } @@ -382,7 +446,7 @@ int __init omap_wakeupgen_init(void) */ /* Associate all the IRQs to boot CPU like GIC init does. */ - for (i = 0; i < NR_IRQS; i++) + for (i = 0; i < max_irqs; i++) irq_target_cpu[i] = boot_cpu; irq_hotplug_init(); |