// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2020 Toradex */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include DECLARE_GLOBAL_DATA_PTR; int spl_board_boot_device(enum boot_device boot_dev_spl) { switch (boot_dev_spl) { case MMC1_BOOT: return BOOT_DEVICE_MMC1; case SD2_BOOT: case MMC2_BOOT: return BOOT_DEVICE_MMC2; case SD3_BOOT: case MMC3_BOOT: return BOOT_DEVICE_MMC1; case USB_BOOT: return BOOT_DEVICE_BOARD; default: return BOOT_DEVICE_NONE; } } void spl_dram_init(void) { ddr_init(&dram_timing); } #define I2C_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PE) #define PC MUX_PAD_CTRL(I2C_PAD_CTRL) struct i2c_pads_info i2c_pad_info1 = { .scl = { .i2c_mode = IMX8MM_PAD_I2C1_SCL_I2C1_SCL | PC, .gpio_mode = IMX8MM_PAD_I2C1_SCL_GPIO5_IO14 | PC, .gp = IMX_GPIO_NR(5, 14), }, .sda = { .i2c_mode = IMX8MM_PAD_I2C1_SDA_I2C1_SDA | PC, .gpio_mode = IMX8MM_PAD_I2C1_SDA_GPIO5_IO15 | PC, .gp = IMX_GPIO_NR(5, 15), }, }; #define USDHC2_CD_GPIO IMX_GPIO_NR(2, 12) #define USDHC2_PWR_GPIO IMX_GPIO_NR(3, 5) #define USDHC_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PE | \ PAD_CTL_FSEL2) #define USDHC_GPIO_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_DSE1) #define USDHC_RESET_PAD_CTRL (PAD_CTL_DSE1 | PAD_CTL_HYS | PAD_CTL_PUE | \ PAD_CTL_FSEL2 | PAD_CTL_PE) static iomux_v3_cfg_t const usdhc1_pads[] = { IMX8MM_PAD_SD1_CLK_USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_CMD_USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA0_USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA1_USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA2_USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA3_USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA4_USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA5_USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA6_USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_DATA7_USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD1_RESET_B_USDHC1_RESET_B | MUX_PAD_CTRL(USDHC_RESET_PAD_CTRL), IMX8MM_PAD_SD1_STROBE_USDHC1_STROBE | MUX_PAD_CTRL(USDHC_PAD_CTRL), }; static iomux_v3_cfg_t const usdhc2_pads[] = { IMX8MM_PAD_SD2_CLK_USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD2_CMD_USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD2_DATA0_USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD2_DATA1_USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD2_DATA2_USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD2_DATA3_USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), IMX8MM_PAD_SD2_RESET_B_GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL), IMX8MM_PAD_SD2_CD_B_GPIO2_IO12 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL), IMX8MM_PAD_NAND_CLE_GPIO3_IO5 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL), }; static struct fsl_esdhc_cfg usdhc_cfg[2] = { /* esdhc_base, sdhc_clk, max_bus_width */ {USDHC1_BASE_ADDR, 0, 8}, {USDHC2_BASE_ADDR, 0, 4}, }; int board_mmc_init(bd_t *bis) { int i, ret; /* * According to the board_mmc_init() the following map is done: * (U-Boot device node) (Physical Port) * mmc0 USDHC1 (eMMC) * mmc1 USDHC2 (SD card) */ for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { switch (i) { case 0: usdhc_cfg[i].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); imx_iomux_v3_setup_multiple_pads( usdhc1_pads, ARRAY_SIZE(usdhc1_pads)); break; case 1: usdhc_cfg[i].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); imx_iomux_v3_setup_multiple_pads( usdhc2_pads, ARRAY_SIZE(usdhc2_pads)); gpio_request(USDHC2_PWR_GPIO, "SD_1_PWR_EN"); gpio_direction_output(USDHC2_PWR_GPIO, 1); break; default: printf("Warning: you configured more USDHC controllers" "(%d) than supported by the board\n", i + 1); return -EINVAL; } ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]); if (ret) return ret; } return 0; } int board_mmc_getcd(struct mmc *mmc) { struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; int ret = 0; switch (cfg->esdhc_base) { case USDHC1_BASE_ADDR: ret = 1; /* eMMC */ break; case USDHC2_BASE_ADDR: gpio_request(USDHC2_CD_GPIO, "SD_1_CD#"); gpio_direction_input(USDHC2_CD_GPIO); ret = !gpio_get_value(USDHC2_CD_GPIO); return ret; } return 1; } #ifdef CONFIG_POWER #define I2C_PMIC 0 int power_init_board(void) { struct pmic *p; int ret; ret = power_bd71837_init(I2C_PMIC); if (ret) printf("power init failed"); p = pmic_get("BD71837"); pmic_probe(p); /* decrease RESET key long push time from the default 10s to 10ms */ pmic_reg_write(p, BD71837_PWRONCONFIG1, 0x0); /* unlock the PMIC regs */ pmic_reg_write(p, BD71837_REGLOCK, 0x1); /* increase VDD_SOC to typical value 0.85v before first DRAM access */ pmic_reg_write(p, BD71837_BUCK1_VOLT_RUN, 0x0f); /* increase VDD_DRAM to 0.975v for 3Ghz DDR */ pmic_reg_write(p, BD71837_BUCK5_VOLT, 0x83); #ifndef CONFIG_IMX8M_LPDDR4 /* increase NVCC_DRAM_1V2 to 1.2v for DDR4 */ pmic_reg_write(p, BD71837_BUCK8_VOLT, 0x28); #endif /* lock the PMIC regs */ pmic_reg_write(p, BD71837_REGLOCK, 0x11); return 0; } #endif void spl_board_init(void) { #ifndef CONFIG_SPL_USB_SDP_SUPPORT /* Serial download mode */ if (is_usb_boot()) { puts("Back to ROM, SDP\n"); restore_boot_params(); } #endif puts("Normal Boot\n"); } #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) { /* Just empty function now - can't decide what to choose */ debug("%s: %s\n", __func__, name); return 0; } #endif void board_init_f(ulong dummy) { int ret; /* Clear the BSS. */ memset(__bss_start, 0, __bss_end - __bss_start); arch_cpu_init(); init_uart_clk(0); board_early_init_f(); timer_init(); preloader_console_init(); ret = spl_init(); if (ret) { debug("spl_init() failed: %d\n", ret); hang(); } enable_tzc380(); /* Adjust pmic voltage to 1.0V for 800M */ setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); power_init_board(); /* DDR initialization */ spl_dram_init(); board_init_r(NULL, 0); } int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { puts ("resetting ...\n"); reset_cpu(WDOG1_BASE_ADDR); return 0; }