1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2010 Samsung Electronics
4 * Minkyu Kang <mk7.kang@samsung.com>
5 */
6
7#include <common.h>
8#include <clock_legacy.h>
9#include <log.h>
10#include <asm/io.h>
11#include <asm/arch/clock.h>
12#include <asm/arch/clk.h>
13#include <asm/arch/periph.h>
14
15#define PLL_DIV_1024	1024
16#define PLL_DIV_65535	65535
17#define PLL_DIV_65536	65536
18/* *
19 * This structure is to store the src bit, div bit and prediv bit
20 * positions of the peripheral clocks of the src and div registers
21 */
22struct clk_bit_info {
23	enum periph_id id;
24	int32_t src_mask;
25	int32_t div_mask;
26	int32_t prediv_mask;
27	int8_t src_bit;
28	int8_t div_bit;
29	int8_t prediv_bit;
30};
31
32static struct clk_bit_info exynos5_bit_info[] = {
33	/* periph id		s_mask	d_mask	p_mask	s_bit	d_bit	p_bit */
34	{PERIPH_ID_UART0,	0xf,	0xf,	-1,	0,	0,	-1},
35	{PERIPH_ID_UART1,	0xf,	0xf,	-1,	4,	4,	-1},
36	{PERIPH_ID_UART2,	0xf,	0xf,	-1,	8,	8,	-1},
37	{PERIPH_ID_UART3,	0xf,	0xf,	-1,	12,	12,	-1},
38	{PERIPH_ID_I2C0,	-1,	0x7,	0x7,	-1,	24,	0},
39	{PERIPH_ID_I2C1,	-1,	0x7,	0x7,	-1,	24,	0},
40	{PERIPH_ID_I2C2,	-1,	0x7,	0x7,	-1,	24,	0},
41	{PERIPH_ID_I2C3,	-1,	0x7,	0x7,	-1,	24,	0},
42	{PERIPH_ID_I2C4,	-1,	0x7,	0x7,	-1,	24,	0},
43	{PERIPH_ID_I2C5,	-1,	0x7,	0x7,	-1,	24,	0},
44	{PERIPH_ID_I2C6,	-1,	0x7,	0x7,	-1,	24,	0},
45	{PERIPH_ID_I2C7,	-1,	0x7,	0x7,	-1,	24,	0},
46	{PERIPH_ID_SPI0,	0xf,	0xf,	0xff,	16,	0,	8},
47	{PERIPH_ID_SPI1,	0xf,	0xf,	0xff,	20,	16,	24},
48	{PERIPH_ID_SPI2,	0xf,	0xf,	0xff,	24,	0,	8},
49	{PERIPH_ID_SDMMC0,	0xf,	0xf,	0xff,	0,	0,	8},
50	{PERIPH_ID_SDMMC1,	0xf,	0xf,	0xff,	4,	16,	24},
51	{PERIPH_ID_SDMMC2,	0xf,	0xf,	0xff,	8,	0,	8},
52	{PERIPH_ID_SDMMC3,	0xf,	0xf,	0xff,	12,	16,	24},
53	{PERIPH_ID_I2S0,	0xf,	0xf,	0xff,	0,	0,	4},
54	{PERIPH_ID_I2S1,	0xf,	0xf,	0xff,	4,	12,	16},
55	{PERIPH_ID_SPI3,	0xf,	0xf,	0xff,	0,	0,	4},
56	{PERIPH_ID_SPI4,	0xf,	0xf,	0xff,	4,	12,	16},
57	{PERIPH_ID_SDMMC4,	0xf,	0xf,	0xff,	16,	0,	8},
58	{PERIPH_ID_PWM0,	0xf,	0xf,	-1,	24,	0,	-1},
59	{PERIPH_ID_PWM1,	0xf,	0xf,	-1,	24,	0,	-1},
60	{PERIPH_ID_PWM2,	0xf,	0xf,	-1,	24,	0,	-1},
61	{PERIPH_ID_PWM3,	0xf,	0xf,	-1,	24,	0,	-1},
62	{PERIPH_ID_PWM4,	0xf,	0xf,	-1,	24,	0,	-1},
63
64	{PERIPH_ID_NONE,	-1,	-1,	-1,	-1,	-1,	-1},
65};
66
67static struct clk_bit_info exynos542x_bit_info[] = {
68	/* periph id		s_mask	d_mask	p_mask	s_bit	d_bit	p_bit */
69	{PERIPH_ID_UART0,	0xf,	0xf,	-1,	4,	8,	-1},
70	{PERIPH_ID_UART1,	0xf,	0xf,	-1,	8,	12,	-1},
71	{PERIPH_ID_UART2,	0xf,	0xf,	-1,	12,	16,	-1},
72	{PERIPH_ID_UART3,	0xf,	0xf,	-1,	16,	20,	-1},
73	{PERIPH_ID_I2C0,	-1,	0x3f,	-1,	-1,	8,	-1},
74	{PERIPH_ID_I2C1,	-1,	0x3f,	-1,	-1,	8,	-1},
75	{PERIPH_ID_I2C2,	-1,	0x3f,	-1,	-1,	8,	-1},
76	{PERIPH_ID_I2C3,	-1,	0x3f,	-1,	-1,	8,	-1},
77	{PERIPH_ID_I2C4,	-1,	0x3f,	-1,	-1,	8,	-1},
78	{PERIPH_ID_I2C5,	-1,	0x3f,	-1,	-1,	8,	-1},
79	{PERIPH_ID_I2C6,	-1,	0x3f,	-1,	-1,	8,	-1},
80	{PERIPH_ID_I2C7,	-1,	0x3f,	-1,	-1,	8,	-1},
81	{PERIPH_ID_SPI0,	0xf,	0xf,	0xff,	20,	20,	8},
82	{PERIPH_ID_SPI1,	0xf,	0xf,	0xff,	24,	24,	16},
83	{PERIPH_ID_SPI2,	0xf,	0xf,	0xff,	28,	28,	24},
84	{PERIPH_ID_SDMMC0,	0x7,	0x3ff,	-1,	8,	0,	-1},
85	{PERIPH_ID_SDMMC1,	0x7,	0x3ff,	-1,	12,	10,	-1},
86	{PERIPH_ID_SDMMC2,	0x7,	0x3ff,	-1,	16,	20,	-1},
87	{PERIPH_ID_I2C8,	-1,	0x3f,	-1,	-1,	8,	-1},
88	{PERIPH_ID_I2C9,	-1,	0x3f,	-1,	-1,	8,	-1},
89	{PERIPH_ID_I2S0,	0xf,	0xf,	0xff,	0,	0,	4},
90	{PERIPH_ID_I2S1,	0xf,	0xf,	0xff,	4,	12,	16},
91	{PERIPH_ID_SPI3,	0xf,	0xf,	0xff,	12,	16,	0},
92	{PERIPH_ID_SPI4,	0xf,	0xf,	0xff,	16,	20,	8},
93	{PERIPH_ID_PWM0,	0xf,	0xf,	-1,	24,	28,	-1},
94	{PERIPH_ID_PWM1,	0xf,	0xf,	-1,	24,	28,	-1},
95	{PERIPH_ID_PWM2,	0xf,	0xf,	-1,	24,	28,	-1},
96	{PERIPH_ID_PWM3,	0xf,	0xf,	-1,	24,	28,	-1},
97	{PERIPH_ID_PWM4,	0xf,	0xf,	-1,	24,	28,	-1},
98	{PERIPH_ID_I2C10,	-1,	0x3f,	-1,	-1,	8,	-1},
99
100	{PERIPH_ID_NONE,	-1,	-1,	-1,	-1,	-1,	-1},
101};
102
103/* Epll Clock division values to achive different frequency output */
104static struct set_epll_con_val exynos5_epll_div[] = {
105	{ 192000000, 0, 48, 3, 1, 0 },
106	{ 180000000, 0, 45, 3, 1, 0 },
107	{  73728000, 1, 73, 3, 3, 47710 },
108	{  67737600, 1, 90, 4, 3, 20762 },
109	{  49152000, 0, 49, 3, 3, 9961 },
110	{  45158400, 0, 45, 3, 3, 10381 },
111	{ 180633600, 0, 45, 3, 1, 10381 }
112};
113
114/* exynos: return pll clock frequency */
115static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
116{
117	unsigned long m, p, s = 0, mask, fout;
118	unsigned int div;
119	unsigned int freq;
120	/*
121	 * APLL_CON: MIDV [25:16]
122	 * MPLL_CON: MIDV [25:16]
123	 * EPLL_CON: MIDV [24:16]
124	 * VPLL_CON: MIDV [24:16]
125	 * BPLL_CON: MIDV [25:16]: Exynos5
126	 */
127	if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL ||
128	    pllreg == SPLL)
129		mask = 0x3ff;
130	else
131		mask = 0x1ff;
132
133	m = (r >> 16) & mask;
134
135	/* PDIV [13:8] */
136	p = (r >> 8) & 0x3f;
137	/* SDIV [2:0] */
138	s = r & 0x7;
139
140	freq = get_board_sys_clk();
141
142	if (pllreg == EPLL || pllreg == RPLL) {
143		k = k & 0xffff;
144		/* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
145		fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
146	} else if (pllreg == VPLL) {
147		k = k & 0xfff;
148
149		/*
150		 * Exynos4210
151		 * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
152		 *
153		 * Exynos4412
154		 * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
155		 *
156		 * Exynos5250
157		 * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
158		 */
159		if (proid_is_exynos4210())
160			div = PLL_DIV_1024;
161		else if (proid_is_exynos4412())
162			div = PLL_DIV_65535;
163		else if (proid_is_exynos5250() || proid_is_exynos5420() ||
164			 proid_is_exynos5422())
165			div = PLL_DIV_65536;
166		else
167			return 0;
168
169		fout = (m + k / div) * (freq / (p * (1 << s)));
170	} else {
171		/*
172		 * Exynos4412 / Exynos5250
173		 * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
174		 *
175		 * Exynos4210
176		 * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
177		 */
178		if (proid_is_exynos4210())
179			fout = m * (freq / (p * (1 << (s - 1))));
180		else
181			fout = m * (freq / (p * (1 << s)));
182	}
183	return fout;
184}
185
186/* exynos4: return pll clock frequency */
187static unsigned long exynos4_get_pll_clk(int pllreg)
188{
189	struct exynos4_clock *clk =
190		(struct exynos4_clock *)samsung_get_base_clock();
191	unsigned long r, k = 0;
192
193	switch (pllreg) {
194	case APLL:
195		r = readl(&clk->apll_con0);
196		break;
197	case MPLL:
198		r = readl(&clk->mpll_con0);
199		break;
200	case EPLL:
201		r = readl(&clk->epll_con0);
202		k = readl(&clk->epll_con1);
203		break;
204	case VPLL:
205		r = readl(&clk->vpll_con0);
206		k = readl(&clk->vpll_con1);
207		break;
208	default:
209		printf("Unsupported PLL (%d)\n", pllreg);
210		return 0;
211	}
212
213	return exynos_get_pll_clk(pllreg, r, k);
214}
215
216/* exynos4x12: return pll clock frequency */
217static unsigned long exynos4x12_get_pll_clk(int pllreg)
218{
219	struct exynos4x12_clock *clk =
220		(struct exynos4x12_clock *)samsung_get_base_clock();
221	unsigned long r, k = 0;
222
223	switch (pllreg) {
224	case APLL:
225		r = readl(&clk->apll_con0);
226		break;
227	case MPLL:
228		r = readl(&clk->mpll_con0);
229		break;
230	case EPLL:
231		r = readl(&clk->epll_con0);
232		k = readl(&clk->epll_con1);
233		break;
234	case VPLL:
235		r = readl(&clk->vpll_con0);
236		k = readl(&clk->vpll_con1);
237		break;
238	default:
239		printf("Unsupported PLL (%d)\n", pllreg);
240		return 0;
241	}
242
243	return exynos_get_pll_clk(pllreg, r, k);
244}
245
246/* exynos5: return pll clock frequency */
247static unsigned long exynos5_get_pll_clk(int pllreg)
248{
249	struct exynos5_clock *clk =
250		(struct exynos5_clock *)samsung_get_base_clock();
251	unsigned long r, k = 0, fout;
252	unsigned int pll_div2_sel, fout_sel;
253
254	switch (pllreg) {
255	case APLL:
256		r = readl(&clk->apll_con0);
257		break;
258	case MPLL:
259		r = readl(&clk->mpll_con0);
260		break;
261	case EPLL:
262		r = readl(&clk->epll_con0);
263		k = readl(&clk->epll_con1);
264		break;
265	case VPLL:
266		r = readl(&clk->vpll_con0);
267		k = readl(&clk->vpll_con1);
268		break;
269	case BPLL:
270		r = readl(&clk->bpll_con0);
271		break;
272	default:
273		printf("Unsupported PLL (%d)\n", pllreg);
274		return 0;
275	}
276
277	fout = exynos_get_pll_clk(pllreg, r, k);
278
279	/* According to the user manual, in EVT1 MPLL and BPLL always gives
280	 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
281	if (pllreg == MPLL || pllreg == BPLL) {
282		pll_div2_sel = readl(&clk->pll_div2_sel);
283
284		switch (pllreg) {
285		case MPLL:
286			fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
287					& MPLL_FOUT_SEL_MASK;
288			break;
289		case BPLL:
290			fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
291					& BPLL_FOUT_SEL_MASK;
292			break;
293		default:
294			fout_sel = -1;
295			break;
296		}
297
298		if (fout_sel == 0)
299			fout /= 2;
300	}
301
302	return fout;
303}
304
305/* exynos542x: return pll clock frequency */
306static unsigned long exynos542x_get_pll_clk(int pllreg)
307{
308	struct exynos5420_clock *clk =
309		(struct exynos5420_clock *)samsung_get_base_clock();
310	unsigned long r, k = 0;
311
312	switch (pllreg) {
313	case APLL:
314		r = readl(&clk->apll_con0);
315		break;
316	case MPLL:
317		r = readl(&clk->mpll_con0);
318		break;
319	case EPLL:
320		r = readl(&clk->epll_con0);
321		k = readl(&clk->epll_con1);
322		break;
323	case VPLL:
324		r = readl(&clk->vpll_con0);
325		k = readl(&clk->vpll_con1);
326		break;
327	case BPLL:
328		r = readl(&clk->bpll_con0);
329		break;
330	case RPLL:
331		r = readl(&clk->rpll_con0);
332		k = readl(&clk->rpll_con1);
333		break;
334	case SPLL:
335		r = readl(&clk->spll_con0);
336		break;
337	default:
338		printf("Unsupported PLL (%d)\n", pllreg);
339		return 0;
340	}
341
342	return exynos_get_pll_clk(pllreg, r, k);
343}
344
345static struct clk_bit_info *get_clk_bit_info(int peripheral)
346{
347	int i;
348	struct clk_bit_info *info;
349
350	if (proid_is_exynos542x())
351		info = exynos542x_bit_info;
352	else
353		info = exynos5_bit_info;
354
355	for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
356		if (info[i].id == peripheral)
357			break;
358	}
359
360	if (info[i].id == PERIPH_ID_NONE)
361		debug("ERROR: Peripheral ID %d not found\n", peripheral);
362
363	return &info[i];
364}
365
366static unsigned long exynos5_get_periph_rate(int peripheral)
367{
368	struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
369	unsigned long sclk = 0;
370	unsigned int src = 0, div = 0, sub_div = 0;
371	struct exynos5_clock *clk =
372			(struct exynos5_clock *)samsung_get_base_clock();
373
374	switch (peripheral) {
375	case PERIPH_ID_UART0:
376	case PERIPH_ID_UART1:
377	case PERIPH_ID_UART2:
378	case PERIPH_ID_UART3:
379		src = readl(&clk->src_peric0);
380		div = readl(&clk->div_peric0);
381		break;
382	case PERIPH_ID_PWM0:
383	case PERIPH_ID_PWM1:
384	case PERIPH_ID_PWM2:
385	case PERIPH_ID_PWM3:
386	case PERIPH_ID_PWM4:
387		src = readl(&clk->src_peric0);
388		div = readl(&clk->div_peric3);
389		break;
390	case PERIPH_ID_I2S0:
391		src = readl(&clk->src_mau);
392		div = sub_div = readl(&clk->div_mau);
393	case PERIPH_ID_SPI0:
394	case PERIPH_ID_SPI1:
395		src = readl(&clk->src_peric1);
396		div = sub_div = readl(&clk->div_peric1);
397		break;
398	case PERIPH_ID_SPI2:
399		src = readl(&clk->src_peric1);
400		div = sub_div = readl(&clk->div_peric2);
401		break;
402	case PERIPH_ID_SPI3:
403	case PERIPH_ID_SPI4:
404		src = readl(&clk->sclk_src_isp);
405		div = sub_div = readl(&clk->sclk_div_isp);
406		break;
407	case PERIPH_ID_SDMMC0:
408	case PERIPH_ID_SDMMC1:
409		src = readl(&clk->src_fsys);
410		div = sub_div = readl(&clk->div_fsys1);
411		break;
412	case PERIPH_ID_SDMMC2:
413	case PERIPH_ID_SDMMC3:
414		src = readl(&clk->src_fsys);
415		div = sub_div = readl(&clk->div_fsys2);
416		break;
417	case PERIPH_ID_I2C0:
418	case PERIPH_ID_I2C1:
419	case PERIPH_ID_I2C2:
420	case PERIPH_ID_I2C3:
421	case PERIPH_ID_I2C4:
422	case PERIPH_ID_I2C5:
423	case PERIPH_ID_I2C6:
424	case PERIPH_ID_I2C7:
425		src = EXYNOS_SRC_MPLL;
426		div = readl(&clk->div_top1);
427		sub_div = readl(&clk->div_top0);
428		break;
429	default:
430		debug("%s: invalid peripheral %d", __func__, peripheral);
431		return -1;
432	};
433
434	if (bit_info->src_bit >= 0)
435		src = (src >> bit_info->src_bit) & bit_info->src_mask;
436
437	switch (src) {
438	case EXYNOS_SRC_MPLL:
439		sclk = exynos5_get_pll_clk(MPLL);
440		break;
441	case EXYNOS_SRC_EPLL:
442		sclk = exynos5_get_pll_clk(EPLL);
443		break;
444	case EXYNOS_SRC_VPLL:
445		sclk = exynos5_get_pll_clk(VPLL);
446		break;
447	default:
448		debug("%s: EXYNOS_SRC %d not supported\n", __func__, src);
449		return 0;
450	}
451
452	/* Clock divider ratio for this peripheral */
453	if (bit_info->div_bit >= 0)
454		div = (div >> bit_info->div_bit) & bit_info->div_mask;
455
456	/* Clock pre-divider ratio for this peripheral */
457	if (bit_info->prediv_bit >= 0)
458		sub_div = (sub_div >> bit_info->prediv_bit)
459			  & bit_info->prediv_mask;
460
461	/* Calculate and return required clock rate */
462	return (sclk / (div + 1)) / (sub_div + 1);
463}
464
465static unsigned long exynos542x_get_periph_rate(int peripheral)
466{
467	struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
468	unsigned long sclk = 0;
469	unsigned int src = 0, div = 0, sub_div = 0;
470	struct exynos5420_clock *clk =
471			(struct exynos5420_clock *)samsung_get_base_clock();
472
473	switch (peripheral) {
474	case PERIPH_ID_UART0:
475	case PERIPH_ID_UART1:
476	case PERIPH_ID_UART2:
477	case PERIPH_ID_UART3:
478	case PERIPH_ID_PWM0:
479	case PERIPH_ID_PWM1:
480	case PERIPH_ID_PWM2:
481	case PERIPH_ID_PWM3:
482	case PERIPH_ID_PWM4:
483		src = readl(&clk->src_peric0);
484		div = readl(&clk->div_peric0);
485		break;
486	case PERIPH_ID_SPI0:
487	case PERIPH_ID_SPI1:
488	case PERIPH_ID_SPI2:
489		src = readl(&clk->src_peric1);
490		div = readl(&clk->div_peric1);
491		sub_div = readl(&clk->div_peric4);
492		break;
493	case PERIPH_ID_SPI3:
494	case PERIPH_ID_SPI4:
495		src = readl(&clk->src_isp);
496		div = readl(&clk->div_isp1);
497		sub_div = readl(&clk->div_isp1);
498		break;
499	case PERIPH_ID_SDMMC0:
500	case PERIPH_ID_SDMMC1:
501	case PERIPH_ID_SDMMC2:
502	case PERIPH_ID_SDMMC3:
503		src = readl(&clk->src_fsys);
504		div = readl(&clk->div_fsys1);
505		break;
506	case PERIPH_ID_I2C0:
507	case PERIPH_ID_I2C1:
508	case PERIPH_ID_I2C2:
509	case PERIPH_ID_I2C3:
510	case PERIPH_ID_I2C4:
511	case PERIPH_ID_I2C5:
512	case PERIPH_ID_I2C6:
513	case PERIPH_ID_I2C7:
514	case PERIPH_ID_I2C8:
515	case PERIPH_ID_I2C9:
516	case PERIPH_ID_I2C10:
517		src = EXYNOS542X_SRC_MPLL;
518		div = readl(&clk->div_top1);
519		break;
520	default:
521		debug("%s: invalid peripheral %d", __func__, peripheral);
522		return -1;
523	};
524
525	if (bit_info->src_bit >= 0)
526		src = (src >> bit_info->src_bit) & bit_info->src_mask;
527
528	switch (src) {
529	case EXYNOS542X_SRC_MPLL:
530		sclk = exynos542x_get_pll_clk(MPLL);
531		break;
532	case EXYNOS542X_SRC_SPLL:
533		sclk = exynos542x_get_pll_clk(SPLL);
534		break;
535	case EXYNOS542X_SRC_EPLL:
536		sclk = exynos542x_get_pll_clk(EPLL);
537		break;
538	case EXYNOS542X_SRC_RPLL:
539		sclk = exynos542x_get_pll_clk(RPLL);
540		break;
541	default:
542		debug("%s: EXYNOS542X_SRC %d not supported", __func__, src);
543		return 0;
544	}
545
546	/* Clock divider ratio for this peripheral */
547	if (bit_info->div_bit >= 0)
548		div = (div >> bit_info->div_bit) & bit_info->div_mask;
549
550	/* Clock pre-divider ratio for this peripheral */
551	if (bit_info->prediv_bit >= 0)
552		sub_div = (sub_div >> bit_info->prediv_bit)
553			  & bit_info->prediv_mask;
554
555	/* Calculate and return required clock rate */
556	return (sclk / (div + 1)) / (sub_div + 1);
557}
558
559unsigned long clock_get_periph_rate(int peripheral)
560{
561	if (cpu_is_exynos5()) {
562		if (proid_is_exynos542x())
563			return exynos542x_get_periph_rate(peripheral);
564		return exynos5_get_periph_rate(peripheral);
565	} else {
566		return 0;
567	}
568}
569
570/* exynos4: return ARM clock frequency */
571static unsigned long exynos4_get_arm_clk(void)
572{
573	struct exynos4_clock *clk =
574		(struct exynos4_clock *)samsung_get_base_clock();
575	unsigned long div;
576	unsigned long armclk;
577	unsigned int core_ratio;
578	unsigned int core2_ratio;
579
580	div = readl(&clk->div_cpu0);
581
582	/* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
583	core_ratio = (div >> 0) & 0x7;
584	core2_ratio = (div >> 28) & 0x7;
585
586	armclk = get_pll_clk(APLL) / (core_ratio + 1);
587	armclk /= (core2_ratio + 1);
588
589	return armclk;
590}
591
592/* exynos4x12: return ARM clock frequency */
593static unsigned long exynos4x12_get_arm_clk(void)
594{
595	struct exynos4x12_clock *clk =
596		(struct exynos4x12_clock *)samsung_get_base_clock();
597	unsigned long div;
598	unsigned long armclk;
599	unsigned int core_ratio;
600	unsigned int core2_ratio;
601
602	div = readl(&clk->div_cpu0);
603
604	/* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
605	core_ratio = (div >> 0) & 0x7;
606	core2_ratio = (div >> 28) & 0x7;
607
608	armclk = get_pll_clk(APLL) / (core_ratio + 1);
609	armclk /= (core2_ratio + 1);
610
611	return armclk;
612}
613
614/* exynos5: return ARM clock frequency */
615static unsigned long exynos5_get_arm_clk(void)
616{
617	struct exynos5_clock *clk =
618		(struct exynos5_clock *)samsung_get_base_clock();
619	unsigned long div;
620	unsigned long armclk;
621	unsigned int arm_ratio;
622	unsigned int arm2_ratio;
623
624	div = readl(&clk->div_cpu0);
625
626	/* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
627	arm_ratio = (div >> 0) & 0x7;
628	arm2_ratio = (div >> 28) & 0x7;
629
630	armclk = get_pll_clk(APLL) / (arm_ratio + 1);
631	armclk /= (arm2_ratio + 1);
632
633	return armclk;
634}
635
636/* exynos4: return pwm clock frequency */
637static unsigned long exynos4_get_pwm_clk(void)
638{
639	struct exynos4_clock *clk =
640		(struct exynos4_clock *)samsung_get_base_clock();
641	unsigned long pclk, sclk;
642	unsigned int sel;
643	unsigned int ratio;
644
645	if (s5p_get_cpu_rev() == 0) {
646		/*
647		 * CLK_SRC_PERIL0
648		 * PWM_SEL [27:24]
649		 */
650		sel = readl(&clk->src_peril0);
651		sel = (sel >> 24) & 0xf;
652
653		if (sel == 0x6)
654			sclk = get_pll_clk(MPLL);
655		else if (sel == 0x7)
656			sclk = get_pll_clk(EPLL);
657		else if (sel == 0x8)
658			sclk = get_pll_clk(VPLL);
659		else
660			return 0;
661
662		/*
663		 * CLK_DIV_PERIL3
664		 * PWM_RATIO [3:0]
665		 */
666		ratio = readl(&clk->div_peril3);
667		ratio = ratio & 0xf;
668	} else if (s5p_get_cpu_rev() == 1) {
669		sclk = get_pll_clk(MPLL);
670		ratio = 8;
671	} else
672		return 0;
673
674	pclk = sclk / (ratio + 1);
675
676	return pclk;
677}
678
679/* exynos4x12: return pwm clock frequency */
680static unsigned long exynos4x12_get_pwm_clk(void)
681{
682	unsigned long pclk, sclk;
683	unsigned int ratio;
684
685	sclk = get_pll_clk(MPLL);
686	ratio = 8;
687
688	pclk = sclk / (ratio + 1);
689
690	return pclk;
691}
692
693/* exynos4: return uart clock frequency */
694static unsigned long exynos4_get_uart_clk(int dev_index)
695{
696	struct exynos4_clock *clk =
697		(struct exynos4_clock *)samsung_get_base_clock();
698	unsigned long uclk, sclk;
699	unsigned int sel;
700	unsigned int ratio;
701
702	/*
703	 * CLK_SRC_PERIL0
704	 * UART0_SEL [3:0]
705	 * UART1_SEL [7:4]
706	 * UART2_SEL [8:11]
707	 * UART3_SEL [12:15]
708	 * UART4_SEL [16:19]
709	 * UART5_SEL [23:20]
710	 */
711	sel = readl(&clk->src_peril0);
712	sel = (sel >> (dev_index << 2)) & 0xf;
713
714	if (sel == 0x6)
715		sclk = get_pll_clk(MPLL);
716	else if (sel == 0x7)
717		sclk = get_pll_clk(EPLL);
718	else if (sel == 0x8)
719		sclk = get_pll_clk(VPLL);
720	else
721		return 0;
722
723	/*
724	 * CLK_DIV_PERIL0
725	 * UART0_RATIO [3:0]
726	 * UART1_RATIO [7:4]
727	 * UART2_RATIO [8:11]
728	 * UART3_RATIO [12:15]
729	 * UART4_RATIO [16:19]
730	 * UART5_RATIO [23:20]
731	 */
732	ratio = readl(&clk->div_peril0);
733	ratio = (ratio >> (dev_index << 2)) & 0xf;
734
735	uclk = sclk / (ratio + 1);
736
737	return uclk;
738}
739
740/* exynos4x12: return uart clock frequency */
741static unsigned long exynos4x12_get_uart_clk(int dev_index)
742{
743	struct exynos4x12_clock *clk =
744		(struct exynos4x12_clock *)samsung_get_base_clock();
745	unsigned long uclk, sclk;
746	unsigned int sel;
747	unsigned int ratio;
748
749	/*
750	 * CLK_SRC_PERIL0
751	 * UART0_SEL [3:0]
752	 * UART1_SEL [7:4]
753	 * UART2_SEL [8:11]
754	 * UART3_SEL [12:15]
755	 * UART4_SEL [16:19]
756	 */
757	sel = readl(&clk->src_peril0);
758	sel = (sel >> (dev_index << 2)) & 0xf;
759
760	if (sel == 0x6)
761		sclk = get_pll_clk(MPLL);
762	else if (sel == 0x7)
763		sclk = get_pll_clk(EPLL);
764	else if (sel == 0x8)
765		sclk = get_pll_clk(VPLL);
766	else
767		return 0;
768
769	/*
770	 * CLK_DIV_PERIL0
771	 * UART0_RATIO [3:0]
772	 * UART1_RATIO [7:4]
773	 * UART2_RATIO [8:11]
774	 * UART3_RATIO [12:15]
775	 * UART4_RATIO [16:19]
776	 */
777	ratio = readl(&clk->div_peril0);
778	ratio = (ratio >> (dev_index << 2)) & 0xf;
779
780	uclk = sclk / (ratio + 1);
781
782	return uclk;
783}
784
785static unsigned long exynos4_get_mmc_clk(int dev_index)
786{
787	struct exynos4_clock *clk =
788		(struct exynos4_clock *)samsung_get_base_clock();
789	unsigned long uclk, sclk;
790	unsigned int sel, ratio, pre_ratio;
791	int shift = 0;
792
793	sel = readl(&clk->src_fsys);
794	sel = (sel >> (dev_index << 2)) & 0xf;
795
796	if (sel == 0x6)
797		sclk = get_pll_clk(MPLL);
798	else if (sel == 0x7)
799		sclk = get_pll_clk(EPLL);
800	else if (sel == 0x8)
801		sclk = get_pll_clk(VPLL);
802	else
803		return 0;
804
805	switch (dev_index) {
806	case 0:
807	case 1:
808		ratio = readl(&clk->div_fsys1);
809		pre_ratio = readl(&clk->div_fsys1);
810		break;
811	case 2:
812	case 3:
813		ratio = readl(&clk->div_fsys2);
814		pre_ratio = readl(&clk->div_fsys2);
815		break;
816	case 4:
817		ratio = readl(&clk->div_fsys3);
818		pre_ratio = readl(&clk->div_fsys3);
819		break;
820	default:
821		return 0;
822	}
823
824	if (dev_index == 1 || dev_index == 3)
825		shift = 16;
826
827	ratio = (ratio >> shift) & 0xf;
828	pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
829	uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
830
831	return uclk;
832}
833
834/* exynos4: set the mmc clock */
835static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
836{
837	struct exynos4_clock *clk =
838		(struct exynos4_clock *)samsung_get_base_clock();
839	unsigned int addr, clear_bit, set_bit;
840
841	/*
842	 * CLK_DIV_FSYS1
843	 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
844	 * CLK_DIV_FSYS2
845	 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
846	 * CLK_DIV_FSYS3
847	 * MMC4_RATIO [3:0]
848	 */
849	if (dev_index < 2) {
850		addr = (unsigned int)&clk->div_fsys1;
851		clear_bit = MASK_PRE_RATIO(dev_index);
852		set_bit = SET_PRE_RATIO(dev_index, div);
853	} else if (dev_index == 4) {
854		addr = (unsigned int)&clk->div_fsys3;
855		dev_index -= 4;
856		/* MMC4 is controlled with the MMC4_RATIO value */
857		clear_bit = MASK_RATIO(dev_index);
858		set_bit = SET_RATIO(dev_index, div);
859	} else {
860		addr = (unsigned int)&clk->div_fsys2;
861		dev_index -= 2;
862		clear_bit = MASK_PRE_RATIO(dev_index);
863		set_bit = SET_PRE_RATIO(dev_index, div);
864	}
865
866	clrsetbits_le32(addr, clear_bit, set_bit);
867}
868
869/* exynos5: set the mmc clock */
870static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
871{
872	struct exynos5_clock *clk =
873		(struct exynos5_clock *)samsung_get_base_clock();
874	unsigned int addr;
875
876	/*
877	 * CLK_DIV_FSYS1
878	 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
879	 * CLK_DIV_FSYS2
880	 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
881	 */
882	if (dev_index < 2) {
883		addr = (unsigned int)&clk->div_fsys1;
884	} else {
885		addr = (unsigned int)&clk->div_fsys2;
886		dev_index -= 2;
887	}
888
889	clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
890			(div & 0xff) << ((dev_index << 4) + 8));
891}
892
893/* exynos5: set the mmc clock */
894static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
895{
896	struct exynos5420_clock *clk =
897		(struct exynos5420_clock *)samsung_get_base_clock();
898	unsigned int addr;
899	unsigned int shift;
900
901	/*
902	 * CLK_DIV_FSYS1
903	 * MMC0_RATIO [9:0]
904	 * MMC1_RATIO [19:10]
905	 * MMC2_RATIO [29:20]
906	 */
907	addr = (unsigned int)&clk->div_fsys1;
908	shift = dev_index * 10;
909
910	clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
911}
912
913/* get_lcd_clk: return lcd clock frequency */
914static unsigned long exynos4_get_lcd_clk(void)
915{
916	struct exynos4_clock *clk =
917		(struct exynos4_clock *)samsung_get_base_clock();
918	unsigned long pclk, sclk;
919	unsigned int sel;
920	unsigned int ratio;
921
922	/*
923	 * CLK_SRC_LCD0
924	 * FIMD0_SEL [3:0]
925	 */
926	sel = readl(&clk->src_lcd0);
927	sel = sel & 0xf;
928
929	/*
930	 * 0x6: SCLK_MPLL
931	 * 0x7: SCLK_EPLL
932	 * 0x8: SCLK_VPLL
933	 */
934	if (sel == 0x6)
935		sclk = get_pll_clk(MPLL);
936	else if (sel == 0x7)
937		sclk = get_pll_clk(EPLL);
938	else if (sel == 0x8)
939		sclk = get_pll_clk(VPLL);
940	else
941		return 0;
942
943	/*
944	 * CLK_DIV_LCD0
945	 * FIMD0_RATIO [3:0]
946	 */
947	ratio = readl(&clk->div_lcd0);
948	ratio = ratio & 0xf;
949
950	pclk = sclk / (ratio + 1);
951
952	return pclk;
953}
954
955/* get_lcd_clk: return lcd clock frequency */
956static unsigned long exynos5_get_lcd_clk(void)
957{
958	struct exynos5_clock *clk =
959		(struct exynos5_clock *)samsung_get_base_clock();
960	unsigned long pclk, sclk;
961	unsigned int sel;
962	unsigned int ratio;
963
964	/*
965	 * CLK_SRC_LCD0
966	 * FIMD0_SEL [3:0]
967	 */
968	sel = readl(&clk->src_disp1_0);
969	sel = sel & 0xf;
970
971	/*
972	 * 0x6: SCLK_MPLL
973	 * 0x7: SCLK_EPLL
974	 * 0x8: SCLK_VPLL
975	 */
976	if (sel == 0x6)
977		sclk = get_pll_clk(MPLL);
978	else if (sel == 0x7)
979		sclk = get_pll_clk(EPLL);
980	else if (sel == 0x8)
981		sclk = get_pll_clk(VPLL);
982	else
983		return 0;
984
985	/*
986	 * CLK_DIV_LCD0
987	 * FIMD0_RATIO [3:0]
988	 */
989	ratio = readl(&clk->div_disp1_0);
990	ratio = ratio & 0xf;
991
992	pclk = sclk / (ratio + 1);
993
994	return pclk;
995}
996
997static unsigned long exynos5420_get_lcd_clk(void)
998{
999	struct exynos5420_clock *clk =
1000		(struct exynos5420_clock *)samsung_get_base_clock();
1001	unsigned long pclk, sclk;
1002	unsigned int sel;
1003	unsigned int ratio;
1004
1005	/*
1006	 * CLK_SRC_DISP10
1007	 * FIMD1_SEL [4]
1008	 * 0: SCLK_RPLL
1009	 * 1: SCLK_SPLL
1010	 */
1011	sel = readl(&clk->src_disp10);
1012	sel &= (1 << 4);
1013
1014	if (sel)
1015		sclk = get_pll_clk(SPLL);
1016	else
1017		sclk = get_pll_clk(RPLL);
1018
1019	/*
1020	 * CLK_DIV_DISP10
1021	 * FIMD1_RATIO [3:0]
1022	 */
1023	ratio = readl(&clk->div_disp10);
1024	ratio = ratio & 0xf;
1025
1026	pclk = sclk / (ratio + 1);
1027
1028	return pclk;
1029}
1030
1031static unsigned long exynos5800_get_lcd_clk(void)
1032{
1033	struct exynos5420_clock *clk =
1034		(struct exynos5420_clock *)samsung_get_base_clock();
1035	unsigned long sclk;
1036	unsigned int sel;
1037	unsigned int ratio;
1038
1039	/*
1040	 * CLK_SRC_DISP10
1041	 * CLKMUX_FIMD1 [6:4]
1042	 */
1043	sel = (readl(&clk->src_disp10) >> 4) & 0x7;
1044
1045	if (sel) {
1046		/*
1047		 * Mapping of CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4] values into
1048		 * PLLs. The first element is a placeholder to bypass the
1049		 * default settig.
1050		 */
1051		const int reg_map[] = {0, CPLL, DPLL, MPLL, SPLL, IPLL, EPLL,
1052									RPLL};
1053		sclk = get_pll_clk(reg_map[sel]);
1054	} else
1055		sclk = get_board_sys_clk();
1056	/*
1057	 * CLK_DIV_DISP10
1058	 * FIMD1_RATIO [3:0]
1059	 */
1060	ratio = readl(&clk->div_disp10) & 0xf;
1061
1062	return sclk / (ratio + 1);
1063}
1064
1065void exynos4_set_lcd_clk(void)
1066{
1067	struct exynos4_clock *clk =
1068	    (struct exynos4_clock *)samsung_get_base_clock();
1069
1070	/*
1071	 * CLK_GATE_BLOCK
1072	 * CLK_CAM	[0]
1073	 * CLK_TV	[1]
1074	 * CLK_MFC	[2]
1075	 * CLK_G3D	[3]
1076	 * CLK_LCD0	[4]
1077	 * CLK_LCD1	[5]
1078	 * CLK_GPS	[7]
1079	 */
1080	setbits_le32(&clk->gate_block, 1 << 4);
1081
1082	/*
1083	 * CLK_SRC_LCD0
1084	 * FIMD0_SEL		[3:0]
1085	 * MDNIE0_SEL		[7:4]
1086	 * MDNIE_PWM0_SEL	[8:11]
1087	 * MIPI0_SEL		[12:15]
1088	 * set lcd0 src clock 0x6: SCLK_MPLL
1089	 */
1090	clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
1091
1092	/*
1093	 * CLK_GATE_IP_LCD0
1094	 * CLK_FIMD0		[0]
1095	 * CLK_MIE0		[1]
1096	 * CLK_MDNIE0		[2]
1097	 * CLK_DSIM0		[3]
1098	 * CLK_SMMUFIMD0	[4]
1099	 * CLK_PPMULCD0		[5]
1100	 * Gating all clocks for FIMD0
1101	 */
1102	setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
1103
1104	/*
1105	 * CLK_DIV_LCD0
1106	 * FIMD0_RATIO		[3:0]
1107	 * MDNIE0_RATIO		[7:4]
1108	 * MDNIE_PWM0_RATIO	[11:8]
1109	 * MDNIE_PWM_PRE_RATIO	[15:12]
1110	 * MIPI0_RATIO		[19:16]
1111	 * MIPI0_PRE_RATIO	[23:20]
1112	 * set fimd ratio
1113	 */
1114	clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
1115}
1116
1117void exynos5_set_lcd_clk(void)
1118{
1119	struct exynos5_clock *clk =
1120	    (struct exynos5_clock *)samsung_get_base_clock();
1121
1122	/*
1123	 * CLK_GATE_BLOCK
1124	 * CLK_CAM	[0]
1125	 * CLK_TV	[1]
1126	 * CLK_MFC	[2]
1127	 * CLK_G3D	[3]
1128	 * CLK_LCD0	[4]
1129	 * CLK_LCD1	[5]
1130	 * CLK_GPS	[7]
1131	 */
1132	setbits_le32(&clk->gate_block, 1 << 4);
1133
1134	/*
1135	 * CLK_SRC_LCD0
1136	 * FIMD0_SEL		[3:0]
1137	 * MDNIE0_SEL		[7:4]
1138	 * MDNIE_PWM0_SEL	[8:11]
1139	 * MIPI0_SEL		[12:15]
1140	 * set lcd0 src clock 0x6: SCLK_MPLL
1141	 */
1142	clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
1143
1144	/*
1145	 * CLK_GATE_IP_LCD0
1146	 * CLK_FIMD0		[0]
1147	 * CLK_MIE0		[1]
1148	 * CLK_MDNIE0		[2]
1149	 * CLK_DSIM0		[3]
1150	 * CLK_SMMUFIMD0	[4]
1151	 * CLK_PPMULCD0		[5]
1152	 * Gating all clocks for FIMD0
1153	 */
1154	setbits_le32(&clk->gate_ip_disp1, 1 << 0);
1155
1156	/*
1157	 * CLK_DIV_LCD0
1158	 * FIMD0_RATIO		[3:0]
1159	 * MDNIE0_RATIO		[7:4]
1160	 * MDNIE_PWM0_RATIO	[11:8]
1161	 * MDNIE_PWM_PRE_RATIO	[15:12]
1162	 * MIPI0_RATIO		[19:16]
1163	 * MIPI0_PRE_RATIO	[23:20]
1164	 * set fimd ratio
1165	 */
1166	clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
1167}
1168
1169void exynos5420_set_lcd_clk(void)
1170{
1171	struct exynos5420_clock *clk =
1172		(struct exynos5420_clock *)samsung_get_base_clock();
1173	unsigned int cfg;
1174
1175	/*
1176	 * CLK_SRC_DISP10
1177	 * FIMD1_SEL [4]
1178	 * 0: SCLK_RPLL
1179	 * 1: SCLK_SPLL
1180	 */
1181	cfg = readl(&clk->src_disp10);
1182	cfg &= ~(0x1 << 4);
1183	cfg |= (0 << 4);
1184	writel(cfg, &clk->src_disp10);
1185
1186	/*
1187	 * CLK_DIV_DISP10
1188	 * FIMD1_RATIO		[3:0]
1189	 */
1190	cfg = readl(&clk->div_disp10);
1191	cfg &= ~(0xf << 0);
1192	cfg |= (0 << 0);
1193	writel(cfg, &clk->div_disp10);
1194}
1195
1196void exynos5800_set_lcd_clk(void)
1197{
1198	struct exynos5420_clock *clk =
1199		(struct exynos5420_clock *)samsung_get_base_clock();
1200	unsigned int cfg;
1201
1202	/*
1203	 * Use RPLL for pixel clock
1204	 * CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4]
1205	 * ==================
1206	 * 111: SCLK_RPLL
1207	 */
1208	cfg = readl(&clk->src_disp10) | (0x7 << 4);
1209	writel(cfg, &clk->src_disp10);
1210
1211	/*
1212	 * CLK_DIV_DISP10
1213	 * FIMD1_RATIO		[3:0]
1214	 */
1215	clrsetbits_le32(&clk->div_disp10, 0xf << 0, 0x0 << 0);
1216}
1217
1218void exynos4_set_mipi_clk(void)
1219{
1220	struct exynos4_clock *clk =
1221	    (struct exynos4_clock *)samsung_get_base_clock();
1222
1223	/*
1224	 * CLK_SRC_LCD0
1225	 * FIMD0_SEL		[3:0]
1226	 * MDNIE0_SEL		[7:4]
1227	 * MDNIE_PWM0_SEL	[8:11]
1228	 * MIPI0_SEL		[12:15]
1229	 * set mipi0 src clock 0x6: SCLK_MPLL
1230	 */
1231	clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
1232
1233	/*
1234	 * CLK_SRC_MASK_LCD0
1235	 * FIMD0_MASK		[0]
1236	 * MDNIE0_MASK		[4]
1237	 * MDNIE_PWM0_MASK	[8]
1238	 * MIPI0_MASK		[12]
1239	 * set src mask mipi0 0x1: Unmask
1240	 */
1241	setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
1242
1243	/*
1244	 * CLK_GATE_IP_LCD0
1245	 * CLK_FIMD0		[0]
1246	 * CLK_MIE0		[1]
1247	 * CLK_MDNIE0		[2]
1248	 * CLK_DSIM0		[3]
1249	 * CLK_SMMUFIMD0	[4]
1250	 * CLK_PPMULCD0		[5]
1251	 * Gating all clocks for MIPI0
1252	 */
1253	setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
1254
1255	/*
1256	 * CLK_DIV_LCD0
1257	 * FIMD0_RATIO		[3:0]
1258	 * MDNIE0_RATIO		[7:4]
1259	 * MDNIE_PWM0_RATIO	[11:8]
1260	 * MDNIE_PWM_PRE_RATIO	[15:12]
1261	 * MIPI0_RATIO		[19:16]
1262	 * MIPI0_PRE_RATIO	[23:20]
1263	 * set mipi ratio
1264	 */
1265	clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
1266}
1267
1268int exynos5_set_epll_clk(unsigned long rate)
1269{
1270	unsigned int epll_con, epll_con_k;
1271	unsigned int i;
1272	unsigned int lockcnt;
1273	unsigned int start;
1274	struct exynos5_clock *clk =
1275		(struct exynos5_clock *)samsung_get_base_clock();
1276
1277	epll_con = readl(&clk->epll_con0);
1278	epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1279			EPLL_CON0_LOCK_DET_EN_SHIFT) |
1280		EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1281		EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1282		EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1283
1284	for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1285		if (exynos5_epll_div[i].freq_out == rate)
1286			break;
1287	}
1288
1289	if (i == ARRAY_SIZE(exynos5_epll_div))
1290		return -1;
1291
1292	epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1293	epll_con |= exynos5_epll_div[i].en_lock_det <<
1294				EPLL_CON0_LOCK_DET_EN_SHIFT;
1295	epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1296	epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1297	epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1298
1299	/*
1300	 * Required period ( in cycles) to genarate a stable clock output.
1301	 * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1302	 * frequency input (as per spec)
1303	 */
1304	lockcnt = 3000 * exynos5_epll_div[i].p_div;
1305
1306	writel(lockcnt, &clk->epll_lock);
1307	writel(epll_con, &clk->epll_con0);
1308	writel(epll_con_k, &clk->epll_con1);
1309
1310	start = get_timer(0);
1311
1312	 while (!(readl(&clk->epll_con0) &
1313			(0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1314		if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1315			debug("%s: Timeout waiting for EPLL lock\n", __func__);
1316			return -1;
1317		}
1318	}
1319	return 0;
1320}
1321
1322static int exynos5420_set_i2s_clk_source(void)
1323{
1324	struct exynos5420_clock *clk =
1325		(struct exynos5420_clock *)samsung_get_base_clock();
1326
1327	setbits_le32(&clk->src_top6, EXYNOS5420_CLK_SRC_MOUT_EPLL);
1328	clrsetbits_le32(&clk->src_mau, EXYNOS5420_AUDIO0_SEL_MASK,
1329			(EXYNOS5420_CLK_SRC_SCLK_EPLL));
1330	setbits_le32(EXYNOS5_AUDIOSS_BASE, 1 << 0);
1331
1332	return 0;
1333}
1334
1335int exynos5_set_i2s_clk_source(unsigned int i2s_id)
1336{
1337	struct exynos5_clock *clk =
1338		(struct exynos5_clock *)samsung_get_base_clock();
1339	unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
1340
1341	if (i2s_id == 0) {
1342		setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1343		clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1344				(CLK_SRC_SCLK_EPLL));
1345		setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1346	} else if (i2s_id == 1) {
1347		clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1348				(CLK_SRC_SCLK_EPLL));
1349	} else {
1350		return -1;
1351	}
1352	return 0;
1353}
1354
1355int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
1356				  unsigned int dst_frq,
1357				  unsigned int i2s_id)
1358{
1359	struct exynos5_clock *clk =
1360		(struct exynos5_clock *)samsung_get_base_clock();
1361	unsigned int div;
1362
1363	if ((dst_frq == 0) || (src_frq == 0)) {
1364		debug("%s: Invalid requency input for prescaler\n", __func__);
1365		debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1366		return -1;
1367	}
1368
1369	div = (src_frq / dst_frq);
1370	if (i2s_id == 0) {
1371		if (div > AUDIO_0_RATIO_MASK) {
1372			debug("%s: Frequency ratio is out of range\n",
1373			      __func__);
1374			debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1375			return -1;
1376		}
1377		clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1378				(div & AUDIO_0_RATIO_MASK));
1379	} else if (i2s_id == 1) {
1380		if (div > AUDIO_1_RATIO_MASK) {
1381			debug("%s: Frequency ratio is out of range\n",
1382			      __func__);
1383			debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1384			return -1;
1385		}
1386		clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1387				(div & AUDIO_1_RATIO_MASK));
1388	} else {
1389		return -1;
1390	}
1391	return 0;
1392}
1393
1394/**
1395 * Linearly searches for the most accurate main and fine stage clock scalars
1396 * (divisors) for a specified target frequency and scalar bit sizes by checking
1397 * all multiples of main_scalar_bits values. Will always return scalars up to or
1398 * slower than target.
1399 *
1400 * @param main_scalar_bits	Number of main scalar bits, must be > 0 and < 32
1401 * @param fine_scalar_bits	Number of fine scalar bits, must be > 0 and < 32
1402 * @param input_freq		Clock frequency to be scaled in Hz
1403 * @param target_freq		Desired clock frequency in Hz
1404 * @param best_fine_scalar	Pointer to store the fine stage divisor
1405 *
1406 * Return: best_main_scalar	Main scalar for desired frequency or -1 if none
1407 * found
1408 */
1409static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1410	unsigned int fine_scalar_bits, unsigned int input_rate,
1411	unsigned int target_rate, unsigned int *best_fine_scalar)
1412{
1413	int i;
1414	int best_main_scalar = -1;
1415	unsigned int best_error = target_rate;
1416	const unsigned int cap = (1 << fine_scalar_bits) - 1;
1417	const unsigned int loops = 1 << main_scaler_bits;
1418
1419	debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1420			target_rate, cap);
1421
1422	assert(best_fine_scalar != NULL);
1423	assert(main_scaler_bits <= fine_scalar_bits);
1424
1425	*best_fine_scalar = 1;
1426
1427	if (input_rate == 0 || target_rate == 0)
1428		return -1;
1429
1430	if (target_rate >= input_rate)
1431		return 1;
1432
1433	for (i = 1; i <= loops; i++) {
1434		const unsigned int effective_div =
1435			max(min(input_rate / i / target_rate, cap), 1U);
1436		const unsigned int effective_rate = input_rate / i /
1437							effective_div;
1438		const int error = target_rate - effective_rate;
1439
1440		debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1441				effective_rate, error);
1442
1443		if (error >= 0 && error <= best_error) {
1444			best_error = error;
1445			best_main_scalar = i;
1446			*best_fine_scalar = effective_div;
1447		}
1448	}
1449
1450	return best_main_scalar;
1451}
1452
1453static int exynos5_set_spi_clk(enum periph_id periph_id,
1454					unsigned int rate)
1455{
1456	struct exynos5_clock *clk =
1457		(struct exynos5_clock *)samsung_get_base_clock();
1458	int main;
1459	unsigned int fine;
1460	unsigned shift, pre_shift;
1461	unsigned mask = 0xff;
1462	u32 *reg;
1463
1464	main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1465	if (main < 0) {
1466		debug("%s: Cannot set clock rate for periph %d",
1467				__func__, periph_id);
1468		return -1;
1469	}
1470	main = main - 1;
1471	fine = fine - 1;
1472
1473	switch (periph_id) {
1474	case PERIPH_ID_SPI0:
1475		reg = &clk->div_peric1;
1476		shift = 0;
1477		pre_shift = 8;
1478		break;
1479	case PERIPH_ID_SPI1:
1480		reg = &clk->div_peric1;
1481		shift = 16;
1482		pre_shift = 24;
1483		break;
1484	case PERIPH_ID_SPI2:
1485		reg = &clk->div_peric2;
1486		shift = 0;
1487		pre_shift = 8;
1488		break;
1489	case PERIPH_ID_SPI3:
1490		reg = &clk->sclk_div_isp;
1491		shift = 0;
1492		pre_shift = 4;
1493		break;
1494	case PERIPH_ID_SPI4:
1495		reg = &clk->sclk_div_isp;
1496		shift = 12;
1497		pre_shift = 16;
1498		break;
1499	default:
1500		debug("%s: Unsupported peripheral ID %d\n", __func__,
1501		      periph_id);
1502		return -1;
1503	}
1504	clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1505	clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1506
1507	return 0;
1508}
1509
1510static int exynos5420_set_spi_clk(enum periph_id periph_id,
1511					unsigned int rate)
1512{
1513	struct exynos5420_clock *clk =
1514		(struct exynos5420_clock *)samsung_get_base_clock();
1515	int main;
1516	unsigned int fine;
1517	unsigned shift, pre_shift;
1518	unsigned div_mask = 0xf, pre_div_mask = 0xff;
1519	u32 *reg;
1520	u32 *pre_reg;
1521
1522	main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1523	if (main < 0) {
1524		debug("%s: Cannot set clock rate for periph %d",
1525		      __func__, periph_id);
1526		return -1;
1527	}
1528	main = main - 1;
1529	fine = fine - 1;
1530
1531	switch (periph_id) {
1532	case PERIPH_ID_SPI0:
1533		reg = &clk->div_peric1;
1534		shift = 20;
1535		pre_reg = &clk->div_peric4;
1536		pre_shift = 8;
1537		break;
1538	case PERIPH_ID_SPI1:
1539		reg = &clk->div_peric1;
1540		shift = 24;
1541		pre_reg = &clk->div_peric4;
1542		pre_shift = 16;
1543		break;
1544	case PERIPH_ID_SPI2:
1545		reg = &clk->div_peric1;
1546		shift = 28;
1547		pre_reg = &clk->div_peric4;
1548		pre_shift = 24;
1549		break;
1550	case PERIPH_ID_SPI3:
1551		reg = &clk->div_isp1;
1552		shift = 16;
1553		pre_reg = &clk->div_isp1;
1554		pre_shift = 0;
1555		break;
1556	case PERIPH_ID_SPI4:
1557		reg = &clk->div_isp1;
1558		shift = 20;
1559		pre_reg = &clk->div_isp1;
1560		pre_shift = 8;
1561		break;
1562	default:
1563		debug("%s: Unsupported peripheral ID %d\n", __func__,
1564		      periph_id);
1565		return -1;
1566	}
1567
1568	clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
1569	clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
1570			(fine & pre_div_mask) << pre_shift);
1571
1572	return 0;
1573}
1574
1575static unsigned long exynos4_get_i2c_clk(void)
1576{
1577	struct exynos4_clock *clk =
1578		(struct exynos4_clock *)samsung_get_base_clock();
1579	unsigned long sclk, aclk_100;
1580	unsigned int ratio;
1581
1582	sclk = get_pll_clk(APLL);
1583
1584	ratio = (readl(&clk->div_top)) >> 4;
1585	ratio &= 0xf;
1586	aclk_100 = sclk / (ratio + 1);
1587	return aclk_100;
1588}
1589
1590unsigned long get_pll_clk(int pllreg)
1591{
1592	if (cpu_is_exynos5()) {
1593		if (proid_is_exynos542x())
1594			return exynos542x_get_pll_clk(pllreg);
1595		return exynos5_get_pll_clk(pllreg);
1596	} else if (cpu_is_exynos4()) {
1597		if (proid_is_exynos4412())
1598			return exynos4x12_get_pll_clk(pllreg);
1599		return exynos4_get_pll_clk(pllreg);
1600	}
1601
1602	return 0;
1603}
1604
1605unsigned long get_arm_clk(void)
1606{
1607	if (cpu_is_exynos5()) {
1608		return exynos5_get_arm_clk();
1609	} else if (cpu_is_exynos4()) {
1610		if (proid_is_exynos4412())
1611			return exynos4x12_get_arm_clk();
1612		return exynos4_get_arm_clk();
1613	}
1614
1615	return 0;
1616}
1617
1618unsigned long get_i2c_clk(void)
1619{
1620	if (cpu_is_exynos5())
1621		return clock_get_periph_rate(PERIPH_ID_I2C0);
1622	else if (cpu_is_exynos4())
1623		return exynos4_get_i2c_clk();
1624
1625	return 0;
1626}
1627
1628unsigned long get_pwm_clk(void)
1629{
1630	if (cpu_is_exynos5()) {
1631		return clock_get_periph_rate(PERIPH_ID_PWM0);
1632	} else if (cpu_is_exynos4()) {
1633		if (proid_is_exynos4412())
1634			return exynos4x12_get_pwm_clk();
1635		return exynos4_get_pwm_clk();
1636	}
1637
1638	return 0;
1639}
1640
1641unsigned long get_uart_clk(int dev_index)
1642{
1643	enum periph_id id;
1644
1645	switch (dev_index) {
1646	case 0:
1647		id = PERIPH_ID_UART0;
1648		break;
1649	case 1:
1650		id = PERIPH_ID_UART1;
1651		break;
1652	case 2:
1653		id = PERIPH_ID_UART2;
1654		break;
1655	case 3:
1656		id = PERIPH_ID_UART3;
1657		break;
1658	default:
1659		debug("%s: invalid UART index %d", __func__, dev_index);
1660		return -1;
1661	}
1662
1663	if (cpu_is_exynos5()) {
1664		return clock_get_periph_rate(id);
1665	} else if (cpu_is_exynos4()) {
1666		if (proid_is_exynos4412())
1667			return exynos4x12_get_uart_clk(dev_index);
1668		return exynos4_get_uart_clk(dev_index);
1669	}
1670
1671	return 0;
1672}
1673
1674unsigned long get_mmc_clk(int dev_index)
1675{
1676	enum periph_id id;
1677
1678	if (cpu_is_exynos4())
1679		return exynos4_get_mmc_clk(dev_index);
1680
1681	switch (dev_index) {
1682	case 0:
1683		id = PERIPH_ID_SDMMC0;
1684		break;
1685	case 1:
1686		id = PERIPH_ID_SDMMC1;
1687		break;
1688	case 2:
1689		id = PERIPH_ID_SDMMC2;
1690		break;
1691	case 3:
1692		id = PERIPH_ID_SDMMC3;
1693		break;
1694	default:
1695		debug("%s: invalid MMC index %d", __func__, dev_index);
1696		return -1;
1697	}
1698
1699	return clock_get_periph_rate(id);
1700}
1701
1702void set_mmc_clk(int dev_index, unsigned int div)
1703{
1704	/* If want to set correct value, it needs to substract one from div.*/
1705	if (div > 0)
1706		div -= 1;
1707
1708	if (cpu_is_exynos5()) {
1709		if (proid_is_exynos542x())
1710			exynos5420_set_mmc_clk(dev_index, div);
1711		else
1712			exynos5_set_mmc_clk(dev_index, div);
1713	} else if (cpu_is_exynos4()) {
1714		exynos4_set_mmc_clk(dev_index, div);
1715	}
1716}
1717
1718unsigned long get_lcd_clk(void)
1719{
1720	if (cpu_is_exynos4()) {
1721		return exynos4_get_lcd_clk();
1722	} else if (cpu_is_exynos5()) {
1723		if (proid_is_exynos5420())
1724			return exynos5420_get_lcd_clk();
1725		else if (proid_is_exynos5422())
1726			return exynos5800_get_lcd_clk();
1727		else
1728			return exynos5_get_lcd_clk();
1729	}
1730
1731	return 0;
1732}
1733
1734void set_lcd_clk(void)
1735{
1736	if (cpu_is_exynos4()) {
1737		exynos4_set_lcd_clk();
1738	} else if (cpu_is_exynos5()) {
1739		if (proid_is_exynos5250())
1740			exynos5_set_lcd_clk();
1741		else if (proid_is_exynos5420())
1742			exynos5420_set_lcd_clk();
1743		else
1744			exynos5800_set_lcd_clk();
1745	}
1746}
1747
1748void set_mipi_clk(void)
1749{
1750	if (cpu_is_exynos4())
1751		exynos4_set_mipi_clk();
1752}
1753
1754int set_spi_clk(int periph_id, unsigned int rate)
1755{
1756	if (cpu_is_exynos5()) {
1757		if (proid_is_exynos542x())
1758			return exynos5420_set_spi_clk(periph_id, rate);
1759		return exynos5_set_spi_clk(periph_id, rate);
1760	}
1761
1762	return 0;
1763}
1764
1765int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1766			  unsigned int i2s_id)
1767{
1768	if (cpu_is_exynos5())
1769		return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
1770
1771	return 0;
1772}
1773
1774int set_i2s_clk_source(unsigned int i2s_id)
1775{
1776	if (cpu_is_exynos5()) {
1777		if (proid_is_exynos542x())
1778			return exynos5420_set_i2s_clk_source();
1779		else
1780			return exynos5_set_i2s_clk_source(i2s_id);
1781	}
1782
1783	return 0;
1784}
1785
1786int set_epll_clk(unsigned long rate)
1787{
1788	if (cpu_is_exynos5())
1789		return exynos5_set_epll_clk(rate);
1790
1791	return 0;
1792}
1793