summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrashant Gaikwad <pgaikwad@nvidia.com>2012-05-25 10:48:09 +0530
committerManish Tuteja <mtuteja@nvidia.com>2012-05-25 01:10:56 -0700
commit9cfc0bba2e56ef61ee8211994849aadc05669898 (patch)
treea580987ec20ea578b8c95ed2163969fd1a0194f6
parent37c6b17cce927f36ee18b06d97b881865eb7ae26 (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 Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com> Reviewed on http://git-master/r/#change,104661 (cherry picked from commit 6350d1fd475373779cf5110403717b2c84e723ba) Change-Id: I048e3f925daf02074312472afa667609a8338c15 Reviewed-on: http://git-master/r/104698 Reviewed-by: Manish Tuteja <mtuteja@nvidia.com> Tested-by: Manish Tuteja <mtuteja@nvidia.com>
-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