From b09db45c56c299438a09b85c06067d7dcd951ea4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Feb 2012 11:01:11 -0800 Subject: cpufreq: OMAP driver depends CPUfreq tables The OMAP driver depends on CPUfreq table support for creating a table of frequencies from the OPP layer. Ensure that it's build to avoid link-time errors. Signed-off-by: Russell King [khilman@ti.com: make user-selectable, but default y] Signed-off-by: Kevin Hilman --- drivers/cpufreq/Kconfig.arm | 5 +++++ drivers/cpufreq/Makefile | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index e0664fed018a..82f1aa9c3b6f 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -2,6 +2,11 @@ # ARM CPU Frequency scaling drivers # +config ARM_OMAP2PLUS_CPUFREQ + bool "TI OMAP2+" + default ARCH_OMAP2PLUS + select CPU_FREQ_TABLE + config ARM_S3C64XX_CPUFREQ bool "Samsung S3C64XX" depends on CPU_S3C6410 diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index ac000fa76bbb..fda94c74eab0 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o -obj-$(CONFIG_ARCH_OMAP2PLUS) += omap-cpufreq.o +obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o ################################################################################## # PowerPC platform drivers -- cgit v1.2.3 From 53dfe8a884e6f85d73379f84cffa72225cd52ad6 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 15 Jul 2011 15:05:04 -0700 Subject: cpufreq: OMAP: scale voltage along with frequency 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 Signed-off-by: Kevin Hilman --- drivers/cpufreq/omap-cpufreq.c | 68 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 5d04c57aae30..9f5d6368766e 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -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) { @@ -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__, @@ -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 @@ -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; @@ -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); } -- cgit v1.2.3 From 42daffd2d6c665716d442d518022ecaad17ddf64 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Thu, 23 Feb 2012 19:19:24 +0530 Subject: cpufreq: OMAP: specify range for voltage scaling Specify voltage in ranges for regulator. Range used is tolerance specified for OPP. This helps to achieve DVFS with a wider range of regulators. Cc: Kevin Hilman Cc: Sekhar Nori Signed-off-by: Afzal Mohammed --- drivers/cpufreq/omap-cpufreq.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 9f5d6368766e..67bbb06d0460 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -38,6 +38,9 @@ #include +/* OPP tolerance in percentage */ +#define OPP_TOLERANCE 4 + #ifdef CONFIG_SMP struct lpj_info { unsigned long ref; @@ -81,7 +84,7 @@ static int omap_target(struct cpufreq_policy *policy, int r, ret = 0; struct cpufreq_freqs freqs; struct opp *opp; - unsigned long freq, volt = 0, volt_old = 0; + unsigned long freq, volt = 0, volt_old = 0, tol = 0; if (!freq_table) { dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__, @@ -125,6 +128,7 @@ static int omap_target(struct cpufreq_policy *policy, return -EINVAL; } volt = opp_get_voltage(opp); + tol = volt * OPP_TOLERANCE / 100; volt_old = regulator_get_voltage(mpu_reg); } @@ -134,7 +138,7 @@ static int omap_target(struct cpufreq_policy *policy, /* scaling up? scale voltage before frequency */ if (mpu_reg && (freqs.new > freqs.old)) { - r = regulator_set_voltage(mpu_reg, volt, volt); + r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); if (r < 0) { dev_warn(mpu_dev, "%s: unable to scale voltage up.\n", __func__); @@ -147,7 +151,7 @@ static int omap_target(struct cpufreq_policy *policy, /* scaling down? scale voltage after frequency */ if (mpu_reg && (freqs.new < freqs.old)) { - r = regulator_set_voltage(mpu_reg, volt, volt); + r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); if (r < 0) { dev_warn(mpu_dev, "%s: unable to scale voltage down.\n", __func__); -- cgit v1.2.3