diff options
Diffstat (limited to 'drivers/char/vr41xx_giu.c')
-rw-r--r-- | drivers/char/vr41xx_giu.c | 132 |
1 files changed, 34 insertions, 98 deletions
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 0cea8d4907df..e5ed09192be8 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
@@ -19,18 +19,17 @@ | |||
19 | * along with this program; if not, write to the Free Software | 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 | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
24 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/irq.h> | ||
27 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/irq.h> | ||
28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | 32 | ||
33 | #include <asm/cpu.h> | ||
34 | #include <asm/io.h> | 33 | #include <asm/io.h> |
35 | #include <asm/vr41xx/giu.h> | 34 | #include <asm/vr41xx/giu.h> |
36 | #include <asm/vr41xx/irq.h> | 35 | #include <asm/vr41xx/irq.h> |
@@ -44,18 +43,6 @@ static int major; /* default is dynamic major device number */ | |||
44 | module_param(major, int, 0); | 43 | module_param(major, int, 0); |
45 | MODULE_PARM_DESC(major, "Major device number"); | 44 | MODULE_PARM_DESC(major, "Major device number"); |
46 | 45 | ||
47 | #define GIU_TYPE1_START 0x0b000100UL | ||
48 | #define GIU_TYPE1_SIZE 0x20UL | ||
49 | |||
50 | #define GIU_TYPE2_START 0x0f000140UL | ||
51 | #define GIU_TYPE2_SIZE 0x20UL | ||
52 | |||
53 | #define GIU_TYPE3_START 0x0f000140UL | ||
54 | #define GIU_TYPE3_SIZE 0x28UL | ||
55 | |||
56 | #define GIU_PULLUPDOWN_START 0x0b0002e0UL | ||
57 | #define GIU_PULLUPDOWN_SIZE 0x04UL | ||
58 | |||
59 | #define GIUIOSELL 0x00 | 46 | #define GIUIOSELL 0x00 |
60 | #define GIUIOSELH 0x02 | 47 | #define GIUIOSELH 0x02 |
61 | #define GIUPIODL 0x04 | 48 | #define GIUPIODL 0x04 |
@@ -89,8 +76,6 @@ MODULE_PARM_DESC(major, "Major device number"); | |||
89 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 | 76 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 |
90 | 77 | ||
91 | static spinlock_t giu_lock; | 78 | static spinlock_t giu_lock; |
92 | static struct resource *giu_resource1; | ||
93 | static struct resource *giu_resource2; | ||
94 | static unsigned long giu_flags; | 79 | static unsigned long giu_flags; |
95 | static unsigned int giu_nr_pins; | 80 | static unsigned int giu_nr_pins; |
96 | 81 | ||
@@ -234,7 +219,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
234 | giu_set(GIUINTHTSELL, mask); | 219 | giu_set(GIUINTHTSELL, mask); |
235 | else | 220 | else |
236 | giu_clear(GIUINTHTSELL, mask); | 221 | giu_clear(GIUINTHTSELL, mask); |
237 | if (current_cpu_data.cputype == CPU_VR4133) { | 222 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { |
238 | switch (trigger) { | 223 | switch (trigger) { |
239 | case IRQ_TRIGGER_EDGE_FALLING: | 224 | case IRQ_TRIGGER_EDGE_FALLING: |
240 | giu_set(GIUFEDGEINHL, mask); | 225 | giu_set(GIUFEDGEINHL, mask); |
@@ -269,7 +254,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
269 | giu_set(GIUINTHTSELH, mask); | 254 | giu_set(GIUINTHTSELH, mask); |
270 | else | 255 | else |
271 | giu_clear(GIUINTHTSELH, mask); | 256 | giu_clear(GIUINTHTSELH, mask); |
272 | if (current_cpu_data.cputype == CPU_VR4133) { | 257 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { |
273 | switch (trigger) { | 258 | switch (trigger) { |
274 | case IRQ_TRIGGER_EDGE_FALLING: | 259 | case IRQ_TRIGGER_EDGE_FALLING: |
275 | giu_set(GIUFEDGEINHH, mask); | 260 | giu_set(GIUFEDGEINHH, mask); |
@@ -298,7 +283,6 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
298 | giu_write(GIUINTSTATH, mask); | 283 | giu_write(GIUINTSTATH, mask); |
299 | } | 284 | } |
300 | } | 285 | } |
301 | |||
302 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | 286 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); |
303 | 287 | ||
304 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | 288 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) |
@@ -321,7 +305,6 @@ void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | |||
321 | giu_write(GIUINTSTATH, mask); | 305 | giu_write(GIUINTSTATH, mask); |
322 | } | 306 | } |
323 | } | 307 | } |
324 | |||
325 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | 308 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); |
326 | 309 | ||
327 | gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) | 310 | gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) |
@@ -350,7 +333,6 @@ gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) | |||
350 | 333 | ||
351 | return GPIO_DATA_LOW; | 334 | return GPIO_DATA_LOW; |
352 | } | 335 | } |
353 | |||
354 | EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); | 336 | EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); |
355 | 337 | ||
356 | int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) | 338 | int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) |
@@ -388,7 +370,6 @@ int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) | |||
388 | 370 | ||
389 | return 0; | 371 | return 0; |
390 | } | 372 | } |
391 | |||
392 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); | 373 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); |
393 | 374 | ||
394 | int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) | 375 | int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) |
@@ -438,7 +419,6 @@ int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) | |||
438 | 419 | ||
439 | return 0; | 420 | return 0; |
440 | } | 421 | } |
441 | |||
442 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); | 422 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); |
443 | 423 | ||
444 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | 424 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) |
@@ -477,7 +457,6 @@ int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | |||
477 | 457 | ||
478 | return 0; | 458 | return 0; |
479 | } | 459 | } |
480 | |||
481 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | 460 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); |
482 | 461 | ||
483 | static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, | 462 | static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, |
@@ -596,61 +575,40 @@ static const struct file_operations gpio_fops = { | |||
596 | 575 | ||
597 | static int __devinit giu_probe(struct platform_device *dev) | 576 | static int __devinit giu_probe(struct platform_device *dev) |
598 | { | 577 | { |
599 | unsigned long start, size, flags = 0; | 578 | struct resource *res; |
600 | unsigned int nr_pins = 0, trigger, i, pin; | 579 | unsigned int trigger, i, pin; |
601 | struct resource *res1, *res2 = NULL; | ||
602 | void *base; | ||
603 | struct irq_chip *chip; | 580 | struct irq_chip *chip; |
604 | int retval; | 581 | int irq, retval; |
605 | 582 | ||
606 | switch (current_cpu_data.cputype) { | 583 | switch (dev->id) { |
607 | case CPU_VR4111: | 584 | case GPIO_50PINS_PULLUPDOWN: |
608 | case CPU_VR4121: | 585 | giu_flags = GPIO_HAS_PULLUPDOWN_IO; |
609 | start = GIU_TYPE1_START; | 586 | giu_nr_pins = 50; |
610 | size = GIU_TYPE1_SIZE; | ||
611 | flags = GPIO_HAS_PULLUPDOWN_IO; | ||
612 | nr_pins = 50; | ||
613 | break; | 587 | break; |
614 | case CPU_VR4122: | 588 | case GPIO_36PINS: |
615 | case CPU_VR4131: | 589 | giu_nr_pins = 36; |
616 | start = GIU_TYPE2_START; | ||
617 | size = GIU_TYPE2_SIZE; | ||
618 | nr_pins = 36; | ||
619 | break; | 590 | break; |
620 | case CPU_VR4133: | 591 | case GPIO_48PINS_EDGE_SELECT: |
621 | start = GIU_TYPE3_START; | 592 | giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; |
622 | size = GIU_TYPE3_SIZE; | 593 | giu_nr_pins = 48; |
623 | flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | ||
624 | nr_pins = 48; | ||
625 | break; | 594 | break; |
626 | default: | 595 | default: |
596 | printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); | ||
627 | return -ENODEV; | 597 | return -ENODEV; |
628 | } | 598 | } |
629 | 599 | ||
630 | res1 = request_mem_region(start, size, "GIU"); | 600 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
631 | if (res1 == NULL) | 601 | if (!res) |
632 | return -EBUSY; | 602 | return -EBUSY; |
633 | 603 | ||
634 | base = ioremap(start, size); | 604 | giu_base = ioremap(res->start, res->end - res->start + 1); |
635 | if (base == NULL) { | 605 | if (!giu_base) |
636 | release_resource(res1); | ||
637 | return -ENOMEM; | 606 | return -ENOMEM; |
638 | } | ||
639 | |||
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; | ||
646 | } | ||
647 | } | ||
648 | 607 | ||
649 | retval = register_chrdev(major, "GIU", &gpio_fops); | 608 | retval = register_chrdev(major, "GIU", &gpio_fops); |
650 | if (retval < 0) { | 609 | if (retval < 0) { |
651 | iounmap(base); | 610 | iounmap(giu_base); |
652 | release_resource(res1); | 611 | giu_base = NULL; |
653 | release_resource(res2); | ||
654 | return retval; | 612 | return retval; |
655 | } | 613 | } |
656 | 614 | ||
@@ -660,11 +618,6 @@ static int __devinit giu_probe(struct platform_device *dev) | |||
660 | } | 618 | } |
661 | 619 | ||
662 | spin_lock_init(&giu_lock); | 620 | 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; | ||
668 | 621 | ||
669 | giu_write(GIUINTENL, 0); | 622 | giu_write(GIUINTENL, 0); |
670 | giu_write(GIUINTENH, 0); | 623 | giu_write(GIUINTENH, 0); |
@@ -685,22 +638,23 @@ static int __devinit giu_probe(struct platform_device *dev) | |||
685 | 638 | ||
686 | } | 639 | } |
687 | 640 | ||
688 | return cascade_irq(GIUINT_IRQ, giu_get_irq); | 641 | irq = platform_get_irq(dev, 0); |
642 | if (irq < 0 || irq >= NR_IRQS) | ||
643 | return -EBUSY; | ||
644 | |||
645 | return cascade_irq(irq, giu_get_irq); | ||
689 | } | 646 | } |
690 | 647 | ||
691 | static int __devexit giu_remove(struct platform_device *dev) | 648 | static int __devexit giu_remove(struct platform_device *dev) |
692 | { | 649 | { |
693 | iounmap(giu_base); | 650 | if (giu_base) { |
694 | 651 | iounmap(giu_base); | |
695 | release_resource(giu_resource1); | 652 | giu_base = NULL; |
696 | if (giu_flags & GPIO_HAS_PULLUPDOWN_IO) | 653 | } |
697 | release_resource(giu_resource2); | ||
698 | 654 | ||
699 | return 0; | 655 | return 0; |
700 | } | 656 | } |
701 | 657 | ||
702 | static struct platform_device *giu_platform_device; | ||
703 | |||
704 | static struct platform_driver giu_device_driver = { | 658 | static struct platform_driver giu_device_driver = { |
705 | .probe = giu_probe, | 659 | .probe = giu_probe, |
706 | .remove = __devexit_p(giu_remove), | 660 | .remove = __devexit_p(giu_remove), |
@@ -712,30 +666,12 @@ static struct platform_driver giu_device_driver = { | |||
712 | 666 | ||
713 | static int __init vr41xx_giu_init(void) | 667 | static int __init vr41xx_giu_init(void) |
714 | { | 668 | { |
715 | int retval; | 669 | return platform_driver_register(&giu_device_driver); |
716 | |||
717 | giu_platform_device = platform_device_alloc("GIU", -1); | ||
718 | if (!giu_platform_device) | ||
719 | return -ENOMEM; | ||
720 | |||
721 | retval = platform_device_add(giu_platform_device); | ||
722 | if (retval < 0) { | ||
723 | platform_device_put(giu_platform_device); | ||
724 | return retval; | ||
725 | } | ||
726 | |||
727 | retval = platform_driver_register(&giu_device_driver); | ||
728 | if (retval < 0) | ||
729 | platform_device_unregister(giu_platform_device); | ||
730 | |||
731 | return retval; | ||
732 | } | 670 | } |
733 | 671 | ||
734 | static void __exit vr41xx_giu_exit(void) | 672 | static void __exit vr41xx_giu_exit(void) |
735 | { | 673 | { |
736 | platform_driver_unregister(&giu_device_driver); | 674 | platform_driver_unregister(&giu_device_driver); |
737 | |||
738 | platform_device_unregister(giu_platform_device); | ||
739 | } | 675 | } |
740 | 676 | ||
741 | module_init(vr41xx_giu_init); | 677 | module_init(vr41xx_giu_init); |