WakeupGen IP is integrated along with GIC to manage the interrupt wakeups from CPU low power states. It's located in always ON power domain. 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. Considering this GIC and WakeupGen save and restore is done together. Signed-off-by: Santosh Shilimkar <santosh.shilimkar@xxxxxx> Cc: Kevin Hilman <khilman@xxxxxx> --- arch/arm/mach-omap2/include/mach/omap-wakeupgen.h | 1 + arch/arm/mach-omap2/omap-wakeupgen.c | 81 +++++++++++++++++++++ arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 2 + arch/arm/mach-omap2/omap4-sar-layout.h | 11 +++ 4 files changed, 95 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h index f10d106..66f31c3 100644 --- a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h +++ b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h @@ -37,4 +37,5 @@ extern int __init omap_wakeupgen_init(void); extern void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set); +extern void omap_wakeupgen_save(void); #endif diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index d9d2a3e..345a55c 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -24,6 +24,9 @@ #include <asm/hardware/gic.h> #include <mach/omap-wakeupgen.h> +#include <mach/omap4-common.h> + +#include "omap4-sar-layout.h" #define NR_BANKS 4 #define MAX_IRQS 128 @@ -35,6 +38,7 @@ /* WakeupGen Base addres */ static void __iomem *wakeupgen_base; +static void __iomem *sar_base; static DEFINE_PER_CPU(u32 [NR_BANKS], irqmasks); static DEFINE_SPINLOCK(wakeupgen_lock); @@ -54,6 +58,11 @@ static inline void wakeupgen_writel(u32 val, u8 idx, u32 cpu) (cpu * CPU_ENA_OFFSET) + (idx * 4)); } +static inline void sar_writel(u32 val, u32 offset, u8 idx) +{ + __raw_writel(val, sar_base + offset + (idx * 4)); +} + static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg) { u8 i; @@ -236,3 +245,75 @@ int __init omap_wakeupgen_init(void) return 0; } + +/** + * omap_wakeupgen_save() - WakeupGen context save function + * + * Save WakewupGen 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's located in + * always ON power domain. 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. Hence GIC and WakeupGen are saved + * and restored together. + + * During normal operation, WakeupGen delivers external interrupts + * directly to the GIC. When the CPU asserts StandbyWFI, indicating + * it wants to enter lowpower state, the Standby Controller checks + * with the WakeupGen unit using the idlereq/idleack handshake to make + * sure there is no incoming interrupts. + */ + +void omap_wakeupgen_save(void) +{ + u8 i; + u32 val; + + if (omap_rev() == OMAP4430_REV_ES1_0) + return; + + if (!sar_base) + sar_base = omap4_get_sar_ram_base(); + + for (i = 0; i < NR_BANKS; i++) { + /* Save the CPUx interrupt mask for IRQ 0 to 127 */ + val = wakeupgen_readl(i, 0); + sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i); + val = wakeupgen_readl(i, 1); + sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i); + + /* + * Disable the secure interrupts for CPUx. The restore + * code blindly restores secure and non-secure interrupt + * masks from SAR RAM. Secure interrupts are not suppose + * to be enabled from HLOS. So overwrite the SAR location + * so that the secure interrupt remains disabled. + */ + sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i); + sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i); + } + + /* Save AuxBoot* registers */ + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET); + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET); + + /* Save SyncReq generation logic */ + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET); + val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + __raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET); + + /* Save SyncReq generation logic */ + val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK); + __raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET); + val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN); + __raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET); + + /* Set the Backup Bit Mask status */ + val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); + val |= SAR_BACKUP_STATUS_WAKEUPGEN; + __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); +} diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c index 446b956..ddf5b72 100644 --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c @@ -52,6 +52,7 @@ #include <plat/omap44xx.h> #include <mach/omap4-common.h> +#include <mach/omap-wakeupgen.h> #include "omap4-sar-layout.h" #include "pm.h" @@ -292,6 +293,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) * GIC lost during MPU OFF and OSWR */ if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) { + omap_wakeupgen_save(); gic_save_context(); save_state = 3; } diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h index baac4c0..3f3e3c9 100644 --- a/arch/arm/mach-omap2/omap4-sar-layout.h +++ b/arch/arm/mach-omap2/omap4-sar-layout.h @@ -50,4 +50,15 @@ #define SAR_BACKUP_STATUS_GIC_CPU0 0x1 #define SAR_BACKUP_STATUS_GIC_CPU1 0x2 +/* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */ +#define WAKEUPGENENB_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x684) +#define WAKEUPGENENB_SECURE_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x694) +#define WAKEUPGENENB_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6a4) +#define WAKEUPGENENB_SECURE_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6b4) +#define AUXCOREBOOT0_OFFSET (SAR_BANK3_OFFSET + 0x6c4) +#define AUXCOREBOOT1_OFFSET (SAR_BANK3_OFFSET + 0x6c8) +#define PTMSYNCREQ_MASK_OFFSET (SAR_BANK3_OFFSET + 0x6cc) +#define PTMSYNCREQ_EN_OFFSET (SAR_BANK3_OFFSET + 0x6d0) +#define SAR_BACKUP_STATUS_WAKEUPGEN 0x10 + #endif -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html