gpiolib-acpi.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * ACPI helpers for GPIO API
  3. *
  4. * Copyright (C) 2012, Intel Corporation
  5. * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
  6. * Mika Westerberg <mika.westerberg@linux.intel.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/errno.h>
  13. #include <linux/gpio.h>
  14. #include <linux/export.h>
  15. #include <linux/acpi_gpio.h>
  16. #include <linux/acpi.h>
  17. #include <linux/interrupt.h>
  18. static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
  19. {
  20. if (!gc->dev)
  21. return false;
  22. return ACPI_HANDLE(gc->dev) == data;
  23. }
  24. /**
  25. * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API
  26. * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
  27. * @pin: ACPI GPIO pin number (0-based, controller-relative)
  28. *
  29. * Returns GPIO number to use with Linux generic GPIO API, or errno error value
  30. */
  31. int acpi_get_gpio(char *path, int pin)
  32. {
  33. struct gpio_chip *chip;
  34. acpi_handle handle;
  35. acpi_status status;
  36. status = acpi_get_handle(NULL, path, &handle);
  37. if (ACPI_FAILURE(status))
  38. return -ENODEV;
  39. chip = gpiochip_find(handle, acpi_gpiochip_find);
  40. if (!chip)
  41. return -ENODEV;
  42. if (!gpio_is_valid(chip->base + pin))
  43. return -EINVAL;
  44. return chip->base + pin;
  45. }
  46. EXPORT_SYMBOL_GPL(acpi_get_gpio);
  47. static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
  48. {
  49. acpi_handle handle = data;
  50. acpi_evaluate_object(handle, NULL, NULL, NULL);
  51. return IRQ_HANDLED;
  52. }
  53. /**
  54. * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
  55. * @chip: gpio chip
  56. *
  57. * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
  58. * handled by ACPI event methods which need to be called from the GPIO
  59. * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which
  60. * gpio pins have acpi event methods and assigns interrupt handlers that calls
  61. * the acpi event methods for those pins.
  62. *
  63. * Interrupts are automatically freed on driver detach
  64. */
  65. void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
  66. {
  67. struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
  68. struct acpi_resource *res;
  69. acpi_handle handle, ev_handle;
  70. acpi_status status;
  71. unsigned int pin;
  72. int irq, ret;
  73. char ev_name[5];
  74. if (!chip->dev || !chip->to_irq)
  75. return;
  76. handle = ACPI_HANDLE(chip->dev);
  77. if (!handle)
  78. return;
  79. status = acpi_get_event_resources(handle, &buf);
  80. if (ACPI_FAILURE(status))
  81. return;
  82. /* If a gpio interrupt has an acpi event handler method, then
  83. * set up an interrupt handler that calls the acpi event handler
  84. */
  85. for (res = buf.pointer;
  86. res && (res->type != ACPI_RESOURCE_TYPE_END_TAG);
  87. res = ACPI_NEXT_RESOURCE(res)) {
  88. if (res->type != ACPI_RESOURCE_TYPE_GPIO ||
  89. res->data.gpio.connection_type !=
  90. ACPI_RESOURCE_GPIO_TYPE_INT)
  91. continue;
  92. pin = res->data.gpio.pin_table[0];
  93. if (pin > chip->ngpio)
  94. continue;
  95. sprintf(ev_name, "_%c%02X",
  96. res->data.gpio.triggering ? 'E' : 'L', pin);
  97. status = acpi_get_handle(handle, ev_name, &ev_handle);
  98. if (ACPI_FAILURE(status))
  99. continue;
  100. irq = chip->to_irq(chip, pin);
  101. if (irq < 0)
  102. continue;
  103. /* Assume BIOS sets the triggering, so no flags */
  104. ret = devm_request_threaded_irq(chip->dev, irq, NULL,
  105. acpi_gpio_irq_handler,
  106. 0,
  107. "GPIO-signaled-ACPI-event",
  108. ev_handle);
  109. if (ret)
  110. dev_err(chip->dev,
  111. "Failed to request IRQ %d ACPI event handler\n",
  112. irq);
  113. }
  114. }
  115. EXPORT_SYMBOL(acpi_gpiochip_request_interrupts);