Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Implement TI AM335x's SDHC reset quirk. Beaglebone SDHC...



details:   https://anonhg.NetBSD.org/src/rev/998cbaccccf1
branches:  trunk
changeset: 783282:998cbaccccf1
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Thu Dec 13 06:43:37 2012 +0000

description:
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

diffstat:

 sys/arch/arm/omap/omap3_sdhc.c |   7 +++++--
 sys/dev/sdmmc/sdhc.c           |  28 ++++++++++++++++++++++++----
 sys/dev/sdmmc/sdhcvar.h        |   3 ++-
 3 files changed, 31 insertions(+), 7 deletions(-)

diffs (103 lines):

diff -r c002c9eccaf3 -r 998cbaccccf1 sys/arch/arm/omap/omap3_sdhc.c
--- a/sys/arch/arm/omap/omap3_sdhc.c    Thu Dec 13 05:58:14 2012 +0000
+++ b/sys/arch/arm/omap/omap3_sdhc.c    Thu Dec 13 06:43:37 2012 +0000
@@ -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 @@
        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))
diff -r c002c9eccaf3 -r 998cbaccccf1 sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c      Thu Dec 13 05:58:14 2012 +0000
+++ b/sys/dev/sdmmc/sdhc.c      Thu Dec 13 06:43:37 2012 +0000
@@ -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 @@
 
        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;
        }
 
diff -r c002c9eccaf3 -r 998cbaccccf1 sys/dev/sdmmc/sdhcvar.h
--- a/sys/dev/sdmmc/sdhcvar.h   Thu Dec 13 05:58:14 2012 +0000
+++ b/sys/dev/sdmmc/sdhcvar.h   Thu Dec 13 06:43:37 2012 +0000
@@ -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 @@
 #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 */



Home | Main Index | Thread Index | Old Index