From 484a58607a808c3721917f5ca5fba7eff809e4df Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 4 Feb 2021 13:13:13 +0100 Subject: fpga: fpga-mgr: xilinx-spi: fix error messages on -EPROBE_DEFER The current code produces an error message on devm_gpiod_get() errors even when the error is -EPROBE_DEFER, which should be silent. This has been observed producing a significant amount of messages like: xlnx-slave-spi spi1.1: Failed to get PROGRAM_B gpio: -517 Fix and simplify code by using the dev_err_probe() helper function. Signed-off-by: Luca Ceresoli Fixes: dd2784c01d93 ("fpga manager: xilinx-spi: check INIT_B pin during write_init") Fixes: 061c97d13f1a ("fpga manager: Add Xilinx slave serial SPI driver") Signed-off-by: Moritz Fischer --- drivers/fpga/xilinx-spi.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c index 27defa98092d..fee4d0abf6bf 100644 --- a/drivers/fpga/xilinx-spi.c +++ b/drivers/fpga/xilinx-spi.c @@ -233,25 +233,19 @@ static int xilinx_spi_probe(struct spi_device *spi) /* PROGRAM_B is active low */ conf->prog_b = devm_gpiod_get(&spi->dev, "prog_b", GPIOD_OUT_LOW); - if (IS_ERR(conf->prog_b)) { - dev_err(&spi->dev, "Failed to get PROGRAM_B gpio: %ld\n", - PTR_ERR(conf->prog_b)); - return PTR_ERR(conf->prog_b); - } + if (IS_ERR(conf->prog_b)) + return dev_err_probe(&spi->dev, PTR_ERR(conf->prog_b), + "Failed to get PROGRAM_B gpio\n"); conf->init_b = devm_gpiod_get_optional(&spi->dev, "init-b", GPIOD_IN); - if (IS_ERR(conf->init_b)) { - dev_err(&spi->dev, "Failed to get INIT_B gpio: %ld\n", - PTR_ERR(conf->init_b)); - return PTR_ERR(conf->init_b); - } + if (IS_ERR(conf->init_b)) + return dev_err_probe(&spi->dev, PTR_ERR(conf->init_b), + "Failed to get INIT_B gpio\n"); conf->done = devm_gpiod_get(&spi->dev, "done", GPIOD_IN); - if (IS_ERR(conf->done)) { - dev_err(&spi->dev, "Failed to get DONE gpio: %ld\n", - PTR_ERR(conf->done)); - return PTR_ERR(conf->done); - } + if (IS_ERR(conf->done)) + return dev_err_probe(&spi->dev, PTR_ERR(conf->done), + "Failed to get DONE gpio\n"); mgr = devm_fpga_mgr_create(&spi->dev, "Xilinx Slave Serial FPGA Manager", -- cgit From 2d6e820c4e9e7a6d681a413cca6c7dc53b420c97 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 4 Feb 2021 14:36:11 +0100 Subject: fpga: xilinx-pr-decoupler: Simplify code by using dev_err_probe() Use already prepared dev_err_probe() introduced by commit a787e5400a1c ("driver core: add device probe log helper"). It simplifies EPROBE_DEFER handling. Signed-off-by: Michal Simek Signed-off-by: Moritz Fischer --- drivers/fpga/xilinx-pr-decoupler.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c index 7d69af230567..b0eaf26af6e7 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c @@ -100,11 +100,9 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) return PTR_ERR(priv->io_base); priv->clk = devm_clk_get(&pdev->dev, "aclk"); - if (IS_ERR(priv->clk)) { - if (PTR_ERR(priv->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "input clock not found\n"); - return PTR_ERR(priv->clk); - } + if (IS_ERR(priv->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), + "input clock not found\n"); err = clk_prepare_enable(priv->clk); if (err) { -- cgit From 6f1e376cfc6864a2f46538db909bbd5253c3c146 Mon Sep 17 00:00:00 2001 From: Nava kishore Manne Date: Thu, 11 Feb 2021 10:41:48 +0530 Subject: fpga: Add support for Xilinx DFX AXI Shutdown manager This patch adds support for Xilinx Dynamic Function eXchange(DFX) AXI shutdown manager IP. It can be used to safely handling the AXI traffic on a Reconfigurable Partition when it is undergoing dynamic reconfiguration and there by preventing system deadlock that may occur if AXI transactions are interrupted during reconfiguration. PR-Decoupler and AXI shutdown manager are completely different IPs. But both the IP registers are compatible and also both belong to the same sub-system (fpga-bridge).So using same driver for both IP's. Signed-off-by: Nava kishore Manne Reviewed-by: Tom Rix Signed-off-by: Moritz Fischer --- drivers/fpga/Kconfig | 9 ++++++++- drivers/fpga/xilinx-pr-decoupler.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 6 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 5ff9438b7b46..d591dd9b7c60 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -118,10 +118,17 @@ config XILINX_PR_DECOUPLER depends on FPGA_BRIDGE depends on HAS_IOMEM help - Say Y to enable drivers for Xilinx LogiCORE PR Decoupler. + Say Y to enable drivers for Xilinx LogiCORE PR Decoupler + or Xilinx Dynamic Function eXchnage AIX Shutdown Manager. The PR Decoupler exists in the FPGA fabric to isolate one region of the FPGA from the busses while that region is being reprogrammed during partial reconfig. + The Dynamic Function eXchange AXI shutdown manager prevents + AXI traffic from passing through the bridge. The controller + safely handles AXI4MM and AXI4-Lite interfaces on a + Reconfigurable Partition when it is undergoing dynamic + reconfiguration, preventing the system deadlock that can + occur if AXI transactions are interrupted by DFX. config FPGA_REGION tristate "FPGA Region" diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c index b0eaf26af6e7..ea2bde6e5bc4 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017, National Instruments Corp. - * Copyright (c) 2017, Xilix Inc + * Copyright (c) 2017, Xilinx Inc * * FPGA Bridge Driver for the Xilinx LogiCORE Partial Reconfiguration * Decoupler IP Core. @@ -18,7 +18,12 @@ #define CTRL_CMD_COUPLE 0 #define CTRL_OFFSET 0 +struct xlnx_config_data { + const char *name; +}; + struct xlnx_pr_decoupler_data { + const struct xlnx_config_data *ipconfig; void __iomem *io_base; struct clk *clk; }; @@ -76,15 +81,28 @@ static const struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = { .enable_show = xlnx_pr_decoupler_enable_show, }; +static const struct xlnx_config_data decoupler_config = { + .name = "Xilinx PR Decoupler", +}; + +static const struct xlnx_config_data shutdown_config = { + .name = "Xilinx DFX AXI Shutdown Manager", +}; + static const struct of_device_id xlnx_pr_decoupler_of_match[] = { - { .compatible = "xlnx,pr-decoupler-1.00", }, - { .compatible = "xlnx,pr-decoupler", }, + { .compatible = "xlnx,pr-decoupler-1.00", .data = &decoupler_config }, + { .compatible = "xlnx,pr-decoupler", .data = &decoupler_config }, + { .compatible = "xlnx,dfx-axi-shutdown-manager-1.00", + .data = &shutdown_config }, + { .compatible = "xlnx,dfx-axi-shutdown-manager", + .data = &shutdown_config }, {}, }; MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match); static int xlnx_pr_decoupler_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct xlnx_pr_decoupler_data *priv; struct fpga_bridge *br; int err; @@ -94,6 +112,14 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + if (np) { + const struct of_device_id *match; + + match = of_match_node(xlnx_pr_decoupler_of_match, np); + if (match && match->data) + priv->ipconfig = match->data; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->io_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->io_base)) @@ -112,7 +138,7 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) clk_disable(priv->clk); - br = devm_fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler", + br = devm_fpga_bridge_create(&pdev->dev, priv->ipconfig->name, &xlnx_pr_decoupler_br_ops, priv); if (!br) { err = -ENOMEM; @@ -123,7 +149,8 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) err = fpga_bridge_register(br); if (err) { - dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler"); + dev_err(&pdev->dev, "unable to register %s", + priv->ipconfig->name); goto err_clk; } -- cgit From 4a9a1a5602d82c079325bf37466af0b67d6c0b9e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 11 Mar 2021 16:25:38 +0100 Subject: arm64: socfpga: merge Agilex and N5X into ARCH_INTEL_SOCFPGA Agilex, N5X and Stratix 10 share all quite similar arm64 hard cores and SoC-part. Up to a point that N5X uses the same DTSI as Agilex. From the Linux kernel point of view these are flavors of the same architecture so there is no need for three top-level arm64 architectures. Simplify this by merging all three architectures into ARCH_INTEL_SOCFPGA and dropping the other ARCH* arm64 Kconfig entries. The side effect is that the INTEL_STRATIX10_SERVICE will now be available for both 32-bit and 64-bit Intel SoCFPGA, even though it is used only for 64-bit. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Dinh Nguyen --- drivers/fpga/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 5ff9438b7b46..fd325e9c5ce6 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -60,7 +60,7 @@ config FPGA_MGR_ZYNQ_FPGA config FPGA_MGR_STRATIX10_SOC tristate "Intel Stratix10 SoC FPGA Manager" - depends on (ARCH_STRATIX10 && INTEL_STRATIX10_SERVICE) + depends on (ARCH_INTEL_SOCFPGA && INTEL_STRATIX10_SERVICE) help FPGA manager driver support for the Intel Stratix10 SoC. -- cgit From 3a1fef70ff875ec58dca7002e219943afd7d240c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 11 Mar 2021 16:27:35 +0100 Subject: fpga: altera: use ARCH_INTEL_SOCFPGA also for 32-bit ARM SoCs ARCH_SOCFPGA is being renamed to ARCH_INTEL_SOCFPGA so adjust the 32-bit ARM drivers to rely on new symbol. Acked-by: Moritz Fischer Signed-off-by: Krzysztof Kozlowski Signed-off-by: Dinh Nguyen --- drivers/fpga/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index fd325e9c5ce6..b1026c6fb119 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -14,13 +14,13 @@ if FPGA config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" - depends on ARCH_SOCFPGA || COMPILE_TEST + depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST help FPGA manager driver support for Altera SOCFPGA. config FPGA_MGR_SOCFPGA_A10 tristate "Altera SoCFPGA Arria10" - depends on ARCH_SOCFPGA || COMPILE_TEST + depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST select REGMAP_MMIO help FPGA manager driver support for Altera Arria10 SoCFPGA. @@ -99,7 +99,7 @@ config FPGA_BRIDGE config SOCFPGA_FPGA_BRIDGE tristate "Altera SoCFPGA FPGA Bridges" - depends on ARCH_SOCFPGA && FPGA_BRIDGE + depends on ARCH_INTEL_SOCFPGA && FPGA_BRIDGE help Say Y to enable drivers for FPGA bridges for Altera SOCFPGA devices. -- cgit From 9a8d3cda8daf54b1f8e67ccb360876379b7e7895 Mon Sep 17 00:00:00 2001 From: Russ Weight Date: Tue, 23 Mar 2021 15:46:50 -0700 Subject: fpga: dfl: afu: harden port enable logic Port enable is not complete until ACK = 0. Change __afu_port_enable() to guarantee that the enable process is complete by polling for ACK == 0. Signed-off-by: Russ Weight Reviewed-by: Tom Rix Reviewed-by: Matthew Gerlach Acked-by: Wu Hao Signed-off-by: Moritz Fischer --- drivers/fpga/dfl-afu-error.c | 10 ++++++---- drivers/fpga/dfl-afu-main.c | 35 ++++++++++++++++++++++++----------- drivers/fpga/dfl-afu.h | 2 +- 3 files changed, 31 insertions(+), 16 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c index c4691187cca9..ab7be6217368 100644 --- a/drivers/fpga/dfl-afu-error.c +++ b/drivers/fpga/dfl-afu-error.c @@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err) struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); struct platform_device *pdev = to_platform_device(dev); void __iomem *base_err, *base_hdr; - int ret = -EBUSY; + int enable_ret = 0, ret = -EBUSY; u64 v; base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR); @@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err) v = readq(base_err + PORT_FIRST_ERROR); writeq(v, base_err + PORT_FIRST_ERROR); } else { + dev_warn(dev, "%s: received 0x%llx, expected 0x%llx\n", + __func__, v, err); ret = -EINVAL; } /* Clear mask */ __afu_port_err_mask(dev, false); - /* Enable the Port by clear the reset */ - __afu_port_enable(pdev); + /* Enable the Port by clearing the reset */ + enable_ret = __afu_port_enable(pdev); done: mutex_unlock(&pdata->lock); - return ret; + return enable_ret ? enable_ret : ret; } static ssize_t errors_show(struct device *dev, struct device_attribute *attr, diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c index 753cda4b2568..7f621e96d3b8 100644 --- a/drivers/fpga/dfl-afu-main.c +++ b/drivers/fpga/dfl-afu-main.c @@ -21,6 +21,9 @@ #include "dfl-afu.h" +#define RST_POLL_INVL 10 /* us */ +#define RST_POLL_TIMEOUT 1000 /* us */ + /** * __afu_port_enable - enable a port by clear reset * @pdev: port platform device. @@ -32,7 +35,7 @@ * * The caller needs to hold lock for protection. */ -void __afu_port_enable(struct platform_device *pdev) +int __afu_port_enable(struct platform_device *pdev) { struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); void __iomem *base; @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev) WARN_ON(!pdata->disable_count); if (--pdata->disable_count != 0) - return; + return 0; base = dfl_get_feature_ioaddr_by_id(&pdev->dev, PORT_FEATURE_ID_HEADER); @@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev) v = readq(base + PORT_HDR_CTRL); v &= ~PORT_CTRL_SFTRST; writeq(v, base + PORT_HDR_CTRL); -} -#define RST_POLL_INVL 10 /* us */ -#define RST_POLL_TIMEOUT 1000 /* us */ + /* + * HW clears the ack bit to indicate that the port is fully out + * of reset. + */ + if (readq_poll_timeout(base + PORT_HDR_CTRL, v, + !(v & PORT_CTRL_SFTRST_ACK), + RST_POLL_INVL, RST_POLL_TIMEOUT)) { + dev_err(&pdev->dev, "timeout, failure to enable device\n"); + return -ETIMEDOUT; + } + + return 0; +} /** * __afu_port_disable - disable a port by hold reset @@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev) if (readq_poll_timeout(base + PORT_HDR_CTRL, v, v & PORT_CTRL_SFTRST_ACK, RST_POLL_INVL, RST_POLL_TIMEOUT)) { - dev_err(&pdev->dev, "timeout, fail to reset device\n"); + dev_err(&pdev->dev, "timeout, failure to disable device\n"); return -ETIMEDOUT; } @@ -110,10 +123,10 @@ static int __port_reset(struct platform_device *pdev) int ret; ret = __afu_port_disable(pdev); - if (!ret) - __afu_port_enable(pdev); + if (ret) + return ret; - return ret; + return __afu_port_enable(pdev); } static int port_reset(struct platform_device *pdev) @@ -872,11 +885,11 @@ static int afu_dev_destroy(struct platform_device *pdev) static int port_enable_set(struct platform_device *pdev, bool enable) { struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); - int ret = 0; + int ret; mutex_lock(&pdata->lock); if (enable) - __afu_port_enable(pdev); + ret = __afu_port_enable(pdev); else ret = __afu_port_disable(pdev); mutex_unlock(&pdata->lock); diff --git a/drivers/fpga/dfl-afu.h b/drivers/fpga/dfl-afu.h index 576e94960086..e5020e2b1f3d 100644 --- a/drivers/fpga/dfl-afu.h +++ b/drivers/fpga/dfl-afu.h @@ -80,7 +80,7 @@ struct dfl_afu { }; /* hold pdata->lock when call __afu_port_enable/disable */ -void __afu_port_enable(struct platform_device *pdev); +int __afu_port_enable(struct platform_device *pdev); int __afu_port_disable(struct platform_device *pdev); void afu_mmio_region_init(struct dfl_feature_platform_data *pdata); -- cgit From a78a51a851ed3edc83264a67e2ba77a34f27965f Mon Sep 17 00:00:00 2001 From: Russ Weight Date: Mon, 5 Apr 2021 16:52:59 -0700 Subject: fpga: dfl: pci: add DID for D5005 PAC cards This patch adds the approved PCI Express Device IDs for the PF and VF for the card for D5005 PAC cards. Signed-off-by: Russ Weight Signed-off-by: Matthew Gerlach Signed-off-by: Moritz Fischer --- drivers/fpga/dfl-pci.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/fpga') diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c index 04e47e266f26..b44523ea8c91 100644 --- a/drivers/fpga/dfl-pci.c +++ b/drivers/fpga/dfl-pci.c @@ -69,14 +69,16 @@ static void cci_pci_free_irq(struct pci_dev *pcidev) } /* PCI Device ID */ -#define PCIE_DEVICE_ID_PF_INT_5_X 0xBCBD -#define PCIE_DEVICE_ID_PF_INT_6_X 0xBCC0 -#define PCIE_DEVICE_ID_PF_DSC_1_X 0x09C4 -#define PCIE_DEVICE_ID_INTEL_PAC_N3000 0x0B30 +#define PCIE_DEVICE_ID_PF_INT_5_X 0xBCBD +#define PCIE_DEVICE_ID_PF_INT_6_X 0xBCC0 +#define PCIE_DEVICE_ID_PF_DSC_1_X 0x09C4 +#define PCIE_DEVICE_ID_INTEL_PAC_N3000 0x0B30 +#define PCIE_DEVICE_ID_INTEL_PAC_D5005 0x0B2B /* VF Device */ -#define PCIE_DEVICE_ID_VF_INT_5_X 0xBCBF -#define PCIE_DEVICE_ID_VF_INT_6_X 0xBCC1 -#define PCIE_DEVICE_ID_VF_DSC_1_X 0x09C5 +#define PCIE_DEVICE_ID_VF_INT_5_X 0xBCBF +#define PCIE_DEVICE_ID_VF_INT_6_X 0xBCC1 +#define PCIE_DEVICE_ID_VF_DSC_1_X 0x09C5 +#define PCIE_DEVICE_ID_INTEL_PAC_D5005_VF 0x0B2C static struct pci_device_id cci_pcie_id_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_5_X),}, @@ -86,6 +88,8 @@ static struct pci_device_id cci_pcie_id_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_DSC_1_X),}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_DSC_1_X),}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_N3000),}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005),}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005_VF),}, {0,} }; MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl); -- cgit