1bb0dc108SYing Zhang /* 2bb0dc108SYing Zhang * Copyright 2013 Freescale Semiconductor, Inc. 3bb0dc108SYing Zhang * 4bf902566SYork Sun * SPDX-License-Identifier: GPL-2.0+ 5bb0dc108SYing Zhang */ 6bb0dc108SYing Zhang 7bb0dc108SYing Zhang #include <common.h> 8bb0dc108SYing Zhang #include <mmc.h> 9bb0dc108SYing Zhang #include <malloc.h> 10bb0dc108SYing Zhang 11bb0dc108SYing Zhang /* 12bb0dc108SYing Zhang * The environment variables are written to just after the u-boot image 13bb0dc108SYing Zhang * on SDCard, so we must read the MBR to get the start address and code 14bb0dc108SYing Zhang * length of the u-boot image, then calculate the address of the env. 15bb0dc108SYing Zhang */ 16bb0dc108SYing Zhang #define ESDHC_BOOT_IMAGE_SIZE 0x48 17bb0dc108SYing Zhang #define ESDHC_BOOT_IMAGE_ADDR 0x50 18bb0dc108SYing Zhang #define MBRDBR_BOOT_SIG_55 0x1fe 19bb0dc108SYing Zhang #define MBRDBR_BOOT_SIG_AA 0x1ff 20bb0dc108SYing Zhang #define CONFIG_CFG_DATA_SECTOR 0 21bb0dc108SYing Zhang 22*1eaa742dSPrabhakar Kushwaha 23*1eaa742dSPrabhakar Kushwaha void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst) 24*1eaa742dSPrabhakar Kushwaha { 25*1eaa742dSPrabhakar Kushwaha uint blk_start, blk_cnt, err; 26*1eaa742dSPrabhakar Kushwaha 27*1eaa742dSPrabhakar Kushwaha struct mmc *mmc = find_mmc_device(0); 28*1eaa742dSPrabhakar Kushwaha if (!mmc) { 29*1eaa742dSPrabhakar Kushwaha puts("spl: mmc device not found!!\n"); 30*1eaa742dSPrabhakar Kushwaha hang(); 31*1eaa742dSPrabhakar Kushwaha } 32*1eaa742dSPrabhakar Kushwaha 33*1eaa742dSPrabhakar Kushwaha if (mmc_init(mmc)) { 34*1eaa742dSPrabhakar Kushwaha puts("MMC init failed\n"); 35*1eaa742dSPrabhakar Kushwaha return; 36*1eaa742dSPrabhakar Kushwaha } 37*1eaa742dSPrabhakar Kushwaha 38*1eaa742dSPrabhakar Kushwaha blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len; 39*1eaa742dSPrabhakar Kushwaha blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; 40*1eaa742dSPrabhakar Kushwaha 41*1eaa742dSPrabhakar Kushwaha err = mmc->block_dev.block_read(0, blk_start, blk_cnt, vdst); 42*1eaa742dSPrabhakar Kushwaha if (err != blk_cnt) { 43*1eaa742dSPrabhakar Kushwaha puts("spl: mmc read failed!!\n"); 44*1eaa742dSPrabhakar Kushwaha hang(); 45*1eaa742dSPrabhakar Kushwaha } 46*1eaa742dSPrabhakar Kushwaha } 47*1eaa742dSPrabhakar Kushwaha 48bb0dc108SYing Zhang /* 49bb0dc108SYing Zhang * The main entry for mmc booting. It's necessary that SDRAM is already 50bb0dc108SYing Zhang * configured and available since this code loads the main U-Boot image 51bb0dc108SYing Zhang * from mmc into SDRAM and starts it from there. 52bb0dc108SYing Zhang */ 53bb0dc108SYing Zhang 54bb0dc108SYing Zhang void __noreturn mmc_boot(void) 55bb0dc108SYing Zhang { 56bb0dc108SYing Zhang __attribute__((noreturn)) void (*uboot)(void); 57bb0dc108SYing Zhang uint blk_start, blk_cnt, err; 58613ab32cSPrabhakar Kushwaha #ifndef CONFIG_FSL_CORENET 59bb0dc108SYing Zhang uchar *tmp_buf; 60613ab32cSPrabhakar Kushwaha u32 blklen; 61bb0dc108SYing Zhang uchar val; 62bb0dc108SYing Zhang uint i, byte_num; 63613ab32cSPrabhakar Kushwaha #endif 64bb0dc108SYing Zhang u32 offset, code_len; 65bb0dc108SYing Zhang struct mmc *mmc; 66bb0dc108SYing Zhang 67bb0dc108SYing Zhang mmc = find_mmc_device(0); 68bb0dc108SYing Zhang if (!mmc) { 69bb0dc108SYing Zhang puts("spl: mmc device not found!!\n"); 70bb0dc108SYing Zhang hang(); 71bb0dc108SYing Zhang } 72bb0dc108SYing Zhang 734520a2f2SPriyanka Jain #ifdef CONFIG_FSL_CORENET 744520a2f2SPriyanka Jain offset = CONFIG_SYS_MMC_U_BOOT_OFFS; 754520a2f2SPriyanka Jain code_len = CONFIG_SYS_MMC_U_BOOT_SIZE; 764520a2f2SPriyanka Jain #else 77bb0dc108SYing Zhang blklen = mmc->read_bl_len; 78bb0dc108SYing Zhang tmp_buf = malloc(blklen); 79bb0dc108SYing Zhang if (!tmp_buf) { 80bb0dc108SYing Zhang puts("spl: malloc memory failed!!\n"); 81bb0dc108SYing Zhang hang(); 82bb0dc108SYing Zhang } 83bb0dc108SYing Zhang memset(tmp_buf, 0, blklen); 84bb0dc108SYing Zhang 85bb0dc108SYing Zhang /* 86bb0dc108SYing Zhang * Read source addr from sd card 87bb0dc108SYing Zhang */ 88bb0dc108SYing Zhang err = mmc->block_dev.block_read(0, CONFIG_CFG_DATA_SECTOR, 1, tmp_buf); 89bb0dc108SYing Zhang if (err != 1) { 90bb0dc108SYing Zhang puts("spl: mmc read failed!!\n"); 91bb0dc108SYing Zhang free(tmp_buf); 92bb0dc108SYing Zhang hang(); 93bb0dc108SYing Zhang } 94bb0dc108SYing Zhang 95bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_55); 96bb0dc108SYing Zhang if (0x55 != val) { 97bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n"); 98bb0dc108SYing Zhang free(tmp_buf); 99bb0dc108SYing Zhang hang(); 100bb0dc108SYing Zhang } 101bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_AA); 102bb0dc108SYing Zhang if (0xAA != val) { 103bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n"); 104bb0dc108SYing Zhang free(tmp_buf); 105bb0dc108SYing Zhang hang(); 106bb0dc108SYing Zhang } 107bb0dc108SYing Zhang 108bb0dc108SYing Zhang byte_num = 4; 109bb0dc108SYing Zhang offset = 0; 110bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) { 111bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i); 112bb0dc108SYing Zhang offset = (offset << 8) + val; 113bb0dc108SYing Zhang } 114bb0dc108SYing Zhang offset += CONFIG_SYS_MMC_U_BOOT_OFFS; 115bb0dc108SYing Zhang /* Get the code size from offset 0x48 */ 116bb0dc108SYing Zhang byte_num = 4; 117bb0dc108SYing Zhang code_len = 0; 118bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) { 119bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i); 120bb0dc108SYing Zhang code_len = (code_len << 8) + val; 121bb0dc108SYing Zhang } 122bb0dc108SYing Zhang code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS; 123bb0dc108SYing Zhang /* 124bb0dc108SYing Zhang * Load U-Boot image from mmc into RAM 125bb0dc108SYing Zhang */ 1264520a2f2SPriyanka Jain #endif 127bb0dc108SYing Zhang blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; 128bb0dc108SYing Zhang blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len; 129bb0dc108SYing Zhang err = mmc->block_dev.block_read(0, blk_start, blk_cnt, 130bb0dc108SYing Zhang (uchar *)CONFIG_SYS_MMC_U_BOOT_DST); 131bb0dc108SYing Zhang if (err != blk_cnt) { 132bb0dc108SYing Zhang puts("spl: mmc read failed!!\n"); 133613ab32cSPrabhakar Kushwaha #ifndef CONFIG_FSL_CORENET 134bb0dc108SYing Zhang free(tmp_buf); 135613ab32cSPrabhakar Kushwaha #endif 136bb0dc108SYing Zhang hang(); 137bb0dc108SYing Zhang } 138bb0dc108SYing Zhang 139bb0dc108SYing Zhang /* 140bb0dc108SYing Zhang * Clean d-cache and invalidate i-cache, to 141bb0dc108SYing Zhang * make sure that no stale data is executed. 142bb0dc108SYing Zhang */ 143bb0dc108SYing Zhang flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE); 144bb0dc108SYing Zhang 145bb0dc108SYing Zhang /* 146bb0dc108SYing Zhang * Jump to U-Boot image 147bb0dc108SYing Zhang */ 148bb0dc108SYing Zhang uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START; 149bb0dc108SYing Zhang (*uboot)(); 150bb0dc108SYing Zhang } 151