aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2010-10-26 20:33:31 -0400
committerColin Cross <ccross@android.com>2011-02-21 03:16:47 -0500
commitc2f44a9df9e1f8974911ef538565e301b38e0680 (patch)
tree734b9169458a7372818152bd955d61027c0fe757 /arch/arm
parent9743b38969790d33b077ab80b175ea63a0398703 (diff)
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')
-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)
2236 2236
2237#ifdef CONFIG_PM 2237#ifdef CONFIG_PM
2238static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM + 2238static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
2239 PERIPH_CLK_SOURCE_NUM + 19]; 2239 PERIPH_CLK_SOURCE_NUM + 22];
2240 2240
2241void tegra_clk_suspend(void) 2241void tegra_clk_suspend(void)
2242{ 2242{
@@ -2244,16 +2244,18 @@ void tegra_clk_suspend(void)
2244 u32 *ctx = clk_rst_suspend; 2244 u32 *ctx = clk_rst_suspend;
2245 2245
2246 *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK; 2246 *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
2247 *ctx++ = clk_readl(tegra_pll_p.reg + PLL_BASE);
2248 *ctx++ = clk_readl(tegra_pll_p.reg + PLL_MISC(&tegra_pll_p));
2249 *ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE); 2247 *ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE);
2250 *ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c)); 2248 *ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
2251 *ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE); 2249 *ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE);
2252 *ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a)); 2250 *ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
2251 *ctx++ = clk_readl(tegra_pll_s.reg + PLL_BASE);
2252 *ctx++ = clk_readl(tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
2253 *ctx++ = clk_readl(tegra_pll_d.reg + PLL_BASE);
2254 *ctx++ = clk_readl(tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
2255 *ctx++ = clk_readl(tegra_pll_u.reg + PLL_BASE);
2256 *ctx++ = clk_readl(tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
2253 2257
2254 *ctx++ = clk_readl(tegra_pll_m_out1.reg); 2258 *ctx++ = clk_readl(tegra_pll_m_out1.reg);
2255 *ctx++ = clk_readl(tegra_pll_p_out1.reg);
2256 *ctx++ = clk_readl(tegra_pll_p_out3.reg);
2257 *ctx++ = clk_readl(tegra_pll_a_out0.reg); 2259 *ctx++ = clk_readl(tegra_pll_a_out0.reg);
2258 *ctx++ = clk_readl(tegra_pll_c_out1.reg); 2260 *ctx++ = clk_readl(tegra_pll_c_out1.reg);
2259 2261
@@ -2264,6 +2266,8 @@ void tegra_clk_suspend(void)
2264 *ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER); 2266 *ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
2265 *ctx++ = clk_readl(tegra_clk_pclk.reg); 2267 *ctx++ = clk_readl(tegra_clk_pclk.reg);
2266 2268
2269 *ctx++ = clk_readl(tegra_clk_audio.reg);
2270
2267 for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; 2271 for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
2268 off += 4) { 2272 off += 4) {
2269 if (off == PERIPH_CLK_SOURCE_EMC) 2273 if (off == PERIPH_CLK_SOURCE_EMC)
@@ -2281,6 +2285,8 @@ void tegra_clk_suspend(void)
2281 2285
2282 *ctx++ = clk_readl(MISC_CLK_ENB); 2286 *ctx++ = clk_readl(MISC_CLK_ENB);
2283 *ctx++ = clk_readl(CLK_MASK_ARM); 2287 *ctx++ = clk_readl(CLK_MASK_ARM);
2288
2289 BUG_ON(ctx - clk_rst_suspend != ARRAY_SIZE(clk_rst_suspend));
2284} 2290}
2285 2291
2286void tegra_clk_resume(void) 2292void tegra_clk_resume(void)
@@ -2293,17 +2299,19 @@ void tegra_clk_resume(void)
2293 val |= *ctx++; 2299 val |= *ctx++;
2294 clk_writel(val, OSC_CTRL); 2300 clk_writel(val, OSC_CTRL);
2295 2301
2296 clk_writel(*ctx++, tegra_pll_p.reg + PLL_BASE);
2297 clk_writel(*ctx++, tegra_pll_p.reg + PLL_MISC(&tegra_pll_p));
2298 clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE); 2302 clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE);
2299 clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c)); 2303 clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
2300 clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE); 2304 clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE);
2301 clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a)); 2305 clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
2302 udelay(300); 2306 clk_writel(*ctx++, tegra_pll_s.reg + PLL_BASE);
2307 clk_writel(*ctx++, tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
2308 clk_writel(*ctx++, tegra_pll_d.reg + PLL_BASE);
2309 clk_writel(*ctx++, tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
2310 clk_writel(*ctx++, tegra_pll_u.reg + PLL_BASE);
2311 clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
2312 udelay(1000);
2303 2313
2304 clk_writel(*ctx++, tegra_pll_m_out1.reg); 2314 clk_writel(*ctx++, tegra_pll_m_out1.reg);
2305 clk_writel(*ctx++, tegra_pll_p_out1.reg);
2306 clk_writel(*ctx++, tegra_pll_p_out3.reg);
2307 clk_writel(*ctx++, tegra_pll_a_out0.reg); 2315 clk_writel(*ctx++, tegra_pll_a_out0.reg);
2308 clk_writel(*ctx++, tegra_pll_c_out1.reg); 2316 clk_writel(*ctx++, tegra_pll_c_out1.reg);
2309 2317
@@ -2314,6 +2322,8 @@ void tegra_clk_resume(void)
2314 clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER); 2322 clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
2315 clk_writel(*ctx++, tegra_clk_pclk.reg); 2323 clk_writel(*ctx++, tegra_clk_pclk.reg);
2316 2324
2325 clk_writel(*ctx++, tegra_clk_audio.reg);
2326
2317 /* enable all clocks before configuring clock sources */ 2327 /* enable all clocks before configuring clock sources */
2318 clk_writel(0xbffffff9ul, CLK_OUT_ENB); 2328 clk_writel(0xbffffff9ul, CLK_OUT_ENB);
2319 clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4); 2329 clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);