Skip to content

Commit

Permalink
Add Voltage Control (OC/Uv)
Browse files Browse the repository at this point in the history
Signed-off-by: Javier Sayago <admin@lonasdigital.com>
  • Loading branch information
javilonas committed Jun 4, 2015
1 parent 8f78fbf commit 4a4075b
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/arm/configs/apq8084_sec_defconfig
Expand Up @@ -871,6 +871,7 @@ CONFIG_DEFAULT_TCP_CONG="westwood"

CONFIG_FORCE_FAST_CHARGE=y
CONFIG_SIMPLE_GPU_ALGORITHM=y
CONFIG_CPU_VOLTAGE_CONTROL=y

#
# IO Schedulers
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/mach-msm/Kconfig
Expand Up @@ -982,6 +982,12 @@ config FORCE_FAST_CHARGE
are detected as USB to charge as AC (1A/h) or to set
custom charging currents for AC and USB.

config CPU_VOLTAGE_CONTROL
bool "Userspace CPU Voltage Control"
default y
help
This enables userspace CPU Voltage Control.

config MSM_AVS_HW
bool "Enable Adaptive Voltage Scaling (AVS)"
default n
Expand Down
75 changes: 75 additions & 0 deletions drivers/clk/qcom/clock-krait-8974.c
Expand Up @@ -22,6 +22,9 @@
#include <linux/regulator/rpm-smd-regulator.h>
#include <linux/of.h>
#include <linux/cpumask.h>
#ifdef CONFIG_CPU_VOLTAGE_CONTROL
#include <linux/cpufreq.h>
#endif
#include <linux/clk/msm-clk-provider.h>
#include <linux/clk/msm-clk.h>
#include <linux/clk/msm-clock-generic.h>
Expand Down Expand Up @@ -702,6 +705,78 @@ static void krait_update_uv(int *uv, int num, int boost_uv)
}
}

#ifdef CONFIG_CPU_VOLTAGE_CONTROL

#define CPU_VDD_MIN 600
#define CPU_VDD_MAX 1800

extern bool is_used_by_scaling(unsigned int freq);

ssize_t show_UV_mV_table(struct cpufreq_policy *policy, char *buf)
{
int i, freq, len = 0;
/* use only master core 0 */
int num_levels = cpu_clk[0]->vdd_class->num_levels;

/* sanity checks */
if (num_levels < 0)
return -EINVAL;

if (!buf)
return -EINVAL;

/* format UV_mv table */
for (i = 0; i < num_levels; i++) {
/* show only those used in scaling */
if (!is_used_by_scaling(freq = cpu_clk[0]->fmax[i] / 1000))
continue;

len += sprintf(buf + len, "%dmhz: %u mV\n", freq / 1000,
cpu_clk[0]->vdd_class->vdd_uv[i] / 1000);
}
return len;
}

ssize_t store_UV_mV_table(struct cpufreq_policy *policy, char *buf,
size_t count)
{
int i, j;
int ret = 0;
unsigned int val;
char size_cur[8];
/* use only master core 0 */
int num_levels = cpu_clk[0]->vdd_class->num_levels;

/* sanity checks */
if (num_levels < 0)
return -1;

for (i = 0; i < num_levels; i++) {
if (!is_used_by_scaling(cpu_clk[0]->fmax[i] / 1000))
continue;

ret = sscanf(buf, "%u", &val);
if (!ret)
return -EINVAL;

/* bounds check */
val = min( max((unsigned int)val, (unsigned int)CPU_VDD_MIN),
(unsigned int)CPU_VDD_MAX);

/* apply it to all available cores */
for (j = 0; j < NR_CPUS; j++)
cpu_clk[j]->vdd_class->vdd_uv[i] = val * 1000;

/* Non-standard sysfs interface: advance buf */
ret = sscanf(buf, "%s", size_cur);
buf += strlen(size_cur) + 1;
}
pr_warn("faux123: user voltage table modified!\n");

return count;
}
#endif

static char table_name[] = "qcom,speedXX-pvsXX-bin-vXX";
module_param_string(table_name, table_name, sizeof(table_name), S_IRUGO);
static unsigned int pvs_config_ver;
Expand Down
13 changes: 13 additions & 0 deletions drivers/cpufreq/cpufreq.c
Expand Up @@ -627,6 +627,12 @@ 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_CONTROL
extern ssize_t show_UV_mV_table(struct cpufreq_policy *policy, char *buf);
extern ssize_t store_UV_mV_table(struct cpufreq_policy *policy,
const char *buf, size_t 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 @@ -640,6 +646,10 @@ cpufreq_freq_attr_ro(affected_cpus);
cpufreq_freq_attr_ro(cpu_utilization);
cpufreq_freq_attr_ro(cpu_load);
cpufreq_freq_attr_rw(scaling_min_freq);
#ifdef CONFIG_CPU_VOLTAGE_CONTROL
cpufreq_freq_attr_rw(UV_mV_table);
#endif

cpufreq_freq_attr_rw(scaling_max_freq);
cpufreq_freq_attr_rw(scaling_governor);
cpufreq_freq_attr_rw(scaling_setspeed);
Expand All @@ -658,6 +668,9 @@ static struct attribute *default_attrs[] = {
&scaling_driver.attr,
&scaling_available_governors.attr,
&scaling_setspeed.attr,
#ifdef CONFIG_CPU_VOLTAGE_CONTROL
&UV_mV_table.attr,
#endif
NULL
};

Expand Down
34 changes: 34 additions & 0 deletions drivers/cpufreq/qcom-cpufreq.c
Expand Up @@ -35,6 +35,10 @@
#include <trace/events/power.h>
#include <mach/msm_bus.h>

#ifdef CONFIG_CPU_VOLTAGE_CONTROL
static struct cpufreq_frequency_table *dts_freq_table;
#endif

#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
Expand Down Expand Up @@ -595,6 +599,20 @@ static int cpufreq_parse_dt(struct device *dev)
freq_table[i].driver_data = i;
freq_table[i].frequency = CPUFREQ_TABLE_END;

#ifdef CONFIG_CPU_VOLTAGE_CONTROL
dts_freq_table =
devm_kzalloc(dev, (nf + 1) *
sizeof(struct cpufreq_frequency_table),
GFP_KERNEL);

if (!dts_freq_table)
return -ENOMEM;

for (i = 0, j = 0; i < nf; i++, j += 3)
dts_freq_table[i].frequency = data[j];
dts_freq_table[i].frequency = CPUFREQ_TABLE_END;
#endif

if (ports)
devm_kfree(dev, ports);

Expand All @@ -603,6 +621,22 @@ static int cpufreq_parse_dt(struct device *dev)
return 0;
}

#ifdef CONFIG_CPU_VOLTAGE_CONTROL
bool is_used_by_scaling(unsigned int freq)
{
unsigned int i, cpu_freq;

for (i = 0; dts_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
cpu_freq = dts_freq_table[i].frequency;
if (cpu_freq == CPUFREQ_ENTRY_INVALID)
continue;
if (freq == cpu_freq)
return true;
}
return -EINVAL;
}
#endif

#ifdef CONFIG_DEBUG_FS
static int msm_cpufreq_show(struct seq_file *m, void *unused)
{
Expand Down

0 comments on commit 4a4075b

Please sign in to comment.