From 97d3260c03342c16e17d20d5ec4f5aeb4e1e1be9 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Sun, 13 Aug 2017 18:27:11 +0000 Subject: [PATCH] Add fdtbus_gpio_acquire_index for accessing multi-xref gpios properties. --- sys/dev/fdt/fdt_gpio.c | 68 +++++++++++++++++++++++------------------- sys/dev/fdt/fdtvar.h | 3 +- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/sys/dev/fdt/fdt_gpio.c b/sys/dev/fdt/fdt_gpio.c index 919931eae209..7b636ca6881e 100644 --- a/sys/dev/fdt/fdt_gpio.c +++ b/sys/dev/fdt/fdt_gpio.c @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_gpio.c,v 1.4 2016/10/15 08:30:42 maxv Exp $ */ +/* $NetBSD: fdt_gpio.c,v 1.5 2017/08/13 18:27:11 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: fdt_gpio.c,v 1.4 2016/10/15 08:30:42 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_gpio.c,v 1.5 2017/08/13 18:27:11 jmcneill Exp $"); #include #include @@ -79,40 +79,46 @@ fdtbus_get_gpio_controller(int phandle) struct fdtbus_gpio_pin * fdtbus_gpio_acquire(int phandle, const char *prop, int flags) +{ + return fdtbus_gpio_acquire_index(phandle, prop, 0, flags); +} + +struct fdtbus_gpio_pin * +fdtbus_gpio_acquire_index(int phandle, const char *prop, + int index, int flags) { struct fdtbus_gpio_controller *gc; - struct fdtbus_gpio_pin *gp; - int gpio_phandle, len; - u_int *data; + struct fdtbus_gpio_pin *gp = NULL; + const uint32_t *gpios, *p; + u_int n, gpio_cells; + int len, resid; - gpio_phandle = fdtbus_get_phandle(phandle, prop); - if (gpio_phandle == -1) { + gpios = fdtbus_get_prop(phandle, prop, &len); + if (gpios == NULL) return NULL; - } - gc = fdtbus_get_gpio_controller(gpio_phandle); - if (gc == NULL) { - return NULL; - } - - len = OF_getproplen(phandle, prop); - if (len < 4) { - return NULL; - } - - data = kmem_alloc(len, KM_SLEEP); - if (OF_getprop(phandle, prop, data, len) != len) { - kmem_free(data, len); - return NULL; - } - - gp = kmem_alloc(sizeof(*gp), KM_SLEEP); - gp->gp_gc = gc; - gp->gp_priv = gc->gc_funcs->acquire(gc->gc_dev, data, len, flags); - if (gp->gp_priv == NULL) { - kmem_free(data, len); - kmem_free(gp, sizeof(*gp)); - return NULL; + p = gpios; + for (n = 0, resid = len; resid > 0; n++) { + const int gc_phandle = + fdtbus_get_phandle_from_native(be32toh(p[0])); + if (of_getprop_uint32(gc_phandle, "#gpio-cells", &gpio_cells)) + break; + if (n == index) { + gc = fdtbus_get_gpio_controller(gc_phandle); + if (gc == NULL) + return NULL; + gp = kmem_alloc(sizeof(*gp), KM_SLEEP); + gp->gp_gc = gc; + gp->gp_priv = gc->gc_funcs->acquire(gc->gc_dev, + &p[0], (gpio_cells + 1) * 4, flags); + if (gp->gp_priv == NULL) { + kmem_free(gp, sizeof(*gp)); + return NULL; + } + break; + } + resid -= (gpio_cells + 1) * 4; + p += gpio_cells + 1; } return gp; diff --git a/sys/dev/fdt/fdtvar.h b/sys/dev/fdt/fdtvar.h index 2d22eab680cb..6db5b11cef14 100644 --- a/sys/dev/fdt/fdtvar.h +++ b/sys/dev/fdt/fdtvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fdtvar.h,v 1.24 2017/07/08 12:36:51 jmcneill Exp $ */ +/* $NetBSD: fdtvar.h,v 1.25 2017/08/13 18:27:11 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -236,6 +236,7 @@ void * fdtbus_intr_establish(int, u_int, int, int, void fdtbus_intr_disestablish(int, void *); bool fdtbus_intr_str(int, u_int, char *, size_t); struct fdtbus_gpio_pin *fdtbus_gpio_acquire(int, const char *, int); +struct fdtbus_gpio_pin *fdtbus_gpio_acquire_index(int, const char *, int, int); void fdtbus_gpio_release(struct fdtbus_gpio_pin *); int fdtbus_gpio_read(struct fdtbus_gpio_pin *); void fdtbus_gpio_write(struct fdtbus_gpio_pin *, int);