Module Name: src Committed By: jmcneill Date: Tue Sep 9 20:39:52 UTC 2014
Modified Files: src/sys/arch/arm/allwinner: awin_mmc.c Log Message: if "dma" property is set to false, fallback to pio mode To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/allwinner/awin_mmc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/allwinner/awin_mmc.c diff -u src/sys/arch/arm/allwinner/awin_mmc.c:1.8 src/sys/arch/arm/allwinner/awin_mmc.c:1.9 --- src/sys/arch/arm/allwinner/awin_mmc.c:1.8 Tue Sep 9 19:23:46 2014 +++ src/sys/arch/arm/allwinner/awin_mmc.c Tue Sep 9 20:39:52 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: awin_mmc.c,v 1.8 2014/09/09 19:23:46 jmcneill Exp $ */ +/* $NetBSD: awin_mmc.c,v 1.9 2014/09/09 20:39:52 jmcneill Exp $ */ /*- * Copyright (c) 2014 Jared D. McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include "locators.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.8 2014/09/09 19:23:46 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.9 2014/09/09 20:39:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -89,6 +89,8 @@ struct awin_mmc_softc { bus_space_handle_t sc_bsh; bus_dma_tag_t sc_dmat; + bool sc_use_dma; + void *sc_ih; kmutex_t sc_intr_lock; kcondvar_t sc_intr_cv; @@ -236,8 +238,11 @@ awin_mmc_attach(device_t parent, device_ bus_space_subregion(sc->sc_bst, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_bsh); + sc->sc_use_dma = true; + prop_dictionary_get_bool(cfg, "dma", &sc->sc_use_dma); + aprint_naive("\n"); - aprint_normal(": SD/MMC interface\n"); + aprint_normal(": SD3.0 (%s)\n", sc->sc_use_dma ? "DMA" : "PIO"); awin_mmc_probe_clocks(sc, aio); @@ -266,9 +271,11 @@ awin_mmc_attach(device_t parent, device_ } } - if (awin_mmc_idma_setup(sc) != 0) { - aprint_error_dev(self, "failed to setup DMA\n"); - return; + if (sc->sc_use_dma) { + if (awin_mmc_idma_setup(sc) != 0) { + aprint_error_dev(self, "failed to setup DMA\n"); + return; + } } sc->sc_ih = intr_establish(loc->loc_intr, IPL_BIO, IST_LEVEL, @@ -296,16 +303,18 @@ awin_mmc_attach_i(device_t self) saa.saa_busname = "sdmmc"; saa.saa_sct = &awin_mmc_chip_functions; saa.saa_sch = sc; - saa.saa_dmat = sc->sc_dmat; saa.saa_clkmin = 400; saa.saa_clkmax = 50000; saa.saa_caps = SMC_CAPS_4BIT_MODE| SMC_CAPS_8BIT_MODE| SMC_CAPS_SD_HIGHSPEED| SMC_CAPS_MMC_HIGHSPEED| - SMC_CAPS_AUTO_STOP| - SMC_CAPS_DMA| - SMC_CAPS_MULTI_SEG_DMA; + SMC_CAPS_AUTO_STOP; + if (sc->sc_use_dma) { + saa.saa_dmat = sc->sc_dmat; + saa.saa_caps |= SMC_CAPS_DMA| + SMC_CAPS_MULTI_SEG_DMA; + } if (sc->sc_has_gpio_detect) { saa.saa_caps |= SMC_CAPS_POLL_CARD_DET; } @@ -410,9 +419,7 @@ awin_mmc_host_ocr(sdmmc_chipset_handle_t static int awin_mmc_host_maxblklen(sdmmc_chipset_handle_t sch) { - struct awin_mmc_softc *sc = sch; - - return sc->sc_idma_xferlen; + return 8192; } static int @@ -553,6 +560,43 @@ awin_mmc_bus_rod(sdmmc_chipset_handle_t return -1; } + +static int +awin_mmc_pio_wait(struct awin_mmc_softc *sc, struct sdmmc_command *cmd) +{ + int retry = 0xfffff; + uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ? + AWIN_MMC_STATUS_FIFO_EMPTY : AWIN_MMC_STATUS_FIFO_FULL; + + while (--retry > 0) { + uint32_t status = MMC_READ(sc, AWIN_MMC_STATUS); + if (!(status & bit)) + return 0; + delay(10); + } + + return ETIMEDOUT; +} + +static int +awin_mmc_pio_transfer(struct awin_mmc_softc *sc, struct sdmmc_command *cmd) +{ + uint32_t *datap = (uint32_t *)cmd->c_data; + int i; + + for (i = 0; i < (cmd->c_resid >> 2); i++) { + if (awin_mmc_pio_wait(sc, cmd)) + return ETIMEDOUT; + if (cmd->c_flags & SCF_CMD_READ) { + datap[i] = MMC_READ(sc, AWIN_MMC_FIFO); + } else { + MMC_WRITE(sc, AWIN_MMC_FIFO, datap[i]); + } + } + + return 0; +} + static int awin_mmc_dma_prepare(struct awin_mmc_softc *sc, struct sdmmc_command *cmd) { @@ -693,18 +737,25 @@ awin_mmc_exec_command(sdmmc_chipset_hand MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode); } else { cmd->c_resid = cmd->c_datalen; - cmd->c_error = awin_mmc_dma_prepare(sc, cmd); awin_mmc_led(sc, 0); - MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode); - if (cmd->c_error == 0) { - cmd->c_error = cv_timedwait(&sc->sc_idst_cv, - &sc->sc_intr_lock, hz*10); - } - awin_mmc_dma_complete(sc); - if (sc->sc_idma_idst & AWIN_MMC_IDST_ERROR) { - cmd->c_error = EIO; - } else if (!(sc->sc_idma_idst & AWIN_MMC_IDST_COMPLETE)) { - cmd->c_error = ETIMEDOUT; + if (sc->sc_use_dma) { + cmd->c_error = awin_mmc_dma_prepare(sc, cmd); + MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode); + if (cmd->c_error == 0) { + cmd->c_error = cv_timedwait(&sc->sc_idst_cv, + &sc->sc_intr_lock, hz*10); + } + awin_mmc_dma_complete(sc); + if (sc->sc_idma_idst & AWIN_MMC_IDST_ERROR) { + cmd->c_error = EIO; + } else if (!(sc->sc_idma_idst & AWIN_MMC_IDST_COMPLETE)) { + cmd->c_error = ETIMEDOUT; + } + } else { + mutex_exit(&sc->sc_intr_lock); + MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode); + cmd->c_error = awin_mmc_pio_transfer(sc, cmd); + mutex_enter(&sc->sc_intr_lock); } awin_mmc_led(sc, 1); if (cmd->c_error) { @@ -796,6 +847,11 @@ done: awin_mmc_host_reset(sc); awin_mmc_update_clock(sc); } + + if (!sc->sc_use_dma) { + MMC_WRITE(sc, AWIN_MMC_GCTRL, + MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_FIFORESET); + } } static void