diff options
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 138 |
1 files changed, 66 insertions, 72 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 5c1ef2b3ef18..ae0ffdce8bd5 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
@@ -11,7 +11,7 @@ | |||
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/export.h> | 15 | #include <linux/export.h> |
16 | #include <linux/acpi_gpio.h> | 16 | #include <linux/acpi_gpio.h> |
17 | #include <linux/acpi.h> | 17 | #include <linux/acpi.h> |
@@ -33,14 +33,15 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) | |||
33 | } | 33 | } |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API | 36 | * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API |
37 | * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1") | 37 | * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1") |
38 | * @pin: ACPI GPIO pin number (0-based, controller-relative) | 38 | * @pin: ACPI GPIO pin number (0-based, controller-relative) |
39 | * | 39 | * |
40 | * Returns GPIO number to use with Linux generic GPIO API, or errno error value | 40 | * Returns GPIO descriptor to use with Linux generic GPIO API, or ERR_PTR |
41 | * error value | ||
41 | */ | 42 | */ |
42 | 43 | ||
43 | int acpi_get_gpio(char *path, int pin) | 44 | static struct gpio_desc *acpi_get_gpiod(char *path, int pin) |
44 | { | 45 | { |
45 | struct gpio_chip *chip; | 46 | struct gpio_chip *chip; |
46 | acpi_handle handle; | 47 | acpi_handle handle; |
@@ -48,18 +49,17 @@ int acpi_get_gpio(char *path, int pin) | |||
48 | 49 | ||
49 | status = acpi_get_handle(NULL, path, &handle); | 50 | status = acpi_get_handle(NULL, path, &handle); |
50 | if (ACPI_FAILURE(status)) | 51 | if (ACPI_FAILURE(status)) |
51 | return -ENODEV; | 52 | return ERR_PTR(-ENODEV); |
52 | 53 | ||
53 | chip = gpiochip_find(handle, acpi_gpiochip_find); | 54 | chip = gpiochip_find(handle, acpi_gpiochip_find); |
54 | if (!chip) | 55 | if (!chip) |
55 | return -ENODEV; | 56 | return ERR_PTR(-ENODEV); |
56 | 57 | ||
57 | if (!gpio_is_valid(chip->base + pin)) | 58 | if (pin < 0 || pin > chip->ngpio) |
58 | return -EINVAL; | 59 | return ERR_PTR(-EINVAL); |
59 | 60 | ||
60 | return chip->base + pin; | 61 | return gpio_to_desc(chip->base + pin); |
61 | } | 62 | } |
62 | EXPORT_SYMBOL_GPL(acpi_get_gpio); | ||
63 | 63 | ||
64 | static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) | 64 | static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) |
65 | { | 65 | { |
@@ -73,15 +73,8 @@ static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) | |||
73 | static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data) | 73 | static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data) |
74 | { | 74 | { |
75 | struct acpi_gpio_evt_pin *evt_pin = data; | 75 | struct acpi_gpio_evt_pin *evt_pin = data; |
76 | struct acpi_object_list args; | ||
77 | union acpi_object arg; | ||
78 | 76 | ||
79 | arg.type = ACPI_TYPE_INTEGER; | 77 | acpi_execute_simple_method(evt_pin->evt_handle, NULL, evt_pin->pin); |
80 | arg.integer.value = evt_pin->pin; | ||
81 | args.count = 1; | ||
82 | args.pointer = &arg; | ||
83 | |||
84 | acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL); | ||
85 | 78 | ||
86 | return IRQ_HANDLED; | 79 | return IRQ_HANDLED; |
87 | } | 80 | } |
@@ -201,10 +194,48 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) | |||
201 | } | 194 | } |
202 | EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); | 195 | EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); |
203 | 196 | ||
197 | /** | ||
198 | * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts. | ||
199 | * @chip: gpio chip | ||
200 | * | ||
201 | * Free interrupts associated with the _EVT method for the given GPIO chip. | ||
202 | * | ||
203 | * The remaining ACPI event interrupts associated with the chip are freed | ||
204 | * automatically. | ||
205 | */ | ||
206 | void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) | ||
207 | { | ||
208 | acpi_handle handle; | ||
209 | acpi_status status; | ||
210 | struct list_head *evt_pins; | ||
211 | struct acpi_gpio_evt_pin *evt_pin, *ep; | ||
212 | |||
213 | if (!chip->dev || !chip->to_irq) | ||
214 | return; | ||
215 | |||
216 | handle = ACPI_HANDLE(chip->dev); | ||
217 | if (!handle) | ||
218 | return; | ||
219 | |||
220 | status = acpi_get_data(handle, acpi_gpio_evt_dh, (void **)&evt_pins); | ||
221 | if (ACPI_FAILURE(status)) | ||
222 | return; | ||
223 | |||
224 | list_for_each_entry_safe_reverse(evt_pin, ep, evt_pins, node) { | ||
225 | devm_free_irq(chip->dev, evt_pin->irq, evt_pin); | ||
226 | list_del(&evt_pin->node); | ||
227 | kfree(evt_pin); | ||
228 | } | ||
229 | |||
230 | acpi_detach_data(handle, acpi_gpio_evt_dh); | ||
231 | kfree(evt_pins); | ||
232 | } | ||
233 | EXPORT_SYMBOL(acpi_gpiochip_free_interrupts); | ||
234 | |||
204 | struct acpi_gpio_lookup { | 235 | struct acpi_gpio_lookup { |
205 | struct acpi_gpio_info info; | 236 | struct acpi_gpio_info info; |
206 | int index; | 237 | int index; |
207 | int gpio; | 238 | struct gpio_desc *desc; |
208 | int n; | 239 | int n; |
209 | }; | 240 | }; |
210 | 241 | ||
@@ -215,37 +246,39 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) | |||
215 | if (ares->type != ACPI_RESOURCE_TYPE_GPIO) | 246 | if (ares->type != ACPI_RESOURCE_TYPE_GPIO) |
216 | return 1; | 247 | return 1; |
217 | 248 | ||
218 | if (lookup->n++ == lookup->index && lookup->gpio < 0) { | 249 | if (lookup->n++ == lookup->index && !lookup->desc) { |
219 | const struct acpi_resource_gpio *agpio = &ares->data.gpio; | 250 | const struct acpi_resource_gpio *agpio = &ares->data.gpio; |
220 | 251 | ||
221 | lookup->gpio = acpi_get_gpio(agpio->resource_source.string_ptr, | 252 | lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, |
222 | agpio->pin_table[0]); | 253 | agpio->pin_table[0]); |
223 | lookup->info.gpioint = | 254 | lookup->info.gpioint = |
224 | agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; | 255 | agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; |
256 | lookup->info.active_low = | ||
257 | agpio->polarity == ACPI_ACTIVE_LOW; | ||
225 | } | 258 | } |
226 | 259 | ||
227 | return 1; | 260 | return 1; |
228 | } | 261 | } |
229 | 262 | ||
230 | /** | 263 | /** |
231 | * acpi_get_gpio_by_index() - get a GPIO number from device resources | 264 | * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources |
232 | * @dev: pointer to a device to get GPIO from | 265 | * @dev: pointer to a device to get GPIO from |
233 | * @index: index of GpioIo/GpioInt resource (starting from %0) | 266 | * @index: index of GpioIo/GpioInt resource (starting from %0) |
234 | * @info: info pointer to fill in (optional) | 267 | * @info: info pointer to fill in (optional) |
235 | * | 268 | * |
236 | * Function goes through ACPI resources for @dev and based on @index looks | 269 | * 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, | 270 | * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor, |
238 | * and returns it. @index matches GpioIo/GpioInt resources only so if there | 271 | * 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. | 272 | * are total %3 GPIO resources, the index goes from %0 to %2. |
240 | * | 273 | * |
241 | * If the GPIO cannot be translated or there is an error, negative errno is | 274 | * If the GPIO cannot be translated or there is an error an ERR_PTR is |
242 | * returned. | 275 | * returned. |
243 | * | 276 | * |
244 | * Note: if the GPIO resource has multiple entries in the pin list, this | 277 | * Note: if the GPIO resource has multiple entries in the pin list, this |
245 | * function only returns the first. | 278 | * function only returns the first. |
246 | */ | 279 | */ |
247 | int acpi_get_gpio_by_index(struct device *dev, int index, | 280 | struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, |
248 | struct acpi_gpio_info *info) | 281 | struct acpi_gpio_info *info) |
249 | { | 282 | { |
250 | struct acpi_gpio_lookup lookup; | 283 | struct acpi_gpio_lookup lookup; |
251 | struct list_head resource_list; | 284 | struct list_head resource_list; |
@@ -254,65 +287,26 @@ int acpi_get_gpio_by_index(struct device *dev, int index, | |||
254 | int ret; | 287 | int ret; |
255 | 288 | ||
256 | if (!dev) | 289 | if (!dev) |
257 | return -EINVAL; | 290 | return ERR_PTR(-EINVAL); |
258 | 291 | ||
259 | handle = ACPI_HANDLE(dev); | 292 | handle = ACPI_HANDLE(dev); |
260 | if (!handle || acpi_bus_get_device(handle, &adev)) | 293 | if (!handle || acpi_bus_get_device(handle, &adev)) |
261 | return -ENODEV; | 294 | return ERR_PTR(-ENODEV); |
262 | 295 | ||
263 | memset(&lookup, 0, sizeof(lookup)); | 296 | memset(&lookup, 0, sizeof(lookup)); |
264 | lookup.index = index; | 297 | lookup.index = index; |
265 | lookup.gpio = -ENODEV; | ||
266 | 298 | ||
267 | INIT_LIST_HEAD(&resource_list); | 299 | INIT_LIST_HEAD(&resource_list); |
268 | ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, | 300 | ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, |
269 | &lookup); | 301 | &lookup); |
270 | if (ret < 0) | 302 | if (ret < 0) |
271 | return ret; | 303 | return ERR_PTR(ret); |
272 | 304 | ||
273 | acpi_dev_free_resource_list(&resource_list); | 305 | acpi_dev_free_resource_list(&resource_list); |
274 | 306 | ||
275 | if (lookup.gpio >= 0 && info) | 307 | if (lookup.desc && info) |
276 | *info = lookup.info; | 308 | *info = lookup.info; |
277 | 309 | ||
278 | return lookup.gpio; | 310 | return lookup.desc ? lookup.desc : ERR_PTR(-ENODEV); |
279 | } | 311 | } |
280 | EXPORT_SYMBOL_GPL(acpi_get_gpio_by_index); | 312 | EXPORT_SYMBOL_GPL(acpi_get_gpiod_by_index); |
281 | |||
282 | /** | ||
283 | * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts. | ||
284 | * @chip: gpio chip | ||
285 | * | ||
286 | * Free interrupts associated with the _EVT method for the given GPIO chip. | ||
287 | * | ||
288 | * The remaining ACPI event interrupts associated with the chip are freed | ||
289 | * automatically. | ||
290 | */ | ||
291 | void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) | ||
292 | { | ||
293 | acpi_handle handle; | ||
294 | acpi_status status; | ||
295 | struct list_head *evt_pins; | ||
296 | struct acpi_gpio_evt_pin *evt_pin, *ep; | ||
297 | |||
298 | if (!chip->dev || !chip->to_irq) | ||
299 | return; | ||
300 | |||
301 | handle = ACPI_HANDLE(chip->dev); | ||
302 | if (!handle) | ||
303 | return; | ||
304 | |||
305 | status = acpi_get_data(handle, acpi_gpio_evt_dh, (void **)&evt_pins); | ||
306 | if (ACPI_FAILURE(status)) | ||
307 | return; | ||
308 | |||
309 | list_for_each_entry_safe_reverse(evt_pin, ep, evt_pins, node) { | ||
310 | devm_free_irq(chip->dev, evt_pin->irq, evt_pin); | ||
311 | list_del(&evt_pin->node); | ||
312 | kfree(evt_pin); | ||
313 | } | ||
314 | |||
315 | acpi_detach_data(handle, acpi_gpio_evt_dh); | ||
316 | kfree(evt_pins); | ||
317 | } | ||
318 | EXPORT_SYMBOL(acpi_gpiochip_free_interrupts); | ||