Commit | Line | Data |
---|---|---|
cf18acf0 BD |
1 | /* linux/arch/arm/plat-s3c64xx/s3c6400-clock.c |
2 | * | |
3 | * Copyright 2008 Openmoko, Inc. | |
4 | * Copyright 2008 Simtec Electronics | |
5 | * Ben Dooks <ben@simtec.co.uk> | |
6 | * http://armlinux.simtec.co.uk/ | |
7 | * | |
8 | * S3C6400 based common clock support | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | */ | |
14 | ||
15 | #include <linux/init.h> | |
16 | #include <linux/module.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/list.h> | |
19 | #include <linux/errno.h> | |
20 | #include <linux/err.h> | |
21 | #include <linux/clk.h> | |
22 | #include <linux/sysdev.h> | |
23 | #include <linux/io.h> | |
24 | ||
25 | #include <mach/hardware.h> | |
26 | #include <mach/map.h> | |
27 | ||
28 | #include <plat/cpu-freq.h> | |
29 | ||
3501c9ae | 30 | #include <mach/regs-clock.h> |
cf18acf0 | 31 | #include <plat/clock.h> |
399cae74 | 32 | #include <plat/clock-clksrc.h> |
cf18acf0 BD |
33 | #include <plat/cpu.h> |
34 | #include <plat/pll.h> | |
35 | ||
36 | /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call | |
37 | * ext_xtal_mux for want of an actual name from the manual. | |
38 | */ | |
39 | ||
3782d360 | 40 | static struct clk clk_ext_xtal_mux = { |
cf18acf0 BD |
41 | .name = "ext_xtal", |
42 | .id = -1, | |
43 | }; | |
44 | ||
45 | #define clk_fin_apll clk_ext_xtal_mux | |
46 | #define clk_fin_mpll clk_ext_xtal_mux | |
47 | #define clk_fin_epll clk_ext_xtal_mux | |
48 | ||
49 | #define clk_fout_mpll clk_mpll | |
87d26d2d | 50 | #define clk_fout_epll clk_epll |
cf18acf0 | 51 | |
3782d360 | 52 | static struct clk clk_fout_apll = { |
cf18acf0 BD |
53 | .name = "fout_apll", |
54 | .id = -1, | |
55 | }; | |
56 | ||
57 | static struct clk *clk_src_apll_list[] = { | |
58 | [0] = &clk_fin_apll, | |
59 | [1] = &clk_fout_apll, | |
60 | }; | |
61 | ||
399cae74 | 62 | static struct clksrc_sources clk_src_apll = { |
cf18acf0 BD |
63 | .sources = clk_src_apll_list, |
64 | .nr_sources = ARRAY_SIZE(clk_src_apll_list), | |
65 | }; | |
66 | ||
3782d360 | 67 | static struct clksrc_clk clk_mout_apll = { |
cf18acf0 BD |
68 | .clk = { |
69 | .name = "mout_apll", | |
70 | .id = -1, | |
71 | }, | |
f3e0b724 | 72 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 0, .size = 1 }, |
cf18acf0 BD |
73 | .sources = &clk_src_apll, |
74 | }; | |
75 | ||
cf18acf0 BD |
76 | static struct clk *clk_src_epll_list[] = { |
77 | [0] = &clk_fin_epll, | |
78 | [1] = &clk_fout_epll, | |
79 | }; | |
80 | ||
399cae74 | 81 | static struct clksrc_sources clk_src_epll = { |
cf18acf0 BD |
82 | .sources = clk_src_epll_list, |
83 | .nr_sources = ARRAY_SIZE(clk_src_epll_list), | |
84 | }; | |
85 | ||
3782d360 | 86 | static struct clksrc_clk clk_mout_epll = { |
cf18acf0 BD |
87 | .clk = { |
88 | .name = "mout_epll", | |
89 | .id = -1, | |
90 | }, | |
f3e0b724 | 91 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 2, .size = 1 }, |
cf18acf0 BD |
92 | .sources = &clk_src_epll, |
93 | }; | |
94 | ||
95 | static struct clk *clk_src_mpll_list[] = { | |
96 | [0] = &clk_fin_mpll, | |
97 | [1] = &clk_fout_mpll, | |
98 | }; | |
99 | ||
399cae74 | 100 | static struct clksrc_sources clk_src_mpll = { |
cf18acf0 BD |
101 | .sources = clk_src_mpll_list, |
102 | .nr_sources = ARRAY_SIZE(clk_src_mpll_list), | |
103 | }; | |
104 | ||
3782d360 | 105 | static struct clksrc_clk clk_mout_mpll = { |
cf18acf0 BD |
106 | .clk = { |
107 | .name = "mout_mpll", | |
108 | .id = -1, | |
109 | }, | |
f3e0b724 | 110 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 1, .size = 1 }, |
cf18acf0 BD |
111 | .sources = &clk_src_mpll, |
112 | }; | |
113 | ||
496a3f09 BD |
114 | static unsigned int armclk_mask; |
115 | ||
116 | static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk) | |
117 | { | |
118 | unsigned long rate = clk_get_rate(clk->parent); | |
119 | u32 clkdiv; | |
120 | ||
121 | /* divisor mask starts at bit0, so no need to shift */ | |
122 | clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask; | |
123 | ||
124 | return rate / (clkdiv + 1); | |
125 | } | |
126 | ||
127 | static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk, | |
128 | unsigned long rate) | |
129 | { | |
130 | unsigned long parent = clk_get_rate(clk->parent); | |
131 | u32 div; | |
132 | ||
133 | if (parent < rate) | |
1d91e1a2 | 134 | return parent; |
496a3f09 BD |
135 | |
136 | div = (parent / rate) - 1; | |
137 | if (div > armclk_mask) | |
138 | div = armclk_mask; | |
139 | ||
140 | return parent / (div + 1); | |
141 | } | |
142 | ||
143 | static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate) | |
144 | { | |
145 | unsigned long parent = clk_get_rate(clk->parent); | |
146 | u32 div; | |
147 | u32 val; | |
148 | ||
149 | if (rate < parent / (armclk_mask + 1)) | |
150 | return -EINVAL; | |
151 | ||
152 | rate = clk_round_rate(clk, rate); | |
153 | div = clk_get_rate(clk->parent) / rate; | |
154 | ||
155 | val = __raw_readl(S3C_CLK_DIV0); | |
9b71de49 | 156 | val &= ~armclk_mask; |
496a3f09 BD |
157 | val |= (div - 1); |
158 | __raw_writel(val, S3C_CLK_DIV0); | |
159 | ||
160 | return 0; | |
161 | ||
162 | } | |
163 | ||
164 | static struct clk clk_arm = { | |
165 | .name = "armclk", | |
166 | .id = -1, | |
167 | .parent = &clk_mout_apll.clk, | |
b3bf41be BD |
168 | .ops = &(struct clk_ops) { |
169 | .get_rate = s3c64xx_clk_arm_get_rate, | |
170 | .set_rate = s3c64xx_clk_arm_set_rate, | |
171 | .round_rate = s3c64xx_clk_arm_round_rate, | |
172 | }, | |
496a3f09 BD |
173 | }; |
174 | ||
cf18acf0 BD |
175 | static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk) |
176 | { | |
177 | unsigned long rate = clk_get_rate(clk->parent); | |
178 | ||
39669f59 | 179 | printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate); |
cf18acf0 BD |
180 | |
181 | if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK) | |
182 | rate /= 2; | |
183 | ||
184 | return rate; | |
185 | } | |
186 | ||
b3bf41be BD |
187 | static struct clk_ops clk_dout_ops = { |
188 | .get_rate = s3c64xx_clk_doutmpll_get_rate, | |
189 | }; | |
190 | ||
3782d360 | 191 | static struct clk clk_dout_mpll = { |
cf18acf0 BD |
192 | .name = "dout_mpll", |
193 | .id = -1, | |
194 | .parent = &clk_mout_mpll.clk, | |
b3bf41be | 195 | .ops = &clk_dout_ops, |
cf18acf0 BD |
196 | }; |
197 | ||
198 | static struct clk *clkset_spi_mmc_list[] = { | |
199 | &clk_mout_epll.clk, | |
200 | &clk_dout_mpll, | |
201 | &clk_fin_epll, | |
202 | &clk_27m, | |
203 | }; | |
204 | ||
399cae74 | 205 | static struct clksrc_sources clkset_spi_mmc = { |
cf18acf0 BD |
206 | .sources = clkset_spi_mmc_list, |
207 | .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list), | |
208 | }; | |
209 | ||
210 | static struct clk *clkset_irda_list[] = { | |
211 | &clk_mout_epll.clk, | |
212 | &clk_dout_mpll, | |
213 | NULL, | |
214 | &clk_27m, | |
215 | }; | |
216 | ||
399cae74 | 217 | static struct clksrc_sources clkset_irda = { |
cf18acf0 BD |
218 | .sources = clkset_irda_list, |
219 | .nr_sources = ARRAY_SIZE(clkset_irda_list), | |
220 | }; | |
221 | ||
222 | static struct clk *clkset_uart_list[] = { | |
223 | &clk_mout_epll.clk, | |
224 | &clk_dout_mpll, | |
225 | NULL, | |
226 | NULL | |
227 | }; | |
228 | ||
399cae74 | 229 | static struct clksrc_sources clkset_uart = { |
cf18acf0 BD |
230 | .sources = clkset_uart_list, |
231 | .nr_sources = ARRAY_SIZE(clkset_uart_list), | |
232 | }; | |
233 | ||
234 | static struct clk *clkset_uhost_list[] = { | |
41ba41d7 | 235 | &clk_48m, |
cf18acf0 BD |
236 | &clk_mout_epll.clk, |
237 | &clk_dout_mpll, | |
238 | &clk_fin_epll, | |
cf18acf0 BD |
239 | }; |
240 | ||
399cae74 | 241 | static struct clksrc_sources clkset_uhost = { |
cf18acf0 BD |
242 | .sources = clkset_uhost_list, |
243 | .nr_sources = ARRAY_SIZE(clkset_uhost_list), | |
244 | }; | |
245 | ||
cf18acf0 BD |
246 | /* The peripheral clocks are all controlled via clocksource followed |
247 | * by an optional divider and gate stage. We currently roll this into | |
248 | * one clock which hides the intermediate clock from the mux. | |
249 | * | |
250 | * Note, the JPEG clock can only be an even divider... | |
251 | * | |
252 | * The scaler and LCD clocks depend on the S3C64XX version, and also | |
253 | * have a common parent divisor so are not included here. | |
254 | */ | |
255 | ||
8360493c | 256 | /* clocks that feed other parts of the clock source tree */ |
cf18acf0 BD |
257 | |
258 | static struct clk clk_iis_cd0 = { | |
259 | .name = "iis_cdclk0", | |
260 | .id = -1, | |
261 | }; | |
262 | ||
263 | static struct clk clk_iis_cd1 = { | |
264 | .name = "iis_cdclk1", | |
265 | .id = -1, | |
266 | }; | |
267 | ||
268 | static struct clk clk_pcm_cd = { | |
269 | .name = "pcm_cdclk", | |
270 | .id = -1, | |
271 | }; | |
272 | ||
273 | static struct clk *clkset_audio0_list[] = { | |
274 | [0] = &clk_mout_epll.clk, | |
275 | [1] = &clk_dout_mpll, | |
276 | [2] = &clk_fin_epll, | |
277 | [3] = &clk_iis_cd0, | |
278 | [4] = &clk_pcm_cd, | |
279 | }; | |
280 | ||
399cae74 | 281 | static struct clksrc_sources clkset_audio0 = { |
cf18acf0 BD |
282 | .sources = clkset_audio0_list, |
283 | .nr_sources = ARRAY_SIZE(clkset_audio0_list), | |
284 | }; | |
285 | ||
cf18acf0 BD |
286 | static struct clk *clkset_audio1_list[] = { |
287 | [0] = &clk_mout_epll.clk, | |
288 | [1] = &clk_dout_mpll, | |
289 | [2] = &clk_fin_epll, | |
290 | [3] = &clk_iis_cd1, | |
291 | [4] = &clk_pcm_cd, | |
292 | }; | |
293 | ||
399cae74 | 294 | static struct clksrc_sources clkset_audio1 = { |
cf18acf0 BD |
295 | .sources = clkset_audio1_list, |
296 | .nr_sources = ARRAY_SIZE(clkset_audio1_list), | |
297 | }; | |
298 | ||
e2c977dc WA |
299 | static struct clk *clkset_camif_list[] = { |
300 | &clk_h2, | |
301 | }; | |
302 | ||
399cae74 | 303 | static struct clksrc_sources clkset_camif = { |
e2c977dc WA |
304 | .sources = clkset_camif_list, |
305 | .nr_sources = ARRAY_SIZE(clkset_camif_list), | |
306 | }; | |
307 | ||
8360493c BD |
308 | static struct clksrc_clk clksrcs[] = { |
309 | { | |
310 | .clk = { | |
311 | .name = "mmc_bus", | |
312 | .id = 0, | |
313 | .ctrlbit = S3C_CLKCON_SCLK_MMC0, | |
314 | .enable = s3c64xx_sclk_ctrl, | |
315 | }, | |
f3e0b724 BD |
316 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2 }, |
317 | .reg_div = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4 }, | |
8360493c | 318 | .sources = &clkset_spi_mmc, |
8360493c BD |
319 | }, { |
320 | .clk = { | |
321 | .name = "mmc_bus", | |
322 | .id = 1, | |
323 | .ctrlbit = S3C_CLKCON_SCLK_MMC1, | |
324 | .enable = s3c64xx_sclk_ctrl, | |
325 | }, | |
f3e0b724 BD |
326 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2 }, |
327 | .reg_div = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4 }, | |
8360493c | 328 | .sources = &clkset_spi_mmc, |
8360493c BD |
329 | }, { |
330 | .clk = { | |
331 | .name = "mmc_bus", | |
332 | .id = 2, | |
333 | .ctrlbit = S3C_CLKCON_SCLK_MMC2, | |
334 | .enable = s3c64xx_sclk_ctrl, | |
335 | }, | |
f3e0b724 BD |
336 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2 }, |
337 | .reg_div = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4 }, | |
8360493c | 338 | .sources = &clkset_spi_mmc, |
8360493c BD |
339 | }, { |
340 | .clk = { | |
341 | .name = "usb-bus-host", | |
342 | .id = -1, | |
343 | .ctrlbit = S3C_CLKCON_SCLK_UHOST, | |
344 | .enable = s3c64xx_sclk_ctrl, | |
345 | }, | |
f3e0b724 BD |
346 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2 }, |
347 | .reg_div = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4 }, | |
8360493c | 348 | .sources = &clkset_uhost, |
8360493c BD |
349 | }, { |
350 | .clk = { | |
351 | .name = "uclk1", | |
352 | .id = -1, | |
353 | .ctrlbit = S3C_CLKCON_SCLK_UART, | |
354 | .enable = s3c64xx_sclk_ctrl, | |
355 | }, | |
f3e0b724 BD |
356 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1 }, |
357 | .reg_div = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4 }, | |
8360493c | 358 | .sources = &clkset_uart, |
8360493c BD |
359 | }, { |
360 | /* Where does UCLK0 come from? */ | |
361 | .clk = { | |
362 | .name = "spi-bus", | |
363 | .id = 0, | |
364 | .ctrlbit = S3C_CLKCON_SCLK_SPI0, | |
365 | .enable = s3c64xx_sclk_ctrl, | |
366 | }, | |
f3e0b724 BD |
367 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 }, |
368 | .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 }, | |
8360493c | 369 | .sources = &clkset_spi_mmc, |
8360493c BD |
370 | }, { |
371 | .clk = { | |
372 | .name = "spi-bus", | |
373 | .id = 1, | |
374 | .ctrlbit = S3C_CLKCON_SCLK_SPI1, | |
375 | .enable = s3c64xx_sclk_ctrl, | |
376 | }, | |
f3e0b724 BD |
377 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 }, |
378 | .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 }, | |
8360493c | 379 | .sources = &clkset_spi_mmc, |
8360493c BD |
380 | }, { |
381 | .clk = { | |
382 | .name = "audio-bus", | |
383 | .id = 0, | |
384 | .ctrlbit = S3C_CLKCON_SCLK_AUDIO0, | |
385 | .enable = s3c64xx_sclk_ctrl, | |
386 | }, | |
f3e0b724 BD |
387 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3 }, |
388 | .reg_div = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4 }, | |
8360493c | 389 | .sources = &clkset_audio0, |
8360493c BD |
390 | }, { |
391 | .clk = { | |
392 | .name = "audio-bus", | |
393 | .id = 1, | |
394 | .ctrlbit = S3C_CLKCON_SCLK_AUDIO1, | |
395 | .enable = s3c64xx_sclk_ctrl, | |
396 | }, | |
f3e0b724 BD |
397 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3 }, |
398 | .reg_div = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4 }, | |
8360493c | 399 | .sources = &clkset_audio1, |
8360493c BD |
400 | }, { |
401 | .clk = { | |
402 | .name = "irda-bus", | |
403 | .id = 0, | |
404 | .ctrlbit = S3C_CLKCON_SCLK_IRDA, | |
405 | .enable = s3c64xx_sclk_ctrl, | |
406 | }, | |
f3e0b724 BD |
407 | .reg_src = { .reg = S3C_CLK_SRC, .shift = 24, .size = 2 }, |
408 | .reg_div = { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4 }, | |
8360493c | 409 | .sources = &clkset_irda, |
8360493c BD |
410 | }, { |
411 | .clk = { | |
412 | .name = "camera", | |
413 | .id = -1, | |
414 | .ctrlbit = S3C_CLKCON_SCLK_CAM, | |
415 | .enable = s3c64xx_sclk_ctrl, | |
416 | }, | |
f3e0b724 BD |
417 | .reg_div = { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4 }, |
418 | .reg_src = { .reg = NULL, .shift = 0, .size = 0 }, | |
8360493c | 419 | .sources = &clkset_camif, |
e2c977dc | 420 | }, |
e2c977dc WA |
421 | }; |
422 | ||
cf18acf0 BD |
423 | /* Clock initialisation code */ |
424 | ||
425 | static struct clksrc_clk *init_parents[] = { | |
426 | &clk_mout_apll, | |
427 | &clk_mout_epll, | |
428 | &clk_mout_mpll, | |
cf18acf0 BD |
429 | }; |
430 | ||
cf18acf0 BD |
431 | #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) |
432 | ||
433 | void __init_or_cpufreq s3c6400_setup_clocks(void) | |
434 | { | |
435 | struct clk *xtal_clk; | |
436 | unsigned long xtal; | |
437 | unsigned long fclk; | |
438 | unsigned long hclk; | |
439 | unsigned long hclk2; | |
440 | unsigned long pclk; | |
441 | unsigned long epll; | |
442 | unsigned long apll; | |
443 | unsigned long mpll; | |
444 | unsigned int ptr; | |
445 | u32 clkdiv0; | |
446 | ||
39669f59 | 447 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); |
cf18acf0 BD |
448 | |
449 | clkdiv0 = __raw_readl(S3C_CLK_DIV0); | |
39669f59 | 450 | printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0); |
cf18acf0 BD |
451 | |
452 | xtal_clk = clk_get(NULL, "xtal"); | |
453 | BUG_ON(IS_ERR(xtal_clk)); | |
454 | ||
455 | xtal = clk_get_rate(xtal_clk); | |
456 | clk_put(xtal_clk); | |
457 | ||
39669f59 | 458 | printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); |
cf18acf0 | 459 | |
e179ac0f MB |
460 | /* For now assume the mux always selects the crystal */ |
461 | clk_ext_xtal_mux.parent = xtal_clk; | |
462 | ||
cf18acf0 BD |
463 | epll = s3c6400_get_epll(xtal); |
464 | mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON)); | |
465 | apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON)); | |
466 | ||
467 | fclk = mpll; | |
468 | ||
469 | printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n", | |
470 | apll, mpll, epll); | |
471 | ||
472 | hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2); | |
473 | hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK); | |
474 | pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK); | |
475 | ||
476 | printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n", | |
477 | hclk2, hclk, pclk); | |
478 | ||
479 | clk_fout_mpll.rate = mpll; | |
480 | clk_fout_epll.rate = epll; | |
481 | clk_fout_apll.rate = apll; | |
482 | ||
a03f7daf | 483 | clk_h2.rate = hclk2; |
cf18acf0 BD |
484 | clk_h.rate = hclk; |
485 | clk_p.rate = pclk; | |
486 | clk_f.rate = fclk; | |
487 | ||
488 | for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++) | |
682e2b7d | 489 | s3c_set_clksrc(init_parents[ptr], true); |
8360493c BD |
490 | |
491 | for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) | |
682e2b7d | 492 | s3c_set_clksrc(&clksrcs[ptr], true); |
cf18acf0 BD |
493 | } |
494 | ||
495 | static struct clk *clks[] __initdata = { | |
496 | &clk_ext_xtal_mux, | |
497 | &clk_iis_cd0, | |
498 | &clk_iis_cd1, | |
499 | &clk_pcm_cd, | |
500 | &clk_mout_epll.clk, | |
501 | &clk_mout_mpll.clk, | |
502 | &clk_dout_mpll, | |
496a3f09 | 503 | &clk_arm, |
cf18acf0 BD |
504 | }; |
505 | ||
496a3f09 BD |
506 | /** |
507 | * s3c6400_register_clocks - register clocks for s3c6400 and above | |
508 | * @armclk_divlimit: Divisor mask for ARMCLK | |
509 | * | |
510 | * Register the clocks for the S3C6400 and above SoC range, such | |
511 | * as ARMCLK and the clocks which have divider chains attached. | |
512 | * | |
513 | * This call does not setup the clocks, which is left to the | |
514 | * s3c6400_setup_clocks() call which may be needed by the cpufreq | |
515 | * or resume code to re-set the clocks if the bootloader has changed | |
516 | * them. | |
517 | */ | |
518 | void __init s3c6400_register_clocks(unsigned armclk_divlimit) | |
cf18acf0 BD |
519 | { |
520 | struct clk *clkp; | |
521 | int ret; | |
522 | int ptr; | |
523 | ||
496a3f09 BD |
524 | armclk_mask = armclk_divlimit; |
525 | ||
cf18acf0 BD |
526 | for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { |
527 | clkp = clks[ptr]; | |
528 | ret = s3c24xx_register_clock(clkp); | |
529 | if (ret < 0) { | |
530 | printk(KERN_ERR "Failed to register clock %s (%d)\n", | |
531 | clkp->name, ret); | |
532 | } | |
533 | } | |
8360493c | 534 | |
399cae74 | 535 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); |
cf18acf0 | 536 | } |