Commit d7ea31ca authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'fpga-late-for-5.13' of...

Merge tag 'fpga-late-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga into char-misc-next

Moritz writes:

Second set of FPGA Manager changes for 5.13-rc1

FPGA Manager:
- Russ' first change improves port_enable reliability
- Russ' second change adds a new device ID for a DFL device
- Geert's change updates the examples in binding with dt overlay sugar
  syntax

All patches have been reviewed on the mailing list, and have been in the
last linux-next releases (as part of my for-next branch) without issues.
Signed-off-by: default avatarMoritz Fischer <mdf@kernel.org>

* tag 'fpga-late-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga:
  fpga: dfl: pci: add DID for D5005 PAC cards
  dt-bindings: fpga: fpga-region: Convert to sugar syntax
  fpga: dfl: afu: harden port enable logic
  fpga: Add support for Xilinx DFX AXI Shutdown manager
  dt-bindings: fpga: Add compatible value for Xilinx DFX AXI shutdown manager
  fpga: xilinx-pr-decoupler: Simplify code by using dev_err_probe()
  fpga: fpga-mgr: xilinx-spi: fix error messages on -EPROBE_DEFER
parents e76e8b56 a78a51a8
...@@ -245,36 +245,31 @@ Base tree contains: ...@@ -245,36 +245,31 @@ Base tree contains:
Overlay contains: Overlay contains:
/dts-v1/ /plugin/; /dts-v1/;
/ { /plugin/;
fragment@0 {
target = <&fpga_region0>; &fpga_region0 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
__overlay__ {
#address-cells = <1>; firmware-name = "soc_system.rbf";
#size-cells = <1>; fpga-bridges = <&fpga_bridge1>;
ranges = <0x20000 0xff200000 0x100000>,
firmware-name = "soc_system.rbf"; <0x0 0xc0000000 0x20000000>;
fpga-bridges = <&fpga_bridge1>;
ranges = <0x20000 0xff200000 0x100000>, gpio@10040 {
<0x0 0xc0000000 0x20000000>; compatible = "altr,pio-1.0";
reg = <0x10040 0x20>;
gpio@10040 { altr,ngpio = <4>;
compatible = "altr,pio-1.0"; #gpio-cells = <2>;
reg = <0x10040 0x20>; clocks = <2>;
altr,ngpio = <4>; gpio-controller;
#gpio-cells = <2>; };
clocks = <2>;
gpio-controller; onchip-memory {
}; device_type = "memory";
compatible = "altr,onchipmem-15.1";
onchip-memory { reg = <0x0 0x10000>;
device_type = "memory";
compatible = "altr,onchipmem-15.1";
reg = <0x0 0x10000>;
};
};
}; };
}; };
...@@ -371,25 +366,22 @@ Live Device Tree contains: ...@@ -371,25 +366,22 @@ Live Device Tree contains:
}; };
DT Overlay contains: DT Overlay contains:
/dts-v1/ /plugin/;
/ { /dts-v1/;
fragment@0 { /plugin/;
target = <&fpga_region0>;
&fpga_region0 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <1>;
firmware-name = "zynq-gpio.bin"; firmware-name = "zynq-gpio.bin";
gpio1: gpio@40000000 { gpio1: gpio@40000000 {
compatible = "xlnx,xps-gpio-1.00.a"; compatible = "xlnx,xps-gpio-1.00.a";
reg = <0x40000000 0x10000>; reg = <0x40000000 0x10000>;
gpio-controller; gpio-controller;
#gpio-cells = <0x2>; #gpio-cells = <0x2>;
xlnx,gpio-width= <0x6>; xlnx,gpio-width= <0x6>;
};
}; };
}; };
...@@ -402,41 +394,37 @@ This example programs the FPGA to have two regions that can later be partially ...@@ -402,41 +394,37 @@ This example programs the FPGA to have two regions that can later be partially
configured. Each region has its own bridge in the FPGA fabric. configured. Each region has its own bridge in the FPGA fabric.
DT Overlay contains: DT Overlay contains:
/dts-v1/ /plugin/;
/ { /dts-v1/;
fragment@0 { /plugin/;
target = <&fpga_region0>;
#address-cells = <1>; &fpga_region0 {
#size-cells = <1>; #address-cells = <1>;
__overlay__ { #size-cells = <1>;
#address-cells = <1>;
#size-cells = <1>; firmware-name = "base.rbf";
firmware-name = "base.rbf"; fpga-bridge@4400 {
compatible = "altr,freeze-bridge-controller";
fpga-bridge@4400 { reg = <0x4400 0x10>;
compatible = "altr,freeze-bridge-controller";
reg = <0x4400 0x10>; fpga_region1: fpga-region1 {
compatible = "fpga-region";
fpga_region1: fpga-region1 { #address-cells = <0x1>;
compatible = "fpga-region"; #size-cells = <0x1>;
#address-cells = <0x1>; ranges;
#size-cells = <0x1>; };
ranges; };
};
}; fpga-bridge@4420 {
compatible = "altr,freeze-bridge-controller";
fpga-bridge@4420 { reg = <0x4420 0x10>;
compatible = "altr,freeze-bridge-controller";
reg = <0x4420 0x10>; fpga_region2: fpga-region2 {
compatible = "fpga-region";
fpga_region2: fpga-region2 { #address-cells = <0x1>;
compatible = "fpga-region"; #size-cells = <0x1>;
#address-cells = <0x1>; ranges;
#size-cells = <0x1>;
ranges;
};
};
}; };
}; };
}; };
...@@ -451,28 +439,23 @@ differences are that the FPGA is partially reconfigured due to the ...@@ -451,28 +439,23 @@ differences are that the FPGA is partially reconfigured due to the
"partial-fpga-config" boolean and the only bridge that is controlled during "partial-fpga-config" boolean and the only bridge that is controlled during
programming is the FPGA based bridge of fpga_region1. programming is the FPGA based bridge of fpga_region1.
/dts-v1/ /plugin/; /dts-v1/;
/ { /plugin/;
fragment@0 {
target = <&fpga_region1>; &fpga_region1 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
__overlay__ {
#address-cells = <1>; firmware-name = "soc_image2.rbf";
#size-cells = <1>; partial-fpga-config;
firmware-name = "soc_image2.rbf"; gpio@10040 {
partial-fpga-config; compatible = "altr,pio-1.0";
reg = <0x10040 0x20>;
gpio@10040 { clocks = <0x2>;
compatible = "altr,pio-1.0"; altr,ngpio = <0x4>;
reg = <0x10040 0x20>; #gpio-cells = <0x2>;
clocks = <0x2>; gpio-controller;
altr,ngpio = <0x4>;
#gpio-cells = <0x2>;
gpio-controller;
};
};
}; };
}; };
......
...@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err) ...@@ -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 dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr; void __iomem *base_err, *base_hdr;
int ret = -EBUSY; int enable_ret = 0, ret = -EBUSY;
u64 v; u64 v;
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR); 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) ...@@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
v = readq(base_err + PORT_FIRST_ERROR); v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR); writeq(v, base_err + PORT_FIRST_ERROR);
} else { } else {
dev_warn(dev, "%s: received 0x%llx, expected 0x%llx\n",
__func__, v, err);
ret = -EINVAL; ret = -EINVAL;
} }
/* Clear mask */ /* Clear mask */
__afu_port_err_mask(dev, false); __afu_port_err_mask(dev, false);
/* Enable the Port by clear the reset */ /* Enable the Port by clearing the reset */
__afu_port_enable(pdev); enable_ret = __afu_port_enable(pdev);
done: done:
mutex_unlock(&pdata->lock); mutex_unlock(&pdata->lock);
return ret; return enable_ret ? enable_ret : ret;
} }
static ssize_t errors_show(struct device *dev, struct device_attribute *attr, static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
#include "dfl-afu.h" #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 * __afu_port_enable - enable a port by clear reset
* @pdev: port platform device. * @pdev: port platform device.
...@@ -32,7 +35,7 @@ ...@@ -32,7 +35,7 @@
* *
* The caller needs to hold lock for protection. * 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); struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
void __iomem *base; void __iomem *base;
...@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev) ...@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count); WARN_ON(!pdata->disable_count);
if (--pdata->disable_count != 0) if (--pdata->disable_count != 0)
return; return 0;
base = dfl_get_feature_ioaddr_by_id(&pdev->dev, PORT_FEATURE_ID_HEADER); 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) ...@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL); v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST; v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL); 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 * __afu_port_disable - disable a port by hold reset
...@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev) ...@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v, if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
v & PORT_CTRL_SFTRST_ACK, v & PORT_CTRL_SFTRST_ACK,
RST_POLL_INVL, RST_POLL_TIMEOUT)) { 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; return -ETIMEDOUT;
} }
...@@ -110,10 +123,10 @@ static int __port_reset(struct platform_device *pdev) ...@@ -110,10 +123,10 @@ static int __port_reset(struct platform_device *pdev)
int ret; int ret;
ret = __afu_port_disable(pdev); ret = __afu_port_disable(pdev);
if (!ret) if (ret)
__afu_port_enable(pdev); return ret;
return ret; return __afu_port_enable(pdev);
} }
static int port_reset(struct platform_device *pdev) static int port_reset(struct platform_device *pdev)
...@@ -872,11 +885,11 @@ static int afu_dev_destroy(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) static int port_enable_set(struct platform_device *pdev, bool enable)
{ {
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
int ret = 0; int ret;
mutex_lock(&pdata->lock); mutex_lock(&pdata->lock);
if (enable) if (enable)
__afu_port_enable(pdev); ret = __afu_port_enable(pdev);
else else
ret = __afu_port_disable(pdev); ret = __afu_port_disable(pdev);
mutex_unlock(&pdata->lock); mutex_unlock(&pdata->lock);
......
...@@ -80,7 +80,7 @@ struct dfl_afu { ...@@ -80,7 +80,7 @@ struct dfl_afu {
}; };
/* hold pdata->lock when call __afu_port_enable/disable */ /* 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); int __afu_port_disable(struct platform_device *pdev);
void afu_mmio_region_init(struct dfl_feature_platform_data *pdata); void afu_mmio_region_init(struct dfl_feature_platform_data *pdata);
......
...@@ -69,14 +69,16 @@ static void cci_pci_free_irq(struct pci_dev *pcidev) ...@@ -69,14 +69,16 @@ static void cci_pci_free_irq(struct pci_dev *pcidev)
} }
/* PCI Device ID */ /* PCI Device ID */
#define PCIE_DEVICE_ID_PF_INT_5_X 0xBCBD #define PCIE_DEVICE_ID_PF_INT_5_X 0xBCBD
#define PCIE_DEVICE_ID_PF_INT_6_X 0xBCC0 #define PCIE_DEVICE_ID_PF_INT_6_X 0xBCC0
#define PCIE_DEVICE_ID_PF_DSC_1_X 0x09C4 #define PCIE_DEVICE_ID_PF_DSC_1_X 0x09C4
#define PCIE_DEVICE_ID_INTEL_PAC_N3000 0x0B30 #define PCIE_DEVICE_ID_INTEL_PAC_N3000 0x0B30
#define PCIE_DEVICE_ID_INTEL_PAC_D5005 0x0B2B
/* VF Device */ /* VF Device */
#define PCIE_DEVICE_ID_VF_INT_5_X 0xBCBF #define PCIE_DEVICE_ID_VF_INT_5_X 0xBCBF
#define PCIE_DEVICE_ID_VF_INT_6_X 0xBCC1 #define PCIE_DEVICE_ID_VF_INT_6_X 0xBCC1
#define PCIE_DEVICE_ID_VF_DSC_1_X 0x09C5 #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[] = { static struct pci_device_id cci_pcie_id_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_5_X),}, {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[] = { ...@@ -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_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_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_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,} {0,}
}; };
MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl); MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment