Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
Hi Alan, On Thu, Oct 22, 2015 at 10:56 AM, atull wrote: > On Fri, 16 Oct 2015, Moritz Fischer wrote: > > Hi Moritz, > > I just noticed a problem regarding private data. Fortunately > it is easy to fix. See below... > >> +static int zynq_fpga_probe(struct platform_device *pdev) >> +{ >> + struct device *dev = >dev; >> + struct zynq_fpga_priv *priv; >> + struct resource *res; >> + int err; >> + >> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); >> + if (!priv) >> + return -ENOMEM; >> + >> + platform_set_drvdata(pdev, priv); > > fpga-mgr.c uses drvdata for its struct fpga_manager, so this will > get overwritten. So remove this platform_set_drvdata(). priv > is saved in struct fpga_manager during fpga_mgr_register(). Ouch, I missed that. > > ... > >> +static int zynq_fpga_remove(struct platform_device *pdev) >> +{ > > Here you can get a pointer to priv from the fpga_manager struct: > struct fpga_manager *mgr = platform_get_drvdata(pdev); > struct zynq_fpga_priv *priv = mgr->priv; Thanks, will submit a follow up patch. >> + struct zynq_fpga_priv *priv; >> + >> + fpga_mgr_unregister(>dev); >> + >> + priv = platform_get_drvdata(pdev); >> + >> + clk_disable_unprepare(priv->clk); >> + >> + return 0; >> +}> > Alan > Cheers, Moritz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
On Fri, 16 Oct 2015, Moritz Fischer wrote: Hi Moritz, I just noticed a problem regarding private data. Fortunately it is easy to fix. See below... > +static int zynq_fpga_probe(struct platform_device *pdev) > +{ > + struct device *dev = >dev; > + struct zynq_fpga_priv *priv; > + struct resource *res; > + int err; > + > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, priv); fpga-mgr.c uses drvdata for its struct fpga_manager, so this will get overwritten. So remove this platform_set_drvdata(). priv is saved in struct fpga_manager during fpga_mgr_register(). ... > +static int zynq_fpga_remove(struct platform_device *pdev) > +{ Here you can get a pointer to priv from the fpga_manager struct: struct fpga_manager *mgr = platform_get_drvdata(pdev); struct zynq_fpga_priv *priv = mgr->priv; Alan > + struct zynq_fpga_priv *priv; > + > + fpga_mgr_unregister(>dev); > + > + priv = platform_get_drvdata(pdev); > + > + clk_disable_unprepare(priv->clk); > + > + return 0; > +} -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
On Fri, 16 Oct 2015, Moritz Fischer wrote: Hi Moritz, I just noticed a problem regarding private data. Fortunately it is easy to fix. See below... > +static int zynq_fpga_probe(struct platform_device *pdev) > +{ > + struct device *dev = >dev; > + struct zynq_fpga_priv *priv; > + struct resource *res; > + int err; > + > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, priv); fpga-mgr.c uses drvdata for its struct fpga_manager, so this will get overwritten. So remove this platform_set_drvdata(). priv is saved in struct fpga_manager during fpga_mgr_register(). ... > +static int zynq_fpga_remove(struct platform_device *pdev) > +{ Here you can get a pointer to priv from the fpga_manager struct: struct fpga_manager *mgr = platform_get_drvdata(pdev); struct zynq_fpga_priv *priv = mgr->priv; Alan > + struct zynq_fpga_priv *priv; > + > + fpga_mgr_unregister(>dev); > + > + priv = platform_get_drvdata(pdev); > + > + clk_disable_unprepare(priv->clk); > + > + return 0; > +} -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
Hi Alan, On Thu, Oct 22, 2015 at 10:56 AM, atullwrote: > On Fri, 16 Oct 2015, Moritz Fischer wrote: > > Hi Moritz, > > I just noticed a problem regarding private data. Fortunately > it is easy to fix. See below... > >> +static int zynq_fpga_probe(struct platform_device *pdev) >> +{ >> + struct device *dev = >dev; >> + struct zynq_fpga_priv *priv; >> + struct resource *res; >> + int err; >> + >> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); >> + if (!priv) >> + return -ENOMEM; >> + >> + platform_set_drvdata(pdev, priv); > > fpga-mgr.c uses drvdata for its struct fpga_manager, so this will > get overwritten. So remove this platform_set_drvdata(). priv > is saved in struct fpga_manager during fpga_mgr_register(). Ouch, I missed that. > > ... > >> +static int zynq_fpga_remove(struct platform_device *pdev) >> +{ > > Here you can get a pointer to priv from the fpga_manager struct: > struct fpga_manager *mgr = platform_get_drvdata(pdev); > struct zynq_fpga_priv *priv = mgr->priv; Thanks, will submit a follow up patch. >> + struct zynq_fpga_priv *priv; >> + >> + fpga_mgr_unregister(>dev); >> + >> + priv = platform_get_drvdata(pdev); >> + >> + clk_disable_unprepare(priv->clk); >> + >> + return 0; >> +}> > Alan > Cheers, Moritz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
On Sun, Oct 18, 2015 at 11:02 AM, Josh Cartwright wrote: > Hey Moritz- > > On Fri, Oct 16, 2015 at 03:42:30PM -0700, Moritz Fischer wrote: >> This commit adds FPGA Manager support for the Xilinx Zynq chip. >> The code borrows some from the xdevcfg driver in Xilinx' >> vendor tree. >> >> Signed-off-by: Moritz Fischer >> --- >> >> v2: >> - Replaced locking error flag and broken completion with irq masking >>and changed completion handling >> - Dealing with timeout cases >> - Reworked clock handling >> - Moved initialization from probe() to write_init() >> - Fixed return value of devm_request_irq() check to check for non-zero >> - Alphabetized includes ;-) >> - Changed some of the comments, to better explain what's happening > [..] >> +static int zynq_fpga_probe(struct platform_device *pdev) >> +{ > [..] >> + priv->clk = devm_clk_get(dev, "ref_clk"); >> + if (IS_ERR(priv->clk)) { >> + dev_err(dev, "input clock not found"); >> + return PTR_ERR(priv->clk); >> + } >> + >> + err = clk_prepare_enable(priv->clk); >> + if (err) { >> + dev_err(dev, "unable to enable clock"); >> + return err; >> + } > > prepare_cnt = 1, enable_cnt = 1 > >> + >> + /* unlock the device */ >> + zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK); >> + >> + clk_disable(priv->clk); > > prepare_cnt = 1, enable_cnt = 0 >> + >> + err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", >> + _fpga_ops, priv); >> + if (err) { >> + dev_err(dev, "unable to register FPGA manager"); >> + clk_disable_unprepare(priv->clk); > > prepare_cnt = 0, enable_cnt = -1 /* OOPS! */ > > Clock management is still wonky. I think you only want clk_unprepare here. > >> + return err; >> + } >> + > > Assuming all goes well, you'll be leaving probe() with: > > prepare_cnt = 1, enable_cnt = 0. > >> + return 0; >> +} >> + >> +static int zynq_fpga_remove(struct platform_device *pdev) >> +{ >> + struct zynq_fpga_priv *priv; >> + >> + fpga_mgr_unregister(>dev); >> + >> + priv = platform_get_drvdata(pdev); >> + >> + clk_disable_unprepare(priv->clk); > > Which means, symmetrically, you'll only want this to be a clk_unprepare(). > > Josh Greg had already queued the v2 this weekend (which caught me by suprise). I tried to figure out if it's possible to send a v3, but he said to send follow up patches as he can't rebase the branch he merged it into. I will have access to hardware this afternoon, and send out follow up patches to fix the unbalanced clock handling. Cheers, Moritz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
On Sun, Oct 18, 2015 at 11:02 AM, Josh Cartwrightwrote: > Hey Moritz- > > On Fri, Oct 16, 2015 at 03:42:30PM -0700, Moritz Fischer wrote: >> This commit adds FPGA Manager support for the Xilinx Zynq chip. >> The code borrows some from the xdevcfg driver in Xilinx' >> vendor tree. >> >> Signed-off-by: Moritz Fischer >> --- >> >> v2: >> - Replaced locking error flag and broken completion with irq masking >>and changed completion handling >> - Dealing with timeout cases >> - Reworked clock handling >> - Moved initialization from probe() to write_init() >> - Fixed return value of devm_request_irq() check to check for non-zero >> - Alphabetized includes ;-) >> - Changed some of the comments, to better explain what's happening > [..] >> +static int zynq_fpga_probe(struct platform_device *pdev) >> +{ > [..] >> + priv->clk = devm_clk_get(dev, "ref_clk"); >> + if (IS_ERR(priv->clk)) { >> + dev_err(dev, "input clock not found"); >> + return PTR_ERR(priv->clk); >> + } >> + >> + err = clk_prepare_enable(priv->clk); >> + if (err) { >> + dev_err(dev, "unable to enable clock"); >> + return err; >> + } > > prepare_cnt = 1, enable_cnt = 1 > >> + >> + /* unlock the device */ >> + zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK); >> + >> + clk_disable(priv->clk); > > prepare_cnt = 1, enable_cnt = 0 >> + >> + err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", >> + _fpga_ops, priv); >> + if (err) { >> + dev_err(dev, "unable to register FPGA manager"); >> + clk_disable_unprepare(priv->clk); > > prepare_cnt = 0, enable_cnt = -1 /* OOPS! */ > > Clock management is still wonky. I think you only want clk_unprepare here. > >> + return err; >> + } >> + > > Assuming all goes well, you'll be leaving probe() with: > > prepare_cnt = 1, enable_cnt = 0. > >> + return 0; >> +} >> + >> +static int zynq_fpga_remove(struct platform_device *pdev) >> +{ >> + struct zynq_fpga_priv *priv; >> + >> + fpga_mgr_unregister(>dev); >> + >> + priv = platform_get_drvdata(pdev); >> + >> + clk_disable_unprepare(priv->clk); > > Which means, symmetrically, you'll only want this to be a clk_unprepare(). > > Josh Greg had already queued the v2 this weekend (which caught me by suprise). I tried to figure out if it's possible to send a v3, but he said to send follow up patches as he can't rebase the branch he merged it into. I will have access to hardware this afternoon, and send out follow up patches to fix the unbalanced clock handling. Cheers, Moritz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
Hey Moritz- On Fri, Oct 16, 2015 at 03:42:30PM -0700, Moritz Fischer wrote: > This commit adds FPGA Manager support for the Xilinx Zynq chip. > The code borrows some from the xdevcfg driver in Xilinx' > vendor tree. > > Signed-off-by: Moritz Fischer > --- > > v2: > - Replaced locking error flag and broken completion with irq masking >and changed completion handling > - Dealing with timeout cases > - Reworked clock handling > - Moved initialization from probe() to write_init() > - Fixed return value of devm_request_irq() check to check for non-zero > - Alphabetized includes ;-) > - Changed some of the comments, to better explain what's happening [..] > +static int zynq_fpga_probe(struct platform_device *pdev) > +{ [..] > + priv->clk = devm_clk_get(dev, "ref_clk"); > + if (IS_ERR(priv->clk)) { > + dev_err(dev, "input clock not found"); > + return PTR_ERR(priv->clk); > + } > + > + err = clk_prepare_enable(priv->clk); > + if (err) { > + dev_err(dev, "unable to enable clock"); > + return err; > + } prepare_cnt = 1, enable_cnt = 1 > + > + /* unlock the device */ > + zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK); > + > + clk_disable(priv->clk); prepare_cnt = 1, enable_cnt = 0 > + > + err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", > + _fpga_ops, priv); > + if (err) { > + dev_err(dev, "unable to register FPGA manager"); > + clk_disable_unprepare(priv->clk); prepare_cnt = 0, enable_cnt = -1 /* OOPS! */ Clock management is still wonky. I think you only want clk_unprepare here. > + return err; > + } > + Assuming all goes well, you'll be leaving probe() with: prepare_cnt = 1, enable_cnt = 0. > + return 0; > +} > + > +static int zynq_fpga_remove(struct platform_device *pdev) > +{ > + struct zynq_fpga_priv *priv; > + > + fpga_mgr_unregister(>dev); > + > + priv = platform_get_drvdata(pdev); > + > + clk_disable_unprepare(priv->clk); Which means, symmetrically, you'll only want this to be a clk_unprepare(). Josh -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
Hey Moritz- On Fri, Oct 16, 2015 at 03:42:30PM -0700, Moritz Fischer wrote: > This commit adds FPGA Manager support for the Xilinx Zynq chip. > The code borrows some from the xdevcfg driver in Xilinx' > vendor tree. > > Signed-off-by: Moritz Fischer> --- > > v2: > - Replaced locking error flag and broken completion with irq masking >and changed completion handling > - Dealing with timeout cases > - Reworked clock handling > - Moved initialization from probe() to write_init() > - Fixed return value of devm_request_irq() check to check for non-zero > - Alphabetized includes ;-) > - Changed some of the comments, to better explain what's happening [..] > +static int zynq_fpga_probe(struct platform_device *pdev) > +{ [..] > + priv->clk = devm_clk_get(dev, "ref_clk"); > + if (IS_ERR(priv->clk)) { > + dev_err(dev, "input clock not found"); > + return PTR_ERR(priv->clk); > + } > + > + err = clk_prepare_enable(priv->clk); > + if (err) { > + dev_err(dev, "unable to enable clock"); > + return err; > + } prepare_cnt = 1, enable_cnt = 1 > + > + /* unlock the device */ > + zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK); > + > + clk_disable(priv->clk); prepare_cnt = 1, enable_cnt = 0 > + > + err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", > + _fpga_ops, priv); > + if (err) { > + dev_err(dev, "unable to register FPGA manager"); > + clk_disable_unprepare(priv->clk); prepare_cnt = 0, enable_cnt = -1 /* OOPS! */ Clock management is still wonky. I think you only want clk_unprepare here. > + return err; > + } > + Assuming all goes well, you'll be leaving probe() with: prepare_cnt = 1, enable_cnt = 0. > + return 0; > +} > + > +static int zynq_fpga_remove(struct platform_device *pdev) > +{ > + struct zynq_fpga_priv *priv; > + > + fpga_mgr_unregister(>dev); > + > + priv = platform_get_drvdata(pdev); > + > + clk_disable_unprepare(priv->clk); Which means, symmetrically, you'll only want this to be a clk_unprepare(). Josh -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
This commit adds FPGA Manager support for the Xilinx Zynq chip. The code borrows some from the xdevcfg driver in Xilinx' vendor tree. Signed-off-by: Moritz Fischer --- v2: - Replaced locking error flag and broken completion with irq masking and changed completion handling - Dealing with timeout cases - Reworked clock handling - Moved initialization from probe() to write_init() - Fixed return value of devm_request_irq() check to check for non-zero - Alphabetized includes ;-) - Changed some of the comments, to better explain what's happening --- drivers/fpga/Kconfig | 5 + drivers/fpga/Makefile| 1 + drivers/fpga/zynq-fpga.c | 533 +++ 3 files changed, 539 insertions(+) create mode 100644 drivers/fpga/zynq-fpga.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index dfc1f1e..c9b9fdf 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -19,6 +19,11 @@ config FPGA_MGR_SOCFPGA help FPGA manager driver support for Altera SOCFPGA. +config FPGA_MGR_ZYNQ_FPGA + tristate "Xilinx Zynq FPGA" + help + FPGA manager driver support for Xilinx Zynq FPGAs. + endif # FPGA endmenu diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index ba6c5c5..8d83fc6 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o +obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c new file mode 100644 index 000..103303c --- /dev/null +++ b/drivers/fpga/zynq-fpga.c @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2011-2015 Xilinx Inc. + * Copyright (c) 2015, National Instruments Corp. + * + * FPGA Manager Driver for Xilinx Zynq, heavily based on xdevcfg driver + * in their vendor tree. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Offsets into SLCR regmap */ + +/* FPGA Software Reset Control */ +#define SLCR_FPGA_RST_CTRL_OFFSET 0x240 +/* Level Shifters Enable */ +#define SLCR_LVL_SHFTR_EN_OFFSET 0x900 + +/* Constant Definitions */ + +/* Control Register */ +#define CTRL_OFFSET0x00 +/* Lock Register */ +#define LOCK_OFFSET0x04 +/* Interrupt Status Register */ +#define INT_STS_OFFSET 0x0c +/* Interrupt Mask Register */ +#define INT_MASK_OFFSET0x10 +/* Status Register */ +#define STATUS_OFFSET 0x14 +/* DMA Source Address Register */ +#define DMA_SRC_ADDR_OFFSET0x18 +/* DMA Destination Address Reg */ +#define DMA_DST_ADDR_OFFSET0x1c +/* DMA Source Transfer Length */ +#define DMA_SRC_LEN_OFFSET 0x20 +/* DMA Destination Transfer */ +#define DMA_DEST_LEN_OFFSET0x24 +/* Unlock Register */ +#define UNLOCK_OFFSET 0x34 +/* Misc. Control Register */ +#define MCTRL_OFFSET 0x80 + +/* Control Register Bit definitions */ + +/* Signal to reset FPGA */ +#define CTRL_PCFG_PROG_B_MASK BIT(30) +/* Enable PCAP for PR */ +#define CTRL_PCAP_PR_MASK BIT(27) +/* Enable PCAP */ +#define CTRL_PCAP_MODE_MASKBIT(26) + +/* Miscellaneous Control Register bit definitions */ +/* Internal PCAP loopback */ +#define MCTRL_PCAP_LPBK_MASK BIT(4) + +/* Status register bit definitions */ + +/* FPGA init status */ +#define STATUS_DMA_Q_F BIT(31) +#define STATUS_PCFG_INIT_MASK BIT(4) + +/* Interrupt Status/Mask Register Bit definitions */ +/* DMA command done */ +#define IXR_DMA_DONE_MASK BIT(13) +/* DMA and PCAP cmd done */ +#define IXR_D_P_DONE_MASK BIT(12) + /* FPGA programmed */ +#define IXR_PCFG_DONE_MASK BIT(2) +#define IXR_ERROR_FLAGS_MASK 0x00F0F860 +#define IXR_ALL_MASK 0xF8F7F87F + +/* Miscellaneous constant values */ + +/* Invalid DMA addr */ +#define DMA_INVALID_ADDRESSGENMASK(31, 0) +/* Used to unlock the dev */ +#define UNLOCK_MASK0x757bdf0d +/* Timeout for DMA to complete */ +#define DMA_DONE_TIMEOUT msecs_to_jiffies(1000) +/* Timeout for polling reset bits */ +#define INIT_POLL_TIMEOUT 250 +/* Delay for polling reset bits */ +#define INIT_POLL_DELAY
[PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000
This commit adds FPGA Manager support for the Xilinx Zynq chip. The code borrows some from the xdevcfg driver in Xilinx' vendor tree. Signed-off-by: Moritz Fischer--- v2: - Replaced locking error flag and broken completion with irq masking and changed completion handling - Dealing with timeout cases - Reworked clock handling - Moved initialization from probe() to write_init() - Fixed return value of devm_request_irq() check to check for non-zero - Alphabetized includes ;-) - Changed some of the comments, to better explain what's happening --- drivers/fpga/Kconfig | 5 + drivers/fpga/Makefile| 1 + drivers/fpga/zynq-fpga.c | 533 +++ 3 files changed, 539 insertions(+) create mode 100644 drivers/fpga/zynq-fpga.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index dfc1f1e..c9b9fdf 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -19,6 +19,11 @@ config FPGA_MGR_SOCFPGA help FPGA manager driver support for Altera SOCFPGA. +config FPGA_MGR_ZYNQ_FPGA + tristate "Xilinx Zynq FPGA" + help + FPGA manager driver support for Xilinx Zynq FPGAs. + endif # FPGA endmenu diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index ba6c5c5..8d83fc6 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o +obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c new file mode 100644 index 000..103303c --- /dev/null +++ b/drivers/fpga/zynq-fpga.c @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2011-2015 Xilinx Inc. + * Copyright (c) 2015, National Instruments Corp. + * + * FPGA Manager Driver for Xilinx Zynq, heavily based on xdevcfg driver + * in their vendor tree. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Offsets into SLCR regmap */ + +/* FPGA Software Reset Control */ +#define SLCR_FPGA_RST_CTRL_OFFSET 0x240 +/* Level Shifters Enable */ +#define SLCR_LVL_SHFTR_EN_OFFSET 0x900 + +/* Constant Definitions */ + +/* Control Register */ +#define CTRL_OFFSET0x00 +/* Lock Register */ +#define LOCK_OFFSET0x04 +/* Interrupt Status Register */ +#define INT_STS_OFFSET 0x0c +/* Interrupt Mask Register */ +#define INT_MASK_OFFSET0x10 +/* Status Register */ +#define STATUS_OFFSET 0x14 +/* DMA Source Address Register */ +#define DMA_SRC_ADDR_OFFSET0x18 +/* DMA Destination Address Reg */ +#define DMA_DST_ADDR_OFFSET0x1c +/* DMA Source Transfer Length */ +#define DMA_SRC_LEN_OFFSET 0x20 +/* DMA Destination Transfer */ +#define DMA_DEST_LEN_OFFSET0x24 +/* Unlock Register */ +#define UNLOCK_OFFSET 0x34 +/* Misc. Control Register */ +#define MCTRL_OFFSET 0x80 + +/* Control Register Bit definitions */ + +/* Signal to reset FPGA */ +#define CTRL_PCFG_PROG_B_MASK BIT(30) +/* Enable PCAP for PR */ +#define CTRL_PCAP_PR_MASK BIT(27) +/* Enable PCAP */ +#define CTRL_PCAP_MODE_MASKBIT(26) + +/* Miscellaneous Control Register bit definitions */ +/* Internal PCAP loopback */ +#define MCTRL_PCAP_LPBK_MASK BIT(4) + +/* Status register bit definitions */ + +/* FPGA init status */ +#define STATUS_DMA_Q_F BIT(31) +#define STATUS_PCFG_INIT_MASK BIT(4) + +/* Interrupt Status/Mask Register Bit definitions */ +/* DMA command done */ +#define IXR_DMA_DONE_MASK BIT(13) +/* DMA and PCAP cmd done */ +#define IXR_D_P_DONE_MASK BIT(12) + /* FPGA programmed */ +#define IXR_PCFG_DONE_MASK BIT(2) +#define IXR_ERROR_FLAGS_MASK 0x00F0F860 +#define IXR_ALL_MASK 0xF8F7F87F + +/* Miscellaneous constant values */ + +/* Invalid DMA addr */ +#define DMA_INVALID_ADDRESSGENMASK(31, 0) +/* Used to unlock the dev */ +#define UNLOCK_MASK0x757bdf0d +/* Timeout for DMA to complete */ +#define DMA_DONE_TIMEOUT msecs_to_jiffies(1000) +/* Timeout for polling reset bits */ +#define INIT_POLL_TIMEOUT 250 +/* Delay for polling reset bits */