[RFC PATCH] cpufreq: cpufreq-cpu0: account for regulator step sizeaccuracy

From: Nishanth Menon
Date: Thu Jun 20 2013 - 17:37:30 EST


Generic regulator consumers such as cpufreq-cpu0 are not aware
of the characteristics of regulator used to supply. For example:
consumerX requests for voltage min_uV = 500mV, max_uV = 500mV
On a regulator which has a step size of 10mV, this can be exactly
achieved.

However, on a regulator which is non-exact divider step size (example
12.66mV step size), the closest achievable would be 506.4.
regulator_set_voltage_tol does not work out either as <500mV is not an
acceptable operational voltage.

Account for step size accuracy when exact voltage requests are send for
step based regulators.

Signed-off-by: Nishanth Menon <nm@xxxxxx>
---
drivers/cpufreq/cpufreq-cpu0.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index ad1fde2..707565c 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -28,6 +28,7 @@ static struct device *cpu_dev;
static struct clk *cpu_clk;
static struct regulator *cpu_reg;
static struct cpufreq_frequency_table *freq_table;
+static int cpu_reg_step_size;

static int cpu0_verify_speed(struct cpufreq_policy *policy)
{
@@ -91,7 +92,12 @@ static int cpu0_set_target(struct cpufreq_policy *policy,

/* scaling up? scale voltage before frequency */
if (cpu_reg && freqs.new > freqs.old) {
- ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
+ if (tol)
+ ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
+ else
+ ret = regulator_set_voltage(cpu_reg, volt,
+ volt + cpu_reg_step_size);
+
if (ret) {
pr_err("failed to scale voltage up: %d\n", ret);
freqs.new = freqs.old;
@@ -102,15 +108,28 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
ret = clk_set_rate(cpu_clk, freq_exact);
if (ret) {
pr_err("failed to set clock rate: %d\n", ret);
- if (cpu_reg)
- regulator_set_voltage_tol(cpu_reg, volt_old, tol);
+ if (cpu_reg) {
+ if (tol)
+ ret = regulator_set_voltage_tol(cpu_reg,
+ volt_old,
+ tol);
+ else
+ ret = regulator_set_voltage(cpu_reg,
+ volt_old,
+ volt_old +
+ cpu_reg_step_size);
+ }
freqs.new = freqs.old;
goto post_notify;
}

/* scaling down? scale voltage after frequency */
if (cpu_reg && freqs.new < freqs.old) {
- ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
+ if (tol)
+ ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
+ else
+ ret = regulator_set_voltage(cpu_reg, volt,
+ volt + cpu_reg_step_size);
if (ret) {
pr_err("failed to scale voltage down: %d\n", ret);
clk_set_rate(cpu_clk, freqs.old * 1000);
@@ -260,6 +279,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
if (ret > 0)
transition_latency += ret * 1000;
+ cpu_reg_step_size = regulator_get_linear_step(cpu_reg);
}

ret = cpufreq_register_driver(&cpu0_cpufreq_driver);
--
1.7.9.5


--
Regards,
Nishanth Menon
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/