aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2014-11-03 06:01:32 -0500
committerLinus Walleij <linus.walleij@linaro.org>2014-11-04 05:18:52 -0500
commit354567e6084c0760dc1e3a164ce4e77c5a943acc (patch)
treec2645d3c9e71da01ab64eb93d363eb4094ec8bb8
parentee76a9abde4f428a3d342822301ddb8d080d6557 (diff)
gpio / ACPI: Add knowledge about pin controllers to acpi_get_gpiod()
The GPIO resources (GpioIo/GpioInt) used in ACPI contain a GPIO number which is relative to the hardware GPIO controller. Typically this number can be translated directly to Linux GPIO number because the mapping is pretty much 1:1. However, when the GPIO driver is using pins exported by a pin controller driver via set of GPIO ranges, the mapping might not be 1:1 anymore and direct translation does not work. In such cases we need to translate the ACPI GPIO number to be suitable for the GPIO controller driver in question by checking all the pin controller GPIO ranges under the given device and using those to get the proper GPIO number. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpiolib-acpi.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 05c6275da224..5be637dffa73 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -11,12 +11,14 @@
11 */ 11 */
12 12
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/gpio.h>
14#include <linux/gpio/consumer.h> 15#include <linux/gpio/consumer.h>
15#include <linux/gpio/driver.h> 16#include <linux/gpio/driver.h>
16#include <linux/export.h> 17#include <linux/export.h>
17#include <linux/acpi.h> 18#include <linux/acpi.h>
18#include <linux/interrupt.h> 19#include <linux/interrupt.h>
19#include <linux/mutex.h> 20#include <linux/mutex.h>
21#include <linux/pinctrl/pinctrl.h>
20 22
21#include "gpiolib.h" 23#include "gpiolib.h"
22 24
@@ -55,6 +57,58 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
55 return ACPI_HANDLE(gc->dev) == data; 57 return ACPI_HANDLE(gc->dev) == data;
56} 58}
57 59
60#ifdef CONFIG_PINCTRL
61/**
62 * acpi_gpiochip_pin_to_gpio_offset() - translates ACPI GPIO to Linux GPIO
63 * @chip: GPIO chip
64 * @pin: ACPI GPIO pin number from GpioIo/GpioInt resource
65 *
66 * Function takes ACPI GpioIo/GpioInt pin number as a parameter and
67 * translates it to a corresponding offset suitable to be passed to a
68 * GPIO controller driver.
69 *
70 * Typically the returned offset is same as @pin, but if the GPIO
71 * controller uses pin controller and the mapping is not contigous the
72 * offset might be different.
73 */
74static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_chip *chip, int pin)
75{
76 struct gpio_pin_range *pin_range;
77
78 /* If there are no ranges in this chip, use 1:1 mapping */
79 if (list_empty(&chip->pin_ranges))
80 return pin;
81
82 list_for_each_entry(pin_range, &chip->pin_ranges, node) {
83 const struct pinctrl_gpio_range *range = &pin_range->range;
84 int i;
85
86 if (range->pins) {
87 for (i = 0; i < range->npins; i++) {
88 if (range->pins[i] == pin)
89 return range->base + i - chip->base;
90 }
91 } else {
92 if (pin >= range->pin_base &&
93 pin < range->pin_base + range->npins) {
94 unsigned gpio_base;
95
96 gpio_base = range->base - chip->base;
97 return gpio_base + pin - range->pin_base;
98 }
99 }
100 }
101
102 return -EINVAL;
103}
104#else
105static inline int acpi_gpiochip_pin_to_gpio_offset(struct gpio_chip *chip,
106 int pin)
107{
108 return pin;
109}
110#endif
111
58/** 112/**
59 * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API 113 * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API
60 * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1") 114 * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
@@ -69,6 +123,7 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
69 struct gpio_chip *chip; 123 struct gpio_chip *chip;
70 acpi_handle handle; 124 acpi_handle handle;
71 acpi_status status; 125 acpi_status status;
126 int offset;
72 127
73 status = acpi_get_handle(NULL, path, &handle); 128 status = acpi_get_handle(NULL, path, &handle);
74 if (ACPI_FAILURE(status)) 129 if (ACPI_FAILURE(status))
@@ -78,10 +133,11 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
78 if (!chip) 133 if (!chip)
79 return ERR_PTR(-ENODEV); 134 return ERR_PTR(-ENODEV);
80 135
81 if (pin < 0 || pin > chip->ngpio) 136 offset = acpi_gpiochip_pin_to_gpio_offset(chip, pin);
82 return ERR_PTR(-EINVAL); 137 if (offset < 0)
138 return ERR_PTR(offset);
83 139
84 return gpiochip_get_desc(chip, pin); 140 return gpiochip_get_desc(chip, offset);
85} 141}
86 142
87static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) 143static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)