Re: [PATCH 1/2] mmc: t210: Add autocal and tap/trim updates for SDMMC1/3
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
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
[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
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
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;