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