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 exynos4_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 .devname
= "s5p-mfc",
345 .parent
= &clk_pclk_psys
.clk
,
346 .enable
= s5pv210_clk_ip0_ctrl
,
347 .ctrlbit
= (1 << 16),
350 .devname
= "s5p-sdo",
351 .parent
= &clk_hclk_dsys
.clk
,
352 .enable
= s5pv210_clk_ip1_ctrl
,
353 .ctrlbit
= (1 << 10),
356 .devname
= "s5p-mixer",
357 .parent
= &clk_hclk_dsys
.clk
,
358 .enable
= s5pv210_clk_ip1_ctrl
,
362 .devname
= "s5p-mixer",
363 .parent
= &clk_hclk_dsys
.clk
,
364 .enable
= s5pv210_clk_ip1_ctrl
,
368 .devname
= "s5pv210-hdmi",
369 .parent
= &clk_hclk_dsys
.clk
,
370 .enable
= s5pv210_clk_ip1_ctrl
,
371 .ctrlbit
= (1 << 11),
374 .devname
= "s5pv210-hdmi",
375 .enable
= exynos4_clk_hdmiphy_ctrl
,
379 .devname
= "s5p-sdo",
380 .enable
= exynos4_clk_dac_ctrl
,
384 .parent
= &clk_hclk_psys
.clk
,
385 .enable
= s5pv210_clk_ip1_ctrl
,
389 .parent
= &clk_hclk_psys
.clk
,
390 .enable
= s5pv210_clk_ip1_ctrl
,
394 .parent
= &clk_hclk_dsys
.clk
,
395 .enable
= s5pv210_clk_ip1_ctrl
,
399 .parent
= &clk_hclk_psys
.clk
,
400 .enable
= s5pv210_clk_ip1_ctrl
,
404 .devname
= "s3c-sdhci.0",
405 .parent
= &clk_hclk_psys
.clk
,
406 .enable
= s5pv210_clk_ip2_ctrl
,
410 .devname
= "s3c-sdhci.1",
411 .parent
= &clk_hclk_psys
.clk
,
412 .enable
= s5pv210_clk_ip2_ctrl
,
416 .devname
= "s3c-sdhci.2",
417 .parent
= &clk_hclk_psys
.clk
,
418 .enable
= s5pv210_clk_ip2_ctrl
,
422 .devname
= "s3c-sdhci.3",
423 .parent
= &clk_hclk_psys
.clk
,
424 .enable
= s5pv210_clk_ip2_ctrl
,
428 .parent
= &clk_pclk_psys
.clk
,
429 .enable
= s5pv210_clk_ip3_ctrl
,
433 .parent
= &clk_pclk_psys
.clk
,
434 .enable
= s5pv210_clk_ip3_ctrl
,
438 .parent
= &clk_pclk_psys
.clk
,
439 .enable
= s5pv210_clk_ip3_ctrl
,
443 .devname
= "s3c2440-i2c.0",
444 .parent
= &clk_pclk_psys
.clk
,
445 .enable
= s5pv210_clk_ip3_ctrl
,
449 .devname
= "s3c2440-i2c.1",
450 .parent
= &clk_pclk_psys
.clk
,
451 .enable
= s5pv210_clk_ip3_ctrl
,
452 .ctrlbit
= (1 << 10),
455 .devname
= "s3c2440-i2c.2",
456 .parent
= &clk_pclk_psys
.clk
,
457 .enable
= s5pv210_clk_ip3_ctrl
,
461 .devname
= "s3c2440-hdmiphy-i2c",
462 .parent
= &clk_pclk_psys
.clk
,
463 .enable
= s5pv210_clk_ip3_ctrl
,
464 .ctrlbit
= (1 << 11),
467 .devname
= "s3c64xx-spi.0",
468 .parent
= &clk_pclk_psys
.clk
,
469 .enable
= s5pv210_clk_ip3_ctrl
,
473 .devname
= "s3c64xx-spi.1",
474 .parent
= &clk_pclk_psys
.clk
,
475 .enable
= s5pv210_clk_ip3_ctrl
,
479 .devname
= "s3c64xx-spi.2",
480 .parent
= &clk_pclk_psys
.clk
,
481 .enable
= s5pv210_clk_ip3_ctrl
,
485 .parent
= &clk_pclk_psys
.clk
,
486 .enable
= s5pv210_clk_ip3_ctrl
,
490 .parent
= &clk_pclk_psys
.clk
,
491 .enable
= s5pv210_clk_ip3_ctrl
,
495 .parent
= &clk_pclk_psys
.clk
,
496 .enable
= s5pv210_clk_ip3_ctrl
,
500 .devname
= "samsung-i2s.0",
502 .enable
= s5pv210_clk_ip3_ctrl
,
506 .devname
= "samsung-i2s.1",
508 .enable
= s5pv210_clk_ip3_ctrl
,
512 .devname
= "samsung-i2s.2",
514 .enable
= s5pv210_clk_ip3_ctrl
,
519 .enable
= s5pv210_clk_ip3_ctrl
,
524 static struct clk init_clocks
[] = {
527 .parent
= &clk_hclk_msys
.clk
,
529 .enable
= s5pv210_clk_ip0_ctrl
,
530 .ops
= &clk_hclk_imem_ops
,
533 .devname
= "s5pv210-uart.0",
534 .parent
= &clk_pclk_psys
.clk
,
535 .enable
= s5pv210_clk_ip3_ctrl
,
536 .ctrlbit
= (1 << 17),
539 .devname
= "s5pv210-uart.1",
540 .parent
= &clk_pclk_psys
.clk
,
541 .enable
= s5pv210_clk_ip3_ctrl
,
542 .ctrlbit
= (1 << 18),
545 .devname
= "s5pv210-uart.2",
546 .parent
= &clk_pclk_psys
.clk
,
547 .enable
= s5pv210_clk_ip3_ctrl
,
548 .ctrlbit
= (1 << 19),
551 .devname
= "s5pv210-uart.3",
552 .parent
= &clk_pclk_psys
.clk
,
553 .enable
= s5pv210_clk_ip3_ctrl
,
554 .ctrlbit
= (1 << 20),
557 .parent
= &clk_hclk_psys
.clk
,
558 .enable
= s5pv210_clk_ip1_ctrl
,
559 .ctrlbit
= (1 << 26),
563 static struct clk
*clkset_uart_list
[] = {
564 [6] = &clk_mout_mpll
.clk
,
565 [7] = &clk_mout_epll
.clk
,
568 static struct clksrc_sources clkset_uart
= {
569 .sources
= clkset_uart_list
,
570 .nr_sources
= ARRAY_SIZE(clkset_uart_list
),
573 static struct clk
*clkset_group1_list
[] = {
574 [0] = &clk_sclk_a2m
.clk
,
575 [1] = &clk_mout_mpll
.clk
,
576 [2] = &clk_mout_epll
.clk
,
577 [3] = &clk_sclk_vpll
.clk
,
580 static struct clksrc_sources clkset_group1
= {
581 .sources
= clkset_group1_list
,
582 .nr_sources
= ARRAY_SIZE(clkset_group1_list
),
585 static struct clk
*clkset_sclk_onenand_list
[] = {
586 [0] = &clk_hclk_psys
.clk
,
587 [1] = &clk_hclk_dsys
.clk
,
590 static struct clksrc_sources clkset_sclk_onenand
= {
591 .sources
= clkset_sclk_onenand_list
,
592 .nr_sources
= ARRAY_SIZE(clkset_sclk_onenand_list
),
595 static struct clk
*clkset_sclk_dac_list
[] = {
596 [0] = &clk_sclk_vpll
.clk
,
597 [1] = &clk_sclk_hdmiphy
,
600 static struct clksrc_sources clkset_sclk_dac
= {
601 .sources
= clkset_sclk_dac_list
,
602 .nr_sources
= ARRAY_SIZE(clkset_sclk_dac_list
),
605 static struct clksrc_clk clk_sclk_dac
= {
608 .enable
= s5pv210_clk_mask0_ctrl
,
611 .sources
= &clkset_sclk_dac
,
612 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 8, .size
= 1 },
615 static struct clksrc_clk clk_sclk_pixel
= {
617 .name
= "sclk_pixel",
618 .parent
= &clk_sclk_vpll
.clk
,
620 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 0, .size
= 4},
623 static struct clk
*clkset_sclk_hdmi_list
[] = {
624 [0] = &clk_sclk_pixel
.clk
,
625 [1] = &clk_sclk_hdmiphy
,
628 static struct clksrc_sources clkset_sclk_hdmi
= {
629 .sources
= clkset_sclk_hdmi_list
,
630 .nr_sources
= ARRAY_SIZE(clkset_sclk_hdmi_list
),
633 static struct clksrc_clk clk_sclk_hdmi
= {
636 .enable
= s5pv210_clk_mask0_ctrl
,
639 .sources
= &clkset_sclk_hdmi
,
640 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 0, .size
= 1 },
643 static struct clk
*clkset_sclk_mixer_list
[] = {
644 [0] = &clk_sclk_dac
.clk
,
645 [1] = &clk_sclk_hdmi
.clk
,
648 static struct clksrc_sources clkset_sclk_mixer
= {
649 .sources
= clkset_sclk_mixer_list
,
650 .nr_sources
= ARRAY_SIZE(clkset_sclk_mixer_list
),
653 static struct clksrc_clk clk_sclk_mixer
= {
655 .name
= "sclk_mixer",
656 .enable
= s5pv210_clk_mask0_ctrl
,
659 .sources
= &clkset_sclk_mixer
,
660 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 4, .size
= 1 },
663 static struct clksrc_clk
*sclk_tv
[] = {
670 static struct clk
*clkset_sclk_audio0_list
[] = {
671 [0] = &clk_ext_xtal_mux
,
672 [1] = &clk_pcmcdclk0
,
673 [2] = &clk_sclk_hdmi27m
,
674 [3] = &clk_sclk_usbphy0
,
675 [4] = &clk_sclk_usbphy1
,
676 [5] = &clk_sclk_hdmiphy
,
677 [6] = &clk_mout_mpll
.clk
,
678 [7] = &clk_mout_epll
.clk
,
679 [8] = &clk_sclk_vpll
.clk
,
682 static struct clksrc_sources clkset_sclk_audio0
= {
683 .sources
= clkset_sclk_audio0_list
,
684 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio0_list
),
687 static struct clksrc_clk clk_sclk_audio0
= {
689 .name
= "sclk_audio",
690 .devname
= "soc-audio.0",
691 .enable
= s5pv210_clk_mask0_ctrl
,
692 .ctrlbit
= (1 << 24),
694 .sources
= &clkset_sclk_audio0
,
695 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 0, .size
= 4 },
696 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 0, .size
= 4 },
699 static struct clk
*clkset_sclk_audio1_list
[] = {
700 [0] = &clk_ext_xtal_mux
,
701 [1] = &clk_pcmcdclk1
,
702 [2] = &clk_sclk_hdmi27m
,
703 [3] = &clk_sclk_usbphy0
,
704 [4] = &clk_sclk_usbphy1
,
705 [5] = &clk_sclk_hdmiphy
,
706 [6] = &clk_mout_mpll
.clk
,
707 [7] = &clk_mout_epll
.clk
,
708 [8] = &clk_sclk_vpll
.clk
,
711 static struct clksrc_sources clkset_sclk_audio1
= {
712 .sources
= clkset_sclk_audio1_list
,
713 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio1_list
),
716 static struct clksrc_clk clk_sclk_audio1
= {
718 .name
= "sclk_audio",
719 .devname
= "soc-audio.1",
720 .enable
= s5pv210_clk_mask0_ctrl
,
721 .ctrlbit
= (1 << 25),
723 .sources
= &clkset_sclk_audio1
,
724 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 4, .size
= 4 },
725 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 4, .size
= 4 },
728 static struct clk
*clkset_sclk_audio2_list
[] = {
729 [0] = &clk_ext_xtal_mux
,
730 [1] = &clk_pcmcdclk0
,
731 [2] = &clk_sclk_hdmi27m
,
732 [3] = &clk_sclk_usbphy0
,
733 [4] = &clk_sclk_usbphy1
,
734 [5] = &clk_sclk_hdmiphy
,
735 [6] = &clk_mout_mpll
.clk
,
736 [7] = &clk_mout_epll
.clk
,
737 [8] = &clk_sclk_vpll
.clk
,
740 static struct clksrc_sources clkset_sclk_audio2
= {
741 .sources
= clkset_sclk_audio2_list
,
742 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio2_list
),
745 static struct clksrc_clk clk_sclk_audio2
= {
747 .name
= "sclk_audio",
748 .devname
= "soc-audio.2",
749 .enable
= s5pv210_clk_mask0_ctrl
,
750 .ctrlbit
= (1 << 26),
752 .sources
= &clkset_sclk_audio2
,
753 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 8, .size
= 4 },
754 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 8, .size
= 4 },
757 static struct clk
*clkset_sclk_spdif_list
[] = {
758 [0] = &clk_sclk_audio0
.clk
,
759 [1] = &clk_sclk_audio1
.clk
,
760 [2] = &clk_sclk_audio2
.clk
,
763 static struct clksrc_sources clkset_sclk_spdif
= {
764 .sources
= clkset_sclk_spdif_list
,
765 .nr_sources
= ARRAY_SIZE(clkset_sclk_spdif_list
),
768 static struct clksrc_clk clk_sclk_spdif
= {
770 .name
= "sclk_spdif",
771 .enable
= s5pv210_clk_mask0_ctrl
,
772 .ctrlbit
= (1 << 27),
773 .ops
= &s5p_sclk_spdif_ops
,
775 .sources
= &clkset_sclk_spdif
,
776 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 12, .size
= 2 },
779 static struct clk
*clkset_group2_list
[] = {
780 [0] = &clk_ext_xtal_mux
,
782 [2] = &clk_sclk_hdmi27m
,
783 [3] = &clk_sclk_usbphy0
,
784 [4] = &clk_sclk_usbphy1
,
785 [5] = &clk_sclk_hdmiphy
,
786 [6] = &clk_mout_mpll
.clk
,
787 [7] = &clk_mout_epll
.clk
,
788 [8] = &clk_sclk_vpll
.clk
,
791 static struct clksrc_sources clkset_group2
= {
792 .sources
= clkset_group2_list
,
793 .nr_sources
= ARRAY_SIZE(clkset_group2_list
),
796 static struct clksrc_clk clksrcs
[] = {
801 .sources
= &clkset_group1
,
802 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 24, .size
= 2 },
803 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 28, .size
= 4 },
806 .name
= "sclk_onenand",
808 .sources
= &clkset_sclk_onenand
,
809 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 28, .size
= 1 },
810 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 12, .size
= 3 },
814 .devname
= "s5pv210-uart.0",
815 .enable
= s5pv210_clk_mask0_ctrl
,
816 .ctrlbit
= (1 << 12),
818 .sources
= &clkset_uart
,
819 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 16, .size
= 4 },
820 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 16, .size
= 4 },
824 .devname
= "s5pv210-uart.1",
825 .enable
= s5pv210_clk_mask0_ctrl
,
826 .ctrlbit
= (1 << 13),
828 .sources
= &clkset_uart
,
829 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 20, .size
= 4 },
830 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 20, .size
= 4 },
834 .devname
= "s5pv210-uart.2",
835 .enable
= s5pv210_clk_mask0_ctrl
,
836 .ctrlbit
= (1 << 14),
838 .sources
= &clkset_uart
,
839 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 24, .size
= 4 },
840 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 24, .size
= 4 },
844 .devname
= "s5pv210-uart.3",
845 .enable
= s5pv210_clk_mask0_ctrl
,
846 .ctrlbit
= (1 << 15),
848 .sources
= &clkset_uart
,
849 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 28, .size
= 4 },
850 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 28, .size
= 4 },
854 .devname
= "s5pv210-fimc.0",
855 .enable
= s5pv210_clk_mask1_ctrl
,
858 .sources
= &clkset_group2
,
859 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 12, .size
= 4 },
860 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 12, .size
= 4 },
864 .devname
= "s5pv210-fimc.1",
865 .enable
= s5pv210_clk_mask1_ctrl
,
868 .sources
= &clkset_group2
,
869 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 16, .size
= 4 },
870 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 16, .size
= 4 },
874 .devname
= "s5pv210-fimc.2",
875 .enable
= s5pv210_clk_mask1_ctrl
,
878 .sources
= &clkset_group2
,
879 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 20, .size
= 4 },
880 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 20, .size
= 4 },
884 .enable
= s5pv210_clk_mask0_ctrl
,
887 .sources
= &clkset_group2
,
888 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 12, .size
= 4 },
889 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 12, .size
= 4 },
893 .enable
= s5pv210_clk_mask0_ctrl
,
896 .sources
= &clkset_group2
,
897 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 16, .size
= 4 },
898 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 16, .size
= 4 },
902 .enable
= s5pv210_clk_mask0_ctrl
,
905 .sources
= &clkset_group2
,
906 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 20, .size
= 4 },
907 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 20, .size
= 4 },
911 .devname
= "s3c-sdhci.0",
912 .enable
= s5pv210_clk_mask0_ctrl
,
915 .sources
= &clkset_group2
,
916 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 0, .size
= 4 },
917 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 0, .size
= 4 },
921 .devname
= "s3c-sdhci.1",
922 .enable
= s5pv210_clk_mask0_ctrl
,
925 .sources
= &clkset_group2
,
926 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 4, .size
= 4 },
927 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 4, .size
= 4 },
931 .devname
= "s3c-sdhci.2",
932 .enable
= s5pv210_clk_mask0_ctrl
,
933 .ctrlbit
= (1 << 10),
935 .sources
= &clkset_group2
,
936 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 8, .size
= 4 },
937 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 8, .size
= 4 },
941 .devname
= "s3c-sdhci.3",
942 .enable
= s5pv210_clk_mask0_ctrl
,
943 .ctrlbit
= (1 << 11),
945 .sources
= &clkset_group2
,
946 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 12, .size
= 4 },
947 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 12, .size
= 4 },
951 .devname
= "s5p-mfc",
952 .enable
= s5pv210_clk_ip0_ctrl
,
953 .ctrlbit
= (1 << 16),
955 .sources
= &clkset_group1
,
956 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 4, .size
= 2 },
957 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 4, .size
= 4 },
961 .enable
= s5pv210_clk_ip0_ctrl
,
962 .ctrlbit
= (1 << 12),
964 .sources
= &clkset_group1
,
965 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 8, .size
= 2 },
966 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 8, .size
= 4 },
970 .enable
= s5pv210_clk_ip0_ctrl
,
973 .sources
= &clkset_group1
,
974 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 0, .size
= 2 },
975 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 0, .size
= 4 },
979 .enable
= s5pv210_clk_mask0_ctrl
,
982 .sources
= &clkset_group2
,
983 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 24, .size
= 4 },
984 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 28, .size
= 4 },
988 .devname
= "s3c64xx-spi.0",
989 .enable
= s5pv210_clk_mask0_ctrl
,
990 .ctrlbit
= (1 << 16),
992 .sources
= &clkset_group2
,
993 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 0, .size
= 4 },
994 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 0, .size
= 4 },
998 .devname
= "s3c64xx-spi.1",
999 .enable
= s5pv210_clk_mask0_ctrl
,
1000 .ctrlbit
= (1 << 17),
1002 .sources
= &clkset_group2
,
1003 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 4, .size
= 4 },
1004 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 4, .size
= 4 },
1008 .enable
= s5pv210_clk_mask0_ctrl
,
1009 .ctrlbit
= (1 << 29),
1011 .sources
= &clkset_group2
,
1012 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 20, .size
= 4 },
1013 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 24, .size
= 4 },
1017 .enable
= s5pv210_clk_mask0_ctrl
,
1018 .ctrlbit
= (1 << 19),
1020 .sources
= &clkset_group2
,
1021 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 12, .size
= 4 },
1022 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 12, .size
= 4 },
1026 /* Clock initialisation code */
1027 static struct clksrc_clk
*sysclks
[] = {
1049 static u32 epll_div
[][6] = {
1050 { 48000000, 0, 48, 3, 3, 0 },
1051 { 96000000, 0, 48, 3, 2, 0 },
1052 { 144000000, 1, 72, 3, 2, 0 },
1053 { 192000000, 0, 48, 3, 1, 0 },
1054 { 288000000, 1, 72, 3, 1, 0 },
1055 { 32750000, 1, 65, 3, 4, 35127 },
1056 { 32768000, 1, 65, 3, 4, 35127 },
1057 { 45158400, 0, 45, 3, 3, 10355 },
1058 { 45000000, 0, 45, 3, 3, 10355 },
1059 { 45158000, 0, 45, 3, 3, 10355 },
1060 { 49125000, 0, 49, 3, 3, 9961 },
1061 { 49152000, 0, 49, 3, 3, 9961 },
1062 { 67737600, 1, 67, 3, 3, 48366 },
1063 { 67738000, 1, 67, 3, 3, 48366 },
1064 { 73800000, 1, 73, 3, 3, 47710 },
1065 { 73728000, 1, 73, 3, 3, 47710 },
1066 { 36000000, 1, 32, 3, 4, 0 },
1067 { 60000000, 1, 60, 3, 3, 0 },
1068 { 72000000, 1, 72, 3, 3, 0 },
1069 { 80000000, 1, 80, 3, 3, 0 },
1070 { 84000000, 0, 42, 3, 2, 0 },
1071 { 50000000, 0, 50, 3, 3, 0 },
1074 static int s5pv210_epll_set_rate(struct clk
*clk
, unsigned long rate
)
1076 unsigned int epll_con
, epll_con_k
;
1079 /* Return if nothing changed */
1080 if (clk
->rate
== rate
)
1083 epll_con
= __raw_readl(S5P_EPLL_CON
);
1084 epll_con_k
= __raw_readl(S5P_EPLL_CON1
);
1086 epll_con_k
&= ~PLL46XX_KDIV_MASK
;
1087 epll_con
&= ~(1 << 27 |
1088 PLL46XX_MDIV_MASK
<< PLL46XX_MDIV_SHIFT
|
1089 PLL46XX_PDIV_MASK
<< PLL46XX_PDIV_SHIFT
|
1090 PLL46XX_SDIV_MASK
<< PLL46XX_SDIV_SHIFT
);
1092 for (i
= 0; i
< ARRAY_SIZE(epll_div
); i
++) {
1093 if (epll_div
[i
][0] == rate
) {
1094 epll_con_k
|= epll_div
[i
][5] << 0;
1095 epll_con
|= (epll_div
[i
][1] << 27 |
1096 epll_div
[i
][2] << PLL46XX_MDIV_SHIFT
|
1097 epll_div
[i
][3] << PLL46XX_PDIV_SHIFT
|
1098 epll_div
[i
][4] << PLL46XX_SDIV_SHIFT
);
1103 if (i
== ARRAY_SIZE(epll_div
)) {
1104 printk(KERN_ERR
"%s: Invalid Clock EPLL Frequency\n",
1109 __raw_writel(epll_con
, S5P_EPLL_CON
);
1110 __raw_writel(epll_con_k
, S5P_EPLL_CON1
);
1112 printk(KERN_WARNING
"EPLL Rate changes from %lu to %lu\n",
1120 static struct clk_ops s5pv210_epll_ops
= {
1121 .set_rate
= s5pv210_epll_set_rate
,
1122 .get_rate
= s5p_epll_get_rate
,
1125 static u32 vpll_div
[][5] = {
1126 { 54000000, 3, 53, 3, 0 },
1127 { 108000000, 3, 53, 2, 0 },
1130 static unsigned long s5pv210_vpll_get_rate(struct clk
*clk
)
1135 static int s5pv210_vpll_set_rate(struct clk
*clk
, unsigned long rate
)
1137 unsigned int vpll_con
;
1140 /* Return if nothing changed */
1141 if (clk
->rate
== rate
)
1144 vpll_con
= __raw_readl(S5P_VPLL_CON
);
1145 vpll_con
&= ~(0x1 << 27 | \
1146 PLL90XX_MDIV_MASK
<< PLL90XX_MDIV_SHIFT
| \
1147 PLL90XX_PDIV_MASK
<< PLL90XX_PDIV_SHIFT
| \
1148 PLL90XX_SDIV_MASK
<< PLL90XX_SDIV_SHIFT
);
1150 for (i
= 0; i
< ARRAY_SIZE(vpll_div
); i
++) {
1151 if (vpll_div
[i
][0] == rate
) {
1152 vpll_con
|= vpll_div
[i
][1] << PLL90XX_PDIV_SHIFT
;
1153 vpll_con
|= vpll_div
[i
][2] << PLL90XX_MDIV_SHIFT
;
1154 vpll_con
|= vpll_div
[i
][3] << PLL90XX_SDIV_SHIFT
;
1155 vpll_con
|= vpll_div
[i
][4] << 27;
1160 if (i
== ARRAY_SIZE(vpll_div
)) {
1161 printk(KERN_ERR
"%s: Invalid Clock VPLL Frequency\n",
1166 __raw_writel(vpll_con
, S5P_VPLL_CON
);
1168 /* Wait for VPLL lock */
1169 while (!(__raw_readl(S5P_VPLL_CON
) & (1 << PLL90XX_LOCKED_SHIFT
)))
1175 static struct clk_ops s5pv210_vpll_ops
= {
1176 .get_rate
= s5pv210_vpll_get_rate
,
1177 .set_rate
= s5pv210_vpll_set_rate
,
1180 void __init_or_cpufreq
s5pv210_setup_clocks(void)
1182 struct clk
*xtal_clk
;
1183 unsigned long vpllsrc
;
1184 unsigned long armclk
;
1185 unsigned long hclk_msys
;
1186 unsigned long hclk_dsys
;
1187 unsigned long hclk_psys
;
1188 unsigned long pclk_msys
;
1189 unsigned long pclk_dsys
;
1190 unsigned long pclk_psys
;
1196 u32 clkdiv0
, clkdiv1
;
1198 /* Set functions for clk_fout_epll */
1199 clk_fout_epll
.enable
= s5p_epll_enable
;
1200 clk_fout_epll
.ops
= &s5pv210_epll_ops
;
1202 printk(KERN_DEBUG
"%s: registering clocks\n", __func__
);
1204 clkdiv0
= __raw_readl(S5P_CLK_DIV0
);
1205 clkdiv1
= __raw_readl(S5P_CLK_DIV1
);
1207 printk(KERN_DEBUG
"%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
1208 __func__
, clkdiv0
, clkdiv1
);
1210 xtal_clk
= clk_get(NULL
, "xtal");
1211 BUG_ON(IS_ERR(xtal_clk
));
1213 xtal
= clk_get_rate(xtal_clk
);
1216 printk(KERN_DEBUG
"%s: xtal is %ld\n", __func__
, xtal
);
1218 apll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_APLL_CON
), pll_4508
);
1219 mpll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_MPLL_CON
), pll_4502
);
1220 epll
= s5p_get_pll46xx(xtal
, __raw_readl(S5P_EPLL_CON
),
1221 __raw_readl(S5P_EPLL_CON1
), pll_4600
);
1222 vpllsrc
= clk_get_rate(&clk_vpllsrc
.clk
);
1223 vpll
= s5p_get_pll45xx(vpllsrc
, __raw_readl(S5P_VPLL_CON
), pll_4502
);
1225 clk_fout_apll
.ops
= &clk_fout_apll_ops
;
1226 clk_fout_mpll
.rate
= mpll
;
1227 clk_fout_epll
.rate
= epll
;
1228 clk_fout_vpll
.ops
= &s5pv210_vpll_ops
;
1229 clk_fout_vpll
.rate
= vpll
;
1231 printk(KERN_INFO
"S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
1232 apll
, mpll
, epll
, vpll
);
1234 armclk
= clk_get_rate(&clk_armclk
.clk
);
1235 hclk_msys
= clk_get_rate(&clk_hclk_msys
.clk
);
1236 hclk_dsys
= clk_get_rate(&clk_hclk_dsys
.clk
);
1237 hclk_psys
= clk_get_rate(&clk_hclk_psys
.clk
);
1238 pclk_msys
= clk_get_rate(&clk_pclk_msys
.clk
);
1239 pclk_dsys
= clk_get_rate(&clk_pclk_dsys
.clk
);
1240 pclk_psys
= clk_get_rate(&clk_pclk_psys
.clk
);
1242 printk(KERN_INFO
"S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
1243 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
1244 armclk
, hclk_msys
, hclk_dsys
, hclk_psys
,
1245 pclk_msys
, pclk_dsys
, pclk_psys
);
1247 clk_f
.rate
= armclk
;
1248 clk_h
.rate
= hclk_psys
;
1249 clk_p
.rate
= pclk_psys
;
1251 for (ptr
= 0; ptr
< ARRAY_SIZE(clksrcs
); ptr
++)
1252 s3c_set_clksrc(&clksrcs
[ptr
], true);
1255 static struct clk
*clks
[] __initdata
= {
1265 void __init
s5pv210_register_clocks(void)
1269 s3c24xx_register_clocks(clks
, ARRAY_SIZE(clks
));
1271 for (ptr
= 0; ptr
< ARRAY_SIZE(sysclks
); ptr
++)
1272 s3c_register_clksrc(sysclks
[ptr
], 1);
1274 for (ptr
= 0; ptr
< ARRAY_SIZE(sclk_tv
); ptr
++)
1275 s3c_register_clksrc(sclk_tv
[ptr
], 1);
1277 s3c_register_clksrc(clksrcs
, ARRAY_SIZE(clksrcs
));
1278 s3c_register_clocks(init_clocks
, ARRAY_SIZE(init_clocks
));
1280 s3c_register_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1281 s3c_disable_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1283 s3c24xx_register_clock(&dummy_apb_pclk
);