RE: [PATCH 1/2] [1/2] mmc: sdhci-cadence: Fix writing PHY delay

2017-02-23 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 23 February, 2017 12:29 PM
> Subject: Re: [PATCH 1/2] [1/2] mmc: sdhci-cadence: Fix writing PHY delay
> 
> Hi.
> 
> > -static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> > +static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> >  u8 addr, u8 data)
> 
> 
> If you have a chance to submit v2,
> I want the indent of the above line adjusted.
> 
Ok thanks. I will fix the indent in v2.

Regards
Piotr Sroka



RE: [PATCH 2/2] [2/2] mmc: sdhci-cadence: Update PHY delay configuration

2017-02-17 Thread Piotr Sroka
> -Original Message-
> From: Ulf Hansson [mailto:ulf.hans...@linaro.org]
> Sent: 16 February, 2017 4:10 PM
> Subject: Re: [PATCH 2/2] [2/2] mmc: sdhci-cadence: Update PHY delay
> configuration
> 
> On 16 February 2017 at 14:06, Piotr Sroka <pio...@cadence.com> wrote:
> > DTS properties are used instead of fixed data because PHY settings can
> > be different for different platforms.
> > Configuration of new three PHY delays were added
> >
> > Signed-off-by: Piotr Sroka <pio...@cadence.com>
> > ---
> >  .../devicetree/bindings/mmc/sdhci-cadence.txt  | 54 ++
> 
> Please split this patch.
> 
> DT docs should be a separate patch and make sure it precedes the changes
> where the new bindings are being parsed in the driver code.
> 

Ok I will do it in next version of patch.

> >  drivers/mmc/host/sdhci-cadence.c   | 83 
> > +++-
> --
> >  2 files changed, 129 insertions(+), 8 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
> > b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
> > index c0f37cb..221d3fe 100644
> > --- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
> > +++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
> > @@ -19,6 +19,59 @@ if supported.  See mmc.txt for details.
> >  - mmc-hs400-1_8v
> >  - mmc-hs400-1_2v
> >
> > +- phy-input-delay-sd-hs:
> > +  Value of the delay in the input path for High Speed work mode.
> > +  Valid range = [0:0x1F].
> 
> Please specify what unit this in. And then also a suffix, like "-ns"
> to the name of the binding.

The delay starts from 5ns (for delay parameter equal to 0), and it is increased 
by 2.5ns.
0 - means 5ns, 1 means 7.5 ns etc.
I will add this description. 
I think the suffix in this case will not be necessary because the unit is a 
2.5ns.
What is your opinion?

> 
> Similar comment applies to all new bindings below.
> 
> > +  Delay configuration stay unchanged if this property is not provided.
> 
> I would remove this information from the DT doc, it's just confusion when
> you refer to something that should remain "unchanged".
> 

Ok I will remove it in next version of patch.

> Similar comment applies to all new bindings below.
> 
> > +- phy-input-delay-sd-default:
> > +  Value of the delay in the input path for Default Speed work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-input-delay-sd-sdr12:
> > +  Value of the delay in the input path for SDR12 work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-input-delay-sd-sdr25:
> > +  Value of the delay in the input path for SDR25 work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-input-delay-sd-sdr50:
> > +  Value of the delay in the input path for SDR50 work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-input-delay-sd-ddr50:
> > +  Value of the delay in the input path for DDR50 work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-input-delay-emmc-legacy:
> 
> Legacy? As in legacy speed mode?

Yes as legacy speed mode. But there are two delays each for one specific mode.
One for SD legacy mode and one for MMC legacy mode.

