diff options
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 134 |
1 files changed, 41 insertions, 93 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index eb4528c87c0b..e2232cbcec8b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -58,58 +58,6 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) return ACPI_HANDLE(gc->parent) == data; } -#ifdef CONFIG_PINCTRL -/** - * acpi_gpiochip_pin_to_gpio_offset() - translates ACPI GPIO to Linux GPIO - * @gdev: GPIO device - * @pin: ACPI GPIO pin number from GpioIo/GpioInt resource - * - * Function takes ACPI GpioIo/GpioInt pin number as a parameter and - * translates it to a corresponding offset suitable to be passed to a - * GPIO controller driver. - * - * Typically the returned offset is same as @pin, but if the GPIO - * controller uses pin controller and the mapping is not contiguous the - * offset might be different. - */ -static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev, int pin) -{ - struct gpio_pin_range *pin_range; - - /* If there are no ranges in this chip, use 1:1 mapping */ - if (list_empty(&gdev->pin_ranges)) - return pin; - - list_for_each_entry(pin_range, &gdev->pin_ranges, node) { - const struct pinctrl_gpio_range *range = &pin_range->range; - int i; - - if (range->pins) { - for (i = 0; i < range->npins; i++) { - if (range->pins[i] == pin) - return range->base + i - gdev->base; - } - } else { - if (pin >= range->pin_base && - pin < range->pin_base + range->npins) { - unsigned gpio_base; - - gpio_base = range->base - gdev->base; - return gpio_base + pin - range->pin_base; - } - } - } - - return -EINVAL; -} -#else -static inline int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev, - int pin) -{ - return pin; -} -#endif - /** * 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") @@ -125,7 +73,6 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin) struct gpio_chip *chip; acpi_handle handle; acpi_status status; - int offset; status = acpi_get_handle(NULL, path, &handle); if (ACPI_FAILURE(status)) @@ -135,11 +82,7 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin) if (!chip) return ERR_PTR(-EPROBE_DEFER); - offset = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin); - if (offset < 0) - return ERR_PTR(offset); - - return gpiochip_get_desc(chip, offset); + return gpiochip_get_desc(chip, pin); } static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) @@ -216,10 +159,6 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, if (!handler) return AE_OK; - pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin); - if (pin < 0) - return AE_BAD_PARAMETER; - desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event"); if (IS_ERR(desc)) { dev_err(chip->parent, "Failed to request GPIO\n"); @@ -414,7 +353,8 @@ EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios); static bool acpi_get_driver_gpio_data(struct acpi_device *adev, const char *name, int index, - struct acpi_reference_args *args) + struct acpi_reference_args *args, + unsigned int *quirks) { const struct acpi_gpio_mapping *gm; @@ -430,6 +370,8 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev, args->args[1] = par->line_index; args->args[2] = par->active_low; args->nargs = 3; + + *quirks = gm->quirks; return true; } @@ -461,8 +403,8 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio) } } -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, enum gpiod_flags update) { int ret = 0; @@ -489,12 +431,31 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) return ret; } +int +acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info) +{ + struct device *dev = &info->adev->dev; + enum gpiod_flags old = *flags; + int ret; + + ret = __acpi_gpio_update_gpiod_flags(&old, info->flags); + if (info->quirks & ACPI_GPIO_QUIRK_NO_IO_RESTRICTION) { + if (ret) + dev_warn(dev, FW_BUG "GPIO not in correct mode, fixing\n"); + } else { + if (ret) + dev_dbg(dev, "Override GPIO initialization flags\n"); + *flags = old; + } + + return ret; +} + struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; int pin_index; bool active_low; - struct acpi_device *adev; struct gpio_desc *desc; int n; }; @@ -531,8 +492,8 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) lookup->info.triggering = agpio->triggering; } else { lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio); + lookup->info.polarity = lookup->active_low; } - } return 1; @@ -541,12 +502,13 @@ 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) { + struct acpi_device *adev = lookup->info.adev; struct list_head res_list; int ret; INIT_LIST_HEAD(&res_list); - ret = acpi_dev_get_resources(lookup->adev, &res_list, + ret = acpi_dev_get_resources(adev, &res_list, acpi_populate_gpio_lookup, lookup); if (ret < 0) @@ -557,11 +519,8 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, if (!lookup->desc) return -ENOENT; - if (info) { + if (info) *info = lookup->info; - if (lookup->active_low) - info->polarity = lookup->active_low; - } return 0; } @@ -570,6 +529,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, struct acpi_gpio_lookup *lookup) { struct acpi_reference_args args; + unsigned int quirks = 0; int ret; memset(&args, 0, sizeof(args)); @@ -581,14 +541,14 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, if (!adev) return ret; - if (!acpi_get_driver_gpio_data(adev, propname, index, &args)) + if (!acpi_get_driver_gpio_data(adev, propname, index, &args, + &quirks)) return ret; } /* * The property was found and resolved, so need to lookup the GPIO based * on returned args. */ - lookup->adev = args.adev; if (args.nargs != 3) return -EPROTO; @@ -596,6 +556,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, lookup->pin_index = args.args[1]; lookup->active_low = !!args.args[2]; + lookup->info.adev = args.adev; + lookup->info.quirks = quirks; return 0; } @@ -643,11 +605,11 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, return ERR_PTR(ret); dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n", - dev_name(&lookup.adev->dev), lookup.index, + dev_name(&lookup.info.adev->dev), lookup.index, lookup.pin_index, lookup.active_low); } else { dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); - lookup.adev = adev; + lookup.info.adev = adev; } ret = acpi_gpio_resource_lookup(&lookup, info); @@ -664,7 +626,6 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, struct acpi_gpio_info info; struct gpio_desc *desc; char propname[32]; - int err; int i; /* Try first from _DSD */ @@ -703,10 +664,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, if (info.polarity == GPIO_ACTIVE_LOW) *lookupflags |= GPIO_ACTIVE_LOW; - err = acpi_gpio_update_gpiod_flags(dflags, info.flags); - if (err) - dev_dbg(dev, "Override GPIO initialization flags\n"); - + acpi_gpio_update_gpiod_flags(dflags, &info); return desc; } @@ -852,12 +810,6 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, struct gpio_desc *desc; bool found; - pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin); - if (pin < 0) { - status = AE_BAD_PARAMETER; - goto out; - } - mutex_lock(&achip->conn_lock); found = false; @@ -990,11 +942,7 @@ static struct gpio_desc *acpi_gpiochip_parse_own_gpio( if (ret < 0) return ERR_PTR(ret); - ret = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, gpios[0]); - if (ret < 0) - return ERR_PTR(ret); - - desc = gpiochip_get_desc(chip, ret); + desc = gpiochip_get_desc(chip, gpios[0]); if (IS_ERR(desc)) return desc; @@ -1074,7 +1022,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip) } if (!chip->names) - devprop_gpiochip_set_names(chip); + devprop_gpiochip_set_names(chip, dev_fwnode(chip->parent)); acpi_gpiochip_request_regions(acpi_gpio); acpi_gpiochip_scan_gpios(acpi_gpio); |