diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2008-10-10 00:43:17 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-12 19:55:47 -0400 |
commit | 64b60e096fa391c56f93e6216115e6757bf86b7e (patch) | |
tree | 901a0fa1f9f533fe81305341fa869c34a1e913a9 /drivers/of/gpio.c | |
parent | 302905a3473d9a1f00e4b2fe373d2763a041a93d (diff) |
of: Add new helper of_parse_phandles_with_args()
The helper is factored out of of_get_gpio(). Will be used by the QE
pin multiplexing functions (they need to parse the gpios = <> too).
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/of/gpio.c')
-rw-r--r-- | drivers/of/gpio.c | 81 |
1 files changed, 19 insertions, 62 deletions
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 1c9cab844f10..7cd7301b5839 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c | |||
@@ -28,78 +28,35 @@ | |||
28 | */ | 28 | */ |
29 | int of_get_gpio(struct device_node *np, int index) | 29 | int of_get_gpio(struct device_node *np, int index) |
30 | { | 30 | { |
31 | int ret = -EINVAL; | 31 | int ret; |
32 | struct device_node *gc; | 32 | struct device_node *gc; |
33 | struct of_gpio_chip *of_gc = NULL; | 33 | struct of_gpio_chip *of_gc = NULL; |
34 | int size; | 34 | int size; |
35 | const u32 *gpios; | ||
36 | u32 nr_cells; | ||
37 | int i; | ||
38 | const void *gpio_spec; | 35 | const void *gpio_spec; |
39 | const u32 *gpio_cells; | 36 | const u32 *gpio_cells; |
40 | int gpio_index = 0; | ||
41 | 37 | ||
42 | gpios = of_get_property(np, "gpios", &size); | 38 | ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index, |
43 | if (!gpios) { | 39 | &gc, &gpio_spec); |
44 | ret = -ENOENT; | 40 | if (ret) { |
41 | pr_debug("%s: can't parse gpios property\n", __func__); | ||
45 | goto err0; | 42 | goto err0; |
46 | } | 43 | } |
47 | nr_cells = size / sizeof(u32); | ||
48 | |||
49 | for (i = 0; i < nr_cells; gpio_index++) { | ||
50 | const phandle *gpio_phandle; | ||
51 | |||
52 | gpio_phandle = gpios + i; | ||
53 | gpio_spec = gpio_phandle + 1; | ||
54 | |||
55 | /* one cell hole in the gpios = <>; */ | ||
56 | if (!*gpio_phandle) { | ||
57 | if (gpio_index == index) | ||
58 | return -ENOENT; | ||
59 | i++; | ||
60 | continue; | ||
61 | } | ||
62 | |||
63 | gc = of_find_node_by_phandle(*gpio_phandle); | ||
64 | if (!gc) { | ||
65 | pr_debug("%s: could not find phandle for gpios\n", | ||
66 | np->full_name); | ||
67 | goto err0; | ||
68 | } | ||
69 | |||
70 | of_gc = gc->data; | ||
71 | if (!of_gc) { | ||
72 | pr_debug("%s: gpio controller %s isn't registered\n", | ||
73 | np->full_name, gc->full_name); | ||
74 | goto err1; | ||
75 | } | ||
76 | |||
77 | gpio_cells = of_get_property(gc, "#gpio-cells", &size); | ||
78 | if (!gpio_cells || size != sizeof(*gpio_cells) || | ||
79 | *gpio_cells != of_gc->gpio_cells) { | ||
80 | pr_debug("%s: wrong #gpio-cells for %s\n", | ||
81 | np->full_name, gc->full_name); | ||
82 | goto err1; | ||
83 | } | ||
84 | |||
85 | /* Next phandle is at phandle cells + #gpio-cells */ | ||
86 | i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells; | ||
87 | if (i >= nr_cells + 1) { | ||
88 | pr_debug("%s: insufficient gpio-spec length\n", | ||
89 | np->full_name); | ||
90 | goto err1; | ||
91 | } | ||
92 | |||
93 | if (gpio_index == index) | ||
94 | break; | ||
95 | |||
96 | of_gc = NULL; | ||
97 | of_node_put(gc); | ||
98 | } | ||
99 | 44 | ||
45 | of_gc = gc->data; | ||
100 | if (!of_gc) { | 46 | if (!of_gc) { |
101 | ret = -ENOENT; | 47 | pr_debug("%s: gpio controller %s isn't registered\n", |
102 | goto err0; | 48 | np->full_name, gc->full_name); |
49 | ret = -ENODEV; | ||
50 | goto err1; | ||
51 | } | ||
52 | |||
53 | gpio_cells = of_get_property(gc, "#gpio-cells", &size); | ||
54 | if (!gpio_cells || size != sizeof(*gpio_cells) || | ||
55 | *gpio_cells != of_gc->gpio_cells) { | ||
56 | pr_debug("%s: wrong #gpio-cells for %s\n", | ||
57 | np->full_name, gc->full_name); | ||
58 | ret = -EINVAL; | ||
59 | goto err1; | ||
103 | } | 60 | } |
104 | 61 | ||
105 | ret = of_gc->xlate(of_gc, np, gpio_spec); | 62 | ret = of_gc->xlate(of_gc, np, gpio_spec); |