svn commit: r254507 - head/sys/dev/sdhci

Ian Lepore ian at FreeBSD.org
Mon Aug 19 01:29:14 UTC 2013


Author: ian
Date: Mon Aug 19 01:29:13 2013
New Revision: 254507
URL: http://svnweb.freebsd.org/changeset/base/254507

Log:
  Allow a hardware driver to pass clock frequencies into the sdhci driver.
  
  The sdhci spec says that if the base or timeout clock frequency in the
  capabilities register is zero, the driver must obtain the frequency "from
  another source."  This change defines that other source to be the low-level
  hardware driver, which can pre-set the frequencies in slot.max_clk and
  slot.timeout_clk before calling sdhci_init_slot().
  
  This helps with a growing number of SoCs that have sdhci base clock
  frequencies that either won't fit into the range allowed by the number of
  bits available in the capabilities register, or the frequency is runtime-
  configurable.

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

Modified: head/sys/dev/sdhci/sdhci.c
==============================================================================
--- head/sys/dev/sdhci/sdhci.c	Sun Aug 18 23:40:30 2013	(r254506)
+++ head/sys/dev/sdhci/sdhci.c	Mon Aug 19 01:29:13 2013	(r254507)
@@ -477,7 +477,7 @@ sdhci_card_task(void *arg, int pending)
 int
 sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
 {
-	uint32_t caps;
+	uint32_t caps, freq;
 	int err;
 
 	SDHCI_LOCK_INIT(slot);
@@ -527,17 +527,23 @@ sdhci_init_slot(device_t dev, struct sdh
 		caps = RD4(slot, SDHCI_CAPABILITIES);
 	/* Calculate base clock frequency. */
 	if (slot->version >= SDHCI_SPEC_300)
-		slot->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) 
-		    >> SDHCI_CLOCK_BASE_SHIFT;
+		freq = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
+		    SDHCI_CLOCK_BASE_SHIFT;
 	else	
-		slot->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) 
-		    >> SDHCI_CLOCK_BASE_SHIFT;
+		freq = (caps & SDHCI_CLOCK_BASE_MASK) >>
+		    SDHCI_CLOCK_BASE_SHIFT;
+	if (freq != 0)
+		slot->max_clk = freq * 1000000;
+	/*
+	 * If the frequency wasn't in the capabilities and the hardware driver
+	 * hasn't already set max_clk we're probably not going to work right
+	 * with an assumption, so complain about it.
+	 */
 	if (slot->max_clk == 0) {
-		slot->max_clk = SDHCI_DEFAULT_MAX_FREQ;
+		slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000;
 		device_printf(dev, "Hardware doesn't specify base clock "
 		    "frequency, using %dMHz as default.\n", SDHCI_DEFAULT_MAX_FREQ);
 	}
-	slot->max_clk *= 1000000;
 	/* Calculate timeout clock frequency. */
 	if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) {
 		slot->timeout_clk = slot->max_clk / 1000;
@@ -547,7 +553,11 @@ sdhci_init_slot(device_t dev, struct sdh
 		if (caps & SDHCI_TIMEOUT_CLK_UNIT)
 			slot->timeout_clk *= 1000;
 	}
-
+	/*
+	 * If the frequency wasn't in the capabilities and the hardware driver
+	 * hasn't already set timeout_clk we'll probably work okay using the
+	 * max timeout, but still mention it.
+	 */
 	if (slot->timeout_clk == 0) {
 		device_printf(dev, "Hardware doesn't specify timeout clock "
 		    "frequency, setting BROKEN_TIMEOUT quirk.\n");


More information about the svn-src-all mailing list