> 
> > +  Value of the delay in the input path for eMMC legacy work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-input-delay-emmc-sdr:
> > +  Value of the delay in the input path for eMMC SDR work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-input-delay-emmc-ddr:
> > +  Value of the delay in the input path for eMMC DDR work mode.
> > +  Valid range = [0:0x1F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-dll-delay-sdclk:
> > +  Value of the delay introduced on the sdclk output
> > +  for all modes except HS200, HS400 and HS400_ES.
> > +  Valid range = [0:0x7F].
> > +  Delay configuration stay unchanged if this property is not provided.
> > +- phy-dll-delay-sdclk-hsmmc:
> > +  Value of the delay introduced on the sdclk output
> > +  for HS200, HS400 and HS400_ES speed modes.
> > +  Valid rang

[PATCH 1/2] [1/2] mmc: sdhci-cadence: Fix writing PHY delay

2017-02-16 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
 drivers/mmc/host/sdhci-cadence.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 4b0ecb9..c946e45 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -65,11 +65,12 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
 u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -78,8 +79,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



[PATCH 2/2] [2/2] mmc: sdhci-cadence: Update PHY delay configuration

2017-02-16 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different platforms.
Configuration of new three PHY delays were added

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 54 ++
 drivers/mmc/host/sdhci-cadence.c   | 83 +++---
 2 files changed, 129 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..221d3fe 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,59 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+- phy-input-delay-sd-hs:
+  Value of the delay in the input path for High Speed work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-default:
+  Value of the delay in the input path for Default Speed work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-sdr12:
+  Value of the delay in the input path for SDR12 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-sdr25:
+  Value of the delay in the input path for SDR25 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-sdr50:
+  Value of the delay in the input path for SDR50 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-ddr50:
+  Value of the delay in the input path for DDR50 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-emmc-legacy:
+  Value of the delay in the input path for eMMC legacy work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-emmc-sdr:
+  Value of the delay in the input path for eMMC SDR work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-emmc-ddr:
+  Value of the delay in the input path for eMMC DDR work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+  Delay configuration stay unchanged if this property is not provided.
+
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +82,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   phy-input-delay-sd-hs = <0>;
};
diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index c946e45..6c338d2 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -53,6 +54,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -89,13 +93,73 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_parse_dt(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 tmp;
+   int ret;
+
+   if (!of_property_read_u32(np, "phy-input-delay-sd-hs", )) {

[PATCH] Add HS400 enhanced strobe support

2017-02-15 Thread Piotr Sroka
Add support for HS400ES mode to Cadence SDHCI driver.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
 drivers/mmc/host/sdhci-cadence.c | 41 +---
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 4b0ecb9..5296c7c 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -39,6 +39,7 @@
 #define   SDHCI_CDNS_HRS06_MODE_MMC_DDR0x3
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS200  0x4
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS400  0x5
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400ES0x6
 
 /* SRS - Slot Register Set (SDHCI-compatible) */
 #define SDHCI_CDNS_SRS_BASE0x200
@@ -63,6 +64,7 @@
 
 struct sdhci_cdns_priv {
void __iomem *hrs_addr;
+   bool enhanced_strobe;
 };
 
 static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
@@ -107,11 +109,22 @@ static unsigned int sdhci_cdns_get_timeout_clock(struct 
sdhci_host *host)
return host->max_clk / 1000;
 }
 
+static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode)
+{
+   u32 tmp;
+
+   /* The speed mode for eMMC is selected by HRS06 register */
+   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
+   tmp |= mode;
+   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+}
+
 static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
 unsigned int timing)
 {
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
-   u32 mode, tmp;
+   u32 mode;
 
switch (timing) {
case MMC_TIMING_MMC_HS:
@@ -124,24 +137,35 @@ static void sdhci_cdns_set_uhs_signaling(struct 
sdhci_host *host,
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
break;
case MMC_TIMING_MMC_HS400:
-   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
+   if (priv->enhanced_strobe)
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
+   else
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
break;
default:
mode = SDHCI_CDNS_HRS06_MODE_SD;
break;
}
 
-   /* The speed mode for eMMC is selected by HRS06 register */
-   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
-   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
-   tmp |= mode;
-   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+   sdhci_cdns_set_emmc_mode(priv, mode);
 
/* For SD, fall back to the default handler */
if (mode == SDHCI_CDNS_HRS06_MODE_SD)
sdhci_set_uhs_signaling(host, timing);
 }
 
+static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
+struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+
+   priv->enhanced_strobe = ios->enhanced_strobe;
+   if (ios->enhanced_strobe)
+   sdhci_cdns_set_emmc_mode(priv,
+SDHCI_CDNS_HRS06_MODE_MMC_HS400ES);
+}
+
 static const struct sdhci_ops sdhci_cdns_ops = {
.set_clock = sdhci_set_clock,
.get_timeout_clock = sdhci_cdns_get_timeout_clock,
@@ -239,8 +263,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
 
priv = sdhci_cdns_priv(host);
priv->hrs_addr = host->ioaddr;
+   priv->enhanced_strobe = false;
host->ioaddr += SDHCI_CDNS_SRS_BASE;
host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
+   host->mmc_host_ops.hs400_enhanced_strobe =
+   sdhci_cdns_hs400_enhanced_strobe;
 
ret = mmc_of_parse(host->mmc);
if (ret)
-- 
2.2.2



[PATCH] mmc: core: fix changing bus witdh in hs400es mode

2017-03-02 Thread Piotr Sroka
Fix the code to avoid changing bus width if HS400ES mode is selected.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
 drivers/mmc/core/mmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 7fd7228..c7d9c9f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1730,7 +1730,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_select_hs400(card);
if (err)
goto free_card;
-   } else {
+   } else if (!mmc_card_hs400(card)) {
/* Select the desired bus width optionally */
err = mmc_select_bus_width(card);
if (err > 0 && mmc_card_hs(card)) {
-- 
2.2.2



RE: [v5 2/4] dt-bindings: mmc: add description of PHY delays for sdhci-cadence

2017-03-30 Thread Piotr Sroka
Hi Masahiro

2017-03-22 16:30  Masahiro Yamada <yamada.masah...@socionext.com>:
> 2017-03-21 23:33 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> > DTS properties are used instead of fixed data
> > because PHY settings can be different for different chips/boards.
> > Add description of new DLL PHY delays.
> >
> > Signed-off-by: Piotr Sroka <pio...@cadence.com>
> > ---
> > Changes for v2:
> > - file was created in v2. It was a part of driver source file patch.
> > - most delays were moved from dts file
> >   to data associated with an SoC specific compatible
> > - description of delays was updated to be more clearly
> > ---
> > Changes for v3:
> > - move all delays back to dts because they are also boards dependent
> > - prefix all of the Cadence-specific properties with cdns prefix
> > ---
> > Changes for v4:
> > - change the beginning of the commit subject
> > ---
> > Changes for v5:
> > - change name of property to be consistent with timing modes
> >   available in Linux
> 
> 
> As I gave Reviewed-by in v4 already, this looks good to me.
> 
> 
> Reviewed-by: Masahiro Yamada <yamada.masah...@socionext.com>
> 
> 
> As I said before,
> once you get Reviewed/Acked tags,
> please include them in your later version.
> 

Ok. I will remember next time.

-- 
Best Regards
Piotr Sroka



[no subject]

2017-03-21 Thread Piotr Sroka
Subject: RE: [v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration
In-reply-to: 

RE: [v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-21 Thread Piotr Sroka
Hi Masahiro,

> Hi Piotr,
> 
> 2017-03-20 17:47 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> >
> >>
> >> > @@ -227,6 +267,7 @@ static int sdhci_cdns_probe(struct platform_device 
> >> > *pdev)
> >> > struct sdhci_cdns_priv *priv;
> >> > struct clk *clk;
> >> > int ret;
> >> > +   struct device *dev = >dev;
> >> >
> >> > clk = devm_clk_get(>dev, NULL);
> >>
> >>
> >> If you add "dev", please use it for devm_clk_get, too.
> >>
> > I did on the first patch version but Ulf pointed that this is unrelated 
> > change and should be removed.
> > Therefore I remove it.
> 
> Ah, OK.
> 
> Could you consider to send a separate patch for this?
> 
Ok. If v5 is needed I will add additional patch making this modification. If 
not I will prepare a spearate patch.


Best Regards
Piotr Sroka


RE: [v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-21 Thread Piotr Sroka

Hi Masahiro 

2017-03-21 02:46 AM Masahiro Yamada <yamada.masah...@socionext.com>:
> Hi Piotr,
> 
> 
> 2017-03-20 20:20 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> > DTS properties are used instead of fixed data
> > because PHY settings can be different for different chips/boards.
> >
> > Signed-off-by: Piotr Sroka <pio...@cadence.com>
> 
> 
> I found this version is a problem for me.
> 
> 
> > +
> > +static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
> > +   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
> > +   { "cdns,phy-input-delay-sd-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 
> > },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr12", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr25", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr50", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
> > +   { "cdns,phy-input-delay-sd-uhs-ddr50", 
> > SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
> > +   { "cdns,phy-input-delay-mmc-highspeed", 
> > SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
> > +   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
> > +   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
> > +   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
> > +   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
> > +};
> > +
> 
> 
> I see mmc-legacy property in v1,
> but it is missing now.
> 
> 
> >  static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> > u8 addr, u8 data)
> >  {
> > @@ -90,13 +113,26 @@ static int sdhci_cdns_write_phy_reg(struct 
> > sdhci_cdns_priv *priv,
> > return 0;
> >  }
> >
> > -static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
> > +static int sdhci_cdns_phy_init(struct device_node *np,
> > +  struct sdhci_cdns_priv *priv)
> >  {
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
> 
> 
> I need to set SDHCI_CDNS_PHY_DLY_EMMC_LEGACY to 9 for my SoC.
> 
> Maybe, do we need a DT property for this, too?
> 
I can add it but could you check if you realy need it? There is no selection 
MMC legacy mode
in this driver. 


Best Regards
Piotr Sroka


[v4 1/3] mmc: sdhci-cadence: Fix writing PHY delay

2017-03-20 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- fix indent
---
Changes for v3:
- none
---
Changes for v4:
- none
---
 drivers/mmc/host/sdhci-cadence.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 316cfec..b2334ec 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -66,11 +66,12 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
-u8 addr, u8 data)
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+   u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -79,8 +80,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



RE: [v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-20 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 17 March, 2017 6:24 PM
> Subject: Re: [v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration
> 
> 
> 
> > @@ -62,10 +66,33 @@
> >   */
> >  #define SDHCI_CDNS_MAX_TUNING_LOOP 40
> >
> > +static const struct of_device_id sdhci_cdns_match[];
> > +
> 
> You forgot to remove this.
> 
You are right. Thanks.
 
> 
> > @@ -227,6 +267,7 @@ static int sdhci_cdns_probe(struct platform_device 
> > *pdev)
> > struct sdhci_cdns_priv *priv;
> > struct clk *clk;
> > int ret;
> > +   struct device *dev = >dev;
> >
> > clk = devm_clk_get(>dev, NULL);
> 
> 
> If you add "dev", please use it for devm_clk_get, too.
> 
I did on the first patch version but Ulf pointed that this is unrelated change 
and should be removed. 
Therefore I remove it. 

> 
> 
> --
> Best Regards
> Masahiro Yamada


RE: [v3 2/3] Documentation: bindings: add description of PHY delays for sdhci-cadence

2017-03-20 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 17 March, 2017 6:30 PM
> Subject: Re: [v3 2/3] Documentation: bindings: add description of PHY delays 
> for sdhci-cadence
> 
> Hi Piotr,
> 
> 2017-03-17 21:40 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> > DTS properties are used instead of fixed data because PHY settings can
> > be different for different chips/boards.
> > Add description of new DLL PHY delays.
> >
> > Signed-off-by: Piotr Sroka <pio...@cadence.com>
> 
> 
> I think you have a chance for v4.
> 
> Next time, please follow Rob's suggestion
> 
> > For the subject: "dt-bindings: mmc: ..."
> 
> 
I missed it. Thanks. I will use proper prefix in the next version.

Best Regards
Piotr Sroka


[v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-20 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- dts part was removed from this patch
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- remove unrelated changes
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
- put checking delay properties inside the for loop
  instead of using a lot of single if expressions
---
Changes for v4:
- remove unecessary declaration of sdhci_cdns_match
- format fix (blank line removed)
---
 drivers/mmc/host/sdhci-cadence.c | 53 ++--
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index b2334ec..308a372 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -54,6 +55,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -66,6 +70,25 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
+struct sdhci_cdns_phy_cfg {
+   const char *property;
+   u8 addr;
+};
+
+static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
+   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
+   { "cdns,phy-input-delay-sd-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
+   { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
+   { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
+   { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
+   { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
+   { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
+   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
+   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
+   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
+   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
+};
+
 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
u8 addr, u8 data)
 {
@@ -90,13 +113,26 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_init(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 val;
+   int ret, i;
+
+   for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
+   ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
+  );
+   if (ret)
+   continue;
+
+   ret = sdhci_cdns_write_phy_reg(priv,
+  sdhci_cdns_phy_cfgs[i].addr,
+  val);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
 }
 
 static inline void *sdhci_cdns_priv(struct sdhci_host *host)
@@ -227,6 +263,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
struct sdhci_cdns_priv *priv;
struct clk *clk;
int ret;
+   struct device *dev = >dev;
 
clk = devm_clk_get(>dev, NULL);
if (IS_ERR(clk))
@@ -254,7 +291,9 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
if (ret)
goto free;
 
-   sdhci_cdns_phy_init(priv);
+   ret = sdhci_cdns_phy_init(dev->of_node, priv);
+   if (ret)
+   goto free;
 
ret = sdhci_add_host(host);
if (ret)
-- 
2.2.2



[v4 2/3] dt-bindings: mmc: add description of PHY delays for sdhci-cadence

2017-03-20 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.
Add description of new DLL PHY delays.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- file was created in v2. It was a part of driver source file patch.
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- description of delays was updated to be more clearly
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
---
Changes for v4:
- change the beginning of the commit subject
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..c341820 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,53 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+Some PHY delays can be configured by following properties.
+PHY DLL input delays:
+They are used to delay the data valid window, and align the window
+to sampling clock. The delay starts from 5ns (for delay parameter equal to 0)
+and it is increased by 2.5ns in each step.
+- cdns,phy-input-delay-sd-highspeed:
+  Value of the delay in the input path for SD high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-legacy:
+  Value of the delay in the input path for SD legacy timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr12:
+  Value of the delay in the input path for SD UHS SDR12 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr25:
+  Value of the delay in the input path for SD UHS SDR25 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr50:
+  Value of the delay in the input path for SD UHS SDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-ddr50:
+  Value of the delay in the input path for SD UHS DDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-highspeed:
+  Value of the delay in the input path for MMC high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-ddr:
+  Value of the delay in the input path for eMMC high-speed DDR timing
+  Valid range = [0:0x1F].
+
+PHY DLL clock delays:
+Each delay property represents the fraction of the clock period.
+The approximate delay value will be
+(/128)*sdmclk_clock_period.
+- cdns,phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +76,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   cdns,phy-dll-delay-sdclk = <0>;
};
-- 
2.2.2



RE: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-20 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 17 March, 2017 6:23 PM
> Subject: Re: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration
> 
> Hi Piotr,
> 
> Sorry for my late reply.
> 
> 
> >
> > It looks that "input delays" and "DLL sdclk delays" should be defined in 
> > dts file because they depend on a chip and a board
> implementation. On the other hand the less dts properties the better.
> >
> > There is one more way to handle input delays. It can be achieved by PHY 
> > training. PHY training is similar to the tuning and it should be
> done when proper timing mode is selected and clock frequency is set.
> > To make it possible the sdhci_set_ios function need to be global. Then I 
> > could create sdhci_cdns_set_ios function as follows:
> > void sdhci_cdns_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) {
> > . . .
> >
> > sdhci_set_ios(mmc, ios);
> > /* execute PHY training if needed */
> > sdhci_cdns_exec_phy_training(host);
> > }
> >
> > The mmc framework configures timing and frequency separately so PHY 
> > training should be executed every time if timing or clock
> frequency is changed. I am not sure If I can change sdhci_set_ios to global 
> function.
> 
> 
> I am OK with this, but I hope Adrian can advise us.
> 
> 
> 
> 
> > So maybe put all delays to dts file would be a better solution? What do you 
> > think?
> 
> I am OK with DT approach too
> because this way seems simpler, after all.
> 
> (My suggestion for data array approach was misleading, sorry.)
> 
Thanks for review anyway it was useful. Now decision between DTS and data array 
is more clear for me. 

Regards 
Piotr Sroka


[v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-17 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- dts part was removed from this patch
- most delays were moved from dts file 
  to data associated with an SoC specific compatible
- remove unrelated changes
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
- put checking delay properties inside the for loop 
  instead of using a lot of single if expressions 
---
 drivers/mmc/host/sdhci-cadence.c | 57 +++-
 1 file changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index b2334ec..7728ce6 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -54,6 +55,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -62,10 +66,33 @@
  */
 #define SDHCI_CDNS_MAX_TUNING_LOOP 40
 
+static const struct of_device_id sdhci_cdns_match[];
+
 struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
+
+struct sdhci_cdns_phy_cfg {
+   const char *property;
+   u8 addr;
+};
+
+static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
+   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
+   { "cdns,phy-input-delay-sd-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
+   { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
+   { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
+   { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
+   { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
+   { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
+   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
+   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
+   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
+   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
+};
+
+
 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
u8 addr, u8 data)
 {
@@ -90,13 +117,26 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_init(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 val;
+   int ret, i;
+
+   for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
+   ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
+  );
+   if (ret)
+   continue;
+
+   ret = sdhci_cdns_write_phy_reg(priv,
+  sdhci_cdns_phy_cfgs[i].addr,
+  val);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
 }
 
 static inline void *sdhci_cdns_priv(struct sdhci_host *host)
@@ -227,6 +267,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
struct sdhci_cdns_priv *priv;
struct clk *clk;
int ret;
+   struct device *dev = >dev;
 
clk = devm_clk_get(>dev, NULL);
if (IS_ERR(clk))
@@ -254,7 +295,9 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
if (ret)
goto free;
 
-   sdhci_cdns_phy_init(priv);
+   ret = sdhci_cdns_phy_init(dev->of_node, priv);
+   if (ret)
+   goto free;
 
ret = sdhci_add_host(host);
if (ret)
-- 
2.2.2



[v3 1/3] mmc: sdhci-cadence: Fix writing PHY delay

2017-03-17 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- fix indent
---
Changes for v3:
- none
---
 drivers/mmc/host/sdhci-cadence.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 316cfec..b2334ec 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -66,11 +66,12 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
-u8 addr, u8 data)
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+   u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -79,8 +80,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



[v3 2/3] Documentation: bindings: add description of PHY delays for sdhci-cadence

2017-03-17 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.
Add description of new DLL PHY delays.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- file was created in v2. It was a part of driver source file patch.
- most delays were moved from dts file 
  to data associated with an SoC specific compatible
- description of delays was updated to be more clearly
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..c341820 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,53 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+Some PHY delays can be configured by following properties.
+PHY DLL input delays:
+They are used to delay the data valid window, and align the window
+to sampling clock. The delay starts from 5ns (for delay parameter equal to 0)
+and it is increased by 2.5ns in each step.
+- cdns,phy-input-delay-sd-highspeed:
+  Value of the delay in the input path for SD high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-legacy:
+  Value of the delay in the input path for SD legacy timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr12:
+  Value of the delay in the input path for SD UHS SDR12 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr25:
+  Value of the delay in the input path for SD UHS SDR25 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr50:
+  Value of the delay in the input path for SD UHS SDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-ddr50:
+  Value of the delay in the input path for SD UHS DDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-highspeed:
+  Value of the delay in the input path for MMC high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-ddr:
+  Value of the delay in the input path for eMMC high-speed DDR timing
+  Valid range = [0:0x1F].
+
+PHY DLL clock delays:
+Each delay property represents the fraction of the clock period.
+The approximate delay value will be
+(/128)*sdmclk_clock_period.
+- cdns,phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +76,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   cdns,phy-dll-delay-sdclk = <0>;
};
-- 
2.2.2



RE: [v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-22 Thread Piotr Sroka
Hi Masahiro

2017-03-21 08:3 AM  Masahiro Yamada <yamada.masah...@socionext.com>:
> Hi Piotr,
> 
> 2017-03-21 16:01 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> >
> > Hi Masahiro
> >
> > 2017-03-21 02:46 AM Masahiro Yamada <yamada.masah...@socionext.com>:
> >> Hi Piotr,
> >>
> >>
> >> 2017-03-20 20:20 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> >> > DTS properties are used instead of fixed data
> >> > because PHY settings can be different for different chips/boards.
> >> >
> >> > Signed-off-by: Piotr Sroka <pio...@cadence.com>
> >>
> >>
> >> I found this version is a problem for me.
> >>
> >>
> >> > +
> >> > +static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
> >> > +   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, 
> >> > },
> >> > +   { "cdns,phy-input-delay-sd-legacy", 
> >> > SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-sdr12", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-sdr25", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-sdr50", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-ddr50", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
> >> > +   { "cdns,phy-input-delay-mmc-highspeed", 
> >> > SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
> >> > +   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
> >> > +   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
> >> > +   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
> >> > +   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
> >> > +};
> >> > +
> >>
> >>
> >> I see mmc-legacy property in v1,
> >> but it is missing now.
> >>
> >>
> >> >  static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> >> > u8 addr, u8 data)
> >> >  {
> >> > @@ -90,13 +113,26 @@ static int sdhci_cdns_write_phy_reg(struct 
> >> > sdhci_cdns_priv *priv,
> >> > return 0;
> >> >  }
> >> >
> >> > -static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
> >> > +static int sdhci_cdns_phy_init(struct device_node *np,
> >> > +  struct sdhci_cdns_priv *priv)
> >> >  {
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 
> >> > 9);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
> >>
> >>
> >> I need to set SDHCI_CDNS_PHY_DLY_EMMC_LEGACY to 9 for my SoC.
> >>
> >> Maybe, do we need a DT property for this, too?
> >>
> > I can add it but could you check if you realy need it? There is no 
> > selection MMC legacy mode
> > in this driver.
> >
> 
> Ah, you are right.
> 
> For Linux, SD-Legacy and MMC-Legacy share the same timing flag.
> The legacy mode is covered by SDHCI_CDNS_PHY_DLY_SD_DEFAULT,
> so we need not to set SDHCI_CDNS_PHY_DLY_EMMC_LEGACY.
> 
> So, I have no problem with patch.
> 
> Reviewed-by: Masahiro Yamada <yamada.masah...@socionext.com>
> 
> 
> 
> 
> From here, just my minor comments.
> The binding should not be too Linux-oriented.
> Device Tree is hardware description language, and project-neutral from
> its concept.
> I wonder if there is a project that handles SD-Legacy and MMC-Legacy 
> separately.
> I am not sure about this, and I do not have a strong opinion, either.
> 
> I leave this to you  (and other developers).
> 

Thanks for your comments.

Because patch adding HS400 enhanced strobe support was applied 
for next branch I needed to create v5. BTW I added one extra patch modifing
probe function as you suggested.
I also modify binding to be consistent with linux MMC timing names.
The driver does not use MMC legacy at all so I think there is no need 
to distinguish between SD Legacy and MMC Legacy. So there are no 
contraindications
for being consistent with Linux.


Best Regards
Piotr Sroka


[PATCH] mmc: sdhci-cadence: add parsing sdhci properties

2017-04-11 Thread Piotr Sroka
Add calling sdhci_get_of_property function to parse sdhci properties.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
 drivers/mmc/host/sdhci-cadence.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 7797e98..19d5698 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -330,6 +330,8 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
host->mmc_host_ops.hs400_enhanced_strobe =
sdhci_cdns_hs400_enhanced_strobe;
 
+   sdhci_get_of_property(pdev);
+
ret = mmc_of_parse(host->mmc);
if (ret)
goto free;
-- 
2.2.2



RE: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-13 Thread Piotr Sroka
Hi Masahiro

> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 09 March, 2017 3:37 AM
> Subject: Re: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration
> 
> Hi Piotr,
> 
> 2017-03-07 20:00 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> > Hi Masahiro,
> >
> >> -Original Message-----
> >> Sent: 07 March, 2017 9:03 AM
> >> To: Piotr Sroka
> >> Subject: Re: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay
> >> configuration
> >>
> >>
> >> With this patch, we will have two groups for PHY parameters.
> >>
> >> (A) specified via a data array associated with a compatible string
> >>
> >> (B) specified with DT property
> >>
> >> I am confused.
> >> What is the difference between (A) and (B)?
> >
> > The first group of delays are input delays. These delays are set in current 
> > version of sdhci-cadence driver in sdhci_cdns_phy_init
> function.
> > Following by spec:
> > They are provided to help in meeting timings relations between data window 
> > and sampling clock.
> > The clock is fixed position in respect to the SDCLK. And the idea of 
> > sampling is to delay and align the data to the data window.
> > If the default values of the delays are not sufficient/correct for the
> > chip/board implementation those can be adjusted
> >
> > The second group are DLL delays.
> > There are three delays
> > SDHCI_CDNS_PHY_DLY_SDCLK  - sdclk delay line use to delay outgoing
> > sdclk signal SDHCI_CDNS_PHY_DLY_HSMMC - sdclk delay line use to delay
> > outgoing sdclk signal for for HS200, HS400 and HS400ES
> > SDHCI_CDNS_PHY_DLY_STROBE - DLL strobe delay for HS400ES Following by spec:
> > They allows to setup basic DLL parameters. In general the default values 
> > are sufficient to start working in any speed mode. The
> default values of delays and phase detect select can be adjusted depending on 
> the chip/board implementation.
> 
> 
> 
> It was not clear what makes one group different from the other.
> 
> After all, parameters from both groups
> should be adjusted depending on chip/board implementation.
> 
> 
> > In general all PHY delays values either should be properly hardcoded in HW 
> > or they should be properly set  by FW depending on the
> chip/board.
> > So PHY driver should do not touch PHY delays at all or should set values 
> > which are proper for specific chip/board.
> >
> > I am not sure where exactly they should be placed in dts file or in 
> > compatible data.
> 
> I am not quite sure, either.
> (comments are appreciated.)
> 
> 
> FWIW:
> The first group (data associated with compatible) allows per-chip adjustment,
> but not per-board.   Pros are, we will not break DT compatibility,
> and we can avoid a list of properties difficult to understand.
> Cons are, we can not make fine-grained adjustment for each board.
> 
> 
> The second group (DT property) gives more flexibility for per-chip and 
> per-board adjustment.
> A bad thing is we will end up with specifying a bunch of mysterious 
> properties from DT.
> 
> 

It looks that "input delays" and "DLL sdclk delays" should be defined in dts 
file because they depend on a chip and a board implementation. On the other 
hand the less dts properties the better.

There is one more way to handle input delays. It can be achieved by PHY 
training. PHY training is similar to the tuning and it should be done when 
proper timing mode is selected and clock frequency is set.
To make it possible the sdhci_set_ios function need to be global. Then I could 
create sdhci_cdns_set_ios function as follows:
void sdhci_cdns_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
    . . .

    sdhci_set_ios(mmc, ios);
/* execute PHY training if needed */
sdhci_cdns_exec_phy_training(host);
}

The mmc framework configures timing and frequency separately so PHY training 
should be executed every time if timing or clock frequency is changed. I am not 
sure If I can change sdhci_set_ios to global function.
So maybe put all delays to dts file would be a better solution? What do you 
think?

Best Regards
Piotr Sroka


[v2 PATCH 2/3] Documentation: bindings: add description of PHY delays for sdhci-cadence

2017-03-06 Thread Piotr Sroka
Add description of new DLL PHY delays.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- file was created in v2. It was a part of driver source file patch.
- most delays were moved from dts file 
  to data associated with an SoC specific compatible
- description of delays was updated to be more clearly
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..77c4b99 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,23 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+Some PHY delays can be configured by following properties.
+Each delay property represents the fraction of the clock period.
+The approximate delay value will be
+(/128)*sdmclk_clock_period.
+- phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+- phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+- phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +46,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   phy-dll-delay-sdclk = <0>;
};
-- 
2.2.2



[v2 PATCH 1/3] mmc: sdhci-cadence: Fix writing PHY delay

2017-03-06 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- fix indent
---
 drivers/mmc/host/sdhci-cadence.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 316cfec..b2334ec 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -66,11 +66,12 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
-u8 addr, u8 data)
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+   u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -79,8 +80,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



[v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-06 Thread Piotr Sroka
PHY settings can be different for different platforms and SoCs.
Fixed PHY input delays was replaced with SoC specific compatible data.
DTS properties are used for configuration new PHY DLL delays.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- dts part was removed from this patch
- most delays were moved from dts file 
  to data associated with an SoC specific compatible
- remove unrelated changes
---

 drivers/mmc/host/sdhci-cadence.c | 124 ---
 1 file changed, 116 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index b2334ec..29b5d11 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -54,6 +55,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -62,10 +66,24 @@
  */
 #define SDHCI_CDNS_MAX_TUNING_LOOP 40
 
+static const struct of_device_id sdhci_cdns_match[];
+
 struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
+struct sdhci_cdns_config {
+   u8 phy_dly_sd_highspeed;
+   u8 phy_dly_sd_legacy;
+   u8 phy_dly_sd_uhs_sdr12;
+   u8 phy_dly_sd_uhs_sdr25;
+   u8 phy_dly_sd_uhs_sdr50;
+   u8 phy_dly_sd_uhs_ddr50;
+   u8 phy_dly_emmc_legacy;
+   u8 phy_dly_emmc_sdr;
+   u8 phy_dly_emmc_ddr;
+};
+
 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
u8 addr, u8 data)
 {
@@ -90,13 +108,77 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_in_delay_init(struct sdhci_cdns_priv *priv,
+   const struct sdhci_cdns_config *config)
+{
+   int ret = 0;
+
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS,
+  config->phy_dly_sd_highspeed);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT,
+  config->phy_dly_sd_legacy);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_UHS_SDR12,
+  config->phy_dly_sd_uhs_sdr12);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_UHS_SDR25,
+  config->phy_dly_sd_uhs_sdr25);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_UHS_SDR50,
+  config->phy_dly_sd_uhs_sdr50);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_UHS_DDR50,
+  config->phy_dly_sd_uhs_ddr50);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY,
+  config->phy_dly_emmc_legacy);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR,
+  config->phy_dly_emmc_sdr);
+   if (ret)
+   return ret;
+   ret = sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR,
+  config->phy_dly_emmc_ddr);
+   if (ret)
+   return ret;
+   return 0;
+}
+
+static int sdhci_cdns_phy_dll_delay_parse_dt(struct device_node *np,
+struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 tmp;
+   int ret;
+
+   if (!of_property_read_u32(np, "phy-dll-delay-sdclk", )) {
+   ret = sdhci_cdns_write_phy_reg(priv,
+  SDHCI_CDNS_PHY_DLY_SDCLK, tmp);
+
+   if (ret)
+   return ret;
+   }
+   if (!of_property_read_u32(np, "phy-dll-delay-sdclk-hsmmc", )) {
+   ret = sdhci_cdns_write_phy_reg(priv,
+  SDHCI_CDNS_PHY_DLY_HSMMC, tm

RE: [v3] mmc: sdhci-cadence: add HS400 enhanced strobe support

2017-03-06 Thread Piotr Sroka
Hi Masahiro,

Thanks for all of your reviews.

Best Regards
Piotr Sroka

> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 06 March, 2017 9:59 PM
> Subject: Re: [v3] mmc: sdhci-cadence: add HS400 enhanced strobe support
> 
> Hi Piotr,
> 
> 2017-03-06 17:28 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> > Add support for HS400ES mode to Cadence SDHCI driver.
> >
> > Signed-off-by: Piotr Sroka <pio...@cadence.com>
> > ---
> > Changes in v2:
> > - Modify enhanced strobe function to handle disabling
> >   enhanced strobe inside the function.
> >   Do no relay on that mmc_set_ios() is called
> >   immediately after host->ops->hs400_enhanced_strobe(host, >ios).
> > Changes in v3:
> > - Few coding-style fixes were made.
> 
> 
> Thanks for the update, and it looks good to me.
> 
> Reviewed-by: Masahiro Yamada <yamada.masah...@socionext.com>
> 
> --
> Best Regards
> Masahiro Yamada


RE: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-07 Thread Piotr Sroka
Hi Masahiro,

> -Original Message-
> Sent: 07 March, 2017 9:03 AM
> To: Piotr Sroka
> Subject: Re: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration
> 
> Hi Piotr,
> 
> 2017-03-06 22:39 GMT+09:00 Piotr Sroka <pio...@cadence.com>:
> > PHY settings can be different for different platforms and SoCs.
> > Fixed PHY input delays was replaced with SoC specific compatible data.
> > DTS properties are used for configuration new PHY DLL delays.
> 
> 
> Probably you are familiar with this IP.
> 
> Please teach me this.
> 
> With this patch, we will have two groups for PHY parameters.
> 
> (A) specified via a data array associated with a compatible string 
> SDHCI_CDNS_PHY_DLY_SD_HS SDHCI_CDNS_PHY_DLY_SD_DEFAULT
> SDHCI_CDNS_PHY_DLY_UHS_SDR12
> SDHCI_CDNS_PHY_DLY_UHS_SDR25
> SDHCI_CDNS_PHY_DLY_UHS_SDR50
> SDHCI_CDNS_PHY_DLY_UHS_DDR50
> SDHCI_CDNS_PHY_DLY_EMMC_LEGACY
> SDHCI_CDNS_PHY_DLY_EMMC_SDR
> SDHCI_CDNS_PHY_DLY_EMMC_DDR
> 
> (B) specified with DT property
> SDHCI_CDNS_PHY_DLY_SDCLK
> SDHCI_CDNS_PHY_DLY_HSMMC
> SDHCI_CDNS_PHY_DLY_STROBE
> 
> I am confused.
> What is the difference between (A) and (B)?

The first group of delays are input delays. These delays are set in current 
version of sdhci-cadence driver in sdhci_cdns_phy_init function.
Following by spec:
They are provided to help in meeting timings relations between data window and 
sampling clock. 
The clock is fixed position in respect to the SDCLK. And the idea of sampling 
is to delay and align the data to the data window.
If the default values of the delays are not sufficient/correct for the 
chip/board implementation those can be adjusted

The second group are DLL delays.
There are three delays
SDHCI_CDNS_PHY_DLY_SDCLK  - sdclk delay line use to delay outgoing sdclk signal
SDHCI_CDNS_PHY_DLY_HSMMC - sdclk delay line use to delay outgoing sdclk signal 
for for HS200, HS400 and HS400ES
SDHCI_CDNS_PHY_DLY_STROBE - DLL strobe delay for HS400ES
Following by spec:
They allows to setup basic DLL parameters. In general the default values are 
sufficient to start working in any speed mode. The default values of delays and 
phase detect select can be adjusted depending on the chip/board implementation. 

In general all PHY delays values either should be properly hardcoded in HW or 
they should be properly set  by FW depending on the chip/board.
So PHY driver should do not touch PHY delays at all or should set values which 
are proper for specific chip/board.

I am not sure where exactly they should be placed in dts file or in compatible 
data. 
  
Best Regards
Piotr Sroka


[v3] mmc: sdhci-cadence: add HS400 enhanced strobe support

2017-03-06 Thread Piotr Sroka
Add support for HS400ES mode to Cadence SDHCI driver.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes in v2:
- Modify enhanced strobe function to handle disabling 
  enhanced strobe inside the function. 
  Do no relay on that mmc_set_ios() is called 
  immediately after host->ops->hs400_enhanced_strobe(host, >ios).
Changes in v3:
- Few coding-style fixes were made.
---
 drivers/mmc/host/sdhci-cadence.c | 57 +++-
 1 file changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 316cfec..48f6419 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -40,6 +40,7 @@
 #define   SDHCI_CDNS_HRS06_MODE_MMC_DDR0x3
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS200  0x4
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS400  0x5
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400ES0x6
 
 /* SRS - Slot Register Set (SDHCI-compatible) */
 #define SDHCI_CDNS_SRS_BASE0x200
@@ -64,6 +65,7 @@
 
 struct sdhci_cdns_priv {
void __iomem *hrs_addr;
+   bool enhanced_strobe;
 };
 
 static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
@@ -108,11 +110,30 @@ static unsigned int sdhci_cdns_get_timeout_clock(struct 
sdhci_host *host)
return host->max_clk / 1000;
 }
 
+static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode)
+{
+   u32 tmp;
+
+   /* The speed mode for eMMC is selected by HRS06 register */
+   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
+   tmp |= mode;
+   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+}
+
+static u32 sdhci_cdns_get_emmc_mode(struct sdhci_cdns_priv *priv)
+{
+   u32 tmp;
+
+   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+   return tmp & SDHCI_CDNS_HRS06_MODE_MASK;
+}
+
 static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
 unsigned int timing)
 {
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
-   u32 mode, tmp;
+   u32 mode;
 
switch (timing) {
case MMC_TIMING_MMC_HS:
@@ -125,18 +146,17 @@ static void sdhci_cdns_set_uhs_signaling(struct 
sdhci_host *host,
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
break;
case MMC_TIMING_MMC_HS400:
-   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
+   if (priv->enhanced_strobe)
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
+   else
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
break;
default:
mode = SDHCI_CDNS_HRS06_MODE_SD;
break;
}
 
-   /* The speed mode for eMMC is selected by HRS06 register */
-   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
-   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
-   tmp |= mode;
-   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+   sdhci_cdns_set_emmc_mode(priv, mode);
 
/* For SD, fall back to the default handler */
if (mode == SDHCI_CDNS_HRS06_MODE_SD)
@@ -213,6 +233,26 @@ static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, 
u32 opcode)
return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
 }
 
+static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
+struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+   u32 mode;
+
+   priv->enhanced_strobe = ios->enhanced_strobe;
+
+   mode = sdhci_cdns_get_emmc_mode(priv);
+
+   if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400 && ios->enhanced_strobe)
+   sdhci_cdns_set_emmc_mode(priv,
+SDHCI_CDNS_HRS06_MODE_MMC_HS400ES);
+
+   if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400ES && !ios->enhanced_strobe)
+   sdhci_cdns_set_emmc_mode(priv,
+SDHCI_CDNS_HRS06_MODE_MMC_HS400);
+}
+
 static int sdhci_cdns_probe(struct platform_device *pdev)
 {
struct sdhci_host *host;
@@ -240,8 +280,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
 
priv = sdhci_cdns_priv(host);
priv->hrs_addr = host->ioaddr;
+   priv->enhanced_strobe = false;
host->ioaddr += SDHCI_CDNS_SRS_BASE;
host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
+   host->mmc_host_ops.hs400_enhanced_strobe =
+   sdhci_cdns_hs400_enhanced_strobe;
 
ret = mmc_of_parse(host->mmc);
if (ret)
-- 
2.2.2



[v2] mmc: sdhci-cadence: add HS400 enhanced strobe support

2017-03-03 Thread Piotr Sroka
Add support for HS400ES mode to Cadence SDHCI driver.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes in v2:
- Modify enhanced strobe function to handle disabling 
  enhanced strobe inside the function. 
  Do no relay on that mmc_set_ios() is called 
  immediately after host->ops->hs400_enhanced_strobe(host, >ios).
---
 drivers/mmc/host/sdhci-cadence.c | 57 +++-
 1 file changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 316cfec..6198ae2 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -40,6 +40,7 @@
 #define   SDHCI_CDNS_HRS06_MODE_MMC_DDR0x3
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS200  0x4
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS400  0x5
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400ES0x6
 
 /* SRS - Slot Register Set (SDHCI-compatible) */
 #define SDHCI_CDNS_SRS_BASE0x200
@@ -64,6 +65,7 @@
 
 struct sdhci_cdns_priv {
void __iomem *hrs_addr;
+   bool enhanced_strobe;
 };
 
 static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
@@ -108,11 +110,28 @@ static unsigned int sdhci_cdns_get_timeout_clock(struct 
sdhci_host *host)
return host->max_clk / 1000;
 }
 
+static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode)
+{
+   u32 tmp;
+
+   /* The speed mode for eMMC is selected by HRS06 register */
+   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
+   tmp |= mode;
+   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+}
+
+static void sdhci_cdns_get_emmc_mode(struct sdhci_cdns_priv *priv, u32 *mode)
+{
+   *mode = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+   *mode = *mode & SDHCI_CDNS_HRS06_MODE_MASK;
+}
+
 static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
 unsigned int timing)
 {
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
-   u32 mode, tmp;
+   u32 mode;
 
switch (timing) {
case MMC_TIMING_MMC_HS:
@@ -125,18 +144,17 @@ static void sdhci_cdns_set_uhs_signaling(struct 
sdhci_host *host,
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
break;
case MMC_TIMING_MMC_HS400:
-   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
+   if (priv->enhanced_strobe)
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
+   else
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
break;
default:
mode = SDHCI_CDNS_HRS06_MODE_SD;
break;
}
 
-   /* The speed mode for eMMC is selected by HRS06 register */
-   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
-   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
-   tmp |= mode;
-   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+   sdhci_cdns_set_emmc_mode(priv, mode);
 
/* For SD, fall back to the default handler */
if (mode == SDHCI_CDNS_HRS06_MODE_SD)
@@ -213,6 +231,28 @@ static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, 
u32 opcode)
return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
 }
 
