blob: 555228a52083dd34fbf26958005c4206c598d450 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Minkyu Kang399e5ae2009-10-01 17:20:01 +09002/*
3 * Copyright (C) 2009 Samsung Electronics
4 * Minkyu Kang <mk7.kang@samsung.com>
5 * Heungjun Kim <riverful.kim@samsung.com>
Minkyu Kang399e5ae2009-10-01 17:20:01 +09006 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <asm/arch/clock.h>
Naveen Krishna CH6c71a8f2010-02-04 14:17:38 +090011#include <asm/arch/clk.h>
Minkyu Kang399e5ae2009-10-01 17:20:01 +090012
13#define CLK_M 0
14#define CLK_D 1
15#define CLK_P 2
16
17#ifndef CONFIG_SYS_CLK_FREQ_C100
18#define CONFIG_SYS_CLK_FREQ_C100 12000000
19#endif
20#ifndef CONFIG_SYS_CLK_FREQ_C110
21#define CONFIG_SYS_CLK_FREQ_C110 24000000
22#endif
23
Minkyu Kang399e5ae2009-10-01 17:20:01 +090024/* s5pc110: return pll clock frequency */
25static unsigned long s5pc100_get_pll_clk(int pllreg)
26{
Minkyu Kangd93d0f02010-08-13 16:07:35 +090027 struct s5pc100_clock *clk =
28 (struct s5pc100_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +090029 unsigned long r, m, p, s, mask, fout;
30 unsigned int freq;
31
32 switch (pllreg) {
33 case APLL:
34 r = readl(&clk->apll_con);
35 break;
36 case MPLL:
37 r = readl(&clk->mpll_con);
38 break;
39 case EPLL:
40 r = readl(&clk->epll_con);
41 break;
42 case HPLL:
43 r = readl(&clk->hpll_con);
44 break;
45 default:
46 printf("Unsupported PLL (%d)\n", pllreg);
47 return 0;
48 }
49
50 /*
51 * APLL_CON: MIDV [25:16]
52 * MPLL_CON: MIDV [23:16]
53 * EPLL_CON: MIDV [23:16]
54 * HPLL_CON: MIDV [23:16]
55 */
56 if (pllreg == APLL)
57 mask = 0x3ff;
58 else
59 mask = 0x0ff;
60
61 m = (r >> 16) & mask;
62
63 /* PDIV [13:8] */
64 p = (r >> 8) & 0x3f;
65 /* SDIV [2:0] */
66 s = r & 0x7;
67
68 /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
69 freq = CONFIG_SYS_CLK_FREQ_C100;
70 fout = m * (freq / (p * (1 << s)));
71
72 return fout;
73}
74
75/* s5pc100: return pll clock frequency */
76static unsigned long s5pc110_get_pll_clk(int pllreg)
77{
Minkyu Kangd93d0f02010-08-13 16:07:35 +090078 struct s5pc110_clock *clk =
79 (struct s5pc110_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +090080 unsigned long r, m, p, s, mask, fout;
81 unsigned int freq;
82
83 switch (pllreg) {
84 case APLL:
85 r = readl(&clk->apll_con);
86 break;
87 case MPLL:
88 r = readl(&clk->mpll_con);
89 break;
90 case EPLL:
91 r = readl(&clk->epll_con);
92 break;
93 case VPLL:
94 r = readl(&clk->vpll_con);
95 break;
96 default:
97 printf("Unsupported PLL (%d)\n", pllreg);
98 return 0;
99 }
100
101 /*
102 * APLL_CON: MIDV [25:16]
103 * MPLL_CON: MIDV [25:16]
104 * EPLL_CON: MIDV [24:16]
105 * VPLL_CON: MIDV [24:16]
106 */
107 if (pllreg == APLL || pllreg == MPLL)
108 mask = 0x3ff;
109 else
110 mask = 0x1ff;
111
112 m = (r >> 16) & mask;
113
114 /* PDIV [13:8] */
115 p = (r >> 8) & 0x3f;
116 /* SDIV [2:0] */
117 s = r & 0x7;
118
119 freq = CONFIG_SYS_CLK_FREQ_C110;
120 if (pllreg == APLL) {
121 if (s < 1)
122 s = 1;
123 /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
124 fout = m * (freq / (p * (1 << (s - 1))));
125 } else
126 /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
127 fout = m * (freq / (p * (1 << s)));
128
129 return fout;
130}
131
132/* s5pc110: return ARM clock frequency */
133static unsigned long s5pc110_get_arm_clk(void)
134{
Minkyu Kangd93d0f02010-08-13 16:07:35 +0900135 struct s5pc110_clock *clk =
136 (struct s5pc110_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900137 unsigned long div;
138 unsigned long dout_apll, armclk;
139 unsigned int apll_ratio;
140
141 div = readl(&clk->div0);
142
143 /* APLL_RATIO: [2:0] */
144 apll_ratio = div & 0x7;
145
146 dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
147 armclk = dout_apll;
148
149 return armclk;
150}
151
152/* s5pc100: return ARM clock frequency */
153static unsigned long s5pc100_get_arm_clk(void)
154{
Minkyu Kangd93d0f02010-08-13 16:07:35 +0900155 struct s5pc100_clock *clk =
156 (struct s5pc100_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900157 unsigned long div;
158 unsigned long dout_apll, armclk;
159 unsigned int apll_ratio, arm_ratio;
160
161 div = readl(&clk->div0);
162
163 /* ARM_RATIO: [6:4] */
164 arm_ratio = (div >> 4) & 0x7;
165 /* APLL_RATIO: [0] */
166 apll_ratio = div & 0x1;
167
168 dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
169 armclk = dout_apll / (arm_ratio + 1);
170
171 return armclk;
172}
173
174/* s5pc100: return HCLKD0 frequency */
175static unsigned long get_hclk(void)
176{
Minkyu Kangd93d0f02010-08-13 16:07:35 +0900177 struct s5pc100_clock *clk =
178 (struct s5pc100_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900179 unsigned long hclkd0;
180 uint div, d0_bus_ratio;
181
182 div = readl(&clk->div0);
183 /* D0_BUS_RATIO: [10:8] */
184 d0_bus_ratio = (div >> 8) & 0x7;
185
186 hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);
187
188 return hclkd0;
189}
190
191/* s5pc100: return PCLKD1 frequency */
192static unsigned long get_pclkd1(void)
193{
Minkyu Kangd93d0f02010-08-13 16:07:35 +0900194 struct s5pc100_clock *clk =
195 (struct s5pc100_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900196 unsigned long d1_bus, pclkd1;
197 uint div, d1_bus_ratio, pclkd1_ratio;
198
199 div = readl(&clk->div0);
200 /* D1_BUS_RATIO: [14:12] */
201 d1_bus_ratio = (div >> 12) & 0x7;
202 /* PCLKD1_RATIO: [18:16] */
203 pclkd1_ratio = (div >> 16) & 0x7;
204
205 /* ASYNC Mode */
206 d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1);
207 pclkd1 = d1_bus / (pclkd1_ratio + 1);
208
209 return pclkd1;
210}
211
212/* s5pc110: return HCLKs frequency */
213static unsigned long get_hclk_sys(int dom)
214{
Minkyu Kangd93d0f02010-08-13 16:07:35 +0900215 struct s5pc110_clock *clk =
216 (struct s5pc110_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900217 unsigned long hclk;
218 unsigned int div;
219 unsigned int offset;
220 unsigned int hclk_sys_ratio;
221
222 if (dom == CLK_M)
223 return get_hclk();
224
225 div = readl(&clk->div0);
226
227 /*
228 * HCLK_MSYS_RATIO: [10:8]
229 * HCLK_DSYS_RATIO: [19:16]
230 * HCLK_PSYS_RATIO: [27:24]
231 */
232 offset = 8 + (dom << 0x3);
233
234 hclk_sys_ratio = (div >> offset) & 0xf;
235
236 hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1);
237
238 return hclk;
239}
240
241/* s5pc110: return PCLKs frequency */
242static unsigned long get_pclk_sys(int dom)
243{
Minkyu Kangd93d0f02010-08-13 16:07:35 +0900244 struct s5pc110_clock *clk =
245 (struct s5pc110_clock *)samsung_get_base_clock();
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900246 unsigned long pclk;
247 unsigned int div;
248 unsigned int offset;
249 unsigned int pclk_sys_ratio;
250
251 div = readl(&clk->div0);
252
253 /*
254 * PCLK_MSYS_RATIO: [14:12]
255 * PCLK_DSYS_RATIO: [22:20]
256 * PCLK_PSYS_RATIO: [30:28]
257 */
258 offset = 12 + (dom << 0x3);
259
260 pclk_sys_ratio = (div >> offset) & 0x7;
261
262 pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);
263
264 return pclk;
265}
266
267/* s5pc110: return peripheral clock frequency */
268static unsigned long s5pc110_get_pclk(void)
269{
270 return get_pclk_sys(CLK_P);
271}
272
273/* s5pc100: return peripheral clock frequency */
274static unsigned long s5pc100_get_pclk(void)
275{
276 return get_pclkd1();
277}
278
Minkyu Kangf70409a2010-08-24 15:51:55 +0900279/* s5pc1xx: return uart clock frequency */
280static unsigned long s5pc1xx_get_uart_clk(int dev_index)
281{
282 if (cpu_is_s5pc110())
283 return s5pc110_get_pclk();
284 else
285 return s5pc100_get_pclk();
286}
287
288/* s5pc1xx: return pwm clock frequency */
289static unsigned long s5pc1xx_get_pwm_clk(void)
290{
291 if (cpu_is_s5pc110())
292 return s5pc110_get_pclk();
293 else
294 return s5pc100_get_pclk();
295}
296
Minkyu Kang3c152162010-12-27 15:55:48 +0900297unsigned long get_pll_clk(int pllreg)
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900298{
Minkyu Kang3c152162010-12-27 15:55:48 +0900299 if (cpu_is_s5pc110())
300 return s5pc110_get_pll_clk(pllreg);
301 else
302 return s5pc100_get_pll_clk(pllreg);
303}
304
305unsigned long get_arm_clk(void)
306{
307 if (cpu_is_s5pc110())
308 return s5pc110_get_arm_clk();
309 else
310 return s5pc100_get_arm_clk();
311}
312
313unsigned long get_pwm_clk(void)
314{
315 return s5pc1xx_get_pwm_clk();
316}
317
318unsigned long get_uart_clk(int dev_index)
319{
320 return s5pc1xx_get_uart_clk(dev_index);
Minkyu Kang399e5ae2009-10-01 17:20:01 +0900321}
Jaehoon Chung68a8cbf2011-05-17 21:19:17 +0000322
323void set_mmc_clk(int dev_index, unsigned int div)
324{
325 /* Do NOTHING */
326}