1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2bb0dc108SYing Zhang /*
3bb0dc108SYing Zhang * Copyright 2013 Freescale Semiconductor, Inc.
4bb0dc108SYing Zhang */
5bb0dc108SYing Zhang
6bb0dc108SYing Zhang #include <common.h>
7bb0dc108SYing Zhang #include <mmc.h>
8bb0dc108SYing Zhang #include <malloc.h>
9bb0dc108SYing Zhang
10bb0dc108SYing Zhang /*
11bb0dc108SYing Zhang * The environment variables are written to just after the u-boot image
12bb0dc108SYing Zhang * on SDCard, so we must read the MBR to get the start address and code
13bb0dc108SYing Zhang * length of the u-boot image, then calculate the address of the env.
14bb0dc108SYing Zhang */
15bb0dc108SYing Zhang #define ESDHC_BOOT_IMAGE_SIZE 0x48
16bb0dc108SYing Zhang #define ESDHC_BOOT_IMAGE_ADDR 0x50
17bb0dc108SYing Zhang #define MBRDBR_BOOT_SIG_55 0x1fe
18bb0dc108SYing Zhang #define MBRDBR_BOOT_SIG_AA 0x1ff
19bb0dc108SYing Zhang #define CONFIG_CFG_DATA_SECTOR 0
20bb0dc108SYing Zhang
211eaa742dSPrabhakar Kushwaha
mmc_spl_load_image(uint32_t offs,unsigned int size,void * vdst)221eaa742dSPrabhakar Kushwaha void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst)
231eaa742dSPrabhakar Kushwaha {
241eaa742dSPrabhakar Kushwaha uint blk_start, blk_cnt, err;
251eaa742dSPrabhakar Kushwaha
261eaa742dSPrabhakar Kushwaha struct mmc *mmc = find_mmc_device(0);
271eaa742dSPrabhakar Kushwaha if (!mmc) {
281eaa742dSPrabhakar Kushwaha puts("spl: mmc device not found!!\n");
291eaa742dSPrabhakar Kushwaha hang();
301eaa742dSPrabhakar Kushwaha }
311eaa742dSPrabhakar Kushwaha
321eaa742dSPrabhakar Kushwaha if (mmc_init(mmc)) {
331eaa742dSPrabhakar Kushwaha puts("MMC init failed\n");
341eaa742dSPrabhakar Kushwaha return;
351eaa742dSPrabhakar Kushwaha }
361eaa742dSPrabhakar Kushwaha
371eaa742dSPrabhakar Kushwaha blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len;
381eaa742dSPrabhakar Kushwaha blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
391eaa742dSPrabhakar Kushwaha
407c4213f6SStephen Warren err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
417c4213f6SStephen Warren vdst);
421eaa742dSPrabhakar Kushwaha if (err != blk_cnt) {
431eaa742dSPrabhakar Kushwaha puts("spl: mmc read failed!!\n");
441eaa742dSPrabhakar Kushwaha hang();
451eaa742dSPrabhakar Kushwaha }
461eaa742dSPrabhakar Kushwaha }
471eaa742dSPrabhakar 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
mmc_boot(void)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 */
887c4213f6SStephen Warren err = mmc->block_dev.block_read(&mmc->block_dev,
897c4213f6SStephen Warren CONFIG_CFG_DATA_SECTOR, 1, tmp_buf);
90bb0dc108SYing Zhang if (err != 1) {
91bb0dc108SYing Zhang puts("spl: mmc read failed!!\n");
92bb0dc108SYing Zhang free(tmp_buf);
93bb0dc108SYing Zhang hang();
94bb0dc108SYing Zhang }
95bb0dc108SYing Zhang
96bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_55);
97bb0dc108SYing Zhang if (0x55 != val) {
98bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n");
99bb0dc108SYing Zhang free(tmp_buf);
100bb0dc108SYing Zhang hang();
101bb0dc108SYing Zhang }
102bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_AA);
103bb0dc108SYing Zhang if (0xAA != val) {
104bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n");
105bb0dc108SYing Zhang free(tmp_buf);
106bb0dc108SYing Zhang hang();
107bb0dc108SYing Zhang }
108bb0dc108SYing Zhang
109bb0dc108SYing Zhang byte_num = 4;
110bb0dc108SYing Zhang offset = 0;
111bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) {
112bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i);
113bb0dc108SYing Zhang offset = (offset << 8) + val;
114bb0dc108SYing Zhang }
115bb0dc108SYing Zhang offset += CONFIG_SYS_MMC_U_BOOT_OFFS;
116bb0dc108SYing Zhang /* Get the code size from offset 0x48 */
117bb0dc108SYing Zhang byte_num = 4;
118bb0dc108SYing Zhang code_len = 0;
119bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) {
120bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i);
121bb0dc108SYing Zhang code_len = (code_len << 8) + val;
122bb0dc108SYing Zhang }
123bb0dc108SYing Zhang code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS;
124bb0dc108SYing Zhang /*
125bb0dc108SYing Zhang * Load U-Boot image from mmc into RAM
126bb0dc108SYing Zhang */
1274520a2f2SPriyanka Jain #endif
128bb0dc108SYing Zhang blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
129bb0dc108SYing Zhang blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len;
1307c4213f6SStephen Warren err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
131bb0dc108SYing Zhang (uchar *)CONFIG_SYS_MMC_U_BOOT_DST);
132bb0dc108SYing Zhang if (err != blk_cnt) {
133bb0dc108SYing Zhang puts("spl: mmc read failed!!\n");
134613ab32cSPrabhakar Kushwaha #ifndef CONFIG_FSL_CORENET
135bb0dc108SYing Zhang free(tmp_buf);
136613ab32cSPrabhakar Kushwaha #endif
137bb0dc108SYing Zhang hang();
138bb0dc108SYing Zhang }
139bb0dc108SYing Zhang
140bb0dc108SYing Zhang /*
141bb0dc108SYing Zhang * Clean d-cache and invalidate i-cache, to
142bb0dc108SYing Zhang * make sure that no stale data is executed.
143bb0dc108SYing Zhang */
144bb0dc108SYing Zhang flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE);
145bb0dc108SYing Zhang
146bb0dc108SYing Zhang /*
147bb0dc108SYing Zhang * Jump to U-Boot image
148bb0dc108SYing Zhang */
149bb0dc108SYing Zhang uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START;
150bb0dc108SYing Zhang (*uboot)();
151bb0dc108SYing Zhang }
152