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


file:973135f9cb3a1c8b7c490a8d5fbe28ce1def0407 -> file:8d8eea63f607b8f717c1d618cd7eb4d0c1a61403
--- 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
file:bbde88eedb91db2c78b5d23a1ea63466dea28611 -> file:72e7bbc937bd8ec48f2b19db031db152ecbf631a
--- 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 */