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
221eaa742dSPrabhakar Kushwaha
mmc_spl_load_image(uint32_t offs,unsigned int size,void * vdst)231eaa742dSPrabhakar Kushwaha void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst)
241eaa742dSPrabhakar Kushwaha {
251eaa742dSPrabhakar Kushwaha uint blk_start, blk_cnt, err;
261eaa742dSPrabhakar Kushwaha
271eaa742dSPrabhakar Kushwaha struct mmc *mmc = find_mmc_device(0);
281eaa742dSPrabhakar Kushwaha if (!mmc) {
291eaa742dSPrabhakar Kushwaha puts("spl: mmc device not found!!\n");
301eaa742dSPrabhakar Kushwaha hang();
311eaa742dSPrabhakar Kushwaha }
321eaa742dSPrabhakar Kushwaha
331eaa742dSPrabhakar Kushwaha if (mmc_init(mmc)) {
341eaa742dSPrabhakar Kushwaha puts("MMC init failed\n");
351eaa742dSPrabhakar Kushwaha return;
361eaa742dSPrabhakar Kushwaha }
371eaa742dSPrabhakar Kushwaha
381eaa742dSPrabhakar Kushwaha blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len;
391eaa742dSPrabhakar Kushwaha blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
401eaa742dSPrabhakar Kushwaha
41*7c4213f6SStephen Warren err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
42*7c4213f6SStephen Warren vdst);
431eaa742dSPrabhakar Kushwaha if (err != blk_cnt) {
441eaa742dSPrabhakar Kushwaha puts("spl: mmc read failed!!\n");
451eaa742dSPrabhakar Kushwaha hang();
461eaa742dSPrabhakar Kushwaha }
471eaa742dSPrabhakar Kushwaha }
481eaa742dSPrabhakar Kushwaha
49bb0dc108SYing Zhang /*
50bb0dc108SYing Zhang * The main entry for mmc booting. It's necessary that SDRAM is already
51bb0dc108SYing Zhang * configured and available since this code loads the main U-Boot image
52bb0dc108SYing Zhang * from mmc into SDRAM and starts it from there.
53bb0dc108SYing Zhang */
54bb0dc108SYing Zhang
mmc_boot(void)55bb0dc108SYing Zhang void __noreturn mmc_boot(void)
56bb0dc108SYing Zhang {
57bb0dc108SYing Zhang __attribute__((noreturn)) void (*uboot)(void);
58bb0dc108SYing Zhang uint blk_start, blk_cnt, err;
59613ab32cSPrabhakar Kushwaha #ifndef CONFIG_FSL_CORENET
60bb0dc108SYing Zhang uchar *tmp_buf;
61613ab32cSPrabhakar Kushwaha u32 blklen;
62bb0dc108SYing Zhang uchar val;
63bb0dc108SYing Zhang uint i, byte_num;
64613ab32cSPrabhakar Kushwaha #endif
65bb0dc108SYing Zhang u32 offset, code_len;
66bb0dc108SYing Zhang struct mmc *mmc;
67bb0dc108SYing Zhang
68bb0dc108SYing Zhang mmc = find_mmc_device(0);
69bb0dc108SYing Zhang if (!mmc) {
70bb0dc108SYing Zhang puts("spl: mmc device not found!!\n");
71bb0dc108SYing Zhang hang();
72bb0dc108SYing Zhang }
73bb0dc108SYing Zhang
744520a2f2SPriyanka Jain #ifdef CONFIG_FSL_CORENET
754520a2f2SPriyanka Jain offset = CONFIG_SYS_MMC_U_BOOT_OFFS;
764520a2f2SPriyanka Jain code_len = CONFIG_SYS_MMC_U_BOOT_SIZE;
774520a2f2SPriyanka Jain #else
78bb0dc108SYing Zhang blklen = mmc->read_bl_len;
79bb0dc108SYing Zhang tmp_buf = malloc(blklen);
80bb0dc108SYing Zhang if (!tmp_buf) {
81bb0dc108SYing Zhang puts("spl: malloc memory failed!!\n");
82bb0dc108SYing Zhang hang();
83bb0dc108SYing Zhang }
84bb0dc108SYing Zhang memset(tmp_buf, 0, blklen);
85bb0dc108SYing Zhang
86bb0dc108SYing Zhang /*
87bb0dc108SYing Zhang * Read source addr from sd card
88bb0dc108SYing Zhang */
89*7c4213f6SStephen Warren err = mmc->block_dev.block_read(&mmc->block_dev,
90*7c4213f6SStephen Warren CONFIG_CFG_DATA_SECTOR, 1, tmp_buf);
91bb0dc108SYing Zhang if (err != 1) {
92bb0dc108SYing Zhang puts("spl: mmc read failed!!\n");
93bb0dc108SYing Zhang free(tmp_buf);
94bb0dc108SYing Zhang hang();
95bb0dc108SYing Zhang }
96bb0dc108SYing Zhang
97bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_55);
98bb0dc108SYing Zhang if (0x55 != val) {
99bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n");
100bb0dc108SYing Zhang free(tmp_buf);
101bb0dc108SYing Zhang hang();
102bb0dc108SYing Zhang }
103bb0dc108SYing Zhang val = *(tmp_buf + MBRDBR_BOOT_SIG_AA);
104bb0dc108SYing Zhang if (0xAA != val) {
105bb0dc108SYing Zhang puts("spl: mmc signature is not valid!!\n");
106bb0dc108SYing Zhang free(tmp_buf);
107bb0dc108SYing Zhang hang();
108bb0dc108SYing Zhang }
109bb0dc108SYing Zhang
110bb0dc108SYing Zhang byte_num = 4;
111bb0dc108SYing Zhang offset = 0;
112bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) {
113bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i);
114bb0dc108SYing Zhang offset = (offset << 8) + val;
115bb0dc108SYing Zhang }
116bb0dc108SYing Zhang offset += CONFIG_SYS_MMC_U_BOOT_OFFS;
117bb0dc108SYing Zhang /* Get the code size from offset 0x48 */
118bb0dc108SYing Zhang byte_num = 4;
119bb0dc108SYing Zhang code_len = 0;
120bb0dc108SYing Zhang for (i = 0; i < byte_num; i++) {
121bb0dc108SYing Zhang val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i);
122bb0dc108SYing Zhang code_len = (code_len << 8) + val;
123bb0dc108SYing Zhang }
124bb0dc108SYing Zhang code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS;
125bb0dc108SYing Zhang /*
126bb0dc108SYing Zhang * Load U-Boot image from mmc into RAM
127bb0dc108SYing Zhang */
1284520a2f2SPriyanka Jain #endif
129bb0dc108SYing Zhang blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
130bb0dc108SYing Zhang blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len;
131*7c4213f6SStephen Warren err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
132bb0dc108SYing Zhang (uchar *)CONFIG_SYS_MMC_U_BOOT_DST);
133bb0dc108SYing Zhang if (err != blk_cnt) {
134bb0dc108SYing Zhang puts("spl: mmc read failed!!\n");
135613ab32cSPrabhakar Kushwaha #ifndef CONFIG_FSL_CORENET
136bb0dc108SYing Zhang free(tmp_buf);
137613ab32cSPrabhakar Kushwaha #endif
138bb0dc108SYing Zhang hang();
139bb0dc108SYing Zhang }
140bb0dc108SYing Zhang
141bb0dc108SYing Zhang /*
142bb0dc108SYing Zhang * Clean d-cache and invalidate i-cache, to
143bb0dc108SYing Zhang * make sure that no stale data is executed.
144bb0dc108SYing Zhang */
145bb0dc108SYing Zhang flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE);
146bb0dc108SYing Zhang
147bb0dc108SYing Zhang /*
148bb0dc108SYing Zhang * Jump to U-Boot image
149bb0dc108SYing Zhang */
150bb0dc108SYing Zhang uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START;
151bb0dc108SYing Zhang (*uboot)();
152bb0dc108SYing Zhang }
153