Commit 44173fb2e83183b585e137e6fee8ba32460f5645

Authored by Yoichi Yuasa
Committed by Ralf Baechle
1 parent a74b460518

[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
... ... @@ -2,5 +2,5 @@
2 2 # Makefile for common code of the NEC VR4100 series.
3 3 #
4 4  
5   -obj-y += bcu.o cmu.o icu.o init.o irq.o pmu.o siu.o type.o
  5 +obj-y += bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o siu.o type.o
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,