1 /* linux/arch/arm/mach-s3c2443/clock.c
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
6 * S3C2443 Clock control support
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/list.h>
27 #include <linux/errno.h>
28 #include <linux/err.h>
29 #include <linux/sysdev.h>
30 #include <linux/clk.h>
31 #include <linux/mutex.h>
32 #include <linux/delay.h>
33 #include <linux/serial_core.h>
36 #include <asm/mach/map.h>
38 #include <mach/hardware.h>
40 #include <mach/regs-s3c2443-clock.h>
42 #include <plat/cpu-freq.h>
44 #include <plat/s3c2443.h>
45 #include <plat/clock.h>
48 /* We currently have to assume that the system is running
49 * from the XTPll input, and that all ***REFCLKs are being
50 * fed from it, as we cannot read the state of OM[4] from
53 * It would be possible for each board initialisation to
54 * set the correct muxing at initialisation
57 static int s3c2443_clkcon_enable_h(struct clk
*clk
, int enable
)
59 unsigned int clocks
= clk
->ctrlbit
;
62 clkcon
= __raw_readl(S3C2443_HCLKCON
);
69 __raw_writel(clkcon
, S3C2443_HCLKCON
);
74 static int s3c2443_clkcon_enable_p(struct clk
*clk
, int enable
)
76 unsigned int clocks
= clk
->ctrlbit
;
79 clkcon
= __raw_readl(S3C2443_PCLKCON
);
86 __raw_writel(clkcon
, S3C2443_PCLKCON
);
91 static int s3c2443_clkcon_enable_s(struct clk
*clk
, int enable
)
93 unsigned int clocks
= clk
->ctrlbit
;
96 clkcon
= __raw_readl(S3C2443_SCLKCON
);
103 __raw_writel(clkcon
, S3C2443_SCLKCON
);
108 static unsigned long s3c2443_roundrate_clksrc(struct clk
*clk
,
112 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
115 if (rate
> parent_rate
)
118 /* note, we remove the +/- 1 calculations as they cancel out */
120 div
= (rate
/ parent_rate
);
127 return parent_rate
/ div
;
130 static unsigned long s3c2443_roundrate_clksrc4(struct clk
*clk
,
133 return s3c2443_roundrate_clksrc(clk
, rate
, 4);
136 static unsigned long s3c2443_roundrate_clksrc16(struct clk
*clk
,
139 return s3c2443_roundrate_clksrc(clk
, rate
, 16);
142 static unsigned long s3c2443_roundrate_clksrc256(struct clk
*clk
,
145 return s3c2443_roundrate_clksrc(clk
, rate
, 256);
148 /* clock selections */
150 /* CPU EXTCLK input */
151 static struct clk clk_ext
= {
156 static struct clk clk_mpllref
= {
163 static struct clk clk_mpll
= {
165 .parent
= &clk_mpllref
,
170 static struct clk clk_epllref
;
172 static struct clk clk_epll
= {
174 .parent
= &clk_epllref
,
178 static struct clk clk_i2s_ext
= {
183 static int s3c2443_setparent_epllref(struct clk
*clk
, struct clk
*parent
)
185 unsigned long clksrc
= __raw_readl(S3C2443_CLKSRC
);
187 clksrc
&= ~S3C2443_CLKSRC_EPLLREF_MASK
;
189 if (parent
== &clk_xtal
)
190 clksrc
|= S3C2443_CLKSRC_EPLLREF_XTAL
;
191 else if (parent
== &clk_ext
)
192 clksrc
|= S3C2443_CLKSRC_EPLLREF_EXTCLK
;
193 else if (parent
!= &clk_mpllref
)
196 __raw_writel(clksrc
, S3C2443_CLKSRC
);
197 clk
->parent
= parent
;
202 static struct clk clk_epllref
= {
205 .set_parent
= s3c2443_setparent_epllref
,
208 static unsigned long s3c2443_getrate_mdivclk(struct clk
*clk
)
210 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
211 unsigned long div
= __raw_readl(S3C2443_CLKDIV0
);
213 div
&= S3C2443_CLKDIV0_EXTDIV_MASK
;
214 div
>>= (S3C2443_CLKDIV0_EXTDIV_SHIFT
-1); /* x2 */
216 return parent_rate
/ (div
+ 1);
219 static struct clk clk_mdivclk
= {
221 .parent
= &clk_mpllref
,
223 .get_rate
= s3c2443_getrate_mdivclk
,
226 static int s3c2443_setparent_msysclk(struct clk
*clk
, struct clk
*parent
)
228 unsigned long clksrc
= __raw_readl(S3C2443_CLKSRC
);
230 clksrc
&= ~(S3C2443_CLKSRC_MSYSCLK_MPLL
|
231 S3C2443_CLKSRC_EXTCLK_DIV
);
233 if (parent
== &clk_mpll
)
234 clksrc
|= S3C2443_CLKSRC_MSYSCLK_MPLL
;
235 else if (parent
== &clk_mdivclk
)
236 clksrc
|= S3C2443_CLKSRC_EXTCLK_DIV
;
237 else if (parent
!= &clk_mpllref
)
240 __raw_writel(clksrc
, S3C2443_CLKSRC
);
241 clk
->parent
= parent
;
246 static struct clk clk_msysclk
= {
250 .set_parent
= s3c2443_setparent_msysclk
,
255 * this clock is sourced from msysclk and can have a number of
256 * divider values applied to it to then be fed into armclk.
259 static struct clk clk_armdiv
= {
262 .parent
= &clk_msysclk
,
267 * this is the clock fed into the ARM core itself, either from
268 * armdiv or from hclk.
271 static int s3c2443_setparent_armclk(struct clk
*clk
, struct clk
*parent
)
273 unsigned long clkdiv0
;
275 clkdiv0
= __raw_readl(S3C2443_CLKDIV0
);
277 if (parent
== &clk_armdiv
)
278 clkdiv0
&= ~S3C2443_CLKDIV0_DVS
;
279 else if (parent
== &clk_h
)
280 clkdiv0
|= S3C2443_CLKDIV0_DVS
;
284 __raw_writel(clkdiv0
, S3C2443_CLKDIV0
);
288 static struct clk clk_arm
= {
291 .set_parent
= s3c2443_setparent_armclk
,
296 * this is sourced from either the EPLL or the EPLLref clock
299 static int s3c2443_setparent_esysclk(struct clk
*clk
, struct clk
*parent
)
301 unsigned long clksrc
= __raw_readl(S3C2443_CLKSRC
);
303 if (parent
== &clk_epll
)
304 clksrc
|= S3C2443_CLKSRC_ESYSCLK_EPLL
;
305 else if (parent
== &clk_epllref
)
306 clksrc
&= ~S3C2443_CLKSRC_ESYSCLK_EPLL
;
310 __raw_writel(clksrc
, S3C2443_CLKSRC
);
311 clk
->parent
= parent
;
316 static struct clk clk_esysclk
= {
320 .set_parent
= s3c2443_setparent_esysclk
,
325 * UART baud-rate clock sourced from esysclk via a divisor
328 static unsigned long s3c2443_getrate_uart(struct clk
*clk
)
330 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
331 unsigned long div
= __raw_readl(S3C2443_CLKDIV1
);
333 div
&= S3C2443_CLKDIV1_UARTDIV_MASK
;
334 div
>>= S3C2443_CLKDIV1_UARTDIV_SHIFT
;
336 return parent_rate
/ (div
+ 1);
340 static int s3c2443_setrate_uart(struct clk
*clk
, unsigned long rate
)
342 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
343 unsigned long clkdivn
= __raw_readl(S3C2443_CLKDIV1
);
345 rate
= s3c2443_roundrate_clksrc16(clk
, rate
);
346 rate
= parent_rate
/ rate
;
348 clkdivn
&= ~S3C2443_CLKDIV1_UARTDIV_MASK
;
349 clkdivn
|= (rate
- 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT
;
351 __raw_writel(clkdivn
, S3C2443_CLKDIV1
);
355 static struct clk clk_uart
= {
358 .parent
= &clk_esysclk
,
359 .get_rate
= s3c2443_getrate_uart
,
360 .set_rate
= s3c2443_setrate_uart
,
361 .round_rate
= s3c2443_roundrate_clksrc16
,
366 * high-speed spi clock, sourced from esysclk
369 static unsigned long s3c2443_getrate_hsspi(struct clk
*clk
)
371 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
372 unsigned long div
= __raw_readl(S3C2443_CLKDIV1
);
374 div
&= S3C2443_CLKDIV1_HSSPIDIV_MASK
;
375 div
>>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT
;
377 return parent_rate
/ (div
+ 1);
381 static int s3c2443_setrate_hsspi(struct clk
*clk
, unsigned long rate
)
383 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
384 unsigned long clkdivn
= __raw_readl(S3C2443_CLKDIV1
);
386 rate
= s3c2443_roundrate_clksrc4(clk
, rate
);
387 rate
= parent_rate
/ rate
;
389 clkdivn
&= ~S3C2443_CLKDIV1_HSSPIDIV_MASK
;
390 clkdivn
|= (rate
- 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT
;
392 __raw_writel(clkdivn
, S3C2443_CLKDIV1
);
396 static struct clk clk_hsspi
= {
399 .parent
= &clk_esysclk
,
400 .ctrlbit
= S3C2443_SCLKCON_HSSPICLK
,
401 .enable
= s3c2443_clkcon_enable_s
,
402 .get_rate
= s3c2443_getrate_hsspi
,
403 .set_rate
= s3c2443_setrate_hsspi
,
404 .round_rate
= s3c2443_roundrate_clksrc4
,
409 * usb host bus-clock, usually 48MHz to provide USB bus clock timing
412 static unsigned long s3c2443_getrate_usbhost(struct clk
*clk
)
414 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
415 unsigned long div
= __raw_readl(S3C2443_CLKDIV1
);
417 div
&= S3C2443_CLKDIV1_USBHOSTDIV_MASK
;
418 div
>>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT
;
420 return parent_rate
/ (div
+ 1);
423 static int s3c2443_setrate_usbhost(struct clk
*clk
, unsigned long rate
)
425 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
426 unsigned long clkdivn
= __raw_readl(S3C2443_CLKDIV1
);
428 rate
= s3c2443_roundrate_clksrc4(clk
, rate
);
429 rate
= parent_rate
/ rate
;
431 clkdivn
&= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK
;
432 clkdivn
|= (rate
- 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT
;
434 __raw_writel(clkdivn
, S3C2443_CLKDIV1
);
438 static struct clk clk_usb_bus_host
= {
439 .name
= "usb-bus-host-parent",
441 .parent
= &clk_esysclk
,
442 .ctrlbit
= S3C2443_SCLKCON_USBHOST
,
443 .enable
= s3c2443_clkcon_enable_s
,
444 .get_rate
= s3c2443_getrate_usbhost
,
445 .set_rate
= s3c2443_setrate_usbhost
,
446 .round_rate
= s3c2443_roundrate_clksrc4
,
451 * this clock is sourced from epll, and is fed through a divider,
452 * to a mux controlled by sclkcon where either it or a extclk can
453 * be fed to the hsmmc block
456 static unsigned long s3c2443_getrate_hsmmc_div(struct clk
*clk
)
458 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
459 unsigned long div
= __raw_readl(S3C2443_CLKDIV1
);
461 div
&= S3C2443_CLKDIV1_HSMMCDIV_MASK
;
462 div
>>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT
;
464 return parent_rate
/ (div
+ 1);
467 static int s3c2443_setrate_hsmmc_div(struct clk
*clk
, unsigned long rate
)
469 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
470 unsigned long clkdivn
= __raw_readl(S3C2443_CLKDIV1
);
472 rate
= s3c2443_roundrate_clksrc4(clk
, rate
);
473 rate
= parent_rate
/ rate
;
475 clkdivn
&= ~S3C2443_CLKDIV1_HSMMCDIV_MASK
;
476 clkdivn
|= (rate
- 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT
;
478 __raw_writel(clkdivn
, S3C2443_CLKDIV1
);
482 static struct clk clk_hsmmc_div
= {
485 .parent
= &clk_esysclk
,
486 .get_rate
= s3c2443_getrate_hsmmc_div
,
487 .set_rate
= s3c2443_setrate_hsmmc_div
,
488 .round_rate
= s3c2443_roundrate_clksrc4
,
491 static int s3c2443_setparent_hsmmc(struct clk
*clk
, struct clk
*parent
)
493 unsigned long clksrc
= __raw_readl(S3C2443_SCLKCON
);
495 clksrc
&= ~(S3C2443_SCLKCON_HSMMCCLK_EXT
|
496 S3C2443_SCLKCON_HSMMCCLK_EPLL
);
498 if (parent
== &clk_epll
)
499 clksrc
|= S3C2443_SCLKCON_HSMMCCLK_EPLL
;
500 else if (parent
== &clk_ext
)
501 clksrc
|= S3C2443_SCLKCON_HSMMCCLK_EXT
;
505 if (clk
->usage
> 0) {
506 __raw_writel(clksrc
, S3C2443_SCLKCON
);
509 clk
->parent
= parent
;
513 static int s3c2443_enable_hsmmc(struct clk
*clk
, int enable
)
515 return s3c2443_setparent_hsmmc(clk
, clk
->parent
);
518 static struct clk clk_hsmmc
= {
521 .parent
= &clk_hsmmc_div
,
522 .enable
= s3c2443_enable_hsmmc
,
523 .set_parent
= s3c2443_setparent_hsmmc
,
528 * this clock is the output from the i2s divisor of esysclk
531 static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk
*clk
)
533 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
534 unsigned long div
= __raw_readl(S3C2443_CLKDIV1
);
536 div
&= S3C2443_CLKDIV1_I2SDIV_MASK
;
537 div
>>= S3C2443_CLKDIV1_I2SDIV_SHIFT
;
539 return parent_rate
/ (div
+ 1);
542 static int s3c2443_setrate_i2s_eplldiv(struct clk
*clk
, unsigned long rate
)
544 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
545 unsigned long clkdivn
= __raw_readl(S3C2443_CLKDIV1
);
547 rate
= s3c2443_roundrate_clksrc16(clk
, rate
);
548 rate
= parent_rate
/ rate
;
550 clkdivn
&= ~S3C2443_CLKDIV1_I2SDIV_MASK
;
551 clkdivn
|= (rate
- 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT
;
553 __raw_writel(clkdivn
, S3C2443_CLKDIV1
);
557 static struct clk clk_i2s_eplldiv
= {
558 .name
= "i2s-eplldiv",
560 .parent
= &clk_esysclk
,
561 .get_rate
= s3c2443_getrate_i2s_eplldiv
,
562 .set_rate
= s3c2443_setrate_i2s_eplldiv
,
563 .round_rate
= s3c2443_roundrate_clksrc16
,
568 * i2s bus reference clock, selectable from external, esysclk or epllref
571 static int s3c2443_setparent_i2s(struct clk
*clk
, struct clk
*parent
)
573 unsigned long clksrc
= __raw_readl(S3C2443_CLKSRC
);
575 clksrc
&= ~S3C2443_CLKSRC_I2S_MASK
;
577 if (parent
== &clk_epllref
)
578 clksrc
|= S3C2443_CLKSRC_I2S_EPLLREF
;
579 else if (parent
== &clk_i2s_ext
)
580 clksrc
|= S3C2443_CLKSRC_I2S_EXT
;
581 else if (parent
!= &clk_i2s_eplldiv
)
584 clk
->parent
= parent
;
585 __raw_writel(clksrc
, S3C2443_CLKSRC
);
590 static struct clk clk_i2s
= {
593 .parent
= &clk_i2s_eplldiv
,
594 .ctrlbit
= S3C2443_SCLKCON_I2SCLK
,
595 .enable
= s3c2443_clkcon_enable_s
,
596 .set_parent
= s3c2443_setparent_i2s
,
601 * camera interface bus-clock, divided down from esysclk
604 static unsigned long s3c2443_getrate_cam(struct clk
*clk
)
606 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
607 unsigned long div
= __raw_readl(S3C2443_CLKDIV1
);
609 div
&= S3C2443_CLKDIV1_CAMDIV_MASK
;
610 div
>>= S3C2443_CLKDIV1_CAMDIV_SHIFT
;
612 return parent_rate
/ (div
+ 1);
615 static int s3c2443_setrate_cam(struct clk
*clk
, unsigned long rate
)
617 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
618 unsigned long clkdiv1
= __raw_readl(S3C2443_CLKDIV1
);
620 rate
= s3c2443_roundrate_clksrc16(clk
, rate
);
621 rate
= parent_rate
/ rate
;
623 clkdiv1
&= ~S3C2443_CLKDIV1_CAMDIV_MASK
;
624 clkdiv1
|= (rate
- 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT
;
626 __raw_writel(clkdiv1
, S3C2443_CLKDIV1
);
630 static struct clk clk_cam
= {
631 .name
= "camif-upll", /* same as 2440 name */
633 .parent
= &clk_esysclk
,
634 .ctrlbit
= S3C2443_SCLKCON_CAMCLK
,
635 .enable
= s3c2443_clkcon_enable_s
,
636 .get_rate
= s3c2443_getrate_cam
,
637 .set_rate
= s3c2443_setrate_cam
,
638 .round_rate
= s3c2443_roundrate_clksrc16
,
643 * display interface clock, divided from esysclk
646 static unsigned long s3c2443_getrate_display(struct clk
*clk
)
648 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
649 unsigned long div
= __raw_readl(S3C2443_CLKDIV1
);
651 div
&= S3C2443_CLKDIV1_DISPDIV_MASK
;
652 div
>>= S3C2443_CLKDIV1_DISPDIV_SHIFT
;
654 return parent_rate
/ (div
+ 1);
657 static int s3c2443_setrate_display(struct clk
*clk
, unsigned long rate
)
659 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
660 unsigned long clkdivn
= __raw_readl(S3C2443_CLKDIV1
);
662 rate
= s3c2443_roundrate_clksrc256(clk
, rate
);
663 rate
= parent_rate
/ rate
;
665 clkdivn
&= ~S3C2443_CLKDIV1_UARTDIV_MASK
;
666 clkdivn
|= (rate
- 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT
;
668 __raw_writel(clkdivn
, S3C2443_CLKDIV1
);
672 static struct clk clk_display
= {
673 .name
= "display-if",
675 .parent
= &clk_esysclk
,
676 .ctrlbit
= S3C2443_SCLKCON_DISPCLK
,
677 .enable
= s3c2443_clkcon_enable_s
,
678 .get_rate
= s3c2443_getrate_display
,
679 .set_rate
= s3c2443_setrate_display
,
680 .round_rate
= s3c2443_roundrate_clksrc256
,
685 * this divides the msysclk down to pass to h/p/etc.
688 static unsigned long s3c2443_prediv_getrate(struct clk
*clk
)
690 unsigned long rate
= clk_get_rate(clk
->parent
);
691 unsigned long clkdiv0
= __raw_readl(S3C2443_CLKDIV0
);
693 clkdiv0
&= S3C2443_CLKDIV0_PREDIV_MASK
;
694 clkdiv0
>>= S3C2443_CLKDIV0_PREDIV_SHIFT
;
696 return rate
/ (clkdiv0
+ 1);
699 static struct clk clk_prediv
= {
702 .parent
= &clk_msysclk
,
703 .get_rate
= s3c2443_prediv_getrate
,
706 /* standard clock definitions */
708 static struct clk init_clocks_disable
[] = {
717 .enable
= s3c2443_clkcon_enable_p
,
718 .ctrlbit
= S3C2443_PCLKCON_SDI
,
723 .enable
= s3c2443_clkcon_enable_p
,
724 .ctrlbit
= S3C2443_PCLKCON_ADC
,
729 .enable
= s3c2443_clkcon_enable_p
,
730 .ctrlbit
= S3C2443_PCLKCON_IIC
,
735 .enable
= s3c2443_clkcon_enable_p
,
736 .ctrlbit
= S3C2443_PCLKCON_IIS
,
741 .enable
= s3c2443_clkcon_enable_p
,
742 .ctrlbit
= S3C2443_PCLKCON_SPI0
,
747 .enable
= s3c2443_clkcon_enable_p
,
748 .ctrlbit
= S3C2443_PCLKCON_SPI1
,
752 static struct clk init_clocks
[] = {
757 .enable
= s3c2443_clkcon_enable_h
,
758 .ctrlbit
= S3C2443_HCLKCON_DMA0
,
763 .enable
= s3c2443_clkcon_enable_h
,
764 .ctrlbit
= S3C2443_HCLKCON_DMA1
,
769 .enable
= s3c2443_clkcon_enable_h
,
770 .ctrlbit
= S3C2443_HCLKCON_DMA2
,
775 .enable
= s3c2443_clkcon_enable_h
,
776 .ctrlbit
= S3C2443_HCLKCON_DMA3
,
781 .enable
= s3c2443_clkcon_enable_h
,
782 .ctrlbit
= S3C2443_HCLKCON_DMA4
,
787 .enable
= s3c2443_clkcon_enable_h
,
788 .ctrlbit
= S3C2443_HCLKCON_DMA5
,
793 .enable
= s3c2443_clkcon_enable_h
,
794 .ctrlbit
= S3C2443_HCLKCON_LCDC
,
799 .enable
= s3c2443_clkcon_enable_p
,
800 .ctrlbit
= S3C2443_PCLKCON_GPIO
,
805 .enable
= s3c2443_clkcon_enable_h
,
806 .ctrlbit
= S3C2443_HCLKCON_USBH
,
808 .name
= "usb-device",
811 .enable
= s3c2443_clkcon_enable_h
,
812 .ctrlbit
= S3C2443_HCLKCON_USBD
,
817 .enable
= s3c2443_clkcon_enable_h
,
818 .ctrlbit
= S3C2443_HCLKCON_HSMMC
,
823 .enable
= s3c2443_clkcon_enable_h
,
824 .ctrlbit
= S3C2443_HCLKCON_CFC
,
829 .enable
= s3c2443_clkcon_enable_h
,
830 .ctrlbit
= S3C2443_HCLKCON_SSMC
,
835 .enable
= s3c2443_clkcon_enable_p
,
836 .ctrlbit
= S3C2443_PCLKCON_PWMT
,
841 .enable
= s3c2443_clkcon_enable_p
,
842 .ctrlbit
= S3C2443_PCLKCON_UART0
,
847 .enable
= s3c2443_clkcon_enable_p
,
848 .ctrlbit
= S3C2443_PCLKCON_UART1
,
853 .enable
= s3c2443_clkcon_enable_p
,
854 .ctrlbit
= S3C2443_PCLKCON_UART2
,
859 .enable
= s3c2443_clkcon_enable_p
,
860 .ctrlbit
= S3C2443_PCLKCON_UART3
,
865 .enable
= s3c2443_clkcon_enable_p
,
866 .ctrlbit
= S3C2443_PCLKCON_RTC
,
871 .ctrlbit
= S3C2443_PCLKCON_WDT
,
873 .name
= "usb-bus-host",
875 .parent
= &clk_usb_bus_host
,
880 .ctrlbit
= S3C2443_PCLKCON_AC97
,
884 /* clocks to add where we need to check their parentage */
886 /* s3c2443_clk_initparents
888 * Initialise the parents for the clocks that we get at start-time
891 static int __init
clk_init_set_parent(struct clk
*clk
, struct clk
*parent
)
893 printk(KERN_DEBUG
"clock %s: parent %s\n", clk
->name
, parent
->name
);
894 return clk_set_parent(clk
, parent
);
897 static void __init
s3c2443_clk_initparents(void)
899 unsigned long clksrc
= __raw_readl(S3C2443_CLKSRC
);
902 switch (clksrc
& S3C2443_CLKSRC_EPLLREF_MASK
) {
903 case S3C2443_CLKSRC_EPLLREF_EXTCLK
:
907 case S3C2443_CLKSRC_EPLLREF_XTAL
:
912 case S3C2443_CLKSRC_EPLLREF_MPLLREF
:
913 case S3C2443_CLKSRC_EPLLREF_MPLLREF2
:
914 parent
= &clk_mpllref
;
918 clk_init_set_parent(&clk_epllref
, parent
);
920 switch (clksrc
& S3C2443_CLKSRC_I2S_MASK
) {
921 case S3C2443_CLKSRC_I2S_EXT
:
922 parent
= &clk_i2s_ext
;
925 case S3C2443_CLKSRC_I2S_EPLLDIV
:
927 parent
= &clk_i2s_eplldiv
;
930 case S3C2443_CLKSRC_I2S_EPLLREF
:
931 case S3C2443_CLKSRC_I2S_EPLLREF3
:
932 parent
= &clk_epllref
;
935 clk_init_set_parent(&clk_i2s
, &clk_epllref
);
939 parent
= (clksrc
& S3C2443_CLKSRC_ESYSCLK_EPLL
) ?
940 &clk_epll
: &clk_epllref
;
942 clk_init_set_parent(&clk_esysclk
, parent
);
946 if (clksrc
& S3C2443_CLKSRC_MSYSCLK_MPLL
) {
949 parent
= (clksrc
& S3C2443_CLKSRC_EXTCLK_DIV
) ?
950 &clk_mdivclk
: &clk_mpllref
;
953 clk_init_set_parent(&clk_msysclk
, parent
);
957 if (__raw_readl(S3C2443_CLKDIV0
) & S3C2443_CLKDIV0_DVS
)
960 parent
= &clk_armdiv
;
962 clk_init_set_parent(&clk_arm
, parent
);
965 /* armdiv divisor table */
967 static unsigned int armdiv
[16] = {
968 [S3C2443_CLKDIV0_ARMDIV_1
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 1,
969 [S3C2443_CLKDIV0_ARMDIV_2
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 2,
970 [S3C2443_CLKDIV0_ARMDIV_3
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 3,
971 [S3C2443_CLKDIV0_ARMDIV_4
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 4,
972 [S3C2443_CLKDIV0_ARMDIV_6
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 6,
973 [S3C2443_CLKDIV0_ARMDIV_8
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 8,
974 [S3C2443_CLKDIV0_ARMDIV_12
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 12,
975 [S3C2443_CLKDIV0_ARMDIV_16
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
] = 16,
978 static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0
)
980 clkcon0
&= S3C2443_CLKDIV0_ARMDIV_MASK
;
982 return armdiv
[clkcon0
>> S3C2443_CLKDIV0_ARMDIV_SHIFT
];
985 static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0
)
987 clkcon0
&= S3C2443_CLKDIV0_HCLKDIV_MASK
;
992 /* clocks to add straight away */
994 static struct clk
*clks
[] __initdata
= {
1016 void __init_or_cpufreq
s3c2443_setup_clocks(void)
1018 unsigned long mpllcon
= __raw_readl(S3C2443_MPLLCON
);
1019 unsigned long clkdiv0
= __raw_readl(S3C2443_CLKDIV0
);
1020 struct clk
*xtal_clk
;
1027 xtal_clk
= clk_get(NULL
, "xtal");
1028 xtal
= clk_get_rate(xtal_clk
);
1031 pll
= s3c2443_get_mpll(mpllcon
, xtal
);
1032 clk_msysclk
.rate
= pll
;
1034 fclk
= pll
/ s3c2443_fclk_div(clkdiv0
);
1035 hclk
= s3c2443_prediv_getrate(&clk_prediv
);
1036 hclk
/= s3c2443_get_hdiv(clkdiv0
);
1037 pclk
= hclk
/ ((clkdiv0
& S3C2443_CLKDIV0_HALF_PCLK
) ? 2 : 1);
1039 s3c24xx_setup_clocks(fclk
, hclk
, pclk
);
1041 printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
1042 (mpllcon
& S3C2443_PLLCON_OFF
) ? "off":"on",
1043 print_mhz(pll
), print_mhz(fclk
),
1044 print_mhz(hclk
), print_mhz(pclk
));
1046 s3c24xx_setup_clocks(fclk
, hclk
, pclk
);
1049 void __init
s3c2443_init_clocks(int xtal
)
1052 unsigned long epllcon
= __raw_readl(S3C2443_EPLLCON
);
1056 /* s3c2443 parents h and p clocks from prediv */
1057 clk_h
.parent
= &clk_prediv
;
1058 clk_p
.parent
= &clk_prediv
;
1060 s3c24xx_register_baseclocks(xtal
);
1061 s3c2443_setup_clocks();
1062 s3c2443_clk_initparents();
1064 for (ptr
= 0; ptr
< ARRAY_SIZE(clks
); ptr
++) {
1067 ret
= s3c24xx_register_clock(clkp
);
1069 printk(KERN_ERR
"Failed to register clock %s (%d)\n",
1074 clk_epll
.rate
= s3c2443_get_epll(epllcon
, xtal
);
1075 clk_usb_bus
.parent
= &clk_usb_bus_host
;
1077 /* ensure usb bus clock is within correct rate of 48MHz */
1079 if (clk_get_rate(&clk_usb_bus_host
) != (48 * 1000 * 1000)) {
1080 printk(KERN_INFO
"Warning: USB host bus not at 48MHz\n");
1081 clk_set_rate(&clk_usb_bus_host
, 48*1000*1000);
1084 printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
1085 (epllcon
& S3C2443_PLLCON_OFF
) ? "off":"on",
1086 print_mhz(clk_get_rate(&clk_epll
)),
1087 print_mhz(clk_get_rate(&clk_usb_bus
)));
1089 /* register clocks from clock array */
1092 for (ptr
= 0; ptr
< ARRAY_SIZE(init_clocks
); ptr
++, clkp
++) {
1093 ret
= s3c24xx_register_clock(clkp
);
1095 printk(KERN_ERR
"Failed to register clock %s (%d)\n",
1100 /* We must be careful disabling the clocks we are not intending to
1101 * be using at boot time, as subsystems such as the LCD which do
1102 * their own DMA requests to the bus can cause the system to lockup
1103 * if they where in the middle of requesting bus access.
1105 * Disabling the LCD clock if the LCD is active is very dangerous,
1106 * and therefore the bootloader should be careful to not enable
1107 * the LCD clock if it is not needed.
1110 /* install (and disable) the clocks we do not need immediately */
1112 clkp
= init_clocks_disable
;
1113 for (ptr
= 0; ptr
< ARRAY_SIZE(init_clocks_disable
); ptr
++, clkp
++) {
1115 ret
= s3c24xx_register_clock(clkp
);
1117 printk(KERN_ERR
"Failed to register clock %s (%d)\n",
1121 (clkp
->enable
)(clkp
, 0);