atheros: fix gpio interrupt handling on 2315

SVN-Revision: 14973
This commit is contained in:
Felix Fietkau 2009-03-22 18:33:08 +00:00
parent bb63dea4fb
commit 3387cbae63
2 changed files with 38 additions and 28 deletions

View File

@ -2096,7 +2096,7 @@
+ +
--- /dev/null --- /dev/null
+++ b/arch/mips/ar231x/ar2315.c +++ 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 + * 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 + * License. See the file "COPYING" in the main directory of this archive
@ -2142,22 +2142,24 @@
+static inline void ar2315_gpio_irq(void) +static inline void ar2315_gpio_irq(void)
+{ +{
+ u32 pend; + u32 pend;
+ int bit; + int bit = -1;
+ +
+ /* only do one gpio interrupt at a time */ + /* only do one gpio interrupt at a time */
+ pend = (ar231x_read_reg(AR2315_GPIO_DI) ^ gpiointval) & gpiointmask; + pend = (ar231x_read_reg(AR2315_GPIO_DI) ^ gpiointval) & gpiointmask;
+
+ 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);
+ }
+
+ if (!pend) + if (!pend)
+ return; + ar231x_write_reg(AR2315_ISR, AR2315_ISR_GPIO);
+ +
+ bit = fls(pend); + if (bit >= 0)
+ pend ^= (1 << bit); + do_IRQ(AR531X_GPIO_IRQ_BASE + bit);
+ gpiointval ^= (1 << 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);
+
+ do_IRQ(AR531X_GPIO_IRQ_BASE + fls(pend) - 1);
+} +}
+ +
+ +
@ -2203,7 +2205,6 @@
+{ +{
+ u32 reg; + u32 reg;
+ +
+
+ reg = ar231x_read_reg(AR2315_GPIO_INT); + reg = ar231x_read_reg(AR2315_GPIO_INT);
+ reg &= ~(AR2315_GPIO_INT_M | AR2315_GPIO_INT_LVL_M); + reg &= ~(AR2315_GPIO_INT_M | AR2315_GPIO_INT_LVL_M);
+ reg |= gpio | AR2315_GPIO_INT_LVL(level); + reg |= gpio | AR2315_GPIO_INT_LVL(level);
@ -2213,17 +2214,12 @@
+static void ar2315_gpio_intr_enable(unsigned int irq) +static void ar2315_gpio_intr_enable(unsigned int irq)
+{ +{
+ unsigned int gpio = irq - AR531X_GPIO_IRQ_BASE; + unsigned int gpio = irq - AR531X_GPIO_IRQ_BASE;
+ u32 reg;
+
+ gpiointmask &= ~(1 << gpio);
+ +
+ /* reconfigure GPIO line as input */ + /* reconfigure GPIO line as input */
+ reg = ar231x_read_reg(AR2315_GPIO_CR); + ar231x_mask_reg(AR2315_GPIO_CR, AR2315_GPIO_CR_M(gpio), AR2315_GPIO_CR_I(gpio));
+ reg &= ~(AR2315_GPIO_CR_M(gpio));
+ reg |= AR2315_GPIO_CR_I(gpio);
+ ar231x_write_reg(AR2315_GPIO_CR, reg);
+ +
+ /* Enable interrupt with edge detection */ + /* Enable interrupt with edge detection */
+ gpiointmask |= (1 << gpio);
+ ar2315_set_gpiointmask(gpio, 3); + ar2315_set_gpiointmask(gpio, 3);
+} +}
+ +
@ -2231,19 +2227,33 @@
+{ +{
+ unsigned int gpio = irq - AR531X_GPIO_IRQ_BASE; + unsigned int gpio = irq - AR531X_GPIO_IRQ_BASE;
+ +
+ gpiointmask |= (1 << gpio);
+
+ /* Disable interrupt */ + /* Disable interrupt */
+ gpiointmask &= ~(1 << gpio);
+ ar2315_set_gpiointmask(gpio, 0); + 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 = { +static struct irq_chip ar2315_gpio_intr_controller = {
+ .typename = "AR2315-GPIO", + .typename = "AR2315-GPIO",
+ .startup = ar2315_gpio_intr_startup,
+ .shutdown = ar2315_gpio_intr_disable,
+ .enable = ar2315_gpio_intr_enable,
+ .disable = ar2315_gpio_intr_disable, + .disable = ar2315_gpio_intr_disable,
+ .ack = ar2315_gpio_intr_disable, + .ack = ar2315_gpio_intr_disable,
+ .mask_ack = ar2315_gpio_intr_disable, + .end = ar2315_gpio_intr_end,
+ .unmask = ar2315_gpio_intr_enable,
+ .eoi = ar2315_gpio_intr_enable,
+}; +};
+ +
+static void +static void

View File

@ -257,8 +257,8 @@
+ default y + default y
--- a/arch/mips/ar231x/ar2315.c --- a/arch/mips/ar231x/ar2315.c
+++ b/arch/mips/ar231x/ar2315.c +++ b/arch/mips/ar231x/ar2315.c
@@ -61,6 +61,27 @@ static inline void ar2315_gpio_irq(void) @@ -63,6 +63,27 @@ static inline void ar2315_gpio_irq(void)
do_IRQ(AR531X_GPIO_IRQ_BASE + fls(pend) - 1); do_IRQ(AR531X_GPIO_IRQ_BASE + bit);
} }
+#ifdef CONFIG_ATHEROS_AR2315_PCI +#ifdef CONFIG_ATHEROS_AR2315_PCI
@ -285,7 +285,7 @@
/* /*
* Called when an interrupt is received, this function * 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); do_IRQ(AR2315_IRQ_WLAN0_INTRS);
else if (pending & CAUSEF_IP4) else if (pending & CAUSEF_IP4)
do_IRQ(AR2315_IRQ_ENET0_INTRS); do_IRQ(AR2315_IRQ_ENET0_INTRS);