uboot/board/freescale/imx8mq_evk/spl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2018 NXP
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <hang.h>
  10#include <image.h>
  11#include <init.h>
  12#include <log.h>
  13#include <asm/global_data.h>
  14#include <asm/io.h>
  15#include <errno.h>
  16#include <asm/io.h>
  17#include <asm/arch/ddr.h>
  18#include <asm/arch/imx8mq_pins.h>
  19#include <asm/arch/sys_proto.h>
  20#include <asm/arch/clock.h>
  21#include <asm/mach-imx/iomux-v3.h>
  22#include <asm/mach-imx/gpio.h>
  23#include <asm/mach-imx/mxc_i2c.h>
  24#include <fsl_esdhc_imx.h>
  25#include <mmc.h>
  26#include <linux/delay.h>
  27#include <power/pmic.h>
  28#include <power/pfuze100_pmic.h>
  29#include <spl.h>
  30#include "../common/pfuze.h"
  31
  32DECLARE_GLOBAL_DATA_PTR;
  33
  34extern struct dram_timing_info dram_timing_b0;
  35
  36static void spl_dram_init(void)
  37{
  38        /* ddr init */
  39        if (soc_rev() >= CHIP_REV_2_1)
  40                ddr_init(&dram_timing);
  41        else
  42                ddr_init(&dram_timing_b0);
  43}
  44
  45#define I2C_PAD_CTRL    (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
  46#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
  47static struct i2c_pads_info i2c_pad_info1 = {
  48        .scl = {
  49                .i2c_mode = IMX8MQ_PAD_I2C1_SCL__I2C1_SCL | PC,
  50                .gpio_mode = IMX8MQ_PAD_I2C1_SCL__GPIO5_IO14 | PC,
  51                .gp = IMX_GPIO_NR(5, 14),
  52        },
  53        .sda = {
  54                .i2c_mode = IMX8MQ_PAD_I2C1_SDA__I2C1_SDA | PC,
  55                .gpio_mode = IMX8MQ_PAD_I2C1_SDA__GPIO5_IO15 | PC,
  56                .gp = IMX_GPIO_NR(5, 15),
  57        },
  58};
  59
  60#define USDHC2_CD_GPIO  IMX_GPIO_NR(2, 12)
  61#define USDHC1_PWR_GPIO IMX_GPIO_NR(2, 10)
  62#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)
  63
  64int board_mmc_getcd(struct mmc *mmc)
  65{
  66        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
  67        int ret = 0;
  68
  69        switch (cfg->esdhc_base) {
  70        case USDHC1_BASE_ADDR:
  71                ret = 1;
  72                break;
  73        case USDHC2_BASE_ADDR:
  74                ret = !gpio_get_value(USDHC2_CD_GPIO);
  75                return ret;
  76        }
  77
  78        return 1;
  79}
  80
  81#define USDHC_PAD_CTRL  (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | \
  82                         PAD_CTL_FSEL2)
  83#define USDHC_GPIO_PAD_CTRL (PAD_CTL_PUE | PAD_CTL_DSE1)
  84
  85static iomux_v3_cfg_t const usdhc1_pads[] = {
  86        IMX8MQ_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  87        IMX8MQ_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  88        IMX8MQ_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  89        IMX8MQ_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  90        IMX8MQ_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  91        IMX8MQ_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  92        IMX8MQ_PAD_SD1_DATA4__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  93        IMX8MQ_PAD_SD1_DATA5__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  94        IMX8MQ_PAD_SD1_DATA6__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  95        IMX8MQ_PAD_SD1_DATA7__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  96        IMX8MQ_PAD_SD1_RESET_B__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
  97};
  98
  99static iomux_v3_cfg_t const usdhc2_pads[] = {
 100        IMX8MQ_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
 101        IMX8MQ_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
 102        IMX8MQ_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
 103        IMX8MQ_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
 104        IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0x16 */
 105        IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
 106        IMX8MQ_PAD_SD2_CD_B__GPIO2_IO12 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
 107        IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
 108};
 109
 110static struct fsl_esdhc_cfg usdhc_cfg[2] = {
 111        {USDHC1_BASE_ADDR, 0, 8},
 112        {USDHC2_BASE_ADDR, 0, 4},
 113};
 114
 115int board_mmc_init(struct bd_info *bis)
 116{
 117        int i, ret;
 118        /*
 119         * According to the board_mmc_init() the following map is done:
 120         * (U-Boot device node)    (Physical Port)
 121         * mmc0                    USDHC1
 122         * mmc1                    USDHC2
 123         */
 124        for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
 125                switch (i) {
 126                case 0:
 127                        init_clk_usdhc(0);
 128                        usdhc_cfg[0].sdhc_clk = mxc_get_clock(USDHC1_CLK_ROOT);
 129                        imx_iomux_v3_setup_multiple_pads(usdhc1_pads,
 130                                                         ARRAY_SIZE(usdhc1_pads));
 131                        gpio_request(USDHC1_PWR_GPIO, "usdhc1_reset");
 132                        gpio_direction_output(USDHC1_PWR_GPIO, 0);
 133                        udelay(500);
 134                        gpio_direction_output(USDHC1_PWR_GPIO, 1);
 135                        break;
 136                case 1:
 137                        init_clk_usdhc(1);
 138                        usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT);
 139                        imx_iomux_v3_setup_multiple_pads(usdhc2_pads,
 140                                                         ARRAY_SIZE(usdhc2_pads));
 141                        gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset");
 142                        gpio_direction_output(USDHC2_PWR_GPIO, 0);
 143                        udelay(500);
 144                        gpio_direction_output(USDHC2_PWR_GPIO, 1);
 145                        break;
 146                default:
 147                        printf("Warning: you configured more USDHC controllers(%d) than supported by the board\n", i + 1);
 148                        return -EINVAL;
 149                }
 150
 151                ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
 152                if (ret)
 153                        return ret;
 154        }
 155
 156        return 0;
 157}
 158
 159#if CONFIG_IS_ENABLED(POWER_LEGACY)
 160#define I2C_PMIC        0
 161int power_init_board(void)
 162{
 163        struct pmic *p;
 164        int ret;
 165        unsigned int reg;
 166
 167        ret = power_pfuze100_init(I2C_PMIC);
 168        if (ret)
 169                return -ENODEV;
 170
 171        p = pmic_get("PFUZE100");
 172        ret = pmic_probe(p);
 173        if (ret)
 174                return -ENODEV;
 175
 176        pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
 177        printf("PMIC:  PFUZE100 ID=0x%02x\n", reg);
 178
 179        pmic_reg_read(p, PFUZE100_SW3AVOL, &reg);
 180        if ((reg & 0x3f) != 0x18) {
 181                reg &= ~0x3f;
 182                reg |= 0x18;
 183                pmic_reg_write(p, PFUZE100_SW3AVOL, reg);
 184        }
 185
 186        ret = pfuze_mode_init(p, APS_PFM);
 187        if (ret < 0)
 188                return ret;
 189
 190        /* set SW3A standby mode to off */
 191        pmic_reg_read(p, PFUZE100_SW3AMODE, &reg);
 192        reg &= ~0xf;
 193        reg |= APS_OFF;
 194        pmic_reg_write(p, PFUZE100_SW3AMODE, reg);
 195
 196        return 0;
 197}
 198#endif
 199
 200void spl_board_init(void)
 201{
 202        puts("Normal Boot\n");
 203}
 204
 205#ifdef CONFIG_SPL_LOAD_FIT
 206int board_fit_config_name_match(const char *name)
 207{
 208        /* Just empty function now - can't decide what to choose */
 209        debug("%s: %s\n", __func__, name);
 210
 211        return 0;
 212}
 213#endif
 214
 215void board_init_f(ulong dummy)
 216{
 217        int ret;
 218
 219        /* Clear global data */
 220        memset((void *)gd, 0, sizeof(gd_t));
 221
 222        arch_cpu_init();
 223
 224        init_uart_clk(0);
 225
 226        board_early_init_f();
 227
 228        timer_init();
 229
 230        preloader_console_init();
 231
 232        /* Clear the BSS. */
 233        memset(__bss_start, 0, __bss_end - __bss_start);
 234
 235        ret = spl_init();
 236        if (ret) {
 237                debug("spl_init() failed: %d\n", ret);
 238                hang();
 239        }
 240
 241        enable_tzc380();
 242
 243        setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
 244
 245        power_init_board();
 246
 247        /* DDR initialization */
 248        spl_dram_init();
 249
 250        board_init_r(NULL, 0);
 251}
 252