1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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 = {
|