forked from mirrors/linux
		
	gpio: of: Break out OF-only code
The core gpiolib should not contain any OF/device tree-only code. Try to break out the main part of it and push it down into the optional gpiolib-of.c part of the library. Create a local gpiolib-of.h header and move stuff around a bit to get a clean cut. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20190717071001.3858-1-linus.walleij@linaro.org
This commit is contained in:
		
							parent
							
								
									f8650b8ff6
								
							
						
					
					
						commit
						f626d6dfb7
					
				
					 4 changed files with 167 additions and 132 deletions
				
			
		|  | @ -21,6 +21,34 @@ | |||
| #include <linux/gpio/machine.h> | ||||
| 
 | ||||
| #include "gpiolib.h" | ||||
| #include "gpiolib-of.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * This is used by external users of of_gpio_count() from <linux/of_gpio.h> | ||||
|  * | ||||
|  * FIXME: get rid of those external users by converting them to GPIO | ||||
|  * descriptors and let them all use gpiod_get_count() | ||||
|  */ | ||||
| int of_gpio_get_count(struct device *dev, const char *con_id) | ||||
| { | ||||
| 	int ret; | ||||
| 	char propname[32]; | ||||
| 	unsigned int i; | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { | ||||
| 		if (con_id) | ||||
| 			snprintf(propname, sizeof(propname), "%s-%s", | ||||
| 				 con_id, gpio_suffixes[i]); | ||||
| 		else | ||||
| 			snprintf(propname, sizeof(propname), "%s", | ||||
| 				 gpio_suffixes[i]); | ||||
| 
 | ||||
| 		ret = of_gpio_named_count(dev->of_node, propname); | ||||
| 		if (ret > 0) | ||||
| 			break; | ||||
| 	} | ||||
| 	return ret ? ret : -ENOENT; | ||||
| } | ||||
| 
 | ||||
| static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) | ||||
| { | ||||
|  | @ -53,6 +81,23 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, | |||
| 	return gpiochip_get_desc(chip, ret); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * of_gpio_need_valid_mask() - figure out if the OF GPIO driver needs | ||||
|  * to set the .valid_mask | ||||
|  * @dev: the device for the GPIO provider | ||||
|  * @return: true if the valid mask needs to be set | ||||
|  */ | ||||
| bool of_gpio_need_valid_mask(struct gpio_chip *gc) | ||||
| { | ||||
| 	int size; | ||||
| 	struct device_node *np = gc->of_node; | ||||
| 
 | ||||
| 	size = of_property_count_u32_elems(np,  "gpio-reserved-ranges"); | ||||
| 	if (size > 0 && size % 2 == 0) | ||||
| 		return true; | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static void of_gpio_flags_quirks(struct device_node *np, | ||||
| 				 const char *propname, | ||||
| 				 enum of_gpio_flags *flags, | ||||
|  | @ -231,6 +276,75 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, | |||
| } | ||||
| EXPORT_SYMBOL(of_get_named_gpio_flags); | ||||
| 
 | ||||
| /**
 | ||||
|  * gpiod_get_from_of_node() - obtain a GPIO from an OF node | ||||
|  * @node:	handle of the OF node | ||||
|  * @propname:	name of the DT property representing the GPIO | ||||
|  * @index:	index of the GPIO to obtain for the consumer | ||||
|  * @dflags:	GPIO initialization flags | ||||
|  * @label:	label to attach to the requested GPIO | ||||
|  * | ||||
|  * Returns: | ||||
|  * On successful request the GPIO pin is configured in accordance with | ||||
|  * provided @dflags. | ||||
|  * | ||||
|  * In case of error an ERR_PTR() is returned. | ||||
|  */ | ||||
| struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, | ||||
| 					 const char *propname, int index, | ||||
| 					 enum gpiod_flags dflags, | ||||
| 					 const char *label) | ||||
| { | ||||
| 	unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; | ||||
| 	struct gpio_desc *desc; | ||||
| 	enum of_gpio_flags flags; | ||||
| 	bool active_low = false; | ||||
| 	bool single_ended = false; | ||||
| 	bool open_drain = false; | ||||
| 	bool transitory = false; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	desc = of_get_named_gpiod_flags(node, propname, | ||||
| 					index, &flags); | ||||
| 
 | ||||
| 	if (!desc || IS_ERR(desc)) { | ||||
| 		return desc; | ||||
| 	} | ||||
| 
 | ||||
| 	active_low = flags & OF_GPIO_ACTIVE_LOW; | ||||
| 	single_ended = flags & OF_GPIO_SINGLE_ENDED; | ||||
| 	open_drain = flags & OF_GPIO_OPEN_DRAIN; | ||||
| 	transitory = flags & OF_GPIO_TRANSITORY; | ||||
| 
 | ||||
| 	ret = gpiod_request(desc, label); | ||||
| 	if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) | ||||
| 		return desc; | ||||
| 	if (ret) | ||||
| 		return ERR_PTR(ret); | ||||
| 
 | ||||
| 	if (active_low) | ||||
| 		lflags |= GPIO_ACTIVE_LOW; | ||||
| 
 | ||||
| 	if (single_ended) { | ||||
| 		if (open_drain) | ||||
| 			lflags |= GPIO_OPEN_DRAIN; | ||||
| 		else | ||||
| 			lflags |= GPIO_OPEN_SOURCE; | ||||
| 	} | ||||
| 
 | ||||
| 	if (transitory) | ||||
| 		lflags |= GPIO_TRANSITORY; | ||||
| 
 | ||||
| 	ret = gpiod_configure_flags(desc, propname, lflags, dflags); | ||||
| 	if (ret < 0) { | ||||
| 		gpiod_put(desc); | ||||
| 		return ERR_PTR(ret); | ||||
| 	} | ||||
| 
 | ||||
| 	return desc; | ||||
| } | ||||
| EXPORT_SYMBOL(gpiod_get_from_of_node); | ||||
| 
 | ||||
