From 3e78f8f407a0a0e7b50aa7eaa6f2f579f35e9837 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sun, 9 Mar 2025 07:12:41 +0100 Subject: [PATCH] sunxi: mmc: Improve reset procedure Cards should always be reset and threshold set. This fixes eMMC on H616. Signed-off-by: Jernej Skrabec [Andre: use macro-defined offsets to fix build on older SoCs] Signed-off-by: Andre Przywara --- drivers/mmc/sunxi_mmc.c | 28 ++++++++++++++++++++++------ drivers/mmc/sunxi_mmc.h | 18 ++++++++++++++++-- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 8f72d758e46..951e6acd34d 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -449,6 +449,26 @@ out: return error; } +static void sunxi_mmc_reset(void *regs) +{ + /* Reset controller */ + writel(SUNXI_MMC_GCTRL_RESET, regs + SUNXI_MMC_GCTRL); + udelay(1000); + + if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) { + /* Reset card */ + writel(SUNXI_MMC_HWRST_ASSERT, regs + SUNXI_MMC_HWRST); + udelay(10); + writel(SUNXI_MMC_HWRST_DEASSERT, regs + SUNXI_MMC_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, regs + SUNXI_MMC_THLDC); + } +} + /* non-DM code here is used by the (ARM) SPL only */ #if !CONFIG_IS_ENABLED(DM_MMC) @@ -496,9 +516,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; } @@ -691,9 +709,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 f4ae5a790c8..71865160319 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 @@ -57,6 +60,7 @@ struct sunxi_mmc { #define SUNXI_MMC_CLK_ENABLE (0x1 << 16) #define SUNXI_MMC_CLK_DIVIDER_MASK (0xff) +#define SUNXI_MMC_GCTRL 0x000 #define SUNXI_MMC_GCTRL_SOFT_RESET (0x1 << 0) #define SUNXI_MMC_GCTRL_FIFO_RESET (0x1 << 1) #define SUNXI_MMC_GCTRL_DMA_RESET (0x1 << 2) @@ -123,6 +127,10 @@ struct sunxi_mmc { #define SUNXI_MMC_NTSR_MODE_SEL_NEW (0x1 << 31) +#define SUNXI_MMC_HWRST 0x078 +#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 +141,12 @@ struct sunxi_mmc { #define SUNXI_MMC_COMMON_CLK_GATE (1 << 16) #define SUNXI_MMC_COMMON_RESET (1 << 18) +#define SUNXI_MMC_THLDC 0x100 +#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 */ -- 2.39.5