headers: smp_lock.h redux
[linux-2.6] / 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 <source@mvista.com>
6  *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.org>
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/spinlock.h>
33 #include <linux/types.h>
34
35 #include <asm/vr41xx/giu.h>
36 #include <asm/vr41xx/irq.h>
37 #include <asm/vr41xx/vr41xx.h>
38
39 MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
40 MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
41 MODULE_LICENSE("GPL");
42
43 #define GIUIOSELL       0x00
44 #define GIUIOSELH       0x02
45 #define GIUPIODL        0x04
46 #define GIUPIODH        0x06
47 #define GIUINTSTATL     0x08
48 #define GIUINTSTATH     0x0a
49 #define GIUINTENL       0x0c
50 #define GIUINTENH       0x0e
51 #define GIUINTTYPL      0x10
52 #define GIUINTTYPH      0x12
53 #define GIUINTALSELL    0x14
54 #define GIUINTALSELH    0x16
55 #define GIUINTHTSELL    0x18
56 #define GIUINTHTSELH    0x1a
57 #define GIUPODATL       0x1c
58 #define GIUPODATEN      0x1c
59 #define GIUPODATH       0x1e
60  #define PIOEN0         0x0100
61  #define PIOEN1         0x0200
62 #define GIUPODAT        0x1e
63 #define GIUFEDGEINHL    0x20
64 #define GIUFEDGEINHH    0x22
65 #define GIUREDGEINHL    0x24
66 #define GIUREDGEINHH    0x26
67
68 #define GIUUSEUPDN      0x1e0
69 #define GIUTERMUPDN     0x1e2
70
71 #define GPIO_HAS_PULLUPDOWN_IO          0x0001
72 #define GPIO_HAS_OUTPUT_ENABLE          0x0002
73 #define GPIO_HAS_INTERRUPT_EDGE_SELECT  0x0100
74
75 enum {
76         GPIO_INPUT,
77         GPIO_OUTPUT,
78 };
79
80 static DEFINE_SPINLOCK(giu_lock);
81 static unsigned long giu_flags;
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 u16 giu_set(u16 offset, u16 set)
93 {
94         u16 data;
95
96         data = giu_read(offset);
97         data |= set;
98         giu_write(offset, data);
99
100         return data;
101 }
102
103 static inline u16 giu_clear(u16 offset, u16 clear)
104 {
105         u16 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,
149                   1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
150 }
151
152 static void mask_giuint_high(unsigned int irq)
153 {
154         giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
155 }
156
157 static void mask_ack_giuint_high(unsigned int irq)
158 {
159         unsigned int pin;
160
161         pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
162         giu_clear(GIUINTENH, 1 << pin);
163         giu_write(GIUINTSTATH, 1 << pin);
164 }
165
166 static void unmask_giuint_high(unsigned int irq)
167 {
168         giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
169 }
170
171 static struct irq_chip giuint_high_irq_chip = {
172         .name           = "GIUINTH",
173         .ack            = ack_giuint_high,
174         .mask           = mask_giuint_high,
175         .mask_ack       = mask_ack_giuint_high,
176         .unmask         = unmask_giuint_high,
177 };
178
179 static int giu_get_irq(unsigned int irq)
180 {
181         u16 pendl, pendh, maskl, maskh;
182         int i;
183
184         pendl = giu_read(GIUINTSTATL);
185         pendh = giu_read(GIUINTSTATH);
186         maskl = giu_read(GIUINTENL);
187         maskh = giu_read(GIUINTENH);
188
189         maskl &= pendl;
190         maskh &= pendh;
191
192         if (maskl) {
193                 for (i = 0; i < 16; i++) {
194                         if (maskl & (1 << i))
195                                 return GIU_IRQ(i);
196                 }
197         } else if (maskh) {
198                 for (i = 0; i < 16; i++) {
199                         if (maskh & (1 << i))
200                                 return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
201                 }
202         }
203
204         printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
205                maskl, pendl, maskh, pendh);
206
207         atomic_inc(&irq_err_count);
208
209         return -EINVAL;
210 }
211
212 void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
213                             irq_signal_t signal)
214 {
215         u16 mask;
216
217         if (pin < GIUINT_HIGH_OFFSET) {
218                 mask = 1 << pin;
219                 if (trigger != IRQ_TRIGGER_LEVEL) {
220                         giu_set(GIUINTTYPL, mask);
221                         if (signal == IRQ_SIGNAL_HOLD)
222                                 giu_set(GIUINTHTSELL, mask);
223                         else
224                                 giu_clear(GIUINTHTSELL, mask);
225                         if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
226                                 switch (trigger) {
227                                 case IRQ_TRIGGER_EDGE_FALLING:
228                                         giu_set(GIUFEDGEINHL, mask);
229                                         giu_clear(GIUREDGEINHL, mask);
230                                         break;
231                                 case IRQ_TRIGGER_EDGE_RISING:
232                                         giu_clear(GIUFEDGEINHL, mask);
233                                         giu_set(GIUREDGEINHL, mask);
234                                         break;
235                                 default:
236                                         giu_set(GIUFEDGEINHL, mask);
237                                         giu_set(GIUREDGEINHL, mask);
238                                         break;
239                                 }
240                         }
241                         set_irq_chip_and_handler(GIU_IRQ(pin),
242                                                  &giuint_low_irq_chip,
243                                                  handle_edge_irq);
244                 } else {
245                         giu_clear(GIUINTTYPL, mask);
246                         giu_clear(GIUINTHTSELL, mask);
247                         set_irq_chip_and_handler(GIU_IRQ(pin),
248                                                  &giuint_low_irq_chip,
249                                                  handle_level_irq);
250                 }
251                 giu_write(GIUINTSTATL, mask);
252         } else if (pin < GIUINT_HIGH_MAX) {
253                 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
254                 if (trigger != IRQ_TRIGGER_LEVEL) {
255                         giu_set(GIUINTTYPH, mask);
256                         if (signal == IRQ_SIGNAL_HOLD)
257                                 giu_set(GIUINTHTSELH, mask);
258                         else
259                                 giu_clear(GIUINTHTSELH, mask);
260                         if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
261                                 switch (trigger) {
262                                 case IRQ_TRIGGER_EDGE_FALLING:
263                                         giu_set(GIUFEDGEINHH, mask);
264                                         giu_clear(GIUREDGEINHH, mask);
265                                         break;
266                                 case IRQ_TRIGGER_EDGE_RISING:
267                                         giu_clear(GIUFEDGEINHH, mask);
268                                         giu_set(GIUREDGEINHH, mask);
269                                         break;
270                                 default:
271                                         giu_set(GIUFEDGEINHH, mask);
272                                         giu_set(GIUREDGEINHH, mask);
273                                         break;
274                                 }
275                         }
276                         set_irq_chip_and_handler(GIU_IRQ(pin),
277                                                  &giuint_high_irq_chip,
278                                                  handle_edge_irq);
279                 } else {
280                         giu_clear(GIUINTTYPH, mask);
281                         giu_clear(GIUINTHTSELH, mask);
282                         set_irq_chip_and_handler(GIU_IRQ(pin),
283                                                  &giuint_high_irq_chip,
284                                                  handle_level_irq);
285                 }
286                 giu_write(GIUINTSTATH, mask);
287         }
288 }
289 EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
290
291 void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
292 {
293         u16 mask;
294
295         if (pin < GIUINT_HIGH_OFFSET) {
296                 mask = 1 << pin;
297                 if (level == IRQ_LEVEL_HIGH)
298                         giu_set(GIUINTALSELL, mask);
299                 else
300                         giu_clear(GIUINTALSELL, mask);
301                 giu_write(GIUINTSTATL, mask);
302         } else if (pin < GIUINT_HIGH_MAX) {
303                 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
304                 if (level == IRQ_LEVEL_HIGH)
305                         giu_set(GIUINTALSELH, mask);
306                 else
307                         giu_clear(GIUINTALSELH, mask);
308                 giu_write(GIUINTSTATH, mask);
309         }
310 }
311 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
312
313 static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
314 {
315         u16 offset, mask, reg;
316         unsigned long flags;
317
318         if (pin >= chip->ngpio)
319                 return -EINVAL;
320
321         if (pin < 16) {
322                 offset = GIUIOSELL;
323                 mask = 1 << pin;
324         } else if (pin < 32) {
325                 offset = GIUIOSELH;
326                 mask = 1 << (pin - 16);
327         } else {
328                 if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
329                         offset = GIUPODATEN;
330                         mask = 1 << (pin - 32);
331                 } else {
332                         switch (pin) {
333                         case 48:
334                                 offset = GIUPODATH;
335                                 mask = PIOEN0;
336                                 break;
337                         case 49:
338                                 offset = GIUPODATH;
339                                 mask = PIOEN1;
340                                 break;
341                         default:
342                                 return -EINVAL;
343                         }
344                 }
345         }
346
347         spin_lock_irqsave(&giu_lock, flags);
348
349         reg = giu_read(offset);
350         if (dir == GPIO_OUTPUT)
351                 reg |= mask;
352         else
353                 reg &= ~mask;
354         giu_write(offset, reg);
355
356         spin_unlock_irqrestore(&giu_lock, flags);
357
358         return 0;
359 }
360
361 int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
362 {
363         u16 reg, mask;
364         unsigned long flags;
365
366         if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
367                 return -EPERM;
368
369         if (pin >= 15)
370                 return -EINVAL;
371
372         mask = 1 << pin;
373
374         spin_lock_irqsave(&giu_lock, flags);
375
376         if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
377                 reg = giu_read(GIUTERMUPDN);
378                 if (pull == GPIO_PULL_UP)
379                         reg |= mask;
380                 else
381                         reg &= ~mask;
382                 giu_write(GIUTERMUPDN, reg);
383
384                 reg = giu_read(GIUUSEUPDN);
385                 reg |= mask;
386                 giu_write(GIUUSEUPDN, reg);
387         } else {
388                 reg = giu_read(GIUUSEUPDN);
389                 reg &= ~mask;
390                 giu_write(GIUUSEUPDN, reg);
391         }
392
393         spin_unlock_irqrestore(&giu_lock, flags);
394
395         return 0;
396 }
397 EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
398
399 static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
400 {
401         u16 reg, mask;
402
403         if (pin >= chip->ngpio)
404                 return -EINVAL;
405
406         if (pin < 16) {
407                 reg = giu_read(GIUPIODL);
408                 mask = 1 << pin;
409         } else if (pin < 32) {
410                 reg = giu_read(GIUPIODH);
411                 mask = 1 << (pin - 16);
412         } else if (pin < 48) {
413                 reg = giu_read(GIUPODATL);
414                 mask = 1 << (pin - 32);
415         } else {
416                 reg = giu_read(GIUPODATH);
417                 mask = 1 << (pin - 48);
418         }
419
420         if (reg & mask)
421                 return 1;
422
423         return 0;
424 }
425
426 static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
427                             int value)
428 {
429         u16 offset, mask, reg;
430         unsigned long flags;
431
432         if (pin >= chip->ngpio)
433                 return;
434
435         if (pin < 16) {
436                 offset = GIUPIODL;
437                 mask = 1 << pin;
438         } else if (pin < 32) {
439                 offset = GIUPIODH;
440                 mask = 1 << (pin - 16);
441         } else if (pin < 48) {
442                 offset = GIUPODATL;
443                 mask = 1 << (pin - 32);
444         } else {
445                 offset = GIUPODATH;
446                 mask = 1 << (pin - 48);
447         }
448
449         spin_lock_irqsave(&giu_lock, flags);
450
451         reg = giu_read(offset);
452         if (value)
453                 reg |= mask;
454         else
455                 reg &= ~mask;
456         giu_write(offset, reg);
457
458         spin_unlock_irqrestore(&giu_lock, flags);
459 }
460
461
462 static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
463 {
464         return giu_set_direction(chip, offset, GPIO_INPUT);
465 }
466
467 static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
468                                 int value)
469 {
470         vr41xx_gpio_set(chip, offset, value);
471
472         return giu_set_direction(chip, offset, GPIO_OUTPUT);
473 }
474
475 static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
476 {
477         if (offset >= chip->ngpio)
478                 return -EINVAL;
479
480         return GIU_IRQ_BASE + offset;
481 }
482
483 static struct gpio_chip vr41xx_gpio_chip = {
484         .label                  = "vr41xx",
485         .owner                  = THIS_MODULE,
486         .direction_input        = vr41xx_gpio_direction_input,
487         .get                    = vr41xx_gpio_get,
488         .direction_output       = vr41xx_gpio_direction_output,
489         .set                    = vr41xx_gpio_set,
490         .to_irq                 = vr41xx_gpio_to_irq,
491 };
492
493 static int __devinit giu_probe(struct platform_device *pdev)
494 {
495         struct resource *res;
496         unsigned int trigger, i, pin;
497         struct irq_chip *chip;
498         int irq, retval;
499
500         switch (pdev->id) {
501         case GPIO_50PINS_PULLUPDOWN:
502                 giu_flags = GPIO_HAS_PULLUPDOWN_IO;
503                 vr41xx_gpio_chip.ngpio = 50;
504                 break;
505         case GPIO_36PINS:
506                 vr41xx_gpio_chip.ngpio = 36;
507                 break;
508         case GPIO_48PINS_EDGE_SELECT:
509                 giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
510                 vr41xx_gpio_chip.ngpio = 48;
511                 break;
512         default:
513                 dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
514                 return -ENODEV;
515         }
516
517         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
518         if (!res)
519                 return -EBUSY;
520
521         giu_base = ioremap(res->start, res->end - res->start + 1);
522         if (!giu_base)
523                 return -ENOMEM;
524
525         vr41xx_gpio_chip.dev = &pdev->dev;
526
527         retval = gpiochip_add(&vr41xx_gpio_chip);
528
529         giu_write(GIUINTENL, 0);
530         giu_write(GIUINTENH, 0);
531
532         trigger = giu_read(GIUINTTYPH) << 16;
533         trigger |= giu_read(GIUINTTYPL);
534         for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
535                 pin = GPIO_PIN_OF_IRQ(i);
536                 if (pin < GIUINT_HIGH_OFFSET)
537                         chip = &giuint_low_irq_chip;
538                 else
539                         chip = &giuint_high_irq_chip;
540
541                 if (trigger & (1 << pin))
542                         set_irq_chip_and_handler(i, chip, handle_edge_irq);
543                 else
544                         set_irq_chip_and_handler(i, chip, handle_level_irq);
545
546         }
547
548         irq = platform_get_irq(pdev, 0);
549         if (irq < 0 || irq >= nr_irqs)
550                 return -EBUSY;
551
552         return cascade_irq(irq, giu_get_irq);
553 }
554
555 static int __devexit giu_remove(struct platform_device *pdev)
556 {
557         if (giu_base) {
558                 iounmap(giu_base);
559                 giu_base = NULL;
560         }
561
562         return 0;
563 }
564
565 static struct platform_driver giu_device_driver = {
566         .probe          = giu_probe,
567         .remove         = __devexit_p(giu_remove),
568         .driver         = {
569                 .name   = "GIU",
570                 .owner  = THIS_MODULE,
571         },
572 };
573
574 static int __init vr41xx_giu_init(void)
575 {
576         return platform_driver_register(&giu_device_driver);
577 }
578
579 static void __exit vr41xx_giu_exit(void)
580 {
581         platform_driver_unregister(&giu_device_driver);
582 }
583
584 module_init(vr41xx_giu_init);
585 module_exit(vr41xx_giu_exit);