1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2009 Samsung Electronics
4 * Minkyu Kang <mk7.kang@samsung.com>
5 * Heungjun Kim <riverful.kim@samsung.com>
10 #include <asm/arch/clock.h>
11 #include <asm/arch/clk.h>
17 #ifndef CONFIG_SYS_CLK_FREQ_C100
18 #define CONFIG_SYS_CLK_FREQ_C100 12000000
20 #ifndef CONFIG_SYS_CLK_FREQ_C110
21 #define CONFIG_SYS_CLK_FREQ_C110 24000000
24 /* s5pc110: return pll clock frequency */
25 static unsigned long s5pc100_get_pll_clk(int pllreg)
27 struct s5pc100_clock *clk =
28 (struct s5pc100_clock *)samsung_get_base_clock();
29 unsigned long r, m, p, s, mask, fout;
34 r = readl(&clk->apll_con);
37 r = readl(&clk->mpll_con);
40 r = readl(&clk->epll_con);
43 r = readl(&clk->hpll_con);
46 printf("Unsupported PLL (%d)\n", pllreg);
51 * APLL_CON: MIDV [25:16]
52 * MPLL_CON: MIDV [23:16]
53 * EPLL_CON: MIDV [23:16]
54 * HPLL_CON: MIDV [23:16]
68 /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
69 freq = CONFIG_SYS_CLK_FREQ_C100;
70 fout = m * (freq / (p * (1 << s)));
75 /* s5pc100: return pll clock frequency */
76 static unsigned long s5pc110_get_pll_clk(int pllreg)
78 struct s5pc110_clock *clk =
79 (struct s5pc110_clock *)samsung_get_base_clock();
80 unsigned long r, m, p, s, mask, fout;
85 r = readl(&clk->apll_con);
88 r = readl(&clk->mpll_con);
91 r = readl(&clk->epll_con);
94 r = readl(&clk->vpll_con);
97 printf("Unsupported PLL (%d)\n", pllreg);
102 * APLL_CON: MIDV [25:16]
103 * MPLL_CON: MIDV [25:16]
104 * EPLL_CON: MIDV [24:16]
105 * VPLL_CON: MIDV [24:16]
107 if (pllreg == APLL || pllreg == MPLL)
112 m = (r >> 16) & mask;
119 freq = CONFIG_SYS_CLK_FREQ_C110;
120 if (pllreg == APLL) {
123 /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
124 fout = m * (freq / (p * (1 << (s - 1))));
126 /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
127 fout = m * (freq / (p * (1 << s)));
132 /* s5pc110: return ARM clock frequency */
133 static unsigned long s5pc110_get_arm_clk(void)
135 struct s5pc110_clock *clk =
136 (struct s5pc110_clock *)samsung_get_base_clock();
138 unsigned long dout_apll, armclk;
139 unsigned int apll_ratio;
141 div = readl(&clk->div0);
143 /* APLL_RATIO: [2:0] */
144 apll_ratio = div & 0x7;
146 dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
152 /* s5pc100: return ARM clock frequency */
153 static unsigned long s5pc100_get_arm_clk(void)
155 struct s5pc100_clock *clk =
156 (struct s5pc100_clock *)samsung_get_base_clock();
158 unsigned long dout_apll, armclk;
159 unsigned int apll_ratio, arm_ratio;
161 div = readl(&clk->div0);
163 /* ARM_RATIO: [6:4] */
164 arm_ratio = (div >> 4) & 0x7;
165 /* APLL_RATIO: [0] */
166 apll_ratio = div & 0x1;
168 dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
169 armclk = dout_apll / (arm_ratio + 1);
174 /* s5pc100: return HCLKD0 frequency */
175 static unsigned long get_hclk(void)
177 struct s5pc100_clock *clk =
178 (struct s5pc100_clock *)samsung_get_base_clock();
179 unsigned long hclkd0;
180 uint div, d0_bus_ratio;
182 div = readl(&clk->div0);
183 /* D0_BUS_RATIO: [10:8] */
184 d0_bus_ratio = (div >> 8) & 0x7;
186 hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);
191 /* s5pc100: return PCLKD1 frequency */
192 static unsigned long get_pclkd1(void)
194 struct s5pc100_clock *clk =
195 (struct s5pc100_clock *)samsung_get_base_clock();
196 unsigned long d1_bus, pclkd1;
197 uint div, d1_bus_ratio, pclkd1_ratio;
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;
206 d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1);
207 pclkd1 = d1_bus / (pclkd1_ratio + 1);
212 /* s5pc110: return HCLKs frequency */
213 static unsigned long get_hclk_sys(int dom)
215 struct s5pc110_clock *clk =
216 (struct s5pc110_clock *)samsung_get_base_clock();
220 unsigned int hclk_sys_ratio;
225 div = readl(&clk->div0);
228 * HCLK_MSYS_RATIO: [10:8]
229 * HCLK_DSYS_RATIO: [19:16]
230 * HCLK_PSYS_RATIO: [27:24]
232 offset = 8 + (dom << 0x3);
234 hclk_sys_ratio = (div >> offset) & 0xf;
236 hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1);
241 /* s5pc110: return PCLKs frequency */
242 static unsigned long get_pclk_sys(int dom)
244 struct s5pc110_clock *clk =
245 (struct s5pc110_clock *)samsung_get_base_clock();
249 unsigned int pclk_sys_ratio;
251 div = readl(&clk->div0);
254 * PCLK_MSYS_RATIO: [14:12]
255 * PCLK_DSYS_RATIO: [22:20]
256 * PCLK_PSYS_RATIO: [30:28]
258 offset = 12 + (dom << 0x3);
260 pclk_sys_ratio = (div >> offset) & 0x7;
262 pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);
267 /* s5pc110: return peripheral clock frequency */
268 static unsigned long s5pc110_get_pclk(void)
270 return get_pclk_sys(CLK_P);
273 /* s5pc100: return peripheral clock frequency */
274 static unsigned long s5pc100_get_pclk(void)
279 /* s5pc1xx: return uart clock frequency */
280 static unsigned long s5pc1xx_get_uart_clk(int dev_index)
282 if (cpu_is_s5pc110())
283 return s5pc110_get_pclk();
285 return s5pc100_get_pclk();
288 /* s5pc1xx: return pwm clock frequency */
289 static unsigned long s5pc1xx_get_pwm_clk(void)
291 if (cpu_is_s5pc110())
292 return s5pc110_get_pclk();
294 return s5pc100_get_pclk();
297 unsigned long get_pll_clk(int pllreg)
299 if (cpu_is_s5pc110())
300 return s5pc110_get_pll_clk(pllreg);
302 return s5pc100_get_pll_clk(pllreg);
305 unsigned long get_arm_clk(void)
307 if (cpu_is_s5pc110())
308 return s5pc110_get_arm_clk();
310 return s5pc100_get_arm_clk();
313 unsigned long get_pwm_clk(void)
315 return s5pc1xx_get_pwm_clk();
318 unsigned long get_uart_clk(int dev_index)
320 return s5pc1xx_get_uart_clk(dev_index);
323 void set_mmc_clk(int dev_index, unsigned int div)