diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/mach-s5pv210/clock.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/mach-s5pv210/clock.c')
-rw-r--r-- | arch/arm/mach-s5pv210/clock.c | 242 |
1 files changed, 210 insertions, 32 deletions
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d562670e1b0b..2d599499cefe 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <plat/clock-clksrc.h> | 31 | #include <plat/clock-clksrc.h> |
32 | #include <plat/s5pv210.h> | 32 | #include <plat/s5pv210.h> |
33 | 33 | ||
34 | static unsigned long xtal; | ||
35 | |||
34 | static struct clksrc_clk clk_mout_apll = { | 36 | static struct clksrc_clk clk_mout_apll = { |
35 | .clk = { | 37 | .clk = { |
36 | .name = "mout_apll", | 38 | .name = "mout_apll", |
@@ -259,6 +261,36 @@ static struct clksrc_clk clk_sclk_vpll = { | |||
259 | .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, | 261 | .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, |
260 | }; | 262 | }; |
261 | 263 | ||
264 | static struct clk *clkset_moutdmc0src_list[] = { | ||
265 | [0] = &clk_sclk_a2m.clk, | ||
266 | [1] = &clk_mout_mpll.clk, | ||
267 | [2] = NULL, | ||
268 | [3] = NULL, | ||
269 | }; | ||
270 | |||
271 | static struct clksrc_sources clkset_moutdmc0src = { | ||
272 | .sources = clkset_moutdmc0src_list, | ||
273 | .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list), | ||
274 | }; | ||
275 | |||
276 | static struct clksrc_clk clk_mout_dmc0 = { | ||
277 | .clk = { | ||
278 | .name = "mout_dmc0", | ||
279 | .id = -1, | ||
280 | }, | ||
281 | .sources = &clkset_moutdmc0src, | ||
282 | .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 }, | ||
283 | }; | ||
284 | |||
285 | static struct clksrc_clk clk_sclk_dmc0 = { | ||
286 | .clk = { | ||
287 | .name = "sclk_dmc0", | ||
288 | .id = -1, | ||
289 | .parent = &clk_mout_dmc0.clk, | ||
290 | }, | ||
291 | .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 }, | ||
292 | }; | ||
293 | |||
262 | static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) | 294 | static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) |
263 | { | 295 | { |
264 | return clk_get_rate(clk->parent) / 2; | 296 | return clk_get_rate(clk->parent) / 2; |
@@ -268,8 +300,29 @@ static struct clk_ops clk_hclk_imem_ops = { | |||
268 | .get_rate = s5pv210_clk_imem_get_rate, | 300 | .get_rate = s5pv210_clk_imem_get_rate, |
269 | }; | 301 | }; |
270 | 302 | ||
271 | static struct clk init_clocks_disable[] = { | 303 | static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk) |
304 | { | ||
305 | return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); | ||
306 | } | ||
307 | |||
308 | static struct clk_ops clk_fout_apll_ops = { | ||
309 | .get_rate = s5pv210_clk_fout_apll_get_rate, | ||
310 | }; | ||
311 | |||
312 | static struct clk init_clocks_off[] = { | ||
272 | { | 313 | { |
314 | .name = "pdma", | ||
315 | .id = 0, | ||
316 | .parent = &clk_hclk_psys.clk, | ||
317 | .enable = s5pv210_clk_ip0_ctrl, | ||
318 | .ctrlbit = (1 << 3), | ||
319 | }, { | ||
320 | .name = "pdma", | ||
321 | .id = 1, | ||
322 | .parent = &clk_hclk_psys.clk, | ||
323 | .enable = s5pv210_clk_ip0_ctrl, | ||
324 | .ctrlbit = (1 << 4), | ||
325 | }, { | ||
273 | .name = "rot", | 326 | .name = "rot", |
274 | .id = -1, | 327 | .id = -1, |
275 | .parent = &clk_hclk_dsys.clk, | 328 | .parent = &clk_hclk_dsys.clk, |
@@ -414,23 +467,29 @@ static struct clk init_clocks_disable[] = { | |||
414 | .enable = s5pv210_clk_ip3_ctrl, | 467 | .enable = s5pv210_clk_ip3_ctrl, |
415 | .ctrlbit = (1<<21), | 468 | .ctrlbit = (1<<21), |
416 | }, { | 469 | }, { |
417 | .name = "i2s_v50", | 470 | .name = "iis", |
418 | .id = 0, | 471 | .id = 0, |
419 | .parent = &clk_p, | 472 | .parent = &clk_p, |
420 | .enable = s5pv210_clk_ip3_ctrl, | 473 | .enable = s5pv210_clk_ip3_ctrl, |
421 | .ctrlbit = (1<<4), | 474 | .ctrlbit = (1<<4), |
422 | }, { | 475 | }, { |
423 | .name = "i2s_v32", | 476 | .name = "iis", |
424 | .id = 0, | 477 | .id = 1, |
425 | .parent = &clk_p, | 478 | .parent = &clk_p, |
426 | .enable = s5pv210_clk_ip3_ctrl, | 479 | .enable = s5pv210_clk_ip3_ctrl, |
427 | .ctrlbit = (1 << 5), | 480 | .ctrlbit = (1 << 5), |
428 | }, { | 481 | }, { |
429 | .name = "i2s_v32", | 482 | .name = "iis", |
430 | .id = 1, | 483 | .id = 2, |
431 | .parent = &clk_p, | 484 | .parent = &clk_p, |
432 | .enable = s5pv210_clk_ip3_ctrl, | 485 | .enable = s5pv210_clk_ip3_ctrl, |
433 | .ctrlbit = (1 << 6), | 486 | .ctrlbit = (1 << 6), |
487 | }, { | ||
488 | .name = "spdif", | ||
489 | .id = -1, | ||
490 | .parent = &clk_p, | ||
491 | .enable = s5pv210_clk_ip3_ctrl, | ||
492 | .ctrlbit = (1 << 0), | ||
434 | }, | 493 | }, |
435 | }; | 494 | }; |
436 | 495 | ||
@@ -466,6 +525,12 @@ static struct clk init_clocks[] = { | |||
466 | .parent = &clk_pclk_psys.clk, | 525 | .parent = &clk_pclk_psys.clk, |
467 | .enable = s5pv210_clk_ip3_ctrl, | 526 | .enable = s5pv210_clk_ip3_ctrl, |
468 | .ctrlbit = (1 << 20), | 527 | .ctrlbit = (1 << 20), |
528 | }, { | ||
529 | .name = "sromc", | ||
530 | .id = -1, | ||
531 | .parent = &clk_hclk_psys.clk, | ||
532 | .enable = s5pv210_clk_ip1_ctrl, | ||
533 | .ctrlbit = (1 << 26), | ||
469 | }, | 534 | }, |
470 | }; | 535 | }; |
471 | 536 | ||
@@ -660,6 +725,53 @@ static struct clksrc_sources clkset_sclk_spdif = { | |||
660 | .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), | 725 | .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), |
661 | }; | 726 | }; |
662 | 727 | ||
728 | static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate) | ||
729 | { | ||
730 | struct clk *pclk; | ||
731 | int ret; | ||
732 | |||
733 | pclk = clk_get_parent(clk); | ||
734 | if (IS_ERR(pclk)) | ||
735 | return -EINVAL; | ||
736 | |||
737 | ret = pclk->ops->set_rate(pclk, rate); | ||
738 | clk_put(pclk); | ||
739 | |||
740 | return ret; | ||
741 | } | ||
742 | |||
743 | static unsigned long s5pv210_spdif_get_rate(struct clk *clk) | ||
744 | { | ||
745 | struct clk *pclk; | ||
746 | int rate; | ||
747 | |||
748 | pclk = clk_get_parent(clk); | ||
749 | if (IS_ERR(pclk)) | ||
750 | return -EINVAL; | ||
751 | |||
752 | rate = pclk->ops->get_rate(clk); | ||
753 | clk_put(pclk); | ||
754 | |||
755 | return rate; | ||
756 | } | ||
757 | |||
758 | static struct clk_ops s5pv210_sclk_spdif_ops = { | ||
759 | .set_rate = s5pv210_spdif_set_rate, | ||
760 | .get_rate = s5pv210_spdif_get_rate, | ||
761 | }; | ||
762 | |||
763 | static struct clksrc_clk clk_sclk_spdif = { | ||
764 | .clk = { | ||
765 | .name = "sclk_spdif", | ||
766 | .id = -1, | ||
767 | .enable = s5pv210_clk_mask0_ctrl, | ||
768 | .ctrlbit = (1 << 27), | ||
769 | .ops = &s5pv210_sclk_spdif_ops, | ||
770 | }, | ||
771 | .sources = &clkset_sclk_spdif, | ||
772 | .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, | ||
773 | }; | ||
774 | |||
663 | static struct clk *clkset_group2_list[] = { | 775 | static struct clk *clkset_group2_list[] = { |
664 | [0] = &clk_ext_xtal_mux, | 776 | [0] = &clk_ext_xtal_mux, |
665 | [1] = &clk_xusbxti, | 777 | [1] = &clk_xusbxti, |
@@ -744,15 +856,6 @@ static struct clksrc_clk clksrcs[] = { | |||
744 | .sources = &clkset_sclk_mixer, | 856 | .sources = &clkset_sclk_mixer, |
745 | .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, | 857 | .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, |
746 | }, { | 858 | }, { |
747 | .clk = { | ||
748 | .name = "sclk_spdif", | ||
749 | .id = -1, | ||
750 | .enable = s5pv210_clk_mask0_ctrl, | ||
751 | .ctrlbit = (1 << 27), | ||
752 | }, | ||
753 | .sources = &clkset_sclk_spdif, | ||
754 | .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, | ||
755 | }, { | ||
756 | .clk = { | 859 | .clk = { |
757 | .name = "sclk_fimc", | 860 | .name = "sclk_fimc", |
758 | .id = 0, | 861 | .id = 0, |
@@ -953,12 +1056,93 @@ static struct clksrc_clk *sysclks[] = { | |||
953 | &clk_sclk_dac, | 1056 | &clk_sclk_dac, |
954 | &clk_sclk_pixel, | 1057 | &clk_sclk_pixel, |
955 | &clk_sclk_hdmi, | 1058 | &clk_sclk_hdmi, |
1059 | &clk_mout_dmc0, | ||
1060 | &clk_sclk_dmc0, | ||
1061 | &clk_sclk_audio0, | ||
1062 | &clk_sclk_audio1, | ||
1063 | &clk_sclk_audio2, | ||
1064 | &clk_sclk_spdif, | ||
1065 | }; | ||
1066 | |||
1067 | static u32 epll_div[][6] = { | ||
1068 | { 48000000, 0, 48, 3, 3, 0 }, | ||
1069 | { 96000000, 0, 48, 3, 2, 0 }, | ||
1070 | { 144000000, 1, 72, 3, 2, 0 }, | ||
1071 | { 192000000, 0, 48, 3, 1, 0 }, | ||
1072 | { 288000000, 1, 72, 3, 1, 0 }, | ||
1073 | { 32750000, 1, 65, 3, 4, 35127 }, | ||
1074 | { 32768000, 1, 65, 3, 4, 35127 }, | ||
1075 | { 45158400, 0, 45, 3, 3, 10355 }, | ||
1076 | { 45000000, 0, 45, 3, 3, 10355 }, | ||
1077 | { 45158000, 0, 45, 3, 3, 10355 }, | ||
1078 | { 49125000, 0, 49, 3, 3, 9961 }, | ||
1079 | { 49152000, 0, 49, 3, 3, 9961 }, | ||
1080 | { 67737600, 1, 67, 3, 3, 48366 }, | ||
1081 | { 67738000, 1, 67, 3, 3, 48366 }, | ||
1082 | { 73800000, 1, 73, 3, 3, 47710 }, | ||
1083 | { 73728000, 1, 73, 3, 3, 47710 }, | ||
1084 | { 36000000, 1, 32, 3, 4, 0 }, | ||
1085 | { 60000000, 1, 60, 3, 3, 0 }, | ||
1086 | { 72000000, 1, 72, 3, 3, 0 }, | ||
1087 | { 80000000, 1, 80, 3, 3, 0 }, | ||
1088 | { 84000000, 0, 42, 3, 2, 0 }, | ||
1089 | { 50000000, 0, 50, 3, 3, 0 }, | ||
1090 | }; | ||
1091 | |||
1092 | static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate) | ||
1093 | { | ||
1094 | unsigned int epll_con, epll_con_k; | ||
1095 | unsigned int i; | ||
1096 | |||
1097 | /* Return if nothing changed */ | ||
1098 | if (clk->rate == rate) | ||
1099 | return 0; | ||
1100 | |||
1101 | epll_con = __raw_readl(S5P_EPLL_CON); | ||
1102 | epll_con_k = __raw_readl(S5P_EPLL_CON1); | ||
1103 | |||
1104 | epll_con_k &= ~PLL46XX_KDIV_MASK; | ||
1105 | epll_con &= ~(1 << 27 | | ||
1106 | PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | | ||
1107 | PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | | ||
1108 | PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); | ||
1109 | |||
1110 | for (i = 0; i < ARRAY_SIZE(epll_div); i++) { | ||
1111 | if (epll_div[i][0] == rate) { | ||
1112 | epll_con_k |= epll_div[i][5] << 0; | ||
1113 | epll_con |= (epll_div[i][1] << 27 | | ||
1114 | epll_div[i][2] << PLL46XX_MDIV_SHIFT | | ||
1115 | epll_div[i][3] << PLL46XX_PDIV_SHIFT | | ||
1116 | epll_div[i][4] << PLL46XX_SDIV_SHIFT); | ||
1117 | break; | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | if (i == ARRAY_SIZE(epll_div)) { | ||
1122 | printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", | ||
1123 | __func__); | ||
1124 | return -EINVAL; | ||
1125 | } | ||
1126 | |||
1127 | __raw_writel(epll_con, S5P_EPLL_CON); | ||
1128 | __raw_writel(epll_con_k, S5P_EPLL_CON1); | ||
1129 | |||
1130 | printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", | ||
1131 | clk->rate, rate); | ||
1132 | |||
1133 | clk->rate = rate; | ||
1134 | |||
1135 | return 0; | ||
1136 | } | ||
1137 | |||
1138 | static struct clk_ops s5pv210_epll_ops = { | ||
1139 | .set_rate = s5pv210_epll_set_rate, | ||
1140 | .get_rate = s5p_epll_get_rate, | ||
956 | }; | 1141 | }; |
957 | 1142 | ||
958 | void __init_or_cpufreq s5pv210_setup_clocks(void) | 1143 | void __init_or_cpufreq s5pv210_setup_clocks(void) |
959 | { | 1144 | { |
960 | struct clk *xtal_clk; | 1145 | struct clk *xtal_clk; |
961 | unsigned long xtal; | ||
962 | unsigned long vpllsrc; | 1146 | unsigned long vpllsrc; |
963 | unsigned long armclk; | 1147 | unsigned long armclk; |
964 | unsigned long hclk_msys; | 1148 | unsigned long hclk_msys; |
@@ -974,6 +1158,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) | |||
974 | unsigned int ptr; | 1158 | unsigned int ptr; |
975 | u32 clkdiv0, clkdiv1; | 1159 | u32 clkdiv0, clkdiv1; |
976 | 1160 | ||
1161 | /* Set functions for clk_fout_epll */ | ||
1162 | clk_fout_epll.enable = s5p_epll_enable; | ||
1163 | clk_fout_epll.ops = &s5pv210_epll_ops; | ||
1164 | |||
977 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); | 1165 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); |
978 | 1166 | ||
979 | clkdiv0 = __raw_readl(S5P_CLK_DIV0); | 1167 | clkdiv0 = __raw_readl(S5P_CLK_DIV0); |
@@ -992,11 +1180,12 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) | |||
992 | 1180 | ||
993 | apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); | 1181 | apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); |
994 | mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); | 1182 | mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); |
995 | epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500); | 1183 | epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON), |
1184 | __raw_readl(S5P_EPLL_CON1), pll_4600); | ||
996 | vpllsrc = clk_get_rate(&clk_vpllsrc.clk); | 1185 | vpllsrc = clk_get_rate(&clk_vpllsrc.clk); |
997 | vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502); | 1186 | vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502); |
998 | 1187 | ||
999 | clk_fout_apll.rate = apll; | 1188 | clk_fout_apll.ops = &clk_fout_apll_ops; |
1000 | clk_fout_mpll.rate = mpll; | 1189 | clk_fout_mpll.rate = mpll; |
1001 | clk_fout_epll.rate = epll; | 1190 | clk_fout_epll.rate = epll; |
1002 | clk_fout_vpll.rate = vpll; | 1191 | clk_fout_vpll.rate = vpll; |
@@ -1037,13 +1226,9 @@ static struct clk *clks[] __initdata = { | |||
1037 | 1226 | ||
1038 | void __init s5pv210_register_clocks(void) | 1227 | void __init s5pv210_register_clocks(void) |
1039 | { | 1228 | { |
1040 | struct clk *clkp; | ||
1041 | int ret; | ||
1042 | int ptr; | 1229 | int ptr; |
1043 | 1230 | ||
1044 | ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); | 1231 | s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); |
1045 | if (ret > 0) | ||
1046 | printk(KERN_ERR "Failed to register %u clocks\n", ret); | ||
1047 | 1232 | ||
1048 | for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) | 1233 | for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) |
1049 | s3c_register_clksrc(sysclks[ptr], 1); | 1234 | s3c_register_clksrc(sysclks[ptr], 1); |
@@ -1051,15 +1236,8 @@ void __init s5pv210_register_clocks(void) | |||
1051 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); | 1236 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); |
1052 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); | 1237 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); |
1053 | 1238 | ||
1054 | clkp = init_clocks_disable; | 1239 | s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); |
1055 | for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { | 1240 | s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); |
1056 | ret = s3c24xx_register_clock(clkp); | ||
1057 | if (ret < 0) { | ||
1058 | printk(KERN_ERR "Failed to register clock %s (%d)\n", | ||
1059 | clkp->name, ret); | ||
1060 | } | ||
1061 | (clkp->enable)(clkp, 0); | ||
1062 | } | ||
1063 | 1241 | ||
1064 | s3c_pwmclk_init(); | 1242 | s3c_pwmclk_init(); |
1065 | } | 1243 | } |