Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Yoichi Yuasa and committed by
Ralf Baechle
44173fb2 a74b4605

+165 -98
+1 -1
arch/mips/vr41xx/common/Makefile
··· 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
+122
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);
+33 -97
drivers/char/vr41xx_giu.c
··· 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> ··· 42 43 static int major; /* default is dynamic major device number */ 43 44 module_param(major, int, 0); 44 45 MODULE_PARM_DESC(major, "Major device number"); 45 - 46 - #define GIU_TYPE1_START 0x0b000100UL 47 - #define GIU_TYPE1_SIZE 0x20UL 48 - 49 - #define GIU_TYPE2_START 0x0f000140UL 50 - #define GIU_TYPE2_SIZE 0x20UL 51 - 52 - #define GIU_TYPE3_START 0x0f000140UL 53 - #define GIU_TYPE3_SIZE 0x28UL 54 - 55 - #define GIU_PULLUPDOWN_START 0x0b0002e0UL 56 - #define GIU_PULLUPDOWN_SIZE 0x04UL 57 46 58 47 #define GIUIOSELL 0x00 59 48 #define GIUIOSELH 0x02 ··· 76 89 #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 77 90 78 91 static spinlock_t giu_lock; 79 - static struct resource *giu_resource1; 80 - static struct resource *giu_resource2; 81 92 static unsigned long giu_flags; 82 93 static unsigned int giu_nr_pins; 83 94 ··· 219 234 giu_set(GIUINTHTSELL, mask); 220 235 else 221 236 giu_clear(GIUINTHTSELL, mask); 222 - if (current_cpu_data.cputype == CPU_VR4133) { 237 + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 223 238 switch (trigger) { 224 239 case IRQ_TRIGGER_EDGE_FALLING: 225 240 giu_set(GIUFEDGEINHL, mask); ··· 254 269 giu_set(GIUINTHTSELH, mask); 255 270 else 256 271 giu_clear(GIUINTHTSELH, mask); 257 - if (current_cpu_data.cputype == CPU_VR4133) { 272 + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 258 273 switch (trigger) { 259 274 case IRQ_TRIGGER_EDGE_FALLING: 260 275 giu_set(GIUFEDGEINHH, mask); ··· 283 298 giu_write(GIUINTSTATH, mask); 284 299 } 285 300 } 286 - 287 301 EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); 288 302 289 303 void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) ··· 305 321 giu_write(GIUINTSTATH, mask); 306 322 } 307 323 } 308 - 309 324 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); 310 325 311 326 gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) ··· 333 350 334 351 return GPIO_DATA_LOW; 335 352 } 336 - 337 353 EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); 338 354 339 355 int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) ··· 370 388 371 389 return 0; 372 390 } 373 - 374 391 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); 375 392 376 393 int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) ··· 419 438 420 439 return 0; 421 440 } 422 - 423 441 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); 424 442 425 443 int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) ··· 457 477 458 478 return 0; 459 479 } 460 - 461 480 EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); 462 481 463 482 static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, ··· 575 596 576 597 static int __devinit giu_probe(struct platform_device *dev) 577 598 { 578 - unsigned long start, size, flags = 0; 579 - unsigned int nr_pins = 0, trigger, i, pin; 580 - struct resource *res1, *res2 = NULL; 581 - void *base; 599 + struct resource *res; 600 + unsigned int trigger, i, pin; 582 601 struct irq_chip *chip; 583 - int retval; 602 + int irq, retval; 584 603 585 - switch (current_cpu_data.cputype) { 586 - case CPU_VR4111: 587 - case CPU_VR4121: 588 - start = GIU_TYPE1_START; 589 - size = GIU_TYPE1_SIZE; 590 - flags = GPIO_HAS_PULLUPDOWN_IO; 591 - nr_pins = 50; 604 + switch (dev->id) { 605 + case GPIO_50PINS_PULLUPDOWN: 606 + giu_flags = GPIO_HAS_PULLUPDOWN_IO; 607 + giu_nr_pins = 50; 592 608 break; 593 - case CPU_VR4122: 594 - case CPU_VR4131: 595 - start = GIU_TYPE2_START; 596 - size = GIU_TYPE2_SIZE; 597 - nr_pins = 36; 609 + case GPIO_36PINS: 610 + giu_nr_pins = 36; 598 611 break; 599 - case CPU_VR4133: 600 - start = GIU_TYPE3_START; 601 - size = GIU_TYPE3_SIZE; 602 - flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; 603 - nr_pins = 48; 612 + case GPIO_48PINS_EDGE_SELECT: 613 + giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; 614 + giu_nr_pins = 48; 604 615 break; 605 616 default: 617 + printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); 606 618 return -ENODEV; 607 619 } 608 620 609 - res1 = request_mem_region(start, size, "GIU"); 610 - if (res1 == NULL) 621 + res = platform_get_resource(dev, IORESOURCE_MEM, 0); 622 + if (!res) 611 623 return -EBUSY; 612 624 613 - base = ioremap(start, size); 614 - if (base == NULL) { 615 - release_resource(res1); 625 + giu_base = ioremap(res->start, res->end - res->start + 1); 626 + if (!giu_base) 616 627 return -ENOMEM; 617 - } 618 - 619 - if (flags & GPIO_HAS_PULLUPDOWN_IO) { 620 - res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU"); 621 - if (res2 == NULL) { 622 - iounmap(base); 623 - release_resource(res1); 624 - return -EBUSY; 625 - } 626 - } 627 628 628 629 retval = register_chrdev(major, "GIU", &gpio_fops); 629 630 if (retval < 0) { 630 - iounmap(base); 631 - release_resource(res1); 632 - release_resource(res2); 631 + iounmap(giu_base); 632 + giu_base = NULL; 633 633 return retval; 634 634 } 635 635 ··· 618 660 } 619 661 620 662 spin_lock_init(&giu_lock); 621 - giu_base = base; 622 - giu_resource1 = res1; 623 - giu_resource2 = res2; 624 - giu_flags = flags; 625 - giu_nr_pins = nr_pins; 626 663 627 664 giu_write(GIUINTENL, 0); 628 665 giu_write(GIUINTENH, 0); ··· 638 685 639 686 } 640 687 641 - return cascade_irq(GIUINT_IRQ, giu_get_irq); 688 + irq = platform_get_irq(dev, 0); 689 + if (irq < 0 || irq >= NR_IRQS) 690 + return -EBUSY; 691 + 692 + return cascade_irq(irq, giu_get_irq); 642 693 } 643 694 644 695 static int __devexit giu_remove(struct platform_device *dev) 645 696 { 646 - iounmap(giu_base); 647 - 648 - release_resource(giu_resource1); 649 - if (giu_flags & GPIO_HAS_PULLUPDOWN_IO) 650 - release_resource(giu_resource2); 697 + if (giu_base) { 698 + iounmap(giu_base); 699 + giu_base = NULL; 700 + } 651 701 652 702 return 0; 653 703 } 654 - 655 - static struct platform_device *giu_platform_device; 656 704 657 705 static struct platform_driver giu_device_driver = { 658 706 .probe = giu_probe, ··· 666 712 667 713 static int __init vr41xx_giu_init(void) 668 714 { 669 - int retval; 670 - 671 - giu_platform_device = platform_device_alloc("GIU", -1); 672 - if (!giu_platform_device) 673 - return -ENOMEM; 674 - 675 - retval = platform_device_add(giu_platform_device); 676 - if (retval < 0) { 677 - platform_device_put(giu_platform_device); 678 - return retval; 679 - } 680 - 681 - retval = platform_driver_register(&giu_device_driver); 682 - if (retval < 0) 683 - platform_device_unregister(giu_platform_device); 684 - 685 - return retval; 715 + return platform_driver_register(&giu_device_driver); 686 716 } 687 717 688 718 static void __exit vr41xx_giu_exit(void) 689 719 { 690 720 platform_driver_unregister(&giu_device_driver); 691 - 692 - platform_device_unregister(giu_platform_device); 693 721 } 694 722 695 723 module_init(vr41xx_giu_init);
+9
include/asm-mips/vr41xx/giu.h
··· 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,