X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=drivers%2Fof%2Fgpio.c;h=6eea601a92043b69f3c95c86aa06ae077327c03a;hb=7d8a804c594b61a05c698126165b5dc417d94a0f;hp=1c9cab844f10aaa60cf80d9996b4782d0c1256e6;hpb=8a392625b665c676a77c62f8608d10ff430bcb83;p=linux-2.6-omap-h63xx.git diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 1c9cab844f1..6eea601a920 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c @@ -19,90 +19,54 @@ #include /** - * of_get_gpio - Get a GPIO number from the device tree to use with GPIO API + * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API * @np: device node to get GPIO from * @index: index of the GPIO + * @flags: a flags pointer to fill in * * Returns GPIO number to use with Linux generic GPIO API, or one of the errno - * value on the error condition. + * value on the error condition. If @flags is not NULL the function also fills + * in flags for the GPIO. */ -int of_get_gpio(struct device_node *np, int index) +int of_get_gpio_flags(struct device_node *np, int index, + enum of_gpio_flags *flags) { - int ret = -EINVAL; + int ret; struct device_node *gc; struct of_gpio_chip *of_gc = NULL; int size; - const u32 *gpios; - u32 nr_cells; - int i; const void *gpio_spec; const u32 *gpio_cells; - int gpio_index = 0; - gpios = of_get_property(np, "gpios", &size); - if (!gpios) { - ret = -ENOENT; + ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index, + &gc, &gpio_spec); + if (ret) { + pr_debug("%s: can't parse gpios property\n", __func__); goto err0; } - nr_cells = size / sizeof(u32); - - for (i = 0; i < nr_cells; gpio_index++) { - const phandle *gpio_phandle; - - gpio_phandle = gpios + i; - gpio_spec = gpio_phandle + 1; - - /* one cell hole in the gpios = <>; */ - if (!*gpio_phandle) { - if (gpio_index == index) - return -ENOENT; - i++; - continue; - } - - gc = of_find_node_by_phandle(*gpio_phandle); - if (!gc) { - pr_debug("%s: could not find phandle for gpios\n", - np->full_name); - goto err0; - } - - of_gc = gc->data; - if (!of_gc) { - pr_debug("%s: gpio controller %s isn't registered\n", - np->full_name, gc->full_name); - goto err1; - } - - gpio_cells = of_get_property(gc, "#gpio-cells", &size); - if (!gpio_cells || size != sizeof(*gpio_cells) || - *gpio_cells != of_gc->gpio_cells) { - pr_debug("%s: wrong #gpio-cells for %s\n", - np->full_name, gc->full_name); - goto err1; - } - - /* Next phandle is at phandle cells + #gpio-cells */ - i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells; - if (i >= nr_cells + 1) { - pr_debug("%s: insufficient gpio-spec length\n", - np->full_name); - goto err1; - } - - if (gpio_index == index) - break; - of_gc = NULL; - of_node_put(gc); + of_gc = gc->data; + if (!of_gc) { + pr_debug("%s: gpio controller %s isn't registered\n", + np->full_name, gc->full_name); + ret = -ENODEV; + goto err1; } - if (!of_gc) { - ret = -ENOENT; - goto err0; + gpio_cells = of_get_property(gc, "#gpio-cells", &size); + if (!gpio_cells || size != sizeof(*gpio_cells) || + *gpio_cells != of_gc->gpio_cells) { + pr_debug("%s: wrong #gpio-cells for %s\n", + np->full_name, gc->full_name); + ret = -EINVAL; + goto err1; } - ret = of_gc->xlate(of_gc, np, gpio_spec); + /* .xlate might decide to not fill in the flags, so clear it. */ + if (flags) + *flags = 0; + + ret = of_gc->xlate(of_gc, np, gpio_spec, flags); if (ret < 0) goto err1; @@ -113,26 +77,75 @@ err0: pr_debug("%s exited with status %d\n", __func__, ret); return ret; } -EXPORT_SYMBOL(of_get_gpio); +EXPORT_SYMBOL(of_get_gpio_flags); + +/** + * of_gpio_count - Count GPIOs for a device + * @np: device node to count GPIOs for + * + * The function returns the count of GPIOs specified for a node. + * + * Note that the empty GPIO specifiers counts too. For example, + * + * gpios = <0 + * &pio1 1 2 + * 0 + * &pio2 3 4>; + * + * defines four GPIOs (so this function will return 4), two of which + * are not specified. + */ +unsigned int of_gpio_count(struct device_node *np) +{ + unsigned int cnt = 0; + + do { + int ret; + + ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", + cnt, NULL, NULL); + /* A hole in the gpios = <> counts anyway. */ + if (ret < 0 && ret != -EEXIST) + break; + } while (++cnt); + + return cnt; +} +EXPORT_SYMBOL(of_gpio_count); /** - * of_gpio_simple_xlate - translate gpio_spec to the GPIO number + * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags * @of_gc: pointer to the of_gpio_chip structure * @np: device node of the GPIO chip * @gpio_spec: gpio specifier as found in the device tree + * @flags: a flags pointer to fill in * * This is simple translation function, suitable for the most 1:1 mapped * gpio chips. This function performs only one sanity check: whether gpio * is less than ngpios (that is specified in the gpio_chip). */ int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, - const void *gpio_spec) + const void *gpio_spec, enum of_gpio_flags *flags) { const u32 *gpio = gpio_spec; + /* + * We're discouraging gpio_cells < 2, since that way you'll have to + * write your own xlate function (that will have to retrive the GPIO + * number and the flags from a single gpio cell -- this is possible, + * but not recommended). + */ + if (of_gc->gpio_cells < 2) { + WARN_ON(1); + return -EINVAL; + } + if (*gpio > of_gc->gc.ngpio) return -EINVAL; + if (flags) + *flags = gpio[1]; + return *gpio; } EXPORT_SYMBOL(of_gpio_simple_xlate);