Add clocks and definitions needed by TV driver infrastructure for Samsung Exynos4 machine. Signed-off-by: Tomasz Stanislawski <t.stanislaws@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> Reviewed-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> --- arch/arm/mach-exynos4/clock.c | 217 ++++++++++++++++++++++- arch/arm/mach-exynos4/cpu.c | 4 + arch/arm/mach-exynos4/include/mach/irqs.h | 4 + arch/arm/mach-exynos4/include/mach/map.h | 26 +++ arch/arm/mach-exynos4/include/mach/regs-clock.h | 1 + arch/arm/mach-exynos4/include/mach/regs-pmu.h | 6 + 6 files changed, 257 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c index 035eacc..6ac2cbd 100644 --- a/arch/arm/mach-exynos4/clock.c +++ b/arch/arm/mach-exynos4/clock.c @@ -87,6 +87,11 @@ static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable); } +static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable); +} + static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable); @@ -127,6 +132,16 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable); } +static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable); +} + +static int exynos4_clk_dac_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable); +} + /* Core list of CMU_CPU side */ static struct clksrc_clk clk_mout_apll = { @@ -473,6 +488,36 @@ static struct clk init_clocks_off[] = { .enable = exynos4_clk_ip_fsys_ctrl, .ctrlbit = (1 << 8), }, { + .name = "dac", + .id = -1, + .enable = exynos4_clk_ip_tv_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "mixer", + .id = -1, + .enable = exynos4_clk_ip_tv_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "vp", + .id = -1, + .enable = exynos4_clk_ip_tv_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "hdmi", + .id = -1, + .enable = exynos4_clk_ip_tv_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "hdmiphy", + .id = -1, + .enable = exynos4_clk_hdmiphy_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "dacphy", + .id = -1, + .enable = exynos4_clk_dac_ctrl, + .ctrlbit = (1 << 0), + }, { .name = "hsmmc", .id = 4, .parent = &clk_aclk_133.clk, @@ -791,6 +836,93 @@ static struct clksrc_sources clkset_mout_g2d = { .nr_sources = ARRAY_SIZE(clkset_mout_g2d_list), }; +/* -------------------------------------- + * TV subsystem CLOCKS + * -------------------------------------- + */ + +static struct clk *clkset_sclk_dac_list[] = { + [0] = &clk_sclk_vpll.clk, + [1] = &clk_sclk_hdmiphy, +}; + +static struct clksrc_sources clkset_sclk_dac = { + .sources = clkset_sclk_dac_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list), +}; + +static struct clksrc_clk clk_sclk_dac = { + .clk = { + .name = "sclk_dac", + .id = -1, + .enable = exynos4_clksrc_mask_tv_ctrl, + .ctrlbit = (1 << 8), + }, + .sources = &clkset_sclk_dac, + .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 }, +}; + +static struct clksrc_clk clk_sclk_pixel = { + .clk = { + .name = "sclk_pixel", + .id = -1, + .parent = &clk_sclk_vpll.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 }, +}; + +static struct clk *clkset_sclk_hdmi_list[] = { + [0] = &clk_sclk_pixel.clk, + [1] = &clk_sclk_hdmiphy, +}; + +static struct clksrc_sources clkset_sclk_hdmi = { + .sources = clkset_sclk_hdmi_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list), +}; + +static struct clksrc_clk clk_sclk_hdmi = { + .clk = { + .name = "sclk_hdmi", + .id = -1, + .enable = exynos4_clksrc_mask_tv_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &clkset_sclk_hdmi, + .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 }, +}; + +static struct clk *clkset_sclk_mixer_list[] = { + [0] = &clk_sclk_dac.clk, + [1] = &clk_sclk_hdmi.clk, +}; + +static struct clksrc_sources clkset_sclk_mixer = { + .sources = clkset_sclk_mixer_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list), +}; + +static struct clksrc_clk clk_sclk_mixer = { + .clk = { + .name = "sclk_mixer", + .id = -1, + .enable = exynos4_clksrc_mask_tv_ctrl, + .ctrlbit = (1 << 4), + }, + .sources = &clkset_sclk_mixer, + .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 }, +}; + +static struct clksrc_clk *sclk_tv[] = { + &clk_sclk_dac, + &clk_sclk_pixel, + &clk_sclk_hdmi, + &clk_sclk_mixer, + NULL, +}; + +/* -------------------------------------------- */ + static struct clksrc_clk clk_dout_mmc0 = { .clk = { .name = "dout_mmc0", @@ -1131,6 +1263,81 @@ static struct clk_ops exynos4_fout_apll_ops = { .get_rate = exynos4_fout_apll_get_rate, }; +struct vpll_div_data { + u32 rate; + u32 pdiv; + u32 mdiv; + u32 sdiv; + u32 k; + u32 mfr; + u32 mrr; + u32 vsel; + +}; + +static struct vpll_div_data vpll_div[] = { + { 54000000, 3, 53, 3, 1024, 0, 17, 0 }, + { 108000000, 3, 53, 2, 1024, 0, 17, 0 }, +}; + +static unsigned long exynos4_vpll_get_rate(struct clk *clk) +{ + return clk->rate; +} + +static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int vpll_con0, vpll_con1; + unsigned int i; + + /* Return if nothing changed */ + if (clk->rate == rate) + return 0; + + vpll_con0 = __raw_readl(S5P_VPLL_CON0); + vpll_con0 &= ~(0x1 << 27 | \ + PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT | \ + PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT | \ + PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT); + + vpll_con1 = __raw_readl(S5P_VPLL_CON1); + vpll_con1 &= ~(0x1f << 24 | \ + 0x3f << 16 | \ + 0xfff << 0); + + for (i = 0; i < ARRAY_SIZE(vpll_div); i++) { + if (vpll_div[i].rate == rate) { + vpll_con0 |= vpll_div[i].vsel << 27; + vpll_con0 |= vpll_div[i].pdiv << PLL90XX_PDIV_SHIFT; + vpll_con0 |= vpll_div[i].mdiv << PLL90XX_MDIV_SHIFT; + vpll_con0 |= vpll_div[i].sdiv << PLL90XX_SDIV_SHIFT; + + vpll_con1 |= vpll_div[i].mrr << 24; + vpll_con1 |= vpll_div[i].mfr << 16; + vpll_con1 |= vpll_div[i].k << 0; + break; + } + } + + if (i == ARRAY_SIZE(vpll_div)) { + printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n", + __func__); + return -EINVAL; + } + + __raw_writel(vpll_con0, S5P_VPLL_CON0); + __raw_writel(vpll_con1, S5P_VPLL_CON1); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops exynos4_vpll_ops = { + .get_rate = exynos4_vpll_get_rate, + .set_rate = exynos4_vpll_set_rate, +}; + void __init_or_cpufreq exynos4_setup_clocks(void) { struct clk *xtal_clk; @@ -1173,6 +1380,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void) clk_fout_apll.ops = &exynos4_fout_apll_ops; clk_fout_mpll.rate = mpll; clk_fout_epll.rate = epll; + clk_fout_vpll.ops = &exynos4_vpll_ops; clk_fout_vpll.rate = vpll; printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", @@ -1200,7 +1408,10 @@ void __init_or_cpufreq exynos4_setup_clocks(void) } static struct clk *clks[] __initdata = { - /* Nothing here yet */ + &clk_sclk_hdmi27m, + &clk_sclk_hdmiphy, + &clk_sclk_usbphy0, + &clk_sclk_usbphy1, }; void __init exynos4_register_clocks(void) @@ -1212,6 +1423,10 @@ void __init exynos4_register_clocks(void) for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) s3c_register_clksrc(sysclks[ptr], 1); + /* register TV clocks */ + for (ptr = 0; sclk_tv[ptr]; ++ptr) + s3c_register_clksrc(sclk_tv[ptr], 1); + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 52b145e..133b5f2 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -24,6 +24,7 @@ #include <plat/devs.h> #include <plat/fimc-core.h> #include <plat/iic-core.h> +#include <plat/tv-core.h> #include <mach/regs-irq.h> @@ -130,6 +131,9 @@ void __init exynos4_map_io(void) s3c_fimc_setname(1, "exynos4-fimc"); s3c_fimc_setname(2, "exynos4-fimc"); s3c_fimc_setname(3, "exynos4-fimc"); + + /* setup TV devices */ + s5p_hdmi_setname("exynos4-hdmi"); } void __init exynos4_init_clocks(int xtal) diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h index 7e9eb1c..53e9c3c 100644 --- a/arch/arm/mach-exynos4/include/mach/irqs.h +++ b/arch/arm/mach-exynos4/include/mach/irqs.h @@ -124,6 +124,10 @@ #define IRQ_MCT_L1 COMBINER_IRQ(35, 3) +/* Set the default NR_IRQS */ +#define IRQ_MIXER COMBINER_IRQ(36, 0) +#define IRQ_SDO COMBINER_IRQ(36, 1) + #define IRQ_EINT4 COMBINER_IRQ(37, 0) #define IRQ_EINT5 COMBINER_IRQ(37, 1) #define IRQ_EINT6 COMBINER_IRQ(37, 2) diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h index 263f38b..df89627 100644 --- a/arch/arm/mach-exynos4/include/mach/map.h +++ b/arch/arm/mach-exynos4/include/mach/map.h @@ -160,4 +160,30 @@ #define S5P_SZ_UART SZ_256 +/* CEC */ +#define S5PV210_PA_CEC (0x100B0000) +#define S5P_PA_CEC S5PV210_PA_CEC +#define S5P_SZ_CEC SZ_4K + +/* TVOUT */ +#define S5PV210_PA_SDO (0x12C20000) +#define S5P_PA_SDO S5PV210_PA_SDO +#define S5P_SZ_SDO SZ_64K + +#define S5PV210_PA_VP (0x12C00000) +#define S5P_PA_VP S5PV210_PA_VP +#define S5P_SZ_VP SZ_64K + +#define S5PV210_PA_MIXER (0x12C10000) +#define S5P_PA_MIXER S5PV210_PA_MIXER +#define S5P_SZ_MIXER SZ_64K + +#define S5PV210_PA_HDMI (0x12D00000) +#define S5P_PA_HDMI S5PV210_PA_HDMI +#define S5P_SZ_HDMI SZ_1M + +#define S5PV210_I2C_HDMI_PHY (0x138E0000) +#define S5P_I2C_HDMI_PHY S5PV210_I2C_HDMI_PHY +#define S5P_I2C_HDMI_SZ_PHY SZ_1K + #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h index 2c1472b..b7e1bda 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h @@ -33,6 +33,7 @@ #define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210) #define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214) #define S5P_CLKSRC_CAM S5P_CLKREG(0x0C220) +#define S5P_CLKSRC_TV S5P_CLKREG(0x0C224) #define S5P_CLKSRC_MFC S5P_CLKREG(0x0C228) #define S5P_CLKSRC_IMAGE S5P_CLKREG(0x0C230) #define S5P_CLKSRC_LCD0 S5P_CLKREG(0x0C234) diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h index 62b0014..6bfb451 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h @@ -33,6 +33,12 @@ #define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) #define S5P_WAKEUP_MASK S5P_PMUREG(0x0608) +#define S5P_HDMI_PHY_CONTROL S5P_PMUREG(0x0700) +#define S5P_HDMI_PHY_ENABLE (1 << 0) + +#define S5P_DAC_PHY_CONTROL S5P_PMUREG(0x070C) +#define S5P_DAC_PHY_ENABLE (1 << 0) + #define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4) #define S5P_MIPI_DPHY_ENABLE (1 << 0) #define S5P_MIPI_DPHY_SRESETN (1 << 1) -- 1.7.5.1 -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html