+static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
+struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+   u32 timingMode;
+
+   priv->enhanced_strobe = ios->enhanced_strobe;
+
+   sdhci_cdns_get_emmc_mode(priv, );
+
+   if (timingMode == SDHCI_CDNS_HRS06_MODE_MMC_HS400 &&
+   ios->enhanced_strobe)
+   sdhci_cdns_set_emmc_mode(priv,
+SDHCI_CDNS_HRS06_MODE_MMC_HS400ES);
+
+   if (timingMode == SDHCI_CDNS_HRS06_MODE_MMC_HS400ES &&
+   !ios->enhanced_strobe)
+   sdhci_cdns_set_emmc_mode(priv,
+SDHCI_CDNS_HRS06_MODE_MMC_HS400);
+}
+
 static int sdhci_cdns_probe(struct platform_device *pdev)
 {
struct sdhci_host *host;
@@ -240,8 +280,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
 
priv = sdhci_cdns_priv(host);
priv->hrs_addr = host->ioaddr;
+   priv->enhanced_strobe = false;
host->ioaddr += SDHCI_CDNS_SRS_BASE;
host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
+   host->mmc_host_ops.hs400_enhanced_strobe =
+   sdhci_cdns_hs400_enhanced_strobe;
 
ret = mmc_of_parse(host->mmc);
if (ret)
-- 
2.2.2



RE: [PATCH] mmc: core: fix changing bus witdh in hs400es mode

2017-03-02 Thread Piotr Sroka
Hi Shawn

Thanks for the information.

Best Regards
Piotr Sroka

> -Original Message-
> From: Shawn Lin [mailto:shawn@rock-chips.com]
> Sent: 03 March, 2017 4:43 AM
> Subject: Re: [PATCH] mmc: core: fix changing bus witdh in hs400es mode
> 
> Hi Poitr,
> 
> On 2017/3/2 21:47, Piotr Sroka wrote:
> > Fix the code to avoid changing bus width if HS400ES mode is selected.
> >
> 
> Thanks for catching this, but Guenter posted a fix[1] already. :)
> 
> [1]: https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__patchwork.kernel.org_patch_9599261_=DwICbg=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-
> _haXqY=TGZtNfZu5Cjhu2K8A0Qhsot4HlKpSJ0Xmyc_L8hPwSI=z53GwiPyaRw9P09VfO84zhV8cTwdYWUhcbZBPTOUbXE=vtPh-
> 0g7-O6PZJOdgFp0jZeMrve8EG6qLDpphJN1vuM=
> 
> > Signed-off-by: Piotr Sroka <pio...@cadence.com>
> > ---
> >  drivers/mmc/core/mmc.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index
> > 7fd7228..c7d9c9f 100644
> > --- a/drivers/mmc/core/mmc.c
> > +++ b/drivers/mmc/core/mmc.c
> > @@ -1730,7 +1730,7 @@ static int mmc_init_card(struct mmc_host *host, u32 
> > ocr,
> > err = mmc_select_hs400(card);
> > if (err)
> > goto free_card;
> > -   } else {
> > +   } else if (!mmc_card_hs400(card)) {
> > /* Select the desired bus width optionally */
> > err = mmc_select_bus_width(card);
> > if (err > 0 && mmc_card_hs(card)) {
> >
> 
> 
> --
> Best Regards
> Shawn Lin



[v5 2/4] dt-bindings: mmc: add description of PHY delays for sdhci-cadence

2017-03-21 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.
Add description of new DLL PHY delays.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- file was created in v2. It was a part of driver source file patch.
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- description of delays was updated to be more clearly
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
---
Changes for v4:
- change the beginning of the commit subject
---
Changes for v5:
- change name of property to be consistent with timing modes 
  available in Linux
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..fa423c2 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,53 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+Some PHY delays can be configured by following properties.
+PHY DLL input delays:
+They are used to delay the data valid window, and align the window
+to sampling clock. The delay starts from 5ns (for delay parameter equal to 0)
+and it is increased by 2.5ns in each step.
+- cdns,phy-input-delay-sd-highspeed:
+  Value of the delay in the input path for SD high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-legacy:
+  Value of the delay in the input path for legacy timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr12:
+  Value of the delay in the input path for SD UHS SDR12 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr25:
+  Value of the delay in the input path for SD UHS SDR25 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr50:
+  Value of the delay in the input path for SD UHS SDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-ddr50:
+  Value of the delay in the input path for SD UHS DDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-highspeed:
+  Value of the delay in the input path for MMC high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-ddr:
+  Value of the delay in the input path for eMMC high-speed DDR timing
+  Valid range = [0:0x1F].
+
+PHY DLL clock delays:
+Each delay property represents the fraction of the clock period.
+The approximate delay value will be
+(/128)*sdmclk_clock_period.
+- cdns,phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +76,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   cdns,phy-dll-delay-sdclk = <0>;
};
-- 
2.2.2



[v5 1/4] mmc: sdhci-cadence: Fix writing PHY delay

2017-03-21 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- fix indent
---
Changes for v3:
- none
---
Changes for v4:
- none
---
Changes for v5:
- use driver version from next branch, with applied enhanced strobe feature 
support.
---
 drivers/mmc/host/sdhci-cadence.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 48f6419..83c3b55 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -68,11 +68,12 @@ struct sdhci_cdns_priv {
bool enhanced_strobe;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
-u8 addr, u8 data)
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+   u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -81,8 +82,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



[v5 4/4] mmc: sdhci-cadence: refactor probe function

2017-03-21 Thread Piotr Sroka
Use added dev variable for devm_clk_get.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v5:
- patch created in v5
---
 drivers/mmc/host/sdhci-cadence.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index c3c7090..5aa238d 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -305,7 +305,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
int ret;
struct device *dev = >dev;
 
-   clk = devm_clk_get(>dev, NULL);
+   clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk))
return PTR_ERR(clk);
 
-- 
2.2.2



[v5 3/4] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-21 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.

Signed-off-by: Piotr Sroka <pio...@cadence.com>
---
Changes for v2:
- dts part was removed from this patch
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- remove unrelated changes
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
- put checking delay properties inside the for loop
  instead of using a lot of single if expressions
---
Changes for v4:
- remove unecessary declaration of sdhci_cdns_match
- format fix (blank line removed)
---
Changes for v5:
- use driver version from next branch, with applied enhanced strobe feature 
support.
- change name of property to be consistent with timing modes 
  available in Linux
---
 drivers/mmc/host/sdhci-cadence.c | 53 ++--
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 83c3b55..c3c7090 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -55,6 +56,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -68,6 +72,25 @@ struct sdhci_cdns_priv {
bool enhanced_strobe;
 };
 
+struct sdhci_cdns_phy_cfg {
+   const char *property;
+   u8 addr;
+};
+
+static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
+   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
+   { "cdns,phy-input-delay-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
+   { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
+   { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
+   { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
+   { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
+   { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
+   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
+   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
+   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
+   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
+};
+
 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
u8 addr, u8 data)
 {
@@ -92,13 +115,26 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_init(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 val;
+   int ret, i;
+
+   for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
+   ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
+  );
+   if (ret)
+   continue;
+
+   ret = sdhci_cdns_write_phy_reg(priv,
+  sdhci_cdns_phy_cfgs[i].addr,
+  val);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
 }
 
 static inline void *sdhci_cdns_priv(struct sdhci_host *host)
@@ -267,6 +303,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
struct sdhci_cdns_priv *priv;
struct clk *clk;
int ret;
+   struct device *dev = >dev;
 
clk = devm_clk_get(>dev, NULL);
if (IS_ERR(clk))
@@ -297,7 +334,9 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
if (ret)
goto free;
 
-   sdhci_cdns_phy_init(priv);
+   ret = sdhci_cdns_phy_init(dev->of_node, priv);
+   if (ret)
+   goto free;
 
ret = sdhci_add_host(host);
if (ret)
-- 
2.2.2



[v3 0/2] mtd: nand: Add Cadence NAND controller driver

2019-06-14 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.

Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  dt-bindings: nand: Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   51 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3119 
 4 files changed, 3178 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



[v3 1/2] mtd: nand: Add Cadence NAND controller driver

2019-06-14 Thread Piotr Sroka
Signed-off-by: Piotr Sroka 
---
Changes for v3:
- remove definitions of unused registres/
- remove configuring registers which are not excpected to be configured in
  asynchronous mode
- remove not needed function reading timing registers
- remove information about oob size and write size from cdns_nand_chip type
  and use vales from mtd_info directly
- use nand_cleanup instead of nand_release if mtd device is not registered yet
- fix cadence_nand_chips_init function add garbage collection 
  if a chip init fails
- simplify PHY calculations
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines 
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3119 
 3 files changed, 3127 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e604625e2dfa..4d2ce3b5b2ae 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -557,5 +557,12 @@ config MTD_NAND_MESON
help
  Enables support for NAND controller on Amlogic's Meson SoCs.
  This controller is found on Meson SoCs.
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
 
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 5a5a72f0793e..f4b099f276f7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_MTK)+= mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c 
b/drivers/mtd/nand/raw/cadence-nand-controller.c
new file mode 100644
index ..6c6f515e424a
--- /dev/null
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -0,0 +1,3119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cadence NAND flash controller driver
+ *
+ * Copyright (C) 2019 Cadence
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_OOB_SIZE_PER_SECTOR32
+#define MAX_ADDRESS_CYC6
+#define MAX_ERASE_ADDRESS_CYC  3
+#define MAX_DATA_SIZE  0xFFFC
+
+/* Register definition. */
+/*
+ * Command register 0.
+ * Writing data to this register will initiate a new transaction
+ * of the NF controller.
+ */
+#define CMD_REG0   0x
+/* Command type field mask. */
+#defineCMD_REG0_CT GENMASK(31, 30)
+/* Command type CDMA. */
+#defineCMD_REG0_CT_CDMA0uL
+/* Command type generic. */
+#defineCMD_REG0_CT_GEN 3uL
+/* Command thread number field mask. */
+#defineCMD_REG0_TN GENMASK(27, 24)
+
+/* Command register 2. */
+#define CMD_REG2   0x0008
+/* Command register 3. */
+#define CMD_REG3   0x000C
+/* Pointer register to select which thread status will be selected. */
+#define CMD_STATUS_PTR 0x0010
+/* Command status register for selected thread. */
+#define CMD_STATUS 0x0014
+
+/* Interrupt status register. */
+#define INTR_STATUS0x0110
+#defineINTR_STATUS_SDMA_ERRBIT(22)
+#defineINTR_STATUS_SDMA_TRIGG  BIT(21)
+#defineINTR_STATUS_UNSUPP_CMD  BIT(19)
+#defineINTR_STATUS_DDMA_TERR   BIT(18)
+#defineINTR_STATUS_CDMA_TERR   BIT(17)
+#defineINTR_STATUS_CDMA_IDLBIT(16)
+
+/* Interrupt enable register. */
+#define INTR_ENABLE0x0114
+#defineINTR_ENABLE_INTR_EN BIT(31)
+#defineINTR_ENABLE_S

[v3 2/2] dt-bindings: nand: Add Cadence NAND controller driver

2019-06-14 Thread Piotr Sroka
Signed-off-by: Piotr Sroka 
---
Changes for v3:
- add unit suffix for board_delay 
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 51 ++
 1 file changed, 51 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..e485b87075bd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,51 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hpnfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay_ps : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board_delay = RE#PAD_delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Children nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller @6000 {
+
+ compatible = "cdns,hpnfc";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay_ps = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
-- 
2.15.0



Re: [v3 2/2] dt-bindings: nand: Add Cadence NAND controller driver

2019-07-17 Thread Piotr Sroka

The 07/09/2019 08:48, Rob Herring wrote:

EXTERNAL MAIL


On Fri, Jun 14, 2019 at 04:13:01PM +0100, Piotr Sroka wrote:

Signed-off-by: Piotr Sroka 
---
Changes for v3:
- add unit suffix for board_delay
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 51 ++
 1 file changed, 51 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..e485b87075bd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,51 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hpnfc"


Only 1 version of h/w features and bugs?


At the moment, yes.


'hp-nfc' would be a bit more readable IMO.


I will replace it.


+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay_ps : Estimated Board delay. The value includes the total


s/_/-/


+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board_delay = RE#PAD_delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Children nodes represent the available NAND chips.


Child nodes...


+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller @6000 {


remove space   ^


+
+ compatible = "cdns,hpnfc";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay_ps = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
--
2.15.0


Thanks
Piotr
 





[v7 0/2] mtd: rawnand: Add Cadence NAND controller driver

2019-09-18 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.

Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   53 +
 MAINTAINERS|7 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3036 
 5 files changed, 3104 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



[v7 1/2] mtd: rawnand: Add new Cadence NAND driver to MTD subsystem

2019-09-18 Thread Piotr Sroka
Add new Cadence NAND driver to MTD subsystem

Signed-off-by: Piotr Sroka 
Reported-by: kbuild test robot 
---
Changes for v7:
- replace readls with ioread32_rep and writesl with iowrite32_rep
 to avoid compilation errors on parisc architecture
Changes for v6:
- add support for bank addressing modified in HPNFC R013 version
- change type of data_control_supp and is_phy_type_dll from u8 to bool
- fix writing and reading data for HPNFC slave DMA interface connected 
  directly to AHB/AXI instead of external DMA engine.
- the default value of the board-delay parameter is set to other than 0 
  when it is not defined in the dts file
- put myself as maintainer of the Cadence nand driver
Changes for v5:
- fix "ecc config strength" field size
- remove unused macros
- fix address of timing2 register
- add guard for accessing data_control_size register
- simplify the driver by use the same function 
  for accessing main area and oob area
- add comment to the driver describing main controller modes
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- fix comments issues like typos, missing capitals, missing dots etc.
- remove unnecessary PHY options phy_dll_aging and phy_per_bit_deskew
- replace all register access functions to "relaxed" version
- remove all unnecessary variables initializations
- handle error inside cadence_nand_get_ecc_strength_idx function in case 
  correnction strength is not found
- add commit message
Changes for v3:
- remove definitions of unused registers
- remove configuring registers which are not expected to be configured in
  asynchronous mode
- remove not needed function reading timing registers
- remove information about oob size and write size from cdns_nand_chip type
  and use vales from mtd_info directly
- use nand_cleanup instead of nand_release if mtd device is not registered yet
- fix cadence_nand_chips_init function add garbage collection 
  if a chip init fails
- simplify PHY calculations
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines 
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 MAINTAINERS|6 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3036 
 4 files changed, 3050 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 783569e3c4b4..16e16445b88b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3579,6 +3579,12 @@ S:   Maintained
 F: Documentation/devicetree/bindings/media/cdns,*.txt
 F: drivers/media/platform/cadence/cdns-csi2*
 
+CADENCE NAND DRIVER
+M: Piotr Sroka 
+L: linux-...@lists.infradead.org
+S: Maintained
+F: drivers/mtd/nand/raw/cadence-nand-controller.c
+
 CADET FM/AM RADIO RECEIVER DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e59de3f60cf6..74fb91adeb46 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -450,6 +450,13 @@ config MTD_NAND_PLATFORM
  devices. You will need to provide platform-specific functions
  via platform_data.
 
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF || COMPILE_TEST
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
 comment "Misc"
 
 config MTD_SM_COMMON
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index a98721988e61..2d136b158fb7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_MXIC)   += mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c 
b/drivers/mtd/nand/raw/cadence-nand-controller.c
new file mode 100644
index ..376dc5187

[v7 2/2] dt-bindings: mtd: Add Cadence NAND controller driver

2019-09-18 Thread Piotr Sroka
Document the bindings used by Cadence NAND controller driver

Signed-off-by: Piotr Sroka 
Reviewed-by: Rob Herring 
---
Changes for v7:
- none
Changes for v6:
- add documentation for address-cells and size-cells
- remove not needed space
- put myself as maintainer of the Cadence nand driver bindings
Changes for v5:
- replace "_" by "-" in all properties
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- add commit message
Changes for v3:
- add unit suffix for board_delay 
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 53 ++
 MAINTAINERS|  1 +
 2 files changed, 54 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..f3893c4d3c6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,53 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hp-nfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - #address-cells: should be 1. The cell encodes the chip select connection.
+  - #size-cells : should be 0.
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay-ps : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board delay = RE#PAD delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Child nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller@6000 {
+ compatible = "cdns,hp-nfc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay-ps = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 16e16445b88b..94d78f4e29ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3584,6 +3584,7 @@ M:Piotr Sroka 
 L: linux-...@lists.infradead.org
 S: Maintained
 F: drivers/mtd/nand/raw/cadence-nand-controller.c
+F: Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 
 CADET FM/AM RADIO RECEIVER DRIVER
 M: Hans Verkuil 
-- 
2.15.0



[PATCH] - change calculating of position page containing BBM

2019-09-19 Thread Piotr Sroka
Change calculating of position page containing BBM

If none of BBM flags is set then function nand_bbm_get_next_page 
reports EINVAL. It causes that BBM is not read at all during scanning
factory bad blocks. The result is that the BBT table is build without 
checking factory BBM at all. For Micron flash memories none of this 
flag is set if page size is different than 2048 bytes.

This patch changes the nand_bbm_get_next_page function.
It will return 0 if none of BBM flag is set and page parameter is 0. 
After that modification way of discovering factory bad blocks will work 
similar as in kernel version 5.1.

Signed-off-by: Piotr Sroka 
---
 drivers/mtd/nand/raw/nand_base.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 5c2c30a7dffa..f64e3b6605c6 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -292,12 +292,16 @@ int nand_bbm_get_next_page(struct nand_chip *chip, int 
page)
struct mtd_info *mtd = nand_to_mtd(chip);
int last_page = ((mtd->erasesize - mtd->writesize) >>
 chip->page_shift) & chip->pagemask;
+   unsigned int bbm_flags = NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE
+   | NAND_BBM_LASTPAGE;
 
+   if (page == 0 && !(chip->options & bbm_flags))
+   return 0;
if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE)
return 0;
-   else if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
+   if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
return 1;
-   else if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
+   if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
return last_page;
 
return -EINVAL;
-- 
2.15.0



Re: [v5 1/2] mtd: nand: Add new Cadence NAND driver to MTD subsystem

2019-09-11 Thread Piotr Sroka

The 08/30/2019 11:46, Miquel Raynal wrote:

EXTERNAL MAIL


Hi Piotr,

Piotr Sroka  wrote on Thu, 25 Jul 2019 16:00:12
+0100:

Subject should be: mtd: rawnand:

Last few nits in your driver which overall looks good (see below).

Now I'm waiting for Rob's ack on the bindings. This driver should be a
good candidate for 5.5.


I think that Rob alredy review it. You can find hist review on
https://patchwork.ozlabs.org/patch/1136932/
Let me know if something else should be improved or fixed.




Add new Cadence NAND driver to MTD subsystem

Signed-off-by: Piotr Sroka 
---
Changes for v5:
- fix "ecc config strength" field size
- remove unused macros
- fix address of timing2 register
- add guard for accessing data_control_size register
- simplify the driver by use the same function
  for accessing main area and oob area
- add comment to the driver describing main controller modes
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- fix comments issues like typos, missing capitals, missing dots etc.
- remove unnecessary PHY options phy_dll_aging and phy_per_bit_deskew
- replace all register access functions to "relaxed" version
- remove all unnecessary variables initializations
- handle error inside cadence_nand_get_ecc_strength_idx function in case
  correnction strength is not found
- add commit message
Changes for v3:
- remove definitions of unused registers
- remove configuring registers which are not expected to be configured in
  asynchronous mode
- remove not needed function reading timing registers
- remove information about oob size and write size from cdns_nand_chip type
  and use vales from mtd_info directly
- use nand_cleanup instead of nand_release if mtd device is not registered yet
- fix cadence_nand_chips_init function add garbage collection
  if a chip init fails
- simplify PHY calculations
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3021 
 3 files changed, 3029 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e604625e2dfa..4d2ce3b5b2ae 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -557,5 +557,12 @@ config MTD_NAND_MESON
help
  Enables support for NAND controller on Amlogic's Meson SoCs.
  This controller is found on Meson SoCs.


Missing space?


+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF


|| COMPILE_TEST


+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+

 endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 5a5a72f0793e..f4b099f276f7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_MTK)+= mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o

 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c 
b/drivers/mtd/nand/raw/cadence-nand-controller.c
new file mode 100644
index ..a7ff4e4585d3
--- /dev/null
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -0,0 +1,3021 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cadence NAND flash controller driver
+ *
+ * Copyright (C) 2019 Cadence


I guess you deserve the Author: entry here :)



Right. Thanks :)
 

+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * HPNFC can work in 3 modes:
+ * -  PIO - can work in master or slave DMA.
+ * -  CDMA - needs Master DMA for accessing command descriptors.
+ * -  Generic mode - can use only slave DMA.
+ * CDMA and PIO modes can be used to execute only base commands.
+ * Gener

Re: [v5 2/2] dt-bindings: mtd: Add Cadence NAND controller driver

2019-09-11 Thread Piotr Sroka

Hi Miquel

The 08/30/2019 11:46, Miquel Raynal wrote:

EXTERNAL MAIL


Hi Piotr,

Piotr Sroka  wrote on Thu, 25 Jul 2019 15:59:55
+0100:


Document the bindings used by Cadence NAND controller driver

Signed-off-by: Piotr Sroka 
---
Changes for v5:
- replace "_" by "-" in all properties
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- add commit message
Changes for v3:
- add unit suffix for board_delay
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 50 ++
 1 file changed, 50 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..423547a3f993
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,50 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hp-nfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay-ps : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board delay = RE#PAD delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Child nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller @6000 {
+ compatible = "cdns,hp-nfc";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay-ps = <4830>;


