stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 4.14] mmc: sdhci-msm: Disable CDR function on TX
@ 2019-01-18 13:39 Georgi Djakov
  2019-01-18 13:40 ` [PATCH 4.19,4.20] " Georgi Djakov
  2019-01-18 15:59 ` [PATCH 4.14] " Greg KH
  0 siblings, 2 replies; 3+ messages in thread
From: Georgi Djakov @ 2019-01-18 13:39 UTC (permalink / raw)
  To: stable; +Cc: loic.poulain, georgi.djakov

From: Loic Poulain <loic.poulain@linaro.org>

commit a89e7bcb18081c611eb6cf50edd440fa4983a71a upstream.

The Clock Data Recovery (CDR) circuit allows to automatically adjust
the RX sampling-point/phase for high frequency cards (SDR104, HS200...).
CDR is automatically enabled during DLL configuration.
However, according to the APQ8016 reference manual, this function
must be disabled during TX and tuning phase in order to prevent any
interferences during tuning challenges and unexpected phase alteration
during TX transfers.

This patch enables/disables CDR according to the current transfer mode.

This fixes sporadic write transfer issues observed with some SDR104 and
HS200 cards.

Inspired by sdhci-msm downstream patch:
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/432516/

Reported-by: Leonid Segal <leonid.s@variscite.com>
Reported-by: Manabu Igusa <migusa@arrowjapan.com>
Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Georgi Djakov <georgi.djakov@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
[georgi: backport to v4.14]
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/mmc/host/sdhci-msm.c | 51 +++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 92c483ec6cb2..192844b50c69 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -138,6 +138,8 @@ struct sdhci_msm_host {
 	bool calibration_done;
 	u8 saved_tuning_phase;
 	bool use_cdclp533;
+	bool use_cdr;
+	u32 transfer_mode;
 };
 
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
@@ -815,6 +817,23 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
 	return ret;
 }
 
