Skip to contentSkip to conversation

mmc: sdhci-msm: Provide support for enhanced strobe

PATCH RESEND In review Ritesh Harjani 5 participants 24 messages Jan 10, 2017 – Jan 24, 2017

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

cover mmc: sdhci-msm: Provide support for enhanced strobe

Hi,

Resending this patch series, as no one could review it -possibly due to holidays during that time.

This patch series mainly provides enhanced strobe support to sdhci-msm driver along with some additions of HW recommended sequence. This has been tested on 8996 based internal target & on db410c.

Patches 1-3 :- Factors out few functions to be re-used again.
To also simplify large functions and makes it more readable.

Patches 4-5 :- Few recommendations based on HW prog. guide.

Patches 6 :- Clear SDHCI_HS400_TUNING flag after platform_execute_tuning

	     so that ->platform_execute_tuning (underlying platform driver) can
	     know about HS400 tuning.

Patch 7 :- Implements an additional step as per HPG for HS400 tuning.

Patch 8 :- Implements enhanced strobe functionality in sdhci-msm driver.

Ritesh Harjani (6):
mmc: sdhci-msm: Factor out sdhci_msm_hc_select_mode
mmc: sdhci-msm: Factor out function to set/get msm clock rate
mmc: sdhci-msm: Factor out sdhci_msm_hs400
mmc: sdhci: Clear SDHCI_HS400_TUNING flag after
platform_execute_tuning
mmc: sdhci-msm: Make HS400 tuning follow as per recommeneded HW
sequence
mmc: sdhci-msm: Provide enhanced_strobe mode feature support

Subhash Jadavani (1):
mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

Venkat Gopalakrishnan (1):
mmc: sdhci-msm: Reset vendor specific func register on probe

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

PATCH RESEND 1/8 mmc: sdhci-msm: Factor out sdhci_msm_hc_select_mode

This factors out sdhci_msm_hc_select_mode to later use it during enhanced_strobe mode select.
It also further breaks sdhci_msm_hc_select_mode into separate functions for configuring HS400 mode or other modes.

---
 drivers/mmc/host/sdhci-msm.c | 201 ++++++++++++++++++++++++-------------------
 1 file changed, 114 insertions(+), 87 deletions(-)
drivers/mmc/host/sdhci-msm.c +114 -87
index 32879b8..1e42647 100644
@@ -464,6 +464,119 @@ static int msm_init_cm_dll(struct sdhci_host *host)
 	return 0;
 }
 
+static void msm_hc_select_default(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	u32 config;
+
+	if (!msm_host->use_cdclp533) {
+		config = readl_relaxed(host->ioaddr +
+				CORE_VENDOR_SPEC3);
+		config &= ~CORE_PWRSAVE_DLL;
+		writel_relaxed(config, host->ioaddr +
+				CORE_VENDOR_SPEC3);
+	}
+
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+	config &= ~CORE_HC_MCLK_SEL_MASK;
+	config |= CORE_HC_MCLK_SEL_DFLT;
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+	/*
+	 * Disable HC_SELECT_IN to be able to use the UHS mode select
+	 * configuration from Host Control2 register for all other
+	 * modes.
+	 * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
+	 * in VENDOR_SPEC_FUNC
+	 */
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+	config &= ~CORE_HC_SELECT_IN_EN;
+	config &= ~CORE_HC_SELECT_IN_MASK;
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+	/*
+	 * Make sure above writes impacting free running MCLK are completed
+	 * before changing the clk_rate at GCC.
+	 */
+	wmb();
+}
+
+static void msm_hc_select_hs400(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	u32 config, dll_lock;
+	int rc;
+
+	/* Select the divided clock (free running MCLK/2) */
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+	config &= ~CORE_HC_MCLK_SEL_MASK;
+	config |= CORE_HC_MCLK_SEL_HS400;
+
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+	/*
+	 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
+	 * register
+	 */
+	if (msm_host->tuning_done && !msm_host->calibration_done) {
+		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+		config |= CORE_HC_SELECT_IN_HS400;
+		config |= CORE_HC_SELECT_IN_EN;
+		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+	}
+	if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
+		/*
+		 * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
+		 * CORE_DLL_STATUS to be set.  This should get set
+		 * within 15 us at 200 MHz.
+		 */
+		rc = readl_relaxed_poll_timeout(host->ioaddr +
+						CORE_DLL_STATUS,
+						dll_lock,
+						(dll_lock &
+						(CORE_DLL_LOCK |
+						CORE_DDR_DLL_LOCK)), 10,
+						1000);
+		if (rc == -ETIMEDOUT)
+			pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
+			       mmc_hostname(host->mmc), dll_lock);
+	}
+	/*
+	 * Make sure above writes impacting free running MCLK are completed
+	 * before changing the clk_rate at GCC.
+	 */
+	wmb();
+}
+
+/*
+ * sdhci_msm_hc_select_mode :- In general all timing modes are
+ * controlled via UHS mode select in Host Control2 register.
+ * eMMC specific HS200/HS400 doesn't have their respective modes
+ * defined here, hence we use these values.
+ *
+ * HS200 - SDR104 (Since they both are equivalent in functionality)
+ * HS400 - This involves multiple configurations
+ *		Initially SDR104 - when tuning is required as HS200
+ *		Then when switching to DDR @ 400MHz (HS400) we use
+ *		the vendor specific HC_SELECT_IN to control the mode.
+ *
+ * In addition to controlling the modes we also need to select the
+ * correct input clock for DLL depending on the mode.
+ *
+ * HS400 - divided clock (free running MCLK/2)
+ * All other modes - default (free running MCLK)
+ */
+void sdhci_msm_hc_select_mode(struct sdhci_host *host)
+{
+	struct mmc_ios ios = host->mmc->ios;
+
+	if (ios.timing == MMC_TIMING_MMC_HS400)
+		msm_hc_select_hs400(host);
+	else
+		msm_hc_select_default(host);
+}
+
 static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -894,7 +1007,6 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 	struct mmc_ios curr_ios = host->mmc->ios;
-	u32 config, dll_lock;
 	int rc;
 
 	if (!clock) {
@@ -913,93 +1025,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 	    curr_ios.timing == MMC_TIMING_MMC_DDR52 ||
 	    curr_ios.timing == MMC_TIMING_MMC_HS400)
 		clock *= 2;
-	/*
-	 * In general all timing modes are controlled via UHS mode select in
-	 * Host Control2 register. eMMC specific HS200/HS400 doesn't have
-	 * their respective modes defined here, hence we use these values.
-	 *
-	 * HS200 - SDR104 (Since they both are equivalent in functionality)
-	 * HS400 - This involves multiple configurations
-	 *		Initially SDR104 - when tuning is required as HS200
-	 *		Then when switching to DDR @ 400MHz (HS400) we use
-	 *		the vendor specific HC_SELECT_IN to control the mode.
-	 *
-	 * In addition to controlling the modes we also need to select the
-	 * correct input clock for DLL depending on the mode.
-	 *
-	 * HS400 - divided clock (free running MCLK/2)
-	 * All other modes - default (free running MCLK)
-	 */
-	if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
-		/* Select the divided clock (free running MCLK/2) */
-		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-		config &= ~CORE_HC_MCLK_SEL_MASK;
-		config |= CORE_HC_MCLK_SEL_HS400;
 
