Added sysfs interface for undervolting based on information from here:

http://forum.xda-developers.com/showthread.php?t=821372

See the thread for information on how to use it.
This commit is contained in:
Jon Benson 2010-11-17 18:20:25 +11:00
parent 1d971023be
commit 19867bdf03
5 changed files with 128 additions and 3 deletions

View File

@ -29,6 +29,9 @@
#include "acpuclock.h"
#include "proc_comm.h"
#include "clock.h"
#ifdef CONFIG_CPU_FREQ_VDD_LEVELS
#include "board-htcleo.h"
#endif
#if 0
#define DEBUG(x...) pr_info(x)
@ -693,3 +696,41 @@ void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
clk_set_rate(drv_state.clk_ebi1, drv_state.current_speed->axiclk_khz * 1000);
#endif
}
#ifdef CONFIG_CPU_FREQ_VDD_LEVELS
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].acpu_khz; i++)
{
if (freq_table[i].frequency != CPUFREQ_ENTRY_INVALID)
len += sprintf(buf + len, "%8u: %4d\n", acpu_freq_tbl[i].acpu_khz, acpu_freq_tbl[i].vdd);
}
mutex_unlock(&drv_state.lock);
}
return len;
}
void acpuclk_set_vdd(unsigned acpu_khz, int vdd)
{
int i;
vdd = vdd / 25 * 25; //! regulator only accepts multiples of 25 (mV)
mutex_lock(&drv_state.lock);
for (i = 0; acpu_freq_tbl[i].acpu_khz; i++)
{
if (freq_table[i].frequency != CPUFREQ_ENTRY_INVALID)
{
if (acpu_khz == 0)
acpu_freq_tbl[i].vdd = min(max((acpu_freq_tbl[i].vdd + vdd), HTCLEO_TPS65023_MIN_UV_MV), HTCLEO_TPS65023_MAX_UV_MV);
else if (acpu_freq_tbl[i].acpu_khz == acpu_khz)
acpu_freq_tbl[i].vdd = min(max(vdd, HTCLEO_TPS65023_MIN_UV_MV), HTCLEO_TPS65023_MAX_UV_MV);
}
}
mutex_unlock(&drv_state.lock);
}
#endif

View File

@ -110,8 +110,8 @@ static struct regulator_init_data tps65023_data[5] =
.constraints =
{
.name = "dcdc1", /* VREG_MSMC2_1V29 */
.min_uV = 800000,
.max_uV = 1350000,
.min_uV = HTCLEO_TPS65023_MIN_UV_MV * 1000,
.max_uV = HTCLEO_TPS65023_MAX_UV_MV * 1000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
},
.consumer_supplies = tps65023_dcdc1_supplies,

View File

@ -168,7 +168,9 @@
#define HTCLEO_LCD_HSYNC (137)
#define HTCLEO_LCD_DE (138)
/* Voltage driver */
#define HTCLEO_TPS65023_MIN_UV_MV (800)
#define HTCLEO_TPS65023_MAX_UV_MV (1350)
int htcleo_pm_set_vreg(int enable, unsigned id);
int __init htcleo_init_panel(void);

View File

@ -205,4 +205,12 @@ config CPU_FREQ_GOV_CONSERVATIVE
If in doubt, say N.
config CPU_FREQ_VDD_LEVELS
bool "CPU Vdd levels sysfs interface"
depends on CPU_FREQ_STAT
depends on ARCH_QSD8X50
default n
help
CPU Vdd levels sysfs interface
endif # CPU_FREQ

View File

@ -647,6 +647,74 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
return policy->governor->show_setspeed(policy, buf);
}
#ifdef CONFIG_CPU_FREQ_VDD_LEVELS
extern ssize_t acpuclk_get_vdd_levels_str(char *buf);
static ssize_t show_vdd_levels(struct cpufreq_policy *policy, char *buf)
{
return acpuclk_get_vdd_levels_str(buf);
}
extern void acpuclk_set_vdd(unsigned acpu_khz, int vdd);
static ssize_t store_vdd_levels(struct cpufreq_policy *policy, 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
#define define_one_ro(_name) \
static struct freq_attr _name = \
__ATTR(_name, 0444, show_##_name, NULL)
@ -672,6 +740,9 @@ define_one_rw(scaling_min_freq);
define_one_rw(scaling_max_freq);
define_one_rw(scaling_governor);
define_one_rw(scaling_setspeed);
#ifdef CONFIG_CPU_FREQ_VDD_LEVELS
define_one_rw(vdd_levels);
#endif
static struct attribute *default_attrs[] = {
&cpuinfo_min_freq.attr,
@ -685,6 +756,9 @@ static struct attribute *default_attrs[] = {
&scaling_driver.attr,
&scaling_available_governors.attr,
&scaling_setspeed.attr,
#ifdef CONFIG_CPU_FREQ_VDD_LEVELS
&vdd_levels.attr,
#endif
NULL
};