svn commit: r266751 - in stable/10/sys: arm/conf arm/ti arm/ti/omap4 boot/fdt/dts/arm dev/sdhci

Ian Lepore ian at FreeBSD.org
Tue May 27 15:30:25 UTC 2014


Author: ian
Date: Tue May 27 15:30:24 2014
New Revision: 266751
URL: http://svnweb.freebsd.org/changeset/base/266751

Log:
  MFC r264096, r264097, r264099 r264100, r264101, r264102, r264119:
  
  Fixes to the ti_sdhci and sdhci drivers (fix clock divisor calcs).
  
  Use the ti_sdhci driver instead of ti_mmchs for Pandaboard.

Modified:
  stable/10/sys/arm/conf/PANDABOARD
  stable/10/sys/arm/ti/omap4/files.omap4
  stable/10/sys/arm/ti/ti_sdhci.c
  stable/10/sys/boot/fdt/dts/arm/beaglebone-black.dts
  stable/10/sys/boot/fdt/dts/arm/pandaboard.dts
  stable/10/sys/dev/sdhci/sdhci.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/arm/conf/PANDABOARD
==============================================================================
--- stable/10/sys/arm/conf/PANDABOARD	Tue May 27 15:30:06 2014	(r266750)
+++ stable/10/sys/arm/conf/PANDABOARD	Tue May 27 15:30:24 2014	(r266751)
@@ -76,6 +76,7 @@ options 	PREEMPTION
 # MMC/SD/SDIO Card slot support
 device		mmc			# mmc/sd bus
 device		mmcsd			# mmc/sd flash cards
+device		sdhci			# mmc/sd host controller
 
 # I2C support
 device		iicbus

Modified: stable/10/sys/arm/ti/omap4/files.omap4
==============================================================================
--- stable/10/sys/arm/ti/omap4/files.omap4	Tue May 27 15:30:06 2014	(r266750)
+++ stable/10/sys/arm/ti/omap4/files.omap4	Tue May 27 15:30:24 2014	(r266751)
@@ -6,7 +6,8 @@ arm/ti/ti_smc.S					standard
 
 arm/ti/usb/omap_ehci.c				optional	usb ehci
 arm/ti/ti_sdma.c				optional	ti_sdma
-arm/ti/ti_mmchs.c				optional	mmc
+arm/ti/ti_sdhci.c 				optional	sdhci
+#arm/ti/ti_mmchs.c				optional	mmc
 
 arm/ti/omap4/omap4_l2cache.c			optional	pl310
 arm/ti/omap4/omap4_prcm_clks.c			standard