-		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-		/*
-		 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
-		 * register
-		 */
-		if (msm_host->tuning_done && !msm_host->calibration_done) {
-			/*
-			 * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
-			 * field in VENDOR_SPEC_FUNC
-			 */
-			config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-			config |= CORE_HC_SELECT_IN_HS400;
-			config |= CORE_HC_SELECT_IN_EN;
-			writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-		}
-		if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
-			/*
-			 * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
-			 * CORE_DLL_STATUS to be set.  This should get set
-			 * within 15 us at 200 MHz.
-			 */
-			rc = readl_relaxed_poll_timeout(host->ioaddr +
-							CORE_DLL_STATUS,
-							dll_lock,
-							(dll_lock &
-							(CORE_DLL_LOCK |
-							CORE_DDR_DLL_LOCK)), 10,
-							1000);
-			if (rc == -ETIMEDOUT)
-				pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
-				       mmc_hostname(host->mmc), dll_lock);
-		}
-	} else {
-		if (!msm_host->use_cdclp533) {
-			config = readl_relaxed(host->ioaddr +
-					CORE_VENDOR_SPEC3);
-			config &= ~CORE_PWRSAVE_DLL;
-			writel_relaxed(config, host->ioaddr +
-					CORE_VENDOR_SPEC3);
-		}
-
-		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-		config &= ~CORE_HC_MCLK_SEL_MASK;
-		config |= CORE_HC_MCLK_SEL_DFLT;
-		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-
-		/*
-		 * Disable HC_SELECT_IN to be able to use the UHS mode select
-		 * configuration from Host Control2 register for all other
-		 * modes.
-		 * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
-		 * in VENDOR_SPEC_FUNC
-		 */
-		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-		config &= ~CORE_HC_SELECT_IN_EN;
-		config &= ~CORE_HC_SELECT_IN_MASK;
-		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-	}
-
-	/*
-	 * Make sure above writes impacting free running MCLK are completed
-	 * before changing the clk_rate at GCC.
-	 */
-	wmb();
+	sdhci_msm_hc_select_mode(host);
 
 	rc = clk_set_rate(msm_host->clk, clock);
 	if (rc) {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer Acked-by on v1 1/8
#2 lore raw

Re: [RESEND PATCHv1 1/8] mmc: sdhci-msm: Factor out sdhci_msm_hc_select_mode

Quoted 7 lines · Ritesh Harjani

This factors out sdhci_msm_hc_select_mode to later use it during enhanced_strobe mode select.
It also further breaks sdhci_msm_hc_select_mode into separate functions for configuring HS400 mode or other modes.

Quoted 232 lines
---
 drivers/mmc/host/sdhci-msm.c | 201 ++++++++++++++++++++++++-------------------
 1 file changed, 114 insertions(+), 87 deletions(-)
drivers/mmc/host/sdhci-msm.c +114 -87
index 32879b8..1e42647 100644
@@ -464,6 +464,119 @@ static int msm_init_cm_dll(struct sdhci_host *host)
 	return 0;
 }
 
+static void msm_hc_select_default(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	u32 config;
+
+	if (!msm_host->use_cdclp533) {
+		config = readl_relaxed(host->ioaddr +
+				CORE_VENDOR_SPEC3);
+		config &= ~CORE_PWRSAVE_DLL;
+		writel_relaxed(config, host->ioaddr +
+				CORE_VENDOR_SPEC3);
+	}
+
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+	config &= ~CORE_HC_MCLK_SEL_MASK;
+	config |= CORE_HC_MCLK_SEL_DFLT;
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+	/*
+	 * Disable HC_SELECT_IN to be able to use the UHS mode select
+	 * configuration from Host Control2 register for all other
+	 * modes.
+	 * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
+	 * in VENDOR_SPEC_FUNC
+	 */
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+	config &= ~CORE_HC_SELECT_IN_EN;
+	config &= ~CORE_HC_SELECT_IN_MASK;
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+	/*
+	 * Make sure above writes impacting free running MCLK are completed
+	 * before changing the clk_rate at GCC.
+	 */
+	wmb();
+}
+
+static void msm_hc_select_hs400(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	u32 config, dll_lock;
+	int rc;
+
+	/* Select the divided clock (free running MCLK/2) */
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+	config &= ~CORE_HC_MCLK_SEL_MASK;
+	config |= CORE_HC_MCLK_SEL_HS400;
+
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+	/*
+	 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
+	 * register
+	 */
+	if (msm_host->tuning_done && !msm_host->calibration_done) {
+		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+		config |= CORE_HC_SELECT_IN_HS400;
+		config |= CORE_HC_SELECT_IN_EN;
+		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+	}
+	if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
+		/*
+		 * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
+		 * CORE_DLL_STATUS to be set.  This should get set
+		 * within 15 us at 200 MHz.
+		 */
+		rc = readl_relaxed_poll_timeout(host->ioaddr +
+						CORE_DLL_STATUS,
+						dll_lock,
+						(dll_lock &
+						(CORE_DLL_LOCK |
+						CORE_DDR_DLL_LOCK)), 10,
+						1000);
+		if (rc == -ETIMEDOUT)
+			pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
+			       mmc_hostname(host->mmc), dll_lock);
+	}
+	/*
+	 * Make sure above writes impacting free running MCLK are completed
+	 * before changing the clk_rate at GCC.
+	 */
+	wmb();
+}
+
+/*
+ * sdhci_msm_hc_select_mode :- In general all timing modes are
+ * controlled via UHS mode select in Host Control2 register.
+ * eMMC specific HS200/HS400 doesn't have their respective modes
+ * defined here, hence we use these values.
+ *
+ * HS200 - SDR104 (Since they both are equivalent in functionality)
+ * HS400 - This involves multiple configurations
+ *		Initially SDR104 - when tuning is required as HS200
+ *		Then when switching to DDR @ 400MHz (HS400) we use
+ *		the vendor specific HC_SELECT_IN to control the mode.
+ *
+ * In addition to controlling the modes we also need to select the
+ * correct input clock for DLL depending on the mode.
+ *
+ * HS400 - divided clock (free running MCLK/2)
+ * All other modes - default (free running MCLK)
+ */
+void sdhci_msm_hc_select_mode(struct sdhci_host *host)
+{
+	struct mmc_ios ios = host->mmc->ios;
+
+	if (ios.timing == MMC_TIMING_MMC_HS400)
+		msm_hc_select_hs400(host);
+	else
+		msm_hc_select_default(host);
+}
+
 static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -894,7 +1007,6 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 	struct mmc_ios curr_ios = host->mmc->ios;
-	u32 config, dll_lock;
 	int rc;
 
 	if (!clock) {
@@ -913,93 +1025,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 	    curr_ios.timing == MMC_TIMING_MMC_DDR52 ||
 	    curr_ios.timing == MMC_TIMING_MMC_HS400)
 		clock *= 2;
-	/*
-	 * In general all timing modes are controlled via UHS mode select in
-	 * Host Control2 register. eMMC specific HS200/HS400 doesn't have
-	 * their respective modes defined here, hence we use these values.
-	 *
-	 * HS200 - SDR104 (Since they both are equivalent in functionality)
-	 * HS400 - This involves multiple configurations
-	 *		Initially SDR104 - when tuning is required as HS200
-	 *		Then when switching to DDR @ 400MHz (HS400) we use
-	 *		the vendor specific HC_SELECT_IN to control the mode.
-	 *
-	 * In addition to controlling the modes we also need to select the
-	 * correct input clock for DLL depending on the mode.
-	 *
-	 * HS400 - divided clock (free running MCLK/2)
-	 * All other modes - default (free running MCLK)
-	 */
-	if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
-		/* Select the divided clock (free running MCLK/2) */
-		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-		config &= ~CORE_HC_MCLK_SEL_MASK;
-		config |= CORE_HC_MCLK_SEL_HS400;
 
