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
|
@ -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
|
||||
|
|
|
@ -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 New Issue