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> 1502b1343eSNikita Kiryanov #include <netdev.h> 164377859aSNikita Kiryanov #include <errno.h> 17d6276ab1SNikita Kiryanov #include <usb.h> 1802b1343eSNikita Kiryanov #include <fdt_support.h> 19206f38f7SNikita Kiryanov #include <sata.h> 20f82eb2faSNikita Kiryanov #include <splash.h> 21a6b0652bSNikita Kiryanov #include <asm/arch/crm_regs.h> 22e32028a7SNikita Kiryanov #include <asm/arch/sys_proto.h> 230f3effb9SNikita Kiryanov #include <asm/arch/iomux.h> 24deb94d61SNikita Kiryanov #include <asm/arch/mxc_hdmi.h> 25f42b2f60SNikita Kiryanov #include <asm/imx-common/mxc_i2c.h> 26206f38f7SNikita Kiryanov #include <asm/imx-common/sata.h> 27deb94d61SNikita Kiryanov #include <asm/imx-common/video.h> 28a6b0652bSNikita Kiryanov #include <asm/io.h> 2902b1343eSNikita Kiryanov #include <asm/gpio.h> 3086256b79SMasahiro Yamada #include <dm/platform_data/serial_mxc.h> 31e32028a7SNikita Kiryanov #include "common.h" 32f66113c0SNikita Kiryanov #include "../common/eeprom.h" 333a236a35SNikita Kiryanov #include "../common/common.h" 34e32028a7SNikita Kiryanov 35e32028a7SNikita Kiryanov DECLARE_GLOBAL_DATA_PTR; 36e32028a7SNikita Kiryanov 373a236a35SNikita Kiryanov #ifdef CONFIG_SPLASH_SCREEN 383a236a35SNikita Kiryanov static struct splash_location cm_fx6_splash_locations[] = { 393a236a35SNikita Kiryanov { 403a236a35SNikita Kiryanov .name = "sf", 413a236a35SNikita Kiryanov .storage = SPLASH_STORAGE_SF, 42*870dd309SNikita Kiryanov .flags = SPLASH_STORAGE_RAW, 433a236a35SNikita Kiryanov .offset = 0x100000, 443a236a35SNikita Kiryanov }, 453a236a35SNikita Kiryanov }; 463a236a35SNikita Kiryanov 473a236a35SNikita Kiryanov int splash_screen_prepare(void) 483a236a35SNikita Kiryanov { 49f82eb2faSNikita Kiryanov return splash_source_load(cm_fx6_splash_locations, 503a236a35SNikita Kiryanov ARRAY_SIZE(cm_fx6_splash_locations)); 513a236a35SNikita Kiryanov } 523a236a35SNikita Kiryanov #endif 533a236a35SNikita Kiryanov 54deb94d61SNikita Kiryanov #ifdef CONFIG_IMX_HDMI 55deb94d61SNikita Kiryanov static void cm_fx6_enable_hdmi(struct display_info_t const *dev) 56deb94d61SNikita Kiryanov { 57b406f903SNikita Kiryanov struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 58b406f903SNikita Kiryanov imx_setup_hdmi(); 59b406f903SNikita Kiryanov setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK); 60deb94d61SNikita Kiryanov imx_enable_hdmi_phy(); 61deb94d61SNikita Kiryanov } 62deb94d61SNikita Kiryanov 634377859aSNikita Kiryanov static struct display_info_t preset_hdmi_1024X768 = { 64deb94d61SNikita Kiryanov .bus = -1, 65deb94d61SNikita Kiryanov .addr = 0, 66deb94d61SNikita Kiryanov .pixfmt = IPU_PIX_FMT_RGB24, 67deb94d61SNikita Kiryanov .enable = cm_fx6_enable_hdmi, 68deb94d61SNikita Kiryanov .mode = { 69deb94d61SNikita Kiryanov .name = "HDMI", 70deb94d61SNikita Kiryanov .refresh = 60, 71deb94d61SNikita Kiryanov .xres = 1024, 72deb94d61SNikita Kiryanov .yres = 768, 73deb94d61SNikita Kiryanov .pixclock = 40385, 74deb94d61SNikita Kiryanov .left_margin = 220, 75deb94d61SNikita Kiryanov .right_margin = 40, 76deb94d61SNikita Kiryanov .upper_margin = 21, 77deb94d61SNikita Kiryanov .lower_margin = 7, 78deb94d61SNikita Kiryanov .hsync_len = 60, 79deb94d61SNikita Kiryanov .vsync_len = 10, 80deb94d61SNikita Kiryanov .sync = FB_SYNC_EXT, 81deb94d61SNikita Kiryanov .vmode = FB_VMODE_NONINTERLACED, 82deb94d61SNikita Kiryanov } 83deb94d61SNikita Kiryanov }; 84deb94d61SNikita Kiryanov 85deb94d61SNikita Kiryanov static void cm_fx6_setup_display(void) 86deb94d61SNikita Kiryanov { 8775dbbbfdSNikita Kiryanov struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; 88deb94d61SNikita Kiryanov 89deb94d61SNikita Kiryanov enable_ipu_clock(); 9075dbbbfdSNikita Kiryanov clrbits_le32(&iomuxc_regs->gpr[3], MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK); 91deb94d61SNikita Kiryanov } 924377859aSNikita Kiryanov 934377859aSNikita Kiryanov int board_video_skip(void) 944377859aSNikita Kiryanov { 954377859aSNikita Kiryanov int ret; 964377859aSNikita Kiryanov struct display_info_t *preset; 9733299499SNikita Kiryanov char const *panel = getenv("displaytype"); 9833299499SNikita Kiryanov 9933299499SNikita Kiryanov if (!panel) /* Also accept panel for backward compatibility */ 10033299499SNikita Kiryanov panel = getenv("panel"); 1014377859aSNikita Kiryanov 1024377859aSNikita Kiryanov if (!panel) 1034377859aSNikita Kiryanov return -ENOENT; 1044377859aSNikita Kiryanov 1054377859aSNikita Kiryanov if (!strcmp(panel, "HDMI")) 1064377859aSNikita Kiryanov preset = &preset_hdmi_1024X768; 1074377859aSNikita Kiryanov else 1084377859aSNikita Kiryanov return -EINVAL; 1094377859aSNikita Kiryanov 1104377859aSNikita Kiryanov ret = ipuv3_fb_init(&preset->mode, 0, preset->pixfmt); 1114377859aSNikita Kiryanov if (ret) { 1124377859aSNikita Kiryanov printf("Can't init display %s: %d\n", preset->mode.name, ret); 1134377859aSNikita Kiryanov return ret; 1144377859aSNikita Kiryanov } 1154377859aSNikita Kiryanov 1164377859aSNikita Kiryanov preset->enable(preset); 1174377859aSNikita Kiryanov printf("Display: %s (%ux%u)\n", preset->mode.name, preset->mode.xres, 1184377859aSNikita Kiryanov preset->mode.yres); 1194377859aSNikita Kiryanov 1204377859aSNikita Kiryanov return 0; 1214377859aSNikita Kiryanov } 122deb94d61SNikita Kiryanov #else 123deb94d61SNikita Kiryanov static inline void cm_fx6_setup_display(void) {} 124deb94d61SNikita Kiryanov #endif /* CONFIG_VIDEO_IPUV3 */ 125deb94d61SNikita Kiryanov 126206f38f7SNikita Kiryanov #ifdef CONFIG_DWC_AHSATA 127206f38f7SNikita Kiryanov static int cm_fx6_issd_gpios[] = { 128206f38f7SNikita Kiryanov /* The order of the GPIOs in the array is important! */ 129b65cbab1SNikita Kiryanov CM_FX6_SATA_LDO_EN, 130206f38f7SNikita Kiryanov CM_FX6_SATA_PHY_SLP, 131206f38f7SNikita Kiryanov CM_FX6_SATA_NRSTDLY, 132206f38f7SNikita Kiryanov CM_FX6_SATA_PWREN, 133206f38f7SNikita Kiryanov CM_FX6_SATA_NSTANDBY1, 134206f38f7SNikita Kiryanov CM_FX6_SATA_NSTANDBY2, 135206f38f7SNikita Kiryanov }; 136206f38f7SNikita Kiryanov 137206f38f7SNikita Kiryanov static void cm_fx6_sata_power(int on) 138206f38f7SNikita Kiryanov { 139206f38f7SNikita Kiryanov int i; 140206f38f7SNikita Kiryanov 141206f38f7SNikita Kiryanov if (!on) { /* tell the iSSD that the power will be removed */ 142206f38f7SNikita Kiryanov gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 1); 143206f38f7SNikita Kiryanov mdelay(10); 144206f38f7SNikita Kiryanov } 145206f38f7SNikita Kiryanov 146206f38f7SNikita Kiryanov for (i = 0; i < ARRAY_SIZE(cm_fx6_issd_gpios); i++) { 147206f38f7SNikita Kiryanov gpio_direction_output(cm_fx6_issd_gpios[i], on); 148206f38f7SNikita Kiryanov udelay(100); 149206f38f7SNikita Kiryanov } 150206f38f7SNikita Kiryanov 151206f38f7SNikita Kiryanov if (!on) /* for compatibility lower the power loss interrupt */ 152206f38f7SNikita Kiryanov gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0); 153206f38f7SNikita Kiryanov } 154206f38f7SNikita Kiryanov 155206f38f7SNikita Kiryanov static iomux_v3_cfg_t const sata_pads[] = { 156206f38f7SNikita Kiryanov /* SATA PWR */ 157206f38f7SNikita Kiryanov IOMUX_PADS(PAD_ENET_TX_EN__GPIO1_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)), 158206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_A22__GPIO2_IO16 | MUX_PAD_CTRL(NO_PAD_CTRL)), 159206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_D20__GPIO3_IO20 | MUX_PAD_CTRL(NO_PAD_CTRL)), 160206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_A25__GPIO5_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL)), 161206f38f7SNikita Kiryanov /* SATA CTRL */ 162206f38f7SNikita Kiryanov IOMUX_PADS(PAD_ENET_TXD0__GPIO1_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL)), 163206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_D23__GPIO3_IO23 | MUX_PAD_CTRL(NO_PAD_CTRL)), 164206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL)), 165206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_A23__GPIO6_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL)), 166206f38f7SNikita Kiryanov IOMUX_PADS(PAD_EIM_BCLK__GPIO6_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL)), 167206f38f7SNikita Kiryanov }; 168206f38f7SNikita Kiryanov 1698f488c1bSNikita Kiryanov static int cm_fx6_setup_issd(void) 170206f38f7SNikita Kiryanov { 1718f488c1bSNikita Kiryanov int ret, i; 172206f38f7SNikita Kiryanov 1738f488c1bSNikita Kiryanov SETUP_IOMUX_PADS(sata_pads); 1748f488c1bSNikita Kiryanov 1758f488c1bSNikita Kiryanov for (i = 0; i < ARRAY_SIZE(cm_fx6_issd_gpios); i++) { 1768f488c1bSNikita Kiryanov ret = gpio_request(cm_fx6_issd_gpios[i], "sata"); 1778f488c1bSNikita Kiryanov if (ret) 1788f488c1bSNikita Kiryanov return ret; 1798f488c1bSNikita Kiryanov } 1808f488c1bSNikita Kiryanov 1818f488c1bSNikita Kiryanov ret = gpio_request(CM_FX6_SATA_PWLOSS_INT, "sata_pwloss_int"); 1828f488c1bSNikita Kiryanov if (ret) 1838f488c1bSNikita Kiryanov return ret; 1848f488c1bSNikita Kiryanov 1858f488c1bSNikita Kiryanov return 0; 186206f38f7SNikita Kiryanov } 187206f38f7SNikita Kiryanov 188206f38f7SNikita Kiryanov #define CM_FX6_SATA_INIT_RETRIES 10 189206f38f7SNikita Kiryanov int sata_initialize(void) 190206f38f7SNikita Kiryanov { 191206f38f7SNikita Kiryanov int err, i; 192206f38f7SNikita Kiryanov 1938f488c1bSNikita Kiryanov /* Make sure this gpio has logical 0 value */ 1948f488c1bSNikita Kiryanov gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0); 1958f488c1bSNikita Kiryanov udelay(100); 1968f488c1bSNikita Kiryanov cm_fx6_sata_power(1); 1978f488c1bSNikita Kiryanov 198206f38f7SNikita Kiryanov for (i = 0; i < CM_FX6_SATA_INIT_RETRIES; i++) { 199206f38f7SNikita Kiryanov err = setup_sata(); 200206f38f7SNikita Kiryanov if (err) { 201206f38f7SNikita Kiryanov printf("SATA setup failed: %d\n", err); 202206f38f7SNikita Kiryanov return err; 203206f38f7SNikita Kiryanov } 204206f38f7SNikita Kiryanov 205206f38f7SNikita Kiryanov udelay(100); 206206f38f7SNikita Kiryanov 207206f38f7SNikita Kiryanov err = __sata_initialize(); 208206f38f7SNikita Kiryanov if (!err) 209206f38f7SNikita Kiryanov break; 210206f38f7SNikita Kiryanov 211206f38f7SNikita Kiryanov /* There is no device on the SATA port */ 212206f38f7SNikita Kiryanov if (sata_port_status(0, 0) == 0) 213206f38f7SNikita Kiryanov break; 214206f38f7SNikita Kiryanov 215206f38f7SNikita Kiryanov /* There's a device, but link not established. Retry */ 216206f38f7SNikita Kiryanov } 217206f38f7SNikita Kiryanov 218206f38f7SNikita Kiryanov return err; 219206f38f7SNikita Kiryanov } 2209cad3544SNikita Kiryanov 2219cad3544SNikita Kiryanov int sata_stop(void) 2229cad3544SNikita Kiryanov { 2239cad3544SNikita Kiryanov __sata_stop(); 2249cad3544SNikita Kiryanov cm_fx6_sata_power(0); 2259cad3544SNikita Kiryanov mdelay(250); 2269cad3544SNikita Kiryanov 2279cad3544SNikita Kiryanov return 0; 2289cad3544SNikita Kiryanov } 2298f488c1bSNikita Kiryanov #else 2308f488c1bSNikita Kiryanov static int cm_fx6_setup_issd(void) { return 0; } 231206f38f7SNikita Kiryanov #endif 232206f38f7SNikita Kiryanov 233f42b2f60SNikita Kiryanov #ifdef CONFIG_SYS_I2C_MXC 234f42b2f60SNikita Kiryanov #define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 235f42b2f60SNikita Kiryanov PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ 236f42b2f60SNikita Kiryanov PAD_CTL_ODE | PAD_CTL_SRE_FAST) 237f42b2f60SNikita Kiryanov 238f42b2f60SNikita Kiryanov I2C_PADS(i2c0_pads, 239f42b2f60SNikita Kiryanov PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), 240f42b2f60SNikita Kiryanov PAD_EIM_D21__GPIO3_IO21 | MUX_PAD_CTRL(I2C_PAD_CTRL), 241f42b2f60SNikita Kiryanov IMX_GPIO_NR(3, 21), 242f42b2f60SNikita Kiryanov PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), 243f42b2f60SNikita Kiryanov PAD_EIM_D28__GPIO3_IO28 | MUX_PAD_CTRL(I2C_PAD_CTRL), 244f42b2f60SNikita Kiryanov IMX_GPIO_NR(3, 28)); 245f42b2f60SNikita Kiryanov 246f42b2f60SNikita Kiryanov I2C_PADS(i2c1_pads, 247f42b2f60SNikita Kiryanov PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), 248f42b2f60SNikita Kiryanov PAD_KEY_COL3__GPIO4_IO12 | MUX_PAD_CTRL(I2C_PAD_CTRL), 249f42b2f60SNikita Kiryanov IMX_GPIO_NR(4, 12), 250f42b2f60SNikita Kiryanov PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), 251f42b2f60SNikita Kiryanov PAD_KEY_ROW3__GPIO4_IO13 | MUX_PAD_CTRL(I2C_PAD_CTRL), 252f42b2f60SNikita Kiryanov IMX_GPIO_NR(4, 13)); 253f42b2f60SNikita Kiryanov 254f42b2f60SNikita Kiryanov I2C_PADS(i2c2_pads, 255f42b2f60SNikita Kiryanov PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), 256f42b2f60SNikita Kiryanov PAD_GPIO_3__GPIO1_IO03 | MUX_PAD_CTRL(I2C_PAD_CTRL), 257f42b2f60SNikita Kiryanov IMX_GPIO_NR(1, 3), 258f42b2f60SNikita Kiryanov PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), 259f42b2f60SNikita Kiryanov PAD_GPIO_6__GPIO1_IO06 | MUX_PAD_CTRL(I2C_PAD_CTRL), 260f42b2f60SNikita Kiryanov IMX_GPIO_NR(1, 6)); 261f42b2f60SNikita Kiryanov 262f42b2f60SNikita Kiryanov 263edbf8b4fSSimon Glass static int cm_fx6_setup_one_i2c(int busnum, struct i2c_pads_info *pads) 264f42b2f60SNikita Kiryanov { 265edbf8b4fSSimon Glass int ret; 266edbf8b4fSSimon Glass 267edbf8b4fSSimon Glass ret = setup_i2c(busnum, CONFIG_SYS_I2C_SPEED, 0x7f, pads); 268edbf8b4fSSimon Glass if (ret) 269edbf8b4fSSimon Glass printf("Warning: I2C%d setup failed: %d\n", busnum, ret); 270edbf8b4fSSimon Glass 271edbf8b4fSSimon Glass return ret; 272edbf8b4fSSimon Glass } 273edbf8b4fSSimon Glass 274edbf8b4fSSimon Glass static int cm_fx6_setup_i2c(void) 275edbf8b4fSSimon Glass { 276edbf8b4fSSimon Glass int ret = 0, err; 277edbf8b4fSSimon Glass 278edbf8b4fSSimon Glass /* i2c<x>_pads are wierd macro variables; we can't use an array */ 279edbf8b4fSSimon Glass err = cm_fx6_setup_one_i2c(0, I2C_PADS_INFO(i2c0_pads)); 280edbf8b4fSSimon Glass if (err) 281edbf8b4fSSimon Glass ret = err; 282edbf8b4fSSimon Glass err = cm_fx6_setup_one_i2c(1, I2C_PADS_INFO(i2c1_pads)); 283edbf8b4fSSimon Glass if (err) 284edbf8b4fSSimon Glass ret = err; 285edbf8b4fSSimon Glass err = cm_fx6_setup_one_i2c(2, I2C_PADS_INFO(i2c2_pads)); 286edbf8b4fSSimon Glass if (err) 287edbf8b4fSSimon Glass ret = err; 288edbf8b4fSSimon Glass 289edbf8b4fSSimon Glass return ret; 290f42b2f60SNikita Kiryanov } 291f42b2f60SNikita Kiryanov #else 292edbf8b4fSSimon Glass static int cm_fx6_setup_i2c(void) { return 0; } 293f42b2f60SNikita Kiryanov #endif 294f42b2f60SNikita Kiryanov 2950f3effb9SNikita Kiryanov #ifdef CONFIG_USB_EHCI_MX6 2960f3effb9SNikita Kiryanov #define WEAK_PULLDOWN (PAD_CTL_PUS_100K_DOWN | \ 2970f3effb9SNikita Kiryanov PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ 2980f3effb9SNikita Kiryanov PAD_CTL_HYS | PAD_CTL_SRE_SLOW) 2998f488c1bSNikita Kiryanov #define MX6_USBNC_BASEADDR 0x2184800 3008f488c1bSNikita Kiryanov #define USBNC_USB_H1_PWR_POL (1 << 9) 3010f3effb9SNikita Kiryanov 3028f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_host(void) 3030f3effb9SNikita Kiryanov { 3040f3effb9SNikita Kiryanov int err; 3050f3effb9SNikita Kiryanov 3060f3effb9SNikita Kiryanov err = gpio_request(CM_FX6_USB_HUB_RST, "usb hub rst"); 3078f488c1bSNikita Kiryanov if (err) 3088f488c1bSNikita Kiryanov return err; 3090f3effb9SNikita Kiryanov 3108f488c1bSNikita Kiryanov SETUP_IOMUX_PAD(PAD_GPIO_0__USB_H1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL)); 3110f3effb9SNikita Kiryanov SETUP_IOMUX_PAD(PAD_SD3_RST__GPIO7_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL)); 3120f3effb9SNikita Kiryanov 3130f3effb9SNikita Kiryanov return 0; 3140f3effb9SNikita Kiryanov } 3150f3effb9SNikita Kiryanov 3168f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_otg(void) 3170f3effb9SNikita Kiryanov { 3188f488c1bSNikita Kiryanov int err; 3190f3effb9SNikita Kiryanov struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; 3200f3effb9SNikita Kiryanov 3218f488c1bSNikita Kiryanov err = gpio_request(SB_FX6_USB_OTG_PWR, "usb-pwr"); 3228f488c1bSNikita Kiryanov if (err) { 3238f488c1bSNikita Kiryanov printf("USB OTG pwr gpio request failed: %d\n", err); 3248f488c1bSNikita Kiryanov return err; 3250f3effb9SNikita Kiryanov } 3260f3effb9SNikita Kiryanov 3270f3effb9SNikita Kiryanov SETUP_IOMUX_PAD(PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL)); 3280f3effb9SNikita Kiryanov SETUP_IOMUX_PAD(PAD_ENET_RX_ER__USB_OTG_ID | 3290f3effb9SNikita Kiryanov MUX_PAD_CTRL(WEAK_PULLDOWN)); 3300f3effb9SNikita Kiryanov clrbits_le32(&iomux->gpr[1], IOMUXC_GPR1_OTG_ID_MASK); 3310f3effb9SNikita Kiryanov /* disable ext. charger detect, or it'll affect signal quality at dp. */ 3320f3effb9SNikita Kiryanov return gpio_direction_output(SB_FX6_USB_OTG_PWR, 0); 3330f3effb9SNikita Kiryanov } 3340f3effb9SNikita Kiryanov 335d6276ab1SNikita Kiryanov int board_usb_phy_mode(int port) 336d6276ab1SNikita Kiryanov { 337d6276ab1SNikita Kiryanov return USB_INIT_HOST; 338d6276ab1SNikita Kiryanov } 339d6276ab1SNikita Kiryanov 3400f3effb9SNikita Kiryanov int board_ehci_hcd_init(int port) 3410f3effb9SNikita Kiryanov { 3428f488c1bSNikita Kiryanov int ret; 3430f3effb9SNikita Kiryanov u32 *usbnc_usb_uh1_ctrl = (u32 *)(MX6_USBNC_BASEADDR + 4); 3440f3effb9SNikita Kiryanov 3458f488c1bSNikita Kiryanov /* Only 1 host controller in use. port 0 is OTG & needs no attention */ 3468f488c1bSNikita Kiryanov if (port != 1) 3478f488c1bSNikita Kiryanov return 0; 3480f3effb9SNikita Kiryanov 3490f3effb9SNikita Kiryanov /* Set PWR polarity to match power switch's enable polarity */ 3500f3effb9SNikita Kiryanov setbits_le32(usbnc_usb_uh1_ctrl, USBNC_USB_H1_PWR_POL); 3518f488c1bSNikita Kiryanov ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 0); 3528f488c1bSNikita Kiryanov if (ret) 3538f488c1bSNikita Kiryanov return ret; 3548f488c1bSNikita Kiryanov 3558f488c1bSNikita Kiryanov udelay(10); 3568f488c1bSNikita Kiryanov ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 1); 3578f488c1bSNikita Kiryanov if (ret) 3588f488c1bSNikita Kiryanov return ret; 3598f488c1bSNikita Kiryanov 3608f488c1bSNikita Kiryanov mdelay(1); 3610f3effb9SNikita Kiryanov 3620f3effb9SNikita Kiryanov return 0; 3630f3effb9SNikita Kiryanov } 3640f3effb9SNikita Kiryanov 3650f3effb9SNikita Kiryanov int board_ehci_power(int port, int on) 3660f3effb9SNikita Kiryanov { 3670f3effb9SNikita Kiryanov if (port == 0) 3680f3effb9SNikita Kiryanov return gpio_direction_output(SB_FX6_USB_OTG_PWR, on); 3690f3effb9SNikita Kiryanov 3700f3effb9SNikita Kiryanov return 0; 3710f3effb9SNikita Kiryanov } 3728f488c1bSNikita Kiryanov #else 3738f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_otg(void) { return 0; } 3748f488c1bSNikita Kiryanov static int cm_fx6_setup_usb_host(void) { return 0; } 3750f3effb9SNikita Kiryanov #endif 3760f3effb9SNikita Kiryanov 37702b1343eSNikita Kiryanov #ifdef CONFIG_FEC_MXC 37802b1343eSNikita Kiryanov #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 37902b1343eSNikita Kiryanov PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 38002b1343eSNikita Kiryanov 38102b1343eSNikita Kiryanov static int mx6_rgmii_rework(struct phy_device *phydev) 38202b1343eSNikita Kiryanov { 38302b1343eSNikita Kiryanov unsigned short val; 38402b1343eSNikita Kiryanov 38502b1343eSNikita Kiryanov /* Ar8031 phy SmartEEE feature cause link status generates glitch, 38602b1343eSNikita Kiryanov * which cause ethernet link down/up issue, so disable SmartEEE 38702b1343eSNikita Kiryanov */ 38802b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x3); 38902b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x805d); 39002b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4003); 39102b1343eSNikita Kiryanov val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); 39202b1343eSNikita Kiryanov val &= ~(0x1 << 8); 39302b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val); 39402b1343eSNikita Kiryanov 39502b1343eSNikita Kiryanov /* To enable AR8031 ouput a 125MHz clk from CLK_25M */ 39602b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7); 39702b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); 39802b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); 39902b1343eSNikita Kiryanov 40002b1343eSNikita Kiryanov val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); 40102b1343eSNikita Kiryanov val &= 0xffe3; 40202b1343eSNikita Kiryanov val |= 0x18; 40302b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val); 40402b1343eSNikita Kiryanov 40502b1343eSNikita Kiryanov /* introduce tx clock delay */ 40602b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); 40702b1343eSNikita Kiryanov val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); 40802b1343eSNikita Kiryanov val |= 0x0100; 40902b1343eSNikita Kiryanov phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val); 41002b1343eSNikita Kiryanov 41102b1343eSNikita Kiryanov return 0; 41202b1343eSNikita Kiryanov } 41302b1343eSNikita Kiryanov 41402b1343eSNikita Kiryanov int board_phy_config(struct phy_device *phydev) 41502b1343eSNikita Kiryanov { 41602b1343eSNikita Kiryanov mx6_rgmii_rework(phydev); 41702b1343eSNikita Kiryanov 41802b1343eSNikita Kiryanov if (phydev->drv->config) 41902b1343eSNikita Kiryanov return phydev->drv->config(phydev); 42002b1343eSNikita Kiryanov 42102b1343eSNikita Kiryanov return 0; 42202b1343eSNikita Kiryanov } 42302b1343eSNikita Kiryanov 42402b1343eSNikita Kiryanov static iomux_v3_cfg_t const enet_pads[] = { 42502b1343eSNikita Kiryanov IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)), 42602b1343eSNikita Kiryanov IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 42702b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 42802b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 42902b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43002b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43102b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43202b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43302b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43402b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43502b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43602b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 43702b1343eSNikita Kiryanov IOMUX_PADS(PAD_GPIO_0__CCM_CLKO1 | MUX_PAD_CTRL(NO_PAD_CTRL)), 43802b1343eSNikita Kiryanov IOMUX_PADS(PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL)), 43902b1343eSNikita Kiryanov IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(0x84)), 44002b1343eSNikita Kiryanov IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | 44102b1343eSNikita Kiryanov MUX_PAD_CTRL(ENET_PAD_CTRL)), 44202b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | 44302b1343eSNikita Kiryanov MUX_PAD_CTRL(ENET_PAD_CTRL)), 44402b1343eSNikita Kiryanov IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | 44502b1343eSNikita Kiryanov MUX_PAD_CTRL(ENET_PAD_CTRL)), 44602b1343eSNikita Kiryanov }; 44702b1343eSNikita Kiryanov 448eab29802SNikita Kiryanov static int handle_mac_address(char *env_var, uint eeprom_bus) 449f66113c0SNikita Kiryanov { 450f66113c0SNikita Kiryanov unsigned char enetaddr[6]; 451f66113c0SNikita Kiryanov int rc; 452f66113c0SNikita Kiryanov 453eab29802SNikita Kiryanov rc = eth_getenv_enetaddr(env_var, enetaddr); 454f66113c0SNikita Kiryanov if (rc) 455f66113c0SNikita Kiryanov return 0; 456f66113c0SNikita Kiryanov 457eab29802SNikita Kiryanov rc = cl_eeprom_read_mac_addr(enetaddr, eeprom_bus); 458f66113c0SNikita Kiryanov if (rc) 459f66113c0SNikita Kiryanov return rc; 460f66113c0SNikita Kiryanov 4610adb5b76SJoe Hershberger if (!is_valid_ethaddr(enetaddr)) 462f66113c0SNikita Kiryanov return -1; 463f66113c0SNikita Kiryanov 464eab29802SNikita Kiryanov return eth_setenv_enetaddr(env_var, enetaddr); 465f66113c0SNikita Kiryanov } 466f66113c0SNikita Kiryanov 467eab29802SNikita Kiryanov #define SB_FX6_I2C_EEPROM_BUS 0 468eab29802SNikita Kiryanov #define NO_MAC_ADDR "No MAC address found for %s\n" 46902b1343eSNikita Kiryanov int board_eth_init(bd_t *bis) 47002b1343eSNikita Kiryanov { 4718f488c1bSNikita Kiryanov int err; 4728f488c1bSNikita Kiryanov 473eab29802SNikita Kiryanov if (handle_mac_address("ethaddr", CONFIG_SYS_I2C_EEPROM_BUS)) 474eab29802SNikita Kiryanov printf(NO_MAC_ADDR, "primary NIC"); 475eab29802SNikita Kiryanov 476eab29802SNikita Kiryanov if (handle_mac_address("eth1addr", SB_FX6_I2C_EEPROM_BUS)) 477eab29802SNikita Kiryanov printf(NO_MAC_ADDR, "secondary NIC"); 478f66113c0SNikita Kiryanov 47902b1343eSNikita Kiryanov SETUP_IOMUX_PADS(enet_pads); 48002b1343eSNikita Kiryanov /* phy reset */ 4818f488c1bSNikita Kiryanov err = gpio_request(CM_FX6_ENET_NRST, "enet_nrst"); 4828f488c1bSNikita Kiryanov if (err) 4838f488c1bSNikita Kiryanov printf("Etnernet NRST gpio request failed: %d\n", err); 48402b1343eSNikita Kiryanov gpio_direction_output(CM_FX6_ENET_NRST, 0); 48502b1343eSNikita Kiryanov udelay(500); 48602b1343eSNikita Kiryanov gpio_set_value(CM_FX6_ENET_NRST, 1); 48702b1343eSNikita Kiryanov enable_enet_clk(1); 48802b1343eSNikita Kiryanov return cpu_eth_init(bis); 48902b1343eSNikita Kiryanov } 49002b1343eSNikita Kiryanov #endif 49102b1343eSNikita Kiryanov 492a6b0652bSNikita Kiryanov #ifdef CONFIG_NAND_MXS 493a6b0652bSNikita Kiryanov static iomux_v3_cfg_t const nand_pads[] = { 494a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_CLE__NAND_CLE | MUX_PAD_CTRL(NO_PAD_CTRL)), 495a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_ALE__NAND_ALE | MUX_PAD_CTRL(NO_PAD_CTRL)), 496a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_CS0__NAND_CE0_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 497a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 498a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D0__NAND_DATA00 | MUX_PAD_CTRL(NO_PAD_CTRL)), 499a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D1__NAND_DATA01 | MUX_PAD_CTRL(NO_PAD_CTRL)), 500a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D2__NAND_DATA02 | MUX_PAD_CTRL(NO_PAD_CTRL)), 501a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D3__NAND_DATA03 | MUX_PAD_CTRL(NO_PAD_CTRL)), 502a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D4__NAND_DATA04 | MUX_PAD_CTRL(NO_PAD_CTRL)), 503a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D5__NAND_DATA05 | MUX_PAD_CTRL(NO_PAD_CTRL)), 504a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D6__NAND_DATA06 | MUX_PAD_CTRL(NO_PAD_CTRL)), 505a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_NANDF_D7__NAND_DATA07 | MUX_PAD_CTRL(NO_PAD_CTRL)), 506a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_SD4_CMD__NAND_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 507a6b0652bSNikita Kiryanov IOMUX_PADS(PAD_SD4_CLK__NAND_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL)), 508a6b0652bSNikita Kiryanov }; 509a6b0652bSNikita Kiryanov 510a6b0652bSNikita Kiryanov static void cm_fx6_setup_gpmi_nand(void) 511a6b0652bSNikita Kiryanov { 512a6b0652bSNikita Kiryanov SETUP_IOMUX_PADS(nand_pads); 513a6b0652bSNikita Kiryanov /* Enable clock roots */ 514a6b0652bSNikita Kiryanov enable_usdhc_clk(1, 3); 515a6b0652bSNikita Kiryanov enable_usdhc_clk(1, 4); 516a6b0652bSNikita Kiryanov 517a6b0652bSNikita Kiryanov setup_gpmi_io_clk(MXC_CCM_CS2CDR_ENFC_CLK_PODF(0xf) | 518a6b0652bSNikita Kiryanov MXC_CCM_CS2CDR_ENFC_CLK_PRED(1) | 519a6b0652bSNikita Kiryanov MXC_CCM_CS2CDR_ENFC_CLK_SEL(0)); 520a6b0652bSNikita Kiryanov } 521a6b0652bSNikita Kiryanov #else 522a6b0652bSNikita Kiryanov static void cm_fx6_setup_gpmi_nand(void) {} 523a6b0652bSNikita Kiryanov #endif 524a6b0652bSNikita Kiryanov 525e32028a7SNikita Kiryanov #ifdef CONFIG_FSL_ESDHC 526e32028a7SNikita Kiryanov static struct fsl_esdhc_cfg usdhc_cfg[3] = { 527e32028a7SNikita Kiryanov {USDHC1_BASE_ADDR}, 528e32028a7SNikita Kiryanov {USDHC2_BASE_ADDR}, 529e32028a7SNikita Kiryanov {USDHC3_BASE_ADDR}, 530e32028a7SNikita Kiryanov }; 531e32028a7SNikita Kiryanov 532e32028a7SNikita Kiryanov static enum mxc_clock usdhc_clk[3] = { 533e32028a7SNikita Kiryanov MXC_ESDHC_CLK, 534e32028a7SNikita Kiryanov MXC_ESDHC2_CLK, 535e32028a7SNikita Kiryanov MXC_ESDHC3_CLK, 536e32028a7SNikita Kiryanov }; 537e32028a7SNikita Kiryanov 538e32028a7SNikita Kiryanov int board_mmc_init(bd_t *bis) 539e32028a7SNikita Kiryanov { 540e32028a7SNikita Kiryanov int i; 541e32028a7SNikita Kiryanov 542e32028a7SNikita Kiryanov cm_fx6_set_usdhc_iomux(); 543e32028a7SNikita Kiryanov for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { 544e32028a7SNikita Kiryanov usdhc_cfg[i].sdhc_clk = mxc_get_clock(usdhc_clk[i]); 545e32028a7SNikita Kiryanov usdhc_cfg[i].max_bus_width = 4; 546e32028a7SNikita Kiryanov fsl_esdhc_initialize(bis, &usdhc_cfg[i]); 547e32028a7SNikita Kiryanov enable_usdhc_clk(1, i); 548e32028a7SNikita Kiryanov } 549e32028a7SNikita Kiryanov 550e32028a7SNikita Kiryanov return 0; 551e32028a7SNikita Kiryanov } 552e32028a7SNikita Kiryanov #endif 553e32028a7SNikita Kiryanov 5548f488c1bSNikita Kiryanov #ifdef CONFIG_MXC_SPI 5558f488c1bSNikita Kiryanov int cm_fx6_setup_ecspi(void) 5568f488c1bSNikita Kiryanov { 5578f488c1bSNikita Kiryanov cm_fx6_set_ecspi_iomux(); 5588f488c1bSNikita Kiryanov return gpio_request(CM_FX6_ECSPI_BUS0_CS0, "ecspi_bus0_cs0"); 5598f488c1bSNikita Kiryanov } 5608f488c1bSNikita Kiryanov #else 5618f488c1bSNikita Kiryanov int cm_fx6_setup_ecspi(void) { return 0; } 5628f488c1bSNikita Kiryanov #endif 5638f488c1bSNikita Kiryanov 56402b1343eSNikita Kiryanov #ifdef CONFIG_OF_BOARD_SETUP 56541855186SNikita Kiryanov #define USDHC3_PATH "/soc/aips-bus@02100000/usdhc@02198000/" 566e895a4b0SSimon Glass int ft_board_setup(void *blob, bd_t *bd) 56702b1343eSNikita Kiryanov { 56841855186SNikita Kiryanov u32 baseboard_rev; 56941855186SNikita Kiryanov int nodeoffset; 57002b1343eSNikita Kiryanov uint8_t enetaddr[6]; 57141855186SNikita Kiryanov char baseboard_name[16]; 57241855186SNikita Kiryanov int err; 57302b1343eSNikita Kiryanov 57402b1343eSNikita Kiryanov /* MAC addr */ 57502b1343eSNikita Kiryanov if (eth_getenv_enetaddr("ethaddr", enetaddr)) { 576cc67f4a6SNikita Kiryanov fdt_find_and_setprop(blob, 577cc67f4a6SNikita Kiryanov "/soc/aips-bus@02100000/ethernet@02188000", 578cc67f4a6SNikita Kiryanov "local-mac-address", enetaddr, 6, 1); 57902b1343eSNikita Kiryanov } 580e895a4b0SSimon Glass 581eab29802SNikita Kiryanov if (eth_getenv_enetaddr("eth1addr", enetaddr)) { 582eab29802SNikita Kiryanov fdt_find_and_setprop(blob, "/eth@pcie", "local-mac-address", 583eab29802SNikita Kiryanov enetaddr, 6, 1); 584eab29802SNikita Kiryanov } 585eab29802SNikita Kiryanov 58641855186SNikita Kiryanov baseboard_rev = cl_eeprom_get_board_rev(0); 58741855186SNikita Kiryanov err = cl_eeprom_get_product_name((uchar *)baseboard_name, 0); 58841855186SNikita Kiryanov if (err || baseboard_rev == 0) 58941855186SNikita Kiryanov return 0; /* Assume not an early revision SB-FX6m baseboard */ 59041855186SNikita Kiryanov 59141855186SNikita Kiryanov if (!strncmp("SB-FX6m", baseboard_name, 7) && baseboard_rev <= 120) { 59241855186SNikita Kiryanov fdt_shrink_to_minimum(blob); /* Make room for new properties */ 59341855186SNikita Kiryanov nodeoffset = fdt_path_offset(blob, USDHC3_PATH); 59441855186SNikita Kiryanov fdt_delprop(blob, nodeoffset, "cd-gpios"); 59541855186SNikita Kiryanov fdt_find_and_setprop(blob, USDHC3_PATH, "non-removable", 59641855186SNikita Kiryanov NULL, 0, 1); 59741855186SNikita Kiryanov fdt_find_and_setprop(blob, USDHC3_PATH, "keep-power-in-suspend", 59841855186SNikita Kiryanov NULL, 0, 1); 59941855186SNikita Kiryanov } 60041855186SNikita Kiryanov 601e895a4b0SSimon Glass return 0; 60202b1343eSNikita Kiryanov } 60302b1343eSNikita Kiryanov #endif 60402b1343eSNikita Kiryanov 605e32028a7SNikita Kiryanov int board_init(void) 606e32028a7SNikita Kiryanov { 607edbf8b4fSSimon Glass int ret; 608edbf8b4fSSimon Glass 609e32028a7SNikita Kiryanov gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; 610a6b0652bSNikita Kiryanov cm_fx6_setup_gpmi_nand(); 611edbf8b4fSSimon Glass 6128f488c1bSNikita Kiryanov ret = cm_fx6_setup_ecspi(); 6138f488c1bSNikita Kiryanov if (ret) 6148f488c1bSNikita Kiryanov printf("Warning: ECSPI setup failed: %d\n", ret); 6158f488c1bSNikita Kiryanov 6168f488c1bSNikita Kiryanov ret = cm_fx6_setup_usb_otg(); 6178f488c1bSNikita Kiryanov if (ret) 6188f488c1bSNikita Kiryanov printf("Warning: USB OTG setup failed: %d\n", ret); 6198f488c1bSNikita Kiryanov 6208f488c1bSNikita Kiryanov ret = cm_fx6_setup_usb_host(); 6218f488c1bSNikita Kiryanov if (ret) 6228f488c1bSNikita Kiryanov printf("Warning: USB host setup failed: %d\n", ret); 6238f488c1bSNikita Kiryanov 6248f488c1bSNikita Kiryanov /* 6258f488c1bSNikita Kiryanov * cm-fx6 may have iSSD not assembled and in this case it has 6268f488c1bSNikita Kiryanov * bypasses for a (m)SATA socket on the baseboard. The socketed 6278f488c1bSNikita Kiryanov * device is not controlled by those GPIOs. So just print a warning 6288f488c1bSNikita Kiryanov * if the setup fails. 6298f488c1bSNikita Kiryanov */ 6308f488c1bSNikita Kiryanov ret = cm_fx6_setup_issd(); 6318f488c1bSNikita Kiryanov if (ret) 6328f488c1bSNikita Kiryanov printf("Warning: iSSD setup failed: %d\n", ret); 6338f488c1bSNikita Kiryanov 634edbf8b4fSSimon Glass /* Warn on failure but do not abort boot */ 635edbf8b4fSSimon Glass ret = cm_fx6_setup_i2c(); 636edbf8b4fSSimon Glass if (ret) 637edbf8b4fSSimon Glass printf("Warning: I2C setup failed: %d\n", ret); 638a6b0652bSNikita Kiryanov 639deb94d61SNikita Kiryanov cm_fx6_setup_display(); 640deb94d61SNikita Kiryanov 641e32028a7SNikita Kiryanov return 0; 642e32028a7SNikita Kiryanov } 643e32028a7SNikita Kiryanov 644e32028a7SNikita Kiryanov int checkboard(void) 645e32028a7SNikita Kiryanov { 646e32028a7SNikita Kiryanov puts("Board: CM-FX6\n"); 647e32028a7SNikita Kiryanov return 0; 648e32028a7SNikita Kiryanov } 649e32028a7SNikita Kiryanov 6507d1abb7dSNikita Kiryanov int misc_init_r(void) 6517d1abb7dSNikita Kiryanov { 6527d1abb7dSNikita Kiryanov cl_print_pcb_info(); 6537d1abb7dSNikita Kiryanov 6547d1abb7dSNikita Kiryanov return 0; 6557d1abb7dSNikita Kiryanov } 6567d1abb7dSNikita Kiryanov 657e32028a7SNikita Kiryanov void dram_init_banksize(void) 658e32028a7SNikita Kiryanov { 659e32028a7SNikita Kiryanov gd->bd->bi_dram[0].start = PHYS_SDRAM_1; 660e32028a7SNikita Kiryanov gd->bd->bi_dram[1].start = PHYS_SDRAM_2; 661e32028a7SNikita Kiryanov 662e32028a7SNikita Kiryanov switch (gd->ram_size) { 663e32028a7SNikita Kiryanov case 0x10000000: /* DDR_16BIT_256MB */ 664e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x10000000; 665e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0; 666e32028a7SNikita Kiryanov break; 667e32028a7SNikita Kiryanov case 0x20000000: /* DDR_32BIT_512MB */ 668e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x20000000; 669e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0; 670e32028a7SNikita Kiryanov break; 671e32028a7SNikita Kiryanov case 0x40000000: 672e32028a7SNikita Kiryanov if (is_cpu_type(MXC_CPU_MX6SOLO)) { /* DDR_32BIT_1GB */ 673e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x20000000; 674e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0x20000000; 675e32028a7SNikita Kiryanov } else { /* DDR_64BIT_1GB */ 676e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x40000000; 677e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0; 678e32028a7SNikita Kiryanov } 679e32028a7SNikita Kiryanov break; 680e32028a7SNikita Kiryanov case 0x80000000: /* DDR_64BIT_2GB */ 681e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x40000000; 682e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0x40000000; 683e32028a7SNikita Kiryanov break; 684e32028a7SNikita Kiryanov case 0xEFF00000: /* DDR_64BIT_4GB */ 685e32028a7SNikita Kiryanov gd->bd->bi_dram[0].size = 0x70000000; 686e32028a7SNikita Kiryanov gd->bd->bi_dram[1].size = 0x7FF00000; 687e32028a7SNikita Kiryanov break; 688e32028a7SNikita Kiryanov } 689e32028a7SNikita Kiryanov } 690e32028a7SNikita Kiryanov 691e32028a7SNikita Kiryanov int dram_init(void) 692e32028a7SNikita Kiryanov { 693e32028a7SNikita Kiryanov gd->ram_size = imx_ddr_size(); 694e32028a7SNikita Kiryanov switch (gd->ram_size) { 695e32028a7SNikita Kiryanov case 0x10000000: 696e32028a7SNikita Kiryanov case 0x20000000: 697e32028a7SNikita Kiryanov case 0x40000000: 698e32028a7SNikita Kiryanov case 0x80000000: 699e32028a7SNikita Kiryanov break; 700e32028a7SNikita Kiryanov case 0xF0000000: 701e32028a7SNikita Kiryanov gd->ram_size -= 0x100000; 702e32028a7SNikita Kiryanov break; 703e32028a7SNikita Kiryanov default: 704e32028a7SNikita Kiryanov printf("ERROR: Unsupported DRAM size 0x%lx\n", gd->ram_size); 705e32028a7SNikita Kiryanov return -1; 706e32028a7SNikita Kiryanov } 707e32028a7SNikita Kiryanov 708e32028a7SNikita Kiryanov return 0; 709e32028a7SNikita Kiryanov } 710f66113c0SNikita Kiryanov 711f66113c0SNikita Kiryanov u32 get_board_rev(void) 712f66113c0SNikita Kiryanov { 71372898ac7SNikita Kiryanov return cl_eeprom_get_board_rev(CONFIG_SYS_I2C_EEPROM_BUS); 714f66113c0SNikita Kiryanov } 715f66113c0SNikita Kiryanov 7163f0e935fSSimon Glass static struct mxc_serial_platdata cm_fx6_mxc_serial_plat = { 7173f0e935fSSimon Glass .reg = (struct mxc_uart *)UART4_BASE, 7183f0e935fSSimon Glass }; 7193f0e935fSSimon Glass 7203f0e935fSSimon Glass U_BOOT_DEVICE(cm_fx6_serial) = { 7213f0e935fSSimon Glass .name = "serial_mxc", 7223f0e935fSSimon Glass .platdata = &cm_fx6_mxc_serial_plat, 7233f0e935fSSimon Glass }; 724