[HTC Sensation] faux123:
I am in a good mood for some reason.

Here's the global UV patch if needed:

From 24db78877020ed2712847272724dca12d0d9dd2a Mon Sep 17 00:00:00 2001
From: faux123 <reioux@gmail.com>
Date: Mon, 19 Mar 2012 21:33:41 -0700
Subject: [PATCH] board/acpuclock: add global CPU voltage table for adjustment

---
arch/arm/mach-msm/Kconfig | 4 ++
arch/arm/mach-msm/acpuclock-8x60.c | 46 +++++++++++++++++++
drivers/cpufreq/cpufreq.c | 85 ++++++++++++++++++++++++++++++++++++
3 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index d4c15d8..c37b7e6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1494,6 +1494,10 @@ config MSM_DALRPC_TEST
help
Exercises DAL RPC calls to QDSP6.

+config CPU_VOLTAGE_TABLE
+	bool "Enable CPU Voltage Table via sysfs for adjustements"
+	default n
+
if CPU_FREQ_MSM

config MSM_CPU_FREQ_SET_MIN_MAX
diff --git a/arch/arm/mach-msm/acpuclock-8x60.c b/arch/arm/mach-msm/acpuclock-8x60.c
index f5855c1..3d2d185 100644
--- a/arch/arm/mach-msm/acpuclock-8x60.c
+++ b/arch/arm/mach-msm/acpuclock-8x60.c
@@ -46,6 +46,7 @@
#define L_VAL_SCPLL_CAL_MAX	0x1C /* = 1512 MHz with 27MHz source */

#define MAX_VDD_SC	1250000 /* uV */
+#define MIN_VDD_SC	800000 /* uV */
#define MAX_VDD_MEM	1250000 /* uV */
#define MAX_VDD_DIG	1200000 /* uV */
#define MAX_AXI	310500 /* KHz */
@@ -680,6 +681,51 @@ unsigned int get_max_cpu_freq(void)
}
#endif

+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+
+ssize_t acpuclk_get_vdd_levels_str(char *buf) {
+
+	int i, len = 0;
+
+	if (buf) {
+	mutex_lock(&drv_state.lock);
+
+	for (i = 0; acpu_freq_tbl[i].acpuclk_khz; i++) {
+	/* updated to use uv required by 8x60 architecture - faux123 */
+	len += sprintf(buf + len, "%8u: %8d\n", acpu_freq_tbl[i].acpuclk_khz, acpu_freq_tbl[i].vdd_sc );
+	}
+
+	mutex_unlock(&drv_state.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;
+//	int vdd_uv;
+
+//	vdd_uv = vdd_mv * 1000;
+
+	mutex_lock(&drv_state.lock);
+
+	for (i = 0; acpu_freq_tbl[i].acpuclk_khz; i++) {
+	if (khz == 0)
+	new_vdd_uv = min(max((acpu_freq_tbl[i].vdd_sc + vdd_uv), (unsigned int)MIN_VDD_SC), (unsigned int)MAX_VDD_SC);
+	else if ( acpu_freq_tbl[i].acpuclk_khz == khz)
+	new_vdd_uv = min(max((unsigned int)vdd_uv, (unsigned int)MIN_VDD_SC), (unsigned int)MAX_VDD_SC);
+	else
+	continue;
+
+	acpu_freq_tbl[i].vdd_sc = new_vdd_uv;
+	}
+
+	mutex_unlock(&drv_state.lock);
+}
+#endif	/* CONFIG_CPU_VOTALGE_TABLE */
+
static void __init scpll_init(int sc_pll)
{
uint32_t regval;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 124da3b..2ea2d4e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -575,6 +575,68 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
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);
@@ -590,6 +652,10 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
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,
&cpuinfo_max_freq.attr,
@@ -605,6 +671,18 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
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);

@@ -1909,6 +1987,9 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
static int __init cpufreq_core_init(void)
{
int cpu;
+#ifdef CONFIG_CPU_VOLTAGE_TABLE
+	int rc;
+#endif	/* CONFIG_CPU_VOLTAGE_TABLE */

for_each_possible_cpu(cpu) {
per_cpu(cpufreq_policy_cpu, cpu) = -1;
@@ -1920,6 +2001,10 @@ static int __init cpufreq_core_init(void)
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;
}
core_initcall(cpufreq_core_init);
--
1.7.5.4