blob: 20af0c29979a944e9456e03b30599f206b0c0aea [file] [log] [blame]
Ben Dookscf18acf2008-10-21 14:07:02 +01001/* 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
30#include <plat/regs-clock.h>
31#include <plat/clock.h>
Ben Dooks399cae72009-12-01 01:24:35 +000032#include <plat/clock-clksrc.h>
Ben Dookscf18acf2008-10-21 14:07:02 +010033#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
Ben Dooks3782d362009-02-27 11:25:37 +000040static struct clk clk_ext_xtal_mux = {
Ben Dookscf18acf2008-10-21 14:07:02 +010041 .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
Ben Dooks87d26d22010-01-07 11:05:55 +090050#define clk_fout_epll clk_epll
Ben Dookscf18acf2008-10-21 14:07:02 +010051
Ben Dooks3782d362009-02-27 11:25:37 +000052static struct clk clk_fout_apll = {
Ben Dookscf18acf2008-10-21 14:07:02 +010053 .name = "fout_apll",
54 .id = -1,
55};
56
57static struct clk *clk_src_apll_list[] = {
58 [0] = &clk_fin_apll,
59 [1] = &clk_fout_apll,
60};
61
Ben Dooks399cae72009-12-01 01:24:35 +000062static struct clksrc_sources clk_src_apll = {
Ben Dookscf18acf2008-10-21 14:07:02 +010063 .sources = clk_src_apll_list,
64 .nr_sources = ARRAY_SIZE(clk_src_apll_list),
65};
66
Ben Dooks3782d362009-02-27 11:25:37 +000067static struct clksrc_clk clk_mout_apll = {
Ben Dookscf18acf2008-10-21 14:07:02 +010068 .clk = {
69 .name = "mout_apll",
70 .id = -1,
71 },
Ben Dooks399cae72009-12-01 01:24:35 +000072 .reg_src = { S3C_CLK_SRC, 0, 1 },
Ben Dookscf18acf2008-10-21 14:07:02 +010073 .sources = &clk_src_apll,
74};
75
Ben Dookscf18acf2008-10-21 14:07:02 +010076static struct clk *clk_src_epll_list[] = {
77 [0] = &clk_fin_epll,
78 [1] = &clk_fout_epll,
79};
80
Ben Dooks399cae72009-12-01 01:24:35 +000081static struct clksrc_sources clk_src_epll = {
Ben Dookscf18acf2008-10-21 14:07:02 +010082 .sources = clk_src_epll_list,
83 .nr_sources = ARRAY_SIZE(clk_src_epll_list),
84};
85
Ben Dooks3782d362009-02-27 11:25:37 +000086static struct clksrc_clk clk_mout_epll = {
Ben Dookscf18acf2008-10-21 14:07:02 +010087 .clk = {
88 .name = "mout_epll",
89 .id = -1,
90 },
Ben Dooks399cae72009-12-01 01:24:35 +000091 .reg_src = { S3C_CLK_SRC, 2, 1 },
Ben Dookscf18acf2008-10-21 14:07:02 +010092 .sources = &clk_src_epll,
93};
94
95static struct clk *clk_src_mpll_list[] = {
96 [0] = &clk_fin_mpll,
97 [1] = &clk_fout_mpll,
98};
99
Ben Dooks399cae72009-12-01 01:24:35 +0000100static struct clksrc_sources clk_src_mpll = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100101 .sources = clk_src_mpll_list,
102 .nr_sources = ARRAY_SIZE(clk_src_mpll_list),
103};
104
Ben Dooks3782d362009-02-27 11:25:37 +0000105static struct clksrc_clk clk_mout_mpll = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100106 .clk = {
107 .name = "mout_mpll",
108 .id = -1,
109 },
Ben Dooks399cae72009-12-01 01:24:35 +0000110 .reg_src = { S3C_CLK_SRC, 1, 1 },
Ben Dookscf18acf2008-10-21 14:07:02 +0100111 .sources = &clk_src_mpll,
112};
113
Ben Dooks496a3f02009-05-02 13:48:53 +0100114static unsigned int armclk_mask;
115
116static 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
127static 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)
Mark Brown1d91e1a2009-07-15 13:03:34 +0100134 return parent;
Ben Dooks496a3f02009-05-02 13:48:53 +0100135
136 div = (parent / rate) - 1;
137 if (div > armclk_mask)
138 div = armclk_mask;
139
140 return parent / (div + 1);
141}
142
143static 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);
Mark Brown9b71de42009-07-15 13:03:35 +0100156 val &= ~armclk_mask;
Ben Dooks496a3f02009-05-02 13:48:53 +0100157 val |= (div - 1);
158 __raw_writel(val, S3C_CLK_DIV0);
159
160 return 0;
161
162}
163
164static struct clk clk_arm = {
165 .name = "armclk",
166 .id = -1,
167 .parent = &clk_mout_apll.clk,
168 .get_rate = s3c64xx_clk_arm_get_rate,
169 .set_rate = s3c64xx_clk_arm_set_rate,
170 .round_rate = s3c64xx_clk_arm_round_rate,
171};
172
Ben Dookscf18acf2008-10-21 14:07:02 +0100173static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
174{
175 unsigned long rate = clk_get_rate(clk->parent);
176
Ben Dooks39669f52008-10-21 14:07:12 +0100177 printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
Ben Dookscf18acf2008-10-21 14:07:02 +0100178
179 if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
180 rate /= 2;
181
182 return rate;
183}
184
Ben Dooks3782d362009-02-27 11:25:37 +0000185static struct clk clk_dout_mpll = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100186 .name = "dout_mpll",
187 .id = -1,
188 .parent = &clk_mout_mpll.clk,
189 .get_rate = s3c64xx_clk_doutmpll_get_rate,
190};
191
192static struct clk *clkset_spi_mmc_list[] = {
193 &clk_mout_epll.clk,
194 &clk_dout_mpll,
195 &clk_fin_epll,
196 &clk_27m,
197};
198
Ben Dooks399cae72009-12-01 01:24:35 +0000199static struct clksrc_sources clkset_spi_mmc = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100200 .sources = clkset_spi_mmc_list,
201 .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list),
202};
203
204static struct clk *clkset_irda_list[] = {
205 &clk_mout_epll.clk,
206 &clk_dout_mpll,
207 NULL,
208 &clk_27m,
209};
210
Ben Dooks399cae72009-12-01 01:24:35 +0000211static struct clksrc_sources clkset_irda = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100212 .sources = clkset_irda_list,
213 .nr_sources = ARRAY_SIZE(clkset_irda_list),
214};
215
216static struct clk *clkset_uart_list[] = {
217 &clk_mout_epll.clk,
218 &clk_dout_mpll,
219 NULL,
220 NULL
221};
222
Ben Dooks399cae72009-12-01 01:24:35 +0000223static struct clksrc_sources clkset_uart = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100224 .sources = clkset_uart_list,
225 .nr_sources = ARRAY_SIZE(clkset_uart_list),
226};
227
228static struct clk *clkset_uhost_list[] = {
Ben Dooks41ba41d2009-02-26 23:00:34 +0000229 &clk_48m,
Ben Dookscf18acf2008-10-21 14:07:02 +0100230 &clk_mout_epll.clk,
231 &clk_dout_mpll,
232 &clk_fin_epll,
Ben Dookscf18acf2008-10-21 14:07:02 +0100233};
234
Ben Dooks399cae72009-12-01 01:24:35 +0000235static struct clksrc_sources clkset_uhost = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100236 .sources = clkset_uhost_list,
237 .nr_sources = ARRAY_SIZE(clkset_uhost_list),
238};
239
Ben Dookscf18acf2008-10-21 14:07:02 +0100240/* The peripheral clocks are all controlled via clocksource followed
241 * by an optional divider and gate stage. We currently roll this into
242 * one clock which hides the intermediate clock from the mux.
243 *
244 * Note, the JPEG clock can only be an even divider...
245 *
246 * The scaler and LCD clocks depend on the S3C64XX version, and also
247 * have a common parent divisor so are not included here.
248 */
249
Ben Dooks83604932009-11-30 01:31:32 +0000250/* clocks that feed other parts of the clock source tree */
Ben Dookscf18acf2008-10-21 14:07:02 +0100251
252static struct clk clk_iis_cd0 = {
253 .name = "iis_cdclk0",
254 .id = -1,
255};
256
257static struct clk clk_iis_cd1 = {
258 .name = "iis_cdclk1",
259 .id = -1,
260};
261
262static struct clk clk_pcm_cd = {
263 .name = "pcm_cdclk",
264 .id = -1,
265};
266
267static struct clk *clkset_audio0_list[] = {
268 [0] = &clk_mout_epll.clk,
269 [1] = &clk_dout_mpll,
270 [2] = &clk_fin_epll,
271 [3] = &clk_iis_cd0,
272 [4] = &clk_pcm_cd,
273};
274
Ben Dooks399cae72009-12-01 01:24:35 +0000275static struct clksrc_sources clkset_audio0 = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100276 .sources = clkset_audio0_list,
277 .nr_sources = ARRAY_SIZE(clkset_audio0_list),
278};
279
Ben Dookscf18acf2008-10-21 14:07:02 +0100280static struct clk *clkset_audio1_list[] = {
281 [0] = &clk_mout_epll.clk,
282 [1] = &clk_dout_mpll,
283 [2] = &clk_fin_epll,
284 [3] = &clk_iis_cd1,
285 [4] = &clk_pcm_cd,
286};
287
Ben Dooks399cae72009-12-01 01:24:35 +0000288static struct clksrc_sources clkset_audio1 = {
Ben Dookscf18acf2008-10-21 14:07:02 +0100289 .sources = clkset_audio1_list,
290 .nr_sources = ARRAY_SIZE(clkset_audio1_list),
291};
292
Werner Almesbergere2c977d2009-03-05 11:43:14 +0800293static struct clk *clkset_camif_list[] = {
294 &clk_h2,
295};
296
Ben Dooks399cae72009-12-01 01:24:35 +0000297static struct clksrc_sources clkset_camif = {
Werner Almesbergere2c977d2009-03-05 11:43:14 +0800298 .sources = clkset_camif_list,
299 .nr_sources = ARRAY_SIZE(clkset_camif_list),
300};
301
Ben Dooks83604932009-11-30 01:31:32 +0000302static struct clksrc_clk clksrcs[] = {
303 {
304 .clk = {
305 .name = "mmc_bus",
306 .id = 0,
307 .ctrlbit = S3C_CLKCON_SCLK_MMC0,
308 .enable = s3c64xx_sclk_ctrl,
309 },
Ben Dooks399cae72009-12-01 01:24:35 +0000310 .reg_src = { S3C_CLK_SRC, 18, 2 },
311 .reg_div = { S3C_CLK_DIV1, 0, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000312 .sources = &clkset_spi_mmc,
Ben Dooks83604932009-11-30 01:31:32 +0000313 }, {
314 .clk = {
315 .name = "mmc_bus",
316 .id = 1,
317 .ctrlbit = S3C_CLKCON_SCLK_MMC1,
318 .enable = s3c64xx_sclk_ctrl,
319 },
Ben Dooks399cae72009-12-01 01:24:35 +0000320 .reg_src = { S3C_CLK_SRC, 20, 2 },
321 .reg_div = { S3C_CLK_DIV1, 4, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000322 .sources = &clkset_spi_mmc,
Ben Dooks83604932009-11-30 01:31:32 +0000323 }, {
324 .clk = {
325 .name = "mmc_bus",
326 .id = 2,
327 .ctrlbit = S3C_CLKCON_SCLK_MMC2,
328 .enable = s3c64xx_sclk_ctrl,
329 },
Ben Dooks399cae72009-12-01 01:24:35 +0000330 .reg_src = { S3C_CLK_SRC, 22, 2 },
331 .reg_div = { S3C_CLK_DIV1, 8, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000332 .sources = &clkset_spi_mmc,
Ben Dooks83604932009-11-30 01:31:32 +0000333 }, {
334 .clk = {
335 .name = "usb-bus-host",
336 .id = -1,
337 .ctrlbit = S3C_CLKCON_SCLK_UHOST,
338 .enable = s3c64xx_sclk_ctrl,
339 },
Ben Dooks399cae72009-12-01 01:24:35 +0000340 .reg_src = { S3C_CLK_SRC, 5, 2 },
341 .reg_div = { S3C_CLK_DIV1, 20, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000342 .sources = &clkset_uhost,
Ben Dooks83604932009-11-30 01:31:32 +0000343 }, {
344 .clk = {
345 .name = "uclk1",
346 .id = -1,
347 .ctrlbit = S3C_CLKCON_SCLK_UART,
348 .enable = s3c64xx_sclk_ctrl,
349 },
Ben Dooks399cae72009-12-01 01:24:35 +0000350 .reg_src = { S3C_CLK_SRC, 13, 1 },
351 .reg_div = { S3C_CLK_DIV2, 16, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000352 .sources = &clkset_uart,
Ben Dooks83604932009-11-30 01:31:32 +0000353 }, {
354/* Where does UCLK0 come from? */
355 .clk = {
356 .name = "spi-bus",
357 .id = 0,
358 .ctrlbit = S3C_CLKCON_SCLK_SPI0,
359 .enable = s3c64xx_sclk_ctrl,
360 },
Ben Dooks399cae72009-12-01 01:24:35 +0000361 .reg_src = { S3C_CLK_SRC, 14, 2 },
362 .reg_div = { S3C_CLK_DIV2, 0, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000363 .sources = &clkset_spi_mmc,
Ben Dooks83604932009-11-30 01:31:32 +0000364 }, {
365 .clk = {
366 .name = "spi-bus",
367 .id = 1,
368 .ctrlbit = S3C_CLKCON_SCLK_SPI1,
369 .enable = s3c64xx_sclk_ctrl,
370 },
Ben Dooks399cae72009-12-01 01:24:35 +0000371 .reg_src = { S3C_CLK_SRC, 16, 2 },
372 .reg_div = { S3C_CLK_DIV2, 4, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000373 .sources = &clkset_spi_mmc,
Ben Dooks83604932009-11-30 01:31:32 +0000374 }, {
375 .clk = {
376 .name = "audio-bus",
377 .id = 0,
378 .ctrlbit = S3C_CLKCON_SCLK_AUDIO0,
379 .enable = s3c64xx_sclk_ctrl,
380 },
Ben Dooks399cae72009-12-01 01:24:35 +0000381 .reg_src = { S3C_CLK_SRC, 7, 3 },
382 .reg_div = { S3C_CLK_DIV2, 8, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000383 .sources = &clkset_audio0,
Ben Dooks83604932009-11-30 01:31:32 +0000384 }, {
385 .clk = {
386 .name = "audio-bus",
387 .id = 1,
388 .ctrlbit = S3C_CLKCON_SCLK_AUDIO1,
389 .enable = s3c64xx_sclk_ctrl,
390 },
Ben Dooks399cae72009-12-01 01:24:35 +0000391 .reg_src = { S3C_CLK_SRC, 10, 3 },
392 .reg_div = { S3C_CLK_DIV2, 12, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000393 .sources = &clkset_audio1,
Ben Dooks83604932009-11-30 01:31:32 +0000394 }, {
395 .clk = {
396 .name = "irda-bus",
397 .id = 0,
398 .ctrlbit = S3C_CLKCON_SCLK_IRDA,
399 .enable = s3c64xx_sclk_ctrl,
400 },
Ben Dooks399cae72009-12-01 01:24:35 +0000401 .reg_src = { S3C_CLK_SRC, 24, 2 },
402 .reg_div = { S3C_CLK_DIV2, 20, 4 },
Ben Dooks83604932009-11-30 01:31:32 +0000403 .sources = &clkset_irda,
Ben Dooks83604932009-11-30 01:31:32 +0000404 }, {
405 .clk = {
406 .name = "camera",
407 .id = -1,
408 .ctrlbit = S3C_CLKCON_SCLK_CAM,
409 .enable = s3c64xx_sclk_ctrl,
410 },
Ben Dooks399cae72009-12-01 01:24:35 +0000411 .reg_div = { S3C_CLK_DIV0, 20, 4 },
412 .reg_src = { NULL, 0, 0 },
Ben Dooks83604932009-11-30 01:31:32 +0000413 .sources = &clkset_camif,
Werner Almesbergere2c977d2009-03-05 11:43:14 +0800414 },
Werner Almesbergere2c977d2009-03-05 11:43:14 +0800415};
416
Ben Dookscf18acf2008-10-21 14:07:02 +0100417/* Clock initialisation code */
418
419static struct clksrc_clk *init_parents[] = {
420 &clk_mout_apll,
421 &clk_mout_epll,
422 &clk_mout_mpll,
Ben Dookscf18acf2008-10-21 14:07:02 +0100423};
424
Ben Dookscf18acf2008-10-21 14:07:02 +0100425#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
426
427void __init_or_cpufreq s3c6400_setup_clocks(void)
428{
429 struct clk *xtal_clk;
430 unsigned long xtal;
431 unsigned long fclk;
432 unsigned long hclk;
433 unsigned long hclk2;
434 unsigned long pclk;
435 unsigned long epll;
436 unsigned long apll;
437 unsigned long mpll;
438 unsigned int ptr;
439 u32 clkdiv0;
440
Ben Dooks39669f52008-10-21 14:07:12 +0100441 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
Ben Dookscf18acf2008-10-21 14:07:02 +0100442
443 clkdiv0 = __raw_readl(S3C_CLK_DIV0);
Ben Dooks39669f52008-10-21 14:07:12 +0100444 printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
Ben Dookscf18acf2008-10-21 14:07:02 +0100445
446 xtal_clk = clk_get(NULL, "xtal");
447 BUG_ON(IS_ERR(xtal_clk));
448
449 xtal = clk_get_rate(xtal_clk);
450 clk_put(xtal_clk);
451
Ben Dooks39669f52008-10-21 14:07:12 +0100452 printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
Ben Dookscf18acf2008-10-21 14:07:02 +0100453
Mark Browne179ac02009-10-21 18:17:58 +0100454 /* For now assume the mux always selects the crystal */
455 clk_ext_xtal_mux.parent = xtal_clk;
456
Ben Dookscf18acf2008-10-21 14:07:02 +0100457 epll = s3c6400_get_epll(xtal);
458 mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
459 apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
460
461 fclk = mpll;
462
463 printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
464 apll, mpll, epll);
465
466 hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
467 hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
468 pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
469
470 printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
471 hclk2, hclk, pclk);
472
473 clk_fout_mpll.rate = mpll;
474 clk_fout_epll.rate = epll;
475 clk_fout_apll.rate = apll;
476
Werner Almesbergera03f7da2009-03-05 11:43:13 +0800477 clk_h2.rate = hclk2;
Ben Dookscf18acf2008-10-21 14:07:02 +0100478 clk_h.rate = hclk;
479 clk_p.rate = pclk;
480 clk_f.rate = fclk;
481
482 for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
Ben Dooks399cae72009-12-01 01:24:35 +0000483 s3c_set_clksrc(init_parents[ptr]);
Ben Dooks83604932009-11-30 01:31:32 +0000484
485 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
Ben Dooks399cae72009-12-01 01:24:35 +0000486 s3c_set_clksrc(&clksrcs[ptr]);
Ben Dookscf18acf2008-10-21 14:07:02 +0100487}
488
489static struct clk *clks[] __initdata = {
490 &clk_ext_xtal_mux,
491 &clk_iis_cd0,
492 &clk_iis_cd1,
493 &clk_pcm_cd,
494 &clk_mout_epll.clk,
Ben Dookscf18acf2008-10-21 14:07:02 +0100495 &clk_mout_mpll.clk,
496 &clk_dout_mpll,
Ben Dooks496a3f02009-05-02 13:48:53 +0100497 &clk_arm,
Ben Dookscf18acf2008-10-21 14:07:02 +0100498};
499
Ben Dooks496a3f02009-05-02 13:48:53 +0100500/**
501 * s3c6400_register_clocks - register clocks for s3c6400 and above
502 * @armclk_divlimit: Divisor mask for ARMCLK
503 *
504 * Register the clocks for the S3C6400 and above SoC range, such
505 * as ARMCLK and the clocks which have divider chains attached.
506 *
507 * This call does not setup the clocks, which is left to the
508 * s3c6400_setup_clocks() call which may be needed by the cpufreq
509 * or resume code to re-set the clocks if the bootloader has changed
510 * them.
511 */
512void __init s3c6400_register_clocks(unsigned armclk_divlimit)
Ben Dookscf18acf2008-10-21 14:07:02 +0100513{
514 struct clk *clkp;
515 int ret;
516 int ptr;
517
Ben Dooks496a3f02009-05-02 13:48:53 +0100518 armclk_mask = armclk_divlimit;
519
Ben Dookscf18acf2008-10-21 14:07:02 +0100520 for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
521 clkp = clks[ptr];
522 ret = s3c24xx_register_clock(clkp);
523 if (ret < 0) {
524 printk(KERN_ERR "Failed to register clock %s (%d)\n",
525 clkp->name, ret);
526 }
527 }
Ben Dooks83604932009-11-30 01:31:32 +0000528
Ben Dooks399cae72009-12-01 01:24:35 +0000529 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
Ben Dookscf18acf2008-10-21 14:07:02 +0100530}