diff options
author | Vishwanath BS <vishwanath.bs@ti.com> | 2011-02-09 16:27:44 +0530 |
---|---|---|
committer | Nicolas Pitre <nicolas.pitre@linaro.org> | 2011-04-01 23:02:59 -0400 |
commit | b7584aa0a18700c55ef7fc9aa9f664c0514222ff (patch) | |
tree | fe3d5bdfc7f0c1840b1641158a4d6687ece16504 /arch | |
parent | 14db9801db2c522c3a39ad4a6e528fe0707153ca (diff) |
OMAP3: cpufreq driver changes for DVFS support
Changes in the omap cpufreq driver for DVFS support.
Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/plat-omap/cpu-omap.c | 70 |
1 files changed, 67 insertions, 3 deletions
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index da4f68dbba1..d16bd972336 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c @@ -8,6 +8,10 @@ * * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Updated to support OMAP3 + * Rajendra Nayak <rnayak@ti.com> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -21,10 +25,18 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/opp.h> #include <mach/hardware.h> #include <plat/clock.h> #include <asm/system.h> +#include <asm/cpu.h> + +#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) +#include <plat/omap-pm.h> +#include <plat/common.h> +#include <plat/dvfs.h> +#endif #define VERY_HI_RATE 900000000 @@ -32,6 +44,8 @@ static struct cpufreq_frequency_table *freq_table; #ifdef CONFIG_ARCH_OMAP1 #define MPU_CLK "mpu" +#elif defined(CONFIG_ARCH_OMAP3) +#define MPU_CLK "arm_fck" #else #define MPU_CLK "virt_prcm_set" #endif @@ -74,6 +88,12 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int relation) { struct cpufreq_freqs freqs; +#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) + unsigned long freq; + int i; + struct cpufreq_freqs freqs_notify; + struct device *mpu_dev = omap2_get_mpuss_device(); +#endif int ret = 0; /* Ensure desired rate is within allowed range. Some govenors @@ -83,13 +103,13 @@ static int omap_target(struct cpufreq_policy *policy, if (target_freq > policy->max) target_freq = policy->max; +#ifdef CONFIG_ARCH_OMAP1 freqs.old = omap_getspeed(0); freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; freqs.cpu = 0; if (freqs.old == freqs.new) return ret; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); #ifdef CONFIG_CPU_FREQ_DEBUG printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", @@ -97,7 +117,39 @@ static int omap_target(struct cpufreq_policy *policy, #endif ret = clk_set_rate(mpu_clk, freqs.new * 1000); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); +#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) + freqs.old = omap_getspeed(policy->cpu);; + freqs_notify.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; + freqs.cpu = policy->cpu; + + if (freqs.old == freqs.new) + return ret; + + /* pre notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + /* scale the frequency */ + freq = target_freq * 1000; + if (opp_find_freq_ceil(mpu_dev, &freq)) + omap_device_scale(mpu_dev, mpu_dev, freq); + +#ifdef CONFIG_SMP + /* Update loops per jiffy */ + freqs.new = omap_getspeed(policy->cpu); + for_each_cpu(i, policy->cpus) + per_cpu(cpu_data, i).loops_per_jiffy = + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, + freqs.old, freqs.new); +#endif + /* post notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } +#endif return ret; } @@ -114,7 +166,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) policy->cur = policy->min = policy->max = omap_getspeed(0); - clk_init_cpufreq_table(&freq_table); + if (!cpu_is_omap34xx()) { + clk_init_cpufreq_table(&freq_table); + } else { + struct device *mpu_dev = omap2_get_mpuss_device(); + + opp_init_cpufreq_table(mpu_dev, &freq_table); + } + if (freq_table) { result = cpufreq_frequency_table_cpuinfo(policy, freq_table); if (!result) @@ -126,6 +185,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) VERY_HI_RATE) / 1000; } + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = omap_getspeed(0); + /* FIXME: what's the actual transition time? */ policy->cpuinfo.transition_latency = 300 * 1000; @@ -160,7 +223,7 @@ static int __init omap_cpufreq_init(void) return cpufreq_register_driver(&omap_driver); } -arch_initcall(omap_cpufreq_init); +late_initcall(omap_cpufreq_init); /* * if ever we want to remove this, upon cleanup call: @@ -169,3 +232,4 @@ arch_initcall(omap_cpufreq_init); * cpufreq_frequency_table_put_attr() */ + |