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.
This commit is contained in:
dyoung 2007-12-14 01:49:23 +00:00
parent e692a6c76a
commit 417afa7caa
1 changed files with 24 additions and 3 deletions

View File

@ -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;