diff options
author | s.hauer@pengutronix.de <s.hauer@pengutronix.de> | 2008-04-25 06:56:04 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2008-04-29 09:16:59 -0400 |
commit | 3cd2550c736688c7f2651134e08bd5b5db5bed70 (patch) | |
tree | 1a018f08e0fdc0a036c77722ba05f3bb08add9eb | |
parent | f800ab44f5cd094743dc3df371bcf986375f5774 (diff) |
[POWERPC] mpc5200: add gpiolib support for mpc5200
This patch adds gpiolib support for mpc5200 SOCs.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r-- | Documentation/powerpc/mpc52xx-device-tree-bindings.txt | 12 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/Kconfig | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_gpio.c | 465 |
4 files changed, 485 insertions, 0 deletions
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt index 5e03610e186f..cda7a7dffa6d 100644 --- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt +++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt | |||
@@ -186,6 +186,12 @@ Recommended soc5200 child nodes; populate as needed for your board | |||
186 | name device_type compatible Description | 186 | name device_type compatible Description |
187 | ---- ----------- ---------- ----------- | 187 | ---- ----------- ---------- ----------- |
188 | gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers | 188 | gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers |
189 | gpt@<addr> gpt fsl,mpc5200-gpt-gpio General purpose | ||
190 | timers in GPIO mode | ||
191 | gpio@<addr> fsl,mpc5200-gpio MPC5200 simple gpio | ||
192 | controller | ||
193 | gpio@<addr> fsl,mpc5200-gpio-wkup MPC5200 wakeup gpio | ||
194 | controller | ||
189 | rtc@<addr> rtc mpc5200-rtc Real time clock | 195 | rtc@<addr> rtc mpc5200-rtc Real time clock |
190 | mscan@<addr> mscan mpc5200-mscan CAN bus controller | 196 | mscan@<addr> mscan mpc5200-mscan CAN bus controller |
191 | pci@<addr> pci mpc5200-pci PCI bridge | 197 | pci@<addr> pci mpc5200-pci PCI bridge |
@@ -225,6 +231,12 @@ PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in | |||
225 | i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the | 231 | i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the |
226 | compatible field. | 232 | compatible field. |
227 | 233 | ||
234 | 7) GPIO controller nodes | ||
235 | Each GPIO controller node should have the empty property gpio-controller and | ||
236 | #gpio-cells set to 2. First cell is the GPIO number which is interpreted | ||
237 | according to the bit numbers in the GPIO control registers. The second cell | ||
238 | is for flags which is currently unsused. | ||
239 | |||
228 | IV - Extra Notes | 240 | IV - Extra Notes |
229 | ================ | 241 | ================ |
230 | 242 | ||
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index cf945d55c276..acd2fc8cf492 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig | |||
@@ -44,3 +44,9 @@ config PPC_MPC5200_BUGFIX | |||
44 | 44 | ||
45 | It is safe to say 'Y' here | 45 | It is safe to say 'Y' here |
46 | 46 | ||
47 | config PPC_MPC5200_GPIO | ||
48 | bool "MPC5200 GPIO support" | ||
49 | depends on PPC_MPC52xx | ||
50 | select HAVE_GPIO_LIB | ||
51 | help | ||
52 | Enable gpiolib support for mpc5200 based boards | ||
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index fe1b81bb5224..daf0e1568d6d 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile | |||
@@ -14,3 +14,5 @@ obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o | |||
14 | ifeq ($(CONFIG_PPC_LITE5200),y) | 14 | ifeq ($(CONFIG_PPC_LITE5200),y) |
15 | obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o | 15 | obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o |
16 | endif | 16 | endif |
17 | |||
18 | obj-$(CONFIG_PPC_MPC5200_GPIO) += mpc52xx_gpio.o \ No newline at end of file | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c new file mode 100644 index 000000000000..48da5dfe4856 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c | |||
@@ -0,0 +1,465 @@ | |||
1 | /* | ||
2 | * MPC52xx gpio driver | ||
3 | * | ||
4 | * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 | ||
8 | * as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/of.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/of_gpio.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/of_platform.h> | ||
25 | |||
26 | #include <asm/gpio.h> | ||
27 | #include <asm/mpc52xx.h> | ||
28 | #include <sysdev/fsl_soc.h> | ||
29 | |||
30 | static DEFINE_SPINLOCK(gpio_lock); | ||
31 | |||
32 | struct mpc52xx_gpiochip { | ||
33 | struct of_mm_gpio_chip mmchip; | ||
34 | unsigned int shadow_dvo; | ||
35 | unsigned int shadow_gpioe; | ||
36 | unsigned int shadow_ddr; | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * GPIO LIB API implementation for wakeup GPIOs. | ||
41 | * | ||
42 | * There's a maximum of 8 wakeup GPIOs. Which of these are available | ||
43 | * for use depends on your board setup. | ||
44 | * | ||
45 | * 0 -> GPIO_WKUP_7 | ||
46 | * 1 -> GPIO_WKUP_6 | ||
47 | * 2 -> PSC6_1 | ||
48 | * 3 -> PSC6_0 | ||
49 | * 4 -> ETH_17 | ||
50 | * 5 -> PSC3_9 | ||
51 | * 6 -> PSC2_4 | ||
52 | * 7 -> PSC1_4 | ||
53 | * | ||
54 | */ | ||
55 | static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
56 | { | ||
57 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
58 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; | ||
59 | unsigned int ret; | ||
60 | |||
61 | ret = (in_8(®s->wkup_ival) >> (7 - gpio)) & 1; | ||
62 | |||
63 | pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret); | ||
64 | |||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | static inline void | ||
69 | __mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
70 | { | ||
71 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
72 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | ||
73 | struct mpc52xx_gpiochip, mmchip); | ||
74 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; | ||
75 | |||
76 | if (val) | ||
77 | chip->shadow_dvo |= 1 << (7 - gpio); | ||
78 | else | ||
79 | chip->shadow_dvo &= ~(1 << (7 - gpio)); | ||
80 | |||
81 | out_8(®s->wkup_dvo, chip->shadow_dvo); | ||
82 | } | ||
83 | |||
84 | static void | ||
85 | mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
86 | { | ||
87 | unsigned long flags; | ||
88 | |||
89 | spin_lock_irqsave(&gpio_lock, flags); | ||
90 | |||
91 | __mpc52xx_wkup_gpio_set(gc, gpio, val); | ||
92 | |||
93 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
94 | |||
95 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); | ||
96 | } | ||
97 | |||
98 | static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
99 | { | ||
100 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
101 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | ||
102 | struct mpc52xx_gpiochip, mmchip); | ||
103 | struct mpc52xx_gpio_wkup *regs = mm_gc->regs; | ||
104 | unsigned long flags; | ||
105 | |||
106 | spin_lock_irqsave(&gpio_lock, flags); | ||
107 | |||
108 | /* set the direction */ | ||
109 | chip->shadow_ddr &= ~(1 << (7 - gpio)); | ||
110 | out_8(®s->wkup_ddr, chip->shadow_ddr); | ||
111 | |||
112 | /* and enable the pin */ | ||
113 | chip->shadow_gpioe |= 1 << (7 - gpio); | ||
114 | out_8(®s->wkup_gpioe, chip->shadow_gpioe); | ||
115 | |||
116 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int | ||
122 | mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
123 | { | ||
124 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
125 | struct mpc52xx_gpio_wkup *regs = mm_gc->regs; | ||
126 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | ||
127 | struct mpc52xx_gpiochip, mmchip); | ||
128 | unsigned long flags; | ||
129 | |||
130 | spin_lock_irqsave(&gpio_lock, flags); | ||
131 | |||
132 | __mpc52xx_wkup_gpio_set(gc, gpio, val); | ||
133 | |||
134 | /* Then set direction */ | ||
135 | chip->shadow_ddr |= 1 << (7 - gpio); | ||
136 | out_8(®s->wkup_ddr, chip->shadow_ddr); | ||
137 | |||
138 | /* Finally enable the pin */ | ||
139 | chip->shadow_gpioe |= 1 << (7 - gpio); | ||
140 | out_8(®s->wkup_gpioe, chip->shadow_gpioe); | ||
141 | |||
142 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
143 | |||
144 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int __devinit mpc52xx_wkup_gpiochip_probe(struct of_device *ofdev, | ||
150 | const struct of_device_id *match) | ||
151 | { | ||
152 | struct mpc52xx_gpiochip *chip; | ||
153 | struct mpc52xx_gpio_wkup *regs; | ||
154 | struct of_gpio_chip *ofchip; | ||
155 | int ret; | ||
156 | |||
157 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
158 | if (!chip) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | ofchip = &chip->mmchip.of_gc; | ||
162 | |||
163 | ofchip->gpio_cells = 2; | ||
164 | ofchip->gc.ngpio = 8; | ||
165 | ofchip->gc.direction_input = mpc52xx_wkup_gpio_dir_in; | ||
166 | ofchip->gc.direction_output = mpc52xx_wkup_gpio_dir_out; | ||
167 | ofchip->gc.get = mpc52xx_wkup_gpio_get; | ||
168 | ofchip->gc.set = mpc52xx_wkup_gpio_set; | ||
169 | |||
170 | ret = of_mm_gpiochip_add(ofdev->node, &chip->mmchip); | ||
171 | if (ret) | ||
172 | return ret; | ||
173 | |||
174 | regs = chip->mmchip.regs; | ||
175 | chip->shadow_gpioe = in_8(®s->wkup_gpioe); | ||
176 | chip->shadow_ddr = in_8(®s->wkup_ddr); | ||
177 | chip->shadow_dvo = in_8(®s->wkup_dvo); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int mpc52xx_gpiochip_remove(struct of_device *ofdev) | ||
183 | { | ||
184 | return -EBUSY; | ||
185 | } | ||
186 | |||
187 | static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { | ||
188 | { | ||
189 | .compatible = "fsl,mpc5200-gpio-wkup", | ||
190 | }, | ||
191 | {} | ||
192 | }; | ||
193 | |||
194 | static struct of_platform_driver mpc52xx_wkup_gpiochip_driver = { | ||
195 | .name = "gpio_wkup", | ||
196 | .match_table = mpc52xx_wkup_gpiochip_match, | ||
197 | .probe = mpc52xx_wkup_gpiochip_probe, | ||
198 | .remove = mpc52xx_gpiochip_remove, | ||
199 | }; | ||
200 | |||
201 | /* | ||
202 | * GPIO LIB API implementation for simple GPIOs | ||
203 | * | ||
204 | * There's a maximum of 32 simple GPIOs. Which of these are available | ||
205 | * for use depends on your board setup. | ||
206 | * The numbering reflects the bit numbering in the port registers: | ||
207 | * | ||
208 | * 0..1 > reserved | ||
209 | * 2..3 > IRDA | ||
210 | * 4..7 > ETHR | ||
211 | * 8..11 > reserved | ||
212 | * 12..15 > USB | ||
213 | * 16..17 > reserved | ||
214 | * 18..23 > PSC3 | ||
215 | * 24..27 > PSC2 | ||
216 | * 28..31 > PSC1 | ||
217 | */ | ||
218 | static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
219 | { | ||
220 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
221 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; | ||
222 | unsigned int ret; | ||
223 | |||
224 | ret = (in_be32(®s->simple_ival) >> (31 - gpio)) & 1; | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static inline void | ||
230 | __mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
231 | { | ||
232 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
233 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | ||
234 | struct mpc52xx_gpiochip, mmchip); | ||
235 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; | ||
236 | |||
237 | if (val) | ||
238 | chip->shadow_dvo |= 1 << (31 - gpio); | ||
239 | else | ||
240 | chip->shadow_dvo &= ~(1 << (31 - gpio)); | ||
241 | out_be32(®s->simple_dvo, chip->shadow_dvo); | ||
242 | } | ||
243 | |||
244 | static void | ||
245 | mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
246 | { | ||
247 | unsigned long flags; | ||
248 | |||
249 | spin_lock_irqsave(&gpio_lock, flags); | ||
250 | |||
251 | __mpc52xx_simple_gpio_set(gc, gpio, val); | ||
252 | |||
253 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
254 | |||
255 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); | ||
256 | } | ||
257 | |||
258 | static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
259 | { | ||
260 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
261 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | ||
262 | struct mpc52xx_gpiochip, mmchip); | ||
263 | struct mpc52xx_gpio *regs = mm_gc->regs; | ||
264 | unsigned long flags; | ||
265 | |||
266 | spin_lock_irqsave(&gpio_lock, flags); | ||
267 | |||
268 | /* set the direction */ | ||
269 | chip->shadow_ddr &= ~(1 << (31 - gpio)); | ||
270 | out_be32(®s->simple_ddr, chip->shadow_ddr); | ||
271 | |||
272 | /* and enable the pin */ | ||
273 | chip->shadow_gpioe |= 1 << (31 - gpio); | ||
274 | out_be32(®s->simple_gpioe, chip->shadow_gpioe); | ||
275 | |||
276 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int | ||
282 | mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
283 | { | ||
284 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
285 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | ||
286 | struct mpc52xx_gpiochip, mmchip); | ||
287 | struct mpc52xx_gpio *regs = mm_gc->regs; | ||
288 | unsigned long flags; | ||
289 | |||
290 | spin_lock_irqsave(&gpio_lock, flags); | ||
291 | |||
292 | /* First set initial value */ | ||
293 | __mpc52xx_simple_gpio_set(gc, gpio, val); | ||
294 | |||
295 | /* Then set direction */ | ||
296 | chip->shadow_ddr |= 1 << (31 - gpio); | ||
297 | out_be32(®s->simple_ddr, chip->shadow_ddr); | ||
298 | |||
299 | /* Finally enable the pin */ | ||
300 | chip->shadow_gpioe |= 1 << (31 - gpio); | ||
301 | out_be32(®s->simple_gpioe, chip->shadow_gpioe); | ||
302 | |||
303 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
304 | |||
305 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev, | ||
311 | const struct of_device_id *match) | ||
312 | { | ||
313 | struct mpc52xx_gpiochip *chip; | ||
314 | struct of_gpio_chip *ofchip; | ||
315 | struct mpc52xx_gpio *regs; | ||
316 | int ret; | ||
317 | |||
318 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
319 | if (!chip) | ||
320 | return -ENOMEM; | ||
321 | |||
322 | ofchip = &chip->mmchip.of_gc; | ||
323 | |||
324 | ofchip->gpio_cells = 2; | ||
325 | ofchip->gc.ngpio = 32; | ||
326 | ofchip->gc.direction_input = mpc52xx_simple_gpio_dir_in; | ||
327 | ofchip->gc.direction_output = mpc52xx_simple_gpio_dir_out; | ||
328 | ofchip->gc.get = mpc52xx_simple_gpio_get; | ||
329 | ofchip->gc.set = mpc52xx_simple_gpio_set; | ||
330 | |||
331 | ret = of_mm_gpiochip_add(ofdev->node, &chip->mmchip); | ||
332 | if (ret) | ||
333 | return ret; | ||
334 | |||
335 | regs = chip->mmchip.regs; | ||
336 | chip->shadow_gpioe = in_be32(®s->simple_gpioe); | ||
337 | chip->shadow_ddr = in_be32(®s->simple_ddr); | ||
338 | chip->shadow_dvo = in_be32(®s->simple_dvo); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static const struct of_device_id mpc52xx_simple_gpiochip_match[] = { | ||
344 | { | ||
345 | .compatible = "fsl,mpc5200-gpio", | ||
346 | }, | ||
347 | {} | ||
348 | }; | ||
349 | |||
350 | static struct of_platform_driver mpc52xx_simple_gpiochip_driver = { | ||
351 | .name = "gpio", | ||
352 | .match_table = mpc52xx_simple_gpiochip_match, | ||
353 | .probe = mpc52xx_simple_gpiochip_probe, | ||
354 | .remove = mpc52xx_gpiochip_remove, | ||
355 | }; | ||
356 | |||
357 | /* | ||
358 | * GPIO LIB API implementation for gpt GPIOs. | ||
359 | * | ||
360 | * Each gpt only has a single GPIO. | ||
361 | */ | ||
362 | static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
363 | { | ||
364 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
365 | struct mpc52xx_gpt __iomem *regs = mm_gc->regs; | ||
366 | unsigned int ret; | ||
367 | |||
368 | return (in_be32(®s->status) & (1 << (31 - 23))) ? 1 : 0; | ||
369 | |||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | static void | ||
374 | mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
375 | { | ||
376 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
377 | struct mpc52xx_gpt __iomem *regs = mm_gc->regs; | ||
378 | |||
379 | if (val) | ||
380 | out_be32(®s->mode, 0x34); | ||
381 | else | ||
382 | out_be32(®s->mode, 0x24); | ||
383 | |||
384 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); | ||
385 | } | ||
386 | |||
387 | static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
388 | { | ||
389 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
390 | struct mpc52xx_gpt *regs = mm_gc->regs; | ||
391 | |||
392 | out_be32(®s->mode, 0x04); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static int | ||
398 | mpc52xx_gpt_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
399 | { | ||
400 | mpc52xx_gpt_gpio_set(gc, gpio, val); | ||
401 | pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int __devinit mpc52xx_gpt_gpiochip_probe(struct of_device *ofdev, | ||
407 | const struct of_device_id *match) | ||
408 | { | ||
409 | struct of_mm_gpio_chip *mmchip; | ||
410 | struct of_gpio_chip *chip; | ||
411 | |||
412 | mmchip = kzalloc(sizeof(*mmchip), GFP_KERNEL); | ||
413 | if (!mmchip) | ||
414 | return -ENOMEM; | ||
415 | |||
416 | chip = &mmchip->of_gc; | ||
417 | |||
418 | chip->gpio_cells = 2; | ||
419 | chip->gc.ngpio = 1; | ||
420 | chip->gc.direction_input = mpc52xx_gpt_gpio_dir_in; | ||
421 | chip->gc.direction_output = mpc52xx_gpt_gpio_dir_out; | ||
422 | chip->gc.get = mpc52xx_gpt_gpio_get; | ||
423 | chip->gc.set = mpc52xx_gpt_gpio_set; | ||
424 | |||
425 | return of_mm_gpiochip_add(ofdev->node, mmchip); | ||
426 | } | ||
427 | |||
428 | static const struct of_device_id mpc52xx_gpt_gpiochip_match[] = { | ||
429 | { | ||
430 | .compatible = "fsl,mpc5200-gpt-gpio", | ||
431 | }, | ||
432 | {} | ||
433 | }; | ||
434 | |||
435 | static struct of_platform_driver mpc52xx_gpt_gpiochip_driver = { | ||
436 | .name = "gpio_gpt", | ||
437 | .match_table = mpc52xx_gpt_gpiochip_match, | ||
438 | .probe = mpc52xx_gpt_gpiochip_probe, | ||
439 | .remove = mpc52xx_gpiochip_remove, | ||
440 | }; | ||
441 | |||
442 | static int __init mpc52xx_gpio_init(void) | ||
443 | { | ||
444 | if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver)) | ||
445 | printk(KERN_ERR "Unable to register wakeup GPIO driver\n"); | ||
446 | |||
447 | if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver)) | ||
448 | printk(KERN_ERR "Unable to register simple GPIO driver\n"); | ||
449 | |||
450 | if (of_register_platform_driver(&mpc52xx_gpt_gpiochip_driver)) | ||
451 | printk(KERN_ERR "Unable to register gpt GPIO driver\n"); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | |||
457 | /* Make sure we get initialised before anyone else tries to use us */ | ||
458 | subsys_initcall(mpc52xx_gpio_init); | ||
459 | |||
460 | /* No exit call at the moment as we cannot unregister of gpio chips */ | ||
461 | |||
462 | MODULE_DESCRIPTION("Freescale MPC52xx gpio driver"); | ||
463 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); | ||
464 | MODULE_LICENSE("GPL v2"); | ||
465 | |||