Are you sure you want to export this to the user? Not sure it is easily
understandable and tunable... I'm not against but I would have troubles
tuning it myself, unless using the documented value. Maybe you should
explain more how to derive it?

I need to export this parameter somehow. The default value may not be
valid for other platforms. 
This value depends on platform, and may be different on different SoCs. 
So I think the DTS is the best place to put such configuration

parameter.



The rest looks fine, let's see if Rob agrees. Maybe he will request a
yaml schema; in this case you can check sunxi NAND bindings which
already have been converted.


+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};


Thanks,
Miquèl



Thanks
Piotr 


[v5 0/2] mtd: nand: Add Cadence NAND controller driver

2019-07-25 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.

Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   50 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3021 
 4 files changed, 3079 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



[v5 2/2] dt-bindings: mtd: Add Cadence NAND controller driver

2019-07-25 Thread Piotr Sroka
Document the bindings used by Cadence NAND controller driver

Signed-off-by: Piotr Sroka 
---
Changes for v5:
- replace "_" by "-" in all properties
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- add commit message
Changes for v3:
- add unit suffix for board_delay 
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 50 ++
 1 file changed, 50 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..423547a3f993
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,50 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hp-nfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay-ps : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board delay = RE#PAD delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Child nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller @6000 {
+ compatible = "cdns,hp-nfc";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay-ps = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
-- 
2.15.0



[v5 1/2] mtd: nand: Add new Cadence NAND driver to MTD subsystem

2019-07-25 Thread Piotr Sroka
Add new Cadence NAND driver to MTD subsystem

Signed-off-by: Piotr Sroka 
---
Changes for v5:
- fix "ecc config strength" field size
- remove unused macros
- fix address of timing2 register
- add guard for accessing data_control_size register
- simplify the driver by use the same function 
  for accessing main area and oob area
- add comment to the driver describing main controller modes
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- fix comments issues like typos, missing capitals, missing dots etc.
- remove unnecessary PHY options phy_dll_aging and phy_per_bit_deskew
- replace all register access functions to "relaxed" version
- remove all unnecessary variables initializations
- handle error inside cadence_nand_get_ecc_strength_idx function in case 
  correnction strength is not found
- add commit message
Changes for v3:
- remove definitions of unused registers
- remove configuring registers which are not expected to be configured in
  asynchronous mode
- remove not needed function reading timing registers
- remove information about oob size and write size from cdns_nand_chip type
  and use vales from mtd_info directly
- use nand_cleanup instead of nand_release if mtd device is not registered yet
- fix cadence_nand_chips_init function add garbage collection 
  if a chip init fails
- simplify PHY calculations
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines 
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3021 
 3 files changed, 3029 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e604625e2dfa..4d2ce3b5b2ae 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -557,5 +557,12 @@ config MTD_NAND_MESON
help
  Enables support for NAND controller on Amlogic's Meson SoCs.
  This controller is found on Meson SoCs.
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
 
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 5a5a72f0793e..f4b099f276f7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_MTK)+= mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c 
b/drivers/mtd/nand/raw/cadence-nand-controller.c
new file mode 100644
index ..a7ff4e4585d3
--- /dev/null
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -0,0 +1,3021 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cadence NAND flash controller driver
+ *
+ * Copyright (C) 2019 Cadence
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * HPNFC can work in 3 modes:
+ * -  PIO - can work in master or slave DMA.
+ * -  CDMA - needs Master DMA for accessing command descriptors.
+ * -  Generic mode - can use only slave DMA.
+ * CDMA and PIO modes can be used to execute only base commands.
+ * Generic mode can be used to execute any command
+ * on NAND flash memory. Driver uses CDMA mode for
+ * block erasing, page reading, page programing.
+ * Generic mode is used for executing rest of commands.
+ */
+
+#define MAX_OOB_SIZE_PER_SECTOR32
+#define MAX_ADDRESS_CYC6
+#define MAX_ERASE_ADDRESS_CYC  3
+#define MAX_DATA_SIZE  0xFFFC
+
+/* Register definition. */
+/*
+ * Command register 0.
+ * Writing data to this register will initiate a new transaction
+ * of the NF controller.
+ */
+#define CMD_REG0   0x
+/* Comman

Re: [PATCH v2 2/2] dt-bindings: nand: Add Cadence NAND controller driver

2019-06-07 Thread Piotr Sroka

Hi Rob

Thanks for reviwing this.

The 02/22/2019 14:40, Rob Herring wrote:

EXTERNAL MAIL


On Tue, Feb 19, 2019 at 04:19:20PM +, Piotr Sroka wrote:

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
  under the NAND controller node
---
 .../bindings/mtd/cadence-nand-controller.txt   | 48 ++
 1 file changed, 48 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..3d9b4decae24
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,48 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hpnfc"


Only one version of IP or is that discoverable?

In general IP is configurable. There are a lot of configurations options.
Most features are checked in runtime base on controller registers.
Some of capabilities are not shared by registersn. But there is not sense to 
create
all possible configuration here. I think more compatible may appear if
sombody add here a SoC.




+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "cadence_reg" and "cadence_sdma"


'cadence_' part is pointless.


+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+  - Children nodes represent the available NAND chips.


Need a blank line and remove the '-' as it's not a property.


+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+Optional properties:


For child nodes? If not move before child nodes.


+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board_delay = RE#PAD_delay + PCB trace to device + PCB trace from device
++ DQ PAD delay


Units? Use unit suffix as defined in property-units.txt.


+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller @6000 {


space  ^


+ compatible = "cdns,hpnfc";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "cadence_reg", "cadence_sdma";
+ clocks = <_clk>;
+ cdns,board-delay = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
--
2.15.0



Thanks
Piotr Sroka


Re: [v3 1/2] mtd: nand: Add Cadence NAND controller driver

2019-06-25 Thread Piotr Sroka

Hi Dmitry

The 06/16/2019 16:42, Dmitry Osipenko wrote:

EXTERNAL MAIL


14.06.2019 18:09, Piotr Sroka пишет:

Commit description is mandatory.


Signed-off-by: Piotr Sroka 
---


[snip]


+
+/* Cadnence NAND flash controller capabilities get from driver data. */
+struct cadence_nand_dt_devdata {
+   /* Skew value of the output signals of the NAND Flash interface. */
+   u32 if_skew;
+   /* It informs if aging feature in the DLL PHY supported. */
+   u8 phy_dll_aging;
+   /*
+* It informs if per bit deskew for read and write path in
+* the PHY is supported.
+*/
+   u8 phy_per_bit_deskew;
+   /* It informs if slave DMA interface is connected to DMA engine. */
+   u8 has_dma;


There is no needed to dedicate 8 bits to a variable if you only care about a 
single
bit. You may write this as:

bool has_dma : 1;

I modified it locally but it looks that checkpatch does not like such
notation
"WARNING: Avoid using bool as bitfield.  Prefer bool bitfields as
unsigned int or u<8|16|32>"
So maybe I will leave it as is.


[snip]


+static struct
+cdns_nand_chip *to_cdns_nand_chip(struct nand_chip *chip)
+{
+   return container_of(chip, struct cdns_nand_chip, chip);
+}
+
+static struct
+cdns_nand_ctrl *to_cdns_nand_ctrl(struct nand_controller *controller)
+{
+   return container_of(controller, struct cdns_nand_ctrl, controller);
+}


It's better to inline explicitly such cases because they won't get inlined with 
some
kernel configurations, like enabled ftracing for example.


+static bool
+cadence_nand_dma_buf_ok(struct cdns_nand_ctrl *cdns_ctrl, const void *buf,
+   u32 buf_len)
+{
+   u8 data_dma_width = cdns_ctrl->caps2.data_dma_width;
+
+   return buf && virt_addr_valid(buf) &&
+   likely(IS_ALIGNED((uintptr_t)buf, data_dma_width)) &&
+   likely(IS_ALIGNED(buf_len, data_dma_width));
+}
+
+static int cadence_nand_wait_for_value(struct cdns_nand_ctrl *cdns_ctrl,
+  u32 reg_offset, u32 timeout_us,
+  u32 mask, bool is_clear)
+{
+   u32 val;
+   int ret = 0;
+
+   ret = readl_poll_timeout(cdns_ctrl->reg + reg_offset,
+val, !(val & mask) == is_clear,
+10, timeout_us);


Apparently you don't care about having memory barrier here, hence
readl_relaxed_poll_timeout().

ok I will update it.



+   if (ret < 0) {
+   dev_err(cdns_ctrl->dev,
+   "Timeout while waiting for reg %x with mask %x is clear 
%d\n",
+   reg_offset, mask, is_clear);
+   }
+
+   return ret;
+}
+
+static int cadence_nand_set_ecc_enable(struct cdns_nand_ctrl *cdns_ctrl,
+  bool enable)
+{
+   u32 reg;
+
+   if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS,
+   100,
+   CTRL_STATUS_CTRL_BUSY, true))
+   return -ETIMEDOUT;
+
+   reg = readl(cdns_ctrl->reg + ECC_CONFIG_0);
+
+   if (enable)
+   reg |= ECC_CONFIG_0_ECC_EN;
+   else
+   reg &= ~ECC_CONFIG_0_ECC_EN;
+
+   writel(reg, cdns_ctrl->reg + ECC_CONFIG_0);


And here.. looks like there is no need for the memory barries, hence use the 
relaxed
versions of readl/writel. Same for the rest of the patch.


ok

+   return 0;
+}
+
+static void cadence_nand_set_ecc_strength(struct cdns_nand_ctrl *cdns_ctrl,
+ u8 corr_str_idx)
+{
+   u32 reg;
+
+   if (cdns_ctrl->curr_corr_str_idx == corr_str_idx)
+   return;
+
+   reg = readl(cdns_ctrl->reg + ECC_CONFIG_0);
+   reg &= ~ECC_CONFIG_0_CORR_STR;
+   reg |= FIELD_PREP(ECC_CONFIG_0_CORR_STR, corr_str_idx);
+   writel(reg, cdns_ctrl->reg + ECC_CONFIG_0);
+
+   cdns_ctrl->curr_corr_str_idx = corr_str_idx;
+}
+
+static u8 cadence_nand_get_ecc_strength_idx(struct cdns_nand_ctrl *cdns_ctrl,
+   u8 strength)
+{
+   u8 i, corr_str_idx = 0;
+
+   for (i = 0; i < BCH_MAX_NUM_CORR_CAPS; i++) {
+   if (cdns_ctrl->ecc_strengths[i] == strength) {
+   corr_str_idx = i;
+   break;
+   }
+   }


Is it a error case when i == BCH_MAX_NUM_CORR_CAPS?

Yes it is an error but it could appear only if ECC capability registers
have wrong values. I will handle that error anyway.


+   return corr_str_idx;
+}
+
+static int cadence_nand_set_skip_marker_val(struct cdns_nand_ctrl *cdns_ctrl,
+   u16 marker_value)
+{
+   u32 reg = 0;
+
+   if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS,
+   100,
+

[v4 0/2] mtd: nand: Add Cadence NAND controller driver

2019-06-25 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.

Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   51 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3109 
 4 files changed, 3168 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



[v4 1/2] mtd: nand: Add new Cadence NAND driver to MTD subsystem

2019-06-25 Thread Piotr Sroka
Add new Cadence NAND driver to MTD subsystem

Signed-off-by: Piotr Sroka 
---
Changes for v4:
- fix comments issues like typos, missing capitals, missing dots etc.
- remove unnecessary PHY options phy_dll_aging and phy_per_bit_deskew
- replace all register access functions to "relaxed" version
- remove all unnecessary variables initializations
- hanlde error inside cadence_nand_get_ecc_strength_idx function in case 
  correnction strength is not found
- add commit message
Changes for v3:
- remove definitions of unused registres/
- remove configuring registers which are not excpected to be configured in
  asynchronous mode
- remove not needed function reading timing registers
- remove information about oob size and write size from cdns_nand_chip type
  and use vales from mtd_info directly
- use nand_cleanup instead of nand_release if mtd device is not registered yet
- fix cadence_nand_chips_init function add garbage collection 
  if a chip init fails
- simplify PHY calculations
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines 
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3109 
 3 files changed, 3117 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e604625e2dfa..4d2ce3b5b2ae 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -557,5 +557,12 @@ config MTD_NAND_MESON
help
  Enables support for NAND controller on Amlogic's Meson SoCs.
  This controller is found on Meson SoCs.
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
 
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 5a5a72f0793e..f4b099f276f7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_MTK)+= mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c 
b/drivers/mtd/nand/raw/cadence-nand-controller.c
new file mode 100644
index ..90a266c56e38
--- /dev/null
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -0,0 +1,3109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cadence NAND flash controller driver
+ *
+ * Copyright (C) 2019 Cadence
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_OOB_SIZE_PER_SECTOR32
+#define MAX_ADDRESS_CYC6
+#define MAX_ERASE_ADDRESS_CYC  3
+#define MAX_DATA_SIZE  0xFFFC
+
+/* Register definition. */
+/*
+ * Command register 0.
+ * Writing data to this register will initiate a new transaction
+ * of the NF controller.
+ */
+#define CMD_REG0   0x
+/* Command type field mask. */
+#defineCMD_REG0_CT GENMASK(31, 30)
+/* Command type CDMA. */
+#defineCMD_REG0_CT_CDMA0uL
+/* Command type generic. */
+#defineCMD_REG0_CT_GEN 3uL
+/* Command thread number field mask. */
+#defineCMD_REG0_TN GENMASK(27, 24)
+
+/* Command register 2. */
+#define CMD_REG2   0x0008
+/* Command register 3. */
+#define CMD_REG3   0x000C
+/* Pointer register to select which thread status will be selected. */
+#define CMD_STATUS_PTR 0x0010
+/* Command status register for selected thread. */
+#define CMD_STATUS 0x0014
+
+/* Interrupt status register. */
+#define INTR_STATUS0x0110
+#defineINTR_STATUS_SDMA_ERR

[v4 2/2] dt-bindings: mtd: Add Cadence NAND controller driver

2019-06-25 Thread Piotr Sroka
Document the bindings used by Cadence NAND controller driver

Signed-off-by: Piotr Sroka 
---
Changes for v4:
- add commit message
Changes for v3:
- add unit suffix for board_delay 
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 51 ++
 1 file changed, 51 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..e485b87075bd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,51 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hpnfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay_ps : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board_delay = RE#PAD_delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Children nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller @6000 {
+
+ compatible = "cdns,hpnfc";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay_ps = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
-- 
2.15.0



Re: [v5 2/2] dt-bindings: mtd: Add Cadence NAND controller driver

2019-09-13 Thread Piotr Sroka

The 09/13/2019 14:49, Miquel Raynal wrote:

EXTERNAL MAIL


Hi Piotr,

Piotr Sroka  wrote on Wed, 11 Sep 2019 16:04:24
+0100:


Hi Miquel

The 08/30/2019 11:46, Miquel Raynal wrote:
>EXTERNAL MAIL
>
>
>Hi Piotr,
>
>Piotr Sroka  wrote on Thu, 25 Jul 2019 15:59:55
>+0100:
>
>> Document the bindings used by Cadence NAND controller driver
>>
>> Signed-off-by: Piotr Sroka 
>> ---
>> Changes for v5:
>> - replace "_" by "-" in all properties
>> - change compatible name from cdns,hpnfc to cdns,hp-nfc
>> Changes for v4:
>> - add commit message
>> Changes for v3:
>> - add unit suffix for board_delay
>> - move child description to proper place
>> - remove prefix cadence_ for reg and sdma fields
>> Changes for v2:
>> - remove chip dependends parameters from dts bindings
>> - add names for register ranges in dts bindings
>> - add generic bindings to describe NAND chip representation
>> ---
>>  .../bindings/mtd/cadence-nand-controller.txt   | 50 
++
>>  1 file changed, 50 insertions(+)
>>  create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
>>
>> diff --git 
a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
>> new file mode 100644
>> index ..423547a3f993
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
>> @@ -0,0 +1,50 @@
>> +* Cadence NAND controller
>> +
>> +Required properties:
>> +  - compatible : "cdns,hp-nfc"
>> +  - reg : Contains two entries, each of which is a tuple consisting of a
>> +physical address and length. The first entry is the address and
>> +length of the controller register set. The second entry is the
>> +address and length of the Slave DMA data port.
>> +  - reg-names: should contain "reg" and "sdma"
>> +  - interrupts : The interrupt number.
>> +  - clocks: phandle of the controller core clock (nf_clk).
>> +
>> +Optional properties:
>> +  - dmas: shall reference DMA channel associated to the NAND controller
>> +  - cdns,board-delay-ps : Estimated Board delay. The value includes the 
total
>> +round trip delay for the signals and is used for deciding on values
>> +associated with data read capture. The example formula for SDR mode is
>> +the following:
>> +board delay = RE#PAD delay + PCB trace to device + PCB trace from device
>> ++ DQ PAD delay
>> +
>> +Child nodes represent the available NAND chips.
>> +
>> +Required properties of NAND chips:
>> +  - reg: shall contain the native Chip Select ids from 0 to max supported by
>> +the cadence nand flash controller
>> +
>> +
>> +See Documentation/devicetree/bindings/mtd/nand.txt for more details on
>> +generic bindings.
>> +
>> +Example:
>> +
>> +nand_controller: nand-controller @6000 {
>> +compatible = "cdns,hp-nfc";
>> +reg = <0x6000 0x1>, <0x8000 0x1>;
>> +reg-names = "reg", "sdma";
>> +clocks = <_clk>;
>> +cdns,board-delay-ps = <4830>;
>
>Are you sure you want to export this to the user? Not sure it is easily
>understandable and tunable... I'm not against but I would have troubles
>tuning it myself, unless using the documented value. Maybe you should
>explain more how to derive it?
I need to export this parameter somehow. The default value may not be
valid for other platforms. This value depends on platform, and may be different 
on different SoCs. So I think the DTS is the best place to put such 
configuration
parameter.


What about a different compatible if it depends on the SoC?

I considered it but this dealy consists of PADs delay and PCB trace
delay. PAD delays are SoC dependent. Unfortunatelly PCB delay not.
What can I do I can split it on two delays, PAD_delay and trace_delay.
Then handle PAD_delay by compatible and trace_delay by dts. But I am not
sure whether it changes anythig. Still a delay need to passed by dts.


This way you can retrieve a different driver data structure and avoid
the pain for the user.




Thanks,
Miquèl



Thanks
Piotr
 


[v6 0/2] mtd: rawnand: Add Cadence NAND controller driver

2019-09-16 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.

Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   53 +
 MAINTAINERS|7 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3036 
 5 files changed, 3104 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



[v6 1/2] mtd: rawnand: Add new Cadence NAND driver to MTD subsystem

2019-09-16 Thread Piotr Sroka
Add new Cadence NAND driver to MTD subsystem

Signed-off-by: Piotr Sroka 
---
Changes for v6:
- add support for bank addressing modified in HPNFC R013 version
- change type of data_control_supp and is_phy_type_dll from u8 to bool
- fix writing and reading data for HPNFC slave DMA interface connected 
  directly to AHB/AXI instead of external DMA engine.
- the default value of the board-delay parameter is set to other than 0 
  when it is not defined in the dts file
- put myself as maintainer of the Cadence nand driver
Changes for v5:
- fix "ecc config strength" field size
- remove unused macros
- fix address of timing2 register
- add guard for accessing data_control_size register
- simplify the driver by use the same function 
  for accessing main area and oob area
- add comment to the driver describing main controller modes
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- fix comments issues like typos, missing capitals, missing dots etc.
- remove unnecessary PHY options phy_dll_aging and phy_per_bit_deskew
- replace all register access functions to "relaxed" version
- remove all unnecessary variables initializations
- handle error inside cadence_nand_get_ecc_strength_idx function in case 
  correnction strength is not found
- add commit message
Changes for v3:
- remove definitions of unused registers
- remove configuring registers which are not expected to be configured in
  asynchronous mode
- remove not needed function reading timing registers
- remove information about oob size and write size from cdns_nand_chip type
  and use vales from mtd_info directly
- use nand_cleanup instead of nand_release if mtd device is not registered yet
- fix cadence_nand_chips_init function add garbage collection 
  if a chip init fails
- simplify PHY calculations
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines 
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 MAINTAINERS|6 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3036 
 4 files changed, 3050 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 783569e3c4b4..16e16445b88b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3579,6 +3579,12 @@ S:   Maintained
 F: Documentation/devicetree/bindings/media/cdns,*.txt
 F: drivers/media/platform/cadence/cdns-csi2*
 
+CADENCE NAND DRIVER
+M: Piotr Sroka 
+L: linux-...@lists.infradead.org
+S: Maintained
+F: drivers/mtd/nand/raw/cadence-nand-controller.c
+
 CADET FM/AM RADIO RECEIVER DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e59de3f60cf6..74fb91adeb46 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -450,6 +450,13 @@ config MTD_NAND_PLATFORM
  devices. You will need to provide platform-specific functions
  via platform_data.
 
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF || COMPILE_TEST
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
 comment "Misc"
 
 config MTD_SM_COMMON
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index a98721988e61..2d136b158fb7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_MXIC)   += mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c 
b/drivers/mtd/nand/raw/cadence-nand-controller.c
new file mode 100644
index ..87f3ad49622e
--- /dev/null
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -0,0 +1,3036 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cadence NAND flash controller d

[v6 2/2] dt-bindings: mtd: Add Cadence NAND controller driver

2019-09-16 Thread Piotr Sroka
Document the bindings used by Cadence NAND controller driver

Signed-off-by: Piotr Sroka 
Reviewed-by: Rob Herring 
---
Changes for v6:
- add documentation for address-cells and size-cells
- remove not needed space
- put myself as maintainer of the Cadence nand driver bindings
Changes for v5:
- replace "_" by "-" in all properties
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- add commit message
Changes for v3:
- add unit suffix for board_delay 
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 53 ++
 MAINTAINERS|  1 +
 2 files changed, 54 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..f3893c4d3c6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,53 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hp-nfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - #address-cells: should be 1. The cell encodes the chip select connection.
+  - #size-cells : should be 0.
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay-ps : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board delay = RE#PAD delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Child nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller@6000 {
+ compatible = "cdns,hp-nfc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay-ps = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 16e16445b88b..94d78f4e29ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3584,6 +3584,7 @@ M:Piotr Sroka 
 L: linux-...@lists.infradead.org
 S: Maintained
 F: drivers/mtd/nand/raw/cadence-nand-controller.c
