Module Name:    src
Committed By:   martin
Date:           Fri Oct  3 18:53:57 UTC 2014

Modified Files:
        src/sys/arch/arm/broadcom [netbsd-7]: bcm2835_dmac.c bcm2835_dmac.h
            bcm2835_emmc.c bcm2835reg.h files.bcm2835
        src/sys/arch/evbarm/conf [netbsd-7]: RPI
        src/sys/arch/evbarm/rpi [netbsd-7]: rpi_machdep.c
        src/sys/dev/sdmmc [netbsd-7]: sdhc.c sdhcvar.h

Log Message:
Pull up following revision(s) (requested by skrll in ticket #126):
        sys/arch/evbarm/rpi/rpi_machdep.c: revision 1.47
        sys/arch/arm/broadcom/bcm2835reg.h: revision 1.12
        sys/arch/evbarm/conf/RPI: revision 1.52
        sys/arch/evbarm/conf/RPI: revision 1.53
        sys/arch/evbarm/conf/RPI: revision 1.54
        sys/arch/arm/broadcom/bcm2835_emmc.c: revision 1.10
        sys/arch/arm/broadcom/bcm2835_emmc.c: revision 1.11
        sys/arch/arm/broadcom/bcm2835_emmc.c: revision 1.12
        sys/arch/arm/broadcom/bcm2835_emmc.c: revision 1.13
        sys/arch/arm/broadcom/bcm2835_emmc.c: revision 1.14
        sys/arch/arm/broadcom/bcm2835_emmc.c: revision 1.15
        sys/arch/arm/broadcom/bcm2835_dmac.c: revision 1.3
        sys/arch/arm/broadcom/bcm2835_dmac.c: revision 1.4
        sys/arch/arm/broadcom/bcm2835_dmac.h: revision 1.2
        sys/arch/arm/broadcom/bcm2835_dmac.c: revision 1.5
        sys/arch/arm/broadcom/bcm2835_emmc.c: revision 1.18
        sys/arch/arm/broadcom/bcm2835_dmac.h: revision 1.3
        sys/arch/arm/broadcom/bcm2835_dmac.c: revision 1.6
        sys/arch/arm/broadcom/bcm2835_dmac.c: revision 1.7
        sys/arch/arm/broadcom/bcm2835_dmac.c: revision 1.8
        sys/arch/arm/broadcom/bcm2835_dmac.c: revision 1.9
        sys/arch/arm/broadcom/files.bcm2835: revision 1.23
        sys/dev/sdmmc/sdhc.c: revision 1.45
        sys/dev/sdmmc/sdhc.c: revision 1.46
        sys/dev/sdmmc/sdhc.c: revision 1.47
        sys/dev/sdmmc/sdhcvar.h: revision 1.14
Various RPI DMAC and sdhc improvements.


To generate a diff of this commit:
cvs rdiff -u -r1.2.2.2 -r1.2.2.3 src/sys/arch/arm/broadcom/bcm2835_dmac.c
cvs rdiff -u -r1.1.2.2 -r1.1.2.3 src/sys/arch/arm/broadcom/bcm2835_dmac.h
cvs rdiff -u -r1.9 -r1.9.4.1 src/sys/arch/arm/broadcom/bcm2835_emmc.c
cvs rdiff -u -r1.10.12.1 -r1.10.12.2 src/sys/arch/arm/broadcom/bcm2835reg.h
cvs rdiff -u -r1.21.2.1 -r1.21.2.2 src/sys/arch/arm/broadcom/files.bcm2835
cvs rdiff -u -r1.46.2.2 -r1.46.2.3 src/sys/arch/evbarm/conf/RPI
cvs rdiff -u -r1.43.2.1 -r1.43.2.2 src/sys/arch/evbarm/rpi/rpi_machdep.c
cvs rdiff -u -r1.44.2.2 -r1.44.2.3 src/sys/dev/sdmmc/sdhc.c
cvs rdiff -u -r1.13 -r1.13.12.1 src/sys/dev/sdmmc/sdhcvar.h

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/broadcom/bcm2835_dmac.c
diff -u src/sys/arch/arm/broadcom/bcm2835_dmac.c:1.2.2.2 src/sys/arch/arm/broadcom/bcm2835_dmac.c:1.2.2.3
--- src/sys/arch/arm/broadcom/bcm2835_dmac.c:1.2.2.2	Thu Sep 11 14:20:11 2014
+++ src/sys/arch/arm/broadcom/bcm2835_dmac.c	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: bcm2835_dmac.c,v 1.2.2.2 2014/09/11 14:20:11 martin Exp $ */
+/* $NetBSD: bcm2835_dmac.c,v 1.2.2.3 2014/10/03 18:53:56 martin Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "opt_ddb.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_dmac.c,v 1.2.2.2 2014/09/11 14:20:11 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_dmac.c,v 1.2.2.3 2014/10/03 18:53:56 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -45,7 +45,7 @@ __KERNEL_RCSID(0, "$NetBSD: bcm2835_dmac
 
 #include <arm/broadcom/bcm2835_dmac.h>
 
-#define BCM_DMAC_CHANNELMASK	0x00000ff2
+#define BCM_DMAC_CHANNELMASK	0x00000fff
 
 struct bcm_dmac_softc;
 
@@ -109,6 +109,7 @@ static void
 bcm_dmac_attach(device_t parent, device_t self, void *aux)
 {
 	struct bcm_dmac_softc *sc = device_private(self);
+	const prop_dictionary_t cfg = device_properties(self);
 	struct bcm_dmac_channel *ch;
 	struct amba_attach_args *aaa = aux;
 	uint32_t val;
@@ -123,12 +124,12 @@ bcm_dmac_attach(device_t parent, device_
 		return;
 	}
 
-	sc->sc_channelmask = BCM_DMAC_CHANNELMASK;
-	sc->sc_nchannels = 31 - __builtin_clz(sc->sc_channelmask);
+	prop_dictionary_get_uint32(cfg, "chanmask", &sc->sc_channelmask);
+	sc->sc_channelmask &= BCM_DMAC_CHANNELMASK;
 
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED);
 
-	sc->sc_nchannels = 31 - __builtin_clz(BCM_DMAC_CHANNELMASK);
+	sc->sc_nchannels = 31 - __builtin_clz(sc->sc_channelmask);
 	sc->sc_channels = kmem_alloc(
 	    sizeof(*sc->sc_channels) * sc->sc_nchannels, KM_SLEEP);
 	if (sc->sc_channels == NULL) {
@@ -143,6 +144,7 @@ bcm_dmac_attach(device_t parent, device_
 		ch->ch_index = index;
 		ch->ch_callback = NULL;
 		ch->ch_callbackarg = NULL;
+		ch->ch_ih = NULL;
 		if ((__BIT(index) & sc->sc_channelmask) == 0)
 			continue;
 
@@ -153,13 +155,6 @@ bcm_dmac_attach(device_t parent, device_
 		val = DMAC_READ(sc, DMAC_CS(index));
 		val |= DMAC_CS_RESET;
 		DMAC_WRITE(sc, DMAC_CS(index), val);
-
-		ch->ch_ih = bcm2835_intr_establish(BCM2835_INT_DMA0 + index,
-		    IPL_SCHED, bcm_dmac_intr, ch);
-		if (ch->ch_ih == NULL) {
-			aprint_error("(err)");
-			sc->sc_channelmask &= ~__BIT(index);
-		}
 	}
 	aprint_normal("\n");
 	aprint_naive("\n");
@@ -185,7 +180,8 @@ bcm_dmac_intr(void *priv)
 }
 
 struct bcm_dmac_channel *
-bcm_dmac_alloc(enum bcm_dmac_type type, void (*cb)(void *), void *cbarg)
+bcm_dmac_alloc(enum bcm_dmac_type type, int ipl, void (*cb)(void *),
+    void *cbarg)
 {
 	struct bcm_dmac_softc *sc;
 	struct bcm_dmac_channel *ch = NULL;
@@ -213,6 +209,20 @@ bcm_dmac_alloc(enum bcm_dmac_type type, 
 	}
 	mutex_exit(&sc->sc_lock);
 
+	if (ch == NULL)
+		return NULL;
+
+	KASSERT(ch->ch_ih == NULL);
+	ch->ch_ih = bcm2835_intr_establish(BCM2835_INT_DMA0 + ch->ch_index,
+	    ipl, bcm_dmac_intr, ch);
+	if (ch->ch_ih == NULL) {
+		aprint_error_dev(sc->sc_dev,
+		    "failed to establish interrupt for DMA%d\n", ch->ch_index);
+		ch->ch_callback = NULL;
+		ch->ch_callbackarg = NULL;
+		ch = NULL;
+	}
+
 	return ch;
 }
 
@@ -231,6 +241,8 @@ bcm_dmac_free(struct bcm_dmac_channel *c
 	DMAC_WRITE(sc, DMAC_CS(ch->ch_index), val);
 
 	mutex_enter(&sc->sc_lock);
+	intr_disestablish(ch->ch_ih);
+	ch->ch_ih = NULL;
 	ch->ch_callback = NULL;
 	ch->ch_callbackarg = NULL;
 	mutex_exit(&sc->sc_lock);

Index: src/sys/arch/arm/broadcom/bcm2835_dmac.h
diff -u src/sys/arch/arm/broadcom/bcm2835_dmac.h:1.1.2.2 src/sys/arch/arm/broadcom/bcm2835_dmac.h:1.1.2.3
--- src/sys/arch/arm/broadcom/bcm2835_dmac.h:1.1.2.2	Thu Sep 11 14:20:11 2014
+++ src/sys/arch/arm/broadcom/bcm2835_dmac.h	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: bcm2835_dmac.h,v 1.1.2.2 2014/09/11 14:20:11 martin Exp $ */
+/* $NetBSD: bcm2835_dmac.h,v 1.1.2.3 2014/10/03 18:53:56 martin Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -46,6 +46,12 @@
 #define  DMAC_CS_ACTIVE		__BIT(0)
 #define  DMAC_CS_INTMASK	(DMAC_CS_INT|DMAC_CS_END)
 #define DMAC_CONBLK_AD(n)	(0x04 + (0x100 * (n)))
+#define DMAC_TI(n)		(0x08 + (0x100 * (n)))
+#define DMAC_SOURCE_AD(n)	(0x0c + (0x100 * (n)))
+#define DMAC_DEST_AD(n)		(0x10 + (0x100 * (n)))
+#define DMAC_TXFR_LEN(n)	(0x14 + (0x100 * (n)))
+#define DMAC_STRIDE(n)		(0x18 + (0x100 * (n)))
+#define DMAC_NEXTCONBK(n)	(0x1c + (0x100 * (n)))
 #define DMAC_DEBUG(n)		(0x20 + (0x100 * (n)))
 #define  DMAC_DEBUG_LITE	__BIT(28)
 #define  DMAC_DEBUG_VERSION	__BITS(27,25)
@@ -95,7 +101,7 @@ enum bcm_dmac_type {
 
 struct bcm_dmac_channel;
 
-struct bcm_dmac_channel *bcm_dmac_alloc(enum bcm_dmac_type,
+struct bcm_dmac_channel *bcm_dmac_alloc(enum bcm_dmac_type, int,
 					void (*)(void *), void *);
 void bcm_dmac_free(struct bcm_dmac_channel *);
 void bcm_dmac_set_conblk_addr(struct bcm_dmac_channel *, bus_addr_t);

Index: src/sys/arch/arm/broadcom/bcm2835_emmc.c
diff -u src/sys/arch/arm/broadcom/bcm2835_emmc.c:1.9 src/sys/arch/arm/broadcom/bcm2835_emmc.c:1.9.4.1
--- src/sys/arch/arm/broadcom/bcm2835_emmc.c:1.9	Thu Sep  5 07:06:37 2013
+++ src/sys/arch/arm/broadcom/bcm2835_emmc.c	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_emmc.c,v 1.9 2013/09/05 07:06:37 skrll Exp $	*/
+/*	$NetBSD: bcm2835_emmc.c,v 1.9.4.1 2014/10/03 18:53:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,32 +30,61 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_emmc.c,v 1.9 2013/09/05 07:06:37 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_emmc.c,v 1.9.4.1 2014/10/03 18:53:56 martin Exp $");
+
+#include "bcmdmac.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
 #include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/mutex.h>
+#include <sys/kernel.h>
 
 #include <arm/broadcom/bcm2835reg.h>
 #include <arm/broadcom/bcm_amba.h>
+#include <arm/broadcom/bcm2835_dmac.h>
 
 #include <dev/sdmmc/sdhcreg.h>
 #include <dev/sdmmc/sdhcvar.h>
 #include <dev/sdmmc/sdmmcvar.h>
 
+enum bcmemmc_dma_state {
+	EMMC_DMA_STATE_IDLE,
+	EMMC_DMA_STATE_BUSY,
+};
+
 struct bcmemmc_softc {
 	struct sdhc_softc	sc;
-	device_t		sc_sdmmc;
 
 	bus_space_tag_t		sc_iot;
 	bus_space_handle_t	sc_ioh;
+	bus_size_t		sc_ios;
 	struct sdhc_host	*sc_hosts[1];
 	void			*sc_ih;
+
+	kmutex_t		sc_lock;
+	kcondvar_t		sc_cv;
+
+	enum bcmemmc_dma_state	sc_state;
+
+	struct bcm_dmac_channel	*sc_dmac;
+
+	bus_dmamap_t		sc_dmamap;
+	bus_dma_segment_t	sc_segs[1];	/* XXX assumes enough descriptors fit in one page */
+	struct bcm_dmac_conblk	*sc_cblk;
+
+	uint32_t		sc_physaddr;
 };
 
 static int bcmemmc_match(device_t, struct cfdata *, void *);
 static void bcmemmc_attach(device_t, device_t, void *);
