1e32028a7SNikita Kiryanov /* 2e32028a7SNikita Kiryanov * Board functions for Compulab CM-FX6 board 3e32028a7SNikita Kiryanov * 4e32028a7SNikita Kiryanov * Copyright (C) 2014, Compulab Ltd - http://compulab.co.il/ 5e32028a7SNikita Kiryanov * 6e32028a7SNikita Kiryanov * Author: Nikita Kiryanov <nikita@compulab.co.il> 7e32028a7SNikita Kiryanov * 8e32028a7SNikita Kiryanov * SPDX-License-Identifier: GPL-2.0+ 9e32028a7SNikita Kiryanov */ 10e32028a7SNikita Kiryanov 11e32028a7SNikita Kiryanov #include <common.h> 123f0e935fSSimon Glass #include <dm.h> 13e32028a7SNikita Kiryanov #include <fsl_esdhc.h> 1402b1343eSNikita Kiryanov #include <miiphy.h> 1562d6bac6SChristopher Spinrath #include <mtd_node.h> 1602b1343eSNikita Kiryanov #include <netdev.h> 174377859aSNikita Kiryanov #include <errno.h> 18d6276ab1SNikita Kiryanov #include <usb.h> 1902b1343eSNikita Kiryanov #include <fdt_support.h> 20206f38f7SNikita Kiryanov #include <sata.h> 21f82eb2faSNikita Kiryanov #include <splash.h> 22a6b0652bSNikita Kiryanov #include <asm/arch/crm_regs.h> 23e32028a7SNikita Kiryanov #include <asm/arch/sys_proto.h> 240f3effb9SNikita Kiryanov #include <asm/arch/iomux.h> 25deb94d61SNikita Kiryanov #include <asm/arch/mxc_hdmi.h> 26552a848eSStefano Babic #include <asm/mach-imx/mxc_i2c.h> 27552a848eSStefano Babic #include <asm/mach-imx/sata.h> 28552a848eSStefano Babic #include <asm/mach-imx/video.h> 29a6b0652bSNikita Kiryanov #include <asm/io.h> 3002b1343eSNikita Kiryanov #include <asm/gpio.h> 3186256b79SMasahiro Yamada #include <dm/platform_data/serial_mxc.h> 3262d6bac6SChristopher Spinrath #include <jffs2/load_kernel.h> 33e32028a7SNikita Kiryanov #include "common.h" 34f66113c0SNikita Kiryanov #include "../common/eeprom.h" 353a236a35SNikita Kiryanov #include "../common/common.h" 36e32028a7SNikita Kiryanov 37e32028a7SNikita Kiryanov DECLARE_GLOBAL_DATA_PTR; 38e32028a7SNikita Kiryanov 393a236a35SNikita Kiryanov #ifdef CONFIG_SPLASH_SCREEN 403a236a35SNikita Kiryanov static struct splash_location cm_fx6_splash_locations[] = { 413a236a35SNikita Kiryanov { 423a236a35SNikita Kiryanov .name = "sf", 433a236a35SNikita Kiryanov .storage = SPLASH_STORAGE_SF, 44870dd309SNikita Kiryanov .flags = SPLASH_STORAGE_RAW, 453a236a35SNikita Kiryanov .offset = 0x100000, 463a236a35SNikita Kiryanov }, 47ec26c1eeSNikita Kiryanov { 48ec26c1eeSNikita Kiryanov .name = "mmc_fs", 49ec26c1eeSNikita Kiryanov .storage = SPLASH_STORAGE_MMC, 50ec26c1eeSNikita Kiryanov .flags = SPLASH_STORAGE_FS, 51ec26c1eeSNikita Kiryanov .devpart = "2:1", 52ec26c1eeSNikita Kiryanov }, 53ec26c1eeSNikita Kiryanov { 54ec26c1eeSNikita Kiryanov .name = "usb_fs", 55ec26c1eeSNikita Kiryanov .storage = SPLASH_STORAGE_USB, 56ec26c1eeSNikita Kiryanov .flags = SPLASH_STORAGE_FS, 57ec26c1eeSNikita Kiryanov .devpart = "0:1", 58ec26c1eeSNikita Kiryanov }, 59ec26c1eeSNikita Kiryanov { 60ec26c1eeSNikita Kiryanov .name = "sata_fs", 61ec26c1eeSNikita Kiryanov .storage = SPLASH_STORAGE_SATA, 62ec26c1eeSNikita Kiryanov .flags = SPLASH_STORAGE_FS, 63ec26c1eeSNikita Kiryanov .devpart = "0:1", 64ec26c1eeSNikita Kiryanov }, 653a236a35SNikita Kiryanov }; 663a236a35SNikita Kiryanov 673a236a35SNikita Kiryanov int splash_screen_prepare(void) 683a236a35SNikita Kiryanov { 69f82eb2faSNikita Kiryanov return splash_source_load(cm_fx6_splash_locations, 703a236a35SNikita Kiryanov ARRAY_SIZE(cm_fx6_splash_locations)); 713a236a35SNikita Kiryanov } 723a236a35SNikita Kiryanov #endif 733a236a35SNikita Kiryanov 74deb94d61SNikita Kiryanov #ifdef CONFIG_IMX_HDMI 75deb94d61SNikita Kiryanov static void cm_fx6_enable_hdmi(struct display_info_t const *dev) 76deb94d61SNikita Kiryanov { 77b406f903SNikita Kiryanov struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 78b406f903SNikita Kiryanov imx_setup_hdmi(); 79b406f903SNikita Kiryanov setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK); 80deb94d61SNikita Kiryanov imx_enable_hdmi_phy(); 81deb94d61SNikita Kiryanov } 82deb94d61SNikita Kiryanov 834377859aSNikita Kiryanov static struct display_info_t preset_hdmi_1024X768 = { 84deb94d61SNikita Kiryanov .bus = -1, 85deb94d61SNikita Kiryanov .addr = 0, 86deb94d61SNikita Kiryanov .pixfmt = IPU_PIX_FMT_RGB24, 87deb94d61SNikita Kiryanov .enable = cm_fx6_enable_hdmi, 88deb94d61SNikita Kiryanov .mode = { 89deb94d61SNikita Kiryanov .name = "HDMI", 90deb94d61SNikita Kiryanov .refresh = 60, 91deb94d61SNikita Kiryanov .xres = 1024, 92deb94d61SNikita Kiryanov .yres = 768, 93deb94d61SNikita Kiryanov .pixclock = 40385, 94deb94d61SNikita Kiryanov .left_margin = 220, 95deb94d61SNikita Kiryanov .right_margin = 40, 96deb94d61SNikita Kiryanov .upper_margin = 21, 97deb94d61SNikita Kiryanov .lower_margin = 7, 98deb94d61SNikita Kiryanov .hsync_len = 60, 99deb94d61SNikita Kiryanov .vsync_len = 10, 100deb94d61SNikita Kiryanov .sync = FB_SYNC_EXT, 101deb94d61SNikita Kiryanov .vmode = FB_VMODE_NONINTERLACED, 102deb94d61SNikita Kiryanov } 103deb94d61SNikita Kiryanov }; 104deb94d61SNikita Kiryanov 105deb94d61SNikita Kiryanov static void cm_fx6_setup_display(void) 106deb94d61SNikita Kiryanov { 10775dbbbfdSNikita Kiryanov struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; 108deb94d61SNikita Kiryanov 109deb94d61SNikita Kiryanov enable_ipu_clock(); 11075dbbbfdSNikita Kiryanov clrbits_le32(&iomuxc_regs->gpr[3], MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK); 111deb94d61SNikita Kiryanov } 1124377859aSNikita Kiryanov 1134377859aSNikita Kiryanov int board_video_skip(void) 1144377859aSNikita Kiryanov { 1154377859aSNikita Kiryanov int ret; 1164377859aSNikita Kiryanov struct display_info_t *preset; 11733299499SNikita Kiryanov char const *panel = getenv("displaytype"); 11833299499SNikita Kiryanov 11933299499SNikita Kiryanov if (!panel) /* Also accept panel for backward compatibility */ 12033299499SNikita Kiryanov panel = getenv("panel"); 1214377859aSNikita Kiryanov 1224377859aSNikita Kiryanov if (!panel) 1234377859aSNikita Kiryanov return -ENOENT; 1244377859aSNikita Kiryanov 1254377859aSNikita Kiryanov if (!strcmp(panel, "HDMI")) 1264377859aSNikita Kiryanov preset = &preset_hdmi_1024X768; 1274377859aSNikita Kiryanov else 1284377859aSNikita Kiryanov return -EINVAL; 1294377859aSNikita Kiryanov 1304377859aSNikita Kiryanov ret = ipuv3_fb_init(&preset->mode, 0, preset->pixfmt); 1314377859aSNikita Kiryanov if (ret) { 1324377859aSNikita Kiryanov printf("Can't init display %s: %d\n", preset->mode.name, ret); 1334377859aSNikita Kiryanov return ret; 1344377859aSNikita Kiryanov } 1354377859aSNikita Kiryanov 1364377859aSNikita Kiryanov preset->enable(preset); 1374377859aSNikita Kiryanov printf("Display: %s (%ux%u)\n", preset->mode.name, preset->mode.xres, 1384377859aSNikita Kiryanov preset->mode.yres); 1394377859aSNikita Kiryanov 1404377859aSNikita Kiryanov return 0; 1414377859aSNikita Kiryanov } 142deb94d61SNikita Kiryanov #else 143deb94d61SNikita Kiryanov static inline void cm_fx6_setup_display(void) {} 144deb94d61SNikita Kiryanov #endif /* CONFIG_VIDEO_IPUV3 */ 145deb94d61SNikita Kiryanov 146206f38f7SNikita Kiryanov #ifdef CONFIG_DWC_AHSATA 147206f38f7SNikita Kiryanov static int cm_fx6_issd_gpios[] = { 148206f38f7SNikita Kiryanov /* The order of the GPIOs in the array is important! */ 149b65cbab1SNikita Kiryanov CM_FX6_SATA_LDO_EN, 150206f38f7SNikita Kiryanov CM_FX6_SATA_PHY_SLP, 151206f38f7SNikita Kiryanov CM_FX6_SATA_NRSTDLY, 152206f38f7SNikita Kiryanov CM_FX6_SATA_PWREN, 153206f38f7SNikita Kiryanov CM_FX6_SATA_NSTANDBY1, 154206f38f7SNikita Kiryanov CM_FX6_SATA_NSTANDBY2, 155206f38f7SNikita Kiryanov }; 156206f38f7SNikita Kiryanov 157206f38f7SNikita Kiryanov static void cm_fx6_sata_power(int on) 158206f38f7SNikita Kiryanov { 159206f38f7SNikita Kiryanov int i; 160206f38f7SNikita Kiryanov 161206f38f7SNikita Kiryanov if (!on) { /* tell the iSSD that the power will be removed */ 162206f38f7SNikita Kiryanov gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 1); 163206f38f7SNikita Kiryanov mdelay(10); 164206f38f7SNikita Kiryanov } 165206f38f7SNikita Kiryanov 166206f38f7SNikita Kiryanov for (i = 0; i < ARRAY_SIZE(cm_fx6_issd_gpios); i++) { 167206f38f7SNikita Kiryanov gpio_direction_output(cm_fx6_issd_gpios[i], on); 168206f38f7SNikita Kiryanov udelay(100); 169206f38f7SNikita Kiryanov } 170206f38f7SNikita Kiryanov 171206f38f7SNikita Kiryanov if (!on) /* for compatibility lower the power loss interrupt */ 172206f38f7SNikita Kiryanov gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0); 173206f38f7SNikita Kiryanov } 174206f38f7SNikita Kiryanov 175206f38f7SNikita Kiryanov static iomux_v3_cfg_t const sata_pads[] = { 176206f38f7SNikita Kiryanov /* SATA PWR */ 177206f38f7SNikita Kiryanov IOMUX_PADS(PAD_ENET_TX_EN__GPIO1_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)), 178206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_A22__GPIO2_IO16 | MUX_PAD_CTRL(NO_PAD_CTRL)), 179206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_D20__GPIO3_IO20 | MUX_PAD_CTRL(NO_PAD_CTRL)), 180206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_A25__GPIO5_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL)), 181206f38f7SNikita Kiryanov /* SATA CTRL */ 182206f38f7SNikita Kiryanov IOMUX_PADS(PAD_ENET_TXD0__GPIO1_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL)), 183206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_D23__GPIO3_IO23 | MUX_PAD_CTRL(NO_PAD_CTRL)), 184206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL)), 185206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_A23__GPIO6_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL)), 186206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_BCLK__GPIO6_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL)), 187206f38f7SNikita Kiryanov }; 188206f38f7SNikita Kiryanov 1898f488c1bSNikita Kiryanov static int cm_fx6_setup_issd(void) 190206f38f7SNikita Kiryanov { 1918f488c1bSNikita Kiryanov int ret, i; 192206f38f7SNikita Kiryanov 1938f488c1bSNikita Kiryanov SETUP_IOMUX_PADS(sata_pads); 1948f488c1bSNikita Kiryanov 1958f488c1bSNikita Kiryanov for (i = 0; i < ARRAY_SIZE(cm_fx6_issd_gpios); i++) { 1968f488c1bSNikita Kiryanov ret = gpio_request(cm_fx6_issd_gpios[i], "sata"); 1978f488c1bSNikita Kiryanov if (ret) 1988f488c1bSNikita Kiryanov return ret; 1998f488c1bSNikita Kiryanov } 2008f488c1bSNikita Kiryanov 2018f488c1bSNikita Kiryanov ret = gpio_request(CM_FX6_SATA_PWLOSS_INT, "sata_pwloss_int"); 2028f488c1bSNikita Kiryanov if (ret) 2038f488c1bSNikita Kiryanov return ret; 2048f488c1bSNikita Kiryanov 2058f488c1bSNikita Kiryanov return 0; 206206f38f7SNikita Kiryanov } 207206f38f7SNikita Kiryanov 208206f38f7SNikita Kiryanov #define CM_FX6_SATA_INIT_RETRIES 10 209206f38f7SNikita Kiryanov int sata_initialize(void) 210206f38f7SNikita Kiryanov { 211206f38f7SNikita Kiryanov int err, i; 212206f38f7SNikita Kiryanov 2138f488c1bSNikita Kiryanov /* Make sure this gpio has logical 0 value */ 2148f488c1bSNikita Kiryanov gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0); 2158f488c1bSNikita Kiryanov udelay(100); 2168f488c1bSNikita Kiryanov cm_fx6_sata_power(1); 2178f488c1bSNikita Kiryanov 218206f38f7SNikita Kiryanov for (i = 0; i < CM_FX6_SATA_INIT_RETRIES; i++) { 219206f38f7SNikita Kiryanov err = setup_sata(); 220206f38f7SNikita Kiryanov if (err) { 221206f38f7SNikita Kiryanov printf("SATA setup failed: %d\n", err); 222206f38f7SNikita Kiryanov return err; 223206f38f7SNikita Kiryanov } 224206f38f7SNikita Kiryanov 225206f38f7SNikita Kiryanov udelay(100); 226206f38f7SNikita Kiryanov 227206f38f7SNikita Kiryanov err = __sata_initialize(); 228206f38f7SNikita Kiryanov if (!err) 229206f38f7SNikita Kiryanov break; 230206f38f7SNikita Kiryanov 231206f38f7SNikita Kiryanov /* There is no device on the SATA port */ 232206f38f7SNikita Kiryanov if (sata_port_status(0, 0) == 0) 233206f38f7SNikita Kiryanov break; 234206f38f7SNikita Kiryanov 235206f38f7SNikita Kiryanov /* There's a device, but link not established. Retry */ 236206f38f7SNikita Kiryanov } 237206f38f7SNikita Kiryanov 238206f38f7SNikita Kiryanov return err; 239206f38f7SNikita Kiryanov } 2409cad3544SNikita Kiryanov 2419cad3544SNikita Kiryanov int sata_stop(void) 2429cad3544SNikita Kiryanov { 2439cad3544SNikita Kiryanov __sata_stop(); 2449cad3544SNikita Kiryanov cm_fx6_sata_power(0); 2459cad3544SNikita Kiryanov mdelay(250); 2469cad3544SNikita Kiryanov 2479cad3544SNikita Kiryanov return 0; 2489cad3544SNikita Kiryanov } 2498f488c1bSNikita Kiryanov #else 2508f488c1bSNikita Kiryanov static int cm_fx6_setup_issd(void) { return 0; } 251206f38f7SNikita Kiryanov #endif 252206f38f7SNikita Kiryanov 253f42b2f60SNikita Kiryanov #ifdef CONFIG_SYS_I2C_MXC 254f42b2f60SNikita Kiryanov #define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 255f42b2f60SNikita Kiryanov PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ 256f42b2f60SNikita Kiryanov PAD_CTL_ODE | PAD_CTL_SRE_FAST) 257f42b2f60SNikita Kiryanov 258f42b2f60SNikita Kiryanov I2C_PADS(i2c0_pads, 259f42b2f60SNikita Kiryanov PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), 260f42b2f60SNikita Kiryanov PAD_EIM_D21__GPIO3_IO21 | MUX_PAD_CTRL(I2C_PAD_CTRL), 261f42b2f60SNikita Kiryanov IMX_GPIO_NR(3, 21), 262f42b2f60SNikita Kiryanov PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), 263f42b2f60SNikita Kiryanov PAD_EIM_D28__GPIO3_IO28 | MUX_PAD_CTRL(I2C_PAD_CTRL), 264f42b2f60SNikita Kiryanov IMX_GPIO_NR(3, 28)); 265f42b2f60SNikita Kiryanov 266f42b2f60SNikita Kiryanov I2C_PADS(i2c1_pads, 267f42b2f60SNikita Kiryanov PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), 268f42b2f60SNikita Kiryanov PAD_KEY_COL3__GPIO4_IO12 | MUX_PAD_CTRL(I2C_PAD_CTRL), 269f42b2f60SNikita Kiryanov IMX_GPIO_NR(4, 12), 270f42b2f60SNikita Kiryanov PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), 271f42b2f60SNikita Kiryanov PAD_KEY_ROW3__GPIO4_IO13 | MUX_PAD_CTRL(I2C_PAD_CTRL), 272f42b2f60SNikita Kiryanov IMX_GPIO_NR(4, 13)); 273f42b2f60SNikita Kiryanov 274f42b2f60SNikita Kiryanov I2C_PADS(i2c2_pads, 275f42b2f60SNikita Kiryanov PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), 276f42b2f60SNikita Kiryanov PAD_GPIO_3__GPIO1_IO03 | MUX_PAD_CTRL(I2C_PAD_CTRL), 277f42b2f60SNikita Kiryanov IMX_GPIO_NR(1, 3), 278f42b2f60SNikita Kiryanov PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), 279f42b2f60SNikita Kiryanov PAD_GPIO_6__GPIO1_IO06 | MUX_PAD_CTRL(I2C_PAD_CTRL), 280f42b2f60SNikita Kiryanov IMX_GPIO_NR(1, 6)); 281f42b2f60SNikita Kiryanov 282f42b2f60SNikita Kiryanov 283edbf8b4fSSimon Glass static int cm_fx6_setup_one_i2c(int busnum, struct i2c_pads_info *pads) 284f42b2f60SNikita Kiryanov { 285edbf8b4fSSimon Glass int ret; 286edbf8b4fSSimon Glass 287edbf8b4fSSimon Glass ret = setup_i2c(busnum, CONFIG_SYS_I2C_SPEED, 0x7f, pads); 288edbf8b4fSSimon Glass if (ret) 289edbf8b4fSSimon Glass printf("Warning: I2C%d setup failed: %d\n", busnum, ret); 290edbf8b4fSSimon Glass 291edbf8b4fSSimon Glass return ret; 292edbf8b4fSSimon Glass } 293edbf8b4fSSimon Glass 294edbf8b4fSSimon Glass static int cm_fx6_setup_i2c(void) 295edbf8b4fSSimon Glass { 296edbf8b4fSSimon Glass int ret = 0, err; 297edbf8b4fSSimon Glass 298edbf8b4fSSimon Glass /* i2c<x>_pads are wierd macro variables; we can't use an array */ 299edbf8b4fSSimon Glass err = cm_fx6_setup_one_i2c(0, I2C_PADS_INFO(i2c0_pads)); 300edbf8b4fSSimon Glass if (err) 301edbf8b4fSSimon Glass ret = err; 302edbf8b4fSSimon Glass err = cm_fx6_setup_one_i2c(1, I2C_PADS_INFO(i2c1_pads)); 303edbf8b4fSSimon Glass if (err) 304edbf8b4fSSimon Glass ret = err; 305edbf8b4fSSimon Glass err = cm_fx6_setup_one_i2c(2, I2C_PADS_INFO(i2c2_pads)); 306edbf8b4fSSimon Glass if (err) 307edbf8b4fSSimon Glass ret = err; 308edbf8b4fSSimon Glass 309edbf8b4fSSimon Glass return ret; 310f42b2f60SNikita Kiryanov } 311f42b2f60SNikita Kiryanov #else 312edbf8b4fSSimon Glass static int cm_fx6_setup_i2c(void) { return 0; } 313f42b2f60SNikita Kiryanov #endif 314f42b2f60SNikita Kiryanov 3150f3effb9SNikita Kiryanov #ifdef CONFIG_USB_EHCI_MX6 3160f3effb9SNikita Kiryanov #define WEAK_PULLDOWN (PAD_CTL_PUS_100K_DOWN | \ 3170f3effb9SNikita Kiryanov PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ 3180f3effb9SNikita Kiryanov PAD_CTL_HYS | PAD_CTL_SRE_SLOW) 3198f488c1bSNikita Kiryanov #define MX6_USBNC_BASEADDR 0x2184800 3208f488c1bSNikita Kiryanov #define USBNC_USB_H1_PWR_POL (1 << 9) 3210f3effb9SNikita Kiryanov 3228f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_host(void) 3230f3effb9SNikita Kiryanov { 3240f3effb9SNikita Kiryanov int err; 3250f3effb9SNikita Kiryanov 3260f3effb9SNikita Kiryanov err = gpio_request(CM_FX6_USB_HUB_RST, "usb hub rst"); 3278f488c1bSNikita Kiryanov if (err) 3288f488c1bSNikita Kiryanov return err; 3290f3effb9SNikita Kiryanov 3308f488c1bSNikita Kiryanov SETUP_IOMUX_PAD(PAD_GPIO_0__USB_H1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL)); 3310f3effb9SNikita Kiryanov SETUP_IOMUX_PAD(PAD_SD3_RST__GPIO7_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL)); 3320f3effb9SNikita Kiryanov 3330f3effb9SNikita Kiryanov return 0; 3340f3effb9SNikita Kiryanov } 3350f3effb9SNikita Kiryanov 3368f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_otg(void) 3370f3effb9SNikita Kiryanov { 3388f488c1bSNikita Kiryanov int err; 3390f3effb9SNikita Kiryanov struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; 3400f3effb9SNikita Kiryanov 3418f488c1bSNikita Kiryanov err = gpio_request(SB_FX6_USB_OTG_PWR, "usb-pwr"); 3428f488c1bSNikita Kiryanov if (err) { 3438f488c1bSNikita Kiryanov printf("USB OTG pwr gpio request failed: %d\n", err); 3448f488c1bSNikita Kiryanov return err; 3450f3effb9SNikita Kiryanov } 3460f3effb9SNikita Kiryanov 3470f3effb9SNikita Kiryanov SETUP_IOMUX_PAD(PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL)); 3480f3effb9SNikita Kiryanov SETUP_IOMUX_PAD(PAD_ENET_RX_ER__USB_OTG_ID | 3490f3effb9SNikita Kiryanov MUX_PAD_CTRL(WEAK_PULLDOWN)); 3500f3effb9SNikita Kiryanov clrbits_le32(&iomux->gpr[1], IOMUXC_GPR1_OTG_ID_MASK); 3510f3effb9SNikita Kiryanov /* disable ext. charger detect, or it'll affect signal quality at dp. */ 3520f3effb9SNikita Kiryanov return gpio_direction_output(SB_FX6_USB_OTG_PWR, 0); 3530f3effb9SNikita Kiryanov } 3540f3effb9SNikita Kiryanov 355d6276ab1SNikita Kiryanov int board_usb_phy_mode(int port) 356d6276ab1SNikita Kiryanov { 357d6276ab1SNikita Kiryanov return USB_INIT_HOST; 358d6276ab1SNikita Kiryanov } 359d6276ab1SNikita Kiryanov 3600f3effb9SNikita Kiryanov int board_ehci_hcd_init(int port) 3610f3effb9SNikita Kiryanov { 3628f488c1bSNikita Kiryanov int ret; 3630f3effb9SNikita Kiryanov u32 *usbnc_usb_uh1_ctrl = (u32 *)(MX6_USBNC_BASEADDR + 4); 3640f3effb9SNikita Kiryanov 3658f488c1bSNikita Kiryanov /* Only 1 host controller in use. port 0 is OTG & needs no attention */ 3668f488c1bSNikita Kiryanov if (port != 1) 3678f488c1bSNikita Kiryanov return 0; 3680f3effb9SNikita Kiryanov 3690f3effb9SNikita Kiryanov /* Set PWR polarity to match power switch's enable polarity */ 3700f3effb9SNikita Kiryanov setbits_le32(usbnc_usb_uh1_ctrl, USBNC_USB_H1_PWR_POL); 3718f488c1bSNikita Kiryanov ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 0); 3728f488c1bSNikita Kiryanov if (ret) 3738f488c1bSNikita Kiryanov return ret; 3748f488c1bSNikita Kiryanov 3758f488c1bSNikita Kiryanov udelay(10); 3768f488c1bSNikita Kiryanov ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 1); 3778f488c1bSNikita Kiryanov if (ret) 3788f488c1bSNikita Kiryanov return ret; 3798f488c1bSNikita Kiryanov 3808f488c1bSNikita Kiryanov mdelay(1); 3810f3effb9SNikita Kiryanov 3820f3effb9SNikita Kiryanov return 0; 3830f3effb9SNikita Kiryanov } 3840f3effb9SNikita Kiryanov 3850f3effb9SNikita Kiryanov int board_ehci_power(int port, int on) 3860f3effb9SNikita Kiryanov { 3870f3effb9SNikita Kiryanov if (port == 0) 3880f3effb9SNikita Kiryanov return gpio_direction_output(SB_FX6_USB_OTG_PWR, on); 3890f3effb9SNikita Kiryanov 3900f3effb9SNikita Kiryanov return 0; 3910f3effb9SNikita Kiryanov } 3928f488c1bSNikita Kiryanov #else 3938f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_otg(void) { return 0; } 3948f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_host(void) { return 0; } 3950f3effb9SNikita Kiryanov #endif 3960f3effb9SNikita Kiryanov 39702b1343eSNikita Kiryanov #ifdef CONFIG_FEC_MXC 39802b1343eSNikita Kiryanov #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 39902b1343eSNikita Kiryanov PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 40002b1343eSNikita Kiryanov 40102b1343eSNikita Kiryanov static int mx6_rgmii_rework(struct phy_device *phydev) 40202b1343eSNikita Kiryanov { 40302b1343eSNikita Kiryanov unsigned short val; 40402b1343eSNikita Kiryanov 40502b1343eSNikita Kiryanov /* Ar8031 phy SmartEEE feature cause link status generates glitch, 40602b1343eSNikita Kiryanov * which cause ethernet link down/up issue, so disable SmartEEE 40702b1343eSNikita Kiryanov */ 40802b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x3); 40902b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x805d); 41002b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4003); 41102b1343eSNikita Kiryanov val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); 41202b1343eSNikita Kiryanov val &= ~(0x1 << 8); 41302b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val); 41402b1343eSNikita Kiryanov 41502b1343eSNikita Kiryanov /* To enable AR8031 ouput a 125MHz clk from CLK_25M */ 41602b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7); 41702b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); 41802b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); 41902b1343eSNikita Kiryanov 42002b1343eSNikita Kiryanov val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); 42102b1343eSNikita Kiryanov val &= 0xffe3; 42202b1343eSNikita Kiryanov val |= 0x18; 42302b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val); 42402b1343eSNikita Kiryanov 42502b1343eSNikita Kiryanov /* introduce tx clock delay */ 42602b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); 42702b1343eSNikita Kiryanov val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); 42802b1343eSNikita Kiryanov val |= 0x0100; 42902b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val); 43002b1343eSNikita Kiryanov 43102b1343eSNikita Kiryanov return 0; 43202b1343eSNikita Kiryanov } 43302b1343eSNikita Kiryanov 43402b1343eSNikita Kiryanov int board_phy_config(struct phy_device *phydev) 43502b1343eSNikita Kiryanov { 43602b1343eSNikita Kiryanov mx6_rgmii_rework(phydev); 43702b1343eSNikita Kiryanov 43802b1343eSNikita Kiryanov if (phydev->drv->config) 43902b1343eSNikita Kiryanov return phydev->drv->config(phydev); 44002b1343eSNikita Kiryanov 44102b1343eSNikita Kiryanov return 0; 44202b1343eSNikita Kiryanov } 44302b1343eSNikita Kiryanov 44402b1343eSNikita Kiryanov static iomux_v3_cfg_t const enet_pads[] = { 44502b1343eSNikita Kiryanov IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)), 44602b1343eSNikita Kiryanov IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 44702b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 44802b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 44902b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45002b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45102b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45202b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45302b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45402b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45502b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45602b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 45702b1343eSNikita Kiryanov IOMUX_PADS(PAD_GPIO_0__CCM_CLKO1 | MUX_PAD_CTRL(NO_PAD_CTRL)), 45802b1343eSNikita Kiryanov IOMUX_PADS(PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL)), 45902b1343eSNikita Kiryanov IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(0x84)), 46002b1343eSNikita Kiryanov IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | 46102b1343eSNikita Kiryanov MUX_PAD_CTRL(ENET_PAD_CTRL)), 46202b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | 46302b1343eSNikita Kiryanov MUX_PAD_CTRL(ENET_PAD_CTRL)), 46402b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | 46502b1343eSNikita Kiryanov MUX_PAD_CTRL(ENET_PAD_CTRL)), 46602b1343eSNikita Kiryanov }; 46702b1343eSNikita Kiryanov 468eab29802SNikita Kiryanov static int handle_mac_address(char *env_var, uint eeprom_bus) 469f66113c0SNikita Kiryanov { 470f66113c0SNikita Kiryanov unsigned char enetaddr[6]; 471f66113c0SNikita Kiryanov int rc; 472f66113c0SNikita Kiryanov 473eab29802SNikita Kiryanov rc = eth_getenv_enetaddr(env_var, enetaddr); 474f66113c0SNikita Kiryanov if (rc) 475f66113c0SNikita Kiryanov return 0; 476f66113c0SNikita Kiryanov 477eab29802SNikita Kiryanov rc = cl_eeprom_read_mac_addr(enetaddr, eeprom_bus); 478f66113c0SNikita Kiryanov if (rc) 479f66113c0SNikita Kiryanov return rc; 480f66113c0SNikita Kiryanov 4810adb5b76SJoe Hershberger if (!is_valid_ethaddr(enetaddr)) 482f66113c0SNikita Kiryanov return -1; 483f66113c0SNikita Kiryanov 484*fd1e959eSSimon Glass return eth_env_set_enetaddr(env_var, enetaddr); 485f66113c0SNikita Kiryanov } 486f66113c0SNikita Kiryanov 487eab29802SNikita Kiryanov #define SB_FX6_I2C_EEPROM_BUS 0 488eab29802SNikita Kiryanov #define NO_MAC_ADDR "No MAC address found for %s\n" 48902b1343eSNikita Kiryanov int board_eth_init(bd_t *bis) 49002b1343eSNikita Kiryanov { 4918f488c1bSNikita Kiryanov int err; 4928f488c1bSNikita Kiryanov 493eab29802SNikita Kiryanov if (handle_mac_address("ethaddr", CONFIG_SYS_I2C_EEPROM_BUS)) 494eab29802SNikita Kiryanov printf(NO_MAC_ADDR, "primary NIC"); 495eab29802SNikita Kiryanov 496eab29802SNikita Kiryanov if (handle_mac_address("eth1addr", SB_FX6_I2C_EEPROM_BUS)) 497eab29802SNikita Kiryanov printf(NO_MAC_ADDR, "secondary NIC"); 498f66113c0SNikita Kiryanov 49902b1343eSNikita Kiryanov SETUP_IOMUX_PADS(enet_pads); 50002b1343eSNikita Kiryanov /* phy reset */ 5018f488c1bSNikita Kiryanov err = gpio_request(CM_FX6_ENET_NRST, "enet_nrst"); 5028f488c1bSNikita Kiryanov if (err) 5038f488c1bSNikita Kiryanov printf("Etnernet NRST gpio request failed: %d\n", err); 50402b1343eSNikita Kiryanov gpio_direction_output(CM_FX6_ENET_NRST, 0); 50502b1343eSNikita Kiryanov udelay(500); 50602b1343eSNikita Kiryanov gpio_set_value(CM_FX6_ENET_NRST, 1); 50702b1343eSNikita Kiryanov enable_enet_clk(1); 50802b1343eSNikita Kiryanov return cpu_eth_init(bis); 50902b1343eSNikita Kiryanov } 51002b1343eSNikita Kiryanov #endif 51102b1343eSNikita Kiryanov 512a6b0652bSNikita Kiryanov #ifdef CONFIG_NAND_MXS 513a6b0652bSNikita Kiryanov static iomux_v3_cfg_t const nand_pads[] = { 514a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_CLE__NAND_CLE | MUX_PAD_CTRL(NO_PAD_CTRL)), 515a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_ALE__NAND_ALE | MUX_PAD_CTRL(NO_PAD_CTRL)), 516a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_CS0__NAND_CE0_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 517a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 518a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D0__NAND_DATA00 | MUX_PAD_CTRL(NO_PAD_CTRL)), 519a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D1__NAND_DATA01 | MUX_PAD_CTRL(NO_PAD_CTRL)), 520a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D2__NAND_DATA02 | MUX_PAD_CTRL(NO_PAD_CTRL)), 521a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D3__NAND_DATA03 | MUX_PAD_CTRL(NO_PAD_CTRL)), 522a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D4__NAND_DATA04 | MUX_PAD_CTRL(NO_PAD_CTRL)), 523a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D5__NAND_DATA05 | MUX_PAD_CTRL(NO_PAD_CTRL)), 524a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D6__NAND_DATA06 | MUX_PAD_CTRL(NO_PAD_CTRL)), 525a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D7__NAND_DATA07 | MUX_PAD_CTRL(NO_PAD_CTRL)), 526a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_SD4_CMD__NAND_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 527a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_SD4_CLK__NAND_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 528a6b0652bSNikita Kiryanov }; 529a6b0652bSNikita Kiryanov 530a6b0652bSNikita Kiryanov static void cm_fx6_setup_gpmi_nand(void) 531a6b0652bSNikita Kiryanov { 532a6b0652bSNikita Kiryanov SETUP_IOMUX_PADS(nand_pads); 533a6b0652bSNikita Kiryanov /* Enable clock roots */ 534a6b0652bSNikita Kiryanov enable_usdhc_clk(1, 3); 535a6b0652bSNikita Kiryanov enable_usdhc_clk(1, 4); 536a6b0652bSNikita Kiryanov 537a6b0652bSNikita Kiryanov setup_gpmi_io_clk(MXC_CCM_CS2CDR_ENFC_CLK_PODF(0xf) | 538a6b0652bSNikita Kiryanov MXC_CCM_CS2CDR_ENFC_CLK_PRED(1) | 539a6b0652bSNikita Kiryanov MXC_CCM_CS2CDR_ENFC_CLK_SEL(0)); 540a6b0652bSNikita Kiryanov } 541a6b0652bSNikita Kiryanov #else 542a6b0652bSNikita Kiryanov static void cm_fx6_setup_gpmi_nand(void) {} 543a6b0652bSNikita Kiryanov #endif 544a6b0652bSNikita Kiryanov 545e32028a7SNikita Kiryanov #ifdef CONFIG_FSL_ESDHC 546e32028a7SNikita Kiryanov static struct fsl_esdhc_cfg usdhc_cfg[3] = { 547e32028a7SNikita Kiryanov {USDHC1_BASE_ADDR}, 548e32028a7SNikita Kiryanov {USDHC2_BASE_ADDR}, 549e32028a7SNikita Kiryanov {USDHC3_BASE_ADDR}, 550e32028a7SNikita Kiryanov }; 551e32028a7SNikita Kiryanov 552e32028a7SNikita Kiryanov static enum mxc_clock usdhc_clk[3] = { 553e32028a7SNikita Kiryanov MXC_ESDHC_CLK, 554e32028a7SNikita Kiryanov MXC_ESDHC2_CLK, 555e32028a7SNikita Kiryanov MXC_ESDHC3_CLK, 556e32028a7SNikita Kiryanov }; 557e32028a7SNikita Kiryanov 558e32028a7SNikita Kiryanov int board_mmc_init(bd_t *bis) 559e32028a7SNikita Kiryanov { 560e32028a7SNikita Kiryanov int i; 561e32028a7SNikita Kiryanov 562e32028a7SNikita Kiryanov cm_fx6_set_usdhc_iomux(); 563e32028a7SNikita Kiryanov for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { 564e32028a7SNikita Kiryanov usdhc_cfg[i].sdhc_clk = mxc_get_clock(usdhc_clk[i]); 565e32028a7SNikita Kiryanov usdhc_cfg[i].max_bus_width = 4; 566e32028a7SNikita Kiryanov fsl_esdhc_initialize(bis, &usdhc_cfg[i]); 567e32028a7SNikita Kiryanov enable_usdhc_clk(1, i); 568e32028a7SNikita Kiryanov } 569e32028a7SNikita Kiryanov 570e32028a7SNikita Kiryanov return 0; 571e32028a7SNikita Kiryanov } 572e32028a7SNikita Kiryanov #endif 573e32028a7SNikita Kiryanov 5748f488c1bSNikita Kiryanov #ifdef CONFIG_MXC_SPI 5758f488c1bSNikita Kiryanov int cm_fx6_setup_ecspi(void) 5768f488c1bSNikita Kiryanov { 5778f488c1bSNikita Kiryanov cm_fx6_set_ecspi_iomux(); 5788f488c1bSNikita Kiryanov return gpio_request(CM_FX6_ECSPI_BUS0_CS0, "ecspi_bus0_cs0"); 5798f488c1bSNikita Kiryanov } 5808f488c1bSNikita Kiryanov #else 5818f488c1bSNikita Kiryanov int cm_fx6_setup_ecspi(void) { return 0; } 5828f488c1bSNikita Kiryanov #endif 5838f488c1bSNikita Kiryanov 58402b1343eSNikita Kiryanov #ifdef CONFIG_OF_BOARD_SETUP 58541855186SNikita Kiryanov #define USDHC3_PATH "/soc/aips-bus@02100000/usdhc@02198000/" 58662d6bac6SChristopher Spinrath 58762d6bac6SChristopher Spinrath struct node_info nodes[] = { 58862d6bac6SChristopher Spinrath /* 58962d6bac6SChristopher Spinrath * Both entries target the same flash chip. The st,m25p compatible 59062d6bac6SChristopher Spinrath * is used in the vendor device trees, while upstream uses (the 591f8de60bdSChristopher Spinrath * documented) jedec,spi-nor compatible. 59262d6bac6SChristopher Spinrath */ 59362d6bac6SChristopher Spinrath { "st,m25p", MTD_DEV_TYPE_NOR, }, 59462d6bac6SChristopher Spinrath { "jedec,spi-nor", MTD_DEV_TYPE_NOR, }, 59562d6bac6SChristopher Spinrath }; 59662d6bac6SChristopher Spinrath 597e895a4b0SSimon Glass int ft_board_setup(void *blob, bd_t *bd) 59802b1343eSNikita Kiryanov { 59941855186SNikita Kiryanov u32 baseboard_rev; 60041855186SNikita Kiryanov int nodeoffset; 60102b1343eSNikita Kiryanov uint8_t enetaddr[6]; 60241855186SNikita Kiryanov char baseboard_name[16]; 60341855186SNikita Kiryanov int err; 60402b1343eSNikita Kiryanov 605ef476836SHannes Schmelzer fdt_shrink_to_minimum(blob, 0); /* Make room for new properties */ 60662d6bac6SChristopher Spinrath 60702b1343eSNikita Kiryanov /* MAC addr */ 60802b1343eSNikita Kiryanov if (eth_getenv_enetaddr("ethaddr", enetaddr)) { 609cc67f4a6SNikita Kiryanov fdt_find_and_setprop(blob, 610cc67f4a6SNikita Kiryanov "/soc/aips-bus@02100000/ethernet@02188000", 611cc67f4a6SNikita Kiryanov "local-mac-address", enetaddr, 6, 1); 61202b1343eSNikita Kiryanov } 613e895a4b0SSimon Glass 614eab29802SNikita Kiryanov if (eth_getenv_enetaddr("eth1addr", enetaddr)) { 615eab29802SNikita Kiryanov fdt_find_and_setprop(blob, "/eth@pcie", "local-mac-address", 616eab29802SNikita Kiryanov enetaddr, 6, 1); 617eab29802SNikita Kiryanov } 618eab29802SNikita Kiryanov 619f8de60bdSChristopher Spinrath fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); 620f8de60bdSChristopher Spinrath 62141855186SNikita Kiryanov baseboard_rev = cl_eeprom_get_board_rev(0); 62241855186SNikita Kiryanov err = cl_eeprom_get_product_name((uchar *)baseboard_name, 0); 62341855186SNikita Kiryanov if (err || baseboard_rev == 0) 62441855186SNikita Kiryanov return 0; /* Assume not an early revision SB-FX6m baseboard */ 62541855186SNikita Kiryanov 62641855186SNikita Kiryanov if (!strncmp("SB-FX6m", baseboard_name, 7) && baseboard_rev <= 120) { 62741855186SNikita Kiryanov nodeoffset = fdt_path_offset(blob, USDHC3_PATH); 62841855186SNikita Kiryanov fdt_delprop(blob, nodeoffset, "cd-gpios"); 629c133c503SChristopher Spinrath fdt_find_and_setprop(blob, USDHC3_PATH, "broken-cd", 63041855186SNikita Kiryanov NULL, 0, 1); 63141855186SNikita Kiryanov fdt_find_and_setprop(blob, USDHC3_PATH, "keep-power-in-suspend", 63241855186SNikita Kiryanov NULL, 0, 1); 63341855186SNikita Kiryanov } 63441855186SNikita Kiryanov 635e895a4b0SSimon Glass return 0; 63602b1343eSNikita Kiryanov } 63702b1343eSNikita Kiryanov #endif 63802b1343eSNikita Kiryanov 639e32028a7SNikita Kiryanov int board_init(void) 640e32028a7SNikita Kiryanov { 641edbf8b4fSSimon Glass int ret; 642edbf8b4fSSimon Glass 643e32028a7SNikita Kiryanov gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; 644a6b0652bSNikita Kiryanov cm_fx6_setup_gpmi_nand(); 645edbf8b4fSSimon Glass 6468f488c1bSNikita Kiryanov ret = cm_fx6_setup_ecspi(); 6478f488c1bSNikita Kiryanov if (ret) 6488f488c1bSNikita Kiryanov printf("Warning: ECSPI setup failed: %d\n", ret); 6498f488c1bSNikita Kiryanov 6508f488c1bSNikita Kiryanov ret = cm_fx6_setup_usb_otg(); 6518f488c1bSNikita Kiryanov if (ret) 6528f488c1bSNikita Kiryanov printf("Warning: USB OTG setup failed: %d\n", ret); 6538f488c1bSNikita Kiryanov 6548f488c1bSNikita Kiryanov ret = cm_fx6_setup_usb_host(); 6558f488c1bSNikita Kiryanov if (ret) 6568f488c1bSNikita Kiryanov printf("Warning: USB host setup failed: %d\n", ret); 6578f488c1bSNikita Kiryanov 6588f488c1bSNikita Kiryanov /* 6598f488c1bSNikita Kiryanov * cm-fx6 may have iSSD not assembled and in this case it has 6608f488c1bSNikita Kiryanov * bypasses for a (m)SATA socket on the baseboard. The socketed 6618f488c1bSNikita Kiryanov * device is not controlled by those GPIOs. So just print a warning 6628f488c1bSNikita Kiryanov * if the setup fails. 6638f488c1bSNikita Kiryanov */ 6648f488c1bSNikita Kiryanov ret = cm_fx6_setup_issd(); 6658f488c1bSNikita Kiryanov if (ret) 6668f488c1bSNikita Kiryanov printf("Warning: iSSD setup failed: %d\n", ret); 6678f488c1bSNikita Kiryanov 668edbf8b4fSSimon Glass /* Warn on failure but do not abort boot */ 669edbf8b4fSSimon Glass ret = cm_fx6_setup_i2c(); 670edbf8b4fSSimon Glass if (ret) 671edbf8b4fSSimon Glass printf("Warning: I2C setup failed: %d\n", ret); 672a6b0652bSNikita Kiryanov 673deb94d61SNikita Kiryanov cm_fx6_setup_display(); 674deb94d61SNikita Kiryanov 675e32028a7SNikita Kiryanov return 0; 676e32028a7SNikita Kiryanov } 677e32028a7SNikita Kiryanov 678e32028a7SNikita Kiryanov int checkboard(void) 679e32028a7SNikita Kiryanov { 680e32028a7SNikita Kiryanov puts("Board: CM-FX6\n"); 681e32028a7SNikita Kiryanov return 0; 682e32028a7SNikita Kiryanov } 683e32028a7SNikita Kiryanov 6847d1abb7dSNikita Kiryanov int misc_init_r(void) 6857d1abb7dSNikita Kiryanov { 6867d1abb7dSNikita Kiryanov cl_print_pcb_info(); 6877d1abb7dSNikita Kiryanov 6887d1abb7dSNikita Kiryanov return 0; 6897d1abb7dSNikita Kiryanov } 6907d1abb7dSNikita Kiryanov 69176b00acaSSimon Glass int dram_init_banksize(void) 692e32028a7SNikita Kiryanov { 693e32028a7SNikita Kiryanov gd->bd->bi_dram[0].start = PHYS_SDRAM_1; 694e32028a7SNikita Kiryanov gd->bd->bi_dram[1].start = PHYS_SDRAM_2; 695e32028a7SNikita Kiryanov 696e32028a7SNikita Kiryanov switch (gd->ram_size) { 697e32028a7SNikita Kiryanov case 0x10000000: /* DDR_16BIT_256MB */ 698e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x10000000; 699e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0; 700e32028a7SNikita Kiryanov break; 701e32028a7SNikita Kiryanov case 0x20000000: /* DDR_32BIT_512MB */ 702e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x20000000; 703e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0; 704e32028a7SNikita Kiryanov break; 705e32028a7SNikita Kiryanov case 0x40000000: 706e32028a7SNikita Kiryanov if (is_cpu_type(MXC_CPU_MX6SOLO)) { /* DDR_32BIT_1GB */ 707e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x20000000; 708e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0x20000000; 709e32028a7SNikita Kiryanov } else { /* DDR_64BIT_1GB */ 710e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x40000000; 711e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0; 712e32028a7SNikita Kiryanov } 713e32028a7SNikita Kiryanov break; 714e32028a7SNikita Kiryanov case 0x80000000: /* DDR_64BIT_2GB */ 715e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x40000000; 716e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0x40000000; 717e32028a7SNikita Kiryanov break; 718e32028a7SNikita Kiryanov case 0xEFF00000: /* DDR_64BIT_4GB */ 719e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x70000000; 720e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0x7FF00000; 721e32028a7SNikita Kiryanov break; 722e32028a7SNikita Kiryanov } 72376b00acaSSimon Glass 72476b00acaSSimon Glass return 0; 725e32028a7SNikita Kiryanov } 726e32028a7SNikita Kiryanov 727e32028a7SNikita Kiryanov int dram_init(void) 728e32028a7SNikita Kiryanov { 729e32028a7SNikita Kiryanov gd->ram_size = imx_ddr_size(); 730e32028a7SNikita Kiryanov switch (gd->ram_size) { 731e32028a7SNikita Kiryanov case 0x10000000: 732e32028a7SNikita Kiryanov case 0x20000000: 733e32028a7SNikita Kiryanov case 0x40000000: 734e32028a7SNikita Kiryanov case 0x80000000: 735e32028a7SNikita Kiryanov break; 736e32028a7SNikita Kiryanov case 0xF0000000: 737e32028a7SNikita Kiryanov gd->ram_size -= 0x100000; 738e32028a7SNikita Kiryanov break; 739e32028a7SNikita Kiryanov default: 740e32028a7SNikita Kiryanov printf("ERROR: Unsupported DRAM size 0x%lx\n", gd->ram_size); 741e32028a7SNikita Kiryanov return -1; 742e32028a7SNikita Kiryanov } 743e32028a7SNikita Kiryanov 744e32028a7SNikita Kiryanov return 0; 745e32028a7SNikita Kiryanov } 746f66113c0SNikita Kiryanov 747f66113c0SNikita Kiryanov u32 get_board_rev(void) 748f66113c0SNikita Kiryanov { 74972898ac7SNikita Kiryanov return cl_eeprom_get_board_rev(CONFIG_SYS_I2C_EEPROM_BUS); 750f66113c0SNikita Kiryanov } 751f66113c0SNikita Kiryanov 7523f0e935fSSimon Glass static struct mxc_serial_platdata cm_fx6_mxc_serial_plat = { 7533f0e935fSSimon Glass .reg = (struct mxc_uart *)UART4_BASE, 7543f0e935fSSimon Glass }; 7553f0e935fSSimon Glass 7563f0e935fSSimon Glass U_BOOT_DEVICE(cm_fx6_serial) = { 7573f0e935fSSimon Glass .name = "serial_mxc", 7583f0e935fSSimon Glass .platdata = &cm_fx6_mxc_serial_plat, 7593f0e935fSSimon Glass }; 760