aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-06-08 09:48:16 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-07-05 18:14:30 -0400
commit594fa265e084073443390c5b93d5410fd28e9bcd (patch)
tree42c0e5536ae2fd016159e1e1bd1f27f0a9f3cac2
parenta19e3da5bc5fc6c10ab73f310bea80f3845b4531 (diff)
of/gpio: stop using device_node data pointer to find gpio_chip
Currently the kernel uses the struct device_node.data pointer to resolve a struct gpio_chip pointer from a device tree node. However, the .data member doesn't provide any type checking and there aren't any rules enforced on what it should be used for. There's no guarantee that the data stored in it actually points to an gpio_chip pointer. Instead of relying on the .data pointer, this patch modifies the code to add a lookup function which scans through the registered gpio_chips and returns the gpio_chip that has a pointer to the specified device_node. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> CC: Andrew Morton <akpm@linux-foundation.org> CC: Anton Vorontsov <avorontsov@ru.mvista.com> CC: Grant Likely <grant.likely@secretlab.ca> CC: David Brownell <dbrownell@users.sourceforge.net> CC: Bill Gatliff <bgat@billgatliff.com> CC: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> CC: Benjamin Herrenschmidt <benh@kernel.crashing.org> CC: Jean Delvare <khali@linux-fr.org> CC: linux-kernel@vger.kernel.org CC: devicetree-discuss@lists.ozlabs.org
-rw-r--r--arch/microblaze/kernel/reset.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_gpt.c1
-rw-r--r--arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c23
-rw-r--r--arch/powerpc/sysdev/qe_lib/gpio.c2
-rw-r--r--drivers/gpio/gpiolib.c32
-rw-r--r--drivers/of/gpio.c15
-rw-r--r--include/asm-generic/gpio.h3
-rw-r--r--include/linux/of_gpio.h3
8 files changed, 56 insertions, 25 deletions
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
index 5476d3caf045..bd8ccab5ceff 100644
--- a/arch/microblaze/kernel/reset.c
+++ b/arch/microblaze/kernel/reset.c
@@ -39,7 +39,7 @@ static int of_reset_gpio_handle(void)
39 goto err0; 39 goto err0;
40 } 40 }
41 41
42 gc = gpio->data; 42 gc = of_node_to_gpiochip(gpio);
43 if (!gc) { 43 if (!gc) {
44 pr_debug("%s: gpio controller %s isn't registered\n", 44 pr_debug("%s: gpio controller %s isn't registered\n",
45 root->full_name, gpio->full_name); 45 root->full_name, gpio->full_name);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index 3f2ee47f1d01..6e82bd27132c 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -350,6 +350,7 @@ mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
350 gpt->gc.base = -1; 350 gpt->gc.base = -1;
351 gpt->gc.of_gpio_n_cells = 2; 351 gpt->gc.of_gpio_n_cells = 2;
352 gpt->gc.of_xlate = of_gpio_simple_xlate; 352 gpt->gc.of_xlate = of_gpio_simple_xlate;
353 gpt->gc.of_node = node;
353 of_node_get(node); 354 of_node_get(node);
354 355
355 /* Setup external pin in GPIO mode */ 356 /* Setup external pin in GPIO mode */
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
index e49f4bd2f991..f0dbace6185a 100644
--- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
+++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
@@ -35,7 +35,6 @@
35 35
36struct mcu { 36struct mcu {
37 struct mutex lock; 37 struct mutex lock;
38 struct device_node *np;
39 struct i2c_client *client; 38 struct i2c_client *client;
40 struct gpio_chip gc; 39 struct gpio_chip gc;
41 u8 reg_ctrl; 40 u8 reg_ctrl;
@@ -79,7 +78,6 @@ static int mcu_gpiochip_add(struct mcu *mcu)
79{ 78{
80 struct device_node *np; 79 struct device_node *np;
81 struct gpio_chip *gc = &mcu->gc; 80 struct gpio_chip *gc = &mcu->gc;
82 int ret;
83 81
84 np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx"); 82 np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
85 if (!np) 83 if (!np)
@@ -94,29 +92,14 @@ static int mcu_gpiochip_add(struct mcu *mcu)
94 gc->direction_output = mcu_gpio_dir_out; 92 gc->direction_output = mcu_gpio_dir_out;
95 gc->of_gpio_n_cells = 2; 93 gc->of_gpio_n_cells = 2;
96 gc->of_xlate = of_gpio_simple_xlate; 94 gc->of_xlate = of_gpio_simple_xlate;
95 gc->of_node = np;
97 96
98 mcu->np = np; 97 return gpiochip_add(gc);
99
100 /*
101 * We don't want to lose the node, its ->data and ->full_name...
102 * So, if succeeded, we don't put the node here.
103 */
104 ret = gpiochip_add(gc);
105 if (ret)
106 of_node_put(np);
107 return ret;
108} 98}
109 99
110static int mcu_gpiochip_remove(struct mcu *mcu) 100static int mcu_gpiochip_remove(struct mcu *mcu)
111{ 101{
112 int ret; 102 return gpiochip_remove(&mcu->gc);
113
114 ret = gpiochip_remove(&mcu->gc);
115 if (ret)
116 return ret;
117 of_node_put(mcu->np);
118
119 return 0;
120} 103}
121 104
122static int __devinit mcu_probe(struct i2c_client *client, 105static int __devinit mcu_probe(struct i2c_client *client,
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
index 194478c2f4b4..32e9440010a1 100644
--- a/arch/powerpc/sysdev/qe_lib/gpio.c
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -167,7 +167,7 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index)
167 goto err1; 167 goto err1;
168 } 168 }
169 169
170 gc = gpio_np->data; 170 gc = of_node_to_gpiochip(gpio_np);
171 if (!gc) { 171 if (!gc) {
172 pr_debug("%s: gpio controller %s isn't registered\n", 172 pr_debug("%s: gpio controller %s isn't registered\n",
173 np->full_name, gpio_np->full_name); 173 np->full_name, gpio_np->full_name);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 713ca0e37f23..73fd328f6fe4 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1153,6 +1153,38 @@ int gpiochip_remove(struct gpio_chip *chip)
1153} 1153}
1154EXPORT_SYMBOL_GPL(gpiochip_remove); 1154EXPORT_SYMBOL_GPL(gpiochip_remove);
1155 1155
1156/**
1157 * gpiochip_find() - iterator for locating a specific gpio_chip
1158 * @data: data to pass to match function
1159 * @callback: Callback function to check gpio_chip
1160 *
1161 * Similar to bus_find_device. It returns a reference to a gpio_chip as
1162 * determined by a user supplied @match callback. The callback should return
1163 * 0 if the device doesn't match and non-zero if it does. If the callback is
1164 * non-zero, this function will return to the caller and not iterate over any
1165 * more gpio_chips.
1166 */
1167struct gpio_chip *gpiochip_find(void *data,
1168 int (*match)(struct gpio_chip *chip, void *data))
1169{
1170 struct gpio_chip *chip = NULL;
1171 unsigned long flags;
1172 int i;
1173
1174 spin_lock_irqsave(&gpio_lock, flags);
1175 for (i = 0; i < ARCH_NR_GPIOS; i++) {
1176 if (!gpio_desc[i].chip)
1177 continue;
1178
1179 if (match(gpio_desc[i].chip, data)) {
1180 chip = gpio_desc[i].chip;
1181 break;
1182 }
1183 }
1184 spin_unlock_irqrestore(&gpio_lock, flags);
1185
1186 return chip;
1187}
1156 1188
1157/* These "optional" allocation calls help prevent drivers from stomping 1189/* These "optional" allocation calls help prevent drivers from stomping
1158 * on each other, and help provide better diagnostics in debugfs. 1190 * on each other, and help provide better diagnostics in debugfs.
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index fde53a3a45a3..c8618d3282cf 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -46,7 +46,7 @@ int of_get_gpio_flags(struct device_node *np, int index,
46 goto err0; 46 goto err0;
47 } 47 }
48 48
49 gc = gpio_np->data; 49 gc = of_node_to_gpiochip(gpio_np);
50 if (!gc) { 50 if (!gc) {
51 pr_debug("%s: gpio controller %s isn't registered\n", 51 pr_debug("%s: gpio controller %s isn't registered\n",
52 np->full_name, gpio_np->full_name); 52 np->full_name, gpio_np->full_name);
@@ -193,7 +193,6 @@ int of_mm_gpiochip_add(struct device_node *np,
193 if (mm_gc->save_regs) 193 if (mm_gc->save_regs)
194 mm_gc->save_regs(mm_gc); 194 mm_gc->save_regs(mm_gc);
195 195
196 np->data = &mm_gc->gc;
197 mm_gc->gc.of_node = np; 196 mm_gc->gc.of_node = np;
198 197
199 ret = gpiochip_add(gc); 198 ret = gpiochip_add(gc);
@@ -207,7 +206,6 @@ int of_mm_gpiochip_add(struct device_node *np,
207 np->full_name, gc->base); 206 np->full_name, gc->base);
208 return 0; 207 return 0;
209err2: 208err2:
210 np->data = NULL;
211 iounmap(mm_gc->regs); 209 iounmap(mm_gc->regs);
212err1: 210err1:
213 kfree(gc->label); 211 kfree(gc->label);
@@ -217,3 +215,14 @@ err0:
217 return ret; 215 return ret;
218} 216}
219EXPORT_SYMBOL(of_mm_gpiochip_add); 217EXPORT_SYMBOL(of_mm_gpiochip_add);
218
219/* Private function for resolving node pointer to gpio_chip */
220static int of_gpiochip_is_match(struct gpio_chip *chip, void *data)
221{
222 return chip->of_node == data;
223}
224
225struct gpio_chip *of_node_to_gpiochip(struct device_node *np)
226{
227 return gpiochip_find(np, of_gpiochip_is_match);
228}
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index af2544ef0b59..c7376bf80b06 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -127,6 +127,9 @@ extern int __must_check gpiochip_reserve(int start, int ngpio);
127/* add/remove chips */ 127/* add/remove chips */
128extern int gpiochip_add(struct gpio_chip *chip); 128extern int gpiochip_add(struct gpio_chip *chip);
129extern int __must_check gpiochip_remove(struct gpio_chip *chip); 129extern int __must_check gpiochip_remove(struct gpio_chip *chip);
130extern struct gpio_chip *gpiochip_find(void *data,
131 int (*match)(struct gpio_chip *chip,
132 void *data));
130 133
131 134
132/* Always use the library code for GPIO management calls, 135/* Always use the library code for GPIO management calls,
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 460d6810c5eb..1020587efed1 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -54,6 +54,9 @@ extern int of_mm_gpiochip_add(struct device_node *np,
54 struct of_mm_gpio_chip *mm_gc); 54 struct of_mm_gpio_chip *mm_gc);
55extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np, 55extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
56 const void *gpio_spec, u32 *flags); 56 const void *gpio_spec, u32 *flags);
57
58extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
59
57#else /* CONFIG_OF_GPIO */ 60#else /* CONFIG_OF_GPIO */
58 61
59/* Drivers may not strictly depend on the GPIO support, so let them link. */ 62/* Drivers may not strictly depend on the GPIO support, so let them link. */