ARM: tegra: Use WFE for power-gating on Tegra30
authorDmitry Osipenko <digetx@gmail.com>
Tue, 30 Jul 2019 17:23:40 +0000 (20:23 +0300)
committerThierry Reding <treding@nvidia.com>
Tue, 29 Oct 2019 13:32:01 +0000 (14:32 +0100)
Turned out that WFI doesn't work reliably on Tegra30 as a trigger for
the power-gating, it causes CPU hang under some circumstances like having
memory controller running of PLLP. The TRM doc states that WFI should be
used for the Big-Little "Cluster Switch", while WFE for the power-gating.
Hence let's use the WFE for CPU0 power-gating, like it is done for the
power-gating of a secondary cores. This fixes CPU hang after entering LP2
with memory running off PLLP.

Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Tested-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
arch/arm/mach-tegra/sleep-tegra30.S
drivers/soc/tegra/flowctrl.c

index b408fa5..3341a12 100644 (file)
@@ -682,10 +682,12 @@ tegra30_enter_sleep:
        dsb
        ldr     r0, [r6, r2] /* memory barrier */
 
+       cmp     r10, #TEGRA30
 halted:
        isb
        dsb
-       wfi     /* CPU should be power gated here */
+       wfine   /* CPU should be power gated here */
+       wfeeq
 
        /* !!!FIXME!!! Implement halt failure handler */
        b       halted
index b6bdeef..eb96a30 100644 (file)
@@ -91,8 +91,23 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid)
                reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
                /* clear wfi bitmap */
                reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
-               /* pwr gating on wfi */
-               reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;
+
+               if (tegra_get_chip_id() == TEGRA30) {
+                       /*
+                        * The wfi doesn't work well on Tegra30 because
+                        * CPU hangs under some odd circumstances after
+                        * power-gating (like memory running off PLLP),
+                        * hence use wfe that is working perfectly fine.
+                        * Note that Tegra30 TRM doc clearly stands that
+                        * wfi should be used for the "Cluster Switching",
+                        * while wfe for the power-gating, just like it
+                        * is done on Tegra20.
+                        */
+                       reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
+               } else {
+                       /* pwr gating on wfi */
+                       reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;
+               }
                break;
        }
        reg |= FLOW_CTRL_CSR_INTR_FLAG;                 /* clear intr flag */