Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic More or less a rewrite of dwc_mmc, based on awin_...
details: https://anonhg.NetBSD.org/src/rev/b59fb82572c1
branches: trunk
changeset: 354523:b59fb82572c1
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Jun 19 22:03:02 2017 +0000
description:
More or less a rewrite of dwc_mmc, based on awin_mmc, adding DMA support.
diffstat:
sys/dev/ic/dwc_mmc.c | 928 ++++++++++++++++++++++++++++------------------
sys/dev/ic/dwc_mmc_reg.h | 309 +++++++--------
sys/dev/ic/dwc_mmc_var.h | 63 ++-
3 files changed, 737 insertions(+), 563 deletions(-)
diffs (truncated from 1546 to 300 lines):
diff -r 7eb26b873127 -r b59fb82572c1 sys/dev/ic/dwc_mmc.c
--- a/sys/dev/ic/dwc_mmc.c Mon Jun 19 22:01:18 2017 +0000
+++ b/sys/dev/ic/dwc_mmc.c Mon Jun 19 22:03:02 2017 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: dwc_mmc.c,v 1.10 2015/12/27 18:35:29 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc.c,v 1.11 2017/06/19 22:03:02 jmcneill Exp $ */
/*-
- * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,8 @@
* SUCH DAMAGE.
*/
-#include "opt_dwc_mmc.h"
-
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.10 2015/12/27 18:35:29 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.11 2017/06/19 22:03:02 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -45,6 +43,8 @@
#include <dev/ic/dwc_mmc_reg.h>
#include <dev/ic/dwc_mmc_var.h>
+#define DWC_MMC_NDESC 64
+
static int dwc_mmc_host_reset(sdmmc_chipset_handle_t);
static uint32_t dwc_mmc_host_ocr(sdmmc_chipset_handle_t);
static int dwc_mmc_host_maxblklen(sdmmc_chipset_handle_t);
@@ -55,25 +55,10 @@
static int dwc_mmc_bus_width(sdmmc_chipset_handle_t, int);
static int dwc_mmc_bus_rod(sdmmc_chipset_handle_t, int);
static void dwc_mmc_exec_command(sdmmc_chipset_handle_t,
- struct sdmmc_command *);
+ struct sdmmc_command *);
static void dwc_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
static void dwc_mmc_card_intr_ack(sdmmc_chipset_handle_t);
-static int dwc_mmc_set_clock(struct dwc_mmc_softc *, u_int);
-static int dwc_mmc_update_clock(struct dwc_mmc_softc *);
-static int dwc_mmc_wait_rint(struct dwc_mmc_softc *, uint32_t, int);
-static int dwc_mmc_pio_wait(struct dwc_mmc_softc *,
- struct sdmmc_command *);
-static int dwc_mmc_pio_transfer(struct dwc_mmc_softc *,
- struct sdmmc_command *);
-
-#ifdef DWC_MMC_DEBUG
-static void dwc_mmc_print_rint(struct dwc_mmc_softc *, const char *,
- uint32_t);
-#endif
-
-void dwc_mmc_dump_regs(int);
-
static struct sdmmc_chip_functions dwc_mmc_chip_functions = {
.host_reset = dwc_mmc_host_reset,
.host_ocr = dwc_mmc_host_ocr,
@@ -89,23 +74,67 @@
.card_intr_ack = dwc_mmc_card_intr_ack,
};
-#define MMC_WRITE(sc, reg, val) \
+#define MMC_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
#define MMC_READ(sc, reg) \
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
-void
-dwc_mmc_init(struct dwc_mmc_softc *sc)
+static void
+dwc_mmc_dump_regs(struct dwc_mmc_softc *sc)
{
- struct sdmmcbus_attach_args saa;
+ device_printf(sc->sc_dev, "device registers:\n");
+ for (u_int off = 0x00; off < 0x100; off += 16) {
+ device_printf(sc->sc_dev, "xxxxxx%02x: %08x %08x %08x %08x\n",
+ off,
+ MMC_READ(sc, off + 0), MMC_READ(sc, off + 4),
+ MMC_READ(sc, off + 8), MMC_READ(sc, off + 12));
+ }
+}
+
+static int
+dwc_mmc_idma_setup(struct dwc_mmc_softc *sc)
+{
+ int error;
+
+ sc->sc_idma_xferlen = 0x1000;
- mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
- cv_init(&sc->sc_intr_cv, "dwcmmcirq");
+ sc->sc_idma_ndesc = DWC_MMC_NDESC;
+ sc->sc_idma_size = sizeof(struct dwc_mmc_idma_desc) *
+ sc->sc_idma_ndesc;
+ error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 8,
+ sc->sc_idma_size, sc->sc_idma_segs, 1,
+ &sc->sc_idma_nsegs, BUS_DMA_WAITOK);
+ if (error)
+ return error;
+ error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
+ sc->sc_idma_nsegs, sc->sc_idma_size,
+ &sc->sc_idma_desc, BUS_DMA_WAITOK);
+ if (error)
+ goto free;
+ error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
+ sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
+ if (error)
+ goto unmap;
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
+ sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
+ if (error)
+ goto destroy;
+ return 0;
-#ifdef DWC_MMC_DEBUG
- const uint32_t verid = MMC_READ(sc, DWC_MMC_VERID_REG);
- aprint_normal_dev(sc->sc_dev, "version 0x%04x\n", verid & 0xffff);
-#endif
+destroy:
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
+unmap:
+ bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
+free:
+ bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
+ return error;
+}
+
+static void
+dwc_mmc_attach_i(device_t self)
+{
+ struct dwc_mmc_softc *sc = device_private(self);
+ struct sdmmcbus_attach_args saa;
dwc_mmc_host_reset(sc);
dwc_mmc_bus_width(sc, 1);
@@ -115,114 +144,27 @@
saa.saa_sct = &dwc_mmc_chip_functions;
saa.saa_sch = sc;
saa.saa_clkmin = 400;
- if (sc->sc_clock_max) {
- saa.saa_clkmax = sc->sc_clock_max;
- } else {
- saa.saa_clkmax = sc->sc_clock_freq / 1000;
- }
+ saa.saa_clkmax = sc->sc_clock_freq / 1000;
saa.saa_caps = SMC_CAPS_4BIT_MODE|
SMC_CAPS_8BIT_MODE|
SMC_CAPS_SD_HIGHSPEED|
SMC_CAPS_MMC_HIGHSPEED|
SMC_CAPS_AUTO_STOP;
-
-#if notyet
- saa.saa_dmat = sc->sc_dmat;
- saa.saa_caps |= SMC_CAPS_DMA|
- SMC_CAPS_MULTI_SEG_DMA;
-#endif
-
- sc->sc_sdmmc_dev = config_found(sc->sc_dev, &saa, NULL);
-}
-
-int
-dwc_mmc_intr(void *priv)
-{
- struct dwc_mmc_softc *sc = priv;
- uint32_t mint, rint;
-
- mutex_enter(&sc->sc_intr_lock);
- rint = MMC_READ(sc, DWC_MMC_RINTSTS_REG);
- mint = MMC_READ(sc, DWC_MMC_MINTSTS_REG);
- if (!rint && !mint) {
- mutex_exit(&sc->sc_intr_lock);
- return 0;
+ if (ISSET(sc->sc_flags, DWC_MMC_F_DMA)) {
+ saa.saa_dmat = sc->sc_dmat;
+ saa.saa_caps |= SMC_CAPS_DMA |
+ SMC_CAPS_MULTI_SEG_DMA;
}
- MMC_WRITE(sc, DWC_MMC_RINTSTS_REG, rint);
- MMC_WRITE(sc, DWC_MMC_MINTSTS_REG, mint);
-
-#ifdef DWC_MMC_DEBUG
- dwc_mmc_print_rint(sc, "irq", rint);
-#endif
-
- if (rint & DWC_MMC_INT_CARDDET) {
- rint &= ~DWC_MMC_INT_CARDDET;
- if (sc->sc_sdmmc_dev) {
- sdmmc_needs_discover(sc->sc_sdmmc_dev);
- }
- }
-
- if (rint) {
- sc->sc_intr_rint |= rint;
- cv_broadcast(&sc->sc_intr_cv);
- }
-
- mutex_exit(&sc->sc_intr_lock);
-
- return 1;
-}
+ if (sc->sc_card_detect)
+ saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
-static int
-dwc_mmc_set_clock(struct dwc_mmc_softc *sc, u_int freq)
-{
- const u_int pll_freq = sc->sc_clock_freq / 1000;
- const u_int clk_div = howmany(pll_freq, freq * 2);
-
-#ifdef DWC_MMC_DEBUG
- printf("%s: using clk_div %d for freq %d (act %u)\n",
- __func__, clk_div, freq, pll_freq / (clk_div * 2));
-#endif
-
- MMC_WRITE(sc, DWC_MMC_CLKDIV_REG,
- __SHIFTIN(clk_div, DWC_MMC_CLKDIV_CLK_DIVIDER0));
- MMC_WRITE(sc, DWC_MMC_CLKSRC_REG, 0); /* clock divider 0 */
-
- return dwc_mmc_update_clock(sc);
-}
-
-static int
-dwc_mmc_update_clock(struct dwc_mmc_softc *sc)
-{
- uint32_t cmd;
- int retry;
-
- cmd = DWC_MMC_CMD_START_CMD |
- DWC_MMC_CMD_UPDATE_CLOCK_REGS_ONLY |
- DWC_MMC_CMD_WAIT_PRVDATA_COMPLETE;
-
- if (sc->sc_flags & DWC_MMC_F_USE_HOLD_REG)
- cmd |= DWC_MMC_CMD_USE_HOLD_REG;
-
- MMC_WRITE(sc, DWC_MMC_CMD_REG, cmd);
- retry = 0xfffff;
- while (--retry > 0) {
- cmd = MMC_READ(sc, DWC_MMC_CMD_REG);
- if ((cmd & DWC_MMC_CMD_START_CMD) == 0)
- break;
- delay(10);
- }
-
- if (retry == 0) {
- device_printf(sc->sc_dev, "timeout updating clock\n");
- return ETIMEDOUT;
- }
-
- return 0;
+ sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
}
static int
dwc_mmc_wait_rint(struct dwc_mmc_softc *sc, uint32_t mask, int timeout)
{
+ const bool use_dma = ISSET(sc->sc_flags, DWC_MMC_F_DMA);
int retry, error;
KASSERT(mutex_owned(&sc->sc_intr_lock));
@@ -233,17 +175,254 @@
retry = timeout / hz;
while (retry > 0) {
- error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_intr_lock, hz);
- if (error && error != EWOULDBLOCK)
- return error;
- if (sc->sc_intr_rint & mask)
- return 0;
+ if (use_dma) {
+ error = cv_timedwait(&sc->sc_intr_cv,
+ &sc->sc_intr_lock, hz);
+ if (error && error != EWOULDBLOCK)
+ return error;
+ if (sc->sc_intr_rint & mask)
+ return 0;
+ } else {
+ sc->sc_intr_rint |= MMC_READ(sc, DWC_MMC_RINT);
+ if (sc->sc_intr_rint & mask)
+ return 0;
+ delay(1000);
+ }
--retry;
}
return ETIMEDOUT;
}
+static void
+dwc_mmc_led(struct dwc_mmc_softc *sc, int on)
+{
+ if (sc->sc_set_led)
+ sc->sc_set_led(sc, on);
+}
+
+static int
+dwc_mmc_host_reset(sdmmc_chipset_handle_t sch)
Home |
Main Index |
Thread Index |
Old Index