aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors.hauer@pengutronix.de <s.hauer@pengutronix.de>2008-04-25 06:56:04 -0400
committerGrant Likely <grant.likely@secretlab.ca>2008-04-29 09:16:59 -0400
commit3cd2550c736688c7f2651134e08bd5b5db5bed70 (patch)
tree1a018f08e0fdc0a036c77722ba05f3bb08add9eb
parentf800ab44f5cd094743dc3df371bcf986375f5774 (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.txt12
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig6
-rw-r--r--arch/powerpc/platforms/52xx/Makefile2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_gpio.c465
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
186name device_type compatible Description 186name device_type compatible Description
187---- ----------- ---------- ----------- 187---- ----------- ---------- -----------
188gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers 188gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers
189gpt@<addr> gpt fsl,mpc5200-gpt-gpio General purpose
190 timers in GPIO mode
191gpio@<addr> fsl,mpc5200-gpio MPC5200 simple gpio
192 controller
193gpio@<addr> fsl,mpc5200-gpio-wkup MPC5200 wakeup gpio
194 controller
189rtc@<addr> rtc mpc5200-rtc Real time clock 195rtc@<addr> rtc mpc5200-rtc Real time clock
190mscan@<addr> mscan mpc5200-mscan CAN bus controller 196mscan@<addr> mscan mpc5200-mscan CAN bus controller
191pci@<addr> pci mpc5200-pci PCI bridge 197pci@<addr> pci mpc5200-pci PCI bridge
@@ -225,6 +231,12 @@ PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in
225i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the 231i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
226compatible field. 232compatible field.
227 233
2347) GPIO controller nodes
235Each 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
237according to the bit numbers in the GPIO control registers. The second cell
238is for flags which is currently unsused.
239
228IV - Extra Notes 240IV - 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
47config 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
14ifeq ($(CONFIG_PPC_LITE5200),y) 14ifeq ($(CONFIG_PPC_LITE5200),y)
15 obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o 15 obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o
16endif 16endif
17
18obj-$(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
30static DEFINE_SPINLOCK(gpio_lock);
31
32struct 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 */
55static 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(&regs->wkup_ival) >> (7 - gpio)) & 1;
62
63 pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
64
65 return ret;
66}
67
68static 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(&regs->wkup_dvo, chip->shadow_dvo);
82}
83
84static void
85mpc52xx_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
98static 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(&regs->wkup_ddr, chip->shadow_ddr);
111
112 /* and enable the pin */
113 chip->shadow_gpioe |= 1 << (7 - gpio);
114 out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
115
116 spin_unlock_irqrestore(&gpio_lock, flags);
117
118 return 0;
119}
120
121static int
122mpc52xx_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(&regs->wkup_ddr, chip->shadow_ddr);
137
138 /* Finally enable the pin */
139 chip->shadow_gpioe |= 1 << (7 - gpio);
140 out_8(&regs->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
149static 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(&regs->wkup_gpioe);
176 chip->shadow_ddr = in_8(&regs->wkup_ddr);
177 chip->shadow_dvo = in_8(&regs->wkup_dvo);
178
179 return 0;
180}
181
182static int mpc52xx_gpiochip_remove(struct of_device *ofdev)
183{
184 return -EBUSY;
185}
186
187static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
188 {
189 .compatible = "fsl,mpc5200-gpio-wkup",
190 },
191 {}
192};
193
194static 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 */
218static 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(&regs->simple_ival) >> (31 - gpio)) & 1;
225
226 return ret;
227}
228
229static 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(&regs->simple_dvo, chip->shadow_dvo);
242}
243
244static void
245mpc52xx_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
258static 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(&regs->simple_ddr, chip->shadow_ddr);
271
272 /* and enable the pin */
273 chip->shadow_gpioe |= 1 << (31 - gpio);
274 out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
275
276 spin_unlock_irqrestore(&gpio_lock, flags);
277
278 return 0;
279}
280
281static int
282mpc52xx_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(&regs->simple_ddr, chip->shadow_ddr);
298
299 /* Finally enable the pin */
300 chip->shadow_gpioe |= 1 << (31 - gpio);
301 out_be32(&regs->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
310static 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(&regs->simple_gpioe);
337 chip->shadow_ddr = in_be32(&regs->simple_ddr);
338 chip->shadow_dvo = in_be32(&regs->simple_dvo);
339
340 return 0;
341}
342
343static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
344 {
345 .compatible = "fsl,mpc5200-gpio",
346 },
347 {}
348};
349
350static 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 */
362static 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(&regs->status) & (1 << (31 - 23))) ? 1 : 0;
369
370 return ret;
371}
372
373static void
374mpc52xx_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(&regs->mode, 0x34);
381 else
382 out_be32(&regs->mode, 0x24);
383
384 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
385}
386
387static 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(&regs->mode, 0x04);
393
394 return 0;
395}
396
397static int
398mpc52xx_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
406static 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
428static const struct of_device_id mpc52xx_gpt_gpiochip_match[] = {
429 {
430 .compatible = "fsl,mpc5200-gpt-gpio",
431 },
432 {}
433};
434
435static 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
442static 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 */
458subsys_initcall(mpc52xx_gpio_init);
459
460/* No exit call at the moment as we cannot unregister of gpio chips */
461
462MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
463MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
464MODULE_LICENSE("GPL v2");
465