diff options
Diffstat (limited to 'drivers/fpga/fpga-mgr.c')
| -rw-r--r-- | drivers/fpga/fpga-mgr.c | 129 |
1 files changed, 82 insertions, 47 deletions
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 9939d2cbc9a6..c1564cf827fe 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) |
| @@ -429,11 +438,9 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) | |||
| 429 | } | 438 | } |
| 430 | 439 | ||
| 431 | /** | 440 | /** |
| 432 | * fpga_mgr_get - get a reference to a fpga mgr | 441 | * fpga_mgr_get - Given a device, get a reference to a fpga mgr. |
| 433 | * @dev: parent device that fpga mgr was registered with | 442 | * @dev: parent device that fpga mgr was registered with |
| 434 | * | 443 | * |
| 435 | * Given a device, get a reference to a fpga mgr. | ||
| 436 | * | ||
| 437 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 444 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
| 438 | */ | 445 | */ |
| 439 | struct fpga_manager *fpga_mgr_get(struct device *dev) | 446 | struct fpga_manager *fpga_mgr_get(struct device *dev) |
| @@ -453,10 +460,9 @@ static int fpga_mgr_of_node_match(struct device *dev, const void *data) | |||
| 453 | } | 460 | } |
| 454 | 461 | ||
| 455 | /** | 462 | /** |
| 456 | * of_fpga_mgr_get - get a reference to a fpga mgr | 463 | * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr. |
| 457 | * @node: device node | ||
| 458 | * | 464 | * |
| 459 | * Given a device node, get a reference to a fpga mgr. | 465 | * @node: device node |
| 460 | * | 466 | * |
| 461 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 467 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
| 462 | */ | 468 | */ |
| @@ -489,7 +495,10 @@ EXPORT_SYMBOL_GPL(fpga_mgr_put); | |||
| 489 | * @mgr: fpga manager | 495 | * @mgr: fpga manager |
| 490 | * | 496 | * |
| 491 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or | 497 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or |
| 492 | * of_fpga_mgr_put()) attempt to get the mutex. | 498 | * of_fpga_mgr_put()) attempt to get the mutex. The user should call |
| 499 | * fpga_mgr_lock() and verify that it returns 0 before attempting to | ||
| 500 | * program the FPGA. Likewise, the user should call fpga_mgr_unlock | ||
| 501 | * when done programming the FPGA. | ||
| 493 | * | 502 | * |
| 494 | * Return: 0 for success or -EBUSY | 503 | * Return: 0 for success or -EBUSY |
| 495 | */ | 504 | */ |
| @@ -505,7 +514,7 @@ int fpga_mgr_lock(struct fpga_manager *mgr) | |||
| 505 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); | 514 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); |
| 506 | 515 | ||
| 507 | /** | 516 | /** |
| 508 | * fpga_mgr_unlock - Unlock FPGA manager | 517 | * fpga_mgr_unlock - Unlock FPGA manager after done programming |
| 509 | * @mgr: fpga manager | 518 | * @mgr: fpga manager |
| 510 | */ | 519 | */ |
| 511 | void fpga_mgr_unlock(struct fpga_manager *mgr) | 520 | void fpga_mgr_unlock(struct fpga_manager *mgr) |
| @@ -515,17 +524,17 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) | |||
| 515 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); | 524 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); |
| 516 | 525 | ||
| 517 | /** | 526 | /** |
| 518 | * fpga_mgr_register - register a low level fpga manager driver | 527 | * fpga_mgr_create - create and initialize a FPGA manager struct |
| 519 | * @dev: fpga manager device from pdev | 528 | * @dev: fpga manager device from pdev |
| 520 | * @name: fpga manager name | 529 | * @name: fpga manager name |
| 521 | * @mops: pointer to structure of fpga manager ops | 530 | * @mops: pointer to structure of fpga manager ops |
| 522 | * @priv: fpga manager private data | 531 | * @priv: fpga manager private data |
| 523 | * | 532 | * |
| 524 | * Return: 0 on success, negative error code otherwise. | 533 | * Return: pointer to struct fpga_manager or NULL |
| 525 | */ | 534 | */ |
| 526 | int fpga_mgr_register(struct device *dev, const char *name, | 535 | struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, |
| 527 | const struct fpga_manager_ops *mops, | 536 | const struct fpga_manager_ops *mops, |
| 528 | void *priv) | 537 | void *priv) |
| 529 | { | 538 | { |
| 530 | struct fpga_manager *mgr; | 539 | struct fpga_manager *mgr; |
| 531 | int id, ret; | 540 | int id, ret; |
| @@ -534,17 +543,17 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
| 534 | !mops->write_init || (!mops->write && !mops->write_sg) || | 543 | !mops->write_init || (!mops->write && !mops->write_sg) || |
| 535 | (mops->write && mops->write_sg)) { | 544 | (mops->write && mops->write_sg)) { |
| 536 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); | 545 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); |
| 537 | return -EINVAL; | 546 | return NULL; |
| 538 | } | 547 | } |
| 539 | 548 | ||
| 540 | if (!name || !strlen(name)) { | 549 | if (!name || !strlen(name)) { |
| 541 | dev_err(dev, "Attempt to register with no name!\n"); | 550 | dev_err(dev, "Attempt to register with no name!\n"); |
| 542 | return -EINVAL; | 551 | return NULL; |
| 543 | } | 552 | } |
| 544 | 553 | ||
| 545 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | 554 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); |
| 546 | if (!mgr) | 555 | if (!mgr) |
| 547 | return -ENOMEM; | 556 | return NULL; |
| 548 | 557 | ||
| 549 | id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); | 558 | id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); |
| 550 | if (id < 0) { | 559 | if (id < 0) { |
| @@ -558,25 +567,56 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
| 558 | mgr->mops = mops; | 567 | mgr->mops = mops; |
| 559 | mgr->priv = priv; | 568 | mgr->priv = priv; |
| 560 | 569 | ||
| 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); | 570 | device_initialize(&mgr->dev); |
| 569 | mgr->dev.class = fpga_mgr_class; | 571 | mgr->dev.class = fpga_mgr_class; |
| 570 | mgr->dev.groups = mops->groups; | 572 | mgr->dev.groups = mops->groups; |
| 571 | mgr->dev.parent = dev; | 573 | mgr->dev.parent = dev; |
| 572 | mgr->dev.of_node = dev->of_node; | 574 | mgr->dev.of_node = dev->of_node; |
| 573 | mgr->dev.id = id; | 575 | mgr->dev.id = id; |
| 574 | dev_set_drvdata(dev, mgr); | ||
| 575 | 576 | ||
| 576 | ret = dev_set_name(&mgr->dev, "fpga%d", id); | 577 | ret = dev_set_name(&mgr->dev, "fpga%d", id); |
| 577 | if (ret) | 578 | if (ret) |
| 578 | goto error_device; | 579 | goto error_device; |
| 579 | 580 | ||
| 581 | return mgr; | ||
| 582 | |||
| 583 | error_device: | ||
| 584 | ida_simple_remove(&fpga_mgr_ida, id); | ||
| 585 | error_kfree: | ||
| 586 | kfree(mgr); | ||
| 587 | |||
| 588 | return NULL; | ||
| 589 | } | ||
| 590 | EXPORT_SYMBOL_GPL(fpga_mgr_create); | ||
| 591 | |||
| 592 | /** | ||
| 593 | * fpga_mgr_free - deallocate a FPGA manager | ||
| 594 | * @mgr: fpga manager struct created by fpga_mgr_create | ||
| 595 | */ | ||
| 596 | void fpga_mgr_free(struct fpga_manager *mgr) | ||
| 597 | { | ||
| 598 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); | ||
| 599 | kfree(mgr); | ||
| 600 | } | ||
| 601 | EXPORT_SYMBOL_GPL(fpga_mgr_free); | ||
| 602 | |||
| 603 | /** | ||
| 604 | * fpga_mgr_register - register a FPGA manager | ||
| 605 | * @mgr: fpga manager struct created by fpga_mgr_create | ||
| 606 | * | ||
| 607 | * Return: 0 on success, negative error code otherwise. | ||
| 608 | */ | ||
| 609 | int fpga_mgr_register(struct fpga_manager *mgr) | ||
| 610 | { | ||
| 611 | int ret; | ||
| 612 | |||
| 613 | /* | ||
| 614 | * Initialize framework state by requesting low level driver read state | ||
| 615 | * from device. FPGA may be in reset mode or may have been programmed | ||
| 616 | * by bootloader or EEPROM. | ||
| 617 | */ | ||
| 618 | mgr->state = mgr->mops->state(mgr); | ||
| 619 | |||
| 580 | ret = device_add(&mgr->dev); | 620 | ret = device_add(&mgr->dev); |
| 581 | if (ret) | 621 | if (ret) |
| 582 | goto error_device; | 622 | goto error_device; |
| @@ -586,22 +626,18 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
| 586 | return 0; | 626 | return 0; |
| 587 | 627 | ||
| 588 | error_device: | 628 | error_device: |
| 589 | ida_simple_remove(&fpga_mgr_ida, id); | 629 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); |
| 590 | error_kfree: | ||
| 591 | kfree(mgr); | ||
| 592 | 630 | ||
| 593 | return ret; | 631 | return ret; |
| 594 | } | 632 | } |
| 595 | EXPORT_SYMBOL_GPL(fpga_mgr_register); | 633 | EXPORT_SYMBOL_GPL(fpga_mgr_register); |
| 596 | 634 | ||
| 597 | /** | 635 | /** |
| 598 | * fpga_mgr_unregister - unregister a low level fpga manager driver | 636 | * fpga_mgr_unregister - unregister and free a FPGA manager |
| 599 | * @dev: fpga manager device from pdev | 637 | * @mgr: fpga manager struct |
| 600 | */ | 638 | */ |
| 601 | void fpga_mgr_unregister(struct device *dev) | 639 | void fpga_mgr_unregister(struct fpga_manager *mgr) |
| 602 | { | 640 | { |
| 603 | struct fpga_manager *mgr = dev_get_drvdata(dev); | ||
| 604 | |||
| 605 | dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); | 641 | dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); |
| 606 | 642 | ||
| 607 | /* | 643 | /* |
| @@ -619,8 +655,7 @@ static void fpga_mgr_dev_release(struct device *dev) | |||
| 619 | { | 655 | { |
| 620 | struct fpga_manager *mgr = to_fpga_manager(dev); | 656 | struct fpga_manager *mgr = to_fpga_manager(dev); |
| 621 | 657 | ||
| 622 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); | 658 | fpga_mgr_free(mgr); |
| 623 | kfree(mgr); | ||
| 624 | } | 659 | } |
| 625 | 660 | ||
| 626 | static int __init fpga_mgr_class_init(void) | 661 | static int __init fpga_mgr_class_init(void) |
