diff options
Diffstat (limited to 'drivers/fpga/fpga-mgr.c')
-rw-r--r-- | drivers/fpga/fpga-mgr.c | 157 |
1 files changed, 110 insertions, 47 deletions
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 9939d2cbc9a6..a41b07e37884 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Manager Core | 3 | * FPGA Manager Core |
3 | * | 4 | * |
@@ -6,18 +7,6 @@ | |||
6 | * | 7 | * |
7 | * With code from the mailing list: | 8 | * With code from the mailing list: |
8 | * Copyright (C) 2013 Xilinx, Inc. | 9 | * Copyright (C) 2013 Xilinx, Inc. |
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms and conditions of the GNU General Public License, | ||
12 | * version 2, as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
17 | * more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along with | ||
20 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | */ | 10 | */ |
22 | #include <linux/firmware.h> | 11 | #include <linux/firmware.h> |
23 | #include <linux/fpga/fpga-mgr.h> | 12 | #include <linux/fpga/fpga-mgr.h> |
@@ -32,6 +21,12 @@ | |||
32 | static DEFINE_IDA(fpga_mgr_ida); | 21 | static DEFINE_IDA(fpga_mgr_ida); |
33 | static struct class *fpga_mgr_class; | 22 | static struct class *fpga_mgr_class; |
34 | 23 | ||
24 | /** | ||
25 | * fpga_image_info_alloc - Allocate a FPGA image info struct | ||
26 | * @dev: owning device | ||
27 | * | ||
28 | * Return: struct fpga_image_info or NULL | ||
29 | */ | ||
35 | struct fpga_image_info *fpga_image_info_alloc(struct device *dev) | 30 | struct fpga_image_info *fpga_image_info_alloc(struct device *dev) |
36 | { | 31 | { |
37 | struct fpga_image_info *info; | 32 | struct fpga_image_info *info; |
@@ -50,6 +45,10 @@ struct fpga_image_info *fpga_image_info_alloc(struct device *dev) | |||
50 | } | 45 | } |
51 | EXPORT_SYMBOL_GPL(fpga_image_info_alloc); | 46 | EXPORT_SYMBOL_GPL(fpga_image_info_alloc); |
52 | 47 | ||
48 | /** | ||
49 | * fpga_image_info_free - Free a FPGA image info struct | ||
50 | * @info: FPGA image info struct to free | ||
51 | */ | ||
53 | void fpga_image_info_free(struct fpga_image_info *info) | 52 | void fpga_image_info_free(struct fpga_image_info *info) |
54 | { | 53 | { |
55 | struct device *dev; | 54 | struct device *dev; |
@@ -234,7 +233,7 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, | |||
234 | /** | 233 | /** |
235 | * fpga_mgr_buf_load - load fpga from image in buffer | 234 | * fpga_mgr_buf_load - load fpga from image in buffer |
236 | * @mgr: fpga manager | 235 | * @mgr: fpga manager |
237 | * @flags: flags setting fpga confuration modes | 236 | * @info: fpga image info |
238 | * @buf: buffer contain fpga image | 237 | * @buf: buffer contain fpga image |
239 | * @count: byte count of buf | 238 | * @count: byte count of buf |
240 | * | 239 | * |
@@ -343,6 +342,16 @@ static int fpga_mgr_firmware_load(struct fpga_manager *mgr, | |||
343 | return ret; | 342 | return ret; |
344 | } | 343 | } |
345 | 344 | ||
345 | /** | ||
346 | * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware | ||
347 | * @mgr: fpga manager | ||
348 | * @info: fpga image information. | ||
349 | * | ||
350 | * Load the FPGA from an image which is indicated in @info. If successful, the | ||
351 | * FPGA ends up in operating mode. | ||
352 | * | ||
353 | * Return: 0 on success, negative error code otherwise. | ||
354 | */ | ||
346 | int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) | 355 | int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) |
347 | { | 356 | { |
348 | if (info->sgt) | 357 | if (info->sgt) |
@@ -397,12 +406,40 @@ static ssize_t state_show(struct device *dev, | |||
397 | return sprintf(buf, "%s\n", state_str[mgr->state]); | 406 | return sprintf(buf, "%s\n", state_str[mgr->state]); |
398 | } | 407 | } |
399 | 408 | ||
409 | static ssize_t status_show(struct device *dev, | ||
410 | struct device_attribute *attr, char *buf) | ||
411 | { | ||
412 | struct fpga_manager *mgr = to_fpga_manager(dev); | ||
413 | u64 status; | ||
414 | int len = 0; | ||
415 | |||
416 | if (!mgr->mops->status) | ||
417 | return -ENOENT; | ||
418 | |||
419 | status = mgr->mops->status(mgr); | ||
420 | |||
421 | if (status & FPGA_MGR_STATUS_OPERATION_ERR) | ||
422 | len += sprintf(buf + len, "reconfig operation error\n"); | ||
423 | if (status & FPGA_MGR_STATUS_CRC_ERR) | ||
424 | len += sprintf(buf + len, "reconfig CRC error\n"); | ||
425 | if (status & FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR) | ||
426 | len += sprintf(buf + len, "reconfig incompatible image\n"); | ||
427 | if (status & FPGA_MGR_STATUS_IP_PROTOCOL_ERR) | ||
428 | len += sprintf(buf + len, "reconfig IP protocol error\n"); | ||
429 | if (status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR) | ||
430 | len += sprintf(buf + len, "reconfig fifo overflow error\n"); | ||
431 | |||
432 | return len; | ||
433 | } | ||
434 | |||
400 | static DEVICE_ATTR_RO(name); | 435 | static DEVICE_ATTR_RO(name); |
401 | static DEVICE_ATTR_RO(state); | 436 | static DEVICE_ATTR_RO(state); |
437 | static DEVICE_ATTR_RO(status); | ||
402 | 438 | ||
403 | static struct attribute *fpga_mgr_attrs[] = { | 439 | static struct attribute *fpga_mgr_attrs[] = { |
404 | &dev_attr_name.attr, | 440 | &dev_attr_name.attr, |
405 | &dev_attr_state.attr, | 441 | &dev_attr_state.attr, |
442 | &dev_attr_status.attr, | ||
406 | NULL, | 443 | NULL, |
407 | }; | 444 | }; |
408 | ATTRIBUTE_GROUPS(fpga_mgr); | 445 | ATTRIBUTE_GROUPS(fpga_mgr); |
@@ -429,11 +466,9 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) | |||
429 | } | 466 | } |
430 | 467 | ||
431 | /** | 468 | /** |
432 | * fpga_mgr_get - get a reference to a fpga mgr | 469 | * fpga_mgr_get - Given a device, get a reference to a fpga mgr. |
433 | * @dev: parent device that fpga mgr was registered with | 470 | * @dev: parent device that fpga mgr was registered with |
434 | * | 471 | * |
435 | * Given a device, get a reference to a fpga mgr. | ||
436 | * | ||
437 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 472 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
438 | */ | 473 | */ |
439 | struct fpga_manager *fpga_mgr_get(struct device *dev) | 474 | struct fpga_manager *fpga_mgr_get(struct device *dev) |
@@ -453,10 +488,9 @@ static int fpga_mgr_of_node_match(struct device *dev, const void *data) | |||
453 | } | 488 | } |
454 | 489 | ||
455 | /** | 490 | /** |
456 | * of_fpga_mgr_get - get a reference to a fpga mgr | 491 | * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr. |
457 | * @node: device node | ||
458 | * | 492 | * |
459 | * Given a device node, get a reference to a fpga mgr. | 493 | * @node: device node |
460 | * | 494 | * |
461 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 495 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
462 | */ | 496 | */ |
@@ -489,7 +523,10 @@ EXPORT_SYMBOL_GPL(fpga_mgr_put); | |||
489 | * @mgr: fpga manager | 523 | * @mgr: fpga manager |
490 | * | 524 | * |
491 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or | 525 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or |
492 | * of_fpga_mgr_put()) attempt to get the mutex. | 526 | * of_fpga_mgr_put()) attempt to get the mutex. The user should call |
527 | * fpga_mgr_lock() and verify that it returns 0 before attempting to | ||
528 | * program the FPGA. Likewise, the user should call fpga_mgr_unlock | ||
529 | * when done programming the FPGA. | ||
493 | * | 530 | * |
494 | * Return: 0 for success or -EBUSY | 531 | * Return: 0 for success or -EBUSY |
495 | */ | 532 | */ |
@@ -505,7 +542,7 @@ int fpga_mgr_lock(struct fpga_manager *mgr) | |||
505 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); | 542 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); |
506 | 543 | ||
507 | /** | 544 | /** |
508 | * fpga_mgr_unlock - Unlock FPGA manager | 545 | * fpga_mgr_unlock - Unlock FPGA manager after done programming |
509 | * @mgr: fpga manager | 546 | * @mgr: fpga manager |
510 | */ | 547 | */ |
511 | void fpga_mgr_unlock(struct fpga_manager *mgr) | 548 | void fpga_mgr_unlock(struct fpga_manager *mgr) |
@@ -515,17 +552,17 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) | |||
515 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); | 552 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); |
516 | 553 | ||
517 | /** | 554 | /** |
518 | * fpga_mgr_register - register a low level fpga manager driver | 555 | * fpga_mgr_create - create and initialize a FPGA manager struct |
519 | * @dev: fpga manager device from pdev | 556 | * @dev: fpga manager device from pdev |
520 | * @name: fpga manager name | 557 | * @name: fpga manager name |
521 | * @mops: pointer to structure of fpga manager ops | 558 | * @mops: pointer to structure of fpga manager ops |
522 | * @priv: fpga manager private data | 559 | * @priv: fpga manager private data |
523 | * | 560 | * |
524 | * Return: 0 on success, negative error code otherwise. | 561 | * Return: pointer to struct fpga_manager or NULL |
525 | */ | 562 | */ |
526 | int fpga_mgr_register(struct device *dev, const char *name, | 563 | struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, |
527 | const struct fpga_manager_ops *mops, | 564 | const struct fpga_manager_ops *mops, |
528 | void *priv) | 565 | void *priv) |
529 | { | 566 | { |
530 | struct fpga_manager *mgr; | 567 | struct fpga_manager *mgr; |
531 | int id, ret; | 568 | int id, ret; |
@@ -534,17 +571,17 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
534 | !mops->write_init || (!mops->write && !mops->write_sg) || | 571 | !mops->write_init || (!mops->write && !mops->write_sg) || |
535 | (mops->write && mops->write_sg)) { | 572 | (mops->write && mops->write_sg)) { |
536 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); | 573 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); |
537 | return -EINVAL; | 574 | return NULL; |
538 | } | 575 | } |
539 | 576 | ||
540 | if (!name || !strlen(name)) { | 577 | if (!name || !strlen(name)) { |
541 | dev_err(dev, "Attempt to register with no name!\n"); | 578 | dev_err(dev, "Attempt to register with no name!\n"); |
542 | return -EINVAL; | 579 | return NULL; |
543 | } | 580 | } |
544 | 581 | ||
545 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | 582 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); |
546 | if (!mgr) | 583 | if (!mgr) |
547 | return -ENOMEM; | 584 | return NULL; |
548 | 585 | ||
549 | id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); | 586 | id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); |
550 | if (id < 0) { | 587 | if (id < 0) { |
@@ -558,25 +595,56 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
558 | mgr->mops = mops; | 595 | mgr->mops = mops; |
559 | mgr->priv = priv; | 596 | mgr->priv = priv; |
560 | 597 | ||
561 | /* | ||
562 | * Initialize framework state by requesting low level driver read state | ||
563 | * from device. FPGA may be in reset mode or may have been programmed | ||
564 | * by bootloader or EEPROM. | ||
565 | */ | ||
566 | mgr->state = mgr->mops->state(mgr); | ||
567 | |||
568 | device_initialize(&mgr->dev); | 598 | device_initialize(&mgr->dev); |
569 | mgr->dev.class = fpga_mgr_class; | 599 | mgr->dev.class = fpga_mgr_class; |
570 | mgr->dev.groups = mops->groups; | 600 | mgr->dev.groups = mops->groups; |
571 | mgr->dev.parent = dev; | 601 | mgr->dev.parent = dev; |
572 | mgr->dev.of_node = dev->of_node; | 602 | mgr->dev.of_node = dev->of_node; |
573 | mgr->dev.id = id; | 603 | mgr->dev.id = id; |
574 | dev_set_drvdata(dev, mgr); | ||
575 | 604 | ||
576 | ret = dev_set_name(&mgr->dev, "fpga%d", id); | 605 | ret = dev_set_name(&mgr->dev, "fpga%d", id); |
577 | if (ret) | 606 | if (ret) |
578 | goto error_device; | 607 | goto error_device; |
579 | 608 | ||
609 | return mgr; | ||
610 | |||
611 | error_device: | ||
612 | ida_simple_remove(&fpga_mgr_ida, id); | ||
613 | error_kfree: | ||
614 | kfree(mgr); | ||
615 | |||
616 | return NULL; | ||
617 | } | ||
618 | EXPORT_SYMBOL_GPL(fpga_mgr_create); | ||
619 | |||
620 | /** | ||
621 | * fpga_mgr_free - deallocate a FPGA manager | ||
622 | * @mgr: fpga manager struct created by fpga_mgr_create | ||
623 | */ | ||
624 | void fpga_mgr_free(struct fpga_manager *mgr) | ||
625 | { | ||
626 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); | ||
627 | kfree(mgr); | ||
628 | } | ||
629 | EXPORT_SYMBOL_GPL(fpga_mgr_free); | ||
630 | |||
631 | /** | ||
632 | * fpga_mgr_register - register a FPGA manager | ||
633 | * @mgr: fpga manager struct created by fpga_mgr_create | ||
634 | * | ||
635 | * Return: 0 on success, negative error code otherwise. | ||
636 | */ | ||
637 | int fpga_mgr_register(struct fpga_manager *mgr) | ||
638 | { | ||
639 | int ret; | ||
640 | |||
641 | /* | ||
642 | * Initialize framework state by requesting low level driver read state | ||
643 | * from device. FPGA may be in reset mode or may have been programmed | ||
644 | * by bootloader or EEPROM. | ||
645 | */ | ||
646 | mgr->state = mgr->mops->state(mgr); | ||
647 | |||
580 | ret = device_add(&mgr->dev); | 648 | ret = device_add(&mgr->dev); |
581 | if (ret) | 649 | if (ret) |
582 | goto error_device; | 650 | goto error_device; |
@@ -586,22 +654,18 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
586 | return 0; | 654 | return 0; |
587 | 655 | ||
588 | error_device: | 656 | error_device: |
589 | ida_simple_remove(&fpga_mgr_ida, id); | 657 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); |
590 | error_kfree: | ||
591 | kfree(mgr); | ||
592 | 658 | ||
593 | return ret; | 659 | return ret; |
594 | } | 660 | } |
595 | EXPORT_SYMBOL_GPL(fpga_mgr_register); | 661 | EXPORT_SYMBOL_GPL(fpga_mgr_register); |
596 | 662 | ||
597 | /** | 663 | /** |
598 | * fpga_mgr_unregister - unregister a low level fpga manager driver | 664 | * fpga_mgr_unregister - unregister and free a FPGA manager |
599 | * @dev: fpga manager device from pdev | 665 | * @mgr: fpga manager struct |
600 | */ | 666 | */ |
601 | void fpga_mgr_unregister(struct device *dev) | 667 | void fpga_mgr_unregister(struct fpga_manager *mgr) |
602 | { | 668 | { |
603 | struct fpga_manager *mgr = dev_get_drvdata(dev); | ||
604 | |||
605 | dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); | 669 | dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); |
606 | 670 | ||
607 | /* | 671 | /* |
@@ -619,8 +683,7 @@ static void fpga_mgr_dev_release(struct device *dev) | |||
619 | { | 683 | { |
620 | struct fpga_manager *mgr = to_fpga_manager(dev); | 684 | struct fpga_manager *mgr = to_fpga_manager(dev); |
621 | 685 | ||
622 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); | 686 | fpga_mgr_free(mgr); |
623 | kfree(mgr); | ||
624 | } | 687 | } |
625 | 688 | ||
626 | static int __init fpga_mgr_class_init(void) | 689 | static int __init fpga_mgr_class_init(void) |