diff options
Diffstat (limited to 'drivers/gpio')
| -rw-r--r-- | drivers/gpio/gpio-pca953x.c | 78 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 21 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.c | 19 | 
3 files changed, 47 insertions, 71 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 5ea09fd01544..c91d05651596 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -113,8 +113,29 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id);  #ifdef CONFIG_GPIO_PCA953X_IRQ  #include <linux/dmi.h> -#include <linux/gpio.h> -#include <linux/list.h> + +static const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true }; + +static const struct acpi_gpio_mapping pca953x_acpi_irq_gpios[] = { +	{ "irq-gpios", &pca953x_irq_gpios, 1, ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER }, +	{ } +}; + +static int pca953x_acpi_get_irq(struct device *dev) +{ +	int ret; + +	ret = devm_acpi_dev_add_driver_gpios(dev, pca953x_acpi_irq_gpios); +	if (ret) +		dev_warn(dev, "can't add GPIO ACPI mapping\n"); + +	ret = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(dev), "irq-gpios", 0); +	if (ret < 0) +		return ret; + +	dev_info(dev, "ACPI interrupt quirk (IRQ %d)\n", ret); +	return ret; +}  static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {  	{ @@ -133,59 +154,6 @@ static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {  	},  	{}  }; - -#ifdef CONFIG_ACPI -static int pca953x_acpi_get_pin(struct acpi_resource *ares, void *data) -{ -	struct acpi_resource_gpio *agpio; -	int *pin = data; - -	if (acpi_gpio_get_irq_resource(ares, &agpio)) -		*pin = agpio->pin_table[0]; -	return 1; -} - -static int pca953x_acpi_find_pin(struct device *dev) -{ -	struct acpi_device *adev = ACPI_COMPANION(dev); -	int pin = -ENOENT, ret; -	LIST_HEAD(r); - -	ret = acpi_dev_get_resources(adev, &r, pca953x_acpi_get_pin, &pin); -	acpi_dev_free_resource_list(&r); -	if (ret < 0) -		return ret; - -	return pin; -} -#else -static inline int pca953x_acpi_find_pin(struct device *dev) { return -ENXIO; } -#endif - -static int pca953x_acpi_get_irq(struct device *dev) -{ -	int pin, ret; - -	pin = pca953x_acpi_find_pin(dev); -	if (pin < 0) -		return pin; - -	dev_info(dev, "Applying ACPI interrupt quirk (GPIO %d)\n", pin); - -	if (!gpio_is_valid(pin)) -		return -EINVAL; - -	ret = gpio_request(pin, "pca953x interrupt"); -	if (ret) -		return ret; - -	ret = gpio_to_irq(pin); - -	/* When pin is used as an IRQ, no need to keep it requested */ -	gpio_free(pin); - -	return ret; -}  #endif  static const struct acpi_device_id pca953x_acpi_ids[] = { diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index e37a57d0a2f0..1aacd2a5a1fd 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -174,7 +174,7 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,  	int ret, value;  	ret = request_threaded_irq(event->irq, NULL, event->handler, -				   event->irqflags, "ACPI:Event", event); +				   event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);  	if (ret) {  		dev_err(acpi_gpio->chip->parent,  			"Failed to setup interrupt handler for %d\n", @@ -677,6 +677,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)  	if (!lookup->desc) {  		const struct acpi_resource_gpio *agpio = &ares->data.gpio;  		bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; +		struct gpio_desc *desc;  		u16 pin_index;  		if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint) @@ -689,8 +690,12 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)  		if (pin_index >= agpio->pin_table_length)  			return 1; -		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, +		if (lookup->info.quirks & ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER) +			desc = gpio_to_desc(agpio->pin_table[pin_index]); +		else +			desc = acpi_get_gpiod(agpio->resource_source.string_ptr,  					      agpio->pin_table[pin_index]); +		lookup->desc = desc;  		lookup->info.pin_config = agpio->pin_config;  		lookup->info.debounce = agpio->debounce_timeout;  		lookup->info.gpioint = gpioint; @@ -940,8 +945,9 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,  }  /** - * acpi_dev_gpio_irq_get() - Find GpioInt and translate it to Linux IRQ number + * acpi_dev_gpio_irq_get_by() - Find GpioInt and translate it to Linux IRQ number   * @adev: pointer to a ACPI device to get IRQ from + * @name: optional name of GpioInt resource   * @index: index of GpioInt resource (starting from %0)   *   * If the device has one or more GpioInt resources, this function can be @@ -951,9 +957,12 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,   * 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 @name parameter. If the resource has a property + * name, then only those will be taken into account. + *   * Return: Linux IRQ number (> %0) on success, negative errno on failure.   */ -int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) +int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index)  {  	int idx, i;  	unsigned int irq_flags; @@ -963,7 +972,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)  		struct acpi_gpio_info info;  		struct gpio_desc *desc; -		desc = acpi_get_gpiod_by_index(adev, NULL, i, &info); +		desc = acpi_get_gpiod_by_index(adev, name, i, &info);  		/* Ignore -EPROBE_DEFER, it only matters if idx matches */  		if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER) @@ -1008,7 +1017,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)  	}  	return -ENOENT;  } -EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get); +EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get_by);  static acpi_status  acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index adf55db080d8..7ec0822c0505 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -367,22 +367,18 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)   *   * Looks for device property "gpio-line-names" and if it exists assigns   * GPIO line names for the chip. The memory allocated for the assigned - * names belong to the underlying software node and should not be released + * names belong to the underlying firmware node and should not be released   * by the caller.   */  static int devprop_gpiochip_set_names(struct gpio_chip *chip)  {  	struct gpio_device *gdev = chip->gpiodev; -	struct device *dev = chip->parent; +	struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev);  	const char **names;  	int ret, i;  	int count; -	/* GPIO chip may not have a parent device whose properties we inspect. */ -	if (!dev) -		return 0; - -	count = device_property_string_array_count(dev, "gpio-line-names"); +	count = fwnode_property_string_array_count(fwnode, "gpio-line-names");  	if (count < 0)  		return 0; @@ -396,7 +392,7 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)  	if (!names)  		return -ENOMEM; -	ret = device_property_read_string_array(dev, "gpio-line-names", +	ret = fwnode_property_read_string_array(fwnode, "gpio-line-names",  						names, count);  	if (ret < 0) {  		dev_warn(&gdev->dev, "failed to read GPIO line names\n"); @@ -474,9 +470,13 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);  static void gpiodevice_release(struct device *dev)  { -	struct gpio_device *gdev = dev_get_drvdata(dev); +	struct gpio_device *gdev = container_of(dev, struct gpio_device, dev); +	unsigned long flags; +	spin_lock_irqsave(&gpio_lock, flags);  	list_del(&gdev->list); +	spin_unlock_irqrestore(&gpio_lock, flags); +  	ida_free(&gpio_ida, gdev->id);  	kfree_const(gdev->label);  	kfree(gdev->descs); @@ -605,7 +605,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,  		goto err_free_ida;  	device_initialize(&gdev->dev); -	dev_set_drvdata(&gdev->dev, gdev);  	if (gc->parent && gc->parent->driver)  		gdev->owner = gc->parent->driver->owner;  	else if (gc->owner)  | 
