Commit 44173fb2e83183b585e137e6fee8ba32460f5645
Committed by
Ralf Baechle
1 parent
a74b460518
Exists in
master
and in
7 other branches
[MIPS] Separate platform_device registration for VR41xx GPIO
Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Showing 4 changed files with 166 additions and 99 deletions Side-by-side Diff
arch/mips/vr41xx/common/Makefile
arch/mips/vr41xx/common/giu.c
1 | +/* | |
2 | + * NEC VR4100 series GIU platform device. | |
3 | + * | |
4 | + * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | |
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 as published by | |
8 | + * the Free Software Foundation; either version 2 of the License, or | |
9 | + * (at your option) any later version. | |
10 | + * | |
11 | + * This program is distributed in the hope that it will be useful, | |
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + * GNU General Public License for more details. | |
15 | + * | |
16 | + * You should have received a copy of the GNU General Public License | |
17 | + * along with this program; if not, write to the Free Software | |
18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | + */ | |
20 | +#include <linux/errno.h> | |
21 | +#include <linux/init.h> | |
22 | +#include <linux/ioport.h> | |
23 | +#include <linux/platform_device.h> | |
24 | + | |
25 | +#include <asm/cpu.h> | |
26 | +#include <asm/vr41xx/giu.h> | |
27 | +#include <asm/vr41xx/irq.h> | |
28 | + | |
29 | +static struct resource giu_50pins_pullupdown_resource[] __initdata = { | |
30 | + { | |
31 | + .start = 0x0b000100, | |
32 | + .end = 0x0b00011f, | |
33 | + .flags = IORESOURCE_MEM, | |
34 | + }, | |
35 | + { | |
36 | + .start = 0x0b0002e0, | |
37 | + .end = 0x0b0002e3, | |
38 | + .flags = IORESOURCE_MEM, | |
39 | + }, | |
40 | + { | |
41 | + .start = GIUINT_IRQ, | |
42 | + .end = GIUINT_IRQ, | |
43 | + .flags = IORESOURCE_IRQ, | |
44 | + }, | |
45 | +}; | |
46 | + | |
47 | +static struct resource giu_36pins_resource[] __initdata = { | |
48 | + { | |
49 | + .start = 0x0f000140, | |
50 | + .end = 0x0f00015f, | |
51 | + .flags = IORESOURCE_MEM, | |
52 | + }, | |
53 | + { | |
54 | + .start = GIUINT_IRQ, | |
55 | + .end = GIUINT_IRQ, | |
56 | + .flags = IORESOURCE_IRQ, | |
57 | + }, | |
58 | +}; | |
59 | + | |
60 | +static struct resource giu_48pins_resource[] __initdata = { | |
61 | + { | |
62 | + .start = 0x0f000140, | |
63 | + .end = 0x0f000167, | |
64 | + .flags = IORESOURCE_MEM, | |
65 | + }, | |
66 | + { | |
67 | + .start = GIUINT_IRQ, | |
68 | + .end = GIUINT_IRQ, | |
69 | + .flags = IORESOURCE_IRQ, | |
70 | + }, | |
71 | +}; | |
72 | + | |
73 | +static int __init vr41xx_giu_add(void) | |
74 | +{ | |
75 | + struct platform_device *pdev; | |
76 | + struct resource *res; | |
77 | + unsigned int num; | |
78 | + int retval; | |
79 | + | |
80 | + pdev = platform_device_alloc("GIU", -1); | |
81 | + if (!pdev) | |
82 | + return -ENOMEM; | |
83 | + | |
84 | + switch (current_cpu_data.cputype) { | |
85 | + case CPU_VR4111: | |
86 | + case CPU_VR4121: | |
87 | + pdev->id = GPIO_50PINS_PULLUPDOWN; | |
88 | + res = giu_50pins_pullupdown_resource; | |
89 | + num = ARRAY_SIZE(giu_50pins_pullupdown_resource); | |
90 | + break; | |
91 | + case CPU_VR4122: | |
92 | + case CPU_VR4131: | |
93 | + pdev->id = GPIO_36PINS; | |
94 | + res = giu_36pins_resource; | |
95 | + num = ARRAY_SIZE(giu_36pins_resource); | |
96 | + break; | |
97 | + case CPU_VR4133: | |
98 | + pdev->id = GPIO_48PINS_EDGE_SELECT; | |
99 | + res = giu_48pins_resource; | |
100 | + num = ARRAY_SIZE(giu_48pins_resource); | |
101 | + break; | |
102 | + default: | |
103 | + retval = -ENODEV; | |
104 | + goto err_free_device; | |
105 | + } | |
106 | + | |
107 | + retval = platform_device_add_resources(pdev, res, num); | |
108 | + if (retval) | |
109 | + goto err_free_device; | |
110 | + | |
111 | + retval = platform_device_add(pdev); | |
112 | + if (retval) | |
113 | + goto err_free_device; | |
114 | + | |
115 | + return 0; | |
116 | + | |
117 | +err_free_device: | |
118 | + platform_device_put(pdev); | |
119 | + | |
120 | + return retval; | |
121 | +} | |
122 | +device_initcall(vr41xx_giu_add); |
drivers/char/vr41xx_giu.c
... | ... | @@ -19,18 +19,17 @@ |
19 | 19 | * along with this program; if not, write to the Free Software |
20 | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | 21 | */ |
22 | -#include <linux/platform_device.h> | |
23 | 22 | #include <linux/errno.h> |
24 | 23 | #include <linux/fs.h> |
25 | 24 | #include <linux/init.h> |
26 | -#include <linux/irq.h> | |
27 | 25 | #include <linux/interrupt.h> |
26 | +#include <linux/irq.h> | |
28 | 27 | #include <linux/kernel.h> |
29 | 28 | #include <linux/module.h> |
29 | +#include <linux/platform_device.h> | |
30 | 30 | #include <linux/spinlock.h> |
31 | 31 | #include <linux/types.h> |
32 | 32 | |
33 | -#include <asm/cpu.h> | |
34 | 33 | #include <asm/io.h> |
35 | 34 | #include <asm/vr41xx/giu.h> |
36 | 35 | #include <asm/vr41xx/irq.h> |
... | ... | @@ -44,18 +43,6 @@ |
44 | 43 | module_param(major, int, 0); |
45 | 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 | 46 | #define GIUIOSELL 0x00 |
60 | 47 | #define GIUIOSELH 0x02 |
61 | 48 | #define GIUPIODL 0x04 |
... | ... | @@ -89,8 +76,6 @@ |
89 | 76 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 |
90 | 77 | |
91 | 78 | static spinlock_t giu_lock; |
92 | -static struct resource *giu_resource1; | |
93 | -static struct resource *giu_resource2; | |
94 | 79 | static unsigned long giu_flags; |
95 | 80 | static unsigned int giu_nr_pins; |
96 | 81 | |
... | ... | @@ -234,7 +219,7 @@ |
234 | 219 | giu_set(GIUINTHTSELL, mask); |
235 | 220 | else |
236 | 221 | giu_clear(GIUINTHTSELL, mask); |
237 | - if (current_cpu_data.cputype == CPU_VR4133) { | |
222 | + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | |
238 | 223 | switch (trigger) { |
239 | 224 | case IRQ_TRIGGER_EDGE_FALLING: |
240 | 225 | giu_set(GIUFEDGEINHL, mask); |
... | ... | @@ -269,7 +254,7 @@ |
269 | 254 | giu_set(GIUINTHTSELH, mask); |
270 | 255 | else |
271 | 256 | giu_clear(GIUINTHTSELH, mask); |
272 | - if (current_cpu_data.cputype == CPU_VR4133) { | |
257 | + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | |
273 | 258 | switch (trigger) { |
274 | 259 | case IRQ_TRIGGER_EDGE_FALLING: |
275 | 260 | giu_set(GIUFEDGEINHH, mask); |
... | ... | @@ -298,7 +283,6 @@ |
298 | 283 | giu_write(GIUINTSTATH, mask); |
299 | 284 | } |
300 | 285 | } |
301 | - | |
302 | 286 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); |
303 | 287 | |
304 | 288 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) |
... | ... | @@ -321,7 +305,6 @@ |
321 | 305 | giu_write(GIUINTSTATH, mask); |
322 | 306 | } |
323 | 307 | } |
324 | - | |
325 | 308 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); |
326 | 309 | |
327 | 310 | gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) |
... | ... | @@ -350,7 +333,6 @@ |
350 | 333 | |
351 | 334 | return GPIO_DATA_LOW; |
352 | 335 | } |
353 | - | |
354 | 336 | EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); |
355 | 337 | |
356 | 338 | int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) |
... | ... | @@ -388,7 +370,6 @@ |
388 | 370 | |
389 | 371 | return 0; |
390 | 372 | } |
391 | - | |
392 | 373 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); |
393 | 374 | |
394 | 375 | int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) |
... | ... | @@ -438,7 +419,6 @@ |
438 | 419 | |
439 | 420 | return 0; |
440 | 421 | } |
441 | - | |
442 | 422 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); |
443 | 423 | |
444 | 424 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) |
... | ... | @@ -477,7 +457,6 @@ |
477 | 457 | |
478 | 458 | return 0; |
479 | 459 | } |
480 | - | |
481 | 460 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); |
482 | 461 | |
483 | 462 | static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, |
484 | 463 | |
485 | 464 | |
486 | 465 | |
487 | 466 | |
488 | 467 | |
489 | 468 | |
490 | 469 | |
491 | 470 | |
492 | 471 | |
493 | 472 | |
... | ... | @@ -596,61 +575,40 @@ |
596 | 575 | |
597 | 576 | static int __devinit giu_probe(struct platform_device *dev) |
598 | 577 | { |
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; | |
578 | + struct resource *res; | |
579 | + unsigned int trigger, i, pin; | |
603 | 580 | struct irq_chip *chip; |
604 | - int retval; | |
581 | + int irq, retval; | |
605 | 582 | |
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; | |
583 | + switch (dev->id) { | |
584 | + case GPIO_50PINS_PULLUPDOWN: | |
585 | + giu_flags = GPIO_HAS_PULLUPDOWN_IO; | |
586 | + giu_nr_pins = 50; | |
613 | 587 | break; |
614 | - case CPU_VR4122: | |
615 | - case CPU_VR4131: | |
616 | - start = GIU_TYPE2_START; | |
617 | - size = GIU_TYPE2_SIZE; | |
618 | - nr_pins = 36; | |
588 | + case GPIO_36PINS: | |
589 | + giu_nr_pins = 36; | |
619 | 590 | 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; | |
591 | + case GPIO_48PINS_EDGE_SELECT: | |
592 | + giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | |
593 | + giu_nr_pins = 48; | |
625 | 594 | break; |
626 | 595 | default: |
596 | + printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); | |
627 | 597 | return -ENODEV; |
628 | 598 | } |
629 | 599 | |
630 | - res1 = request_mem_region(start, size, "GIU"); | |
631 | - if (res1 == NULL) | |
600 | + res = platform_get_resource(dev, IORESOURCE_MEM, 0); | |
601 | + if (!res) | |
632 | 602 | return -EBUSY; |
633 | 603 | |
634 | - base = ioremap(start, size); | |
635 | - if (base == NULL) { | |
636 | - release_resource(res1); | |
604 | + giu_base = ioremap(res->start, res->end - res->start + 1); | |
605 | + if (!giu_base) | |
637 | 606 | return -ENOMEM; |
638 | - } | |
639 | 607 | |
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 | - | |
649 | 608 | retval = register_chrdev(major, "GIU", &gpio_fops); |
650 | 609 | if (retval < 0) { |
651 | - iounmap(base); | |
652 | - release_resource(res1); | |
653 | - release_resource(res2); | |
610 | + iounmap(giu_base); | |
611 | + giu_base = NULL; | |
654 | 612 | return retval; |
655 | 613 | } |
656 | 614 | |
... | ... | @@ -660,11 +618,6 @@ |
660 | 618 | } |
661 | 619 | |
662 | 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 | 622 | giu_write(GIUINTENL, 0); |
670 | 623 | giu_write(GIUINTENH, 0); |
671 | 624 | |
672 | 625 | |
673 | 626 | |
... | ... | @@ -685,22 +638,23 @@ |
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 | 648 | static int __devexit giu_remove(struct platform_device *dev) |
692 | 649 | { |
693 | - iounmap(giu_base); | |
650 | + if (giu_base) { | |
651 | + iounmap(giu_base); | |
652 | + giu_base = NULL; | |
653 | + } | |
694 | 654 | |
695 | - release_resource(giu_resource1); | |
696 | - if (giu_flags & GPIO_HAS_PULLUPDOWN_IO) | |
697 | - release_resource(giu_resource2); | |
698 | - | |
699 | 655 | return 0; |
700 | 656 | } |
701 | 657 | |
702 | -static struct platform_device *giu_platform_device; | |
703 | - | |
704 | 658 | static struct platform_driver giu_device_driver = { |
705 | 659 | .probe = giu_probe, |
706 | 660 | .remove = __devexit_p(giu_remove), |
707 | 661 | |
... | ... | @@ -712,30 +666,12 @@ |
712 | 666 | |
713 | 667 | static int __init vr41xx_giu_init(void) |
714 | 668 | { |
715 | - int retval; | |
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; | |
669 | + return platform_driver_register(&giu_device_driver); | |
732 | 670 | } |
733 | 671 | |
734 | 672 | static void __exit vr41xx_giu_exit(void) |
735 | 673 | { |
736 | 674 | platform_driver_unregister(&giu_device_driver); |
737 | - | |
738 | - platform_device_unregister(giu_platform_device); | |
739 | 675 | } |
740 | 676 | |
741 | 677 | module_init(vr41xx_giu_init); |
include/asm-mips/vr41xx/giu.h
... | ... | @@ -20,6 +20,15 @@ |
20 | 20 | #ifndef __NEC_VR41XX_GIU_H |
21 | 21 | #define __NEC_VR41XX_GIU_H |
22 | 22 | |
23 | +/* | |
24 | + * NEC VR4100 series GIU platform device IDs. | |
25 | + */ | |
26 | +enum { | |
27 | + GPIO_50PINS_PULLUPDOWN, | |
28 | + GPIO_36PINS, | |
29 | + GPIO_48PINS_EDGE_SELECT, | |
30 | +}; | |
31 | + | |
23 | 32 | typedef enum { |
24 | 33 | IRQ_TRIGGER_LEVEL, |
25 | 34 | IRQ_TRIGGER_EDGE, |