diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2011-06-04 20:38:28 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-06-06 12:10:11 -0400 |
commit | c103de240439dfee24ac50eb99c8be3a30d13323 (patch) | |
tree | 014eeda779510d7d3dfabd1183ce7f1a288d367b /drivers/gpio/timbgpio.c | |
parent | 8c31b1635b91e48f867e010cd7bcd06393e5858a (diff) |
gpio: reorganize drivers
Sort the gpio makefile and enforce the naming convention gpio-*.c for
gpio drivers.
v2: cleaned up filenames in Kconfig and comment blocks
v3: fixup use of BASIC_MMIO to GENERIC_GPIO for mxc
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio/timbgpio.c')
-rw-r--r-- | drivers/gpio/timbgpio.c | 379 |
1 files changed, 0 insertions, 379 deletions
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c deleted file mode 100644 index 0265872e57d1..000000000000 --- a/drivers/gpio/timbgpio.c +++ /dev/null | |||
@@ -1,379 +0,0 @@ | |||
1 | /* | ||
2 | * timbgpio.c timberdale FPGA GPIO driver | ||
3 | * Copyright (c) 2009 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | /* Supports: | ||
20 | * Timberdale FPGA GPIO | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/timb_gpio.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/slab.h> | ||
31 | |||
32 | #define DRIVER_NAME "timb-gpio" | ||
33 | |||
34 | #define TGPIOVAL 0x00 | ||
35 | #define TGPIODIR 0x04 | ||
36 | #define TGPIO_IER 0x08 | ||
37 | #define TGPIO_ISR 0x0c | ||
38 | #define TGPIO_IPR 0x10 | ||
39 | #define TGPIO_ICR 0x14 | ||
40 | #define TGPIO_FLR 0x18 | ||
41 | #define TGPIO_LVR 0x1c | ||
42 | #define TGPIO_VER 0x20 | ||
43 | #define TGPIO_BFLR 0x24 | ||
44 | |||
45 | struct timbgpio { | ||
46 | void __iomem *membase; | ||
47 | spinlock_t lock; /* mutual exclusion */ | ||
48 | struct gpio_chip gpio; | ||
49 | int irq_base; | ||
50 | unsigned long last_ier; | ||
51 | }; | ||
52 | |||
53 | static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, | ||
54 | unsigned offset, bool enabled) | ||
55 | { | ||
56 | struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); | ||
57 | u32 reg; | ||
58 | |||
59 | spin_lock(&tgpio->lock); | ||
60 | reg = ioread32(tgpio->membase + offset); | ||
61 | |||
62 | if (enabled) | ||
63 | reg |= (1 << index); | ||
64 | else | ||
65 | reg &= ~(1 << index); | ||
66 | |||
67 | iowrite32(reg, tgpio->membase + offset); | ||
68 | spin_unlock(&tgpio->lock); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | ||
74 | { | ||
75 | return timbgpio_update_bit(gpio, nr, TGPIODIR, true); | ||
76 | } | ||
77 | |||
78 | static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) | ||
79 | { | ||
80 | struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); | ||
81 | u32 value; | ||
82 | |||
83 | value = ioread32(tgpio->membase + TGPIOVAL); | ||
84 | return (value & (1 << nr)) ? 1 : 0; | ||
85 | } | ||
86 | |||
87 | static int timbgpio_gpio_direction_output(struct gpio_chip *gpio, | ||
88 | unsigned nr, int val) | ||
89 | { | ||
90 | return timbgpio_update_bit(gpio, nr, TGPIODIR, false); | ||
91 | } | ||
92 | |||
93 | static void timbgpio_gpio_set(struct gpio_chip *gpio, | ||
94 | unsigned nr, int val) | ||
95 | { | ||
96 | timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0); | ||
97 | } | ||
98 | |||
99 | static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) | ||
100 | { | ||
101 | struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); | ||
102 | |||
103 | if (tgpio->irq_base <= 0) | ||
104 | return -EINVAL; | ||
105 | |||
106 | return tgpio->irq_base + offset; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * GPIO IRQ | ||
111 | */ | ||
112 | static void timbgpio_irq_disable(struct irq_data *d) | ||
113 | { | ||
114 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); | ||
115 | int offset = d->irq - tgpio->irq_base; | ||
116 | unsigned long flags; | ||
117 | |||
118 | spin_lock_irqsave(&tgpio->lock, flags); | ||
119 | tgpio->last_ier &= ~(1 << offset); | ||
120 | iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); | ||
121 | spin_unlock_irqrestore(&tgpio->lock, flags); | ||
122 | } | ||
123 | |||
124 | static void timbgpio_irq_enable(struct irq_data *d) | ||
125 | { | ||
126 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); | ||
127 | int offset = d->irq - tgpio->irq_base; | ||
128 | unsigned long flags; | ||
129 | |||
130 | spin_lock_irqsave(&tgpio->lock, flags); | ||
131 | tgpio->last_ier |= 1 << offset; | ||
132 | iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); | ||
133 | spin_unlock_irqrestore(&tgpio->lock, flags); | ||
134 | } | ||
135 | |||
136 | static int timbgpio_irq_type(struct irq_data *d, unsigned trigger) | ||
137 | { | ||
138 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); | ||
139 | int offset = d->irq - tgpio->irq_base; | ||
140 | unsigned long flags; | ||
141 | u32 lvr, flr, bflr = 0; | ||
142 | u32 ver; | ||
143 | int ret = 0; | ||
144 | |||
145 | if (offset < 0 || offset > tgpio->gpio.ngpio) | ||
146 | return -EINVAL; | ||
147 | |||
148 | ver = ioread32(tgpio->membase + TGPIO_VER); | ||
149 | |||
150 | spin_lock_irqsave(&tgpio->lock, flags); | ||
151 | |||
152 | lvr = ioread32(tgpio->membase + TGPIO_LVR); | ||
153 | flr = ioread32(tgpio->membase + TGPIO_FLR); | ||
154 | if (ver > 2) | ||
155 | bflr = ioread32(tgpio->membase + TGPIO_BFLR); | ||
156 | |||
157 | if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | ||
158 | bflr &= ~(1 << offset); | ||
159 | flr &= ~(1 << offset); | ||
160 | if (trigger & IRQ_TYPE_LEVEL_HIGH) | ||
161 | lvr |= 1 << offset; | ||
162 | else | ||
163 | lvr &= ~(1 << offset); | ||
164 | } | ||
165 | |||
166 | if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { | ||
167 | if (ver < 3) { | ||
168 | ret = -EINVAL; | ||
169 | goto out; | ||
170 | } | ||
171 | else { | ||
172 | flr |= 1 << offset; | ||
173 | bflr |= 1 << offset; | ||
174 | } | ||
175 | } else { | ||
176 | bflr &= ~(1 << offset); | ||
177 | flr |= 1 << offset; | ||
178 | if (trigger & IRQ_TYPE_EDGE_FALLING) | ||
179 | lvr &= ~(1 << offset); | ||
180 | else | ||
181 | lvr |= 1 << offset; | ||
182 | } | ||
183 | |||
184 | iowrite32(lvr, tgpio->membase + TGPIO_LVR); | ||
185 | iowrite32(flr, tgpio->membase + TGPIO_FLR); | ||
186 | if (ver > 2) | ||
187 | iowrite32(bflr, tgpio->membase + TGPIO_BFLR); | ||
188 | |||
189 | iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); | ||
190 | |||
191 | out: | ||
192 | spin_unlock_irqrestore(&tgpio->lock, flags); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) | ||
197 | { | ||
198 | struct timbgpio *tgpio = irq_get_handler_data(irq); | ||
199 | unsigned long ipr; | ||
200 | int offset; | ||
201 | |||
202 | desc->irq_data.chip->irq_ack(irq_get_irq_data(irq)); | ||
203 | ipr = ioread32(tgpio->membase + TGPIO_IPR); | ||
204 | iowrite32(ipr, tgpio->membase + TGPIO_ICR); | ||
205 | |||
206 | /* | ||
207 | * Some versions of the hardware trash the IER register if more than | ||
208 | * one interrupt is received simultaneously. | ||
209 | */ | ||
210 | iowrite32(0, tgpio->membase + TGPIO_IER); | ||
211 | |||
212 | for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) | ||
213 | generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); | ||
214 | |||
215 | iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); | ||
216 | } | ||
217 | |||
218 | static struct irq_chip timbgpio_irqchip = { | ||
219 | .name = "GPIO", | ||
220 | .irq_enable = timbgpio_irq_enable, | ||
221 | .irq_disable = timbgpio_irq_disable, | ||
222 | .irq_set_type = timbgpio_irq_type, | ||
223 | }; | ||
224 | |||
225 | static int __devinit timbgpio_probe(struct platform_device *pdev) | ||
226 | { | ||
227 | int err, i; | ||
228 | struct gpio_chip *gc; | ||
229 | struct timbgpio *tgpio; | ||
230 | struct resource *iomem; | ||
231 | struct timbgpio_platform_data *pdata = pdev->dev.platform_data; | ||
232 | int irq = platform_get_irq(pdev, 0); | ||
233 | |||
234 | if (!pdata || pdata->nr_pins > 32) { | ||
235 | err = -EINVAL; | ||
236 | goto err_mem; | ||
237 | } | ||
238 | |||
239 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
240 | if (!iomem) { | ||
241 | err = -EINVAL; | ||
242 | goto err_mem; | ||
243 | } | ||
244 | |||
245 | tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL); | ||
246 | if (!tgpio) { | ||
247 | err = -EINVAL; | ||
248 | goto err_mem; | ||
249 | } | ||
250 | tgpio->irq_base = pdata->irq_base; | ||
251 | |||
252 | spin_lock_init(&tgpio->lock); | ||
253 | |||
254 | if (!request_mem_region(iomem->start, resource_size(iomem), | ||
255 | DRIVER_NAME)) { | ||
256 | err = -EBUSY; | ||
257 | goto err_request; | ||
258 | } | ||
259 | |||
260 | tgpio->membase = ioremap(iomem->start, resource_size(iomem)); | ||
261 | if (!tgpio->membase) { | ||
262 | err = -ENOMEM; | ||
263 | goto err_ioremap; | ||
264 | } | ||
265 | |||
266 | gc = &tgpio->gpio; | ||
267 | |||
268 | gc->label = dev_name(&pdev->dev); | ||
269 | gc->owner = THIS_MODULE; | ||
270 | gc->dev = &pdev->dev; | ||
271 | gc->direction_input = timbgpio_gpio_direction_input; | ||
272 | gc->get = timbgpio_gpio_get; | ||
273 | gc->direction_output = timbgpio_gpio_direction_output; | ||
274 | gc->set = timbgpio_gpio_set; | ||
275 | gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL; | ||
276 | gc->dbg_show = NULL; | ||
277 | gc->base = pdata->gpio_base; | ||
278 | gc->ngpio = pdata->nr_pins; | ||
279 | gc->can_sleep = 0; | ||
280 | |||
281 | err = gpiochip_add(gc); | ||
282 | if (err) | ||
283 | goto err_chipadd; | ||
284 | |||
285 | platform_set_drvdata(pdev, tgpio); | ||
286 | |||
287 | /* make sure to disable interrupts */ | ||
288 | iowrite32(0x0, tgpio->membase + TGPIO_IER); | ||
289 | |||
290 | if (irq < 0 || tgpio->irq_base <= 0) | ||
291 | return 0; | ||
292 | |||
293 | for (i = 0; i < pdata->nr_pins; i++) { | ||
294 | irq_set_chip_and_handler_name(tgpio->irq_base + i, | ||
295 | &timbgpio_irqchip, handle_simple_irq, "mux"); | ||
296 | irq_set_chip_data(tgpio->irq_base + i, tgpio); | ||
297 | #ifdef CONFIG_ARM | ||
298 | set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); | ||
299 | #endif | ||
300 | } | ||
301 | |||
302 | irq_set_handler_data(irq, tgpio); | ||
303 | irq_set_chained_handler(irq, timbgpio_irq); | ||
304 | |||
305 | return 0; | ||
306 | |||
307 | err_chipadd: | ||
308 | iounmap(tgpio->membase); | ||
309 | err_ioremap: | ||
310 | release_mem_region(iomem->start, resource_size(iomem)); | ||
311 | err_request: | ||
312 | kfree(tgpio); | ||
313 | err_mem: | ||
314 | printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err); | ||
315 | |||
316 | return err; | ||
317 | } | ||
318 | |||
319 | static int __devexit timbgpio_remove(struct platform_device *pdev) | ||
320 | { | ||
321 | int err; | ||
322 | struct timbgpio_platform_data *pdata = pdev->dev.platform_data; | ||
323 | struct timbgpio *tgpio = platform_get_drvdata(pdev); | ||
324 | struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
325 | int irq = platform_get_irq(pdev, 0); | ||
326 | |||
327 | if (irq >= 0 && tgpio->irq_base > 0) { | ||
328 | int i; | ||
329 | for (i = 0; i < pdata->nr_pins; i++) { | ||
330 | irq_set_chip(tgpio->irq_base + i, NULL); | ||
331 | irq_set_chip_data(tgpio->irq_base + i, NULL); | ||
332 | } | ||
333 | |||
334 | irq_set_handler(irq, NULL); | ||
335 | irq_set_handler_data(irq, NULL); | ||
336 | } | ||
337 | |||
338 | err = gpiochip_remove(&tgpio->gpio); | ||
339 | if (err) | ||
340 | printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n"); | ||
341 | |||
342 | iounmap(tgpio->membase); | ||
343 | release_mem_region(iomem->start, resource_size(iomem)); | ||
344 | kfree(tgpio); | ||
345 | |||
346 | platform_set_drvdata(pdev, NULL); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static struct platform_driver timbgpio_platform_driver = { | ||
352 | .driver = { | ||
353 | .name = DRIVER_NAME, | ||
354 | .owner = THIS_MODULE, | ||
355 | }, | ||
356 | .probe = timbgpio_probe, | ||
357 | .remove = timbgpio_remove, | ||
358 | }; | ||
359 | |||
360 | /*--------------------------------------------------------------------------*/ | ||
361 | |||
362 | static int __init timbgpio_init(void) | ||
363 | { | ||
364 | return platform_driver_register(&timbgpio_platform_driver); | ||
365 | } | ||
366 | |||
367 | static void __exit timbgpio_exit(void) | ||
368 | { | ||
369 | platform_driver_unregister(&timbgpio_platform_driver); | ||
370 | } | ||
371 | |||
372 | module_init(timbgpio_init); | ||
373 | module_exit(timbgpio_exit); | ||
374 | |||
375 | MODULE_DESCRIPTION("Timberdale GPIO driver"); | ||
376 | MODULE_LICENSE("GPL v2"); | ||
377 | MODULE_AUTHOR("Mocean Laboratories"); | ||
378 | MODULE_ALIAS("platform:"DRIVER_NAME); | ||
379 | |||