Modified: stable/10/sys/arm/ti/ti_sdhci.c
==============================================================================
--- stable/10/sys/arm/ti/ti_sdhci.c	Tue May 27 15:30:06 2014	(r266750)
+++ stable/10/sys/arm/ti/ti_sdhci.c	Tue May 27 15:30:24 2014	(r266751)
@@ -72,6 +72,8 @@ struct ti_sdhci_softc {
 	uint32_t		wp_gpio_pin;
 	uint32_t		cmd_and_mode;
 	uint32_t		sdhci_clkdiv;
+	boolean_t		disable_highspeed;
+	boolean_t		force_card_present;
 };
 
 /*
@@ -105,9 +107,13 @@ static struct ofw_compat_data compat_dat
 #define	MMCHS_SYSCONFIG			0x010
 #define	  MMCHS_SYSCONFIG_RESET		  (1 << 1)
 #define	MMCHS_SYSSTATUS			0x014
+#define	  MMCHS_SYSSTATUS_RESETDONE	  (1 << 0)
 #define	MMCHS_CON			0x02C
 #define	  MMCHS_CON_DW8			  (1 << 5)
 #define	  MMCHS_CON_DVAL_8_4MS		  (3 << 9)
+#define MMCHS_SYSCTL			0x12C
+#define   MMCHS_SYSCTL_CLKD_MASK	   0x3FF
+#define   MMCHS_SYSCTL_CLKD_SHIFT	   6
 #define	MMCHS_SD_CAPA			0x140
 #define	  MMCHS_SD_CAPA_VS18		  (1 << 26)
 #define	  MMCHS_SD_CAPA_VS30		  (1 << 25)
@@ -161,19 +167,22 @@ ti_sdhci_read_2(device_t dev, struct sdh
 	 * but doesn't split them into low:high fields.  Instead they're a
 	 * single number in the range 0..1023 and the number is exactly the
 	 * clock divisor (with 0 and 1 both meaning divide by 1).  The SDHCI
-	 * driver code expects a v2.0 divisor (value N is power of two in the
-	 * range 0..128 and clock is divided by 2N).  The shifting and masking
+	 * driver code expects a v2.0 or v3.0 divisor.  The shifting and masking
 	 * here extracts the MMCHS representation from the hardware word, cleans
-	 * those bits out, applies the 2N adjustment, and plugs that into the
-	 * bit positions for the 2.0 divisor in the returned register value. The
-	 * ti_sdhci_write_2() routine performs the opposite transformation when
-	 * the SDHCI driver writes to the register.
+	 * those bits out, applies the 2N adjustment, and plugs the result into
+	 * the bit positions for the 2.0 or 3.0 divisor in the returned register
+	 * value. The ti_sdhci_write_2() routine performs the opposite
+	 * transformation when the SDHCI driver writes to the register.
 	 */
 	if (off == SDHCI_CLOCK_CONTROL) {
 		val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
-		clkdiv = (val32 >> SDHCI_DIVIDER_HI_SHIFT) & 0xff;
-		val32 &= ~(0xff << SDHCI_DIVIDER_HI_SHIFT);
-		val32 |= (clkdiv / 2) << SDHCI_DIVIDER_SHIFT;
+		clkdiv = ((val32 >> MMCHS_SYSCTL_CLKD_SHIFT) &
+		    MMCHS_SYSCTL_CLKD_MASK) / 2;
+		val32 &= ~(MMCHS_SYSCTL_CLKD_MASK << MMCHS_SYSCTL_CLKD_SHIFT);
+		val32 |= (clkdiv & SDHCI_DIVIDER_MASK) << SDHCI_DIVIDER_SHIFT;
+		if (slot->version >= SDHCI_SPEC_300)
+			val32 |= ((clkdiv >> SDHCI_DIVIDER_MASK_LEN) &
+			    SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_HI_SHIFT;
 		return (val32 & 0xffff);
 	}
 
@@ -193,8 +202,24 @@ static uint32_t
 ti_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
 {
 	struct ti_sdhci_softc *sc = device_get_softc(dev);
+	uint32_t val32;
+
+	val32 = RD4(sc, off);
+
+	/*
+	 * If we need to disallow highspeed mode due to the OMAP4 erratum, strip
+	 * that flag from the returned capabilities.
+	 */
+	if (off == SDHCI_CAPABILITIES && sc->disable_highspeed)
+		val32 &= ~SDHCI_CAN_DO_HISPD;
+
+	/*
+	 * Force the card-present state if necessary.
+	 */
+	if (off == SDHCI_PRESENT_STATE && sc->force_card_present)
+		val32 |= SDHCI_CARD_PRESENT;
 
-	return (RD4(sc, off));
+	return (val32);
 }
 
 static void
@@ -228,15 +253,23 @@ ti_sdhci_write_2(device_t dev, struct sd
 	uint32_t clkdiv, val32;
 
 	/*
-	 * Translate between the hardware and SDHCI 2.0 representations of the
-	 * clock divisor.  See the comments in ti_sdhci_read_2() for details.
+	 * Translate between the hardware and SDHCI 2.0 or 3.0 representations
+	 * of the clock divisor.  See the comments in ti_sdhci_read_2() for
+	 * details.
 	 */
 	if (off == SDHCI_CLOCK_CONTROL) {
 		clkdiv = (val >> SDHCI_DIVIDER_SHIFT) & SDHCI_DIVIDER_MASK;
+		if (slot->version >= SDHCI_SPEC_300)
+			clkdiv |= ((val >> SDHCI_DIVIDER_HI_SHIFT) &
+			    SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_MASK_LEN;
+		clkdiv *= 2;
+		if (clkdiv > MMCHS_SYSCTL_CLKD_MASK)
+			clkdiv = MMCHS_SYSCTL_CLKD_MASK;
 		val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
 		val32 &= 0xffff0000;
-		val32 |= val & ~(SDHCI_DIVIDER_MASK << SDHCI_DIVIDER_SHIFT);
-		val32 |= (clkdiv * 2) << SDHCI_DIVIDER_HI_SHIFT;
+		val32 |= val & ~(MMCHS_SYSCTL_CLKD_MASK <<
+		    MMCHS_SYSCTL_CLKD_SHIFT);
+		val32 |= clkdiv << MMCHS_SYSCTL_CLKD_SHIFT;
 		WR4(sc, SDHCI_CLOCK_CONTROL, val32);
 		return;
 	}
@@ -358,7 +391,7 @@ ti_sdhci_hw_init(device_t dev)
 	/* Issue a softreset to the controller */
 	ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET);
 	timeout = 1000;
-	while ((ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & MMCHS_SYSCONFIG_RESET)) {
+	while (!(ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & MMCHS_SYSSTATUS_RESETDONE)) {
 		if (--timeout == 0) {
 			device_printf(dev, "Error: Controller reset operation timed out\n");
 			break;
@@ -458,12 +491,14 @@ ti_sdhci_attach(device_t dev)
 
 	/*
 	 * Set the offset from the device's memory start to the MMCHS registers.
+	 * Also for OMAP4 disable high speed mode due to erratum ID i626.
 	 */
 	if (ti_chip() == CHIP_OMAP_3)
 		sc->mmchs_reg_off = OMAP3_MMCHS_REG_OFFSET;
-	else if (ti_chip() == CHIP_OMAP_4)
+	else if (ti_chip() == CHIP_OMAP_4) {
 		sc->mmchs_reg_off = OMAP4_MMCHS_REG_OFFSET;
-	else if (ti_chip() == CHIP_AM335X)
+		sc->disable_highspeed = true;
+        } else if (ti_chip() == CHIP_AM335X)
 		sc->mmchs_reg_off = AM335X_MMCHS_REG_OFFSET;
 	else
 		panic("Unknown OMAP device\n");
@@ -560,6 +595,14 @@ ti_sdhci_attach(device_t dev)
 		}
 	}
 
+	/*
+	 * If the slot is flagged with the non-removable property, set our flag
+	 * to always force the SDHCI_CARD_PRESENT bit on.
+	 */
+	node = ofw_bus_get_node(dev);
+	if (OF_hasprop(node, "non-removable"))
+		sc->force_card_present = true;
+
 	bus_generic_probe(dev);
 	bus_generic_attach(dev);
 

Modified: stable/10/sys/boot/fdt/dts/arm/beaglebone-black.dts
==============================================================================
--- stable/10/sys/boot/fdt/dts/arm/beaglebone-black.dts	Tue May 27 15:30:06 2014	(r266750)
+++ stable/10/sys/boot/fdt/dts/arm/beaglebone-black.dts	Tue May 27 15:30:24 2014	(r266751)
@@ -142,6 +142,7 @@
 		mmchs1 at 481D8000 {
                 	bus-width = <8>;
 			status = "okay";
+			non-removable;
 		};
 
  

Modified: stable/10/sys/boot/fdt/dts/arm/pandaboard.dts
==============================================================================
--- stable/10/sys/boot/fdt/dts/arm/pandaboard.dts	Tue May 27 15:30:06 2014	(r266750)
+++ stable/10/sys/boot/fdt/dts/arm/pandaboard.dts	Tue May 27 15:30:24 2014	(r266751)
@@ -174,6 +174,7 @@
 			interrupts = <115>;
 			interrupt-parent = <&GIC>;
 			mmchs-device-id = <1>;
+			non-removable; /* XXX need real solution */
 		};
 
 	};

Modified: stable/10/sys/dev/sdhci/sdhci.c
==============================================================================
--- stable/10/sys/dev/sdhci/sdhci.c	Tue May 27 15:30:06 2014	(r266750)
+++ stable/10/sys/dev/sdhci/sdhci.c	Tue May 27 15:30:24 2014	(r266751)
@@ -235,7 +235,8 @@ sdhci_set_clock(struct sdhci_slot *slot,
 	slot->clock = clock;
 
 	/* Turn off the clock. */
-	WR2(slot, SDHCI_CLOCK_CONTROL, 0);
+	clk = RD2(slot, SDHCI_CLOCK_CONTROL);
+	WR2(slot, SDHCI_CLOCK_CONTROL, clk & ~SDHCI_CLOCK_CARD_EN);
 	/* If no clock requested - left it so. */
 	if (clock == 0)
 		return;


More information about the svn-src-stable-10 mailing list