Module Name:    src
Committed By:   skrll
Date:           Tue Oct  7 08:30:05 UTC 2014

Modified Files:
        src/sys/arch/arm/broadcom: bcm2835_mbox.c bcm2835_mbox.h
            bcm2835_mbox_subr.c bcm2835_obio.c

Log Message:
Mailbox improvements from mlelstv@

Serialise access to the mailbox and use interrupts.

XXX if (cold) should go


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/broadcom/bcm2835_mbox.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/broadcom/bcm2835_mbox.h
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/broadcom/bcm2835_mbox_subr.c
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/broadcom/bcm2835_obio.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/broadcom/bcm2835_mbox.c
diff -u src/sys/arch/arm/broadcom/bcm2835_mbox.c:1.7 src/sys/arch/arm/broadcom/bcm2835_mbox.c:1.8
--- src/sys/arch/arm/broadcom/bcm2835_mbox.c:1.7	Thu Oct  2 11:58:12 2014
+++ src/sys/arch/arm/broadcom/bcm2835_mbox.c	Tue Oct  7 08:30:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_mbox.c,v 1.7 2014/10/02 11:58:12 skrll Exp $	*/
+/*	$NetBSD: bcm2835_mbox.c,v 1.8 2014/10/07 08:30:05 skrll Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_mbox.c,v 1.7 2014/10/02 11:58:12 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_mbox.c,v 1.8 2014/10/07 08:30:05 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -52,14 +52,20 @@ struct bcm2835mbox_softc {
 	bus_space_tag_t sc_iot;
 	bus_space_handle_t sc_ioh;
 	bus_dma_tag_t sc_dmat;
+	void *sc_intrh;
 
 	kmutex_t sc_lock;
+	kmutex_t sc_intr_lock;
+	kcondvar_t sc_chan[BCM2835_MBOX_NUMCHANNELS];
+	uint32_t sc_mbox[BCM2835_MBOX_NUMCHANNELS];
 };
 
 static struct bcm2835mbox_softc *bcm2835mbox_sc;
 
 static int bcmmbox_match(device_t, cfdata_t, void *);
 static void bcmmbox_attach(device_t, device_t, void *);
+static int bcmmbox_intr1(struct bcm2835mbox_softc *, int);
+static int bcmmbox_intr(void *);
 
 CFATTACH_DECL_NEW(bcmmbox, sizeof(struct bcm2835mbox_softc),
     bcmmbox_match, bcmmbox_attach, NULL, NULL);
@@ -82,17 +88,18 @@ bcmmbox_attach(device_t parent, device_t
         struct bcm2835mbox_softc *sc = device_private(self);
  	struct amba_attach_args *aaa = aux;
 	struct bcmmbox_attach_args baa;
+	int i;
 
 	aprint_naive("\n");
 	aprint_normal(": VC mailbox\n");
 
-	if (bcm2835mbox_sc == NULL)
-		bcm2835mbox_sc = sc;
-
 	sc->sc_dev = self;
 	sc->sc_iot = aaa->aaa_iot;
 	sc->sc_dmat = aaa->aaa_dmat;
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_VM);
+	for (i = 0; i < BCM2835_MBOX_NUMCHANNELS; ++i)
+		cv_init(&sc->sc_chan[i], "bcmmbox");
 
 	if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, BCM2835_MBOX_SIZE, 0,
 	    &sc->sc_ioh)) {
@@ -100,10 +107,74 @@ bcmmbox_attach(device_t parent, device_t
 		return;
 	}
 
+	sc->sc_intrh = bcm2835_intr_establish(aaa->aaa_intr, IPL_VM,
+	    bcmmbox_intr, sc);
+	if (sc->sc_intrh == NULL) {
+		aprint_error_dev(sc->sc_dev, "unable to establish interrupt\n");
+		return;
+	}
+
+	/* enable mbox interrupt */
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCM2835_MBOX_CFG,
+	    BCM2835_MBOX_CFG_DATAIRQEN);
+
+	if (bcm2835mbox_sc == NULL)
+		bcm2835mbox_sc = sc;
+
 	baa.baa_dmat = aaa->aaa_dmat;
 	sc->sc_platdev = config_found_ia(self, "bcmmboxbus", &baa, NULL);
 }
 
