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/sysdev.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>
32 #include <plat/s5pv210.h>
34 static unsigned long xtal
;
36 static struct clksrc_clk clk_mout_apll
= {
40 .sources
= &clk_src_apll
,
41 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 0, .size
= 1 },
44 static struct clksrc_clk clk_mout_epll
= {
48 .sources
= &clk_src_epll
,
49 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 8, .size
= 1 },
52 static struct clksrc_clk clk_mout_mpll
= {
56 .sources
= &clk_src_mpll
,
57 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 4, .size
= 1 },
60 static struct clk
*clkset_armclk_list
[] = {
61 [0] = &clk_mout_apll
.clk
,
62 [1] = &clk_mout_mpll
.clk
,
65 static struct clksrc_sources clkset_armclk
= {
66 .sources
= clkset_armclk_list
,
67 .nr_sources
= ARRAY_SIZE(clkset_armclk_list
),
70 static struct clksrc_clk clk_armclk
= {
74 .sources
= &clkset_armclk
,
75 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 16, .size
= 1 },
76 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 0, .size
= 3 },
79 static struct clksrc_clk clk_hclk_msys
= {
82 .parent
= &clk_armclk
.clk
,
84 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 8, .size
= 3 },
87 static struct clksrc_clk clk_pclk_msys
= {
90 .parent
= &clk_hclk_msys
.clk
,
92 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 12, .size
= 3 },
95 static struct clksrc_clk clk_sclk_a2m
= {
98 .parent
= &clk_mout_apll
.clk
,
100 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 4, .size
= 3 },
103 static struct clk
*clkset_hclk_sys_list
[] = {
104 [0] = &clk_mout_mpll
.clk
,
105 [1] = &clk_sclk_a2m
.clk
,
108 static struct clksrc_sources clkset_hclk_sys
= {
109 .sources
= clkset_hclk_sys_list
,
110 .nr_sources
= ARRAY_SIZE(clkset_hclk_sys_list
),
113 static struct clksrc_clk clk_hclk_dsys
= {
117 .sources
= &clkset_hclk_sys
,
118 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 20, .size
= 1 },
119 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 16, .size
= 4 },
122 static struct clksrc_clk clk_pclk_dsys
= {
125 .parent
= &clk_hclk_dsys
.clk
,
127 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 20, .size
= 3 },
130 static struct clksrc_clk clk_hclk_psys
= {
134 .sources
= &clkset_hclk_sys
,
135 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 24, .size
= 1 },
136 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 24, .size
= 4 },
139 static struct clksrc_clk clk_pclk_psys
= {
142 .parent
= &clk_hclk_psys
.clk
,
144 .reg_div
= { .reg
= S5P_CLK_DIV0
, .shift
= 28, .size
= 3 },
147 static int s5pv210_clk_ip0_ctrl(struct clk
*clk
, int enable
)
149 return s5p_gatectrl(S5P_CLKGATE_IP0
, clk
, enable
);
152 static int s5pv210_clk_ip1_ctrl(struct clk
*clk
, int enable
)
154 return s5p_gatectrl(S5P_CLKGATE_IP1
, clk
, enable
);
157 static int s5pv210_clk_ip2_ctrl(struct clk
*clk
, int enable
)
159 return s5p_gatectrl(S5P_CLKGATE_IP2
, clk
, enable
);
162 static int s5pv210_clk_ip3_ctrl(struct clk
*clk
, int enable
)
164 return s5p_gatectrl(S5P_CLKGATE_IP3
, clk
, enable
);
167 static int s5pv210_clk_mask0_ctrl(struct clk
*clk
, int enable
)
169 return s5p_gatectrl(S5P_CLK_SRC_MASK0
, clk
, enable
);
172 static int s5pv210_clk_mask1_ctrl(struct clk
*clk
, int enable
)
174 return s5p_gatectrl(S5P_CLK_SRC_MASK1
, clk
, enable
);
177 static int exynos4_clk_hdmiphy_ctrl(struct clk
*clk
, int enable
)
179 return s5p_gatectrl(S5P_HDMI_PHY_CONTROL
, clk
, enable
);
182 static int exynos4_clk_dac_ctrl(struct clk
*clk
, int enable
)
184 return s5p_gatectrl(S5P_DAC_PHY_CONTROL
, clk
, enable
);
187 static struct clk clk_sclk_hdmi27m
= {
188 .name
= "sclk_hdmi27m",
192 static struct clk clk_sclk_hdmiphy
= {
193 .name
= "sclk_hdmiphy",
196 static struct clk clk_sclk_usbphy0
= {
197 .name
= "sclk_usbphy0",
200 static struct clk clk_sclk_usbphy1
= {
201 .name
= "sclk_usbphy1",
204 static struct clk clk_pcmcdclk0
= {
208 static struct clk clk_pcmcdclk1
= {
212 static struct clk clk_pcmcdclk2
= {
216 static struct clk dummy_apb_pclk
= {
221 static struct clk
*clkset_vpllsrc_list
[] = {
223 [1] = &clk_sclk_hdmi27m
,
226 static struct clksrc_sources clkset_vpllsrc
= {
227 .sources
= clkset_vpllsrc_list
,
228 .nr_sources
= ARRAY_SIZE(clkset_vpllsrc_list
),
231 static struct clksrc_clk clk_vpllsrc
= {
234 .enable
= s5pv210_clk_mask0_ctrl
,
237 .sources
= &clkset_vpllsrc
,
238 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 28, .size
= 1 },
241 static struct clk
*clkset_sclk_vpll_list
[] = {
242 [0] = &clk_vpllsrc
.clk
,
243 [1] = &clk_fout_vpll
,
246 static struct clksrc_sources clkset_sclk_vpll
= {
247 .sources
= clkset_sclk_vpll_list
,
248 .nr_sources
= ARRAY_SIZE(clkset_sclk_vpll_list
),
251 static struct clksrc_clk clk_sclk_vpll
= {
255 .sources
= &clkset_sclk_vpll
,
256 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 12, .size
= 1 },
259 static struct clk
*clkset_moutdmc0src_list
[] = {
260 [0] = &clk_sclk_a2m
.clk
,
261 [1] = &clk_mout_mpll
.clk
,
266 static struct clksrc_sources clkset_moutdmc0src
= {
267 .sources
= clkset_moutdmc0src_list
,
268 .nr_sources
= ARRAY_SIZE(clkset_moutdmc0src_list
),
271 static struct clksrc_clk clk_mout_dmc0
= {
275 .sources
= &clkset_moutdmc0src
,
276 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 24, .size
= 2 },
279 static struct clksrc_clk clk_sclk_dmc0
= {
282 .parent
= &clk_mout_dmc0
.clk
,
284 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 28, .size
= 4 },
287 static unsigned long s5pv210_clk_imem_get_rate(struct clk
*clk
)
289 return clk_get_rate(clk
->parent
) / 2;
292 static struct clk_ops clk_hclk_imem_ops
= {
293 .get_rate
= s5pv210_clk_imem_get_rate
,
296 static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk
*clk
)
298 return s5p_get_pll45xx(xtal
, __raw_readl(S5P_APLL_CON
), pll_4508
);
301 static struct clk_ops clk_fout_apll_ops
= {
302 .get_rate
= s5pv210_clk_fout_apll_get_rate
,
305 static struct clk init_clocks_off
[] = {
308 .devname
= "dma-pl330.0",
309 .parent
= &clk_hclk_psys
.clk
,
310 .enable
= s5pv210_clk_ip0_ctrl
,
314 .devname
= "dma-pl330.1",
315 .parent
= &clk_hclk_psys
.clk
,
316 .enable
= s5pv210_clk_ip0_ctrl
,
320 .parent
= &clk_hclk_dsys
.clk
,
321 .enable
= s5pv210_clk_ip0_ctrl
,
325 .devname
= "s5pv210-fimc.0",
326 .parent
= &clk_hclk_dsys
.clk
,
327 .enable
= s5pv210_clk_ip0_ctrl
,
328 .ctrlbit
= (1 << 24),
331 .devname
= "s5pv210-fimc.1",
332 .parent
= &clk_hclk_dsys
.clk
,
333 .enable
= s5pv210_clk_ip0_ctrl
,
334 .ctrlbit
= (1 << 25),
337 .devname
= "s5pv210-fimc.2",
338 .parent
= &clk_hclk_dsys
.clk
,
339 .enable
= s5pv210_clk_ip0_ctrl
,
340 .ctrlbit
= (1 << 26),
343 .devname
= "s5p-mfc",
344 .parent
= &clk_pclk_psys
.clk
,
345 .enable
= s5pv210_clk_ip0_ctrl
,
346 .ctrlbit
= (1 << 16),
349 .devname
= "s5p-sdo",
350 .parent
= &clk_hclk_dsys
.clk
,
351 .enable
= s5pv210_clk_ip1_ctrl
,
352 .ctrlbit
= (1 << 10),
355 .devname
= "s5p-mixer",
356 .parent
= &clk_hclk_dsys
.clk
,
357 .enable
= s5pv210_clk_ip1_ctrl
,
361 .devname
= "s5p-mixer",
362 .parent
= &clk_hclk_dsys
.clk
,
363 .enable
= s5pv210_clk_ip1_ctrl
,
367 .devname
= "s5pv210-hdmi",
368 .parent
= &clk_hclk_dsys
.clk
,
369 .enable
= s5pv210_clk_ip1_ctrl
,
370 .ctrlbit
= (1 << 11),
373 .devname
= "s5pv210-hdmi",
374 .enable
= exynos4_clk_hdmiphy_ctrl
,
378 .devname
= "s5p-sdo",
379 .enable
= exynos4_clk_dac_ctrl
,
383 .parent
= &clk_hclk_psys
.clk
,
384 .enable
= s5pv210_clk_ip1_ctrl
,
388 .parent
= &clk_hclk_psys
.clk
,
389 .enable
= s5pv210_clk_ip1_ctrl
,
393 .parent
= &clk_hclk_dsys
.clk
,
394 .enable
= s5pv210_clk_ip1_ctrl
,
398 .parent
= &clk_hclk_psys
.clk
,
399 .enable
= s5pv210_clk_ip1_ctrl
,
403 .devname
= "s3c-sdhci.0",
404 .parent
= &clk_hclk_psys
.clk
,
405 .enable
= s5pv210_clk_ip2_ctrl
,
409 .devname
= "s3c-sdhci.1",
410 .parent
= &clk_hclk_psys
.clk
,
411 .enable
= s5pv210_clk_ip2_ctrl
,
415 .devname
= "s3c-sdhci.2",
416 .parent
= &clk_hclk_psys
.clk
,
417 .enable
= s5pv210_clk_ip2_ctrl
,
421 .devname
= "s3c-sdhci.3",
422 .parent
= &clk_hclk_psys
.clk
,
423 .enable
= s5pv210_clk_ip2_ctrl
,
427 .parent
= &clk_pclk_psys
.clk
,
428 .enable
= s5pv210_clk_ip3_ctrl
,
432 .parent
= &clk_pclk_psys
.clk
,
433 .enable
= s5pv210_clk_ip3_ctrl
,
437 .parent
= &clk_pclk_psys
.clk
,
438 .enable
= s5pv210_clk_ip3_ctrl
,
442 .devname
= "s3c2440-i2c.0",
443 .parent
= &clk_pclk_psys
.clk
,
444 .enable
= s5pv210_clk_ip3_ctrl
,
448 .devname
= "s3c2440-i2c.1",
449 .parent
= &clk_pclk_psys
.clk
,
450 .enable
= s5pv210_clk_ip3_ctrl
,
451 .ctrlbit
= (1 << 10),
454 .devname
= "s3c2440-i2c.2",
455 .parent
= &clk_pclk_psys
.clk
,
456 .enable
= s5pv210_clk_ip3_ctrl
,
460 .devname
= "s3c2440-hdmiphy-i2c",
461 .parent
= &clk_pclk_psys
.clk
,
462 .enable
= s5pv210_clk_ip3_ctrl
,
463 .ctrlbit
= (1 << 11),
466 .devname
= "s3c64xx-spi.0",
467 .parent
= &clk_pclk_psys
.clk
,
468 .enable
= s5pv210_clk_ip3_ctrl
,
472 .devname
= "s3c64xx-spi.1",
473 .parent
= &clk_pclk_psys
.clk
,
474 .enable
= s5pv210_clk_ip3_ctrl
,
478 .devname
= "s3c64xx-spi.2",
479 .parent
= &clk_pclk_psys
.clk
,
480 .enable
= s5pv210_clk_ip3_ctrl
,
484 .parent
= &clk_pclk_psys
.clk
,
485 .enable
= s5pv210_clk_ip3_ctrl
,
489 .parent
= &clk_pclk_psys
.clk
,
490 .enable
= s5pv210_clk_ip3_ctrl
,
494 .parent
= &clk_pclk_psys
.clk
,
495 .enable
= s5pv210_clk_ip3_ctrl
,
499 .devname
= "samsung-i2s.0",
501 .enable
= s5pv210_clk_ip3_ctrl
,
505 .devname
= "samsung-i2s.1",
507 .enable
= s5pv210_clk_ip3_ctrl
,
511 .devname
= "samsung-i2s.2",
513 .enable
= s5pv210_clk_ip3_ctrl
,
518 .enable
= s5pv210_clk_ip3_ctrl
,
523 static struct clk init_clocks
[] = {
526 .parent
= &clk_hclk_msys
.clk
,
528 .enable
= s5pv210_clk_ip0_ctrl
,
529 .ops
= &clk_hclk_imem_ops
,
532 .devname
= "s5pv210-uart.0",
533 .parent
= &clk_pclk_psys
.clk
,
534 .enable
= s5pv210_clk_ip3_ctrl
,
535 .ctrlbit
= (1 << 17),
538 .devname
= "s5pv210-uart.1",
539 .parent
= &clk_pclk_psys
.clk
,
540 .enable
= s5pv210_clk_ip3_ctrl
,
541 .ctrlbit
= (1 << 18),
544 .devname
= "s5pv210-uart.2",
545 .parent
= &clk_pclk_psys
.clk
,
546 .enable
= s5pv210_clk_ip3_ctrl
,
547 .ctrlbit
= (1 << 19),
550 .devname
= "s5pv210-uart.3",
551 .parent
= &clk_pclk_psys
.clk
,
552 .enable
= s5pv210_clk_ip3_ctrl
,
553 .ctrlbit
= (1 << 20),
556 .parent
= &clk_hclk_psys
.clk
,
557 .enable
= s5pv210_clk_ip1_ctrl
,
558 .ctrlbit
= (1 << 26),
562 static struct clk
*clkset_uart_list
[] = {
563 [6] = &clk_mout_mpll
.clk
,
564 [7] = &clk_mout_epll
.clk
,
567 static struct clksrc_sources clkset_uart
= {
568 .sources
= clkset_uart_list
,
569 .nr_sources
= ARRAY_SIZE(clkset_uart_list
),
572 static struct clk
*clkset_group1_list
[] = {
573 [0] = &clk_sclk_a2m
.clk
,
574 [1] = &clk_mout_mpll
.clk
,
575 [2] = &clk_mout_epll
.clk
,
576 [3] = &clk_sclk_vpll
.clk
,
579 static struct clksrc_sources clkset_group1
= {
580 .sources
= clkset_group1_list
,
581 .nr_sources
= ARRAY_SIZE(clkset_group1_list
),
584 static struct clk
*clkset_sclk_onenand_list
[] = {
585 [0] = &clk_hclk_psys
.clk
,
586 [1] = &clk_hclk_dsys
.clk
,
589 static struct clksrc_sources clkset_sclk_onenand
= {
590 .sources
= clkset_sclk_onenand_list
,
591 .nr_sources
= ARRAY_SIZE(clkset_sclk_onenand_list
),
594 static struct clk
*clkset_sclk_dac_list
[] = {
595 [0] = &clk_sclk_vpll
.clk
,
596 [1] = &clk_sclk_hdmiphy
,
599 static struct clksrc_sources clkset_sclk_dac
= {
600 .sources
= clkset_sclk_dac_list
,
601 .nr_sources
= ARRAY_SIZE(clkset_sclk_dac_list
),
604 static struct clksrc_clk clk_sclk_dac
= {
607 .enable
= s5pv210_clk_mask0_ctrl
,
610 .sources
= &clkset_sclk_dac
,
611 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 8, .size
= 1 },
614 static struct clksrc_clk clk_sclk_pixel
= {
616 .name
= "sclk_pixel",
617 .parent
= &clk_sclk_vpll
.clk
,
619 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 0, .size
= 4},
622 static struct clk
*clkset_sclk_hdmi_list
[] = {
623 [0] = &clk_sclk_pixel
.clk
,
624 [1] = &clk_sclk_hdmiphy
,
627 static struct clksrc_sources clkset_sclk_hdmi
= {
628 .sources
= clkset_sclk_hdmi_list
,
629 .nr_sources
= ARRAY_SIZE(clkset_sclk_hdmi_list
),
632 static struct clksrc_clk clk_sclk_hdmi
= {
635 .enable
= s5pv210_clk_mask0_ctrl
,
638 .sources
= &clkset_sclk_hdmi
,
639 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 0, .size
= 1 },
642 static struct clk
*clkset_sclk_mixer_list
[] = {
643 [0] = &clk_sclk_dac
.clk
,
644 [1] = &clk_sclk_hdmi
.clk
,
647 static struct clksrc_sources clkset_sclk_mixer
= {
648 .sources
= clkset_sclk_mixer_list
,
649 .nr_sources
= ARRAY_SIZE(clkset_sclk_mixer_list
),
652 static struct clksrc_clk clk_sclk_mixer
= {
654 .name
= "sclk_mixer",
655 .enable
= s5pv210_clk_mask0_ctrl
,
658 .sources
= &clkset_sclk_mixer
,
659 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 4, .size
= 1 },
662 static struct clksrc_clk
*sclk_tv
[] = {
669 static struct clk
*clkset_sclk_audio0_list
[] = {
670 [0] = &clk_ext_xtal_mux
,
671 [1] = &clk_pcmcdclk0
,
672 [2] = &clk_sclk_hdmi27m
,
673 [3] = &clk_sclk_usbphy0
,
674 [4] = &clk_sclk_usbphy1
,
675 [5] = &clk_sclk_hdmiphy
,
676 [6] = &clk_mout_mpll
.clk
,
677 [7] = &clk_mout_epll
.clk
,
678 [8] = &clk_sclk_vpll
.clk
,
681 static struct clksrc_sources clkset_sclk_audio0
= {
682 .sources
= clkset_sclk_audio0_list
,
683 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio0_list
),
686 static struct clksrc_clk clk_sclk_audio0
= {
688 .name
= "sclk_audio",
689 .devname
= "soc-audio.0",
690 .enable
= s5pv210_clk_mask0_ctrl
,
691 .ctrlbit
= (1 << 24),
693 .sources
= &clkset_sclk_audio0
,
694 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 0, .size
= 4 },
695 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 0, .size
= 4 },
698 static struct clk
*clkset_sclk_audio1_list
[] = {
699 [0] = &clk_ext_xtal_mux
,
700 [1] = &clk_pcmcdclk1
,
701 [2] = &clk_sclk_hdmi27m
,
702 [3] = &clk_sclk_usbphy0
,
703 [4] = &clk_sclk_usbphy1
,
704 [5] = &clk_sclk_hdmiphy
,
705 [6] = &clk_mout_mpll
.clk
,
706 [7] = &clk_mout_epll
.clk
,
707 [8] = &clk_sclk_vpll
.clk
,
710 static struct clksrc_sources clkset_sclk_audio1
= {
711 .sources
= clkset_sclk_audio1_list
,
712 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio1_list
),
715 static struct clksrc_clk clk_sclk_audio1
= {
717 .name
= "sclk_audio",
718 .devname
= "soc-audio.1",
719 .enable
= s5pv210_clk_mask0_ctrl
,
720 .ctrlbit
= (1 << 25),
722 .sources
= &clkset_sclk_audio1
,
723 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 4, .size
= 4 },
724 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 4, .size
= 4 },
727 static struct clk
*clkset_sclk_audio2_list
[] = {
728 [0] = &clk_ext_xtal_mux
,
729 [1] = &clk_pcmcdclk0
,
730 [2] = &clk_sclk_hdmi27m
,
731 [3] = &clk_sclk_usbphy0
,
732 [4] = &clk_sclk_usbphy1
,
733 [5] = &clk_sclk_hdmiphy
,
734 [6] = &clk_mout_mpll
.clk
,
735 [7] = &clk_mout_epll
.clk
,
736 [8] = &clk_sclk_vpll
.clk
,
739 static struct clksrc_sources clkset_sclk_audio2
= {
740 .sources
= clkset_sclk_audio2_list
,
741 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio2_list
),
744 static struct clksrc_clk clk_sclk_audio2
= {
746 .name
= "sclk_audio",
747 .devname
= "soc-audio.2",
748 .enable
= s5pv210_clk_mask0_ctrl
,
749 .ctrlbit
= (1 << 26),
751 .sources
= &clkset_sclk_audio2
,
752 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 8, .size
= 4 },
753 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 8, .size
= 4 },
756 static struct clk
*clkset_sclk_spdif_list
[] = {
757 [0] = &clk_sclk_audio0
.clk
,
758 [1] = &clk_sclk_audio1
.clk
,
759 [2] = &clk_sclk_audio2
.clk
,
762 static struct clksrc_sources clkset_sclk_spdif
= {
763 .sources
= clkset_sclk_spdif_list
,
764 .nr_sources
= ARRAY_SIZE(clkset_sclk_spdif_list
),
767 static struct clksrc_clk clk_sclk_spdif
= {
769 .name
= "sclk_spdif",
770 .enable
= s5pv210_clk_mask0_ctrl
,
771 .ctrlbit
= (1 << 27),
772 .ops
= &s5p_sclk_spdif_ops
,
774 .sources
= &clkset_sclk_spdif
,
775 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 12, .size
= 2 },
778 static struct clk
*clkset_group2_list
[] = {
779 [0] = &clk_ext_xtal_mux
,
781 [2] = &clk_sclk_hdmi27m
,
782 [3] = &clk_sclk_usbphy0
,
783 [4] = &clk_sclk_usbphy1
,
784 [5] = &clk_sclk_hdmiphy
,
785 [6] = &clk_mout_mpll
.clk
,
786 [7] = &clk_mout_epll
.clk
,
787 [8] = &clk_sclk_vpll
.clk
,
790 static struct clksrc_sources clkset_group2
= {
791 .sources
= clkset_group2_list
,
792 .nr_sources
= ARRAY_SIZE(clkset_group2_list
),
795 static struct clksrc_clk clksrcs
[] = {
800 .sources
= &clkset_group1
,
801 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 24, .size
= 2 },
802 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 28, .size
= 4 },
805 .name
= "sclk_onenand",
807 .sources
= &clkset_sclk_onenand
,
808 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 28, .size
= 1 },
809 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 12, .size
= 3 },
813 .devname
= "s5pv210-uart.0",
814 .enable
= s5pv210_clk_mask0_ctrl
,
815 .ctrlbit
= (1 << 12),
817 .sources
= &clkset_uart
,
818 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 16, .size
= 4 },
819 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 16, .size
= 4 },
823 .devname
= "s5pv210-uart.1",
824 .enable
= s5pv210_clk_mask0_ctrl
,
825 .ctrlbit
= (1 << 13),
827 .sources
= &clkset_uart
,
828 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 20, .size
= 4 },
829 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 20, .size
= 4 },
833 .devname
= "s5pv210-uart.2",
834 .enable
= s5pv210_clk_mask0_ctrl
,
835 .ctrlbit
= (1 << 14),
837 .sources
= &clkset_uart
,
838 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 24, .size
= 4 },
839 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 24, .size
= 4 },
843 .devname
= "s5pv210-uart.3",
844 .enable
= s5pv210_clk_mask0_ctrl
,
845 .ctrlbit
= (1 << 15),
847 .sources
= &clkset_uart
,
848 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 28, .size
= 4 },
849 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 28, .size
= 4 },
853 .devname
= "s5pv210-fimc.0",
854 .enable
= s5pv210_clk_mask1_ctrl
,
857 .sources
= &clkset_group2
,
858 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 12, .size
= 4 },
859 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 12, .size
= 4 },
863 .devname
= "s5pv210-fimc.1",
864 .enable
= s5pv210_clk_mask1_ctrl
,
867 .sources
= &clkset_group2
,
868 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 16, .size
= 4 },
869 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 16, .size
= 4 },
873 .devname
= "s5pv210-fimc.2",
874 .enable
= s5pv210_clk_mask1_ctrl
,
877 .sources
= &clkset_group2
,
878 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 20, .size
= 4 },
879 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 20, .size
= 4 },
883 .enable
= s5pv210_clk_mask0_ctrl
,
886 .sources
= &clkset_group2
,
887 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 12, .size
= 4 },
888 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 12, .size
= 4 },
892 .enable
= s5pv210_clk_mask0_ctrl
,
895 .sources
= &clkset_group2
,
896 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 16, .size
= 4 },
897 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 16, .size
= 4 },
901 .enable
= s5pv210_clk_mask0_ctrl
,
904 .sources
= &clkset_group2
,
905 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 20, .size
= 4 },
906 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 20, .size
= 4 },
910 .devname
= "s3c-sdhci.0",
911 .enable
= s5pv210_clk_mask0_ctrl
,
914 .sources
= &clkset_group2
,
915 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 0, .size
= 4 },
916 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 0, .size
= 4 },
920 .devname
= "s3c-sdhci.1",
921 .enable
= s5pv210_clk_mask0_ctrl
,
924 .sources
= &clkset_group2
,
925 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 4, .size
= 4 },
926 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 4, .size
= 4 },
930 .devname
= "s3c-sdhci.2",
931 .enable
= s5pv210_clk_mask0_ctrl
,
932 .ctrlbit
= (1 << 10),
934 .sources
= &clkset_group2
,
935 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 8, .size
= 4 },
936 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 8, .size
= 4 },
940 .devname
= "s3c-sdhci.3",
941 .enable
= s5pv210_clk_mask0_ctrl
,
942 .ctrlbit
= (1 << 11),
944 .sources
= &clkset_group2
,
945 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 12, .size
= 4 },
946 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 12, .size
= 4 },
950 .devname
= "s5p-mfc",
951 .enable
= s5pv210_clk_ip0_ctrl
,
952 .ctrlbit
= (1 << 16),
954 .sources
= &clkset_group1
,
955 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 4, .size
= 2 },
956 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 4, .size
= 4 },
960 .enable
= s5pv210_clk_ip0_ctrl
,
961 .ctrlbit
= (1 << 12),
963 .sources
= &clkset_group1
,
964 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 8, .size
= 2 },
965 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 8, .size
= 4 },
969 .enable
= s5pv210_clk_ip0_ctrl
,
972 .sources
= &clkset_group1
,
973 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 0, .size
= 2 },
974 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 0, .size
= 4 },
978 .enable
= s5pv210_clk_mask0_ctrl
,
981 .sources
= &clkset_group2
,
982 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 24, .size
= 4 },
983 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 28, .size
= 4 },
987 .devname
= "s3c64xx-spi.0",
988 .enable
= s5pv210_clk_mask0_ctrl
,
989 .ctrlbit
= (1 << 16),
991 .sources
= &clkset_group2
,
992 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 0, .size
= 4 },
993 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 0, .size
= 4 },
997 .devname
= "s3c64xx-spi.1",
998 .enable
= s5pv210_clk_mask0_ctrl
,
999 .ctrlbit
= (1 << 17),
1001 .sources
= &clkset_group2
,
1002 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 4, .size
= 4 },
1003 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 4, .size
= 4 },
1007 .enable
= s5pv210_clk_mask0_ctrl
,
1008 .ctrlbit
= (1 << 29),
1010 .sources
= &clkset_group2
,
1011 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 20, .size
= 4 },
1012 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 24, .size
= 4 },
1016 .enable
= s5pv210_clk_mask0_ctrl
,
1017 .ctrlbit
= (1 << 19),
1019 .sources
= &clkset_group2
,
1020 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 12, .size
= 4 },
1021 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 12, .size
= 4 },
1025 /* Clock initialisation code */
1026 static struct clksrc_clk
*sysclks
[] = {
1048 static u32 epll_div
[][6] = {
1049 { 48000000, 0, 48, 3, 3, 0 },
1050 { 96000000, 0, 48, 3, 2, 0 },
1051 { 144000000, 1, 72, 3, 2, 0 },
1052 { 192000000, 0, 48, 3, 1, 0 },
1053 { 288000000, 1, 72, 3, 1, 0 },
1054 { 32750000, 1, 65, 3, 4, 35127 },
1055 { 32768000, 1, 65, 3, 4, 35127 },
1056 { 45158400, 0, 45, 3, 3, 10355 },
1057 { 45000000, 0, 45, 3, 3, 10355 },
1058 { 45158000, 0, 45, 3, 3, 10355 },
1059 { 49125000, 0, 49, 3, 3, 9961 },
1060 { 49152000, 0, 49, 3, 3, 9961 },
1061 { 67737600, 1, 67, 3, 3, 48366 },
1062 { 67738000, 1, 67, 3, 3, 48366 },
1063 { 73800000, 1, 73, 3, 3, 47710 },
1064 { 73728000, 1, 73, 3, 3, 47710 },
1065 { 36000000, 1, 32, 3, 4, 0 },
1066 { 60000000, 1, 60, 3, 3, 0 },
1067 { 72000000, 1, 72, 3, 3, 0 },
1068 { 80000000, 1, 80, 3, 3, 0 },
1069 { 84000000, 0, 42, 3, 2, 0 },
1070 { 50000000, 0, 50, 3, 3, 0 },
1073 static int s5pv210_epll_set_rate(struct clk
*clk
, unsigned long rate
)
1075 unsigned int epll_con
, epll_con_k
;
1078 /* Return if nothing changed */
1079 if (clk
->rate
== rate
)
1082 epll_con
= __raw_readl(S5P_EPLL_CON
);
1083 epll_con_k
= __raw_readl(S5P_EPLL_CON1
);
1085 epll_con_k
&= ~PLL46XX_KDIV_MASK
;
1086 epll_con
&= ~(1 << 27 |
1087 PLL46XX_MDIV_MASK
<< PLL46XX_MDIV_SHIFT
|
1088 PLL46XX_PDIV_MASK
<< PLL46XX_PDIV_SHIFT
|
1089 PLL46XX_SDIV_MASK
<< PLL46XX_SDIV_SHIFT
);
1091 for (i
= 0; i
< ARRAY_SIZE(epll_div
); i
++) {
1092 if (epll_div
[i
][0] == rate
) {
1093 epll_con_k
|= epll_div
[i
][5] << 0;
1094 epll_con
|= (epll_div
[i
][1] << 27 |
1095 epll_div
[i
][2] << PLL46XX_MDIV_SHIFT
|
1096 epll_div
[i
][3] << PLL46XX_PDIV_SHIFT
|
1097 epll_div
[i
][4] << PLL46XX_SDIV_SHIFT
);
1102 if (i
== ARRAY_SIZE(epll_div
)) {
1103 printk(KERN_ERR
"%s: Invalid Clock EPLL Frequency\n",
1108 __raw_writel(epll_con
, S5P_EPLL_CON
);
1109 __raw_writel(epll_con_k
, S5P_EPLL_CON1
);
1111 printk(KERN_WARNING
"EPLL Rate changes from %lu to %lu\n",
1119 static struct clk_ops s5pv210_epll_ops
= {
1120 .set_rate
= s5pv210_epll_set_rate
,
1121 .get_rate
= s5p_epll_get_rate
,
1124 static u32 vpll_div
[][5] = {
1125 { 54000000, 3, 53, 3, 0 },
1126 { 108000000, 3, 53, 2, 0 },
1129 static unsigned long s5pv210_vpll_get_rate(struct clk
*clk
)
1134 static int s5pv210_vpll_set_rate(struct clk
*clk
, unsigned long rate
)
1136 unsigned int vpll_con
;
1139 /* Return if nothing changed */
1140 if (clk
->rate
== rate
)
1143 vpll_con
= __raw_readl(S5P_VPLL_CON
);
1144 vpll_con
&= ~(0x1 << 27 | \
1145 PLL90XX_MDIV_MASK
<< PLL90XX_MDIV_SHIFT
| \
1146 PLL90XX_PDIV_MASK
<< PLL90XX_PDIV_SHIFT
| \
1147 PLL90XX_SDIV_MASK
<< PLL90XX_SDIV_SHIFT
);
1149 for (i
= 0; i
< ARRAY_SIZE(vpll_div
); i
++) {
1150 if (vpll_div
[i
][0] == rate
) {
1151 vpll_con
|= vpll_div
[i
][1] << PLL90XX_PDIV_SHIFT
;
1152 vpll_con
|= vpll_div
[i
][2] << PLL90XX_MDIV_SHIFT
;
1153 vpll_con
|= vpll_div
[i
][3] << PLL90XX_SDIV_SHIFT
;
1154 vpll_con
|= vpll_div
[i
][4] << 27;
1159 if (i
== ARRAY_SIZE(vpll_div
)) {
1160 printk(KERN_ERR
"%s: Invalid Clock VPLL Frequency\n",
1165 __raw_writel(vpll_con
, S5P_VPLL_CON
);
1167 /* Wait for VPLL lock */
1168 while (!(__raw_readl(S5P_VPLL_CON
) & (1 << PLL90XX_LOCKED_SHIFT
)))
1174 static struct clk_ops s5pv210_vpll_ops
= {
1175 .get_rate
= s5pv210_vpll_get_rate
,
1176 .set_rate
= s5pv210_vpll_set_rate
,
1179 void __init_or_cpufreq
s5pv210_setup_clocks(void)
1181 struct clk
*xtal_clk
;
1182 unsigned long vpllsrc
;
1183 unsigned long armclk
;
1184 unsigned long hclk_msys
;
1185 unsigned long hclk_dsys
;
1186 unsigned long hclk_psys
;
1187 unsigned long pclk_msys
;
1188 unsigned long pclk_dsys
;
1189 unsigned long pclk_psys
;
1195 u32 clkdiv0
, clkdiv1
;
1197 /* Set functions for clk_fout_epll */
1198 clk_fout_epll
.enable
= s5p_epll_enable
;
1199 clk_fout_epll
.ops
= &s5pv210_epll_ops
;
1201 printk(KERN_DEBUG
"%s: registering clocks\n", __func__
);
1203 clkdiv0
= __raw_readl(S5P_CLK_DIV0
);
1204 clkdiv1
= __raw_readl(S5P_CLK_DIV1
);
1206 printk(KERN_DEBUG
"%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
1207 __func__
, clkdiv0
, clkdiv1
);
1209 xtal_clk
= clk_get(NULL
, "xtal");
1210 BUG_ON(IS_ERR(xtal_clk
));
1212 xtal
= clk_get_rate(xtal_clk
);
1215 printk(KERN_DEBUG
"%s: xtal is %ld\n", __func__
, xtal
);
1217 apll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_APLL_CON
), pll_4508
);
1218 mpll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_MPLL_CON
), pll_4502
);
1219 epll
= s5p_get_pll46xx(xtal
, __raw_readl(S5P_EPLL_CON
),
1220 __raw_readl(S5P_EPLL_CON1
), pll_4600
);
1221 vpllsrc
= clk_get_rate(&clk_vpllsrc
.clk
);
1222 vpll
= s5p_get_pll45xx(vpllsrc
, __raw_readl(S5P_VPLL_CON
), pll_4502
);
1224 clk_fout_apll
.ops
= &clk_fout_apll_ops
;
1225 clk_fout_mpll
.rate
= mpll
;
1226 clk_fout_epll
.rate
= epll
;
1227 clk_fout_vpll
.ops
= &s5pv210_vpll_ops
;
1228 clk_fout_vpll
.rate
= vpll
;
1230 printk(KERN_INFO
"S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
1231 apll
, mpll
, epll
, vpll
);
1233 armclk
= clk_get_rate(&clk_armclk
.clk
);
1234 hclk_msys
= clk_get_rate(&clk_hclk_msys
.clk
);
1235 hclk_dsys
= clk_get_rate(&clk_hclk_dsys
.clk
);
1236 hclk_psys
= clk_get_rate(&clk_hclk_psys
.clk
);
1237 pclk_msys
= clk_get_rate(&clk_pclk_msys
.clk
);
1238 pclk_dsys
= clk_get_rate(&clk_pclk_dsys
.clk
);
1239 pclk_psys
= clk_get_rate(&clk_pclk_psys
.clk
);
1241 printk(KERN_INFO
"S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
1242 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
1243 armclk
, hclk_msys
, hclk_dsys
, hclk_psys
,
1244 pclk_msys
, pclk_dsys
, pclk_psys
);
1246 clk_f
.rate
= armclk
;
1247 clk_h
.rate
= hclk_psys
;
1248 clk_p
.rate
= pclk_psys
;
1250 for (ptr
= 0; ptr
< ARRAY_SIZE(clksrcs
); ptr
++)
1251 s3c_set_clksrc(&clksrcs
[ptr
], true);
1254 static struct clk
*clks
[] __initdata
= {
1264 void __init
s5pv210_register_clocks(void)
1268 s3c24xx_register_clocks(clks
, ARRAY_SIZE(clks
));
1270 for (ptr
= 0; ptr
< ARRAY_SIZE(sysclks
); ptr
++)
1271 s3c_register_clksrc(sysclks
[ptr
], 1);
1273 for (ptr
= 0; ptr
< ARRAY_SIZE(sclk_tv
); ptr
++)
1274 s3c_register_clksrc(sclk_tv
[ptr
], 1);
1276 s3c_register_clksrc(clksrcs
, ARRAY_SIZE(clksrcs
));
1277 s3c_register_clocks(init_clocks
, ARRAY_SIZE(init_clocks
));
1279 s3c_register_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1280 s3c_disable_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1282 s3c24xx_register_clock(&dummy_apb_pclk
);