|
@@ -282,6 +282,29 @@ static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * gpio_to_pin() - GPIO range GPIO number to pin number translation
|
|
|
+ * @range: GPIO range used for the translation
|
|
|
+ * @gpio: gpio pin to translate to a pin number
|
|
|
+ *
|
|
|
+ * Finds the pin number for a given GPIO using the specified GPIO range
|
|
|
+ * as a base for translation. The distinction between linear GPIO ranges
|
|
|
+ * and pin list based GPIO ranges is managed correctly by this function.
|
|
|
+ *
|
|
|
+ * This function assumes the gpio is part of the specified GPIO range, use
|
|
|
+ * only after making sure this is the case (e.g. by calling it on the
|
|
|
+ * result of successful pinctrl_get_device_gpio_range calls)!
|
|
|
+ */
|
|
|
+static inline int gpio_to_pin(struct pinctrl_gpio_range *range,
|
|
|
+ unsigned int gpio)
|
|
|
+{
|
|
|
+ unsigned int offset = gpio - range->base;
|
|
|
+ if (range->pins)
|
|
|
+ return range->pins[offset];
|
|
|
+ else
|
|
|
+ return range->pin_base + offset;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* pinctrl_match_gpio_range() - check if a certain GPIO pin is in range
|
|
|
* @pctldev: pin controller device to check
|
|
@@ -448,8 +471,14 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
|
|
|
/* Loop over the ranges */
|
|
|
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
|
|
/* Check if we're in the valid range */
|
|
|
- if (pin >= range->pin_base &&
|
|
|
- pin < range->pin_base + range->npins) {
|
|
|
+ if (range->pins) {
|
|
|
+ int a;
|
|
|
+ for (a = 0; a < range->npins; a++) {
|
|
|
+ if (range->pins[a] == pin)
|
|
|
+ return range;
|
|
|
+ }
|
|
|
+ } else if (pin >= range->pin_base &&
|
|
|
+ pin < range->pin_base + range->npins) {
|
|
|
mutex_unlock(&pctldev->mutex);
|
|
|
return range;
|
|
|
}
|
|
@@ -529,7 +558,7 @@ int pinctrl_request_gpio(unsigned gpio)
|
|
|
}
|
|
|
|
|
|
/* Convert to the pin controllers number space */
|
|
|
- pin = gpio - range->base + range->pin_base;
|
|
|
+ pin = gpio_to_pin(range, gpio);
|
|
|
|
|
|
ret = pinmux_request_gpio(pctldev, range, pin, gpio);
|
|
|
|
|
@@ -559,7 +588,7 @@ void pinctrl_free_gpio(unsigned gpio)
|
|
|
mutex_lock(&pctldev->mutex);
|
|
|
|
|
|
/* Convert to the pin controllers number space */
|
|
|
- pin = gpio - range->base + range->pin_base;
|
|
|
+ pin = gpio_to_pin(range, gpio);
|
|
|
|
|
|
pinmux_free_gpio(pctldev, pin, range);
|
|
|
|
|
@@ -582,7 +611,7 @@ static int pinctrl_gpio_direction(unsigned gpio, bool input)
|
|
|
mutex_lock(&pctldev->mutex);
|
|
|
|
|
|
/* Convert to the pin controllers number space */
|
|
|
- pin = gpio - range->base + range->pin_base;
|
|
|
+ pin = gpio_to_pin(range, gpio);
|
|
|
ret = pinmux_gpio_direction(pctldev, range, pin, input);
|
|
|
|
|
|
mutex_unlock(&pctldev->mutex);
|
|
@@ -1349,11 +1378,21 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
|
|
|
|
|
|
/* Loop over the ranges */
|
|
|
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
|
|
- seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
|
|
|
- range->id, range->name,
|
|
|
- range->base, (range->base + range->npins - 1),
|
|
|
- range->pin_base,
|
|
|
- (range->pin_base + range->npins - 1));
|
|
|
+ if (range->pins) {
|
|
|
+ int a;
|
|
|
+ seq_printf(s, "%u: %s GPIOS [%u - %u] PINS {",
|
|
|
+ range->id, range->name,
|
|
|
+ range->base, (range->base + range->npins - 1));
|
|
|
+ for (a = 0; a < range->npins - 1; a++)
|
|
|
+ seq_printf(s, "%u, ", range->pins[a]);
|
|
|
+ seq_printf(s, "%u}\n", range->pins[a]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
|
|
|
+ range->id, range->name,
|
|
|
+ range->base, (range->base + range->npins - 1),
|
|
|
+ range->pin_base,
|
|
|
+ (range->pin_base + range->npins - 1));
|
|
|
}
|
|
|
|
|
|
mutex_unlock(&pctldev->mutex);
|