-		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-		/*
-		 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
-		 * register
-		 */
-		if (msm_host->tuning_done && !msm_host->calibration_done) {
-			/*
-			 * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
-			 * field in VENDOR_SPEC_FUNC
-			 */
-			config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-			config |= CORE_HC_SELECT_IN_HS400;
-			config |= CORE_HC_SELECT_IN_EN;
-			writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-		}
-		if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
-			/*
-			 * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
-			 * CORE_DLL_STATUS to be set.  This should get set
-			 * within 15 us at 200 MHz.
-			 */
-			rc = readl_relaxed_poll_timeout(host->ioaddr +
-							CORE_DLL_STATUS,
-							dll_lock,
-							(dll_lock &
-							(CORE_DLL_LOCK |
-							CORE_DDR_DLL_LOCK)), 10,
-							1000);
-			if (rc == -ETIMEDOUT)
-				pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
-				       mmc_hostname(host->mmc), dll_lock);
-		}
-	} else {
-		if (!msm_host->use_cdclp533) {
-			config = readl_relaxed(host->ioaddr +
-					CORE_VENDOR_SPEC3);
-			config &= ~CORE_PWRSAVE_DLL;
-			writel_relaxed(config, host->ioaddr +
-					CORE_VENDOR_SPEC3);
-		}
-
-		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-		config &= ~CORE_HC_MCLK_SEL_MASK;
-		config |= CORE_HC_MCLK_SEL_DFLT;
-		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-
-		/*
-		 * Disable HC_SELECT_IN to be able to use the UHS mode select
-		 * configuration from Host Control2 register for all other
-		 * modes.
-		 * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
-		 * in VENDOR_SPEC_FUNC
-		 */
-		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
-		config &= ~CORE_HC_SELECT_IN_EN;
-		config &= ~CORE_HC_SELECT_IN_MASK;
-		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
-	}
-
-	/*
-	 * Make sure above writes impacting free running MCLK are completed
-	 * before changing the clk_rate at GCC.
-	 */
-	wmb();
+	sdhci_msm_hc_select_mode(host);
 
 	rc = clk_set_rate(msm_host->clk, clock);
 	if (rc) {
#3 lore raw

PATCH RESEND 2/8 mmc: sdhci-msm: Factor out function to set/get msm clock rate

In reply to Ritesh Harjani

Factor out msm_set/get_clock_rate_for_bus_mode for it's later use in changing the tuning sequence for selecting HS400 bus speed mode.

---
 drivers/mmc/host/sdhci-msm.c | 64 +++++++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 24 deletions(-)
drivers/mmc/host/sdhci-msm.c +40 -24
index 1e42647..3fc496e 100644
@@ -138,6 +138,45 @@ struct sdhci_msm_host {
 	bool use_cdclp533;
 };
 
+static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
+						    unsigned int clock)
+{
+	struct mmc_ios ios = host->mmc->ios;
+	/*
+	 * The SDHC requires internal clock frequency to be double the
+	 * actual clock that will be set for DDR mode. The controller
+	 * uses the faster clock(100/400MHz) for some of its parts and
+	 * send the actual required clock (50/200MHz) to the card.
+	 */
+	if (ios.timing == MMC_TIMING_UHS_DDR50 ||
+	    ios.timing == MMC_TIMING_MMC_DDR52 ||
+	    ios.timing == MMC_TIMING_MMC_HS400)
+		clock *= 2;
+	return clock;
+}
+
+static void msm_set_clock_rate_for_bus_mode(struct sdhci_host *host,
+					    unsigned int clock)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_ios curr_ios = host->mmc->ios;
+	int rc;
+
+	clock = msm_get_clock_rate_for_bus_mode(host, clock);
+	rc = clk_set_rate(msm_host->clk, clock);
+	if (rc) {
+		pr_err("%s: Failed to set clock at rate %u at timing %d\n",
+		       mmc_hostname(host->mmc), clock,
+		       curr_ios.timing);
+		return;
+	}
+	msm_host->clk_rate = clock;
+	pr_debug("%s: Setting clock at rate %lu at timing %d\n",
+		 mmc_hostname(host->mmc), clk_get_rate(msm_host->clk),
+		 curr_ios.timing);
+}
+
 /* Platform specific tuning */
 static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
 {
@@ -1006,8 +1045,6 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
-	struct mmc_ios curr_ios = host->mmc->ios;
-	int rc;
 
 	if (!clock) {
 		msm_host->clk_rate = clock;
@@ -1015,32 +1052,11 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 	}
 
 	spin_unlock_irq(&host->lock);
-	/*
-	 * The SDHC requires internal clock frequency to be double the
-	 * actual clock that will be set for DDR mode. The controller
-	 * uses the faster clock(100/400MHz) for some of its parts and
-	 * send the actual required clock (50/200MHz) to the card.
-	 */
-	if (curr_ios.timing == MMC_TIMING_UHS_DDR50 ||
-	    curr_ios.timing == MMC_TIMING_MMC_DDR52 ||
-	    curr_ios.timing == MMC_TIMING_MMC_HS400)
-		clock *= 2;
 
 	sdhci_msm_hc_select_mode(host);
 
-	rc = clk_set_rate(msm_host->clk, clock);
-	if (rc) {
-		pr_err("%s: Failed to set clock at rate %u at timing %d\n",
-		       mmc_hostname(host->mmc), clock,
-		       curr_ios.timing);
-		goto out_lock;
-	}
-	msm_host->clk_rate = clock;
-	pr_debug("%s: Setting clock at rate %lu at timing %d\n",
-		 mmc_hostname(host->mmc), clk_get_rate(msm_host->clk),
-		 curr_ios.timing);
+	msm_set_clock_rate_for_bus_mode(host, clock);
 
-out_lock:
 	spin_lock_irq(&host->lock);
 out:
 	__sdhci_msm_set_clock(host, clock);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer Acked-by on v1 2/8
#4 lore raw

Re: [RESEND PATCHv1 2/8] mmc: sdhci-msm: Factor out function to set/get msm clock rate

Quoted 5 lines · Ritesh Harjani

Factor out msm_set/get_clock_rate_for_bus_mode for it's later use in changing the tuning sequence for selecting HS400 bus speed mode.

Quoted 98 lines
---
 drivers/mmc/host/sdhci-msm.c | 64 +++++++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 24 deletions(-)
drivers/mmc/host/sdhci-msm.c +40 -24
index 1e42647..3fc496e 100644
@@ -138,6 +138,45 @@ struct sdhci_msm_host {
 	bool use_cdclp533;
 };
 
+static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
+						    unsigned int clock)
+{
+	struct mmc_ios ios = host->mmc->ios;
+	/*
+	 * The SDHC requires internal clock frequency to be double the
+	 * actual clock that will be set for DDR mode. The controller
+	 * uses the faster clock(100/400MHz) for some of its parts and
+	 * send the actual required clock (50/200MHz) to the card.
+	 */
+	if (ios.timing == MMC_TIMING_UHS_DDR50 ||
+	    ios.timing == MMC_TIMING_MMC_DDR52 ||
+	    ios.timing == MMC_TIMING_MMC_HS400)
+		clock *= 2;
+	return clock;
+}
+
+static void msm_set_clock_rate_for_bus_mode(struct sdhci_host *host,
+					    unsigned int clock)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_ios curr_ios = host->mmc->ios;
+	int rc;
+
+	clock = msm_get_clock_rate_for_bus_mode(host, clock);
+	rc = clk_set_rate(msm_host->clk, clock);
+	if (rc) {
+		pr_err("%s: Failed to set clock at rate %u at timing %d\n",
+		       mmc_hostname(host->mmc), clock,
+		       curr_ios.timing);
+		return;
+	}
+	msm_host->clk_rate = clock;
+	pr_debug("%s: Setting clock at rate %lu at timing %d\n",
+		 mmc_hostname(host->mmc), clk_get_rate(msm_host->clk),
+		 curr_ios.timing);
+}
+
 /* Platform specific tuning */
 static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
 {
@@ -1006,8 +1045,6 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
-	struct mmc_ios curr_ios = host->mmc->ios;
-	int rc;
 
 	if (!clock) {
 		msm_host->clk_rate = clock;
@@ -1015,32 +1052,11 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 	}
 
 	spin_unlock_irq(&host->lock);
-	/*
-	 * The SDHC requires internal clock frequency to be double the
-	 * actual clock that will be set for DDR mode. The controller
-	 * uses the faster clock(100/400MHz) for some of its parts and
-	 * send the actual required clock (50/200MHz) to the card.
-	 */
-	if (curr_ios.timing == MMC_TIMING_UHS_DDR50 ||
-	    curr_ios.timing == MMC_TIMING_MMC_DDR52 ||
-	    curr_ios.timing == MMC_TIMING_MMC_HS400)
-		clock *= 2;
 
 	sdhci_msm_hc_select_mode(host);
 
-	rc = clk_set_rate(msm_host->clk, clock);
-	if (rc) {
-		pr_err("%s: Failed to set clock at rate %u at timing %d\n",
-		       mmc_hostname(host->mmc), clock,
-		       curr_ios.timing);
-		goto out_lock;
-	}
-	msm_host->clk_rate = clock;
-	pr_debug("%s: Setting clock at rate %lu at timing %d\n",
-		 mmc_hostname(host->mmc), clk_get_rate(msm_host->clk),
-		 curr_ios.timing);
+	msm_set_clock_rate_for_bus_mode(host, clock);
 
-out_lock:
 	spin_lock_irq(&host->lock);
 out:
 	__sdhci_msm_set_clock(host, clock);
#5 lore raw

PATCH RESEND 3/8 mmc: sdhci-msm: Factor out sdhci_msm_hs400

In reply to Ritesh Harjani

Factor out sdhci_msm_hs400 used for DLL calibration in HS400 modes. This function will be needed for enhanced_strobe as well.

---
 drivers/mmc/host/sdhci-msm.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)
