summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPrashant Gaikwad <pgaikwad@nvidia.com>2012-05-25 10:48:09 +0530
committerSimone Willett <swillett@nvidia.com>2012-05-25 14:54:35 -0700
commited1309fe218e55d7f32bee16a40816f74ccd4fe5 (patch)
treea376cb17ce6c89e0c06c6554eec5b99345cb0d58 /arch
parentd3869078b53e6e3499880d508607dc4a9883cbe0 (diff)
ARM: tegra: clock: Update secondary pll dividers resume
During resume from LP0 on Tegra2 always enable pll secondary dividers before clocks restoration (to make sure clock sources are enabled). Restore actual secondary dividers settings after clocks are restored. Bug 965928 Bug 953030 Change-Id: Id0cd99b601f90ad9fe8452817810969e41002199 Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com> Reviewed on http://git-master/r/#change,104661 (cherry picked from commit 6350d1fd475373779cf5110403717b2c84e723ba) Change-Id: Ic50477603b97a99d2ac2c926df1728faa107b108 Reviewed-on: http://git-master/r/104668 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com> Tested-by: Prashant Gaikwad <pgaikwad@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index af30cf2ea18c..135ae6ad9765 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -2771,7 +2771,7 @@ unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate)
#ifdef CONFIG_PM_SLEEP
static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
- PERIPH_CLK_SOURCE_NUM + 22];
+ PERIPH_CLK_SOURCE_NUM + 24];
static int tegra_clk_suspend(void)
{
@@ -2779,6 +2779,8 @@ static int tegra_clk_suspend(void)
u32 *ctx = clk_rst_suspend;
*ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+ *ctx++ = clk_readl(tegra_pll_p_out1.reg);
+ *ctx++ = clk_readl(tegra_pll_p_out3.reg);
*ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE);
*ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
*ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE);
@@ -2831,11 +2833,26 @@ static void tegra_clk_resume(void)
unsigned long off, i;
const u32 *ctx = clk_rst_suspend;
u32 val;
+ u32 pll_p_out12, pll_p_out34;
+ u32 pll_m_out1, pll_a_out0, pll_c_out1;
val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
val |= *ctx++;
clk_writel(val, OSC_CTRL);
+ /* Since we are going to reset devices and switch clock sources in this
+ * function, plls and secondary dividers is required to be enabled. The
+ * actual value will be restored back later. Note that boot plls: pllm,
+ * pllp, and pllu are already configured and enabled.
+ */
+
+ val = PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+ val |= val << 16;
+ pll_p_out12 = *ctx++;
+ clk_writel(pll_p_out12 | val, tegra_pll_p_out1.reg);
+ pll_p_out34 = *ctx++;
+ clk_writel(pll_p_out34 | val, tegra_pll_p_out3.reg);
+
clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE);
clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE);
@@ -2848,9 +2865,13 @@ static void tegra_clk_resume(void)
clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
udelay(1000);
- clk_writel(*ctx++, tegra_pll_m_out1.reg);
- clk_writel(*ctx++, tegra_pll_a_out0.reg);
- clk_writel(*ctx++, tegra_pll_c_out1.reg);
+ val = PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+ pll_m_out1 = *ctx++;
+ clk_writel(pll_m_out1 | val, tegra_pll_m_out1.reg);
+ pll_a_out0 = *ctx++;
+ clk_writel(pll_a_out0 | val, tegra_pll_a_out0.reg);
+ pll_c_out1 = *ctx++;
+ clk_writel(pll_c_out1 | val, tegra_pll_c_out1.reg);
clk_writel(*ctx++, tegra_clk_cclk.reg);
clk_writel(*ctx++, tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
@@ -2887,6 +2908,13 @@ static void tegra_clk_resume(void)
clk_writel(*ctx++, MISC_CLK_ENB);
clk_writel(*ctx++, CLK_MASK_ARM);
+
+ /* Restore back the actual pll and secondary divider values */
+ clk_writel(pll_p_out12, tegra_pll_p_out1.reg);
+ clk_writel(pll_p_out34, tegra_pll_p_out3.reg);
+ clk_writel(pll_m_out1, tegra_pll_m_out1.reg);
+ clk_writel(pll_a_out0, tegra_pll_a_out0.reg);
+ clk_writel(pll_c_out1, tegra_pll_c_out1.reg);
}
#else