* [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips
@ 2012-05-18 8:19 Roland Stigge
2012-05-18 8:19 ` [PATCH 2/2] gpio: Device tree support for LPC32xx Roland Stigge
2012-05-18 9:36 ` [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips Arnd Bergmann
0 siblings, 2 replies; 4+ messages in thread
From: Roland Stigge @ 2012-05-18 8:19 UTC (permalink / raw)
To: linux-kernel, grant.likely; +Cc: Roland Stigge
From: Grant Likely <grant.likely@secretlab.ca>
This patch changes the of_xlate API to make it possible for multiple
gpio_chips to refer to the same device tree node. This is useful for
banked GPIO controllers that use multiple gpio_chips for a single
device. With this change the core code will try calling of_xlate on
each gpio_chip that references the device_node and will return the
gpio number for the first one to return 'true'.
Cc: Roland Stigge <stigge@antcom.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Roland Stigge <stigge@antcom.de>
---
arch/arm/mach-imx/mach-mx35_3ds.c | 3 +-
drivers/gpio/gpiolib-of.c | 80 ++++++++++++++++++-------------------
drivers/gpio/gpiolib.c | 2 +-
include/asm-generic/gpio.h | 2 +-
include/linux/of_gpio.h | 1 -
5 files changed, 41 insertions(+), 47 deletions(-)
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index 6ae51c6..6a7cf91 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -96,8 +96,7 @@ static struct i2c_board_info __initdata i2c_devices_3ds[] = {
static int lcd_power_gpio = -ENXIO;
-static int mc9s08dz60_gpiochip_match(struct gpio_chip *chip,
- const void *data)
+static int mc9s08dz60_gpiochip_match(struct gpio_chip *chip, void *data)
{
return !strcmp(chip->label, data);
}
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index bf984b6..d18068a 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -15,11 +15,39 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
+/* Private data structure for of_gpiochip_is_match */
+struct gg_data {
+ enum of_gpio_flags *flags;
+ struct of_phandle_args gpiospec;
+
+ int out_gpio;
+};
+
+/* Private function for resolving node pointer to gpio_chip */
+static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
+{
+ struct gg_data *gg_data = data;
+ int ret;
+
+ if ((gc->of_node != gg_data->gpiospec.np) ||
+ (gc->of_gpio_n_cells != gg_data->gpiospec.args_count) ||
+ (!gc->of_xlate))
+ return false;
+
+ ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags);
+ if (ret < 0)
+ return false;
+
+ gg_data->out_gpio = ret + gc->base;
+ return true;
+}
+
/**
* of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
* @np: device node to get GPIO from
@@ -34,46 +62,25 @@
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
int index, enum of_gpio_flags *flags)
{
+ struct gg_data gg_data = { .flags = flags, .out_gpio = -ENODEV };
int ret;
- struct gpio_chip *gc;
- struct of_phandle_args gpiospec;
+
+ /* .of_xlate might decide to not fill in the flags, so clear it. */
+ if (flags)
+ *flags = 0;
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
- &gpiospec);
+ &gg_data.gpiospec);
if (ret) {
pr_debug("%s: can't parse gpios property\n", __func__);
- goto err0;
- }
-
- gc = of_node_to_gpiochip(gpiospec.np);
- if (!gc) {
- pr_debug("%s: gpio controller %s isn't registered\n",
- np->full_name, gpiospec.np->full_name);
- ret = -ENODEV;
- goto err1;
- }
-
- if (gpiospec.args_count != gc->of_gpio_n_cells) {
- pr_debug("%s: wrong #gpio-cells for %s\n",
- np->full_name, gpiospec.np->full_name);
- ret = -EINVAL;
- goto err1;
+ return -EINVAL;
}
- /* .xlate might decide to not fill in the flags, so clear it. */
- if (flags)
- *flags = 0;
-
- ret = gc->of_xlate(gc, &gpiospec, flags);
- if (ret < 0)
- goto err1;
+ gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
- ret += gc->base;
-err1:
- of_node_put(gpiospec.np);
-err0:
+ of_node_put(gg_data.gpiospec.np);
pr_debug("%s exited with status %d\n", __func__, ret);
- return ret;
+ return gg_data.out_gpio;
}
EXPORT_SYMBOL(of_get_named_gpio_flags);
@@ -227,14 +234,3 @@ void of_gpiochip_remove(struct gpio_chip *chip)
if (chip->of_node)
of_node_put(chip->of_node);
}
-
-/* Private function for resolving node pointer to gpio_chip */
-static int of_gpiochip_is_match(struct gpio_chip *chip, const void *data)
-{
- return chip->of_node == data;
-}
-
-struct gpio_chip *of_node_to_gpiochip(struct device_node *np)
-{
- return gpiochip_find(np, of_gpiochip_is_match);
-}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 566d012..38353c0 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1156,7 +1156,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove);
*/
struct gpio_chip *gpiochip_find(const void *data,
int (*match)(struct gpio_chip *chip,
- const void *data))
+ void *data))
{
struct gpio_chip *chip = NULL;
unsigned long flags;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 5f52690..1cb3dd1 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -144,7 +144,7 @@ extern int gpiochip_add(struct gpio_chip *chip);
extern int __must_check gpiochip_remove(struct gpio_chip *chip);
extern struct gpio_chip *gpiochip_find(const void *data,
int (*match)(struct gpio_chip *chip,
- const void *data));
+ void *data));
/* Always use the library code for GPIO management calls,
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 81733d1..c454f57 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -58,7 +58,6 @@ extern int of_mm_gpiochip_add(struct device_node *np,
extern void of_gpiochip_add(struct gpio_chip *gc);
extern void of_gpiochip_remove(struct gpio_chip *gc);
-extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
extern int of_gpio_simple_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec,
u32 *flags);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] gpio: Device tree support for LPC32xx
2012-05-18 8:19 [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips Roland Stigge
@ 2012-05-18 8:19 ` Roland Stigge
2012-05-18 22:27 ` Grant Likely
2012-05-18 9:36 ` [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips Arnd Bergmann
1 sibling, 1 reply; 4+ messages in thread
From: Roland Stigge @ 2012-05-18 8:19 UTC (permalink / raw)
To: linux-kernel, grant.likely; +Cc: Roland Stigge
This patch adds device tree support for gpio-lpc32xx.c.
To register the various GPIO banks as (struct) gpio_chips via the same DT
gpio-controller, we utilize the adjusted of_xlate API to manipulate the
actually used struct gpio_chip.
Signed-off-by: Roland Stigge <stigge@antcom.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
Thanks to Jean-Christophe PLAGNIOL-VILLARD, Grant Likely, Arnd Bergmann, Jon
Smirl, Mark Brown for reviewing!
You can also pull from:
git://git.antcom.de/linux-2.6.git dt/gpio
http://git.antcom.de/linux-2.6.git dt/gpio
http://git.antcom.de/?p=linux-2.6.git;a=shortlog;h=refs/heads/dt/gpio
Documentation/devicetree/bindings/gpio/gpio_lpc32xx.txt | 43 +++++++++++++
arch/arm/mach-lpc32xx/include/mach/gpio.h | 9 ++
drivers/gpio/gpio-lpc32xx.c | 52 +++++++++++++++-
3 files changed, 102 insertions(+), 2 deletions(-)
--- /dev/null
+++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio_lpc32xx.txt
@@ -0,0 +1,43 @@
+NXP LPC32xx SoC GPIO controller
+
+Required properties:
+- compatible: must be "nxp,lpc3220-gpio"
+- reg: Physical base address and length of the controller's registers.
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells: Should be 3:
+ 1) bank:
+ 0: GPIO P0
+ 1: GPIO P1
+ 2: GPIO P2
+ 3: GPIO P3
+ 4: GPI P3
+ 5: GPO P3
+ 2) pin number
+ 3) optional parameters:
+ - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- reg: Index of the GPIO group
+
+Example:
+
+ gpio: gpio@40028000 {
+ compatible = "nxp,lpc3220-gpio";
+ reg = <0x40028000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <3>; /* bank, pin, flags */
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led0 {
+ gpios = <&gpio 5 1 1>; /* GPO_P3 1, active low */
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ led1 {
+ gpios = <&gpio 5 14 1>; /* GPO_P3 14, active low */
+ linux,default-trigger = "timer";
+ default-state = "off";
+ };
+ };
--- linux-2.6.orig/arch/arm/mach-lpc32xx/include/mach/gpio.h
+++ linux-2.6/arch/arm/mach-lpc32xx/include/mach/gpio.h
@@ -1 +1,8 @@
-/* empty */
+#ifndef __MACH_GPIO_H
+#define __MACH_GPIO_H
+
+#include "gpio-lpc32xx.h"
+
+#define ARCH_NR_GPIOS (LPC32XX_GPO_P3_GRP + LPC32XX_GPO_P3_MAX)
+
+#endif /* __MACH_GPIO_H */
--- linux-2.6.orig/drivers/gpio/gpio-lpc32xx.c
+++ linux-2.6/drivers/gpio/gpio-lpc32xx.c
@@ -21,6 +21,9 @@
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
#include <mach/hardware.h>
#include <mach/platform.h>
@@ -454,10 +457,57 @@ static struct lpc32xx_gpio_chip lpc32xx_
},
};
+/* Empty now, can be removed later when mach-lpc32xx is finally switched over
+ * to DT support
+ */
void __init lpc32xx_gpio_init(void)
{
+}
+
+static int lpc32xx_of_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags)
+{
+ /* Is this the correct bank? */
+ u32 bank = gpiospec->args[0];
+ if ((bank > ARRAY_SIZE(lpc32xx_gpiochip) ||
+ (gc != &lpc32xx_gpiochip[bank].chip)))
+ return -EINVAL;
+
+ if (flags)
+ *flags = gpiospec->args[2];
+ return gpiospec->args[1];
+}
+
+static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
+{
int i;
- for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
+ for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
+ if (pdev->dev.of_node) {
+ lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
+ lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
+ lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
+ }
gpiochip_add(&lpc32xx_gpiochip[i].chip);
+ }
+
+ return 0;
}
+
+#ifdef CONFIG_OF
+static struct of_device_id lpc32xx_gpio_of_match[] __devinitdata = {
+ { .compatible = "nxp,lpc3220-gpio", },
+ { },
+};
+#endif
+
+static struct platform_driver lpc32xx_gpio_driver = {
+ .driver = {
+ .name = "lpc32xx-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(lpc32xx_gpio_of_match),
+ },
+ .probe = lpc32xx_gpio_probe,
+};
+
+module_platform_driver(lpc32xx_gpio_driver);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips
2012-05-18 8:19 [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips Roland Stigge
2012-05-18 8:19 ` [PATCH 2/2] gpio: Device tree support for LPC32xx Roland Stigge
@ 2012-05-18 9:36 ` Arnd Bergmann
1 sibling, 0 replies; 4+ messages in thread
From: Arnd Bergmann @ 2012-05-18 9:36 UTC (permalink / raw)
To: Roland Stigge; +Cc: linux-kernel, grant.likely
On Friday 18 May 2012, Roland Stigge wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
>
> This patch changes the of_xlate API to make it possible for multiple
> gpio_chips to refer to the same device tree node. This is useful for
> banked GPIO controllers that use multiple gpio_chips for a single
> device. With this change the core code will try calling of_xlate on
> each gpio_chip that references the device_node and will return the
> gpio number for the first one to return 'true'.
>
> Cc: Roland Stigge <stigge@antcom.de>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> Tested-by: Roland Stigge <stigge@antcom.de>
>
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] gpio: Device tree support for LPC32xx
2012-05-18 8:19 ` [PATCH 2/2] gpio: Device tree support for LPC32xx Roland Stigge
@ 2012-05-18 22:27 ` Grant Likely
0 siblings, 0 replies; 4+ messages in thread
From: Grant Likely @ 2012-05-18 22:27 UTC (permalink / raw)
To: Roland Stigge, linux-kernel; +Cc: Roland Stigge
On Fri, 18 May 2012 10:19:52 +0200, Roland Stigge <stigge@antcom.de> wrote:
> This patch adds device tree support for gpio-lpc32xx.c.
>
> To register the various GPIO banks as (struct) gpio_chips via the same DT
> gpio-controller, we utilize the adjusted of_xlate API to manipulate the
> actually used struct gpio_chip.
>
> Signed-off-by: Roland Stigge <stigge@antcom.de>
> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Applied, thanks.
g.
>
> ---
>
> Thanks to Jean-Christophe PLAGNIOL-VILLARD, Grant Likely, Arnd Bergmann, Jon
> Smirl, Mark Brown for reviewing!
>
> You can also pull from:
> git://git.antcom.de/linux-2.6.git dt/gpio
> http://git.antcom.de/linux-2.6.git dt/gpio
> http://git.antcom.de/?p=linux-2.6.git;a=shortlog;h=refs/heads/dt/gpio
>
> Documentation/devicetree/bindings/gpio/gpio_lpc32xx.txt | 43 +++++++++++++
> arch/arm/mach-lpc32xx/include/mach/gpio.h | 9 ++
> drivers/gpio/gpio-lpc32xx.c | 52 +++++++++++++++-
> 3 files changed, 102 insertions(+), 2 deletions(-)
>
> --- /dev/null
> +++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio_lpc32xx.txt
> @@ -0,0 +1,43 @@
> +NXP LPC32xx SoC GPIO controller
> +
> +Required properties:
> +- compatible: must be "nxp,lpc3220-gpio"
> +- reg: Physical base address and length of the controller's registers.
> +- gpio-controller: Marks the device node as a GPIO controller.
> +- #gpio-cells: Should be 3:
> + 1) bank:
> + 0: GPIO P0
> + 1: GPIO P1
> + 2: GPIO P2
> + 3: GPIO P3
> + 4: GPI P3
> + 5: GPO P3
> + 2) pin number
> + 3) optional parameters:
> + - bit 0 specifies polarity (0 for normal, 1 for inverted)
> +- reg: Index of the GPIO group
> +
> +Example:
> +
> + gpio: gpio@40028000 {
> + compatible = "nxp,lpc3220-gpio";
> + reg = <0x40028000 0x1000>;
> + gpio-controller;
> + #gpio-cells = <3>; /* bank, pin, flags */
> + };
> +
> + leds {
> + compatible = "gpio-leds";
> +
> + led0 {
> + gpios = <&gpio 5 1 1>; /* GPO_P3 1, active low */
> + linux,default-trigger = "heartbeat";
> + default-state = "off";
> + };
> +
> + led1 {
> + gpios = <&gpio 5 14 1>; /* GPO_P3 14, active low */
> + linux,default-trigger = "timer";
> + default-state = "off";
> + };
> + };
> --- linux-2.6.orig/arch/arm/mach-lpc32xx/include/mach/gpio.h
> +++ linux-2.6/arch/arm/mach-lpc32xx/include/mach/gpio.h
> @@ -1 +1,8 @@
> -/* empty */
> +#ifndef __MACH_GPIO_H
> +#define __MACH_GPIO_H
> +
> +#include "gpio-lpc32xx.h"
> +
> +#define ARCH_NR_GPIOS (LPC32XX_GPO_P3_GRP + LPC32XX_GPO_P3_MAX)
> +
> +#endif /* __MACH_GPIO_H */
> --- linux-2.6.orig/drivers/gpio/gpio-lpc32xx.c
> +++ linux-2.6/drivers/gpio/gpio-lpc32xx.c
> @@ -21,6 +21,9 @@
> #include <linux/io.h>
> #include <linux/errno.h>
> #include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
>
> #include <mach/hardware.h>
> #include <mach/platform.h>
> @@ -454,10 +457,57 @@ static struct lpc32xx_gpio_chip lpc32xx_
> },
> };
>
> +/* Empty now, can be removed later when mach-lpc32xx is finally switched over
> + * to DT support
> + */
> void __init lpc32xx_gpio_init(void)
> {
> +}
> +
> +static int lpc32xx_of_xlate(struct gpio_chip *gc,
> + const struct of_phandle_args *gpiospec, u32 *flags)
> +{
> + /* Is this the correct bank? */
> + u32 bank = gpiospec->args[0];
> + if ((bank > ARRAY_SIZE(lpc32xx_gpiochip) ||
> + (gc != &lpc32xx_gpiochip[bank].chip)))
> + return -EINVAL;
> +
> + if (flags)
> + *flags = gpiospec->args[2];
> + return gpiospec->args[1];
> +}
> +
> +static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
> +{
> int i;
>
> - for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
> + for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
> + if (pdev->dev.of_node) {
> + lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
> + lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
> + lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
> + }
> gpiochip_add(&lpc32xx_gpiochip[i].chip);
> + }
> +
> + return 0;
> }
> +
> +#ifdef CONFIG_OF
> +static struct of_device_id lpc32xx_gpio_of_match[] __devinitdata = {
> + { .compatible = "nxp,lpc3220-gpio", },
> + { },
> +};
> +#endif
> +
> +static struct platform_driver lpc32xx_gpio_driver = {
> + .driver = {
> + .name = "lpc32xx-gpio",
> + .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(lpc32xx_gpio_of_match),
> + },
> + .probe = lpc32xx_gpio_probe,
> +};
> +
> +module_platform_driver(lpc32xx_gpio_driver);
--
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-05-18 22:27 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-18 8:19 [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips Roland Stigge
2012-05-18 8:19 ` [PATCH 2/2] gpio: Device tree support for LPC32xx Roland Stigge
2012-05-18 22:27 ` Grant Likely
2012-05-18 9:36 ` [PATCH 1/2] gpio: Adjust of_xlate API to support multiple GPIO chips Arnd Bergmann
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.