+static void bcmemmc_attach_i(device_t);
+#if NBCMDMAC > 0
+static int bcmemmc_xfer_data_dma(struct sdhc_host *, struct sdmmc_command *);
+static void bcmemmc_dma_done(void *);
+#endif
 
 CFATTACH_DECL_NEW(bcmemmc, sizeof(struct bcmemmc_softc),
     bcmemmc_match, bcmemmc_attach, NULL, NULL);
@@ -89,11 +118,8 @@ bcmemmc_attach(device_t parent, device_t
 	sc->sc.sc_flags |= SDHC_FLAG_HOSTCAPS;
 	sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT;
 	sc->sc.sc_caps = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP |
-	    SDHC_MAX_BLK_LEN_1024;
-#if notyet
- 	sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
-	sc->sc.sc_caps |= SDHC_DMA_SUPPORT;
-#endif
+	    (SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT);
+
 	sc->sc.sc_host = sc->sc_hosts;
 	sc->sc.sc_clkbase = 50000;	/* Default to 50MHz */
 	sc->sc_iot = aaa->aaa_iot;
@@ -111,6 +137,8 @@ bcmemmc_attach(device_t parent, device_t
 		    "can't map registers for %s: %d\n", aaa->aaa_name, error);
 		return;
 	}
+	sc->sc_ios = aaa->aaa_size;
+	sc->sc_physaddr = aaa->aaa_addr;
 
 	aprint_naive(": SDHC controller\n");
 	aprint_normal(": SDHC controller\n");