+F: Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 
 CADET FM/AM RADIO RECEIVER DRIVER
 M: Hans Verkuil 
-- 
2.15.0



Re: [PATCH] - change calculating of position page containing BBM

2019-09-23 Thread Piotr Sroka

Hello

The 09/19/2019 13:33, Schrempf Frieder wrote:

EXTERNAL MAIL


On 19.09.19 15:18, Miquel Raynal wrote:

Hello,

Schrempf Frieder  wrote on Thu, 19 Sep
2019 13:15:08 +:


On 19.09.19 14:58, Miquel Raynal wrote:

Hi Piotr,

Piotr Sroka  wrote on Thu, 19 Sep 2019 13:41:35
+0100:


Change calculating of position page containing BBM

If none of BBM flags is set then function nand_bbm_get_next_page
reports EINVAL. It causes that BBM is not read at all during scanning
factory bad blocks. The result is that the BBT table is build without
checking factory BBM at all. For Micron flash memories none of this
flag is set if page size is different than 2048 bytes.


I wonder if it wouldn't be better to fix the Micron driver instead:

--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -448,6 +448,8 @@ static int micron_nand_init(struct nand_chip *chip)

  if (mtd->writesize == 2048)
  chip->options |= NAND_BBM_FIRSTPAGE |
   NAND_BBM_SECONDPAGE;
+   else
+   chip->options |= NAND_BBM_FIRSTPAGE;


That's what I forgot in my last answer to this thread, I think I only
told Piotr privately: I would like both. I think it is important to fix
the bbm_get_next_page function but for clarity, setting the FIRSTPAGE
flag in Micron's driver seems also pertinent.


Indeed, that sounds reasonable. Piotr, can you send another patch with
the diff above? And by the way: thanks for fixing my code ;)

Reviewed-by: Frieder Schrempf 


Thanks Frieder and Miquel for the very quick reply. I will send next
version containing Micron driver fix.





  ondie = micron_supports_on_die_ecc(chip);




"none of these flags are set"



This patch changes the nand_bbm_get_next_page function.


"Address this regression by changing the
nand_bbm_get_next_page_function."


It will return 0 if none of BBM flag is set and page parameter is 0.


no BBM flag is set


After that modification way of discovering factory bad blocks will work
similar as in kernel version 5.1.



Fixes + stable tags would be great!
Ok I will add fixes tag and "Cc: ". 




Signed-off-by: Piotr Sroka 
---
   drivers/mtd/nand/raw/nand_base.c | 8 ++--
   1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 5c2c30a7dffa..f64e3b6605c6 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -292,12 +292,16 @@ int nand_bbm_get_next_page(struct nand_chip *chip, int 
page)
struct mtd_info *mtd = nand_to_mtd(chip);
int last_page = ((mtd->erasesize - mtd->writesize) >>
 chip->page_shift) & chip->pagemask;
+   unsigned int bbm_flags = NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE
+   | NAND_BBM_LASTPAGE;

+   if (page == 0 && !(chip->options & bbm_flags))
+   return 0;
if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE)
return 0;
-   else if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
+   if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
return 1;
-   else if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
+   if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
return last_page;

return -EINVAL;


Lookgs good otherwise.

Thanks,
Miquèl



Thanks,
Miquèl



Thanks,
Piotr


[v2] mtd: rawnand: Change calculating of position page containing BBM

2019-09-23 Thread Piotr Sroka
Change calculating of position page containing BBM

If none of BBM flags are set then function nand_bbm_get_next_page 
reports EINVAL. It causes that BBM is not read at all during scanning
factory bad blocks. The result is that the BBT table is build without 
checking factory BBM at all. For Micron flash memories none of these 
flags are set if page size is different than 2048 bytes.

Address this regression by:
- adding NAND_BBM_FIRSTPAGE chip flag without any condition. It solves
  issue only for Micron devices.
- changing the nand_bbm_get_next_page_function. It will return 0 
  if no of BBM flag is set and page parameter is 0. After that modification
  way of discovering factory bad blocks will work similar as in kernel 
  version 5.1.

Cc: sta...@vger.kernel.org
Fixes: f90da7818b14 (mtd: rawnand: Support bad block markers in first, second 
or last page)
Signed-off-by: Piotr Sroka 
Reviewed-by: Frieder Schrempf 
---
Changes for v2:
- add fix for micron nand driver
- add fixes and stable tags
---
 drivers/mtd/nand/raw/nand_base.c   | 8 ++--
 drivers/mtd/nand/raw/nand_micron.c | 4 +++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 5c2c30a7dffa..f64e3b6605c6 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -292,12 +292,16 @@ int nand_bbm_get_next_page(struct nand_chip *chip, int 
page)
struct mtd_info *mtd = nand_to_mtd(chip);
int last_page = ((mtd->erasesize - mtd->writesize) >>
 chip->page_shift) & chip->pagemask;
+   unsigned int bbm_flags = NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE
+   | NAND_BBM_LASTPAGE;
 
+   if (page == 0 && !(chip->options & bbm_flags))
+   return 0;
if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE)
return 0;
-   else if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
+   if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
return 1;
-   else if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
+   if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
return last_page;
 
return -EINVAL;
diff --git a/drivers/mtd/nand/raw/nand_micron.c 
b/drivers/mtd/nand/raw/nand_micron.c
index 1622d3145587..913f42854563 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -438,8 +438,10 @@ static int micron_nand_init(struct nand_chip *chip)
if (ret)
goto err_free_manuf_data;
 
+   chip->options |= NAND_BBM_FIRSTPAGE;
+
if (mtd->writesize == 2048)
-   chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
+   chip->options |= NAND_BBM_SECONDPAGE;
 
ondie = micron_supports_on_die_ecc(chip);
 
-- 
2.15.0



[v8 0/2] mtd: rawnand: Add Cadence NAND controller driver

2019-09-25 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.

Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   53 +
 MAINTAINERS|7 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3036 
 5 files changed, 3104 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



Re: [v8 0/2] mtd: rawnand: Add Cadence NAND controller driver

2019-09-25 Thread Piotr Sroka

The 09/25/2019 16:52, Piotr Sroka wrote:

Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.


Please ignore that email. 


Thanks
Piotr


Re: [v7 1/2] mtd: rawnand: Add new Cadence NAND driver to MTD subsystem (fwd)

2019-09-25 Thread Piotr Sroka

Hi Miquel

Sure I will do it this week.

Thanks
Piotr

The 09/25/2019 10:17, Miquel Raynal wrote:

EXTERNAL MAIL


Hi Piotr,

Can you fix the below issue reported by Julia? Either convert the
structure parameter to a signed parameter or use an intermediate
variable.

Thanks,
Miquèl

Julia Lawall  wrote on Wed, 18 Sep 2019 21:04:37
+0200 (CEST):


-- Forwarded message --
Date: Wed, 18 Sep 2019 23:17:29 +0800
From: kbuild test robot 
To: kbu...@01.org
Cc: Julia Lawall 
Subject: Re: [v7 1/2] mtd: rawnand: Add new Cadence NAND driver to MTD subsystem

CC: kbuild-...@01.org
In-Reply-To: <20190918123115.30510-1-pio...@cadence.com>
References: <20190918123115.30510-1-pio...@cadence.com>
TO: Piotr Sroka 
CC: Kazuhiro Kasai , Piotr Sroka , Miquel Raynal , Richard Weinberger , David Woodhouse 
, Brian Norris , Marek Vasut , Vignesh Raghavendra , Mauro Carvalho Chehab , 
"David S. Miller" , Greg Kroah-Hartman , Linus Walleij , Nicolas Ferre , "Paul E. 
McKenney" , Boris Brezillon , Thomas Gleixner , Paul Cercueil , Arnd Bergmann , 
Marcel Ziswiler , Liang Yang , Anders Roxell , linux-kernel@vger.kernel.org, linux-...@lists.infradead.org

Hi Piotr,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[cannot apply to v5.3 next-20190917]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_0day-2Dci_linux_commits_Piotr-2DSroka_mtd-2Drawnand-2DAdd-2Dnew-2DCadence-2DNAND-2Ddriver-2Dto-2DMTD-2Dsubsystem_20190918-2D204505=DwIFaQ=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY=TGZtNfZu5Cjhu2K8A0Qhsot4HlKpSJ0Xmyc_L8hPwSI=mgwNQ1SA26JWmty5PuDLavsJlIOFJvmPqnwJa6yPWMA=NawctdULcP90SHk2dQOe0pKiQerhjWFPA6n5lT8EFxY=
:: branch date: 3 hours ago
:: commit date: 3 hours ago

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot 
Reported-by: Julia Lawall 

>> drivers/mtd/nand/raw/cadence-nand-controller.c:2644:5-28: WARNING: Unsigned 
expression compared with zero: cdns_chip -> corr_str_idx < 0

# 
https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_0day-2Dci_linux_commit_3235ae79d58b8d95b44d5d3773f59065f04d4f00=DwIFaQ=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY=TGZtNfZu5Cjhu2K8A0Qhsot4HlKpSJ0Xmyc_L8hPwSI=mgwNQ1SA26JWmty5PuDLavsJlIOFJvmPqnwJa6yPWMA=Mx7SXvJoMz9s4OjGbntC5eTU-djHxf6cpfehouD_uFI=
git remote add linux-review 
https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_0day-2Dci_linux=DwIFaQ=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY=TGZtNfZu5Cjhu2K8A0Qhsot4HlKpSJ0Xmyc_L8hPwSI=mgwNQ1SA26JWmty5PuDLavsJlIOFJvmPqnwJa6yPWMA=aKS20tAkXcvBbq1SBp9yJSghFIfIuFqSNAL_Fq5uCI4=
git remote update linux-review
git checkout 3235ae79d58b8d95b44d5d3773f59065f04d4f00
vim +2644 drivers/mtd/nand/raw/cadence-nand-controller.c

