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