aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/exynos5250-cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/exynos5250-cpufreq.c')
-rw-r--r--drivers/cpufreq/exynos5250-cpufreq.c168
1 files changed, 37 insertions, 131 deletions
diff --git a/drivers/cpufreq/exynos5250-cpufreq.c b/drivers/cpufreq/exynos5250-cpufreq.c
index 8a5d7338b795..736a5cfdfd17 100644
--- a/drivers/cpufreq/exynos5250-cpufreq.c
+++ b/drivers/cpufreq/exynos5250-cpufreq.c
@@ -21,21 +21,18 @@
21#include <mach/regs-clock.h> 21#include <mach/regs-clock.h>
22#include <mach/cpufreq.h> 22#include <mach/cpufreq.h>
23 23
24#define CPUFREQ_LEVEL_END (L15 + 1)
25
26static struct clk *cpu_clk; 24static struct clk *cpu_clk;
27static struct clk *moutcore; 25static struct clk *moutcore;
28static struct clk *mout_mpll; 26static struct clk *mout_mpll;
29static struct clk *mout_apll; 27static struct clk *mout_apll;
30 28
31struct cpufreq_clkdiv { 29static unsigned int exynos5250_volt_table[] = {
32 unsigned int index; 30 1300000, 1250000, 1225000, 1200000, 1150000,
33 unsigned int clkdiv; 31 1125000, 1100000, 1075000, 1050000, 1025000,
34 unsigned int clkdiv1; 32 1012500, 1000000, 975000, 950000, 937500,
33 925000
35}; 34};
36 35
37static unsigned int exynos5250_volt_table[CPUFREQ_LEVEL_END];
38
39static struct cpufreq_frequency_table exynos5250_freq_table[] = { 36static struct cpufreq_frequency_table exynos5250_freq_table[] = {
40 {L0, 1700 * 1000}, 37 {L0, 1700 * 1000},
41 {L1, 1600 * 1000}, 38 {L1, 1600 * 1000},
@@ -45,8 +42,8 @@ static struct cpufreq_frequency_table exynos5250_freq_table[] = {
45 {L5, 1200 * 1000}, 42 {L5, 1200 * 1000},
46 {L6, 1100 * 1000}, 43 {L6, 1100 * 1000},
47 {L7, 1000 * 1000}, 44 {L7, 1000 * 1000},
48 {L8, 900 * 1000}, 45 {L8, 900 * 1000},
49 {L9, 800 * 1000}, 46 {L9, 800 * 1000},
50 {L10, 700 * 1000}, 47 {L10, 700 * 1000},
51 {L11, 600 * 1000}, 48 {L11, 600 * 1000},
52 {L12, 500 * 1000}, 49 {L12, 500 * 1000},
@@ -56,78 +53,30 @@ static struct cpufreq_frequency_table exynos5250_freq_table[] = {
56 {0, CPUFREQ_TABLE_END}, 53 {0, CPUFREQ_TABLE_END},
57}; 54};
58 55
59static struct cpufreq_clkdiv exynos5250_clkdiv_table[CPUFREQ_LEVEL_END]; 56static struct apll_freq apll_freq_5250[] = {
60
61static unsigned int clkdiv_cpu0_5250[CPUFREQ_LEVEL_END][8] = {
62 /* 57 /*
63 * Clock divider value for following 58 * values:
64 * { ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2 } 59 * freq
65 */ 60 * clock divider for ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2
66 { 0, 3, 7, 7, 7, 3, 5, 0 }, /* 1700 MHz */ 61 * clock divider for COPY, HPM, RESERVED
67 { 0, 3, 7, 7, 7, 1, 4, 0 }, /* 1600 MHz */ 62 * PLL M, P, S
68 { 0, 2, 7, 7, 7, 1, 4, 0 }, /* 1500 MHz */
69 { 0, 2, 7, 7, 6, 1, 4, 0 }, /* 1400 MHz */
70 { 0, 2, 7, 7, 6, 1, 3, 0 }, /* 1300 MHz */
71 { 0, 2, 7, 7, 5, 1, 3, 0 }, /* 1200 MHz */
72 { 0, 3, 7, 7, 5, 1, 3, 0 }, /* 1100 MHz */
73 { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 1000 MHz */
74 { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 900 MHz */
75 { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 800 MHz */
76 { 0, 1, 7, 7, 3, 1, 1, 0 }, /* 700 MHz */
77 { 0, 1, 7, 7, 3, 1, 1, 0 }, /* 600 MHz */
78 { 0, 1, 7, 7, 2, 1, 1, 0 }, /* 500 MHz */
79 { 0, 1, 7, 7, 2, 1, 1, 0 }, /* 400 MHz */
80 { 0, 1, 7, 7, 1, 1, 1, 0 }, /* 300 MHz */
81 { 0, 1, 7, 7, 1, 1, 1, 0 }, /* 200 MHz */
82};
83
84static unsigned int clkdiv_cpu1_5250[CPUFREQ_LEVEL_END][2] = {
85 /* Clock divider value for following
86 * { COPY, HPM }
87 */ 63 */
88 { 0, 2 }, /* 1700 MHz */ 64 APLL_FREQ(1700, 0, 3, 7, 7, 7, 3, 5, 0, 0, 2, 0, 425, 6, 0),
89 { 0, 2 }, /* 1600 MHz */ 65 APLL_FREQ(1600, 0, 3, 7, 7, 7, 1, 4, 0, 0, 2, 0, 200, 3, 0),
90 { 0, 2 }, /* 1500 MHz */ 66 APLL_FREQ(1500, 0, 2, 7, 7, 7, 1, 4, 0, 0, 2, 0, 250, 4, 0),
91 { 0, 2 }, /* 1400 MHz */ 67 APLL_FREQ(1400, 0, 2, 7, 7, 6, 1, 4, 0, 0, 2, 0, 175, 3, 0),
92 { 0, 2 }, /* 1300 MHz */ 68 APLL_FREQ(1300, 0, 2, 7, 7, 6, 1, 3, 0, 0, 2, 0, 325, 6, 0),
93 { 0, 2 }, /* 1200 MHz */ 69 APLL_FREQ(1200, 0, 2, 7, 7, 5, 1, 3, 0, 0, 2, 0, 200, 4, 0),
94 { 0, 2 }, /* 1100 MHz */ 70 APLL_FREQ(1100, 0, 3, 7, 7, 5, 1, 3, 0, 0, 2, 0, 275, 6, 0),
95 { 0, 2 }, /* 1000 MHz */ 71 APLL_FREQ(1000, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 125, 3, 0),
96 { 0, 2 }, /* 900 MHz */ 72 APLL_FREQ(900, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 150, 4, 0),
97 { 0, 2 }, /* 800 MHz */ 73 APLL_FREQ(800, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 100, 3, 0),
98 { 0, 2 }, /* 700 MHz */ 74 APLL_FREQ(700, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 175, 3, 1),
99 { 0, 2 }, /* 600 MHz */ 75 APLL_FREQ(600, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 200, 4, 1),
100 { 0, 2 }, /* 500 MHz */ 76 APLL_FREQ(500, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 125, 3, 1),
101 { 0, 2 }, /* 400 MHz */ 77 APLL_FREQ(400, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 100, 3, 1),
102 { 0, 2 }, /* 300 MHz */ 78 APLL_FREQ(300, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 200, 4, 2),
103 { 0, 2 }, /* 200 MHz */ 79 APLL_FREQ(200, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 100, 3, 2),
104};
105
106static unsigned int exynos5_apll_pms_table[CPUFREQ_LEVEL_END] = {
107 ((425 << 16) | (6 << 8) | 0), /* 1700 MHz */
108 ((200 << 16) | (3 << 8) | 0), /* 1600 MHz */
109 ((250 << 16) | (4 << 8) | 0), /* 1500 MHz */
110 ((175 << 16) | (3 << 8) | 0), /* 1400 MHz */
111 ((325 << 16) | (6 << 8) | 0), /* 1300 MHz */
112 ((200 << 16) | (4 << 8) | 0), /* 1200 MHz */
113 ((275 << 16) | (6 << 8) | 0), /* 1100 MHz */
114 ((125 << 16) | (3 << 8) | 0), /* 1000 MHz */
115 ((150 << 16) | (4 << 8) | 0), /* 900 MHz */
116 ((100 << 16) | (3 << 8) | 0), /* 800 MHz */
117 ((175 << 16) | (3 << 8) | 1), /* 700 MHz */
118 ((200 << 16) | (4 << 8) | 1), /* 600 MHz */
119 ((125 << 16) | (3 << 8) | 1), /* 500 MHz */
120 ((100 << 16) | (3 << 8) | 1), /* 400 MHz */
121 ((200 << 16) | (4 << 8) | 2), /* 300 MHz */
122 ((100 << 16) | (3 << 8) | 2), /* 200 MHz */
123};
124
125/* ASV group voltage table */
126static const unsigned int asv_voltage_5250[CPUFREQ_LEVEL_END] = {
127 1300000, 1250000, 1225000, 1200000, 1150000,
128 1125000, 1100000, 1075000, 1050000, 1025000,
129 1012500, 1000000, 975000, 950000, 937500,
130 925000
131}; 80};
132 81
133static void set_clkdiv(unsigned int div_index) 82static void set_clkdiv(unsigned int div_index)
@@ -136,7 +85,7 @@ static void set_clkdiv(unsigned int div_index)
136 85
137 /* Change Divider - CPU0 */ 86 /* Change Divider - CPU0 */
138 87
139 tmp = exynos5250_clkdiv_table[div_index].clkdiv; 88 tmp = apll_freq_5250[div_index].clk_div_cpu0;
140 89
141 __raw_writel(tmp, EXYNOS5_CLKDIV_CPU0); 90 __raw_writel(tmp, EXYNOS5_CLKDIV_CPU0);
142 91
@@ -144,7 +93,7 @@ static void set_clkdiv(unsigned int div_index)
144 cpu_relax(); 93 cpu_relax();
145 94
146 /* Change Divider - CPU1 */ 95 /* Change Divider - CPU1 */
147 tmp = exynos5250_clkdiv_table[div_index].clkdiv1; 96 tmp = apll_freq_5250[div_index].clk_div_cpu1;
148 97
149 __raw_writel(tmp, EXYNOS5_CLKDIV_CPU1); 98 __raw_writel(tmp, EXYNOS5_CLKDIV_CPU1);
150 99
@@ -167,14 +116,14 @@ static void set_apll(unsigned int new_index,
167 } while (tmp != 0x2); 116 } while (tmp != 0x2);
168 117
169 /* 2. Set APLL Lock time */ 118 /* 2. Set APLL Lock time */
170 pdiv = ((exynos5_apll_pms_table[new_index] >> 8) & 0x3f); 119 pdiv = ((apll_freq_5250[new_index].mps >> 8) & 0x3f);
171 120
172 __raw_writel((pdiv * 250), EXYNOS5_APLL_LOCK); 121 __raw_writel((pdiv * 250), EXYNOS5_APLL_LOCK);
173 122
174 /* 3. Change PLL PMS values */ 123 /* 3. Change PLL PMS values */
175 tmp = __raw_readl(EXYNOS5_APLL_CON0); 124 tmp = __raw_readl(EXYNOS5_APLL_CON0);
176 tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0)); 125 tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
177 tmp |= exynos5_apll_pms_table[new_index]; 126 tmp |= apll_freq_5250[new_index].mps;
178 __raw_writel(tmp, EXYNOS5_APLL_CON0); 127 __raw_writel(tmp, EXYNOS5_APLL_CON0);
179 128
180 /* 4. wait_lock_time */ 129 /* 4. wait_lock_time */
@@ -196,8 +145,8 @@ static void set_apll(unsigned int new_index,
196 145
197bool exynos5250_pms_change(unsigned int old_index, unsigned int new_index) 146bool exynos5250_pms_change(unsigned int old_index, unsigned int new_index)
198{ 147{
199 unsigned int old_pm = (exynos5_apll_pms_table[old_index] >> 8); 148 unsigned int old_pm = apll_freq_5250[old_index].mps >> 8;
200 unsigned int new_pm = (exynos5_apll_pms_table[new_index] >> 8); 149 unsigned int new_pm = apll_freq_5250[new_index].mps >> 8;
201 150
202 return (old_pm == new_pm) ? 0 : 1; 151 return (old_pm == new_pm) ? 0 : 1;
203} 152}
@@ -214,7 +163,7 @@ static void exynos5250_set_frequency(unsigned int old_index,
214 /* 2. Change just s value in apll m,p,s value */ 163 /* 2. Change just s value in apll m,p,s value */
215 tmp = __raw_readl(EXYNOS5_APLL_CON0); 164 tmp = __raw_readl(EXYNOS5_APLL_CON0);
216 tmp &= ~(0x7 << 0); 165 tmp &= ~(0x7 << 0);
217 tmp |= (exynos5_apll_pms_table[new_index] & 0x7); 166 tmp |= apll_freq_5250[new_index].mps & 0x7;
218 __raw_writel(tmp, EXYNOS5_APLL_CON0); 167 __raw_writel(tmp, EXYNOS5_APLL_CON0);
219 168
220 } else { 169 } else {
@@ -229,7 +178,7 @@ static void exynos5250_set_frequency(unsigned int old_index,
229 /* 1. Change just s value in apll m,p,s value */ 178 /* 1. Change just s value in apll m,p,s value */
230 tmp = __raw_readl(EXYNOS5_APLL_CON0); 179 tmp = __raw_readl(EXYNOS5_APLL_CON0);
231 tmp &= ~(0x7 << 0); 180 tmp &= ~(0x7 << 0);
232 tmp |= (exynos5_apll_pms_table[new_index] & 0x7); 181 tmp |= apll_freq_5250[new_index].mps & 0x7;
233 __raw_writel(tmp, EXYNOS5_APLL_CON0); 182 __raw_writel(tmp, EXYNOS5_APLL_CON0);
234 /* 2. Change the system clock divider values */ 183 /* 2. Change the system clock divider values */
235 set_clkdiv(new_index); 184 set_clkdiv(new_index);
@@ -243,22 +192,10 @@ static void exynos5250_set_frequency(unsigned int old_index,
243 } 192 }
244} 193}
245 194
246static void __init set_volt_table(void)
247{
248 unsigned int i;
249
250 for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++)
251 exynos5250_volt_table[i] = asv_voltage_5250[i];
252}
253
254int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) 195int exynos5250_cpufreq_init(struct exynos_dvfs_info *info)
255{ 196{
256 int i;
257 unsigned int tmp;
258 unsigned long rate; 197 unsigned long rate;
259 198
260 set_volt_table();
261
262 cpu_clk = clk_get(NULL, "armclk"); 199 cpu_clk = clk_get(NULL, "armclk");
263 if (IS_ERR(cpu_clk)) 200 if (IS_ERR(cpu_clk))
264 return PTR_ERR(cpu_clk); 201 return PTR_ERR(cpu_clk);
@@ -277,37 +214,6 @@ int exynos5250_cpufreq_init(struct exynos_dvfs_info *info)
277 if (IS_ERR(mout_apll)) 214 if (IS_ERR(mout_apll))
278 goto err_mout_apll; 215 goto err_mout_apll;
279 216
280 for (i = L0; i < CPUFREQ_LEVEL_END; i++) {
281
282 exynos5250_clkdiv_table[i].index = i;
283
284 tmp = __raw_readl(EXYNOS5_CLKDIV_CPU0);
285
286 tmp &= ~((0x7 << 0) | (0x7 << 4) | (0x7 << 8) |
287 (0x7 << 12) | (0x7 << 16) | (0x7 << 20) |
288 (0x7 << 24) | (0x7 << 28));
289
290 tmp |= ((clkdiv_cpu0_5250[i][0] << 0) |
291 (clkdiv_cpu0_5250[i][1] << 4) |
292 (clkdiv_cpu0_5250[i][2] << 8) |
293 (clkdiv_cpu0_5250[i][3] << 12) |
294 (clkdiv_cpu0_5250[i][4] << 16) |
295 (clkdiv_cpu0_5250[i][5] << 20) |
296 (clkdiv_cpu0_5250[i][6] << 24) |
297 (clkdiv_cpu0_5250[i][7] << 28));
298
299 exynos5250_clkdiv_table[i].clkdiv = tmp;
300
301 tmp = __raw_readl(EXYNOS5_CLKDIV_CPU1);
302
303 tmp &= ~((0x7 << 0) | (0x7 << 4));
304
305 tmp |= ((clkdiv_cpu1_5250[i][0] << 0) |
306 (clkdiv_cpu1_5250[i][1] << 4));
307
308 exynos5250_clkdiv_table[i].clkdiv1 = tmp;
309 }
310
311 info->mpll_freq_khz = rate; 217 info->mpll_freq_khz = rate;
312 /* 800Mhz */ 218 /* 800Mhz */
313 info->pll_safe_idx = L9; 219 info->pll_safe_idx = L9;