1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2013 Freescale Semiconductor, Inc.
4  */
5 
6 #include <common.h>
7 #include <cpu_func.h>
8 #include <hang.h>
9 #include <mmc.h>
10 #include <malloc.h>
11 
12 #ifndef CFG_SYS_MMC_U_BOOT_OFFS
13 extern uchar mmc_u_boot_offs[];
14 #endif
15 
16 /*
17  * The environment variables are written to just after the u-boot image
18  * on SDCard, so we must read the MBR to get the start address and code
19  * length of the u-boot image, then calculate the address of the env.
20  */
21 #define ESDHC_BOOT_SIGNATURE_OFF 0x40
22 #define ESDHC_BOOT_SIGNATURE	0x424f4f54
23 #define ESDHC_BOOT_IMAGE_SIZE	0x48
24 #define ESDHC_BOOT_IMAGE_ADDR	0x50
25 #define MBRDBR_BOOT_SIG_55	0x1fe
26 #define MBRDBR_BOOT_SIG_AA	0x1ff
27 
28 
mmc_spl_load_image(uint32_t offs,unsigned int size,void * vdst)29 void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst)
30 {
31 	uint blk_start, blk_cnt, err;
32 
33 	struct mmc *mmc = find_mmc_device(0);
34 	if (!mmc) {
35 		puts("spl: mmc device not found!!\n");
36 		hang();
37 	}
38 
39 	if (mmc_init(mmc)) {
40 		puts("MMC init failed\n");
41 		return;
42 	}
43 
44 	blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len;
45 	blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
46 
47 	err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
48 					vdst);
49 	if (err != blk_cnt) {
50 		puts("spl: mmc read failed!!\n");
51 		hang();
52 	}
53 }
54 
55 /*
56  * The main entry for mmc booting. It's necessary that SDRAM is already
57  * configured and available since this code loads the main U-Boot image
58  * from mmc into SDRAM and starts it from there.
59  */
60 
mmc_boot(void)61 void __noreturn mmc_boot(void)
62 {
63 	__attribute__((noreturn)) void (*uboot)(void);
64 	uint blk_start, blk_cnt, err;
65 	uchar *tmp_buf;
66 	u32 blklen;
67 	u32 blk_off;
68 #ifndef CONFIG_FSL_CORENET
69 	uchar val;
70 #ifndef CONFIG_SPL_FSL_PBL
71 	u32 val32;
72 #endif
73 	uint i, byte_num;
74 	u32 sector;
75 #endif
76 	u32 offset, code_len;
77 	struct mmc *mmc;
78 
79 	mmc = find_mmc_device(0);
80 	if (!mmc) {
81 		puts("spl: mmc device not found!!\n");
82 		hang();
83 	}
84 
85 	if (mmc_init(mmc)) {
86 		puts("spl: mmc device init failed!\n");
87 		hang();
88 	}
89 
90 	blklen = mmc->read_bl_len;
91 	if (blklen < 512)
92 		blklen = 512;
93 	tmp_buf = malloc(blklen);
94 	if (!tmp_buf) {
95 		puts("spl: malloc memory failed!!\n");
96 		hang();
97 	}
98 
99 #ifdef CONFIG_FSL_CORENET
100 	offset = CFG_SYS_MMC_U_BOOT_OFFS;
101 #else
102 	sector = 0;
103 again:
104 	memset(tmp_buf, 0, blklen);
105 
106 	/*
107 	* Read source addr from sd card
108 	*/
109 	blk_start = (sector * 512) / mmc->read_bl_len;
110 	blk_off = (sector * 512) % mmc->read_bl_len;
111 	blk_cnt = DIV_ROUND_UP(512,  mmc->read_bl_len);
112 	err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, tmp_buf);
113 	if (err != blk_cnt) {
114 		puts("spl: mmc read failed!!\n");
115 		hang();
116 	}
117 
118 #ifdef CONFIG_SPL_FSL_PBL
119 	val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_55);
120 	if (0x55 != val) {
121 		puts("spl: mmc MBR/DBR signature is not valid!!\n");
122 		hang();
123 	}
124 	val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_AA);
125 	if (0xAA != val) {
126 		puts("spl: mmc MBR/DBR signature is not valid!!\n");
127 		hang();
128 	}
129 #else
130 	/*
131 	 * Booting from On-Chip ROM (eSDHC or eSPI), Document Number: AN3659, Rev. 2, 06/2012.
132 	 * Pre-PBL BootROMs (MPC8536E, MPC8569E, P2020, P1011, P1012, P1013, P1020, P1021, P1022)
133 	 * require custom BOOT signature on sector 0 and MBR/DBR signature is not required at all.
134 	 */
135 	byte_num = 4;
136 	val32 = 0;
137 	for (i = 0; i < byte_num; i++) {
138 		val = *(tmp_buf + blk_off + ESDHC_BOOT_SIGNATURE_OFF + i);
139 		val32 = (val32 << 8) + val;
140 	}
141 	if (val32 != ESDHC_BOOT_SIGNATURE) {
142 		/* BOOT signature may be on the first 24 sectors (each being 512 bytes) */
143 		if (++sector < 24)
144 			goto again;
145 		puts("spl: mmc BOOT signature is not valid!!\n");
146 		hang();
147 	}
148 #endif
149 
150 	byte_num = 4;
151 	offset = 0;
152 	for (i = 0; i < byte_num; i++) {
153 		val = *(tmp_buf + blk_off + ESDHC_BOOT_IMAGE_ADDR + i);
154 		offset = (offset << 8) + val;
155 	}
156 #ifndef CFG_SYS_MMC_U_BOOT_OFFS
157 	offset += (ulong)&mmc_u_boot_offs - CONFIG_SPL_TEXT_BASE;
158 #else
159 	offset += CFG_SYS_MMC_U_BOOT_OFFS;
160 #endif
161 #endif
162 	/*
163 	* Load U-Boot image from mmc into RAM
164 	*/
165 	code_len = CFG_SYS_MMC_U_BOOT_SIZE;
166 	blk_start = offset / mmc->read_bl_len;
167 	blk_off = offset % mmc->read_bl_len;
168 	blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len + 1;
169 	if (blk_off) {
170 		err = mmc->block_dev.block_read(&mmc->block_dev,
171 						blk_start, 1, tmp_buf);
172 		if (err != 1) {
173 			puts("spl: mmc read failed!!\n");
174 			hang();
175 		}
176 		blk_start++;
177 	}
178 	err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
179 					(uchar *)CFG_SYS_MMC_U_BOOT_DST +
180 					(blk_off ? (mmc->read_bl_len - blk_off) : 0));
181 	if (err != blk_cnt) {
182 		puts("spl: mmc read failed!!\n");
183 		free(tmp_buf);
184 		hang();
185 	}
186 	/*
187 	 * SDHC DMA may erase bytes at dst + bl_len - blk_off - 8
188 	 * due to unaligned access. So copy leading bytes from tmp_buf
189 	 * after SDHC DMA transfer.
190 	 */
191 	if (blk_off)
192 		memcpy((uchar *)CFG_SYS_MMC_U_BOOT_DST,
193 		       tmp_buf + blk_off, mmc->read_bl_len - blk_off);
194 
195 	/*
196 	* Clean d-cache and invalidate i-cache, to
197 	* make sure that no stale data is executed.
198 	*/
199 	flush_cache(CFG_SYS_MMC_U_BOOT_DST, CFG_SYS_MMC_U_BOOT_SIZE);
200 
201 	/*
202 	* Jump to U-Boot image
203 	*/
204 	uboot = (void *)CFG_SYS_MMC_U_BOOT_START;
205 	(*uboot)();
206 }
207