Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Aug 2013 19:40:01 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r254423 - head/sys/dev/sdhci
Message-ID:  <201308161940.r7GJe17H025945@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Fri Aug 16 19:40:00 2013
New Revision: 254423
URL: http://svnweb.freebsd.org/changeset/base/254423

Log:
  When the timeout clock is based on the SD clock, the timeout counter
  has to be recalculated every time the SD clock frequency changes.
  
  Also, tidy up the counter calculation... it makes no sense to calculate
  a value one larger than the limit, then whine that it's too large and
  truncate it to the limit.  If the BROKEN_TIMEOUT quirk is set, don't
  calculate the counter at all, just set it to the limit value.

Modified:
  head/sys/dev/sdhci/sdhci.c

Modified: head/sys/dev/sdhci/sdhci.c
==============================================================================
--- head/sys/dev/sdhci/sdhci.c	Fri Aug 16 19:33:36 2013	(r254422)
+++ head/sys/dev/sdhci/sdhci.c	Fri Aug 16 19:40:00 2013	(r254423)
@@ -238,6 +238,11 @@ sdhci_set_clock(struct sdhci_slot *slot,
 	/* If no clock requested - left it so. */
 	if (clock == 0)
 		return;
+
+	/* Recalculate timeout clock frequency based on the new sd clock. */
+	if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
+		slot->timeout_clk = slot->clock / 1000;
+
 	if (slot->version < SDHCI_SPEC_300) {
 		/* Looking for highest freq <= clock. */
 		res = slot->max_clk;
@@ -545,7 +550,8 @@ sdhci_init_slot(device_t dev, struct sdh
 
 	if (slot->timeout_clk == 0) {
 		device_printf(dev, "Hardware doesn't specify timeout clock "
-		    "frequency.\n");
+		    "frequency, setting BROKEN_TIMEOUT quirk.\n");
+		slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 	}
 
 	slot->host.f_min = SDHCI_MIN_FREQ(slot->bus, slot);
@@ -855,24 +861,22 @@ sdhci_start_data(struct sdhci_slot *slot
 
 	/* Calculate and set data timeout.*/
 	/* XXX: We should have this from mmc layer, now assume 1 sec. */
-	target_timeout = 1000000;
-	div = 0;
-	current_timeout = (1 << 13) * 1000 / slot->timeout_clk;
-	while (current_timeout < target_timeout) {
-		div++;
-		current_timeout <<= 1;
-		if (div >= 0xF)
-			break;
-	}
-	/* Compensate for an off-by-one error in the CaFe chip.*/
-	if (slot->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)
-		div++;
-	if (div >= 0xF) {
-		slot_printf(slot, "Timeout too large!\n");
+	if (slot->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) {
 		div = 0xE;
+	} else {
+		target_timeout = 1000000;
+		div = 0;
+		current_timeout = (1 << 13) * 1000 / slot->timeout_clk;
+		while (current_timeout < target_timeout && div < 0xE) {
+			++div;
+			current_timeout <<= 1;
+		}
+		/* Compensate for an off-by-one error in the CaFe chip.*/
+		if (div < 0xE && 
+		    (slot->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)) {
+			++div;
+		}
 	}
-	if (slot->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
-		div = 0xE;
 	WR1(slot, SDHCI_TIMEOUT_CONTROL, div);
 
 	if (data == NULL)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308161940.r7GJe17H025945>