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