drivers/mmc/host/sdhci-msm.c +26 -6
index 3fc496e..5a37c29 100644
@@ -884,6 +884,28 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 	return rc;
 }
 
+/*
+ * sdhci_msm_hs400 - Calibrate the DLL for HS400 bus speed mode operation.
+ * DLL operation is only needed for clock > 100MHz. For clock <= 100MHz
+ * fixed feedback clock is used.
+ */
+static void sdhci_msm_hs400(struct sdhci_host *host, struct mmc_ios *ios)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	int ret;
+
+	if (host->clock > CORE_FREQ_100MHZ &&
+	    msm_host->tuning_done && !msm_host->calibration_done) {
+		ret = sdhci_msm_hs400_dll_calibration(host);
+		if (!ret)
+			msm_host->calibration_done = true;
+		else
+			pr_err("%s: Failed to calibrate DLL for hs400 mode (%d)\n",
+			       mmc_hostname(host->mmc), ret);
+	}
+}
+
 static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
 					unsigned int uhs)
 {
@@ -952,12 +974,10 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
 	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
 
 	spin_unlock_irq(&host->lock);
-	/* CDCLP533 HW calibration is only required for HS400 mode*/
-	if (host->clock > CORE_FREQ_100MHZ &&
-	    msm_host->tuning_done && !msm_host->calibration_done &&
-	    mmc->ios.timing == MMC_TIMING_MMC_HS400)
-		if (!sdhci_msm_hs400_dll_calibration(host))
-			msm_host->calibration_done = true;
+
+	if (mmc->ios.timing == MMC_TIMING_MMC_HS400)
+		sdhci_msm_hs400(host, &mmc->ios);
+
 	spin_lock_irq(&host->lock);
 }
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer Acked-by on v1 3/8
#6 lore raw

Re: [RESEND PATCHv1 3/8] mmc: sdhci-msm: Factor out sdhci_msm_hs400

Quoted 4 lines · Ritesh Harjani

Factor out sdhci_msm_hs400 used for DLL calibration in HS400 modes. This function will be needed for enhanced_strobe as well.

Quoted 55 lines
---
 drivers/mmc/host/sdhci-msm.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)
drivers/mmc/host/sdhci-msm.c +26 -6
index 3fc496e..5a37c29 100644
@@ -884,6 +884,28 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 	return rc;
 }
 
+/*
+ * sdhci_msm_hs400 - Calibrate the DLL for HS400 bus speed mode operation.
+ * DLL operation is only needed for clock > 100MHz. For clock <= 100MHz
+ * fixed feedback clock is used.
+ */
+static void sdhci_msm_hs400(struct sdhci_host *host, struct mmc_ios *ios)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	int ret;
+
+	if (host->clock > CORE_FREQ_100MHZ &&
+	    msm_host->tuning_done && !msm_host->calibration_done) {
+		ret = sdhci_msm_hs400_dll_calibration(host);
+		if (!ret)
+			msm_host->calibration_done = true;
+		else
+			pr_err("%s: Failed to calibrate DLL for hs400 mode (%d)\n",
+			       mmc_hostname(host->mmc), ret);
+	}
+}
+
 static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
 					unsigned int uhs)
 {
@@ -952,12 +974,10 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
 	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
 
 	spin_unlock_irq(&host->lock);
-	/* CDCLP533 HW calibration is only required for HS400 mode*/
-	if (host->clock > CORE_FREQ_100MHZ &&
-	    msm_host->tuning_done && !msm_host->calibration_done &&
-	    mmc->ios.timing == MMC_TIMING_MMC_HS400)
-		if (!sdhci_msm_hs400_dll_calibration(host))
-			msm_host->calibration_done = true;
+
+	if (mmc->ios.timing == MMC_TIMING_MMC_HS400)
+		sdhci_msm_hs400(host, &mmc->ios);
+
 	spin_lock_irq(&host->lock);
 }
 
#7 lore raw

PATCH RESEND 4/8 mmc: sdhci-msm: Reset vendor specific func register on probe

In reply to Ritesh Harjani

From: Venkat Gopalakrishnan <[email protected]>

The vendor specific func register doesn't get reset when using the software reset register. The various bootloader's could leave this in an unknown state, hence reset this register to it's power on reset value during probe.

---
 drivers/mmc/host/sdhci-msm.c | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci-msm.c +4 -11
index 5a37c29..a028568 100644
@@ -69,6 +69,7 @@
 #define CORE_DLL_CLOCK_DISABLE	BIT(21)
 
 #define CORE_VENDOR_SPEC	0x10c
+#define CORE_VENDOR_SPEC_POR_VAL	0xa1c
 #define CORE_CLK_PWRSAVE	BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT	(2 << 8)
 #define CORE_HC_MCLK_SEL_HS400	(3 << 8)
@@ -1197,17 +1198,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 		goto clk_disable;
 	}
 
-	config = readl_relaxed(msm_host->core_mem + CORE_POWER);
-	config |= CORE_SW_RST;
-	writel_relaxed(config, msm_host->core_mem + CORE_POWER);
-
-	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
-	usleep_range(1000, 5000);
-	if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) {
-		dev_err(&pdev->dev, "Stuck in reset\n");
-		ret = -ETIMEDOUT;
-		goto clk_disable;
-	}
+	/* Reset the vendor spec register to power on reset state */
+	writel_relaxed(CORE_VENDOR_SPEC_POR_VAL,
+		       host->ioaddr + CORE_VENDOR_SPEC);
 
 	/* Set HC_MODE_EN bit in HC_MODE register */
 	writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer Acked-by on v1 4/8
#8 lore raw

Re: [RESEND PATCHv1 4/8] mmc: sdhci-msm: Reset vendor specific func register on probe

Quoted 9 lines · Ritesh Harjani

From: Venkat Gopalakrishnan <[email protected]>

The vendor specific func register doesn't get reset when using the software reset register. The various bootloader's could leave this in an unknown state, hence reset this register to it's power on reset value during probe.

Quoted 38 lines
---
 drivers/mmc/host/sdhci-msm.c | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci-msm.c +4 -11
index 5a37c29..a028568 100644
@@ -69,6 +69,7 @@
 #define CORE_DLL_CLOCK_DISABLE	BIT(21)
 
 #define CORE_VENDOR_SPEC	0x10c
+#define CORE_VENDOR_SPEC_POR_VAL	0xa1c
 #define CORE_CLK_PWRSAVE	BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT	(2 << 8)
 #define CORE_HC_MCLK_SEL_HS400	(3 << 8)
@@ -1197,17 +1198,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 		goto clk_disable;
 	}
 
