diff options
author | 2018-05-27 18:03:22 +0000 | |
---|---|---|
committer | 2018-05-27 18:03:22 +0000 | |
commit | 541a0a51e95e099b564536be593df497f77a45d9 (patch) | |
tree | 382045a06481cff27c81d30cbbc709022346bbd9 | |
parent | BCM43430 SDIO works if we load the appropriate firmware. (diff) | |
download | wireguard-openbsd-541a0a51e95e099b564536be593df497f77a45d9.tar.xz wireguard-openbsd-541a0a51e95e099b564536be593df497f77a45d9.zip |
Add SDIO support:
- Implement SDIO interrupt handling
- Set control bit that allows CPU access to the FIFO
- Fix PIO transfers that are not a multiple of 4 bytes
- Handle vqmmc-supply
ok patrick@
-rw-r--r-- | sys/dev/fdt/sximmc.c | 81 |
1 files changed, 74 insertions, 7 deletions
diff --git a/sys/dev/fdt/sximmc.c b/sys/dev/fdt/sximmc.c index 7acb8f55d56..293db1af683 100644 --- a/sys/dev/fdt/sximmc.c +++ b/sys/dev/fdt/sximmc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sximmc.c,v 1.3 2017/08/13 00:13:07 kettenis Exp $ */ +/* $OpenBSD: sximmc.c,v 1.4 2018/05/27 18:03:22 kettenis Exp $ */ /* $NetBSD: awin_mmc.c,v 1.23 2015/11/14 10:32:40 bouyer Exp $ */ /*- @@ -219,6 +219,8 @@ int sximmc_bus_power(sdmmc_chipset_handle_t, uint32_t); int sximmc_bus_clock(sdmmc_chipset_handle_t, int, int); int sximmc_bus_width(sdmmc_chipset_handle_t, int); void sximmc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *); +void sximmc_card_intr_mask(sdmmc_chipset_handle_t, int); +void sximmc_card_intr_ack(sdmmc_chipset_handle_t); void sximmc_pwrseq_pre(uint32_t); void sximmc_pwrseq_post(uint32_t); @@ -232,6 +234,8 @@ struct sdmmc_chip_functions sximmc_chip_functions = { .bus_clock = sximmc_bus_clock, .bus_width = sximmc_bus_width, .exec_command = sximmc_exec_command, + .card_intr_mask = sximmc_card_intr_mask, + .card_intr_ack = sximmc_card_intr_ack, }; struct sximmc_softc { @@ -265,6 +269,7 @@ struct sximmc_softc { uint32_t sc_gpio[4]; uint32_t sc_vmmc; + uint32_t sc_vqmmc; uint32_t sc_pwrseq; uint32_t sc_vdd; }; @@ -407,6 +412,7 @@ sximmc_attach(struct device *parent, struct device *self, void *aux) gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT); sc->sc_vmmc = OF_getpropint(sc->sc_node, "vmmc-supply", 0); + sc->sc_vqmmc = OF_getpropint(sc->sc_node, "vqmmc-supply", 0); sc->sc_pwrseq = OF_getpropint(sc->sc_node, "mmc-pwrseq", 0); sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO, @@ -489,11 +495,46 @@ sximmc_intr(void *priv) if (rint) { sc->sc_intr_rint |= rint; wakeup(&sc->sc_intr_rint); + + if (rint & SXIMMC_INT_SDIO_INT) { + uint32_t imask; + + imask = MMC_READ(sc, SXIMMC_IMASK); + imask &= ~SXIMMC_INT_SDIO_INT; + MMC_WRITE(sc, SXIMMC_IMASK, imask); + sdmmc_card_intr(sc->sc_sdmmc_dev); + } } return 1; } +void +sximmc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable) +{ + struct sximmc_softc *sc = sch; + uint32_t imask; + + imask = MMC_READ(sc, SXIMMC_IMASK); + if (enable) + imask |= SXIMMC_INT_SDIO_INT; + else + imask &= ~SXIMMC_INT_SDIO_INT; + MMC_WRITE(sc, SXIMMC_IMASK, imask); +} + +void +sximmc_card_intr_ack(sdmmc_chipset_handle_t sch) +{ + struct sximmc_softc *sc = sch; + uint32_t imask; + + MMC_WRITE(sc, SXIMMC_RINT, SXIMMC_INT_SDIO_INT); + imask = MMC_READ(sc, SXIMMC_IMASK); + imask |= SXIMMC_INT_SDIO_INT; + MMC_WRITE(sc, SXIMMC_IMASK, imask); +} + int sximmc_wait_rint(struct sximmc_softc *sc, uint32_t mask, int timeout) { @@ -562,6 +603,10 @@ sximmc_host_reset(sdmmc_chipset_handle_t sch) printf("%s: host reset succeeded\n", sc->sc_dev.dv_xname); #endif + /* Allow access to the FIFO by the CPU. */ + MMC_WRITE(sc, SXIMMC_GCTRL, + MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_ACCESS_BY_AHB); + MMC_WRITE(sc, SXIMMC_TIMEOUT, 0xffffffff); MMC_WRITE(sc, SXIMMC_IMASK, @@ -625,6 +670,11 @@ sximmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) if (sc->sc_vmmc && vdd > 0) regulator_enable(sc->sc_vmmc); + if (sc->sc_vqmmc && vdd > 0) + regulator_enable(sc->sc_vqmmc); + + delay(10000); + if (sc->sc_vdd == 0 && vdd > 0) sximmc_pwrseq_post(sc->sc_pwrseq); @@ -749,17 +799,34 @@ sximmc_pio_wait(struct sximmc_softc *sc, struct sdmmc_command *cmd) int sximmc_pio_transfer(struct sximmc_softc *sc, struct sdmmc_command *cmd) { - uint32_t *datap = (uint32_t *)cmd->c_data; - int i; + u_char *datap = cmd->c_data; + int datalen = cmd->c_resid; - for (i = 0; i < (cmd->c_resid >> 2); i++) { + while (datalen > 3) { if (sximmc_pio_wait(sc, cmd)) return ETIMEDOUT; if (cmd->c_flags & SCF_CMD_READ) { - datap[i] = MMC_READ(sc, sc->sc_fifo_reg); + *(uint32_t *)datap = MMC_READ(sc, sc->sc_fifo_reg); } else { - MMC_WRITE(sc, sc->sc_fifo_reg, datap[i]); + MMC_WRITE(sc, sc->sc_fifo_reg, *(uint32_t *)datap); } + datap += 4; + datalen -= 4; + } + + if (datalen > 0 && cmd->c_flags & SCF_CMD_READ) { + uint32_t rv = MMC_READ(sc, sc->sc_fifo_reg); + do { + *datap++ = rv & 0xff; + rv = rv >> 8; + } while(--datalen > 0); + } else if (datalen > 0) { + uint32_t rv = *datap++; + if (datalen > 1) + rv |= *datap++ << 8; + if (datalen > 2) + rv |= *datap++ << 16; + MMC_WRITE(sc, sc->sc_fifo_reg, rv); } return 0; @@ -887,7 +954,7 @@ sximmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) blksize = MIN(cmd->c_datalen, cmd->c_blklen); blkcount = cmd->c_datalen / blksize; - if (blkcount > 1) { + if (blkcount > 1 && cmd->c_opcode != SD_IO_RW_EXTENDED) { cmdval |= SXIMMC_CMD_SEND_AUTO_STOP; } |