15 #include <linux/kernel.h>
16 #include <linux/types.h>
22 #include <linux/reboot.h>
23 #include <linux/module.h>
33 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
51 #define FREQ_DVS 132333
57 #define FREQ_SLEEP 133333
61 #define SOURCE_ARMDIV 1
63 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
90 static int s3c2416_cpufreq_verify_speed(
struct cpufreq_policy *policy)
100 static unsigned int s3c2416_cpufreq_get_speed(
unsigned int cpu)
114 static int s3c2416_cpufreq_set_armdiv(
struct s3c2416_data *s3c_freq,
122 pr_err(
"cpufreq: Failed to set armdiv rate %dkHz: %d\n",
131 static int s3c2416_cpufreq_enter_dvs(
struct s3c2416_data *s3c_freq,
int idx)
133 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
139 pr_debug(
"cpufreq: already in dvs mode, nothing to do\n");
143 pr_debug(
"cpufreq: switching armclk to hclk (%lukHz)\n",
147 pr_err(
"cpufreq: Failed to switch armclk to hclk: %d\n", ret);
151 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
153 if (s3c_freq->vddarm) {
154 dvfs = &s3c2416_dvfs_table[
idx];
156 pr_debug(
"cpufreq: setting regulator to %d-%d\n",
164 pr_err(
"cpufreq: Failed to set VDDARM: %d\n", ret);
173 static int s3c2416_cpufreq_leave_dvs(
struct s3c2416_data *s3c_freq,
int idx)
175 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
181 pr_debug(
"cpufreq: not in dvs mode, so can't leave\n");
185 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
186 if (s3c_freq->vddarm) {
187 dvfs = &s3c2416_dvfs_table[
idx];
189 pr_debug(
"cpufreq: setting regulator to %d-%d\n",
195 pr_err(
"cpufreq: Failed to set VDDARM: %d\n", ret);
203 pr_debug(
"cpufreq: force armdiv to hclk frequency (%lukHz)\n",
205 ret = s3c2416_cpufreq_set_armdiv(s3c_freq,
208 pr_err(
"cpufreq: Failed to to set the armdiv to %lukHz: %d\n",
214 pr_debug(
"cpufreq: switching armclk parent to armdiv (%lukHz)\n",
219 pr_err(
"cpufreq: Failed to switch armclk clock parent to armdiv: %d\n",
229 static int s3c2416_cpufreq_set_target(
struct cpufreq_policy *policy,
230 unsigned int target_freq,
231 unsigned int relation)
240 pr_debug(
"cpufreq: to %dKHz, relation %d\n", target_freq, relation);
243 target_freq, relation, &i);
254 pr_debug(
"cpufreq: entering dvs mode not allowed\n");
268 freqs.new = (s3c_freq->
is_dvs && !to_dvs)
272 pr_debug(
"cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
274 if (!to_dvs && freqs.old == freqs.new)
281 ret = s3c2416_cpufreq_enter_dvs(s3c_freq, idx);
282 }
else if (s3c_freq->
is_dvs) {
284 ret = s3c2416_cpufreq_leave_dvs(s3c_freq, idx);
286 pr_debug(
"cpufreq: change armdiv to %dkHz\n", freqs.new);
287 ret = s3c2416_cpufreq_set_armdiv(s3c_freq, freqs.new);
298 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
307 pr_err(
"cpufreq: Unable to check supported voltages\n");
316 dvfs = &s3c2416_dvfs_table[freq->
index];
320 for (i = 0; i <
count; i++) {
327 pr_debug(
"cpufreq: %dkHz unsupported by regulator\n",
340 static int s3c2416_cpufreq_reboot_notifier_evt(
struct notifier_block *
this,
358 pr_debug(
"cpufreq: leave dvs on reboot\n");
368 .notifier_call = s3c2416_cpufreq_reboot_notifier_evt,
379 if (policy->
cpu != 0)
383 if (IS_ERR(msysclk)) {
384 ret = PTR_ERR(msysclk);
385 pr_err(
"cpufreq: Unable to obtain msysclk: %d\n", ret);
395 if (rate == 800 * 1000 * 1000) {
396 pr_info(
"cpufreq: msysclk running at %lukHz, using S3C2416 frequency table\n",
399 policy->
cpuinfo.max_freq = 400000;
400 }
else if (rate / 1000 == 534000) {
401 pr_info(
"cpufreq: msysclk running at %lukHz, using S3C2450 frequency table\n",
404 policy->
cpuinfo.max_freq = 534000;
411 pr_err(
"cpufreq: No frequency information for this CPU, msysclk at %lukHz\n",
419 if (IS_ERR(s3c_freq->
armdiv)) {
420 ret = PTR_ERR(s3c_freq->
armdiv);
421 pr_err(
"cpufreq: Unable to obtain ARMDIV: %d\n", ret);
426 if (IS_ERR(s3c_freq->
hclk)) {
427 ret = PTR_ERR(s3c_freq->
hclk);
428 pr_err(
"cpufreq: Unable to obtain HCLK: %d\n", ret);
436 if (rate < 133 * 1000 * 1000) {
437 pr_err(
"cpufreq: HCLK not at 133MHz\n");
444 if (IS_ERR(s3c_freq->
armclk)) {
445 ret = PTR_ERR(s3c_freq->
armclk);
446 pr_err(
"cpufreq: Unable to obtain ARMCLK: %d\n", ret);
450 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
452 if (IS_ERR(s3c_freq->vddarm)) {
453 ret = PTR_ERR(s3c_freq->vddarm);
454 pr_err(
"cpufreq: Failed to obtain VDDARM: %d\n", ret);
458 s3c2416_cpufreq_cfg_regulator(s3c_freq);
466 if (freq->
index == 0) {
467 if (!s3c_freq->
hclk) {
468 pr_debug(
"cpufreq: %dkHz unsupported as it would need unavailable dvs mode\n",
482 pr_debug(
"cpufreq: %dkHz unsupported by clock (clk_round_rate return %lu)\n",
495 policy->
cpuinfo.transition_latency = (500 * 1000) +
509 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
522 static struct freq_attr *s3c2416_cpufreq_attr[] = {
530 .verify = s3c2416_cpufreq_verify_speed,
531 .target = s3c2416_cpufreq_set_target,
532 .get = s3c2416_cpufreq_get_speed,
533 .init = s3c2416_cpufreq_driver_init,
535 .attr = s3c2416_cpufreq_attr,
538 static int __init s3c2416_cpufreq_init(
void)