diff options
author | Dave Gerlach <d-gerlach@ti.com> | 2017-03-28 21:57:54 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2017-05-16 11:44:31 -0400 |
commit | e1a9e61e141d2b61780602b0af2befd7133c0bae (patch) | |
tree | cad262f71e45a473de803c2a44c79188cb479d76 | |
parent | 2ea659a9ef488125eb46da6eb571de5eae5c43f6 (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.c | 68 |
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; | |||
58 | static unsigned int max_irqs = DEFAULT_IRQS; | 58 | static unsigned int max_irqs = DEFAULT_IRQS; |
59 | static unsigned int omap_secure_apis; | 59 | static unsigned int omap_secure_apis; |
60 | 60 | ||
61 | #ifdef CONFIG_CPU_PM | ||
62 | static unsigned int wakeupgen_context[MAX_NR_REG_BANKS]; | ||
63 | #endif | ||
64 | |||
65 | struct omap_wakeupgen_ops { | ||
66 | void (*save_context)(void); | ||
67 | void (*restore_context)(void); | ||
68 | }; | ||
69 | |||
70 | static 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 | ||
278 | static 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 | ||
327 | static 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 | |||
335 | static 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 */ | ||
356 | static struct omap_wakeupgen_ops omap4_wakeupgen_ops = { | ||
357 | .save_context = omap4_irq_save_context, | ||
358 | .restore_context = irq_sar_clear, | ||
359 | }; | ||
360 | |||
361 | static struct omap_wakeupgen_ops omap5_wakeupgen_ops = { | ||
362 | .save_context = omap5_irq_save_context, | ||
363 | .restore_context = irq_sar_clear, | ||
364 | }; | ||
365 | |||
366 | static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = { | ||
367 | .save_context = am43xx_irq_save_context, | ||
368 | .restore_context = am43xx_irq_restore_context, | ||
369 | }; | ||
370 | #else | ||
371 | static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {}; | ||
372 | static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {}; | ||
373 | static 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, |