diff options
Diffstat (limited to 'drivers/cpufreq/exynos5440-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/exynos5440-cpufreq.c | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 76bef8b078cb..49b756015316 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c | |||
@@ -100,7 +100,6 @@ struct exynos_dvfs_data { | |||
100 | struct resource *mem; | 100 | struct resource *mem; |
101 | int irq; | 101 | int irq; |
102 | struct clk *cpu_clk; | 102 | struct clk *cpu_clk; |
103 | unsigned int cur_frequency; | ||
104 | unsigned int latency; | 103 | unsigned int latency; |
105 | struct cpufreq_frequency_table *freq_table; | 104 | struct cpufreq_frequency_table *freq_table; |
106 | unsigned int freq_count; | 105 | unsigned int freq_count; |
@@ -165,7 +164,7 @@ static int init_div_table(void) | |||
165 | return 0; | 164 | return 0; |
166 | } | 165 | } |
167 | 166 | ||
168 | static void exynos_enable_dvfs(void) | 167 | static void exynos_enable_dvfs(unsigned int cur_frequency) |
169 | { | 168 | { |
170 | unsigned int tmp, i, cpu; | 169 | unsigned int tmp, i, cpu; |
171 | struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table; | 170 | struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table; |
@@ -184,18 +183,18 @@ static void exynos_enable_dvfs(void) | |||
184 | 183 | ||
185 | /* Set initial performance index */ | 184 | /* Set initial performance index */ |
186 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) | 185 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) |
187 | if (freq_table[i].frequency == dvfs_info->cur_frequency) | 186 | if (freq_table[i].frequency == cur_frequency) |
188 | break; | 187 | break; |
189 | 188 | ||
190 | if (freq_table[i].frequency == CPUFREQ_TABLE_END) { | 189 | if (freq_table[i].frequency == CPUFREQ_TABLE_END) { |
191 | dev_crit(dvfs_info->dev, "Boot up frequency not supported\n"); | 190 | dev_crit(dvfs_info->dev, "Boot up frequency not supported\n"); |
192 | /* Assign the highest frequency */ | 191 | /* Assign the highest frequency */ |
193 | i = 0; | 192 | i = 0; |
194 | dvfs_info->cur_frequency = freq_table[i].frequency; | 193 | cur_frequency = freq_table[i].frequency; |
195 | } | 194 | } |
196 | 195 | ||
197 | dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ", | 196 | dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ", |
198 | dvfs_info->cur_frequency); | 197 | cur_frequency); |
199 | 198 | ||
200 | for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) { | 199 | for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) { |
201 | tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4); | 200 | tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4); |
@@ -209,11 +208,6 @@ static void exynos_enable_dvfs(void) | |||
209 | dvfs_info->base + XMU_DVFS_CTRL); | 208 | dvfs_info->base + XMU_DVFS_CTRL); |
210 | } | 209 | } |
211 | 210 | ||
212 | static unsigned int exynos_getspeed(unsigned int cpu) | ||
213 | { | ||
214 | return dvfs_info->cur_frequency; | ||
215 | } | ||
216 | |||
217 | static int exynos_target(struct cpufreq_policy *policy, unsigned int index) | 211 | static int exynos_target(struct cpufreq_policy *policy, unsigned int index) |
218 | { | 212 | { |
219 | unsigned int tmp; | 213 | unsigned int tmp; |
@@ -222,7 +216,7 @@ static int exynos_target(struct cpufreq_policy *policy, unsigned int index) | |||
222 | 216 | ||
223 | mutex_lock(&cpufreq_lock); | 217 | mutex_lock(&cpufreq_lock); |
224 | 218 | ||
225 | freqs.old = dvfs_info->cur_frequency; | 219 | freqs.old = policy->cur; |
226 | freqs.new = freq_table[index].frequency; | 220 | freqs.new = freq_table[index].frequency; |
227 | 221 | ||
228 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 222 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); |
@@ -250,7 +244,7 @@ static void exynos_cpufreq_work(struct work_struct *work) | |||
250 | goto skip_work; | 244 | goto skip_work; |
251 | 245 | ||
252 | mutex_lock(&cpufreq_lock); | 246 | mutex_lock(&cpufreq_lock); |
253 | freqs.old = dvfs_info->cur_frequency; | 247 | freqs.old = policy->cur; |
254 | 248 | ||
255 | cur_pstate = __raw_readl(dvfs_info->base + XMU_P_STATUS); | 249 | cur_pstate = __raw_readl(dvfs_info->base + XMU_P_STATUS); |
256 | if (cur_pstate >> C0_3_PSTATE_VALID_SHIFT & 0x1) | 250 | if (cur_pstate >> C0_3_PSTATE_VALID_SHIFT & 0x1) |
@@ -260,10 +254,9 @@ static void exynos_cpufreq_work(struct work_struct *work) | |||
260 | 254 | ||
261 | if (likely(index < dvfs_info->freq_count)) { | 255 | if (likely(index < dvfs_info->freq_count)) { |
262 | freqs.new = freq_table[index].frequency; | 256 | freqs.new = freq_table[index].frequency; |
263 | dvfs_info->cur_frequency = freqs.new; | ||
264 | } else { | 257 | } else { |
265 | dev_crit(dvfs_info->dev, "New frequency out of range\n"); | 258 | dev_crit(dvfs_info->dev, "New frequency out of range\n"); |
266 | freqs.new = dvfs_info->cur_frequency; | 259 | freqs.new = freqs.old; |
267 | } | 260 | } |
268 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 261 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); |
269 | 262 | ||
@@ -307,15 +300,17 @@ static void exynos_sort_descend_freq_table(void) | |||
307 | 300 | ||
308 | static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) | 301 | static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) |
309 | { | 302 | { |
303 | policy->clk = dvfs_info->cpu_clk; | ||
310 | return cpufreq_generic_init(policy, dvfs_info->freq_table, | 304 | return cpufreq_generic_init(policy, dvfs_info->freq_table, |
311 | dvfs_info->latency); | 305 | dvfs_info->latency); |
312 | } | 306 | } |
313 | 307 | ||
314 | static struct cpufreq_driver exynos_driver = { | 308 | static struct cpufreq_driver exynos_driver = { |
315 | .flags = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION, | 309 | .flags = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION | |
310 | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||
316 | .verify = cpufreq_generic_frequency_table_verify, | 311 | .verify = cpufreq_generic_frequency_table_verify, |
317 | .target_index = exynos_target, | 312 | .target_index = exynos_target, |
318 | .get = exynos_getspeed, | 313 | .get = cpufreq_generic_get, |
319 | .init = exynos_cpufreq_cpu_init, | 314 | .init = exynos_cpufreq_cpu_init, |
320 | .exit = cpufreq_generic_exit, | 315 | .exit = cpufreq_generic_exit, |
321 | .name = CPUFREQ_NAME, | 316 | .name = CPUFREQ_NAME, |
@@ -335,6 +330,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) | |||
335 | int ret = -EINVAL; | 330 | int ret = -EINVAL; |
336 | struct device_node *np; | 331 | struct device_node *np; |
337 | struct resource res; | 332 | struct resource res; |
333 | unsigned int cur_frequency; | ||
338 | 334 | ||
339 | np = pdev->dev.of_node; | 335 | np = pdev->dev.of_node; |
340 | if (!np) | 336 | if (!np) |
@@ -391,13 +387,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) | |||
391 | goto err_free_table; | 387 | goto err_free_table; |
392 | } | 388 | } |
393 | 389 | ||
394 | dvfs_info->cur_frequency = clk_get_rate(dvfs_info->cpu_clk); | 390 | cur_frequency = clk_get_rate(dvfs_info->cpu_clk); |
395 | if (!dvfs_info->cur_frequency) { | 391 | if (!cur_frequency) { |
396 | dev_err(dvfs_info->dev, "Failed to get clock rate\n"); | 392 | dev_err(dvfs_info->dev, "Failed to get clock rate\n"); |
397 | ret = -EINVAL; | 393 | ret = -EINVAL; |
398 | goto err_free_table; | 394 | goto err_free_table; |
399 | } | 395 | } |
400 | dvfs_info->cur_frequency /= 1000; | 396 | cur_frequency /= 1000; |
401 | 397 | ||
402 | INIT_WORK(&dvfs_info->irq_work, exynos_cpufreq_work); | 398 | INIT_WORK(&dvfs_info->irq_work, exynos_cpufreq_work); |
403 | ret = devm_request_irq(dvfs_info->dev, dvfs_info->irq, | 399 | ret = devm_request_irq(dvfs_info->dev, dvfs_info->irq, |
@@ -414,7 +410,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) | |||
414 | goto err_free_table; | 410 | goto err_free_table; |
415 | } | 411 | } |
416 | 412 | ||
417 | exynos_enable_dvfs(); | 413 | exynos_enable_dvfs(cur_frequency); |
418 | ret = cpufreq_register_driver(&exynos_driver); | 414 | ret = cpufreq_register_driver(&exynos_driver); |
419 | if (ret) { | 415 | if (ret) { |
420 | dev_err(dvfs_info->dev, | 416 | dev_err(dvfs_info->dev, |