Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
u-boot-ge: Add u-boot recipe for GE i.MX6 boards
This recipe is a fork of the fslc u-boot with patches for supporting the imx6q-elo platform. This recipe is intended to be a stop-gap until the imx6q-elo board can be rebased and tested with the most recent fslc branch. Signed-off-by: Justin Waters <justin.waters@timesys.com> Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
- Loading branch information
1 parent
fef20e7
commit a100778
Showing
8 changed files
with
2,349 additions
and
0 deletions.
There are no files selected for viewing
1,245 changes: 1,245 additions & 0 deletions
1,245
recipes-bsp/u-boot/u-boot-ge-2015.10/0001-arm-imx-Add-support-for-GE-Bx50v3-boards.patch
Large diffs are not rendered by default.
Oops, something went wrong.
293 changes: 293 additions & 0 deletions
293
recipes-bsp/u-boot/u-boot-ge-2015.10/0002-board-ge-bx50v3-Update-display-setup.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
From 047844511f92e9e9ea089f019318280cb4c3a75a Mon Sep 17 00:00:00 2001 | ||
From: Akshay Bhat <akshay.bhat@timesys.com> | ||
Date: Thu, 4 Feb 2016 12:22:52 -0500 | ||
Subject: [PATCH 2/7] board: ge: bx50v3: Update display setup | ||
|
||
- Disable LVDS1 on B450v3/B650v3 boards since they no longer have | ||
connectors for it. | ||
- Implement imx6 MLK-10782-3 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. | ||
|
||
Upstream-Status: Pending | ||
|
||
Waiting on v2 patch to get accepted. | ||
http://lists.denx.de/pipermail/u-boot/2016-January/243985.html | ||
|
||
Signed-off-by: Akshay Bhat <akshay.bhat@timesys.com> | ||
--- | ||
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.5.0 | ||
|
Oops, something went wrong.