Voltage Control via sysfs

file:2c433d393ddc09d0472dd9680800a4ff7055f8af -> file:ad009f54a47b814a3c457ee9cbe9b493ea148b13
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1753,6 +1753,12 @@ config MSM_CPU_FREQ_MIN
endif # CPU_FREQ_MSM
+config CPU_VOLTAGE_TABLE
+ bool "Enable CPU Voltage Table via sysfs for adjustements"
+ default n
+ help
+ Krait User Votlage Control
+
config MSM_AVS_HW
bool "Enable Adaptive Voltage Scaling (AVS)"
default n
file:44e48d89efc3362465b41f0c2baeaa42280adb6e -> file:f13cf98d10cce44d26f660a33696b5d71191ba75
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -936,6 +936,54 @@ static void __init bus_init(const struct
dev_err(drv.dev, "initial bandwidth req failed (%d)\n", ret);
}
+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+
+#define HFPLL_MIN_VDD 600000
+#define HFPLL_MAX_VDD 1450000
+
+ssize_t acpuclk_get_vdd_levels_str(char *buf) {
+
+ int i, len = 0;
+
+ if (buf) {
+ mutex_lock(&driver_lock);
+
+ for (i = 0; drv.acpu_freq_tbl[i].speed.khz; i++) {
+ /* updated to use uv required by 8x60 architecture - faux123 */
+ len += sprintf(buf + len, "%8lu: %8d\n", drv.acpu_freq_tbl[i].speed.khz,
+ drv.acpu_freq_tbl[i].vdd_core );
+ }
+
+ mutex_unlock(&driver_lock);
+ }
+ return len;
+}
+
+/* updated to use uv required by 8x60 architecture - faux123 */
+void acpuclk_set_vdd(unsigned int khz, int vdd_uv) {
+
+ int i;
+ unsigned int new_vdd_uv;
+
+ mutex_lock(&driver_lock);
+
+ for (i = 0; drv.acpu_freq_tbl[i].speed.khz; i++) {
+ if (khz == 0)
+ new_vdd_uv = min(max((unsigned int)(drv.acpu_freq_tbl[i].vdd_core + vdd_uv),
+ (unsigned int)HFPLL_MIN_VDD), (unsigned int)HFPLL_MAX_VDD);
+ else if ( drv.acpu_freq_tbl[i].speed.khz == khz)
+ new_vdd_uv = min(max((unsigned int)vdd_uv,
+ (unsigned int)HFPLL_MIN_VDD), (unsigned int)HFPLL_MAX_VDD);
+ else
+ continue;
+
+ drv.acpu_freq_tbl[i].vdd_core = new_vdd_uv;
+ }
+ pr_warn("faux123: user voltage table modified!\n");
+ mutex_unlock(&driver_lock);
+}
+#endif /* CONFIG_CPU_VOTALGE_TABLE */
+
#ifdef CONFIG_CPU_FREQ_MSM
static struct cpufreq_frequency_table freq_table[NR_CPUS][35];
extern int console_batt_stat;
file:5d233066b788071636be7efeb775ecaf40c04add -> file:11e953fc813a300980a378349a4b96032b98b860
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -619,6 +619,68 @@ static ssize_t show_bios_limit(struct cp
return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
}
+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+
+extern ssize_t acpuclk_get_vdd_levels_str(char *buf);
+extern void acpuclk_set_vdd(unsigned acpu_khz, int vdd);
+
+static ssize_t show_vdd_levels(struct kobject *a, struct attribute *b, char *buf) {
+ return acpuclk_get_vdd_levels_str(buf);
+}
+
+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;
+
+ if (count < 1)
+ return 0;
+
+ if (buf[0] == '-') {
+ sign = -1;
+ i++;
+ }
+ else if (buf[0] == '+') {
+ sign = 1;
+ i++;
+ }
+
+ for (j = 0; i < count; i++) {
+
+ char c = buf[i];
+
+ if ((c >= '0') && (c <= '9')) {
+ pair[j] *= 10;
+ pair[j] += (c - '0');
+ }
+ else if ((c == ' ') || (c == '\t')) {
+ if (pair[j] != 0) {
+ j++;
+
+ if ((sign != 0) || (j > 1))
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ if (sign != 0) {
+ if (pair[0] > 0)
+ acpuclk_set_vdd(0, sign * 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_CPU_VOLTAGE_TABLE */
+
cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400);
cpufreq_freq_attr_ro(cpuinfo_min_freq);
cpufreq_freq_attr_ro(cpuinfo_max_freq);
@@ -634,6 +696,9 @@ cpufreq_freq_attr_rw(scaling_min_freq);
cpufreq_freq_attr_rw(scaling_max_freq);
cpufreq_freq_attr_rw(scaling_governor);
cpufreq_freq_attr_rw(scaling_setspeed);
+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+define_one_global_rw(vdd_levels);
+#endif
static struct attribute *default_attrs[] = {
&cpuinfo_min_freq.attr,
@@ -651,6 +716,18 @@ static struct attribute *default_attrs[]
NULL
};
+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+static struct attribute *vddtbl_attrs[] = {
+ &vdd_levels.attr,
+ NULL
+};
+
+static struct attribute_group vddtbl_attr_group = {
+ .attrs = vddtbl_attrs,
+ .name = "vdd_table",
+};
+#endif /* CONFIG_CPU_VOLTAGE_TABLE */
+
struct kobject *cpufreq_global_kobject;
EXPORT_SYMBOL(cpufreq_global_kobject);
@@ -2009,6 +2086,9 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_dri
static int __init cpufreq_core_init(void)
{
int cpu;
+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+ int rc;
+#endif /* CONFIG_CPU_VOLTAGE_TABLE */
if (cpufreq_disabled())
return -ENODEV;
@@ -2021,6 +2101,9 @@ static int __init cpufreq_core_init(void
cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
BUG_ON(!cpufreq_global_kobject);
register_syscore_ops(&cpufreq_syscore_ops);
+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+ rc = sysfs_create_group(cpufreq_global_kobject, &vddtbl_attr_group);
+#endif /* CONFIG_CPU_VOLTAGE_TABLE */
return 0;
}