All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] mmc: omap_hsmmc: Workaround errata regarding SDR104/HS200 tuning failures (i929)
@ 2019-01-30 12:38 Faiz Abbas
  2019-02-10 13:09 ` [U-Boot] " Tom Rini
  0 siblings, 1 reply; 2+ messages in thread
From: Faiz Abbas @ 2019-01-30 12:38 UTC (permalink / raw)
  To: u-boot

Errata i929 in certain OMAP5/DRA7XX/AM57XX silicon revisions
(SPRZ426D - November 2014 - Revised February 2018 [1]) mentions
unexpected tuning pattern errors. A small failure band may be present
in the tuning range which may be missed by the current algorithm.
Furthermore, the failure bands vary with temperature leading to
different optimum tuning values for different temperatures.

As suggested in the related Application Report (SPRACA9B - October 2017
- Revised July 2018 [2]), tuning should be done in two stages.
In stage 1, assign the optimum ratio in the maximum pass window for the
current temperature. In stage 2, if the chosen value is close to the
small failure band, move away from it in the appropriate direction.

References:
[1] http://www.ti.com/lit/pdf/sprz426
[2] http://www.ti.com/lit/pdf/SPRACA9

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
---
 drivers/mmc/omap_hsmmc.c | 92 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 5cb97eb02a..b11c71cae7 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -47,6 +47,7 @@
 #endif
 #include <dm.h>
 #include <power/regulator.h>
+#include <thermal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -622,6 +623,10 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
 	u32 phase_delay = 0;
 	u32 start_window = 0, max_window = 0;
 	u32 length = 0, max_len = 0;
+	bool single_point_failure = false;
+	struct udevice *thermal_dev;
+	int temperature;
+	int i;
 
 	mmc_base = priv->base_addr;
 	val = readl(&mmc_base->capa2);
@@ -632,9 +637,25 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
 	      ((mmc->selected_mode == UHS_SDR50) && (val & CAPA2_TSDR50))))
 		return 0;
 
+	ret = uclass_first_device(UCLASS_THERMAL, &thermal_dev);
+	if (ret) {
+		printf("Couldn't get thermal device for tuning\n");
+		return ret;
+	}
+	ret = thermal_get_temp(thermal_dev, &temperature);
+	if (ret) {
+		printf("Couldn't get temperature for tuning\n");
+		return ret;
+	}
 	val = readl(&mmc_base->dll);
 	val |= DLL_SWT;
 	writel(val, &mmc_base->dll);
+
+	/*
+	 * Stage 1: Search for a maximum pass window ignoring any
+	 * any single point failures. If the tuning value ends up
+	 * near it, move away from it in stage 2 below
+	 */
 	while (phase_delay <= MAX_PHASE_DELAY) {
 		omap_hsmmc_set_dll(mmc, phase_delay);
 
@@ -643,10 +664,16 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
 		if (cur_match) {
 			if (prev_match) {
 				length++;
+			} else if (single_point_failure) {
+				/* ignore single point failure */
+				length++;
+				single_point_failure = false;
 			} else {
 				start_window = phase_delay;
 				length = 1;
 			}
+		} else {
+			single_point_failure = prev_match;
 		}
 
 		if (length > max_len) {
@@ -668,8 +695,71 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
 		ret = -EIO;
 		goto tuning_error;
 	}
+	/*
+	 * Assign tuning value as a ratio of maximum pass window based
+	 * on temperature
+	 */
+	if (temperature < -20000)
+		phase_delay = min(max_window + 4 * max_len - 24,
+				  max_window +
+				  DIV_ROUND_UP(13 * max_len, 16) * 4);
+	else if (temperature < 20000)
+		phase_delay = max_window + DIV_ROUND_UP(9 * max_len, 16) * 4;
+	else if (temperature < 40000)
+		phase_delay = max_window + DIV_ROUND_UP(8 * max_len, 16) * 4;
+	else if (temperature < 70000)
+		phase_delay = max_window + DIV_ROUND_UP(7 * max_len, 16) * 4;
+	else if (temperature < 90000)
+		phase_delay = max_window + DIV_ROUND_UP(5 * max_len, 16) * 4;
+	else if (temperature < 120000)
+		phase_delay = max_window + DIV_ROUND_UP(4 * max_len, 16) * 4;
+	else
+		phase_delay = max_window + DIV_ROUND_UP(3 * max_len, 16) * 4;
+
+	/*
+	 * Stage 2: Search for a single point failure near the chosen tuning
+	 * value in two steps. First in the +3 to +10 range and then in the
+	 * +2 to -10 range. If found, move away from it in the appropriate
+	 * direction by the appropriate amount depending on the temperature.
+	 */
+	for (i = 3; i <= 10; i++) {
+		omap_hsmmc_set_dll(mmc, phase_delay + i);
+		if (mmc_send_tuning(mmc, opcode, NULL)) {
+			if (temperature < 10000)
+				phase_delay += i + 6;
+			else if (temperature < 20000)
+				phase_delay += i - 12;
+			else if (temperature < 70000)
+				phase_delay += i - 8;
+			else if (temperature < 90000)
+				phase_delay += i - 6;
+			else
+				phase_delay += i - 6;
+
+			goto single_failure_found;
+		}
+	}
+
+	for (i = 2; i >= -10; i--) {
+		omap_hsmmc_set_dll(mmc, phase_delay + i);
+		if (mmc_send_tuning(mmc, opcode, NULL)) {
+			if (temperature < 10000)
+				phase_delay += i + 12;
+			else if (temperature < 20000)
+				phase_delay += i + 8;
+			else if (temperature < 70000)
+				phase_delay += i + 8;
+			else if (temperature < 90000)
+				phase_delay += i + 10;
+			else
+				phase_delay += i + 12;
+
+			goto single_failure_found;
+		}
+	}
+
+single_failure_found:
 
-	phase_delay = max_window + 4 * ((3 * max_len) >> 2);
 	omap_hsmmc_set_dll(mmc, phase_delay);
 
 	mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
-- 
2.19.2

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

* [U-Boot] mmc: omap_hsmmc: Workaround errata regarding SDR104/HS200 tuning failures (i929)
  2019-01-30 12:38 [U-Boot] [PATCH] mmc: omap_hsmmc: Workaround errata regarding SDR104/HS200 tuning failures (i929) Faiz Abbas
@ 2019-02-10 13:09 ` Tom Rini
  0 siblings, 0 replies; 2+ messages in thread
