aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/exynos4210-cpufreq.c
diff options
context:
space:
mode:
authorJaecheol Lee <jc.lee@samsung.com>2011-12-06 21:44:09 -0500
committerDave Jones <davej@redhat.com>2011-12-09 10:38:02 -0500
commit27f805dcb058178444a9a4e380c7dcb2fe2d3a94 (patch)
tree06b8cc22d30fba71d07e246dfcd99758ef556bc2 /drivers/cpufreq/exynos4210-cpufreq.c
parentba9d78031116a216d0e53aa629a584932e813375 (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.c101
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
37static struct cpufreq_freqs freqs; 37static struct cpufreq_freqs freqs;
38 38
39struct cpufreq_clkdiv {
40 unsigned int clkdiv;
41};
42
39static unsigned int locking_frequency; 43static unsigned int locking_frequency;
40static bool frequency_locked; 44static bool frequency_locked;
41static DEFINE_MUTEX(cpufreq_lock); 45static 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
51static struct cpufreq_clkdiv exynos4_clkdiv_table[CPUFREQ_LEVEL_END];
52
47static struct cpufreq_frequency_table exynos4_freq_table[] = { 53static 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
331out: 330out:
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
478static int __init exynos4_cpufreq_init(void) 482static 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
508out: 537out: