1*bb0dc108SYing Zhang /* 2*bb0dc108SYing Zhang * Copyright 2013 Freescale Semiconductor, Inc. 3*bb0dc108SYing Zhang * 4*bb0dc108SYing Zhang * This program is free software; you can redistribute it and/or 5*bb0dc108SYing Zhang * modify it under the terms of the GNU General Public License as 6*bb0dc108SYing Zhang * published by the Free Software Foundation; either version 2 of 7*bb0dc108SYing Zhang * the License, or (at your option) any later version. 8*bb0dc108SYing Zhang * 9*bb0dc108SYing Zhang * This program is distributed in the hope that it will be useful, 10*bb0dc108SYing Zhang * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*bb0dc108SYing Zhang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*bb0dc108SYing Zhang * 13*bb0dc108SYing Zhang * GNU General Public License for more details. 14*bb0dc108SYing Zhang * 15*bb0dc108SYing Zhang * You should have received a copy of the GNU General Public License 16*bb0dc108SYing Zhang * along with this program; if not, write to the Free Software 17*bb0dc108SYing Zhang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 18*bb0dc108SYing Zhang * MA 02111-1307 USA 19*bb0dc108SYing Zhang * 20*bb0dc108SYing Zhang */ 21*bb0dc108SYing Zhang 22*bb0dc108SYing Zhang #include <common.h> 23*bb0dc108SYing Zhang #include <mmc.h> 24*bb0dc108SYing Zhang #include <malloc.h> 25*bb0dc108SYing Zhang 26*bb0dc108SYing Zhang /* 27*bb0dc108SYing Zhang * The environment variables are written to just after the u-boot image 28*bb0dc108SYing Zhang * on SDCard, so we must read the MBR to get the start address and code 29*bb0dc108SYing Zhang * length of the u-boot image, then calculate the address of the env. 30*bb0dc108SYing Zhang */ 31*bb0dc108SYing Zhang #define ESDHC_BOOT_IMAGE_SIZE 0x48 32*bb0dc108SYing Zhang #define ESDHC_BOOT_IMAGE_ADDR 0x50 33*bb0dc108SYing Zhang #define MBRDBR_BOOT_SIG_55 0x1fe 34*bb0dc108SYing Zhang #define MBRDBR_BOOT_SIG_AA 0x1ff 35*bb0dc108SYing Zhang #define CONFIG_CFG_DATA_SECTOR 0 36*bb0dc108SYing Zhang 37*bb0dc108SYing Zhang /* 38*bb0dc108SYing Zhang * The main entry for mmc booting. It's necessary that SDRAM is already 39*bb0dc108SYing Zhang * configured and available since this code loads the main U-Boot image 40*bb0dc108SYing Zhang * from mmc into SDRAM and starts it from there. 41*bb0dc108SYing Zhang */ 42*bb0dc108SYing Zhang 43*bb0dc108SYing Zhang void __noreturn mmc_boot(void) 44*bb0dc108SYing Zhang { 45*bb0dc108SYing Zhang __attribute__((noreturn)) void (*uboot)(void); 46*bb0dc108SYing Zhang uint blk_start, blk_cnt, err; 47*bb0dc108SYing Zhang u32 blklen; 48*bb0dc108SYing Zhang uchar *tmp_buf; 49*bb0dc108SYing Zhang uchar val; 50*bb0dc108SYing Zhang uint i, byte_num; 51*bb0dc108SYing Zhang u32 offset, code_len; 52*bb0dc108SYing Zhang struct mmc *mmc; 53*bb0dc108SYing Zhang 54*bb0dc108SYing Zhang mmc = find_mmc_device(0); 55*bb0dc108SYing Zhang if (!mmc) { 56*bb0dc108SYing Zhang puts("spl: mmc device not found!!\n"); 57*bb0dc108SYing Zhang hang(); 58*bb0dc108SYing Zhang } 59*bb0dc108SYing Zhang 60*bb0dc108SYing Zhang blklen = mmc->read_bl_len; 61*bb0dc108SYing Zhang tmp_buf = malloc(blklen); 62*bb0dc108SYing Zhang if (!tmp_buf) { 63*bb0dc108SYing Zhang puts("spl: malloc memory failed!!\n"); 64*bb0dc108SYing Zhang hang(); 65*bb0dc108SYing Zhang } 66*bb0dc108SYing Zhang memset(tmp_buf, 0, blklen); 67*bb0dc108SYing Zhang 68*bb0dc108SYing Zhang /* 69*bb0dc108SYing Zhang * Read source addr from sd card 70*bb0dc108SYing Zhang */ 71*bb0dc108SYing Zhang err = mmc->block_dev.block_read(0, CONFIG_CFG_DATA_SECTOR, 1, tmp_buf); 72*bb0dc108SYing Zhang if (err != 1) { 73*bb0dc108SYing Zhang puts("spl: mmc read failed!!\n"); 74*bb0dc108SYing Zhang free(tmp_buf); 75*bb0dc108SYing Zhang hang(); 76*bb0dc108SYing Zhang } 77*bb0dc108SYing Zhang 78*bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_55); 79*bb0dc108SYing Zhang if (0x55 != val) { 80*bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n"); 81*bb0dc108SYing Zhang free(tmp_buf); 82*bb0dc108SYing Zhang hang(); 83*bb0dc108SYing Zhang } 84*bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_AA); 85*bb0dc108SYing Zhang if (0xAA != val) { 86*bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n"); 87*bb0dc108SYing Zhang free(tmp_buf); 88*bb0dc108SYing Zhang hang(); 89*bb0dc108SYing Zhang } 90*bb0dc108SYing Zhang 91*bb0dc108SYing Zhang byte_num = 4; 92*bb0dc108SYing Zhang offset = 0; 93*bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) { 94*bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i); 95*bb0dc108SYing Zhang offset = (offset << 8) + val; 96*bb0dc108SYing Zhang } 97*bb0dc108SYing Zhang offset += CONFIG_SYS_MMC_U_BOOT_OFFS; 98*bb0dc108SYing Zhang /* Get the code size from offset 0x48 */ 99*bb0dc108SYing Zhang byte_num = 4; 100*bb0dc108SYing Zhang code_len = 0; 101*bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) { 102*bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i); 103*bb0dc108SYing Zhang code_len = (code_len << 8) + val; 104*bb0dc108SYing Zhang } 105*bb0dc108SYing Zhang code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS; 106*bb0dc108SYing Zhang /* 107*bb0dc108SYing Zhang * Load U-Boot image from mmc into RAM 108*bb0dc108SYing Zhang */ 109*bb0dc108SYing Zhang blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; 110*bb0dc108SYing Zhang blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len; 111*bb0dc108SYing Zhang err = mmc->block_dev.block_read(0, blk_start, blk_cnt, 112*bb0dc108SYing Zhang (uchar *)CONFIG_SYS_MMC_U_BOOT_DST); 113*bb0dc108SYing Zhang if (err != blk_cnt) { 114*bb0dc108SYing Zhang puts("spl: mmc read failed!!\n"); 115*bb0dc108SYing Zhang free(tmp_buf); 116*bb0dc108SYing Zhang hang(); 117*bb0dc108SYing Zhang } 118*bb0dc108SYing Zhang 119*bb0dc108SYing Zhang /* 120*bb0dc108SYing Zhang * Clean d-cache and invalidate i-cache, to 121*bb0dc108SYing Zhang * make sure that no stale data is executed. 122*bb0dc108SYing Zhang */ 123*bb0dc108SYing Zhang flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE); 124*bb0dc108SYing Zhang 125*bb0dc108SYing Zhang /* 126*bb0dc108SYing Zhang * Jump to U-Boot image 127*bb0dc108SYing Zhang */ 128*bb0dc108SYing Zhang uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START; 129*bb0dc108SYing Zhang (*uboot)(); 130*bb0dc108SYing Zhang } 131