@@ -125,8 +153,74 @@ bcmemmc_attach(device_t parent, device_t
 	}
 	aprint_normal_dev(self, "interrupting on intr %d\n", aaa->aaa_intr);
 
-	error = sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh,
-	    aaa->aaa_size);
+#if NBCMDMAC > 0
+	sc->sc_dmac = bcm_dmac_alloc(BCM_DMAC_TYPE_NORMAL, IPL_SDMMC,
+	    bcmemmc_dma_done, sc);
+	if (sc->sc_dmac == NULL)
+		goto done;
+
+ 	sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
+	sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA;
+	sc->sc.sc_caps |= SDHC_DMA_SUPPORT;
+	sc->sc.sc_vendor_transfer_data_dma = bcmemmc_xfer_data_dma;
+
+	sc->sc_state = EMMC_DMA_STATE_IDLE;
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SDMMC);
+	cv_init(&sc->sc_cv, "bcmemmcdma");
+
+	int rseg;
+	error = bus_dmamem_alloc(sc->sc.sc_dmat, PAGE_SIZE, PAGE_SIZE,
+	     PAGE_SIZE, sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK);
+	if (error) {
+		aprint_error_dev(self, "dmamem_alloc failed (%d)\n", error);
+		goto fail;
+	}
+
+	error = bus_dmamem_map(sc->sc.sc_dmat, sc->sc_segs, rseg, PAGE_SIZE,
+	    (void **)&sc->sc_cblk, BUS_DMA_WAITOK);
+	if (error) {
+		aprint_error_dev(self, "dmamem_map failed (%d)\n", error);
+		goto fail;
+	}
+	KASSERT(sc->sc_cblk != NULL);
+
+	memset(sc->sc_cblk, 0, PAGE_SIZE);
+
+	error = bus_dmamap_create(sc->sc.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
+	    BUS_DMA_WAITOK, &sc->sc_dmamap);
+	if (error) {
+		aprint_error_dev(self, "dmamap_create failed (%d)\n", error);
+		goto fail;
+	}
+
+	error = bus_dmamap_load(sc->sc.sc_dmat, sc->sc_dmamap, sc->sc_cblk,
+	    PAGE_SIZE, NULL, BUS_DMA_WAITOK|BUS_DMA_WRITE);
+	if (error) {
+		aprint_error_dev(self, "dmamap_load failed (%d)\n", error);
+		goto fail;
+	}
+
+done:
+#endif
+	config_interrupts(self, bcmemmc_attach_i);
+	return;
+
+fail:
+	/* XXX add bus_dma failure cleanup */
+	if (sc->sc_ih) {
+		intr_disestablish(sc->sc_ih);
+		sc->sc_ih = NULL;
+	}
+	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
+}
+
+static void
+bcmemmc_attach_i(device_t self)
+{
+	struct bcmemmc_softc * const sc = device_private(self);
+	int error;
+
+	error = sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_ios);
 	if (error != 0) {
 		aprint_error_dev(self, "couldn't initialize host, error=%d\n",
 		    error);
@@ -135,9 +229,99 @@ bcmemmc_attach(device_t parent, device_t
 	return;
 
 fail:
+	/* XXX add bus_dma failure cleanup */
 	if (sc->sc_ih) {
 		intr_disestablish(sc->sc_ih);
 		sc->sc_ih = NULL;
 	}
-	bus_space_unmap(sc->sc_iot, sc->sc_ioh, aaa->aaa_size);
+	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
+}
+
+#if NBCMDMAC > 0
+static int
+bcmemmc_xfer_data_dma(struct sdhc_host *hp, struct sdmmc_command *cmd)
+{
+	struct bcmemmc_softc * const sc = *(void **)hp;	/* XXX XXX XXX */
+	size_t seg;
+	int error;
+
+	for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
+		sc->sc_cblk[seg].cb_ti =
+		    __SHIFTIN(11, DMAC_TI_PERMAP); /* e.MMC */
+		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_DEST_INC;
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_DEST_WIDTH;
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_SRC_DREQ;
+			sc->sc_cblk[seg].cb_source_ad =
+			    BCM2835_PERIPHERALS_TO_BUS(sc->sc_physaddr +
+			    SDHC_DATA);
+			sc->sc_cblk[seg].cb_dest_ad =
+			    cmd->c_dmamap->dm_segs[seg].ds_addr;
+		} else {
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_SRC_INC;
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_SRC_WIDTH;
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_DEST_DREQ;
+			sc->sc_cblk[seg].cb_source_ad =
+			    cmd->c_dmamap->dm_segs[seg].ds_addr;
+			sc->sc_cblk[seg].cb_dest_ad =
+			    BCM2835_PERIPHERALS_TO_BUS(sc->sc_physaddr +
+			    SDHC_DATA);
+		}
+		sc->sc_cblk[seg].cb_txfr_len =
+		    cmd->c_dmamap->dm_segs[seg].ds_len;
+		sc->sc_cblk[seg].cb_stride = 0;
+		if (seg == cmd->c_dmamap->dm_nsegs - 1) {
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_WAIT_RESP;
+			sc->sc_cblk[seg].cb_ti |= DMAC_TI_INTEN;
+			sc->sc_cblk[seg].cb_nextconbk = 0;
+		} else {
+			sc->sc_cblk[seg].cb_nextconbk =
+			    sc->sc_dmamap->dm_segs[0].ds_addr +
+			    sizeof(struct bcm_dmac_conblk) * (seg+1);
+		}
+		sc->sc_cblk[seg].cb_padding[0] = 0;
+		sc->sc_cblk[seg].cb_padding[1] = 0;
+	}
+
+	bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_dmamap, 0,
+	    sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
+
+	error = 0;
+
+	mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_state == EMMC_DMA_STATE_IDLE);
+	sc->sc_state = EMMC_DMA_STATE_BUSY;
+	bcm_dmac_set_conblk_addr(sc->sc_dmac,
+	    sc->sc_dmamap->dm_segs[0].ds_addr);
+	bcm_dmac_transfer(sc->sc_dmac);
+	while (sc->sc_state == EMMC_DMA_STATE_BUSY) {
+		error = cv_timedwait(&sc->sc_cv, &sc->sc_lock, hz * 10);
+		if (error == EWOULDBLOCK) {
+			device_printf(sc->sc.sc_dev, "transfer timeout!\n");
+			bcm_dmac_halt(sc->sc_dmac);
+			sc->sc_state = EMMC_DMA_STATE_IDLE;
+			error = ETIMEDOUT;
+			break;
+		}
+	}
+	mutex_exit(&sc->sc_lock);
+
+	bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_dmamap, 0,
+	    sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+
+	return error;
+}
+
+static void
+bcmemmc_dma_done(void *arg)
+{
+	struct bcmemmc_softc * const sc = arg;
+
+	mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_state == EMMC_DMA_STATE_BUSY);
+	sc->sc_state = EMMC_DMA_STATE_IDLE;
+	cv_broadcast(&sc->sc_cv);
+	mutex_exit(&sc->sc_lock);
+
 }
