[REPOST RFC PATCH 2/3] of_gpio: Add new helpers for easily requesting lots of GPIOs
From: Kyle Moffett
Date: Tue Dec 13 2011 - 13:24:29 EST
Mirroring the new gpio_request_array() interface, we add several a few
helper functions for operating on entire arrays of GPIOs.
Also, to make it easier to write various combinations of "of_get_gpio()"
followed by "gpio_request()", add several other new inline wrappers.
Signed-off-by: Kyle Moffett <Kyle.D.Moffett@xxxxxxxxxx>
---
drivers/of/gpio.c | 96 +++++++++++++++++++++++++++++
include/linux/of_gpio.h | 154 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 250 insertions(+), 0 deletions(-)
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index f349aaf..4c04f2f 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -83,6 +83,47 @@ err0:
EXPORT_SYMBOL(of_get_named_gpio_flags);
/**
+ * of_get_gpio_array_flags() - Get array of gpios to use with GPIO API
+ * @np: device node to get GPIOs from
+ * @of_gpios: array of "struct of_gpio" to select which GPIOs to look up
+ * @of_flags: array of "enum of_gpio_flags" to be filled in (may be NULL)
+ * @gpios: array of "struct gpio" to be filled in
+ * @num: the number of GPIOs to look up
+ *
+ * Takes a constant array of "struct of_gpio" and looks up each item in the
+ * indicated device-node. The results are stored into the @gpios array,
+ * along with the optional GPIO "label" and "flags" values from the "of_gpio"
+ * structure.
+ *
+ * If an array of @of_flags is provided then any flags from the translate
+ * function will be stored into the corresponding element there.
+ */
+int of_get_gpio_array_flags(struct device_node *np,
+ const struct of_gpio *of_gpios, enum of_gpio_flags *of_flags,
+ struct gpio *gpios, size_t num)
+{
+ int err = 0;
+
+ size_t i;
+ for (i = 0; i < num; i++) {
+ /* Copy over the GPIO values */
+ gpios[i].flags = of_gpios[i].gpio_flags;
+ gpios[i].label = of_gpios[i].gpio_label;
+
+ /* Now dig the rest out of the device-tree */
+ gpios[i].gpio = of_get_named_gpio_flags(np,
+ of_gpios[i].propname, of_gpios[i].index,
+ (of_flags ? &of_flags[num] : NULL));
+
+ if (gpios[i].gpio < 0)
+ err = err ?: gpios[i].gpio;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(of_get_gpio_array_flags);
+
+/**
* of_gpio_count_named - Count GPIOs for a device
* @np: device node to count GPIOs for
* @propname: property name containing gpio specifier(s)
@@ -116,6 +157,61 @@ unsigned int of_gpio_count_named(struct device_node *np, const char *propname)
EXPORT_SYMBOL(of_gpio_count_named);
/**
+ * of_gpio_request_named_flags() - Request a GPIO using the device-tree
+ * @np: device node to get GPIO from
+ * @propname: property name containing gpio specifier(s)
+ * @index: index of the GPIO
+ * @flags: a flags pointer to fill in
+ * @gpio_flags: The setup flags to pass into the GPIO API
+ * @gpio_label: The label to pass into the GPIO API
+ *
+ * This is a simple wrapper around gpio_request_one() that looks up the GPIO
+ * from the device-tree first using of_get_named_gpio_flags().
+ */
+int of_gpio_request_named_flags(struct device_node *np,
+ const char *propname, int index, enum of_gpio_flags *of_flags,
+ unsigned long gpio_flags, const char *gpio_label)
+{
+ int err;
+
+ /* Retrieve the GPIO information from the device-tree */
+ int gpio = of_get_named_gpio_flags(np, propname, index, of_flags);
+ if (gpio < 0)
+ return gpio;
+
+ /* Request the GPIO */
+ err = gpio_request_one(gpio, gpio_flags, gpio_label);
+ return err ? err : gpio;
+}
+EXPORT_SYMBOL(of_gpio_request_named_flags);
+
+/**
+ * of_gpio_request_array_flags() - Request GPIOs using the device-tree
+ * @np: device node to get GPIO from
+ * @of_gpios: array of "struct of_gpio" to select which GPIOs to request
+ * @of_flags: array of "enum of_gpio_flags" to be filled in (may be NULL)
+ * @gpios: array of "struct gpio" to be filled in
+ * @num: the number of GPIOs to request
+ *
+ * This is a simple wrapper around gpio_request_array() that looks up the
+ * GPIOs from the device-tree first using of_get_gpio_array_flags().
+ */
+int of_gpio_request_array_flags(struct device_node *np,
+ const struct of_gpio *of_gpios, enum of_gpio_flags *of_flags,
+ struct gpio *gpios, size_t num)
+{
+ /* Retrieve the GPIO information from the device-tree */
+ int err = of_get_gpio_array_flags(np, of_gpios,
+ of_flags, gpios, num);
+ if (err)
+ return err;
+
+ /* Request all of the GPIOs */
+ return gpio_request_array(gpios, num);
+}
+EXPORT_SYMBOL(of_gpio_request_array_flags);
+
+/**
* of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
* @gc: pointer to the gpio_chip structure
* @np: device node of the GPIO chip
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 1411a06..babce09 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -30,6 +30,20 @@ enum of_gpio_flags {
OF_GPIO_ACTIVE_LOW = 0x1,
};
+/*
+ * This struct is passed to of_named_gpio_request_array() to initialize the
+ * passed-in array of "struct gpio" for use by gpio_request_array().
+ */
+struct of_gpio {
+ /* These values are used to locate the GPIO in the device-tree */
+ const char *propname;
+ int index;
+
+ /* These values are used to request the discovered GPIO */
+ unsigned long gpio_flags;
+ const char *gpio_label;
+};
+
#ifdef CONFIG_OF_GPIO
/*
@@ -49,9 +63,21 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
extern int of_get_named_gpio_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
+extern int of_get_gpio_array_flags(struct device_node *np,
+ const struct of_gpio *of_gpios, enum of_gpio_flags *of_flags,
+ struct gpio *gpios, size_t num);
+
extern unsigned int of_gpio_count_named(struct device_node *np,
const char *propname);
+extern int of_gpio_request_named_flags(struct device_node *np,
+ const char *propname, int index, enum of_gpio_flags *of_flags,
+ unsigned long gpio_flags, const char *gpio_label);
+
+extern int of_gpio_request_array_flags(struct device_node *np,
+ const struct of_gpio *of_gpios, enum of_gpio_flags *of_flags,
+ struct gpio *gpios, size_t num);
+
extern int of_mm_gpiochip_add(struct device_node *np,
struct of_mm_gpio_chip *mm_gc);
@@ -70,12 +96,51 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
return -ENOSYS;
}
+static inline int of_get_gpio_array_flags(struct device_node *np,
+ const struct of_gpio *of_gpios, enum of_gpio_flags *of_flags,
+ struct gpio *gpios, size_t num)
+{
+ /*
+ * This function must always initialize all the "struct gpio"s even
+ * if they cannot be probed to allow the user to detect the source of
+ * each error.
+ */
+ size_t i;
+ for (i = 0; i < num; i++) {
+ gpios[i].gpio = -ENOSYS;
+ gpios[i].label = of_gpios[i].label;
+ gpios[i].flags = of_gpios[i].flags;
+ }
+ return -ENOSYS;
+}
+
static inline unsigned int of_gpio_count_named(struct device_node *np,
const char *propname)
{
return 0;
}
+static inline int of_gpio_request_named_flags(struct device_node *np,
+ const char *propname, int index, enum of_gpio_flags *of_flags,
+ unsigned long gpio_flags, const char *gpio_label)
+{
+ return -ENOSYS;
+}
+
+static inline int of_gpio_request_array_flags(struct device_node *np,
+ const struct of_gpio *of_gpios, enum of_gpio_flags *of_flags,
+ struct gpio *gpios, size_t num)
+{
+ /* Same initialization as of_get_gpio_array_flags() above */
+ size_t i;
+ for (i = 0; i < num; i++) {
+ gpios[i].gpio = -ENOSYS;
+ gpios[i].label = of_gpios[i].label;
+ gpios[i].flags = of_gpios[i].flags;
+ }
+ return -ENOSYS;
+}
+
static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
struct device_node *np,
const void *gpio_spec, u32 *flags)
@@ -153,4 +218,93 @@ static inline int of_get_gpio(struct device_node *np, int index)
return of_get_gpio_flags(np, index, NULL);
}
+/**
+ * of_gpio_request_one_flags() - Request a GPIO using the device-tree
+ * @np: device node to get GPIO from
+ * @index: index of the GPIO
+ * @flags: a flags pointer to fill in
+ * @gpio_flags: The setup flags to pass into the GPIO API
+ * @gpio_label: The label to pass into the GPIO API
+ *
+ * This is a simple wrapper around gpio_request_one() that looks up the GPIO
+ * from the device-tree first using of_get_gpio_flags().
+ */
+static inline int of_gpio_request_one_flags(struct device_node *np,
+ int index, enum of_gpio_flags *of_flags,
+ unsigned long gpio_flags, const char *gpio_label)
+{
+ return of_gpio_request_named_flags(np, "gpios", index,
+ of_flags, gpio_flags, gpio_label);
+}
+
+/**
+ * of_gpio_request_named() - Request a GPIO using the device-tree
+ * @np: device node to get GPIO from
+ * @propname: Name of property containing gpio specifier(s)
+ * @index: index of the GPIO
+ * @gpio_flags: The setup flags to pass into the GPIO API
+ * @gpio_label: The label to pass into the GPIO API
+ *
+ * This is a simple wrapper around gpio_request_one() that looks up the GPIO
+ * from the device-tree first using of_get_named_gpio().
+ */
+static inline int of_gpio_request_named(struct device_node *np,
+ const char *propname, int index,
+ unsigned long gpio_flags, const char *gpio_label)
+{
+ return of_gpio_request_named_flags(np, propname, index,
+ NULL, gpio_flags, gpio_label);
+}
+
+/**
+ * of_gpio_request_one() - Request a GPIO using the device-tree
+ * @np: device node to get GPIO from
+ * @index: index of the GPIO
+ * @gpio_flags: The setup flags to pass into the GPIO API
+ * @gpio_label: The label to pass into the GPIO API
+ *
+ * This is a simple wrapper around gpio_request_one() that looks up the GPIO
+ * from the device-tree first using of_get_gpio().
+ */
+static inline int of_gpio_request_one(struct device_node *np,
+ int index, unsigned long gpio_flags, const char *gpio_label)
+{
+ return of_gpio_request_one_flags(np, index, NULL,
+ gpio_flags, gpio_label);
+}
+
+/**
+ * of_get_gpio_array() - Get an array of GPIO numbers to use with GPIO API
+ * @np: device node to get GPIO from
+ * @of_gpios: array of "struct of_gpio" to select which GPIOs to look up
+ * @gpios: array of "struct gpio" to be filled in
+ * @num: the number of GPIOs to look up
+ *
+ * Takes a constant array of "struct of_gpio" and looks up each item in the
+ * indicated device-node. The results are stored into the @gpios array,
+ * along with the optional GPIO "label" and "flags" values from the "of_gpio"
+ * structure.
+ */
+static inline int of_get_gpio_array(struct device_node *np,
+ const struct of_gpio *of_gpios, struct gpio *gpios, size_t num)
+{
+ return of_get_gpio_array_flags(np, of_gpios, NULL, gpios, num);
+}
+
+/**
+ * of_gpio_request_array() - Request GPIOs using the device-tree
+ * @np: device node to get GPIO from
+ * @of_gpios: array of "struct of_gpio" to select which GPIOs to request
+ * @gpios: array of "struct gpio" to be filled in
+ * @num: the number of GPIOs to request
+ *
+ * This is a simple wrapper around gpio_request_array() that looks up the
+ * GPIOs from the device-tree first using of_get_gpio_array().
+ */
+static inline int of_gpio_request_array(struct device_node *np,
+ const struct of_gpio *of_gpios, struct gpio *gpios, size_t num)
+{
+ return of_gpio_request_array_flags(np, of_gpios, NULL, gpios, num);
+}
+
#endif /* __LINUX_OF_GPIO_H */
--
1.7.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/