aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos4/clock.c
diff options
context:
space:
mode:
authorTomasz Stanislawski <t.stanislaws@samsung.com>2011-09-19 03:44:42 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-10-04 05:58:26 -0400
commitfbf05563fe2a3c83c18b4e2768a0d96971a07b16 (patch)
tree7647b301bd1a9046ba943636df5d89be56a460cc /arch/arm/mach-exynos4/clock.c
parentc40e7e0d91b799ed5acf79ae16a2521809d03dd5 (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.c194
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
91static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
92{
93 return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
94}
95
91static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable) 96static 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
136static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
137{
138 return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
139}
140
141static 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
133static struct clksrc_clk clk_mout_apll = { 148static 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
841static struct clk *clkset_sclk_dac_list[] = {
842 [0] = &clk_sclk_vpll.clk,
843 [1] = &clk_sclk_hdmiphy,
844};
845
846static struct clksrc_sources clkset_sclk_dac = {
847 .sources = clkset_sclk_dac_list,
848 .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list),
849};
850
851static 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
861static 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
869static struct clk *clkset_sclk_hdmi_list[] = {
870 [0] = &clk_sclk_pixel.clk,
871 [1] = &clk_sclk_hdmiphy,
872};
873
874static struct clksrc_sources clkset_sclk_hdmi = {
875 .sources = clkset_sclk_hdmi_list,
876 .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list),
877};
878
879static 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
889static struct clk *clkset_sclk_mixer_list[] = {
890 [0] = &clk_sclk_dac.clk,
891 [1] = &clk_sclk_hdmi.clk,
892};
893
894static struct clksrc_sources clkset_sclk_mixer = {
895 .sources = clkset_sclk_mixer_list,
896 .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
897};
898
899static 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
909static struct clksrc_clk *sclk_tv[] = {
910 &clk_sclk_dac,
911 &clk_sclk_pixel,
912 &clk_sclk_hdmi,
913 &clk_sclk_mixer,
914};
915
796static struct clksrc_clk clk_dout_mmc0 = { 916static 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
1255static u32 vpll_div[][8] = {
1256 { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
1257 { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
1258};
1259
1260static unsigned long exynos4_vpll_get_rate(struct clk *clk)
1261{
1262 return clk->rate;
1263}
1264
1265static 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
1315static struct clk_ops exynos4_vpll_ops = {
1316 .get_rate = exynos4_vpll_get_rate,
1317 .set_rate = exynos4_vpll_set_rate,
1318};
1319
1135void __init_or_cpufreq exynos4_setup_clocks(void) 1320void __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
1203static struct clk *clks[] __initdata = { 1389static 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
1207void __init exynos4_register_clocks(void) 1396void __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