Module Name:    src
Committed By:   riastradh
Date:           Thu Dec 13 06:43:38 UTC 2012

Modified Files:
        src/sys/arch/arm/omap: omap3_sdhc.c
        src/sys/dev/sdmmc: sdhc.c sdhcvar.h

Log Message:
Implement TI AM335x's SDHC reset quirk.  Beaglebone SDHC works now!

On the AM335x, we first must wait for the controller to acknowledge
the reset; then we can wait for the reset to complete.

I believe this quirk also applies to the OMAP4 ES, but I don't have
one of those to test and we don't seem to have an obvious conditional
for it anyway.

This quirk may work for controllers that don't require it too, but I
am nervous about doing it by default because if we miss the reset
acknowledgement, then we'll just time out even though everything is
really hunky-dory.

Also, for all sdhc, don't bother writing 0 in sdhc_soft_reset while
waiting for the reset to complete; there is no need.

ok matt


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/omap/omap3_sdhc.c
cvs rdiff -u -r1.34 -r1.35 src/sys/dev/sdmmc/sdhc.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/sdmmc/sdhcvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/omap/omap3_sdhc.c
diff -u src/sys/arch/arm/omap/omap3_sdhc.c:1.5 src/sys/arch/arm/omap/omap3_sdhc.c:1.6
--- src/sys/arch/arm/omap/omap3_sdhc.c:1.5	Wed Dec 12 15:19:53 2012
+++ src/sys/arch/arm/omap/omap3_sdhc.c	Thu Dec 13 06:43:38 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: omap3_sdhc.c,v 1.5 2012/12/12 15:19:53 matt Exp $	*/
+/*	$NetBSD: omap3_sdhc.c,v 1.6 2012/12/13 06:43:38 riastradh Exp $	*/
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.5 2012/12/12 15:19:53 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.6 2012/12/13 06:43:38 riastradh Exp $");
 
 #include "opt_omap.h"
 
@@ -150,6 +150,9 @@ obiosdhc_attach(device_t parent, device_
 	sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
 	sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
 	sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY;
+#ifdef TI_AM335X
+	sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET;
+#endif
 	sc->sc.sc_host = sc->sc_hosts;
 	sc->sc.sc_clkbase = 96000;	/* 96MHZ */
 	if (!prop_dictionary_get_uint32(prop, "clkmask", &sc->sc.sc_clkmsk))

Index: src/sys/dev/sdmmc/sdhc.c
diff -u src/sys/dev/sdmmc/sdhc.c:1.34 src/sys/dev/sdmmc/sdhc.c:1.35
--- src/sys/dev/sdmmc/sdhc.c:1.34	Wed Dec 12 15:15:31 2012
+++ src/sys/dev/sdmmc/sdhc.c	Thu Dec 13 06:43:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhc.c,v 1.34 2012/12/12 15:15:31 matt Exp $	*/
+/*	$NetBSD: sdhc.c,v 1.35 2012/12/13 06:43:37 riastradh Exp $	*/
 /*	$OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $	*/
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.34 2012/12/12 15:15:31 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.35 2012/12/13 06:43:37 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -1518,17 +1518,37 @@ sdhc_soft_reset(struct sdhc_host *hp, in
 
 	DPRINTF(1,("%s: software reset reg=%08x\n", HDEVNAME(hp), mask));
 
+	/* Request the reset.  */
 	HWRITE1(hp, SDHC_SOFTWARE_RESET, mask);
+
+	/*
+	 * If necessary, wait for the controller to set the bits to
+	 * acknowledge the reset.
+	 */
+	if (ISSET(hp->sc->sc_flags, SDHC_FLAG_WAIT_RESET) &&
+	    ISSET(mask, (SDHC_RESET_DAT | SDHC_RESET_CMD))) {
+		for (timo = 10000; timo > 0; timo--) {
+			if (ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask))
+				break;
+			/* Short delay because I worry we may miss it...  */
+			sdmmc_delay(1);
+		}
+		if (timo == 0)
+			return ETIMEDOUT;
+	}
+
+	/*
+	 * Wait for the controller to clear the bits to indicate that
+	 * the reset has completed.
+	 */
 	for (timo = 10; timo > 0; timo--) {
 		if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask))
 			break;
 		sdmmc_delay(10000);
-		HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
 	}
 	if (timo == 0) {
 		DPRINTF(1,("%s: timeout reg=%08x\n", HDEVNAME(hp),
 		    HREAD1(hp, SDHC_SOFTWARE_RESET)));
-		HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
 		return ETIMEDOUT;
 	}
 

Index: src/sys/dev/sdmmc/sdhcvar.h
diff -u src/sys/dev/sdmmc/sdhcvar.h:1.10 src/sys/dev/sdmmc/sdhcvar.h:1.11
--- src/sys/dev/sdmmc/sdhcvar.h:1.10	Wed Dec 12 15:15:31 2012
+++ src/sys/dev/sdmmc/sdhcvar.h	Thu Dec 13 06:43:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhcvar.h,v 1.10 2012/12/12 15:15:31 matt Exp $	*/
+/*	$NetBSD: sdhcvar.h,v 1.11 2012/12/13 06:43:37 riastradh Exp $	*/
 /*	$OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $	*/
 
 /*
@@ -47,6 +47,7 @@ struct sdhc_softc {
 #define	SDHC_FLAG_HOSTCAPS	0x0200	/* No device provided capabilities */
 #define	SDHC_FLAG_RSP136_CRC	0x0400	/* Resp 136 with CRC and end-bit */
 #define	SDHC_FLAG_SINGLE_ONLY	0x0800	/* Single transfer only */
+#define	SDHC_FLAG_WAIT_RESET	0x1000	/* Wait for soft resets to start */
 
 	uint32_t		sc_clkbase;
 	int			sc_clkmsk;	/* Mask for SDCLK */

Reply via email to