Commit 30a2ac9a authored by Nava kishore Manne's avatar Nava kishore Manne Committed by Greg Kroah-Hartman

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: default avatarNava kishore Manne <nava.manne@xilinx.com>
Reviewed-by: default avatarTom Rix <trix@redhat.com>
Signed-off-by: default avatarMoritz Fischer <mdf@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8058182f
...@@ -118,10 +118,17 @@ config XILINX_PR_DECOUPLER ...@@ -118,10 +118,17 @@ config XILINX_PR_DECOUPLER
depends on FPGA_BRIDGE depends on FPGA_BRIDGE
depends on HAS_IOMEM depends on HAS_IOMEM
help 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 The PR Decoupler exists in the FPGA fabric to isolate one
region of the FPGA from the busses while that region is region of the FPGA from the busses while that region is
being reprogrammed during partial reconfig. 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 config FPGA_REGION
tristate "FPGA Region" tristate "FPGA Region"
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2017, National Instruments Corp. * 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 * FPGA Bridge Driver for the Xilinx LogiCORE Partial Reconfiguration
* Decoupler IP Core. * Decoupler IP Core.
...@@ -18,7 +18,12 @@ ...@@ -18,7 +18,12 @@
#define CTRL_CMD_COUPLE 0 #define CTRL_CMD_COUPLE 0
#define CTRL_OFFSET 0 #define CTRL_OFFSET 0
struct xlnx_config_data {
const char *name;
};
struct xlnx_pr_decoupler_data { struct xlnx_pr_decoupler_data {
const struct xlnx_config_data *ipconfig;
void __iomem *io_base; void __iomem *io_base;
struct clk *clk; struct clk *clk;
}; };
...@@ -76,15 +81,28 @@ static const struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = { ...@@ -76,15 +81,28 @@ static const struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = {
.enable_show = xlnx_pr_decoupler_enable_show, .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[] = { static const struct of_device_id xlnx_pr_decoupler_of_match[] = {
{ .compatible = "xlnx,pr-decoupler-1.00", }, { .compatible = "xlnx,pr-decoupler-1.00", .data = &decoupler_config },
{ .compatible = "xlnx,pr-decoupler", }, { .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); MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match);
static int xlnx_pr_decoupler_probe(struct platform_device *pdev) 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 xlnx_pr_decoupler_data *priv;
struct fpga_bridge *br; struct fpga_bridge *br;
int err; int err;
...@@ -94,6 +112,14 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) ...@@ -94,6 +112,14 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; 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); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io_base = devm_ioremap_resource(&pdev->dev, res); priv->io_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->io_base)) if (IS_ERR(priv->io_base))
...@@ -112,7 +138,7 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) ...@@ -112,7 +138,7 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
clk_disable(priv->clk); 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); &xlnx_pr_decoupler_br_ops, priv);
if (!br) { if (!br) {
err = -ENOMEM; err = -ENOMEM;
...@@ -123,7 +149,8 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) ...@@ -123,7 +149,8 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
err = fpga_bridge_register(br); err = fpga_bridge_register(br);
if (err) { 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; goto err_clk;
} }
......
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