ARM: tegra11: clock: Turn Off memory PLLs in resume
Alex Frid [Thu, 13 Jun 2013 04:10:13 +0000 (21:10 -0700)]
Turned Off memory PLLs (PLLM or PLLC) in clock resume if they are left
enabled by LP0 or LP1 exit code, but not used as EMC clock sources.

Change-Id: I017e79007873d8d4b918853e08e0cc27a424e310
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/238745
(cherry picked from commit ab02ca044fe93aceb6e32f7daa24ab5d9dcb2fd1)
Reviewed-on: http://git-master/r/258304
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

arch/arm/mach-tegra/tegra11_clocks.c

index 2af7f89..7b12b23 100644 (file)
@@ -7898,21 +7898,22 @@ static void tegra11_clk_resume(void)
        p = tegra_clk_emc.parent;
        tegra11_periph_clk_init(&tegra_clk_emc);
 
+       /* Turn Off pll_m if it was OFF before suspend, and emc was not switched
+          to pll_m across suspend; re-init pll_m to sync s/w and h/w states */
+       if ((tegra_pll_m.state == OFF) &&
+           (&tegra_pll_m != tegra_clk_emc.parent))
+               tegra11_pllm_clk_disable(&tegra_pll_m);
+       tegra11_pllm_clk_init(&tegra_pll_m);
+
        if (p != tegra_clk_emc.parent) {
-               /* FIXME: old parent is left enabled here even if EMC was its
-                  only child before suspend (may happen on Tegra11 !!) */
                pr_debug("EMC parent(refcount) across suspend: %s(%d) : %s(%d)",
                        p->name, p->refcnt, tegra_clk_emc.parent->name,
                        tegra_clk_emc.parent->refcnt);
 
-               BUG_ON(!p->refcnt);
-               p->refcnt--;
-
-               /* the new parent is enabled by low level code, but ref count
-                  need to be updated up to the root */
-               p = tegra_clk_emc.parent;
-               while (p && ((p->refcnt++) == 0))
-                       p = p->parent;
+               /* emc switched to the new parent by low level code, but ref
+                  count and s/w state need to be updated */
+               clk_disable(p);
+               clk_enable(tegra_clk_emc.parent);
        }
        tegra_emc_timing_invalidate();