blob: 1f6782537de96b146283a2afc4bf168d67e619c1 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenke2211742002-11-02 23:30:20 +00002/*
3 * (C) Copyright 2002
4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
wdenke2211742002-11-02 23:30:20 +00005 */
6
Michal Simek5125ba12013-04-26 08:46:56 +02007/* Generic FPGA support */
Simon Glass97589732020-05-10 11:40:02 -06008#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
wdenke2211742002-11-02 23:30:20 +000010#include <xilinx.h> /* xilinx specific definitions */
11#include <altera.h> /* altera specific definitions */
Stefano Babicec65c592010-06-29 11:47:48 +020012#include <lattice.h>
Simon Glass9bc15642020-02-03 07:36:16 -070013#include <dm/device_compat.h>
wdenke2211742002-11-02 23:30:20 +000014
wdenke2211742002-11-02 23:30:20 +000015/* Local static data */
wdenke2211742002-11-02 23:30:20 +000016static int next_desc = FPGA_INVALID_DEVICE;
17static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES];
18
Michal Simek5125ba12013-04-26 08:46:56 +020019/*
20 * fpga_no_sup
wdenke2211742002-11-02 23:30:20 +000021 * 'no support' message function
22 */
Michal Simek5125ba12013-04-26 08:46:56 +020023static void fpga_no_sup(char *fn, char *msg)
wdenke2211742002-11-02 23:30:20 +000024{
Michal Simek5125ba12013-04-26 08:46:56 +020025 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
Robert P. J. Day8d56db92016-07-15 13:44:45 -040030 printf("No FPGA support!\n");
wdenke2211742002-11-02 23:30:20 +000031}
32
wdenke2211742002-11-02 23:30:20 +000033/* fpga_get_desc
34 * map a device number to a descriptor
35 */
Michal Simekfbadb762015-01-13 16:09:53 +010036const fpga_desc *const fpga_get_desc(int devnum)
wdenke2211742002-11-02 23:30:20 +000037{
Michal Simek5125ba12013-04-26 08:46:56 +020038 fpga_desc *desc = (fpga_desc *)NULL;
wdenke2211742002-11-02 23:30:20 +000039
Michal Simek5125ba12013-04-26 08:46:56 +020040 if ((devnum >= 0) && (devnum < next_desc)) {
wdenke2211742002-11-02 23:30:20 +000041 desc = &desc_table[devnum];
Michal Simek5125ba12013-04-26 08:46:56 +020042 debug("%s: found fpga descriptor #%d @ 0x%p\n",
43 __func__, devnum, desc);
wdenke2211742002-11-02 23:30:20 +000044 }
45
46 return desc;
47}
48
Michal Simek5125ba12013-04-26 08:46:56 +020049/*
50 * fpga_validate
wdenke2211742002-11-02 23:30:20 +000051 * generic parameter checking code
52 */
Michal Simek6ff890d2013-04-26 15:04:48 +020053const fpga_desc *const fpga_validate(int devnum, const void *buf,
54 size_t bsize, char *fn)
wdenke2211742002-11-02 23:30:20 +000055{
Michal Simek5125ba12013-04-26 08:46:56 +020056 const fpga_desc *desc = fpga_get_desc(devnum);
wdenke2211742002-11-02 23:30:20 +000057
Michal Simek5125ba12013-04-26 08:46:56 +020058 if (!desc)
59 printf("%s: Invalid device number %d\n", fn, devnum);
wdenke2211742002-11-02 23:30:20 +000060
Michal Simek5125ba12013-04-26 08:46:56 +020061 if (!buf) {
62 printf("%s: Null buffer.\n", fn);
wdenke2211742002-11-02 23:30:20 +000063 return (fpga_desc * const)NULL;
64 }
wdenke2211742002-11-02 23:30:20 +000065 return desc;
66}
67
Michal Simek5125ba12013-04-26 08:46:56 +020068/*
69 * fpga_dev_info
wdenke2211742002-11-02 23:30:20 +000070 * generic multiplexing code
71 */
Michal Simek5125ba12013-04-26 08:46:56 +020072static int fpga_dev_info(int devnum)
wdenke2211742002-11-02 23:30:20 +000073{
Michal Simek5125ba12013-04-26 08:46:56 +020074 int ret_val = FPGA_FAIL; /* assume failure */
75 const fpga_desc * const desc = fpga_get_desc(devnum);
wdenke2211742002-11-02 23:30:20 +000076
Michal Simek5125ba12013-04-26 08:46:56 +020077 if (desc) {
78 debug("%s: Device Descriptor @ 0x%p\n",
79 __func__, desc->devdesc);
wdenke2211742002-11-02 23:30:20 +000080
Michal Simek5125ba12013-04-26 08:46:56 +020081 switch (desc->devtype) {
wdenke2211742002-11-02 23:30:20 +000082 case fpga_xilinx:
Matthias Fuchsa4400872007-12-27 17:12:34 +010083#if defined(CONFIG_FPGA_XILINX)
Michal Simek5125ba12013-04-26 08:46:56 +020084 printf("Xilinx Device\nDescriptor @ 0x%p\n", desc);
85 ret_val = xilinx_info(desc->devdesc);
wdenke2211742002-11-02 23:30:20 +000086#else
Michal Simek5125ba12013-04-26 08:46:56 +020087 fpga_no_sup((char *)__func__, "Xilinx devices");
wdenke2211742002-11-02 23:30:20 +000088#endif
89 break;
90 case fpga_altera:
Matthias Fuchsa4400872007-12-27 17:12:34 +010091#if defined(CONFIG_FPGA_ALTERA)
Michal Simek5125ba12013-04-26 08:46:56 +020092 printf("Altera Device\nDescriptor @ 0x%p\n", desc);
93 ret_val = altera_info(desc->devdesc);
wdenke2211742002-11-02 23:30:20 +000094#else
Michal Simek5125ba12013-04-26 08:46:56 +020095 fpga_no_sup((char *)__func__, "Altera devices");
wdenke2211742002-11-02 23:30:20 +000096#endif
97 break;
Stefano Babicec65c592010-06-29 11:47:48 +020098 case fpga_lattice:
Wolfgang Denkace143a2010-10-18 21:32:14 +020099#if defined(CONFIG_FPGA_LATTICE)
Stefano Babicec65c592010-06-29 11:47:48 +0200100 printf("Lattice Device\nDescriptor @ 0x%p\n", desc);
101 ret_val = lattice_info(desc->devdesc);
Wolfgang Denkace143a2010-10-18 21:32:14 +0200102#else
Michal Simek5125ba12013-04-26 08:46:56 +0200103 fpga_no_sup((char *)__func__, "Lattice devices");
Wolfgang Denkace143a2010-10-18 21:32:14 +0200104#endif
Stefano Babicec65c592010-06-29 11:47:48 +0200105 break;
wdenke2211742002-11-02 23:30:20 +0000106 default:
Michal Simek5125ba12013-04-26 08:46:56 +0200107 printf("%s: Invalid or unsupported device type %d\n",
108 __func__, desc->devtype);
wdenke2211742002-11-02 23:30:20 +0000109 }
110 } else {
Michal Simek5125ba12013-04-26 08:46:56 +0200111 printf("%s: Invalid device number %d\n", __func__, devnum);
wdenke2211742002-11-02 23:30:20 +0000112 }
113
114 return ret_val;
115}
116
Michal Simek5125ba12013-04-26 08:46:56 +0200117/*
Michal Simekb563a6b2016-05-17 14:32:00 +0200118 * fpga_init is usually called from misc_init_r() and MUST be called
wdenke2211742002-11-02 23:30:20 +0000119 * before any of the other fpga functions are used.
120 */
Peter Tysercf8582c2009-09-21 11:20:32 -0500121void fpga_init(void)
wdenke2211742002-11-02 23:30:20 +0000122{
wdenke2211742002-11-02 23:30:20 +0000123 next_desc = 0;
Michal Simek5125ba12013-04-26 08:46:56 +0200124 memset(desc_table, 0, sizeof(desc_table));
wdenke2211742002-11-02 23:30:20 +0000125
Michal Simekaefbf8f2013-04-26 09:38:26 +0200126 debug("%s\n", __func__);
wdenke2211742002-11-02 23:30:20 +0000127}
128
Michal Simek5125ba12013-04-26 08:46:56 +0200129/*
130 * fpga_count
wdenke2211742002-11-02 23:30:20 +0000131 * Basic interface function to get the current number of devices available.
132 */
Michal Simek5125ba12013-04-26 08:46:56 +0200133int fpga_count(void)
wdenke2211742002-11-02 23:30:20 +0000134{
135 return next_desc;
136}
137
Michal Simek5125ba12013-04-26 08:46:56 +0200138/*
139 * fpga_add
Peter Tysercf8582c2009-09-21 11:20:32 -0500140 * Add the device descriptor to the device table.
wdenke2211742002-11-02 23:30:20 +0000141 */
Michal Simek5125ba12013-04-26 08:46:56 +0200142int fpga_add(fpga_type devtype, void *desc)
wdenke2211742002-11-02 23:30:20 +0000143{
144 int devnum = FPGA_INVALID_DEVICE;
145
Michal Simek3529c112018-01-26 13:17:04 +0100146 if (!desc) {
147 printf("%s: NULL device descriptor\n", __func__);
148 return devnum;
149 }
150
Michal Simek5125ba12013-04-26 08:46:56 +0200151 if (next_desc < 0) {
152 printf("%s: FPGA support not initialized!\n", __func__);
153 } else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) {
Michal Simek3529c112018-01-26 13:17:04 +0100154 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;
wdenke2211742002-11-02 23:30:20 +0000158 } else {
Michal Simek3529c112018-01-26 13:17:04 +0100159 printf("%s: Exceeded Max FPGA device count\n",
160 __func__);
wdenke2211742002-11-02 23:30:20 +0000161 }
162 } else {
Michal Simek5125ba12013-04-26 08:46:56 +0200163 printf("%s: Unsupported FPGA type %d\n", __func__, devtype);
wdenke2211742002-11-02 23:30:20 +0000164 }
165
166 return devnum;
167}
168
169/*
Goldschmidt Simon9179c812017-11-10 14:17:41 +0000170 * Return 1 if the fpga data is partial.
171 * This is only required for fpga drivers that support bitstream_type.
172 */
173int __weak fpga_is_partial_data(int devnum, size_t img_len)
174{
175 return 0;
176}
177
178/*
Michal Simekcd5a1cf2013-04-26 13:12:07 +0200179 * Convert bitstream data and load into the fpga
180 */
Michal Simek14663652014-05-02 14:09:30 +0200181int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
182 bitstream_type bstype)
Michal Simekcd5a1cf2013-04-26 13:12:07 +0200183{
184 printf("Bitstream support not implemented for this FPGA device\n");
185 return FPGA_FAIL;
186}
187
Siva Durga Prasad Paladugu9112b4c2014-03-14 16:35:37 +0530188#if defined(CONFIG_CMD_FPGA_LOADFS)
189int 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
Oleksandr Suvorovfbe31bb2022-07-22 17:16:02 +0300216#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE)
Siva Durga Prasad Paladugucce0cb02018-05-31 15:10:22 +0530217int 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
Christian Taedckedf369812023-07-20 09:27:24 +0200245static 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
Michal Simekcd5a1cf2013-04-26 13:12:07 +0200260/*
Michal Simek5125ba12013-04-26 08:46:56 +0200261 * Generic multiplexing code
wdenke2211742002-11-02 23:30:20 +0000262 */
Oleksandr Suvorov4ff163d2022-07-22 17:16:07 +0300263int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype,
264 int flags)
wdenke2211742002-11-02 23:30:20 +0000265{
266 int ret_val = FPGA_FAIL; /* assume failure */
Christian Taedckedf369812023-07-20 09:27:24 +0200267 int ret_notify;
Michal Simek5125ba12013-04-26 08:46:56 +0200268 const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
269 (char *)__func__);
wdenke2211742002-11-02 23:30:20 +0000270
Michal Simek5125ba12013-04-26 08:46:56 +0200271 if (desc) {
272 switch (desc->devtype) {
wdenke2211742002-11-02 23:30:20 +0000273 case fpga_xilinx:
Matthias Fuchsa4400872007-12-27 17:12:34 +0100274#if defined(CONFIG_FPGA_XILINX)
Michal Simek14663652014-05-02 14:09:30 +0200275 ret_val = xilinx_load(desc->devdesc, buf, bsize,
Oleksandr Suvorov4ff163d2022-07-22 17:16:07 +0300276 bstype, flags);
wdenke2211742002-11-02 23:30:20 +0000277#else
Michal Simek5125ba12013-04-26 08:46:56 +0200278 fpga_no_sup((char *)__func__, "Xilinx devices");
wdenke2211742002-11-02 23:30:20 +0000279#endif
280 break;
281 case fpga_altera:
Matthias Fuchsa4400872007-12-27 17:12:34 +0100282#if defined(CONFIG_FPGA_ALTERA)
Michal Simek5125ba12013-04-26 08:46:56 +0200283 ret_val = altera_load(desc->devdesc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +0000284#else
Michal Simek5125ba12013-04-26 08:46:56 +0200285 fpga_no_sup((char *)__func__, "Altera devices");
wdenke2211742002-11-02 23:30:20 +0000286#endif
287 break;
Stefano Babicec65c592010-06-29 11:47:48 +0200288 case fpga_lattice:
Wolfgang Denkace143a2010-10-18 21:32:14 +0200289#if defined(CONFIG_FPGA_LATTICE)
Stefano Babicec65c592010-06-29 11:47:48 +0200290 ret_val = lattice_load(desc->devdesc, buf, bsize);
Wolfgang Denkace143a2010-10-18 21:32:14 +0200291#else
Michal Simek5125ba12013-04-26 08:46:56 +0200292 fpga_no_sup((char *)__func__, "Lattice devices");
Wolfgang Denkace143a2010-10-18 21:32:14 +0200293#endif
Stefano Babicec65c592010-06-29 11:47:48 +0200294 break;
wdenke2211742002-11-02 23:30:20 +0000295 default:
Michal Simek5125ba12013-04-26 08:46:56 +0200296 printf("%s: Invalid or unsupported device type %d\n",
297 __func__, desc->devtype);
wdenke2211742002-11-02 23:30:20 +0000298 }
299 }
300
Christian Taedckedf369812023-07-20 09:27:24 +0200301 ret_notify = fpga_load_event_notify(buf, bsize, ret_val);
302 if (ret_notify)
303 return ret_notify;
304
wdenke2211742002-11-02 23:30:20 +0000305 return ret_val;
306}
307
Michal Simek5125ba12013-04-26 08:46:56 +0200308/*
309 * fpga_dump
wdenke2211742002-11-02 23:30:20 +0000310 * generic multiplexing code
311 */
Wolfgang Denk74f9b382011-07-30 13:33:49 +0000312int fpga_dump(int devnum, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +0000313{
314 int ret_val = FPGA_FAIL; /* assume failure */
Michal Simek5125ba12013-04-26 08:46:56 +0200315 const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
316 (char *)__func__);
wdenke2211742002-11-02 23:30:20 +0000317
Michal Simek5125ba12013-04-26 08:46:56 +0200318 if (desc) {
319 switch (desc->devtype) {
wdenke2211742002-11-02 23:30:20 +0000320 case fpga_xilinx:
Matthias Fuchsa4400872007-12-27 17:12:34 +0100321#if defined(CONFIG_FPGA_XILINX)
Michal Simek5125ba12013-04-26 08:46:56 +0200322 ret_val = xilinx_dump(desc->devdesc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +0000323#else
Michal Simek5125ba12013-04-26 08:46:56 +0200324 fpga_no_sup((char *)__func__, "Xilinx devices");
wdenke2211742002-11-02 23:30:20 +0000325#endif
326 break;
327 case fpga_altera:
Matthias Fuchsa4400872007-12-27 17:12:34 +0100328#if defined(CONFIG_FPGA_ALTERA)
Michal Simek5125ba12013-04-26 08:46:56 +0200329 ret_val = altera_dump(desc->devdesc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +0000330#else
Michal Simek5125ba12013-04-26 08:46:56 +0200331 fpga_no_sup((char *)__func__, "Altera devices");
wdenke2211742002-11-02 23:30:20 +0000332#endif
333 break;
Stefano Babicec65c592010-06-29 11:47:48 +0200334 case fpga_lattice:
Wolfgang Denkace143a2010-10-18 21:32:14 +0200335#if defined(CONFIG_FPGA_LATTICE)
Stefano Babicec65c592010-06-29 11:47:48 +0200336 ret_val = lattice_dump(desc->devdesc, buf, bsize);
Wolfgang Denkace143a2010-10-18 21:32:14 +0200337#else
Michal Simek5125ba12013-04-26 08:46:56 +0200338 fpga_no_sup((char *)__func__, "Lattice devices");
Wolfgang Denkace143a2010-10-18 21:32:14 +0200339#endif
Stefano Babicec65c592010-06-29 11:47:48 +0200340 break;
wdenke2211742002-11-02 23:30:20 +0000341 default:
Michal Simek5125ba12013-04-26 08:46:56 +0200342 printf("%s: Invalid or unsupported device type %d\n",
343 __func__, desc->devtype);
wdenke2211742002-11-02 23:30:20 +0000344 }
345 }
346
347 return ret_val;
348}
349
Michal Simek5125ba12013-04-26 08:46:56 +0200350/*
351 * fpga_info
wdenke2211742002-11-02 23:30:20 +0000352 * front end to fpga_dev_info. If devnum is invalid, report on all
353 * available devices.
354 */
Michal Simek5125ba12013-04-26 08:46:56 +0200355int fpga_info(int devnum)
wdenke2211742002-11-02 23:30:20 +0000356{
Michal Simek5125ba12013-04-26 08:46:56 +0200357 if (devnum == FPGA_INVALID_DEVICE) {
358 if (next_desc > 0) {
wdenke2211742002-11-02 23:30:20 +0000359 int dev;
360
Michal Simek5125ba12013-04-26 08:46:56 +0200361 for (dev = 0; dev < next_desc; dev++)
362 fpga_dev_info(dev);
363
wdenke2211742002-11-02 23:30:20 +0000364 return FPGA_SUCCESS;
365 } else {
Michal Simek5125ba12013-04-26 08:46:56 +0200366 printf("%s: No FPGA devices available.\n", __func__);
wdenke2211742002-11-02 23:30:20 +0000367 return FPGA_FAIL;
368 }
369 }
wdenke2211742002-11-02 23:30:20 +0000370
Michal Simek5125ba12013-04-26 08:46:56 +0200371 return fpga_dev_info(devnum);
372}
Oleksandr Suvorova4d95932022-07-22 17:16:08 +0300373
374#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE)
375int 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