diff options
Diffstat (limited to 'arch/arm/mach-davinci/cpufreq.c')
-rw-r--r-- | arch/arm/mach-davinci/cpufreq.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c index d3fa6de1e20f..41669ecc1f91 100644 --- a/arch/arm/mach-davinci/cpufreq.c +++ b/arch/arm/mach-davinci/cpufreq.c | |||
@@ -34,6 +34,8 @@ | |||
34 | struct davinci_cpufreq { | 34 | struct davinci_cpufreq { |
35 | struct device *dev; | 35 | struct device *dev; |
36 | struct clk *armclk; | 36 | struct clk *armclk; |
37 | struct clk *asyncclk; | ||
38 | unsigned long asyncrate; | ||
37 | }; | 39 | }; |
38 | static struct davinci_cpufreq cpufreq; | 40 | static struct davinci_cpufreq cpufreq; |
39 | 41 | ||
@@ -92,9 +94,7 @@ static int davinci_target(struct cpufreq_policy *policy, | |||
92 | if (freqs.old == freqs.new) | 94 | if (freqs.old == freqs.new) |
93 | return ret; | 95 | return ret; |
94 | 96 | ||
95 | cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, | 97 | dev_dbg(&cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new); |
96 | dev_driver_string(cpufreq.dev), | ||
97 | "transition: %u --> %u\n", freqs.old, freqs.new); | ||
98 | 98 | ||
99 | ret = cpufreq_frequency_table_target(policy, pdata->freq_table, | 99 | ret = cpufreq_frequency_table_target(policy, pdata->freq_table, |
100 | freqs.new, relation, &idx); | 100 | freqs.new, relation, &idx); |
@@ -104,21 +104,33 @@ static int davinci_target(struct cpufreq_policy *policy, | |||
104 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 104 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |
105 | 105 | ||
106 | /* if moving to higher frequency, up the voltage beforehand */ | 106 | /* if moving to higher frequency, up the voltage beforehand */ |
107 | if (pdata->set_voltage && freqs.new > freqs.old) | 107 | if (pdata->set_voltage && freqs.new > freqs.old) { |
108 | pdata->set_voltage(idx); | 108 | ret = pdata->set_voltage(idx); |
109 | if (ret) | ||
110 | goto out; | ||
111 | } | ||
109 | 112 | ||
110 | ret = clk_set_rate(armclk, idx); | 113 | ret = clk_set_rate(armclk, idx); |
114 | if (ret) | ||
115 | goto out; | ||
116 | |||
117 | if (cpufreq.asyncclk) { | ||
118 | ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate); | ||
119 | if (ret) | ||
120 | goto out; | ||
121 | } | ||
111 | 122 | ||
112 | /* if moving to lower freq, lower the voltage after lowering freq */ | 123 | /* if moving to lower freq, lower the voltage after lowering freq */ |
113 | if (pdata->set_voltage && freqs.new < freqs.old) | 124 | if (pdata->set_voltage && freqs.new < freqs.old) |
114 | pdata->set_voltage(idx); | 125 | pdata->set_voltage(idx); |
115 | 126 | ||
127 | out: | ||
116 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 128 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
117 | 129 | ||
118 | return ret; | 130 | return ret; |
119 | } | 131 | } |
120 | 132 | ||
121 | static int __init davinci_cpu_init(struct cpufreq_policy *policy) | 133 | static int davinci_cpu_init(struct cpufreq_policy *policy) |
122 | { | 134 | { |
123 | int result = 0; | 135 | int result = 0; |
124 | struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; | 136 | struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; |
@@ -153,7 +165,7 @@ static int __init davinci_cpu_init(struct cpufreq_policy *policy) | |||
153 | /* | 165 | /* |
154 | * Time measurement across the target() function yields ~1500-1800us | 166 | * Time measurement across the target() function yields ~1500-1800us |
155 | * time taken with no drivers on notification list. | 167 | * time taken with no drivers on notification list. |
156 | * Setting the latency to 2000 us to accomodate addition of drivers | 168 | * Setting the latency to 2000 us to accommodate addition of drivers |
157 | * to pre/post change notification list. | 169 | * to pre/post change notification list. |
158 | */ | 170 | */ |
159 | policy->cpuinfo.transition_latency = 2000 * 1000; | 171 | policy->cpuinfo.transition_latency = 2000 * 1000; |
@@ -185,6 +197,7 @@ static struct cpufreq_driver davinci_driver = { | |||
185 | static int __init davinci_cpufreq_probe(struct platform_device *pdev) | 197 | static int __init davinci_cpufreq_probe(struct platform_device *pdev) |
186 | { | 198 | { |
187 | struct davinci_cpufreq_config *pdata = pdev->dev.platform_data; | 199 | struct davinci_cpufreq_config *pdata = pdev->dev.platform_data; |
200 | struct clk *asyncclk; | ||
188 | 201 | ||
189 | if (!pdata) | 202 | if (!pdata) |
190 | return -EINVAL; | 203 | return -EINVAL; |
@@ -199,6 +212,12 @@ static int __init davinci_cpufreq_probe(struct platform_device *pdev) | |||
199 | return PTR_ERR(cpufreq.armclk); | 212 | return PTR_ERR(cpufreq.armclk); |
200 | } | 213 | } |
201 | 214 | ||
215 | asyncclk = clk_get(cpufreq.dev, "async"); | ||
216 | if (!IS_ERR(asyncclk)) { | ||
217 | cpufreq.asyncclk = asyncclk; | ||
218 | cpufreq.asyncrate = clk_get_rate(asyncclk); | ||
219 | } | ||
220 | |||
202 | return cpufreq_register_driver(&davinci_driver); | 221 | return cpufreq_register_driver(&davinci_driver); |
203 | } | 222 | } |
204 | 223 | ||
@@ -206,6 +225,9 @@ static int __exit davinci_cpufreq_remove(struct platform_device *pdev) | |||
206 | { | 225 | { |
207 | clk_put(cpufreq.armclk); | 226 | clk_put(cpufreq.armclk); |
208 | 227 | ||
228 | if (cpufreq.asyncclk) | ||
229 | clk_put(cpufreq.asyncclk); | ||
230 | |||
209 | return cpufreq_unregister_driver(&davinci_driver); | 231 | return cpufreq_unregister_driver(&davinci_driver); |
210 | } | 232 | } |
211 | 233 | ||