Commit f626d6df authored by Linus Walleij's avatar Linus Walleij
Browse files

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: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20190717071001.3858-1-linus.walleij@linaro.org
parent f8650b8f
Loading
Loading
Loading
Loading
+114 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/* 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 */
+8 −105
Original line number Diff line number Diff line
@@ -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
+0 −27
Original line number Diff line number Diff line
@@ -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);