diff options
Diffstat (limited to 'drivers/mmc/fsl_esdhc_spl.c')
-rw-r--r-- | drivers/mmc/fsl_esdhc_spl.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/mmc/fsl_esdhc_spl.c b/drivers/mmc/fsl_esdhc_spl.c new file mode 100644 index 0000000000..65c52a22db --- /dev/null +++ b/drivers/mmc/fsl_esdhc_spl.c @@ -0,0 +1,115 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mmc.h> +#include <malloc.h> + +/* + * The environment variables are written to just after the u-boot image + * on SDCard, so we must read the MBR to get the start address and code + * length of the u-boot image, then calculate the address of the env. + */ +#define ESDHC_BOOT_IMAGE_SIZE 0x48 +#define ESDHC_BOOT_IMAGE_ADDR 0x50 +#define MBRDBR_BOOT_SIG_55 0x1fe +#define MBRDBR_BOOT_SIG_AA 0x1ff +#define CONFIG_CFG_DATA_SECTOR 0 + +/* + * The main entry for mmc booting. It's necessary that SDRAM is already + * configured and available since this code loads the main U-Boot image + * from mmc into SDRAM and starts it from there. + */ + +void __noreturn mmc_boot(void) +{ + __attribute__((noreturn)) void (*uboot)(void); + uint blk_start, blk_cnt, err; + u32 blklen; + uchar *tmp_buf; + uchar val; + uint i, byte_num; + u32 offset, code_len; + struct mmc *mmc; + + mmc = find_mmc_device(0); + if (!mmc) { + puts("spl: mmc device not found!!\n"); + hang(); + } + + blklen = mmc->read_bl_len; + tmp_buf = malloc(blklen); + if (!tmp_buf) { + puts("spl: malloc memory failed!!\n"); + hang(); + } + memset(tmp_buf, 0, blklen); + + /* + * Read source addr from sd card + */ + err = mmc->block_dev.block_read(0, CONFIG_CFG_DATA_SECTOR, 1, tmp_buf); + if (err != 1) { + puts("spl: mmc read failed!!\n"); + free(tmp_buf); + hang(); + } + + val = *(tmp_buf + MBRDBR_BOOT_SIG_55); + if (0x55 != val) { + puts("spl: mmc signature is not valid!!\n"); + free(tmp_buf); + hang(); + } + val = *(tmp_buf + MBRDBR_BOOT_SIG_AA); + if (0xAA != val) { + puts("spl: mmc signature is not valid!!\n"); + free(tmp_buf); + hang(); + } + + byte_num = 4; + offset = 0; + for (i = 0; i < byte_num; i++) { + val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i); + offset = (offset << 8) + val; + } + offset += CONFIG_SYS_MMC_U_BOOT_OFFS; + /* Get the code size from offset 0x48 */ + byte_num = 4; + code_len = 0; + for (i = 0; i < byte_num; i++) { + val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i); + code_len = (code_len << 8) + val; + } + code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS; + /* + * Load U-Boot image from mmc into RAM + */ + blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; + blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len; + err = mmc->block_dev.block_read(0, blk_start, blk_cnt, + (uchar *)CONFIG_SYS_MMC_U_BOOT_DST); + if (err != blk_cnt) { + puts("spl: mmc read failed!!\n"); + free(tmp_buf); + hang(); + } + + /* + * Clean d-cache and invalidate i-cache, to + * make sure that no stale data is executed. + */ + flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE); + + /* + * Jump to U-Boot image + */ + uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START; + (*uboot)(); +} |