Commit 1cbebc78627607fa3f46b17fecdb4a0819b7e590
Committed by
Stefano Babic
1 parent
a92c7b144f
Exists in
smarc_8mq_lf_v2020.04
and in
9 other branches
imx: add rom api support
i.MX8MN support loading images with rom api, so we implement reuse board_return_to_bootrom to let ROM loading images. Signed-off-by: Peng Fan <peng.fan@nxp.com>
Showing 4 changed files with 331 additions and 0 deletions Side-by-side Diff
arch/arm/include/asm/mach-imx/sys_proto.h
... | ... | @@ -106,6 +106,39 @@ |
106 | 106 | |
107 | 107 | #endif /* CONFIG_MX6 */ |
108 | 108 | |
109 | +#ifdef CONFIG_IMX8M | |
110 | +struct rom_api { | |
111 | + u16 ver; | |
112 | + u16 tag; | |
113 | + u32 reserved1; | |
114 | + u32 (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor); | |
115 | + u32 (*query_boot_infor)(u32 info_type, u32 *info, u32 xor); | |
116 | +}; | |
117 | + | |
118 | +enum boot_dev_type_e { | |
119 | + BT_DEV_TYPE_SD = 1, | |
120 | + BT_DEV_TYPE_MMC = 2, | |
121 | + BT_DEV_TYPE_NAND = 3, | |
122 | + BT_DEV_TYPE_FLEXSPINOR = 4, | |
123 | + | |
124 | + BT_DEV_TYPE_USB = 0xE, | |
125 | + BT_DEV_TYPE_MEM_DEV = 0xF, | |
126 | + | |
127 | + BT_DEV_TYPE_INVALID = 0xFF | |
128 | +}; | |
129 | + | |
130 | +#define QUERY_ROM_VER 1 | |
131 | +#define QUERY_BT_DEV 2 | |
132 | +#define QUERY_PAGE_SZ 3 | |
133 | +#define QUERY_IVT_OFF 4 | |
134 | +#define QUERY_BT_STAGE 5 | |
135 | +#define QUERY_IMG_OFF 6 | |
136 | + | |
137 | +#define ROM_API_OKAY 0xF0 | |
138 | + | |
139 | +extern struct rom_api *g_rom_api; | |
140 | +#endif | |
141 | + | |
109 | 142 | u32 get_nr_cpus(void); |
110 | 143 | u32 get_cpu_rev(void); |
111 | 144 | u32 get_cpu_speed_grade_hz(void); |
arch/arm/mach-imx/Kconfig
... | ... | @@ -109,4 +109,8 @@ |
109 | 109 | NXP does NOT recommend to perform this calibration at each boot. One |
110 | 110 | shall perform it on a new PCB and then use those values to program |
111 | 111 | the ddrmc_cr_setting on relevant board file. |
112 | + | |
113 | +config SPL_IMX_ROMAPI_LOADADDR | |
114 | + hex "Default load address to load image through ROM API" | |
115 | + depends on IMX8MN |
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/spl_imx_romapi.c
1 | +// SPDX-License-Identifier: GPL-2.0+ | |
2 | +/* | |
3 | + * Copyright 2019 NXP | |
4 | + */ | |
5 | + | |
6 | +#include <common.h> | |
7 | +#include <errno.h> | |
8 | +#include <image.h> | |
9 | +#include <linux/libfdt.h> | |
10 | +#include <spl.h> | |
11 | + | |
12 | +#include <asm/arch/sys_proto.h> | |
13 | + | |
14 | +DECLARE_GLOBAL_DATA_PTR; | |
15 | + | |
16 | +static int is_boot_from_stream_device(u32 boot) | |
17 | +{ | |
18 | + u32 interface; | |
19 | + | |
20 | + interface = boot >> 16; | |
21 | + if (interface >= BT_DEV_TYPE_USB) | |
22 | + return 1; | |
23 | + | |
24 | + if (interface == BT_DEV_TYPE_MMC && (boot & 1)) | |
25 | + return 1; | |
26 | + | |
27 | + return 0; | |
28 | +} | |
29 | + | |
30 | +static ulong spl_romapi_read_seekable(struct spl_load_info *load, | |
31 | + ulong sector, ulong count, | |
32 | + void *buf) | |
33 | +{ | |
34 | + u32 pagesize = *(u32 *)load->priv; | |
35 | + volatile gd_t *pgd = gd; | |
36 | + ulong byte = count * pagesize; | |
37 | + int ret; | |
38 | + u32 offset; | |
39 | + | |
40 | + offset = sector * pagesize; | |
41 | + | |
42 | + debug("ROM API load from 0x%x, size 0x%x\n", offset, (u32)byte); | |
43 | + | |
44 | + ret = g_rom_api->download_image(buf, offset, byte, | |
45 | + ((uintptr_t)buf) ^ offset ^ byte); | |
46 | + gd = pgd; | |
47 | + | |
48 | + if (ret == ROM_API_OKAY) | |
49 | + return count; | |
50 | + | |
51 | + printf("ROM API Failure when load 0x%x\n", offset); | |
52 | + | |
53 | + return 0; | |
54 | +} | |
55 | + | |
56 | +static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, | |
57 | + struct spl_boot_device *bootdev, | |
58 | + u32 rom_bt_dev) | |
59 | +{ | |
60 | + volatile gd_t *pgd = gd; | |
61 | + int ret; | |
62 | + u32 offset; | |
63 | + u32 pagesize, size; | |
64 | + struct image_header *header; | |
65 | + u32 image_offset; | |
66 | + | |
67 | + ret = g_rom_api->query_boot_infor(QUERY_IVT_OFF, &offset, | |
68 | + ((uintptr_t)&offset) ^ QUERY_IVT_OFF); | |
69 | + ret |= g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize, | |
70 | + ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ); | |
71 | + ret |= g_rom_api->query_boot_infor(QUERY_IMG_OFF, &image_offset, | |
72 | + ((uintptr_t)&image_offset) ^ QUERY_IMG_OFF); | |
73 | + | |
74 | + gd = pgd; | |
75 | + | |
76 | + if (ret != ROM_API_OKAY) { | |
77 | + puts("ROMAPI: Failure query boot infor pagesize/offset\n"); | |
78 | + return -1; | |
79 | + } | |
80 | + | |
81 | + header = (struct image_header *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR); | |
82 | + | |
83 | + printf("image offset 0x%x, pagesize 0x%x, ivt offset 0x%x\n", | |
84 | + image_offset, pagesize, offset); | |
85 | + | |
86 | + if (((rom_bt_dev >> 16) & 0xff) == BT_DEV_TYPE_FLEXSPINOR) | |
87 | + offset = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512; | |
88 | + else | |
89 | + offset = image_offset + | |
90 | + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512 - 0x8000; | |
91 | + | |
92 | + size = ALIGN(sizeof(struct image_header), pagesize); | |
93 | + ret = g_rom_api->download_image((u8 *)header, offset, size, | |
94 | + ((uintptr_t)header) ^ offset ^ size); | |
95 | + gd = pgd; | |
96 | + | |
97 | + if (ret != ROM_API_OKAY) { | |
98 | + printf("ROMAPI: download failure offset 0x%x size 0x%x\n", | |
99 | + offset, size); | |
100 | + return -1; | |
101 | + } | |
102 | + | |
103 | + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && | |
104 | + image_get_magic(header) == FDT_MAGIC) { | |
105 | + struct spl_load_info load; | |
106 | + | |
107 | + memset(&load, 0, sizeof(load)); | |
108 | + load.bl_len = pagesize; | |
109 | + load.read = spl_romapi_read_seekable; | |
110 | + load.priv = &pagesize; | |
111 | + return spl_load_simple_fit(spl_image, &load, | |
112 | + offset / pagesize, header); | |
113 | + } else { | |
114 | + /* TODO */ | |
115 | + puts("Can't support legacy image\n"); | |
116 | + return -1; | |
117 | + } | |
118 | + | |
119 | + return 0; | |
120 | +} | |
121 | + | |
122 | +static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, | |
123 | + ulong count, void *buf) | |
124 | +{ | |
125 | + memcpy(buf, (void *)(sector), count); | |
126 | + | |
127 | + if (load->priv) { | |
128 | + ulong *p = (ulong *)load->priv; | |
129 | + ulong total = sector + count; | |
130 | + | |
131 | + if (total > *p) | |
132 | + *p = total; | |
133 | + } | |
134 | + | |
135 | + return count; | |
136 | +} | |
137 | + | |
138 | +static ulong get_fit_image_size(void *fit) | |
139 | +{ | |
140 | + struct spl_image_info spl_image; | |
141 | + struct spl_load_info spl_load_info; | |
142 | + ulong last = (ulong)fit; | |
143 | + | |
144 | + memset(&spl_load_info, 0, sizeof(spl_load_info)); | |
145 | + spl_load_info.bl_len = 1; | |
146 | + spl_load_info.read = spl_ram_load_read; | |
147 | + spl_load_info.priv = &last; | |
148 | + | |
149 | + spl_load_simple_fit(&spl_image, &spl_load_info, | |
150 | + (uintptr_t)fit, fit); | |
151 | + | |
152 | + return last - (ulong)fit; | |
153 | +} | |
154 | + | |
155 | +u8 *search_fit_header(u8 *p, int size) | |
156 | +{ | |
157 | + int i; | |
158 | + | |
159 | + for (i = 0; i < size; i += 4) | |
160 | + if (genimg_get_format(p + i) == IMAGE_FORMAT_FIT) | |
161 | + return p + i; | |
162 | + | |
163 | + return NULL; | |
164 | +} | |
165 | + | |
166 | +static int spl_romapi_load_image_stream(struct spl_image_info *spl_image, | |
167 | + struct spl_boot_device *bootdev) | |
168 | +{ | |
169 | + struct spl_load_info load; | |
170 | + volatile gd_t *pgd = gd; | |
171 | + u32 pagesize, pg; | |
172 | + int ret; | |
173 | + int i = 0; | |
174 | + u8 *p = (u8 *)CONFIG_SPL_IMX_ROMAPI_LOADADDR; | |
175 | + u8 *pfit = NULL; | |
176 | + int imagesize; | |
177 | + int total; | |
178 | + | |
179 | + ret = g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize, | |
180 | + ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ); | |
181 | + gd = pgd; | |
182 | + | |
183 | + if (ret != ROM_API_OKAY) | |
184 | + puts("failure at query_boot_info\n"); | |
185 | + | |
186 | + pg = pagesize; | |
187 | + if (pg < 1024) | |
188 | + pg = 1024; | |
189 | + | |
190 | + for (i = 0; i < 640; i++) { | |
191 | + ret = g_rom_api->download_image(p, 0, pg, | |
192 | + ((uintptr_t)p) ^ pg); | |
193 | + gd = pgd; | |
194 | + | |
195 | + if (ret != ROM_API_OKAY) { | |
196 | + puts("Steam(USB) download failure\n"); | |
197 | + return -1; | |
198 | + } | |
199 | + | |
200 | + pfit = search_fit_header(p, pg); | |
201 | + p += pg; | |
202 | + | |
203 | + if (pfit) | |
204 | + break; | |
205 | + } | |
206 | + | |
207 | + if (!pfit) { | |
208 | + puts("Can't found uboot FIT image in 640K range \n"); | |
209 | + return -1; | |
210 | + } | |
211 | + | |
212 | + if (p - pfit < sizeof(struct fdt_header)) { | |
213 | + ret = g_rom_api->download_image(p, 0, pg, ((uintptr_t)p) ^ pg); | |
214 | + gd = pgd; | |
215 | + | |
216 | + if (ret != ROM_API_OKAY) { | |
217 | + puts("Steam(USB) download failure\n"); | |
218 | + return -1; | |
219 | + } | |
220 | + | |
221 | + p += pg; | |
222 | + } | |
223 | + | |
224 | + imagesize = fit_get_size(pfit); | |
225 | + printf("Find FIT header 0x&%p, size %d\n", pfit, imagesize); | |
226 | + | |
227 | + if (p - pfit < imagesize) { | |
228 | + imagesize -= p - pfit; | |
229 | + /*need pagesize hear after ROM fix USB problme*/ | |
230 | + imagesize += pg - 1; | |
231 | + imagesize /= pg; | |
232 | + imagesize *= pg; | |
233 | + | |
234 | + printf("Need continue download %d\n", imagesize); | |
235 | + | |
236 | + ret = g_rom_api->download_image(p, 0, imagesize, | |
237 | + ((uintptr_t)p) ^ imagesize); | |
238 | + gd = pgd; | |
239 | + | |
240 | + p += imagesize; | |
241 | + | |
242 | + if (ret != ROM_API_OKAY) { | |
243 | + printf("Failure download %d\n", imagesize); | |
244 | + return -1; | |
245 | + } | |
246 | + } | |
247 | + | |
248 | + total = get_fit_image_size(pfit); | |
249 | + total += 3; | |
250 | + total &= ~0x3; | |
251 | + | |
252 | + imagesize = total - (p - pfit); | |
253 | + | |
254 | + imagesize += pagesize - 1; | |
255 | + imagesize /= pagesize; | |
256 | + imagesize *= pagesize; | |
257 | + | |
258 | + printf("Download %d, total fit %d\n", imagesize, total); | |
259 | + | |
260 | + ret = g_rom_api->download_image(p, 0, imagesize, | |
261 | + ((uintptr_t)p) ^ imagesize); | |
262 | + if (ret != ROM_API_OKAY) | |
263 | + printf("ROM download failure %d\n", imagesize); | |
264 | + | |
265 | + memset(&load, 0, sizeof(load)); | |
266 | + load.bl_len = 1; | |
267 | + load.read = spl_ram_load_read; | |
268 | + | |
269 | + return spl_load_simple_fit(spl_image, &load, (ulong)pfit, pfit); | |
270 | +} | |
271 | + | |
272 | +int board_return_to_bootrom(struct spl_image_info *spl_image, | |
273 | + struct spl_boot_device *bootdev) | |
274 | +{ | |
275 | + volatile gd_t *pgd = gd; | |
276 | + int ret; | |
277 | + u32 boot; | |
278 | + | |
279 | + ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot, | |
280 | + ((uintptr_t)&boot) ^ QUERY_BT_DEV); | |
281 | + gd = pgd; | |
282 | + | |
283 | + if (ret != ROM_API_OKAY) { | |
284 | + puts("ROMAPI: failure at query_boot_info\n"); | |
285 | + return -1; | |
286 | + } | |
287 | + | |
288 | + if (is_boot_from_stream_device(boot)) | |
289 | + return spl_romapi_load_image_stream(spl_image, bootdev); | |
290 | + | |
291 | + return spl_romapi_load_image_seekable(spl_image, bootdev, boot); | |
292 | +} |