diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2012-11-20 06:40:15 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-11-21 02:55:03 -0500 |
commit | 3f0f8670608766ef26a178d4e80cad3ce030fecc (patch) | |
tree | d2f192a4a454bd677983c7eb0b88a0016f128bf6 /drivers/gpio/gpiolib.c | |
parent | 5212d096cbed2eae1e442b3f8bf448e6a577af6f (diff) |
gpiolib: let gpiochip_add_pin_range() specify offset
Like with commit 3c739ad0df5eb41cd7adad879eda6aa09879eb76
it is not always enough to specify all the pins of a gpio_chip
from offset zero to be added to a pin map range, since the
mapping from GPIO to pin controller may not be linear at all,
but need to be broken into a few consecutive sub-ranges or
1-pin entries for complicated cases. The ranges may also be
sparse.
This alters the signature of the function to accept offsets
into both the GPIO-chip local pinspace and the pin controller
local pinspace.
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c5f650095faa..6d13bea4778a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -1187,24 +1187,45 @@ EXPORT_SYMBOL_GPL(gpiochip_find); | |||
1187 | 1187 | ||
1188 | #ifdef CONFIG_PINCTRL | 1188 | #ifdef CONFIG_PINCTRL |
1189 | 1189 | ||
1190 | /** | ||
1191 | * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping | ||
1192 | * @chip: the gpiochip to add the range for | ||
1193 | * @pinctrl_name: the dev_name() of the pin controller to map to | ||
1194 | * @offset: the start offset in the current gpio_chip number space | ||
1195 | * @pin_base: the start offset in the pin controller number space | ||
1196 | * @npins: the number of pins from the offset of each pin space (GPIO and | ||
1197 | * pin controller) to accumulate in this range | ||
1198 | */ | ||
1190 | int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | 1199 | int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, |
1191 | unsigned int pin_base, unsigned int npins) | 1200 | unsigned int offset, unsigned int pin_base, |
1201 | unsigned int npins) | ||
1192 | { | 1202 | { |
1193 | struct gpio_pin_range *pin_range; | 1203 | struct gpio_pin_range *pin_range; |
1194 | 1204 | ||
1195 | pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), GFP_KERNEL); | 1205 | pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); |
1196 | if (!pin_range) { | 1206 | if (!pin_range) { |
1197 | pr_err("%s: GPIO chip: failed to allocate pin ranges\n", | 1207 | pr_err("%s: GPIO chip: failed to allocate pin ranges\n", |
1198 | chip->label); | 1208 | chip->label); |
1199 | return -ENOMEM; | 1209 | return -ENOMEM; |
1200 | } | 1210 | } |
1201 | 1211 | ||
1212 | /* Use local offset as range ID */ | ||
1213 | pin_range->range.id = offset; | ||
1214 | pin_range->range.gc = chip; | ||
1202 | pin_range->range.name = chip->label; | 1215 | pin_range->range.name = chip->label; |
1203 | pin_range->range.base = chip->base; | 1216 | pin_range->range.base = chip->base + offset; |
1204 | pin_range->range.pin_base = pin_base; | 1217 | pin_range->range.pin_base = pin_base; |
1205 | pin_range->range.npins = npins; | 1218 | pin_range->range.npins = npins; |
1206 | pin_range->pctldev = find_pinctrl_and_add_gpio_range(pinctl_name, | 1219 | pin_range->pctldev = find_pinctrl_and_add_gpio_range(pinctl_name, |
1207 | &pin_range->range); | 1220 | &pin_range->range); |
1221 | if (!pin_range->pctldev) { | ||
1222 | pr_err("%s: GPIO chip: could not create pin range\n", | ||
1223 | chip->label); | ||
1224 | kfree(pin_range); | ||
1225 | } | ||
1226 | pr_debug("%s: GPIO chip: created GPIO range %d->%d ==> PIN %d->%d\n", | ||
1227 | chip->label, offset, offset + npins - 1, | ||
1228 | pin_base, pin_base + npins - 1); | ||
1208 | 1229 | ||
1209 | list_add_tail(&pin_range->node, &chip->pin_ranges); | 1230 | list_add_tail(&pin_range->node, &chip->pin_ranges); |
1210 | 1231 | ||
@@ -1212,6 +1233,10 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | |||
1212 | } | 1233 | } |
1213 | EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); | 1234 | EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); |
1214 | 1235 | ||
1236 | /** | ||
1237 | * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings | ||
1238 | * @chip: the chip to remove all the mappings for | ||
1239 | */ | ||
1215 | void gpiochip_remove_pin_ranges(struct gpio_chip *chip) | 1240 | void gpiochip_remove_pin_ranges(struct gpio_chip *chip) |
1216 | { | 1241 | { |
1217 | struct gpio_pin_range *pin_range, *tmp; | 1242 | struct gpio_pin_range *pin_range, *tmp; |
@@ -1220,6 +1245,7 @@ void gpiochip_remove_pin_ranges(struct gpio_chip *chip) | |||
1220 | list_del(&pin_range->node); | 1245 | list_del(&pin_range->node); |
1221 | pinctrl_remove_gpio_range(pin_range->pctldev, | 1246 | pinctrl_remove_gpio_range(pin_range->pctldev, |
1222 | &pin_range->range); | 1247 | &pin_range->range); |
1248 | kfree(pin_range); | ||
1223 | } | 1249 | } |
1224 | } | 1250 | } |
1225 | EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); | 1251 | EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); |