+#endif

Index: src/sys/arch/arm/broadcom/bcm2835reg.h
diff -u src/sys/arch/arm/broadcom/bcm2835reg.h:1.10.12.1 src/sys/arch/arm/broadcom/bcm2835reg.h:1.10.12.2
--- src/sys/arch/arm/broadcom/bcm2835reg.h:1.10.12.1	Thu Sep 11 14:20:11 2014
+++ src/sys/arch/arm/broadcom/bcm2835reg.h	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835reg.h,v 1.10.12.1 2014/09/11 14:20:11 martin Exp $	*/
+/*	$NetBSD: bcm2835reg.h,v 1.10.12.2 2014/10/03 18:53:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -40,6 +40,9 @@
 
 #define	BCM2835_PERIPHERALS_BASE	0x20000000
 #define	BCM2835_PERIPHERALS_SIZE	0x01000000	/* 16MBytes */
+#define	BCM2835_PERIPHERALS_BASE_BUS	0x7e000000
+#define	BCM2835_PERIPHERALS_TO_BUS(a) \
+    ((a) - BCM2835_PERIPHERALS_BASE + BCM2835_PERIPHERALS_BASE_BUS)
 
 #define	BCM2835_STIMER_BASE	(BCM2835_PERIPHERALS_BASE + 0x00003000)
 #define	BCM2835_DMA0_BASE	(BCM2835_PERIPHERALS_BASE + 0x00007000)

