diff options
Diffstat (limited to 'arch/arm/mach-shmobile/pm-sh7372.c')
-rw-r--r-- | arch/arm/mach-shmobile/pm-sh7372.c | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index f742c61c8902..1e659d7360d1 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -256,6 +256,14 @@ struct sh7372_pm_domain sh7372_a3ri = { .bit_shift = 8, }; +struct sh7372_pm_domain sh7372_a4s = { + .genpd.name = "A4S", + .bit_shift = 10, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .stay_on = true, +}; + struct sh7372_pm_domain sh7372_a3sp = { .genpd.name = "A3SP", .bit_shift = 11, @@ -289,11 +297,16 @@ static int sh7372_do_idle_core_standby(unsigned long unused) return 0; } -static void sh7372_enter_core_standby(void) +static void sh7372_set_reset_vector(unsigned long address) { /* set reset vector, translate 4k */ - __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); + __raw_writel(address, SBAR); __raw_writel(0, APARMBAREA); +} + +static void sh7372_enter_core_standby(void) +{ + sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); /* enter sleep mode with SYSTBCR to 0x10 */ __raw_writel(0x10, SYSTBCR); @@ -306,27 +319,22 @@ static void sh7372_enter_core_standby(void) #endif #ifdef CONFIG_SUSPEND -static void sh7372_enter_a3sm_common(int pllc0_on) +static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode) { - /* set reset vector, translate 4k */ - __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); - __raw_writel(0, APARMBAREA); - if (pllc0_on) __raw_writel(0, PLLC01STPCR); else __raw_writel(1 << 28, PLLC01STPCR); - __raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */ __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */ - cpu_suspend(0, sh7372_do_idle_a3sm); + cpu_suspend(sleep_mode, sh7372_do_idle_sysc); __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */ /* disable reset vector translation */ __raw_writel(0, SBAR); } -static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p) +static int sh7372_sysc_valid(unsigned long *mskp, unsigned long *msk2p) { unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4; unsigned long msk, msk2; @@ -414,7 +422,7 @@ static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p) *irqcr2p = irqcr2; } -static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) +static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2) { u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high; unsigned long tmp; @@ -447,6 +455,22 @@ static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3); __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4); } + +static void sh7372_enter_a3sm_common(int pllc0_on) +{ + sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); + sh7372_enter_sysc(pllc0_on, 1 << 12); +} + +static void sh7372_enter_a4s_common(int pllc0_on) +{ + sh7372_intca_suspend(); + memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); + sh7372_set_reset_vector(SMFRAM); + sh7372_enter_sysc(pllc0_on, 1 << 10); + sh7372_intca_resume(); +} + #endif #ifdef CONFIG_CPU_IDLE @@ -480,14 +504,20 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state) unsigned long msk, msk2; /* check active clocks to determine potential wakeup sources */ - if (sh7372_a3sm_valid(&msk, &msk2)) { - + if (sh7372_sysc_valid(&msk, &msk2)) { /* convert INTC mask and sense to SYSC mask and sense */ - sh7372_setup_a3sm(msk, msk2); - - /* enter A3SM sleep with PLLC0 off */ - pr_debug("entering A3SM\n"); - sh7372_enter_a3sm_common(0); + sh7372_setup_sysc(msk, msk2); + + if (!sh7372_a3sp.stay_on && + sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) { + /* enter A4S sleep with PLLC0 off */ + pr_debug("entering A4S\n"); + sh7372_enter_a4s_common(0); + } else { + /* enter A3SM sleep with PLLC0 off */ + pr_debug("entering A3SM\n"); + sh7372_enter_a3sm_common(0); + } } else { /* default to Core Standby that supports all wakeup sources */ pr_debug("entering Core Standby\n"); |