summaryrefslogtreecommitdiff
path: root/arch/arm/plat-mxs/cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-mxs/cpufreq.c')
-rw-r--r--arch/arm/plat-mxs/cpufreq.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/arch/arm/plat-mxs/cpufreq.c b/arch/arm/plat-mxs/cpufreq.c
index 8cb0ff581267..d36baa740dbc 100644
--- a/arch/arm/plat-mxs/cpufreq.c
+++ b/arch/arm/plat-mxs/cpufreq.c
@@ -52,6 +52,7 @@ int cpufreq_trig_needed;
int cur_freq_table_size;
int lcd_on_freq_table_size;
int lcd_off_freq_table_size;
+int high_freq_needed;
extern char *ahb_clk_id;
extern struct profile profiles[OPERATION_WP_SUPPORTED];
@@ -100,7 +101,7 @@ static int set_freq_table(struct cpufreq_policy *policy, int end_index)
return ret;
}
-static int set_op(unsigned int target_freq)
+static int set_op(struct cpufreq_policy *policy, unsigned int target_freq)
{
struct cpufreq_freqs freqs;
int ret = 0, i;
@@ -129,7 +130,7 @@ static int set_op(unsigned int target_freq)
if (i == 0)
freqs.new = profiles[i].cpu;
- if (freqs.old == freqs.new) {
+ if ((freqs.old / 1000) == (freqs.new / 1000)) {
if (regulator_get_voltage(vddd) == profiles[i].vddd)
return 0;
}
@@ -144,8 +145,10 @@ static int set_op(unsigned int target_freq)
}
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
if (freqs.old > freqs.new) {
int ss = profiles[i].ss;
+
clk_set_rate(cpu_clk, (profiles[i].cpu) * 1000);
clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
clk_set_rate(emi_clk, (profiles[i].emi) * 1000);
@@ -206,21 +209,33 @@ static int set_op(unsigned int target_freq)
profiles[i].vdda);
}
timing_ctrl_rams(ss);
+ if (freqs.old == 64000)
+ clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
clk_set_rate(cpu_clk, (profiles[i].cpu) * 1000);
- clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
+ if (freqs.old != 64000)
+ clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
clk_set_rate(emi_clk, (profiles[i].emi) * 1000);
}
udelay(100);
cpu_clk_set_pll_off(cpu_clk, freqs.new);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ if (high_freq_needed == 0)
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
if (cpu_regulator && (freqs.old > freqs.new)) /* will not fail */
regulator_set_current_limit(cpu_regulator,
profiles[i].cur,
profiles[i].cur);
+ if (high_freq_needed == 1) {
+ high_freq_needed = 0;
+ cur_freq_table_size = lcd_on_freq_table_size;
+ hbus_auto_slow_mode_disable();
+ set_freq_table(policy, cur_freq_table_size);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+
return ret;
}
@@ -259,13 +274,23 @@ static int mxs_target(struct cpufreq_policy *policy,
/* Set the current working point. */
cpufreq_trig_needed = 0;
target_freq = clk_get_rate(cpu_clk) / 1000;
+ low_freq_bus_ready = low_freq_used();
+
+ if ((target_freq < LCD_ON_CPU_FREQ_KHZ) &&
+ (low_freq_bus_ready == 0)) {
+ high_freq_needed = 1;
+ target_freq = LCD_ON_CPU_FREQ_KHZ;
+ goto change_freq;
+ }
+
+ target_freq = clk_get_rate(cpu_clk) / 1000;
freq_KHz = calc_frequency_khz(target_freq, relation);
freqs.old = target_freq;
freqs.new = freq_KHz;
freqs.cpu = 0;
freqs.flags = 0;
-
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
low_freq_bus_ready = low_freq_used();
if (low_freq_bus_ready) {
cur_freq_table_size = lcd_off_freq_table_size;
@@ -276,9 +301,7 @@ static int mxs_target(struct cpufreq_policy *policy,
}
set_freq_table(policy, cur_freq_table_size);
-
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
return 0;
}
@@ -287,37 +310,21 @@ static int mxs_target(struct cpufreq_policy *policy,
* which leads to bad things (division by zero etc), ensure
* that such things do not happen.
*/
- if (target_freq < policy->cpuinfo.min_freq)
+change_freq: if (target_freq < policy->cpuinfo.min_freq)
target_freq = policy->cpuinfo.min_freq;
if (target_freq < policy->min)
target_freq = policy->min;
freq_KHz = calc_frequency_khz(target_freq, relation);
- return set_op(freq_KHz);
+ return set_op(policy, freq_KHz);
}
static unsigned int mxs_getspeed(unsigned int cpu)
{
- struct cpufreq_freqs freqs;
- int freq_KHz;
- unsigned int target_freq;
-
if (cpu)
return 0;
- if (cpufreq_trig_needed == 1) {
- target_freq = clk_get_rate(cpu_clk) / 1000;
- freq_KHz = calc_frequency_khz(target_freq, CPUFREQ_RELATION_L);
-
- freqs.old = target_freq;
- freqs.new = freq_KHz;
- freqs.cpu = 0;
- freqs.flags = 0;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- }
-
return clk_get_rate(cpu_clk) / 1000;
}
@@ -341,7 +348,7 @@ static int __init mxs_cpu_init(struct cpufreq_policy *policy)
goto out_cpu;
}
- ahb_clk = clk_get(NULL, ahb_clk_id);
+ ahb_clk = clk_get(NULL, "h");
if (IS_ERR(ahb_clk)) {
ret = PTR_ERR(ahb_clk);
goto out_ahb;
@@ -423,6 +430,7 @@ static int __init mxs_cpu_init(struct cpufreq_policy *policy)
/* Set the current working point. */
set_freq_table(policy, lcd_on_freq_table_size);
cpufreq_trig_needed = 0;
+ high_freq_needed = 0;
cur_freq_table_size = lcd_on_freq_table_size;
printk(KERN_INFO "%s: cpufreq init finished\n", __func__);
@@ -451,7 +459,7 @@ static int mxs_cpu_exit(struct cpufreq_policy *policy)
cpufreq_frequency_table_put_attr(policy->cpu);
/* Reset CPU to 392MHz */
- set_op(profiles[1].cpu);
+ set_op(policy, profiles[1].cpu);
clk_put(cpu_clk);
regulator_put(cpu_regulator);