|
|
|
@ -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
|
|
|
|
|