aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx
diff options
context:
space:
mode:
authorHerbert Valerio Riedel <hvr@gnu.org>2007-11-26 12:49:08 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 09:37:31 -0500
commit3c9a071d77e007464952a2d41b6686d98eb3f0b8 (patch)
tree7e346e17e81ed78adaeee94741c2ec68fd8fac28 /arch/arm/mach-ep93xx
parent7ca722533979d47563e75a40c86c405153818b83 (diff)
[ARM] 4670/1: ep93xx: implement IRQT_BOTHEDGE gpio irq sense type
Having a both-edge sensitive irq trigger type is required for the generic gpio-keys input driver; alas the ep93xx does not support both-edge gpio triggers in hardware, so this patch implements them by switching edge polarity on each triggered interrupt. This is the same approach as taken by the Orion SoC both-edge gpio irq support implementation. Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org> Acked-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r--arch/arm/mach-ep93xx/core.c64
1 files changed, 53 insertions, 11 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 58957d7a576..2788da06417 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -3,6 +3,7 @@
3 * Core routines for Cirrus EP93xx chips. 3 * Core routines for Cirrus EP93xx chips.
4 * 4 *
5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
6 * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
6 * 7 *
7 * Thanks go to Michael Burian and Ray Lehtiniemi for their key 8 * Thanks go to Michael Burian and Ray Lehtiniemi for their key
8 * role in the ep93xx linux community. 9 * role in the ep93xx linux community.
@@ -315,12 +316,29 @@ static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
315 desc_handle_irq(gpio_irq, irq_desc + gpio_irq); 316 desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
316} 317}
317 318
319static void ep93xx_gpio_irq_ack(unsigned int irq)
320{
321 int line = irq_to_gpio(irq);
322 int port = line >> 3;
323 int port_mask = 1 << (line & 7);
324
325 if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
326 gpio_int_type2[port] ^= port_mask; /* switch edge direction */
327 update_gpio_int_params(port);
328 }
329
330 __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
331}
332
318static void ep93xx_gpio_irq_mask_ack(unsigned int irq) 333static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
319{ 334{
320 int line = irq_to_gpio(irq); 335 int line = irq_to_gpio(irq);
321 int port = line >> 3; 336 int port = line >> 3;
322 int port_mask = 1 << (line & 7); 337 int port_mask = 1 << (line & 7);
323 338
339 if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE)
340 gpio_int_type2[port] ^= port_mask; /* switch edge direction */
341
324 gpio_int_unmasked[port] &= ~port_mask; 342 gpio_int_unmasked[port] &= ~port_mask;
325 update_gpio_int_params(port); 343 update_gpio_int_params(port);
326 344
@@ -353,31 +371,54 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq)
353 */ 371 */
354static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) 372static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
355{ 373{
374 struct irq_desc *desc = irq_desc + irq;
356 const int gpio = irq_to_gpio(irq); 375 const int gpio = irq_to_gpio(irq);
357 const int port = gpio >> 3; 376 const int port = gpio >> 3;
358 const int port_mask = 1 << (gpio & 7); 377 const int port_mask = 1 << (gpio & 7);
359 378
360 ep93xx_gpio_set_direction(gpio, GPIO_IN); 379 ep93xx_gpio_set_direction(gpio, GPIO_IN);
361 380
362 if (type & IRQT_RISING) { 381 switch (type) {
363 gpio_int_enabled[port] |= port_mask; 382 case IRQT_RISING:
364 gpio_int_type1[port] |= port_mask; 383 gpio_int_type1[port] |= port_mask;
365 gpio_int_type2[port] |= port_mask; 384 gpio_int_type2[port] |= port_mask;
366 } else if (type & IRQT_FALLING) { 385 desc->handle_irq = handle_edge_irq;
367 gpio_int_enabled[port] |= port_mask; 386 break;
387 case IRQT_FALLING:
368 gpio_int_type1[port] |= port_mask; 388 gpio_int_type1[port] |= port_mask;
369 gpio_int_type2[port] &= ~port_mask; 389 gpio_int_type2[port] &= ~port_mask;
370 } else if (type & IRQT_HIGH) { 390 desc->handle_irq = handle_edge_irq;
371 gpio_int_enabled[port] |= port_mask; 391 break;
392 case IRQT_HIGH:
372 gpio_int_type1[port] &= ~port_mask; 393 gpio_int_type1[port] &= ~port_mask;
373 gpio_int_type2[port] |= port_mask; 394 gpio_int_type2[port] |= port_mask;
374 } else if (type & IRQT_LOW) { 395 desc->handle_irq = handle_level_irq;
375 gpio_int_enabled[port] |= port_mask; 396 break;
397 case IRQT_LOW:
376 gpio_int_type1[port] &= ~port_mask; 398 gpio_int_type1[port] &= ~port_mask;
377 gpio_int_type2[port] &= ~port_mask; 399 gpio_int_type2[port] &= ~port_mask;
378 } else { 400 desc->handle_irq = handle_level_irq;
379 gpio_int_enabled[port] &= ~port_mask; 401 break;
402 case IRQT_BOTHEDGE:
403 gpio_int_type1[port] |= port_mask;
404 /* set initial polarity based on current input level */
405 if (gpio_get_value(gpio))
406 gpio_int_type2[port] &= ~port_mask; /* falling */
407 else
408 gpio_int_type2[port] |= port_mask; /* rising */
409 desc->handle_irq = handle_edge_irq;
410 break;
411 default:
412 pr_err("ep93xx: failed to set irq type %d for gpio %d\n",
413 type, gpio);
414 return -EINVAL;
380 } 415 }
416
417 gpio_int_enabled[port] |= port_mask;
418
419 desc->status &= ~IRQ_TYPE_SENSE_MASK;
420 desc->status |= type & IRQ_TYPE_SENSE_MASK;
421
381 update_gpio_int_params(port); 422 update_gpio_int_params(port);
382 423
383 return 0; 424 return 0;
@@ -385,7 +426,8 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
385 426
386static struct irq_chip ep93xx_gpio_irq_chip = { 427static struct irq_chip ep93xx_gpio_irq_chip = {
387 .name = "GPIO", 428 .name = "GPIO",
388 .ack = ep93xx_gpio_irq_mask_ack, 429 .ack = ep93xx_gpio_irq_ack,
430 .mask_ack = ep93xx_gpio_irq_mask_ack,
389 .mask = ep93xx_gpio_irq_mask, 431 .mask = ep93xx_gpio_irq_mask,
390 .unmask = ep93xx_gpio_irq_unmask, 432 .unmask = ep93xx_gpio_irq_unmask,
391 .set_type = ep93xx_gpio_irq_type, 433 .set_type = ep93xx_gpio_irq_type,