1 /*
2  * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
3  *		http://www.samsung.com
4  *
5  * EXYNOS4X12 - CPU frequency scaling support
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10 */
11 
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/err.h>
15 #include <linux/clk.h>
16 #include <linux/io.h>
17 #include <linux/slab.h>
18 #include <linux/cpufreq.h>
19 
20 #include <mach/regs-clock.h>
21 #include <mach/cpufreq.h>
22 
23 #define CPUFREQ_LEVEL_END	(L13 + 1)
24 
25 static int max_support_idx;
26 static int min_support_idx = (CPUFREQ_LEVEL_END - 1);
27 
28 static struct clk *cpu_clk;
29 static struct clk *moutcore;
30 static struct clk *mout_mpll;
31 static struct clk *mout_apll;
32 
33 struct cpufreq_clkdiv {
34 	unsigned int	index;
35 	unsigned int	clkdiv;
36 	unsigned int	clkdiv1;
37 };
38 
39 static unsigned int exynos4x12_volt_table[CPUFREQ_LEVEL_END];
40 
41 static struct cpufreq_frequency_table exynos4x12_freq_table[] = {
42 	{L0, 1500 * 1000},
43 	{L1, 1400 * 1000},
44 	{L2, 1300 * 1000},
45 	{L3, 1200 * 1000},
46 	{L4, 1100 * 1000},
47 	{L5, 1000 * 1000},
48 	{L6,  900 * 1000},
49 	{L7,  800 * 1000},
50 	{L8,  700 * 1000},
51 	{L9,  600 * 1000},
52 	{L10, 500 * 1000},
53 	{L11, 400 * 1000},
54 	{L12, 300 * 1000},
55 	{L13, 200 * 1000},
56 	{0, CPUFREQ_TABLE_END},
57 };
58 
59 static struct cpufreq_clkdiv exynos4x12_clkdiv_table[CPUFREQ_LEVEL_END];
60 
61 static unsigned int clkdiv_cpu0_4212[CPUFREQ_LEVEL_END][8] = {
62 	/*
63 	 * Clock divider value for following
64 	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
65 	 *		DIVATB, DIVPCLK_DBG, DIVAPLL, DIVCORE2 }
66 	 */
67 	/* ARM L0: 1500 MHz */
68 	{ 0, 3, 7, 0, 6, 1, 2, 0 },
69 
70 	/* ARM L1: 1400 MHz */
71 	{ 0, 3, 7, 0, 6, 1, 2, 0 },
72 
73 	/* ARM L2: 1300 MHz */
74 	{ 0, 3, 7, 0, 5, 1, 2, 0 },
75 
76 	/* ARM L3: 1200 MHz */
77 	{ 0, 3, 7, 0, 5, 1, 2, 0 },
78 
79 	/* ARM L4: 1100 MHz */
80 	{ 0, 3, 6, 0, 4, 1, 2, 0 },
81 
82 	/* ARM L5: 1000 MHz */
83 	{ 0, 2, 5, 0, 4, 1, 1, 0 },
84 
85 	/* ARM L6: 900 MHz */
86 	{ 0, 2, 5, 0, 3, 1, 1, 0 },
87 
88 	/* ARM L7: 800 MHz */
89 	{ 0, 2, 5, 0, 3, 1, 1, 0 },
90 
91 	/* ARM L8: 700 MHz */
92 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
93 
94 	/* ARM L9: 600 MHz */
95 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
96 
97 	/* ARM L10: 500 MHz */
98 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
99 
100 	/* ARM L11: 400 MHz */
101 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
102 
103 	/* ARM L12: 300 MHz */
104 	{ 0, 2, 4, 0, 2, 1, 1, 0 },
105 
106 	/* ARM L13: 200 MHz */
107 	{ 0, 1, 3, 0, 1, 1, 1, 0 },
108 };
109 
110 static unsigned int clkdiv_cpu0_4412[CPUFREQ_LEVEL_END][8] = {
111 	/*
112 	 * Clock divider value for following
113 	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
114 	 *		DIVATB, DIVPCLK_DBG, DIVAPLL, DIVCORE2 }
115 	 */
116 	/* ARM L0: 1500 MHz */
117 	{ 0, 3, 7, 0, 6, 1, 2, 0 },
118 
119 	/* ARM L1: 1400 MHz */
120 	{ 0, 3, 7, 0, 6, 1, 2, 0 },
121 
122 	/* ARM L2: 1300 MHz */
123 	{ 0, 3, 7, 0, 5, 1, 2, 0 },
124 
125 	/* ARM L3: 1200 MHz */
126 	{ 0, 3, 7, 0, 5, 1, 2, 0 },
127 
128 	/* ARM L4: 1100 MHz */
129 	{ 0, 3, 6, 0, 4, 1, 2, 0 },
130 
131 	/* ARM L5: 1000 MHz */
132 	{ 0, 2, 5, 0, 4, 1, 1, 0 },
133 
134 	/* ARM L6: 900 MHz */
135 	{ 0, 2, 5, 0, 3, 1, 1, 0 },
136 
137 	/* ARM L7: 800 MHz */
138 	{ 0, 2, 5, 0, 3, 1, 1, 0 },
139 
140 	/* ARM L8: 700 MHz */
141 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
142 
143 	/* ARM L9: 600 MHz */
144 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
145 
146 	/* ARM L10: 500 MHz */
147 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
148 
149 	/* ARM L11: 400 MHz */
150 	{ 0, 2, 4, 0, 3, 1, 1, 0 },
151 
152 	/* ARM L12: 300 MHz */
153 	{ 0, 2, 4, 0, 2, 1, 1, 0 },
154 
155 	/* ARM L13: 200 MHz */
156 	{ 0, 1, 3, 0, 1, 1, 1, 0 },
157 };
158 
159 static unsigned int clkdiv_cpu1_4212[CPUFREQ_LEVEL_END][2] = {
160 	/* Clock divider value for following
161 	 * { DIVCOPY, DIVHPM }
162 	 */
163 	/* ARM L0: 1500 MHz */
164 	{ 6, 0 },
165 
166 	/* ARM L1: 1400 MHz */
167 	{ 6, 0 },
168 
169 	/* ARM L2: 1300 MHz */
170 	{ 5, 0 },
171 
172 	/* ARM L3: 1200 MHz */
173 	{ 5, 0 },
174 
175 	/* ARM L4: 1100 MHz */
176 	{ 4, 0 },
177 
178 	/* ARM L5: 1000 MHz */
179 	{ 4, 0 },
180 
181 	/* ARM L6: 900 MHz */
182 	{ 3, 0 },
183 
184 	/* ARM L7: 800 MHz */
185 	{ 3, 0 },
186 
187 	/* ARM L8: 700 MHz */
188 	{ 3, 0 },
189 
190 	/* ARM L9: 600 MHz */
191 	{ 3, 0 },
192 
193 	/* ARM L10: 500 MHz */
194 	{ 3, 0 },
195 
196 	/* ARM L11: 400 MHz */
197 	{ 3, 0 },
198 
199 	/* ARM L12: 300 MHz */
200 	{ 3, 0 },
201 
202 	/* ARM L13: 200 MHz */
203 	{ 3, 0 },
204 };
205 
206 static unsigned int clkdiv_cpu1_4412[CPUFREQ_LEVEL_END][3] = {
207 	/* Clock divider value for following
208 	 * { DIVCOPY, DIVHPM, DIVCORES }
209 	 */
210 	/* ARM L0: 1500 MHz */
211 	{ 6, 0, 7 },
212 
213 	/* ARM L1: 1400 MHz */
214 	{ 6, 0, 6 },
215 
216 	/* ARM L2: 1300 MHz */
217 	{ 5, 0, 6 },
218 
219 	/* ARM L3: 1200 MHz */
220 	{ 5, 0, 5 },
221 
222 	/* ARM L4: 1100 MHz */
223 	{ 4, 0, 5 },
224 
225 	/* ARM L5: 1000 MHz */
226 	{ 4, 0, 4 },
227 
228 	/* ARM L6: 900 MHz */
229 	{ 3, 0, 4 },
230 
231 	/* ARM L7: 800 MHz */
232 	{ 3, 0, 3 },
233 
234 	/* ARM L8: 700 MHz */
235 	{ 3, 0, 3 },
236 
237 	/* ARM L9: 600 MHz */
238 	{ 3, 0, 2 },
239 
240 	/* ARM L10: 500 MHz */
241 	{ 3, 0, 2 },
242 
243 	/* ARM L11: 400 MHz */
244 	{ 3, 0, 1 },
245 
246 	/* ARM L12: 300 MHz */
247 	{ 3, 0, 1 },
248 
249 	/* ARM L13: 200 MHz */
250 	{ 3, 0, 0 },
251 };
252 
253 static unsigned int exynos4x12_apll_pms_table[CPUFREQ_LEVEL_END] = {
254 	/* APLL FOUT L0: 1500 MHz */
255 	((250 << 16) | (4 << 8) | (0x0)),
256 
257 	/* APLL FOUT L1: 1400 MHz */
258 	((175 << 16) | (3 << 8) | (0x0)),
259 
260 	/* APLL FOUT L2: 1300 MHz */
261 	((325 << 16) | (6 << 8) | (0x0)),
262 
263 	/* APLL FOUT L3: 1200 MHz */
264 	((200 << 16) | (4 << 8) | (0x0)),
265 
266 	/* APLL FOUT L4: 1100 MHz */
267 	((275 << 16) | (6 << 8) | (0x0)),
268 
269 	/* APLL FOUT L5: 1000 MHz */
270 	((125 << 16) | (3 << 8) | (0x0)),
271 
272 	/* APLL FOUT L6: 900 MHz */
273 	((150 << 16) | (4 << 8) | (0x0)),
274 
275 	/* APLL FOUT L7: 800 MHz */
276 	((100 << 16) | (3 << 8) | (0x0)),
277 
278 	/* APLL FOUT L8: 700 MHz */
279 	((175 << 16) | (3 << 8) | (0x1)),
280 
281 	/* APLL FOUT L9: 600 MHz */
282 	((200 << 16) | (4 << 8) | (0x1)),
283 
284 	/* APLL FOUT L10: 500 MHz */
285 	((125 << 16) | (3 << 8) | (0x1)),
286 
287 	/* APLL FOUT L11 400 MHz */
288 	((100 << 16) | (3 << 8) | (0x1)),
289 
290 	/* APLL FOUT L12: 300 MHz */
291 	((200 << 16) | (4 << 8) | (0x2)),
292 
293 	/* APLL FOUT L13: 200 MHz */
294 	((100 << 16) | (3 << 8) | (0x2)),
295 };
296 
297 static const unsigned int asv_voltage_4x12[CPUFREQ_LEVEL_END] = {
298 	1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500,
299 	1000000,  987500,  975000,  950000,  925000,  900000,  900000
300 };
301 
exynos4x12_set_clkdiv(unsigned int div_index)302 static void exynos4x12_set_clkdiv(unsigned int div_index)
303 {
304 	unsigned int tmp;
305 	unsigned int stat_cpu1;
306 
307 	/* Change Divider - CPU0 */
308 
309 	tmp = exynos4x12_clkdiv_table[div_index].clkdiv;
310 
311 	__raw_writel(tmp, EXYNOS4_CLKDIV_CPU);
312 
313 	while (__raw_readl(EXYNOS4_CLKDIV_STATCPU) & 0x11111111)
314 		cpu_relax();
315 
316 	/* Change Divider - CPU1 */
317 	tmp = exynos4x12_clkdiv_table[div_index].clkdiv1;
318 
319 	__raw_writel(tmp, EXYNOS4_CLKDIV_CPU1);
320 	if (soc_is_exynos4212())
321 		stat_cpu1 = 0x11;
322 	else
323 		stat_cpu1 = 0x111;
324 
325 	while (__raw_readl(EXYNOS4_CLKDIV_STATCPU1) & stat_cpu1)
326 		cpu_relax();
327 }
328 
exynos4x12_set_apll(unsigned int index)329 static void exynos4x12_set_apll(unsigned int index)
330 {
331 	unsigned int tmp, pdiv;
332 
333 	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
334 	clk_set_parent(moutcore, mout_mpll);
335 
336 	do {
337 		cpu_relax();
338 		tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU)
339 			>> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT);
340 		tmp &= 0x7;
341 	} while (tmp != 0x2);
342 
343 	/* 2. Set APLL Lock time */
344 	pdiv = ((exynos4x12_apll_pms_table[index] >> 8) & 0x3f);
345 
346 	__raw_writel((pdiv * 250), EXYNOS4_APLL_LOCK);
347 
348 	/* 3. Change PLL PMS values */
349 	tmp = __raw_readl(EXYNOS4_APLL_CON0);
350 	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
351 	tmp |= exynos4x12_apll_pms_table[index];
352 	__raw_writel(tmp, EXYNOS4_APLL_CON0);
353 
354 	/* 4. wait_lock_time */
355 	do {
356 		cpu_relax();
357 		tmp = __raw_readl(EXYNOS4_APLL_CON0);
358 	} while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));
359 
360 	/* 5. MUX_CORE_SEL = APLL */
361 	clk_set_parent(moutcore, mout_apll);
362 
363 	do {
364 		cpu_relax();
365 		tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU);
366 		tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK;
367 	} while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
368 }
369 
exynos4x12_pms_change(unsigned int old_index,unsigned int new_index)370 bool exynos4x12_pms_change(unsigned int old_index, unsigned int new_index)
371 {
372 	unsigned int old_pm = exynos4x12_apll_pms_table[old_index] >> 8;
373 	unsigned int new_pm = exynos4x12_apll_pms_table[new_index] >> 8;
374 
375 	return (old_pm == new_pm) ? 0 : 1;
376 }
377 
exynos4x12_set_frequency(unsigned int old_index,unsigned int new_index)378 static void exynos4x12_set_frequency(unsigned int old_index,
379 				  unsigned int new_index)
380 {
381 	unsigned int tmp;
382 
383 	if (old_index > new_index) {
384 		if (!exynos4x12_pms_change(old_index, new_index)) {
385 			/* 1. Change the system clock divider values */
386 			exynos4x12_set_clkdiv(new_index);
387 			/* 2. Change just s value in apll m,p,s value */
388 			tmp = __raw_readl(EXYNOS4_APLL_CON0);
389 			tmp &= ~(0x7 << 0);
390 			tmp |= (exynos4x12_apll_pms_table[new_index] & 0x7);
391 			__raw_writel(tmp, EXYNOS4_APLL_CON0);
392 
393 		} else {
394 			/* Clock Configuration Procedure */
395 			/* 1. Change the system clock divider values */
396 			exynos4x12_set_clkdiv(new_index);
397 			/* 2. Change the apll m,p,s value */
398 			exynos4x12_set_apll(new_index);
399 		}
400 	} else if (old_index < new_index) {
401 		if (!exynos4x12_pms_change(old_index, new_index)) {
402 			/* 1. Change just s value in apll m,p,s value */
403 			tmp = __raw_readl(EXYNOS4_APLL_CON0);
404 			tmp &= ~(0x7 << 0);
405 			tmp |= (exynos4x12_apll_pms_table[new_index] & 0x7);
406 			__raw_writel(tmp, EXYNOS4_APLL_CON0);
407 			/* 2. Change the system clock divider values */
408 			exynos4x12_set_clkdiv(new_index);
409 		} else {
410 			/* Clock Configuration Procedure */
411 			/* 1. Change the apll m,p,s value */
412 			exynos4x12_set_apll(new_index);
413 			/* 2. Change the system clock divider values */
414 			exynos4x12_set_clkdiv(new_index);
415 		}
416 	}
417 }
418 
set_volt_table(void)419 static void __init set_volt_table(void)
420 {
421 	unsigned int i;
422 
423 	max_support_idx = L1;
424 
425 	/* Not supported */
426 	exynos4x12_freq_table[L0].frequency = CPUFREQ_ENTRY_INVALID;
427 
428 	for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++)
429 		exynos4x12_volt_table[i] = asv_voltage_4x12[i];
430 }
431 
exynos4x12_cpufreq_init(struct exynos_dvfs_info * info)432 int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
433 {
434 	int i;
435 	unsigned int tmp;
436 	unsigned long rate;
437 
438 	set_volt_table();
439 
440 	cpu_clk = clk_get(NULL, "armclk");
441 	if (IS_ERR(cpu_clk))
442 		return PTR_ERR(cpu_clk);
443 
444 	moutcore = clk_get(NULL, "moutcore");
445 	if (IS_ERR(moutcore))
446 		goto err_moutcore;
447 
448 	mout_mpll = clk_get(NULL, "mout_mpll");
449 	if (IS_ERR(mout_mpll))
450 		goto err_mout_mpll;
451 
452 	rate = clk_get_rate(mout_mpll) / 1000;
453 
454 	mout_apll = clk_get(NULL, "mout_apll");
455 	if (IS_ERR(mout_apll))
456 		goto err_mout_apll;
457 
458 	for (i = L0; i <  CPUFREQ_LEVEL_END; i++) {
459 
460 		exynos4x12_clkdiv_table[i].index = i;
461 
462 		tmp = __raw_readl(EXYNOS4_CLKDIV_CPU);
463 
464 		tmp &= ~(EXYNOS4_CLKDIV_CPU0_CORE_MASK |
465 			EXYNOS4_CLKDIV_CPU0_COREM0_MASK |
466 			EXYNOS4_CLKDIV_CPU0_COREM1_MASK |
467 			EXYNOS4_CLKDIV_CPU0_PERIPH_MASK |
468 			EXYNOS4_CLKDIV_CPU0_ATB_MASK |
469 			EXYNOS4_CLKDIV_CPU0_PCLKDBG_MASK |
470 			EXYNOS4_CLKDIV_CPU0_APLL_MASK);
471 
472 		if (soc_is_exynos4212()) {
473 			tmp |= ((clkdiv_cpu0_4212[i][0] << EXYNOS4_CLKDIV_CPU0_CORE_SHIFT) |
474 				(clkdiv_cpu0_4212[i][1] << EXYNOS4_CLKDIV_CPU0_COREM0_SHIFT) |
475 				(clkdiv_cpu0_4212[i][2] << EXYNOS4_CLKDIV_CPU0_COREM1_SHIFT) |
476 				(clkdiv_cpu0_4212[i][3] << EXYNOS4_CLKDIV_CPU0_PERIPH_SHIFT) |
477 				(clkdiv_cpu0_4212[i][4] << EXYNOS4_CLKDIV_CPU0_ATB_SHIFT) |
478 				(clkdiv_cpu0_4212[i][5] << EXYNOS4_CLKDIV_CPU0_PCLKDBG_SHIFT) |
479 				(clkdiv_cpu0_4212[i][6] << EXYNOS4_CLKDIV_CPU0_APLL_SHIFT));
480 		} else {
481 			tmp &= ~EXYNOS4_CLKDIV_CPU0_CORE2_MASK;
482 
483 			tmp |= ((clkdiv_cpu0_4412[i][0] << EXYNOS4_CLKDIV_CPU0_CORE_SHIFT) |
484 				(clkdiv_cpu0_4412[i][1] << EXYNOS4_CLKDIV_CPU0_COREM0_SHIFT) |
485 				(clkdiv_cpu0_4412[i][2] << EXYNOS4_CLKDIV_CPU0_COREM1_SHIFT) |
486 				(clkdiv_cpu0_4412[i][3] << EXYNOS4_CLKDIV_CPU0_PERIPH_SHIFT) |
487 				(clkdiv_cpu0_4412[i][4] << EXYNOS4_CLKDIV_CPU0_ATB_SHIFT) |
488 				(clkdiv_cpu0_4412[i][5] << EXYNOS4_CLKDIV_CPU0_PCLKDBG_SHIFT) |
489 				(clkdiv_cpu0_4412[i][6] << EXYNOS4_CLKDIV_CPU0_APLL_SHIFT) |
490 				(clkdiv_cpu0_4412[i][7] << EXYNOS4_CLKDIV_CPU0_CORE2_SHIFT));
491 		}
492 
493 		exynos4x12_clkdiv_table[i].clkdiv = tmp;
494 
495 		tmp = __raw_readl(EXYNOS4_CLKDIV_CPU1);
496 
497 		if (soc_is_exynos4212()) {
498 			tmp &= ~(EXYNOS4_CLKDIV_CPU1_COPY_MASK |
499 				EXYNOS4_CLKDIV_CPU1_HPM_MASK);
500 			tmp |= ((clkdiv_cpu1_4212[i][0] << EXYNOS4_CLKDIV_CPU1_COPY_SHIFT) |
501 				(clkdiv_cpu1_4212[i][1] << EXYNOS4_CLKDIV_CPU1_HPM_SHIFT));
502 		} else {
503 			tmp &= ~(EXYNOS4_CLKDIV_CPU1_COPY_MASK |
504 				EXYNOS4_CLKDIV_CPU1_HPM_MASK |
505 				EXYNOS4_CLKDIV_CPU1_CORES_MASK);
506 			tmp |= ((clkdiv_cpu1_4412[i][0] << EXYNOS4_CLKDIV_CPU1_COPY_SHIFT) |
507 				(clkdiv_cpu1_4412[i][1] << EXYNOS4_CLKDIV_CPU1_HPM_SHIFT) |
508 				(clkdiv_cpu1_4412[i][2] << EXYNOS4_CLKDIV_CPU1_CORES_SHIFT));
509 		}
510 		exynos4x12_clkdiv_table[i].clkdiv1 = tmp;
511 	}
512 
513 	info->mpll_freq_khz = rate;
514 	info->pm_lock_idx = L5;
515 	info->pll_safe_idx = L7;
516 	info->max_support_idx = max_support_idx;
517 	info->min_support_idx = min_support_idx;
518 	info->cpu_clk = cpu_clk;
519 	info->volt_table = exynos4x12_volt_table;
520 	info->freq_table = exynos4x12_freq_table;
521 	info->set_freq = exynos4x12_set_frequency;
522 	info->need_apll_change = exynos4x12_pms_change;
523 
524 	return 0;
525 
526 err_mout_apll:
527 	clk_put(mout_mpll);
528 err_mout_mpll:
529 	clk_put(moutcore);
530 err_moutcore:
531 	clk_put(cpu_clk);
532 
533 	pr_debug("%s: failed initialization\n", __func__);
534 	return -EINVAL;
535 }
536 EXPORT_SYMBOL(exynos4x12_cpufreq_init);
537