summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWenchao Chen <wenchao.chen@unisoc.com>2023-12-04 14:49:34 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-01-15 18:48:07 +0100
commitae64985e0e9c5de50d54c51105144aa1475dfe18 (patch)
treec06c6891040b0b5d6a761211ca2ebd9d6306f82b
parentf7796d76bdddf052171ee05f79570826eabf1fd0 (diff)
downloadlinux-ae64985e0e9c5de50d54c51105144aa1475dfe18.tar.gz
linux-ae64985e0e9c5de50d54c51105144aa1475dfe18.tar.bz2
linux-ae64985e0e9c5de50d54c51105144aa1475dfe18.zip
mmc: sdhci-sprd: Fix eMMC init failure after hw reset
commit 8abf77c88929b6d20fa4f9928b18d6448d64e293 upstream. Some eMMC devices that do not close the auto clk gate after hw reset will cause eMMC initialization to fail. Let's fix this. Signed-off-by: Wenchao Chen <wenchao.chen@unisoc.com> Fixes: ff874dbc4f86 ("mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K") Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20231204064934.21236-1-wenchao.chen@unisoc.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/mmc/host/sdhci-sprd.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
index d8e412bbb93b..52bfe356f1e5 100644
--- a/drivers/mmc/host/sdhci-sprd.c
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -224,15 +224,19 @@ static inline void _sdhci_sprd_set_clock(struct sdhci_host *host,
div = ((div & 0x300) >> 2) | ((div & 0xFF) << 8);
sdhci_enable_clk(host, div);
+ val = sdhci_readl(host, SDHCI_SPRD_REG_32_BUSY_POSI);
+ mask = SDHCI_SPRD_BIT_OUTR_CLK_AUTO_EN | SDHCI_SPRD_BIT_INNR_CLK_AUTO_EN;
/* Enable CLK_AUTO when the clock is greater than 400K. */
if (clk > 400000) {
- val = sdhci_readl(host, SDHCI_SPRD_REG_32_BUSY_POSI);
- mask = SDHCI_SPRD_BIT_OUTR_CLK_AUTO_EN |
- SDHCI_SPRD_BIT_INNR_CLK_AUTO_EN;
if (mask != (val & mask)) {
val |= mask;
sdhci_writel(host, val, SDHCI_SPRD_REG_32_BUSY_POSI);
}
+ } else {
+ if (val & mask) {
+ val &= ~mask;
+ sdhci_writel(host, val, SDHCI_SPRD_REG_32_BUSY_POSI);
+ }
}
}