MLK-12088 ARM: imx: low power idle support for imx7d single core
authorAnson Huang <Anson.Huang@nxp.com>
Mon, 28 Dec 2015 14:38:26 +0000 (22:38 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:49:37 +0000 (14:49 -0500)
When only single core online for i.MX7D, the secondary core wfi
flag should be set to make sure low power idle can be entered when
last core enters wfi. Otherwise, DDR/CCM/ANATOP will NOT enter
low power mode as the secondary core wfi flag is always clear;

Make sure the last power up slot do the ack for single core case.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
arch/arm/mach-imx/cpuidle-imx7d.c
arch/arm/mach-imx/gpcv2.c

index 4ba99d8..6743884 100644 (file)
@@ -158,6 +158,26 @@ static struct cpuidle_driver imx7d_cpuidle_driver = {
        .safe_state_index = 0,
 };
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int cpu_hotplug_notify(struct notifier_block *self,
+                                 unsigned long action, void *hcpu)
+{
+       switch (action) {
+       case CPU_UP_PREPARE:
+               cpuidle_pm_info->cpu1_wfi = 0;
+               break;
+       case CPU_DEAD:
+               cpuidle_pm_info->cpu1_wfi = 1;
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata cpu_hotplug_notifier = {
+       .notifier_call = cpu_hotplug_notify,
+};
+#endif
+
 int imx7d_enable_rcosc(void)
 {
        void __iomem *anatop_base =
@@ -232,7 +252,10 @@ int __init imx7d_cpuidle_init(void)
        cpuidle_pm_info->pbase = (phys_addr_t) wfi_iram_base_phys;
        cpuidle_pm_info->pm_info_size = sizeof(*cpuidle_pm_info);
        cpuidle_pm_info->resume_addr = virt_to_phys(ca7_cpu_resume);
-       cpuidle_pm_info->cpu1_wfi = 0;
+       if (num_online_cpus() == 1)
+               cpuidle_pm_info->cpu1_wfi = 1;
+       else
+               cpuidle_pm_info->cpu1_wfi = 0;
        cpuidle_pm_info->lpi_enter = 0;
        /* initialize the last cpu id to invalid here */
        cpuidle_pm_info->last_cpu = -1;
@@ -259,6 +282,9 @@ int __init imx7d_cpuidle_init(void)
 
        imx7d_enable_rcosc();
 
+#ifdef CONFIG_HOTPLUG_CPU
+       register_hotcpu_notifier(&cpu_hotplug_notifier);
+#endif
        /* code size should include cpuidle_pm_info size */
        imx7d_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base +
                sizeof(*cpuidle_pm_info),
index af1a57a..8fdb5ce 100644 (file)
@@ -385,9 +385,9 @@ void imx_gpcv2_set_cpu_power_gate_in_idle(bool pdn)
                        imx_gpcv2_set_slot_ack(1, CORE1_A7, false, false);
                imx_gpcv2_set_slot_ack(2, SCU_A7, false, true);
                imx_gpcv2_set_slot_ack(6, SCU_A7, true, false);
-               imx_gpcv2_set_slot_ack(7, CORE0_A7, true, false);
                if (num_online_cpus() > 1)
-                       imx_gpcv2_set_slot_ack(8, CORE1_A7, true, true);
+                       imx_gpcv2_set_slot_ack(7, CORE1_A7, true, false);
+               imx_gpcv2_set_slot_ack(8, CORE0_A7, true, true);
        } else {
                writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 0 * 0x4);
                writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 1 * 0x4);