diff options
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 12 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 32 | ||||
-rw-r--r-- | include/asm-generic/gpio.h | 6 | ||||
-rw-r--r-- | include/linux/gpio.h | 3 |
4 files changed, 47 insertions, 6 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a40cd84c5c10..d542a141811a 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c | |||
@@ -238,8 +238,20 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) | |||
238 | if (!pctldev) | 238 | if (!pctldev) |
239 | break; | 239 | break; |
240 | 240 | ||
241 | /* | ||
242 | * This assumes that the n GPIO pins are consecutive in the | ||
243 | * GPIO number space, and that the pins are also consecutive | ||
244 | * in their local number space. Currently it is not possible | ||
245 | * to add different ranges for one and the same GPIO chip, | ||
246 | * as the code assumes that we have one consecutive range | ||
247 | * on both, mapping 1-to-1. | ||
248 | * | ||
249 | * TODO: make the OF bindings handle multiple sparse ranges | ||
250 | * on the same GPIO chip. | ||
251 | */ | ||
241 | ret = gpiochip_add_pin_range(chip, | 252 | ret = gpiochip_add_pin_range(chip, |
242 | pinctrl_dev_get_name(pctldev), | 253 | pinctrl_dev_get_name(pctldev), |
254 | 0, /* offset in gpiochip */ | ||
243 | pinspec.args[0], | 255 | pinspec.args[0], |
244 | pinspec.args[1]); | 256 | pinspec.args[1]); |
245 | 257 | ||
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); |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 2b84fc32fae2..ec58fdbddb59 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
@@ -283,14 +283,16 @@ struct gpio_pin_range { | |||
283 | }; | 283 | }; |
284 | 284 | ||
285 | int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | 285 | int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, |
286 | unsigned int pin_base, unsigned int npins); | 286 | unsigned int offset, unsigned int pin_base, |
287 | unsigned int npins); | ||
287 | void gpiochip_remove_pin_ranges(struct gpio_chip *chip); | 288 | void gpiochip_remove_pin_ranges(struct gpio_chip *chip); |
288 | 289 | ||
289 | #else | 290 | #else |
290 | 291 | ||
291 | static inline int | 292 | static inline int |
292 | gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | 293 | gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, |
293 | unsigned int pin_base, unsigned int npins) | 294 | unsigned int offset, unsigned int pin_base, |
295 | unsigned int npins) | ||
294 | { | 296 | { |
295 | return 0; | 297 | return 0; |
296 | } | 298 | } |
diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 7ba2762abbc9..99861c65dd8b 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h | |||
@@ -233,7 +233,8 @@ static inline int irq_to_gpio(unsigned irq) | |||
233 | 233 | ||
234 | static inline int | 234 | static inline int |
235 | gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | 235 | gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, |
236 | unsigned int pin_base, unsigned int npins) | 236 | unsigned int offset, unsigned int pin_base, |
237 | unsigned int npins) | ||
237 | { | 238 | { |
238 | WARN_ON(1); | 239 | WARN_ON(1); |
239 | return -EINVAL; | 240 | return -EINVAL; |