Skip to content

Commit 7b3d622

Browse files
committed
gpio: support low and high level interrupts
1 parent f04ff75 commit 7b3d622

File tree

1 file changed

+37
-15
lines changed

1 file changed

+37
-15
lines changed

arch/arm/mach-bcm2708/bcm2708_gpio.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ struct bcm2708_gpio {
5858
struct gpio_chip gc;
5959
unsigned long rising;
6060
unsigned long falling;
61+
unsigned long high;
62+
unsigned long low;
6163
};
6264

6365
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)
145147
unsigned irq = d->irq;
146148
struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
147149

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))
149156
return -EINVAL;
150157

151-
if (type & IRQ_TYPE_EDGE_RISING) {
158+
if (type & IRQ_TYPE_EDGE_RISING)
152159
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)
158161
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));
162166
return 0;
163167
}
164168

@@ -168,13 +172,17 @@ static void bcm2708_gpio_irq_mask(struct irq_data *d)
168172
struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
169173
unsigned gn = __bcm2708_irq_to_gpio(irq);
170174
unsigned gb = gn / 32;
171-
unsigned long rising = readl(gpio->base + GPIOREN(gb));
175+
unsigned long rising = readl(gpio->base + GPIOREN(gb));
172176
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));
173179

174180
gn = gn % 32;
175181

176-
writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
182+
writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
177183
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));
178186
}
179187

180188
static void bcm2708_gpio_irq_unmask(struct irq_data *d)
@@ -183,24 +191,38 @@ static void bcm2708_gpio_irq_unmask(struct irq_data *d)
183191
struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
184192
unsigned gn = __bcm2708_irq_to_gpio(irq);
185193
unsigned gb = gn / 32;
186-
unsigned long rising = readl(gpio->base + GPIOREN(gb));
194+
unsigned long rising = readl(gpio->base + GPIOREN(gb));
187195
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));
188198

189199
gn = gn % 32;
190200

191201
writel(1 << gn, gpio->base + GPIOEDS(gb));
192202

193203
if (gpio->rising & (1 << gn)) {
194-
writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
204+
writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
195205
} else {
196206
writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
197207
}
198208

199209
if (gpio->falling & (1 << gn)) {
200-
writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
210+
writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
201211
} else {
202212
writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
203213
}
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+
}
204226
}
205227

206228
static struct irq_chip bcm2708_irqchip = {

0 commit comments

Comments
 (0)