Skip to content

Commit

Permalink
cpufreq: OMAP: scale voltage along with frequency
Browse files Browse the repository at this point in the history
Use the regulator framework to get the voltage regulator associated
with the MPU voltage domain and use it to scale voltage along with
frequency.

While here, CONFIG_CPU_FREQ_DEBUG doesn't exist anymore, so move
debug prints to use dev_dbg().

Special thanks to Afzal Mohammed for suggestions on more robust error
checking.

Cc: Afzal Mohammed  <afzal@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
  • Loading branch information
Kevin Hilman committed Feb 22, 2012
1 parent b09db45 commit 53dfe8a
Showing 1 changed file with 63 additions and 5 deletions.
68 changes: 63 additions & 5 deletions drivers/cpufreq/omap-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/opp.h>
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>

#include <asm/system.h>
#include <asm/smp_plat.h>
Expand Down Expand Up @@ -52,6 +53,7 @@ static atomic_t freq_table_users = ATOMIC_INIT(0);
static struct clk *mpu_clk;
static char *mpu_clk_name;
static struct device *mpu_dev;
static struct regulator *mpu_reg;

static int omap_verify_speed(struct cpufreq_policy *policy)
{
Expand All @@ -76,8 +78,10 @@ static int omap_target(struct cpufreq_policy *policy,
unsigned int relation)
{
unsigned int i;
int ret = 0;
int r, ret = 0;
struct cpufreq_freqs freqs;
struct opp *opp;
unsigned long freq, volt = 0, volt_old = 0;

if (!freq_table) {
dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
Expand Down Expand Up @@ -111,13 +115,49 @@ static int omap_target(struct cpufreq_policy *policy,
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}

#ifdef CONFIG_CPU_FREQ_DEBUG
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
#endif
freq = freqs.new * 1000;

if (mpu_reg) {
opp = opp_find_freq_ceil(mpu_dev, &freq);
if (IS_ERR(opp)) {
dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
__func__, freqs.new);
return -EINVAL;
}
volt = opp_get_voltage(opp);
volt_old = regulator_get_voltage(mpu_reg);
}

dev_dbg(mpu_dev, "cpufreq-omap: %u MHz, %ld mV --> %u MHz, %ld mV\n",
freqs.old / 1000, volt_old ? volt_old / 1000 : -1,
freqs.new / 1000, volt ? volt / 1000 : -1);

/* scaling up? scale voltage before frequency */
if (mpu_reg && (freqs.new > freqs.old)) {
r = regulator_set_voltage(mpu_reg, volt, volt);
if (r < 0) {
dev_warn(mpu_dev, "%s: unable to scale voltage up.\n",
__func__);
freqs.new = freqs.old;
goto done;
}
}

ret = clk_set_rate(mpu_clk, freqs.new * 1000);
freqs.new = omap_getspeed(policy->cpu);

/* scaling down? scale voltage after frequency */
if (mpu_reg && (freqs.new < freqs.old)) {
r = regulator_set_voltage(mpu_reg, volt, volt);
if (r < 0) {
dev_warn(mpu_dev, "%s: unable to scale voltage down.\n",
__func__);
ret = clk_set_rate(mpu_clk, freqs.old * 1000);
freqs.new = freqs.old;
goto done;
}
}

freqs.new = omap_getspeed(policy->cpu);
#ifdef CONFIG_SMP
/*
* Note that loops_per_jiffy is not updated on SMP systems in
Expand All @@ -144,6 +184,7 @@ static int omap_target(struct cpufreq_policy *policy,
freqs.new);
#endif

done:
/* notifiers */
for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
Expand Down Expand Up @@ -260,6 +301,23 @@ static int __init omap_cpufreq_init(void)
return -EINVAL;
}

mpu_reg = regulator_get(mpu_dev, "vcc");
if (IS_ERR(mpu_reg)) {
pr_warning("%s: unable to get MPU regulator\n", __func__);
mpu_reg = NULL;
} else {
/*
* Ensure physical regulator is present.
* (e.g. could be dummy regulator.)
*/
if (regulator_get_voltage(mpu_reg) < 0) {
pr_warn("%s: physical regulator not present for MPU\n",
__func__);
regulator_put(mpu_reg);
mpu_reg = NULL;
}
}

return cpufreq_register_driver(&omap_driver);
}

Expand Down

0 comments on commit 53dfe8a

Please sign in to comment.