-	config = readl_relaxed(msm_host->core_mem + CORE_POWER);
-	config |= CORE_SW_RST;
-	writel_relaxed(config, msm_host->core_mem + CORE_POWER);
-
-	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
-	usleep_range(1000, 5000);
-	if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) {
-		dev_err(&pdev->dev, "Stuck in reset\n");
-		ret = -ETIMEDOUT;
-		goto clk_disable;
-	}
+	/* Reset the vendor spec register to power on reset state */
+	writel_relaxed(CORE_VENDOR_SPEC_POR_VAL,
+		       host->ioaddr + CORE_VENDOR_SPEC);
 
 	/* Set HC_MODE_EN bit in HC_MODE register */
 	writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
#9 lore raw

PATCH RESEND 5/8 mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

In reply to Ritesh Harjani

From: Subhash Jadavani <[email protected]>

Program CORE_CSR_CDC_DELAY_CFG for hardware recommended 1.25ns delay. We may see data CRC errors if it's programmed for any other delay value.

---
 drivers/mmc/host/sdhci-msm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mmc/host/sdhci-msm.c +1 -1
index a028568..84d29dd 100644
@@ -679,7 +679,7 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 	writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
 	writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
 	writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
-	writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+	writel_relaxed(0x4E2, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
 	writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
 	writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer Acked-by on v1 5/8
#10 lore raw

Re: [RESEND PATCHv1 5/8] mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

Quoted 8 lines · Ritesh Harjani

From: Subhash Jadavani <[email protected]>

Program CORE_CSR_CDC_DELAY_CFG for hardware recommended 1.25ns delay. We may see data CRC errors if it's programmed for any other delay value.

Quoted 18 lines
---
 drivers/mmc/host/sdhci-msm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mmc/host/sdhci-msm.c +1 -1
index a028568..84d29dd 100644
@@ -679,7 +679,7 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 	writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
 	writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
 	writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
-	writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+	writel_relaxed(0x4E2, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
 	writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
 	writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
 
#11 lore raw

Re: [RESEND PATCHv1 5/8] mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

In reply to Ritesh Harjani
Quoted 17 lines · Ritesh Harjani

From: Subhash Jadavani <[email protected]>

Program CORE_CSR_CDC_DELAY_CFG for hardware recommended 1.25ns delay. We may see data CRC errors if it's programmed for any other delay value.

---
 drivers/mmc/host/sdhci-msm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mmc/host/sdhci-msm.c +0 -0
index a028568..84d29dd 100644

drivers/mmc/host/sdhci-msm.c static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host) · line 685

Quoted 8 lines
drivers/mmc/host/sdhci-msm.c +1 -1
@@ -679,7 +679,7 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 	writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
 	writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
 	writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
-	writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+	writel_relaxed(0x4E2, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
 	writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
 	writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
 

There's a comment block above this set of writes that repeats what's happening in the code.

/*
* Perform CDC Register Initialization Sequence *
* CORE_CSR_CDC_CTLR_CFG0 0x11800EC
* CORE_CSR_CDC_CTLR_CFG1 0x3011111
* CORE_CSR_CDC_CAL_TIMER_CFG0 0x1201000
* CORE_CSR_CDC_CAL_TIMER_CFG1 0x4
* CORE_CSR_CDC_REFCOUNT_CFG 0xCB732020
* CORE_CSR_CDC_COARSE_CAL_CFG 0xB19
* CORE_CSR_CDC_DELAY_CFG 0x3AC
* CORE_CDC_OFFSET_CFG 0x0
* CORE_CDC_SLAVE_DDA_CFG 0x16334
*/

Perhaps we should just delete those comments because they're incorrect now.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#12 lore raw

Re: [RESEND PATCHv1 5/8] mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

Hi Stephen,

Quoted 44 lines · Stephen Boyd
Quoted 17 lines · Ritesh Harjani

From: Subhash Jadavani <[email protected]>

Program CORE_CSR_CDC_DELAY_CFG for hardware recommended 1.25ns delay. We may see data CRC errors if it's programmed for any other delay value.

---
 drivers/mmc/host/sdhci-msm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mmc/host/sdhci-msm.c +0 -0
index a028568..84d29dd 100644

drivers/mmc/host/sdhci-msm.c static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host) · line 685

Quoted 8 lines
drivers/mmc/host/sdhci-msm.c +1 -1
@@ -679,7 +679,7 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 	writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
 	writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
 	writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
-	writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+	writel_relaxed(0x4E2, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
 	writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
 	writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
 

There's a comment block above this set of writes that repeats what's happening in the code.

/*
* Perform CDC Register Initialization Sequence *
* CORE_CSR_CDC_CTLR_CFG0 0x11800EC
* CORE_CSR_CDC_CTLR_CFG1 0x3011111
* CORE_CSR_CDC_CAL_TIMER_CFG0 0x1201000
* CORE_CSR_CDC_CAL_TIMER_CFG1 0x4
* CORE_CSR_CDC_REFCOUNT_CFG 0xCB732020
* CORE_CSR_CDC_COARSE_CAL_CFG 0xB19
* CORE_CSR_CDC_DELAY_CFG 0x3AC
* CORE_CDC_OFFSET_CFG 0x0
* CORE_CDC_SLAVE_DDA_CFG 0x16334
*/

Quoted 2 lines

Perhaps we should just delete those comments because they're incorrect now.

Thanks for the review. Yes, I have addressed this comment on top of this series along with one other fix. -named ("mmc: sdhci-msm: Addresses minor cleanups")

Regards
Ritesh

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#13 lore raw

PATCH RESEND 6/8 mmc: sdhci: Clear SDHCI_HS400_TUNING flag after platform_execute_tuning

In reply to Ritesh Harjani

Clear SDHCI_HS400_TUNING flag after platform_execute_tuning so that platform_execute_tuning may use it if needed.

---
 drivers/mmc/host/sdhci.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/mmc/host/sdhci.c +4 -2
index 2390980..2658f89 100644
@@ -2114,7 +2114,6 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	spin_lock_irqsave(&host->lock, flags);
 
 	hs400_tuning = host->flags & SDHCI_HS400_TUNING;
-	host->flags &= ~SDHCI_HS400_TUNING;
 
 	if (host->tuning_mode == SDHCI_TUNING_MODE_1)
 		tuning_count = host->tuning_count;
@@ -2156,7 +2155,9 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 	if (host->ops->platform_execute_tuning) {
 		spin_unlock_irqrestore(&host->lock, flags);
-		return host->ops->platform_execute_tuning(host, opcode);
+		err = host->ops->platform_execute_tuning(host, opcode);
+		spin_lock_irqsave(&host->lock, flags);
+		goto out_unlock;
 	}
 
 	host->mmc->retune_period = tuning_count;
@@ -2167,6 +2168,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 	sdhci_end_tuning(host);
 out_unlock:
+	host->flags &= ~SDHCI_HS400_TUNING;
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	return err;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer
#14 lore raw

Re: [RESEND PATCHv1 6/8] mmc: sdhci: Clear SDHCI_HS400_TUNING flag after platform_execute_tuning

Quoted 2 lines · Ritesh Harjani

Clear SDHCI_HS400_TUNING flag after platform_execute_tuning so that platform_execute_tuning may use it if needed.

Sorry for the slow reply.

platform_execute_tuning() should not really exist because it doesn't do anything useful.

If it is not too much trouble please consider just hooking ->execute_tuning() directly i.e.

	host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning;

Then you can use and clear the flag in sdhci_msm_execute_tuning().

Quoted 38 lines
---
 drivers/mmc/host/sdhci.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/mmc/host/sdhci.c +4 -2
index 2390980..2658f89 100644
@@ -2114,7 +2114,6 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	spin_lock_irqsave(&host->lock, flags);
 
 	hs400_tuning = host->flags & SDHCI_HS400_TUNING;
-	host->flags &= ~SDHCI_HS400_TUNING;
 
 	if (host->tuning_mode == SDHCI_TUNING_MODE_1)
 		tuning_count = host->tuning_count;
@@ -2156,7 +2155,9 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 	if (host->ops->platform_execute_tuning) {
 		spin_unlock_irqrestore(&host->lock, flags);
-		return host->ops->platform_execute_tuning(host, opcode);
+		err = host->ops->platform_execute_tuning(host, opcode);
+		spin_lock_irqsave(&host->lock, flags);
+		goto out_unlock;
 	}
 
 	host->mmc->retune_period = tuning_count;
@@ -2167,6 +2168,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 	sdhci_end_tuning(host);
 out_unlock:
+	host->flags &= ~SDHCI_HS400_TUNING;
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	return err;
#15 lore raw

Re: [RESEND PATCHv1 6/8] mmc: sdhci: Clear SDHCI_HS400_TUNING flag after platform_execute_tuning

Hi Adrian,

Thanks for reviewing.

Quoted 9 lines · Adrian Hunter
Quoted 2 lines · Ritesh Harjani

Clear SDHCI_HS400_TUNING flag after platform_execute_tuning so that platform_execute_tuning may use it if needed.

Sorry for the slow reply.

platform_execute_tuning() should not really exist because it doesn't do anything useful.

Quoted 6 lines

If it is not too much trouble please consider just hooking ->execute_tuning() directly i.e.

	host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning;

Then you can use and clear the flag in sdhci_msm_execute_tuning().

Sure, this seems fine. I will try it and re-submit based on your above suggestion.

Regards
Ritesh

Quoted 40 lines
Quoted 39 lines
---
 drivers/mmc/host/sdhci.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/mmc/host/sdhci.c +4 -2
index 2390980..2658f89 100644
@@ -2114,7 +2114,6 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	spin_lock_irqsave(&host->lock, flags);
 
 	hs400_tuning = host->flags & SDHCI_HS400_TUNING;
-	host->flags &= ~SDHCI_HS400_TUNING;
 
 	if (host->tuning_mode == SDHCI_TUNING_MODE_1)
 		tuning_count = host->tuning_count;
@@ -2156,7 +2155,9 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 	if (host->ops->platform_execute_tuning) {
 		spin_unlock_irqrestore(&host->lock, flags);
-		return host->ops->platform_execute_tuning(host, opcode);
+		err = host->ops->platform_execute_tuning(host, opcode);
+		spin_lock_irqsave(&host->lock, flags);
+		goto out_unlock;
 	}
 
 	host->mmc->retune_period = tuning_count;
@@ -2167,6 +2168,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 	sdhci_end_tuning(host);
 out_unlock:
+	host->flags &= ~SDHCI_HS400_TUNING;
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	return err;
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#16 lore raw

PATCH RESEND 7/8 mmc: sdhci-msm: Make HS400 tuning follow as per recommeneded HW sequence

In reply to Ritesh Harjani

During tuning execution for HS400 mode, HW sequence recommends to select MCLK_SEL/2(0x3) in VENDOR_SPEC & sdhc msm clock at GCC to be 400MHZ (nearest supported clk). Add this change in tuning sequence during HS400 tuning.

---
 drivers/mmc/host/sdhci-msm.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
drivers/mmc/host/sdhci-msm.c +14 -2
index 84d29dd..fa9bce3 100644
@@ -151,7 +151,8 @@ static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
 	 */
 	if (ios.timing == MMC_TIMING_UHS_DDR50 ||
 	    ios.timing == MMC_TIMING_MMC_DDR52 ||
-	    ios.timing == MMC_TIMING_MMC_HS400)
+	    ios.timing == MMC_TIMING_MMC_HS400 ||
+	    host->flags & SDHCI_HS400_TUNING)
 		clock *= 2;
 	return clock;
 }
