aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2010-06-16 13:59:31 -0400
committerKevin Hilman <khilman@ti.com>2011-12-08 14:29:01 -0500
commit0f3cf2ec81aeb4747624954bae2cc8decc48e12f (patch)
treef9ed87ad69bd96cf8915a3d427a3c6786b5572eb /arch
parentda82ce57a45ac2f295415ed487b9aec051db4f7f (diff)
ARM: OMAP4: PM: Add WakeupGen and secure GIC low power support
Add WakeupGen and secure GIC low power support to save and restore it's registers. WakeupGen Registers are saved to pre-defined SAR RAM layout and the restore is automatically done by hardware(ROM code) while coming out of MPUSS OSWR or Device off state. Secure GIC is saved using secure API and restored by hardware like WakeupGen. Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Jean Pihet <j-pihet@ti.com> Reviewed-by: Kevin Hilman <khilman@ti.com> Tested-by: Vishwanath BS <vishwanath.bs@ti.com> Signed-off-by: Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/omap-wakeupgen.c131
-rw-r--r--arch/arm/mach-omap2/omap4-sar-layout.h15
2 files changed, 146 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 701dfecad64b..d3d8971d7f30 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -22,10 +22,16 @@
22#include <linux/irq.h> 22#include <linux/irq.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/cpu.h> 24#include <linux/cpu.h>
25#include <linux/notifier.h>
26#include <linux/cpu_pm.h>
25 27
26#include <asm/hardware/gic.h> 28#include <asm/hardware/gic.h>
27 29
28#include <mach/omap-wakeupgen.h> 30#include <mach/omap-wakeupgen.h>
31#include <mach/omap-secure.h>
32
33#include "omap4-sar-layout.h"
34#include "common.h"
29 35
30#define NR_REG_BANKS 4 36#define NR_REG_BANKS 4
31#define MAX_IRQS 128 37#define MAX_IRQS 128
@@ -36,6 +42,7 @@
36#define CPU1_ID 0x1 42#define CPU1_ID 0x1
37 43
38static void __iomem *wakeupgen_base; 44static void __iomem *wakeupgen_base;
45static void __iomem *sar_base;
39static DEFINE_PER_CPU(u32 [NR_REG_BANKS], irqmasks); 46static DEFINE_PER_CPU(u32 [NR_REG_BANKS], irqmasks);
40static DEFINE_SPINLOCK(wakeupgen_lock); 47static DEFINE_SPINLOCK(wakeupgen_lock);
41static unsigned int irq_target_cpu[NR_IRQS]; 48static unsigned int irq_target_cpu[NR_IRQS];
@@ -55,6 +62,11 @@ static inline void wakeupgen_writel(u32 val, u8 idx, u32 cpu)
55 (cpu * CPU_ENA_OFFSET) + (idx * 4)); 62 (cpu * CPU_ENA_OFFSET) + (idx * 4));
56} 63}
57 64
65static inline void sar_writel(u32 val, u32 offset, u8 idx)
66{
67 __raw_writel(val, sar_base + offset + (idx * 4));
68}
69
58static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg) 70static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
59{ 71{
60 u8 i; 72 u8 i;
@@ -180,6 +192,93 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
180 spin_unlock_irqrestore(&wakeupgen_lock, flags); 192 spin_unlock_irqrestore(&wakeupgen_lock, flags);
181} 193}
182 194
195#ifdef CONFIG_CPU_PM
196/*
197 * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
198 * ROM code. WakeupGen IP is integrated along with GIC to manage the
199 * interrupt wakeups from CPU low power states. It manages
200 * masking/unmasking of Shared peripheral interrupts(SPI). So the
201 * interrupt enable/disable control should be in sync and consistent
202 * at WakeupGen and GIC so that interrupts are not lost.
203 */
204static void irq_save_context(void)
205{
206 u32 i, val;
207
208 if (omap_rev() == OMAP4430_REV_ES1_0)
209 return;
210
211 if (!sar_base)
212 sar_base = omap4_get_sar_ram_base();
213
214 for (i = 0; i < NR_REG_BANKS; i++) {
215 /* Save the CPUx interrupt mask for IRQ 0 to 127 */
216 val = wakeupgen_readl(i, 0);
217 sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
218 val = wakeupgen_readl(i, 1);
219 sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i);
220
221 /*
222 * Disable the secure interrupts for CPUx. The restore
223 * code blindly restores secure and non-secure interrupt
224 * masks from SAR RAM. Secure interrupts are not suppose
225 * to be enabled from HLOS. So overwrite the SAR location
226 * so that the secure interrupt remains disabled.
227 */
228 sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
229 sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
230 }
231
232 /* Save AuxBoot* registers */
233 val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
234 __raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
235 val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
236 __raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);
237
238 /* Save SyncReq generation logic */
239 val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
240 __raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
241 val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
242 __raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);
243
244 /* Save SyncReq generation logic */
245 val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK);
246 __raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET);
247 val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN);
248 __raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET);
249
250 /* Set the Backup Bit Mask status */
251 val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
252 val |= SAR_BACKUP_STATUS_WAKEUPGEN;
253 __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
254}
255
256/*
257 * Clear WakeupGen SAR backup status.
258 */
259void irq_sar_clear(void)
260{
261 u32 val;
262 val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
263 val &= ~SAR_BACKUP_STATUS_WAKEUPGEN;
264 __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
265}
266
267/*
268 * Save GIC and Wakeupgen interrupt context using secure API
269 * for HS/EMU devices.
270 */
271static void irq_save_secure_context(void)
272{
273 u32 ret;
274 ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,
275 FLAG_START_CRITICAL,
276 0, 0, 0, 0, 0);
277 if (ret != API_HAL_RET_VALUE_OK)
278 pr_err("GIC and Wakeupgen context save failed\n");
279}
280#endif
281
183#ifdef CONFIG_HOTPLUG_CPU 282#ifdef CONFIG_HOTPLUG_CPU
184static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self, 283static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
185 unsigned long action, void *hcpu) 284 unsigned long action, void *hcpu)
@@ -210,6 +309,37 @@ static void __init irq_hotplug_init(void)
210{} 309{}
211#endif 310#endif
212 311
312#ifdef CONFIG_CPU_PM
313static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v)
314{
315 switch (cmd) {
316 case CPU_CLUSTER_PM_ENTER:
317 if (omap_type() == OMAP2_DEVICE_TYPE_GP)
318 irq_save_context();
319 else
320 irq_save_secure_context();
321 break;
322 case CPU_CLUSTER_PM_EXIT:
323 if (omap_type() == OMAP2_DEVICE_TYPE_GP)
324 irq_sar_clear();
325 break;
326 }
327 return NOTIFY_OK;
328}
329
330static struct notifier_block irq_notifier_block = {
331 .notifier_call = irq_notifier,
332};
333
334static void __init irq_pm_init(void)
335{
336 cpu_pm_register_notifier(&irq_notifier_block);
337}
338#else
339static void __init irq_pm_init(void)
340{}
341#endif
342
213/* 343/*
214 * Initialise the wakeupgen module. 344 * Initialise the wakeupgen module.
215 */ 345 */
@@ -253,6 +383,7 @@ int __init omap_wakeupgen_init(void)
253 irq_target_cpu[i] = boot_cpu; 383 irq_target_cpu[i] = boot_cpu;
254 384
255 irq_hotplug_init(); 385 irq_hotplug_init();
386 irq_pm_init();
256 387
257 return 0; 388 return 0;
258} 389}
diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
index 970a2eef3ab9..aa14a8dd2505 100644
--- a/arch/arm/mach-omap2/omap4-sar-layout.h
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -28,4 +28,19 @@
28#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04 28#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
29#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08 29#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08
30 30
31#define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500)
32#define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504)
33#define SAR_SECRAM_SAVED_AT_OFFSET (SAR_BANK3_OFFSET + 0x508)
34
35/* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
36#define WAKEUPGENENB_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x684)
37#define WAKEUPGENENB_SECURE_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x694)
38#define WAKEUPGENENB_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6a4)
39#define WAKEUPGENENB_SECURE_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6b4)
40#define AUXCOREBOOT0_OFFSET (SAR_BANK3_OFFSET + 0x6c4)
41#define AUXCOREBOOT1_OFFSET (SAR_BANK3_OFFSET + 0x6c8)
42#define PTMSYNCREQ_MASK_OFFSET (SAR_BANK3_OFFSET + 0x6cc)
43#define PTMSYNCREQ_EN_OFFSET (SAR_BANK3_OFFSET + 0x6d0)
44#define SAR_BACKUP_STATUS_WAKEUPGEN 0x10
45
31#endif 46#endif