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 22bb0dc108SYing Zhang /* 23bb0dc108SYing Zhang * The main entry for mmc booting. It's necessary that SDRAM is already 24bb0dc108SYing Zhang * configured and available since this code loads the main U-Boot image 25bb0dc108SYing Zhang * from mmc into SDRAM and starts it from there. 26bb0dc108SYing Zhang */ 27bb0dc108SYing Zhang 28bb0dc108SYing Zhang void __noreturn mmc_boot(void) 29bb0dc108SYing Zhang { 30bb0dc108SYing Zhang __attribute__((noreturn)) void (*uboot)(void); 31bb0dc108SYing Zhang uint blk_start, blk_cnt, err; 32bb0dc108SYing Zhang u32 blklen; 33bb0dc108SYing Zhang uchar *tmp_buf; 34bb0dc108SYing Zhang uchar val; 35bb0dc108SYing Zhang uint i, byte_num; 36bb0dc108SYing Zhang u32 offset, code_len; 37bb0dc108SYing Zhang struct mmc *mmc; 38bb0dc108SYing Zhang 39bb0dc108SYing Zhang mmc = find_mmc_device(0); 40bb0dc108SYing Zhang if (!mmc) { 41bb0dc108SYing Zhang puts("spl: mmc device not found!!\n"); 42bb0dc108SYing Zhang hang(); 43bb0dc108SYing Zhang } 44bb0dc108SYing Zhang 45*4520a2f2SPriyanka Jain #ifdef CONFIG_FSL_CORENET 46*4520a2f2SPriyanka Jain offset = CONFIG_SYS_MMC_U_BOOT_OFFS; 47*4520a2f2SPriyanka Jain code_len = CONFIG_SYS_MMC_U_BOOT_SIZE; 48*4520a2f2SPriyanka Jain #else 49bb0dc108SYing Zhang blklen = mmc->read_bl_len; 50bb0dc108SYing Zhang tmp_buf = malloc(blklen); 51bb0dc108SYing Zhang if (!tmp_buf) { 52bb0dc108SYing Zhang puts("spl: malloc memory failed!!\n"); 53bb0dc108SYing Zhang hang(); 54bb0dc108SYing Zhang } 55bb0dc108SYing Zhang memset(tmp_buf, 0, blklen); 56bb0dc108SYing Zhang 57bb0dc108SYing Zhang /* 58bb0dc108SYing Zhang * Read source addr from sd card 59bb0dc108SYing Zhang */ 60bb0dc108SYing Zhang err = mmc->block_dev.block_read(0, CONFIG_CFG_DATA_SECTOR, 1, tmp_buf); 61bb0dc108SYing Zhang if (err != 1) { 62bb0dc108SYing Zhang puts("spl: mmc read failed!!\n"); 63bb0dc108SYing Zhang free(tmp_buf); 64bb0dc108SYing Zhang hang(); 65bb0dc108SYing Zhang } 66bb0dc108SYing Zhang 67bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_55); 68bb0dc108SYing Zhang if (0x55 != val) { 69bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n"); 70bb0dc108SYing Zhang free(tmp_buf); 71bb0dc108SYing Zhang hang(); 72bb0dc108SYing Zhang } 73bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_AA); 74bb0dc108SYing Zhang if (0xAA != val) { 75bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n"); 76bb0dc108SYing Zhang free(tmp_buf); 77bb0dc108SYing Zhang hang(); 78bb0dc108SYing Zhang } 79bb0dc108SYing Zhang 80bb0dc108SYing Zhang byte_num = 4; 81bb0dc108SYing Zhang offset = 0; 82bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) { 83bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i); 84bb0dc108SYing Zhang offset = (offset << 8) + val; 85bb0dc108SYing Zhang } 86bb0dc108SYing Zhang offset += CONFIG_SYS_MMC_U_BOOT_OFFS; 87bb0dc108SYing Zhang /* Get the code size from offset 0x48 */ 88bb0dc108SYing Zhang byte_num = 4; 89bb0dc108SYing Zhang code_len = 0; 90bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) { 91bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i); 92bb0dc108SYing Zhang code_len = (code_len << 8) + val; 93bb0dc108SYing Zhang } 94bb0dc108SYing Zhang code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS; 95bb0dc108SYing Zhang /* 96bb0dc108SYing Zhang * Load U-Boot image from mmc into RAM 97bb0dc108SYing Zhang */ 98*4520a2f2SPriyanka Jain #endif 99bb0dc108SYing Zhang blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; 100bb0dc108SYing Zhang blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len; 101bb0dc108SYing Zhang err = mmc->block_dev.block_read(0, blk_start, blk_cnt, 102bb0dc108SYing Zhang (uchar *)CONFIG_SYS_MMC_U_BOOT_DST); 103bb0dc108SYing Zhang if (err != blk_cnt) { 104bb0dc108SYing Zhang puts("spl: mmc read failed!!\n"); 105bb0dc108SYing Zhang free(tmp_buf); 106bb0dc108SYing Zhang hang(); 107bb0dc108SYing Zhang } 108bb0dc108SYing Zhang 109bb0dc108SYing Zhang /* 110bb0dc108SYing Zhang * Clean d-cache and invalidate i-cache, to 111bb0dc108SYing Zhang * make sure that no stale data is executed. 112bb0dc108SYing Zhang */ 113bb0dc108SYing Zhang flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE); 114bb0dc108SYing Zhang 115bb0dc108SYing Zhang /* 116bb0dc108SYing Zhang * Jump to U-Boot image 117bb0dc108SYing Zhang */ 118bb0dc108SYing Zhang uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START; 119bb0dc108SYing Zhang (*uboot)(); 120bb0dc108SYing Zhang } 121