diff options
author | Ben Dooks <ben-linux@fluff.org> | 2006-03-20 12:10:07 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-03-21 17:06:05 -0500 |
commit | 3fc3e1c0640887f883c28330e9d35145d23b2696 (patch) | |
tree | 94a98fb93f5f742d0d984a84934bf9cb90315119 /arch/arm/mach-s3c2410 | |
parent | a08ceff2a98e09cb14afefdd9276714b85c945f7 (diff) |
[ARM] 3333/1: S3C2XX - add dclk and clkout clock support
Patch from Ben Dooks
Add enable and set_parent calls for the dclk
and clkout clocks.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-s3c2410')
-rw-r--r-- | arch/arm/mach-s3c2410/clock.c | 94 |
1 files changed, 93 insertions, 1 deletions
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 773b7aec3e99..e205a6316b08 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/io.h> | 45 | #include <asm/io.h> |
46 | 46 | ||
47 | #include <asm/arch/regs-clock.h> | 47 | #include <asm/arch/regs-clock.h> |
48 | #include <asm/arch/regs-gpio.h> | ||
48 | 49 | ||
49 | #include "clock.h" | 50 | #include "clock.h" |
50 | #include "cpu.h" | 51 | #include "cpu.h" |
@@ -285,24 +286,115 @@ static struct clk clk_p = { | |||
285 | 286 | ||
286 | /* clocks that could be registered by external code */ | 287 | /* clocks that could be registered by external code */ |
287 | 288 | ||
289 | static int s3c24xx_dclk_enable(struct clk *clk, int enable) | ||
290 | { | ||
291 | unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON); | ||
292 | |||
293 | if (enable) | ||
294 | dclkcon |= clk->ctrlbit; | ||
295 | else | ||
296 | dclkcon &= ~clk->ctrlbit; | ||
297 | |||
298 | __raw_writel(dclkcon, S3C2410_DCLKCON); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) | ||
304 | { | ||
305 | unsigned long dclkcon; | ||
306 | unsigned int uclk; | ||
307 | |||
308 | if (parent == &clk_upll) | ||
309 | uclk = 1; | ||
310 | else if (parent == &clk_p) | ||
311 | uclk = 0; | ||
312 | else | ||
313 | return -EINVAL; | ||
314 | |||
315 | clk->parent = parent; | ||
316 | |||
317 | dclkcon = __raw_readl(S3C2410_DCLKCON); | ||
318 | |||
319 | if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { | ||
320 | if (uclk) | ||
321 | dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; | ||
322 | else | ||
323 | dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; | ||
324 | } else { | ||
325 | if (uclk) | ||
326 | dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; | ||
327 | else | ||
328 | dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; | ||
329 | } | ||
330 | |||
331 | __raw_writel(dclkcon, S3C2410_DCLKCON); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | |||
337 | static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) | ||
338 | { | ||
339 | unsigned long mask; | ||
340 | unsigned long source; | ||
341 | |||
342 | /* calculate the MISCCR setting for the clock */ | ||
343 | |||
344 | if (parent == &clk_xtal) | ||
345 | source = S3C2410_MISCCR_CLK0_MPLL; | ||
346 | else if (parent == &clk_upll) | ||
347 | source = S3C2410_MISCCR_CLK0_UPLL; | ||
348 | else if (parent == &clk_f) | ||
349 | source = S3C2410_MISCCR_CLK0_FCLK; | ||
350 | else if (parent == &clk_p) | ||
351 | source = S3C2410_MISCCR_CLK0_PCLK; | ||
352 | else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) | ||
353 | source = S3C2410_MISCCR_CLK0_DCLK0; | ||
354 | else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) | ||
355 | source = S3C2410_MISCCR_CLK0_DCLK0; | ||
356 | else | ||
357 | return -EINVAL; | ||
358 | |||
359 | if (clk == &s3c24xx_dclk0) | ||
360 | mask = S3C2410_MISCCR_CLK0_MASK; | ||
361 | else { | ||
362 | source <<= 4; | ||
363 | mask = S3C2410_MISCCR_CLK1_MASK; | ||
364 | } | ||
365 | |||
366 | s3c2410_modify_misccr(mask, source); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /* external clock definitions */ | ||
371 | |||
288 | struct clk s3c24xx_dclk0 = { | 372 | struct clk s3c24xx_dclk0 = { |
289 | .name = "dclk0", | 373 | .name = "dclk0", |
290 | .id = -1, | 374 | .id = -1, |
375 | .ctrlbit = S3C2410_DCLKCON_DCLK0EN, | ||
376 | .enable = s3c24xx_dclk_enable, | ||
377 | .set_parent = s3c24xx_dclk_setparent, | ||
291 | }; | 378 | }; |
292 | 379 | ||
293 | struct clk s3c24xx_dclk1 = { | 380 | struct clk s3c24xx_dclk1 = { |
294 | .name = "dclk1", | 381 | .name = "dclk1", |
295 | .id = -1, | 382 | .id = -1, |
383 | .ctrlbit = S3C2410_DCLKCON_DCLK0EN, | ||
384 | .enable = s3c24xx_dclk_enable, | ||
385 | .set_parent = s3c24xx_dclk_setparent, | ||
296 | }; | 386 | }; |
297 | 387 | ||
298 | struct clk s3c24xx_clkout0 = { | 388 | struct clk s3c24xx_clkout0 = { |
299 | .name = "clkout0", | 389 | .name = "clkout0", |
300 | .id = -1, | 390 | .id = -1, |
391 | .set_parent = s3c24xx_clkout_setparent, | ||
301 | }; | 392 | }; |
302 | 393 | ||
303 | struct clk s3c24xx_clkout1 = { | 394 | struct clk s3c24xx_clkout1 = { |
304 | .name = "clkout1", | 395 | .name = "clkout1", |
305 | .id = -1, | 396 | .id = -1, |
397 | .set_parent = s3c24xx_clkout_setparent, | ||
306 | }; | 398 | }; |
307 | 399 | ||
308 | struct clk s3c24xx_uclk = { | 400 | struct clk s3c24xx_uclk = { |
@@ -423,7 +515,7 @@ int s3c24xx_register_clock(struct clk *clk) | |||
423 | 515 | ||
424 | /* if this is a standard clock, set the usage state */ | 516 | /* if this is a standard clock, set the usage state */ |
425 | 517 | ||
426 | if (clk->ctrlbit) { | 518 | if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) { |
427 | unsigned long clkcon = __raw_readl(S3C2410_CLKCON); | 519 | unsigned long clkcon = __raw_readl(S3C2410_CLKCON); |
428 | 520 | ||
429 | clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; | 521 | clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; |