X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=board%2Fkaro%2Ftx51%2Ftx51.c;h=6bb463243ac89598475a3baba80e31f02ed45b6d;hp=bdf1d101caceb36196eadec9bbd25a7154d54025;hb=3d5920a31bb846249385e1ca5c086662c39bc44e;hpb=6dc9f272437cb39b18aaf2b5cd730cb3160777b4 diff --git a/board/karo/tx51/tx51.c b/board/karo/tx51/tx51.c index bdf1d101ca..6bb463243a 100644 --- a/board/karo/tx51/tx51.c +++ b/board/karo/tx51/tx51.c @@ -1,14 +1,13 @@ /* - * Copyright (C) 2011 Lothar Waßmann + * Copyright (C) 2011-2013 Lothar Waßmann * based on: board/freescale/mx28_evk.c (C) 2010 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -57,7 +56,7 @@ DECLARE_GLOBAL_DATA_PTR; #define FEC_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DVS | PAD_CTL_DSE_HIGH | \ PAD_CTL_SRE_FAST) #define FEC_PAD_CTRL2 MUX_PAD_CTRL(PAD_CTL_DVS | PAD_CTL_SRE_FAST) -#define GPIO_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DVS | PAD_CTL_DSE_HIGH) +#define GPIO_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DVS | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP) static iomux_v3_cfg_t tx51_pads[] = { /* NAND flash pads are set up in lowlevel_init.S */ @@ -121,29 +120,29 @@ static iomux_v3_cfg_t tx51_pads[] = { static const struct gpio tx51_gpios[] = { /* RESET_OUT */ - { TX51_RESET_OUT_GPIO, GPIOF_OUTPUT_INIT_LOW, "RESET_OUT", }, + { TX51_RESET_OUT_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "RESET_OUT", }, /* FEC PHY control GPIOs */ - { TX51_FEC_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "FEC POWER", }, /* PHY POWER */ - { TX51_FEC_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "FEC RESET", }, /* PHY RESET */ - { TX51_FEC_INT_GPIO, GPIOF_INPUT, "FEC PHY INT", }, /* PHY INT (TX_ER) */ + { TX51_FEC_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "FEC POWER", }, /* PHY POWER */ + { TX51_FEC_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "FEC RESET", }, /* PHY RESET */ + { TX51_FEC_INT_GPIO, GPIOFLAG_INPUT, "FEC PHY INT", }, /* PHY INT (TX_ER) */ /* FEC PHY strap pins */ - { IMX_GPIO_NR(3, 11), GPIOF_OUTPUT_INIT_LOW, "FEC PHY REGOFF", }, /* RX_CLK/REGOFF */ - { IMX_GPIO_NR(3, 31), GPIOF_OUTPUT_INIT_LOW, "FEC PHY MODE0", }, /* RXD0/Mode0 */ - { IMX_GPIO_NR(2, 23), GPIOF_OUTPUT_INIT_LOW, "FEC PHY MODE1", }, /* RXD1/Mode1 */ - { IMX_GPIO_NR(2, 27), GPIOF_OUTPUT_INIT_LOW, "FEC PHY MODE2", }, /* RXD2/Mode2 */ - { IMX_GPIO_NR(2, 28), GPIOF_OUTPUT_INIT_LOW, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */ - { IMX_GPIO_NR(3, 10), GPIOF_OUTPUT_INIT_LOW, "FEC PHY RMII", }, /* COL/RMII/CRSDV */ - { IMX_GPIO_NR(2, 30), GPIOF_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */ + { IMX_GPIO_NR(3, 11), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY REGOFF", }, /* RX_CLK/REGOFF */ + { IMX_GPIO_NR(3, 31), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY MODE0", }, /* RXD0/Mode0 */ + { IMX_GPIO_NR(2, 23), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY MODE1", }, /* RXD1/Mode1 */ + { IMX_GPIO_NR(2, 27), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY MODE2", }, /* RXD2/Mode2 */ + { IMX_GPIO_NR(2, 28), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */ + { IMX_GPIO_NR(3, 10), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY RMII", }, /* COL/RMII/CRSDV */ + { IMX_GPIO_NR(2, 30), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */ /* module internal I2C bus */ - { IMX_GPIO_NR(4, 17), GPIOF_INPUT, "I2C1 SDA", }, - { IMX_GPIO_NR(4, 16), GPIOF_INPUT, "I2C1 SCL", }, + { IMX_GPIO_NR(4, 17), GPIOFLAG_INPUT, "I2C1 SDA", }, + { IMX_GPIO_NR(4, 16), GPIOFLAG_INPUT, "I2C1 SCL", }, /* Unconnected pins */ - { IMX_GPIO_NR(1, 0), GPIOF_OUTPUT_INIT_LOW, "N/C", }, - { IMX_GPIO_NR(1, 1), GPIOF_OUTPUT_INIT_LOW, "N/C", }, + { IMX_GPIO_NR(1, 0), GPIOFLAG_OUTPUT_INIT_LOW, "N/C", }, + { IMX_GPIO_NR(1, 1), GPIOFLAG_OUTPUT_INIT_LOW, "N/C", }, }; /* @@ -226,14 +225,8 @@ static void tx51_print_cpuinfo(void) int board_early_init_f(void) { - struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)MXC_CCM_BASE; + struct mxc_ccm_reg *ccm_regs = (void *)CCM_BASE_ADDR; -#ifdef CONFIG_CMD_BOOTCE - /* WinCE fails to enable these clocks */ - writel(readl(&ccm_regs->CCGR2) | 0x0c000000, &ccm_regs->CCGR2); /* usboh3_ipg_ahb */ - writel(readl(&ccm_regs->CCGR4) | 0x30000000, &ccm_regs->CCGR4); /* srtc */ - writel(readl(&ccm_regs->CCGR6) | 0x00000300, &ccm_regs->CCGR6); /* emi_garb */ -#endif gpio_request_array(tx51_gpios, ARRAY_SIZE(tx51_gpios)); imx_iomux_v3_setup_multiple_pads(tx51_pads, ARRAY_SIZE(tx51_pads)); @@ -255,6 +248,20 @@ int board_early_init_f(void) writel(0x00000000, AIPS2_BASE_ADDR + 0x4c); writel(0x00000000, AIPS2_BASE_ADDR + 0x50); + writel(0xffcfffff, &ccm_regs->CCGR0); + writel(0x003fffff, &ccm_regs->CCGR1); + writel(0x030c003c, &ccm_regs->CCGR2); + writel(0x000000ff, &ccm_regs->CCGR3); + writel(0x00000000, &ccm_regs->CCGR4); + writel(0x003fc003, &ccm_regs->CCGR5); + writel(0x00000000, &ccm_regs->CCGR6); + writel(0x00000000, &ccm_regs->cmeor); +#ifdef CONFIG_CMD_BOOTCE + /* WinCE fails to enable these clocks */ + writel(readl(&ccm_regs->CCGR2) | 0x0c000000, &ccm_regs->CCGR2); /* usboh3_ipg_ahb */ + writel(readl(&ccm_regs->CCGR4) | 0x30000000, &ccm_regs->CCGR4); /* srtc */ + writel(readl(&ccm_regs->CCGR6) | 0x00000300, &ccm_regs->CCGR6); /* emi_garb */ +#endif return 0; } @@ -262,6 +269,14 @@ int board_init(void) { /* Address of boot parameters */ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x1000; + + if (ctrlc() || (wrsr & WRSR_TOUT)) { + if (wrsr & WRSR_TOUT) + printf("WDOG RESET detected\n"); + else + printf(" detected; safeboot enabled\n"); + return 1; + } return 0; } @@ -307,7 +322,7 @@ static const iomux_v3_cfg_t mmc0_pads[] = { MX51_PAD_SD1_DATA2__SD1_DATA2, MX51_PAD_SD1_DATA3__SD1_DATA3, /* SD1 CD */ - MX51_PAD_DISPB2_SER_RS__GPIO3_8 | MUX_PAD_CTRL(PAD_CTL_PUE | PAD_CTL_PKE), + MX51_PAD_DISPB2_SER_RS__GPIO3_8 | GPIO_PAD_CTRL, }; static const iomux_v3_cfg_t mmc1_pads[] = { @@ -318,7 +333,7 @@ static const iomux_v3_cfg_t mmc1_pads[] = { MX51_PAD_SD2_DATA2__SD2_DATA2, MX51_PAD_SD2_DATA3__SD2_DATA3, /* SD2 CD */ - MX51_PAD_DISPB2_SER_DIO__GPIO3_6 | MUX_PAD_CTRL(PAD_CTL_PUE | PAD_CTL_PKE), + MX51_PAD_DISPB2_SER_DIO__GPIO3_6 | GPIO_PAD_CTRL, }; static struct tx51_esdhc_cfg { @@ -332,6 +347,7 @@ static struct tx51_esdhc_cfg { .num_pads = ARRAY_SIZE(mmc0_pads), .cfg = { .esdhc_base = (void __iomem *)MMC_SDHC1_BASE_ADDR, + .max_bus_width = 4, }, .cd_gpio = IMX_GPIO_NR(3, 8), }, @@ -340,12 +356,13 @@ static struct tx51_esdhc_cfg { .num_pads = ARRAY_SIZE(mmc1_pads), .cfg = { .esdhc_base = (void __iomem *)MMC_SDHC2_BASE_ADDR, + .max_bus_width = 4, }, .cd_gpio = IMX_GPIO_NR(3, 6), }, }; -static struct tx51_esdhc_cfg *to_tx51_esdhc_cfg(struct fsl_esdhc_cfg *cfg) +static inline struct tx51_esdhc_cfg *to_tx51_esdhc_cfg(struct fsl_esdhc_cfg *cfg) { return container_of(cfg, struct tx51_esdhc_cfg, cfg); } @@ -372,23 +389,21 @@ int board_mmc_init(bd_t *bis) struct tx51_esdhc_cfg *cfg = &tx51_esdhc_cfg[i]; int ret; - if (i >= CONFIG_SYS_FSL_ESDHC_NUM) - break; - imx_iomux_v3_setup_multiple_pads(cfg->pads, cfg->num_pads); cfg->cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); - fsl_esdhc_initialize(bis, &cfg->cfg); - ret = gpio_request_one(cfg->cd_gpio, - GPIOF_INPUT, "MMC CD"); + GPIOFLAG_INPUT, "MMC CD"); if (ret) { printf("Error %d requesting GPIO%d_%d\n", ret, cfg->cd_gpio / 32, cfg->cd_gpio % 32); continue; } + debug("%s: Initializing MMC slot %d\n", __func__, i); + fsl_esdhc_initialize(bis, &cfg->cfg); + mmc = find_mmc_device(i); if (mmc == NULL) continue; @@ -436,22 +451,21 @@ static iomux_v3_cfg_t tx51_fec_pads[] = { #define PHYAD4 ((CONFIG_FEC_MXC_PHYADDR >> 4) & !(CONFIG_FEC_MXC_PHYADDR >> 5)) static struct gpio tx51_fec_gpios[] = { - { TX51_FEC_PWR_GPIO, GPIOF_OUTPUT_INIT_HIGH, "FEC PHY POWER", }, - { IMX_GPIO_NR(3, 31), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY Mode0", }, /* RXD0/Mode0 */ - { IMX_GPIO_NR(2, 23), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY Mode1", }, /* RXD1/Mode1 */ - { IMX_GPIO_NR(2, 27), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY Mode2", }, /* RXD2/Mode2 */ - { IMX_GPIO_NR(2, 28), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */ + { TX51_FEC_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY POWER", }, + { IMX_GPIO_NR(3, 31), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY Mode0", }, /* RXD0/Mode0 */ + { IMX_GPIO_NR(2, 23), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY Mode1", }, /* RXD1/Mode1 */ + { IMX_GPIO_NR(2, 27), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY Mode2", }, /* RXD2/Mode2 */ + { IMX_GPIO_NR(2, 28), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */ #if PHYAD4 - { IMX_GPIO_NR(2, 30), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */ + { IMX_GPIO_NR(2, 30), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */ #else - { IMX_GPIO_NR(2, 30), GPIOF_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */ + { IMX_GPIO_NR(2, 30), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */ #endif }; int board_eth_init(bd_t *bis) { int ret; - unsigned char mac[ETH_ALEN]; /* Power up the external phy and assert strap options */ gpio_request_array(tx51_fec_gpios, ARRAY_SIZE(tx51_fec_gpios)); @@ -462,22 +476,18 @@ int board_eth_init(bd_t *bis) /* Deassert RESET to the external phy */ gpio_set_value(TX51_FEC_RST_GPIO, 1); - /* Without this delay the PHY won't work, though nothing in - * the datasheets suggests that it should be necessary! + /* + * Due to an RC-filter in the PHY RESET line, a minimum + * delay of 535us is required to let the RESET line rise + * above the logic high threshold of the PHY input pin. */ - udelay(400); + udelay(550); imx_iomux_v3_setup_multiple_pads(tx51_fec_pads, ARRAY_SIZE(tx51_fec_pads)); ret = cpu_eth_init(bis); - if (ret) { + if (ret) printf("cpu_eth_init() failed: %d\n", ret); - return ret; - } - - imx_get_mac_from_fuse(0, mac); - eth_setenv_enetaddr("ethaddr", mac); - printf("MAC addr from fuse: %pM\n", mac); return ret; } @@ -513,38 +523,38 @@ void show_activity(int arg) static const iomux_v3_cfg_t stk5_pads[] = { /* SW controlled LED on STK5 baseboard */ - MX51_PAD_CSI2_D13__GPIO4_10, + MX51_PAD_CSI2_D13__GPIO4_10 | GPIO_PAD_CTRL, /* USB PHY reset */ - MX51_PAD_GPIO1_4__GPIO1_4, + MX51_PAD_GPIO1_4__GPIO1_4 | GPIO_PAD_CTRL, /* USBOTG OC */ - MX51_PAD_GPIO1_6__GPIO1_6, + MX51_PAD_GPIO1_6__GPIO1_6 | GPIO_PAD_CTRL, /* USB PHY clock enable */ - MX51_PAD_GPIO1_7__GPIO1_7, + MX51_PAD_GPIO1_7__GPIO1_7 | GPIO_PAD_CTRL, /* USBH1 VBUS enable */ - MX51_PAD_GPIO1_8__GPIO1_8, + MX51_PAD_GPIO1_8__GPIO1_8 | GPIO_PAD_CTRL, /* USBH1 OC */ - MX51_PAD_GPIO1_9__GPIO1_9, + MX51_PAD_GPIO1_9__GPIO1_9 | GPIO_PAD_CTRL, }; static const struct gpio stk5_gpios[] = { - { TX51_LED_GPIO, GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", }, + { TX51_LED_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "HEARTBEAT LED", }, - { IMX_GPIO_NR(1, 4), GPIOF_OUTPUT_INIT_LOW, "ULPI PHY clk enable", }, - { IMX_GPIO_NR(1, 6), GPIOF_INPUT, "USBOTG OC", }, - { IMX_GPIO_NR(1, 7), GPIOF_OUTPUT_INIT_LOW, "ULPI PHY reset", }, - { IMX_GPIO_NR(1, 8), GPIOF_OUTPUT_INIT_LOW, "USBH1 VBUS enable", }, - { IMX_GPIO_NR(1, 9), GPIOF_INPUT, "USBH1 OC", }, + { IMX_GPIO_NR(1, 4), GPIOFLAG_OUTPUT_INIT_LOW, "ULPI PHY clk enable", }, + { IMX_GPIO_NR(1, 6), GPIOFLAG_INPUT, "USBOTG OC", }, + { IMX_GPIO_NR(1, 7), GPIOFLAG_OUTPUT_INIT_LOW, "ULPI PHY reset", }, + { IMX_GPIO_NR(1, 8), GPIOFLAG_OUTPUT_INIT_LOW, "USBH1 VBUS enable", }, + { IMX_GPIO_NR(1, 9), GPIOFLAG_INPUT, "USBH1 OC", }, }; #ifdef CONFIG_LCD -static ushort tx51_cmap[256]; +static u16 tx51_cmap[256]; vidinfo_t panel_info = { /* set to max. size supported by SoC */ .vl_col = 1600, .vl_row = 1200, - .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */ + .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */ .cmap = tx51_cmap, }; @@ -681,6 +691,12 @@ static struct fb_videomode tx51_fb_modes[] = { }; static int lcd_enabled = 1; +static int lcd_bl_polarity; + +static int lcd_backlight_polarity(void) +{ + return lcd_bl_polarity; +} void lcd_enable(void) { @@ -691,27 +707,33 @@ void lcd_enable(void) */ lcd_is_enabled = 0; - karo_load_splashimage(1); if (lcd_enabled) { + karo_load_splashimage(1); + debug("Switching LCD on\n"); gpio_set_value(TX51_LCD_PWR_GPIO, 1); udelay(100); gpio_set_value(TX51_LCD_RST_GPIO, 1); udelay(300000); - gpio_set_value(TX51_LCD_BACKLIGHT_GPIO, 0); + gpio_set_value(TX51_LCD_BACKLIGHT_GPIO, + lcd_backlight_polarity()); } } void lcd_disable(void) { - printf("Disabling LCD\n"); + if (lcd_enabled) { + printf("Disabling LCD\n"); + ipuv3_fb_shutdown(); + } } void lcd_panel_disable(void) { if (lcd_enabled) { debug("Switching LCD off\n"); - gpio_set_value(TX51_LCD_BACKLIGHT_GPIO, 1); + gpio_set_value(TX51_LCD_BACKLIGHT_GPIO, + !lcd_backlight_polarity()); gpio_set_value(TX51_LCD_RST_GPIO, 0); gpio_set_value(TX51_LCD_PWR_GPIO, 0); } @@ -755,21 +777,23 @@ static const iomux_v3_cfg_t stk5_lcd_pads[] = { }; static const struct gpio stk5_lcd_gpios[] = { - { TX51_LCD_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD RESET", }, - { TX51_LCD_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD POWER", }, - { TX51_LCD_BACKLIGHT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", }, + { TX51_LCD_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", }, + { TX51_LCD_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", }, + { TX51_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", }, }; void lcd_ctrl_init(void *lcdbase) { int color_depth = 24; - char *vm; + const char *video_mode = karo_get_vmode(getenv("video_mode")); + const char *vm; unsigned long val; int refresh = 60; struct fb_videomode *p = &tx51_fb_modes[0]; struct fb_videomode fb_mode; int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0; - int pix_fmt = 0; + int pix_fmt; + int lcd_bus_width; ipu_di_clk_parent_t di_clk_parent = DI_PCLK_PLL3; unsigned long di_clk_rate = 65000000; @@ -778,28 +802,34 @@ void lcd_ctrl_init(void *lcdbase) return; } - if (tstc() || (wrsr & WRSR_TOUT)) { + if (had_ctrlc() || (wrsr & WRSR_TOUT)) { debug("Disabling LCD\n"); lcd_enabled = 0; + setenv("splashimage", NULL); return; } karo_fdt_move_fdt(); + lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt); - vm = getenv("video_mode"); - if (vm == NULL) { + if (video_mode == NULL) { debug("Disabling LCD\n"); lcd_enabled = 0; return; } - if (karo_fdt_get_fb_mode(working_fdt, vm, &fb_mode) == 0) { + vm = video_mode; + if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) { p = &fb_mode; debug("Using video mode from FDT\n"); vm += strlen(vm); - if (fb_mode.xres < panel_info.vl_col) - panel_info.vl_col = fb_mode.xres; - if (fb_mode.yres < panel_info.vl_row) - panel_info.vl_row = fb_mode.yres; + if (fb_mode.xres > panel_info.vl_col || + fb_mode.yres > panel_info.vl_row) { + printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n", + fb_mode.xres, fb_mode.yres, + panel_info.vl_col, panel_info.vl_row); + lcd_enabled = 0; + return; + } } if (p->name != NULL) debug("Trying compiled-in video modes\n"); @@ -836,6 +866,7 @@ void lcd_ctrl_init(void *lcdbase) case 8: case 16: case 24: + case 32: color_depth = val; break; @@ -867,14 +898,6 @@ void lcd_ctrl_init(void *lcdbase) break; default: - if (!pix_fmt) { - char *tmp; - - pix_fmt = IPU_PIX_FMT_RGB24; - tmp = strchr(vm, ':'); - if (tmp) - vm = tmp; - } if (*vm != '\0') vm++; } @@ -889,34 +912,85 @@ void lcd_ctrl_init(void *lcdbase) printf("\n"); return; } + if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) { + printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n", + p->xres, p->yres, panel_info.vl_col, panel_info.vl_row); + lcd_enabled = 0; + return; + } + panel_info.vl_col = p->xres; + panel_info.vl_row = p->yres; + + switch (color_depth) { + case 8: + panel_info.vl_bpix = LCD_COLOR8; + break; + case 16: + panel_info.vl_bpix = LCD_COLOR16; + break; + default: + panel_info.vl_bpix = LCD_COLOR32; + } p->pixclock = KHZ2PICOS(refresh * (p->xres + p->left_margin + p->right_margin + p->hsync_len) * - (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) - / 1000); + (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) / + 1000); debug("Pixel clock set to %lu.%03lu MHz\n", PICOS2KHZ(p->pixclock) / 1000, PICOS2KHZ(p->pixclock) % 1000); + if (p != &fb_mode) { + int ret; + + debug("Creating new display-timing node from '%s'\n", + video_mode); + ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p); + if (ret) + printf("Failed to create new display-timing node from '%s': %d\n", + video_mode, ret); + } + gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios)); imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads, ARRAY_SIZE(stk5_lcd_pads)); - debug("Initializing FB driver\n"); - if (!pix_fmt) + lcd_bus_width = karo_fdt_get_lcd_bus_width(working_fdt, 24); + switch (lcd_bus_width) { + case 24: pix_fmt = IPU_PIX_FMT_RGB24; + break; + + case 18: + pix_fmt = IPU_PIX_FMT_RGB666; + break; + + case 16: + pix_fmt = IPU_PIX_FMT_RGB565; + break; + default: + lcd_enabled = 0; + printf("Invalid LCD bus width: %d\n", lcd_bus_width); + return; + } if (karo_load_splashimage(0) == 0) { + int ret; struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)MXC_CCM_BASE; u32 ccgr4 = readl(&ccm_regs->CCGR4); /* MIPI HSC clock is required for initialization */ writel(ccgr4 | (3 << 12), &ccm_regs->CCGR4); - debug("Initializing LCD controller\n"); - ipuv3_fb_init(p, 0, pix_fmt, di_clk_parent, di_clk_rate, -1); + gd->arch.ipu_hw_rev = IPUV3_HW_REV_IPUV3DEX; + debug("Initializing LCD controller\n"); + ret = ipuv3_fb_init(p, 0, pix_fmt, di_clk_parent, di_clk_rate, -1); writel(ccgr4 & ~(3 << 12), &ccm_regs->CCGR4); + if (ret) { + printf("Failed to initialize FB driver: %d\n", ret); + lcd_enabled = 0; + } } else { debug("Skipping initialization of LCD controller\n"); } @@ -939,22 +1013,34 @@ static void stk5v3_board_init(void) static void tx51_set_cpu_clock(void) { unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0); - int ret; - if (tstc() || (wrsr & WRSR_TOUT)) + if (had_ctrlc() || (wrsr & WRSR_TOUT)) return; if (cpu_clk == 0 || cpu_clk == mxc_get_clock(MXC_ARM_CLK) / 1000000) return; - ret = mxc_set_clock(CONFIG_SYS_MX5_HCLK, cpu_clk, MXC_ARM_CLK); - if (ret != 0) { + if (mxc_set_clock(CONFIG_SYS_MX5_HCLK, cpu_clk, MXC_ARM_CLK) == 0) { + cpu_clk = mxc_get_clock(MXC_ARM_CLK); + printf("CPU clock set to %lu.%03lu MHz\n", + cpu_clk / 1000000, cpu_clk / 1000 % 1000); + } else { printf("Error: Failed to set CPU clock to %lu MHz\n", cpu_clk); + } +} + +static void tx51_init_mac(void) +{ + u8 mac[ETH_ALEN]; + + imx_get_mac_from_fuse(0, mac); + if (!is_valid_ether_addr(mac)) { + printf("No valid MAC address programmed\n"); return; } - printf("CPU clock set to %u.%03u MHz\n", - mxc_get_clock(MXC_ARM_CLK) / 1000000, - mxc_get_clock(MXC_ARM_CLK) / 1000 % 1000); + + printf("MAC addr from fuse: %pM\n", mac); + eth_setenv_enetaddr("ethaddr", mac); } int board_late_init(void) @@ -962,15 +1048,24 @@ int board_late_init(void) int ret = 0; const char *baseboard; + env_cleanup(); + tx51_set_cpu_clock(); - karo_fdt_move_fdt(); + + if (had_ctrlc()) + setenv_ulong("safeboot", 1); + else if (wrsr & WRSR_TOUT) + setenv_ulong("wdreset", 1); + else + karo_fdt_move_fdt(); baseboard = getenv("baseboard"); if (!baseboard) goto exit; + printf("Baseboard: %s\n", baseboard); + if (strncmp(baseboard, "stk5", 4) == 0) { - printf("Baseboard: %s\n", baseboard); if ((strlen(baseboard) == 4) || strcmp(baseboard, "stk5-v3") == 0) { stk5v3_board_init(); @@ -989,17 +1084,21 @@ int board_late_init(void) } exit: + tx51_init_mac(); + gpio_set_value(TX51_RESET_OUT_GPIO, 1); + clear_ctrlc(); return ret; } int checkboard(void) { tx51_print_cpuinfo(); - - printf("Board: Ka-Ro TX51-%sxx%s\n", - TX51_MOD_PREFIX, TX51_MOD_SUFFIX); - +#if CONFIG_NR_DRAM_BANKS > 1 + printf("Board: Ka-Ro TX51-8xx1 | TX51-8xx2\n"); +#else + printf("Board: Ka-Ro TX51-8xx0\n"); +#endif return 0; } @@ -1007,20 +1106,36 @@ int checkboard(void) #ifdef CONFIG_FDT_FIXUP_PARTITIONS #include #include -struct node_info nodes[] = { +static struct node_info nodes[] = { { "fsl,imx51-nand", MTD_DEV_TYPE_NAND, }, }; - #else #define fdt_fixup_mtdparts(b,n,c) do { } while (0) #endif -void ft_board_setup(void *blob, bd_t *bd) +static const char *tx51_touchpanels[] = { + "ti,tsc2007", + "edt,edt-ft5x06", +}; + +int ft_board_setup(void *blob, bd_t *bd) { + const char *video_mode = karo_get_vmode(getenv("video_mode")); + int ret; + + ret = fdt_increase_size(blob, 4096); + if (ret) { + printf("Failed to increase FDT size: %s\n", fdt_strerror(ret)); + return ret; + } fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); fdt_fixup_ethernet(blob); - karo_fdt_fixup_touchpanel(blob); - karo_fdt_fixup_usb_otg(blob, "fsl,imx-otg", "fsl,usbphy"); + karo_fdt_fixup_touchpanel(blob, tx51_touchpanels, + ARRAY_SIZE(tx51_touchpanels)); + karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply"); + karo_fdt_update_fb_mode(blob, video_mode); + + return 0; } -#endif +#endif /* CONFIG_OF_BOARD_SETUP */