Skip to content

Commit

Permalink
timbgpio: add support for interrupt triggering on both flanks
Browse files Browse the repository at this point in the history
Introduce support for triggering interrupts on both rising and falling
edge.

This feature requires version 3 or newer of the IP, a version check is
done when triggering on both edges is requested.

Signed-off-by: Richard Röjfors <richard.rojfors@pelagicore.com>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Richard Röjfors authored and Linus Torvalds committed Mar 6, 2010
1 parent 3e45f1d commit 8c35c89
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions drivers/gpio/timbgpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#define TGPIO_ICR 0x14
#define TGPIO_FLR 0x18
#define TGPIO_LVR 0x1c
#define TGPIO_VER 0x20
#define TGPIO_BFLR 0x24

struct timbgpio {
void __iomem *membase;
Expand Down Expand Up @@ -126,39 +128,51 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger)
struct timbgpio *tgpio = get_irq_chip_data(irq);
int offset = irq - tgpio->irq_base;
unsigned long flags;
u32 lvr, flr;
u32 lvr, flr, bflr = 0;
u32 ver;

if (offset < 0 || offset > tgpio->gpio.ngpio)
return -EINVAL;

ver = ioread32(tgpio->membase + TGPIO_VER);

spin_lock_irqsave(&tgpio->lock, flags);

lvr = ioread32(tgpio->membase + TGPIO_LVR);
flr = ioread32(tgpio->membase + TGPIO_FLR);
if (ver > 2)
bflr = ioread32(tgpio->membase + TGPIO_BFLR);

if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
bflr &= ~(1 << offset);
flr &= ~(1 << offset);
if (trigger & IRQ_TYPE_LEVEL_HIGH)
lvr |= 1 << offset;
else
lvr &= ~(1 << offset);
}

if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
return -EINVAL;
else {
if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
if (ver < 3)
return -EINVAL;
else {
flr |= 1 << offset;
bflr |= 1 << offset;
}
} else {
bflr &= ~(1 << offset);
flr |= 1 << offset;
/* opposite compared to the datasheet, but it mirrors the
* reality
*/
if (trigger & IRQ_TYPE_EDGE_FALLING)
lvr |= 1 << offset;
else
lvr &= ~(1 << offset);
else
lvr |= 1 << offset;
}

iowrite32(lvr, tgpio->membase + TGPIO_LVR);
iowrite32(flr, tgpio->membase + TGPIO_FLR);
if (ver > 2)
iowrite32(bflr, tgpio->membase + TGPIO_BFLR);

iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
spin_unlock_irqrestore(&tgpio->lock, flags);

Expand Down

0 comments on commit 8c35c89

Please sign in to comment.