diff options
author | Richard Röjfors <richard.rojfors@pelagicore.com> | 2010-03-05 13:44:35 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-06 11:26:48 -0800 |
commit | 8c35c89aa3d7e0f253c3a10456a8b075288b4565 (patch) | |
tree | 571fa92195a23fbd6cab7de7cba099aa69da7269 | |
parent | 3e45f1d1155894e6f4291f5536b224874d52d8e2 (diff) | |
download | kernel_samsung_smdk4412-8c35c89aa3d7e0f253c3a10456a8b075288b4565.zip kernel_samsung_smdk4412-8c35c89aa3d7e0f253c3a10456a8b075288b4565.tar.gz kernel_samsung_smdk4412-8c35c89aa3d7e0f253c3a10456a8b075288b4565.tar.bz2 |
timbgpio: add support for interrupt triggering on both flanks
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>
-rw-r--r-- | drivers/gpio/timbgpio.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index 4ecba6e..d4295fa 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/timbgpio.c @@ -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; @@ -126,17 +128,23 @@ 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; @@ -144,21 +152,27 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger) 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); |