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
*clkset_vpllsrc_list
[] = {
219 [1] = &clk_sclk_hdmi27m
,
222 static struct clksrc_sources clkset_vpllsrc
= {
223 .sources
= clkset_vpllsrc_list
,
224 .nr_sources
= ARRAY_SIZE(clkset_vpllsrc_list
),
227 static struct clksrc_clk clk_vpllsrc
= {
230 .enable
= s5pv210_clk_mask0_ctrl
,
233 .sources
= &clkset_vpllsrc
,
234 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 28, .size
= 1 },
237 static struct clk
*clkset_sclk_vpll_list
[] = {
238 [0] = &clk_vpllsrc
.clk
,
239 [1] = &clk_fout_vpll
,
242 static struct clksrc_sources clkset_sclk_vpll
= {
243 .sources
= clkset_sclk_vpll_list
,
244 .nr_sources
= ARRAY_SIZE(clkset_sclk_vpll_list
),
247 static struct clksrc_clk clk_sclk_vpll
= {
251 .sources
= &clkset_sclk_vpll
,
252 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 12, .size
= 1 },
255 static struct clk
*clkset_moutdmc0src_list
[] = {
256 [0] = &clk_sclk_a2m
.clk
,
257 [1] = &clk_mout_mpll
.clk
,
262 static struct clksrc_sources clkset_moutdmc0src
= {
263 .sources
= clkset_moutdmc0src_list
,
264 .nr_sources
= ARRAY_SIZE(clkset_moutdmc0src_list
),
267 static struct clksrc_clk clk_mout_dmc0
= {
271 .sources
= &clkset_moutdmc0src
,
272 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 24, .size
= 2 },
275 static struct clksrc_clk clk_sclk_dmc0
= {
278 .parent
= &clk_mout_dmc0
.clk
,
280 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 28, .size
= 4 },
283 static unsigned long s5pv210_clk_imem_get_rate(struct clk
*clk
)
285 return clk_get_rate(clk
->parent
) / 2;
288 static struct clk_ops clk_hclk_imem_ops
= {
289 .get_rate
= s5pv210_clk_imem_get_rate
,
292 static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk
*clk
)
294 return s5p_get_pll45xx(xtal
, __raw_readl(S5P_APLL_CON
), pll_4508
);
297 static struct clk_ops clk_fout_apll_ops
= {
298 .get_rate
= s5pv210_clk_fout_apll_get_rate
,
301 static struct clk init_clocks_off
[] = {
304 .parent
= &clk_hclk_dsys
.clk
,
305 .enable
= s5pv210_clk_ip0_ctrl
,
309 .devname
= "s5pv210-fimc.0",
310 .parent
= &clk_hclk_dsys
.clk
,
311 .enable
= s5pv210_clk_ip0_ctrl
,
312 .ctrlbit
= (1 << 24),
315 .devname
= "s5pv210-fimc.1",
316 .parent
= &clk_hclk_dsys
.clk
,
317 .enable
= s5pv210_clk_ip0_ctrl
,
318 .ctrlbit
= (1 << 25),
321 .devname
= "s5pv210-fimc.2",
322 .parent
= &clk_hclk_dsys
.clk
,
323 .enable
= s5pv210_clk_ip0_ctrl
,
324 .ctrlbit
= (1 << 26),
327 .parent
= &clk_hclk_dsys
.clk
,
328 .enable
= s5pv210_clk_ip0_ctrl
,
329 .ctrlbit
= (1 << 28),
332 .devname
= "s5p-mfc",
333 .parent
= &clk_pclk_psys
.clk
,
334 .enable
= s5pv210_clk_ip0_ctrl
,
335 .ctrlbit
= (1 << 16),
338 .devname
= "s5p-sdo",
339 .parent
= &clk_hclk_dsys
.clk
,
340 .enable
= s5pv210_clk_ip1_ctrl
,
341 .ctrlbit
= (1 << 10),
344 .devname
= "s5p-mixer",
345 .parent
= &clk_hclk_dsys
.clk
,
346 .enable
= s5pv210_clk_ip1_ctrl
,
350 .devname
= "s5p-mixer",
351 .parent
= &clk_hclk_dsys
.clk
,
352 .enable
= s5pv210_clk_ip1_ctrl
,
356 .devname
= "s5pv210-hdmi",
357 .parent
= &clk_hclk_dsys
.clk
,
358 .enable
= s5pv210_clk_ip1_ctrl
,
359 .ctrlbit
= (1 << 11),
362 .devname
= "s5pv210-hdmi",
363 .enable
= s5pv210_clk_hdmiphy_ctrl
,
367 .devname
= "s5p-sdo",
368 .enable
= exynos4_clk_dac_ctrl
,
372 .parent
= &clk_hclk_psys
.clk
,
373 .enable
= s5pv210_clk_ip1_ctrl
,
377 .parent
= &clk_hclk_psys
.clk
,
378 .enable
= s5pv210_clk_ip1_ctrl
,
382 .parent
= &clk_hclk_dsys
.clk
,
383 .enable
= s5pv210_clk_ip1_ctrl
,
387 .parent
= &clk_hclk_psys
.clk
,
388 .enable
= s5pv210_clk_ip1_ctrl
,
392 .parent
= &clk_pclk_psys
.clk
,
393 .enable
= s5pv210_clk_ip3_ctrl
,
397 .parent
= &clk_pclk_psys
.clk
,
398 .enable
= s5pv210_clk_ip3_ctrl
,
402 .parent
= &clk_pclk_psys
.clk
,
403 .enable
= s5pv210_clk_ip3_ctrl
,
407 .devname
= "s3c2440-i2c.0",
408 .parent
= &clk_pclk_psys
.clk
,
409 .enable
= s5pv210_clk_ip3_ctrl
,
413 .devname
= "s3c2440-i2c.1",
414 .parent
= &clk_pclk_psys
.clk
,
415 .enable
= s5pv210_clk_ip3_ctrl
,
416 .ctrlbit
= (1 << 10),
419 .devname
= "s3c2440-i2c.2",
420 .parent
= &clk_pclk_psys
.clk
,
421 .enable
= s5pv210_clk_ip3_ctrl
,
425 .devname
= "s3c2440-hdmiphy-i2c",
426 .parent
= &clk_pclk_psys
.clk
,
427 .enable
= s5pv210_clk_ip3_ctrl
,
428 .ctrlbit
= (1 << 11),
431 .devname
= "s5pv210-spi.0",
432 .parent
= &clk_pclk_psys
.clk
,
433 .enable
= s5pv210_clk_ip3_ctrl
,
437 .devname
= "s5pv210-spi.1",
438 .parent
= &clk_pclk_psys
.clk
,
439 .enable
= s5pv210_clk_ip3_ctrl
,
443 .devname
= "s5pv210-spi.2",
444 .parent
= &clk_pclk_psys
.clk
,
445 .enable
= s5pv210_clk_ip3_ctrl
,
449 .parent
= &clk_pclk_psys
.clk
,
450 .enable
= s5pv210_clk_ip3_ctrl
,
454 .parent
= &clk_pclk_psys
.clk
,
455 .enable
= s5pv210_clk_ip3_ctrl
,
459 .parent
= &clk_pclk_psys
.clk
,
460 .enable
= s5pv210_clk_ip3_ctrl
,
464 .devname
= "samsung-i2s.0",
466 .enable
= s5pv210_clk_ip3_ctrl
,
470 .devname
= "samsung-i2s.1",
472 .enable
= s5pv210_clk_ip3_ctrl
,
476 .devname
= "samsung-i2s.2",
478 .enable
= s5pv210_clk_ip3_ctrl
,
483 .enable
= s5pv210_clk_ip3_ctrl
,
488 static struct clk init_clocks
[] = {
491 .parent
= &clk_hclk_msys
.clk
,
493 .enable
= s5pv210_clk_ip0_ctrl
,
494 .ops
= &clk_hclk_imem_ops
,
497 .devname
= "s5pv210-uart.0",
498 .parent
= &clk_pclk_psys
.clk
,
499 .enable
= s5pv210_clk_ip3_ctrl
,
500 .ctrlbit
= (1 << 17),
503 .devname
= "s5pv210-uart.1",
504 .parent
= &clk_pclk_psys
.clk
,
505 .enable
= s5pv210_clk_ip3_ctrl
,
506 .ctrlbit
= (1 << 18),
509 .devname
= "s5pv210-uart.2",
510 .parent
= &clk_pclk_psys
.clk
,
511 .enable
= s5pv210_clk_ip3_ctrl
,
512 .ctrlbit
= (1 << 19),
515 .devname
= "s5pv210-uart.3",
516 .parent
= &clk_pclk_psys
.clk
,
517 .enable
= s5pv210_clk_ip3_ctrl
,
518 .ctrlbit
= (1 << 20),
521 .parent
= &clk_hclk_psys
.clk
,
522 .enable
= s5pv210_clk_ip1_ctrl
,
523 .ctrlbit
= (1 << 26),
527 static struct clk clk_hsmmc0
= {
529 .devname
= "s3c-sdhci.0",
530 .parent
= &clk_hclk_psys
.clk
,
531 .enable
= s5pv210_clk_ip2_ctrl
,
535 static struct clk clk_hsmmc1
= {
537 .devname
= "s3c-sdhci.1",
538 .parent
= &clk_hclk_psys
.clk
,
539 .enable
= s5pv210_clk_ip2_ctrl
,
543 static struct clk clk_hsmmc2
= {
545 .devname
= "s3c-sdhci.2",
546 .parent
= &clk_hclk_psys
.clk
,
547 .enable
= s5pv210_clk_ip2_ctrl
,
551 static struct clk clk_hsmmc3
= {
553 .devname
= "s3c-sdhci.3",
554 .parent
= &clk_hclk_psys
.clk
,
555 .enable
= s5pv210_clk_ip2_ctrl
,
559 static struct clk clk_pdma0
= {
561 .parent
= &clk_hclk_psys
.clk
,
562 .enable
= s5pv210_clk_ip0_ctrl
,
566 static struct clk clk_pdma1
= {
568 .parent
= &clk_hclk_psys
.clk
,
569 .enable
= s5pv210_clk_ip0_ctrl
,
573 static struct clk
*clkset_uart_list
[] = {
574 [6] = &clk_mout_mpll
.clk
,
575 [7] = &clk_mout_epll
.clk
,
578 static struct clksrc_sources clkset_uart
= {
579 .sources
= clkset_uart_list
,
580 .nr_sources
= ARRAY_SIZE(clkset_uart_list
),
583 static struct clk
*clkset_group1_list
[] = {
584 [0] = &clk_sclk_a2m
.clk
,
585 [1] = &clk_mout_mpll
.clk
,
586 [2] = &clk_mout_epll
.clk
,
587 [3] = &clk_sclk_vpll
.clk
,
590 static struct clksrc_sources clkset_group1
= {
591 .sources
= clkset_group1_list
,
592 .nr_sources
= ARRAY_SIZE(clkset_group1_list
),
595 static struct clk
*clkset_sclk_onenand_list
[] = {
596 [0] = &clk_hclk_psys
.clk
,
597 [1] = &clk_hclk_dsys
.clk
,
600 static struct clksrc_sources clkset_sclk_onenand
= {
601 .sources
= clkset_sclk_onenand_list
,
602 .nr_sources
= ARRAY_SIZE(clkset_sclk_onenand_list
),
605 static struct clk
*clkset_sclk_dac_list
[] = {
606 [0] = &clk_sclk_vpll
.clk
,
607 [1] = &clk_sclk_hdmiphy
,
610 static struct clksrc_sources clkset_sclk_dac
= {
611 .sources
= clkset_sclk_dac_list
,
612 .nr_sources
= ARRAY_SIZE(clkset_sclk_dac_list
),
615 static struct clksrc_clk clk_sclk_dac
= {
618 .enable
= s5pv210_clk_mask0_ctrl
,
621 .sources
= &clkset_sclk_dac
,
622 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 8, .size
= 1 },
625 static struct clksrc_clk clk_sclk_pixel
= {
627 .name
= "sclk_pixel",
628 .parent
= &clk_sclk_vpll
.clk
,
630 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 0, .size
= 4},
633 static struct clk
*clkset_sclk_hdmi_list
[] = {
634 [0] = &clk_sclk_pixel
.clk
,
635 [1] = &clk_sclk_hdmiphy
,
638 static struct clksrc_sources clkset_sclk_hdmi
= {
639 .sources
= clkset_sclk_hdmi_list
,
640 .nr_sources
= ARRAY_SIZE(clkset_sclk_hdmi_list
),
643 static struct clksrc_clk clk_sclk_hdmi
= {
646 .enable
= s5pv210_clk_mask0_ctrl
,
649 .sources
= &clkset_sclk_hdmi
,
650 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 0, .size
= 1 },
653 static struct clk
*clkset_sclk_mixer_list
[] = {
654 [0] = &clk_sclk_dac
.clk
,
655 [1] = &clk_sclk_hdmi
.clk
,
658 static struct clksrc_sources clkset_sclk_mixer
= {
659 .sources
= clkset_sclk_mixer_list
,
660 .nr_sources
= ARRAY_SIZE(clkset_sclk_mixer_list
),
663 static struct clksrc_clk clk_sclk_mixer
= {
665 .name
= "sclk_mixer",
666 .enable
= s5pv210_clk_mask0_ctrl
,
669 .sources
= &clkset_sclk_mixer
,
670 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 4, .size
= 1 },
673 static struct clksrc_clk
*sclk_tv
[] = {
680 static struct clk
*clkset_sclk_audio0_list
[] = {
681 [0] = &clk_ext_xtal_mux
,
682 [1] = &clk_pcmcdclk0
,
683 [2] = &clk_sclk_hdmi27m
,
684 [3] = &clk_sclk_usbphy0
,
685 [4] = &clk_sclk_usbphy1
,
686 [5] = &clk_sclk_hdmiphy
,
687 [6] = &clk_mout_mpll
.clk
,
688 [7] = &clk_mout_epll
.clk
,
689 [8] = &clk_sclk_vpll
.clk
,
692 static struct clksrc_sources clkset_sclk_audio0
= {
693 .sources
= clkset_sclk_audio0_list
,
694 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio0_list
),
697 static struct clksrc_clk clk_sclk_audio0
= {
699 .name
= "sclk_audio",
700 .devname
= "soc-audio.0",
701 .enable
= s5pv210_clk_mask0_ctrl
,
702 .ctrlbit
= (1 << 24),
704 .sources
= &clkset_sclk_audio0
,
705 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 0, .size
= 4 },
706 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 0, .size
= 4 },
709 static struct clk
*clkset_sclk_audio1_list
[] = {
710 [0] = &clk_ext_xtal_mux
,
711 [1] = &clk_pcmcdclk1
,
712 [2] = &clk_sclk_hdmi27m
,
713 [3] = &clk_sclk_usbphy0
,
714 [4] = &clk_sclk_usbphy1
,
715 [5] = &clk_sclk_hdmiphy
,
716 [6] = &clk_mout_mpll
.clk
,
717 [7] = &clk_mout_epll
.clk
,
718 [8] = &clk_sclk_vpll
.clk
,
721 static struct clksrc_sources clkset_sclk_audio1
= {
722 .sources
= clkset_sclk_audio1_list
,
723 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio1_list
),
726 static struct clksrc_clk clk_sclk_audio1
= {
728 .name
= "sclk_audio",
729 .devname
= "soc-audio.1",
730 .enable
= s5pv210_clk_mask0_ctrl
,
731 .ctrlbit
= (1 << 25),
733 .sources
= &clkset_sclk_audio1
,
734 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 4, .size
= 4 },
735 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 4, .size
= 4 },
738 static struct clk
*clkset_sclk_audio2_list
[] = {
739 [0] = &clk_ext_xtal_mux
,
740 [1] = &clk_pcmcdclk0
,
741 [2] = &clk_sclk_hdmi27m
,
742 [3] = &clk_sclk_usbphy0
,
743 [4] = &clk_sclk_usbphy1
,
744 [5] = &clk_sclk_hdmiphy
,
745 [6] = &clk_mout_mpll
.clk
,
746 [7] = &clk_mout_epll
.clk
,
747 [8] = &clk_sclk_vpll
.clk
,
750 static struct clksrc_sources clkset_sclk_audio2
= {
751 .sources
= clkset_sclk_audio2_list
,
752 .nr_sources
= ARRAY_SIZE(clkset_sclk_audio2_list
),
755 static struct clksrc_clk clk_sclk_audio2
= {
757 .name
= "sclk_audio",
758 .devname
= "soc-audio.2",
759 .enable
= s5pv210_clk_mask0_ctrl
,
760 .ctrlbit
= (1 << 26),
762 .sources
= &clkset_sclk_audio2
,
763 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 8, .size
= 4 },
764 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 8, .size
= 4 },
767 static struct clk
*clkset_sclk_spdif_list
[] = {
768 [0] = &clk_sclk_audio0
.clk
,
769 [1] = &clk_sclk_audio1
.clk
,
770 [2] = &clk_sclk_audio2
.clk
,
773 static struct clksrc_sources clkset_sclk_spdif
= {
774 .sources
= clkset_sclk_spdif_list
,
775 .nr_sources
= ARRAY_SIZE(clkset_sclk_spdif_list
),
778 static struct clksrc_clk clk_sclk_spdif
= {
780 .name
= "sclk_spdif",
781 .enable
= s5pv210_clk_mask0_ctrl
,
782 .ctrlbit
= (1 << 27),
783 .ops
= &s5p_sclk_spdif_ops
,
785 .sources
= &clkset_sclk_spdif
,
786 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 12, .size
= 2 },
789 static struct clk
*clkset_group2_list
[] = {
790 [0] = &clk_ext_xtal_mux
,
792 [2] = &clk_sclk_hdmi27m
,
793 [3] = &clk_sclk_usbphy0
,
794 [4] = &clk_sclk_usbphy1
,
795 [5] = &clk_sclk_hdmiphy
,
796 [6] = &clk_mout_mpll
.clk
,
797 [7] = &clk_mout_epll
.clk
,
798 [8] = &clk_sclk_vpll
.clk
,
801 static struct clksrc_sources clkset_group2
= {
802 .sources
= clkset_group2_list
,
803 .nr_sources
= ARRAY_SIZE(clkset_group2_list
),
806 static struct clksrc_clk clksrcs
[] = {
811 .sources
= &clkset_group1
,
812 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 24, .size
= 2 },
813 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 28, .size
= 4 },
816 .name
= "sclk_onenand",
818 .sources
= &clkset_sclk_onenand
,
819 .reg_src
= { .reg
= S5P_CLK_SRC0
, .shift
= 28, .size
= 1 },
820 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 12, .size
= 3 },
824 .devname
= "s5pv210-fimc.0",
825 .enable
= s5pv210_clk_mask1_ctrl
,
828 .sources
= &clkset_group2
,
829 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 12, .size
= 4 },
830 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 12, .size
= 4 },
834 .devname
= "s5pv210-fimc.1",
835 .enable
= s5pv210_clk_mask1_ctrl
,
838 .sources
= &clkset_group2
,
839 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 16, .size
= 4 },
840 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 16, .size
= 4 },
844 .devname
= "s5pv210-fimc.2",
845 .enable
= s5pv210_clk_mask1_ctrl
,
848 .sources
= &clkset_group2
,
849 .reg_src
= { .reg
= S5P_CLK_SRC3
, .shift
= 20, .size
= 4 },
850 .reg_div
= { .reg
= S5P_CLK_DIV3
, .shift
= 20, .size
= 4 },
854 .enable
= s5pv210_clk_mask0_ctrl
,
857 .sources
= &clkset_group2
,
858 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 12, .size
= 4 },
859 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 12, .size
= 4 },
863 .enable
= s5pv210_clk_mask0_ctrl
,
866 .sources
= &clkset_group2
,
867 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 16, .size
= 4 },
868 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 16, .size
= 4 },
872 .enable
= s5pv210_clk_mask0_ctrl
,
875 .sources
= &clkset_group2
,
876 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 20, .size
= 4 },
877 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 20, .size
= 4 },
881 .devname
= "s5p-mfc",
882 .enable
= s5pv210_clk_ip0_ctrl
,
883 .ctrlbit
= (1 << 16),
885 .sources
= &clkset_group1
,
886 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 4, .size
= 2 },
887 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 4, .size
= 4 },
891 .enable
= s5pv210_clk_ip0_ctrl
,
892 .ctrlbit
= (1 << 12),
894 .sources
= &clkset_group1
,
895 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 8, .size
= 2 },
896 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 8, .size
= 4 },
900 .enable
= s5pv210_clk_ip0_ctrl
,
903 .sources
= &clkset_group1
,
904 .reg_src
= { .reg
= S5P_CLK_SRC2
, .shift
= 0, .size
= 2 },
905 .reg_div
= { .reg
= S5P_CLK_DIV2
, .shift
= 0, .size
= 4 },
909 .enable
= s5pv210_clk_mask0_ctrl
,
912 .sources
= &clkset_group2
,
913 .reg_src
= { .reg
= S5P_CLK_SRC1
, .shift
= 24, .size
= 4 },
914 .reg_div
= { .reg
= S5P_CLK_DIV1
, .shift
= 28, .size
= 4 },
918 .enable
= s5pv210_clk_mask0_ctrl
,
919 .ctrlbit
= (1 << 29),
921 .sources
= &clkset_group2
,
922 .reg_src
= { .reg
= S5P_CLK_SRC6
, .shift
= 20, .size
= 4 },
923 .reg_div
= { .reg
= S5P_CLK_DIV6
, .shift
= 24, .size
= 4 },
927 .enable
= s5pv210_clk_mask0_ctrl
,
928 .ctrlbit
= (1 << 19),
930 .sources
= &clkset_group2
,
931 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 12, .size
= 4 },
932 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 12, .size
= 4 },
936 static struct clksrc_clk clk_sclk_uart0
= {
939 .devname
= "s5pv210-uart.0",
940 .enable
= s5pv210_clk_mask0_ctrl
,
941 .ctrlbit
= (1 << 12),
943 .sources
= &clkset_uart
,
944 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 16, .size
= 4 },
945 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 16, .size
= 4 },
948 static struct clksrc_clk clk_sclk_uart1
= {
951 .devname
= "s5pv210-uart.1",
952 .enable
= s5pv210_clk_mask0_ctrl
,
953 .ctrlbit
= (1 << 13),
955 .sources
= &clkset_uart
,
956 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 20, .size
= 4 },
957 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 20, .size
= 4 },
960 static struct clksrc_clk clk_sclk_uart2
= {
963 .devname
= "s5pv210-uart.2",
964 .enable
= s5pv210_clk_mask0_ctrl
,
965 .ctrlbit
= (1 << 14),
967 .sources
= &clkset_uart
,
968 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 24, .size
= 4 },
969 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 24, .size
= 4 },
972 static struct clksrc_clk clk_sclk_uart3
= {
975 .devname
= "s5pv210-uart.3",
976 .enable
= s5pv210_clk_mask0_ctrl
,
977 .ctrlbit
= (1 << 15),
979 .sources
= &clkset_uart
,
980 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 28, .size
= 4 },
981 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 28, .size
= 4 },
984 static struct clksrc_clk clk_sclk_mmc0
= {
987 .devname
= "s3c-sdhci.0",
988 .enable
= s5pv210_clk_mask0_ctrl
,
991 .sources
= &clkset_group2
,
992 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 0, .size
= 4 },
993 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 0, .size
= 4 },
996 static struct clksrc_clk clk_sclk_mmc1
= {
999 .devname
= "s3c-sdhci.1",
1000 .enable
= s5pv210_clk_mask0_ctrl
,
1001 .ctrlbit
= (1 << 9),
1003 .sources
= &clkset_group2
,
1004 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 4, .size
= 4 },
1005 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 4, .size
= 4 },
1008 static struct clksrc_clk clk_sclk_mmc2
= {
1011 .devname
= "s3c-sdhci.2",
1012 .enable
= s5pv210_clk_mask0_ctrl
,
1013 .ctrlbit
= (1 << 10),
1015 .sources
= &clkset_group2
,
1016 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 8, .size
= 4 },
1017 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 8, .size
= 4 },
1020 static struct clksrc_clk clk_sclk_mmc3
= {
1023 .devname
= "s3c-sdhci.3",
1024 .enable
= s5pv210_clk_mask0_ctrl
,
1025 .ctrlbit
= (1 << 11),
1027 .sources
= &clkset_group2
,
1028 .reg_src
= { .reg
= S5P_CLK_SRC4
, .shift
= 12, .size
= 4 },
1029 .reg_div
= { .reg
= S5P_CLK_DIV4
, .shift
= 12, .size
= 4 },
1032 static struct clksrc_clk clk_sclk_spi0
= {
1035 .devname
= "s5pv210-spi.0",
1036 .enable
= s5pv210_clk_mask0_ctrl
,
1037 .ctrlbit
= (1 << 16),
1039 .sources
= &clkset_group2
,
1040 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 0, .size
= 4 },
1041 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 0, .size
= 4 },
1044 static struct clksrc_clk clk_sclk_spi1
= {
1047 .devname
= "s5pv210-spi.1",
1048 .enable
= s5pv210_clk_mask0_ctrl
,
1049 .ctrlbit
= (1 << 17),
1051 .sources
= &clkset_group2
,
1052 .reg_src
= { .reg
= S5P_CLK_SRC5
, .shift
= 4, .size
= 4 },
1053 .reg_div
= { .reg
= S5P_CLK_DIV5
, .shift
= 4, .size
= 4 },
1057 static struct clksrc_clk
*clksrc_cdev
[] = {
1070 static struct clk
*clk_cdev
[] = {
1079 /* Clock initialisation code */
1080 static struct clksrc_clk
*sysclks
[] = {
1102 static u32 epll_div
[][6] = {
1103 { 48000000, 0, 48, 3, 3, 0 },
1104 { 96000000, 0, 48, 3, 2, 0 },
1105 { 144000000, 1, 72, 3, 2, 0 },
1106 { 192000000, 0, 48, 3, 1, 0 },
1107 { 288000000, 1, 72, 3, 1, 0 },
1108 { 32750000, 1, 65, 3, 4, 35127 },
1109 { 32768000, 1, 65, 3, 4, 35127 },
1110 { 45158400, 0, 45, 3, 3, 10355 },
1111 { 45000000, 0, 45, 3, 3, 10355 },
1112 { 45158000, 0, 45, 3, 3, 10355 },
1113 { 49125000, 0, 49, 3, 3, 9961 },
1114 { 49152000, 0, 49, 3, 3, 9961 },
1115 { 67737600, 1, 67, 3, 3, 48366 },
1116 { 67738000, 1, 67, 3, 3, 48366 },
1117 { 73800000, 1, 73, 3, 3, 47710 },
1118 { 73728000, 1, 73, 3, 3, 47710 },
1119 { 36000000, 1, 32, 3, 4, 0 },
1120 { 60000000, 1, 60, 3, 3, 0 },
1121 { 72000000, 1, 72, 3, 3, 0 },
1122 { 80000000, 1, 80, 3, 3, 0 },
1123 { 84000000, 0, 42, 3, 2, 0 },
1124 { 50000000, 0, 50, 3, 3, 0 },
1127 static int s5pv210_epll_set_rate(struct clk
*clk
, unsigned long rate
)
1129 unsigned int epll_con
, epll_con_k
;
1132 /* Return if nothing changed */
1133 if (clk
->rate
== rate
)
1136 epll_con
= __raw_readl(S5P_EPLL_CON
);
1137 epll_con_k
= __raw_readl(S5P_EPLL_CON1
);
1139 epll_con_k
&= ~PLL46XX_KDIV_MASK
;
1140 epll_con
&= ~(1 << 27 |
1141 PLL46XX_MDIV_MASK
<< PLL46XX_MDIV_SHIFT
|
1142 PLL46XX_PDIV_MASK
<< PLL46XX_PDIV_SHIFT
|
1143 PLL46XX_SDIV_MASK
<< PLL46XX_SDIV_SHIFT
);
1145 for (i
= 0; i
< ARRAY_SIZE(epll_div
); i
++) {
1146 if (epll_div
[i
][0] == rate
) {
1147 epll_con_k
|= epll_div
[i
][5] << 0;
1148 epll_con
|= (epll_div
[i
][1] << 27 |
1149 epll_div
[i
][2] << PLL46XX_MDIV_SHIFT
|
1150 epll_div
[i
][3] << PLL46XX_PDIV_SHIFT
|
1151 epll_div
[i
][4] << PLL46XX_SDIV_SHIFT
);
1156 if (i
== ARRAY_SIZE(epll_div
)) {
1157 printk(KERN_ERR
"%s: Invalid Clock EPLL Frequency\n",
1162 __raw_writel(epll_con
, S5P_EPLL_CON
);
1163 __raw_writel(epll_con_k
, S5P_EPLL_CON1
);
1165 printk(KERN_WARNING
"EPLL Rate changes from %lu to %lu\n",
1173 static struct clk_ops s5pv210_epll_ops
= {
1174 .set_rate
= s5pv210_epll_set_rate
,
1175 .get_rate
= s5p_epll_get_rate
,
1178 static u32 vpll_div
[][5] = {
1179 { 54000000, 3, 53, 3, 0 },
1180 { 108000000, 3, 53, 2, 0 },
1183 static unsigned long s5pv210_vpll_get_rate(struct clk
*clk
)
1188 static int s5pv210_vpll_set_rate(struct clk
*clk
, unsigned long rate
)
1190 unsigned int vpll_con
;
1193 /* Return if nothing changed */
1194 if (clk
->rate
== rate
)
1197 vpll_con
= __raw_readl(S5P_VPLL_CON
);
1198 vpll_con
&= ~(0x1 << 27 | \
1199 PLL90XX_MDIV_MASK
<< PLL90XX_MDIV_SHIFT
| \
1200 PLL90XX_PDIV_MASK
<< PLL90XX_PDIV_SHIFT
| \
1201 PLL90XX_SDIV_MASK
<< PLL90XX_SDIV_SHIFT
);
1203 for (i
= 0; i
< ARRAY_SIZE(vpll_div
); i
++) {
1204 if (vpll_div
[i
][0] == rate
) {
1205 vpll_con
|= vpll_div
[i
][1] << PLL90XX_PDIV_SHIFT
;
1206 vpll_con
|= vpll_div
[i
][2] << PLL90XX_MDIV_SHIFT
;
1207 vpll_con
|= vpll_div
[i
][3] << PLL90XX_SDIV_SHIFT
;
1208 vpll_con
|= vpll_div
[i
][4] << 27;
1213 if (i
== ARRAY_SIZE(vpll_div
)) {
1214 printk(KERN_ERR
"%s: Invalid Clock VPLL Frequency\n",
1219 __raw_writel(vpll_con
, S5P_VPLL_CON
);
1221 /* Wait for VPLL lock */
1222 while (!(__raw_readl(S5P_VPLL_CON
) & (1 << PLL90XX_LOCKED_SHIFT
)))
1228 static struct clk_ops s5pv210_vpll_ops
= {
1229 .get_rate
= s5pv210_vpll_get_rate
,
1230 .set_rate
= s5pv210_vpll_set_rate
,
1233 void __init_or_cpufreq
s5pv210_setup_clocks(void)
1235 struct clk
*xtal_clk
;
1236 unsigned long vpllsrc
;
1237 unsigned long armclk
;
1238 unsigned long hclk_msys
;
1239 unsigned long hclk_dsys
;
1240 unsigned long hclk_psys
;
1241 unsigned long pclk_msys
;
1242 unsigned long pclk_dsys
;
1243 unsigned long pclk_psys
;
1249 u32 clkdiv0
, clkdiv1
;
1251 /* Set functions for clk_fout_epll */
1252 clk_fout_epll
.enable
= s5p_epll_enable
;
1253 clk_fout_epll
.ops
= &s5pv210_epll_ops
;
1255 printk(KERN_DEBUG
"%s: registering clocks\n", __func__
);
1257 clkdiv0
= __raw_readl(S5P_CLK_DIV0
);
1258 clkdiv1
= __raw_readl(S5P_CLK_DIV1
);
1260 printk(KERN_DEBUG
"%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
1261 __func__
, clkdiv0
, clkdiv1
);
1263 xtal_clk
= clk_get(NULL
, "xtal");
1264 BUG_ON(IS_ERR(xtal_clk
));
1266 xtal
= clk_get_rate(xtal_clk
);
1269 printk(KERN_DEBUG
"%s: xtal is %ld\n", __func__
, xtal
);
1271 apll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_APLL_CON
), pll_4508
);
1272 mpll
= s5p_get_pll45xx(xtal
, __raw_readl(S5P_MPLL_CON
), pll_4502
);
1273 epll
= s5p_get_pll46xx(xtal
, __raw_readl(S5P_EPLL_CON
),
1274 __raw_readl(S5P_EPLL_CON1
), pll_4600
);
1275 vpllsrc
= clk_get_rate(&clk_vpllsrc
.clk
);
1276 vpll
= s5p_get_pll45xx(vpllsrc
, __raw_readl(S5P_VPLL_CON
), pll_4502
);
1278 clk_fout_apll
.ops
= &clk_fout_apll_ops
;
1279 clk_fout_mpll
.rate
= mpll
;
1280 clk_fout_epll
.rate
= epll
;
1281 clk_fout_vpll
.ops
= &s5pv210_vpll_ops
;
1282 clk_fout_vpll
.rate
= vpll
;
1284 printk(KERN_INFO
"S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
1285 apll
, mpll
, epll
, vpll
);
1287 armclk
= clk_get_rate(&clk_armclk
.clk
);
1288 hclk_msys
= clk_get_rate(&clk_hclk_msys
.clk
);
1289 hclk_dsys
= clk_get_rate(&clk_hclk_dsys
.clk
);
1290 hclk_psys
= clk_get_rate(&clk_hclk_psys
.clk
);
1291 pclk_msys
= clk_get_rate(&clk_pclk_msys
.clk
);
1292 pclk_dsys
= clk_get_rate(&clk_pclk_dsys
.clk
);
1293 pclk_psys
= clk_get_rate(&clk_pclk_psys
.clk
);
1295 printk(KERN_INFO
"S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
1296 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
1297 armclk
, hclk_msys
, hclk_dsys
, hclk_psys
,
1298 pclk_msys
, pclk_dsys
, pclk_psys
);
1300 clk_f
.rate
= armclk
;
1301 clk_h
.rate
= hclk_psys
;
1302 clk_p
.rate
= pclk_psys
;
1304 for (ptr
= 0; ptr
< ARRAY_SIZE(clksrcs
); ptr
++)
1305 s3c_set_clksrc(&clksrcs
[ptr
], true);
1308 static struct clk
*clks
[] __initdata
= {
1318 static struct clk_lookup s5pv210_clk_lookup
[] = {
1319 CLKDEV_INIT(NULL
, "clk_uart_baud0", &clk_p
),
1320 CLKDEV_INIT("s5pv210-uart.0", "clk_uart_baud1", &clk_sclk_uart0
.clk
),
1321 CLKDEV_INIT("s5pv210-uart.1", "clk_uart_baud1", &clk_sclk_uart1
.clk
),
1322 CLKDEV_INIT("s5pv210-uart.2", "clk_uart_baud1", &clk_sclk_uart2
.clk
),
1323 CLKDEV_INIT("s5pv210-uart.3", "clk_uart_baud1", &clk_sclk_uart3
.clk
),
1324 CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0
),
1325 CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1
),
1326 CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2
),
1327 CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.0", &clk_hsmmc3
),
1328 CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0
.clk
),
1329 CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1
.clk
),
1330 CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2
.clk
),
1331 CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3
.clk
),
1332 CLKDEV_INIT(NULL
, "spi_busclk0", &clk_p
),
1333 CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0
.clk
),
1334 CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1
.clk
),
1335 CLKDEV_INIT("dma-pl330.0", "apb_pclk", &clk_pdma0
),
1336 CLKDEV_INIT("dma-pl330.1", "apb_pclk", &clk_pdma1
),
1339 void __init
s5pv210_register_clocks(void)
1343 s3c24xx_register_clocks(clks
, ARRAY_SIZE(clks
));
1345 for (ptr
= 0; ptr
< ARRAY_SIZE(sysclks
); ptr
++)
1346 s3c_register_clksrc(sysclks
[ptr
], 1);
1348 for (ptr
= 0; ptr
< ARRAY_SIZE(sclk_tv
); ptr
++)
1349 s3c_register_clksrc(sclk_tv
[ptr
], 1);
1351 for (ptr
= 0; ptr
< ARRAY_SIZE(clksrc_cdev
); ptr
++)
1352 s3c_register_clksrc(clksrc_cdev
[ptr
], 1);
1354 s3c_register_clksrc(clksrcs
, ARRAY_SIZE(clksrcs
));
1355 s3c_register_clocks(init_clocks
, ARRAY_SIZE(init_clocks
));
1357 s3c_register_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1358 s3c_disable_clocks(init_clocks_off
, ARRAY_SIZE(init_clocks_off
));
1359 clkdev_add_table(s5pv210_clk_lookup
, ARRAY_SIZE(s5pv210_clk_lookup
));
1361 s3c24xx_register_clocks(clk_cdev
, ARRAY_SIZE(clk_cdev
));
1362 for (ptr
= 0; ptr
< ARRAY_SIZE(clk_cdev
); ptr
++)
1363 s3c_disable_clocks(clk_cdev
[ptr
], 1);