summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-tegra/clock.c5
-rw-r--r--arch/arm/mach-tegra/clock.h1
-rw-r--r--arch/arm/mach-tegra/cpu-tegra3.c8
-rw-r--r--arch/arm/mach-tegra/tegra3_clocks.c30
4 files changed, 35 insertions, 9 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 2fe6df739fd6..cc83511ce446 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -137,6 +137,11 @@ unsigned long clk_get_max_rate(struct clk *c)
return c->max_rate;
}
+unsigned long clk_get_min_rate(struct clk *c)
+{
+ return c->min_rate;
+}
+
/* Must be called with clk_lock(c) held */
unsigned long clk_get_rate_locked(struct clk *c)
{
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 3c109571321f..3c8710076d64 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -202,6 +202,7 @@ int clk_reparent(struct clk *c, struct clk *parent);
void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
void clk_set_cansleep(struct clk *c);
unsigned long clk_get_max_rate(struct clk *c);
+unsigned long clk_get_min_rate(struct clk *c);
unsigned long clk_get_rate_locked(struct clk *c);
int clk_set_rate_locked(struct clk *c, unsigned long rate);
void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c
index acd6889e54f7..84ddc4ffb626 100644
--- a/arch/arm/mach-tegra/cpu-tegra3.c
+++ b/arch/arm/mach-tegra/cpu-tegra3.c
@@ -37,7 +37,6 @@
#include "clock.h"
#define INITIAL_STATE TEGRA_HP_DISABLED
-#define IDLE_HYSTERESIS 100000
#define UP2G0_DELAY_MS 200
#define UP2Gn_DELAY_MS 1000
#define DOWN_DELAY_MS 2000
@@ -62,8 +61,6 @@ static unsigned int idle_bottom_freq;
module_param(idle_top_freq, uint, 0644);
module_param(idle_bottom_freq, uint, 0644);
-static unsigned int lpcpu_max_freq;
-
static struct clk *cpu_clk;
static struct clk *cpu_g_clk;
static struct clk *cpu_lp_clk;
@@ -340,9 +337,8 @@ int tegra_auto_hotplug_init(struct mutex *cpu_lock)
if (IS_ERR(cpu_clk) || IS_ERR(cpu_g_clk) || IS_ERR(cpu_lp_clk))
return -ENOENT;
- lpcpu_max_freq = clk_get_max_rate(cpu_lp_clk) / 1000;
- idle_top_freq = lpcpu_max_freq;
- idle_bottom_freq = idle_top_freq - IDLE_HYSTERESIS;
+ idle_top_freq = clk_get_max_rate(cpu_lp_clk) / 1000;
+ idle_bottom_freq = clk_get_min_rate(cpu_g_clk) / 1000;
up2g0_delay = msecs_to_jiffies(UP2G0_DELAY_MS);
up2gn_delay = msecs_to_jiffies(UP2Gn_DELAY_MS);
diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c
index 97534eb743b3..68c38450cf41 100644
--- a/arch/arm/mach-tegra/tegra3_clocks.c
+++ b/arch/arm/mach-tegra/tegra3_clocks.c
@@ -2974,7 +2974,6 @@ static struct clk tegra_clk_virtual_cpu_g = {
.parent = &tegra_clk_cclk_g,
.ops = &tegra_cpu_ops,
.max_rate = 1000000000,
- .min_rate = 312000000,
.u.cpu = {
.main = &tegra_pll_x,
.backup = &tegra_pll_p,
@@ -2986,7 +2985,7 @@ static struct clk tegra_clk_virtual_cpu_lp = {
.name = "cpu_lp",
.parent = &tegra_clk_cclk_lp,
.ops = &tegra_cpu_ops,
- .max_rate = 456000000,
+ .max_rate = 500000000,
.u.cpu = {
.main = &tegra_pll_x,
.backup = &tegra_pll_p,
@@ -3479,6 +3478,27 @@ static struct tegra_cpufreq_table_data cpufreq_tables[] = {
{ freq_table_1p0GHz, 2, 6 },
};
+static void clip_cpu_rate_limits(
+ struct cpufreq_frequency_table *freq_table,
+ struct cpufreq_policy *policy)
+{
+ int idx, ret;
+ struct clk *cpu_clk_g = tegra_get_clock_by_name("cpu_g");
+ struct clk *cpu_clk_lp = tegra_get_clock_by_name("cpu_lp");
+
+ /* clip CPU LP mode maximum frequency to table entry, and
+ set CPU G mode minimum frequency one table step below */
+ ret = cpufreq_frequency_table_target(policy, freq_table,
+ cpu_clk_lp->max_rate / 1000, CPUFREQ_RELATION_H, &idx);
+ if (ret || !idx) {
+ pr_err("%s: LP CPU max rate %lu %s of cpufreq table", __func__,
+ cpu_clk_lp->max_rate, ret ? "outside" : "at the bottom");
+ BUG();
+ }
+ cpu_clk_lp->max_rate = freq_table[idx].frequency * 1000;
+ cpu_clk_g->min_rate = freq_table[idx-1].frequency * 1000;
+}
+
struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void)
{
int i, ret;
@@ -3486,11 +3506,15 @@ struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void)
for (i = 0; i < ARRAY_SIZE(cpufreq_tables); i++) {
struct cpufreq_policy policy;
+ policy.cpu = 0; /* any on-line cpu */
ret = cpufreq_frequency_table_cpuinfo(
&policy, cpufreq_tables[i].freq_table);
BUG_ON(ret);
- if ((policy.max * 1000) == cpu_clk->max_rate)
+ if ((policy.max * 1000) == cpu_clk->max_rate) {
+ clip_cpu_rate_limits(
+ cpufreq_tables[i].freq_table, &policy);
return &cpufreq_tables[i];
+ }
}
pr_err("%s: No cpufreq table matching cpu range", __func__);
BUG();