diff options
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 115 |
1 files changed, 76 insertions, 39 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 30d0baf7ddae..c9fc9e232aaf 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -24,13 +24,13 @@ * * @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: irq_handler to pass to request_irq when requesting the IRQ - * @pin: GPIO pin number on the gpio_chip - * @irq: Linux IRQ number for the event, for request_ / free_irq - * @irqflags: flags to pass to request_irq when requesting the IRQ + * @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: gpio_desc for the GPIO pin for this event + * @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 list_head node; @@ -65,10 +65,10 @@ struct acpi_gpio_chip { }; /* - * For gpiochips which call acpi_gpiochip_request_interrupts() before late_init + * 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 gpiochips + * 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); @@ -90,7 +90,7 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) * * 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 gpiochip registered at the moment. This is to + * 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, int pin) @@ -287,9 +287,9 @@ fail_free_desc: * * 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. + * 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) { @@ -444,8 +444,6 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev, static enum gpiod_flags acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio) { - bool pull_up = agpio->pin_config == ACPI_PIN_CONFIG_PULLUP; - switch (agpio->io_restriction) { case ACPI_IO_RESTRICT_INPUT: return GPIOD_IN; @@ -454,16 +452,26 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio) * ACPI GPIO resources don't contain an initial value for the * GPIO. Therefore we deduce that value from the pull field * instead. If the pin is pulled up we assume default to be - * high, otherwise low. + * high, if it is pulled down we assume default to be low, + * otherwise we leave pin untouched. */ - return pull_up ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; + switch (agpio->pin_config) { + case ACPI_PIN_CONFIG_PULLUP: + return GPIOD_OUT_HIGH; + case ACPI_PIN_CONFIG_PULLDOWN: + return GPIOD_OUT_LOW; + default: + break; + } default: - /* - * Assume that the BIOS has configured the direction and pull - * accordingly. - */ - return GPIOD_ASIS; + break; } + + /* + * Assume that the BIOS has configured the direction and pull + * accordingly. + */ + return GPIOD_ASIS; } static int @@ -517,6 +525,26 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *inf return ret; } +int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, + struct acpi_gpio_info *info) +{ + switch (info->pin_config) { + case ACPI_PIN_CONFIG_PULLUP: + *lookupflags |= GPIO_PULL_UP; + break; + case ACPI_PIN_CONFIG_PULLDOWN: + *lookupflags |= GPIO_PULL_DOWN; + break; + default: + break; + } + + if (info->polarity == GPIO_ACTIVE_LOW) + *lookupflags |= GPIO_ACTIVE_LOW; + + return 0; +} + struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; @@ -550,6 +578,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, agpio->pin_table[pin_index]); + lookup->info.pin_config = agpio->pin_config; lookup->info.gpioint = gpioint; /* @@ -653,7 +682,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, * 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 + * 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 @@ -696,7 +725,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, - enum gpio_lookup_flags *lookupflags) + unsigned long *lookupflags) { struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_gpio_info info; @@ -737,10 +766,8 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, return ERR_PTR(-ENOENT); } - if (info.polarity == GPIO_ACTIVE_LOW) - *lookupflags |= GPIO_ACTIVE_LOW; - acpi_gpio_update_gpiod_flags(dflags, &info); + acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info); return desc; } @@ -751,10 +778,13 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, * @index: index of GpioIo/GpioInt resource (starting from %0) * @info: info pointer to fill in (optional) * - * If @fwnode is an ACPI device object, call %acpi_get_gpiod_by_index() for it. - * Otherwise (ie. it is a data-only non-device object), use the property-based + * If @fwnode is an ACPI device object, call acpi_get_gpiod_by_index() for it. + * Otherwise (i.e. it is a data-only non-device object), use the property-based * GPIO lookup to get to the GPIO resource with the relevant information and use * that to obtain the GPIO descriptor to return. + * + * If the GPIO cannot be translated or there is an error an ERR_PTR is + * returned. */ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, @@ -816,6 +846,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) return PTR_ERR(desc); if (info.gpioint && idx++ == index) { + unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; char label[32]; int irq; @@ -827,7 +858,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) return irq; snprintf(label, sizeof(label), "GpioInt() %d", index); - ret = gpiod_configure_flags(desc, label, 0, info.flags); + ret = gpiod_configure_flags(desc, label, lflags, info.flags); if (ret < 0) return ret; @@ -992,16 +1023,19 @@ 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 int *lflags, unsigned int *dflags) +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) { struct gpio_chip *chip = achip->chip; struct gpio_desc *desc; u32 gpios[2]; int ret; - *lflags = 0; + *lflags = GPIO_LOOKUP_FLAGS_DEFAULT; *dflags = 0; *name = NULL; @@ -1037,7 +1071,8 @@ static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) struct fwnode_handle *fwnode; device_for_each_child_node(chip->parent, fwnode) { - unsigned int lflags, dflags; + unsigned long lflags; + enum gpiod_flags dflags; struct gpio_desc *desc; const char *name; int ret; @@ -1158,11 +1193,13 @@ static int acpi_find_gpio_count(struct acpi_resource *ares, void *data) } /** - * acpi_gpio_count - return the number of GPIOs associated with a - * device / function or -ENOENT if no GPIO has been - * assigned to the requested function. - * @dev: GPIO consumer, can be NULL for system-global GPIOs + * acpi_gpio_count - count the GPIOs associated with a device / function + * @dev: GPIO consumer, can be %NULL for system-global GPIOs * @con_id: function within the GPIO consumer + * + * Return: + * The number of GPIOs associated with a device / function or %-ENOENT, + * if no GPIO has been assigned to the requested function. */ int acpi_gpio_count(struct device *dev, const char *con_id) { |