X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=board%2Fkaro%2Ftx51%2Ftx51.c;h=3f5b496b3c3e3a29fdd4d71ecd1d61165349c953;hb=63652ce377ee8ce60a6217aefe238313d0989c60;hp=30296710fb3fbc1fc29370f43fc3e75c48c0f178;hpb=431ef5ba905a3cdb726073ae9522fcd782de5592;p=karo-tx-uboot.git diff --git a/board/karo/tx51/tx51.c b/board/karo/tx51/tx51.c index 30296710fb..3f5b496b3c 100644 --- a/board/karo/tx51/tx51.c +++ b/board/karo/tx51/tx51.c @@ -120,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", }, }; /* @@ -248,7 +248,7 @@ int board_early_init_f(void) writel(0x00000000, AIPS2_BASE_ADDR + 0x4c); writel(0x00000000, AIPS2_BASE_ADDR + 0x50); - writel(0xffcffffc, &ccm_regs->CCGR0); + writel(0xffcfffff, &ccm_regs->CCGR0); writel(0x003fffff, &ccm_regs->CCGR1); writel(0x030c003c, &ccm_regs->CCGR2); writel(0x000000ff, &ccm_regs->CCGR3); @@ -269,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; } @@ -354,7 +362,10 @@ static struct tx51_esdhc_cfg { }, }; -#define to_tx51_esdhc_cfg(p) container_of(p, struct tx51_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); +} int board_mmc_getcd(struct mmc *mmc) { @@ -378,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; @@ -442,15 +451,15 @@ 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 }; @@ -467,16 +476,19 @@ 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) printf("cpu_eth_init() failed: %d\n", ret); + return ret; } #endif /* CONFIG_FEC_MXC */ @@ -526,13 +538,13 @@ static const iomux_v3_cfg_t stk5_pads[] = { }; 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 @@ -541,7 +553,7 @@ vidinfo_t panel_info = { .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 ... */ }; static struct fb_videomode tx51_fb_modes[] = { @@ -677,6 +689,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) { @@ -695,7 +713,8 @@ void lcd_enable(void) 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()); } } @@ -711,7 +730,8 @@ 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 +775,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,7 +800,7 @@ 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); @@ -786,14 +808,15 @@ void lcd_ctrl_init(void *lcdbase) } 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); @@ -873,14 +896,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++; } @@ -912,37 +927,51 @@ void lcd_ctrl_init(void *lcdbase) panel_info.vl_bpix = LCD_COLOR16; break; default: - panel_info.vl_bpix = LCD_COLOR24; + 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; - char *modename = getenv("video_mode"); - printf("Creating new display-timing node from '%s'\n", - modename); - ret = karo_fdt_create_fb_mode(working_fdt, modename, p); + 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", - modename, ret); + 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; @@ -982,22 +1011,20 @@ 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); - 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); } static void tx51_init_mac(void) @@ -1005,13 +1032,13 @@ static void tx51_init_mac(void) u8 mac[ETH_ALEN]; imx_get_mac_from_fuse(0, mac); - if (!is_valid_ether_addr(mac)) { + if (!is_valid_ethaddr(mac)) { printf("No valid MAC address programmed\n"); return; } - eth_setenv_enetaddr("ethaddr", mac); printf("MAC addr from fuse: %pM\n", mac); + eth_setenv_enetaddr("ethaddr", mac); } int board_late_init(void) @@ -1019,15 +1046,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(); @@ -1047,7 +1083,9 @@ int board_late_init(void) exit: tx51_init_mac(); + gpio_set_value(TX51_RESET_OUT_GPIO, 1); + clear_ctrlc(); return ret; } @@ -1066,21 +1104,35 @@ 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_update_fb_mode(blob, getenv("video_mode")); + 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, "/lcd-panel"); + + return 0; } -#endif +#endif /* CONFIG_OF_BOARD_SETUP */