summaryrefslogtreecommitdiff
path: root/board/freescale/mx6q_arm2/mx6q_arm2.c
diff options
context:
space:
mode:
authorDanny Nold <dannynold@freescale.com>2012-05-30 09:10:39 -0500
committerDanny Nold <dannynold@freescale.com>2012-05-30 09:10:39 -0500
commit41e9b04376a74ee74133368d9f5b18ee033efa55 (patch)
treedbe569f42a85f0733a17469fad2f216e963b8550 /board/freescale/mx6q_arm2/mx6q_arm2.c
parent75752c1cbe95c9f6241f3054b6435312d6708a38 (diff)
downloadu-boot-imx-41e9b04376a74ee74133368d9f5b18ee033efa55.zip
u-boot-imx-41e9b04376a74ee74133368d9f5b18ee033efa55.tar.gz
u-boot-imx-41e9b04376a74ee74133368d9f5b18ee033efa55.tar.bz2
ENGR00211117 - U-Boot: Add EPDC splash screen for MX 6DL/S platforms
- EPDC Splash support for MX6DL/S Sabre SD - EPDC Splash support for MX6DL/S ARM2 - Currently, splash screen consists of a simple black border around a white screen. Done this way to save in memory footprint. Signed-off-by: Danny Nold <dannynold@freescale.com>
Diffstat (limited to 'board/freescale/mx6q_arm2/mx6q_arm2.c')
-rw-r--r--board/freescale/mx6q_arm2/mx6q_arm2.c298
1 files changed, 298 insertions, 0 deletions
diff --git a/board/freescale/mx6q_arm2/mx6q_arm2.c b/board/freescale/mx6q_arm2/mx6q_arm2.c
index d78c704..4e189d8 100644
--- a/board/freescale/mx6q_arm2/mx6q_arm2.c
+++ b/board/freescale/mx6q_arm2/mx6q_arm2.c
@@ -38,9 +38,13 @@
#include <linux/fb.h>
#include <linux/mxcfb.h>
#include <ipu.h>
+#endif
+#if defined(CONFIG_VIDEO_MX5) || defined(CONFIG_MXC_EPDC)
#include <lcd.h>
#endif
+#include "../../../drivers/video/mxc_epdc_fb.h"
+
#ifdef CONFIG_IMX_ECSPI
#include <imx_spi.h>
#endif
@@ -737,6 +741,294 @@ int board_mmc_init(bd_t *bis)
return -1;
}
+#ifdef CONFIG_MXC_EPDC
+#ifdef CONFIG_SPLASH_SCREEN
+int setup_splash_img()
+{
+#ifdef CONFIG_SPLASH_IS_IN_MMC
+ int mmc_dev = get_mmc_env_devno();
+ ulong offset = CONFIG_SPLASH_IMG_OFFSET;
+ ulong size = CONFIG_SPLASH_IMG_SIZE;
+ ulong addr = 0;
+ char *s = NULL;
+ struct mmc *mmc = find_mmc_device(mmc_dev);
+ uint blk_start, blk_cnt, n;
+
+ s = getenv("splashimage");
+
+ if (NULL == s) {
+ puts("env splashimage not found!\n");
+ return -1;
+ }
+ addr = simple_strtoul(s, NULL, 16);
+
+ if (!mmc) {
+ printf("MMC Device %d not found\n",
+ mmc_dev);
+ return -1;
+ }
+
+ if (mmc_init(mmc)) {
+ puts("MMC init failed\n");
+ return -1;
+ }
+
+ blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
+ blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
+ n = mmc->block_dev.block_read(mmc_dev, blk_start,
+ blk_cnt, (u_char *)addr);
+ flush_cache((ulong)addr, blk_cnt * mmc->read_bl_len);
+
+ return (n == blk_cnt) ? 0 : -1;
+#endif
+}
+#endif
+
+vidinfo_t panel_info = {
+ .vl_refresh = 85,
+ .vl_col = 800,
+ .vl_row = 600,
+ .vl_pixclock = 26666667,
+ .vl_left_margin = 8,
+ .vl_right_margin = 100,
+ .vl_upper_margin = 4,
+ .vl_lower_margin = 8,
+ .vl_hsync = 4,
+ .vl_vsync = 1,
+ .vl_sync = 0,
+ .vl_mode = 0,
+ .vl_flag = 0,
+ .vl_bpix = 3,
+ cmap:0,
+};
+
+struct epdc_timing_params panel_timings = {
+ .vscan_holdoff = 4,
+ .sdoed_width = 10,
+ .sdoed_delay = 20,
+ .sdoez_width = 10,
+ .sdoez_delay = 20,
+ .gdclk_hp_offs = 419,
+ .gdsp_offs = 20,
+ .gdoe_offs = 0,
+ .gdclk_offs = 5,
+ .num_ce = 1,
+};
+
+static void setup_epdc_power()
+{
+ unsigned int reg;
+
+ /* Setup epdc voltage */
+
+ /* EIM_A17 - GPIO2[21] for PWR_GOOD status */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A17__GPIO_2_21);
+
+ /* EIM_D17 - GPIO3[17] for VCOM control */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_D17__GPIO_3_17);
+
+ /* Set as output */
+ reg = readl(GPIO3_BASE_ADDR + GPIO_GDIR);
+ reg |= (1 << 17);
+ writel(reg, GPIO3_BASE_ADDR + GPIO_GDIR);
+
+ /* EIM_D20 - GPIO3[20] for EPD PMIC WAKEUP */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_D20__GPIO_3_20);
+ /* Set as output */
+ reg = readl(GPIO3_BASE_ADDR + GPIO_GDIR);
+ reg |= (1 << 20);
+ writel(reg, GPIO3_BASE_ADDR + GPIO_GDIR);
+
+ /* EIM_A18 - GPIO2[20] for EPD PWR CTL0 */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A18__GPIO_2_20);
+ /* Set as output */
+ reg = readl(GPIO2_BASE_ADDR + GPIO_GDIR);
+ reg |= (1 << 20);
+ writel(reg, GPIO2_BASE_ADDR + GPIO_GDIR);
+}
+
+unsigned int g_pgood_1, g_pgood_2, g_pgood_3;
+void epdc_power_on()
+{
+ unsigned int reg;
+
+ g_pgood_1 = readl(GPIO2_BASE_ADDR + GPIO_DR);
+
+ /* Set EPD_PWR_CTL0 to high - enable EINK_VDD (3.15) */
+ reg = readl(GPIO2_BASE_ADDR + GPIO_DR);
+ reg |= (1 << 20);
+ writel(reg, GPIO2_BASE_ADDR + GPIO_DR);
+
+ /* Set PMIC Wakeup to high - enable Display power */
+ reg = readl(GPIO3_BASE_ADDR + GPIO_DR);
+ reg |= (1 << 20);
+ writel(reg, GPIO3_BASE_ADDR + GPIO_DR);
+
+ g_pgood_2 = readl(GPIO2_BASE_ADDR + GPIO_DR);
+ udelay(1000000);
+ g_pgood_3 = readl(GPIO2_BASE_ADDR + GPIO_DR);
+return;
+ /* Wait for PWRGOOD == 1 */
+ while (1) {
+ reg = readl(GPIO2_BASE_ADDR + GPIO_DR);
+ if (!(reg & (1 << 21)))
+ break;
+
+ udelay(100);
+ }
+
+ /* Enable VCOM */
+ reg = readl(GPIO3_BASE_ADDR + GPIO_DR);
+ reg |= (1 << 17);
+ writel(reg, GPIO3_BASE_ADDR + GPIO_DR);
+
+ reg = readl(GPIO3_BASE_ADDR + GPIO_DR);
+
+ udelay(500);
+}
+
+void epdc_power_off()
+{
+ unsigned int reg;
+ /* Set PMIC Wakeup to low - disable Display power */
+ reg = readl(GPIO3_BASE_ADDR + GPIO_DR);
+ reg &= ~(1 << 20);
+ writel(reg, GPIO3_BASE_ADDR + GPIO_DR);
+
+ /* Disable VCOM */
+ reg = readl(GPIO3_BASE_ADDR + GPIO_DR);
+ reg &= ~(1 << 17);
+ writel(reg, GPIO3_BASE_ADDR + GPIO_DR);
+
+ /* Set EPD_PWR_CTL0 to low - disable EINK_VDD (3.15) */
+ reg = readl(GPIO2_BASE_ADDR + GPIO_DR);
+ reg &= ~(1 << 20);
+ writel(reg, GPIO2_BASE_ADDR + GPIO_DR);
+}
+
+int setup_waveform_file()
+{
+#ifdef CONFIG_WAVEFORM_FILE_IN_MMC
+ int mmc_dev = get_mmc_env_devno();
+ ulong offset = CONFIG_WAVEFORM_FILE_OFFSET;
+ ulong size = CONFIG_WAVEFORM_FILE_SIZE;
+ ulong addr = CONFIG_WAVEFORM_BUF_ADDR;
+ char *s = NULL;
+ struct mmc *mmc = find_mmc_device(mmc_dev);
+ uint blk_start, blk_cnt, n;
+
+ if (!mmc) {
+ printf("MMC Device %d not found\n",
+ mmc_dev);
+ return -1;
+ }
+
+ if (mmc_init(mmc)) {
+ puts("MMC init failed\n");
+ return -1;
+ }
+
+ blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
+ blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
+ n = mmc->block_dev.block_read(mmc_dev, blk_start,
+ blk_cnt, (u_char *)addr);
+ flush_cache((ulong)addr, blk_cnt * mmc->read_bl_len);
+
+ return (n == blk_cnt) ? 0 : -1;
+#else
+ return -1;
+#endif
+}
+
+static void setup_epdc()
+{
+ unsigned int reg;
+
+ /* epdc iomux settings */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A16__EPDC_SDDO_0);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA10__EPDC_SDDO_1);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA12__EPDC_SDDO_2);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA11__EPDC_SDDO_3);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_LBA__EPDC_SDDO_4);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_EB2__EPDC_SDDO_5);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_CS0__EPDC_SDDO_6);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_RW__EPDC_SDDO_7);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A21__EPDC_GDCLK);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A22__EPDC_GDSP);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A23__EPDC_GDOE);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A24__EPDC_GDRL);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_D31__EPDC_SDCLK);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_D27__EPDC_SDOE);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA1__EPDC_SDLE);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_EB1__EPDC_SDSHR);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA2__EPDC_BDR_0);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA4__EPDC_SDCE_0);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA5__EPDC_SDCE_1);
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_DA6__EPDC_SDCE_2);
+
+ /*** epdc Maxim PMIC settings ***/
+
+ /* EPDC PWRSTAT - GPIO2[21] for PWR_GOOD status */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A17__GPIO_2_21);
+
+ /* EPDC VCOM0 - GPIO3[17] for VCOM control */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_D17__GPIO_3_17);
+
+ /* UART4 TXD - GPIO3[20] for EPD PMIC WAKEUP */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_D20__GPIO_3_20);
+
+ /* EIM_A18 - GPIO2[20] for EPD PWR CTL0 */
+ mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_A18__GPIO_2_20);
+
+ /*** Set pixel clock rates for EPDC ***/
+
+ /* EPDC AXI clk (IPU2_CLK) from PFD_400M, set to 396/2 = 198MHz */
+ reg = readl(CCM_BASE_ADDR + CLKCTL_CSCDR3);
+ reg &= ~0x7C000;
+ reg |= (1 << 16) | (1 << 14);
+ writel(reg, CCM_BASE_ADDR + CLKCTL_CSCDR3);
+
+ /* EPDC AXI clk enable */
+ reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3);
+ reg |= 0x00C0;
+ writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3);
+
+ /* EPDC PIX clk (IPU2_DI1_CLK) from PLL5, set to 650/4/6 = ~27MHz */
+ reg = readl(CCM_BASE_ADDR + CLKCTL_CSCDR2);
+ reg &= ~0x3FE00;
+ reg |= (2 << 15) | (5 << 12);
+ writel(reg, CCM_BASE_ADDR + CLKCTL_CSCDR2);
+
+ /* EPDC PIX clk enable */
+ reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3);
+ reg |= 0x0C00;
+ writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3);
+
+ /* PLL5 enable (defaults to 650) */
+ reg = readl(ANATOP_BASE_ADDR + ANATOP_PLL_VIDEO);
+ reg &= ~((1 << 16) | (1 << 12));
+ reg |= (1 << 13);
+ writel(reg, ANATOP_BASE_ADDR + ANATOP_PLL_VIDEO);
+
+ panel_info.epdc_data.working_buf_addr = CONFIG_WORKING_BUF_ADDR;
+ panel_info.epdc_data.waveform_buf_addr = CONFIG_WAVEFORM_BUF_ADDR;
+
+ panel_info.epdc_data.wv_modes.mode_init = 0;
+ panel_info.epdc_data.wv_modes.mode_du = 1;
+ panel_info.epdc_data.wv_modes.mode_gc4 = 3;
+ panel_info.epdc_data.wv_modes.mode_gc8 = 2;
+ panel_info.epdc_data.wv_modes.mode_gc16 = 2;
+ panel_info.epdc_data.wv_modes.mode_gc32 = 2;
+
+ panel_info.epdc_data.epdc_timings = panel_timings;
+
+ setup_epdc_power();
+
+ /* Assign fb_base */
+ gd->fb_base = CONFIG_FB_BASE;
+}
+#endif
+
/* For DDR mode operation, provide target delay parameter for each SD port.
* Use cfg->esdhc_base to distinguish the SD port #. The delay for each port
* is dependent on signal layout for that particular port. If the following
@@ -752,6 +1044,7 @@ u32 get_ddr_delay(struct fsl_esdhc_cfg *cfg)
#endif
+#ifndef CONFIG_MXC_EPDC
#ifdef CONFIG_LCD
void lcd_enable(void)
{
@@ -853,6 +1146,7 @@ void setup_splash_image(void)
}
}
#endif
+#endif /* !CONFIG_MXC_EPDC */
int board_init(void)
{
@@ -890,6 +1184,10 @@ int board_init(void)
#ifdef CONFIG_NAND_GPMI
setup_gpmi_nand();
#endif
+
+#ifdef CONFIG_MXC_EPDC
+ setup_epdc();
+#endif
return 0;
}