aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2410/clock.c
diff options
context:
space:
mode:
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}