diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-06-04 13:33:11 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-06-04 13:33:11 +0000 |
commit | 73c98b2862be8227db0b54c6c28c379e4b1f6997 (patch) | |
tree | 3f160fd52fc0bb747aa13f91f333190b7c127adf /sys/dev | |
parent | 2403ffa0d269f3234df9de6cdedfc62f3ee806eb (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.c | 23 | ||||
-rw-r--r-- | sys/dev/sdmmc/sdmmc_ioreg.h | 4 | ||||
-rw-r--r-- | sys/dev/sdmmc/sdmmc_mem.c | 8 |
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; |