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
drivers/gpio
@ -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 New Issue
Block a user