Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / 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-2005  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/platform_device.h>
23 #include <linux/errno.h>
24 #include <linux/fs.h>
25 #include <linux/init.h>
26 #include <linux/irq.h>
27 #include <linux/interrupt.h>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/spinlock.h>
31 #include <linux/types.h>
32
33 #include <asm/cpu.h>
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 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 #define GIUIOSELL       0x00
60 #define GIUIOSELH       0x02
61 #define GIUPIODL        0x04
62 #define GIUPIODH        0x06
63 #define GIUINTSTATL     0x08
64 #define GIUINTSTATH     0x0a
65 #define GIUINTENL       0x0c
66 #define GIUINTENH       0x0e
67 #define GIUINTTYPL      0x10
68 #define GIUINTTYPH      0x12
69 #define GIUINTALSELL    0x14
70 #define GIUINTALSELH    0x16
71 #define GIUINTHTSELL    0x18
72 #define GIUINTHTSELH    0x1a
73 #define GIUPODATL       0x1c
74 #define GIUPODATEN      0x1c
75 #define GIUPODATH       0x1e
76  #define PIOEN0         0x0100
77  #define PIOEN1         0x0200
78 #define GIUPODAT        0x1e
79 #define GIUFEDGEINHL    0x20
80 #define GIUFEDGEINHH    0x22
81 #define GIUREDGEINHL    0x24
82 #define GIUREDGEINHH    0x26
83
84 #define GIUUSEUPDN      0x1e0
85 #define GIUTERMUPDN     0x1e2
86
87 #define GPIO_HAS_PULLUPDOWN_IO          0x0001
88 #define GPIO_HAS_OUTPUT_ENABLE          0x0002
89 #define GPIO_HAS_INTERRUPT_EDGE_SELECT  0x0100
90
91 static spinlock_t giu_lock;
92 static struct resource *giu_resource1;
93 static struct resource *giu_resource2;
94 static unsigned long giu_flags;
95 static unsigned int giu_nr_pins;
96
97 static void __iomem *giu_base;
98
99 #define giu_read(offset)                readw(giu_base + (offset))
100 #define giu_write(offset, value)        writew((value), giu_base + (offset))
101
102 #define GPIO_PIN_OF_IRQ(irq)    ((irq) - GIU_IRQ_BASE)
103 #define GIUINT_HIGH_OFFSET      16
104 #define GIUINT_HIGH_MAX         32
105
106 static inline uint16_t giu_set(uint16_t offset, uint16_t set)
107 {
108         uint16_t data;
109
110         data = giu_read(offset);
111         data |= set;
112         giu_write(offset, data);
113
114         return data;
115 }
116
117 static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
118 {
119         uint16_t data;
120
121         data = giu_read(offset);
122         data &= ~clear;
123         giu_write(offset, data);
124
125         return data;
126 }
127
128 static unsigned int startup_giuint_low_irq(unsigned int irq)
129 {
130         unsigned int pin;
131
132         pin = GPIO_PIN_OF_IRQ(irq);
133         giu_write(GIUINTSTATL, 1 << pin);
134         giu_set(GIUINTENL, 1 << pin);
135
136         return 0;
137 }
138
139 static void shutdown_giuint_low_irq(unsigned int irq)
140 {
141         giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
142 }
143
144 static void enable_giuint_low_irq(unsigned int irq)
145 {
146         giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
147 }
148
149 #define disable_giuint_low_irq  shutdown_giuint_low_irq
150
151 static void ack_giuint_low_irq(unsigned int irq)
152 {
153         unsigned int pin;
154
155         pin = GPIO_PIN_OF_IRQ(irq);
156         giu_clear(GIUINTENL, 1 << pin);
157         giu_write(GIUINTSTATL, 1 << pin);
158 }
159
160 static void end_giuint_low_irq(unsigned int irq)
161 {
162         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
163                 giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
164 }
165
166 static struct hw_interrupt_type giuint_low_irq_type = {
167         .typename       = "GIUINTL",
168         .startup        = startup_giuint_low_irq,
169         .shutdown       = shutdown_giuint_low_irq,
170         .enable         = enable_giuint_low_irq,
171         .disable        = disable_giuint_low_irq,
172         .ack            = ack_giuint_low_irq,
173         .end            = end_giuint_low_irq,
174 };
175
176 static unsigned int startup_giuint_high_irq(unsigned int irq)
177 {
178         unsigned int pin;
179
180         pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
181         giu_write(GIUINTSTATH, 1 << pin);
182         giu_set(GIUINTENH, 1 << pin);
183
184         return 0;
185 }
186
187 static void shutdown_giuint_high_irq(unsigned int irq)
188 {
189         giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
190 }
191
192 static void enable_giuint_high_irq(unsigned int irq)
193 {
194         giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
195 }
196
197 #define disable_giuint_high_irq shutdown_giuint_high_irq
198
199 static void ack_giuint_high_irq(unsigned int irq)
200 {
201         unsigned int pin;
202
203         pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
204         giu_clear(GIUINTENH, 1 << pin);
205         giu_write(GIUINTSTATH, 1 << pin);
206 }
207
208 static void end_giuint_high_irq(unsigned int irq)
209 {
210         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
211                 giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
212 }
213
214 static struct hw_interrupt_type giuint_high_irq_type = {
215         .typename       = "GIUINTH",
216         .startup        = startup_giuint_high_irq,
217         .shutdown       = shutdown_giuint_high_irq,
218         .enable         = enable_giuint_high_irq,
219         .disable        = disable_giuint_high_irq,
220         .ack            = ack_giuint_high_irq,
221         .end            = end_giuint_high_irq,
222 };
223
224 static int giu_get_irq(unsigned int irq)
225 {
226         uint16_t pendl, pendh, maskl, maskh;
227         int i;
228
229         pendl = giu_read(GIUINTSTATL);
230         pendh = giu_read(GIUINTSTATH);
231         maskl = giu_read(GIUINTENL);
232         maskh = giu_read(GIUINTENH);
233
234         maskl &= pendl;
235         maskh &= pendh;
236
237         if (maskl) {
238                 for (i = 0; i < 16; i++) {
239                         if (maskl & (1 << i))
240                                 return GIU_IRQ(i);
241                 }
242         } else if (maskh) {
243                 for (i = 0; i < 16; i++) {
244                         if (maskh & (1 << i))
245                                 return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
246                 }
247         }
248
249         printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
250                maskl, pendl, maskh, pendh);
251
252         atomic_inc(&irq_err_count);
253
254         return -EINVAL;
255 }
256
257 void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
258 {
259         uint16_t mask;
260
261         if (pin < GIUINT_HIGH_OFFSET) {
262                 mask = 1 << pin;
263                 if (trigger != IRQ_TRIGGER_LEVEL) {
264                         giu_set(GIUINTTYPL, mask);
265                         if (signal == IRQ_SIGNAL_HOLD)
266                                 giu_set(GIUINTHTSELL, mask);
267                         else
268                                 giu_clear(GIUINTHTSELL, mask);
269                         if (current_cpu_data.cputype == CPU_VR4133) {
270                                 switch (trigger) {
271                                 case IRQ_TRIGGER_EDGE_FALLING:
272                                         giu_set(GIUFEDGEINHL, mask);
273                                         giu_clear(GIUREDGEINHL, mask);
274                                         break;
275                                 case IRQ_TRIGGER_EDGE_RISING:
276                                         giu_clear(GIUFEDGEINHL, mask);
277                                         giu_set(GIUREDGEINHL, mask);
278                                         break;
279                                 default:
280                                         giu_set(GIUFEDGEINHL, mask);
281                                         giu_set(GIUREDGEINHL, mask);
282                                         break;
283                                 }
284                         }
285                 } else {
286                         giu_clear(GIUINTTYPL, mask);
287                         giu_clear(GIUINTHTSELL, mask);
288                 }
289                 giu_write(GIUINTSTATL, mask);
290         } else if (pin < GIUINT_HIGH_MAX) {
291                 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
292                 if (trigger != IRQ_TRIGGER_LEVEL) {
293                         giu_set(GIUINTTYPH, mask);
294                         if (signal == IRQ_SIGNAL_HOLD)
295                                 giu_set(GIUINTHTSELH, mask);
296                         else
297                                 giu_clear(GIUINTHTSELH, mask);
298                         if (current_cpu_data.cputype == CPU_VR4133) {
299                                 switch (trigger) {
300                                 case IRQ_TRIGGER_EDGE_FALLING:
301                                         giu_set(GIUFEDGEINHH, mask);
302                                         giu_clear(GIUREDGEINHH, mask);
303                                         break;
304                                 case IRQ_TRIGGER_EDGE_RISING:
305                                         giu_clear(GIUFEDGEINHH, mask);
306                                         giu_set(GIUREDGEINHH, mask);
307                                         break;
308                                 default:
309                                         giu_set(GIUFEDGEINHH, mask);
310                                         giu_set(GIUREDGEINHH, mask);
311                                         break;
312                                 }
313                         }
314                 } else {
315                         giu_clear(GIUINTTYPH, mask);
316                         giu_clear(GIUINTHTSELH, mask);
317                 }
318                 giu_write(GIUINTSTATH, mask);
319         }
320 }
321
322 EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
323
324 void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
325 {
326         uint16_t mask;
327
328         if (pin < GIUINT_HIGH_OFFSET) {
329                 mask = 1 << pin;
330                 if (level == IRQ_LEVEL_HIGH)
331                         giu_set(GIUINTALSELL, mask);
332                 else
333                         giu_clear(GIUINTALSELL, mask);
334                 giu_write(GIUINTSTATL, mask);
335         } else if (pin < GIUINT_HIGH_MAX) {
336                 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
337                 if (level == IRQ_LEVEL_HIGH)
338                         giu_set(GIUINTALSELH, mask);
339                 else
340                         giu_clear(GIUINTALSELH, mask);
341                 giu_write(GIUINTSTATH, mask);
342         }
343 }
344
345 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
346
347 gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
348 {
349         uint16_t reg, mask;
350
351         if (pin >= giu_nr_pins)
352                 return GPIO_DATA_INVAL;
353
354         if (pin < 16) {
355                 reg = giu_read(GIUPIODL);
356                 mask = (uint16_t)1 << pin;
357         } else if (pin < 32) {
358                 reg = giu_read(GIUPIODH);
359                 mask = (uint16_t)1 << (pin - 16);
360         } else if (pin < 48) {
361                 reg = giu_read(GIUPODATL);
362                 mask = (uint16_t)1 << (pin - 32);
363         } else {
364                 reg = giu_read(GIUPODATH);
365                 mask = (uint16_t)1 << (pin - 48);
366         }
367
368         if (reg & mask)
369                 return GPIO_DATA_HIGH;
370
371         return GPIO_DATA_LOW;
372 }
373
374 EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
375
376 int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
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 = GIUPIODL;
386                 mask = (uint16_t)1 << pin;
387         } else if (pin < 32) {
388                 offset = GIUPIODH;
389                 mask = (uint16_t)1 << (pin - 16);
390         } else if (pin < 48) {
391                 offset = GIUPODATL;
392                 mask = (uint16_t)1 << (pin - 32);
393         } else {
394                 offset = GIUPODATH;
395                 mask = (uint16_t)1 << (pin - 48);
396         }
397
398         spin_lock_irqsave(&giu_lock, flags);
399
400         reg = giu_read(offset);
401         if (data == GPIO_DATA_HIGH)
402                 reg |= mask;
403         else
404                 reg &= ~mask;
405         giu_write(offset, reg);
406
407         spin_unlock_irqrestore(&giu_lock, flags);
408
409         return 0;
410 }
411
412 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
413
414 int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
415 {
416         uint16_t offset, mask, reg;
417         unsigned long flags;
418
419         if (pin >= giu_nr_pins)
420                 return -EINVAL;
421
422         if (pin < 16) {
423                 offset = GIUIOSELL;
424                 mask = (uint16_t)1 << pin;
425         } else if (pin < 32) {
426                 offset = GIUIOSELH;
427                 mask = (uint16_t)1 << (pin - 16);
428         } else {
429                 if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
430                         offset = GIUPODATEN;
431                         mask = (uint16_t)1 << (pin - 32);
432                 } else {
433                         switch (pin) {
434                         case 48:
435                                 offset = GIUPODATH;
436                                 mask = PIOEN0;
437                                 break;
438                         case 49:
439                                 offset = GIUPODATH;
440                                 mask = PIOEN1;
441                                 break;
442                         default:
443                                 return -EINVAL;
444                         }
445                 }
446         }
447
448         spin_lock_irqsave(&giu_lock, flags);
449
450         reg = giu_read(offset);
451         if (dir == GPIO_OUTPUT)
452                 reg |= mask;
453         else
454                 reg &= ~mask;
455         giu_write(offset, reg);
456
457         spin_unlock_irqrestore(&giu_lock, flags);
458
459         return 0;
460 }
461
462 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
463
464 int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
465 {
466         uint16_t reg, mask;
467         unsigned long flags;
468
469         if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
470                 return -EPERM;
471
472         if (pin >= 15)
473                 return -EINVAL;
474
475         mask = (uint16_t)1 << pin;
476
477         spin_lock_irqsave(&giu_lock, flags);
478
479         if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
480                 reg = giu_read(GIUTERMUPDN);
481                 if (pull == GPIO_PULL_UP)
482                         reg |= mask;
483                 else
484                         reg &= ~mask;
485                 giu_write(GIUTERMUPDN, reg);
486
487                 reg = giu_read(GIUUSEUPDN);
488                 reg |= mask;
489                 giu_write(GIUUSEUPDN, reg);
490         } else {
491                 reg = giu_read(GIUUSEUPDN);
492                 reg &= ~mask;
493                 giu_write(GIUUSEUPDN, reg);
494         }
495
496         spin_unlock_irqrestore(&giu_lock, flags);
497
498         return 0;
499 }
500
501 EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
502
503 static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
504                          loff_t *ppos)
505 {
506         unsigned int pin;
507         char value = '0';
508
509         pin = iminor(file->f_dentry->d_inode);
510         if (pin >= giu_nr_pins)
511                 return -EBADF;
512
513         if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
514                 value = '1';
515
516         if (len <= 0)
517                 return -EFAULT;
518
519         if (put_user(value, buf))
520                 return -EFAULT;
521
522         return 1;
523 }
524
525 static ssize_t gpio_write(struct file *file, const char __user *data,
526                           size_t len, loff_t *ppos)
527 {
528         unsigned int pin;
529         size_t i;
530         char c;
531         int retval = 0;
532
533         pin = iminor(file->f_dentry->d_inode);
534         if (pin >= giu_nr_pins)
535                 return -EBADF;
536
537         for (i = 0; i < len; i++) {
538                 if (get_user(c, data + i))
539                         return -EFAULT;
540
541                 switch (c) {
542                 case '0':
543                         retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
544                         break;
545                 case '1':
546                         retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
547                         break;
548                 case 'D':
549                         printk(KERN_INFO "GPIO%d: pull down\n", pin);
550                         retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
551                         break;
552                 case 'd':
553                         printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
554                         retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
555                         break;
556                 case 'I':
557                         printk(KERN_INFO "GPIO%d: input\n", pin);
558                         retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
559                         break;
560                 case 'O':
561                         printk(KERN_INFO "GPIO%d: output\n", pin);
562                         retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
563                         break;
564                 case 'o':
565                         printk(KERN_INFO "GPIO%d: output disable\n", pin);
566                         retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
567                         break;
568                 case 'P':
569                         printk(KERN_INFO "GPIO%d: pull up\n", pin);
570                         retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
571                         break;
572                 case 'p':
573                         printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
574                         retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
575                         break;
576                 default:
577                         break;
578                 }
579
580                 if (retval < 0)
581                         break;
582         }
583
584         return i;
585 }
586
587 static int gpio_open(struct inode *inode, struct file *file)
588 {
589         unsigned int pin;
590
591         pin = iminor(inode);
592         if (pin >= giu_nr_pins)
593                 return -EBADF;
594
595         return nonseekable_open(inode, file);
596 }
597
598 static int gpio_release(struct inode *inode, struct file *file)
599 {
600         unsigned int pin;
601
602         pin = iminor(inode);
603         if (pin >= giu_nr_pins)
604                 return -EBADF;
605
606         return 0;
607 }
608
609 static const struct file_operations gpio_fops = {
610         .owner          = THIS_MODULE,
611         .read           = gpio_read,
612         .write          = gpio_write,
613         .open           = gpio_open,
614         .release        = gpio_release,
615 };
616
617 static int __devinit giu_probe(struct platform_device *dev)
618 {
619         unsigned long start, size, flags = 0;
620         unsigned int nr_pins = 0;
621         struct resource *res1, *res2 = NULL;
622         void *base;
623         int retval, i;
624
625         switch (current_cpu_data.cputype) {
626         case CPU_VR4111:
627         case CPU_VR4121:
628                 start = GIU_TYPE1_START;
629                 size = GIU_TYPE1_SIZE;
630                 flags = GPIO_HAS_PULLUPDOWN_IO;
631                 nr_pins = 50;
632                 break;
633         case CPU_VR4122:
634         case CPU_VR4131:
635                 start = GIU_TYPE2_START;
636                 size = GIU_TYPE2_SIZE;
637                 nr_pins = 36;
638                 break;
639         case CPU_VR4133:
640                 start = GIU_TYPE3_START;
641                 size = GIU_TYPE3_SIZE;
642                 flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
643                 nr_pins = 48;
644                 break;
645         default:
646                 return -ENODEV;
647         }
648
649         res1 = request_mem_region(start, size, "GIU");
650         if (res1 == NULL)
651                 return -EBUSY;
652
653         base = ioremap(start, size);
654         if (base == NULL) {
655                 release_resource(res1);
656                 return -ENOMEM;
657         }
658
659         if (flags & GPIO_HAS_PULLUPDOWN_IO) {
660                 res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
661                 if (res2 == NULL) {
662                         iounmap(base);
663                         release_resource(res1);
664                         return -EBUSY;
665                 }
666         }
667
668         retval = register_chrdev(major, "GIU", &gpio_fops);
669         if (retval < 0) {
670                 iounmap(base);
671                 release_resource(res1);
672                 release_resource(res2);
673                 return retval;
674         }
675
676         if (major == 0) {
677                 major = retval;
678                 printk(KERN_INFO "GIU: major number %d\n", major);
679         }
680
681         spin_lock_init(&giu_lock);
682         giu_base = base;
683         giu_resource1 = res1;
684         giu_resource2 = res2;
685         giu_flags = flags;
686         giu_nr_pins = nr_pins;
687
688         giu_write(GIUINTENL, 0);
689         giu_write(GIUINTENH, 0);
690
691         for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
692                 if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))
693                         irq_desc[i].chip = &giuint_low_irq_type;
694                 else
695                         irq_desc[i].chip = &giuint_high_irq_type;
696         }
697
698         return cascade_irq(GIUINT_IRQ, giu_get_irq);
699 }
700
701 static int __devexit giu_remove(struct platform_device *dev)
702 {
703         iounmap(giu_base);
704
705         release_resource(giu_resource1);
706         if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
707                 release_resource(giu_resource2);
708
709         return 0;
710 }
711
712 static struct platform_device *giu_platform_device;
713
714 static struct platform_driver giu_device_driver = {
715         .probe          = giu_probe,
716         .remove         = __devexit_p(giu_remove),
717         .driver         = {
718                 .name   = "GIU",
719                 .owner  = THIS_MODULE,
720         },
721 };
722
723 static int __init vr41xx_giu_init(void)
724 {
725         int retval;
726
727         giu_platform_device = platform_device_alloc("GIU", -1);
728         if (!giu_platform_device)
729                 return -ENOMEM;
730
731         retval = platform_device_add(giu_platform_device);
732         if (retval < 0) {
733                 platform_device_put(giu_platform_device);
734                 return retval;
735         }
736
737         retval = platform_driver_register(&giu_device_driver);
738         if (retval < 0)
739                 platform_device_unregister(giu_platform_device);
740
741         return retval;
742 }
743
744 static void __exit vr41xx_giu_exit(void)
745 {
746         platform_driver_unregister(&giu_device_driver);
747
748         platform_device_unregister(giu_platform_device);
749 }
750
751 module_init(vr41xx_giu_init);
752 module_exit(vr41xx_giu_exit);