+obj-$(CONFIG_ATHEROS_AR2315) += ar2315.o
--- /dev/null
+++ b/arch/mips/ar231x/board.c
-@@ -0,0 +1,247 @@
+@@ -0,0 +1,249 @@
+/*
+ * 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
+ config = ar231x_board.config;
+ if (!memcmp(config->enet0_mac, "\x00\x00\x00\x00\x00\x00", 6)) {
+ printk(KERN_INFO "Fixing up empty mac addresses\n");
++ random_ether_addr(config->wlan0_mac);
++ config->wlan0_mac[0] &= ~0x06;
+ random_ether_addr(config->enet0_mac);
+ random_ether_addr(config->enet1_mac);
+ }
+ .name = "leds-gpio",
+ .id = -1,
+ .dev.platform_data = (void *) &ar5312_led_data,
-+ .num_resources = 1,
+};
+#endif
+
+ if (!ar231x_board.radio)
+ return 0;
+
-+ if (*((u32 *) ar231x_board.radio) & AR531X_RADIO0_MASK)
++ if (*((u32 *) radio) & AR531X_RADIO0_MASK)
+ ar231x_add_wmac(0, AR531X_WLAN0,
+ AR5312_IRQ_WLAN0_INTRS);
+
+ break;
+ }
+
-+ if (*((u32 *) ar231x_board.radio) & AR531X_RADIO1_MASK)
++ if (*((u32 *) radio) & AR531X_RADIO1_MASK)
+ ar231x_add_wmac(1, AR531X_WLAN1,
+ AR5312_IRQ_WLAN1_INTRS);
+
+ if ((result = ar231x_read_reg(AR5312_SCRATCH)))
+ return result;
+
-+ devid = ar231x_board.devid;
++ devid = ar231x_read_reg(AR531X_REV);
+ devid &= AR531X_REV_MAJ;
+ devid >>= AR531X_REV_MAJ_S;
+ if (devid == AR531X_REV_MAJ_AR2313) {
+ if (!IS_5312())
+ return;
+
-+ devid = ar231x_read_reg(AR531X_REV);
-+ devid &= AR531X_REV_MAJ | AR531X_REV_MIN;
-+
+ /* Detect memory size */
+ memcfg = ar231x_read_reg(AR531X_MEM_CFG1);
+ bank0AC = (memcfg & MEM_CFG1_AC0) >> MEM_CFG1_AC0_S;
+ + (bank1AC ? (1 << (bank1AC+1)) : 0);
+ memsize <<= 20;
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
-+ ar231x_gpiodev = &ar5312_gpiodev;
++
++ devid = ar231x_read_reg(AR531X_REV);
++ devid >>= AR531X_REV_WMAC_MIN_S;
++ devid &= AR531X_REV_CHIP;
+ ar231x_board.devid = (u16) devid;
++ ar231x_gpiodev = &ar5312_gpiodev;
+}
+
+void __init
+
--- /dev/null
+++ b/arch/mips/ar231x/ar2315.c
-@@ -0,0 +1,663 @@
+@@ -0,0 +1,677 @@
+/*
+ * 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
+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;
++ pend &= ~(1 << 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);
++ 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);
+}
+
+
+{
+ 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);
+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);
+}
+
+{
+ 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
+{
+ int i;
+
++ if (!IS_2315())
++ return;
++
+ ar231x_irq_dispatch = ar2315_irq_dispatch;
+ gpiointval = ar231x_read_reg(AR2315_GPIO_DI);
+ for (i = 0; i < AR531X_MISC_IRQ_COUNT; i++) {
+void __init
+ar2315_time_init(void)
+{
++ if (!IS_2315())
++ return;
++
+ mips_hpt_frequency = ar2315_cpu_frequency() / 2;
+}
+
+static inline u32
+ar231x_read_reg(u32 reg)
+{
-+ return __raw_readl((u32 *) reg);
++ return __raw_readl((u32 *) KSEG1ADDR(reg));
+}
+
+static inline void
+ar231x_write_reg(u32 reg, u32 val)
+{
-+ __raw_writel(val, (u32 *)reg);
++ __raw_writel(val, (u32 *) KSEG1ADDR(reg));
+}
+
+static inline u32