diff options
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/core.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index dca9208f5463..33710b5e7bb5 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -283,6 +283,29 @@ static int pinctrl_register_pins(struct pinctrl_dev *pctldev, | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /** | 285 | /** |
286 | * gpio_to_pin() - GPIO range GPIO number to pin number translation | ||
287 | * @range: GPIO range used for the translation | ||
288 | * @gpio: gpio pin to translate to a pin number | ||
289 | * | ||
290 | * Finds the pin number for a given GPIO using the specified GPIO range | ||
291 | * as a base for translation. The distinction between linear GPIO ranges | ||
292 | * and pin list based GPIO ranges is managed correctly by this function. | ||
293 | * | ||
294 | * This function assumes the gpio is part of the specified GPIO range, use | ||
295 | * only after making sure this is the case (e.g. by calling it on the | ||
296 | * result of successful pinctrl_get_device_gpio_range calls)! | ||
297 | */ | ||
298 | static inline int gpio_to_pin(struct pinctrl_gpio_range *range, | ||
299 | unsigned int gpio) | ||
300 | { | ||
301 | unsigned int offset = gpio - range->base; | ||
302 | if (range->pins) | ||
303 | return range->pins[offset]; | ||
304 | else | ||
305 | return range->pin_base + offset; | ||
306 | } | ||
307 | |||
308 | /** | ||
286 | * pinctrl_match_gpio_range() - check if a certain GPIO pin is in range | 309 | * pinctrl_match_gpio_range() - check if a certain GPIO pin is in range |
287 | * @pctldev: pin controller device to check | 310 | * @pctldev: pin controller device to check |
288 | * @gpio: gpio pin to check taken from the global GPIO pin space | 311 | * @gpio: gpio pin to check taken from the global GPIO pin space |
@@ -448,8 +471,14 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, | |||
448 | /* Loop over the ranges */ | 471 | /* Loop over the ranges */ |
449 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { | 472 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { |
450 | /* Check if we're in the valid range */ | 473 | /* Check if we're in the valid range */ |
451 | if (pin >= range->pin_base && | 474 | if (range->pins) { |
452 | pin < range->pin_base + range->npins) { | 475 | int a; |
476 | for (a = 0; a < range->npins; a++) { | ||
477 | if (range->pins[a] == pin) | ||
478 | return range; | ||
479 | } | ||
480 | } else if (pin >= range->pin_base && | ||
481 | pin < range->pin_base + range->npins) { | ||
453 | mutex_unlock(&pctldev->mutex); | 482 | mutex_unlock(&pctldev->mutex); |
454 | return range; | 483 | return range; |
455 | } | 484 | } |
@@ -529,7 +558,7 @@ int pinctrl_request_gpio(unsigned gpio) | |||
529 | } | 558 | } |
530 | 559 | ||
531 | /* Convert to the pin controllers number space */ | 560 | /* Convert to the pin controllers number space */ |
532 | pin = gpio - range->base + range->pin_base; | 561 | pin = gpio_to_pin(range, gpio); |
533 | 562 | ||
534 | ret = pinmux_request_gpio(pctldev, range, pin, gpio); | 563 | ret = pinmux_request_gpio(pctldev, range, pin, gpio); |
535 | 564 | ||
@@ -559,7 +588,7 @@ void pinctrl_free_gpio(unsigned gpio) | |||
559 | mutex_lock(&pctldev->mutex); | 588 | mutex_lock(&pctldev->mutex); |
560 | 589 | ||
561 | /* Convert to the pin controllers number space */ | 590 | /* Convert to the pin controllers number space */ |
562 | pin = gpio - range->base + range->pin_base; | 591 | pin = gpio_to_pin(range, gpio); |
563 | 592 | ||
564 | pinmux_free_gpio(pctldev, pin, range); | 593 | pinmux_free_gpio(pctldev, pin, range); |
565 | 594 | ||
@@ -582,7 +611,7 @@ static int pinctrl_gpio_direction(unsigned gpio, bool input) | |||
582 | mutex_lock(&pctldev->mutex); | 611 | mutex_lock(&pctldev->mutex); |
583 | 612 | ||
584 | /* Convert to the pin controllers number space */ | 613 | /* Convert to the pin controllers number space */ |
585 | pin = gpio - range->base + range->pin_base; | 614 | pin = gpio_to_pin(range, gpio); |
586 | ret = pinmux_gpio_direction(pctldev, range, pin, input); | 615 | ret = pinmux_gpio_direction(pctldev, range, pin, input); |
587 | 616 | ||
588 | mutex_unlock(&pctldev->mutex); | 617 | mutex_unlock(&pctldev->mutex); |
@@ -1349,11 +1378,21 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what) | |||
1349 | 1378 | ||
1350 | /* Loop over the ranges */ | 1379 | /* Loop over the ranges */ |
1351 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { | 1380 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { |
1352 | seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n", | 1381 | if (range->pins) { |
1353 | range->id, range->name, | 1382 | int a; |
1354 | range->base, (range->base + range->npins - 1), | 1383 | seq_printf(s, "%u: %s GPIOS [%u - %u] PINS {", |
1355 | range->pin_base, | 1384 | range->id, range->name, |
1356 | (range->pin_base + range->npins - 1)); | 1385 | range->base, (range->base + range->npins - 1)); |
1386 | for (a = 0; a < range->npins - 1; a++) | ||
1387 | seq_printf(s, "%u, ", range->pins[a]); | ||
1388 | seq_printf(s, "%u}\n", range->pins[a]); | ||
1389 | } | ||
1390 | else | ||
1391 | seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n", | ||
1392 | range->id, range->name, | ||
1393 | range->base, (range->base + range->npins - 1), | ||
1394 | range->pin_base, | ||
1395 | (range->pin_base + range->npins - 1)); | ||
1357 | } | 1396 | } |
1358 | 1397 | ||
1359 | mutex_unlock(&pctldev->mutex); | 1398 | mutex_unlock(&pctldev->mutex); |