diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Makefile | 3 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc_spl.c | 130 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 2 |
3 files changed, 135 insertions, 0 deletions
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 49e5cb9..bedf833 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -32,6 +32,9 @@ COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o COBJS-$(CONFIG_DWMMC) += dw_mmc.o COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o +ifdef CONFIG_SPL_BUILD +COBJS-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o +endif COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mmc/fsl_esdhc_spl.c b/drivers/mmc/fsl_esdhc_spl.c new file mode 100644 index 0000000..25a1dff --- /dev/null +++ b/drivers/mmc/fsl_esdhc_spl.c @@ -0,0 +1,130 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#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)(); +} diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 4da8db9..5502675 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1483,7 +1483,9 @@ int mmc_initialize(bd_t *bis) if (board_mmc_init(bis) < 0) cpu_mmc_init(bis); +#ifndef CONFIG_SPL_BUILD print_mmc_devices(','); +#endif do_preinit(); return 0; |