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
This commit is contained in:
riastradh 2012-12-13 06:43:37 +00:00
parent a7e8133750
commit 98770c509f
3 changed files with 31 additions and 7 deletions

View File

@ -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. * Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
@ -29,7 +29,7 @@
*/ */
#include <sys/cdefs.h> #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" #include "opt_omap.h"
@ -150,6 +150,9 @@ obiosdhc_attach(device_t parent, device_t self, void *aux)
sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON; sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC; sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY; 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_host = sc->sc_hosts;
sc->sc.sc_clkbase = 96000; /* 96MHZ */ sc->sc.sc_clkbase = 96000; /* 96MHZ */
if (!prop_dictionary_get_uint32(prop, "clkmask", &sc->sc.sc_clkmsk)) if (!prop_dictionary_get_uint32(prop, "clkmask", &sc->sc.sc_clkmsk))

View File

@ -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 $ */ /* $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $ */
/* /*
@ -23,7 +23,7 @@
*/ */
#include <sys/cdefs.h> #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 #ifdef _KERNEL_OPT
#include "opt_sdmmc.h" #include "opt_sdmmc.h"
@ -1518,17 +1518,37 @@ sdhc_soft_reset(struct sdhc_host *hp, int mask)
DPRINTF(1,("%s: software reset reg=%08x\n", HDEVNAME(hp), mask)); DPRINTF(1,("%s: software reset reg=%08x\n", HDEVNAME(hp), mask));
/* Request the reset. */
HWRITE1(hp, SDHC_SOFTWARE_RESET, mask); 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--) { for (timo = 10; timo > 0; timo--) {
if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask)) if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask))
break; break;
sdmmc_delay(10000); sdmmc_delay(10000);
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
} }
if (timo == 0) { if (timo == 0) {
DPRINTF(1,("%s: timeout reg=%08x\n", HDEVNAME(hp), DPRINTF(1,("%s: timeout reg=%08x\n", HDEVNAME(hp),
HREAD1(hp, SDHC_SOFTWARE_RESET))); HREAD1(hp, SDHC_SOFTWARE_RESET)));
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
return ETIMEDOUT; return ETIMEDOUT;
} }

View File

@ -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 $ */ /* $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_HOSTCAPS 0x0200 /* No device provided capabilities */
#define SDHC_FLAG_RSP136_CRC 0x0400 /* Resp 136 with CRC and end-bit */ #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_SINGLE_ONLY 0x0800 /* Single transfer only */
#define SDHC_FLAG_WAIT_RESET 0x1000 /* Wait for soft resets to start */
uint32_t sc_clkbase; uint32_t sc_clkbase;
int sc_clkmsk; /* Mask for SDCLK */ int sc_clkmsk; /* Mask for SDCLK */