diff options
Diffstat (limited to 'arch/arm/plat-s3c24xx')
-rw-r--r-- | arch/arm/plat-s3c24xx/clock.c | 56 |
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 | ||
335 | static 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 | |||
351 | static 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 | |||
362 | static 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 | ||
336 | static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) | 388 | static 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 | ||
383 | struct clk s3c24xx_dclk1 = { | 437 | struct 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 | ||
391 | struct clk s3c24xx_clkout0 = { | 447 | struct clk s3c24xx_clkout0 = { |