diff options
author | Alex Frid <afrid@nvidia.com> | 2011-01-16 19:18:44 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:41:56 -0800 |
commit | 96133b6042b7418074cdf14a647937f4b28a1548 (patch) | |
tree | dccacc377437ac9adb35675e3101fd04437d2b97 /arch | |
parent | 4499f598e2af7ede7ab81d1a20d9671126e2922d (diff) |
ARM: tegra: cpufreq: Add cpu frequency table selection
Define cpu frequency tables for different tegra2 CPU clock ranges,
and add matching selection mechanism for scaling table as well as
throttling limits.
Original-Change-Id: I06b13f150d72f8a80f879ecf80ed44cc1f63bad4
Reviewed-on: http://git-master/r/16076
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Rebase-Id: Rc69b8d00284b7bc164d47beb3615b712bfc2c25c
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 11 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 38 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 67 |
3 files changed, 95 insertions, 21 deletions
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 1e5559bdc2f8..d997f8bf27e4 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -203,4 +203,15 @@ static inline void clk_lock_init(struct clk *c) spin_lock_init(&c->spinlock); } +#ifdef CONFIG_CPU_FREQ +struct cpufreq_frequency_table; + +struct tegra_cpufreq_table_data { + struct cpufreq_frequency_table *freq_table; + int throttle_lowest_index; + int throttle_highest_index; +}; +struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void); +#endif + #endif diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index 461e7fb0785c..29845ae46d8a 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -35,21 +35,9 @@ #include <mach/clk.h> -/* - * Frequency table index must be sequential starting at 0 and frequencies - * must be ascending. - */ -static struct cpufreq_frequency_table freq_table[] = { - { 0, 216000 }, - { 1, 312000 }, - { 2, 456000 }, - { 3, 608000 }, - { 4, 760000 }, - { 5, 816000 }, - { 6, 912000 }, - { 7, 1000000 }, - { 8, CPUFREQ_TABLE_END }, -}; +#include "clock.h" + +static struct cpufreq_frequency_table *freq_table; #define NUM_CPUS 2 @@ -66,11 +54,11 @@ static unsigned long tegra_cpu_highest_speed(void); #ifdef CONFIG_TEGRA_THERMAL_THROTTLE /* CPU frequency is gradually lowered when throttling is enabled */ -#define THROTTLE_LOWEST_INDEX 2 /* 456000 */ -#define THROTTLE_HIGHEST_INDEX 6 /* 912000 */ #define THROTTLE_DELAY msecs_to_jiffies(2000) static bool is_throttling; +static int throttle_lowest_index; +static int throttle_highest_index; static int throttle_index; static int throttle_next_index; static struct delayed_work throttle_work; @@ -89,7 +77,7 @@ static void tegra_throttle_work_func(struct work_struct *work) if (freq_table[throttle_index].frequency < current_freq) tegra_update_cpu_speed(freq_table[throttle_index].frequency); - if (throttle_index > THROTTLE_LOWEST_INDEX) { + if (throttle_index > throttle_lowest_index) { throttle_next_index = throttle_index - 1; queue_delayed_work(workqueue, &throttle_work, THROTTLE_DELAY); } @@ -110,14 +98,14 @@ void tegra_throttling_enable(bool enable) is_throttling = true; - for (throttle_index = THROTTLE_HIGHEST_INDEX; - throttle_index >= THROTTLE_LOWEST_INDEX; + for (throttle_index = throttle_highest_index; + throttle_index >= throttle_lowest_index; throttle_index--) if (freq_table[throttle_index].frequency < current_freq) break; - throttle_index = max(throttle_index, THROTTLE_LOWEST_INDEX); + throttle_index = max(throttle_index, throttle_lowest_index); throttle_next_index = throttle_index; queue_delayed_work(workqueue, &throttle_work, 0); } else if (!enable && is_throttling) { @@ -382,6 +370,10 @@ static struct cpufreq_driver tegra_cpufreq_driver = { static int __init tegra_cpufreq_init(void) { + struct tegra_cpufreq_table_data *table_data = + tegra_cpufreq_table_get(); + BUG_ON(!table_data); + #ifdef CONFIG_TEGRA_THERMAL_THROTTLE /* * High-priority, others flags default: not bound to a specific @@ -393,7 +385,11 @@ static int __init tegra_cpufreq_init(void) if (!workqueue) return -ENOMEM; INIT_DELAYED_WORK(&throttle_work, tegra_throttle_work_func); + + throttle_lowest_index = table_data->throttle_lowest_index; + throttle_highest_index = table_data->throttle_highest_index; #endif + freq_table = table_data->freq_table; return cpufreq_register_driver(&tegra_cpufreq_driver); } diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 68b79094a3df..95eef1652a18 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -26,6 +26,7 @@ #include <linux/clkdev.h> #include <linux/clk.h> #include <linux/syscore_ops.h> +#include <linux/cpufreq.h> #include <mach/iomap.h> @@ -2315,6 +2316,72 @@ static void tegra2_init_one_clock(struct clk *c) clkdev_add(&c->lookup); } +#ifdef CONFIG_CPU_FREQ + +/* + * Frequency table index must be sequential starting at 0 and frequencies + * must be ascending. + */ + +static struct cpufreq_frequency_table freq_table_750MHz[] = { + { 0, 216000 }, + { 1, 312000 }, + { 2, 456000 }, + { 3, 608000 }, + { 4, 750000 }, + { 5, CPUFREQ_TABLE_END }, +}; + +static struct cpufreq_frequency_table freq_table_1p0GHz[] = { + { 0, 216000 }, + { 1, 312000 }, + { 2, 456000 }, + { 3, 608000 }, + { 4, 760000 }, + { 5, 816000 }, + { 6, 912000 }, + { 7, 1000000 }, + { 8, CPUFREQ_TABLE_END }, +}; + +static struct cpufreq_frequency_table freq_table_1p2GHz[] = { + { 0, 216000 }, + { 1, 312000 }, + { 2, 456000 }, + { 3, 608000 }, + { 4, 760000 }, + { 5, 816000 }, + { 6, 912000 }, + { 7, 1000000 }, + { 8, 1200000 }, + { 9, CPUFREQ_TABLE_END }, +}; + +static struct tegra_cpufreq_table_data cpufreq_tables[] = { + { freq_table_750MHz, 1, 4 }, + { freq_table_1p0GHz, 2, 6 }, + { freq_table_1p2GHz, 2, 7 }, +}; + +struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void) +{ + int i, ret; + struct clk *cpu_clk = tegra_get_clock_by_name("cpu"); + + for (i = 0; i < ARRAY_SIZE(cpufreq_tables); i++) { + struct cpufreq_policy policy; + ret = cpufreq_frequency_table_cpuinfo( + &policy, cpufreq_tables[i].freq_table); + BUG_ON(ret); + if ((policy.max * 1000) == cpu_clk->max_rate) + return &cpufreq_tables[i]; + } + pr_err("%s: No cpufreq table matching cpu range", __func__); + BUG(); + return &cpufreq_tables[0]; +} +#endif + #ifdef CONFIG_PM static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM + PERIPH_CLK_SOURCE_NUM + 22]; |