atheros[uart]: pass only physical I/O mem address to 8250 driver
[openwrt/svn-archive/archive.git] / target / linux / atheros / patches-3.10 / 100-board.patch
index 28c93bee8bcc4c90200cb9bb6047e84101b53c9f..611d7ccf6000596ef109e49f805100bafaf9131e 100644 (file)
 + * 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;
 +      struct ar231x_board_config *config;
 +      char *macaddr;
 +};
 +#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,617 @@
 +/*
 + * 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_LOCAL            0x10400000      /* LOCAL BUS MMR */
 +#define AR2315_ENET0            0x10500000      /* ETHERNET MMR */
 +#define AR2315_DSLBASE          0x11000000      /* RESET CONTROL MMR */
-+#define AR2315_UART0            0x11100003      /* UART MMR */
++#define AR2315_UART0            0x11100000      /* UART MMR */
 +#define AR2315_SPI_MMR          0x11300000      /* SPI FLASH MMR */
 +#define AR2315_PCIEXT           0x80000000      /* pci external */
 +
++/* MII registers offset inside Ethernet MMR region */
++#define AR2315_ENET0_MII      (AR2315_ENET0 + 0x14)
++
 +/*
 + * Reset Register
 + */
 + */
 +#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,253 @@
 +/*
 + * 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
 +#define AR531X_SDRAMCTL         0x18300000
 +#define AR531X_FLASHCTL         0x18400000
 +#define AR531X_APBBASE                0x1c000000
++#define AR531X_UART0            0x1c000000      /* UART MMR */
 +#define AR531X_FLASH            0x1e000000
-+#define AR531X_UART0            0xbc000003      /* UART MMR */
 +
 +/*
 + * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
 +#define AR5212_AR5312_REV7      0x0057          /* AR5312 WMAC (AP30-040) */
 +#define AR5212_AR2313_REV8      0x0058          /* AR2313 WMAC (AP43-030) */
 +
++/* MII registers offset inside Ethernet MMR region */
++#define AR531X_ENET0_MII      (AR531X_ENET0 + 0x14)
++#define AR531X_ENET1_MII      (AR531X_ENET1 + 0x14)
++
 +/*
 + * AR531X_NUM_WMAC defines the number of Wireless MACs that\
 + * should be considered available.
 +
 --- /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),
 +      .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),
 +      .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, "eth0_mii",
++                                  AR531X_ENET0_MII, 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, "eth1_mii",
++                                  AR531X_ENET1_MII, AR5312_IRQ_ENET1_INTRS,
++                                  &ar5312_eth1_data);
 +
 +              if (!ar231x_board.radio)
 +                      return 0;
 +       */
 +      case DEV_TYPE_AR2312:
 +      case DEV_TYPE_AR2313:
-+              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),
-+                      AR5312_IRQ_ENET1_INTRS, &ar5312_eth1_data);
++              ar231x_add_ethernet(1, AR531X_ENET1, "eth0_mii",
++                                  AR531X_ENET0_MII, AR5312_IRQ_ENET1_INTRS,
++                                  &ar5312_eth1_data);
 +
 +              if (!ar231x_board.radio)
 +                      return 0;
 +      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(AR531X_UART0, AR531X_MISC_IRQ_UART0,
++                          ar5312_sys_frequency());
 +}
 +
 --- /dev/null
 +++ b/arch/mips/ar231x/ar2315.c
-@@ -0,0 +1,639 @@
+@@ -0,0 +1,556 @@
 +/*
 + * 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),
 +      .config = &ar231x_board,
 +};
 +
 +      },
 +      {
 +              .flags = IORESOURCE_IRQ,
-+              .start = AR531X_MISC_IRQ_WATCHDOG,
-+              .end = AR531X_MISC_IRQ_WATCHDOG,
++              .start = AR2315_MISC_IRQ_WATCHDOG,
++              .end = AR2315_MISC_IRQ_WATCHDOG,
 +      }
 +};
 +
 +      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, "eth0_mii", AR2315_ENET0_MII,
++                          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(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,38 @@
 +#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);
++extern int ar231x_add_ethernet(int nr, u32 base, const char *mii_name,
++                             u32 mii_base, int irq, void *pdata);
 +
 +static inline bool is_2315(void)
 +{
 +      return !is_2315();
 +}
 +
-+struct ar231x_gpio_chip {
-+      u32 valid_mask;
-+      struct gpio_chip chip;
-+};
 +#endif
 --- /dev/null
 +++ b/arch/mips/ar231x/devices.c
-@@ -0,0 +1,168 @@
+@@ -0,0 +1,180 @@
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/serial.h>
 +              .flags = IORESOURCE_MEM,
 +      },
 +      {
++              .name = "eth0_mii",
++              .flags = IORESOURCE_MEM,
++      },
++      {
 +              .name = "eth0_irq",
 +              .flags = IORESOURCE_IRQ,
 +      }
 +              .flags = IORESOURCE_MEM,
 +      },
 +      {
++              .name = "eth1_mii",
++              .flags = IORESOURCE_MEM,
++      },
++      {
 +              .name = "eth1_irq",
 +              .flags = IORESOURCE_IRQ,
 +      }
 +
 +
 +int __init
-+ar231x_add_ethernet(int nr, u32 base, int irq, void *pdata)
++ar231x_add_ethernet(int nr, u32 base, const char *mii_name, u32 mii_base,
++                  int irq, void *pdata)
 +{
 +      struct resource *res;
 +
 +      res->start = base;
 +      res->end = base + 0x2000 - 1;
 +      res++;
++      res->name = mii_name;
++      res->start = mii_base;
++      res->end = mii_base + 8 - 1;
++      res++;
 +      res->start = irq;
 +      res->end = irq;
 +      return platform_device_register(&ar231x_eth[nr]);
 +}
 +
 +void __init
-+ar231x_serial_setup(u32 mapbase, unsigned int uartclk)
++ar231x_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
 +{
 +      struct uart_port s;
 +
 +      memset(&s, 0, sizeof(s));
 +
-+      s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-+      s.iotype = UPIO_MEM;
-+      s.irq = AR531X_MISC_IRQ_UART0;
++      s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP;
++      s.iotype = UPIO_MEM32;
++      s.irq = irq;
 +      s.regshift = 2;
 +      s.mapbase = mapbase;
 +      s.uartclk = uartclk;
-+      s.membase = (void __iomem *)s.mapbase;
 +
 +      early_serial_setup(&s);
 +}