xref: /openbmc/u-boot/common/spl/spl_mmc.c (revision 60031375ae63a1f0897d05f0c7a1123ae0992c27)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2ade8a1a6SYing Zhang /*
3ade8a1a6SYing Zhang  * (C) Copyright 2010
4ade8a1a6SYing Zhang  * Texas Instruments, <www.ti.com>
5ade8a1a6SYing Zhang  *
6ade8a1a6SYing Zhang  * Aneesh V <aneesh@ti.com>
7ade8a1a6SYing Zhang  */
8ade8a1a6SYing Zhang #include <common.h>
9dc3dedfeSSimon Glass #include <dm.h>
10ade8a1a6SYing Zhang #include <spl.h>
1191199f4aSPaul Kocialkowski #include <linux/compiler.h>
1236afd451SNikita Kiryanov #include <errno.h>
13ade8a1a6SYing Zhang #include <asm/u-boot.h>
144188ba32SNikita Kiryanov #include <errno.h>
15ade8a1a6SYing Zhang #include <mmc.h>
16e4c444b3STom Rini #include <image.h>
17ade8a1a6SYing Zhang 
mmc_load_legacy(struct spl_image_info * spl_image,struct mmc * mmc,ulong sector,struct image_header * header)182a2ee2acSSimon Glass static int mmc_load_legacy(struct spl_image_info *spl_image, struct mmc *mmc,
192a2ee2acSSimon Glass 			   ulong sector, struct image_header *header)
20ade8a1a6SYing Zhang {
21ade8a1a6SYing Zhang 	u32 image_size_sectors;
2296debd1fSSimon Glass 	unsigned long count;
237e0f2267SMarek Vasut 	int ret;
24e4c444b3STom Rini 
252a2ee2acSSimon Glass 	ret = spl_parse_image_header(spl_image, header);
267e0f2267SMarek Vasut 	if (ret)
277e0f2267SMarek Vasut 		return ret;
287e0f2267SMarek Vasut 
29ade8a1a6SYing Zhang 	/* convert size to sectors - round up */
302a2ee2acSSimon Glass 	image_size_sectors = (spl_image->size + mmc->read_bl_len - 1) /
31ade8a1a6SYing Zhang 			     mmc->read_bl_len;
32ade8a1a6SYing Zhang 
33ade8a1a6SYing Zhang 	/* Read the header too to avoid extra memcpy */
34ef5609c3SSimon Glass 	count = blk_dread(mmc_get_blk_desc(mmc), sector, image_size_sectors,
352a2ee2acSSimon Glass 			  (void *)(ulong)spl_image->load_addr);
3611e1479bSAndre Przywara 	debug("read %x sectors to %lx\n", image_size_sectors,
372a2ee2acSSimon Glass 	      spl_image->load_addr);
3896debd1fSSimon Glass 	if (count != image_size_sectors)
3996debd1fSSimon Glass 		return -EIO;
4096debd1fSSimon Glass 
4196debd1fSSimon Glass 	return 0;
4296debd1fSSimon Glass }
4396debd1fSSimon Glass 
h_spl_load_read(struct spl_load_info * load,ulong sector,ulong count,void * buf)4496debd1fSSimon Glass static ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
4596debd1fSSimon Glass 			     ulong count, void *buf)
4696debd1fSSimon Glass {
4796debd1fSSimon Glass 	struct mmc *mmc = load->dev;
4896debd1fSSimon Glass 
49ef5609c3SSimon Glass 	return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf);
5096debd1fSSimon Glass }
5196debd1fSSimon Glass 
52b016b585SSeung-Woo Kim static __maybe_unused
mmc_load_image_raw_sector(struct spl_image_info * spl_image,struct mmc * mmc,unsigned long sector)53b016b585SSeung-Woo Kim int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
542a2ee2acSSimon Glass 			      struct mmc *mmc, unsigned long sector)
5596debd1fSSimon Glass {
5696debd1fSSimon Glass 	unsigned long count;
5796debd1fSSimon Glass 	struct image_header *header;
5804ce5427SMarek Vasut 	struct blk_desc *bd = mmc_get_blk_desc(mmc);
5996debd1fSSimon Glass 	int ret = 0;
6096debd1fSSimon Glass 
6104ce5427SMarek Vasut 	header = spl_get_load_buffer(-sizeof(*header), bd->blksz);
6296debd1fSSimon Glass 
6396debd1fSSimon Glass 	/* read image header to find the image size & load address */
6404ce5427SMarek Vasut 	count = blk_dread(bd, sector, 1, header);
6596debd1fSSimon Glass 	debug("hdr read sector %lx, count=%lu\n", sector, count);
6696debd1fSSimon Glass 	if (count == 0) {
6796debd1fSSimon Glass 		ret = -EIO;
6896debd1fSSimon Glass 		goto end;
6996debd1fSSimon Glass 	}
7096debd1fSSimon Glass 
714976f482SMasahiro Yamada 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
724976f482SMasahiro Yamada 	    image_get_magic(header) == FDT_MAGIC) {
7396debd1fSSimon Glass 		struct spl_load_info load;
7496debd1fSSimon Glass 
7596debd1fSSimon Glass 		debug("Found FIT\n");
7696debd1fSSimon Glass 		load.dev = mmc;
7796debd1fSSimon Glass 		load.priv = NULL;
78eafd5410SLokesh Vutla 		load.filename = NULL;
7996debd1fSSimon Glass 		load.bl_len = mmc->read_bl_len;
8096debd1fSSimon Glass 		load.read = h_spl_load_read;
81f4d7d859SSimon Glass 		ret = spl_load_simple_fit(spl_image, &load, sector, header);
824976f482SMasahiro Yamada 	} else {
832a2ee2acSSimon Glass 		ret = mmc_load_legacy(spl_image, mmc, sector, header);
8496debd1fSSimon Glass 	}
85ade8a1a6SYing Zhang 
86ade8a1a6SYing Zhang end:
8796debd1fSSimon Glass 	if (ret) {
888112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
895bbf4099SFabio Estevam 		puts("mmc_load_image_raw_sector: mmc block read error\n");
908112f5faSPaul Burton #endif
913bc37b6dSPaul Kocialkowski 		return -1;
921ec26469SPaul Kocialkowski 	}
933bc37b6dSPaul Kocialkowski 
943bc37b6dSPaul Kocialkowski 	return 0;
95ade8a1a6SYing Zhang }
96ade8a1a6SYing Zhang 
spl_mmc_get_device_index(u32 boot_device)97207d8b35SMasahiro Yamada static int spl_mmc_get_device_index(u32 boot_device)
98a1e56cf6SNikita Kiryanov {
99a1e56cf6SNikita Kiryanov 	switch (boot_device) {
100a1e56cf6SNikita Kiryanov 	case BOOT_DEVICE_MMC1:
101a1e56cf6SNikita Kiryanov 		return 0;
102a1e56cf6SNikita Kiryanov 	case BOOT_DEVICE_MMC2:
103a1e56cf6SNikita Kiryanov 	case BOOT_DEVICE_MMC2_2:
104a1e56cf6SNikita Kiryanov 		return 1;
105a1e56cf6SNikita Kiryanov 	}
106a1e56cf6SNikita Kiryanov 
107a1e56cf6SNikita Kiryanov #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
108a1e56cf6SNikita Kiryanov 	printf("spl: unsupported mmc boot device.\n");
109a1e56cf6SNikita Kiryanov #endif
110a1e56cf6SNikita Kiryanov 
111a1e56cf6SNikita Kiryanov 	return -ENODEV;
112a1e56cf6SNikita Kiryanov }
113a1e56cf6SNikita Kiryanov 
spl_mmc_find_device(struct mmc ** mmcp,u32 boot_device)11499c7a51aSSimon Glass static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
1154188ba32SNikita Kiryanov {
116c4d660d4SSimon Glass #if CONFIG_IS_ENABLED(DM_MMC)
1174188ba32SNikita Kiryanov 	struct udevice *dev;
118b4857aa9SSimon Glass #endif
119a1e56cf6SNikita Kiryanov 	int err, mmc_dev;
120a1e56cf6SNikita Kiryanov 
121a1e56cf6SNikita Kiryanov 	mmc_dev = spl_mmc_get_device_index(boot_device);
122a1e56cf6SNikita Kiryanov 	if (mmc_dev < 0)
123a1e56cf6SNikita Kiryanov 		return mmc_dev;
1244188ba32SNikita Kiryanov 
1254188ba32SNikita Kiryanov 	err = mmc_initialize(NULL);
1264188ba32SNikita Kiryanov 	if (err) {
1274188ba32SNikita Kiryanov #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
1284188ba32SNikita Kiryanov 		printf("spl: could not initialize mmc. error: %d\n", err);
1294188ba32SNikita Kiryanov #endif
1304188ba32SNikita Kiryanov 		return err;
1314188ba32SNikita Kiryanov 	}
1324188ba32SNikita Kiryanov 
133c4d660d4SSimon Glass #if CONFIG_IS_ENABLED(DM_MMC)
134a1e56cf6SNikita Kiryanov 	err = uclass_get_device(UCLASS_MMC, mmc_dev, &dev);
135b4857aa9SSimon Glass 	if (!err)
136b4857aa9SSimon Glass 		*mmcp = mmc_get_mmc_dev(dev);
137b4857aa9SSimon Glass #else
138b4857aa9SSimon Glass 	*mmcp = find_mmc_device(mmc_dev);
139b4857aa9SSimon Glass 	err = *mmcp ? 0 : -ENODEV;
140b4857aa9SSimon Glass #endif
1414188ba32SNikita Kiryanov 	if (err) {
1424188ba32SNikita Kiryanov #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
143aa608b6cSAlex Kiernan 		printf("spl: could not find mmc device %d. error: %d\n",
144aa608b6cSAlex Kiernan 		       mmc_dev, err);
1454188ba32SNikita Kiryanov #endif
1464188ba32SNikita Kiryanov 		return err;
1474188ba32SNikita Kiryanov 	}
1484188ba32SNikita Kiryanov 
1494188ba32SNikita Kiryanov 	return 0;
1504188ba32SNikita Kiryanov }
1514188ba32SNikita Kiryanov 
152949123e3SDalon Westergreen #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
mmc_load_image_raw_partition(struct spl_image_info * spl_image,struct mmc * mmc,int partition,unsigned long sector)1532a2ee2acSSimon Glass static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
154*65f2e689SAndreas Dannenberg 					struct mmc *mmc, int partition,
155*65f2e689SAndreas Dannenberg 					unsigned long sector)
156b97300b6SPaul Kocialkowski {
157b97300b6SPaul Kocialkowski 	disk_partition_t info;
1583bc37b6dSPaul Kocialkowski 	int err;
159b97300b6SPaul Kocialkowski 
160f0fb4fa7SDalon Westergreen #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE
161f0fb4fa7SDalon Westergreen 	int type_part;
162f0fb4fa7SDalon Westergreen 	/* Only support MBR so DOS_ENTRY_NUMBERS */
163f0fb4fa7SDalon Westergreen 	for (type_part = 1; type_part <= DOS_ENTRY_NUMBERS; type_part++) {
164f0fb4fa7SDalon Westergreen 		err = part_get_info(mmc_get_blk_desc(mmc), type_part, &info);
165f0fb4fa7SDalon Westergreen 		if (err)
166f0fb4fa7SDalon Westergreen 			continue;
167f0fb4fa7SDalon Westergreen 		if (info.sys_ind ==
168f0fb4fa7SDalon Westergreen 			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE) {
169f0fb4fa7SDalon Westergreen 			partition = type_part;
170f0fb4fa7SDalon Westergreen 			break;
171f0fb4fa7SDalon Westergreen 		}
172f0fb4fa7SDalon Westergreen 	}
173f0fb4fa7SDalon Westergreen #endif
174f0fb4fa7SDalon Westergreen 
1751e2b3ef8SSimon Glass 	err = part_get_info(mmc_get_blk_desc(mmc), partition, &info);
1763bc37b6dSPaul Kocialkowski 	if (err) {
177b97300b6SPaul Kocialkowski #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
1781ec26469SPaul Kocialkowski 		puts("spl: partition error\n");
179b97300b6SPaul Kocialkowski #endif
180b97300b6SPaul Kocialkowski 		return -1;
181b97300b6SPaul Kocialkowski 	}
182b97300b6SPaul Kocialkowski 
18338fed8abSSemen Protsenko #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
184*65f2e689SAndreas Dannenberg 	return mmc_load_image_raw_sector(spl_image, mmc, info.start + sector);
1854bfcc54cSStefan Roese #else
1862a2ee2acSSimon Glass 	return mmc_load_image_raw_sector(spl_image, mmc, info.start);
1874bfcc54cSStefan Roese #endif
188b97300b6SPaul Kocialkowski }
189b97300b6SPaul Kocialkowski #endif
190b97300b6SPaul Kocialkowski 
1912b75b0adSPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT
mmc_load_image_raw_os(struct spl_image_info * spl_image,struct mmc * mmc)1922a2ee2acSSimon Glass static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
1932a2ee2acSSimon Glass 				 struct mmc *mmc)
1942b75b0adSPeter Korsgaard {
195811906aeSLokesh Vutla 	int ret;
19691199f4aSPaul Kocialkowski 
1977267fbf7SYork Sun #if defined(CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR)
1987267fbf7SYork Sun 	unsigned long count;
1997267fbf7SYork Sun 
20087bce4e5SSimon Glass 	count = blk_dread(mmc_get_blk_desc(mmc),
2012b75b0adSPeter Korsgaard 		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
2022b75b0adSPeter Korsgaard 		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
20391199f4aSPaul Kocialkowski 		(void *) CONFIG_SYS_SPL_ARGS_ADDR);
2049585dd3fSTom Rini 	if (count != CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS) {
2058112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
2065bbf4099SFabio Estevam 		puts("mmc_load_image_raw_os: mmc block read error\n");
2078112f5faSPaul Burton #endif
2082b75b0adSPeter Korsgaard 		return -1;
2092b75b0adSPeter Korsgaard 	}
2107267fbf7SYork Sun #endif	/* CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR */
2112b75b0adSPeter Korsgaard 
2122a2ee2acSSimon Glass 	ret = mmc_load_image_raw_sector(spl_image, mmc,
213b97300b6SPaul Kocialkowski 		CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR);
214811906aeSLokesh Vutla 	if (ret)
215811906aeSLokesh Vutla 		return ret;
216811906aeSLokesh Vutla 
2172a2ee2acSSimon Glass 	if (spl_image->os != IH_OS_LINUX) {
218811906aeSLokesh Vutla 		puts("Expected Linux image is not found. Trying to start U-boot\n");
219811906aeSLokesh Vutla 		return -ENOENT;
220811906aeSLokesh Vutla 	}
221811906aeSLokesh Vutla 
222811906aeSLokesh Vutla 	return 0;
2232b75b0adSPeter Korsgaard }
224339245b7SNikita Kiryanov #else
spl_start_uboot(void)225339245b7SNikita Kiryanov int spl_start_uboot(void)
226339245b7SNikita Kiryanov {
227339245b7SNikita Kiryanov 	return 1;
228339245b7SNikita Kiryanov }
mmc_load_image_raw_os(struct spl_image_info * spl_image,struct mmc * mmc)2292a2ee2acSSimon Glass static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
2302a2ee2acSSimon Glass 				 struct mmc *mmc)
231339245b7SNikita Kiryanov {
232339245b7SNikita Kiryanov 	return -ENOSYS;
233339245b7SNikita Kiryanov }
2342b75b0adSPeter Korsgaard #endif
2352b75b0adSPeter Korsgaard 
236f52b7293SNikita Kiryanov #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
spl_mmc_do_fs_boot(struct spl_image_info * spl_image,struct mmc * mmc,const char * filename)237*65f2e689SAndreas Dannenberg static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
238*65f2e689SAndreas Dannenberg 			      const char *filename)
239f52b7293SNikita Kiryanov {
240f52b7293SNikita Kiryanov 	int err = -ENOSYS;
241f52b7293SNikita Kiryanov 
2420c3a9ed4STien Fong Chee #ifdef CONFIG_SPL_FS_FAT
243f52b7293SNikita Kiryanov 	if (!spl_start_uboot()) {
244710e9ca5SSimon Glass 		err = spl_load_image_fat_os(spl_image, mmc_get_blk_desc(mmc),
245f52b7293SNikita Kiryanov 			CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
246f52b7293SNikita Kiryanov 		if (!err)
247f52b7293SNikita Kiryanov 			return err;
248f52b7293SNikita Kiryanov 	}
249f52b7293SNikita Kiryanov #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
250710e9ca5SSimon Glass 	err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc),
251f52b7293SNikita Kiryanov 				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
252*65f2e689SAndreas Dannenberg 				 filename);
253f52b7293SNikita Kiryanov 	if (!err)
254f52b7293SNikita Kiryanov 		return err;
255f52b7293SNikita Kiryanov #endif
256f52b7293SNikita Kiryanov #endif
257f4b40924STien Fong Chee #ifdef CONFIG_SPL_FS_EXT4
258f52b7293SNikita Kiryanov 	if (!spl_start_uboot()) {
2591a92541dSMichal Simek 		err = spl_load_image_ext_os(spl_image, mmc_get_blk_desc(mmc),
260f52b7293SNikita Kiryanov 			CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
261f52b7293SNikita Kiryanov 		if (!err)
262f52b7293SNikita Kiryanov 			return err;
263f52b7293SNikita Kiryanov 	}
264f52b7293SNikita Kiryanov #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
2651a92541dSMichal Simek 	err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc),
266f52b7293SNikita Kiryanov 				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
267*65f2e689SAndreas Dannenberg 				 filename);
268f52b7293SNikita Kiryanov 	if (!err)
269f52b7293SNikita Kiryanov 		return err;
270f52b7293SNikita Kiryanov #endif
271f52b7293SNikita Kiryanov #endif
272f52b7293SNikita Kiryanov 
273f4b40924STien Fong Chee #if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
274f52b7293SNikita Kiryanov 	err = -ENOENT;
275f52b7293SNikita Kiryanov #endif
276f52b7293SNikita Kiryanov 
277f52b7293SNikita Kiryanov 	return err;
278f52b7293SNikita Kiryanov }
279f52b7293SNikita Kiryanov #else
spl_mmc_do_fs_boot(struct spl_image_info * spl_image,struct mmc * mmc,const char * filename)280*65f2e689SAndreas Dannenberg static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
281*65f2e689SAndreas Dannenberg 			      const char *filename)
282f52b7293SNikita Kiryanov {
283f52b7293SNikita Kiryanov 	return -ENOSYS;
284f52b7293SNikita Kiryanov }
285f52b7293SNikita Kiryanov #endif
286f52b7293SNikita Kiryanov 
spl_boot_mode(const u32 boot_device)287d695d662SLukasz Majewski u32 __weak spl_boot_mode(const u32 boot_device)
288d695d662SLukasz Majewski {
289f4b40924STien Fong Chee #if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
290d695d662SLukasz Majewski 	return MMCSD_MODE_FS;
291d695d662SLukasz Majewski #elif defined(CONFIG_SUPPORT_EMMC_BOOT)
292d695d662SLukasz Majewski 	return MMCSD_MODE_EMMCBOOT;
293d695d662SLukasz Majewski #else
294d695d662SLukasz Majewski 	return MMCSD_MODE_RAW;
295d695d662SLukasz Majewski #endif
296d695d662SLukasz Majewski }
297d695d662SLukasz Majewski 
29835a66960SPatrick Delaunay #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
29935a66960SPatrick Delaunay __weak
spl_boot_partition(const u32 boot_device)30035a66960SPatrick Delaunay int spl_boot_partition(const u32 boot_device)
30135a66960SPatrick Delaunay {
30235a66960SPatrick Delaunay 	return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION;
30335a66960SPatrick Delaunay }
30435a66960SPatrick Delaunay #endif
30535a66960SPatrick Delaunay 
spl_mmc_load(struct spl_image_info * spl_image,struct spl_boot_device * bootdev,const char * filename,int raw_part,unsigned long raw_sect)306*65f2e689SAndreas Dannenberg int spl_mmc_load(struct spl_image_info *spl_image,
307*65f2e689SAndreas Dannenberg 		 struct spl_boot_device *bootdev,
308*65f2e689SAndreas Dannenberg 		 const char *filename,
309*65f2e689SAndreas Dannenberg 		 int raw_part,
310*65f2e689SAndreas Dannenberg 		 unsigned long raw_sect)
311ade8a1a6SYing Zhang {
312*65f2e689SAndreas Dannenberg 	static struct mmc *mmc;
313ade8a1a6SYing Zhang 	u32 boot_mode;
314dc3dedfeSSimon Glass 	int err = 0;
31591199f4aSPaul Kocialkowski 	__maybe_unused int part;
316ade8a1a6SYing Zhang 
317*65f2e689SAndreas Dannenberg 	/* Perform peripheral init only once */
318*65f2e689SAndreas Dannenberg 	if (!mmc) {
319ecdfd69aSSimon Glass 		err = spl_mmc_find_device(&mmc, bootdev->boot_device);
32036afd451SNikita Kiryanov 		if (err)
32136afd451SNikita Kiryanov 			return err;
322ade8a1a6SYing Zhang 
323ade8a1a6SYing Zhang 		err = mmc_init(mmc);
324ade8a1a6SYing Zhang 		if (err) {
325*65f2e689SAndreas Dannenberg 			mmc = NULL;
3268112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
32791199f4aSPaul Kocialkowski 			printf("spl: mmc init failed with error: %d\n", err);
3288112f5faSPaul Burton #endif
32936afd451SNikita Kiryanov 			return err;
330ade8a1a6SYing Zhang 		}
331*65f2e689SAndreas Dannenberg 	}
33279adb7a2SPeter Korsgaard 
333ecdfd69aSSimon Glass 	boot_mode = spl_boot_mode(bootdev->boot_device);
33436afd451SNikita Kiryanov 	err = -EINVAL;
33591199f4aSPaul Kocialkowski 	switch (boot_mode) {
33683cdf6faSNikita Kiryanov 	case MMCSD_MODE_EMMCBOOT:
33783cdf6faSNikita Kiryanov 			/*
33883cdf6faSNikita Kiryanov 			 * We need to check what the partition is configured to.
33983cdf6faSNikita Kiryanov 			 * 1 and 2 match up to boot0 / boot1 and 7 is user data
34083cdf6faSNikita Kiryanov 			 * which is the first physical partition (0).
34183cdf6faSNikita Kiryanov 			 */
34283cdf6faSNikita Kiryanov 			part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
34383cdf6faSNikita Kiryanov 
34483cdf6faSNikita Kiryanov 			if (part == 7)
34583cdf6faSNikita Kiryanov 				part = 0;
34683cdf6faSNikita Kiryanov 
347b5b838f1SMarek Vasut 			if (CONFIG_IS_ENABLED(MMC_TINY))
348b5b838f1SMarek Vasut 				err = mmc_switch_part(mmc, part);
349b5b838f1SMarek Vasut 			else
35069f45cd5SSimon Glass 				err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part);
351b5b838f1SMarek Vasut 
35236afd451SNikita Kiryanov 			if (err) {
35383cdf6faSNikita Kiryanov #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
35483cdf6faSNikita Kiryanov 				puts("spl: mmc partition switch failed\n");
35583cdf6faSNikita Kiryanov #endif
35636afd451SNikita Kiryanov 				return err;
35783cdf6faSNikita Kiryanov 			}
35883cdf6faSNikita Kiryanov 			/* Fall through */
35991199f4aSPaul Kocialkowski 	case MMCSD_MODE_RAW:
36091199f4aSPaul Kocialkowski 		debug("spl: mmc boot mode: raw\n");
36191199f4aSPaul Kocialkowski 
36291199f4aSPaul Kocialkowski 		if (!spl_start_uboot()) {
3632a2ee2acSSimon Glass 			err = mmc_load_image_raw_os(spl_image, mmc);
36491199f4aSPaul Kocialkowski 			if (!err)
36536afd451SNikita Kiryanov 				return err;
36691199f4aSPaul Kocialkowski 		}
367949123e3SDalon Westergreen #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
368*65f2e689SAndreas Dannenberg 		err = mmc_load_image_raw_partition(spl_image, mmc, raw_part,
369*65f2e689SAndreas Dannenberg 						   raw_sect);
37091199f4aSPaul Kocialkowski 		if (!err)
37136afd451SNikita Kiryanov 			return err;
372949123e3SDalon Westergreen #endif
37338fed8abSSemen Protsenko #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
374*65f2e689SAndreas Dannenberg 		err = mmc_load_image_raw_sector(spl_image, mmc, raw_sect);
3753ae8f4c8SPaul Kocialkowski 		if (!err)
37636afd451SNikita Kiryanov 			return err;
3773ae8f4c8SPaul Kocialkowski #endif
37886a0df73SGuillaume GARDET 		/* If RAW mode fails, try FS mode. */
37991199f4aSPaul Kocialkowski 	case MMCSD_MODE_FS:
38091199f4aSPaul Kocialkowski 		debug("spl: mmc boot mode: fs\n");
38191199f4aSPaul Kocialkowski 
382*65f2e689SAndreas Dannenberg 		err = spl_mmc_do_fs_boot(spl_image, mmc, filename);
38391199f4aSPaul Kocialkowski 		if (!err)
38436afd451SNikita Kiryanov 			return err;
385f52b7293SNikita Kiryanov 
386fd61d399SNikita Kiryanov 		break;
3878112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
388fd61d399SNikita Kiryanov 	default:
38991199f4aSPaul Kocialkowski 		puts("spl: mmc: wrong boot mode\n");
3908112f5faSPaul Burton #endif
391ade8a1a6SYing Zhang 	}
392fd61d399SNikita Kiryanov 
39336afd451SNikita Kiryanov 	return err;
394ade8a1a6SYing Zhang }
3950fed9c7eSSimon Glass 
spl_mmc_load_image(struct spl_image_info * spl_image,struct spl_boot_device * bootdev)396*65f2e689SAndreas Dannenberg int spl_mmc_load_image(struct spl_image_info *spl_image,
397*65f2e689SAndreas Dannenberg 		       struct spl_boot_device *bootdev)
398*65f2e689SAndreas Dannenberg {
399*65f2e689SAndreas Dannenberg 	return spl_mmc_load(spl_image, bootdev,
400*65f2e689SAndreas Dannenberg #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
401*65f2e689SAndreas Dannenberg 			    CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
402*65f2e689SAndreas Dannenberg #else
403*65f2e689SAndreas Dannenberg 			    NULL,
404*65f2e689SAndreas Dannenberg #endif
405*65f2e689SAndreas Dannenberg #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
406*65f2e689SAndreas Dannenberg 			    spl_boot_partition(bootdev->boot_device),
407*65f2e689SAndreas Dannenberg #else
408*65f2e689SAndreas Dannenberg 			    0,
409*65f2e689SAndreas Dannenberg #endif
410*65f2e689SAndreas Dannenberg #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
411*65f2e689SAndreas Dannenberg 			    CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
412*65f2e689SAndreas Dannenberg #else
413*65f2e689SAndreas Dannenberg 			    0);
414*65f2e689SAndreas Dannenberg #endif
415*65f2e689SAndreas Dannenberg }
416*65f2e689SAndreas Dannenberg 
417ebc4ef61SSimon Glass SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
418ebc4ef61SSimon Glass SPL_LOAD_IMAGE_METHOD("MMC2", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image);
419ebc4ef61SSimon Glass SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image);
420