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