diff options
author | Alex Frid <afrid@nvidia.com> | 2011-04-05 20:24:36 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-04-26 15:55:24 -0700 |
commit | ee032660b52e0b1f5a3a1d79f9a90294e23bae2e (patch) | |
tree | 57186fc53525a72ee7471ae8e76d6cddc5b0648b /arch/arm/mach-tegra | |
parent | 6d6404ee3a1d8646b9a26bbe2e17b518e6f41545 (diff) |
ARM: tegra: power: Re-initialize Tegra3 EMC after LP0
Since EMC frequency is not restored after exit from LP0, re-initialize
EMC clock with the new warm boot configuration, and make sure that the
1st after LP0 clock change does not use stale timing cache.
Skip Tegra2 specific EMC restoration on Tegra3 platforms.
Original-Change-Id: I4be0d3b839e871151c3c2158a002a0c763de34c2
Reviewed-on: http://git-master/r/26807
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Change-Id: I2ffeb64d96a425966d258d0479b3561c4a6eb406
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/suspend.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_clocks.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.c | 9 |
4 files changed, 18 insertions, 5 deletions
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 95dcf48a4f78..46ada3ac50b1 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -196,8 +196,6 @@ struct tegra_sku_rate_limit { void tegra_soc_init_clocks(void); void tegra2_init_clocks(void); -void tegra2_periph_reset_deassert(struct clk *c); -void tegra2_periph_reset_assert(struct clk *c); void clk_init(struct clk *clk); struct clk *tegra_get_clock_by_name(const char *name); unsigned long clk_measure_input_freq(void); @@ -210,6 +208,7 @@ void tegra2_sdmmc_tap_delay(struct clk *c, int delay); int tegra_emc_set_rate(unsigned long rate); long tegra_emc_round_rate(unsigned long rate); struct clk *tegra_emc_predict_parent(unsigned long rate, u32 *div_value); +void tegra_emc_timing_invalidate(void); #ifdef CONFIG_CPU_FREQ struct cpufreq_frequency_table; diff --git a/arch/arm/mach-tegra/suspend.c b/arch/arm/mach-tegra/suspend.c index 0839b861f9e6..77aa88c7ac18 100644 --- a/arch/arm/mach-tegra/suspend.c +++ b/arch/arm/mach-tegra/suspend.c @@ -771,7 +771,9 @@ static int tegra_suspend_enter(suspend_state_t state) { struct irq_desc *desc; void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE); +#endif unsigned long flags; u32 mc_data[3] = {0, 0, 0}; int irq; @@ -840,10 +842,10 @@ static int tegra_suspend_enter(suspend_state_t state) writel(mc_data[0], mc + MC_SECURITY_START); writel(mc_data[1], mc + MC_SECURITY_SIZE); writel(mc_data[2], mc + MC_SECURITY_CFG2); - +#ifdef CONFIG_ARCH_TEGRA_2x_SOC /* trigger emc mode write */ writel(EMC_MRW_DEV_NONE, emc + EMC_MRW_0); - +#endif tegra_clk_resume(); tegra_gpio_resume(); tegra_timer_resume(); diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index 169124a6bef9..1af74d1c5655 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -3661,5 +3661,10 @@ void tegra_clk_resume(void) clk_writel(*ctx++, MISC_CLK_ENB); clk_writel(*ctx++, CLK_MASK_ARM); + + /* Since EMC clock is not restored update current state, and mark + EMC DFS as out of sync */ + tegra3_periph_clk_init(&tegra_clk_emc); + tegra_emc_timing_invalidate(); } #endif diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c index 2335d90504b8..d4ee7d9f3af2 100644 --- a/arch/arm/mach-tegra/tegra3_emc.c +++ b/arch/arm/mach-tegra/tegra3_emc.c @@ -181,6 +181,7 @@ enum { static struct clk_mux_sel tegra_emc_clk_sel[TEGRA_EMC_TABLE_MAX_SIZE]; static int emc_last_sel; static struct tegra_emc_table start_timing; +static bool emc_timing_in_sync; static const struct tegra_emc_table *tegra_emc_table; static int tegra_emc_table_size; @@ -606,7 +607,7 @@ int tegra_emc_set_rate(unsigned long rate) if (i >= tegra_emc_table_size) return -EINVAL; - if (!emc_stats.clkchange_count) { + if (!emc_timing_in_sync) { /* can not assume that boot timing matches dfs table even if boot frequency matches one of the table nodes */ emc_get_timing(&start_timing); @@ -617,6 +618,7 @@ int tegra_emc_set_rate(unsigned long rate) clk_setting = tegra_emc_clk_sel[i].value; emc_set_clock(&tegra_emc_table[i], last_timing, clk_setting); + emc_timing_in_sync = true; emc_last_stats_update(i); pr_debug("%s: rate %lu setting 0x%x\n", __func__, rate, clk_setting); @@ -781,6 +783,11 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size) tegra_emc_table = table; } +void tegra_emc_timing_invalidate(void) +{ + emc_timing_in_sync = false; +} + #ifdef CONFIG_DEBUG_FS static struct dentry *emc_debugfs_root; |