]>
Commit | Line | Data |
---|---|---|
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 <spl.h> | |
11 | #include <linux/compiler.h> | |
12 | #include <asm/u-boot.h> | |
13 | #include <mmc.h> | |
14 | #include <image.h> | |
15 | ||
16 | DECLARE_GLOBAL_DATA_PTR; | |
17 | ||
18 | static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) | |
19 | { | |
20 | unsigned long err; | |
21 | u32 image_size_sectors; | |
22 | struct image_header *header; | |
23 | ||
24 | header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - | |
25 | sizeof(struct image_header)); | |
26 | ||
27 | /* read image header to find the image size & load address */ | |
28 | err = mmc->block_dev.block_read(0, sector, 1, header); | |
29 | if (err == 0) | |
30 | goto end; | |
31 | ||
32 | if (image_get_magic(header) != IH_MAGIC) | |
33 | return -1; | |
34 | ||
35 | spl_parse_image_header(header); | |
36 | ||
37 | /* convert size to sectors - round up */ | |
38 | image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / | |
39 | mmc->read_bl_len; | |
40 | ||
41 | /* Read the header too to avoid extra memcpy */ | |
42 | err = mmc->block_dev.block_read(0, sector, image_size_sectors, | |
43 | (void *)spl_image.load_addr); | |
44 | ||
45 | end: | |
46 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
47 | if (err == 0) | |
48 | printf("spl: mmc block read error\n"); | |
49 | #endif | |
50 | ||
51 | return (err == 0); | |
52 | } | |
53 | ||
54 | #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION | |
55 | static int mmc_load_image_raw_partition(struct mmc *mmc, int partition) | |
56 | { | |
57 | disk_partition_t info; | |
58 | ||
59 | if (get_partition_info(&mmc->block_dev, partition, &info)) { | |
60 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
61 | printf("spl: partition error\n"); | |
62 | #endif | |
63 | return -1; | |
64 | } | |
65 | ||
66 | return mmc_load_image_raw_sector(mmc, info.start); | |
67 | } | |
68 | #endif | |
69 | ||
70 | #ifdef CONFIG_SPL_OS_BOOT | |
71 | static int mmc_load_image_raw_os(struct mmc *mmc) | |
72 | { | |
73 | unsigned long err; | |
74 | ||
75 | err = mmc->block_dev.block_read(0, | |
76 | CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, | |
77 | CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, | |
78 | (void *)CONFIG_SYS_SPL_ARGS_ADDR); | |
79 | if (err == 0) { | |
80 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
81 | printf("spl: mmc block read error\n"); | |
82 | #endif | |
83 | return -1; | |
84 | } | |
85 | ||
86 | return mmc_load_image_raw_sector(mmc, | |
87 | CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); | |
88 | } | |
89 | #endif | |
90 | ||
91 | void spl_mmc_load_image(void) | |
92 | { | |
93 | struct mmc *mmc; | |
94 | u32 boot_mode; | |
95 | int err; | |
96 | __maybe_unused int part; | |
97 | ||
98 | mmc_initialize(gd->bd); | |
99 | ||
100 | /* We register only one device. So, the dev id is always 0 */ | |
101 | mmc = find_mmc_device(0); | |
102 | if (!mmc) { | |
103 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
104 | puts("spl: mmc device not found\n"); | |
105 | #endif | |
106 | hang(); | |
107 | } | |
108 | ||
109 | err = mmc_init(mmc); | |
110 | if (err) { | |
111 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
112 | printf("spl: mmc init failed with error: %d\n", err); | |
113 | #endif | |
114 | hang(); | |
115 | } | |
116 | ||
117 | boot_mode = spl_boot_mode(); | |
118 | switch (boot_mode) { | |
119 | case MMCSD_MODE_RAW: | |
120 | debug("spl: mmc boot mode: raw\n"); | |
121 | ||
122 | #ifdef CONFIG_SPL_OS_BOOT | |
123 | if (!spl_start_uboot()) { | |
124 | err = mmc_load_image_raw_os(mmc); | |
125 | if (!err) | |
126 | return; | |
127 | } | |
128 | #endif | |
129 | #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION | |
130 | err = mmc_load_image_raw_partition(mmc, | |
131 | CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); | |
132 | #else | |
133 | err = mmc_load_image_raw_sector(mmc, | |
134 | CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); | |
135 | #endif | |
136 | if (!err) | |
137 | return; | |
138 | #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) | |
139 | case MMCSD_MODE_FS: | |
140 | debug("spl: mmc boot mode: fs\n"); | |
141 | ||
142 | #ifdef CONFIG_SPL_FAT_SUPPORT | |
143 | #ifdef CONFIG_SPL_OS_BOOT | |
144 | if (!spl_start_uboot()) { | |
145 | err = spl_load_image_fat_os(&mmc->block_dev, | |
146 | CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); | |
147 | if (!err) | |
148 | return; | |
149 | } | |
150 | #endif | |
151 | err = spl_load_image_fat(&mmc->block_dev, | |
152 | CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, | |
153 | CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); | |
154 | if (!err) | |
155 | return; | |
156 | #endif | |
157 | #ifdef CONFIG_SPL_EXT_SUPPORT | |
158 | #ifdef CONFIG_SPL_OS_BOOT | |
159 | if (!spl_start_uboot()) { | |
160 | err = spl_load_image_ext_os(&mmc->block_dev, | |
161 | CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); | |
162 | if (!err) | |
163 | return; | |
164 | } | |
165 | #endif | |
166 | err = spl_load_image_ext(&mmc->block_dev, | |
167 | CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, | |
168 | CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); | |
169 | if (!err) | |
170 | return; | |
171 | #endif | |
172 | #endif | |
173 | #ifdef CONFIG_SUPPORT_EMMC_BOOT | |
174 | case MMCSD_MODE_EMMCBOOT: | |
175 | /* | |
176 | * We need to check what the partition is configured to. | |
177 | * 1 and 2 match up to boot0 / boot1 and 7 is user data | |
178 | * which is the first physical partition (0). | |
179 | */ | |
180 | part = (mmc->part_config >> 3) & PART_ACCESS_MASK; | |
181 | ||
182 | if (part == 7) | |
183 | part = 0; | |
184 | ||
185 | if (mmc_switch_part(0, part)) { | |
186 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
187 | puts("spl: mmc partition switch failed\n"); | |
188 | #endif | |
189 | hang(); | |
190 | } | |
191 | ||
192 | #ifdef CONFIG_SPL_OS_BOOT | |
193 | if (!spl_start_uboot()) { | |
194 | err = mmc_load_image_raw_os(mmc); | |
195 | if (!err) | |
196 | return; | |
197 | } | |
198 | #endif | |
199 | #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION | |
200 | err = mmc_load_image_raw_partition(mmc, | |
201 | CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); | |
202 | #else | |
203 | err = mmc_load_image_raw_sector(mmc, | |
204 | CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); | |
205 | #endif | |
206 | if (!err) | |
207 | return; | |
208 | #endif | |
209 | case MMCSD_MODE_UNDEFINED: | |
210 | default: | |
211 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
212 | if (err) | |
213 | puts("spl: mmc: no boot mode left to try\n"); | |
214 | else | |
215 | puts("spl: mmc: wrong boot mode\n"); | |
216 | #endif | |
217 | hang(); | |
218 | } | |
219 | } |