svn commit: r279153 - head/sys/arm/broadcom/bcm2835
Andrew Turner
andrew at FreeBSD.org
Sun Feb 22 11:11:06 UTC 2015
Author: andrew
Date: Sun Feb 22 11:11:05 2015
New Revision: 279153
URL: https://svnweb.freebsd.org/changeset/base/279153
Log:
Add support to the bcm2835 mailbox driver to work before interrupts are
enabled. This will be needed to enable the power on devices early on in the
boot process.
Modified:
head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
Modified: head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c Sun Feb 22 08:54:25 2015 (r279152)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c Sun Feb 22 11:11:05 2015 (r279153)
@@ -89,27 +89,39 @@ struct bcm_mbox_softc {
#define mbox_write_4(sc, reg, val) \
bus_space_write_4((sc)->bst, (sc)->bsh, reg, val)
+static int
+bcm_mbox_read_msg(struct bcm_mbox_softc *sc, int *ochan)
+{
+ uint32_t data;
+ uint32_t msg;
+ int chan;
+
+ msg = mbox_read_4(sc, REG_READ);
+ dprintf("bcm_mbox_intr: raw data %08x\n", msg);
+ chan = MBOX_CHAN(msg);
+ data = MBOX_DATA(msg);
+ if (sc->msg[chan]) {
+ printf("bcm_mbox_intr: channel %d oveflow\n", chan);
+ return (1);
+ }
+ dprintf("bcm_mbox_intr: chan %d, data %08x\n", chan, data);
+ sc->msg[chan] = msg;
+
+ if (ochan != NULL)
+ *ochan = chan;
+
+ return (0);
+}
+
static void
bcm_mbox_intr(void *arg)
{
struct bcm_mbox_softc *sc = arg;
int chan;
- uint32_t data;
- uint32_t msg;
- while (!(mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY)) {
- msg = mbox_read_4(sc, REG_READ);
- dprintf("bcm_mbox_intr: raw data %08x\n", msg);
- chan = MBOX_CHAN(msg);
- data = MBOX_DATA(msg);
- if (sc->msg[chan]) {
- printf("bcm_mbox_intr: channel %d oveflow\n", chan);
- continue;
- }
- dprintf("bcm_mbox_intr: chan %d, data %08x\n", chan, data);
- sc->msg[chan] = msg;
- sema_post(&sc->sema[chan]);
- }
+ while (!(mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY))
+ if (bcm_mbox_read_msg(sc, &chan) == 0)
+ sema_post(&sc->sema[chan]);
}
static int
@@ -201,14 +213,30 @@ static int
bcm_mbox_read(device_t dev, int chan, uint32_t *data)
{
struct bcm_mbox_softc *sc = device_get_softc(dev);
+ int err, read_chan;
dprintf("bcm_mbox_read: chan %d\n", chan);
+
+ err = 0;
MBOX_LOCK(sc);
- while (sema_trywait(&sc->sema[chan]) == 0) {
- /* do not unlock sc while waiting for the mbox */
- if (sema_timedwait(&sc->sema[chan], 10*hz) == 0)
- break;
- printf("timeout sema for chan %d\n", chan);
+ if (!cold) {
+ while (sema_trywait(&sc->sema[chan]) == 0) {
+ /* do not unlock sc while waiting for the mbox */
+ if (sema_timedwait(&sc->sema[chan], 10*hz) == 0)
+ break;
+ printf("timeout sema for chan %d\n", chan);
+ }
+ } else {
+ do {
+ /* Wait for a message */
+ while ((mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY))
+ ;
+ /* Read the message */
+ if (bcm_mbox_read_msg(sc, &read_chan) != 0) {
+ err = EINVAL;
+ goto out;
+ }
+ } while (read_chan != chan);
}
/*
* get data from intr handler, the same channel is never coming
@@ -216,10 +244,11 @@ bcm_mbox_read(device_t dev, int chan, ui
*/
*data = MBOX_DATA(sc->msg[chan]);
sc->msg[chan] = 0;
+out:
MBOX_UNLOCK(sc);
dprintf("bcm_mbox_read: chan %d, data %08x\n", chan, *data);
- return (0);
+ return (err);
}
static device_method_t bcm_mbox_methods[] = {
More information about the svn-src-all
mailing list