aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2410/clock.c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2006-06-22 17:18:20 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-22 17:18:20 -0400
commit99c13853ffa26dd6527995b3f47548e075f201fb (patch)
treeb007bb3e79739f7f442daa00f92a34b1348cd29b /arch/arm/mach-s3c2410/clock.c
parenta341305e94982c66a2e94125a24b860605da9066 (diff)
[ARM] 3627/1: S3C24XX: split s3c2410 clocks from core clocks
Patch from Ben Dooks Split the s3c2410 specific clocks from the core clock code, as part of the work to support more of the Samsung line of SoCs. The patch does not use the sysdev mechanism as the clocks are needed for the timer init, which is very early in the kernel init sequence. 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/clock.c')
-rw-r--r--arch/arm/mach-s3c2410/clock.c221
1 files changed, 7 insertions, 214 deletions
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index 99d174612b53..f553e5ee7477 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -3,7 +3,7 @@
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * S3C2410 Clock control support 6 * S3C24XX Core clock control support
7 * 7 *
8 * Based on, and code from linux/arch/arm/mach-versatile/clock.c 8 * Based on, and code from linux/arch/arm/mach-versatile/clock.c
9 ** 9 **
@@ -56,25 +56,6 @@ static LIST_HEAD(clocks);
56 56
57DEFINE_MUTEX(clocks_mutex); 57DEFINE_MUTEX(clocks_mutex);
58 58
59/* old functions */
60
61void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
62{
63 unsigned long clkcon;
64
65 clkcon = __raw_readl(S3C2410_CLKCON);
66
67 if (enable)
68 clkcon |= clocks;
69 else
70 clkcon &= ~clocks;
71
72 /* ensure none of the special function bits set */
73 clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER | 3);
74
75 __raw_writel(clkcon, S3C2410_CLKCON);
76}
77
78/* enable and disable calls for use with the clk struct */ 59/* enable and disable calls for use with the clk struct */
79 60
80static int clk_null_enable(struct clk *clk, int enable) 61static int clk_null_enable(struct clk *clk, int enable)
@@ -82,12 +63,6 @@ static int clk_null_enable(struct clk *clk, int enable)
82 return 0; 63 return 0;
83} 64}
84 65
85int s3c24xx_clkcon_enable(struct clk *clk, int enable)
86{
87 s3c24xx_clk_enable(clk->ctrlbit, enable);
88 return 0;
89}
90
91/* Clock API calls */ 66/* Clock API calls */
92 67
93struct clk *clk_get(struct device *dev, const char *id) 68struct clk *clk_get(struct device *dev, const char *id)
@@ -233,28 +208,6 @@ EXPORT_SYMBOL(clk_set_rate);
233EXPORT_SYMBOL(clk_get_parent); 208EXPORT_SYMBOL(clk_get_parent);
234EXPORT_SYMBOL(clk_set_parent); 209EXPORT_SYMBOL(clk_set_parent);
235 210
236/* base clock enable */
237
238static int s3c24xx_upll_enable(struct clk *clk, int enable)
239{
240 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
241 unsigned long orig = clkslow;
242
243 if (enable)
244 clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
245 else
246 clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
247
248 __raw_writel(clkslow, S3C2410_CLKSLOW);
249
250 /* if we started the UPLL, then allow to settle */
251
252 if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
253 udelay(200);
254
255 return 0;
256}
257
258/* base clocks */ 211/* base clocks */
259 212
260static struct clk clk_xtal = { 213static struct clk clk_xtal = {
@@ -265,15 +218,14 @@ static struct clk clk_xtal = {
265 .ctrlbit = 0, 218 .ctrlbit = 0,
266}; 219};
267 220
268static struct clk clk_upll = { 221struct clk clk_upll = {
269 .name = "upll", 222 .name = "upll",
270 .id = -1, 223 .id = -1,
271 .parent = NULL, 224 .parent = NULL,
272 .enable = s3c24xx_upll_enable,
273 .ctrlbit = 0, 225 .ctrlbit = 0,
274}; 226};
275 227
276static struct clk clk_f = { 228struct clk clk_f = {
277 .name = "fclk", 229 .name = "fclk",
278 .id = -1, 230 .id = -1,
279 .rate = 0, 231 .rate = 0,
@@ -281,7 +233,7 @@ static struct clk clk_f = {
281 .ctrlbit = 0, 233 .ctrlbit = 0,
282}; 234};
283 235
284static struct clk clk_h = { 236struct clk clk_h = {
285 .name = "hclk", 237 .name = "hclk",
286 .id = -1, 238 .id = -1,
287 .rate = 0, 239 .rate = 0,
@@ -289,7 +241,7 @@ static struct clk clk_h = {
289 .ctrlbit = 0, 241 .ctrlbit = 0,
290}; 242};
291 243
292static struct clk clk_p = { 244struct clk clk_p = {
293 .name = "pclk", 245 .name = "pclk",
294 .id = -1, 246 .id = -1,
295 .rate = 0, 247 .rate = 0,
@@ -426,108 +378,6 @@ struct clk s3c24xx_uclk = {
426 .id = -1, 378 .id = -1,
427}; 379};
428 380
429
430/* standard clock definitions */
431
432static struct clk init_clocks[] = {
433 {
434 .name = "nand",
435 .id = -1,
436 .parent = &clk_h,
437 .enable = s3c24xx_clkcon_enable,
438 .ctrlbit = S3C2410_CLKCON_NAND,
439 }, {
440 .name = "lcd",
441 .id = -1,
442 .parent = &clk_h,
443 .enable = s3c24xx_clkcon_enable,
444 .ctrlbit = S3C2410_CLKCON_LCDC,
445 }, {
446 .name = "usb-host",
447 .id = -1,
448 .parent = &clk_h,
449 .enable = s3c24xx_clkcon_enable,
450 .ctrlbit = S3C2410_CLKCON_USBH,
451 }, {
452 .name = "usb-device",
453 .id = -1,
454 .parent = &clk_h,
455 .enable = s3c24xx_clkcon_enable,
456 .ctrlbit = S3C2410_CLKCON_USBD,
457 }, {
458 .name = "timers",
459 .id = -1,
460 .parent = &clk_p,
461 .enable = s3c24xx_clkcon_enable,
462 .ctrlbit = S3C2410_CLKCON_PWMT,
463 }, {
464 .name = "sdi",
465 .id = -1,
466 .parent = &clk_p,
467 .enable = s3c24xx_clkcon_enable,
468 .ctrlbit = S3C2410_CLKCON_SDI,
469 }, {
470 .name = "uart",
471 .id = 0,
472 .parent = &clk_p,
473 .enable = s3c24xx_clkcon_enable,
474 .ctrlbit = S3C2410_CLKCON_UART0,
475 }, {
476 .name = "uart",
477 .id = 1,
478 .parent = &clk_p,
479 .enable = s3c24xx_clkcon_enable,
480 .ctrlbit = S3C2410_CLKCON_UART1,
481 }, {
482 .name = "uart",
483 .id = 2,
484 .parent = &clk_p,
485 .enable = s3c24xx_clkcon_enable,
486 .ctrlbit = S3C2410_CLKCON_UART2,
487 }, {
488 .name = "gpio",
489 .id = -1,
490 .parent = &clk_p,
491 .enable = s3c24xx_clkcon_enable,
492 .ctrlbit = S3C2410_CLKCON_GPIO,
493 }, {
494 .name = "rtc",
495 .id = -1,
496 .parent = &clk_p,
497 .enable = s3c24xx_clkcon_enable,
498 .ctrlbit = S3C2410_CLKCON_RTC,
499 }, {
500 .name = "adc",
501 .id = -1,
502 .parent = &clk_p,
503 .enable = s3c24xx_clkcon_enable,
504 .ctrlbit = S3C2410_CLKCON_ADC,
505 }, {
506 .name = "i2c",
507 .id = -1,
508 .parent = &clk_p,
509 .enable = s3c24xx_clkcon_enable,
510 .ctrlbit = S3C2410_CLKCON_IIC,
511 }, {
512 .name = "iis",
513 .id = -1,
514 .parent = &clk_p,
515 .enable = s3c24xx_clkcon_enable,
516 .ctrlbit = S3C2410_CLKCON_IIS,
517 }, {
518 .name = "spi",
519 .id = -1,
520 .parent = &clk_p,
521 .enable = s3c24xx_clkcon_enable,
522 .ctrlbit = S3C2410_CLKCON_SPI,
523 }, {
524 .name = "watchdog",
525 .id = -1,
526 .parent = &clk_p,
527 .ctrlbit = 0,
528 }
529};
530
531/* initialise the clock system */ 381/* initialise the clock system */
532 382
533int s3c24xx_register_clock(struct clk *clk) 383int s3c24xx_register_clock(struct clk *clk)
@@ -537,14 +387,6 @@ int s3c24xx_register_clock(struct clk *clk)
537 if (clk->enable == NULL) 387 if (clk->enable == NULL)
538 clk->enable = clk_null_enable; 388 clk->enable = clk_null_enable;
539 389
540 /* if this is a standard clock, set the usage state */
541
542 if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) {
543 unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
544
545 clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0;
546 }
547
548 /* add to the list of available clocks */ 390 /* add to the list of available clocks */
549 391
550 mutex_lock(&clocks_mutex); 392 mutex_lock(&clocks_mutex);
@@ -561,44 +403,17 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
561 unsigned long hclk, 403 unsigned long hclk,
562 unsigned long pclk) 404 unsigned long pclk)
563{ 405{
564 unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); 406 printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
565 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
566 struct clk *clkp = init_clocks;
567 int ptr;
568 int ret;
569
570 printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n");
571 407
572 /* initialise the main system clocks */ 408 /* initialise the main system clocks */
573 409
574 clk_xtal.rate = xtal; 410 clk_xtal.rate = xtal;
575 clk_upll.rate = s3c2410_get_pll(upllcon, xtal); 411 clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
576 412
577 clk_h.rate = hclk; 413 clk_h.rate = hclk;
578 clk_p.rate = pclk; 414 clk_p.rate = pclk;
579 clk_f.rate = fclk; 415 clk_f.rate = fclk;
580 416
581 /* We must be careful disabling the clocks we are not intending to
582 * be using at boot time, as subsytems such as the LCD which do
583 * their own DMA requests to the bus can cause the system to lockup
584 * if they where in the middle of requesting bus access.
585 *
586 * Disabling the LCD clock if the LCD is active is very dangerous,
587 * and therefore the bootloader should be careful to not enable
588 * the LCD clock if it is not needed.
589 */
590
591 mutex_lock(&clocks_mutex);
592
593 s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0);
594 s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0);
595 s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0);
596 s3c24xx_clk_enable(S3C2410_CLKCON_ADC, 0);
597 s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0);
598 s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0);
599
600 mutex_unlock(&clocks_mutex);
601
602 /* assume uart clocks are correctly setup */ 417 /* assume uart clocks are correctly setup */
603 418
604 /* register our clocks */ 419 /* register our clocks */
@@ -618,27 +433,5 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
618 if (s3c24xx_register_clock(&clk_p) < 0) 433 if (s3c24xx_register_clock(&clk_p) < 0)
619 printk(KERN_ERR "failed to register cpu pclk\n"); 434 printk(KERN_ERR "failed to register cpu pclk\n");
620 435
621
622 if (s3c24xx_register_clock(&clk_usb_bus) < 0)
623 printk(KERN_ERR "failed to register usb bus clock\n");
624
625 /* register clocks from clock array */
626
627 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
628 ret = s3c24xx_register_clock(clkp);
629 if (ret < 0) {
630 printk(KERN_ERR "Failed to register clock %s (%d)\n",
631 clkp->name, ret);
632 }
633 }
634
635 /* show the clock-slow value */
636
637 printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
638 print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
639 (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
640 (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
641 (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
642
643 return 0; 436 return 0;
644} 437}