aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Gerlach <d-gerlach@ti.com>2017-03-28 21:57:54 -0400
committerTony Lindgren <tony@atomide.com>2017-05-16 11:44:31 -0400
commite1a9e61e141d2b61780602b0af2befd7133c0bae (patch)
treecad262f71e45a473de803c2a44c79188cb479d76
parent2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff)
ARM: OMAP: Wakeupgen: Add context save/restore for AM43XX
AM43XX has the same wakeupgen IP as OMAP4/5. The only notable difference is the presence of 7 register banks and lack of SAR area which has been used in OMAP4/5 for saving and restoring the context around low power states. In case of AM43XX the context is saved and restored by the kernel. Introduce wakeupgen_ops so that context save and restore can be set on a per-SoC basis during init. Signed-off-by: Dave Gerlach <d-gerlach@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r--arch/arm/mach-omap2/omap-wakeupgen.c68
1 files changed, 62 insertions, 6 deletions
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 369f95a703ac..33ed5d53fa45 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -58,6 +58,17 @@ static unsigned int irq_banks = DEFAULT_NR_REG_BANKS;
58static unsigned int max_irqs = DEFAULT_IRQS; 58static unsigned int max_irqs = DEFAULT_IRQS;
59static unsigned int omap_secure_apis; 59static unsigned int omap_secure_apis;
60 60
61#ifdef CONFIG_CPU_PM
62static unsigned int wakeupgen_context[MAX_NR_REG_BANKS];
63#endif
64
65struct omap_wakeupgen_ops {
66 void (*save_context)(void);
67 void (*restore_context)(void);
68};
69
70static struct omap_wakeupgen_ops *wakeupgen_ops;
71
61/* 72/*
62 * Static helper functions. 73 * Static helper functions.
63 */ 74 */
@@ -264,6 +275,16 @@ static inline void omap5_irq_save_context(void)
264 275
265} 276}
266 277
278static inline void am43xx_irq_save_context(void)
279{
280 u32 i;
281
282 for (i = 0; i < irq_banks; i++) {
283 wakeupgen_context[i] = wakeupgen_readl(i, 0);
284 wakeupgen_writel(0, i, CPU0_ID);
285 }
286}
287
267/* 288/*
268 * Save WakeupGen interrupt context in SAR BANK3. Restore is done by 289 * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
269 * ROM code. WakeupGen IP is integrated along with GIC to manage the 290 * ROM code. WakeupGen IP is integrated along with GIC to manage the
@@ -280,11 +301,8 @@ static void irq_save_context(void)
280 301
281 if (!sar_base) 302 if (!sar_base)
282 sar_base = omap4_get_sar_ram_base(); 303 sar_base = omap4_get_sar_ram_base();
283 304 if (wakeupgen_ops && wakeupgen_ops->save_context)
284 if (soc_is_omap54xx()) 305 wakeupgen_ops->save_context();
285 omap5_irq_save_context();
286 else
287 omap4_irq_save_context();
288} 306}
289 307
290/* 308/*
@@ -306,6 +324,20 @@ static void irq_sar_clear(void)
306 writel_relaxed(val, sar_base + offset); 324 writel_relaxed(val, sar_base + offset);
307} 325}
308 326
327static void am43xx_irq_restore_context(void)
328{
329 u32 i;
330
331 for (i = 0; i < irq_banks; i++)
332 wakeupgen_writel(wakeupgen_context[i], i, CPU0_ID);
333}
334
335static void irq_restore_context(void)
336{
337 if (wakeupgen_ops && wakeupgen_ops->restore_context)
338 wakeupgen_ops->restore_context();
339}
340
309/* 341/*
310 * Save GIC and Wakeupgen interrupt context using secure API 342 * Save GIC and Wakeupgen interrupt context using secure API
311 * for HS/EMU devices. 343 * for HS/EMU devices.
@@ -319,6 +351,26 @@ static void irq_save_secure_context(void)
319 if (ret != API_HAL_RET_VALUE_OK) 351 if (ret != API_HAL_RET_VALUE_OK)
320 pr_err("GIC and Wakeupgen context save failed\n"); 352 pr_err("GIC and Wakeupgen context save failed\n");
321} 353}
354
355/* Define ops for context save and restore for each SoC */
356static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {
357 .save_context = omap4_irq_save_context,
358 .restore_context = irq_sar_clear,
359};
360
361static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {
362 .save_context = omap5_irq_save_context,
363 .restore_context = irq_sar_clear,
364};
365
366static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {
367 .save_context = am43xx_irq_save_context,
368 .restore_context = am43xx_irq_restore_context,
369};
370#else
371static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {};
372static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {};
373static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {};
322#endif 374#endif
323 375
324#ifdef CONFIG_HOTPLUG_CPU 376#ifdef CONFIG_HOTPLUG_CPU
@@ -359,7 +411,7 @@ static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v)
359 break; 411 break;
360 case CPU_CLUSTER_PM_EXIT: 412 case CPU_CLUSTER_PM_EXIT:
361 if (omap_type() == OMAP2_DEVICE_TYPE_GP) 413 if (omap_type() == OMAP2_DEVICE_TYPE_GP)
362 irq_sar_clear(); 414 irq_restore_context();
363 break; 415 break;
364 } 416 }
365 return NOTIFY_OK; 417 return NOTIFY_OK;
@@ -494,9 +546,13 @@ static int __init wakeupgen_init(struct device_node *node,
494 irq_banks = OMAP4_NR_BANKS; 546 irq_banks = OMAP4_NR_BANKS;
495 max_irqs = OMAP4_NR_IRQS; 547 max_irqs = OMAP4_NR_IRQS;
496 omap_secure_apis = 1; 548 omap_secure_apis = 1;
549 wakeupgen_ops = &omap4_wakeupgen_ops;
550 } else if (soc_is_omap54xx()) {
551 wakeupgen_ops = &omap5_wakeupgen_ops;
497 } else if (soc_is_am43xx()) { 552 } else if (soc_is_am43xx()) {
498 irq_banks = AM43XX_NR_REG_BANKS; 553 irq_banks = AM43XX_NR_REG_BANKS;
499 max_irqs = AM43XX_IRQS; 554 max_irqs = AM43XX_IRQS;
555 wakeupgen_ops = &am43xx_wakeupgen_ops;
500 } 556 }
501 557
502 domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs, 558 domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,