diff options
Diffstat (limited to 'drivers/gpio/gpiolib-of.c')
| -rw-r--r-- | drivers/gpio/gpiolib-of.c | 66 | 
1 files changed, 59 insertions, 7 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 42a4bb7cf49a..d22dcc38179d 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -196,21 +196,68 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,  }  /** + * of_gpiochip_set_names() - set up the names of the lines + * @chip: GPIO chip whose lines should be named, if possible + */ +static void of_gpiochip_set_names(struct gpio_chip *gc) +{ +	struct gpio_device *gdev = gc->gpiodev; +	struct device_node *np = gc->of_node; +	int i; +	int nstrings; + +	nstrings = of_property_count_strings(np, "gpio-line-names"); +	if (nstrings <= 0) +		/* Lines names not present */ +		return; + +	/* This is normally not what you want */ +	if (gdev->ngpio != nstrings) +		dev_info(&gdev->dev, "gpio-line-names specifies %d line " +			 "names but there are %d lines on the chip\n", +			 nstrings, gdev->ngpio); + +	/* +	 * Make sure to not index beyond the end of the number of descriptors +	 * of the GPIO device. +	 */ +	for (i = 0; i < gdev->ngpio; i++) { +		const char *name; +		int ret; + +		ret = of_property_read_string_index(np, +						    "gpio-line-names", +						    i, +						    &name); +		if (ret) { +			if (ret != -ENODATA) +                                dev_err(&gdev->dev, +                                        "unable to name line %d: %d\n", +                                        i, ret); +			break; +		} +		gdev->descs[i].name = name; +	} +} + +/**   * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions   * @chip:	gpio chip to act on   *   * This is only used by of_gpiochip_add to request/set GPIO initial   * configuration. + * It retures error if it fails otherwise 0 on success.   */ -static void of_gpiochip_scan_gpios(struct gpio_chip *chip) +static int of_gpiochip_scan_gpios(struct gpio_chip *chip)  {  	struct gpio_desc *desc = NULL;  	struct device_node *np;  	const char *name;  	enum gpio_lookup_flags lflags;  	enum gpiod_flags dflags; +	int ret; -	for_each_child_of_node(chip->of_node, np) { +	for_each_available_child_of_node(chip->of_node, np) {  		if (!of_property_read_bool(np, "gpio-hog"))  			continue; @@ -218,9 +265,12 @@ static void of_gpiochip_scan_gpios(struct gpio_chip *chip)  		if (IS_ERR(desc))  			continue; -		if (gpiod_hog(desc, name, lflags, dflags)) -			continue; +		ret = gpiod_hog(desc, name, lflags, dflags); +		if (ret < 0) +			return ret;  	} + +	return 0;  }  /** @@ -440,11 +490,13 @@ int of_gpiochip_add(struct gpio_chip *chip)  	if (status)  		return status; -	of_node_get(chip->of_node); +	/* If the chip defines names itself, these take precedence */ +	if (!chip->names) +		of_gpiochip_set_names(chip); -	of_gpiochip_scan_gpios(chip); +	of_node_get(chip->of_node); -	return 0; +	return of_gpiochip_scan_gpios(chip);  }  void of_gpiochip_remove(struct gpio_chip *chip)  | 
