blob: 05a69ab3ecb9e0b1cd82b82fe25ddf59b388d370 [file] [log] [blame]
Alan Tull473f01f2018-05-16 18:49:58 -05001// SPDX-License-Identifier: GPL-2.0
Alan Tull6a8c3be2015-10-07 16:36:28 +01002/*
3 * FPGA Manager Core
4 *
5 * Copyright (C) 2013-2015 Altera Corporation
Alan Tull5cf0c7f2017-11-15 14:20:12 -06006 * Copyright (C) 2017 Intel Corporation
Alan Tull6a8c3be2015-10-07 16:36:28 +01007 *
8 * With code from the mailing list:
9 * Copyright (C) 2013 Xilinx, Inc.
Alan Tull6a8c3be2015-10-07 16:36:28 +010010 */
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>
Jason Gunthorpebaa6d392017-02-01 12:48:44 -070018#include <linux/scatterlist.h>
19#include <linux/highmem.h>
Alan Tull6a8c3be2015-10-07 16:36:28 +010020
21static DEFINE_IDA(fpga_mgr_ida);
22static struct class *fpga_mgr_class;
23
Moritz Fischer57d93522020-11-15 11:51:18 -080024struct fpga_mgr_devres {
25 struct fpga_manager *mgr;
26};
27
Tom Rix72d93502021-06-25 12:51:43 -070028/*
29 * After all the FPGA image has been written, do the device specific steps to
30 * finish and set the FPGA into operating mode.
31 */
32static inline int fpga_mgr_write_complete(struct fpga_manager *mgr,
33 struct fpga_image_info *info)
34{
35 int ret = 0;
36
37 mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
38 if (mgr->mops->write_complete)
39 ret = mgr->mops->write_complete(mgr, info);
40 if (ret) {
41 dev_err(&mgr->dev, "Error after writing image data to FPGA\n");
42 mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
43 return ret;
44 }
45 mgr->state = FPGA_MGR_STATE_OPERATING;
46
47 return 0;
48}
49
Tom Rix2e8438b2021-06-25 12:51:42 -070050static inline int fpga_mgr_write_init(struct fpga_manager *mgr,
51 struct fpga_image_info *info,
52 const char *buf, size_t count)
53{
54 if (mgr->mops->write_init)
55 return mgr->mops->write_init(mgr, info, buf, count);
56 return 0;
57}
58
Alan Tullff9da892018-05-16 18:49:59 -050059/**
Tom Rix895ec9c2021-06-08 14:23:46 -070060 * fpga_image_info_alloc - Allocate an FPGA image info struct
Alan Tullff9da892018-05-16 18:49:59 -050061 * @dev: owning device
62 *
63 * Return: struct fpga_image_info or NULL
64 */
Alan Tull5cf0c7f2017-11-15 14:20:12 -060065struct fpga_image_info *fpga_image_info_alloc(struct device *dev)
66{
67 struct fpga_image_info *info;
68
69 get_device(dev);
70
71 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
72 if (!info) {
73 put_device(dev);
74 return NULL;
75 }
76
77 info->dev = dev;
78
79 return info;
80}
81EXPORT_SYMBOL_GPL(fpga_image_info_alloc);
82
Alan Tullff9da892018-05-16 18:49:59 -050083/**
Tom Rix895ec9c2021-06-08 14:23:46 -070084 * fpga_image_info_free - Free an FPGA image info struct
Alan Tullff9da892018-05-16 18:49:59 -050085 * @info: FPGA image info struct to free
86 */
Alan Tull5cf0c7f2017-11-15 14:20:12 -060087void fpga_image_info_free(struct fpga_image_info *info)
88{
89 struct device *dev;
90
91 if (!info)
92 return;
93
94 dev = info->dev;
95 if (info->firmware_name)
96 devm_kfree(dev, info->firmware_name);
97
98 devm_kfree(dev, info);
99 put_device(dev);
100}
101EXPORT_SYMBOL_GPL(fpga_image_info_free);
102
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700103/*
104 * Call the low level driver's write_init function. This will do the
105 * device-specific things to get the FPGA into the state where it is ready to
106 * receive an FPGA image. The low level driver only gets to see the first
107 * initial_header_size bytes in the buffer.
108 */
109static int fpga_mgr_write_init_buf(struct fpga_manager *mgr,
110 struct fpga_image_info *info,
111 const char *buf, size_t count)
112{
113 int ret;
114
115 mgr->state = FPGA_MGR_STATE_WRITE_INIT;
116 if (!mgr->mops->initial_header_size)
Tom Rix2e8438b2021-06-25 12:51:42 -0700117 ret = fpga_mgr_write_init(mgr, info, NULL, 0);
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700118 else
Tom Rix2e8438b2021-06-25 12:51:42 -0700119 ret = fpga_mgr_write_init(
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700120 mgr, info, buf, min(mgr->mops->initial_header_size, count));
121
122 if (ret) {
123 dev_err(&mgr->dev, "Error preparing FPGA for writing\n");
124 mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
125 return ret;
126 }
127
128 return 0;
129}
130
131static int fpga_mgr_write_init_sg(struct fpga_manager *mgr,
132 struct fpga_image_info *info,
133 struct sg_table *sgt)
134{
135 struct sg_mapping_iter miter;
136 size_t len;
137 char *buf;
138 int ret;
139
140 if (!mgr->mops->initial_header_size)
141 return fpga_mgr_write_init_buf(mgr, info, NULL, 0);
142
143 /*
144 * First try to use miter to map the first fragment to access the
145 * header, this is the typical path.
146 */
147 sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
148 if (sg_miter_next(&miter) &&
149 miter.length >= mgr->mops->initial_header_size) {
150 ret = fpga_mgr_write_init_buf(mgr, info, miter.addr,
151 miter.length);
152 sg_miter_stop(&miter);
153 return ret;
154 }
155 sg_miter_stop(&miter);
156
157 /* Otherwise copy the fragments into temporary memory. */
158 buf = kmalloc(mgr->mops->initial_header_size, GFP_KERNEL);
159 if (!buf)
160 return -ENOMEM;
161
162 len = sg_copy_to_buffer(sgt->sgl, sgt->nents, buf,
163 mgr->mops->initial_header_size);
164 ret = fpga_mgr_write_init_buf(mgr, info, buf, len);
165
166 kfree(buf);
167
168 return ret;
169}
170
Alan Tull6a8c3be2015-10-07 16:36:28 +0100171/**
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700172 * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list
Alan Tull6a8c3be2015-10-07 16:36:28 +0100173 * @mgr: fpga manager
Alan Tull1df28652016-11-01 14:14:26 -0500174 * @info: fpga image specific information
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700175 * @sgt: scatterlist table
Alan Tull6a8c3be2015-10-07 16:36:28 +0100176 *
177 * Step the low level fpga manager through the device-specific steps of getting
178 * an FPGA ready to be configured, writing the image to it, then doing whatever
Alan Tull92d94a72015-10-22 12:38:38 -0500179 * post-configuration steps necessary. This code assumes the caller got the
Alan Tull9dce0282016-11-01 14:14:23 -0500180 * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is
181 * not an error code.
Alan Tull6a8c3be2015-10-07 16:36:28 +0100182 *
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700183 * This is the preferred entry point for FPGA programming, it does not require
184 * any contiguous kernel memory.
185 *
Alan Tull6a8c3be2015-10-07 16:36:28 +0100186 * Return: 0 on success, negative error code otherwise.
187 */
Alan Tull5cf0c7f2017-11-15 14:20:12 -0600188static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
189 struct fpga_image_info *info,
190 struct sg_table *sgt)
Alan Tull6a8c3be2015-10-07 16:36:28 +0100191{
Alan Tull6a8c3be2015-10-07 16:36:28 +0100192 int ret;
193
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700194 ret = fpga_mgr_write_init_sg(mgr, info, sgt);
195 if (ret)
196 return ret;
197
198 /* Write the FPGA image to the FPGA. */
199 mgr->state = FPGA_MGR_STATE_WRITE;
200 if (mgr->mops->write_sg) {
201 ret = mgr->mops->write_sg(mgr, sgt);
202 } else {
203 struct sg_mapping_iter miter;
204
205 sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
206 while (sg_miter_next(&miter)) {
207 ret = mgr->mops->write(mgr, miter.addr, miter.length);
208 if (ret)
209 break;
210 }
211 sg_miter_stop(&miter);
212 }
213
Alan Tull6a8c3be2015-10-07 16:36:28 +0100214 if (ret) {
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700215 dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
216 mgr->state = FPGA_MGR_STATE_WRITE_ERR;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100217 return ret;
218 }
219
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700220 return fpga_mgr_write_complete(mgr, info);
221}
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700222
223static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr,
224 struct fpga_image_info *info,
225 const char *buf, size_t count)
226{
227 int ret;
228
229 ret = fpga_mgr_write_init_buf(mgr, info, buf, count);
230 if (ret)
231 return ret;
232
Alan Tull6a8c3be2015-10-07 16:36:28 +0100233 /*
234 * Write the FPGA image to the FPGA.
235 */
236 mgr->state = FPGA_MGR_STATE_WRITE;
237 ret = mgr->mops->write(mgr, buf, count);
238 if (ret) {
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700239 dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
Alan Tull6a8c3be2015-10-07 16:36:28 +0100240 mgr->state = FPGA_MGR_STATE_WRITE_ERR;
241 return ret;
242 }
243
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700244 return fpga_mgr_write_complete(mgr, info);
245}
Alan Tull6a8c3be2015-10-07 16:36:28 +0100246
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700247/**
248 * fpga_mgr_buf_load - load fpga from image in buffer
249 * @mgr: fpga manager
Alan Tullff9da892018-05-16 18:49:59 -0500250 * @info: fpga image info
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700251 * @buf: buffer contain fpga image
252 * @count: byte count of buf
253 *
254 * Step the low level fpga manager through the device-specific steps of getting
255 * an FPGA ready to be configured, writing the image to it, then doing whatever
256 * post-configuration steps necessary. This code assumes the caller got the
257 * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
258 *
259 * Return: 0 on success, negative error code otherwise.
260 */
Alan Tull5cf0c7f2017-11-15 14:20:12 -0600261static int fpga_mgr_buf_load(struct fpga_manager *mgr,
262 struct fpga_image_info *info,
263 const char *buf, size_t count)
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700264{
265 struct page **pages;
266 struct sg_table sgt;
267 const void *p;
268 int nr_pages;
269 int index;
270 int rc;
271
272 /*
273 * This is just a fast path if the caller has already created a
274 * contiguous kernel buffer and the driver doesn't require SG, non-SG
275 * drivers will still work on the slow path.
276 */
277 if (mgr->mops->write)
278 return fpga_mgr_buf_load_mapped(mgr, info, buf, count);
279
280 /*
281 * Convert the linear kernel pointer into a sg_table of pages for use
282 * by the driver.
283 */
284 nr_pages = DIV_ROUND_UP((unsigned long)buf + count, PAGE_SIZE) -
285 (unsigned long)buf / PAGE_SIZE;
286 pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
287 if (!pages)
288 return -ENOMEM;
289
290 p = buf - offset_in_page(buf);
291 for (index = 0; index < nr_pages; index++) {
292 if (is_vmalloc_addr(p))
293 pages[index] = vmalloc_to_page(p);
294 else
295 pages[index] = kmap_to_page((void *)p);
296 if (!pages[index]) {
297 kfree(pages);
298 return -EFAULT;
299 }
300 p += PAGE_SIZE;
301 }
302
303 /*
304 * The temporary pages list is used to code share the merging algorithm
305 * in sg_alloc_table_from_pages
306 */
307 rc = sg_alloc_table_from_pages(&sgt, pages, index, offset_in_page(buf),
308 count, GFP_KERNEL);
309 kfree(pages);
310 if (rc)
311 return rc;
312
313 rc = fpga_mgr_buf_load_sg(mgr, info, &sgt);
314 sg_free_table(&sgt);
315
316 return rc;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100317}
Alan Tull6a8c3be2015-10-07 16:36:28 +0100318
319/**
320 * fpga_mgr_firmware_load - request firmware and load to fpga
321 * @mgr: fpga manager
Alan Tull1df28652016-11-01 14:14:26 -0500322 * @info: fpga image specific information
Alan Tull6a8c3be2015-10-07 16:36:28 +0100323 * @image_name: name of image file on the firmware search path
324 *
325 * Request an FPGA image using the firmware class, then write out to the FPGA.
326 * Update the state before each step to provide info on what step failed if
Alan Tull92d94a72015-10-22 12:38:38 -0500327 * there is a failure. This code assumes the caller got the mgr pointer
Alan Tull9dce0282016-11-01 14:14:23 -0500328 * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error
329 * code.
Alan Tull6a8c3be2015-10-07 16:36:28 +0100330 *
331 * Return: 0 on success, negative error code otherwise.
332 */
Alan Tull5cf0c7f2017-11-15 14:20:12 -0600333static int fpga_mgr_firmware_load(struct fpga_manager *mgr,
334 struct fpga_image_info *info,
335 const char *image_name)
Alan Tull6a8c3be2015-10-07 16:36:28 +0100336{
337 struct device *dev = &mgr->dev;
338 const struct firmware *fw;
339 int ret;
340
Alan Tull6a8c3be2015-10-07 16:36:28 +0100341 dev_info(dev, "writing %s to %s\n", image_name, mgr->name);
342
343 mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
344
345 ret = request_firmware(&fw, image_name, dev);
346 if (ret) {
347 mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
348 dev_err(dev, "Error requesting firmware %s\n", image_name);
349 return ret;
350 }
351
Alan Tull1df28652016-11-01 14:14:26 -0500352 ret = fpga_mgr_buf_load(mgr, info, fw->data, fw->size);
Alan Tull6a8c3be2015-10-07 16:36:28 +0100353
354 release_firmware(fw);
355
Tobias Klausere8c77bd2015-11-18 10:48:16 +0100356 return ret;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100357}
Alan Tull5cf0c7f2017-11-15 14:20:12 -0600358
Alan Tullff9da892018-05-16 18:49:59 -0500359/**
360 * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware
361 * @mgr: fpga manager
362 * @info: fpga image information.
363 *
364 * Load the FPGA from an image which is indicated in @info. If successful, the
365 * FPGA ends up in operating mode.
366 *
367 * Return: 0 on success, negative error code otherwise.
368 */
Alan Tull5cf0c7f2017-11-15 14:20:12 -0600369int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info)
370{
371 if (info->sgt)
372 return fpga_mgr_buf_load_sg(mgr, info, info->sgt);
373 if (info->buf && info->count)
374 return fpga_mgr_buf_load(mgr, info, info->buf, info->count);
375 if (info->firmware_name)
376 return fpga_mgr_firmware_load(mgr, info, info->firmware_name);
377 return -EINVAL;
378}
379EXPORT_SYMBOL_GPL(fpga_mgr_load);
Alan Tull6a8c3be2015-10-07 16:36:28 +0100380
381static const char * const state_str[] = {
382 [FPGA_MGR_STATE_UNKNOWN] = "unknown",
383 [FPGA_MGR_STATE_POWER_OFF] = "power off",
384 [FPGA_MGR_STATE_POWER_UP] = "power up",
385 [FPGA_MGR_STATE_RESET] = "reset",
386
387 /* requesting FPGA image from firmware */
388 [FPGA_MGR_STATE_FIRMWARE_REQ] = "firmware request",
389 [FPGA_MGR_STATE_FIRMWARE_REQ_ERR] = "firmware request error",
390
391 /* Preparing FPGA to receive image */
392 [FPGA_MGR_STATE_WRITE_INIT] = "write init",
393 [FPGA_MGR_STATE_WRITE_INIT_ERR] = "write init error",
394
395 /* Writing image to FPGA */
396 [FPGA_MGR_STATE_WRITE] = "write",
397 [FPGA_MGR_STATE_WRITE_ERR] = "write error",
398
399 /* Finishing configuration after image has been written */
400 [FPGA_MGR_STATE_WRITE_COMPLETE] = "write complete",
401 [FPGA_MGR_STATE_WRITE_COMPLETE_ERR] = "write complete error",
402
403 /* FPGA reports to be in normal operating mode */
404 [FPGA_MGR_STATE_OPERATING] = "operating",
405};
406
407static ssize_t name_show(struct device *dev,
408 struct device_attribute *attr, char *buf)
409{
410 struct fpga_manager *mgr = to_fpga_manager(dev);
411
412 return sprintf(buf, "%s\n", mgr->name);
413}
414
415static ssize_t state_show(struct device *dev,
416 struct device_attribute *attr, char *buf)
417{
418 struct fpga_manager *mgr = to_fpga_manager(dev);
419
420 return sprintf(buf, "%s\n", state_str[mgr->state]);
421}
422
Wu Haoecb5fbe2018-06-30 08:53:10 +0800423static ssize_t status_show(struct device *dev,
424 struct device_attribute *attr, char *buf)
425{
426 struct fpga_manager *mgr = to_fpga_manager(dev);
427 u64 status;
428 int len = 0;
429
430 if (!mgr->mops->status)
431 return -ENOENT;
432
433 status = mgr->mops->status(mgr);
434
435 if (status & FPGA_MGR_STATUS_OPERATION_ERR)
436 len += sprintf(buf + len, "reconfig operation error\n");
437 if (status & FPGA_MGR_STATUS_CRC_ERR)
438 len += sprintf(buf + len, "reconfig CRC error\n");
439 if (status & FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR)
440 len += sprintf(buf + len, "reconfig incompatible image\n");
441 if (status & FPGA_MGR_STATUS_IP_PROTOCOL_ERR)
442 len += sprintf(buf + len, "reconfig IP protocol error\n");
443 if (status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR)
444 len += sprintf(buf + len, "reconfig fifo overflow error\n");
445
446 return len;
447}
448
Alan Tull6a8c3be2015-10-07 16:36:28 +0100449static DEVICE_ATTR_RO(name);
450static DEVICE_ATTR_RO(state);
Wu Haoecb5fbe2018-06-30 08:53:10 +0800451static DEVICE_ATTR_RO(status);
Alan Tull6a8c3be2015-10-07 16:36:28 +0100452
453static struct attribute *fpga_mgr_attrs[] = {
454 &dev_attr_name.attr,
455 &dev_attr_state.attr,
Wu Haoecb5fbe2018-06-30 08:53:10 +0800456 &dev_attr_status.attr,
Alan Tull6a8c3be2015-10-07 16:36:28 +0100457 NULL,
458};
459ATTRIBUTE_GROUPS(fpga_mgr);
460
Dinh Nguyen47910a42017-02-27 09:18:59 -0600461static struct fpga_manager *__fpga_mgr_get(struct device *dev)
Alan Tull6a8c3be2015-10-07 16:36:28 +0100462{
463 struct fpga_manager *mgr;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100464
Alan Tull6a8c3be2015-10-07 16:36:28 +0100465 mgr = to_fpga_manager(dev);
Alan Tull6a8c3be2015-10-07 16:36:28 +0100466
Alan Tull654ba4c2015-10-22 12:38:37 -0500467 if (!try_module_get(dev->parent->driver->owner))
Alan Tullebf877a52017-11-15 14:20:13 -0600468 goto err_dev;
Alan Tull654ba4c2015-10-22 12:38:37 -0500469
Alan Tull6a8c3be2015-10-07 16:36:28 +0100470 return mgr;
Alan Tull654ba4c2015-10-22 12:38:37 -0500471
Alan Tull654ba4c2015-10-22 12:38:37 -0500472err_dev:
473 put_device(dev);
Alan Tullebf877a52017-11-15 14:20:13 -0600474 return ERR_PTR(-ENODEV);
Alan Tull6a8c3be2015-10-07 16:36:28 +0100475}
Alan Tull9dce0282016-11-01 14:14:23 -0500476
477static int fpga_mgr_dev_match(struct device *dev, const void *data)
478{
479 return dev->parent == data;
480}
481
482/**
Tom Rix895ec9c2021-06-08 14:23:46 -0700483 * fpga_mgr_get - Given a device, get a reference to an fpga mgr.
Alan Tull9dce0282016-11-01 14:14:23 -0500484 * @dev: parent device that fpga mgr was registered with
485 *
Alan Tull9dce0282016-11-01 14:14:23 -0500486 * Return: fpga manager struct or IS_ERR() condition containing error code.
487 */
488struct fpga_manager *fpga_mgr_get(struct device *dev)
489{
490 struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev,
491 fpga_mgr_dev_match);
492 if (!mgr_dev)
493 return ERR_PTR(-ENODEV);
494
495 return __fpga_mgr_get(mgr_dev);
496}
497EXPORT_SYMBOL_GPL(fpga_mgr_get);
498
Alan Tull9dce0282016-11-01 14:14:23 -0500499/**
Tom Rix895ec9c2021-06-08 14:23:46 -0700500 * of_fpga_mgr_get - Given a device node, get a reference to an fpga mgr.
Alan Tull9dce0282016-11-01 14:14:23 -0500501 *
Alan Tullff9da892018-05-16 18:49:59 -0500502 * @node: device node
Alan Tull9dce0282016-11-01 14:14:23 -0500503 *
504 * Return: fpga manager struct or IS_ERR() condition containing error code.
505 */
506struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
507{
508 struct device *dev;
509
Suzuki K Poulosecfba5de2019-07-23 23:18:33 +0100510 dev = class_find_device_by_of_node(fpga_mgr_class, node);
Alan Tull9dce0282016-11-01 14:14:23 -0500511 if (!dev)
512 return ERR_PTR(-ENODEV);
513
514 return __fpga_mgr_get(dev);
515}
Alan Tull6a8c3be2015-10-07 16:36:28 +0100516EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
517
518/**
Tom Rix895ec9c2021-06-08 14:23:46 -0700519 * fpga_mgr_put - release a reference to an fpga manager
Alan Tull6a8c3be2015-10-07 16:36:28 +0100520 * @mgr: fpga manager structure
521 */
522void fpga_mgr_put(struct fpga_manager *mgr)
523{
Alan Tull654ba4c2015-10-22 12:38:37 -0500524 module_put(mgr->dev.parent->driver->owner);
Alan Tull654ba4c2015-10-22 12:38:37 -0500525 put_device(&mgr->dev);
Alan Tull6a8c3be2015-10-07 16:36:28 +0100526}
527EXPORT_SYMBOL_GPL(fpga_mgr_put);
528
529/**
Alan Tullebf877a52017-11-15 14:20:13 -0600530 * fpga_mgr_lock - Lock FPGA manager for exclusive use
531 * @mgr: fpga manager
532 *
533 * Given a pointer to FPGA Manager (from fpga_mgr_get() or
Alan Tullff9da892018-05-16 18:49:59 -0500534 * of_fpga_mgr_put()) attempt to get the mutex. The user should call
535 * fpga_mgr_lock() and verify that it returns 0 before attempting to
536 * program the FPGA. Likewise, the user should call fpga_mgr_unlock
537 * when done programming the FPGA.
Alan Tullebf877a52017-11-15 14:20:13 -0600538 *
539 * Return: 0 for success or -EBUSY
540 */
541int fpga_mgr_lock(struct fpga_manager *mgr)
542{
543 if (!mutex_trylock(&mgr->ref_mutex)) {
544 dev_err(&mgr->dev, "FPGA manager is in use.\n");
545 return -EBUSY;
546 }
547
548 return 0;
549}
550EXPORT_SYMBOL_GPL(fpga_mgr_lock);
551
552/**
Alan Tullff9da892018-05-16 18:49:59 -0500553 * fpga_mgr_unlock - Unlock FPGA manager after done programming
Alan Tullebf877a52017-11-15 14:20:13 -0600554 * @mgr: fpga manager
555 */
556void fpga_mgr_unlock(struct fpga_manager *mgr)
557{
558 mutex_unlock(&mgr->ref_mutex);
559}
560EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
561
562/**
Tom Rix895ec9c2021-06-08 14:23:46 -0700563 * fpga_mgr_create - create and initialize an FPGA manager struct
Russ Weight59ef3622021-06-14 10:09:04 -0700564 * @parent: fpga manager device from pdev
Alan Tull6a8c3be2015-10-07 16:36:28 +0100565 * @name: fpga manager name
566 * @mops: pointer to structure of fpga manager ops
567 * @priv: fpga manager private data
568 *
Alan Tull084181f2018-10-15 17:20:01 -0500569 * The caller of this function is responsible for freeing the struct with
570 * fpga_mgr_free(). Using devm_fpga_mgr_create() instead is recommended.
571 *
Alan Tull7085e2a2018-05-16 18:49:55 -0500572 * Return: pointer to struct fpga_manager or NULL
Alan Tull6a8c3be2015-10-07 16:36:28 +0100573 */
Russ Weight59ef3622021-06-14 10:09:04 -0700574struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name,
Alan Tull7085e2a2018-05-16 18:49:55 -0500575 const struct fpga_manager_ops *mops,
576 void *priv)
Alan Tull6a8c3be2015-10-07 16:36:28 +0100577{
578 struct fpga_manager *mgr;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100579 int id, ret;
580
Tom Rix72d93502021-06-25 12:51:43 -0700581 if (!mops || !mops->state ||
Tom Rix2e8438b2021-06-25 12:51:42 -0700582 (!mops->write && !mops->write_sg) ||
Jason Gunthorpebaa6d392017-02-01 12:48:44 -0700583 (mops->write && mops->write_sg)) {
Russ Weight59ef3622021-06-14 10:09:04 -0700584 dev_err(parent, "Attempt to register without fpga_manager_ops\n");
Alan Tull7085e2a2018-05-16 18:49:55 -0500585 return NULL;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100586 }
587
588 if (!name || !strlen(name)) {
Russ Weight59ef3622021-06-14 10:09:04 -0700589 dev_err(parent, "Attempt to register with no name!\n");
Alan Tull7085e2a2018-05-16 18:49:55 -0500590 return NULL;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100591 }
592
593 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
594 if (!mgr)
Alan Tull7085e2a2018-05-16 18:49:55 -0500595 return NULL;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100596
597 id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
Tom Rix88aaab92020-06-08 05:54:45 -0700598 if (id < 0)
Alan Tull6a8c3be2015-10-07 16:36:28 +0100599 goto error_kfree;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100600
601 mutex_init(&mgr->ref_mutex);
602
603 mgr->name = name;
604 mgr->mops = mops;
605 mgr->priv = priv;
606
Alan Tull6a8c3be2015-10-07 16:36:28 +0100607 device_initialize(&mgr->dev);
608 mgr->dev.class = fpga_mgr_class;
Alan Tull845089b2017-11-15 14:20:28 -0600609 mgr->dev.groups = mops->groups;
Russ Weight59ef3622021-06-14 10:09:04 -0700610 mgr->dev.parent = parent;
611 mgr->dev.of_node = parent->of_node;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100612 mgr->dev.id = id;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100613
Alan Tull07687c02015-10-29 14:39:56 -0500614 ret = dev_set_name(&mgr->dev, "fpga%d", id);
615 if (ret)
616 goto error_device;
Alan Tull6a8c3be2015-10-07 16:36:28 +0100617
Alan Tull7085e2a2018-05-16 18:49:55 -0500618 return mgr;
619
620error_device:
621 ida_simple_remove(&fpga_mgr_ida, id);
622error_kfree:
623 kfree(mgr);
624
625 return NULL;
626}
627EXPORT_SYMBOL_GPL(fpga_mgr_create);
628
629/**
Tom Rix895ec9c2021-06-08 14:23:46 -0700630 * fpga_mgr_free - free an FPGA manager created with fpga_mgr_create()
Alan Tull084181f2018-10-15 17:20:01 -0500631 * @mgr: fpga manager struct
Alan Tull7085e2a2018-05-16 18:49:55 -0500632 */
633void fpga_mgr_free(struct fpga_manager *mgr)
634{
635 ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
636 kfree(mgr);
637}
638EXPORT_SYMBOL_GPL(fpga_mgr_free);
639
Alan Tull084181f2018-10-15 17:20:01 -0500640static void devm_fpga_mgr_release(struct device *dev, void *res)
641{
Moritz Fischer57d93522020-11-15 11:51:18 -0800642 struct fpga_mgr_devres *dr = res;
Alan Tull084181f2018-10-15 17:20:01 -0500643
Moritz Fischer57d93522020-11-15 11:51:18 -0800644 fpga_mgr_free(dr->mgr);
Alan Tull084181f2018-10-15 17:20:01 -0500645}
646
647/**
648 * devm_fpga_mgr_create - create and initialize a managed FPGA manager struct
Russ Weight59ef3622021-06-14 10:09:04 -0700649 * @parent: fpga manager device from pdev
Alan Tull084181f2018-10-15 17:20:01 -0500650 * @name: fpga manager name
651 * @mops: pointer to structure of fpga manager ops
652 * @priv: fpga manager private data
653 *
Tom Rix895ec9c2021-06-08 14:23:46 -0700654 * This function is intended for use in an FPGA manager driver's probe function.
Alan Tull084181f2018-10-15 17:20:01 -0500655 * After the manager driver creates the manager struct with
656 * devm_fpga_mgr_create(), it should register it with fpga_mgr_register(). The
657 * manager driver's remove function should call fpga_mgr_unregister(). The
658 * manager struct allocated with this function will be freed automatically on
659 * driver detach. This includes the case of a probe function returning error
660 * before calling fpga_mgr_register(), the struct will still get cleaned up.
661 *
662 * Return: pointer to struct fpga_manager or NULL
663 */
Russ Weight59ef3622021-06-14 10:09:04 -0700664struct fpga_manager *devm_fpga_mgr_create(struct device *parent, const char *name,
Alan Tull084181f2018-10-15 17:20:01 -0500665 const struct fpga_manager_ops *mops,
666 void *priv)
667{
Moritz Fischer57d93522020-11-15 11:51:18 -0800668 struct fpga_mgr_devres *dr;
Alan Tull084181f2018-10-15 17:20:01 -0500669
Moritz Fischer57d93522020-11-15 11:51:18 -0800670 dr = devres_alloc(devm_fpga_mgr_release, sizeof(*dr), GFP_KERNEL);
671 if (!dr)
Alan Tull084181f2018-10-15 17:20:01 -0500672 return NULL;
673
Russ Weight59ef3622021-06-14 10:09:04 -0700674 dr->mgr = fpga_mgr_create(parent, name, mops, priv);
Moritz Fischer57d93522020-11-15 11:51:18 -0800675 if (!dr->mgr) {
676 devres_free(dr);
677 return NULL;
Alan Tull084181f2018-10-15 17:20:01 -0500678 }
679
Russ Weight59ef3622021-06-14 10:09:04 -0700680 devres_add(parent, dr);
Moritz Fischer57d93522020-11-15 11:51:18 -0800681
682 return dr->mgr;
Alan Tull084181f2018-10-15 17:20:01 -0500683}
684EXPORT_SYMBOL_GPL(devm_fpga_mgr_create);
685
Alan Tull7085e2a2018-05-16 18:49:55 -0500686/**
Tom Rix895ec9c2021-06-08 14:23:46 -0700687 * fpga_mgr_register - register an FPGA manager
Alan Tull084181f2018-10-15 17:20:01 -0500688 * @mgr: fpga manager struct
Alan Tull7085e2a2018-05-16 18:49:55 -0500689 *
690 * Return: 0 on success, negative error code otherwise.
691 */
692int fpga_mgr_register(struct fpga_manager *mgr)
693{
694 int ret;
695
696 /*
697 * Initialize framework state by requesting low level driver read state
698 * from device. FPGA may be in reset mode or may have been programmed
699 * by bootloader or EEPROM.
700 */
701 mgr->state = mgr->mops->state(mgr);
702
Alan Tull6a8c3be2015-10-07 16:36:28 +0100703 ret = device_add(&mgr->dev);
704 if (ret)
705 goto error_device;
706
707 dev_info(&mgr->dev, "%s registered\n", mgr->name);
708
709 return 0;
710
711error_device:
Alan Tull7085e2a2018-05-16 18:49:55 -0500712 ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
Alan Tull6a8c3be2015-10-07 16:36:28 +0100713
714 return ret;
715}
716EXPORT_SYMBOL_GPL(fpga_mgr_register);
717
718/**
Tom Rix895ec9c2021-06-08 14:23:46 -0700719 * fpga_mgr_unregister - unregister an FPGA manager
Alan Tull084181f2018-10-15 17:20:01 -0500720 * @mgr: fpga manager struct
721 *
Tom Rix895ec9c2021-06-08 14:23:46 -0700722 * This function is intended for use in an FPGA manager driver's remove function.
Alan Tull6a8c3be2015-10-07 16:36:28 +0100723 */
Alan Tull7085e2a2018-05-16 18:49:55 -0500724void fpga_mgr_unregister(struct fpga_manager *mgr)
Alan Tull6a8c3be2015-10-07 16:36:28 +0100725{
Alan Tull6a8c3be2015-10-07 16:36:28 +0100726 dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name);
727
728 /*
729 * If the low level driver provides a method for putting fpga into
730 * a desired state upon unregister, do it.
731 */
732 if (mgr->mops->fpga_remove)
733 mgr->mops->fpga_remove(mgr);
734
735 device_unregister(&mgr->dev);
736}
737EXPORT_SYMBOL_GPL(fpga_mgr_unregister);
738
Moritz Fischer57d93522020-11-15 11:51:18 -0800739static int fpga_mgr_devres_match(struct device *dev, void *res,
740 void *match_data)
741{
742 struct fpga_mgr_devres *dr = res;
743
744 return match_data == dr->mgr;
745}
746
747static void devm_fpga_mgr_unregister(struct device *dev, void *res)
748{
749 struct fpga_mgr_devres *dr = res;
750
751 fpga_mgr_unregister(dr->mgr);
752}
753
754/**
755 * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
756 * @dev: managing device for this FPGA manager
757 * @mgr: fpga manager struct
758 *
759 * This is the devres variant of fpga_mgr_register() for which the unregister
760 * function will be called automatically when the managing device is detached.
761 */
762int devm_fpga_mgr_register(struct device *dev, struct fpga_manager *mgr)
763{
764 struct fpga_mgr_devres *dr;
765 int ret;
766
767 /*
768 * Make sure that the struct fpga_manager * that is passed in is
769 * managed itself.
770 */
771 if (WARN_ON(!devres_find(dev, devm_fpga_mgr_release,
772 fpga_mgr_devres_match, mgr)))
773 return -EINVAL;
774
775 dr = devres_alloc(devm_fpga_mgr_unregister, sizeof(*dr), GFP_KERNEL);
776 if (!dr)
777 return -ENOMEM;
778
779 ret = fpga_mgr_register(mgr);
780 if (ret) {
781 devres_free(dr);
782 return ret;
783 }
784
785 dr->mgr = mgr;
786 devres_add(dev, dr);
787
788 return 0;
789}
790EXPORT_SYMBOL_GPL(devm_fpga_mgr_register);
791
Alan Tull6a8c3be2015-10-07 16:36:28 +0100792static void fpga_mgr_dev_release(struct device *dev)
793{
Alan Tull6a8c3be2015-10-07 16:36:28 +0100794}
795
796static int __init fpga_mgr_class_init(void)
797{
798 pr_info("FPGA manager framework\n");
799
800 fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
801 if (IS_ERR(fpga_mgr_class))
802 return PTR_ERR(fpga_mgr_class);
803
804 fpga_mgr_class->dev_groups = fpga_mgr_groups;
805 fpga_mgr_class->dev_release = fpga_mgr_dev_release;
806
807 return 0;
808}
809
810static void __exit fpga_mgr_class_exit(void)
811{
812 class_destroy(fpga_mgr_class);
813 ida_destroy(&fpga_mgr_ida);
814}
815
Alan Tull5cf0c7f2017-11-15 14:20:12 -0600816MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
Alan Tull6a8c3be2015-10-07 16:36:28 +0100817MODULE_DESCRIPTION("FPGA manager framework");
818MODULE_LICENSE("GPL v2");
819
820subsys_initcall(fpga_mgr_class_init);
821module_exit(fpga_mgr_class_exit);