summaryrefslogtreecommitdiff
path: root/sys/dev/sdmmc
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2018-06-04 10:37:15 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2018-06-04 10:37:15 +0000
commitb43860623738aed88bc80a3e3f0efb39612cf602 (patch)
tree7fb92dec09b054012d617399495dc86d4e132a87 /sys/dev/sdmmc
parent56c2bc828ac64d3056a3146cb7a9a13ad56ac310 (diff)
Switch to SDIO High Speed mode if the host controller supports it.
ok kettenis@
Diffstat (limited to 'sys/dev/sdmmc')
-rw-r--r--sys/dev/sdmmc/sdmmc_io.c31
-rw-r--r--sys/dev/sdmmc/sdmmc_ioreg.h11
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)