]> git.sur5r.net Git - u-boot/blob - common/spl/spl_mmc.c
Merge git://www.denx.de/git/u-boot-marvell
[u-boot] / 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
27         header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
28                                          sizeof(struct image_header));
29
30         /* read image header to find the image size & load address */
31         count = mmc->block_dev.block_read(&mmc->block_dev, sector, 1, header);
32         debug("read sector %lx, count=%lu\n", sector, count);
33         if (count == 0)
34                 goto end;
35
36         if (image_get_magic(header) != IH_MAGIC) {
37                 puts("bad magic\n");
38                 return -1;
39         }
40
41         spl_parse_image_header(header);
42
43         /* convert size to sectors - round up */
44         image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) /
45                              mmc->read_bl_len;
46
47         /* Read the header too to avoid extra memcpy */
48         count = mmc->block_dev.block_read(&mmc->block_dev, sector,
49                                           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(&mmc->block_dev,
154                 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
155                 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
156                 (void *) CONFIG_SYS_SPL_ARGS_ADDR);
157         if (count == 0) {
158 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
159                 puts("spl: mmc block read error\n");
160 #endif
161                 return -1;
162         }
163
164         return mmc_load_image_raw_sector(mmc,
165                 CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR);
166 }
167 #else
168 int spl_start_uboot(void)
169 {
170         return 1;
171 }
172 static int mmc_load_image_raw_os(struct mmc *mmc)
173 {
174         return -ENOSYS;
175 }
176 #endif
177
178 #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
179 int spl_mmc_do_fs_boot(struct mmc *mmc)
180 {
181         int err = -ENOSYS;
182
183 #ifdef CONFIG_SPL_FAT_SUPPORT
184         if (!spl_start_uboot()) {
185                 err = spl_load_image_fat_os(&mmc->block_dev,
186                         CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
187                 if (!err)
188                         return err;
189         }
190 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
191         err = spl_load_image_fat(&mmc->block_dev,
192                                  CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
193                                  CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
194         if (!err)
195                 return err;
196 #endif
197 #endif
198 #ifdef CONFIG_SPL_EXT_SUPPORT
199         if (!spl_start_uboot()) {
200                 err = spl_load_image_ext_os(&mmc->block_dev,
201                         CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
202                 if (!err)
203                         return err;
204         }
205 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
206         err = spl_load_image_ext(&mmc->block_dev,
207                                  CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
208                                  CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
209         if (!err)
210                 return err;
211 #endif
212 #endif
213
214 #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT)
215         err = -ENOENT;
216 #endif
217
218         return err;
219 }
220 #else
221 int spl_mmc_do_fs_boot(struct mmc *mmc)
222 {
223         return -ENOSYS;
224 }
225 #endif
226
227 int spl_mmc_load_image(u32 boot_device)
228 {
229         struct mmc *mmc = NULL;
230         u32 boot_mode;
231         int err = 0;
232         __maybe_unused int part;
233
234         err = spl_mmc_find_device(&mmc, boot_device);
235         if (err)
236                 return err;
237
238         err = mmc_init(mmc);
239         if (err) {
240 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
241                 printf("spl: mmc init failed with error: %d\n", err);
242 #endif
243                 return err;
244         }
245
246         boot_mode = spl_boot_mode();
247         err = -EINVAL;
248         switch (boot_mode) {
249         case MMCSD_MODE_EMMCBOOT:
250                         /*
251                          * We need to check what the partition is configured to.
252                          * 1 and 2 match up to boot0 / boot1 and 7 is user data
253                          * which is the first physical partition (0).
254                          */
255                         part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
256
257                         if (part == 7)
258                                 part = 0;
259
260                         err = mmc_switch_part(0, part);
261                         if (err) {
262 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
263                                 puts("spl: mmc partition switch failed\n");
264 #endif
265                                 return err;
266                         }
267                         /* Fall through */
268         case MMCSD_MODE_RAW:
269                 debug("spl: mmc boot mode: raw\n");
270
271                 if (!spl_start_uboot()) {
272                         err = mmc_load_image_raw_os(mmc);
273                         if (!err)
274                                 return err;
275                 }
276
277                 err = mmc_load_image_raw_partition(mmc,
278                         CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION);
279                 if (!err)
280                         return err;
281 #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR)
282                 err = mmc_load_image_raw_sector(mmc,
283                         CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
284                 if (!err)
285                         return err;
286 #endif
287                 break;
288         case MMCSD_MODE_FS:
289                 debug("spl: mmc boot mode: fs\n");
290
291                 err = spl_mmc_do_fs_boot(mmc);
292                 if (!err)
293                         return err;
294
295                 break;
296         case MMCSD_MODE_UNDEFINED:
297 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
298         default:
299                 puts("spl: mmc: wrong boot mode\n");
300 #endif
301         }
302
303         return err;
304 }