Linux 2.6.20.7
[linux/fpc-iii.git] / drivers / char / vr41xx_giu.c
blob0cea8d4907dfb965d509e356f51c18ca23118756
1 /*
2 * Driver for NEC VR4100 series General-purpose I/O Unit.
4 * Copyright (C) 2002 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
6 * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/platform_device.h>
23 #include <linux/errno.h>
24 #include <linux/fs.h>
25 #include <linux/init.h>
26 #include <linux/irq.h>
27 #include <linux/interrupt.h>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/spinlock.h>
31 #include <linux/types.h>
33 #include <asm/cpu.h>
34 #include <asm/io.h>
35 #include <asm/vr41xx/giu.h>
36 #include <asm/vr41xx/irq.h>
37 #include <asm/vr41xx/vr41xx.h>
39 MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
40 MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
41 MODULE_LICENSE("GPL");
43 static int major; /* default is dynamic major device number */
44 module_param(major, int, 0);
45 MODULE_PARM_DESC(major, "Major device number");
47 #define GIU_TYPE1_START 0x0b000100UL
48 #define GIU_TYPE1_SIZE 0x20UL
50 #define GIU_TYPE2_START 0x0f000140UL
51 #define GIU_TYPE2_SIZE 0x20UL
53 #define GIU_TYPE3_START 0x0f000140UL
54 #define GIU_TYPE3_SIZE 0x28UL
56 #define GIU_PULLUPDOWN_START 0x0b0002e0UL
57 #define GIU_PULLUPDOWN_SIZE 0x04UL
59 #define GIUIOSELL 0x00
60 #define GIUIOSELH 0x02
61 #define GIUPIODL 0x04
62 #define GIUPIODH 0x06
63 #define GIUINTSTATL 0x08
64 #define GIUINTSTATH 0x0a
65 #define GIUINTENL 0x0c
66 #define GIUINTENH 0x0e
67 #define GIUINTTYPL 0x10
68 #define GIUINTTYPH 0x12
69 #define GIUINTALSELL 0x14
70 #define GIUINTALSELH 0x16
71 #define GIUINTHTSELL 0x18
72 #define GIUINTHTSELH 0x1a
73 #define GIUPODATL 0x1c
74 #define GIUPODATEN 0x1c
75 #define GIUPODATH 0x1e
76 #define PIOEN0 0x0100
77 #define PIOEN1 0x0200
78 #define GIUPODAT 0x1e
79 #define GIUFEDGEINHL 0x20
80 #define GIUFEDGEINHH 0x22
81 #define GIUREDGEINHL 0x24
82 #define GIUREDGEINHH 0x26
84 #define GIUUSEUPDN 0x1e0
85 #define GIUTERMUPDN 0x1e2
87 #define GPIO_HAS_PULLUPDOWN_IO 0x0001
88 #define GPIO_HAS_OUTPUT_ENABLE 0x0002
89 #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
91 static spinlock_t giu_lock;
92 static struct resource *giu_resource1;
93 static struct resource *giu_resource2;
94 static unsigned long giu_flags;
95 static unsigned int giu_nr_pins;
97 static void __iomem *giu_base;
99 #define giu_read(offset) readw(giu_base + (offset))
100 #define giu_write(offset, value) writew((value), giu_base + (offset))
102 #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE)
103 #define GIUINT_HIGH_OFFSET 16
104 #define GIUINT_HIGH_MAX 32
106 static inline uint16_t giu_set(uint16_t offset, uint16_t set)
108 uint16_t data;
110 data = giu_read(offset);
111 data |= set;
112 giu_write(offset, data);
114 return data;
117 static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
119 uint16_t data;
121 data = giu_read(offset);
122 data &= ~clear;
123 giu_write(offset, data);
125 return data;
128 static void ack_giuint_low(unsigned int irq)
130 giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
133 static void mask_giuint_low(unsigned int irq)
135 giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
138 static void mask_ack_giuint_low(unsigned int irq)
140 unsigned int pin;
142 pin = GPIO_PIN_OF_IRQ(irq);
143 giu_clear(GIUINTENL, 1 << pin);
144 giu_write(GIUINTSTATL, 1 << pin);
147 static void unmask_giuint_low(unsigned int irq)
149 giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
152 static struct irq_chip giuint_low_irq_chip = {
153 .name = "GIUINTL",
154 .ack = ack_giuint_low,
155 .mask = mask_giuint_low,
156 .mask_ack = mask_ack_giuint_low,
157 .unmask = unmask_giuint_low,
160 static void ack_giuint_high(unsigned int irq)
162 giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
165 static void mask_giuint_high(unsigned int irq)
167 giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
170 static void mask_ack_giuint_high(unsigned int irq)
172 unsigned int pin;
174 pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
175 giu_clear(GIUINTENH, 1 << pin);
176 giu_write(GIUINTSTATH, 1 << pin);
179 static void unmask_giuint_high(unsigned int irq)
181 giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
184 static struct irq_chip giuint_high_irq_chip = {
185 .name = "GIUINTH",
186 .ack = ack_giuint_high,
187 .mask = mask_giuint_high,
188 .mask_ack = mask_ack_giuint_high,
189 .unmask = unmask_giuint_high,
192 static int giu_get_irq(unsigned int irq)
194 uint16_t pendl, pendh, maskl, maskh;
195 int i;
197 pendl = giu_read(GIUINTSTATL);
198 pendh = giu_read(GIUINTSTATH);
199 maskl = giu_read(GIUINTENL);
200 maskh = giu_read(GIUINTENH);
202 maskl &= pendl;
203 maskh &= pendh;
205 if (maskl) {
206 for (i = 0; i < 16; i++) {
207 if (maskl & (1 << i))
208 return GIU_IRQ(i);
210 } else if (maskh) {
211 for (i = 0; i < 16; i++) {
212 if (maskh & (1 << i))
213 return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
217 printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
218 maskl, pendl, maskh, pendh);
220 atomic_inc(&irq_err_count);
222 return -EINVAL;
225 void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
227 uint16_t mask;
229 if (pin < GIUINT_HIGH_OFFSET) {
230 mask = 1 << pin;
231 if (trigger != IRQ_TRIGGER_LEVEL) {
232 giu_set(GIUINTTYPL, mask);
233 if (signal == IRQ_SIGNAL_HOLD)
234 giu_set(GIUINTHTSELL, mask);
235 else
236 giu_clear(GIUINTHTSELL, mask);
237 if (current_cpu_data.cputype == CPU_VR4133) {
238 switch (trigger) {
239 case IRQ_TRIGGER_EDGE_FALLING:
240 giu_set(GIUFEDGEINHL, mask);
241 giu_clear(GIUREDGEINHL, mask);
242 break;
243 case IRQ_TRIGGER_EDGE_RISING:
244 giu_clear(GIUFEDGEINHL, mask);
245 giu_set(GIUREDGEINHL, mask);
246 break;
247 default:
248 giu_set(GIUFEDGEINHL, mask);
249 giu_set(GIUREDGEINHL, mask);
250 break;
253 set_irq_chip_and_handler(GIU_IRQ(pin),
254 &giuint_low_irq_chip,
255 handle_edge_irq);
256 } else {
257 giu_clear(GIUINTTYPL, mask);
258 giu_clear(GIUINTHTSELL, mask);
259 set_irq_chip_and_handler(GIU_IRQ(pin),
260 &giuint_low_irq_chip,
261 handle_level_irq);
263 giu_write(GIUINTSTATL, mask);
264 } else if (pin < GIUINT_HIGH_MAX) {
265 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
266 if (trigger != IRQ_TRIGGER_LEVEL) {
267 giu_set(GIUINTTYPH, mask);
268 if (signal == IRQ_SIGNAL_HOLD)
269 giu_set(GIUINTHTSELH, mask);
270 else
271 giu_clear(GIUINTHTSELH, mask);
272 if (current_cpu_data.cputype == CPU_VR4133) {
273 switch (trigger) {
274 case IRQ_TRIGGER_EDGE_FALLING:
275 giu_set(GIUFEDGEINHH, mask);
276 giu_clear(GIUREDGEINHH, mask);
277 break;
278 case IRQ_TRIGGER_EDGE_RISING:
279 giu_clear(GIUFEDGEINHH, mask);
280 giu_set(GIUREDGEINHH, mask);
281 break;
282 default:
283 giu_set(GIUFEDGEINHH, mask);
284 giu_set(GIUREDGEINHH, mask);
285 break;
288 set_irq_chip_and_handler(GIU_IRQ(pin),
289 &giuint_high_irq_chip,
290 handle_edge_irq);
291 } else {
292 giu_clear(GIUINTTYPH, mask);
293 giu_clear(GIUINTHTSELH, mask);
294 set_irq_chip_and_handler(GIU_IRQ(pin),
295 &giuint_high_irq_chip,
296 handle_level_irq);
298 giu_write(GIUINTSTATH, mask);
302 EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
304 void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
306 uint16_t mask;
308 if (pin < GIUINT_HIGH_OFFSET) {
309 mask = 1 << pin;
310 if (level == IRQ_LEVEL_HIGH)
311 giu_set(GIUINTALSELL, mask);
312 else
313 giu_clear(GIUINTALSELL, mask);
314 giu_write(GIUINTSTATL, mask);
315 } else if (pin < GIUINT_HIGH_MAX) {
316 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
317 if (level == IRQ_LEVEL_HIGH)
318 giu_set(GIUINTALSELH, mask);
319 else
320 giu_clear(GIUINTALSELH, mask);
321 giu_write(GIUINTSTATH, mask);
325 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
327 gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
329 uint16_t reg, mask;
331 if (pin >= giu_nr_pins)
332 return GPIO_DATA_INVAL;
334 if (pin < 16) {
335 reg = giu_read(GIUPIODL);
336 mask = (uint16_t)1 << pin;
337 } else if (pin < 32) {
338 reg = giu_read(GIUPIODH);
339 mask = (uint16_t)1 << (pin - 16);
340 } else if (pin < 48) {
341 reg = giu_read(GIUPODATL);
342 mask = (uint16_t)1 << (pin - 32);
343 } else {
344 reg = giu_read(GIUPODATH);
345 mask = (uint16_t)1 << (pin - 48);
348 if (reg & mask)
349 return GPIO_DATA_HIGH;
351 return GPIO_DATA_LOW;
354 EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
356 int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
358 uint16_t offset, mask, reg;
359 unsigned long flags;
361 if (pin >= giu_nr_pins)
362 return -EINVAL;
364 if (pin < 16) {
365 offset = GIUPIODL;
366 mask = (uint16_t)1 << pin;
367 } else if (pin < 32) {
368 offset = GIUPIODH;
369 mask = (uint16_t)1 << (pin - 16);
370 } else if (pin < 48) {
371 offset = GIUPODATL;
372 mask = (uint16_t)1 << (pin - 32);
373 } else {
374 offset = GIUPODATH;
375 mask = (uint16_t)1 << (pin - 48);
378 spin_lock_irqsave(&giu_lock, flags);
380 reg = giu_read(offset);
381 if (data == GPIO_DATA_HIGH)
382 reg |= mask;
383 else
384 reg &= ~mask;
385 giu_write(offset, reg);
387 spin_unlock_irqrestore(&giu_lock, flags);
389 return 0;
392 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
394 int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
396 uint16_t offset, mask, reg;
397 unsigned long flags;
399 if (pin >= giu_nr_pins)
400 return -EINVAL;
402 if (pin < 16) {
403 offset = GIUIOSELL;
404 mask = (uint16_t)1 << pin;
405 } else if (pin < 32) {
406 offset = GIUIOSELH;
407 mask = (uint16_t)1 << (pin - 16);
408 } else {
409 if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
410 offset = GIUPODATEN;
411 mask = (uint16_t)1 << (pin - 32);
412 } else {
413 switch (pin) {
414 case 48:
415 offset = GIUPODATH;
416 mask = PIOEN0;
417 break;
418 case 49:
419 offset = GIUPODATH;
420 mask = PIOEN1;
421 break;
422 default:
423 return -EINVAL;
428 spin_lock_irqsave(&giu_lock, flags);
430 reg = giu_read(offset);
431 if (dir == GPIO_OUTPUT)
432 reg |= mask;
433 else
434 reg &= ~mask;
435 giu_write(offset, reg);
437 spin_unlock_irqrestore(&giu_lock, flags);
439 return 0;
442 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
444 int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
446 uint16_t reg, mask;
447 unsigned long flags;
449 if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
450 return -EPERM;
452 if (pin >= 15)
453 return -EINVAL;
455 mask = (uint16_t)1 << pin;
457 spin_lock_irqsave(&giu_lock, flags);
459 if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
460 reg = giu_read(GIUTERMUPDN);
461 if (pull == GPIO_PULL_UP)
462 reg |= mask;
463 else
464 reg &= ~mask;
465 giu_write(GIUTERMUPDN, reg);
467 reg = giu_read(GIUUSEUPDN);
468 reg |= mask;
469 giu_write(GIUUSEUPDN, reg);
470 } else {
471 reg = giu_read(GIUUSEUPDN);
472 reg &= ~mask;
473 giu_write(GIUUSEUPDN, reg);
476 spin_unlock_irqrestore(&giu_lock, flags);
478 return 0;
481 EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
483 static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
484 loff_t *ppos)
486 unsigned int pin;
487 char value = '0';
489 pin = iminor(file->f_path.dentry->d_inode);
490 if (pin >= giu_nr_pins)
491 return -EBADF;
493 if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
494 value = '1';
496 if (len <= 0)
497 return -EFAULT;
499 if (put_user(value, buf))
500 return -EFAULT;
502 return 1;
505 static ssize_t gpio_write(struct file *file, const char __user *data,
506 size_t len, loff_t *ppos)
508 unsigned int pin;
509 size_t i;
510 char c;
511 int retval = 0;
513 pin = iminor(file->f_path.dentry->d_inode);
514 if (pin >= giu_nr_pins)
515 return -EBADF;
517 for (i = 0; i < len; i++) {
518 if (get_user(c, data + i))
519 return -EFAULT;
521 switch (c) {
522 case '0':
523 retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
524 break;
525 case '1':
526 retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
527 break;
528 case 'D':
529 printk(KERN_INFO "GPIO%d: pull down\n", pin);
530 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
531 break;
532 case 'd':
533 printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
534 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
535 break;
536 case 'I':
537 printk(KERN_INFO "GPIO%d: input\n", pin);
538 retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
539 break;
540 case 'O':
541 printk(KERN_INFO "GPIO%d: output\n", pin);
542 retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
543 break;
544 case 'o':
545 printk(KERN_INFO "GPIO%d: output disable\n", pin);
546 retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
547 break;
548 case 'P':
549 printk(KERN_INFO "GPIO%d: pull up\n", pin);
550 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
551 break;
552 case 'p':
553 printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
554 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
555 break;
556 default:
557 break;
560 if (retval < 0)
561 break;
564 return i;
567 static int gpio_open(struct inode *inode, struct file *file)
569 unsigned int pin;
571 pin = iminor(inode);
572 if (pin >= giu_nr_pins)
573 return -EBADF;
575 return nonseekable_open(inode, file);
578 static int gpio_release(struct inode *inode, struct file *file)
580 unsigned int pin;
582 pin = iminor(inode);
583 if (pin >= giu_nr_pins)
584 return -EBADF;
586 return 0;
589 static const struct file_operations gpio_fops = {
590 .owner = THIS_MODULE,
591 .read = gpio_read,
592 .write = gpio_write,
593 .open = gpio_open,
594 .release = gpio_release,
597 static int __devinit giu_probe(struct platform_device *dev)
599 unsigned long start, size, flags = 0;
600 unsigned int nr_pins = 0, trigger, i, pin;
601 struct resource *res1, *res2 = NULL;
602 void *base;
603 struct irq_chip *chip;
604 int retval;
606 switch (current_cpu_data.cputype) {
607 case CPU_VR4111:
608 case CPU_VR4121:
609 start = GIU_TYPE1_START;
610 size = GIU_TYPE1_SIZE;
611 flags = GPIO_HAS_PULLUPDOWN_IO;
612 nr_pins = 50;
613 break;
614 case CPU_VR4122:
615 case CPU_VR4131:
616 start = GIU_TYPE2_START;
617 size = GIU_TYPE2_SIZE;
618 nr_pins = 36;
619 break;
620 case CPU_VR4133:
621 start = GIU_TYPE3_START;
622 size = GIU_TYPE3_SIZE;
623 flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
624 nr_pins = 48;
625 break;
626 default:
627 return -ENODEV;
630 res1 = request_mem_region(start, size, "GIU");
631 if (res1 == NULL)
632 return -EBUSY;
634 base = ioremap(start, size);
635 if (base == NULL) {
636 release_resource(res1);
637 return -ENOMEM;
640 if (flags & GPIO_HAS_PULLUPDOWN_IO) {
641 res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
642 if (res2 == NULL) {
643 iounmap(base);
644 release_resource(res1);
645 return -EBUSY;
649 retval = register_chrdev(major, "GIU", &gpio_fops);
650 if (retval < 0) {
651 iounmap(base);
652 release_resource(res1);
653 release_resource(res2);
654 return retval;
657 if (major == 0) {
658 major = retval;
659 printk(KERN_INFO "GIU: major number %d\n", major);
662 spin_lock_init(&giu_lock);
663 giu_base = base;
664 giu_resource1 = res1;
665 giu_resource2 = res2;
666 giu_flags = flags;
667 giu_nr_pins = nr_pins;
669 giu_write(GIUINTENL, 0);
670 giu_write(GIUINTENH, 0);
672 trigger = giu_read(GIUINTTYPH) << 16;
673 trigger |= giu_read(GIUINTTYPL);
674 for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
675 pin = GPIO_PIN_OF_IRQ(i);
676 if (pin < GIUINT_HIGH_OFFSET)
677 chip = &giuint_low_irq_chip;
678 else
679 chip = &giuint_high_irq_chip;
681 if (trigger & (1 << pin))
682 set_irq_chip_and_handler(i, chip, handle_edge_irq);
683 else
684 set_irq_chip_and_handler(i, chip, handle_level_irq);
688 return cascade_irq(GIUINT_IRQ, giu_get_irq);
691 static int __devexit giu_remove(struct platform_device *dev)
693 iounmap(giu_base);
695 release_resource(giu_resource1);
696 if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
697 release_resource(giu_resource2);
699 return 0;
702 static struct platform_device *giu_platform_device;
704 static struct platform_driver giu_device_driver = {
705 .probe = giu_probe,
706 .remove = __devexit_p(giu_remove),
707 .driver = {
708 .name = "GIU",
709 .owner = THIS_MODULE,
713 static int __init vr41xx_giu_init(void)
715 int retval;
717 giu_platform_device = platform_device_alloc("GIU", -1);
718 if (!giu_platform_device)
719 return -ENOMEM;
721 retval = platform_device_add(giu_platform_device);
722 if (retval < 0) {
723 platform_device_put(giu_platform_device);
724 return retval;
727 retval = platform_driver_register(&giu_device_driver);
728 if (retval < 0)
729 platform_device_unregister(giu_platform_device);
731 return retval;
734 static void __exit vr41xx_giu_exit(void)
736 platform_driver_unregister(&giu_device_driver);
738 platform_device_unregister(giu_platform_device);
741 module_init(vr41xx_giu_init);
742 module_exit(vr41xx_giu_exit);