summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/gpio/gpiobus.c50
-rw-r--r--sys/dev/gpio/gpiobus_if.m17
-rw-r--r--sys/dev/gpio/gpiobusvar.h3
-rw-r--r--sys/dev/gpio/gpioiic.c12
-rw-r--r--sys/dev/gpio/gpioled.c23
5 files changed, 44 insertions, 61 deletions
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index 2a81a1258f9a..68adab05d5df 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -53,9 +53,7 @@ static void gpiobus_hinted_child(device_t, const char *, int);
/*
* GPIOBUS interface
*/
-static void gpiobus_lock_bus(device_t);
-static void gpiobus_unlock_bus(device_t);
-static void gpiobus_acquire_bus(device_t, device_t);
+static int gpiobus_acquire_bus(device_t, device_t, int);
static void gpiobus_release_bus(device_t, device_t);
static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t);
static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*);
@@ -326,37 +324,26 @@ gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
device_delete_child(bus, child);
}
-static void
-gpiobus_lock_bus(device_t busdev)
+static int
+gpiobus_acquire_bus(device_t busdev, device_t child, int how)
{
struct gpiobus_softc *sc;
sc = device_get_softc(busdev);
GPIOBUS_ASSERT_UNLOCKED(sc);
GPIOBUS_LOCK(sc);
-}
-
-static void
-gpiobus_unlock_bus(device_t busdev)
-{
- struct gpiobus_softc *sc;
-
- sc = device_get_softc(busdev);
- GPIOBUS_ASSERT_LOCKED(sc);
+ if (sc->sc_owner != NULL) {
+ if (how == GPIOBUS_DONTWAIT) {
+ GPIOBUS_UNLOCK(sc);
+ return (EWOULDBLOCK);
+ }
+ while (sc->sc_owner != NULL)
+ mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0);
+ }
+ sc->sc_owner = child;
GPIOBUS_UNLOCK(sc);
-}
-static void
-gpiobus_acquire_bus(device_t busdev, device_t child)
-{
- struct gpiobus_softc *sc;
-
- sc = device_get_softc(busdev);
- GPIOBUS_ASSERT_LOCKED(sc);
-
- if (sc->sc_owner)
- panic("gpiobus: cannot serialize the access to device.");
- sc->sc_owner = child;
+ return (0);
}
static void
@@ -365,14 +352,15 @@ gpiobus_release_bus(device_t busdev, device_t child)
struct gpiobus_softc *sc;
sc = device_get_softc(busdev);
- GPIOBUS_ASSERT_LOCKED(sc);
-
- if (!sc->sc_owner)
+ GPIOBUS_ASSERT_UNLOCKED(sc);
+ GPIOBUS_LOCK(sc);
+ if (sc->sc_owner == NULL)
panic("gpiobus: releasing unowned bus.");
if (sc->sc_owner != child)
panic("gpiobus: you don't own the bus. game over.");
-
sc->sc_owner = NULL;
+ wakeup(sc);
+ GPIOBUS_UNLOCK(sc);
}
static int
@@ -469,8 +457,6 @@ static device_method_t gpiobus_methods[] = {
DEVMETHOD(bus_hinted_child, gpiobus_hinted_child),
/* GPIO protocol */
- DEVMETHOD(gpiobus_lock_bus, gpiobus_lock_bus),
- DEVMETHOD(gpiobus_unlock_bus, gpiobus_unlock_bus),
DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus),
DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus),
DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags),
diff --git a/sys/dev/gpio/gpiobus_if.m b/sys/dev/gpio/gpiobus_if.m
index 6bf1ad839b66..242502005428 100644
--- a/sys/dev/gpio/gpiobus_if.m
+++ b/sys/dev/gpio/gpiobus_if.m
@@ -32,25 +32,12 @@
INTERFACE gpiobus;
#
-# Lock the gpio bus
-#
-METHOD void lock_bus {
- device_t busdev;
-};
-
-#
-# Unlock the gpio bus
-#
-METHOD void unlock_bus {
- device_t busdev;
-};
-
-#
# Dedicate the gpio bus control for a child
#
-METHOD void acquire_bus {
+METHOD int acquire_bus {
device_t busdev;
device_t dev;
+ int how;
};
#
diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h
index 7396ddcd4ebd..47c0b6b725ae 100644
--- a/sys/dev/gpio/gpiobusvar.h
+++ b/sys/dev/gpio/gpiobusvar.h
@@ -56,6 +56,9 @@
#define GPIOBUS_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
#define GPIOBUS_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
+#define GPIOBUS_WAIT 1
+#define GPIOBUS_DONTWAIT 2
+
struct gpiobus_softc
{
struct mtx sc_mtx; /* bus mutex */
diff --git a/sys/dev/gpio/gpioiic.c b/sys/dev/gpio/gpioiic.c
index 2698e5013b6f..15f8f180c312 100644
--- a/sys/dev/gpio/gpioiic.c
+++ b/sys/dev/gpio/gpioiic.c
@@ -154,18 +154,18 @@ static int
gpioiic_callback(device_t dev, int index, caddr_t data)
{
struct gpioiic_softc *sc = device_get_softc(dev);
- int error = 0;
+ int error, how;
+ how = GPIOBUS_DONTWAIT;
+ if (data != NULL && (int)*data == IIC_WAIT)
+ how = GPIOBUS_WAIT;
+ error = 0;
switch (index) {
case IIC_REQUEST_BUS:
- GPIOBUS_LOCK_BUS(sc->sc_busdev);
- GPIOBUS_ACQUIRE_BUS(sc->sc_busdev, sc->sc_dev);
- GPIOBUS_UNLOCK_BUS(sc->sc_busdev);
+ error = GPIOBUS_ACQUIRE_BUS(sc->sc_busdev, sc->sc_dev, how);
break;
case IIC_RELEASE_BUS:
- GPIOBUS_LOCK_BUS(sc->sc_busdev);
GPIOBUS_RELEASE_BUS(sc->sc_busdev, sc->sc_dev);
- GPIOBUS_UNLOCK_BUS(sc->sc_busdev);
break;
default:
error = EINVAL;
diff --git a/sys/dev/gpio/gpioled.c b/sys/dev/gpio/gpioled.c
index 1377a14ef93b..a9152773c3fd 100644
--- a/sys/dev/gpio/gpioled.c
+++ b/sys/dev/gpio/gpioled.c
@@ -79,16 +79,23 @@ static int gpioled_detach(device_t);
static void
gpioled_control(void *priv, int onoff)
{
- struct gpioled_softc *sc = priv;
+ int error;
+ struct gpioled_softc *sc;
+
+ sc = (struct gpioled_softc *)priv;
GPIOLED_LOCK(sc);
- GPIOBUS_LOCK_BUS(sc->sc_busdev);
- GPIOBUS_ACQUIRE_BUS(sc->sc_busdev, sc->sc_dev);
- GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, GPIOLED_PIN,
- GPIO_PIN_OUTPUT);
- GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, GPIOLED_PIN,
- onoff ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
+ error = GPIOBUS_ACQUIRE_BUS(sc->sc_busdev, sc->sc_dev,
+ GPIOBUS_DONTWAIT);
+ if (error != 0) {
+ GPIOLED_UNLOCK(sc);
+ return;
+ }
+ error = GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev,
+ GPIOLED_PIN, GPIO_PIN_OUTPUT);
+ if (error == 0)
+ GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, GPIOLED_PIN,
+ onoff ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
GPIOBUS_RELEASE_BUS(sc->sc_busdev, sc->sc_dev);
- GPIOBUS_UNLOCK_BUS(sc->sc_busdev);
GPIOLED_UNLOCK(sc);
}