blob: c1c29c02d7edec75b5d64a186679e7755f079607 [file] [log] [blame]
Simon Schwarze21d2d82011-09-14 15:33:34 -04001/*
2 * (C) Copyright 2010
3 * Texas Instruments, <www.ti.com>
4 *
5 * Aneesh V <aneesh@ti.com>
6 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Simon Schwarze21d2d82011-09-14 15:33:34 -04008 */
9#include <common.h>
Simon Glassf22851a2015-06-23 15:38:51 -060010#include <dm.h>
Tom Rini28591df2012-08-13 12:03:19 -070011#include <spl.h>
Paul Kocialkowski0d139722015-04-27 10:20:22 +020012#include <linux/compiler.h>
Nikita Kiryanov33eefe42015-11-08 17:11:49 +020013#include <errno.h>
Simon Schwarze21d2d82011-09-14 15:33:34 -040014#include <asm/u-boot.h>
Nikita Kiryanov022ddb82015-11-08 17:11:44 +020015#include <errno.h>
Simon Schwarze21d2d82011-09-14 15:33:34 -040016#include <mmc.h>
Tom Rini1530e8a2013-06-28 14:43:01 -040017#include <image.h>
Simon Schwarze21d2d82011-09-14 15:33:34 -040018
19DECLARE_GLOBAL_DATA_PTR;
20
Paul Kocialkowski17675c82014-11-08 23:14:56 +010021static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector)
Simon Schwarze21d2d82011-09-14 15:33:34 -040022{
Paul Kocialkowski2d69f252015-05-22 12:45:35 +020023 unsigned long count;
Peter Korsgaardf2471292013-03-21 04:55:17 +000024 u32 image_size_sectors;
25 struct image_header *header;
Eric Nelsond09e59f2015-12-05 12:32:28 -070026 int dev_num = mmc->block_dev.dev;
Simon Schwarze21d2d82011-09-14 15:33:34 -040027
28 header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
Paul Kocialkowski0d139722015-04-27 10:20:22 +020029 sizeof(struct image_header));
Simon Schwarze21d2d82011-09-14 15:33:34 -040030
31 /* read image header to find the image size & load address */
Eric Nelsond09e59f2015-12-05 12:32:28 -070032 count = mmc->block_dev.block_read(dev_num, sector, 1, header);
Simon Glass5614db82015-06-23 15:38:47 -060033 debug("read sector %lx, count=%lu\n", sector, count);
Paul Kocialkowski2d69f252015-05-22 12:45:35 +020034 if (count == 0)
Simon Schwarze21d2d82011-09-14 15:33:34 -040035 goto end;
36
Simon Glass5614db82015-06-23 15:38:47 -060037 if (image_get_magic(header) != IH_MAGIC) {
38 puts("bad magic\n");
Tom Rini1530e8a2013-06-28 14:43:01 -040039 return -1;
Simon Glass5614db82015-06-23 15:38:47 -060040 }
Tom Rini1530e8a2013-06-28 14:43:01 -040041
Simon Schwarze21d2d82011-09-14 15:33:34 -040042 spl_parse_image_header(header);
43
44 /* convert size to sectors - round up */
Tom Rinia0b9fa52012-08-14 10:25:15 -070045 image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) /
Paul Kocialkowski0d139722015-04-27 10:20:22 +020046 mmc->read_bl_len;
Simon Schwarze21d2d82011-09-14 15:33:34 -040047
48 /* Read the header too to avoid extra memcpy */
Eric Nelsond09e59f2015-12-05 12:32:28 -070049 count = mmc->block_dev.block_read(dev_num, sector, image_size_sectors,
Gong Qianyu2ae45892015-07-30 14:07:12 +080050 (void *)(ulong)spl_image.load_addr);
Simon Glass5614db82015-06-23 15:38:47 -060051 debug("read %x sectors to %x\n", image_size_sectors,
52 spl_image.load_addr);
Simon Schwarze21d2d82011-09-14 15:33:34 -040053
54end:
Paul Kocialkowski01c723f2015-06-03 18:48:51 +020055 if (count == 0) {
Paul Burtona8015fd2013-09-04 16:12:24 +010056#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Paul Kocialkowski01c723f2015-06-03 18:48:51 +020057 puts("spl: mmc block read error\n");
Paul Burtona8015fd2013-09-04 16:12:24 +010058#endif
Paul Kocialkowski2d69f252015-05-22 12:45:35 +020059 return -1;
Paul Kocialkowski01c723f2015-06-03 18:48:51 +020060 }
Paul Kocialkowski2d69f252015-05-22 12:45:35 +020061
62 return 0;
Simon Schwarze21d2d82011-09-14 15:33:34 -040063}
64
Nikita Kiryanove63b2dd2015-11-08 17:11:54 +020065int spl_mmc_get_device_index(u32 boot_device)
66{
67 switch (boot_device) {
68 case BOOT_DEVICE_MMC1:
69 return 0;
70 case BOOT_DEVICE_MMC2:
71 case BOOT_DEVICE_MMC2_2:
72 return 1;
73 }
74
75#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
76 printf("spl: unsupported mmc boot device.\n");
77#endif
78
79 return -ENODEV;
80}
81
Simon Glass4faf63b2015-12-02 10:59:12 -070082static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
Nikita Kiryanov022ddb82015-11-08 17:11:44 +020083{
Simon Glass51ace322015-12-02 10:59:13 -070084#ifdef CONFIG_DM_MMC
Nikita Kiryanov022ddb82015-11-08 17:11:44 +020085 struct udevice *dev;
Simon Glass51ace322015-12-02 10:59:13 -070086#endif
Nikita Kiryanove63b2dd2015-11-08 17:11:54 +020087 int err, mmc_dev;
88
89 mmc_dev = spl_mmc_get_device_index(boot_device);
90 if (mmc_dev < 0)
91 return mmc_dev;
Nikita Kiryanov022ddb82015-11-08 17:11:44 +020092
93 err = mmc_initialize(NULL);
94 if (err) {
95#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
96 printf("spl: could not initialize mmc. error: %d\n", err);
97#endif
98 return err;
99 }
100
Simon Glass51ace322015-12-02 10:59:13 -0700101#ifdef CONFIG_DM_MMC
Nikita Kiryanove63b2dd2015-11-08 17:11:54 +0200102 err = uclass_get_device(UCLASS_MMC, mmc_dev, &dev);
Simon Glass51ace322015-12-02 10:59:13 -0700103 if (!err)
104 *mmcp = mmc_get_mmc_dev(dev);
Nikita Kiryanov022ddb82015-11-08 17:11:44 +0200105#else
Simon Glass51ace322015-12-02 10:59:13 -0700106 *mmcp = find_mmc_device(mmc_dev);
107 err = *mmcp ? 0 : -ENODEV;
108#endif
Nikita Kiryanov022ddb82015-11-08 17:11:44 +0200109 if (err) {
110#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Simon Glass51ace322015-12-02 10:59:13 -0700111 printf("spl: could not find mmc device. error: %d\n", err);
Nikita Kiryanov022ddb82015-11-08 17:11:44 +0200112#endif
113 return err;
114 }
115
Nikita Kiryanov022ddb82015-11-08 17:11:44 +0200116 return 0;
117}
Nikita Kiryanov022ddb82015-11-08 17:11:44 +0200118
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100119#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
120static int mmc_load_image_raw_partition(struct mmc *mmc, int partition)
121{
122 disk_partition_t info;
Paul Kocialkowski2d69f252015-05-22 12:45:35 +0200123 int err;
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100124
Paul Kocialkowski2d69f252015-05-22 12:45:35 +0200125 err = get_partition_info(&mmc->block_dev, partition, &info);
126 if (err) {
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100127#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Paul Kocialkowski01c723f2015-06-03 18:48:51 +0200128 puts("spl: partition error\n");
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100129#endif
130 return -1;
131 }
132
Stefan Roesed0503cd2015-07-20 11:20:39 +0200133#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
134 return mmc_load_image_raw_sector(mmc, info.start +
135 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
136#else
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100137 return mmc_load_image_raw_sector(mmc, info.start);
Stefan Roesed0503cd2015-07-20 11:20:39 +0200138#endif
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100139}
Nikita Kiryanov011cd8f2015-11-08 17:11:46 +0200140#else
141#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION -1
142static int mmc_load_image_raw_partition(struct mmc *mmc, int partition)
143{
144 return -ENOSYS;
145}
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100146#endif
147
Peter Korsgaard01b542f2013-05-13 08:36:29 +0000148#ifdef CONFIG_SPL_OS_BOOT
149static int mmc_load_image_raw_os(struct mmc *mmc)
150{
Paul Kocialkowski2d69f252015-05-22 12:45:35 +0200151 unsigned long count;
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200152
Eric Nelsond09e59f2015-12-05 12:32:28 -0700153 count = mmc->block_dev.block_read(
154 mmc->block_dev.dev,
Paul Kocialkowski2d69f252015-05-22 12:45:35 +0200155 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
156 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
157 (void *) CONFIG_SYS_SPL_ARGS_ADDR);
158 if (count == 0) {
Paul Burtona8015fd2013-09-04 16:12:24 +0100159#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Paul Kocialkowski01c723f2015-06-03 18:48:51 +0200160 puts("spl: mmc block read error\n");
Paul Burtona8015fd2013-09-04 16:12:24 +0100161#endif
Peter Korsgaard01b542f2013-05-13 08:36:29 +0000162 return -1;
163 }
164
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100165 return mmc_load_image_raw_sector(mmc,
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200166 CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR);
Peter Korsgaard01b542f2013-05-13 08:36:29 +0000167}
Nikita Kiryanovcc49f552015-11-08 17:11:45 +0200168#else
169int spl_start_uboot(void)
170{
171 return 1;
172}
173static int mmc_load_image_raw_os(struct mmc *mmc)
174{
175 return -ENOSYS;
176}
Peter Korsgaard01b542f2013-05-13 08:36:29 +0000177#endif
178
Nikita Kiryanov642648c2015-11-08 17:11:47 +0200179#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
180int spl_mmc_do_fs_boot(struct mmc *mmc)
181{
182 int err = -ENOSYS;
183
184#ifdef CONFIG_SPL_FAT_SUPPORT
185 if (!spl_start_uboot()) {
186 err = spl_load_image_fat_os(&mmc->block_dev,
187 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
188 if (!err)
189 return err;
190 }
191#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
192 err = spl_load_image_fat(&mmc->block_dev,
193 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
194 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
195 if (!err)
196 return err;
197#endif
198#endif
199#ifdef CONFIG_SPL_EXT_SUPPORT
200 if (!spl_start_uboot()) {
201 err = spl_load_image_ext_os(&mmc->block_dev,
202 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
203 if (!err)
204 return err;
205 }
206#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
207 err = spl_load_image_ext(&mmc->block_dev,
208 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
209 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
210 if (!err)
211 return err;
212#endif
213#endif
214
215#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT)
216 err = -ENOENT;
217#endif
218
219 return err;
220}
221#else
222int spl_mmc_do_fs_boot(struct mmc *mmc)
223{
224 return -ENOSYS;
225}
226#endif
227
Nikita Kiryanove63b2dd2015-11-08 17:11:54 +0200228int spl_mmc_load_image(u32 boot_device)
Simon Schwarze21d2d82011-09-14 15:33:34 -0400229{
Simon Glassa2b771c2015-12-02 10:59:11 -0700230 struct mmc *mmc = NULL;
Simon Schwarze21d2d82011-09-14 15:33:34 -0400231 u32 boot_mode;
Simon Glassf22851a2015-06-23 15:38:51 -0600232 int err = 0;
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200233 __maybe_unused int part;
Simon Schwarze21d2d82011-09-14 15:33:34 -0400234
Nikita Kiryanove63b2dd2015-11-08 17:11:54 +0200235 err = spl_mmc_find_device(&mmc, boot_device);
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200236 if (err)
237 return err;
Simon Schwarze21d2d82011-09-14 15:33:34 -0400238
Nikita Kiryanov022ddb82015-11-08 17:11:44 +0200239 err = mmc_init(mmc);
Simon Schwarze21d2d82011-09-14 15:33:34 -0400240 if (err) {
Paul Burtona8015fd2013-09-04 16:12:24 +0100241#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200242 printf("spl: mmc init failed with error: %d\n", err);
Paul Burtona8015fd2013-09-04 16:12:24 +0100243#endif
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200244 return err;
Simon Schwarze21d2d82011-09-14 15:33:34 -0400245 }
Peter Korsgaard5e5483d2013-05-13 08:36:25 +0000246
Tom Rinia76ff952012-08-14 09:19:44 -0700247 boot_mode = spl_boot_mode();
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200248 err = -EINVAL;
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200249 switch (boot_mode) {
Nikita Kiryanov2b3ae5f2015-11-08 17:11:48 +0200250 case MMCSD_MODE_EMMCBOOT:
251 /*
252 * We need to check what the partition is configured to.
253 * 1 and 2 match up to boot0 / boot1 and 7 is user data
254 * which is the first physical partition (0).
255 */
256 part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
257
258 if (part == 7)
259 part = 0;
260
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200261 err = mmc_switch_part(0, part);
262 if (err) {
Nikita Kiryanov2b3ae5f2015-11-08 17:11:48 +0200263#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
264 puts("spl: mmc partition switch failed\n");
265#endif
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200266 return err;
Nikita Kiryanov2b3ae5f2015-11-08 17:11:48 +0200267 }
268 /* Fall through */
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200269 case MMCSD_MODE_RAW:
270 debug("spl: mmc boot mode: raw\n");
271
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200272 if (!spl_start_uboot()) {
273 err = mmc_load_image_raw_os(mmc);
274 if (!err)
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200275 return err;
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200276 }
Nikita Kiryanov011cd8f2015-11-08 17:11:46 +0200277
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100278 err = mmc_load_image_raw_partition(mmc,
279 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION);
Paul Kocialkowski4bd66e72015-06-08 23:05:09 +0200280 if (!err)
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200281 return err;
Nikita Kiryanov011cd8f2015-11-08 17:11:46 +0200282#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR)
Paul Kocialkowski17675c82014-11-08 23:14:56 +0100283 err = mmc_load_image_raw_sector(mmc,
Dan Murphyb7b5b0c2014-01-16 11:23:29 -0600284 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200285 if (!err)
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200286 return err;
Paul Kocialkowski4bd66e72015-06-08 23:05:09 +0200287#endif
Nikita Kiryanoved52f4d2015-11-08 17:11:43 +0200288 break;
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200289 case MMCSD_MODE_FS:
290 debug("spl: mmc boot mode: fs\n");
291
Nikita Kiryanov642648c2015-11-08 17:11:47 +0200292 err = spl_mmc_do_fs_boot(mmc);
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200293 if (!err)
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200294 return err;
Nikita Kiryanov642648c2015-11-08 17:11:47 +0200295
Nikita Kiryanoved52f4d2015-11-08 17:11:43 +0200296 break;
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200297 case MMCSD_MODE_UNDEFINED:
Paul Burtona8015fd2013-09-04 16:12:24 +0100298#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Nikita Kiryanoved52f4d2015-11-08 17:11:43 +0200299 default:
300 puts("spl: mmc: wrong boot mode\n");
Paul Burtona8015fd2013-09-04 16:12:24 +0100301#endif
Paul Kocialkowski0d139722015-04-27 10:20:22 +0200302 }
Nikita Kiryanoved52f4d2015-11-08 17:11:43 +0200303
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200304 return err;
Simon Schwarze21d2d82011-09-14 15:33:34 -0400305}