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 = {
41 .sources = &clk_src_apll,
42 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
45 static struct clksrc_clk clk_mout_epll = {
50 .sources = &clk_src_epll,
51 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
54 static struct clksrc_clk clk_mout_mpll = {
59 .sources = &clk_src_mpll,
60 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
63 static struct clk *clkset_armclk_list[] = {
64 [0] = &clk_mout_apll.clk,
65 [1] = &clk_mout_mpll.clk,
68 static struct clksrc_sources clkset_armclk = {
69 .sources = clkset_armclk_list,
70 .nr_sources = ARRAY_SIZE(clkset_armclk_list),
73 static struct clksrc_clk clk_armclk = {
78 .sources = &clkset_armclk,
79 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
80 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },
83 static struct clksrc_clk clk_hclk_msys = {
87 .parent = &clk_armclk.clk,
89 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
92 static struct clksrc_clk clk_pclk_msys = {
96 .parent = &clk_hclk_msys.clk,
98 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
101 static struct clksrc_clk clk_sclk_a2m = {
105 .parent = &clk_mout_apll.clk,
107 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
110 static struct clk *clkset_hclk_sys_list[] = {
111 [0] = &clk_mout_mpll.clk,
112 [1] = &clk_sclk_a2m.clk,
115 static struct clksrc_sources clkset_hclk_sys = {
116 .sources = clkset_hclk_sys_list,
117 .nr_sources = ARRAY_SIZE(clkset_hclk_sys_list),
120 static struct clksrc_clk clk_hclk_dsys = {
125 .sources = &clkset_hclk_sys,
126 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
127 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },
130 static struct clksrc_clk clk_pclk_dsys = {
134 .parent = &clk_hclk_dsys.clk,
136 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
139 static struct clksrc_clk clk_hclk_psys = {
144 .sources = &clkset_hclk_sys,
145 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
146 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },
149 static struct clksrc_clk clk_pclk_psys = {
153 .parent = &clk_hclk_psys.clk,
155 .reg_div = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
158 static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
160 return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
163 static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
165 return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
168 static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
170 return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
173 static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
175 return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
178 static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
180 return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
183 static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
185 return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
188 static struct clk clk_sclk_hdmi27m = {
189 .name = "sclk_hdmi27m",
194 static struct clk clk_sclk_hdmiphy = {
195 .name = "sclk_hdmiphy",
199 static struct clk clk_sclk_usbphy0 = {
200 .name = "sclk_usbphy0",
204 static struct clk clk_sclk_usbphy1 = {
205 .name = "sclk_usbphy1",
209 static struct clk clk_pcmcdclk0 = {
214 static struct clk clk_pcmcdclk1 = {
219 static struct clk clk_pcmcdclk2 = {
224 static struct clk *clkset_vpllsrc_list[] = {
226 [1] = &clk_sclk_hdmi27m,
229 static struct clksrc_sources clkset_vpllsrc = {
230 .sources = clkset_vpllsrc_list,
231 .nr_sources = ARRAY_SIZE(clkset_vpllsrc_list),
234 static struct clksrc_clk clk_vpllsrc = {
238 .enable = s5pv210_clk_mask0_ctrl,
241 .sources = &clkset_vpllsrc,
242 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 },
245 static struct clk *clkset_sclk_vpll_list[] = {
246 [0] = &clk_vpllsrc.clk,
247 [1] = &clk_fout_vpll,
250 static struct clksrc_sources clkset_sclk_vpll = {
251 .sources = clkset_sclk_vpll_list,
252 .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list),
255 static struct clksrc_clk clk_sclk_vpll = {
260 .sources = &clkset_sclk_vpll,
261 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
264 static struct clk *clkset_moutdmc0src_list[] = {
265 [0] = &clk_sclk_a2m.clk,
266 [1] = &clk_mout_mpll.clk,
271 static struct clksrc_sources clkset_moutdmc0src = {
272 .sources = clkset_moutdmc0src_list,
273 .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list),
276 static struct clksrc_clk clk_mout_dmc0 = {
281 .sources = &clkset_moutdmc0src,
282 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
285 static struct clksrc_clk clk_sclk_dmc0 = {
289 .parent = &clk_mout_dmc0.clk,
291 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
294 static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
296 return clk_get_rate(clk->parent) / 2;
299 static struct clk_ops clk_hclk_imem_ops = {
300 .get_rate = s5pv210_clk_imem_get_rate,
303 static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk)
305 return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
308 static struct clk_ops clk_fout_apll_ops = {
309 .get_rate = s5pv210_clk_fout_apll_get_rate,
312 static struct clk init_clocks_disable[] = {
316 .parent = &clk_hclk_psys.clk,
317 .enable = s5pv210_clk_ip0_ctrl,
322 .parent = &clk_hclk_psys.clk,
323 .enable = s5pv210_clk_ip0_ctrl,
328 .parent = &clk_hclk_dsys.clk,
329 .enable = s5pv210_clk_ip0_ctrl,
334 .parent = &clk_hclk_dsys.clk,
335 .enable = s5pv210_clk_ip0_ctrl,
336 .ctrlbit = (1 << 24),
340 .parent = &clk_hclk_dsys.clk,
341 .enable = s5pv210_clk_ip0_ctrl,
342 .ctrlbit = (1 << 25),
346 .parent = &clk_hclk_dsys.clk,
347 .enable = s5pv210_clk_ip0_ctrl,
348 .ctrlbit = (1 << 26),
352 .parent = &clk_hclk_psys.clk,
353 .enable = s5pv210_clk_ip1_ctrl,
358 .parent = &clk_hclk_psys.clk,
359 .enable = s5pv210_clk_ip1_ctrl,
364 .parent = &clk_hclk_dsys.clk,
365 .enable = s5pv210_clk_ip1_ctrl,
370 .parent = &clk_hclk_psys.clk,
371 .enable = s5pv210_clk_ip1_ctrl,
376 .parent = &clk_hclk_psys.clk,
377 .enable = s5pv210_clk_ip2_ctrl,
382 .parent = &clk_hclk_psys.clk,
383 .enable = s5pv210_clk_ip2_ctrl,
388 .parent = &clk_hclk_psys.clk,
389 .enable = s5pv210_clk_ip2_ctrl,
394 .parent = &clk_hclk_psys.clk,
395 .enable = s5pv210_clk_ip2_ctrl,
400 .parent = &clk_pclk_psys.clk,
401 .enable = s5pv210_clk_ip3_ctrl,
406 .parent = &clk_pclk_psys.clk,
407 .enable = s5pv210_clk_ip3_ctrl,
412 .parent = &clk_pclk_psys.clk,
413 .enable = s5pv210_clk_ip3_ctrl,
418 .parent = &clk_pclk_psys.clk,
419 .enable = s5pv210_clk_ip3_ctrl,
424 .parent = &clk_pclk_psys.clk,
425 .enable = s5pv210_clk_ip3_ctrl,
426 .ctrlbit = (1 << 10),
430 .parent = &clk_pclk_psys.clk,
431 .enable = s5pv210_clk_ip3_ctrl,
436 .parent = &clk_pclk_psys.clk,
437 .enable = s5pv210_clk_ip3_ctrl,
442 .parent = &clk_pclk_psys.clk,
443 .enable = s5pv210_clk_ip3_ctrl,
448 .parent = &clk_pclk_psys.clk,
449 .enable = s5pv210_clk_ip3_ctrl,
454 .parent = &clk_pclk_psys.clk,
455 .enable = s5pv210_clk_ip3_ctrl,
460 .parent = &clk_pclk_psys.clk,
461 .enable = s5pv210_clk_ip3_ctrl,
466 .parent = &clk_pclk_psys.clk,
467 .enable = s5pv210_clk_ip3_ctrl,
473 .enable = s5pv210_clk_ip3_ctrl,
479 .enable = s5pv210_clk_ip3_ctrl,
485 .enable = s5pv210_clk_ip3_ctrl,
491 .enable = s5pv210_clk_ip3_ctrl,
496 static struct clk init_clocks[] = {
500 .parent = &clk_hclk_msys.clk,
502 .enable = s5pv210_clk_ip0_ctrl,
503 .ops = &clk_hclk_imem_ops,
507 .parent = &clk_pclk_psys.clk,
508 .enable = s5pv210_clk_ip3_ctrl,
509 .ctrlbit = (1 << 17),
513 .parent = &clk_pclk_psys.clk,
514 .enable = s5pv210_clk_ip3_ctrl,
515 .ctrlbit = (1 << 18),
519 .parent = &clk_pclk_psys.clk,
520 .enable = s5pv210_clk_ip3_ctrl,
521 .ctrlbit = (1 << 19),
525 .parent = &clk_pclk_psys.clk,
526 .enable = s5pv210_clk_ip3_ctrl,
527 .ctrlbit = (1 << 20),
531 static struct clk *clkset_uart_list[] = {
532 [6] = &clk_mout_mpll.clk,
533 [7] = &clk_mout_epll.clk,
536 static struct clksrc_sources clkset_uart = {
537 .sources = clkset_uart_list,
538 .nr_sources = ARRAY_SIZE(clkset_uart_list),
541 static struct clk *clkset_group1_list[] = {
542 [0] = &clk_sclk_a2m.clk,
543 [1] = &clk_mout_mpll.clk,
544 [2] = &clk_mout_epll.clk,
545 [3] = &clk_sclk_vpll.clk,
548 static struct clksrc_sources clkset_group1 = {
549 .sources = clkset_group1_list,
550 .nr_sources = ARRAY_SIZE(clkset_group1_list),
553 static struct clk *clkset_sclk_onenand_list[] = {
554 [0] = &clk_hclk_psys.clk,
555 [1] = &clk_hclk_dsys.clk,
558 static struct clksrc_sources clkset_sclk_onenand = {
559 .sources = clkset_sclk_onenand_list,
560 .nr_sources = ARRAY_SIZE(clkset_sclk_onenand_list),
563 static struct clk *clkset_sclk_dac_list[] = {
564 [0] = &clk_sclk_vpll.clk,
565 [1] = &clk_sclk_hdmiphy,
568 static struct clksrc_sources clkset_sclk_dac = {
569 .sources = clkset_sclk_dac_list,
570 .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list),
573 static struct clksrc_clk clk_sclk_dac = {
577 .enable = s5pv210_clk_mask0_ctrl,
580 .sources = &clkset_sclk_dac,
581 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 1 },
584 static struct clksrc_clk clk_sclk_pixel = {
586 .name = "sclk_pixel",
588 .parent = &clk_sclk_vpll.clk,
590 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
593 static struct clk *clkset_sclk_hdmi_list[] = {
594 [0] = &clk_sclk_pixel.clk,
595 [1] = &clk_sclk_hdmiphy,
598 static struct clksrc_sources clkset_sclk_hdmi = {
599 .sources = clkset_sclk_hdmi_list,
600 .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list),
603 static struct clksrc_clk clk_sclk_hdmi = {
607 .enable = s5pv210_clk_mask0_ctrl,
610 .sources = &clkset_sclk_hdmi,
611 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
614 static struct clk *clkset_sclk_mixer_list[] = {
615 [0] = &clk_sclk_dac.clk,
616 [1] = &clk_sclk_hdmi.clk,
619 static struct clksrc_sources clkset_sclk_mixer = {
620 .sources = clkset_sclk_mixer_list,
621 .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
624 static struct clk *clkset_sclk_audio0_list[] = {
625 [0] = &clk_ext_xtal_mux,
626 [1] = &clk_pcmcdclk0,
627 [2] = &clk_sclk_hdmi27m,
628 [3] = &clk_sclk_usbphy0,
629 [4] = &clk_sclk_usbphy1,
630 [5] = &clk_sclk_hdmiphy,
631 [6] = &clk_mout_mpll.clk,
632 [7] = &clk_mout_epll.clk,
633 [8] = &clk_sclk_vpll.clk,
636 static struct clksrc_sources clkset_sclk_audio0 = {
637 .sources = clkset_sclk_audio0_list,
638 .nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list),
641 static struct clksrc_clk clk_sclk_audio0 = {
643 .name = "sclk_audio",
645 .enable = s5pv210_clk_mask0_ctrl,
646 .ctrlbit = (1 << 24),
648 .sources = &clkset_sclk_audio0,
649 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 0, .size = 4 },
650 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 },
653 static struct clk *clkset_sclk_audio1_list[] = {
654 [0] = &clk_ext_xtal_mux,
655 [1] = &clk_pcmcdclk1,
656 [2] = &clk_sclk_hdmi27m,
657 [3] = &clk_sclk_usbphy0,
658 [4] = &clk_sclk_usbphy1,
659 [5] = &clk_sclk_hdmiphy,
660 [6] = &clk_mout_mpll.clk,
661 [7] = &clk_mout_epll.clk,
662 [8] = &clk_sclk_vpll.clk,
665 static struct clksrc_sources clkset_sclk_audio1 = {
666 .sources = clkset_sclk_audio1_list,
667 .nr_sources = ARRAY_SIZE(clkset_sclk_audio1_list),
670 static struct clksrc_clk clk_sclk_audio1 = {
672 .name = "sclk_audio",
674 .enable = s5pv210_clk_mask0_ctrl,
675 .ctrlbit = (1 << 25),
677 .sources = &clkset_sclk_audio1,
678 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 4, .size = 4 },
679 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 4, .size = 4 },
682 static struct clk *clkset_sclk_audio2_list[] = {
683 [0] = &clk_ext_xtal_mux,
684 [1] = &clk_pcmcdclk0,
685 [2] = &clk_sclk_hdmi27m,
686 [3] = &clk_sclk_usbphy0,
687 [4] = &clk_sclk_usbphy1,
688 [5] = &clk_sclk_hdmiphy,
689 [6] = &clk_mout_mpll.clk,
690 [7] = &clk_mout_epll.clk,
691 [8] = &clk_sclk_vpll.clk,
694 static struct clksrc_sources clkset_sclk_audio2 = {
695 .sources = clkset_sclk_audio2_list,
696 .nr_sources = ARRAY_SIZE(clkset_sclk_audio2_list),
699 static struct clksrc_clk clk_sclk_audio2 = {
701 .name = "sclk_audio",
703 .enable = s5pv210_clk_mask0_ctrl,
704 .ctrlbit = (1 << 26),
706 .sources = &clkset_sclk_audio2,
707 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 8, .size = 4 },
708 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 8, .size = 4 },
711 static struct clk *clkset_sclk_spdif_list[] = {
712 [0] = &clk_sclk_audio0.clk,
713 [1] = &clk_sclk_audio1.clk,
714 [2] = &clk_sclk_audio2.clk,
717 static struct clksrc_sources clkset_sclk_spdif = {
718 .sources = clkset_sclk_spdif_list,
719 .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list),
722 static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate)
727 pclk = clk_get_parent(clk);
731 ret = pclk->ops->set_rate(pclk, rate);
737 static unsigned long s5pv210_spdif_get_rate(struct clk *clk)
742 pclk = clk_get_parent(clk);
746 rate = pclk->ops->get_rate(clk);
752 static struct clk_ops s5pv210_sclk_spdif_ops = {
753 .set_rate = s5pv210_spdif_set_rate,
754 .get_rate = s5pv210_spdif_get_rate,
757 static struct clksrc_clk clk_sclk_spdif = {
759 .name = "sclk_spdif",
761 .enable = s5pv210_clk_mask0_ctrl,
762 .ctrlbit = (1 << 27),
763 .ops = &s5pv210_sclk_spdif_ops,
765 .sources = &clkset_sclk_spdif,
766 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
769 static struct clk *clkset_group2_list[] = {
770 [0] = &clk_ext_xtal_mux,
772 [2] = &clk_sclk_hdmi27m,
773 [3] = &clk_sclk_usbphy0,
774 [4] = &clk_sclk_usbphy1,
775 [5] = &clk_sclk_hdmiphy,
776 [6] = &clk_mout_mpll.clk,
777 [7] = &clk_mout_epll.clk,
778 [8] = &clk_sclk_vpll.clk,
781 static struct clksrc_sources clkset_group2 = {
782 .sources = clkset_group2_list,
783 .nr_sources = ARRAY_SIZE(clkset_group2_list),
786 static struct clksrc_clk clksrcs[] = {
792 .sources = &clkset_group1,
793 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
794 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
797 .name = "sclk_onenand",
800 .sources = &clkset_sclk_onenand,
801 .reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
802 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
807 .enable = s5pv210_clk_mask0_ctrl,
808 .ctrlbit = (1 << 12),
810 .sources = &clkset_uart,
811 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
812 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
817 .enable = s5pv210_clk_mask0_ctrl,
818 .ctrlbit = (1 << 13),
820 .sources = &clkset_uart,
821 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
822 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
827 .enable = s5pv210_clk_mask0_ctrl,
828 .ctrlbit = (1 << 14),
830 .sources = &clkset_uart,
831 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
832 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
837 .enable = s5pv210_clk_mask0_ctrl,
838 .ctrlbit = (1 << 15),
840 .sources = &clkset_uart,
841 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
842 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
845 .name = "sclk_mixer",
847 .enable = s5pv210_clk_mask0_ctrl,
850 .sources = &clkset_sclk_mixer,
851 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
856 .enable = s5pv210_clk_mask1_ctrl,
859 .sources = &clkset_group2,
860 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 4 },
861 .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
866 .enable = s5pv210_clk_mask1_ctrl,
869 .sources = &clkset_group2,
870 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 4 },
871 .reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
876 .enable = s5pv210_clk_mask1_ctrl,
879 .sources = &clkset_group2,
880 .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 4 },
881 .reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
886 .enable = s5pv210_clk_mask0_ctrl,
889 .sources = &clkset_group2,
890 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 4 },
891 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
896 .enable = s5pv210_clk_mask0_ctrl,
899 .sources = &clkset_group2,
900 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 4 },
901 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 4 },
906 .enable = s5pv210_clk_mask0_ctrl,
909 .sources = &clkset_group2,
910 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
911 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 },
916 .enable = s5pv210_clk_mask0_ctrl,
919 .sources = &clkset_group2,
920 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
921 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
926 .enable = s5pv210_clk_mask0_ctrl,
929 .sources = &clkset_group2,
930 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
931 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
936 .enable = s5pv210_clk_mask0_ctrl,
937 .ctrlbit = (1 << 10),
939 .sources = &clkset_group2,
940 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
941 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
946 .enable = s5pv210_clk_mask0_ctrl,
947 .ctrlbit = (1 << 11),
949 .sources = &clkset_group2,
950 .reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
951 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
956 .enable = s5pv210_clk_ip0_ctrl,
957 .ctrlbit = (1 << 16),
959 .sources = &clkset_group1,
960 .reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
961 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
966 .enable = s5pv210_clk_ip0_ctrl,
967 .ctrlbit = (1 << 12),
969 .sources = &clkset_group1,
970 .reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
971 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
976 .enable = s5pv210_clk_ip0_ctrl,
979 .sources = &clkset_group1,
980 .reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
981 .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
986 .enable = s5pv210_clk_mask0_ctrl,
989 .sources = &clkset_group2,
990 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
991 .reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
996 .enable = s5pv210_clk_mask0_ctrl,
997 .ctrlbit = (1 << 16),
999 .sources = &clkset_group2,
1000 .reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
1001 .reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
1006 .enable = s5pv210_clk_mask0_ctrl,
1007 .ctrlbit = (1 << 17),
1009 .sources = &clkset_group2,
1010 .reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
1011 .reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
1016 .enable = s5pv210_clk_mask0_ctrl,
1017 .ctrlbit = (1 << 29),
1019 .sources = &clkset_group2,
1020 .reg_src = { .reg = S5P_CLK_SRC6, .shift = 20, .size = 4 },
1021 .reg_div = { .reg = S5P_CLK_DIV6, .shift = 24, .size = 4 },
1026 .enable = s5pv210_clk_mask0_ctrl,
1027 .ctrlbit = (1 << 19),
1029 .sources = &clkset_group2,
1030 .reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 },
1031 .reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 },
1035 /* Clock initialisation code */
1036 static struct clksrc_clk *sysclks[] = {
1061 static u32 epll_div[][6] = {
1062 { 48000000, 0, 48, 3, 3, 0 },
1063 { 96000000, 0, 48, 3, 2, 0 },
1064 { 144000000, 1, 72, 3, 2, 0 },
1065 { 192000000, 0, 48, 3, 1, 0 },
1066 { 288000000, 1, 72, 3, 1, 0 },
1067 { 32750000, 1, 65, 3, 4, 35127 },
1068 { 32768000, 1, 65, 3, 4, 35127 },
1069 { 45158400, 0, 45, 3, 3, 10355 },
1070 { 45000000, 0, 45, 3, 3, 10355 },
1071 { 45158000, 0, 45, 3, 3, 10355 },
1072 { 49125000, 0, 49, 3, 3, 9961 },
1073 { 49152000, 0, 49, 3, 3, 9961 },
1074 { 67737600, 1, 67, 3, 3, 48366 },
1075 { 67738000, 1, 67, 3, 3, 48366 },
1076 { 73800000, 1, 73, 3, 3, 47710 },
1077 { 73728000, 1, 73, 3, 3, 47710 },
1078 { 36000000, 1, 32, 3, 4, 0 },
1079 { 60000000, 1, 60, 3, 3, 0 },
1080 { 72000000, 1, 72, 3, 3, 0 },
1081 { 80000000, 1, 80, 3, 3, 0 },
1082 { 84000000, 0, 42, 3, 2, 0 },
1083 { 50000000, 0, 50, 3, 3, 0 },
1086 static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate)
1088 unsigned int epll_con, epll_con_k;
1091 /* Return if nothing changed */
1092 if (clk->rate == rate)
1095 epll_con = __raw_readl(S5P_EPLL_CON);
1096 epll_con_k = __raw_readl(S5P_EPLL_CON1);
1098 epll_con_k &= ~PLL46XX_KDIV_MASK;
1099 epll_con &= ~(1 << 27 |
1100 PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |
1101 PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |
1102 PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
1104 for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
1105 if (epll_div[i][0] == rate) {
1106 epll_con_k |= epll_div[i][5] << 0;
1107 epll_con |= (epll_div[i][1] << 27 |
1108 epll_div[i][2] << PLL46XX_MDIV_SHIFT |
1109 epll_div[i][3] << PLL46XX_PDIV_SHIFT |
1110 epll_div[i][4] << PLL46XX_SDIV_SHIFT);
1115 if (i == ARRAY_SIZE(epll_div)) {
1116 printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
1121 __raw_writel(epll_con, S5P_EPLL_CON);
1122 __raw_writel(epll_con_k, S5P_EPLL_CON1);
1124 printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
1132 static struct clk_ops s5pv210_epll_ops = {
1133 .set_rate = s5pv210_epll_set_rate,
1134 .get_rate = s5p_epll_get_rate,
1137 void __init_or_cpufreq s5pv210_setup_clocks(void)
1139 struct clk *xtal_clk;
1140 unsigned long vpllsrc;
1141 unsigned long armclk;
1142 unsigned long hclk_msys;
1143 unsigned long hclk_dsys;
1144 unsigned long hclk_psys;
1145 unsigned long pclk_msys;
1146 unsigned long pclk_dsys;
1147 unsigned long pclk_psys;
1153 u32 clkdiv0, clkdiv1;
1155 /* Set functions for clk_fout_epll */
1156 clk_fout_epll.enable = s5p_epll_enable;
1157 clk_fout_epll.ops = &s5pv210_epll_ops;
1159 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
1161 clkdiv0 = __raw_readl(S5P_CLK_DIV0);
1162 clkdiv1 = __raw_readl(S5P_CLK_DIV1);
1164 printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
1165 __func__, clkdiv0, clkdiv1);
1167 xtal_clk = clk_get(NULL, "xtal");
1168 BUG_ON(IS_ERR(xtal_clk));
1170 xtal = clk_get_rate(xtal_clk);
1173 printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
1175 apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
1176 mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
1177 epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON),
1178 __raw_readl(S5P_EPLL_CON1), pll_4600);
1179 vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
1180 vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
1182 clk_fout_apll.ops = &clk_fout_apll_ops;
1183 clk_fout_mpll.rate = mpll;
1184 clk_fout_epll.rate = epll;
1185 clk_fout_vpll.rate = vpll;
1187 printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
1188 apll, mpll, epll, vpll);
1190 armclk = clk_get_rate(&clk_armclk.clk);
1191 hclk_msys = clk_get_rate(&clk_hclk_msys.clk);
1192 hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk);
1193 hclk_psys = clk_get_rate(&clk_hclk_psys.clk);
1194 pclk_msys = clk_get_rate(&clk_pclk_msys.clk);
1195 pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk);
1196 pclk_psys = clk_get_rate(&clk_pclk_psys.clk);
1198 printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
1199 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
1200 armclk, hclk_msys, hclk_dsys, hclk_psys,
1201 pclk_msys, pclk_dsys, pclk_psys);
1203 clk_f.rate = armclk;
1204 clk_h.rate = hclk_psys;
1205 clk_p.rate = pclk_psys;
1207 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
1208 s3c_set_clksrc(&clksrcs[ptr], true);
1211 static struct clk *clks[] __initdata = {
1221 void __init s5pv210_register_clocks(void)
1227 ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
1229 printk(KERN_ERR "Failed to register %u clocks\n", ret);
1231 for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
1232 s3c_register_clksrc(sysclks[ptr], 1);
1234 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
1235 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
1237 clkp = init_clocks_disable;
1238 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
1239 ret = s3c24xx_register_clock(clkp);
1241 printk(KERN_ERR "Failed to register clock %s (%d)\n",
1244 (clkp->enable)(clkp, 0);