diff options
author | Alex Frid <afrid@nvidia.com> | 2012-01-19 23:21:21 -0800 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-01-30 13:52:24 -0800 |
commit | de35867d1c0b0c5cfab4b667ff81eab2ad114dc4 (patch) | |
tree | 23585b58c73f90e103fab6b42b37883553a61c1d /arch/arm/mach-tegra | |
parent | 67982941e82909832661865aea8f7ff939f4cd6e (diff) |
ARM: tegra: clock: Update CPU clock scaling dependencies
Added Tegra3 MSelect clock to memory on CPU clock dependencies:
MSelect rate is scaled as half of CPU rate, up to 102MHz. Prevented
CPU clock increase if updates of dependent clocks (EMC and MSelect)
have failed.
Reviewed-on: http://git-master/r/76485
Change-Id: I679b60eb5aa13d5cca2b9751ff2c8c2fb866a076
Signed-off-by: Alex Frid <afrid@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/77767
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_clocks.c | 24 |
3 files changed, 47 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 33dfe3e47718..b47821e12274 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -298,6 +298,12 @@ struct tegra_cpufreq_table_data { }; struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void); unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +static inline int tegra_update_mselect_rate(unsigned long cpu_rate) +{ return 0; } +#else +int tegra_update_mselect_rate(unsigned long cpu_rate); +#endif #endif #endif diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index 24ed5d229a5d..de290ce65804 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -473,8 +473,20 @@ static int tegra_update_cpu_speed(unsigned long rate) * Vote on memory bus frequency based on cpu frequency * This sets the minimum frequency, display or avp may request higher */ - if (freqs.old < freqs.new) - clk_set_rate(emc_clk, tegra_emc_to_cpu_ratio(freqs.new)); + if (freqs.old < freqs.new) { + ret = tegra_update_mselect_rate(freqs.new); + if (ret) { + pr_err("cpu-tegra: Failed to scale mselect for cpu" + " frequency %u kHz\n", freqs.new); + return ret; + } + ret = clk_set_rate(emc_clk, tegra_emc_to_cpu_ratio(freqs.new)); + if (ret) { + pr_err("cpu-tegra: Failed to scale emc for cpu" + " frequency %u kHz\n", freqs.new); + return ret; + } + } for_each_online_cpu(freqs.cpu) cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); @@ -494,8 +506,10 @@ static int tegra_update_cpu_speed(unsigned long rate) for_each_online_cpu(freqs.cpu) cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - if (freqs.old > freqs.new) + if (freqs.old > freqs.new) { clk_set_rate(emc_clk, tegra_emc_to_cpu_ratio(freqs.new)); + tegra_update_mselect_rate(freqs.new); + } return 0; } diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index 9d82186dc5f0..ff7c0d09e7c6 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -4728,6 +4728,30 @@ unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate) else return 0; /* emc min */ } + +int tegra_update_mselect_rate(unsigned long cpu_rate) +{ + static struct clk *mselect = NULL; + + unsigned long mselect_rate; + + if (!mselect) { + mselect = tegra_get_clock_by_name("mselect"); + if (!mselect) + return -ENODEV; + } + + /* Vote on mselect frequency based on cpu frequency: + keep mselect at half of cpu rate up to 102 MHz; + cpu rate is in kHz, mselect rate is in Hz */ + mselect_rate = DIV_ROUND_UP(cpu_rate, 2) * 1000; + mselect_rate = min(mselect_rate, 102000000UL); + + if (mselect_rate != clk_get_rate(mselect)) + return clk_set_rate(mselect, mselect_rate); + + return 0; +} #endif #ifdef CONFIG_PM_SLEEP |