From: Tom Rini @ 2019-02-10 13:09 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 30, 2019 at 06:08:42PM +0530, Faiz Abbas wrote:

> Errata i929 in certain OMAP5/DRA7XX/AM57XX silicon revisions
> (SPRZ426D - November 2014 - Revised February 2018 [1]) mentions
> unexpected tuning pattern errors. A small failure band may be present
> in the tuning range which may be missed by the current algorithm.
> Furthermore, the failure bands vary with temperature leading to
> different optimum tuning values for different temperatures.
> 
> As suggested in the related Application Report (SPRACA9B - October 2017
> - Revised July 2018 [2]), tuning should be done in two stages.
> In stage 1, assign the optimum ratio in the maximum pass window for the
> current temperature. In stage 2, if the chosen value is close to the
> small failure band, move away from it in the appropriate direction.
> 
> References:
> [1] http://www.ti.com/lit/pdf/sprz426
> [2] http://www.ti.com/lit/pdf/SPRACA9
> 
> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190210/5fd0658b/attachment.sig>

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

end of thread, other threads:[~2019-02-10 13:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-30 12:38 [U-Boot] [PATCH] mmc: omap_hsmmc: Workaround errata regarding SDR104/HS200 tuning failures (i929) Faiz Abbas
2019-02-10 13:09 ` [U-Boot] " Tom Rini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.