Skip to contentSkip to conversation

Toggle fifo write clk after ungating sdcc clk

RFC PATCH In review Sayali Lokhande 4 participants 7 messages Feb 20, 2020 – Feb 28, 2020

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 Toggle fifo write clk after ungating sdcc clk

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.

Ram Prakash Gupta (1):
mmc: sdhci-msm: Toggle fifo write clk after ungating sdcc clk

 drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#1 lore raw

RFC PATCH 1/1 mmc: sdhci-msm: Toggle fifo write clk after ungating sdcc clk

From: Ram Prakash Gupta <[email protected]>

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
---
 drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
drivers/mmc/host/sdhci-msm.c +43 -0
index c3a160c..eaa3e95 100644
@@ -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)) {
+		/*
+		 * 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))
+		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.
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#2 lore raw

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

Quoted 7 lines · Sayali Lokhande

From: Ram Prakash Gupta <[email protected]>

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.

Does this always happen, on what platforms does this happen? How does this manifest itself? Can you please elaborate.

Quoted 6 lines

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

Please drop the Change-Id and please add

If this is a bug fix that should be backported to e.g. 5.4.

Quoted 11 lines
---
 drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
drivers/mmc/host/sdhci-msm.c +0 -0
index c3a160c..eaa3e95 100644

drivers/mmc/host/sdhci-msm.c line 130

Quoted 4 lines
drivers/mmc/host/sdhci-msm.c +1 -0
@@ -127,6 +127,8 @@
 #define CQHCI_VENDOR_CFG1	0xA00
 #define CQHCI_VENDOR_DIS_RST_ON_CQ_EN	(0x3 << 13)
 
+#define RCLK_TOGGLE 0x2

Please use BIT(1) instead.

Quoted 8 lines
drivers/mmc/host/sdhci-msm.c +1 -0
+
 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);
 }
 

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1568

Quoted 10 lines
drivers/mmc/host/sdhci-msm.c +10 -0
+/*
+ * 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;

This doesn't look to be > 80 chars, please unwrap.

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1576

Quoted 8 lines
drivers/mmc/host/sdhci-msm.c +8 -0
+	struct mmc_card *card = host->mmc->card;
+
+	if (msm_host->tuning_done ||
+			(card && card->ext_csd.strobe_support &&
+			card->host->ios.enhanced_strobe)) {
+		/*
+		 * set HC_REG_DLL_CONFIG_3[1] to select MCLK as
+		 * DLL input clock

You can shorten this to /* Select MCLK as DLL input clock */ if you make the below readl/writel a little bit easier to read.

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1581

Quoted 5 lines
drivers/mmc/host/sdhci-msm.c +5 -0
+		 */
+		writel_relaxed(((readl_relaxed(host->ioaddr +
+			msm_offset->core_dll_config_3))
+			| RCLK_TOGGLE), host->ioaddr +
+			msm_offset->core_dll_config_3);

Please use a local variable and write this out as:

		val = readl(addr);
		val |= RCLK_TOGGLE;
		writel(val, addr);

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1583

Quoted 2 lines
drivers/mmc/host/sdhci-msm.c +2 -0
+		/* ensure above write as toggling same bit quickly */
+		wmb();

This ensures ordering of writes, if you want to make sure the write has hit the hardware before the delay perform a readl() on the address.

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1588

Quoted 5 lines
drivers/mmc/host/sdhci-msm.c +5 -0
+		udelay(2);
+		/*
+		 * clear HC_REG_DLL_CONFIG_3[1] to select RCLK as
+		 * DLL input clock
+		 */
		/* Select RCLK as DLL input clock */

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1592

Quoted 4 lines
drivers/mmc/host/sdhci-msm.c +4 -0
+		writel_relaxed(((readl_relaxed(host->ioaddr +
+			msm_offset->core_dll_config_3))
+			& ~RCLK_TOGGLE), host->ioaddr +
+			msm_offset->core_dll_config_3);

Same as above, readl(); val &= ~RCLK_TOGGLE; writel(); will make this easier on the eyes.

drivers/mmc/host/sdhci-msm.c static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) · line 2190

