diff options
Diffstat (limited to 'sys/dev/gpio')
-rw-r--r-- | sys/dev/gpio/gpio_if.m | 8 | ||||
-rw-r--r-- | sys/dev/gpio/gpiobus.c | 25 | ||||
-rw-r--r-- | sys/dev/gpio/gpiobusvar.h | 1 | ||||
-rw-r--r-- | sys/dev/gpio/gpioc.c | 18 |
4 files changed, 38 insertions, 14 deletions
diff --git a/sys/dev/gpio/gpio_if.m b/sys/dev/gpio/gpio_if.m index 4d6dfd1..adc119e 100644 --- a/sys/dev/gpio/gpio_if.m +++ b/sys/dev/gpio/gpio_if.m @@ -32,9 +32,7 @@ INTERFACE gpio; CODE { - static gpio_map_gpios_t gpio_default_map_gpios; - - int + static int gpio_default_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags) @@ -58,11 +56,11 @@ HEADER { }; # -# Get total number of pins +# Get maximum pin number # METHOD int pin_max { device_t dev; - int *npins; + int *maxpin; }; # diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index dcf6049..efff2c0 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> +#include <sys/gpio.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> @@ -70,6 +71,23 @@ static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int); static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*); static int gpiobus_pin_toggle(device_t, device_t, uint32_t); +int +gpio_check_flags(uint32_t caps, uint32_t flags) +{ + + /* Check for unwanted flags. */ + if ((flags & caps) == 0 || (flags & caps) != flags) + return (EINVAL); + /* Cannot mix input/output together. */ + if (flags & GPIO_PIN_INPUT && flags & GPIO_PIN_OUTPUT) + return (EINVAL); + /* Cannot mix pull-up/pull-down together. */ + if (flags & GPIO_PIN_PULLUP && flags & GPIO_PIN_PULLDOWN) + return (EINVAL); + + return (0); +} + static void gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen) { @@ -490,11 +508,16 @@ gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, { struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); + uint32_t caps; if (pin >= devi->npins) return (EINVAL); + if (GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], &caps) != 0) + return (EINVAL); + if (gpio_check_flags(caps, flags) != 0) + return (EINVAL); - return GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags); + return (GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags)); } static int diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h index 3ec8a17..a1c2be0 100644 --- a/sys/dev/gpio/gpiobusvar.h +++ b/sys/dev/gpio/gpiobusvar.h @@ -94,6 +94,7 @@ gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, device_t ofw_gpiobus_add_fdt_child(device_t, phandle_t); #endif +int gpio_check_flags(uint32_t, uint32_t); int gpiobus_init_softc(device_t); extern driver_t gpiobus_driver; diff --git a/sys/dev/gpio/gpioc.c b/sys/dev/gpio/gpioc.c index 156f05c..2fad4df 100644 --- a/sys/dev/gpio/gpioc.c +++ b/sys/dev/gpio/gpioc.c @@ -29,19 +29,16 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> -#include <sys/types.h> - #include <sys/bus.h> #include <sys/conf.h> +#include <sys/gpio.h> #include <sys/ioccom.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> -#include <sys/queue.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/gpio.h> +#include <dev/gpio/gpiobusvar.h> + #include "gpio_if.h" #undef GPIOC_DEBUG @@ -119,6 +116,7 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, struct gpioc_softc *sc = cdev->si_drv1; struct gpio_pin pin; struct gpio_req req; + uint32_t caps; switch (cmd) { case GPIOMAXPIN: @@ -141,8 +139,12 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, case GPIOSETCONFIG: bcopy(arg, &pin, sizeof(pin)); dprintf("set config pin %d\n", pin.gp_pin); - res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin, - pin.gp_flags); + res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &caps); + if (res == 0) + res = gpio_check_flags(caps, pin.gp_flags); + if (res == 0) + res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin, + pin.gp_flags); break; case GPIOGET: bcopy(arg, &req, sizeof(req)); |