Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sdmmc Support 32-bit only access to the SDHC registers.
details: https://anonhg.NetBSD.org/src/rev/413804c7501c
branches: trunk
changeset: 777575:413804c7501c
user: matt <matt%NetBSD.org@localhost>
date: Thu Feb 23 21:06:21 2012 +0000
description:
Support 32-bit only access to the SDHC registers.
Add support for FreeScale "Enhanced" SDHC port.
Add support for CGM mode (XLP and BCM2835 (Arason)).
diffstat:
sys/dev/sdmmc/sdhc.c | 685 +++++++++++++++++++++++++++++++++++++-------------
1 files changed, 499 insertions(+), 186 deletions(-)
diffs (truncated from 1077 to 300 lines):
diff -r a218c3ae0958 -r 413804c7501c sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c Thu Feb 23 20:59:19 2012 +0000
+++ b/sys/dev/sdmmc/sdhc.c Thu Feb 23 21:06:21 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhc.c,v 1.10 2012/02/02 22:49:17 nonaka Exp $ */
+/* $NetBSD: sdhc.c,v 1.11 2012/02/23 21:06:21 matt 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.10 2012/02/02 22:49:17 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.11 2012/02/23 21:06:21 matt Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -82,30 +82,80 @@
uint32_t flags; /* flags for this host */
#define SHF_USE_DMA 0x0001
#define SHF_USE_4BIT_MODE 0x0002
+#define SHF_USE_8BIT_MODE 0x0004
};
#define HDEVNAME(hp) (device_xname((hp)->sc->sc_dev))
-#define HREAD1(hp, reg) \
- (bus_space_read_1((hp)->iot, (hp)->ioh, (reg)))
-#define HREAD2(hp, reg) \
- (bus_space_read_2((hp)->iot, (hp)->ioh, (reg)))
-#define HREAD4(hp, reg) \
+static uint8_t
+hread1(struct sdhc_host *hp, bus_size_t reg)
+{
+ if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS))
+ return bus_space_read_1(hp->iot, hp->ioh, reg);
+
+ return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 3));
+}
+
+static uint16_t
+hread2(struct sdhc_host *hp, bus_size_t reg)
+{
+ if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS))
+ return bus_space_read_2(hp->iot, hp->ioh, reg);
+
+ return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 2));
+}
+
+#define HREAD1(hp, reg) hread1(hp, reg)
+#define HREAD2(hp, reg) hread2(hp, reg)
+#define HREAD4(hp, reg) \
(bus_space_read_4((hp)->iot, (hp)->ioh, (reg)))
-#define HWRITE1(hp, reg, val) \
- bus_space_write_1((hp)->iot, (hp)->ioh, (reg), (val))
-#define HWRITE2(hp, reg, val) \
- bus_space_write_2((hp)->iot, (hp)->ioh, (reg), (val))
+
+
+static void
+hwrite1(struct sdhc_host *hp, bus_size_t o, uint8_t val)
+{
+ if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
+ bus_space_write_1(hp->iot, hp->ioh, o, val);
+ } else {
+ const size_t shift = 8 * (o & 3);
+ o &= -4;
+ uint32_t tmp = bus_space_read_4(hp->iot, hp->ioh, o);
+ tmp = (val << shift) | (tmp & ~(0xff << shift));
+ bus_space_write_4(hp->iot, hp->ioh, o, tmp);
+ }
+}
+
+static void
+hwrite2(struct sdhc_host *hp, bus_size_t o, uint16_t val)
+{
+ if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
+ bus_space_write_2(hp->iot, hp->ioh, o, val);
+ } else {
+ const size_t shift = 8 * (o & 2);
+ o &= -4;
+ uint32_t tmp = bus_space_read_4(hp->iot, hp->ioh, o);
+ tmp = (val << shift) | (tmp & ~(0xffff << shift));
+ bus_space_write_4(hp->iot, hp->ioh, o, tmp);
+ }
+}
+
+#define HWRITE1(hp, reg, val) hwrite1(hp, reg, val)
+#define HWRITE2(hp, reg, val) hwrite2(hp, reg, val)
#define HWRITE4(hp, reg, val) \
bus_space_write_4((hp)->iot, (hp)->ioh, (reg), (val))
+
#define HCLR1(hp, reg, bits) \
- HWRITE1((hp), (reg), HREAD1((hp), (reg)) & ~(bits))
+ do if (bits) HWRITE1((hp), (reg), HREAD1((hp), (reg)) & ~(bits)); while (0)
#define HCLR2(hp, reg, bits) \
- HWRITE2((hp), (reg), HREAD2((hp), (reg)) & ~(bits))
+ do if (bits) HWRITE2((hp), (reg), HREAD2((hp), (reg)) & ~(bits)); while (0)
+#define HCLR4(hp, reg, bits) \
+ do if (bits) HWRITE4((hp), (reg), HREAD4((hp), (reg)) & ~(bits)); while (0)
#define HSET1(hp, reg, bits) \
- HWRITE1((hp), (reg), HREAD1((hp), (reg)) | (bits))
+ do if (bits) HWRITE1((hp), (reg), HREAD1((hp), (reg)) | (bits)); while (0)
#define HSET2(hp, reg, bits) \
- HWRITE2((hp), (reg), HREAD2((hp), (reg)) | (bits))
+ do if (bits) HWRITE2((hp), (reg), HREAD2((hp), (reg)) | (bits)); while (0)
+#define HSET4(hp, reg, bits) \
+ do if (bits) HWRITE4((hp), (reg), HREAD4((hp), (reg)) | (bits)); while (0)
static int sdhc_host_reset(sdmmc_chipset_handle_t);
static int sdhc_host_reset1(sdmmc_chipset_handle_t);
@@ -128,8 +178,11 @@
static void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *);
static int sdhc_transfer_data_dma(struct sdhc_host *, struct sdmmc_command *);
static int sdhc_transfer_data_pio(struct sdhc_host *, struct sdmmc_command *);
-static void sdhc_read_data_pio(struct sdhc_host *, uint8_t *, int);
-static void sdhc_write_data_pio(struct sdhc_host *, uint8_t *, int);
+static void sdhc_read_data_pio(struct sdhc_host *, uint8_t *, u_int);
+static void sdhc_write_data_pio(struct sdhc_host *, uint8_t *, u_int);
+static void esdhc_read_data_pio(struct sdhc_host *, uint8_t *, u_int);
+static void esdhc_write_data_pio(struct sdhc_host *, uint8_t *, u_int);
+
static struct sdmmc_chip_functions sdhc_functions = {
/* host controller reset */
@@ -257,16 +310,23 @@
* capabilities. (2.2.15)
*/
HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX);
+#if 0
+ if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED))
+ HWRITE4(hp, SDHC_NINTR_STATUS, SDHC_CMD_TIMEOUT_ERROR << 16);
+#endif
/*
* Determine SD bus voltage levels supported by the controller.
*/
- if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V))
+ if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V)) {
SET(hp->ocr, MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V);
- if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_0V))
+ }
+ if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_0V)) {
SET(hp->ocr, MMC_OCR_2_9V_3_0V | MMC_OCR_3_0V_3_1V);
- if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_3V))
+ }
+ if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_3V)) {
SET(hp->ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V);
+ }
/*
* Determine the maximum block length supported by the host
@@ -308,9 +368,15 @@
saa.saa_dmat = hp->dmat;
saa.saa_clkmin = hp->clkbase / 256;
saa.saa_clkmax = hp->clkbase;
- if (ISSET(sc->sc_flags, SDHC_FLAG_HAVE_DVS))
+ if (ISSET(sc->sc_flags, SDHC_FLAG_HAVE_CGM))
+ saa.saa_clkmin /= 2046;
+ else if (ISSET(sc->sc_flags, SDHC_FLAG_HAVE_DVS))
saa.saa_clkmin /= 16;
saa.saa_caps = SMC_CAPS_4BIT_MODE|SMC_CAPS_AUTO_STOP;
+ if (ISSET(sc->sc_flags, SDHC_FLAG_8BIT_MODE))
+ saa.saa_caps |= SMC_CAPS_8BIT_MODE;
+ if (ISSET(caps, SDHC_HIGH_SPEED_SUPP))
+ saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED;
#if notyet
if (ISSET(hp->flags, SHF_USE_DMA))
saa.saa_caps |= SMC_CAPS_DMA;
@@ -353,16 +419,26 @@
{
struct sdhc_softc *sc = device_private(dev);
struct sdhc_host *hp;
- int n, i;
/* XXX poll for command completion or suspend command
* in progress */
/* Save the host controller state. */
- for (n = 0; n < sc->sc_nhosts; n++) {
+ for (size_t n = 0; n < sc->sc_nhosts; n++) {
hp = sc->sc_host[n];
- for (i = 0; i < sizeof hp->regs; i++)
- hp->regs[i] = HREAD1(hp, i);
+ if (ISSET(sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
+ for (size_t i = 0; i < sizeof hp->regs; i += 4) {
+ uint32_t v = HREAD4(hp, i);
+ hp->regs[i+0] = (v >> 0);
+ hp->regs[i+1] = (v >> 8);
+ hp->regs[i+2] = (v >> 16);
+ hp->regs[i+3] = (v >> 24);
+ }
+ } else {
+ for (size_t i = 0; i < sizeof hp->regs; i++) {
+ hp->regs[i] = HREAD1(hp, i);
+ }
+ }
}
return true;
}
@@ -372,14 +448,24 @@
{
struct sdhc_softc *sc = device_private(dev);
struct sdhc_host *hp;
- int n, i;
/* Restore the host controller state. */
- for (n = 0; n < sc->sc_nhosts; n++) {
+ for (size_t n = 0; n < sc->sc_nhosts; n++) {
hp = sc->sc_host[n];
(void)sdhc_host_reset(hp);
- for (i = 0; i < sizeof hp->regs; i++)
- HWRITE1(hp, i, hp->regs[i]);
+ if (ISSET(sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
+ for (size_t i = 0; i < sizeof hp->regs; i += 4) {
+ HWRITE4(hp, i,
+ (hp->regs[i+0] << 0)
+ |(hp->regs[i+1] << 8)
+ |(hp->regs[i+2] << 16)
+ |(hp->regs[i+3] << 24));
+ }
+ } else {
+ for (size_t i = 0; i < sizeof hp->regs; i++) {
+ HWRITE1(hp, i, hp->regs[i]);
+ }
+ }
}
return true;
}
@@ -389,10 +475,9 @@
{
struct sdhc_softc *sc = device_private(dev);
struct sdhc_host *hp;
- int i;
/* XXX chip locks up if we don't disable it before reboot. */
- for (i = 0; i < sc->sc_nhosts; i++) {
+ for (size_t i = 0; i < sc->sc_nhosts; i++) {
hp = sc->sc_host[i];
(void)sdhc_host_reset(hp);
}
@@ -407,13 +492,17 @@
sdhc_host_reset1(sdmmc_chipset_handle_t sch)
{
struct sdhc_host *hp = (struct sdhc_host *)sch;
- uint16_t sdhcimask;
+ uint32_t sdhcimask;
int error;
/* Don't lock. */
/* Disable all interrupts. */
- HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, 0);
+ if (ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
+ HWRITE4(hp, SDHC_NINTR_SIGNAL_EN, 0);
+ } else {
+ HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, 0);
+ }
/*
* Reset the entire host controller and wait up to 100ms for
@@ -425,16 +514,30 @@
/* Set data timeout counter value to max for now. */
HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX);
+#if 0
+ if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED))
+ HWRITE4(hp, SDHC_NINTR_STATUS, SDHC_CMD_TIMEOUT_ERROR << 16);
+#endif
/* Enable interrupts. */
sdhcimask = SDHC_CARD_REMOVAL | SDHC_CARD_INSERTION |
SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY |
SDHC_DMA_INTERRUPT | SDHC_BLOCK_GAP_EVENT |
SDHC_TRANSFER_COMPLETE | SDHC_COMMAND_COMPLETE;
- HWRITE2(hp, SDHC_NINTR_STATUS_EN, sdhcimask);
- HWRITE2(hp, SDHC_EINTR_STATUS_EN, SDHC_EINTR_STATUS_MASK);
- HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, sdhcimask);
- HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, SDHC_EINTR_SIGNAL_MASK);
+ if (ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
+ sdhcimask |= SDHC_EINTR_STATUS_MASK << 16;
+ HWRITE4(hp, SDHC_NINTR_STATUS_EN, sdhcimask);
+ sdhcimask ^=
+ (SDHC_EINTR_STATUS_MASK ^ SDHC_EINTR_SIGNAL_MASK) << 16;
+ sdhcimask ^= SDHC_BUFFER_READ_READY ^ SDHC_BUFFER_WRITE_READY;
+ HWRITE4(hp, SDHC_NINTR_SIGNAL_EN, sdhcimask);
+ } else {
+ HWRITE2(hp, SDHC_NINTR_STATUS_EN, sdhcimask);
+ HWRITE2(hp, SDHC_EINTR_STATUS_EN, SDHC_EINTR_STATUS_MASK);
+ sdhcimask ^= SDHC_BUFFER_READ_READY ^ SDHC_BUFFER_WRITE_READY;
+ HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, sdhcimask);
+ HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, SDHC_EINTR_SIGNAL_MASK);
+ }
out:
return error;
@@ -482,9 +585,7 @@
r = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CARD_INSERTED);
mutex_exit(&hp->host_mtx);
Home |
Main Index |
Thread Index |
Old Index