diff options
author | Alex Frid <afrid@nvidia.com> | 2010-08-21 22:38:44 -0700 |
---|---|---|
committer | Yu-Huan Hsu <yhsu@nvidia.com> | 2010-09-03 12:16:24 -0700 |
commit | 0e52d7fe25b11a656c376a37890be219470661fb (patch) | |
tree | aa4411e695c2f180f935d91554b1fee1212c59a1 | |
parent | a537fc2dce58424510fc514eb499c544ae1ac96e (diff) |
[ARM/tegra] power: Added non-boot PLL restoration.tegra-10.8.3
Added non-boot PLL (PLLC/PLLA/PLLD) restoration during clock resume
before clock dividers are restored. (Current restoration in RM happens
late after clock dividers are restored).
Change-Id: I9661f5ddba0ba4b25d5a00c78820792791777429
Reviewed-on: http://git-master/r/5515
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Iqbal Bhinderwala <iqbalb@nvidia.com>
Reviewed-by: Rajkumar Jayaraman <rjayaraman@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/clock_nvrm.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/clock_nvrm.c b/arch/arm/mach-tegra/clock_nvrm.c index cc4dde9be1e6..598c001179a2 100644 --- a/arch/arm/mach-tegra/clock_nvrm.c +++ b/arch/arm/mach-tegra/clock_nvrm.c @@ -455,6 +455,7 @@ void __init tegra_init_clock(void) #ifdef CONFIG_PM #define CLK_RESET_RST_DEVICES_L 0x04 #define CLK_RESET_RST_DEVICES_NUM 3 +#define CLK_RESET_PROPAGATION_US 10 #define CLK_RESET_CLK_OUT_ENB_L 0x10 #define CLK_RESET_CLK_OUT_ENB_H 0x14 @@ -469,6 +470,17 @@ void __init tegra_init_clock(void) #define CLK_RESET_OSC_CTRL 0x50 #define CLK_RESET_OSC_CTRL_MASK 0x3f2 /* drive strength & bypass */ +#define CLK_RESET_PLLC_BASE 0x80 +#define CLK_RESET_PLLC_MISC 0x8C +#define CLK_RESET_PLLA_BASE 0xB0 +#define CLK_RESET_PLLA_MISC 0xBC +#define CLK_RESET_PLLD_BASE 0xD0 +#define CLK_RESET_PLLD_MISC 0xDC +#define CLK_RESET_NON_BOOT_PLLS_NUM 3 +#define CLK_RESET_PLL_ENABLE_MASK (0x1 << 30) +#define CLK_RESET_PLL_STAB_US 300 +#define CLK_RESET_PLL_STAB_LONG_US 1000 + #define CLK_RESET_CLK_SOURCE_I2S1 0x100 #define CLK_RESET_CLK_SOURCE_EMC 0x19c #define CLK_RESET_CLK_SOURCE_OSC 0x1fc @@ -476,6 +488,7 @@ void __init tegra_init_clock(void) (((CLK_RESET_CLK_SOURCE_OSC - CLK_RESET_CLK_SOURCE_I2S1) / 4) + 1 - 1) static u32 clk_rst[CLK_RESET_RST_DEVICES_NUM + CLK_RESET_CLK_OUT_ENB_NUM + + (CLK_RESET_NON_BOOT_PLLS_NUM * 2) + CLK_RESET_CLK_SOURCE_NUM + 3]; void tegra_clk_suspend(void) @@ -486,6 +499,13 @@ void tegra_clk_suspend(void) *ctx++ = readl(car + CLK_RESET_OSC_CTRL) & CLK_RESET_OSC_CTRL_MASK; + *ctx++ = readl(car + CLK_RESET_PLLC_MISC); + *ctx++ = readl(car + CLK_RESET_PLLC_BASE); + *ctx++ = readl(car + CLK_RESET_PLLA_MISC); + *ctx++ = readl(car + CLK_RESET_PLLA_BASE); + *ctx++ = readl(car + CLK_RESET_PLLD_MISC); + *ctx++ = readl(car + CLK_RESET_PLLD_BASE); + for (offs=CLK_RESET_CLK_SOURCE_I2S1; offs<=CLK_RESET_CLK_SOURCE_OSC; offs+=4) { @@ -519,6 +539,30 @@ void tegra_clk_resume(void) temp = readl(car + CLK_RESET_OSC_CTRL) & ~CLK_RESET_OSC_CTRL_MASK; temp |= *ctx++; writel(temp, car + CLK_RESET_OSC_CTRL); + wmb(); + + writel(*ctx++, car + CLK_RESET_PLLC_MISC); + temp = *ctx & (~CLK_RESET_PLL_ENABLE_MASK); + writel(temp, car + CLK_RESET_PLLC_BASE); + wmb(); + writel(*ctx++, car + CLK_RESET_PLLC_BASE); + + writel(*ctx++, car + CLK_RESET_PLLA_MISC); + temp = *ctx & (~CLK_RESET_PLL_ENABLE_MASK); + writel(temp, car + CLK_RESET_PLLA_BASE); + wmb(); + writel(*ctx++, car + CLK_RESET_PLLA_BASE); + + writel(*ctx++, car + CLK_RESET_PLLD_MISC); + temp = *ctx & (~CLK_RESET_PLL_ENABLE_MASK); + writel(temp, car + CLK_RESET_PLLD_BASE); + wmb(); + temp = *ctx++; + if (temp & CLK_RESET_PLL_ENABLE_MASK) { + writel(temp, car + CLK_RESET_PLLD_BASE); + udelay(CLK_RESET_PLL_STAB_LONG_US); + } else + udelay(CLK_RESET_PLL_STAB_US); writel(CLK_RESET_CLK_OUT_ENB_L_ALL, car + CLK_RESET_CLK_OUT_ENB_L); writel(CLK_RESET_CLK_OUT_ENB_H_ALL, car + CLK_RESET_CLK_OUT_ENB_H); @@ -532,6 +576,7 @@ void tegra_clk_resume(void) writel(*ctx++, car + offs); } wmb(); + udelay(CLK_RESET_PROPAGATION_US); offs = CLK_RESET_RST_DEVICES_L; for (i=0; i<CLK_RESET_RST_DEVICES_NUM; i++) |