diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index 64fadb382a02..3551c9d228df 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -77,6 +77,8 @@ 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); +#define GPIO_ACTIVE_LOW 1 /* XXX Note that nothing currently sets this flag */ + /* * XXX -> Move me to better place - gpio_subr.c? * Also, this function must be changed when interrupt configuration @@ -135,6 +137,114 @@ gpio_check_flags(uint32_t caps, uint32_t flags) return (0); } +int +gpio_pin_get_by_bus_pinnum(device_t busdev, uint32_t pinnum, gpio_pin_t *ppin) +{ + gpio_pin_t pin; + int err; + + err = gpiobus_acquire_pin(busdev, pinnum); + if (err != 0) + return (EBUSY); + + pin = malloc(sizeof(*pin), M_DEVBUF, M_WAITOK | M_ZERO); + + pin->dev = device_get_parent(busdev); + pin->pin = pinnum; + GPIO_PIN_GETFLAGS(pin->dev, pin->pin, &pin->flags); + + *ppin = pin; + return (0); +} + +int +gpio_pin_get_by_child_index(device_t childdev, uint32_t idx, gpio_pin_t *ppin) +{ + struct gpiobus_ivar *devi; + + devi = GPIOBUS_IVAR(childdev); + if (idx >= devi->npins) + return (EINVAL); + + return (gpio_pin_get_by_bus_pinnum(device_get_parent(childdev), + devi->pins[idx], ppin)); +} + +int +gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps) +{ + + KASSERT(pin != NULL, ("GPIO pin is NULL.")); + KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); + return (GPIO_PIN_GETCAPS(pin->dev, pin->pin, caps)); +} + +int +gpio_pin_is_active(gpio_pin_t pin, bool *active) +{ + int rv; + uint32_t tmp; + + KASSERT(pin != NULL, ("GPIO pin is NULL.")); + KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); + rv = GPIO_PIN_GET(pin->dev, pin->pin, &tmp); + if (rv != 0) { + return (rv); + } + + if (pin->flags & GPIO_ACTIVE_LOW) + *active = tmp == 0; + else + *active = tmp != 0; + return (0); +} + +void +gpio_pin_release(gpio_pin_t gpio) +{ + device_t busdev; + + if (gpio == NULL) + return; + + KASSERT(gpio->dev != NULL, ("GPIO pin device is NULL.")); + + busdev = GPIO_GET_BUS(gpio->dev); + if (busdev != NULL) + gpiobus_release_pin(busdev, gpio->pin); + + free(gpio, M_DEVBUF); +} + +int +gpio_pin_set_active(gpio_pin_t pin, bool active) +{ + int rv; + uint32_t tmp; + + if (pin->flags & GPIO_ACTIVE_LOW) + tmp = active ? 0 : 1; + else + tmp = active ? 1 : 0; + + KASSERT(pin != NULL, ("GPIO pin is NULL.")); + KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); + rv = GPIO_PIN_SET(pin->dev, pin->pin, tmp); + return (rv); +} + +int +gpio_pin_setflags(gpio_pin_t pin, uint32_t flags) +{ + int rv; + + KASSERT(pin != NULL, ("GPIO pin is NULL.")); + KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); + + rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags); + return (rv); +} + static void gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen) { @@ -370,8 +480,6 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask) devi->pins[npins++] = i; } - if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0) - return (EINVAL); return (0); } @@ -425,8 +533,6 @@ gpiobus_parse_pin_list(struct gpiobus_softc *sc, device_t child, p = endp + 1; } - if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0) - return (EINVAL); return (0); } diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h index 08f0ccf904d0..e83ea62bc50d 100644 --- a/sys/dev/gpio/gpiobusvar.h +++ b/sys/dev/gpio/gpiobusvar.h @@ -141,7 +141,7 @@ int ofw_gpiobus_parse_gpios(device_t, char *, struct gpiobus_pin **); void ofw_gpiobus_register_provider(device_t); void ofw_gpiobus_unregister_provider(device_t); -/* Consumers interface. */ +/* Acquire a pin by parsing FDT data. */ int gpio_pin_get_by_ofw_name(device_t consumer, phandle_t node, char *name, gpio_pin_t *gpio); int gpio_pin_get_by_ofw_idx(device_t consumer, phandle_t node, @@ -150,14 +150,29 @@ int gpio_pin_get_by_ofw_property(device_t consumer, phandle_t node, char *name, gpio_pin_t *gpio); int gpio_pin_get_by_ofw_propidx(device_t consumer, phandle_t node, char *name, int idx, gpio_pin_t *gpio); +#endif /* FDT */ + +/* Acquire a pin by bus and pin number. */ +int gpio_pin_get_by_bus_pinnum(device_t _bus, uint32_t _pinnum, gpio_pin_t *_gp); + +/* Acquire a pin by child and index (used by direct children of gpiobus). */ +int gpio_pin_get_by_child_index(device_t _child, uint32_t _idx, gpio_pin_t *_gp); + +/* Release a pin acquired via any gpio_pin_get_xxx() function. */ void gpio_pin_release(gpio_pin_t gpio); + +/* Work with gpio pins acquired using the functions above. */ int gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps); int gpio_pin_is_active(gpio_pin_t pin, bool *active); int gpio_pin_set_active(gpio_pin_t pin, bool active); int gpio_pin_setflags(gpio_pin_t pin, uint32_t flags); -#endif struct resource *gpio_alloc_intr_resource(device_t consumer_dev, int *rid, u_int alloc_flags, gpio_pin_t pin, uint32_t intr_mode); + +/* + * Functions shared between gpiobus and other bus classes that derive from it; + * these should not be called directly by other drivers. + */ int gpio_check_flags(uint32_t, uint32_t); device_t gpiobus_attach_bus(device_t); int gpiobus_detach_bus(device_t); diff --git a/sys/dev/gpio/ofw_gpiobus.c b/sys/dev/gpio/ofw_gpiobus.c index 940e54b6f04e..89d5006e5c34 100644 --- a/sys/dev/gpio/ofw_gpiobus.c +++ b/sys/dev/gpio/ofw_gpiobus.c @@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$"); #include "gpiobus_if.h" -#define GPIO_ACTIVE_LOW 1 - static struct ofw_gpiobus_devinfo *ofw_gpiobus_setup_devinfo(device_t, device_t, phandle_t); static void ofw_gpiobus_destroy_devinfo(device_t, struct ofw_gpiobus_devinfo *); @@ -140,82 +138,6 @@ gpio_pin_get_by_ofw_name(device_t consumer, phandle_t node, return (gpio_pin_get_by_ofw_idx(consumer, node, idx, pin)); } -void -gpio_pin_release(gpio_pin_t gpio) -{ - device_t busdev; - - if (gpio == NULL) - return; - - KASSERT(gpio->dev != NULL, ("invalid pin state")); - - busdev = GPIO_GET_BUS(gpio->dev); - if (busdev != NULL) - gpiobus_release_pin(busdev, gpio->pin); - - /* XXXX Unreserve pin. */ - free(gpio, M_DEVBUF); -} - -int -gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps) -{ - - KASSERT(pin != NULL, ("GPIO pin is NULL.")); - KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); - return (GPIO_PIN_GETCAPS(pin->dev, pin->pin, caps)); -} - -int -gpio_pin_is_active(gpio_pin_t pin, bool *active) -{ - int rv; - uint32_t tmp; - - KASSERT(pin != NULL, ("GPIO pin is NULL.")); - KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); - rv = GPIO_PIN_GET(pin->dev, pin->pin, &tmp); - if (rv != 0) { - return (rv); - } - - if (pin->flags & GPIO_ACTIVE_LOW) - *active = tmp == 0; - else - *active = tmp != 0; - return (0); -} - -int -gpio_pin_set_active(gpio_pin_t pin, bool active) -{ - int rv; - uint32_t tmp; - - if (pin->flags & GPIO_ACTIVE_LOW) - tmp = active ? 0 : 1; - else - tmp = active ? 1 : 0; - - KASSERT(pin != NULL, ("GPIO pin is NULL.")); - KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); - rv = GPIO_PIN_SET(pin->dev, pin->pin, tmp); - return (rv); -} - -int -gpio_pin_setflags(gpio_pin_t pin, uint32_t flags) -{ - int rv; - - KASSERT(pin != NULL, ("GPIO pin is NULL.")); - KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); - - rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags); - return (rv); -} - /* * OFW_GPIOBUS driver. */