From e332623b0328f91c76d99c356c350fc04b1fc8dc Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Sun, 11 Dec 2016 19:24:27 +0800 Subject: imx: mx6sl: add lcdif clock support Add lcdif clock support for i.MX6SL. Signed-off-by: Peng Fan --- arch/arm/cpu/armv7/mx6/clock.c | 78 ++++++++++++++++++++++++-------- arch/arm/include/asm/arch-mx6/crm_regs.h | 21 +++++++++ 2 files changed, 80 insertions(+), 19 deletions(-) diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 2092260..007c135 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -625,16 +625,18 @@ void mxs_set_lcdclk(u32 base_addr, u32 freq) debug("mxs_set_lcdclk, freq = %dKHz\n", freq); - if (!is_mx6sx() && !is_mx6ul() && !is_mx6ull()) { + if (!is_mx6sx() && !is_mx6ul() && !is_mx6ull() && !is_mx6sl()) { debug("This chip not support lcd!\n"); return; } - if (base_addr == LCDIF1_BASE_ADDR) { - reg = readl(&imx_ccm->cscdr2); - /* Can't change clocks when clock not from pre-mux */ - if ((reg & MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK) != 0) - return; + if (!is_mx6sl()) { + if (base_addr == LCDIF1_BASE_ADDR) { + reg = readl(&imx_ccm->cscdr2); + /* Can't change clocks when clock not from pre-mux */ + if ((reg & MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK) != 0) + return; + } } if (is_mx6sx()) { @@ -705,19 +707,35 @@ void mxs_set_lcdclk(u32 base_addr, u32 freq) if (enable_pll_video(pll_div, pll_num, pll_denom, post_div)) return; - /* Select pre-lcd clock to PLL5 and set pre divider */ - clrsetbits_le32(&imx_ccm->cscdr2, - MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_MASK | - MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_MASK, - (0x2 << MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_OFFSET) | - ((pred - 1) << - MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_OFFSET)); - - /* Set the post divider */ - clrsetbits_le32(&imx_ccm->cbcmr, - MXC_CCM_CBCMR_LCDIF1_PODF_MASK, - ((postd - 1) << - MXC_CCM_CBCMR_LCDIF1_PODF_OFFSET)); + if (!is_mx6sl()) { + /* Select pre-lcd clock to PLL5 and set pre divider */ + clrsetbits_le32(&imx_ccm->cscdr2, + MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_MASK | + MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_MASK, + (0x2 << MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_OFFSET) | + ((pred - 1) << + MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_OFFSET)); + + /* Set the post divider */ + clrsetbits_le32(&imx_ccm->cbcmr, + MXC_CCM_CBCMR_LCDIF1_PODF_MASK, + ((postd - 1) << + MXC_CCM_CBCMR_LCDIF1_PODF_OFFSET)); + } else { + /* Select pre-lcd clock to PLL5 and set pre divider */ + clrsetbits_le32(&imx_ccm->cscdr2, + MXC_CCM_CSCDR2_LCDIF_PIX_CLK_SEL_MASK | + MXC_CCM_CSCDR2_LCDIF_PIX_PRE_DIV_MASK, + (0x2 << MXC_CCM_CSCDR2_LCDIF_PIX_CLK_SEL_OFFSET) | + ((pred - 1) << + MXC_CCM_CSCDR2_LCDIF_PIX_PRE_DIV_OFFSET)); + + /* Set the post divider */ + clrsetbits_le32(&imx_ccm->cscmr1, + MXC_CCM_CSCMR1_LCDIF_PIX_PODF_MASK, + (((postd - 1)^0x6) << + MXC_CCM_CSCMR1_LCDIF_PIX_PODF_OFFSET)); + } } else if (is_mx6sx()) { /* Setting LCDIF2 for i.MX6SX */ if (enable_pll_video(pll_div, pll_num, pll_denom, post_div)) @@ -767,6 +785,28 @@ int enable_lcdif_clock(u32 base_addr) /* Set to pre-mux clock at default */ lcdif_clk_sel_mask = MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK; lcdif_ccgr3_mask = MXC_CCM_CCGR3_LCDIF1_PIX_MASK; + } else if (is_mx6sl()) { + if (base_addr != LCDIF1_BASE_ADDR) { + puts("Wrong LCD interface!\n"); + return -EINVAL; + } + + reg = readl(&imx_ccm->CCGR3); + reg &= ~(MXC_CCM_CCGR3_LCDIF_AXI_MASK | + MXC_CCM_CCGR3_LCDIF_PIX_MASK); + writel(reg, &imx_ccm->CCGR3); + + reg = readl(&imx_ccm->cscdr3); + reg &= ~MXC_CCM_CSCDR3_LCDIF_AXI_CLK_SEL_MASK; + reg |= 1 << MXC_CCM_CSCDR3_LCDIF_AXI_CLK_SEL_OFFSET; + writel(reg, &imx_ccm->cscdr3); + + reg = readl(&imx_ccm->CCGR3); + reg |= MXC_CCM_CCGR3_LCDIF_AXI_MASK | + MXC_CCM_CCGR3_LCDIF_PIX_MASK; + writel(reg, &imx_ccm->CCGR3); + + return 0; } else { return 0; } diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index 29674ce..74ed912 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -307,6 +307,9 @@ struct mxc_ccm_reg { /* LCFIF2_PODF on i.MX6SX */ #define MXC_CCM_CSCMR1_LCDIF2_PODF_MASK (0x7 << 20) #define MXC_CCM_CSCMR1_LCDIF2_PODF_OFFSET 20 +/* LCDIF_PIX_PODF on i.MX6SL */ +#define MXC_CCM_CSCMR1_LCDIF_PIX_PODF_MASK (0x7 << 20) +#define MXC_CCM_CSCMR1_LCDIF_PIX_PODF_OFFSET 20 /* ACLK_EMI on i.MX6DQ/SDL/DQP */ #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << 20) #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET 20 @@ -529,6 +532,12 @@ struct mxc_ccm_reg { #define MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK (0x7 << 0) #define MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_OFFSET 0 +/*LCD on i.MX6SL */ +#define MXC_CCM_CSCDR2_LCDIF_PIX_CLK_SEL_MASK (0x7 << 6) +#define MXC_CCM_CSCDR2_LCDIF_PIX_CLK_SEL_OFFSET 6 +#define MXC_CCM_CSCDR2_LCDIF_PIX_PRE_DIV_MASK (0x7 << 3) +#define MXC_CCM_CSCDR2_LCDIF_PIX_PRE_DIV_OFFSET 3 + /* All IPU2_DI1 are LCDIF1 on MX6SX */ #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << 15) #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_OFFSET 15 @@ -554,6 +563,12 @@ struct mxc_ccm_reg { #define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK (0x3 << 9) #define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET 9 +/* For i.MX6SL */ +#define MXC_CCM_CSCDR3_LCDIF_AXI_PODF_MASK (0x7 << 16) +#define MXC_CCM_CSCDR3_LCDIF_AXI_PODF_OFFSET 16 +#define MXC_CCM_CSCDR3_LCDIF_AXI_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCDR3_LCDIF_AXI_CLK_SEL_OFFSET 14 + /* Define the bits in register CDHIPR */ #define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) #define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) @@ -783,6 +798,12 @@ struct mxc_ccm_reg { #define MXC_CCM_CCGR3_QSPI_OFFSET 14 #define MXC_CCM_CCGR3_QSPI_MASK (3 << MXC_CCM_CCGR3_QSPI_OFFSET) +/* i.MX6SL */ +#define MXC_CCM_CCGR3_LCDIF_AXI_OFFSET 6 +#define MXC_CCM_CCGR3_LCDIF_AXI_MASK (3 << MXC_CCM_CCGR3_LCDIF_AXI_OFFSET) +#define MXC_CCM_CCGR3_LCDIF_PIX_OFFSET 8 +#define MXC_CCM_CCGR3_LCDIF_PIX_MASK (3 << MXC_CCM_CCGR3_LCDIF_PIX_OFFSET) + #define MXC_CCM_CCGR3_IPU1_IPU_OFFSET 0 #define MXC_CCM_CCGR3_IPU1_IPU_MASK (3 << MXC_CCM_CCGR3_IPU1_IPU_OFFSET) #define MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET 2 -- cgit v1.1