diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-06-04 10:37:15 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-06-04 10:37:15 +0000 |
commit | b43860623738aed88bc80a3e3f0efb39612cf602 (patch) | |
tree | 7fb92dec09b054012d617399495dc86d4e132a87 | |
parent | 56c2bc828ac64d3056a3146cb7a9a13ad56ac310 (diff) |
Switch to SDIO High Speed mode if the host controller supports it.
ok kettenis@
-rw-r--r-- | sys/dev/sdmmc/sdmmc_io.c | 31 | ||||
-rw-r--r-- | sys/dev/sdmmc/sdmmc_ioreg.h | 11 |
2 files changed, 37 insertions, 5 deletions
diff --git a/sys/dev/sdmmc/sdmmc_io.c b/sys/dev/sdmmc/sdmmc_io.c index 78fdc6f4723..8af5b18b17b 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.35 2018/05/30 14:53:11 patrick Exp $ */ +/* $OpenBSD: sdmmc_io.c,v 1.36 2018/06/04 10:37:14 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); +int sdmmc_io_set_highspeed(struct sdmmc_function *sf, int); #ifdef SDMMC_DEBUG #define DPRINTF(s) printf s @@ -183,9 +184,13 @@ sdmmc_io_init(struct sdmmc_softc *sc, struct sdmmc_function *sf) sdmmc_print_cis(sf); if (sf->number == 0) { - /* XXX respect host and card capabilities */ - (void)sdmmc_chip_bus_clock(sc->sct, sc->sch, - 25000, SDMMC_TIMING_LEGACY); + if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) && + sdmmc_io_set_highspeed(sf, 1) == 0) + (void)sdmmc_chip_bus_clock(sc->sct, sc->sch, + SDMMC_SDCLK_50MHZ, SDMMC_TIMING_HIGHSPEED); + else + (void)sdmmc_chip_bus_clock(sc->sct, sc->sch, + SDMMC_SDCLK_25MHZ, SDMMC_TIMING_LEGACY); } return 0; @@ -857,3 +862,21 @@ sdmmc_io_set_blocklen(struct sdmmc_function *sf, unsigned int blklen) SD_IO_FBR_BLOCKLEN+ 1, (blklen >> 8) & 0xff); sf->cur_blklen = blklen; } + +int +sdmmc_io_set_highspeed(struct sdmmc_function *sf, int enable) +{ + 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_SPEED); + if (enable && !(rv & CCCR_SPEED_SHS)) + return 1; + rv &= ~CCCR_SPEED_MASK; + if (enable) + rv |= CCCR_SPEED_EHS; + sdmmc_io_write_1(sf, SD_IO_CCCR_SPEED, rv); + return 0; +} diff --git a/sys/dev/sdmmc/sdmmc_ioreg.h b/sys/dev/sdmmc/sdmmc_ioreg.h index fee72e55446..9761f48b648 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.8 2018/05/25 00:12:53 patrick Exp $ */ +/* $OpenBSD: sdmmc_ioreg.h,v 1.9 2018/06/04 10:37:14 patrick Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -73,6 +73,15 @@ #define CCCR_BUS_WIDTH_4 (2<<0) #define CCCR_BUS_WIDTH_8 (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) +#define CCCR_SPEED_EHS CCCR_SPEED_SDR25 +#define CCCR_SPEED_SDR12 (0<<1) +#define CCCR_SPEED_SDR25 (1<<1) +#define CCCR_SPEED_SDR50 (2<<1) +#define CCCR_SPEED_SDR104 (3<<1) +#define CCCR_SPEED_DDR50 (4<<1) +#define CCCR_SPEED_MASK (0x7<<1) /* Function Basic Registers (FBR) */ #define SD_IO_FBR_BASE(f) ((f) * 0x100) |