+}
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar231x/ar231x_platform.h
-@@ -0,0 +1,83 @@
+@@ -0,0 +1,84 @@
+#ifndef __AR531X_PLATFORM_H
+#define __AR531X_PLATFORM_H
+
+ * Platform device information for the Ethernet MAC
+ */
+struct ar231x_eth {
-+ u32 reset_base;
++ void (*reset_set)(u32);
++ void (*reset_clear)(u32);
+ u32 reset_mac;
+ u32 reset_phy;
+ u32 phy_base;
+#endif /* __ASM_MIPS_MACH_ATHEROS_WAR_H */
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar231x/ar2315_regs.h
-@@ -0,0 +1,597 @@
+@@ -0,0 +1,614 @@
+/*
+ * Register definitions for AR2315+
+ *
+#define AR2315_IRQ_LCBUS_PCI (MIPS_CPU_IRQ_BASE+5) /* C0_CAUSE: 0x2000 */
+#define AR2315_IRQ_WLAN0_POLL (MIPS_CPU_IRQ_BASE+6) /* C0_CAUSE: 0x4000 */
+
++
++/*
++ * Miscellaneous interrupts, which share IP2.
++ */
++#define AR2315_MISC_IRQ_NONE (AR531X_MISC_IRQ_BASE+0)
++#define AR2315_MISC_IRQ_UART0 (AR531X_MISC_IRQ_BASE+1)
++#define AR2315_MISC_IRQ_I2C_RSVD (AR531X_MISC_IRQ_BASE+2)
++#define AR2315_MISC_IRQ_SPI (AR531X_MISC_IRQ_BASE+3)
++#define AR2315_MISC_IRQ_AHB (AR531X_MISC_IRQ_BASE+4)
++#define AR2315_MISC_IRQ_APB (AR531X_MISC_IRQ_BASE+5)
++#define AR2315_MISC_IRQ_TIMER (AR531X_MISC_IRQ_BASE+6)
++#define AR2315_MISC_IRQ_GPIO (AR531X_MISC_IRQ_BASE+7)
++#define AR2315_MISC_IRQ_WATCHDOG (AR531X_MISC_IRQ_BASE+8)
++#define AR2315_MISC_IRQ_IR_RSVD (AR531X_MISC_IRQ_BASE+9)
++#define AR2315_MISC_IRQ_COUNT 10
++
++
+/*
+ * Address map
+ */
+ */
+#define AR2315_GPIO_DI (AR2315_DSLBASE + 0x0088)
+#define AR2315_GPIO_DO (AR2315_DSLBASE + 0x0090)
-+#define AR2315_GPIO_CR (AR2315_DSLBASE + 0x0098)
++#define AR2315_GPIO_DIR (AR2315_DSLBASE + 0x0098)
+#define AR2315_GPIO_INT (AR2315_DSLBASE + 0x00a0)
+
-+#define AR2315_GPIO_CR_M(x) (1 << (x)) /* mask for i/o */
-+#define AR2315_GPIO_CR_O(x) (1 << (x)) /* output */
-+#define AR2315_GPIO_CR_I(x) (0) /* input */
++#define AR2315_GPIO_DIR_M(x) (1 << (x)) /* mask for i/o */
++#define AR2315_GPIO_DIR_O(x) (1 << (x)) /* output */
++#define AR2315_GPIO_DIR_I(x) (0) /* input */
+
+#define AR2315_GPIO_INT_S(x) (x) /* interrupt enable */
+#define AR2315_GPIO_INT_M (0x3F) /* mask for int */
+#endif /* __AR2315_REG_H */
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar231x/ar5312_regs.h
-@@ -0,0 +1,233 @@
+@@ -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
+#define AR5312_IRQ_MISC_INTRS (MIPS_CPU_IRQ_BASE+6) /* C0_CAUSE: 0x4000 */
+
+
++/*
++ * Miscellaneous interrupts, which share IP6.
++ */
++#define AR531X_MISC_IRQ_NONE (AR531X_MISC_IRQ_BASE+0)
++#define AR531X_MISC_IRQ_TIMER (AR531X_MISC_IRQ_BASE+1)
++#define AR531X_MISC_IRQ_AHB_PROC (AR531X_MISC_IRQ_BASE+2)
++#define AR531X_MISC_IRQ_AHB_DMA (AR531X_MISC_IRQ_BASE+3)
++#define AR531X_MISC_IRQ_GPIO (AR531X_MISC_IRQ_BASE+4)
++#define AR531X_MISC_IRQ_UART0 (AR531X_MISC_IRQ_BASE+5)
++#define AR531X_MISC_IRQ_UART0_DMA (AR531X_MISC_IRQ_BASE+6)
++#define AR531X_MISC_IRQ_WATCHDOG (AR531X_MISC_IRQ_BASE+7)
++#define AR531X_MISC_IRQ_LOCAL (AR531X_MISC_IRQ_BASE+8)
++#define AR531X_MISC_IRQ_SPI (AR531X_MISC_IRQ_BASE+9)
++#define AR531X_MISC_IRQ_COUNT 10
++
++
+/* Address Map */
+#define AR531X_WLAN0 0x18000000
+#define AR531X_WLAN1 0x18500000
+
--- /dev/null
+++ b/arch/mips/ar231x/ar5312.c
-@@ -0,0 +1,582 @@
+@@ -0,0 +1,540 @@
+/*
+ * 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
+#include "devices.h"
+#include "ar5312.h"
+
-+static void
-+ar5312_misc_irq_dispatch(void)
++static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ unsigned int ar231x_misc_intrs = ar231x_read_reg(AR531X_ISR) &
+ ar231x_read_reg(AR531X_IMR);
+ else if (pending & CAUSEF_IP5)
+ do_IRQ(AR5312_IRQ_WLAN1_INTRS);
+ else if (pending & CAUSEF_IP6)
-+ ar5312_misc_irq_dispatch();
++ do_IRQ(AR5312_IRQ_MISC_INTRS);
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(AR531X_IRQ_CPU_CLOCK);
+}
+
+/* Enable the specified AR531X_MISC_IRQ interrupt */
+static void
-+ar5312_misc_intr_enable(struct irq_data *d)
++ar5312_misc_irq_unmask(struct irq_data *d)
+{
+ unsigned int imr;
+
+
+/* Disable the specified AR531X_MISC_IRQ interrupt */
+static void
-+ar5312_misc_intr_disable(struct irq_data *d)
++ar5312_misc_irq_mask(struct irq_data *d)
+{
+ unsigned int imr;
+
+ ar231x_read_reg(AR531X_IMR); /* flush write buffer */
+}
+
-+static struct irq_chip ar5312_misc_intr_controller = {
-+ .irq_mask = ar5312_misc_intr_disable,
-+ .irq_unmask = ar5312_misc_intr_enable,
++static struct irq_chip ar5312_misc_irq_chip = {
++ .name = "AR5312-MISC",
++ .irq_unmask = ar5312_misc_irq_unmask,
++ .irq_mask = ar5312_misc_irq_mask,
+};
+
+
+};
+
+
-+static struct irqaction cascade = {
-+ .handler = no_action,
-+ .name = "cascade",
-+};
-+
+void __init ar5312_irq_init(void)
+{
+ int i;
+ ar231x_irq_dispatch = ar5312_irq_dispatch;
+ for (i = 0; i < AR531X_MISC_IRQ_COUNT; i++) {
+ int irq = AR531X_MISC_IRQ_BASE + i;
-+ irq_set_chip_and_handler(irq, &ar5312_misc_intr_controller,
-+ handle_level_irq);
++ irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip,
++ handle_level_irq);
+ }
+ setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar5312_ahb_proc_interrupt);
-+ setup_irq(AR5312_IRQ_MISC_INTRS, &cascade);
-+}
-+
-+static u32
-+ar5312_gpio_set_output(u32 mask, u32 val)
-+{
-+ u32 reg;
-+
-+ reg = ar231x_read_reg(AR531X_GPIO_CR);
-+ reg |= mask;
-+ reg &= ~val;
-+ ar231x_write_reg(AR531X_GPIO_CR, reg);
-+ return reg;
-+}
-+
-+static u32
-+ar5312_gpio_get(u32 valid_mask)
-+{
-+ u32 reg;
-+ reg = ar231x_read_reg(AR531X_GPIO_DI);
-+ reg &= valid_mask;
-+ return reg;
-+}
-+
-+static u32
-+ar5312_gpio_set(u32 mask, u32 value)
-+{
-+ u32 reg;
-+ reg = ar231x_read_reg(AR531X_GPIO_DO);
-+ reg &= ~mask;
-+ reg |= value;
-+ ar231x_write_reg(AR531X_GPIO_DO, reg);
-+ return reg;
++ irq_set_chained_handler(AR5312_IRQ_MISC_INTRS, ar5312_misc_irq_handler);
+}
+
+/*
-+ * gpiolib implementations. Original mask based methods preserved
++ * gpiolib implementations
+ */
+static int
+ar5312_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ u32 rett;
-+ if (!(gpch->valid_mask & mask))
-+ return 0;
-+ rett = ar5312_gpio_get(gpch->valid_mask);
-+ return !!(rett & mask);
++ return (ar231x_read_reg(AR531X_GPIO_DI) >> gpio) & 1;
+}
+
+static void
+ar5312_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ if (!(gpch->valid_mask & mask))
-+ return;
-+ ar5312_gpio_set(mask, (!!value) * mask);
++ u32 reg = ar231x_read_reg(AR531X_GPIO_DO);
++ reg = value ? reg | (1 << gpio) : reg & ~(1 << gpio);
++ ar231x_write_reg(AR531X_GPIO_DO, reg);
+}
+
+static int
+ar5312_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ if (!(gpch->valid_mask & mask))
-+ return -ENXIO;
-+ ar5312_gpio_set_output(mask, 0);
++ ar231x_mask_reg(AR531X_GPIO_CR, 0, 1 << gpio);
+ return 0;
+}
++
+static int
+ar5312_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ if (!(gpch->valid_mask & mask))
-+ return -ENXIO;
-+ ar5312_gpio_set_output(mask, mask);
-+ ar5312_gpio_set(mask, (!!value) * mask);
++ ar231x_mask_reg(AR531X_GPIO_CR, 1 << gpio, 0);
++ ar5312_gpio_set_value(chip, gpio, value);
+ return 0;
+}
+
-+static struct ar231x_gpio_chip ar5312_gpio_chip = {
-+ .valid_mask = (1 << 22) - 1,
-+ .chip = {
-+ .label = "ar5312-gpio",
-+ .direction_input = ar5312_gpio_direction_input,
-+ .direction_output = ar5312_gpio_direction_output,
-+ .set = ar5312_gpio_set_value,
-+ .get = ar5312_gpio_get_value,
-+ .base = 0,
-+ .ngpio = AR531X_GPIO_IRQ_COUNT, /* 22 */
-+ }
++static struct gpio_chip ar5312_gpio_chip = {
++ .label = "ar5312-gpio",
++ .direction_input = ar5312_gpio_direction_input,
++ .direction_output = ar5312_gpio_direction_output,
++ .set = ar5312_gpio_set_value,
++ .get = ar5312_gpio_get_value,
++ .base = 0,
++ .ngpio = AR531X_NUM_GPIO, /* 8 */
+};
+
+/* end of gpiolib */
+
++static void ar5312_device_reset_set(u32 mask)
++{
++ u32 val;
++
++ val = ar231x_read_reg(AR531X_RESET);
++ ar231x_write_reg(AR531X_RESET, val | mask);
++}
++
++static void ar5312_device_reset_clear(u32 mask)
++{
++ u32 val;
++
++ val = ar231x_read_reg(AR531X_RESET);
++ ar231x_write_reg(AR531X_RESET, val & ~mask);
++}
++
+static struct physmap_flash_data ar5312_flash_data = {
+ .width = 2,
+};
+};
+
+static struct ar231x_eth ar5312_eth0_data = {
-+ .reset_base = AR531X_RESET,
++ .reset_set = ar5312_device_reset_set,
++ .reset_clear = ar5312_device_reset_clear,
+ .reset_mac = AR531X_RESET_ENET0,
+ .reset_phy = AR531X_RESET_EPHY0,
-+ .phy_base = KSEG1ADDR(AR531X_ENET0),
++ .phy_base = AR531X_ENET0,
+ .config = &ar231x_board,
+};
+
+static struct ar231x_eth ar5312_eth1_data = {
-+ .reset_base = AR531X_RESET,
++ .reset_set = ar5312_device_reset_set,
++ .reset_clear = ar5312_device_reset_clear,
+ .reset_mac = AR531X_RESET_ENET1,
+ .reset_phy = AR531X_RESET_EPHY1,
-+ .phy_base = KSEG1ADDR(AR531X_ENET1),
++ .phy_base = AR531X_ENET1,
+ .config = &ar231x_board,
+};
+
+ switch (ar231x_devtype) {
+ case DEV_TYPE_AR5312:
+ ar5312_eth0_data.macaddr = config->enet0_mac;
-+ ar231x_add_ethernet(0, KSEG1ADDR(AR531X_ENET0),
-+ AR5312_IRQ_ENET0_INTRS, &ar5312_eth0_data);
++ ar231x_add_ethernet(0, AR531X_ENET0, AR5312_IRQ_ENET0_INTRS,
++ &ar5312_eth0_data);
+
+ ar5312_eth1_data.macaddr = config->enet1_mac;
-+ ar231x_add_ethernet(1, KSEG1ADDR(AR531X_ENET1),
-+ AR5312_IRQ_ENET1_INTRS, &ar5312_eth1_data);
++ ar231x_add_ethernet(1, AR531X_ENET1, AR5312_IRQ_ENET1_INTRS,
++ &ar5312_eth1_data);
+
+ if (!ar231x_board.radio)
+ return 0;
+ ar5312_eth1_data.phy_base = ar5312_eth0_data.phy_base;
+ ar5312_eth1_data.reset_phy = ar5312_eth0_data.reset_phy;
+ ar5312_eth1_data.macaddr = config->enet0_mac;
-+ ar231x_add_ethernet(0, KSEG1ADDR(AR531X_ENET1),
++ ar231x_add_ethernet(0, AR531X_ENET1,
+ AR5312_IRQ_ENET1_INTRS, &ar5312_eth1_data);
+
+ if (!ar231x_board.radio)
+ mips_hpt_frequency = ar5312_cpu_frequency() / 2;
+}
+
-+int __init
++static int __init
+ar5312_gpio_init(void)
+{
+ int ret;
-+ struct ar231x_gpio_chip *gpch;
-+ gpch = &ar5312_gpio_chip;
-+ ret = gpiochip_add(&gpch->chip);
++ ret = gpiochip_add(&ar5312_gpio_chip);
+ if (ret) {
-+ pr_err("%s: failed to add gpiochip\n", gpch->chip.label);
++ pr_err("%s: failed to add gpiochip\n", ar5312_gpio_chip.label);
+ return ret;
+ }
-+ pr_info("%s: registered %d GPIOs\n", gpch->chip.label,
-+ gpch->chip.ngpio);
++ pr_info("%s: registered %d GPIOs\n", ar5312_gpio_chip.label,
++ ar5312_gpio_chip.ngpio);
+ return ret;
+}
+
+ ar231x_write_reg(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
+
+ _machine_restart = ar5312_restart;
-+ ar231x_serial_setup(KSEG1ADDR(AR531X_UART0), ar5312_sys_frequency());
++ ar231x_serial_setup(KSEG1ADDR(AR531X_UART0), AR531X_MISC_IRQ_UART0,
++ ar5312_sys_frequency());
+}
+
--- /dev/null
+++ b/arch/mips/ar231x/ar2315.c
-@@ -0,0 +1,624 @@
+@@ -0,0 +1,557 @@
+/*
+ * 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 u32 gpiointmask, gpiointval;
+
-+static inline void ar2315_gpio_irq(void)
++static void ar2315_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pend;
+ int bit = -1;
+ ar231x_write_reg(AR2315_ISR, AR2315_ISR_GPIO);
+
+ /* Enable interrupt with edge detection */
-+ if ((ar231x_read_reg(AR2315_GPIO_CR) & AR2315_GPIO_CR_M(bit)) !=
-+ AR2315_GPIO_CR_I(bit))
++ if ((ar231x_read_reg(AR2315_GPIO_DIR) & AR2315_GPIO_DIR_M(bit)) !=
++ AR2315_GPIO_DIR_I(bit))
+ return;
+
+ if (bit >= 0)
+ do_IRQ(AR531X_GPIO_IRQ_BASE + bit);
+}
+
++static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc)
++{
++ unsigned int misc_intr = ar231x_read_reg(AR2315_ISR) &
++ ar231x_read_reg(AR2315_IMR);
++
++ if (misc_intr & AR2315_ISR_SPI)
++ do_IRQ(AR2315_MISC_IRQ_SPI);
++ else if (misc_intr & AR2315_ISR_TIMER)
++ do_IRQ(AR2315_MISC_IRQ_TIMER);
++ else if (misc_intr & AR2315_ISR_AHB)
++ do_IRQ(AR2315_MISC_IRQ_AHB);
++ else if (misc_intr & AR2315_ISR_GPIO)
++ do_IRQ(AR2315_MISC_IRQ_GPIO);
++ else if (misc_intr & AR2315_ISR_UART0)
++ do_IRQ(AR2315_MISC_IRQ_UART0);
++ else if (misc_intr & AR2315_ISR_WD) {
++ ar231x_write_reg(AR2315_ISR, AR2315_ISR_WD);
++ do_IRQ(AR2315_MISC_IRQ_WATCHDOG);
++ } else
++ do_IRQ(AR2315_MISC_IRQ_NONE);
++}
+
+/*
+ * Called when an interrupt is received, this function
+ do_IRQ(AR2315_IRQ_WLAN0_INTRS);
+ else if (pending & CAUSEF_IP4)
+ do_IRQ(AR2315_IRQ_ENET0_INTRS);
-+ else if (pending & CAUSEF_IP2) {
-+ unsigned int misc_intr = ar231x_read_reg(AR2315_ISR) &
-+ ar231x_read_reg(AR2315_IMR);
-+
-+ if (misc_intr & AR2315_ISR_SPI)
-+ do_IRQ(AR531X_MISC_IRQ_SPI);
-+ else if (misc_intr & AR2315_ISR_TIMER)
-+ do_IRQ(AR531X_MISC_IRQ_TIMER);
-+ else if (misc_intr & AR2315_ISR_AHB)
-+ do_IRQ(AR531X_MISC_IRQ_AHB_PROC);
-+ else if (misc_intr & AR2315_ISR_GPIO)
-+ ar2315_gpio_irq();
-+ else if (misc_intr & AR2315_ISR_UART0)
-+ do_IRQ(AR531X_MISC_IRQ_UART0);
-+ else if (misc_intr & AR2315_ISR_WD) {
-+ ar231x_write_reg(AR2315_ISR, AR2315_ISR_WD);
-+ do_IRQ(AR531X_MISC_IRQ_WATCHDOG);
-+ } else
-+ do_IRQ(AR531X_MISC_IRQ_NONE);
-+ } else if (pending & CAUSEF_IP7)
++ else if (pending & CAUSEF_IP2)
++ do_IRQ(AR2315_IRQ_MISC_INTRS);
++ else if (pending & CAUSEF_IP7)
+ do_IRQ(AR531X_IRQ_CPU_CLOCK);
+}
+
+ ar231x_write_reg(AR2315_GPIO_INT, reg);
+}
+
-+static void ar2315_gpio_intr_enable(struct irq_data *d)
++static void ar2315_gpio_irq_unmask(struct irq_data *d)
+{
+ unsigned int gpio = d->irq - AR531X_GPIO_IRQ_BASE;
+
+ /* Enable interrupt with edge detection */
-+ if ((ar231x_read_reg(AR2315_GPIO_CR) & AR2315_GPIO_CR_M(gpio)) !=
-+ AR2315_GPIO_CR_I(gpio))
++ if ((ar231x_read_reg(AR2315_GPIO_DIR) & AR2315_GPIO_DIR_M(gpio)) !=
++ AR2315_GPIO_DIR_I(gpio))
+ return;
+
+ gpiointmask |= (1 << gpio);
+ ar2315_set_gpiointmask(gpio, 3);
+}
+
-+static void ar2315_gpio_intr_disable(struct irq_data *d)
++static void ar2315_gpio_irq_mask(struct irq_data *d)
+{
+ unsigned int gpio = d->irq - AR531X_GPIO_IRQ_BASE;
+
+ ar2315_set_gpiointmask(gpio, 0);
+}
+
-+static struct irq_chip ar2315_gpio_intr_controller = {
-+ .irq_mask = ar2315_gpio_intr_disable,
-+ .irq_unmask = ar2315_gpio_intr_enable,
++static struct irq_chip ar2315_gpio_irq_chip = {
++ .name = "AR2315-GPIO",
++ .irq_unmask = ar2315_gpio_irq_unmask,
++ .irq_mask = ar2315_gpio_irq_mask,
+};
+
+static void
-+ar2315_misc_intr_enable(struct irq_data *d)
++ar2315_misc_irq_unmask(struct irq_data *d)
+{
+ unsigned int imr;
+
+ imr = ar231x_read_reg(AR2315_IMR);
-+ switch (d->irq) {
-+ case AR531X_MISC_IRQ_SPI:
-+ imr |= AR2315_ISR_SPI;
-+ break;
-+ case AR531X_MISC_IRQ_TIMER:
-+ imr |= AR2315_ISR_TIMER;
-+ break;
-+ case AR531X_MISC_IRQ_AHB_PROC:
-+ imr |= AR2315_ISR_AHB;
-+ break;
-+ case AR531X_MISC_IRQ_GPIO:
-+ imr |= AR2315_ISR_GPIO;
-+ break;
-+ case AR531X_MISC_IRQ_UART0:
-+ imr |= AR2315_ISR_UART0;
-+ break;
-+ case AR531X_MISC_IRQ_WATCHDOG:
-+ imr |= AR2315_ISR_WD;
-+ break;
-+ default:
-+ break;
-+ }
++ imr |= 1 << (d->irq - AR531X_MISC_IRQ_BASE - 1);
+ ar231x_write_reg(AR2315_IMR, imr);
+}
+
+static void
-+ar2315_misc_intr_disable(struct irq_data *d)
++ar2315_misc_irq_mask(struct irq_data *d)
+{
+ unsigned int imr;
+
+ imr = ar231x_read_reg(AR2315_IMR);
-+ switch (d->irq) {
-+ case AR531X_MISC_IRQ_SPI:
-+ imr &= ~AR2315_ISR_SPI;
-+ break;
-+ case AR531X_MISC_IRQ_TIMER:
-+ imr &= ~AR2315_ISR_TIMER;
-+ break;
-+ case AR531X_MISC_IRQ_AHB_PROC:
-+ imr &= ~AR2315_ISR_AHB;
-+ break;
-+ case AR531X_MISC_IRQ_GPIO:
-+ imr &= ~AR2315_ISR_GPIO;
-+ break;
-+ case AR531X_MISC_IRQ_UART0:
-+ imr &= ~AR2315_ISR_UART0;
-+ break;
-+ case AR531X_MISC_IRQ_WATCHDOG:
-+ imr &= ~AR2315_ISR_WD;
-+ break;
-+ default:
-+ break;
-+ }
++ imr &= ~(1 << (d->irq - AR531X_MISC_IRQ_BASE - 1));
+ ar231x_write_reg(AR2315_IMR, imr);
+}
+
-+static struct irq_chip ar2315_misc_intr_controller = {
-+ .irq_mask = ar2315_misc_intr_disable,
-+ .irq_unmask = ar2315_misc_intr_enable,
++static struct irq_chip ar2315_misc_irq_chip = {
++ .name = "AR2315-MISC",
++ .irq_unmask = ar2315_misc_irq_unmask,
++ .irq_mask = ar2315_misc_irq_mask,
+};
+
+static irqreturn_t ar2315_ahb_proc_handler(int cpl, void *dev_id)
+ .name = "ar2315_ahb_proc_interrupt",
+};
+
-+static struct irqaction cascade = {
-+ .handler = no_action,
-+ .name = "cascade",
-+};
-+
+void
+ar2315_irq_init(void)
+{
+
+ ar231x_irq_dispatch = ar2315_irq_dispatch;
+ gpiointval = ar231x_read_reg(AR2315_GPIO_DI);
-+ for (i = 0; i < AR531X_MISC_IRQ_COUNT; i++) {
++ for (i = 0; i < AR2315_MISC_IRQ_COUNT; i++) {
+ int irq = AR531X_MISC_IRQ_BASE + i;
-+ irq_set_chip_and_handler(irq, &ar2315_misc_intr_controller,
++ irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip,
+ handle_level_irq);
+ }
-+ for (i = 0; i < AR531X_GPIO_IRQ_COUNT; i++) {
++ for (i = 0; i < AR2315_NUM_GPIO; i++) {
+ int irq = AR531X_GPIO_IRQ_BASE + i;
-+ irq_set_chip_and_handler(irq, &ar2315_gpio_intr_controller,
++ irq_set_chip_and_handler(irq, &ar2315_gpio_irq_chip,
+ handle_level_irq);
+ }
-+ setup_irq(AR531X_MISC_IRQ_GPIO, &cascade);
-+ setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar2315_ahb_proc_interrupt);
-+ setup_irq(AR2315_IRQ_MISC_INTRS, &cascade);
-+}
-+
-+static u32
-+ar2315_gpio_set_output(u32 mask, u32 val)
-+{
-+ u32 reg;
-+
-+ reg = ar231x_read_reg(AR2315_GPIO_CR);
-+ reg &= ~mask;
-+ reg |= val;
-+ ar231x_write_reg(AR2315_GPIO_CR, reg);
-+ return reg;
-+}
-+
-+static u32
-+ar2315_gpio_get(u32 valid_mask)
-+{
-+ u32 reg;
-+ reg = ar231x_read_reg(AR2315_GPIO_DI);
-+ reg &= valid_mask;
-+ return reg;
-+}
-+
-+static u32
-+ar2315_gpio_set(u32 mask, u32 value)
-+{
-+ u32 reg;
-+ reg = ar231x_read_reg(AR2315_GPIO_DO);
-+ reg &= ~mask;
-+ reg |= value;
-+ ar231x_write_reg(AR2315_GPIO_DO, reg);
-+ return reg;
++ irq_set_chained_handler(AR2315_MISC_IRQ_GPIO, ar2315_gpio_irq_handler);
++ setup_irq(AR2315_MISC_IRQ_AHB, &ar2315_ahb_proc_interrupt);
++ irq_set_chained_handler(AR2315_IRQ_MISC_INTRS, ar2315_misc_irq_handler);
+}
+
+/*
-+ * gpiolib implementation. Original legacy mask based methods
-+ * preserved for now.
++ * gpiolib implementation
+ */
+static int
+ar2315_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ u32 rett;
-+ if (!(gpch->valid_mask & mask))
-+ return 0;
-+ rett = ar2315_gpio_get(gpch->valid_mask); /* legacy code */
-+ return !!(rett & mask);
++ return (ar231x_read_reg(AR2315_GPIO_DI) >> gpio) & 1;
+}
+
+static void
+ar2315_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ if (!(gpch->valid_mask & mask))
-+ return;
-+ ar2315_gpio_set(mask, (!!value) * mask); /* legacy */
++ u32 reg = ar231x_read_reg(AR2315_GPIO_DO);
++ reg = value ? reg | (1 << gpio) : reg & ~(1 << gpio);
++ ar231x_write_reg(AR2315_GPIO_DO, reg);
+}
+
+static int
+ar2315_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ if (!(gpch->valid_mask & mask))
-+ return -ENXIO;
-+ ar2315_gpio_set_output(mask, 0); /* legacy */
++ ar231x_mask_reg(AR2315_GPIO_DIR, 1 << gpio, 0);
+ return 0;
+}
+
+static int
+ar2315_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
-+ struct ar231x_gpio_chip *gpch =
-+ container_of(chip, struct ar231x_gpio_chip, chip);
-+ u32 mask = 1 << gpio;
-+ if (!(gpch->valid_mask & mask))
-+ return -ENXIO;
-+ ar2315_gpio_set_output(mask, mask); /* both legacy */
-+ ar2315_gpio_set(mask, (!!value) * mask);
++ ar231x_mask_reg(AR2315_GPIO_DIR, 0, 1 << gpio);
++ ar2315_gpio_set_value(chip, gpio, value);
+ return 0;
+}
+
-+static struct ar231x_gpio_chip ar2315_gpio_chip = {
-+ .valid_mask = (1 << 22) - 1,
-+ .chip = {
-+ .label = "ar2315-gpio",
-+ .direction_input = ar2315_gpio_direction_input,
-+ .direction_output = ar2315_gpio_direction_output,
-+ .set = ar2315_gpio_set_value,
-+ .get = ar2315_gpio_get_value,
-+ .base = 0,
-+ .ngpio = AR531X_GPIO_IRQ_COUNT, /* 22 */
-+ }
++static struct gpio_chip ar2315_gpio_chip = {
++ .label = "ar2315-gpio",
++ .direction_input = ar2315_gpio_direction_input,
++ .direction_output = ar2315_gpio_direction_output,
++ .set = ar2315_gpio_set_value,
++ .get = ar2315_gpio_get_value,
++ .base = 0,
++ .ngpio = AR2315_NUM_GPIO, /* 22 */
+};
+
+/* end of gpiolib */
+
++static void ar2315_device_reset_set(u32 mask)
++{
++ u32 val;
++
++ val = ar231x_read_reg(AR2315_RESET);
++ ar231x_write_reg(AR2315_RESET, val | mask);
++}
++
++static void ar2315_device_reset_clear(u32 mask)
++{
++ u32 val;
++
++ val = ar231x_read_reg(AR2315_RESET);
++ ar231x_write_reg(AR2315_RESET, val & ~mask);
++}
+
+static struct ar231x_eth ar2315_eth_data = {
-+ .reset_base = AR2315_RESET,
++ .reset_set = ar2315_device_reset_set,
++ .reset_clear = ar2315_device_reset_clear,
+ .reset_mac = AR2315_RESET_ENET0,
+ .reset_phy = AR2315_RESET_EPHY0,
-+ .phy_base = KSEG1ADDR(AR2315_ENET0),
++ .phy_base = AR2315_ENET0,
+ .config = &ar231x_board,
+};
+
+ .num_resources = ARRAY_SIZE(ar2315_spiflash_res)
+};
+
++static struct resource ar2315_wdt_res[] = {
++ {
++ .flags = IORESOURCE_MEM,
++ .start = AR2315_WD,
++ .end = AR2315_WD + 8 - 1,
++ },
++ {
++ .flags = IORESOURCE_IRQ,
++ .start = AR2315_MISC_IRQ_WATCHDOG,
++ .end = AR2315_MISC_IRQ_WATCHDOG,
++ }
++};
++
+static struct platform_device ar2315_wdt = {
+ .id = 0,
+ .name = "ar2315-wdt",
++ .resource = ar2315_wdt_res,
++ .num_resources = ARRAY_SIZE(ar2315_wdt_res)
+};
+
+/*
+ ar2315_init_gpio_leds();
+ platform_device_register(&ar2315_wdt);
+ platform_device_register(&ar2315_spiflash);
-+ ar231x_add_ethernet(0, KSEG1ADDR(AR2315_ENET0), AR2315_IRQ_ENET0_INTRS,
-+ &ar2315_eth_data);
++ ar231x_add_ethernet(0, AR2315_ENET0, AR2315_IRQ_ENET0_INTRS,
++ &ar2315_eth_data);
+ ar231x_add_wmac(0, AR2315_WLAN0, AR2315_IRQ_WLAN0_INTRS);
+
+ return 0;
+ mips_hpt_frequency = ar2315_cpu_frequency() / 2;
+}
+
-+int __init
++static int __init
+ar2315_gpio_init(void)
+{
+ int ret;
-+ struct ar231x_gpio_chip *gpch;
-+ gpch = &ar2315_gpio_chip;
-+ ret = gpiochip_add(&gpch->chip);
++ ret = gpiochip_add(&ar2315_gpio_chip);
+ if (ret) {
-+ pr_err("%s: failed to add gpiochip\n", gpch->chip.label);
++ pr_err("%s: failed to add gpiochip\n", ar2315_gpio_chip.label);
+ return ret;
+ }
-+ pr_info("%s: registered %d GPIOs\n", gpch->chip.label,
-+ gpch->chip.ngpio);
++ pr_info("%s: registered %d GPIOs\n", ar2315_gpio_chip.label,
++ ar2315_gpio_chip.ngpio);
+ return ret;
+}
+
+ ar231x_write_reg(AR2315_WDC, AR2315_WDC_IGNORE_EXPIRATION);
+
+ _machine_restart = ar2315_restart;
-+ ar231x_serial_setup(KSEG1ADDR(AR2315_UART0), ar2315_apb_frequency());
++ ar231x_serial_setup(KSEG1ADDR(AR2315_UART0), AR2315_MISC_IRQ_UART0,
++ ar2315_apb_frequency());
+}
--- /dev/null
+++ b/arch/mips/ar231x/ar2315.h
+#endif
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar231x/ar231x.h
-@@ -0,0 +1,57 @@
+@@ -0,0 +1,43 @@
+#ifndef __AR531X_H
+#define __AR531X_H
+
+#define AR531X_IRQ_NONE (MIPS_CPU_IRQ_BASE+0)
+#define AR531X_IRQ_CPU_CLOCK (MIPS_CPU_IRQ_BASE+7) /* C0_CAUSE: 0x8000 */
+
-+/* Miscellaneous interrupts, which share IP6 */
-+#define AR531X_MISC_IRQ_NONE (AR531X_MISC_IRQ_BASE+0)
-+#define AR531X_MISC_IRQ_TIMER (AR531X_MISC_IRQ_BASE+1)
-+#define AR531X_MISC_IRQ_AHB_PROC (AR531X_MISC_IRQ_BASE+2)
-+#define AR531X_MISC_IRQ_AHB_DMA (AR531X_MISC_IRQ_BASE+3)
-+#define AR531X_MISC_IRQ_GPIO (AR531X_MISC_IRQ_BASE+4)
-+#define AR531X_MISC_IRQ_UART0 (AR531X_MISC_IRQ_BASE+5)
-+#define AR531X_MISC_IRQ_UART0_DMA (AR531X_MISC_IRQ_BASE+6)
-+#define AR531X_MISC_IRQ_WATCHDOG (AR531X_MISC_IRQ_BASE+7)
-+#define AR531X_MISC_IRQ_LOCAL (AR531X_MISC_IRQ_BASE+8)
-+#define AR531X_MISC_IRQ_SPI (AR531X_MISC_IRQ_BASE+9)
-+#define AR531X_MISC_IRQ_COUNT 10
-+
-+/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
++/* GPIO Interrupts, share ARXXXX_MISC_IRQ_GPIO */
+#define AR531X_GPIO_IRQ_NONE (AR531X_GPIO_IRQ_BASE+0)
+#define AR531X_GPIO_IRQ(n) (AR531X_GPIO_IRQ_BASE+n)
-+#define AR531X_GPIO_IRQ_COUNT 22
+
+static inline u32
+ar231x_read_reg(u32 reg)
+#endif
--- /dev/null
+++ b/arch/mips/ar231x/devices.h
-@@ -0,0 +1,42 @@
+@@ -0,0 +1,37 @@
+#ifndef __AR231X_DEVICES_H
+#define __AR231X_DEVICES_H
-+#include <linux/gpio.h>
+
+enum {
+ /* handled by ar5312.c */
+extern asmlinkage void (*ar231x_irq_dispatch)(void);
+
+extern int ar231x_find_config(u8 *flash_limit);
-+extern void ar231x_serial_setup(u32 mapbase, unsigned int uartclk);
++extern void ar231x_serial_setup(u32 mapbase, int irq, unsigned int uartclk);
+extern int ar231x_add_wmac(int nr, u32 base, int irq);
+extern int ar231x_add_ethernet(int nr, u32 base, int irq, void *pdata);
+
+ return !is_2315();
+}
+
-+struct ar231x_gpio_chip {
-+ u32 valid_mask;
-+ struct gpio_chip chip;
-+};
+#endif
--- /dev/null
+++ b/arch/mips/ar231x/devices.c
+}
+
+void __init
-+ar231x_serial_setup(u32 mapbase, unsigned int uartclk)
++ar231x_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
+{
+ struct uart_port s;
+
+
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+ s.iotype = UPIO_MEM;
-+ s.irq = AR531X_MISC_IRQ_UART0;
++ s.irq = irq;
+ s.regshift = 2;
+ s.mapbase = mapbase;
+ s.uartclk = uartclk;