+static void sdhci_msm_set_cdr(struct sdhci_host *host, bool enable)
+{
+	u32 config, oldconfig = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+
+	config = oldconfig;
+	if (enable) {
+		config |= CORE_CDR_EN;
+		config &= ~CORE_CDR_EXT_EN;
+	} else {
+		config &= ~CORE_CDR_EN;
+		config |= CORE_CDR_EXT_EN;
+	}
+
+	if (config != oldconfig)
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+}
+
 static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -832,8 +851,14 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	if (host->clock <= CORE_FREQ_100MHZ ||
 	    !(ios.timing == MMC_TIMING_MMC_HS400 ||
 	    ios.timing == MMC_TIMING_MMC_HS200 ||
-	    ios.timing == MMC_TIMING_UHS_SDR104))
+	    ios.timing == MMC_TIMING_UHS_SDR104)) {
+		msm_host->use_cdr = false;
+		sdhci_msm_set_cdr(host, false);
 		return 0;
+	}
+
+	/* Clock-Data-Recovery used to dynamically adjust RX sampling point */
+	msm_host->use_cdr = true;
 
 	/*
 	 * For HS400 tuning in HS200 timing requires:
@@ -1092,6 +1117,29 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 	__sdhci_msm_set_clock(host, clock);
 }
 
+static void sdhci_msm_write_w(struct sdhci_host *host, u16 val, int reg)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+	switch (reg) {
+	case SDHCI_TRANSFER_MODE:
+		msm_host->transfer_mode = val;
+		break;
+	case SDHCI_COMMAND:
+		if (!msm_host->use_cdr)
+			break;
+		if ((msm_host->transfer_mode & SDHCI_TRNS_READ) &&
+		    (SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK_HS200) &&
+		    (SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK))
+			sdhci_msm_set_cdr(host, true);
+		else
+			sdhci_msm_set_cdr(host, false);
+		break;
+	}
+	writew(val, host->ioaddr + reg);
+}
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
 	{ .compatible = "qcom,sdhci-msm-v4" },
 	{},
@@ -1107,6 +1155,7 @@ static const struct sdhci_ops sdhci_msm_ops = {
 	.set_bus_width = sdhci_set_bus_width,
 	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
 	.voltage_switch = sdhci_msm_voltage_switch,
+	.write_w = sdhci_msm_write_w,
 };
 
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 4.19,4.20] mmc: sdhci-msm: Disable CDR function on TX
  2019-01-18 13:39 [PATCH 4.14] mmc: sdhci-msm: Disable CDR function on TX Georgi Djakov
@ 2019-01-18 13:40 ` Georgi Djakov
  2019-01-18 15:59 ` [PATCH 4.14] " Greg KH
  1 sibling, 0 replies; 3+ messages in thread
From: Georgi Djakov @ 2019-01-18 13:40 UTC (permalink / raw)
  To: stable; +Cc: loic.poulain, georgi.djakov

From: Loic Poulain <loic.poulain@linaro.org>

commit a89e7bcb18081c611eb6cf50edd440fa4983a71a upstream.

The Clock Data Recovery (CDR) circuit allows to automatically adjust
the RX sampling-point/phase for high frequency cards (SDR104, HS200...).
CDR is automatically enabled during DLL configuration.
However, according to the APQ8016 reference manual, this function
must be disabled during TX and tuning phase in order to prevent any
interferences during tuning challenges and unexpected phase alteration
during TX transfers.

This patch enables/disables CDR according to the current transfer mode.

This fixes sporadic write transfer issues observed with some SDR104 and
HS200 cards.

Inspired by sdhci-msm downstream patch:
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/432516/

Reported-by: Leonid Segal <leonid.s@variscite.com>
Reported-by: Manabu Igusa <migusa@arrowjapan.com>
Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Georgi Djakov <georgi.djakov@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
[georgi: backport to v4.19+]
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/mmc/host/sdhci-msm.c | 43 +++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 3cc8bfee6c18..8594659cb592 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -258,6 +258,8 @@ struct sdhci_msm_host {
 	bool mci_removed;
 	const struct sdhci_msm_variant_ops *var_ops;
 	const struct sdhci_msm_offset *offset;
+	bool use_cdr;
+	u32 transfer_mode;
 };
 
 static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
@@ -1025,6 +1027,26 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
 	return ret;
 }
 
+static void sdhci_msm_set_cdr(struct sdhci_host *host, bool enable)
+{
+	const struct sdhci_msm_offset *msm_offset = sdhci_priv_msm_offset(host);
+	u32 config, oldconfig = readl_relaxed(host->ioaddr +
+					      msm_offset->core_dll_config);
+
+	config = oldconfig;
+	if (enable) {
+		config |= CORE_CDR_EN;
+		config &= ~CORE_CDR_EXT_EN;
+	} else {
+		config &= ~CORE_CDR_EN;
+		config |= CORE_CDR_EXT_EN;
+	}
+
+	if (config != oldconfig)
+		writel_relaxed(config, host->ioaddr +
+			       msm_offset->core_dll_config);
+}
+
 static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -1042,8 +1064,14 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	if (host->clock <= CORE_FREQ_100MHZ ||
 	    !(ios.timing == MMC_TIMING_MMC_HS400 ||
 	    ios.timing == MMC_TIMING_MMC_HS200 ||
-	    ios.timing == MMC_TIMING_UHS_SDR104))
+	    ios.timing == MMC_TIMING_UHS_SDR104)) {
+		msm_host->use_cdr = false;
+		sdhci_msm_set_cdr(host, false);
 		return 0;
+	}
+
+	/* Clock-Data-Recovery used to dynamically adjust RX sampling point */
+	msm_host->use_cdr = true;
 
 	/*
 	 * For HS400 tuning in HS200 timing requires:
@@ -1525,6 +1553,19 @@ static int __sdhci_msm_check_write(struct sdhci_host *host, u16 val, int reg)
 	case SDHCI_POWER_CONTROL:
 		req_type = !val ? REQ_BUS_OFF : REQ_BUS_ON;
 		break;
+	case SDHCI_TRANSFER_MODE:
+		msm_host->transfer_mode = val;
+		break;
+	case SDHCI_COMMAND:
+		if (!msm_host->use_cdr)
+			break;
+		if ((msm_host->transfer_mode & SDHCI_TRNS_READ) &&
+		    SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK_HS200 &&
+		    SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK)
+			sdhci_msm_set_cdr(host, true);
+		else
+			sdhci_msm_set_cdr(host, false);
+		break;
 	}
 
 	if (req_type) {

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 4.14] mmc: sdhci-msm: Disable CDR function on TX
  2019-01-18 13:39 [PATCH 4.14] mmc: sdhci-msm: Disable CDR function on TX Georgi Djakov
  2019-01-18 13:40 ` [PATCH 4.19,4.20] " Georgi Djakov
@ 2019-01-18 15:59 ` Greg KH
  1 sibling, 0 replies; 3+ messages in thread
From: Greg KH @ 2019-01-18 15:59 UTC (permalink / raw)
  To: Georgi Djakov; +Cc: stable, loic.poulain

On Fri, Jan 18, 2019 at 03:39:59PM +0200, Georgi Djakov wrote:
> From: Loic Poulain <loic.poulain@linaro.org>
> 
> commit a89e7bcb18081c611eb6cf50edd440fa4983a71a upstream.
> 
> The Clock Data Recovery (CDR) circuit allows to automatically adjust
> the RX sampling-point/phase for high frequency cards (SDR104, HS200...).
> CDR is automatically enabled during DLL configuration.
> However, according to the APQ8016 reference manual, this function
> must be disabled during TX and tuning phase in order to prevent any
> interferences during tuning challenges and unexpected phase alteration
> during TX transfers.
> 
> This patch enables/disables CDR according to the current transfer mode.
> 
> This fixes sporadic write transfer issues observed with some SDR104 and
> HS200 cards.
> 
> Inspired by sdhci-msm downstream patch:
> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/432516/
> 
> Reported-by: Leonid Segal <leonid.s@variscite.com>
> Reported-by: Manabu Igusa <migusa@arrowjapan.com>
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> Acked-by: Georgi Djakov <georgi.djakov@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> [georgi: backport to v4.14]
> Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>

Both patches now applied, thanks.

greg k-h

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-01-18 15:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-01-18 13:39 [PATCH 4.14] mmc: sdhci-msm: Disable CDR function on TX Georgi Djakov
2019-01-18 13:40 ` [PATCH 4.19,4.20] " Georgi Djakov
2019-01-18 15:59 ` [PATCH 4.14] " Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).