]> git.ipfire.org Git - people/ms/u-boot.git/blob - common/spl/spl_mmc.c
Merge git://git.denx.de/u-boot-rockchip
[people/ms/u-boot.git] / common / spl / spl_mmc.c
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 }