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; |