From 1c5855bf32be271eb9c08b687d417d686d7f6782 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 12 Jan 2015 16:38:14 +0000 Subject: [PATCH] bcm2708_gpio: Avoid calling irq_unmask for all interrupts When setting up the interrupts, specify that the handle_simple_irq handler should be used. This leaves interrupt acknowledgement to the caller, and prevents irq_unmask from being called for all interrupts. Issue: linux #760 --- arch/arm/mach-bcm2708/bcm2708_gpio.c | 38 +++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c index 68f6ffd2d0327..25e917c3908f5 100644 --- a/arch/arm/mach-bcm2708/bcm2708_gpio.c +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c @@ -43,6 +43,8 @@ #define GPIOUD(x) (0x94+(x)*4) #define GPIOUDCLK(x) (0x98+(x)*4) +#define GPIO_BANKS 2 + enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT, GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4, GPIO_FSEL_ALT0, GPIO_FSEL_ALT1, @@ -239,8 +241,6 @@ static void bcm2708_gpio_irq_unmask(struct irq_data *d) unsigned long high = readl(gpio->base + GPIOHEN(gb)); unsigned long low = readl(gpio->base + GPIOLEN(gb)); - writel(1 << go, gpio->base + GPIOEDS(gb)); - if (gpio->rising[gb] & (1 << go)) { writel(rising | (1 << go), gpio->base + GPIOREN(gb)); } else { @@ -281,12 +281,24 @@ static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) unsigned bank; int i; unsigned gpio; - for (bank = 0; bank <= 1; bank++) { + unsigned level_bits; + struct bcm2708_gpio *gpio_data = dev_id; + + for (bank = 0; bank < GPIO_BANKS; bank++) { edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank)); + level_bits = gpio_data->high[bank] | gpio_data->low[bank]; + for_each_set_bit(i, &edsr, 32) { gpio = i + bank * 32; + /* ack edge triggered IRQs immediately */ + if (!(level_bits & (1<gc.set = bcm2708_gpio_set; ucb->gc.can_sleep = 0; + for (bank = 0; bank < GPIO_BANKS; bank++) { + writel(0, ucb->base + GPIOREN(bank)); + writel(0, ucb->base + GPIOFEN(bank)); + writel(0, ucb->base + GPIOHEN(bank)); + writel(0, ucb->base + GPIOLEN(bank)); + writel(0, ucb->base + GPIOAREN(bank)); + writel(0, ucb->base + GPIOAFEN(bank)); + writel(0, ucb->base + GPIOEDS(bank)); + } + bcm2708_gpio_irq_init(ucb); err = gpiochip_add(&ucb->gc); - if (err) - goto err; err: return err;