From 178248c4177c6ec1c14f8ad13b927167262825c0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 20 Nov 2012 12:40:15 +0100 Subject: [PATCH] --- yaml --- r: 336427 b: refs/heads/master c: 3f0f8670608766ef26a178d4e80cad3ce030fecc h: refs/heads/master i: 336425: ad39e86d89f0517a201f57dd593e0a7836fd0210 336423: e2ac5020ca2757f70d862c1108aaf8a48abf2373 v: v3 --- [refs] | 2 +- trunk/drivers/gpio/gpiolib-of.c | 12 ++++++++++++ trunk/drivers/gpio/gpiolib.c | 32 +++++++++++++++++++++++++++++--- trunk/include/asm-generic/gpio.h | 6 ++++-- trunk/include/linux/gpio.h | 3 ++- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index cd1b7f3ca491..e52910094df2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5212d096cbed2eae1e442b3f8bf448e6a577af6f +refs/heads/master: 3f0f8670608766ef26a178d4e80cad3ce030fecc diff --git a/trunk/drivers/gpio/gpiolib-of.c b/trunk/drivers/gpio/gpiolib-of.c index a40cd84c5c10..d542a141811a 100644 --- a/trunk/drivers/gpio/gpiolib-of.c +++ b/trunk/drivers/gpio/gpiolib-of.c @@ -238,8 +238,20 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) if (!pctldev) break; + /* + * This assumes that the n GPIO pins are consecutive in the + * GPIO number space, and that the pins are also consecutive + * in their local number space. Currently it is not possible + * to add different ranges for one and the same GPIO chip, + * as the code assumes that we have one consecutive range + * on both, mapping 1-to-1. + * + * TODO: make the OF bindings handle multiple sparse ranges + * on the same GPIO chip. + */ ret = gpiochip_add_pin_range(chip, pinctrl_dev_get_name(pctldev), + 0, /* offset in gpiochip */ pinspec.args[0], pinspec.args[1]); diff --git a/trunk/drivers/gpio/gpiolib.c b/trunk/drivers/gpio/gpiolib.c index c5f650095faa..6d13bea4778a 100644 --- a/trunk/drivers/gpio/gpiolib.c +++ b/trunk/drivers/gpio/gpiolib.c @@ -1187,24 +1187,45 @@ EXPORT_SYMBOL_GPL(gpiochip_find); #ifdef CONFIG_PINCTRL +/** + * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping + * @chip: the gpiochip to add the range for + * @pinctrl_name: the dev_name() of the pin controller to map to + * @offset: the start offset in the current gpio_chip number space + * @pin_base: the start offset in the pin controller number space + * @npins: the number of pins from the offset of each pin space (GPIO and + * pin controller) to accumulate in this range + */ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, - unsigned int pin_base, unsigned int npins) + unsigned int offset, unsigned int pin_base, + unsigned int npins) { struct gpio_pin_range *pin_range; - pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), GFP_KERNEL); + pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { pr_err("%s: GPIO chip: failed to allocate pin ranges\n", chip->label); return -ENOMEM; } + /* Use local offset as range ID */ + pin_range->range.id = offset; + pin_range->range.gc = chip; pin_range->range.name = chip->label; - pin_range->range.base = chip->base; + pin_range->range.base = chip->base + offset; pin_range->range.pin_base = pin_base; pin_range->range.npins = npins; pin_range->pctldev = find_pinctrl_and_add_gpio_range(pinctl_name, &pin_range->range); + if (!pin_range->pctldev) { + pr_err("%s: GPIO chip: could not create pin range\n", + chip->label); + kfree(pin_range); + } + pr_debug("%s: GPIO chip: created GPIO range %d->%d ==> PIN %d->%d\n", + chip->label, offset, offset + npins - 1, + pin_base, pin_base + npins - 1); list_add_tail(&pin_range->node, &chip->pin_ranges); @@ -1212,6 +1233,10 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, } EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); +/** + * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings + * @chip: the chip to remove all the mappings for + */ void gpiochip_remove_pin_ranges(struct gpio_chip *chip) { struct gpio_pin_range *pin_range, *tmp; @@ -1220,6 +1245,7 @@ void gpiochip_remove_pin_ranges(struct gpio_chip *chip) list_del(&pin_range->node); pinctrl_remove_gpio_range(pin_range->pctldev, &pin_range->range); + kfree(pin_range); } } EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); diff --git a/trunk/include/asm-generic/gpio.h b/trunk/include/asm-generic/gpio.h index 2b84fc32fae2..ec58fdbddb59 100644 --- a/trunk/include/asm-generic/gpio.h +++ b/trunk/include/asm-generic/gpio.h @@ -283,14 +283,16 @@ struct gpio_pin_range { }; int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, - unsigned int pin_base, unsigned int npins); + unsigned int offset, unsigned int pin_base, + unsigned int npins); void gpiochip_remove_pin_ranges(struct gpio_chip *chip); #else static inline int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, - unsigned int pin_base, unsigned int npins) + unsigned int offset, unsigned int pin_base, + unsigned int npins) { return 0; } diff --git a/trunk/include/linux/gpio.h b/trunk/include/linux/gpio.h index 7ba2762abbc9..99861c65dd8b 100644 --- a/trunk/include/linux/gpio.h +++ b/trunk/include/linux/gpio.h @@ -233,7 +233,8 @@ static inline int irq_to_gpio(unsigned irq) static inline int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, - unsigned int pin_base, unsigned int npins) + unsigned int offset, unsigned int pin_base, + unsigned int npins) { WARN_ON(1); return -EINVAL;