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 */