uboot/board/compulab/cl-som-imx7/cl-som-imx7.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * U-Boot board functions for CompuLab CL-SOM-iMX7 module
   4 *
   5 * (C) Copyright 2017 CompuLab, Ltd. http://www.compulab.com
   6 *
   7 * Author: Uri Mashiach <uri.mashiach@compulab.co.il>
   8 */
   9
  10#include <common.h>
  11#include <env.h>
  12#include <init.h>
  13#include <mmc.h>
  14#include <phy.h>
  15#include <netdev.h>
  16#include <fsl_esdhc_imx.h>
  17#include <power/pmic.h>
  18#include <power/pfuze3000_pmic.h>
  19#include <asm/mach-imx/mxc_i2c.h>
  20#include <asm/mach-imx/iomux-v3.h>
  21#include <asm/arch-mx7/mx7-pins.h>
  22#include <asm/arch-mx7/sys_proto.h>
  23#include <asm/arch-mx7/clock.h>
  24#include "../common/eeprom.h"
  25#include "common.h"
  26
  27DECLARE_GLOBAL_DATA_PTR;
  28
  29#ifdef CONFIG_SYS_I2C_MXC
  30
  31#define I2C_PAD_CTRL            (PAD_CTL_DSE_3P3V_32OHM | PAD_CTL_SRE_SLOW | \
  32                                PAD_CTL_HYS)
  33
  34#define CL_SOM_IMX7_GPIO_I2C2_SCL       IMX_GPIO_NR(1, 6)
  35#define CL_SOM_IMX7_GPIO_I2C2_SDA       IMX_GPIO_NR(1, 7)
  36
  37static struct i2c_pads_info cl_som_imx7_i2c_pad_info2 = {
  38        .scl = {
  39                .i2c_mode = MX7D_PAD_GPIO1_IO06__I2C2_SCL |
  40                        MUX_PAD_CTRL(I2C_PAD_CTRL),
  41                .gpio_mode = MX7D_PAD_GPIO1_IO06__GPIO1_IO6 |
  42                        MUX_PAD_CTRL(I2C_PAD_CTRL),
  43                .gp = CL_SOM_IMX7_GPIO_I2C2_SCL,
  44        },
  45        .sda = {
  46                .i2c_mode = MX7D_PAD_GPIO1_IO07__I2C2_SDA |
  47                        MUX_PAD_CTRL(I2C_PAD_CTRL),
  48                .gpio_mode = MX7D_PAD_GPIO1_IO07__GPIO1_IO7 |
  49                        MUX_PAD_CTRL(I2C_PAD_CTRL),
  50                .gp = CL_SOM_IMX7_GPIO_I2C2_SDA,
  51        },
  52};
  53
  54/*
  55 * cl_som_imx7_setup_i2c() - I2C  pinmux configuration.
  56 */
  57static void cl_som_imx7_setup_i2c(void)
  58{
  59        setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &cl_som_imx7_i2c_pad_info2);
  60}
  61#else /* !CONFIG_SYS_I2C_MXC */
  62static void cl_som_imx7_setup_i2c(void) {}
  63#endif /* CONFIG_SYS_I2C_MXC */
  64
  65int dram_init(void)
  66{
  67        gd->ram_size = imx_ddr_size();
  68
  69        return 0;
  70}
  71
  72#ifdef CONFIG_FSL_ESDHC_IMX
  73
  74#define CL_SOM_IMX7_GPIO_USDHC3_PWR     IMX_GPIO_NR(6, 11)
  75
  76static struct fsl_esdhc_cfg cl_som_imx7_usdhc_cfg[3] = {
  77        {USDHC1_BASE_ADDR, 0, 4},
  78        {USDHC3_BASE_ADDR},
  79};
  80
  81int board_mmc_init(bd_t *bis)
  82{
  83        int i, ret;
  84        /*
  85         * According to the board_mmc_init() the following map is done:
  86         * (U-boot device node)    (Physical Port)
  87         * mmc0                    USDHC1
  88         * mmc2                    USDHC3 (eMMC)
  89         */
  90        for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
  91                switch (i) {
  92                case 0:
  93                        cl_som_imx7_usdhc1_pads_set();
  94                        gpio_request(CL_SOM_IMX7_GPIO_USDHC1_CD, "usdhc1_cd");
  95                        cl_som_imx7_usdhc_cfg[0].sdhc_clk =
  96                                mxc_get_clock(MXC_ESDHC_CLK);
  97                        break;
  98                case 1:
  99                        cl_som_imx7_usdhc3_emmc_pads_set();
 100                        gpio_request(CL_SOM_IMX7_GPIO_USDHC3_PWR, "usdhc3_pwr");
 101                        gpio_direction_output(CL_SOM_IMX7_GPIO_USDHC3_PWR, 0);
 102                        udelay(500);
 103                        gpio_direction_output(CL_SOM_IMX7_GPIO_USDHC3_PWR, 1);
 104                        cl_som_imx7_usdhc_cfg[1].sdhc_clk =
 105                                mxc_get_clock(MXC_ESDHC3_CLK);
 106                        break;
 107                default:
 108                        printf("Warning: you configured more USDHC controllers "
 109                                "(%d) than supported by the board\n", i + 1);
 110                        return -EINVAL;
 111                }
 112
 113                ret = fsl_esdhc_initialize(bis, &cl_som_imx7_usdhc_cfg[i]);
 114                if (ret)
 115                        return ret;
 116        }
 117
 118        return 0;
 119}
 120#endif /* CONFIG_FSL_ESDHC_IMX */
 121
 122#ifdef CONFIG_FEC_MXC
 123
 124#define CL_SOM_IMX7_ETH1_PHY_NRST       IMX_GPIO_NR(1, 4)
 125
 126/*
 127 * cl_som_imx7_rgmii_rework() - Ethernet PHY configuration.
 128 */
 129static void cl_som_imx7_rgmii_rework(struct phy_device *phydev)
 130{
 131        unsigned short val;
 132
 133        /* Ar8031 phy SmartEEE feature cause link status generates glitch,
 134         * which cause ethernet link down/up issue, so disable SmartEEE
 135         */
 136        phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x3);
 137        phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x805d);
 138        phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4003);
 139        val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
 140        val &= ~(0x1 << 8);
 141        phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
 142
 143        /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
 144        phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
 145        phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
 146        phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
 147
 148        val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
 149        val &= 0xffe3;
 150        val |= 0x18;
 151        phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
 152
 153        /* introduce tx clock delay */
 154        phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
 155        val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
 156        val |= 0x0100;
 157        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
 158}
 159
 160int board_phy_config(struct phy_device *phydev)
 161{
 162        cl_som_imx7_rgmii_rework(phydev);
 163
 164        if (phydev->drv->config)
 165                phydev->drv->config(phydev);
 166
 167        return 0;
 168}
 169
 170/*
 171 * cl_som_imx7_handle_mac_address() - set Ethernet MAC address environment.
 172 *
 173 * @env_var: MAC address environment variable
 174 * @eeprom_bus: I2C bus of the environment EEPROM
 175 *
 176 * @return: 0 on success, < 0 on failure
 177 */
 178static int cl_som_imx7_handle_mac_address(char *env_var, uint eeprom_bus)
 179{
 180        int ret;
 181        unsigned char enetaddr[6];
 182
 183        ret = eth_env_get_enetaddr(env_var, enetaddr);
 184        if (ret)
 185                return 0;
 186
 187        ret = cl_eeprom_read_mac_addr(enetaddr, eeprom_bus);
 188        if (ret)
 189                return ret;
 190
 191        ret = is_valid_ethaddr(enetaddr);
 192        if (!ret)
 193                return -1;
 194
 195        return eth_env_set_enetaddr(env_var, enetaddr);
 196}
 197
 198#define CL_SOM_IMX7_FEC_DEV_ID_PRI 0
 199
 200int board_eth_init(bd_t *bis)
 201{
 202        /* set Ethernet MAC address environment */
 203        cl_som_imx7_handle_mac_address("ethaddr", CONFIG_SYS_I2C_EEPROM_BUS);
 204        /* Ethernet interface pinmux configuration  */
 205        cl_som_imx7_phy1_rst_pads_set();
 206        cl_som_imx7_fec1_pads_set();
 207        /* PHY reset */
 208        gpio_request(CL_SOM_IMX7_ETH1_PHY_NRST, "eth1_phy_nrst");
 209        gpio_direction_output(CL_SOM_IMX7_ETH1_PHY_NRST, 0);
 210        mdelay(10);
 211        gpio_set_value(CL_SOM_IMX7_ETH1_PHY_NRST, 1);
 212        /* MAC initialization */
 213        return fecmxc_initialize_multi(bis, CL_SOM_IMX7_FEC_DEV_ID_PRI,
 214                                       CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
 215}
 216
 217/*
 218 * cl_som_imx7_setup_fec() - Ethernet MAC 1 clock configuration.
 219 * - ENET1 reference clock mode select.
 220 * - ENET1_TX_CLK output driver is disabled when configured for ALT1.
 221 */
 222static void cl_som_imx7_setup_fec(void)
 223{
 224        struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs
 225                = (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
 226
 227        /* Use 125M anatop REF_CLK1 for ENET1, clear gpr1[13], gpr1[17]*/
 228        clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
 229                        (IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK |
 230                         IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0);
 231
 232        set_clk_enet(ENET_125MHZ);
 233}
 234#else /* !CONFIG_FEC_MXC */
 235static void cl_som_imx7_setup_fec(void) {}
 236#endif /* CONFIG_FEC_MXC */
 237
 238#ifdef CONFIG_SPI
 239
 240static void cl_som_imx7_spi_init(void)
 241{
 242        cl_som_imx7_espi1_pads_set();
 243}
 244#else /* !CONFIG_SPI */
 245static void cl_som_imx7_spi_init(void) {}
 246#endif /* CONFIG_SPI */
 247
 248int board_early_init_f(void)
 249{
 250        cl_som_imx7_uart1_pads_set();
 251        cl_som_imx7_usb_otg1_pads_set();
 252
 253        return 0;
 254}
 255
 256int board_init(void)
 257{
 258        /* address of boot parameters */
 259        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 260        cl_som_imx7_setup_i2c();
 261        cl_som_imx7_setup_fec();
 262        cl_som_imx7_spi_init();
 263
 264        return 0;
 265}
 266
 267#ifdef CONFIG_POWER
 268#define I2C_PMIC        0
 269int power_init_board(void)
 270{
 271        struct pmic *p;
 272        int ret;
 273        unsigned int reg, rev_id;
 274
 275        ret = power_pfuze3000_init(I2C_PMIC);
 276        if (ret)
 277                return ret;
 278
 279        p = pmic_get("PFUZE3000");
 280        ret = pmic_probe(p);
 281        if (ret)
 282                return ret;
 283
 284        pmic_reg_read(p, PFUZE3000_DEVICEID, &reg);
 285        pmic_reg_read(p, PFUZE3000_REVID, &rev_id);
 286        printf("PMIC: PFUZE3000 DEV_ID=0x%x REV_ID=0x%x\n", reg, rev_id);
 287
 288        /* disable Low Power Mode during standby mode */
 289        pmic_reg_write(p, PFUZE3000_LDOGCTL, 0x1);
 290
 291        return 0;
 292}
 293#endif /* CONFIG_POWER */
 294
 295/*
 296 * cl_som_imx7_setup_wdog() - watchdog configuration.
 297 * - Output WDOG_B signal to reset external pmic.
 298 * - Suspend the watchdog timer during low-power modes.
 299 */
 300void cl_som_imx7_setup_wdog(void)
 301{
 302        struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
 303
 304        cl_som_imx7_wdog_pads_set();
 305        set_wdog_reset(wdog);
 306       /*
 307        * Do not assert internal WDOG_RESET_B_DEB(controlled by bit 4),
 308        * since we use PMIC_PWRON to reset the board.
 309        */
 310        clrsetbits_le16(&wdog->wcr, 0, 0x10);
 311}
 312
 313int board_late_init(void)
 314{
 315        env_set("board_name", "CL-SOM-iMX7");
 316        cl_som_imx7_setup_wdog();
 317        return 0;
 318}
 319
 320int checkboard(void)
 321{
 322        char *mode;
 323
 324        if (IS_ENABLED(CONFIG_ARMV7_BOOT_SEC_DEFAULT))
 325                mode = "secure";
 326        else
 327                mode = "non-secure";
 328
 329        printf("Board: CL-SOM-iMX7 in %s mode\n", mode);
 330
 331        return 0;
 332}
 333