uboot/board/toradex/colibri_imx7/colibri_imx7.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2016 Toradex AG
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <asm/arch/clock.h>
   8#include <asm/arch/crm_regs.h>
   9#include <asm/arch/imx-regs.h>
  10#include <asm/arch/mx7-pins.h>
  11#include <asm/arch/sys_proto.h>
  12#include <asm/gpio.h>
  13#include <asm/mach-imx/boot_mode.h>
  14#include <asm/mach-imx/iomux-v3.h>
  15#include <asm/io.h>
  16#include <common.h>
  17#include <dm.h>
  18#include <dm/platform_data/serial_mxc.h>
  19#include <fdt_support.h>
  20#include <fsl_esdhc.h>
  21#include <jffs2/load_kernel.h>
  22#include <linux/sizes.h>
  23#include <mmc.h>
  24#include <miiphy.h>
  25#include <mtd_node.h>
  26#include <netdev.h>
  27#include <power/pmic.h>
  28#include <power/rn5t567_pmic.h>
  29#include <usb.h>
  30#include <usb/ehci-ci.h>
  31#include "../common/tdx-common.h"
  32
  33DECLARE_GLOBAL_DATA_PTR;
  34
  35#define UART_PAD_CTRL  (PAD_CTL_DSE_3P3V_49OHM | \
  36        PAD_CTL_PUS_PU100KOHM | PAD_CTL_HYS)
  37
  38#define USDHC_PAD_CTRL (PAD_CTL_DSE_3P3V_32OHM | PAD_CTL_SRE_SLOW | \
  39        PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PUS_PU47KOHM)
  40
  41#define ENET_PAD_CTRL  (PAD_CTL_PUS_PU100KOHM | PAD_CTL_DSE_3P3V_49OHM)
  42#define ENET_PAD_CTRL_MII  (PAD_CTL_DSE_3P3V_32OHM)
  43
  44#define ENET_RX_PAD_CTRL  (PAD_CTL_PUS_PU100KOHM | PAD_CTL_DSE_3P3V_49OHM)
  45
  46#define LCD_PAD_CTRL    (PAD_CTL_HYS | PAD_CTL_PUS_PU100KOHM | \
  47        PAD_CTL_DSE_3P3V_49OHM)
  48
  49#define NAND_PAD_CTRL (PAD_CTL_DSE_3P3V_49OHM | PAD_CTL_SRE_SLOW | PAD_CTL_HYS)
  50
  51#define NAND_PAD_READY0_CTRL (PAD_CTL_DSE_3P3V_49OHM | PAD_CTL_PUS_PU5KOHM)
  52
  53#define USB_CDET_GPIO   IMX_GPIO_NR(7, 14)
  54
  55int dram_init(void)
  56{
  57        gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
  58
  59        return 0;
  60}
  61
  62static iomux_v3_cfg_t const uart1_pads[] = {
  63        MX7D_PAD_UART1_RX_DATA__UART1_DTE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
  64        MX7D_PAD_UART1_TX_DATA__UART1_DTE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
  65        MX7D_PAD_SAI2_TX_BCLK__UART1_DTE_CTS | MUX_PAD_CTRL(UART_PAD_CTRL),
  66        MX7D_PAD_SAI2_TX_SYNC__UART1_DTE_RTS | MUX_PAD_CTRL(UART_PAD_CTRL),
  67};
  68
  69static iomux_v3_cfg_t const usdhc1_pads[] = {
  70        MX7D_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  71        MX7D_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  72        MX7D_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  73        MX7D_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  74        MX7D_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  75        MX7D_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  76
  77        MX7D_PAD_GPIO1_IO00__GPIO1_IO0 | MUX_PAD_CTRL(NO_PAD_CTRL),
  78};
  79
  80#ifdef CONFIG_USB_EHCI_MX7
  81static iomux_v3_cfg_t const usb_cdet_pads[] = {
  82        MX7D_PAD_ENET1_CRS__GPIO7_IO14 | MUX_PAD_CTRL(NO_PAD_CTRL),
  83};
  84#endif
  85
  86#ifdef CONFIG_NAND_MXS
  87static iomux_v3_cfg_t const gpmi_pads[] = {
  88        MX7D_PAD_SD3_DATA0__NAND_DATA00 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  89        MX7D_PAD_SD3_DATA1__NAND_DATA01 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  90        MX7D_PAD_SD3_DATA2__NAND_DATA02 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  91        MX7D_PAD_SD3_DATA3__NAND_DATA03 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  92        MX7D_PAD_SD3_DATA4__NAND_DATA04 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  93        MX7D_PAD_SD3_DATA5__NAND_DATA05 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  94        MX7D_PAD_SD3_DATA6__NAND_DATA06 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  95        MX7D_PAD_SD3_DATA7__NAND_DATA07 | MUX_PAD_CTRL(NAND_PAD_CTRL),
  96        MX7D_PAD_SD3_CLK__NAND_CLE      | MUX_PAD_CTRL(NAND_PAD_CTRL),
  97        MX7D_PAD_SD3_CMD__NAND_ALE      | MUX_PAD_CTRL(NAND_PAD_CTRL),
  98        MX7D_PAD_SD3_STROBE__NAND_RE_B  | MUX_PAD_CTRL(NAND_PAD_CTRL),
  99        MX7D_PAD_SD3_RESET_B__NAND_WE_B | MUX_PAD_CTRL(NAND_PAD_CTRL),
 100        MX7D_PAD_SAI1_RX_DATA__NAND_CE1_B       | MUX_PAD_CTRL(NAND_PAD_CTRL),
 101        MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B       | MUX_PAD_CTRL(NAND_PAD_CTRL),
 102        MX7D_PAD_SAI1_TX_DATA__NAND_READY_B     | MUX_PAD_CTRL(NAND_PAD_READY0_CTRL),
 103};
 104
 105static void setup_gpmi_nand(void)
 106{
 107        imx_iomux_v3_setup_multiple_pads(gpmi_pads, ARRAY_SIZE(gpmi_pads));
 108
 109        /* NAND_USDHC_BUS_CLK is set in rom */
 110        set_clk_nand();
 111}
 112#endif
 113
 114#ifdef CONFIG_VIDEO_MXS
 115static iomux_v3_cfg_t const lcd_pads[] = {
 116        MX7D_PAD_LCD_CLK__LCD_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
 117        MX7D_PAD_LCD_ENABLE__LCD_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
 118        MX7D_PAD_LCD_HSYNC__LCD_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
 119        MX7D_PAD_LCD_VSYNC__LCD_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
 120        MX7D_PAD_LCD_DATA00__LCD_DATA0 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 121        MX7D_PAD_LCD_DATA01__LCD_DATA1 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 122        MX7D_PAD_LCD_DATA02__LCD_DATA2 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 123        MX7D_PAD_LCD_DATA03__LCD_DATA3 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 124        MX7D_PAD_LCD_DATA04__LCD_DATA4 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 125        MX7D_PAD_LCD_DATA05__LCD_DATA5 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 126        MX7D_PAD_LCD_DATA06__LCD_DATA6 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 127        MX7D_PAD_LCD_DATA07__LCD_DATA7 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 128        MX7D_PAD_LCD_DATA08__LCD_DATA8 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 129        MX7D_PAD_LCD_DATA09__LCD_DATA9 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 130        MX7D_PAD_LCD_DATA10__LCD_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 131        MX7D_PAD_LCD_DATA11__LCD_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 132        MX7D_PAD_LCD_DATA12__LCD_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 133        MX7D_PAD_LCD_DATA13__LCD_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 134        MX7D_PAD_LCD_DATA14__LCD_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 135        MX7D_PAD_LCD_DATA15__LCD_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 136        MX7D_PAD_LCD_DATA16__LCD_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 137        MX7D_PAD_LCD_DATA17__LCD_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
 138};
 139
 140static iomux_v3_cfg_t const backlight_pads[] = {
 141        /* Backlight On */
 142        MX7D_PAD_SD1_WP__GPIO5_IO1 | MUX_PAD_CTRL(NO_PAD_CTRL),
 143        /* Backlight PWM<A> (multiplexed pin) */
 144        MX7D_PAD_GPIO1_IO08__GPIO1_IO8   | MUX_PAD_CTRL(NO_PAD_CTRL),
 145        MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 | MUX_PAD_CTRL(NO_PAD_CTRL),
 146};
 147
 148#define GPIO_BL_ON IMX_GPIO_NR(5, 1)
 149#define GPIO_PWM_A IMX_GPIO_NR(1, 8)
 150
 151static int setup_lcd(void)
 152{
 153        imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
 154
 155        imx_iomux_v3_setup_multiple_pads(backlight_pads, ARRAY_SIZE(backlight_pads));
 156
 157        /* Set BL_ON */
 158        gpio_request(GPIO_BL_ON, "BL_ON");
 159        gpio_direction_output(GPIO_BL_ON, 1);
 160
 161        /* Set PWM<A> to full brightness (assuming inversed polarity) */
 162        gpio_request(GPIO_PWM_A, "PWM<A>");
 163        gpio_direction_output(GPIO_PWM_A, 0);
 164
 165        return 0;
 166}
 167#endif
 168
 169#ifdef CONFIG_FEC_MXC
 170static iomux_v3_cfg_t const fec1_pads[] = {
 171#ifndef CONFIG_COLIBRI_IMX7_EXT_PHYCLK
 172        MX7D_PAD_GPIO1_IO12__CCM_ENET_REF_CLK1 | MUX_PAD_CTRL(ENET_PAD_CTRL) | MUX_MODE_SION,
 173#else
 174        MX7D_PAD_GPIO1_IO12__CCM_ENET_REF_CLK1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 175#endif
 176        MX7D_PAD_SD2_CD_B__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
 177        MX7D_PAD_SD2_WP__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
 178        MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
 179        MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
 180        MX7D_PAD_ENET1_RGMII_RXC__ENET1_RX_ER | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
 181        MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL   | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
 182        MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 183        MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 184        MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
 185};
 186
 187static void setup_iomux_fec(void)
 188{
 189        imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
 190}
 191#endif
 192
 193static void setup_iomux_uart(void)
 194{
 195        imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
 196}
 197
 198#ifdef CONFIG_FSL_ESDHC
 199
 200#define USDHC1_CD_GPIO  IMX_GPIO_NR(1, 0)
 201
 202static struct fsl_esdhc_cfg usdhc_cfg[] = {
 203        {USDHC1_BASE_ADDR, 0, 4},
 204};
 205
 206int board_mmc_getcd(struct mmc *mmc)
 207{
 208        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 209        int ret = 0;
 210
 211        switch (cfg->esdhc_base) {
 212        case USDHC1_BASE_ADDR:
 213                ret = !gpio_get_value(USDHC1_CD_GPIO);
 214                break;
 215        }
 216
 217        return ret;
 218}
 219
 220int board_mmc_init(bd_t *bis)
 221{
 222        int i, ret;
 223        /* USDHC1 is mmc0 */
 224        for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
 225                switch (i) {
 226                case 0:
 227                        imx_iomux_v3_setup_multiple_pads(
 228                                usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
 229                        gpio_request(USDHC1_CD_GPIO, "usdhc1_cd");
 230                        gpio_direction_input(USDHC1_CD_GPIO);
 231                        usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
 232                        break;
 233                default:
 234                        printf("Warning: you configured more USDHC controllers"
 235                                "(%d) than supported by the board\n", i + 1);
 236                        return -EINVAL;
 237                }
 238
 239                ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
 240                if (ret)
 241                        return ret;
 242        }
 243
 244        return 0;
 245}
 246#endif
 247
 248#ifdef CONFIG_FEC_MXC
 249int board_eth_init(bd_t *bis)
 250{
 251        int ret;
 252
 253        setup_iomux_fec();
 254
 255        ret = fecmxc_initialize_multi(bis, 0,
 256                CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
 257        if (ret)
 258                printf("FEC1 MXC: %s:failed\n", __func__);
 259
 260        return ret;
 261}
 262
 263static int setup_fec(void)
 264{
 265        struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs
 266                = (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
 267
 268#ifndef CONFIG_COLIBRI_IMX7_EXT_PHYCLK
 269        /*
 270         * Use 50M anatop REF_CLK1 for ENET1, clear gpr1[13], set gpr1[17]
 271         * and output it on the pin
 272         */
 273        clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
 274                        IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK,
 275                        IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK);
 276#else
 277        /* Use 50M external CLK for ENET1, set gpr1[13], clear gpr1[17] */
 278        clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
 279                        IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK,
 280                        IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK);
 281#endif
 282
 283        return set_clk_enet(ENET_50MHZ);
 284}
 285
 286int board_phy_config(struct phy_device *phydev)
 287{
 288        if (phydev->drv->config)
 289                phydev->drv->config(phydev);
 290        return 0;
 291}
 292#endif
 293
 294int board_early_init_f(void)
 295{
 296        setup_iomux_uart();
 297
 298        return 0;
 299}
 300
 301int board_init(void)
 302{
 303        /* address of boot parameters */
 304        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 305
 306#ifdef CONFIG_FEC_MXC
 307        setup_fec();
 308#endif
 309
 310#ifdef CONFIG_NAND_MXS
 311        setup_gpmi_nand();
 312#endif
 313
 314#ifdef CONFIG_VIDEO_MXS
 315        setup_lcd();
 316#endif
 317
 318#ifdef CONFIG_USB_EHCI_MX7
 319        imx_iomux_v3_setup_multiple_pads(usb_cdet_pads, ARRAY_SIZE(usb_cdet_pads));
 320        gpio_request(USB_CDET_GPIO, "usb-cdet-gpio");
 321#endif
 322
 323        return 0;
 324}
 325
 326#ifdef CONFIG_CMD_BMODE
 327static const struct boot_mode board_boot_modes[] = {
 328        /* 4 bit bus width */
 329        {"nand", MAKE_CFGVAL(0x40, 0x34, 0x00, 0x00)},
 330        {"sd1", MAKE_CFGVAL(0x10, 0x10, 0x00, 0x00)},
 331        {NULL, 0},
 332};
 333#endif
 334
 335int board_late_init(void)
 336{
 337#ifdef CONFIG_CMD_BMODE
 338        add_board_boot_modes(board_boot_modes);
 339#endif
 340
 341        return 0;
 342}
 343
 344#ifdef CONFIG_DM_PMIC
 345int power_init_board(void)
 346{
 347        struct udevice *dev;
 348        int reg, ver;
 349        int ret;
 350
 351
 352        ret = pmic_get("rn5t567", &dev);
 353        if (ret)
 354                return ret;
 355        ver = pmic_reg_read(dev, RN5T567_LSIVER);
 356        reg = pmic_reg_read(dev, RN5T567_OTPVER);
 357
 358        printf("PMIC:  RN5T567 LSIVER=0x%02x OTPVER=0x%02x\n", ver, reg);
 359
 360        /* set judge and press timer of N_OE to minimal values */
 361        pmic_clrsetbits(dev, RN5T567_NOETIMSETCNT, 0x7, 0);
 362
 363        /* configure sleep slot for 3.3V Ethernet */
 364        reg = pmic_reg_read(dev, RN5T567_LDO1_SLOT);
 365        reg = (reg & 0xf0) | reg >> 4;
 366        pmic_reg_write(dev, RN5T567_LDO1_SLOT, reg);
 367
 368        /* disable DCDC2 discharge to avoid backfeeding through VFB2 */
 369        pmic_clrsetbits(dev, RN5T567_DC2CTL, 0x2, 0);
 370
 371        /* configure sleep slot for ARM rail */
 372        reg = pmic_reg_read(dev, RN5T567_DC2_SLOT);
 373        reg = (reg & 0xf0) | reg >> 4;
 374        pmic_reg_write(dev, RN5T567_DC2_SLOT, reg);
 375
 376        /* disable LDO2 discharge to avoid backfeeding from +V3.3_SD */
 377        pmic_clrsetbits(dev, RN5T567_LDODIS1, 0x2, 0);
 378
 379        return 0;
 380}
 381
 382void reset_cpu(ulong addr)
 383{
 384        struct udevice *dev;
 385
 386        pmic_get("rn5t567", &dev);
 387
 388        /* Use PMIC to reset, set REPWRTIM to 0 and REPWRON to 1 */
 389        pmic_reg_write(dev, RN5T567_REPCNT, 0x1);
 390        pmic_reg_write(dev, RN5T567_SLPCNT, 0x1);
 391
 392        /*
 393         * Re-power factor detection on PMIC side is not instant. 1ms
 394         * proved to be enough time until reset takes effect.
 395         */
 396        mdelay(1);
 397}
 398#endif
 399
 400int checkboard(void)
 401{
 402        printf("Model: Toradex Colibri iMX7%c\n",
 403               is_cpu_type(MXC_CPU_MX7D) ? 'D' : 'S');
 404
 405        return 0;
 406}
 407
 408#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 409int ft_board_setup(void *blob, bd_t *bd)
 410{
 411#if defined(CONFIG_FDT_FIXUP_PARTITIONS)
 412        static struct node_info nodes[] = {
 413                { "fsl,imx7d-gpmi-nand", MTD_DEV_TYPE_NAND, }, /* NAND flash */
 414        };
 415
 416        /* Update partition nodes using info from mtdparts env var */
 417        puts("   Updating MTD partitions...\n");
 418        fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
 419#endif
 420
 421        return ft_common_board_setup(blob, bd);
 422}
 423#endif
 424
 425#ifdef CONFIG_USB_EHCI_MX7
 426static iomux_v3_cfg_t const usb_otg2_pads[] = {
 427        MX7D_PAD_UART3_CTS_B__USB_OTG2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
 428};
 429
 430int board_ehci_hcd_init(int port)
 431{
 432        switch (port) {
 433        case 0:
 434                break;
 435        case 1:
 436                if (is_cpu_type(MXC_CPU_MX7S))
 437                        return -ENODEV;
 438
 439                imx_iomux_v3_setup_multiple_pads(usb_otg2_pads,
 440                                                 ARRAY_SIZE(usb_otg2_pads));
 441                break;
 442        default:
 443                return -EINVAL;
 444        }
 445        return 0;
 446}
 447
 448int board_usb_phy_mode(int port)
 449{
 450        switch (port) {
 451        case 0:
 452                if (gpio_get_value(USB_CDET_GPIO))
 453                        return USB_INIT_DEVICE;
 454                else
 455                        return USB_INIT_HOST;
 456        case 1:
 457        default:
 458                return USB_INIT_HOST;
 459        }
 460}
 461#endif
 462