···22# Makefile for common code of the NEC VR4100 series.33#4455-obj-y += bcu.o cmu.o icu.o init.o irq.o pmu.o siu.o type.o55+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
···11+/*22+ * NEC VR4100 series GIU platform device.33+ *44+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ *1111+ * This program is distributed in the hope that it will be useful,1212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ *1616+ * You should have received a copy of the GNU General Public License1717+ * along with this program; if not, write to the Free Software1818+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA1919+ */2020+#include <linux/errno.h>2121+#include <linux/init.h>2222+#include <linux/ioport.h>2323+#include <linux/platform_device.h>2424+2525+#include <asm/cpu.h>2626+#include <asm/vr41xx/giu.h>2727+#include <asm/vr41xx/irq.h>2828+2929+static struct resource giu_50pins_pullupdown_resource[] __initdata = {3030+ {3131+ .start = 0x0b000100,3232+ .end = 0x0b00011f,3333+ .flags = IORESOURCE_MEM,3434+ },3535+ {3636+ .start = 0x0b0002e0,3737+ .end = 0x0b0002e3,3838+ .flags = IORESOURCE_MEM,3939+ },4040+ {4141+ .start = GIUINT_IRQ,4242+ .end = GIUINT_IRQ,4343+ .flags = IORESOURCE_IRQ,4444+ },4545+};4646+4747+static struct resource giu_36pins_resource[] __initdata = {4848+ {4949+ .start = 0x0f000140,5050+ .end = 0x0f00015f,5151+ .flags = IORESOURCE_MEM,5252+ },5353+ {5454+ .start = GIUINT_IRQ,5555+ .end = GIUINT_IRQ,5656+ .flags = IORESOURCE_IRQ,5757+ },5858+};5959+6060+static struct resource giu_48pins_resource[] __initdata = {6161+ {6262+ .start = 0x0f000140,6363+ .end = 0x0f000167,6464+ .flags = IORESOURCE_MEM,6565+ },6666+ {6767+ .start = GIUINT_IRQ,6868+ .end = GIUINT_IRQ,6969+ .flags = IORESOURCE_IRQ,7070+ },7171+};7272+7373+static int __init vr41xx_giu_add(void)7474+{7575+ struct platform_device *pdev;7676+ struct resource *res;7777+ unsigned int num;7878+ int retval;7979+8080+ pdev = platform_device_alloc("GIU", -1);8181+ if (!pdev)8282+ return -ENOMEM;8383+8484+ switch (current_cpu_data.cputype) {8585+ case CPU_VR4111:8686+ case CPU_VR4121:8787+ pdev->id = GPIO_50PINS_PULLUPDOWN;8888+ res = giu_50pins_pullupdown_resource;8989+ num = ARRAY_SIZE(giu_50pins_pullupdown_resource);9090+ break;9191+ case CPU_VR4122:9292+ case CPU_VR4131:9393+ pdev->id = GPIO_36PINS;9494+ res = giu_36pins_resource;9595+ num = ARRAY_SIZE(giu_36pins_resource);9696+ break;9797+ case CPU_VR4133:9898+ pdev->id = GPIO_48PINS_EDGE_SELECT;9999+ res = giu_48pins_resource;100100+ num = ARRAY_SIZE(giu_48pins_resource);101101+ break;102102+ default:103103+ retval = -ENODEV;104104+ goto err_free_device;105105+ }106106+107107+ retval = platform_device_add_resources(pdev, res, num);108108+ if (retval)109109+ goto err_free_device;110110+111111+ retval = platform_device_add(pdev);112112+ if (retval)113113+ goto err_free_device;114114+115115+ return 0;116116+117117+err_free_device:118118+ platform_device_put(pdev);119119+120120+ return retval;121121+}122122+device_initcall(vr41xx_giu_add);
+33-97
drivers/char/vr41xx_giu.c
···1919 * along with this program; if not, write to the Free Software2020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2121 */2222-#include <linux/platform_device.h>2322#include <linux/errno.h>2423#include <linux/fs.h>2524#include <linux/init.h>2626-#include <linux/irq.h>2725#include <linux/interrupt.h>2626+#include <linux/irq.h>2827#include <linux/kernel.h>2928#include <linux/module.h>2929+#include <linux/platform_device.h>3030#include <linux/spinlock.h>3131#include <linux/types.h>32323333-#include <asm/cpu.h>3433#include <asm/io.h>3534#include <asm/vr41xx/giu.h>3635#include <asm/vr41xx/irq.h>···4243static int major; /* default is dynamic major device number */4344module_param(major, int, 0);4445MODULE_PARM_DESC(major, "Major device number");4545-4646-#define GIU_TYPE1_START 0x0b000100UL4747-#define GIU_TYPE1_SIZE 0x20UL4848-4949-#define GIU_TYPE2_START 0x0f000140UL5050-#define GIU_TYPE2_SIZE 0x20UL5151-5252-#define GIU_TYPE3_START 0x0f000140UL5353-#define GIU_TYPE3_SIZE 0x28UL5454-5555-#define GIU_PULLUPDOWN_START 0x0b0002e0UL5656-#define GIU_PULLUPDOWN_SIZE 0x04UL57465847#define GIUIOSELL 0x005948#define GIUIOSELH 0x02···7689#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x010077907891static spinlock_t giu_lock;7979-static struct resource *giu_resource1;8080-static struct resource *giu_resource2;8192static unsigned long giu_flags;8293static unsigned int giu_nr_pins;8394···219234 giu_set(GIUINTHTSELL, mask);220235 else221236 giu_clear(GIUINTHTSELL, mask);222222- if (current_cpu_data.cputype == CPU_VR4133) {237237+ if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {223238 switch (trigger) {224239 case IRQ_TRIGGER_EDGE_FALLING:225240 giu_set(GIUFEDGEINHL, mask);···254269 giu_set(GIUINTHTSELH, mask);255270 else256271 giu_clear(GIUINTHTSELH, mask);257257- if (current_cpu_data.cputype == CPU_VR4133) {272272+ if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {258273 switch (trigger) {259274 case IRQ_TRIGGER_EDGE_FALLING:260275 giu_set(GIUFEDGEINHH, mask);···283298 giu_write(GIUINTSTATH, mask);284299 }285300}286286-287301EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);288302289303void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)···305321 giu_write(GIUINTSTATH, mask);306322 }307323}308308-309324EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);310325311326gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)···333350334351 return GPIO_DATA_LOW;335352}336336-337353EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);338354339355int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)···370388371389 return 0;372390}373373-374391EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);375392376393int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)···419438420439 return 0;421440}422422-423441EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);424442425443int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)···457477458478 return 0;459479}460460-461480EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);462481463482static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,···575596576597static int __devinit giu_probe(struct platform_device *dev)577598{578578- unsigned long start, size, flags = 0;579579- unsigned int nr_pins = 0, trigger, i, pin;580580- struct resource *res1, *res2 = NULL;581581- void *base;599599+ struct resource *res;600600+ unsigned int trigger, i, pin;582601 struct irq_chip *chip;583583- int retval;602602+ int irq, retval;584603585585- switch (current_cpu_data.cputype) {586586- case CPU_VR4111:587587- case CPU_VR4121:588588- start = GIU_TYPE1_START;589589- size = GIU_TYPE1_SIZE;590590- flags = GPIO_HAS_PULLUPDOWN_IO;591591- nr_pins = 50;604604+ switch (dev->id) {605605+ case GPIO_50PINS_PULLUPDOWN:606606+ giu_flags = GPIO_HAS_PULLUPDOWN_IO;607607+ giu_nr_pins = 50;592608 break;593593- case CPU_VR4122:594594- case CPU_VR4131:595595- start = GIU_TYPE2_START;596596- size = GIU_TYPE2_SIZE;597597- nr_pins = 36;609609+ case GPIO_36PINS:610610+ giu_nr_pins = 36;598611 break;599599- case CPU_VR4133:600600- start = GIU_TYPE3_START;601601- size = GIU_TYPE3_SIZE;602602- flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;603603- nr_pins = 48;612612+ case GPIO_48PINS_EDGE_SELECT:613613+ giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;614614+ giu_nr_pins = 48;604615 break;605616 default:617617+ printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);606618 return -ENODEV;607619 }608620609609- res1 = request_mem_region(start, size, "GIU");610610- if (res1 == NULL)621621+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);622622+ if (!res)611623 return -EBUSY;612624613613- base = ioremap(start, size);614614- if (base == NULL) {615615- release_resource(res1);625625+ giu_base = ioremap(res->start, res->end - res->start + 1);626626+ if (!giu_base)616627 return -ENOMEM;617617- }618618-619619- if (flags & GPIO_HAS_PULLUPDOWN_IO) {620620- res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");621621- if (res2 == NULL) {622622- iounmap(base);623623- release_resource(res1);624624- return -EBUSY;625625- }626626- }627628628629 retval = register_chrdev(major, "GIU", &gpio_fops);629630 if (retval < 0) {630630- iounmap(base);631631- release_resource(res1);632632- release_resource(res2);631631+ iounmap(giu_base);632632+ giu_base = NULL;633633 return retval;634634 }635635···618660 }619661620662 spin_lock_init(&giu_lock);621621- giu_base = base;622622- giu_resource1 = res1;623623- giu_resource2 = res2;624624- giu_flags = flags;625625- giu_nr_pins = nr_pins;626663627664 giu_write(GIUINTENL, 0);628665 giu_write(GIUINTENH, 0);···638685639686 }640687641641- return cascade_irq(GIUINT_IRQ, giu_get_irq);688688+ irq = platform_get_irq(dev, 0);689689+ if (irq < 0 || irq >= NR_IRQS)690690+ return -EBUSY;691691+692692+ return cascade_irq(irq, giu_get_irq);642693}643694644695static int __devexit giu_remove(struct platform_device *dev)645696{646646- iounmap(giu_base);647647-648648- release_resource(giu_resource1);649649- if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)650650- release_resource(giu_resource2);697697+ if (giu_base) {698698+ iounmap(giu_base);699699+ giu_base = NULL;700700+ }651701652702 return 0;653703}654654-655655-static struct platform_device *giu_platform_device;656704657705static struct platform_driver giu_device_driver = {658706 .probe = giu_probe,···666712667713static int __init vr41xx_giu_init(void)668714{669669- int retval;670670-671671- giu_platform_device = platform_device_alloc("GIU", -1);672672- if (!giu_platform_device)673673- return -ENOMEM;674674-675675- retval = platform_device_add(giu_platform_device);676676- if (retval < 0) {677677- platform_device_put(giu_platform_device);678678- return retval;679679- }680680-681681- retval = platform_driver_register(&giu_device_driver);682682- if (retval < 0)683683- platform_device_unregister(giu_platform_device);684684-685685- return retval;715715+ return platform_driver_register(&giu_device_driver);686716}687717688718static void __exit vr41xx_giu_exit(void)689719{690720 platform_driver_unregister(&giu_device_driver);691691-692692- platform_device_unregister(giu_platform_device);693721}694722695723module_init(vr41xx_giu_init);
+9
include/asm-mips/vr41xx/giu.h
···2020#ifndef __NEC_VR41XX_GIU_H2121#define __NEC_VR41XX_GIU_H22222323+/*2424+ * NEC VR4100 series GIU platform device IDs.2525+ */2626+enum {2727+ GPIO_50PINS_PULLUPDOWN,2828+ GPIO_36PINS,2929+ GPIO_48PINS_EDGE_SELECT,3030+};3131+2332typedef enum {2433 IRQ_TRIGGER_LEVEL,2534 IRQ_TRIGGER_EDGE,