aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/cpu-omap.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/cpu-omap.c')
-rw-r--r--arch/arm/plat-omap/cpu-omap.c57
1 files changed, 53 insertions, 4 deletions
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index b2690242a390..843e8af64066 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -23,10 +23,13 @@
23#include <linux/io.h> 23#include <linux/io.h>
24 24
25#include <mach/hardware.h> 25#include <mach/hardware.h>
26#include <mach/clock.h>
26#include <asm/system.h> 27#include <asm/system.h>
27 28
28#define VERY_HI_RATE 900000000 29#define VERY_HI_RATE 900000000
29 30
31static struct cpufreq_frequency_table *freq_table;
32
30#ifdef CONFIG_ARCH_OMAP1 33#ifdef CONFIG_ARCH_OMAP1
31#define MPU_CLK "mpu" 34#define MPU_CLK "mpu"
32#else 35#else
@@ -39,6 +42,9 @@ static struct clk *mpu_clk;
39 42
40int omap_verify_speed(struct cpufreq_policy *policy) 43int omap_verify_speed(struct cpufreq_policy *policy)
41{ 44{
45 if (freq_table)
46 return cpufreq_frequency_table_verify(policy, freq_table);
47
42 if (policy->cpu) 48 if (policy->cpu)
43 return -EINVAL; 49 return -EINVAL;
44 50
@@ -70,12 +76,26 @@ static int omap_target(struct cpufreq_policy *policy,
70 struct cpufreq_freqs freqs; 76 struct cpufreq_freqs freqs;
71 int ret = 0; 77 int ret = 0;
72 78
79 /* Ensure desired rate is within allowed range. Some govenors
80 * (ondemand) will just pass target_freq=0 to get the minimum. */
81 if (target_freq < policy->cpuinfo.min_freq)
82 target_freq = policy->cpuinfo.min_freq;
83 if (target_freq > policy->cpuinfo.max_freq)
84 target_freq = policy->cpuinfo.max_freq;
85
73 freqs.old = omap_getspeed(0); 86 freqs.old = omap_getspeed(0);
74 freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; 87 freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
75 freqs.cpu = 0; 88 freqs.cpu = 0;
76 89
90 if (freqs.old == freqs.new)
91 return ret;
92
77 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 93 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
78 ret = clk_set_rate(mpu_clk, target_freq * 1000); 94#ifdef CONFIG_CPU_FREQ_DEBUG
95 printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
96 freqs.old, freqs.new);
97#endif
98 ret = clk_set_rate(mpu_clk, freqs.new * 1000);
79 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 99 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
80 100
81 return ret; 101 return ret;
@@ -83,16 +103,31 @@ static int omap_target(struct cpufreq_policy *policy,
83 103
84static int __init omap_cpu_init(struct cpufreq_policy *policy) 104static int __init omap_cpu_init(struct cpufreq_policy *policy)
85{ 105{
106 int result = 0;
107
86 mpu_clk = clk_get(NULL, MPU_CLK); 108 mpu_clk = clk_get(NULL, MPU_CLK);
87 if (IS_ERR(mpu_clk)) 109 if (IS_ERR(mpu_clk))
88 return PTR_ERR(mpu_clk); 110 return PTR_ERR(mpu_clk);
89 111
90 if (policy->cpu != 0) 112 if (policy->cpu != 0)
91 return -EINVAL; 113 return -EINVAL;
114
92 policy->cur = policy->min = policy->max = omap_getspeed(0); 115 policy->cur = policy->min = policy->max = omap_getspeed(0);
93 policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; 116
94 policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000; 117 clk_init_cpufreq_table(&freq_table);
95 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 118 if (freq_table) {
119 result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
120 if (!result)
121 cpufreq_frequency_table_get_attr(freq_table,
122 policy->cpu);
123 } else {
124 policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
125 policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
126 VERY_HI_RATE) / 1000;
127 }
128
129 /* FIXME: what's the actual transition time? */
130 policy->cpuinfo.transition_latency = 10 * 1000 * 1000;
96 131
97 return 0; 132 return 0;
98} 133}
@@ -103,6 +138,11 @@ static int omap_cpu_exit(struct cpufreq_policy *policy)
103 return 0; 138 return 0;
104} 139}
105 140
141static struct freq_attr *omap_cpufreq_attr[] = {
142 &cpufreq_freq_attr_scaling_available_freqs,
143 NULL,
144};
145
106static struct cpufreq_driver omap_driver = { 146static struct cpufreq_driver omap_driver = {
107 .flags = CPUFREQ_STICKY, 147 .flags = CPUFREQ_STICKY,
108 .verify = omap_verify_speed, 148 .verify = omap_verify_speed,
@@ -111,6 +151,7 @@ static struct cpufreq_driver omap_driver = {
111 .init = omap_cpu_init, 151 .init = omap_cpu_init,
112 .exit = omap_cpu_exit, 152 .exit = omap_cpu_exit,
113 .name = "omap", 153 .name = "omap",
154 .attr = omap_cpufreq_attr,
114}; 155};
115 156
116static int __init omap_cpufreq_init(void) 157static int __init omap_cpufreq_init(void)
@@ -119,3 +160,11 @@ static int __init omap_cpufreq_init(void)
119} 160}
120 161
121arch_initcall(omap_cpufreq_init); 162arch_initcall(omap_cpufreq_init);
163
164/*
165 * if ever we want to remove this, upon cleanup call:
166 *
167 * cpufreq_unregister_driver()
168 * cpufreq_frequency_table_put_attr()
169 */
170