@@ -611,7 +612,8 @@ void sdhci_msm_hc_select_mode(struct sdhci_host *host)
 {
 	struct mmc_ios ios = host->mmc->ios;
 
-	if (ios.timing == MMC_TIMING_MMC_HS400)
+	if (ios.timing == MMC_TIMING_MMC_HS400 ||
+	    host->flags & SDHCI_HS400_TUNING)
 		msm_hc_select_hs400(host);
 	else
 		msm_hc_select_default(host);
@@ -831,6 +833,16 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 	    ios.timing == MMC_TIMING_UHS_SDR104))
 		return 0;
 
+	/*
+	 * For HS400 tuning in HS200 timing requires:
+	 * - select MCLK/2 in VENDOR_SPEC
+	 * - program MCLK to 400MHz (or nearest supported) in GCC
+	 */
+	if (host->flags & SDHCI_HS400_TUNING) {
+		sdhci_msm_hc_select_mode(host);
+		msm_set_clock_rate_for_bus_mode(host, ios.clock);
+	}
+
 retry:
 	/* First of all reset the tuning block */
 	rc = msm_init_cm_dll(host);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer Acked-by on v1 7/8
#17 lore raw

Re: [RESEND PATCHv1 7/8] mmc: sdhci-msm: Make HS400 tuning follow as per recommeneded HW sequence

Quoted 6 lines · Ritesh Harjani

During tuning execution for HS400 mode, HW sequence recommends to select MCLK_SEL/2(0x3) in VENDOR_SPEC & sdhc msm clock at GCC to be 400MHZ (nearest supported clk). Add this change in tuning sequence during HS400 tuning.

You may need to re-base this if you make changes as per patch 6, but otherwise:

Quoted 46 lines
---
 drivers/mmc/host/sdhci-msm.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
drivers/mmc/host/sdhci-msm.c +14 -2
index 84d29dd..fa9bce3 100644
@@ -151,7 +151,8 @@ static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
 	 */
 	if (ios.timing == MMC_TIMING_UHS_DDR50 ||
 	    ios.timing == MMC_TIMING_MMC_DDR52 ||
-	    ios.timing == MMC_TIMING_MMC_HS400)
+	    ios.timing == MMC_TIMING_MMC_HS400 ||
+	    host->flags & SDHCI_HS400_TUNING)
 		clock *= 2;
 	return clock;
 }
@@ -611,7 +612,8 @@ void sdhci_msm_hc_select_mode(struct sdhci_host *host)
 {
 	struct mmc_ios ios = host->mmc->ios;
 
-	if (ios.timing == MMC_TIMING_MMC_HS400)
+	if (ios.timing == MMC_TIMING_MMC_HS400 ||
+	    host->flags & SDHCI_HS400_TUNING)
 		msm_hc_select_hs400(host);
 	else
 		msm_hc_select_default(host);
@@ -831,6 +833,16 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 	    ios.timing == MMC_TIMING_UHS_SDR104))
 		return 0;
 
+	/*
+	 * For HS400 tuning in HS200 timing requires:
+	 * - select MCLK/2 in VENDOR_SPEC
+	 * - program MCLK to 400MHz (or nearest supported) in GCC
+	 */
+	if (host->flags & SDHCI_HS400_TUNING) {
+		sdhci_msm_hc_select_mode(host);
+		msm_set_clock_rate_for_bus_mode(host, ios.clock);
+	}
+
 retry:
 	/* First of all reset the tuning block */
 	rc = msm_init_cm_dll(host);
#18 lore raw

PATCH RESEND 8/8 mmc: sdhci-msm: Provide enhanced_strobe mode feature support

In reply to Ritesh Harjani

This provides enhanced_strobe mode feature support in sdhci-msm driver.

---
 drivers/mmc/host/sdhci-msm.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci-msm.c +25 -9
index fa9bce3..f958697 100644
@@ -103,6 +103,7 @@
 
 #define CORE_DDR_200_CFG		0x184
 #define CORE_CDC_T4_DLY_SEL		BIT(0)
+#define CORE_CMDIN_RCLK_EN		BIT(1)
 #define CORE_START_CDC_TRAFFIC		BIT(6)
 #define CORE_VENDOR_SPEC3	0x1b0
 #define CORE_PWRSAVE_DLL	BIT(3)
