diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
| -rw-r--r-- | drivers/gpio/gpiolib.c | 97 | 
1 files changed, 62 insertions, 35 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bf4bd1d120c3..980c1f87866a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -190,7 +190,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_direction);   */  static int gpiochip_add_to_list(struct gpio_chip *chip)  { -	struct list_head *pos = &gpio_chips; +	struct list_head *pos;  	struct gpio_chip *_chip;  	int err = 0; @@ -287,7 +287,13 @@ int gpiochip_add(struct gpio_chip *chip)  	INIT_LIST_HEAD(&chip->pin_ranges);  #endif -	of_gpiochip_add(chip); +	if (!chip->owner && chip->dev && chip->dev->driver) +		chip->owner = chip->dev->driver->owner; + +	status = of_gpiochip_add(chip); +	if (status) +		goto err_remove_chip; +  	acpi_gpiochip_add(chip);  	status = gpiochip_sysfs_register(chip); @@ -443,8 +449,8 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,  		 * The parent irqchip is already using the chip_data for this  		 * irqchip, so our callbacks simply use the handler_data.  		 */ -		irq_set_handler_data(parent_irq, gpiochip); -		irq_set_chained_handler(parent_irq, parent_handler); +		irq_set_chained_handler_and_data(parent_irq, parent_handler, +						 gpiochip);  		gpiochip->irq_parent = parent_irq;  	} @@ -456,12 +462,6 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,  }  EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); -/* - * This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpiochip_irq_lock_class; -  /**   * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip   * @d: the irqdomain used by this irqchip @@ -478,16 +478,17 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,  	struct gpio_chip *chip = d->host_data;  	irq_set_chip_data(irq, chip); -	irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); +	/* +	 * This lock class tells lockdep that GPIO irqs are in a different +	 * category than their parents, so it won't report false recursion. +	 */ +	irq_set_lockdep_class(irq, chip->lock_key);  	irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);  	/* Chips that can sleep need nested thread handlers */  	if (chip->can_sleep && !chip->irq_not_threaded)  		irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM -	set_irq_flags(irq, IRQF_VALID); -#else  	irq_set_noprobe(irq); -#endif +  	/*  	 * No set-up of the hardware will happen if IRQ_TYPE_NONE  	 * is passed as default type. @@ -502,9 +503,6 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)  {  	struct gpio_chip *chip = d->host_data; -#ifdef CONFIG_ARM -	set_irq_flags(irq, 0); -#endif  	if (chip->can_sleep)  		irq_set_nested_thread(irq, 0);  	irq_set_chip_and_handler(irq, NULL, NULL); @@ -522,10 +520,14 @@ static int gpiochip_irq_reqres(struct irq_data *d)  {  	struct gpio_chip *chip = irq_data_get_irq_chip_data(d); +	if (!try_module_get(chip->owner)) +		return -ENODEV; +  	if (gpiochip_lock_as_irq(chip, d->hwirq)) {  		chip_err(chip,  			"unable to lock HW IRQ %lu for IRQ\n",  			d->hwirq); +		module_put(chip->owner);  		return -EINVAL;  	}  	return 0; @@ -536,6 +538,7 @@ static void gpiochip_irq_relres(struct irq_data *d)  	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);  	gpiochip_unlock_as_irq(chip, d->hwirq); +	module_put(chip->owner);  }  static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) @@ -584,6 +587,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)   * @handler: the irq handler to use (often a predefined irq core function)   * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE   * to have the core avoid setting up any default type in the hardware. + * @lock_key: lockdep class   *   * This function closely associates a certain irqchip with a certain   * gpiochip, providing an irq domain to translate the local IRQs to @@ -599,11 +603,12 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)   * the pins on the gpiochip can generate a unique IRQ. Everything else   * need to be open coded.   */ -int gpiochip_irqchip_add(struct gpio_chip *gpiochip, -			 struct irq_chip *irqchip, -			 unsigned int first_irq, -			 irq_flow_handler_t handler, -			 unsigned int type) +int _gpiochip_irqchip_add(struct gpio_chip *gpiochip, +			  struct irq_chip *irqchip, +			  unsigned int first_irq, +			  irq_flow_handler_t handler, +			  unsigned int type, +			  struct lock_class_key *lock_key)  {  	struct device_node *of_node;  	unsigned int offset; @@ -629,6 +634,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,  	gpiochip->irq_handler = handler;  	gpiochip->irq_default_type = type;  	gpiochip->to_irq = gpiochip_to_irq; +	gpiochip->lock_key = lock_key;  	gpiochip->irqdomain = irq_domain_add_simple(of_node,  					gpiochip->ngpio, first_irq,  					&gpiochip_domain_ops, gpiochip); @@ -636,8 +642,16 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,  		gpiochip->irqchip = NULL;  		return -EINVAL;  	} -	irqchip->irq_request_resources = gpiochip_irq_reqres; -	irqchip->irq_release_resources = gpiochip_irq_relres; + +	/* +	 * It is possible for a driver to override this, but only if the +	 * alternative functions are both implemented. +	 */ +	if (!irqchip->irq_request_resources && +	    !irqchip->irq_release_resources) { +		irqchip->irq_request_resources = gpiochip_irq_reqres; +		irqchip->irq_release_resources = gpiochip_irq_relres; +	}  	/*  	 * Prepare the mapping since the irqchip shall be orthogonal to @@ -658,7 +672,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,  	return 0;  } -EXPORT_SYMBOL_GPL(gpiochip_irqchip_add); +EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add);  #else /* CONFIG_GPIOLIB_IRQCHIP */ @@ -671,7 +685,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}  /**   * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping   * @chip: the gpiochip to add the range for - * @pinctrl: the dev_name() of the pin controller to map to + * @pctldev: the pin controller to map to   * @gpio_offset: the start offset in the current gpio_chip number space   * @pin_group: name of the pin group inside the pin controller   */ @@ -1672,6 +1686,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table)  	mutex_unlock(&gpio_lookup_lock);  } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ +	mutex_lock(&gpio_lookup_lock); + +	list_del(&table->list); + +	mutex_unlock(&gpio_lookup_lock); +} +  static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,  				      unsigned int idx,  				      enum gpio_lookup_flags *flags) @@ -1894,12 +1921,12 @@ EXPORT_SYMBOL_GPL(gpiod_count);   * dev, -ENOENT if no GPIO has been assigned to the requested function, or   * another IS_ERR() code if an error occurred while trying to acquire the GPIO.   */ -struct gpio_desc *__must_check __gpiod_get(struct device *dev, const char *con_id, +struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id,  					 enum gpiod_flags flags)  {  	return gpiod_get_index(dev, con_id, 0, flags);  } -EXPORT_SYMBOL_GPL(__gpiod_get); +EXPORT_SYMBOL_GPL(gpiod_get);  /**   * gpiod_get_optional - obtain an optional GPIO for a given GPIO function @@ -1911,13 +1938,13 @@ EXPORT_SYMBOL_GPL(__gpiod_get);   * the requested function it will return NULL. This is convenient for drivers   * that need to handle optional GPIOs.   */ -struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev, +struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,  						  const char *con_id,  						  enum gpiod_flags flags)  {  	return gpiod_get_index_optional(dev, con_id, 0, flags);  } -EXPORT_SYMBOL_GPL(__gpiod_get_optional); +EXPORT_SYMBOL_GPL(gpiod_get_optional);  /** @@ -1974,7 +2001,7 @@ static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,   * requested function and/or index, or another IS_ERR() code if an error   * occurred while trying to acquire the GPIO.   */ -struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, +struct gpio_desc *__must_check gpiod_get_index(struct device *dev,  					       const char *con_id,  					       unsigned int idx,  					       enum gpiod_flags flags) @@ -2023,7 +2050,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,  	return desc;  } -EXPORT_SYMBOL_GPL(__gpiod_get_index); +EXPORT_SYMBOL_GPL(gpiod_get_index);  /**   * fwnode_get_named_gpiod - obtain a GPIO from firmware node @@ -2092,7 +2119,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);   * specified index was assigned to the requested function it will return NULL.   * This is convenient for drivers that need to handle optional GPIOs.   */ -struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev, +struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,  							const char *con_id,  							unsigned int index,  							enum gpiod_flags flags) @@ -2107,7 +2134,7 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,  	return desc;  } -EXPORT_SYMBOL_GPL(__gpiod_get_index_optional); +EXPORT_SYMBOL_GPL(gpiod_get_index_optional);  /**   * gpiod_hog - Hog the specified GPIO desc given the provided flags  |