aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-08-22 06:27:24 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-03 19:46:17 -0400
commitcaaca999d335872a53b3fff8fa5af2de794d16a1 (patch)
tree74fef4014f2740631333c8dc971f29ff585229d9 /arch
parent6bf9af464c4894e613567c0fb6559be67f31c88a (diff)
ARM: shmobile: Add A4S cpuidle state on sh7372
Add a "C5" cpuidle state to the SH7372 SoC connected to the A4S power domain in such a way that A4S may be turned off by cpuidle if all I/O devices in that domain have been suspended (or do not have attached drivers). This requires some reorganization of the initialization of SH7372 power management which affects the the boards based on it, Mackerel and AP4EVB. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Magnus Damm <damm@opensource.se>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c2
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c2
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h2
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c56
4 files changed, 50 insertions, 12 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 5168a0338cf4..264340a60f65 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1486,6 +1486,6 @@ MACHINE_START(AP4EVB, "ap4evb")
1486 .init_irq = sh7372_init_irq, 1486 .init_irq = sh7372_init_irq,
1487 .handle_irq = shmobile_handle_irq_intc, 1487 .handle_irq = shmobile_handle_irq_intc,
1488 .init_machine = ap4evb_init, 1488 .init_machine = ap4evb_init,
1489 .init_late = shmobile_init_late, 1489 .init_late = sh7372_pm_init_late,
1490 .timer = &shmobile_timer, 1490 .timer = &shmobile_timer,
1491MACHINE_END 1491MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index d1e8fe83588c..f96e41557d65 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1654,6 +1654,6 @@ MACHINE_START(MACKEREL, "mackerel")
1654 .init_irq = sh7372_init_irq, 1654 .init_irq = sh7372_init_irq,
1655 .handle_irq = shmobile_handle_irq_intc, 1655 .handle_irq = shmobile_handle_irq_intc,
1656 .init_machine = mackerel_init, 1656 .init_machine = mackerel_init,
1657 .init_late = shmobile_init_late, 1657 .init_late = sh7372_pm_init_late,
1658 .timer = &shmobile_timer, 1658 .timer = &shmobile_timer,
1659MACHINE_END 1659MACHINE_END
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index 40beb796d020..eb98b45c5089 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -489,4 +489,6 @@ extern void __init sh7372_init_pm_domains(void);
489static inline void sh7372_init_pm_domains(void) {} 489static inline void sh7372_init_pm_domains(void) {}
490#endif 490#endif
491 491
492extern void __init sh7372_pm_init_late(void);
493
492#endif /* __ASM_SH7372_H__ */ 494#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 5cafd35cc411..a7a5e20ae9a0 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -339,6 +339,21 @@ static void sh7372_enter_a3sm_common(int pllc0_on)
339 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); 339 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
340 sh7372_enter_sysc(pllc0_on, 1 << 12); 340 sh7372_enter_sysc(pllc0_on, 1 << 12);
341} 341}
342
343static void sh7372_enter_a4s_common(int pllc0_on)
344{
345 sh7372_intca_suspend();
346 sh7372_set_reset_vector(SMFRAM);
347 sh7372_enter_sysc(pllc0_on, 1 << 10);
348 sh7372_intca_resume();
349}
350
351static void sh7372_pm_setup_smfram(void)
352{
353 memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
354}
355#else
356static inline void sh7372_pm_setup_smfram(void) {}
342#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ 357#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */
343 358
344#ifdef CONFIG_CPU_IDLE 359#ifdef CONFIG_CPU_IDLE
@@ -378,11 +393,24 @@ static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev,
378 return 3; 393 return 3;
379} 394}
380 395
396static int sh7372_enter_a4s(struct cpuidle_device *dev,
397 struct cpuidle_driver *drv, int index)
398{
399 unsigned long msk, msk2;
400
401 if (!sh7372_sysc_valid(&msk, &msk2))
402 return sh7372_enter_a3sm_pll_off(dev, drv, index);
403
404 sh7372_setup_sysc(msk, msk2);
405 sh7372_enter_a4s_common(0);
406 return 4;
407}
408
381static struct cpuidle_driver sh7372_cpuidle_driver = { 409static struct cpuidle_driver sh7372_cpuidle_driver = {
382 .name = "sh7372_cpuidle", 410 .name = "sh7372_cpuidle",
383 .owner = THIS_MODULE, 411 .owner = THIS_MODULE,
384 .en_core_tk_irqen = 1, 412 .en_core_tk_irqen = 1,
385 .state_count = 4, 413 .state_count = 5,
386 .safe_state_index = 0, /* C1 */ 414 .safe_state_index = 0, /* C1 */
387 .states[0] = ARM_CPUIDLE_WFI_STATE, 415 .states[0] = ARM_CPUIDLE_WFI_STATE,
388 .states[0].enter = shmobile_enter_wfi, 416 .states[0].enter = shmobile_enter_wfi,
@@ -410,6 +438,15 @@ static struct cpuidle_driver sh7372_cpuidle_driver = {
410 .flags = CPUIDLE_FLAG_TIME_VALID, 438 .flags = CPUIDLE_FLAG_TIME_VALID,
411 .enter = sh7372_enter_a3sm_pll_off, 439 .enter = sh7372_enter_a3sm_pll_off,
412 }, 440 },
441 .states[4] = {
442 .name = "C5",
443 .desc = "A4S PLL OFF",
444 .exit_latency = 240,
445 .target_residency = 30 + 240,
446 .flags = CPUIDLE_FLAG_TIME_VALID,
447 .enter = sh7372_enter_a4s,
448 .disabled = true,
449 },
413}; 450};
414 451
415static void sh7372_cpuidle_init(void) 452static void sh7372_cpuidle_init(void)
@@ -421,15 +458,6 @@ static void sh7372_cpuidle_init(void) {}
421#endif 458#endif
422 459
423#ifdef CONFIG_SUSPEND 460#ifdef CONFIG_SUSPEND
424static void sh7372_enter_a4s_common(int pllc0_on)
425{
426 sh7372_intca_suspend();
427 memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
428 sh7372_set_reset_vector(SMFRAM);
429 sh7372_enter_sysc(pllc0_on, 1 << 10);
430 sh7372_intca_resume();
431}
432
433static int sh7372_enter_suspend(suspend_state_t suspend_state) 461static int sh7372_enter_suspend(suspend_state_t suspend_state)
434{ 462{
435 unsigned long msk, msk2; 463 unsigned long msk, msk2;
@@ -497,6 +525,14 @@ void __init sh7372_pm_init(void)
497 /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ 525 /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
498 __raw_writel(0, PDNSEL); 526 __raw_writel(0, PDNSEL);
499 527
528 sh7372_pm_setup_smfram();
529
500 sh7372_suspend_init(); 530 sh7372_suspend_init();
501 sh7372_cpuidle_init(); 531 sh7372_cpuidle_init();
502} 532}
533
534void __init sh7372_pm_init_late(void)
535{
536 shmobile_init_late();
537 pm_genpd_name_attach_cpuidle("A4S", 4);
538}