From fa22f81fb15a65cba57a66a55d7a09bfcf853ed7 Mon Sep 17 00:00:00 2001 From: Andrew Dodd Date: Fri, 29 Jun 2012 15:29:06 -0400 Subject: [PATCH] cpufreq: Make voltage control compatible with ASV The old approach used a fixed voltage table not compatible with ASV. New approach uses ASV values by default. This approach is based on gokhanmoral's SiyahKernel UV implementation for I9100 ICS. Also add min/max voltage enforcement. Signed-off-by: Andrew Dodd --- arch/arm/mach-s5pv210/cpu-freq_c110b.c | 39 +++++++++++++++++++++----- drivers/cpufreq/cpufreq.c | 28 ++---------------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/arch/arm/mach-s5pv210/cpu-freq_c110b.c b/arch/arm/mach-s5pv210/cpu-freq_c110b.c index 8afa36b5..ad980099 100755 --- a/arch/arm/mach-s5pv210/cpu-freq_c110b.c +++ b/arch/arm/mach-s5pv210/cpu-freq_c110b.c @@ -50,8 +50,8 @@ static unsigned int mpll_freq; /* in MHz */ static unsigned int apll_freq_max; /* in MHz */ static DEFINE_MUTEX(set_freq_lock); -/* UV */ -extern int exp_UV_mV[5]; +#define CPU_UV_MV_MAX 1350000 +#define CPU_UV_MV_MIN 800000 /* frequency */ static struct cpufreq_frequency_table freq_table[] = { @@ -509,7 +509,7 @@ static int s5pv210_cpufreq_target(struct cpufreq_policy *policy, if (s3c_freqs.freqs.new == s3c_freqs.freqs.old && !first_run) goto out; - arm_volt = exp_UV_mV[index]; //dvs_conf[index].arm_volt; + arm_volt = dvs_conf[index].arm_volt; int_volt = dvs_conf[index].int_volt; /* New clock information update */ @@ -692,8 +692,7 @@ static int s5pv210_cpufreq_target(struct cpufreq_policy *policy, memcpy(&s3c_freqs.old, &s3c_freqs.new, sizeof(struct s3c_freq)); cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, KERN_INFO, "cpufreq: Performance changed[L%d]\n", index); -// previous_arm_volt = dvs_conf[index].arm_volt; - previous_arm_volt = exp_UV_mV[index]; + previous_arm_volt = dvs_conf[index].arm_volt; if (first_run) first_run = false; @@ -736,7 +735,7 @@ static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy) memcpy(&s3c_freqs.old, &clk_info[level], sizeof(struct s3c_freq)); - previous_arm_volt = exp_UV_mV[level]; //dvs_conf[level].arm_volt; + previous_arm_volt = dvs_conf[level].arm_volt; return ret; } @@ -804,7 +803,7 @@ static int __init s5pv210_cpufreq_driver_init(struct cpufreq_policy *policy) memcpy(&s3c_freqs.old, &clk_info[level], sizeof(struct s3c_freq)); - previous_arm_volt = exp_UV_mV[level]; //dvs_conf[level].arm_volt; + previous_arm_volt = dvs_conf[level].arm_volt; #ifdef CONFIG_DVFS_LIMIT for(i = 0; i < DVFS_LOCK_TOKEN_NUM; i++) @@ -914,3 +913,29 @@ static int __init s5pv210_cpufreq_init(void) } late_initcall(s5pv210_cpufreq_init); + +/* sysfs interface for UV control */ +ssize_t show_UV_mV_table(struct cpufreq_policy *policy, char *buf) { + return sprintf(buf, "1200mhz: %lu mV\n800mhz: %lu mV\n400mhz: %lu mV\n200mhz: %lu mV\n100mhz: %lu mV\n", dvs_conf[0].arm_volt/1000, dvs_conf[1].arm_volt/1000, dvs_conf[2].arm_volt/1000, dvs_conf[3].arm_volt/1000, dvs_conf[4].arm_volt/1000); +} + +ssize_t store_UV_mV_table(struct cpufreq_policy *policy, + const char *buf, size_t count) { + unsigned int ret = -EINVAL; + int u[5]; + int i = 0; + ret = sscanf(buf, "%d %d %d %d %d", &u[0], &u[1], &u[2], &u[3], &u[4]); + if(ret != 5) { + return -EINVAL; + } + else { + for( i = 0; i < 5; i++ ) { + if (u[i] > CPU_UV_MV_MAX / 1000) u[i] = CPU_UV_MV_MAX / 1000; + else if (u[i] < CPU_UV_MV_MIN / 1000) u[i] = CPU_UV_MV_MIN / 1000; + } + for( i = 0; i < 5; i++ ) { + dvs_conf[i].arm_volt = u[i] * 1000; + } + return count; + } +} diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 266f42e4..8f1804d5 100755 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -32,9 +32,6 @@ #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \ "cpufreq-core", msg) -/* UV */ -int exp_UV_mV[5] = { 1300000, 1200000, 1050000, 950000, 950000 }; - /** * The "cpufreq driver" - the arch- or hardware-dependent low * level driver of CPUFreq support, and its spinlock. This lock @@ -651,28 +648,9 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) } /* sysfs interface for UV control */ -static ssize_t show_UV_mV_table(struct cpufreq_policy *policy, char *buf) { - - return sprintf(buf, "1200mhz: %d mV\n800mhz: %d mV\n400mhz: %d mV\n200mhz: %d mV\n100mhz: %d mV\n", exp_UV_mV[0]/1000, exp_UV_mV[1]/1000, exp_UV_mV[2]/1000, exp_UV_mV[3]/1000, exp_UV_mV[4]/1000); - -} - -static ssize_t store_UV_mV_table(struct cpufreq_policy *policy, - const char *buf, size_t count) { - - unsigned int ret = -EINVAL; - int i = 0; - ret = sscanf(buf, "%d %d %d %d %d", &exp_UV_mV[0], &exp_UV_mV[1], &exp_UV_mV[2], &exp_UV_mV[3], &exp_UV_mV[4]); - if(ret != 5) { - return -EINVAL; - } - else - for( i = 0; i < 5; i++ ) - { - exp_UV_mV[i] *= 1000; - } - return count; -} +extern ssize_t show_UV_mV_table(struct cpufreq_policy *policy, char *buf); +extern ssize_t store_UV_mV_table(struct cpufreq_policy *policy, + const char *buf, size_t count); /** * show_scaling_driver - show the current cpufreq HW/BIOS limitation