Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gpio-pl061.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008, 2009 Provigent Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
9  *
10  * Data sheet: ARM DDI 0190B, September 2000
11  */
12 #include <linux/spinlock.h>
13 #include <linux/errno.h>
14 #include <linux/module.h>
15 #include <linux/io.h>
16 #include <linux/ioport.h>
17 #include <linux/irq.h>
18 #include <linux/bitops.h>
19 #include <linux/workqueue.h>
20 #include <linux/gpio.h>
21 #include <linux/device.h>
22 #include <linux/amba/bus.h>
23 #include <linux/amba/pl061.h>
24 #include <linux/slab.h>
25 #include <linux/pm.h>
26 #include <asm/mach/irq.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 #ifdef CONFIG_PM
40 struct pl061_context_save_regs {
41  u8 gpio_data;
42  u8 gpio_dir;
43  u8 gpio_is;
44  u8 gpio_ibe;
45  u8 gpio_iev;
46  u8 gpio_ie;
47 };
48 #endif
49 
50 struct pl061_gpio {
51  /* Each of the two spinlocks protects a different set of hardware
52  * regiters and data structurs. This decouples the code of the IRQ from
53  * the GPIO code. This also makes the case of a GPIO routine call from
54  * the IRQ code simpler.
55  */
56  spinlock_t lock; /* GPIO registers */
57 
58  void __iomem *base;
59  int irq_base;
60  struct irq_chip_generic *irq_gc;
61  struct gpio_chip gc;
62 
63 #ifdef CONFIG_PM
64  struct pl061_context_save_regs csave_regs;
65 #endif
66 };
67 
68 static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
69 {
70  struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
71  unsigned long flags;
72  unsigned char gpiodir;
73 
74  if (offset >= gc->ngpio)
75  return -EINVAL;
76 
77  spin_lock_irqsave(&chip->lock, flags);
78  gpiodir = readb(chip->base + GPIODIR);
79  gpiodir &= ~(1 << offset);
80  writeb(gpiodir, chip->base + GPIODIR);
81  spin_unlock_irqrestore(&chip->lock, flags);
82 
83  return 0;
84 }
85 
86 static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
87  int value)
88 {
89  struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
90  unsigned long flags;
91  unsigned char gpiodir;
92 
93  if (offset >= gc->ngpio)
94  return -EINVAL;
95 
96  spin_lock_irqsave(&chip->lock, flags);
97  writeb(!!value << offset, chip->base + (1 << (offset + 2)));
98  gpiodir = readb(chip->base + GPIODIR);
99  gpiodir |= 1 << offset;
100  writeb(gpiodir, chip->base + GPIODIR);
101 
102  /*
103  * gpio value is set again, because pl061 doesn't allow to set value of
104  * a gpio pin before configuring it in OUT mode.
105  */
106  writeb(!!value << offset, chip->base + (1 << (offset + 2)));
107  spin_unlock_irqrestore(&chip->lock, flags);
108 
109  return 0;
110 }
111 
112 static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
113 {
114  struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
115 
116  return !!readb(chip->base + (1 << (offset + 2)));
117 }
118 
119 static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
120 {
121  struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
122 
123  writeb(!!value << offset, chip->base + (1 << (offset + 2)));
124 }
125 
126 static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
127 {
128  struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
129 
130  if (chip->irq_base <= 0)
131  return -EINVAL;
132 
133  return chip->irq_base + offset;
134 }
135 
136 static int pl061_irq_type(struct irq_data *d, unsigned trigger)
137 {
138  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
139  struct pl061_gpio *chip = gc->private;
140  int offset = d->irq - chip->irq_base;
141  unsigned long flags;
142  u8 gpiois, gpioibe, gpioiev;
143 
145  return -EINVAL;
146 
147  raw_spin_lock_irqsave(&gc->lock, flags);
148 
149  gpioiev = readb(chip->base + GPIOIEV);
150 
151  gpiois = readb(chip->base + GPIOIS);
152  if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
153  gpiois |= 1 << offset;
154  if (trigger & IRQ_TYPE_LEVEL_HIGH)
155  gpioiev |= 1 << offset;
156  else
157  gpioiev &= ~(1 << offset);
158  } else
159  gpiois &= ~(1 << offset);
160  writeb(gpiois, chip->base + GPIOIS);
161 
162  gpioibe = readb(chip->base + GPIOIBE);
163  if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
164  gpioibe |= 1 << offset;
165  else {
166  gpioibe &= ~(1 << offset);
167  if (trigger & IRQ_TYPE_EDGE_RISING)
168  gpioiev |= 1 << offset;
169  else if (trigger & IRQ_TYPE_EDGE_FALLING)
170  gpioiev &= ~(1 << offset);
171  }
172  writeb(gpioibe, chip->base + GPIOIBE);
173 
174  writeb(gpioiev, chip->base + GPIOIEV);
175 
176  raw_spin_unlock_irqrestore(&gc->lock, flags);
177 
178  return 0;
179 }
180 
181 static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
182 {
183  unsigned long pending;
184  int offset;
185  struct pl061_gpio *chip = irq_desc_get_handler_data(desc);
186  struct irq_chip *irqchip = irq_desc_get_chip(desc);
187 
188  chained_irq_enter(irqchip, desc);
189 
190  pending = readb(chip->base + GPIOMIS);
191  writeb(pending, chip->base + GPIOIC);
192  if (pending) {
193  for_each_set_bit(offset, &pending, PL061_GPIO_NR)
194  generic_handle_irq(pl061_to_irq(&chip->gc, offset));
195  }
196 
197  chained_irq_exit(irqchip, desc);
198 }
199 
200 static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
201 {
202  struct irq_chip_type *ct;
203 
204  chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base,
205  chip->base, handle_simple_irq);
206  chip->irq_gc->private = chip;
207 
208  ct = chip->irq_gc->chip_types;
209  ct->chip.irq_mask = irq_gc_mask_clr_bit;
210  ct->chip.irq_unmask = irq_gc_mask_set_bit;
211  ct->chip.irq_set_type = pl061_irq_type;
212  ct->chip.irq_set_wake = irq_gc_set_wake;
213  ct->regs.mask = GPIOIE;
214 
215  irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR),
216  IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
217 }
218 
219 static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
220 {
221  struct pl061_platform_data *pdata;
222  struct pl061_gpio *chip;
223  int ret, irq, i;
224 
225  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
226  if (chip == NULL)
227  return -ENOMEM;
228 
229  pdata = dev->dev.platform_data;
230  if (pdata) {
231  chip->gc.base = pdata->gpio_base;
232  chip->irq_base = pdata->irq_base;
233  } else if (dev->dev.of_node) {
234  chip->gc.base = -1;
235  chip->irq_base = 0;
236  } else {
237  ret = -ENODEV;
238  goto free_mem;
239  }
240 
241  if (!request_mem_region(dev->res.start,
242  resource_size(&dev->res), "pl061")) {
243  ret = -EBUSY;
244  goto free_mem;
245  }
246 
247  chip->base = ioremap(dev->res.start, resource_size(&dev->res));
248  if (chip->base == NULL) {
249  ret = -ENOMEM;
250  goto release_region;
251  }
252 
253  spin_lock_init(&chip->lock);
254 
255  chip->gc.direction_input = pl061_direction_input;
256  chip->gc.direction_output = pl061_direction_output;
257  chip->gc.get = pl061_get_value;
258  chip->gc.set = pl061_set_value;
259  chip->gc.to_irq = pl061_to_irq;
260  chip->gc.ngpio = PL061_GPIO_NR;
261  chip->gc.label = dev_name(&dev->dev);
262  chip->gc.dev = &dev->dev;
263  chip->gc.owner = THIS_MODULE;
264 
265  ret = gpiochip_add(&chip->gc);
266  if (ret)
267  goto iounmap;
268 
269  /*
270  * irq_chip support
271  */
272 
273  if (chip->irq_base <= 0)
274  return 0;
275 
276  pl061_init_gc(chip, chip->irq_base);
277 
278  writeb(0, chip->base + GPIOIE); /* disable irqs */
279  irq = dev->irq[0];
280  if (irq < 0) {
281  ret = -ENODEV;
282  goto iounmap;
283  }
284  irq_set_chained_handler(irq, pl061_irq_handler);
285  irq_set_handler_data(irq, chip);
286 
287  for (i = 0; i < PL061_GPIO_NR; i++) {
288  if (pdata) {
289  if (pdata->directions & (1 << i))
290  pl061_direction_output(&chip->gc, i,
291  pdata->values & (1 << i));
292  else
293  pl061_direction_input(&chip->gc, i);
294  }
295  }
296 
297  amba_set_drvdata(dev, chip);
298 
299  return 0;
300 
301 iounmap:
302  iounmap(chip->base);
304  release_mem_region(dev->res.start, resource_size(&dev->res));
305 free_mem:
306  kfree(chip);
307 
308  return ret;
309 }
310 
311 #ifdef CONFIG_PM
312 static int pl061_suspend(struct device *dev)
313 {
314  struct pl061_gpio *chip = dev_get_drvdata(dev);
315  int offset;
316 
317  chip->csave_regs.gpio_data = 0;
318  chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR);
319  chip->csave_regs.gpio_is = readb(chip->base + GPIOIS);
320  chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE);
321  chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV);
322  chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
323 
324  for (offset = 0; offset < PL061_GPIO_NR; offset++) {
325  if (chip->csave_regs.gpio_dir & (1 << offset))
326  chip->csave_regs.gpio_data |=
327  pl061_get_value(&chip->gc, offset) << offset;
328  }
329 
330  return 0;
331 }
332 
333 static int pl061_resume(struct device *dev)
334 {
335  struct pl061_gpio *chip = dev_get_drvdata(dev);
336  int offset;
337 
338  for (offset = 0; offset < PL061_GPIO_NR; offset++) {
339  if (chip->csave_regs.gpio_dir & (1 << offset))
340  pl061_direction_output(&chip->gc, offset,
341  chip->csave_regs.gpio_data &
342  (1 << offset));
343  else
344  pl061_direction_input(&chip->gc, offset);
345  }
346 
347  writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS);
348  writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE);
349  writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV);
350  writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE);
351 
352  return 0;
353 }
354 
355 static const struct dev_pm_ops pl061_dev_pm_ops = {
356  .suspend = pl061_suspend,
357  .resume = pl061_resume,
358  .freeze = pl061_suspend,
359  .restore = pl061_resume,
360 };
361 #endif
362 
363 static struct amba_id pl061_ids[] = {
364  {
365  .id = 0x00041061,
366  .mask = 0x000fffff,
367  },
368  { 0, 0 },
369 };
370 
371 MODULE_DEVICE_TABLE(amba, pl061_ids);
372 
373 static struct amba_driver pl061_gpio_driver = {
374  .drv = {
375  .name = "pl061_gpio",
376 #ifdef CONFIG_PM
377  .pm = &pl061_dev_pm_ops,
378 #endif
379  },
380  .id_table = pl061_ids,
381  .probe = pl061_probe,
382 };
383 
384 static int __init pl061_gpio_init(void)
385 {
386  return amba_driver_register(&pl061_gpio_driver);
387 }
388 subsys_initcall(pl061_gpio_init);
389 
390 MODULE_AUTHOR("Baruch Siach <[email protected]>");
391 MODULE_DESCRIPTION("PL061 GPIO driver");
392 MODULE_LICENSE("GPL");