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 */