[PATCH] sunxi: mmc: Improve reset procedure
Andre Przywara
andre.przywara at arm.com
Tue Mar 25 02:16:41 CET 2025
On Sun, 9 Mar 2025 07:12:41 +0100
Jernej Skrabec <jernej.skrabec at gmail.com> wrote:
Hi Jernej,
many thanks for your investigation and this fix here! Not having
working eMMC access was a major annoyance for those TV boxes, and this
indeed seems to be fixed now, judging by my experiments. Also checked
boot partition access, works fine (though data partitions seem to take
precedence on most devices).
> Cards should always be reset and threshold set. This fixes eMMC on H616.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
Acked-by: Andre Przywara <andre.przywara at arm.com>
Cheers,
Andre
> ---
> drivers/mmc/sunxi_mmc.c | 28 ++++++++++++++++++++++------
> drivers/mmc/sunxi_mmc.h | 15 +++++++++++++--
> 2 files changed, 35 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
> index 0b56d1405bee..335def4b9738 100644
> --- a/drivers/mmc/sunxi_mmc.c
> +++ b/drivers/mmc/sunxi_mmc.c
> @@ -442,6 +442,26 @@ out:
> return error;
> }
>
> +static void sunxi_mmc_reset(struct sunxi_mmc *regs)
> +{
> + /* Reset controller */
> + writel(SUNXI_MMC_GCTRL_RESET, ®s->gctrl);
> + udelay(1000);
> +
> + if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
> + /* Reset card */
> + writel(SUNXI_MMC_HWRST_ASSERT, ®s->hwrst);
> + udelay(10);
> + writel(SUNXI_MMC_HWRST_DEASSERT, ®s->hwrst);
> + udelay(300);
> +
> + /* Setup FIFO R/W threshold. Needed on H616. */
> + writel(SUNXI_MMC_THLDC_READ_THLD(512) |
> + SUNXI_MMC_THLDC_WRITE_EN |
> + SUNXI_MMC_THLDC_READ_EN, ®s->thldc);
> + }
> +}
> +
> /* non-DM code here is used by the (ARM) SPL only */
>
> #if !CONFIG_IS_ENABLED(DM_MMC)
> @@ -489,9 +509,7 @@ static int sunxi_mmc_core_init(struct mmc *mmc)
> {
> struct sunxi_mmc_priv *priv = mmc->priv;
>
> - /* Reset controller */
> - writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
> - udelay(1000);
> + sunxi_mmc_reset(priv->reg);
>
> return 0;
> }
> @@ -684,9 +702,7 @@ static int sunxi_mmc_probe(struct udevice *dev)
>
> upriv->mmc = &plat->mmc;
>
> - /* Reset controller */
> - writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
> - udelay(1000);
> + sunxi_mmc_reset(priv->reg);
>
> return 0;
> }
> diff --git a/drivers/mmc/sunxi_mmc.h b/drivers/mmc/sunxi_mmc.h
> index f4ae5a790c87..9d55904c213c 100644
> --- a/drivers/mmc/sunxi_mmc.h
> +++ b/drivers/mmc/sunxi_mmc.h
> @@ -37,7 +37,9 @@ struct sunxi_mmc {
> u32 res0; /* 0x54 reserved */
> u32 a12a; /* 0x58 Auto command 12 argument */
> u32 ntsr; /* 0x5c New timing set register */
> - u32 res1[8];
> + u32 res1[6];
> + u32 hwrst; /* 0x78 Hardware Reset */
> + u32 res5;
> u32 dmac; /* 0x80 internal DMA control */
> u32 dlba; /* 0x84 internal DMA descr list base address */
> u32 idst; /* 0x88 internal DMA status */
> @@ -46,7 +48,8 @@ struct sunxi_mmc {
> u32 cbda; /* 0x94 */
> u32 res2[26];
> #if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
> - u32 res3[17];
> + u32 thldc; /* 0x100 Threshold control */
> + u32 res3[16];
> u32 samp_dl;
> u32 res4[46];
> #endif
> @@ -123,6 +126,9 @@ struct sunxi_mmc {
>
> #define SUNXI_MMC_NTSR_MODE_SEL_NEW (0x1 << 31)
>
> +#define SUNXI_MMC_HWRST_ASSERT (0x0 << 0)
> +#define SUNXI_MMC_HWRST_DEASSERT (0x1 << 0)
> +
> #define SUNXI_MMC_IDMAC_RESET (0x1 << 0)
> #define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1)
> #define SUNXI_MMC_IDMAC_ENABLE (0x1 << 7)
> @@ -133,6 +139,11 @@ struct sunxi_mmc {
> #define SUNXI_MMC_COMMON_CLK_GATE (1 << 16)
> #define SUNXI_MMC_COMMON_RESET (1 << 18)
>
> +#define SUNXI_MMC_THLDC_READ_EN (0x1 << 0)
> +#define SUNXI_MMC_THLDC_BSY_CLR_INT_EN (0x1 << 1)
> +#define SUNXI_MMC_THLDC_WRITE_EN (0x1 << 2)
> +#define SUNXI_MMC_THLDC_READ_THLD(x) (((x) & 0xfff) << 16)
> +
> #define SUNXI_MMC_CAL_DL_SW_EN (0x1 << 7)
>
> #endif /* _SUNXI_MMC_H */
More information about the U-Boot
mailing list