1 /* linux/arch/arm/mach-s5pv210/clock.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * S5PV210 - Clock 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 version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/list.h>
17 #include <linux/errno.h>
18 #include <linux/err.h>
19 #include <linux/clk.h>
20 #include <linux/device.h>
25 #include <plat/cpu-freq.h>
26 #include <mach/regs-clock.h>
27 #include <plat/clock.h>
30 #include <plat/s5p-clock.h>
31 #include <plat/clock-clksrc.h>
35 static unsigned long xtal
;
37 static struct clksrc_clk clk_mout_apll
= {
41 .sources
= &clk_src_apll
,
42 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 0, .size
= 1 },
45 static struct clksrc_clk clk_mout_epll
= {
49 .sources
= &clk_src_epll
,
50 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 8, .size
= 1 },
53 static struct clksrc_clk clk_mout_mpll
= {
57 .sources
= &clk_src_mpll
,
58 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 4, .size
= 1 },
61 static struct clk
*clkset_armclk_list
[] = {
62 [0] = &clk_mout_apll
.clk
,
63 [1] = &clk_mout_mpll
.clk
,
66 static struct clksrc_sources clkset_armclk
= {
67 .sources
= clkset_armclk_list
,
68 .nr_sources
= ARRAY_SIZE(clkset_armclk_list
),
71 static struct clksrc_clk clk_armclk
= {
75 .sources
= &clkset_armclk
,
76 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 16, .size
= 1 },
77 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 0, .size
= 3 },
80 static struct clksrc_clk clk_hclk_msys
= {
83 .parent
= &clk_armclk
.clk
,
85 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 8, .size
= 3 },
88 static struct clksrc_clk clk_pclk_msys
= {
91 .parent
= &clk_hclk_msys
.clk
,
93 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 12, .size
= 3 },
96 static struct clksrc_clk clk_sclk_a2m
= {
99 .parent
= &clk_mout_apll
.clk
,
101 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 4, .size
= 3 },
104 static struct clk
*clkset_hclk_sys_list
[] = {
105 [0] = &clk_mout_mpll
.clk
,
106 [1] = &clk_sclk_a2m
.clk
,
109 static struct clksrc_sources clkset_hclk_sys
= {
110 .sources
= clkset_hclk_sys_list
,
111 .nr_sources
= ARRAY_SIZE(clkset_hclk_sys_list
),
114 static struct clksrc_clk clk_hclk_dsys
= {
118 .sources
= &clkset_hclk_sys
,
119 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 20, .size
= 1 },
120 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 16, .size
= 4 },
123 static struct clksrc_clk clk_pclk_dsys
= {
126 .parent
= &clk_hclk_dsys
.clk
,
128 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 20, .size
= 3 },
131 static struct clksrc_clk clk_hclk_psys
= {
135 .sources
= &clkset_hclk_sys
,
136 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 24, .size
= 1 },
137 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 24, .size
= 4 },
140 static struct clksrc_clk clk_pclk_psys
= {
143 .parent
= &clk_hclk_psys
.clk
,
145 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 28, .size
= 3 },
148 static int s5pv210_clk_ip0_ctrl(struct clk
*clk
, int enable
)
150 return s5p_gatectrl(S5P_CLKGATE_IP0
, clk
, enable
);
153 static int s5pv210_clk_ip1_ctrl(struct clk
*clk
, int enable
)
155 return s5p_gatectrl(S5P_CLKGATE_IP1
, clk
, enable
);
158 static int s5pv210_clk_ip2_ctrl(struct clk
*clk
, int enable
)
160 return s5p_gatectrl(S5P_CLKGATE_IP2
, clk
, enable
);
163 static int s5pv210_clk_ip3_ctrl(struct clk
*clk
, int enable
)
165 return s5p_gatectrl(S5P_CLKGATE_IP3
, clk
, enable
);
168 static int s5pv210_clk_mask0_ctrl(struct clk
*clk
, int enable
)
170 return s5p_gatectrl(S5P_CLK_SRC_MASK0
, clk
, enable
);
173 static int s5pv210_clk_mask1_ctrl(struct clk
*clk
, int enable
)
175 return s5p_gatectrl(S5P_CLK_SRC_MASK1
, clk
, enable
);
178 static int s5pv210_clk_hdmiphy_ctrl(struct clk
*clk
, int enable
)
180 return s5p_gatectrl(S5P_HDMI_PHY_CONTROL
, clk
, enable
);
183 static int exynos4_clk_dac_ctrl(struct clk
*clk
, int enable
)
185 return s5p_gatectrl(S5P_DAC_PHY_CONTROL
, clk
, enable
);
188 static struct clk clk_sclk_hdmi27m
= {
189 .name
= "sclk_hdmi27m",
193 static struct clk clk_sclk_hdmiphy
= {
194 .name
= "sclk_hdmiphy",
197 static struct clk clk_sclk_usbphy0
= {
198 .name
= "sclk_usbphy0",
201 static struct clk clk_sclk_usbphy1
= {
202 .name
= "sclk_usbphy1",
205 static struct clk clk_pcmcdclk0
= {
209 static struct clk clk_pcmcdclk1
= {
213 static struct clk clk_pcmcdclk2
= {
217 static struct clk dummy_apb_pclk
= {
222 static struct clk
*clkset_vpllsrc_list
[] = {
224 [1] = &clk_sclk_hdmi27m
,
227 static struct clksrc_sources clkset_vpllsrc
= {
228 .sources
= clkset_vpllsrc_list
,
229 .nr_sources
= ARRAY_SIZE(clkset_vpllsrc_list
),
232 static struct clksrc_clk clk_vpllsrc
= {
235 .enable
= s5pv210_clk_mask0_ctrl
,
238 .sources
= &clkset_vpllsrc
,
239 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 28, .size
= 1 },
242 static struct clk
*clkset_sclk_vpll_list
[] = {
243 [0] = &clk_vpllsrc
.clk
,
244 [1] = &clk_fout_vpll
,
247 static struct clksrc_sources clkset_sclk_vpll
= {
248 .sources
= clkset_sclk_vpll_list
,
249 .nr_sources
= ARRAY_SIZE(clkset_sclk_vpll_list
),
252 static struct clksrc_clk clk_sclk_vpll
= {
256 .sources
= &clkset_sclk_vpll
,
257 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 12, .size
= 1 },
260 static struct clk
*clkset_moutdmc0src_list
[] = {
261 [0] = &clk_sclk_a2m
.clk
,
262 [1] = &clk_mout_mpll
.clk
,
267 static struct clksrc_sources clkset_moutdmc0src
= {
268 .sources
= clkset_moutdmc0src_list
,
269 .nr_sources
= ARRAY_SIZE(clkset_moutdmc0src_list
),
272 static struct clksrc_clk clk_mout_dmc0
= {
276 .sources
= &clkset_moutdmc0src
,
277 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 24, .size
= 2 },
280 static struct clksrc_clk clk_sclk_dmc0
= {
283 .parent
= &clk_mout_dmc0
.clk
,
285 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 28, .size
= 4 },
288 static unsigned long s5pv210_clk_imem_get_rate(struct clk
*clk
)
290 return clk_get_rate(clk
->parent
) / 2;
293 static struct clk_ops clk_hclk_imem_ops
= {
294 .get_rate
= s5pv210_clk_imem_get_rate
,
297 static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk
*clk
)
299 return s5p_get_pll45xx(xtal
, __raw_readl(S5P_APLL_CON
), pll_4508
);
302 static struct clk_ops clk_fout_apll_ops
= {
303 .get_rate
= s5pv210_clk_fout_apll_get_rate
,
306 static struct clk init_clocks_off
[] = {
309 .devname
= "dma-pl330.0",
310 .parent
= &clk_hclk_psys
.clk
,
311 .enable
= s5pv210_clk_ip0_ctrl
,
315 .devname
= "dma-pl330.1",
316 .parent
= &clk_hclk_psys
.clk
,
317 .enable
= s5pv210_clk_ip0_ctrl
,
321 .parent
= &clk_hclk_dsys
.clk
,
322 .enable
= s5pv210_clk_ip0_ctrl
,
326 .devname
= "s5pv210-fimc.0",
327 .parent
= &clk_hclk_dsys
.clk
,
328 .enable
= s5pv210_clk_ip0_ctrl
,
329 .ctrlbit
= (1 << 24),
332 .devname
= "s5pv210-fimc.1",
333 .parent
= &clk_hclk_dsys
.clk
,
334 .enable
= s5pv210_clk_ip0_ctrl
,
335 .ctrlbit
= (1 << 25),
338 .devname
= "s5pv210-fimc.2",
339 .parent
= &clk_hclk_dsys
.clk
,
340 .enable
= s5pv210_clk_ip0_ctrl
,
341 .ctrlbit
= (1 << 26),
344 .parent
= &clk_hclk_dsys
.clk
,
345 .enable
= s5pv210_clk_ip0_ctrl
,
346 .ctrlbit
= (1 << 28),
349 .devname
= "s5p-mfc",
350 .parent
= &clk_pclk_psys
.clk
,
351 .enable
= s5pv210_clk_ip0_ctrl
,
352 .ctrlbit
= (1 << 16),
355 .devname
= "s5p-sdo",
356 .parent
= &clk_hclk_dsys
.clk
,
357 .enable
= s5pv210_clk_ip1_ctrl
,
358 .ctrlbit
= (1 << 10),
361 .devname
= "s5p-mixer",
362 .parent
= &clk_hclk_dsys
.clk
,
363 .enable
= s5pv210_clk_ip1_ctrl
,
367 .devname
= "s5p-mixer",
368 .parent
= &clk_hclk_dsys
.clk
,
369 .enable
= s5pv210_clk_ip1_ctrl
,
373 .devname
= "s5pv210-hdmi",
374 .parent
= &clk_hclk_dsys
.clk
,
375 .enable
= s5pv210_clk_ip1_ctrl
,
376 .ctrlbit
= (1 << 11),
379 .devname
= "s5pv210-hdmi",
380 .enable
= s5pv210_clk_hdmiphy_ctrl
,
384 .devname
= "s5p-sdo",
385 .enable
= exynos4_clk_dac_ctrl
,
389 .parent
= &clk_hclk_psys
.clk
,
390 .enable
= s5pv210_clk_ip1_ctrl
,
394 .parent
= &clk_hclk_psys
.clk
,
395 .enable
= s5pv210_clk_ip1_ctrl
,
399 .parent
= &clk_hclk_dsys
.clk
,
400 .enable
= s5pv210_clk_ip1_ctrl
,
404 .parent
= &clk_hclk_psys
.clk
,
405 .enable
= s5pv210_clk_ip1_ctrl
,
409 .parent
= &clk_pclk_psys
.clk
,
410 .enable
= s5pv210_clk_ip3_ctrl
,
414 .parent
= &clk_pclk_psys
.clk
,
415 .enable
= s5pv210_clk_ip3_ctrl
,
419 .parent
= &clk_pclk_psys
.clk
,
420 .enable
= s5pv210_clk_ip3_ctrl
,
424 .devname
= "s3c2440-i2c.0",
425 .parent
= &clk_pclk_psys
.clk
,
426 .enable
= s5pv210_clk_ip3_ctrl
,
430 .devname
= "s3c2440-i2c.1",
431 .parent
= &clk_pclk_psys
.clk
,
432 .enable
= s5pv210_clk_ip3_ctrl
,
433 .ctrlbit
= (1 << 10),
436 .devname
= "s3c2440-i2c.2",
437 .parent
= &clk_pclk_psys
.clk
,
438 .enable
= s5pv210_clk_ip3_ctrl
,
442 .devname
= "s3c2440-hdmiphy-i2c",
443 .parent
= &clk_pclk_psys
.clk
,
444 .enable
= s5pv210_clk_ip3_ctrl
,
445 .ctrlbit
= (1 << 11),
448 .devname
= "s5pv210-spi.0",
449 .parent
= &clk_pclk_psys
.clk
,
450 .enable
= s5pv210_clk_ip3_ctrl
,
454 .devname
= "s5pv210-spi.1",
455 .parent
= &clk_pclk_psys
.clk
,
456 .enable
= s5pv210_clk_ip3_ctrl
,
460 .devname
= "s5pv210-spi.2",
461 .parent
= &clk_pclk_psys
.clk
,
462 .enable
= s5pv210_clk_ip3_ctrl
,
466 .parent
= &clk_pclk_psys
.clk
,
467 .enable
= s5pv210_clk_ip3_ctrl
,
471 .parent
= &clk_pclk_psys
.clk
,
472 .enable
= s5pv210_clk_ip3_ctrl
,
476 .parent
= &clk_pclk_psys
.clk
,
477 .enable
= s5pv210_clk_ip3_ctrl
,
481 .devname
= "samsung-i2s.0",
483 .enable
= s5pv210_clk_ip3_ctrl
,
487 .devname
= "samsung-i2s.1",
489 .enable
= s5pv210_clk_ip3_ctrl
,
493 .devname
= "samsung-i2s.2",
495 .enable
= s5pv210_clk_ip3_ctrl
,
500 .enable
= s5pv210_clk_ip3_ctrl
,
505 static struct clk init_clocks
[] = {
508 .parent
= &clk_hclk_msys
.clk
,
510 .enable
= s5pv210_clk_ip0_ctrl
,
511 .ops
= &clk_hclk_imem_ops
,
514 .devname
= "s5pv210-uart.0",
515 .parent
= &clk_pclk_psys
.clk
,
516 .enable
= s5pv210_clk_ip3_ctrl
,
517 .ctrlbit
= (1 << 17),
520 .devname
= "s5pv210-uart.1",
521 .parent
= &clk_pclk_psys
.clk
,
522 .enable
= s5pv210_clk_ip3_ctrl
,
523 .ctrlbit
= (1 << 18),
526 .devname
= "s5pv210-uart.2",
527 .parent
= &clk_pclk_psys
.clk
,
528 .enable
= s5pv210_clk_ip3_ctrl
,
529 .ctrlbit
= (1 << 19),
532 .devname
= "s5pv210-uart.3",
533 .parent
= &clk_pclk_psys
.clk
,
534 .enable
= s5pv210_clk_ip3_ctrl
,
535 .ctrlbit
= (1 << 20),
538 .parent
= &clk_hclk_psys
.clk
,
539 .enable
= s5pv210_clk_ip1_ctrl
,
540 .ctrlbit
= (1 << 26),
544 static struct clk clk_hsmmc0
= {
546 .devname
= "s3c-sdhci.0",
547 .parent
= &clk_hclk_psys
.clk
,
548 .enable
= s5pv210_clk_ip2_ctrl
,
552 static struct clk clk_hsmmc1
= {
554 .devname
= "s3c-sdhci.1",
555 .parent
= &clk_hclk_psys
.clk
,
556 .enable
= s5pv210_clk_ip2_ctrl
,
560 static struct clk clk_hsmmc2
= {
562 .devname
= "s3c-sdhci.2",
563 .parent
= &clk_hclk_psys
.clk
,
564 .enable
= s5pv210_clk_ip2_ctrl
,
568 static struct clk clk_hsmmc3
= {
570 .devname
= "s3c-sdhci.3",
571 .parent
= &clk_hclk_psys
.clk
,
572 .enable
= s5pv210_clk_ip2_ctrl
,
576 static struct clk
*clkset_uart_list
[] = {
577 [6] = &clk_mout_mpll
.clk
,
578 [7] = &clk_mout_epll
.clk
,
581 static struct clksrc_sources clkset_uart
= {
582 .sources
= clkset_uart_list
,
583 .nr_sources
= ARRAY_SIZE(clkset_uart_list
),
586 static struct clk
*clkset_group1_list
[] = {
587 [0] = &clk_sclk_a2m
.clk
,
588 [1] = &clk_mout_mpll
.clk
,
589 [2] = &clk_mout_epll
.clk
,
590 [3] = &clk_sclk_vpll
.clk
,
593 static struct clksrc_sources clkset_group1
= {
594 .sources
= clkset_group1_list
,
595 .nr_sources
= ARRAY_SIZE(clkset_group1_list
),
598 static struct clk
*clkset_sclk_onenand_list
[] = {
599 [0] = &clk_hclk_psys
.clk
,
600 [1] = &clk_hclk_dsys
.clk
,
603 static struct clksrc_sources clkset_sclk_onenand
= {
604 .sources
= clkset_sclk_onenand_list
,
605 .nr_sources
= ARRAY_SIZE(clkset_sclk_onenand_list
),
608 static struct clk
*clkset_sclk_dac_list
[] = {
609 [0] = &clk_sclk_vpll
.clk
,
610 [1] = &clk_sclk_hdmiphy
,
613 static struct clksrc_sources clkset_sclk_dac
= {
614 .sources
= clkset_sclk_dac_list
,
615 .nr_sources
= ARRAY_SIZE(clkset_sclk_dac_list
),
618 static struct clksrc_clk clk_sclk_dac
= {
621 .enable
= s5pv210_clk_mask0_ctrl
,
624 .sources
= &clkset_sclk_dac
,
625 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 8, .size
= 1 },
628 static struct clksrc_clk clk_sclk_pixel
= {
630 .name
= "sclk_pixel",
631 .parent
= &clk_sclk_vpll
.clk
,
633 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 0, .size
= 4},
636 static struct clk
*clkset_sclk_hdmi_list
[] = {
637 [0] = &clk_sclk_pixel
.clk
,
638 [1] = &clk_sclk_hdmiphy
,
641 static struct clksrc_sources clkset_sclk_hdmi
= {
642 .sources
= clkset_sclk_hdmi_list
,
643 .nr_sources
= ARRAY_SIZE(clkset_sclk_hdmi_list
),
646 static struct clksrc_clk clk_sclk_hdmi
= {
649 .enable
= s5pv210_clk_mask0_ctrl
,
652 .sources
= &clkset_sclk_hdmi
,
653 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 0, .size
= 1 },
656 static struct clk
*clkset_sclk_mixer_list
[] = {
657 [0] = &clk_sclk_dac
.clk
,
658 [1] = &clk_sclk_hdmi
.clk
,
661 static struct clksrc_sources clkset_sclk_mixer
= {
662 .sources
= clkset_sclk_mixer_list
,
663 .nr_sources
= ARRAY_SIZE(clkset_sclk_mixer_list
),
666 static struct clksrc_clk clk_sclk_mixer
= {
668 .name
= "sclk_mixer",
669 .enable
= s5pv210_clk_mask0_ctrl
,
672 .sources
= &clkset_sclk_mixer
,
673 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 4, .size
= 1 },
676 static struct clksrc_clk
*sclk_tv
[] = {
683 static struct clk
*clkset_sclk_audio0_list
[] = {
684 [0] = &clk_ext_xtal_mux
,
685 [1] = &clk_pcmcdclk0
,
686 [2] = &clk_sclk_hdmi27m
,
687 [3] = &clk_sclk_usbphy0
,
688 [4] = &clk_sclk_usbphy1
,
689 [5] = &clk_sclk_hdmiphy
,
690 [6] = &clk_mout_mpll
.clk
,
691 [7] = &clk_mout_epll
.clk
,
692 [8] = &clk_sclk_vpll
.clk
,
695 static struct clksrc_sources clkset_sclk_audio0
= {
696 .sources
= clkset_sclk_audio0_list
,
697 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio0_list
),
700 static struct clksrc_clk clk_sclk_audio0
= {
702 .name
= "sclk_audio",
703 .devname
= "soc-audio.0",
704 .enable
= s5pv210_clk_mask0_ctrl
,
705 .ctrlbit
= (1 << 24),
707 .sources
= &clkset_sclk_audio0
,
708 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 0, .size
= 4 },
709 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 0, .size
= 4 },
712 static struct clk
*clkset_sclk_audio1_list
[] = {
713 [0] = &clk_ext_xtal_mux
,
714 [1] = &clk_pcmcdclk1
,
715 [2] = &clk_sclk_hdmi27m
,
716 [3] = &clk_sclk_usbphy0
,
717 [4] = &clk_sclk_usbphy1
,
718 [5] = &clk_sclk_hdmiphy
,
719 [6] = &clk_mout_mpll
.clk
,
720 [7] = &clk_mout_epll
.clk
,
721 [8] = &clk_sclk_vpll
.clk
,
724 static struct clksrc_sources clkset_sclk_audio1
= {
725 .sources
= clkset_sclk_audio1_list
,
726 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio1_list
),
729 static struct clksrc_clk clk_sclk_audio1
= {
731 .name
= "sclk_audio",
732 .devname
= "soc-audio.1",
733 .enable
= s5pv210_clk_mask0_ctrl
,
734 .ctrlbit
= (1 << 25),
736 .sources
= &clkset_sclk_audio1
,
737 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 4, .size
= 4 },
738 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 4, .size
= 4 },
741 static struct clk
*clkset_sclk_audio2_list
[] = {
742 [0] = &clk_ext_xtal_mux
,
743 [1] = &clk_pcmcdclk0
,
744 [2] = &clk_sclk_hdmi27m
,
745 [3] = &clk_sclk_usbphy0
,
746 [4] = &clk_sclk_usbphy1
,
747 [5] = &clk_sclk_hdmiphy
,
748 [6] = &clk_mout_mpll
.clk
,
749 [7] = &clk_mout_epll
.clk
,
750 [8] = &clk_sclk_vpll
.clk
,
753 static struct clksrc_sources clkset_sclk_audio2
= {
754 .sources
= clkset_sclk_audio2_list
,
755 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio2_list
),
758 static struct clksrc_clk clk_sclk_audio2
= {
760 .name
= "sclk_audio",
761 .devname
= "soc-audio.2",
762 .enable
= s5pv210_clk_mask0_ctrl
,
763 .ctrlbit
= (1 << 26),
765 .sources
= &clkset_sclk_audio2
,
766 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 8, .size
= 4 },
767 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 8, .size
= 4 },
770 static struct clk
*clkset_sclk_spdif_list
[] = {
771 [0] = &clk_sclk_audio0
.clk
,
772 [1] = &clk_sclk_audio1
.clk
,
773 [2] = &clk_sclk_audio2
.clk
,
776 static struct clksrc_sources clkset_sclk_spdif
= {
777 .sources
= clkset_sclk_spdif_list
,
778 .nr_sources
= ARRAY_SIZE(clkset_sclk_spdif_list
),
781 static struct clksrc_clk clk_sclk_spdif
= {
783 .name
= "sclk_spdif",
784 .enable
= s5pv210_clk_mask0_ctrl
,
785 .ctrlbit
= (1 << 27),
786 .ops
= &s5p_sclk_spdif_ops
,
788 .sources
= &clkset_sclk_spdif
,
789 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 12, .size
= 2 },
792 static struct clk
*clkset_group2_list
[] = {
793 [0] = &clk_ext_xtal_mux
,
795 [2] = &clk_sclk_hdmi27m
,
796 [3] = &clk_sclk_usbphy0
,
797 [4] = &clk_sclk_usbphy1
,
798 [5] = &clk_sclk_hdmiphy
,
799 [6] = &clk_mout_mpll
.clk
,
800 [7] = &clk_mout_epll
.clk
,
801 [8] = &clk_sclk_vpll
.clk
,
804 static struct clksrc_sources clkset_group2
= {
805 .sources
= clkset_group2_list
,
806 .nr_sources
= ARRAY_SIZE(clkset_group2_list
),
809 static struct clksrc_clk clksrcs
[] = {
814 .sources
= &clkset_group1
,
815 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 24, .size
= 2 },
816 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 28, .size
= 4 },
819 .name
= "sclk_onenand",
821 .sources
= &clkset_sclk_onenand
,
822 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 28, .size
= 1 },
823 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 12, .size
= 3 },
827 .devname
= "s5pv210-fimc.0",
828 .enable
= s5pv210_clk_mask1_ctrl
,
831 .sources
= &clkset_group2
,
832 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 12, .size
= 4 },
833 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 12, .size
= 4 },
837 .devname
= "s5pv210-fimc.1",
838 .enable
= s5pv210_clk_mask1_ctrl
,
841 .sources
= &clkset_group2
,
842 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 16, .size
= 4 },
843 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 16, .size
= 4 },
847 .devname
= "s5pv210-fimc.2",
848 .enable
= s5pv210_clk_mask1_ctrl
,
851 .sources
= &clkset_group2
,
852 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 20, .size
= 4 },
853 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 20, .size
= 4 },
857 .enable
= s5pv210_clk_mask0_ctrl
,
860 .sources
= &clkset_group2
,
861 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 12, .size
= 4 },
862 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 12, .size
= 4 },
866 .enable
= s5pv210_clk_mask0_ctrl
,
869 .sources
= &clkset_group2
,
870 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 16, .size
= 4 },
871 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 16, .size
= 4 },
875 .enable
= s5pv210_clk_mask0_ctrl
,
878 .sources
= &clkset_group2
,
879 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 20, .size
= 4 },
880 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 20, .size
= 4 },
884 .devname
= "s5p-mfc",
885 .enable
= s5pv210_clk_ip0_ctrl
,
886 .ctrlbit
= (1 << 16),
888 .sources
= &clkset_group1
,
889 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 4, .size
= 2 },
890 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 4, .size
= 4 },
894 .enable
= s5pv210_clk_ip0_ctrl
,
895 .ctrlbit
= (1 << 12),
897 .sources
= &clkset_group1
,
898 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 8, .size
= 2 },
899 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 8, .size
= 4 },
903 .enable
= s5pv210_clk_ip0_ctrl
,
906 .sources
= &clkset_group1
,
907 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 0, .size
= 2 },
908 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 0, .size
= 4 },
912 .enable
= s5pv210_clk_mask0_ctrl
,
915 .sources
= &clkset_group2
,
916 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 24, .size
= 4 },
917 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 28, .size
= 4 },
921 .enable
= s5pv210_clk_mask0_ctrl
,
922 .ctrlbit
= (1 << 29),
924 .sources
= &clkset_group2
,
925 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 20, .size
= 4 },
926 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 24, .size
= 4 },
930 .enable
= s5pv210_clk_mask0_ctrl
,
931 .ctrlbit
= (1 << 19),
933 .sources
= &clkset_group2
,
934 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 12, .size
= 4 },
935 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 12, .size
= 4 },
939 static struct clksrc_clk clk_sclk_uart0
= {
942 .devname
= "s5pv210-uart.0",
943 .enable
= s5pv210_clk_mask0_ctrl
,
944 .ctrlbit
= (1 << 12),
946 .sources
= &clkset_uart
,
947 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 16, .size
= 4 },
948 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 16, .size
= 4 },
951 static struct clksrc_clk clk_sclk_uart1
= {
954 .devname
= "s5pv210-uart.1",
955 .enable
= s5pv210_clk_mask0_ctrl
,
956 .ctrlbit
= (1 << 13),
958 .sources
= &clkset_uart
,
959 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 20, .size
= 4 },
960 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 20, .size
= 4 },
963 static struct clksrc_clk clk_sclk_uart2
= {
966 .devname
= "s5pv210-uart.2",
967 .enable
= s5pv210_clk_mask0_ctrl
,
968 .ctrlbit
= (1 << 14),
970 .sources
= &clkset_uart
,
971 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 24, .size
= 4 },
972 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 24, .size
= 4 },
975 static struct clksrc_clk clk_sclk_uart3
= {
978 .devname
= "s5pv210-uart.3",
979 .enable
= s5pv210_clk_mask0_ctrl
,
980 .ctrlbit
= (1 << 15),
982 .sources
= &clkset_uart
,
983 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 28, .size
= 4 },
984 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 28, .size
= 4 },
987 static struct clksrc_clk clk_sclk_mmc0
= {
990 .devname
= "s3c-sdhci.0",
991 .enable
= s5pv210_clk_mask0_ctrl
,
994 .sources
= &clkset_group2
,
995 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 0, .size
= 4 },
996 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 0, .size
= 4 },
999 static struct clksrc_clk clk_sclk_mmc1
= {
1002 .devname
= "s3c-sdhci.1",
1003 .enable
= s5pv210_clk_mask0_ctrl
,
1004 .ctrlbit
= (1 << 9),
1006 .sources
= &clkset_group2
,
1007 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 4, .size
= 4 },
1008 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 4, .size
= 4 },
1011 static struct clksrc_clk clk_sclk_mmc2
= {
1014 .devname
= "s3c-sdhci.2",
1015 .enable
= s5pv210_clk_mask0_ctrl
,
1016 .ctrlbit
= (1 << 10),
1018 .sources
= &clkset_group2
,
1019 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 8, .size
= 4 },
1020 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 8, .size
= 4 },
1023 static struct clksrc_clk clk_sclk_mmc3
= {
1026 .devname
= "s3c-sdhci.3",
1027 .enable
= s5pv210_clk_mask0_ctrl
,
1028 .ctrlbit
= (1 << 11),
1030 .sources
= &clkset_group2
,
1031 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 12, .size
= 4 },
1032 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 12, .size
= 4 },
1035 static struct clksrc_clk clk_sclk_spi0
= {
1038 .devname
= "s5pv210-spi.0",
1039 .enable
= s5pv210_clk_mask0_ctrl
,
1040 .ctrlbit
= (1 << 16),
1042 .sources
= &clkset_group2
,
1043 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 0, .size
= 4 },
1044 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 0, .size
= 4 },
1047 static struct clksrc_clk clk_sclk_spi1
= {
1050 .devname
= "s5pv210-spi.1",
1051 .enable
= s5pv210_clk_mask0_ctrl
,
1052 .ctrlbit
= (1 << 17),
1054 .sources
= &clkset_group2
,
1055 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 4, .size
= 4 },
1056 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 4, .size
= 4 },
1060 static struct clksrc_clk
*clksrc_cdev
[] = {
1073 static struct clk
*clk_cdev
[] = {
1080 /* Clock initialisation code */
1081 static struct clksrc_clk
*sysclks
[] = {
1103 static u32 epll_div
[][6] = {
1104 { 48000000, 0, 48, 3, 3, 0 },
1105 { 96000000, 0, 48, 3, 2, 0 },
1106 { 144000000, 1, 72, 3, 2, 0 },
1107 { 192000000, 0, 48, 3, 1, 0 },
1108 { 288000000, 1, 72, 3, 1, 0 },
1109 { 32750000, 1, 65, 3, 4, 35127 },
1110 { 32768000, 1, 65, 3, 4, 35127 },
1111 { 45158400, 0, 45, 3, 3, 10355 },
1112 { 45000000, 0, 45, 3, 3, 10355 },
1113 { 45158000, 0, 45, 3, 3, 10355 },
1114 { 49125000, 0, 49, 3, 3, 9961 },
1115 { 49152000, 0, 49, 3, 3, 9961 },
1116 { 67737600, 1, 67, 3, 3, 48366 },
1117 { 67738000, 1, 67, 3, 3, 48366 },
1118 { 73800000, 1, 73, 3, 3, 47710 },
1119 { 73728000, 1, 73, 3, 3, 47710 },
1120 { 36000000, 1, 32, 3, 4, 0 },
1121 { 60000000, 1, 60, 3, 3, 0 },
1122 { 72000000, 1, 72, 3, 3, 0 },
1123 { 80000000, 1, 80, 3, 3, 0 },
1124 { 84000000, 0, 42, 3, 2, 0 },
1125 { 50000000, 0, 50, 3, 3, 0 },
1128 static int s5pv210_epll_set_rate(struct clk
*clk
, unsigned long rate
)
1130 unsigned int epll_con
, epll_con_k
;
1133 /* Return if nothing changed */
1134 if (clk
->rate
== rate
)
1137 epll_con
= __raw_readl(S5P_EPLL_CON
);
1138 epll_con_k
= __raw_readl(S5P_EPLL_CON1
);
1140 epll_con_k
&= ~PLL46XX_KDIV_MASK
;
1141 epll_con
&= ~(1 << 27 |
1142 PLL46XX_MDIV_MASK
<< PLL46XX_MDIV_SHIFT
|
1143 PLL46XX_PDIV_MASK
<< PLL46XX_PDIV_SHIFT
|
1144 PLL46XX_SDIV_MASK
<< PLL46XX_SDIV_SHIFT
);
1146 for (i
= 0; i
< ARRAY_SIZE(epll_div
); i
++) {
1147 if (epll_div
[i
][0] == rate
) {
1148 epll_con_k
|= epll_div
[i
][5] << 0;
1149 epll_con
|= (epll_div
[i
][1] << 27 |
1150 epll_div
[i
][2] << PLL46XX_MDIV_SHIFT
|
1151 epll_div
[i
][3] << PLL46XX_PDIV_SHIFT
|
1152 epll_div
[i
][4] << PLL46XX_SDIV_SHIFT
);
1157 if (i
== ARRAY_SIZE(epll_div
)) {
1158 printk(KERN_ERR
"%s: Invalid Clock EPLL Frequency\n",
1163 __raw_writel(epll_con
, S5P_EPLL_CON
);
1164 __raw_writel(epll_con_k
, S5P_EPLL_CON1
);
1166 printk(KERN_WARNING
"EPLL Rate changes from %lu to %lu\n",
1174 static struct clk_ops s5pv210_epll_ops
= {
1175 .set_rate
= s5pv210_epll_set_rate
,
1176 .get_rate
= s5p_epll_get_rate
,
1179 static u32 vpll_div
[][5] = {
1180 { 54000000, 3, 53, 3, 0 },
1181 { 108000000, 3, 53, 2, 0 },
1184 static unsigned long s5pv210_vpll_get_rate(struct clk
*clk
)
1189 static int s5pv210_vpll_set_rate(struct clk
*clk
, unsigned long rate
)
1191 unsigned int vpll_con
;
1194 /* Return if nothing changed */
1195 if (clk
->rate
== rate
)
1198 vpll_con
= __raw_readl(S5P_VPLL_CON
);
1199 vpll_con
&= ~(0x1 << 27 | \
1200 PLL90XX_MDIV_MASK
<< PLL90XX_MDIV_SHIFT
| \
1201 PLL90XX_PDIV_MASK
<< PLL90XX_PDIV_SHIFT
| \
1202 PLL90XX_SDIV_MASK
<< PLL90XX_SDIV_SHIFT
);
1204 for (i
= 0; i
< ARRAY_SIZE(vpll_div
); i
++) {
1205 if (vpll_div
[i
][0] == rate
) {
1206 vpll_con
|= vpll_div
[i
][1] << PLL90XX_PDIV_SHIFT
;
1207 vpll_con
|= vpll_div
[i
][2] << PLL90XX_MDIV_SHIFT
;
1208 vpll_con
|= vpll_div
[i
][3] << PLL90XX_SDIV_SHIFT
;
1209 vpll_con
|= vpll_div
[i
][4] << 27;
1214 if (i
== ARRAY_SIZE(vpll_div
)) {
1215 printk(KERN_ERR
"%s: Invalid Clock VPLL Frequency\n",
1220 __raw_writel(vpll_con
, S5P_VPLL_CON
);
1222 /* Wait for VPLL lock */
1223 while (!(__raw_readl(S5P_VPLL_CON
) & (1 << PLL90XX_LOCKED_SHIFT
)))
1229 static struct clk_ops s5pv210_vpll_ops
= {
1230 .get_rate
= s5pv210_vpll_get_rate
,
1231 .set_rate
= s5pv210_vpll_set_rate
,
1234 void __init_or_cpufreq
s5pv210_setup_clocks(void)
1236 struct clk
*xtal_clk
;
1237 unsigned long vpllsrc
;
1238 unsigned long armclk
;
1239 unsigned long hclk_msys
;
1240 unsigned long hclk_dsys
;
1241 unsigned long hclk_psys
;
1242 unsigned long pclk_msys
;
1243 unsigned long pclk_dsys
;
1244 unsigned long pclk_psys
;
1250 u32 clkdiv0
, clkdiv1
;
1252 /* Set functions for clk_fout_epll */
1253 clk_fout_epll
.enable
= s5p_epll_enable
;
1254 clk_fout_epll
.ops
= &s5pv210_epll_ops
;
1256 printk(KERN_DEBUG
"%s: registering clocks\n", __func__
);
1258 clkdiv0
= __raw_readl(S5P_CLK_DIV0
);
1259 clkdiv1
= __raw_readl(S5P_CLK_DIV1
);
1261 printk(KERN_DEBUG
"%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
1262 __func__
, clkdiv0
, clkdiv1
);
1264 xtal_clk
= clk_get(NULL
, "xtal");
1265 BUG_ON(IS_ERR(xtal_clk
));
1267 xtal
= clk_get_rate(xtal_clk
);
1270 printk(KERN_DEBUG
"%s: xtal is %ld\n", __func__
, xtal
);
1272 apll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_APLL_CON
), pll_4508
);
1273 mpll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_MPLL_CON
), pll_4502
);
1274 epll
= s5p_get_pll46xx(xtal
, __raw_readl(S5P_EPLL_CON
),
1275 __raw_readl(S5P_EPLL_CON1
), pll_4600
);
1276 vpllsrc
= clk_get_rate(&clk_vpllsrc
.clk
);
1277 vpll
= s5p_get_pll45xx(vpllsrc
, __raw_readl(S5P_VPLL_CON
), pll_4502
);
1279 clk_fout_apll
.ops
= &clk_fout_apll_ops
;
1280 clk_fout_mpll
.rate
= mpll
;
1281 clk_fout_epll
.rate
= epll
;
1282 clk_fout_vpll
.ops
= &s5pv210_vpll_ops
;
1283 clk_fout_vpll
.rate
= vpll
;
1285 printk(KERN_INFO
"S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
1286 apll
, mpll
, epll
, vpll
);
1288 armclk
= clk_get_rate(&clk_armclk
.clk
);
1289 hclk_msys
= clk_get_rate(&clk_hclk_msys
.clk
);
1290 hclk_dsys
= clk_get_rate(&clk_hclk_dsys
.clk
);
1291 hclk_psys
= clk_get_rate(&clk_hclk_psys
.clk
);
1292 pclk_msys
= clk_get_rate(&clk_pclk_msys
.clk
);
1293 pclk_dsys
= clk_get_rate(&clk_pclk_dsys
.clk
);
1294 pclk_psys
= clk_get_rate(&clk_pclk_psys
.clk
);
1296 printk(KERN_INFO
"S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
1297 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
1298 armclk
, hclk_msys
, hclk_dsys
, hclk_psys
,
1299 pclk_msys
, pclk_dsys
, pclk_psys
);
1301 clk_f
.rate
= armclk
;
1302 clk_h
.rate
= hclk_psys
;
1303 clk_p
.rate
= pclk_psys
;
1305 for (ptr
= 0; ptr
< ARRAY_SIZE(clksrcs
); ptr
++)
1306 s3c_set_clksrc(&clksrcs
[ptr
], true);
1309 static struct clk
*clks
[] __initdata
= {
1319 static struct clk_lookup s5pv210_clk_lookup
[] = {
1320 CLKDEV_INIT(NULL
, "clk_uart_baud0", &clk_p
),
1321 CLKDEV_INIT("s5pv210-uart.0", "clk_uart_baud1", &clk_sclk_uart0
.clk
),
1322 CLKDEV_INIT("s5pv210-uart.1", "clk_uart_baud1", &clk_sclk_uart1
.clk
),
1323 CLKDEV_INIT("s5pv210-uart.2", "clk_uart_baud1", &clk_sclk_uart2
.clk
),
1324 CLKDEV_INIT("s5pv210-uart.3", "clk_uart_baud1", &clk_sclk_uart3
.clk
),
1325 CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0
),
1326 CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1
),
1327 CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2
),
1328 CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.0", &clk_hsmmc3
),
1329 CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0
.clk
),
1330 CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1
.clk
),
1331 CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2
.clk
),
1332 CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3
.clk
),
1333 CLKDEV_INIT(NULL
, "spi_busclk0", &clk_p
),
1334 CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0
.clk
),
1335 CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1
.clk
),
1338 void __init
s5pv210_register_clocks(void)
1342 s3c24xx_register_clocks(clks
, ARRAY_SIZE(clks
));
1344 for (ptr
= 0; ptr
< ARRAY_SIZE(sysclks
); ptr
++)
1345 s3c_register_clksrc(sysclks
[ptr
], 1);
1347 for (ptr
= 0; ptr
< ARRAY_SIZE(sclk_tv
); ptr
++)
1348 s3c_register_clksrc(sclk_tv
[ptr
], 1);
1350 for (ptr
= 0; ptr
< ARRAY_SIZE(clksrc_cdev
); ptr
++)
1351 s3c_register_clksrc(clksrc_cdev
[ptr
], 1);
1353 s3c_register_clksrc(clksrcs
, ARRAY_SIZE(clksrcs
));
1354 s3c_register_clocks(init_clocks
, ARRAY_SIZE(init_clocks
));
1356 s3c_register_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1357 s3c_disable_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1358 clkdev_add_table(s5pv210_clk_lookup
, ARRAY_SIZE(s5pv210_clk_lookup
));
1360 s3c24xx_register_clocks(clk_cdev
, ARRAY_SIZE(clk_cdev
));
1361 for (ptr
= 0; ptr
< ARRAY_SIZE(clk_cdev
); ptr
++)
1362 s3c_disable_clocks(clk_cdev
[ptr
], 1);
1364 s3c24xx_register_clock(&dummy_apb_pclk
);