Commit 4932e397be71370b95f555f87d3b424d2b5ca57b
Committed by
Russell King
1 parent
fac105d05e
[ARM] 4122/1: ep93xx: add support for GPIO port F interrupts
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Showing 3 changed files with 73 additions and 30 deletions Side-by-side Diff
arch/arm/mach-ep93xx/core.c
... | ... | @@ -152,22 +152,29 @@ |
152 | 152 | /************************************************************************* |
153 | 153 | * GPIO handling for EP93xx |
154 | 154 | *************************************************************************/ |
155 | -static unsigned char gpio_int_enable[2]; | |
156 | -static unsigned char gpio_int_type1[2]; | |
157 | -static unsigned char gpio_int_type2[2]; | |
155 | +static unsigned char gpio_int_enable[3]; | |
156 | +static unsigned char gpio_int_type1[3]; | |
157 | +static unsigned char gpio_int_type2[3]; | |
158 | 158 | |
159 | -static void update_gpio_ab_int_params(int port) | |
159 | +static void update_gpio_int_params(int abf) | |
160 | 160 | { |
161 | - if (port == 0) { | |
161 | + if (abf == 0) { | |
162 | 162 | __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE); |
163 | 163 | __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2); |
164 | 164 | __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1); |
165 | 165 | __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE); |
166 | - } else if (port == 1) { | |
166 | + } else if (abf == 1) { | |
167 | 167 | __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE); |
168 | 168 | __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2); |
169 | 169 | __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1); |
170 | 170 | __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE); |
171 | + } else if (abf == 2) { | |
172 | + __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE); | |
173 | + __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2); | |
174 | + __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1); | |
175 | + __raw_writeb(gpio_int_enable[2], EP93XX_GPIO_F_INT_ENABLE); | |
176 | + } else { | |
177 | + BUG(); | |
171 | 178 | } |
172 | 179 | } |
173 | 180 | |
174 | 181 | |
... | ... | @@ -192,8 +199,13 @@ |
192 | 199 | local_irq_save(flags); |
193 | 200 | if (direction == GPIO_OUT) { |
194 | 201 | if (line >= 0 && line < 16) { |
202 | + /* Port A/B. */ | |
195 | 203 | gpio_int_enable[line >> 3] &= ~(1 << (line & 7)); |
196 | - update_gpio_ab_int_params(line >> 3); | |
204 | + update_gpio_int_params(line >> 3); | |
205 | + } else if (line >= 40 && line < 48) { | |
206 | + /* Port F. */ | |
207 | + gpio_int_enable[2] &= ~(1 << (line & 7)); | |
208 | + update_gpio_int_params(2); | |
197 | 209 | } |
198 | 210 | |
199 | 211 | v = __raw_readb(data_direction_register); |
... | ... | @@ -244,8 +256,7 @@ |
244 | 256 | /************************************************************************* |
245 | 257 | * EP93xx IRQ handling |
246 | 258 | *************************************************************************/ |
247 | -static void ep93xx_gpio_ab_irq_handler(unsigned int irq, | |
248 | - struct irq_desc *desc) | |
259 | +static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) | |
249 | 260 | { |
250 | 261 | unsigned char status; |
251 | 262 | int i; |
252 | 263 | |
253 | 264 | |
254 | 265 | |
255 | 266 | |
256 | 267 | |
257 | 268 | |
258 | 269 | |
259 | 270 | |
... | ... | @@ -267,37 +278,46 @@ |
267 | 278 | } |
268 | 279 | } |
269 | 280 | |
270 | -static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq) | |
281 | +static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) | |
271 | 282 | { |
283 | + int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4); | |
284 | + | |
285 | + desc_handle_irq(gpio_irq, irq_desc + gpio_irq); | |
286 | +} | |
287 | + | |
288 | +static void ep93xx_gpio_irq_mask_ack(unsigned int irq) | |
289 | +{ | |
272 | 290 | int line = irq - IRQ_EP93XX_GPIO(0); |
273 | 291 | int port = line >> 3; |
274 | 292 | |
275 | 293 | gpio_int_enable[port] &= ~(1 << (line & 7)); |
276 | - update_gpio_ab_int_params(port); | |
294 | + update_gpio_int_params(port); | |
277 | 295 | |
278 | - if (line >> 3) { | |
279 | - __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK); | |
280 | - } else { | |
296 | + if (port == 0) { | |
281 | 297 | __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK); |
298 | + } else if (port == 1) { | |
299 | + __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK); | |
300 | + } else if (port == 2) { | |
301 | + __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK); | |
282 | 302 | } |
283 | 303 | } |
284 | 304 | |
285 | -static void ep93xx_gpio_ab_irq_mask(unsigned int irq) | |
305 | +static void ep93xx_gpio_irq_mask(unsigned int irq) | |
286 | 306 | { |
287 | 307 | int line = irq - IRQ_EP93XX_GPIO(0); |
288 | 308 | int port = line >> 3; |
289 | 309 | |
290 | 310 | gpio_int_enable[port] &= ~(1 << (line & 7)); |
291 | - update_gpio_ab_int_params(port); | |
311 | + update_gpio_int_params(port); | |
292 | 312 | } |
293 | 313 | |
294 | -static void ep93xx_gpio_ab_irq_unmask(unsigned int irq) | |
314 | +static void ep93xx_gpio_irq_unmask(unsigned int irq) | |
295 | 315 | { |
296 | 316 | int line = irq - IRQ_EP93XX_GPIO(0); |
297 | 317 | int port = line >> 3; |
298 | 318 | |
299 | 319 | gpio_int_enable[port] |= 1 << (line & 7); |
300 | - update_gpio_ab_int_params(port); | |
320 | + update_gpio_int_params(port); | |
301 | 321 | } |
302 | 322 | |
303 | 323 | |
304 | 324 | |
... | ... | @@ -306,13 +326,17 @@ |
306 | 326 | * edge (1) triggered, while gpio_int_type2 controls whether it |
307 | 327 | * triggers on low/falling (0) or high/rising (1). |
308 | 328 | */ |
309 | -static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) | |
329 | +static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) | |
310 | 330 | { |
311 | 331 | int port; |
312 | 332 | int line; |
313 | 333 | |
314 | 334 | line = irq - IRQ_EP93XX_GPIO(0); |
315 | - gpio_line_config(line, GPIO_IN); | |
335 | + if (line >= 0 && line < 16) { | |
336 | + gpio_line_config(line, GPIO_IN); | |
337 | + } else { | |
338 | + gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN); | |
339 | + } | |
316 | 340 | |
317 | 341 | port = line >> 3; |
318 | 342 | line &= 7; |
319 | 343 | |
... | ... | @@ -330,16 +354,17 @@ |
330 | 354 | gpio_int_type1[port] &= ~(1 << line); |
331 | 355 | gpio_int_type2[port] &= ~(1 << line); |
332 | 356 | } |
333 | - update_gpio_ab_int_params(port); | |
357 | + update_gpio_int_params(port); | |
334 | 358 | |
335 | 359 | return 0; |
336 | 360 | } |
337 | 361 | |
338 | -static struct irq_chip ep93xx_gpio_ab_irq_chip = { | |
339 | - .ack = ep93xx_gpio_ab_irq_mask_ack, | |
340 | - .mask = ep93xx_gpio_ab_irq_mask, | |
341 | - .unmask = ep93xx_gpio_ab_irq_unmask, | |
342 | - .set_type = ep93xx_gpio_ab_irq_type, | |
362 | +static struct irq_chip ep93xx_gpio_irq_chip = { | |
363 | + .name = "GPIO", | |
364 | + .ack = ep93xx_gpio_irq_mask_ack, | |
365 | + .mask = ep93xx_gpio_irq_mask, | |
366 | + .unmask = ep93xx_gpio_irq_unmask, | |
367 | + .set_type = ep93xx_gpio_irq_type, | |
343 | 368 | }; |
344 | 369 | |
345 | 370 | |
346 | 371 | |
347 | 372 | |
... | ... | @@ -350,12 +375,21 @@ |
350 | 375 | vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); |
351 | 376 | vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); |
352 | 377 | |
353 | - for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) { | |
354 | - set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip); | |
378 | + for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) { | |
379 | + set_irq_chip(irq, &ep93xx_gpio_irq_chip); | |
355 | 380 | set_irq_handler(irq, handle_level_irq); |
356 | 381 | set_irq_flags(irq, IRQF_VALID); |
357 | 382 | } |
383 | + | |
358 | 384 | set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); |
385 | + set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler); | |
386 | + set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler); | |
387 | + set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler); | |
388 | + set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler); | |
389 | + set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler); | |
390 | + set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler); | |
391 | + set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler); | |
392 | + set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler); | |
359 | 393 | } |
360 | 394 | |
361 | 395 |
include/asm-arm/arch-ep93xx/ep93xx-regs.h
... | ... | @@ -73,6 +73,11 @@ |
73 | 73 | |
74 | 74 | #define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) |
75 | 75 | #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) |
76 | +#define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c) | |
77 | +#define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50) | |
78 | +#define EP93XX_GPIO_F_INT_ACK EP93XX_GPIO_REG(0x54) | |
79 | +#define EP93XX_GPIO_F_INT_ENABLE EP93XX_GPIO_REG(0x58) | |
80 | +#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) | |
76 | 81 | #define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90) |
77 | 82 | #define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94) |
78 | 83 | #define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98) |
include/asm-arm/arch-ep93xx/irqs.h
... | ... | @@ -67,9 +67,13 @@ |
67 | 67 | #define IRQ_EP93XX_SAI 60 |
68 | 68 | #define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff |
69 | 69 | |
70 | -#define IRQ_EP93XX_GPIO(x) (64 + (x)) | |
70 | +/* | |
71 | + * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and | |
72 | + * F0..F7 to 80..87. | |
73 | + */ | |
74 | +#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f)) | |
71 | 75 | |
72 | -#define NR_EP93XX_IRQS IRQ_EP93XX_GPIO(16) | |
76 | +#define NR_EP93XX_IRQS (64 + 24) | |
73 | 77 | |
74 | 78 | #define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) |
75 | 79 | #define EP93XX_BOARD_IRQS 32 |