1 /* linux/arch/arm/plat-s5pc1xx/s5pc100-clock.c
3 * Copyright 2009 Samsung Electronics, Co.
4 * Byungho Min <bhmin@samsung.com>
6 * S5PC100 based common clock support
8 * Based on plat-s3c64xx/s3c6400-clock.c
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/list.h>
19 #include <linux/errno.h>
20 #include <linux/err.h>
21 #include <linux/clk.h>
22 #include <linux/sysdev.h>
25 #include <mach/hardware.h>
28 #include <plat/cpu-freq.h>
30 #include <plat/regs-clock.h>
31 #include <plat/clock.h>
34 #include <plat/devs.h>
35 #include <plat/s5pc100.h>
37 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
38 * ext_xtal_mux for want of an actual name from the manual.
41 static struct clk clk_ext_xtal_mux
= {
46 #define clk_fin_apll clk_ext_xtal_mux
47 #define clk_fin_mpll clk_ext_xtal_mux
48 #define clk_fin_epll clk_ext_xtal_mux
49 #define clk_fin_hpll clk_ext_xtal_mux
51 #define clk_fout_mpll clk_mpll
52 #define clk_vclk_54m clk_54m
55 unsigned int nr_sources
;
64 struct clk_sources
*sources
;
66 unsigned int divider_shift
;
67 void __iomem
*reg_divider
;
68 void __iomem
*reg_source
;
72 static struct clk clk_fout_apll
= {
78 static struct clk
*clk_src_apll_list
[] = {
83 static struct clk_sources clk_src_apll
= {
84 .sources
= clk_src_apll_list
,
85 .nr_sources
= ARRAY_SIZE(clk_src_apll_list
),
88 static struct clksrc_clk clk_mout_apll
= {
93 .shift
= S5PC100_CLKSRC0_APLL_SHIFT
,
94 .mask
= S5PC100_CLKSRC0_APLL_MASK
,
95 .sources
= &clk_src_apll
,
96 .reg_source
= S5PC100_CLKSRC0
,
99 static unsigned long s5pc100_clk_dout_apll_get_rate(struct clk
*clk
)
101 unsigned long rate
= clk_get_rate(clk
->parent
);
104 ratio
= __raw_readl(S5PC100_CLKDIV0
) & S5PC100_CLKDIV0_APLL_MASK
;
105 ratio
>>= S5PC100_CLKDIV0_APLL_SHIFT
;
107 return rate
/ (ratio
+ 1);
110 static struct clk clk_dout_apll
= {
113 .parent
= &clk_mout_apll
.clk
,
114 .get_rate
= s5pc100_clk_dout_apll_get_rate
,
117 static unsigned long s5pc100_clk_arm_get_rate(struct clk
*clk
)
119 unsigned long rate
= clk_get_rate(clk
->parent
);
122 ratio
= __raw_readl(S5PC100_CLKDIV0
) & S5PC100_CLKDIV0_ARM_MASK
;
123 ratio
>>= S5PC100_CLKDIV0_ARM_SHIFT
;
125 return rate
/ (ratio
+ 1);
128 static unsigned long s5pc100_clk_arm_round_rate(struct clk
*clk
,
131 unsigned long parent
= clk_get_rate(clk
->parent
);
137 div
= (parent
/ rate
) - 1;
138 if (div
> S5PC100_CLKDIV0_ARM_MASK
)
139 div
= S5PC100_CLKDIV0_ARM_MASK
;
141 return parent
/ (div
+ 1);
144 static int s5pc100_clk_arm_set_rate(struct clk
*clk
, unsigned long rate
)
146 unsigned long parent
= clk_get_rate(clk
->parent
);
150 if (rate
< parent
/ (S5PC100_CLKDIV0_ARM_MASK
+ 1))
153 rate
= clk_round_rate(clk
, rate
);
154 div
= clk_get_rate(clk
->parent
) / rate
;
156 val
= __raw_readl(S5PC100_CLKDIV0
);
157 val
&= S5PC100_CLKDIV0_ARM_MASK
;
159 __raw_writel(val
, S5PC100_CLKDIV0
);
164 static struct clk clk_arm
= {
167 .parent
= &clk_dout_apll
,
168 .get_rate
= s5pc100_clk_arm_get_rate
,
169 .set_rate
= s5pc100_clk_arm_set_rate
,
170 .round_rate
= s5pc100_clk_arm_round_rate
,
173 static unsigned long s5pc100_clk_dout_d0_bus_get_rate(struct clk
*clk
)
175 unsigned long rate
= clk_get_rate(clk
->parent
);
178 ratio
= __raw_readl(S5PC100_CLKDIV0
) & S5PC100_CLKDIV0_D0_MASK
;
179 ratio
>>= S5PC100_CLKDIV0_D0_SHIFT
;
181 return rate
/ (ratio
+ 1);
184 static struct clk clk_dout_d0_bus
= {
185 .name
= "dout_d0_bus",
188 .get_rate
= s5pc100_clk_dout_d0_bus_get_rate
,
191 static unsigned long s5pc100_clk_dout_pclkd0_get_rate(struct clk
*clk
)
193 unsigned long rate
= clk_get_rate(clk
->parent
);
196 ratio
= __raw_readl(S5PC100_CLKDIV0
) & S5PC100_CLKDIV0_PCLKD0_MASK
;
197 ratio
>>= S5PC100_CLKDIV0_PCLKD0_SHIFT
;
199 return rate
/ (ratio
+ 1);
202 static struct clk clk_dout_pclkd0
= {
203 .name
= "dout_pclkd0",
205 .parent
= &clk_dout_d0_bus
,
206 .get_rate
= s5pc100_clk_dout_pclkd0_get_rate
,
209 static unsigned long s5pc100_clk_dout_apll2_get_rate(struct clk
*clk
)
211 unsigned long rate
= clk_get_rate(clk
->parent
);
214 ratio
= __raw_readl(S5PC100_CLKDIV1
) & S5PC100_CLKDIV1_APLL2_MASK
;
215 ratio
>>= S5PC100_CLKDIV1_APLL2_SHIFT
;
217 return rate
/ (ratio
+ 1);
220 static struct clk clk_dout_apll2
= {
221 .name
= "dout_apll2",
223 .parent
= &clk_mout_apll
.clk
,
224 .get_rate
= s5pc100_clk_dout_apll2_get_rate
,
228 static struct clk
*clk_src_mpll_list
[] = {
230 [1] = &clk_fout_mpll
,
233 static struct clk_sources clk_src_mpll
= {
234 .sources
= clk_src_mpll_list
,
235 .nr_sources
= ARRAY_SIZE(clk_src_mpll_list
),
238 static struct clksrc_clk clk_mout_mpll
= {
243 .shift
= S5PC100_CLKSRC0_MPLL_SHIFT
,
244 .mask
= S5PC100_CLKSRC0_MPLL_MASK
,
245 .sources
= &clk_src_mpll
,
246 .reg_source
= S5PC100_CLKSRC0
,
249 static struct clk
*clkset_am_list
[] = {
250 [0] = &clk_mout_mpll
.clk
,
251 [1] = &clk_dout_apll2
,
254 static struct clk_sources clk_src_am
= {
255 .sources
= clkset_am_list
,
256 .nr_sources
= ARRAY_SIZE(clkset_am_list
),
259 static struct clksrc_clk clk_mout_am
= {
264 .shift
= S5PC100_CLKSRC0_AMMUX_SHIFT
,
265 .mask
= S5PC100_CLKSRC0_AMMUX_MASK
,
266 .sources
= &clk_src_am
,
267 .reg_source
= S5PC100_CLKSRC0
,
270 static unsigned long s5pc100_clk_dout_d1_bus_get_rate(struct clk
*clk
)
272 unsigned long rate
= clk_get_rate(clk
->parent
);
275 printk(KERN_DEBUG
"%s: parent is %ld\n", __func__
, rate
);
277 ratio
= __raw_readl(S5PC100_CLKDIV1
) & S5PC100_CLKDIV1_D1_MASK
;
278 ratio
>>= S5PC100_CLKDIV1_D1_SHIFT
;
280 return rate
/ (ratio
+ 1);
283 static struct clk clk_dout_d1_bus
= {
284 .name
= "dout_d1_bus",
286 .parent
= &clk_mout_am
.clk
,
287 .get_rate
= s5pc100_clk_dout_d1_bus_get_rate
,
290 static struct clk
*clkset_onenand_list
[] = {
291 [0] = &clk_dout_d0_bus
,
292 [1] = &clk_dout_d1_bus
,
295 static struct clk_sources clk_src_onenand
= {
296 .sources
= clkset_onenand_list
,
297 .nr_sources
= ARRAY_SIZE(clkset_onenand_list
),
300 static struct clksrc_clk clk_mout_onenand
= {
302 .name
= "mout_onenand",
305 .shift
= S5PC100_CLKSRC0_ONENAND_SHIFT
,
306 .mask
= S5PC100_CLKSRC0_ONENAND_MASK
,
307 .sources
= &clk_src_onenand
,
308 .reg_source
= S5PC100_CLKSRC0
,
311 static unsigned long s5pc100_clk_dout_pclkd1_get_rate(struct clk
*clk
)
313 unsigned long rate
= clk_get_rate(clk
->parent
);
316 printk(KERN_DEBUG
"%s: parent is %ld\n", __func__
, rate
);
318 ratio
= __raw_readl(S5PC100_CLKDIV1
) & S5PC100_CLKDIV1_PCLKD1_MASK
;
319 ratio
>>= S5PC100_CLKDIV1_PCLKD1_SHIFT
;
321 return rate
/ (ratio
+ 1);
324 static struct clk clk_dout_pclkd1
= {
325 .name
= "dout_pclkd1",
327 .parent
= &clk_dout_d1_bus
,
328 .get_rate
= s5pc100_clk_dout_pclkd1_get_rate
,
331 static unsigned long s5pc100_clk_dout_mpll2_get_rate(struct clk
*clk
)
333 unsigned long rate
= clk_get_rate(clk
->parent
);
336 printk(KERN_DEBUG
"%s: parent is %ld\n", __func__
, rate
);
338 ratio
= __raw_readl(S5PC100_CLKDIV1
) & S5PC100_CLKDIV1_MPLL2_MASK
;
339 ratio
>>= S5PC100_CLKDIV1_MPLL2_SHIFT
;
341 return rate
/ (ratio
+ 1);
344 static struct clk clk_dout_mpll2
= {
345 .name
= "dout_mpll2",
347 .parent
= &clk_mout_am
.clk
,
348 .get_rate
= s5pc100_clk_dout_mpll2_get_rate
,
351 static unsigned long s5pc100_clk_dout_cam_get_rate(struct clk
*clk
)
353 unsigned long rate
= clk_get_rate(clk
->parent
);
356 printk(KERN_DEBUG
"%s: parent is %ld\n", __func__
, rate
);
358 ratio
= __raw_readl(S5PC100_CLKDIV1
) & S5PC100_CLKDIV1_CAM_MASK
;
359 ratio
>>= S5PC100_CLKDIV1_CAM_SHIFT
;
361 return rate
/ (ratio
+ 1);
364 static struct clk clk_dout_cam
= {
367 .parent
= &clk_dout_mpll2
,
368 .get_rate
= s5pc100_clk_dout_cam_get_rate
,
371 static unsigned long s5pc100_clk_dout_mpll_get_rate(struct clk
*clk
)
373 unsigned long rate
= clk_get_rate(clk
->parent
);
376 printk(KERN_DEBUG
"%s: parent is %ld\n", __func__
, rate
);
378 ratio
= __raw_readl(S5PC100_CLKDIV1
) & S5PC100_CLKDIV1_MPLL_MASK
;
379 ratio
>>= S5PC100_CLKDIV1_MPLL_SHIFT
;
381 return rate
/ (ratio
+ 1);
384 static struct clk clk_dout_mpll
= {
387 .parent
= &clk_mout_am
.clk
,
388 .get_rate
= s5pc100_clk_dout_mpll_get_rate
,
392 static struct clk clk_fout_epll
= {
397 static struct clk
*clk_src_epll_list
[] = {
399 [1] = &clk_fout_epll
,
402 static struct clk_sources clk_src_epll
= {
403 .sources
= clk_src_epll_list
,
404 .nr_sources
= ARRAY_SIZE(clk_src_epll_list
),
407 static struct clksrc_clk clk_mout_epll
= {
412 .shift
= S5PC100_CLKSRC0_EPLL_SHIFT
,
413 .mask
= S5PC100_CLKSRC0_EPLL_MASK
,
414 .sources
= &clk_src_epll
,
415 .reg_source
= S5PC100_CLKSRC0
,
419 static struct clk clk_fout_hpll
= {
424 static struct clk
*clk_src_hpll_list
[] = {
426 [1] = &clk_fout_hpll
,
429 static struct clk_sources clk_src_hpll
= {
430 .sources
= clk_src_hpll_list
,
431 .nr_sources
= ARRAY_SIZE(clk_src_hpll_list
),
434 static struct clksrc_clk clk_mout_hpll
= {
439 .shift
= S5PC100_CLKSRC0_HPLL_SHIFT
,
440 .mask
= S5PC100_CLKSRC0_HPLL_MASK
,
441 .sources
= &clk_src_hpll
,
442 .reg_source
= S5PC100_CLKSRC0
,
447 * The peripheral clocks are all controlled via clocksource followed
448 * by an optional divider and gate stage. We currently roll this into
449 * one clock which hides the intermediate clock from the mux.
451 * Note, the JPEG clock can only be an even divider...
453 * The scaler and LCD clocks depend on the S5PC100 version, and also
454 * have a common parent divisor so are not included here.
457 static inline struct clksrc_clk
*to_clksrc(struct clk
*clk
)
459 return container_of(clk
, struct clksrc_clk
, clk
);
462 static unsigned long s5pc100_getrate_clksrc(struct clk
*clk
)
464 struct clksrc_clk
*sclk
= to_clksrc(clk
);
465 unsigned long rate
= clk_get_rate(clk
->parent
);
466 u32 clkdiv
= __raw_readl(sclk
->reg_divider
);
468 clkdiv
>>= sclk
->divider_shift
;
476 static int s5pc100_setrate_clksrc(struct clk
*clk
, unsigned long rate
)
478 struct clksrc_clk
*sclk
= to_clksrc(clk
);
479 void __iomem
*reg
= sclk
->reg_divider
;
483 rate
= clk_round_rate(clk
, rate
);
484 div
= clk_get_rate(clk
->parent
) / rate
;
488 val
= __raw_readl(reg
);
489 val
&= ~(0xf << sclk
->divider_shift
);
490 val
|= (div
- 1) << sclk
->divider_shift
;
491 __raw_writel(val
, reg
);
496 static int s5pc100_setparent_clksrc(struct clk
*clk
, struct clk
*parent
)
498 struct clksrc_clk
*sclk
= to_clksrc(clk
);
499 struct clk_sources
*srcs
= sclk
->sources
;
500 u32 clksrc
= __raw_readl(sclk
->reg_source
);
504 for (ptr
= 0; ptr
< srcs
->nr_sources
; ptr
++)
505 if (srcs
->sources
[ptr
] == parent
) {
511 clksrc
&= ~sclk
->mask
;
512 clksrc
|= src_nr
<< sclk
->shift
;
514 __raw_writel(clksrc
, sclk
->reg_source
);
521 static unsigned long s5pc100_roundrate_clksrc(struct clk
*clk
,
524 unsigned long parent_rate
= clk_get_rate(clk
->parent
);
527 if (rate
> parent_rate
)
530 div
= rate
/ parent_rate
;
537 rate
= parent_rate
/ div
;
543 static struct clk
*clkset_spi_list
[] = {
550 static struct clk_sources clkset_spi
= {
551 .sources
= clkset_spi_list
,
552 .nr_sources
= ARRAY_SIZE(clkset_spi_list
),
555 static struct clksrc_clk clk_spi0
= {
559 .ctrlbit
= S5PC100_CLKGATE_SCLK0_SPI0
,
560 .enable
= s5pc100_sclk0_ctrl
,
561 .set_parent
= s5pc100_setparent_clksrc
,
562 .get_rate
= s5pc100_getrate_clksrc
,
563 .set_rate
= s5pc100_setrate_clksrc
,
564 .round_rate
= s5pc100_roundrate_clksrc
,
566 .shift
= S5PC100_CLKSRC1_SPI0_SHIFT
,
567 .mask
= S5PC100_CLKSRC1_SPI0_MASK
,
568 .sources
= &clkset_spi
,
569 .divider_shift
= S5PC100_CLKDIV2_SPI0_SHIFT
,
570 .reg_divider
= S5PC100_CLKDIV2
,
571 .reg_source
= S5PC100_CLKSRC1
,
574 static struct clksrc_clk clk_spi1
= {
578 .ctrlbit
= S5PC100_CLKGATE_SCLK0_SPI1
,
579 .enable
= s5pc100_sclk0_ctrl
,
580 .set_parent
= s5pc100_setparent_clksrc
,
581 .get_rate
= s5pc100_getrate_clksrc
,
582 .set_rate
= s5pc100_setrate_clksrc
,
583 .round_rate
= s5pc100_roundrate_clksrc
,
585 .shift
= S5PC100_CLKSRC1_SPI1_SHIFT
,
586 .mask
= S5PC100_CLKSRC1_SPI1_MASK
,
587 .sources
= &clkset_spi
,
588 .divider_shift
= S5PC100_CLKDIV2_SPI1_SHIFT
,
589 .reg_divider
= S5PC100_CLKDIV2
,
590 .reg_source
= S5PC100_CLKSRC1
,
593 static struct clksrc_clk clk_spi2
= {
597 .ctrlbit
= S5PC100_CLKGATE_SCLK0_SPI2
,
598 .enable
= s5pc100_sclk0_ctrl
,
599 .set_parent
= s5pc100_setparent_clksrc
,
600 .get_rate
= s5pc100_getrate_clksrc
,
601 .set_rate
= s5pc100_setrate_clksrc
,
602 .round_rate
= s5pc100_roundrate_clksrc
,
604 .shift
= S5PC100_CLKSRC1_SPI2_SHIFT
,
605 .mask
= S5PC100_CLKSRC1_SPI2_MASK
,
606 .sources
= &clkset_spi
,
607 .divider_shift
= S5PC100_CLKDIV2_SPI2_SHIFT
,
608 .reg_divider
= S5PC100_CLKDIV2
,
609 .reg_source
= S5PC100_CLKSRC1
,
612 static struct clk
*clkset_uart_list
[] = {
617 static struct clk_sources clkset_uart
= {
618 .sources
= clkset_uart_list
,
619 .nr_sources
= ARRAY_SIZE(clkset_uart_list
),
622 static struct clksrc_clk clk_uart_uclk1
= {
626 .ctrlbit
= S5PC100_CLKGATE_SCLK0_UART
,
627 .enable
= s5pc100_sclk0_ctrl
,
628 .set_parent
= s5pc100_setparent_clksrc
,
629 .get_rate
= s5pc100_getrate_clksrc
,
630 .set_rate
= s5pc100_setrate_clksrc
,
631 .round_rate
= s5pc100_roundrate_clksrc
,
633 .shift
= S5PC100_CLKSRC1_UART_SHIFT
,
634 .mask
= S5PC100_CLKSRC1_UART_MASK
,
635 .sources
= &clkset_uart
,
636 .divider_shift
= S5PC100_CLKDIV2_UART_SHIFT
,
637 .reg_divider
= S5PC100_CLKDIV2
,
638 .reg_source
= S5PC100_CLKSRC1
,
641 static struct clk clk_iis_cd0
= {
642 .name
= "iis_cdclk0",
646 static struct clk clk_iis_cd1
= {
647 .name
= "iis_cdclk1",
651 static struct clk clk_iis_cd2
= {
652 .name
= "iis_cdclk2",
656 static struct clk clk_pcm_cd0
= {
657 .name
= "pcm_cdclk0",
661 static struct clk clk_pcm_cd1
= {
662 .name
= "pcm_cdclk1",
666 static struct clk
*clkset_audio0_list
[] = {
675 static struct clk_sources clkset_audio0
= {
676 .sources
= clkset_audio0_list
,
677 .nr_sources
= ARRAY_SIZE(clkset_audio0_list
),
680 static struct clksrc_clk clk_audio0
= {
684 .ctrlbit
= S5PC100_CLKGATE_SCLK1_AUDIO0
,
685 .enable
= s5pc100_sclk1_ctrl
,
686 .set_parent
= s5pc100_setparent_clksrc
,
687 .get_rate
= s5pc100_getrate_clksrc
,
688 .set_rate
= s5pc100_setrate_clksrc
,
689 .round_rate
= s5pc100_roundrate_clksrc
,
691 .shift
= S5PC100_CLKSRC3_AUDIO0_SHIFT
,
692 .mask
= S5PC100_CLKSRC3_AUDIO0_MASK
,
693 .sources
= &clkset_audio0
,
694 .divider_shift
= S5PC100_CLKDIV4_AUDIO0_SHIFT
,
695 .reg_divider
= S5PC100_CLKDIV4
,
696 .reg_source
= S5PC100_CLKSRC3
,
699 static struct clk
*clkset_audio1_list
[] = {
708 static struct clk_sources clkset_audio1
= {
709 .sources
= clkset_audio1_list
,
710 .nr_sources
= ARRAY_SIZE(clkset_audio1_list
),
713 static struct clksrc_clk clk_audio1
= {
717 .ctrlbit
= S5PC100_CLKGATE_SCLK1_AUDIO1
,
718 .enable
= s5pc100_sclk1_ctrl
,
719 .set_parent
= s5pc100_setparent_clksrc
,
720 .get_rate
= s5pc100_getrate_clksrc
,
721 .set_rate
= s5pc100_setrate_clksrc
,
722 .round_rate
= s5pc100_roundrate_clksrc
,
724 .shift
= S5PC100_CLKSRC3_AUDIO1_SHIFT
,
725 .mask
= S5PC100_CLKSRC3_AUDIO1_MASK
,
726 .sources
= &clkset_audio1
,
727 .divider_shift
= S5PC100_CLKDIV4_AUDIO1_SHIFT
,
728 .reg_divider
= S5PC100_CLKDIV4
,
729 .reg_source
= S5PC100_CLKSRC3
,
732 static struct clk
*clkset_audio2_list
[] = {
740 static struct clk_sources clkset_audio2
= {
741 .sources
= clkset_audio2_list
,
742 .nr_sources
= ARRAY_SIZE(clkset_audio2_list
),
745 static struct clksrc_clk clk_audio2
= {
749 .ctrlbit
= S5PC100_CLKGATE_SCLK1_AUDIO2
,
750 .enable
= s5pc100_sclk1_ctrl
,
751 .set_parent
= s5pc100_setparent_clksrc
,
752 .get_rate
= s5pc100_getrate_clksrc
,
753 .set_rate
= s5pc100_setrate_clksrc
,
754 .round_rate
= s5pc100_roundrate_clksrc
,
756 .shift
= S5PC100_CLKSRC3_AUDIO2_SHIFT
,
757 .mask
= S5PC100_CLKSRC3_AUDIO2_MASK
,
758 .sources
= &clkset_audio2
,
759 .divider_shift
= S5PC100_CLKDIV4_AUDIO2_SHIFT
,
760 .reg_divider
= S5PC100_CLKDIV4
,
761 .reg_source
= S5PC100_CLKSRC3
,
764 static struct clk
*clkset_spdif_list
[] = {
770 static struct clk_sources clkset_spdif
= {
771 .sources
= clkset_spdif_list
,
772 .nr_sources
= ARRAY_SIZE(clkset_spdif_list
),
775 static struct clksrc_clk clk_spdif
= {
780 .shift
= S5PC100_CLKSRC3_SPDIF_SHIFT
,
781 .mask
= S5PC100_CLKSRC3_SPDIF_MASK
,
782 .sources
= &clkset_spdif
,
783 .reg_source
= S5PC100_CLKSRC3
,
786 static struct clk
*clkset_lcd_fimc_list
[] = {
793 static struct clk_sources clkset_lcd_fimc
= {
794 .sources
= clkset_lcd_fimc_list
,
795 .nr_sources
= ARRAY_SIZE(clkset_lcd_fimc_list
),
798 static struct clksrc_clk clk_lcd
= {
802 .ctrlbit
= S5PC100_CLKGATE_SCLK1_LCD
,
803 .enable
= s5pc100_sclk1_ctrl
,
804 .set_parent
= s5pc100_setparent_clksrc
,
805 .get_rate
= s5pc100_getrate_clksrc
,
806 .set_rate
= s5pc100_setrate_clksrc
,
807 .round_rate
= s5pc100_roundrate_clksrc
,
809 .shift
= S5PC100_CLKSRC2_LCD_SHIFT
,
810 .mask
= S5PC100_CLKSRC2_LCD_MASK
,
811 .sources
= &clkset_lcd_fimc
,
812 .divider_shift
= S5PC100_CLKDIV3_LCD_SHIFT
,
813 .reg_divider
= S5PC100_CLKDIV3
,
814 .reg_source
= S5PC100_CLKSRC2
,
817 static struct clksrc_clk clk_fimc0
= {
821 .ctrlbit
= S5PC100_CLKGATE_SCLK1_FIMC0
,
822 .enable
= s5pc100_sclk1_ctrl
,
823 .set_parent
= s5pc100_setparent_clksrc
,
824 .get_rate
= s5pc100_getrate_clksrc
,
825 .set_rate
= s5pc100_setrate_clksrc
,
826 .round_rate
= s5pc100_roundrate_clksrc
,
828 .shift
= S5PC100_CLKSRC2_FIMC0_SHIFT
,
829 .mask
= S5PC100_CLKSRC2_FIMC0_MASK
,
830 .sources
= &clkset_lcd_fimc
,
831 .divider_shift
= S5PC100_CLKDIV3_FIMC0_SHIFT
,
832 .reg_divider
= S5PC100_CLKDIV3
,
833 .reg_source
= S5PC100_CLKSRC2
,
836 static struct clksrc_clk clk_fimc1
= {
840 .ctrlbit
= S5PC100_CLKGATE_SCLK1_FIMC1
,
841 .enable
= s5pc100_sclk1_ctrl
,
842 .set_parent
= s5pc100_setparent_clksrc
,
843 .get_rate
= s5pc100_getrate_clksrc
,
844 .set_rate
= s5pc100_setrate_clksrc
,
845 .round_rate
= s5pc100_roundrate_clksrc
,
847 .shift
= S5PC100_CLKSRC2_FIMC1_SHIFT
,
848 .mask
= S5PC100_CLKSRC2_FIMC1_MASK
,
849 .sources
= &clkset_lcd_fimc
,
850 .divider_shift
= S5PC100_CLKDIV3_FIMC1_SHIFT
,
851 .reg_divider
= S5PC100_CLKDIV3
,
852 .reg_source
= S5PC100_CLKSRC2
,
855 static struct clksrc_clk clk_fimc2
= {
859 .ctrlbit
= S5PC100_CLKGATE_SCLK1_FIMC2
,
860 .enable
= s5pc100_sclk1_ctrl
,
861 .set_parent
= s5pc100_setparent_clksrc
,
862 .get_rate
= s5pc100_getrate_clksrc
,
863 .set_rate
= s5pc100_setrate_clksrc
,
864 .round_rate
= s5pc100_roundrate_clksrc
,
866 .shift
= S5PC100_CLKSRC2_FIMC2_SHIFT
,
867 .mask
= S5PC100_CLKSRC2_FIMC2_MASK
,
868 .sources
= &clkset_lcd_fimc
,
869 .divider_shift
= S5PC100_CLKDIV3_FIMC2_SHIFT
,
870 .reg_divider
= S5PC100_CLKDIV3
,
871 .reg_source
= S5PC100_CLKSRC2
,
874 static struct clk
*clkset_mmc_list
[] = {
881 static struct clk_sources clkset_mmc
= {
882 .sources
= clkset_mmc_list
,
883 .nr_sources
= ARRAY_SIZE(clkset_mmc_list
),
886 static struct clksrc_clk clk_mmc0
= {
890 .ctrlbit
= S5PC100_CLKGATE_SCLK0_MMC0
,
891 .enable
= s5pc100_sclk0_ctrl
,
892 .set_parent
= s5pc100_setparent_clksrc
,
893 .get_rate
= s5pc100_getrate_clksrc
,
894 .set_rate
= s5pc100_setrate_clksrc
,
895 .round_rate
= s5pc100_roundrate_clksrc
,
897 .shift
= S5PC100_CLKSRC2_MMC0_SHIFT
,
898 .mask
= S5PC100_CLKSRC2_MMC0_MASK
,
899 .sources
= &clkset_mmc
,
900 .divider_shift
= S5PC100_CLKDIV3_MMC0_SHIFT
,
901 .reg_divider
= S5PC100_CLKDIV3
,
902 .reg_source
= S5PC100_CLKSRC2
,
905 static struct clksrc_clk clk_mmc1
= {
909 .ctrlbit
= S5PC100_CLKGATE_SCLK0_MMC1
,
910 .enable
= s5pc100_sclk0_ctrl
,
911 .set_parent
= s5pc100_setparent_clksrc
,
912 .get_rate
= s5pc100_getrate_clksrc
,
913 .set_rate
= s5pc100_setrate_clksrc
,
914 .round_rate
= s5pc100_roundrate_clksrc
,
916 .shift
= S5PC100_CLKSRC2_MMC1_SHIFT
,
917 .mask
= S5PC100_CLKSRC2_MMC1_MASK
,
918 .sources
= &clkset_mmc
,
919 .divider_shift
= S5PC100_CLKDIV3_MMC1_SHIFT
,
920 .reg_divider
= S5PC100_CLKDIV3
,
921 .reg_source
= S5PC100_CLKSRC2
,
924 static struct clksrc_clk clk_mmc2
= {
928 .ctrlbit
= S5PC100_CLKGATE_SCLK0_MMC2
,
929 .enable
= s5pc100_sclk0_ctrl
,
930 .set_parent
= s5pc100_setparent_clksrc
,
931 .get_rate
= s5pc100_getrate_clksrc
,
932 .set_rate
= s5pc100_setrate_clksrc
,
933 .round_rate
= s5pc100_roundrate_clksrc
,
935 .shift
= S5PC100_CLKSRC2_MMC2_SHIFT
,
936 .mask
= S5PC100_CLKSRC2_MMC2_MASK
,
937 .sources
= &clkset_mmc
,
938 .divider_shift
= S5PC100_CLKDIV3_MMC2_SHIFT
,
939 .reg_divider
= S5PC100_CLKDIV3
,
940 .reg_source
= S5PC100_CLKSRC2
,
944 static struct clk
*clkset_usbhost_list
[] = {
951 static struct clk_sources clkset_usbhost
= {
952 .sources
= clkset_usbhost_list
,
953 .nr_sources
= ARRAY_SIZE(clkset_usbhost_list
),
956 static struct clksrc_clk clk_usbhost
= {
960 .ctrlbit
= S5PC100_CLKGATE_SCLK0_USBHOST
,
961 .enable
= s5pc100_sclk0_ctrl
,
962 .set_parent
= s5pc100_setparent_clksrc
,
963 .get_rate
= s5pc100_getrate_clksrc
,
964 .set_rate
= s5pc100_setrate_clksrc
,
965 .round_rate
= s5pc100_roundrate_clksrc
,
967 .shift
= S5PC100_CLKSRC1_UHOST_SHIFT
,
968 .mask
= S5PC100_CLKSRC1_UHOST_MASK
,
969 .sources
= &clkset_usbhost
,
970 .divider_shift
= S5PC100_CLKDIV2_UHOST_SHIFT
,
971 .reg_divider
= S5PC100_CLKDIV2
,
972 .reg_source
= S5PC100_CLKSRC1
,
975 /* Clock initialisation code */
977 static struct clksrc_clk
*init_parents
[] = {
1002 static void __init_or_cpufreq
s5pc100_set_clksrc(struct clksrc_clk
*clk
)
1004 struct clk_sources
*srcs
= clk
->sources
;
1005 u32 clksrc
= __raw_readl(clk
->reg_source
);
1007 clksrc
&= clk
->mask
;
1008 clksrc
>>= clk
->shift
;
1010 if (clksrc
> srcs
->nr_sources
|| !srcs
->sources
[clksrc
]) {
1011 printk(KERN_ERR
"%s: bad source %d\n",
1012 clk
->clk
.name
, clksrc
);
1016 clk
->clk
.parent
= srcs
->sources
[clksrc
];
1018 printk(KERN_INFO
"%s: source is %s (%d), rate is %ld.%03ld MHz\n",
1019 clk
->clk
.name
, clk
->clk
.parent
->name
, clksrc
,
1020 print_mhz(clk_get_rate(&clk
->clk
)));
1023 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
1025 void __init_or_cpufreq
s5pc100_setup_clocks(void)
1027 struct clk
*xtal_clk
;
1029 unsigned long armclk
;
1030 unsigned long hclkd0
;
1032 unsigned long pclkd0
;
1034 unsigned long apll
, mpll
, epll
, hpll
;
1036 u32 clkdiv0
, clkdiv1
;
1038 printk(KERN_DEBUG
"%s: registering clocks\n", __func__
);
1040 clkdiv0
= __raw_readl(S5PC100_CLKDIV0
);
1041 clkdiv1
= __raw_readl(S5PC100_CLKDIV1
);
1043 printk(KERN_DEBUG
"%s: clkdiv0 = %08x, clkdiv1 = %08x\n", __func__
, clkdiv0
, clkdiv1
);
1045 xtal_clk
= clk_get(NULL
, "xtal");
1046 BUG_ON(IS_ERR(xtal_clk
));
1048 xtal
= clk_get_rate(xtal_clk
);
1051 printk(KERN_DEBUG
"%s: xtal is %ld\n", __func__
, xtal
);
1053 apll
= s5pc1xx_get_pll(xtal
, __raw_readl(S5PC100_APLL_CON
));
1054 mpll
= s5pc1xx_get_pll(xtal
, __raw_readl(S5PC100_MPLL_CON
));
1055 epll
= s5pc1xx_get_pll(xtal
, __raw_readl(S5PC100_EPLL_CON
));
1056 hpll
= s5pc1xx_get_pll(xtal
, __raw_readl(S5PC100_HPLL_CON
));
1058 printk(KERN_INFO
"S5PC100: Apll=%ld.%03ld Mhz, Mpll=%ld.%03ld Mhz"
1059 ", Epll=%ld.%03ld Mhz, Hpll=%ld.%03ld Mhz\n",
1060 print_mhz(apll
), print_mhz(mpll
),
1061 print_mhz(epll
), print_mhz(hpll
));
1063 armclk
= apll
/ GET_DIV(clkdiv0
, S5PC100_CLKDIV0_APLL
);
1064 armclk
= armclk
/ GET_DIV(clkdiv0
, S5PC100_CLKDIV0_ARM
);
1065 hclkd0
= armclk
/ GET_DIV(clkdiv0
, S5PC100_CLKDIV0_D0
);
1066 pclkd0
= hclkd0
/ GET_DIV(clkdiv0
, S5PC100_CLKDIV0_PCLKD0
);
1067 hclk
= mpll
/ GET_DIV(clkdiv1
, S5PC100_CLKDIV1_D1
);
1068 pclk
= hclk
/ GET_DIV(clkdiv1
, S5PC100_CLKDIV1_PCLKD1
);
1070 printk(KERN_INFO
"S5PC100: ARMCLK=%ld.%03ld MHz, HCLKD0=%ld.%03ld MHz,"
1071 " PCLKD0=%ld.%03ld MHz\n, HCLK=%ld.%03ld MHz,"
1072 " PCLK=%ld.%03ld MHz\n",
1073 print_mhz(armclk
), print_mhz(hclkd0
),
1074 print_mhz(pclkd0
), print_mhz(hclk
), print_mhz(pclk
));
1076 clk_fout_apll
.rate
= apll
;
1077 clk_fout_mpll
.rate
= mpll
;
1078 clk_fout_epll
.rate
= epll
;
1079 clk_fout_hpll
.rate
= hpll
;
1083 clk_f
.rate
= armclk
;
1085 for (ptr
= 0; ptr
< ARRAY_SIZE(init_parents
); ptr
++)
1086 s5pc100_set_clksrc(init_parents
[ptr
]);
1089 static struct clk
*clks
[] __initdata
= {
1099 &clk_mout_onenand
.clk
,
1114 &clk_uart_uclk1
.clk
,
1130 void __init
s5pc100_register_clocks(void)
1136 for (ptr
= 0; ptr
< ARRAY_SIZE(clks
); ptr
++) {
1138 ret
= s3c24xx_register_clock(clkp
);
1140 printk(KERN_ERR
"Failed to register clock %s (%d)\n",