aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavide Rizzo <davide@elpa.it>2008-04-12 10:08:15 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-04-19 09:04:30 -0400
commiteb1f7d10d6b6728c87f79f30d1ae844d01d3486a (patch)
tree4a3dbdceea736fee36a869f554acd1e16039b6f5
parent79b34afa68de4088081bcb7b4aed0fc4d8bf3618 (diff)
[ARM] 4967/1: Adds functions to set clkout rate for Samsung S3C2410
This patch adds functions to set clkout rate for Samsung S3C2410 This patch supersedes 4884/1, that contained an error Comments from Ben Dooks: Note, looks like this needs to be applied before 4882/1 Signed-off-by: Davide Rizzo <davide@elpa.it> Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/plat-s3c24xx/clock.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
index 99a44746f8f2..d84167fb33b1 100644
--- a/arch/arm/plat-s3c24xx/clock.c
+++ b/arch/arm/plat-s3c24xx/clock.c
@@ -332,6 +332,58 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
332 return 0; 332 return 0;
333} 333}
334 334
335static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate)
336{
337 unsigned long div;
338
339 if ((rate == 0) || !clk->parent)
340 return 0;
341
342 div = clk_get_rate(clk->parent) / rate;
343 if (div < 2)
344 div = 2;
345 else if (div > 16)
346 div = 16;
347
348 return div;
349}
350
351static unsigned long s3c24xx_round_dclk_rate(struct clk *clk,
352 unsigned long rate)
353{
354 unsigned long div = s3c24xx_calc_div(clk, rate);
355
356 if (div == 0)
357 return 0;
358
359 return clk_get_rate(clk->parent) / div;
360}
361
362static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate)
363{
364 unsigned long mask, data, div = s3c24xx_calc_div(clk, rate);
365
366 if (div == 0)
367 return -EINVAL;
368
369 if (clk == &s3c24xx_dclk0) {
370 mask = S3C2410_DCLKCON_DCLK0_DIV_MASK |
371 S3C2410_DCLKCON_DCLK0_CMP_MASK;
372 data = S3C2410_DCLKCON_DCLK0_DIV(div) |
373 S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2);
374 } else if (clk == &s3c24xx_dclk1) {
375 mask = S3C2410_DCLKCON_DCLK1_DIV_MASK |
376 S3C2410_DCLKCON_DCLK1_CMP_MASK;
377 data = S3C2410_DCLKCON_DCLK1_DIV(div) |
378 S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2);
379 } else
380 return -EINVAL;
381
382 clk->rate = clk_get_rate(clk->parent) / div;
383 __raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data),
384 S3C24XX_DCLKCON);
385 return clk->rate;
386}
335 387
336static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) 388static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
337{ 389{
@@ -378,6 +430,8 @@ struct clk s3c24xx_dclk0 = {
378 .ctrlbit = S3C2410_DCLKCON_DCLK0EN, 430 .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
379 .enable = s3c24xx_dclk_enable, 431 .enable = s3c24xx_dclk_enable,
380 .set_parent = s3c24xx_dclk_setparent, 432 .set_parent = s3c24xx_dclk_setparent,
433 .set_rate = s3c24xx_set_dclk_rate,
434 .round_rate = s3c24xx_round_dclk_rate,
381}; 435};
382 436
383struct clk s3c24xx_dclk1 = { 437struct clk s3c24xx_dclk1 = {
@@ -386,6 +440,8 @@ struct clk s3c24xx_dclk1 = {
386 .ctrlbit = S3C2410_DCLKCON_DCLK0EN, 440 .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
387 .enable = s3c24xx_dclk_enable, 441 .enable = s3c24xx_dclk_enable,
388 .set_parent = s3c24xx_dclk_setparent, 442 .set_parent = s3c24xx_dclk_setparent,
443 .set_rate = s3c24xx_set_dclk_rate,
444 .round_rate = s3c24xx_round_dclk_rate,
389}; 445};
390 446
391struct clk s3c24xx_clkout0 = { 447struct clk s3c24xx_clkout0 = {