From 3387cbae6318b9e030323a76da64a2951328e93b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 22 Mar 2009 18:33:08 +0000 Subject: [PATCH] atheros: fix gpio interrupt handling on 2315 SVN-Revision: 14973 --- .../atheros/patches-2.6.28/100-board.patch | 56 +++++++++++-------- .../patches-2.6.28/105-ar2315_pci.patch | 6 +- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/target/linux/atheros/patches-2.6.28/100-board.patch b/target/linux/atheros/patches-2.6.28/100-board.patch index 2f7bb5b196eb..7c4fad18545a 100644 --- a/target/linux/atheros/patches-2.6.28/100-board.patch +++ b/target/linux/atheros/patches-2.6.28/100-board.patch @@ -2096,7 +2096,7 @@ + --- /dev/null +++ b/arch/mips/ar231x/ar2315.c -@@ -0,0 +1,663 @@ +@@ -0,0 +1,673 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive @@ -2142,22 +2142,24 @@ +static inline void ar2315_gpio_irq(void) +{ + u32 pend; -+ int bit; ++ int bit = -1; + + /* only do one gpio interrupt at a time */ + pend = (ar231x_read_reg(AR2315_GPIO_DI) ^ gpiointval) & gpiointmask; -+ if (!pend) -+ return; + -+ bit = fls(pend); -+ pend ^= (1 << bit); -+ gpiointval ^= (1 << bit); ++ if (pend) { ++ bit = fls(pend) - 1; ++ printk("GPIO IRQ: pend=0x%08x, val=%08x, bit=%d\n", pend, gpiointval, bit); ++ pend &= ~(1 << bit); ++ gpiointval ^= (1 << bit); ++ printk("AFTER IRQ: pend=0x%08x, val=%08x, bit=%d\n", pend, gpiointval, bit); ++ } + -+ /* ACK the interrupt only if we handled all bits */ + if (!pend) -+ ar231x_write_reg(AR2315_ISR, ar231x_read_reg(AR2315_IMR) | ~AR2315_ISR_GPIO); ++ ar231x_write_reg(AR2315_ISR, AR2315_ISR_GPIO); + -+ do_IRQ(AR531X_GPIO_IRQ_BASE + fls(pend) - 1); ++ if (bit >= 0) ++ do_IRQ(AR531X_GPIO_IRQ_BASE + bit); +} + + @@ -2203,7 +2205,6 @@ +{ + u32 reg; + -+ + reg = ar231x_read_reg(AR2315_GPIO_INT); + reg &= ~(AR2315_GPIO_INT_M | AR2315_GPIO_INT_LVL_M); + reg |= gpio | AR2315_GPIO_INT_LVL(level); @@ -2213,17 +2214,12 @@ +static void ar2315_gpio_intr_enable(unsigned int irq) +{ + unsigned int gpio = irq - AR531X_GPIO_IRQ_BASE; -+ u32 reg; -+ -+ gpiointmask &= ~(1 << gpio); + + /* reconfigure GPIO line as input */ -+ reg = ar231x_read_reg(AR2315_GPIO_CR); -+ reg &= ~(AR2315_GPIO_CR_M(gpio)); -+ reg |= AR2315_GPIO_CR_I(gpio); -+ ar231x_write_reg(AR2315_GPIO_CR, reg); ++ ar231x_mask_reg(AR2315_GPIO_CR, AR2315_GPIO_CR_M(gpio), AR2315_GPIO_CR_I(gpio)); + + /* Enable interrupt with edge detection */ ++ gpiointmask |= (1 << gpio); + ar2315_set_gpiointmask(gpio, 3); +} + @@ -2231,19 +2227,33 @@ +{ + unsigned int gpio = irq - AR531X_GPIO_IRQ_BASE; + -+ gpiointmask |= (1 << gpio); -+ + /* Disable interrupt */ ++ gpiointmask &= ~(1 << gpio); + ar2315_set_gpiointmask(gpio, 0); +} + ++static unsigned int ++ar2315_gpio_intr_startup(unsigned int irq) ++{ ++ ar2315_gpio_intr_enable(irq); ++ return 0; ++} ++ ++static void ++ar2315_gpio_intr_end(unsigned int irq) ++{ ++ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) ++ ar2315_gpio_intr_enable(irq); ++} ++ +static struct irq_chip ar2315_gpio_intr_controller = { + .typename = "AR2315-GPIO", ++ .startup = ar2315_gpio_intr_startup, ++ .shutdown = ar2315_gpio_intr_disable, ++ .enable = ar2315_gpio_intr_enable, + .disable = ar2315_gpio_intr_disable, + .ack = ar2315_gpio_intr_disable, -+ .mask_ack = ar2315_gpio_intr_disable, -+ .unmask = ar2315_gpio_intr_enable, -+ .eoi = ar2315_gpio_intr_enable, ++ .end = ar2315_gpio_intr_end, +}; + +static void diff --git a/target/linux/atheros/patches-2.6.28/105-ar2315_pci.patch b/target/linux/atheros/patches-2.6.28/105-ar2315_pci.patch index 389a0ec21489..69c334923068 100644 --- a/target/linux/atheros/patches-2.6.28/105-ar2315_pci.patch +++ b/target/linux/atheros/patches-2.6.28/105-ar2315_pci.patch @@ -257,8 +257,8 @@ + default y --- a/arch/mips/ar231x/ar2315.c +++ b/arch/mips/ar231x/ar2315.c -@@ -61,6 +61,27 @@ static inline void ar2315_gpio_irq(void) - do_IRQ(AR531X_GPIO_IRQ_BASE + fls(pend) - 1); +@@ -63,6 +63,27 @@ static inline void ar2315_gpio_irq(void) + do_IRQ(AR531X_GPIO_IRQ_BASE + bit); } +#ifdef CONFIG_ATHEROS_AR2315_PCI @@ -285,7 +285,7 @@ /* * Called when an interrupt is received, this function -@@ -79,6 +100,10 @@ ar2315_irq_dispatch(void) +@@ -81,6 +102,10 @@ ar2315_irq_dispatch(void) do_IRQ(AR2315_IRQ_WLAN0_INTRS); else if (pending & CAUSEF_IP4) do_IRQ(AR2315_IRQ_ENET0_INTRS); -- 2.30.2