Commit 27fdd325dace4a1ebfa10e93ba6f3d25f25df674

Authored by Yoichi Yuasa
Committed by Ralf Baechle
1 parent 69f16c9a86

MIPS: Update VR41xx GPIO driver to use gpiolib

Signed-off-by: Yoichi Yuasa <yyuasa@linux.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 8 changed files with 597 additions and 704 deletions Side-by-side Diff

... ... @@ -267,6 +267,7 @@
267 267 select CEVT_R4K
268 268 select CSRC_R4K
269 269 select SYS_HAS_CPU_VR41XX
  270 + select ARCH_REQUIRE_GPIOLIB
270 271  
271 272 config NXP_STB220
272 273 bool "NXP STB220 board"
arch/mips/include/asm/vr41xx/giu.h
1 1 /*
2 2 * Include file for NEC VR4100 series General-purpose I/O Unit.
3 3 *
4   - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  4 + * Copyright (C) 2005-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
5 5 *
6 6 * This program is free software; you can redistribute it and/or modify
7 7 * it under the terms of the GNU General Public License as published by
... ... @@ -41,7 +41,8 @@
41 41 IRQ_SIGNAL_HOLD,
42 42 } irq_signal_t;
43 43  
44   -extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal);
  44 +extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
  45 + irq_signal_t signal);
45 46  
46 47 typedef enum {
47 48 IRQ_LEVEL_LOW,
... ... @@ -49,23 +50,6 @@
49 50 } irq_level_t;
50 51  
51 52 extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level);
52   -
53   -typedef enum {
54   - GPIO_DATA_LOW,
55   - GPIO_DATA_HIGH,
56   - GPIO_DATA_INVAL,
57   -} gpio_data_t;
58   -
59   -extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin);
60   -extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data);
61   -
62   -typedef enum {
63   - GPIO_INPUT,
64   - GPIO_OUTPUT,
65   - GPIO_OUTPUT_DISABLE,
66   -} gpio_direction_t;
67   -
68   -extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir);
69 53  
70 54 typedef enum {
71 55 GPIO_PULL_DOWN,
drivers/char/Kconfig
... ... @@ -1029,10 +1029,6 @@
1029 1029  
1030 1030 If compiled as a module, it will be called cs5535_gpio.
1031 1031  
1032   -config GPIO_VR41XX
1033   - tristate "NEC VR4100 series General-purpose I/O Unit support"
1034   - depends on CPU_VR41XX
1035   -
1036 1032 config RAW_DRIVER
1037 1033 tristate "RAW driver (/dev/raw/rawN)"
1038 1034 depends on BLOCK
drivers/char/Makefile
... ... @@ -95,7 +95,6 @@
95 95 obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
96 96 obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
97 97 obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
98   -obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
99 98 obj-$(CONFIG_GPIO_TB0219) += tb0219.o
100 99 obj-$(CONFIG_TELCLOCK) += tlclk.o
101 100  
drivers/char/vr41xx_giu.c
1   -/*
2   - * Driver for NEC VR4100 series General-purpose I/O Unit.
3   - *
4   - * Copyright (C) 2002 MontaVista Software Inc.
5   - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
6   - * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
7   - *
8   - * This program is free software; you can redistribute it and/or modify
9   - * it under the terms of the GNU General Public License as published by
10   - * the Free Software Foundation; either version 2 of the License, or
11   - * (at your option) any later version.
12   - *
13   - * This program is distributed in the hope that it will be useful,
14   - * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16   - * GNU General Public License for more details.
17   - *
18   - * You should have received a copy of the GNU General Public License
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
21   - */
22   -#include <linux/errno.h>
23   -#include <linux/fs.h>
24   -#include <linux/init.h>
25   -#include <linux/interrupt.h>
26   -#include <linux/irq.h>
27   -#include <linux/kernel.h>
28   -#include <linux/module.h>
29   -#include <linux/platform_device.h>
30   -#include <linux/smp_lock.h>
31   -#include <linux/spinlock.h>
32   -#include <linux/types.h>
33   -
34   -#include <asm/io.h>
35   -#include <asm/vr41xx/giu.h>
36   -#include <asm/vr41xx/irq.h>
37   -#include <asm/vr41xx/vr41xx.h>
38   -
39   -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
40   -MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
41   -MODULE_LICENSE("GPL");
42   -
43   -static int major; /* default is dynamic major device number */
44   -module_param(major, int, 0);
45   -MODULE_PARM_DESC(major, "Major device number");
46   -
47   -#define GIUIOSELL 0x00
48   -#define GIUIOSELH 0x02
49   -#define GIUPIODL 0x04
50   -#define GIUPIODH 0x06
51   -#define GIUINTSTATL 0x08
52   -#define GIUINTSTATH 0x0a
53   -#define GIUINTENL 0x0c
54   -#define GIUINTENH 0x0e
55   -#define GIUINTTYPL 0x10
56   -#define GIUINTTYPH 0x12
57   -#define GIUINTALSELL 0x14
58   -#define GIUINTALSELH 0x16
59   -#define GIUINTHTSELL 0x18
60   -#define GIUINTHTSELH 0x1a
61   -#define GIUPODATL 0x1c
62   -#define GIUPODATEN 0x1c
63   -#define GIUPODATH 0x1e
64   - #define PIOEN0 0x0100
65   - #define PIOEN1 0x0200
66   -#define GIUPODAT 0x1e
67   -#define GIUFEDGEINHL 0x20
68   -#define GIUFEDGEINHH 0x22
69   -#define GIUREDGEINHL 0x24
70   -#define GIUREDGEINHH 0x26
71   -
72   -#define GIUUSEUPDN 0x1e0
73   -#define GIUTERMUPDN 0x1e2
74   -
75   -#define GPIO_HAS_PULLUPDOWN_IO 0x0001
76   -#define GPIO_HAS_OUTPUT_ENABLE 0x0002
77   -#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
78   -
79   -static spinlock_t giu_lock;
80   -static unsigned long giu_flags;
81   -static unsigned int giu_nr_pins;
82   -
83   -static void __iomem *giu_base;
84   -
85   -#define giu_read(offset) readw(giu_base + (offset))
86   -#define giu_write(offset, value) writew((value), giu_base + (offset))
87   -
88   -#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE)
89   -#define GIUINT_HIGH_OFFSET 16
90   -#define GIUINT_HIGH_MAX 32
91   -
92   -static inline uint16_t giu_set(uint16_t offset, uint16_t set)
93   -{
94   - uint16_t data;
95   -
96   - data = giu_read(offset);
97   - data |= set;
98   - giu_write(offset, data);
99   -
100   - return data;
101   -}
102   -
103   -static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
104   -{
105   - uint16_t data;
106   -
107   - data = giu_read(offset);
108   - data &= ~clear;
109   - giu_write(offset, data);
110   -
111   - return data;
112   -}
113   -
114   -static void ack_giuint_low(unsigned int irq)
115   -{
116   - giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
117   -}
118   -
119   -static void mask_giuint_low(unsigned int irq)
120   -{
121   - giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
122   -}
123   -
124   -static void mask_ack_giuint_low(unsigned int irq)
125   -{
126   - unsigned int pin;
127   -
128   - pin = GPIO_PIN_OF_IRQ(irq);
129   - giu_clear(GIUINTENL, 1 << pin);
130   - giu_write(GIUINTSTATL, 1 << pin);
131   -}
132   -
133   -static void unmask_giuint_low(unsigned int irq)
134   -{
135   - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
136   -}
137   -
138   -static struct irq_chip giuint_low_irq_chip = {
139   - .name = "GIUINTL",
140   - .ack = ack_giuint_low,
141   - .mask = mask_giuint_low,
142   - .mask_ack = mask_ack_giuint_low,
143   - .unmask = unmask_giuint_low,
144   -};
145   -
146   -static void ack_giuint_high(unsigned int irq)
147   -{
148   - giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
149   -}
150   -
151   -static void mask_giuint_high(unsigned int irq)
152   -{
153   - giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
154   -}
155   -
156   -static void mask_ack_giuint_high(unsigned int irq)
157   -{
158   - unsigned int pin;
159   -
160   - pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
161   - giu_clear(GIUINTENH, 1 << pin);
162   - giu_write(GIUINTSTATH, 1 << pin);
163   -}
164   -
165   -static void unmask_giuint_high(unsigned int irq)
166   -{
167   - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
168   -}
169   -
170   -static struct irq_chip giuint_high_irq_chip = {
171   - .name = "GIUINTH",
172   - .ack = ack_giuint_high,
173   - .mask = mask_giuint_high,
174   - .mask_ack = mask_ack_giuint_high,
175   - .unmask = unmask_giuint_high,
176   -};
177   -
178   -static int giu_get_irq(unsigned int irq)
179   -{
180   - uint16_t pendl, pendh, maskl, maskh;
181   - int i;
182   -
183   - pendl = giu_read(GIUINTSTATL);
184   - pendh = giu_read(GIUINTSTATH);
185   - maskl = giu_read(GIUINTENL);
186   - maskh = giu_read(GIUINTENH);
187   -
188   - maskl &= pendl;
189   - maskh &= pendh;
190   -
191   - if (maskl) {
192   - for (i = 0; i < 16; i++) {
193   - if (maskl & (1 << i))
194   - return GIU_IRQ(i);
195   - }
196   - } else if (maskh) {
197   - for (i = 0; i < 16; i++) {
198   - if (maskh & (1 << i))
199   - return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
200   - }
201   - }
202   -
203   - printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
204   - maskl, pendl, maskh, pendh);
205   -
206   - atomic_inc(&irq_err_count);
207   -
208   - return -EINVAL;
209   -}
210   -
211   -void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
212   -{
213   - uint16_t mask;
214   -
215   - if (pin < GIUINT_HIGH_OFFSET) {
216   - mask = 1 << pin;
217   - if (trigger != IRQ_TRIGGER_LEVEL) {
218   - giu_set(GIUINTTYPL, mask);
219   - if (signal == IRQ_SIGNAL_HOLD)
220   - giu_set(GIUINTHTSELL, mask);
221   - else
222   - giu_clear(GIUINTHTSELL, mask);
223   - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
224   - switch (trigger) {
225   - case IRQ_TRIGGER_EDGE_FALLING:
226   - giu_set(GIUFEDGEINHL, mask);
227   - giu_clear(GIUREDGEINHL, mask);
228   - break;
229   - case IRQ_TRIGGER_EDGE_RISING:
230   - giu_clear(GIUFEDGEINHL, mask);
231   - giu_set(GIUREDGEINHL, mask);
232   - break;
233   - default:
234   - giu_set(GIUFEDGEINHL, mask);
235   - giu_set(GIUREDGEINHL, mask);
236   - break;
237   - }
238   - }
239   - set_irq_chip_and_handler(GIU_IRQ(pin),
240   - &giuint_low_irq_chip,
241   - handle_edge_irq);
242   - } else {
243   - giu_clear(GIUINTTYPL, mask);
244   - giu_clear(GIUINTHTSELL, mask);
245   - set_irq_chip_and_handler(GIU_IRQ(pin),
246   - &giuint_low_irq_chip,
247   - handle_level_irq);
248   - }
249   - giu_write(GIUINTSTATL, mask);
250   - } else if (pin < GIUINT_HIGH_MAX) {
251   - mask = 1 << (pin - GIUINT_HIGH_OFFSET);
252   - if (trigger != IRQ_TRIGGER_LEVEL) {
253   - giu_set(GIUINTTYPH, mask);
254   - if (signal == IRQ_SIGNAL_HOLD)
255   - giu_set(GIUINTHTSELH, mask);
256   - else
257   - giu_clear(GIUINTHTSELH, mask);
258   - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
259   - switch (trigger) {
260   - case IRQ_TRIGGER_EDGE_FALLING:
261   - giu_set(GIUFEDGEINHH, mask);
262   - giu_clear(GIUREDGEINHH, mask);
263   - break;
264   - case IRQ_TRIGGER_EDGE_RISING:
265   - giu_clear(GIUFEDGEINHH, mask);
266   - giu_set(GIUREDGEINHH, mask);
267   - break;
268   - default:
269   - giu_set(GIUFEDGEINHH, mask);
270   - giu_set(GIUREDGEINHH, mask);
271   - break;
272   - }
273   - }
274   - set_irq_chip_and_handler(GIU_IRQ(pin),
275   - &giuint_high_irq_chip,
276   - handle_edge_irq);
277   - } else {
278   - giu_clear(GIUINTTYPH, mask);
279   - giu_clear(GIUINTHTSELH, mask);
280   - set_irq_chip_and_handler(GIU_IRQ(pin),
281   - &giuint_high_irq_chip,
282   - handle_level_irq);
283   - }
284   - giu_write(GIUINTSTATH, mask);
285   - }
286   -}
287   -EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
288   -
289   -void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
290   -{
291   - uint16_t mask;
292   -
293   - if (pin < GIUINT_HIGH_OFFSET) {
294   - mask = 1 << pin;
295   - if (level == IRQ_LEVEL_HIGH)
296   - giu_set(GIUINTALSELL, mask);
297   - else
298   - giu_clear(GIUINTALSELL, mask);
299   - giu_write(GIUINTSTATL, mask);
300   - } else if (pin < GIUINT_HIGH_MAX) {
301   - mask = 1 << (pin - GIUINT_HIGH_OFFSET);
302   - if (level == IRQ_LEVEL_HIGH)
303   - giu_set(GIUINTALSELH, mask);
304   - else
305   - giu_clear(GIUINTALSELH, mask);
306   - giu_write(GIUINTSTATH, mask);
307   - }
308   -}
309   -EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
310   -
311   -gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
312   -{
313   - uint16_t reg, mask;
314   -
315   - if (pin >= giu_nr_pins)
316   - return GPIO_DATA_INVAL;
317   -
318   - if (pin < 16) {
319   - reg = giu_read(GIUPIODL);
320   - mask = (uint16_t)1 << pin;
321   - } else if (pin < 32) {
322   - reg = giu_read(GIUPIODH);
323   - mask = (uint16_t)1 << (pin - 16);
324   - } else if (pin < 48) {
325   - reg = giu_read(GIUPODATL);
326   - mask = (uint16_t)1 << (pin - 32);
327   - } else {
328   - reg = giu_read(GIUPODATH);
329   - mask = (uint16_t)1 << (pin - 48);
330   - }
331   -
332   - if (reg & mask)
333   - return GPIO_DATA_HIGH;
334   -
335   - return GPIO_DATA_LOW;
336   -}
337   -EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
338   -
339   -int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
340   -{
341   - uint16_t offset, mask, reg;
342   - unsigned long flags;
343   -
344   - if (pin >= giu_nr_pins)
345   - return -EINVAL;
346   -
347   - if (pin < 16) {
348   - offset = GIUPIODL;
349   - mask = (uint16_t)1 << pin;
350   - } else if (pin < 32) {
351   - offset = GIUPIODH;
352   - mask = (uint16_t)1 << (pin - 16);
353   - } else if (pin < 48) {
354   - offset = GIUPODATL;
355   - mask = (uint16_t)1 << (pin - 32);
356   - } else {
357   - offset = GIUPODATH;
358   - mask = (uint16_t)1 << (pin - 48);
359   - }
360   -
361   - spin_lock_irqsave(&giu_lock, flags);
362   -
363   - reg = giu_read(offset);
364   - if (data == GPIO_DATA_HIGH)
365   - reg |= mask;
366   - else
367   - reg &= ~mask;
368   - giu_write(offset, reg);
369   -
370   - spin_unlock_irqrestore(&giu_lock, flags);
371   -
372   - return 0;
373   -}
374   -EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
375   -
376   -int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
377   -{
378   - uint16_t offset, mask, reg;
379   - unsigned long flags;
380   -
381   - if (pin >= giu_nr_pins)
382   - return -EINVAL;
383   -
384   - if (pin < 16) {
385   - offset = GIUIOSELL;
386   - mask = (uint16_t)1 << pin;
387   - } else if (pin < 32) {
388   - offset = GIUIOSELH;
389   - mask = (uint16_t)1 << (pin - 16);
390   - } else {
391   - if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
392   - offset = GIUPODATEN;
393   - mask = (uint16_t)1 << (pin - 32);
394   - } else {
395   - switch (pin) {
396   - case 48:
397   - offset = GIUPODATH;
398   - mask = PIOEN0;
399   - break;
400   - case 49:
401   - offset = GIUPODATH;
402   - mask = PIOEN1;
403   - break;
404   - default:
405   - return -EINVAL;
406   - }
407   - }
408   - }
409   -
410   - spin_lock_irqsave(&giu_lock, flags);
411   -
412   - reg = giu_read(offset);
413   - if (dir == GPIO_OUTPUT)
414   - reg |= mask;
415   - else
416   - reg &= ~mask;
417   - giu_write(offset, reg);
418   -
419   - spin_unlock_irqrestore(&giu_lock, flags);
420   -
421   - return 0;
422   -}
423   -EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
424   -
425   -int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
426   -{
427   - uint16_t reg, mask;
428   - unsigned long flags;
429   -
430   - if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
431   - return -EPERM;
432   -
433   - if (pin >= 15)
434   - return -EINVAL;
435   -
436   - mask = (uint16_t)1 << pin;
437   -
438   - spin_lock_irqsave(&giu_lock, flags);
439   -
440   - if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
441   - reg = giu_read(GIUTERMUPDN);
442   - if (pull == GPIO_PULL_UP)
443   - reg |= mask;
444   - else
445   - reg &= ~mask;
446   - giu_write(GIUTERMUPDN, reg);
447   -
448   - reg = giu_read(GIUUSEUPDN);
449   - reg |= mask;
450   - giu_write(GIUUSEUPDN, reg);
451   - } else {
452   - reg = giu_read(GIUUSEUPDN);
453   - reg &= ~mask;
454   - giu_write(GIUUSEUPDN, reg);
455   - }
456   -
457   - spin_unlock_irqrestore(&giu_lock, flags);
458   -
459   - return 0;
460   -}
461   -EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
462   -
463   -static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
464   - loff_t *ppos)
465   -{
466   - unsigned int pin;
467   - char value = '0';
468   -
469   - pin = iminor(file->f_path.dentry->d_inode);
470   - if (pin >= giu_nr_pins)
471   - return -EBADF;
472   -
473   - if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
474   - value = '1';
475   -
476   - if (len <= 0)
477   - return -EFAULT;
478   -
479   - if (put_user(value, buf))
480   - return -EFAULT;
481   -
482   - return 1;
483   -}
484   -
485   -static ssize_t gpio_write(struct file *file, const char __user *data,
486   - size_t len, loff_t *ppos)
487   -{
488   - unsigned int pin;
489   - size_t i;
490   - char c;
491   - int retval = 0;
492   -
493   - pin = iminor(file->f_path.dentry->d_inode);
494   - if (pin >= giu_nr_pins)
495   - return -EBADF;
496   -
497   - for (i = 0; i < len; i++) {
498   - if (get_user(c, data + i))
499   - return -EFAULT;
500   -
501   - switch (c) {
502   - case '0':
503   - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
504   - break;
505   - case '1':
506   - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
507   - break;
508   - case 'D':
509   - printk(KERN_INFO "GPIO%d: pull down\n", pin);
510   - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
511   - break;
512   - case 'd':
513   - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
514   - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
515   - break;
516   - case 'I':
517   - printk(KERN_INFO "GPIO%d: input\n", pin);
518   - retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
519   - break;
520   - case 'O':
521   - printk(KERN_INFO "GPIO%d: output\n", pin);
522   - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
523   - break;
524   - case 'o':
525   - printk(KERN_INFO "GPIO%d: output disable\n", pin);
526   - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
527   - break;
528   - case 'P':
529   - printk(KERN_INFO "GPIO%d: pull up\n", pin);
530   - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
531   - break;
532   - case 'p':
533   - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
534   - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
535   - break;
536   - default:
537   - break;
538   - }
539   -
540   - if (retval < 0)
541   - break;
542   - }
543   -
544   - return i;
545   -}
546   -
547   -static int gpio_open(struct inode *inode, struct file *file)
548   -{
549   - unsigned int pin;
550   -
551   - cycle_kernel_lock();
552   - pin = iminor(inode);
553   - if (pin >= giu_nr_pins)
554   - return -EBADF;
555   -
556   - return nonseekable_open(inode, file);
557   -}
558   -
559   -static int gpio_release(struct inode *inode, struct file *file)
560   -{
561   - unsigned int pin;
562   -
563   - pin = iminor(inode);
564   - if (pin >= giu_nr_pins)
565   - return -EBADF;
566   -
567   - return 0;
568   -}
569   -
570   -static const struct file_operations gpio_fops = {
571   - .owner = THIS_MODULE,
572   - .read = gpio_read,
573   - .write = gpio_write,
574   - .open = gpio_open,
575   - .release = gpio_release,
576   -};
577   -
578   -static int __devinit giu_probe(struct platform_device *dev)
579   -{
580   - struct resource *res;
581   - unsigned int trigger, i, pin;
582   - struct irq_chip *chip;
583   - int irq, retval;
584   -
585   - switch (dev->id) {
586   - case GPIO_50PINS_PULLUPDOWN:
587   - giu_flags = GPIO_HAS_PULLUPDOWN_IO;
588   - giu_nr_pins = 50;
589   - break;
590   - case GPIO_36PINS:
591   - giu_nr_pins = 36;
592   - break;
593   - case GPIO_48PINS_EDGE_SELECT:
594   - giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
595   - giu_nr_pins = 48;
596   - break;
597   - default:
598   - printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
599   - return -ENODEV;
600   - }
601   -
602   - res = platform_get_resource(dev, IORESOURCE_MEM, 0);
603   - if (!res)
604   - return -EBUSY;
605   -
606   - giu_base = ioremap(res->start, res->end - res->start + 1);
607   - if (!giu_base)
608   - return -ENOMEM;
609   -
610   - retval = register_chrdev(major, "GIU", &gpio_fops);
611   - if (retval < 0) {
612   - iounmap(giu_base);
613   - giu_base = NULL;
614   - return retval;
615   - }
616   -
617   - if (major == 0) {
618   - major = retval;
619   - printk(KERN_INFO "GIU: major number %d\n", major);
620   - }
621   -
622   - spin_lock_init(&giu_lock);
623   -
624   - giu_write(GIUINTENL, 0);
625   - giu_write(GIUINTENH, 0);
626   -
627   - trigger = giu_read(GIUINTTYPH) << 16;
628   - trigger |= giu_read(GIUINTTYPL);
629   - for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
630   - pin = GPIO_PIN_OF_IRQ(i);
631   - if (pin < GIUINT_HIGH_OFFSET)
632   - chip = &giuint_low_irq_chip;
633   - else
634   - chip = &giuint_high_irq_chip;
635   -
636   - if (trigger & (1 << pin))
637   - set_irq_chip_and_handler(i, chip, handle_edge_irq);
638   - else
639   - set_irq_chip_and_handler(i, chip, handle_level_irq);
640   -
641   - }
642   -
643   - irq = platform_get_irq(dev, 0);
644   - if (irq < 0 || irq >= nr_irqs)
645   - return -EBUSY;
646   -
647   - return cascade_irq(irq, giu_get_irq);
648   -}
649   -
650   -static int __devexit giu_remove(struct platform_device *dev)
651   -{
652   - if (giu_base) {
653   - iounmap(giu_base);
654   - giu_base = NULL;
655   - }
656   -
657   - return 0;
658   -}
659   -
660   -static struct platform_driver giu_device_driver = {
661   - .probe = giu_probe,
662   - .remove = __devexit_p(giu_remove),
663   - .driver = {
664   - .name = "GIU",
665   - .owner = THIS_MODULE,
666   - },
667   -};
668   -
669   -static int __init vr41xx_giu_init(void)
670   -{
671   - return platform_driver_register(&giu_device_driver);
672   -}
673   -
674   -static void __exit vr41xx_giu_exit(void)
675   -{
676   - platform_driver_unregister(&giu_device_driver);
677   -}
678   -
679   -module_init(vr41xx_giu_init);
680   -module_exit(vr41xx_giu_exit);
drivers/gpio/Kconfig
... ... @@ -79,6 +79,12 @@
79 79 help
80 80 Say yes here to support the Xilinx FPGA GPIO device
81 81  
  82 +config GPIO_VR41XX
  83 + tristate "NEC VR4100 series General-purpose I/O Uint support"
  84 + depends on CPU_VR41XX
  85 + help
  86 + Say yes here to support the NEC VR4100 series General-purpose I/O Uint
  87 +