3235ae79d58b8d Piotr Sroka 2019-09-18  2584
3235ae79d58b8d Piotr Sroka 2019-09-18  2585  int 
cadence_nand_attach_chip(struct nand_chip *chip)
3235ae79d58b8d Piotr Sroka 2019-09-18  2586  {
3235ae79d58b8d Piotr Sroka 2019-09-18  2587 struct cdns_nand_ctrl *cdns_ctrl = 
to_cdns_nand_ctrl(chip->controller);
3235ae79d58b8d Piotr Sroka 2019-09-18  2588 struct cdns_nand_chip 
*cdns_chip = to_cdns_nand_chip(chip);
3235ae79d58b8d Piotr Sroka 2019-09-18  2589 u32 ecc_size = 
cdns_chip->sector_count * chip->ecc.bytes;
3235ae79d58b8d Piotr Sroka 2019-09-18  2590 struct mtd_info *mtd = 
nand_to_mtd(chip);
3235ae79d58b8d Piotr Sroka 2019-09-18  2591 u32 max_oob_data_size;
3235ae79d58b8d Piotr Sroka 2019-09-18  2592 int ret;
3235ae79d58b8d Piotr Sroka 2019-09-18  2593
3235ae79d58b8d Piotr Sroka 2019-09-18  2594 if (chip->options & 
NAND_BUSWIDTH_16) {
3235ae79d58b8d Piotr Sroka 2019-09-18  2595 ret = 
cadence_nand_set_access_width16(cdns_ctrl, true);
3235ae79d58b8d Piotr Sroka 2019-09-18  2596 if (ret)
3235ae79d58b8d Piotr Sroka 2019-09-18  2597     goto free_buf;
3235ae79d58b8d Piotr Sroka 2019-09-18  2598 }
3235ae79d58b8d Piotr Sroka 2019-09-18  2599
3235ae79d58b8d Piotr Sroka 2019-09-18  2600     chip->bbt_options |= 
NAND_BBT_USE_FLASH;
3235ae79d58b8d Piotr Sroka 2019-09-18  2601     chip->bbt_options |= 
NAND_BBT_NO_OOB;
3235ae79d58b8d Piotr Sroka 2019-09-18  2602 chip->ecc.mode = NAND_ECC_HW;
3235ae79d58b8d Piotr Sroka 2019-09-18  2603
3235ae79d58b8d Piotr Sroka 2019-09-18  2604     chip->options |= 
NAND_NO_SUBPAGE_WRITE;
3235ae79d58b8d Piotr Sroka 2019-09-18  2605
3235ae79d58b8d Piotr Sroka 2019-09-18  2606 cdns_chip->bbm_offs = 
chip->badblockpos;
3235ae79d58b8d Piotr Sroka 2019-09-18  2607 if (chip->options & 
NAND_BUSWIDTH_16) {
3235ae79d58b8d Piotr Sroka 2019-09-18  2608 cdns_chip->bbm_offs &= 
~0x01;
3235ae79d58b8d Piotr Sroka 2019-09-18  2609 cdns_chip->bbm_len = 2;
3235ae79d58b8d Piotr Sroka 2019-09-1

[v8 0/2] mtd: rawnand: Add Cadence NAND controller driver

2019-09-26 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.

Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   53 +
 MAINTAINERS|7 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3031 
 5 files changed, 3099 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



[v8 2/2] dt-bindings: mtd: Add Cadence NAND controller driver

2019-09-26 Thread Piotr Sroka
Document the bindings used by Cadence NAND controller driver

Signed-off-by: Piotr Sroka 
Reviewed-by: Rob Herring 
---
Changes for v8:
- none
Changes for v7:
- none
Changes for v6:
- add documentation for address-cells and size-cells
- remove not needed space
- put myself as maintainer of the Cadence nand driver bindings
Changes for v5:
- replace "_" by "-" in all properties
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- add commit message
Changes for v3:
- add unit suffix for board_delay 
- move child description to proper place
- remove prefix cadence_ for reg and sdma fields
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
---
 .../bindings/mtd/cadence-nand-controller.txt   | 53 ++
 MAINTAINERS|  1 +
 2 files changed, 54 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..f3893c4d3c6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,53 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hp-nfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "reg" and "sdma"
+  - #address-cells: should be 1. The cell encodes the chip select connection.
+  - #size-cells : should be 0.
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay-ps : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board delay = RE#PAD delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Child nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller@6000 {
+ compatible = "cdns,hp-nfc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "reg", "sdma";
+ clocks = <_clk>;
+ cdns,board-delay-ps = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 16e16445b88b..94d78f4e29ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3584,6 +3584,7 @@ M:Piotr Sroka 
 L: linux-...@lists.infradead.org
 S: Maintained
 F: drivers/mtd/nand/raw/cadence-nand-controller.c
+F: Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 
 CADET FM/AM RADIO RECEIVER DRIVER
 M: Hans Verkuil 
-- 
2.15.0



[v8 1/2] mtd: rawnand: Add new Cadence NAND driver to MTD subsystem

2019-09-26 Thread Piotr Sroka
Add new Cadence NAND driver to MTD subsystem

Signed-off-by: Piotr Sroka 
Reported-by: kbuild test robot 
Reported-by: Julia Lawall 
---
Changes for v8:
- fix compilation waring in cadence_nand_attach_chip function
- change reallocating DMA common buffer to be done after all chips are
  attached.
Changes for v7:
- replace readls with ioread32_rep and writesl with iowrite32_rep
 to avoid compilation errors on parisc architecture
Changes for v6:
- add support for bank addressing modified in HPNFC R013 version
- change type of data_control_supp and is_phy_type_dll from u8 to bool
- fix writing and reading data for HPNFC slave DMA interface connected 
  directly to AHB/AXI instead of external DMA engine.
- the default value of the board-delay parameter is set to other than 0 
  when it is not defined in the dts file
- put myself as maintainer of the Cadence nand driver
Changes for v5:
- fix "ecc config strength" field size
- remove unused macros
- fix address of timing2 register
- add guard for accessing data_control_size register
- simplify the driver by use the same function 
  for accessing main area and oob area
- add comment to the driver describing main controller modes
- change compatible name from cdns,hpnfc to cdns,hp-nfc
Changes for v4:
- fix comments issues like typos, missing capitals, missing dots etc.
- remove unnecessary PHY options phy_dll_aging and phy_per_bit_deskew
- replace all register access functions to "relaxed" version
- remove all unnecessary variables initializations
- handle error inside cadence_nand_get_ecc_strength_idx function in case 
  correnction strength is not found
- add commit message
Changes for v3:
- remove definitions of unused registers
- remove configuring registers which are not expected to be configured in
  asynchronous mode
- remove not needed function reading timing registers
- remove information about oob size and write size from cdns_nand_chip type
  and use vales from mtd_info directly
- use nand_cleanup instead of nand_release if mtd device is not registered yet
- fix cadence_nand_chips_init function add garbage collection 
  if a chip init fails
- simplify PHY calculations
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines 
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 MAINTAINERS|6 +
 drivers/mtd/nand/raw/Kconfig   |7 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3031 
 4 files changed, 3045 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 783569e3c4b4..16e16445b88b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3579,6 +3579,12 @@ S:   Maintained
 F: Documentation/devicetree/bindings/media/cdns,*.txt
 F: drivers/media/platform/cadence/cdns-csi2*
 
+CADENCE NAND DRIVER
+M: Piotr Sroka 
+L: linux-...@lists.infradead.org
+S: Maintained
+F: drivers/mtd/nand/raw/cadence-nand-controller.c
+
 CADET FM/AM RADIO RECEIVER DRIVER
 M: Hans Verkuil 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e59de3f60cf6..74fb91adeb46 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -450,6 +450,13 @@ config MTD_NAND_PLATFORM
  devices. You will need to provide platform-specific functions
  via platform_data.
 
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF || COMPILE_TEST
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
 comment "Misc"
 
 config MTD_SM_COMMON
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index a98721988e61..2d136b158fb7 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_MXIC)   += mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_id

Re: [PATCH v2 1/2] mtd: nand: Add Cadence NAND controller driver

2019-07-01 Thread Piotr Sroka

The 06/27/2019 18:15, Miquel Raynal wrote:

EXTERNAL MAIL


Hi Piotr,

Piotr Sroka  wrote on Thu, 6 Jun 2019 16:19:51
+0100:


Hi Miquel


The 05/12/2019 14:24, Miquel Raynal wrote:
>EXTERNAL MAIL
>
>
>EXTERNAL MAIL
>
>
>Hi Piotr,
>
>Sorry for de delay.
>
>Piotr Sroka  wrote on Thu, 21 Mar 2019 09:33:58
>+:
>
>> The 03/05/2019 19:09, Miquel Raynal wrote:
>> >EXTERNAL MAIL
>> >
>> >
>> >Hi Piotr,
>> >
>> >Piotr Sroka  wrote on Tue, 19 Feb 2019 16:18:23
>> >+:
>> >
>> >> This patch adds driver for Cadence HPNFC NAND controller.
>> >>
>> >> Signed-off-by: Piotr Sroka 
>> >> ---
>> >> Changes for v2:
>> >> - create one universal wait function for all events instead of one
>> >>   function per event.
>> >> - split one big function executing nand operations to separate
>> >>   functions one per each type of operation.
>> >> - add erase atomic operation to nand operation parser
>> >> - remove unnecessary includes.
>> >> - remove unused register defines
>> >> - add support for multiple nand chips
>> >> - remove all code using legacy functions
>> >> - remove chip dependents parameters from dts bindings, they were
>> >>   attached to the SoC specific compatible at the driver level
>> >> - simplify interrupt handling
>> >> - simplify timing calculations
>> >> - fix calculation of maximum supported cs signals
>> >> - simplify ecc size calculation
>> >> - remove header file and put whole code to one c file
>> >> ---
>> >>  drivers/mtd/nand/raw/Kconfig   |8 +
>> >>  drivers/mtd/nand/raw/Makefile  |1 +
>> >>  drivers/mtd/nand/raw/cadence-nand-controller.c | 3288 

>> >
>> >This driver is way too massive, I am pretty sure it can shrink a
>> >little bit more.
>> >[...]
>> >
>> I will try to make it shorer but it will be difucult to achive. It is 
because - there are a lot of calculation needed for PHY  - ECC are interleaved 
with data (like on marvell-nand or gpmi-nand).
>>Therefore:+ RAW mode is complicated+ protecting BBM increases 
number of lines of source code
>> - need to support two DMA engines internal and external (slave) We will see 
on next patch version what is the result.  That page layout looks:
>
>Maybe you don't need to support both internal and external DMA?
>
>I am pretty sure there are rooms for size reduction.

I describe how it works in general and maybe you help me chose better solution.

HW controller can work in 3 modes. PIO - can work in master or slave DMA
CDMA - needs Master DMA for accessing command descriptors.
Generic mode - can use only Slave DMA.

Generic mode is neccessery to implement functions other than page
program, page read, block erase. So it is essential. I cannot avoid
to use Slave DMA.


This deserves a nice comment at the top.
Ok I will add the modes description to cover letter. 




I change CDMA mode to PIO mode. Then I can use only slave DMA. But CDMA has a 
feature which is not present in PIO mode. The feature
gives possibility to point DMA engine two buffers to transfer. It is
used to point data buffer and oob bufer. In PIO mode I would need to
copy data buffer and oob buffer to third buffer. Next transfer data from
third buffer.
In that solution we need to copy all data by CPU and then use DMA.  Controller 
needs always transfer oob because of HW ECC restrictions. Such change will 
decrease performce for all data transfers.
I think performance is more important in that case. What is your
opinion? [...]


Indeed


>> >
>> >What is this for?
>> Fucntions enables/disables hardware detection of erased data
>> pages. >
>
>Ok, the name is not very explicit , maybe you could tell this with a
>comment.
>
Ok.

>> >> +
>> >> +/* hardware initialization */
>> >> +static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
>> >> +{
>> >> + int status = 0;
>> >> + u32 reg;
>> >> +
>> >> + status = cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS,
>> >> +  100,
>> >> +  CTRL_STATUS_INIT_COMP, false);
>> >> + if (status)
>> >> + return status;
>> >> +
>> >> + reg = readl(cdns_ctrl->reg + CTRL_VERSION);
>> >> +
>> >> + dev_info(cdns_ctrl->dev,
>&

Re: [PATCH v2 1/2] mtd: nand: Add Cadence NAND controller driver

2019-07-01 Thread Piotr Sroka

The 07/01/2019 12:04, Miquel Raynal wrote:

EXTERNAL MAIL


Hi Piotr,

Piotr Sroka  wrote on Mon, 1 Jul 2019 10:51:45
+0100:


[...]

>> >> >
>> >> >This driver is way too massive, I am pretty sure it can shrink a
>> >> >little bit more.
>> >> >[...]
>> >> >
>> >> I will try to make it shorer but it will be difucult to achive. It is 
because - there are a lot of calculation needed for PHY  - ECC are interleaved with 
data (like on marvell-nand or gpmi-nand).
>> >>Therefore:+ RAW mode is complicated+ protecting BBM increases 
number of lines of source code
>> >> - need to support two DMA engines internal and external (slave) We will 
see on next patch version what is the result.  That page layout looks:
>> >
>> >Maybe you don't need to support both internal and external DMA?
>> >
>> >I am pretty sure there are rooms for size reduction.
>>
>> I describe how it works in general and maybe you help me chose better 
solution.
>>
>> HW controller can work in 3 modes. PIO - can work in master or slave DMA
>> CDMA - needs Master DMA for accessing command descriptors.
>> Generic mode - can use only Slave DMA.
>>
>> Generic mode is neccessery to implement functions other than page
>> program, page read, block erase. So it is essential. I cannot avoid
>> to use Slave DMA.
>
>This deserves a nice comment at the top.
Ok I will add the modes description to cover letter. >


Not only to the cover letter: People read the code. Interested people
might also read the commit log which is quite easy to find. The cover
letter however will just disappear in the history of the Internet. I
would rather prefer you explain how the IP works at the top of the
driver.
So I will add the modes description to both cover letter and 
at the top of the driver. 



Thanks,
Miquèl


Thanks,
Piotr 


Re: [PATCH v2 1/2] mtd: nand: Add Cadence NAND controller driver

2019-06-06 Thread Piotr Sroka

Hi Miquel


The 05/12/2019 14:24, Miquel Raynal wrote:

EXTERNAL MAIL


EXTERNAL MAIL


Hi Piotr,

Sorry for de delay.

Piotr Sroka  wrote on Thu, 21 Mar 2019 09:33:58
+:


The 03/05/2019 19:09, Miquel Raynal wrote:
>EXTERNAL MAIL
>
>
>Hi Piotr,
>
>Piotr Sroka  wrote on Tue, 19 Feb 2019 16:18:23
>+:
>
>> This patch adds driver for Cadence HPNFC NAND controller.
>>
>> Signed-off-by: Piotr Sroka 
>> ---
>> Changes for v2:
>> - create one universal wait function for all events instead of one
>>   function per event.
>> - split one big function executing nand operations to separate
>>   functions one per each type of operation.
>> - add erase atomic operation to nand operation parser
>> - remove unnecessary includes.
>> - remove unused register defines
>> - add support for multiple nand chips
>> - remove all code using legacy functions
>> - remove chip dependents parameters from dts bindings, they were
>>   attached to the SoC specific compatible at the driver level
>> - simplify interrupt handling
>> - simplify timing calculations
>> - fix calculation of maximum supported cs signals
>> - simplify ecc size calculation
>> - remove header file and put whole code to one c file
>> ---
>>  drivers/mtd/nand/raw/Kconfig   |8 +
>>  drivers/mtd/nand/raw/Makefile  |1 +
>>  drivers/mtd/nand/raw/cadence-nand-controller.c | 3288 

>
>This driver is way too massive, I am pretty sure it can shrink a
>little bit more.
>[...]
>
I will try to make it shorer but it will be difucult to achive. It is because - 
there are a lot of calculation needed for PHY  - ECC are interleaved with 
data (like on marvell-nand or gpmi-nand).
   Therefore:+ RAW mode is complicated+ protecting BBM increases number 
of lines of source code
- need to support two DMA engines internal and external (slave) We will see on 
next patch version what is the result.  That page layout looks:


Maybe you don't need to support both internal and external DMA?

I am pretty sure there are rooms for size reduction.


I describe how it works in general and maybe you help me chose better solution.

HW controller can work in 3 modes. 
PIO - can work in master or slave DMA

CDMA - needs Master DMA for accessing command descriptors.
Generic mode - can use only Slave DMA.

Generic mode is neccessery to implement functions other than page
program, page read, block erase. So it is essential. I cannot avoid
to use Slave DMA.

I change CDMA mode to PIO mode. Then I can use only slave DMA. 
But CDMA has a feature which is not present in PIO mode. The feature

gives possibility to point DMA engine two buffers to transfer. It is
used to point data buffer and oob bufer. In PIO mode I would need to
copy data buffer and oob buffer to third buffer. Next transfer data from
third buffer.
In that solution we need to copy all data by CPU and then use DMA.  
Controller needs always transfer oob because of HW ECC restrictions. 
Such change will decrease performce for all data transfers.

I think performance is more important in that case. What is your
opinion? 


[...]

>
>What is this for?
Fucntions enables/disables hardware detection of erased data
pages. >


Ok, the name is not very explicit , maybe you could tell this with a
comment.


Ok.


>> +
>> +/* hardware initialization */
>> +static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
>> +{
>> +  int status = 0;
>> +  u32 reg;
>> +
>> +  status = cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS,
>> +   100,
>> +   CTRL_STATUS_INIT_COMP, false);
>> +  if (status)
>> +  return status;
>> +
>> +  reg = readl(cdns_ctrl->reg + CTRL_VERSION);
>> +
>> +  dev_info(cdns_ctrl->dev,
>> +   "%s: cadence nand controller version reg %x\n",
>> +   __func__, reg);
>> +
>> +  /* disable cache and multiplane */
>> +  writel(0, cdns_ctrl->reg + MULTIPLANE_CFG);
>> +  writel(0, cdns_ctrl->reg + CACHE_CFG);
>> +
>> +  /* clear all interrupts */
>> +  writel(0x, cdns_ctrl->reg + INTR_STATUS);
>> +
>> +  cadence_nand_get_caps(cdns_ctrl);
>> +  cadence_nand_read_bch_cfg(cdns_ctrl);
>
>No, you cannot rely on the bootloader's configuration. And I suppose
>this is what the first call to read_bch_cfg does?
I do not realy on boot loader. Just read NAND flash
controller configuration from read only capabilities registers.


Ok, if these are RO registers, it's fine. But maybe don't call t

Re: [PATCH 2/2] dt-bindings: nand: Add Cadence NAND controller driver

2019-02-05 Thread Piotr Sroka

The 01/29/2019 18:21, Boris Brezillon wrote:
 

+Optional properties:
+Driver calculates controller timings base on NAND flash memory timings and
+the following delays in picoseconds.
+  - cdns,if-skew : Skew value of the output signals of the NAND Flash interface
+  - cdns,nand2-delay : Delay value of one NAND2 gate from which
+the delay element is build
+  - cdns,board-delay : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board_delay = RE#PAD_delay + PCB trace to device + PCB trace from device
++ DQ PAD delay


The unit of those props is not defined, and if possible I'd like to
avoid specifying custom timing adjustment values in the DT. Looks like
some of these values are SoC specific (depends on the integration of
this IP in a SoC) and others are board specific. For SoC specific
values, this should be attached to the SoC specific compatible at the
driver level. For board-specific values, I'd prefer to have a generic
way to describe boards constraints.

Moving SoC specific delays from DTS to the driver data is clear for me. I do 
not know how to handle a board delay. Could you give me an example how it may 
be implemented? Where this board related stuff could be placed?

--
--
Regards
Piotr Sroka


[PATCH 0/2] mtd: nand: Add Cadence NAND controller driver

2019-01-29 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.


Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  dt-bindings: nand: Add Cadence NAND driver

 .../devicetree/bindings/mtd/cadence-nand.txt   |   35 +
 drivers/mtd/nand/raw/Kconfig   |8 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence_nand.c| 2655 
 drivers/mtd/nand/raw/cadence_nand.h|  631 +
 5 files changed, 3330 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/cadence-nand.txt
 create mode 100644 drivers/mtd/nand/raw/cadence_nand.c
 create mode 100644 drivers/mtd/nand/raw/cadence_nand.h

-- 
2.15.0



[PATCH 1/2] mtd: nand: Add Cadence NAND controller driver

2019-01-29 Thread Piotr Sroka
This patch adds driver for Cadence HPNFC NAND controller.

Signed-off-by: Piotr Sroka 
---
 drivers/mtd/nand/raw/Kconfig|8 +
 drivers/mtd/nand/raw/Makefile   |1 +
 drivers/mtd/nand/raw/cadence_nand.c | 2655 +++
 drivers/mtd/nand/raw/cadence_nand.h |  631 +
 4 files changed, 3295 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence_nand.c
 create mode 100644 drivers/mtd/nand/raw/cadence_nand.h

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 1a55d3e3d4c5..742dcc947203 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -541,4 +541,12 @@ config MTD_NAND_TEGRA
  is supported. Extra OOB bytes when using HW ECC are currently
  not supported.
 
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 57159b349054..9c1301164996 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND)   += brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence_nand.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence_nand.c 
b/drivers/mtd/nand/raw/cadence_nand.c
new file mode 100644
index ..c941e702d325
--- /dev/null
+++ b/drivers/mtd/nand/raw/cadence_nand.c
@@ -0,0 +1,2655 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cadence NAND flash controller driver
+ *
+ * Copyright (C) 2019 Cadence
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "cadence_nand.h"
+
+MODULE_LICENSE("GPL v2");
+#define CADENCE_NAND_NAME"cadence_nand"
+
+#define MAX_OOB_SIZE_PER_SECTOR32
+#define MAX_ADDRESS_CYC6
+#define MAX_DATA_SIZE  0xFFFC
+
+static int cadence_nand_wait_for_thread(struct cdns_nand_info *cdns_nand,
+   int8_t thread);
+static int cadence_nand_wait_for_idle(struct cdns_nand_info *cdns_nand);
+static int cadence_nand_cmd(struct nand_chip *chip,
+   const struct nand_subop *subop);
+static int cadence_nand_waitrdy(struct nand_chip *chip,
+   const struct nand_subop *subop);
+
+static const struct nand_op_parser cadence_nand_op_parser = NAND_OP_PARSER(
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_cmd,
+   NAND_OP_PARSER_PAT_CMD_ELEM(false)),
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_cmd,
+   NAND_OP_PARSER_PAT_ADDR_ELEM(false, MAX_ADDRESS_CYC)),
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_cmd,
+   NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, MAX_DATA_SIZE)),
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_cmd,
+   NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, MAX_DATA_SIZE)),
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_waitrdy,
+   NAND_OP_PARSER_PAT_WAITRDY_ELEM(false))
+   );
+
+static inline struct cdns_nand_info *mtd_cdns_nand_info(struct mtd_info *mtd)
+{
+   return container_of(mtd_to_nand(mtd), struct cdns_nand_info, chip);
+}
+
+static inline struct
+cdns_nand_info *chip_to_cdns_nand_info(struct nand_chip *chip)
+{
+   return container_of(chip, struct cdns_nand_info, chip);
+}
+
+static inline bool
+cadence_nand_dma_buf_ok(struct cdns_nand_info *cdns_nand, const void *buf,
+   u32 buf_len)
+{
+   u8 data_dma_width = cdns_nand->caps.data_dma_width;
+
+   return buf && virt_addr_valid(buf) &&
+   likely(IS_ALIGNED((uintptr_t)buf, data_dma_width)) &&
+   likely(IS_ALIGNED(buf_len, data_dma_width));
+}
+
+static int cadence_nand_set_ecc_enable(struct cdns_nand_info *cdns_nand,
+  bool enable)
+{
+   u32 reg;
+
+   if (cadence_nand_wait_for_idle(cdns_nand)) {
+   dev_err(cdns_nand->dev, "Error. Controller is busy");
+   return -ETIMEDOUT;
+   }
+
+   reg = readl(cdns_nand->reg + ECC_CONFIG_0);
+
+   if (enable)
+   reg |= ECC_CONFIG_0_ECC_EN;
+   else
+   reg &= ~ECC_CONFIG_0_ECC_EN;
+
+   writel(reg, cdns_nand->reg + ECC_CONFIG_0);
+
+   return 0;
+}
+
+static int cadence_nand_set_ecc_strength(struct cdns_nand

[PATCH 2/2] dt-bindings: nand: Add Cadence NAND controller driver

2019-01-29 Thread Piotr Sroka
Signed-off-by: Piotr Sroka 
---
 .../devicetree/bindings/mtd/cadence-nand.txt   | 35 ++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/cadence-nand.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand.txt
new file mode 100644
index ..82afa34d5652
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand.txt
@@ -0,0 +1,35 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hpnfc-nand"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+
+Optional properties:
+Driver calculates controller timings base on NAND flash memory timings and
+the following delays in picoseconds.
+  - cdns,if-skew : Skew value of the output signals of the NAND Flash interface
+  - cdns,nand2-delay : Delay value of one NAND2 gate from which
+the delay element is build
+  - cdns,board-delay : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board_delay = RE#PAD_delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+Example
+
+nand: nand@6000 {
+ compatible = "cdns,hpnfc-nand";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ clocks = <_clk>;
+ cdns,if-skew = <50>;
+ cdns,nand2-delay = <37>;
+ cdns,board-delay = <4830>;
+ interrupts = <2 0>;
+};
-- 
2.15.0



Re: [PATCH 1/2] mtd: nand: Add Cadence NAND controller driver

2019-02-07 Thread Piotr Sroka

Hi Boris

The 01/29/2019 19:19, Boris Brezillon wrote:



+   NAND_OP_PARSER_PAT_ADDR_ELEM(false, MAX_ADDRESS_CYC)),
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_cmd,
+   NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, MAX_DATA_SIZE)),
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_cmd,
+   NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, MAX_DATA_SIZE)),
+   NAND_OP_PARSER_PATTERN(
+   cadence_nand_waitrdy,
+   NAND_OP_PARSER_PAT_WAITRDY_ELEM(false))
+   );


Are you sure you can't pack several instructions into an atomic
controller operation? I'd be surprised if that was not the case...

All write and reads operations are handled by function pointers. Apart from 
that I
could handle erase command as a atomic operation. I will add such function to
the parser. 




+static int cadence_nand_set_ecc_strength(struct cdns_nand_info *cdns_nand,
+u8 strength)
+{
+   u32 reg;
+   u8 i, corr_str_idx = 0;
+
+   if (cadence_nand_wait_for_idle(cdns_nand)) {
+   dev_err(cdns_nand->dev, "Error. Controller is busy");
+   return -ETIMEDOUT;
+   }
+
+   for (i = 0; i < BCH_MAX_NUM_CORR_CAPS; i++) {
+   if (cdns_nand->ecc_strengths[i] == strength) {
+   corr_str_idx = i;
+   break;
+   }
+   }


The index should be retrieved at init time and stored somewhere to avoid
searching it every time this function is called.


Function is called only once at initilization stage. Do we need to make
a optimalization in succh case?  

+
+   reg = readl(cdns_nand->reg + ECC_CONFIG_0);
+   reg &= ~ECC_CONFIG_0_CORR_STR;
+   reg |= FIELD_PREP(ECC_CONFIG_0_CORR_STR, corr_str_idx);
+   writel(reg, cdns_nand->reg + ECC_CONFIG_0);
+
+   return 0;
+}
+


...


