diff options
author | Jaecheol Lee <jc.lee@samsung.com> | 2011-12-06 21:44:09 -0500 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2011-12-09 10:38:02 -0500 |
commit | 27f805dcb058178444a9a4e380c7dcb2fe2d3a94 (patch) | |
tree | 06b8cc22d30fba71d07e246dfcd99758ef556bc2 /drivers/cpufreq/exynos4210-cpufreq.c | |
parent | ba9d78031116a216d0e53aa629a584932e813375 (diff) |
[CPUFREQ] EXYNOS4210: cpufreq code is changed for stable working
This patch is modify code for stable working
1. Remove unused register access code
2. Change sequence for frequency changing
Signed-off-by: Jaecheol Lee <jc.lee@samsung.com>
Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'drivers/cpufreq/exynos4210-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/exynos4210-cpufreq.c | 101 |
1 files changed, 65 insertions, 36 deletions
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c index ba579e0a5c3f..a0af2d4448a9 100644 --- a/drivers/cpufreq/exynos4210-cpufreq.c +++ b/drivers/cpufreq/exynos4210-cpufreq.c | |||
@@ -36,6 +36,10 @@ static struct regulator *arm_regulator; | |||
36 | 36 | ||
37 | static struct cpufreq_freqs freqs; | 37 | static struct cpufreq_freqs freqs; |
38 | 38 | ||
39 | struct cpufreq_clkdiv { | ||
40 | unsigned int clkdiv; | ||
41 | }; | ||
42 | |||
39 | static unsigned int locking_frequency; | 43 | static unsigned int locking_frequency; |
40 | static bool frequency_locked; | 44 | static bool frequency_locked; |
41 | static DEFINE_MUTEX(cpufreq_lock); | 45 | static DEFINE_MUTEX(cpufreq_lock); |
@@ -44,6 +48,8 @@ enum cpufreq_level_index { | |||
44 | L0, L1, L2, L3, L4, CPUFREQ_LEVEL_END, | 48 | L0, L1, L2, L3, L4, CPUFREQ_LEVEL_END, |
45 | }; | 49 | }; |
46 | 50 | ||
51 | static struct cpufreq_clkdiv exynos4_clkdiv_table[CPUFREQ_LEVEL_END]; | ||
52 | |||
47 | static struct cpufreq_frequency_table exynos4_freq_table[] = { | 53 | static struct cpufreq_frequency_table exynos4_freq_table[] = { |
48 | {L0, 1200*1000}, | 54 | {L0, 1200*1000}, |
49 | {L1, 1000*1000}, | 55 | {L1, 1000*1000}, |
@@ -155,20 +161,7 @@ static void exynos4_set_clkdiv(unsigned int div_index) | |||
155 | 161 | ||
156 | /* Change Divider - CPU0 */ | 162 | /* Change Divider - CPU0 */ |
157 | 163 | ||
158 | tmp = __raw_readl(S5P_CLKDIV_CPU); | 164 | tmp = exynos4_clkdiv_table[div_index].clkdiv; |
159 | |||
160 | tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK | | ||
161 | S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK | | ||
162 | S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK | | ||
163 | S5P_CLKDIV_CPU0_APLL_MASK); | ||
164 | |||
165 | tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) | | ||
166 | (clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) | | ||
167 | (clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) | | ||
168 | (clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) | | ||
169 | (clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) | | ||
170 | (clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) | | ||
171 | (clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT)); | ||
172 | 165 | ||
173 | __raw_writel(tmp, S5P_CLKDIV_CPU); | 166 | __raw_writel(tmp, S5P_CLKDIV_CPU); |
174 | 167 | ||
@@ -233,14 +226,12 @@ static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index | |||
233 | unsigned int tmp; | 226 | unsigned int tmp; |
234 | 227 | ||
235 | if (old_index > new_index) { | 228 | if (old_index > new_index) { |
236 | /* The frequency changing to L0 needs to change apll */ | 229 | /* |
237 | if (freqs.new == exynos4_freq_table[L0].frequency) { | 230 | * L1/L3, L2/L4 Level change require |
238 | /* 1. Change the system clock divider values */ | 231 | * to only change s divider value |
239 | exynos4_set_clkdiv(new_index); | 232 | */ |
240 | 233 | if (((old_index == L3) && (new_index == L1)) || | |
241 | /* 2. Change the apll m,p,s value */ | 234 | ((old_index == L4) && (new_index == L2))) { |
242 | exynos4_set_apll(new_index); | ||
243 | } else { | ||
244 | /* 1. Change the system clock divider values */ | 235 | /* 1. Change the system clock divider values */ |
245 | exynos4_set_clkdiv(new_index); | 236 | exynos4_set_clkdiv(new_index); |
246 | 237 | ||
@@ -249,18 +240,20 @@ static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index | |||
249 | tmp &= ~(0x7 << 0); | 240 | tmp &= ~(0x7 << 0); |
250 | tmp |= (exynos4_apll_pms_table[new_index] & 0x7); | 241 | tmp |= (exynos4_apll_pms_table[new_index] & 0x7); |
251 | __raw_writel(tmp, S5P_APLL_CON0); | 242 | __raw_writel(tmp, S5P_APLL_CON0); |
252 | } | ||
253 | } | ||
254 | |||
255 | else if (old_index < new_index) { | ||
256 | /* The frequency changing from L0 needs to change apll */ | ||
257 | if (freqs.old == exynos4_freq_table[L0].frequency) { | ||
258 | /* 1. Change the apll m,p,s value */ | ||
259 | exynos4_set_apll(new_index); | ||
260 | |||
261 | /* 2. Change the system clock divider values */ | ||
262 | exynos4_set_clkdiv(new_index); | ||
263 | } else { | 243 | } else { |
244 | /* Clock Configuration Procedure */ | ||
245 | /* 1. Change the system clock divider values */ | ||
246 | exynos4_set_clkdiv(new_index); | ||
247 | /* 2. Change the apll m,p,s value */ | ||
248 | exynos4_set_apll(new_index); | ||
249 | } | ||
250 | } else if (old_index < new_index) { | ||
251 | /* | ||
252 | * L1/L3, L2/L4 Level change require | ||
253 | * to only change s divider value | ||
254 | */ | ||
255 | if (((old_index == L1) && (new_index == L3)) || | ||
256 | ((old_index == L2) && (new_index == L4))) { | ||
264 | /* 1. Change just s value in apll m,p,s value */ | 257 | /* 1. Change just s value in apll m,p,s value */ |
265 | tmp = __raw_readl(S5P_APLL_CON0); | 258 | tmp = __raw_readl(S5P_APLL_CON0); |
266 | tmp &= ~(0x7 << 0); | 259 | tmp &= ~(0x7 << 0); |
@@ -269,6 +262,12 @@ static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index | |||
269 | 262 | ||
270 | /* 2. Change the system clock divider values */ | 263 | /* 2. Change the system clock divider values */ |
271 | exynos4_set_clkdiv(new_index); | 264 | exynos4_set_clkdiv(new_index); |
265 | } else { | ||
266 | /* Clock Configuration Procedure */ | ||
267 | /* 1. Change the apll m,p,s value */ | ||
268 | exynos4_set_apll(new_index); | ||
269 | /* 2. Change the system clock divider values */ | ||
270 | exynos4_set_clkdiv(new_index); | ||
272 | } | 271 | } |
273 | } | 272 | } |
274 | } | 273 | } |
@@ -320,14 +319,14 @@ static int exynos4_target(struct cpufreq_policy *policy, | |||
320 | /* Clock Configuration Procedure */ | 319 | /* Clock Configuration Procedure */ |
321 | exynos4_set_frequency(old_index, index); | 320 | exynos4_set_frequency(old_index, index); |
322 | 321 | ||
322 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
323 | |||
323 | /* control regulator */ | 324 | /* control regulator */ |
324 | if (freqs.new < freqs.old) { | 325 | if (freqs.new < freqs.old) { |
325 | /* Voltage down */ | 326 | /* Voltage down */ |
326 | regulator_set_voltage(arm_regulator, arm_volt, arm_volt); | 327 | regulator_set_voltage(arm_regulator, arm_volt, arm_volt); |
327 | } | 328 | } |
328 | 329 | ||
329 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
330 | |||
331 | out: | 330 | out: |
332 | mutex_unlock(&cpufreq_lock); | 331 | mutex_unlock(&cpufreq_lock); |
333 | return err; | 332 | return err; |
@@ -438,7 +437,12 @@ static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
438 | * Each cpu is bound to the same speed. | 437 | * Each cpu is bound to the same speed. |
439 | * So the affected cpu is all of the cpus. | 438 | * So the affected cpu is all of the cpus. |
440 | */ | 439 | */ |
441 | cpumask_setall(policy->cpus); | 440 | if (!cpu_online(1)) { |
441 | cpumask_copy(policy->related_cpus, cpu_possible_mask); | ||
442 | cpumask_copy(policy->cpus, cpu_online_mask); | ||
443 | } else { | ||
444 | cpumask_setall(policy->cpus); | ||
445 | } | ||
442 | 446 | ||
443 | ret = cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table); | 447 | ret = cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table); |
444 | if (ret) | 448 | if (ret) |
@@ -477,6 +481,9 @@ static struct cpufreq_driver exynos4_driver = { | |||
477 | 481 | ||
478 | static int __init exynos4_cpufreq_init(void) | 482 | static int __init exynos4_cpufreq_init(void) |
479 | { | 483 | { |
484 | int i; | ||
485 | unsigned int tmp; | ||
486 | |||
480 | cpu_clk = clk_get(NULL, "armclk"); | 487 | cpu_clk = clk_get(NULL, "armclk"); |
481 | if (IS_ERR(cpu_clk)) | 488 | if (IS_ERR(cpu_clk)) |
482 | return PTR_ERR(cpu_clk); | 489 | return PTR_ERR(cpu_clk); |
@@ -503,6 +510,28 @@ static int __init exynos4_cpufreq_init(void) | |||
503 | 510 | ||
504 | register_pm_notifier(&exynos4_cpufreq_nb); | 511 | register_pm_notifier(&exynos4_cpufreq_nb); |
505 | 512 | ||
513 | tmp = __raw_readl(S5P_CLKDIV_CPU); | ||
514 | |||
515 | for (i = L0; i < CPUFREQ_LEVEL_END; i++) { | ||
516 | tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | | ||
517 | S5P_CLKDIV_CPU0_COREM0_MASK | | ||
518 | S5P_CLKDIV_CPU0_COREM1_MASK | | ||
519 | S5P_CLKDIV_CPU0_PERIPH_MASK | | ||
520 | S5P_CLKDIV_CPU0_ATB_MASK | | ||
521 | S5P_CLKDIV_CPU0_PCLKDBG_MASK | | ||
522 | S5P_CLKDIV_CPU0_APLL_MASK); | ||
523 | |||
524 | tmp |= ((clkdiv_cpu0[i][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) | | ||
525 | (clkdiv_cpu0[i][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) | | ||
526 | (clkdiv_cpu0[i][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) | | ||
527 | (clkdiv_cpu0[i][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) | | ||
528 | (clkdiv_cpu0[i][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) | | ||
529 | (clkdiv_cpu0[i][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) | | ||
530 | (clkdiv_cpu0[i][6] << S5P_CLKDIV_CPU0_APLL_SHIFT)); | ||
531 | |||
532 | exynos4_clkdiv_table[i].clkdiv = tmp; | ||
533 | } | ||
534 | |||
506 | return cpufreq_register_driver(&exynos4_driver); | 535 | return cpufreq_register_driver(&exynos4_driver); |
507 | 536 | ||
508 | out: | 537 | out: |