summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-01-16 19:18:44 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:41:56 -0800
commit96133b6042b7418074cdf14a647937f4b28a1548 (patch)
treedccacc377437ac9adb35675e3101fd04437d2b97 /arch
parent4499f598e2af7ede7ab81d1a20d9671126e2922d (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.h11
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c38
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c67
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];