diff options
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.patch | 115 |
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 0000000000..ec9bb76168 --- /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 = { |