diff options
-rw-r--r-- | sys/dev/gpio/files.gpio | 4 | ||||
-rw-r--r-- | sys/dev/gpio/gpio.c | 91 | ||||
-rw-r--r-- | sys/dev/gpio/gpiovar.h | 26 |
3 files changed, 109 insertions, 12 deletions
diff --git a/sys/dev/gpio/files.gpio b/sys/dev/gpio/files.gpio index e462d526ed1..4a19ba656e5 100644 --- a/sys/dev/gpio/files.gpio +++ b/sys/dev/gpio/files.gpio @@ -1,6 +1,6 @@ -# $OpenBSD: files.gpio,v 1.2 2005/03/08 20:00:24 tdeval Exp $ +# $OpenBSD: files.gpio,v 1.3 2006/01/05 11:52:24 grange Exp $ -define gpio {pin, mask} +define gpio {offset, mask} device gpio: gpio attach gpio at gpiobus diff --git a/sys/dev/gpio/gpio.c b/sys/dev/gpio/gpio.c index fc4f6844696..d28c5c9dcee 100644 --- a/sys/dev/gpio/gpio.c +++ b/sys/dev/gpio/gpio.c @@ -1,6 +1,7 @@ -/* $OpenBSD: gpio.c,v 1.4 2004/11/23 21:18:37 grange Exp $ */ +/* $OpenBSD: gpio.c,v 1.5 2006/01/05 11:52:24 grange Exp $ */ + /* - * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> + * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -84,7 +85,7 @@ gpio_attach(struct device *parent, struct device *self, void *aux) * Attach all devices that can be connected to the GPIO pins * described in the kernel configuration file. */ - config_search(gpio_search, self, NULL); + config_search(gpio_search, self, sc); } int @@ -110,7 +111,8 @@ gpio_search(struct device *parent, void *arg, void *aux) struct cfdata *cf = arg; struct gpio_attach_args ga; - ga.ga_pin = cf->cf_loc[0]; + ga.ga_gpio = aux; + ga.ga_offset = cf->cf_loc[0]; ga.ga_mask = cf->cf_loc[1]; if (cf->cf_attach->ca_match(parent, cf, &ga) > 0) @@ -128,7 +130,7 @@ gpio_print(void *aux, const char *pnp) printf(" pins"); for (i = 0; i < 32; i++) if (ga->ga_mask & (1 << i)) - printf(" %d", ga->ga_pin + i); + printf(" %d", ga->ga_offset + i); return (UNCONF); } @@ -145,6 +147,79 @@ gpiobus_print(void *aux, const char *pnp) } int +gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map) +{ + struct gpio_softc *sc = gpio; + int npins, pin, i; + + npins = gpio_npins(mask); + if (npins > sc->sc_npins) + return (1); + + for (npins = 0, i = 0; i < 32; i++) + if (mask & (1 << i)) { + pin = offset + i; + if (pin < 0 || pin >= sc->sc_npins) + return (1); + if (sc->sc_pins[pin].pin_mapped) + return (1); + sc->sc_pins[pin].pin_mapped = 1; + map->pm_map[npins++] = pin; + } + map->pm_size = npins; + + return (0); +} + +void +gpio_pin_unmap(void *gpio, struct gpio_pinmap *map) +{ + struct gpio_softc *sc = gpio; + int pin, i; + + for (i = 0; i < map->pm_size; i++) { + pin = map->pm_map[i]; + sc->sc_pins[pin].pin_mapped = 0; + } +} + +int +gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin) +{ + struct gpio_softc *sc = gpio; + + return (gpiobus_pin_read(sc->sc_gc, map->pm_map[pin])); +} + +void +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)); +} + +void +gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags) +{ + struct gpio_softc *sc = gpio; + + return (gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags)); +} + +int +gpio_npins(u_int32_t mask) +{ + int npins, i; + + for (npins = 0, i = 0; i < 32; i++) + if (mask & (1 << i)) + npins++; + + return (npins); +} + +int gpioopen(dev_t dev, int flag, int mode, struct proc *p) { struct gpio_softc *sc; @@ -206,6 +281,8 @@ gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) pin = op->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); + if (sc->sc_pins[pin].pin_mapped) + return (EBUSY); value = op->gp_value; if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH) @@ -223,6 +300,8 @@ gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) pin = op->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); + if (sc->sc_pins[pin].pin_mapped) + return (EBUSY); value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ? GPIO_PIN_HIGH : GPIO_PIN_LOW); @@ -238,6 +317,8 @@ gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) pin = ctl->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); + if (sc->sc_pins[pin].pin_mapped) + return (EBUSY); flags = ctl->gp_flags; /* check that the controller supports all requested flags */ diff --git a/sys/dev/gpio/gpiovar.h b/sys/dev/gpio/gpiovar.h index 505f557bc65..7c700088ac5 100644 --- a/sys/dev/gpio/gpiovar.h +++ b/sys/dev/gpio/gpiovar.h @@ -1,6 +1,7 @@ -/* $OpenBSD: gpiovar.h,v 1.1 2004/06/03 18:08:00 grange Exp $ */ +/* $OpenBSD: gpiovar.h,v 1.2 2006/01/05 11:52:24 grange Exp $ */ + /* - * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> + * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -33,6 +34,7 @@ typedef struct gpio_pin { int pin_caps; /* capabilities */ int pin_flags; /* current configuration */ int pin_state; /* current state */ + int pin_mapped; /* is mapped */ } gpio_pin_t; /* Attach GPIO framework to the controller */ @@ -53,11 +55,25 @@ int gpiobus_print(void *, const char *); #define gpiobus_pin_ctl(gc, pin, flags) \ ((gc)->gp_pin_ctl((gc)->gp_cookie, (pin), (flags))) - /* Attach devices connected to the GPIO pins */ struct gpio_attach_args { - int ga_pin; - u_int32_t ga_mask; + void * ga_gpio; + int ga_offset; + u_int32_t ga_mask; +}; + +/* GPIO pin map */ +struct gpio_pinmap { + int * pm_map; /* pin map */ + int pm_size; /* map size */ }; +int gpio_pin_map(void *, int, u_int32_t, struct gpio_pinmap *); +void gpio_pin_unmap(void *, struct gpio_pinmap *); +int gpio_pin_read(void *, struct gpio_pinmap *, int); +void gpio_pin_write(void *, struct gpio_pinmap *, int, int); +void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int); + +int gpio_npins(u_int32_t); + #endif /* !_DEV_GPIO_GPIOVAR_H_ */ |