diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-12-22 19:23:39 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-12-25 17:39:27 -0500 |
| commit | 767c0f3aed74be56f268709f5347e6c86d52b408 (patch) | |
| tree | 95064f1a46ddf9497178db52c7e2292a7d52a3df | |
| parent | 0f966d74cf77a9140a025464a287e1d2fee8a1fc (diff) | |
PM / shmobile: Remove the stay_on flag from SH7372's PM domains
SH7372 uses two independent mechanisms for ensuring that power
domains will never be turned off: the stay_on flag and the "always
on" domain governor. Moreover, the "always on" governor is only taken
into accout by runtime PM code paths, while the stay_on flag affects
all attempts to turn the given domain off. Thus setting the stay_on
flag causes the "always on" governor to be unnecessary, which is
quite confusing.
However, the stay_on flag is currently only set for two domains: A3SP
and A4S. Moreover, it only is set for the A3SP domain if
console_suspend_enabled is set, so stay_on won't be necessary for
that domain any more if console_suspend_enabled is checked directly
in its .suspend() routine. [This requires domain .suspend() to
return a result, but that is a minor modification.] Analogously,
stay_on won't be necessary for the A4S domain if it's .suspend()
routine always returns an error code.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Magnus Damm <damm@opensource.se>
| -rw-r--r-- | arch/arm/mach-shmobile/include/mach/sh7372.h | 3 | ||||
| -rw-r--r-- | arch/arm/mach-shmobile/pm-sh7372.c | 49 |
2 files changed, 29 insertions, 23 deletions
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index d0731d973f1f..8254ab86f6cd 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h | |||
| @@ -480,11 +480,10 @@ struct platform_device; | |||
| 480 | struct sh7372_pm_domain { | 480 | struct sh7372_pm_domain { |
| 481 | struct generic_pm_domain genpd; | 481 | struct generic_pm_domain genpd; |
| 482 | struct dev_power_governor *gov; | 482 | struct dev_power_governor *gov; |
| 483 | void (*suspend)(void); | 483 | int (*suspend)(void); |
| 484 | void (*resume)(void); | 484 | void (*resume)(void); |
| 485 | unsigned int bit_shift; | 485 | unsigned int bit_shift; |
| 486 | bool no_debug; | 486 | bool no_debug; |
| 487 | bool stay_on; | ||
| 488 | }; | 487 | }; |
| 489 | 488 | ||
| 490 | static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) | 489 | static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) |
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 1e659d7360d1..7fda2301c9b2 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c | |||
| @@ -82,11 +82,12 @@ static int pd_power_down(struct generic_pm_domain *genpd) | |||
| 82 | struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); | 82 | struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); |
| 83 | unsigned int mask = 1 << sh7372_pd->bit_shift; | 83 | unsigned int mask = 1 << sh7372_pd->bit_shift; |
| 84 | 84 | ||
| 85 | if (sh7372_pd->suspend) | 85 | if (sh7372_pd->suspend) { |
| 86 | sh7372_pd->suspend(); | 86 | int ret = sh7372_pd->suspend(); |
| 87 | 87 | ||
| 88 | if (sh7372_pd->stay_on) | 88 | if (ret) |
| 89 | return 0; | 89 | return ret; |
| 90 | } | ||
| 90 | 91 | ||
| 91 | if (__raw_readl(PSTR) & mask) { | 92 | if (__raw_readl(PSTR) & mask) { |
| 92 | unsigned int retry_count; | 93 | unsigned int retry_count; |
| @@ -113,9 +114,6 @@ static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume) | |||
| 113 | unsigned int retry_count; | 114 | unsigned int retry_count; |
| 114 | int ret = 0; | 115 | int ret = 0; |
| 115 | 116 | ||
| 116 | if (sh7372_pd->stay_on) | ||
| 117 | goto out; | ||
| 118 | |||
| 119 | if (__raw_readl(PSTR) & mask) | 117 | if (__raw_readl(PSTR) & mask) |
| 120 | goto out; | 118 | goto out; |
| 121 | 119 | ||
| @@ -148,10 +146,11 @@ static int pd_power_up(struct generic_pm_domain *genpd) | |||
| 148 | return __pd_power_up(to_sh7372_pd(genpd), true); | 146 | return __pd_power_up(to_sh7372_pd(genpd), true); |
| 149 | } | 147 | } |
| 150 | 148 | ||
| 151 | static void sh7372_a4r_suspend(void) | 149 | static int sh7372_a4r_suspend(void) |
| 152 | { | 150 | { |
| 153 | sh7372_intcs_suspend(); | 151 | sh7372_intcs_suspend(); |
| 154 | __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ | 152 | __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ |
| 153 | return 0; | ||
| 155 | } | 154 | } |
| 156 | 155 | ||
| 157 | static bool pd_active_wakeup(struct device *dev) | 156 | static bool pd_active_wakeup(struct device *dev) |
| @@ -243,7 +242,6 @@ struct sh7372_pm_domain sh7372_a4r = { | |||
| 243 | .gov = &pm_domain_always_on_gov, | 242 | .gov = &pm_domain_always_on_gov, |
| 244 | .suspend = sh7372_a4r_suspend, | 243 | .suspend = sh7372_a4r_suspend, |
| 245 | .resume = sh7372_intcs_resume, | 244 | .resume = sh7372_intcs_resume, |
| 246 | .stay_on = true, | ||
| 247 | }; | 245 | }; |
| 248 | 246 | ||
| 249 | struct sh7372_pm_domain sh7372_a3rv = { | 247 | struct sh7372_pm_domain sh7372_a3rv = { |
| @@ -256,29 +254,40 @@ struct sh7372_pm_domain sh7372_a3ri = { | |||
| 256 | .bit_shift = 8, | 254 | .bit_shift = 8, |
| 257 | }; | 255 | }; |
| 258 | 256 | ||
| 257 | static int sh7372_a4s_suspend(void) | ||
| 258 | { | ||
| 259 | /* | ||
| 260 | * The A4S domain contains the CPU core and therefore it should | ||
| 261 | * only be turned off if the CPU is in use. | ||
| 262 | */ | ||
| 263 | return -EBUSY; | ||
| 264 | } | ||
| 265 | |||
| 259 | struct sh7372_pm_domain sh7372_a4s = { | 266 | struct sh7372_pm_domain sh7372_a4s = { |
| 260 | .genpd.name = "A4S", | 267 | .genpd.name = "A4S", |
| 261 | .bit_shift = 10, | 268 | .bit_shift = 10, |
| 262 | .gov = &pm_domain_always_on_gov, | 269 | .gov = &pm_domain_always_on_gov, |
| 263 | .no_debug = true, | 270 | .no_debug = true, |
| 264 | .stay_on = true, | 271 | .suspend = sh7372_a4s_suspend, |
| 265 | }; | 272 | }; |
| 266 | 273 | ||
| 274 | static int sh7372_a3sp_suspend(void) | ||
| 275 | { | ||
| 276 | /* | ||
| 277 | * Serial consoles make use of SCIF hardware located in A3SP, | ||
| 278 | * keep such power domain on if "no_console_suspend" is set. | ||
| 279 | */ | ||
| 280 | return console_suspend_enabled ? -EBUSY : 0; | ||
| 281 | } | ||
| 282 | |||
| 267 | struct sh7372_pm_domain sh7372_a3sp = { | 283 | struct sh7372_pm_domain sh7372_a3sp = { |
| 268 | .genpd.name = "A3SP", | 284 | .genpd.name = "A3SP", |
| 269 | .bit_shift = 11, | 285 | .bit_shift = 11, |
| 270 | .gov = &pm_domain_always_on_gov, | 286 | .gov = &pm_domain_always_on_gov, |
| 271 | .no_debug = true, | 287 | .no_debug = true, |
| 288 | .suspend = sh7372_a3sp_suspend, | ||
| 272 | }; | 289 | }; |
| 273 | 290 | ||
| 274 | static void sh7372_a3sp_init(void) | ||
| 275 | { | ||
| 276 | /* serial consoles make use of SCIF hardware located in A3SP, | ||
| 277 | * keep such power domain on if "no_console_suspend" is set. | ||
| 278 | */ | ||
| 279 | sh7372_a3sp.stay_on = !console_suspend_enabled; | ||
| 280 | } | ||
| 281 | |||
| 282 | struct sh7372_pm_domain sh7372_a3sg = { | 291 | struct sh7372_pm_domain sh7372_a3sg = { |
| 283 | .genpd.name = "A3SG", | 292 | .genpd.name = "A3SG", |
| 284 | .bit_shift = 13, | 293 | .bit_shift = 13, |
| @@ -508,7 +517,7 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state) | |||
| 508 | /* convert INTC mask and sense to SYSC mask and sense */ | 517 | /* convert INTC mask and sense to SYSC mask and sense */ |
| 509 | sh7372_setup_sysc(msk, msk2); | 518 | sh7372_setup_sysc(msk, msk2); |
| 510 | 519 | ||
| 511 | if (!sh7372_a3sp.stay_on && | 520 | if (!console_suspend_enabled && |
| 512 | sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) { | 521 | sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) { |
| 513 | /* enter A4S sleep with PLLC0 off */ | 522 | /* enter A4S sleep with PLLC0 off */ |
| 514 | pr_debug("entering A4S\n"); | 523 | pr_debug("entering A4S\n"); |
| @@ -544,8 +553,6 @@ void __init sh7372_pm_init(void) | |||
| 544 | /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ | 553 | /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ |
| 545 | __raw_writel(0, PDNSEL); | 554 | __raw_writel(0, PDNSEL); |
| 546 | 555 | ||
| 547 | sh7372_a3sp_init(); | ||
| 548 | |||
| 549 | sh7372_suspend_init(); | 556 | sh7372_suspend_init(); |
| 550 | sh7372_cpuidle_init(); | 557 | sh7372_cpuidle_init(); |
| 551 | } | 558 | } |
