diff options
Diffstat (limited to 'arch/arm/mach-s5pv210/clock.c')
-rw-r--r-- | arch/arm/mach-s5pv210/clock.c | 131 |
1 files changed, 120 insertions, 11 deletions
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 60cf8226de8b..4c5ac7a69e9e 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c | |||
@@ -174,6 +174,16 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable) | |||
174 | return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable); | 174 | return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable); |
175 | } | 175 | } |
176 | 176 | ||
177 | static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable) | ||
178 | { | ||
179 | return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable); | ||
180 | } | ||
181 | |||
182 | static int exynos4_clk_dac_ctrl(struct clk *clk, int enable) | ||
183 | { | ||
184 | return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable); | ||
185 | } | ||
186 | |||
177 | static struct clk clk_sclk_hdmi27m = { | 187 | static struct clk clk_sclk_hdmi27m = { |
178 | .name = "sclk_hdmi27m", | 188 | .name = "sclk_hdmi27m", |
179 | .rate = 27000000, | 189 | .rate = 27000000, |
@@ -335,6 +345,40 @@ static struct clk init_clocks_off[] = { | |||
335 | .enable = s5pv210_clk_ip0_ctrl, | 345 | .enable = s5pv210_clk_ip0_ctrl, |
336 | .ctrlbit = (1 << 16), | 346 | .ctrlbit = (1 << 16), |
337 | }, { | 347 | }, { |
348 | .name = "dac", | ||
349 | .devname = "s5p-sdo", | ||
350 | .parent = &clk_hclk_dsys.clk, | ||
351 | .enable = s5pv210_clk_ip1_ctrl, | ||
352 | .ctrlbit = (1 << 10), | ||
353 | }, { | ||
354 | .name = "mixer", | ||
355 | .devname = "s5p-mixer", | ||
356 | .parent = &clk_hclk_dsys.clk, | ||
357 | .enable = s5pv210_clk_ip1_ctrl, | ||
358 | .ctrlbit = (1 << 9), | ||
359 | }, { | ||
360 | .name = "vp", | ||
361 | .devname = "s5p-mixer", | ||
362 | .parent = &clk_hclk_dsys.clk, | ||
363 | .enable = s5pv210_clk_ip1_ctrl, | ||
364 | .ctrlbit = (1 << 8), | ||
365 | }, { | ||
366 | .name = "hdmi", | ||
367 | .devname = "s5pv210-hdmi", | ||
368 | .parent = &clk_hclk_dsys.clk, | ||
369 | .enable = s5pv210_clk_ip1_ctrl, | ||
370 | .ctrlbit = (1 << 11), | ||
371 | }, { | ||
372 | .name = "hdmiphy", | ||
373 | .devname = "s5pv210-hdmi", | ||
374 | .enable = exynos4_clk_hdmiphy_ctrl, | ||
375 | .ctrlbit = (1 << 0), | ||
376 | }, { | ||
377 | .name = "dacphy", | ||
378 | .devname = "s5p-sdo", | ||
379 | .enable = exynos4_clk_dac_ctrl, | ||
380 | .ctrlbit = (1 << 0), | ||
381 | }, { | ||
338 | .name = "otg", | 382 | .name = "otg", |
339 | .parent = &clk_hclk_psys.clk, | 383 | .parent = &clk_hclk_psys.clk, |
340 | .enable = s5pv210_clk_ip1_ctrl, | 384 | .enable = s5pv210_clk_ip1_ctrl, |
@@ -605,6 +649,23 @@ static struct clksrc_sources clkset_sclk_mixer = { | |||
605 | .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list), | 649 | .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list), |
606 | }; | 650 | }; |
607 | 651 | ||
652 | static struct clksrc_clk clk_sclk_mixer = { | ||
653 | .clk = { | ||
654 | .name = "sclk_mixer", | ||
655 | .enable = s5pv210_clk_mask0_ctrl, | ||
656 | .ctrlbit = (1 << 1), | ||
657 | }, | ||
658 | .sources = &clkset_sclk_mixer, | ||
659 | .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, | ||
660 | }; | ||
661 | |||
662 | static struct clksrc_clk *sclk_tv[] = { | ||
663 | &clk_sclk_dac, | ||
664 | &clk_sclk_pixel, | ||
665 | &clk_sclk_hdmi, | ||
666 | &clk_sclk_mixer, | ||
667 | }; | ||
668 | |||
608 | static struct clk *clkset_sclk_audio0_list[] = { | 669 | static struct clk *clkset_sclk_audio0_list[] = { |
609 | [0] = &clk_ext_xtal_mux, | 670 | [0] = &clk_ext_xtal_mux, |
610 | [1] = &clk_pcmcdclk0, | 671 | [1] = &clk_pcmcdclk0, |
@@ -788,14 +849,6 @@ static struct clksrc_clk clksrcs[] = { | |||
788 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 }, | 849 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 }, |
789 | }, { | 850 | }, { |
790 | .clk = { | 851 | .clk = { |
791 | .name = "sclk_mixer", | ||
792 | .enable = s5pv210_clk_mask0_ctrl, | ||
793 | .ctrlbit = (1 << 1), | ||
794 | }, | ||
795 | .sources = &clkset_sclk_mixer, | ||
796 | .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, | ||
797 | }, { | ||
798 | .clk = { | ||
799 | .name = "sclk_fimc", | 852 | .name = "sclk_fimc", |
800 | .devname = "s5pv210-fimc.0", | 853 | .devname = "s5pv210-fimc.0", |
801 | .enable = s5pv210_clk_mask1_ctrl, | 854 | .enable = s5pv210_clk_mask1_ctrl, |
@@ -984,9 +1037,6 @@ static struct clksrc_clk *sysclks[] = { | |||
984 | &clk_pclk_psys, | 1037 | &clk_pclk_psys, |
985 | &clk_vpllsrc, | 1038 | &clk_vpllsrc, |
986 | &clk_sclk_vpll, | 1039 | &clk_sclk_vpll, |
987 | &clk_sclk_dac, | ||
988 | &clk_sclk_pixel, | ||
989 | &clk_sclk_hdmi, | ||
990 | &clk_mout_dmc0, | 1040 | &clk_mout_dmc0, |
991 | &clk_sclk_dmc0, | 1041 | &clk_sclk_dmc0, |
992 | &clk_sclk_audio0, | 1042 | &clk_sclk_audio0, |
@@ -1071,6 +1121,61 @@ static struct clk_ops s5pv210_epll_ops = { | |||
1071 | .get_rate = s5p_epll_get_rate, | 1121 | .get_rate = s5p_epll_get_rate, |
1072 | }; | 1122 | }; |
1073 | 1123 | ||
1124 | static u32 vpll_div[][5] = { | ||
1125 | { 54000000, 3, 53, 3, 0 }, | ||
1126 | { 108000000, 3, 53, 2, 0 }, | ||
1127 | }; | ||
1128 | |||
1129 | static unsigned long s5pv210_vpll_get_rate(struct clk *clk) | ||
1130 | { | ||
1131 | return clk->rate; | ||
1132 | } | ||
1133 | |||
1134 | static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate) | ||
1135 | { | ||
1136 | unsigned int vpll_con; | ||
1137 | unsigned int i; | ||
1138 | |||
1139 | /* Return if nothing changed */ | ||
1140 | if (clk->rate == rate) | ||
1141 | return 0; | ||
1142 | |||
1143 | vpll_con = __raw_readl(S5P_VPLL_CON); | ||
1144 | vpll_con &= ~(0x1 << 27 | \ | ||
1145 | PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT | \ | ||
1146 | PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT | \ | ||
1147 | PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT); | ||
1148 | |||
1149 | for (i = 0; i < ARRAY_SIZE(vpll_div); i++) { | ||
1150 | if (vpll_div[i][0] == rate) { | ||
1151 | vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT; | ||
1152 | vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT; | ||
1153 | vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT; | ||
1154 | vpll_con |= vpll_div[i][4] << 27; | ||
1155 | break; | ||
1156 | } | ||
1157 | } | ||
1158 | |||
1159 | if (i == ARRAY_SIZE(vpll_div)) { | ||
1160 | printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n", | ||
1161 | __func__); | ||
1162 | return -EINVAL; | ||
1163 | } | ||
1164 | |||
1165 | __raw_writel(vpll_con, S5P_VPLL_CON); | ||
1166 | |||
1167 | /* Wait for VPLL lock */ | ||
1168 | while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT))) | ||
1169 | continue; | ||
1170 | |||
1171 | clk->rate = rate; | ||
1172 | return 0; | ||
1173 | } | ||
1174 | static struct clk_ops s5pv210_vpll_ops = { | ||
1175 | .get_rate = s5pv210_vpll_get_rate, | ||
1176 | .set_rate = s5pv210_vpll_set_rate, | ||
1177 | }; | ||
1178 | |||
1074 | void __init_or_cpufreq s5pv210_setup_clocks(void) | 1179 | void __init_or_cpufreq s5pv210_setup_clocks(void) |
1075 | { | 1180 | { |
1076 | struct clk *xtal_clk; | 1181 | struct clk *xtal_clk; |
@@ -1119,6 +1224,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) | |||
1119 | clk_fout_apll.ops = &clk_fout_apll_ops; | 1224 | clk_fout_apll.ops = &clk_fout_apll_ops; |
1120 | clk_fout_mpll.rate = mpll; | 1225 | clk_fout_mpll.rate = mpll; |
1121 | clk_fout_epll.rate = epll; | 1226 | clk_fout_epll.rate = epll; |
1227 | clk_fout_vpll.ops = &s5pv210_vpll_ops; | ||
1122 | clk_fout_vpll.rate = vpll; | 1228 | clk_fout_vpll.rate = vpll; |
1123 | 1229 | ||
1124 | printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", | 1230 | printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", |
@@ -1164,6 +1270,9 @@ void __init s5pv210_register_clocks(void) | |||
1164 | for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) | 1270 | for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) |
1165 | s3c_register_clksrc(sysclks[ptr], 1); | 1271 | s3c_register_clksrc(sysclks[ptr], 1); |
1166 | 1272 | ||
1273 | for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++) | ||
1274 | s3c_register_clksrc(sclk_tv[ptr], 1); | ||
1275 | |||
1167 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); | 1276 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); |
1168 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); | 1277 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); |
1169 | 1278 | ||