+
+static int cadence_nand_set_erase_detection(struct cdns_nand_info *cdns_nand,
+   bool enable,
+   u8 bitflips_threshold)
+{
+   u32 reg;
+
+   if (cadence_nand_wait_for_idle(cdns_nand)) {
+   dev_err(cdns_nand->dev, "Error. Controller is busy");
+   return -ETIMEDOUT;
+   }
+
+   reg = readl(cdns_nand->reg + ECC_CONFIG_0);
+
+   if (enable)
+   reg |= ECC_CONFIG_0_ERASE_DET_EN;
+   else
+   reg &= ~ECC_CONFIG_0_ERASE_DET_EN;
+
+   writel(reg, cdns_nand->reg + ECC_CONFIG_0);
+
+   writel(bitflips_threshold, cdns_nand->reg + ECC_CONFIG_1);


I'm curious, is the threshold defining the max number of bitflips in a
page or in an ECC-chunk (ecc_step_size)?
Threshold defines number of max bitflips in a sector/ecc_step_size. 



+static void
+cadence_nand_irq_cleanup(int irqnum, struct cdns_nand_info *cdns_nand)
+{
+   /* disable interrupts */
+   writel(INTR_ENABLE_INTR_EN, cdns_nand->reg + INTR_ENABLE);
+   free_irq(irqnum, cdns_nand);


You don't need that if you use devm_request_irq(), do you?

I agree I do not need it I forgot to remove it.



+
+static int cadence_nand_calc_ecc_bytes_256(int step_size, int strength)
+{
+   return cadence_nand_calc_ecc_bytes(256, strength);
+}
+
+static int cadence_nand_calc_ecc_bytes_512(int step_size, int strength)
+{
+   return cadence_nand_calc_ecc_bytes(512, strength);
+}
+
+static int cadence_nand_calc_ecc_bytes_1024(int step_size, int strength)
+{
+   return cadence_nand_calc_ecc_bytes(1024, strength);
+}
+
+static int cadence_nand_calc_ecc_bytes_2048(int step_size, int strength)
+{
+   return  cadence_nand_calc_ecc_bytes(2048, strength);
+}
+
+static int cadence_nand_calc_ecc_bytes_4096(int step_size, int strength)
+{
+   return  cadence_nand_calc_ecc_bytes(4096, strength);
+}


And you absolutely don't need those wrappers, just use
cadence_nand_calc_ecc_bytes() directly.

Unfortunately I need these  wrappers. It is because size of ecc 
does not depend on selected step_size which is on parameter list but it

depends on maximum supported ecc step size which is not avaible in this
function. Lets say that controller supports the following steps sizes
512, 1024, 2048. No matter what step size is set the calculation will be
made always for step size 2048. 
I could use such function directly if it contains nand_chip
parameter. Then I could get this parameter from cdns_nand.  


I'm stopping here, but I think you got the idea: there's a lot of
duplicated code in this driver, try to factor this out or simplify the
logic.

Thans for review. I will try to simplify the rest of code by myself.


Regards,

Piotr Sroka



Re: [PATCH v2 1/2] mtd: nand: Add Cadence NAND controller driver

2019-03-21 Thread Piotr Sroka

The 03/05/2019 19:09, Miquel Raynal wrote:

EXTERNAL MAIL


Hi Piotr,

Piotr Sroka  wrote on Tue, 19 Feb 2019 16:18:23
+:


This patch adds driver for Cadence HPNFC NAND controller.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 drivers/mtd/nand/raw/Kconfig   |8 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3288 


This driver is way too massive, I am pretty sure it can shrink a
little bit more.
[...]

I will try to make it shorer but it will be difucult to achive. It is because 
- there are a lot of calculation needed for PHY  
- ECC are interleaved with data (like on marvell-nand or gpmi-nand).
  Therefore: 
  + RAW mode is complicated 
  + protecting BBM increases number of lines of source code
- need to support two DMA engines internal and external (slave) 
We will see on next patch version what is the result.  
   
That page layout looks:


 +-
 | Data 1 | ECC 1 | ... | Data N  | ECC N |  
 +-


  --+
   Last Data | OOB bytes | Last ECC |
  --+
	/\ 
	|| 
   OOB area started

usualy vendor specified BBM

Flash OOB area starts somewhere in last data sector. 
Flash OOB area contains part of last sector, oob data 
(accessible by driver), and last ECC code   


+
+struct cdns_nand_chip {
+   struct cadence_nand_timings timings;
+   struct nand_chip chip;
+   u8 nsels;
+   struct list_head node;
+
+   /*
+* part of oob area of NANF flash memory page.
+* This part is available for user to read or write.
+*/
+   u32 avail_oob_size;
+   /* oob area size of NANF flash memory page */
+   u32 oob_size;
+   /* main area size of NANF flash memory page */
+   u32 main_size;


These fields are redundant and exist in mtd_info/nand_chip.


Ok I will use the parameters from mtd_info.

+
+   /* sector size few sectors are located on main area of NF memory page */
+   u32 sector_size;
+   u32 sector_count;
+
+   /* offset of BBM*/
+   u8 bbm_offs;
+   /* number of bytes reserved for BBM */
+   u8 bbm_len;


Why do you bother at the controller driver level with bbm?

When ECC is enabled then BBM is somewhere in last data sector. 
So for write operation real BBM will be overwritten. For read operation
it will be read from wrong offset. To protect BBM we use HW feature 
skip bytes. To be able to properly configure this feature we need to
know what is the offset of BBM.   

+
+static int cadence_nand_set_erase_detection(struct cdns_nand_ctrl *cdns_ctrl,
+   bool enable,
+   u8 bitflips_threshold)


What is this for?

Fucntions enables/disables hardware detection of erased data
pages. 



+
+/* hardware initialization */
+static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
+{
+   int status = 0;
+   u32 reg;
+
+   status = cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS,
+100,
+CTRL_STATUS_INIT_COMP, false);
+   if (status)
+   return status;
+
+   reg = readl(cdns_ctrl->reg + CTRL_VERSION);
+
+   dev_info(cdns_ctrl->dev,
+"%s: cadence nand controller version reg %x\n",
+__func__, reg);
+
+   /* disable cache and multiplane */
+   writel(0, cdns_ctrl->reg + MULTIPLANE_CFG);
+   writel(0, cdns_ctrl->reg + CACHE_CFG);
+
+   /* clear all interrupts */
+   writel(0x, cdns_ctrl->reg + INTR_STATUS);
+
+   cadence_nand_get_caps(cdns_ctrl);
+   cadence_nand_read_bch_cfg(cdns_ctrl);


No, you cannot rely on the bootloader's configuration. And I suppose
this is what the first call to read_bch_cfg does?

I do not realy on boot loader. Just read NAND flash
controller configuration from read only capabilities registers.



+
+#define TT_OOB_AREA1
+#define TT_MAIN_OOB_AREAS  2
+#define TT_RAW_PAGE3
+#define TT_BBM  

[PATCH v2 0/2] mtd: nand: Add Cadence NAND controller driver

2019-02-19 Thread Piotr Sroka
Driver for Cadence HPNFC NAND flash controller.

HW DMA interface
Page write and page read operations are executed in Command DMA mode.
Commands are defined by DMA descriptors.
In CDMA mode controller own DMA engine is used (Master DMA mode).
Other operations defined by nand_op_instr are executed in "Generic" mode.
In that mode data can be transferred only in by Slave DMA interface.
Slave DMA interface can be connected directly to AXI or to an external
DMA engine.

HW ECC support
Cadence NAND controller supports HW BCH correction.
 ECC is transparent from SW point of view. It means that ECC codes
are calculated and written to flash. In read operation ECC codes 
are removed from user data and correction is made if necessary.

Controller data layout with ECC enabled:
 -
|Sec 1 | ECC | Sec 2 | ECC .. | Sec n | OOB (32B) | ECC | unused data |
 -

Last sector is extended by a out-bound data. Tha maximum size of
"extra data" is 32 bytes. The oob data are protected by ECC. If we need to 
read only oob data the whole last sector must be read. It is because 
oob data are part of last sector. Reading oob function always reads 
whole sector and writing oob function always writes whole last sector.
Written data are interleaved with the ECC therefore part of the 
last sector is located on oob area and the BBM is overwritten.

SKIP BYTES feature
To protect BBM the "skip byte" HW feature is used. 
Write page function copies BBM value from first byte of oob data to 
BBM offset defined by manufacturer. Read page functions always takes 
BBM from flash manufacturer offset. It causes that for not written 
pages the proper value of BBM marker is used.

ECC size calculation
Information about supported ECC steps and ECC strengths are read 
from controller registers. ECC sector size and ECC strength can be
configurable. Size of ECC depends on maximum supported sector size 
it not depends on selected sector size. Therefore there is a separate
function for calculating ECC size for each of possible 
sector size/step size.


Piotr Sroka (2):
  Add new Cadence NAND driver to MTD subsystem
  dt-bindings: nand: Add Cadence NAND controller driver

 .../bindings/mtd/cadence-nand-controller.txt   |   48 +
 drivers/mtd/nand/raw/Kconfig   |8 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3288 
 4 files changed, 3345 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

-- 
2.15.0



[PATCH v2 2/2] dt-bindings: nand: Add Cadence NAND controller driver

2019-02-19 Thread Piotr Sroka
Signed-off-by: Piotr Sroka 
---
Changes for v2:
- remove chip dependends parameters from dts bindings
- add names for register ranges in dts bindings
- add generic bindings to describe NAND chip representation
  under the NAND controller node 
---
 .../bindings/mtd/cadence-nand-controller.txt   | 48 ++
 1 file changed, 48 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt

diff --git a/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt 
b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
new file mode 100644
index ..3d9b4decae24
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
@@ -0,0 +1,48 @@
+* Cadence NAND controller
+
+Required properties:
+  - compatible : "cdns,hpnfc"
+  - reg : Contains two entries, each of which is a tuple consisting of a
+ physical address and length. The first entry is the address and
+ length of the controller register set. The second entry is the
+ address and length of the Slave DMA data port.
+  - reg-names: should contain "cadence_reg" and "cadence_sdma"
+  - interrupts : The interrupt number.
+  - clocks: phandle of the controller core clock (nf_clk).
+  - Children nodes represent the available NAND chips.
+
+Required properties of NAND chips:
+  - reg: shall contain the native Chip Select ids from 0 to max supported by
+the cadence nand flash controller
+
+Optional properties:
+  - dmas: shall reference DMA channel associated to the NAND controller
+  - cdns,board-delay : Estimated Board delay. The value includes the total
+round trip delay for the signals and is used for deciding on values
+associated with data read capture. The example formula for SDR mode is
+the following:
+board_delay = RE#PAD_delay + PCB trace to device + PCB trace from device
++ DQ PAD delay
+
+See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+generic bindings.
+
+Example:
+
+nand_controller: nand-controller @6000 {
+ compatible = "cdns,hpnfc";
+ reg = <0x6000 0x1>, <0x8000 0x1>;
+ reg-names = "cadence_reg", "cadence_sdma";
+ clocks = <_clk>;
+ cdns,board-delay = <4830>;
+ interrupts = <2 0>;
+ nand@0 {
+ reg = <0>;
+ label = "nand-1";
+ };
+ nand@1 {
+ reg = <1>;
+ label = "nand-2";
+ };
+
+};
-- 
2.15.0



[PATCH v2 1/2] mtd: nand: Add Cadence NAND controller driver

2019-02-19 Thread Piotr Sroka
This patch adds driver for Cadence HPNFC NAND controller.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- create one universal wait function for all events instead of one
  function per event.
- split one big function executing nand operations to separate
  functions one per each type of operation.
- add erase atomic operation to nand operation parser
- remove unnecessary includes.
- remove unused register defines 
- add support for multiple nand chips
- remove all code using legacy functions
- remove chip dependents parameters from dts bindings, they were
  attached to the SoC specific compatible at the driver level
- simplify interrupt handling
- simplify timing calculations
- fix calculation of maximum supported cs signals
- simplify ecc size calculation
- remove header file and put whole code to one c file
---
 drivers/mtd/nand/raw/Kconfig   |8 +
 drivers/mtd/nand/raw/Makefile  |1 +
 drivers/mtd/nand/raw/cadence-nand-controller.c | 3288 
 3 files changed, 3297 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 1a55d3e3d4c5..742dcc947203 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -541,4 +541,12 @@ config MTD_NAND_TEGRA
  is supported. Extra OOB bytes when using HW ECC are currently
  not supported.
 
+config MTD_NAND_CADENCE
+   tristate "Support Cadence NAND (HPNFC) controller"
+   depends on OF
+   help
+ Enable the driver for NAND flash on platforms using a Cadence NAND
+ controller.
+
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 57159b349054..1d5432fb65e3 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND)   += brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
+obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c 
b/drivers/mtd/nand/raw/cadence-nand-controller.c
new file mode 100644
index ..6ff023c4459b
--- /dev/null
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -0,0 +1,3288 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cadence NAND flash controller driver
+ *
+ * Copyright (C) 2019 Cadence
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_OOB_SIZE_PER_SECTOR32
+#define MAX_ADDRESS_CYC6
+#define MAX_ERASE_ADDRESS_CYC  3
+#define MAX_DATA_SIZE  0xFFFC
+
+/***/
+/*  Register definition */
+/***/
+
+/* Command register 0.
+ * Writing data to this register will initiate a new transaction
+ * of the NF controller.
+ */
+#define CMD_REG0   0x
+/* command type field mask */
+#defineCMD_REG0_CT GENMASK(31, 30)
+/* command type CDMA */
+#defineCMD_REG0_CT_CDMA0uL
+/* command type reset */
+#defineCMD_REG0_CT_RST 2uL
+/* command type generic */
+#defineCMD_REG0_CT_GEN 3uL
+/* command thread number field mask */
+#defineCMD_REG0_TN GENMASK(27, 24)
+/* command interrupt mask */
+#defineCMD_REG0_INTBIT(20)
+
+/* Command register 2 */
+#define CMD_REG2   0x0008
+/* Command register 3 */
+#define CMD_REG3   0x000C
+/* Pointer register to select which thread status will be selected. */
+#define CMD_STATUS_PTR 0x0010
+/* Command status register for selected thread */
+#define CMD_STATUS 0x0014
+
+/* interrupt status register */
+#define INTR_STATUS0x0110
+#defineINTR_STATUS_SDMA_ERRBIT(22)
+#defineINTR_STATUS_SDMA_TRIGG  BIT(21)
+#defineINTR_STATUS_UNSUPP_CMD  BIT(19)
+#defineINTR_STATUS_DDMA_TERR   BIT(18)
+#defineINTR_STATUS_CDMA_TERR   BIT(17)
+#defineINTR_STATUS_CDMA_IDLBIT(16)
+
+/* interrupt enable register */
+#define INTR_ENABLE0x0114
+#defineINTR_ENABLE_INTR_EN BIT(31)
+#defineINTR_ENABLE_SDMA_ERR_EN BIT(22)
+#defineINTR_ENABLE_SDMA_TRIGG_EN   BIT(21)
+#defineINTR_ENABLE_UNSUPP_CMD_EN   BIT(19)
+#defineINTR_ENABLE_DDMA_TERR_ENBIT(18

RE: [PATCH 1/2] [1/2] mmc: sdhci-cadence: Fix writing PHY delay

2017-02-23 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 23 February, 2017 12:29 PM
> Subject: Re: [PATCH 1/2] [1/2] mmc: sdhci-cadence: Fix writing PHY delay
> 
> Hi.
> 
> > -static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> > +static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> >  u8 addr, u8 data)
> 
> 
> If you have a chance to submit v2,
> I want the indent of the above line adjusted.
> 
Ok thanks. I will fix the indent in v2.

Regards
Piotr Sroka



RE: [v5 2/4] dt-bindings: mmc: add description of PHY delays for sdhci-cadence

2017-03-30 Thread Piotr Sroka
Hi Masahiro

2017-03-22 16:30  Masahiro Yamada :
> 2017-03-21 23:33 GMT+09:00 Piotr Sroka :
> > DTS properties are used instead of fixed data
> > because PHY settings can be different for different chips/boards.
> > Add description of new DLL PHY delays.
> >
> > Signed-off-by: Piotr Sroka 
> > ---
> > Changes for v2:
> > - file was created in v2. It was a part of driver source file patch.
> > - most delays were moved from dts file
> >   to data associated with an SoC specific compatible
> > - description of delays was updated to be more clearly
> > ---
> > Changes for v3:
> > - move all delays back to dts because they are also boards dependent
> > - prefix all of the Cadence-specific properties with cdns prefix
> > ---
> > Changes for v4:
> > - change the beginning of the commit subject
> > ---
> > Changes for v5:
> > - change name of property to be consistent with timing modes
> >   available in Linux
> 
> 
> As I gave Reviewed-by in v4 already, this looks good to me.
> 
> 
> Reviewed-by: Masahiro Yamada 
> 
> 
> As I said before,
> once you get Reviewed/Acked tags,
> please include them in your later version.
> 

Ok. I will remember next time.

-- 
Best Regards
Piotr Sroka



[v5 2/4] dt-bindings: mmc: add description of PHY delays for sdhci-cadence

2017-03-21 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.
Add description of new DLL PHY delays.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- file was created in v2. It was a part of driver source file patch.
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- description of delays was updated to be more clearly
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
---
Changes for v4:
- change the beginning of the commit subject
---
Changes for v5:
- change name of property to be consistent with timing modes 
  available in Linux
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..fa423c2 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,53 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+Some PHY delays can be configured by following properties.
+PHY DLL input delays:
+They are used to delay the data valid window, and align the window
+to sampling clock. The delay starts from 5ns (for delay parameter equal to 0)
+and it is increased by 2.5ns in each step.
+- cdns,phy-input-delay-sd-highspeed:
+  Value of the delay in the input path for SD high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-legacy:
+  Value of the delay in the input path for legacy timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr12:
+  Value of the delay in the input path for SD UHS SDR12 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr25:
+  Value of the delay in the input path for SD UHS SDR25 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr50:
+  Value of the delay in the input path for SD UHS SDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-ddr50:
+  Value of the delay in the input path for SD UHS DDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-highspeed:
+  Value of the delay in the input path for MMC high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-ddr:
+  Value of the delay in the input path for eMMC high-speed DDR timing
+  Valid range = [0:0x1F].
+
+PHY DLL clock delays:
+Each delay property represents the fraction of the clock period.
+The approximate delay value will be
+(/128)*sdmclk_clock_period.
+- cdns,phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +76,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   cdns,phy-dll-delay-sdclk = <0>;
};
-- 
2.2.2



[v5 1/4] mmc: sdhci-cadence: Fix writing PHY delay

2017-03-21 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- fix indent
---
Changes for v3:
- none
---
Changes for v4:
- none
---
Changes for v5:
- use driver version from next branch, with applied enhanced strobe feature 
support.
---
 drivers/mmc/host/sdhci-cadence.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 48f6419..83c3b55 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -68,11 +68,12 @@ struct sdhci_cdns_priv {
bool enhanced_strobe;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
-u8 addr, u8 data)
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+   u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -81,8 +82,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



[v5 4/4] mmc: sdhci-cadence: refactor probe function

2017-03-21 Thread Piotr Sroka
Use added dev variable for devm_clk_get.

Signed-off-by: Piotr Sroka 
---
Changes for v5:
- patch created in v5
---
 drivers/mmc/host/sdhci-cadence.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index c3c7090..5aa238d 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -305,7 +305,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
int ret;
struct device *dev = >dev;
 
-   clk = devm_clk_get(>dev, NULL);
+   clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk))
return PTR_ERR(clk);
 
-- 
2.2.2



[v5 3/4] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-21 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- dts part was removed from this patch
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- remove unrelated changes
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
- put checking delay properties inside the for loop
  instead of using a lot of single if expressions
---
Changes for v4:
- remove unecessary declaration of sdhci_cdns_match
- format fix (blank line removed)
---
Changes for v5:
- use driver version from next branch, with applied enhanced strobe feature 
support.
- change name of property to be consistent with timing modes 
  available in Linux
---
 drivers/mmc/host/sdhci-cadence.c | 53 ++--
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 83c3b55..c3c7090 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -55,6 +56,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -68,6 +72,25 @@ struct sdhci_cdns_priv {
bool enhanced_strobe;
 };
 
