Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[linux-2.6] / drivers / gpio / pl061.c
1 /*
2  *  linux/drivers/gpio/pl061.c
3  *
4  *  Copyright (C) 2008, 2009 Provigent Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
11  *
12  * Data sheet: ARM DDI 0190B, September 2000
13  */
14 #include <linux/spinlock.h>
15 #include <linux/errno.h>
16 #include <linux/module.h>
17 #include <linux/list.h>
18 #include <linux/io.h>
19 #include <linux/ioport.h>
20 #include <linux/irq.h>
21 #include <linux/bitops.h>
22 #include <linux/workqueue.h>
23 #include <linux/gpio.h>
24 #include <linux/device.h>
25 #include <linux/amba/bus.h>
26 #include <linux/amba/pl061.h>
27
28 #define GPIODIR 0x400
29 #define GPIOIS  0x404
30 #define GPIOIBE 0x408
31 #define GPIOIEV 0x40C
32 #define GPIOIE  0x410
33 #define GPIORIS 0x414
34 #define GPIOMIS 0x418
35 #define GPIOIC  0x41C
36
37 #define PL061_GPIO_NR   8
38
39 struct pl061_gpio {
40         /* We use a list of pl061_gpio structs for each trigger IRQ in the main
41          * interrupts controller of the system. We need this to support systems
42          * in which more that one PL061s are connected to the same IRQ. The ISR
43          * interates through this list to find the source of the interrupt.
44          */
45         struct list_head        list;
46
47         /* Each of the two spinlocks protects a different set of hardware
48          * regiters and data structurs. This decouples the code of the IRQ from
49          * the GPIO code. This also makes the case of a GPIO routine call from
50          * the IRQ code simpler.
51          */
52         spinlock_t              lock;           /* GPIO registers */
53         spinlock_t              irq_lock;       /* IRQ registers */
54
55         void __iomem            *base;
56         unsigned                irq_base;
57         struct gpio_chip        gc;
58 };
59
60 static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
61 {
62         struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
63         unsigned long flags;
64         unsigned char gpiodir;
65
66         if (offset >= gc->ngpio)
67                 return -EINVAL;
68
69         spin_lock_irqsave(&chip->lock, flags);
70         gpiodir = readb(chip->base + GPIODIR);
71         gpiodir &= ~(1 << offset);
72         writeb(gpiodir, chip->base + GPIODIR);
73         spin_unlock_irqrestore(&chip->lock, flags);
74
75         return 0;
76 }
77
78 static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
79                 int value)
80 {
81         struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
82         unsigned long flags;
83         unsigned char gpiodir;
84
85         if (offset >= gc->ngpio)
86                 return -EINVAL;
87
88         spin_lock_irqsave(&chip->lock, flags);
89         writeb(!!value << offset, chip->base + (1 << (offset + 2)));
90         gpiodir = readb(chip->base + GPIODIR);
91         gpiodir |= 1 << offset;
92         writeb(gpiodir, chip->base + GPIODIR);
93         spin_unlock_irqrestore(&chip->lock, flags);
94
95         return 0;
96 }
97
98 static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
99 {
100         struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
101
102         return !!readb(chip->base + (1 << (offset + 2)));
103 }
104
105 static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
106 {
107         struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
108
109         writeb(!!value << offset, chip->base + (1 << (offset + 2)));
110 }
111
112 static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
113 {
114         struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
115
116         if (chip->irq_base == (unsigned) -1)
117                 return -EINVAL;
118
119         return chip->irq_base + offset;
120 }
121
122 /*
123  * PL061 GPIO IRQ
124  */
125 static void pl061_irq_disable(unsigned irq)
126 {
127         struct pl061_gpio *chip = get_irq_chip_data(irq);
128         int offset = irq - chip->irq_base;
129         unsigned long flags;
130         u8 gpioie;
131
132         spin_lock_irqsave(&chip->irq_lock, flags);
133         gpioie = readb(chip->base + GPIOIE);
134         gpioie &= ~(1 << offset);
135         writeb(gpioie, chip->base + GPIOIE);
136         spin_unlock_irqrestore(&chip->irq_lock, flags);
137 }
138
139 static void pl061_irq_enable(unsigned irq)
140 {
141         struct pl061_gpio *chip = get_irq_chip_data(irq);
142         int offset = irq - chip->irq_base;
143         unsigned long flags;
144         u8 gpioie;
145
146         spin_lock_irqsave(&chip->irq_lock, flags);
147         gpioie = readb(chip->base + GPIOIE);
148         gpioie |= 1 << offset;
149         writeb(gpioie, chip->base + GPIOIE);
150         spin_unlock_irqrestore(&chip->irq_lock, flags);
151 }
152
153 static int pl061_irq_type(unsigned irq, unsigned trigger)
154 {
155         struct pl061_gpio *chip = get_irq_chip_data(irq);
156         int offset = irq - chip->irq_base;
157         unsigned long flags;
158         u8 gpiois, gpioibe, gpioiev;
159
160         if (offset < 0 || offset > PL061_GPIO_NR)
161                 return -EINVAL;
162
163         spin_lock_irqsave(&chip->irq_lock, flags);
164
165         gpioiev = readb(chip->base + GPIOIEV);
166
167         gpiois = readb(chip->base + GPIOIS);
168         if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
169                 gpiois |= 1 << offset;
170                 if (trigger & IRQ_TYPE_LEVEL_HIGH)
171                         gpioiev |= 1 << offset;
172                 else
173                         gpioiev &= ~(1 << offset);
174         } else
175                 gpiois &= ~(1 << offset);
176         writeb(gpiois, chip->base + GPIOIS);
177
178         gpioibe = readb(chip->base + GPIOIBE);
179         if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
180                 gpioibe |= 1 << offset;
181         else {
182                 gpioibe &= ~(1 << offset);
183                 if (trigger & IRQ_TYPE_EDGE_RISING)
184                         gpioiev |= 1 << offset;
185                 else
186                         gpioiev &= ~(1 << offset);
187         }
188         writeb(gpioibe, chip->base + GPIOIBE);
189
190         writeb(gpioiev, chip->base + GPIOIEV);
191
192         spin_unlock_irqrestore(&chip->irq_lock, flags);
193
194         return 0;
195 }
196
197 static struct irq_chip pl061_irqchip = {
198         .name           = "GPIO",
199         .enable         = pl061_irq_enable,
200         .disable        = pl061_irq_disable,
201         .set_type       = pl061_irq_type,
202 };
203
204 static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
205 {
206         struct list_head *chip_list = get_irq_chip_data(irq);
207         struct list_head *ptr;
208         struct pl061_gpio *chip;
209
210         desc->chip->ack(irq);
211         list_for_each(ptr, chip_list) {
212                 unsigned long pending;
213                 int offset;
214
215                 chip = list_entry(ptr, struct pl061_gpio, list);
216                 pending = readb(chip->base + GPIOMIS);
217                 writeb(pending, chip->base + GPIOIC);
218
219                 if (pending == 0)
220                         continue;
221
222                 for_each_bit(offset, &pending, PL061_GPIO_NR)
223                         generic_handle_irq(pl061_to_irq(&chip->gc, offset));
224         }
225         desc->chip->unmask(irq);
226 }
227
228 static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)
229 {
230         struct pl061_platform_data *pdata;
231         struct pl061_gpio *chip;
232         struct list_head *chip_list;
233         int ret, irq, i;
234         static DECLARE_BITMAP(init_irq, NR_IRQS);
235
236         pdata = dev->dev.platform_data;
237         if (pdata == NULL)
238                 return -ENODEV;
239
240         chip = kzalloc(sizeof(*chip), GFP_KERNEL);
241         if (chip == NULL)
242                 return -ENOMEM;
243
244         if (!request_mem_region(dev->res.start,
245                                 resource_size(&dev->res), "pl061")) {
246                 ret = -EBUSY;
247                 goto free_mem;
248         }
249
250         chip->base = ioremap(dev->res.start, resource_size(&dev->res));
251         if (chip->base == NULL) {
252                 ret = -ENOMEM;
253                 goto release_region;
254         }
255
256         spin_lock_init(&chip->lock);
257         spin_lock_init(&chip->irq_lock);
258         INIT_LIST_HEAD(&chip->list);
259
260         chip->gc.direction_input = pl061_direction_input;
261         chip->gc.direction_output = pl061_direction_output;
262         chip->gc.get = pl061_get_value;
263         chip->gc.set = pl061_set_value;
264         chip->gc.to_irq = pl061_to_irq;
265         chip->gc.base = pdata->gpio_base;
266         chip->gc.ngpio = PL061_GPIO_NR;
267         chip->gc.label = dev_name(&dev->dev);
268         chip->gc.dev = &dev->dev;
269         chip->gc.owner = THIS_MODULE;
270
271         chip->irq_base = pdata->irq_base;
272
273         ret = gpiochip_add(&chip->gc);
274         if (ret)
275                 goto iounmap;
276
277         /*
278          * irq_chip support
279          */
280
281         if (chip->irq_base == (unsigned) -1)
282                 return 0;
283
284         writeb(0, chip->base + GPIOIE); /* disable irqs */
285         irq = dev->irq[0];
286         if (irq < 0) {
287                 ret = -ENODEV;
288                 goto iounmap;
289         }
290         set_irq_chained_handler(irq, pl061_irq_handler);
291         if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
292                 chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
293                 if (chip_list == NULL) {
294                         clear_bit(irq, init_irq);
295                         ret = -ENOMEM;
296                         goto iounmap;
297                 }
298                 INIT_LIST_HEAD(chip_list);
299                 set_irq_chip_data(irq, chip_list);
300         } else
301                 chip_list = get_irq_chip_data(irq);
302         list_add(&chip->list, chip_list);
303
304         for (i = 0; i < PL061_GPIO_NR; i++) {
305                 if (pdata->directions & (1 << i))
306                         pl061_direction_output(&chip->gc, i,
307                                         pdata->values & (1 << i));
308                 else
309                         pl061_direction_input(&chip->gc, i);
310
311                 set_irq_chip(i+chip->irq_base, &pl061_irqchip);
312                 set_irq_handler(i+chip->irq_base, handle_simple_irq);
313                 set_irq_flags(i+chip->irq_base, IRQF_VALID);
314                 set_irq_chip_data(i+chip->irq_base, chip);
315         }
316
317         return 0;
318
319 iounmap:
320         iounmap(chip->base);
321 release_region:
322         release_mem_region(dev->res.start, resource_size(&dev->res));
323 free_mem:
324         kfree(chip);
325
326         return ret;
327 }
328
329 static struct amba_id pl061_ids[] __initdata = {
330         {
331                 .id     = 0x00041061,
332                 .mask   = 0x000fffff,
333         },
334         { 0, 0 },
335 };
336
337 static struct amba_driver pl061_gpio_driver = {
338         .drv = {
339                 .name   = "pl061_gpio",
340         },
341         .id_table       = pl061_ids,
342         .probe          = pl061_probe,
343 };
344
345 static int __init pl061_gpio_init(void)
346 {
347         return amba_driver_register(&pl061_gpio_driver);
348 }
349 subsys_initcall(pl061_gpio_init);
350
351 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
352 MODULE_DESCRIPTION("PL061 GPIO driver");
353 MODULE_LICENSE("GPL");