From: Ziggy Date: Sun, 3 Feb 2013 10:41:15 +0000 (-0500) Subject: Allow resetting of acpu_freq_tbl voltage minimum via vdd_levels sysfs interface X-Git-Url: https://projects.ziggy471.com/git/gitweb.cgi?p=ziggy471-sgs3-jb.git;a=commitdiff;h=6472c97a1c880bebb80342a63736544c4ca6a25f Allow resetting of acpu_freq_tbl voltage minimum via vdd_levels sysfs interface example to reset vmin to 950mV: echo "vmin 950000" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels Signed-off-by: Ziggy --- --- a/arch/arm/mach-msm/acpuclock-8960.c +++ b/arch/arm/mach-msm/acpuclock-8960.c @@ -70,6 +70,7 @@ #define MAX_VDD_SC CONFIG_CPU_FREQ_MAX_VDD_SC /* uV */ #define MIN_VDD_SC CONFIG_CPU_FREQ_MIN_VDD_SC /* uV */ +int VMIN = CONFIG_MSM_VMIN; #define HFPLL_NOMINAL_VDD 1050000 #define HFPLL_LOW_VDD CONFIG_CPU_FREQ_MIN_VDD_SC @@ -129,6 +130,7 @@ struct acpu_level { struct core_speed speed; struct l2_level *l2_level; unsigned int vdd_core; + unsigned int vdd_core_save; }; struct scalable { @@ -476,10 +478,10 @@ static struct acpu_level acpu_freq_tbl_8 { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 900000 }, { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(8), 950000 }, { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(9), 950000 }, - { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(10), 975000 }, - { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 975000 }, - { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(12), 1025000 }, - { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(13), 1025000 }, + { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(10), 975000 }, + { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 975000 }, + { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(12), 1025000 }, + { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(13), 1025000 }, { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(14), 1050000 }, { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1050000 }, { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1075000 }, @@ -1289,9 +1291,13 @@ static const int krait_needs_vmin(void) static void kraitv2_apply_vmin(struct acpu_level *tbl) { - for (; tbl->speed.khz != 0; tbl++) - if (tbl->vdd_core < CONFIG_MSM_VMIN) - tbl->vdd_core = CONFIG_MSM_VMIN; + for (; tbl->speed.khz != 0; tbl++) { + tbl->vdd_core_save = tbl->vdd_core; + if (tbl->vdd_core < VMIN) { + pr_info("%8u: cur-vdd %4d - new-vdd %4d", tbl->speed.khz, tbl->vdd_core, VMIN); + tbl->vdd_core = VMIN; + } + } } #ifdef CONFIG_SEC_L1_DCACHE_PANIC_CHK @@ -1395,13 +1401,14 @@ static struct acpu_level * __init select kraitv2_apply_vmin(acpu_freq_tbl); /* Find the max supported scaling frequency. */ - for (l = acpu_freq_tbl; l->speed.khz != 0; l++) - if (l->use_for_scaling) + for (l = acpu_freq_tbl; l->speed.khz != 0; l++) { + if (l->use_for_scaling) { if (l->speed.khz <= MAX_FREQ_LIMIT) max_acpu_level = l; else l->use_for_scaling = 0; - + } + } BUG_ON(!max_acpu_level); pr_info("Max ACPU freq: %u KHz\n", max_acpu_level->speed.khz); @@ -1467,4 +1474,16 @@ void acpuclk_set_vdd(unsigned int khz, i } mutex_unlock(&driver_lock); } + +void acpuclk_set_vmin(int newvmin) +{ + int i; + + if (newvmin >= MIN_VDD_SC && newvmin <= MAX_VDD_SC) { + VMIN = newvmin; + for (i = 0; acpu_freq_tbl[i].speed.khz; i++) + acpu_freq_tbl[i].vdd_core = acpu_freq_tbl[i].vdd_core_save; + kraitv2_apply_vmin(acpu_freq_tbl); + } +} #endif --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -672,21 +672,28 @@ static ssize_t show_vdd_levels(struct ko } extern void acpuclk_set_vdd(unsigned acpu_khz, int vdd); +extern void acpuclk_set_vmin(int newvmin); static ssize_t store_vdd_levels(struct kobject *a, struct attribute *b, const char *buf, size_t count) { int i = 0, j; int pair[2] = { 0, 0 }; int sign = 0; + int vmin = 0; + if (count < 1) return 0; + if (buf[0] == '-') { sign = -1; i++; - } - else if (buf[0] == '+') { + } else if (buf[0] == '+') { sign = 1; i++; + } else if (buf[0] == 'v' && buf[1] == 'm' && buf[2] == 'i' && buf[3] == 'n') { + vmin = 1; + i+=4; } + for (j = 0; i < count; i++) { char c = buf[i]; if ((c >= '0') && (c <= '9')) { @@ -703,16 +710,20 @@ static ssize_t store_vdd_levels(struct k else break; } + if (sign != 0) { if (pair[0] > 0) acpuclk_set_vdd(0, sign * pair[0]); - } - else { + } else if (vmin == 1) { + if (pair[0] > 0) + acpuclk_set_vmin(pair[0]); + } else { if ((pair[0] > 0) && (pair[1] > 0)) acpuclk_set_vdd((unsigned)pair[0], pair[1]); else return -EINVAL; } + return count; } #endif /* CONFIG_VDD_USERSPACE */