121 lines
4.1 KiB
Diff
121 lines
4.1 KiB
Diff
From 504b5a3a5f492deccf35a3ed5e7b9a48a069ece2 Mon Sep 17 00:00:00 2001
|
|
From: popcornmix <popcornmix@gmail.com>
|
|
Date: Thu, 9 Jan 2014 16:05:20 +0000
|
|
Subject: [PATCH 154/196] gpio: support low and high level interrupts
|
|
|
|
---
|
|
arch/arm/mach-bcm2708/bcm2708_gpio.c | 52 +++++++++++++++++++++++++-----------
|
|
1 file changed, 37 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c
|
|
index 96fae74..1d93ad8 100644
|
|
--- a/arch/arm/mach-bcm2708/bcm2708_gpio.c
|
|
+++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c
|
|
@@ -58,6 +58,8 @@ struct bcm2708_gpio {
|
|
struct gpio_chip gc;
|
|
unsigned long rising;
|
|
unsigned long falling;
|
|
+ unsigned long high;
|
|
+ unsigned long low;
|
|
};
|
|
|
|
static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
|
|
@@ -145,20 +147,22 @@ static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type)
|
|
unsigned irq = d->irq;
|
|
struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
|
|
|
|
- if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
|
+ gpio->rising &= ~(1 << __bcm2708_irq_to_gpio(irq));
|
|
+ gpio->falling &= ~(1 << __bcm2708_irq_to_gpio(irq));
|
|
+ gpio->high &= ~(1 << __bcm2708_irq_to_gpio(irq));
|
|
+ gpio->low &= ~(1 << __bcm2708_irq_to_gpio(irq));
|
|
+
|
|
+ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
|
return -EINVAL;
|
|
|
|
- if (type & IRQ_TYPE_EDGE_RISING) {
|
|
+ if (type & IRQ_TYPE_EDGE_RISING)
|
|
gpio->rising |= (1 << __bcm2708_irq_to_gpio(irq));
|
|
- } else {
|
|
- gpio->rising &= ~(1 << __bcm2708_irq_to_gpio(irq));
|
|
- }
|
|
-
|
|
- if (type & IRQ_TYPE_EDGE_FALLING) {
|
|
+ if (type & IRQ_TYPE_EDGE_FALLING)
|
|
gpio->falling |= (1 << __bcm2708_irq_to_gpio(irq));
|
|
- } else {
|
|
- gpio->falling &= ~(1 << __bcm2708_irq_to_gpio(irq));
|
|
- }
|
|
+ if (type & IRQ_TYPE_LEVEL_HIGH)
|
|
+ gpio->high |= (1 << __bcm2708_irq_to_gpio(irq));
|
|
+ if (type & IRQ_TYPE_LEVEL_LOW)
|
|
+ gpio->low |= (1 << __bcm2708_irq_to_gpio(irq));
|
|
return 0;
|
|
}
|
|
|
|
@@ -168,13 +172,17 @@ static void bcm2708_gpio_irq_mask(struct irq_data *d)
|
|
struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
|
|
unsigned gn = __bcm2708_irq_to_gpio(irq);
|
|
unsigned gb = gn / 32;
|
|
- unsigned long rising = readl(gpio->base + GPIOREN(gb));
|
|
+ unsigned long rising = readl(gpio->base + GPIOREN(gb));
|
|
unsigned long falling = readl(gpio->base + GPIOFEN(gb));
|
|
+ unsigned long high = readl(gpio->base + GPIOHEN(gb));
|
|
+ unsigned long low = readl(gpio->base + GPIOLEN(gb));
|
|
|
|
gn = gn % 32;
|
|
|
|
- writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
|
|
+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
|
|
writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
|
|
+ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
|
|
+ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
|
|
}
|
|
|
|
static void bcm2708_gpio_irq_unmask(struct irq_data *d)
|
|
@@ -183,24 +191,38 @@ static void bcm2708_gpio_irq_unmask(struct irq_data *d)
|
|
struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
|
|
unsigned gn = __bcm2708_irq_to_gpio(irq);
|
|
unsigned gb = gn / 32;
|
|
- unsigned long rising = readl(gpio->base + GPIOREN(gb));
|
|
+ unsigned long rising = readl(gpio->base + GPIOREN(gb));
|
|
unsigned long falling = readl(gpio->base + GPIOFEN(gb));
|
|
+ unsigned long high = readl(gpio->base + GPIOHEN(gb));
|
|
+ unsigned long low = readl(gpio->base + GPIOLEN(gb));
|
|
|
|
gn = gn % 32;
|
|
|
|
writel(1 << gn, gpio->base + GPIOEDS(gb));
|
|
|
|
if (gpio->rising & (1 << gn)) {
|
|
- writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
|
|
+ writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
|
|
} else {
|
|
writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
|
|
}
|
|
|
|
if (gpio->falling & (1 << gn)) {
|
|
- writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
|
|
+ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
|
|
} else {
|
|
writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
|
|
}
|
|
+
|
|
+ if (gpio->high & (1 << gn)) {
|
|
+ writel(high | (1 << gn), gpio->base + GPIOHEN(gb));
|
|
+ } else {
|
|
+ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
|
|
+ }
|
|
+
|
|
+ if (gpio->low & (1 << gn)) {
|
|
+ writel(low | (1 << gn), gpio->base + GPIOLEN(gb));
|
|
+ } else {
|
|
+ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
|
|
+ }
|
|
}
|
|
|
|
static struct irq_chip bcm2708_irqchip = {
|
|
--
|
|
1.9.1
|
|
|