diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
| -rw-r--r-- | drivers/gpio/gpiolib.c | 73 | 
1 files changed, 58 insertions, 15 deletions
| diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index abfbf546d159..3859911b61e9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -422,8 +422,16 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)  	if (count > chip->ngpio)  		count = chip->ngpio; -	for (i = 0; i < count; i++) -		gdev->descs[i].name = names[chip->offset + i]; +	for (i = 0; i < count; i++) { +		/* +		 * Allow overriding "fixed" names provided by the GPIO +		 * provider. The "fixed" names are more often than not +		 * generic and less informative than the names given in +		 * device properties. +		 */ +		if (names[chip->offset + i] && names[chip->offset + i][0]) +			gdev->descs[i].name = names[chip->offset + i]; +	}  	kfree(names); @@ -593,12 +601,18 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,  			       struct lock_class_key *lock_key,  			       struct lock_class_key *request_key)  { -	struct fwnode_handle *fwnode = gc->parent ? dev_fwnode(gc->parent) : NULL; -	unsigned long	flags; -	int		ret = 0; -	unsigned	i; -	int		base = gc->base; +	struct fwnode_handle *fwnode = NULL;  	struct gpio_device *gdev; +	unsigned long flags; +	int base = gc->base; +	unsigned int i; +	int ret = 0; +	u32 ngpios; + +	if (gc->fwnode) +		fwnode = gc->fwnode; +	else if (gc->parent) +		fwnode = dev_fwnode(gc->parent);  	/*  	 * First: allocate and populate the internal stat container, and @@ -646,6 +660,26 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,  		goto err_free_dev_name;  	} +	/* +	 * Try the device properties if the driver didn't supply the number +	 * of GPIO lines. +	 */ +	if (gc->ngpio == 0) { +		ret = device_property_read_u32(&gdev->dev, "ngpios", &ngpios); +		if (ret == -ENODATA) +			/* +			 * -ENODATA means that there is no property found and +			 * we want to issue the error message to the user. +			 * Besides that, we want to return different error code +			 * to state that supplied value is not valid. +			 */ +			ngpios = 0; +		else if (ret) +			goto err_free_descs; + +		gc->ngpio = ngpios; +	} +  	if (gc->ngpio == 0) {  		chip_err(gc, "tried to insert a GPIO chip with zero lines\n");  		ret = -EINVAL; @@ -708,10 +742,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,  	INIT_LIST_HEAD(&gdev->pin_ranges);  #endif -	if (gc->names) +	if (gc->names) {  		ret = gpiochip_set_desc_names(gc); -	else -		ret = devprop_gpiochip_set_names(gc); +		if (ret) +			goto err_remove_from_list; +	} +	ret = devprop_gpiochip_set_names(gc);  	if (ret)  		goto err_remove_from_list; @@ -3487,11 +3523,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);   */  void gpiod_add_lookup_table(struct gpiod_lookup_table *table)  { -	mutex_lock(&gpio_lookup_lock); - -	list_add_tail(&table->list, &gpio_lookup_list); - -	mutex_unlock(&gpio_lookup_lock); +	gpiod_add_lookup_tables(&table, 1);  }  EXPORT_SYMBOL_GPL(gpiod_add_lookup_table); @@ -3540,6 +3572,17 @@ void gpiod_add_hogs(struct gpiod_hog *hogs)  }  EXPORT_SYMBOL_GPL(gpiod_add_hogs); +void gpiod_remove_hogs(struct gpiod_hog *hogs) +{ +	struct gpiod_hog *hog; + +	mutex_lock(&gpio_machine_hogs_mutex); +	for (hog = &hogs[0]; hog->chip_label; hog++) +		list_del(&hog->list); +	mutex_unlock(&gpio_machine_hogs_mutex); +} +EXPORT_SYMBOL_GPL(gpiod_remove_hogs); +  static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)  {  	const char *dev_id = dev ? dev_name(dev) : NULL; |