Re: [PATCH RFC] mmc: sdhci-msm: Toggle fifo write clk after ungating sdcc clk

From: Sayali Lokhande
Date: Fri Feb 28 2020 - 01:55:19 EST


Hi Veera,

On 2/24/2020 7:19 PM, Veerabhadrarao Badiganti wrote:

On 2/20/2020 2:50 PM, Sayali Lokhande wrote:
From: Ram Prakash Gupta <rampraka@xxxxxxxxxxxxxx>

During GCC level clock gating of MCLK, the async FIFO
gets into some hang condition, such that for the next
transfer after MCLK ungating, first bit of CMD response
doesn't get written in to the FIFO. This cause the CPSM
to hang eventually leading to SW timeout.

To fix the issue, toggle the FIFO write clock after
MCLK ungated to get the FIFO pointers and flags to
valid states.

Change-Id: Ibef2d1d283ac0b6983c609a4abc98bc574d31fa6
Signed-off-by: Ram Prakash Gupta <rampraka@xxxxxxxxxxxxxx>
Signed-off-by: Sayali Lokhande <sayalil@xxxxxxxxxxxxxx>
---
 drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c3a160c..eaa3e95 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -127,6 +127,8 @@
 #define CQHCI_VENDOR_CFG1 0xA00
 #define CQHCI_VENDOR_DIS_RST_ON_CQ_EN (0x3 << 13)
 +#define RCLK_TOGGLE 0x2
+
 struct sdhci_msm_offset {
ÂÂÂÂÂ u32 core_hc_mode;
ÂÂÂÂÂ u32 core_mci_data_cnt;
@@ -1554,6 +1556,43 @@ static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
ÂÂÂÂÂ sdhci_enable_clk(host, clk);
 }
 +/*
+ * After MCLK ugating, toggle the FIFO write clock to get
+ * the FIFO pointers and flags to valid state.
+ */
+static void sdhci_msm_toggle_fifo_write_clk(struct sdhci_host *host)
+{
+ÂÂÂ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ÂÂÂ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+ÂÂÂ const struct sdhci_msm_offset *msm_offset =
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ msm_host->offset;
+ÂÂÂ struct mmc_card *card = host->mmc->card;
+
+ÂÂÂ if (msm_host->tuning_done ||
+ÂÂÂÂÂÂÂÂÂÂÂ (card && card->ext_csd.strobe_support &&
+ÂÂÂÂÂÂÂÂÂÂÂ card->host->ios.enhanced_strobe)) {

This issue is present on only HS400ES mode.

If(host->ios.enhanced_strob) check should be sufficient, other checks are not needed.
Agree, Will update.

+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * set HC_REG_DLL_CONFIG_3[1] to select MCLK as
+ÂÂÂÂÂÂÂÂ * DLL input clock
+ÂÂÂÂÂÂÂÂ */
+ÂÂÂÂÂÂÂ writel_relaxed(((readl_relaxed(host->ioaddr +
+ÂÂÂÂÂÂÂÂÂÂÂ msm_offset->core_dll_config_3))
+ÂÂÂÂÂÂÂÂÂÂÂ | RCLK_TOGGLE), host->ioaddr +
+ÂÂÂÂÂÂÂÂÂÂÂ msm_offset->core_dll_config_3);
+ÂÂÂÂÂÂÂ /* ensure above write as toggling same bit quickly */
+ÂÂÂÂÂÂÂ wmb();
+ÂÂÂÂÂÂÂ udelay(2);
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * clear HC_REG_DLL_CONFIG_3[1] to select RCLK as
+ÂÂÂÂÂÂÂÂ * DLL input clock
+ÂÂÂÂÂÂÂÂ */
+ÂÂÂÂÂÂÂ writel_relaxed(((readl_relaxed(host->ioaddr +
+ÂÂÂÂÂÂÂÂÂÂÂ msm_offset->core_dll_config_3))
+ÂÂÂÂÂÂÂÂÂÂÂ & ~RCLK_TOGGLE), host->ioaddr +
+ÂÂÂÂÂÂÂÂÂÂÂ msm_offset->core_dll_config_3);
+ÂÂÂ }
+}
+
 /* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
 static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 {
@@ -2149,6 +2188,10 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ msm_host->bulk_clks);
ÂÂÂÂÂ if (ret)
ÂÂÂÂÂÂÂÂÂ return ret;
+ÂÂÂ if (host->mmc &&
+ÂÂÂÂÂÂÂÂÂÂÂ (host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
These checks are not needed. You can have these checks within sdhci_msm_toggle_fifo_write_clk
Agree. Will update.
+ sdhci_msm_toggle_fifo_write_clk(host);
+
ÂÂÂÂÂ /*
ÂÂÂÂÂÂ * Whenever core-clock is gated dynamically, it's needed to
ÂÂÂÂÂÂ * restore the SDR DLL settings when the clock is ungated.