RE: [PATCH v3 1/4] edac: synps: Add platform specific structures for ddrc controller

2018-08-03 Thread Manish Narani
Hi Boris,


> -Original Message-
> From: Borislav Petkov [mailto:b...@alien8.de]
> Sent: Saturday, August 4, 2018 10:49 AM
> Subject: Re: [PATCH v3 1/4] edac: synps: Add platform specific structures for
> ddrc controller
> 
> On Thu, Aug 02, 2018 at 06:21:19PM +0530, Manish Narani wrote:
> > This patch adds platform specific structures, so that we can add
> 
> "This patch" in a commit message is tautologically redundant.
Okay. I will update this in v4.

> 
> > different IP support later using quirks.
> >
> > Signed-off-by: Manish Narani 
> > ---
> >  drivers/edac/synopsys_edac.c | 64
> > 
> >  1 file changed, 53 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/edac/synopsys_edac.c
> > b/drivers/edac/synopsys_edac.c index 0c9c59e..d4798e8 100644
> > --- a/drivers/edac/synopsys_edac.c
> > +++ b/drivers/edac/synopsys_edac.c
> > @@ -22,6 +22,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include "edac_module.h"
> >
> > @@ -130,6 +131,7 @@ struct synps_ecc_status {
> >   * @baseaddr:  Base address of the DDR controller
> >   * @message:   Buffer for framing the event specific info
> >   * @stat:  ECC status information
> > + * @p_data:Pointer to platform data
> >   * @ce_cnt:Correctable Error count
> >   * @ue_cnt:Uncorrectable Error count
> >   */
> > @@ -137,11 +139,29 @@ struct synps_edac_priv {
> > void __iomem *baseaddr;
> > char message[SYNPS_EDAC_MSG_SIZE];
> > struct synps_ecc_status stat;
> > +   const struct synps_platform_data *p_data;
> > u32 ce_cnt;
> > u32 ue_cnt;
> >  };
> >
> >  /**
> > + * struct synps_platform_data -  synps platform data structure
> > + * @synps_edac_geterror_info:  function pointer to synps edac error
> info
> > + * @synps_edac_get_mtype:  function pointer to synps edac mtype
> > + * @synps_edac_get_dtype:  function pointer to synps edac dtype
> > + * @synps_edac_get_eccstate:   function pointer to synps edac eccstate
> > + * @quirks:to differentiate IPs
> > + */
> > +struct synps_platform_data {
> > +   int (*synps_edac_geterror_info)(void __iomem *base,
> > +   struct synps_ecc_status *p);
> > +   enum mem_type (*synps_edac_get_mtype)(const void __iomem
> *base);
> > +   enum dev_type (*synps_edac_get_dtype)(const void __iomem *base);
> > +   bool (*synps_edac_get_eccstate)(void __iomem *base);
> > +   int quirks;
> > +};
> > +
> > +/**
> >   * synps_edac_geterror_info - Get the current ecc error info
> >   * @base:  Pointer to the base address of the ddr memory controller
> >   * @p: Pointer to the synopsys ecc status structure
> > @@ -242,7 +262,8 @@ static void synps_edac_check(struct mem_ctl_info
> *mci)
> > struct synps_edac_priv *priv = mci->pvt_info;
> > int status;
> >
> > -   status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
> > +   status = priv->p_data->synps_edac_geterror_info(priv->baseaddr,
> > +   &priv->stat);
> 
> Unnecessarily long line - shortening by renaming might help.
Fair One. I will look to change the name. Also, May be I could use only 'priv' 
as argument and extract/use 'baseaddr' and 'stat' in the function definition 
itself.

> 
> > @@ -372,10 +393,12 @@ static int synps_edac_init_csrows(struct
> mem_ctl_info *mci)
> > for (j = 0; j < csi->nr_channels; j++) {
> > dimm= csi->channels[j]->dimm;
> > dimm->edac_mode = EDAC_FLAG_SECDED;
> > -   dimm->mtype = synps_edac_get_mtype(priv-
> >baseaddr);
> > +   dimm->mtype = priv->p_data-
> >synps_edac_get_mtype(
> > +   priv->baseaddr);
> 
> Ditto - that trailing opening brace at the end is just yucky. Shorten it and 
> let is
> stick out even if it longer than 80 cols.
Okay. Will modify it.

> 
> >
> > +static const struct synps_platform_data zynq_edac_def = {
> > +   .synps_edac_geterror_info   = synps_edac_geterror_info,
> > +   .synps_edac_get_mtype   = synps_edac_get_mtype,
> > +   .synps_edac_get_dtype   = synps_edac_get_dtype,
> > +   .synps_edac_get_eccstate= synps_edac_get_eccstate,
> > +   .quirks = 0,
> 
> Drop the "synps_" prefix from the function pointer names and leave them in
> the actual function names so that when one looks at the code, knows what is
> what.
Okay. I will correct it in v4.

Thanks,
Manish Narani


[PATCH v4 1/4] edac: synps: Add platform specific structures for ddrc controller

2018-08-04 Thread Manish Narani
Add platform specific structures, so that we can add different IP
support later using quirks.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 83 ++--
 1 file changed, 65 insertions(+), 18 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0c9c59e..b3c54e7 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "edac_module.h"
 
@@ -130,6 +131,7 @@ struct synps_ecc_status {
  * @baseaddr:  Base address of the DDR controller
  * @message:   Buffer for framing the event specific info
  * @stat:  ECC status information
+ * @p_data:Pointer to platform data
  * @ce_cnt:Correctable Error count
  * @ue_cnt:Uncorrectable Error count
  */
@@ -137,24 +139,47 @@ struct synps_edac_priv {
void __iomem *baseaddr;
char message[SYNPS_EDAC_MSG_SIZE];
struct synps_ecc_status stat;
+   const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
 };
 
 /**
+ * struct synps_platform_data -  synps platform data structure
+ * @edac_geterror_info:function pointer to synps edac error info
+ * @edac_get_mtype:function pointer to synps edac mtype
+ * @edac_get_dtype:function pointer to synps edac dtype
+ * @edac_get_eccstate: function pointer to synps edac eccstate
+ * @quirks:to differentiate IPs
+ */
+struct synps_platform_data {
+   int (*edac_geterror_info)(struct synps_edac_priv *priv);
+   enum mem_type (*edac_get_mtype)(const void __iomem *base);
+   enum dev_type (*edac_get_dtype)(const void __iomem *base);
+   bool (*edac_get_eccstate)(void __iomem *base);
+   int quirks;
+};
+
+/**
  * synps_edac_geterror_info - Get the current ecc error info
- * @base:  Pointer to the base address of the ddr memory controller
- * @p: Pointer to the synopsys ecc status structure
+ * @priv:  Pointer to DDR memory controller private instance data
  *
  * Determines there is any ecc error or not
  *
  * Return: one if there is no error otherwise returns zero
  */
-static int synps_edac_geterror_info(void __iomem *base,
-   struct synps_ecc_status *p)
+static int synps_edac_geterror_info(struct synps_edac_priv *priv)
 {
+   void __iomem *base;
+   struct synps_ecc_status *p;
u32 regval, clearval = 0;
 
+   if (!priv)
+   return 1;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
+
regval = readl(base + STAT_OFST);
if (!regval)
return 1;
@@ -240,9 +265,10 @@ static void synps_edac_handle_error(struct mem_ctl_info 
*mci,
 static void synps_edac_check(struct mem_ctl_info *mci)
 {
struct synps_edac_priv *priv = mci->pvt_info;
+   const struct synps_platform_data *p_data = priv->p_data;
int status;
 
-   status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = p_data->edac_geterror_info(priv);
if (status)
return;
 
@@ -362,6 +388,7 @@ static int synps_edac_init_csrows(struct mem_ctl_info *mci)
struct csrow_info *csi;
struct dimm_info *dimm;
struct synps_edac_priv *priv = mci->pvt_info;
+   const struct synps_platform_data *p_data = priv->p_data;
u32 size;
int row, j;
 
@@ -370,12 +397,13 @@ static int synps_edac_init_csrows(struct mem_ctl_info 
*mci)
size = synps_edac_get_memsize();
 
for (j = 0; j < csi->nr_channels; j++) {
-   dimm= csi->channels[j]->dimm;
+   dimm = csi->channels[j]->dimm;
dimm->edac_mode = EDAC_FLAG_SECDED;
-   dimm->mtype = synps_edac_get_mtype(priv->baseaddr);
-   dimm->nr_pages  = (size >> PAGE_SHIFT) / 
csi->nr_channels;
-   dimm->grain = SYNPS_EDAC_ERR_GRAIN;
-   dimm->dtype = synps_edac_get_dtype(priv->baseaddr);
+   dimm->mtype = p_data->edac_get_mtype(priv->baseaddr);
+   dimm->nr_pages = (size >> PAGE_SHIFT) /
+   csi->nr_channels;
+   dimm->grain = SYNPS_EDAC_ERR_GRAIN;
+   dimm->dtype = p_data->edac_get_dtype(priv->baseaddr);
}
}
 
@@ -423,6 +451,21 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci,
return status;
 }
 
+static const struct synps_platform_data zynq_edac_def = {
+   .edac_geterror_info = synps_edac_geterror_info,
+   .edac_get_mtype = synps_edac_get_mtype,
+   .edac_get_dtype = synps_edac_get_dtype,
+   .edac_get_eccstate  = synps_edac_get_eccst

[PATCH v4 2/4] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-08-04 Thread Manish Narani
This patch adds information of ZynqMP DDRC which reports the single bit
errors that are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v4 3/4] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-08-04 Thread Manish Narani
Add EDAC ECC support for ZynqMP DDRC IP. Also add support for ECC Error
Injection in ZynqMP. The corrected and uncorrected error interrupts
support is added. The Row, Column, Bank, Bank Group and Rank bits
positions are determined via Address Map registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 864 ++-
 2 files changed, 848 insertions(+), 18 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..b1fc7a16 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARM64
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index b3c54e7..82f276b 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "edac_module.h"
@@ -96,6 +97,170 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORT BIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST 0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON1_BANKGRP_SHIFT 28
+#define ECC_POISON1_BANKNR_SHIFT 24
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK 0x3
+#define ECC_UEPOISON_MASK 0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_DEV_CONFIG_MASK 0xC000
+#define DDRC_MSTR_DEV_CONFIG_SHIFT 30
+#define DDRC_MSTR_DEV_CONFIG_X4_MASK   0x0
+#define DDRC_MSTR_DEV_CONFIG_X8_MASK   0x1
+#define DDRC_MSTR_DEV_CONFIG_X16_MASK  0x2
+#define DDRC_MSTR_DEV_CONFIG_X32_MASK  0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#define ROW_MAX_VAL_MASK   0xF
+#define COL_MAX_VAL_MASK   0xF
+#define BAN

[PATCH v4 4/4] arm64: zynqmp: Add DDRC node

2018-08-04 Thread Manish Narani
This patch adds ddrc memory controller node in dts. The size mentioned
in dts is 0x3, because we need to access DDR_QOS INTR registers
located at fd090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index a091e6f..7d6a3cf 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH v4 0/4] EDAC: Enhancements to Synopsys EDAC driver

2018-08-04 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms.This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Changes in v3:
- The commit message in (2/4) is modified (Synopsys EDAC Driver -->
  ZynqMP DDRC)

Changes in v4:
- Updated the commit message in (1/4)
- Renamed function pointer names removing 'synps_' in (1/4)
- Shortened unnecessary long lines as per the review comment on (1/4)

Manish Narani (4):
  edac: synps: Add platform specific structures for ddrc controller
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node

 .../bindings/memory-controllers/synopsys.txt   |  27 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
 drivers/edac/Kconfig   |   2 +-
 drivers/edac/synopsys_edac.c   | 945 -
 4 files changed, 941 insertions(+), 40 deletions(-)

-- 
2.1.1



RE: [PATCH v4 0/4] EDAC: Enhancements to Synopsys EDAC driver

2018-08-06 Thread Manish Narani
Hi Boris,


> -Original Message-
> From: Borislav Petkov [mailto:b...@alien8.de]
> Sent: Saturday, August 4, 2018 10:03 PM
> Subject: Re: [PATCH v4 0/4] EDAC: Enhancements to Synopsys EDAC driver
> 
> On Sat, Aug 04, 2018 at 02:55:31PM +0530, Manish Narani wrote:
> > This patch series enhances the current EDAC driver to support
> > different
> 
> This one, your 2/4 and 4/4 still says "this patch". Hurried too much?
> How about slowing down and looking at them with a critical eye?
> 
> Also, how about waiting for a week before resending your patches so that you
> give people chance to review them too?
> 
> While you wait, please read Documentation/process/submitting-patches.rst
> - it'll help you with the submission modalities.

Yes, I missed it. Sorry for that. I will surely wait for around a week for 
others to review.
Thanks for the guidance.

Thanks,
Manish Narani


RE: [RFC PATCH 2/3] dt: bindings: Add SD tap value properties details

2018-06-21 Thread Manish Narani
Hi Mark,

> -Original Message-
> From: Mark Rutland [mailto:mark.rutl...@arm.com]
> Sent: Thursday, June 7, 2018 6:18 PM
> To: Manish Narani 
> Cc: robh...@kernel.org; catalin.mari...@arm.com; will.dea...@arm.com;
> m...@kernel.org; stefan.krsmano...@aggios.com; linux-arm-
> ker...@lists.infradead.org; linux-kernel@vger.kernel.org; linux-
> m...@vger.kernel.org; devicet...@vger.kernel.org; adrian.hun...@intel.com;
> michal.si...@xilinx.com; ulf.hans...@linaro.org
> Subject: Re: [RFC PATCH 2/3] dt: bindings: Add SD tap value properties details
> 
> On Thu, Jun 07, 2018 at 05:41:39PM +0530, Manish Narani wrote:
> > This patch adds details of SD tap value properties in device tree.
> >
> > Signed-off-by: Manish Narani 
> > ---
> >  .../devicetree/bindings/mmc/arasan,sdhci.txt   | 26
> ++
> >  1 file changed, 26 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> > b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> > index 60481bf..0e08877 100644
> > --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> > +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> > @@ -15,6 +15,8 @@ Required Properties:
> >  - "arasan,sdhci-5.1": generic Arasan SDHCI 5.1 PHY
> >  - "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1": rk3399 eMMC PHY
> >For this device it is strongly suggested to include 
> > arasan,soc-ctl-syscon.
> > +- "xlnx,zynqmp-8.9a": Xilinx ZynqMP Arasan SDHCI 8.9a PHY
> > +  For this device it is strongly suggested to include 
> > arasan,soc-ctl-syscon.
> >- reg: From mmc bindings: Register location and length.
> >- clocks: From clock bindings: Handles to clock inputs.
> >- clock-names: From clock bindings: Tuple including "clk_xin" and 
> > "clk_ahb"
> > @@ -26,6 +28,30 @@ Required Properties for "arasan,sdhci-5.1":
> >- phys: From PHY bindings: Phandle for the Generic PHY for arasan.
> >- phy-names:  MUST be "phy_arasan".
> >
> > +Required Properties for "xlnx,zynqmp-8.9a":
> > +  - xlnx,mio_bank: The value will be 0/1/2 depending on MIO bank selection.
> 
> For all of these properties, please s/_/-/, folowing the usual property name
> conventions.
I will correct this in the next version.
> 
> It's not clear to me why you need this property. The code in patch 3 only 
> seems
> to use this to determine which properties to read, choosing between _b0
> or _b2. I don't see why you dont have the base  alone...
The property 'xlnx,mio_bank' will be different for various ZynqMP varients. So 
different ZynqMP dts files may have different values for 'xlnx,mio_bank'. 
That's why I am maintaining _b0 and _b2 as different values
> 
> Is this a HW detail, or configuration that you prefer?
These are SD tap values which are generally used for configuring taps in SD. 
Keeping it in device tree makes it User Configurable without changing the 
driver code.
> 
> > +  - xlnx,device_id: Unique Id of the device, value will be 0/1.
> 
> What's this used for?
This used to identify the controller ID between two SD controllers present on 
ZynqMP.
> 
> > +  - xlnx,itap_delay_sd_hsd: Input Tap Delay for SD HS.
> 
> What unit at hese delays in?
The tap values don't have specific units. They are generally a fraction of the 
clock cycle.
For the SD frequency of -
200 MHz: 30 Input taps are available
100 MHz: 60 Input taps are available
50 MHz: 120 Input taps are available
200 MHz: 8 Output taps are available
100 MHz: 15 Output taps are available
50 MHz: 30 Output taps are available

Thanks,
Manish
> 
> Please follow the conventions in
> Documentation/devicetree/bindings/property-units.txt.
> 
> > +  - xlnx,itap_delay_sdr25: Input Tap Delay for SDR25.
> > +  - xlnx,itap_delay_sdr50: Input Tap Delay for SDR50.
> > +  - xlnx,itap_delay_sdr104_b0: Input Tap Delay for SDR104.
> > +  - xlnx,itap_delay_sdr104_b2: Input Tap Delay for SDR104.
> 
> As above, Given you have to specify the bank, I don't see why you need 
> multiple
> properties.
> 
> Thanks,
> Mark.
> 
> > +  - xlnx,itap_delay_sd_ddr50: Input Tap Delay for SD DDR50.
> > +  - xlnx,itap_delay_mmc_hsd: Input Tap Delay for MMC HS.
> > +  - xlnx,itap_delay_mmc_ddr50: Input Tap Delay for MMC DDR50.
> > +  - xlnx,itap_delay_mmc_hs200_b0: Input Tap Delay for MMC HS200.
> > +  - xlnx,itap_delay_mmc_hs200_b2: Input Tap Delay for MMC HS200.
> > +  - xlnx,otap_delay_sd_hsd: Output Tap Delay for SD HS.
> > +  - xlnx,otap_delay_sdr25: Output Tap 

RE: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay values from DT

2018-06-21 Thread Manish Narani
Hi Adrian,

> -Original Message-
> From: Adrian Hunter [mailto:adrian.hun...@intel.com]
> Sent: Tuesday, June 19, 2018 5:08 PM
> To: Manish Narani ; robh...@kernel.org;
> catalin.mari...@arm.com; will.dea...@arm.com; m...@kernel.org;
> stefan.krsmano...@aggios.com; linux-arm-ker...@lists.infradead.org; linux-
> ker...@vger.kernel.org; linux-...@vger.kernel.org;
> devicet...@vger.kernel.org; Michal Simek ;
> ulf.hans...@linaro.org
> Cc: Srinivas Goud ; Anirudha Sarangi
> 
> Subject: Re: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay
> values from DT
> 
> On 14/06/18 08:38, Manish Narani wrote:
> > Ping for RFC
> 
> What is eemi?  Why aren't there patches for that?
Eemi(Extensible Energy Management Interface) is a power management interface 
for ZynqMP core. The patches for the same are already in process of mainlining. 
https://lkml.org/lkml/2018/6/20/823

Thanks,
Manish
> 
> >
> >> -Original Message-
> >> From: Manish Narani [mailto:manish.nar...@xilinx.com]
> >> Sent: Thursday, June 7, 2018 5:42 PM
> >> To: robh...@kernel.org; mark.rutl...@arm.com;
> >> catalin.mari...@arm.com; will.dea...@arm.com; m...@kernel.org;
> >> stefan.krsmano...@aggios.com; linux-arm-ker...@lists.infradead.org;
> >> linux-kernel@vger.kernel.org; linux- m...@vger.kernel.org;
> >> devicet...@vger.kernel.org; adrian.hun...@intel.com;
> >> michal.si...@xilinx.com; ulf.hans...@linaro.org
> >> Cc: Manish Narani 
> >> Subject: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay
> >> values from DT
> >>
> >> This patch adds support for reading Tap Delay values from Device Tree
> >> and write them via eemi calls. The macros containing these tap delay
> >> values are removed from the driver.
> >>
> >> Signed-off-by: Manish Narani 
> >> ---
> >>  drivers/mmc/host/sdhci-of-arasan.c | 131
> >> +
> >>  1 file changed, 131 insertions(+)
> >>
> >> diff --git a/drivers/mmc/host/sdhci-of-arasan.c
> >> b/drivers/mmc/host/sdhci- of-arasan.c index e3332a5..fc0fd01 100644
> >> --- a/drivers/mmc/host/sdhci-of-arasan.c
> >> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> >> @@ -36,6 +36,8 @@
> >>
> >>  #define PHY_CLK_TOO_SLOW_HZ   40
> >>
> >> +#define MMC_BANK2 0x2
> >> +
> >>  /*
> >>   * On some SoCs the syscon area has a feature where the upper 16-bits of
> >>   * each 32-bit register act as a write mask for the lower 16-bits.
> >> This allows @@ -90,6 +92,10 @@ struct sdhci_arasan_data {
> >>struct sdhci_host *host;
> >>struct clk  *clk_ahb;
> >>struct phy  *phy;
> >> +  u32 mio_bank;
> >> +  u32 device_id;
> >> +  u32 itapdly[MMC_TIMING_MMC_HS400 + 1];
> >> +  u32 otapdly[MMC_TIMING_MMC_HS400 + 1];
> >>boolis_phy_on;
> >>
> >>boolhas_cqe;
> >> @@ -160,11 +166,36 @@ static int sdhci_arasan_syscon_write(struct
> >> sdhci_host *host,
> >>return ret;
> >>  }
> >>
> >> +/**
> >> + * arasan_zynqmp_set_tap_delay - Program the tap delays.
> >> + * @deviceid: Unique Id of device
> >> + * @itap_delay:   Input Tap Delay
> >> + * @oitap_delay:  Output Tap Delay
> >> + */
> >> +static void arasan_zynqmp_set_tap_delay(u8 deviceid, u8 itap_delay,
> >> +u8
> >> +otap_delay) {
> >> +  const struct zynqmp_eemi_ops *eemi_ops =
> >> zynqmp_pm_get_eemi_ops();
> >> +  u32 node_id = (deviceid == 0) ? NODE_SD_0 : NODE_SD_1;
> >> +
> >> +  if (!eemi_ops || !eemi_ops->ioctl)
> >> +  return;
> >> +
> >> +  if (itap_delay)
> >> +  eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
> >> +  PM_TAPDELAY_INPUT, itap_delay, NULL);
> >> +
> >> +  if (otap_delay)
> >> +  eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
> >> +  PM_TAPDELAY_OUTPUT, otap_delay, NULL);
> >> }
> >> +
> >>  static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned
> >> int
> >> clock)  {
> >>struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> >>struct sdhci_arasan_data *sdhci_arasan =
> >> sdhci_pltfm_priv(pltfm_host);
> >>bool ctrl_phy = false;
> >> +  u8 itap_delay;
> >> +  u8 otap_delay;
> >>

[PATCH 0/3] Add Xilinx AMS Driver

2018-08-30 Thread Manish Narani
Add Xilinx AMS driver which is used for Xilinx's ZynqMP AMS controller.
This AMS driver is used to report various interface voltages and
temperatures across the system.
This driver handles AMS module including PS-Sysmon & PL-Sysmon. The
binding documentation is added for understanding of AMS, PS, PL Sysmon
Channels.

Manish Narani (3):
  dt-bindings: iio: adc: Add Xilinx AMS binding documentation
  iio: adc: Add Xilinx AMS driver
  arm64: zynqmp: DT: Add Xilinx AMS node

 .../devicetree/bindings/iio/adc/xilinx-ams.txt |  159 +++
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   26 +
 drivers/iio/adc/Kconfig|   10 +
 drivers/iio/adc/Makefile   |1 +
 drivers/iio/adc/xilinx-ams.c   | 1081 
 drivers/iio/adc/xilinx-ams.h   |  281 +
 6 files changed, 1558 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/xilinx-ams.txt
 create mode 100644 drivers/iio/adc/xilinx-ams.c
 create mode 100644 drivers/iio/adc/xilinx-ams.h

-- 
2.1.1



[PATCH 3/3] arm64: zynqmp: DT: Add Xilinx AMS node

2018-08-30 Thread Manish Narani
The Xilinx AMS includes an ADC as well as on-chip sensors that can be
used to sample external and monitor on-die operating conditions, such as
temperature and supply voltage levels.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 29ce234..6e42ca2 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -617,5 +617,31 @@
reg = <0x0 0xfd4d 0x0 0x1000>;
timeout-sec = <10>;
};
+
+   xilinx_ams: ams@ffa5 {
+   compatible = "xlnx,zynqmp-ams";
+   status = "disabled";
+   interrupt-parent = <&gic>;
+   interrupts = <0 56 4>;
+   interrupt-names = "ams-irq";
+   reg = <0x0 0xffa5 0x0 0x800>;
+   reg-names = "ams-base";
+   #address-cells = <2>;
+   #size-cells = <2>;
+   #io-channel-cells = <1>;
+   ranges;
+
+   ams_ps: ams_ps@ffa50800 {
+   compatible = "xlnx,zynqmp-ams-ps";
+   status = "disabled";
+   reg = <0x0 0xffa50800 0x0 0x400>;
+   };
+
+   ams_pl: ams_pl@ffa50c00 {
+   compatible = "xlnx,zynqmp-ams-pl";
+   status = "disabled";
+   reg = <0x0 0xffa50c00 0x0 0x400>;
+   };
+   };
};
 };
-- 
2.1.1



[PATCH 2/3] iio: adc: Add Xilinx AMS driver

2018-08-30 Thread Manish Narani
The AMS includes an ADC as well as on-chip sensors that can be used to
sample external voltages and monitor on-die operating conditions, such
as temperature and supply voltage levels. The AMS has two SYSMON blocks.
PL-SYSMON block is capable of monitoring off chip voltage and
temperature.
PL-SYSMON block has DRP, JTAG and I2C interface to enable monitoring
from external master. Out of these interface currently only DRP is
supported.
Other block PS-SYSMON is memory mapped to PS.
The AMS can use internal channels to monitor voltage and temperature as
well as one primary and up to 16 auxiliary channels for measuring
external voltages.
The voltage and temperature monitoring channels also have event
capability which allows to generate an interrupt when their value falls
below or raises above a set threshold.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/Kconfig  |   10 +
 drivers/iio/adc/Makefile |1 +
 drivers/iio/adc/xilinx-ams.c | 1081 ++
 drivers/iio/adc/xilinx-ams.h |  281 +++
 4 files changed, 1373 insertions(+)
 create mode 100644 drivers/iio/adc/xilinx-ams.c
 create mode 100644 drivers/iio/adc/xilinx-ams.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 4a75492..405ea00 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -941,4 +941,14 @@ config XILINX_XADC
  The driver can also be build as a module. If so, the module will be 
called
  xilinx-xadc.
 
+config XILINX_AMS
+   tristate "Xilinx AMS driver"
+   depends on ARCH_ZYNQMP || COMPILE_TEST
+   depends on HAS_IOMEM
+   help
+ Say yes here to have support for the Xilinx AMS.
+
+ The driver can also be build as a module. If so, the module will be 
called
+ xilinx-ams.
+
 endmenu
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 03db7b5..fbfcc45 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -85,4 +85,5 @@ obj-$(CONFIG_VF610_ADC) += vf610_adc.o
 obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
 xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o
 obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o
+obj-$(CONFIG_XILINX_AMS) += xilinx-ams.o
 obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o
diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
new file mode 100644
index 000..10bcc52
--- /dev/null
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -0,0 +1,1081 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AMS driver
+ *
+ *  Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ *  Manish Narani 
+ *  Rajnikant Bhojani 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "xilinx-ams.h"
+
+static const unsigned int AMS_UNMASK_TIMEOUT_MS = 500;
+
+static inline void ams_ps_update_reg(struct ams *ams, unsigned int offset,
+u32 mask, u32 data)
+{
+   u32 val;
+
+   val = readl(ams->ps_base + offset);
+   writel((val & ~mask) | (data & mask), ams->ps_base + offset);
+}
+
+static inline void ams_pl_write_reg(struct ams *ams, unsigned int offset,
+   u32 data)
+{
+   writel(data, ams->pl_base + offset);
+}
+
+static inline void ams_pl_update_reg(struct ams *ams, unsigned int offset,
+u32 mask, u32 data)
+{
+   u32 val;
+
+   val = readl(ams->pl_base + offset);
+   writel((val & ~mask) | (data & mask), ams->pl_base + offset);
+}
+
+static void ams_update_intrmask(struct ams *ams, u64 mask, u64 val)
+{
+   ams->intr_mask &= ~mask;
+   ams->intr_mask |= (val & mask);
+
+   writel(~(ams->intr_mask | ams->masked_alarm), ams->base + AMS_IER_0);
+   writel(~(ams->intr_mask >> AMS_ISR1_INTR_MASK_SHIFT),
+   ams->base + AMS_IER_1);
+   writel(ams->intr_mask | ams->masked_alarm, ams->base + AMS_IDR_0);
+   writel(ams->intr_mask >> AMS_ISR1_INTR_MASK_SHIFT,
+   ams->base + AMS_IDR_1);
+}
+
+static void ams_disable_all_alarms(struct ams *ams)
+{
+   /* disable PS module alarm */
+   if (ams->ps_base) {
+   ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_REGCFG1_ALARM_MASK,
+ AMS_REGCFG1_ALARM_MASK);
+   ams_ps_update_reg(ams, AMS_REG_CONFIG3, AMS_REGCFG3_ALARM_MASK,
+ AMS_REGCFG3_ALARM_MASK);
+   }
+
+   /* disable PL module alarm */
+   if (ams->pl_base) {
+   ams_pl_update_reg(ams, AMS_REG_CONFIG1,
+   AMS_REGCFG1_ALARM_MASK,
+   AMS_REGCFG1_ALARM_MASK);
+   ams_pl_update_reg(ams, AMS_REG_CONFIG3,
+   AMS_REGCFG3_ALARM_MA

[PATCH 1/3] dt-bindings: iio: adc: Add Xilinx AMS binding documentation

2018-08-30 Thread Manish Narani
Xilinx AMS have several ADC channels that can be used for measurement of
different voltages and temperatures. Document the same in the bindings.

Signed-off-by: Manish Narani 
---
 .../devicetree/bindings/iio/adc/xilinx-ams.txt | 159 +
 1 file changed, 159 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/xilinx-ams.txt

diff --git a/Documentation/devicetree/bindings/iio/adc/xilinx-ams.txt 
b/Documentation/devicetree/bindings/iio/adc/xilinx-ams.txt
new file mode 100644
index 000..8cc96f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/xilinx-ams.txt
@@ -0,0 +1,159 @@
+Xilinx AMS controller
+
+The AMS includes an ADC as well as on-chip sensors that can be used to
+sample external voltages and monitor on-die operating conditions, such as
+temperature and supply voltage levels. The AMS has two SYSMON blocks.
+PL-SYSMON block is capable of monitoring off chip voltage and temperature.
+PL-SYSMON block has DRP, JTAG and I2C interface to enable monitoring from
+external master. Out of this interface currently only DRP is supported.
+Other block PS-SYSMON is memory mapped to PS. Both of block has built-in
+alarm generation logic that is used to interrupt the processor based on
+condition set.
+
+All designs should have AMS registers, but PS and PL are optional. The
+AMS controller can work with only PS, only PL and both PS and PL
+configurations. Please specify registers according to your design. Devicetree
+should always have AMS module property. Providing PS & PL module is optional.
+
+Required properties:
+   - compatible: Should be "xlnx,zynqmp-ams"
+   - reg:  Should specify AMS register space
+   - interrupts: Interrupt number for the AMS control interface
+   - interrupt-names: Interrupt name, must be "ams-irq"
+   - clocks: Should contain a clock specifier for the device
+   - ranges: keep the property empty to map child address space
+ (for PS and/or PL) nodes 1:1 onto the parent address
+ space
+
+AMS device tree subnode:
+   - compatible: Should be "xlnx,zynqmp-ams-ps" or "xlnx,zynqmp-ams-pl"
+   - reg:  Register space for PS or PL
+
+Optional properties:
+
+Following optional property only valid for PL.
+   - xlnx,ext-channels: List of external channels that are connected to the
+AMS PL module.
+
+ The child nodes of this node represent the external channels which are
+ connected to the AMS Module. If the property is not present
+ no external channels will be assumed to be connected.
+
+ Each child node represents one channel and has the following
+ properties:
+   Required properties:
+   * reg: Pair of pins the channel is connected to.
+   0: VP/VN
+   1: VUSER0
+   2: VUSER1
+   3: VUSER3
+   4: VUSER4
+   5: VAUXP[0]/VAUXN[0]
+   6: VAUXP[1]/VAUXN[1]
+   ...
+   20: VAUXP[15]/VAUXN[15]
+ Note each channel number should only be used at most
+ once.
+   Optional properties:
+   * xlnx,bipolar: If set the channel is used in bipolar
+ mode.
+
+
+Example:
+   xilinx_ams: ams@ffa5 {
+   compatible = "xlnx,zynqmp-ams";
+   interrupt-parent = <&gic>;
+   interrupts = <0 56 4>;
+   interrupt-names = "ams-irq";
+   clocks = <&clkc 70>;
+   reg = <0x0 0xffa5 0x0 0x800>;
+   reg-names = "ams-base";
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+
+   ams_ps: ams_ps@ffa50800 {
+   compatible = "xlnx,zynqmp-ams-ps";
+   reg = <0x0 0xffa50800 0x0 0x400>;
+   };
+
+   ams_pl: ams_pl@ffa50c00 {
+   compatible = "xlnx,zynqmp-ams-pl";
+   reg = <0x0 0xffa50c00 0x0 0x400>;
+   xlnx,ext-channels {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   channel@0 {
+   reg = <0>;
+   xlnx,bipolar;
+   };
+   channel@1 {
+   reg = <1>;
+   };
+   channel@8 {
+ 

RE: [PATCH v4 1/4] edac: synps: Add platform specific structures for ddrc controller

2018-08-22 Thread Manish Narani
Hi Boris,

Thank you so much for the review.

> -Original Message-
> From: Borislav Petkov [mailto:b...@alien8.de]
> Sent: Tuesday, August 21, 2018 6:37 PM
> To: Manish Narani 
> Cc: robh...@kernel.org; mark.rutl...@arm.com; catalin.mari...@arm.com;
> will.dea...@arm.com; Michal Simek ;
> mche...@kernel.org; m...@kernel.org; Edgar Iglesias ;
> Shubhrajyoti Datta ; Naga Sureshkumar Relli
> ; Bharat Kumar Gogada ;
> stefan.krsmano...@aggios.com; Srinivas Goud ; Anirudha
> Sarangi ; linux-kernel@vger.kernel.org;
> devicet...@vger.kernel.org; linux-arm-ker...@lists.infradead.org; linux-
> e...@vger.kernel.org
> Subject: Re: [PATCH v4 1/4] edac: synps: Add platform specific structures for
> ddrc controller
> 
> On Sat, Aug 04, 2018 at 02:55:32PM +0530, Manish Narani wrote:
> > Add platform specific structures, so that we can add different IP
> > support later using quirks.
> >
> > Signed-off-by: Manish Narani 
> > ---
> >  drivers/edac/synopsys_edac.c | 83
> > ++--
> >  1 file changed, 65 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/edac/synopsys_edac.c
> > b/drivers/edac/synopsys_edac.c index 0c9c59e..b3c54e7 100644
> > --- a/drivers/edac/synopsys_edac.c
> > +++ b/drivers/edac/synopsys_edac.c
> > @@ -22,6 +22,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include "edac_module.h"
> >
> > @@ -130,6 +131,7 @@ struct synps_ecc_status {
> >   * @baseaddr:  Base address of the DDR controller
> >   * @message:   Buffer for framing the event specific info
> >   * @stat:  ECC status information
> > + * @p_data:Pointer to platform data
> >   * @ce_cnt:Correctable Error count
> >   * @ue_cnt:Uncorrectable Error count
> >   */
> > @@ -137,24 +139,47 @@ struct synps_edac_priv {
> > void __iomem *baseaddr;
> > char message[SYNPS_EDAC_MSG_SIZE];
> > struct synps_ecc_status stat;
> > +   const struct synps_platform_data *p_data;
> > u32 ce_cnt;
> > u32 ue_cnt;
> >  };
> >
> >  /**
> > + * struct synps_platform_data -  synps platform data structure
> > + * @edac_geterror_info:function pointer to synps edac error info
> > + * @edac_get_mtype:function pointer to synps edac mtype
> > + * @edac_get_dtype:function pointer to synps edac dtype
> > + * @edac_get_eccstate: function pointer to synps edac eccstate
> > + * @quirks:to differentiate IPs
> > + */
> > +struct synps_platform_data {
> > +   int (*edac_geterror_info)(struct synps_edac_priv *priv);
> > +   enum mem_type (*edac_get_mtype)(const void __iomem *base);
> > +   enum dev_type (*edac_get_dtype)(const void __iomem *base);
> > +   bool (*edac_get_eccstate)(void __iomem *base);
> > +   int quirks;
> > +};
> > +
> > +/**
> >   * synps_edac_geterror_info - Get the current ecc error info
> > - * @base:  Pointer to the base address of the ddr memory controller
> > - * @p: Pointer to the synopsys ecc status structure
> > + * @priv:  Pointer to DDR memory controller private instance data
> >   *
> >   * Determines there is any ecc error or not
> >   *
> >   * Return: one if there is no error otherwise returns zero
> >   */
> > -static int synps_edac_geterror_info(void __iomem *base,
> > -   struct synps_ecc_status *p)
> > +static int synps_edac_geterror_info(struct synps_edac_priv *priv)
> >  {
> > +   void __iomem *base;
> > +   struct synps_ecc_status *p;
> > u32 regval, clearval = 0;
> >
> > +   if (!priv)
> > +   return 1;
> > +
> > +   base = priv->baseaddr;
> > +   p = &priv->stat;
> > +
> > regval = readl(base + STAT_OFST);
> > if (!regval)
> > return 1;
> > @@ -240,9 +265,10 @@ static void synps_edac_handle_error(struct
> > mem_ctl_info *mci,  static void synps_edac_check(struct mem_ctl_info
> > *mci)  {
> > struct synps_edac_priv *priv = mci->pvt_info;
> > +   const struct synps_platform_data *p_data = priv->p_data;
> > int status;
> >
> > -   status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
> > +   status = p_data->edac_geterror_info(priv);
> > if (status)
> > return;
> >
> > @@ -362,6 +388,7 @@ static int synps_edac_init_csrows(struct
> mem_ctl_info *mci)
> > struct csrow_info *csi;
> > struct dimm_info *dimm;
&

RE: [PATCH v4 3/4] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-08-22 Thread Manish Narani
Hi Boris,

Thanks a lot for the review.

> -Original Message-
> From: Borislav Petkov [mailto:b...@alien8.de]
> Sent: Tuesday, August 21, 2018 6:40 PM
> To: Manish Narani 
> Cc: robh...@kernel.org; mark.rutl...@arm.com; catalin.mari...@arm.com;
> will.dea...@arm.com; Michal Simek ;
> mche...@kernel.org; m...@kernel.org; Edgar Iglesias ;
> Shubhrajyoti Datta ; Naga Sureshkumar Relli
> ; Bharat Kumar Gogada ;
> stefan.krsmano...@aggios.com; Srinivas Goud ; Anirudha
> Sarangi ; linux-kernel@vger.kernel.org;
> devicet...@vger.kernel.org; linux-arm-ker...@lists.infradead.org; linux-
> e...@vger.kernel.org
> Subject: Re: [PATCH v4 3/4] edac: synopsys: Add EDAC ECC support for ZynqMP
> DDRC
> 
> On Sat, Aug 04, 2018 at 02:55:34PM +0530, Manish Narani wrote:
> > Add EDAC ECC support for ZynqMP DDRC IP. Also add support for ECC
> > Error Injection in ZynqMP. The corrected and uncorrected error
> > interrupts support is added. The Row, Column, Bank, Bank Group and
> > Rank bits positions are determined via Address Map registers of Synopsys
> DDRC.
> >
> > Signed-off-by: Manish Narani 
> > ---
> >  drivers/edac/Kconfig |   2 +-
> >  drivers/edac/synopsys_edac.c | 864
> > ++-
> >  2 files changed, 848 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index
> > 57304b2..b1fc7a16 100644
> > --- a/drivers/edac/Kconfig
> > +++ b/drivers/edac/Kconfig
> > @@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
> >
> >  config EDAC_SYNOPSYS
> > tristate "Synopsys DDR Memory Controller"
> > -   depends on ARCH_ZYNQ
> > +   depends on ARCH_ZYNQ || ARM64
> > help
> >   Support for error detection and correction on the Synopsys DDR
> >   memory controller.
> > diff --git a/drivers/edac/synopsys_edac.c
> > b/drivers/edac/synopsys_edac.c index b3c54e7..82f276b 100644
> > --- a/drivers/edac/synopsys_edac.c
> > +++ b/drivers/edac/synopsys_edac.c
> > @@ -22,6 +22,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >
> >  #include "edac_module.h"
> > @@ -96,6 +97,170 @@
> >  #define SCRUB_MODE_MASK0x7
> >  #define SCRUB_MODE_SECDED  0x4
> >
> > +/* DDR ECC Quirks */
> > +#define DDR_ECC_INTR_SUPPORT   BIT(0)
> > +
> > +/* DDR ECC Quirks */
> > +#define DDR_ECC_INTR_SUPPORT   BIT(0)
> 
> This is repeated.
I missed that. I will update the same in v5.

> 
> > +#define DDR_ECC_DATA_POISON_SUPPORT BIT(1)
> > +
> > +/* ZynqMP Enhanced DDR memory controller registers that are relevant
> > +to ECC */
> > +/* ECC Configuration Registers */
> > +#define ECC_CFG0_OFST  0x70
> > +#define ECC_CFG1_OFST  0x74
> > +
> > +/* ECC Status Register */
> > +#define ECC_STAT_OFST  0x78
> > +
> > +/* ECC Clear Register */
> > +#define ECC_CLR_OFST   0x7C
> > +
> > +/* ECC Error count Register */
> > +#define ECC_ERRCNT_OFST0x80
> 
> Do you not see how the rest of the defines' values are aligned vertically in 
> this
> file?
Will work in this and update the same.
> 
> > +
> > +/* ECC Corrected Error Address Register */
> > +#define ECC_CEADDR0_OFST   0x84
> > +#define ECC_CEADDR1_OFST   0x88
> > +
> > +/* ECC Syndrome Registers */
> > +#define ECC_CSYND0_OFST0x8C
> > +#define ECC_CSYND1_OFST0x90
> > +#define ECC_CSYND2_OFST0x94
> > +
> > +/* ECC Bit Mask0 Address Register */
> > +#define ECC_BITMASK0_OFST  0x98
> > +#define ECC_BITMASK1_OFST  0x9C
> > +#define ECC_BITMASK2_OFST  0xA0
> > +
> > +/* ECC UnCorrected Error Address Register */
> > +#define ECC_UEADDR0_OFST   0xA4
> > +#define ECC_UEADDR1_OFST   0xA8
> > +
> > +/* ECC Syndrome Registers */
> > +#define ECC_UESYND0_OFST   0xAC
> > +#define ECC_UESYND1_OFST   0xB0
> > +#define ECC_UESYND2_OFST   0xB4
> > +
> > +/* ECC Poison Address Reg */
> > +#define ECC_POISON0_OFST   0xB8
> > +#define ECC_POISON1_OFST   0xBC
> > +
> > +#define ECC_ADDRMAP0_OFFSET0x200
> > +
> > +/* Control register bitfield definitions */
> > +#define ECC_CTRL_BUSWIDTH_MASK 0x3000
> > +#define ECC_CTRL_BUSWIDTH_SHIFT12
> > +#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
> > +#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
> > +
> > +/* DDR Control Register width definitions  */
> > +#define DDRCTL_EWDTH_162
> > +#define DDRCTL

RE: [PATCH v2 2/4] iio: adc: xilinx: limit pcap clock frequency value

2018-07-30 Thread Manish Narani
Hi Jonathan,


> -Original Message-
> From: Jonathan Cameron [mailto:ji...@kernel.org]
> Sent: Sunday, July 29, 2018 5:21 PM
> To: Manish Narani 
> Cc: Sai Krishna Potthuri ; Michal Simek
> ; pme...@pmeerw.net; l...@metafoo.de;
> knaac...@gmx.de; Anirudha Sarangi ; Srinivas Goud
> ; linux-kernel@vger.kernel.org; linux-arm-
> ker...@lists.infradead.org; linux-...@vger.kernel.org
> Subject: Re: [PATCH v2 2/4] iio: adc: xilinx: limit pcap clock frequency value
> 
> On Mon, 23 Jul 2018 20:32:01 +0530
> Manish Narani  wrote:
> 
> > This patch limits the xadc pcap clock frequency value to be less than
> > 200MHz. This fixes the issue when zynq is booted at higher frequency
> > values, pcap crosses the maximum limit of 200MHz(Fmax) as it is
> > derived from IOPLL.
> > If this limit is crossed it is required to alter the WEDGE and REDGE
> > bits of XADC_CFG register to make timings better in the interface. So
> > to avoid alteration of these bits every time, the pcap value should
> > not cross the Fmax limit.
> >
> > Signed-off-by: Manish Narani 
> 
> Applied, to the togreg branch of iio.git.  If you want this backported to 
> stable,
> then request it once this patch is upstream.  It may be sometime given we've
> probably just missed the coming merge window.
> 
> If you do need it faster then let me know and I'll look at moving it over to 
> the
> branch of fixes during the RC phases.
Thanks for getting this applied. There is no concern for this to be in the 
stable
ASAP. I can wait.

Thanks & Regards,
Manish Narani


[PATCH 2/4] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-07-19 Thread Manish Narani
This patch documents Synopsys EDAC driver which reports the single bit
errors that are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
---
 .../bindings/memory-controllers/synopsys.txt   | 25 ++
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..5d20b76 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
+Synopsys EDAC driver, it does reports the DDR ECC single bit errors
+that are corrected and double bit ecc errors that are detected by the DDR
+ECC controller.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration. The ECC controller corrects one bit error and detects
 two bit errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupt-parent: Should be core interrupt controller.
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH 1/4] edac: synps: Add platform specific structures for ddrc controller

2018-07-19 Thread Manish Narani
This patch adds platform specific structures, so that we can add
different IP support later using quirks.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 70 
 1 file changed, 58 insertions(+), 12 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0c9c59e..447396e 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "edac_module.h"
 
@@ -95,6 +96,9 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+
 /**
  * struct ecc_error_info - ECC error log information
  * @row:   Row number
@@ -130,6 +134,7 @@ struct synps_ecc_status {
  * @baseaddr:  Base address of the DDR controller
  * @message:   Buffer for framing the event specific info
  * @stat:  ECC status information
+ * @p_data:Pointer to platform data
  * @ce_cnt:Correctable Error count
  * @ue_cnt:Uncorrectable Error count
  */
@@ -137,11 +142,29 @@ struct synps_edac_priv {
void __iomem *baseaddr;
char message[SYNPS_EDAC_MSG_SIZE];
struct synps_ecc_status stat;
+   const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
 };
 
 /**
+ * struct synps_platform_data -  synps platform data structure
+ * @synps_edac_geterror_info:  function pointer to synps edac error info
+ * @synps_edac_get_mtype:  function pointer to synps edac mtype
+ * @synps_edac_get_dtype:  function pointer to synps edac dtype
+ * @synps_edac_get_eccstate:   function pointer to synps edac eccstate
+ * @quirks:to differentiate IPs
+ */
+struct synps_platform_data {
+   int (*synps_edac_geterror_info)(void __iomem *base,
+   struct synps_ecc_status *p);
+   enum mem_type (*synps_edac_get_mtype)(const void __iomem *base);
+   enum dev_type (*synps_edac_get_dtype)(const void __iomem *base);
+   bool (*synps_edac_get_eccstate)(void __iomem *base);
+   int quirks;
+};
+
+/**
  * synps_edac_geterror_info - Get the current ecc error info
  * @base:  Pointer to the base address of the ddr memory controller
  * @p: Pointer to the synopsys ecc status structure
@@ -242,7 +265,8 @@ static void synps_edac_check(struct mem_ctl_info *mci)
struct synps_edac_priv *priv = mci->pvt_info;
int status;
 
-   status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = priv->p_data->synps_edac_geterror_info(priv->baseaddr,
+   &priv->stat);
if (status)
return;
 
@@ -372,10 +396,12 @@ static int synps_edac_init_csrows(struct mem_ctl_info 
*mci)
for (j = 0; j < csi->nr_channels; j++) {
dimm= csi->channels[j]->dimm;
dimm->edac_mode = EDAC_FLAG_SECDED;
-   dimm->mtype = synps_edac_get_mtype(priv->baseaddr);
+   dimm->mtype = priv->p_data->synps_edac_get_mtype(
+   priv->baseaddr);
dimm->nr_pages  = (size >> PAGE_SHIFT) / 
csi->nr_channels;
dimm->grain = SYNPS_EDAC_ERR_GRAIN;
-   dimm->dtype = synps_edac_get_dtype(priv->baseaddr);
+   dimm->dtype = priv->p_data->synps_edac_get_dtype(
+   priv->baseaddr);
}
}
 
@@ -423,6 +449,21 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci,
return status;
 }
 
+static const struct synps_platform_data zynq_edac_def = {
+   .synps_edac_geterror_info   = synps_edac_geterror_info,
+   .synps_edac_get_mtype   = synps_edac_get_mtype,
+   .synps_edac_get_dtype   = synps_edac_get_dtype,
+   .synps_edac_get_eccstate= synps_edac_get_eccstate,
+   .quirks = 0,
+};
+
+static const struct of_device_id synps_edac_match[] = {
+   { .compatible = "xlnx,zynq-ddrc-a05", .data = (void *)&zynq_edac_def },
+   { /* end of table */ }
+};
+
+MODULE_DEVICE_TABLE(of, synps_edac_match);
+
 /**
  * synps_edac_mc_probe - Check controller and bind driver
  * @pdev:  Pointer to the platform_device struct
@@ -440,13 +481,22 @@ static int synps_edac_mc_probe(struct platform_device 
*pdev)
int rc;
struct resource *res;
void __iomem *baseaddr;
+   const struct of_device_id *match;
+   const struct synps_platform_data *p_data;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
baseaddr = devm_ioremap_resource(&pdev->dev,

[PATCH 3/4] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-07-19 Thread Manish Narani
This patch adds EDAC ECC support for ZynqMP DDRC IP. The patch also adds
support for ECC Error Injection in ZynqMP. The corrected and uncorrected
error interrupts support is added in this patch. The Row, Column, Bank,
Bank Group and Rank bits positions are determined via Address Map
registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 848 ++-
 2 files changed, 833 insertions(+), 17 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..b1fc7a16 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARM64
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 447396e..4380eb9 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "edac_module.h"
@@ -98,6 +99,164 @@
 
 /* DDR ECC Quirks */
 #define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORT BIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST 0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON1_BANKGRP_SHIFT 28
+#define ECC_POISON1_BANKNR_SHIFT 24
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK 0x3
+#define ECC_UEPOISON_MASK 0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_DEV_CONFIG_MASK 0xC000
+#define DDRC_MSTR_DEV_CONFIG_SHIFT 30
+#define DDRC_MSTR_DEV_CONFIG_X4_MASK   0x0
+#define DDRC_MSTR_DEV_CONFIG_X8_MASK   0x1
+#define DDRC_MSTR_DEV_CONFIG_X16_MASK  0x2
+#define DDRC_MSTR_DEV_CONFIG_X32_MASK  0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#define ROW_MAX_VAL_MASK   0xF
+#define COL_MAX_VAL_MASK   0xF
+#define BANK_MAX_VAL_MASK  0x1F
+#define BANKGRP_MAX_VAL_MASK   0x1F
+#define RANK_MAX_VAL_MASK  0x1

[PATCH 4/4] arm64: zynqmp: Add DDRC node

2018-07-19 Thread Manish Narani
This patch adds ddrc memory controller node in dts. The size mentioned
in dts is 0x3, because we need to access DDR_QOS INTR registers
located at fd090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index a091e6f..7d6a3cf 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH 0/4] EDAC: Enhancements to Synopsys EDAC driver

2018-07-19 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms.This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Manish Narani (4):
  edac: synps: Add platform specific structures for ddrc controller
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node

 .../bindings/memory-controllers/synopsys.txt   |  25 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
 drivers/edac/Kconfig   |   2 +-
 drivers/edac/synopsys_edac.c   | 916 -
 4 files changed, 918 insertions(+), 32 deletions(-)

-- 
2.1.1



RE: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay values from DT

2018-07-19 Thread Manish Narani
Hi Uffe,

> -Original Message-
> From: Ulf Hansson [mailto:ulf.hans...@linaro.org]
> Sent: Tuesday, July 10, 2018 2:02 PM
> To: Manish Narani 
> Cc: Rob Herring ; Mark Rutland
> ; Catalin Marinas ; Will
> Deacon ; Moritz Fischer ;
> stefan.krsmano...@aggios.com; Linux ARM  ker...@lists.infradead.org>; Linux Kernel Mailing List  ker...@vger.kernel.org>; linux-...@vger.kernel.org;
> devicet...@vger.kernel.org; Adrian Hunter ;
> Michal Simek 
> Subject: Re: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay
> values from DT
> 
> On 7 June 2018 at 14:11, Manish Narani  wrote:
> > This patch adds support for reading Tap Delay values from Device Tree
> > and write them via eemi calls. The macros containing these tap delay
> > values are removed from the driver.
> >
> > Signed-off-by: Manish Narani 
> > ---
> >  drivers/mmc/host/sdhci-of-arasan.c | 131
> > +
> >  1 file changed, 131 insertions(+)
> >
> > diff --git a/drivers/mmc/host/sdhci-of-arasan.c
> > b/drivers/mmc/host/sdhci-of-arasan.c
> > index e3332a5..fc0fd01 100644
> > --- a/drivers/mmc/host/sdhci-of-arasan.c
> > +++ b/drivers/mmc/host/sdhci-of-arasan.c
> > @@ -36,6 +36,8 @@
> >
> >  #define PHY_CLK_TOO_SLOW_HZ40
> >
> > +#define MMC_BANK2  0x2
> > +
> >  /*
> >   * On some SoCs the syscon area has a feature where the upper 16-bits of
> >   * each 32-bit register act as a write mask for the lower 16-bits.
> > This allows @@ -90,6 +92,10 @@ struct sdhci_arasan_data {
> > struct sdhci_host *host;
> > struct clk  *clk_ahb;
> > struct phy  *phy;
> > +   u32 mio_bank;
> > +   u32 device_id;
> > +   u32 itapdly[MMC_TIMING_MMC_HS400 + 1];
> > +   u32 otapdly[MMC_TIMING_MMC_HS400 + 1];
> > boolis_phy_on;
> >
> > boolhas_cqe;
> > @@ -160,11 +166,36 @@ static int sdhci_arasan_syscon_write(struct
> sdhci_host *host,
> > return ret;
> >  }
> >
> > +/**
> > + * arasan_zynqmp_set_tap_delay - Program the tap delays.
> > + * @deviceid:  Unique Id of device
> > + * @itap_delay:Input Tap Delay
> > + * @oitap_delay:   Output Tap Delay
> > + */
> > +static void arasan_zynqmp_set_tap_delay(u8 deviceid, u8 itap_delay,
> > +u8 otap_delay) {
> > +   const struct zynqmp_eemi_ops *eemi_ops =
> > +zynqmp_pm_get_eemi_ops();
> 
> No thanks!
> 
> Isn't there a more generic framework we can use to change the tap values,
> rather than calling SoC specific functions from the driver?
Yes, Thanks for your suggestion. I will work on the generic framework which 
will be used to change tap values
Via SoC drivers.
> 
> BTW, what is a tap value, more exactly?
> What does changing a tap value mean and where does the property belong,
> really?
Tap Value is the delay of clock phase which is used to adjust phase to the 
working value. The auto tuning
process generally sets tap values internally in controller in SD UHS modes. But 
for other modes where
auto tuning is applicable, we are determining tap values via trial & error 
method for specific SoC.
> > 
> Of course this doesn't even compile, as you have a dependency to another
> series. Next time, please clarify that in a cover-letter (maybe you did, but I
> can't find it).
> 
> > +   u32 node_id = (deviceid == 0) ? NODE_SD_0 : NODE_SD_1;
> > +
> > +   if (!eemi_ops || !eemi_ops->ioctl)
> > +   return;
> > +
> > +   if (itap_delay)
> > +   eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
> > +   PM_TAPDELAY_INPUT, itap_delay, NULL);
> > +
> > +   if (otap_delay)
> > +   eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
> > +   PM_TAPDELAY_OUTPUT, otap_delay, NULL);
> > +}
> 
> Another overall comment for the series.
> 
> I would recommend to change the order of the patches in the series.
> Let the DT doc change come first, next the driver change and finally the 
> change
> to the DTS file(s). This makes it easier to follow and review.
Sure, I will do that.

Thanks & Regards,
Manish

> 
> [...]
> 
> Kind regards
> Uffe


RE: [PATCH 4/4] iio: adc: xilinx: Use devm_ functions while requesting irq

2018-07-23 Thread Manish Narani
Hi Lars,

> -Original Message-
> From: Lars-Peter Clausen [mailto:l...@metafoo.de]
> Sent: Thursday, July 19, 2018 10:08 PM
> To: Manish Narani ; ji...@kernel.org;
> knaac...@gmx.de; pme...@pmeerw.net; Michal Simek
> ; linux-...@vger.kernel.org; linux-arm-
> ker...@lists.infradead.org; linux-kernel@vger.kernel.org
> Cc: Anirudha Sarangi ; Srinivas Goud
> 
> Subject: Re: [PATCH 4/4] iio: adc: xilinx: Use devm_ functions while 
> requesting
> irq
> 
> > @@ -1310,7 +1308,6 @@ static int xadc_remove(struct platform_device
> > *pdev)  {
> > struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> > struct xadc *xadc = iio_priv(indio_dev);
> > -   int irq = platform_get_irq(pdev, 0);
> >
> > iio_device_unregister(indio_dev);
> > if (xadc->ops->flags & XADC_FLAGS_BUFFERED) { @@ -1318,7 +1315,6
> @@
> > static int xadc_remove(struct platform_device *pdev)
> > iio_trigger_free(xadc->convst_trigger);
> > iio_triggered_buffer_cleanup(indio_dev);
> > }
> > -   free_irq(irq, indio_dev);
> 
> This opens up a race condition. The IRQ needs to be freed before any of these
> other things below the free_irq() are executed.
Will look into it and send with taking care of the same.

> 
> > clk_disable_unprepare(xadc->clk);
> > cancel_delayed_work(&xadc->zynq_unmask_work);
> > kfree(xadc->data);
> >

Thanks,
Manish


RE: [PATCH 3/4] iio: adc: xilinx: Check for return values in clk related functions

2018-07-23 Thread Manish Narani
Hi Jonathan,

Thanks for your comments.

> -Original Message-
> From: Jonathan Cameron [mailto:ji...@kernel.org]
> Sent: Saturday, July 21, 2018 9:54 PM
> To: Lars-Peter Clausen 
> Cc: Manish Narani ; knaac...@gmx.de;
> pme...@pmeerw.net; Michal Simek ; linux-
> i...@vger.kernel.org; linux-arm-ker...@lists.infradead.org; linux-
> ker...@vger.kernel.org; Anirudha Sarangi ; Srinivas
> Goud 
> Subject: Re: [PATCH 3/4] iio: adc: xilinx: Check for return values in clk 
> related
> functions
> 
> On Thu, 19 Jul 2018 18:40:26 +0200
> Lars-Peter Clausen  wrote:
> 
> > On 07/18/2018 01:12 PM, Manish Narani wrote:
> > > This patch adds check for return values from clock related functions.
> > > This was reported by static code analysis tool.
> >
> > This patch seems to do something else.
> Indeed, definitely doing two things only one of which is mentioned.
> Please break it up and resend.
I will break it up and resend.

> 
> Jonathan
> 
> >
> > >
> > > Signed-off-by: Manish Narani 
> > > ---
> > >  drivers/iio/adc/xilinx-xadc-core.c | 24 ++--
> > >  1 file changed, 22 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/iio/adc/xilinx-xadc-core.c
> > > b/drivers/iio/adc/xilinx-xadc-core.c
> > > index 248cffa..47eb364 100644
> > > --- a/drivers/iio/adc/xilinx-xadc-core.c
> > > +++ b/drivers/iio/adc/xilinx-xadc-core.c
> > > @@ -322,6 +322,7 @@ static irqreturn_t
> > > xadc_zynq_interrupt_handler(int irq, void *devid)
> > >
> > >  #define XADC_ZYNQ_TCK_RATE_MAX 5000  #define
> > > XADC_ZYNQ_IGAP_DEFAULT 20
> > > +#define XADC_ZYNQ_PCAP_RATE_MAX 2
> > >
> > >  static int xadc_zynq_setup(struct platform_device *pdev,
> > >   struct iio_dev *indio_dev, int irq) @@ -332,6 +333,7 @@ static int
> > > xadc_zynq_setup(struct platform_device *pdev,
> > >   unsigned int div;
> > >   unsigned int igap;
> > >   unsigned int tck_rate;
> > > + int ret;
> > >
> > >   /* TODO: Figure out how to make igap and tck_rate configurable */
> > >   igap = XADC_ZYNQ_IGAP_DEFAULT;
> > > @@ -341,6 +343,13 @@ static int xadc_zynq_setup(struct
> > > platform_device *pdev,
> > >
> > >   pcap_rate = clk_get_rate(xadc->clk);
> > >
> > > + if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) {
> > > + ret = clk_set_rate(xadc->clk,
> > > +(unsigned
> long)XADC_ZYNQ_PCAP_RATE_MAX);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > +
> > >   if (tck_rate > pcap_rate / 2) {
> > >   div = 2;
> > >   } else {
> > > @@ -366,6 +375,12 @@ static int xadc_zynq_setup(struct platform_device
> *pdev,
> > >   XADC_ZYNQ_CFG_REDGE | XADC_ZYNQ_CFG_WEDGE
> |
> > >   tck_div | XADC_ZYNQ_CFG_IGAP(igap));
> > >
> > > + if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) {
> > > + ret = clk_set_rate(xadc->clk, pcap_rate);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > +
> > >   return 0;
> > >  }
> > >
> > > @@ -887,6 +902,9 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
> > >   unsigned long clk_rate = xadc_get_dclk_rate(xadc);
> > >   unsigned int div;
> > >
> > > + if (!clk_rate)
> > > +     return -EINVAL;
> > > +
> > >   if (info != IIO_CHAN_INFO_SAMP_FREQ)
> > >   return -EINVAL;
> > >
> > > @@ -1239,8 +1257,10 @@ static int xadc_probe(struct platform_device
> *pdev)
> > >   goto err_free_irq;
> > >
> > >   /* Disable all alarms */
> > > - xadc_update_adc_reg(xadc, XADC_REG_CONF1,
> XADC_CONF1_ALARM_MASK,
> > > - XADC_CONF1_ALARM_MASK);
> > > + ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1,
> XADC_CONF1_ALARM_MASK,
> > > +   XADC_CONF1_ALARM_MASK);
> > > + if (ret)
> > > + goto err_free_irq;
> > >
> > >   /* Set thresholds to min/max */
> > >   for (i = 0; i < 16; i++) {
> > >
> >

Thanks,
Manish Narani


[PATCH v2 4/4] arm64: zynqmp: Add DDRC node

2018-08-02 Thread Manish Narani
This patch adds ddrc memory controller node in dts. The size mentioned
in dts is 0x3, because we need to access DDR_QOS INTR registers
located at fd090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index a091e6f..7d6a3cf 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH v2 0/4] EDAC: Enhancements to Synopsys EDAC driver

2018-08-02 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms.This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Manish Narani (4):
  edac: synps: Add platform specific structures for ddrc controller
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node

 .../bindings/memory-controllers/synopsys.txt   |  27 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
 drivers/edac/Kconfig   |   2 +-
 drivers/edac/synopsys_edac.c   | 919 -
 4 files changed, 922 insertions(+), 33 deletions(-)

-- 
2.1.1



[PATCH v2 2/4] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-08-02 Thread Manish Narani
This patch documents Synopsys EDAC driver which reports the single bit
errors that are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v2 1/4] edac: synps: Add platform specific structures for ddrc controller

2018-08-02 Thread Manish Narani
This patch adds platform specific structures, so that we can add
different IP support later using quirks.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 64 
 1 file changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0c9c59e..d4798e8 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "edac_module.h"
 
@@ -130,6 +131,7 @@ struct synps_ecc_status {
  * @baseaddr:  Base address of the DDR controller
  * @message:   Buffer for framing the event specific info
  * @stat:  ECC status information
+ * @p_data:Pointer to platform data
  * @ce_cnt:Correctable Error count
  * @ue_cnt:Uncorrectable Error count
  */
@@ -137,11 +139,29 @@ struct synps_edac_priv {
void __iomem *baseaddr;
char message[SYNPS_EDAC_MSG_SIZE];
struct synps_ecc_status stat;
+   const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
 };
 
 /**
+ * struct synps_platform_data -  synps platform data structure
+ * @synps_edac_geterror_info:  function pointer to synps edac error info
+ * @synps_edac_get_mtype:  function pointer to synps edac mtype
+ * @synps_edac_get_dtype:  function pointer to synps edac dtype
+ * @synps_edac_get_eccstate:   function pointer to synps edac eccstate
+ * @quirks:to differentiate IPs
+ */
+struct synps_platform_data {
+   int (*synps_edac_geterror_info)(void __iomem *base,
+   struct synps_ecc_status *p);
+   enum mem_type (*synps_edac_get_mtype)(const void __iomem *base);
+   enum dev_type (*synps_edac_get_dtype)(const void __iomem *base);
+   bool (*synps_edac_get_eccstate)(void __iomem *base);
+   int quirks;
+};
+
+/**
  * synps_edac_geterror_info - Get the current ecc error info
  * @base:  Pointer to the base address of the ddr memory controller
  * @p: Pointer to the synopsys ecc status structure
@@ -242,7 +262,8 @@ static void synps_edac_check(struct mem_ctl_info *mci)
struct synps_edac_priv *priv = mci->pvt_info;
int status;
 
-   status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = priv->p_data->synps_edac_geterror_info(priv->baseaddr,
+   &priv->stat);
if (status)
return;
 
@@ -372,10 +393,12 @@ static int synps_edac_init_csrows(struct mem_ctl_info 
*mci)
for (j = 0; j < csi->nr_channels; j++) {
dimm= csi->channels[j]->dimm;
dimm->edac_mode = EDAC_FLAG_SECDED;
-   dimm->mtype = synps_edac_get_mtype(priv->baseaddr);
+   dimm->mtype = priv->p_data->synps_edac_get_mtype(
+   priv->baseaddr);
dimm->nr_pages  = (size >> PAGE_SHIFT) / 
csi->nr_channels;
dimm->grain = SYNPS_EDAC_ERR_GRAIN;
-   dimm->dtype = synps_edac_get_dtype(priv->baseaddr);
+   dimm->dtype = priv->p_data->synps_edac_get_dtype(
+   priv->baseaddr);
}
}
 
@@ -423,6 +446,21 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci,
return status;
 }
 
+static const struct synps_platform_data zynq_edac_def = {
+   .synps_edac_geterror_info   = synps_edac_geterror_info,
+   .synps_edac_get_mtype   = synps_edac_get_mtype,
+   .synps_edac_get_dtype   = synps_edac_get_dtype,
+   .synps_edac_get_eccstate= synps_edac_get_eccstate,
+   .quirks = 0,
+};
+
+static const struct of_device_id synps_edac_match[] = {
+   { .compatible = "xlnx,zynq-ddrc-a05", .data = (void *)&zynq_edac_def },
+   { /* end of table */ }
+};
+
+MODULE_DEVICE_TABLE(of, synps_edac_match);
+
 /**
  * synps_edac_mc_probe - Check controller and bind driver
  * @pdev:  Pointer to the platform_device struct
@@ -440,13 +478,22 @@ static int synps_edac_mc_probe(struct platform_device 
*pdev)
int rc;
struct resource *res;
void __iomem *baseaddr;
+   const struct of_device_id *match;
+   const struct synps_platform_data *p_data;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
baseaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(baseaddr))
return PTR_ERR(baseaddr);
 
-   if (!synps_edac_get_eccstate(baseaddr)) {
+   match = of_match_node(synps_edac_match, pdev->dev.of_node);
+   if (!match && !match->data) {
+

[PATCH v2 3/4] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-08-02 Thread Manish Narani
This patch adds EDAC ECC support for ZynqMP DDRC IP. The patch also adds
support for ECC Error Injection in ZynqMP. The corrected and uncorrected
error interrupts support is added in this patch. The Row, Column, Bank,
Bank Group and Rank bits positions are determined via Address Map
registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 857 ++-
 2 files changed, 841 insertions(+), 18 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..b1fc7a16 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARM64
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index d4798e8..8a1c327 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "edac_module.h"
@@ -96,6 +97,170 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORT BIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST 0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON1_BANKGRP_SHIFT 28
+#define ECC_POISON1_BANKNR_SHIFT 24
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK 0x3
+#define ECC_UEPOISON_MASK 0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_DEV_CONFIG_MASK 0xC000
+#define DDRC_MSTR_DEV_CONFIG_SHIFT 30
+#define DDRC_MSTR_DEV_CONFIG_X4_MASK   0x0
+#define DDRC_MSTR_DEV_CONFIG_X8_MASK   0x1
+#define DDRC_MSTR_DEV_CONFIG_X16_MASK  0x2
+#define DDRC_MSTR_DEV_CONFIG_X32_MASK  0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#define ROW_MAX_VAL_MASK   0xF
+#define CO

[PATCH v3 1/4] edac: synps: Add platform specific structures for ddrc controller

2018-08-02 Thread Manish Narani
This patch adds platform specific structures, so that we can add
different IP support later using quirks.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 64 
 1 file changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0c9c59e..d4798e8 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "edac_module.h"
 
@@ -130,6 +131,7 @@ struct synps_ecc_status {
  * @baseaddr:  Base address of the DDR controller
  * @message:   Buffer for framing the event specific info
  * @stat:  ECC status information
+ * @p_data:Pointer to platform data
  * @ce_cnt:Correctable Error count
  * @ue_cnt:Uncorrectable Error count
  */
@@ -137,11 +139,29 @@ struct synps_edac_priv {
void __iomem *baseaddr;
char message[SYNPS_EDAC_MSG_SIZE];
struct synps_ecc_status stat;
+   const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
 };
 
 /**
+ * struct synps_platform_data -  synps platform data structure
+ * @synps_edac_geterror_info:  function pointer to synps edac error info
+ * @synps_edac_get_mtype:  function pointer to synps edac mtype
+ * @synps_edac_get_dtype:  function pointer to synps edac dtype
+ * @synps_edac_get_eccstate:   function pointer to synps edac eccstate
+ * @quirks:to differentiate IPs
+ */
+struct synps_platform_data {
+   int (*synps_edac_geterror_info)(void __iomem *base,
+   struct synps_ecc_status *p);
+   enum mem_type (*synps_edac_get_mtype)(const void __iomem *base);
+   enum dev_type (*synps_edac_get_dtype)(const void __iomem *base);
+   bool (*synps_edac_get_eccstate)(void __iomem *base);
+   int quirks;
+};
+
+/**
  * synps_edac_geterror_info - Get the current ecc error info
  * @base:  Pointer to the base address of the ddr memory controller
  * @p: Pointer to the synopsys ecc status structure
@@ -242,7 +262,8 @@ static void synps_edac_check(struct mem_ctl_info *mci)
struct synps_edac_priv *priv = mci->pvt_info;
int status;
 
-   status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = priv->p_data->synps_edac_geterror_info(priv->baseaddr,
+   &priv->stat);
if (status)
return;
 
@@ -372,10 +393,12 @@ static int synps_edac_init_csrows(struct mem_ctl_info 
*mci)
for (j = 0; j < csi->nr_channels; j++) {
dimm= csi->channels[j]->dimm;
dimm->edac_mode = EDAC_FLAG_SECDED;
-   dimm->mtype = synps_edac_get_mtype(priv->baseaddr);
+   dimm->mtype = priv->p_data->synps_edac_get_mtype(
+   priv->baseaddr);
dimm->nr_pages  = (size >> PAGE_SHIFT) / 
csi->nr_channels;
dimm->grain = SYNPS_EDAC_ERR_GRAIN;
-   dimm->dtype = synps_edac_get_dtype(priv->baseaddr);
+   dimm->dtype = priv->p_data->synps_edac_get_dtype(
+   priv->baseaddr);
}
}
 
@@ -423,6 +446,21 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci,
return status;
 }
 
+static const struct synps_platform_data zynq_edac_def = {
+   .synps_edac_geterror_info   = synps_edac_geterror_info,
+   .synps_edac_get_mtype   = synps_edac_get_mtype,
+   .synps_edac_get_dtype   = synps_edac_get_dtype,
+   .synps_edac_get_eccstate= synps_edac_get_eccstate,
+   .quirks = 0,
+};
+
+static const struct of_device_id synps_edac_match[] = {
+   { .compatible = "xlnx,zynq-ddrc-a05", .data = (void *)&zynq_edac_def },
+   { /* end of table */ }
+};
+
+MODULE_DEVICE_TABLE(of, synps_edac_match);
+
 /**
  * synps_edac_mc_probe - Check controller and bind driver
  * @pdev:  Pointer to the platform_device struct
@@ -440,13 +478,22 @@ static int synps_edac_mc_probe(struct platform_device 
*pdev)
int rc;
struct resource *res;
void __iomem *baseaddr;
+   const struct of_device_id *match;
+   const struct synps_platform_data *p_data;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
baseaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(baseaddr))
return PTR_ERR(baseaddr);
 
-   if (!synps_edac_get_eccstate(baseaddr)) {
+   match = of_match_node(synps_edac_match, pdev->dev.of_node);
+   if (!match && !match->data) {
+

[PATCH v3 0/4] EDAC: Enhancements to Synopsys EDAC driver

2018-08-02 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms.This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Changes in v3:
- The commit message in (2/4) is modified (Synopsys EDAC Driver -->
  ZynqMP DDRC)

Manish Narani (4):
  edac: synps: Add platform specific structures for ddrc controller
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node

 .../bindings/memory-controllers/synopsys.txt   |  27 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
 drivers/edac/Kconfig   |   2 +-
 drivers/edac/synopsys_edac.c   | 919 -
 4 files changed, 922 insertions(+), 33 deletions(-)

-- 
2.1.1



[PATCH v3 4/4] arm64: zynqmp: Add DDRC node

2018-08-02 Thread Manish Narani
This patch adds ddrc memory controller node in dts. The size mentioned
in dts is 0x3, because we need to access DDR_QOS INTR registers
located at fd090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index a091e6f..7d6a3cf 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH v3 3/4] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-08-02 Thread Manish Narani
This patch adds EDAC ECC support for ZynqMP DDRC IP. The patch also adds
support for ECC Error Injection in ZynqMP. The corrected and uncorrected
error interrupts support is added in this patch. The Row, Column, Bank,
Bank Group and Rank bits positions are determined via Address Map
registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 857 ++-
 2 files changed, 841 insertions(+), 18 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..b1fc7a16 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARM64
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index d4798e8..8a1c327 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "edac_module.h"
@@ -96,6 +97,170 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORT BIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST 0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON1_BANKGRP_SHIFT 28
+#define ECC_POISON1_BANKNR_SHIFT 24
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK 0x3
+#define ECC_UEPOISON_MASK 0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_DEV_CONFIG_MASK 0xC000
+#define DDRC_MSTR_DEV_CONFIG_SHIFT 30
+#define DDRC_MSTR_DEV_CONFIG_X4_MASK   0x0
+#define DDRC_MSTR_DEV_CONFIG_X8_MASK   0x1
+#define DDRC_MSTR_DEV_CONFIG_X16_MASK  0x2
+#define DDRC_MSTR_DEV_CONFIG_X32_MASK  0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#define ROW_MAX_VAL_MASK   0xF
+#define CO

[PATCH v3 2/4] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-08-02 Thread Manish Narani
This patch adds information of ZynqMP DDRC which reports the single bit
errors that are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v2 2/4] iio: adc: xilinx: limit pcap clock frequency value

2018-07-23 Thread Manish Narani
This patch limits the xadc pcap clock frequency value to be less than
200MHz. This fixes the issue when zynq is booted at higher frequency
values, pcap crosses the maximum limit of 200MHz(Fmax) as it is derived
from IOPLL.
If this limit is crossed it is required to alter the WEDGE and REDGE
bits of XADC_CFG register to make timings better in the interface. So to
avoid alteration of these bits every time, the pcap value should not
cross the Fmax limit.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index 23395fc..0dd306d 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -322,6 +322,7 @@ static irqreturn_t xadc_zynq_interrupt_handler(int irq, 
void *devid)
 
 #define XADC_ZYNQ_TCK_RATE_MAX 5000
 #define XADC_ZYNQ_IGAP_DEFAULT 20
+#define XADC_ZYNQ_PCAP_RATE_MAX 2
 
 static int xadc_zynq_setup(struct platform_device *pdev,
struct iio_dev *indio_dev, int irq)
@@ -332,6 +333,7 @@ static int xadc_zynq_setup(struct platform_device *pdev,
unsigned int div;
unsigned int igap;
unsigned int tck_rate;
+   int ret;
 
/* TODO: Figure out how to make igap and tck_rate configurable */
igap = XADC_ZYNQ_IGAP_DEFAULT;
@@ -343,6 +345,13 @@ static int xadc_zynq_setup(struct platform_device *pdev,
if (!pcap_rate)
return -EINVAL;
 
+   if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) {
+   ret = clk_set_rate(xadc->clk,
+  (unsigned long)XADC_ZYNQ_PCAP_RATE_MAX);
+   if (ret)
+   return ret;
+   }
+
if (tck_rate > pcap_rate / 2) {
div = 2;
} else {
@@ -368,6 +377,12 @@ static int xadc_zynq_setup(struct platform_device *pdev,
XADC_ZYNQ_CFG_REDGE | XADC_ZYNQ_CFG_WEDGE |
tck_div | XADC_ZYNQ_CFG_IGAP(igap));
 
+   if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) {
+   ret = clk_set_rate(xadc->clk, pcap_rate);
+   if (ret)
+   return ret;
+   }
+
return 0;
 }
 
-- 
2.1.1



[PATCH v2 1/4] iio: adc: xilinx: Check for return values in clk related functions

2018-07-23 Thread Manish Narani
This patch adds check for return values from clock related functions.
This was reported by static code analysis tool.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index 0127e85..23395fc 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -340,6 +340,8 @@ static int xadc_zynq_setup(struct platform_device *pdev,
xadc->zynq_intmask = ~0;
 
pcap_rate = clk_get_rate(xadc->clk);
+   if (!pcap_rate)
+   return -EINVAL;
 
if (tck_rate > pcap_rate / 2) {
div = 2;
@@ -887,6 +889,9 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
unsigned long clk_rate = xadc_get_dclk_rate(xadc);
unsigned int div;
 
+   if (!clk_rate)
+   return -EINVAL;
+
if (info != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
 
@@ -1237,8 +1242,10 @@ static int xadc_probe(struct platform_device *pdev)
goto err_free_irq;
 
/* Disable all alarms */
-   xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
-   XADC_CONF1_ALARM_MASK);
+   ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
+ XADC_CONF1_ALARM_MASK);
+   if (ret)
+   goto err_free_irq;
 
/* Set thresholds to min/max */
for (i = 0; i < 16; i++) {
-- 
2.1.1



[PATCH v2 3/4] iio: adc: xilinx: Remove platform_get_irq from xadc_remove function

2018-07-23 Thread Manish Narani
This patch avoids getting irq number in xadc_remove function. Instead
store 'irq' in xadc struct and use xadc->irq wherever needed.
This patch also resolves a warning reported by coverity where it asks to
check return value of platform_get_irq() for any errors in xadc_remove.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 10 +-
 drivers/iio/adc/xilinx-xadc.h  |  1 +
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index 0dd306d..44a2519 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1175,6 +1175,7 @@ static int xadc_probe(struct platform_device *pdev)
 
xadc = iio_priv(indio_dev);
xadc->ops = id->data;
+   xadc->irq = irq;
init_completion(&xadc->completion);
mutex_init(&xadc->mutex);
spin_lock_init(&xadc->lock);
@@ -1225,11 +1226,11 @@ static int xadc_probe(struct platform_device *pdev)
if (ret)
goto err_free_samplerate_trigger;
 
-   ret = xadc->ops->setup(pdev, indio_dev, irq);
+   ret = xadc->ops->setup(pdev, indio_dev, xadc->irq);
if (ret)
goto err_clk_disable_unprepare;
 
-   ret = request_irq(irq, xadc->ops->interrupt_handler, 0,
+   ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
dev_name(&pdev->dev), indio_dev);
if (ret)
goto err_clk_disable_unprepare;
@@ -1288,7 +1289,7 @@ static int xadc_probe(struct platform_device *pdev)
return 0;
 
 err_free_irq:
-   free_irq(irq, indio_dev);
+   free_irq(xadc->irq, indio_dev);
 err_clk_disable_unprepare:
clk_disable_unprepare(xadc->clk);
 err_free_samplerate_trigger:
@@ -1310,7 +1311,6 @@ static int xadc_remove(struct platform_device *pdev)
 {
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct xadc *xadc = iio_priv(indio_dev);
-   int irq = platform_get_irq(pdev, 0);
 
iio_device_unregister(indio_dev);
if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
@@ -1318,7 +1318,7 @@ static int xadc_remove(struct platform_device *pdev)
iio_trigger_free(xadc->convst_trigger);
iio_triggered_buffer_cleanup(indio_dev);
}
-   free_irq(irq, indio_dev);
+   free_irq(xadc->irq, indio_dev);
clk_disable_unprepare(xadc->clk);
cancel_delayed_work(&xadc->zynq_unmask_work);
kfree(xadc->data);
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
index 62edbda..8c00095 100644
--- a/drivers/iio/adc/xilinx-xadc.h
+++ b/drivers/iio/adc/xilinx-xadc.h
@@ -68,6 +68,7 @@ struct xadc {
spinlock_t lock;
 
struct completion completion;
+   int irq;
 };
 
 struct xadc_ops {
-- 
2.1.1



[PATCH v2 0/4] iio: adc: xilinx: XADC driver Enhancements and bug fixes

2018-07-23 Thread Manish Narani
This patch series resolves code style problems as reported by code analysis
tools.

Changes in v2:
- From the first version of patches, 2 patches are dropped in this
  series.
- In the v1 patch set, 1/4 was not required as the issue is in
  checkpatch.pl script and not in the code.
- In the v1 patch set 2/4 was applied on togreg branch of iio.git
- for 3/4 patch in v1 patch set, the patch is broken up in 2 patches
  in this series as per review comments. They are now 1/4 and 2/4 in
  this series.
- 4/4 patch in the v1 patch set was basically to resolve coverity
  warning for platform_get_irq() in xadc_remove function, but that was
  causing potential race condition. Fixed that in this series (3/4).
- A new patch is added in this series for moving request_irq() before
  enabling interrupts.


Manish Narani (4):
  iio: adc: xilinx: Check for return values in clk related functions
  iio: adc: xilinx: limit pcap clock frequency value
  iio: adc: xilinx: Remove platform_get_irq from xadc_remove function
  iio: adc: xilinx: Move request_irq before enabling interrupts

 drivers/iio/adc/xilinx-xadc-core.c | 40 +-
 drivers/iio/adc/xilinx-xadc.h  |  1 +
 2 files changed, 32 insertions(+), 9 deletions(-)

-- 
2.1.1



[PATCH v2 4/4] iio: adc: xilinx: Move request_irq before enabling interrupts

2018-07-23 Thread Manish Narani
Enabling the Interrupts before registering the irq handler is a bad
idea. This patch corrects the same for XADC driver.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index 44a2519..3f6be5a 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1226,15 +1226,15 @@ static int xadc_probe(struct platform_device *pdev)
if (ret)
goto err_free_samplerate_trigger;
 
-   ret = xadc->ops->setup(pdev, indio_dev, xadc->irq);
-   if (ret)
-   goto err_clk_disable_unprepare;
-
ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
dev_name(&pdev->dev), indio_dev);
if (ret)
goto err_clk_disable_unprepare;
 
+   ret = xadc->ops->setup(pdev, indio_dev, xadc->irq);
+   if (ret)
+   goto err_free_irq;
+
for (i = 0; i < 16; i++)
xadc_read_adc_reg(xadc, XADC_REG_THRESHOLD(i),
&xadc->threshold[i]);
-- 
2.1.1



[RFC PATCH] mmc: sdhci-of-arasan: Add auto tuning support for ZynqMP Platform

2018-01-30 Thread Manish Narani
This patch adds support of SD auto tuning for ZynqMP platform. Auto
tuning sequence sends tuning block to card when operating in UHS-1
modes. This resets the DLL and sends CMD19/CMD21 as a part of the auto
tuning process. Once the auto tuning process gets completed, reset the
DLL to load the newly obtained SDHC tuned tap value.

Signed-off-by: Manish Narani 
---
 .../devicetree/bindings/mmc/arasan,sdhci.txt   |   1 +
 drivers/mmc/host/sdhci-of-arasan.c | 219 -
 2 files changed, 219 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt 
b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
index 60481bf..7d29751 100644
--- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
@@ -14,6 +14,7 @@ Required Properties:
 - "arasan,sdhci-4.9a": generic Arasan SDHCI 4.9a PHY
 - "arasan,sdhci-5.1": generic Arasan SDHCI 5.1 PHY
 - "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1": rk3399 eMMC PHY
+- "xlnx,zynqmp-8.9a": Xilinx ZynqMP 8.9a PHY
   For this device it is strongly suggested to include 
arasan,soc-ctl-syscon.
   - reg: From mmc bindings: Register location and length.
   - clocks: From clock bindings: Handles to clock inputs.
diff --git a/drivers/mmc/host/sdhci-of-arasan.c 
b/drivers/mmc/host/sdhci-of-arasan.c
index 0720ea7..7673db4 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -24,15 +24,18 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "sdhci-pltfm.h"
 #include 
+#include 

 #define SDHCI_ARASAN_VENDOR_REGISTER   0x78

 #define VENDOR_ENHANCED_STROBE BIT(0)

 #define PHY_CLK_TOO_SLOW_HZ40
+#define MAX_TUNING_LOOP40

 /*
  * On some SoCs the syscon area has a feature where the upper 16-bits of
@@ -88,6 +91,7 @@ struct sdhci_arasan_data {
struct sdhci_host *host;
struct clk  *clk_ahb;
struct phy  *phy;
+   u32 device_id;
boolis_phy_on;

struct clk_hw   sdcardclk_hw;
@@ -157,6 +161,213 @@ static int sdhci_arasan_syscon_write(struct sdhci_host 
*host,
return ret;
 }

+/**
+ * arasan_zynqmp_dll_reset - Issue the DLL reset.
+ * @deviceid:  Unique Id of device
+ */
+void zynqmp_dll_reset(u8 deviceid)
+{
+   const struct zynqmp_eemi_ops *eemi_ops = get_eemi_ops();
+
+   if (!eemi_ops || !eemi_ops->ioctl)
+   return;
+
+   /* Issue DLL Reset */
+   if (deviceid == 0)
+   eemi_ops->ioctl(NODE_SD_0, IOCTL_SD_DLL_RESET,
+   PM_DLL_RESET_PULSE, 0, NULL);
+   else
+   eemi_ops->ioctl(NODE_SD_1, IOCTL_SD_DLL_RESET,
+   PM_DLL_RESET_PULSE, 0, NULL);
+}
+
+static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
+{
+   u16 clk;
+   unsigned long timeout;
+
+   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   clk &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+   /* Issue DLL Reset */
+   zynqmp_dll_reset(deviceid);
+
+   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   clk |= SDHCI_CLOCK_INT_EN;
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+   /* Wait max 20 ms */
+   timeout = 20;
+   while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+   & SDHCI_CLOCK_INT_STABLE)) {
+   if (timeout == 0) {
+   dev_err(mmc_dev(host->mmc),
+   ": Internal clock never stabilised.\n");
+   return;
+   }
+   timeout--;
+   mdelay(1);
+   }
+
+   clk |= SDHCI_CLOCK_CARD_EN;
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static int arasan_zynqmp_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+   struct mmc_host *mmc = host->mmc;
+   u16 ctrl;
+   int tuning_loop_counter = MAX_TUNING_LOOP;
+   int err = 0;
+   unsigned long flags;
+   unsigned int tuning_count = 0;
+
+   spin_lock_irqsave(&host->lock, flags);
+
+   if (host->tuning_mode == SDHCI_TUNING_MODE_1)
+   tuning_count = host->tuning_count;
+
+   ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+   ctrl |= SDHCI_CTRL_EXEC_TUNING;
+   if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
+   ctrl |= SDHCI_CTRL_TUNED_CLK;
+   sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+   mdelay(1);
+
+   arasan_zynqmp_dll_reset(host, sdhci_arasan->device_id);
+
+   /*
+* As

RE: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay values from DT

2018-07-09 Thread Manish Narani
Ping

> -Original Message-
> From: Manish Narani
> Sent: Thursday, June 21, 2018 6:25 PM
> To: Adrian Hunter ; robh...@kernel.org;
> catalin.mari...@arm.com; will.dea...@arm.com; m...@kernel.org;
> stefan.krsmano...@aggios.com; linux-arm-ker...@lists.infradead.org; linux-
> ker...@vger.kernel.org; linux-...@vger.kernel.org;
> devicet...@vger.kernel.org; Michal Simek ;
> ulf.hans...@linaro.org
> Cc: Srinivas Goud ; Anirudha Sarangi
> 
> Subject: RE: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay
> values from DT
> 
> Hi Adrian,
> 
> > -Original Message-
> > From: Adrian Hunter [mailto:adrian.hun...@intel.com]
> > Sent: Tuesday, June 19, 2018 5:08 PM
> > To: Manish Narani ; robh...@kernel.org;
> > catalin.mari...@arm.com; will.dea...@arm.com; m...@kernel.org;
> > stefan.krsmano...@aggios.com; linux-arm-ker...@lists.infradead.org;
> > linux- ker...@vger.kernel.org; linux-...@vger.kernel.org;
> > devicet...@vger.kernel.org; Michal Simek ;
> > ulf.hans...@linaro.org
> > Cc: Srinivas Goud ; Anirudha Sarangi
> > 
> > Subject: Re: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap
> > Delay values from DT
> >
> > On 14/06/18 08:38, Manish Narani wrote:
> > > Ping for RFC
> >
> > What is eemi?  Why aren't there patches for that?
> Eemi(Extensible Energy Management Interface) is a power management
> interface for ZynqMP core. The patches for the same are already in process of
> mainlining.
> https://lkml.org/lkml/2018/6/20/823
> 
> Thanks,
> Manish
> >
> > >
> > >> -Original Message-
> > >> From: Manish Narani [mailto:manish.nar...@xilinx.com]
> > >> Sent: Thursday, June 7, 2018 5:42 PM
> > >> To: robh...@kernel.org; mark.rutl...@arm.com;
> > >> catalin.mari...@arm.com; will.dea...@arm.com; m...@kernel.org;
> > >> stefan.krsmano...@aggios.com; linux-arm-ker...@lists.infradead.org;
> > >> linux-kernel@vger.kernel.org; linux- m...@vger.kernel.org;
> > >> devicet...@vger.kernel.org; adrian.hun...@intel.com;
> > >> michal.si...@xilinx.com; ulf.hans...@linaro.org
> > >> Cc: Manish Narani 
> > >> Subject: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap
> > >> Delay values from DT
> > >>
> > >> This patch adds support for reading Tap Delay values from Device
> > >> Tree and write them via eemi calls. The macros containing these tap
> > >> delay values are removed from the driver.
> > >>
> > >> Signed-off-by: Manish Narani 
> > >> ---
> > >>  drivers/mmc/host/sdhci-of-arasan.c | 131
> > >> +
> > >>  1 file changed, 131 insertions(+)
> > >>
> > >> diff --git a/drivers/mmc/host/sdhci-of-arasan.c
> > >> b/drivers/mmc/host/sdhci- of-arasan.c index e3332a5..fc0fd01 100644
> > >> --- a/drivers/mmc/host/sdhci-of-arasan.c
> > >> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> > >> @@ -36,6 +36,8 @@
> > >>
> > >>  #define PHY_CLK_TOO_SLOW_HZ 40
> > >>
> > >> +#define MMC_BANK2   0x2
> > >> +
> > >>  /*
> > >>   * On some SoCs the syscon area has a feature where the upper 16-bits of
> > >>   * each 32-bit register act as a write mask for the lower 16-bits.
> > >> This allows @@ -90,6 +92,10 @@ struct sdhci_arasan_data {
> > >>  struct sdhci_host *host;
> > >>  struct clk  *clk_ahb;
> > >>  struct phy  *phy;
> > >> +u32 mio_bank;
> > >> +u32 device_id;
> > >> +u32 itapdly[MMC_TIMING_MMC_HS400 + 1];
> > >> +u32 otapdly[MMC_TIMING_MMC_HS400 + 1];
> > >>  boolis_phy_on;
> > >>
> > >>  boolhas_cqe;
> > >> @@ -160,11 +166,36 @@ static int sdhci_arasan_syscon_write(struct
> > >> sdhci_host *host,
> > >>  return ret;
> > >>  }
> > >>
> > >> +/**
> > >> + * arasan_zynqmp_set_tap_delay - Program the tap delays.
> > >> + * @deviceid:   Unique Id of device
> > >> + * @itap_delay: Input Tap Delay
> > >> + * @oitap_delay:Output Tap Delay
> > >> + */
> > >> +static void arasan_zynqmp_set_tap_delay(u8 deviceid, u8
> > >> +itap_delay,
> > >> +u8
> > >> +otap_delay) {
> > 

RE: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay values from DT

2018-06-13 Thread Manish Narani
Ping for RFC

> -Original Message-
> From: Manish Narani [mailto:manish.nar...@xilinx.com]
> Sent: Thursday, June 7, 2018 5:42 PM
> To: robh...@kernel.org; mark.rutl...@arm.com; catalin.mari...@arm.com;
> will.dea...@arm.com; m...@kernel.org; stefan.krsmano...@aggios.com;
> linux-arm-ker...@lists.infradead.org; linux-kernel@vger.kernel.org; linux-
> m...@vger.kernel.org; devicet...@vger.kernel.org;
> adrian.hun...@intel.com; michal.si...@xilinx.com; ulf.hans...@linaro.org
> Cc: Manish Narani 
> Subject: [RFC PATCH 3/3] sdhci: arasan: Add support to read Tap Delay values
> from DT
> 
> This patch adds support for reading Tap Delay values from Device Tree and
> write them via eemi calls. The macros containing these tap delay values are
> removed from the driver.
> 
> Signed-off-by: Manish Narani 
> ---
>  drivers/mmc/host/sdhci-of-arasan.c | 131
> +
>  1 file changed, 131 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-
> of-arasan.c
> index e3332a5..fc0fd01 100644
> --- a/drivers/mmc/host/sdhci-of-arasan.c
> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> @@ -36,6 +36,8 @@
> 
>  #define PHY_CLK_TOO_SLOW_HZ  40
> 
> +#define MMC_BANK20x2
> +
>  /*
>   * On some SoCs the syscon area has a feature where the upper 16-bits of
>   * each 32-bit register act as a write mask for the lower 16-bits.  This 
> allows
> @@ -90,6 +92,10 @@ struct sdhci_arasan_data {
>   struct sdhci_host *host;
>   struct clk  *clk_ahb;
>   struct phy  *phy;
> + u32 mio_bank;
> + u32 device_id;
> + u32 itapdly[MMC_TIMING_MMC_HS400 + 1];
> + u32 otapdly[MMC_TIMING_MMC_HS400 + 1];
>   boolis_phy_on;
> 
>   boolhas_cqe;
> @@ -160,11 +166,36 @@ static int sdhci_arasan_syscon_write(struct
> sdhci_host *host,
>   return ret;
>  }
> 
> +/**
> + * arasan_zynqmp_set_tap_delay - Program the tap delays.
> + * @deviceid:Unique Id of device
> + * @itap_delay:  Input Tap Delay
> + * @oitap_delay: Output Tap Delay
> + */
> +static void arasan_zynqmp_set_tap_delay(u8 deviceid, u8 itap_delay, u8
> +otap_delay) {
> + const struct zynqmp_eemi_ops *eemi_ops =
> zynqmp_pm_get_eemi_ops();
> + u32 node_id = (deviceid == 0) ? NODE_SD_0 : NODE_SD_1;
> +
> + if (!eemi_ops || !eemi_ops->ioctl)
> + return;
> +
> + if (itap_delay)
> + eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
> + PM_TAPDELAY_INPUT, itap_delay, NULL);
> +
> + if (otap_delay)
> + eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
> + PM_TAPDELAY_OUTPUT, otap_delay, NULL);
> }
> +
>  static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int
> clock)  {
>   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>   struct sdhci_arasan_data *sdhci_arasan =
> sdhci_pltfm_priv(pltfm_host);
>   bool ctrl_phy = false;
> + u8 itap_delay;
> + u8 otap_delay;
> 
>   if (!IS_ERR(sdhci_arasan->phy)) {
>   if (!sdhci_arasan->is_phy_on && clock <=
> PHY_CLK_TOO_SLOW_HZ) { @@ -200,6 +231,16 @@ static void
> sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)
>   }
>   }
> 
> + if (host->version >= SDHCI_SPEC_300) {
> + if ((host->timing != MMC_TIMING_LEGACY) &&
> + (host->timing != MMC_TIMING_UHS_SDR12)) {
> + itap_delay = sdhci_arasan->itapdly[host->timing];
> + otap_delay = sdhci_arasan->otapdly[host->timing];
> + arasan_zynqmp_set_tap_delay(sdhci_arasan-
> >device_id,
> + itap_delay, otap_delay);
> + }
> + }
> +
>   if (ctrl_phy && sdhci_arasan->is_phy_on) {
>   phy_power_off(sdhci_arasan->phy);
>   sdhci_arasan->is_phy_on = false;
> @@ -456,6 +497,7 @@ static const struct of_device_id
> sdhci_arasan_of_match[] = {
>   { .compatible = "arasan,sdhci-8.9a" },
>   { .compatible = "arasan,sdhci-5.1" },
>   { .compatible = "arasan,sdhci-4.9a" },
> + { .compatible = "xlnx,zynqmp-8.9a" },
> 
>   { /* sentinel */ }
>  };
> @@ -641,6 +683,74 @@ static void sdhci_arasan_unregister_sdclk(struct
> device *dev)
>   of_clk_del_provider(dev->of_node);
>  }
> 
> +/**
> + * arasan_zynqmp_dt_parse_tap_delays - Read Tap Delay val

RE: [PATCH v4 1/4] edac: synps: Add platform specific structures for ddrc controller

2018-08-18 Thread Manish Narani
Ping.
 
> -Original Message-
> From: Manish Narani [mailto:manish.nar...@xilinx.com]
> Sent: Saturday, August 4, 2018 2:56 PM
> To: robh...@kernel.org; mark.rutl...@arm.com; catalin.mari...@arm.com;
> will.dea...@arm.com; Michal Simek ; b...@alien8.de;
> mche...@kernel.org; m...@kernel.org; Edgar Iglesias ;
> Shubhrajyoti Datta ; Naga Sureshkumar Relli
> ; Bharat Kumar Gogada ;
> stefan.krsmano...@aggios.com
> Cc: Srinivas Goud ; Anirudha Sarangi
> ; linux-kernel@vger.kernel.org;
> devicet...@vger.kernel.org; linux-arm-ker...@lists.infradead.org; linux-
> e...@vger.kernel.org; Manish Narani 
> Subject: [PATCH v4 1/4] edac: synps: Add platform specific structures for ddrc
> controller
> 
> Add platform specific structures, so that we can add different IP support 
> later
> using quirks.
> 
> Signed-off-by: Manish Narani 
> ---
>  drivers/edac/synopsys_edac.c | 83 ++--
> 
>  1 file changed, 65 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index
> 0c9c59e..b3c54e7 100644
> --- a/drivers/edac/synopsys_edac.c
> +++ b/drivers/edac/synopsys_edac.c
> @@ -22,6 +22,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
> 
>  #include "edac_module.h"
> 
> @@ -130,6 +131,7 @@ struct synps_ecc_status {
>   * @baseaddr:Base address of the DDR controller
>   * @message: Buffer for framing the event specific info
>   * @stat:ECC status information
> + * @p_data:  Pointer to platform data
>   * @ce_cnt:  Correctable Error count
>   * @ue_cnt:  Uncorrectable Error count
>   */
> @@ -137,24 +139,47 @@ struct synps_edac_priv {
>   void __iomem *baseaddr;
>   char message[SYNPS_EDAC_MSG_SIZE];
>   struct synps_ecc_status stat;
> + const struct synps_platform_data *p_data;
>   u32 ce_cnt;
>   u32 ue_cnt;
>  };
> 
>  /**
> + * struct synps_platform_data -  synps platform data structure
> + * @edac_geterror_info:  function pointer to synps edac error info
> + * @edac_get_mtype:  function pointer to synps edac mtype
> + * @edac_get_dtype:  function pointer to synps edac dtype
> + * @edac_get_eccstate:   function pointer to synps edac eccstate
> + * @quirks:  to differentiate IPs
> + */
> +struct synps_platform_data {
> + int (*edac_geterror_info)(struct synps_edac_priv *priv);
> + enum mem_type (*edac_get_mtype)(const void __iomem *base);
> + enum dev_type (*edac_get_dtype)(const void __iomem *base);
> + bool (*edac_get_eccstate)(void __iomem *base);
> + int quirks;
> +};
> +
> +/**
>   * synps_edac_geterror_info - Get the current ecc error info
> - * @base:Pointer to the base address of the ddr memory controller
> - * @p:   Pointer to the synopsys ecc status structure
> + * @priv:Pointer to DDR memory controller private instance data
>   *
>   * Determines there is any ecc error or not
>   *
>   * Return: one if there is no error otherwise returns zero
>   */
> -static int synps_edac_geterror_info(void __iomem *base,
> - struct synps_ecc_status *p)
> +static int synps_edac_geterror_info(struct synps_edac_priv *priv)
>  {
> + void __iomem *base;
> + struct synps_ecc_status *p;
>   u32 regval, clearval = 0;
> 
> + if (!priv)
> + return 1;
> +
> + base = priv->baseaddr;
> + p = &priv->stat;
> +
>   regval = readl(base + STAT_OFST);
>   if (!regval)
>   return 1;
> @@ -240,9 +265,10 @@ static void synps_edac_handle_error(struct
> mem_ctl_info *mci,  static void synps_edac_check(struct mem_ctl_info *mci)  {
>   struct synps_edac_priv *priv = mci->pvt_info;
> + const struct synps_platform_data *p_data = priv->p_data;
>   int status;
> 
> - status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
> + status = p_data->edac_geterror_info(priv);
>   if (status)
>   return;
> 
> @@ -362,6 +388,7 @@ static int synps_edac_init_csrows(struct mem_ctl_info
> *mci)
>   struct csrow_info *csi;
>   struct dimm_info *dimm;
>   struct synps_edac_priv *priv = mci->pvt_info;
> + const struct synps_platform_data *p_data = priv->p_data;
>   u32 size;
>   int row, j;
> 
> @@ -370,12 +397,13 @@ static int synps_edac_init_csrows(struct
> mem_ctl_info *mci)
>   size = synps_edac_get_memsize();
> 
>   for (j = 0; j < csi->nr_channels; j++) {
> - dimm= csi->channels[j]->dimm;
> + dimm = csi->chan

RE: [PATCH v4 4/4] arm64: zynqmp: Add DDRC node

2018-08-18 Thread Manish Narani
Ping.

> -Original Message-
> From: Manish Narani [mailto:manish.nar...@xilinx.com]
> Sent: Saturday, August 4, 2018 2:56 PM
> To: robh...@kernel.org; mark.rutl...@arm.com; catalin.mari...@arm.com;
> will.dea...@arm.com; Michal Simek ; b...@alien8.de;
> mche...@kernel.org; m...@kernel.org; Edgar Iglesias ;
> Shubhrajyoti Datta ; Naga Sureshkumar Relli
> ; Bharat Kumar Gogada ;
> stefan.krsmano...@aggios.com
> Cc: Srinivas Goud ; Anirudha Sarangi
> ; linux-kernel@vger.kernel.org;
> devicet...@vger.kernel.org; linux-arm-ker...@lists.infradead.org; linux-
> e...@vger.kernel.org; Manish Narani 
> Subject: [PATCH v4 4/4] arm64: zynqmp: Add DDRC node
> 
> This patch adds ddrc memory controller node in dts. The size mentioned in dts
> is 0x3, because we need to access DDR_QOS INTR registers located at
> fd090208 from this driver.
> 
> Signed-off-by: Manish Narani 
> ---
>  arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
> b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
> index a091e6f..7d6a3cf 100644
> --- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
> +++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
> @@ -355,6 +355,13 @@
>   xlnx,bus-width = <64>;
>   };
> 
> + mc: memory-controller@fd07 {
> + compatible = "xlnx,zynqmp-ddrc-2.40a";
> + reg = <0x0 0xfd07 0x0 0x3>;
> + interrupt-parent = <&gic>;
> + interrupts = <0 112 4>;
> + };
> +
>   gem0: ethernet@ff0b {
>   compatible = "cdns,zynqmp-gem", "cdns,gem";
>   status = "disabled";
> --
> 2.1.1



RE: [PATCH v10 0/6] EDAC: Enhancements to Synopsys EDAC driver

2018-11-06 Thread Manish Narani
Hi Boris,

> -Original Message-
> From: Borislav Petkov [mailto:b...@alien8.de]
> Sent: Tuesday, November 6, 2018 3:34 PM
> To: Manish Narani 
> Cc: robh...@kernel.org; mark.rutl...@arm.com; Michal Simek
> ; mche...@kernel.org; amit.kuche...@linaro.org;
> sudeep.ho...@arm.com; leoyang...@nxp.com; devicet...@vger.kernel.org;
> linux-kernel@vger.kernel.org; linux-arm-ker...@lists.infradead.org; linux-
> e...@vger.kernel.org
> Subject: Re: [PATCH v10 0/6] EDAC: Enhancements to Synopsys EDAC driver
> 
> On Thu, Oct 25, 2018 at 11:36:55AM +0530, Manish Narani wrote:
> > Change in v10:
> > - Moved the checking for ce_cnt and ue_cnt before the readl() call
> > - Aligned arguments on the opening brace in setup_irq()
> >
> > Manish Narani (6):
> >   edac: synopsys: Add error handling for NULL in probe()
> >   dt: bindings: Document ZynqMP DDRC in Synopsys documentation
> >   edac: synopsys: Add macro defines for ZynqMP DDRC
> >   edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
> >   arm64: zynqmp: Add DDRC node
> >   edac: synopsys: Add Error Injection support for ZynqMP DDRC
> >
> >  .../bindings/memory-controllers/synopsys.txt   |  27 +-
> >  arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
> >  drivers/edac/Kconfig   |   2 +-
> >  drivers/edac/synopsys_edac.c   | 911 
> > -
> >  4 files changed, 918 insertions(+), 29 deletions(-)
> 
> Ok, patches pushed here:
> 
> (minus https://lkml.kernel.org/r/1540447621-22870-6-git-send-email-
> manish.nar...@xilinx.com)
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git/log/?h=edac-for-4.21-
> synps
> 
Thanks a lot for your support.

> Please run this on the hw before I queue it for linux-next.
I have tested this and verified as working fine on hardware. You can go ahead 
and queue it for linux-next.

Thanks,
Manish


[PATCH v9 3/6] edac: synopsys: Add macro defines for ZynqMP DDRC

2018-10-14 Thread Manish Narani
Add macro defines for ZynqMP DDR controller. These macros will be used
for ZynqMP ECC operations.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 168 +++
 1 file changed, 168 insertions(+)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0005ef3..d1999e0 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -97,6 +97,174 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORTBIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON0_RANK_MASK  BIT(24)
+#define ECC_POISON0_COLUMN_SHIFT   0
+#define ECC_POISON0_COLUMN_MASK0xFFF
+#define ECC_POISON1_BG_SHIFT   28
+#define ECC_POISON1_BG_MASK0x3000
+#define ECC_POISON1_BANKNR_SHIFT   24
+#define ECC_POISON1_BANKNR_MASK0x700
+#define ECC_POISON1_ROW_SHIFT  0
+#define ECC_POISON1_ROW_MASK   0x3
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK  0x3
+#define ECC_UEPOISON_MASK  0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_CFG_MASK 0xC000
+#define DDRC_MSTR_CFG_SHIFT30
+#define DDRC_MSTR_CFG_X4_MASK  0x0
+#define DDRC_MSTR_CFG_X8_MASK  0x1
+#define DDRC_MSTR_CFG_X16_MASK 0x2
+#define DDRC_MSTR_CFG_X32_MASK 0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#de

[PATCH v9 0/6] EDAC: Enhancements to Synopsys EDAC driver

2018-10-14 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms. This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Changes in v3:
- The commit message in (2/4) is modified (Synopsys EDAC Driver -->
  ZynqMP DDRC)

Changes in v4:
- Updated the commit message in (1/4)
- Renamed function pointer names removing 'synps_' in (1/4)
- Shortened unnecessary long lines as per the review comment on (1/4)

Changes in v5:
- Updated the commit message in (2/4) and (4/4).
- Removed the unnecessary check for match data in probe() in (1/4)
- Some Indentation changes for better readability in (1/4) and (3/4)
- Removed repeated code in (3/4)
- Used 'zynq' and 'zynqmp' instead of 'synps_enh_edac' in function names

Changes in v6:
- Splitted the patches according to functionalities
- Addressed code style comments from v5 review
- Moved the Error Injection to CONFIG_EDAC_DEBUG mode

Changes in v7:
- Included DTS patch (6/7) which was missed in v6 patch set

Changes in v8:
- patch (1/7) from v7 is split in to 3 different logically different 
patches
1. functional changes like code cleanup
2. functions renaming
3. comments cleanup
- Added a separate patch (4) for making always successful functions as 
void
- Corrected 'Too many parentheses' review comment in patch (5)
- Corrected comments as per the v7 review feedback
- Made dedicated functions for IRQ setup, IRQ enable and IRQ disable in 
patch (8)
- Addressed review comments in patch (10)

Changes in v9:
- Added check for return value of of_device_get_match_data() function
  in (1/6).
- From v8 the first 5 patches are removed in this series as they are
  applied on:

https://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git/?h=edac-for-4.20-synps
- Updated Kconfig to check for ARCH_ZYNQMP instead of ARM64

Manish Narani (6):
  edac: synopsys: Add error handling for NULL in probe()
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add macro defines for ZynqMP DDRC
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node
  edac: synopsys: Add Error Injection support for ZynqMP DDRC

 .../bindings/memory-controllers/synopsys.txt   |  27 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
 drivers/edac/Kconfig   |   2 +-
 drivers/edac/synopsys_edac.c   | 913 -
 4 files changed, 920 insertions(+), 29 deletions(-)

-- 
2.1.1



[PATCH v9 4/6] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-10-14 Thread Manish Narani
Add EDAC ECC support for ZynqMP DDRC IP. The IP supports interrupts for
corrected and uncorrected errors. Add interrupt handlers for the same.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 324 ---
 2 files changed, 308 insertions(+), 18 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..7c40eb2 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARCH_ZYNQMP
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index d1999e0..603c4bd 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -272,6 +273,8 @@
  * @bank:  Bank number.
  * @bitpos:Bit position.
  * @data:  Data causing the error.
+ * @bankgrpnr: Bank group number.
+ * @blknr: Block number.
  */
 struct ecc_error_info {
u32 row;
@@ -279,6 +282,8 @@ struct ecc_error_info {
u32 bank;
u32 bitpos;
u32 data;
+   u32 bankgrpnr;
+   u32 blknr;
 };
 
 /**
@@ -385,6 +390,66 @@ static int zynq_get_error_info(struct synps_edac_priv 
*priv)
 }
 
 /**
+ * zynqmp_get_error_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Return: one if there is no error otherwise returns zero.
+ */
+static int zynqmp_get_error_info(struct synps_edac_priv *priv)
+{
+   struct synps_ecc_status *p;
+   u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
+
+   regval = readl(base + ECC_STAT_OFST);
+   if (!regval)
+   return 1;
+
+   p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
+   p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
+   p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
+
+   regval = readl(base + ECC_CEADDR0_OFST);
+   if (!p->ce_cnt)
+   goto ue_err;
+
+   p->ceinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_CEADDR1_OFST);
+   p->ceinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ceinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ceinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ceinfo.data = readl(base + ECC_CSYND0_OFST);
+   edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n",
+readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST),
+readl(base + ECC_CSYND2_OFST));
+ue_err:
+   regval = readl(base + ECC_UEADDR0_OFST);
+   if (!p->ue_cnt)
+   goto out;
+
+   p->ueinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_UEADDR1_OFST);
+   p->ueinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ueinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ueinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ueinfo.data = readl(base + ECC_UESYND0_OFST);
+out:
+   clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT;
+   clearval |= ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT;
+   writel(clearval, base + ECC_CLR_OFST);
+   writel(0x0, base + ECC_CLR_OFST);
+
+   return 0;
+}
+
+/**
  * handle_error - Handle Correctable and Uncorrectable errors.
  * @mci:   EDAC memory controller instance.
  * @p: Synopsys ECC status structure.
@@ -398,9 +463,25 @@ static void handle_error(struct mem_ctl_info *mci, struct 
synps_ecc_status *p)
 
if (p->ce_cnt) {
pinf = &p->ceinfo;
-   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-"DDR ECC error type :%s Row %d Bank %d Col %d ",
-"CE", pinf->row, pinf->bank, pinf->col);
+   if (!priv->p_data->quirks) {
+   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
+"DDR ECC error type:%s Row %d Bank %d Col %d ",
+ "CE", pinf->row, pinf->bank, pinf->col);
+   snprintf(priv->message, SYN

[PATCH v9 5/6] arm64: zynqmp: Add DDRC node

2018-10-14 Thread Manish Narani
Add ddrc memory controller node in dts. The size mentioned in dts is
0x3, because we need to access DDR_QOS INTR registers located at
0xFD090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 29ce234..a81d3b16 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH v9 6/6] edac: synopsys: Add Error Injection support for ZynqMP DDRC

2018-10-14 Thread Manish Narani
Add support for Error Injection for ZynqMP DDRC IP. For injecting
errors, the Row, Column, Bank, Bank Group and Rank bits positions are
determined via Address Map registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 420 ++-
 1 file changed, 413 insertions(+), 7 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 603c4bd..1f86d5e 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -302,12 +302,18 @@ struct synps_ecc_status {
 
 /**
  * struct synps_edac_priv - DDR memory controller private instance data.
- * @baseaddr:  Base address of the DDR controller.
- * @message:   Buffer for framing the event specific info.
- * @stat:  ECC status information.
- * @p_data:Platform data.
- * @ce_cnt:Correctable Error count.
- * @ue_cnt:Uncorrectable Error count.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @p_data:Platform data.
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
+ * @poison_addr:   Data poison address.
+ * @row_shift: Bit shifts for row bit.
+ * @col_shift: Bit shifts for column bit.
+ * @bank_shift:Bit shifts for bank bit.
+ * @bankgrp_shift: Bit shifts for bank group bit.
+ * @rank_shift:Bit shifts for rank bit.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -316,6 +322,14 @@ struct synps_edac_priv {
const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
+#ifdef CONFIG_EDAC_DEBUG
+   ulong poison_addr;
+   u32 row_shift[18];
+   u32 col_shift[14];
+   u32 bank_shift[3];
+   u32 bankgrp_shift[2];
+   u32 rank_shift[1];
+#endif
 };
 
 /**
@@ -877,7 +891,11 @@ static const struct synps_platform_data zynqmp_edac_def = {
.get_mtype  = zynqmp_get_mtype,
.get_dtype  = zynqmp_get_dtype,
.get_ecc_state  = zynqmp_get_ecc_state,
-   .quirks = DDR_ECC_INTR_SUPPORT,
+   .quirks = (DDR_ECC_INTR_SUPPORT
+#ifdef CONFIG_EDAC_DEBUG
+ | DDR_ECC_DATA_POISON_SUPPORT
+#endif
+ ),
 };
 
 static const struct of_device_id synps_edac_match[] = {
@@ -896,6 +914,375 @@ static const struct of_device_id synps_edac_match[] = {
 
 MODULE_DEVICE_TABLE(of, synps_edac_match);
 
+#ifdef CONFIG_EDAC_DEBUG
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/**
+ * ddr_poison_setup -  Update poison registers.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Update poison registers as per DDR mapping.
+ * Return: none.
+ */
+static void ddr_poison_setup(struct synps_edac_priv *priv)
+{
+   int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
+   int index;
+   ulong hif_addr = 0;
+
+   hif_addr = priv->poison_addr >> 3;
+
+   for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
+   if (priv->row_shift[index])
+   row |= (((hif_addr >> priv->row_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_COL_SHIFT; index++) {
+   if (priv->col_shift[index] || index < 3)
+   col |= (((hif_addr >> priv->col_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) {
+   if (priv->bank_shift[index])
+   bank |= (((hif_addr >> priv->bank_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) {
+   if (priv->bankgrp_shift[index])
+   bankgrp |= (((hif_addr >> priv->bankgrp_shift[index])
+   & BIT(0)) << index);
+   else
+   break;
+   }
+
+   if (priv->rank_shift[0])
+   rank = (hif_addr >> priv->rank_shift[0]) & BIT(0);
+
+   regval = (rank << ECC_POISON0_RANK_SHIFT) & ECC_POISON0_RANK_MASK;
+   regval |= (col << ECC_POISON0_COLUMN_SHIFT) & ECC_POISON0_COLUMN_MASK;
+   writel(regval, priv->baseaddr + ECC_POISON0_OFST);
+
+   regval = (bankgrp << ECC_POISON1_BG_SHIFT) & ECC_POISON1_BG_MASK;
+   regval |= (bank << ECC_POISON1_BANKNR_SHIFT) & ECC_PO

[PATCH v9 1/6] edac: synopsys: Add error handling for NULL in probe()

2018-10-14 Thread Manish Narani
The function of_device_get_match_data() can return NULL in case of
error. Add error handling for the same in probe().

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 1c3795d..0005ef3 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -477,6 +477,9 @@ static int mc_probe(struct platform_device *pdev)
return PTR_ERR(baseaddr);
 
p_data = of_device_get_match_data(&pdev->dev);
+   if (!p_data)
+   return -ENODEV;
+
if (!p_data->get_ecc_state(baseaddr)) {
edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n");
return -ENXIO;
-- 
2.1.1



[PATCH v9 2/6] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-10-14 Thread Manish Narani
Add information of ZynqMP DDRC which reports the single bit errors that
are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
Reviewed-by: Rob Herring 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v8 01/10] edac: synopsys: Update the driver code for better readability

2018-10-04 Thread Manish Narani
Modify the driver with some changes for code clean up. Update the debug
messages for EDAC errors reported. Increase the indentation of the
macros for better readability.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 104 +--
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0c9c59e..1936c73 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -26,74 +26,74 @@
 #include "edac_module.h"
 
 /* Number of cs_rows needed per memory controller */
-#define SYNPS_EDAC_NR_CSROWS   1
+#define SYNPS_EDAC_NR_CSROWS   1
 
 /* Number of channels per memory controller */
-#define SYNPS_EDAC_NR_CHANS1
+#define SYNPS_EDAC_NR_CHANS1
 
 /* Granularity of reported error in bytes */
-#define SYNPS_EDAC_ERR_GRAIN   1
+#define SYNPS_EDAC_ERR_GRAIN   1
 
-#define SYNPS_EDAC_MSG_SIZE256
+#define SYNPS_EDAC_MSG_SIZE256
 
-#define SYNPS_EDAC_MOD_STRING  "synps_edac"
-#define SYNPS_EDAC_MOD_VER "1"
+#define SYNPS_EDAC_MOD_STRING  "synps_edac"
+#define SYNPS_EDAC_MOD_VER "1"
 
 /* Synopsys DDR memory controller registers that are relevant to ECC */
-#define CTRL_OFST  0x0
-#define T_ZQ_OFST  0xA4
+#define CTRL_OFST  0x0
+#define T_ZQ_OFST  0xA4
 
 /* ECC control register */
-#define ECC_CTRL_OFST  0xC4
+#define ECC_CTRL_OFST  0xC4
 /* ECC log register */
-#define CE_LOG_OFST0xC8
+#define CE_LOG_OFST0xC8
 /* ECC address register */
-#define CE_ADDR_OFST   0xCC
+#define CE_ADDR_OFST   0xCC
 /* ECC data[31:0] register */
-#define CE_DATA_31_0_OFST  0xD0
+#define CE_DATA_31_0_OFST  0xD0
 
 /* Uncorrectable error info registers */
-#define UE_LOG_OFST0xDC
-#define UE_ADDR_OFST   0xE0
-#define UE_DATA_31_0_OFST  0xE4
+#define UE_LOG_OFST0xDC
+#define UE_ADDR_OFST   0xE0
+#define UE_DATA_31_0_OFST  0xE4
 
-#define STAT_OFST  0xF0
-#define SCRUB_OFST 0xF4
+#define STAT_OFST  0xF0
+#define SCRUB_OFST 0xF4
 
 /* Control register bit field definitions */
-#define CTRL_BW_MASK   0xC
-#define CTRL_BW_SHIFT  2
+#define CTRL_BW_MASK   0xC
+#define CTRL_BW_SHIFT  2
 
-#define DDRCTL_WDTH_16 1
-#define DDRCTL_WDTH_32 0
+#define DDRCTL_WDTH_16 1
+#define DDRCTL_WDTH_32 0
 
 /* ZQ register bit field definitions */
-#define T_ZQ_DDRMODE_MASK  0x2
+#define T_ZQ_DDRMODE_MASK  0x2
 
 /* ECC control register bit field definitions */
-#define ECC_CTRL_CLR_CE_ERR0x2
-#define ECC_CTRL_CLR_UE_ERR0x1
+#define ECC_CTRL_CLR_CE_ERR0x2
+#define ECC_CTRL_CLR_UE_ERR0x1
 
 /* ECC correctable/uncorrectable error log register definitions */
-#define LOG_VALID  0x1
-#define CE_LOG_BITPOS_MASK 0xFE
-#define CE_LOG_BITPOS_SHIFT1
+#define LOG_VALID  0x1
+#define CE_LOG_BITPOS_MASK 0xFE
+#define CE_LOG_BITPOS_SHIFT1
 
 /* ECC correctable/uncorrectable error address register definitions */
-#define ADDR_COL_MASK  0xFFF
-#define ADDR_ROW_MASK  0x000
-#define ADDR_ROW_SHIFT 12
-#define ADDR_BANK_MASK 0x7000
-#define ADDR_BANK_SHIFT28
+#define ADDR_COL_MASK  0xFFF
+#define ADDR_ROW_MASK  0x000
+#define ADDR_ROW_SHIFT 12
+#define ADDR_BANK_MASK 0x7000
+#define ADDR_BANK_SHIFT28
 
 /* ECC statistic register definitions */
-#define STAT_UECNT_MASK0xFF
-#define STAT_CECNT_MASK0xFF00
-#define STAT_CECNT_SHIFT   8
+#define STAT_UECNT_MASK0xFF
+#define STAT_CECNT_MASK0xFF00
+#define STAT_CECNT_SHIFT   8
 
 /* ECC scrub register definitions */
-#define SCRUB_MODE_MASK0x7
-#define SCRUB_MODE_SECDED  0x4
+#define SCRUB_MODE_MASK0x7
+#define SCRUB_MODE_SECDED  0x4
 
 /**
  * struct ecc_error_info - ECC error log information
@@ -172,7 +172,7 @@ static int synps_edac_geterror_info(void __iomem *base,
p->ceinfo.col = regval & ADDR_COL_MASK;
p->ceinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT;
p->ceinfo.data = readl(base + CE_DATA_31_0_OFST);
-   edac_dbg(3, "ce bit position: %d data: %d\n", p->ceinfo.bitpos,
+   edac_dbg(3, "CE bit position: %d data: %d\n", p->ceinfo.bitpos,
 p->ceinfo.data);
clear

[PATCH v8 04/10] edac: synopsys: Make return type void for functions always returning 0

2018-10-04 Thread Manish Narani
The current driver has functions which are always returning 0. Those
functions can be modified to void.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 22 --
 1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 7db5928..675155f 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -352,10 +352,8 @@ static enum mem_type edac_get_mtype(const void __iomem 
*base)
  *
  * Initializes the chip select rows associated with the EDAC memory
  * controller instance.
- *
- * Return: Unconditionally 0.
  */
-static int edac_init_csrows(struct mem_ctl_info *mci)
+static void edac_init_csrows(struct mem_ctl_info *mci)
 {
struct synps_edac_priv *priv = mci->pvt_info;
struct csrow_info *csi;
@@ -376,8 +374,6 @@ static int edac_init_csrows(struct mem_ctl_info *mci)
dimm->dtype = edac_get_dtype(priv->baseaddr);
}
}
-
-   return 0;
 }
 
 /**
@@ -388,13 +384,10 @@ static int edac_init_csrows(struct mem_ctl_info *mci)
  * Performs initialization of the EDAC memory controller instance and
  * related driver-private data associated with the memory controller the
  * instance is bound to.
- *
- * Return: Always zero.
  */
-static int edac_mc_init(struct mem_ctl_info *mci,
+static void edac_mc_init(struct mem_ctl_info *mci,
 struct platform_device *pdev)
 {
-   int status;
struct synps_edac_priv *priv;
 
mci->pdev = &pdev->dev;
@@ -416,9 +409,7 @@ static int edac_mc_init(struct mem_ctl_info *mci,
mci->edac_check = edac_check;
mci->ctl_page_to_phys = NULL;
 
-   status = edac_init_csrows(mci);
-
-   return status;
+   edac_init_csrows(mci);
 }
 
 /**
@@ -466,12 +457,7 @@ static int synps_edac_mc_probe(struct platform_device 
*pdev)
 
priv = mci->pvt_info;
priv->baseaddr = baseaddr;
-   rc = edac_mc_init(mci, pdev);
-   if (rc) {
-   edac_printk(KERN_ERR, EDAC_MC,
-   "Failed to initialize instance\n");
-   goto free_edac_mc;
-   }
+   edac_mc_init(mci, pdev);
 
rc = edac_mc_add_mc(mci);
if (rc) {
-- 
2.1.1



[PATCH v8 05/10] edac: synps: Add platform specific structures for ddrc controller

2018-10-04 Thread Manish Narani
Add platform specific structures, so that we can add different IP
support later using quirks.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 91 +++-
 1 file changed, 65 insertions(+), 26 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 675155f..f0f4704 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "edac_module.h"
 
@@ -130,6 +132,7 @@ struct synps_ecc_status {
  * @baseaddr:  Base address of the DDR controller.
  * @message:   Buffer for framing the event specific info.
  * @stat:  ECC status information.
+ * @p_data:Platform data.
  * @ce_cnt:Correctable Error count.
  * @ue_cnt:Uncorrectable Error count.
  */
@@ -137,21 +140,41 @@ struct synps_edac_priv {
void __iomem *baseaddr;
char message[SYNPS_EDAC_MSG_SIZE];
struct synps_ecc_status stat;
+   const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
 };
 
 /**
- * edac_geterror_info - Get the current ECC error info.
- * @base:  Base address of the DDR memory controller.
- * @p: Synopsys ECC status structure.
+ * struct synps_platform_data -  synps platform data structure.
+ * @geterror_info: EDAC error info.
+ * @get_mtype: Get mtype.
+ * @get_dtype: Get dtype.
+ * @get_eccstate:  Get ECC state.
+ * @quirks:To differentiate IPs.
+ */
+struct synps_platform_data {
+   int (*geterror_info)(struct synps_edac_priv *priv);
+   enum mem_type (*get_mtype)(const void __iomem *base);
+   enum dev_type (*get_dtype)(const void __iomem *base);
+   bool (*get_eccstate)(void __iomem *base);
+   int quirks;
+};
+
+/**
+ * zynq_geterror_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
  *
  * Return: one if there is no error otherwise returns zero.
  */
-static int edac_geterror_info(void __iomem *base,
-   struct synps_ecc_status *p)
+static int zynq_geterror_info(struct synps_edac_priv *priv)
 {
+   struct synps_ecc_status *p;
u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
 
regval = readl(base + STAT_OFST);
if (!regval)
@@ -230,17 +253,18 @@ static void edac_handle_error(struct mem_ctl_info *mci,
 }
 
 /**
- * edac_check - Check controller for ECC errors.
+ * edac_error_check - Check controller for ECC errors.
  * @mci:   EDAC memory controller instance.
  *
  * Used to check and post ECC errors. Called by the polling thread.
  */
-static void edac_check(struct mem_ctl_info *mci)
+static void edac_error_check(struct mem_ctl_info *mci)
 {
struct synps_edac_priv *priv = mci->pvt_info;
+   const struct synps_platform_data *p_data = priv->p_data;
int status;
 
-   status = edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = p_data->geterror_info(priv);
if (status)
return;
 
@@ -253,7 +277,7 @@ static void edac_check(struct mem_ctl_info *mci)
 }
 
 /**
- * edac_get_dtype - Return the controller memory width.
+ * zynq_get_dtype - Return the controller memory width.
  * @base:  DDR memory controller base address.
  *
  * Get the EDAC device type width appropriate for the current controller
@@ -261,7 +285,7 @@ static void edac_check(struct mem_ctl_info *mci)
  *
  * Return: a device type width enumeration.
  */
-static enum dev_type edac_get_dtype(const void __iomem *base)
+static enum dev_type zynq_get_dtype(const void __iomem *base)
 {
enum dev_type dt;
u32 width;
@@ -284,20 +308,20 @@ static enum dev_type edac_get_dtype(const void __iomem 
*base)
 }
 
 /**
- * edac_get_eccstate - Return the controller ECC enable/disable status.
+ * zynq_get_eccstate - Return the controller ECC enable/disable status.
  * @base:  DDR memory controller base address.
  *
  * Get the ECC enable/disable status for the controller.
  *
  * Return: a ECC status boolean i.e true/false - enabled/disabled.
  */
-static bool edac_get_eccstate(void __iomem *base)
+static bool zynq_get_eccstate(void __iomem *base)
 {
bool state = false;
enum dev_type dt;
u32 ecctype;
 
-   dt = edac_get_dtype(base);
+   dt = zynq_get_dtype(base);
if (dt == DEV_UNKNOWN)
return state;
 
@@ -323,7 +347,7 @@ static u32 edac_get_memsize(void)
 }
 
 /**
- * edac_get_mtype - Returns controller memory type.
+ * zynq_get_mtype - Returns controller memory type.
  * @base:  Synopsys ECC status structure.
  *
  * Get the EDAC memory type appropriate for the current controller
@@ -331,7 +355,7 @@ static u32 edac_get_memsize(void)
  *
  * Return: a memory type enumeration.
  */
-static enum mem_type edac_get_mtype

[PATCH v8 09/10] arm64: zynqmp: Add DDRC node

2018-10-04 Thread Manish Narani
Add ddrc memory controller node in dts. The size mentioned in dts is
0x3, because we need to access DDR_QOS INTR registers located at
0xFD090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 29ce234..a81d3b16 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH v8 02/10] edac: synopsys: Rename the static functions to a shorter name

2018-10-04 Thread Manish Narani
Rename the static functions to a shorter name. Since this is Synopsys
EDAC driver, better to remove unnecessary 'synps_' prefix in function
names.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 56 ++--
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 1936c73..abb5de8 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -142,7 +142,7 @@ struct synps_edac_priv {
 };
 
 /**
- * synps_edac_geterror_info - Get the current ecc error info
+ * edac_geterror_info - Get the current ecc error info
  * @base:  Pointer to the base address of the ddr memory controller
  * @p: Pointer to the synopsys ecc status structure
  *
@@ -150,7 +150,7 @@ struct synps_edac_priv {
  *
  * Return: one if there is no error otherwise returns zero
  */
-static int synps_edac_geterror_info(void __iomem *base,
+static int edac_geterror_info(void __iomem *base,
struct synps_ecc_status *p)
 {
u32 regval, clearval = 0;
@@ -196,13 +196,13 @@ static int synps_edac_geterror_info(void __iomem *base,
 }
 
 /**
- * synps_edac_handle_error - Handle controller error types CE and UE
+ * edac_handle_error - Handle controller error types CE and UE
  * @mci:   Pointer to the edac memory controller instance
  * @p: Pointer to the synopsys ecc status structure
  *
  * Handles the controller ECC correctable and un correctable error.
  */
-static void synps_edac_handle_error(struct mem_ctl_info *mci,
+static void edac_handle_error(struct mem_ctl_info *mci,
struct synps_ecc_status *p)
 {
struct synps_edac_priv *priv = mci->pvt_info;
@@ -232,30 +232,30 @@ static void synps_edac_handle_error(struct mem_ctl_info 
*mci,
 }
 
 /**
- * synps_edac_check - Check controller for ECC errors
+ * edac_check - Check controller for ECC errors
  * @mci:   Pointer to the edac memory controller instance
  *
  * Used to check and post ECC errors. Called by the polling thread
  */
-static void synps_edac_check(struct mem_ctl_info *mci)
+static void edac_check(struct mem_ctl_info *mci)
 {
struct synps_edac_priv *priv = mci->pvt_info;
int status;
 
-   status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = edac_geterror_info(priv->baseaddr, &priv->stat);
if (status)
return;
 
priv->ce_cnt += priv->stat.ce_cnt;
priv->ue_cnt += priv->stat.ue_cnt;
-   synps_edac_handle_error(mci, &priv->stat);
+   edac_handle_error(mci, &priv->stat);
 
edac_dbg(3, "Total error count CE %d UE %d\n",
 priv->ce_cnt, priv->ue_cnt);
 }
 
 /**
- * synps_edac_get_dtype - Return the controller memory width
+ * edac_get_dtype - Return the controller memory width
  * @base:  Pointer to the ddr memory controller base address
  *
  * Get the EDAC device type width appropriate for the current controller
@@ -263,7 +263,7 @@ static void synps_edac_check(struct mem_ctl_info *mci)
  *
  * Return: a device type width enumeration.
  */
-static enum dev_type synps_edac_get_dtype(const void __iomem *base)
+static enum dev_type edac_get_dtype(const void __iomem *base)
 {
enum dev_type dt;
u32 width;
@@ -286,20 +286,20 @@ static enum dev_type synps_edac_get_dtype(const void 
__iomem *base)
 }
 
 /**
- * synps_edac_get_eccstate - Return the controller ecc enable/disable status
+ * edac_get_eccstate - Return the controller ecc enable/disable status
  * @base:  Pointer to the ddr memory controller base address
  *
  * Get the ECC enable/disable status for the controller
  *
  * Return: a ecc status boolean i.e true/false - enabled/disabled.
  */
-static bool synps_edac_get_eccstate(void __iomem *base)
+static bool edac_get_eccstate(void __iomem *base)
 {
bool state = false;
enum dev_type dt;
u32 ecctype;
 
-   dt = synps_edac_get_dtype(base);
+   dt = edac_get_dtype(base);
if (dt == DEV_UNKNOWN)
return state;
 
@@ -311,11 +311,11 @@ static bool synps_edac_get_eccstate(void __iomem *base)
 }
 
 /**
- * synps_edac_get_memsize - reads the size of the attached memory device
+ * edac_get_memsize - reads the size of the attached memory device
  *
  * Return: the memory size in bytes
  */
-static u32 synps_edac_get_memsize(void)
+static u32 edac_get_memsize(void)
 {
struct sysinfo inf;
 
@@ -325,7 +325,7 @@ static u32 synps_edac_get_memsize(void)
 }
 
 /**
- * synps_edac_get_mtype - Returns controller memory type
+ * edac_get_mtype - Returns controller memory type
  * @base:  pointer to the synopsys ecc status structure
  *
  * Get the EDAC memory type appropriate for the current controller
@@ -333,7 +333,7 @@ static u32 synps_edac_get_memsize(void)
  *
  * Return: a 

[PATCH v8 10/10] edac: synopsys: Add Error Injection support for ZynqMP DDRC

2018-10-04 Thread Manish Narani
Add support for Error Injection for ZynqMP DDRC IP. For injecting
errors, the Row, Column, Bank, Bank Group and Rank bits positions are
determined via Address Map registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 421 ++-
 1 file changed, 414 insertions(+), 7 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index adfa3bb..b64de4a 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -302,12 +302,18 @@ struct synps_ecc_status {
 
 /**
  * struct synps_edac_priv - DDR memory controller private instance data.
- * @baseaddr:  Base address of the DDR controller.
- * @message:   Buffer for framing the event specific info.
- * @stat:  ECC status information.
- * @p_data:Platform data.
- * @ce_cnt:Correctable Error count.
- * @ue_cnt:Uncorrectable Error count.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @p_data:Platform data.
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
+ * @poison_addr:   Data poison address.
+ * @row_shift: Bit shifts for row bit.
+ * @col_shift: Bit shifts for column bit.
+ * @bank_shift:Bit shifts for bank bit.
+ * @bankgrp_shift: Bit shifts for bank group bit.
+ * @rank_shift:Bit shifts for rank bit.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -316,6 +322,14 @@ struct synps_edac_priv {
const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
+#ifdef CONFIG_EDAC_DEBUG
+   ulong poison_addr;
+   u32 row_shift[18];
+   u32 col_shift[14];
+   u32 bank_shift[3];
+   u32 bankgrp_shift[2];
+   u32 rank_shift[1];
+#endif
 };
 
 /**
@@ -882,7 +896,11 @@ static const struct synps_platform_data zynqmp_edac_def = {
.get_mtype  = zynqmp_get_mtype,
.get_dtype  = zynqmp_get_dtype,
.get_eccstate   = zynqmp_get_eccstate,
-   .quirks = DDR_ECC_INTR_SUPPORT,
+   .quirks = (DDR_ECC_INTR_SUPPORT
+#ifdef CONFIG_EDAC_DEBUG
+ | DDR_ECC_DATA_POISON_SUPPORT
+#endif
+ ),
 };
 
 static const struct of_device_id synps_edac_match[] = {
@@ -901,6 +919,375 @@ static const struct of_device_id synps_edac_match[] = {
 
 MODULE_DEVICE_TABLE(of, synps_edac_match);
 
+#ifdef CONFIG_EDAC_DEBUG
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/**
+ * ddr_poison_setup -  Update poison registers.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Update poison registers as per DDR mapping.
+ * Return: none.
+ */
+static void ddr_poison_setup(struct synps_edac_priv *priv)
+{
+   int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
+   int index;
+   ulong hif_addr = 0;
+
+   hif_addr = priv->poison_addr >> 3;
+
+   for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
+   if (priv->row_shift[index])
+   row |= (((hif_addr >> priv->row_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_COL_SHIFT; index++) {
+   if (priv->col_shift[index] || index < 3)
+   col |= (((hif_addr >> priv->col_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) {
+   if (priv->bank_shift[index])
+   bank |= (((hif_addr >> priv->bank_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) {
+   if (priv->bankgrp_shift[index])
+   bankgrp |= (((hif_addr >> priv->bankgrp_shift[index])
+   & BIT(0)) << index);
+   else
+   break;
+   }
+
+   if (priv->rank_shift[0])
+   rank = (hif_addr >> priv->rank_shift[0]) & BIT(0);
+
+   regval = (rank << ECC_POISON0_RANK_SHIFT) & ECC_POISON0_RANK_MASK;
+   regval |= (col << ECC_POISON0_COLUMN_SHIFT) & ECC_POISON0_COLUMN_MASK;
+   writel(regval, priv->baseaddr + ECC_POISON0_OFST);
+
+   regval = (bankgrp << ECC_POISON1_BG_SHIFT) & ECC_POISON1_BG_MASK;
+   regval |= (bank << ECC_POISON1_BANKNR_SHIFT) & ECC_PO

[PATCH v8 08/10] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-10-04 Thread Manish Narani
Add EDAC ECC support for ZynqMP DDRC IP. The IP supports interrupts for
corrected and uncorrected errors. Add interrupt handlers for the same.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 328 ---
 2 files changed, 311 insertions(+), 19 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..b1fc7a16 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARM64
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 94d1398..adfa3bb 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -272,6 +273,8 @@
  * @bank:  Bank number.
  * @bitpos:Bit position.
  * @data:  Data causing the error.
+ * @bankgrpnr: Bank group number.
+ * @blknr: Block number.
  */
 struct ecc_error_info {
u32 row;
@@ -279,6 +282,8 @@ struct ecc_error_info {
u32 bank;
u32 bitpos;
u32 data;
+   u32 bankgrpnr;
+   u32 blknr;
 };
 
 /**
@@ -385,6 +390,68 @@ static int zynq_geterror_info(struct synps_edac_priv *priv)
 }
 
 /**
+ * zynqmp_geterror_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Return: one if there is no error otherwise returns zero.
+ */
+static int zynqmp_geterror_info(struct synps_edac_priv *priv)
+{
+   struct synps_ecc_status *p;
+   u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
+
+   regval = readl(base + ECC_STAT_OFST);
+   if (!regval)
+   return 1;
+
+   p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
+   p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
+   p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
+
+   regval = readl(base + ECC_CEADDR0_OFST);
+   if (!p->ce_cnt)
+   goto ue_err;
+
+   p->ceinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_CEADDR1_OFST);
+   p->ceinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ceinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ceinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ceinfo.data = readl(base + ECC_CSYND0_OFST);
+   edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n",
+readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST),
+readl(base + ECC_CSYND2_OFST));
+
+
+ue_err:
+   regval = readl(base + ECC_UEADDR0_OFST);
+   if (!p->ue_cnt)
+   goto out;
+
+   p->ueinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_UEADDR1_OFST);
+   p->ueinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ueinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ueinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ueinfo.data = readl(base + ECC_UESYND0_OFST);
+out:
+   clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT;
+   clearval |= ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT;
+   writel(clearval, base + ECC_CLR_OFST);
+   writel(0x0, base + ECC_CLR_OFST);
+
+   return 0;
+}
+
+/**
  * edac_handle_error - Handle controller error types CE and UE.
  * @mci:   EDAC memory controller instance.
  * @p: Synopsys ECC status structure.
@@ -399,9 +466,25 @@ static void edac_handle_error(struct mem_ctl_info *mci,
 
if (p->ce_cnt) {
pinf = &p->ceinfo;
-   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-"DDR ECC error type :%s Row %d Bank %d Col %d ",
-"CE", pinf->row, pinf->bank, pinf->col);
+   if (!priv->p_data->quirks) {
+   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
+"DDR ECC error type:%s Row %d Bank %d Col %d ",
+ "CE", pinf->row, pinf->bank, pinf->col);
+   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
+

[PATCH v8 06/10] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-10-04 Thread Manish Narani
Add information of ZynqMP DDRC which reports the single bit errors that
are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
Reviewed-by: Rob Herring 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v8 00/10] EDAC: Enhancements to Synopsys EDAC driver

2018-10-04 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms. This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Changes in v3:
- The commit message in (2/4) is modified (Synopsys EDAC Driver -->
  ZynqMP DDRC)

Changes in v4:
- Updated the commit message in (1/4)
- Renamed function pointer names removing 'synps_' in (1/4)
- Shortened unnecessary long lines as per the review comment on (1/4)

Changes in v5:
- Updated the commit message in (2/4) and (4/4).
- Removed the unnecessary check for match data in probe() in (1/4)
- Some Indentation changes for better readability in (1/4) and (3/4)
- Removed repeated code in (3/4)
- Used 'zynq' and 'zynqmp' instead of 'synps_enh_edac' in function names

Changes in v6:
- Splitted the patches according to functionalities
- Addressed code style comments from v5 review
- Moved the Error Injection to CONFIG_EDAC_DEBUG mode

Changes in v7:
- Included DTS patch (6/7) which was missed in v6 patch set

Changes in v8:
- patch (1/7) from v7 is split in to 3 different logically different 
patches
1. functional changes like code cleanup
2. functions renaming
3. comments cleanup
- Added a separate patch (4) for making always successful functions as 
void
- Corrected 'Too many parentheses' review comment in patch (5)
- Corrected comments as per the v7 review feedback
- Made dedicated functions for IRQ setup, IRQ enable and IRQ disable in 
patch (8)
    - Addressed review comments in patch (10)

Manish Narani (10):
  edac: synopsys: Update the driver code for better readability
  edac: synopsys: Rename the static functions to a shorter name
  edac: synopsys: Modify the comments in the driver
  edac: synopsys: Make return type void for functions always returning 0
  edac: synps: Add platform specific structures for ddrc controller
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add macro defines for ZynqMP DDRC
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node
  edac: synopsys: Add Error Injection support for ZynqMP DDRC

 .../bindings/memory-controllers/synopsys.txt   |   27 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |7 +
 drivers/edac/Kconfig   |2 +-
 drivers/edac/synopsys_edac.c   | 1194 +---
 4 files changed, 1072 insertions(+), 158 deletions(-)

-- 
2.1.1



[PATCH v8 07/10] edac: synopsys: Add macro defines for ZynqMP DDRC

2018-10-04 Thread Manish Narani
Add macro defines for ZynqMP DDR controller. These macros will be used
for ZynqMP ECC operations.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 168 +++
 1 file changed, 168 insertions(+)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index f0f4704..94d1398 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -97,6 +97,174 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORTBIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON0_RANK_MASK  BIT(24)
+#define ECC_POISON0_COLUMN_SHIFT   0
+#define ECC_POISON0_COLUMN_MASK0xFFF
+#define ECC_POISON1_BG_SHIFT   28
+#define ECC_POISON1_BG_MASK0x3000
+#define ECC_POISON1_BANKNR_SHIFT   24
+#define ECC_POISON1_BANKNR_MASK0x700
+#define ECC_POISON1_ROW_SHIFT  0
+#define ECC_POISON1_ROW_MASK   0x3
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK  0x3
+#define ECC_UEPOISON_MASK  0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_CFG_MASK 0xC000
+#define DDRC_MSTR_CFG_SHIFT30
+#define DDRC_MSTR_CFG_X4_MASK  0x0
+#define DDRC_MSTR_CFG_X8_MASK  0x1
+#define DDRC_MSTR_CFG_X16_MASK 0x2
+#define DDRC_MSTR_CFG_X32_MASK 0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#de

[PATCH v8 03/10] edac: synopsys: Modify the comments in the driver

2018-10-04 Thread Manish Narani
There are some comments which can be updated for better readability of
the driver. Update abbreviations to capital letters in the comments.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 98 ++--
 1 file changed, 48 insertions(+), 50 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index abb5de8..7db5928 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -96,12 +96,12 @@
 #define SCRUB_MODE_SECDED  0x4
 
 /**
- * struct ecc_error_info - ECC error log information
- * @row:   Row number
- * @col:   Column number
- * @bank:  Bank number
- * @bitpos:Bit position
- * @data:  Data causing the error
+ * struct ecc_error_info - ECC error log information.
+ * @row:   Row number.
+ * @col:   Column number.
+ * @bank:  Bank number.
+ * @bitpos:Bit position.
+ * @data:  Data causing the error.
  */
 struct ecc_error_info {
u32 row;
@@ -112,11 +112,11 @@ struct ecc_error_info {
 };
 
 /**
- * struct synps_ecc_status - ECC status information to report
- * @ce_cnt:Correctable error count
- * @ue_cnt:Uncorrectable error count
- * @ceinfo:Correctable error log information
- * @ueinfo:Uncorrectable error log information
+ * struct synps_ecc_status - ECC status information to report.
+ * @ce_cnt:Correctable error count.
+ * @ue_cnt:Uncorrectable error count.
+ * @ceinfo:Correctable error log information.
+ * @ueinfo:Uncorrectable error log information.
  */
 struct synps_ecc_status {
u32 ce_cnt;
@@ -126,12 +126,12 @@ struct synps_ecc_status {
 };
 
 /**
- * struct synps_edac_priv - DDR memory controller private instance data
- * @baseaddr:  Base address of the DDR controller
- * @message:   Buffer for framing the event specific info
- * @stat:  ECC status information
- * @ce_cnt:Correctable Error count
- * @ue_cnt:Uncorrectable Error count
+ * struct synps_edac_priv - DDR memory controller private instance data.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -142,13 +142,11 @@ struct synps_edac_priv {
 };
 
 /**
- * edac_geterror_info - Get the current ecc error info
- * @base:  Pointer to the base address of the ddr memory controller
- * @p: Pointer to the synopsys ecc status structure
+ * edac_geterror_info - Get the current ECC error info.
+ * @base:  Base address of the DDR memory controller.
+ * @p: Synopsys ECC status structure.
  *
- * Determines there is any ecc error or not
- *
- * Return: one if there is no error otherwise returns zero
+ * Return: one if there is no error otherwise returns zero.
  */
 static int edac_geterror_info(void __iomem *base,
struct synps_ecc_status *p)
@@ -196,11 +194,11 @@ static int edac_geterror_info(void __iomem *base,
 }
 
 /**
- * edac_handle_error - Handle controller error types CE and UE
- * @mci:   Pointer to the edac memory controller instance
- * @p: Pointer to the synopsys ecc status structure
+ * edac_handle_error - Handle controller error types CE and UE.
+ * @mci:   EDAC memory controller instance.
+ * @p: Synopsys ECC status structure.
  *
- * Handles the controller ECC correctable and un correctable error.
+ * Handles the controller ECC correctable and un-correctable error.
  */
 static void edac_handle_error(struct mem_ctl_info *mci,
struct synps_ecc_status *p)
@@ -232,10 +230,10 @@ static void edac_handle_error(struct mem_ctl_info *mci,
 }
 
 /**
- * edac_check - Check controller for ECC errors
- * @mci:   Pointer to the edac memory controller instance
+ * edac_check - Check controller for ECC errors.
+ * @mci:   EDAC memory controller instance.
  *
- * Used to check and post ECC errors. Called by the polling thread
+ * Used to check and post ECC errors. Called by the polling thread.
  */
 static void edac_check(struct mem_ctl_info *mci)
 {
@@ -255,8 +253,8 @@ static void edac_check(struct mem_ctl_info *mci)
 }
 
 /**
- * edac_get_dtype - Return the controller memory width
- * @base:  Pointer to the ddr memory controller base address
+ * edac_get_dtype - Return the controller memory width.
+ * @base:  DDR memory controller base address.
  *
  * Get the EDAC device type width appropriate for the current controller
  * configuration.
@@ -286,12 +284,12 @@ static enum dev_type edac_get_dtype(const void __iomem 
*base)
 }
 
 /**
- * edac_get_eccstate - Return the controller ecc enable/disable status
- * @base:  Pointer to the ddr memory controller base address
+ * edac_get_eccstate - Return the controller ECC enable/disable status.
+ * @base:  DDR

RE: [PATCH v8 02/10] edac: synopsys: Rename the static functions to a shorter name

2018-10-08 Thread Manish Narani
Hi Boris,

Thanks a lot for the review.

> -Original Message-
> From: Borislav Petkov [mailto:b...@alien8.de]
> Sent: Friday, October 5, 2018 2:06 AM
> Subject: Re: [PATCH v8 02/10] edac: synopsys: Rename the static functions to a
> shorter name
> 
> On Thu, Oct 04, 2018 at 09:05:20PM +0530, Manish Narani wrote:
> > Rename the static functions to a shorter name. Since this is Synopsys
> > EDAC driver, better to remove unnecessary 'synps_' prefix in function
> > names.
> >
> > Signed-off-by: Manish Narani 
> > ---
> >  drivers/edac/synopsys_edac.c | 56 ++---
> ---
> >  1 file changed, 28 insertions(+), 28 deletions(-)
> 
> Ok, let's flip the roles - now you get to review what I've committed:

Okay. Few minor nits below. :)

> 
> ---
> From: Manish Narani 
> Date: Thu, 4 Oct 2018 21:05:20 +0530
> Subject: [PATCH 1/2] EDAC, synopsys: Shorten static function names
> 
> Shorten static function names, remove the unnecessary 'synps_' prefix in
> function names.
> 
>  [ bp: Drop the "edac_" prefix too as that prefix is reserved for
>EDAC core functions. ]
> 
> Signed-off-by: Manish Narani 
> Signed-off-by: Borislav Petkov 
> CC: Mauro Carvalho Chehab 
> CC: Michal Simek 
> CC: amit.kuche...@linaro.org
> CC: devicet...@vger.kernel.org
> CC: leoyang...@nxp.com
> CC: linux-arm-ker...@lists.infradead.org
> CC: linux-edac 
> CC: mark.rutl...@arm.com
> CC: robh...@kernel.org
> CC: sudeep.ho...@arm.com
> Link: http://lkml.kernel.org/r/1538667328-9465-3-git-send-email-
> manish.nar...@xilinx.com
> ---
>  drivers/edac/synopsys_edac.c | 79 +---
>  1 file changed, 38 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
> index 1936c73f1d15..fbaf33540ce3 100644
> --- a/drivers/edac/synopsys_edac.c
> +++ b/drivers/edac/synopsys_edac.c
> @@ -142,7 +142,7 @@ struct synps_edac_priv {
>  };
> 
>  /**
> - * synps_edac_geterror_info - Get the current ecc error info
> + * get_error_info - Get the current ecc error info
>   * @base:Pointer to the base address of the ddr memory controller
>   * @p:   Pointer to the synopsys ecc status structure
>   *
> @@ -150,8 +150,7 @@ struct synps_edac_priv {
>   *
>   * Return: one if there is no error otherwise returns zero
>   */
> -static int synps_edac_geterror_info(void __iomem *base,
> - struct synps_ecc_status *p)
> +static int get_error_info(void __iomem *base, struct synps_ecc_status *p)
>  {
>   u32 regval, clearval = 0;
> 
> @@ -196,14 +195,13 @@ static int synps_edac_geterror_info(void __iomem
> *base,
>  }
> 
>  /**
> - * synps_edac_handle_error - Handle controller error types CE and UE
> + * handle_error - Handle controller error types CE and UE
>   * @mci: Pointer to the edac memory controller instance
>   * @p:   Pointer to the synopsys ecc status structure
>   *
> - * Handles the controller ECC correctable and un correctable error.
> + * Handles the controller ECC correctable and uncorrectable error.

Nit: This can be moved to Comments Correction patch

>   */
> -static void synps_edac_handle_error(struct mem_ctl_info *mci,
> - struct synps_ecc_status *p)
> +static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status
> *p)
>  {
>   struct synps_edac_priv *priv = mci->pvt_info;
>   struct ecc_error_info *pinf;
> @@ -232,30 +230,30 @@ static void synps_edac_handle_error(struct
> mem_ctl_info *mci,
>  }
> 
>  /**
> - * synps_edac_check - Check controller for ECC errors
> + * check_errors - Check controller for ECC errors
>   * @mci: Pointer to the edac memory controller instance
>   *
>   * Used to check and post ECC errors. Called by the polling thread
>   */
> -static void synps_edac_check(struct mem_ctl_info *mci)
> +static void check_errors(struct mem_ctl_info *mci)
>  {
>   struct synps_edac_priv *priv = mci->pvt_info;
>   int status;
> 
> - status = synps_edac_geterror_info(priv->baseaddr, &priv->stat);
> + status = get_error_info(priv->baseaddr, &priv->stat);
>   if (status)
>   return;
> 
>   priv->ce_cnt += priv->stat.ce_cnt;
>   priv->ue_cnt += priv->stat.ue_cnt;
> - synps_edac_handle_error(mci, &priv->stat);
> + handle_error(mci, &priv->stat);
> 
>   edac_dbg(3, "Total error count CE %d UE %d\n",
>priv->ce_cnt, priv->ue_cnt);
>  }
> 
>  /**
> - * synp

RE: [PATCH v10 0/6] EDAC: Enhancements to Synopsys EDAC driver

2018-11-02 Thread Manish Narani
Ping!


> -Original Message-
> From: Manish Narani [mailto:manish.nar...@xilinx.com]
> Sent: Thursday, October 25, 2018 11:37 AM
> To: robh...@kernel.org; mark.rutl...@arm.com; Michal Simek
> ; b...@alien8.de; mche...@kernel.org; Manish Narani
> ; amit.kuche...@linaro.org; sudeep.ho...@arm.com;
> leoyang...@nxp.com
> Cc: devicet...@vger.kernel.org; linux-kernel@vger.kernel.org; linux-arm-
> ker...@lists.infradead.org; linux-e...@vger.kernel.org
> Subject: [PATCH v10 0/6] EDAC: Enhancements to Synopsys EDAC driver
> 
> This patch series enhances the current EDAC driver to support different
> platforms. This series adds support for ZynqMP DDRC controller in synopsys
> EDAC driver. This series also adds Device tree properties and relevant binding
> documentation.
> 
> Changes in v2:
>   - Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it
> is
> a feature of ZynqMP DDRC
>   - The Binding Documentation in (2/4) is modified as per the review
> comments
> 
> Changes in v3:
>   - The commit message in (2/4) is modified (Synopsys EDAC Driver -->
> ZynqMP DDRC)
> 
> Changes in v4:
>   - Updated the commit message in (1/4)
>   - Renamed function pointer names removing 'synps_' in (1/4)
>   - Shortened unnecessary long lines as per the review comment on (1/4)
> 
> Changes in v5:
>   - Updated the commit message in (2/4) and (4/4).
>   - Removed the unnecessary check for match data in probe() in (1/4)
>   - Some Indentation changes for better readability in (1/4) and (3/4)
>   - Removed repeated code in (3/4)
>   - Used 'zynq' and 'zynqmp' instead of 'synps_enh_edac' in function
> names
> 
> Changes in v6:
>   - Splitted the patches according to functionalities
>   - Addressed code style comments from v5 review
>   - Moved the Error Injection to CONFIG_EDAC_DEBUG mode
> 
> Changes in v7:
>   - Included DTS patch (6/7) which was missed in v6 patch set
> 
> Changes in v8:
>   - patch (1/7) from v7 is split in to 3 different logically different 
> patches
>   1. functional changes like code cleanup
>   2. functions renaming
>   3. comments cleanup
>   - Added a separate patch (4) for making always successful functions as
> void
>   - Corrected 'Too many parentheses' review comment in patch (5)
>   - Corrected comments as per the v7 review feedback
>   - Made dedicated functions for IRQ setup, IRQ enable and IRQ disable
> in patch (8)
>   - Addressed review comments in patch (10)
> 
> Changes in v9:
>   - Added check for return value of of_device_get_match_data() function
> in (1/6).
>   - From v8 the first 5 patches are removed in this series as they are
> applied on:
> 
>   https://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git/?h=edac-for-
> 4.20-synps
>   - Updated Kconfig to check for ARCH_ZYNQMP instead of ARM64
> 
> Change in v10:
>   - Moved the checking for ce_cnt and ue_cnt before the readl() call
>   - Aligned arguments on the opening brace in setup_irq()
> 
> Manish Narani (6):
>   edac: synopsys: Add error handling for NULL in probe()
>   dt: bindings: Document ZynqMP DDRC in Synopsys documentation
>   edac: synopsys: Add macro defines for ZynqMP DDRC
>   edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
>   arm64: zynqmp: Add DDRC node
>   edac: synopsys: Add Error Injection support for ZynqMP DDRC
> 
>  .../bindings/memory-controllers/synopsys.txt   |  27 +-
>  arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
>  drivers/edac/Kconfig   |   2 +-
>  drivers/edac/synopsys_edac.c   | 911 
> -
>  4 files changed, 918 insertions(+), 29 deletions(-)
> 
> --
> 2.1.1



[PATCH v10 4/6] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-10-24 Thread Manish Narani
Add EDAC ECC support for ZynqMP DDRC IP. The IP supports interrupts for
corrected and uncorrected errors. Add interrupt handlers for the same.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 322 ---
 2 files changed, 306 insertions(+), 18 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..7c40eb2 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARCH_ZYNQMP
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index d1999e0..e81f18a 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -272,6 +273,8 @@
  * @bank:  Bank number.
  * @bitpos:Bit position.
  * @data:  Data causing the error.
+ * @bankgrpnr: Bank group number.
+ * @blknr: Block number.
  */
 struct ecc_error_info {
u32 row;
@@ -279,6 +282,8 @@ struct ecc_error_info {
u32 bank;
u32 bitpos;
u32 data;
+   u32 bankgrpnr;
+   u32 blknr;
 };
 
 /**
@@ -385,6 +390,66 @@ static int zynq_get_error_info(struct synps_edac_priv 
*priv)
 }
 
 /**
+ * zynqmp_get_error_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Return: one if there is no error otherwise returns zero.
+ */
+static int zynqmp_get_error_info(struct synps_edac_priv *priv)
+{
+   struct synps_ecc_status *p;
+   u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
+
+   regval = readl(base + ECC_STAT_OFST);
+   if (!regval)
+   return 1;
+
+   p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
+   p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
+   if (!p->ce_cnt)
+   goto ue_err;
+
+   p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
+
+   regval = readl(base + ECC_CEADDR0_OFST);
+   p->ceinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_CEADDR1_OFST);
+   p->ceinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ceinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ceinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ceinfo.data = readl(base + ECC_CSYND0_OFST);
+   edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n",
+readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST),
+readl(base + ECC_CSYND2_OFST));
+ue_err:
+   if (!p->ue_cnt)
+   goto out;
+
+   regval = readl(base + ECC_UEADDR0_OFST);
+   p->ueinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_UEADDR1_OFST);
+   p->ueinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ueinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ueinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ueinfo.data = readl(base + ECC_UESYND0_OFST);
+out:
+   clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT;
+   clearval |= ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT;
+   writel(clearval, base + ECC_CLR_OFST);
+   writel(0x0, base + ECC_CLR_OFST);
+
+   return 0;
+}
+
+/**
  * handle_error - Handle Correctable and Uncorrectable errors.
  * @mci:   EDAC memory controller instance.
  * @p: Synopsys ECC status structure.
@@ -398,9 +463,25 @@ static void handle_error(struct mem_ctl_info *mci, struct 
synps_ecc_status *p)
 
if (p->ce_cnt) {
pinf = &p->ceinfo;
-   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-"DDR ECC error type :%s Row %d Bank %d Col %d ",
-"CE", pinf->row, pinf->bank, pinf->col);
+   if (!priv->p_data->quirks) {
+   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
+"DDR ECC error type:%s Row %d Bank %d Col %d ",
+ "CE", pinf->row, pinf->bank, pinf->col);
+   snprintf(priv->message, SYN

[PATCH v10 2/6] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-10-24 Thread Manish Narani
Add information of ZynqMP DDRC which reports the single bit errors that
are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
Reviewed-by: Rob Herring 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v10 0/6] EDAC: Enhancements to Synopsys EDAC driver

2018-10-24 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms. This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Changes in v3:
- The commit message in (2/4) is modified (Synopsys EDAC Driver -->
  ZynqMP DDRC)

Changes in v4:
- Updated the commit message in (1/4)
- Renamed function pointer names removing 'synps_' in (1/4)
- Shortened unnecessary long lines as per the review comment on (1/4)

Changes in v5:
- Updated the commit message in (2/4) and (4/4).
- Removed the unnecessary check for match data in probe() in (1/4)
- Some Indentation changes for better readability in (1/4) and (3/4)
- Removed repeated code in (3/4)
- Used 'zynq' and 'zynqmp' instead of 'synps_enh_edac' in function names

Changes in v6:
- Splitted the patches according to functionalities
- Addressed code style comments from v5 review
- Moved the Error Injection to CONFIG_EDAC_DEBUG mode

Changes in v7:
- Included DTS patch (6/7) which was missed in v6 patch set

Changes in v8:
- patch (1/7) from v7 is split in to 3 different logically different 
patches
1. functional changes like code cleanup
2. functions renaming
3. comments cleanup
- Added a separate patch (4) for making always successful functions as 
void
- Corrected 'Too many parentheses' review comment in patch (5)
- Corrected comments as per the v7 review feedback
- Made dedicated functions for IRQ setup, IRQ enable and IRQ disable in 
patch (8)
- Addressed review comments in patch (10)

Changes in v9:
- Added check for return value of of_device_get_match_data() function
  in (1/6).
- From v8 the first 5 patches are removed in this series as they are
  applied on:

https://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git/?h=edac-for-4.20-synps
- Updated Kconfig to check for ARCH_ZYNQMP instead of ARM64

Change in v10:
- Moved the checking for ce_cnt and ue_cnt before the readl() call
- Aligned arguments on the opening brace in setup_irq()

Manish Narani (6):
  edac: synopsys: Add error handling for NULL in probe()
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add macro defines for ZynqMP DDRC
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node
  edac: synopsys: Add Error Injection support for ZynqMP DDRC

 .../bindings/memory-controllers/synopsys.txt   |  27 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |   7 +
 drivers/edac/Kconfig   |   2 +-
 drivers/edac/synopsys_edac.c   | 911 -
 4 files changed, 918 insertions(+), 29 deletions(-)

-- 
2.1.1



[PATCH v10 1/6] edac: synopsys: Add error handling for NULL in probe()

2018-10-24 Thread Manish Narani
The function of_device_get_match_data() can return NULL in case of
error. Add error handling for the same in probe().

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 1c3795d..0005ef3 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -477,6 +477,9 @@ static int mc_probe(struct platform_device *pdev)
return PTR_ERR(baseaddr);
 
p_data = of_device_get_match_data(&pdev->dev);
+   if (!p_data)
+   return -ENODEV;
+
if (!p_data->get_ecc_state(baseaddr)) {
edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n");
return -ENXIO;
-- 
2.1.1



[PATCH v10 6/6] edac: synopsys: Add Error Injection support for ZynqMP DDRC

2018-10-24 Thread Manish Narani
Add support for Error Injection for ZynqMP DDRC IP. For injecting
errors, the Row, Column, Bank, Bank Group and Rank bits positions are
determined via Address Map registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 420 ++-
 1 file changed, 413 insertions(+), 7 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index e81f18a..2d26338 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -302,12 +302,18 @@ struct synps_ecc_status {
 
 /**
  * struct synps_edac_priv - DDR memory controller private instance data.
- * @baseaddr:  Base address of the DDR controller.
- * @message:   Buffer for framing the event specific info.
- * @stat:  ECC status information.
- * @p_data:Platform data.
- * @ce_cnt:Correctable Error count.
- * @ue_cnt:Uncorrectable Error count.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @p_data:Platform data.
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
+ * @poison_addr:   Data poison address.
+ * @row_shift: Bit shifts for row bit.
+ * @col_shift: Bit shifts for column bit.
+ * @bank_shift:Bit shifts for bank bit.
+ * @bankgrp_shift: Bit shifts for bank group bit.
+ * @rank_shift:Bit shifts for rank bit.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -316,6 +322,14 @@ struct synps_edac_priv {
const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
+#ifdef CONFIG_EDAC_DEBUG
+   ulong poison_addr;
+   u32 row_shift[18];
+   u32 col_shift[14];
+   u32 bank_shift[3];
+   u32 bankgrp_shift[2];
+   u32 rank_shift[1];
+#endif
 };
 
 /**
@@ -877,7 +891,11 @@ static const struct synps_platform_data zynqmp_edac_def = {
.get_mtype  = zynqmp_get_mtype,
.get_dtype  = zynqmp_get_dtype,
.get_ecc_state  = zynqmp_get_ecc_state,
-   .quirks = DDR_ECC_INTR_SUPPORT,
+   .quirks = (DDR_ECC_INTR_SUPPORT
+#ifdef CONFIG_EDAC_DEBUG
+ | DDR_ECC_DATA_POISON_SUPPORT
+#endif
+ ),
 };
 
 static const struct of_device_id synps_edac_match[] = {
@@ -896,6 +914,375 @@ static const struct of_device_id synps_edac_match[] = {
 
 MODULE_DEVICE_TABLE(of, synps_edac_match);
 
+#ifdef CONFIG_EDAC_DEBUG
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/**
+ * ddr_poison_setup -  Update poison registers.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Update poison registers as per DDR mapping.
+ * Return: none.
+ */
+static void ddr_poison_setup(struct synps_edac_priv *priv)
+{
+   int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
+   int index;
+   ulong hif_addr = 0;
+
+   hif_addr = priv->poison_addr >> 3;
+
+   for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
+   if (priv->row_shift[index])
+   row |= (((hif_addr >> priv->row_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_COL_SHIFT; index++) {
+   if (priv->col_shift[index] || index < 3)
+   col |= (((hif_addr >> priv->col_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) {
+   if (priv->bank_shift[index])
+   bank |= (((hif_addr >> priv->bank_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) {
+   if (priv->bankgrp_shift[index])
+   bankgrp |= (((hif_addr >> priv->bankgrp_shift[index])
+   & BIT(0)) << index);
+   else
+   break;
+   }
+
+   if (priv->rank_shift[0])
+   rank = (hif_addr >> priv->rank_shift[0]) & BIT(0);
+
+   regval = (rank << ECC_POISON0_RANK_SHIFT) & ECC_POISON0_RANK_MASK;
+   regval |= (col << ECC_POISON0_COLUMN_SHIFT) & ECC_POISON0_COLUMN_MASK;
+   writel(regval, priv->baseaddr + ECC_POISON0_OFST);
+
+   regval = (bankgrp << ECC_POISON1_BG_SHIFT) & ECC_POISON1_BG_MASK;
+   regval |= (bank << ECC_POISON1_BANKNR_SHIFT) & ECC_PO

[PATCH v10 3/6] edac: synopsys: Add macro defines for ZynqMP DDRC

2018-10-24 Thread Manish Narani
Add macro defines for ZynqMP DDR controller. These macros will be used
for ZynqMP ECC operations.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 168 +++
 1 file changed, 168 insertions(+)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0005ef3..d1999e0 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -97,6 +97,174 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORTBIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON0_RANK_MASK  BIT(24)
+#define ECC_POISON0_COLUMN_SHIFT   0
+#define ECC_POISON0_COLUMN_MASK0xFFF
+#define ECC_POISON1_BG_SHIFT   28
+#define ECC_POISON1_BG_MASK0x3000
+#define ECC_POISON1_BANKNR_SHIFT   24
+#define ECC_POISON1_BANKNR_MASK0x700
+#define ECC_POISON1_ROW_SHIFT  0
+#define ECC_POISON1_ROW_MASK   0x3
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK  0x3
+#define ECC_UEPOISON_MASK  0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_CFG_MASK 0xC000
+#define DDRC_MSTR_CFG_SHIFT30
+#define DDRC_MSTR_CFG_X4_MASK  0x0
+#define DDRC_MSTR_CFG_X8_MASK  0x1
+#define DDRC_MSTR_CFG_X16_MASK 0x2
+#define DDRC_MSTR_CFG_X32_MASK 0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#de

[PATCH v10 5/6] arm64: zynqmp: Add DDRC node

2018-10-24 Thread Manish Narani
Add ddrc memory controller node in dts. The size mentioned in dts is
0x3, because we need to access DDR_QOS INTR registers located at
0xFD090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 29ce234..a81d3b16 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH v6 0/6] EDAC: Enhancements to Synopsys EDAC driver

2018-09-17 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms. This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Changes in v3:
- The commit message in (2/4) is modified (Synopsys EDAC Driver -->
  ZynqMP DDRC)

Changes in v4:
- Updated the commit message in (1/4)
- Renamed function pointer names removing 'synps_' in (1/4)
- Shortened unnecessary long lines as per the review comment on (1/4)

Changes in v5:
- Updated the commit message in (2/4) and (4/4).
- Removed the unnecessary check for match data in probe() in (1/4)
- Some Indentation changes for better readability in (1/4) and (3/4)
- Removed repeated code in (3/4)
- Used 'zynq' and 'zynqmp' instead of 'synps_enh_edac' in function names

Changes in v6:
- Splitted the patches according to functionalities
- Addressed code style comments from v5 review
- Moved the Error Injection to CONFIG_EDAC_DEBUG mode

Manish Narani (6):
  edac: synopsys: Fix code comments and naming convention
  edac: synps: Add platform specific structures for ddrc controller
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add macro defines for ZynqMP DDRC
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  edac: synopsys: Add Error Injection support for ZynqMP DDRC

 .../bindings/memory-controllers/synopsys.txt   |   27 +-
 drivers/edac/Kconfig   |2 +-
 drivers/edac/synopsys_edac.c   | 1098 ++--
 3 files changed, 1007 insertions(+), 120 deletions(-)

-- 
2.1.1



[PATCH v6 1/6] edac: synopsys: Fix code comments and naming convention

2018-09-17 Thread Manish Narani
Update the comments in the Synopsys EDAC driver. Minor changes to function
names and return types are also included.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 176 ---
 1 file changed, 80 insertions(+), 96 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0c9c59e..4963930 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -96,12 +96,12 @@
 #define SCRUB_MODE_SECDED  0x4
 
 /**
- * struct ecc_error_info - ECC error log information
- * @row:   Row number
- * @col:   Column number
- * @bank:  Bank number
- * @bitpos:Bit position
- * @data:  Data causing the error
+ * struct ecc_error_info - ECC error log information.
+ * @row:   Row number.
+ * @col:   Column number.
+ * @bank:  Bank number.
+ * @bitpos:Bit position.
+ * @data:  Data causing the error.
  */
 struct ecc_error_info {
u32 row;
@@ -112,11 +112,11 @@ struct ecc_error_info {
 };
 
 /**
- * struct synps_ecc_status - ECC status information to report
- * @ce_cnt:Correctable error count
- * @ue_cnt:Uncorrectable error count
- * @ceinfo:Correctable error log information
- * @ueinfo:Uncorrectable error log information
+ * struct synps_ecc_status - ECC status information to report.
+ * @ce_cnt:Correctable error count.
+ * @ue_cnt:Uncorrectable error count.
+ * @ceinfo:Correctable error log information.
+ * @ueinfo:Uncorrectable error log information.
  */
 struct synps_ecc_status {
u32 ce_cnt;
@@ -126,12 +126,12 @@ struct synps_ecc_status {
 };
 
 /**
- * struct synps_edac_priv - DDR memory controller private instance data
- * @baseaddr:  Base address of the DDR controller
- * @message:   Buffer for framing the event specific info
- * @stat:  ECC status information
- * @ce_cnt:Correctable Error count
- * @ue_cnt:Uncorrectable Error count
+ * struct synps_edac_priv - DDR memory controller private instance data.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -142,15 +142,13 @@ struct synps_edac_priv {
 };
 
 /**
- * synps_edac_geterror_info - Get the current ecc error info
- * @base:  Pointer to the base address of the ddr memory controller
- * @p: Pointer to the synopsys ecc status structure
+ * edac_geterror_info - Get the current ECC error info.
+ * @base:  Base address of the DDR memory controller.
+ * @p: Synopsys ECC status structure.
  *
- * Determines there is any ecc error or not
- *
- * Return: one if there is no error otherwise returns zero
+ * Return: one if there is no error otherwise returns zero.
  */
-static int synps_edac_geterror_info(void __iomem *base,
+static int edac_geterror_info(void __iomem *base,
struct synps_ecc_status *p)
 {
u32 regval, clearval = 0;
@@ -172,7 +170,7 @@ static int synps_edac_geterror_info(void __iomem *base,
p->ceinfo.col = regval & ADDR_COL_MASK;
p->ceinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT;
p->ceinfo.data = readl(base + CE_DATA_31_0_OFST);
-   edac_dbg(3, "ce bit position: %d data: %d\n", p->ceinfo.bitpos,
+   edac_dbg(3, "CE bit position: %d data: %d\n", p->ceinfo.bitpos,
 p->ceinfo.data);
clearval = ECC_CTRL_CLR_CE_ERR;
 
@@ -196,13 +194,13 @@ static int synps_edac_geterror_info(void __iomem *base,
 }
 
 /**
- * synps_edac_handle_error - Handle controller error types CE and UE
- * @mci:   Pointer to the edac memory controller instance
- * @p: Pointer to the synopsys ecc status structure
+ * edac_handle_error - Handle controller error types CE and UE.
+ * @mci:   EDAC memory controller instance.
+ * @p: Synopsys ECC status structure.
  *
- * Handles the controller ECC correctable and un correctable error.
+ * Handles the controller ECC correctable and un-correctable error.
  */
-static void synps_edac_handle_error(struct mem_ctl_info *mci,
+static void edac_handle_error(struct mem_ctl_info *mci,
struct synps_ecc_status *p)
 {
struct synps_edac_priv *priv = mci->pvt_info;
@@ -232,38 +230,38 @@ static void synps_edac_handle_error(struct mem_ctl_info 
*mci,
 }
 
 /**
- * synps_edac_check - Check controller for ECC errors
- * @mci:   Pointer to the edac memory controller instance
+ * edac_check - Check controller for ECC errors.
+ * @mci:   EDAC memory controller instance.
  *
- * Used to check and post ECC errors. Called by the polling thread
+ * Used to check and post ECC errors. Called by the polling thread.
  */
-static void synps_edac_check(struct mem_ctl

[PATCH v6 6/6] edac: synopsys: Add Error Injection support for ZynqMP DDRC

2018-09-17 Thread Manish Narani
Add support for Error Injection for ZynqMP DDRC IP. For injecting
errors, the Row, Column, Bank, Bank Group and Rank bits positions are
determined via Address Map registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 423 ++-
 1 file changed, 417 insertions(+), 6 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 7ab5b9a..177b5c3 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -302,12 +302,18 @@ struct synps_ecc_status {
 
 /**
  * struct synps_edac_priv - DDR memory controller private instance data.
- * @baseaddr:  Base address of the DDR controller.
- * @message:   Buffer for framing the event specific info.
- * @stat:  ECC status information.
- * @p_data:Platform data
- * @ce_cnt:Correctable Error count.
- * @ue_cnt:Uncorrectable Error count.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @p_data:Platform data
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
+ * @poison_addr:   Data poison address.
+ * @row_shift: Bit shifts for row bit.
+ * @col_shift: Bit shifts for column bit.
+ * @bank_shift:Bit shifts for bank bit.
+ * @bankgrp_shift: Bit shifts for bank group bit.
+ * @rank_shift:Bit shifts for rank bit.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -316,6 +322,14 @@ struct synps_edac_priv {
const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
+#ifdef CONFIG_EDAC_DEBUG
+   ulong poison_addr;
+   u32 row_shift[18];
+   u32 col_shift[14];
+   u32 bank_shift[3];
+   u32 bankgrp_shift[2];
+   u32 rank_shift[1];
+#endif
 };
 
 /**
@@ -842,7 +856,12 @@ static const struct synps_platform_data zynqmp_edac_def = {
.get_mtype  = zynqmp_get_mtype,
.get_dtype  = zynqmp_get_dtype,
.get_eccstate   = zynqmp_get_eccstate,
+#ifdef CONFIG_EDAC_DEBUG
+   .quirks = (DDR_ECC_INTR_SUPPORT |
+  DDR_ECC_DATA_POISON_SUPPORT),
+#else
.quirks = DDR_ECC_INTR_SUPPORT,
+#endif
 };
 
 static const struct of_device_id synps_edac_match[] = {
@@ -861,6 +880,380 @@ static const struct of_device_id synps_edac_match[] = {
 
 MODULE_DEVICE_TABLE(of, synps_edac_match);
 
+#ifdef CONFIG_EDAC_DEBUG
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/**
+ * ddr_poison_setup -  Update poison registers.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Update poison registers as per DDR mapping.
+ * Return: none.
+ */
+static void ddr_poison_setup(struct synps_edac_priv *priv)
+{
+   int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
+   int index;
+   ulong hif_addr = 0;
+
+   hif_addr = priv->poison_addr >> 3;
+
+   for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
+   if (priv->row_shift[index])
+   row |= (((hif_addr >> priv->row_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_COL_SHIFT; index++) {
+   if (priv->col_shift[index] || index < 3)
+   col |= (((hif_addr >> priv->col_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) {
+   if (priv->bank_shift[index])
+   bank |= (((hif_addr >> priv->bank_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) {
+   if (priv->bankgrp_shift[index])
+   bankgrp |= (((hif_addr >> priv->bankgrp_shift[index])
+   & BIT(0)) << index);
+   else
+   break;
+   }
+
+   if (priv->rank_shift[0])
+   rank = (hif_addr >> priv->rank_shift[0]) & BIT(0);
+
+   regval = (rank << ECC_POISON0_RANK_SHIFT) & ECC_POISON0_RANK_MASK;
+   regval |= (col << ECC_POISON0_COLUMN_SHIFT) & ECC_POISON0_COLUMN_MASK;
+   writel(regval, priv->baseaddr + ECC_POISON0_OFST);
+
+   regval = (bankgrp << ECC_POISON1_BG_SHIFT) & ECC_POISON1_BG_MASK;
+   regval |= (bank << ECC_POISON1_BANKNR_SHIFT) & ECC_POISON1_BANKNR_MASK;
+   

[PATCH v6 3/6] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-09-17 Thread Manish Narani
Add information of ZynqMP DDRC which reports the single bit errors that
are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
Reviewed-by: Rob Herring 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v6 5/6] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-09-17 Thread Manish Narani
Add EDAC ECC support for ZynqMP DDRC IP. The IP supports interrupts for
corrected and uncorrected errors. Add interrupt handlers for the same.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 304 ---
 2 files changed, 287 insertions(+), 19 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..b1fc7a16 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARM64
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 6bf7959..7ab5b9a 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -272,6 +273,8 @@
  * @bank:  Bank number.
  * @bitpos:Bit position.
  * @data:  Data causing the error.
+ * @bankgrpnr: Bank group number.
+ * @blknr: Block number.
  */
 struct ecc_error_info {
u32 row;
@@ -279,6 +282,8 @@ struct ecc_error_info {
u32 bank;
u32 bitpos;
u32 data;
+   u32 bankgrpnr;
+   u32 blknr;
 };
 
 /**
@@ -385,6 +390,68 @@ static int zynq_geterror_info(struct synps_edac_priv *priv)
 }
 
 /**
+ * zynqmp_geterror_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Return: one if there is no error otherwise returns zero.
+ */
+static int zynqmp_geterror_info(struct synps_edac_priv *priv)
+{
+   struct synps_ecc_status *p;
+   u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
+
+   regval = readl(base + ECC_STAT_OFST);
+   if (!regval)
+   return 1;
+
+   p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
+   p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
+   p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
+
+   regval = readl(base + ECC_CEADDR0_OFST);
+   if (!(p->ce_cnt))
+   goto ue_err;
+
+   p->ceinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_CEADDR1_OFST);
+   p->ceinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ceinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ceinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ceinfo.data = readl(base + ECC_CSYND0_OFST);
+   edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n",
+readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST),
+readl(base + ECC_CSYND2_OFST));
+
+
+ue_err:
+   regval = readl(base + ECC_UEADDR0_OFST);
+   if (!(p->ue_cnt))
+   goto out;
+
+   p->ueinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_UEADDR1_OFST);
+   p->ueinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ueinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ueinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ueinfo.data = readl(base + ECC_UESYND0_OFST);
+out:
+   clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT;
+   clearval |= ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT;
+   writel(clearval, base + ECC_CLR_OFST);
+   writel(0x0, base + ECC_CLR_OFST);
+
+   return 0;
+}
+
+/**
  * edac_handle_error - Handle controller error types CE and UE.
  * @mci:   EDAC memory controller instance.
  * @p: Synopsys ECC status structure.
@@ -399,9 +466,25 @@ static void edac_handle_error(struct mem_ctl_info *mci,
 
if (p->ce_cnt) {
pinf = &p->ceinfo;
-   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-"DDR ECC error type :%s Row %d Bank %d Col %d ",
-"CE", pinf->row, pinf->bank, pinf->col);
+   if (!priv->p_data->quirks) {
+   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
+"DDR ECC error type:%s Row %d Bank %d Col %d ",
+ "CE", pinf->row, pinf->bank, pinf->col);
+   snprintf(priv->message, SYN

[PATCH v6 2/6] edac: synps: Add platform specific structures for ddrc controller

2018-09-17 Thread Manish Narani
Add platform specific structures, so that we can add different IP
support later using quirks.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 91 +++-
 1 file changed, 65 insertions(+), 26 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 4963930..eb458e5 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "edac_module.h"
 
@@ -130,6 +132,7 @@ struct synps_ecc_status {
  * @baseaddr:  Base address of the DDR controller.
  * @message:   Buffer for framing the event specific info.
  * @stat:  ECC status information.
+ * @p_data:Platform data
  * @ce_cnt:Correctable Error count.
  * @ue_cnt:Uncorrectable Error count.
  */
@@ -137,21 +140,41 @@ struct synps_edac_priv {
void __iomem *baseaddr;
char message[SYNPS_EDAC_MSG_SIZE];
struct synps_ecc_status stat;
+   const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
 };
 
 /**
- * edac_geterror_info - Get the current ECC error info.
- * @base:  Base address of the DDR memory controller.
- * @p: Synopsys ECC status structure.
+ * struct synps_platform_data -  synps platform data structure.
+ * @geterror_info: Get error info.
+ * @get_mtype: Get mtype.
+ * @get_dtype: Get dtype.
+ * @get_eccstate:  Get eccstate.
+ * @quirks:To differentiate IPs.
+ */
+struct synps_platform_data {
+   int (*geterror_info)(struct synps_edac_priv *priv);
+   enum mem_type (*get_mtype)(const void __iomem *base);
+   enum dev_type (*get_dtype)(const void __iomem *base);
+   bool (*get_eccstate)(void __iomem *base);
+   int quirks;
+};
+
+/**
+ * zynq_geterror_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
  *
  * Return: one if there is no error otherwise returns zero.
  */
-static int edac_geterror_info(void __iomem *base,
-   struct synps_ecc_status *p)
+static int zynq_geterror_info(struct synps_edac_priv *priv)
 {
+   struct synps_ecc_status *p;
u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
 
regval = readl(base + STAT_OFST);
if (!regval)
@@ -230,17 +253,18 @@ static void edac_handle_error(struct mem_ctl_info *mci,
 }
 
 /**
- * edac_check - Check controller for ECC errors.
+ * edac_error_check - Check controller for ECC errors.
  * @mci:   EDAC memory controller instance.
  *
  * Used to check and post ECC errors. Called by the polling thread.
  */
-static void edac_check(struct mem_ctl_info *mci)
+static void edac_error_check(struct mem_ctl_info *mci)
 {
struct synps_edac_priv *priv = mci->pvt_info;
+   const struct synps_platform_data *p_data = priv->p_data;
int status;
 
-   status = edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = p_data->geterror_info(priv);
if (status)
return;
 
@@ -253,7 +277,7 @@ static void edac_check(struct mem_ctl_info *mci)
 }
 
 /**
- * edac_get_dtype - Return the controller memory width.
+ * zynq_get_dtype - Return the controller memory width.
  * @base:  DDR memory controller base address.
  *
  * Get the EDAC device type width appropriate for the current controller
@@ -261,7 +285,7 @@ static void edac_check(struct mem_ctl_info *mci)
  *
  * Return: a device type width enumeration.
  */
-static enum dev_type edac_get_dtype(const void __iomem *base)
+static enum dev_type zynq_get_dtype(const void __iomem *base)
 {
enum dev_type dt;
u32 width;
@@ -284,20 +308,20 @@ static enum dev_type edac_get_dtype(const void __iomem 
*base)
 }
 
 /**
- * edac_get_eccstate - Return the controller ECC enable/disable status.
+ * zynq_get_eccstate - Return the controller ECC enable/disable status.
  * @base:  DDR memory controller base address.
  *
  * Get the ECC enable/disable status for the controller.
  *
  * Return: a ECC status boolean i.e true/false - enabled/disabled.
  */
-static bool edac_get_eccstate(void __iomem *base)
+static bool zynq_get_eccstate(void __iomem *base)
 {
bool state = false;
enum dev_type dt;
u32 ecctype;
 
-   dt = edac_get_dtype(base);
+   dt = zynq_get_dtype(base);
if (dt == DEV_UNKNOWN)
return state;
 
@@ -323,7 +347,7 @@ static u32 edac_get_memsize(void)
 }
 
 /**
- * edac_get_mtype - Returns controller memory type.
+ * zynq_get_mtype - Returns controller memory type.
  * @base:  Synopsys ECC status structure.
  *
  * Get the EDAC memory type appropriate for the current controller
@@ -331,7 +355,7 @@ static u32 edac_get_memsize(void)
  *
  * Return: a memory type enumeration.
  */
-static enum mem_type edac_get_mtype(const vo

[PATCH v6 4/6] edac: synopsys: Add macro defines for ZynqMP DDRC

2018-09-17 Thread Manish Narani
Add macro defines for ZynqMP DDR controller. These macros will be used
for ZyqnMP ECC operations.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 168 +++
 1 file changed, 168 insertions(+)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index eb458e5..6bf7959 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -97,6 +97,174 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORTBIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON0_RANK_MASK  BIT(24)
+#define ECC_POISON0_COLUMN_SHIFT   0
+#define ECC_POISON0_COLUMN_MASK0xFFF
+#define ECC_POISON1_BG_SHIFT   28
+#define ECC_POISON1_BG_MASK0x3000
+#define ECC_POISON1_BANKNR_SHIFT   24
+#define ECC_POISON1_BANKNR_MASK0x700
+#define ECC_POISON1_ROW_SHIFT  0
+#define ECC_POISON1_ROW_MASK   0x3
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK  0x3
+#define ECC_UEPOISON_MASK  0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_CFG_MASK 0xC000
+#define DDRC_MSTR_CFG_SHIFT30
+#define DDRC_MSTR_CFG_X4_MASK  0x0
+#define DDRC_MSTR_CFG_X8_MASK  0x1
+#define DDRC_MSTR_CFG_X16_MASK 0x2
+#define DDRC_MSTR_CFG_X32_MASK 0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#define ROW_MAX_VAL_

[PATCH v7 0/7] EDAC: Enhancements to Synopsys EDAC driver

2018-09-17 Thread Manish Narani
This patch series enhances the current EDAC driver to support different
platforms. This series adds support for ZynqMP DDRC controller in synopsys
EDAC driver. This series also adds Device tree properties and relevant
binding documentation.

Changes in v2:
- Moved checking of DDR_ECC_INTR_SUPPORT from (1/4) to (3/4) as it is
  a feature of ZynqMP DDRC
- The Binding Documentation in (2/4) is modified as per the review
  comments

Changes in v3:
- The commit message in (2/4) is modified (Synopsys EDAC Driver -->
  ZynqMP DDRC)

Changes in v4:
- Updated the commit message in (1/4)
- Renamed function pointer names removing 'synps_' in (1/4)
- Shortened unnecessary long lines as per the review comment on (1/4)

Changes in v5:
- Updated the commit message in (2/4) and (4/4).
- Removed the unnecessary check for match data in probe() in (1/4)
- Some Indentation changes for better readability in (1/4) and (3/4)
- Removed repeated code in (3/4)
- Used 'zynq' and 'zynqmp' instead of 'synps_enh_edac' in function names

Changes in v6:
- Splitted the patches according to functionalities
- Addressed code style comments from v5 review
- Moved the Error Injection to CONFIG_EDAC_DEBUG mode

Changes in v7:
- Included DTS patch (6/7) which was missed in v6 patch set

Manish Narani (7):
  edac: synopsys: Fix code comments and naming convention
  edac: synps: Add platform specific structures for ddrc controller
  dt: bindings: Document ZynqMP DDRC in Synopsys documentation
  edac: synopsys: Add macro defines for ZynqMP DDRC
  edac: synopsys: Add EDAC ECC support for ZynqMP DDRC
  arm64: zynqmp: Add DDRC node
  edac: synopsys: Add Error Injection support for ZynqMP DDRC

 .../bindings/memory-controllers/synopsys.txt   |   27 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |7 +
 drivers/edac/Kconfig   |2 +-
 drivers/edac/synopsys_edac.c   | 1098 ++--
 4 files changed, 1014 insertions(+), 120 deletions(-)

-- 
2.1.1



[PATCH v7 1/7] edac: synopsys: Fix code comments and naming convention

2018-09-17 Thread Manish Narani
Update the comments in the Synopsys EDAC driver. Minor changes to function
names and return types are also included.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 176 ---
 1 file changed, 80 insertions(+), 96 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 0c9c59e..4963930 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -96,12 +96,12 @@
 #define SCRUB_MODE_SECDED  0x4
 
 /**
- * struct ecc_error_info - ECC error log information
- * @row:   Row number
- * @col:   Column number
- * @bank:  Bank number
- * @bitpos:Bit position
- * @data:  Data causing the error
+ * struct ecc_error_info - ECC error log information.
+ * @row:   Row number.
+ * @col:   Column number.
+ * @bank:  Bank number.
+ * @bitpos:Bit position.
+ * @data:  Data causing the error.
  */
 struct ecc_error_info {
u32 row;
@@ -112,11 +112,11 @@ struct ecc_error_info {
 };
 
 /**
- * struct synps_ecc_status - ECC status information to report
- * @ce_cnt:Correctable error count
- * @ue_cnt:Uncorrectable error count
- * @ceinfo:Correctable error log information
- * @ueinfo:Uncorrectable error log information
+ * struct synps_ecc_status - ECC status information to report.
+ * @ce_cnt:Correctable error count.
+ * @ue_cnt:Uncorrectable error count.
+ * @ceinfo:Correctable error log information.
+ * @ueinfo:Uncorrectable error log information.
  */
 struct synps_ecc_status {
u32 ce_cnt;
@@ -126,12 +126,12 @@ struct synps_ecc_status {
 };
 
 /**
- * struct synps_edac_priv - DDR memory controller private instance data
- * @baseaddr:  Base address of the DDR controller
- * @message:   Buffer for framing the event specific info
- * @stat:  ECC status information
- * @ce_cnt:Correctable Error count
- * @ue_cnt:Uncorrectable Error count
+ * struct synps_edac_priv - DDR memory controller private instance data.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -142,15 +142,13 @@ struct synps_edac_priv {
 };
 
 /**
- * synps_edac_geterror_info - Get the current ecc error info
- * @base:  Pointer to the base address of the ddr memory controller
- * @p: Pointer to the synopsys ecc status structure
+ * edac_geterror_info - Get the current ECC error info.
+ * @base:  Base address of the DDR memory controller.
+ * @p: Synopsys ECC status structure.
  *
- * Determines there is any ecc error or not
- *
- * Return: one if there is no error otherwise returns zero
+ * Return: one if there is no error otherwise returns zero.
  */
-static int synps_edac_geterror_info(void __iomem *base,
+static int edac_geterror_info(void __iomem *base,
struct synps_ecc_status *p)
 {
u32 regval, clearval = 0;
@@ -172,7 +170,7 @@ static int synps_edac_geterror_info(void __iomem *base,
p->ceinfo.col = regval & ADDR_COL_MASK;
p->ceinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT;
p->ceinfo.data = readl(base + CE_DATA_31_0_OFST);
-   edac_dbg(3, "ce bit position: %d data: %d\n", p->ceinfo.bitpos,
+   edac_dbg(3, "CE bit position: %d data: %d\n", p->ceinfo.bitpos,
 p->ceinfo.data);
clearval = ECC_CTRL_CLR_CE_ERR;
 
@@ -196,13 +194,13 @@ static int synps_edac_geterror_info(void __iomem *base,
 }
 
 /**
- * synps_edac_handle_error - Handle controller error types CE and UE
- * @mci:   Pointer to the edac memory controller instance
- * @p: Pointer to the synopsys ecc status structure
+ * edac_handle_error - Handle controller error types CE and UE.
+ * @mci:   EDAC memory controller instance.
+ * @p: Synopsys ECC status structure.
  *
- * Handles the controller ECC correctable and un correctable error.
+ * Handles the controller ECC correctable and un-correctable error.
  */
-static void synps_edac_handle_error(struct mem_ctl_info *mci,
+static void edac_handle_error(struct mem_ctl_info *mci,
struct synps_ecc_status *p)
 {
struct synps_edac_priv *priv = mci->pvt_info;
@@ -232,38 +230,38 @@ static void synps_edac_handle_error(struct mem_ctl_info 
*mci,
 }
 
 /**
- * synps_edac_check - Check controller for ECC errors
- * @mci:   Pointer to the edac memory controller instance
+ * edac_check - Check controller for ECC errors.
+ * @mci:   EDAC memory controller instance.
  *
- * Used to check and post ECC errors. Called by the polling thread
+ * Used to check and post ECC errors. Called by the polling thread.
  */
-static void synps_edac_check(struct mem_ctl

[PATCH v7 2/7] edac: synps: Add platform specific structures for ddrc controller

2018-09-17 Thread Manish Narani
Add platform specific structures, so that we can add different IP
support later using quirks.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 91 +++-
 1 file changed, 65 insertions(+), 26 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 4963930..eb458e5 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "edac_module.h"
 
@@ -130,6 +132,7 @@ struct synps_ecc_status {
  * @baseaddr:  Base address of the DDR controller.
  * @message:   Buffer for framing the event specific info.
  * @stat:  ECC status information.
+ * @p_data:Platform data
  * @ce_cnt:Correctable Error count.
  * @ue_cnt:Uncorrectable Error count.
  */
@@ -137,21 +140,41 @@ struct synps_edac_priv {
void __iomem *baseaddr;
char message[SYNPS_EDAC_MSG_SIZE];
struct synps_ecc_status stat;
+   const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
 };
 
 /**
- * edac_geterror_info - Get the current ECC error info.
- * @base:  Base address of the DDR memory controller.
- * @p: Synopsys ECC status structure.
+ * struct synps_platform_data -  synps platform data structure.
+ * @geterror_info: Get error info.
+ * @get_mtype: Get mtype.
+ * @get_dtype: Get dtype.
+ * @get_eccstate:  Get eccstate.
+ * @quirks:To differentiate IPs.
+ */
+struct synps_platform_data {
+   int (*geterror_info)(struct synps_edac_priv *priv);
+   enum mem_type (*get_mtype)(const void __iomem *base);
+   enum dev_type (*get_dtype)(const void __iomem *base);
+   bool (*get_eccstate)(void __iomem *base);
+   int quirks;
+};
+
+/**
+ * zynq_geterror_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
  *
  * Return: one if there is no error otherwise returns zero.
  */
-static int edac_geterror_info(void __iomem *base,
-   struct synps_ecc_status *p)
+static int zynq_geterror_info(struct synps_edac_priv *priv)
 {
+   struct synps_ecc_status *p;
u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
 
regval = readl(base + STAT_OFST);
if (!regval)
@@ -230,17 +253,18 @@ static void edac_handle_error(struct mem_ctl_info *mci,
 }
 
 /**
- * edac_check - Check controller for ECC errors.
+ * edac_error_check - Check controller for ECC errors.
  * @mci:   EDAC memory controller instance.
  *
  * Used to check and post ECC errors. Called by the polling thread.
  */
-static void edac_check(struct mem_ctl_info *mci)
+static void edac_error_check(struct mem_ctl_info *mci)
 {
struct synps_edac_priv *priv = mci->pvt_info;
+   const struct synps_platform_data *p_data = priv->p_data;
int status;
 
-   status = edac_geterror_info(priv->baseaddr, &priv->stat);
+   status = p_data->geterror_info(priv);
if (status)
return;
 
@@ -253,7 +277,7 @@ static void edac_check(struct mem_ctl_info *mci)
 }
 
 /**
- * edac_get_dtype - Return the controller memory width.
+ * zynq_get_dtype - Return the controller memory width.
  * @base:  DDR memory controller base address.
  *
  * Get the EDAC device type width appropriate for the current controller
@@ -261,7 +285,7 @@ static void edac_check(struct mem_ctl_info *mci)
  *
  * Return: a device type width enumeration.
  */
-static enum dev_type edac_get_dtype(const void __iomem *base)
+static enum dev_type zynq_get_dtype(const void __iomem *base)
 {
enum dev_type dt;
u32 width;
@@ -284,20 +308,20 @@ static enum dev_type edac_get_dtype(const void __iomem 
*base)
 }
 
 /**
- * edac_get_eccstate - Return the controller ECC enable/disable status.
+ * zynq_get_eccstate - Return the controller ECC enable/disable status.
  * @base:  DDR memory controller base address.
  *
  * Get the ECC enable/disable status for the controller.
  *
  * Return: a ECC status boolean i.e true/false - enabled/disabled.
  */
-static bool edac_get_eccstate(void __iomem *base)
+static bool zynq_get_eccstate(void __iomem *base)
 {
bool state = false;
enum dev_type dt;
u32 ecctype;
 
-   dt = edac_get_dtype(base);
+   dt = zynq_get_dtype(base);
if (dt == DEV_UNKNOWN)
return state;
 
@@ -323,7 +347,7 @@ static u32 edac_get_memsize(void)
 }
 
 /**
- * edac_get_mtype - Returns controller memory type.
+ * zynq_get_mtype - Returns controller memory type.
  * @base:  Synopsys ECC status structure.
  *
  * Get the EDAC memory type appropriate for the current controller
@@ -331,7 +355,7 @@ static u32 edac_get_memsize(void)
  *
  * Return: a memory type enumeration.
  */
-static enum mem_type edac_get_mtype(const vo

[PATCH v7 5/7] edac: synopsys: Add EDAC ECC support for ZynqMP DDRC

2018-09-17 Thread Manish Narani
Add EDAC ECC support for ZynqMP DDRC IP. The IP supports interrupts for
corrected and uncorrected errors. Add interrupt handlers for the same.

Signed-off-by: Manish Narani 
---
 drivers/edac/Kconfig |   2 +-
 drivers/edac/synopsys_edac.c | 304 ---
 2 files changed, 287 insertions(+), 19 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2..b1fc7a16 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -441,7 +441,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SYNOPSYS
tristate "Synopsys DDR Memory Controller"
-   depends on ARCH_ZYNQ
+   depends on ARCH_ZYNQ || ARM64
help
  Support for error detection and correction on the Synopsys DDR
  memory controller.
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 6bf7959..7ab5b9a 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -272,6 +273,8 @@
  * @bank:  Bank number.
  * @bitpos:Bit position.
  * @data:  Data causing the error.
+ * @bankgrpnr: Bank group number.
+ * @blknr: Block number.
  */
 struct ecc_error_info {
u32 row;
@@ -279,6 +282,8 @@ struct ecc_error_info {
u32 bank;
u32 bitpos;
u32 data;
+   u32 bankgrpnr;
+   u32 blknr;
 };
 
 /**
@@ -385,6 +390,68 @@ static int zynq_geterror_info(struct synps_edac_priv *priv)
 }
 
 /**
+ * zynqmp_geterror_info - Get the current ECC error info.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Return: one if there is no error otherwise returns zero.
+ */
+static int zynqmp_geterror_info(struct synps_edac_priv *priv)
+{
+   struct synps_ecc_status *p;
+   u32 regval, clearval = 0;
+   void __iomem *base;
+
+   base = priv->baseaddr;
+   p = &priv->stat;
+
+   regval = readl(base + ECC_STAT_OFST);
+   if (!regval)
+   return 1;
+
+   p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
+   p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
+   p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
+
+   regval = readl(base + ECC_CEADDR0_OFST);
+   if (!(p->ce_cnt))
+   goto ue_err;
+
+   p->ceinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_CEADDR1_OFST);
+   p->ceinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ceinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ceinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ceinfo.data = readl(base + ECC_CSYND0_OFST);
+   edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n",
+readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST),
+readl(base + ECC_CSYND2_OFST));
+
+
+ue_err:
+   regval = readl(base + ECC_UEADDR0_OFST);
+   if (!(p->ue_cnt))
+   goto out;
+
+   p->ueinfo.row = (regval & ECC_CEADDR0_RW_MASK);
+   regval = readl(base + ECC_UEADDR1_OFST);
+   p->ueinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >>
+   ECC_CEADDR1_BNKGRP_SHIFT;
+   p->ueinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >>
+   ECC_CEADDR1_BNKNR_SHIFT;
+   p->ueinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK);
+   p->ueinfo.data = readl(base + ECC_UESYND0_OFST);
+out:
+   clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT;
+   clearval |= ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT;
+   writel(clearval, base + ECC_CLR_OFST);
+   writel(0x0, base + ECC_CLR_OFST);
+
+   return 0;
+}
+
+/**
  * edac_handle_error - Handle controller error types CE and UE.
  * @mci:   EDAC memory controller instance.
  * @p: Synopsys ECC status structure.
@@ -399,9 +466,25 @@ static void edac_handle_error(struct mem_ctl_info *mci,
 
if (p->ce_cnt) {
pinf = &p->ceinfo;
-   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-"DDR ECC error type :%s Row %d Bank %d Col %d ",
-"CE", pinf->row, pinf->bank, pinf->col);
+   if (!priv->p_data->quirks) {
+   snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
+"DDR ECC error type:%s Row %d Bank %d Col %d ",
+ "CE", pinf->row, pinf->bank, pinf->col);
+   snprintf(priv->message, SYN

[PATCH v7 6/7] arm64: zynqmp: Add DDRC node

2018-09-17 Thread Manish Narani
Add ddrc memory controller node in dts. The size mentioned in dts is
0x3, because we need to access DDR_QOS INTR registers located at
0xFD090208 from this driver.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 29ce234..a81d3b16 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -355,6 +355,13 @@
xlnx,bus-width = <64>;
};
 
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
+
gem0: ethernet@ff0b {
compatible = "cdns,zynqmp-gem", "cdns,gem";
status = "disabled";
-- 
2.1.1



[PATCH v7 7/7] edac: synopsys: Add Error Injection support for ZynqMP DDRC

2018-09-17 Thread Manish Narani
Add support for Error Injection for ZynqMP DDRC IP. For injecting
errors, the Row, Column, Bank, Bank Group and Rank bits positions are
determined via Address Map registers of Synopsys DDRC.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 423 ++-
 1 file changed, 417 insertions(+), 6 deletions(-)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 7ab5b9a..177b5c3 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -302,12 +302,18 @@ struct synps_ecc_status {
 
 /**
  * struct synps_edac_priv - DDR memory controller private instance data.
- * @baseaddr:  Base address of the DDR controller.
- * @message:   Buffer for framing the event specific info.
- * @stat:  ECC status information.
- * @p_data:Platform data
- * @ce_cnt:Correctable Error count.
- * @ue_cnt:Uncorrectable Error count.
+ * @baseaddr:  Base address of the DDR controller.
+ * @message:   Buffer for framing the event specific info.
+ * @stat:  ECC status information.
+ * @p_data:Platform data
+ * @ce_cnt:Correctable Error count.
+ * @ue_cnt:Uncorrectable Error count.
+ * @poison_addr:   Data poison address.
+ * @row_shift: Bit shifts for row bit.
+ * @col_shift: Bit shifts for column bit.
+ * @bank_shift:Bit shifts for bank bit.
+ * @bankgrp_shift: Bit shifts for bank group bit.
+ * @rank_shift:Bit shifts for rank bit.
  */
 struct synps_edac_priv {
void __iomem *baseaddr;
@@ -316,6 +322,14 @@ struct synps_edac_priv {
const struct synps_platform_data *p_data;
u32 ce_cnt;
u32 ue_cnt;
+#ifdef CONFIG_EDAC_DEBUG
+   ulong poison_addr;
+   u32 row_shift[18];
+   u32 col_shift[14];
+   u32 bank_shift[3];
+   u32 bankgrp_shift[2];
+   u32 rank_shift[1];
+#endif
 };
 
 /**
@@ -842,7 +856,12 @@ static const struct synps_platform_data zynqmp_edac_def = {
.get_mtype  = zynqmp_get_mtype,
.get_dtype  = zynqmp_get_dtype,
.get_eccstate   = zynqmp_get_eccstate,
+#ifdef CONFIG_EDAC_DEBUG
+   .quirks = (DDR_ECC_INTR_SUPPORT |
+  DDR_ECC_DATA_POISON_SUPPORT),
+#else
.quirks = DDR_ECC_INTR_SUPPORT,
+#endif
 };
 
 static const struct of_device_id synps_edac_match[] = {
@@ -861,6 +880,380 @@ static const struct of_device_id synps_edac_match[] = {
 
 MODULE_DEVICE_TABLE(of, synps_edac_match);
 
+#ifdef CONFIG_EDAC_DEBUG
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/**
+ * ddr_poison_setup -  Update poison registers.
+ * @priv:  DDR memory controller private instance data.
+ *
+ * Update poison registers as per DDR mapping.
+ * Return: none.
+ */
+static void ddr_poison_setup(struct synps_edac_priv *priv)
+{
+   int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
+   int index;
+   ulong hif_addr = 0;
+
+   hif_addr = priv->poison_addr >> 3;
+
+   for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
+   if (priv->row_shift[index])
+   row |= (((hif_addr >> priv->row_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_COL_SHIFT; index++) {
+   if (priv->col_shift[index] || index < 3)
+   col |= (((hif_addr >> priv->col_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) {
+   if (priv->bank_shift[index])
+   bank |= (((hif_addr >> priv->bank_shift[index]) &
+   BIT(0)) << index);
+   else
+   break;
+   }
+
+   for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) {
+   if (priv->bankgrp_shift[index])
+   bankgrp |= (((hif_addr >> priv->bankgrp_shift[index])
+   & BIT(0)) << index);
+   else
+   break;
+   }
+
+   if (priv->rank_shift[0])
+   rank = (hif_addr >> priv->rank_shift[0]) & BIT(0);
+
+   regval = (rank << ECC_POISON0_RANK_SHIFT) & ECC_POISON0_RANK_MASK;
+   regval |= (col << ECC_POISON0_COLUMN_SHIFT) & ECC_POISON0_COLUMN_MASK;
+   writel(regval, priv->baseaddr + ECC_POISON0_OFST);
+
+   regval = (bankgrp << ECC_POISON1_BG_SHIFT) & ECC_POISON1_BG_MASK;
+   regval |= (bank << ECC_POISON1_BANKNR_SHIFT) & ECC_POISON1_BANKNR_MASK;
+   

[PATCH v7 3/7] dt: bindings: Document ZynqMP DDRC in Synopsys documentation

2018-09-17 Thread Manish Narani
Add information of ZynqMP DDRC which reports the single bit errors that
are corrected and the double bit errors that are detected.

Signed-off-by: Manish Narani 
Reviewed-by: Rob Herring 
---
 .../bindings/memory-controllers/synopsys.txt   | 27 ++
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt 
b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
index a43d26d..9d32762 100644
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -1,15 +1,32 @@
 Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
 
-This controller has an optional ECC support in half-bus width (16-bit)
-configuration. The ECC controller corrects one bit error and detects
-two bit errors.
+The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
+bus width configurations.
+
+The Zynq DDR ECC controller has an optional ECC support in half-bus width
+(16-bit) configuration.
+
+These both ECC controllers correct single bit ECC errors and detect double bit
+ECC errors.
 
 Required properties:
- - compatible: Should be 'xlnx,zynq-ddrc-a05'
- - reg: Base address and size of the controllers memory area
+ - compatible: One of:
+   - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
+   - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
+ - reg: Should contain DDR controller registers location and length.
+
+Required properties for "xlnx,zynqmp-ddrc-2.40a":
+ - interrupts: Property with a value describing the interrupt number.
 
 Example:
memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
+
+   mc: memory-controller@fd07 {
+   compatible = "xlnx,zynqmp-ddrc-2.40a";
+   reg = <0x0 0xfd07 0x0 0x3>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 112 4>;
+   };
-- 
2.1.1



[PATCH v7 4/7] edac: synopsys: Add macro defines for ZynqMP DDRC

2018-09-17 Thread Manish Narani
Add macro defines for ZynqMP DDR controller. These macros will be used
for ZyqnMP ECC operations.

Signed-off-by: Manish Narani 
---
 drivers/edac/synopsys_edac.c | 168 +++
 1 file changed, 168 insertions(+)

diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index eb458e5..6bf7959 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -97,6 +97,174 @@
 #define SCRUB_MODE_MASK0x7
 #define SCRUB_MODE_SECDED  0x4
 
+/* DDR ECC Quirks */
+#define DDR_ECC_INTR_SUPPORT   BIT(0)
+#define DDR_ECC_DATA_POISON_SUPPORTBIT(1)
+
+/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
+/* ECC Configuration Registers */
+#define ECC_CFG0_OFST  0x70
+#define ECC_CFG1_OFST  0x74
+
+/* ECC Status Register */
+#define ECC_STAT_OFST  0x78
+
+/* ECC Clear Register */
+#define ECC_CLR_OFST   0x7C
+
+/* ECC Error count Register */
+#define ECC_ERRCNT_OFST0x80
+
+/* ECC Corrected Error Address Register */
+#define ECC_CEADDR0_OFST   0x84
+#define ECC_CEADDR1_OFST   0x88
+
+/* ECC Syndrome Registers */
+#define ECC_CSYND0_OFST0x8C
+#define ECC_CSYND1_OFST0x90
+#define ECC_CSYND2_OFST0x94
+
+/* ECC Bit Mask0 Address Register */
+#define ECC_BITMASK0_OFST  0x98
+#define ECC_BITMASK1_OFST  0x9C
+#define ECC_BITMASK2_OFST  0xA0
+
+/* ECC UnCorrected Error Address Register */
+#define ECC_UEADDR0_OFST   0xA4
+#define ECC_UEADDR1_OFST   0xA8
+
+/* ECC Syndrome Registers */
+#define ECC_UESYND0_OFST   0xAC
+#define ECC_UESYND1_OFST   0xB0
+#define ECC_UESYND2_OFST   0xB4
+
+/* ECC Poison Address Reg */
+#define ECC_POISON0_OFST   0xB8
+#define ECC_POISON1_OFST   0xBC
+
+#define ECC_ADDRMAP0_OFFSET0x200
+
+/* Control register bitfield definitions */
+#define ECC_CTRL_BUSWIDTH_MASK 0x3000
+#define ECC_CTRL_BUSWIDTH_SHIFT12
+#define ECC_CTRL_CLR_CE_ERRCNT BIT(2)
+#define ECC_CTRL_CLR_UE_ERRCNT BIT(3)
+
+/* DDR Control Register width definitions  */
+#define DDRCTL_EWDTH_162
+#define DDRCTL_EWDTH_321
+#define DDRCTL_EWDTH_640
+
+/* ECC status register definitions */
+#define ECC_STAT_UECNT_MASK0xF
+#define ECC_STAT_UECNT_SHIFT   16
+#define ECC_STAT_CECNT_MASK0xF00
+#define ECC_STAT_CECNT_SHIFT   8
+#define ECC_STAT_BITNUM_MASK   0x7F
+
+/* DDR QOS Interrupt register definitions */
+#define DDR_QOS_IRQ_STAT_OFST  0x20200
+#define DDR_QOSUE_MASK 0x4
+#defineDDR_QOSCE_MASK  0x2
+#defineECC_CE_UE_INTR_MASK 0x6
+#define DDR_QOS_IRQ_EN_OFST0x20208
+#define DDR_QOS_IRQ_DB_OFST0x2020C
+
+/* ECC Corrected Error Register Mask and Shifts*/
+#define ECC_CEADDR0_RW_MASK0x3
+#define ECC_CEADDR0_RNK_MASK   BIT(24)
+#define ECC_CEADDR1_BNKGRP_MASK0x300
+#define ECC_CEADDR1_BNKNR_MASK 0x7
+#define ECC_CEADDR1_BLKNR_MASK 0xFFF
+#define ECC_CEADDR1_BNKGRP_SHIFT   24
+#define ECC_CEADDR1_BNKNR_SHIFT16
+
+/* ECC Poison register shifts */
+#define ECC_POISON0_RANK_SHIFT 24
+#define ECC_POISON0_RANK_MASK  BIT(24)
+#define ECC_POISON0_COLUMN_SHIFT   0
+#define ECC_POISON0_COLUMN_MASK0xFFF
+#define ECC_POISON1_BG_SHIFT   28
+#define ECC_POISON1_BG_MASK0x3000
+#define ECC_POISON1_BANKNR_SHIFT   24
+#define ECC_POISON1_BANKNR_MASK0x700
+#define ECC_POISON1_ROW_SHIFT  0
+#define ECC_POISON1_ROW_MASK   0x3
+
+/* DDR Memory type defines */
+#define MEM_TYPE_DDR3  0x1
+#define MEM_TYPE_LPDDR30x8
+#define MEM_TYPE_DDR2  0x4
+#define MEM_TYPE_DDR4  0x10
+#define MEM_TYPE_LPDDR40x20
+
+/* DDRC Software control register */
+#define DDRC_SWCTL 0x320
+
+/* DDRC ECC CE & UE poison mask */
+#define ECC_CEPOISON_MASK  0x3
+#define ECC_UEPOISON_MASK  0x1
+
+/* DDRC Device config masks */
+#define DDRC_MSTR_CFG_MASK 0xC000
+#define DDRC_MSTR_CFG_SHIFT30
+#define DDRC_MSTR_CFG_X4_MASK  0x0
+#define DDRC_MSTR_CFG_X8_MASK  0x1
+#define DDRC_MSTR_CFG_X16_MASK 0x2
+#define DDRC_MSTR_CFG_X32_MASK 0x3
+
+#define DDR_MAX_ROW_SHIFT  18
+#define DDR_MAX_COL_SHIFT  14
+#define DDR_MAX_BANK_SHIFT 3
+#define DDR_MAX_BANKGRP_SHIFT  2
+
+#define ROW_MAX_VAL_

[RFC PATCH 0/4] Add auto tuning support for ZynqMP SDHCI controller

2018-09-18 Thread Manish Narani
This series of patches are created On top of the
below series of patches.
https://lkml.org/lkml/2018/8/3/687 

Manish Narani (4):
  firmware: xilinx: Add SD Node and DLL Reset Data APIs
  dt-bindings: mmc: arasan: Document 'xlnx,zynqmp-8.9a' controller
  mmc: sdhci-of-arasan: Add auto tuning support for ZynqMP platform
  arm64: zynqmp: Add new SDHCI compatible string

 .../devicetree/bindings/mmc/arasan,sdhci.txt   | 14 
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi |  6 +-
 drivers/mmc/host/sdhci-of-arasan.c | 83 ++
 include/linux/firmware/xlnx-zynqmp.h   | 12 
 4 files changed, 113 insertions(+), 2 deletions(-)

-- 
2.1.1



[RFC PATCH 3/4] mmc: sdhci-of-arasan: Add auto tuning support for ZynqMP platform

2018-09-18 Thread Manish Narani
Add support of SD auto tuning for ZynqMP platform. Before tuning
execution, reset the DLL and after the auto tuning process gets
completed, reset the DLL to load the newly obtained SDHC tuned tap
value.

Signed-off-by: Manish Narani 
---
 drivers/mmc/host/sdhci-of-arasan.c | 83 ++
 1 file changed, 83 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-arasan.c 
b/drivers/mmc/host/sdhci-of-arasan.c
index a40bcc2..1a8bbd2 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cqhci.h"
 #include "sdhci-pltfm.h"
@@ -98,6 +99,7 @@ struct sdhci_arasan_data {
 
struct regmap   *soc_ctl_base;
const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
+   unsigned intdevice_id;
unsigned intquirks; /* Arasan deviations from spec */
 
 /* Controller does not have CD wired and will not function normally without */
@@ -163,6 +165,72 @@ static int sdhci_arasan_syscon_write(struct sdhci_host 
*host,
return ret;
 }
 
+static void zynqmp_dll_reset(u8 deviceid)
+{
+   const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+   if (!eemi_ops || !eemi_ops->ioctl)
+   return;
+
+   /* Issue DLL Reset */
+   if (deviceid == 0)
+   eemi_ops->ioctl(NODE_SD_0, IOCTL_SD_DLL_RESET,
+   PM_DLL_RESET_PULSE, 0, NULL);
+   else
+   eemi_ops->ioctl(NODE_SD_1, IOCTL_SD_DLL_RESET,
+   PM_DLL_RESET_PULSE, 0, NULL);
+}
+
+static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
+{
+   u16 clk;
+   unsigned long timeout;
+
+   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   clk &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+   /* Issue DLL Reset */
+   zynqmp_dll_reset(deviceid);
+
+   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   clk |= SDHCI_CLOCK_INT_EN;
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+   /* Wait max 20 ms */
+   timeout = 20;
+   while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+   & SDHCI_CLOCK_INT_STABLE)) {
+   if (timeout == 0) {
+   dev_err(mmc_dev(host->mmc),
+   ": Internal clock never stabilised.\n");
+   return;
+   }
+   timeout--;
+   mdelay(1);
+   }
+
+   clk |= SDHCI_CLOCK_CARD_EN;
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static int arasan_zynqmp_execute_tuning(struct mmc_host *mmc, u32 opcode) {
+   struct sdhci_host *host = mmc_priv(mmc);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+   int err;
+
+   arasan_zynqmp_dll_reset(host, sdhci_arasan->device_id);
+
+   err = sdhci_execute_tuning(mmc, opcode);
+   if (err)
+   return err;
+
+   arasan_zynqmp_dll_reset(host, sdhci_arasan->device_id);
+
+   return 0;
+}
+
 static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -469,6 +537,7 @@ static const struct of_device_id sdhci_arasan_of_match[] = {
{ .compatible = "arasan,sdhci-8.9a" },
{ .compatible = "arasan,sdhci-5.1" },
{ .compatible = "arasan,sdhci-4.9a" },
+   { .compatible = "xlnx,zynqmp-8.9a" },
 
{ /* sentinel */ }
 };
@@ -792,6 +861,20 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
goto unreg_clk;
}
 
+   if (of_device_is_compatible(pdev->dev.of_node, "xlnx,zynqmp-8.9a")) {
+   ret = of_property_read_u32(pdev->dev.of_node,
+  "xlnx,device_id",
+  &sdhci_arasan->device_id);
+   if (ret < 0) {
+   dev_err(&pdev->dev,
+   "\"xlnx,device_id \" property is missing.\n");
+   goto unreg_clk;
+   }
+
+   host->mmc_host_ops.execute_tuning =
+   arasan_zynqmp_execute_tuning;
+   }
+
sdhci_arasan->phy = ERR_PTR(-ENODEV);
if (of_device_is_compatible(pdev->dev.of_node,
"arasan,sdhci-5.1")) {
-- 
2.1.1



[RFC PATCH 1/4] firmware: xilinx: Add SD Node and DLL Reset Data APIs

2018-09-18 Thread Manish Narani
Add ZynqMP firmware SD Node data API to be used in call from SDHCI
driver. Also add DLL Reset data API to used for DLL reset calls from any
drivers.

Signed-off-by: Manish Narani 
---
 include/linux/firmware/xlnx-zynqmp.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/include/linux/firmware/xlnx-zynqmp.h 
b/include/linux/firmware/xlnx-zynqmp.h
index 58a7478..743687b 100644
--- a/include/linux/firmware/xlnx-zynqmp.h
+++ b/include/linux/firmware/xlnx-zynqmp.h
@@ -58,13 +58,25 @@ enum pm_ret_status {
XST_PM_ABORT_SUSPEND,
 };
 
+enum pm_node_id {
+   NODE_SD_0 = 39,
+   NODE_SD_1,
+};
+
 enum pm_ioctl_id {
+   IOCTL_SD_DLL_RESET = 6,
IOCTL_SET_PLL_FRAC_MODE = 8,
IOCTL_GET_PLL_FRAC_MODE,
IOCTL_SET_PLL_FRAC_DATA,
IOCTL_GET_PLL_FRAC_DATA,
 };
 
+enum dll_reset_type {
+   PM_DLL_RESET_ASSERT,
+   PM_DLL_RESET_RELEASE,
+   PM_DLL_RESET_PULSE,
+};
+
 enum pm_query_id {
PM_QID_INVALID,
PM_QID_CLOCK_GET_NAME,
-- 
2.1.1



[RFC PATCH 4/4] arm64: zynqmp: Add new SDHCI compatible string

2018-09-18 Thread Manish Narani
Mainline kernel has arasan compatible string now. Append this new
compatible string for ZynqMP SDHCI controller. Also add a required
property indicating ZynqMP SDHCI controller device ID.

Signed-off-by: Manish Narani 
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi 
b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 29ce234..1def7e1 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -485,21 +485,23 @@
};
 
sdhci0: sdhci@ff16 {
-   compatible = "arasan,sdhci-8.9a";
+   compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 48 4>;
reg = <0x0 0xff16 0x0 0x1000>;
clock-names = "clk_xin", "clk_ahb";
+   xlnx,device_id = <0>;
};
 
sdhci1: sdhci@ff17 {
-   compatible = "arasan,sdhci-8.9a";
+   compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 49 4>;
reg = <0x0 0xff17 0x0 0x1000>;
clock-names = "clk_xin", "clk_ahb";
+   xlnx,device_id = <1>;
};
 
smmu: smmu@fd80 {
-- 
2.1.1



[RFC PATCH 2/4] dt-bindings: mmc: arasan: Document 'xlnx,zynqmp-8.9a' controller

2018-09-18 Thread Manish Narani
Add documentation for 'xlnx,zynqmp-8.9a' SDHCI controller and required
properties followed by example.

Signed-off-by: Manish Narani 
---
 Documentation/devicetree/bindings/mmc/arasan,sdhci.txt | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt 
b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
index f6ddba3..72769e0 100644
--- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
@@ -15,6 +15,7 @@ Required Properties:
 - "arasan,sdhci-5.1": generic Arasan SDHCI 5.1 PHY
 - "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1": rk3399 eMMC PHY
   For this device it is strongly suggested to include 
arasan,soc-ctl-syscon.
+- "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a": Xilinx ZynqMP Arasan SDHCI 8.9a 
PHY
   - reg: From mmc bindings: Register location and length.
   - clocks: From clock bindings: Handles to clock inputs.
   - clock-names: From clock bindings: Tuple including "clk_xin" and "clk_ahb"
@@ -24,6 +25,9 @@ Required Properties for "arasan,sdhci-5.1":
   - phys: From PHY bindings: Phandle for the Generic PHY for arasan.
   - phy-names:  MUST be "phy_arasan".
 
+Required Properties for "xlnx,zynqmp-8.9a":
+  - xlnx,device_id: SD controller device ID. Must be either <0> or <1>.
+
 Optional Properties:
   - arasan,soc-ctl-syscon: A phandle to a syscon device (see ../mfd/syscon.txt)
 used to access core corecfg registers.  Offsets of registers in this
@@ -75,3 +79,13 @@ Example:
phy-names = "phy_arasan";
#clock-cells = <0>;
};
+
+   sdhci: sdhci@ff16 {
+   compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
+   reg = <0x0 0xff16 0x0 0x1000>;
+   interrupt-parent = <&gic>;
+   interrupts = <0 48 4>;
+   clock-names = "clk_xin", "clk_ahb";
+   clocks = <&clk 54>, <&clk 31>;
+   xlnx,device_id = <0>;
+   };
-- 
2.1.1



[PATCH] sdhci: arasan: Add runtime PM support

2018-09-18 Thread Manish Narani
Add runtime PM support in Arasan SDHCI driver.

Signed-off-by: Manish Narani 
---
 drivers/mmc/host/sdhci-of-arasan.c | 80 +-
 1 file changed, 78 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-arasan.c 
b/drivers/mmc/host/sdhci-of-arasan.c
index a40bcc2..370ada5 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,7 @@
 #include "cqhci.h"
 #include "sdhci-pltfm.h"
 
+#define SDHCI_ARASAN_AUTOSUSPEND_DELAY 2000 /* ms */
 #define SDHCI_ARASAN_VENDOR_REGISTER   0x78
 #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
 #define VENDOR_ENHANCED_STROBE BIT(0)
@@ -363,6 +365,70 @@ static const struct sdhci_pltfm_data 
sdhci_arasan_cqe_pdata = {
SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
 };
 
+#ifdef CONFIG_PM
+static int sdhci_arasan_runtime_suspend(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct sdhci_host *host = platform_get_drvdata(pdev);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+   int ret;
+
+   if (sdhci_arasan->has_cqe) {
+   ret = cqhci_suspend(host->mmc);
+   if (ret)
+   return ret;
+   }
+
+   ret = sdhci_runtime_suspend_host(host);
+   if (ret)
+   return ret;
+
+   if (host->tuning_mode != SDHCI_TUNING_MODE_3)
+   mmc_retune_needed(host->mmc);
+
+   clk_disable(pltfm_host->clk);
+   clk_disable(sdhci_arasan->clk_ahb);
+
+   return 0;
+}
+
+static int sdhci_arasan_runtime_resume(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct sdhci_host *host = platform_get_drvdata(pdev);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+   int ret;
+
+   ret = clk_enable(sdhci_arasan->clk_ahb);
+   if (ret) {
+   dev_err(dev, "Cannot enable AHB clock.\n");
+   return ret;
+   }
+
+   ret = clk_enable(pltfm_host->clk);
+   if (ret) {
+   dev_err(dev, "Cannot enable SD clock.\n");
+   return ret;
+   }
+
+   ret = sdhci_runtime_resume_host(host);
+   if (ret)
+   goto out;
+
+   if (sdhci_arasan->has_cqe)
+   return cqhci_resume(host->mmc);
+
+   return 0;
+out:
+   clk_disable(pltfm_host->clk);
+   clk_disable(sdhci_arasan->clk_ahb);
+
+   return ret;
+}
+#endif /* ! CONFIG_PM */
+
 #ifdef CONFIG_PM_SLEEP
 /**
  * sdhci_arasan_suspend - Suspend method for the driver
@@ -455,8 +521,10 @@ static int sdhci_arasan_resume(struct device *dev)
 }
 #endif /* ! CONFIG_PM_SLEEP */
 
-static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
-sdhci_arasan_resume);
+static const struct dev_pm_ops sdhci_arasan_dev_pm_ops = {
+   SET_SYSTEM_SLEEP_PM_OPS(sdhci_arasan_suspend, sdhci_arasan_resume)
+   SET_RUNTIME_PM_OPS(sdhci_arasan_runtime_suspend,
+  sdhci_arasan_runtime_resume, NULL) };
 
 static const struct of_device_id sdhci_arasan_of_match[] = {
/* SoC-specific compatible strings w/ soc_ctl_map */
@@ -821,6 +889,14 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
if (ret)
goto err_add_host;
 
+   pm_runtime_set_active(&pdev->dev);
+   pm_runtime_enable(&pdev->dev);
+   pm_runtime_set_autosuspend_delay(&pdev->dev,
+SDHCI_ARASAN_AUTOSUSPEND_DELAY);
+   pm_runtime_mark_last_busy(&pdev->dev);
+   pm_runtime_use_autosuspend(&pdev->dev);
+   pm_runtime_forbid(&pdev->dev);
+
return 0;
 
 err_add_host:
-- 
2.1.1



[PATCH 4/4] iio: adc: xilinx: Use devm_ functions while requesting irq

2018-07-18 Thread Manish Narani
This patch adds support for using devm_ functions for requesting irq.
This will let the core free irq itself whenever the error condition
happens in probe or when xadc_remove is called.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index 47eb364..7cadcc77 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1229,8 +1229,8 @@ static int xadc_probe(struct platform_device *pdev)
if (ret)
goto err_clk_disable_unprepare;
 
-   ret = request_irq(irq, xadc->ops->interrupt_handler, 0,
-   dev_name(&pdev->dev), indio_dev);
+   ret = devm_request_irq(&pdev->dev, irq, xadc->ops->interrupt_handler, 0,
+  dev_name(&pdev->dev), indio_dev);
if (ret)
goto err_clk_disable_unprepare;
 
@@ -1240,7 +1240,7 @@ static int xadc_probe(struct platform_device *pdev)
 
ret = xadc_write_adc_reg(xadc, XADC_REG_CONF0, conf0);
if (ret)
-   goto err_free_irq;
+   goto err_clk_disable_unprepare;
 
bipolar_mask = 0;
for (i = 0; i < indio_dev->num_channels; i++) {
@@ -1250,17 +1250,17 @@ static int xadc_probe(struct platform_device *pdev)
 
ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(0), bipolar_mask);
if (ret)
-   goto err_free_irq;
+   goto err_clk_disable_unprepare;
ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(1),
bipolar_mask >> 16);
if (ret)
-   goto err_free_irq;
+   goto err_clk_disable_unprepare;
 
/* Disable all alarms */
ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
  XADC_CONF1_ALARM_MASK);
if (ret)
-   goto err_free_irq;
+   goto err_clk_disable_unprepare;
 
/* Set thresholds to min/max */
for (i = 0; i < 16; i++) {
@@ -1281,14 +1281,12 @@ static int xadc_probe(struct platform_device *pdev)
 
ret = iio_device_register(indio_dev);
if (ret)
-   goto err_free_irq;
+   goto err_clk_disable_unprepare;
 
platform_set_drvdata(pdev, indio_dev);
 
return 0;
 
-err_free_irq:
-   free_irq(irq, indio_dev);
 err_clk_disable_unprepare:
clk_disable_unprepare(xadc->clk);
 err_free_samplerate_trigger:
@@ -1310,7 +1308,6 @@ static int xadc_remove(struct platform_device *pdev)
 {
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct xadc *xadc = iio_priv(indio_dev);
-   int irq = platform_get_irq(pdev, 0);
 
iio_device_unregister(indio_dev);
if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
@@ -1318,7 +1315,6 @@ static int xadc_remove(struct platform_device *pdev)
iio_trigger_free(xadc->convst_trigger);
iio_triggered_buffer_cleanup(indio_dev);
}
-   free_irq(irq, indio_dev);
clk_disable_unprepare(xadc->clk);
cancel_delayed_work(&xadc->zynq_unmask_work);
kfree(xadc->data);
-- 
2.1.1



[PATCH 2/4] iio: adc: xilinx: Remove dead code from xadc_zynq_setup

2018-07-18 Thread Manish Narani
This patch removes dead code from xadc_zynq_setup. The condition
"if (tck_rate > XADC_ZYNQ_TCK_RATE_MAX)" cannot be true at any point of
time. There is also an incompatible parameter used in the code.
This patch fixes the same reported by coverity.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index 27b45df..248cffa 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -341,8 +341,6 @@ static int xadc_zynq_setup(struct platform_device *pdev,
 
pcap_rate = clk_get_rate(xadc->clk);
 
-   if (tck_rate > XADC_ZYNQ_TCK_RATE_MAX)
-   tck_rate = XADC_ZYNQ_TCK_RATE_MAX;
if (tck_rate > pcap_rate / 2) {
div = 2;
} else {
@@ -1045,7 +1043,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, 
struct device_node *np,
unsigned int num_channels;
const char *external_mux;
u32 ext_mux_chan;
-   int reg;
+   u32 reg;
int ret;
 
*conf = 0;
-- 
2.1.1



[PATCH 3/4] iio: adc: xilinx: Check for return values in clk related functions

2018-07-18 Thread Manish Narani
This patch adds check for return values from clock related functions.
This was reported by static code analysis tool.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 24 ++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index 248cffa..47eb364 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -322,6 +322,7 @@ static irqreturn_t xadc_zynq_interrupt_handler(int irq, 
void *devid)
 
 #define XADC_ZYNQ_TCK_RATE_MAX 5000
 #define XADC_ZYNQ_IGAP_DEFAULT 20
+#define XADC_ZYNQ_PCAP_RATE_MAX 2
 
 static int xadc_zynq_setup(struct platform_device *pdev,
struct iio_dev *indio_dev, int irq)
@@ -332,6 +333,7 @@ static int xadc_zynq_setup(struct platform_device *pdev,
unsigned int div;
unsigned int igap;
unsigned int tck_rate;
+   int ret;
 
/* TODO: Figure out how to make igap and tck_rate configurable */
igap = XADC_ZYNQ_IGAP_DEFAULT;
@@ -341,6 +343,13 @@ static int xadc_zynq_setup(struct platform_device *pdev,
 
pcap_rate = clk_get_rate(xadc->clk);
 
+   if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) {
+   ret = clk_set_rate(xadc->clk,
+  (unsigned long)XADC_ZYNQ_PCAP_RATE_MAX);
+   if (ret)
+   return ret;
+   }
+
if (tck_rate > pcap_rate / 2) {
div = 2;
} else {
@@ -366,6 +375,12 @@ static int xadc_zynq_setup(struct platform_device *pdev,
XADC_ZYNQ_CFG_REDGE | XADC_ZYNQ_CFG_WEDGE |
tck_div | XADC_ZYNQ_CFG_IGAP(igap));
 
+   if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) {
+   ret = clk_set_rate(xadc->clk, pcap_rate);
+   if (ret)
+   return ret;
+   }
+
return 0;
 }
 
@@ -887,6 +902,9 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
unsigned long clk_rate = xadc_get_dclk_rate(xadc);
unsigned int div;
 
+   if (!clk_rate)
+   return -EINVAL;
+
if (info != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
 
@@ -1239,8 +1257,10 @@ static int xadc_probe(struct platform_device *pdev)
goto err_free_irq;
 
/* Disable all alarms */
-   xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
-   XADC_CONF1_ALARM_MASK);
+   ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
+ XADC_CONF1_ALARM_MASK);
+   if (ret)
+   goto err_free_irq;
 
/* Set thresholds to min/max */
for (i = 0; i < 16; i++) {
-- 
2.1.1



[PATCH 0/4] iio: adc: xilinx: XADC driver enhancements and bug fixes

2018-07-18 Thread Manish Narani
This patch series resolves code style problems as reported by code analysis
tools.

Manish Narani (4):
  iio: adc: xilinx: Rename 'channels' variable name to
'iio_xadc_channels'
  iio: adc: xilinx: Remove dead code from xadc_zynq_setup
  iio: adc: xilinx: Check for return values in clk related functions
  iio: adc: xilinx: Use devm_ functions while requesting irq

 drivers/iio/adc/xilinx-xadc-core.c | 60 --
 1 file changed, 38 insertions(+), 22 deletions(-)

-- 
2.1.1



[PATCH 1/4] iio: adc: xilinx: Rename 'channels' variable name to 'iio_xadc_channels'

2018-07-18 Thread Manish Narani
This patch fix the following checkpatch warning in xadc driver.
- Reusing the krealloc arg is almost always a bug.

Renamed the 'channels' variable as 'iio_xadc_channels' to fix the above
warning.

Signed-off-by: Manish Narani 
---
 drivers/iio/adc/xilinx-xadc-core.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c 
b/drivers/iio/adc/xilinx-xadc-core.c
index d4f21d1..27b45df 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1040,7 +1040,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, 
struct device_node *np,
unsigned int *conf)
 {
struct xadc *xadc = iio_priv(indio_dev);
-   struct iio_chan_spec *channels, *chan;
+   struct iio_chan_spec *iio_xadc_channels, *chan;
struct device_node *chan_node, *child;
unsigned int num_channels;
const char *external_mux;
@@ -1083,12 +1083,13 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, 
struct device_node *np,
*conf |= XADC_CONF0_MUX | XADC_CONF0_CHAN(ext_mux_chan);
}
 
-   channels = kmemdup(xadc_channels, sizeof(xadc_channels), GFP_KERNEL);
-   if (!channels)
+   iio_xadc_channels = kmemdup(xadc_channels, sizeof(xadc_channels),
+   GFP_KERNEL);
+   if (!iio_xadc_channels)
return -ENOMEM;
 
num_channels = 9;
-   chan = &channels[9];
+   chan = &iio_xadc_channels[9];
 
chan_node = of_get_child_by_name(np, "xlnx,channels");
if (chan_node) {
@@ -1119,11 +1120,12 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, 
struct device_node *np,
of_node_put(chan_node);
 
indio_dev->num_channels = num_channels;
-   indio_dev->channels = krealloc(channels, sizeof(*channels) *
-   num_channels, GFP_KERNEL);
+   indio_dev->channels = krealloc(iio_xadc_channels,
+  sizeof(*iio_xadc_channels) *
+  num_channels, GFP_KERNEL);
/* If we can't resize the channels array, just use the original */
if (!indio_dev->channels)
-   indio_dev->channels = channels;
+   indio_dev->channels = iio_xadc_channels;
 
return 0;
 }
-- 
2.1.1



RE: [PATCH 1/4] iio: adc: xilinx: Rename 'channels' variable name to 'iio_xadc_channels'

2018-07-18 Thread Manish Narani
Hi Lars,

> -Original Message-
> From: Lars-Peter Clausen [mailto:l...@metafoo.de]
> Sent: Wednesday, July 18, 2018 4:49 PM
> To: Manish Narani ; ji...@kernel.org;
> knaac...@gmx.de; pme...@pmeerw.net; Michal Simek
> ; linux-...@vger.kernel.org; linux-arm-
> ker...@lists.infradead.org; linux-kernel@vger.kernel.org
> Cc: Anirudha Sarangi ; Srinivas Goud
> ; Joe Perches 
> Subject: Re: [PATCH 1/4] iio: adc: xilinx: Rename 'channels' variable name to
> 'iio_xadc_channels'
> 
> On 07/18/2018 01:12 PM, Manish Narani wrote:
> > This patch fix the following checkpatch warning in xadc driver.
> > - Reusing the krealloc arg is almost always a bug.
> >
> > Renamed the 'channels' variable as 'iio_xadc_channels' to fix the
> > above warning.
> >
> 
> This is a bug in checkpatch and should be fixed in checkpatch. The code is not
> actually re-using the parameter. channels and xadc_channels are independent
> variables, just checkpatch somehow does not realize this.
I agree with you on this. Initially I presumed the checkpatch to be giving 
genuine
warning but now I am sure that this is certainly the checkpatch script issue.
In that case should we keep this code change?
Please suggest.

Thanks,
Manish

> 
> > Signed-off-by: Manish Narani 
> > ---
> >  drivers/iio/adc/xilinx-xadc-core.c | 16 +---
> >  1 file changed, 9 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/iio/adc/xilinx-xadc-core.c
> > b/drivers/iio/adc/xilinx-xadc-core.c
> > index d4f21d1..27b45df 100644
> > --- a/drivers/iio/adc/xilinx-xadc-core.c
> > +++ b/drivers/iio/adc/xilinx-xadc-core.c
> > @@ -1040,7 +1040,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev,
> struct device_node *np,
> > unsigned int *conf)
> >  {
> > struct xadc *xadc = iio_priv(indio_dev);
> > -   struct iio_chan_spec *channels, *chan;
> > +   struct iio_chan_spec *iio_xadc_channels, *chan;
> > struct device_node *chan_node, *child;
> > unsigned int num_channels;
> > const char *external_mux;
> > @@ -1083,12 +1083,13 @@ static int xadc_parse_dt(struct iio_dev
> *indio_dev, struct device_node *np,
> > *conf |= XADC_CONF0_MUX |
> XADC_CONF0_CHAN(ext_mux_chan);
> > }
> >
> > -   channels = kmemdup(xadc_channels, sizeof(xadc_channels),
> GFP_KERNEL);
> > -   if (!channels)
> > +   iio_xadc_channels = kmemdup(xadc_channels, sizeof(xadc_channels),
> > +   GFP_KERNEL);
> > +   if (!iio_xadc_channels)
> > return -ENOMEM;
> >
> > num_channels = 9;
> > -   chan = &channels[9];
> > +   chan = &iio_xadc_channels[9];
> >
> > chan_node = of_get_child_by_name(np, "xlnx,channels");
> > if (chan_node) {
> > @@ -1119,11 +1120,12 @@ static int xadc_parse_dt(struct iio_dev
> *indio_dev, struct device_node *np,
> > of_node_put(chan_node);
> >
> > indio_dev->num_channels = num_channels;
> > -   indio_dev->channels = krealloc(channels, sizeof(*channels) *
> > -   num_channels, GFP_KERNEL);
> > +   indio_dev->channels = krealloc(iio_xadc_channels,
> > +  sizeof(*iio_xadc_channels) *
> > +  num_channels, GFP_KERNEL);
> > /* If we can't resize the channels array, just use the original */
> > if (!indio_dev->channels)
> > -   indio_dev->channels = channels;
> > +   indio_dev->channels = iio_xadc_channels;
> >
> > return 0;
> >  }
> >



[PATCH] checkpatch: Resolve improper warning for krealloc arg reuse

2018-07-18 Thread Manish Narani
Correct the check for reuse of krealloc. It gives false warning when a
structure member variable name and krealloc argument name is same.

For Example:
{
...
abc.def_var = krealloc(def_var, sizeof(*def_var),
GFP_KERNEL);
...
}

$ ./scripts/checkpatch.pl -f file.c

WARNING: Reusing the krealloc arg is almost always a bug
+   abc.def_var = krealloc(def_var, sizeof(*def_var),

This patch resolves the above false warning.

Signed-off-by: Manish Narani 
---
 scripts/checkpatch.pl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 447857f..db9b666 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6119,7 +6119,7 @@ sub process {
 
 # check for krealloc arg reuse
if ($^V && $^V ge 5.10.0 &&
-   $line =~ 
/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
+   $line =~ 
/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/ && $line !~ 
m/[\.|\-\>].*\s*\=\s*.*/) {
WARN("KREALLOC_ARG_REUSE",
 "Reusing the krealloc arg is almost always a 
bug\n" . $herecurr);
}
-- 
2.1.1



  1   2   3   >