diff options
author | Tomasz Stanislawski <t.stanislaws@samsung.com> | 2011-09-19 03:44:42 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2011-10-04 05:58:26 -0400 |
commit | fbf05563fe2a3c83c18b4e2768a0d96971a07b16 (patch) | |
tree | 7647b301bd1a9046ba943636df5d89be56a460cc /arch/arm/mach-exynos4/clock.c | |
parent | c40e7e0d91b799ed5acf79ae16a2521809d03dd5 (diff) |
ARM: S5P: add support for tv device
This patch adds all the resources for TV drivers and devices for Samsung
Exynos4 and S5PV210 platforms.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
[m.szyprowski: squashed Exynos4 and S5PV210 patches and rewrote commit message]
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-exynos4/clock.c')
-rw-r--r-- | arch/arm/mach-exynos4/clock.c | 194 |
1 files changed, 193 insertions, 1 deletions
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c index 0e1ba071e764..13e2421ba9e6 100644 --- a/arch/arm/mach-exynos4/clock.c +++ b/arch/arm/mach-exynos4/clock.c | |||
@@ -88,6 +88,11 @@ static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable) | |||
88 | return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable); | 88 | return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable); |
89 | } | 89 | } |
90 | 90 | ||
91 | static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable) | ||
92 | { | ||
93 | return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable); | ||
94 | } | ||
95 | |||
91 | static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable) | 96 | static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable) |
92 | { | 97 | { |
93 | return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable); | 98 | return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable); |
@@ -128,6 +133,16 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable) | |||
128 | return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable); | 133 | return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable); |
129 | } | 134 | } |
130 | 135 | ||
136 | static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable) | ||
137 | { | ||
138 | return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable); | ||
139 | } | ||
140 | |||
141 | static int exynos4_clk_dac_ctrl(struct clk *clk, int enable) | ||
142 | { | ||
143 | return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable); | ||
144 | } | ||
145 | |||
131 | /* Core list of CMU_CPU side */ | 146 | /* Core list of CMU_CPU side */ |
132 | 147 | ||
133 | static struct clksrc_clk clk_mout_apll = { | 148 | static struct clksrc_clk clk_mout_apll = { |
@@ -454,6 +469,36 @@ static struct clk init_clocks_off[] = { | |||
454 | .enable = exynos4_clk_ip_fsys_ctrl, | 469 | .enable = exynos4_clk_ip_fsys_ctrl, |
455 | .ctrlbit = (1 << 9), | 470 | .ctrlbit = (1 << 9), |
456 | }, { | 471 | }, { |
472 | .name = "dac", | ||
473 | .devname = "s5p-sdo", | ||
474 | .enable = exynos4_clk_ip_tv_ctrl, | ||
475 | .ctrlbit = (1 << 2), | ||
476 | }, { | ||
477 | .name = "mixer", | ||
478 | .devname = "s5p-mixer", | ||
479 | .enable = exynos4_clk_ip_tv_ctrl, | ||
480 | .ctrlbit = (1 << 1), | ||
481 | }, { | ||
482 | .name = "vp", | ||
483 | .devname = "s5p-mixer", | ||
484 | .enable = exynos4_clk_ip_tv_ctrl, | ||
485 | .ctrlbit = (1 << 0), | ||
486 | }, { | ||
487 | .name = "hdmi", | ||
488 | .devname = "exynos4-hdmi", | ||
489 | .enable = exynos4_clk_ip_tv_ctrl, | ||
490 | .ctrlbit = (1 << 3), | ||
491 | }, { | ||
492 | .name = "hdmiphy", | ||
493 | .devname = "exynos4-hdmi", | ||
494 | .enable = exynos4_clk_hdmiphy_ctrl, | ||
495 | .ctrlbit = (1 << 0), | ||
496 | }, { | ||
497 | .name = "dacphy", | ||
498 | .devname = "s5p-sdo", | ||
499 | .enable = exynos4_clk_dac_ctrl, | ||
500 | .ctrlbit = (1 << 0), | ||
501 | }, { | ||
457 | .name = "sata", | 502 | .name = "sata", |
458 | .parent = &clk_aclk_133.clk, | 503 | .parent = &clk_aclk_133.clk, |
459 | .enable = exynos4_clk_ip_fsys_ctrl, | 504 | .enable = exynos4_clk_ip_fsys_ctrl, |
@@ -793,6 +838,81 @@ static struct clksrc_sources clkset_mout_mfc = { | |||
793 | .nr_sources = ARRAY_SIZE(clkset_mout_mfc_list), | 838 | .nr_sources = ARRAY_SIZE(clkset_mout_mfc_list), |
794 | }; | 839 | }; |
795 | 840 | ||
841 | static struct clk *clkset_sclk_dac_list[] = { | ||
842 | [0] = &clk_sclk_vpll.clk, | ||
843 | [1] = &clk_sclk_hdmiphy, | ||
844 | }; | ||
845 | |||
846 | static struct clksrc_sources clkset_sclk_dac = { | ||
847 | .sources = clkset_sclk_dac_list, | ||
848 | .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list), | ||
849 | }; | ||
850 | |||
851 | static struct clksrc_clk clk_sclk_dac = { | ||
852 | .clk = { | ||
853 | .name = "sclk_dac", | ||
854 | .enable = exynos4_clksrc_mask_tv_ctrl, | ||
855 | .ctrlbit = (1 << 8), | ||
856 | }, | ||
857 | .sources = &clkset_sclk_dac, | ||
858 | .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 }, | ||
859 | }; | ||
860 | |||
861 | static struct clksrc_clk clk_sclk_pixel = { | ||
862 | .clk = { | ||
863 | .name = "sclk_pixel", | ||
864 | .parent = &clk_sclk_vpll.clk, | ||
865 | }, | ||
866 | .reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 }, | ||
867 | }; | ||
868 | |||
869 | static struct clk *clkset_sclk_hdmi_list[] = { | ||
870 | [0] = &clk_sclk_pixel.clk, | ||
871 | [1] = &clk_sclk_hdmiphy, | ||
872 | }; | ||
873 | |||
874 | static struct clksrc_sources clkset_sclk_hdmi = { | ||
875 | .sources = clkset_sclk_hdmi_list, | ||
876 | .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list), | ||
877 | }; | ||
878 | |||
879 | static struct clksrc_clk clk_sclk_hdmi = { | ||
880 | .clk = { | ||
881 | .name = "sclk_hdmi", | ||
882 | .enable = exynos4_clksrc_mask_tv_ctrl, | ||
883 | .ctrlbit = (1 << 0), | ||
884 | }, | ||
885 | .sources = &clkset_sclk_hdmi, | ||
886 | .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 }, | ||
887 | }; | ||
888 | |||
889 | static struct clk *clkset_sclk_mixer_list[] = { | ||
890 | [0] = &clk_sclk_dac.clk, | ||
891 | [1] = &clk_sclk_hdmi.clk, | ||
892 | }; | ||
893 | |||
894 | static struct clksrc_sources clkset_sclk_mixer = { | ||
895 | .sources = clkset_sclk_mixer_list, | ||
896 | .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list), | ||
897 | }; | ||
898 | |||
899 | static struct clksrc_clk clk_sclk_mixer = { | ||
900 | .clk = { | ||
901 | .name = "sclk_mixer", | ||
902 | .enable = exynos4_clksrc_mask_tv_ctrl, | ||
903 | .ctrlbit = (1 << 4), | ||
904 | }, | ||
905 | .sources = &clkset_sclk_mixer, | ||
906 | .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 }, | ||
907 | }; | ||
908 | |||
909 | static struct clksrc_clk *sclk_tv[] = { | ||
910 | &clk_sclk_dac, | ||
911 | &clk_sclk_pixel, | ||
912 | &clk_sclk_hdmi, | ||
913 | &clk_sclk_mixer, | ||
914 | }; | ||
915 | |||
796 | static struct clksrc_clk clk_dout_mmc0 = { | 916 | static struct clksrc_clk clk_dout_mmc0 = { |
797 | .clk = { | 917 | .clk = { |
798 | .name = "dout_mmc0", | 918 | .name = "dout_mmc0", |
@@ -1132,6 +1252,71 @@ static struct clk_ops exynos4_fout_apll_ops = { | |||
1132 | .get_rate = exynos4_fout_apll_get_rate, | 1252 | .get_rate = exynos4_fout_apll_get_rate, |
1133 | }; | 1253 | }; |
1134 | 1254 | ||
1255 | static u32 vpll_div[][8] = { | ||
1256 | { 54000000, 3, 53, 3, 1024, 0, 17, 0 }, | ||
1257 | { 108000000, 3, 53, 2, 1024, 0, 17, 0 }, | ||
1258 | }; | ||
1259 | |||
1260 | static unsigned long exynos4_vpll_get_rate(struct clk *clk) | ||
1261 | { | ||
1262 | return clk->rate; | ||
1263 | } | ||
1264 | |||
1265 | static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate) | ||
1266 | { | ||
1267 | unsigned int vpll_con0, vpll_con1 = 0; | ||
1268 | unsigned int i; | ||
1269 | |||
1270 | /* Return if nothing changed */ | ||
1271 | if (clk->rate == rate) | ||
1272 | return 0; | ||
1273 | |||
1274 | vpll_con0 = __raw_readl(S5P_VPLL_CON0); | ||
1275 | vpll_con0 &= ~(0x1 << 27 | \ | ||
1276 | PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \ | ||
1277 | PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \ | ||
1278 | PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); | ||
1279 | |||
1280 | vpll_con1 = __raw_readl(S5P_VPLL_CON1); | ||
1281 | vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \ | ||
1282 | PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \ | ||
1283 | PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT); | ||
1284 | |||
1285 | for (i = 0; i < ARRAY_SIZE(vpll_div); i++) { | ||
1286 | if (vpll_div[i][0] == rate) { | ||
1287 | vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT; | ||
1288 | vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT; | ||
1289 | vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT; | ||
1290 | vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT; | ||
1291 | vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT; | ||
1292 | vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT; | ||
1293 | vpll_con0 |= vpll_div[i][7] << 27; | ||
1294 | break; | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1298 | if (i == ARRAY_SIZE(vpll_div)) { | ||
1299 | printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n", | ||
1300 | __func__); | ||
1301 | return -EINVAL; | ||
1302 | } | ||
1303 | |||
1304 | __raw_writel(vpll_con0, S5P_VPLL_CON0); | ||
1305 | __raw_writel(vpll_con1, S5P_VPLL_CON1); | ||
1306 | |||
1307 | /* Wait for VPLL lock */ | ||
1308 | while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT))) | ||
1309 | continue; | ||
1310 | |||
1311 | clk->rate = rate; | ||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | static struct clk_ops exynos4_vpll_ops = { | ||
1316 | .get_rate = exynos4_vpll_get_rate, | ||
1317 | .set_rate = exynos4_vpll_set_rate, | ||
1318 | }; | ||
1319 | |||
1135 | void __init_or_cpufreq exynos4_setup_clocks(void) | 1320 | void __init_or_cpufreq exynos4_setup_clocks(void) |
1136 | { | 1321 | { |
1137 | struct clk *xtal_clk; | 1322 | struct clk *xtal_clk; |
@@ -1174,6 +1359,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void) | |||
1174 | clk_fout_apll.ops = &exynos4_fout_apll_ops; | 1359 | clk_fout_apll.ops = &exynos4_fout_apll_ops; |
1175 | clk_fout_mpll.rate = mpll; | 1360 | clk_fout_mpll.rate = mpll; |
1176 | clk_fout_epll.rate = epll; | 1361 | clk_fout_epll.rate = epll; |
1362 | clk_fout_vpll.ops = &exynos4_vpll_ops; | ||
1177 | clk_fout_vpll.rate = vpll; | 1363 | clk_fout_vpll.rate = vpll; |
1178 | 1364 | ||
1179 | printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", | 1365 | printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", |
@@ -1201,7 +1387,10 @@ void __init_or_cpufreq exynos4_setup_clocks(void) | |||
1201 | } | 1387 | } |
1202 | 1388 | ||
1203 | static struct clk *clks[] __initdata = { | 1389 | static struct clk *clks[] __initdata = { |
1204 | /* Nothing here yet */ | 1390 | &clk_sclk_hdmi27m, |
1391 | &clk_sclk_hdmiphy, | ||
1392 | &clk_sclk_usbphy0, | ||
1393 | &clk_sclk_usbphy1, | ||
1205 | }; | 1394 | }; |
1206 | 1395 | ||
1207 | void __init exynos4_register_clocks(void) | 1396 | void __init exynos4_register_clocks(void) |
@@ -1213,6 +1402,9 @@ void __init exynos4_register_clocks(void) | |||
1213 | for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) | 1402 | for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) |
1214 | s3c_register_clksrc(sysclks[ptr], 1); | 1403 | s3c_register_clksrc(sysclks[ptr], 1); |
1215 | 1404 | ||
1405 | for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++) | ||
1406 | s3c_register_clksrc(sclk_tv[ptr], 1); | ||
1407 | |||
1216 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); | 1408 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); |
1217 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); | 1409 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); |
1218 | 1410 | ||