82 88 comment "I2C GPIO expanders:"
83 89  
84 90 config GPIO_MAX732X
drivers/gpio/Makefile
... ... @@ -13,4 +13,5 @@
13 13 obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
14 14 obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
15 15 obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
  16 +obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
drivers/gpio/vr41xx_giu.c
  1 +/*
  2 + * Driver for NEC VR4100 series General-purpose I/O Unit.
  3 + *
  4 + * Copyright (C) 2002 MontaVista Software Inc.
  5 + * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
  6 + * Copyright (C) 2003-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License as published by
  10 + * the Free Software Foundation; either version 2 of the License, or
  11 + * (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  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
  21 + */
  22 +#include <linux/errno.h>
  23 +#include <linux/fs.h>
  24 +#include <linux/gpio.h>
  25 +#include <linux/init.h>
  26 +#include <linux/interrupt.h>
  27 +#include <linux/io.h>
  28 +#include <linux/irq.h>
  29 +#include <linux/kernel.h>
  30 +#include <linux/module.h>
  31 +#include <linux/platform_device.h>
  32 +#include <linux/smp_lock.h>
  33 +#include <linux/spinlock.h>
  34 +#include <linux/types.h>
  35 +
  36 +#include <asm/vr41xx/giu.h>
  37 +#include <asm/vr41xx/irq.h>
  38 +#include <asm/vr41xx/vr41xx.h>
  39 +
  40 +MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
  41 +MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
  42 +MODULE_LICENSE("GPL");
  43 +
  44 +#define GIUIOSELL 0x00
  45 +#define GIUIOSELH 0x02
  46 +#define GIUPIODL 0x04
  47 +#define GIUPIODH 0x06
  48 +#define GIUINTSTATL 0x08
  49 +#define GIUINTSTATH 0x0a
  50 +#define GIUINTENL 0x0c
  51 +#define GIUINTENH 0x0e
  52 +#define GIUINTTYPL 0x10
  53 +#define GIUINTTYPH 0x12
  54 +#define GIUINTALSELL 0x14
  55 +#define GIUINTALSELH 0x16
  56 +#define GIUINTHTSELL 0x18
  57 +#define GIUINTHTSELH 0x1a
  58 +#define GIUPODATL 0x1c
  59 +#define GIUPODATEN 0x1c
  60 +#define GIUPODATH 0x1e
  61 + #define PIOEN0 0x0100
  62 + #define PIOEN1 0x0200
  63 +#define GIUPODAT 0x1e
  64 +#define GIUFEDGEINHL 0x20
  65 +#define GIUFEDGEINHH 0x22
  66 +#define GIUREDGEINHL 0x24
  67 +#define GIUREDGEINHH 0x26
  68 +
  69 +#define GIUUSEUPDN 0x1e0
  70 +#define GIUTERMUPDN 0x1e2
  71 +
  72 +#define GPIO_HAS_PULLUPDOWN_IO 0x0001
  73 +#define GPIO_HAS_OUTPUT_ENABLE 0x0002
  74 +#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
  75 +
  76 +enum {
  77 + GPIO_INPUT,
  78 + GPIO_OUTPUT,
  79 +};
  80 +
  81 +static DEFINE_SPINLOCK(giu_lock);
  82 +static unsigned long giu_flags;
  83 +
  84 +static void __iomem *giu_base;
  85 +
  86 +#define giu_read(offset) readw(giu_base + (offset))
  87 +#define giu_write(offset, value) writew((value), giu_base + (offset))
  88 +
  89 +#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE)
  90 +#define GIUINT_HIGH_OFFSET 16
  91 +#define GIUINT_HIGH_MAX 32
  92 +
  93 +static inline u16 giu_set(u16 offset, u16 set)
  94 +{
  95 + u16 data;
  96 +
  97 + data = giu_read(offset);
  98 + data |= set;
  99 + giu_write(offset, data);
  100 +
  101 + return data;
  102 +}
  103 +
  104 +static inline u16 giu_clear(u16 offset, u16 clear)
  105 +{
  106 + u16 data;
  107 +
  108 + data = giu_read(offset);
  109 + data &= ~clear;
  110 + giu_write(offset, data);
  111 +
  112 + return data;
  113 +}
  114 +
  115 +static void ack_giuint_low(unsigned int irq)
  116 +{
  117 + giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
  118 +}
  119 +
  120 +static void mask_giuint_low(unsigned int irq)
  121 +{
  122 + giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
  123 +}
  124 +
  125 +static void mask_ack_giuint_low(unsigned int irq)
  126 +{
  127 + unsigned int pin;
  128 +
  129 + pin = GPIO_PIN_OF_IRQ(irq);
  130 + giu_clear(GIUINTENL, 1 << pin);
  131 + giu_write(GIUINTSTATL, 1 << pin);
  132 +}
  133 +
  134 +static void unmask_giuint_low(unsigned int irq)
  135 +{
  136 + giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
  137 +}
  138 +
  139 +static struct irq_chip giuint_low_irq_chip = {
  140 + .name = "GIUINTL",
  141 + .ack = ack_giuint_low,
  142 + .mask = mask_giuint_low,
  143 + .mask_ack = mask_ack_giuint_low,
  144 + .unmask = unmask_giuint_low,
  145 +};
  146 +
  147 +static void ack_giuint_high(unsigned int irq)
  148 +{
  149 + giu_write(GIUINTSTATH,
  150 + 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
  151 +}
  152 +
  153 +static void mask_giuint_high(unsigned int irq)
  154 +{
  155 + giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
  156 +}
  157 +
  158 +static void mask_ack_giuint_high(unsigned int irq)
  159 +{
  160 + unsigned int pin;
  161 +
  162 + pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
  163 + giu_clear(GIUINTENH, 1 << pin);
  164 + giu_write(GIUINTSTATH, 1 << pin);
  165 +}
  166 +
  167 +static void unmask_giuint_high(unsigned int irq)
  168 +{
  169 + giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
  170 +}
  171 +
  172 +static struct irq_chip giuint_high_irq_chip = {
  173 + .name = "GIUINTH",
  174 + .ack = ack_giuint_high,
  175 + .mask = mask_giuint_high,
  176 + .mask_ack = mask_ack_giuint_high,
  177 + .unmask = unmask_giuint_high,
  178 +};
  179 +
  180 +static int giu_get_irq(unsigned int irq)
  181 +{
  182 + u16 pendl, pendh, maskl, maskh;
  183 + int i;
  184 +
  185 + pendl = giu_read(GIUINTSTATL);
  186 + pendh = giu_read(GIUINTSTATH);
  187 + maskl = giu_read(GIUINTENL);
  188 + maskh = giu_read(GIUINTENH);
  189 +
  190 + maskl &= pendl;
  191 + maskh &= pendh;
  192 +
  193 + if (maskl) {
  194 + for (i = 0; i < 16; i++) {
  195 + if (maskl & (1 << i))
  196 + return GIU_IRQ(i);
  197 + }
  198 + } else if (maskh) {
  199 + for (i = 0; i < 16; i++) {
  200 + if (maskh & (1 << i))
  201 + return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
  202 + }
  203 + }
  204 +
  205 + printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
  206 + maskl, pendl, maskh, pendh);
  207 +
  208 + atomic_inc(&irq_err_count);
  209 +
  210 + return -EINVAL;
  211 +}
  212 +
  213 +void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
  214 + irq_signal_t signal)
  215 +{
  216 + u16 mask;
  217 +
  218 + if (pin < GIUINT_HIGH_OFFSET) {
  219 + mask = 1 << pin;
  220 + if (trigger != IRQ_TRIGGER_LEVEL) {
  221 + giu_set(GIUINTTYPL, mask);
  222 + if (signal == IRQ_SIGNAL_HOLD)
  223 + giu_set(GIUINTHTSELL, mask);
  224 + else
  225 + giu_clear(GIUINTHTSELL, mask);
  226 + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
  227 + switch (trigger) {
  228 + case IRQ_TRIGGER_EDGE_FALLING:
  229 + giu_set(GIUFEDGEINHL, mask);
  230 + giu_clear(GIUREDGEINHL, mask);
  231 + break;
  232 + case IRQ_TRIGGER_EDGE_RISING:
  233 + giu_clear(GIUFEDGEINHL, mask);
  234 + giu_set(GIUREDGEINHL, mask);
  235 + break;
  236 + default:
  237 + giu_set(GIUFEDGEINHL, mask);
  238 + giu_set(GIUREDGEINHL, mask);
  239 + break;
  240 + }
  241 + }
  242 + set_irq_chip_and_handler(GIU_IRQ(pin),
  243 + &giuint_low_irq_chip,
  244 + handle_edge_irq);
  245 + } else {
  246 + giu_clear(GIUINTTYPL, mask);
  247 + giu_clear(GIUINTHTSELL, mask);
  248 + set_irq_chip_and_handler(GIU_IRQ(pin),
  249 + &giuint_low_irq_chip,
  250 + handle_level_irq);
  251 + }
  252 + giu_write(GIUINTSTATL, mask);
  253 + } else if (pin < GIUINT_HIGH_MAX) {
  254 + mask = 1 << (pin - GIUINT_HIGH_OFFSET);
  255 + if (trigger != IRQ_TRIGGER_LEVEL) {
  256 + giu_set(GIUINTTYPH, mask);
  257 + if (signal == IRQ_SIGNAL_HOLD)
  258 + giu_set(GIUINTHTSELH, mask);
  259 + else
  260 + giu_clear(GIUINTHTSELH, mask);
  261 + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
  262 + switch (trigger) {
  263 + case IRQ_TRIGGER_EDGE_FALLING:
  264 + giu_set(GIUFEDGEINHH, mask);
  265 + giu_clear(GIUREDGEINHH, mask);
  266 + break;
  267 + case IRQ_TRIGGER_EDGE_RISING:
  268 + giu_clear(GIUFEDGEINHH, mask);
  269 + giu_set(GIUREDGEINHH, mask);
  270 + break;
  271 + default:
  272 + giu_set(GIUFEDGEINHH, mask);
  273 + giu_set(GIUREDGEINHH, mask);
  274 + break;
  275 + }
  276 + }
  277 + set_irq_chip_and_handler(GIU_IRQ(pin),
  278 + &giuint_high_irq_chip,
  279 + handle_edge_irq);
  280 + } else {
  281 + giu_clear(GIUINTTYPH, mask);
  282 + giu_clear(GIUINTHTSELH, mask);
  283 + set_irq_chip_and_handler(GIU_IRQ(pin),
  284 + &giuint_high_irq_chip,
  285 + handle_level_irq);
  286 + }
  287 + giu_write(GIUINTSTATH, mask);
  288 + }
  289 +}
  290 +EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
  291 +
  292 +void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
  293 +{
  294 + u16 mask;
  295 +
  296 + if (pin < GIUINT_HIGH_OFFSET) {
  297 + mask = 1 << pin;
  298 + if (level == IRQ_LEVEL_HIGH)
  299 + giu_set(GIUINTALSELL, mask);
  300 + else
  301 + giu_clear(GIUINTALSELL, mask);
  302 + giu_write(GIUINTSTATL, mask);
  303 + } else if (pin < GIUINT_HIGH_MAX) {
  304 + mask = 1 << (pin - GIUINT_HIGH_OFFSET);
  305 + if (level == IRQ_LEVEL_HIGH)
  306 + giu_set(GIUINTALSELH, mask);
  307 + else
  308 + giu_clear(GIUINTALSELH, mask);
  309 + giu_write(GIUINTSTATH, mask);
  310 + }
  311 +}
  312 +EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
  313 +
  314 +static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
  315 +{
  316 + u16 offset, mask, reg;
  317 + unsigned long flags;
  318 +
  319 + if (pin >= chip->ngpio)
  320 + return -EINVAL;
  321 +
  322 + if (pin < 16) {
  323 + offset = GIUIOSELL;
  324 + mask = 1 << pin;
  325 + } else if (pin < 32) {
  326 + offset = GIUIOSELH;
  327 + mask = 1 << (pin - 16);
  328 + } else {
  329 + if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
  330 + offset = GIUPODATEN;
  331 + mask = 1 << (pin - 32);
  332 + } else {
  333 + switch (pin) {
  334 + case 48:
  335 + offset = GIUPODATH;
  336 + mask = PIOEN0;
  337 + break;
  338 + case 49:
  339 + offset = GIUPODATH;
  340 + mask = PIOEN1;
  341 + break;
  342 + default:
  343 + return -EINVAL;
  344 + }
  345 + }
  346 + }
  347 +
  348 + spin_lock_irqsave(&giu_lock, flags);
  349 +
  350 + reg = giu_read(offset);
  351 + if (dir == GPIO_OUTPUT)
  352 + reg |= mask;
  353 + else
  354 + reg &= ~mask;
  355 + giu_write(offset, reg);
  356 +
  357 + spin_unlock_irqrestore(&giu_lock, flags);
  358 +
  359 + return 0;
  360 +}
  361 +
  362 +int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
  363 +{
  364 + u16 reg, mask;
  365 + unsigned long flags;
  366 +
  367 + if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
  368 + return -EPERM;
  369 +
  370 + if (pin >= 15)
  371 + return -EINVAL;
  372 +
  373 + mask = 1 << pin;
  374 +
  375 + spin_lock_irqsave(&giu_lock, flags);
  376 +
  377 + if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
  378 + reg = giu_read(GIUTERMUPDN);
  379 + if (pull == GPIO_PULL_UP)
  380 + reg |= mask;
  381 + else
  382 + reg &= ~mask;
  383 + giu_write(GIUTERMUPDN, reg);
  384 +
  385 + reg = giu_read(GIUUSEUPDN);
  386 + reg |= mask;
  387 + giu_write(GIUUSEUPDN, reg);
  388 + } else {
  389 + reg = giu_read(GIUUSEUPDN);
  390 + reg &= ~mask;
  391 + giu_write(GIUUSEUPDN, reg);
  392 + }
  393 +
  394 + spin_unlock_irqrestore(&giu_lock, flags);
  395 +
  396 + return 0;
  397 +}
  398 +EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
  399 +
  400 +static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
  401 +{
  402 + u16 reg, mask;
  403 +
  404 + if (pin >= chip->ngpio)
  405 + return -EINVAL;
  406 +
  407 + if (pin < 16) {
  408 + reg = giu_read(GIUPIODL);
  409 + mask = 1 << pin;
  410 + } else if (pin < 32) {
  411 + reg = giu_read(GIUPIODH);
  412 + mask = 1 << (pin - 16);
  413 + } else if (pin < 48) {
  414 + reg = giu_read(GIUPODATL);
  415 + mask = 1 << (pin - 32);
  416 + } else {
  417 + reg = giu_read(GIUPODATH);
  418 + mask = 1 << (pin - 48);
  419 + }
  420 +
  421 + if (reg & mask)
  422 + return 1;
  423 +
  424 + return 0;
  425 +}
  426 +
  427 +static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
  428 + int value)
  429 +{
  430 + u16 offset, mask, reg;
  431 + unsigned long flags;
  432 +
  433 + if (pin >= chip->ngpio)
  434 + return;
  435 +
  436 + if (pin < 16) {
  437 + offset = GIUPIODL;
  438 + mask = 1 << pin;
  439 + } else if (pin < 32) {
  440 + offset = GIUPIODH;
  441 + mask = 1 << (pin - 16);
  442 + } else if (pin < 48) {
  443 + offset = GIUPODATL;
  444 + mask = 1 << (pin - 32);
  445 + } else {
  446 + offset = GIUPODATH;
  447 + mask = 1 << (pin - 48);
  448 + }
  449 +
  450 + spin_lock_irqsave(&giu_lock, flags);
  451 +
  452 + reg = giu_read(offset);
  453 + if (value)
  454 + reg |= mask;
  455 + else
  456 + reg &= ~mask;
  457 + giu_write(offset, reg);
  458 +
  459 + spin_unlock_irqrestore(&giu_lock, flags);
  460 +}
  461 +
  462 +
  463 +static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
  464 +{
  465 + return giu_set_direction(chip, offset, GPIO_INPUT);
  466 +}
  467 +
  468 +static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
  469 + int value)
  470 +{
  471 + vr41xx_gpio_set(chip, offset, value);
  472 +
  473 + return giu_set_direction(chip, offset, GPIO_OUTPUT);
  474 +}
  475 +
  476 +static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  477 +{
  478 + if (offset >= chip->ngpio)
  479 + return -EINVAL;
  480 +
  481 + return GIU_IRQ_BASE + offset;
  482 +}
  483 +
  484 +static struct gpio_chip vr41xx_gpio_chip = {
  485 + .label = "vr41xx",
  486 + .owner = THIS_MODULE,
  487 + .direction_input = vr41xx_gpio_direction_input,
  488 + .get = vr41xx_gpio_get,
  489 + .direction_output = vr41xx_gpio_direction_output,
  490 + .set = vr41xx_gpio_set,
  491 + .to_irq = vr41xx_gpio_to_irq,
  492 +};
  493 +
  494 +static int __devinit giu_probe(struct platform_device *pdev)
  495 +{
  496 + struct resource *res;
  497 + unsigned int trigger, i, pin;
  498 + struct irq_chip *chip;
  499 + int irq, retval;
  500 +
  501 + switch (pdev->id) {
  502 + case GPIO_50PINS_PULLUPDOWN:
  503 + giu_flags = GPIO_HAS_PULLUPDOWN_IO;
  504 + vr41xx_gpio_chip.ngpio = 50;
  505 + break;
  506 + case GPIO_36PINS:
  507 + vr41xx_gpio_chip.ngpio = 36;
  508 + break;
  509 + case GPIO_48PINS_EDGE_SELECT:
  510 + giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
  511 + vr41xx_gpio_chip.ngpio = 48;
  512 + break;
  513 + default:
  514 + dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
  515 + return -ENODEV;
  516 + }
  517 +
  518 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  519 + if (!res)
  520 + return -EBUSY;
  521 +
  522 + giu_base = ioremap(res->start, res->end - res->start + 1);
  523 + if (!giu_base)
  524 + return -ENOMEM;
  525 +
  526 + vr41xx_gpio_chip.dev = &pdev->dev;
  527 +
  528 + retval = gpiochip_add(&vr41xx_gpio_chip);
  529 +
  530 + giu_write(GIUINTENL, 0);
  531 + giu_write(GIUINTENH, 0);
  532 +
  533 + trigger = giu_read(GIUINTTYPH) << 16;
  534 + trigger |= giu_read(GIUINTTYPL);
  535 + for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
  536 + pin = GPIO_PIN_OF_IRQ(i);
  537 + if (pin < GIUINT_HIGH_OFFSET)
  538 + chip = &giuint_low_irq_chip;
  539 + else
  540 + chip = &giuint_high_irq_chip;
  541 +
  542 + if (trigger & (1 << pin))
  543 + set_irq_chip_and_handler(i, chip, handle_edge_irq);
  544 + else
  545 + set_irq_chip_and_handler(i, chip, handle_level_irq);
  546 +
  547 + }
  548 +
  549 + irq = platform_get_irq(pdev, 0);
  550 + if (irq < 0 || irq >= nr_irqs)
  551 + return -EBUSY;
  552 +
  553 + return cascade_irq(irq, giu_get_irq);
  554 +}
  555 +
  556 +static int __devexit giu_remove(struct platform_device *pdev)
  557 +{
  558 + if (giu_base) {
  559 + iounmap(giu_base);
  560 + giu_base = NULL;
  561 + }
  562 +
  563 + return 0;
  564 +}
  565 +
  566 +static struct platform_driver giu_device_driver = {
  567 + .probe = giu_probe,
  568 + .remove = __devexit_p(giu_remove),
  569 + .driver = {
  570 + .name = "GIU",
  571 + .owner = THIS_MODULE,
  572 + },
  573 +};
  574 +
  575 +static int __init vr41xx_giu_init(void)
  576 +{
  577 + return platform_driver_register(&giu_device_driver);
  578 +}
  579 +
  580 +static void __exit vr41xx_giu_exit(void)
  581 +{
  582 + platform_driver_unregister(&giu_device_driver);
  583 +}
  584 +
  585 +module_init(vr41xx_giu_init);
  586 +module_exit(vr41xx_giu_exit);