// SPDX-License-Identifier: GPL-2.0 /* * ACPI helpers for GPIO API * * Copyright (C) 2012, Intel Corporation * Authors: Mathias Nyman <[email protected]> * Mika Westerberg <[email protected]> */ #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/errno.h> #include <linux/export.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/mutex.h> #include <linux/pinctrl/pinctrl.h> #include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> #include <linux/gpio/machine.h> #include "gpiolib.h" #include "gpiolib-acpi.h" static int run_edge_events_on_boot = …; module_param(run_edge_events_on_boot, int, 0444); MODULE_PARM_DESC(…) …; static char *ignore_wake; module_param(ignore_wake, charp, 0444); MODULE_PARM_DESC(…) …; static char *ignore_interrupt; module_param(ignore_interrupt, charp, 0444); MODULE_PARM_DESC(…) …; struct acpi_gpiolib_dmi_quirk { … }; /** * struct acpi_gpio_event - ACPI GPIO event handler data * * @node: list-entry of the events list of the struct acpi_gpio_chip * @handle: handle of ACPI method to execute when the IRQ triggers * @handler: handler function to pass to request_irq() when requesting the IRQ * @pin: GPIO pin number on the struct gpio_chip * @irq: Linux IRQ number for the event, for request_irq() / free_irq() * @irqflags: flags to pass to request_irq() when requesting the IRQ * @irq_is_wake: If the ACPI flags indicate the IRQ is a wakeup source * @irq_requested:True if request_irq() has been done * @desc: struct gpio_desc for the GPIO pin for this event */ struct acpi_gpio_event { … }; struct acpi_gpio_connection { … }; struct acpi_gpio_chip { … }; /** * struct acpi_gpio_info - ACPI GPIO specific information * @adev: reference to ACPI device which consumes GPIO resource * @flags: GPIO initialization flags * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo * @pin_config: pin bias as provided by ACPI * @polarity: interrupt polarity as provided by ACPI * @triggering: triggering type as provided by ACPI * @wake_capable: wake capability as provided by ACPI * @debounce: debounce timeout as provided by ACPI * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping */ struct acpi_gpio_info { … }; /* * For GPIO chips which call acpi_gpiochip_request_interrupts() before late_init * (so builtin drivers) we register the ACPI GpioInt IRQ handlers from a * late_initcall_sync() handler, so that other builtin drivers can register their * OpRegions before the event handlers can run. This list contains GPIO chips * for which the acpi_gpiochip_request_irqs() call has been deferred. */ static DEFINE_MUTEX(acpi_gpio_deferred_req_irqs_lock); static LIST_HEAD(acpi_gpio_deferred_req_irqs_list); static bool acpi_gpio_deferred_req_irqs_done; static int acpi_gpiochip_find(struct gpio_chip *gc, const void *data) { … } /** * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1") * @pin: ACPI GPIO pin number (0-based, controller-relative) * * Return: GPIO descriptor to use with Linux generic GPIO API, or ERR_PTR * error value. Specifically returns %-EPROBE_DEFER if the referenced GPIO * controller does not have GPIO chip registered at the moment. This is to * support probe deferral. */ static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin) { … } static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) { … } static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data) { … } static void acpi_gpio_chip_dh(acpi_handle handle, void *data) { … } bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio) { … } EXPORT_SYMBOL_GPL(…); /** * acpi_gpio_get_io_resource - Fetch details of an ACPI resource if it is a GPIO * I/O resource or return False if not. * @ares: Pointer to the ACPI resource to fetch * @agpio: Pointer to a &struct acpi_resource_gpio to store the output pointer */ bool acpi_gpio_get_io_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio) { … } EXPORT_SYMBOL_GPL(…); static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio, struct acpi_gpio_event *event) { … } static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio) { … } static enum gpiod_flags acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity) { … } static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip, struct acpi_resource_gpio *agpio, unsigned int index, const char *label) { … } static bool acpi_gpio_in_ignore_list(const char *ignore_list, const char *controller_in, unsigned int pin_in) { … } static bool acpi_gpio_irq_is_wake(struct device *parent, const struct acpi_resource_gpio *agpio) { … } /* Always returns AE_OK so that we keep looping over the resources */ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, void *context) { … } /** * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events * @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 * chip's interrupt handler. acpi_gpiochip_request_interrupts() finds out which * GPIO pins have ACPI event methods and assigns interrupt handlers that calls * the ACPI event methods for those pins. */ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { … } EXPORT_SYMBOL_GPL(…); /** * acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts. * @chip: GPIO chip * * Free interrupts associated with GPIO ACPI event method for the given * GPIO chip. */ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { … } EXPORT_SYMBOL_GPL(…); int acpi_dev_add_driver_gpios(struct acpi_device *adev, const struct acpi_gpio_mapping *gpios) { … } EXPORT_SYMBOL_GPL(…); void acpi_dev_remove_driver_gpios(struct acpi_device *adev) { … } EXPORT_SYMBOL_GPL(…); static void acpi_dev_release_driver_gpios(void *adev) { … } int devm_acpi_dev_add_driver_gpios(struct device *dev, const struct acpi_gpio_mapping *gpios) { … } EXPORT_SYMBOL_GPL(…); static bool acpi_get_driver_gpio_data(struct acpi_device *adev, const char *name, int index, struct fwnode_reference_args *args, unsigned int *quirks) { … } static int __acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) { … } static int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info) { … } static int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, struct acpi_gpio_info *info) { … } struct acpi_gpio_lookup { … }; static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) { … } static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, struct acpi_gpio_info *info) { … } static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, const char *propname, int index, struct acpi_gpio_lookup *lookup) { … } /** * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources * @adev: pointer to a ACPI device to get GPIO from * @propname: Property name of the GPIO (optional) * @index: index of GpioIo/GpioInt resource (starting from %0) * @info: info pointer to fill in (optional) * * Function goes through ACPI resources for @adev and based on @index looks * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor, * and returns it. @index matches GpioIo/GpioInt resources only so if there * are total %3 GPIO resources, the index goes from %0 to %2. * * If @propname is specified the GPIO is looked using device property. In * that case @index is used to select the GPIO entry in the property value * (in case of multiple). * * If the GPIO cannot be translated or there is an error, an ERR_PTR is * returned. * * Note: if the GPIO resource has multiple entries in the pin list, this * function only returns the first. */ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname, int index, struct acpi_gpio_info *info) { … } /** * acpi_get_gpiod_from_data() - get a GPIO descriptor from ACPI data node * @fwnode: pointer to an ACPI firmware node to get the GPIO information from * @propname: Property name of the GPIO * @index: index of GpioIo/GpioInt resource (starting from %0) * @info: info pointer to fill in (optional) * * This function uses the property-based GPIO lookup to get to the GPIO * resource with the relevant information from a data-only ACPI firmware node * and uses that to obtain the GPIO descriptor to return. * * If the GPIO cannot be translated or there is an error an ERR_PTR is * returned. */ static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode, const char *propname, int index, struct acpi_gpio_info *info) { … } static bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id) { … } static struct gpio_desc * __acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx, bool can_fallback, struct acpi_gpio_info *info) { … } struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, unsigned long *lookupflags) { … } /** * acpi_dev_gpio_irq_wake_get_by() - Find GpioInt and translate it to Linux IRQ number * @adev: pointer to a ACPI device to get IRQ from * @con_id: optional name of GpioInt resource * @index: index of GpioInt resource (starting from %0) * @wake_capable: Set to true if the IRQ is wake capable * * If the device has one or more GpioInt resources, this function can be * used to translate from the GPIO offset in the resource to the Linux IRQ * number. * * The function is idempotent, though each time it runs it will configure GPIO * pin direction according to the flags in GpioInt resource. * * The function takes optional @con_id parameter. If the resource has * a @con_id in a property, then only those will be taken into account. * * The GPIO is considered wake capable if the GpioInt resource specifies * SharedAndWake or ExclusiveAndWake. * * Return: Linux IRQ number (> %0) on success, negative errno on failure. */ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *con_id, int index, bool *wake_capable) { … } EXPORT_SYMBOL_GPL(…); static acpi_status acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, u32 bits, u64 *value, void *handler_context, void *region_context) { … } static void acpi_gpiochip_request_regions(struct acpi_gpio_chip *achip) { … } static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip) { … } static struct gpio_desc * acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode, const char **name, unsigned long *lflags, enum gpiod_flags *dflags) { … } static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) { … } void acpi_gpiochip_add(struct gpio_chip *chip) { … } void acpi_gpiochip_remove(struct gpio_chip *chip) { … } static int acpi_gpio_package_count(const union acpi_object *obj) { … } static int acpi_find_gpio_count(struct acpi_resource *ares, void *data) { … } /** * acpi_gpio_count - count the GPIOs associated with a firmware node / function * @fwnode: firmware node of the GPIO consumer * @con_id: function within the GPIO consumer * * Return: * The number of GPIOs associated with a firmware node / function or %-ENOENT, * if no GPIO has been assigned to the requested function. */ int acpi_gpio_count(const struct fwnode_handle *fwnode, const char *con_id) { … } /* Run deferred acpi_gpiochip_request_irqs() */ static int __init acpi_gpio_handle_deferred_request_irqs(void) { … } /* We must use _sync so that this runs after the first deferred_probe run */ late_initcall_sync(acpi_gpio_handle_deferred_request_irqs); static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = …; static int __init acpi_gpio_setup_params(void) { … } /* Directly after dmi_setup() which runs as core_initcall() */ postcore_initcall(acpi_gpio_setup_params);