| /*
 | ||||
|  * The SPI GPIO bindings happened before we managed to establish that GPIO | ||||
|  * properties should be named "foo-gpios" so we have this special kludge for | ||||
|  |  | |||
							
								
								
									
										45
									
								
								drivers/gpio/gpiolib-of.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								drivers/gpio/gpiolib-of.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| 
 | ||||
| #ifndef GPIOLIB_OF_H | ||||
| #define GPIOLIB_OF_H | ||||
| 
 | ||||
| struct gpio_chip; | ||||
| enum of_gpio_flags; | ||||
| 
 | ||||
| #ifdef CONFIG_OF_GPIO | ||||
| struct gpio_desc *of_find_gpio(struct device *dev, | ||||
| 			       const char *con_id, | ||||
| 			       unsigned int idx, | ||||
| 			       unsigned long *lookupflags); | ||||
| struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, | ||||
| 		   const char *list_name, int index, enum of_gpio_flags *flags); | ||||
| int of_gpiochip_add(struct gpio_chip *gc); | ||||
| void of_gpiochip_remove(struct gpio_chip *gc); | ||||
| int of_gpio_get_count(struct device *dev, const char *con_id); | ||||
| bool of_gpio_need_valid_mask(struct gpio_chip *gc); | ||||
| #else | ||||
| static inline struct gpio_desc *of_find_gpio(struct device *dev, | ||||
| 					     const char *con_id, | ||||
| 					     unsigned int idx, | ||||
| 					     unsigned long *lookupflags) | ||||
| { | ||||
| 	return ERR_PTR(-ENOENT); | ||||
| } | ||||
| static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, | ||||
| 		   const char *list_name, int index, enum of_gpio_flags *flags) | ||||
| { | ||||
| 	return ERR_PTR(-ENOENT); | ||||
| } | ||||
| static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } | ||||
| static inline void of_gpiochip_remove(struct gpio_chip *gc) { } | ||||
| static inline int of_gpio_get_count(struct device *dev, const char *con_id) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| static inline bool of_gpio_need_valid_mask(struct gpio_chip *gc) | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
| #endif /* CONFIG_OF_GPIO */ | ||||
| 
 | ||||
