diff options
author | Tony Lindgren <tony@atomide.com> | 2005-07-10 14:58:15 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-07-10 14:58:15 -0400 |
commit | 5e1c5ff4783e0ddd241580c9996390508722190e (patch) | |
tree | 6c0a8a16046936f9046488790f817e0aa5884ac5 /arch/arm/plat-omap/gpio.c | |
parent | b91585560b59fd3ef4e20ca6f7d35aefda193774 (diff) |
[PATCH] ARM: 2812/1: OMAP update 7c/11: Move arch-omap to plat-omap
Patch from Tony Lindgren
This patch move common OMAP code from arch-omap to plat-omap
directory.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-omap/gpio.c')
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 762 |
1 files changed, 762 insertions, 0 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c new file mode 100644 index 000000000000..1c85b4e536c2 --- /dev/null +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -0,0 +1,762 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/gpio.c | ||
3 | * | ||
4 | * Support functions for OMAP GPIO | ||
5 | * | ||
6 | * Copyright (C) 2003 Nokia Corporation | ||
7 | * Written by Juha Yrjölä <juha.yrjola@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/ptrace.h> | ||
20 | |||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/arch/irqs.h> | ||
24 | #include <asm/arch/gpio.h> | ||
25 | #include <asm/mach/irq.h> | ||
26 | |||
27 | #include <asm/io.h> | ||
28 | |||
29 | /* | ||
30 | * OMAP1510 GPIO registers | ||
31 | */ | ||
32 | #define OMAP1510_GPIO_BASE 0xfffce000 | ||
33 | #define OMAP1510_GPIO_DATA_INPUT 0x00 | ||
34 | #define OMAP1510_GPIO_DATA_OUTPUT 0x04 | ||
35 | #define OMAP1510_GPIO_DIR_CONTROL 0x08 | ||
36 | #define OMAP1510_GPIO_INT_CONTROL 0x0c | ||
37 | #define OMAP1510_GPIO_INT_MASK 0x10 | ||
38 | #define OMAP1510_GPIO_INT_STATUS 0x14 | ||
39 | #define OMAP1510_GPIO_PIN_CONTROL 0x18 | ||
40 | |||
41 | #define OMAP1510_IH_GPIO_BASE 64 | ||
42 | |||
43 | /* | ||
44 | * OMAP1610 specific GPIO registers | ||
45 | */ | ||
46 | #define OMAP1610_GPIO1_BASE 0xfffbe400 | ||
47 | #define OMAP1610_GPIO2_BASE 0xfffbec00 | ||
48 | #define OMAP1610_GPIO3_BASE 0xfffbb400 | ||
49 | #define OMAP1610_GPIO4_BASE 0xfffbbc00 | ||
50 | #define OMAP1610_GPIO_REVISION 0x0000 | ||
51 | #define OMAP1610_GPIO_SYSCONFIG 0x0010 | ||
52 | #define OMAP1610_GPIO_SYSSTATUS 0x0014 | ||
53 | #define OMAP1610_GPIO_IRQSTATUS1 0x0018 | ||
54 | #define OMAP1610_GPIO_IRQENABLE1 0x001c | ||
55 | #define OMAP1610_GPIO_DATAIN 0x002c | ||
56 | #define OMAP1610_GPIO_DATAOUT 0x0030 | ||
57 | #define OMAP1610_GPIO_DIRECTION 0x0034 | ||
58 | #define OMAP1610_GPIO_EDGE_CTRL1 0x0038 | ||
59 | #define OMAP1610_GPIO_EDGE_CTRL2 0x003c | ||
60 | #define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c | ||
61 | #define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0 | ||
62 | #define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc | ||
63 | #define OMAP1610_GPIO_SET_DATAOUT 0x00f0 | ||
64 | |||
65 | /* | ||
66 | * OMAP730 specific GPIO registers | ||
67 | */ | ||
68 | #define OMAP730_GPIO1_BASE 0xfffbc000 | ||
69 | #define OMAP730_GPIO2_BASE 0xfffbc800 | ||
70 | #define OMAP730_GPIO3_BASE 0xfffbd000 | ||
71 | #define OMAP730_GPIO4_BASE 0xfffbd800 | ||
72 | #define OMAP730_GPIO5_BASE 0xfffbe000 | ||
73 | #define OMAP730_GPIO6_BASE 0xfffbe800 | ||
74 | #define OMAP730_GPIO_DATA_INPUT 0x00 | ||
75 | #define OMAP730_GPIO_DATA_OUTPUT 0x04 | ||
76 | #define OMAP730_GPIO_DIR_CONTROL 0x08 | ||
77 | #define OMAP730_GPIO_INT_CONTROL 0x0c | ||
78 | #define OMAP730_GPIO_INT_MASK 0x10 | ||
79 | #define OMAP730_GPIO_INT_STATUS 0x14 | ||
80 | |||
81 | #define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff) | ||
82 | |||
83 | struct gpio_bank { | ||
84 | u32 base; | ||
85 | u16 irq; | ||
86 | u16 virtual_irq_start; | ||
87 | u8 method; | ||
88 | u32 reserved_map; | ||
89 | spinlock_t lock; | ||
90 | }; | ||
91 | |||
92 | #define METHOD_MPUIO 0 | ||
93 | #define METHOD_GPIO_1510 1 | ||
94 | #define METHOD_GPIO_1610 2 | ||
95 | #define METHOD_GPIO_730 3 | ||
96 | |||
97 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
98 | static struct gpio_bank gpio_bank_1610[5] = { | ||
99 | { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO}, | ||
100 | { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 }, | ||
101 | { OMAP1610_GPIO2_BASE, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, METHOD_GPIO_1610 }, | ||
102 | { OMAP1610_GPIO3_BASE, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, METHOD_GPIO_1610 }, | ||
103 | { OMAP1610_GPIO4_BASE, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48, METHOD_GPIO_1610 }, | ||
104 | }; | ||
105 | #endif | ||
106 | |||
107 | #ifdef CONFIG_ARCH_OMAP1510 | ||
108 | static struct gpio_bank gpio_bank_1510[2] = { | ||
109 | { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, | ||
110 | { OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1510 } | ||
111 | }; | ||
112 | #endif | ||
113 | |||
114 | #ifdef CONFIG_ARCH_OMAP730 | ||
115 | static struct gpio_bank gpio_bank_730[7] = { | ||
116 | { OMAP_MPUIO_BASE, INT_730_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, | ||
117 | { OMAP730_GPIO1_BASE, INT_730_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 }, | ||
118 | { OMAP730_GPIO2_BASE, INT_730_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_730 }, | ||
119 | { OMAP730_GPIO3_BASE, INT_730_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_730 }, | ||
120 | { OMAP730_GPIO4_BASE, INT_730_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_730 }, | ||
121 | { OMAP730_GPIO5_BASE, INT_730_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_730 }, | ||
122 | { OMAP730_GPIO6_BASE, INT_730_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_730 }, | ||
123 | }; | ||
124 | #endif | ||
125 | |||
126 | static struct gpio_bank *gpio_bank; | ||
127 | static int gpio_bank_count; | ||
128 | |||
129 | static inline struct gpio_bank *get_gpio_bank(int gpio) | ||
130 | { | ||
131 | #ifdef CONFIG_ARCH_OMAP1510 | ||
132 | if (cpu_is_omap1510()) { | ||
133 | if (OMAP_GPIO_IS_MPUIO(gpio)) | ||
134 | return &gpio_bank[0]; | ||
135 | return &gpio_bank[1]; | ||
136 | } | ||
137 | #endif | ||
138 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
139 | if (cpu_is_omap16xx()) { | ||
140 | if (OMAP_GPIO_IS_MPUIO(gpio)) | ||
141 | return &gpio_bank[0]; | ||
142 | return &gpio_bank[1 + (gpio >> 4)]; | ||
143 | } | ||
144 | #endif | ||
145 | #ifdef CONFIG_ARCH_OMAP730 | ||
146 | if (cpu_is_omap730()) { | ||
147 | if (OMAP_GPIO_IS_MPUIO(gpio)) | ||
148 | return &gpio_bank[0]; | ||
149 | return &gpio_bank[1 + (gpio >> 5)]; | ||
150 | } | ||
151 | #endif | ||
152 | } | ||
153 | |||
154 | static inline int get_gpio_index(int gpio) | ||
155 | { | ||
156 | if (cpu_is_omap730()) | ||
157 | return gpio & 0x1f; | ||
158 | else | ||
159 | return gpio & 0x0f; | ||
160 | } | ||
161 | |||
162 | static inline int gpio_valid(int gpio) | ||
163 | { | ||
164 | if (gpio < 0) | ||
165 | return -1; | ||
166 | if (OMAP_GPIO_IS_MPUIO(gpio)) { | ||
167 | if ((gpio & OMAP_MPUIO_MASK) > 16) | ||
168 | return -1; | ||
169 | return 0; | ||
170 | } | ||
171 | #ifdef CONFIG_ARCH_OMAP1510 | ||
172 | if (cpu_is_omap1510() && gpio < 16) | ||
173 | return 0; | ||
174 | #endif | ||
175 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
176 | if ((cpu_is_omap16xx()) && gpio < 64) | ||
177 | return 0; | ||
178 | #endif | ||
179 | #ifdef CONFIG_ARCH_OMAP730 | ||
180 | if (cpu_is_omap730() && gpio < 192) | ||
181 | return 0; | ||
182 | #endif | ||
183 | return -1; | ||
184 | } | ||
185 | |||
186 | static int check_gpio(int gpio) | ||
187 | { | ||
188 | if (unlikely(gpio_valid(gpio)) < 0) { | ||
189 | printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio); | ||
190 | dump_stack(); | ||
191 | return -1; | ||
192 | } | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) | ||
197 | { | ||
198 | u32 reg = bank->base; | ||
199 | u32 l; | ||
200 | |||
201 | switch (bank->method) { | ||
202 | case METHOD_MPUIO: | ||
203 | reg += OMAP_MPUIO_IO_CNTL; | ||
204 | break; | ||
205 | case METHOD_GPIO_1510: | ||
206 | reg += OMAP1510_GPIO_DIR_CONTROL; | ||
207 | break; | ||
208 | case METHOD_GPIO_1610: | ||
209 | reg += OMAP1610_GPIO_DIRECTION; | ||
210 | break; | ||
211 | case METHOD_GPIO_730: | ||
212 | reg += OMAP730_GPIO_DIR_CONTROL; | ||
213 | break; | ||
214 | } | ||
215 | l = __raw_readl(reg); | ||
216 | if (is_input) | ||
217 | l |= 1 << gpio; | ||
218 | else | ||
219 | l &= ~(1 << gpio); | ||
220 | __raw_writel(l, reg); | ||
221 | } | ||
222 | |||
223 | void omap_set_gpio_direction(int gpio, int is_input) | ||
224 | { | ||
225 | struct gpio_bank *bank; | ||
226 | |||
227 | if (check_gpio(gpio) < 0) | ||
228 | return; | ||
229 | bank = get_gpio_bank(gpio); | ||
230 | spin_lock(&bank->lock); | ||
231 | _set_gpio_direction(bank, get_gpio_index(gpio), is_input); | ||
232 | spin_unlock(&bank->lock); | ||
233 | } | ||
234 | |||
235 | static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) | ||
236 | { | ||
237 | u32 reg = bank->base; | ||
238 | u32 l = 0; | ||
239 | |||
240 | switch (bank->method) { | ||
241 | case METHOD_MPUIO: | ||
242 | reg += OMAP_MPUIO_OUTPUT; | ||
243 | l = __raw_readl(reg); | ||
244 | if (enable) | ||
245 | l |= 1 << gpio; | ||
246 | else | ||
247 | l &= ~(1 << gpio); | ||
248 | break; | ||
249 | case METHOD_GPIO_1510: | ||
250 | reg += OMAP1510_GPIO_DATA_OUTPUT; | ||
251 | l = __raw_readl(reg); | ||
252 | if (enable) | ||
253 | l |= 1 << gpio; | ||
254 | else | ||
255 | l &= ~(1 << gpio); | ||
256 | break; | ||
257 | case METHOD_GPIO_1610: | ||
258 | if (enable) | ||
259 | reg += OMAP1610_GPIO_SET_DATAOUT; | ||
260 | else | ||
261 | reg += OMAP1610_GPIO_CLEAR_DATAOUT; | ||
262 | l = 1 << gpio; | ||
263 | break; | ||
264 | case METHOD_GPIO_730: | ||
265 | reg += OMAP730_GPIO_DATA_OUTPUT; | ||
266 | l = __raw_readl(reg); | ||
267 | if (enable) | ||
268 | l |= 1 << gpio; | ||
269 | else | ||
270 | l &= ~(1 << gpio); | ||
271 | break; | ||
272 | default: | ||
273 | BUG(); | ||
274 | return; | ||
275 | } | ||
276 | __raw_writel(l, reg); | ||
277 | } | ||
278 | |||
279 | void omap_set_gpio_dataout(int gpio, int enable) | ||
280 | { | ||
281 | struct gpio_bank *bank; | ||
282 | |||
283 | if (check_gpio(gpio) < 0) | ||
284 | return; | ||
285 | bank = get_gpio_bank(gpio); | ||
286 | spin_lock(&bank->lock); | ||
287 | _set_gpio_dataout(bank, get_gpio_index(gpio), enable); | ||
288 | spin_unlock(&bank->lock); | ||
289 | } | ||
290 | |||
291 | int omap_get_gpio_datain(int gpio) | ||
292 | { | ||
293 | struct gpio_bank *bank; | ||
294 | u32 reg; | ||
295 | |||
296 | if (check_gpio(gpio) < 0) | ||
297 | return -1; | ||
298 | bank = get_gpio_bank(gpio); | ||
299 | reg = bank->base; | ||
300 | switch (bank->method) { | ||
301 | case METHOD_MPUIO: | ||
302 | reg += OMAP_MPUIO_INPUT_LATCH; | ||
303 | break; | ||
304 | case METHOD_GPIO_1510: | ||
305 | reg += OMAP1510_GPIO_DATA_INPUT; | ||
306 | break; | ||
307 | case METHOD_GPIO_1610: | ||
308 | reg += OMAP1610_GPIO_DATAIN; | ||
309 | break; | ||
310 | case METHOD_GPIO_730: | ||
311 | reg += OMAP730_GPIO_DATA_INPUT; | ||
312 | break; | ||
313 | default: | ||
314 | BUG(); | ||
315 | return -1; | ||
316 | } | ||
317 | return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0; | ||
318 | } | ||
319 | |||
320 | static void _set_gpio_edge_ctrl(struct gpio_bank *bank, int gpio, int edge) | ||
321 | { | ||
322 | u32 reg = bank->base; | ||
323 | u32 l; | ||
324 | |||
325 | switch (bank->method) { | ||
326 | case METHOD_MPUIO: | ||
327 | reg += OMAP_MPUIO_GPIO_INT_EDGE; | ||
328 | l = __raw_readl(reg); | ||
329 | if (edge == OMAP_GPIO_RISING_EDGE) | ||
330 | l |= 1 << gpio; | ||
331 | else | ||
332 | l &= ~(1 << gpio); | ||
333 | __raw_writel(l, reg); | ||
334 | break; | ||
335 | case METHOD_GPIO_1510: | ||
336 | reg += OMAP1510_GPIO_INT_CONTROL; | ||
337 | l = __raw_readl(reg); | ||
338 | if (edge == OMAP_GPIO_RISING_EDGE) | ||
339 | l |= 1 << gpio; | ||
340 | else | ||
341 | l &= ~(1 << gpio); | ||
342 | __raw_writel(l, reg); | ||
343 | break; | ||
344 | case METHOD_GPIO_1610: | ||
345 | edge &= 0x03; | ||
346 | if (gpio & 0x08) | ||
347 | reg += OMAP1610_GPIO_EDGE_CTRL2; | ||
348 | else | ||
349 | reg += OMAP1610_GPIO_EDGE_CTRL1; | ||
350 | gpio &= 0x07; | ||
351 | l = __raw_readl(reg); | ||
352 | l &= ~(3 << (gpio << 1)); | ||
353 | l |= edge << (gpio << 1); | ||
354 | __raw_writel(l, reg); | ||
355 | break; | ||
356 | case METHOD_GPIO_730: | ||
357 | reg += OMAP730_GPIO_INT_CONTROL; | ||
358 | l = __raw_readl(reg); | ||
359 | if (edge == OMAP_GPIO_RISING_EDGE) | ||
360 | l |= 1 << gpio; | ||
361 | else | ||
362 | l &= ~(1 << gpio); | ||
363 | __raw_writel(l, reg); | ||
364 | break; | ||
365 | default: | ||
366 | BUG(); | ||
367 | return; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | void omap_set_gpio_edge_ctrl(int gpio, int edge) | ||
372 | { | ||
373 | struct gpio_bank *bank; | ||
374 | |||
375 | if (check_gpio(gpio) < 0) | ||
376 | return; | ||
377 | bank = get_gpio_bank(gpio); | ||
378 | spin_lock(&bank->lock); | ||
379 | _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), edge); | ||
380 | spin_unlock(&bank->lock); | ||
381 | } | ||
382 | |||
383 | |||
384 | static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio) | ||
385 | { | ||
386 | u32 reg = bank->base, l; | ||
387 | |||
388 | switch (bank->method) { | ||
389 | case METHOD_MPUIO: | ||
390 | l = __raw_readl(reg + OMAP_MPUIO_GPIO_INT_EDGE); | ||
391 | return (l & (1 << gpio)) ? | ||
392 | OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE; | ||
393 | case METHOD_GPIO_1510: | ||
394 | l = __raw_readl(reg + OMAP1510_GPIO_INT_CONTROL); | ||
395 | return (l & (1 << gpio)) ? | ||
396 | OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE; | ||
397 | case METHOD_GPIO_1610: | ||
398 | if (gpio & 0x08) | ||
399 | reg += OMAP1610_GPIO_EDGE_CTRL2; | ||
400 | else | ||
401 | reg += OMAP1610_GPIO_EDGE_CTRL1; | ||
402 | return (__raw_readl(reg) >> ((gpio & 0x07) << 1)) & 0x03; | ||
403 | case METHOD_GPIO_730: | ||
404 | l = __raw_readl(reg + OMAP730_GPIO_INT_CONTROL); | ||
405 | return (l & (1 << gpio)) ? | ||
406 | OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE; | ||
407 | default: | ||
408 | BUG(); | ||
409 | return -1; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) | ||
414 | { | ||
415 | u32 reg = bank->base; | ||
416 | |||
417 | switch (bank->method) { | ||
418 | case METHOD_MPUIO: | ||
419 | /* MPUIO irqstatus is reset by reading the status register, | ||
420 | * so do nothing here */ | ||
421 | return; | ||
422 | case METHOD_GPIO_1510: | ||
423 | reg += OMAP1510_GPIO_INT_STATUS; | ||
424 | break; | ||
425 | case METHOD_GPIO_1610: | ||
426 | reg += OMAP1610_GPIO_IRQSTATUS1; | ||
427 | break; | ||
428 | case METHOD_GPIO_730: | ||
429 | reg += OMAP730_GPIO_INT_STATUS; | ||
430 | break; | ||
431 | default: | ||
432 | BUG(); | ||
433 | return; | ||
434 | } | ||
435 | __raw_writel(gpio_mask, reg); | ||
436 | } | ||
437 | |||
438 | static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) | ||
439 | { | ||
440 | _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); | ||
441 | } | ||
442 | |||
443 | static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) | ||
444 | { | ||
445 | u32 reg = bank->base; | ||
446 | u32 l; | ||
447 | |||
448 | switch (bank->method) { | ||
449 | case METHOD_MPUIO: | ||
450 | reg += OMAP_MPUIO_GPIO_MASKIT; | ||
451 | l = __raw_readl(reg); | ||
452 | if (enable) | ||
453 | l &= ~(gpio_mask); | ||
454 | else | ||
455 | l |= gpio_mask; | ||
456 | break; | ||
457 | case METHOD_GPIO_1510: | ||
458 | reg += OMAP1510_GPIO_INT_MASK; | ||
459 | l = __raw_readl(reg); | ||
460 | if (enable) | ||
461 | l &= ~(gpio_mask); | ||
462 | else | ||
463 | l |= gpio_mask; | ||
464 | break; | ||
465 | case METHOD_GPIO_1610: | ||
466 | if (enable) | ||
467 | reg += OMAP1610_GPIO_SET_IRQENABLE1; | ||
468 | else | ||
469 | reg += OMAP1610_GPIO_CLEAR_IRQENABLE1; | ||
470 | l = gpio_mask; | ||
471 | break; | ||
472 | case METHOD_GPIO_730: | ||
473 | reg += OMAP730_GPIO_INT_MASK; | ||
474 | l = __raw_readl(reg); | ||
475 | if (enable) | ||
476 | l &= ~(gpio_mask); | ||
477 | else | ||
478 | l |= gpio_mask; | ||
479 | break; | ||
480 | default: | ||
481 | BUG(); | ||
482 | return; | ||
483 | } | ||
484 | __raw_writel(l, reg); | ||
485 | } | ||
486 | |||
487 | static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) | ||
488 | { | ||
489 | _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable); | ||
490 | } | ||
491 | |||
492 | int omap_request_gpio(int gpio) | ||
493 | { | ||
494 | struct gpio_bank *bank; | ||
495 | |||
496 | if (check_gpio(gpio) < 0) | ||
497 | return -EINVAL; | ||
498 | |||
499 | bank = get_gpio_bank(gpio); | ||
500 | spin_lock(&bank->lock); | ||
501 | if (unlikely(bank->reserved_map & (1 << get_gpio_index(gpio)))) { | ||
502 | printk(KERN_ERR "omap-gpio: GPIO %d is already reserved!\n", gpio); | ||
503 | dump_stack(); | ||
504 | spin_unlock(&bank->lock); | ||
505 | return -1; | ||
506 | } | ||
507 | bank->reserved_map |= (1 << get_gpio_index(gpio)); | ||
508 | #ifdef CONFIG_ARCH_OMAP1510 | ||
509 | if (bank->method == METHOD_GPIO_1510) { | ||
510 | u32 reg; | ||
511 | |||
512 | /* Claim the pin for the ARM */ | ||
513 | reg = bank->base + OMAP1510_GPIO_PIN_CONTROL; | ||
514 | __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg); | ||
515 | } | ||
516 | #endif | ||
517 | spin_unlock(&bank->lock); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | void omap_free_gpio(int gpio) | ||
523 | { | ||
524 | struct gpio_bank *bank; | ||
525 | |||
526 | if (check_gpio(gpio) < 0) | ||
527 | return; | ||
528 | bank = get_gpio_bank(gpio); | ||
529 | spin_lock(&bank->lock); | ||
530 | if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) { | ||
531 | printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); | ||
532 | dump_stack(); | ||
533 | spin_unlock(&bank->lock); | ||
534 | return; | ||
535 | } | ||
536 | bank->reserved_map &= ~(1 << get_gpio_index(gpio)); | ||
537 | _set_gpio_direction(bank, get_gpio_index(gpio), 1); | ||
538 | _set_gpio_irqenable(bank, gpio, 0); | ||
539 | _clear_gpio_irqstatus(bank, gpio); | ||
540 | spin_unlock(&bank->lock); | ||
541 | } | ||
542 | |||
543 | /* | ||
544 | * We need to unmask the GPIO bank interrupt as soon as possible to | ||
545 | * avoid missing GPIO interrupts for other lines in the bank. | ||
546 | * Then we need to mask-read-clear-unmask the triggered GPIO lines | ||
547 | * in the bank to avoid missing nested interrupts for a GPIO line. | ||
548 | * If we wait to unmask individual GPIO lines in the bank after the | ||
549 | * line's interrupt handler has been run, we may miss some nested | ||
550 | * interrupts. | ||
551 | */ | ||
552 | static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | ||
553 | struct pt_regs *regs) | ||
554 | { | ||
555 | u32 isr_reg = 0; | ||
556 | u32 isr; | ||
557 | unsigned int gpio_irq; | ||
558 | struct gpio_bank *bank; | ||
559 | |||
560 | desc->chip->ack(irq); | ||
561 | |||
562 | bank = (struct gpio_bank *) desc->data; | ||
563 | if (bank->method == METHOD_MPUIO) | ||
564 | isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; | ||
565 | #ifdef CONFIG_ARCH_OMAP1510 | ||
566 | if (bank->method == METHOD_GPIO_1510) | ||
567 | isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS; | ||
568 | #endif | ||
569 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
570 | if (bank->method == METHOD_GPIO_1610) | ||
571 | isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1; | ||
572 | #endif | ||
573 | #ifdef CONFIG_ARCH_OMAP730 | ||
574 | if (bank->method == METHOD_GPIO_730) | ||
575 | isr_reg = bank->base + OMAP730_GPIO_INT_STATUS; | ||
576 | #endif | ||
577 | |||
578 | isr = __raw_readl(isr_reg); | ||
579 | _enable_gpio_irqbank(bank, isr, 0); | ||
580 | _clear_gpio_irqbank(bank, isr); | ||
581 | _enable_gpio_irqbank(bank, isr, 1); | ||
582 | desc->chip->unmask(irq); | ||
583 | |||
584 | if (unlikely(!isr)) | ||
585 | return; | ||
586 | |||
587 | gpio_irq = bank->virtual_irq_start; | ||
588 | for (; isr != 0; isr >>= 1, gpio_irq++) { | ||
589 | struct irqdesc *d; | ||
590 | if (!(isr & 1)) | ||
591 | continue; | ||
592 | d = irq_desc + gpio_irq; | ||
593 | d->handle(gpio_irq, d, regs); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | static void gpio_ack_irq(unsigned int irq) | ||
598 | { | ||
599 | unsigned int gpio = irq - IH_GPIO_BASE; | ||
600 | struct gpio_bank *bank = get_gpio_bank(gpio); | ||
601 | |||
602 | _clear_gpio_irqstatus(bank, gpio); | ||
603 | } | ||
604 | |||
605 | static void gpio_mask_irq(unsigned int irq) | ||
606 | { | ||
607 | unsigned int gpio = irq - IH_GPIO_BASE; | ||
608 | struct gpio_bank *bank = get_gpio_bank(gpio); | ||
609 | |||
610 | _set_gpio_irqenable(bank, gpio, 0); | ||
611 | } | ||
612 | |||
613 | static void gpio_unmask_irq(unsigned int irq) | ||
614 | { | ||
615 | unsigned int gpio = irq - IH_GPIO_BASE; | ||
616 | struct gpio_bank *bank = get_gpio_bank(gpio); | ||
617 | |||
618 | if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) { | ||
619 | printk(KERN_ERR "OMAP GPIO %d: trying to enable GPIO IRQ while no edge is set\n", | ||
620 | gpio); | ||
621 | _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE); | ||
622 | } | ||
623 | _set_gpio_irqenable(bank, gpio, 1); | ||
624 | } | ||
625 | |||
626 | static void mpuio_ack_irq(unsigned int irq) | ||
627 | { | ||
628 | /* The ISR is reset automatically, so do nothing here. */ | ||
629 | } | ||
630 | |||
631 | static void mpuio_mask_irq(unsigned int irq) | ||
632 | { | ||
633 | unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); | ||
634 | struct gpio_bank *bank = get_gpio_bank(gpio); | ||
635 | |||
636 | _set_gpio_irqenable(bank, gpio, 0); | ||
637 | } | ||
638 | |||
639 | static void mpuio_unmask_irq(unsigned int irq) | ||
640 | { | ||
641 | unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); | ||
642 | struct gpio_bank *bank = get_gpio_bank(gpio); | ||
643 | |||
644 | _set_gpio_irqenable(bank, gpio, 1); | ||
645 | } | ||
646 | |||
647 | static struct irqchip gpio_irq_chip = { | ||
648 | .ack = gpio_ack_irq, | ||
649 | .mask = gpio_mask_irq, | ||
650 | .unmask = gpio_unmask_irq, | ||
651 | }; | ||
652 | |||
653 | static struct irqchip mpuio_irq_chip = { | ||
654 | .ack = mpuio_ack_irq, | ||
655 | .mask = mpuio_mask_irq, | ||
656 | .unmask = mpuio_unmask_irq | ||
657 | }; | ||
658 | |||
659 | static int initialized = 0; | ||
660 | |||
661 | static int __init _omap_gpio_init(void) | ||
662 | { | ||
663 | int i; | ||
664 | struct gpio_bank *bank; | ||
665 | |||
666 | initialized = 1; | ||
667 | |||
668 | #ifdef CONFIG_ARCH_OMAP1510 | ||
669 | if (cpu_is_omap1510()) { | ||
670 | printk(KERN_INFO "OMAP1510 GPIO hardware\n"); | ||
671 | gpio_bank_count = 2; | ||
672 | gpio_bank = gpio_bank_1510; | ||
673 | } | ||
674 | #endif | ||
675 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
676 | if (cpu_is_omap16xx()) { | ||
677 | int rev; | ||
678 | |||
679 | gpio_bank_count = 5; | ||
680 | gpio_bank = gpio_bank_1610; | ||
681 | rev = omap_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION); | ||
682 | printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n", | ||
683 | (rev >> 4) & 0x0f, rev & 0x0f); | ||
684 | } | ||
685 | #endif | ||
686 | #ifdef CONFIG_ARCH_OMAP730 | ||
687 | if (cpu_is_omap730()) { | ||
688 | printk(KERN_INFO "OMAP730 GPIO hardware\n"); | ||
689 | gpio_bank_count = 7; | ||
690 | gpio_bank = gpio_bank_730; | ||
691 | } | ||
692 | #endif | ||
693 | for (i = 0; i < gpio_bank_count; i++) { | ||
694 | int j, gpio_count = 16; | ||
695 | |||
696 | bank = &gpio_bank[i]; | ||
697 | bank->reserved_map = 0; | ||
698 | bank->base = IO_ADDRESS(bank->base); | ||
699 | spin_lock_init(&bank->lock); | ||
700 | if (bank->method == METHOD_MPUIO) { | ||
701 | omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT); | ||
702 | } | ||
703 | #ifdef CONFIG_ARCH_OMAP1510 | ||
704 | if (bank->method == METHOD_GPIO_1510) { | ||
705 | __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK); | ||
706 | __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS); | ||
707 | } | ||
708 | #endif | ||
709 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
710 | if (bank->method == METHOD_GPIO_1610) { | ||
711 | __raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1); | ||
712 | __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1); | ||
713 | } | ||
714 | #endif | ||
715 | #ifdef CONFIG_ARCH_OMAP730 | ||
716 | if (bank->method == METHOD_GPIO_730) { | ||
717 | __raw_writel(0xffffffff, bank->base + OMAP730_GPIO_INT_MASK); | ||
718 | __raw_writel(0x00000000, bank->base + OMAP730_GPIO_INT_STATUS); | ||
719 | |||
720 | gpio_count = 32; /* 730 has 32-bit GPIOs */ | ||
721 | } | ||
722 | #endif | ||
723 | for (j = bank->virtual_irq_start; | ||
724 | j < bank->virtual_irq_start + gpio_count; j++) { | ||
725 | if (bank->method == METHOD_MPUIO) | ||
726 | set_irq_chip(j, &mpuio_irq_chip); | ||
727 | else | ||
728 | set_irq_chip(j, &gpio_irq_chip); | ||
729 | set_irq_handler(j, do_simple_IRQ); | ||
730 | set_irq_flags(j, IRQF_VALID); | ||
731 | } | ||
732 | set_irq_chained_handler(bank->irq, gpio_irq_handler); | ||
733 | set_irq_data(bank->irq, bank); | ||
734 | } | ||
735 | |||
736 | /* Enable system clock for GPIO module. | ||
737 | * The CAM_CLK_CTRL *is* really the right place. */ | ||
738 | if (cpu_is_omap1610() || cpu_is_omap1710()) | ||
739 | omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL); | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * This may get called early from board specific init | ||
746 | */ | ||
747 | int omap_gpio_init(void) | ||
748 | { | ||
749 | if (!initialized) | ||
750 | return _omap_gpio_init(); | ||
751 | else | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | EXPORT_SYMBOL(omap_request_gpio); | ||
756 | EXPORT_SYMBOL(omap_free_gpio); | ||
757 | EXPORT_SYMBOL(omap_set_gpio_direction); | ||
758 | EXPORT_SYMBOL(omap_set_gpio_dataout); | ||
759 | EXPORT_SYMBOL(omap_get_gpio_datain); | ||
760 | EXPORT_SYMBOL(omap_set_gpio_edge_ctrl); | ||
761 | |||
762 | arch_initcall(omap_gpio_init); | ||