ARM: tegra: power: add combined power req processing
Joshua Cha [Mon, 14 Nov 2011 01:37:31 +0000 (10:37 +0900)]
For platforms where the core & CPU power requests are combined
as a single request to the PMU, we need separate processing to
enable its suspend/resume operation.

Bug 862504

Change-Id: If66282a7b069d35568147e2d64f14371e1692bfd
Reviewed-on: http://git-master/r/64011
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Tested-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>

Rebase-Id: R21b966a438be03b11b80ce7deb70e3036b80dab2

arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/pm.h

index 9b4ee17..076181f 100644 (file)
@@ -535,7 +535,10 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
        /* Only the last cpu down does the final suspend steps */
        mode = readl(pmc + PMC_CTRL);
        mode |= TEGRA_POWER_CPU_PWRREQ_OE;
-       mode |= TEGRA_POWER_PWRREQ_OE;
+       if (pdata->combined_req)
+               mode &= ~TEGRA_POWER_PWRREQ_OE;
+       else
+               mode |= TEGRA_POWER_PWRREQ_OE;
        mode &= ~TEGRA_POWER_EFFECT_LP0;
        pmc_32kwritel(mode, PMC_CTRL);
        mode |= flags;
@@ -662,11 +665,19 @@ static void tegra_pm_set(enum tegra_suspend_mode mode)
 
        reg = readl(pmc + PMC_CTRL);
        reg |= TEGRA_POWER_CPU_PWRREQ_OE;
-       reg |= TEGRA_POWER_PWRREQ_OE;
+       if (pdata->combined_req)
+               reg &= ~TEGRA_POWER_PWRREQ_OE;
+       else
+               reg |= TEGRA_POWER_PWRREQ_OE;
        reg &= ~TEGRA_POWER_EFFECT_LP0;
 
        switch (mode) {
        case TEGRA_SUSPEND_LP0:
+               if (pdata->combined_req) {
+                       reg |= TEGRA_POWER_PWRREQ_OE;
+                       reg &= ~TEGRA_POWER_CPU_PWRREQ_OE;
+               }
+
                /*
                 * LP0 boots through the AVP, which then resumes the AVP to
                 * the address in scratch 39, and the cpu to the address in
@@ -812,6 +823,19 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags)
 
        restore_cpu_complex(flags);
 
+       /* for platforms where the core & CPU power requests are
+        * combined as a single request to the PMU, transition out
+        * of LP0 state by temporarily enabling both requests
+        */
+       if (mode == TEGRA_SUSPEND_LP0 && pdata->combined_req) {
+               u32 reg;
+               reg = readl(pmc + PMC_CTRL);
+               reg |= TEGRA_POWER_CPU_PWRREQ_OE;
+               pmc_32kwritel(reg, PMC_CTRL);
+               reg &= ~TEGRA_POWER_PWRREQ_OE;
+               pmc_32kwritel(reg, PMC_CTRL);
+       }
+
        cpu_cluster_pm_exit();
        cpu_pm_exit();
 
@@ -1051,7 +1075,8 @@ out:
 
        /* now enable requests */
        reg |= TEGRA_POWER_SYSCLK_OE;
-       reg |= TEGRA_POWER_PWRREQ_OE;
+       if (!pdata->combined_req)
+               reg |= TEGRA_POWER_PWRREQ_OE;
        pmc_32kwritel(reg, PMC_CTRL);
 
        if (pdata->suspend_mode == TEGRA_SUSPEND_LP0)
index 2ffbf24..ddf8571 100644 (file)
@@ -54,6 +54,7 @@ struct tegra_suspend_platform_data {
        unsigned long core_off_timer;   /* core power off time ticks, LP0 */
        bool corereq_high;         /* Core power request active-high */
        bool sysclkreq_high;       /* System clock request is active-high */
+       bool combined_req;         /* if core & CPU power requests are combined */
        enum tegra_suspend_mode suspend_mode;
        unsigned long cpu_lp2_min_residency; /* Min LP2 state residency in us */
        void (*board_suspend)(int lp_state, enum suspend_stage stg);