+static int
+bcmmbox_intr1(struct bcm2835mbox_softc *sc, int cv)
+{
+	uint32_t mbox, chan, data;
+	int ret = 0;
+
+	KASSERT(mutex_owned(&sc->sc_intr_lock));
+
+	bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, BCM2835_MBOX_SIZE,
+	    BUS_SPACE_BARRIER_READ);
+
+	while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+	    BCM2835_MBOX0_STATUS) & BCM2835_MBOX_STATUS_EMPTY) == 0) {
+
+		mbox = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+		    BCM2835_MBOX0_READ);
+
+		chan = BCM2835_MBOX_CHAN(mbox);
+		data = BCM2835_MBOX_DATA(mbox);
+		ret = 1;
+
+		if (BCM2835_MBOX_CHAN(sc->sc_mbox[chan]) != 0) {
+			aprint_error("bcmmbox_intr: chan %d overflow\n",chan);
+			continue;
+		}
+
+		sc->sc_mbox[chan] = data | BCM2835_MBOX_CHANMASK;
+
+		if (cv)
+			cv_broadcast(&sc->sc_chan[chan]);
+	}
+
+	return ret;
+}
+
+static int
+bcmmbox_intr(void *cookie)
+{
+	struct bcm2835mbox_softc *sc = cookie;
+	int ret;
+
+	mutex_enter(&sc->sc_intr_lock);
+
+	ret = bcmmbox_intr1(sc, 1);
+
+	mutex_exit(&sc->sc_intr_lock);
+
+	return ret;
+}
+
 void
 bcmmbox_read(uint8_t chan, uint32_t *data)
 {
@@ -111,7 +182,20 @@ bcmmbox_read(uint8_t chan, uint32_t *dat
 
 	KASSERT(sc != NULL);
 
-	return bcm2835_mbox_read(sc->sc_iot, sc->sc_ioh, chan, data);
+	mutex_enter(&sc->sc_lock);
+
+	mutex_enter(&sc->sc_intr_lock);
+	while (BCM2835_MBOX_CHAN(sc->sc_mbox[chan]) == 0) {
+		if (cold)
+			bcmmbox_intr1(sc, 0);
+		else
+			cv_wait(&sc->sc_chan[chan], &sc->sc_intr_lock);
+	}
+	*data = BCM2835_MBOX_DATA(sc->sc_mbox[chan]);
+	sc->sc_mbox[chan] = 0;
+	mutex_exit(&sc->sc_intr_lock);
+
+	mutex_exit(&sc->sc_lock);
 }
 
 void
@@ -120,8 +204,14 @@ bcmmbox_write(uint8_t chan, uint32_t dat
 	struct bcm2835mbox_softc *sc = bcm2835mbox_sc;
 
 	KASSERT(sc != NULL);
+	KASSERT(BCM2835_MBOX_CHAN(chan) == chan);
+	KASSERT(BCM2835_MBOX_CHAN(data) == 0);
+
+	mutex_enter(&sc->sc_lock);
+
+	bcm2835_mbox_write(sc->sc_iot, sc->sc_ioh, chan, data);
 
-	return bcm2835_mbox_write(sc->sc_iot, sc->sc_ioh, chan, data);
+	mutex_exit(&sc->sc_lock);
 }
 
 int
@@ -155,16 +245,12 @@ bcmmbox_request(uint8_t chan, void *buf,
 
 	memcpy(dma_buf, buf, buflen);
 
-	mutex_enter(&sc->sc_lock);
-
-	bus_dmamap_sync(sc->sc_dmat, map, 0, buflen, BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(sc->sc_dmat, map, 0, buflen,
+	     BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
 	bcmmbox_write(chan, map->dm_segs[0].ds_addr);
-	bus_dmamap_sync(sc->sc_dmat, map, 0, buflen, BUS_DMASYNC_POSTWRITE);
-	bus_dmamap_sync(sc->sc_dmat, map, 0, buflen, BUS_DMASYNC_PREREAD);
 	bcmmbox_read(chan, pres);
-	bus_dmamap_sync(sc->sc_dmat, map, 0, buflen, BUS_DMASYNC_POSTREAD);
-
-	mutex_exit(&sc->sc_lock);
+	bus_dmamap_sync(sc->sc_dmat, map, 0, buflen,
+	    BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
 
 	memcpy(buf, dma_buf, buflen);
 

Index: src/sys/arch/arm/broadcom/bcm2835_mbox.h
diff -u src/sys/arch/arm/broadcom/bcm2835_mbox.h:1.4 src/sys/arch/arm/broadcom/bcm2835_mbox.h:1.5
--- src/sys/arch/arm/broadcom/bcm2835_mbox.h:1.4	Mon Jan  7 20:15:32 2013
+++ src/sys/arch/arm/broadcom/bcm2835_mbox.h	Tue Oct  7 08:30:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_mbox.h,v 1.4 2013/01/07 20:15:32 jmcneill Exp $	*/
+/*	$NetBSD: bcm2835_mbox.h,v 1.5 2014/10/07 08:30:05 skrll Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -34,6 +34,15 @@
 
 #include <sys/bus.h>
 
+#define	BCM2835_MBOX_NUMCHANNELS 16
+#define	BCM2835_MBOX_CHANMASK    0xf
+
+#define	BCM2835_MBOX_CHAN(chan) ((chan) & BCM2835_MBOX_CHANMASK)
+#define	BCM2835_MBOX_DATA(data) ((data) & ~BCM2835_MBOX_CHANMASK)
+
+#define	BCM2835_MBOX_MSG(chan, data) \
+    (BCM2835_MBOX_CHAN(chan) | BCM2835_MBOX_DATA(data))
+
 void bcm2835_mbox_read(bus_space_tag_t, bus_space_handle_t, uint8_t,
     uint32_t *);
 void bcm2835_mbox_write(bus_space_tag_t, bus_space_handle_t, uint8_t,

Index: src/sys/arch/arm/broadcom/bcm2835_mbox_subr.c
diff -u src/sys/arch/arm/broadcom/bcm2835_mbox_subr.c:1.3 src/sys/arch/arm/broadcom/bcm2835_mbox_subr.c:1.4
--- src/sys/arch/arm/broadcom/bcm2835_mbox_subr.c:1.3	Sat Oct 13 08:42:50 2012
+++ src/sys/arch/arm/broadcom/bcm2835_mbox_subr.c	Tue Oct  7 08:30:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_mbox_subr.c,v 1.3 2012/10/13 08:42:50 skrll Exp $	*/
+/*	$NetBSD: bcm2835_mbox_subr.c,v 1.4 2014/10/07 08:30:05 skrll Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_mbox_subr.c,v 1.3 2012/10/13 08:42:50 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_mbox_subr.c,v 1.4 2014/10/07 08:30:05 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -44,12 +44,6 @@ __KERNEL_RCSID(0, "$NetBSD: bcm2835_mbox
 #include <arm/broadcom/bcm2835_mboxreg.h>
 #include <arm/broadcom/bcm2835reg.h>
 
-
-#define	BCM2835_MBOX_CHAN(chan) ((chan) & 0xf)
-#define	BCM2835_MBOX_DATA(data) ((data) & ~0xf)
-
-#define	BCM2835_MBOX_MSG(chan, data) (((chan) & 0xf) | ((data) & ~0xf))
-
 void
 bcm2835_mbox_read(bus_space_tag_t iot, bus_space_handle_t ioh, uint8_t chan,
     uint32_t *data)

Index: src/sys/arch/arm/broadcom/bcm2835_obio.c
diff -u src/sys/arch/arm/broadcom/bcm2835_obio.c:1.21 src/sys/arch/arm/broadcom/bcm2835_obio.c:1.22
--- src/sys/arch/arm/broadcom/bcm2835_obio.c:1.21	Sun Sep  7 14:16:44 2014
+++ src/sys/arch/arm/broadcom/bcm2835_obio.c	Tue Oct  7 08:30:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_obio.c,v 1.21 2014/09/07 14:16:44 jmcneill Exp $	*/
+/*	$NetBSD: bcm2835_obio.c,v 1.22 2014/10/07 08:30:05 skrll Exp $	*/
 
 /*-
  * Copyright (c) 2012, 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_obio.c,v 1.21 2014/09/07 14:16:44 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_obio.c,v 1.22 2014/10/07 08:30:05 skrll Exp $");
 
 #include "locators.h"
 #include "obio.h"
@@ -81,7 +81,7 @@ static const struct ambadev_locators bcm
 		.ad_name = "bcmmbox",
 		.ad_addr = BCM2835_ARMMBOX_BASE,
 		.ad_size = BCM2835_ARMMBOX_SIZE,
-		.ad_intr = -1, /* BCM2835_INT_ARMMAILBOX */
+		.ad_intr = BCM2835_INT_ARMMAILBOX
 	},
 	{
 		/* System Timer */

Reply via email to