aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/enumeration.txt32
-rw-r--r--drivers/gpio/gpiolib-acpi.c77
-rw-r--r--include/linux/acpi_gpio.h17
3 files changed, 125 insertions, 1 deletions
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
index 94a656131885..b0d541042ac6 100644
--- a/Documentation/acpi/enumeration.txt
+++ b/Documentation/acpi/enumeration.txt
@@ -199,6 +199,8 @@ the device to the driver. For example:
199 { 199 {
200 Name (SBUF, ResourceTemplate() 200 Name (SBUF, ResourceTemplate()
201 { 201 {
202 ...
203 // Used to power on/off the device
202 GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, 204 GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
203 IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0", 205 IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
204 0x00, ResourceConsumer,,) 206 0x00, ResourceConsumer,,)
@@ -206,10 +208,20 @@ the device to the driver. For example:
206 // Pin List 208 // Pin List
207 0x0055 209 0x0055
208 } 210 }
211
212 // Interrupt for the device
213 GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullNone,
214 0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer,,)
215 {
216 // Pin list
217 0x0058
218 }
219
209 ... 220 ...
210 221
211 Return (SBUF)
212 } 222 }
223
224 Return (SBUF)
213 } 225 }
214 226
215These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0" 227These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
@@ -220,6 +232,24 @@ The driver can do this by including <linux/acpi_gpio.h> and then calling
220acpi_get_gpio(path, gpio). This will return the Linux GPIO number or 232acpi_get_gpio(path, gpio). This will return the Linux GPIO number or
221negative errno if there was no translation found. 233negative errno if there was no translation found.
222 234
235In a simple case of just getting the Linux GPIO number from device
236resources one can use acpi_get_gpio_by_index() helper function. It takes
237pointer to the device and index of the GpioIo/GpioInt descriptor in the
238device resources list. For example:
239
240 int gpio_irq, gpio_power;
241 int ret;
242
243 gpio_irq = acpi_get_gpio_by_index(dev, 1, NULL);
244 if (gpio_irq < 0)
245 /* handle error */
246
247 gpio_power = acpi_get_gpio_by_index(dev, 0, NULL);
248 if (gpio_power < 0)
249 /* handle error */
250
251 /* Now we can use the GPIO numbers */
252
223Other GpioIo parameters must be converted first by the driver to be 253Other GpioIo parameters must be converted first by the driver to be
224suitable to the gpiolib before passing them. 254suitable to the gpiolib before passing them.
225 255
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 89336c4f82cd..5c1ef2b3ef18 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -201,6 +201,83 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
201} 201}
202EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); 202EXPORT_SYMBOL(acpi_gpiochip_request_interrupts);
203 203
204struct acpi_gpio_lookup {
205 struct acpi_gpio_info info;
206 int index;
207 int gpio;
208 int n;
209};
210
211static int acpi_find_gpio(struct acpi_resource *ares, void *data)
212{
213 struct acpi_gpio_lookup *lookup = data;
214
215 if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
216 return 1;
217
218 if (lookup->n++ == lookup->index && lookup->gpio < 0) {
219 const struct acpi_resource_gpio *agpio = &ares->data.gpio;
220
221 lookup->gpio = acpi_get_gpio(agpio->resource_source.string_ptr,
222 agpio->pin_table[0]);
223 lookup->info.gpioint =
224 agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
225 }
226
227 return 1;
228}
229
230/**
231 * acpi_get_gpio_by_index() - get a GPIO number from device resources
232 * @dev: pointer to a device to get GPIO from
233 * @index: index of GpioIo/GpioInt resource (starting from %0)
234 * @info: info pointer to fill in (optional)
235 *
236 * Function goes through ACPI resources for @dev and based on @index looks
237 * up a GpioIo/GpioInt resource, translates it to the Linux GPIO number,
238 * and returns it. @index matches GpioIo/GpioInt resources only so if there
239 * are total %3 GPIO resources, the index goes from %0 to %2.
240 *
241 * If the GPIO cannot be translated or there is an error, negative errno is
242 * returned.
243 *
244 * Note: if the GPIO resource has multiple entries in the pin list, this
245 * function only returns the first.
246 */
247int acpi_get_gpio_by_index(struct device *dev, int index,
248 struct acpi_gpio_info *info)
249{
250 struct acpi_gpio_lookup lookup;
251 struct list_head resource_list;
252 struct acpi_device *adev;
253 acpi_handle handle;
254 int ret;
255
256 if (!dev)
257 return -EINVAL;
258
259 handle = ACPI_HANDLE(dev);
260 if (!handle || acpi_bus_get_device(handle, &adev))
261 return -ENODEV;
262
263 memset(&lookup, 0, sizeof(lookup));
264 lookup.index = index;
265 lookup.gpio = -ENODEV;
266
267 INIT_LIST_HEAD(&resource_list);
268 ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
269 &lookup);
270 if (ret < 0)
271 return ret;
272
273 acpi_dev_free_resource_list(&resource_list);
274
275 if (lookup.gpio >= 0 && info)
276 *info = lookup.info;
277
278 return lookup.gpio;
279}
280EXPORT_SYMBOL_GPL(acpi_get_gpio_by_index);
204 281
205/** 282/**
206 * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts. 283 * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts.
diff --git a/include/linux/acpi_gpio.h b/include/linux/acpi_gpio.h
index 213135f44333..4c120a1e0ca3 100644
--- a/include/linux/acpi_gpio.h
+++ b/include/linux/acpi_gpio.h
@@ -1,12 +1,23 @@
1#ifndef _LINUX_ACPI_GPIO_H_ 1#ifndef _LINUX_ACPI_GPIO_H_
2#define _LINUX_ACPI_GPIO_H_ 2#define _LINUX_ACPI_GPIO_H_
3 3
4#include <linux/device.h>
4#include <linux/errno.h> 5#include <linux/errno.h>
5#include <linux/gpio.h> 6#include <linux/gpio.h>
6 7
8/**
9 * struct acpi_gpio_info - ACPI GPIO specific information
10 * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
11 */
12struct acpi_gpio_info {
13 bool gpioint;
14};
15
7#ifdef CONFIG_GPIO_ACPI 16#ifdef CONFIG_GPIO_ACPI
8 17
9int acpi_get_gpio(char *path, int pin); 18int acpi_get_gpio(char *path, int pin);
19int acpi_get_gpio_by_index(struct device *dev, int index,
20 struct acpi_gpio_info *info);
10void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); 21void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
11void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); 22void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
12 23
@@ -17,6 +28,12 @@ static inline int acpi_get_gpio(char *path, int pin)
17 return -ENODEV; 28 return -ENODEV;
18} 29}
19 30
31static inline int acpi_get_gpio_by_index(struct device *dev, int index,
32 struct acpi_gpio_info *info)
33{
34 return -ENODEV;
35}
36
20static inline void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } 37static inline void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
21static inline void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } 38static inline void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
22 39