aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s5pv210/clock.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/mach-s5pv210/clock.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (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.c242
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
34static unsigned long xtal;
35
34static struct clksrc_clk clk_mout_apll = { 36static 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
264static 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
271static struct clksrc_sources clkset_moutdmc0src = {
272 .sources = clkset_moutdmc0src_list,
273 .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list),
274};
275
276static 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
285static 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
262static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) 294static 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
271static struct clk init_clocks_disable[] = { 303static 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
308static struct clk_ops clk_fout_apll_ops = {
309 .get_rate = s5pv210_clk_fout_apll_get_rate,
310};
311
312static 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
728static 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
743static 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
758static struct clk_ops s5pv210_sclk_spdif_ops = {
759 .set_rate = s5pv210_spdif_set_rate,
760 .get_rate = s5pv210_spdif_get_rate,
761};
762
763static 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
663static struct clk *clkset_group2_list[] = { 775static 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
1067static 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
1092static 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
1138static struct clk_ops s5pv210_epll_ops = {
1139 .set_rate = s5pv210_epll_set_rate,
1140 .get_rate = s5p_epll_get_rate,
956}; 1141};
957 1142
958void __init_or_cpufreq s5pv210_setup_clocks(void) 1143void __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
1038void __init s5pv210_register_clocks(void) 1227void __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}