diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 17:50:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 17:50:57 -0400 |
commit | c7c8518498e82591d7784452f5674c3aeb4d079c (patch) | |
tree | 790ff7e6b6741daf32ec686b9a302b957b07c0f4 /arch/arm/mach-ep93xx | |
parent | ece236ce2fad9c27a6fd2530f899289025194bce (diff) | |
parent | 591567a5ea25852f20b7ef2953f6f72020121199 (diff) |
Merge branch 'gpio/next' of git://git.secretlab.ca/git/linux-2.6
* 'gpio/next' of git://git.secretlab.ca/git/linux-2.6: (61 commits)
gpio/mxc/mxs: fix build error introduced by the irq_gc_ack() renaming
mcp23s08: add i2c support
mcp23s08: isolate spi specific parts
mcp23s08: get rid of setup/teardown callbacks
gpio/tegra: dt: add binding for gpio polarity
mcp23s08: remove unused work queue
gpio/da9052: remove a redundant assignment for gpio->da9052
gpio/mxc: add device tree probe support
ARM: mxc: use ARCH_NR_GPIOS to define gpio number
gpio/mxc: get rid of the uses of cpu_is_mx()
gpio/mxc: add missing initialization of basic_mmio_gpio shadow variables
gpio: Move mpc5200 gpio driver to drivers/gpio
GPIO: DA9052 GPIO module v3
gpio/tegra: Use engineering names in DT compatible property
of/gpio: Add new method for getting gpios under different property names
gpio/dt: Refine GPIO device tree binding
gpio/ml-ioh: fix off-by-one for displaying variable i in dev_err
gpio/pca953x: Deprecate meaningless device-tree bindings
gpio/pca953x: Remove dynamic platform data pointer
gpio/pca953x: Fix IRQ support.
...
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r-- | arch/arm/mach-ep93xx/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/core.c | 27 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/gpio.c | 410 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 1 |
4 files changed, 22 insertions, 418 deletions
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index 33ee2c863d1..6b7c41d155d 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | obj-y := core.o clock.o dma-m2p.o gpio.o | 4 | obj-y := core.o clock.o dma-m2p.o |
5 | obj-m := | 5 | obj-m := |
6 | obj-n := | 6 | obj-n := |
7 | obj- := | 7 | obj- := |
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 6659a0d137a..c488e4bd61e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
@@ -174,14 +174,10 @@ struct sys_timer ep93xx_timer = { | |||
174 | /************************************************************************* | 174 | /************************************************************************* |
175 | * EP93xx IRQ handling | 175 | * EP93xx IRQ handling |
176 | *************************************************************************/ | 176 | *************************************************************************/ |
177 | extern void ep93xx_gpio_init_irq(void); | ||
178 | |||
179 | void __init ep93xx_init_irq(void) | 177 | void __init ep93xx_init_irq(void) |
180 | { | 178 | { |
181 | vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); | 179 | vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); |
182 | vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); | 180 | vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); |
183 | |||
184 | ep93xx_gpio_init_irq(); | ||
185 | } | 181 | } |
186 | 182 | ||
187 | 183 | ||
@@ -241,6 +237,24 @@ unsigned int ep93xx_chip_revision(void) | |||
241 | } | 237 | } |
242 | 238 | ||
243 | /************************************************************************* | 239 | /************************************************************************* |
240 | * EP93xx GPIO | ||
241 | *************************************************************************/ | ||
242 | static struct resource ep93xx_gpio_resource[] = { | ||
243 | { | ||
244 | .start = EP93XX_GPIO_PHYS_BASE, | ||
245 | .end = EP93XX_GPIO_PHYS_BASE + 0xcc - 1, | ||
246 | .flags = IORESOURCE_MEM, | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | static struct platform_device ep93xx_gpio_device = { | ||
251 | .name = "gpio-ep93xx", | ||
252 | .id = -1, | ||
253 | .num_resources = ARRAY_SIZE(ep93xx_gpio_resource), | ||
254 | .resource = ep93xx_gpio_resource, | ||
255 | }; | ||
256 | |||
257 | /************************************************************************* | ||
244 | * EP93xx peripheral handling | 258 | * EP93xx peripheral handling |
245 | *************************************************************************/ | 259 | *************************************************************************/ |
246 | #define EP93XX_UART_MCR_OFFSET (0x0100) | 260 | #define EP93XX_UART_MCR_OFFSET (0x0100) |
@@ -870,14 +884,13 @@ void __init ep93xx_register_ac97(void) | |||
870 | platform_device_register(&ep93xx_pcm_device); | 884 | platform_device_register(&ep93xx_pcm_device); |
871 | } | 885 | } |
872 | 886 | ||
873 | extern void ep93xx_gpio_init(void); | ||
874 | |||
875 | void __init ep93xx_init_devices(void) | 887 | void __init ep93xx_init_devices(void) |
876 | { | 888 | { |
877 | /* Disallow access to MaverickCrunch initially */ | 889 | /* Disallow access to MaverickCrunch initially */ |
878 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); | 890 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); |
879 | 891 | ||
880 | ep93xx_gpio_init(); | 892 | /* Get the GPIO working early, other devices need it */ |
893 | platform_device_register(&ep93xx_gpio_device); | ||
881 | 894 | ||
882 | amba_device_register(&uart1_device, &iomem_resource); | 895 | amba_device_register(&uart1_device, &iomem_resource); |
883 | amba_device_register(&uart2_device, &iomem_resource); | 896 | amba_device_register(&uart2_device, &iomem_resource); |
diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c deleted file mode 100644 index 415dce37b88..00000000000 --- a/arch/arm/mach-ep93xx/gpio.c +++ /dev/null | |||
@@ -1,410 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-ep93xx/gpio.c | ||
3 | * | ||
4 | * Generic EP93xx GPIO handling | ||
5 | * | ||
6 | * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com> | ||
7 | * | ||
8 | * Based on code originally from: | ||
9 | * linux/arch/arm/mach-ep93xx/core.c | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/seq_file.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/irq.h> | ||
24 | |||
25 | #include <mach/hardware.h> | ||
26 | |||
27 | /************************************************************************* | ||
28 | * Interrupt handling for EP93xx on-chip GPIOs | ||
29 | *************************************************************************/ | ||
30 | static unsigned char gpio_int_unmasked[3]; | ||
31 | static unsigned char gpio_int_enabled[3]; | ||
32 | static unsigned char gpio_int_type1[3]; | ||
33 | static unsigned char gpio_int_type2[3]; | ||
34 | static unsigned char gpio_int_debounce[3]; | ||
35 | |||
36 | /* Port ordering is: A B F */ | ||
37 | static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c }; | ||
38 | static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 }; | ||
39 | static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 }; | ||
40 | static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 }; | ||
41 | static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 }; | ||
42 | |||
43 | static void ep93xx_gpio_update_int_params(unsigned port) | ||
44 | { | ||
45 | BUG_ON(port > 2); | ||
46 | |||
47 | __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); | ||
48 | |||
49 | __raw_writeb(gpio_int_type2[port], | ||
50 | EP93XX_GPIO_REG(int_type2_register_offset[port])); | ||
51 | |||
52 | __raw_writeb(gpio_int_type1[port], | ||
53 | EP93XX_GPIO_REG(int_type1_register_offset[port])); | ||
54 | |||
55 | __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], | ||
56 | EP93XX_GPIO_REG(int_en_register_offset[port])); | ||
57 | } | ||
58 | |||
59 | static inline void ep93xx_gpio_int_mask(unsigned line) | ||
60 | { | ||
61 | gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); | ||
62 | } | ||
63 | |||
64 | static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable) | ||
65 | { | ||
66 | int line = irq_to_gpio(irq); | ||
67 | int port = line >> 3; | ||
68 | int port_mask = 1 << (line & 7); | ||
69 | |||
70 | if (enable) | ||
71 | gpio_int_debounce[port] |= port_mask; | ||
72 | else | ||
73 | gpio_int_debounce[port] &= ~port_mask; | ||
74 | |||
75 | __raw_writeb(gpio_int_debounce[port], | ||
76 | EP93XX_GPIO_REG(int_debounce_register_offset[port])); | ||
77 | } | ||
78 | |||
79 | static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
80 | { | ||
81 | unsigned char status; | ||
82 | int i; | ||
83 | |||
84 | status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); | ||
85 | for (i = 0; i < 8; i++) { | ||
86 | if (status & (1 << i)) { | ||
87 | int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; | ||
88 | generic_handle_irq(gpio_irq); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); | ||
93 | for (i = 0; i < 8; i++) { | ||
94 | if (status & (1 << i)) { | ||
95 | int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; | ||
96 | generic_handle_irq(gpio_irq); | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
102 | { | ||
103 | /* | ||
104 | * map discontiguous hw irq range to continuous sw irq range: | ||
105 | * | ||
106 | * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) | ||
107 | */ | ||
108 | int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ | ||
109 | int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; | ||
110 | |||
111 | generic_handle_irq(gpio_irq); | ||
112 | } | ||
113 | |||
114 | static void ep93xx_gpio_irq_ack(struct irq_data *d) | ||
115 | { | ||
116 | int line = irq_to_gpio(d->irq); | ||
117 | int port = line >> 3; | ||
118 | int port_mask = 1 << (line & 7); | ||
119 | |||
120 | if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { | ||
121 | gpio_int_type2[port] ^= port_mask; /* switch edge direction */ | ||
122 | ep93xx_gpio_update_int_params(port); | ||
123 | } | ||
124 | |||
125 | __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); | ||
126 | } | ||
127 | |||
128 | static void ep93xx_gpio_irq_mask_ack(struct irq_data *d) | ||
129 | { | ||
130 | int line = irq_to_gpio(d->irq); | ||
131 | int port = line >> 3; | ||
132 | int port_mask = 1 << (line & 7); | ||
133 | |||
134 | if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) | ||
135 | gpio_int_type2[port] ^= port_mask; /* switch edge direction */ | ||
136 | |||
137 | gpio_int_unmasked[port] &= ~port_mask; | ||
138 | ep93xx_gpio_update_int_params(port); | ||
139 | |||
140 | __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); | ||
141 | } | ||
142 | |||
143 | static void ep93xx_gpio_irq_mask(struct irq_data *d) | ||
144 | { | ||
145 | int line = irq_to_gpio(d->irq); | ||
146 | int port = line >> 3; | ||
147 | |||
148 | gpio_int_unmasked[port] &= ~(1 << (line & 7)); | ||
149 | ep93xx_gpio_update_int_params(port); | ||
150 | } | ||
151 | |||
152 | static void ep93xx_gpio_irq_unmask(struct irq_data *d) | ||
153 | { | ||
154 | int line = irq_to_gpio(d->irq); | ||
155 | int port = line >> 3; | ||
156 | |||
157 | gpio_int_unmasked[port] |= 1 << (line & 7); | ||
158 | ep93xx_gpio_update_int_params(port); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * gpio_int_type1 controls whether the interrupt is level (0) or | ||
163 | * edge (1) triggered, while gpio_int_type2 controls whether it | ||
164 | * triggers on low/falling (0) or high/rising (1). | ||
165 | */ | ||
166 | static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type) | ||
167 | { | ||
168 | const int gpio = irq_to_gpio(d->irq); | ||
169 | const int port = gpio >> 3; | ||
170 | const int port_mask = 1 << (gpio & 7); | ||
171 | irq_flow_handler_t handler; | ||
172 | |||
173 | gpio_direction_input(gpio); | ||
174 | |||
175 | switch (type) { | ||
176 | case IRQ_TYPE_EDGE_RISING: | ||
177 | gpio_int_type1[port] |= port_mask; | ||
178 | gpio_int_type2[port] |= port_mask; | ||
179 | handler = handle_edge_irq; | ||
180 | break; | ||
181 | case IRQ_TYPE_EDGE_FALLING: | ||
182 | gpio_int_type1[port] |= port_mask; | ||
183 | gpio_int_type2[port] &= ~port_mask; | ||
184 | handler = handle_edge_irq; | ||
185 | break; | ||
186 | case IRQ_TYPE_LEVEL_HIGH: | ||
187 | gpio_int_type1[port] &= ~port_mask; | ||
188 | gpio_int_type2[port] |= port_mask; | ||
189 | handler = handle_level_irq; | ||
190 | break; | ||
191 | case IRQ_TYPE_LEVEL_LOW: | ||
192 | gpio_int_type1[port] &= ~port_mask; | ||
193 | gpio_int_type2[port] &= ~port_mask; | ||
194 | handler = handle_level_irq; | ||
195 | break; | ||
196 | case IRQ_TYPE_EDGE_BOTH: | ||
197 | gpio_int_type1[port] |= port_mask; | ||
198 | /* set initial polarity based on current input level */ | ||
199 | if (gpio_get_value(gpio)) | ||
200 | gpio_int_type2[port] &= ~port_mask; /* falling */ | ||
201 | else | ||
202 | gpio_int_type2[port] |= port_mask; /* rising */ | ||
203 | handler = handle_edge_irq; | ||
204 | break; | ||
205 | default: | ||
206 | pr_err("failed to set irq type %d for gpio %d\n", type, gpio); | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | |||
210 | __irq_set_handler_locked(d->irq, handler); | ||
211 | |||
212 | gpio_int_enabled[port] |= port_mask; | ||
213 | |||
214 | ep93xx_gpio_update_int_params(port); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static struct irq_chip ep93xx_gpio_irq_chip = { | ||
220 | .name = "GPIO", | ||
221 | .irq_ack = ep93xx_gpio_irq_ack, | ||
222 | .irq_mask_ack = ep93xx_gpio_irq_mask_ack, | ||
223 | .irq_mask = ep93xx_gpio_irq_mask, | ||
224 | .irq_unmask = ep93xx_gpio_irq_unmask, | ||
225 | .irq_set_type = ep93xx_gpio_irq_type, | ||
226 | }; | ||
227 | |||
228 | void __init ep93xx_gpio_init_irq(void) | ||
229 | { | ||
230 | int gpio_irq; | ||
231 | |||
232 | for (gpio_irq = gpio_to_irq(0); | ||
233 | gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { | ||
234 | irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip, | ||
235 | handle_level_irq); | ||
236 | set_irq_flags(gpio_irq, IRQF_VALID); | ||
237 | } | ||
238 | |||
239 | irq_set_chained_handler(IRQ_EP93XX_GPIO_AB, | ||
240 | ep93xx_gpio_ab_irq_handler); | ||
241 | irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX, | ||
242 | ep93xx_gpio_f_irq_handler); | ||
243 | irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX, | ||
244 | ep93xx_gpio_f_irq_handler); | ||
245 | irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX, | ||
246 | ep93xx_gpio_f_irq_handler); | ||
247 | irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX, | ||
248 | ep93xx_gpio_f_irq_handler); | ||
249 | irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX, | ||
250 | ep93xx_gpio_f_irq_handler); | ||
251 | irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX, | ||
252 | ep93xx_gpio_f_irq_handler); | ||
253 | irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX, | ||
254 | ep93xx_gpio_f_irq_handler); | ||
255 | irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX, | ||
256 | ep93xx_gpio_f_irq_handler); | ||
257 | } | ||
258 | |||
259 | |||
260 | /************************************************************************* | ||
261 | * gpiolib interface for EP93xx on-chip GPIOs | ||
262 | *************************************************************************/ | ||
263 | struct ep93xx_gpio_chip { | ||
264 | struct gpio_chip chip; | ||
265 | |||
266 | void __iomem *data_reg; | ||
267 | void __iomem *data_dir_reg; | ||
268 | }; | ||
269 | |||
270 | #define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip) | ||
271 | |||
272 | static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
273 | { | ||
274 | struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); | ||
275 | unsigned long flags; | ||
276 | u8 v; | ||
277 | |||
278 | local_irq_save(flags); | ||
279 | v = __raw_readb(ep93xx_chip->data_dir_reg); | ||
280 | v &= ~(1 << offset); | ||
281 | __raw_writeb(v, ep93xx_chip->data_dir_reg); | ||
282 | local_irq_restore(flags); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static int ep93xx_gpio_direction_output(struct gpio_chip *chip, | ||
288 | unsigned offset, int val) | ||
289 | { | ||
290 | struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); | ||
291 | unsigned long flags; | ||
292 | int line; | ||
293 | u8 v; | ||
294 | |||
295 | local_irq_save(flags); | ||
296 | |||
297 | /* Set the value */ | ||
298 | v = __raw_readb(ep93xx_chip->data_reg); | ||
299 | if (val) | ||
300 | v |= (1 << offset); | ||
301 | else | ||
302 | v &= ~(1 << offset); | ||
303 | __raw_writeb(v, ep93xx_chip->data_reg); | ||
304 | |||
305 | /* Drive as an output */ | ||
306 | line = chip->base + offset; | ||
307 | if (line <= EP93XX_GPIO_LINE_MAX_IRQ) { | ||
308 | /* Ports A/B/F */ | ||
309 | ep93xx_gpio_int_mask(line); | ||
310 | ep93xx_gpio_update_int_params(line >> 3); | ||
311 | } | ||
312 | |||
313 | v = __raw_readb(ep93xx_chip->data_dir_reg); | ||
314 | v |= (1 << offset); | ||
315 | __raw_writeb(v, ep93xx_chip->data_dir_reg); | ||
316 | |||
317 | local_irq_restore(flags); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
323 | { | ||
324 | struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); | ||
325 | |||
326 | return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset)); | ||
327 | } | ||
328 | |||
329 | static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
330 | { | ||
331 | struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); | ||
332 | unsigned long flags; | ||
333 | u8 v; | ||
334 | |||
335 | local_irq_save(flags); | ||
336 | v = __raw_readb(ep93xx_chip->data_reg); | ||
337 | if (val) | ||
338 | v |= (1 << offset); | ||
339 | else | ||
340 | v &= ~(1 << offset); | ||
341 | __raw_writeb(v, ep93xx_chip->data_reg); | ||
342 | local_irq_restore(flags); | ||
343 | } | ||
344 | |||
345 | static int ep93xx_gpio_set_debounce(struct gpio_chip *chip, | ||
346 | unsigned offset, unsigned debounce) | ||
347 | { | ||
348 | int gpio = chip->base + offset; | ||
349 | int irq = gpio_to_irq(gpio); | ||
350 | |||
351 | if (irq < 0) | ||
352 | return -EINVAL; | ||
353 | |||
354 | ep93xx_gpio_int_debounce(irq, debounce ? true : false); | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | #define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \ | ||
360 | { \ | ||
361 | .chip = { \ | ||
362 | .label = name, \ | ||
363 | .direction_input = ep93xx_gpio_direction_input, \ | ||
364 | .direction_output = ep93xx_gpio_direction_output, \ | ||
365 | .get = ep93xx_gpio_get, \ | ||
366 | .set = ep93xx_gpio_set, \ | ||
367 | .base = base_gpio, \ | ||
368 | .ngpio = 8, \ | ||
369 | }, \ | ||
370 | .data_reg = EP93XX_GPIO_REG(dr), \ | ||
371 | .data_dir_reg = EP93XX_GPIO_REG(ddr), \ | ||
372 | } | ||
373 | |||
374 | static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = { | ||
375 | EP93XX_GPIO_BANK("A", 0x00, 0x10, 0), | ||
376 | EP93XX_GPIO_BANK("B", 0x04, 0x14, 8), | ||
377 | EP93XX_GPIO_BANK("C", 0x08, 0x18, 40), | ||
378 | EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24), | ||
379 | EP93XX_GPIO_BANK("E", 0x20, 0x24, 32), | ||
380 | EP93XX_GPIO_BANK("F", 0x30, 0x34, 16), | ||
381 | EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48), | ||
382 | EP93XX_GPIO_BANK("H", 0x40, 0x44, 56), | ||
383 | }; | ||
384 | |||
385 | void __init ep93xx_gpio_init(void) | ||
386 | { | ||
387 | int i; | ||
388 | |||
389 | /* Set Ports C, D, E, G, and H for GPIO use */ | ||
390 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | | ||
391 | EP93XX_SYSCON_DEVCFG_GONK | | ||
392 | EP93XX_SYSCON_DEVCFG_EONIDE | | ||
393 | EP93XX_SYSCON_DEVCFG_GONIDE | | ||
394 | EP93XX_SYSCON_DEVCFG_HONIDE); | ||
395 | |||
396 | for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) { | ||
397 | struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip; | ||
398 | |||
399 | /* | ||
400 | * Ports A, B, and F support input debouncing when | ||
401 | * used as interrupts. | ||
402 | */ | ||
403 | if (!strcmp(chip->label, "A") || | ||
404 | !strcmp(chip->label, "B") || | ||
405 | !strcmp(chip->label, "F")) | ||
406 | chip->set_debounce = ep93xx_gpio_set_debounce; | ||
407 | |||
408 | gpiochip_add(chip); | ||
409 | } | ||
410 | } | ||
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 9ac4d105509..c4a7b84ef06 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | |||
@@ -98,6 +98,7 @@ | |||
98 | 98 | ||
99 | #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) | 99 | #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) |
100 | 100 | ||
101 | #define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000) | ||
101 | #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) | 102 | #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) |
102 | #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) | 103 | #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) |
103 | #define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) | 104 | #define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) |