All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] board: ge: bx50v3: Update display setup
@ 2016-03-15 18:10 Akshay Bhat
  2016-03-28 19:27 ` Akshay Bhat
  2016-04-06 15:18 ` Stefano Babic
  0 siblings, 2 replies; 6+ messages in thread
From: Akshay Bhat @ 2016-03-15 18:10 UTC (permalink / raw)
  To: u-boot

Implements the below changes:
- Disable LVDS1 on B450v3/B650v3 boards since the final boards no longer
have connectors for the same. Only LVDS0 hardware connectors are present.
- Implement imx6 EB821 or ERR009219 errata for LVDS clock switch.
This patch was ported from Freescale 3.10.17_1.0.0_ga kernel to u-boot.
- Split the display setup into 2 different functions. One for B850v3 that
does a setup of LVDS and HDMI with clock source for LVDS/IPU_DI set to
video PLL. The other for B450v3/B650v3 that does a setup of LVDS only with
clock source for LVDS/IPU_DI set to USB PLL. This helps us generate
accurate pixel clock required for display connected to LVDS.

Signed-off-by: Akshay Bhat <akshay.bhat@timesys.com>
Cc: Stefano Babic <sbabic@denx.de>
---
 board/ge/bx50v3/bx50v3.c | 240 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 198 insertions(+), 42 deletions(-)

diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c
index 70c298d..cf2cd1a 100644
--- a/board/ge/bx50v3/bx50v3.c
+++ b/board/ge/bx50v3/bx50v3.c
@@ -390,55 +390,208 @@ struct display_info_t const displays[] = {{
 } } };
 size_t display_count = ARRAY_SIZE(displays);
 