Quoted 10 lines
drivers/mmc/host/sdhci-msm.c +3 -0
+	}
+}
+
 /* 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;

An empty line please.

drivers/mmc/host/sdhci-msm.c static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) · line 2191

Quoted 1 line
drivers/mmc/host/sdhci-msm.c +1 -0
+	if (host->mmc &&

Afaict host->mmc can't be NULL, can you please confirm that you need this check.

drivers/mmc/host/sdhci-msm.c static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) · line 2194

Quoted 3 lines
drivers/mmc/host/sdhci-msm.c +3 -0
+			(host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
+		sdhci_msm_toggle_fifo_write_clk(host);
+

Regards,
Bjorn

Quoted 6 lines
drivers/mmc/host/sdhci-msm.c +0 -0
 	/*
 	 * Whenever core-clock is gated dynamically, it's needed to
 	 * restore the SDR DLL settings when the clock is ungated.
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#3 lore raw

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

In reply to Sayali Lokhande

Quoting Sayali Lokhande (2020-02-20 01:20:46)

Quoted 3 lines

From: Ram Prakash Gupta <[email protected]>

During GCC level clock gating of MCLK, the async FIFO

Is this automatic hardware clock gating?

Quoted 21 lines

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
---
 drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
drivers/mmc/host/sdhci-msm.c +0 -0
index c3a160c..eaa3e95 100644

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1560

Quoted 5 lines
drivers/mmc/host/sdhci-msm.c +2 -0
@@ -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

What is ugating?

Quoted 17 lines
drivers/mmc/host/sdhci-msm.c +17 -0
+ * 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)) {
+               /*
+                * set HC_REG_DLL_CONFIG_3[1] to select MCLK as
+                * DLL input clock
+                */
#4 lore raw

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

In reply to Sayali Lokhande
Quoted 41 lines · Sayali Lokhande

From: Ram Prakash Gupta <[email protected]>

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
---
  drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 43 insertions(+)
drivers/mmc/host/sdhci-msm.c +7 -0
index c3a160c..eaa3e95 100644
@@ -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)

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1573

Quoted 10 lines
drivers/mmc/host/sdhci-msm.c +10 -0
+{
+	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.

Quoted 26 lines
drivers/mmc/host/sdhci-msm.c +22 -0
+		/*
+		 * 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)
  {

drivers/mmc/host/sdhci-msm.c static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) · line 2192

Quoted 5 lines
drivers/mmc/host/sdhci-msm.c +2 -0
@@ -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

Quoted 5 lines
drivers/mmc/host/sdhci-msm.c +2 -0
+		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.
#5 lore raw

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

Hi Veera,

Quoted 56 lines · Veerabhadrarao Badiganti
Quoted 41 lines · Sayali Lokhande

From: Ram Prakash Gupta <[email protected]>

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

---
  drivers/mmc/host/sdhci-msm.c | 43
+++++++++++++++++++++++++++++++++++++++++++

  1 file changed, 43 insertions(+)
drivers/mmc/host/sdhci-msm.c +0 -0
index c3a160c..eaa3e95 100644
@@ -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;

drivers/mmc/host/sdhci-msm.c +0 -0
@@ -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.
+ */

drivers/mmc/host/sdhci-msm.c +1 -0
+static void sdhci_msm_toggle_fifo_write_clk(struct sdhci_host *host)

drivers/mmc/host/sdhci-msm.c static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) · line 1573

Quoted 10 lines
drivers/mmc/host/sdhci-msm.c +10 -0
+{
+    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.

Quoted 1 line

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

Agree, Will update.

Quoted 26 lines
Quoted 26 lines

+        /*
+         * 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);
+    }

drivers/mmc/host/sdhci-msm.c +2 -0
+}
+

  /* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) {

Quoted 8 lines

drivers/mmc/host/sdhci-msm.c static __maybe_unused int · line 2193

Quoted 7 lines
drivers/mmc/host/sdhci-msm.c +2 -0
@@ -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.

Quoted 5 lines
Quoted 5 lines
drivers/mmc/host/sdhci-msm.c +2 -0
+ 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.

#6 lore raw
In reply to Sayali Lokhande
Quoted 10 lines · Sayali Lokhande

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.

Please don't provide cover letters for a single patch.

Regards,
Bjorn

Quoted 9 lines

Ram Prakash Gupta (1):
mmc: sdhci-msm: Toggle fifo write clk after ungating sdcc clk

 drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project