2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
5 * Clock support for EXYNOS5 SoCs
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/kernel.h>
13 #include <linux/err.h>
15 #include <linux/syscore_ops.h>
17 #include <plat/cpu-freq.h>
18 #include <plat/clock.h>
21 #include <plat/s5p-clock.h>
22 #include <plat/clock-clksrc.h>
26 #include <mach/regs-clock.h>
27 #include <mach/sysmmu.h>
31 #ifdef CONFIG_PM_SLEEP
32 static struct sleep_save exynos5_clock_save[] = {
33 /* will be implemented */
37 static struct clk exynos5_clk_sclk_dptxphy = {
41 static struct clk exynos5_clk_sclk_hdmi24m = {
42 .name = "sclk_hdmi24m",
46 static struct clk exynos5_clk_sclk_hdmi27m = {
47 .name = "sclk_hdmi27m",
51 static struct clk exynos5_clk_sclk_hdmiphy = {
52 .name = "sclk_hdmiphy",
55 static struct clk exynos5_clk_sclk_usbphy = {
56 .name = "sclk_usbphy",
60 static int exynos5_clksrc_mask_top_ctrl(struct clk *clk, int enable)
62 return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_TOP, clk, enable);
65 static int exynos5_clksrc_mask_disp1_0_ctrl(struct clk *clk, int enable)
67 return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_DISP1_0, clk, enable);
70 static int exynos5_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
72 return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_FSYS, clk, enable);
75 static int exynos5_clksrc_mask_gscl_ctrl(struct clk *clk, int enable)
77 return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_GSCL, clk, enable);
80 static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
82 return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
85 static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable)
87 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable);
90 static int exynos5_clk_ip_disp1_ctrl(struct clk *clk, int enable)
92 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_DISP1, clk, enable);
95 static int exynos5_clk_ip_fsys_ctrl(struct clk *clk, int enable)
97 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_FSYS, clk, enable);
100 static int exynos5_clk_block_ctrl(struct clk *clk, int enable)
102 return s5p_gatectrl(EXYNOS5_CLKGATE_BLOCK, clk, enable);
105 static int exynos5_clk_ip_gen_ctrl(struct clk *clk, int enable)
107 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GEN, clk, enable);
110 static int exynos5_clk_ip_gps_ctrl(struct clk *clk, int enable)
112 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GPS, clk, enable);
115 static int exynos5_clk_ip_mfc_ctrl(struct clk *clk, int enable)
117 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_MFC, clk, enable);
120 static int exynos5_clk_ip_peric_ctrl(struct clk *clk, int enable)
122 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIC, clk, enable);
125 static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable)
127 return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable);
130 /* Core list of CMU_CPU side */
132 static struct clksrc_clk exynos5_clk_mout_apll = {
136 .sources = &clk_src_apll,
137 .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 0, .size = 1 },
140 static struct clksrc_clk exynos5_clk_sclk_apll = {
143 .parent = &exynos5_clk_mout_apll.clk,
145 .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 24, .size = 3 },
148 static struct clksrc_clk exynos5_clk_mout_bpll = {
152 .sources = &clk_src_bpll,
153 .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 0, .size = 1 },
156 static struct clk *exynos5_clk_src_bpll_user_list[] = {
158 [1] = &exynos5_clk_mout_bpll.clk,
161 static struct clksrc_sources exynos5_clk_src_bpll_user = {
162 .sources = exynos5_clk_src_bpll_user_list,
163 .nr_sources = ARRAY_SIZE(exynos5_clk_src_bpll_user_list),
166 static struct clksrc_clk exynos5_clk_mout_bpll_user = {
168 .name = "mout_bpll_user",
170 .sources = &exynos5_clk_src_bpll_user,
171 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 24, .size = 1 },
174 static struct clksrc_clk exynos5_clk_mout_cpll = {
178 .sources = &clk_src_cpll,
179 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 8, .size = 1 },
182 static struct clksrc_clk exynos5_clk_mout_epll = {
186 .sources = &clk_src_epll,
187 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 12, .size = 1 },
190 struct clksrc_clk exynos5_clk_mout_mpll = {
194 .sources = &clk_src_mpll,
195 .reg_src = { .reg = EXYNOS5_CLKSRC_CORE1, .shift = 8, .size = 1 },
198 static struct clk *exynos_clkset_vpllsrc_list[] = {
200 [1] = &exynos5_clk_sclk_hdmi27m,
203 static struct clksrc_sources exynos5_clkset_vpllsrc = {
204 .sources = exynos_clkset_vpllsrc_list,
205 .nr_sources = ARRAY_SIZE(exynos_clkset_vpllsrc_list),
208 static struct clksrc_clk exynos5_clk_vpllsrc = {
211 .enable = exynos5_clksrc_mask_top_ctrl,
214 .sources = &exynos5_clkset_vpllsrc,
215 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 0, .size = 1 },
218 static struct clk *exynos5_clkset_sclk_vpll_list[] = {
219 [0] = &exynos5_clk_vpllsrc.clk,
220 [1] = &clk_fout_vpll,
223 static struct clksrc_sources exynos5_clkset_sclk_vpll = {
224 .sources = exynos5_clkset_sclk_vpll_list,
225 .nr_sources = ARRAY_SIZE(exynos5_clkset_sclk_vpll_list),
228 static struct clksrc_clk exynos5_clk_sclk_vpll = {
232 .sources = &exynos5_clkset_sclk_vpll,
233 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 16, .size = 1 },
236 static struct clksrc_clk exynos5_clk_sclk_pixel = {
238 .name = "sclk_pixel",
239 .parent = &exynos5_clk_sclk_vpll.clk,
241 .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 28, .size = 4 },
244 static struct clk *exynos5_clkset_sclk_hdmi_list[] = {
245 [0] = &exynos5_clk_sclk_pixel.clk,
246 [1] = &exynos5_clk_sclk_hdmiphy,
249 static struct clksrc_sources exynos5_clkset_sclk_hdmi = {
250 .sources = exynos5_clkset_sclk_hdmi_list,
251 .nr_sources = ARRAY_SIZE(exynos5_clkset_sclk_hdmi_list),
254 static struct clksrc_clk exynos5_clk_sclk_hdmi = {
257 .enable = exynos5_clksrc_mask_disp1_0_ctrl,
258 .ctrlbit = (1 << 20),
260 .sources = &exynos5_clkset_sclk_hdmi,
261 .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 20, .size = 1 },
264 static struct clksrc_clk *exynos5_sclk_tv[] = {
265 &exynos5_clk_sclk_pixel,
266 &exynos5_clk_sclk_hdmi,
269 static struct clk *exynos5_clk_src_mpll_user_list[] = {
271 [1] = &exynos5_clk_mout_mpll.clk,
274 static struct clksrc_sources exynos5_clk_src_mpll_user = {
275 .sources = exynos5_clk_src_mpll_user_list,
276 .nr_sources = ARRAY_SIZE(exynos5_clk_src_mpll_user_list),
279 static struct clksrc_clk exynos5_clk_mout_mpll_user = {
281 .name = "mout_mpll_user",
283 .sources = &exynos5_clk_src_mpll_user,
284 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 20, .size = 1 },
287 static struct clk *exynos5_clkset_mout_cpu_list[] = {
288 [0] = &exynos5_clk_mout_apll.clk,
289 [1] = &exynos5_clk_mout_mpll.clk,
292 static struct clksrc_sources exynos5_clkset_mout_cpu = {
293 .sources = exynos5_clkset_mout_cpu_list,
294 .nr_sources = ARRAY_SIZE(exynos5_clkset_mout_cpu_list),
297 static struct clksrc_clk exynos5_clk_mout_cpu = {
301 .sources = &exynos5_clkset_mout_cpu,
302 .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 16, .size = 1 },
305 static struct clksrc_clk exynos5_clk_dout_armclk = {
307 .name = "dout_armclk",
308 .parent = &exynos5_clk_mout_cpu.clk,
310 .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 0, .size = 3 },
313 static struct clksrc_clk exynos5_clk_dout_arm2clk = {
315 .name = "dout_arm2clk",
316 .parent = &exynos5_clk_dout_armclk.clk,
318 .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 28, .size = 3 },
321 static struct clk exynos5_clk_armclk = {
323 .parent = &exynos5_clk_dout_arm2clk.clk,
326 /* Core list of CMU_CDREX side */
328 static struct clk *exynos5_clkset_cdrex_list[] = {
329 [0] = &exynos5_clk_mout_mpll.clk,
330 [1] = &exynos5_clk_mout_bpll.clk,
333 static struct clksrc_sources exynos5_clkset_cdrex = {
334 .sources = exynos5_clkset_cdrex_list,
335 .nr_sources = ARRAY_SIZE(exynos5_clkset_cdrex_list),
338 static struct clksrc_clk exynos5_clk_cdrex = {
342 .sources = &exynos5_clkset_cdrex,
343 .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 4, .size = 1 },
344 .reg_div = { .reg = EXYNOS5_CLKDIV_CDREX, .shift = 16, .size = 3 },
347 static struct clksrc_clk exynos5_clk_aclk_acp = {
350 .parent = &exynos5_clk_mout_mpll.clk,
352 .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 0, .size = 3 },
355 static struct clksrc_clk exynos5_clk_pclk_acp = {
358 .parent = &exynos5_clk_aclk_acp.clk,
360 .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 4, .size = 3 },
363 /* Core list of CMU_TOP side */
365 struct clk *exynos5_clkset_aclk_top_list[] = {
366 [0] = &exynos5_clk_mout_mpll_user.clk,
367 [1] = &exynos5_clk_mout_bpll_user.clk,
370 struct clksrc_sources exynos5_clkset_aclk = {
371 .sources = exynos5_clkset_aclk_top_list,
372 .nr_sources = ARRAY_SIZE(exynos5_clkset_aclk_top_list),
375 static struct clksrc_clk exynos5_clk_aclk_400 = {
379 .sources = &exynos5_clkset_aclk,
380 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
381 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
384 struct clk *exynos5_clkset_aclk_333_166_list[] = {
385 [0] = &exynos5_clk_mout_cpll.clk,
386 [1] = &exynos5_clk_mout_mpll_user.clk,
389 struct clksrc_sources exynos5_clkset_aclk_333_166 = {
390 .sources = exynos5_clkset_aclk_333_166_list,
391 .nr_sources = ARRAY_SIZE(exynos5_clkset_aclk_333_166_list),
394 static struct clksrc_clk exynos5_clk_aclk_333 = {
398 .sources = &exynos5_clkset_aclk_333_166,
399 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 16, .size = 1 },
400 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 20, .size = 3 },
403 static struct clksrc_clk exynos5_clk_aclk_166 = {
407 .sources = &exynos5_clkset_aclk_333_166,
408 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 8, .size = 1 },
409 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 8, .size = 3 },
412 static struct clksrc_clk exynos5_clk_aclk_266 = {
415 .parent = &exynos5_clk_mout_mpll_user.clk,
417 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 16, .size = 3 },
420 static struct clksrc_clk exynos5_clk_aclk_200 = {
424 .sources = &exynos5_clkset_aclk,
425 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 12, .size = 1 },
426 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 12, .size = 3 },
429 static struct clksrc_clk exynos5_clk_aclk_66_pre = {
431 .name = "aclk_66_pre",
432 .parent = &exynos5_clk_mout_mpll_user.clk,
434 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP1, .shift = 24, .size = 3 },
437 static struct clksrc_clk exynos5_clk_aclk_66 = {
440 .parent = &exynos5_clk_aclk_66_pre.clk,
442 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 0, .size = 3 },
445 static struct clk exynos5_init_clocks_off[] = {
448 .parent = &exynos5_clk_aclk_66.clk,
449 .enable = exynos5_clk_ip_peric_ctrl,
450 .ctrlbit = (1 << 24),
453 .parent = &exynos5_clk_aclk_66.clk,
454 .enable = exynos5_clk_ip_peris_ctrl,
455 .ctrlbit = (1 << 20),
458 .devname = "exynos4-sdhci.0",
459 .parent = &exynos5_clk_aclk_200.clk,
460 .enable = exynos5_clk_ip_fsys_ctrl,
461 .ctrlbit = (1 << 12),
464 .devname = "exynos4-sdhci.1",
465 .parent = &exynos5_clk_aclk_200.clk,
466 .enable = exynos5_clk_ip_fsys_ctrl,
467 .ctrlbit = (1 << 13),
470 .devname = "exynos4-sdhci.2",
471 .parent = &exynos5_clk_aclk_200.clk,
472 .enable = exynos5_clk_ip_fsys_ctrl,
473 .ctrlbit = (1 << 14),
476 .devname = "exynos4-sdhci.3",
477 .parent = &exynos5_clk_aclk_200.clk,
478 .enable = exynos5_clk_ip_fsys_ctrl,
479 .ctrlbit = (1 << 15),
482 .parent = &exynos5_clk_aclk_200.clk,
483 .enable = exynos5_clk_ip_fsys_ctrl,
484 .ctrlbit = (1 << 16),
488 .enable = exynos5_clk_ip_fsys_ctrl,
492 .enable = exynos5_clk_ip_fsys_ctrl,
493 .ctrlbit = (1 << 24),
495 .name = "sata_phy_i2c",
496 .enable = exynos5_clk_ip_fsys_ctrl,
497 .ctrlbit = (1 << 25),
500 .devname = "s5p-mfc",
501 .enable = exynos5_clk_ip_mfc_ctrl,
505 .devname = "exynos4-hdmi",
506 .enable = exynos5_clk_ip_disp1_ctrl,
510 .devname = "s5p-mixer",
511 .enable = exynos5_clk_ip_disp1_ctrl,
515 .enable = exynos5_clk_ip_gen_ctrl,
519 .enable = exynos5_clk_ip_disp1_ctrl,
523 .devname = "samsung-i2s.1",
524 .enable = exynos5_clk_ip_peric_ctrl,
525 .ctrlbit = (1 << 20),
528 .devname = "samsung-i2s.2",
529 .enable = exynos5_clk_ip_peric_ctrl,
530 .ctrlbit = (1 << 21),
533 .devname = "samsung-pcm.1",
534 .enable = exynos5_clk_ip_peric_ctrl,
535 .ctrlbit = (1 << 22),
538 .devname = "samsung-pcm.2",
539 .enable = exynos5_clk_ip_peric_ctrl,
540 .ctrlbit = (1 << 23),
543 .devname = "samsung-spdif",
544 .enable = exynos5_clk_ip_peric_ctrl,
545 .ctrlbit = (1 << 26),
548 .devname = "samsung-ac97",
549 .enable = exynos5_clk_ip_peric_ctrl,
550 .ctrlbit = (1 << 27),
553 .enable = exynos5_clk_ip_fsys_ctrl ,
554 .ctrlbit = (1 << 18),
557 .enable = exynos5_clk_ip_fsys_ctrl,
561 .enable = exynos5_clk_ip_gps_ctrl,
562 .ctrlbit = ((1 << 3) | (1 << 2) | (1 << 0)),
565 .enable = exynos5_clk_ip_fsys_ctrl,
566 .ctrlbit = (1 << 22),
569 .enable = exynos5_clk_ip_fsys_ctrl,
570 .ctrlbit = ((1 << 30) | (1 << 26) | (1 << 23)),
573 .enable = exynos5_clk_ip_core_ctrl,
574 .ctrlbit = ((1 << 21) | (1 << 3)),
577 .enable = exynos5_clk_ip_fsys_ctrl,
581 .devname = "s3c2440-i2c.0",
582 .parent = &exynos5_clk_aclk_66.clk,
583 .enable = exynos5_clk_ip_peric_ctrl,
587 .devname = "s3c2440-i2c.1",
588 .parent = &exynos5_clk_aclk_66.clk,
589 .enable = exynos5_clk_ip_peric_ctrl,
593 .devname = "s3c2440-i2c.2",
594 .parent = &exynos5_clk_aclk_66.clk,
595 .enable = exynos5_clk_ip_peric_ctrl,
599 .devname = "s3c2440-i2c.3",
600 .parent = &exynos5_clk_aclk_66.clk,
601 .enable = exynos5_clk_ip_peric_ctrl,
605 .devname = "s3c2440-i2c.4",
606 .parent = &exynos5_clk_aclk_66.clk,
607 .enable = exynos5_clk_ip_peric_ctrl,
608 .ctrlbit = (1 << 10),
611 .devname = "s3c2440-i2c.5",
612 .parent = &exynos5_clk_aclk_66.clk,
613 .enable = exynos5_clk_ip_peric_ctrl,
614 .ctrlbit = (1 << 11),
617 .devname = "s3c2440-i2c.6",
618 .parent = &exynos5_clk_aclk_66.clk,
619 .enable = exynos5_clk_ip_peric_ctrl,
620 .ctrlbit = (1 << 12),
623 .devname = "s3c2440-i2c.7",
624 .parent = &exynos5_clk_aclk_66.clk,
625 .enable = exynos5_clk_ip_peric_ctrl,
626 .ctrlbit = (1 << 13),
629 .devname = "s3c2440-hdmiphy-i2c",
630 .parent = &exynos5_clk_aclk_66.clk,
631 .enable = exynos5_clk_ip_peric_ctrl,
632 .ctrlbit = (1 << 14),
636 static struct clk exynos5_init_clocks_on[] = {
639 .devname = "s5pv210-uart.0",
640 .enable = exynos5_clk_ip_peric_ctrl,
644 .devname = "s5pv210-uart.1",
645 .enable = exynos5_clk_ip_peric_ctrl,
649 .devname = "s5pv210-uart.2",
650 .enable = exynos5_clk_ip_peric_ctrl,
654 .devname = "s5pv210-uart.3",
655 .enable = exynos5_clk_ip_peric_ctrl,
659 .devname = "s5pv210-uart.4",
660 .enable = exynos5_clk_ip_peric_ctrl,
664 .devname = "s5pv210-uart.5",
665 .enable = exynos5_clk_ip_peric_ctrl,
670 static struct clk exynos5_clk_pdma0 = {
672 .devname = "dma-pl330.0",
673 .enable = exynos5_clk_ip_fsys_ctrl,
677 static struct clk exynos5_clk_pdma1 = {
679 .devname = "dma-pl330.1",
680 .enable = exynos5_clk_ip_fsys_ctrl,
684 static struct clk exynos5_clk_mdma1 = {
686 .devname = "dma-pl330.2",
687 .enable = exynos5_clk_ip_gen_ctrl,
691 struct clk *exynos5_clkset_group_list[] = {
692 [0] = &clk_ext_xtal_mux,
694 [2] = &exynos5_clk_sclk_hdmi24m,
695 [3] = &exynos5_clk_sclk_dptxphy,
696 [4] = &exynos5_clk_sclk_usbphy,
697 [5] = &exynos5_clk_sclk_hdmiphy,
698 [6] = &exynos5_clk_mout_mpll_user.clk,
699 [7] = &exynos5_clk_mout_epll.clk,
700 [8] = &exynos5_clk_sclk_vpll.clk,
701 [9] = &exynos5_clk_mout_cpll.clk,
704 struct clksrc_sources exynos5_clkset_group = {
705 .sources = exynos5_clkset_group_list,
706 .nr_sources = ARRAY_SIZE(exynos5_clkset_group_list),
709 /* Possible clock sources for aclk_266_gscl_sub Mux */
710 static struct clk *clk_src_gscl_266_list[] = {
711 [0] = &clk_ext_xtal_mux,
712 [1] = &exynos5_clk_aclk_266.clk,
715 static struct clksrc_sources clk_src_gscl_266 = {
716 .sources = clk_src_gscl_266_list,
717 .nr_sources = ARRAY_SIZE(clk_src_gscl_266_list),
720 static struct clksrc_clk exynos5_clk_dout_mmc0 = {
724 .sources = &exynos5_clkset_group,
725 .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 0, .size = 4 },
726 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 0, .size = 4 },
729 static struct clksrc_clk exynos5_clk_dout_mmc1 = {
733 .sources = &exynos5_clkset_group,
734 .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 4, .size = 4 },
735 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 16, .size = 4 },
738 static struct clksrc_clk exynos5_clk_dout_mmc2 = {
742 .sources = &exynos5_clkset_group,
743 .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 8, .size = 4 },
744 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 0, .size = 4 },
747 static struct clksrc_clk exynos5_clk_dout_mmc3 = {
751 .sources = &exynos5_clkset_group,
752 .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 12, .size = 4 },
753 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 16, .size = 4 },
756 static struct clksrc_clk exynos5_clk_dout_mmc4 = {
760 .sources = &exynos5_clkset_group,
761 .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 16, .size = 4 },
762 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 0, .size = 4 },
765 static struct clksrc_clk exynos5_clk_sclk_uart0 = {
768 .devname = "exynos4210-uart.0",
769 .enable = exynos5_clksrc_mask_peric0_ctrl,
772 .sources = &exynos5_clkset_group,
773 .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 0, .size = 4 },
774 .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 0, .size = 4 },
777 static struct clksrc_clk exynos5_clk_sclk_uart1 = {
780 .devname = "exynos4210-uart.1",
781 .enable = exynos5_clksrc_mask_peric0_ctrl,
784 .sources = &exynos5_clkset_group,
785 .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 4, .size = 4 },
786 .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 4, .size = 4 },
789 static struct clksrc_clk exynos5_clk_sclk_uart2 = {
792 .devname = "exynos4210-uart.2",
793 .enable = exynos5_clksrc_mask_peric0_ctrl,
796 .sources = &exynos5_clkset_group,
797 .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 8, .size = 4 },
798 .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 8, .size = 4 },
801 static struct clksrc_clk exynos5_clk_sclk_uart3 = {
804 .devname = "exynos4210-uart.3",
805 .enable = exynos5_clksrc_mask_peric0_ctrl,
806 .ctrlbit = (1 << 12),
808 .sources = &exynos5_clkset_group,
809 .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 12, .size = 4 },
810 .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 12, .size = 4 },
813 static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
816 .devname = "exynos4-sdhci.0",
817 .parent = &exynos5_clk_dout_mmc0.clk,
818 .enable = exynos5_clksrc_mask_fsys_ctrl,
821 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 8, .size = 8 },
824 static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
827 .devname = "exynos4-sdhci.1",
828 .parent = &exynos5_clk_dout_mmc1.clk,
829 .enable = exynos5_clksrc_mask_fsys_ctrl,
832 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 24, .size = 8 },
835 static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
838 .devname = "exynos4-sdhci.2",
839 .parent = &exynos5_clk_dout_mmc2.clk,
840 .enable = exynos5_clksrc_mask_fsys_ctrl,
843 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 8, .size = 8 },
846 static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
849 .devname = "exynos4-sdhci.3",
850 .parent = &exynos5_clk_dout_mmc3.clk,
851 .enable = exynos5_clksrc_mask_fsys_ctrl,
852 .ctrlbit = (1 << 12),
854 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 24, .size = 8 },
857 static struct clksrc_clk exynos5_clksrcs[] = {
860 .name = "sclk_dwmci",
861 .parent = &exynos5_clk_dout_mmc4.clk,
862 .enable = exynos5_clksrc_mask_fsys_ctrl,
863 .ctrlbit = (1 << 16),
865 .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 8, .size = 8 },
869 .devname = "s3cfb.1",
870 .enable = exynos5_clksrc_mask_disp1_0_ctrl,
873 .sources = &exynos5_clkset_group,
874 .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 0, .size = 4 },
875 .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 0, .size = 4 },
878 .name = "aclk_266_gscl",
880 .sources = &clk_src_gscl_266,
881 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 8, .size = 1 },
885 .devname = "mali-t604.0",
886 .enable = exynos5_clk_block_ctrl,
889 .sources = &exynos5_clkset_aclk,
890 .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
891 .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
894 .name = "sclk_gscl_wrap",
895 .devname = "s5p-mipi-csis.0",
896 .enable = exynos5_clksrc_mask_gscl_ctrl,
897 .ctrlbit = (1 << 24),
899 .sources = &exynos5_clkset_group,
900 .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 24, .size = 4 },
901 .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 24, .size = 4 },
904 .name = "sclk_gscl_wrap",
905 .devname = "s5p-mipi-csis.1",
906 .enable = exynos5_clksrc_mask_gscl_ctrl,
907 .ctrlbit = (1 << 28),
909 .sources = &exynos5_clkset_group,
910 .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 28, .size = 4 },
911 .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 28, .size = 4 },
915 .enable = exynos5_clksrc_mask_gscl_ctrl,
916 .ctrlbit = (1 << 16),
918 .sources = &exynos5_clkset_group,
919 .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 16, .size = 4 },
920 .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 16, .size = 4 },
924 .enable = exynos5_clksrc_mask_gscl_ctrl,
925 .ctrlbit = (1 << 20),
927 .sources = &exynos5_clkset_group,
928 .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 20, .size = 4 },
929 .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 20, .size = 4 },
933 .parent = &exynos5_clk_mout_cpll.clk,
935 .reg_div = { .reg = EXYNOS5_CLKDIV_GEN, .shift = 4, .size = 3 },
939 /* Clock initialization code */
940 static struct clksrc_clk *exynos5_sysclks[] = {
941 &exynos5_clk_mout_apll,
942 &exynos5_clk_sclk_apll,
943 &exynos5_clk_mout_bpll,
944 &exynos5_clk_mout_bpll_user,
945 &exynos5_clk_mout_cpll,
946 &exynos5_clk_mout_epll,
947 &exynos5_clk_mout_mpll,
948 &exynos5_clk_mout_mpll_user,
949 &exynos5_clk_vpllsrc,
950 &exynos5_clk_sclk_vpll,
951 &exynos5_clk_mout_cpu,
952 &exynos5_clk_dout_armclk,
953 &exynos5_clk_dout_arm2clk,
955 &exynos5_clk_aclk_400,
956 &exynos5_clk_aclk_333,
957 &exynos5_clk_aclk_266,
958 &exynos5_clk_aclk_200,
959 &exynos5_clk_aclk_166,
960 &exynos5_clk_aclk_66_pre,
961 &exynos5_clk_aclk_66,
962 &exynos5_clk_dout_mmc0,
963 &exynos5_clk_dout_mmc1,
964 &exynos5_clk_dout_mmc2,
965 &exynos5_clk_dout_mmc3,
966 &exynos5_clk_dout_mmc4,
967 &exynos5_clk_aclk_acp,
968 &exynos5_clk_pclk_acp,
971 static struct clk *exynos5_clk_cdev[] = {
977 static struct clksrc_clk *exynos5_clksrc_cdev[] = {
978 &exynos5_clk_sclk_uart0,
979 &exynos5_clk_sclk_uart1,
980 &exynos5_clk_sclk_uart2,
981 &exynos5_clk_sclk_uart3,
982 &exynos5_clk_sclk_mmc0,
983 &exynos5_clk_sclk_mmc1,
984 &exynos5_clk_sclk_mmc2,
985 &exynos5_clk_sclk_mmc3,
988 static struct clk_lookup exynos5_clk_lookup[] = {
989 CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos5_clk_sclk_uart0.clk),
990 CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos5_clk_sclk_uart1.clk),
991 CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos5_clk_sclk_uart2.clk),
992 CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos5_clk_sclk_uart3.clk),
993 CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
994 CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
995 CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
996 CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
997 CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
998 CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
999 CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
1002 static unsigned long exynos5_epll_get_rate(struct clk *clk)
1007 static struct clk *exynos5_clks[] __initdata = {
1008 &exynos5_clk_sclk_hdmi27m,
1009 &exynos5_clk_sclk_hdmiphy,
1012 &exynos5_clk_armclk,
1015 static u32 epll_div[][6] = {
1016 { 192000000, 0, 48, 3, 1, 0 },
1017 { 180000000, 0, 45, 3, 1, 0 },
1018 { 73728000, 1, 73, 3, 3, 47710 },
1019 { 67737600, 1, 90, 4, 3, 20762 },
1020 { 49152000, 0, 49, 3, 3, 9961 },
1021 { 45158400, 0, 45, 3, 3, 10381 },
1022 { 180633600, 0, 45, 3, 1, 10381 },
1025 static int exynos5_epll_set_rate(struct clk *clk, unsigned long rate)
1027 unsigned int epll_con, epll_con_k;
1030 unsigned int epll_rate;
1031 unsigned int locktime;
1032 unsigned int lockcnt;
1034 /* Return if nothing changed */
1035 if (clk->rate == rate)
1039 epll_rate = clk_get_rate(clk->parent);
1041 epll_rate = clk_ext_xtal_mux.rate;
1043 if (epll_rate != 24000000) {
1044 pr_err("Invalid Clock : recommended clock is 24MHz.\n");
1048 epll_con = __raw_readl(EXYNOS5_EPLL_CON0);
1049 epll_con &= ~(0x1 << 27 | \
1050 PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
1051 PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
1052 PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
1054 for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
1055 if (epll_div[i][0] == rate) {
1056 epll_con_k = epll_div[i][5] << 0;
1057 epll_con |= epll_div[i][1] << 27;
1058 epll_con |= epll_div[i][2] << PLL46XX_MDIV_SHIFT;
1059 epll_con |= epll_div[i][3] << PLL46XX_PDIV_SHIFT;
1060 epll_con |= epll_div[i][4] << PLL46XX_SDIV_SHIFT;
1065 if (i == ARRAY_SIZE(epll_div)) {
1066 printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
1071 epll_rate /= 1000000;
1073 /* 3000 max_cycls : specification data */
1074 locktime = 3000 / epll_rate * epll_div[i][3];
1075 lockcnt = locktime * 10000 / (10000 / epll_rate);
1077 __raw_writel(lockcnt, EXYNOS5_EPLL_LOCK);
1079 __raw_writel(epll_con, EXYNOS5_EPLL_CON0);
1080 __raw_writel(epll_con_k, EXYNOS5_EPLL_CON1);
1083 tmp = __raw_readl(EXYNOS5_EPLL_CON0);
1084 } while (!(tmp & 0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT));
1091 static struct clk_ops exynos5_epll_ops = {
1092 .get_rate = exynos5_epll_get_rate,
1093 .set_rate = exynos5_epll_set_rate,
1096 static int xtal_rate;
1098 static unsigned long exynos5_fout_apll_get_rate(struct clk *clk)
1100 return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS5_APLL_CON0));
1103 static struct clk_ops exynos5_fout_apll_ops = {
1104 .get_rate = exynos5_fout_apll_get_rate,
1108 static int exynos5_clock_suspend(void)
1110 s3c_pm_do_save(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
1115 static void exynos5_clock_resume(void)
1117 s3c_pm_do_restore_core(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
1120 #define exynos5_clock_suspend NULL
1121 #define exynos5_clock_resume NULL
1124 struct syscore_ops exynos5_clock_syscore_ops = {
1125 .suspend = exynos5_clock_suspend,
1126 .resume = exynos5_clock_resume,
1129 void __init_or_cpufreq exynos5_setup_clocks(void)
1131 struct clk *xtal_clk;
1138 unsigned long vpllsrc;
1140 unsigned long armclk;
1141 unsigned long mout_cdrex;
1142 unsigned long aclk_400;
1143 unsigned long aclk_333;
1144 unsigned long aclk_266;
1145 unsigned long aclk_200;
1146 unsigned long aclk_166;
1147 unsigned long aclk_66;
1150 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
1152 xtal_clk = clk_get(NULL, "xtal");
1153 BUG_ON(IS_ERR(xtal_clk));
1155 xtal = clk_get_rate(xtal_clk);
1161 printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
1163 apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_APLL_CON0));
1164 bpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_BPLL_CON0));
1165 cpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_CPLL_CON0));
1166 mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_MPLL_CON0));
1167 epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS5_EPLL_CON0),
1168 __raw_readl(EXYNOS5_EPLL_CON1));
1170 vpllsrc = clk_get_rate(&exynos5_clk_vpllsrc.clk);
1171 vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS5_VPLL_CON0),
1172 __raw_readl(EXYNOS5_VPLL_CON1));
1174 clk_fout_apll.ops = &exynos5_fout_apll_ops;
1175 clk_fout_bpll.rate = bpll;
1176 clk_fout_cpll.rate = cpll;
1177 clk_fout_mpll.rate = mpll;
1178 clk_fout_epll.rate = epll;
1179 clk_fout_vpll.rate = vpll;
1181 printk(KERN_INFO "EXYNOS5: PLL settings, A=%ld, B=%ld, C=%ld\n"
1182 "M=%ld, E=%ld V=%ld",
1183 apll, bpll, cpll, mpll, epll, vpll);
1185 armclk = clk_get_rate(&exynos5_clk_armclk);
1186 mout_cdrex = clk_get_rate(&exynos5_clk_cdrex.clk);
1188 aclk_400 = clk_get_rate(&exynos5_clk_aclk_400.clk);
1189 aclk_333 = clk_get_rate(&exynos5_clk_aclk_333.clk);
1190 aclk_266 = clk_get_rate(&exynos5_clk_aclk_266.clk);
1191 aclk_200 = clk_get_rate(&exynos5_clk_aclk_200.clk);
1192 aclk_166 = clk_get_rate(&exynos5_clk_aclk_166.clk);
1193 aclk_66 = clk_get_rate(&exynos5_clk_aclk_66.clk);
1195 printk(KERN_INFO "EXYNOS5: ARMCLK=%ld, CDREX=%ld, ACLK400=%ld\n"
1196 "ACLK333=%ld, ACLK266=%ld, ACLK200=%ld\n"
1197 "ACLK166=%ld, ACLK66=%ld\n",
1198 armclk, mout_cdrex, aclk_400,
1199 aclk_333, aclk_266, aclk_200,
1203 clk_fout_epll.ops = &exynos5_epll_ops;
1205 if (clk_set_parent(&exynos5_clk_mout_epll.clk, &clk_fout_epll))
1206 printk(KERN_ERR "Unable to set parent %s of clock %s.\n",
1207 clk_fout_epll.name, exynos5_clk_mout_epll.clk.name);
1209 clk_set_rate(&exynos5_clk_sclk_apll.clk, 100000000);
1210 clk_set_rate(&exynos5_clk_aclk_266.clk, 300000000);
1212 clk_set_rate(&exynos5_clk_aclk_acp.clk, 267000000);
1213 clk_set_rate(&exynos5_clk_pclk_acp.clk, 134000000);
1215 for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrcs); ptr++)
1216 s3c_set_clksrc(&exynos5_clksrcs[ptr], true);
1219 void __init exynos5_register_clocks(void)
1223 s3c24xx_register_clocks(exynos5_clks, ARRAY_SIZE(exynos5_clks));
1225 for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sysclks); ptr++)
1226 s3c_register_clksrc(exynos5_sysclks[ptr], 1);
1228 for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sclk_tv); ptr++)
1229 s3c_register_clksrc(exynos5_sclk_tv[ptr], 1);
1231 for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrc_cdev); ptr++)
1232 s3c_register_clksrc(exynos5_clksrc_cdev[ptr], 1);
1234 s3c_register_clksrc(exynos5_clksrcs, ARRAY_SIZE(exynos5_clksrcs));
1235 s3c_register_clocks(exynos5_init_clocks_on, ARRAY_SIZE(exynos5_init_clocks_on));
1237 s3c24xx_register_clocks(exynos5_clk_cdev, ARRAY_SIZE(exynos5_clk_cdev));
1238 for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clk_cdev); ptr++)
1239 s3c_disable_clocks(exynos5_clk_cdev[ptr], 1);
1241 s3c_register_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
1242 s3c_disable_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
1243 clkdev_add_table(exynos5_clk_lookup, ARRAY_SIZE(exynos5_clk_lookup));
1245 register_syscore_ops(&exynos5_clock_syscore_ops);