| #endif /* GPIOLIB_OF_H */ | ||||
|  | @ -11,7 +11,6 @@ | |||
| #include <linux/debugfs.h> | ||||
| #include <linux/seq_file.h> | ||||
| #include <linux/gpio.h> | ||||
| #include <linux/of_gpio.h> | ||||
| #include <linux/idr.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/acpi.h> | ||||
|  | @ -30,6 +29,7 @@ | |||
| #include <uapi/linux/gpio.h> | ||||
| 
 | ||||
| #include "gpiolib.h" | ||||
| #include "gpiolib-of.h" | ||||
| 
 | ||||
| #define CREATE_TRACE_POINTS | ||||
| #include <trace/events/gpio.h> | ||||
|  | @ -360,22 +360,15 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) | |||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| static int gpiochip_alloc_valid_mask(struct gpio_chip *gpiochip) | ||||
| static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) | ||||
| { | ||||
| #ifdef CONFIG_OF_GPIO | ||||
| 	int size; | ||||
| 	struct device_node *np = gpiochip->of_node; | ||||
| 
 | ||||
| 	size = of_property_count_u32_elems(np,  "gpio-reserved-ranges"); | ||||
| 	if (size > 0 && size % 2 == 0) | ||||
| 		gpiochip->need_valid_mask = true; | ||||
| #endif | ||||
| 
 | ||||
| 	if (!gpiochip->need_valid_mask) | ||||
| 	if (IS_ENABLED(CONFIG_OF_GPIO)) | ||||
| 		gc->need_valid_mask = of_gpio_need_valid_mask(gc); | ||||
| 	if (!gc->need_valid_mask) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip); | ||||
| 	if (!gpiochip->valid_mask) | ||||
| 	gc->valid_mask = gpiochip_allocate_mask(gc); | ||||
| 	if (!gc->valid_mask) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	return 0; | ||||
|  | @ -3993,27 +3986,6 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, | |||
| 	return desc; | ||||
| } | ||||
| 
 | ||||
| static int dt_gpio_count(struct device *dev, const char *con_id) | ||||
| { | ||||
| 	int ret; | ||||
| 	char propname[32]; | ||||
| 	unsigned int i; | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { | ||||
| 		if (con_id) | ||||
| 			snprintf(propname, sizeof(propname), "%s-%s", | ||||
| 				 con_id, gpio_suffixes[i]); | ||||
| 		else | ||||
| 			snprintf(propname, sizeof(propname), "%s", | ||||
| 				 gpio_suffixes[i]); | ||||
| 
 | ||||
| 		ret = of_gpio_named_count(dev->of_node, propname); | ||||
| 		if (ret > 0) | ||||
| 			break; | ||||
| 	} | ||||
| 	return ret ? ret : -ENOENT; | ||||
| } | ||||
| 
 | ||||
| static int platform_gpio_count(struct device *dev, const char *con_id) | ||||
| { | ||||
| 	struct gpiod_lookup_table *table; | ||||
|  | @ -4046,7 +4018,7 @@ int gpiod_count(struct device *dev, const char *con_id) | |||
| 	int count = -ENOENT; | ||||
| 
 | ||||
| 	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) | ||||
| 		count = dt_gpio_count(dev, con_id); | ||||
| 		count = of_gpio_get_count(dev, con_id); | ||||
| 	else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) | ||||
| 		count = acpi_gpio_count(dev, con_id); | ||||
| 
 | ||||
|  | @ -4247,75 +4219,6 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, | |||
| } | ||||
| EXPORT_SYMBOL_GPL(gpiod_get_index); | ||||
| 
 | ||||
