]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/spl/spl_mmc.c
Merge branch 'master' of git://www.denx.de/git/u-boot-imx
[karo-tx-uboot.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_image_raw_sector(struct mmc *mmc, unsigned long sector)
22 {
23         unsigned long count;
24         u32 image_size_sectors;
25         struct image_header *header;
26         int dev_num = mmc->block_dev.dev;
27
28         header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
29                                          sizeof(struct image_header));
30
31         /* read image header to find the image size & load address */
32         count = mmc->block_dev.block_read(dev_num, sector, 1, header);
33         debug("read sector %lx, count=%lu\n", sector, count);
34         if (count == 0)
35                 goto end;
36
37         if (image_get_magic(header) != IH_MAGIC) {
38                 puts("bad magic\n");
39                 return -1;
40         }
41
42         spl_parse_image_header(header);
43
44         /* convert size to sectors - round up */
45         image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) /
46                              mmc->read_bl_len;
47
48         /* Read the header too to avoid extra memcpy */
49         count = mmc->block_dev.block_read(dev_num, sector, image_size_sectors,
50                                           (void *)(ulong)spl_image.load_addr);
51         debug("read %x sectors to %x\n", image_size_sectors,
52               spl_image.load_addr);
53
54 end:
55         if (count == 0) {
56 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
57                 puts("spl: mmc block read error\n");
58 #endif
59                 return -1;
60         }
61
62         return 0;
63 }
64
65 int 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
82 static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
83 {
84 #ifdef CONFIG_DM_MMC
85         struct udevice *dev;
86 #endif
87         int err, mmc_dev;
88
89         mmc_dev = spl_mmc_get_device_index(boot_device);
90         if (mmc_dev < 0)
91                 return mmc_dev;
92
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
101 #ifdef CONFIG_DM_MMC
102         err = uclass_get_device(UCLASS_MMC, mmc_dev, &dev);
103         if (!err)
104                 *mmcp = mmc_get_mmc_dev(dev);
105 #else
106         *mmcp = find_mmc_device(mmc_dev);
107         err = *mmcp ? 0 : -ENODEV;
108 #endif
109         if (err) {
110 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
111                 printf("spl: could not find mmc device. error: %d\n", err);
112 #endif
113                 return err;
114         }
115
116         return 0;
117 }
118
119 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
120 static int mmc_load_image_raw_partition(struct mmc *mmc, int partition)
121 {
122         disk_partition_t info;
123         int err;
124
125         err = get_partition_info(&mmc->block_dev, partition, &info);
126         if (err) {
127 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
128                 puts("spl: partition error\n");
129 #endif
130                 return -1;
131         }
132
133 #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
137         return mmc_load_image_raw_sector(mmc, info.start);
138 #endif
139 }
140 #else
141 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION -1
142 static int mmc_load_image_raw_partition(struct mmc *mmc, int partition)
143 {
144         return -ENOSYS;
145 }
146 #endif
147
148 #ifdef CONFIG_SPL_OS_BOOT
149 static int mmc_load_image_raw_os(struct mmc *mmc)
150 {
151         unsigned long count;
152
153         count = mmc->block_dev.block_read(
154                 mmc->block_dev.dev,
155                 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) {
159 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
160                 puts("spl: mmc block read error\n");
161 #endif
162                 return -1;
163         }
164
165         return mmc_load_image_raw_sector(mmc,
166                 CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR);
167 }
168 #else
169 int spl_start_uboot(void)
170 {
171         return 1;
172 }
173 static int mmc_load_image_raw_os(struct mmc *mmc)
174 {
175         return -ENOSYS;
176 }
177 #endif
178
179 #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
180 int 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
222 int spl_mmc_do_fs_boot(struct mmc *mmc)
223 {
224         return -ENOSYS;
225 }
226 #endif
227
228 int spl_mmc_load_image(u32 boot_device)
229 {
230         struct mmc *mmc = NULL;
231         u32 boot_mode;
232         int err = 0;
233         __maybe_unused int part;
234
235         err = spl_mmc_find_device(&mmc, boot_device);
236         if (err)
237                 return err;
238
239         err = mmc_init(mmc);
240         if (err) {
241 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
242                 printf("spl: mmc init failed with error: %d\n", err);
243 #endif
244                 return err;
245         }
246
247         boot_mode = spl_boot_mode();
248         err = -EINVAL;
249         switch (boot_mode) {
250         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
261                         err = mmc_switch_part(0, part);
262                         if (err) {
263 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
264                                 puts("spl: mmc partition switch failed\n");
265 #endif
266                                 return err;
267                         }
268                         /* Fall through */
269         case MMCSD_MODE_RAW:
270                 debug("spl: mmc boot mode: raw\n");
271
272                 if (!spl_start_uboot()) {
273                         err = mmc_load_image_raw_os(mmc);
274                         if (!err)
275                                 return err;
276                 }
277
278                 err = mmc_load_image_raw_partition(mmc,
279                         CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION);
280                 if (!err)
281                         return err;
282 #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR)
283                 err = mmc_load_image_raw_sector(mmc,
284                         CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
285                 if (!err)
286                         return err;
287 #endif
288                 break;
289         case MMCSD_MODE_FS:
290                 debug("spl: mmc boot mode: fs\n");
291
292                 err = spl_mmc_do_fs_boot(mmc);
293                 if (!err)
294                         return err;
295
296                 break;
297         case MMCSD_MODE_UNDEFINED:
298 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
299         default:
300                 puts("spl: mmc: wrong boot mode\n");
301 #endif
302         }
303
304         return err;
305 }