brcm2708: update 3.10 patches with raspberrypi/rpi-3.10.y of 27 Apr. 2014
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0154-gpio-support-low-and-high-level-interrupts.patch
1 From 504b5a3a5f492deccf35a3ed5e7b9a48a069ece2 Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Thu, 9 Jan 2014 16:05:20 +0000
4 Subject: [PATCH 154/196] gpio: support low and high level interrupts
5
6 ---
7 arch/arm/mach-bcm2708/bcm2708_gpio.c | 52 +++++++++++++++++++++++++-----------
8 1 file changed, 37 insertions(+), 15 deletions(-)
9
10 diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c
11 index 96fae74..1d93ad8 100644
12 --- a/arch/arm/mach-bcm2708/bcm2708_gpio.c
13 +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c
14 @@ -58,6 +58,8 @@ struct bcm2708_gpio {
15 struct gpio_chip gc;
16 unsigned long rising;
17 unsigned long falling;
18 + unsigned long high;
19 + unsigned long low;
20 };
21
22 static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
23 @@ -145,20 +147,22 @@ static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type)
24 unsigned irq = d->irq;
25 struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
26
27 - if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
28 + gpio->rising &= ~(1 << __bcm2708_irq_to_gpio(irq));
29 + gpio->falling &= ~(1 << __bcm2708_irq_to_gpio(irq));
30 + gpio->high &= ~(1 << __bcm2708_irq_to_gpio(irq));
31 + gpio->low &= ~(1 << __bcm2708_irq_to_gpio(irq));
32 +
33 + if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
34 return -EINVAL;
35
36 - if (type & IRQ_TYPE_EDGE_RISING) {
37 + if (type & IRQ_TYPE_EDGE_RISING)
38 gpio->rising |= (1 << __bcm2708_irq_to_gpio(irq));
39 - } else {
40 - gpio->rising &= ~(1 << __bcm2708_irq_to_gpio(irq));
41 - }
42 -
43 - if (type & IRQ_TYPE_EDGE_FALLING) {
44 + if (type & IRQ_TYPE_EDGE_FALLING)
45 gpio->falling |= (1 << __bcm2708_irq_to_gpio(irq));
46 - } else {
47 - gpio->falling &= ~(1 << __bcm2708_irq_to_gpio(irq));
48 - }
49 + if (type & IRQ_TYPE_LEVEL_HIGH)
50 + gpio->high |= (1 << __bcm2708_irq_to_gpio(irq));
51 + if (type & IRQ_TYPE_LEVEL_LOW)
52 + gpio->low |= (1 << __bcm2708_irq_to_gpio(irq));
53 return 0;
54 }
55
56 @@ -168,13 +172,17 @@ static void bcm2708_gpio_irq_mask(struct irq_data *d)
57 struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
58 unsigned gn = __bcm2708_irq_to_gpio(irq);
59 unsigned gb = gn / 32;
60 - unsigned long rising = readl(gpio->base + GPIOREN(gb));
61 + unsigned long rising = readl(gpio->base + GPIOREN(gb));
62 unsigned long falling = readl(gpio->base + GPIOFEN(gb));
63 + unsigned long high = readl(gpio->base + GPIOHEN(gb));
64 + unsigned long low = readl(gpio->base + GPIOLEN(gb));
65
66 gn = gn % 32;
67
68 - writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
69 + writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
70 writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
71 + writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
72 + writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
73 }
74
75 static void bcm2708_gpio_irq_unmask(struct irq_data *d)
76 @@ -183,24 +191,38 @@ static void bcm2708_gpio_irq_unmask(struct irq_data *d)
77 struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
78 unsigned gn = __bcm2708_irq_to_gpio(irq);
79 unsigned gb = gn / 32;
80 - unsigned long rising = readl(gpio->base + GPIOREN(gb));
81 + unsigned long rising = readl(gpio->base + GPIOREN(gb));
82 unsigned long falling = readl(gpio->base + GPIOFEN(gb));
83 + unsigned long high = readl(gpio->base + GPIOHEN(gb));
84 + unsigned long low = readl(gpio->base + GPIOLEN(gb));
85
86 gn = gn % 32;
87
88 writel(1 << gn, gpio->base + GPIOEDS(gb));
89
90 if (gpio->rising & (1 << gn)) {
91 - writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
92 + writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
93 } else {
94 writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
95 }
96
97 if (gpio->falling & (1 << gn)) {
98 - writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
99 + writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
100 } else {
101 writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
102 }
103 +
104 + if (gpio->high & (1 << gn)) {
105 + writel(high | (1 << gn), gpio->base + GPIOHEN(gb));
106 + } else {
107 + writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
108 + }
109 +
110 + if (gpio->low & (1 << gn)) {
111 + writel(low | (1 << gn), gpio->base + GPIOLEN(gb));
112 + } else {
113 + writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
114 + }
115 }
116
117 static struct irq_chip bcm2708_irqchip = {
118 --
119 1.9.1
120