acpi_handle handle;
unsigned int pin;
unsigned int irq;
+ struct gpio_desc *desc;
};
struct acpi_gpio_connection {
struct list_head node;
+ unsigned int pin;
struct gpio_desc *desc;
};
gpiod_direction_input(desc);
- ret = gpiod_lock_as_irq(desc);
+ ret = gpio_lock_as_irq(chip, pin);
if (ret) {
dev_err(chip->dev, "Failed to lock GPIO as interrupt\n");
goto fail_free_desc;
event->handle = evt_handle;
event->irq = irq;
event->pin = pin;
+ event->desc = desc;
ret = request_threaded_irq(event->irq, NULL, handler, irqflags,
"ACPI:Event", event);
fail_free_event:
kfree(event);
fail_unlock_irq:
- gpiod_unlock_as_irq(desc);
+ gpio_unlock_as_irq(chip, pin);
fail_free_desc:
gpiochip_free_own_desc(desc);
/**
* acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
- * @acpi_gpio: ACPI GPIO chip
+ * @chip: GPIO chip
*
* ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
* handled by ACPI event methods which need to be called from the GPIO
* gpio pins have acpi event methods and assigns interrupt handlers that calls
* the acpi event methods for those pins.
*/
-static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
+void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
{
- struct gpio_chip *chip = acpi_gpio->chip;
+ struct acpi_gpio_chip *acpi_gpio;
+ acpi_handle handle;
+ acpi_status status;
- if (!chip->to_irq)
+ if (!chip->dev || !chip->to_irq)
+ return;
+
+ handle = ACPI_HANDLE(chip->dev);
+ if (!handle)
+ return;
+
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status))
return;
INIT_LIST_HEAD(&acpi_gpio->events);
/**
* acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts.
- * @acpi_gpio: ACPI GPIO chip
+ * @chip: GPIO chip
*
* Free interrupts associated with GPIO ACPI event method for the given
* GPIO chip.
*/
-static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
+void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
{
+ struct acpi_gpio_chip *acpi_gpio;
struct acpi_gpio_event *event, *ep;
- struct gpio_chip *chip = acpi_gpio->chip;
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!chip->dev || !chip->to_irq)
+ return;
+
+ handle = ACPI_HANDLE(chip->dev);
+ if (!handle)
+ return;
- if (!chip->to_irq)
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status))
return;
list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
struct gpio_desc *desc;
free_irq(event->irq, event);
- desc = gpiochip_get_desc(chip, event->pin);
+ desc = event->desc;
if (WARN_ON(IS_ERR(desc)))
continue;
- gpiod_unlock_as_irq(desc);
+ gpio_unlock_as_irq(chip, event->pin);
gpiochip_free_own_desc(desc);
list_del(&event->node);
kfree(event);
struct gpio_desc *desc;
bool found;
- desc = gpiochip_get_desc(chip, pin);
- if (IS_ERR(desc)) {
- status = AE_ERROR;
- goto out;
- }
-
mutex_lock(&achip->conn_lock);
found = false;
list_for_each_entry(conn, &achip->conns, node) {
- if (conn->desc == desc) {
+ if (conn->pin == pin) {
found = true;
+ desc = conn->desc;
break;
}
}
if (!found) {
int ret;
+ desc = gpiochip_get_desc(chip, pin);
+ if (IS_ERR(desc)) {
+ status = AE_ERROR;
+ mutex_unlock(&achip->conn_lock);
+ goto out;
+ }
+
ret = gpiochip_request_own_desc(desc, "ACPI:OpRegion");
if (ret) {
status = AE_ERROR;
goto out;
}
+ conn->pin = pin;
conn->desc = desc;
list_add_tail(&conn->node, &achip->conns);
}
return;
}
- acpi_gpiochip_request_interrupts(acpi_gpio);
acpi_gpiochip_request_regions(acpi_gpio);
}
}
acpi_gpiochip_free_regions(acpi_gpio);
- acpi_gpiochip_free_interrupts(acpi_gpio);
acpi_detach_data(handle, acpi_gpio_chip_dh);
kfree(acpi_gpio);