@@ -58,6 +58,8 @@ struct bcm2708_gpio {
58
58
struct gpio_chip gc ;
59
59
unsigned long rising ;
60
60
unsigned long falling ;
61
+ unsigned long high ;
62
+ unsigned long low ;
61
63
};
62
64
63
65
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)
145
147
unsigned irq = d -> irq ;
146
148
struct bcm2708_gpio * gpio = irq_get_chip_data (irq );
147
149
148
- if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING ))
150
+ gpio -> rising &= ~(1 << __bcm2708_irq_to_gpio (irq ));
151
+ gpio -> falling &= ~(1 << __bcm2708_irq_to_gpio (irq ));
152
+ gpio -> high &= ~(1 << __bcm2708_irq_to_gpio (irq ));
153
+ gpio -> low &= ~(1 << __bcm2708_irq_to_gpio (irq ));
154
+
155
+ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH ))
149
156
return - EINVAL ;
150
157
151
- if (type & IRQ_TYPE_EDGE_RISING ) {
158
+ if (type & IRQ_TYPE_EDGE_RISING )
152
159
gpio -> rising |= (1 << __bcm2708_irq_to_gpio (irq ));
153
- } else {
154
- gpio -> rising &= ~(1 << __bcm2708_irq_to_gpio (irq ));
155
- }
156
-
157
- if (type & IRQ_TYPE_EDGE_FALLING ) {
160
+ if (type & IRQ_TYPE_EDGE_FALLING )
158
161
gpio -> falling |= (1 << __bcm2708_irq_to_gpio (irq ));
159
- } else {
160
- gpio -> falling &= ~(1 << __bcm2708_irq_to_gpio (irq ));
161
- }
162
+ if (type & IRQ_TYPE_LEVEL_HIGH )
163
+ gpio -> high |= (1 << __bcm2708_irq_to_gpio (irq ));
164
+ if (type & IRQ_TYPE_LEVEL_LOW )
165
+ gpio -> low |= (1 << __bcm2708_irq_to_gpio (irq ));
162
166
return 0 ;
163
167
}
164
168
@@ -168,13 +172,17 @@ static void bcm2708_gpio_irq_mask(struct irq_data *d)
168
172
struct bcm2708_gpio * gpio = irq_get_chip_data (irq );
169
173
unsigned gn = __bcm2708_irq_to_gpio (irq );
170
174
unsigned gb = gn / 32 ;
171
- unsigned long rising = readl (gpio -> base + GPIOREN (gb ));
175
+ unsigned long rising = readl (gpio -> base + GPIOREN (gb ));
172
176
unsigned long falling = readl (gpio -> base + GPIOFEN (gb ));
177
+ unsigned long high = readl (gpio -> base + GPIOHEN (gb ));
178
+ unsigned long low = readl (gpio -> base + GPIOLEN (gb ));
173
179
174
180
gn = gn % 32 ;
175
181
176
- writel (rising & ~(1 << gn ), gpio -> base + GPIOREN (gb ));
182
+ writel (rising & ~(1 << gn ), gpio -> base + GPIOREN (gb ));
177
183
writel (falling & ~(1 << gn ), gpio -> base + GPIOFEN (gb ));
184
+ writel (high & ~(1 << gn ), gpio -> base + GPIOHEN (gb ));
185
+ writel (low & ~(1 << gn ), gpio -> base + GPIOLEN (gb ));
178
186
}
179
187
180
188
static void bcm2708_gpio_irq_unmask (struct irq_data * d )
@@ -183,24 +191,38 @@ static void bcm2708_gpio_irq_unmask(struct irq_data *d)
183
191
struct bcm2708_gpio * gpio = irq_get_chip_data (irq );
184
192
unsigned gn = __bcm2708_irq_to_gpio (irq );
185
193
unsigned gb = gn / 32 ;
186
- unsigned long rising = readl (gpio -> base + GPIOREN (gb ));
194
+ unsigned long rising = readl (gpio -> base + GPIOREN (gb ));
187
195
unsigned long falling = readl (gpio -> base + GPIOFEN (gb ));
196
+ unsigned long high = readl (gpio -> base + GPIOHEN (gb ));
197
+ unsigned long low = readl (gpio -> base + GPIOLEN (gb ));
188
198
189
199
gn = gn % 32 ;
190
200
191
201
writel (1 << gn , gpio -> base + GPIOEDS (gb ));
192
202
193
203
if (gpio -> rising & (1 << gn )) {
194
- writel (rising | (1 << gn ), gpio -> base + GPIOREN (gb ));
204
+ writel (rising | (1 << gn ), gpio -> base + GPIOREN (gb ));
195
205
} else {
196
206
writel (rising & ~(1 << gn ), gpio -> base + GPIOREN (gb ));
197
207
}
198
208
199
209
if (gpio -> falling & (1 << gn )) {
200
- writel (falling | (1 << gn ), gpio -> base + GPIOFEN (gb ));
210
+ writel (falling | (1 << gn ), gpio -> base + GPIOFEN (gb ));
201
211
} else {
202
212
writel (falling & ~(1 << gn ), gpio -> base + GPIOFEN (gb ));
203
213
}
214
+
215
+ if (gpio -> high & (1 << gn )) {
216
+ writel (high | (1 << gn ), gpio -> base + GPIOHEN (gb ));
217
+ } else {
218
+ writel (high & ~(1 << gn ), gpio -> base + GPIOHEN (gb ));
219
+ }
220
+
221
+ if (gpio -> low & (1 << gn )) {
222
+ writel (low | (1 << gn ), gpio -> base + GPIOLEN (gb ));
223
+ } else {
224
+ writel (low & ~(1 << gn ), gpio -> base + GPIOLEN (gb ));
225
+ }
204
226
}
205
227
206
228
static struct irq_chip bcm2708_irqchip = {
0 commit comments