diff options
| author | dyoung <dyoung@NetBSD.org> | 2007-12-14 01:49:23 +0000 |
|---|---|---|
| committer | dyoung <dyoung@NetBSD.org> | 2007-12-14 01:49:23 +0000 |
| commit | 417afa7caaf0629bc3e817aef9fcd6be21b3289b (patch) | |
| tree | 75a3f9f631e227346d12602c2c6fba50a828cc40 /sys/dev/gpio | |
| parent | e692a6c76aa4426238cded9ce5682f8289bfb560 (diff) | |
Bug fix: record the new state (high/low) set by gpio_pin_write().
I don't know why we gpio(4) didn't do that before, but it seems
harmless.
Add naive power handling: when a gpio(4) instance is resumed, write
each pin's configuration flags and output state from the softc to
the hardware using gpiobus_pin_ctl() and gpiobus_pin_write().
While suspended, fail every ioctl() except for GPIOINFO with EBUSY.
Diffstat (limited to 'sys/dev/gpio')
| -rw-r--r-- | sys/dev/gpio/gpio.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/sys/dev/gpio/gpio.c b/sys/dev/gpio/gpio.c index d82e49ea5f2..75ce2a7202d 100644 --- a/sys/dev/gpio/gpio.c +++ b/sys/dev/gpio/gpio.c @@ -1,4 +1,4 @@ -/* $NetBSD: gpio.c,v 1.12 2007/03/04 06:01:46 christos Exp $ */ +/* $NetBSD: gpio.c,v 1.13 2007/12/14 01:49:23 dyoung Exp $ */ /* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */ /* @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.12 2007/03/04 06:01:46 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.13 2007/12/14 01:49:23 dyoung Exp $"); /* * General Purpose Input/Output framework. @@ -49,6 +49,7 @@ struct gpio_softc { int gpio_match(struct device *, struct cfdata *, void *); void gpio_attach(struct device *, struct device *, void *); +bool gpio_resume(device_t); int gpio_detach(struct device *, int); int gpio_activate(struct device *, enum devact); int gpio_search(struct device *, struct cfdata *, const int *, void *); @@ -76,6 +77,19 @@ gpio_match(struct device *parent, struct cfdata *cf, return (1); } +bool +gpio_resume(device_t self) +{ + struct gpio_softc *sc = device_private(self); + int pin; + + for (pin = 0; pin < sc->sc_npins; pin++) { + gpiobus_pin_ctl(sc->sc_gc, pin, sc->sc_pins[pin].pin_flags); + gpiobus_pin_write(sc->sc_gc, pin, sc->sc_pins[pin].pin_state); + } + return true; +} + void gpio_attach(struct device *parent, struct device *self, void *aux) { @@ -88,6 +102,9 @@ gpio_attach(struct device *parent, struct device *self, void *aux) printf(": %d pins\n", sc->sc_npins); + if (!pmf_device_register(self, NULL, gpio_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + /* * Attach all devices that can be connected to the GPIO pins * described in the kernel configuration file. @@ -222,7 +239,8 @@ gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value) { struct gpio_softc *sc = gpio; - return (gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value)); + gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value); + sc->sc_pins[map->pm_map[pin]].pin_state = value; } void @@ -296,6 +314,9 @@ gpioioctl(dev_t dev, u_long cmd, void *data, int flag, sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev)); gc = sc->sc_gc; + if (cmd != GPIOINFO && !device_is_active(&sc->sc_dev)) + return EBUSY; + switch (cmd) { case GPIOINFO: info = (struct gpio_info *)data; |
