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:
parent
a7e8133750
commit
98770c509f
@ -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))
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user