Index: src/sys/arch/arm/broadcom/files.bcm2835
diff -u src/sys/arch/arm/broadcom/files.bcm2835:1.21.2.1 src/sys/arch/arm/broadcom/files.bcm2835:1.21.2.2
--- src/sys/arch/arm/broadcom/files.bcm2835:1.21.2.1	Thu Sep 11 14:20:11 2014
+++ src/sys/arch/arm/broadcom/files.bcm2835	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-#	$NetBSD: files.bcm2835,v 1.21.2.1 2014/09/11 14:20:11 martin Exp $
+#	$NetBSD: files.bcm2835,v 1.21.2.2 2014/10/03 18:53:56 martin Exp $
 #
 # Configuration info for Broadcom BCM2835 ARM Peripherals
 #
@@ -57,7 +57,7 @@ file	arch/arm/broadcom/bcm2835_emmc.c	bc
 # DMA Controller (BCM2835_DMA0_BASE)
 device	bcmdmac
 attach	bcmdmac at obio with bcmdmac_amba
-file	arch/arm/broadcom/bcm2835_dmac.c	bcmdmac
+file	arch/arm/broadcom/bcm2835_dmac.c	bcmdmac		needs-flag
 
 # USB (BCM2835_USB_BASE)
 attach dwctwo at obio with bcmdwctwo

