From 84d84c5b8ff1a91bbd463a84df65b16ea60dff5d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 17 Apr 2018 19:49:06 +0200 Subject: fpga: Remove depends on HAS_DMA in case of platform dependency Remove dependencies on HAS_DMA where a Kconfig symbol depends on another symbol that implies HAS_DMA, and, optionally, on "|| COMPILE_TEST". In most cases this other symbol is an architecture or platform specific symbol, or PCI. Generic symbols and drivers without platform dependencies keep their dependencies on HAS_DMA, to prevent compiling subsystems or drivers that cannot work anyway. This simplifies the dependencies, and allows to improve compile-testing. Signed-off-by: Geert Uytterhoeven Reviewed-by: Mark Brown Acked-by: Robin Murphy Acked-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index f47ef848bcd0..fd539132542e 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -53,7 +53,6 @@ config FPGA_MGR_ALTERA_CVP config FPGA_MGR_ZYNQ_FPGA tristate "Xilinx Zynq FPGA" depends on ARCH_ZYNQ || COMPILE_TEST - depends on HAS_DMA help FPGA manager driver support for Xilinx Zynq FPGAs. -- cgit v1.2.3 From 88fb3a0023307356a05f6b8e61a0ccddc6d32b2c Mon Sep 17 00:00:00 2001 From: Paolo Pisati Date: Mon, 16 Apr 2018 20:43:36 -0700 Subject: fpga: lattice machxo2: Add Lattice MachXO2 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support to the FPGA manager for programming MachXO2 device’s internal flash memory, via slave SPI. Signed-off-by: Paolo Pisati [atull@kernel.org: use existing FPGA mgr API] Signed-off-by: Alan Tull Signed-off-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/Kconfig | 7 + drivers/fpga/Makefile | 1 + drivers/fpga/machxo2-spi.c | 403 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+) create mode 100644 drivers/fpga/machxo2-spi.c (limited to 'drivers/fpga') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index fd539132542e..ee9c5420c47f 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -69,6 +69,13 @@ config FPGA_MGR_ICE40_SPI help FPGA manager driver support for Lattice iCE40 FPGAs over SPI. +config FPGA_MGR_MACHXO2_SPI + tristate "Lattice MachXO2 SPI" + depends on SPI + help + FPGA manager driver support for Lattice MachXO2 configuration + over slave SPI interface. + config FPGA_MGR_TS73XX tristate "Technologic Systems TS-73xx SBC FPGA Manager" depends on ARCH_EP93XX && MACH_TS72XX diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 3cb276a0f88d..f9803dad6919 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o obj-$(CONFIG_FPGA_MGR_ALTERA_CVP) += altera-cvp.o obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI) += altera-ps-spi.o obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o +obj-$(CONFIG_FPGA_MGR_MACHXO2_SPI) += machxo2-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c new file mode 100644 index 000000000000..8e95ec9c5c9a --- /dev/null +++ b/drivers/fpga/machxo2-spi.c @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Lattice MachXO2 Slave SPI Driver + * + * Manage Lattice FPGA firmware that is loaded over SPI using + * the slave serial configuration interface. + * + * Copyright (C) 2018 Paolo Pisati + */ + +#include +#include +#include +#include +#include +#include + +/* MachXO2 Programming Guide - sysCONFIG Programming Commands */ +#define IDCODE_PUB {0xe0, 0x00, 0x00, 0x00} +#define ISC_ENABLE {0xc6, 0x08, 0x00, 0x00} +#define ISC_ERASE {0x0e, 0x04, 0x00, 0x00} +#define ISC_PROGRAMDONE {0x5e, 0x00, 0x00, 0x00} +#define LSC_INITADDRESS {0x46, 0x00, 0x00, 0x00} +#define LSC_PROGINCRNV {0x70, 0x00, 0x00, 0x01} +#define LSC_READ_STATUS {0x3c, 0x00, 0x00, 0x00} +#define LSC_REFRESH {0x79, 0x00, 0x00, 0x00} + +/* + * Max CCLK in Slave SPI mode according to 'MachXO2 Family Data + * Sheet' sysCONFIG Port Timing Specifications (3-36) + */ +#define MACHXO2_MAX_SPEED 66000000 + +#define MACHXO2_LOW_DELAY_USEC 5 +#define MACHXO2_HIGH_DELAY_USEC 200 +#define MACHXO2_REFRESH_USEC 4800 +#define MACHXO2_MAX_BUSY_LOOP 128 +#define MACHXO2_MAX_REFRESH_LOOP 16 + +#define MACHXO2_PAGE_SIZE 16 +#define MACHXO2_BUF_SIZE (MACHXO2_PAGE_SIZE + 4) + +/* Status register bits, errors and error mask */ +#define BUSY 12 +#define DONE 8 +#define DVER 27 +#define ENAB 9 +#define ERRBITS 23 +#define ERRMASK 7 +#define FAIL 13 + +#define ENOERR 0 /* no error */ +#define EID 1 +#define ECMD 2 +#define ECRC 3 +#define EPREAM 4 /* preamble error */ +#define EABRT 5 /* abort error */ +#define EOVERFL 6 /* overflow error */ +#define ESDMEOF 7 /* SDM EOF */ + +static inline u8 get_err(unsigned long *status) +{ + return (*status >> ERRBITS) & ERRMASK; +} + +static int get_status(struct spi_device *spi, unsigned long *status) +{ + struct spi_message msg; + struct spi_transfer rx, tx; + static const u8 cmd[] = LSC_READ_STATUS; + int ret; + + memset(&rx, 0, sizeof(rx)); + memset(&tx, 0, sizeof(tx)); + tx.tx_buf = cmd; + tx.len = sizeof(cmd); + rx.rx_buf = status; + rx.len = 4; + spi_message_init(&msg); + spi_message_add_tail(&tx, &msg); + spi_message_add_tail(&rx, &msg); + ret = spi_sync(spi, &msg); + if (ret) + return ret; + + *status = be32_to_cpu(*status); + + return 0; +} + +#ifdef DEBUG +static const char *get_err_string(u8 err) +{ + switch (err) { + case ENOERR: return "No Error"; + case EID: return "ID ERR"; + case ECMD: return "CMD ERR"; + case ECRC: return "CRC ERR"; + case EPREAM: return "Preamble ERR"; + case EABRT: return "Abort ERR"; + case EOVERFL: return "Overflow ERR"; + case ESDMEOF: return "SDM EOF"; + } + + return "Default switch case"; +} +#endif + +static void dump_status_reg(unsigned long *status) +{ +#ifdef DEBUG + pr_debug("machxo2 status: 0x%08lX - done=%d, cfgena=%d, busy=%d, fail=%d, devver=%d, err=%s\n", + *status, test_bit(DONE, status), test_bit(ENAB, status), + test_bit(BUSY, status), test_bit(FAIL, status), + test_bit(DVER, status), get_err_string(get_err(status))); +#endif +} + +static int wait_until_not_busy(struct spi_device *spi) +{ + unsigned long status; + int ret, loop = 0; + + do { + ret = get_status(spi, &status); + if (ret) + return ret; + if (++loop >= MACHXO2_MAX_BUSY_LOOP) + return -EBUSY; + } while (test_bit(BUSY, &status)); + + return 0; +} + +static int machxo2_cleanup(struct fpga_manager *mgr) +{ + struct spi_device *spi = mgr->priv; + struct spi_message msg; + struct spi_transfer tx[2]; + static const u8 erase[] = ISC_ERASE; + static const u8 refresh[] = LSC_REFRESH; + int ret; + + memset(tx, 0, sizeof(tx)); + spi_message_init(&msg); + tx[0].tx_buf = &erase; + tx[0].len = sizeof(erase); + spi_message_add_tail(&tx[0], &msg); + ret = spi_sync(spi, &msg); + if (ret) + goto fail; + + ret = wait_until_not_busy(spi); + if (ret) + goto fail; + + spi_message_init(&msg); + tx[1].tx_buf = &refresh; + tx[1].len = sizeof(refresh); + tx[1].delay_usecs = MACHXO2_REFRESH_USEC; + spi_message_add_tail(&tx[1], &msg); + ret = spi_sync(spi, &msg); + if (ret) + goto fail; + + return 0; +fail: + dev_err(&mgr->dev, "Cleanup failed\n"); + + return ret; +} + +static enum fpga_mgr_states machxo2_spi_state(struct fpga_manager *mgr) +{ + struct spi_device *spi = mgr->priv; + unsigned long status; + + get_status(spi, &status); + if (!test_bit(BUSY, &status) && test_bit(DONE, &status) && + get_err(&status) == ENOERR) + return FPGA_MGR_STATE_OPERATING; + + return FPGA_MGR_STATE_UNKNOWN; +} + +static int machxo2_write_init(struct fpga_manager *mgr, + struct fpga_image_info *info, + const char *buf, size_t count) +{ + struct spi_device *spi = mgr->priv; + struct spi_message msg; + struct spi_transfer tx[3]; + static const u8 enable[] = ISC_ENABLE; + static const u8 erase[] = ISC_ERASE; + static const u8 initaddr[] = LSC_INITADDRESS; + unsigned long status; + int ret; + + if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { + dev_err(&mgr->dev, + "Partial reconfiguration is not supported\n"); + return -ENOTSUPP; + } + + get_status(spi, &status); + dump_status_reg(&status); + memset(tx, 0, sizeof(tx)); + spi_message_init(&msg); + tx[0].tx_buf = &enable; + tx[0].len = sizeof(enable); + tx[0].delay_usecs = MACHXO2_LOW_DELAY_USEC; + spi_message_add_tail(&tx[0], &msg); + + tx[1].tx_buf = &erase; + tx[1].len = sizeof(erase); + spi_message_add_tail(&tx[1], &msg); + ret = spi_sync(spi, &msg); + if (ret) + goto fail; + + ret = wait_until_not_busy(spi); + if (ret) + goto fail; + + get_status(spi, &status); + if (test_bit(FAIL, &status)) + goto fail; + dump_status_reg(&status); + + spi_message_init(&msg); + tx[2].tx_buf = &initaddr; + tx[2].len = sizeof(initaddr); + spi_message_add_tail(&tx[2], &msg); + ret = spi_sync(spi, &msg); + if (ret) + goto fail; + + get_status(spi, &status); + dump_status_reg(&status); + + return 0; +fail: + dev_err(&mgr->dev, "Error during FPGA init.\n"); + + return ret; +} + +static int machxo2_write(struct fpga_manager *mgr, const char *buf, + size_t count) +{ + struct spi_device *spi = mgr->priv; + struct spi_message msg; + struct spi_transfer tx; + static const u8 progincr[] = LSC_PROGINCRNV; + u8 payload[MACHXO2_BUF_SIZE]; + unsigned long status; + int i, ret; + + if (count % MACHXO2_PAGE_SIZE != 0) { + dev_err(&mgr->dev, "Malformed payload.\n"); + return -EINVAL; + } + get_status(spi, &status); + dump_status_reg(&status); + memcpy(payload, &progincr, sizeof(progincr)); + for (i = 0; i < count; i += MACHXO2_PAGE_SIZE) { + memcpy(&payload[sizeof(progincr)], &buf[i], MACHXO2_PAGE_SIZE); + memset(&tx, 0, sizeof(tx)); + spi_message_init(&msg); + tx.tx_buf = payload; + tx.len = MACHXO2_BUF_SIZE; + tx.delay_usecs = MACHXO2_HIGH_DELAY_USEC; + spi_message_add_tail(&tx, &msg); + ret = spi_sync(spi, &msg); + if (ret) { + dev_err(&mgr->dev, "Error loading the bitstream.\n"); + return ret; + } + } + get_status(spi, &status); + dump_status_reg(&status); + + return 0; +} + +static int machxo2_write_complete(struct fpga_manager *mgr, + struct fpga_image_info *info) +{ + struct spi_device *spi = mgr->priv; + struct spi_message msg; + struct spi_transfer tx[2]; + static const u8 progdone[] = ISC_PROGRAMDONE; + static const u8 refresh[] = LSC_REFRESH; + unsigned long status; + int ret, refreshloop = 0; + + memset(tx, 0, sizeof(tx)); + spi_message_init(&msg); + tx[0].tx_buf = &progdone; + tx[0].len = sizeof(progdone); + spi_message_add_tail(&tx[0], &msg); + ret = spi_sync(spi, &msg); + if (ret) + goto fail; + ret = wait_until_not_busy(spi); + if (ret) + goto fail; + + get_status(spi, &status); + dump_status_reg(&status); + if (!test_bit(DONE, &status)) { + machxo2_cleanup(mgr); + goto fail; + } + + do { + spi_message_init(&msg); + tx[1].tx_buf = &refresh; + tx[1].len = sizeof(refresh); + tx[1].delay_usecs = MACHXO2_REFRESH_USEC; + spi_message_add_tail(&tx[1], &msg); + ret = spi_sync(spi, &msg); + if (ret) + goto fail; + + /* check refresh status */ + get_status(spi, &status); + dump_status_reg(&status); + if (!test_bit(BUSY, &status) && test_bit(DONE, &status) && + get_err(&status) == ENOERR) + break; + if (++refreshloop == MACHXO2_MAX_REFRESH_LOOP) { + machxo2_cleanup(mgr); + goto fail; + } + } while (1); + + get_status(spi, &status); + dump_status_reg(&status); + + return 0; +fail: + dev_err(&mgr->dev, "Refresh failed.\n"); + + return ret; +} + +static const struct fpga_manager_ops machxo2_ops = { + .state = machxo2_spi_state, + .write_init = machxo2_write_init, + .write = machxo2_write, + .write_complete = machxo2_write_complete, +}; + +static int machxo2_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + + if (spi->max_speed_hz > MACHXO2_MAX_SPEED) { + dev_err(dev, "Speed is too high\n"); + return -EINVAL; + } + + return fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager", + &machxo2_ops, spi); +} + +static int machxo2_spi_remove(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + + fpga_mgr_unregister(dev); + + return 0; +} + +static const struct of_device_id of_match[] = { + { .compatible = "lattice,machxo2-slave-spi", }, + {} +}; +MODULE_DEVICE_TABLE(of, of_match); + +static const struct spi_device_id lattice_ids[] = { + { "machxo2-slave-spi", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, lattice_ids); + +static struct spi_driver machxo2_spi_driver = { + .driver = { + .name = "machxo2-slave-spi", + .of_match_table = of_match_ptr(of_match), + }, + .probe = machxo2_spi_probe, + .remove = machxo2_spi_remove, + .id_table = lattice_ids, +}; + +module_spi_driver(machxo2_spi_driver) + +MODULE_AUTHOR("Paolo Pisati "); +MODULE_DESCRIPTION("Load Lattice FPGA firmware over SPI"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 093a89d4c21701e61025386a08a2d1ec5d97c805 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Mon, 16 Apr 2018 20:43:37 -0700 Subject: fpga: fpga-region: comment on fpga_region_program_fpga locking Add a comment to the header of fpga_region_program_fpga() regarding locking of the bridges. Signed-off-by: Alan Tull Signed-off-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/fpga') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index edab2a2e03ef..cb0603e07ff8 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -95,6 +95,11 @@ static void fpga_region_put(struct fpga_region *region) * fpga_region_program_fpga - program FPGA * @region: FPGA region * Program an FPGA using fpga image info (region->info). + * If the region has a get_bridges function, the exclusive reference for the + * bridges will be held if programming succeeds. This is intended to prevent + * reprogramming the region until the caller considers it safe to do so. + * The caller will need to call fpga_bridges_put() before attempting to + * reprogram the region. * Return 0 for success or negative error code. */ int fpga_region_program_fpga(struct fpga_region *region) -- cgit v1.2.3 From bbaa9cd3a605e337cefc566e5ac1b110763c8d1c Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:49:54 -0500 Subject: fpga: region: don't use drvdata in common fpga code Changes to fpga_region_register function to not set drvdata. Setting drvdata is fine for DT based devices that will have one region per platform device. However PCIe based devices may have multiple FPGA regions under one PCIe device. Without these changes, the PCIe solution has to create an extra device for each child region to hold drvdata. Signed-off-by: Alan Tull Reported-by: Jiuyue Ma Signed-off-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 1 - drivers/fpga/of-fpga-region.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index cb0603e07ff8..f634a8ed5e2c 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -183,7 +183,6 @@ int fpga_region_register(struct device *dev, struct fpga_region *region) region->dev.parent = dev; region->dev.of_node = dev->of_node; region->dev.id = id; - dev_set_drvdata(dev, region); ret = dev_set_name(®ion->dev, "region%d", id); if (ret) diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index 119ff75522f1..35e7e8c4a0cb 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -438,6 +438,7 @@ static int of_fpga_region_probe(struct platform_device *pdev) goto eprobe_mgr_put; of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); + dev_set_drvdata(dev, region); dev_info(dev, "FPGA Region probed\n"); -- cgit v1.2.3 From 7085e2a94f7df5f419e3cfb2fe809ce6564e9629 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:49:55 -0500 Subject: fpga: manager: change api, don't use drvdata Change fpga_mgr_register to not set or use drvdata. This supports the case where a PCIe device has more than one manager. Add fpga_mgr_create/free functions. Change fpga_mgr_register and fpga_mgr_unregister functions to take the mgr struct as their only parameter. struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, const struct fpga_manager_ops *mops, void *priv); void fpga_mgr_free(struct fpga_manager *mgr); int fpga_mgr_register(struct fpga_manager *mgr); void fpga_mgr_unregister(struct fpga_manager *mgr); Update the drivers that call fpga_mgr_register with the new API. Signed-off-by: Alan Tull [Moritz: Fixup whitespace issue] Reported-by: Jiuyue Ma Signed-off-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/altera-cvp.c | 19 +++++++--- drivers/fpga/altera-pr-ip-core.c | 18 ++++++++-- drivers/fpga/altera-ps-spi.c | 20 +++++++++-- drivers/fpga/fpga-mgr.c | 78 ++++++++++++++++++++++++++-------------- drivers/fpga/ice40-spi.c | 21 ++++++++--- drivers/fpga/machxo2-spi.c | 20 ++++++++--- drivers/fpga/socfpga-a10.c | 14 ++++++-- drivers/fpga/socfpga.c | 19 ++++++++-- drivers/fpga/ts73xx-fpga.c | 20 +++++++++-- drivers/fpga/xilinx-spi.c | 20 +++++++++-- drivers/fpga/zynq-fpga.c | 14 ++++++-- 11 files changed, 204 insertions(+), 59 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 77b04e4b3254..dd4edd8f22ce 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -401,6 +401,7 @@ static int altera_cvp_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) { struct altera_cvp_conf *conf; + struct fpga_manager *mgr; u16 cmd, val; int ret; @@ -452,16 +453,24 @@ static int altera_cvp_probe(struct pci_dev *pdev, snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s", ALTERA_CVP_MGR_NAME, pci_name(pdev)); - ret = fpga_mgr_register(&pdev->dev, conf->mgr_name, - &altera_cvp_ops, conf); - if (ret) + mgr = fpga_mgr_create(&pdev->dev, conf->mgr_name, + &altera_cvp_ops, conf); + if (!mgr) + return -ENOMEM; + + pci_set_drvdata(pdev, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) { + fpga_mgr_free(mgr); goto err_unmap; + } ret = driver_create_file(&altera_cvp_driver.driver, &driver_attr_chkcfg); if (ret) { dev_err(&pdev->dev, "Can't create sysfs chkcfg file\n"); - fpga_mgr_unregister(&pdev->dev); + fpga_mgr_unregister(mgr); goto err_unmap; } @@ -483,7 +492,7 @@ static void altera_cvp_remove(struct pci_dev *pdev) u16 cmd; driver_remove_file(&altera_cvp_driver.driver, &driver_attr_chkcfg); - fpga_mgr_unregister(&pdev->dev); + fpga_mgr_unregister(mgr); pci_iounmap(pdev, conf->map); pci_release_region(pdev, CVP_BAR); pci_read_config_word(pdev, PCI_COMMAND, &cmd); diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index a7b31f9797ce..eea521774cf6 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c @@ -187,6 +187,8 @@ static const struct fpga_manager_ops alt_pr_ops = { int alt_pr_register(struct device *dev, void __iomem *reg_base) { struct alt_pr_priv *priv; + struct fpga_manager *mgr; + int ret; u32 val; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -201,15 +203,27 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT, (int)(val & ALT_PR_CSR_PR_START)); - return fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv); + mgr = fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv); + if (!mgr) + return -ENOMEM; + + dev_set_drvdata(dev, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } EXPORT_SYMBOL_GPL(alt_pr_register); int alt_pr_unregister(struct device *dev) { + struct fpga_manager *mgr = dev_get_drvdata(dev); + dev_dbg(dev, "%s\n", __func__); - fpga_mgr_unregister(dev); + fpga_mgr_unregister(mgr); return 0; } diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c index 06d212a3d49d..24b25c626036 100644 --- a/drivers/fpga/altera-ps-spi.c +++ b/drivers/fpga/altera-ps-spi.c @@ -238,6 +238,8 @@ static int altera_ps_probe(struct spi_device *spi) { struct altera_ps_conf *conf; const struct of_device_id *of_id; + struct fpga_manager *mgr; + int ret; conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); if (!conf) @@ -273,13 +275,25 @@ static int altera_ps_probe(struct spi_device *spi) snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s", dev_driver_string(&spi->dev), dev_name(&spi->dev)); - return fpga_mgr_register(&spi->dev, conf->mgr_name, - &altera_ps_ops, conf); + mgr = fpga_mgr_create(&spi->dev, conf->mgr_name, + &altera_ps_ops, conf); + if (!mgr) + return -ENOMEM; + + spi_set_drvdata(spi, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } static int altera_ps_remove(struct spi_device *spi) { - fpga_mgr_unregister(&spi->dev); + struct fpga_manager *mgr = spi_get_drvdata(spi); + + fpga_mgr_unregister(mgr); return 0; } diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 9939d2cbc9a6..0a5181db3e2b 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -515,17 +515,17 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) EXPORT_SYMBOL_GPL(fpga_mgr_unlock); /** - * fpga_mgr_register - register a low level fpga manager driver + * fpga_mgr_create - create and initialize a FPGA manager struct * @dev: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops * @priv: fpga manager private data * - * Return: 0 on success, negative error code otherwise. + * Return: pointer to struct fpga_manager or NULL */ -int fpga_mgr_register(struct device *dev, const char *name, - const struct fpga_manager_ops *mops, - void *priv) +struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, + const struct fpga_manager_ops *mops, + void *priv) { struct fpga_manager *mgr; int id, ret; @@ -534,17 +534,17 @@ int fpga_mgr_register(struct device *dev, const char *name, !mops->write_init || (!mops->write && !mops->write_sg) || (mops->write && mops->write_sg)) { dev_err(dev, "Attempt to register without fpga_manager_ops\n"); - return -EINVAL; + return NULL; } if (!name || !strlen(name)) { dev_err(dev, "Attempt to register with no name!\n"); - return -EINVAL; + return NULL; } mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); if (!mgr) - return -ENOMEM; + return NULL; id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); if (id < 0) { @@ -558,25 +558,56 @@ int fpga_mgr_register(struct device *dev, const char *name, mgr->mops = mops; mgr->priv = priv; - /* - * Initialize framework state by requesting low level driver read state - * from device. FPGA may be in reset mode or may have been programmed - * by bootloader or EEPROM. - */ - mgr->state = mgr->mops->state(mgr); - device_initialize(&mgr->dev); mgr->dev.class = fpga_mgr_class; mgr->dev.groups = mops->groups; mgr->dev.parent = dev; mgr->dev.of_node = dev->of_node; mgr->dev.id = id; - dev_set_drvdata(dev, mgr); ret = dev_set_name(&mgr->dev, "fpga%d", id); if (ret) goto error_device; + return mgr; + +error_device: + ida_simple_remove(&fpga_mgr_ida, id); +error_kfree: + kfree(mgr); + + return NULL; +} +EXPORT_SYMBOL_GPL(fpga_mgr_create); + +/** + * fpga_mgr_free - deallocate a FPGA manager + * @mgr: fpga manager struct created by fpga_mgr_create + */ +void fpga_mgr_free(struct fpga_manager *mgr) +{ + ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); + kfree(mgr); +} +EXPORT_SYMBOL_GPL(fpga_mgr_free); + +/** + * fpga_mgr_register - register a FPGA manager + * @mgr: fpga manager struct created by fpga_mgr_create + * + * Return: 0 on success, negative error code otherwise. + */ +int fpga_mgr_register(struct fpga_manager *mgr) +{ + int ret; + + /* + * Initialize framework state by requesting low level driver read state + * from device. FPGA may be in reset mode or may have been programmed + * by bootloader or EEPROM. + */ + mgr->state = mgr->mops->state(mgr); + ret = device_add(&mgr->dev); if (ret) goto error_device; @@ -586,22 +617,18 @@ int fpga_mgr_register(struct device *dev, const char *name, return 0; error_device: - ida_simple_remove(&fpga_mgr_ida, id); -error_kfree: - kfree(mgr); + ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); return ret; } EXPORT_SYMBOL_GPL(fpga_mgr_register); /** - * fpga_mgr_unregister - unregister a low level fpga manager driver - * @dev: fpga manager device from pdev + * fpga_mgr_unregister - unregister a FPGA manager + * @mgr: fpga manager struct */ -void fpga_mgr_unregister(struct device *dev) +void fpga_mgr_unregister(struct fpga_manager *mgr) { - struct fpga_manager *mgr = dev_get_drvdata(dev); - dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); /* @@ -619,8 +646,7 @@ static void fpga_mgr_dev_release(struct device *dev) { struct fpga_manager *mgr = to_fpga_manager(dev); - ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); - kfree(mgr); + fpga_mgr_free(mgr); } static int __init fpga_mgr_class_init(void) diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c index 7fca82023062..5981c7ee7a7d 100644 --- a/drivers/fpga/ice40-spi.c +++ b/drivers/fpga/ice40-spi.c @@ -133,6 +133,7 @@ static int ice40_fpga_probe(struct spi_device *spi) { struct device *dev = &spi->dev; struct ice40_fpga_priv *priv; + struct fpga_manager *mgr; int ret; priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); @@ -174,14 +175,26 @@ static int ice40_fpga_probe(struct spi_device *spi) return ret; } - /* Register with the FPGA manager */ - return fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager", - &ice40_fpga_ops, priv); + mgr = fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager", + &ice40_fpga_ops, priv); + if (!mgr) + return -ENOMEM; + + spi_set_drvdata(spi, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } static int ice40_fpga_remove(struct spi_device *spi) { - fpga_mgr_unregister(&spi->dev); + struct fpga_manager *mgr = spi_get_drvdata(spi); + + fpga_mgr_unregister(mgr); + return 0; } diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c index 8e95ec9c5c9a..a582e0000c97 100644 --- a/drivers/fpga/machxo2-spi.c +++ b/drivers/fpga/machxo2-spi.c @@ -355,21 +355,33 @@ static const struct fpga_manager_ops machxo2_ops = { static int machxo2_spi_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct fpga_manager *mgr; + int ret; if (spi->max_speed_hz > MACHXO2_MAX_SPEED) { dev_err(dev, "Speed is too high\n"); return -EINVAL; } - return fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager", - &machxo2_ops, spi); + mgr = fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager", + &machxo2_ops, spi); + if (!mgr) + return -ENOMEM; + + spi_set_drvdata(spi, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } static int machxo2_spi_remove(struct spi_device *spi) { - struct device *dev = &spi->dev; + struct fpga_manager *mgr = spi_get_drvdata(spi); - fpga_mgr_unregister(dev); + fpga_mgr_unregister(mgr); return 0; } diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c index a46e343a5b72..dec3db5cdab1 100644 --- a/drivers/fpga/socfpga-a10.c +++ b/drivers/fpga/socfpga-a10.c @@ -482,6 +482,7 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct a10_fpga_priv *priv; void __iomem *reg_base; + struct fpga_manager *mgr; struct resource *res; int ret; @@ -519,9 +520,16 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) return -EBUSY; } - ret = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager", - &socfpga_a10_fpga_mgr_ops, priv); + mgr = fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager", + &socfpga_a10_fpga_mgr_ops, priv); + if (!mgr) + return -ENOMEM; + + platform_set_drvdata(pdev, mgr); + + ret = fpga_mgr_register(mgr); if (ret) { + fpga_mgr_free(mgr); clk_disable_unprepare(priv->clk); return ret; } @@ -534,7 +542,7 @@ static int socfpga_a10_fpga_remove(struct platform_device *pdev) struct fpga_manager *mgr = platform_get_drvdata(pdev); struct a10_fpga_priv *priv = mgr->priv; - fpga_mgr_unregister(&pdev->dev); + fpga_mgr_unregister(mgr); clk_disable_unprepare(priv->clk); return 0; diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index b6672e66cda6..51efaf9e0e03 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c @@ -555,6 +555,7 @@ static int socfpga_fpga_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct socfpga_fpga_priv *priv; + struct fpga_manager *mgr; struct resource *res; int ret; @@ -581,13 +582,25 @@ static int socfpga_fpga_probe(struct platform_device *pdev) if (ret) return ret; - return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", - &socfpga_fpga_ops, priv); + mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", + &socfpga_fpga_ops, priv); + if (!mgr) + return -ENOMEM; + + platform_set_drvdata(pdev, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } static int socfpga_fpga_remove(struct platform_device *pdev) { - fpga_mgr_unregister(&pdev->dev); + struct fpga_manager *mgr = platform_get_drvdata(pdev); + + fpga_mgr_unregister(mgr); return 0; } diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c index f6a96b42e2ca..08efd1895b1b 100644 --- a/drivers/fpga/ts73xx-fpga.c +++ b/drivers/fpga/ts73xx-fpga.c @@ -116,7 +116,9 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) { struct device *kdev = &pdev->dev; struct ts73xx_fpga_priv *priv; + struct fpga_manager *mgr; struct resource *res; + int ret; priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -131,13 +133,25 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) return PTR_ERR(priv->io_base); } - return fpga_mgr_register(kdev, "TS-73xx FPGA Manager", - &ts73xx_fpga_ops, priv); + mgr = fpga_mgr_create(kdev, "TS-73xx FPGA Manager", + &ts73xx_fpga_ops, priv); + if (!mgr) + return -ENOMEM; + + platform_set_drvdata(pdev, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } static int ts73xx_fpga_remove(struct platform_device *pdev) { - fpga_mgr_unregister(&pdev->dev); + struct fpga_manager *mgr = platform_get_drvdata(pdev); + + fpga_mgr_unregister(mgr); return 0; } diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c index 9b62a4c2a3df..8d1945966533 100644 --- a/drivers/fpga/xilinx-spi.c +++ b/drivers/fpga/xilinx-spi.c @@ -143,6 +143,8 @@ static const struct fpga_manager_ops xilinx_spi_ops = { static int xilinx_spi_probe(struct spi_device *spi) { struct xilinx_spi_conf *conf; + struct fpga_manager *mgr; + int ret; conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); if (!conf) @@ -165,13 +167,25 @@ static int xilinx_spi_probe(struct spi_device *spi) return PTR_ERR(conf->done); } - return fpga_mgr_register(&spi->dev, "Xilinx Slave Serial FPGA Manager", - &xilinx_spi_ops, conf); + mgr = fpga_mgr_create(&spi->dev, "Xilinx Slave Serial FPGA Manager", + &xilinx_spi_ops, conf); + if (!mgr) + return -ENOMEM; + + spi_set_drvdata(spi, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } static int xilinx_spi_remove(struct spi_device *spi) { - fpga_mgr_unregister(&spi->dev); + struct fpga_manager *mgr = spi_get_drvdata(spi); + + fpga_mgr_unregister(mgr); return 0; } diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index 70b15b303471..3110e00121ca 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -558,6 +558,7 @@ static int zynq_fpga_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct zynq_fpga_priv *priv; + struct fpga_manager *mgr; struct resource *res; int err; @@ -613,10 +614,17 @@ static int zynq_fpga_probe(struct platform_device *pdev) clk_disable(priv->clk); - err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", - &zynq_fpga_ops, priv); + mgr = fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager", + &zynq_fpga_ops, priv); + if (!mgr) + return -ENOMEM; + + platform_set_drvdata(pdev, mgr); + + err = fpga_mgr_register(mgr); if (err) { dev_err(dev, "unable to register FPGA manager\n"); + fpga_mgr_free(mgr); clk_unprepare(priv->clk); return err; } @@ -632,7 +640,7 @@ static int zynq_fpga_remove(struct platform_device *pdev) mgr = platform_get_drvdata(pdev); priv = mgr->priv; - fpga_mgr_unregister(&pdev->dev); + fpga_mgr_unregister(mgr); clk_unprepare(priv->clk); -- cgit v1.2.3 From 371cd1b1fdabb33603340559049e46dfeae45b1e Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:49:56 -0500 Subject: fpga: bridge: change api, don't use drvdata Change fpga_bridge_register to not set drvdata. This is to support the case where a PCIe device can have more than one bridge. Add API functions to create/free the fpga bridge struct. Change fpga_bridge_register/unregister to take FPGA bridge struct as the only parameter. struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, const struct fpga_bridge_ops *br_ops, void *priv); void fpga_bridge_free(struct fpga_bridge *br); int fpga_bridge_register(struct fpga_bridge *br); void fpga_bridge_unregister(struct fpga_bridge *br); Update the drivers that call fpga_bridge_register with the new API. Signed-off-by: Alan Tull Reported-by: Jiuyue Ma Signed-off-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/altera-fpga2sdram.c | 21 ++++++++--- drivers/fpga/altera-freeze-bridge.c | 22 ++++++++++-- drivers/fpga/altera-hps2fpga.c | 24 ++++++++++--- drivers/fpga/fpga-bridge.c | 70 ++++++++++++++++++++++++------------- drivers/fpga/xilinx-pr-decoupler.c | 22 +++++++++--- 5 files changed, 117 insertions(+), 42 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c index d4eeb74388da..5a29ab6e3b28 100644 --- a/drivers/fpga/altera-fpga2sdram.c +++ b/drivers/fpga/altera-fpga2sdram.c @@ -106,6 +106,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct alt_fpga2sdram_data *priv; + struct fpga_bridge *br; u32 enable; struct regmap *sysmgr; int ret = 0; @@ -131,10 +132,18 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) /* Get f2s bridge configuration saved in handoff register */ regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask); - ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME, - &altera_fpga2sdram_br_ops, priv); - if (ret) + br = fpga_bridge_create(dev, F2S_BRIDGE_NAME, + &altera_fpga2sdram_br_ops, priv); + if (!br) + return -ENOMEM; + + platform_set_drvdata(pdev, br); + + ret = fpga_bridge_register(br); + if (ret) { + fpga_bridge_free(br); return ret; + } dev_info(dev, "driver initialized with handoff %08x\n", priv->mask); @@ -146,7 +155,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) (enable ? "enabling" : "disabling")); ret = _alt_fpga2sdram_enable_set(priv, enable); if (ret) { - fpga_bridge_unregister(&pdev->dev); + fpga_bridge_unregister(br); return ret; } } @@ -157,7 +166,9 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) static int alt_fpga_bridge_remove(struct platform_device *pdev) { - fpga_bridge_unregister(&pdev->dev); + struct fpga_bridge *br = platform_get_drvdata(pdev); + + fpga_bridge_unregister(br); return 0; } diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c index 6159cfcf78a2..fa4b693cf4be 100644 --- a/drivers/fpga/altera-freeze-bridge.c +++ b/drivers/fpga/altera-freeze-bridge.c @@ -221,8 +221,10 @@ static int altera_freeze_br_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; void __iomem *base_addr; struct altera_freeze_br_data *priv; + struct fpga_bridge *br; struct resource *res; u32 status, revision; + int ret; if (!np) return -ENODEV; @@ -254,13 +256,27 @@ static int altera_freeze_br_probe(struct platform_device *pdev) priv->base_addr = base_addr; - return fpga_bridge_register(dev, FREEZE_BRIDGE_NAME, - &altera_freeze_br_br_ops, priv); + br = fpga_bridge_create(dev, FREEZE_BRIDGE_NAME, + &altera_freeze_br_br_ops, priv); + if (!br) + return -ENOMEM; + + platform_set_drvdata(pdev, br); + + ret = fpga_bridge_register(br); + if (ret) { + fpga_bridge_free(br); + return ret; + } + + return 0; } static int altera_freeze_br_remove(struct platform_device *pdev) { - fpga_bridge_unregister(&pdev->dev); + struct fpga_bridge *br = platform_get_drvdata(pdev); + + fpga_bridge_unregister(br); return 0; } diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c index 406d2f10741f..e4d39f0a7572 100644 --- a/drivers/fpga/altera-hps2fpga.c +++ b/drivers/fpga/altera-hps2fpga.c @@ -139,6 +139,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct altera_hps2fpga_data *priv; const struct of_device_id *of_id; + struct fpga_bridge *br; u32 enable; int ret; @@ -190,11 +191,24 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) } } - ret = fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops, - priv); -err: + br = fpga_bridge_create(dev, priv->name, &altera_hps2fpga_br_ops, priv); + if (!br) { + ret = -ENOMEM; + goto err; + } + + platform_set_drvdata(pdev, br); + + ret = fpga_bridge_register(br); if (ret) - clk_disable_unprepare(priv->clk); + goto err_free; + + return 0; + +err_free: + fpga_bridge_free(br); +err: + clk_disable_unprepare(priv->clk); return ret; } @@ -204,7 +218,7 @@ static int alt_fpga_bridge_remove(struct platform_device *pdev) struct fpga_bridge *bridge = platform_get_drvdata(pdev); struct altera_hps2fpga_data *priv = bridge->priv; - fpga_bridge_unregister(&pdev->dev); + fpga_bridge_unregister(bridge); clk_disable_unprepare(priv->clk); diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 31bd2c59c305..2db1573507eb 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -328,28 +328,29 @@ static struct attribute *fpga_bridge_attrs[] = { ATTRIBUTE_GROUPS(fpga_bridge); /** - * fpga_bridge_register - register a fpga bridge driver + * fpga_bridge_create - create and initialize a struct fpga_bridge * @dev: FPGA bridge device from pdev * @name: FPGA bridge name * @br_ops: pointer to structure of fpga bridge ops * @priv: FPGA bridge private data * - * Return: 0 for success, error code otherwise. + * Return: struct fpga_bridge or NULL */ -int fpga_bridge_register(struct device *dev, const char *name, - const struct fpga_bridge_ops *br_ops, void *priv) +struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, + const struct fpga_bridge_ops *br_ops, + void *priv) { struct fpga_bridge *bridge; int id, ret = 0; if (!name || !strlen(name)) { dev_err(dev, "Attempt to register with no name!\n"); - return -EINVAL; + return NULL; } bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) - return -ENOMEM; + return NULL; id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL); if (id < 0) { @@ -370,40 +371,62 @@ int fpga_bridge_register(struct device *dev, const char *name, bridge->dev.parent = dev; bridge->dev.of_node = dev->of_node; bridge->dev.id = id; - dev_set_drvdata(dev, bridge); ret = dev_set_name(&bridge->dev, "br%d", id); if (ret) goto error_device; - ret = device_add(&bridge->dev); - if (ret) - goto error_device; - - of_platform_populate(dev->of_node, NULL, NULL, dev); - - dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n", - bridge->name); - - return 0; + return bridge; error_device: ida_simple_remove(&fpga_bridge_ida, id); error_kfree: kfree(bridge); - return ret; + return NULL; +} +EXPORT_SYMBOL_GPL(fpga_bridge_create); + +/** + * fpga_bridge_free - free a fpga bridge and its id + * @bridge: FPGA bridge struct created by fpga_bridge_create + */ +void fpga_bridge_free(struct fpga_bridge *bridge) +{ + ida_simple_remove(&fpga_bridge_ida, bridge->dev.id); + kfree(bridge); +} +EXPORT_SYMBOL_GPL(fpga_bridge_free); + +/** + * fpga_bridge_register - register a fpga bridge + * @bridge: FPGA bridge struct created by fpga_bridge_create + * + * Return: 0 for success, error code otherwise. + */ +int fpga_bridge_register(struct fpga_bridge *bridge) +{ + struct device *dev = &bridge->dev; + int ret; + + ret = device_add(dev); + if (ret) + return ret; + + of_platform_populate(dev->of_node, NULL, NULL, dev); + + dev_info(dev->parent, "fpga bridge [%s] registered\n", bridge->name); + + return 0; } EXPORT_SYMBOL_GPL(fpga_bridge_register); /** * fpga_bridge_unregister - unregister a fpga bridge driver - * @dev: FPGA bridge device from pdev + * @bridge: FPGA bridge struct created by fpga_bridge_create */ -void fpga_bridge_unregister(struct device *dev) +void fpga_bridge_unregister(struct fpga_bridge *bridge) { - struct fpga_bridge *bridge = dev_get_drvdata(dev); - /* * If the low level driver provides a method for putting bridge into * a desired state upon unregister, do it. @@ -419,8 +442,7 @@ static void fpga_bridge_dev_release(struct device *dev) { struct fpga_bridge *bridge = to_fpga_bridge(dev); - ida_simple_remove(&fpga_bridge_ida, bridge->dev.id); - kfree(bridge); + fpga_bridge_free(bridge); } static int __init fpga_bridge_dev_init(void) diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c index 0d7743089414..07ba1539e82c 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c @@ -94,6 +94,7 @@ MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match); static int xlnx_pr_decoupler_probe(struct platform_device *pdev) { struct xlnx_pr_decoupler_data *priv; + struct fpga_bridge *br; int err; struct resource *res; @@ -120,16 +121,27 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) clk_disable(priv->clk); - err = fpga_bridge_register(&pdev->dev, "Xilinx PR Decoupler", - &xlnx_pr_decoupler_br_ops, priv); + br = fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler", + &xlnx_pr_decoupler_br_ops, priv); + if (!br) { + err = -ENOMEM; + goto err_clk; + } + + platform_set_drvdata(pdev, br); + err = fpga_bridge_register(br); if (err) { dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler"); - clk_unprepare(priv->clk); - return err; + goto err_clk; } return 0; + +err_clk: + clk_unprepare(priv->clk); + + return err; } static int xlnx_pr_decoupler_remove(struct platform_device *pdev) @@ -137,7 +149,7 @@ static int xlnx_pr_decoupler_remove(struct platform_device *pdev) struct fpga_bridge *bridge = platform_get_drvdata(pdev); struct xlnx_pr_decoupler_data *p = bridge->priv; - fpga_bridge_unregister(&pdev->dev); + fpga_bridge_unregister(bridge); clk_unprepare(p->clk); -- cgit v1.2.3 From 9f368977b4589e2fe0b9d3a4cbaf11ff6a58ecf5 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:49:57 -0500 Subject: fpga: region: change api, add fpga_region_create/free Add fpga_region_create/free API functions. Change fpga_region_register to take FPGA region struct as the only parameter. Change fpga_region_unregister to return void. struct fpga_region *fpga_region_create(struct device *dev, struct fpga_manager *mgr, int (*get_bridges)(struct fpga_region *)); void fpga_region_free(struct fpga_region *region); int fpga_region_register(struct fpga_region *region); void fpga_region_unregister(struct fpga_region *region); Remove groups storage from struct fpga_region, it's not needed. Callers can just "region->dev.groups = groups;" after calling fpga_region_create. Update the drivers that call fpga_region_register with the new API. Signed-off-by: Alan Tull Signed-off-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 68 ++++++++++++++++++++++++++++++++++--------- drivers/fpga/of-fpga-region.c | 13 ++++----- 2 files changed, 60 insertions(+), 21 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index f634a8ed5e2c..b3ba3e40c44b 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -167,18 +167,36 @@ err_put_region: } EXPORT_SYMBOL_GPL(fpga_region_program_fpga); -int fpga_region_register(struct device *dev, struct fpga_region *region) +/** + * fpga_region_create - alloc and init a struct fpga_region + * @dev: device parent + * @mgr: manager that programs this region + * @get_bridges: optional function to get bridges to a list + * + * Return: struct fpga_region or NULL + */ +struct fpga_region +*fpga_region_create(struct device *dev, + struct fpga_manager *mgr, + int (*get_bridges)(struct fpga_region *)) { + struct fpga_region *region; int id, ret = 0; + region = kzalloc(sizeof(*region), GFP_KERNEL); + if (!region) + return NULL; + id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); if (id < 0) - return id; + goto err_free; + region->mgr = mgr; + region->get_bridges = get_bridges; mutex_init(®ion->mutex); INIT_LIST_HEAD(®ion->bridge_list); + device_initialize(®ion->dev); - region->dev.groups = region->groups; region->dev.class = fpga_region_class; region->dev.parent = dev; region->dev.of_node = dev->of_node; @@ -188,23 +206,47 @@ int fpga_region_register(struct device *dev, struct fpga_region *region) if (ret) goto err_remove; - ret = device_add(®ion->dev); - if (ret) - goto err_remove; - - return 0; + return region; err_remove: ida_simple_remove(&fpga_region_ida, id); - return ret; +err_free: + kfree(region); + + return NULL; +} +EXPORT_SYMBOL_GPL(fpga_region_create); + +/** + * fpga_region_free - free a struct fpga_region + * @region: FPGA region created by fpga_region_create + */ +void fpga_region_free(struct fpga_region *region) +{ + ida_simple_remove(&fpga_region_ida, region->dev.id); + kfree(region); +} +EXPORT_SYMBOL_GPL(fpga_region_free); + +/* + * fpga_region_register - register a FPGA region + * @region: FPGA region created by fpga_region_create + * Return: 0 or -errno + */ +int fpga_region_register(struct fpga_region *region) +{ + return device_add(®ion->dev); + } EXPORT_SYMBOL_GPL(fpga_region_register); -int fpga_region_unregister(struct fpga_region *region) +/* + * fpga_region_unregister - unregister a FPGA region + * @region: FPGA region + */ +void fpga_region_unregister(struct fpga_region *region) { device_unregister(®ion->dev); - - return 0; } EXPORT_SYMBOL_GPL(fpga_region_unregister); @@ -212,7 +254,7 @@ static void fpga_region_dev_release(struct device *dev) { struct fpga_region *region = to_fpga_region(dev); - ida_simple_remove(&fpga_region_ida, region->dev.id); + fpga_region_free(region); } /** diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index 35e7e8c4a0cb..9d681a1c5738 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -422,20 +422,15 @@ static int of_fpga_region_probe(struct platform_device *pdev) if (IS_ERR(mgr)) return -EPROBE_DEFER; - region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); + region = fpga_region_create(dev, mgr, of_fpga_region_get_bridges); if (!region) { ret = -ENOMEM; goto eprobe_mgr_put; } - region->mgr = mgr; - - /* Specify how to get bridges for this type of region. */ - region->get_bridges = of_fpga_region_get_bridges; - - ret = fpga_region_register(dev, region); + ret = fpga_region_register(region); if (ret) - goto eprobe_mgr_put; + goto eprobe_free; of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); dev_set_drvdata(dev, region); @@ -444,6 +439,8 @@ static int of_fpga_region_probe(struct platform_device *pdev) return 0; +eprobe_free: + fpga_region_free(region); eprobe_mgr_put: fpga_mgr_put(mgr); return ret; -- cgit v1.2.3 From 473f01f7e4b9fc53d44c446ad22b39070c65393f Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:49:58 -0500 Subject: fpga: use SPDX Replace GPLv2 boilerplate with SPDX in FPGA code that came from me or from Altera. Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/altera-fpga2sdram.c | 13 +------------ drivers/fpga/altera-freeze-bridge.c | 13 +------------ drivers/fpga/altera-hps2fpga.c | 13 +------------ drivers/fpga/altera-pr-ip-core-plat.c | 13 +------------ drivers/fpga/altera-pr-ip-core.c | 13 +------------ drivers/fpga/fpga-bridge.c | 13 +------------ drivers/fpga/fpga-mgr.c | 13 +------------ drivers/fpga/fpga-region.c | 14 +------------- drivers/fpga/of-fpga-region.c | 14 +------------- drivers/fpga/socfpga-a10.c | 14 +------------- drivers/fpga/socfpga.c | 13 +------------ 11 files changed, 11 insertions(+), 135 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c index 5a29ab6e3b28..23660ccd634b 100644 --- a/drivers/fpga/altera-fpga2sdram.c +++ b/drivers/fpga/altera-fpga2sdram.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices * * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ /* diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c index fa4b693cf4be..ffd586c48ecf 100644 --- a/drivers/fpga/altera-freeze-bridge.c +++ b/drivers/fpga/altera-freeze-bridge.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA Freeze Bridge Controller * * Copyright (C) 2016 Altera Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ #include #include diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c index e4d39f0a7572..a974d3f60321 100644 --- a/drivers/fpga/altera-hps2fpga.c +++ b/drivers/fpga/altera-hps2fpga.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices * @@ -6,18 +7,6 @@ * Includes this patch from the mailing list: * fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters * Signed-off-by: Anatolij Gustschin - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ /* diff --git a/drivers/fpga/altera-pr-ip-core-plat.c b/drivers/fpga/altera-pr-ip-core-plat.c index 8fb36b8b4648..b293d83143f1 100644 --- a/drivers/fpga/altera-pr-ip-core-plat.c +++ b/drivers/fpga/altera-pr-ip-core-plat.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for Altera Partial Reconfiguration IP Core * @@ -5,18 +6,6 @@ * * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation * by Alan Tull - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ #include #include diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index eea521774cf6..65e0b6a2c031 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for Altera Partial Reconfiguration IP Core * @@ -5,18 +6,6 @@ * * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation * by Alan Tull - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ #include #include diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 2db1573507eb..164eb552da45 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -1,20 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA Bridge Framework Driver * * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. * Copyright (C) 2017 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ #include #include diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 0a5181db3e2b..151ac364be80 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA Manager Core * @@ -6,18 +7,6 @@ * * With code from the mailing list: * Copyright (C) 2013 Xilinx, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ #include #include diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index b3ba3e40c44b..0878f62dd1fc 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -1,22 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA Region - Device Tree support for FPGA programming under Linux * * Copyright (C) 2013-2016 Altera Corporation * Copyright (C) 2017 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ - #include #include #include diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index 9d681a1c5738..35fabb8083fb 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -1,22 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA Region - Device Tree support for FPGA programming under Linux * * Copyright (C) 2013-2016 Altera Corporation * Copyright (C) 2017 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ - #include #include #include diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c index dec3db5cdab1..be30c48eb6e4 100644 --- a/drivers/fpga/socfpga-a10.c +++ b/drivers/fpga/socfpga-a10.c @@ -1,21 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA Manager Driver for Altera Arria10 SoCFPGA * * Copyright (C) 2015-2016 Altera Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ - #include #include #include diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index 51efaf9e0e03..959d71f26896 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FPGA Manager Driver for Altera SOCFPGA * * Copyright (C) 2013-2015 Altera Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . */ #include #include -- cgit v1.2.3 From ff9da89c22379fc1b2d45cfc4430fa9168189080 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:49:59 -0500 Subject: fpga: mgr: kernel-doc fixes Clean up the kernel-doc documentation in fpga-mgr.c and fix the following warnings when documentation is built: ./drivers/fpga/fpga-mgr.c:252: warning: Function parameter or member 'info' not described in 'fpga_mgr_buf_load' ./drivers/fpga/fpga-mgr.c:252: warning: Excess function parameter 'flags' description in 'fpga_mgr_buf_load' Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-mgr.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 151ac364be80..5fffeeffed5f 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -21,6 +21,12 @@ static DEFINE_IDA(fpga_mgr_ida); static struct class *fpga_mgr_class; +/** + * fpga_image_info_alloc - Allocate a FPGA image info struct + * @dev: owning device + * + * Return: struct fpga_image_info or NULL + */ struct fpga_image_info *fpga_image_info_alloc(struct device *dev) { struct fpga_image_info *info; @@ -39,6 +45,10 @@ struct fpga_image_info *fpga_image_info_alloc(struct device *dev) } EXPORT_SYMBOL_GPL(fpga_image_info_alloc); +/** + * fpga_image_info_free - Free a FPGA image info struct + * @info: FPGA image info struct to free + */ void fpga_image_info_free(struct fpga_image_info *info) { struct device *dev; @@ -223,7 +233,7 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, /** * fpga_mgr_buf_load - load fpga from image in buffer * @mgr: fpga manager - * @flags: flags setting fpga confuration modes + * @info: fpga image info * @buf: buffer contain fpga image * @count: byte count of buf * @@ -332,6 +342,16 @@ static int fpga_mgr_firmware_load(struct fpga_manager *mgr, return ret; } +/** + * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware + * @mgr: fpga manager + * @info: fpga image information. + * + * Load the FPGA from an image which is indicated in @info. If successful, the + * FPGA ends up in operating mode. + * + * Return: 0 on success, negative error code otherwise. + */ int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) { if (info->sgt) @@ -418,11 +438,9 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) } /** - * fpga_mgr_get - get a reference to a fpga mgr + * fpga_mgr_get - Given a device, get a reference to a fpga mgr. * @dev: parent device that fpga mgr was registered with * - * Given a device, get a reference to a fpga mgr. - * * Return: fpga manager struct or IS_ERR() condition containing error code. */ struct fpga_manager *fpga_mgr_get(struct device *dev) @@ -442,10 +460,9 @@ static int fpga_mgr_of_node_match(struct device *dev, const void *data) } /** - * of_fpga_mgr_get - get a reference to a fpga mgr - * @node: device node + * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr. * - * Given a device node, get a reference to a fpga mgr. + * @node: device node * * Return: fpga manager struct or IS_ERR() condition containing error code. */ @@ -478,7 +495,10 @@ EXPORT_SYMBOL_GPL(fpga_mgr_put); * @mgr: fpga manager * * Given a pointer to FPGA Manager (from fpga_mgr_get() or - * of_fpga_mgr_put()) attempt to get the mutex. + * of_fpga_mgr_put()) attempt to get the mutex. The user should call + * fpga_mgr_lock() and verify that it returns 0 before attempting to + * program the FPGA. Likewise, the user should call fpga_mgr_unlock + * when done programming the FPGA. * * Return: 0 for success or -EBUSY */ @@ -494,7 +514,7 @@ int fpga_mgr_lock(struct fpga_manager *mgr) EXPORT_SYMBOL_GPL(fpga_mgr_lock); /** - * fpga_mgr_unlock - Unlock FPGA manager + * fpga_mgr_unlock - Unlock FPGA manager after done programming * @mgr: fpga manager */ void fpga_mgr_unlock(struct fpga_manager *mgr) -- cgit v1.2.3 From 060ac5c8fa7bae6a7a63953ecb48f6a42257ae64 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:50:00 -0500 Subject: fpga: bridge: kernel-doc fixes Fix the following warnings when documentation is built: ./drivers/fpga/fpga-bridge.c:143: warning: Function parameter or member 'info' not described in 'fpga_bridge_get' ./drivers/fpga/fpga-bridge.c:1: warning: no structured comments found Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-bridge.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/fpga') diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 164eb552da45..4b207a75b696 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -121,6 +121,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data) /** * fpga_bridge_get - get an exclusive reference to a fpga bridge * @dev: parent device that fpga bridge was registered with + * @info: fpga manager info * * Given a device, get an exclusive reference to a fpga bridge. * -- cgit v1.2.3 From 917a4304fe48c12d346f038c7d64da3f51bce53a Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:50:01 -0500 Subject: fpga: region: kernel-doc fixes Fix formatting and some cleanup for the kernel-doc documentation in fpga-region.c Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 0878f62dd1fc..112fa3a0f977 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -81,13 +81,16 @@ static void fpga_region_put(struct fpga_region *region) /** * fpga_region_program_fpga - program FPGA + * * @region: FPGA region + * * Program an FPGA using fpga image info (region->info). * If the region has a get_bridges function, the exclusive reference for the * bridges will be held if programming succeeds. This is intended to prevent * reprogramming the region until the caller considers it safe to do so. * The caller will need to call fpga_bridges_put() before attempting to * reprogram the region. + * * Return 0 for success or negative error code. */ int fpga_region_program_fpga(struct fpga_region *region) @@ -216,7 +219,7 @@ void fpga_region_free(struct fpga_region *region) } EXPORT_SYMBOL_GPL(fpga_region_free); -/* +/** * fpga_region_register - register a FPGA region * @region: FPGA region created by fpga_region_create * Return: 0 or -errno @@ -228,7 +231,7 @@ int fpga_region_register(struct fpga_region *region) } EXPORT_SYMBOL_GPL(fpga_region_register); -/* +/** * fpga_region_unregister - unregister a FPGA region * @region: FPGA region */ -- cgit v1.2.3 From fdff4053d51be4850185aa895813405decd6e956 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 16 May 2018 18:50:06 -0500 Subject: fpga: clarify that unregister functions also free The following functions also free the struct. Add that fact to the function documentation. - fpga_mgr_free - fpga_bridge_free - fpga_region_free Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-bridge.c | 2 +- drivers/fpga/fpga-mgr.c | 2 +- drivers/fpga/fpga-region.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 4b207a75b696..24b8f98b73ec 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -412,7 +412,7 @@ int fpga_bridge_register(struct fpga_bridge *bridge) EXPORT_SYMBOL_GPL(fpga_bridge_register); /** - * fpga_bridge_unregister - unregister a fpga bridge driver + * fpga_bridge_unregister - unregister and free a fpga bridge * @bridge: FPGA bridge struct created by fpga_bridge_create */ void fpga_bridge_unregister(struct fpga_bridge *bridge) diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 5fffeeffed5f..c1564cf827fe 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -633,7 +633,7 @@ error_device: EXPORT_SYMBOL_GPL(fpga_mgr_register); /** - * fpga_mgr_unregister - unregister a FPGA manager + * fpga_mgr_unregister - unregister and free a FPGA manager * @mgr: fpga manager struct */ void fpga_mgr_unregister(struct fpga_manager *mgr) diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 112fa3a0f977..6d214d75c7be 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -232,7 +232,7 @@ int fpga_region_register(struct fpga_region *region) EXPORT_SYMBOL_GPL(fpga_region_register); /** - * fpga_region_unregister - unregister a FPGA region + * fpga_region_unregister - unregister and free a FPGA region * @region: FPGA region */ void fpga_region_unregister(struct fpga_region *region) -- cgit v1.2.3