summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2018-06-04 13:33:11 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2018-06-04 13:33:11 +0000
commit73c98b2862be8227db0b54c6c28c379e4b1f6997 (patch)
tree3f160fd52fc0bb747aa13f91f333190b7c127adf /sys/dev
parent2403ffa0d269f3234df9de6cdedfc62f3ee806eb (diff)
4-bit bus width is mandatory for SDIO cards that support High Speed
mode, so switch from 1-bit to 4-bit bus width if the host controller supports it. ok kettenis@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/sdmmc/sdmmc_io.c23
-rw-r--r--sys/dev/sdmmc/sdmmc_ioreg.h4
-rw-r--r--sys/dev/sdmmc/sdmmc_mem.c8
3 files changed, 28 insertions, 7 deletions
diff --git a/sys/dev/sdmmc/sdmmc_io.c b/sys/dev/sdmmc/sdmmc_io.c
index 8af5b18b17b..d3848b696a5 100644
--- a/sys/dev/sdmmc/sdmmc_io.c
+++ b/sys/dev/sdmmc/sdmmc_io.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdmmc_io.c,v 1.36 2018/06/04 10:37:14 patrick Exp $ */
+/* $OpenBSD: sdmmc_io.c,v 1.37 2018/06/04 13:33:10 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -49,6 +49,7 @@ int sdmmc_io_xchg(struct sdmmc_softc *, struct sdmmc_function *,
void sdmmc_io_reset(struct sdmmc_softc *);
int sdmmc_io_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
void sdmmc_io_set_blocklen(struct sdmmc_function *, unsigned int);
+void sdmmc_io_set_bus_width(struct sdmmc_function *, int);
int sdmmc_io_set_highspeed(struct sdmmc_function *sf, int);
#ifdef SDMMC_DEBUG
@@ -188,6 +189,10 @@ sdmmc_io_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
sdmmc_io_set_highspeed(sf, 1) == 0)
(void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
SDMMC_SDCLK_50MHZ, SDMMC_TIMING_HIGHSPEED);
+ if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
+ sdmmc_io_set_bus_width(sf, 4);
+ sdmmc_chip_bus_width(sc->sct, sc->sch, 4);
+ }
else
(void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
SDMMC_SDCLK_25MHZ, SDMMC_TIMING_LEGACY);
@@ -863,6 +868,22 @@ sdmmc_io_set_blocklen(struct sdmmc_function *sf, unsigned int blklen)
sf->cur_blklen = blklen;
}
+void
+sdmmc_io_set_bus_width(struct sdmmc_function *sf, int width)
+{
+ struct sdmmc_softc *sc = sf->sc;
+ u_int8_t rv;
+
+ rw_assert_wrlock(&sc->sc_lock);
+ rv = sdmmc_io_read_1(sf, SD_IO_CCCR_BUS_WIDTH);
+ rv &= ~CCCR_BUS_WIDTH_MASK;
+ if (width == 4)
+ rv |= CCCR_BUS_WIDTH_4;
+ else
+ rv |= CCCR_BUS_WIDTH_1;
+ sdmmc_io_write_1(sf, SD_IO_CCCR_BUS_WIDTH, rv);
+}
+
int
sdmmc_io_set_highspeed(struct sdmmc_function *sf, int enable)
{
diff --git a/sys/dev/sdmmc/sdmmc_ioreg.h b/sys/dev/sdmmc/sdmmc_ioreg.h
index 9761f48b648..627c5f99b3a 100644
--- a/sys/dev/sdmmc/sdmmc_ioreg.h
+++ b/sys/dev/sdmmc/sdmmc_ioreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdmmc_ioreg.h,v 1.9 2018/06/04 10:37:14 patrick Exp $ */
+/* $OpenBSD: sdmmc_ioreg.h,v 1.10 2018/06/04 13:33:10 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -71,7 +71,7 @@
#define SD_IO_CCCR_BUS_WIDTH 0x07
#define CCCR_BUS_WIDTH_1 (0<<0)
#define CCCR_BUS_WIDTH_4 (2<<0)
-#define CCCR_BUS_WIDTH_8 (3<<0)
+#define CCCR_BUS_WIDTH_MASK (3<<0)
#define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */
#define SD_IO_CCCR_SPEED 0x13
#define CCCR_SPEED_SHS (1<<0)
diff --git a/sys/dev/sdmmc/sdmmc_mem.c b/sys/dev/sdmmc/sdmmc_mem.c
index 0afcbf6af1a..9412593de04 100644
--- a/sys/dev/sdmmc/sdmmc_mem.c
+++ b/sys/dev/sdmmc/sdmmc_mem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdmmc_mem.c,v 1.32 2018/05/01 18:30:37 patrick Exp $ */
+/* $OpenBSD: sdmmc_mem.c,v 1.33 2018/06/04 13:33:10 patrick Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -50,7 +50,7 @@ int sdmmc_mem_decode_scr(struct sdmmc_softc *, uint32_t *,
struct sdmmc_function *);
int sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t);
-int sdmmc_set_bus_width(struct sdmmc_function *, int);
+int sdmmc_mem_set_bus_width(struct sdmmc_function *, int);
int sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, uint8_t);
int sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *);
@@ -452,7 +452,7 @@ out:
}
int
-sdmmc_set_bus_width(struct sdmmc_function *sf, int width)
+sdmmc_mem_set_bus_width(struct sdmmc_function *sf, int width)
{
struct sdmmc_softc *sc = sf->sc;
struct sdmmc_command cmd;
@@ -613,7 +613,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) &&
ISSET(sf->scr.bus_width, SCR_SD_BUS_WIDTHS_4BIT)) {
DPRINTF(("%s: change bus width\n", DEVNAME(sc)));
- error = sdmmc_set_bus_width(sf, 4);
+ error = sdmmc_mem_set_bus_width(sf, 4);
if (error) {
printf("%s: can't change bus width\n", DEVNAME(sc));
return error;