Commit | Line | Data |
---|---|---|
473f01f7 | 1 | // SPDX-License-Identifier: GPL-2.0 |
6a8c3be7 AT |
2 | /* |
3 | * FPGA Manager Core | |
4 | * | |
5 | * Copyright (C) 2013-2015 Altera Corporation | |
5cf0c7f6 | 6 | * Copyright (C) 2017 Intel Corporation |
6a8c3be7 AT |
7 | * |
8 | * With code from the mailing list: | |
9 | * Copyright (C) 2013 Xilinx, Inc. | |
6a8c3be7 AT |
10 | */ |
11 | #include <linux/firmware.h> | |
12 | #include <linux/fpga/fpga-mgr.h> | |
13 | #include <linux/idr.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/of.h> | |
16 | #include <linux/mutex.h> | |
17 | #include <linux/slab.h> | |
baa6d396 JG |
18 | #include <linux/scatterlist.h> |
19 | #include <linux/highmem.h> | |
6a8c3be7 AT |
20 | |
21 | static DEFINE_IDA(fpga_mgr_ida); | |
22 | static struct class *fpga_mgr_class; | |
23 | ||
57d9352b MF |
24 | struct fpga_mgr_devres { |
25 | struct fpga_manager *mgr; | |
26 | }; | |
27 | ||
6489d3b0 TR |
28 | static inline void fpga_mgr_fpga_remove(struct fpga_manager *mgr) |
29 | { | |
30 | if (mgr->mops->fpga_remove) | |
31 | mgr->mops->fpga_remove(mgr); | |
32 | } | |
33 | ||
b02a4071 TR |
34 | static inline enum fpga_mgr_states fpga_mgr_state(struct fpga_manager *mgr) |
35 | { | |
36 | if (mgr->mops->state) | |
37 | return mgr->mops->state(mgr); | |
38 | return FPGA_MGR_STATE_UNKNOWN; | |
39 | } | |
40 | ||
6f992271 TR |
41 | static inline u64 fpga_mgr_status(struct fpga_manager *mgr) |
42 | { | |
43 | if (mgr->mops->status) | |
44 | return mgr->mops->status(mgr); | |
45 | return 0; | |
46 | } | |
47 | ||
8ebab40f TR |
48 | static inline int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count) |
49 | { | |
50 | if (mgr->mops->write) | |
51 | return mgr->mops->write(mgr, buf, count); | |
52 | return -EOPNOTSUPP; | |
53 | } | |
54 | ||
72d93502 TR |
55 | /* |
56 | * After all the FPGA image has been written, do the device specific steps to | |
57 | * finish and set the FPGA into operating mode. | |
58 | */ | |
59 | static inline int fpga_mgr_write_complete(struct fpga_manager *mgr, | |
60 | struct fpga_image_info *info) | |
61 | { | |
62 | int ret = 0; | |
63 | ||
64 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE; | |
65 | if (mgr->mops->write_complete) | |
66 | ret = mgr->mops->write_complete(mgr, info); | |
67 | if (ret) { | |
68 | dev_err(&mgr->dev, "Error after writing image data to FPGA\n"); | |
69 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR; | |
70 | return ret; | |
71 | } | |
72 | mgr->state = FPGA_MGR_STATE_OPERATING; | |
73 | ||
74 | return 0; | |
75 | } | |
76 | ||
3cc624be IB |
77 | static inline int fpga_mgr_parse_header(struct fpga_manager *mgr, |
78 | struct fpga_image_info *info, | |
79 | const char *buf, size_t count) | |
80 | { | |
81 | if (mgr->mops->parse_header) | |
82 | return mgr->mops->parse_header(mgr, info, buf, count); | |
83 | return 0; | |
84 | } | |
85 | ||
2e8438b7 TR |
86 | static inline int fpga_mgr_write_init(struct fpga_manager *mgr, |
87 | struct fpga_image_info *info, | |
88 | const char *buf, size_t count) | |
89 | { | |
90 | if (mgr->mops->write_init) | |
91 | return mgr->mops->write_init(mgr, info, buf, count); | |
92 | return 0; | |
93 | } | |
94 | ||
630211a1 TR |
95 | static inline int fpga_mgr_write_sg(struct fpga_manager *mgr, |
96 | struct sg_table *sgt) | |
97 | { | |
98 | if (mgr->mops->write_sg) | |
99 | return mgr->mops->write_sg(mgr, sgt); | |
100 | return -EOPNOTSUPP; | |
101 | } | |
102 | ||
ff9da89c | 103 | /** |
895ec9c0 | 104 | * fpga_image_info_alloc - Allocate an FPGA image info struct |
ff9da89c AT |
105 | * @dev: owning device |
106 | * | |
107 | * Return: struct fpga_image_info or NULL | |
108 | */ | |
5cf0c7f6 AT |
109 | struct fpga_image_info *fpga_image_info_alloc(struct device *dev) |
110 | { | |
111 | struct fpga_image_info *info; | |
112 | ||
113 | get_device(dev); | |
114 | ||
115 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | |
116 | if (!info) { | |
117 | put_device(dev); | |
118 | return NULL; | |
119 | } | |
120 | ||
121 | info->dev = dev; | |
122 | ||
123 | return info; | |
124 | } | |
125 | EXPORT_SYMBOL_GPL(fpga_image_info_alloc); | |
126 | ||
ff9da89c | 127 | /** |
895ec9c0 | 128 | * fpga_image_info_free - Free an FPGA image info struct |
ff9da89c AT |
129 | * @info: FPGA image info struct to free |
130 | */ | |
5cf0c7f6 AT |
131 | void fpga_image_info_free(struct fpga_image_info *info) |
132 | { | |
133 | struct device *dev; | |
134 | ||
135 | if (!info) | |
136 | return; | |
137 | ||
138 | dev = info->dev; | |
139 | if (info->firmware_name) | |
140 | devm_kfree(dev, info->firmware_name); | |
141 | ||
142 | devm_kfree(dev, info); | |
143 | put_device(dev); | |
144 | } | |
145 | EXPORT_SYMBOL_GPL(fpga_image_info_free); | |
146 | ||
baa6d396 | 147 | /* |
3cc624be IB |
148 | * Call the low level driver's parse_header function with entire FPGA image |
149 | * buffer on the input. This will set info->header_size and info->data_size. | |
150 | */ | |
151 | static int fpga_mgr_parse_header_mapped(struct fpga_manager *mgr, | |
152 | struct fpga_image_info *info, | |
153 | const char *buf, size_t count) | |
154 | { | |
155 | int ret; | |
156 | ||
157 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER; | |
158 | ret = fpga_mgr_parse_header(mgr, info, buf, count); | |
159 | ||
160 | if (info->header_size + info->data_size > count) { | |
ee794221 | 161 | dev_err(&mgr->dev, "Bitstream data outruns FPGA image\n"); |
3cc624be IB |
162 | ret = -EINVAL; |
163 | } | |
164 | ||
165 | if (ret) { | |
166 | dev_err(&mgr->dev, "Error while parsing FPGA image header\n"); | |
167 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER_ERR; | |
168 | } | |
169 | ||
170 | return ret; | |
171 | } | |
172 | ||
173 | /* | |
174 | * Call the low level driver's parse_header function with first fragment of | |
175 | * scattered FPGA image on the input. If header fits first fragment, | |
176 | * parse_header will set info->header_size and info->data_size. If it is not, | |
177 | * parse_header will set desired size to info->header_size and -EAGAIN will be | |
178 | * returned. | |
179 | */ | |
180 | static int fpga_mgr_parse_header_sg_first(struct fpga_manager *mgr, | |
181 | struct fpga_image_info *info, | |
182 | struct sg_table *sgt) | |
183 | { | |
184 | struct sg_mapping_iter miter; | |
185 | int ret; | |
186 | ||
187 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER; | |
188 | ||
189 | sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG); | |
190 | if (sg_miter_next(&miter) && | |
191 | miter.length >= info->header_size) | |
192 | ret = fpga_mgr_parse_header(mgr, info, miter.addr, miter.length); | |
193 | else | |
194 | ret = -EAGAIN; | |
195 | sg_miter_stop(&miter); | |
196 | ||
197 | if (ret && ret != -EAGAIN) { | |
198 | dev_err(&mgr->dev, "Error while parsing FPGA image header\n"); | |
199 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER_ERR; | |
200 | } | |
201 | ||
202 | return ret; | |
203 | } | |
204 | ||
205 | /* | |
206 | * Copy scattered FPGA image fragments to temporary buffer and call the | |
207 | * low level driver's parse_header function. This should be called after | |
208 | * fpga_mgr_parse_header_sg_first() returned -EAGAIN. In case of success, | |
209 | * pointer to the newly allocated image header copy will be returned and | |
210 | * its size will be set into *ret_size. Returned buffer needs to be freed. | |
211 | */ | |
212 | static void *fpga_mgr_parse_header_sg(struct fpga_manager *mgr, | |
213 | struct fpga_image_info *info, | |
214 | struct sg_table *sgt, size_t *ret_size) | |
215 | { | |
216 | size_t len, new_header_size, header_size = 0; | |
217 | char *new_buf, *buf = NULL; | |
218 | int ret; | |
219 | ||
220 | do { | |
221 | new_header_size = info->header_size; | |
222 | if (new_header_size <= header_size) { | |
223 | dev_err(&mgr->dev, "Requested invalid header size\n"); | |
224 | ret = -EFAULT; | |
225 | break; | |
226 | } | |
227 | ||
228 | new_buf = krealloc(buf, new_header_size, GFP_KERNEL); | |
229 | if (!new_buf) { | |
230 | ret = -ENOMEM; | |
231 | break; | |
232 | } | |
233 | ||
234 | buf = new_buf; | |
235 | ||
236 | len = sg_pcopy_to_buffer(sgt->sgl, sgt->nents, | |
237 | buf + header_size, | |
238 | new_header_size - header_size, | |
239 | header_size); | |
240 | if (len != new_header_size - header_size) { | |
241 | ret = -EFAULT; | |
242 | break; | |
243 | } | |
244 | ||
245 | header_size = new_header_size; | |
246 | ret = fpga_mgr_parse_header(mgr, info, buf, header_size); | |
247 | } while (ret == -EAGAIN); | |
248 | ||
249 | if (ret) { | |
250 | dev_err(&mgr->dev, "Error while parsing FPGA image header\n"); | |
251 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER_ERR; | |
252 | kfree(buf); | |
253 | buf = ERR_PTR(ret); | |
254 | } | |
255 | ||
256 | *ret_size = header_size; | |
257 | ||
258 | return buf; | |
259 | } | |
260 | ||
261 | /* | |
262 | * Call the low level driver's write_init function. This will do the | |
baa6d396 | 263 | * device-specific things to get the FPGA into the state where it is ready to |
3cc624be IB |
264 | * receive an FPGA image. The low level driver gets to see at least first |
265 | * info->header_size bytes in the buffer. If info->header_size is 0, | |
266 | * write_init will not get any bytes of image buffer. | |
baa6d396 JG |
267 | */ |
268 | static int fpga_mgr_write_init_buf(struct fpga_manager *mgr, | |
269 | struct fpga_image_info *info, | |
270 | const char *buf, size_t count) | |
271 | { | |
3cc624be | 272 | size_t header_size = info->header_size; |
baa6d396 JG |
273 | int ret; |
274 | ||
275 | mgr->state = FPGA_MGR_STATE_WRITE_INIT; | |
3cc624be IB |
276 | |
277 | if (header_size > count) | |
278 | ret = -EINVAL; | |
279 | else if (!header_size) | |
2e8438b7 | 280 | ret = fpga_mgr_write_init(mgr, info, NULL, 0); |
3cc624be | 281 | else |
57ce2e40 | 282 | ret = fpga_mgr_write_init(mgr, info, buf, count); |
baa6d396 JG |
283 | |
284 | if (ret) { | |
285 | dev_err(&mgr->dev, "Error preparing FPGA for writing\n"); | |
286 | mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR; | |
287 | return ret; | |
288 | } | |
289 | ||
290 | return 0; | |
291 | } | |
292 | ||
3cc624be IB |
293 | static int fpga_mgr_prepare_sg(struct fpga_manager *mgr, |
294 | struct fpga_image_info *info, | |
295 | struct sg_table *sgt) | |
baa6d396 JG |
296 | { |
297 | struct sg_mapping_iter miter; | |
298 | size_t len; | |
299 | char *buf; | |
300 | int ret; | |
301 | ||
3cc624be IB |
302 | /* Short path. Low level driver don't care about image header. */ |
303 | if (!mgr->mops->initial_header_size && !mgr->mops->parse_header) | |
baa6d396 JG |
304 | return fpga_mgr_write_init_buf(mgr, info, NULL, 0); |
305 | ||
306 | /* | |
307 | * First try to use miter to map the first fragment to access the | |
308 | * header, this is the typical path. | |
309 | */ | |
3cc624be IB |
310 | ret = fpga_mgr_parse_header_sg_first(mgr, info, sgt); |
311 | /* If 0, header fits first fragment, call write_init on it */ | |
312 | if (!ret) { | |
313 | sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG); | |
314 | if (sg_miter_next(&miter)) { | |
315 | ret = fpga_mgr_write_init_buf(mgr, info, miter.addr, | |
316 | miter.length); | |
317 | sg_miter_stop(&miter); | |
318 | return ret; | |
319 | } | |
baa6d396 | 320 | sg_miter_stop(&miter); |
3cc624be IB |
321 | /* |
322 | * If -EAGAIN, more sg buffer is needed, | |
323 | * otherwise an error has occurred. | |
324 | */ | |
325 | } else if (ret != -EAGAIN) { | |
baa6d396 JG |
326 | return ret; |
327 | } | |
baa6d396 | 328 | |
3cc624be IB |
329 | /* |
330 | * Copy the fragments into temporary memory. | |
331 | * Copying is done inside fpga_mgr_parse_header_sg(). | |
332 | */ | |
333 | buf = fpga_mgr_parse_header_sg(mgr, info, sgt, &len); | |
334 | if (IS_ERR(buf)) | |
335 | return PTR_ERR(buf); | |
baa6d396 | 336 | |
baa6d396 JG |
337 | ret = fpga_mgr_write_init_buf(mgr, info, buf, len); |
338 | ||
339 | kfree(buf); | |
340 | ||
341 | return ret; | |
342 | } | |
343 | ||
6a8c3be7 | 344 | /** |
baa6d396 | 345 | * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list |
6a8c3be7 | 346 | * @mgr: fpga manager |
1df2865f | 347 | * @info: fpga image specific information |
baa6d396 | 348 | * @sgt: scatterlist table |
6a8c3be7 AT |
349 | * |
350 | * Step the low level fpga manager through the device-specific steps of getting | |
351 | * an FPGA ready to be configured, writing the image to it, then doing whatever | |
92d94a7e | 352 | * post-configuration steps necessary. This code assumes the caller got the |
9dce0287 AT |
353 | * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is |
354 | * not an error code. | |
6a8c3be7 | 355 | * |
baa6d396 JG |
356 | * This is the preferred entry point for FPGA programming, it does not require |
357 | * any contiguous kernel memory. | |
358 | * | |
6a8c3be7 AT |
359 | * Return: 0 on success, negative error code otherwise. |
360 | */ | |
5cf0c7f6 AT |
361 | static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, |
362 | struct fpga_image_info *info, | |
363 | struct sg_table *sgt) | |
6a8c3be7 | 364 | { |
6a8c3be7 AT |
365 | int ret; |
366 | ||
3cc624be | 367 | ret = fpga_mgr_prepare_sg(mgr, info, sgt); |
baa6d396 JG |
368 | if (ret) |
369 | return ret; | |
370 | ||
371 | /* Write the FPGA image to the FPGA. */ | |
372 | mgr->state = FPGA_MGR_STATE_WRITE; | |
373 | if (mgr->mops->write_sg) { | |
630211a1 | 374 | ret = fpga_mgr_write_sg(mgr, sgt); |
baa6d396 | 375 | } else { |
3cc624be | 376 | size_t length, count = 0, data_size = info->data_size; |
baa6d396 JG |
377 | struct sg_mapping_iter miter; |
378 | ||
379 | sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG); | |
3cc624be IB |
380 | |
381 | if (mgr->mops->skip_header && | |
382 | !sg_miter_skip(&miter, info->header_size)) { | |
383 | ret = -EINVAL; | |
384 | goto out; | |
385 | } | |
386 | ||
baa6d396 | 387 | while (sg_miter_next(&miter)) { |
3cc624be IB |
388 | if (data_size) |
389 | length = min(miter.length, data_size - count); | |
390 | else | |
391 | length = miter.length; | |
392 | ||
393 | ret = fpga_mgr_write(mgr, miter.addr, length); | |
baa6d396 JG |
394 | if (ret) |
395 | break; | |
3cc624be IB |
396 | |
397 | count += length; | |
398 | if (data_size && count >= data_size) | |
399 | break; | |
baa6d396 JG |
400 | } |
401 | sg_miter_stop(&miter); | |
402 | } | |
403 | ||
3cc624be | 404 | out: |
6a8c3be7 | 405 | if (ret) { |
baa6d396 JG |
406 | dev_err(&mgr->dev, "Error while writing image data to FPGA\n"); |
407 | mgr->state = FPGA_MGR_STATE_WRITE_ERR; | |
6a8c3be7 AT |
408 | return ret; |
409 | } | |
410 | ||
baa6d396 JG |
411 | return fpga_mgr_write_complete(mgr, info); |
412 | } | |
baa6d396 JG |
413 | |
414 | static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, | |
415 | struct fpga_image_info *info, | |
416 | const char *buf, size_t count) | |
417 | { | |
418 | int ret; | |
419 | ||
3cc624be IB |
420 | ret = fpga_mgr_parse_header_mapped(mgr, info, buf, count); |
421 | if (ret) | |
422 | return ret; | |
423 | ||
baa6d396 JG |
424 | ret = fpga_mgr_write_init_buf(mgr, info, buf, count); |
425 | if (ret) | |
426 | return ret; | |
427 | ||
3cc624be IB |
428 | if (mgr->mops->skip_header) { |
429 | buf += info->header_size; | |
430 | count -= info->header_size; | |
431 | } | |
432 | ||
433 | if (info->data_size) | |
434 | count = info->data_size; | |
435 | ||
6a8c3be7 AT |
436 | /* |
437 | * Write the FPGA image to the FPGA. | |
438 | */ | |
439 | mgr->state = FPGA_MGR_STATE_WRITE; | |
8ebab40f | 440 | ret = fpga_mgr_write(mgr, buf, count); |
6a8c3be7 | 441 | if (ret) { |
baa6d396 | 442 | dev_err(&mgr->dev, "Error while writing image data to FPGA\n"); |
6a8c3be7 AT |
443 | mgr->state = FPGA_MGR_STATE_WRITE_ERR; |
444 | return ret; | |
445 | } | |
446 | ||
baa6d396 JG |
447 | return fpga_mgr_write_complete(mgr, info); |
448 | } | |
449 | ||
450 | /** | |
451 | * fpga_mgr_buf_load - load fpga from image in buffer | |
452 | * @mgr: fpga manager | |
ff9da89c | 453 | * @info: fpga image info |
baa6d396 JG |
454 | * @buf: buffer contain fpga image |
455 | * @count: byte count of buf | |
456 | * | |
457 | * Step the low level fpga manager through the device-specific steps of getting | |
458 | * an FPGA ready to be configured, writing the image to it, then doing whatever | |
459 | * post-configuration steps necessary. This code assumes the caller got the | |
460 | * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code. | |
461 | * | |
462 | * Return: 0 on success, negative error code otherwise. | |
463 | */ | |
5cf0c7f6 AT |
464 | static int fpga_mgr_buf_load(struct fpga_manager *mgr, |
465 | struct fpga_image_info *info, | |
466 | const char *buf, size_t count) | |
baa6d396 JG |
467 | { |
468 | struct page **pages; | |
469 | struct sg_table sgt; | |
470 | const void *p; | |
471 | int nr_pages; | |
472 | int index; | |
473 | int rc; | |
474 | ||
6a8c3be7 | 475 | /* |
baa6d396 JG |
476 | * This is just a fast path if the caller has already created a |
477 | * contiguous kernel buffer and the driver doesn't require SG, non-SG | |
478 | * drivers will still work on the slow path. | |
6a8c3be7 | 479 | */ |
baa6d396 JG |
480 | if (mgr->mops->write) |
481 | return fpga_mgr_buf_load_mapped(mgr, info, buf, count); | |
482 | ||
483 | /* | |
484 | * Convert the linear kernel pointer into a sg_table of pages for use | |
485 | * by the driver. | |
486 | */ | |
487 | nr_pages = DIV_ROUND_UP((unsigned long)buf + count, PAGE_SIZE) - | |
488 | (unsigned long)buf / PAGE_SIZE; | |
489 | pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL); | |
490 | if (!pages) | |
491 | return -ENOMEM; | |
492 | ||
493 | p = buf - offset_in_page(buf); | |
494 | for (index = 0; index < nr_pages; index++) { | |
495 | if (is_vmalloc_addr(p)) | |
496 | pages[index] = vmalloc_to_page(p); | |
497 | else | |
498 | pages[index] = kmap_to_page((void *)p); | |
499 | if (!pages[index]) { | |
500 | kfree(pages); | |
501 | return -EFAULT; | |
502 | } | |
503 | p += PAGE_SIZE; | |
6a8c3be7 | 504 | } |
6a8c3be7 | 505 | |
baa6d396 JG |
506 | /* |
507 | * The temporary pages list is used to code share the merging algorithm | |
508 | * in sg_alloc_table_from_pages | |
509 | */ | |
510 | rc = sg_alloc_table_from_pages(&sgt, pages, index, offset_in_page(buf), | |
511 | count, GFP_KERNEL); | |
512 | kfree(pages); | |
513 | if (rc) | |
514 | return rc; | |
515 | ||
516 | rc = fpga_mgr_buf_load_sg(mgr, info, &sgt); | |
517 | sg_free_table(&sgt); | |
518 | ||
519 | return rc; | |
6a8c3be7 | 520 | } |
6a8c3be7 AT |
521 | |
522 | /** | |
523 | * fpga_mgr_firmware_load - request firmware and load to fpga | |
524 | * @mgr: fpga manager | |
1df2865f | 525 | * @info: fpga image specific information |
6a8c3be7 AT |
526 | * @image_name: name of image file on the firmware search path |
527 | * | |
528 | * Request an FPGA image using the firmware class, then write out to the FPGA. | |
529 | * Update the state before each step to provide info on what step failed if | |
92d94a7e | 530 | * there is a failure. This code assumes the caller got the mgr pointer |
9dce0287 AT |
531 | * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error |
532 | * code. | |
6a8c3be7 AT |
533 | * |
534 | * Return: 0 on success, negative error code otherwise. | |
535 | */ | |
5cf0c7f6 AT |
536 | static int fpga_mgr_firmware_load(struct fpga_manager *mgr, |
537 | struct fpga_image_info *info, | |
538 | const char *image_name) | |
6a8c3be7 AT |
539 | { |
540 | struct device *dev = &mgr->dev; | |
541 | const struct firmware *fw; | |
542 | int ret; | |
543 | ||
6a8c3be7 AT |
544 | dev_info(dev, "writing %s to %s\n", image_name, mgr->name); |
545 | ||
546 | mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ; | |
547 | ||
548 | ret = request_firmware(&fw, image_name, dev); | |
549 | if (ret) { | |
550 | mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR; | |
551 | dev_err(dev, "Error requesting firmware %s\n", image_name); | |
552 | return ret; | |
553 | } | |
554 | ||
1df2865f | 555 | ret = fpga_mgr_buf_load(mgr, info, fw->data, fw->size); |
6a8c3be7 AT |
556 | |
557 | release_firmware(fw); | |
558 | ||
e8c77bda | 559 | return ret; |
6a8c3be7 | 560 | } |
5cf0c7f6 | 561 | |
ff9da89c AT |
562 | /** |
563 | * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware | |
564 | * @mgr: fpga manager | |
565 | * @info: fpga image information. | |
566 | * | |
567 | * Load the FPGA from an image which is indicated in @info. If successful, the | |
568 | * FPGA ends up in operating mode. | |
569 | * | |
570 | * Return: 0 on success, negative error code otherwise. | |
571 | */ | |
5cf0c7f6 AT |
572 | int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) |
573 | { | |
3cc624be IB |
574 | info->header_size = mgr->mops->initial_header_size; |
575 | ||
5cf0c7f6 AT |
576 | if (info->sgt) |
577 | return fpga_mgr_buf_load_sg(mgr, info, info->sgt); | |
578 | if (info->buf && info->count) | |
579 | return fpga_mgr_buf_load(mgr, info, info->buf, info->count); | |
580 | if (info->firmware_name) | |
581 | return fpga_mgr_firmware_load(mgr, info, info->firmware_name); | |
582 | return -EINVAL; | |
583 | } | |
584 | EXPORT_SYMBOL_GPL(fpga_mgr_load); | |
6a8c3be7 AT |
585 | |
586 | static const char * const state_str[] = { | |
587 | [FPGA_MGR_STATE_UNKNOWN] = "unknown", | |
588 | [FPGA_MGR_STATE_POWER_OFF] = "power off", | |
589 | [FPGA_MGR_STATE_POWER_UP] = "power up", | |
590 | [FPGA_MGR_STATE_RESET] = "reset", | |
591 | ||
592 | /* requesting FPGA image from firmware */ | |
593 | [FPGA_MGR_STATE_FIRMWARE_REQ] = "firmware request", | |
594 | [FPGA_MGR_STATE_FIRMWARE_REQ_ERR] = "firmware request error", | |
595 | ||
3cc624be IB |
596 | /* Parse FPGA image header */ |
597 | [FPGA_MGR_STATE_PARSE_HEADER] = "parse header", | |
598 | [FPGA_MGR_STATE_PARSE_HEADER_ERR] = "parse header error", | |
599 | ||
6a8c3be7 AT |
600 | /* Preparing FPGA to receive image */ |
601 | [FPGA_MGR_STATE_WRITE_INIT] = "write init", | |
602 | [FPGA_MGR_STATE_WRITE_INIT_ERR] = "write init error", | |
603 | ||
604 | /* Writing image to FPGA */ | |
605 | [FPGA_MGR_STATE_WRITE] = "write", | |
606 | [FPGA_MGR_STATE_WRITE_ERR] = "write error", | |
607 | ||
608 | /* Finishing configuration after image has been written */ | |
609 | [FPGA_MGR_STATE_WRITE_COMPLETE] = "write complete", | |
610 | [FPGA_MGR_STATE_WRITE_COMPLETE_ERR] = "write complete error", | |
611 | ||
612 | /* FPGA reports to be in normal operating mode */ | |
613 | [FPGA_MGR_STATE_OPERATING] = "operating", | |
614 | }; | |
615 | ||
616 | static ssize_t name_show(struct device *dev, | |
617 | struct device_attribute *attr, char *buf) | |
618 | { | |
619 | struct fpga_manager *mgr = to_fpga_manager(dev); | |
620 | ||
621 | return sprintf(buf, "%s\n", mgr->name); | |
622 | } | |
623 | ||
624 | static ssize_t state_show(struct device *dev, | |
625 | struct device_attribute *attr, char *buf) | |
626 | { | |
627 | struct fpga_manager *mgr = to_fpga_manager(dev); | |
628 | ||
629 | return sprintf(buf, "%s\n", state_str[mgr->state]); | |
630 | } | |
631 | ||
ecb5fbe2 WH |
632 | static ssize_t status_show(struct device *dev, |
633 | struct device_attribute *attr, char *buf) | |
634 | { | |
635 | struct fpga_manager *mgr = to_fpga_manager(dev); | |
636 | u64 status; | |
637 | int len = 0; | |
638 | ||
6f992271 | 639 | status = fpga_mgr_status(mgr); |
ecb5fbe2 WH |
640 | |
641 | if (status & FPGA_MGR_STATUS_OPERATION_ERR) | |
642 | len += sprintf(buf + len, "reconfig operation error\n"); | |
643 | if (status & FPGA_MGR_STATUS_CRC_ERR) | |
644 | len += sprintf(buf + len, "reconfig CRC error\n"); | |
645 | if (status & FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR) | |
646 | len += sprintf(buf + len, "reconfig incompatible image\n"); | |
647 | if (status & FPGA_MGR_STATUS_IP_PROTOCOL_ERR) | |
648 | len += sprintf(buf + len, "reconfig IP protocol error\n"); | |
649 | if (status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR) | |
650 | len += sprintf(buf + len, "reconfig fifo overflow error\n"); | |
651 | ||
652 | return len; | |
653 | } | |
654 | ||
6a8c3be7 AT |
655 | static DEVICE_ATTR_RO(name); |
656 | static DEVICE_ATTR_RO(state); | |
ecb5fbe2 | 657 | static DEVICE_ATTR_RO(status); |
6a8c3be7 AT |
658 | |
659 | static struct attribute *fpga_mgr_attrs[] = { | |
660 | &dev_attr_name.attr, | |
661 | &dev_attr_state.attr, | |
ecb5fbe2 | 662 | &dev_attr_status.attr, |
6a8c3be7 AT |
663 | NULL, |
664 | }; | |
665 | ATTRIBUTE_GROUPS(fpga_mgr); | |
666 | ||
47910a49 | 667 | static struct fpga_manager *__fpga_mgr_get(struct device *dev) |
6a8c3be7 AT |
668 | { |
669 | struct fpga_manager *mgr; | |
6a8c3be7 | 670 | |
6a8c3be7 | 671 | mgr = to_fpga_manager(dev); |
6a8c3be7 | 672 | |
654ba4cc | 673 | if (!try_module_get(dev->parent->driver->owner)) |
ebf877a5 | 674 | goto err_dev; |
654ba4cc | 675 | |
6a8c3be7 | 676 | return mgr; |
654ba4cc | 677 | |
654ba4cc AT |
678 | err_dev: |
679 | put_device(dev); | |
ebf877a5 | 680 | return ERR_PTR(-ENODEV); |
6a8c3be7 | 681 | } |
9dce0287 AT |
682 | |
683 | static int fpga_mgr_dev_match(struct device *dev, const void *data) | |
684 | { | |
685 | return dev->parent == data; | |
686 | } | |
687 | ||
688 | /** | |
895ec9c0 | 689 | * fpga_mgr_get - Given a device, get a reference to an fpga mgr. |
9dce0287 AT |
690 | * @dev: parent device that fpga mgr was registered with |
691 | * | |
9dce0287 AT |
692 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
693 | */ | |
694 | struct fpga_manager *fpga_mgr_get(struct device *dev) | |
695 | { | |
696 | struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev, | |
697 | fpga_mgr_dev_match); | |
698 | if (!mgr_dev) | |
699 | return ERR_PTR(-ENODEV); | |
700 | ||
701 | return __fpga_mgr_get(mgr_dev); | |
702 | } | |
703 | EXPORT_SYMBOL_GPL(fpga_mgr_get); | |
704 | ||
9dce0287 | 705 | /** |
895ec9c0 | 706 | * of_fpga_mgr_get - Given a device node, get a reference to an fpga mgr. |
9dce0287 | 707 | * |
ff9da89c | 708 | * @node: device node |
9dce0287 AT |
709 | * |
710 | * Return: fpga manager struct or IS_ERR() condition containing error code. | |
711 | */ | |
712 | struct fpga_manager *of_fpga_mgr_get(struct device_node *node) | |
713 | { | |
714 | struct device *dev; | |
715 | ||
cfba5de9 | 716 | dev = class_find_device_by_of_node(fpga_mgr_class, node); |
9dce0287 AT |
717 | if (!dev) |
718 | return ERR_PTR(-ENODEV); | |
719 | ||
720 | return __fpga_mgr_get(dev); | |
721 | } | |
6a8c3be7 AT |
722 | EXPORT_SYMBOL_GPL(of_fpga_mgr_get); |
723 | ||
724 | /** | |
895ec9c0 | 725 | * fpga_mgr_put - release a reference to an fpga manager |
6a8c3be7 AT |
726 | * @mgr: fpga manager structure |
727 | */ | |
728 | void fpga_mgr_put(struct fpga_manager *mgr) | |
729 | { | |
654ba4cc | 730 | module_put(mgr->dev.parent->driver->owner); |
654ba4cc | 731 | put_device(&mgr->dev); |
6a8c3be7 AT |
732 | } |
733 | EXPORT_SYMBOL_GPL(fpga_mgr_put); | |
734 | ||
ebf877a5 AT |
735 | /** |
736 | * fpga_mgr_lock - Lock FPGA manager for exclusive use | |
737 | * @mgr: fpga manager | |
738 | * | |
739 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or | |
ff9da89c AT |
740 | * of_fpga_mgr_put()) attempt to get the mutex. The user should call |
741 | * fpga_mgr_lock() and verify that it returns 0 before attempting to | |
742 | * program the FPGA. Likewise, the user should call fpga_mgr_unlock | |
743 | * when done programming the FPGA. | |
ebf877a5 AT |
744 | * |
745 | * Return: 0 for success or -EBUSY | |
746 | */ | |
747 | int fpga_mgr_lock(struct fpga_manager *mgr) | |
748 | { | |
749 | if (!mutex_trylock(&mgr->ref_mutex)) { | |
750 | dev_err(&mgr->dev, "FPGA manager is in use.\n"); | |
751 | return -EBUSY; | |
752 | } | |
753 | ||
754 | return 0; | |
755 | } | |
756 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); | |
757 | ||
758 | /** | |
ff9da89c | 759 | * fpga_mgr_unlock - Unlock FPGA manager after done programming |
ebf877a5 AT |
760 | * @mgr: fpga manager |
761 | */ | |
762 | void fpga_mgr_unlock(struct fpga_manager *mgr) | |
763 | { | |
764 | mutex_unlock(&mgr->ref_mutex); | |
765 | } | |
766 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); | |
767 | ||
6a8c3be7 | 768 | /** |
4ba0b2c2 | 769 | * fpga_mgr_register_full - create and register an FPGA Manager device |
59ef3622 | 770 | * @parent: fpga manager device from pdev |
4ba0b2c2 | 771 | * @info: parameters for fpga manager |
6a8c3be7 | 772 | * |
4ba0b2c2 RW |
773 | * The caller of this function is responsible for calling fpga_mgr_unregister(). |
774 | * Using devm_fpga_mgr_register_full() instead is recommended. | |
084181fe | 775 | * |
4ba0b2c2 | 776 | * Return: pointer to struct fpga_manager pointer or ERR_PTR() |
6a8c3be7 | 777 | */ |
4ba0b2c2 RW |
778 | struct fpga_manager * |
779 | fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info) | |
6a8c3be7 | 780 | { |
4ba0b2c2 | 781 | const struct fpga_manager_ops *mops = info->mops; |
6a8c3be7 | 782 | struct fpga_manager *mgr; |
6a8c3be7 AT |
783 | int id, ret; |
784 | ||
b02a4071 | 785 | if (!mops) { |
59ef3622 | 786 | dev_err(parent, "Attempt to register without fpga_manager_ops\n"); |
4ba0b2c2 | 787 | return ERR_PTR(-EINVAL); |
6a8c3be7 AT |
788 | } |
789 | ||
4ba0b2c2 | 790 | if (!info->name || !strlen(info->name)) { |
59ef3622 | 791 | dev_err(parent, "Attempt to register with no name!\n"); |
4ba0b2c2 | 792 | return ERR_PTR(-EINVAL); |
6a8c3be7 AT |
793 | } |
794 | ||
795 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | |
796 | if (!mgr) | |
4ba0b2c2 | 797 | return ERR_PTR(-ENOMEM); |
6a8c3be7 | 798 | |
a5e3d775 | 799 | id = ida_alloc(&fpga_mgr_ida, GFP_KERNEL); |
4ba0b2c2 RW |
800 | if (id < 0) { |
801 | ret = id; | |
6a8c3be7 | 802 | goto error_kfree; |
4ba0b2c2 | 803 | } |
6a8c3be7 AT |
804 | |
805 | mutex_init(&mgr->ref_mutex); | |
806 | ||
4ba0b2c2 RW |
807 | mgr->name = info->name; |
808 | mgr->mops = info->mops; | |
809 | mgr->priv = info->priv; | |
810 | mgr->compat_id = info->compat_id; | |
6a8c3be7 | 811 | |
6a8c3be7 | 812 | mgr->dev.class = fpga_mgr_class; |
845089bb | 813 | mgr->dev.groups = mops->groups; |
59ef3622 RW |
814 | mgr->dev.parent = parent; |
815 | mgr->dev.of_node = parent->of_node; | |
6a8c3be7 | 816 | mgr->dev.id = id; |
6a8c3be7 | 817 | |
07687c03 AT |
818 | ret = dev_set_name(&mgr->dev, "fpga%d", id); |
819 | if (ret) | |
820 | goto error_device; | |
6a8c3be7 | 821 | |
4ba0b2c2 RW |
822 | /* |
823 | * Initialize framework state by requesting low level driver read state | |
824 | * from device. FPGA may be in reset mode or may have been programmed | |
825 | * by bootloader or EEPROM. | |
826 | */ | |
827 | mgr->state = fpga_mgr_state(mgr); | |
828 | ||
829 | ret = device_register(&mgr->dev); | |
830 | if (ret) { | |
831 | put_device(&mgr->dev); | |
832 | return ERR_PTR(ret); | |
833 | } | |
834 | ||
7085e2a9 AT |
835 | return mgr; |
836 | ||
837 | error_device: | |
a5e3d775 | 838 | ida_free(&fpga_mgr_ida, id); |
7085e2a9 AT |
839 | error_kfree: |
840 | kfree(mgr); | |
841 | ||
4ba0b2c2 | 842 | return ERR_PTR(ret); |
7085e2a9 | 843 | } |
4ba0b2c2 | 844 | EXPORT_SYMBOL_GPL(fpga_mgr_register_full); |
7085e2a9 AT |
845 | |
846 | /** | |
4ba0b2c2 | 847 | * fpga_mgr_register - create and register an FPGA Manager device |
59ef3622 | 848 | * @parent: fpga manager device from pdev |
084181fe AT |
849 | * @name: fpga manager name |
850 | * @mops: pointer to structure of fpga manager ops | |
851 | * @priv: fpga manager private data | |
852 | * | |
4ba0b2c2 RW |
853 | * The caller of this function is responsible for calling fpga_mgr_unregister(). |
854 | * Using devm_fpga_mgr_register() instead is recommended. This simple | |
855 | * version of the register function should be sufficient for most users. The | |
856 | * fpga_mgr_register_full() function is available for users that need to pass | |
857 | * additional, optional parameters. | |
084181fe | 858 | * |
4ba0b2c2 | 859 | * Return: pointer to struct fpga_manager pointer or ERR_PTR() |
084181fe | 860 | */ |
4ba0b2c2 RW |
861 | struct fpga_manager * |
862 | fpga_mgr_register(struct device *parent, const char *name, | |
863 | const struct fpga_manager_ops *mops, void *priv) | |
084181fe | 864 | { |
4ba0b2c2 | 865 | struct fpga_manager_info info = { 0 }; |
084181fe | 866 | |
4ba0b2c2 RW |
867 | info.name = name; |
868 | info.mops = mops; | |
869 | info.priv = priv; | |
084181fe | 870 | |
4ba0b2c2 | 871 | return fpga_mgr_register_full(parent, &info); |
6a8c3be7 AT |
872 | } |
873 | EXPORT_SYMBOL_GPL(fpga_mgr_register); | |
874 | ||
875 | /** | |
895ec9c0 | 876 | * fpga_mgr_unregister - unregister an FPGA manager |
084181fe AT |
877 | * @mgr: fpga manager struct |
878 | * | |
895ec9c0 | 879 | * This function is intended for use in an FPGA manager driver's remove function. |
6a8c3be7 | 880 | */ |
7085e2a9 | 881 | void fpga_mgr_unregister(struct fpga_manager *mgr) |
6a8c3be7 | 882 | { |
6a8c3be7 AT |
883 | dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); |
884 | ||
885 | /* | |
886 | * If the low level driver provides a method for putting fpga into | |
887 | * a desired state upon unregister, do it. | |
888 | */ | |
6489d3b0 | 889 | fpga_mgr_fpga_remove(mgr); |
6a8c3be7 AT |
890 | |
891 | device_unregister(&mgr->dev); | |
892 | } | |
893 | EXPORT_SYMBOL_GPL(fpga_mgr_unregister); | |
894 | ||
57d9352b MF |
895 | static void devm_fpga_mgr_unregister(struct device *dev, void *res) |
896 | { | |
897 | struct fpga_mgr_devres *dr = res; | |
898 | ||
899 | fpga_mgr_unregister(dr->mgr); | |
900 | } | |
901 | ||
902 | /** | |
4ba0b2c2 RW |
903 | * devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register() |
904 | * @parent: fpga manager device from pdev | |
905 | * @info: parameters for fpga manager | |
57d9352b | 906 | * |
3f3f9cb6 NM |
907 | * Return: fpga manager pointer on success, negative error code otherwise. |
908 | * | |
4ba0b2c2 | 909 | * This is the devres variant of fpga_mgr_register_full() for which the unregister |
57d9352b MF |
910 | * function will be called automatically when the managing device is detached. |
911 | */ | |
4ba0b2c2 RW |
912 | struct fpga_manager * |
913 | devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info) | |
57d9352b MF |
914 | { |
915 | struct fpga_mgr_devres *dr; | |
4ba0b2c2 | 916 | struct fpga_manager *mgr; |
57d9352b MF |
917 | |
918 | dr = devres_alloc(devm_fpga_mgr_unregister, sizeof(*dr), GFP_KERNEL); | |
919 | if (!dr) | |
4ba0b2c2 | 920 | return ERR_PTR(-ENOMEM); |
57d9352b | 921 | |
4ba0b2c2 RW |
922 | mgr = fpga_mgr_register_full(parent, info); |
923 | if (IS_ERR(mgr)) { | |
57d9352b | 924 | devres_free(dr); |
4ba0b2c2 | 925 | return mgr; |
57d9352b MF |
926 | } |
927 | ||
928 | dr->mgr = mgr; | |
4ba0b2c2 | 929 | devres_add(parent, dr); |
57d9352b | 930 | |
4ba0b2c2 RW |
931 | return mgr; |
932 | } | |
933 | EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full); | |
934 | ||
935 | /** | |
936 | * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register() | |
937 | * @parent: fpga manager device from pdev | |
938 | * @name: fpga manager name | |
939 | * @mops: pointer to structure of fpga manager ops | |
940 | * @priv: fpga manager private data | |
941 | * | |
3f3f9cb6 NM |
942 | * Return: fpga manager pointer on success, negative error code otherwise. |
943 | * | |
4ba0b2c2 RW |
944 | * This is the devres variant of fpga_mgr_register() for which the |
945 | * unregister function will be called automatically when the managing | |
946 | * device is detached. | |
947 | */ | |
948 | struct fpga_manager * | |
949 | devm_fpga_mgr_register(struct device *parent, const char *name, | |
950 | const struct fpga_manager_ops *mops, void *priv) | |
951 | { | |
952 | struct fpga_manager_info info = { 0 }; | |
953 | ||
954 | info.name = name; | |
955 | info.mops = mops; | |
956 | info.priv = priv; | |
957 | ||
958 | return devm_fpga_mgr_register_full(parent, &info); | |
57d9352b MF |
959 | } |
960 | EXPORT_SYMBOL_GPL(devm_fpga_mgr_register); | |
961 | ||
6a8c3be7 AT |
962 | static void fpga_mgr_dev_release(struct device *dev) |
963 | { | |
4ba0b2c2 RW |
964 | struct fpga_manager *mgr = to_fpga_manager(dev); |
965 | ||
a5e3d775 | 966 | ida_free(&fpga_mgr_ida, mgr->dev.id); |
4ba0b2c2 | 967 | kfree(mgr); |
6a8c3be7 AT |
968 | } |
969 | ||
970 | static int __init fpga_mgr_class_init(void) | |
971 | { | |
972 | pr_info("FPGA manager framework\n"); | |
973 | ||
974 | fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager"); | |
975 | if (IS_ERR(fpga_mgr_class)) | |
976 | return PTR_ERR(fpga_mgr_class); | |
977 | ||
978 | fpga_mgr_class->dev_groups = fpga_mgr_groups; | |
979 | fpga_mgr_class->dev_release = fpga_mgr_dev_release; | |
980 | ||
981 | return 0; | |
982 | } | |
983 | ||
984 | static void __exit fpga_mgr_class_exit(void) | |
985 | { | |
986 | class_destroy(fpga_mgr_class); | |
987 | ida_destroy(&fpga_mgr_ida); | |
988 | } | |
989 | ||
5cf0c7f6 | 990 | MODULE_AUTHOR("Alan Tull <atull@kernel.org>"); |
6a8c3be7 AT |
991 | MODULE_DESCRIPTION("FPGA manager framework"); |
992 | MODULE_LICENSE("GPL v2"); | |
993 | ||
994 | subsys_initcall(fpga_mgr_class_init); | |
995 | module_exit(fpga_mgr_class_exit); |