uboot/board/dhelectronics/dh_imx6/dh_imx6.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * DHCOM DH-iMX6 PDK board support
   4 *
   5 * Copyright (C) 2017 Marek Vasut <marex@denx.de>
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <dm/device-internal.h>
  11#include <asm/arch/clock.h>
  12#include <asm/arch/crm_regs.h>
  13#include <asm/arch/imx-regs.h>
  14#include <asm/arch/iomux.h>
  15#include <asm/arch/mx6-pins.h>
  16#include <asm/arch/sys_proto.h>
  17#include <asm/gpio.h>
  18#include <asm/io.h>
  19#include <asm/mach-imx/boot_mode.h>
  20#include <asm/mach-imx/iomux-v3.h>
  21#include <asm/mach-imx/mxc_i2c.h>
  22#include <asm/mach-imx/sata.h>
  23#include <ahci.h>
  24#include <dwc_ahsata.h>
  25#include <environment.h>
  26#include <errno.h>
  27#include <fsl_esdhc.h>
  28#include <fuse.h>
  29#include <i2c.h>
  30#include <miiphy.h>
  31#include <mmc.h>
  32#include <net.h>
  33#include <netdev.h>
  34#include <usb.h>
  35#include <usb/ehci-ci.h>
  36
  37DECLARE_GLOBAL_DATA_PTR;
  38
  39#define I2C_PAD_CTRL                                                    \
  40        (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |  \
  41        PAD_CTL_HYS | PAD_CTL_ODE | PAD_CTL_SRE_FAST)
  42
  43#define EEPROM_I2C_ADDRESS      0x50
  44
  45#define PC                      MUX_PAD_CTRL(I2C_PAD_CTRL)
  46
  47static struct i2c_pads_info dh6sdl_i2c_pad_info0 = {
  48        .scl = {
  49                .i2c_mode  = MX6DL_PAD_EIM_D21__I2C1_SCL | PC,
  50                .gpio_mode = MX6DL_PAD_EIM_D21__GPIO3_IO21 | PC,
  51                .gp = IMX_GPIO_NR(3, 21)
  52        },
  53        .sda = {
  54                 .i2c_mode = MX6DL_PAD_EIM_D28__I2C1_SDA | PC,
  55                 .gpio_mode = MX6DL_PAD_EIM_D28__GPIO3_IO28 | PC,
  56                 .gp = IMX_GPIO_NR(3, 28)
  57         }
  58};
  59
  60static struct i2c_pads_info dh6sdl_i2c_pad_info1 = {
  61        .scl = {
  62                .i2c_mode  = MX6DL_PAD_KEY_COL3__I2C2_SCL | PC,
  63                .gpio_mode = MX6DL_PAD_KEY_COL3__GPIO4_IO12 | PC,
  64                .gp = IMX_GPIO_NR(4, 12)
  65        },
  66        .sda = {
  67                 .i2c_mode = MX6DL_PAD_KEY_ROW3__I2C2_SDA | PC,
  68                 .gpio_mode = MX6DL_PAD_KEY_ROW3__GPIO4_IO13 | PC,
  69                 .gp = IMX_GPIO_NR(4, 13)
  70         }
  71};
  72
  73static struct i2c_pads_info dh6sdl_i2c_pad_info2 = {
  74        .scl = {
  75                .i2c_mode  = MX6DL_PAD_GPIO_3__I2C3_SCL | PC,
  76                .gpio_mode = MX6DL_PAD_GPIO_3__GPIO1_IO03 | PC,
  77                .gp = IMX_GPIO_NR(1, 3)
  78        },
  79        .sda = {
  80                 .i2c_mode = MX6DL_PAD_GPIO_6__I2C3_SDA | PC,
  81                 .gpio_mode = MX6DL_PAD_GPIO_6__GPIO1_IO06 | PC,
  82                 .gp = IMX_GPIO_NR(1, 6)
  83         }
  84};
  85
  86static struct i2c_pads_info dh6dq_i2c_pad_info0 = {
  87        .scl = {
  88                .i2c_mode  = MX6Q_PAD_EIM_D21__I2C1_SCL | PC,
  89                .gpio_mode = MX6Q_PAD_EIM_D21__GPIO3_IO21 | PC,
  90                .gp = IMX_GPIO_NR(3, 21)
  91        },
  92        .sda = {
  93                 .i2c_mode = MX6Q_PAD_EIM_D28__I2C1_SDA | PC,
  94                 .gpio_mode = MX6Q_PAD_EIM_D28__GPIO3_IO28 | PC,
  95                 .gp = IMX_GPIO_NR(3, 28)
  96         }
  97};
  98
  99static struct i2c_pads_info dh6dq_i2c_pad_info1 = {
 100        .scl = {
 101                .i2c_mode  = MX6Q_PAD_KEY_COL3__I2C2_SCL | PC,
 102                .gpio_mode = MX6Q_PAD_KEY_COL3__GPIO4_IO12 | PC,
 103                .gp = IMX_GPIO_NR(4, 12)
 104        },
 105        .sda = {
 106                 .i2c_mode = MX6Q_PAD_KEY_ROW3__I2C2_SDA | PC,
 107                 .gpio_mode = MX6Q_PAD_KEY_ROW3__GPIO4_IO13 | PC,
 108                 .gp = IMX_GPIO_NR(4, 13)
 109         }
 110};
 111
 112static struct i2c_pads_info dh6dq_i2c_pad_info2 = {
 113        .scl = {
 114                .i2c_mode  = MX6Q_PAD_GPIO_3__I2C3_SCL | PC,
 115                .gpio_mode = MX6Q_PAD_GPIO_3__GPIO1_IO03 | PC,
 116                .gp = IMX_GPIO_NR(1, 3)
 117        },
 118        .sda = {
 119                 .i2c_mode = MX6Q_PAD_GPIO_6__I2C3_SDA | PC,
 120                 .gpio_mode = MX6Q_PAD_GPIO_6__GPIO1_IO06 | PC,
 121                 .gp = IMX_GPIO_NR(1, 6)
 122         }
 123};
 124
 125int dram_init(void)
 126{
 127        gd->ram_size = imx_ddr_size();
 128        return 0;
 129}
 130
 131/*
 132 * Do not overwrite the console
 133 * Use always serial for U-Boot console
 134 */
 135int overwrite_console(void)
 136{
 137        return 1;
 138}
 139
 140#ifdef CONFIG_FEC_MXC
 141static void eth_phy_reset(void)
 142{
 143        /* Reset PHY */
 144        gpio_direction_output(IMX_GPIO_NR(5, 0) , 0);
 145        udelay(500);
 146        gpio_set_value(IMX_GPIO_NR(5, 0), 1);
 147
 148        /* Enable VIO */
 149        gpio_direction_output(IMX_GPIO_NR(1, 7) , 0);
 150
 151        /*
 152         * KSZ9021 PHY needs at least 10 mSec after PHY reset
 153         * is released to stabilize
 154         */
 155        mdelay(10);
 156}
 157
 158static int setup_fec_clock(void)
 159{
 160        struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
 161
 162        /* set gpr1[21] to select anatop clock */
 163        clrsetbits_le32(&iomuxc_regs->gpr[1], 0x1 << 21, 0x1 << 21);
 164
 165        return enable_fec_anatop_clock(0, ENET_50MHZ);
 166}
 167
 168int board_eth_init(bd_t *bis)
 169{
 170        uint32_t base = IMX_FEC_BASE;
 171        struct mii_dev *bus = NULL;
 172        struct phy_device *phydev = NULL;
 173
 174        gpio_request(IMX_GPIO_NR(5, 0), "PHY-reset");
 175        gpio_request(IMX_GPIO_NR(1, 7), "VIO");
 176
 177        setup_fec_clock();
 178
 179        eth_phy_reset();
 180
 181        bus = fec_get_miibus(base, -1);
 182        if (!bus)
 183                return -EINVAL;
 184
 185        /* Scan PHY 0 */
 186        phydev = phy_find_by_mask(bus, 0xf, PHY_INTERFACE_MODE_RGMII);
 187        if (!phydev) {
 188                printf("Ethernet PHY not found!\n");
 189                return -EINVAL;
 190        }
 191
 192        return fec_probe(bis, -1, base, bus, phydev);
 193}
 194#endif
 195
 196#ifdef CONFIG_USB_EHCI_MX6
 197static void setup_usb(void)
 198{
 199        gpio_request(IMX_GPIO_NR(3, 31), "USB-VBUS");
 200        /*
 201         * Set daisy chain for otg_pin_id on MX6Q.
 202         * For MX6DL, this bit is reserved.
 203         */
 204        imx_iomux_set_gpr_register(1, 13, 1, 0);
 205}
 206
 207int board_usb_phy_mode(int port)
 208{
 209        if (port == 1)
 210                return USB_INIT_HOST;
 211        else
 212                return USB_INIT_DEVICE;
 213}
 214
 215int board_ehci_power(int port, int on)
 216{
 217        switch (port) {
 218        case 0:
 219                break;
 220        case 1:
 221                gpio_direction_output(IMX_GPIO_NR(3, 31), !!on);
 222                break;
 223        default:
 224                printf("MXC USB port %d not yet supported\n", port);
 225                return -EINVAL;
 226        }
 227
 228        return 0;
 229}
 230#endif
 231
 232static int setup_dhcom_mac_from_fuse(void)
 233{
 234        unsigned char enetaddr[6];
 235        int ret;
 236
 237        ret = eth_env_get_enetaddr("ethaddr", enetaddr);
 238        if (ret)        /* ethaddr is already set */
 239                return 0;
 240
 241        imx_get_mac_from_fuse(0, enetaddr);
 242
 243        if (is_valid_ethaddr(enetaddr)) {
 244                eth_env_set_enetaddr("ethaddr", enetaddr);
 245                return 0;
 246        }
 247
 248        ret = i2c_set_bus_num(2);
 249        if (ret) {
 250                printf("Error switching I2C bus!\n");
 251                return ret;
 252        }
 253
 254        ret = i2c_read(EEPROM_I2C_ADDRESS, 0xfa, 0x1, enetaddr, 0x6);
 255        if (ret) {
 256                printf("Error reading configuration EEPROM!\n");
 257                return ret;
 258        }
 259
 260        if (is_valid_ethaddr(enetaddr))
 261                eth_env_set_enetaddr("ethaddr", enetaddr);
 262
 263        return 0;
 264}
 265
 266int board_early_init_f(void)
 267{
 268#ifdef CONFIG_USB_EHCI_MX6
 269        setup_usb();
 270#endif
 271
 272        return 0;
 273}
 274
 275int board_init(void)
 276{
 277        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 278
 279        /* address of boot parameters */
 280        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 281
 282        /* Enable eim_slow clocks */
 283        setbits_le32(&mxc_ccm->CCGR6, 0x1 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET);
 284
 285#ifdef CONFIG_SYS_I2C_MXC
 286        if (is_mx6dq()) {
 287                setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info0);
 288                setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info1);
 289                setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6dq_i2c_pad_info2);
 290        } else {
 291                setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info0);
 292                setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info1);
 293                setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &dh6sdl_i2c_pad_info2);
 294        }
 295#endif
 296
 297        setup_dhcom_mac_from_fuse();
 298
 299        return 0;
 300}
 301
 302#ifdef CONFIG_CMD_BMODE
 303static const struct boot_mode board_boot_modes[] = {
 304        /* 4 bit bus width */
 305        {"sd2",  MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
 306        {"sd3",  MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
 307        /* 8 bit bus width */
 308        {"emmc", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
 309        {NULL,   0},
 310};
 311#endif
 312
 313#define HW_CODE_BIT_0   IMX_GPIO_NR(2, 19)
 314#define HW_CODE_BIT_1   IMX_GPIO_NR(6, 6)
 315#define HW_CODE_BIT_2   IMX_GPIO_NR(2, 16)
 316
 317static int board_get_hwcode(void)
 318{
 319        int hw_code;
 320
 321        gpio_request(HW_CODE_BIT_0, "HW-code-bit-0");
 322        gpio_request(HW_CODE_BIT_1, "HW-code-bit-1");
 323        gpio_request(HW_CODE_BIT_2, "HW-code-bit-2");
 324
 325        gpio_direction_input(HW_CODE_BIT_0);
 326        gpio_direction_input(HW_CODE_BIT_1);
 327        gpio_direction_input(HW_CODE_BIT_2);
 328
 329        /* HW 100 + HW 200 = 00b; HW 300 = 01b */
 330        hw_code = ((gpio_get_value(HW_CODE_BIT_2) << 2) |
 331                   (gpio_get_value(HW_CODE_BIT_1) << 1) |
 332                    gpio_get_value(HW_CODE_BIT_0)) + 2;
 333
 334        return hw_code;
 335}
 336
 337int board_late_init(void)
 338{
 339        u32 hw_code;
 340        char buf[16];
 341
 342        hw_code = board_get_hwcode();
 343
 344        switch (get_cpu_type()) {
 345        case MXC_CPU_MX6SOLO:
 346                snprintf(buf, sizeof(buf), "imx6s-dhcom%1d", hw_code);
 347                break;
 348        case MXC_CPU_MX6DL:
 349                snprintf(buf, sizeof(buf), "imx6dl-dhcom%1d", hw_code);
 350                break;
 351        case MXC_CPU_MX6D:
 352                snprintf(buf, sizeof(buf), "imx6d-dhcom%1d", hw_code);
 353                break;
 354        case MXC_CPU_MX6Q:
 355                snprintf(buf, sizeof(buf), "imx6q-dhcom%1d", hw_code);
 356                break;
 357        default:
 358                snprintf(buf, sizeof(buf), "UNKNOWN%1d", hw_code);
 359                break;
 360        }
 361
 362        env_set("dhcom", buf);
 363
 364#ifdef CONFIG_CMD_BMODE
 365        add_board_boot_modes(board_boot_modes);
 366#endif
 367        return 0;
 368}
 369
 370int checkboard(void)
 371{
 372        puts("Board: DHCOM i.MX6\n");
 373        return 0;
 374}
 375