diff options
Diffstat (limited to 'drivers/cpufreq/s3c2416-cpufreq.c')
| -rw-r--r-- | drivers/cpufreq/s3c2416-cpufreq.c | 129 |
1 files changed, 40 insertions, 89 deletions
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 22dcb81ef9d..2fd53eaaec2 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -72,31 +72,21 @@ static struct s3c2416_dvfs s3c2416_dvfs_table[] = { #endif static struct cpufreq_frequency_table s3c2416_freq_table[] = { - { SOURCE_HCLK, FREQ_DVS }, - { SOURCE_ARMDIV, 133333 }, - { SOURCE_ARMDIV, 266666 }, - { SOURCE_ARMDIV, 400000 }, - { 0, CPUFREQ_TABLE_END }, + { 0, SOURCE_HCLK, FREQ_DVS }, + { 0, SOURCE_ARMDIV, 133333 }, + { 0, SOURCE_ARMDIV, 266666 }, + { 0, SOURCE_ARMDIV, 400000 }, + { 0, 0, CPUFREQ_TABLE_END }, }; static struct cpufreq_frequency_table s3c2450_freq_table[] = { - { SOURCE_HCLK, FREQ_DVS }, - { SOURCE_ARMDIV, 133500 }, - { SOURCE_ARMDIV, 267000 }, - { SOURCE_ARMDIV, 534000 }, - { 0, CPUFREQ_TABLE_END }, + { 0, SOURCE_HCLK, FREQ_DVS }, + { 0, SOURCE_ARMDIV, 133500 }, + { 0, SOURCE_ARMDIV, 267000 }, + { 0, SOURCE_ARMDIV, 534000 }, + { 0, 0, CPUFREQ_TABLE_END }, }; -static int s3c2416_cpufreq_verify_speed(struct cpufreq_policy *policy) -{ - struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; - - if (policy->cpu != 0) - return -EINVAL; - - return cpufreq_frequency_table_verify(policy, s3c_freq->freq_table); -} - static unsigned int s3c2416_cpufreq_get_speed(unsigned int cpu) { struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; @@ -227,24 +217,15 @@ static int s3c2416_cpufreq_leave_dvs(struct s3c2416_data *s3c_freq, int idx) } static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int index) { struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; - struct cpufreq_freqs freqs; + unsigned int new_freq; int idx, ret, to_dvs = 0; - unsigned int i; mutex_lock(&cpufreq_lock); - pr_debug("cpufreq: to %dKHz, relation %d\n", target_freq, relation); - - ret = cpufreq_frequency_table_target(policy, s3c_freq->freq_table, - target_freq, relation, &i); - if (ret != 0) - goto out; - - idx = s3c_freq->freq_table[i].driver_data; + idx = s3c_freq->freq_table[index].driver_data; if (idx == SOURCE_HCLK) to_dvs = 1; @@ -256,24 +237,13 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, goto out; } - freqs.flags = 0; - freqs.old = s3c_freq->is_dvs ? FREQ_DVS - : clk_get_rate(s3c_freq->armclk) / 1000; - /* When leavin dvs mode, always switch the armdiv to the hclk rate * The S3C2416 has stability issues when switching directly to * higher frequencies. */ - freqs.new = (s3c_freq->is_dvs && !to_dvs) + new_freq = (s3c_freq->is_dvs && !to_dvs) ? clk_get_rate(s3c_freq->hclk) / 1000 - : s3c_freq->freq_table[i].frequency; - - pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new); - - if (!to_dvs && freqs.old == freqs.new) - goto out; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + : s3c_freq->freq_table[index].frequency; if (to_dvs) { pr_debug("cpufreq: enter dvs\n"); @@ -282,12 +252,10 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, pr_debug("cpufreq: leave dvs\n"); ret = s3c2416_cpufreq_leave_dvs(s3c_freq, idx); } else { - pr_debug("cpufreq: change armdiv to %dkHz\n", freqs.new); - ret = s3c2416_cpufreq_set_armdiv(s3c_freq, freqs.new); + pr_debug("cpufreq: change armdiv to %dkHz\n", new_freq); + ret = s3c2416_cpufreq_set_armdiv(s3c_freq, new_freq); } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - out: mutex_unlock(&cpufreq_lock); @@ -298,7 +266,7 @@ out: static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) { int count, v, i, found; - struct cpufreq_frequency_table *freq; + struct cpufreq_frequency_table *pos; struct s3c2416_dvfs *dvfs; count = regulator_count_voltages(s3c_freq->vddarm); @@ -307,12 +275,11 @@ static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) return; } - freq = s3c_freq->freq_table; - while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) { - if (freq->frequency == CPUFREQ_ENTRY_INVALID) - continue; + if (!count) + goto out; - dvfs = &s3c2416_dvfs_table[freq->driver_data]; + cpufreq_for_each_valid_entry(pos, s3c_freq->freq_table) { + dvfs = &s3c2416_dvfs_table[pos->driver_data]; found = 0; /* Check only the min-voltage, more is always ok on S3C2416 */ @@ -324,13 +291,12 @@ static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) if (!found) { pr_debug("cpufreq: %dkHz unsupported by regulator\n", - freq->frequency); - freq->frequency = CPUFREQ_ENTRY_INVALID; + pos->frequency); + pos->frequency = CPUFREQ_ENTRY_INVALID; } - - freq++; } +out: /* Guessed */ s3c_freq->regulator_latency = 1 * 1000 * 1000; } @@ -370,7 +336,7 @@ static struct notifier_block s3c2416_cpufreq_reboot_notifier = { static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) { struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; - struct cpufreq_frequency_table *freq; + struct cpufreq_frequency_table *pos; struct clk *msysclk; unsigned long rate; int ret; @@ -459,47 +425,37 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) s3c_freq->regulator_latency = 0; #endif - freq = s3c_freq->freq_table; - while (freq->frequency != CPUFREQ_TABLE_END) { + cpufreq_for_each_entry(pos, s3c_freq->freq_table) { /* special handling for dvs mode */ - if (freq->driver_data == 0) { + if (pos->driver_data == 0) { if (!s3c_freq->hclk) { pr_debug("cpufreq: %dkHz unsupported as it would need unavailable dvs mode\n", - freq->frequency); - freq->frequency = CPUFREQ_ENTRY_INVALID; + pos->frequency); + pos->frequency = CPUFREQ_ENTRY_INVALID; } else { - freq++; continue; } } /* Check for frequencies we can generate */ rate = clk_round_rate(s3c_freq->armdiv, - freq->frequency * 1000); + pos->frequency * 1000); rate /= 1000; - if (rate != freq->frequency) { + if (rate != pos->frequency) { pr_debug("cpufreq: %dkHz unsupported by clock (clk_round_rate return %lu)\n", - freq->frequency, rate); - freq->frequency = CPUFREQ_ENTRY_INVALID; + pos->frequency, rate); + pos->frequency = CPUFREQ_ENTRY_INVALID; } - - freq++; } - policy->cur = clk_get_rate(s3c_freq->armclk) / 1000; - /* Datasheet says PLL stabalisation time must be at least 300us, * so but add some fudge. (reference in LOCKCON0 register description) */ - policy->cpuinfo.transition_latency = (500 * 1000) + - s3c_freq->regulator_latency; - - ret = cpufreq_frequency_table_cpuinfo(policy, s3c_freq->freq_table); + ret = cpufreq_generic_init(policy, s3c_freq->freq_table, + (500 * 1000) + s3c_freq->regulator_latency); if (ret) goto err_freq_table; - cpufreq_frequency_table_get_attr(s3c_freq->freq_table, 0); - register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier); return 0; @@ -518,19 +474,14 @@ err_hclk: return ret; } -static struct freq_attr *s3c2416_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver s3c2416_cpufreq_driver = { - .flags = 0, - .verify = s3c2416_cpufreq_verify_speed, - .target = s3c2416_cpufreq_set_target, + .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, + .verify = cpufreq_generic_frequency_table_verify, + .target_index = s3c2416_cpufreq_set_target, .get = s3c2416_cpufreq_get_speed, .init = s3c2416_cpufreq_driver_init, .name = "s3c2416", - .attr = s3c2416_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int __init s3c2416_cpufreq_init(void) |