| /**
 | ||||
|  * gpiod_get_from_of_node() - obtain a GPIO from an OF node | ||||
|  * @node:	handle of the OF node | ||||
|  * @propname:	name of the DT property representing the GPIO | ||||
|  * @index:	index of the GPIO to obtain for the consumer | ||||
|  * @dflags:	GPIO initialization flags | ||||
|  * @label:	label to attach to the requested GPIO | ||||
|  * | ||||
|  * Returns: | ||||
|  * On successful request the GPIO pin is configured in accordance with | ||||
|  * provided @dflags. | ||||
|  * | ||||
|  * In case of error an ERR_PTR() is returned. | ||||
|  */ | ||||
| struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, | ||||
| 					 const char *propname, int index, | ||||
| 					 enum gpiod_flags dflags, | ||||
| 					 const char *label) | ||||
| { | ||||
| 	unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; | ||||
| 	struct gpio_desc *desc; | ||||
| 	enum of_gpio_flags flags; | ||||
| 	bool active_low = false; | ||||
| 	bool single_ended = false; | ||||
| 	bool open_drain = false; | ||||
| 	bool transitory = false; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	desc = of_get_named_gpiod_flags(node, propname, | ||||
| 					index, &flags); | ||||
| 
 | ||||
| 	if (!desc || IS_ERR(desc)) { | ||||
| 		return desc; | ||||
| 	} | ||||
| 
 | ||||
| 	active_low = flags & OF_GPIO_ACTIVE_LOW; | ||||
| 	single_ended = flags & OF_GPIO_SINGLE_ENDED; | ||||
| 	open_drain = flags & OF_GPIO_OPEN_DRAIN; | ||||
| 	transitory = flags & OF_GPIO_TRANSITORY; | ||||
| 
 | ||||
| 	ret = gpiod_request(desc, label); | ||||
| 	if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) | ||||
| 		return desc; | ||||
| 	if (ret) | ||||
| 		return ERR_PTR(ret); | ||||
| 
 | ||||
| 	if (active_low) | ||||
| 		lflags |= GPIO_ACTIVE_LOW; | ||||
| 
 | ||||
| 	if (single_ended) { | ||||
| 		if (open_drain) | ||||
| 			lflags |= GPIO_OPEN_DRAIN; | ||||
| 		else | ||||
| 			lflags |= GPIO_OPEN_SOURCE; | ||||
| 	} | ||||
| 
 | ||||
| 	if (transitory) | ||||
| 		lflags |= GPIO_TRANSITORY; | ||||
| 
 | ||||
| 	ret = gpiod_configure_flags(desc, propname, lflags, dflags); | ||||
| 	if (ret < 0) { | ||||
| 		gpiod_put(desc); | ||||
| 		return ERR_PTR(ret); | ||||
| 	} | ||||
| 
 | ||||
| 	return desc; | ||||
| } | ||||
| EXPORT_SYMBOL(gpiod_get_from_of_node); | ||||
| 
 | ||||
| /**
 | ||||
|  * fwnode_get_named_gpiod - obtain a GPIO from firmware node | ||||
|  * @fwnode:	handle of the firmware node | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ | |||
| #include <linux/module.h> | ||||
| #include <linux/cdev.h> | ||||
| 
 | ||||
| enum of_gpio_flags; | ||||
| struct acpi_device; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -92,32 +91,6 @@ struct acpi_gpio_info { | |||
| /* gpio suffixes used for ACPI and device tree lookup */ | ||||
| static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; | ||||
| 
 | ||||
| #ifdef CONFIG_OF_GPIO | ||||
| struct gpio_desc *of_find_gpio(struct device *dev, | ||||
| 			       const char *con_id, | ||||
| 			       unsigned int idx, | ||||
| 			       unsigned long *lookupflags); | ||||
| struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, | ||||
| 		   const char *list_name, int index, enum of_gpio_flags *flags); | ||||
| int of_gpiochip_add(struct gpio_chip *gc); | ||||
| void of_gpiochip_remove(struct gpio_chip *gc); | ||||
| #else | ||||
| static inline struct gpio_desc *of_find_gpio(struct device *dev, | ||||
| 					     const char *con_id, | ||||
| 					     unsigned int idx, | ||||
| 					     unsigned long *lookupflags) | ||||
| { | ||||
| 	return ERR_PTR(-ENOENT); | ||||
| } | ||||
| static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, | ||||
| 		   const char *list_name, int index, enum of_gpio_flags *flags) | ||||
| { | ||||
| 	return ERR_PTR(-ENOENT); | ||||
| } | ||||
| static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } | ||||
| static inline void of_gpiochip_remove(struct gpio_chip *gc) { } | ||||
| #endif /* CONFIG_OF_GPIO */ | ||||
| 
 | ||||
| #ifdef CONFIG_ACPI | ||||
| void acpi_gpiochip_add(struct gpio_chip *chip); | ||||
| void acpi_gpiochip_remove(struct gpio_chip *chip); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Linus Walleij
						Linus Walleij