Re: [PATCH 1/2] mmc: t210: Add autocal and tap/trim updates for SDMMC1/3

2020-04-01 Thread Jaehoon Chung
Hi Tom,

On 3/27/20 7:30 AM, tomcwarren3...@gmail.com wrote:
> From: Tom Warren 
> 
> As per the T210 TRM, when running at 3.3v, the SDMMC1 tap/trim and
> autocal values need to be set to condition the signals correctly before
> talking to the SD-card. This is the same as what's being done in CBoot,
> but it gets reset when the SDMMC1 HW is soft-reset during SD driver
> init, so needs to be repeated here. Also set autocal and tap/trim for
> SDMMC3, although no T210 boards use it for SD-card at this time.
> 
> Signed-off-by: Tom Warren 


Reviewed-by: Jaehoon Chung 

Best Regards,
Jaehoon Chung


> ---
> Changes for v2:
>  - Added clocks.h include for TEGRA30 to fix T30 32-bit builds
> 
>  arch/arm/include/asm/arch-tegra/tegra_mmc.h | 20 +--
>  drivers/mmc/tegra_mmc.c | 84 
> ++---
>  2 files changed, 92 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h 
> b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> index a2b6f63..a8bfa46 100644
> --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> @@ -2,7 +2,7 @@
>  /*
>   * (C) Copyright 2009 SAMSUNG Electronics
>   * Minkyu Kang 
> - * Portions Copyright (C) 2011-2012 NVIDIA Corporation
> + * Portions Copyright (C) 2011-2012,2019 NVIDIA Corporation
>   */
>  
>  #ifndef __TEGRA_MMC_H_
> @@ -52,7 +52,7 @@ struct tegra_mmc {
>   unsigned char   admaerr;/* offset 54h */
>   unsigned char   res4[3];/* RESERVED, offset 55h-57h */
>   unsigned long   admaaddr;   /* offset 58h-5Fh */
> - unsigned char   res5[0xa0]; /* RESERVED, offset 60h-FBh */
> + unsigned char   res5[0x9c]; /* RESERVED, offset 60h-FBh */
>   unsigned short  slotintstatus;  /* offset FCh */
>   unsigned short  hcver;  /* HOST Version */
>   unsigned intvenclkctl;  /* _VENDOR_CLOCK_CNTRL_0,100h */
> @@ -127,11 +127,23 @@ struct tegra_mmc {
>  
>  #define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE  (1 << 1)
>  
> -/* SDMMC1/3 settings from section 24.6 of T30 TRM */
> +/* SDMMC1/3 settings from SDMMCx Initialization Sequence of TRM */
>  #define MEMCOMP_PADCTRL_VREF 7
> -#define AUTO_CAL_ENABLED (1 << 29)
> +#define AUTO_CAL_ENABLE  (1 << 29)
> +#if defined(CONFIG_TEGRA210)
> +#define AUTO_CAL_ACTIVE  (1 << 31)
> +#define AUTO_CAL_START   (1 << 31)
> +#define AUTO_CAL_PD_OFFSET   (0x7D << 8)
> +#define AUTO_CAL_PU_OFFSET   (0 << 0)
> +#define IO_TRIM_BYPASS_MASK  (1 << 2)
> +#define TRIM_VAL_SHIFT   24
> +#define TRIM_VAL_MASK(0x1F << TRIM_VAL_SHIFT)
> +#define TAP_VAL_SHIFT16
> +#define TAP_VAL_MASK (0xFF << TAP_VAL_SHIFT)
> +#else
>  #define AUTO_CAL_PD_OFFSET   (0x70 << 8)
>  #define AUTO_CAL_PU_OFFSET   (0x62 << 0)
> +#endif
>  
>  #endif   /* __ASSEMBLY__ */
>  #endif   /* __TEGRA_MMC_H_ */
> diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
> index f022e93..73ac58c 100644
> --- a/drivers/mmc/tegra_mmc.c
> +++ b/drivers/mmc/tegra_mmc.c
> @@ -3,7 +3,7 @@
>   * (C) Copyright 2009 SAMSUNG Electronics
>   * Minkyu Kang 
>   * Jaehoon Chung 
> - * Portions Copyright 2011-2016 NVIDIA Corporation
> + * Portions Copyright 2011-2019 NVIDIA Corporation
>   */
>  
>  #include 
> @@ -15,6 +15,9 @@
>  #include 
>  #include 
>  #include 
> +#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210)
> +#include 
> +#endif
>  
>  struct tegra_mmc_plat {
>   struct mmc_config cfg;
> @@ -30,6 +33,7 @@ struct tegra_mmc_priv {
>   struct gpio_desc wp_gpio;   /* Write Protect GPIO */
>   unsigned int version;   /* SDHCI spec. version */
>   unsigned int clock; /* Current clock (MHz) */
> + int mmc_id; /* peripheral id */
>  };
>  
>  static void tegra_mmc_set_power(struct tegra_mmc_priv *priv,
> @@ -446,16 +450,19 @@ static int tegra_mmc_set_ios(struct udevice *dev)
>  
>  static void tegra_mmc_pad_init(struct tegra_mmc_priv *priv)
>  {
> -#if defined(CONFIG_TEGRA30)
> +#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210)
>   u32 val;
> + u16 clk_con;
> + int timeout;
> + int id = priv->mmc_id;
>  
> - debug("%s: sdmmc address = %08x\n", __func__, (unsigned int)priv->reg);
> + debug("%s: sdmmc address = %p, id = %d\n", __func__,
> + priv->reg, id);
>  
>   /* Set the pad drive strength for SDMMC1 or 3 only */
> - if (priv->reg != (void *)0x7800 &&
> - priv->reg != (void *)0x78000400) {
> + if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) {
>   debug("%s: settings are only valid for SDMMC1/SDMMC3!\n",
> -   __func__);
> + __func__);
>   return;
>   }
>  
> @@ -464,11 +471,65 @@ static void tegra_mmc_pad_init(struct tegra_mmc_priv 
> *priv)
>   val |= MEMCOMP_PADCTRL_VREF;
>   writel(val, &priv->reg->sdmemcmppadc

[PATCH 1/2] mmc: t210: Add autocal and tap/trim updates for SDMMC1/3

2020-03-26 Thread tomcwarren3959
From: Tom Warren 

As per the T210 TRM, when running at 3.3v, the SDMMC1 tap/trim and
autocal values need to be set to condition the signals correctly before
talking to the SD-card. This is the same as what's being done in CBoot,
but it gets reset when the SDMMC1 HW is soft-reset during SD driver
init, so needs to be repeated here. Also set autocal and tap/trim for
SDMMC3, although no T210 boards use it for SD-card at this time.

Signed-off-by: Tom Warren 
---
Changes for v2:
 - Added clocks.h include for TEGRA30 to fix T30 32-bit builds

 arch/arm/include/asm/arch-tegra/tegra_mmc.h | 20 +--
 drivers/mmc/tegra_mmc.c | 84 ++---
 2 files changed, 92 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h 
b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index a2b6f63..a8bfa46 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -2,7 +2,7 @@
 /*
  * (C) Copyright 2009 SAMSUNG Electronics
  * Minkyu Kang 
- * Portions Copyright (C) 2011-2012 NVIDIA Corporation
+ * Portions Copyright (C) 2011-2012,2019 NVIDIA Corporation
  */
 
 #ifndef __TEGRA_MMC_H_
@@ -52,7 +52,7 @@ struct tegra_mmc {
unsigned char   admaerr;/* offset 54h */
unsigned char   res4[3];/* RESERVED, offset 55h-57h */
unsigned long   admaaddr;   /* offset 58h-5Fh */
-   unsigned char   res5[0xa0]; /* RESERVED, offset 60h-FBh */
+   unsigned char   res5[0x9c]; /* RESERVED, offset 60h-FBh */
unsigned short  slotintstatus;  /* offset FCh */
unsigned short  hcver;  /* HOST Version */
unsigned intvenclkctl;  /* _VENDOR_CLOCK_CNTRL_0,100h */
@@ -127,11 +127,23 @@ struct tegra_mmc {
 
 #define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE(1 << 1)
 
-/* SDMMC1/3 settings from section 24.6 of T30 TRM */
+/* SDMMC1/3 settings from SDMMCx Initialization Sequence of TRM */
 #define MEMCOMP_PADCTRL_VREF   7
-#define AUTO_CAL_ENABLED   (1 << 29)
+#define AUTO_CAL_ENABLE(1 << 29)
+#if defined(CONFIG_TEGRA210)
+#define AUTO_CAL_ACTIVE(1 << 31)
+#define AUTO_CAL_START (1 << 31)
+#define AUTO_CAL_PD_OFFSET (0x7D << 8)
+#define AUTO_CAL_PU_OFFSET (0 << 0)
+#define IO_TRIM_BYPASS_MASK(1 << 2)
+#define TRIM_VAL_SHIFT 24
+#define TRIM_VAL_MASK  (0x1F << TRIM_VAL_SHIFT)
+#define TAP_VAL_SHIFT  16
+#define TAP_VAL_MASK   (0xFF << TAP_VAL_SHIFT)
+#else
 #define AUTO_CAL_PD_OFFSET (0x70 << 8)
 #define AUTO_CAL_PU_OFFSET (0x62 << 0)
+#endif
 
 #endif /* __ASSEMBLY__ */
 #endif /* __TEGRA_MMC_H_ */
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index f022e93..73ac58c 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -3,7 +3,7 @@
  * (C) Copyright 2009 SAMSUNG Electronics
  * Minkyu Kang 
  * Jaehoon Chung 
- * Portions Copyright 2011-2016 NVIDIA Corporation
+ * Portions Copyright 2011-2019 NVIDIA Corporation
  */
 
 #include 
@@ -15,6 +15,9 @@
 #include 
 #include 
 #include 
+#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210)
+#include 
+#endif
 
 struct tegra_mmc_plat {
struct mmc_config cfg;
@@ -30,6 +33,7 @@ struct tegra_mmc_priv {
struct gpio_desc wp_gpio;   /* Write Protect GPIO */
unsigned int version;   /* SDHCI spec. version */
unsigned int clock; /* Current clock (MHz) */
+   int mmc_id; /* peripheral id */
 };
 
 static void tegra_mmc_set_power(struct tegra_mmc_priv *priv,
@@ -446,16 +450,19 @@ static int tegra_mmc_set_ios(struct udevice *dev)
 
 static void tegra_mmc_pad_init(struct tegra_mmc_priv *priv)
 {
-#if defined(CONFIG_TEGRA30)
+#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210)
u32 val;
+   u16 clk_con;
+   int timeout;
+   int id = priv->mmc_id;
 
-   debug("%s: sdmmc address = %08x\n", __func__, (unsigned int)priv->reg);
+   debug("%s: sdmmc address = %p, id = %d\n", __func__,
+   priv->reg, id);
 
/* Set the pad drive strength for SDMMC1 or 3 only */
-   if (priv->reg != (void *)0x7800 &&
-   priv->reg != (void *)0x78000400) {
+   if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) {
debug("%s: settings are only valid for SDMMC1/SDMMC3!\n",
- __func__);
+   __func__);
return;
}
 
@@ -464,11 +471,65 @@ static void tegra_mmc_pad_init(struct tegra_mmc_priv 
*priv)
val |= MEMCOMP_PADCTRL_VREF;
writel(val, &priv->reg->sdmemcmppadctl);
 
+   /* Disable SD Clock Enable before running auto-cal as per TRM */
+   clk_con = readw(&priv->reg->clkcon);
+   debug("%s: CLOCK_CONTROL = 0x%04X\n", __func__, clk_con);
+   clk_con &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
+   writew(clk_con, &priv->reg->clkcon);
+
val = readl(&priv->reg->autocal

RE: [PATCH 1/2] mmc: t210: Add autocal and tap/trim updates for SDMMC1/3

2020-03-18 Thread Tom Warren
[Tom] see below

-Original Message-
From: Jaehoon Chung  
Sent: Tuesday, March 17, 2020 4:48 PM
To: Tom Warren ; u-boot@lists.denx.de
Subject: Re: [PATCH 1/2] mmc: t210: Add autocal and tap/trim updates for 
SDMMC1/3

External email: Use caution opening links or attachments


On 3/17/20 6:59 AM, twar...@nvidia.com wrote:
> From: Tom Warren 
>
> As per the T210 TRM, when running at 3.3v, the SDMMC1 tap/trim and 
> autocal values need to be set to condition the signals correctly 
> before talking to the SD-card. This is the same as what's being done 
> in CBoot, but it gets reset when the SDMMC1 HW is soft-reset during SD 
> driver init, so needs to be repeated here. Also set autocal and 
> tap/trim for SDMMC3, although no T210 boards use it for SD-card at this time.
>
> Signed-off-by: Tom Warren 
> ---
>  arch/arm/include/asm/arch-tegra/tegra_mmc.h | 20 +--
>  drivers/mmc/tegra_mmc.c | 84 
> ++---
>  2 files changed, 92 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h 
> b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> index a2b6f63..a8bfa46 100644
> --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> @@ -2,7 +2,7 @@
>  /*
>   * (C) Copyright 2009 SAMSUNG Electronics
>   * Minkyu Kang 
> - * Portions Copyright (C) 2011-2012 NVIDIA Corporation
> + * Portions Copyright (C) 2011-2012,2019 NVIDIA Corporation
>   */
>
>  #ifndef __TEGRA_MMC_H_
> @@ -52,7 +52,7 @@ struct tegra_mmc {
>   unsigned char   admaerr;/* offset 54h */
>   unsigned char   res4[3];/* RESERVED, offset 55h-57h */
>   unsigned long   admaaddr;   /* offset 58h-5Fh */
> - unsigned char   res5[0xa0]; /* RESERVED, offset 60h-FBh */
> + unsigned char   res5[0x9c]; /* RESERVED, offset 60h-FBh */

Is comment right? "RESERVED, offset 60h-FBh"..
[Tom] yes, the comment was/is correct, it's the number of reserved bytes that 
was wrong - 0x9C is correct.

>   unsigned short  slotintstatus;  /* offset FCh */
>   unsigned short  hcver;  /* HOST Version */
>   unsigned intvenclkctl;  /* _VENDOR_CLOCK_CNTRL_0,100h */
> @@ -127,11 +127,23 @@ struct tegra_mmc {
>
>  #define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE  (1 << 1)
>
> -/* SDMMC1/3 settings from section 24.6 of T30 TRM */
> +/* SDMMC1/3 settings from SDMMCx Initialization Sequence of TRM */
>  #define MEMCOMP_PADCTRL_VREF 7
> -#define AUTO_CAL_ENABLED (1 << 29)
> +#define AUTO_CAL_ENABLE  (1 << 29)
> +#if defined(CONFIG_TEGRA210)
> +#define AUTO_CAL_ACTIVE  (1 << 31)
> +#define AUTO_CAL_START   (1 << 31)
> +#define AUTO_CAL_PD_OFFSET   (0x7D << 8)
> +#define AUTO_CAL_PU_OFFSET   (0 << 0)
> +#define IO_TRIM_BYPASS_MASK  (1 << 2)
> +#define TRIM_VAL_SHIFT   24
> +#define TRIM_VAL_MASK(0x1F << TRIM_VAL_SHIFT)
> +#define TAP_VAL_SHIFT16
> +#define TAP_VAL_MASK (0xFF << TAP_VAL_SHIFT)
> +#else
>  #define AUTO_CAL_PD_OFFSET   (0x70 << 8)
>  #define AUTO_CAL_PU_OFFSET   (0x62 << 0)
> +#endif
>
>  #endif   /* __ASSEMBLY__ */
>  #endif   /* __TEGRA_MMC_H_ */
> diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 
> f022e93..a4bd679 100644
> --- a/drivers/mmc/tegra_mmc.c
> +++ b/drivers/mmc/tegra_mmc.c
> @@ -3,7 +3,7 @@
>   * (C) Copyright 2009 SAMSUNG Electronics
>   * Minkyu Kang 
>   * Jaehoon Chung 
> - * Portions Copyright 2011-2016 NVIDIA Corporation
> + * Portions Copyright 2011-2019 NVIDIA Corporation
>   */
>
>  #include 
> @@ -15,6 +15,9 @@
>  #include 
>  #include   #include 
> +#if defined(CONFIG_TEGRA210)
> +#include 
> +#endif
>
>  struct tegra_mmc_plat {
>   struct mmc_config cfg;
> @@ -30,6 +33,7 @@ struct tegra_mmc_priv {
>   struct gpio_desc wp_gpio;   /* Write Protect GPIO */
>   unsigned int version;   /* SDHCI spec. version */
>   unsigned int clock; /* Current clock (MHz) */
> + int mmc_id; /* peripheral id */
>  };
>
>  static void tegra_mmc_set_power(struct tegra_mmc_priv *priv, @@ 
> -446,16 +450,19 @@ static int tegra_mmc_set_ios(struct udevice *dev)
>
>  static void tegra_mmc_pad_init(struct tegra_mmc_priv *priv)  { -#if 
> defined(CONFIG_TEGRA30)
> +#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210)
>   u32 val;
> + u16 clk_con;
> + int timeout;
> + int id = priv->mmc_id;
>
> - debug("%s: sdmmc address = %08x\n", __func__, (unsigned int)priv->

Re: [PATCH 1/2] mmc: t210: Add autocal and tap/trim updates for SDMMC1/3

2020-03-17 Thread Jaehoon Chung
On 3/17/20 6:59 AM, twar...@nvidia.com wrote:
> From: Tom Warren 
> 
> As per the T210 TRM, when running at 3.3v, the SDMMC1 tap/trim and
> autocal values need to be set to condition the signals correctly before
> talking to the SD-card. This is the same as what's being done in CBoot,
> but it gets reset when the SDMMC1 HW is soft-reset during SD driver
> init, so needs to be repeated here. Also set autocal and tap/trim for
> SDMMC3, although no T210 boards use it for SD-card at this time.
> 
> Signed-off-by: Tom Warren 
> ---
>  arch/arm/include/asm/arch-tegra/tegra_mmc.h | 20 +--
>  drivers/mmc/tegra_mmc.c | 84 
> ++---
>  2 files changed, 92 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h 
> b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> index a2b6f63..a8bfa46 100644
> --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> @@ -2,7 +2,7 @@
>  /*
>   * (C) Copyright 2009 SAMSUNG Electronics
>   * Minkyu Kang 
> - * Portions Copyright (C) 2011-2012 NVIDIA Corporation
> + * Portions Copyright (C) 2011-2012,2019 NVIDIA Corporation
>   */
>  
>  #ifndef __TEGRA_MMC_H_
> @@ -52,7 +52,7 @@ struct tegra_mmc {
>   unsigned char   admaerr;/* offset 54h */
>   unsigned char   res4[3];/* RESERVED, offset 55h-57h */
>   unsigned long   admaaddr;   /* offset 58h-5Fh */
> - unsigned char   res5[0xa0]; /* RESERVED, offset 60h-FBh */
> + unsigned char   res5[0x9c]; /* RESERVED, offset 60h-FBh */

Is comment right? "RESERVED, offset 60h-FBh"..

>   unsigned short  slotintstatus;  /* offset FCh */
>   unsigned short  hcver;  /* HOST Version */
>   unsigned intvenclkctl;  /* _VENDOR_CLOCK_CNTRL_0,100h */
> @@ -127,11 +127,23 @@ struct tegra_mmc {
>  
>  #define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE  (1 << 1)
>  
> -/* SDMMC1/3 settings from section 24.6 of T30 TRM */
> +/* SDMMC1/3 settings from SDMMCx Initialization Sequence of TRM */
>  #define MEMCOMP_PADCTRL_VREF 7
> -#define AUTO_CAL_ENABLED (1 << 29)
> +#define AUTO_CAL_ENABLE  (1 << 29)
> +#if defined(CONFIG_TEGRA210)
> +#define AUTO_CAL_ACTIVE  (1 << 31)
> +#define AUTO_CAL_START   (1 << 31)
> +#define AUTO_CAL_PD_OFFSET   (0x7D << 8)
> +#define AUTO_CAL_PU_OFFSET   (0 << 0)
> +#define IO_TRIM_BYPASS_MASK  (1 << 2)
> +#define TRIM_VAL_SHIFT   24
> +#define TRIM_VAL_MASK(0x1F << TRIM_VAL_SHIFT)
> +#define TAP_VAL_SHIFT16
> +#define TAP_VAL_MASK (0xFF << TAP_VAL_SHIFT)
> +#else
>  #define AUTO_CAL_PD_OFFSET   (0x70 << 8)
>  #define AUTO_CAL_PU_OFFSET   (0x62 << 0)
> +#endif
>  
>  #endif   /* __ASSEMBLY__ */
>  #endif   /* __TEGRA_MMC_H_ */
> diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
> index f022e93..a4bd679 100644
> --- a/drivers/mmc/tegra_mmc.c
> +++ b/drivers/mmc/tegra_mmc.c
> @@ -3,7 +3,7 @@
>   * (C) Copyright 2009 SAMSUNG Electronics
>   * Minkyu Kang 
>   * Jaehoon Chung 
> - * Portions Copyright 2011-2016 NVIDIA Corporation
> + * Portions Copyright 2011-2019 NVIDIA Corporation
>   */
>  
>  #include 
> @@ -15,6 +15,9 @@
>  #include 
>  #include 
>  #include 
> +#if defined(CONFIG_TEGRA210)
> +#include 
> +#endif
>  
>  struct tegra_mmc_plat {
>   struct mmc_config cfg;
> @@ -30,6 +33,7 @@ struct tegra_mmc_priv {
>   struct gpio_desc wp_gpio;   /* Write Protect GPIO */
>   unsigned int version;   /* SDHCI spec. version */
>   unsigned int clock; /* Current clock (MHz) */
> + int mmc_id; /* peripheral id */
>  };
>  
>  static void tegra_mmc_set_power(struct tegra_mmc_priv *priv,
> @@ -446,16 +450,19 @@ static int tegra_mmc_set_ios(struct udevice *dev)
>  
>  static void tegra_mmc_pad_init(struct tegra_mmc_priv *priv)
>  {
> -#if defined(CONFIG_TEGRA30)
> +#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210)
>   u32 val;
> + u16 clk_con;
> + int timeout;
> + int id = priv->mmc_id;
>  
> - debug("%s: sdmmc address = %08x\n", __func__, (unsigned int)priv->reg);
> + debug("%s: sdmmc address = %p, id = %d\n", __func__,
> + priv->reg, id);
>  
>   /* Set the pad drive strength for SDMMC1 or 3 only */
> - if (priv->reg != (void *)0x7800 &&
> - priv->reg != (void *)0x78000400) {
> + if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) {
>   debug("%s: settings are only valid for SDMMC1/SDMMC3!\n",
> -   __func__);
> + __func__);
>   return;
>   }
>  
> @@ -464,11 +471,65 @@ static void tegra_mmc_pad_init(struct tegra_mmc_priv 
> *priv)
>   val |= MEMCOMP_PADCTRL_VREF;
>   writel(val, &priv->reg->sdmemcmppadctl);
>  
> + /* Disable SD Clock Enable before running auto-cal as per TRM */
> + clk_con = readw(&priv->reg->clkcon);
> + debug

[PATCH 1/2] mmc: t210: Add autocal and tap/trim updates for SDMMC1/3

2020-03-16 Thread twarren
From: Tom Warren 

As per the T210 TRM, when running at 3.3v, the SDMMC1 tap/trim and
autocal values need to be set to condition the signals correctly before
talking to the SD-card. This is the same as what's being done in CBoot,
but it gets reset when the SDMMC1 HW is soft-reset during SD driver
init, so needs to be repeated here. Also set autocal and tap/trim for
SDMMC3, although no T210 boards use it for SD-card at this time.

Signed-off-by: Tom Warren 
---
 arch/arm/include/asm/arch-tegra/tegra_mmc.h | 20 +--
 drivers/mmc/tegra_mmc.c | 84 ++---
 2 files changed, 92 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h 
b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index a2b6f63..a8bfa46 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -2,7 +2,7 @@
 /*
  * (C) Copyright 2009 SAMSUNG Electronics
  * Minkyu Kang 
- * Portions Copyright (C) 2011-2012 NVIDIA Corporation
+ * Portions Copyright (C) 2011-2012,2019 NVIDIA Corporation
  */
 
 #ifndef __TEGRA_MMC_H_
@@ -52,7 +52,7 @@ struct tegra_mmc {
unsigned char   admaerr;/* offset 54h */
unsigned char   res4[3];/* RESERVED, offset 55h-57h */
unsigned long   admaaddr;   /* offset 58h-5Fh */
-   unsigned char   res5[0xa0]; /* RESERVED, offset 60h-FBh */
+   unsigned char   res5[0x9c]; /* RESERVED, offset 60h-FBh */
unsigned short  slotintstatus;  /* offset FCh */
unsigned short  hcver;  /* HOST Version */
unsigned intvenclkctl;  /* _VENDOR_CLOCK_CNTRL_0,100h */
@@ -127,11 +127,23 @@ struct tegra_mmc {
 
 #define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE(1 << 1)
 
-/* SDMMC1/3 settings from section 24.6 of T30 TRM */
+/* SDMMC1/3 settings from SDMMCx Initialization Sequence of TRM */
 #define MEMCOMP_PADCTRL_VREF   7
-#define AUTO_CAL_ENABLED   (1 << 29)
+#define AUTO_CAL_ENABLE(1 << 29)
+#if defined(CONFIG_TEGRA210)
+#define AUTO_CAL_ACTIVE(1 << 31)
+#define AUTO_CAL_START (1 << 31)
+#define AUTO_CAL_PD_OFFSET (0x7D << 8)
+#define AUTO_CAL_PU_OFFSET (0 << 0)
+#define IO_TRIM_BYPASS_MASK(1 << 2)
+#define TRIM_VAL_SHIFT 24
+#define TRIM_VAL_MASK  (0x1F << TRIM_VAL_SHIFT)
+#define TAP_VAL_SHIFT  16
+#define TAP_VAL_MASK   (0xFF << TAP_VAL_SHIFT)
+#else
 #define AUTO_CAL_PD_OFFSET (0x70 << 8)
 #define AUTO_CAL_PU_OFFSET (0x62 << 0)
+#endif
 
 #endif /* __ASSEMBLY__ */
 #endif /* __TEGRA_MMC_H_ */
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index f022e93..a4bd679 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -3,7 +3,7 @@
  * (C) Copyright 2009 SAMSUNG Electronics
  * Minkyu Kang 
  * Jaehoon Chung 
- * Portions Copyright 2011-2016 NVIDIA Corporation
+ * Portions Copyright 2011-2019 NVIDIA Corporation
  */
 
 #include 
@@ -15,6 +15,9 @@
 #include 
 #include 
 #include 
+#if defined(CONFIG_TEGRA210)
+#include 
+#endif
 
 struct tegra_mmc_plat {
struct mmc_config cfg;
@@ -30,6 +33,7 @@ struct tegra_mmc_priv {
struct gpio_desc wp_gpio;   /* Write Protect GPIO */
unsigned int version;   /* SDHCI spec. version */
unsigned int clock; /* Current clock (MHz) */
+   int mmc_id; /* peripheral id */
 };
 
 static void tegra_mmc_set_power(struct tegra_mmc_priv *priv,
@@ -446,16 +450,19 @@ static int tegra_mmc_set_ios(struct udevice *dev)
 
 static void tegra_mmc_pad_init(struct tegra_mmc_priv *priv)
 {
-#if defined(CONFIG_TEGRA30)
+#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210)
u32 val;
+   u16 clk_con;
+   int timeout;
+   int id = priv->mmc_id;
 
-   debug("%s: sdmmc address = %08x\n", __func__, (unsigned int)priv->reg);
+   debug("%s: sdmmc address = %p, id = %d\n", __func__,
+   priv->reg, id);
 
/* Set the pad drive strength for SDMMC1 or 3 only */
-   if (priv->reg != (void *)0x7800 &&
-   priv->reg != (void *)0x78000400) {
+   if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) {
debug("%s: settings are only valid for SDMMC1/SDMMC3!\n",
- __func__);
+   __func__);
return;
}
 
@@ -464,11 +471,65 @@ static void tegra_mmc_pad_init(struct tegra_mmc_priv 
*priv)
val |= MEMCOMP_PADCTRL_VREF;
writel(val, &priv->reg->sdmemcmppadctl);
 
+   /* Disable SD Clock Enable before running auto-cal as per TRM */
+   clk_con = readw(&priv->reg->clkcon);
+   debug("%s: CLOCK_CONTROL = 0x%04X\n", __func__, clk_con);
+   clk_con &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
+   writew(clk_con, &priv->reg->clkcon);
+
val = readl(&priv->reg->autocalcfg);
val &= 0x;
-   val |= AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET | AUTO_CAL_ENABLED;