summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/tegra2_clocks.c
diff options
context:
space:
mode:
authorColin Cross2010-10-27 02:33:31 +0200
committerColin Cross2011-02-21 09:16:47 +0100
commitc2f44a9df9e1f8974911ef538565e301b38e0680 (patch)
tree734b9169458a7372818152bd955d61027c0fe757 /arch/arm/mach-tegra/tegra2_clocks.c
parentARM: tegra: clock: Add function to set SDMMC tap delay (diff)
downloadkernel-qcow2-linux-c2f44a9df9e1f8974911ef538565e301b38e0680.tar.gz
kernel-qcow2-linux-c2f44a9df9e1f8974911ef538565e301b38e0680.tar.xz
kernel-qcow2-linux-c2f44a9df9e1f8974911ef538565e301b38e0680.zip
ARM: tegra: clock: Fix clock issues in suspend
The PLLP registers are now being restored by the low-level resume code, and the CPU may be running off PLLP, so don't touch them during clock resume. Save plld, plls, pllu, and audio clock during suspend (originally fixed by Mayuresh Kulkarni <mkulkarni@nvidia.com>) The lock time for plld is 1000 us, so increase the delay after setting the PLLs. Add a BUG_ON to ensure the size of the suspend context area is correct. Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra2_clocks.c')
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index b85d2c75fb3c..260b77c41436 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -2236,7 +2236,7 @@ void __init tegra2_init_clocks(void)
#ifdef CONFIG_PM
static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
- PERIPH_CLK_SOURCE_NUM + 19];
+ PERIPH_CLK_SOURCE_NUM + 22];
void tegra_clk_suspend(void)
{
@@ -2244,16 +2244,18 @@ void tegra_clk_suspend(void)
u32 *ctx = clk_rst_suspend;
*ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
- *ctx++ = clk_readl(tegra_pll_p.reg + PLL_BASE);
- *ctx++ = clk_readl(tegra_pll_p.reg + PLL_MISC(&tegra_pll_p));
*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);
*ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
+ *ctx++ = clk_readl(tegra_pll_s.reg + PLL_BASE);
+ *ctx++ = clk_readl(tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+ *ctx++ = clk_readl(tegra_pll_d.reg + PLL_BASE);
+ *ctx++ = clk_readl(tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+ *ctx++ = clk_readl(tegra_pll_u.reg + PLL_BASE);
+ *ctx++ = clk_readl(tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
*ctx++ = clk_readl(tegra_pll_m_out1.reg);
- *ctx++ = clk_readl(tegra_pll_p_out1.reg);
- *ctx++ = clk_readl(tegra_pll_p_out3.reg);
*ctx++ = clk_readl(tegra_pll_a_out0.reg);
*ctx++ = clk_readl(tegra_pll_c_out1.reg);
@@ -2264,6 +2266,8 @@ void tegra_clk_suspend(void)
*ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
*ctx++ = clk_readl(tegra_clk_pclk.reg);
+ *ctx++ = clk_readl(tegra_clk_audio.reg);
+
for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
off += 4) {
if (off == PERIPH_CLK_SOURCE_EMC)
@@ -2281,6 +2285,8 @@ void tegra_clk_suspend(void)
*ctx++ = clk_readl(MISC_CLK_ENB);
*ctx++ = clk_readl(CLK_MASK_ARM);
+
+ BUG_ON(ctx - clk_rst_suspend != ARRAY_SIZE(clk_rst_suspend));
}
void tegra_clk_resume(void)
@@ -2293,17 +2299,19 @@ void tegra_clk_resume(void)
val |= *ctx++;
clk_writel(val, OSC_CTRL);
- clk_writel(*ctx++, tegra_pll_p.reg + PLL_BASE);
- clk_writel(*ctx++, tegra_pll_p.reg + PLL_MISC(&tegra_pll_p));
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);
clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
- udelay(300);
+ clk_writel(*ctx++, tegra_pll_s.reg + PLL_BASE);
+ clk_writel(*ctx++, tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+ clk_writel(*ctx++, tegra_pll_d.reg + PLL_BASE);
+ clk_writel(*ctx++, tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+ clk_writel(*ctx++, tegra_pll_u.reg + PLL_BASE);
+ 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_p_out1.reg);
- clk_writel(*ctx++, tegra_pll_p_out3.reg);
clk_writel(*ctx++, tegra_pll_a_out0.reg);
clk_writel(*ctx++, tegra_pll_c_out1.reg);
@@ -2314,6 +2322,8 @@ void tegra_clk_resume(void)
clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
clk_writel(*ctx++, tegra_clk_pclk.reg);
+ clk_writel(*ctx++, tegra_clk_audio.reg);
+
/* enable all clocks before configuring clock sources */
clk_writel(0xbffffff9ul, CLK_OUT_ENB);
clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);