@@ -547,6 +548,7 @@ static void msm_hc_select_hs400(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_ios ios = host->mmc->ios;
 	u32 config, dll_lock;
 	int rc;
 
@@ -560,7 +562,8 @@ static void msm_hc_select_hs400(struct sdhci_host *host)
 	 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
 	 * register
 	 */
-	if (msm_host->tuning_done && !msm_host->calibration_done) {
+	if ((msm_host->tuning_done || ios.enhanced_strobe) &&
+	    !msm_host->calibration_done) {
 		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
 		config |= CORE_HC_SELECT_IN_HS400;
 		config |= CORE_HC_SELECT_IN_EN;
@@ -734,6 +737,7 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 
 static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
 {
+	struct mmc_host *mmc = host->mmc;
 	u32 dll_status, config;
 	int ret;
 
@@ -748,6 +752,12 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
 	 */
 	writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG);
 
+	if (mmc->ios.enhanced_strobe) {
+		config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+		config |= CORE_CMDIN_RCLK_EN;
+		writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+	}
+
 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
 	config |= CORE_DDR_CAL_EN;
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
@@ -782,6 +792,7 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_host *mmc = host->mmc;
 	int ret;
 	u32 config;
 
@@ -795,14 +806,17 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
 	if (ret)
 		goto out;
 
-	/* Set the selected phase in delay line hw block */
-	ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
-	if (ret)
-		goto out;
+	if (!mmc->ios.enhanced_strobe) {
+		/* Set the selected phase in delay line hw block */
+		ret = msm_config_cm_dll_phase(host,
+					      msm_host->saved_tuning_phase);
+		if (ret)
+			goto out;
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+		config |= CORE_CMD_DAT_TRACK_SEL;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+	}
 
-	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
-	config |= CORE_CMD_DAT_TRACK_SEL;
-	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 	if (msm_host->use_cdclp533)
 		ret = sdhci_msm_cdclp533_calibration(host);
 	else
@@ -899,6 +913,7 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 
 /*
  * sdhci_msm_hs400 - Calibrate the DLL for HS400 bus speed mode operation.
+ * This needs to be done for both tuning and enhanced_strobe mode.
  * DLL operation is only needed for clock > 100MHz. For clock <= 100MHz
  * fixed feedback clock is used.
  */
@@ -909,7 +924,8 @@ static void sdhci_msm_hs400(struct sdhci_host *host, struct mmc_ios *ios)
 	int ret;
 
 	if (host->clock > CORE_FREQ_100MHZ &&
-	    msm_host->tuning_done && !msm_host->calibration_done) {
+	    (msm_host->tuning_done || ios->enhanced_strobe) &&
+	    !msm_host->calibration_done) {
 		ret = sdhci_msm_hs400_dll_calibration(host);
 		if (!ret)
 			msm_host->calibration_done = true;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
maintainer Acked-by on v1 8/8
#19 lore raw

Re: [RESEND PATCHv1 8/8] mmc: sdhci-msm: Provide enhanced_strobe mode feature support

Quoted 4 lines · Ritesh Harjani

This provides enhanced_strobe mode feature support in sdhci-msm driver.

Quoted 107 lines
---
 drivers/mmc/host/sdhci-msm.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci-msm.c +25 -9
index fa9bce3..f958697 100644
@@ -103,6 +103,7 @@
 
 #define CORE_DDR_200_CFG		0x184
 #define CORE_CDC_T4_DLY_SEL		BIT(0)
+#define CORE_CMDIN_RCLK_EN		BIT(1)
 #define CORE_START_CDC_TRAFFIC		BIT(6)
 #define CORE_VENDOR_SPEC3	0x1b0
 #define CORE_PWRSAVE_DLL	BIT(3)
@@ -547,6 +548,7 @@ static void msm_hc_select_hs400(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_ios ios = host->mmc->ios;
 	u32 config, dll_lock;
 	int rc;
 
@@ -560,7 +562,8 @@ static void msm_hc_select_hs400(struct sdhci_host *host)
 	 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
 	 * register
 	 */
-	if (msm_host->tuning_done && !msm_host->calibration_done) {
+	if ((msm_host->tuning_done || ios.enhanced_strobe) &&
+	    !msm_host->calibration_done) {
 		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
 		config |= CORE_HC_SELECT_IN_HS400;
 		config |= CORE_HC_SELECT_IN_EN;
@@ -734,6 +737,7 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
 
 static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
 {
+	struct mmc_host *mmc = host->mmc;
 	u32 dll_status, config;
 	int ret;
 
@@ -748,6 +752,12 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
 	 */
 	writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG);
 
+	if (mmc->ios.enhanced_strobe) {
+		config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+		config |= CORE_CMDIN_RCLK_EN;
+		writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+	}
+
 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
 	config |= CORE_DDR_CAL_EN;
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
@@ -782,6 +792,7 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_host *mmc = host->mmc;
 	int ret;
 	u32 config;
 
@@ -795,14 +806,17 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
 	if (ret)
 		goto out;
 
-	/* Set the selected phase in delay line hw block */
-	ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
-	if (ret)
-		goto out;
+	if (!mmc->ios.enhanced_strobe) {
+		/* Set the selected phase in delay line hw block */
+		ret = msm_config_cm_dll_phase(host,
+					      msm_host->saved_tuning_phase);
+		if (ret)
+			goto out;
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+		config |= CORE_CMD_DAT_TRACK_SEL;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+	}
 
-	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
-	config |= CORE_CMD_DAT_TRACK_SEL;
-	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 	if (msm_host->use_cdclp533)
 		ret = sdhci_msm_cdclp533_calibration(host);
 	else
@@ -899,6 +913,7 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 
 /*
  * sdhci_msm_hs400 - Calibrate the DLL for HS400 bus speed mode operation.
+ * This needs to be done for both tuning and enhanced_strobe mode.
  * DLL operation is only needed for clock > 100MHz. For clock <= 100MHz
  * fixed feedback clock is used.
  */
@@ -909,7 +924,8 @@ static void sdhci_msm_hs400(struct sdhci_host *host, struct mmc_ios *ios)
 	int ret;
 
 	if (host->clock > CORE_FREQ_100MHZ &&
-	    msm_host->tuning_done && !msm_host->calibration_done) {
+	    (msm_host->tuning_done || ios->enhanced_strobe) &&
+	    !msm_host->calibration_done) {
 		ret = sdhci_msm_hs400_dll_calibration(host);
 		if (!ret)
 			msm_host->calibration_done = true;
Tested-by on the v1 series
#20 lore raw
In reply to Ritesh Harjani
Quoted 14 lines · Ritesh Harjani

Hi,

Resending this patch series, as no one could review it -possibly due to holidays during that time.

This patch series mainly provides enhanced strobe support to sdhci-msm driver along with some additions of HW recommended sequence. This has been tested on 8996 based internal target & on db410c.

Patches 1-3 :- Factors out few functions to be re-used again.
To also simplify large functions and makes it more readable.

Patches 4-5 :- Few recommendations based on HW prog. guide.

Quoted 9 lines

Patches 6 :- Clear SDHCI_HS400_TUNING flag after platform_execute_tuning

	     so that ->platform_execute_tuning (underlying platform driver) can
	     know about HS400 tuning.

Patch 7 :- Implements an additional step as per HPG for HS400 tuning.

Patch 8 :- Implements enhanced strobe functionality in sdhci-msm driver.

I have included this series in my tree while testing my SDHCI V2 series.

One message did occur which looks new or unfamilar and relatively harmless,

"sdhci_msm f9824900.mmc: TCXO clk not present (-2) "

Is that something I am missing on my side?

In anycase,

-jeremy

Quoted 24 lines

Ritesh Harjani (6):
mmc: sdhci-msm: Factor out sdhci_msm_hc_select_mode
mmc: sdhci-msm: Factor out function to set/get msm clock rate
mmc: sdhci-msm: Factor out sdhci_msm_hs400
mmc: sdhci: Clear SDHCI_HS400_TUNING flag after
platform_execute_tuning
mmc: sdhci-msm: Make HS400 tuning follow as per recommeneded HW
sequence
mmc: sdhci-msm: Provide enhanced_strobe mode feature support

Subhash Jadavani (1):
mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

Venkat Gopalakrishnan (1):
mmc: sdhci-msm: Reset vendor specific func register on probe

 drivers/mmc/host/sdhci-msm.c | 356 ++++++++++++++++++++++++++-----------------
 drivers/mmc/host/sdhci.c     |   6 +-
 2 files changed, 224 insertions(+), 138 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.
#21 lore raw
Quoted 25 lines · Jeremy McNicoll
Quoted 14 lines · Ritesh Harjani

Hi,

Resending this patch series, as no one could review it -possibly due to holidays during that time.

This patch series mainly provides enhanced strobe support to sdhci-msm driver along with some additions of HW recommended sequence. This has been tested on 8996 based internal target & on db410c.

Patches 1-3 :- Factors out few functions to be re-used again.
To also simplify large functions and makes it more readable.

Patches 4-5 :- Few recommendations based on HW prog. guide.

Quoted 9 lines

Patches 6 :- Clear SDHCI_HS400_TUNING flag after platform_execute_tuning

	     so that ->platform_execute_tuning (underlying platform driver) can
	     know about HS400 tuning.

Patch 7 :- Implements an additional step as per HPG for HS400 tuning.

Patch 8 :- Implements enhanced strobe functionality in sdhci-msm driver.

Quoted 6 lines

I have included this series in my tree while testing my SDHCI V2 series.

One message did occur which looks new or unfamilar and relatively harmless,

"sdhci_msm f9824900.mmc: TCXO clk not present (-2) "

This should be ok.

Quoted 2 lines

Is that something I am missing on my side?

You should provide this in your DT.
@@ -463,8 +463,9 @@

                        interrupts = <0 141 0>, <0 134 0>;
                        interrupt-names = "hc_irq", "pwr_irq";
                        clocks = <&gcc GCC_SDCC1_APPS_CLK>,

- <&gcc GCC_SDCC1_AHB_CLK>;
- clock-names = "core", "iface";
+ <&gcc GCC_SDCC1_AHB_CLK>,
+ <&xo_board>;
+ clock-names = "core", "iface", "xo";

Quoted 4 lines

In anycase,

Thanks for testing this series.

Hi Adrian/Ulf,
In case if we dont have any other comments, can we please include this series in next ?

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#22 lore raw
In reply to Ritesh Harjani
Quoted 39 lines · Ritesh Harjani

Hi,

Resending this patch series, as no one could review it -possibly due to holidays during that time.

This patch series mainly provides enhanced strobe support to sdhci-msm driver along with some additions of HW recommended sequence. This has been tested on 8996 based internal target & on db410c.

Patches 1-3 :- Factors out few functions to be re-used again.
To also simplify large functions and makes it more readable.

Patches 4-5 :- Few recommendations based on HW prog. guide.

Patches 6 :- Clear SDHCI_HS400_TUNING flag after platform_execute_tuning
so that ->platform_execute_tuning (underlying platform driver) can know about HS400 tuning.

Patch 7 :- Implements an additional step as per HPG for HS400 tuning.

Patch 8 :- Implements enhanced strobe functionality in sdhci-msm driver.

Ritesh Harjani (6):
mmc: sdhci-msm: Factor out sdhci_msm_hc_select_mode
mmc: sdhci-msm: Factor out function to set/get msm clock rate
mmc: sdhci-msm: Factor out sdhci_msm_hs400
mmc: sdhci: Clear SDHCI_HS400_TUNING flag after
platform_execute_tuning
mmc: sdhci-msm: Make HS400 tuning follow as per recommeneded HW
sequence
mmc: sdhci-msm: Provide enhanced_strobe mode feature support

Subhash Jadavani (1):
mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

Venkat Gopalakrishnan (1):
mmc: sdhci-msm: Reset vendor specific func register on probe

Quoted 8 lines
 drivers/mmc/host/sdhci-msm.c | 356 ++++++++++++++++++++++++++-----------------
 drivers/mmc/host/sdhci.c     |   6 +-
 2 files changed, 224 insertions(+), 138 deletions(-)

--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.

Ritesh, Adrian,

I realized that Adrian requested a minor fixup of patch6. However to simplify a bit for all of us, avoiding another new version of the series being sent I decided to pick this series as is.

Adrian, I even took the liberty of adding your ack for patch6. I also trust Ritesh to make a fix for patch6, but on top of the series I have just applied.

If you have any objections, please tell me!

Kind regards
Uffe

#23 lore raw
Quoted 49 lines · Ulf Hansson
Quoted 39 lines · Ritesh Harjani

Hi,

Resending this patch series, as no one could review it -possibly due to holidays during that time.

This patch series mainly provides enhanced strobe support to sdhci-msm driver along with some additions of HW recommended sequence. This has been tested on 8996 based internal target & on db410c.

Patches 1-3 :- Factors out few functions to be re-used again.
To also simplify large functions and makes it more readable.

Patches 4-5 :- Few recommendations based on HW prog. guide.

Patches 6 :- Clear SDHCI_HS400_TUNING flag after platform_execute_tuning
so that ->platform_execute_tuning (underlying platform driver) can know about HS400 tuning.

Patch 7 :- Implements an additional step as per HPG for HS400 tuning.

Patch 8 :- Implements enhanced strobe functionality in sdhci-msm driver.

Ritesh Harjani (6):
mmc: sdhci-msm: Factor out sdhci_msm_hc_select_mode
mmc: sdhci-msm: Factor out function to set/get msm clock rate
mmc: sdhci-msm: Factor out sdhci_msm_hs400
mmc: sdhci: Clear SDHCI_HS400_TUNING flag after
platform_execute_tuning
mmc: sdhci-msm: Make HS400 tuning follow as per recommeneded HW
sequence
mmc: sdhci-msm: Provide enhanced_strobe mode feature support

Subhash Jadavani (1):
mmc: sdhci-msm: configure CORE_CSR_CDC_DELAY_CFG to recommended value

Venkat Gopalakrishnan (1):
mmc: sdhci-msm: Reset vendor specific func register on probe

Quoted 8 lines
 drivers/mmc/host/sdhci-msm.c | 356 ++++++++++++++++++++++++++-----------------
 drivers/mmc/host/sdhci.c     |   6 +-
 2 files changed, 224 insertions(+), 138 deletions(-)

--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.

Quoted 5 lines

Ritesh, Adrian,

I realized that Adrian requested a minor fixup of patch6. However to simplify a bit for all of us, avoiding another new version of the series being sent I decided to pick this series as is.

Thanks Ulf.

Quoted 4 lines

Adrian, I even took the liberty of adding your ack for patch6. I also trust Ritesh to make a fix for patch6, but on top of the series I have just applied.

Thanks :)

Quoted 2 lines

If you have any objections, please tell me!

No objections as such. But I wanted to clear few things here.

Based on Adrian comments for patch6 - I think since anyway I will hook sdhci-msm to host->mmc_host_ops.execute_tuning (which will call ->sdhci_msm_execute_tuning directly and play with SDHCI_HS400_TUNING inside sdhci_msm_execute_tuning function), I assumed we need to drop path6 (which plays with SDHCI_HS400_TUNING flag inside sdhci_execute_tuning).

@Adrian,
Please let me know if we would anyway like to retain patch6. If yes, I can make the changes you mentioned for sdhci-msm on top of this patch series.

If not, then instead of reverting path6 again on top of this series, I will re-submit a new series with your comments addressed and dropping patch6.

Please let me know what suits better.

Regards
Ritesh

Quoted 4 lines

Kind regards
Uffe

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project