summaryrefslogtreecommitdiff
path: root/target/linux/brcm2708/patches-3.10/0154-gpio-support-low-and-high-level-interrupts.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-3.10/0154-gpio-support-low-and-high-level-interrupts.patch')
-rw-r--r--target/linux/brcm2708/patches-3.10/0154-gpio-support-low-and-high-level-interrupts.patch115
1 files changed, 115 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.10/0154-gpio-support-low-and-high-level-interrupts.patch b/target/linux/brcm2708/patches-3.10/0154-gpio-support-low-and-high-level-interrupts.patch
new file mode 100644
index 0000000..ec9bb76
--- /dev/null
+++ b/target/linux/brcm2708/patches-3.10/0154-gpio-support-low-and-high-level-interrupts.patch
@@ -0,0 +1,115 @@
+From c334aa8da6e17555823ebf05bdb429ff224e99b3 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 9 Jan 2014 16:05:20 +0000
+Subject: [PATCH 154/174] gpio: support low and high level interrupts
+
+---
+ arch/arm/mach-bcm2708/bcm2708_gpio.c | 52 +++++++++++++++++++++++++-----------
+ 1 file changed, 37 insertions(+), 15 deletions(-)
+
+--- 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(str
+ 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
+ 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(stru
+ 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 = {