Skip to content

Commit

Permalink
[Add] VDD sysfs testing
Browse files Browse the repository at this point in the history
  • Loading branch information
Napstar-xda committed May 28, 2012
1 parent 1a3f889 commit 4569b45
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 2 deletions.
1 change: 1 addition & 0 deletions kernel/arch/arm/configs/uckernel_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ CONFIG_CPU_FREQ_GOV_INTERACTIVEX=y
CONFIG_CPU_FREQ_GOV_SAVAGEDZEN=y
CONFIG_CPU_FREQ_GOV_SMARTASS2=y
CONFIG_CPU_FREQ_GOV_SMOOTHASS=y
CONFIG_CPU_FREQ_VDD_LEVELS=y
CONFIG_CPU_FREQ_MIN_TICKS=10
CONFIG_CPU_FREQ_SAMPLING_LATENCY_MULTIPLIER=1000
CONFIG_CPU_IDLE=y
Expand Down
94 changes: 92 additions & 2 deletions kernel/arch/arm/mach-omap2/voltage.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,96 @@ static int vp_debug_get(void *data, u64 *val)
return 0;
}


int volt_debug_set(void *data, unsigned long val, int indx)
{
struct omap_vdd_info *vdd = container_of((struct voltagedomain *) data, struct omap_vdd_info, voltdm);
struct omap_volt_data *vdata;
int res = 1;

int i,j;
u64 old_val;
struct device *mpu_dev = omap2_get_mpuss_device();
struct cpufreq_frequency_table *mpu_freq_table = *omap_pm_cpu_get_freq_table();
struct omap_opp *dsp_opp_table = omap_pm_dsp_get_opp_table();
struct omap_opp *temp_opp;

if (!vdd) {
pr_warning("Wrong paramater passed\n");
return -EINVAL;
}

res = omap_vscale_pause(&vdd->voltdm,false);
if(res == 0) {
/*vdata = omap_voltage_get_nom_volt(&vdd->voltdm);*/
vdata = vdd->volt_data;
if (IS_ERR_OR_NULL(vdata))
return -EINVAL;

printk(KERN_ERR "%s: Requested change from %d to/with %lu \n", __func__,vdata[indx].volt_nominal,val);

if(indx != -1)
{
for (i = 0; i < vdd->dev_count; i++) {
opp_set_voltage(vdd->dev_list[i], vdata[indx].volt_nominal, val, true);
}
old_val = vdata[indx].volt_nominal;
vdata[indx].volt_nominal = val;
}
else
{
for (j = 0; j < vdd->volt_data_count; j++) {
for (i = 0; i < vdd->dev_count; i++) {
opp_set_voltage(vdd->dev_list[i], vdata[j].volt_nominal, vdata[j].volt_nominal+val, true);
}
old_val = vdata[j].volt_nominal;
vdata[j].volt_nominal = vdata[j].volt_nominal + val;
}
}
//omap_voltage_scale(&vdd->voltdm);
omap_voltage_reset(&vdd->voltdm);

if(!mpu_dev || !mpu_freq_table)
{
if (mpu_freq_table == NULL)
printk(KERN_ERR "%s: Could not get freq_table\n", __func__);
return -EINVAL;
}

if(indx != -1)
{
i = indx;
temp_opp = opp_find_freq_exact(mpu_dev, mpu_freq_table[i].frequency*1000, true);
if(IS_ERR(temp_opp))
return -EINVAL;
opp_disable(temp_opp);
temp_opp->u_volt = val;
opp_enable(temp_opp);

opp_disable(&dsp_opp_table[i]);
dsp_opp_table[i].u_volt = val;
opp_enable(&dsp_opp_table[i]);
}
else
for (i = 0; mpu_freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
{
temp_opp = opp_find_freq_exact(mpu_dev, mpu_freq_table[i].frequency*1000, true);
if(IS_ERR(temp_opp))
return -EINVAL;
opp_disable(temp_opp);
temp_opp->u_volt = temp_opp->u_volt + val;
opp_enable(temp_opp);

opp_disable(&dsp_opp_table[i]);
dsp_opp_table[i].u_volt = dsp_opp_table[i].u_volt + val;
opp_enable(&dsp_opp_table[i]);
}

omap_vscale_unpause(&vdd->voltdm);
}
return 0;
}

static int vp_debug_set(void *data, u64 val)
{
if (enable_sr_vp_debug) {
Expand Down Expand Up @@ -2578,8 +2668,8 @@ int omap_voltage_scale(struct voltagedomain *voltdm)

opp = opp_find_voltage(vdd->dev_list[i], volt, true);
if (IS_ERR(opp)) {
dev_err(vdd->dev_list[i], "%s: Unable to find OPP for"
"volt%ld\n", __func__, volt);
dev_err(vdd->dev_list[i], "%s: Unable to find OPP for "
"volt %ld\n", __func__, volt);
continue;
}

Expand Down
10 changes: 10 additions & 0 deletions kernel/arch/arm/plat-omap/include/plat/opp.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ struct omap_opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
struct omap_opp *opp_find_voltage(struct device *dev, unsigned long volt,
bool enabled);

struct omap_opp *opp_set_voltage(struct device *dev, unsigned long volt, unsigned long new_volt,
bool enabled);

int opp_set_rate(struct device *dev, unsigned long freq);

unsigned long opp_get_rate(struct device *dev);
Expand Down Expand Up @@ -164,6 +167,13 @@ static inline struct omap_opp *opp_find_voltage(struct device *dev,
return ERR_PTR(-EINVAL);
}

static inline struct omap_opp *opp_set_voltage(struct device *dev,
unsigned long volt,
bool enabled)
{
return ERR_PTR(-EINVAL);
}

static inline int opp_set_rate(struct device *dev, unsigned long freq)
{
return -EINVAL;
Expand Down
1 change: 1 addition & 0 deletions kernel/arch/arm/plat-omap/include/plat/voltage.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ bool omap_vp_clear_transdone(struct voltagedomain *voltdm);
int omap_voltage_calib_reset(struct voltagedomain *voltdm);
int omap_vscale_pause(struct voltagedomain *voltdm, bool trylock);
int omap_vscale_unpause(struct voltagedomain *voltdm);
int volt_debug_set(void *vdd, unsigned long val, int indx);

#ifdef CONFIG_PM
void omap_voltage_init_vc(struct omap_volt_vc_data *setup_vc);
Expand Down
35 changes: 35 additions & 0 deletions kernel/arch/arm/plat-omap/opp.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,41 @@ struct omap_opp *opp_find_voltage(struct device *dev, unsigned long volt,
return opp;
}

/**
* opp_set_voltage() - Modify an exact voltage
* @dev: device pointer associated with the opp type
* @volt: voltage to replace for
* @new_volt: New voltage value
*
* Replaces an exact match in the opp list and returns handle to the matching
* opp if found, else returns ERR_PTR in case of error and should be handled
* using IS_ERR.
*
* Note enabled is a modifier for the search. If enabled is true then the
* matching opp must be enabled. If enabled is false then the matching opp
* must be disabled.
*/
struct omap_opp *opp_set_voltage(struct device *dev, unsigned long volt, unsigned long new_volt,
bool enabled)
{
struct device_opp *dev_opp;
struct omap_opp *temp_opp, *opp = ERR_PTR(-ENODEV);

dev_opp = find_device_opp(dev);
if (IS_ERR(dev_opp))
return opp;

list_for_each_entry(temp_opp, &dev_opp->opp_list, node) {
if (!(temp_opp->enabled ^ enabled) &&
temp_opp->u_volt == volt) {
opp = temp_opp;
break;
}
}
opp->u_volt = new_volt;
return opp;
}

/**
* opp_set_rate() - Change the operating frequency of the device
* @dev: device pointer associated with the opp type
Expand Down
7 changes: 7 additions & 0 deletions kernel/drivers/cpufreq/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -418,4 +418,11 @@ config CPU_FREQ_GOV_HOTPLUG

If in doubt, say N.

config CPU_FREQ_VDD_LEVELS
bool "CPU Vdd levels sysfs interface"
depends on CPU_FREQ_STAT
default n
help
CPU Vdd levels sysfs interface

endif # CPU_FREQ
166 changes: 166 additions & 0 deletions kernel/drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#include <linux/cpu.h>
#include <linux/completion.h>
#include <linux/mutex.h>
#include <plat/opp.h>
#include <plat/voltage.h>
#include <plat/omap-pm.h>
#include <plat/omap_device.h>
#include <plat/common.h>

#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
"cpufreq-core", msg)
Expand Down Expand Up @@ -691,6 +696,157 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
}


#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)
{
int len = 0, i;
unsigned long *vdd = -1;
unsigned long *temp_vdd = -1;
char *voltdm_name = "mpu";
struct device *mpu_dev = omap2_get_mpuss_device();
struct cpufreq_frequency_table *mpu_freq_table = *omap_pm_cpu_get_freq_table();
struct omap_opp *temp_opp;
struct voltagedomain *mpu_voltdm;
struct omap_volt_data *mpu_voltdata;

if(!mpu_dev || !mpu_freq_table)
{
if (mpu_freq_table == NULL)
printk(KERN_ERR "%s: Could not get freq_table\n", __func__);
return -EINVAL;
}

if (buf)
{
mpu_voltdm = omap_voltage_domain_get(voltdm_name);
for (i = 0; mpu_freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
{
temp_opp = opp_find_freq_exact(mpu_dev, mpu_freq_table[i].frequency*1000, true);
if(IS_ERR(temp_opp))
return -EINVAL;
temp_vdd = opp_get_voltage(temp_opp);
mpu_voltdata = omap_voltage_get_voltdata(mpu_voltdm, temp_vdd);
vdd = mpu_voltdata->volt_nominal;
len += sprintf(buf + len, "%lu: %lu\n", mpu_freq_table[i].frequency/1000, vdd);
}

}
return len;
}

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 len = 0, i = 0;
unsigned long *vdd = -1;
unsigned long *temp_vdd = -1;
char *voltdm_name = "mpu";
struct device *mpu_dev = omap2_get_mpuss_device();
struct cpufreq_frequency_table *mpu_freq_table = *omap_pm_cpu_get_freq_table();
struct omap_opp *temp_opp;
struct voltagedomain *mpu_voltdm;
struct omap_volt_data *mpu_voltdata;

printk(KERN_ERR "%s: Buf:\t%s\n", __func__,buf);

if(!mpu_dev || !mpu_freq_table)
{
if (mpu_freq_table == NULL)
printk(KERN_ERR "%s: Could not get freq_table\n", __func__);
return -EINVAL;
}

if (buf)
{
int j;
int pair[2] = { 0, 0 };
int sign = 0;
unsigned int return_Freq = 0;
unsigned long return_Vdd = 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)
{
return_Freq = 0;
return_Vdd = sign * pair[0];
}
}
else
{
if ((pair[0] > 0) && (pair[1] > 0))
{
return_Freq = (unsigned)pair[0];
return_Vdd = pair[1];
}
else
{
printk(KERN_ERR "%s: Do not provide 0 as input\nInput entries:\t%d,\t%d\n and input buffer:%s", __func__,pair[0],pair[1],buf);
return -EINVAL;
}
}

mpu_voltdm = omap_voltage_domain_get(voltdm_name);

printk(KERN_ERR "%s: return_Freq:%d\treturn_Vdd:%lu\n", __func__,return_Freq,return_Vdd);

for (i = 0; mpu_freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
{
if(return_Freq != 0 && return_Freq == mpu_freq_table[i].frequency)
volt_debug_set(mpu_voltdm, return_Vdd, i);
else if(return_Freq == 0)
{
volt_debug_set(mpu_voltdm, return_Vdd, -1);
break;
}
else
continue;
}
}
return count;
}

#endif


cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400);
cpufreq_freq_attr_ro(cpuinfo_min_freq);
cpufreq_freq_attr_ro(cpuinfo_max_freq);
Expand All @@ -707,6 +863,11 @@ cpufreq_freq_attr_rw(scaling_governor);
cpufreq_freq_attr_rw(scaling_setspeed);
cpufreq_freq_attr_rw(boost_cpufreq);

#ifdef CONFIG_CPU_FREQ_VDD_LEVELS
cpufreq_freq_attr_rw(vdd_levels);
#endif


static struct attribute *default_attrs[] = {
&cpuinfo_min_freq.attr,
&cpuinfo_max_freq.attr,
Expand All @@ -720,6 +881,11 @@ static struct attribute *default_attrs[] = {
&scaling_available_governors.attr,
&scaling_setspeed.attr,
&boost_cpufreq.attr,

#ifdef CONFIG_CPU_FREQ_VDD_LEVELS
&vdd_levels.attr,
#endif

NULL
};

Expand Down

0 comments on commit 4569b45

Please sign in to comment.