|
@@ -334,3 +334,81 @@ static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2)
|
|
|
}
|
|
|
|
|
|
static void sh7372_enter_a3sm_common(int pllc0_on)
|
|
|
+{
|
|
|
+ /* use INTCA together with SYSC for wakeup */
|
|
|
+ sh7372_setup_sysc(1 << 0, 0);
|
|
|
+ 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();
|
|
|
+ sh7372_set_reset_vector(SMFRAM);
|
|
|
+ sh7372_enter_sysc(pllc0_on, 1 << 10);
|
|
|
+ sh7372_intca_resume();
|
|
|
+}
|
|
|
+
|
|
|
+static void sh7372_pm_setup_smfram(void)
|
|
|
+{
|
|
|
+ memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline void sh7372_pm_setup_smfram(void) {}
|
|
|
+#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */
|
|
|
+
|
|
|
+#ifdef CONFIG_CPU_IDLE
|
|
|
+static int sh7372_do_idle_core_standby(unsigned long unused)
|
|
|
+{
|
|
|
+ cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int sh7372_enter_core_standby(struct cpuidle_device *dev,
|
|
|
+ struct cpuidle_driver *drv, int index)
|
|
|
+{
|
|
|
+ sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
|
|
|
+
|
|
|
+ /* enter sleep mode with SYSTBCR to 0x10 */
|
|
|
+ __raw_writel(0x10, SYSTBCR);
|
|
|
+ cpu_suspend(0, sh7372_do_idle_core_standby);
|
|
|
+ __raw_writel(0, SYSTBCR);
|
|
|
+
|
|
|
+ /* disable reset vector translation */
|
|
|
+ __raw_writel(0, SBAR);
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static int sh7372_enter_a3sm_pll_on(struct cpuidle_device *dev,
|
|
|
+ struct cpuidle_driver *drv, int index)
|
|
|
+{
|
|
|
+ sh7372_enter_a3sm_common(1);
|
|
|
+ return 2;
|
|
|
+}
|
|
|
+
|
|
|
+static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev,
|
|
|
+ struct cpuidle_driver *drv, int index)
|
|
|
+{
|
|
|
+ sh7372_enter_a3sm_common(0);
|
|
|
+ return 3;
|
|
|
+}
|
|
|
+
|
|
|
+static int sh7372_enter_a4s(struct cpuidle_device *dev,
|
|
|
+ struct cpuidle_driver *drv, int index)
|
|
|
+{
|
|
|
+ unsigned long msk, msk2;
|
|
|
+
|
|
|
+ if (!sh7372_sysc_valid(&msk, &msk2))
|
|
|
+ return sh7372_enter_a3sm_pll_off(dev, drv, index);
|
|
|
+
|
|
|
+ sh7372_setup_sysc(msk, msk2);
|
|
|
+ sh7372_enter_a4s_common(0);
|
|
|
+ return 4;
|
|
|
+}
|
|
|
+
|
|
|
+static struct cpuidle_driver sh7372_cpuidle_driver = {
|
|
|
+ .name = "sh7372_cpuidle",
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ .en_core_tk_irqen = 1,
|
|
|
+ .state_count = 5,
|