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 <linux/gpio/machine.h> | ||||||
| 
 | 
 | ||||||
| #include "gpiolib.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) | 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); | 	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, | static void of_gpio_flags_quirks(struct device_node *np, | ||||||
| 				 const char *propname, | 				 const char *propname, | ||||||
| 				 enum of_gpio_flags *flags, | 				 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); | 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 |  * 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 |  * 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/debugfs.h> | ||||||
| #include <linux/seq_file.h> | #include <linux/seq_file.h> | ||||||
| #include <linux/gpio.h> | #include <linux/gpio.h> | ||||||
| #include <linux/of_gpio.h> |  | ||||||
| #include <linux/idr.h> | #include <linux/idr.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include <linux/acpi.h> | #include <linux/acpi.h> | ||||||
|  | @ -30,6 +29,7 @@ | ||||||
| #include <uapi/linux/gpio.h> | #include <uapi/linux/gpio.h> | ||||||
| 
 | 
 | ||||||
| #include "gpiolib.h" | #include "gpiolib.h" | ||||||
|  | #include "gpiolib-of.h" | ||||||
| 
 | 
 | ||||||
| #define CREATE_TRACE_POINTS | #define CREATE_TRACE_POINTS | ||||||
| #include <trace/events/gpio.h> | #include <trace/events/gpio.h> | ||||||
|  | @ -360,22 +360,15 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) | ||||||
| 	return p; | 	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 | 	if (IS_ENABLED(CONFIG_OF_GPIO)) | ||||||
| 	int size; | 		gc->need_valid_mask = of_gpio_need_valid_mask(gc); | ||||||
| 	struct device_node *np = gpiochip->of_node; | 	if (!gc->need_valid_mask) | ||||||
| 
 |  | ||||||
| 	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) |  | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip); | 	gc->valid_mask = gpiochip_allocate_mask(gc); | ||||||
| 	if (!gpiochip->valid_mask) | 	if (!gc->valid_mask) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -3993,27 +3986,6 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, | ||||||
| 	return desc; | 	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) | static int platform_gpio_count(struct device *dev, const char *con_id) | ||||||
| { | { | ||||||
| 	struct gpiod_lookup_table *table; | 	struct gpiod_lookup_table *table; | ||||||
|  | @ -4046,7 +4018,7 @@ int gpiod_count(struct device *dev, const char *con_id) | ||||||
| 	int count = -ENOENT; | 	int count = -ENOENT; | ||||||
| 
 | 
 | ||||||
| 	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) | 	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)) | 	else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) | ||||||
| 		count = acpi_gpio_count(dev, con_id); | 		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); | 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_get_named_gpiod - obtain a GPIO from firmware node | ||||||
|  * @fwnode:	handle of the firmware node |  * @fwnode:	handle of the firmware node | ||||||
|  |  | ||||||
|  | @ -16,7 +16,6 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/cdev.h> | #include <linux/cdev.h> | ||||||
| 
 | 
 | ||||||
| enum of_gpio_flags; |  | ||||||
| struct acpi_device; | struct acpi_device; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -92,32 +91,6 @@ struct acpi_gpio_info { | ||||||
| /* gpio suffixes used for ACPI and device tree lookup */ | /* gpio suffixes used for ACPI and device tree lookup */ | ||||||
| static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; | 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 | #ifdef CONFIG_ACPI | ||||||
| void acpi_gpiochip_add(struct gpio_chip *chip); | void acpi_gpiochip_add(struct gpio_chip *chip); | ||||||
| void acpi_gpiochip_remove(struct gpio_chip *chip); | void acpi_gpiochip_remove(struct gpio_chip *chip); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Linus Walleij
						Linus Walleij