-static void setup_display(void)
+static void enable_videopll(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	s32 timeout = 100000;
+
+	setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
+
+	/* set video pll to 910MHz (24MHz * (37+11/12))
+	 * video pll post div to 910/4 = 227.5MHz
+	 */
+	clrsetbits_le32(&ccm->analog_pll_video,
+			BM_ANADIG_PLL_VIDEO_DIV_SELECT |
+			BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT,
+			BF_ANADIG_PLL_VIDEO_DIV_SELECT(37) |
+			BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0));
+
+	writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
+	writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
+
+	clrbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
+
+	while (timeout--)
+		if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
+			break;
+	if (timeout < 0)
+		printf("Warning: video pll lock timeout!\n");
+
+	clrsetbits_le32(&ccm->analog_pll_video,
+			BM_ANADIG_PLL_VIDEO_BYPASS,
+			BM_ANADIG_PLL_VIDEO_ENABLE);
+}
+
+static void set_ldb_clock_source(u8 source)
 {
 	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
-	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
 	int reg;
+	/*
+	 * Need to follow a strict procedure when changing the LDB
+	 * clock, else we can introduce a glitch. Things to keep in
+	 * mind:
+	 * 1. The current and new parent clocks must be disabled.
+	 * 2. The default clock for ldb_dio_clk is mmdc_ch1 which has
+	 * no CG bit.
+	 * 3. In the RTL implementation of the LDB_DI_CLK_SEL mux
+	 * the top four options are in one mux and the PLL3 option along
+	 * with another option is in the second mux. There is third mux
+	 * used to decide between the first and second mux.
+	 * The code below switches the parent to the bottom mux first
+	 * and then manipulates the top mux. This ensures that no glitch
+	 * will enter the divider.
+	 *
+	 * Need to disable MMDC_CH1 clock manually as there is no CG bit
+	 * for this clock. The only way to disable this clock is to move
+	 * it to pll3_sw_clk and then to disable pll3_sw_clk
+	 * Make sure periph2_clk2_sel is set to pll3_sw_clk
+	 */
+	/* Set MMDC_CH1 mask bit */
+	reg = readl(&mxc_ccm->ccdr);
+	reg |= MXC_CCM_CCDR_MMDC_CH1_HS_MASK;
+	writel(reg, &mxc_ccm->ccdr);
+
+	/* Set periph2_clk2_sel to be sourced from PLL3_sw_clk */
+	reg = readl(&mxc_ccm->cbcmr);
+	reg &= ~MXC_CCM_CBCMR_PERIPH2_CLK2_SEL;
+	writel(reg, &mxc_ccm->cbcmr);
+
+	/*
+	 * Set the periph2_clk_sel to the top mux so that
+	 * mmdc_ch1 is from pll3_sw_clk.
+	 */
+	reg = readl(&mxc_ccm->cbcdr);
+	reg |= MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
+	writel(reg, &mxc_ccm->cbcdr);
+
+	/* Wait for the clock switch */
+	while (readl(&mxc_ccm->cdhipr))
+		;
+	/* Disable pll3_sw_clk by selecting bypass clock source */
+	reg = readl(&mxc_ccm->ccsr);
+	reg |= MXC_CCM_CCSR_PLL3_SW_CLK_SEL;
+	writel(reg, &mxc_ccm->ccsr);
+
+	/* Set the ldb_di0_clk and ldb_di1_clk to 111b */
+	reg = readl(&mxc_ccm->cs2cdr);
+	reg |= ((7 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
+	      | (7 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
+	writel(reg, &mxc_ccm->cs2cdr);
 
-	enable_ipu_clock();
-	imx_setup_hdmi();
-
-	reg = readl(&mxc_ccm->CCGR3);
-	reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK;
-	writel(reg, &mxc_ccm->CCGR3);
+	/* Set the ldb_di0_clk and ldb_di1_clk to 100b */
+	reg = readl(&mxc_ccm->cs2cdr);
+	reg &= ~(MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK
+	      | MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK);
+	reg |= ((4 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
+	      | (4 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
+	writel(reg, &mxc_ccm->cs2cdr);
 
+	/* Set the ldb_di0_clk and ldb_di1_clk to desired source */
 	reg = readl(&mxc_ccm->cs2cdr);
-	reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK |
-		 MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
-	reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) |
-	       (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
+	reg &= ~(MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK
+	      | MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK);
+	reg |= ((source << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
+	      | (source << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
 	writel(reg, &mxc_ccm->cs2cdr);
 
-	reg = readl(&mxc_ccm->cscmr2);
-	reg |= (MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
-	writel(reg, &mxc_ccm->cscmr2);
-
-	reg = readl(&mxc_ccm->chsccdr);
-	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
-		<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
-	writel(reg, &mxc_ccm->chsccdr);
-
-	reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
-	     | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH
-	     | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
-	     | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
-	     | IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT
-	     | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
-	     | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT
-	     | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0
-	     | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
-	writel(reg, &iomux->gpr[2]);
-
-	reg = readl(&iomux->gpr[3]);
-	reg = (reg & ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
-		       IOMUXC_GPR3_LVDS1_MUX_CTL_MASK |
-		       IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
-	    | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
-	       << IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET)
-	    | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
-	       << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
-	writel(reg, &iomux->gpr[3]);
+	/* Unbypass pll3_sw_clk */
+	reg = readl(&mxc_ccm->ccsr);
+	reg &= ~MXC_CCM_CCSR_PLL3_SW_CLK_SEL;
+	writel(reg, &mxc_ccm->ccsr);
+
+	/*
+	 * Set the periph2_clk_sel back to the bottom mux so that
+	 * mmdc_ch1 is from its original parent.
+	 */
+	reg = readl(&mxc_ccm->cbcdr);
+	reg &= ~MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
+	writel(reg, &mxc_ccm->cbcdr);
+
+	/* Wait for the clock switch */
+	while (readl(&mxc_ccm->cdhipr))
+		;
+	/* Clear MMDC_CH1 mask bit */
+	reg = readl(&mxc_ccm->ccdr);
+	reg &= ~MXC_CCM_CCDR_MMDC_CH1_HS_MASK;
+	writel(reg, &mxc_ccm->ccdr);
+}
+
+static void setup_display_b850v3(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	/* Set LDB clock to Video PLL */
+	set_ldb_clock_source(0);
+	enable_videopll();
+
+	/* IPU1 D0 clock is 227.5 / 3.5 = 65MHz */
+	clrbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+
+	imx_setup_hdmi();
+
+	/* Set LDB_DI0 as clock source for IPU_DI0 */
+	clrsetbits_le32(&mxc_ccm->chsccdr,
+			MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK,
+			(CHSCCDR_CLK_SEL_LDB_DI0 <<
+			 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
+
+	/* Turn on IPU LDB DI0 clocks */
+	setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+	enable_ipu_clock();
+
+	writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
+	       IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW |
+	       IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
+	       IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG |
+	       IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT |
+	       IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
+	       IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
+	       IOMUXC_GPR2_SPLIT_MODE_EN_MASK |
+	       IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 |
+	       IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0,
+	       &iomux->gpr[2]);
+
+	clrbits_le32(&iomux->gpr[3],
+		     IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
+		     IOMUXC_GPR3_LVDS1_MUX_CTL_MASK |
+		     IOMUXC_GPR3_HDMI_MUX_CTL_MASK);
+}
+
+static void setup_display_bx50v3(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	/* Set LDB clock to USB PLL */
+	set_ldb_clock_source(4);
+
+	/* IPU1 DI0 clock is 480/7 = 68.5 MHz */
+	setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+
+	/* Set LDB_DI0 as clock source for IPU_DI0 */
+	clrsetbits_le32(&mxc_ccm->chsccdr,
+			MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK,
+			(CHSCCDR_CLK_SEL_LDB_DI0 <<
+			MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
+
+	/* Turn on IPU LDB DI0 clocks */
+	setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+	enable_ipu_clock();
+
+	writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
+	       IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
+	       IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
+	       IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
+	       IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0,
+	       &iomux->gpr[2]);
+
+	clrsetbits_le32(&iomux->gpr[3],
+			IOMUXC_GPR3_LVDS0_MUX_CTL_MASK,
+		       (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
+			IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET));
 
 	/* backlights off until needed */
 	imx_iomux_v3_setup_multiple_pads(backlight_pads,
@@ -487,7 +640,10 @@ int board_init(void)
 	gpio_direction_output(SUS_S3_OUT, 1);
 	gpio_direction_output(WIFI_EN, 1);
 #if defined(CONFIG_VIDEO_IPUV3)
-	setup_display();
+	if (IS_ENABLED(CONFIG_TARGET_GE_B850V3))
+		setup_display_b850v3();
+	else
+		setup_display_bx50v3();
 #endif
 	/* address of boot parameters */
 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
-- 
2.7.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH] board: ge: bx50v3: Update display setup
  2016-03-15 18:10 [U-Boot] [PATCH] board: ge: bx50v3: Update display setup Akshay Bhat
@ 2016-03-28 19:27 ` Akshay Bhat
  2016-04-06 15:18 ` Stefano Babic
  1 sibling, 0 replies; 6+ messages in thread
From: Akshay Bhat @ 2016-03-28 19:27 UTC (permalink / raw)
  To: u-boot

Hi Stefano,

On Tue, Mar 15, 2016 at 2:10 PM, Akshay Bhat <akshay.bhat@timesys.com> 
wrote:
> Implements the below changes:
> - Disable LVDS1 on B450v3/B650v3 boards since the final boards no longer
> have connectors for the same. Only LVDS0 hardware connectors are present.
> - Implement imx6 EB821 or ERR009219 errata for LVDS clock switch.
> This patch was ported from Freescale 3.10.17_1.0.0_ga kernel to u-boot.
> - Split the display setup into 2 different functions. One for B850v3 that
> does a setup of LVDS and HDMI with clock source for LVDS/IPU_DI set to
> video PLL. The other for B450v3/B650v3 that does a setup of LVDS only with
> clock source for LVDS/IPU_DI set to USB PLL. This helps us generate
> accurate pixel clock required for display connected to LVDS.
>
> Signed-off-by: Akshay Bhat <akshay.bhat@timesys.com>
> Cc: Stefano Babic <sbabic@denx.de>
> ---

Can this be applied if there are no review comments.

Thanks,
Akshay

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH] board: ge: bx50v3: Update display setup
  2016-03-15 18:10 [U-Boot] [PATCH] board: ge: bx50v3: Update display setup Akshay Bhat
  2016-03-28 19:27 ` Akshay Bhat
@ 2016-04-06 15:18 ` Stefano Babic
  2016-04-06 15:22   ` Fabio Estevam
  1 sibling, 1 reply; 6+ messages in thread
From: Stefano Babic @ 2016-04-06 15:18 UTC (permalink / raw)
  To: u-boot

Hi Akshay,

On 15/03/2016 19:10, Akshay Bhat wrote:
> Implements the below changes:
> - Disable LVDS1 on B450v3/B650v3 boards since the final boards no longer
> have connectors for the same. Only LVDS0 hardware connectors are present.
> - Implement imx6 EB821 or ERR009219 errata for LVDS clock switch.
> This patch was ported from Freescale 3.10.17_1.0.0_ga kernel to u-boot.
> - Split the display setup into 2 different functions. One for B850v3 that
> does a setup of LVDS and HDMI with clock source for LVDS/IPU_DI set to
> video PLL. The other for B450v3/B650v3 that does a setup of LVDS only with
> clock source for LVDS/IPU_DI set to USB PLL. This helps us generate
> accurate pixel clock required for display connected to LVDS.

I propose you split your patch exactly as you describe in the commit
message into 3 patches.

Generally, a patch/patchset should address a single issue. This lets to
better understand the workarounf with MMDC handshake, and let use it on
other boards too.

> 
> Signed-off-by: Akshay Bhat <akshay.bhat@timesys.com>
> Cc: Stefano Babic <sbabic@denx.de>
> ---
>  board/ge/bx50v3/bx50v3.c | 240 ++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 198 insertions(+), 42 deletions(-)
> 
> diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c
> index 70c298d..cf2cd1a 100644
> --- a/board/ge/bx50v3/bx50v3.c
> +++ b/board/ge/bx50v3/bx50v3.c
> @@ -390,55 +390,208 @@ struct display_info_t const displays[] = {{
>  } } };
>  size_t display_count = ARRAY_SIZE(displays);
>  
> -static void setup_display(void)
> +static void enable_videopll(void)
> +{
> +	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +	s32 timeout = 100000;
> +
> +	setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
> +
> +	/* set video pll to 910MHz (24MHz * (37+11/12))
> +	 * video pll post div to 910/4 = 227.5MHz
> +	 */
> +	clrsetbits_le32(&ccm->analog_pll_video,
> +			BM_ANADIG_PLL_VIDEO_DIV_SELECT |
> +			BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT,
> +			BF_ANADIG_PLL_VIDEO_DIV_SELECT(37) |
> +			BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0));
> +
> +	writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
> +	writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
> +
> +	clrbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
> +
> +	while (timeout--)
> +		if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
> +			break;
> +	if (timeout < 0)
> +		printf("Warning: video pll lock timeout!\n");
> +
> +	clrsetbits_le32(&ccm->analog_pll_video,
> +			BM_ANADIG_PLL_VIDEO_BYPASS,
> +			BM_ANADIG_PLL_VIDEO_ENABLE);
> +}
> +
> +static void set_ldb_clock_source(u8 source)
>  {
>  	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> -	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
>  	int reg;
> +	/*
> +	 * Need to follow a strict procedure when changing the LDB
> +	 * clock, else we can introduce a glitch. Things to keep in
> +	 * mind:
> +	 * 1. The current and new parent clocks must be disabled.
> +	 * 2. The default clock for ldb_dio_clk is mmdc_ch1 which has
> +	 * no CG bit.
> +	 * 3. In the RTL implementation of the LDB_DI_CLK_SEL mux
> +	 * the top four options are in one mux and the PLL3 option along
> +	 * with another option is in the second mux. There is third mux
> +	 * used to decide between the first and second mux.
> +	 * The code below switches the parent to the bottom mux first
> +	 * and then manipulates the top mux. This ensures that no glitch
> +	 * will enter the divider.
> +	 *
> +	 * Need to disable MMDC_CH1 clock manually as there is no CG bit
> +	 * for this clock. The only way to disable this clock is to move
> +	 * it to pll3_sw_clk and then to disable pll3_sw_clk
> +	 * Make sure periph2_clk2_sel is set to pll3_sw_clk
> +	 */
> +	/* Set MMDC_CH1 mask bit */
> +	reg = readl(&mxc_ccm->ccdr);
> +	reg |= MXC_CCM_CCDR_MMDC_CH1_HS_MASK;
> +	writel(reg, &mxc_ccm->ccdr);
> +
> +	/* Set periph2_clk2_sel to be sourced from PLL3_sw_clk */
> +	reg = readl(&mxc_ccm->cbcmr);
> +	reg &= ~MXC_CCM_CBCMR_PERIPH2_CLK2_SEL;
> +	writel(reg, &mxc_ccm->cbcmr);
> +
> +	/*
> +	 * Set the periph2_clk_sel to the top mux so that
> +	 * mmdc_ch1 is from pll3_sw_clk.
> +	 */
> +	reg = readl(&mxc_ccm->cbcdr);
> +	reg |= MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
> +	writel(reg, &mxc_ccm->cbcdr);
> +
> +	/* Wait for the clock switch */
> +	while (readl(&mxc_ccm->cdhipr))
> +		;
> +	/* Disable pll3_sw_clk by selecting bypass clock source */
> +	reg = readl(&mxc_ccm->ccsr);
> +	reg |= MXC_CCM_CCSR_PLL3_SW_CLK_SEL;
> +	writel(reg, &mxc_ccm->ccsr);
> +
> +	/* Set the ldb_di0_clk and ldb_di1_clk to 111b */
> +	reg = readl(&mxc_ccm->cs2cdr);
> +	reg |= ((7 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
> +	      | (7 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
> +	writel(reg, &mxc_ccm->cs2cdr);
>  
> -	enable_ipu_clock();
> -	imx_setup_hdmi();
> -
> -	reg = readl(&mxc_ccm->CCGR3);
> -	reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK;
> -	writel(reg, &mxc_ccm->CCGR3);
> +	/* Set the ldb_di0_clk and ldb_di1_clk to 100b */
> +	reg = readl(&mxc_ccm->cs2cdr);
> +	reg &= ~(MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK
> +	      | MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK);
> +	reg |= ((4 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
> +	      | (4 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
> +	writel(reg, &mxc_ccm->cs2cdr);
>  
> +	/* Set the ldb_di0_clk and ldb_di1_clk to desired source */
>  	reg = readl(&mxc_ccm->cs2cdr);
> -	reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK |
> -		 MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
> -	reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) |
> -	       (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
> +	reg &= ~(MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK
> +	      | MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK);
> +	reg |= ((source << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
> +	      | (source << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
>  	writel(reg, &mxc_ccm->cs2cdr);
>  
> -	reg = readl(&mxc_ccm->cscmr2);
> -	reg |= (MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
> -	writel(reg, &mxc_ccm->cscmr2);
> -
> -	reg = readl(&mxc_ccm->chsccdr);
> -	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
> -		<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
> -	writel(reg, &mxc_ccm->chsccdr);
> -
> -	reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
> -	     | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH
> -	     | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
> -	     | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
> -	     | IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT
> -	     | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
> -	     | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT
> -	     | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0
> -	     | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
> -	writel(reg, &iomux->gpr[2]);
> -
> -	reg = readl(&iomux->gpr[3]);
> -	reg = (reg & ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
> -		       IOMUXC_GPR3_LVDS1_MUX_CTL_MASK |
> -		       IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
> -	    | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
> -	       << IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET)
> -	    | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
> -	       << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
> -	writel(reg, &iomux->gpr[3]);
> +	/* Unbypass pll3_sw_clk */
> +	reg = readl(&mxc_ccm->ccsr);
> +	reg &= ~MXC_CCM_CCSR_PLL3_SW_CLK_SEL;
> +	writel(reg, &mxc_ccm->ccsr);
> +
> +	/*
> +	 * Set the periph2_clk_sel back to the bottom mux so that
> +	 * mmdc_ch1 is from its original parent.
> +	 */
> +	reg = readl(&mxc_ccm->cbcdr);
> +	reg &= ~MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
> +	writel(reg, &mxc_ccm->cbcdr);
> +
> +	/* Wait for the clock switch */
> +	while (readl(&mxc_ccm->cdhipr))
> +		;
> +	/* Clear MMDC_CH1 mask bit */
> +	reg = readl(&mxc_ccm->ccdr);
> +	reg &= ~MXC_CCM_CCDR_MMDC_CH1_HS_MASK;
> +	writel(reg, &mxc_ccm->ccdr);
> +}

I frankly ask you if you think that this function can be factorized and
moved from board code to common code. What do you think ? Is there
something that let the implementation bound to the board (I have not
seen it) ?

> +
> +static void setup_display_b850v3(void)
> +{
> +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
> +
> +	/* Set LDB clock to Video PLL */
> +	set_ldb_clock_source(0);
> +	enable_videopll();
> +
> +	/* IPU1 D0 clock is 227.5 / 3.5 = 65MHz */
> +	clrbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
> +
> +	imx_setup_hdmi();
> +
> +	/* Set LDB_DI0 as clock source for IPU_DI0 */
> +	clrsetbits_le32(&mxc_ccm->chsccdr,
> +			MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK,
> +			(CHSCCDR_CLK_SEL_LDB_DI0 <<
> +			 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
> +
> +	/* Turn on IPU LDB DI0 clocks */
> +	setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
> +
> +	enable_ipu_clock();
> +
> +	writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
> +	       IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW |
> +	       IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
> +	       IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG |
> +	       IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT |
> +	       IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
> +	       IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
> +	       IOMUXC_GPR2_SPLIT_MODE_EN_MASK |
> +	       IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 |
> +	       IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0,
> +	       &iomux->gpr[2]);
> +
> +	clrbits_le32(&iomux->gpr[3],
> +		     IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
> +		     IOMUXC_GPR3_LVDS1_MUX_CTL_MASK |
> +		     IOMUXC_GPR3_HDMI_MUX_CTL_MASK);
> +}
> +
> +static void setup_display_bx50v3(void)
> +{
> +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
> +
> +	/* Set LDB clock to USB PLL */
> +	set_ldb_clock_source(4);
> +
> +	/* IPU1 DI0 clock is 480/7 = 68.5 MHz */
> +	setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
> +
> +	/* Set LDB_DI0 as clock source for IPU_DI0 */
> +	clrsetbits_le32(&mxc_ccm->chsccdr,
> +			MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK,
> +			(CHSCCDR_CLK_SEL_LDB_DI0 <<
> +			MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
> +
> +	/* Turn on IPU LDB DI0 clocks */
> +	setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
> +
> +	enable_ipu_clock();
> +
> +	writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
> +	       IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
> +	       IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
> +	       IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
> +	       IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0,
> +	       &iomux->gpr[2]);
> +
> +	clrsetbits_le32(&iomux->gpr[3],
> +			IOMUXC_GPR3_LVDS0_MUX_CTL_MASK,
> +		       (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
> +			IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET));
>  
>  	/* backlights off until needed */
>  	imx_iomux_v3_setup_multiple_pads(backlight_pads,
> @@ -487,7 +640,10 @@ int board_init(void)
>  	gpio_direction_output(SUS_S3_OUT, 1);
>  	gpio_direction_output(WIFI_EN, 1);
>  #if defined(CONFIG_VIDEO_IPUV3)
> -	setup_display();
> +	if (IS_ENABLED(CONFIG_TARGET_GE_B850V3))
> +		setup_display_b850v3();
> +	else
> +		setup_display_bx50v3();
>  #endif
>  	/* address of boot parameters */
>  	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
> 

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH] board: ge: bx50v3: Update display setup
  2016-04-06 15:18 ` Stefano Babic
@ 2016-04-06 15:22   ` Fabio Estevam
  2016-04-07  5:10     ` Akshay Bhat
  0 siblings, 1 reply; 6+ messages in thread
From: Fabio Estevam @ 2016-04-06 15:22 UTC (permalink / raw)
  To: u-boot

On Wed, Apr 6, 2016 at 12:18 PM, Stefano Babic <sbabic@denx.de> wrote:

> I frankly ask you if you think that this function can be factorized and
> moved from board code to common code. What do you think ? Is there
> something that let the implementation bound to the board (I have not
> seen it) ?

Agreed. This should be in common code so that other boards can use it.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH] board: ge: bx50v3: Update display setup
  2016-04-06 15:22   ` Fabio Estevam
@ 2016-04-07  5:10     ` Akshay Bhat
  2016-04-07 12:29       ` Fabio Estevam
  0 siblings, 1 reply; 6+ messages in thread
From: Akshay Bhat @ 2016-04-07  5:10 UTC (permalink / raw)
  To: u-boot

On Wed, Apr 6, 2016 at 11:22 AM, Fabio Estevam <festevam@gmail.com> wrote:

> On Wed, Apr 6, 2016 at 12:18 PM, Stefano Babic <sbabic@denx.de> wrote:
>
> > I frankly ask you if you think that this function can be factorized and
> > moved from board code to common code. What do you think ? Is there
> > something that let the implementation bound to the board (I have not
> > seen it) ?
>
> Agreed. This should be in common code so that other boards can use it.
>

Appreciate the feedback. I will break up the commits and resubmit the
patch, moving the function to common code.

Fabio, does the errata apply to all i.MX6 based processors? If not, which
ones should use the errata?

Thanks,
Akshay

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH] board: ge: bx50v3: Update display setup
  2016-04-07  5:10     ` Akshay Bhat
@ 2016-04-07 12:29       ` Fabio Estevam
  0 siblings, 0 replies; 6+ messages in thread
From: Fabio Estevam @ 2016-04-07 12:29 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 7, 2016 at 2:10 AM, Akshay Bhat <akshay.bhat@timesys.com> wrote:

> Appreciate the feedback. I will break up the commits and resubmit the patch,
> moving the function to common code.
>
> Fabio, does the errata apply to all i.MX6 based processors? If not, which
> ones should use the errata?

mx6 quad/dl/solo.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-04-07 12:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-15 18:10 [U-Boot] [PATCH] board: ge: bx50v3: Update display setup Akshay Bhat
2016-03-28 19:27 ` Akshay Bhat
2016-04-06 15:18 ` Stefano Babic
2016-04-06 15:22   ` Fabio Estevam
2016-04-07  5:10     ` Akshay Bhat
2016-04-07 12:29       ` Fabio Estevam

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.