Index: src/sys/arch/evbarm/conf/RPI
diff -u src/sys/arch/evbarm/conf/RPI:1.46.2.2 src/sys/arch/evbarm/conf/RPI:1.46.2.3
--- src/sys/arch/evbarm/conf/RPI:1.46.2.2	Thu Sep 11 14:20:10 2014
+++ src/sys/arch/evbarm/conf/RPI	Fri Oct  3 18:53:56 2014
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: RPI,v 1.46.2.2 2014/09/11 14:20:10 martin Exp $
+#	$NetBSD: RPI,v 1.46.2.3 2014/10/03 18:53:56 martin Exp $
 #
 #	RPi -- Raspberry Pi
 #
@@ -180,7 +180,7 @@ bcmmbox0	at obio?
 vcmbox0 	at bcmmbox0
 
 # DMA Controller
-#bcmdmac0	at obio?
+bcmdmac0	at obio?
 
 # VCHIQ
 vchiq0		at obio?

Index: src/sys/arch/evbarm/rpi/rpi_machdep.c
diff -u src/sys/arch/evbarm/rpi/rpi_machdep.c:1.43.2.1 src/sys/arch/evbarm/rpi/rpi_machdep.c:1.43.2.2
--- src/sys/arch/evbarm/rpi/rpi_machdep.c:1.43.2.1	Thu Sep 11 14:20:11 2014
+++ src/sys/arch/evbarm/rpi/rpi_machdep.c	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rpi_machdep.c,v 1.43.2.1 2014/09/11 14:20:11 martin Exp $	*/
+/*	$NetBSD: rpi_machdep.c,v 1.43.2.2 2014/10/03 18:53:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.43.2.1 2014/09/11 14:20:11 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.43.2.2 2014/10/03 18:53:56 martin Exp $");
 
 #include "opt_evbarm_boardtype.h"
 #include "opt_ddb.h"
@@ -822,6 +822,11 @@ rpi_device_register(device_t dev, void *
 {
 	prop_dictionary_t dict = device_properties(dev);
 
+	if (device_is_a(dev, "bcmdmac") &&
+	    vcprop_tag_success_p(&vb.vbt_dmachan.tag)) {
+		prop_dictionary_set_uint32(dict,
+		    "chanmask", vb.vbt_dmachan.mask);
+	}
 #if NSDHC > 0
 	if (device_is_a(dev, "sdhc") &&
 	    vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) &&

Index: src/sys/dev/sdmmc/sdhc.c
diff -u src/sys/dev/sdmmc/sdhc.c:1.44.2.2 src/sys/dev/sdmmc/sdhc.c:1.44.2.3
--- src/sys/dev/sdmmc/sdhc.c:1.44.2.2	Thu Oct  2 14:42:53 2014
+++ src/sys/dev/sdmmc/sdhc.c	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhc.c,v 1.44.2.2 2014/10/02 14:42:53 martin Exp $	*/
+/*	$NetBSD: sdhc.c,v 1.44.2.3 2014/10/03 18:53:56 martin Exp $	*/
 /*	$OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $	*/
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.44.2.2 2014/10/02 14:42:53 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.44.2.3 2014/10/03 18:53:56 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -222,7 +222,7 @@ sdhc_cfprint(void *aux, const char *pnp)
 {
 	const struct sdmmcbus_attach_args * const saa = aux;
 	const struct sdhc_host * const hp = saa->saa_sch;
-	
+
 	if (pnp) {
 		aprint_normal("sdmmc at %s", pnp);
 	}
@@ -1034,7 +1034,7 @@ sdhc_card_enable_intr(sdmmc_chipset_hand
 	}
 }
 
