xref: /openbmc/u-boot/common/spl/spl_mmc.c (revision 7dd12830)
1 /*
2  * (C) Copyright 2010
3  * Texas Instruments, <www.ti.com>
4  *
5  * Aneesh V <aneesh@ti.com>
6  *
7  * SPDX-License-Identifier:	GPL-2.0+
8  */
9 #include <common.h>
10 #include <dm.h>
11 #include <spl.h>
12 #include <linux/compiler.h>
13 #include <errno.h>
14 #include <asm/u-boot.h>
15 #include <errno.h>
16 #include <mmc.h>
17 #include <image.h>
18 
19 DECLARE_GLOBAL_DATA_PTR;
20 
21 static int mmc_load_legacy(struct mmc *mmc, ulong sector,
22 			   struct image_header *header)
23 {
24 	u32 image_size_sectors;
25 	unsigned long count;
26 	int ret;
27 
28 	ret = spl_parse_image_header(header);
29 	if (ret)
30 		return ret;
31 
32 	/* convert size to sectors - round up */
33 	image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) /
34 			     mmc->read_bl_len;
35 
36 	/* Read the header too to avoid extra memcpy */
37 	count = mmc->block_dev.block_read(&mmc->block_dev, sector,
38 					  image_size_sectors,
39 					  (void *)(ulong)spl_image.load_addr);
40 	debug("read %x sectors to %x\n", image_size_sectors,
41 	      spl_image.load_addr);
42 	if (count != image_size_sectors)
43 		return -EIO;
44 
45 	return 0;
46 }
47 
48 static ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
49 			     ulong count, void *buf)
50 {
51 	struct mmc *mmc = load->dev;
52 
53 	return mmc->block_dev.block_read(&mmc->block_dev, sector, count, buf);
54 }
55 
56 static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector)
57 {
58 	unsigned long count;
59 	struct image_header *header;
60 	int ret = 0;
61 
62 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
63 					 sizeof(struct image_header));
64 
65 	/* read image header to find the image size & load address */
66 	count = mmc->block_dev.block_read(&mmc->block_dev, sector, 1, header);
67 	debug("hdr read sector %lx, count=%lu\n", sector, count);
68 	if (count == 0) {
69 		ret = -EIO;
70 		goto end;
71 	}
72 
73 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
74 	    image_get_magic(header) == FDT_MAGIC) {
75 		struct spl_load_info load;
76 
77 		debug("Found FIT\n");
78 		load.dev = mmc;
79 		load.priv = NULL;
80 		load.filename = NULL;
81 		load.bl_len = mmc->read_bl_len;
82 		load.read = h_spl_load_read;
83 		ret = spl_load_simple_fit(&load, sector, header);
84 	} else {
85 		ret = mmc_load_legacy(mmc, sector, header);
86 	}
87 
88 end:
89 	if (ret) {
90 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
91 		puts("mmc_load_image_raw_sector: mmc block read error\n");
92 #endif
93 		return -1;
94 	}
95 
96 	return 0;
97 }
98 
99 int spl_mmc_get_device_index(u32 boot_device)
100 {
101 	switch (boot_device) {
102 	case BOOT_DEVICE_MMC1:
103 		return 0;
104 	case BOOT_DEVICE_MMC2:
105 	case BOOT_DEVICE_MMC2_2:
106 		return 1;
107 	}
108 
109 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
110 	printf("spl: unsupported mmc boot device.\n");
111 #endif
112 
113 	return -ENODEV;
114 }
115 
116 static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
117 {
118 #ifdef CONFIG_DM_MMC
119 	struct udevice *dev;
120 #endif
121 	int err, mmc_dev;
122 
123 	mmc_dev = spl_mmc_get_device_index(boot_device);
124 	if (mmc_dev < 0)
125 		return mmc_dev;
126 
127 	err = mmc_initialize(NULL);
128 	if (err) {
129 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
130 		printf("spl: could not initialize mmc. error: %d\n", err);
131 #endif
132 		return err;
133 	}
134 
135 #ifdef CONFIG_DM_MMC
136 	err = uclass_get_device(UCLASS_MMC, mmc_dev, &dev);
137 	if (!err)
138 		*mmcp = mmc_get_mmc_dev(dev);
139 #else
140 	*mmcp = find_mmc_device(mmc_dev);
141 	err = *mmcp ? 0 : -ENODEV;
142 #endif
143 	if (err) {
144 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
145 		printf("spl: could not find mmc device. error: %d\n", err);
146 #endif
147 		return err;
148 	}
149 
150 	return 0;
151 }
152 
153 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
154 static int mmc_load_image_raw_partition(struct mmc *mmc, int partition)
155 {
156 	disk_partition_t info;
157 	int err;
158 
159 	err = part_get_info(&mmc->block_dev, partition, &info);
160 	if (err) {
161 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
162 		puts("spl: partition error\n");
163 #endif
164 		return -1;
165 	}
166 
167 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
168 	return mmc_load_image_raw_sector(mmc, info.start +
169 					 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
170 #else
171 	return mmc_load_image_raw_sector(mmc, info.start);
172 #endif
173 }
174 #else
175 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION -1
176 static int mmc_load_image_raw_partition(struct mmc *mmc, int partition)
177 {
178 	return -ENOSYS;
179 }
180 #endif
181 
182 #ifdef CONFIG_SPL_OS_BOOT
183 static int mmc_load_image_raw_os(struct mmc *mmc)
184 {
185 	unsigned long count;
186 	int ret;
187 
188 	count = mmc->block_dev.block_read(&mmc->block_dev,
189 		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
190 		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
191 		(void *) CONFIG_SYS_SPL_ARGS_ADDR);
192 	if (count == 0) {
193 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
194 		puts("mmc_load_image_raw_os: mmc block read error\n");
195 #endif
196 		return -1;
197 	}
198 
199 	ret = mmc_load_image_raw_sector(mmc,
200 		CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR);
201 	if (ret)
202 		return ret;
203 
204 	if (spl_image.os != IH_OS_LINUX) {
205 		puts("Expected Linux image is not found. Trying to start U-boot\n");
206 		return -ENOENT;
207 	}
208 
209 	return 0;
210 }
211 #else
212 int spl_start_uboot(void)
213 {
214 	return 1;
215 }
216 static int mmc_load_image_raw_os(struct mmc *mmc)
217 {
218 	return -ENOSYS;
219 }
220 #endif
221 
222 #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
223 int spl_mmc_do_fs_boot(struct mmc *mmc)
224 {
225 	int err = -ENOSYS;
226 
227 #ifdef CONFIG_SPL_FAT_SUPPORT
228 	if (!spl_start_uboot()) {
229 		err = spl_load_image_fat_os(&mmc->block_dev,
230 			CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
231 		if (!err)
232 			return err;
233 	}
234 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
235 	err = spl_load_image_fat(&mmc->block_dev,
236 				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
237 				 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
238 	if (!err)
239 		return err;
240 #endif
241 #endif
242 #ifdef CONFIG_SPL_EXT_SUPPORT
243 	if (!spl_start_uboot()) {
244 		err = spl_load_image_ext_os(&mmc->block_dev,
245 			CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
246 		if (!err)
247 			return err;
248 	}
249 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
250 	err = spl_load_image_ext(&mmc->block_dev,
251 				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
252 				 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
253 	if (!err)
254 		return err;
255 #endif
256 #endif
257 
258 #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT)
259 	err = -ENOENT;
260 #endif
261 
262 	return err;
263 }
264 #else
265 int spl_mmc_do_fs_boot(struct mmc *mmc)
266 {
267 	return -ENOSYS;
268 }
269 #endif
270 
271 int spl_mmc_load_image(u32 boot_device)
272 {
273 	struct mmc *mmc = NULL;
274 	u32 boot_mode;
275 	int err = 0;
276 	__maybe_unused int part;
277 
278 	err = spl_mmc_find_device(&mmc, boot_device);
279 	if (err)
280 		return err;
281 
282 	err = mmc_init(mmc);
283 	if (err) {
284 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
285 		printf("spl: mmc init failed with error: %d\n", err);
286 #endif
287 		return err;
288 	}
289 
290 	boot_mode = spl_boot_mode();
291 	err = -EINVAL;
292 	switch (boot_mode) {
293 	case MMCSD_MODE_EMMCBOOT:
294 			/*
295 			 * We need to check what the partition is configured to.
296 			 * 1 and 2 match up to boot0 / boot1 and 7 is user data
297 			 * which is the first physical partition (0).
298 			 */
299 			part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
300 
301 			if (part == 7)
302 				part = 0;
303 
304 			err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part);
305 			if (err) {
306 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
307 				puts("spl: mmc partition switch failed\n");
308 #endif
309 				return err;
310 			}
311 			/* Fall through */
312 	case MMCSD_MODE_RAW:
313 		debug("spl: mmc boot mode: raw\n");
314 
315 		if (!spl_start_uboot()) {
316 			err = mmc_load_image_raw_os(mmc);
317 			if (!err)
318 				return err;
319 		}
320 
321 		err = mmc_load_image_raw_partition(mmc,
322 			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION);
323 		if (!err)
324 			return err;
325 #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR)
326 		err = mmc_load_image_raw_sector(mmc,
327 			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
328 		if (!err)
329 			return err;
330 #endif
331 		/* If RAW mode fails, try FS mode. */
332 	case MMCSD_MODE_FS:
333 		debug("spl: mmc boot mode: fs\n");
334 
335 		err = spl_mmc_do_fs_boot(mmc);
336 		if (!err)
337 			return err;
338 
339 		break;
340 	case MMCSD_MODE_UNDEFINED:
341 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
342 	default:
343 		puts("spl: mmc: wrong boot mode\n");
344 #endif
345 	}
346 
347 	return err;
348 }
349