]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
e2211743 WD |
2 | /* |
3 | * (C) Copyright 2002 | |
4 | * Rich Ireland, Enterasys Networks, [email protected]. | |
e2211743 WD |
5 | */ |
6 | ||
f6555d90 | 7 | /* Generic FPGA support */ |
691d719d | 8 | #include <init.h> |
f7ae49fc | 9 | #include <log.h> |
e2211743 WD |
10 | #include <xilinx.h> /* xilinx specific definitions */ |
11 | #include <altera.h> /* altera specific definitions */ | |
3b8ac464 | 12 | #include <lattice.h> |
336d4615 | 13 | #include <dm/device_compat.h> |
e2211743 | 14 | |
e2211743 | 15 | /* Local static data */ |
e2211743 WD |
16 | static int next_desc = FPGA_INVALID_DEVICE; |
17 | static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES]; | |
18 | ||
f6555d90 MS |
19 | /* |
20 | * fpga_no_sup | |
e2211743 WD |
21 | * 'no support' message function |
22 | */ | |
f6555d90 | 23 | static void fpga_no_sup(char *fn, char *msg) |
e2211743 | 24 | { |
f6555d90 MS |
25 | if (fn && msg) |
26 | printf("%s: No support for %s.\n", fn, msg); | |
27 | else if (msg) | |
28 | printf("No support for %s.\n", msg); | |
29 | else | |
62a3b7dd | 30 | printf("No FPGA support!\n"); |
e2211743 WD |
31 | } |
32 | ||
e2211743 WD |
33 | /* fpga_get_desc |
34 | * map a device number to a descriptor | |
35 | */ | |
ebd322de | 36 | const fpga_desc *const fpga_get_desc(int devnum) |
e2211743 | 37 | { |
f6555d90 | 38 | fpga_desc *desc = (fpga_desc *)NULL; |
e2211743 | 39 | |
f6555d90 | 40 | if ((devnum >= 0) && (devnum < next_desc)) { |
e2211743 | 41 | desc = &desc_table[devnum]; |
f6555d90 MS |
42 | debug("%s: found fpga descriptor #%d @ 0x%p\n", |
43 | __func__, devnum, desc); | |
e2211743 WD |
44 | } |
45 | ||
46 | return desc; | |
47 | } | |
48 | ||
f6555d90 MS |
49 | /* |
50 | * fpga_validate | |
e2211743 WD |
51 | * generic parameter checking code |
52 | */ | |
6631db47 MS |
53 | const fpga_desc *const fpga_validate(int devnum, const void *buf, |
54 | size_t bsize, char *fn) | |
e2211743 | 55 | { |
f6555d90 | 56 | const fpga_desc *desc = fpga_get_desc(devnum); |
e2211743 | 57 | |
f6555d90 MS |
58 | if (!desc) |
59 | printf("%s: Invalid device number %d\n", fn, devnum); | |
e2211743 | 60 | |
f6555d90 MS |
61 | if (!buf) { |
62 | printf("%s: Null buffer.\n", fn); | |
e2211743 WD |
63 | return (fpga_desc * const)NULL; |
64 | } | |
e2211743 WD |
65 | return desc; |
66 | } | |
67 | ||
f6555d90 MS |
68 | /* |
69 | * fpga_dev_info | |
e2211743 WD |
70 | * generic multiplexing code |
71 | */ | |
f6555d90 | 72 | static int fpga_dev_info(int devnum) |
e2211743 | 73 | { |
f6555d90 MS |
74 | int ret_val = FPGA_FAIL; /* assume failure */ |
75 | const fpga_desc * const desc = fpga_get_desc(devnum); | |
e2211743 | 76 | |
f6555d90 MS |
77 | if (desc) { |
78 | debug("%s: Device Descriptor @ 0x%p\n", | |
79 | __func__, desc->devdesc); | |
e2211743 | 80 | |
f6555d90 | 81 | switch (desc->devtype) { |
e2211743 | 82 | case fpga_xilinx: |
0133502e | 83 | #if defined(CONFIG_FPGA_XILINX) |
f6555d90 MS |
84 | printf("Xilinx Device\nDescriptor @ 0x%p\n", desc); |
85 | ret_val = xilinx_info(desc->devdesc); | |
e2211743 | 86 | #else |
f6555d90 | 87 | fpga_no_sup((char *)__func__, "Xilinx devices"); |
e2211743 WD |
88 | #endif |
89 | break; | |
90 | case fpga_altera: | |
0133502e | 91 | #if defined(CONFIG_FPGA_ALTERA) |
f6555d90 MS |
92 | printf("Altera Device\nDescriptor @ 0x%p\n", desc); |
93 | ret_val = altera_info(desc->devdesc); | |
e2211743 | 94 | #else |
f6555d90 | 95 | fpga_no_sup((char *)__func__, "Altera devices"); |
e2211743 WD |
96 | #endif |
97 | break; | |
3b8ac464 | 98 | case fpga_lattice: |
439f6f7e | 99 | #if defined(CONFIG_FPGA_LATTICE) |
3b8ac464 SB |
100 | printf("Lattice Device\nDescriptor @ 0x%p\n", desc); |
101 | ret_val = lattice_info(desc->devdesc); | |
439f6f7e | 102 | #else |
f6555d90 | 103 | fpga_no_sup((char *)__func__, "Lattice devices"); |
439f6f7e | 104 | #endif |
3b8ac464 | 105 | break; |
e2211743 | 106 | default: |
f6555d90 MS |
107 | printf("%s: Invalid or unsupported device type %d\n", |
108 | __func__, desc->devtype); | |
e2211743 WD |
109 | } |
110 | } else { | |
f6555d90 | 111 | printf("%s: Invalid device number %d\n", __func__, devnum); |
e2211743 WD |
112 | } |
113 | ||
114 | return ret_val; | |
115 | } | |
116 | ||
f6555d90 | 117 | /* |
905bca6c | 118 | * fpga_init is usually called from misc_init_r() and MUST be called |
e2211743 WD |
119 | * before any of the other fpga functions are used. |
120 | */ | |
6385b281 | 121 | void fpga_init(void) |
e2211743 | 122 | { |
e2211743 | 123 | next_desc = 0; |
f6555d90 | 124 | memset(desc_table, 0, sizeof(desc_table)); |
e2211743 | 125 | |
ee976c1b | 126 | debug("%s\n", __func__); |
e2211743 WD |
127 | } |
128 | ||
f6555d90 MS |
129 | /* |
130 | * fpga_count | |
e2211743 WD |
131 | * Basic interface function to get the current number of devices available. |
132 | */ | |
f6555d90 | 133 | int fpga_count(void) |
e2211743 WD |
134 | { |
135 | return next_desc; | |
136 | } | |
137 | ||
f6555d90 MS |
138 | /* |
139 | * fpga_add | |
6385b281 | 140 | * Add the device descriptor to the device table. |
e2211743 | 141 | */ |
f6555d90 | 142 | int fpga_add(fpga_type devtype, void *desc) |
e2211743 WD |
143 | { |
144 | int devnum = FPGA_INVALID_DEVICE; | |
145 | ||
cda1e3fb MS |
146 | if (!desc) { |
147 | printf("%s: NULL device descriptor\n", __func__); | |
148 | return devnum; | |
149 | } | |
150 | ||
f6555d90 MS |
151 | if (next_desc < 0) { |
152 | printf("%s: FPGA support not initialized!\n", __func__); | |
153 | } else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) { | |
cda1e3fb MS |
154 | if (next_desc < CONFIG_MAX_FPGA_DEVICES) { |
155 | devnum = next_desc; | |
156 | desc_table[next_desc].devtype = devtype; | |
157 | desc_table[next_desc++].devdesc = desc; | |
e2211743 | 158 | } else { |
cda1e3fb MS |
159 | printf("%s: Exceeded Max FPGA device count\n", |
160 | __func__); | |
e2211743 WD |
161 | } |
162 | } else { | |
f6555d90 | 163 | printf("%s: Unsupported FPGA type %d\n", __func__, devtype); |
e2211743 WD |
164 | } |
165 | ||
166 | return devnum; | |
167 | } | |
168 | ||
8b93a92f GS |
169 | /* |
170 | * Return 1 if the fpga data is partial. | |
171 | * This is only required for fpga drivers that support bitstream_type. | |
172 | */ | |
173 | int __weak fpga_is_partial_data(int devnum, size_t img_len) | |
174 | { | |
175 | return 0; | |
176 | } | |
177 | ||
52c20644 MS |
178 | /* |
179 | * Convert bitstream data and load into the fpga | |
180 | */ | |
7a78bd26 MS |
181 | int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size, |
182 | bitstream_type bstype) | |
52c20644 MS |
183 | { |
184 | printf("Bitstream support not implemented for this FPGA device\n"); | |
185 | return FPGA_FAIL; | |
186 | } | |
187 | ||
1a897668 SDPP |
188 | #if defined(CONFIG_CMD_FPGA_LOADFS) |
189 | int fpga_fsload(int devnum, const void *buf, size_t size, | |
190 | fpga_fs_info *fpga_fsinfo) | |
191 | { | |
192 | int ret_val = FPGA_FAIL; /* assume failure */ | |
193 | const fpga_desc *desc = fpga_validate(devnum, buf, size, | |
194 | (char *)__func__); | |
195 | ||
196 | if (desc) { | |
197 | switch (desc->devtype) { | |
198 | case fpga_xilinx: | |
199 | #if defined(CONFIG_FPGA_XILINX) | |
200 | ret_val = xilinx_loadfs(desc->devdesc, buf, size, | |
201 | fpga_fsinfo); | |
202 | #else | |
203 | fpga_no_sup((char *)__func__, "Xilinx devices"); | |
204 | #endif | |
205 | break; | |
206 | default: | |
207 | printf("%s: Invalid or unsupported device type %d\n", | |
208 | __func__, desc->devtype); | |
209 | } | |
210 | } | |
211 | ||
212 | return ret_val; | |
213 | } | |
214 | #endif | |
215 | ||
fb2b8856 | 216 | #if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) |
cedd48e2 SDPP |
217 | int fpga_loads(int devnum, const void *buf, size_t size, |
218 | struct fpga_secure_info *fpga_sec_info) | |
219 | { | |
220 | int ret_val = FPGA_FAIL; | |
221 | ||
222 | const fpga_desc *desc = fpga_validate(devnum, buf, size, | |
223 | (char *)__func__); | |
224 | ||
225 | if (desc) { | |
226 | switch (desc->devtype) { | |
227 | case fpga_xilinx: | |
228 | #if defined(CONFIG_FPGA_XILINX) | |
229 | ret_val = xilinx_loads(desc->devdesc, buf, size, | |
230 | fpga_sec_info); | |
231 | #else | |
232 | fpga_no_sup((char *)__func__, "Xilinx devices"); | |
233 | #endif | |
234 | break; | |
235 | default: | |
236 | printf("%s: Invalid or unsupported device type %d\n", | |
237 | __func__, desc->devtype); | |
238 | } | |
239 | } | |
240 | ||
241 | return ret_val; | |
242 | } | |
243 | #endif | |
244 | ||
a1190b4d CT |
245 | static int fpga_load_event_notify(const void *buf, size_t bsize, int result) |
246 | { | |
247 | if (CONFIG_IS_ENABLED(EVENT)) { | |
248 | struct event_fpga_load load = { | |
249 | .buf = buf, | |
250 | .bsize = bsize, | |
251 | .result = result | |
252 | }; | |
253 | ||
254 | return event_notify(EVT_FPGA_LOAD, &load, sizeof(load)); | |
255 | } | |
256 | ||
257 | return 0; | |
258 | } | |
259 | ||
e2211743 | 260 | /* |
f6555d90 | 261 | * Generic multiplexing code |
e2211743 | 262 | */ |
282eed50 OS |
263 | int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype, |
264 | int flags) | |
e2211743 WD |
265 | { |
266 | int ret_val = FPGA_FAIL; /* assume failure */ | |
a1190b4d | 267 | int ret_notify; |
f6555d90 MS |
268 | const fpga_desc *desc = fpga_validate(devnum, buf, bsize, |
269 | (char *)__func__); | |
e2211743 | 270 | |
f6555d90 MS |
271 | if (desc) { |
272 | switch (desc->devtype) { | |
e2211743 | 273 | case fpga_xilinx: |
0133502e | 274 | #if defined(CONFIG_FPGA_XILINX) |
7a78bd26 | 275 | ret_val = xilinx_load(desc->devdesc, buf, bsize, |
282eed50 | 276 | bstype, flags); |
e2211743 | 277 | #else |
f6555d90 | 278 | fpga_no_sup((char *)__func__, "Xilinx devices"); |
e2211743 WD |
279 | #endif |
280 | break; | |
281 | case fpga_altera: | |
0133502e | 282 | #if defined(CONFIG_FPGA_ALTERA) |
f6555d90 | 283 | ret_val = altera_load(desc->devdesc, buf, bsize); |
e2211743 | 284 | #else |
f6555d90 | 285 | fpga_no_sup((char *)__func__, "Altera devices"); |
e2211743 WD |
286 | #endif |
287 | break; | |
3b8ac464 | 288 | case fpga_lattice: |
439f6f7e | 289 | #if defined(CONFIG_FPGA_LATTICE) |
3b8ac464 | 290 | ret_val = lattice_load(desc->devdesc, buf, bsize); |
439f6f7e | 291 | #else |
f6555d90 | 292 | fpga_no_sup((char *)__func__, "Lattice devices"); |
439f6f7e | 293 | #endif |
3b8ac464 | 294 | break; |
e2211743 | 295 | default: |
f6555d90 MS |
296 | printf("%s: Invalid or unsupported device type %d\n", |
297 | __func__, desc->devtype); | |
e2211743 WD |
298 | } |
299 | } | |
300 | ||
a1190b4d CT |
301 | ret_notify = fpga_load_event_notify(buf, bsize, ret_val); |
302 | if (ret_notify) | |
303 | return ret_notify; | |
304 | ||
e2211743 WD |
305 | return ret_val; |
306 | } | |
307 | ||
f6555d90 MS |
308 | /* |
309 | * fpga_dump | |
e2211743 WD |
310 | * generic multiplexing code |
311 | */ | |
e6a857da | 312 | int fpga_dump(int devnum, const void *buf, size_t bsize) |
e2211743 WD |
313 | { |
314 | int ret_val = FPGA_FAIL; /* assume failure */ | |
f6555d90 MS |
315 | const fpga_desc *desc = fpga_validate(devnum, buf, bsize, |
316 | (char *)__func__); | |
e2211743 | 317 | |
f6555d90 MS |
318 | if (desc) { |
319 | switch (desc->devtype) { | |
e2211743 | 320 | case fpga_xilinx: |
0133502e | 321 | #if defined(CONFIG_FPGA_XILINX) |
f6555d90 | 322 | ret_val = xilinx_dump(desc->devdesc, buf, bsize); |
e2211743 | 323 | #else |
f6555d90 | 324 | fpga_no_sup((char *)__func__, "Xilinx devices"); |
e2211743 WD |
325 | #endif |
326 | break; | |
327 | case fpga_altera: | |
0133502e | 328 | #if defined(CONFIG_FPGA_ALTERA) |
f6555d90 | 329 | ret_val = altera_dump(desc->devdesc, buf, bsize); |
e2211743 | 330 | #else |
f6555d90 | 331 | fpga_no_sup((char *)__func__, "Altera devices"); |
e2211743 WD |
332 | #endif |
333 | break; | |
3b8ac464 | 334 | case fpga_lattice: |
439f6f7e | 335 | #if defined(CONFIG_FPGA_LATTICE) |
3b8ac464 | 336 | ret_val = lattice_dump(desc->devdesc, buf, bsize); |
439f6f7e | 337 | #else |
f6555d90 | 338 | fpga_no_sup((char *)__func__, "Lattice devices"); |
439f6f7e | 339 | #endif |
3b8ac464 | 340 | break; |
e2211743 | 341 | default: |
f6555d90 MS |
342 | printf("%s: Invalid or unsupported device type %d\n", |
343 | __func__, desc->devtype); | |
e2211743 WD |
344 | } |
345 | } | |
346 | ||
347 | return ret_val; | |
348 | } | |
349 | ||
f6555d90 MS |
350 | /* |
351 | * fpga_info | |
e2211743 WD |
352 | * front end to fpga_dev_info. If devnum is invalid, report on all |
353 | * available devices. | |
354 | */ | |
f6555d90 | 355 | int fpga_info(int devnum) |
e2211743 | 356 | { |
f6555d90 MS |
357 | if (devnum == FPGA_INVALID_DEVICE) { |
358 | if (next_desc > 0) { | |
e2211743 WD |
359 | int dev; |
360 | ||
f6555d90 MS |
361 | for (dev = 0; dev < next_desc; dev++) |
362 | fpga_dev_info(dev); | |
363 | ||
e2211743 WD |
364 | return FPGA_SUCCESS; |
365 | } else { | |
f6555d90 | 366 | printf("%s: No FPGA devices available.\n", __func__); |
e2211743 WD |
367 | return FPGA_FAIL; |
368 | } | |
369 | } | |
e2211743 | 370 | |
f6555d90 MS |
371 | return fpga_dev_info(devnum); |
372 | } | |
2c60514d OS |
373 | |
374 | #if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) | |
375 | int fpga_compatible2flag(int devnum, const char *compatible) | |
376 | { | |
377 | const fpga_desc * const desc = fpga_get_desc(devnum); | |
378 | ||
379 | if (!desc) | |
380 | return 0; | |
381 | ||
382 | switch (desc->devtype) { | |
383 | #if defined(CONFIG_FPGA_XILINX) | |
384 | case fpga_xilinx: | |
385 | { | |
386 | xilinx_desc *xdesc = (xilinx_desc *)desc->devdesc; | |
387 | ||
388 | if (xdesc->operations && xdesc->operations->str2flag) | |
389 | return xdesc->operations->str2flag(xdesc, compatible); | |
390 | } | |
391 | #endif | |
392 | default: | |
393 | break; | |
394 | } | |
395 | ||
396 | return 0; | |
397 | } | |
398 | #endif |