diff options
Diffstat (limited to 'drivers/cpufreq/exynos5250-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/exynos5250-cpufreq.c | 168 |
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 | |||
26 | static struct clk *cpu_clk; | 24 | static struct clk *cpu_clk; |
27 | static struct clk *moutcore; | 25 | static struct clk *moutcore; |
28 | static struct clk *mout_mpll; | 26 | static struct clk *mout_mpll; |
29 | static struct clk *mout_apll; | 27 | static struct clk *mout_apll; |
30 | 28 | ||
31 | struct cpufreq_clkdiv { | 29 | static 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 | ||
37 | static unsigned int exynos5250_volt_table[CPUFREQ_LEVEL_END]; | ||
38 | |||
39 | static struct cpufreq_frequency_table exynos5250_freq_table[] = { | 36 | static 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 | ||
59 | static struct cpufreq_clkdiv exynos5250_clkdiv_table[CPUFREQ_LEVEL_END]; | 56 | static struct apll_freq apll_freq_5250[] = { |
60 | |||
61 | static 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 | |||
84 | static 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 | |||
106 | static 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 */ | ||
126 | static 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 | ||
133 | static void set_clkdiv(unsigned int div_index) | 82 | static 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 | ||
197 | bool exynos5250_pms_change(unsigned int old_index, unsigned int new_index) | 146 | bool 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 | ||
246 | static 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 | |||
254 | int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) | 195 | int 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; |