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