Re: [PATCHv2 3/3] fpga manager: Adding FPGA Manager support for Xilinx Zynq 7000

2015-10-22 Thread Moritz Fischer
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

2015-10-22 Thread atull
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

2015-10-22 Thread atull
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

2015-10-22 Thread Moritz Fischer
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

2015-10-19 Thread Moritz Fischer
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

2015-10-19 Thread Moritz Fischer
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

2015-10-18 Thread Josh Cartwright
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

2015-10-18 Thread Josh Cartwright
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

2015-10-16 Thread Moritz Fischer
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

2015-10-16 Thread Moritz Fischer
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 */