+struct sdhci_cdns_phy_cfg {
+   const char *property;
+   u8 addr;
+};
+
+static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
+   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
+   { "cdns,phy-input-delay-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
+   { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
+   { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
+   { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
+   { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
+   { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
+   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
+   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
+   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
+   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
+};
+
 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
u8 addr, u8 data)
 {
@@ -92,13 +115,26 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_init(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 val;
+   int ret, i;
+
+   for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
+   ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
+  );
+   if (ret)
+   continue;
+
+   ret = sdhci_cdns_write_phy_reg(priv,
+  sdhci_cdns_phy_cfgs[i].addr,
+  val);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
 }
 
 static inline void *sdhci_cdns_priv(struct sdhci_host *host)
@@ -267,6 +303,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
struct sdhci_cdns_priv *priv;
struct clk *clk;
int ret;
+   struct device *dev = >dev;
 
clk = devm_clk_get(>dev, NULL);
if (IS_ERR(clk))
@@ -297,7 +334,9 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
if (ret)
goto free;
 
-   sdhci_cdns_phy_init(priv);
+   ret = sdhci_cdns_phy_init(dev->of_node, priv);
+   if (ret)
+   goto free;
 
ret = sdhci_add_host(host);
if (ret)
-- 
2.2.2



RE: [v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-22 Thread Piotr Sroka
Hi Masahiro

2017-03-21 08:3 AM  Masahiro Yamada :
> Hi Piotr,
> 
> 2017-03-21 16:01 GMT+09:00 Piotr Sroka :
> >
> > Hi Masahiro
> >
> > 2017-03-21 02:46 AM Masahiro Yamada :
> >> Hi Piotr,
> >>
> >>
> >> 2017-03-20 20:20 GMT+09:00 Piotr Sroka :
> >> > DTS properties are used instead of fixed data
> >> > because PHY settings can be different for different chips/boards.
> >> >
> >> > Signed-off-by: Piotr Sroka 
> >>
> >>
> >> I found this version is a problem for me.
> >>
> >>
> >> > +
> >> > +static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
> >> > +   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, 
> >> > },
> >> > +   { "cdns,phy-input-delay-sd-legacy", 
> >> > SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-sdr12", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-sdr25", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-sdr50", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
> >> > +   { "cdns,phy-input-delay-sd-uhs-ddr50", 
> >> > SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
> >> > +   { "cdns,phy-input-delay-mmc-highspeed", 
> >> > SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
> >> > +   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
> >> > +   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
> >> > +   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
> >> > +   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
> >> > +};
> >> > +
> >>
> >>
> >> I see mmc-legacy property in v1,
> >> but it is missing now.
> >>
> >>
> >> >  static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> >> > u8 addr, u8 data)
> >> >  {
> >> > @@ -90,13 +113,26 @@ static int sdhci_cdns_write_phy_reg(struct 
> >> > sdhci_cdns_priv *priv,
> >> > return 0;
> >> >  }
> >> >
> >> > -static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
> >> > +static int sdhci_cdns_phy_init(struct device_node *np,
> >> > +  struct sdhci_cdns_priv *priv)
> >> >  {
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 
> >> > 9);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
> >> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
> >>
> >>
> >> I need to set SDHCI_CDNS_PHY_DLY_EMMC_LEGACY to 9 for my SoC.
> >>
> >> Maybe, do we need a DT property for this, too?
> >>
> > I can add it but could you check if you realy need it? There is no 
> > selection MMC legacy mode
> > in this driver.
> >
> 
> Ah, you are right.
> 
> For Linux, SD-Legacy and MMC-Legacy share the same timing flag.
> The legacy mode is covered by SDHCI_CDNS_PHY_DLY_SD_DEFAULT,
> so we need not to set SDHCI_CDNS_PHY_DLY_EMMC_LEGACY.
> 
> So, I have no problem with patch.
> 
> Reviewed-by: Masahiro Yamada 
> 
> 
> 
> 
> From here, just my minor comments.
> The binding should not be too Linux-oriented.
> Device Tree is hardware description language, and project-neutral from
> its concept.
> I wonder if there is a project that handles SD-Legacy and MMC-Legacy 
> separately.
> I am not sure about this, and I do not have a strong opinion, either.
> 
> I leave this to you  (and other developers).
> 

Thanks for your comments.

Because patch adding HS400 enhanced strobe support was applied 
for next branch I needed to create v5. BTW I added one extra patch modifing
probe function as you suggested.
I also modify binding to be consistent with linux MMC timing names.
The driver does not use MMC legacy at all so I think there is no need 
to distinguish between SD Legacy and MMC Legacy. So there are no 
contraindications
for being consistent with Linux.


Best Regards
Piotr Sroka


[v3 1/3] mmc: sdhci-cadence: Fix writing PHY delay

2017-03-17 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- fix indent
---
Changes for v3:
- none
---
 drivers/mmc/host/sdhci-cadence.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 316cfec..b2334ec 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -66,11 +66,12 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
-u8 addr, u8 data)
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+   u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -79,8 +80,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



[v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-17 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- dts part was removed from this patch
- most delays were moved from dts file 
  to data associated with an SoC specific compatible
- remove unrelated changes
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
- put checking delay properties inside the for loop 
  instead of using a lot of single if expressions 
---
 drivers/mmc/host/sdhci-cadence.c | 57 +++-
 1 file changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index b2334ec..7728ce6 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -54,6 +55,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -62,10 +66,33 @@
  */
 #define SDHCI_CDNS_MAX_TUNING_LOOP 40
 
+static const struct of_device_id sdhci_cdns_match[];
+
 struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
+
+struct sdhci_cdns_phy_cfg {
+   const char *property;
+   u8 addr;
+};
+
+static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
+   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
+   { "cdns,phy-input-delay-sd-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
+   { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
+   { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
+   { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
+   { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
+   { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
+   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
+   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
+   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
+   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
+};
+
+
 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
u8 addr, u8 data)
 {
@@ -90,13 +117,26 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_init(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 val;
+   int ret, i;
+
+   for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
+   ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
+  );
+   if (ret)
+   continue;
+
+   ret = sdhci_cdns_write_phy_reg(priv,
+  sdhci_cdns_phy_cfgs[i].addr,
+  val);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
 }
 
 static inline void *sdhci_cdns_priv(struct sdhci_host *host)
@@ -227,6 +267,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
struct sdhci_cdns_priv *priv;
struct clk *clk;
int ret;
+   struct device *dev = >dev;
 
clk = devm_clk_get(>dev, NULL);
if (IS_ERR(clk))
@@ -254,7 +295,9 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
if (ret)
goto free;
 
-   sdhci_cdns_phy_init(priv);
+   ret = sdhci_cdns_phy_init(dev->of_node, priv);
+   if (ret)
+   goto free;
 
ret = sdhci_add_host(host);
if (ret)
-- 
2.2.2



[v3 2/3] Documentation: bindings: add description of PHY delays for sdhci-cadence

2017-03-17 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.
Add description of new DLL PHY delays.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- file was created in v2. It was a part of driver source file patch.
- most delays were moved from dts file 
  to data associated with an SoC specific compatible
- description of delays was updated to be more clearly
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..c341820 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,53 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+Some PHY delays can be configured by following properties.
+PHY DLL input delays:
+They are used to delay the data valid window, and align the window
+to sampling clock. The delay starts from 5ns (for delay parameter equal to 0)
+and it is increased by 2.5ns in each step.
+- cdns,phy-input-delay-sd-highspeed:
+  Value of the delay in the input path for SD high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-legacy:
+  Value of the delay in the input path for SD legacy timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr12:
+  Value of the delay in the input path for SD UHS SDR12 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr25:
+  Value of the delay in the input path for SD UHS SDR25 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr50:
+  Value of the delay in the input path for SD UHS SDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-ddr50:
+  Value of the delay in the input path for SD UHS DDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-highspeed:
+  Value of the delay in the input path for MMC high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-ddr:
+  Value of the delay in the input path for eMMC high-speed DDR timing
+  Valid range = [0:0x1F].
+
+PHY DLL clock delays:
+Each delay property represents the fraction of the clock period.
+The approximate delay value will be
+(/128)*sdmclk_clock_period.
+- cdns,phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +76,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   cdns,phy-dll-delay-sdclk = <0>;
};
-- 
2.2.2



RE: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-20 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 17 March, 2017 6:23 PM
> Subject: Re: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration
> 
> Hi Piotr,
> 
> Sorry for my late reply.
> 
> 
> >
> > It looks that "input delays" and "DLL sdclk delays" should be defined in 
> > dts file because they depend on a chip and a board
> implementation. On the other hand the less dts properties the better.
> >
> > There is one more way to handle input delays. It can be achieved by PHY 
> > training. PHY training is similar to the tuning and it should be
> done when proper timing mode is selected and clock frequency is set.
> > To make it possible the sdhci_set_ios function need to be global. Then I 
> > could create sdhci_cdns_set_ios function as follows:
> > void sdhci_cdns_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) {
> > . . .
> >
> > sdhci_set_ios(mmc, ios);
> > /* execute PHY training if needed */
> > sdhci_cdns_exec_phy_training(host);
> > }
> >
> > The mmc framework configures timing and frequency separately so PHY 
> > training should be executed every time if timing or clock
> frequency is changed. I am not sure If I can change sdhci_set_ios to global 
> function.
> 
> 
> I am OK with this, but I hope Adrian can advise us.
> 
> 
> 
> 
> > So maybe put all delays to dts file would be a better solution? What do you 
> > think?
> 
> I am OK with DT approach too
> because this way seems simpler, after all.
> 
> (My suggestion for data array approach was misleading, sorry.)
> 
Thanks for review anyway it was useful. Now decision between DTS and data array 
is more clear for me. 

Regards 
Piotr Sroka


RE: [v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-20 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 17 March, 2017 6:24 PM
> Subject: Re: [v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration
> 
> 
> 
> > @@ -62,10 +66,33 @@
> >   */
> >  #define SDHCI_CDNS_MAX_TUNING_LOOP 40
> >
> > +static const struct of_device_id sdhci_cdns_match[];
> > +
> 
> You forgot to remove this.
> 
You are right. Thanks.
 
> 
> > @@ -227,6 +267,7 @@ static int sdhci_cdns_probe(struct platform_device 
> > *pdev)
> > struct sdhci_cdns_priv *priv;
> > struct clk *clk;
> > int ret;
> > +   struct device *dev = >dev;
> >
> > clk = devm_clk_get(>dev, NULL);
> 
> 
> If you add "dev", please use it for devm_clk_get, too.
> 
I did on the first patch version but Ulf pointed that this is unrelated change 
and should be removed. 
Therefore I remove it. 

> 
> 
> --
> Best Regards
> Masahiro Yamada


RE: [v3 2/3] Documentation: bindings: add description of PHY delays for sdhci-cadence

2017-03-20 Thread Piotr Sroka


> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 17 March, 2017 6:30 PM
> Subject: Re: [v3 2/3] Documentation: bindings: add description of PHY delays 
> for sdhci-cadence
> 
> Hi Piotr,
> 
> 2017-03-17 21:40 GMT+09:00 Piotr Sroka :
> > DTS properties are used instead of fixed data because PHY settings can
> > be different for different chips/boards.
> > Add description of new DLL PHY delays.
> >
> > Signed-off-by: Piotr Sroka 
> 
> 
> I think you have a chance for v4.
> 
> Next time, please follow Rob's suggestion
> 
> > For the subject: "dt-bindings: mmc: ..."
> 
> 
I missed it. Thanks. I will use proper prefix in the next version.

Best Regards
Piotr Sroka


[v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-20 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- dts part was removed from this patch
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- remove unrelated changes
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
- put checking delay properties inside the for loop
  instead of using a lot of single if expressions
---
Changes for v4:
- remove unecessary declaration of sdhci_cdns_match
- format fix (blank line removed)
---
 drivers/mmc/host/sdhci-cadence.c | 53 ++--
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index b2334ec..308a372 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -54,6 +55,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -66,6 +70,25 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
+struct sdhci_cdns_phy_cfg {
+   const char *property;
+   u8 addr;
+};
+
+static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
+   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
+   { "cdns,phy-input-delay-sd-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
+   { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
+   { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
+   { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
+   { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
+   { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
+   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
+   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
+   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
+   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
+};
+
 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
u8 addr, u8 data)
 {
@@ -90,13 +113,26 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_init(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 val;
+   int ret, i;
+
+   for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
+   ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
+  );
+   if (ret)
+   continue;
+
+   ret = sdhci_cdns_write_phy_reg(priv,
+  sdhci_cdns_phy_cfgs[i].addr,
+  val);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
 }
 
 static inline void *sdhci_cdns_priv(struct sdhci_host *host)
@@ -227,6 +263,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
struct sdhci_cdns_priv *priv;
struct clk *clk;
int ret;
+   struct device *dev = >dev;
 
clk = devm_clk_get(>dev, NULL);
if (IS_ERR(clk))
@@ -254,7 +291,9 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
if (ret)
goto free;
 
-   sdhci_cdns_phy_init(priv);
+   ret = sdhci_cdns_phy_init(dev->of_node, priv);
+   if (ret)
+   goto free;
 
ret = sdhci_add_host(host);
if (ret)
-- 
2.2.2



[v4 2/3] dt-bindings: mmc: add description of PHY delays for sdhci-cadence

2017-03-20 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.
Add description of new DLL PHY delays.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- file was created in v2. It was a part of driver source file patch.
- most delays were moved from dts file
  to data associated with an SoC specific compatible
- description of delays was updated to be more clearly
---
Changes for v3:
- move all delays back to dts because they are also boards dependent
- prefix all of the Cadence-specific properties with cdns prefix
---
Changes for v4:
- change the beginning of the commit subject
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..c341820 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,53 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+Some PHY delays can be configured by following properties.
+PHY DLL input delays:
+They are used to delay the data valid window, and align the window
+to sampling clock. The delay starts from 5ns (for delay parameter equal to 0)
+and it is increased by 2.5ns in each step.
+- cdns,phy-input-delay-sd-highspeed:
+  Value of the delay in the input path for SD high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-legacy:
+  Value of the delay in the input path for SD legacy timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr12:
+  Value of the delay in the input path for SD UHS SDR12 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr25:
+  Value of the delay in the input path for SD UHS SDR25 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-sdr50:
+  Value of the delay in the input path for SD UHS SDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-sd-uhs-ddr50:
+  Value of the delay in the input path for SD UHS DDR50 timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-highspeed:
+  Value of the delay in the input path for MMC high-speed timing
+  Valid range = [0:0x1F].
+- cdns,phy-input-delay-mmc-ddr:
+  Value of the delay in the input path for eMMC high-speed DDR timing
+  Valid range = [0:0x1F].
+
+PHY DLL clock delays:
+Each delay property represents the fraction of the clock period.
+The approximate delay value will be
+(/128)*sdmclk_clock_period.
+- cdns,phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+- cdns,phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +76,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   cdns,phy-dll-delay-sdclk = <0>;
};
-- 
2.2.2



[v4 1/3] mmc: sdhci-cadence: Fix writing PHY delay

2017-03-20 Thread Piotr Sroka
Add polling for ACK to be sure that data are written to PHY register.

Signed-off-by: Piotr Sroka 
---
Changes for v2:
- fix indent
---
Changes for v3:
- none
---
Changes for v4:
- none
---
 drivers/mmc/host/sdhci-cadence.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 316cfec..b2334ec 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -66,11 +66,12 @@ struct sdhci_cdns_priv {
void __iomem *hrs_addr;
 };
 
-static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
-u8 addr, u8 data)
+static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+   u8 addr, u8 data)
 {
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
u32 tmp;
+   int ret;
 
tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
  (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
@@ -79,8 +80,14 @@ static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
tmp |= SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
 
+   ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
+   if (ret)
+   return ret;
+
tmp &= ~SDHCI_CDNS_HRS04_WR;
writel(tmp, reg);
+
+   return 0;
 }
 
 static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
-- 
2.2.2



[no subject]

2017-03-21 Thread Piotr Sroka
Subject: RE: [v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration
In-reply-to: 

References: <1490008372-16372-1-git-send-email-pio...@cadence.com> 
<1490008855-27135-1-git-send-email-pio...@cadence.com> 



Hi Masahiro 

2017-03-21 02:46 AM Masahiro Yamada :
> Hi Piotr,
> 
> 
> 2017-03-20 20:20 GMT+09:00 Piotr Sroka :
> > DTS properties are used instead of fixed data
> > because PHY settings can be different for different chips/boards.
> >
> > Signed-off-by: Piotr Sroka 
> 
> 
> I found this version is a problem for me.
> 
> 
> > +
> > +static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
> > +   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
> > +   { "cdns,phy-input-delay-sd-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 
> > },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr12", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr25", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr50", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
> > +   { "cdns,phy-input-delay-sd-uhs-ddr50", 
> > SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
> > +   { "cdns,phy-input-delay-mmc-highspeed", 
> > SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
> > +   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
> > +   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
> > +   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
> > +   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
> > +};
> > +
> 
> 
> I see mmc-legacy property in v1,
> but it is missing now.
> 
> 
> >  static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> > u8 addr, u8 data)
> >  {
> > @@ -90,13 +113,26 @@ static int sdhci_cdns_write_phy_reg(struct 
> > sdhci_cdns_priv *priv,
> > return 0;
> >  }
> >
> > -static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
> > +static int sdhci_cdns_phy_init(struct device_node *np,
> > +  struct sdhci_cdns_priv *priv)
> >  {
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
> 
> 
> I need to set SDHCI_CDNS_PHY_DLY_EMMC_LEGACY to 9 for my SoC.
> 
> Maybe, do we need a DT property for this, too?
> 
I can add it but could you check if you realy need it? There is no selection 
MMC legacy mode
in this driver. 


Best Regards
Piotr Sroka


RE: [v4 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-21 Thread Piotr Sroka

Hi Masahiro 

2017-03-21 02:46 AM Masahiro Yamada :
> Hi Piotr,
> 
> 
> 2017-03-20 20:20 GMT+09:00 Piotr Sroka :
> > DTS properties are used instead of fixed data
> > because PHY settings can be different for different chips/boards.
> >
> > Signed-off-by: Piotr Sroka 
> 
> 
> I found this version is a problem for me.
> 
> 
> > +
> > +static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
> > +   { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
> > +   { "cdns,phy-input-delay-sd-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 
> > },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr12", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr25", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
> > +   { "cdns,phy-input-delay-sd-uhs-sdr50", 
> > SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
> > +   { "cdns,phy-input-delay-sd-uhs-ddr50", 
> > SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
> > +   { "cdns,phy-input-delay-mmc-highspeed", 
> > SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
> > +   { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
> > +   { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
> > +   { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
> > +   { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
> > +};
> > +
> 
> 
> I see mmc-legacy property in v1,
> but it is missing now.
> 
> 
> >  static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
> > u8 addr, u8 data)
> >  {
> > @@ -90,13 +113,26 @@ static int sdhci_cdns_write_phy_reg(struct 
> > sdhci_cdns_priv *priv,
> > return 0;
> >  }
> >
> > -static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
> > +static int sdhci_cdns_phy_init(struct device_node *np,
> > +  struct sdhci_cdns_priv *priv)
> >  {
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
> > -   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
> 
> 
> I need to set SDHCI_CDNS_PHY_DLY_EMMC_LEGACY to 9 for my SoC.
> 
> Maybe, do we need a DT property for this, too?
> 
I can add it but could you check if you realy need it? There is no selection 
MMC legacy mode
in this driver. 


Best Regards
Piotr Sroka


RE: [v3 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-21 Thread Piotr Sroka
Hi Masahiro,

> Hi Piotr,
> 
> 2017-03-20 17:47 GMT+09:00 Piotr Sroka :
> >
> >>
> >> > @@ -227,6 +267,7 @@ static int sdhci_cdns_probe(struct platform_device 
> >> > *pdev)
> >> > struct sdhci_cdns_priv *priv;
> >> > struct clk *clk;
> >> > int ret;
> >> > +   struct device *dev = >dev;
> >> >
> >> > clk = devm_clk_get(>dev, NULL);
> >>
> >>
> >> If you add "dev", please use it for devm_clk_get, too.
> >>
> > I did on the first patch version but Ulf pointed that this is unrelated 
> > change and should be removed.
> > Therefore I remove it.
> 
> Ah, OK.
> 
> Could you consider to send a separate patch for this?
> 
Ok. If v5 is needed I will add additional patch making this modification. If 
not I will prepare a spearate patch.


Best Regards
Piotr Sroka


RE: [v3] mmc: sdhci-cadence: add HS400 enhanced strobe support

2017-03-06 Thread Piotr Sroka
Hi Masahiro,

Thanks for all of your reviews.

Best Regards
Piotr Sroka

> -Original Message-
> From: Masahiro Yamada [mailto:yamada.masah...@socionext.com]
> Sent: 06 March, 2017 9:59 PM
> Subject: Re: [v3] mmc: sdhci-cadence: add HS400 enhanced strobe support
> 
> Hi Piotr,
> 
> 2017-03-06 17:28 GMT+09:00 Piotr Sroka :
> > Add support for HS400ES mode to Cadence SDHCI driver.
> >
> > Signed-off-by: Piotr Sroka 
> > ---
> > Changes in v2:
> > - Modify enhanced strobe function to handle disabling
> >   enhanced strobe inside the function.
> >   Do no relay on that mmc_set_ios() is called
> >   immediately after host->ops->hs400_enhanced_strobe(host, >ios).
> > Changes in v3:
> > - Few coding-style fixes were made.
> 
> 
> Thanks for the update, and it looks good to me.
> 
> Reviewed-by: Masahiro Yamada 
> 
> --
> Best Regards
> Masahiro Yamada


RE: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration

2017-03-07 Thread Piotr Sroka
Hi Masahiro,

> -Original Message-
> Sent: 07 March, 2017 9:03 AM
> To: Piotr Sroka
> Subject: Re: [v2 PATCH 3/3] mmc: sdhci-cadence: Update PHY delay configuration
> 
> Hi Piotr,
> 
> 2017-03-06 22:39 GMT+09:00 Piotr Sroka :
> > PHY settings can be different for different platforms and SoCs.
> > Fixed PHY input delays was replaced with SoC specific compatible data.
> > DTS properties are used for configuration new PHY DLL delays.
> 
> 
> Probably you are familiar with this IP.
> 
> Please teach me this.
> 
> With this patch, we will have two groups for PHY parameters.
> 
> (A) specified via a data array associated with a compatible string 
> SDHCI_CDNS_PHY_DLY_SD_HS SDHCI_CDNS_PHY_DLY_SD_DEFAULT
> SDHCI_CDNS_PHY_DLY_UHS_SDR12
> SDHCI_CDNS_PHY_DLY_UHS_SDR25
> SDHCI_CDNS_PHY_DLY_UHS_SDR50
> SDHCI_CDNS_PHY_DLY_UHS_DDR50
> SDHCI_CDNS_PHY_DLY_EMMC_LEGACY
> SDHCI_CDNS_PHY_DLY_EMMC_SDR
> SDHCI_CDNS_PHY_DLY_EMMC_DDR
> 
> (B) specified with DT property
> SDHCI_CDNS_PHY_DLY_SDCLK
> SDHCI_CDNS_PHY_DLY_HSMMC
> SDHCI_CDNS_PHY_DLY_STROBE
> 
> I am confused.
> What is the difference between (A) and (B)?

The first group of delays are input delays. These delays are set in current 
version of sdhci-cadence driver in sdhci_cdns_phy_init function.
Following by spec:
They are provided to help in meeting timings relations between data window and 
sampling clock. 
The clock is fixed position in respect to the SDCLK. And the idea of sampling 
is to delay and align the data to the data window.
If the default values of the delays are not sufficient/correct for the 
chip/board implementation those can be adjusted

The second group are DLL delays.
There are three delays
SDHCI_CDNS_PHY_DLY_SDCLK  - sdclk delay line use to delay outgoing sdclk signal
SDHCI_CDNS_PHY_DLY_HSMMC - sdclk delay line use to delay outgoing sdclk signal 
for for HS200, HS400 and HS400ES
SDHCI_CDNS_PHY_DLY_STROBE - DLL strobe delay for HS400ES
Following by spec:
They allows to setup basic DLL parameters. In general the default values are 
sufficient to start working in any speed mode. The default values of delays and 
phase detect select can be adjusted depending on the chip/board implementation. 

In general all PHY delays values either should be properly hardcoded in HW or 
they should be properly set  by FW depending on the chip/board.
So PHY driver should do not touch PHY delays at all or should set values which 
are proper for specific chip/board.

I am not sure where exactly they should be placed in dts file or in compatible 
data. 
  
Best Regards
Piotr Sroka


[PATCH] mmc: core: fix changing bus witdh in hs400es mode

2017-03-02 Thread Piotr Sroka
Fix the code to avoid changing bus width if HS400ES mode is selected.

Signed-off-by: Piotr Sroka 
---
 drivers/mmc/core/mmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 7fd7228..c7d9c9f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1730,7 +1730,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_select_hs400(card);
if (err)
goto free_card;
-   } else {
+   } else if (!mmc_card_hs400(card)) {
/* Select the desired bus width optionally */
err = mmc_select_bus_width(card);
if (err > 0 && mmc_card_hs(card)) {
-- 
2.2.2



[PATCH] Add HS400 enhanced strobe support

2017-02-15 Thread Piotr Sroka
Add support for HS400ES mode to Cadence SDHCI driver.

Signed-off-by: Piotr Sroka 
---
 drivers/mmc/host/sdhci-cadence.c | 41 +---
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index 4b0ecb9..5296c7c 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -39,6 +39,7 @@
 #define   SDHCI_CDNS_HRS06_MODE_MMC_DDR0x3
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS200  0x4
 #define   SDHCI_CDNS_HRS06_MODE_MMC_HS400  0x5
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400ES0x6
 
 /* SRS - Slot Register Set (SDHCI-compatible) */
 #define SDHCI_CDNS_SRS_BASE0x200
@@ -63,6 +64,7 @@
 
 struct sdhci_cdns_priv {
void __iomem *hrs_addr;
+   bool enhanced_strobe;
 };
 
 static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
@@ -107,11 +109,22 @@ static unsigned int sdhci_cdns_get_timeout_clock(struct 
sdhci_host *host)
return host->max_clk / 1000;
 }
 
+static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode)
+{
+   u32 tmp;
+
+   /* The speed mode for eMMC is selected by HRS06 register */
+   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
+   tmp |= mode;
+   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+}
+
 static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
 unsigned int timing)
 {
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
-   u32 mode, tmp;
+   u32 mode;
 
switch (timing) {
case MMC_TIMING_MMC_HS:
@@ -124,24 +137,35 @@ static void sdhci_cdns_set_uhs_signaling(struct 
sdhci_host *host,
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
break;
case MMC_TIMING_MMC_HS400:
-   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
+   if (priv->enhanced_strobe)
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
+   else
+   mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
break;
default:
mode = SDHCI_CDNS_HRS06_MODE_SD;
break;
}
 
-   /* The speed mode for eMMC is selected by HRS06 register */
-   tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
-   tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
-   tmp |= mode;
-   writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+   sdhci_cdns_set_emmc_mode(priv, mode);
 
/* For SD, fall back to the default handler */
if (mode == SDHCI_CDNS_HRS06_MODE_SD)
sdhci_set_uhs_signaling(host, timing);
 }
 
+static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
+struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+
+   priv->enhanced_strobe = ios->enhanced_strobe;
+   if (ios->enhanced_strobe)
+   sdhci_cdns_set_emmc_mode(priv,
+SDHCI_CDNS_HRS06_MODE_MMC_HS400ES);
+}
+
 static const struct sdhci_ops sdhci_cdns_ops = {
.set_clock = sdhci_set_clock,
.get_timeout_clock = sdhci_cdns_get_timeout_clock,
@@ -239,8 +263,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
 
priv = sdhci_cdns_priv(host);
priv->hrs_addr = host->ioaddr;
+   priv->enhanced_strobe = false;
host->ioaddr += SDHCI_CDNS_SRS_BASE;
host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
+   host->mmc_host_ops.hs400_enhanced_strobe =
+   sdhci_cdns_hs400_enhanced_strobe;
 
ret = mmc_of_parse(host->mmc);
if (ret)
-- 
2.2.2



[PATCH 2/2] [2/2] mmc: sdhci-cadence: Update PHY delay configuration

2017-02-16 Thread Piotr Sroka
DTS properties are used instead of fixed data
because PHY settings can be different for different platforms.
Configuration of new three PHY delays were added

Signed-off-by: Piotr Sroka 
---
 .../devicetree/bindings/mmc/sdhci-cadence.txt  | 54 ++
 drivers/mmc/host/sdhci-cadence.c   | 83 +++---
 2 files changed, 129 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
index c0f37cb..221d3fe 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
@@ -19,6 +19,59 @@ if supported.  See mmc.txt for details.
 - mmc-hs400-1_8v
 - mmc-hs400-1_2v
 
+- phy-input-delay-sd-hs:
+  Value of the delay in the input path for High Speed work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-default:
+  Value of the delay in the input path for Default Speed work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-sdr12:
+  Value of the delay in the input path for SDR12 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-sdr25:
+  Value of the delay in the input path for SDR25 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-sdr50:
+  Value of the delay in the input path for SDR50 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-sd-ddr50:
+  Value of the delay in the input path for DDR50 work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-emmc-legacy:
+  Value of the delay in the input path for eMMC legacy work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-emmc-sdr:
+  Value of the delay in the input path for eMMC SDR work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-input-delay-emmc-ddr:
+  Value of the delay in the input path for eMMC DDR work mode.
+  Valid range = [0:0x1F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-dll-delay-sdclk:
+  Value of the delay introduced on the sdclk output
+  for all modes except HS200, HS400 and HS400_ES.
+  Valid range = [0:0x7F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-dll-delay-sdclk-hsmmc:
+  Value of the delay introduced on the sdclk output
+  for HS200, HS400 and HS400_ES speed modes.
+  Valid range = [0:0x7F].
+  Delay configuration stay unchanged if this property is not provided.
+- phy-dll-delay-strobe:
+  Value of the delay introduced on the dat_strobe input
+  used in HS400 / HS400_ES speed modes.
+  Valid range = [0:0x7F].
+  Delay configuration stay unchanged if this property is not provided.
+
+
 Example:
emmc: sdhci@5a00 {
compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
@@ -29,4 +82,5 @@ Example:
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
+   phy-input-delay-sd-hs = <0>;
};
diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index c946e45..6c338d2 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -53,6 +54,9 @@
 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR0x07
 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR0x08
+#define SDHCI_CDNS_PHY_DLY_SDCLK   0x0b
+#define SDHCI_CDNS_PHY_DLY_HSMMC   0x0c
+#define SDHCI_CDNS_PHY_DLY_STROBE  0x0d
 
 /*
  * The tuned val register is 6 bit-wide, but not the whole of the range is
@@ -89,13 +93,73 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv 
*priv,
return 0;
 }
 
-static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+static int sdhci_cdns_phy_parse_dt(struct device_node *np,
+  struct sdhci_cdns_priv *priv)
 {
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
-   sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+   u32 tmp;
+   int ret;
+
+   if (!of_property_read_u32(np, "phy-input-delay-sd-hs", )) {
+

  1   2   >