On Sat, Aug 19, 2023 at 06:35:01PM +0300, Svyatoslav Ryhel wrote:
> Default-tap and default-trim values are used for eMMC setup
> mostly on T114+ devices. As for now, those values are hardcoded
> for T210 and ignored for all other Tegra generations. Fix this
> by passing tap and trim values from dts.
> 
> Tested-by: Svyatoslav Ryhel <clamo...@gmail.com> # ASUS TF701T
> Signed-off-by: Svyatoslav Ryhel <clamo...@gmail.com>
> ---
>  arch/arm/include/asm/arch-tegra/tegra_mmc.h | 17 ++++----
>  drivers/mmc/tegra_mmc.c                     | 46 ++++++++++-----------
>  2 files changed, 30 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h 
> b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> index d6a55764ba..750c7d809e 100644
> --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> @@ -128,21 +128,22 @@ struct tegra_mmc {
>  
>  /* SDMMC1/3 settings from SDMMCx Initialization Sequence of TRM */
>  #define MEMCOMP_PADCTRL_VREF 7
> -#define AUTO_CAL_ENABLE              (1 << 29)
> -#define AUTO_CAL_ACTIVE              (1 << 31)
> -#define AUTO_CAL_START               (1 << 31)
> +#define AUTO_CAL_ENABLE              BIT(29)
> +#define AUTO_CAL_ACTIVE              BIT(31)
> +#define AUTO_CAL_START               BIT(31)
> +
>  #if defined(CONFIG_TEGRA210)
>  #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
>  
> +#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)
> +
>  #endif       /* __ASSEMBLY__ */
>  #endif       /* __TEGRA_MMC_H_ */
> diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
> index f76fee3ea0..7627800261 100644
> --- a/drivers/mmc/tegra_mmc.c
> +++ b/drivers/mmc/tegra_mmc.c
> @@ -37,6 +37,9 @@ struct tegra_mmc_priv {
>       unsigned int version;   /* SDHCI spec. version */
>       unsigned int clock;     /* Current clock (MHz) */
>       int mmc_id;             /* peripheral id */
> +
> +     u32 tap_value;
> +     u32 trim_value;
>  };
>  
>  static void tegra_mmc_set_power(struct tegra_mmc_priv *priv,
> @@ -526,31 +529,6 @@ static void tegra_mmc_pad_init(struct tegra_mmc_priv 
> *priv)
>               printf("%s: Warning: Autocal timed out!\n", __func__);
>               /* TBD: Set CFG2TMC_SDMMC1_PAD_CAL_DRV* regs here */
>       }
> -
> -#if defined(CONFIG_TEGRA210)
> -     u32 tap_value, trim_value;
> -
> -     /* Set tap/trim values for SDMMC1/3 @ <48MHz here */
> -     val = readl(&priv->reg->venspictl);     /* aka VENDOR_SYS_SW_CNTL */
> -     val &= IO_TRIM_BYPASS_MASK;
> -     if (id == PERIPH_ID_SDMMC1) {
> -             tap_value = 4;                  /* default */
> -             if (val)
> -                     tap_value = 3;
> -             trim_value = 2;
> -     } else {                                /* SDMMC3 */
> -             tap_value = 3;
> -             trim_value = 3;
> -     }
> -
> -     val = readl(&priv->reg->venclkctl);
> -     val &= ~TRIM_VAL_MASK;
> -     val |= (trim_value << TRIM_VAL_SHIFT);
> -     val &= ~TAP_VAL_MASK;
> -     val |= (tap_value << TAP_VAL_SHIFT);
> -     writel(val, &priv->reg->venclkctl);
> -     debug("%s: VENDOR_CLOCK_CNTRL = 0x%08X\n", __func__, val);
> -#endif       /* T210 */
>  #endif       /* T30/T210 */
>  }
>  
> @@ -588,6 +566,21 @@ static void tegra_mmc_reset(struct tegra_mmc_priv *priv, 
> struct mmc *mmc)
>  
>       /* Make sure SDIO pads are set up */
>       tegra_mmc_pad_init(priv);
> +
> +     if (priv->tap_value || priv->trim_value) {

I think 0 is a valid value for both tap and trim, so you want to be able
to write that. I suggest getting rid of the conditional and always
writing these values and rely on defaults to make sure that a good value
is always programmed.

Alternatively if you really only want to program these when they've been
specified, use an extra variable (or something like -1 as a default
value) to discriminate.

The former is superior, in my opinion, because it also allows to avoid
to regression.

Thierry

> +             u32 val;
> +
> +             val = readl(&priv->reg->venclkctl);
> +
> +             val &= ~TRIM_VAL_MASK;
> +             val |= (priv->trim_value << TRIM_VAL_SHIFT);
> +
> +             val &= ~TAP_VAL_MASK;
> +             val |= (priv->tap_value << TAP_VAL_SHIFT);
> +
> +             writel(val, &priv->reg->venclkctl);
> +             debug("%s: VENDOR_CLOCK_CNTRL = 0x%08X\n", __func__, val);
> +     }
>  }
>  
>  static int tegra_mmc_init(struct udevice *dev)
> @@ -742,6 +735,9 @@ static int tegra_mmc_probe(struct udevice *dev)
>       if (dm_gpio_is_valid(&priv->pwr_gpio))
>               dm_gpio_set_value(&priv->pwr_gpio, 1);
>  
> +     priv->tap_value = dev_read_u32_default(dev, "nvidia,default-tap", 0);
> +     priv->trim_value = dev_read_u32_default(dev, "nvidia,default-trim", 0);
> +
>       upriv->mmc = &plat->mmc;
>  
>       return tegra_mmc_init(dev);
> -- 
> 2.39.2
> 

Attachment: signature.asc
Description: PGP signature

Reply via email to