-static void 
+static void
 sdhc_card_intr_ack(sdmmc_chipset_handle_t sch)
 {
 	struct sdhc_host *hp = (struct sdhc_host *)sch;
@@ -1077,7 +1077,7 @@ sdhc_exec_command(sdmmc_chipset_handle_t
 		} else {
 			HSET2(hp, SDHC_NINTR_SIGNAL_EN, ready);
 			HSET2(hp, SDHC_NINTR_STATUS_EN, ready);
-		}  
+		}
 		mutex_exit(&hp->intr_mtx);
 	}
 
@@ -1199,7 +1199,8 @@ sdhc_start_command(struct sdhc_host *hp,
 		/* XXX only for memory commands? */
 		mode |= SDHC_AUTO_CMD12_ENABLE;
 	}
-	if (cmd->c_dmamap != NULL && cmd->c_datalen > 0) {
+	if (cmd->c_dmamap != NULL && cmd->c_datalen > 0 &&
+	    !ISSET(sc->sc_flags, SDHC_FLAG_EXTERNAL_DMA)) {
 		mode |= SDHC_DMA_ENABLE;
 	}
 
@@ -1287,9 +1288,17 @@ sdhc_transfer_data(struct sdhc_host *hp,
 	}
 #endif
 
-	if (cmd->c_dmamap != NULL)
-		error = sdhc_transfer_data_dma(hp, cmd);
-	else
+	if (cmd->c_dmamap != NULL) {
+		if (hp->sc->sc_vendor_transfer_data_dma != NULL) {
+			error = hp->sc->sc_vendor_transfer_data_dma(hp, cmd);
+			if (error == 0 && !sdhc_wait_intr(hp,
+			    SDHC_TRANSFER_COMPLETE, SDHC_TRANSFER_TIMEOUT)) {
+				error = ETIMEDOUT;
+			}
+		} else {
+			error = sdhc_transfer_data_dma(hp, cmd);
+		}
+	} else
 		error = sdhc_transfer_data_pio(hp, cmd);
 	if (error)
 		cmd->c_error = error;
@@ -1643,7 +1652,7 @@ sdhc_wait_intr(struct sdhc_host *hp, int
 
 	DPRINTF(2,("%s: intr status %#x error %#x\n", HDEVNAME(hp), status,
 	    hp->intr_error_status));
-	
+
 	/* Command timeout has higher priority than command complete. */
 	if (ISSET(status, SDHC_ERROR_INTERRUPT) || hp->intr_error_status) {
 		hp->intr_error_status = 0;
@@ -1701,7 +1710,7 @@ sdhc_intr(void *arg)
 				HWRITE2(hp, SDHC_EINTR_STATUS, error);
 			}
 		}
-	
+
 		DPRINTF(2,("%s: interrupt status=%x error=%x\n", HDEVNAME(hp),
 		    status, error));
 
@@ -1724,7 +1733,9 @@ sdhc_intr(void *arg)
 		 * Wake up the sdmmc event thread to scan for cards.
 		 */
 		if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) {
-			sdmmc_needs_discover(hp->sdmmc);
+			if (hp->sdmmc != NULL) {
+				sdmmc_needs_discover(hp->sdmmc);
+			}
 			if (ISSET(sc->sc_flags, SDHC_FLAG_ENHANCED)) {
 				HCLR4(hp, SDHC_NINTR_STATUS_EN,
 				    status & (SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION));

Index: src/sys/dev/sdmmc/sdhcvar.h
diff -u src/sys/dev/sdmmc/sdhcvar.h:1.13 src/sys/dev/sdmmc/sdhcvar.h:1.13.12.1
--- src/sys/dev/sdmmc/sdhcvar.h:1.13	Thu Jan 10 17:19:33 2013
+++ src/sys/dev/sdmmc/sdhcvar.h	Fri Oct  3 18:53:56 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhcvar.h,v 1.13 2013/01/10 17:19:33 jmcneill Exp $	*/
+/*	$NetBSD: sdhcvar.h,v 1.13.12.1 2014/10/03 18:53:56 martin Exp $	*/
 /*	$OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $	*/
 
 /*
@@ -25,6 +25,7 @@
 #include <sys/pmf.h>
 
 struct sdhc_host;
+struct sdmmc_command;
 
 struct sdhc_softc {
 	device_t		sc_dev;
@@ -49,6 +50,7 @@ struct sdhc_softc {
 #define	SDHC_FLAG_SINGLE_ONLY	0x0800	/* Single transfer only */
 #define	SDHC_FLAG_WAIT_RESET	0x1000	/* Wait for soft resets to start */
 #define	SDHC_FLAG_NO_HS_BIT	0x2000	/* Don't set SDHC_HIGH_SPEED bit */
+#define	SDHC_FLAG_EXTERNAL_DMA	0x4000
 
 	uint32_t		sc_clkbase;
 	int			sc_clkmsk;	/* Mask for SDCLK */
@@ -58,6 +60,7 @@ struct sdhc_softc {
 	int (*sc_vendor_write_protect)(struct sdhc_softc *);
 	int (*sc_vendor_card_detect)(struct sdhc_softc *);
 	int (*sc_vendor_bus_clock)(struct sdhc_softc *, int);
+	int (*sc_vendor_transfer_data_dma)(struct sdhc_host *, struct sdmmc_command *);
 };
 
 /* Host controller functions called by the attachment driver. */

Reply via email to