summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1c8d9e3380e1..f0b07bbfcc9a 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1083,6 +1083,10 @@ int gpiochip_add(struct gpio_chip *chip)
}
}
+#ifdef CONFIG_PINCTRL
+ INIT_LIST_HEAD(&chip->pin_ranges);
+#endif
+
of_gpiochip_add(chip);
unlock:
@@ -1180,6 +1184,45 @@ struct gpio_chip *gpiochip_find(void *data,
}
EXPORT_SYMBOL_GPL(gpiochip_find);
+#ifdef CONFIG_PINCTRL
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int pin_base, unsigned int npins)
+{
+ struct gpio_pin_range *pin_range;
+
+ pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), GFP_KERNEL);
+ if (!pin_range) {
+ pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+ chip->label);
+ return;
+ }
+
+ pin_range->range.name = chip->label;
+ pin_range->range.base = chip->base;
+ 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);
+
+ list_add_tail(&pin_range->node, &chip->pin_ranges);
+}
+
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+ struct gpio_pin_range *pin_range, *tmp;
+
+ list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+ list_del(&pin_range->node);
+ pinctrl_remove_gpio_range(pin_range->pctldev,
+ &pin_range->range);
+ }
+}
+#else
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int pin_base, unsigned int npins) {}
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip) {}
+#endif
+
/* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs.
* They're called even less than the "set direction" calls.