diff -urN linux-mips/arch/mips/ar531x/ar531xdbg_io.c mips-linux-2.4.25/arch/mips/ar531x/ar531xdbg_io.c
--- linux-mips/arch/mips/ar531x/ar531xdbg_io.c	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xdbg_io.c	2005-12-30 17:26:30.606883840 +0000
@@ -0,0 +1,234 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright MontaVista Software Inc
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Basic support for polled character input/output
+ * using the AR531X's serial port.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/reboot.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/serial.h>
+#include <asm/gdb-stub.h>
+
+#include "ar531xlnx.h"
+
+#if CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB
+/* base addr of uart and clock timing */
+#if CONFIG_AR5315
+#define         BASE                    AR5315_UART0 
+#else
+#define         BASE                    AR531X_UART0
+#endif
+
+/* distance in bytes between two serial registers */
+#define         REG_OFFSET              4
+
+/*
+ * 0 - we need to do serial init
+ * 1 - skip serial init
+ */
+static int serialPortInitialized = 0;
+
+/*
+ *  * the default baud rate *if* we do serial init
+ *   */
+#define         BAUD_DEFAULT            UART16550_BAUD_9600
+
+/* === END OF CONFIG === */
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* register offset */
+#define         OFS_RCV_BUFFER          (0*REG_OFFSET)
+#define         OFS_TRANS_HOLD          (0*REG_OFFSET)
+#define         OFS_SEND_BUFFER         (0*REG_OFFSET)
+#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
+#define         OFS_INTR_ID             (2*REG_OFFSET)
+#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
+#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
+#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
+#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
+#define         OFS_LINE_STATUS         (5*REG_OFFSET)
+#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
+#define         OFS_RS232_INPUT         (6*REG_OFFSET)
+#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
+
+#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
+#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)    (*((volatile u8*)(BASE + y)))
+#define         UART16550_WRITE(y, z)  ((*((volatile u8*)(BASE + y))) = z)
+
+void
+debugPortInit(u32 baud, u8 data, u8 parity, u8 stop)
+{
+	/* Pull UART out of reset */
+#if CONFIG_AR5315
+	sysRegWrite(AR5315_RESET,
+		sysRegRead(AR5315_RESET) & ~(RESET_UART0));
+#else
+	sysRegWrite(AR531X_RESET,
+		sysRegRead(AR531X_RESET) & ~(AR531X_RESET_UART0));
+#endif
+
+	/* disable interrupts */
+        UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+	UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+	/* set up buad rate */
+	{ 
+		u32 divisor;
+#if CONFIG_AR5315 
+		u32 uart_clock_rate = ar531x_apb_frequency();
+#else
+		u32 uart_clock_rate = ar531x_cpu_frequency() / 4;
+#endif
+		u32 base_baud = uart_clock_rate / 16;
+       
+		/* set DIAB bit */
+	        UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+        
+	        /* set divisor */
+	        divisor = base_baud / baud;
+        	UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+	        UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
+
+        	/* clear DIAB bit */
+	        UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+	}
+
+	/* set data format */
+	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+u8
+getDebugChar(void)
+{
+        if (!serialPortInitialized) {
+                serialPortInitialized = 1;
+                debugPortInit(BAUD_DEFAULT,
+                              UART16550_DATA_8BIT,
+                              UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+        }
+
+	while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+	return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+#if CONFIG_KGDB
+/*
+ * Peek at the most recently received character.
+ * Don't wait for a new character to be received.
+ */
+u8
+peekDebugChar(void)
+{
+	return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+static int kgdbInitialized = 0;
+
+void
+kgdbInit(void)
+{
+#if CONFIG_AR5315
+    sysRegWrite(AR5315_WDC, WDC_IGNORE_EXPIRATION);
+#else
+    sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
+#endif
+
+    if (!kgdbInitialized) {
+        printk("Setting debug traps - please connect the remote debugger.\n");
+        set_debug_traps();
+        kgdbInitialized = 1;
+    }
+    breakpoint();
+}
+
+int
+kgdbEnabled(void)
+{
+    return kgdbInitialized;
+}
+
+#define DEBUG_CHAR '\001';
+
+int
+kgdbInterrupt(void)
+{
+    if (!kgdbInitialized) {
+        return 0;
+    }
+
+    /* 
+     * Try to avoid swallowing too much input: Only consume
+     * a character if nothing new has arrived.  Yes, there's
+     * still a small hole here, and we may lose an input
+     * character now and then.
+     */
+    if (UART16550_READ(OFS_LINE_STATUS) & 1) {
+        return 0;
+    } else {
+        return UART16550_READ(OFS_RCV_BUFFER) == DEBUG_CHAR;
+    }
+}
+#endif
+
+
+void
+putDebugChar(char byte)
+{
+        if (!serialPortInitialized) {
+                serialPortInitialized = 1;
+                debugPortInit(BAUD_DEFAULT,
+                              UART16550_DATA_8BIT,
+                              UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+        }
+
+	while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
+	UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ }
+#endif /* CONFIG_EARLY_PRINTK_HACK || CONFIG_KGDB */
diff -urN linux-mips/arch/mips/ar531x/ar531xgpio.c mips-linux-2.4.25/arch/mips/ar531x/ar531xgpio.c
--- linux-mips/arch/mips/ar531x/ar531xgpio.c	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xgpio.c	2005-12-30 17:26:30.606883840 +0000
@@ -0,0 +1,147 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Support for GPIO -- General Purpose Input/Output Pins
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include "ar531xlnx.h"
+
+/* GPIO Interrupt Support */
+
+/* Turn on the specified AR531X_GPIO_IRQ interrupt */
+static unsigned int
+ar531x_gpio_intr_startup(unsigned int irq)
+{
+	ar531x_gpio_intr_enable(irq);
+	return 0;
+}
+
+/* Turn off the specified AR531X_GPIO_IRQ interrupt */
+static void
+ar531x_gpio_intr_shutdown(unsigned int irq)
+{
+	ar531x_gpio_intr_disable(irq);
+}
+
+u32 gpioIntMask = 0;
+
+/* Enable the specified AR531X_GPIO_IRQ interrupt */
+void
+ar531x_gpio_intr_enable(unsigned int irq)
+{
+    u32 reg;
+    int gpio;
+
+#ifndef CONFIG_AR5315
+    gpio = irq - AR531X_GPIO_IRQ_BASE;
+    gpioIntMask |= gpio;
+
+    reg = sysRegRead(AR531X_GPIO_CR);
+    reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
+    reg |= GPIO_CR_I(gpio);
+    reg |= GPIO_CR_INT(gpio);
+
+    sysRegWrite(AR531X_GPIO_CR, reg);
+    (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
+#endif
+}
+
+/* Disable the specified AR531X_GPIO_IRQ interrupt */
+void
+ar531x_gpio_intr_disable(unsigned int irq)
+{
+    u32 reg;
+    int gpio;
+
+#ifndef CONFIG_AR5315
+    gpio = irq - AR531X_GPIO_IRQ_BASE;
+    reg = sysRegRead(AR531X_GPIO_CR);
+    reg &= ~(GPIO_CR_M(gpio) | GPIO_CR_UART(gpio) | GPIO_CR_INT(gpio));
+    reg |= GPIO_CR_I(gpio);
+    /* No GPIO_CR_INT bit */
+
+    sysRegWrite(AR531X_GPIO_CR, reg);
+    (void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */
+
+    gpioIntMask &= ~gpio;
+#endif
+}
+
+static void
+ar531x_gpio_intr_ack(unsigned int irq)
+{
+	ar531x_gpio_intr_disable(irq);
+}
+
+static void
+ar531x_gpio_intr_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ar531x_gpio_intr_enable(irq);
+}
+
+static void
+ar531x_gpio_intr_set_affinity(unsigned int irq, unsigned long mask)
+{
+	/* Only 1 CPU; ignore affinity request */
+}
+
+int ar531x_gpio_irq_base;
+
+struct hw_interrupt_type ar531x_gpio_intr_controller = {
+	"AR531X GPIO",
+	ar531x_gpio_intr_startup,
+	ar531x_gpio_intr_shutdown,
+	ar531x_gpio_intr_enable,
+	ar531x_gpio_intr_disable,
+	ar531x_gpio_intr_ack,
+	ar531x_gpio_intr_end,
+	ar531x_gpio_intr_set_affinity,
+};
+
+void
+ar531x_gpio_intr_init(int irq_base)
+{
+	int i;
+
+	for (i = irq_base; i < irq_base + AR531X_GPIO_IRQ_COUNT; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &ar531x_gpio_intr_controller;
+	}
+
+	ar531x_gpio_irq_base = irq_base;
+}
+
+/* ARGSUSED */
+void
+spurious_gpio_handler(int cpl, void *dev_id, struct pt_regs *regs)
+{
+    u32 gpioDataIn;
+#if CONFIG_AR5315
+    gpioDataIn = sysRegRead(AR5315_GPIO_DI) & gpioIntMask;
+#else
+    gpioDataIn = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
+#endif
+
+    printk("spurious_gpio_handler: 0x%x di=0x%8.8x gpioIntMask=0x%8.8x\n",
+           cpl, gpioDataIn, gpioIntMask);
+}
+
+struct irqaction spurious_gpio =
+	{spurious_gpio_handler, SA_INTERRUPT, 0, "spurious_gpio",
+            NULL, NULL};
+
diff -urN linux-mips/arch/mips/ar531x/ar531x.h mips-linux-2.4.25/arch/mips/ar531x/ar531x.h
--- linux-mips/arch/mips/ar531x/ar531x.h	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531x.h	2005-12-30 17:26:30.605883992 +0000
@@ -0,0 +1,1018 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+#ifndef AR531X_H
+#define AR531X_H 1
+
+#ifndef CONFIG_AR5315
+
+#include <asm/addrspace.h>
+
+/* Address Map */
+#define AR531X_WLAN0            0x18000000
+#define AR531X_WLAN1            0x18500000
+#define AR531X_ENET0            0x18100000
+#define AR531X_ENET1            0x18200000
+#define AR531X_SDRAMCTL         0x18300000
+#define AR531X_FLASHCTL         0x18400000
+#define AR531X_APBBASE		0x1c000000
+#define AR531X_FLASH            0x1e000000
+#define AR531X_UART0            0xbc000003      /* UART MMR */
+
+/*
+ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
+ * should be considered available.  The AR5312 supports 2 enet MACS,
+ * even though many reference boards only actually use 1 of them
+ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
+ * The AR2312 supports 1 enet MAC.
+ */
+#define AR531X_NUM_ENET_MAC             2
+
+/*
+ * Need these defines to determine true number of ethernet MACs
+ */
+#define AR5212_AR5312_REV2      0x0052          /* AR5312 WMAC (AP31) */
+#define AR5212_AR5312_REV7      0x0057          /* AR5312 WMAC (AP30-040) */
+#define AR5212_AR2313_REV8      0x0058          /* AR2313 WMAC (AP43-030) */
+#define AR531X_RADIO_MASK_OFF  0xc8
+#define AR531X_RADIO0_MASK     0x0003
+#define AR531X_RADIO1_MASK     0x000c
+#define AR531X_RADIO1_S        2 
+
+/*
+ * AR531X_NUM_WMAC defines the number of Wireless MACs that\
+ * should be considered available.
+ */
+#define AR531X_NUM_WMAC                 2
+
+/* Reset/Timer Block Address Map */
+#define AR531X_RESETTMR		(AR531X_APBBASE  + 0x3000)
+#define AR531X_TIMER		(AR531X_RESETTMR + 0x0000) /* countdown timer */
+#define AR531X_WD_CTRL          (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */
+#define AR531X_WD_TIMER         (AR531X_RESETTMR + 0x000c) /* watchdog timer */
+#define AR531X_ISR		(AR531X_RESETTMR + 0x0010) /* Intr Status Reg */
+#define AR531X_IMR		(AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */
+#define AR531X_RESET		(AR531X_RESETTMR + 0x0020)
+#define AR5312_CLOCKCTL1	(AR531X_RESETTMR + 0x0064)
+#define AR5312_SCRATCH   	(AR531X_RESETTMR + 0x006c)
+#define AR531X_PROCADDR		(AR531X_RESETTMR + 0x0070)
+#define AR531X_PROC1		(AR531X_RESETTMR + 0x0074)
+#define AR531X_DMAADDR		(AR531X_RESETTMR + 0x0078)
+#define AR531X_DMA1		(AR531X_RESETTMR + 0x007c)
+#define AR531X_ENABLE           (AR531X_RESETTMR + 0x0080) /* interface enb */
+#define AR531X_REV		(AR531X_RESETTMR + 0x0090) /* revision */
+
+/* AR531X_WD_CTRL register bit field definitions */
+#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000
+#define AR531X_WD_CTRL_NMI               0x0001
+#define AR531X_WD_CTRL_RESET             0x0002
+
+/* AR531X_ISR register bit field definitions */
+#define AR531X_ISR_NONE		0x0000
+#define AR531X_ISR_TIMER	0x0001
+#define AR531X_ISR_AHBPROC	0x0002
+#define AR531X_ISR_AHBDMA	0x0004
+#define AR531X_ISR_GPIO		0x0008
+#define AR531X_ISR_UART0	0x0010
+#define AR531X_ISR_UART0DMA	0x0020
+#define AR531X_ISR_WD		0x0040
+#define AR531X_ISR_LOCAL	0x0080
+
+/* AR531X_RESET register bit field definitions */
+#define AR531X_RESET_SYSTEM     0x00000001  /* cold reset full system */
+#define AR531X_RESET_PROC       0x00000002  /* cold reset MIPS core */
+#define AR531X_RESET_WLAN0      0x00000004  /* cold reset WLAN MAC and BB */
+#define AR531X_RESET_EPHY0      0x00000008  /* cold reset ENET0 phy */
+#define AR531X_RESET_EPHY1      0x00000010  /* cold reset ENET1 phy */
+#define AR531X_RESET_ENET0      0x00000020  /* cold reset ENET0 mac */
+#define AR531X_RESET_ENET1      0x00000040  /* cold reset ENET1 mac */
+#define AR531X_RESET_UART0      0x00000100  /* cold reset UART0 (high speed) */
+#define AR531X_RESET_WLAN1      0x00000200  /* cold reset WLAN MAC/BB */
+#define AR531X_RESET_APB        0x00000400  /* cold reset APB (ar5312) */
+#define AR531X_RESET_WARM_PROC  0x00001000  /* warm reset MIPS core */
+#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000  /* warm reset WLAN0 MAC */
+#define AR531X_RESET_WARM_WLAN0_BB  0x00004000  /* warm reset WLAN0 BaseBand */
+#define AR531X_RESET_NMI        0x00010000  /* send an NMI to the processor */
+#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000  /* warm reset WLAN1 mac */
+#define AR531X_RESET_WARM_WLAN1_BB  0x00040000  /* warm reset WLAN1 baseband */
+#define AR531X_RESET_LOCAL_BUS  0x00080000  /* reset local bus */
+#define AR531X_RESET_WDOG       0x00100000  /* last reset was a watchdog */
+
+#define AR531X_RESET_WMAC0_BITS \
+        AR531X_RESET_WLAN0 |\
+        AR531X_RESET_WARM_WLAN0_MAC |\
+        AR531X_RESET_WARM_WLAN0_BB
+
+#define AR531X_RESERT_WMAC1_BITS \
+        AR531X_RESET_WLAN1 |\
+        AR531X_RESET_WARM_WLAN1_MAC |\
+        AR531X_RESET_WARM_WLAN1_BB
+
+/* AR5312_CLOCKCTL1 register bit field definitions */
+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK    0x00000030
+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT            4
+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK   0x00001f00
+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT           8
+#define AR5312_CLOCKCTL1_DOUBLER_MASK      0x00010000
+
+/* Valid for AR5312 and AR2312 */
+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK    0x00000030
+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT            4
+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK   0x00001f00
+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT           8
+#define AR5312_CLOCKCTL1_DOUBLER_MASK      0x00010000
+
+/* Valid for AR2313 */
+#define AR2313_CLOCKCTL1_PREDIVIDE_MASK    0x00003000
+#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT           12
+#define AR2313_CLOCKCTL1_MULTIPLIER_MASK   0x001f0000
+#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT          16
+#define AR2313_CLOCKCTL1_DOUBLER_MASK      0x00000000
+
+
+/* AR531X_ENABLE register bit field definitions */
+#define AR531X_ENABLE_WLAN0              0x0001
+#define AR531X_ENABLE_ENET0              0x0002
+#define AR531X_ENABLE_ENET1              0x0004
+#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008   /* UART, and WLAN1 PIOs */
+#define AR531X_ENABLE_WLAN1_DMA          0x0010   /* WLAN1 DMAs */
+#define AR531X_ENABLE_WLAN1 \
+            (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)
+
+/* AR531X_REV register bit field definitions */
+#define AR531X_REV_WMAC_MAJ    0xf000
+#define AR531X_REV_WMAC_MAJ_S  12
+#define AR531X_REV_WMAC_MIN    0x0f00
+#define AR531X_REV_WMAC_MIN_S  8
+#define AR531X_REV_MAJ         0x00f0
+#define AR531X_REV_MAJ_S       4
+#define AR531X_REV_MIN         0x000f
+#define AR531X_REV_MIN_S       0
+#define AR531X_REV_CHIP        (REV_MAJ|REV_MIN)
+
+/* Major revision numbers, bits 7..4 of Revision ID register */
+#define AR531X_REV_MAJ_AR5312          0x4
+#define AR531X_REV_MAJ_AR2313          0x5
+
+/* Minor revision numbers, bits 3..0 of Revision ID register */
+#define AR5312_REV_MIN_DUAL     0x0     /* Dual WLAN version */
+#define AR5312_REV_MIN_SINGLE   0x1     /* Single WLAN version */
+
+/* AR531X_FLASHCTL register bit field definitions */
+#define FLASHCTL_IDCY   0x0000000f      /* Idle cycle turn around time */
+#define FLASHCTL_IDCY_S 0
+#define FLASHCTL_WST1   0x000003e0      /* Wait state 1 */
+#define FLASHCTL_WST1_S 5
+#define FLASHCTL_RBLE   0x00000400      /* Read byte lane enable */
+#define FLASHCTL_WST2   0x0000f800      /* Wait state 2 */
+#define FLASHCTL_WST2_S 11
+#define FLASHCTL_AC     0x00070000      /* Flash address check (added) */
+#define FLASHCTL_AC_S   16
+#define FLASHCTL_AC_128K 0x00000000
+#define FLASHCTL_AC_256K 0x00010000
+#define FLASHCTL_AC_512K 0x00020000
+#define FLASHCTL_AC_1M   0x00030000
+#define FLASHCTL_AC_2M   0x00040000
+#define FLASHCTL_AC_4M   0x00050000
+#define FLASHCTL_AC_8M   0x00060000
+#define FLASHCTL_AC_RES  0x00070000     /* 16MB is not supported */
+#define FLASHCTL_E      0x00080000      /* Flash bank enable (added) */
+#define FLASHCTL_BUSERR 0x01000000      /* Bus transfer error status flag */
+#define FLASHCTL_WPERR  0x02000000      /* Write protect error status flag */
+#define FLASHCTL_WP     0x04000000      /* Write protect */
+#define FLASHCTL_BM     0x08000000      /* Burst mode */
+#define FLASHCTL_MW     0x30000000      /* Memory width */
+#define FLASHCTL_MWx8   0x00000000      /* Memory width x8 */
+#define FLASHCTL_MWx16  0x10000000      /* Memory width x16 */
+#define FLASHCTL_MWx32  0x20000000      /* Memory width x32 (not supported) */
+#define FLASHCTL_ATNR   0x00000000      /* Access type == no retry */
+#define FLASHCTL_ATR    0x80000000      /* Access type == retry every */
+#define FLASHCTL_ATR4   0xc0000000      /* Access type == retry every 4 */
+
+/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices.  */
+#define AR531X_FLASHCTL0        (AR531X_FLASHCTL + 0x00)
+#define AR531X_FLASHCTL1        (AR531X_FLASHCTL + 0x04)
+#define AR531X_FLASHCTL2        (AR531X_FLASHCTL + 0x08)
+
+/* ARM SDRAM Controller -- just enough to determine memory size */
+#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)
+#define MEM_CFG1_AC0    0x00000700      /* bank 0: SDRAM addr check (added) */
+#define MEM_CFG1_AC0_S  8
+#define MEM_CFG1_AC1    0x00007000      /* bank 1: SDRAM addr check (added) */
+#define MEM_CFG1_AC1_S  12
+
+/* GPIO Address Map */
+#define AR531X_GPIO         (AR531X_APBBASE  + 0x2000)
+#define AR531X_GPIO_DO      (AR531X_GPIO + 0x00)        /* output register */
+#define AR531X_GPIO_DI      (AR531X_GPIO + 0x04)        /* intput register */
+#define AR531X_GPIO_CR      (AR531X_GPIO + 0x08)        /* control register */
+
+/* GPIO Control Register bit field definitions */
+#define GPIO_CR_M(x)    (1 << (x))                      /* mask for i/o */
+#define GPIO_CR_O(x)    (0 << (x))                      /* mask for output */
+#define GPIO_CR_I(x)    (1 << (x))                      /* mask for input */
+#define GPIO_CR_INT(x)  (1 << ((x)+8))                  /* mask for interrupt */
+#define GPIO_CR_UART(x) (1 << ((x)+16))                 /* uart multiplex */
+
+
+typedef unsigned int AR531X_REG;
+
+#define sysRegRead(phys)	\
+	(*(volatile AR531X_REG *)PHYS_TO_K1(phys))
+
+#define sysRegWrite(phys, val)	\
+	((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
+
+
+/*
+ * This is board-specific data that is stored in a "fixed" location in flash.
+ * It is shared across operating systems, so it should not be changed lightly.
+ * The main reason we need it is in order to extract the ethernet MAC
+ * address(es).
+ */
+struct ar531x_boarddata {
+    u32 magic;                       /* board data is valid */
+#define AR531X_BD_MAGIC 0x35333131   /* "5311", for all 531x platforms */
+    u16 cksum;                       /* checksum (starting with BD_REV 2) */
+    u16 rev;                         /* revision of this struct */
+#define BD_REV  4
+    char   boardName[64];            /* Name of board */
+    u16 major;                       /* Board major number */
+    u16 minor;                       /* Board minor number */
+    u32 config;                      /* Board configuration */
+#define BD_ENET0        0x00000001   /* ENET0 is stuffed */
+#define BD_ENET1        0x00000002   /* ENET1 is stuffed */
+#define BD_UART1        0x00000004   /* UART1 is stuffed */
+#define BD_UART0        0x00000008   /* UART0 is stuffed (dma) */
+#define BD_RSTFACTORY   0x00000010   /* Reset factory defaults stuffed */
+#define BD_SYSLED       0x00000020   /* System LED stuffed */
+#define BD_EXTUARTCLK   0x00000040   /* External UART clock */
+#define BD_CPUFREQ      0x00000080   /* cpu freq is valid in nvram */
+#define BD_SYSFREQ      0x00000100   /* sys freq is set in nvram */
+#define BD_WLAN0        0x00000200   /* Enable WLAN0 */
+#define BD_MEMCAP       0x00000400   /* CAP SDRAM @ memCap for testing */
+#define BD_DISWATCHDOG  0x00000800   /* disable system watchdog */
+#define BD_WLAN1        0x00001000   /* Enable WLAN1 (ar5212) */
+#define BD_ISCASPER     0x00002000   /* FLAG for AR2312 */
+#define BD_WLAN0_2G_EN  0x00004000   /* FLAG for radio0_2G */
+#define BD_WLAN0_5G_EN  0x00008000   /* FLAG for radio0_2G */
+#define BD_WLAN1_2G_EN  0x00020000   /* FLAG for radio0_2G */
+#define BD_WLAN1_5G_EN  0x00040000   /* FLAG for radio0_2G */
+    u16 resetConfigGpio;             /* Reset factory GPIO pin */
+    u16 sysLedGpio;                  /* System LED GPIO pin */
+
+    u32 cpuFreq;                     /* CPU core frequency in Hz */
+    u32 sysFreq;                     /* System frequency in Hz */
+    u32 cntFreq;                     /* Calculated C0_COUNT frequency */
+
+    u8  wlan0Mac[6];
+    u8  enet0Mac[6];
+    u8  enet1Mac[6];
+
+    u16 pciId;                       /* Pseudo PCIID for common code */
+    u16 memCap;                      /* cap bank1 in MB */
+
+    /* version 3 */
+    u8  wlan1Mac[6];                 /* (ar5212) */
+};
+
+#else
+
+/*
+ * Address map
+ */
+#define AR5315_SDRAM0           0x00000000      /* DRAM */
+#define AR5315_SPI_READ         0x08000000      /* SPI FLASH */
+#define AR5315_WLAN0            0xB0000000      /* Wireless MMR */
+#define AR5315_PCI              0xB0100000      /* PCI MMR */
+#define AR5315_SDRAMCTL         0xB0300000      /* SDRAM MMR */
+#define AR5315_LOCAL            0xB0400000      /* LOCAL BUS MMR */
+#define AR5315_ENET0            0xB0500000      /* ETHERNET MMR */
+#define AR5315_DSLBASE          0xB1000000      /* RESET CONTROL MMR */
+#define AR5315_UART0            0xB1100003      /* UART MMR */
+#define AR5315_SPI              0xB1300000      /* SPI FLASH MMR */
+#define AR5315_FLASHBT          0xBfc00000      /* ro boot alias to FLASH */
+#define AR5315_RAM1             0x40000000      /* ram alias */
+#define AR5315_PCIEXT           0x80000000      /* pci external */
+#define AR5315_RAM2             0xc0000000      /* ram alias */
+#define AR5315_RAM3             0xe0000000      /* ram alias */
+
+/*
+ * Reset Register
+ */
+#define AR5315_COLD_RESET       (AR5315_DSLBASE + 0x0000)
+
+/* Cold Reset */
+#define RESET_COLD_AHB              0x00000001
+#define RESET_COLD_APB              0x00000002
+#define RESET_COLD_CPU              0x00000004
+#define RESET_COLD_CPUWARM          0x00000008
+#define RESET_SYSTEM                (RESET_COLD_CPU | RESET_COLD_APB | RESET_COLD_AHB)      /* full system */
+
+/* Warm Reset */
+
+#define AR5315_RESET            (AR5315_DSLBASE + 0x0004)
+
+#define RESET_WARM_WLAN0_MAC        0x00000001      /* warm reset WLAN0 MAC */
+#define RESET_WARM_WLAN0_BB         0x00000002      /* warm reset WLAN0 BaseBand */
+#define RESET_MPEGTS_RSVD           0x00000004      /* warm reset MPEG-TS */
+#define RESET_PCIDMA                0x00000008      /* warm reset PCI ahb/dma */
+#define RESET_MEMCTL                0x00000010      /* warm reset memory controller */
+#define RESET_LOCAL                 0x00000020      /* warm reset local bus */
+#define RESET_I2C_RSVD              0x00000040      /* warm reset I2C bus */
+#define RESET_SPI                   0x00000080      /* warm reset SPI interface */
+#define RESET_UART0                 0x00000100      /* warm reset UART0 */
+#define RESET_IR_RSVD               0x00000200      /* warm reset IR interface */
+#define RESET_EPHY0                 0x00000400      /* cold reset ENET0 phy */
+#define RESET_ENET0                 0x00000800      /* cold reset ENET0 mac */
+
+/*
+ * AHB master arbitration control
+ */
+#define AR5315_AHB_ARB_CTL      (AR5315_DSLBASE + 0x0008)
+
+#define ARB_CPU                     0x00000001      /* CPU, default */
+#define ARB_WLAN                    0x00000002      /* WLAN */
+#define ARB_MPEGTS_RSVD             0x00000004      /* MPEG-TS */
+#define ARB_LOCAL                   0x00000008      /* LOCAL */
+#define ARB_PCI                     0x00000010      /* PCI */
+#define ARB_ETHERNET                0x00000020      /* Ethernet */
+#define ARB_RETRY                   0x00000100      /* retry policy, debug only */
+
+/*
+ * Config Register
+ */
+#define AR5315_ENDIAN_CTL       (AR5315_DSLBASE + 0x000c)
+
+#define CONFIG_AHB                  0x00000001      /* EC - AHB bridge endianess */
+#define CONFIG_WLAN                 0x00000002      /* WLAN byteswap */
+#define CONFIG_MPEGTS_RSVD          0x00000004      /* MPEG-TS byteswap */
+#define CONFIG_PCI                  0x00000008      /* PCI byteswap */
+#define CONFIG_MEMCTL               0x00000010      /* Memory controller endianess */
+#define CONFIG_LOCAL                0x00000020      /* Local bus byteswap */
+#define CONFIG_ETHERNET             0x00000040      /* Ethernet byteswap */
+
+#define CONFIG_MERGE                0x00000200      /* CPU write buffer merge */
+#define CONFIG_CPU                  0x00000400      /* CPU big endian */
+#define CONFIG_PCIAHB               0x00000800
+#define CONFIG_PCIAHB_BRIDGE        0x00001000
+#define CONFIG_SPI                  0x00008000      /* SPI byteswap */
+#define CONFIG_CPU_DRAM             0x00010000
+#define CONFIG_CPU_PCI              0x00020000
+#define CONFIG_CPU_MMR              0x00040000
+#define CONFIG_BIG                  0x00000400      
+
+
+/*
+ * NMI control
+ */
+#define AR5315_NMI_CTL          (AR5315_DSLBASE + 0x0010)
+
+#define NMI_EN  1
+
+/*
+ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR531X 1.0).
+ */
+#define AR5315_SREV             (AR5315_DSLBASE + 0x0014)
+
+#define REV_MAJ                     0x00f0
+#define REV_MAJ_S                   4
+#define REV_MIN                     0x000f
+#define REV_MIN_S                   0
+#define REV_CHIP                    (REV_MAJ|REV_MIN)
+
+/*
+ * Interface Enable
+ */
+#define AR5315_IF_CTL           (AR5315_DSLBASE + 0x0018)
+
+#define IF_MASK                     0x00000007
+#define IF_DISABLED                 0
+#define IF_PCI                      1
+#define IF_TS_LOCAL                 2
+#define IF_ALL                      3   /* only for emulation with separate pins */
+#define IF_LOCAL_HOST               0x00000008
+#define IF_PCI_HOST                 0x00000010
+#define IF_PCI_INTR                 0x00000020
+#define IF_PCI_CLK_MASK             0x00030000
+#define IF_PCI_CLK_INPUT            0 
+#define IF_PCI_CLK_OUTPUT_LOW       1
+#define IF_PCI_CLK_OUTPUT_CLK       2
+#define IF_PCI_CLK_OUTPUT_HIGH      3
+#define IF_PCI_CLK_SHIFT            16 
+ 
+                
+/* Major revision numbers, bits 7..4 of Revision ID register */
+#define REV_MAJ_AR5311              0x01
+#define REV_MAJ_AR5312              0x04
+#define REV_MAJ_AR5315              0x0B
+
+/*
+ * APB Interrupt control
+ */
+
+#define AR5315_ISR              (AR5315_DSLBASE + 0x0020)
+#define AR5315_IMR              (AR5315_DSLBASE + 0x0024)
+#define AR5315_GISR             (AR5315_DSLBASE + 0x0028)
+
+#define ISR_UART0                   0x0001           /* high speed UART */
+#define ISR_I2C_RSVD                0x0002           /* I2C bus */
+#define ISR_SPI                     0x0004           /* SPI bus */
+#define ISR_AHB                     0x0008           /* AHB error */
+#define ISR_APB                     0x0010           /* APB error */
+#define ISR_TIMER                   0x0020           /* timer */
+#define ISR_GPIO                    0x0040           /* GPIO */
+#define ISR_WD                      0x0080           /* watchdog */
+#define ISR_IR_RSVD                 0x0100           /* IR */
+                                
+#define IMR_UART0                   ISR_UART0
+#define IMR_I2C_RSVD                ISR_I2C_RSVD
+#define IMR_SPI                     ISR_SPI
+#define IMR_AHB                     ISR_AHB
+#define IMR_APB                     ISR_APB
+#define IMR_TIMER                   ISR_TIMER
+#define IMR_GPIO                    ISR_GPIO
+#define IMR_WD                      ISR_WD
+#define IMR_IR_RSVD                 ISR_IR_RSVD
+
+#define GISR_MISC                   0x0001
+#define GISR_WLAN0                  0x0002
+#define GISR_MPEGTS_RSVD            0x0004
+#define GISR_LOCALPCI               0x0008
+#define GISR_WMACPOLL               0x0010
+#define GISR_TIMER                  0x0020
+#define GISR_ETHERNET               0x0040
+
+/*
+ * Interrupt routing from IO to the processor IP bits
+ * Define our inter mask and level
+ */
+#define AR5315_INTR_MISCIO      SR_IBIT3
+#define AR5315_INTR_WLAN0       SR_IBIT4
+#define AR5315_INTR_ENET0       SR_IBIT5
+#define AR5315_INTR_LOCALPCI    SR_IBIT6
+#define AR5315_INTR_WMACPOLL    SR_IBIT7
+#define AR5315_INTR_COMPARE     SR_IBIT8
+
+/*
+ * Timers
+ */
+#define AR5315_TIMER            (AR5315_DSLBASE + 0x0030)
+#define AR5315_RELOAD           (AR5315_DSLBASE + 0x0034)
+#define AR5315_WD               (AR5315_DSLBASE + 0x0038)
+#define AR5315_WDC              (AR5315_DSLBASE + 0x003c)
+
+#define WDC_RESET                   0x00000002               /* reset on watchdog */
+#define WDC_NMI                     0x00000001               /* NMI on watchdog */
+#define WDC_IGNORE_EXPIRATION       0x00000000
+
+/*
+ * Interface Debug
+ */
+#define AR531X_FLASHDBG             (AR531X_RESETTMR + 0x0040)
+#define AR531X_MIIDBG               (AR531X_RESETTMR + 0x0044)
+
+
+/*
+ * CPU Performance Counters
+ */
+#define AR5315_PERFCNT0         (AR5315_DSLBASE + 0x0048)
+#define AR5315_PERFCNT1         (AR5315_DSLBASE + 0x004c)
+
+#define PERF_DATAHIT                0x0001  /* Count Data Cache Hits */
+#define PERF_DATAMISS               0x0002  /* Count Data Cache Misses */
+#define PERF_INSTHIT                0x0004  /* Count Instruction Cache Hits */
+#define PERF_INSTMISS               0x0008  /* Count Instruction Cache Misses */
+#define PERF_ACTIVE                 0x0010  /* Count Active Processor Cycles */
+#define PERF_WBHIT                  0x0020  /* Count CPU Write Buffer Hits */
+#define PERF_WBMISS                 0x0040  /* Count CPU Write Buffer Misses */
+                                
+#define PERF_EB_ARDY                0x0001  /* Count EB_ARdy signal */
+#define PERF_EB_AVALID              0x0002  /* Count EB_AValid signal */
+#define PERF_EB_WDRDY               0x0004  /* Count EB_WDRdy signal */
+#define PERF_EB_RDVAL               0x0008  /* Count EB_RdVal signal */
+#define PERF_VRADDR                 0x0010  /* Count valid read address cycles */
+#define PERF_VWADDR                 0x0020  /* Count valid write address cycles */
+#define PERF_VWDATA                 0x0040  /* Count valid write data cycles */
+
+/*
+ * AHB Error Reporting.
+ */
+#define AR5315_AHB_ERR0         (AR5315_DSLBASE + 0x0050)  /* error  */
+#define AR5315_AHB_ERR1         (AR5315_DSLBASE + 0x0054)  /* haddr  */
+#define AR5315_AHB_ERR2         (AR5315_DSLBASE + 0x0058)  /* hwdata */
+#define AR5315_AHB_ERR3         (AR5315_DSLBASE + 0x005c)  /* hrdata */
+#define AR5315_AHB_ERR4         (AR5315_DSLBASE + 0x0060)  /* status */
+
+#define AHB_ERROR_DET               1   /* AHB Error has been detected,          */
+                                        /* write 1 to clear all bits in ERR0     */
+#define AHB_ERROR_OVR               2   /* AHB Error overflow has been detected  */
+#define AHB_ERROR_WDT               4   /* AHB Error due to wdt instead of hresp */
+
+#define PROCERR_HMAST               0x0000000f
+#define PROCERR_HMAST_DFLT          0
+#define PROCERR_HMAST_WMAC          1
+#define PROCERR_HMAST_ENET          2
+#define PROCERR_HMAST_PCIENDPT      3
+#define PROCERR_HMAST_LOCAL         4
+#define PROCERR_HMAST_CPU           5
+#define PROCERR_HMAST_PCITGT        6
+                                    
+#define PROCERR_HMAST_S             0
+#define PROCERR_HWRITE              0x00000010
+#define PROCERR_HSIZE               0x00000060
+#define PROCERR_HSIZE_S             5
+#define PROCERR_HTRANS              0x00000180
+#define PROCERR_HTRANS_S            7
+#define PROCERR_HBURST              0x00000e00
+#define PROCERR_HBURST_S            9
+
+
+
+/*
+ * Clock Control
+ */
+#define AR5315_PLLC_CTL         (AR5315_DSLBASE + 0x0064)
+#define AR5315_PLLV_CTL         (AR5315_DSLBASE + 0x0068)
+#define AR5315_CPUCLK           (AR5315_DSLBASE + 0x006c)
+#define AR5315_AMBACLK          (AR5315_DSLBASE + 0x0070)
+#define AR5315_SYNCCLK          (AR5315_DSLBASE + 0x0074)
+#define AR5315_DSL_SLEEP_CTL    (AR5315_DSLBASE + 0x0080)
+#define AR5315_DSL_SLEEP_DUR    (AR5315_DSLBASE + 0x0084)
+
+/* PLLc Control fields */
+#define PLLC_REF_DIV_M              0x00000003
+#define PLLC_REF_DIV_S              0
+#define PLLC_FDBACK_DIV_M           0x0000007C
+#define PLLC_FDBACK_DIV_S           2
+#define PLLC_ADD_FDBACK_DIV_M       0x00000080
+#define PLLC_ADD_FDBACK_DIV_S       7
+#define PLLC_CLKC_DIV_M             0x0001c000
+#define PLLC_CLKC_DIV_S             14
+#define PLLC_CLKM_DIV_M             0x00700000
+#define PLLC_CLKM_DIV_S             20
+
+/* CPU CLK Control fields */
+#define CPUCLK_CLK_SEL_M            0x00000003
+#define CPUCLK_CLK_SEL_S            0
+#define CPUCLK_CLK_DIV_M            0x0000000c
+#define CPUCLK_CLK_DIV_S            2
+
+/* AMBA CLK Control fields */
+#define AMBACLK_CLK_SEL_M           0x00000003
+#define AMBACLK_CLK_SEL_S           0
+#define AMBACLK_CLK_DIV_M           0x0000000c
+#define AMBACLK_CLK_DIV_S           2
+
+#if defined(COBRA_EMUL)
+#define AR5315_AMBA_CLOCK_RATE  20000000
+#define AR5315_CPU_CLOCK_RATE   40000000
+#else
+#if defined(DEFAULT_PLL)
+#define AR5315_AMBA_CLOCK_RATE  40000000
+#define AR5315_CPU_CLOCK_RATE   40000000
+#else
+#define AR5315_AMBA_CLOCK_RATE  92000000
+#define AR5315_CPU_CLOCK_RATE   184000000
+#endif /* ! DEFAULT_PLL */
+#endif /* ! COBRA_EMUL */
+
+#define AR5315_UART_CLOCK_RATE  AR5315_AMBA_CLOCK_RATE
+#define AR5315_SDRAM_CLOCK_RATE AR5315_AMBA_CLOCK_RATE
+
+/*
+ * The UART computes baud rate as:
+ *   baud = clock / (16 * divisor)
+ * where divisor is specified as a High Byte (DLM) and a Low Byte (DLL).
+ */
+#define DESIRED_BAUD_RATE           38400
+
+/*
+ * The WATCHDOG value is computed as
+ *  10 seconds * AR531X_WATCHDOG_CLOCK_RATE
+ */
+#define DESIRED_WATCHDOG_SECONDS    10
+#define AR531X_WATCHDOG_TIME \
+        (DESIRED_WATCHDOG_SECONDS * AR531X_WATCHDOG_CLOCK_RATE)
+
+
+#define CLOCKCTL_UART0  0x0010  /* enable UART0 external clock */
+
+
+ /*
+ * Applicable "PCICFG" bits for WLAN(s).  Assoc status and LED mode.
+ */
+#define AR531X_PCICFG               (AR531X_RESETTMR + 0x00b0)
+#define ASSOC_STATUS_M              0x00000003
+#define ASSOC_STATUS_NONE           0
+#define ASSOC_STATUS_PENDING        1   
+#define ASSOC_STATUS_ASSOCIATED     2
+#define LED_MODE_M                  0x0000001c
+#define LED_BLINK_THRESHOLD_M       0x000000e0
+#define LED_SLOW_BLINK_MODE         0x00000100
+
+/*
+ * GPIO
+ */
+
+#define AR5315_GPIO_DI          (AR5315_DSLBASE + 0x0088)
+#define AR5315_GPIO_DO          (AR5315_DSLBASE + 0x0090)
+#define AR5315_GPIO_CR          (AR5315_DSLBASE + 0x0098)
+#define AR5315_GPIO_INT         (AR5315_DSLBASE + 0x00a0)
+
+#define GPIO_CR_M(x)                (1 << (x))                  /* mask for i/o */
+#define GPIO_CR_O(x)                (1 << (x))                  /* output */
+#define GPIO_CR_I(x)                (0 << (x))                  /* input */
+
+#define GPIO_INT(x,Y)               ((x) << (8 * (Y)))          /* interrupt enable */
+#define GPIO_INT_M(Y)               ((0x3F) << (8 * (Y)))       /* mask for int */
+#define GPIO_INT_LVL(x,Y)           ((x) << (8 * (Y) + 6))      /* interrupt level */
+#define GPIO_INT_LVL_M(Y)           ((0x3) << (8 * (Y) + 6))    /* mask for int level */
+
+#define AR5315_RESET_GPIO       5
+#define AR5315_NUM_GPIO         22
+
+    
+/* 
+ *  PCI Clock Control
+ */     
+ 
+#define AR5315_PCICLK           (AR5315_DSLBASE + 0x00a4)
+
+#define PCICLK_INPUT_M              0x3
+#define PCICLK_INPUT_S              0
+                         
+#define PCICLK_PLLC_CLKM            0
+#define PCICLK_PLLC_CLKM1           1
+#define PCICLK_PLLC_CLKC            2
+#define PCICLK_REF_CLK              3 
+
+#define PCICLK_DIV_M                0xc
+#define PCICLK_DIV_S                2
+                         
+#define PCICLK_IN_FREQ              0
+#define PCICLK_IN_FREQ_DIV_6        1
+#define PCICLK_IN_FREQ_DIV_8        2
+#define PCICLK_IN_FREQ_DIV_10       3 
+
+/*
+ * Observation Control Register
+ */
+#define AR5315_OCR              (AR5315_DSLBASE + 0x00b0)
+#define OCR_GPIO0_IRIN              0x0040
+#define OCR_GPIO1_IROUT             0x0080
+#define OCR_GPIO3_RXCLR             0x0200
+
+/* 
+ *  General Clock Control
+ */     
+ 
+#define AR5315_MISCCLK          (AR5315_DSLBASE + 0x00b4)
+#define MISCCLK_PLLBYPASS_EN        0x00000001
+#define MISCCLK_PROCREFCLK          0x00000002
+
+/*
+ * SDRAM Controller
+ *   - No read or write buffers are included.
+ */
+#define AR5315_MEM_CFG          (AR5315_SDRAMCTL + 0x00)
+#define AR5315_MEM_CTRL         (AR5315_SDRAMCTL + 0x0c)
+#define AR5315_MEM_REF          (AR5315_SDRAMCTL + 0x10)
+
+#define SDRAM_DATA_WIDTH_M          0x00006000
+#define SDRAM_DATA_WIDTH_S          13
+
+#define SDRAM_COL_WIDTH_M           0x00001E00
+#define SDRAM_COL_WIDTH_S           9
+
+#define SDRAM_ROW_WIDTH_M           0x000001E0
+#define SDRAM_ROW_WIDTH_S           5
+
+#define SDRAM_BANKADDR_BITS_M       0x00000018
+#define SDRAM_BANKADDR_BITS_S       3
+
+
+/*
+ * SDRAM Memory Refresh (MEM_REF) value is computed as:
+ * MEMCTL_SREFR = (Tr * hclk_freq) / R
+ * where Tr is max. time of refresh of any single row
+ * R is number of rows in the DRAM
+ * For most 133MHz SDRAM parts, Tr=64ms, R=4096 or 8192
+ */
+#if defined(COBRA_EMUL)
+#define AR5315_SDRAM_MEMORY_REFRESH_VALUE  0x96
+#else 
+#if defined(DEFAULT_PLL)
+#define AR5315_SDRAM_MEMORY_REFRESH_VALUE  0x200
+#else
+#define AR5315_SDRAM_MEMORY_REFRESH_VALUE  0x61a
+#endif /* ! DEFAULT_PLL */
+#endif 
+
+#if defined(AR5315)
+
+#define AR5315_SDRAM_DDR_SDRAM      0   /* Not DDR SDRAM */
+#define AR5315_SDRAM_DATA_WIDTH     16  /* bits */   
+#define AR5315_SDRAM_COL_WIDTH      8
+#define AR5315_SDRAM_ROW_WIDTH      12
+
+#else
+
+#define AR5315_SDRAM_DDR_SDRAM      0   /* Not DDR SDRAM */
+#define AR5315_SDRAM_DATA_WIDTH     16
+#define AR5315_SDRAM_COL_WIDTH      8
+#define AR5315_SDRAM_ROW_WIDTH      12
+
+#endif /* ! AR5315 */
+
+/*
+ * SPI Flash Interface Registers
+ */
+
+#define AR5315_SPI_CTL      (AR5315_SPI + 0x00)
+#define AR5315_SPI_OPCODE   (AR5315_SPI + 0x04)
+#define AR5315_SPI_DATA     (AR5315_SPI + 0x08)
+
+#define SPI_CTL_START           0x00000100
+#define SPI_CTL_BUSY            0x00010000
+#define SPI_CTL_TXCNT_MASK      0x0000000f
+#define SPI_CTL_RXCNT_MASK      0x000000f0
+#define SPI_CTL_TX_RX_CNT_MASK  0x000000ff
+#define SPI_CTL_SIZE_MASK       0x00060000
+
+#define SPI_CTL_CLK_SEL_MASK    0x03000000
+#define SPI_OPCODE_MASK         0x000000ff
+
+/* 
+ * PCI-MAC Configuration registers 
+ */
+#define PCI_MAC_RC              (AR5315_PCI + 0x4000) 
+#define PCI_MAC_SCR             (AR5315_PCI + 0x4004)
+#define PCI_MAC_INTPEND         (AR5315_PCI + 0x4008)
+#define PCI_MAC_SFR             (AR5315_PCI + 0x400C)
+#define PCI_MAC_PCICFG          (AR5315_PCI + 0x4010)
+#define PCI_MAC_SREV            (AR5315_PCI + 0x4020)
+
+#define PCI_MAC_RC_MAC          0x00000001
+#define PCI_MAC_RC_BB           0x00000002
+
+#define PCI_MAC_SCR_SLMODE_M    0x00030000
+#define PCI_MAC_SCR_SLMODE_S    16        
+#define PCI_MAC_SCR_SLM_FWAKE   0         
+#define PCI_MAC_SCR_SLM_FSLEEP  1         
+#define PCI_MAC_SCR_SLM_NORMAL  2         
+
+#define PCI_MAC_SFR_SLEEP       0x00000001
+
+#define PCI_MAC_PCICFG_SPWR_DN  0x00010000
+
+ 
+
+
+/*
+ * PCI Bus Interface Registers
+ */
+#define AR5315_PCI_1MS_REG      (AR5315_PCI + 0x0008)
+#define AR5315_PCI_1MS_MASK     0x3FFFF         /* # of AHB clk cycles in 1ms */
+
+#define AR5315_PCI_MISC_CONFIG  (AR5315_PCI + 0x000c)
+#define AR5315_PCIMISC_TXD_EN   0x00000001      /* Enable TXD for fragments */
+#define AR5315_PCIMISC_CFG_SEL  0x00000002      /* mem or config cycles */
+#define AR5315_PCIMISC_GIG_MASK 0x0000000C      /* bits 31-30 for pci req */
+#define AR5315_PCIMISC_RST_MODE 0x00000030
+#define AR5315_PCIRST_INPUT     0x00000000      /* 4:5=0 rst is input */
+#define AR5315_PCIRST_LOW       0x00000010      /* 4:5=1 rst to GND */
+#define AR5315_PCIRST_HIGH      0x00000020      /* 4:5=2 rst to VDD */
+#define AR5315_PCIGRANT_EN      0x00000000      /* 6:7=0 early grant en */
+#define AR5315_PCIGRANT_FRAME   0x00000040      /* 6:7=1 grant waits 4 frame */
+#define AR5315_PCIGRANT_IDLE    0x00000080      /* 6:7=2 grant waits 4 idle */
+#define AR5315_PCIGRANT_GAP     0x00000000      /* 6:7=2 grant waits 4 idle */
+#define AR5315_PCICACHE_DIS     0x00001000      /* PCI external access cache disable */
+
+#define AR5315_PCI_OUT_TSTAMP   (AR5315_PCI + 0x0010)
+
+#define AR5315_PCI_UNCACHE_CFG  (AR5315_PCI + 0x0014)
+
+#define AR5315_PCI_IN_EN        (AR5315_PCI + 0x0100)
+#define AR5315_PCI_IN_EN0       0x01            /* Enable chain 0 */
+#define AR5315_PCI_IN_EN1       0x02            /* Enable chain 1 */
+#define AR5315_PCI_IN_EN2       0x04            /* Enable chain 2 */
+#define AR5315_PCI_IN_EN3       0x08            /* Enable chain 3 */
+
+#define AR5315_PCI_IN_DIS       (AR5315_PCI + 0x0104)
+#define AR5315_PCI_IN_DIS0      0x01            /* Disable chain 0 */
+#define AR5315_PCI_IN_DIS1      0x02            /* Disable chain 1 */
+#define AR5315_PCI_IN_DIS2      0x04            /* Disable chain 2 */
+#define AR5315_PCI_IN_DIS3      0x08            /* Disable chain 3 */
+
+#define AR5315_PCI_IN_PTR       (AR5315_PCI + 0x0200)
+
+#define AR5315_PCI_OUT_EN       (AR5315_PCI + 0x0400)
+#define AR5315_PCI_OUT_EN0      0x01            /* Enable chain 0 */
+
+#define AR5315_PCI_OUT_DIS      (AR5315_PCI + 0x0404)
+#define AR5315_PCI_OUT_DIS0     0x01            /* Disable chain 0 */
+
+#define AR5315_PCI_OUT_PTR      (AR5315_PCI + 0x0408)
+
+#define AR5315_PCI_INT_STATUS   (AR5315_PCI + 0x0500)   /* write one to clr */
+#define AR5315_PCI_TXINT        0x00000001      /* Desc In Completed */
+#define AR5315_PCI_TXOK         0x00000002      /* Desc In OK */
+#define AR5315_PCI_TXERR        0x00000004      /* Desc In ERR */
+#define AR5315_PCI_TXEOL        0x00000008      /* Desc In End-of-List */
+#define AR5315_PCI_RXINT        0x00000010      /* Desc Out Completed */
+#define AR5315_PCI_RXOK         0x00000020      /* Desc Out OK */
+#define AR5315_PCI_RXERR        0x00000040      /* Desc Out ERR */
+#define AR5315_PCI_RXEOL        0x00000080      /* Desc Out EOL */
+#define AR5315_PCI_TXOOD        0x00000200      /* Desc In Out-of-Desc */
+#define AR5315_PCI_MASK         0x0000FFFF      /* Desc Mask */
+#define AR5315_PCI_EXT_INT      0x02000000      
+#define AR5315_PCI_ABORT_INT    0x04000000      
+
+#define AR5315_PCI_INT_MASK     (AR5315_PCI + 0x0504)   /* same as INT_STATUS */
+
+#define AR5315_PCI_INTEN_REG    (AR5315_PCI + 0x0508)
+#define AR5315_PCI_INT_DISABLE  0x00            /* disable pci interrupts */
+#define AR5315_PCI_INT_ENABLE   0x01            /* enable pci interrupts */
+
+#define AR5315_PCI_HOST_IN_EN   (AR5315_PCI + 0x0800)
+#define AR5315_PCI_HOST_IN_DIS  (AR5315_PCI + 0x0804)
+#define AR5315_PCI_HOST_IN_PTR  (AR5315_PCI + 0x0810)
+#define AR5315_PCI_HOST_OUT_EN  (AR5315_PCI + 0x0900)
+#define AR5315_PCI_HOST_OUT_DIS (AR5315_PCI + 0x0904)
+#define AR5315_PCI_HOST_OUT_PTR (AR5315_PCI + 0x0908)
+
+
+/*
+ * Local Bus Interface Registers
+ */
+#define AR5315_LB_CONFIG        (AR5315_LOCAL + 0x0000)
+#define AR5315_LBCONF_OE        0x00000001      /* =1 OE is low-true */
+#define AR5315_LBCONF_CS0       0x00000002      /* =1 first CS is low-true */
+#define AR5315_LBCONF_CS1       0x00000004      /* =1 2nd CS is low-true */
+#define AR5315_LBCONF_RDY       0x00000008      /* =1 RDY is low-true */
+#define AR5315_LBCONF_WE        0x00000010      /* =1 Write En is low-true */
+#define AR5315_LBCONF_WAIT      0x00000020      /* =1 WAIT is low-true */
+#define AR5315_LBCONF_ADS       0x00000040      /* =1 Adr Strobe is low-true */
+#define AR5315_LBCONF_MOT       0x00000080      /* =0 Intel, =1 Motorola */
+#define AR5315_LBCONF_8CS       0x00000100      /* =1 8 bits CS, 0= 16bits */
+#define AR5315_LBCONF_8DS       0x00000200      /* =1 8 bits Data S, 0=16bits */
+#define AR5315_LBCONF_ADS_EN    0x00000400      /* =1 Enable ADS */
+#define AR5315_LBCONF_ADR_OE    0x00000800      /* =1 Adr cap on OE, WE or DS */
+#define AR5315_LBCONF_ADDT_MUX  0x00001000      /* =1 Adr and Data share bus */
+#define AR5315_LBCONF_DATA_OE   0x00002000      /* =1 Data cap on OE, WE, DS */
+#define AR5315_LBCONF_16DATA    0x00004000      /* =1 Data is 16 bits wide */
+#define AR5315_LBCONF_SWAPDT    0x00008000      /* =1 Byte swap data */
+#define AR5315_LBCONF_SYNC      0x00010000      /* =1 Bus synchronous to clk */
+#define AR5315_LBCONF_INT       0x00020000      /* =1 Intr is low true */
+#define AR5315_LBCONF_INT_CTR0  0x00000000      /* GND high-Z, Vdd is high-Z */
+#define AR5315_LBCONF_INT_CTR1  0x00040000      /* GND drive, Vdd is high-Z */
+#define AR5315_LBCONF_INT_CTR2  0x00080000      /* GND high-Z, Vdd drive */
+#define AR5315_LBCONF_INT_CTR3  0x000C0000      /* GND drive, Vdd drive */
+#define AR5315_LBCONF_RDY_WAIT  0x00100000      /* =1 RDY is negative of WAIT */
+#define AR5315_LBCONF_INT_PULSE 0x00200000      /* =1 Interrupt is a pulse */
+#define AR5315_LBCONF_ENABLE    0x00400000      /* =1 Falcon respond to LB */
+
+#define AR5315_LB_CLKSEL        (AR5315_LOCAL + 0x0004)
+#define AR5315_LBCLK_EXT        0x0001          /* use external clk for lb */
+
+#define AR5315_LB_1MS           (AR5315_LOCAL + 0x0008)
+#define AR5315_LB1MS_MASK       0x3FFFF         /* # of AHB clk cycles in 1ms */
+
+#define AR5315_LB_MISCCFG       (AR5315_LOCAL + 0x000C)
+#define AR5315_LBM_TXD_EN       0x00000001      /* Enable TXD for fragments */
+#define AR5315_LBM_RX_INTEN     0x00000002      /* Enable LB ints on RX ready */
+#define AR5315_LBM_MBOXWR_INTEN 0x00000004      /* Enable LB ints on mbox wr */
+#define AR5315_LBM_MBOXRD_INTEN 0x00000008      /* Enable LB ints on mbox rd */
+#define AR5315_LMB_DESCSWAP_EN  0x00000010      /* Byte swap desc enable */
+#define AR5315_LBM_TIMEOUT_MASK 0x00FFFF80
+#define AR5315_LBM_TIMEOUT_SHFT 7
+#define AR5315_LBM_PORTMUX      0x07000000
+
+
+#define AR5315_LB_RXTSOFF       (AR5315_LOCAL + 0x0010)
+
+#define AR5315_LB_TX_CHAIN_EN   (AR5315_LOCAL + 0x0100)
+#define AR5315_LB_TXEN_0        0x01
+#define AR5315_LB_TXEN_1        0x02
+#define AR5315_LB_TXEN_2        0x04
+#define AR5315_LB_TXEN_3        0x08
+
+#define AR5315_LB_TX_CHAIN_DIS  (AR5315_LOCAL + 0x0104)
+#define AR5315_LB_TX_DESC_PTR   (AR5315_LOCAL + 0x0200)
+
+#define AR5315_LB_RX_CHAIN_EN   (AR5315_LOCAL + 0x0400)
+#define AR5315_LB_RXEN          0x01
+
+#define AR5315_LB_RX_CHAIN_DIS  (AR5315_LOCAL + 0x0404)
+#define AR5315_LB_RX_DESC_PTR   (AR5315_LOCAL + 0x0408)
+
+#define AR5315_LB_INT_STATUS    (AR5315_LOCAL + 0x0500)
+#define AR5315_INT_TX_DESC      0x0001
+#define AR5315_INT_TX_OK        0x0002
+#define AR5315_INT_TX_ERR       0x0004
+#define AR5315_INT_TX_EOF       0x0008
+#define AR5315_INT_RX_DESC      0x0010
+#define AR5315_INT_RX_OK        0x0020
+#define AR5315_INT_RX_ERR       0x0040
+#define AR5315_INT_RX_EOF       0x0080
+#define AR5315_INT_TX_TRUNC     0x0100
+#define AR5315_INT_TX_STARVE    0x0200
+#define AR5315_INT_LB_TIMEOUT   0x0400
+#define AR5315_INT_LB_ERR       0x0800
+#define AR5315_INT_MBOX_WR      0x1000
+#define AR5315_INT_MBOX_RD      0x2000
+
+/* Bit definitions for INT MASK are the same as INT_STATUS */
+#define AR5315_LB_INT_MASK      (AR5315_LOCAL + 0x0504)
+
+#define AR5315_LB_INT_EN        (AR5315_LOCAL + 0x0508)
+#define AR5315_LB_MBOX          (AR5315_LOCAL + 0x0600)
+
+
+
+/*
+ * IR Interface Registers
+ */
+#define AR5315_IR_PKTDATA                   (AR5315_IR + 0x0000)
+
+#define AR5315_IR_PKTLEN                    (AR5315_IR + 0x07fc) /* 0 - 63 */
+
+#define AR5315_IR_CONTROL                   (AR5315_IR + 0x0800)
+#define AR5315_IRCTL_TX                     0x00000000  /* use as tranmitter */
+#define AR5315_IRCTL_RX                     0x00000001  /* use as receiver   */
+#define AR5315_IRCTL_SAMPLECLK_MASK         0x00003ffe  /* Sample clk divisor mask */
+#define AR5315_IRCTL_SAMPLECLK_SHFT                  1
+#define AR5315_IRCTL_OUTPUTCLK_MASK         0x03ffc000  /* Output clk divisor mask */
+#define AR5315_IRCTL_OUTPUTCLK_SHFT                 14
+
+#define AR5315_IR_STATUS                    (AR5315_IR + 0x0804)
+#define AR5315_IRSTS_RX                     0x00000001  /* receive in progress */
+#define AR5315_IRSTS_TX                     0x00000002  /* transmit in progress */
+
+#define AR5315_IR_CONFIG                    (AR5315_IR + 0x0808)
+#define AR5315_IRCFG_INVIN                  0x00000001  /* invert input polarity */
+#define AR5315_IRCFG_INVOUT                 0x00000002  /* invert output polarity */
+#define AR5315_IRCFG_SEQ_START_WIN_SEL      0x00000004  /* 1 => 28, 0 => 7 */
+#define AR5315_IRCFG_SEQ_START_THRESH       0x000000f0  /*  */
+#define AR5315_IRCFG_SEQ_END_UNIT_SEL       0x00000100  /*  */
+#define AR5315_IRCFG_SEQ_END_UNIT_THRESH    0x00007e00  /*  */
+#define AR5315_IRCFG_SEQ_END_WIN_SEL        0x00008000  /*  */
+#define AR5315_IRCFG_SEQ_END_WIN_THRESH     0x001f0000  /*  */
+#define AR5315_IRCFG_NUM_BACKOFF_WORDS      0x01e00000  /*  */
+
+/*
+ * PCI memory constants: Memory area 1 and 2 are the same size -
+ * (twice the PCI_TLB_PAGE_SIZE). The definition of
+ * CPU_TO_PCI_MEM_SIZE is coupled with the TLB setup routine
+ * sysLib.c/sysTlbInit(), in that it assumes that 2 pages of size
+ * PCI_TLB_PAGE_SIZE are set up in the TLB for each PCI memory space.
+ */
+ 
+#define CPU_TO_PCI_MEM_BASE1    0xE0000000
+#define CPU_TO_PCI_MEM_SIZE1    (2*PCI_TLB_PAGE_SIZE)
+ 
+
+/* TLB attributes for PCI transactions */
+
+#define PCI_MMU_PAGEMASK        0x00003FFF
+#define MMU_PAGE_UNCACHED       0x00000010
+#define MMU_PAGE_DIRTY          0x00000004
+#define MMU_PAGE_VALID          0x00000002
+#define MMU_PAGE_GLOBAL         0x00000001
+#define PCI_MMU_PAGEATTRIB      (MMU_PAGE_UNCACHED|MMU_PAGE_DIRTY|\
+                                 MMU_PAGE_VALID|MMU_PAGE_GLOBAL)
+#define PCI_MEMORY_SPACE1_VIRT  0xE0000000      /* Used for non-prefet  mem   */
+#define PCI_MEMORY_SPACE1_PHYS  0x80000000
+#define PCI_TLB_PAGE_SIZE       0x01000000
+#define TLB_HI_MASK             0xFFFFE000
+#define TLB_LO_MASK             0x3FFFFFFF
+#define PAGEMASK_SHIFT          11
+#define TLB_LO_SHIFT            6
+
+#define PCI_MAX_LATENCY         0xFFF           /* Max PCI latency            */
+
+#define HOST_PCI_DEV_ID         3
+#define HOST_PCI_MBAR0          0x10000000
+#define HOST_PCI_MBAR1          0x20000000
+#define HOST_PCI_MBAR2          0x30000000
+
+#define HOST_PCI_SDRAM_BASEADDR HOST_PCI_MBAR1
+#define PCI_DEVICE_MEM_SPACE    0x800000
+
+
+typedef unsigned int AR531X_REG;
+
+#define sysRegRead(phys)	\
+	(*(volatile AR531X_REG *)PHYS_TO_K1(phys))
+
+#define sysRegWrite(phys, val)	\
+	((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
+#endif
+
+#endif
diff -urN linux-mips/arch/mips/ar531x/ar531xintr.S mips-linux-2.4.25/arch/mips/ar531x/ar531xintr.S
--- linux-mips/arch/mips/ar531x/ar531xintr.S	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xintr.S	2005-12-30 17:26:31.000823952 +0000
@@ -0,0 +1,30 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * Glue code to save registers and get us to the interrupt dispatcher
+ */
+	.text
+	.set	noat
+	.align	5
+NESTED(ar531x_interrupt_receive, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+
+	move	a0, sp
+	jal	ar531x_irq_dispatch
+
+	j	ret_from_irq
+
+	END(ar531x_interrupt_receive)
diff -urN linux-mips/arch/mips/ar531x/ar531xirq.c mips-linux-2.4.25/arch/mips/ar531x/ar531xirq.c
--- linux-mips/arch/mips/ar531x/ar531xirq.c	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xirq.c	2005-12-30 17:26:31.000823952 +0000
@@ -0,0 +1,442 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Interrupt support for AR531X WiSOC.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/gdb-stub.h>
+
+#include "ar531xlnx.h"
+#include <asm/irq_cpu.h>
+
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+
+static void ar531x_misc_intr_enable(unsigned int irq);
+static void ar531x_misc_intr_disable(unsigned int irq);
+
+/* Turn on the specified AR531X_MISC_IRQ interrupt */
+static unsigned int
+ar531x_misc_intr_startup(unsigned int irq)
+{
+	ar531x_misc_intr_enable(irq);
+	return 0;
+}
+
+/* Turn off the specified AR531X_MISC_IRQ interrupt */
+static void
+ar531x_misc_intr_shutdown(unsigned int irq)
+{
+	ar531x_misc_intr_disable(irq);
+}
+
+/* Enable the specified AR531X_MISC_IRQ interrupt */
+static void
+ar531x_misc_intr_enable(unsigned int irq)
+{
+	unsigned int imr;
+
+#if CONFIG_AR5315
+	imr = sysRegRead(AR5315_IMR);
+        switch(irq)
+        {
+           case AR531X_MISC_IRQ_TIMER:
+             imr |= IMR_TIMER;
+	     break;
+
+	   case AR531X_MISC_IRQ_AHB_PROC:
+             imr |= IMR_AHB;
+	     break;
+
+           case AR531X_MISC_IRQ_AHB_DMA:
+             imr |= 0/* ?? */;
+	     break;
+	     /*
+	   case	AR531X_ISR_GPIO:
+             imr |= IMR_GPIO;
+             break;
+             */
+
+	   case AR531X_MISC_IRQ_UART0:
+             imr |= IMR_UART0;
+             break;
+
+
+           case	AR531X_MISC_IRQ_WATCHDOG:
+             imr |= IMR_WD;
+             break;
+
+	   case AR531X_MISC_IRQ_LOCAL:
+             imr |= 0/* ?? */;
+             break;
+
+        }
+	sysRegWrite(AR5315_IMR, imr);
+	imr=sysRegRead(AR5315_IMR); /* flush write buffer */
+        //printk("enable Interrupt irq 0x%x imr 0x%x \n",irq,imr);
+
+#else
+	imr = sysRegRead(AR531X_IMR);
+	imr |= (1 << (irq - AR531X_MISC_IRQ_BASE - 1));
+	sysRegWrite(AR531X_IMR, imr);
+	sysRegRead(AR531X_IMR); /* flush write buffer */
+#endif
+}
+
+/* Disable the specified AR531X_MISC_IRQ interrupt */
+static void
+ar531x_misc_intr_disable(unsigned int irq)
+{
+	unsigned int imr;
+
+#if CONFIG_AR5315
+	imr = sysRegRead(AR5315_IMR);
+        switch(irq)
+        {
+           case AR531X_MISC_IRQ_TIMER:
+             imr &= (~IMR_TIMER);
+	     break;
+
+	   case AR531X_MISC_IRQ_AHB_PROC:
+             imr &= (~IMR_AHB);
+	     break;
+
+           case AR531X_MISC_IRQ_AHB_DMA:
+             imr &= 0/* ?? */;
+	     break;
+	     /*
+	   case	AR531X_ISR_GPIO:
+             imr &= ~IMR_GPIO;
+             break;
+             */
+
+	   case AR531X_MISC_IRQ_UART0:
+             imr &= (~IMR_UART0);
+             break;
+
+           case	AR531X_MISC_IRQ_WATCHDOG:
+             imr &= (~IMR_WD);
+             break;
+
+	   case AR531X_MISC_IRQ_LOCAL:
+             imr &= ~0/* ?? */;
+             break;
+
+        }
+	sysRegWrite(AR5315_IMR, imr);
+	sysRegRead(AR5315_IMR); /* flush write buffer */
+#else
+	imr = sysRegRead(AR531X_IMR);
+	imr &= ~(1 << (irq - AR531X_MISC_IRQ_BASE - 1));
+	sysRegWrite(AR531X_IMR, imr);
+	sysRegRead(AR531X_IMR); /* flush write buffer */
+#endif
+}
+
+static void
+ar531x_misc_intr_ack(unsigned int irq)
+{
+	ar531x_misc_intr_disable(irq);
+}
+
+static void
+ar531x_misc_intr_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ar531x_misc_intr_enable(irq);
+}
+
+static void
+ar531x_misc_intr_set_affinity(unsigned int irq, unsigned long mask)
+{
+	/* Only 1 CPU; ignore affinity request */
+}
+
+struct hw_interrupt_type ar531x_misc_intr_controller = {
+	"AR531X MISC",
+	ar531x_misc_intr_startup,
+	ar531x_misc_intr_shutdown,
+	ar531x_misc_intr_enable,
+	ar531x_misc_intr_disable,
+	ar531x_misc_intr_ack,
+	ar531x_misc_intr_end,
+	ar531x_misc_intr_set_affinity,
+};
+
+int ar531x_misc_irq_base;
+
+/*
+ * Determine interrupt source among interrupts that use IP6
+ */
+void
+ar531x_misc_intr_init(int irq_base)
+{
+	int i;
+
+	for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &ar531x_misc_intr_controller;
+	}
+
+	ar531x_misc_irq_base = irq_base;
+}
+
+/* ARGSUSED */
+void
+spurious_irq_handler(int cpl, void *dev_id, struct pt_regs *regs)
+{
+    /* 
+    printk("spurious_irq_handler: %d  cause=0x%8.8x  status=0x%8.8x\n",
+           cpl, cause_intrs, status_intrs); 
+    */
+}
+
+/* ARGSUSED */
+void
+spurious_misc_handler(int cpl, void *dev_id, struct pt_regs *regs)
+{
+    /*
+    printk("spurious_misc_handler: 0x%x isr=0x%8.8x imr=0x%8.8x\n",
+           cpl, ar531x_isr, ar531x_imr);
+    */
+}
+
+void
+ar531x_timer_handler(int cpl, void *dev_id, struct pt_regs *regs)
+{
+#if CONFIG_AR5315
+	(void)sysRegRead(AR5315_TIMER); /* clear interrupt */
+#else
+	(void)sysRegRead(AR531X_TIMER); /* clear interrupt */
+#endif
+}
+
+void
+ar531x_ahb_proc_handler(int cpl, void *dev_id, struct pt_regs *regs)
+{
+    u32 procAddr;
+    u32 proc1;
+    u32 dmaAddr;
+    u32 dma1;
+#if CONFIG_AR5315
+    sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
+    sysRegRead(AR5315_AHB_ERR1);
+#else
+    proc1 = sysRegRead(AR531X_PROC1);
+    procAddr = sysRegRead(AR531X_PROCADDR); /* clears error state */
+    dma1 = sysRegRead(AR531X_DMA1);
+    dmaAddr = sysRegRead(AR531X_DMAADDR);   /* clears error state */
+#endif
+
+    printk("AHB interrupt: PROCADDR=0x%8.8x  PROC1=0x%8.8x  DMAADDR=0x%8.8x  DMA1=0x%8.8x\n",
+        procAddr, proc1, dmaAddr, dma1);
+        
+    machine_restart("AHB error"); /* Catastrophic failure */
+}
+
+static struct irqaction cascade  =
+	{no_action, SA_INTERRUPT, 0, "cascade",
+            NULL, NULL};
+
+static struct irqaction spurious_irq =
+	{spurious_irq_handler, SA_INTERRUPT, 0, "spurious_irq",
+            NULL, NULL};
+
+static struct irqaction spurious_misc =
+	{spurious_misc_handler, SA_INTERRUPT, 0, "spurious_misc",
+            NULL, NULL};
+
+static struct irqaction ar531x_timer_interrupt =
+	{ar531x_timer_handler, SA_INTERRUPT, 0, "ar531x_timer_interrupt",
+            NULL, NULL};
+
+static struct irqaction ar531x_ahb_proc_interrupt =
+	{ar531x_ahb_proc_handler, SA_INTERRUPT, 0, "ar531x_ahb_proc_interrupt",
+            NULL, NULL};
+
+extern asmlinkage void ar531x_interrupt_receive(void);
+
+/*
+ * Called when an interrupt is received, this function
+ * determines exactly which interrupt it was, and it
+ * invokes the appropriate handler.
+ *
+ * Implicitly, we also define interrupt priority by
+ * choosing which to dispatch first.
+ */
+extern void dump_uart(void *);
+
+#if CONFIG_AR5315
+
+void
+ar531x_irq_dispatch(struct pt_regs *regs)
+{
+	int cause_intrs = regs->cp0_cause;
+	int status_intrs = regs->cp0_status;
+	int pending = cause_intrs & status_intrs;
+
+	if (pending & CAUSEF_IP3) {
+		do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);
+	}		
+	else if (pending & CAUSEF_IP4) {
+		do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);
+	}
+	else if (pending & CAUSEF_IP2) {
+		AR531X_REG ar531x_isr = sysRegRead(AR5315_ISR);
+		AR531X_REG ar531x_imr = sysRegRead(AR5315_IMR);
+		unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;
+
+             	if (ar531x_misc_intrs & ISR_TIMER)
+                        		  do_IRQ(AR531X_MISC_IRQ_TIMER, regs);
+		else if (ar531x_misc_intrs & ISR_AHB)
+					  do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);
+		else if (ar531x_misc_intrs & ISR_GPIO)
+                {
+                    int i;
+                    u32 gpioIntPending;
+
+                    gpioIntPending = sysRegRead(AR5315_GPIO_DI) & gpioIntMask;
+                    for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {
+                        if (gpioIntPending & (1 << i))
+                        		      do_IRQ(AR531X_GPIO_IRQ(i), regs);
+                    }
+                }
+		else if (ar531x_misc_intrs & ISR_UART0) {
+				do_IRQ(AR531X_MISC_IRQ_UART0, regs);
+#if CONFIG_KGDB
+                        if (kgdbInterrupt()) {
+                                if (!user_mode(regs))
+		                    set_async_breakpoint((unsigned long *)&regs->cp0_epc);
+                        }
+#endif 	/* CONFIG_KGDB */
+                }
+		else if (ar531x_misc_intrs & ISR_WD)
+			do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);
+		else
+			do_IRQ(AR531X_MISC_IRQ_NONE, regs);
+	} else if (pending & CAUSEF_IP7) {
+		do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);
+        }
+	else {
+		do_IRQ(AR531X_IRQ_NONE, regs);
+        }
+}
+
+#else
+
+void
+ar531x_irq_dispatch(struct pt_regs *regs)
+{
+	int cause_intrs = regs->cp0_cause;
+	int status_intrs = regs->cp0_status;
+	int pending = cause_intrs & status_intrs;
+
+	if (pending & CAUSEF_IP2) {
+		do_IRQ(AR531X_IRQ_WLAN0_INTRS, regs);
+	}		
+	else if (pending & CAUSEF_IP3) {
+		do_IRQ(AR531X_IRQ_ENET0_INTRS, regs);
+	}
+	else if (pending & CAUSEF_IP4) {
+		do_IRQ(AR531X_IRQ_ENET1_INTRS, regs);
+	}
+	else if (pending & CAUSEF_IP5) {
+		do_IRQ(AR531X_IRQ_WLAN1_INTRS, regs);
+	}
+	else if (pending & CAUSEF_IP6) {
+		AR531X_REG ar531x_isr = sysRegRead(AR531X_ISR);
+		AR531X_REG ar531x_imr = sysRegRead(AR531X_IMR);
+		unsigned int ar531x_misc_intrs = ar531x_isr & ar531x_imr;
+
+		if (ar531x_misc_intrs & AR531X_ISR_TIMER)
+			do_IRQ(AR531X_MISC_IRQ_TIMER, regs);
+		else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
+			do_IRQ(AR531X_MISC_IRQ_AHB_PROC, regs);
+		else if (ar531x_misc_intrs & AR531X_ISR_AHBDMA)
+			do_IRQ(AR531X_MISC_IRQ_AHB_DMA, regs);
+		else if (ar531x_misc_intrs & AR531X_ISR_GPIO)
+                {
+                    int i;
+                    u32 gpioIntPending;
+
+                    gpioIntPending = sysRegRead(AR531X_GPIO_DI) & gpioIntMask;
+                    for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) {
+                        if (gpioIntPending & (1 << i))
+                            do_IRQ(AR531X_GPIO_IRQ(i), regs);
+                    }
+                }
+		else if ((ar531x_misc_intrs & AR531X_ISR_UART0) ||
+		         (ar531x_misc_intrs & AR531X_ISR_UART0DMA)) {
+			do_IRQ(AR531X_MISC_IRQ_UART0, regs);
+#if CONFIG_KGDB
+                        if (kgdbInterrupt()) {
+                                if (!user_mode(regs))
+		                    set_async_breakpoint((unsigned long *)&regs->cp0_epc);
+                        }
+#endif 	/* CONFIG_KGDB */
+                }
+		else if (ar531x_misc_intrs & AR531X_ISR_WD)
+			do_IRQ(AR531X_MISC_IRQ_WATCHDOG, regs);
+		else if (ar531x_misc_intrs & AR531X_ISR_LOCAL)
+			do_IRQ(AR531X_MISC_IRQ_LOCAL, regs);
+		else
+			do_IRQ(AR531X_MISC_IRQ_NONE, regs);
+	} else if (pending & CAUSEF_IP7) {
+		do_IRQ(AR531X_IRQ_CPU_CLOCK, regs);
+	} else
+		do_IRQ(AR531X_IRQ_NONE, regs);
+}
+
+#endif
+
+void __init init_IRQ(void)
+{
+	init_generic_irq();
+	set_except_vector(0, ar531x_interrupt_receive);
+
+	/* Initialize interrupt controllers */
+	mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
+	ar531x_misc_intr_init(AR531X_MISC_IRQ_BASE);
+        ar531x_gpio_intr_init(AR531X_GPIO_IRQ_BASE);
+	setup_irq(AR531X_IRQ_MISC_INTRS, &cascade);
+	/*
+         * AR531X_IRQ_CPU_CLOCK is setup by ar531x_timer_setup.
+         */
+
+	/* Default "spurious interrupt" handlers */
+	setup_irq(AR531X_IRQ_NONE, &spurious_irq);
+	setup_irq(AR531X_MISC_IRQ_NONE, &spurious_misc);
+	setup_irq(AR531X_GPIO_IRQ_NONE, &spurious_gpio);
+#ifndef CONFIG_AR5315
+	setup_irq(AR531X_MISC_IRQ_TIMER, &ar531x_timer_interrupt);
+#endif
+	setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar531x_ahb_proc_interrupt);
+        setup_irq(AR531X_MISC_IRQ_GPIO, &cascade);
+
+#ifdef CONFIG_KGDB
+#if CONFIG_EARLY_STOP
+        kgdbInit();
+#endif
+#endif
+}
diff -urN linux-mips/arch/mips/ar531x/ar531xksyms.c mips-linux-2.4.25/arch/mips/ar531x/ar531xksyms.c
--- linux-mips/arch/mips/ar531x/ar531xksyms.c	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xksyms.c	2005-12-30 17:26:31.001823800 +0000
@@ -0,0 +1,17 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include "asm/atheros/ar531xbsp.h"
+
+#ifdef CONFIG_KGDB
+EXPORT_SYMBOL(kgdbInit);
+EXPORT_SYMBOL(kgdbEnabled);
+#endif
+EXPORT_SYMBOL(ar531x_sys_frequency);
+EXPORT_SYMBOL(get_system_type);
diff -urN linux-mips/arch/mips/ar531x/ar531xlnx.h mips-linux-2.4.25/arch/mips/ar531x/ar531xlnx.h
--- linux-mips/arch/mips/ar531x/ar531xlnx.h	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xlnx.h	2005-12-30 17:26:31.001823800 +0000
@@ -0,0 +1,135 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * This file contains definitions needed in order to compile
+ * AR531X products for linux.  Definitions that are largely
+ * AR531X-specific and independent of operating system belong
+ * in ar531x.h rather than this file.
+ */
+#include "ar531x.h"
+
+#define MIPS_CPU_IRQ_BASE		0x00
+#define AR531X_HIGH_PRIO                0x10
+#define AR531X_MISC_IRQ_BASE		0x20
+#define AR531X_GPIO_IRQ_BASE            0x30
+
+/* Software's idea of interrupts handled by "CPU Interrupt Controller" */
+#if CONFIG_AR5315
+#define AR531X_IRQ_NONE		MIPS_CPU_IRQ_BASE+0
+#define AR531X_IRQ_MISC_INTRS	MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
+#define AR531X_IRQ_WLAN0_INTRS	MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
+#define AR531X_IRQ_ENET0_INTRS	MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
+#define AR531X_IRQ_LCBUS_PCI	MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
+#define AR531X_IRQ_WLAN0_POLL	MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
+#define AR531X_IRQ_CPU_CLOCK	MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
+#else
+#define AR531X_IRQ_NONE		MIPS_CPU_IRQ_BASE+0
+#define AR531X_IRQ_WLAN0_INTRS	MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
+#define AR531X_IRQ_ENET0_INTRS	MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
+#define AR531X_IRQ_ENET1_INTRS	MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
+#define AR531X_IRQ_WLAN1_INTRS	MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */
+#define AR531X_IRQ_MISC_INTRS	MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
+#define AR531X_IRQ_CPU_CLOCK	MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
+#endif
+/* 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_COUNT		9
+
+/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
+#define AR531X_GPIO_IRQ_NONE            AR531X_MISC_IRQ_BASE+0
+#define AR531X_GPIO_IRQ(n)              AR531X_MISC_IRQ_BASE+(n)+1
+#ifdef CONFIG_AR5315
+#define AR531X_GPIO_IRQ_COUNT           2
+#else
+#define AR531X_GPIO_IRQ_COUNT           9
+#endif
+
+#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
+#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)
+#define UNMAPPED_TO_PHYS(vaddr)  PHYSADDR(vaddr)
+#define IS_UNMAPPED_VADDR(vaddr) \
+    ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))
+
+/* IOCTL commands for /proc/ar531x */
+#define AR531X_CTRL_DO_BREAKPOINT       1
+#define AR531X_CTRL_DO_MADWIFI          2
+
+/*
+ * Definitions for operating system portability.
+ * These are vxWorks-->Linux translations.
+ */
+#define LOCAL static
+#define BOOL int
+#define TRUE 1
+#define FALSE 0
+#define UINT8 u8
+#define UINT16 u16
+#define UINT32 u32
+#define PRINTF printk
+#if /* DEBUG */ 1
+#define DEBUG_PRINTF printk
+#define INLINE
+#else
+DEBUG_PRINTF while (0) printk
+#define INLINE inline
+#endif
+#define sysUDelay(usecs) udelay(usecs)
+#define sysMsDelay(msecs) mdelay(msecs)
+typedef volatile UINT8 *VIRT_ADDR;
+#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)
+#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)
+#define FREE(ptr) kfree((void *)ptr)
+#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)
+#define ASSERT(x) BSP_BUG_ON(!(x))
+
+extern struct ar531x_boarddata *ar531x_board_configuration;
+extern char *ar531x_radio_configuration;
+extern char *enet_mac_address_get(int MACUnit);
+
+extern void kgdbInit(void);
+extern int kgdbEnabled(void);
+extern void breakpoint(void);
+extern int kgdbInterrupt(void);
+extern unsigned int ar531x_cpu_frequency(void);
+extern unsigned int ar531x_sys_frequency(void);
+
+/* GPIO support */
+extern struct irqaction spurious_gpio;
+extern unsigned int gpioIntMask;
+extern void ar531x_gpio_intr_init(int irq_base);
+extern void ar531x_gpio_ctrl_output(int gpio);
+extern void ar531x_gpio_ctrl_input(int gpio);
+extern void ar531x_gpio_set(int gpio, int val);
+extern int  ar531x_gpio_get(int gpio);
+extern void ar531x_gpio_intr_enable(unsigned int irq);
+extern void ar531x_gpio_intr_disable(unsigned int irq);
+
+/* Watchdog Timer support */
+extern int watchdog_start(unsigned int milliseconds);
+extern int watchdog_stop(void);
+extern int watchdog_is_enabled(void);
+extern unsigned int watchdog_min_timer_reached(void);
+extern void watchdog_notify_alive(void);
+
+#define A_DATA_CACHE_INVAL(start, length) \
+        dma_cache_inv((UINT32)(start),(length))
+
+#define sysWbFlush() mb()
+
+#define intDisable(x) cli()
+#define intEnable(x) sti()
diff -urN linux-mips/arch/mips/ar531x/ar531xprom.c mips-linux-2.4.25/arch/mips/ar531x/ar531xprom.c
--- linux-mips/arch/mips/ar531x/ar531xprom.c	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xprom.c	2005-12-30 17:26:31.001823800 +0000
@@ -0,0 +1,88 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright MontaVista Software Inc
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Prom setup file for ar531x
+ */
+
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+#include "ar531xlnx.h"
+
+#define COMMAND_LINE_SIZE 512
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+
+void __init prom_init(int argc, char *argv[])
+{
+    int i;
+    unsigned int memcfg1;
+    int bank0AC, bank1AC;
+    int memsz_in_mb;
+    strcpy(arcs_cmdline, "console=ttyS0,9600");
+    for (i=0; i<argc; i++) {
+        strcat(arcs_cmdline, " ");
+        strcat(arcs_cmdline, argv[i]);
+    }
+
+    mips_machgroup = MACH_GROUP_AR531X;
+#ifdef CONFIG_APUNUSED
+    mips_machtype = MACH_ATHEROS_UNUSED;
+#endif
+#ifdef CONFIG_AP30
+    mips_machtype = MACH_ATHEROS_AP30;
+#endif
+#ifdef CONFIG_AP33
+    mips_machtype = MACH_ATHEROS_AP33;
+#endif
+#ifdef CONFIG_AP38
+    mips_machtype = MACH_ATHEROS_AP38;
+#endif
+#ifdef CONFIG_AP43
+    mips_machtype = MACH_ATHEROS_AP43;
+#endif
+#ifdef CONFIG_AP48
+    mips_machtype = MACH_ATHEROS_AP48;
+#endif
+#ifdef CONFIG_PB32
+    mips_machtype = MACH_ATHEROS_PB32;
+#endif
+
+
+    /* Determine SDRAM size based on Address Checks done at startup */
+#if CONFIG_AR5315
+    /* TO-DO : compute the SDRAM size */
+    memsz_in_mb=8;
+#else
+    memcfg1 = sysRegRead(AR531X_MEM_CFG1);
+    bank0AC = (memcfg1 & MEM_CFG1_AC0) >> MEM_CFG1_AC0_S;
+    bank1AC = (memcfg1 & MEM_CFG1_AC1) >> MEM_CFG1_AC1_S;
+    memsz_in_mb = (bank0AC ? (1 << (bank0AC+1)) : 0)
+                + (bank1AC ? (1 << (bank1AC+1)) : 0);
+#endif
+
+    /*
+     * By default, use all available memory.  You can override this
+     * to use, say, 8MB by specifying "mem=8M" as an argument on the
+     * linux bootup command line.
+     */
+    add_memory_region(0, memsz_in_mb << 20, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff -urN linux-mips/arch/mips/ar531x/ar531xsetup.c mips-linux-2.4.25/arch/mips/ar531x/ar531xsetup.c
--- linux-mips/arch/mips/ar531x/ar531xsetup.c	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/ar531xsetup.c	2005-12-30 17:26:31.002823648 +0000
@@ -0,0 +1,406 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Initialization for ar531x SOC.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/reboot.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/serial.h>
+
+#include "ar531xlnx.h"
+
+void
+ar531x_restart(char *command)
+{
+    for(;;) {
+#if CONFIG_AR5315
+    /* 
+    ** Cold reset does not work,work around is to use the GPIO reset bit.  
+    */
+    unsigned int reg;
+    reg = sysRegRead(AR5315_GPIO_DO);
+    reg &= ~(1 << AR5315_RESET_GPIO);
+    sysRegWrite(AR5315_GPIO_DO, reg);
+    (void)sysRegRead(AR5315_GPIO_DO); /* flush write to hardware */
+      
+#else
+        sysRegWrite(AR531X_RESET, AR531X_RESET_SYSTEM);
+#endif
+    }
+}
+
+void
+ar531x_halt(void)
+{
+        printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+        while (1);
+}
+
+void
+ar531x_power_off(void)
+{
+        ar531x_halt();
+}
+
+const char *
+get_system_type(void)
+{
+#if CONFIG_AR5315
+	return "Atheros AR5315";
+#else
+	return "Atheros AR531X";
+#endif
+}
+
+/*
+ * This table is indexed by bits 5..4 of the CLOCKCTL1 register
+ * to determine the predevisor value.
+ */
+static int CLOCKCTL1_PREDIVIDE_TABLE[4] = {
+    1,
+    2,
+    4,
+    5
+};
+
+#if CONFIG_AR5315
+static int PLLC_DIVIDE_TABLE[5] = {
+    2,
+    3,
+    4,
+    6,
+    3
+};
+
+unsigned int
+ar531x_cpu_frequency(void)
+{
+    static unsigned int ar531x_calculated_cpu_freq=0;
+    unsigned int clockCtl,pllcCtrl,cpuDiv;
+    unsigned int pllcOut,refdiv,fdiv,divby2;
+
+    if(ar531x_calculated_cpu_freq) 
+         return ar531x_calculated_cpu_freq; 
+
+    
+    pllcCtrl = sysRegRead(AR5315_PLLC_CTL);
+    refdiv = (pllcCtrl & PLLC_REF_DIV_M) >> PLLC_REF_DIV_S;
+    refdiv = CLOCKCTL1_PREDIVIDE_TABLE[refdiv];
+    fdiv = (pllcCtrl & PLLC_FDBACK_DIV_M) >> PLLC_FDBACK_DIV_S;
+    divby2 = (pllcCtrl & PLLC_ADD_FDBACK_DIV_M) >> PLLC_ADD_FDBACK_DIV_S;
+    divby2 += 1;
+    pllcOut = (40000000/refdiv)*(2*divby2)*fdiv;
+
+    clockCtl = sysRegRead(AR5315_CPUCLK);
+
+    /* clkm input selected */
+    if((clockCtl & CPUCLK_CLK_SEL_M) == 0  || (clockCtl & CPUCLK_CLK_SEL_M) == 1 ) {
+       unsigned int clkMdiv;
+       clkMdiv = (pllcCtrl & PLLC_CLKM_DIV_M) >> PLLC_CLKM_DIV_S;
+       clkMdiv = PLLC_DIVIDE_TABLE[clkMdiv];
+
+       cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;  
+       if(cpuDiv)  cpuDiv *= 2;
+       else cpuDiv=1;
+
+       ar531x_calculated_cpu_freq= (pllcOut/(clkMdiv * cpuDiv)) ;
+        
+       return ar531x_calculated_cpu_freq; 
+    } 
+    
+    /* clkc input selected */
+    if((clockCtl & CPUCLK_CLK_SEL_M) == 2 ) {
+       unsigned int clkCdiv;
+       clkCdiv = (pllcCtrl & PLLC_CLKC_DIV_M) >> PLLC_CLKC_DIV_S;
+       clkCdiv = PLLC_DIVIDE_TABLE[clkCdiv];
+
+       cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;  
+       if(cpuDiv)  cpuDiv *= 2;
+       else cpuDiv=1;
+
+       ar531x_calculated_cpu_freq= (pllcOut/(clkCdiv * cpuDiv)) ;
+        
+       return ar531x_calculated_cpu_freq; 
+    } else {   /* ref_clk  selected */
+
+       cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;  
+       if(cpuDiv)  cpuDiv *= 2;
+       else cpuDiv=1;
+
+       ar531x_calculated_cpu_freq= (40000000/(cpuDiv)) ;
+       return ar531x_calculated_cpu_freq; 
+    }
+}
+
+unsigned int
+ar531x_apb_frequency(void)
+{
+    static unsigned int ar531x_calculated_cpu_freq=0;
+    unsigned int clockCtl,pllcCtrl,cpuDiv;
+    unsigned int pllcOut,refdiv,fdiv,divby2;
+
+    if(ar531x_calculated_cpu_freq) 
+         return ar531x_calculated_cpu_freq; 
+
+    
+    pllcCtrl = sysRegRead(AR5315_PLLC_CTL);
+    refdiv = (pllcCtrl & PLLC_REF_DIV_M) >> PLLC_REF_DIV_S;
+    refdiv = CLOCKCTL1_PREDIVIDE_TABLE[refdiv];
+    fdiv = (pllcCtrl & PLLC_FDBACK_DIV_M) >> PLLC_FDBACK_DIV_S;
+    divby2 = (pllcCtrl & PLLC_ADD_FDBACK_DIV_M) >> PLLC_ADD_FDBACK_DIV_S;
+    divby2 += 1;
+    pllcOut = (40000000/refdiv)*(2*divby2)*fdiv;
+
+    clockCtl = sysRegRead(AR5315_AMBACLK);
+
+    /* clkm input selected */
+    if((clockCtl & CPUCLK_CLK_SEL_M) == 0  || (clockCtl & CPUCLK_CLK_SEL_M) == 1 ) {
+       unsigned int clkMdiv;
+       clkMdiv = (pllcCtrl & PLLC_CLKM_DIV_M) >> PLLC_CLKM_DIV_S;
+       clkMdiv = PLLC_DIVIDE_TABLE[clkMdiv];
+
+       cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;  
+       if(cpuDiv)  cpuDiv *= 2;
+       else cpuDiv=1;
+
+       ar531x_calculated_cpu_freq= (pllcOut/(clkMdiv * cpuDiv)) ;
+        
+       return ar531x_calculated_cpu_freq; 
+    } 
+    
+    /* clkc input selected */
+    if((clockCtl & CPUCLK_CLK_SEL_M) == 2 ) {
+       unsigned int clkCdiv;
+       clkCdiv = (pllcCtrl & PLLC_CLKC_DIV_M) >> PLLC_CLKC_DIV_S;
+       clkCdiv = PLLC_DIVIDE_TABLE[clkCdiv];
+
+       cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;  
+       if(cpuDiv)  cpuDiv *= 2;
+       else cpuDiv=1;
+
+       ar531x_calculated_cpu_freq= (pllcOut/(clkCdiv * cpuDiv)) ;
+        
+       return ar531x_calculated_cpu_freq; 
+    } else {   /* ref_clk  selected */
+
+       cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S;  
+       if(cpuDiv)  cpuDiv *= 2;
+       else cpuDiv=1;
+
+       ar531x_calculated_cpu_freq= (40000000/(cpuDiv)) ;
+       return ar531x_calculated_cpu_freq; 
+    }
+}
+
+#else
+unsigned int
+ar531x_cpu_frequency(void)
+{
+	static unsigned int ar531x_calculated_cpu_freq;
+        unsigned int clockctl1_predivide_mask;
+        unsigned int clockctl1_predivide_shift;
+        unsigned int clockctl1_multiplier_mask;
+        unsigned int clockctl1_multiplier_shift;
+        unsigned int clockctl1_doubler_mask;
+        int wisoc_revision;
+
+        /*
+         * Trust the bootrom's idea of cpu frequency.
+         */
+        ar531x_calculated_cpu_freq = sysRegRead(AR5312_SCRATCH);
+        if (ar531x_calculated_cpu_freq)
+	    return ar531x_calculated_cpu_freq;
+
+        wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;
+
+        if (wisoc_revision == AR531X_REV_MAJ_AR2313) {
+            clockctl1_predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;
+            clockctl1_predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;
+            clockctl1_multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;
+            clockctl1_multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;
+            clockctl1_doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;
+        } else { /* AR5312 and AR2312 */
+            clockctl1_predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;
+            clockctl1_predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;
+            clockctl1_multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;
+            clockctl1_multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;
+            clockctl1_doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;
+        }
+
+        /*
+         * Clocking is derived from a fixed 40MHz input clock.
+         *  cpuFreq = InputClock * MULT (where MULT is PLL multiplier)
+         *
+         *  sysFreq = cpuFreq / 4       (used for APB clock, serial,
+         *                               flash, Timer, Watchdog Timer)
+         *
+         *  cntFreq = cpuFreq / 2       (use for CPU count/compare)
+         *
+         * So, for example, with a PLL multiplier of 5, we have
+         *  cpuFrez = 200MHz
+         *  sysFreq = 50MHz
+         *  cntFreq = 100MHz
+         *
+         * We compute the CPU frequency, based on PLL settings.
+         */
+	if (ar531x_calculated_cpu_freq == 0) {
+            unsigned int clockCtl1 = sysRegRead(AR5312_CLOCKCTL1);
+
+            int preDivideSelect = (clockCtl1 & clockctl1_predivide_mask) >>
+                                   clockctl1_predivide_shift;
+
+            int preDivisor = CLOCKCTL1_PREDIVIDE_TABLE[preDivideSelect];
+
+            int multiplier = (clockCtl1 & clockctl1_multiplier_mask) >>
+                              clockctl1_multiplier_shift;
+
+            if (clockCtl1 & clockctl1_doubler_mask) {
+                multiplier = multiplier << 1;
+            }
+
+            ar531x_calculated_cpu_freq = (40000000 / preDivisor) * multiplier;
+        }
+
+	return ar531x_calculated_cpu_freq;
+}
+#endif
+
+unsigned int
+ar531x_sys_frequency(void)
+{
+	static unsigned int ar531x_calculated_sys_freq = 0;
+
+	if (ar531x_calculated_sys_freq == 0) {
+		ar531x_calculated_sys_freq = ar531x_cpu_frequency() / 4;
+	}
+
+	return ar531x_calculated_sys_freq;
+}
+
+static void __init
+flash_setup(void)
+{
+    UINT32 flash_ctl;
+#ifndef CONFIG_AR5315
+    /* Configure flash bank 0 */
+    flash_ctl = FLASHCTL_E |
+                FLASHCTL_AC_8M |
+                FLASHCTL_RBLE |
+                (0x01 << FLASHCTL_IDCY_S) |
+                (0x07 << FLASHCTL_WST1_S) |
+                (0x07 << FLASHCTL_WST2_S) |
+                (sysRegRead(AR531X_FLASHCTL0) & FLASHCTL_MW);
+
+    sysRegWrite(AR531X_FLASHCTL0, flash_ctl);
+
+    /* Disable other flash banks */
+    sysRegWrite(AR531X_FLASHCTL1,
+                sysRegRead(AR531X_FLASHCTL1) & ~(FLASHCTL_E | FLASHCTL_AC));
+
+    sysRegWrite(AR531X_FLASHCTL2,
+                sysRegRead(AR531X_FLASHCTL2) & ~(FLASHCTL_E | FLASHCTL_AC));
+#endif
+}
+
+
+
+void __init
+serial_setup(void)
+{
+	struct serial_struct s;
+
+	memset(&s, 0, sizeof(s));
+
+	s.flags = STD_COM_FLAGS;
+	s.io_type = SERIAL_IO_MEM;
+#if CONFIG_AR5315
+	s.baud_base = ar531x_apb_frequency()/16;
+#else
+	s.baud_base = ar531x_sys_frequency()/16;
+#endif
+	s.irq = AR531X_MISC_IRQ_UART0;
+	s.iomem_reg_shift = 2;
+#if CONFIG_AR5315
+	s.iomem_base = (u8 *)AR5315_UART0;
+#else
+	s.iomem_base = (u8 *)AR531X_UART0;
+#endif
+
+	if (early_serial_setup(&s) != 0)
+		printk(KERN_ERR "early_serial_setup failed\n");
+}
+
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+static void __init
+ar531x_timer_setup(struct irqaction *irq)
+{
+        unsigned int count;
+
+	/* Usually irq is timer_irqaction (timer_interrupt) */
+      	setup_irq(AR531X_IRQ_CPU_CLOCK, irq);
+
+        /* to generate the first CPU timer interrupt */
+        count = read_c0_count();
+        write_c0_compare(count + 1000);
+}
+
+extern void (*board_time_init)(void);
+
+static void __init
+ar531x_time_init(void)
+{
+	mips_hpt_frequency = ar531x_cpu_frequency() / 2;
+}
+
+void __init
+ar531x_setup(void)
+{
+	/* Clear any lingering AHB errors */
+#if CONFIG_AR5315
+	unsigned int config = read_c0_config();
+	write_c0_config(config & ~0x3);
+	sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
+	sysRegRead(AR5315_AHB_ERR1);
+	sysRegWrite(AR5315_WDC, WDC_IGNORE_EXPIRATION);
+#else
+	sysRegRead(AR531X_PROCADDR);
+	sysRegRead(AR531X_DMAADDR);
+
+	sysRegWrite(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION);
+
+#endif
+
+        /* Disable data watchpoints */
+        write_c0_watchlo0(0);
+
+	board_time_init = ar531x_time_init;
+        board_timer_setup = ar531x_timer_setup;
+
+        _machine_restart = ar531x_restart;
+        _machine_halt = ar531x_halt;
+        _machine_power_off = ar531x_power_off;
+
+        flash_setup();
+        serial_setup();
+}
diff -urN linux-mips/arch/mips/ar531x/Makefile mips-linux-2.4.25/arch/mips/ar531x/Makefile
--- linux-mips/arch/mips/ar531x/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/Makefile	2005-12-30 17:26:29.912989328 +0000
@@ -0,0 +1,33 @@
+#
+# 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
+# for more details.
+#
+# Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+#
+
+# Makefile for Atheros ar531x boards
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
+
+O_TARGET:= ar531x.o
+
+export-objs = ar531xksyms.o
+
+obj-y    := ar531xdbg_io.o	\
+	ar531xsetup.o	\
+	ar531xprom.o	\
+	ar531xirq.o	\
+	ar531xintr.o	\
+	ar531xgpio.o	\
+	ar531xksyms.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-mips/arch/mips/ar531x/README mips-linux-2.4.25/arch/mips/ar531x/README
--- linux-mips/arch/mips/ar531x/README	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/README	2005-12-30 17:26:30.478903296 +0000
@@ -0,0 +1,68 @@
+Basic information for the AR531X Board Support Package
+
+This directory contains the "LBSP" -- Linux Board Support Package --
+for Linux on the Atheros AR531X Wireless System-On-a-Chip.  It is intended
+primarily as a building block for wireless products.  At this time, the
+AR531X Linux BSP is experimental code, and is actively UNDER CONSTRUCTION.
+
+Some components that are supported by this LBSP along with a standard 2.4
+Linux MIPS kernel include
+  R4Kc CPU
+  instruction and data caches
+  SDRAM
+  flash (Macronix, AMD, STS, etc.)
+  16550 serial port
+  ethernet MACs
+  ethernet PHY or PHY Switch (RealTek, Kendin, Marvell)
+  General-Purpose I/O pins
+  kernel debugging with kgdb
+
+This LBSP code does NOT include drivers for the wireless components of the
+chip/boards!  Drivers for those components may be distributed separately.
+In particular, the MADWiFi project under SourceForge supports (not yet!)
+wireless functions on the AR531X chipset.  See
+   http://www.sourceforge.net/projects/madwifi
+
+Files included in this BSP:
+ae531xlnx.c      - Linux-specific portions of the ethernet driver
+ae531xmac.c      - OS-independent AR531X ethernet MAC code
+ae531xmac.h      - OS-independent AR531X ethernet MAC software definitions
+ae531xreg.h      - OS-independent AR531X ethernet MAC hardware definitions
+ar531x.h         - OS-independent AR531X system hardware definitions
+ar531xlnx.h      - Linux-specific AR531X system definitions and externs
+defconfig-ar531x - Default Linux configuration file
+intr_recv.S      - Linux interrupt "glue" code
+ar531xirq.c      - Linux Interrupt Request management
+Makefile         - Linux makefile
+mvPhy.c          - OS-independent ethernet PHY code for Marvell Switch
+mvPhy.h          - OS-independent ethernet PHY definitions for Marvell Switch
+ar531xprom.c     - Linux prom "glue" code
+ar531xsetup.c    - Linux startup code
+ar531xdbg_io.c   - Support for kgdb-based debugging and for EARLY_PRINTK_HACK
+ar531xproc.c     - Pseudo-device driver for /proc/ar531x device
+ar531xgpio.c     - Support for General Purpose I/O pins
+ar531xwmacsl.c   - Wireless MAC Support Layer
+
+Additional files, distributed with the BSP:
+README           - This file
+README.BUILD     - Instructions for building a linux kernel from source
+README.EXECUTE   - Instructions for testing your linux kernel
+README.RAMDISK   - Instructions for building a root ramdisk image
+
+ramdisk.gz       - A binary ramdisk image, suitable for use with AR531X.
+DIFFS            - Directory that contains "patch" files (See README.BUILD)
+
+
+There are several ways to boot a vmlinux image on an AR531X board:
+  -You can boot in over ethernet from the vxWorks bootrom, which is preloaded
+   on all Atheros boards
+  -You can use an ICE (e.g. VisionICE) to load the vmlinux image.  You will
+   need appropriate register initialization (e.g. AP30.ini file)
+  -You can use the eCos RedBoot bootrom loader.  This is a full-featured
+   bootrom which as been ported to AR531x.  It can boot vmlinux over ethernet
+   or from flash.  Source code is available from Atheros.
+
+Please send comments, corrections, complaints, criticisms, suggestions,
+enhancements, requests, or any other reasonable communications regarding
+this effort, to "linux@atheros.com".  Your email will be received by a
+couple of engineers, and redirected as appropriate.
diff -urN linux-mips/arch/mips/ar531x/README.BUILD mips-linux-2.4.25/arch/mips/ar531x/README.BUILD
--- linux-mips/arch/mips/ar531x/README.BUILD	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/README.BUILD	2005-12-30 17:26:30.478903296 +0000
@@ -0,0 +1,47 @@
+       How to BUILD a linux kernel for an AR531X system
+
+It is expected that you will build Linux on an existing Linux system, which 
+has all of the standard Linux tools.
+
+01) Obtain a MIPS BigEndian ELF gcc-compatible toolchain.  For example,
+    if you're cross-compiling on a x86 Linux system, you could use:
+    ftp://ftp.mips.com/pub/tools/software/sde-for-linux/sdelinux-5.01-4eb.i386.rpm
+
+02) Obtain the latest working MIPS Linux kernel
+    cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs login    (password "cvs")
+    cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs co -r linux_2_4 linux
+
+    Now "cd linux".  The remainder of these instructions assume
+    that you are in the linux directory.
+
+03) Place the contents of this directory at arch/mips/ar531x.
+
+04) Use the patch command to patch generic linux files according
+    to the DIFFS directory
+    for i in arch/mips/ar531x/DIFFS/*.diff
+    do
+       patch -p1 < $i
+    done
+    NOTE: This version of the AR531X Linux BSP was tested with
+    MIPS Linux 2.4.22 as of 11/14/03.  If you use a different
+    (e.g. more recent) version of Linux source, you may need to
+    resolve some minor patch and compilation issues.
+
+05) Set up a RAMDISK image.
+    See the instructions in README.RAMDISK.
+
+06) Set up a linux configuration using ar531x/defconfig-ar531x.
+    cp arch/mips/ar531x/defconfig-ar531x .config
+    make oldconfig       (answer all questions that are asked)
+    NOTE: For development/debug purposes, you may want to
+    enable CONFIG_RUNTIME_DEBUG and CONFIG_KGDB.
+
+07) Make dependencies.
+    make dep
+
+08) Build the linux kernel
+    make
+
+09) The linux image you just built is in vmlinux.
+    See instructions in README.EXECUTE to run your vmlinux
+    image on an AP531X-based board.
diff -urN linux-mips/arch/mips/ar531x/README.EXECUTE mips-linux-2.4.25/arch/mips/ar531x/README.EXECUTE
--- linux-mips/arch/mips/ar531x/README.EXECUTE	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/README.EXECUTE	2005-12-30 17:26:30.479903144 +0000
@@ -0,0 +1,23 @@
+      How to EXECUTE a linux image on an AR531X system
+
+There are currently three ways to run you vmlinux image:
+  1) Load it using the vxWorks bootrom that is supplied with the board.
+     You can load it over ethernet or from the TFFS file system, if you
+     have sufficient flash to store the image.
+  2) Load it using an ICE (e.g. VisionICE).
+  3) Use a bootrom loader, such as eCos RedBoot.
+
+After you have booted linux:
+  By default, the root filesystem on ramdisk is read-only.
+  To make it writable, use "mount -o remount w /".
+
+  The user-level commands are slightly non-standard, as they
+  are based on "busybox".
+
+  The "wget" command is included.  You can use wget to fetch
+  files from any ftp server.  So, for instance, you can fetch
+  a kernel module and then "insmod" it.
+
+Note that the standard source-level kernel debugger, kgdb, works well
+over the serial line with this port.  We use kgdb and the kgdb_demux perl
+script -- available over the www -- for debugging.
diff -urN linux-mips/arch/mips/ar531x/README.VERSION mips-linux-2.4.25/arch/mips/ar531x/README.VERSION
--- linux-mips/arch/mips/ar531x/README.VERSION	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/arch/mips/ar531x/README.VERSION	2005-12-30 17:26:30.479903144 +0000
@@ -0,0 +1 @@
+Source release last modified: 12/16/03
diff -urN linux-mips/arch/mips/config-shared.in mips-linux-2.4.25/arch/mips/config-shared.in
--- linux-mips/arch/mips/config-shared.in	2005-12-24 15:11:15.963885864 +0000
+++ mips-linux-2.4.25/arch/mips/config-shared.in	2005-12-30 17:26:31.611731080 +0000
@@ -34,6 +34,7 @@
 dep_bool 'Support for Alchemy PB1550 board' CONFIG_MIPS_PB1550 $CONFIG_MIPS32
 dep_bool 'Support for Alchemy PB1200 board' CONFIG_MIPS_PB1200 $CONFIG_MIPS32
 dep_bool 'Support for Alchemy Hydrogen3 board' CONFIG_MIPS_HYDROGEN3 $CONFIG_MIPS32
+dep_bool 'Support for Atheros AR5312/AR2312 WiSoC (EXPERIMENTAL)' CONFIG_AR531X $CONFIG_AR531X $CONFIG_EXPERIMENTAL
 dep_bool 'Support for MyCable XXS1500 board' CONFIG_MIPS_XXS1500 $CONFIG_MIPS32
 dep_bool 'Support for 4G Systems MTX-1 board' CONFIG_MIPS_MTX1 $CONFIG_MIPS32
 dep_bool 'Support for Cogent CSB250 board' CONFIG_COGENT_CSB250 $CONFIG_MIPS32
@@ -238,6 +239,63 @@
    define_bool CONFIG_PC_KEYB y
    define_bool CONFIG_OLD_TIME_C y
 fi
+if [ "$CONFIG_AR531X" = "y" ]; then
+   define_bool CONFIG_IRQ_CPU y
+   define_bool CONFIG_CPU_R4X00 y
+   define_bool CONFIG_SERIAL y
+   define_bool CONFIG_NEW_IRQ y
+   define_bool CONFIG_NEW_TIME_C y
+   define_bool CONFIG_AR5312
+   define_bool CONFIG_NONCOHERENT_IO y
+   bool 'Enable early printk hack' CONFIG_EARLY_PRINTK_HACK
+   define_bool CONFIG_SCSI n
+   mainmenu_option next_comment
+   comment 'Board selection'
+      choice 'Board type' \
+         "UNKNOWN CONFIG_APUNKNOWN \
+	  AP30 CONFIG_AP30 \
+          AP31 CONFIG_AP31 \
+	  AP33 CONFIG_AP33 \
+    	  AP38 CONFIG_AP38 \
+	  AP43 CONFIG_AP43 \
+	  AP48 CONFIG_AP48 \
+	  AP51 CONFIG_AP51 \
+          AP30-ASK CONFIG_AP30ASK" AP30
+   if [ "$CONFIG_AP30" = "y" -o "$CONFIG_AP30ASK" = "y" ]; then
+	define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 2
+   fi
+   if [ "$CONFIG_AP33" = "y" ]; then
+	define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
+   fi
+   if [ "$CONFIG_AP38" = "y" ]; then
+	define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
+   fi
+   if [ "$CONFIG_AP43" = "y" ]; then
+	define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
+   fi
+   if [ "$CONFIG_AP48" = "y" ]; then
+	define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
+   fi
+   if [ "$CONFIG_AP51" = "y" ]; then
+	define_int CONFIG_MTD_PHYSMAP_BUSWIDTH 1
+	define_bool CONFIG_MTD_REDBOOT_PARTS y
+	define_bool CONFIG_AR5315 y
+	define_bool CONFIG_MTD_SPIFLASH y
+	define_bool CONFIG_MTD_CFI n
+	define_bool CONFIG_MTD_JEDECPROBE n
+	define_bool CONFIG_MTD_CFI_INTELEXT n
+	define_bool CONFIG_MTD_CFI_AMDSTD n
+	define_bool CONFIG_MTD_OBSOLETE_CHIPS n
+	define_bool CONFIG_MTD_AMDSTD n
+	define_bool CONFIG_MTD_JEDEC n
+	define_bool CONFIG_MTD_PHYSMAP n
+   fi
+   mainmenu_option next_comment
+   comment 'Flash Selection'
+      choice 'Flash Size' \
+         "2MB  CONFIG_FLASH_2MB \
+          4MB  CONFIG_FLASH_4MB" 2MB
+fi
 if [ "$CONFIG_CASIO_E55" = "y" ]; then
    define_bool CONFIG_IRQ_CPU y
    define_bool CONFIG_NEW_TIME_C y

diff -urN linux-mips/arch/mips/kernel/setup.c mips-linux-2.4.25/arch/mips/kernel/setup.c
--- linux-mips/arch/mips/kernel/setup.c	2005-12-24 15:11:16.188851664 +0000
+++ mips-linux-2.4.25/arch/mips/kernel/setup.c	2005-12-30 17:26:33.536438480 +0000
@@ -496,6 +496,7 @@
 	void hp_setup(void);
 	void au1x00_setup(void);
 	void frame_info_init(void);
+	void ar531x_setup(void);
 
 	frame_info_init();
 #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
@@ -693,6 +694,12 @@
                 pmc_yosemite_setup();
                 break;
 #endif
+
+#ifdef CONFIG_AR531X
+	case MACH_GROUP_AR531X:
+		ar531x_setup();
+		break;
+#endif
 	default:
 		panic("Unsupported architecture");
 	}
diff -urN linux-mips/arch/mips/Makefile mips-linux-2.4.25/arch/mips/Makefile
--- linux-mips/arch/mips/Makefile	2005-12-24 15:11:15.903894984 +0000
+++ mips-linux-2.4.25/arch/mips/Makefile	2005-12-30 17:26:29.911989480 +0000
@@ -701,6 +701,17 @@
 LOADADDR      += 0x80020000
 endif
 
+ifdef CONFIG_AR531X
+SUBDIRS       += arch/mips/ar531x
+LIBS          += arch/mips/ar531x/ar531x.o
+ifdef CONFIG_AP51
+LOADADDR      += 0x80041000
+else
+LOADADDR      += 0x80002000
+endif
+
+endif
+
 #
 # Choosing incompatible machines durings configuration will result in
 # error messages during linking.  Select a default linkscript if
diff -urN linux-mips/ath_version.mk mips-linux-2.4.25/ath_version.mk
--- linux-mips/ath_version.mk	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/ath_version.mk	2005-12-30 17:27:00.579327336 +0000
@@ -0,0 +1 @@
+EXTRAVERSION=-LSDK-5.0.0-RC5
diff -urN linux-mips/drivers/char/serial.c mips-linux-2.4.25/drivers/char/serial.c
--- linux-mips/drivers/char/serial.c	2005-12-24 15:11:21.796999096 +0000
+++ mips-linux-2.4.25/drivers/char/serial.c	2005-12-30 17:27:10.815771160 +0000
@@ -3441,7 +3441,7 @@
 
 static _INLINE_ void show_serial_version(void)
 {
- 	printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name,
+ 	printk(KERN_INFO "%s version %s%s (%s) with%s\n", serial_name,
 	       serial_version, LOCAL_VERSTRING, serial_revdate,
 	       serial_options);
 }
@@ -5567,7 +5567,7 @@
 			printk(KERN_INFO"ttyS%02d%s at 0x%p (irq = %d) is a %s\n",
 	 		       state->line + SERIAL_DEV_OFFSET,
 			       (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
-			       state->iomem_base, state->irq,
+			       (void *)state->iomem_base, state->irq,
 			       uart_config[state->type].name);
 		}
 		else {
diff -urN linux-mips/drivers/mtd/chips/cfi_cmdset_0002.c mips-linux-2.4.25/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-mips/drivers/mtd/chips/cfi_cmdset_0002.c	2005-12-24 15:11:25.102496584 +0000
+++ mips-linux-2.4.25/drivers/mtd/chips/cfi_cmdset_0002.c	2005-12-30 17:27:21.333172272 +0000
@@ -511,7 +511,7 @@
 	   or tells us why it failed. */        
 	dq6 = CMD(1<<6);
 	dq5 = CMD(1<<5);
-	timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */
+	timeo = jiffies + (HZ/1000) + 1; /* setting timeout to 1ms for now */
 		
 	oldstatus = cfi_read(map, adr);
 	status = cfi_read(map, adr);
@@ -536,16 +536,18 @@
 		if( (status & dq5) == dq5 ) {
 			/* When DQ5 raises, we must check once again
 			   if DQ6 is toggling.  If not, the erase has been
-			   completed OK.  If not, reset chip. */
+			   completed OK.  But if so, reset chip. */
 			oldstatus = cfi_read(map, adr);
 			status = cfi_read(map, adr);
 		    
 			if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) {
+#if 0
 				printk(KERN_WARNING "Warning: DQ5 raised while program operation was in progress, however operation completed OK\n" );
+#endif	
 			} else { 
 				/* DQ5 is active so we can do a reset and stop the erase */
 				cfi_write(map, CMD(0xF0), chip->start);
-				printk(KERN_WARNING "Internal flash device timeout occurred or write operation was performed while flash was programming.\n" );
+				printk(KERN_WARNING "Internal flash device timeout pt A occurred or write operation was performed while flash was programming.  timeout=%d\n",chip->word_write_time );
 			}
 		} else {
 			printk(KERN_WARNING "Waiting for write to complete timed out in do_write_oneword.");        
@@ -959,7 +961,7 @@
             {
 			    /* DQ5 is active so we can do a reset and stop the erase */
 				cfi_write(map, CMD(0xF0), chip->start);
-                printk( KERN_WARNING "Internal flash device timeout occured or write operation was performed while flash was erasing\n" );
+                printk( KERN_WARNING "Internal flash device timeout pt B occured or write operation was performed while flash was erasing\n" );
 			}
 		}
         else
diff -urN linux-mips/drivers/mtd/chips/cfi_probe.c mips-linux-2.4.25/drivers/mtd/chips/cfi_probe.c
--- linux-mips/drivers/mtd/chips/cfi_probe.c	2005-12-24 15:11:25.103496432 +0000
+++ mips-linux-2.4.25/drivers/mtd/chips/cfi_probe.c	2005-12-30 17:27:21.507145824 +0000
@@ -51,7 +51,7 @@
 			  struct flchip *chips, struct cfi_private *cfi)
 {
 	int i;
-	
+
 	if ((base + 0) >= map->size) {
 		printk(KERN_NOTICE
 			"Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
@@ -221,12 +221,10 @@
 
 static void print_cfi_ident(struct cfi_ident *cfip)
 {
-#if 0
 	if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
 		printk("Invalid CFI ident structure.\n");
 		return;
 	}	
-#endif		
 	printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
 	if (cfip->P_ADR)
 		printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
diff -urN linux-mips/drivers/mtd/chips/jedec_probe.c mips-linux-2.4.25/drivers/mtd/chips/jedec_probe.c
--- linux-mips/drivers/mtd/chips/jedec_probe.c	2005-12-24 15:11:25.126492936 +0000
+++ mips-linux-2.4.25/drivers/mtd/chips/jedec_probe.c	2005-12-30 17:27:21.532142024 +0000
@@ -104,6 +104,7 @@
 #define SST29LE512	0x003d
 #define SST39LF800	0x2781
 #define SST39LF160	0x2782
+#define SST39LF1601	0x234b
 #define SST39LF512	0x00D4
 #define SST39LF010	0x00D5
 #define SST39LF020	0x00D6
@@ -113,6 +114,8 @@
 #define SST49LF030A	0x001C
 #define SST49LF040A	0x0051
 #define SST49LF080A	0x005B
+#define SST39VF3201     0x235B
+#define SST39VF3202     0x235A
 
 /* Toshiba */
 #define TC58FVT160	0x00C2
@@ -900,7 +903,43 @@
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,256),
 		}
-	} 
+	}, {
+		mfr_id: MANUFACTURER_SST,
+		dev_id: SST39LF160,
+		name: "SST 39LF160",
+		DevSize: SIZE_2MiB,
+		CmdSet: P_ID_AMD_STD,
+		NumEraseRegions: 1,
+		regions: {ERASEINFO(0x01000,512),
+		}
+        }, {
+		mfr_id: MANUFACTURER_SST,
+		dev_id: SST39LF1601,
+		name: "SST 39LF1601",
+		DevSize: SIZE_2MiB,
+		CmdSet: P_ID_AMD_STD,
+		NumEraseRegions: 1,
+		regions: {ERASEINFO(0x01000,512),
+		}
+        }, {
+		mfr_id: MANUFACTURER_SST,
+		dev_id: SST39VF3201,
+		name: "SST 39VF3201",
+		DevSize: SIZE_4MiB,
+		CmdSet: P_ID_AMD_STD,
+		NumEraseRegions: 1,
+		regions: {ERASEINFO(0x01000,1024),
+		}
+        }, {
+		mfr_id: MANUFACTURER_SST,
+		dev_id: SST39VF3202,
+		name: "SST 39VF3202",
+		DevSize: SIZE_4MiB,
+		CmdSet: P_ID_AMD_STD,
+		NumEraseRegions: 1,
+		regions: {ERASEINFO(0x01000,1024),
+		}
+        }
 };
 
 
@@ -967,6 +1006,35 @@
 	p_cfi->cfiq->DevSize = jedec_table[index].DevSize;
 	p_cfi->cfi_mode = CFI_MODE_JEDEC;
 
+	/*
+	 * Add the following code to set the flash timing parameters.
+	 * Maybe this is done in a table somwehere else? I can't find it.
+	 */
+	   
+	   
+	switch(jedec_table[index].dev_id) {
+	case SST39VF3201:
+	case SST39VF3202:
+		p_cfi->cfiq->WordWriteTimeoutTyp = 3;  /* 8 us */
+		p_cfi->cfiq->WordWriteTimeoutMax = 4;  /* 16 us */
+		p_cfi->cfiq->BlockEraseTimeoutTyp = 15; /* Actually 18ms, max 25 */
+		p_cfi->cfiq->BlockEraseTimeoutMax =  15;  /*  Actually 25ms */ 
+		p_cfi->cfiq->ChipEraseTimeoutTyp = 16;  /* Max is 50ms, typical is 40ms */
+		p_cfi->cfiq->ChipEraseTimeoutMax = 16;
+		break;
+	case SST39LF160:
+	case SST39LF1601:
+		p_cfi->cfiq->WordWriteTimeoutTyp = 4;  /* 14 us */
+		p_cfi->cfiq->WordWriteTimeoutMax = 5;  /* 20 us */
+		p_cfi->cfiq->BlockEraseTimeoutTyp = 15; /* Actually 18ms, max 25 */
+		p_cfi->cfiq->BlockEraseTimeoutMax =  15;  /*  Actually 25ms */ 
+		p_cfi->cfiq->ChipEraseTimeoutTyp = 17;  /* Max is 70ms, typical is 40ms */
+		p_cfi->cfiq->ChipEraseTimeoutMax = 17;
+		break;
+	}
+
+
+
 	for (i=0; i<num_erase_regions; i++){
 		p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
 	}
diff -urN linux-mips/drivers/mtd/Config.in mips-linux-2.4.25/drivers/mtd/Config.in
--- linux-mips/drivers/mtd/Config.in	2005-12-24 15:11:25.091498256 +0000
+++ mips-linux-2.4.25/drivers/mtd/Config.in	2005-12-30 17:27:21.182195224 +0000
@@ -14,6 +14,9 @@
    dep_tristate '  MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
    dep_tristate '  MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD
    dep_tristate '  RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
+   if [ "$CONFIG_MTD_END_RESERVED" != "" ]; then
+      define_int CONFIG_MTD_END_RESERVED $CONFIG_MTD_END_RESERVED
+   fi
    dep_tristate '  Command line partition table parsing' CONFIG_MTD_CMDLINE_PARTS $CONFIG_MTD_PARTITIONS
    if [ "$CONFIG_ARM" = "y" ]; then
       dep_tristate '  ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS
diff -urN linux-mips/drivers/mtd/devices/Makefile mips-linux-2.4.25/drivers/mtd/devices/Makefile
--- linux-mips/drivers/mtd/devices/Makefile	2005-12-24 15:11:25.128492632 +0000
+++ mips-linux-2.4.25/drivers/mtd/devices/Makefile	2005-12-30 17:27:21.561137616 +0000
@@ -22,5 +22,6 @@
 obj-$(CONFIG_MTD_MTDRAM)	+= mtdram.o
 obj-$(CONFIG_MTD_LART)		+= lart.o
 obj-$(CONFIG_MTD_BLKMTD)	+= blkmtd.o
+obj-$(CONFIG_MTD_SPIFLASH)      += spiflash.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-mips/drivers/mtd/devices/spiflash.c mips-linux-2.4.25/drivers/mtd/devices/spiflash.c
--- linux-mips/drivers/mtd/devices/spiflash.c	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/drivers/mtd/devices/spiflash.c	2005-12-30 17:27:21.652123784 +0000
@@ -0,0 +1,506 @@
+
+/*
+ * MTD driver for the SPI Flash Memory support.
+ *
+ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/drivers/mtd/devices/spiflash.c#3 $
+ *
+ *
+ * Copyright (c) 2005-2006 Atheros Communications Inc.
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/*===========================================================================
+** !!!!  VERY IMPORTANT NOTICE !!!!  FLASH DATA STORED IN LITTLE ENDIAN FORMAT
+**
+** This module contains the Serial Flash access routines for the Atheros SOC.
+** The Atheros SOC integrates a SPI flash controller that is used to access
+** serial flash parts. The SPI flash controller executes in "Little Endian"
+** mode. THEREFORE, all WRITES and READS from the MIPS CPU must be
+** BYTESWAPPED! The SPI Flash controller hardware by default performs READ
+** ONLY byteswapping when accessed via the SPI Flash Alias memory region
+** (Physical Address 0x0800_0000 - 0x0fff_ffff). The data stored in the
+** flash sectors is stored in "Little Endian" format.
+**
+** The spiflash_write() routine performs byteswapping on all write
+** operations.
+**===========================================================================*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include "spiflash.h"
+
+/* debugging */
+/* #define SPIFLASH_DEBUG */
+
+#ifndef __BIG_ENDIAN
+#error This driver currently only works with big endian CPU.
+#endif
+
+static char module_name[] = "spiflash";
+
+#define MIN(a,b)        ((a) < (b) ? (a) : (b))
+#define FALSE 	0
+#define TRUE 	1
+
+#define ROOTFS_NAME	"rootfs"
+
+static __u32 spiflash_regread32(int reg);
+static void spiflash_regwrite32(int reg, __u32 data);
+static __u32 spiflash_sendcmd (int op);
+
+int __init spiflash_init (void);
+void __exit spiflash_exit (void);
+static int spiflash_probe (void);
+static int spiflash_erase (struct mtd_info *mtd,struct erase_info *instr);
+static int spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf);
+static int spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf);
+
+/* Flash configuration table */
+struct flashconfig {
+    __u32 byte_cnt;
+    __u32 sector_cnt;
+    __u32 sector_size;
+    __u32 cs_addrmask;
+} flashconfig_tbl[MAX_FLASH] =
+    {
+        { 0, 0, 0, 0},
+        { STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE, 0x0},
+        { STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE, 0x0},
+        { STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE, 0x0}
+    };
+
+/* Mapping of generic opcodes to STM serial flash opcodes */
+struct opcodes {
+    __u16 code;
+    __s8 tx_cnt;
+    __s8 rx_cnt;
+} stm_opcodes[] = {
+        {STM_OP_WR_ENABLE, 1, 0},
+        {STM_OP_WR_DISABLE, 1, 0},
+        {STM_OP_RD_STATUS, 1, 1},
+        {STM_OP_WR_STATUS, 1, 0},
+        {STM_OP_RD_DATA, 4, 4},
+        {STM_OP_FAST_RD_DATA, 1, 0},
+        {STM_OP_PAGE_PGRM, 8, 0},
+        {STM_OP_SECTOR_ERASE, 4, 0},
+        {STM_OP_BULK_ERASE, 1, 0},
+        {STM_OP_DEEP_PWRDOWN, 1, 0},
+        {STM_OP_RD_SIG, 4, 1}
+};
+
+/* Driver private data structure */
+struct spiflash_data {
+	struct 	mtd_info       *mtd;	
+	struct 	mtd_partition  *parsed_parts;     /* parsed partitions */
+	void 	*spiflash_readaddr; /* memory mapped data for read  */
+	void 	*spiflash_mmraddr;  /* memory mapped register space */
+};
+
+static struct spiflash_data *spidata;
+
+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
+
+/***************************************************************************************************/
+
+static __u32
+spiflash_regread32(int reg)
+{
+	volatile __u32 *data = (__u32 *)(spidata->spiflash_mmraddr + reg);
+
+	return (*data);
+}
+
+static void 
+spiflash_regwrite32(int reg, __u32 data)
+{
+	volatile __u32 *addr = (__u32 *)(spidata->spiflash_mmraddr + reg);
+
+	*addr = data;
+	return;
+}
+
+static __u32 
+spiflash_sendcmd (int op)
+{
+	 __u32 reg;
+	 __u32 mask;
+	struct opcodes *ptr_opcode;
+
+	ptr_opcode = &stm_opcodes[op];
+
+	do {
+		reg = spiflash_regread32(SPI_FLASH_CTL);
+	} while (reg & SPI_CTL_BUSY);
+
+	spiflash_regwrite32(SPI_FLASH_OPCODE, ptr_opcode->code);
+
+	reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt |
+        	(ptr_opcode->rx_cnt << 4) | SPI_CTL_START;
+
+	spiflash_regwrite32(SPI_FLASH_CTL, reg);
+ 
+	if (ptr_opcode->rx_cnt > 0) {
+        	do {
+          		reg = spiflash_regread32(SPI_FLASH_CTL);
+        	} while (reg & SPI_CTL_BUSY);
+
+        	reg = (__u32) spiflash_regread32(SPI_FLASH_DATA);
+
+        	switch (ptr_opcode->rx_cnt) {
+        	case 1:
+            		mask = 0x000000ff;
+            		break;
+        	case 2:
+            		mask = 0x0000ffff;
+            		break;
+        	case 3:
+            		mask = 0x00ffffff;
+            		break;
+        	default:
+            		mask = 0xffffffff;
+            		break;
+        	}
+
+        	reg &= mask;
+   	}
+	else {
+       		reg = 0;
+    	}
+
+	return reg;
+}
+
+/* Probe SPI flash device
+ * Function returns 0 for failure.
+ * and flashconfig_tbl array index for success.
+ */
+static int 
+spiflash_probe (void)
+{
+	__u32 sig;
+   	int flash_size;
+
+   	/* Read the signature on the flash device */
+   	sig = spiflash_sendcmd(SPI_RD_SIG);
+
+   	switch (sig) {
+   	case STM_8MBIT_SIGNATURE:
+            	flash_size = FLASH_1MB;
+        	break;
+        case STM_16MBIT_SIGNATURE:
+            	flash_size = FLASH_2MB;
+            	break;
+        case STM_32MBIT_SIGNATURE:
+            	flash_size = FLASH_4MB;
+            	break;
+        default:
+	    	printk (KERN_WARNING "%s: Read of flash device signature failed!\n", module_name);
+            	return (0);
+   	}
+
+   	return (flash_size);
+}
+
+
+static int 
+spiflash_erase (struct mtd_info *mtd,struct erase_info *instr)
+{
+	struct opcodes *ptr_opcode;
+	__u32 temp, reg;
+	int finished = FALSE;
+
+#ifdef SPIFLASH_DEBUG
+   	printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
+#endif
+
+   	/* sanity checks */
+   	if (instr->addr + instr->len > mtd->size) return (-EINVAL);
+
+	ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE];
+
+	temp = ((__u32)instr->addr << 8) | (__u32)(ptr_opcode->code);
+	spiflash_sendcmd(SPI_WRITE_ENABLE);
+	do {
+		reg = spiflash_regread32(SPI_FLASH_CTL);
+	} while (reg & SPI_CTL_BUSY);
+
+	spiflash_regwrite32(SPI_FLASH_OPCODE, temp);
+
+	reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | SPI_CTL_START;
+	spiflash_regwrite32(SPI_FLASH_CTL, reg);
+
+	do {
+		reg = spiflash_sendcmd(SPI_RD_STATUS);
+		if (!(reg & SPI_STATUS_WIP)) {
+			finished = TRUE;
+		}
+	} while (!finished);
+
+   	instr->state = MTD_ERASE_DONE;
+   	if (instr->callback) instr->callback (instr);
+
+#ifdef SPIFLASH_DEBUG
+   	printk (KERN_DEBUG "%s return\n",__FUNCTION__);
+#endif
+   	return (0);
+}
+
+static int 
+spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf)
+{
+	u_char	*read_addr;
+
+#ifdef SPIFLASH_DEBUG
+   	printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,(int)len);  
+#endif
+
+   	/* sanity checks */
+   	if (!len) return (0);
+   	if (from + len > mtd->size) return (-EINVAL);
+	
+
+   	/* we always read len bytes */
+   	*retlen = len;
+
+	read_addr = (u_char *)(spidata->spiflash_readaddr + from);
+	memcpy(buf, read_addr, len);
+
+   	return (0);
+}
+
+static int 
+spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
+{
+	int done = FALSE, page_offset, bytes_left, finished;
+	__u32 xact_len, spi_data = 0, opcode, reg;
+
+#ifdef SPIFLASH_DEBUG
+   	printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len); 
+#endif
+
+   	*retlen = 0;
+	
+   	/* sanity checks */
+   	if (!len) return (0);
+   	if (to + len > mtd->size) return (-EINVAL);
+	
+	opcode = stm_opcodes[SPI_PAGE_PROGRAM].code;
+	bytes_left = len;
+	
+	while (done == FALSE) {
+		xact_len = MIN(bytes_left, sizeof(__u32));
+
+		/* 32-bit writes cannot span across a page boundary
+		 * (256 bytes). This types of writes require two page
+		 * program operations to handle it correctly. The STM part
+		 * will write the overflow data to the beginning of the
+		 * current page as opposed to the subsequent page.
+		 */
+		page_offset = (to & (STM_PAGE_SIZE - 1)) + xact_len;
+
+		if (page_offset > STM_PAGE_SIZE) {
+			xact_len -= (page_offset - STM_PAGE_SIZE);
+		}
+
+		spiflash_sendcmd(SPI_WRITE_ENABLE);
+
+		do {
+			reg = spiflash_regread32(SPI_FLASH_CTL);
+		} while (reg & SPI_CTL_BUSY);
+	
+		switch (xact_len) {
+			case 1:
+			 	(__u8)spi_data = *buf;
+				break;
+			case 2:
+				spi_data = (buf[1] << 8) | buf[0];
+				break;
+			case 3:
+				spi_data = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+				break;
+			case 4:
+				spi_data = (buf[3] << 24) | (buf[2] << 16) | 
+							(buf[1] << 8) | buf[0];
+				break;
+			default:
+				printk("spiflash_write: default case\n");
+				break;
+		}
+
+		spiflash_regwrite32(SPI_FLASH_DATA, spi_data);
+		opcode = (opcode & SPI_OPCODE_MASK) | ((__u32)to << 8);
+		spiflash_regwrite32(SPI_FLASH_OPCODE, opcode);
+
+		reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | (xact_len + 4) | SPI_CTL_START;
+		spiflash_regwrite32(SPI_FLASH_CTL, reg);
+		finished = FALSE;
+		
+		do {
+			udelay(1);
+			reg = spiflash_sendcmd(SPI_RD_STATUS);
+			if (!(reg & SPI_STATUS_WIP)) {
+				finished = TRUE;
+			}
+		} while (!finished);
+
+		bytes_left -= xact_len;
+		to += xact_len;
+		buf += xact_len;
+
+   		*retlen += xact_len;
+
+		if (bytes_left == 0) {
+			done = TRUE;
+		}
+	}
+
+   	return (0);
+}
+
+
+int __init 
+spiflash_init (void)
+{
+   	int result, i;
+   	int index, num_parts;
+	struct mtd_info *mtd;
+	struct  mtd_partition  *mtd_parts;
+
+   	spidata = kmalloc(sizeof(struct spiflash_data), GFP_KERNEL);
+   	if (!spidata)
+		return (-ENXIO);
+
+	spidata->spiflash_mmraddr = ioremap_nocache(SPI_FLASH_MMR, SPI_FLASH_MMR_SIZE);
+	if (!spidata->spiflash_mmraddr) {
+       		printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
+		kfree(spidata);
+       		return (-ENXIO);
+	}
+
+   	mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
+   	if (!mtd) {
+		kfree(spidata);
+		return (-ENXIO);
+	}
+	
+   	memset (mtd,0,sizeof (*mtd));
+	
+   	printk ("MTD driver for SPI flash.\n");
+   	printk ("%s: Probing for Serial flash ...\n", module_name);
+   	if (!(index = spiflash_probe ())) {
+       		printk (KERN_WARNING "%s: Found no serial flash device\n", module_name);
+		kfree(mtd);
+		kfree(spidata);
+       		return (-ENXIO);
+   	}
+   	printk ("%s: Found SPI serial Flash.\n", module_name);
+   	printk ("%d: size\n", flashconfig_tbl[index].byte_cnt);
+
+	spidata->spiflash_readaddr = ioremap_nocache(SPI_FLASH_READ, flashconfig_tbl[index].byte_cnt);
+	if (!spidata->spiflash_readaddr) {
+       		printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
+		kfree(mtd);
+		kfree(spidata);
+       		return (-ENXIO);
+	}
+
+   	mtd->name = module_name;
+   	mtd->type = MTD_NORFLASH;
+   	mtd->flags = (MTD_CAP_NORFLASH|MTD_WRITEABLE);
+   	mtd->size = flashconfig_tbl[index].byte_cnt;
+   	mtd->erasesize = flashconfig_tbl[index].sector_size;
+   	mtd->numeraseregions = 0;
+   	mtd->eraseregions = NULL;
+   	mtd->module = THIS_MODULE;
+   	mtd->erase = spiflash_erase;
+   	mtd->read = spiflash_read;
+   	mtd->write = spiflash_write;
+	
+#ifdef SPIFLASH_DEBUG
+	printk (KERN_DEBUG
+		   "mtd->name = %s\n"
+		   "mtd->size = 0x%.8x (%uM)\n"
+		   "mtd->erasesize = 0x%.8x (%uK)\n"
+		   "mtd->numeraseregions = %d\n",
+		   mtd->name,
+		   mtd->size, mtd->size / (1024*1024),
+		   mtd->erasesize, mtd->erasesize / 1024,
+		   mtd->numeraseregions);
+
+   	if (mtd->numeraseregions) {
+	 	for (result = 0; result < mtd->numeraseregions; result++) {
+	   		printk (KERN_DEBUG
+			   "\n\n"
+			   "mtd->eraseregions[%d].offset = 0x%.8x\n"
+			   "mtd->eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
+			   "mtd->eraseregions[%d].numblocks = %d\n",
+			   result,mtd->eraseregions[result].offset,
+			   result,mtd->eraseregions[result].erasesize,mtd->eraseregions[result].erasesize / 1024,
+			   result,mtd->eraseregions[result].numblocks);
+         	}
+    	}
+#endif
+
+#ifndef CONFIG_BLK_DEV_INITRD
+   	/* parse redboot partitions */
+   	num_parts = parse_redboot_partitions(mtd, &spidata->parsed_parts);
+
+#ifdef SPIFLASH_DEBUG
+   	printk (KERN_DEBUG "Found %d redboot partitions\n", num_parts);
+#endif
+
+	if (num_parts) {
+   		result = add_mtd_partitions(mtd, spidata->parsed_parts, num_parts);
+		/* Find root partition */
+		mtd_parts = spidata->parsed_parts;
+		for (i=0; i < num_parts; i++) {
+			if (!strcmp(mtd_parts[i].name, ROOTFS_NAME)) {
+				/* Create root device */
+        			ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, i);
+				break;
+			}
+		}
+	} else {
+#ifdef SPIFLASH_DEBUG
+   	printk (KERN_DEBUG "Did not find any redboot partitions\n");
+#endif
+		kfree(mtd);
+		kfree(spidata);
+       		return (-ENXIO);
+	}
+#endif
+
+	spidata->mtd = mtd;
+
+   	return (result);
+}
+
+void __exit 
+spiflash_exit (void)
+{
+    	if (spidata && spidata->parsed_parts) {
+        	del_mtd_partitions (spidata->mtd);
+		kfree(spidata->mtd);
+		kfree(spidata);
+    	}
+}
+
+module_init (spiflash_init);
+module_exit (spiflash_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Atheros Communications Inc");
+MODULE_DESCRIPTION("MTD driver for SPI Flash on Atheros SOC");
+
diff -urN linux-mips/drivers/mtd/devices/spiflash.h mips-linux-2.4.25/drivers/mtd/devices/spiflash.h
--- linux-mips/drivers/mtd/devices/spiflash.h	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/drivers/mtd/devices/spiflash.h	2005-12-30 17:27:21.652123784 +0000
@@ -0,0 +1,113 @@
+/*
+ * SPI Flash Memory support header file.
+ *
+ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/drivers/mtd/devices/spiflash.h#3 $
+ *
+ *
+ * Copyright (c) 2005, Atheros Communications Inc.
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#define FLASH_1MB  1
+#define FLASH_2MB  2
+#define FLASH_4MB  3
+#define MAX_FLASH  4
+
+#define STM_PAGE_SIZE           256
+
+#define STM_8MBIT_SIGNATURE     0x13
+#define STM_M25P80_BYTE_COUNT   1048576
+#define STM_M25P80_SECTOR_COUNT 16
+#define STM_M25P80_SECTOR_SIZE  0x10000
+
+#define STM_16MBIT_SIGNATURE    0x14
+#define STM_M25P16_BYTE_COUNT   2097152
+#define STM_M25P16_SECTOR_COUNT 32
+#define STM_M25P16_SECTOR_SIZE  0x10000
+
+#define STM_32MBIT_SIGNATURE    0x15
+#define STM_M25P32_BYTE_COUNT   4194304
+#define STM_M25P32_SECTOR_COUNT 64
+#define STM_M25P32_SECTOR_SIZE  0x10000
+
+#define STM_1MB_BYTE_COUNT   STM_M25P80_BYTE_COUNT
+#define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT
+#define STM_1MB_SECTOR_SIZE  STM_M25P80_SECTOR_SIZE
+#define STM_2MB_BYTE_COUNT   STM_M25P16_BYTE_COUNT
+#define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT
+#define STM_2MB_SECTOR_SIZE  STM_M25P16_SECTOR_SIZE
+#define STM_4MB_BYTE_COUNT   STM_M25P32_BYTE_COUNT
+#define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT
+#define STM_4MB_SECTOR_SIZE  STM_M25P32_SECTOR_SIZE
+
+#define SPI_WRITE_ENABLE    0
+#define SPI_WRITE_DISABLE   1
+#define SPI_RD_STATUS       2
+#define SPI_WR_STATUS       3
+#define SPI_RD_DATA         4
+#define SPI_FAST_RD_DATA    5
+#define SPI_PAGE_PROGRAM    6
+#define SPI_SECTOR_ERASE    7
+#define SPI_BULK_ERASE      8
+#define SPI_DEEP_PWRDOWN    9
+#define SPI_RD_SIG          10
+#define SPI_MAX_OPCODES     11
+
+#define SFI_WRITE_BUFFER_SIZE   4
+#define SFI_FLASH_ADDR_MASK     0x00ffffff
+
+/*
+ * ST Microelectronics Opcodes for Serial Flash
+ */
+
+#define STM_OP_WR_ENABLE       0x06     /* Write Enable */
+#define STM_OP_WR_DISABLE      0x04     /* Write Disable */
+#define STM_OP_RD_STATUS       0x05     /* Read Status */
+#define STM_OP_WR_STATUS       0x01     /* Write Status */
+#define STM_OP_RD_DATA         0x03     /* Read Data */
+#define STM_OP_FAST_RD_DATA    0x0b     /* Fast Read Data */
+#define STM_OP_PAGE_PGRM       0x02     /* Page Program */
+#define STM_OP_SECTOR_ERASE    0xd8     /* Sector Erase */
+#define STM_OP_BULK_ERASE      0xc7     /* Bulk Erase */
+#define STM_OP_DEEP_PWRDOWN    0xb9     /* Deep Power-Down Mode */
+#define STM_OP_RD_SIG          0xab     /* Read Electronic Signature */
+
+#define STM_STATUS_WIP       0x01       /* Write-In-Progress */
+#define STM_STATUS_WEL       0x02       /* Write Enable Latch */
+#define STM_STATUS_BP0       0x04       /* Block Protect 0 */
+#define STM_STATUS_BP1       0x08       /* Block Protect 1 */
+#define STM_STATUS_BP2       0x10       /* Block Protect 2 */
+#define STM_STATUS_SRWD      0x80       /* Status Register Write Disable */
+
+/*
+ * SPI Flash Interface Registers
+ */
+#define AR531XPLUS_SPI_READ     0x1fc00000
+#define AR531XPLUS_SPI_MMR      0x11300000
+#define AR531XPLUS_SPI_MMR_SIZE 12
+
+#define AR531XPLUS_SPI_CTL      0x00
+#define AR531XPLUS_SPI_OPCODE   0x04
+#define AR531XPLUS_SPI_DATA     0x08
+
+#define SPI_FLASH_READ          AR531XPLUS_SPI_READ
+#define SPI_FLASH_MMR           AR531XPLUS_SPI_MMR
+#define SPI_FLASH_MMR_SIZE      AR531XPLUS_SPI_MMR_SIZE
+#define SPI_FLASH_CTL           AR531XPLUS_SPI_CTL
+#define SPI_FLASH_OPCODE        AR531XPLUS_SPI_OPCODE
+#define SPI_FLASH_DATA          AR531XPLUS_SPI_DATA
+
+#define SPI_CTL_START           0x00000100
+#define SPI_CTL_BUSY            0x00010000
+#define SPI_CTL_TXCNT_MASK      0x0000000f
+#define SPI_CTL_RXCNT_MASK      0x000000f0
+#define SPI_CTL_TX_RX_CNT_MASK  0x000000ff
+#define SPI_CTL_SIZE_MASK       0x00060000
+
+#define SPI_CTL_CLK_SEL_MASK    0x03000000
+#define SPI_OPCODE_MASK         0x000000ff
+
+#define SPI_STATUS_WIP		STM_STATUS_WIP
diff -urN linux-mips/drivers/mtd/maps/Config.in mips-linux-2.4.25/drivers/mtd/maps/Config.in
--- linux-mips/drivers/mtd/maps/Config.in	2005-12-24 15:11:25.158488072 +0000
+++ mips-linux-2.4.25/drivers/mtd/maps/Config.in	2005-12-30 17:27:21.660122568 +0000
@@ -9,7 +9,14 @@
 dep_tristate '  CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_GEN_PROBE
 if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then
    hex '    Physical start address of flash mapping' CONFIG_MTD_PHYSMAP_START 0x8000000
-   hex '    Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
+   if [ "$CONFIG_FLASH_2MB" = "y" ]; then
+	define_hex CONFIG_MTD_PHYSMAP_LEN 200000
+   fi	
+   if [ "$CONFIG_FLASH_4MB" = "y" ]; then
+	define_hex CONFIG_MTD_PHYSMAP_LEN 400000
+   fi	
+
+#   hex '    Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
    int '    Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2
 fi
 
diff -urN linux-mips/drivers/mtd/maps/physmap.c mips-linux-2.4.25/drivers/mtd/maps/physmap.c
--- linux-mips/drivers/mtd/maps/physmap.c	2005-12-24 15:11:25.217479104 +0000
+++ mips-linux-2.4.25/drivers/mtd/maps/physmap.c	2005-12-30 17:27:22.044064200 +0000
@@ -80,12 +80,25 @@
 };
 
 #ifdef CONFIG_MTD_PARTITIONS
-#ifdef CONFIG_MTD_CMDLINE_PARTS
+#if defined(CONFIG_MTD_CMDLINE_PARTS) || defined(CONFIG_MTD_REDBOOT_PARTS)
 static struct mtd_partition *mtd_parts = 0;
 static int                   mtd_parts_nb = 0;
 #else
 static struct mtd_partition physmap_partitions[] = {
 /* Put your own partition definitions here */
+    {
+        name:   "rootfs",
+#ifdef CONFIG_FLASH_2MB
+        size:   0x000e0000,
+	offset: 0x000f0000,
+#endif
+#ifdef CONFIG_FLASH_4MB
+        size:   0x002dd000,
+        offset: 0x00100000,
+#endif
+
+        /* Allow file system to be mounted for writing */
+    }
 #if 0
 	{
 		name:		"bootROM",
@@ -138,6 +151,22 @@
 
 		add_mtd_device(mymtd);
 #ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_REDBOOT_PARTS
+                {
+                    extern int parse_redboot_partitions(struct mtd_info *master,
+                                        struct mtd_partition **pparts);
+
+                    struct mtd_partition *rb_parts = 0;
+                    int rb_parts_nb = 0;
+
+		    rb_parts_nb = parse_redboot_partitions(mymtd, &rb_parts);
+		    if (rb_parts_nb > 0) {
+                        printk(KERN_NOTICE
+                               "Using redboot flash partitioning");
+			add_mtd_partitions (mymtd, rb_parts, rb_parts_nb);
+		    }
+                }
+#endif
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 		mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts, 
 							"phys");
@@ -147,7 +176,8 @@
 			       "Using command line partition definition\n");
 			add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
 		}
-#else
+#endif
+#if !defined(CONFIG_MTD_CMDLINE_PARTS) && !defined(CONFIG_MTD_REDBOOT_PARTS)
 		if (NUM_PARTITIONS != 0) 
 		{
 			printk(KERN_NOTICE 
diff -urN linux-mips/drivers/mtd/redboot.c mips-linux-2.4.25/drivers/mtd/redboot.c
--- linux-mips/drivers/mtd/redboot.c	2005-12-24 15:11:25.249474240 +0000
+++ mips-linux-2.4.25/drivers/mtd/redboot.c	2005-12-30 17:27:22.517992152 +0000
@@ -51,8 +51,14 @@
 		return -ENOMEM;
 
 	/* Read the start of the last erase block */
-	ret = master->read(master, master->size - master->erasesize,
+        {
+        u_int32_t part_table_start = master->size - master->erasesize;
+#if defined(CONFIG_MTD_END_RESERVED)
+        part_table_start -= CONFIG_MTD_END_RESERVED;
+#endif
+	ret = master->read(master, part_table_start,
 			   PAGE_SIZE, &retlen, (void *)buf);
+        }
 
 	if (ret)
 		goto out;
diff -urN linux-mips/drivers/net/Config.in mips-linux-2.4.25/drivers/net/Config.in
--- linux-mips/drivers/net/Config.in	2005-12-24 15:11:25.725401888 +0000
+++ mips-linux-2.4.25/drivers/net/Config.in	2005-12-30 17:27:22.684966768 +0000
@@ -24,6 +24,18 @@
 comment 'Ethernet (10 or 100Mbit)'
 bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
 if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
+   define_bool CONFIG_VENETDEV n
+   tristate ' BUILT-IN ATHEROS ENET DRIVER' CONFIG_NET_ATHEROS_ETHER
+   if [ "$CONFIG_AP38" = "y" -o "$CONFIG_AP48" = "y"  ]; then
+      define_bool CONFIG_KENDIN_ENET_PHY y
+   elif [ "$CONFIG_AP30ASK" = "y" ]; then
+      define_bool CONFIG_KENDIN_KS8995XA_ENET_PHY y
+      bool 'Multiple Ethernet address hack ' CONFIG_ASK_MULT_MAC_HACK
+   elif [ "$CONFIG_AP51" = "y" ]; then
+      define_bool CONFIG_ICPLUS_ENET_PHY y
+   else
+      define_bool CONFIG_MARVELL_ENET_PHY y
+   fi
    if [ "$CONFIG_ARM" = "y" ]; then  
       dep_bool '  ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110
       tristate '  Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS
diff -urN linux-mips/drivers/net/Makefile mips-linux-2.4.25/drivers/net/Makefile
--- linux-mips/drivers/net/Makefile	2005-12-24 15:11:25.726401736 +0000
+++ mips-linux-2.4.25/drivers/net/Makefile	2005-12-30 17:27:22.709962968 +0000
@@ -31,6 +31,10 @@
   obj-y += e1000/e1000.o
 endif
 
+ifeq ($(CONFIG_NET_ATHEROS_ETHER),y)
+  obj-y += ath/ae531x.o
+endif
+
 ifeq ($(CONFIG_BONDING),y)
   obj-y += bonding/bonding.o
 endif
@@ -53,8 +57,13 @@
 subdir-$(CONFIG_SKFP) += skfp
 subdir-$(CONFIG_E100) += e100
 subdir-$(CONFIG_E1000) += e1000
+subdir-$(CONFIG_NET_ATHEROS_ETHER) += ath
 subdir-$(CONFIG_BONDING) += bonding
 
+ifeq ($(CONFIG_ATHAP33),y)
+subdir-$(CONFIG_ATHAP33) += athap33
+endif
+
 #
 # link order important here
 #
@@ -242,6 +251,10 @@
 obj-$(CONFIG_R8169) += r8169.o
 obj-$(CONFIG_AMD8111_ETH) += amd8111e.o mii.o
 
+ifeq ($(CONFIG_ATHAP33),y)
+obj-$(CONFIG_ATHAP33) += athap33/ath_ap_mips.o
+endif
+
 # non-drivers/net drivers who want mii lib
 obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
 obj-$(CONFIG_USB_USBNET) += mii.o
diff -urN linux-mips/fs/jffs2/nodelist.h mips-linux-2.4.25/fs/jffs2/nodelist.h
--- linux-mips/fs/jffs2/nodelist.h	2005-12-24 15:11:50.407649616 +0000
+++ mips-linux-2.4.25/fs/jffs2/nodelist.h	2005-12-30 17:27:51.289618200 +0000
@@ -31,7 +31,7 @@
  * provisions above, a recipient may use your version of this file
  * under either the RHEPL or the GPL.
  *
- * $Id: nodelist.h,v 1.46.2.5 2003/11/02 13:54:20 dwmw2 Exp $
+ * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/fs/jffs2/nodelist.h#3 $
  *
  */
 
@@ -222,8 +222,8 @@
 #define ALLOC_DELETION	1	/* Deletion node. Best to allow it */
 #define ALLOC_GC	2	/* Space requested for GC. Give it or die */
 
-#define JFFS2_RESERVED_BLOCKS_BASE 3						/* Number of free blocks there must be before we... */
-#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2)		/* ... allow a normal filesystem write */
+#define JFFS2_RESERVED_BLOCKS_BASE 2						/* Number of free blocks there must be before we... */
+#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 1)		/* ... allow a normal filesystem write */
 #define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE + 1)		/* ... allow a normal filesystem deletion */
 #define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3)	/* ... wake up the GC thread */
 #define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1)		/* ... pick a block from the bad_list to GC */
diff -urN linux-mips/fs/partitions/Config.in mips-linux-2.4.25/fs/partitions/Config.in
--- linux-mips/fs/partitions/Config.in	2005-12-24 15:11:52.366351848 +0000
+++ mips-linux-2.4.25/fs/partitions/Config.in	2005-12-30 17:27:52.279467720 +0000
@@ -39,7 +39,7 @@
    fi
    if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
         "$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
-	"$CONFIG_SGI_IP27" != "y" ]; then
+	"$CONFIG_SGI_IP27" != "y" -a "$CONFIG_AR531X" != "y" ]; then
       define_bool CONFIG_MSDOS_PARTITION y
    fi
    if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_AFFS_FS" = "y" ]; then
diff -urN linux-mips/include/asm-mips/atheros/ar531xbsp.h mips-linux-2.4.25/include/asm-mips/atheros/ar531xbsp.h
--- linux-mips/include/asm-mips/atheros/ar531xbsp.h	1970-01-01 01:00:00.000000000 +0100
+++ mips-linux-2.4.25/include/asm-mips/atheros/ar531xbsp.h	2005-12-30 17:28:01.523062480 +0000
@@ -0,0 +1,17 @@
+#ifndef __ASM_ATHEROS_BSP_SUPPORT_H
+#define __ASM_ATHEROS_BSP_SUPPORT_H
+/*
+ * These are definitions and functions provided by the bsp to support the
+ * AR5312 WiSoC running LSDK.  For different BSP implementations, different
+ * BSP functions will be needed.
+ */
+
+extern unsigned int ar531x_sys_frequency(void);
+extern const char* get_system_type(void);
+
+#ifdef CONFIG_KGDB
+extern  void kgdbInit(void);
+extern int kgdbEnabled(void);
+#endif
+
+#endif /* __ASM_ATHEROS_BSP_SUPPORT_H */
diff -urN linux-mips/include/asm-mips/bootinfo.h mips-linux-2.4.25/include/asm-mips/bootinfo.h
--- linux-mips/include/asm-mips/bootinfo.h	2005-12-24 15:12:00.645093288 +0000
+++ mips-linux-2.4.25/include/asm-mips/bootinfo.h	2005-12-30 17:28:01.534060808 +0000
@@ -37,6 +37,7 @@
 #define MACH_GROUP_HP_LJ       20 /* Hewlett Packard LaserJet               */
 #define MACH_GROUP_LASAT       21
 #define MACH_GROUP_TITAN       22 /* PMC-Sierra Titan 			    */
+#define MACH_GROUP_AR531X      23 /* Atheros AR531X                         */
 
 /*
  * Valid machtype values for group unknown (low order halfword of mips_machtype)
@@ -198,6 +199,17 @@
  */
 #define	MACH_TITAN_YOSEMITE	1 	/* PMC-Sierra Yosemite */
 
+/*
+ * Valid machtype for group MACH_GROUP_AR5312
+ */
+#define MACH_ATHEROS_UNUSED     0
+#define MACH_ATHEROS_AP30       1       /* AP30 */
+#define MACH_ATHEROS_AP33	2       /* AP33 */
+#define MACH_ATHEROS_AP38       3       /* AP38 */
+#define MACH_ATHEROS_AP43       4       /* AP43 */
+#define MACH_ATHEROS_AP48       5       /* AP48 */
+#define MACH_ATHEROS_PB32       6       /* PB32 */
+
 #define CL_SIZE			(256)
 
 const char *get_system_type(void);
diff -urN linux-mips/include/asm-mips/page.h mips-linux-2.4.25/include/asm-mips/page.h
--- linux-mips/include/asm-mips/page.h	2005-12-24 15:12:01.097024584 +0000
+++ mips-linux-2.4.25/include/asm-mips/page.h	2005-12-30 17:28:01.898005480 +0000
@@ -13,7 +13,6 @@
 #include <linux/config.h>
 #include <asm/break.h>
 
-#ifdef __KERNEL__
 
 /*
  * PAGE_SHIFT determines the page size
@@ -30,6 +29,7 @@
 #define PAGE_SIZE	(1L << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
+#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #include <asm/cacheflush.h>
diff -urN linux-mips/include/asm-mips/serial.h mips-linux-2.4.25/include/asm-mips/serial.h
--- linux-mips/include/asm-mips/serial.h	2005-12-24 15:12:01.130019568 +0000
+++ mips-linux-2.4.25/include/asm-mips/serial.h	2005-12-30 17:28:02.143968088 +0000
@@ -410,6 +410,11 @@
 #define DDB5477_SERIAL_PORT_DEFNS
 #endif
 
+#if defined(CONFIG_AR531X)
+#undef RS_TABLE_SIZE
+#define RS_TABLE_SIZE 1
+#endif
+
 #define SERIAL_PORT_DFNS			\
 	ATLAS_SERIAL_PORT_DEFNS			\
 	AU1000_SERIAL_PORT_DEFNS		\
diff -urN linux-mips/kernel/printk.c mips-linux-2.4.25/kernel/printk.c
--- linux-mips/kernel/printk.c	2005-12-24 15:12:09.361768152 +0000
+++ mips-linux-2.4.25/kernel/printk.c	2005-12-30 17:28:11.943478336 +0000
@@ -383,6 +383,18 @@
 	_call_console_drivers(start_print, end, msg_level);
 }
 
+#if CONFIG_EARLY_PRINTK_HACK
+void putDebugChar(char byte);
+static void emit_log_char(char c)
+{
+	if (c == '\n') {
+		putDebugChar('\r');
+		putDebugChar('\n');
+	} else {
+		putDebugChar(c);
+	}
+}
+#else
 static void emit_log_char(char c)
 {
 	LOG_BUF(log_end) = c;
@@ -394,6 +406,7 @@
 	if (logged_chars < LOG_BUF_LEN)
 		logged_chars++;
 }
+#endif
 
 /*
  * This is printk.  It can be called from any context.  We want it to work.
@@ -696,3 +709,4 @@
 		tty->driver.write(tty, 0, msg, strlen(msg));
 	return;
 }
+
diff -urN linux-mips-orig/drivers/net/ath/ae531x.h linux-mips-new/drivers/net/ath/ae531x.h
--- linux-mips-orig/drivers/net/ath/ae531x.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ae531x.h	2005-12-31 12:33:57.672538976 +0000
@@ -0,0 +1,43 @@
+#ifndef __AE531X_H
+#define __AE531X_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <asm/io.h>
+
+#include "ar531xlnx.h"
+#include "ae531xreg.h"
+#include "ae531xmac.h"
+
+extern void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, 
+				int *rxBuffSizep);
+extern void ae531x_swptr_free(VIRT_ADDR desc);
+extern BOOL ae531x_twisted_enet(void);
+extern void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, 
+			    UINT16 data);
+extern UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
+extern void ae531x_unitLinkGained(int ethUnit);
+extern void ae531x_unitLinkLost(int ethUnit);
+extern void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
+extern void ae531x_MACReset(ae531x_MAC_t *MACInfo);
+extern void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
+extern void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
+extern void ae531x_reset(ae531x_MAC_t *MACInfo);
+extern int  ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
+extern void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
+extern void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
+extern void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
+extern void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
+extern void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
+extern void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data);
+extern void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
+extern BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
+extern UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
+extern void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
+
+#endif   /* __AE531X_H */
diff -urN linux-mips-orig/drivers/net/ath/ae531xlnx.c linux-mips-new/drivers/net/ath/ae531xlnx.c
--- linux-mips-orig/drivers/net/ath/ae531xlnx.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ae531xlnx.c	2005-12-31 12:33:57.673538824 +0000
@@ -0,0 +1,1303 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Ethernet driver for Atheros' ae531x ethernet MAC.
+ * This is a fairly generic driver, but it's intended
+ * for use in typical Atheros products.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <asm/io.h>
+
+#include "ar531xlnx.h"
+#include "ae531xreg.h"
+#include "ae531xmac.h"
+#include "ae531x.h"
+
+#ifndef EXPORT_SYMTAB
+#define EXPORT_SYMTAB
+#endif
+
+#ifdef DEBUG
+void my_mvPhyShow(int ethUnit);
+#endif
+
+static struct ar531x_boarddata *ar531x_boardConfig=NULL;
+
+static char *radioConfig=NULL;
+
+#define AE531X_LAN_PORT 0
+#define AE531X_DEV_PER_MAC 1
+
+/*
+ * ae531x_MAC_state contains driver-specific linux-specific per-MAC information.
+ * The OSinfo member of ae531x_MAC_t points to one of these.
+ */
+typedef struct ae531x_MAC_state {
+    int                         irq;
+    struct tq_struct            restart_task;
+    struct net_device_stats     stats;
+    struct ae531x_dev_sw_state  *dev_sw_state[AE531X_DEV_PER_MAC];
+    int                         primary_dev;
+    ae531x_MAC_t                MACInfo; /* hardware state */
+} ae531x_MAC_state_t;
+
+/*
+ * ae531x_dev_sw_state contains driver-specific linux-specific per-device
+ * information.  The net_device priv member points to one of these, and
+ * this structure contains a pointer to the associated MAC information.
+ */
+
+typedef struct ae531x_dev_sw_state {
+    int                     enetUnit;        /* system unit number "eth%d" */
+    int                     unit_on_MAC;     /* MAC-relative unit number */
+    struct net_device       *dev;
+    ae531x_MAC_state_t      *MAC_state;      /* underlying MAC hw/sw state */
+} ae531x_dev_sw_state_t;
+
+/*
+ * Driver-independent linux-specific per-ethernet device software information.
+ */
+static struct net_device *ae531x_MAC_dev[AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC];
+
+/* Driver-dependent per-MAC information */
+static ae531x_MAC_state_t per_MAC_info[AR531X_NUM_ENET_MAC];
+
+/*
+ * Receive buffers need enough room to hold the following:
+ * 1) a max MTU-sized packet.  
+ * 2) space for an ethernet header
+ * 3) room at the beginning of the receive buffer in order
+ *    to facilitate cooperating drivers that need to PREpend
+ *    data.
+ * 4) Depending on configuration, we may need some additional
+ *    room at the END of the rx buffer for phy-supplied
+ *    trailers (if any). (c.f. CONFIG_VENETDEV)
+ *
+ * The DMA engine insists on 32-bit aligned RX buffers.
+ * TBDXXX: With current code, the IP stack ends up looking
+ * at misaligned headers with word operations.  The misaligned
+ * reads are software-emulated via handle_adel_int.  We'd
+ * rather align the buffers on a 16-bit boundary, but the
+ * DMA engine doesn't permit it???
+ */
+#define ETH_MAX_MTU 1518
+#define AE531X_RX_BUF_SIZE \
+    (((RXBUFF_RESERVE + ETH_HLEN + ETH_MAX_MTU + PHY_TRAILER_SIZE) + 3) & ~3)
+
+/* Forward references to local functions */
+static void ae531x_TxReap(ae531x_MAC_state_t *MAC_state);
+static int ae531x_phy_poll(void *data);
+static int ae531x_MAC_stop(struct net_device *dev);
+static int ae531x_MAC_open(struct net_device *dev);
+
+/*******************************************************************************
+* ae531x_MAC_poll checks for received packets, and sends data
+* up the stack.
+*/
+int
+ae531x_MAC_poll(struct net_device *dev, int *budget)
+{
+    struct sk_buff *skb;
+    struct sk_buff *newskb;
+    char *rxBufp;
+    int unused_length;
+    VIRT_ADDR   rxDesc;
+    int length;
+    ae531x_dev_sw_state_t *dev_sw_state;
+    ae531x_MAC_state_t *MAC_state;
+    ae531x_MAC_t *MACInfo;
+    u32 cmdsts;
+    int rx_limit;
+    int rx_received;
+    int rxDescCount;
+    struct net_device *rxdev;
+    int early_stop;
+    int retval;
+#ifdef DEBUG
+	static int rxDescCountMax = 0;
+#endif
+
+    ARRIVE();
+
+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+    MAC_state = dev_sw_state->MAC_state;
+    MACInfo = &MAC_state->MACInfo;
+    rx_limit = MAC_state->dev_sw_state[MAC_state->primary_dev]->dev->quota;
+    rx_received = 0;
+
+    rxDescCount = 0;
+
+    early_stop = 0;
+    do {
+        ae531x_AckIntr(MACInfo, DmaIntRxCompleted);
+
+        for(;!early_stop;) {
+            rxDesc = MACInfo->rxQueue.curDescAddr;
+            cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));
+
+            AE531X_PRINT(AE531X_DEBUG_RX,
+                  ("examine rxDesc %p with cmdsts=0x%x\n",
+                   (void *)rxDesc, cmdsts));
+    
+            if (cmdsts & DescOwnByDma) {
+                /* There's nothing left to process in the RX ring */
+                goto rx_all_done;
+            }
+
+            rxDescCount++;
+
+            AE531X_CONSUME_DESC((&MACInfo->rxQueue));
+    
+            A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);
+
+            /*  Process a packet */
+            length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
+            if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
+                           (DescRxFirst | DescRxLast) ) {
+                /* Descriptor status indicates "NO errors" */
+                skb = AE531X_DESC_SWPTR_GET(rxDesc);
+    
+                /*
+                 * Allocate a replacement skb.
+                 * We want to get another buffer ready for Rx ASAP.
+                 */
+                newskb = (struct sk_buff *)ae531x_rxbuf_alloc(MACInfo, &rxBufp, &unused_length);
+                if(newskb == NULL ) {
+                    /*
+                     * Give this descriptor back to the DMA engine,
+                     * and drop the received packet.
+                     */
+                    MAC_state->stats.rx_dropped++;
+                    AE531X_PRINT(AE531X_DEBUG_ERROR,
+                              ("Can't allocate new skb\n"));
+                } else {
+                    AE531X_DESC_BUFPTR_SET(rxDesc, virt_to_bus(rxBufp));
+                    AE531X_DESC_SWPTR_SET(rxDesc, newskb);
+                }
+
+                AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
+                rxDesc = NULL; /* sanity -- cannot use rxDesc now */
+                sysWbFlush();
+    
+                if (newskb == NULL) {
+                    retval = 1;
+                    goto rx_no_skbs;
+                } else {
+                    /* Sync data cache w.r.t. DMA */
+                    A_DATA_CACHE_INVAL(skb->data, length);
+        
+                    rxdev = dev_sw_state->dev;
+
+                    if (rxdev == NULL) {
+                        /*
+                         * We received a packet for a virtual enet device
+                         * that is no longer up.  Ignore it.
+                         */
+                        kfree_skb(skb);
+                        continue;
+                    }
+
+                    /* Advance data pointer to show that there's data here */
+                    skb_put(skb, length);
+                    skb->protocol = eth_type_trans(skb, rxdev);
+                    skb->dev = rxdev;
+                    rxdev->last_rx = jiffies;
+                    rxdev->quota--;
+
+                    if (rx_limit-- < 0) {
+                        early_stop=1;
+                        /* We've done enough for now -- more later */
+                        AE531X_PRINT(AE531X_DEBUG_RX_STOP,
+                            ("Enet%d RX early stop.  Quota=%d rxDescCount=%d budget=%d\n",
+                             MACInfo->unit, dev->quota, rxDescCount, *budget));
+                    }
+                    rx_received++;
+        
+                    /* Send the data up the stack */
+                    AE531X_PRINT(AE531X_DEBUG_RX,
+                              ("Send data up stack: skb=%p data=%p length=%d\n",
+                               (void *)skb, (void *)skb->data, length));
+
+                    netif_receive_skb(skb);
+
+                    MAC_state->stats.rx_packets++;
+                    MAC_state->stats.rx_bytes += length;
+                }
+            } else {
+                /* Descriptor status indicates ERRORS */
+                MAC_state->stats.rx_errors++;
+    
+                if (cmdsts & (DescRxRunt | DescRxLateColl)) {
+                    MAC_state->stats.collisions++;
+                }
+    
+                if (cmdsts & DescRxLengthError) {
+                    MAC_state->stats.rx_length_errors++;
+                }
+    
+                if (cmdsts & DescRxCrc) {
+                    MAC_state->stats.rx_crc_errors++;
+                }
+    
+                if (cmdsts & DescRxDribbling) {
+                    MAC_state->stats.rx_frame_errors++;
+                }
+				
+				AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
+
+                AE531X_PRINT(AE531X_DEBUG_ERROR,
+                          ("Bad receive.  rxDesc=%p  cmdsts=0x%8.8x\n",
+                           (void *)rxDesc, cmdsts));
+            }
+        }
+    } while ((!early_stop) &&
+             ae531x_ReadDmaReg(MACInfo, DmaStatus) & DmaIntRxCompleted);
+
+rx_all_done:
+    AE531X_PRINT(AE531X_DEBUG_RX, 
+             ("rx done (%d)\n", rxDescCount));
+    *budget -= rxDescCount;
+
+    if (!early_stop) {
+        netif_rx_complete(dev);
+
+        ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
+                     DmaIeRxCompleted | DmaIeRxNoBuffer);
+        ae531x_WriteDmaReg(MACInfo, DmaRxPollDemand, 0);
+    }
+    
+    retval = early_stop;
+
+rx_no_skbs:
+
+    LEAVE();
+
+#ifdef DEBUG
+	if (rxDescCount > rxDescCountMax) {
+		printk("max rx %d\n", rxDescCount);
+		rxDescCountMax = rxDescCount;
+	}
+#endif
+
+    return retval;
+}
+
+/*******************************************************************************
+* ae531x_restart stops all ethernet devices associated with a physical MAC,
+* then shuts down the MAC.  Then it re-opens all devices that were in use.
+* TBDXXX: needs testing!
+*/
+static void
+ae531x_restart(void *data)
+{
+    ae531x_MAC_t *MACInfo = (ae531x_MAC_t *)data;
+    ae531x_MAC_state_t *MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
+    struct net_device *saved_dev[AE531X_DEV_PER_MAC];
+    int i;
+
+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {
+        if ((saved_dev[i] = MAC_state->dev_sw_state[i]->dev) != NULL) {
+            ae531x_MAC_stop(saved_dev[i]);
+        }
+    }
+
+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {
+        if (saved_dev[i])
+            ae531x_MAC_open(saved_dev[i]);
+    }
+}
+
+/*******************************************************************************
+* ae531x_MAC_intr handle interrupts from an ethernet MAC.
+* It checks MAC status registers, and dispatches as appropriate.
+*/
+void
+ae531x_MAC_intr(int cpl, void *dev_id, struct pt_regs *regs)
+{
+	ae531x_MAC_state_t *MAC_state;
+	ae531x_MAC_t *MACInfo;
+	u32 regIsr;
+	u32 regImr;
+	u32 pendIntrs;
+
+	ARRIVE();
+	MACInfo = (ae531x_MAC_t *)dev_id;
+	MAC_state = (ae531x_MAC_state_t *)MACInfo->OSinfo;
+	for(;;) {
+		/* Clear any unhandled intr causes. */
+		ae531x_WriteDmaReg(MACInfo, DmaStatus, UnhandledIntrMask);
+
+		regIsr = ae531x_ReadDmaReg(MACInfo, DmaStatus);
+		regImr = ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
+		pendIntrs = regIsr & regImr;
+
+		AE531X_PRINT(AE531X_DEBUG_INT,
+					 ("ethmac%d: intIsr=0x%8.8x intImr=0x%8.8x pendIntrs=0x%8.8x\n",
+					  MACInfo->unit, regIsr, regImr, pendIntrs ));
+
+		if ((pendIntrs & DmaAllIntCauseMask) == 0)
+			break;
+
+		if ((pendIntrs & DmaIntRxCompleted) ||
+			(pendIntrs & DmaIntRxNoBuffer)) {
+			if (netif_rx_schedule_prep(MAC_state->dev_sw_state[MAC_state->primary_dev]->dev)) {
+				ae531x_ClearDmaReg(MACInfo,
+								   DmaIntrEnb,
+								   DmaIeRxCompleted | DmaIeRxNoBuffer);
+				ae531x_AckIntr(MACInfo,
+							   DmaIntRxCompleted | DmaIntRxNoBuffer);
+				(void)ae531x_ReadDmaReg(MACInfo, DmaIntrEnb);
+				__netif_rx_schedule(MAC_state->dev_sw_state[MAC_state->primary_dev]->dev);
+			} else {
+#if 0
+				AE531X_PRINT(AE531X_DEBUG_ERROR,
+							 ("%s: Interrupt (0x%8.8x/0x%8.8x) while in poll.  regs@%p, pc=%p, ra=%p\n",
+							  __FILE__,
+							  regIsr,
+							  ae531x_ReadDmaReg(MACInfo, DmaIntrEnb),
+							  (void *)regs,
+							  (void *)regs->cp0_epc,
+							  (void *)regs->regs[31]));
+#endif
+				ae531x_AckIntr(MACInfo,
+							   DmaIntRxCompleted | DmaIntRxNoBuffer);
+			}
+		}
+
+		if (pendIntrs &
+			(DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow)) {
+			AE531X_PRINT(AE531X_DEBUG_ERROR,
+						 ("ethmac%d: TX Error Intr (0x%x)\n",
+						  MACInfo->unit, pendIntrs));
+			ae531x_AckIntr(MACInfo,
+						   (DmaIntTxStopped | DmaIntTxJabber | DmaIntTxUnderflow));
+		}
+
+		if (pendIntrs & DmaIntBusError) {
+			AE531X_PRINT(AE531X_DEBUG_ERROR,
+						 ("ethmac%d: DMA Bus Error Intr (0x%x)\n",
+						  MACInfo->unit, pendIntrs));
+			ae531x_AckIntr(MACInfo, DmaIntBusError);
+			/* Reset the chip, if it's not already being done */
+			if (ae531x_IsInResetMode(MACInfo)) {
+				goto intr_done;
+			}
+			ae531x_BeginResetMode(MACInfo);
+			schedule_task(&MAC_state->restart_task);
+		}
+
+		if (pendIntrs & DmaIntRxStopped) {
+			AE531X_PRINT(AE531X_DEBUG_ERROR,
+						 ("ethmac%d: RX Stopped Intr (0x%x)\n",
+						  MACInfo->unit, pendIntrs));
+			ae531x_AckIntr(MACInfo, DmaIntRxStopped);
+		}
+	}
+
+ intr_done:
+	LEAVE();
+}
+
+/*******************************************************************************
+* ae531x_MAC_get_stats returns statistics for a specified device
+*/
+static struct net_device_stats*
+ae531x_MAC_get_stats(struct net_device *dev)
+{
+        ae531x_dev_sw_state_t *dev_sw_state;
+        ae531x_MAC_state_t *MAC_state;
+
+        ARRIVE();
+        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+        MAC_state = dev_sw_state->MAC_state;
+
+        LEAVE();
+        return &MAC_state->stats;
+}
+
+#define AE531X_PHY_POLL_SECONDS 2
+
+#if CONFIG_AR5315
+
+/*******************************************************************************
+* ae531x_getMACInfo returns the MACInfo  of the interface given by unit 
+*/
+ae531x_MAC_t *ae531x_getMAcInfo(int ethUnit)
+{
+  int i,j;
+  for(i=0;i<AR531X_NUM_ENET_MAC;++i) {
+    if(per_MAC_info[i].dev_sw_state) {
+      for(j=0;j<AE531X_DEV_PER_MAC;++j) {
+	 if(per_MAC_info[i].dev_sw_state[j]
+	    && per_MAC_info[i].dev_sw_state[j]->enetUnit == ethUnit)
+            return (&(per_MAC_info[i].MACInfo));
+      }
+    }
+  }
+  return NULL;
+}
+    
+
+#endif
+
+/*******************************************************************************
+* ae531x_phy_poll periodically checks for changes in phy status
+* (e.g. dropped link).
+*/
+static int
+ae531x_phy_poll(void *data)
+{
+    ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)data;
+    ae531x_MAC_t *MACInfo = &dev_sw_state->MAC_state->MACInfo;
+    int unit = dev_sw_state->enetUnit;
+
+    while(dev_sw_state->dev!=NULL) {
+        if (MACInfo->port_is_up) {
+            phyCheckStatusChange(unit);
+        }
+
+        set_current_state(TASK_UNINTERRUPTIBLE);
+        schedule_timeout(AE531X_PHY_POLL_SECONDS * HZ);
+    }
+
+    return 0;
+}
+
+
+static char invalid_enet_MAC_addr[] = {0, 0, 0, 0, 0, 0};
+
+/*
+ * Fetch a pointer to an ethernet's MAC address
+ * in the Board Configuration data (in flash).
+ */
+char *
+ae531x_enet_mac_address_get(int MACUnit)
+{
+	/* XXX: Hack for poorly configured boards.
+	 *      Cannot setup bridging properly (brctl) when both enet
+	 *      interfaces share the same MAC address.
+	 * 
+	 */
+
+#ifdef CONFIG_ASK_MULT_MAC_HACK
+    static u8  enet0Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x16};
+    static u8  enet1Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x17};
+#endif
+
+    if (!ar531x_boardConfig)
+        return invalid_enet_MAC_addr;
+    if (MACUnit == 0) {
+#ifndef CONFIG_ASK_MULT_MAC_HACK
+        return ar531x_boardConfig->enet0Mac;
+#else
+		return enet0Mac;
+#endif
+    }
+    if (MACUnit == 1) {
+#ifndef CONFIG_ASK_MULT_MAC_HACK
+        return ar531x_boardConfig->enet1Mac;
+#else
+		return enet1Mac;
+#endif
+    }
+    printk("Invalid ethernet MAC unit number (%d)!\n", MACUnit);
+    return invalid_enet_MAC_addr;
+}
+
+
+
+/*******************************************************************************
+* ae531x_MAC_open is the standard Linux open function.  It puts
+* hardware into a known good state, allocates queues, starts
+* the phy polling task, and arranges for interrupts to be handled.
+*/
+static int 
+ae531x_MAC_open(struct net_device *dev)
+{
+    ae531x_dev_sw_state_t *dev_sw_state;
+    ae531x_MAC_state_t *MAC_state;
+    ae531x_MAC_t *MACInfo;
+    u8 *MACAddr;
+    int rv;
+    struct tq_struct *restart_task;
+    pid_t phy_poll_pid;
+    ARRIVE();
+
+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+    dev_sw_state->dev = dev;
+    MAC_state = dev_sw_state->MAC_state;
+    MACInfo = &MAC_state->MACInfo;
+
+    restart_task = &MAC_state->restart_task;
+    restart_task->routine = ae531x_restart;
+    restart_task->data = (void *)MACInfo;
+
+    AE531X_PRINT(AE531X_DEBUG_RESET,
+              ("ae531x_MAC_open eth%d ethmac%d macBase=0x%x dmaBase=0x%x irq=0x%x\n",
+               dev_sw_state->enetUnit,
+               MACInfo->unit,
+               MACInfo->macBase,
+               MACInfo->dmaBase,
+               MAC_state->irq));
+
+    /* Default MAC address */
+    MACAddr = ae531x_enet_mac_address_get(MACInfo->unit);
+    memcpy(dev->dev_addr, MACAddr, dev->addr_len );
+ 
+    if (!MACInfo->port_is_up) {
+        /* Bring MAC and PHY out of reset */
+        ae531x_reset(MACInfo);
+    
+        /* Attach interrupt handler */
+        rv = request_irq(MAC_state->irq, ae531x_MAC_intr, SA_INTERRUPT,
+                    "ae531x_MAC_intr", (void *)MACInfo);
+        if (rv < 0) {
+            AE531X_PRINT(AE531X_DEBUG_ERROR,
+                         ("request_irq(0x%x) failed (%d)\n",
+                          MAC_state->irq, rv));
+            goto open_failure;
+        }
+
+        /* Initialize PHY */
+		AE531X_PRINT(AE531X_DEBUG_RESET, ("\n --- phyBase: %08x\n", MACInfo->phyBase));
+        phySetup(MACInfo->unit, MACInfo->phyBase);
+
+        /* Start thread to poll for phy link status changes */
+        phy_poll_pid = kernel_thread(ae531x_phy_poll, dev_sw_state, 0);
+        if (phy_poll_pid < 0) {
+            AE531X_PRINT(AE531X_DEBUG_ERROR,
+                     ("ethmac%d unable to start Phy Poll thread\n",
+                     MACInfo->unit));
+        }
+
+        /* Allocate RX/TX Queues */
+        if (ae531x_AllocateQueues(MACInfo) < 0) {
+            AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));
+            free_irq(MAC_state->irq, (void *)MACInfo);
+            goto open_failure;
+        }
+    
+        /* Initialize DMA and descriptors */
+        ae531x_DmaReset(MACInfo);
+
+        /* Initialize MAC */
+        ae531x_MACReset(MACInfo);
+
+        /* Enable Receive/Transmit */
+        ae531x_EnableComm(MACInfo);
+    
+        MAC_state->primary_dev = dev_sw_state->unit_on_MAC;
+        MACInfo->port_is_up = TRUE;
+    }
+
+    dev->trans_start = jiffies;
+    SET_MODULE_OWNER(dev);
+
+    LEAVE();
+    return 0;
+
+open_failure:
+    LEAVE();
+    return -1;
+}
+
+/*
+ * Shut down MAC hardware.
+ */
+static void
+ae531x_MAC_shutdown(ae531x_MAC_state_t *MAC_state)
+{
+    ae531x_MAC_t *MACInfo;
+
+    MACInfo = &MAC_state->MACInfo;
+    MACInfo->port_is_up = FALSE;
+
+    /* Disable Receive/Transmit */
+    ae531x_DisableComm(MACInfo);
+
+    /* Disable Interrupts */
+    ae531x_DmaIntDisable(MACInfo);
+    sysWbFlush();
+    free_irq(MAC_state->irq, (void *)MACInfo);
+
+    /* Free Transmit & Receive skb's/descriptors */
+    ae531x_TxReap(MAC_state); /* one last time */
+    ae531x_FreeQueues(MACInfo);
+}
+
+/*******************************************************************************
+* ae531x_MAC_stop is the standard Linux stop function.  It undoes
+* everything set up by ae531x_MAC_open.
+*/
+static int
+ae531x_MAC_stop(struct net_device *dev)
+{
+    ae531x_dev_sw_state_t *dev_sw_state;
+    ae531x_MAC_state_t *MAC_state;
+    ae531x_MAC_t *MACInfo;
+    int i;
+
+    ARRIVE();
+
+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+    MAC_state = dev_sw_state->MAC_state;
+    MACInfo = &MAC_state->MACInfo;
+
+    for (i=0; i<AE531X_DEV_PER_MAC; i++) {
+        if ((MAC_state->dev_sw_state[i]->dev) &&
+            (MAC_state->dev_sw_state[i]->dev != dev_sw_state->dev)) {
+            break;
+        }
+    }
+
+    if (i < AE531X_DEV_PER_MAC) {
+        /* Physical MAC is still in use */
+        if (MAC_state->primary_dev == dev_sw_state->unit_on_MAC) {
+            /*
+             * If the primary_dev is being stopped
+             * then we need to assign a new one.
+             */
+            MAC_state->primary_dev = i;
+        }
+    } else {
+        /* Physical MAC is no longer in use */
+        ae531x_MAC_shutdown(MAC_state);
+    }
+
+    dev_sw_state->dev = NULL;
+    LEAVE();
+    return 0;
+}
+
+/*******************************************************************************
+* ae531x_rxbuf_alloc - Allocate an skb to be associated with an RX descriptor.
+*
+* RETURNS: A pointer to the skb.  Also returns a pointer to the underlying
+* buffer and the size of that buffer. 
+*/
+void *
+ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, int *rxBuffSizep)
+{
+    int buf_size;
+    struct sk_buff *skb;
+    char *rxBuff;
+    int rxBuffSize;
+
+    buf_size = AE531X_RX_BUF_SIZE;
+
+    skb = dev_alloc_skb(buf_size);
+    if (skb) {
+        /* skb->dev = dev; */
+        skb_reserve(skb, RXBUFF_RESERVE);
+
+        rxBuffSize = skb_tailroom(skb);
+        rxBuff = skb->tail;
+
+        *rxBuffp = rxBuff;
+        *rxBuffSizep = rxBuffSize;
+    }
+
+    return skb;
+}
+
+/*******************************************************************************
+* ae531x_swptr_free - Free the skb, if any, associated with a descriptor.
+*/
+void
+ae531x_swptr_free(VIRT_ADDR desc)
+{
+    struct sk_buff *skb;
+
+    skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(desc);
+    if (skb) {
+        AE531X_DESC_SWPTR_SET(desc, NULL);
+        kfree_skb(skb);
+    }
+}
+
+/*******************************************************************************
+*
+* ae531x_TxReap - the driver Tx completion routine.
+*
+* This routine reaps sk_buffs which have already been transmitted.
+*
+*/
+static void
+ae531x_TxReap(ae531x_MAC_state_t *MAC_state)
+{
+    AE531X_QUEUE      *txq;
+    VIRT_ADDR         txDesc;
+    UINT32            cmdsts;
+    struct            sk_buff *skb;
+    int               reaped;
+    ae531x_MAC_t      *MACInfo;
+    static int        aeUselessReap = 0;
+#ifdef DEBUG
+    static int        aeMaxReap = 0;
+#endif
+    ARRIVE();
+
+    MACInfo = &MAC_state->MACInfo;
+    txq = &MACInfo->txQueue;
+    reaped = 0;
+
+    while (1) {
+
+        txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);
+        if (txDesc == txq->curDescAddr) {
+            break;
+        }
+
+        cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));
+        if (cmdsts & DescOwnByDma) {
+            break;
+        }
+
+        /* Release sk_buff associated with completed transmit */
+        skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(txDesc);
+        if (skb) {
+            kfree_skb(skb);
+            AE531X_DESC_SWPTR_SET(txDesc, NULL);
+        }
+
+        /* Update statistics according to completed transmit desc */
+        if (cmdsts & DescTxErrors) {
+            AE531X_PRINT(AE531X_DEBUG_ERROR,
+                    ("enetmac%d Tx prior error: 0x%8.8x <0x%8.8x> 0x%8.8x\n",
+                    MACInfo->unit,
+                    cmdsts,
+                    DescTxErrors,
+                    (int)txDesc));
+#ifdef DEBUG
+			//my_mvPhyShow(MACInfo->unit);
+	    printk ("ae531xMacControl: 0x%08x\tMacFlowControl: 0x%08x\n",
+		    ae531x_ReadMacReg(MACInfo, MacControl),
+		    ae531x_ReadMacReg(MACInfo, MacFlowControl));
+#endif
+            MAC_state->stats.tx_errors++;
+            if (cmdsts & (DescTxLateCollision | DescTxExcCollisions)) {
+                MAC_state->stats.tx_aborted_errors++;
+            }
+            if (cmdsts & (DescTxLostCarrier | DescTxNoCarrier)) {
+                MAC_state->stats.tx_carrier_errors++;
+            }
+        } else {
+            MAC_state->stats.tx_bytes += AE531X_DESC_STATUS_RX_SIZE(cmdsts);
+            MAC_state->stats.tx_packets++;
+        }
+
+        MAC_state->stats.collisions +=
+            ((cmdsts & DescTxCollMask) >> DescTxCollShift);
+
+        txq->reapDescAddr = txDesc;
+        reaped++;
+    }
+
+    if (reaped > 0) {
+        int i;
+
+#ifdef DEBUG
+		if (reaped > aeMaxReap) {
+			aeMaxReap = reaped;
+			printk("max reaped = %d\n", reaped);
+		}
+#endif
+        AE531X_PRINT(AE531X_DEBUG_TX_REAP,
+             ("reaped %d\n", reaped));
+
+        /*
+         * Re-start transmit queues for all ethernet devices
+         * associated with this MAC.
+         */
+        for (i=0; i<AE531X_DEV_PER_MAC; i++) {
+            if (MAC_state->dev_sw_state[i]->dev)
+                netif_start_queue(MAC_state->dev_sw_state[i]->dev);
+        }
+    } else {
+        aeUselessReap++;
+    }
+
+    LEAVE();
+}
+
+
+/*******************************************************************************
+* ae531x_MAC_start_xmit sends a packet.
+*/
+static int
+ae531x_MAC_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+    ae531x_dev_sw_state_t *dev_sw_state;
+    ae531x_MAC_state_t *MAC_state;
+    ae531x_MAC_t *MACInfo;
+    u32 buf;
+    u32 ctrlen;
+    u32 length;
+    int mtu;
+    int max_buf_size;
+    VIRT_ADDR txDesc;
+
+    ARRIVE();
+
+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+    MAC_state = dev_sw_state->MAC_state;
+    MACInfo = &MAC_state->MACInfo;
+
+    length = skb->len;
+
+    /* Check if this port is up, else toss packet */
+    if (!MACInfo->port_is_up) {
+        buf = virt_to_bus(skb->data);
+        AE531X_PRINT(AE531X_DEBUG_ERROR,
+                  ("eth%d Tx Down, dropping buf=0x%8.8x, length=0x%8.8x, skb=%p\n",
+                   dev_sw_state->enetUnit, buf, length, (void *)skb));
+
+        MAC_state->stats.tx_dropped++;
+        MAC_state->stats.tx_carrier_errors++;
+        goto dropFrame;
+    }
+
+    if (ae531x_IsInResetMode(MACInfo)) {
+        AE531X_PRINT(AE531X_DEBUG_ERROR,
+                  ("eth%d Tx: In Chip reset - drop frame\n",
+                   dev_sw_state->enetUnit));
+
+        MAC_state->stats.tx_dropped++;
+        MAC_state->stats.tx_aborted_errors++;
+        goto dropFrame;
+    }
+
+    /* Check if we can transport this packet */
+    length = max((u32)60, length);  /* total length */
+    mtu = dev->mtu;
+    max_buf_size = mtu + ETH_HLEN;
+    if (length > max_buf_size) {
+        AE531X_PRINT(AE531X_DEBUG_ERROR,
+                  ("eth%d Tx: length %d too long.  mtu=%d, trailer=%d\n",
+                   dev_sw_state->enetUnit, length, mtu, PHY_TRAILER_SIZE));
+
+        MAC_state->stats.tx_errors++;
+        MAC_state->stats.tx_aborted_errors++;
+
+        goto dropFrame;
+    }
+
+	/* Reap any old, completed Tx descriptors */
+	ae531x_TxReap(MAC_state);
+
+    txDesc = MACInfo->txQueue.curDescAddr;
+    if (txDesc == MACInfo->txQueue.reapDescAddr) {
+        int i;
+
+        AE531X_PRINT(AE531X_DEBUG_ERROR,
+                  ("eth%d Tx: cannot get txDesc\n",
+                   dev_sw_state->enetUnit));
+
+        MAC_state->stats.tx_dropped++;
+        MAC_state->stats.tx_fifo_errors++;
+
+        /*
+         * Stop transmit queues for any ethernet devices
+         * associated with this MAC.
+         */
+#if 0 /* XXX: no way to recover from queue stop until ae531x_MAC_tx_timeout()
+	   *      is rewritten to avoid calls to shedule().
+	   */
+        for (i=0; i<AE531X_DEV_PER_MAC; i++) {
+            if (MAC_state->dev_sw_state[i]->dev)
+                netif_stop_queue(MAC_state->dev_sw_state[i]->dev);
+        }
+#endif
+        goto dropFrame;
+    }
+
+    /* We won't fail now; so consume this descriptor */
+    AE531X_CONSUME_DESC((&MACInfo->txQueue));
+
+    /* Update the descriptor */
+    buf = virt_to_bus(skb->data);
+    AE531X_DESC_BUFPTR_SET(txDesc, buf);
+    AE531X_DESC_SWPTR_SET(txDesc, skb);
+    ctrlen = AE531X_DESC_CTRLEN_GET(txDesc);
+    ctrlen = (ctrlen & (DescEndOfRing)) |
+                            DescTxFirst |
+                             DescTxLast |
+                        DescTxIntEnable;
+
+    ctrlen |= ((length << DescSize1Shift) & DescSize1Mask);
+
+    AE531X_DESC_CTRLEN_SET(txDesc, ctrlen);
+    AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma);
+
+    /* Alert DMA engine to resume Tx */
+    ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0);
+    sysWbFlush();
+
+    AE531X_PRINT(AE531X_DEBUG_TX,
+              ("eth%d Tx: Desc=0x%8.8x, L=0x%8.8x, D=0x%8.8x, d=0x%8.8x, length=0x%8.8x\n",
+               dev_sw_state->enetUnit,
+               (UINT32)txDesc,
+               AE531X_DESC_CTRLEN_GET(txDesc),
+               buf,
+               AE531X_DESC_LNKBUF_GET(txDesc),
+               length));
+
+    /* Tell upper layers to keep it coming */
+    dev->trans_start = jiffies;
+
+    LEAVE();
+
+    return 0;
+
+dropFrame:
+    kfree_skb(skb);
+    LEAVE();
+    return 0;
+}
+
+
+/*******************************************************************************
+* ae531x_MAC_tx_timeout handles transmit timeouts
+*/
+static void
+ae531x_MAC_tx_timeout(struct net_device *dev)
+{
+    ae531x_dev_sw_state_t *dev_sw_state;
+    ae531x_MAC_state_t *MAC_state;
+    ae531x_MAC_t *MACInfo;
+
+    ARRIVE();
+
+    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+    MAC_state = dev_sw_state->MAC_state;
+    MACInfo = &MAC_state->MACInfo;
+
+    AE531X_PRINT(AE531X_DEBUG_ERROR,
+             ("enet%d: Tx timeout\n", dev_sw_state->enetUnit));
+
+    ae531x_restart(MACInfo);
+
+    LEAVE();
+}
+
+
+/*******************************************************************************
+* ae531x_MAC_do_ioctl is a placeholder for future ioctls.
+*/
+static int
+ae531x_MAC_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+        int rv;
+        ae531x_MAC_t *MACInfo;
+        struct ioctl_data {
+                u32 unit;
+                u32 addr;
+                u32 data;
+        } *req;
+        ae531x_dev_sw_state_t *dev_sw_state;
+        ae531x_MAC_state_t *MAC_state;
+
+        ARRIVE();
+
+        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+        MAC_state = dev_sw_state->MAC_state;
+        MACInfo = &MAC_state->MACInfo;
+
+        req = (struct ioctl_data *)ifr->ifr_data;
+
+        switch( cmd ) {
+        default:
+            AE531X_PRINT(AE531X_DEBUG_ERROR,
+                     ("Unsupported ioctl: 0x%x\n", cmd));
+            rv = -EOPNOTSUPP;
+        }
+
+        LEAVE();
+        return rv;
+}
+
+static void
+ae531x_MAC_setup_fntable(struct net_device *dev)
+{
+    ARRIVE();
+
+    dev->get_stats       = ae531x_MAC_get_stats;
+    dev->open            = ae531x_MAC_open;
+    dev->stop            = ae531x_MAC_stop;
+    dev->hard_start_xmit = ae531x_MAC_start_xmit;
+    dev->do_ioctl        = ae531x_MAC_do_ioctl;
+    dev->poll            = ae531x_MAC_poll;
+    dev->weight          = 16;
+#if 0 /* XXX: currently, ae531x_MAC_tx_timeout() will call functions
+	   *      that in turn call schedule(). this is BAD, since the
+	   *      timeout call runs at interrupt time. until ae531x_MAC_tx_timeout
+	   *      is rewritten to avoid schedule() calls, we do not use it.
+	   */
+    dev->tx_timeout      = ae531x_MAC_tx_timeout;
+#else
+    dev->tx_timeout      = NULL;
+#endif
+    dev->features        = NETIF_F_HW_CSUM |\
+                           NETIF_F_HIGHDMA;
+
+    LEAVE();
+}
+
+static void
+ar5312EepromRead(char *EepromAddr, u_int16_t id, unsigned int off, 
+		 unsigned int nbytes, char *data)
+{
+	int i;
+	
+	for (i=0; i<nbytes; i++, off++) {
+		data[i] = EepromAddr[off];
+	}
+}
+
+int
+ae531x_get_numMACs(void)
+{
+    int devid;
+    u16 radioMask;
+
+    /* Probe to find out the silicon revision and enable the
+       correct number of macs */
+    devid = ((u_int16_t) ((sysRegRead(AR531X_REV) >>8) & 
+			  (AR531X_REV_MAJ | AR531X_REV_MIN)));
+    switch (devid) {
+    case AR5212_AR5312_REV2:
+    case AR5212_AR5312_REV7:
+        /* Need to determine if we have a 5312 or a 2312 since they
+           have the same Silicon Rev ID*/
+        ar5312EepromRead(radioConfig,0,2*AR531X_RADIO_MASK_OFF,2,
+			 (char *) &radioMask);
+        if ((radioMask & AR531X_RADIO0_MASK) != 0) {
+            return 2;
+        }
+        return 1;
+    case AR5212_AR2313_REV8:
+        return 1;
+    }
+        
+    /* default to 1 */
+    return 1;
+}
+
+BOOL
+ae531x_twisted_enet(void)
+{
+    int wisoc_revision;
+
+    wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;
+    if ( (wisoc_revision == AR531X_REV_MAJ_AR2313) ||
+         /* next clause is used to determine AR2312, based on number of MACs. 
+          * must do this since revision is same for 5312 and 2312.
+          */
+         (wisoc_revision == AR531X_REV_MAJ_AR5312 && ae531x_get_numMACs() == 1) ) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+int
+ae531x_get_board_config(void)
+{
+    int dataFound;
+    char *bd_config;
+
+    /*
+     * Find start of Board Configuration data, using heuristics:
+     * Search back from the (aliased) end of flash by 0x1000 bytes
+     * at a time until we find the string "5311", which marks the
+     * start of Board Configuration.  Give up if we've searched
+     * more than 500KB.
+     */
+    dataFound = 0;
+    for (bd_config = (char *)0xbffff000;
+         bd_config > (char *)0xbff80000;
+         bd_config -= 0x1000)
+    {
+        if ( *(int *)bd_config == AR531X_BD_MAGIC) {
+            dataFound = 1;
+            break;
+        }
+    }
+
+    if (!dataFound) {
+        printk("Could not find Board Configuration Data\n");
+		bd_config = NULL;
+    }
+	
+    ar531x_boardConfig = (struct ar531x_boarddata *) bd_config;
+	
+    return(dataFound);
+}
+
+int
+ae531x_get_radio_config(void)
+{
+    int dataFound;
+    char *radio_config;
+
+    /* 
+     * Now find the start of Radio Configuration data, using heuristics:
+     * Search forward from Board Configuration data by 0x1000 bytes
+     * at a time until we find non-0xffffffff.
+     */
+    dataFound = 0;
+    for (radio_config = ((char *) ar531x_boardConfig) + 0x1000;
+         radio_config < (char *)0xbffff000;
+         radio_config += 0x1000)
+    {
+        if (*(int *)radio_config != 0xffffffff) {
+            dataFound = 1;
+            break;
+        }
+    }
+
+    if (!dataFound) { /* AR2316 relocates radio config to new location */
+	dataFound = 0;
+	for (radio_config = ((char *) ar531x_boardConfig) + 0xf8;
+	     radio_config < (char *)0xbffff0f8;
+	     radio_config += 0x1000)
+	{
+	    if (*(int *)radio_config != 0xffffffff) {
+		dataFound = 1;
+		break;
+	    }
+	}
+    }
+
+    if (!dataFound) {
+        printk("Could not find Radio Configuration data\n");
+	radio_config = NULL;
+    }
+    radioConfig = radio_config;
+    return(dataFound);
+}
+
+static int __init
+ae531x_MAC_setup(void)
+{
+    int next_dev, i;
+    struct net_device *dev;
+    ae531x_dev_sw_state_t *dev_sw_state;
+    ae531x_MAC_state_t *MAC_state;
+    ae531x_MAC_t *MACInfo;
+    char *addr;
+
+    ARRIVE();
+
+    MOD_INC_USE_COUNT;
+    for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {
+	ae531x_MAC_dev[i] = NULL;
+    }
+    
+    if (!ae531x_get_board_config()) {
+	LEAVE();
+	return -1;
+    }
+    if (!ae531x_get_radio_config()) {
+	LEAVE();
+	return(-1);
+    }
+    for(i=0, next_dev = AR531X_NUM_ENET_MAC-1; 
+        i<ae531x_get_numMACs() && next_dev>=0; 
+        i++, next_dev--){
+	
+        /* if MAC is bogus in config data, skip */
+        addr = ae531x_enet_mac_address_get(next_dev);
+        if((*(u32 *)addr == 0xffffffff) && (*(u16 *)(addr+4)==0xffff)){
+            /* bogus MAC config data */
+            continue;
+        }
+	
+        dev = ae531x_MAC_dev[next_dev] =
+            init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));
+	
+        if (dev == NULL) {
+            LEAVE();
+            return -1;
+        }
+	
+        ae531x_MAC_setup_fntable(dev);
+
+        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;
+        dev_sw_state->enetUnit = next_dev;
+        dev_sw_state->unit_on_MAC = 0;
+        MAC_state = &per_MAC_info[next_dev];
+        dev_sw_state->MAC_state = MAC_state;
+        MAC_state->dev_sw_state[AE531X_LAN_PORT] = dev_sw_state;
+        MAC_state->primary_dev = -1;
+
+        /* Initialize per-MAC information */
+        MACInfo = &MAC_state->MACInfo;
+
+        MACInfo->unit = next_dev;
+
+        if (MACInfo->unit == 0) {
+            MACInfo->macBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);
+            MACInfo->dmaBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);
+            MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
+            MAC_state->irq = AR531X_IRQ_ENET0_INTRS;
+        } else {
+#ifndef CONFIG_AR5315
+            MACInfo->macBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);
+            MACInfo->dmaBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);
+            if (ae531x_twisted_enet()) {
+                MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);
+            } else {
+                MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_PHY_OFFSET);
+            }
+            MAC_state->irq = AR531X_IRQ_ENET1_INTRS;
+#endif
+        }
+
+        MACInfo->OSinfo = (void *)MAC_state;
+
+    }
+
+    LEAVE();
+    return 0;
+}
+module_init(ae531x_MAC_setup);
+
+/*******************************************************************************
+* ae531x_MAC_unload is the module unload function
+*/
+static void __exit
+ae531x_MAC_unload(void)
+{
+    int i;
+
+    for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {
+        if (ae531x_MAC_dev[i] != NULL) {
+            if( (((ae531x_dev_sw_state_t *)ae531x_MAC_dev[i]->priv)->dev) != NULL)
+                  ae531x_MAC_stop(ae531x_MAC_dev[i]);
+            ae531x_MAC_dev[i] = NULL;
+        }
+    }
+   MOD_DEC_USE_COUNT;
+}
+
+MODULE_AUTHOR("Atheros Communications, Inc.");
+MODULE_DESCRIPTION("Support for Atheros WiSoC Ethernet device");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("Atheros");
+#endif
+module_exit(ae531x_MAC_unload);
diff -urN linux-mips-orig/drivers/net/ath/ae531xmac.c linux-mips-new/drivers/net/ath/ae531xmac.c
--- linux-mips-orig/drivers/net/ath/ae531xmac.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ae531xmac.c	2005-12-31 12:33:57.673538824 +0000
@@ -0,0 +1,951 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+
+/*
+ * Ethernet driver for Atheros' ae531x ethernet MAC.
+ */
+
+#if linux
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+#include "ar531xlnx.h"
+#endif /* linux */
+
+#include "ae531xreg.h"
+#include "ae531xmac.h"
+
+#ifdef DEBUG
+int ae531x_MAC_debug = AE531X_DEBUG_ERROR;
+#else
+int ae531x_MAC_debug = 0;
+#endif
+
+extern char *ae531x_enet_mac_address_get(int);
+
+/* Forward references to local functions */
+static void ae531x_QueueDestroy(AE531X_QUEUE *q);
+
+
+/******************************************************************************
+*
+* ae531x_ReadMacReg - read AE MAC register
+*
+* RETURNS: register value
+*/
+UINT32
+ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg)
+{
+    UINT32 addr = MACInfo->macBase+reg;
+    UINT32 data;
+
+    data = RegRead(addr);
+    return data;
+}
+
+
+/******************************************************************************
+*
+* ae531x_WriteMacReg - write AE MAC register
+*
+* RETURNS: N/A
+*/
+void
+ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
+{
+    UINT32 addr = MACInfo->macBase+reg;
+
+    RegWrite(data, addr);
+}
+
+
+/******************************************************************************
+*
+* ae531x_SetMacReg - set bits in AE MAC register
+*
+* RETURNS: N/A
+*/
+void
+ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
+{
+    UINT32 addr = MACInfo->macBase+reg;
+    UINT32 data = RegRead(addr);
+
+    data |= val;
+    RegWrite(data, addr);
+}
+
+
+/******************************************************************************
+*
+* ae531x_ClearMacReg - clear bits in AE MAC register
+*
+* RETURNS: N/A
+*/
+void
+ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
+{
+    UINT32 addr = MACInfo->macBase+reg;
+    UINT32 data = RegRead(addr);
+
+    data &= ~val;
+    RegWrite(data, addr);
+}
+
+
+/******************************************************************************
+*
+* ae531x_ReadDmaReg - read AE DMA register
+*
+* RETURNS: register value
+*/
+UINT32
+ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg)
+{
+    UINT32 addr = MACInfo->dmaBase+reg;
+    UINT32 data = RegRead(addr);
+
+    return data;
+}
+
+
+/******************************************************************************
+*
+* ae531x_WriteDmaReg - write AE DMA register
+*
+* RETURNS: N/A
+*/
+void
+ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data)
+{
+    UINT32 addr = MACInfo->dmaBase+reg;
+
+    RegWrite(data, addr);
+}
+
+
+/******************************************************************************
+ *
+ * ae531x_AckIntr - clear interrupt bits in the status register.
+ * Note: Interrupt bits are *cleared* by writing a 1.
+ */
+void
+ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 data)
+{
+      ae531x_WriteDmaReg(MACInfo, DmaStatus, data);
+}
+
+
+/******************************************************************************
+*
+* ae531x_SetDmaReg - set bits in an AE DMA register
+*
+* RETURNS: N/A
+*/
+void
+ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
+{
+    UINT32 addr = MACInfo->dmaBase+reg;
+    UINT32 data = RegRead(addr);
+
+    data |= val;
+    RegWrite(data, addr);
+}
+
+
+/******************************************************************************
+*
+* ae531x_ClearDmaReg - clear bits in an AE DMA register
+*
+* RETURNS: N/A
+*/
+void
+ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val)
+{
+    UINT32 addr = MACInfo->dmaBase+reg;
+    UINT32 data = RegRead(addr);
+
+    data &= ~val;
+    RegWrite(data, addr);
+}
+
+
+/******************************************************************************
+*
+* ae531x_ReadMiiReg - read PHY registers via AE MAC Mii addr/data registers
+*
+* RETURNS: register value
+*/
+UINT32
+ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg)
+{
+    UINT32 data;
+    UINT32 addr = phyBase+reg;
+
+    data = RegRead(addr);
+    return data;
+}
+
+
+/******************************************************************************
+*
+* ae531x_WriteMiiReg - write PHY registers via AE MAC Mii addr/data registers
+*
+* RETURNS: N/A
+*/
+void
+ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data)
+{
+    UINT32 addr = phyBase+reg;
+
+    RegWrite(data, addr);
+}
+
+
+/******************************************************************************
+*
+* ae531x_MiiRead - read AE Mii register
+*
+* RETURNS: register value
+*/
+UINT16
+ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg)
+{
+    UINT32 addr;
+    UINT16 data;
+
+    addr = ((phyAddr << MiiDevShift) & MiiDevMask) | ((reg << MiiRegShift) & MiiRegMask);
+
+    ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
+    do {
+        /* nop */
+    } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
+
+    data = ae531x_ReadMiiReg(phyBase, MacMiiData) & 0xFFFF;
+
+    return data;
+}
+
+
+/******************************************************************************
+*
+* ae531x_MiiWrite - write AE Mii register
+*
+* RETURNS: N/A
+*/
+void
+ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data)
+{
+    UINT32 addr;
+
+    ae531x_WriteMiiReg(phyBase, MacMiiData, data );
+
+    addr = ((phyAddr << MiiDevShift) & MiiDevMask) |
+        ((reg << MiiRegShift) & MiiRegMask) | MiiWrite;
+    ae531x_WriteMiiReg(phyBase, MacMiiAddr, addr );
+
+    do {
+        /* nop */
+    } while ((ae531x_ReadMiiReg(phyBase, MacMiiAddr ) & MiiBusy) == MiiBusy);
+}
+
+
+/*******************************************************************************
+* ae531x_BeginResetMode - enter a special "reset mode" in which
+*    -no interrupts are expected from the device
+*    -the device will not transmit nor receive
+*    -attempts to send or receive will return with an error and
+*    -the device will be reset at the next convenient opportunity.
+*/
+void
+ae531x_BeginResetMode(ae531x_MAC_t *MACInfo)
+{
+    /* Set the reset flag */
+    MACInfo->aeProcessRst = 1;
+}
+
+
+/*******************************************************************************
+* ae531x_EndResetMode - exit the special "reset mode" entered
+* earlier via a call to ae531x_BeginResetMode.
+*/
+void
+ae531x_EndResetMode(ae531x_MAC_t *MACInfo)
+{
+    MACInfo->aeProcessRst = 0;
+}
+
+
+/*******************************************************************************
+* ae531x_IsInResetMode - determine whether or not the device is
+* currently in "reset mode" (i.e. that a device reset is pending)
+*/
+BOOL
+ae531x_IsInResetMode(ae531x_MAC_t *MACInfo)
+{
+    return MACInfo->aeProcessRst;
+}
+
+
+/******************************************************************************
+*
+* ae531x_DmaRxStart - Start Rx
+*
+* RETURNS: N/A
+*/
+static void
+ae531x_DmaRxStart(ae531x_MAC_t *MACInfo)
+{
+    ae531x_SetDmaReg(MACInfo, DmaControl, DmaRxStart);
+    sysWbFlush();
+}
+
+
+/******************************************************************************
+*
+* ae531x_DmaRxStop - Stop Rx
+*
+* RETURNS: N/A
+*/
+void
+ae531x_DmaRxStop(ae531x_MAC_t *MACInfo)
+{
+    ae531x_ClearDmaReg(MACInfo, DmaControl, DmaRxStart);
+    sysWbFlush();
+}
+
+
+/******************************************************************************
+*
+* ae531x_DmaTxStart - Start Tx
+*
+* RETURNS: N/A
+*/
+void
+ae531x_DmaTxStart(ae531x_MAC_t *MACInfo)
+{
+    ae531x_SetDmaReg(MACInfo, DmaControl, DmaTxStart);
+    sysWbFlush();
+}
+
+
+/******************************************************************************
+*
+* ae531x_DmaTxStop - Stop Tx
+*
+* RETURNS: N/A
+*/
+void
+ae531x_DmaTxStop(ae531x_MAC_t *MACInfo)
+{
+    ae531x_ClearDmaReg(MACInfo, DmaControl, DmaTxStart);
+    sysWbFlush();
+}
+
+
+/******************************************************************************
+*
+* ae531x_DmaIntEnable - Enable DMA interrupts
+*
+* RETURNS: N/A
+*/
+void
+ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo)
+{
+    ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntEnable);
+}
+
+
+/******************************************************************************
+*
+* ae531x_DmaIntDisable - Disable DMA interrupts
+*
+* RETURNS: N/A
+*/
+void
+ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo)
+{
+    ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
+}
+
+
+/******************************************************************************
+*
+* ae531x_DmaIntClear - Clear DMA interrupts
+*
+* RETURNS: N/A
+*/
+static void
+ae531x_DmaIntClear(ae531x_MAC_t *MACInfo)
+{
+    /* clear all interrupt requests */
+    ae531x_WriteDmaReg(MACInfo, DmaStatus,
+                      ae531x_ReadDmaReg(MACInfo, DmaStatus));  
+}
+
+
+/******************************************************************************
+* Initialize generic queue data
+*/
+void
+ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count)
+{
+    ARRIVE();
+    q->firstDescAddr = pMem;
+    q->lastDescAddr = (VIRT_ADDR)((UINT32)q->firstDescAddr +
+                                  (count - 1) * AE531X_QUEUE_ELE_SIZE);
+    q->curDescAddr = q->firstDescAddr;
+    q->count = count;
+    LEAVE();
+}
+
+
+/******************************************************************************
+* ae531x_TxQueueCreate - create a circular queue of descriptors for Transmit
+*/
+static int
+ae531x_TxQueueCreate(ae531x_MAC_t *MACInfo,
+                  AE531X_QUEUE *q,
+                  char *pMem,
+                  int count)
+{
+    int         i;
+    VIRT_ADDR   descAddr;
+
+    ARRIVE();
+
+    ae531x_QueueInit(q, pMem, count);
+    q->reapDescAddr = q->lastDescAddr;
+
+    /* Initialize Tx buffer descriptors.  */
+    for (i=0, descAddr=q->firstDescAddr;
+         i<count;
+         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
+    {
+        /* Update the size, BUFPTR, and SWPTR fields */
+
+        AE531X_DESC_STATUS_SET(descAddr, 0);
+        AE531X_DESC_CTRLEN_SET(descAddr, 0);
+
+        AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
+        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
+        AE531X_DESC_SWPTR_SET(descAddr, (void *)0);
+    } /* for each desc */
+
+    /* Make the queue circular */
+    AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
+                       DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
+
+    AE531X_PRINT(AE531X_DEBUG_RESET,
+            ("ethmac%d Txbuf begin = %x, end = %x\n",
+            MACInfo->unit,
+            (UINT32)q->firstDescAddr,
+            (UINT32)q->lastDescAddr));
+
+    LEAVE();
+    return 0;
+}
+
+
+/******************************************************************************
+* ae531x_RxQueueCreate - create a circular queue of Rx descriptors
+*/
+int
+ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo,
+                  AE531X_QUEUE *q,
+                  char *pMem,
+                  int count)
+{
+    int               i;
+    VIRT_ADDR         descAddr;
+
+    ARRIVE();
+
+    ae531x_QueueInit(q, pMem, count);
+    q->reapDescAddr = NULL;
+
+
+    /* Initialize Rx buffer descriptors */
+    for (i=0, descAddr=q->firstDescAddr;
+         i<count;
+         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))
+    {
+        void *swptr;
+        char *rxBuffer;
+        int  rxBufferSize;
+
+        swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize);
+        if (swptr == NULL) {
+                AE531X_PRINT(AE531X_DEBUG_RESET,
+                          ("ethmac%d RX queue: ae531x_rxbuf_alloc failed\n",
+                           MACInfo->unit));
+                ae531x_QueueDestroy(q);
+                return -1;
+        }
+        AE531X_DESC_SWPTR_SET(descAddr, swptr);
+
+        AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
+        AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize);
+        AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer));
+        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
+    } /* for each desc */
+
+    /* Make the queue circular */
+    AE531X_DESC_CTRLEN_SET(q->lastDescAddr,
+                       DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));
+
+    AE531X_PRINT(AE531X_DEBUG_RESET,
+              ("ethmac%d Rxbuf begin = %x, end = %x\n",
+              MACInfo->unit,
+              (UINT32)q->firstDescAddr,
+              (UINT32)q->lastDescAddr));
+
+    LEAVE();
+    return 0;
+}
+
+
+/******************************************************************************
+* ae531x_QueueDestroy -- Free all buffers and descriptors associated 
+* with a queue.
+*/
+static void
+ae531x_QueueDestroy(AE531X_QUEUE *q)
+{
+    int i;
+    int count;
+    VIRT_ADDR    descAddr;
+
+    ARRIVE();
+
+    count = q->count;
+
+    for (i=0, descAddr=q->firstDescAddr;
+         i<count;
+         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {
+
+        AE531X_DESC_STATUS_SET(descAddr, 0);
+        AE531X_DESC_CTRLEN_SET(descAddr, 0);
+        AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);
+        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);
+
+        ae531x_swptr_free(descAddr); /* Free OS-specific software pointer */
+    }
+
+    LEAVE();
+}
+
+static void
+ae531x_TxQueueDestroy(ae531x_MAC_t *MACInfo)
+{
+    ae531x_QueueDestroy(&MACInfo->txQueue);
+}
+
+static void
+ae531x_RxQueueDestroy(ae531x_MAC_t *MACInfo)
+{
+    ae531x_QueueDestroy(&MACInfo->rxQueue);
+}
+
+
+/******************************************************************************
+* ae531x_AllocateQueues - Allocate receive and transmit queues
+*/
+int
+ae531x_AllocateQueues(ae531x_MAC_t *MACInfo)
+{
+    size_t QMemSize;
+    char *pTxBuf = NULL;
+    char *pRxBuf = NULL;
+
+    ARRIVE();
+
+    MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;
+    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;
+    pTxBuf = MALLOC(QMemSize);
+    if (pTxBuf == NULL) {
+        AE531X_PRINT(AE531X_DEBUG_RESET,
+                  ("ethmac%d Failed to allocate TX queue\n", MACInfo->unit));
+        goto AllocQFail;
+    }
+
+    if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,
+                          MACInfo->txDescCount) < 0)
+    {
+        AE531X_PRINT(AE531X_DEBUG_RESET,
+                ("ethmac%d Failed to create TX queue\n", MACInfo->unit));
+        goto AllocQFail;
+    }
+
+    MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;
+    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;
+    pRxBuf = MALLOC(QMemSize);
+    if (pRxBuf == NULL) {
+        AE531X_PRINT(AE531X_DEBUG_RESET,
+                  ("ethmac%d Failed to allocate RX queue\n", MACInfo->unit));
+        goto AllocQFail;
+    }
+
+    if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,
+                          MACInfo->rxDescCount) < 0)
+    {
+        AE531X_PRINT(AE531X_DEBUG_RESET,
+                ("ethmac%d Failed to create RX queue\n", MACInfo->unit));
+        goto AllocQFail;
+    }
+
+    AE531X_PRINT(AE531X_DEBUG_RESET,
+            ("ethmac%d Memory setup complete.\n", MACInfo->unit));
+
+    LEAVE();
+    return 0;
+
+AllocQFail:
+    MACInfo->txDescCount = 0; /* sanity */
+    MACInfo->rxDescCount = 0; /* sanity */
+
+    if (pTxBuf) {
+        FREE(pTxBuf);
+    }
+    if (pRxBuf) {
+        FREE(pRxBuf);
+    }
+    
+    LEAVE();
+    return -1;
+}
+
+
+/******************************************************************************
+*
+* ae531x_FreeQueues - Free Transmit & Receive queues
+*/
+void
+ae531x_FreeQueues(ae531x_MAC_t *MACInfo)
+{
+    ae531x_TxQueueDestroy(MACInfo);
+    FREE(MACInfo->txQueue.firstDescAddr);
+
+    ae531x_RxQueueDestroy(MACInfo);
+    FREE(MACInfo->rxQueue.firstDescAddr);
+}
+
+/******************************************************************************
+*
+* ae531x_DmaReset - Reset DMA and TLI controllers
+*
+* RETURNS: N/A
+*/
+void
+ae531x_DmaReset(ae531x_MAC_t *MACInfo)
+{
+    int        i;
+    UINT32     descAddr;
+
+    ARRIVE();
+
+    /* Disable device interrupts prior to any errors during stop */
+    intDisable(MACInfo->ilevel);
+
+    /* Disable MAC rx and tx */
+    ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
+
+    udelay(1);
+
+    /* Reset dma controller */
+    
+    ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);
+
+    /* Delay 2 usec */
+    sysUDelay(2);
+
+    /* Flush the rx queue */
+    descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;
+    MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;
+    for (i=0;
+         i<(MACInfo->rxDescCount);
+         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
+            AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
+    }
+
+    /* Flush the tx queue */
+    descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;
+    MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;
+    MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;
+    for (i=0;
+         i<(MACInfo->txDescCount);
+         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
+            AE531X_DESC_STATUS_SET (descAddr, 0);
+    }
+
+    /* Set init register values  */
+    ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);
+
+    /* Install the first Tx and Rx queues on the device */
+    ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,
+                      virt_to_bus(MACInfo->rxQueue.firstDescAddr));
+    ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,
+                      virt_to_bus(MACInfo->txQueue.firstDescAddr));
+
+
+    ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);
+
+    ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);
+
+    AE531X_PRINT(AE531X_DEBUG_RESET,
+              ("ethmac%d: DMA RESET!\n", MACInfo->unit));
+
+    /* Turn on device interrupts -- enable most errors */
+    ae531x_DmaIntClear(MACInfo);    /* clear interrupt requests  */
+    ae531x_DmaIntEnable(MACInfo);   /* enable interrupts */
+
+    ae531x_EndResetMode(MACInfo);
+
+    intEnable(MACInfo->ilevel);
+
+    LEAVE();
+}
+
+
+/******************************************************************************
+*
+* ae531x_MACAddressSet - Set the ethernet address
+*
+* Sets the ethernet address according to settings in flash.
+*
+* RETURNS: void
+*/
+static void
+ae531x_MACAddressSet(ae531x_MAC_t *MACInfo)
+{
+    unsigned int    data;
+    UINT8 *macAddr;
+
+    ARRIVE();
+        
+    macAddr = ae531x_enet_mac_address_get(MACInfo->unit);
+
+    /* set our MAC address  */
+    data = (macAddr[5]<<8) | macAddr[4];
+    ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );
+
+    data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];
+    ae531x_WriteMacReg(MACInfo, MacAddrLow, data );
+
+    AE531X_PRINT(AE531X_DEBUG_RESET,
+              ("ethmac%d Verify MAC address %8.8X %8.8X \n",
+               MACInfo->unit,
+               ae531x_ReadMacReg(MACInfo, MacAddrLow),
+               ae531x_ReadMacReg(MACInfo, MacAddrHigh)));
+
+    AE531X_PRINT(AE531X_DEBUG_RESET,
+              ("  sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+               0xff&macAddr[0],
+               0xff&macAddr[1],
+               0xff&macAddr[2],
+               0xff&macAddr[3],
+               0xff&macAddr[4],
+               0xff&macAddr[5]));
+    LEAVE();
+}
+
+
+/******************************************************************************
+*
+* ae_SetMACFromPhy - read Phy settings and update Mac
+*                    with current duplex and speed.
+*
+* RETURNS:
+*/
+static void
+ae531x_SetMACFromPhy(ae531x_MAC_t *MACInfo)
+{
+    UINT32  macCtl;
+    BOOL    fullDuplex;
+    UINT32  timeout;
+
+    ARRIVE();
+
+    timeout = jiffies+(HZ/1000)*AE531X_NEGOT_TIMEOUT;
+
+    /* Get duplex mode from Phy */
+    while (((fullDuplex = phyIsFullDuplex(MACInfo->unit)) == -1) &&
+	   (jiffies <= timeout));
+
+    /* Flag is set for full duplex mode, else cleared */
+    macCtl = ae531x_ReadMacReg(MACInfo, MacControl);
+
+    if (fullDuplex) {
+        /* set values of control registers */
+        macCtl &= ~MacDisableRxOwn;
+        macCtl |= MacFullDuplex;
+        ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
+        ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitFdx);
+    } else {
+	/* set values of control registers */
+        ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitHdx);
+        macCtl |= MacDisableRxOwn;
+        macCtl &= ~MacFullDuplex;
+        ae531x_WriteMacReg(MACInfo, MacControl, macCtl);
+    }
+
+    LEAVE();
+}
+
+
+/******************************************************************************
+* ae531x_MACReset -- sets MAC address and duplex.
+*/
+void
+ae531x_MACReset(ae531x_MAC_t *MACInfo)
+{
+    ae531x_MACAddressSet(MACInfo);
+#ifndef CONFIG_AR5315
+    ae531x_SetMACFromPhy(MACInfo);
+#endif
+}
+
+
+/******************************************************************************
+* ae531x_EnableComm -- enable Transmit and Receive
+*/
+void
+ae531x_EnableComm(ae531x_MAC_t *MACInfo)
+{
+    ae531x_SetMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
+    ae531x_DmaRxStart(MACInfo);     /* start receiver  */
+    ae531x_DmaTxStart(MACInfo);     /* start transmitter */
+}
+
+
+/******************************************************************************
+* ae531x_DisableComm -- disable Transmit and Receive
+*/
+void
+ae531x_DisableComm(ae531x_MAC_t *MACInfo)
+{
+    ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));
+}
+
+
+/******************************************************************************
+* ae531x_reset -- Cold reset ethernet interface
+*/
+void
+ae531x_reset(ae531x_MAC_t *MACInfo)
+{
+    UINT32 mask = 0;
+    UINT32 regtmp;
+#ifndef CONFIG_AR5315
+   
+    if (MACInfo->unit == 0) {
+        mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
+    } else {
+        mask = AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;
+    }
+
+    /* Put into reset */
+    regtmp = sysRegRead(AR531X_RESET);
+    sysRegWrite(AR531X_RESET, regtmp | mask);
+    sysMsDelay(15);
+
+    /* Pull out of reset */
+    regtmp = sysRegRead(AR531X_RESET);
+    sysRegWrite(AR531X_RESET, regtmp & ~mask);
+    sysUDelay(25);
+
+    /* Enable */
+    if (MACInfo->unit == 0) {
+        mask = AR531X_ENABLE_ENET0;
+    } else {
+        mask = AR531X_ENABLE_ENET1;
+    }
+    regtmp = sysRegRead(AR531X_ENABLE);
+    sysRegWrite(AR531X_ENABLE, regtmp | mask);
+#else
+    if (MACInfo->unit == 0) {
+        mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;
+    }
+    /* Enable Arbitration for Ethernet bus */
+    regtmp = sysRegRead(AR531XPLUS_AHB_ARB_CTL);
+    regtmp |= ARB_ETHERNET;
+    sysRegWrite(AR531XPLUS_AHB_ARB_CTL, regtmp);
+
+    /* Put into reset */
+    regtmp = sysRegRead(AR531X_RESET);
+    sysRegWrite(AR531X_RESET, regtmp | mask);
+    sysMsDelay(10);
+
+    /* Pull out of reset */
+    regtmp = sysRegRead(AR531X_RESET);
+    sysRegWrite(AR531X_RESET, regtmp & ~mask);
+    sysMsDelay(10);
+
+    regtmp = sysRegRead(AR531XPLUS_IF_CTL);
+    regtmp |= IF_TS_LOCAL;
+    sysRegWrite(AR531XPLUS_IF_CTL, regtmp);
+#endif
+}
+
+
+/******************************************************************************
+* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer
+* that there are no longer any live links associated with a MAC.
+*/
+void
+ae531x_unitLinkLost(int ethUnit)
+{
+    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
+             ("enetmac%d link down\n", ethUnit));
+}
+
+
+/******************************************************************************
+* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer
+* that there are 1 or more live links associated with a MAC.
+*/
+void
+ae531x_unitLinkGained(int ethUnit)
+{
+#if CONFIG_AR5315
+#define AE531X_POLL_MILLI_SECONDS 200 
+    ae531x_MAC_t *MACInfo = ae531x_getMAcInfo(ethUnit);
+    while(!MACInfo || !MACInfo->port_is_up)
+    {
+        set_current_state(TASK_UNINTERRUPTIBLE);
+        schedule_timeout((AE531X_POLL_MILLI_SECONDS * HZ)/1000);
+        MACInfo = ae531x_getMAcInfo(ethUnit);
+    }
+    ae531x_SetMACFromPhy(MACInfo);
+#endif
+    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
+             ("enet%d link up\n", ethUnit));
+}
+
+/******************************************************************************
+* ae531x_ethMacDefault -- Called from PHY layer to determine the default
+* ethernet MAC.  On some "twisted" platforms, the only usable MAC is 1,
+* while on others the usable MAC is 0.  Future boards may allow both MACs
+* to be used; in this case, return -1 to indicate that there IS NO default
+* MAC.
+*/
+int
+ae531x_ethMacDefault(void)
+{
+    if (ae531x_twisted_enet())
+        return 1;
+
+    return 0;
+
+}
diff -urN linux-mips-orig/drivers/net/ath/ae531xmac.h linux-mips-new/drivers/net/ath/ae531xmac.h
--- linux-mips-orig/drivers/net/ath/ae531xmac.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ae531xmac.h	2005-12-31 12:33:57.674538672 +0000
@@ -0,0 +1,229 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * See README to understand the decomposition of the ethernet driver.
+ *
+ * This file contains OS-independent pure software definitions for
+ * ethernet support on the AR531X platform.
+ */
+
+#ifndef _AE531XMAC_H_
+#define _AE531XMAC_H_
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+/*
+ * DEBUG switches to control verbosity.
+ * Just modify the value of ae531x_MAC_debug.
+ */
+#define AE531X_DEBUG_ALL         0xffffffff
+#define AE531X_DEBUG_ERROR       0x00000001 /* Unusual conditions and Errors */
+#define AE531X_DEBUG_ARRIVE      0x00000002 /* Arrive into a function */
+#define AE531X_DEBUG_LEAVE       0x00000004 /* Leave a function */
+#define AE531X_DEBUG_RESET       0x00000008 /* Reset */
+#define AE531X_DEBUG_TX          0x00000010 /* Transmit */
+#define AE531X_DEBUG_TX_REAP     0x00000020 /* Transmit Descriptor Reaping */
+#define AE531X_DEBUG_RX          0x00000040 /* Receive */
+#define AE531X_DEBUG_RX_STOP     0x00000080 /* Receive Early Stop */
+#define AE531X_DEBUG_INT         0x00000100 /* Interrupts */
+#define AE531X_DEBUG_LINK_CHANGE 0x00000200 /* PHY Link status changed */
+
+#define AE531X_NEGOT_TIMEOUT	 500        /* ms to wait for autonegotiation */
+
+extern int ae531x_MAC_debug;
+
+#define AE531X_PRINT(FLG, X)                            \
+{                                                   \
+    if (ae531x_MAC_debug & (FLG)) {                  \
+        DEBUG_PRINTF("%s#%d:%s ",                   \
+                     __FILE__,                      \
+                     __LINE__,                      \
+                     __FUNCTION__);                 \
+        DEBUG_PRINTF X;                             \
+    }                                               \
+}
+
+#define ARRIVE() AE531X_PRINT(AE531X_DEBUG_ARRIVE, ("Arrive{\n"))
+#define LEAVE() AE531X_PRINT(AE531X_DEBUG_LEAVE, ("}Leave\n"))
+
+#define RegRead(addr)	\
+	(*(volatile unsigned int *)(addr))
+
+#define RegWrite(val,addr)	\
+	((*(volatile unsigned int *)(addr)) = (val))
+
+/*****************************************************************
+ * Phy code is broken out into a separate layer, so that different
+ * PHY hardware can easily be supported.
+ *
+ * These functions are provided by the PHY layer for use by the MAC layer.
+ *   phySetup             -- Set phy hardware appropriately for a MAC unit
+ *
+ *   phyCheckStatusChange -- Look for dropped/initiated links on any
+ *                           phy port associated with a MAC unit
+ *
+ *   phyIsSpeed100        -- Determines whether or not a PHY is up and
+ *                           running at 100Mbit
+ *
+ *   phyIsFullDuplex      -- Determines whether or not a PHY is up and
+ *                           running in Full Duplex mode
+ *
+ */
+#if CONFIG_MARVELL_ENET_PHY
+/*
+ * Mapping of generic phy APIs to Marvell Ethernet Switch phy functions.
+ */
+#include "mvPhy.h"
+#define phySetup(ethUnit, phyBase)      mv_phySetup((ethUnit), (phyBase))
+#define phyCheckStatusChange(ethUnit)   mv_phyCheckStatusChange(ethUnit)
+#define phyIsSpeed100(ethUnit)          mv_phyIsSpeed100(ethUnit)
+#define phyIsFullDuplex(ethUnit)        mv_phyIsFullDuplex(ethUnit)
+
+#if CONFIG_VENETDEV
+#define PHY_TRAILER_SIZE    MV_PHY_TRAILER_SIZE
+extern void mv_phyDetermineSource(char *data, int len, int *pFromLAN);
+extern void mv_phySetDestinationPort(char *data, int len, int fromLAN);
+#define phyDetermineSource(data, len, pFromLAN) mv_phyDetermineSource((data), (len), (pFromLAN))
+#define phySetDestinationPort(data, len, fromLAN) mv_phySetDestinationPort((data), (len), (fromLAN))
+#else
+#define PHY_TRAILER_SIZE    0
+#endif
+#endif /* CONFIG_MARVELL_ENET_PHY */
+
+#if CONFIG_KENDIN_ENET_PHY || CONFIG_REALTEK_ENET_PHY || CONFIG_KENDIN_KS8995XA_ENET_PHY
+/*
+ * Mapping of generic phy APIs to Kendin KS8721B and RealTek RTL8201BL phys.
+ */
+#include "rtPhy.h"
+#define phySetup(ethUnit, phyBase)      rt_phySetup((ethUnit), (phyBase))
+#define phyCheckStatusChange(ethUnit)   rt_phyCheckStatusChange(ethUnit)
+#define phyIsSpeed100(ethUnit)          rt_phyIsSpeed100(ethUnit)
+#define phyIsFullDuplex(ethUnit)        rt_phyIsFullDuplex(ethUnit)
+#endif
+
+#if CONFIG_ICPLUS_ENET_PHY
+/*
+ * Mapping of generic phy APIs to Icplus phys.
+ */
+#include "ipPhy.h"
+#define phySetup(ethUnit, phyBase)      ip_phySetup((ethUnit), (phyBase))
+#define phyCheckStatusChange(ethUnit)   ip_phyCheckStatusChange(ethUnit)
+#define phyIsSpeed100(ethUnit)          ip_phyIsSpeed100(ethUnit)
+#define phyIsFullDuplex(ethUnit)        ip_phyIsFullDuplex(ethUnit)
+#endif
+
+#if !defined(PHY_TRAILER_SIZE)
+#define PHY_TRAILER_SIZE    0
+#endif
+
+/*****************************************************************
+ * MAC-independent interface to be used by PHY code
+ *
+ * These functions are provided by the MAC layer for use by the PHY layer.
+ */
+#define phyRegRead ae531x_MiiRead
+#define phyRegWrite ae531x_MiiWrite
+#define phyLinkLost(ethUnit) ae531x_unitLinkLost(ethUnit)
+#define phyLinkGained(ethUnit) ae531x_unitLinkGained(ethUnit)
+#define phyEthMacDefault() ae531x_ethMacDefault()
+
+void ae531x_unitLinkLost(int unit);
+void ae531x_unitLinkGained(int unit);
+int ae531x_ethMacDefault(void);
+
+
+/* 
+ * RXBUFF_RESERVE enables building header on WLAN-side in place 
+ * NB: Divisible by 2 but NOT 4. Otherwise handle_adel_int() will
+ *     be used by the ip layer for misaligned word accesses and 
+ *     performance will suffer - a lot.
+ */
+#define ETH_CRC_LEN       4
+#define RXBUFF_RESERVE   98
+// #define RXBUFF_RESERVE   98
+
+/*****************************************************************
+ * Descriptor queue
+ */
+typedef struct ae531x_queue {
+    VIRT_ADDR   firstDescAddr;  /* descriptor array address */
+    VIRT_ADDR   lastDescAddr;   /* last descriptor address */
+    VIRT_ADDR   curDescAddr;    /* current descriptor address */
+    VIRT_ADDR   reapDescAddr;   /* current tail of tx descriptors reaped */
+    UINT16      count;          /* number of elements */
+} AE531X_QUEUE;
+
+/* Given a descriptor, return the next one in a circular list */
+#define AE531X_QUEUE_ELE_NEXT_GET(q, descAddr)                          \
+        ((descAddr) == (q)->lastDescAddr) ? (q)->firstDescAddr :    \
+        (VIRT_ADDR)((UINT32)(descAddr) + AE531X_QUEUE_ELE_SIZE)
+
+/* Move the "current descriptor" forward to the next one */
+#define AE531X_CONSUME_DESC(q)    \
+         q->curDescAddr = AE531X_QUEUE_ELE_NEXT_GET(q, q->curDescAddr)
+
+/*****************************************************************
+ * Per-ethernet-MAC OS-independent information
+ */
+typedef struct ae531x_MAC_s {
+    u32             unit;          /* MAC unit ID */
+    u32             macBase;       /* MAC base address */
+    u32             dmaBase;       /* DMA base address */
+    u32             phyBase;       /* PHY base address */
+    AE531X_QUEUE    txQueue;       /* Transmit descriptor queue */
+    AE531X_QUEUE    rxQueue;       /* Receive descriptor queue */
+    UINT16          txDescCount;   /* Transmit descriptor count */
+    UINT16          rxDescCount;   /* Receive descriptor count */
+    BOOL            aeProcessRst;  /* flag to indicate reset in progress */
+    BOOL            port_is_up;    /* flag to indicate port is up */
+    void            *OSinfo;       /* OS-dependent data */
+} ae531x_MAC_t;
+
+#define	AE531X_TX_DESC_COUNT_DEFAULT	128    /* Transmit descriptors */
+#define AE531X_RX_DESC_COUNT_DEFAULT	128    /* Receive descriptors */
+
+
+/*****************************************************************
+ * Interfaces exported by the OS-independent MAC layer
+ */
+void ae531x_BeginResetMode(ae531x_MAC_t *MACInfo);
+void ae531x_EndResetMode(ae531x_MAC_t *MACInfo);
+BOOL ae531x_IsInResetMode(ae531x_MAC_t *MACInfo);
+int ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q,
+                  char *pMem, int count);
+int ae531x_QueueDelete(struct ae531x_queue *q);
+void ae531x_DmaReset(ae531x_MAC_t *MACInfo);
+void ae531x_MACReset(ae531x_MAC_t *MACInfo);
+void ae531x_EnableComm(ae531x_MAC_t *MACInfo);
+void ae531x_DisableComm(ae531x_MAC_t *MACInfo);
+void ae531x_reset(ae531x_MAC_t *MACInfo);
+int ae531x_AllocateQueues(ae531x_MAC_t *MACInfo);
+void ae531x_FreeQueues(ae531x_MAC_t *MACInfo);
+void ae531x_QueueInit(AE531X_QUEUE *q, char *pMem, int count);
+UINT32 ae531x_ReadMacReg(ae531x_MAC_t *MACInfo, UINT32 reg);
+void ae531x_WriteMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
+void ae531x_SetMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
+void ae531x_ClearMacReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
+void ae531x_SetDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
+void ae531x_ClearDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 val);
+UINT32 ae531x_ReadDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg);
+void ae531x_WriteDmaReg(ae531x_MAC_t *MACInfo, UINT32 reg, UINT32 data);
+UINT32 ae531x_ReadMiiReg(UINT32 phyBase, UINT32 reg);
+void ae531x_WriteMiiReg(UINT32 phyBase, UINT32 reg, UINT32 data);
+UINT16 ae531x_MiiRead(UINT32 phyBase, UINT32 phyAddr, UINT8 reg);
+void ae531x_MiiWrite(UINT32 phyBase, UINT32 phyAddr, UINT8 reg, UINT16 data);
+void ae531x_DmaIntEnable(ae531x_MAC_t *MACInfo);
+void ae531x_DmaIntDisable(ae531x_MAC_t *MACInfo);
+void ae531x_AckIntr(ae531x_MAC_t *MACInfo, UINT32 val);
+void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBptr, int *rxBSize);
+void ae531x_swptr_free(VIRT_ADDR txDesc);
+BOOL ae531x_twisted_enet(void);
+
+#endif /* _AE531XMAC_H_ */
diff -urN linux-mips-orig/drivers/net/ath/ae531xreg.h linux-mips-new/drivers/net/ath/ae531xreg.h
--- linux-mips-orig/drivers/net/ath/ae531xreg.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ae531xreg.h	2005-12-31 12:33:57.675538520 +0000
@@ -0,0 +1,439 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * See README to understand the decomposition of the ethernet driver.
+ *
+ * Register definitions for Atheros AR531X Ethernet MAC.
+ */
+
+#ifndef _AE531XREG_H_
+#define _AE531XREG_H_
+
+#define AE531X_MAC_OFFSET 0x0000
+#define AE531X_PHY_OFFSET 0x0000 /* Same as MAC offset */
+#define AE531X_DMA_OFFSET 0x1000
+
+/***********************************************************/
+/* MAC110 registers, base address is BAR+AE531X_MAC_OFFSET */
+/***********************************************************/
+#define MacControl            0x00  /* control */
+#define MacAddrHigh           0x04  /* address high */
+#define MacAddrLow            0x08  /* address low */
+#define MacMultiHashHigh      0x0C  /* multicast hash table high */
+#define MacMultiHashLow       0x10  /* multicast hash table low */
+#define MacMiiAddr            0x14  /* MII address */
+#define MacMiiData            0x18  /* MII data */
+#define MacFlowControl        0x1C  /* Flow control */
+#define MacVlan1Tag           0x4C  /* VLAN1 tag */
+#define MacVlan2Tag           0x50  /* VLAN2 tag */
+
+
+/***************************************************************/
+/* DMA engine registers, base address is BAR+AE531X_DMA_OFFSET */
+/***************************************************************/
+#define DmaBusMode      0x00 /* CSR0 - Bus Mode */
+#define DmaTxPollDemand 0x04 /* CSR1 - Transmit Poll Demand */
+#define DmaRxPollDemand 0x08 /* CSR2 - Receive Poll Demand */
+#define DmaRxBaseAddr   0x0C /* CSR3 - Receive list base address */
+#define DmaTxBaseAddr   0x10 /* CSR4 - Transmit list base address */
+#define DmaStatus       0x14 /* CSR5 - Dma status */
+#define DmaControl      0x18 /* CSR6 - Dma control */
+#define DmaIntrEnb      0x1C /* CSR7 - Interrupt enable */
+#define DmaOverflowCnt  0x20 /* CSR8 - Missed Frame and Buff Overflow counter */
+#define DmaTxCurrAddr   0x50 /* CSR20 - Current host transmit buffer address */
+#define DmaRxCurrAddr   0x54 /* CSR21 - Current host receive buffer address */
+
+/**********************************************************/
+/* MAC Control register layout                            */
+/**********************************************************/
+#define MacFilterOff           0x80000000 /* Receive all incoming packets RW */
+#define MacFilterOn                     0 /* Receive filtered packets only 0 */
+#define MacBigEndian           0x40000000 /* Big endian mode RW */
+#define MacLittleEndian                 0 /* Little endian 0 */
+#define MacHeartBeatOff        0x10000000 /* Heartbeat signal qual disable RW*/
+#define MacHeartBeatOn                  0 /* Heartbeat signal qual enable 0 */
+#define MacSelectSrl           0x08000000 /* Select SRL port RW */
+#define MacSelectMii                    0 /* Select MII port 0 */
+#define MacDisableRxOwn        0x00800000 /* Disable receive own packets RW */
+#define MacEnableRxOwn                  0 /* Enable receive own packets 0 */
+#define MacLoopbackExt         0x00400000 /* External loopback RW */
+#define MacLoopbackInt         0x00200000 /* Internal loopback */
+#define MacLoopbackOff                  0 /* Normal mode 00 */
+#define MacFullDuplex          0x00100000 /* Full duplex mode RW */
+#define MacHalfDuplex                   0 /* Half duplex mode 0 */
+#define MacMulticastFilterOff  0x00080000 /* Pass all multicast packets RW */
+#define MacMulticastFilterOn            0 /* Pass filtered mcast packets 0 */
+#define MacPromiscuousModeOn   0x00040000 /* Receive all valid packets RW 1 */
+#define MacPromiscuousModeOff           0 /* Receive filtered packets only */
+#define MacFilterInverse       0x00020000 /* Inverse filtering RW */
+#define MacFilterNormal                 0 /* Normal filtering 0 */
+#define MacBadFramesEnable     0x00010000 /* Pass bad frames RW */
+#define MacBadFramesDisable             0 /* Do not pass bad frames 0 */
+#define MacPerfectFilterOff    0x00008000 /* Hash filtering only RW */
+#define MacPerfectFilterOn              0 /* Both perfect and hash filtering 0 */
+#define MacHashFilterOn        0x00002000 /* perform hash filtering RW */
+#define MacHashFilterOff                0 /* perfect filtering only 0 */
+#define MacLateCollisionOn     0x00001000 /* Enable late collision control RW */
+#define MacLateCollisionOff             0 /* Disable late collision control 0 */
+#define MacBroadcastDisable    0x00000800 /* Disable reception of bcast frames RW */
+#define MacBroadcastEnable              0 /* Enable broadcast frames 0 */
+#define MacRetryDisable        0x00000400 /* Disable retransmission RW */
+#define MacRetryEnable                  0 /* Enable retransmission 0 */
+#define MacPadStripEnable      0x00000100 /* Pad stripping enable RW */
+#define MacPadStripDisable              0 /* Pad stripping disable 0 */
+#define MacBackoff                      0 /* Backoff Limit RW 00 */
+#define MacDeferralCheckEnable 0x00000020 /* Deferral check enable RW */
+#define MacDeferralCheckDisable         0 /* Deferral check disable 0 */
+#define MacTxEnable            0x00000008 /* Transmitter enable RW */
+#define MacTxDisable                    0 /* Transmitter disable 0 */
+#define MacRxEnable            0x00000004 /* Receiver enable RW */
+#define MacRxDisable                    0 /* Receiver disable 0 */
+
+
+/**********************************************************/
+/* MII address register layout                            */
+/**********************************************************/
+#define MiiDevMask   0x0000F800 /* MII device address */
+#define MiiDevShift          11
+#define MiiRegMask   0x000007C0 /* MII register */
+#define MiiRegShift           6
+#define MiiWrite     0x00000002 /* Write to register */
+#define MiiRead               0 /* Read from register */
+#define MiiBusy      0x00000001 /* MII interface is busy */
+
+/**********************************************************/
+/* MII Data register layout                               */
+/**********************************************************/
+#define MiiDataMask  0x0000FFFF /* MII Data */
+
+/**********************************************************/
+/* MAC flow control register layout                       */
+/**********************************************************/
+#define MacPauseTimeMask      0xFFFF0000  /* PAUSE TIME field in ctrl frame */
+#define MacPauseTimeShift             15
+#define MacControlFrameEnable 0x00000004  /* Enable pass ctrl frames to host */
+#define MacControlFrameDisable         0  /* Do not pass ctrl frames to host */
+#define MacFlowControlEnable  0x00000002  /* Enable flow control */
+#define MacFlowControlDisable          0  /* Disable flow control */
+#define MacSendPauseFrame     0x00000001  /* send pause frame */
+
+/**********************************************************/
+/* DMA bus mode register layout                           */
+/**********************************************************/
+#define DmaRxAlign16            0x01000000 /* Force all rx buffers to align on odd hw bndry */
+#define DmaBigEndianDes         0x00100000 /* Big endian data buffer descriptors RW */
+#define DmaLittleEndianDesc              0 /* Little endian data descriptors */
+#define DmaBurstLength32        0x00002000 /* Dma burst length 32 RW */
+#define DmaBurstLength16        0x00001000 /* Dma burst length 16 */
+#define DmaBurstLength8         0x00000800 /* Dma burst length 8 */
+#define DmaBurstLength4         0x00000400 /* Dma burst length 4 */
+#define DmaBurstLength2         0x00000200 /* Dma burst length 2 */
+#define DmaBurstLength1         0x00000100 /* Dma burst length 1 */
+#define DmaBurstLength0         0x00000000 /* Dma burst length 0 */
+#define DmaBigEndianData        0x00000080 /* Big endian data buffers RW */
+#define DmaLittleEndianData              0 /* Little endian data buffers 0 */
+#define DmaDescriptorSkip16     0x00000040 /* number of dwords to skip RW */
+#define DmaDescriptorSkip8      0x00000020 /* between two unchained descriptors */
+#define DmaDescriptorSkip4      0x00000010
+#define DmaDescriptorSkip2      0x00000008
+#define DmaDescriptorSkip1      0x00000004
+#define DmaDescriptorSkip0               0
+#define DmaReceivePriorityOff   0x00000002 /* equal rx and tx priorities RW */
+#define DmaReceivePriorityOn             0 /* Rx has prioryty over Tx 0 */
+#define DmaResetOn              0x00000001 /* Reset DMA engine RW */
+#define DmaResetOff                      0
+
+/**********************************************************/
+/* DMA Status register layout                             */
+/**********************************************************/
+#define DmaRxAbort        0x01000000 /* receiver bus abort R 0 */
+#define DmaTxAbort        0x00800000 /* transmitter bus abort R 0 */
+#define DmaTxState        0x00700000 /* Transmit process state R 000 */
+#define DmaTxStopped      0x00000000 /* Stopped */
+#define DmaTxFetching     0x00100000 /* Running - fetching the descriptor */
+#define DmaTxWaiting      0x00200000 /* Running - waiting for end of transmission */
+#define DmaTxReading      0x00300000 /* Running - reading the data from memory */
+#define DmaTxSuspended    0x00600000 /* Suspended */
+#define DmaTxClosing      0x00700000 /* Running - closing descriptor */
+#define DmaRxState        0x000E0000 /* Receive process state 000 */
+#define DmaRxStopped      0x00000000 /* Stopped */
+#define DmaRxFetching     0x00020000 /* Running - fetching the descriptor */
+#define DmaRxChecking     0x00040000 /* Running - checking for end of packet */
+#define DmaRxWaiting      0x00060000 /* Running - waiting for packet */
+#define DmaRxSuspended    0x00080000 /* Suspended */
+#define DmaRxClosing      0x000A0000 /* Running - closing descriptor */
+#define DmaRxFlushing     0x000C0000 /* Running - flushing the current frame */
+#define DmaRxQueuing      0x000E0000 /* Running - queuing the recieve frame into host memory */
+#define DmaIntNormal      0x00010000 /* Normal interrupt summary RW 0 */
+#define DmaIntAbnormal    0x00008000 /* Abnormal interrupt summary RW 0 */
+#define DmaIntEarlyRx     0x00004000 /* Early receive interrupt (Normal) RW 0 */
+#define DmaIntBusError    0x00002000 /* Fatal bus error (Abnormal) RW 0 */
+#define DmaIntEarlyTx     0x00000400 /* Early transmit interrupt RW 0 */
+#define DmaIntRxStopped   0x00000100 /* Receive process stopped (Abnormal) RW 0 */
+#define DmaIntRxNoBuffer  0x00000080 /* Receive buffer unavailable (Abnormal) RW 0*/
+#define DmaIntRxCompleted 0x00000040 /* Completion of frame reception(Normal) RW 0*/
+#define DmaIntTxUnderflow 0x00000020 /* Transmit underflow (Abnormal) RW 0 */
+#define DmaIntTxJabber    0x00000008 /* Transmit Jabber Timeout (Abnormal) RW 0 */ 
+#define DmaIntTxNoBuffer  0x00000004 /* Transmit buffer unavailable (Normal) RW 0*/
+#define DmaIntTxStopped   0x00000002 /* Transmit process stopped (Abnormal) RW 0 */
+#define DmaIntTxCompleted 0x00000001 /* Transmit completed (Normal) RW 0 */
+
+/**********************************************************/
+/* DMA control register layout                            */
+/**********************************************************/
+#define DmaStoreAndForward 0x00000000 /* Store and forward RW 0 */
+#define DmaTxThreshCtl256  0x0000c000 /* Non-SF threshold is 256 words */
+#define DmaTxThreshCtl128  0x00008000 /* Non-SF threshold is 128 words */
+#define DmaTxThreshCtl064  0x00004000 /* Non-SF threshold is 64 words */
+#define DmaTxThreshCtl032  0x00000000 /* Non-SF threshold is 32 words */
+#define DmaTxStart         0x00002000 /* Start/Stop transmission RW 0 */
+#define DmaTxSecondFrame   0x00000004 /* Operate on second frame RW 0 */
+#define DmaRxStart         0x00000002 /* Start/Stop reception RW 0 */
+
+/**********************************************************/
+/* DMA interrupt enable register layout                   */
+/**********************************************************/
+#define DmaIeNormal      DmaIntNormal      /* Normal interrupt enable RW 0 */
+#define DmaIeAbnormal    DmaIntAbnormal    /* Abnormal interrupt enable RW 0 */
+#define DmaIeEarlyRx     DmaIntEarlyRx     /* Early receive interrupt enable RW 0 */
+#define DmaIeBusError    DmaIntBusError    /* Fatal bus error enable RW 0 */
+#define DmaIeEarlyTx     DmaIntEarlyTx     /* Early transmit interrupt enable RW 0 */
+#define DmaIeRxStopped   DmaIntRxStopped   /* Receive process stopped enable RW 0 */
+#define DmaIeRxNoBuffer  DmaIntRxNoBuffer  /* Receive buffer unavailable enable RW 0 */
+#define DmaIeRxCompleted DmaIntRxCompleted /* Completion of frame reception enable RW 0 */
+#define DmaIeTxUnderflow DmaIntTxUnderflow /* Transmit underflow enable RW 0 */
+#define DmaIeTxJabber    DmaIntTxJabber    /* Transmit jabber timeout RW 0 */
+#define DmaIeTxNoBuffer  DmaIntTxNoBuffer  /* Transmit buffer unavailable enable RW 0 */
+#define DmaIeTxStopped   DmaIntTxStopped   /* Transmit process stopped enable RW 0 */
+#define DmaIeTxCompleted DmaIntTxCompleted /* Transmit completed enable RW 0 */
+
+/****************************************************************/
+/* DMA Missed Frame and Buffer Overflow Counter register layout */
+/****************************************************************/
+#define DmaRxBufferMissedFrame  0xffff0000  /* cleared on read */
+#define DmaMissedFrameShift             16
+#define DmaRxBufferOverflowCnt  0x0000ffff  /* cleared on read */
+#define DmaMissedFrameCountMask 0x0000ffff
+
+/**********************************************************/
+/* DMA Engine descriptor layout                           */
+/**********************************************************/
+/* status word of DMA descriptor */
+#define DescOwnByDma         0x80000000 /* Descriptor is owned by DMA engine */
+#define DescFrameLengthMask  0x3FFF0000 /* Receive descriptor frame length */
+#define DescFrameLengthShift         16
+#define DescError            0x00008000 /* Error summary bit OR of following bits */
+#define DescRxTruncated      0x00004000 /* Rx - no more descs for receive frame */
+#define DescRxLengthError    0x00001000 /* Rx - frame size not matching with length field */
+#define DescRxRunt           0x00000800 /* Rx - runt frame, damaged by a
+                                           collision or term before 64 bytes */
+#define DescRxMulticast      0x00000400 /* Rx - received frame is multicast */
+#define DescRxFirst          0x00000200 /* Rx - first descriptor of the frame */
+#define DescRxLast           0x00000100 /* Rx - last descriptor of the frame */
+#define DescRxLongFrame      0x00000080 /* Rx - frame is longer than 1518 bytes */
+#define DescRxLateColl       0x00000040 /* Rx - frame was damaged by a late collision */
+#define DescRxFrameEther     0x00000020 /* Rx - Frame type Ethernet 802.3*/ 
+#define DescRxMiiError       0x00000008 /* Rx - error reported by MII interface */
+#define DescRxDribbling      0x00000004 /* Rx - frame contains noninteger multiple of 8 bits */
+#define DescRxCrc            0x00000002 /* Rx - CRC error */
+#define DescTxTimeout        0x00004000 /* Tx - Transmit jabber timeout */
+#define DescTxLostCarrier    0x00000800 /* Tx - carrier lost during tramsmission */
+#define DescTxNoCarrier      0x00000400 /* Tx - no carrier signal from tranceiver */
+#define DescTxLateCollision  0x00000200 /* Tx - transmission aborted due to collision */
+#define DescTxExcCollisions  0x00000100 /* Tx - transmission aborted after 16 collisions */
+#define DescTxHeartbeatFail  0x00000080 /* Tx - heartbeat collision check failure */
+#define DescTxCollMask       0x00000078 /* Tx - Collision count */
+#define DescTxCollShift               3
+#define DescTxExcDeferral    0x00000004 /* Tx - excessive deferral */
+#define DescTxUnderflow      0x00000002 /* Tx - late data arrival from memory */
+#define DescTxDeferred       0x00000001 /* Tx - frame transmision deferred */
+
+/* length word of DMA descriptor */
+#define DescTxIntEnable      0x80000000 /* Tx - interrupt on completion */
+#define DescTxLast           0x40000000 /* Tx - Last segment of the frame */
+#define DescTxFirst          0x20000000 /* Tx - First segment of the frame */
+#define DescTxDisableCrc     0x04000000 /* Tx - Add CRC disabled (first segment only) */
+#define DescEndOfRing        0x02000000 /* End of descriptors ring */
+#define DescChain            0x01000000 /* Second buffer address is chain address */
+#define DescTxDisablePadd    0x00800000 /* disable padding */
+#define DescSize2Mask        0x003FF800 /* Buffer 2 size */
+#define DescSize2Shift               11
+#define DescSize1Mask        0x000007FF /* Buffer 1 size */
+#define DescSize1Shift                0
+
+/**********************************************************/
+/* Initial register values                                */
+/**********************************************************/
+/* Full-duplex mode with perfect filter on */
+#define MacControlInitFdx \
+       ( MacFilterOn \
+       | MacLittleEndian \
+       | MacHeartBeatOn \
+       | MacSelectMii \
+       | MacEnableRxOwn \
+       | MacLoopbackOff \
+       | MacFullDuplex \
+       | MacMulticastFilterOn \
+       | MacPromiscuousModeOff \
+       | MacFilterNormal \
+       | MacBadFramesDisable \
+       | MacPerfectFilterOn \
+       | MacHashFilterOff \
+       | MacLateCollisionOff \
+       | MacBroadcastEnable \
+       | MacRetryEnable \
+       | MacPadStripDisable \
+       | MacDeferralCheckDisable \
+       | MacTxEnable \
+       | MacRxEnable)
+
+/* Full-duplex mode */
+#define MacFlowControlInitFdx \
+        ( MacControlFrameDisable \
+        | MacFlowControlEnable)
+
+/* Half-duplex mode with perfect filter on */
+#define MacControlInitHdx \
+       ( MacFilterOn \
+       | MacLittleEndian \
+       | MacHeartBeatOn \
+       | MacSelectMii \
+       | MacDisableRxOwn \
+       | MacLoopbackOff \
+       | MacHalfDuplex \
+       | MacMulticastFilterOn \
+       | MacPromiscuousModeOff \
+       | MacFilterNormal \
+       | MacBadFramesDisable \
+       | MacPerfectFilterOn \
+       | MacHashFilterOff \
+       | MacLateCollisionOff \
+       | MacBroadcastEnable \
+       | MacRetryEnable \
+       | MacPadStripDisable \
+       | MacDeferralCheckDisable \
+       | MacTxEnable \
+       | MacRxEnable)
+
+/* Half-duplex mode */
+#define MacFlowControlInitHdx \
+        ( MacControlFrameDisable \
+        | MacFlowControlDisable)
+
+/* Bus Mode Rx odd half word align */
+#define DmaBusModeInit  \
+       ( DmaLittleEndianDesc \
+       | DmaRxAlign16 \
+       | DmaBurstLength32 \
+       | DmaBigEndianData \
+       | DmaDescriptorSkip1 \
+       | DmaReceivePriorityOn \
+       | DmaResetOff)
+
+#define DmaControlInit (DmaStoreAndForward)
+
+/* Interrupt groups */
+#define DmaIntEnable \
+     ( DmaIeNormal \
+     | DmaIeAbnormal \
+     | DmaIntBusError \
+     | DmaIntRxStopped \
+     | DmaIntRxNoBuffer \
+     | DmaIntRxCompleted \
+     | DmaIntTxUnderflow \
+     | DmaIntTxStopped)
+
+#define DmaIntDisable 0
+
+#define DmaAllIntCauseMask \
+      ( DmaIeNormal  \
+      | DmaIeAbnormal  \
+      | DmaIntEarlyRx  \
+      | DmaIntBusError \
+      | DmaIntEarlyTx  \
+      | DmaIntRxStopped \
+      | DmaIntRxNoBuffer \
+      | DmaIntRxCompleted \
+      | DmaIntTxUnderflow \
+      | DmaIntTxJabber \
+      | DmaIntTxNoBuffer \
+      | DmaIntTxStopped \
+      | DmaIntTxCompleted)
+
+#define UnhandledIntrMask    \
+       (DmaAllIntCauseMask   \
+       & ~(DmaIntRxNoBuffer  \
+         | DmaIntTxStopped   \
+         | DmaIntTxJabber    \
+         | DmaIntTxUnderflow \
+         | DmaIntBusError    \
+         | DmaIntRxCompleted ))
+
+#define DescRxErrors    \
+      (DescRxTruncated  \
+     | DescRxRunt       \
+     | DescRxLateColl   \
+     | DescRxMiiError   \
+     | DescRxCrc)
+
+#define DescTxErrors        \
+     ( DescTxTimeout        \
+     | DescTxLateCollision  \
+     | DescTxExcCollisions  \
+     | DescTxExcDeferral    \
+     | DescTxUnderflow)
+
+/**********************************************************/
+/* Descriptor Layout                                      */
+/**********************************************************/
+#define AE531X_DESC_STATUS     0x00 /* Status offset */
+#define AE531X_DESC_CTRLEN     0x04 /* Control and Length offset */ 
+#define AE531X_DESC_BUFPTR     0x08 /* Buffer pointer offset */
+#define AE531X_DESC_LNKBUF     0x0c /* Link field offset, or ptr to 2nd buf */
+#define AE531X_DESC_SWPTR      0x10 /* OS-Dependent software pointer */
+
+#define AE531X_DESC_SIZE       0x10 /* 4 words, 16 bytes */
+#define AE531X_QUEUE_ELE_SIZE  0x14 /* with software pointer extension */
+
+/* Accessors to the dma descriptor fields */
+#define AE531X_DESC_STATUS_GET(ptr) \
+    *(volatile UINT32 *)((UINT32)(ptr) + AE531X_DESC_STATUS)
+
+#define AE531X_DESC_STATUS_SET(ptr, val)  \
+    AE531X_DESC_STATUS_GET(ptr) = (val)
+
+#define AE531X_DESC_CTRLEN_GET(ptr) \
+    *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_CTRLEN)
+
+#define AE531X_DESC_CTRLEN_SET(ptr, val)  \
+    AE531X_DESC_CTRLEN_GET(ptr) = (val)
+
+#define AE531X_DESC_BUFPTR_GET(ptr) \
+    *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_BUFPTR)
+
+#define AE531X_DESC_BUFPTR_SET(ptr,val)  \
+    AE531X_DESC_BUFPTR_GET(ptr) = (UINT32)(val)
+
+#define AE531X_DESC_LNKBUF_GET(ptr)  \
+    *(volatile UINT32 *)((UINT32)ptr + AE531X_DESC_LNKBUF)
+
+#define AE531X_DESC_LNKBUF_SET(ptr, val)  \
+    AE531X_DESC_LNKBUF_GET(ptr) = (val)
+
+#define AE531X_DESC_SWPTR_GET(ptr) \
+    (void *)(*(volatile UINT32 *) ((UINT32)ptr + AE531X_DESC_SWPTR))
+
+#define AE531X_DESC_SWPTR_SET(ptr,val)   \
+    AE531X_DESC_SWPTR_GET(ptr) = (void *)(val)
+
+/* Get size of Rx data from desc, in bytes */
+#define AE531X_DESC_STATUS_RX_SIZE(x) \
+        (((x) & DescFrameLengthMask) >> DescFrameLengthShift)
+
+#endif /* _AE531XREG_H_ */
diff -urN linux-mips-orig/drivers/net/ath/ar531x.h linux-mips-new/drivers/net/ath/ar531x.h
--- linux-mips-orig/drivers/net/ath/ar531x.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ar531x.h	2005-12-31 12:33:57.676538368 +0000
@@ -0,0 +1,1124 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+#ifndef AR531X_H
+#define AR531X_H 1
+
+
+#ifndef CONFIG_AR5315
+
+#include <asm/addrspace.h>
+
+/* Address Map */
+#define AR531X_WLAN0            0x18000000
+#define AR531X_WLAN1            0x18500000
+#define AR531X_ENET0            0x18100000
+#define AR531X_ENET1            0x18200000
+#define AR531X_SDRAMCTL         0x18300000
+#define AR531X_FLASHCTL         0x18400000
+#define AR531X_APBBASE		0x1c000000
+#define AR531X_FLASH            0x1e000000
+
+/*
+ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
+ * should be considered available.  The AR5312 supports 2 enet MACS,
+ * even though many reference boards only actually use 1 of them
+ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
+ * The AR2312 supports 1 enet MAC.
+ */
+#define AR531X_NUM_ENET_MAC             2
+
+/*
+ * Need these defines to determine true number of ethernet MACs
+ */
+#define AR5212_AR5312_REV2      0x0052          /* AR5312 WMAC (AP31) */
+#define AR5212_AR5312_REV7      0x0057          /* AR5312 WMAC (AP30-040) */
+#define AR5212_AR2313_REV8      0x0058          /* AR2313 WMAC (AP43-030) */
+#define AR531X_RADIO_MASK_OFF  0xc8
+#define AR531X_RADIO0_MASK     0x0003
+#define AR531X_RADIO1_MASK     0x000c
+#define AR531X_RADIO1_S        2 
+
+/*
+ * AR531X_NUM_WMAC defines the number of Wireless MACs that\
+ * should be considered available.
+ */
+#define AR531X_NUM_WMAC                 2
+
+/* Reset/Timer Block Address Map */
+#define AR531X_RESETTMR		(AR531X_APBBASE  + 0x3000)
+#define AR531X_TIMER		(AR531X_RESETTMR + 0x0000) /* countdown timer */
+#define AR531X_WD_CTRL          (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */
+#define AR531X_WD_TIMER         (AR531X_RESETTMR + 0x000c) /* watchdog timer */
+#define AR531X_ISR		(AR531X_RESETTMR + 0x0010) /* Intr Status Reg */
+#define AR531X_IMR		(AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */
+#define AR531X_RESET		(AR531X_RESETTMR + 0x0020)
+#define AR5312_CLOCKCTL1	(AR531X_RESETTMR + 0x0064)
+#define AR5312_SCRATCH   	(AR531X_RESETTMR + 0x006c)
+#define AR531X_PROCADDR		(AR531X_RESETTMR + 0x0070)
+#define AR531X_PROC1		(AR531X_RESETTMR + 0x0074)
+#define AR531X_DMAADDR		(AR531X_RESETTMR + 0x0078)
+#define AR531X_DMA1		(AR531X_RESETTMR + 0x007c)
+#define AR531X_ENABLE           (AR531X_RESETTMR + 0x0080) /* interface enb */
+#define AR531X_REV		(AR531X_RESETTMR + 0x0090) /* revision */
+
+/* AR531X_WD_CTRL register bit field definitions */
+#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000
+#define AR531X_WD_CTRL_NMI               0x0001
+#define AR531X_WD_CTRL_RESET             0x0002
+
+/* AR531X_ISR register bit field definitions */
+#define AR531X_ISR_NONE		0x0000
+#define AR531X_ISR_TIMER	0x0001
+#define AR531X_ISR_AHBPROC	0x0002
+#define AR531X_ISR_AHBDMA	0x0004
+#define AR531X_ISR_GPIO		0x0008
+#define AR531X_ISR_UART0	0x0010
+#define AR531X_ISR_UART0DMA	0x0020
+#define AR531X_ISR_WD		0x0040
+#define AR531X_ISR_LOCAL	0x0080
+
+/* AR531X_RESET register bit field definitions */
+#define AR531X_RESET_SYSTEM     0x00000001  /* cold reset full system */
+#define AR531X_RESET_PROC       0x00000002  /* cold reset MIPS core */
+#define AR531X_RESET_WLAN0      0x00000004  /* cold reset WLAN MAC and BB */
+#define AR531X_RESET_EPHY0      0x00000008  /* cold reset ENET0 phy */
+#define AR531X_RESET_EPHY1      0x00000010  /* cold reset ENET1 phy */
+#define AR531X_RESET_ENET0      0x00000020  /* cold reset ENET0 mac */
+#define AR531X_RESET_ENET1      0x00000040  /* cold reset ENET1 mac */
+#define AR531X_RESET_UART0      0x00000100  /* cold reset UART0 (high speed) */
+#define AR531X_RESET_WLAN1      0x00000200  /* cold reset WLAN MAC/BB */
+#define AR531X_RESET_APB        0x00000400  /* cold reset APB (ar5312) */
+#define AR531X_RESET_WARM_PROC  0x00001000  /* warm reset MIPS core */
+#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000  /* warm reset WLAN0 MAC */
+#define AR531X_RESET_WARM_WLAN0_BB  0x00004000  /* warm reset WLAN0 BaseBand */
+#define AR531X_RESET_NMI        0x00010000  /* send an NMI to the processor */
+#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000  /* warm reset WLAN1 mac */
+#define AR531X_RESET_WARM_WLAN1_BB  0x00040000  /* warm reset WLAN1 baseband */
+#define AR531X_RESET_LOCAL_BUS  0x00080000  /* reset local bus */
+#define AR531X_RESET_WDOG       0x00100000  /* last reset was a watchdog */
+
+#define AR531X_RESET_WMAC0_BITS \
+        AR531X_RESET_WLAN0 |\
+        AR531X_RESET_WARM_WLAN0_MAC |\
+        AR531X_RESET_WARM_WLAN0_BB
+
+#define AR531X_RESERT_WMAC1_BITS \
+        AR531X_RESET_WLAN1 |\
+        AR531X_RESET_WARM_WLAN1_MAC |\
+        AR531X_RESET_WARM_WLAN1_BB
+
+/* AR5312_CLOCKCTL1 register bit field definitions */
+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK    0x00000030
+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT            4
+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK   0x00001f00
+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT           8
+#define AR5312_CLOCKCTL1_DOUBLER_MASK      0x00010000
+
+/* Valid for AR5312 and AR2312 */
+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK    0x00000030
+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT            4
+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK   0x00001f00
+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT           8
+#define AR5312_CLOCKCTL1_DOUBLER_MASK      0x00010000
+
+/* Valid for AR2313 */
+#define AR2313_CLOCKCTL1_PREDIVIDE_MASK    0x00003000
+#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT           12
+#define AR2313_CLOCKCTL1_MULTIPLIER_MASK   0x001f0000
+#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT          16
+#define AR2313_CLOCKCTL1_DOUBLER_MASK      0x00000000
+
+
+/* AR531X_ENABLE register bit field definitions */
+#define AR531X_ENABLE_WLAN0              0x0001
+#define AR531X_ENABLE_ENET0              0x0002
+#define AR531X_ENABLE_ENET1              0x0004
+#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008   /* UART, and WLAN1 PIOs */
+#define AR531X_ENABLE_WLAN1_DMA          0x0010   /* WLAN1 DMAs */
+#define AR531X_ENABLE_WLAN1 \
+            (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA)
+
+/* AR531X_REV register bit field definitions */
+#define AR531X_REV_WMAC_MAJ    0xf000
+#define AR531X_REV_WMAC_MAJ_S  12
+#define AR531X_REV_WMAC_MIN    0x0f00
+#define AR531X_REV_WMAC_MIN_S  8
+#define AR531X_REV_MAJ         0x00f0
+#define AR531X_REV_MAJ_S       4
+#define AR531X_REV_MIN         0x000f
+#define AR531X_REV_MIN_S       0
+#define AR531X_REV_CHIP        (REV_MAJ|REV_MIN)
+
+/* Major revision numbers, bits 7..4 of Revision ID register */
+#define AR531X_REV_MAJ_AR5312          0x4
+#define AR531X_REV_MAJ_AR2313          0x5
+
+/* Minor revision numbers, bits 3..0 of Revision ID register */
+#define AR5312_REV_MIN_DUAL     0x0     /* Dual WLAN version */
+#define AR5312_REV_MIN_SINGLE   0x1     /* Single WLAN version */
+
+/* AR531X_FLASHCTL register bit field definitions */
+#define FLASHCTL_IDCY   0x0000000f      /* Idle cycle turn around time */
+#define FLASHCTL_IDCY_S 0
+#define FLASHCTL_WST1   0x000003e0      /* Wait state 1 */
+#define FLASHCTL_WST1_S 5
+#define FLASHCTL_RBLE   0x00000400      /* Read byte lane enable */
+#define FLASHCTL_WST2   0x0000f800      /* Wait state 2 */
+#define FLASHCTL_WST2_S 11
+#define FLASHCTL_AC     0x00070000      /* Flash address check (added) */
+#define FLASHCTL_AC_S   16
+#define FLASHCTL_AC_128K 0x00000000
+#define FLASHCTL_AC_256K 0x00010000
+#define FLASHCTL_AC_512K 0x00020000
+#define FLASHCTL_AC_1M   0x00030000
+#define FLASHCTL_AC_2M   0x00040000
+#define FLASHCTL_AC_4M   0x00050000
+#define FLASHCTL_AC_8M   0x00060000
+#define FLASHCTL_AC_RES  0x00070000     /* 16MB is not supported */
+#define FLASHCTL_E      0x00080000      /* Flash bank enable (added) */
+#define FLASHCTL_BUSERR 0x01000000      /* Bus transfer error status flag */
+#define FLASHCTL_WPERR  0x02000000      /* Write protect error status flag */
+#define FLASHCTL_WP     0x04000000      /* Write protect */
+#define FLASHCTL_BM     0x08000000      /* Burst mode */
+#define FLASHCTL_MW     0x30000000      /* Memory width */
+#define FLASHCTL_MWx8   0x00000000      /* Memory width x8 */
+#define FLASHCTL_MWx16  0x10000000      /* Memory width x16 */
+#define FLASHCTL_MWx32  0x20000000      /* Memory width x32 (not supported) */
+#define FLASHCTL_ATNR   0x00000000      /* Access type == no retry */
+#define FLASHCTL_ATR    0x80000000      /* Access type == retry every */
+#define FLASHCTL_ATR4   0xc0000000      /* Access type == retry every 4 */
+
+/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices.  */
+#define AR531X_FLASHCTL0        (AR531X_FLASHCTL + 0x00)
+#define AR531X_FLASHCTL1        (AR531X_FLASHCTL + 0x04)
+#define AR531X_FLASHCTL2        (AR531X_FLASHCTL + 0x08)
+
+/* ARM SDRAM Controller -- just enough to determine memory size */
+#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04)
+#define MEM_CFG1_AC0    0x00000700      /* bank 0: SDRAM addr check (added) */
+#define MEM_CFG1_AC0_S  8
+#define MEM_CFG1_AC1    0x00007000      /* bank 1: SDRAM addr check (added) */
+#define MEM_CFG1_AC1_S  12
+
+/* GPIO Address Map */
+#define AR531X_GPIO         (AR531X_APBBASE  + 0x2000)
+#define AR531X_GPIO_DO      (AR531X_GPIO + 0x00)        /* output register */
+#define AR531X_GPIO_DI      (AR531X_GPIO + 0x04)        /* intput register */
+#define AR531X_GPIO_CR      (AR531X_GPIO + 0x08)        /* control register */
+
+/* GPIO Control Register bit field definitions */
+#define GPIO_CR_M(x)    (1 << (x))                      /* mask for i/o */
+#define GPIO_CR_O(x)    (0 << (x))                      /* mask for output */
+#define GPIO_CR_I(x)    (1 << (x))                      /* mask for input */
+#define GPIO_CR_INT(x)  (1 << ((x)+8))                  /* mask for interrupt */
+#define GPIO_CR_UART(x) (1 << ((x)+16))                 /* uart multiplex */
+
+
+typedef unsigned int AR531X_REG;
+
+#define sysRegRead(phys)	\
+	(*(volatile AR531X_REG *)PHYS_TO_K1(phys))
+
+#define sysRegWrite(phys, val)	\
+	((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
+
+
+/*
+ * This is board-specific data that is stored in a "fixed" location in flash.
+ * It is shared across operating systems, so it should not be changed lightly.
+ * The main reason we need it is in order to extract the ethernet MAC
+ * address(es).
+ */
+struct ar531x_boarddata {
+    u32 magic;                       /* board data is valid */
+#define AR531X_BD_MAGIC 0x35333131   /* "5311", for all 531x platforms */
+    u16 cksum;                       /* checksum (starting with BD_REV 2) */
+    u16 rev;                         /* revision of this struct */
+#define BD_REV  4
+    char   boardName[64];            /* Name of board */
+    u16 major;                       /* Board major number */
+    u16 minor;                       /* Board minor number */
+    u32 config;                      /* Board configuration */
+#define BD_ENET0        0x00000001   /* ENET0 is stuffed */
+#define BD_ENET1        0x00000002   /* ENET1 is stuffed */
+#define BD_UART1        0x00000004   /* UART1 is stuffed */
+#define BD_UART0        0x00000008   /* UART0 is stuffed (dma) */
+#define BD_RSTFACTORY   0x00000010   /* Reset factory defaults stuffed */
+#define BD_SYSLED       0x00000020   /* System LED stuffed */
+#define BD_EXTUARTCLK   0x00000040   /* External UART clock */
+#define BD_CPUFREQ      0x00000080   /* cpu freq is valid in nvram */
+#define BD_SYSFREQ      0x00000100   /* sys freq is set in nvram */
+#define BD_WLAN0        0x00000200   /* Enable WLAN0 */
+#define BD_MEMCAP       0x00000400   /* CAP SDRAM @ memCap for testing */
+#define BD_DISWATCHDOG  0x00000800   /* disable system watchdog */
+#define BD_WLAN1        0x00001000   /* Enable WLAN1 (ar5212) */
+#define BD_ISCASPER     0x00002000   /* FLAG for AR2312 */
+#define BD_WLAN0_2G_EN  0x00004000   /* FLAG for radio0_2G */
+#define BD_WLAN0_5G_EN  0x00008000   /* FLAG for radio0_2G */
+#define BD_WLAN1_2G_EN  0x00020000   /* FLAG for radio0_2G */
+#define BD_WLAN1_5G_EN  0x00040000   /* FLAG for radio0_2G */
+    u16 resetConfigGpio;             /* Reset factory GPIO pin */
+    u16 sysLedGpio;                  /* System LED GPIO pin */
+
+    u32 cpuFreq;                     /* CPU core frequency in Hz */
+    u32 sysFreq;                     /* System frequency in Hz */
+    u32 cntFreq;                     /* Calculated C0_COUNT frequency */
+
+    u8  wlan0Mac[6];
+    u8  enet0Mac[6];
+    u8  enet1Mac[6];
+
+    u16 pciId;                       /* Pseudo PCIID for common code */
+    u16 memCap;                      /* cap bank1 in MB */
+
+    /* version 3 */
+    u8  wlan1Mac[6];                 /* (ar5212) */
+};
+
+#else
+
+/*
+ * Add support for Cobra
+ *
+ * AR531XPLUSreg.h Register definitions for Atheros AR5311 and AR5312 chipsets.
+ *   - WLAN registers are listed in
+ *         hal/ar5211/ar5211Reg.h
+ *         hal/ar5212/ar5212Reg.h
+ *   - Ethernet registers are listed in ar531xenet.h
+ *   - Standard UART is 16550 compatible.
+ */
+
+
+/*
+ * Address map
+ */
+#define AR531XPLUS_SDRAM0           0x00000000      /* DRAM */
+#define AR531XPLUS_SPI_READ         0x08000000      /* SPI FLASH */
+#define AR531XPLUS_WLAN0            0xB0000000      /* Wireless MMR */
+#define AR531XPLUS_PCI              0xB0100000      /* PCI MMR */
+#define AR531XPLUS_SDRAMCTL         0xB0300000      /* SDRAM MMR */
+#define AR531XPLUS_LOCAL            0xB0400000      /* LOCAL BUS MMR */
+#define AR531XPLUS_ENET0            0xB0500000      /* ETHERNET MMR */
+#define AR531XPLUS_DSLBASE          0xB1000000      /* RESET CONTROL MMR */
+#define AR531XPLUS_UART0            0xB1100003      /* UART MMR */
+#define AR531XPLUS_SPI              0xB1300000      /* SPI FLASH MMR */
+#define AR531XPLUS_FLASHBT          0xBfc00000      /* ro boot alias to FLASH */
+#define AR531XPLUS_RAM1             0x40000000      /* ram alias */
+#define AR531XPLUS_PCIEXT           0x80000000      /* pci external */
+#define AR531XPLUS_RAM2             0xc0000000      /* ram alias */
+#define AR531XPLUS_RAM3             0xe0000000      /* ram alias */
+
+#define AR531X_ENET0  AR531XPLUS_ENET0       
+#define AR531X_ENET1  0 
+/*
+ * Reset Register
+ */
+#define AR531XPLUS_COLD_RESET       (AR531XPLUS_DSLBASE + 0x0000)
+
+/* Cold Reset */
+#define RESET_COLD_AHB              0x00000001
+#define RESET_COLD_APB              0x00000002
+#define RESET_COLD_CPU              0x00000004
+#define RESET_COLD_CPUWARM          0x00000008
+#define RESET_SYSTEM                (RESET_COLD_CPU | RESET_COLD_APB | RESET_COLD_AHB)      /* full system */
+
+/* Warm Reset */
+
+#define AR531XPLUS_RESET            (AR531XPLUS_DSLBASE + 0x0004)
+#define AR531X_RESET AR531XPLUS_RESET
+
+#define RESET_WARM_WLAN0_MAC        0x00000001      /* warm reset WLAN0 MAC */
+#define RESET_WARM_WLAN0_BB         0x00000002      /* warm reset WLAN0 BaseBand */
+#define RESET_MPEGTS_RSVD           0x00000004      /* warm reset MPEG-TS */
+#define RESET_PCIDMA                0x00000008      /* warm reset PCI ahb/dma */
+#define RESET_MEMCTL                0x00000010      /* warm reset memory controller */
+#define RESET_LOCAL                 0x00000020      /* warm reset local bus */
+#define RESET_I2C_RSVD              0x00000040      /* warm reset I2C bus */
+#define RESET_SPI                   0x00000080      /* warm reset SPI interface */
+#define RESET_UART0                 0x00000100      /* warm reset UART0 */
+#define RESET_IR_RSVD               0x00000200      /* warm reset IR interface */
+#define RESET_EPHY0                 0x00000400      /* cold reset ENET0 phy */
+#define RESET_ENET0                 0x00000800      /* cold reset ENET0 mac */
+
+#define AR531X_RESET_ENET0 RESET_ENET0
+#define AR531X_RESET_EPHY0 RESET_EPHY0
+#define AR531X_RESET_ENET1 0
+#define AR531X_RESET_EPHY1 0
+
+/*
+ * AHB master arbitration control
+ */
+#define AR531XPLUS_AHB_ARB_CTL      (AR531XPLUS_DSLBASE + 0x0008)
+
+#define ARB_CPU                     0x00000001      /* CPU, default */
+#define ARB_WLAN                    0x00000002      /* WLAN */
+#define ARB_MPEGTS_RSVD             0x00000004      /* MPEG-TS */
+#define ARB_LOCAL                   0x00000008      /* LOCAL */
+#define ARB_PCI                     0x00000010      /* PCI */
+#define ARB_ETHERNET                0x00000020      /* Ethernet */
+#define ARB_RETRY                   0x00000100      /* retry policy, debug only */
+
+/*
+ * Config Register
+ */
+#define AR531XPLUS_ENDIAN_CTL       (AR531XPLUS_DSLBASE + 0x000c)
+
+#define CONFIG_AHB                  0x00000001      /* EC - AHB bridge endianess */
+#define CONFIG_WLAN                 0x00000002      /* WLAN byteswap */
+#define CONFIG_MPEGTS_RSVD          0x00000004      /* MPEG-TS byteswap */
+#define CONFIG_PCI                  0x00000008      /* PCI byteswap */
+#define CONFIG_MEMCTL               0x00000010      /* Memory controller endianess */
+#define CONFIG_LOCAL                0x00000020      /* Local bus byteswap */
+#define CONFIG_ETHERNET             0x00000040      /* Ethernet byteswap */
+
+#define CONFIG_MERGE                0x00000200      /* CPU write buffer merge */
+#define CONFIG_CPU                  0x00000400      /* CPU big endian */
+#define CONFIG_PCIAHB               0x00000800
+#define CONFIG_PCIAHB_BRIDGE        0x00001000
+#define CONFIG_SPI                  0x00008000      /* SPI byteswap */
+#define CONFIG_CPU_DRAM             0x00010000
+#define CONFIG_CPU_PCI              0x00020000
+#define CONFIG_CPU_MMR              0x00040000
+#define CONFIG_BIG                  0x00000400      
+
+
+/*
+ * NMI control
+ */
+#define AR531XPLUS_NMI_CTL          (AR531XPLUS_DSLBASE + 0x0010)
+
+#define NMI_EN  1
+
+/*
+ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR531X 1.0).
+ */
+#define AR531XPLUS_SREV             (AR531XPLUS_DSLBASE + 0x0014)
+
+#define AR531X_REV  AR531XPLUS_SREV
+
+#define REV_MAJ                     0x00f0
+#define REV_MAJ_S                   4
+#define REV_MIN                     0x000f
+#define REV_MIN_S                   0
+#define REV_CHIP                    (REV_MAJ|REV_MIN)
+
+#define AR531X_REV_MAJ REV_MAJ
+#define AR531X_REV_MAJ_S REV_MAJ_S
+#define AR531X_REV_MIN REV_MIN 
+#define AR531X_REV_MIN_S REV_MIN_S 
+#define REV_CHIP                    (REV_MAJ|REV_MIN)
+/*
+ * Need these defines to determine true number of ethernet MACs
+ */
+#define AR5212_AR5312_REV2      0x0052          /* AR5312 WMAC (AP31) */
+#define AR5212_AR5312_REV7      0x0057          /* AR5312 WMAC (AP30-040) */
+#define AR5212_AR2313_REV8      0x0058          /* AR2313 WMAC (AP43-030) */
+#define AR531X_RADIO_MASK_OFF  0xc8
+#define AR531X_RADIO0_MASK     0x0003
+#define AR531X_RADIO1_MASK     0x000c
+#define AR531X_RADIO1_S        2 
+
+/* Major revision numbers, bits 7..4 of Revision ID register */
+#define AR531X_REV_MAJ_AR5312          0x4
+#define AR531X_REV_MAJ_AR2313          0x5
+
+/*
+ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that
+ * should be considered available.  The AR5312 supports 2 enet MACS,
+ * even though many reference boards only actually use 1 of them
+ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch.
+ * The AR2312 supports 1 enet MAC.
+ */
+#define AR531X_NUM_ENET_MAC             1
+
+/*
+ * Interface Enable
+ */
+#define AR531XPLUS_IF_CTL           (AR531XPLUS_DSLBASE + 0x0018)
+
+#define IF_MASK                     0x00000007
+#define IF_DISABLED                 0
+#define IF_PCI                      1
+#define IF_TS_LOCAL                 2
+#define IF_ALL                      3   /* only for emulation with separate pins */
+#define IF_LOCAL_HOST               0x00000008
+#define IF_PCI_HOST                 0x00000010
+#define IF_PCI_INTR                 0x00000020
+#define IF_PCI_CLK_MASK             0x00030000
+#define IF_PCI_CLK_INPUT            0 
+#define IF_PCI_CLK_OUTPUT_LOW       1
+#define IF_PCI_CLK_OUTPUT_CLK       2
+#define IF_PCI_CLK_OUTPUT_HIGH      3
+#define IF_PCI_CLK_SHIFT            16 
+ 
+                
+/* Major revision numbers, bits 7..4 of Revision ID register */
+#define REV_MAJ_AR5311              0x01
+#define REV_MAJ_AR5312              0x04
+#define REV_MAJ_AR5315              0x0B
+
+/*
+ * APB Interrupt control
+ */
+
+#define AR531XPLUS_ISR              (AR531XPLUS_DSLBASE + 0x0020)
+#define AR531XPLUS_IMR              (AR531XPLUS_DSLBASE + 0x0024)
+#define AR531XPLUS_GISR             (AR531XPLUS_DSLBASE + 0x0028)
+
+#define ISR_UART0                   0x0001           /* high speed UART */
+#define ISR_I2C_RSVD                0x0002           /* I2C bus */
+#define ISR_SPI                     0x0004           /* SPI bus */
+#define ISR_AHB                     0x0008           /* AHB error */
+#define ISR_APB                     0x0010           /* APB error */
+#define ISR_TIMER                   0x0020           /* timer */
+#define ISR_GPIO                    0x0040           /* GPIO */
+#define ISR_WD                      0x0080           /* watchdog */
+#define ISR_IR_RSVD                 0x0100           /* IR */
+                                
+#define IMR_UART0                   ISR_UART0
+#define IMR_I2C_RSVD                ISR_I2C_RSVD
+#define IMR_SPI                     ISR_SPI
+#define IMR_AHB                     ISR_AHB
+#define IMR_APB                     ISR_APB
+#define IMR_TIMER                   ISR_TIMER
+#define IMR_GPIO                    ISR_GPIO
+#define IMR_WD                      ISR_WD
+#define IMR_IR_RSVD                 ISR_IR_RSVD
+
+#define GISR_MISC                   0x0001
+#define GISR_WLAN0                  0x0002
+#define GISR_MPEGTS_RSVD            0x0004
+#define GISR_LOCALPCI               0x0008
+#define GISR_WMACPOLL               0x0010
+#define GISR_TIMER                  0x0020
+#define GISR_ETHERNET               0x0040
+
+/*
+ * Interrupt routing from IO to the processor IP bits
+ * Define our inter mask and level
+ */
+#define AR531XPLUS_INTR_MISCIO      SR_IBIT3
+#define AR531XPLUS_INTR_WLAN0       SR_IBIT4
+#define AR531XPLUS_INTR_ENET0       SR_IBIT5
+#define AR531XPLUS_INTR_LOCALPCI    SR_IBIT6
+#define AR531XPLUS_INTR_WMACPOLL    SR_IBIT7
+#define AR531XPLUS_INTR_COMPARE     SR_IBIT8
+
+/*
+ * Timers
+ */
+#define AR531XPLUS_TIMER            (AR531XPLUS_DSLBASE + 0x0030)
+#define AR531XPLUS_RELOAD           (AR531XPLUS_DSLBASE + 0x0034)
+#define AR531XPLUS_WD               (AR531XPLUS_DSLBASE + 0x0038)
+#define AR531XPLUS_WDC              (AR531XPLUS_DSLBASE + 0x003c)
+
+#define WDC_RESET                   0x00000002               /* reset on watchdog */
+#define WDC_NMI                     0x00000001               /* NMI on watchdog */
+#define WDC_IGNORE_EXPIRATION       0x00000000
+
+/*
+ * Interface Debug
+ */
+#define AR531X_FLASHDBG             (AR531X_RESETTMR + 0x0040)
+#define AR531X_MIIDBG               (AR531X_RESETTMR + 0x0044)
+
+
+/*
+ * CPU Performance Counters
+ */
+#define AR531XPLUS_PERFCNT0         (AR531XPLUS_DSLBASE + 0x0048)
+#define AR531XPLUS_PERFCNT1         (AR531XPLUS_DSLBASE + 0x004c)
+
+#define PERF_DATAHIT                0x0001  /* Count Data Cache Hits */
+#define PERF_DATAMISS               0x0002  /* Count Data Cache Misses */
+#define PERF_INSTHIT                0x0004  /* Count Instruction Cache Hits */
+#define PERF_INSTMISS               0x0008  /* Count Instruction Cache Misses */
+#define PERF_ACTIVE                 0x0010  /* Count Active Processor Cycles */
+#define PERF_WBHIT                  0x0020  /* Count CPU Write Buffer Hits */
+#define PERF_WBMISS                 0x0040  /* Count CPU Write Buffer Misses */
+                                
+#define PERF_EB_ARDY                0x0001  /* Count EB_ARdy signal */
+#define PERF_EB_AVALID              0x0002  /* Count EB_AValid signal */
+#define PERF_EB_WDRDY               0x0004  /* Count EB_WDRdy signal */
+#define PERF_EB_RDVAL               0x0008  /* Count EB_RdVal signal */
+#define PERF_VRADDR                 0x0010  /* Count valid read address cycles */
+#define PERF_VWADDR                 0x0020  /* Count valid write address cycles */
+#define PERF_VWDATA                 0x0040  /* Count valid write data cycles */
+
+/*
+ * AHB Error Reporting.
+ */
+#define AR531XPLUS_AHB_ERR0         (AR531XPLUS_DSLBASE + 0x0050)  /* error  */
+#define AR531XPLUS_AHB_ERR1         (AR531XPLUS_DSLBASE + 0x0054)  /* haddr  */
+#define AR531XPLUS_AHB_ERR2         (AR531XPLUS_DSLBASE + 0x0058)  /* hwdata */
+#define AR531XPLUS_AHB_ERR3         (AR531XPLUS_DSLBASE + 0x005c)  /* hrdata */
+#define AR531XPLUS_AHB_ERR4         (AR531XPLUS_DSLBASE + 0x0060)  /* status */
+
+#define AHB_ERROR_DET               1   /* AHB Error has been detected,          */
+                                        /* write 1 to clear all bits in ERR0     */
+#define AHB_ERROR_OVR               2   /* AHB Error overflow has been detected  */
+#define AHB_ERROR_WDT               4   /* AHB Error due to wdt instead of hresp */
+
+#define PROCERR_HMAST               0x0000000f
+#define PROCERR_HMAST_DFLT          0
+#define PROCERR_HMAST_WMAC          1
+#define PROCERR_HMAST_ENET          2
+#define PROCERR_HMAST_PCIENDPT      3
+#define PROCERR_HMAST_LOCAL         4
+#define PROCERR_HMAST_CPU           5
+#define PROCERR_HMAST_PCITGT        6
+                                    
+#define PROCERR_HMAST_S             0
+#define PROCERR_HWRITE              0x00000010
+#define PROCERR_HSIZE               0x00000060
+#define PROCERR_HSIZE_S             5
+#define PROCERR_HTRANS              0x00000180
+#define PROCERR_HTRANS_S            7
+#define PROCERR_HBURST              0x00000e00
+#define PROCERR_HBURST_S            9
+
+
+
+/*
+ * Clock Control
+ */
+#define AR531XPLUS_PLLC_CTL         (AR531XPLUS_DSLBASE + 0x0064)
+#define AR531XPLUS_PLLV_CTL         (AR531XPLUS_DSLBASE + 0x0068)
+#define AR531XPLUS_CPUCLK           (AR531XPLUS_DSLBASE + 0x006c)
+#define AR531XPLUS_AMBACLK          (AR531XPLUS_DSLBASE + 0x0070)
+#define AR531XPLUS_SYNCCLK          (AR531XPLUS_DSLBASE + 0x0074)
+#define AR531XPLUS_DSL_SLEEP_CTL    (AR531XPLUS_DSLBASE + 0x0080)
+#define AR531XPLUS_DSL_SLEEP_DUR    (AR531XPLUS_DSLBASE + 0x0084)
+
+/* PLLc Control fields */
+#define PLLC_REF_DIV_M              0x00000003
+#define PLLC_REF_DIV_S              0
+#define PLLC_FDBACK_DIV_M           0x0000007C
+#define PLLC_FDBACK_DIV_S           2
+#define PLLC_ADD_FDBACK_DIV_M       0x00000080
+#define PLLC_ADD_FDBACK_DIV_S       7
+#define PLLC_CLKC_DIV_M             0x0001c000
+#define PLLC_CLKC_DIV_S             14
+#define PLLC_CLKM_DIV_M             0x00700000
+#define PLLC_CLKM_DIV_S             20
+
+/* CPU CLK Control fields */
+#define CPUCLK_CLK_SEL_M            0x00000003
+#define CPUCLK_CLK_SEL_S            0
+#define CPUCLK_CLK_DIV_M            0x0000000c
+#define CPUCLK_CLK_DIV_S            2
+
+/* AMBA CLK Control fields */
+#define AMBACLK_CLK_SEL_M           0x00000003
+#define AMBACLK_CLK_SEL_S           0
+#define AMBACLK_CLK_DIV_M           0x0000000c
+#define AMBACLK_CLK_DIV_S           2
+
+#if defined(COBRA_EMUL)
+#define AR531XPLUS_AMBA_CLOCK_RATE  20000000
+#define AR531XPLUS_CPU_CLOCK_RATE   40000000
+#else
+#if defined(DEFAULT_PLL)
+#define AR531XPLUS_AMBA_CLOCK_RATE  40000000
+#define AR531XPLUS_CPU_CLOCK_RATE   40000000
+#else
+#define AR531XPLUS_AMBA_CLOCK_RATE  92000000
+#define AR531XPLUS_CPU_CLOCK_RATE   184000000
+#endif /* ! DEFAULT_PLL */
+#endif /* ! COBRA_EMUL */
+
+#define AR531XPLUS_UART_CLOCK_RATE  AR531XPLUS_AMBA_CLOCK_RATE
+#define AR531XPLUS_SDRAM_CLOCK_RATE AR531XPLUS_AMBA_CLOCK_RATE
+
+/*
+ * The UART computes baud rate as:
+ *   baud = clock / (16 * divisor)
+ * where divisor is specified as a High Byte (DLM) and a Low Byte (DLL).
+ */
+#define DESIRED_BAUD_RATE           38400
+
+/*
+ * The WATCHDOG value is computed as
+ *  10 seconds * AR531X_WATCHDOG_CLOCK_RATE
+ */
+#define DESIRED_WATCHDOG_SECONDS    10
+#define AR531X_WATCHDOG_TIME \
+        (DESIRED_WATCHDOG_SECONDS * AR531X_WATCHDOG_CLOCK_RATE)
+
+
+#define CLOCKCTL_UART0  0x0010  /* enable UART0 external clock */
+
+
+ /*
+ * Applicable "PCICFG" bits for WLAN(s).  Assoc status and LED mode.
+ */
+#define AR531X_PCICFG               (AR531X_RESETTMR + 0x00b0)
+#define ASSOC_STATUS_M              0x00000003
+#define ASSOC_STATUS_NONE           0
+#define ASSOC_STATUS_PENDING        1   
+#define ASSOC_STATUS_ASSOCIATED     2
+#define LED_MODE_M                  0x0000001c
+#define LED_BLINK_THRESHOLD_M       0x000000e0
+#define LED_SLOW_BLINK_MODE         0x00000100
+
+/*
+ * GPIO
+ */
+
+#define AR531XPLUS_GPIO_DI          (AR531XPLUS_DSLBASE + 0x0088)
+#define AR531XPLUS_GPIO_DO          (AR531XPLUS_DSLBASE + 0x0090)
+#define AR531XPLUS_GPIO_CR          (AR531XPLUS_DSLBASE + 0x0098)
+#define AR531XPLUS_GPIO_INT         (AR531XPLUS_DSLBASE + 0x00a0)
+
+#define GPIO_CR_M(x)                (1 << (x))                  /* mask for i/o */
+#define GPIO_CR_O(x)                (1 << (x))                  /* output */
+#define GPIO_CR_I(x)                (0 << (x))                  /* input */
+
+#define GPIO_INT(x,Y)               ((x) << (8 * (Y)))          /* interrupt enable */
+#define GPIO_INT_M(Y)               ((0x3F) << (8 * (Y)))       /* mask for int */
+#define GPIO_INT_LVL(x,Y)           ((x) << (8 * (Y) + 6))      /* interrupt level */
+#define GPIO_INT_LVL_M(Y)           ((0x3) << (8 * (Y) + 6))    /* mask for int level */
+
+#define AR531XPLUS_RESET_GPIO       5
+#define AR531XPLUS_NUM_GPIO         22
+
+    
+/* 
+ *  PCI Clock Control
+ */     
+ 
+#define AR531XPLUS_PCICLK           (AR531XPLUS_DSLBASE + 0x00a4)
+
+#define PCICLK_INPUT_M              0x3
+#define PCICLK_INPUT_S              0
+                         
+#define PCICLK_PLLC_CLKM            0
+#define PCICLK_PLLC_CLKM1           1
+#define PCICLK_PLLC_CLKC            2
+#define PCICLK_REF_CLK              3 
+
+#define PCICLK_DIV_M                0xc
+#define PCICLK_DIV_S                2
+                         
+#define PCICLK_IN_FREQ              0
+#define PCICLK_IN_FREQ_DIV_6        1
+#define PCICLK_IN_FREQ_DIV_8        2
+#define PCICLK_IN_FREQ_DIV_10       3 
+
+/*
+ * Observation Control Register
+ */
+#define AR531XPLUS_OCR              (AR531XPLUS_DSLBASE + 0x00b0)
+#define OCR_GPIO0_IRIN              0x0040
+#define OCR_GPIO1_IROUT             0x0080
+#define OCR_GPIO3_RXCLR             0x0200
+
+/* 
+ *  General Clock Control
+ */     
+ 
+#define AR531XPLUS_MISCCLK          (AR531XPLUS_DSLBASE + 0x00b4)
+#define MISCCLK_PLLBYPASS_EN        0x00000001
+#define MISCCLK_PROCREFCLK          0x00000002
+
+/*
+ * SDRAM Controller
+ *   - No read or write buffers are included.
+ */
+#define AR531XPLUS_MEM_CFG          (AR531XPLUS_SDRAMCTL + 0x00)
+#define AR531XPLUS_MEM_CTRL         (AR531XPLUS_SDRAMCTL + 0x0c)
+#define AR531XPLUS_MEM_REF          (AR531XPLUS_SDRAMCTL + 0x10)
+
+#define SDRAM_DATA_WIDTH_M          0x00006000
+#define SDRAM_DATA_WIDTH_S          13
+
+#define SDRAM_COL_WIDTH_M           0x00001E00
+#define SDRAM_COL_WIDTH_S           9
+
+#define SDRAM_ROW_WIDTH_M           0x000001E0
+#define SDRAM_ROW_WIDTH_S           5
+
+#define SDRAM_BANKADDR_BITS_M       0x00000018
+#define SDRAM_BANKADDR_BITS_S       3
+
+
+/*
+ * SDRAM Memory Refresh (MEM_REF) value is computed as:
+ * MEMCTL_SREFR = (Tr * hclk_freq) / R
+ * where Tr is max. time of refresh of any single row
+ * R is number of rows in the DRAM
+ * For most 133MHz SDRAM parts, Tr=64ms, R=4096 or 8192
+ */
+#if defined(COBRA_EMUL)
+#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE  0x96
+#else 
+#if defined(DEFAULT_PLL)
+#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE  0x200
+#else
+#define AR531XPLUS_SDRAM_MEMORY_REFRESH_VALUE  0x61a
+#endif /* ! DEFAULT_PLL */
+#endif 
+
+#if defined(AR531XPLUS)
+
+#define AR531XPLUS_SDRAM_DDR_SDRAM      0   /* Not DDR SDRAM */
+#define AR531XPLUS_SDRAM_DATA_WIDTH     16  /* bits */   
+#define AR531XPLUS_SDRAM_COL_WIDTH      8
+#define AR531XPLUS_SDRAM_ROW_WIDTH      12
+
+#else
+
+#define AR531XPLUS_SDRAM_DDR_SDRAM      0   /* Not DDR SDRAM */
+#define AR531XPLUS_SDRAM_DATA_WIDTH     16
+#define AR531XPLUS_SDRAM_COL_WIDTH      8
+#define AR531XPLUS_SDRAM_ROW_WIDTH      12
+
+#endif /* ! AR531XPLUS */
+
+/*
+ * SPI Flash Interface Registers
+ */
+
+#define AR531XPLUS_SPI_CTL      (AR531XPLUS_SPI + 0x00)
+#define AR531XPLUS_SPI_OPCODE   (AR531XPLUS_SPI + 0x04)
+#define AR531XPLUS_SPI_DATA     (AR531XPLUS_SPI + 0x08)
+
+#define SPI_CTL_START           0x00000100
+#define SPI_CTL_BUSY            0x00010000
+#define SPI_CTL_TXCNT_MASK      0x0000000f
+#define SPI_CTL_RXCNT_MASK      0x000000f0
+#define SPI_CTL_TX_RX_CNT_MASK  0x000000ff
+#define SPI_CTL_SIZE_MASK       0x00060000
+
+#define SPI_CTL_CLK_SEL_MASK    0x03000000
+#define SPI_OPCODE_MASK         0x000000ff
+
+/* 
+ * PCI-MAC Configuration registers 
+ */
+#define PCI_MAC_RC              (AR531XPLUS_PCI + 0x4000) 
+#define PCI_MAC_SCR             (AR531XPLUS_PCI + 0x4004)
+#define PCI_MAC_INTPEND         (AR531XPLUS_PCI + 0x4008)
+#define PCI_MAC_SFR             (AR531XPLUS_PCI + 0x400C)
+#define PCI_MAC_PCICFG          (AR531XPLUS_PCI + 0x4010)
+#define PCI_MAC_SREV            (AR531XPLUS_PCI + 0x4020)
+
+#define PCI_MAC_RC_MAC          0x00000001
+#define PCI_MAC_RC_BB           0x00000002
+
+#define PCI_MAC_SCR_SLMODE_M    0x00030000
+#define PCI_MAC_SCR_SLMODE_S    16        
+#define PCI_MAC_SCR_SLM_FWAKE   0         
+#define PCI_MAC_SCR_SLM_FSLEEP  1         
+#define PCI_MAC_SCR_SLM_NORMAL  2         
+
+#define PCI_MAC_SFR_SLEEP       0x00000001
+
+#define PCI_MAC_PCICFG_SPWR_DN  0x00010000
+
+ 
+
+
+/*
+ * PCI Bus Interface Registers
+ */
+#define AR531XPLUS_PCI_1MS_REG      (AR531XPLUS_PCI + 0x0008)
+#define AR531XPLUS_PCI_1MS_MASK     0x3FFFF         /* # of AHB clk cycles in 1ms */
+
+#define AR531XPLUS_PCI_MISC_CONFIG  (AR531XPLUS_PCI + 0x000c)
+#define AR531XPLUS_PCIMISC_TXD_EN   0x00000001      /* Enable TXD for fragments */
+#define AR531XPLUS_PCIMISC_CFG_SEL  0x00000002      /* mem or config cycles */
+#define AR531XPLUS_PCIMISC_GIG_MASK 0x0000000C      /* bits 31-30 for pci req */
+#define AR531XPLUS_PCIMISC_RST_MODE 0x00000030
+#define AR531XPLUS_PCIRST_INPUT     0x00000000      /* 4:5=0 rst is input */
+#define AR531XPLUS_PCIRST_LOW       0x00000010      /* 4:5=1 rst to GND */
+#define AR531XPLUS_PCIRST_HIGH      0x00000020      /* 4:5=2 rst to VDD */
+#define AR531XPLUS_PCIGRANT_EN      0x00000000      /* 6:7=0 early grant en */
+#define AR531XPLUS_PCIGRANT_FRAME   0x00000040      /* 6:7=1 grant waits 4 frame */
+#define AR531XPLUS_PCIGRANT_IDLE    0x00000080      /* 6:7=2 grant waits 4 idle */
+#define AR531XPLUS_PCIGRANT_GAP     0x00000000      /* 6:7=2 grant waits 4 idle */
+#define AR531XPLUS_PCICACHE_DIS     0x00001000      /* PCI external access cache disable */
+
+#define AR531XPLUS_PCI_OUT_TSTAMP   (AR531XPLUS_PCI + 0x0010)
+
+#define AR531XPLUS_PCI_UNCACHE_CFG  (AR531XPLUS_PCI + 0x0014)
+
+#define AR531XPLUS_PCI_IN_EN        (AR531XPLUS_PCI + 0x0100)
+#define AR531XPLUS_PCI_IN_EN0       0x01            /* Enable chain 0 */
+#define AR531XPLUS_PCI_IN_EN1       0x02            /* Enable chain 1 */
+#define AR531XPLUS_PCI_IN_EN2       0x04            /* Enable chain 2 */
+#define AR531XPLUS_PCI_IN_EN3       0x08            /* Enable chain 3 */
+
+#define AR531XPLUS_PCI_IN_DIS       (AR531XPLUS_PCI + 0x0104)
+#define AR531XPLUS_PCI_IN_DIS0      0x01            /* Disable chain 0 */
+#define AR531XPLUS_PCI_IN_DIS1      0x02            /* Disable chain 1 */
+#define AR531XPLUS_PCI_IN_DIS2      0x04            /* Disable chain 2 */
+#define AR531XPLUS_PCI_IN_DIS3      0x08            /* Disable chain 3 */
+
+#define AR531XPLUS_PCI_IN_PTR       (AR531XPLUS_PCI + 0x0200)
+
+#define AR531XPLUS_PCI_OUT_EN       (AR531XPLUS_PCI + 0x0400)
+#define AR531XPLUS_PCI_OUT_EN0      0x01            /* Enable chain 0 */
+
+#define AR531XPLUS_PCI_OUT_DIS      (AR531XPLUS_PCI + 0x0404)
+#define AR531XPLUS_PCI_OUT_DIS0     0x01            /* Disable chain 0 */
+
+#define AR531XPLUS_PCI_OUT_PTR      (AR531XPLUS_PCI + 0x0408)
+
+#define AR531XPLUS_PCI_INT_STATUS   (AR531XPLUS_PCI + 0x0500)   /* write one to clr */
+#define AR531XPLUS_PCI_TXINT        0x00000001      /* Desc In Completed */
+#define AR531XPLUS_PCI_TXOK         0x00000002      /* Desc In OK */
+#define AR531XPLUS_PCI_TXERR        0x00000004      /* Desc In ERR */
+#define AR531XPLUS_PCI_TXEOL        0x00000008      /* Desc In End-of-List */
+#define AR531XPLUS_PCI_RXINT        0x00000010      /* Desc Out Completed */
+#define AR531XPLUS_PCI_RXOK         0x00000020      /* Desc Out OK */
+#define AR531XPLUS_PCI_RXERR        0x00000040      /* Desc Out ERR */
+#define AR531XPLUS_PCI_RXEOL        0x00000080      /* Desc Out EOL */
+#define AR531XPLUS_PCI_TXOOD        0x00000200      /* Desc In Out-of-Desc */
+#define AR531XPLUS_PCI_MASK         0x0000FFFF      /* Desc Mask */
+#define AR531XPLUS_PCI_EXT_INT      0x02000000      
+#define AR531XPLUS_PCI_ABORT_INT    0x04000000      
+
+#define AR531XPLUS_PCI_INT_MASK     (AR531XPLUS_PCI + 0x0504)   /* same as INT_STATUS */
+
+#define AR531XPLUS_PCI_INTEN_REG    (AR531XPLUS_PCI + 0x0508)
+#define AR531XPLUS_PCI_INT_DISABLE  0x00            /* disable pci interrupts */
+#define AR531XPLUS_PCI_INT_ENABLE   0x01            /* enable pci interrupts */
+
+#define AR531XPLUS_PCI_HOST_IN_EN   (AR531XPLUS_PCI + 0x0800)
+#define AR531XPLUS_PCI_HOST_IN_DIS  (AR531XPLUS_PCI + 0x0804)
+#define AR531XPLUS_PCI_HOST_IN_PTR  (AR531XPLUS_PCI + 0x0810)
+#define AR531XPLUS_PCI_HOST_OUT_EN  (AR531XPLUS_PCI + 0x0900)
+#define AR531XPLUS_PCI_HOST_OUT_DIS (AR531XPLUS_PCI + 0x0904)
+#define AR531XPLUS_PCI_HOST_OUT_PTR (AR531XPLUS_PCI + 0x0908)
+
+
+/*
+ * Local Bus Interface Registers
+ */
+#define AR531XPLUS_LB_CONFIG        (AR531XPLUS_LOCAL + 0x0000)
+#define AR531XPLUS_LBCONF_OE        0x00000001      /* =1 OE is low-true */
+#define AR531XPLUS_LBCONF_CS0       0x00000002      /* =1 first CS is low-true */
+#define AR531XPLUS_LBCONF_CS1       0x00000004      /* =1 2nd CS is low-true */
+#define AR531XPLUS_LBCONF_RDY       0x00000008      /* =1 RDY is low-true */
+#define AR531XPLUS_LBCONF_WE        0x00000010      /* =1 Write En is low-true */
+#define AR531XPLUS_LBCONF_WAIT      0x00000020      /* =1 WAIT is low-true */
+#define AR531XPLUS_LBCONF_ADS       0x00000040      /* =1 Adr Strobe is low-true */
+#define AR531XPLUS_LBCONF_MOT       0x00000080      /* =0 Intel, =1 Motorola */
+#define AR531XPLUS_LBCONF_8CS       0x00000100      /* =1 8 bits CS, 0= 16bits */
+#define AR531XPLUS_LBCONF_8DS       0x00000200      /* =1 8 bits Data S, 0=16bits */
+#define AR531XPLUS_LBCONF_ADS_EN    0x00000400      /* =1 Enable ADS */
+#define AR531XPLUS_LBCONF_ADR_OE    0x00000800      /* =1 Adr cap on OE, WE or DS */
+#define AR531XPLUS_LBCONF_ADDT_MUX  0x00001000      /* =1 Adr and Data share bus */
+#define AR531XPLUS_LBCONF_DATA_OE   0x00002000      /* =1 Data cap on OE, WE, DS */
+#define AR531XPLUS_LBCONF_16DATA    0x00004000      /* =1 Data is 16 bits wide */
+#define AR531XPLUS_LBCONF_SWAPDT    0x00008000      /* =1 Byte swap data */
+#define AR531XPLUS_LBCONF_SYNC      0x00010000      /* =1 Bus synchronous to clk */
+#define AR531XPLUS_LBCONF_INT       0x00020000      /* =1 Intr is low true */
+#define AR531XPLUS_LBCONF_INT_CTR0  0x00000000      /* GND high-Z, Vdd is high-Z */
+#define AR531XPLUS_LBCONF_INT_CTR1  0x00040000      /* GND drive, Vdd is high-Z */
+#define AR531XPLUS_LBCONF_INT_CTR2  0x00080000      /* GND high-Z, Vdd drive */
+#define AR531XPLUS_LBCONF_INT_CTR3  0x000C0000      /* GND drive, Vdd drive */
+#define AR531XPLUS_LBCONF_RDY_WAIT  0x00100000      /* =1 RDY is negative of WAIT */
+#define AR531XPLUS_LBCONF_INT_PULSE 0x00200000      /* =1 Interrupt is a pulse */
+#define AR531XPLUS_LBCONF_ENABLE    0x00400000      /* =1 Falcon respond to LB */
+
+#define AR531XPLUS_LB_CLKSEL        (AR531XPLUS_LOCAL + 0x0004)
+#define AR531XPLUS_LBCLK_EXT        0x0001          /* use external clk for lb */
+
+#define AR531XPLUS_LB_1MS           (AR531XPLUS_LOCAL + 0x0008)
+#define AR531XPLUS_LB1MS_MASK       0x3FFFF         /* # of AHB clk cycles in 1ms */
+
+#define AR531XPLUS_LB_MISCCFG       (AR531XPLUS_LOCAL + 0x000C)
+#define AR531XPLUS_LBM_TXD_EN       0x00000001      /* Enable TXD for fragments */
+#define AR531XPLUS_LBM_RX_INTEN     0x00000002      /* Enable LB ints on RX ready */
+#define AR531XPLUS_LBM_MBOXWR_INTEN 0x00000004      /* Enable LB ints on mbox wr */
+#define AR531XPLUS_LBM_MBOXRD_INTEN 0x00000008      /* Enable LB ints on mbox rd */
+#define AR531XPLUS_LMB_DESCSWAP_EN  0x00000010      /* Byte swap desc enable */
+#define AR531XPLUS_LBM_TIMEOUT_MASK 0x00FFFF80
+#define AR531XPLUS_LBM_TIMEOUT_SHFT 7
+#define AR531XPLUS_LBM_PORTMUX      0x07000000
+
+
+#define AR531XPLUS_LB_RXTSOFF       (AR531XPLUS_LOCAL + 0x0010)
+
+#define AR531XPLUS_LB_TX_CHAIN_EN   (AR531XPLUS_LOCAL + 0x0100)
+#define AR531XPLUS_LB_TXEN_0        0x01
+#define AR531XPLUS_LB_TXEN_1        0x02
+#define AR531XPLUS_LB_TXEN_2        0x04
+#define AR531XPLUS_LB_TXEN_3        0x08
+
+#define AR531XPLUS_LB_TX_CHAIN_DIS  (AR531XPLUS_LOCAL + 0x0104)
+#define AR531XPLUS_LB_TX_DESC_PTR   (AR531XPLUS_LOCAL + 0x0200)
+
+#define AR531XPLUS_LB_RX_CHAIN_EN   (AR531XPLUS_LOCAL + 0x0400)
+#define AR531XPLUS_LB_RXEN          0x01
+
+#define AR531XPLUS_LB_RX_CHAIN_DIS  (AR531XPLUS_LOCAL + 0x0404)
+#define AR531XPLUS_LB_RX_DESC_PTR   (AR531XPLUS_LOCAL + 0x0408)
+
+#define AR531XPLUS_LB_INT_STATUS    (AR531XPLUS_LOCAL + 0x0500)
+#define AR531XPLUS_INT_TX_DESC      0x0001
+#define AR531XPLUS_INT_TX_OK        0x0002
+#define AR531XPLUS_INT_TX_ERR       0x0004
+#define AR531XPLUS_INT_TX_EOF       0x0008
+#define AR531XPLUS_INT_RX_DESC      0x0010
+#define AR531XPLUS_INT_RX_OK        0x0020
+#define AR531XPLUS_INT_RX_ERR       0x0040
+#define AR531XPLUS_INT_RX_EOF       0x0080
+#define AR531XPLUS_INT_TX_TRUNC     0x0100
+#define AR531XPLUS_INT_TX_STARVE    0x0200
+#define AR531XPLUS_INT_LB_TIMEOUT   0x0400
+#define AR531XPLUS_INT_LB_ERR       0x0800
+#define AR531XPLUS_INT_MBOX_WR      0x1000
+#define AR531XPLUS_INT_MBOX_RD      0x2000
+
+/* Bit definitions for INT MASK are the same as INT_STATUS */
+#define AR531XPLUS_LB_INT_MASK      (AR531XPLUS_LOCAL + 0x0504)
+
+#define AR531XPLUS_LB_INT_EN        (AR531XPLUS_LOCAL + 0x0508)
+#define AR531XPLUS_LB_MBOX          (AR531XPLUS_LOCAL + 0x0600)
+
+
+
+/*
+ * IR Interface Registers
+ */
+#define AR531XPLUS_IR_PKTDATA                   (AR531XPLUS_IR + 0x0000)
+
+#define AR531XPLUS_IR_PKTLEN                    (AR531XPLUS_IR + 0x07fc) /* 0 - 63 */
+
+#define AR531XPLUS_IR_CONTROL                   (AR531XPLUS_IR + 0x0800)
+#define AR531XPLUS_IRCTL_TX                     0x00000000  /* use as tranmitter */
+#define AR531XPLUS_IRCTL_RX                     0x00000001  /* use as receiver   */
+#define AR531XPLUS_IRCTL_SAMPLECLK_MASK         0x00003ffe  /* Sample clk divisor mask */
+#define AR531XPLUS_IRCTL_SAMPLECLK_SHFT                  1
+#define AR531XPLUS_IRCTL_OUTPUTCLK_MASK         0x03ffc000  /* Output clk divisor mask */
+#define AR531XPLUS_IRCTL_OUTPUTCLK_SHFT                 14
+
+#define AR531XPLUS_IR_STATUS                    (AR531XPLUS_IR + 0x0804)
+#define AR531XPLUS_IRSTS_RX                     0x00000001  /* receive in progress */
+#define AR531XPLUS_IRSTS_TX                     0x00000002  /* transmit in progress */
+
+#define AR531XPLUS_IR_CONFIG                    (AR531XPLUS_IR + 0x0808)
+#define AR531XPLUS_IRCFG_INVIN                  0x00000001  /* invert input polarity */
+#define AR531XPLUS_IRCFG_INVOUT                 0x00000002  /* invert output polarity */
+#define AR531XPLUS_IRCFG_SEQ_START_WIN_SEL      0x00000004  /* 1 => 28, 0 => 7 */
+#define AR531XPLUS_IRCFG_SEQ_START_THRESH       0x000000f0  /*  */
+#define AR531XPLUS_IRCFG_SEQ_END_UNIT_SEL       0x00000100  /*  */
+#define AR531XPLUS_IRCFG_SEQ_END_UNIT_THRESH    0x00007e00  /*  */
+#define AR531XPLUS_IRCFG_SEQ_END_WIN_SEL        0x00008000  /*  */
+#define AR531XPLUS_IRCFG_SEQ_END_WIN_THRESH     0x001f0000  /*  */
+#define AR531XPLUS_IRCFG_NUM_BACKOFF_WORDS      0x01e00000  /*  */
+
+/*
+ * PCI memory constants: Memory area 1 and 2 are the same size -
+ * (twice the PCI_TLB_PAGE_SIZE). The definition of
+ * CPU_TO_PCI_MEM_SIZE is coupled with the TLB setup routine
+ * sysLib.c/sysTlbInit(), in that it assumes that 2 pages of size
+ * PCI_TLB_PAGE_SIZE are set up in the TLB for each PCI memory space.
+ */
+ 
+#define CPU_TO_PCI_MEM_BASE1    0xE0000000
+#define CPU_TO_PCI_MEM_SIZE1    (2*PCI_TLB_PAGE_SIZE)
+ 
+
+/* TLB attributes for PCI transactions */
+
+#define PCI_MMU_PAGEMASK        0x00003FFF
+#define MMU_PAGE_UNCACHED       0x00000010
+#define MMU_PAGE_DIRTY          0x00000004
+#define MMU_PAGE_VALID          0x00000002
+#define MMU_PAGE_GLOBAL         0x00000001
+#define PCI_MMU_PAGEATTRIB      (MMU_PAGE_UNCACHED|MMU_PAGE_DIRTY|\
+                                 MMU_PAGE_VALID|MMU_PAGE_GLOBAL)
+#define PCI_MEMORY_SPACE1_VIRT  0xE0000000      /* Used for non-prefet  mem   */
+#define PCI_MEMORY_SPACE1_PHYS  0x80000000
+#define PCI_TLB_PAGE_SIZE       0x01000000
+#define TLB_HI_MASK             0xFFFFE000
+#define TLB_LO_MASK             0x3FFFFFFF
+#define PAGEMASK_SHIFT          11
+#define TLB_LO_SHIFT            6
+
+#define PCI_MAX_LATENCY         0xFFF           /* Max PCI latency            */
+
+#define HOST_PCI_DEV_ID         3
+#define HOST_PCI_MBAR0          0x10000000
+#define HOST_PCI_MBAR1          0x20000000
+#define HOST_PCI_MBAR2          0x30000000
+
+#define HOST_PCI_SDRAM_BASEADDR HOST_PCI_MBAR1
+#define PCI_DEVICE_MEM_SPACE    0x800000
+
+
+typedef unsigned int AR531X_REG;
+
+#define sysRegRead(phys)	\
+	(*(volatile AR531X_REG *)PHYS_TO_K1(phys))
+
+#define sysRegWrite(phys, val)	\
+	((*(volatile AR531X_REG *)PHYS_TO_K1(phys)) = (val))
+
+
+
+/*
+ * This is board-specific data that is stored in a "fixed" location in flash.
+ * It is shared across operating systems, so it should not be changed lightly.
+ * The main reason we need it is in order to extract the ethernet MAC
+ * address(es).
+ */
+struct ar531x_boarddata {
+    u32 magic;                       /* board data is valid */
+#define AR531X_BD_MAGIC 0x35333131   /* "5311", for all 531x platforms */
+    u16 cksum;                       /* checksum (starting with BD_REV 2) */
+    u16 rev;                         /* revision of this struct */
+#define BD_REV  4
+    char   boardName[64];            /* Name of board */
+    u16 major;                       /* Board major number */
+    u16 minor;                       /* Board minor number */
+    u32 config;                      /* Board configuration */
+#define BD_ENET0        0x00000001   /* ENET0 is stuffed */
+#define BD_ENET1        0x00000002   /* ENET1 is stuffed */
+#define BD_UART1        0x00000004   /* UART1 is stuffed */
+#define BD_UART0        0x00000008   /* UART0 is stuffed (dma) */
+#define BD_RSTFACTORY   0x00000010   /* Reset factory defaults stuffed */
+#define BD_SYSLED       0x00000020   /* System LED stuffed */
+#define BD_EXTUARTCLK   0x00000040   /* External UART clock */
+#define BD_CPUFREQ      0x00000080   /* cpu freq is valid in nvram */
+#define BD_SYSFREQ      0x00000100   /* sys freq is set in nvram */
+#define BD_WLAN0        0x00000200   /* Enable WLAN0 */
+#define BD_MEMCAP       0x00000400   /* CAP SDRAM @ memCap for testing */
+#define BD_DISWATCHDOG  0x00000800   /* disable system watchdog */
+#define BD_WLAN1        0x00001000   /* Enable WLAN1 (ar5212) */
+#define BD_ISCASPER     0x00002000   /* FLAG for AR2312 */
+#define BD_WLAN0_2G_EN  0x00004000   /* FLAG for radio0_2G */
+#define BD_WLAN0_5G_EN  0x00008000   /* FLAG for radio0_2G */
+#define BD_WLAN1_2G_EN  0x00020000   /* FLAG for radio0_2G */
+#define BD_WLAN1_5G_EN  0x00040000   /* FLAG for radio0_2G */
+    u16 resetConfigGpio;             /* Reset factory GPIO pin */
+    u16 sysLedGpio;                  /* System LED GPIO pin */
+
+    u32 cpuFreq;                     /* CPU core frequency in Hz */
+    u32 sysFreq;                     /* System frequency in Hz */
+    u32 cntFreq;                     /* Calculated C0_COUNT frequency */
+
+    u8  wlan0Mac[6];
+    u8  enet0Mac[6];
+    u8  enet1Mac[6];
+
+    u16 pciId;                       /* Pseudo PCIID for common code */
+    u16 memCap;                      /* cap bank1 in MB */
+
+    /* version 3 */
+    u8  wlan1Mac[6];                 /* (ar5212) */
+};
+
+#endif
+
+#endif /* AR531X_H */
diff -urN linux-mips-orig/drivers/net/ath/ar531xlnx.h linux-mips-new/drivers/net/ath/ar531xlnx.h
--- linux-mips-orig/drivers/net/ath/ar531xlnx.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ar531xlnx.h	2005-12-31 12:33:57.676538368 +0000
@@ -0,0 +1,137 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * This file contains definitions needed in order to compile
+ * AR531X products for linux.  Definitions that are largely
+ * AR531X-specific and independent of operating system belong
+ * in ar531x.h rather than this file.
+ */
+#ifndef __AR531XLNX_H
+#define __AR531XLNX_H
+#include "ar531x.h"
+
+#define MIPS_CPU_IRQ_BASE		0x00
+#define AR531X_HIGH_PRIO                0x10
+#define AR531X_MISC_IRQ_BASE		0x20
+#define AR531X_GPIO_IRQ_BASE            0x30
+
+/* Software's idea of interrupts handled by "CPU Interrupt Controller" */
+#if CONFIG_AR5315
+#define AR531X_IRQ_NONE		MIPS_CPU_IRQ_BASE+0
+#define AR531X_IRQ_MISC_INTRS	MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
+#define AR531X_IRQ_WLAN0_INTRS	MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
+#define AR531X_IRQ_ENET0_INTRS	MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
+#define AR531X_IRQ_LCBUS_PCI	MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
+#define AR531X_IRQ_WLAN0_POLL	MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
+#define AR531X_IRQ_CPU_CLOCK	MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
+#else
+#define AR531X_IRQ_NONE		MIPS_CPU_IRQ_BASE+0
+#define AR531X_IRQ_WLAN0_INTRS	MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */
+#define AR531X_IRQ_ENET0_INTRS	MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */
+#define AR531X_IRQ_ENET1_INTRS	MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */
+#define AR531X_IRQ_WLAN1_INTRS	MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */
+#define AR531X_IRQ_MISC_INTRS	MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */
+#define AR531X_IRQ_CPU_CLOCK	MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */
+#endif
+
+/* Miscellaneous interrupts, which share IP6 or IP2 */
+#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_COUNT		9
+
+/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
+#define AR531X_GPIO_IRQ_NONE            AR531X_MISC_IRQ_BASE+0
+#define AR531X_GPIO_IRQ(n)              AR531X_MISC_IRQ_BASE+(n)+1
+#define AR531X_GPIO_IRQ_COUNT           9
+
+#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
+#define PHYS_TO_K0(physaddr) KSEG0ADDR(physaddr)
+#define UNMAPPED_TO_PHYS(vaddr)  PHYSADDR(vaddr)
+#define IS_UNMAPPED_VADDR(vaddr) \
+    ((KSEGX(vaddr) == KSEG0) || (KSEGX(vaddr) == KSEG1))
+
+/* IOCTL commands for /proc/ar531x */
+#define AR531X_CTRL_DO_BREAKPOINT       1
+#define AR531X_CTRL_DO_MADWIFI          2
+
+/*
+ * Definitions for operating system portability.
+ * These are vxWorks-->Linux translations.
+ */
+#define LOCAL static
+#define BOOL int
+#define TRUE 1
+#define FALSE 0
+#define UINT8 u8
+#define UINT16 u16
+#define UINT32 u32
+#define PRINTF printk
+#if /* DEBUG */ 1
+#define DEBUG_PRINTF printk
+#define printf printk
+#define INLINE
+#else
+DEBUG_PRINTF while (0) printk
+#define INLINE inline
+#endif
+#define sysUDelay(usecs) udelay(usecs)
+#define sysMsDelay(msecs) mdelay(msecs)
+typedef volatile UINT8 *VIRT_ADDR;
+#define MALLOC(sz) kmalloc(sz, GFP_KERNEL)
+#define MALLOC_NOSLEEP(sz) kmalloc(sz, GFP_ATOMIC)
+#define FREE(ptr) kfree((void *)ptr)
+#define BSP_BUG() do { printk("kernel BSP BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#define BSP_BUG_ON(condition) do { if (unlikely((condition)!=0)) BSP_BUG(); } while(0)
+#define ASSERT(x) BSP_BUG_ON(!(x))
+
+extern struct ar531x_boarddata *ar531x_board_configuration;
+extern char *ar531x_radio_configuration;
+extern char *enet_mac_address_get(int MACUnit);
+
+extern void kgdbInit(void);
+extern int kgdbEnabled(void);
+extern void breakpoint(void);
+extern int kgdbInterrupt(void);
+extern unsigned int ar531x_cpu_frequency(void);
+extern unsigned int ar531x_sys_frequency(void);
+
+/* GPIO support */
+extern struct irqaction spurious_gpio;
+extern unsigned int gpioIntMask;
+extern void ar531x_gpio_intr_init(int irq_base);
+extern void ar531x_gpio_ctrl_output(int gpio);
+extern void ar531x_gpio_ctrl_input(int gpio);
+extern void ar531x_gpio_set(int gpio, int val);
+extern int  ar531x_gpio_get(int gpio);
+extern void ar531x_gpio_intr_enable(unsigned int irq);
+extern void ar531x_gpio_intr_disable(unsigned int irq);
+
+/* Watchdog Timer support */
+extern int watchdog_start(unsigned int milliseconds);
+extern int watchdog_stop(void);
+extern int watchdog_is_enabled(void);
+extern unsigned int watchdog_min_timer_reached(void);
+extern void watchdog_notify_alive(void);
+
+#define A_DATA_CACHE_INVAL(start, length) \
+        dma_cache_inv((UINT32)(start),(length))
+
+#define sysWbFlush() mb()
+
+#define intDisable(x) cli()
+#define intEnable(x) sti()
+
+#endif   /* __AR531XLNX_H */
diff -urN linux-mips-orig/drivers/net/ath/ipPhy.c linux-mips-new/drivers/net/ath/ipPhy.c
--- linux-mips-orig/drivers/net/ath/ipPhy.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ipPhy.c	2005-12-31 12:33:57.677538216 +0000
@@ -0,0 +1,833 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Manage the ICPLUS ethernet PHY.
+ *
+ * All definitions in this file are operating system independent!
+ */
+
+#if defined(linux)
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include "ar531xlnx.h"
+#endif
+
+#include "ae531xmac.h"
+#include "ae531xreg.h"
+#include "ipPhy.h"
+
+/* PHY selections and access functions */
+
+typedef enum {
+    PHY_SRCPORT_INFO, 
+    PHY_PORTINFO_SIZE,
+} PHY_CAP_TYPE;
+
+typedef enum {
+    PHY_SRCPORT_NONE,
+    PHY_SRCPORT_VLANTAG, 
+    PHY_SRCPORT_TRAILER,
+} PHY_SRCPORT_TYPE;
+
+#ifdef DEBUG
+#define DRV_DEBUG 1
+#endif
+#define DRV_DEBUG 1
+
+#if DRV_DEBUG
+#define DRV_DEBUG_PHYERROR  0x00000001
+#define DRV_DEBUG_PHYCHANGE 0x00000002
+#define DRV_DEBUG_PHYSETUP  0x00000004
+
+int ipPhyDebug = DRV_DEBUG_PHYERROR;
+
+#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)    \
+{                                                   \
+    if (ipPhyDebug & (FLG)) {                       \
+        logMsg(X0, X1, X2, X3, X4, X5, X6);         \
+    }                                               \
+}
+
+#define DRV_MSG(x,a,b,c,d,e,f)                      \
+    logMsg(x,a,b,c,d,e,f)
+
+#define DRV_PRINT(FLG, X)                           \
+{                                                   \
+    if (ipPhyDebug & (FLG)) {                       \
+        printf X;                                   \
+    }                                               \
+}
+
+#else /* !DRV_DEBUG */
+#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
+#define DRV_MSG(x,a,b,c,d,e,f)
+#define DRV_PRINT(DBG_SW,X)
+#endif
+
+#define IP_LAN_PORT_VLAN          1
+#define IP_WAN_PORT_VLAN          2
+
+#define ENET_UNIT_DEFAULT 0
+
+/*
+ * Track per-PHY port information.
+ */
+typedef struct {
+    BOOL   isEnetPort;       /* normal enet port */
+    BOOL   isPhyAlive;       /* last known state of link */
+    int    ethUnit;          /* MAC associated with this phy port */
+    UINT32 phyBase;
+    UINT32 phyAddr;          /* PHY registers associated with this phy port */
+    UINT32 VLANTableSetting; /* Value to be written to VLAN table */
+} ipPhyInfo_t;
+
+/*
+ * Per-PHY information, indexed by PHY unit number.
+ */
+ipPhyInfo_t ipPhyInfo[] = {
+    /*
+     * On AP30/AR5312, all PHYs are associated with MAC0.
+     * AP30/AR5312's MAC1 isn't used for anything.
+     * CONFIG_VENETDEV==1 (router) configuration:
+     *    Ports 0,1,2, and 3 are "LAN ports"
+     *    Port 4 is a WAN port
+     *    Port 5 connects to MAC0 in the AR5312
+     * CONFIG_VENETDEV==0 (bridge) configuration:
+     *    Ports 0,1,2,3,4 are "LAN ports"
+     *    Port 5 connects to the MAC0 in the AR5312
+     */
+    {TRUE,   /* phy port 0 -- LAN port 0 */
+     FALSE,
+     ENET_UNIT_DEFAULT,
+     (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
+     IP_PHY0_ADDR,
+     IP_LAN_PORT_VLAN
+    },
+
+    {TRUE,   /* phy port 1 -- LAN port 1 */
+     FALSE,
+     ENET_UNIT_DEFAULT,
+     (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
+     IP_PHY1_ADDR,
+     IP_LAN_PORT_VLAN
+    },
+
+    {TRUE,   /* phy port 2 -- LAN port 2 */
+     FALSE,
+     ENET_UNIT_DEFAULT,
+     (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
+     IP_PHY2_ADDR, 
+     IP_LAN_PORT_VLAN
+    },
+
+    {TRUE,   /* phy port 3 -- LAN port 3 */
+     FALSE,
+     ENET_UNIT_DEFAULT,
+     (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
+     IP_PHY3_ADDR, 
+     IP_LAN_PORT_VLAN
+    },
+
+    {TRUE,   /* phy port 4 -- WAN port or LAN port 4 */
+     FALSE,
+     ENET_UNIT_DEFAULT,
+     (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
+     IP_PHY4_ADDR, 
+     IP_LAN_PORT_VLAN   /* Send to all ports */
+    },
+
+    {FALSE,  /* phy port 5 -- CPU port (no RJ45 connector) */
+     TRUE,
+     ENET_UNIT_DEFAULT,
+     (UINT32) (PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET),
+     0x00, 
+     IP_LAN_PORT_VLAN    /* Send to all ports */
+    },
+};
+
+#define IP_GLOBALREGBASE    ((UINT32) (PHYS_TO_K1(AR531X_ENET0)))
+
+#define IP_PHY_MAX (sizeof(ipPhyInfo) / sizeof(ipPhyInfo[0]))
+
+/* Range of valid PHY IDs is [MIN..MAX] */
+#define IP_ID_MIN 0
+#define IP_ID_MAX (IP_PHY_MAX-1)
+
+/* Convenience macros to access myPhyInfo */
+#define IP_IS_ENET_PORT(phyUnit) (ipPhyInfo[phyUnit].isEnetPort)
+#define IP_IS_PHY_ALIVE(phyUnit) (ipPhyInfo[phyUnit].isPhyAlive)
+#define IP_ETHUNIT(phyUnit) (ipPhyInfo[phyUnit].ethUnit)
+#define IP_PHYBASE(phyUnit) (ipPhyInfo[phyUnit].phyBase)
+#define IP_PHYADDR(phyUnit) (ipPhyInfo[phyUnit].phyAddr)
+#define IP_VLAN_TABLE_SETTING(phyUnit) (ipPhyInfo[phyUnit].VLANTableSetting)
+
+
+#define IP_IS_ETHUNIT(phyUnit, ethUnit) \
+            (IP_IS_ENET_PORT(phyUnit) &&        \
+            IP_ETHUNIT(phyUnit) == (ethUnit))
+
+/* Forward references */
+BOOL       ip_phyIsLinkAlive(int phyUnit);
+LOCAL void ip_VLANInit(int ethUnit);
+LOCAL void ip_verifyReady(int ethUnit);
+#if DEBUG
+void       ip_phyShow(int phyUnit);
+void       ip_phySet(int phyUnit, UINT32 regnum, UINT32 value);
+void       ip_globalSet(UINT32 phyAddr, UINT32 regnum, UINT32 value);
+#endif
+
+/******************************************************************************
+*
+* ip_phyIsLinkAlive - test to see if the specified link is alive
+*
+* RETURNS:
+*    TRUE  --> link is alive
+*    FALSE --> link is down
+*/
+BOOL
+ip_phyIsLinkAlive(int phyUnit)
+{
+    UINT16 phyHwStatus;
+    UINT32 phyBase;
+    UINT32 phyAddr;
+
+    phyBase = IP_PHYBASE(phyUnit);
+    phyAddr = IP_PHYADDR(phyUnit);
+
+    phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
+
+    if (phyHwStatus & IP_STATUS_LINK_PASS) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+/******************************************************************************
+*
+* ip_VLANInit - initialize "port-based VLANs" for the specified enet unit.
+*/
+LOCAL void
+ip_VLANInit(int ethUnit)
+{
+    int     phyUnit;
+    UINT32  phyBase;
+    UINT32  phyReg;
+
+    phyBase = IP_GLOBALREGBASE;
+    
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (IP_ETHUNIT(phyUnit) != ethUnit) {
+            continue;
+        }
+        phyRegWrite(phyBase, IP_GLOBAL_PHY29_ADDR, 
+                    IP_GLOBAL_PHY29_24_REG + ((phyUnit == 5) ? (phyUnit + 1) : phyUnit),
+                                    IP_VLAN_TABLE_SETTING(phyUnit));
+        
+        /* Send all packets to all ports */
+        phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG);
+        phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S);
+        phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg);
+    }
+    phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG);
+    phyReg = phyReg | TAG_VLAN_ENABLE;
+    phyReg = phyReg & ~VID_INDX_SEL_M;
+    phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG, phyReg);
+
+}
+
+
+LOCAL void
+ip_verifyReady(int ethUnit)
+{
+    int     phyUnit;
+    UINT32  phyBase = 0;
+    UINT32  phyAddr;
+    UINT16  phyID1;
+    UINT16  phyID2;
+
+    /*
+     * The first read to the Phy port registers always fails and
+     * returns 0.   So get things started with a bogus read.
+     */
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        phyBase = IP_PHYBASE(phyUnit);
+        phyAddr = IP_PHYADDR(phyUnit);
+    
+        phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1); /* returns 0 */
+        break;
+    }
+
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        /*******************/
+        /* Verify phy port */
+        /*******************/
+        phyBase = IP_PHYBASE(phyUnit);
+        phyAddr = IP_PHYADDR(phyUnit);
+    
+        phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1);
+        if (phyID1 != IP_PHY_ID1_EXPECTATION) {
+            DRV_PRINT(DRV_DEBUG_PHYERROR,
+                      ("Invalid PHY ID1 for enet%d port%d.  Expected 0x%04x, read 0x%04x\n",
+                       ethUnit,
+                       phyUnit,
+                       IP_PHY_ID1_EXPECTATION,
+                       phyID1));
+            return;
+        }
+    
+        phyID2 = phyRegRead(phyBase, phyAddr, IP_PHY_ID2);
+        if ((phyID2 & IP_OUI_LSB_MASK) != IP_OUI_LSB_EXPECTATION) {
+            DRV_PRINT(DRV_DEBUG_PHYERROR,
+                      ("Invalid PHY ID2 for enet%d port %d.  Expected 0x%04x, read 0x%04x\n",
+                       ethUnit,
+                       phyUnit,
+                       IP_OUI_LSB_EXPECTATION,
+                       phyID2));
+            return;
+        }
+    
+        DRV_PRINT(DRV_DEBUG_PHYSETUP,
+                  ("Found PHY enet%d port%d: model 0x%x revision 0x%x\n",
+                   ethUnit,
+                   phyUnit,
+                   (phyID2 & IP_MODEL_NUM_MASK) >> IP_MODEL_NUM_SHIFT,
+                   (phyID2 & IP_REV_NUM_MASK) >> IP_REV_NUM_SHIFT));
+    
+    }
+}
+
+
+/******************************************************************************
+*
+* ip_phySetup - reset and setup the PHY associated with
+* the specified MAC unit number.
+*
+* Resets the associated PHY port.
+*
+* RETURNS:
+*    TRUE  --> associated PHY is alive
+*    FALSE --> no LINKs on this ethernet unit
+*/
+
+BOOL
+ip_phySetup(int ethUnit, UINT32 _phyBase)
+{
+    int     phyUnit;
+    UINT16  phyHwStatus;
+    UINT16  timeout;
+    int     liveLinks = 0;
+    UINT32  phyBase = 0;
+    BOOL    foundPhy = FALSE;
+    UINT32  phyAddr;
+    
+    /* Reset PHYs*/
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        phyBase = IP_PHYBASE(phyUnit);
+        phyAddr = IP_PHYADDR(phyUnit);
+
+        phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,
+                    IP_CTRL_SOFTWARE_RESET);
+    }
+    /*
+     * After the phy is reset, it takes a little while before
+     * it can respond properly.
+     */
+    sysMsDelay(300);
+    /* Verify that the switch is what we think it is, and that it's ready */
+    ip_verifyReady(ethUnit);
+
+    /* See if there's any configuration data for this enet */
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (IP_ETHUNIT(phyUnit) != ethUnit) {
+            continue;
+        }
+
+        phyBase = IP_PHYBASE(phyUnit);
+        foundPhy = TRUE;
+        break;
+    }
+
+    if (!foundPhy) {
+        return FALSE; /* No PHY's configured for this ethUnit */
+    }
+
+#ifdef COBRA_TODO
+    /* Initialize global switch settings */
+
+    /* Initialize the aging time */
+
+    /* Set the learning properties */
+#endif
+
+    /* start auto negogiation on each phy */
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        phyBase = IP_PHYBASE(phyUnit);
+        phyAddr = IP_PHYADDR(phyUnit);
+        
+        phyRegWrite(phyBase, phyAddr, IP_AUTONEG_ADVERT,
+                                        IP_ADVERTISE_ALL);
+        phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,
+                    IP_CTRL_AUTONEGOTIATION_ENABLE | IP_CTRL_START_AUTONEGOTIATION);
+    }
+
+    /*
+     * Wait up to .75 seconds for ALL associated PHYs to finish
+     * autonegotiation.  The only way we get out of here sooner is
+     * if ALL PHYs are connected AND finish autonegotiation.
+     */
+    timeout=5;
+    for (phyUnit=0; (phyUnit < IP_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+        for (;;) {
+            phyBase = IP_PHYBASE(phyUnit);
+            phyAddr = IP_PHYADDR(phyUnit);
+
+            phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
+
+            if (IP_AUTONEG_DONE(phyHwStatus)) {
+                DRV_PRINT(DRV_DEBUG_PHYSETUP,
+                          ("Port %d, Neg Success\n", phyUnit));
+                break;
+            }
+            if (timeout == 0) {
+                DRV_PRINT(DRV_DEBUG_PHYSETUP,
+                          ("Port %d, Negogiation timeout\n", phyUnit));
+                break;
+            }
+            if (--timeout == 0) {
+                DRV_PRINT(DRV_DEBUG_PHYSETUP,
+                          ("Port %d, Negogiation timeout\n", phyUnit));
+                break;
+            }
+
+            sysMsDelay(150);
+        }
+    }
+
+    /*
+     * All PHYs have had adequate time to autonegotiate.
+     * Now initialize software status.
+     *
+     * It's possible that some ports may take a bit longer
+     * to autonegotiate; but we can't wait forever.  They'll
+     * get noticed by mv_phyCheckStatusChange during regular
+     * polling activities.
+     */
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        if (ip_phyIsLinkAlive(phyUnit)) {
+            liveLinks++;
+            IP_IS_PHY_ALIVE(phyUnit) = TRUE;
+        } else {
+            IP_IS_PHY_ALIVE(phyUnit) = FALSE;
+        }
+
+        DRV_PRINT(DRV_DEBUG_PHYSETUP,
+            ("eth%d: Phy Status=%4.4x\n",
+            ethUnit, 
+            phyRegRead(IP_PHYBASE(phyUnit),
+                       IP_PHYADDR(phyUnit),
+                       IP_PHY_STATUS)));
+    }
+#if 0
+    /* XXX Divy. Disable WAN/LAN seggregation. See bug 17866 */
+    ip_VLANInit(ethUnit);
+#endif
+    return (liveLinks > 0);
+}
+
+/******************************************************************************
+*
+* ip_phyIsDuplexFull - Determines whether the phy ports associated with the
+* specified device are FULL or HALF duplex.
+*
+* RETURNS:
+*    1  --> FULL
+*    0 --> HALF
+*/
+int
+ip_phyIsFullDuplex(int ethUnit)
+{
+    int     phyUnit;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+    UINT16  phyHwStatus;
+
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        if (ip_phyIsLinkAlive(phyUnit)) {
+
+            phyBase = IP_PHYBASE(phyUnit);
+            phyAddr = IP_PHYADDR(phyUnit);
+
+            phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY);
+            printk("ipPhy.c: phyHwStatus 0x%x\n",phyHwStatus);
+            if ((phyHwStatus & IP_LINK_100BASETX_FULL_DUPLEX) || 
+                (phyHwStatus & IP_LINK_10BASETX_FULL_DUPLEX)) {
+                return TRUE;
+            }
+        }
+        return -1;
+    }
+
+    return FALSE;
+
+}
+
+
+/******************************************************************************
+*
+* ip_phyIsSpeed100 - Determines the speed of phy ports associated with the
+* specified device.
+*
+* RETURNS:
+*    TRUE --> 100Mbit
+*    FALSE --> 10Mbit
+*/
+
+BOOL
+ip_phyIsSpeed100(int ethUnit)
+{
+    int     phyUnit;
+    UINT16  phyHwStatus;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        if (ip_phyIsLinkAlive(phyUnit)) {
+
+            phyBase = IP_PHYBASE(phyUnit);
+            phyAddr = IP_PHYADDR(phyUnit);
+
+            phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY);
+
+            if (phyHwStatus & IP_LINK_100BASETX) {
+                return TRUE;
+            }
+        }
+    }
+
+    return FALSE;
+}
+
+/*****************************************************************************
+*
+* ip_phyCheckStatusChange -- checks for significant changes in PHY state.
+*
+* A "significant change" is:
+*     dropped link (e.g. ethernet cable unplugged) OR
+*     autonegotiation completed + link (e.g. ethernet cable plugged in)
+*
+* When a PHY is plugged in, phyLinkGained is called.
+* When a PHY is unplugged, phyLinkLost is called.
+*/
+
+void
+ip_phyCheckStatusChange(int ethUnit)
+{
+
+    int           phyUnit;
+    UINT16        phyHwStatus;
+    ipPhyInfo_t   *lastStatus;
+    int           linkCount   = 0;
+    int           lostLinks   = 0;
+    int           gainedLinks = 0;
+    UINT32        phyBase;
+    UINT32        phyAddr;
+
+    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {
+        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        phyBase = IP_PHYBASE(phyUnit);
+        phyAddr = IP_PHYADDR(phyUnit);
+
+        lastStatus = &ipPhyInfo[phyUnit];
+        phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);
+
+        if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
+            /* See if we've lost link */
+            if (phyHwStatus & IP_STATUS_LINK_PASS) {
+                linkCount++;
+            } else {
+                lostLinks++;
+#ifdef COBRA_TODO
+                mv_flushATUDB(phyUnit);
+#endif
+                DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n",
+                                               ethUnit, phyUnit));
+                lastStatus->isPhyAlive = FALSE;
+            }
+        } else { /* last known link status was DEAD */
+            /* Check for AutoNegotiation complete */
+            if (IP_AUTONEG_DONE(phyHwStatus)) {
+                gainedLinks++;
+                linkCount++;
+                DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n",
+                                               ethUnit, phyUnit));
+                lastStatus->isPhyAlive = TRUE;
+            }
+        }
+    }
+
+    if (linkCount == 0) {
+        if (lostLinks) {
+            /* We just lost the last link for this MAC */
+            phyLinkLost(ethUnit);
+        }
+    } else {
+        if (gainedLinks == linkCount) {
+            /* We just gained our first link(s) for this MAC */
+            phyLinkGained(ethUnit);
+        }
+    }
+
+}
+
+#if DEBUG
+
+/* Define the registers of interest for a phyShow command */
+typedef struct ipRegisterTableEntry_s {
+    UINT32 regNum;
+    char  *regIdString;
+} ipRegisterTableEntry_t;
+
+ipRegisterTableEntry_t ipPhyRegisterTable[] = {
+    {IP_PHY_CONTROL,                 "PHY Control                     "},
+    {IP_PHY_STATUS,                  "PHY Status                      "},
+    {IP_PHY_ID1,                     "PHY Identifier 1                "},
+    {IP_PHY_ID2,                     "PHY Identifier 2                "},
+    {IP_AUTONEG_ADVERT,              "Auto-Negotiation Advertisement  "},
+    {IP_LINK_PARTNER_ABILITY,        "Link Partner Ability            "},
+    {IP_AUTONEG_EXPANSION,           "Auto-Negotiation Expansion      "},
+};
+int ipPhyNumRegs = sizeof(ipPhyRegisterTable) / sizeof(ipPhyRegisterTable[0]);
+
+
+ipRegisterTableEntry_t ipPhy29GlobalRegisterTable[] = {
+    {IP_GLOBAL_PHY29_18_REG,        "29_18_REG   "},
+    {IP_GLOBAL_PHY29_19_REG,        "29_19_REG   "},
+    {IP_GLOBAL_PHY29_20_REG,        "29_20_REG   "},
+    {IP_GLOBAL_PHY29_21_REG,        "29_21_REG   "},
+    {IP_GLOBAL_PHY29_22_REG,        "29_22_REG   "},
+    {IP_GLOBAL_PHY29_23_REG,        "29_23_REG   "},
+    {IP_GLOBAL_PHY29_24_REG,        "29_24_REG   "},
+    {IP_GLOBAL_PHY29_25_REG,        "29_25_REG   "},
+    {IP_GLOBAL_PHY29_26_REG,        "29_26_REG   "},
+    {IP_GLOBAL_PHY29_27_REG,        "29_27_REG   "},
+    {IP_GLOBAL_PHY29_28_REG,        "29_28_REG   "},
+    {IP_GLOBAL_PHY29_29_REG,        "29_29_REG   "},
+    {IP_GLOBAL_PHY29_30_REG,        "29_30_REG   "},
+    {IP_GLOBAL_PHY29_31_REG,        "29_31_REG   "},
+};
+int ipPhy29GlobalNumRegs =
+    sizeof(ipPhy29GlobalRegisterTable) / sizeof(ipPhy29GlobalRegisterTable[0]);
+
+
+ipRegisterTableEntry_t ipPhy30GlobalRegisterTable[] = {
+    {IP_GLOBAL_PHY30_0_REG,   "30_0_REG    "},
+    {IP_GLOBAL_PHY30_1_REG,   "30_1_REG    "},
+    {IP_GLOBAL_PHY30_2_REG,   "30_2_REG    "},
+    {IP_GLOBAL_PHY30_3_REG,   "30_3_REG    "},
+    {IP_GLOBAL_PHY30_4_REG,   "30_4_REG    "},
+    {IP_GLOBAL_PHY30_5_REG,   "30_5_REG    "},
+    {IP_GLOBAL_PHY30_6_REG,   "30_6_REG    "},
+    {IP_GLOBAL_PHY30_7_REG,   "30_7_REG    "},
+    {IP_GLOBAL_PHY30_8_REG,   "30_8_REG    "},
+    {IP_GLOBAL_PHY30_9_REG,   "30_9_REG    "},
+    {IP_GLOBAL_PHY30_10_REG,  "30_10_REG   "},
+    {IP_GLOBAL_PHY30_11_REG,  "30_11_REG   "},
+    {IP_GLOBAL_PHY30_12_REG,  "30_12_REG   "},
+    {IP_GLOBAL_PHY30_13_REG,  "30_13_REG   "},
+    {IP_GLOBAL_PHY30_16_REG,  "30_16_REG   "},
+    {IP_GLOBAL_PHY30_17_REG,  "30_17_REG   "},
+    {IP_GLOBAL_PHY30_18_REG,  "30_18_REG   "},
+    {IP_GLOBAL_PHY30_20_REG,  "30_20_REG   "},
+    {IP_GLOBAL_PHY30_21_REG,  "30_21_REG   "},
+    {IP_GLOBAL_PHY30_22_REG,  "30_22_REG   "},
+    {IP_GLOBAL_PHY30_23_REG,  "30_23_REG   "},
+    {IP_GLOBAL_PHY30_24_REG,  "30_24_REG   "},
+    {IP_GLOBAL_PHY30_25_REG,  "30_25_REG   "},
+    {IP_GLOBAL_PHY30_26_REG,  "30_26_REG   "},
+    {IP_GLOBAL_PHY30_27_REG,  "30_27_REG   "},
+    {IP_GLOBAL_PHY30_28_REG,  "30_28_REG   "},
+    {IP_GLOBAL_PHY30_29_REG,  "30_29_REG   "},
+    {IP_GLOBAL_PHY30_30_REG,  "30_30_REG   "},
+    {IP_GLOBAL_PHY30_31_REG,  "30_31_REG   "},
+};
+int ipPhy30GlobalNumRegs =
+    sizeof(ipPhy30GlobalRegisterTable) / sizeof(ipPhy30GlobalRegisterTable[0]);
+
+ipRegisterTableEntry_t ipPhy31GlobalRegisterTable[] = {
+    {IP_GLOBAL_PHY31_0_REG,   "31_0_REG    "},
+    {IP_GLOBAL_PHY31_1_REG,   "31_1_REG    "},
+    {IP_GLOBAL_PHY31_2_REG,   "31_2_REG    "},
+    {IP_GLOBAL_PHY31_3_REG,   "31_3_REG    "},
+    {IP_GLOBAL_PHY31_4_REG,   "31_4_REG    "},
+    {IP_GLOBAL_PHY31_5_REG,   "31_5_REG    "},
+    {IP_GLOBAL_PHY31_6_REG,   "31_6_REG    "},
+};
+
+int ipPhy31GlobalNumRegs =
+    sizeof(ipPhy31GlobalRegisterTable) / sizeof(ipPhy31GlobalRegisterTable[0]);
+
+
+/*****************************************************************************
+*
+* ip_phyShow - Dump the state of a PHY.
+* There are two sets of registers for each phy port:
+*  "phy registers" and
+*  "switch port registers"
+* We dump 'em all, plus the switch global registers.
+*/
+void
+ip_phyShow(int phyUnit)
+{
+    int     i;
+    UINT16  value;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    if (!ip_validPhyId(phyUnit)) {
+        return;
+    }
+
+    phyBase        = IP_PHYBASE(phyUnit);
+    phyAddr        = IP_PHYADDR(phyUnit);
+
+    printf("PHY state for PHY%d (enet%d, phyBase 0x%8x, phyAddr 0x%x)\n",
+           phyUnit,
+           IP_ETHUNIT(phyUnit),
+           IP_PHYBASE(phyUnit),
+           IP_PHYADDR(phyUnit));
+
+    printf("PHY Registers:\n");
+    for (i=0; i < ipPhyNumRegs; i++) {
+
+        value = phyRegRead(phyBase, phyAddr, ipPhyRegisterTable[i].regNum);
+
+        printf("Reg %02d (0x%02x) %s = 0x%08x\n",
+               ipPhyRegisterTable[i].regNum,
+               ipPhyRegisterTable[i].regNum,
+               ipPhyRegisterTable[i].regIdString,
+               value);
+    }
+
+    phyBase = IP_GLOBALREGBASE;
+
+    printf("Switch Global Registers:\n");
+    printf("Phy29 Registers:\n");
+    for (i=0; i < ipPhy29GlobalNumRegs; i++) {
+
+        value = phyRegRead(phyBase, IP_GLOBAL_PHY29_ADDR,
+                           ipPhy29GlobalRegisterTable[i].regNum);
+
+        printf("Reg %02d (0x%02x) %s = 0x%08x\n",
+               ipPhy29GlobalRegisterTable[i].regNum,
+               ipPhy29GlobalRegisterTable[i].regNum,
+               ipPhy29GlobalRegisterTable[i].regIdString,
+               value);
+    }
+
+    printf("Phy30 Registers:\n");
+    for (i=0; i < ipPhy30GlobalNumRegs; i++) {
+
+        value = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR,
+                           ipPhy30GlobalRegisterTable[i].regNum);
+
+        printf("Reg %02d (0x%02x) %s = 0x%08x\n",
+               ipPhy30GlobalRegisterTable[i].regNum,
+               ipPhy30GlobalRegisterTable[i].regNum,
+               ipPhy30GlobalRegisterTable[i].regIdString,
+               value);
+    }
+    printf("Phy31 Registers:\n");
+    for (i=0; i < ipPhy31GlobalNumRegs; i++) {
+
+        value = phyRegRead(phyBase, IP_GLOBAL_PHY31_ADDR,
+                           ipPhy31GlobalRegisterTable[i].regNum);
+
+        printf("Reg %02d (0x%02x) %s = 0x%08x\n",
+               ipPhy31GlobalRegisterTable[i].regNum,
+               ipPhy31GlobalRegisterTable[i].regNum,
+               ipPhy31GlobalRegisterTable[i].regIdString,
+               value);
+    }
+}
+
+/*****************************************************************************
+*
+* ip_phySet - Modify the value of a PHY register (debug only).
+*/
+void
+ip_phySet(int phyUnit, UINT32 regnum, UINT32 value)
+{
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    if (ip_validPhyId(phyUnit)) {
+
+        phyBase = IP_PHYBASE(phyUnit);
+        phyAddr = IP_PHYADDR(phyUnit);
+
+        phyRegWrite(phyBase, phyAddr, regnum, value);
+    }
+}
+
+/*****************************************************************************
+*
+* ip_globalSet - Modify the value of a global register
+* (debug only).
+*/
+void
+ip_globalSet(UINT32 phyAddr, UINT32 regnum, UINT32 value)
+{
+    UINT32  phyBase;
+
+    phyBase = IP_GLOBALREGBASE;
+
+    phyRegWrite(phyBase, phyAddr, regnum, value);
+}
+
+
+#endif
diff -urN linux-mips-orig/drivers/net/ath/ipPhy.h linux-mips-new/drivers/net/ath/ipPhy.h
--- linux-mips-orig/drivers/net/ath/ipPhy.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/ipPhy.h	2005-12-31 12:33:57.678538064 +0000
@@ -0,0 +1,172 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * icPhy.h - definitions for the ethernet PHY.
+ * This code supports a simple 1-port ethernet phy, ICPLUS,
+ * All definitions in this file are operating system independent!
+ */
+
+#ifndef IPPHY_H
+#define IPPHY_H
+
+/*****************/
+/* PHY Registers */
+/*****************/
+#define IP_PHY_CONTROL                 0
+#define IP_PHY_STATUS                  1
+#define IP_PHY_ID1                     2
+#define IP_PHY_ID2                     3
+#define IP_AUTONEG_ADVERT              4
+#define IP_LINK_PARTNER_ABILITY        5
+#define IP_AUTONEG_EXPANSION           6
+
+
+/* IP_PHY_CONTROL fields */
+#define IP_CTRL_SOFTWARE_RESET                    0x8000
+#define IP_CTRL_SPEED_100                         0x2000
+#define IP_CTRL_AUTONEGOTIATION_ENABLE            0x1000
+#define IP_CTRL_START_AUTONEGOTIATION             0x0200
+#define IP_CTRL_SPEED_FULL_DUPLEX                 0x0100
+
+/* Phy status fields */
+#define IP_STATUS_AUTO_NEG_DONE                   0x0020
+#define IP_STATUS_LINK_PASS                       0x0004
+
+#define IP_AUTONEG_DONE(ip_phy_status)                   \
+    (((ip_phy_status) &                                  \
+        (IP_STATUS_AUTO_NEG_DONE)) ==                    \
+        (IP_STATUS_AUTO_NEG_DONE))
+
+/* ICPLUS_PHY_ID1 fields */
+#define IP_PHY_ID1_EXPECTATION                    0x0243 /* OUI >> 6 */
+
+/* ICPLUS_PHY_ID2 fields */
+#define IP_OUI_LSB_MASK                           0xfc00
+#define IP_OUI_LSB_EXPECTATION                    0x0c00
+#define IP_OUI_LSB_SHIFT                              10
+#define IP_MODEL_NUM_MASK                         0x03f0
+#define IP_MODEL_NUM_SHIFT                             4
+#define IP_REV_NUM_MASK                           0x000f
+#define IP_REV_NUM_SHIFT                               0
+
+/* Link Partner ability */
+#define IP_LINK_100BASETX_FULL_DUPLEX       0x0100
+#define IP_LINK_100BASETX                   0x0080
+#define IP_LINK_10BASETX_FULL_DUPLEX        0x0040
+#define IP_LINK_10BASETX                    0x0020
+
+/* Advertisement register. */
+#define IP_ADVERTISE_100FULL                0x0100
+#define IP_ADVERTISE_100HALF                0x0080  
+#define IP_ADVERTISE_10FULL                 0x0040  
+#define IP_ADVERTISE_10HALF                 0x0020  
+
+#define IP_ADVERTISE_ALL (IP_ADVERTISE_10HALF | IP_ADVERTISE_10FULL | \
+                       IP_ADVERTISE_100HALF | IP_ADVERTISE_100FULL)
+               
+               
+#define IP_VLAN_TAG_VALID                   0x81
+#define IP_VLAN_TAG_SIZE                    4
+#define IP_VLAN_TAG_OFFSET                  12   /* After DA & SA */
+#define IP_SPECIAL_TAG_VALID                0x81
+              
+/****************************/
+/* Global Control Registers */
+/****************************/
+/* IP Global register doesn't have names based on functionality
+ * hence has to live with this names  for now */
+#define IP_GLOBAL_PHY29_18_REG  18
+#define IP_GLOBAL_PHY29_19_REG  19
+#define IP_GLOBAL_PHY29_20_REG  20
+#define IP_GLOBAL_PHY29_21_REG  21
+#define IP_GLOBAL_PHY29_22_REG  22
+#define IP_GLOBAL_PHY29_23_REG  23
+#define IP_GLOBAL_PHY29_24_REG  24
+#define IP_GLOBAL_PHY29_25_REG  25
+#define IP_GLOBAL_PHY29_26_REG  26
+#define IP_GLOBAL_PHY29_27_REG  27
+#define IP_GLOBAL_PHY29_28_REG  28
+#define IP_GLOBAL_PHY29_29_REG  29
+#define IP_GLOBAL_PHY29_30_REG  30
+#define IP_GLOBAL_PHY29_31_REG  31
+
+
+#define IP_GLOBAL_PHY30_0_REG   0
+#define IP_GLOBAL_PHY30_1_REG   1
+#define IP_GLOBAL_PHY30_2_REG   2
+#define IP_GLOBAL_PHY30_3_REG   3
+#define IP_GLOBAL_PHY30_4_REG   4
+#define IP_GLOBAL_PHY30_5_REG   5
+#define IP_GLOBAL_PHY30_6_REG   6
+#define IP_GLOBAL_PHY30_7_REG   7
+#define IP_GLOBAL_PHY30_8_REG   8
+#define IP_GLOBAL_PHY30_9_REG   9
+#define IP_GLOBAL_PHY30_10_REG  10
+#define IP_GLOBAL_PHY30_11_REG  11
+#define IP_GLOBAL_PHY30_12_REG  12
+#define IP_GLOBAL_PHY30_13_REG  13
+#define IP_GLOBAL_PHY30_16_REG  16
+#define IP_GLOBAL_PHY30_17_REG  17
+#define IP_GLOBAL_PHY30_18_REG  18
+#define IP_GLOBAL_PHY30_20_REG  20
+#define IP_GLOBAL_PHY30_21_REG  21
+#define IP_GLOBAL_PHY30_22_REG  22
+#define IP_GLOBAL_PHY30_23_REG  23
+#define IP_GLOBAL_PHY30_24_REG  24
+#define IP_GLOBAL_PHY30_25_REG  25
+#define IP_GLOBAL_PHY30_26_REG  26
+#define IP_GLOBAL_PHY30_27_REG  27
+#define IP_GLOBAL_PHY30_28_REG  28
+#define IP_GLOBAL_PHY30_29_REG  29
+#define IP_GLOBAL_PHY30_30_REG  30
+#define IP_GLOBAL_PHY30_31_REG  31
+
+#define IP_GLOBAL_PHY31_0_REG   0
+#define IP_GLOBAL_PHY31_1_REG   1
+#define IP_GLOBAL_PHY31_2_REG   2
+#define IP_GLOBAL_PHY31_3_REG   3
+#define IP_GLOBAL_PHY31_4_REG   4
+#define IP_GLOBAL_PHY31_5_REG   5
+#define IP_GLOBAL_PHY31_6_REG   6
+
+#define IP_GLOBAL_PHY29_31_REG  31
+
+
+#define IP_VLAN0_OUTPUT_PORT_MASK_S     0
+#define IP_VLAN1_OUTPUT_PORT_MASK_S     8
+#define IP_VLAN2_OUTPUT_PORT_MASK_S     0
+#define IP_VLAN3_OUTPUT_PORT_MASK_S     8
+
+/* Masks and shifts for 29.23 register */
+#define IP_PORTX_ADD_TAG_S               11
+#define IP_PORTX_REMOVE_TAG_S            6       
+#define IP_PORT5_ADD_TAG_S               1
+#define IP_PORT5_REMOVE_TAG_S            0
+
+/* 
+ * 30.9   Definitions 
+ */
+#define TAG_VLAN_ENABLE         0x0080
+#define VID_INDX_SEL_M          0x0070            
+#define VID_INDX_SEL_S          4            
+
+                  
+/* PHY Addresses */
+#define IP_PHY0_ADDR    0
+#define IP_PHY1_ADDR    1
+#define IP_PHY2_ADDR    2
+#define IP_PHY3_ADDR    3
+#define IP_PHY4_ADDR    4
+
+#define IP_GLOBAL_PHY29_ADDR    29
+#define IP_GLOBAL_PHY30_ADDR    30
+#define IP_GLOBAL_PHY31_ADDR    31
+
+
+#endif
diff -urN linux-mips-orig/drivers/net/ath/kendSwitchPhy.c linux-mips-new/drivers/net/ath/kendSwitchPhy.c
--- linux-mips-orig/drivers/net/ath/kendSwitchPhy.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/kendSwitchPhy.c	2005-12-31 12:33:57.678538064 +0000
@@ -0,0 +1,286 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright � 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Manage the ethernet PHY.
+ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
+ * and compatible PHYs, such as the Kendin KS8721B.
+ * All definitions in this file are operating system independent!
+ */
+
+#if defined(linux)
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include "ar531xlnx.h"
+#endif
+
+#if defined(__ECOS)
+#include "ae531xecos.h"
+#endif
+
+
+#include "ae531xmac.h"
+#include "ae531xreg.h"
+#include "rtPhy.h"
+
+#define RT_MAX_PORTS 5 /* max addressable ports per MIIM */
+
+#if /* DEBUG */ 1
+#define RT_DEBUG_ERROR     0x00000001
+#define RT_DEBUG_PHYSETUP  0x00000002
+#define RT_DEBUG_PHYCHANGE 0x00000004
+
+/* XXX: must hardcode this since same MIIM for all ethUnits */
+const UINT32 phyBase = 0xb8100000;
+
+int rtPhyDebug = RT_DEBUG_ERROR;
+
+#define RT_PRINT(FLG, X)                            \
+{                                                   \
+    if (rtPhyDebug & (FLG)) {                       \
+        DEBUG_PRINTF X;                             \
+    }                                               \
+}
+#else
+#define RT_PRINT(FLG, X)
+#endif
+
+/*
+ * Track per-PHY state.
+ */
+static BOOL rtPhyAlive[RT_MAX_PORTS];
+
+
+/******************************************************************************
+*
+* rt_phySetup - reset and setup the PHY associated with
+* the specified MAC unit number.
+*
+* Resets the associated PHY port.
+*
+* RETURNS:
+*    TRUE  --> associated PHY is alive
+*    FALSE --> no LINKs on this ethernet unit
+*/
+
+BOOL
+rt_phySetup(int ethUnit, UINT32 phyBaseIgnored)
+{
+    BOOL    linkAlive = FALSE;
+
+    /* Reset phy */
+	if (ethUnit == 0) {
+		int i;
+		for (i=1; i<5; i++) {
+			phyRegWrite(phyBase, i, GEN_ctl, AUTONEGENA);
+			sysMsDelay(200);
+			if (phyRegRead(phyBase, i, GEN_sts) & (AUTOCMPLT | LINK)) {
+				rtPhyAlive[i] = TRUE;
+			}
+			else {
+				rtPhyAlive[i] = FALSE;
+			}
+		}
+	}
+	else {
+		phyRegWrite(phyBase, 5, GEN_ctl, AUTONEGENA);
+		sysMsDelay(200);
+		if (phyRegRead(phyBase, 5, GEN_sts) & (AUTOCMPLT | LINK)) {
+			rtPhyAlive[5] = TRUE;
+		}
+		else {
+			rtPhyAlive[5] = FALSE;
+		}
+	}
+
+    return linkAlive;
+}
+
+/******************************************************************************
+*
+* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
+* specified device are FULL or HALF duplex.
+*
+* RETURNS:
+*    1  --> FULL
+*    0 --> HALF
+*/
+int
+rt_phyIsFullDuplex(int ethUnit)
+{
+	UINT16  phyLpa = 0;
+
+	if (ethUnit == 0) {
+		int i;
+		/* 4 ports connected. If any are half-duplex report half. */
+		for (i=1; i<5; i++) {
+			phyLpa = phyRegRead(phyBase, i, AN_lpa);
+			if ( (!(phyLpa & (LPA_TXFD | LPA_10FD))) && 
+				 (phyLpa & (LPA_TX | LPA_10)) ) {
+				return 0;
+			}
+		}
+		return 1;
+	}
+	else {
+		phyLpa = phyRegRead(phyBase, 5, AN_lpa);
+		if (phyLpa & (LPA_TXFD | LPA_10FD) ) {
+			return 1;
+		}
+		else {
+			return 0;
+		}
+	}
+}
+
+/******************************************************************************
+*
+* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
+* specified device.
+*
+* RETURNS:
+*    TRUE --> 100Mbit
+*    FALSE --> 10Mbit
+*/
+BOOL
+rt_phyIsSpeed100(int ethUnit)
+{
+    UINT16  phyLpa;
+
+	if (ethUnit == 0) {
+		int i;
+		/* 4 ports connected. If any are not 100 report 10. */
+		for (i=1; i<5; i++) {
+			phyLpa = phyRegRead(phyBase, i, AN_lpa);
+			if ( (!(phyLpa & (LPA_TXFD | LPA_TX))) && 
+				 (phyLpa & (LPA_10FD | LPA_10)) ) {
+				printk("10\n");
+				return FALSE;
+			}
+		}
+		printk("100\n");
+		return TRUE;
+	}
+	else {
+		phyLpa = phyRegRead(phyBase, 5, AN_lpa);
+		if (phyLpa & (LPA_TXFD | LPA_TX) ) {
+			printk("100\n");
+			return TRUE;
+		}
+		else {
+			printk("10\n");
+			return FALSE;
+		}
+	}
+}
+
+/*****************************************************************************
+*
+* rt_phyCheckStatusChange -- checks for significant changes in PHY state.
+*
+* A "significant change" is:
+*     dropped link (e.g. ethernet cable unplugged) OR
+*     autonegotiation completed + link (e.g. ethernet cable plugged in)
+*
+* When a PHY is plugged in, phyLinkGained is called.
+* When a PHY is unplugged, phyLinkLost is called.
+*/
+void
+rt_phyCheckStatusChange(int ethUnit)
+{
+    UINT16          phyHwStatus;
+	int i, loopLower, loopUpper;
+	
+	if (ethUnit == 0) {
+		loopLower = 1;
+		loopUpper = 4;
+	}
+	else {
+		loopLower = 5;
+		loopUpper = 5;
+	}
+
+	for (i=loopLower; i<=loopUpper; i++) {
+		phyHwStatus = phyRegRead(phyBase, i, GEN_sts);
+
+		if (rtPhyAlive[i]) { /* last known status was ALIVE */
+			/* See if we've lost link */
+			if (!(phyHwStatus & LINK)) {
+				RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
+				rtPhyAlive[i] = FALSE;
+				phyLinkLost(ethUnit);
+			}
+		} else { /* last known status was DEAD */
+			/* Check for AN complete */
+			if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
+				RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
+				rtPhyAlive[i] = TRUE;
+				phyLinkGained(ethUnit);
+			}
+		}
+	}
+}
+
+#if DEBUG
+
+/* Define the PHY registers of interest for a phyShow command */
+struct rtRegisterTable_s {
+    UINT32 regNum;
+    char  *regIdString;
+} rtRegisterTable[] =
+{
+    {GEN_ctl,    "Basic Mode Control (GEN_ctl)    "},
+    {GEN_sts,    "Basic Mode Status (GEN_sts)     "},
+    {GEN_id_hi,  "PHY Identifier 1 (GET_id_hi)    "},
+    {GEN_id_lo,  "PHY Identifier 2 (GET_id_lo)    "},
+    {AN_adv,     "Auto-Neg Advertisement (AN_adv) "},
+    {AN_lpa,     "Auto-Neg Link Partner Ability   "},
+    {AN_exp,     "Auto-Neg Expansion              "},
+};
+
+int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
+
+/*
+ * Dump the state of a PHY.
+ */
+void
+rt_phyShow(int phyUnit)
+{
+    int i;
+    UINT16  value;
+	int j, loopLower, loopUpper;
+
+    printf("PHY state for ethphy%d\n", phyUnit);
+	
+	if (phyUnit == 0) {
+		loopLower = 1;
+		loopUpper = 4;
+	}
+	else {
+		loopLower = 5;
+		loopUpper = 5;
+	}
+
+	for (j=loopLower; j<=loopUpper; j++) {
+		printk("PHY port %d:\n", j);
+		for (i=0; i<rtNumRegs; i++) {
+			
+			value = phyRegRead(phyBase, j, rtRegisterTable[i].regNum);
+			
+			printf("Reg %02d (0x%02x) %s = 0x%08x\n",
+				   rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
+				   rtRegisterTable[i].regIdString, value);
+		}
+	}
+}
+
+#endif
diff -urN linux-mips-orig/drivers/net/ath/Makefile linux-mips-new/drivers/net/ath/Makefile
--- linux-mips-orig/drivers/net/ath/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/Makefile	2005-12-31 12:33:57.678538064 +0000
@@ -0,0 +1,78 @@
+################################################################################
+#
+# 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
+# for more details.
+#
+# Copyright © 2004 Atheros Communications, Inc.,  All Rights Reserved.
+#
+# Makefile for Atheros ar531x ethernet driver
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+################################################################################
+
+#
+# Makefile for the Atheros ar531x ethernet driver
+#
+
+obj= .
+
+obj-m		 += ae531x.o
+ae531x-objs	 := ae531xlnx.o ae531xmac.o
+export-objs	 := ae531xlnx.o
+list-multi	 := ae531x.o
+
+ifeq ($(CONFIG_KENDIN_ENET_PHY),y)
+  ae531x-objs += rtPhy.o
+endif
+ifeq ($(CONFIG_KENDIN_KS8995XA_ENET_PHY),y)
+  ae531x-objs += kendSwitchPhy.o
+endif
+ifeq ($(CONFIG_MARVELL_ENET_PHY),y)
+  ae531x-objs += mvPhy.o
+endif
+ifeq ($(CONFIG_ICPLUS_ENET_PHY),y)
+  ae531x-objs += ipPhy.o
+endif
+
+#
+# If building directly into kernel
+#
+ifneq ($(MAKING_MODULES),1)
+obj-$(CONFIG_NET_ATHEROS_ETHER) := ae531x.o $(ae531x-objs)
+O_TARGET := ae531x.o
+endif
+
+INCS += -I.
+
+EXTRA_CFLAGS+=$(INCS) ${COPTS} -g
+ifeq ($(DEBUG_BUILD),1)
+EXTRA_CFLAGS+=-DDEBUG
+endif
+
+# release tag versioning
+-include $(KERNELPATH)/ath_version.mk
+
+-include $(TOPDIR)/Rules.make
+STRIP=	${TOOLPREFIX}strip
+
+ifndef MODPATH
+MODPATH = ${KERNELPATH}/arch/mips/ar531x/ROOTDISK/rootdir/lib/modules/${KERNELRELEASE}/
+endif
+
+all:
+	$(MAKE)	-C ${KERNELPATH} SUBDIRS=$(shell pwd) modules
+
+install: all
+	$(STRIP) -S ae531x.o
+	cp ae531x.o ${KERNELPATH}/arch/mips/ar531x/ROOTDISK/rootdir/lib/modules/$(strip $(shell head -n 1 $(KERNELPATH)/Makefile | cut -f 2 -d'=')).$(strip $(shell head -n 2 $(KERNELPATH)/Makefile | tail -1 | cut -f 2 -d'=')).$(strip $(shell head -n 3 $(KERNELPATH)/Makefile | tail -1 | cut -f 2 -d'='))${EXTRAVERSION}/net/.
+
+clean:
+	-rm -f *~ *.o *.ko *.mod.c
+	-rm -f .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
+
+ae531x.o : $(ae531x-objs)
+	$(LD) -o ae531x.o -r $(ae531x-objs)
diff -urN linux-mips-orig/drivers/net/ath/mvPhy.c linux-mips-new/drivers/net/ath/mvPhy.c
--- linux-mips-orig/drivers/net/ath/mvPhy.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/mvPhy.c	2005-12-31 12:33:57.726530768 +0000
@@ -0,0 +1,1230 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+* Manage the ethernet PHY switch, Marvell 88E6060.
+* 
+* This module is intended to be largely OS and platform-independent.
+*/
+
+#if defined(linux)
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include "ar531xlnx.h"
+#endif
+
+#if defined(__ECOS)
+#include "ae531xecos.h"
+#endif
+
+
+#include "ae531xmac.h"
+#include "ae531xreg.h"
+#include "mvPhy.h"
+
+#if /* DEBUG */ 1
+#define MV_DEBUG_ERROR     0x00000001
+#define MV_DEBUG_PHYSETUP  0x00000002
+#define MV_DEBUG_PHYCHANGE 0x00000004
+
+int mvPhyDebug = MV_DEBUG_ERROR;
+
+#define MV_PRINT(FLG, X)                            \
+{                                                   \
+    if (mvPhyDebug & (FLG)) {                       \
+        DEBUG_PRINTF X;                             \
+    }                                               \
+}
+#else
+#define MV_PRINT(FLG, X)
+#endif
+
+#if CONFIG_VENETDEV
+/*
+ * On AR5312 with CONFIG_VENETDEV==1,
+ *   ports 0..3 are LAN ports  (accessed through ae0)
+ *   port 4 is the WAN port.   (accessed through ae1)
+ * 
+ * The phy switch settings in the mvPhyInfo table are set accordingly.
+ */
+#define MV_WAN_PORT          4
+#define MV_IS_LAN_PORT(port) ((port) <  MV_WAN_PORT)
+#define MV_IS_WAN_PORT(port) ((port) == MV_WAN_PORT)
+#endif
+
+/*
+ * Track per-PHY port information.
+ */
+typedef struct {
+    BOOL   isEnetPort;       /* normal enet port */
+    BOOL   isPhyAlive;       /* last known state of link */
+    int    ethUnit;          /* MAC associated with this phy port */
+    UINT32 phyBase;
+    UINT32 phyAddr;          /* PHY registers associated with this phy port */
+    UINT32 switchPortAddr;   /* switch port regs assoc'ed with this phy port */
+    UINT32 VLANTableSetting; /* Value to be written to VLAN table */
+} mvPhyInfo_t;
+
+/******************************************************************************
+ * Per-PHY information, indexed by PHY unit number.
+ *
+ * This table is board-dependent.  It includes information
+ * about which enet MAC controls which PHY port.
+ */
+mvPhyInfo_t mvPhyInfo[] = {
+    /*
+     * On AP30/AR5312, all PHYs are associated with MAC0.
+     * AP30/AR5312's MAC1 isn't used for anything.
+     * CONFIG_VENETDEV==1 (router) configuration:
+     *    Ports 0,1,2, and 3 are "LAN ports"
+     *    Port 4 is a WAN port
+     *    Port 5 connects to MAC0 in the AR5312
+     * CONFIG_VENETDEV==0 (bridge) configuration:
+     *    Ports 0,1,2,3,4 are "LAN ports"
+     *    Port 5 connects to the MAC0 in the AR5312
+     */
+    {isEnetPort: TRUE,   /* phy port 0 -- LAN port 0 */
+     isPhyAlive: FALSE,
+     ethUnit: 0,
+     phyBase: 0,
+     phyAddr: 0x10,
+     switchPortAddr: 0x18,
+#if CONFIG_VENETDEV
+     VLANTableSetting: 0x2e
+#else
+     VLANTableSetting: 0x3e
+#endif
+    },
+
+    {isEnetPort: TRUE,   /* phy port 1 -- LAN port 1 */
+     isPhyAlive: FALSE,
+     ethUnit: 0,
+     phyBase: 0,
+     phyAddr: 0x11,
+     switchPortAddr: 0x19,
+#if CONFIG_VENETDEV
+     VLANTableSetting: 0x2d
+#else
+     VLANTableSetting: 0x3d
+#endif
+    },
+
+    {isEnetPort: TRUE,   /* phy port 2 -- LAN port 2 */
+     isPhyAlive: FALSE,
+     ethUnit: 0,
+     phyBase: 0,
+     phyAddr: 0x12, 
+     switchPortAddr: 0x1a,
+#if CONFIG_VENETDEV
+     VLANTableSetting: 0x2b
+#else
+     VLANTableSetting: 0x3b
+#endif
+    },
+
+    {isEnetPort: TRUE,   /* phy port 3 -- LAN port 3 */
+     isPhyAlive: FALSE,
+     ethUnit: 0,
+     phyBase: 0,
+     phyAddr: 0x13, 
+     switchPortAddr: 0x1b,
+#if CONFIG_VENETDEV
+     VLANTableSetting: 0x27
+#else
+     VLANTableSetting: 0x37
+#endif
+    },
+
+    {isEnetPort: TRUE,   /* phy port 4 -- WAN port or LAN port 4 */
+     isPhyAlive: FALSE,
+     ethUnit: 0,
+     phyBase: 0,
+     phyAddr: 0x14, 
+     switchPortAddr: 0x1c,
+#if CONFIG_VENETDEV
+     VLANTableSetting: 0x1020  /* WAN port */
+#else
+     VLANTableSetting: 0x2f    /* LAN port 4 */
+#endif
+    },
+
+    {isEnetPort: FALSE,  /* phy port 5 -- CPU port (no RJ45 connector) */
+     isPhyAlive: TRUE,
+     ethUnit: 0,
+     phyBase: 0,
+     phyAddr: 0x15, 
+     switchPortAddr: 0x1d,
+#if CONFIG_VENETDEV
+     VLANTableSetting: 0x0f    /* Send only to LAN ports */
+#else
+     VLANTableSetting: 0x1f    /* Send to all ports */
+#endif
+    },
+};
+
+#define MV_PHY_MAX (sizeof(mvPhyInfo) / sizeof(mvPhyInfo[0]))
+
+/* Range of valid PHY IDs is [MIN..MAX] */
+#define MV_ID_MIN 0
+#define MV_ID_MAX (MV_PHY_MAX-1)
+
+/* Convenience macros to access myPhyInfo */
+#define MV_IS_ENET_PORT(phyUnit) (mvPhyInfo[phyUnit].isEnetPort)
+#define MV_IS_PHY_ALIVE(phyUnit) (mvPhyInfo[phyUnit].isPhyAlive)
+#define MV_ETHUNIT(phyUnit) (mvPhyInfo[phyUnit].ethUnit)
+#define MV_PHYBASE(phyUnit) (mvPhyInfo[phyUnit].phyBase)
+#define MV_PHYADDR(phyUnit) (mvPhyInfo[phyUnit].phyAddr)
+#define MV_SWITCH_PORT_ADDR(phyUnit) (mvPhyInfo[phyUnit].switchPortAddr)
+#define MV_VLAN_TABLE_SETTING(phyUnit) (mvPhyInfo[phyUnit].VLANTableSetting)
+
+#define MV_IS_ETHUNIT(phyUnit, ethUnit) \
+    (MV_IS_ENET_PORT(phyUnit) &&        \
+    MV_ETHUNIT(phyUnit) == (ethUnit))
+
+
+/* Forward references */
+BOOL       mv_phyIsLinkAlive(int phyUnit);
+LOCAL void mv_VLANInit(int ethUnit);
+LOCAL void mv_enableConfiguredPorts(int ethUnit);
+LOCAL void mv_verifyReady(int ethUnit);
+BOOL       mv_phySetup(int ethUnit, UINT32 phyBase);
+int        mv_phyIsFullDuplex(int ethUnit);
+BOOL       mv_phyIsSpeed100(int phyUnit);
+LOCAL BOOL mv_validPhyId(int phyUnit);
+void       mv_flushATUDB(int phyUnit);
+void       mv_phyCheckStatusChange(int ethUnit);
+#if DEBUG
+void       mv_phyShow(int phyUnit);
+void       mv_phySet(int phyUnit, UINT32 regnum, UINT32 value);
+void       mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value);
+void       mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value);
+void       mv_showATUDB(int phyUnit);
+void       mv_countGoodFrames(int phyUnit);
+void       mv_countBadFrames(int phyUnit);
+void       mv_showFrameCounts(int phyUnit);
+#endif
+
+
+/******************************************************************************
+*
+* mv_phyIsLinkAlive - test to see if the specified link is alive
+*
+* RETURNS:
+*    TRUE  --> link is alive
+*    FALSE --> link is down
+*/
+BOOL
+mv_phyIsLinkAlive(int phyUnit)
+{
+    UINT16 phyHwStatus;
+    UINT32 phyBase;
+    UINT32 phyAddr;
+
+    phyBase = MV_PHYBASE(phyUnit);
+    phyAddr = MV_PHYADDR(phyUnit);
+
+    phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
+
+    if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+/******************************************************************************
+*
+* mv_VLANInit - initialize "port-based VLANs" for the specified enet unit.
+*/
+LOCAL void
+mv_VLANInit(int ethUnit)
+{
+    int     phyUnit;
+    UINT32  phyBase;
+    UINT32  switchPortAddr;
+
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (MV_ETHUNIT(phyUnit) != ethUnit) {
+            continue;
+        }
+
+        phyBase        = MV_PHYBASE(phyUnit);
+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
+
+        phyRegWrite(phyBase, switchPortAddr, MV_PORT_BASED_VLAN_MAP,
+                    MV_VLAN_TABLE_SETTING(phyUnit));
+    }
+}
+
+#define phyPortConfigured(phyUnit) TRUE /* TBDFREEDOM2 */
+
+/******************************************************************************
+*
+* mv_enableConfiguredPorts - enable whichever PHY ports are supposed
+* to be enabled according to administrative configuration.
+*/
+LOCAL void
+mv_enableConfiguredPorts(int ethUnit)
+{
+    int     phyUnit;
+    UINT32  phyBase;
+    UINT32  switchPortAddr;
+    UINT16  portControl;
+    UINT16  portAssociationVector;
+
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (MV_ETHUNIT(phyUnit) != ethUnit) {
+            continue;
+        }
+
+        phyBase        = MV_PHYBASE(phyUnit);
+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
+
+        if (phyPortConfigured(phyUnit)) {
+
+            portControl = MV_PORT_CONTROL_PORT_STATE_FORWARDING;
+#if CONFIG_VENETDEV
+            if (!MV_IS_ENET_PORT(phyUnit)) {       /* CPU port */
+                portControl |= MV_PORT_CONTROL_INGRESS_TRAILER
+                            | MV_PORT_CONTROL_EGRESS_MODE;
+            }
+#endif
+            phyRegWrite(phyBase, switchPortAddr, MV_PORT_CONTROL, portControl);
+
+            portAssociationVector = 1 << phyUnit;
+
+            phyRegWrite(phyBase, switchPortAddr,
+                MV_PORT_ASSOCIATION_VECTOR, portAssociationVector);
+        }
+    }
+}
+
+/******************************************************************************
+*
+* mv_verifyReady - validates that we're dealing with the device
+* we think we're dealing with, and that it's ready.
+*/
+LOCAL void
+mv_verifyReady(int ethUnit)
+{
+    int     phyUnit;
+    UINT16  globalStatus;
+    UINT32  phyBase = 0;
+    UINT32  phyAddr;
+    UINT32  switchPortAddr;
+    UINT16  phyID1;
+    UINT16  phyID2;
+    UINT16  switchID;
+
+    /*
+     * The first read to the Phy port registers always fails and
+     * returns 0.   So get things started with a bogus read.
+     */
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+        phyBase = MV_PHYBASE(phyUnit);
+        phyAddr = MV_PHYADDR(phyUnit);
+    
+        (void)phyRegRead(phyBase, phyAddr, MV_PHY_ID1); /* returns 0 */
+        break;
+    }
+
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        /*******************/
+        /* Verify phy port */
+        /*******************/
+        phyBase = MV_PHYBASE(phyUnit);
+        phyAddr = MV_PHYADDR(phyUnit);
+    
+        phyID1 = phyRegRead(phyBase, phyAddr, MV_PHY_ID1);
+        if (phyID1 != MV_PHY_ID1_EXPECTATION) {
+            MV_PRINT(MV_DEBUG_PHYSETUP,
+                      ("Invalid PHY ID1 for ethmac%d port%d.  Expected 0x%04x, read 0x%04x\n",
+                       ethUnit,
+                       phyUnit,
+                       MV_PHY_ID1_EXPECTATION,
+                       phyID1));
+            return;
+        }
+    
+        phyID2 = phyRegRead(phyBase, phyAddr, MV_PHY_ID2);
+        if ((phyID2 & MV_OUI_LSB_MASK) != MV_OUI_LSB_EXPECTATION) {
+            MV_PRINT(MV_DEBUG_PHYSETUP,
+                      ("Invalid PHY ID2 for ethmac%d port %d.  Expected 0x%04x, read 0x%04x\n",
+                       ethUnit,
+                       phyUnit,
+                       MV_OUI_LSB_EXPECTATION,
+                       phyID2));
+            return;
+        }
+    
+        MV_PRINT(MV_DEBUG_PHYSETUP,
+                  ("Found PHY ethmac%d port%d: model 0x%x revision 0x%x\n",
+                   ethUnit,
+                   phyUnit,
+                   (phyID2 & MV_MODEL_NUM_MASK) >> MV_MODEL_NUM_SHIFT,
+                   (phyID2 & MV_REV_NUM_MASK) >> MV_REV_NUM_SHIFT));
+    
+    
+        /**********************/
+        /* Verify switch port */
+        /**********************/
+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
+    
+        switchID = phyRegRead(phyBase, switchPortAddr, MV_SWITCH_ID);
+        if ((switchID & MV_SWITCH_ID_DEV_MASK) !=
+            MV_SWITCH_ID_DEV_EXPECTATION) {
+    
+            MV_PRINT(MV_DEBUG_PHYSETUP,
+                      ("Invalid switch ID for ethmac%d port %d.  Expected 0x%04x, read 0x%04x\n",
+                       ethUnit,
+                       phyUnit,
+                       MV_SWITCH_ID_DEV_EXPECTATION,
+                       switchID));
+            return;
+        }
+    
+        MV_PRINT(MV_DEBUG_PHYSETUP,
+                  ("Found PHY switch for enet %d port %d deviceID 0x%x revision 0x%x\n",
+                    ethUnit,
+                    phyUnit,
+                    (switchID & MV_SWITCH_ID_DEV_MASK) >> MV_SWITCH_ID_DEV_SHIFT,
+                    (switchID & MV_SWITCH_ID_REV_MASK) >> MV_SWITCH_ID_REV_SHIFT))
+    }
+    
+    /*******************************/
+    /* Verify that switch is ready */
+    /*******************************/
+    if (phyBase) {
+        globalStatus = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                                  MV_SWITCH_GLOBAL_STATUS);
+
+        if (!(globalStatus & MV_SWITCH_STATUS_READY_MASK)) {
+            MV_PRINT(MV_DEBUG_PHYSETUP,
+                      ("PHY switch for ethmac%d NOT ready!\n",
+                       ethUnit));
+        }
+    } else {
+        MV_PRINT(MV_DEBUG_PHYSETUP,
+                  ("No ports configured for ethmac%d\n", ethUnit));
+    }
+}
+
+/******************************************************************************
+*
+* mv_phySetup - reset and setup the PHY switch.
+*
+* Resets each PHY port.
+*
+* RETURNS:
+*    TRUE  --> at least 1 PHY with LINK
+*    FALSE --> no LINKs on this ethernet unit
+*/
+BOOL
+mv_phySetup(int ethUnit, UINT32 phyBase)
+{
+    int     phyUnit;
+    int     liveLinks = 0;
+    BOOL    foundPhy = FALSE;
+    UINT32  phyAddr;
+    UINT16  atuControl;
+
+    /*
+     * Allow platform-specific code to determine the default Ethernet MAC
+     * at run-time.  If phyEthMacDefault returns a negative value, use the
+     * static mvPhyInfo table "as is".  But if phyEthMacDefault returns a
+     * non-negative value, use it as the default ethernet unit.
+     */
+    {
+        int ethMacDefault = phyEthMacDefault();
+
+        if (ethMacDefault >= 0) {
+            for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+                MV_ETHUNIT(phyUnit)=ethMacDefault;
+            }
+        }
+    }
+
+    /*
+     * See if there's any configuration data for this enet,
+     * and set up phyBase in table.
+     */
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (MV_ETHUNIT(phyUnit) != ethUnit) {
+            continue;
+        }
+
+        MV_PHYBASE(phyUnit) = phyBase;
+        foundPhy = TRUE;
+    }
+
+    if (!foundPhy) {
+        return FALSE; /* No PHY's configured for this ethUnit */
+    }
+
+    /* Verify that the switch is what we think it is, and that it's ready */
+    mv_verifyReady(ethUnit);
+
+    /* Initialize global switch settings */
+    atuControl  = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT;
+    atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT;
+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl);
+
+    /* Reset PHYs and start autonegoation on each. */
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (MV_ETHUNIT(phyUnit) != ethUnit) {
+            continue;
+        }
+
+        phyBase = MV_PHYBASE(phyUnit);
+        phyAddr = MV_PHYADDR(phyUnit);
+
+        phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL,
+                    MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE);
+    }
+
+#if 0 /* Don't wait -- we'll detect shortly after the link comes up */
+{
+    int timeout;
+    UINT16  phyHwStatus;
+
+    /*
+     * Wait 5 seconds for ALL associated PHYs to finish autonegotiation.
+     */
+    timeout=50;
+    for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) {
+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+        for (;;) {
+            phyBase = MV_PHYBASE(phyUnit);
+            phyAddr = MV_PHYADDR(phyUnit);
+
+            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
+
+            if (MV_AUTONEG_DONE(phyHwStatus)) {
+                break;
+            }
+
+            if (--timeout == 0) {
+                break;
+            }
+
+            sysMsDelay(100);
+        }
+    }
+}
+#endif
+
+    /*
+     * All PHYs have had adequate time to autonegotiate.
+     * Now initialize software status.
+     *
+     * It's possible that some ports may take a bit longer
+     * to autonegotiate; but we can't wait forever.  They'll
+     * get noticed by mv_phyCheckStatusChange during regular
+     * polling activities.
+     */
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        if (mv_phyIsLinkAlive(phyUnit)) {
+            liveLinks++;
+            MV_IS_PHY_ALIVE(phyUnit) = TRUE;
+        } else {
+            MV_IS_PHY_ALIVE(phyUnit) = FALSE;
+        }
+
+        MV_PRINT(MV_DEBUG_PHYSETUP,
+            ("ethmac%d: Phy Status=%4.4x\n",
+            ethUnit, 
+            phyRegRead(MV_PHYBASE(phyUnit),
+                       MV_PHYADDR(phyUnit),
+                       MV_PHY_SPECIFIC_STATUS)));
+    }
+
+    mv_VLANInit(ethUnit);
+
+    mv_enableConfiguredPorts(ethUnit);
+
+    return (liveLinks > 0);
+}
+
+
+/******************************************************************************
+*
+* mv_phyIsDuplexFull - Determines whether the phy ports associated with the
+* specified device are FULL or HALF duplex.
+*
+* RETURNS:
+*    1 --> at least one associated PHY in FULL DUPLEX
+*    0 --> all half duplex
+*   -1 --> No links
+*/
+int
+mv_phyIsFullDuplex(int ethUnit)
+{
+    int     phyUnit;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+    UINT16  phyHwStatus;
+    int     oneIsReady=0;
+
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        if (mv_phyIsLinkAlive(phyUnit)) {
+	    oneIsReady = 1;
+
+            phyBase = MV_PHYBASE(phyUnit);
+            phyAddr = MV_PHYADDR(phyUnit);
+
+            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
+
+            if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {
+                return 1;
+            }
+        }
+    }
+    if (oneIsReady)
+	return 0;
+    else
+	return -1;
+}
+
+/******************************************************************************
+*
+* mv_phyIsSpeed100 - Determines the speed of a phy port
+*
+* RETURNS:
+*    TRUE --> PHY operating at 100 Mbit
+*    FALSE --> link down, or not operating at 100 Mbit
+*/
+BOOL
+mv_phyIsSpeed100(int phyUnit)
+{
+    UINT16  phyHwStatus;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    if (MV_IS_ENET_PORT(phyUnit)) {
+        if (mv_phyIsLinkAlive(phyUnit)) {
+
+            phyBase = MV_PHYBASE(phyUnit);
+            phyAddr = MV_PHYADDR(phyUnit);
+
+            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
+
+            if (phyHwStatus & MV_STATUS_RESOLVED_SPEED_100) {
+                return TRUE;
+            }
+        }
+    }
+
+    return FALSE;
+}
+
+#if CONFIG_VENETDEV
+/******************************************************************************
+*
+* mv_phyDetermineSource - Examine a received frame's Egress Trailer
+* to determine whether it came from a LAN or WAN port.
+*
+* RETURNS:
+*    Sets *pFromLAN: 1-->LAN, 0-->WAN
+*    Modifies *pLen to remove PHY trailer from frame
+*/
+void
+mv_phyDetermineSource(char *data, int len, int *pFromLAN)
+{
+    unsigned char *phyTrailer;
+    unsigned char incomingPort;
+
+    phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];
+    ASSERT(phyTrailer[0] == MV_EGRESS_TRAILER_VALID);
+
+    incomingPort = phyTrailer[1];
+    if (MV_IS_LAN_PORT(incomingPort)) {
+        *pFromLAN = 1;
+    } else {
+        ASSERT(MV_IS_WAN_PORT(incomingPort));
+        *pFromLAN = 0;
+    }
+}
+
+
+/******************************************************************************
+*
+* mv_phySetDestinationPort - Set the Ingress Trailer to force the
+* frame to be sent to LAN or WAN, as specified.
+*
+*/
+void
+mv_phySetDestinationPort(char *data, int len, int fromLAN)
+{
+    char *phyTrailer;
+
+    phyTrailer = &data[len];
+    if (fromLAN) {
+        /* LAN ports: Use default settings, as per mvPhyInfo */
+        phyTrailer[0] = 0x00;
+        phyTrailer[1] = 0x00;
+    } else {
+        /* WAN port: Direct to WAN port */
+        phyTrailer[0] = MV_INGRESS_TRAILER_OVERRIDE;
+        phyTrailer[1] = 1 << MV_WAN_PORT;
+    }
+    phyTrailer[2] = 0x00;
+    phyTrailer[3] = 0x00;
+}
+#endif
+
+
+/*****************************************************************************
+*
+* Validate that the specified PHY unit number is a valid PHY ID.
+* Print a message if it is invalid.
+* RETURNS
+*   TRUE  --> valid
+*   FALSE --> invalid
+*/
+LOCAL BOOL
+mv_validPhyId(int phyUnit)
+{
+    if ((phyUnit >= MV_ID_MIN) && (phyUnit <= MV_ID_MAX)) {
+        return TRUE;
+    } else {
+        PRINTF("PHY unit number must be in the range [%d..%d]\n",
+            MV_ID_MIN, MV_ID_MAX);
+        return FALSE;
+    } 
+}
+
+
+/*****************************************************************************
+*
+* mv_waitWhileATUBusy - spins until the ATU completes
+* its previous operation.
+*/
+LOCAL void
+mv_waitWhileATUBusy(UINT32 phyBase)
+{
+    BOOL   isBusy;
+    UINT16 ATUOperation;
+
+    do {
+
+        ATUOperation = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                                  MV_ATU_OPERATION);
+
+        isBusy = (ATUOperation & MV_ATU_BUSY_MASK) == MV_ATU_IS_BUSY;
+
+    } while(isBusy);
+}
+
+/*****************************************************************************
+*
+* mv_flushATUDB - flushes ALL entries in the Address Translation Unit
+* DataBase associated with phyUnit.  [Since we use a single DB for
+* all PHYs, this flushes the entire shared DataBase.]
+*
+* The current implementation flushes even more than absolutely needed --
+* it flushes all entries for all phyUnits on the same ethernet as the
+* specified phyUnit.
+*
+* It is called only when a link failure is detected on a port that was
+* previously working.  In other words, when the cable is unplugged.
+*/
+void
+mv_flushATUDB(int phyUnit)
+{
+    UINT32 phyBase;
+
+    if (!mv_validPhyId(phyUnit)) {
+        PRINTF("Invalid port number: %d\n", phyUnit);
+        return;
+    }
+
+    phyBase = MV_PHYBASE(phyUnit);
+    
+    /* Wait for previous operation (if any) to complete */
+    mv_waitWhileATUBusy(phyBase);
+
+    /* Tell hardware to flush all entries */
+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION, 
+                MV_ATU_OP_FLUSH_ALL | MV_ATU_IS_BUSY);
+
+    mv_waitWhileATUBusy(phyBase);
+}
+ 
+/*****************************************************************************
+*
+* mv_phyCheckStatusChange -- checks for significant changes in PHY state.
+*
+* A "significant change" is:
+*     dropped link (e.g. ethernet cable unplugged) OR
+*     autonegotiation completed + link (e.g. ethernet cable plugged in)
+*/
+void
+mv_phyCheckStatusChange(int ethUnit)
+{
+    int           phyUnit;
+    UINT16        phyHwStatus;
+    mvPhyInfo_t   *lastStatus;
+    int           linkCount   = 0;
+    int           lostLinks   = 0;
+    int           gainedLinks = 0;
+    UINT32        phyBase;
+    UINT32        phyAddr;
+
+    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {
+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        phyBase = MV_PHYBASE(phyUnit);
+        phyAddr = MV_PHYADDR(phyUnit);
+
+        lastStatus = &mvPhyInfo[phyUnit];
+        phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);
+
+        if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
+            /* See if we've lost link */
+            if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {
+                linkCount++;
+            } else {
+                lostLinks++;
+                mv_flushATUDB(phyUnit);
+                MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d down\n",
+                                               ethUnit, phyUnit));
+                lastStatus->isPhyAlive = FALSE;
+            }
+        } else { /* last known link status was DEAD */
+            /* Check for AutoNegotiation complete */
+            if (MV_AUTONEG_DONE(phyHwStatus)) {
+                gainedLinks++;
+		linkCount++;
+                MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d up\n",
+                                               ethUnit, phyUnit));
+                lastStatus->isPhyAlive = TRUE;
+            }
+        }
+    }
+
+    if (linkCount == 0) {
+        if (lostLinks) {
+            /* We just lost the last link for this MAC */
+            phyLinkLost(ethUnit);
+        }
+    } else {
+        if (gainedLinks == linkCount) {
+            /* We just gained our first link(s) for this MAC */
+            phyLinkGained(ethUnit);
+        }
+    }
+}
+
+#if DEBUG
+
+/* Define the registers of interest for a phyShow command */
+typedef struct mvRegisterTableEntry_s {
+    UINT32 regNum;
+    char  *regIdString;
+} mvRegisterTableEntry_t;
+
+mvRegisterTableEntry_t mvPhyRegisterTable[] = {
+    {MV_PHY_CONTROL,                 "PHY Control                     "},
+    {MV_PHY_STATUS,                  "PHY Status                      "},
+    {MV_PHY_ID1,                     "PHY Identifier 1                "},
+    {MV_PHY_ID2,                     "PHY Identifier 2                "},
+    {MV_AUTONEG_ADVERT,              "Auto-Negotiation Advertisement  "},
+    {MV_LINK_PARTNER_ABILITY,        "Link Partner Ability            "},
+    {MV_AUTONEG_EXPANSION,           "Auto-Negotiation Expansion      "},
+    {MV_NEXT_PAGE_TRANSMIT,          "Next Page Transmit              "},
+    {MV_LINK_PARTNER_NEXT_PAGE,      "Link Partner Next Page          "},
+    {MV_PHY_SPECIFIC_CONTROL_1,      "PHY-Specific Control Register 1 "},
+    {MV_PHY_SPECIFIC_STATUS,         "PHY-Specific Status             "},
+    {MV_PHY_INTERRUPT_ENABLE,        "PHY Interrupt Enable            "},
+    {MV_PHY_INTERRUPT_STATUS,        "PHY Interrupt Status            "},
+    {MV_PHY_INTERRUPT_PORT_SUMMARY,  "PHY Interrupt Port Summary      "},
+    {MV_RECEIVE_ERROR_COUNTER,       "Receive Error Counter           "},
+    {MV_LED_PARALLEL_SELECT,         "LED Parallel Select             "},
+    {MV_LED_STREAM_SELECT_LEDS,      "LED Stream Select               "},
+    {MV_PHY_LED_CONTROL,             "PHY LED Control                 "},
+    {MV_PHY_MANUAL_LED_OVERRIDE,     "PHY Manual LED Override         "},
+    {MV_VCT_CONTROL,                 "VCT Control                     "},
+    {MV_VCT_STATUS,                  "VCT Status                      "},
+    {MV_PHY_SPECIFIC_CONTROL_2,      "PHY-Specific Control Register 2 "},
+};
+int mvPhyNumRegs = sizeof(mvPhyRegisterTable) / sizeof(mvPhyRegisterTable[0]);
+
+
+mvRegisterTableEntry_t mvSwitchPortRegisterTable[] = {
+    {MV_PORT_STATUS,              "Port Status             "},
+    {MV_SWITCH_ID,                "Switch ID               "},
+    {MV_PORT_CONTROL,             "Port Control            "},
+    {MV_PORT_BASED_VLAN_MAP,      "Port-Based VLAN Map     "},
+    {MV_PORT_ASSOCIATION_VECTOR,  "Port Association Vector "},
+    {MV_RX_COUNTER,               "RX Counter              "},
+    {MV_TX_COUNTER,               "TX Counter              "},
+};
+int mvSwitchPortNumRegs =
+    sizeof(mvSwitchPortRegisterTable) / sizeof(mvSwitchPortRegisterTable[0]);
+
+
+mvRegisterTableEntry_t mvSwitchGlobalRegisterTable[] = {
+    {MV_SWITCH_GLOBAL_STATUS,  "Switch Global Status  "},
+    {MV_SWITCH_MAC_ADDR0,      "Switch MAC Addr 0 & 1 "},
+    {MV_SWITCH_MAC_ADDR2,      "Switch MAC Addr 2 & 3 "},
+    {MV_SWITCH_MAC_ADDR4,      "Switch MAC Addr 4 & 5 "},
+    {MV_SWITCH_GLOBAL_CONTROL, "Switch Global Control "},
+    {MV_ATU_CONTROL,           "ATU Control           "},
+    {MV_ATU_OPERATION,         "ATU Operation         "},
+    {MV_ATU_DATA,              "ATU Data              "},
+    {MV_ATU_MAC_ADDR0,         "ATU MAC Addr 0 & 1    "},
+    {MV_ATU_MAC_ADDR2,         "ATU MAC Addr 2 & 3    "},
+    {MV_ATU_MAC_ADDR4,         "ATU MAC Addr 4 & 5    "},
+};
+int mvSwitchGlobalNumRegs =
+    sizeof(mvSwitchGlobalRegisterTable) / sizeof(mvSwitchGlobalRegisterTable[0]);
+
+void my_mvPhyShow(int ethUnit)
+{
+    int phyUnit;
+    for (phyUnit=0; (phyUnit < MV_PHY_MAX); phyUnit++) {
+        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+	mv_phyShow(phyUnit);
+    }
+}
+
+/*****************************************************************************
+*
+* mv_phyShow - Dump the state of a PHY.
+* There are two sets of registers for each phy port:
+*  "phy registers" and
+*  "switch port registers"
+* We dump 'em all, plus the switch global registers.
+*/
+void
+mv_phyShow(int phyUnit)
+{
+    int     i;
+    UINT16  value;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+    UINT32  switchPortAddr;
+
+    if (!mv_validPhyId(phyUnit)) {
+        return;
+    }
+
+    phyBase        = MV_PHYBASE(phyUnit);
+    phyAddr        = MV_PHYADDR(phyUnit);
+    switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
+
+    printk("PHY state for PHY%d (ethmac%d, phyBase 0x%8x, phyAddr 0x%x, switchAddr 0x%x)\n",
+           phyUnit,
+           MV_ETHUNIT(phyUnit),
+           MV_PHYBASE(phyUnit),
+           MV_PHYADDR(phyUnit),
+           MV_SWITCH_PORT_ADDR(phyUnit));
+
+    printk("PHY Registers:\n");
+    for (i=0; i < mvPhyNumRegs; i++) {
+
+        value = phyRegRead(phyBase, phyAddr, mvPhyRegisterTable[i].regNum);
+
+        printk("Reg %02d (0x%02x) %s = 0x%08x\n",
+               mvPhyRegisterTable[i].regNum,
+               mvPhyRegisterTable[i].regNum,
+               mvPhyRegisterTable[i].regIdString,
+               value);
+    }
+
+    printk("Switch Port Registers:\n");
+    for (i=0; i < mvSwitchPortNumRegs; i++) {
+
+        value = phyRegRead(phyBase, switchPortAddr,
+                           mvSwitchPortRegisterTable[i].regNum);
+
+        printk("Reg %02d (0x%02x) %s = 0x%08x\n",
+               mvSwitchPortRegisterTable[i].regNum,
+               mvSwitchPortRegisterTable[i].regNum,
+               mvSwitchPortRegisterTable[i].regIdString,
+               value);
+    }
+
+    printk("Switch Global Registers:\n");
+    for (i=0; i < mvSwitchGlobalNumRegs; i++) {
+
+        value = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                           mvSwitchGlobalRegisterTable[i].regNum);
+
+        printk("Reg %02d (0x%02x) %s = 0x%08x\n",
+               mvSwitchGlobalRegisterTable[i].regNum,
+               mvSwitchGlobalRegisterTable[i].regNum,
+               mvSwitchGlobalRegisterTable[i].regIdString,
+               value);
+    }
+}
+
+/*****************************************************************************
+*
+* mv_phySet - Modify the value of a PHY register (debug only).
+*/
+void
+mv_phySet(int phyUnit, UINT32 regnum, UINT32 value)
+{
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    if (mv_validPhyId(phyUnit)) {
+
+        phyBase = MV_PHYBASE(phyUnit);
+        phyAddr = MV_PHYADDR(phyUnit);
+
+        phyRegWrite(phyBase, phyAddr, regnum, value);
+    }
+}
+
+
+/*****************************************************************************
+*
+* mv_switchPortSet - Modify the value of a switch port register (debug only).
+*/
+void
+mv_switchPortSet(int phyUnit, UINT32 regnum, UINT32 value)
+{
+    UINT32  phyBase;
+    UINT32  switchPortAddr;
+
+    if (mv_validPhyId(phyUnit)) {
+
+        phyBase = MV_PHYBASE(phyUnit);
+        switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
+
+        phyRegWrite(phyBase, switchPortAddr, regnum, value);
+    }
+}
+ 
+/*****************************************************************************
+*
+* mv_switchGlobalSet - Modify the value of a switch global register
+* (debug only).
+*/
+void
+mv_switchGlobalSet(int phyUnit, UINT32 regnum, UINT32 value)
+{
+    UINT32  phyBase;
+
+    if (mv_validPhyId(phyUnit)) {
+
+        phyBase = MV_PHYBASE(phyUnit);
+
+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, regnum, value);
+    }
+}
+
+/*****************************************************************************
+*
+* mv_showATUDB - Dump the contents of the Address Translation Unit DataBase
+* for the PHY switch associated with the specified phy.
+*/
+void
+mv_showATUDB(int phyUnit)
+{
+    UINT32 phyBase;
+    UINT16 ATUData;
+    UINT16 ATUMac0;
+    UINT16 ATUMac2;
+    UINT16 ATUMac4;
+    int portVec;
+    int entryState;
+
+    if (!mv_validPhyId(phyUnit)) {
+        printk("Invalid port number: %d\n", phyUnit);
+        return;
+    }
+
+    phyBase = MV_PHYBASE(phyUnit);
+    
+    /* Wait for previous operation (if any) to complete */
+    mv_waitWhileATUBusy(phyBase);
+
+    /* Initialize ATU MAC to all 1's */
+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0, 0xffff);
+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2, 0xffff);
+    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4, 0xffff);
+
+    printk("   MAC ADDRESS    EntryState PortVector\n");
+
+    for(;;) {
+        /* Tell hardware to get next MAC info */
+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION, 
+                    MV_ATU_OP_GET_NEXT | MV_ATU_IS_BUSY);
+
+        mv_waitWhileATUBusy(phyBase);
+
+        ATUData = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_DATA);
+        entryState = (ATUData & MV_ENTRYSTATE_MASK) >> MV_ENTRYSTATE_SHIFT;
+
+        if (entryState == 0) {
+            /* We've hit the end of the list */
+            break;
+        }
+
+        ATUMac0 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR0);
+        ATUMac2 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR2);
+        ATUMac4 = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_MAC_ADDR4);
+
+        portVec    = (ATUData & MV_PORTVEC_MASK) >> MV_PORTVEC_SHIFT;
+
+        printk("%02x:%02x:%02x:%02x:%02x:%02x    0x%02x       0x%02x\n",
+               ATUMac0 >> 8,    /* MAC byte 0 */
+               ATUMac0 & 0xff,  /* MAC byte 1 */
+               ATUMac2 >> 8,    /* MAC byte 2 */
+               ATUMac2 & 0xff,  /* MAC byte 3 */
+               ATUMac4 >> 8,    /* MAC byte 4 */
+               ATUMac4 & 0xff,  /* MAC byte 5 */
+               entryState,
+               portVec);
+    }
+}
+
+LOCAL BOOL countingGoodFrames;
+
+/*****************************************************************************
+*
+* mv_countGoodFrames - starts counting GOOD RX/TX frames per port
+*/
+void
+mv_countGoodFrames(int phyUnit)
+{
+    UINT32 phyBase;
+    UINT16 globalControl;
+
+    if (mv_validPhyId(phyUnit)) {
+        /*
+         * Guarantee that counters are cleared by
+         * forcing CtrMode to toggle and end on GOODFRAMES.
+         */
+
+        phyBase = MV_PHYBASE(phyUnit);
+
+        /* Read current Switch Global Control Register */
+        globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                                   MV_SWITCH_GLOBAL_CONTROL);
+
+        /* Set CtrMode to count BAD frames */
+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
+                         MV_CTRMODE_BADFRAMES);
+
+        /* Push new value out to hardware */
+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);
+
+        /* Now toggle CtrMode to count GOOD frames */
+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
+                         MV_CTRMODE_GOODFRAMES);
+
+        /* Push new value out to hardware */
+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);
+
+        countingGoodFrames = TRUE;
+    }
+}
+
+/*****************************************************************************
+*
+* mv_countBadFrames - starts counting BAD RX/TX frames per port
+*/
+void
+mv_countBadFrames(int phyUnit)
+{
+    UINT32 phyBase;
+    UINT16 globalControl;
+
+    if (mv_validPhyId(phyUnit)) {
+        /*
+         * Guarantee that counters are cleared by
+         * forcing CtrMode to toggle and end on BADFRAMES.
+         */
+
+        phyBase = MV_PHYBASE(phyUnit);
+
+        /* Read current Switch Global Control Register */
+        globalControl = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                                   MV_SWITCH_GLOBAL_CONTROL);
+
+        /* Set CtrMode to count GOOD frames */
+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
+                         MV_CTRMODE_GOODFRAMES);
+
+        /* Push new value out to hardware */
+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);
+
+        /* Now toggle CtrMode to count BAD frames */
+        globalControl = ((globalControl & ~MV_CTRMODE_MASK) |
+                         MV_CTRMODE_BADFRAMES);
+
+        /* Push new value out to hardware */
+        phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR,
+                    MV_SWITCH_GLOBAL_CONTROL, globalControl);
+
+        countingGoodFrames = FALSE;
+    }
+}
+
+/*****************************************************************************
+*
+* mv_showFrameCounts - shows current GOOD/BAD Frame counts
+*/
+void
+mv_showFrameCounts(int phyUnit)
+{
+    UINT16 rxCounter;
+    UINT16 txCounter;
+    UINT32 phyBase;
+    UINT32 switchPortAddr;
+
+    if (!mv_validPhyId(phyUnit)) {
+        return;
+    }
+
+    phyBase = MV_PHYBASE(phyUnit);
+    switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit);
+
+    rxCounter = phyRegRead(phyBase, switchPortAddr, MV_RX_COUNTER);
+
+    txCounter = phyRegRead(phyBase, switchPortAddr, MV_TX_COUNTER);
+
+    printk("port%d %s frames: receive: %05d   transmit: %05d\n",
+           phyUnit,
+           (countingGoodFrames ? "good" : "error"),
+           rxCounter,
+           txCounter);
+}
+#endif
diff -urN linux-mips-orig/drivers/net/ath/mvPhy.h linux-mips-new/drivers/net/ath/mvPhy.h
--- linux-mips-orig/drivers/net/ath/mvPhy.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/mvPhy.h	2005-12-31 12:33:57.727530616 +0000
@@ -0,0 +1,162 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright � 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * mvPhy.h - definitions for the ethernet PHY -- Marvell 88E6060
+ * All definitions in this file are operating system independent!
+ */
+
+#ifndef MVPHY_H
+#define MVPHY_H
+
+/*****************/
+/* PHY Registers */
+/*****************/
+#define MV_PHY_CONTROL                 0
+#define MV_PHY_STATUS                  1
+#define MV_PHY_ID1                     2
+#define MV_PHY_ID2                     3
+#define MV_AUTONEG_ADVERT              4
+#define MV_LINK_PARTNER_ABILITY        5
+#define MV_AUTONEG_EXPANSION           6
+#define MV_NEXT_PAGE_TRANSMIT          7
+#define MV_LINK_PARTNER_NEXT_PAGE      8
+#define MV_PHY_SPECIFIC_CONTROL_1     16
+#define MV_PHY_SPECIFIC_STATUS        17
+#define MV_PHY_INTERRUPT_ENABLE       18
+#define MV_PHY_INTERRUPT_STATUS       19
+#define MV_PHY_INTERRUPT_PORT_SUMMARY 20
+#define MV_RECEIVE_ERROR_COUNTER      21
+#define MV_LED_PARALLEL_SELECT        22
+#define MV_LED_STREAM_SELECT_LEDS     23
+#define MV_PHY_LED_CONTROL            24
+#define MV_PHY_MANUAL_LED_OVERRIDE    25
+
+#define MV_VCT_CONTROL                26
+#define MV_VCT_STATUS                 27
+#define MV_PHY_SPECIFIC_CONTROL_2     28
+
+/* MV_PHY_CONTROL fields */
+#define MV_CTRL_SOFTWARE_RESET                    0x8000
+#define MV_CTRL_AUTONEGOTIATION_ENABLE            0x1000
+#define MV_CTRL_FULL_DUPLEX			  0x0100
+#define MV_CTRL_100_MBPS			  0x2000
+
+/* MV_PHY_ID1 fields */
+#define MV_PHY_ID1_EXPECTATION                    0x0141 /* OUI >> 6 */
+
+/* MV_PHY_ID2 fields */
+#define MV_OUI_LSB_MASK                           0xfc00
+#define MV_OUI_LSB_EXPECTATION                    0x0c00
+#define MV_OUI_LSB_SHIFT                              10
+#define MV_MODEL_NUM_MASK                         0x03f0
+#define MV_MODEL_NUM_SHIFT                             4
+#define MV_REV_NUM_MASK                           0x000f
+#define MV_REV_NUM_SHIFT                               0
+
+/* MV_PHY_SPECIFIC_STATUS fields */
+#define MV_STATUS_RESOLVED_SPEED_100              0x4000
+#define MV_STATUS_RESOLVED_DUPLEX_FULL            0x2000
+#define MV_STATUS_RESOLVED                        0x0800
+#define MV_STATUS_REAL_TIME_LINK_UP               0x0400
+
+/* Check if autonegotiation is complete and link is up */
+#define MV_AUTONEG_DONE(mv_phy_specific_status)                   \
+    (((mv_phy_specific_status) &                                  \
+        (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP)) ==    \
+        (MV_STATUS_RESOLVED | MV_STATUS_REAL_TIME_LINK_UP))
+
+
+/*************************/
+/* Switch Port Registers */
+/*************************/
+#define MV_PORT_STATUS                 0
+#define MV_SWITCH_ID                   3
+#define MV_PORT_CONTROL                4
+#define MV_PORT_BASED_VLAN_MAP         6
+#define MV_PORT_ASSOCIATION_VECTOR    11
+#define MV_RX_COUNTER                 16
+#define MV_TX_COUNTER                 17
+
+/* MV_SWITCH_ID fields */
+#define MV_SWITCH_ID_DEV_MASK                       0xfff0
+#define MV_SWITCH_ID_DEV_EXPECTATION                0x0600
+#define MV_SWITCH_ID_DEV_SHIFT                           4
+#define MV_SWITCH_ID_REV_MASK                       0x000f
+#define MV_SWITCH_ID_REV_SHIFT                           0
+
+/* MV_PORT_CONTROL fields */
+#define MV_PORT_CONTROL_PORT_STATE_MASK             0x0003
+#define MV_PORT_CONTROL_PORT_STATE_DISABLED         0x0000
+#define MV_PORT_CONTROL_PORT_STATE_FORWARDING       0x0003
+
+#define MV_PORT_CONTROL_EGRESS_MODE                 0x0100 /* Receive */
+#define MV_PORT_CONTROL_INGRESS_TRAILER             0x4000 /* Transmit */
+
+#define MV_EGRESS_TRAILER_VALID                       0x80
+#define MV_INGRESS_TRAILER_OVERRIDE                   0x80
+
+#define MV_PHY_TRAILER_SIZE                              4
+
+
+/***************************/
+/* Switch Global Registers */
+/***************************/
+#define MV_SWITCH_GLOBAL_STATUS        0
+#define MV_SWITCH_MAC_ADDR0            1
+#define MV_SWITCH_MAC_ADDR2            2
+#define MV_SWITCH_MAC_ADDR4            3
+#define MV_SWITCH_GLOBAL_CONTROL       4
+#define MV_ATU_CONTROL                10
+#define MV_ATU_OPERATION              11
+#define MV_ATU_DATA                   12
+#define MV_ATU_MAC_ADDR0              13
+#define MV_ATU_MAC_ADDR2              14
+#define MV_ATU_MAC_ADDR4              15
+
+/* MV_SWITCH_GLOBAL_STATUS fields */
+#define MV_SWITCH_STATUS_READY_MASK  0x0800
+
+/* MV_SWITCH_GLOBAL_CONTROL fields */
+#define MV_CTRMODE_MASK              0x0100
+#define MV_CTRMODE_GOODFRAMES        0x0000
+#define MV_CTRMODE_BADFRAMES         0x0100
+
+/* MV_ATU_CONTROL fields */
+#define MV_ATUCTRL_ATU_SIZE_MASK     0x3000
+#define MV_ATUCTRL_ATU_SIZE_SHIFT        12
+#define MV_ATUCTRL_ATU_SIZE_DEFAULT       2 /* 1024 entry database */
+#define MV_ATUCTRL_AGE_TIME_MASK     0x0ff0
+#define MV_ATUCTRL_AGE_TIME_SHIFT         4
+#define MV_ATUCTRL_AGE_TIME_DEFAULT      19 /* 19 * 16 = 304 seconds */
+
+/* MV_ATU_OPERATION fields */
+#define MV_ATU_BUSY_MASK             0x8000
+#define MV_ATU_IS_BUSY               0x8000
+#define MV_ATU_IS_FREE               0x0000
+#define MV_ATU_OP_MASK               0x7000
+#define MV_ATU_OP_FLUSH_ALL          0x1000
+#define MV_ATU_OP_GET_NEXT           0x4000
+
+/* MV_ATU_DATA fields */
+#define MV_ENTRYPRI_MASK             0xc000
+#define MV_ENTRYPRI_SHIFT                14
+#define MV_PORTVEC_MASK              0x03f0
+#define MV_PORTVEC_SHIFT                  4
+#define MV_ENTRYSTATE_MASK           0x000f
+#define MV_ENTRYSTATE_SHIFT               0
+
+/* PHY Address for the switch itself */
+#define MV_SWITCH_GLOBAL_ADDR 0x1f
+
+BOOL    mv_phySetup(int ethUnit, UINT32 phyBase);
+void    mv_phyCheckStatusChange(int ethUnit);
+BOOL    mv_phyIsSpeed100(int ethUnit);
+int     mv_phyIsFullDuplex(int ethUnit);
+
+#endif /* MVPHY_H */
diff -urN linux-mips-orig/drivers/net/ath/rtPhy.c linux-mips-new/drivers/net/ath/rtPhy.c
--- linux-mips-orig/drivers/net/ath/rtPhy.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/rtPhy.c	2005-12-31 12:33:57.727530616 +0000
@@ -0,0 +1,272 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright � 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * Manage the ethernet PHY.
+ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
+ * and compatible PHYs, such as the Kendin KS8721B.
+ * All definitions in this file are operating system independent!
+ */
+
+#if defined(linux)
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include "ar531xlnx.h"
+#endif
+
+#if defined(__ECOS)
+#include "ae531xecos.h"
+#endif
+
+
+#include "ae531xmac.h"
+#include "ae531xreg.h"
+#include "rtPhy.h"
+
+#if /* DEBUG */ 1
+#define RT_DEBUG_ERROR     0x00000001
+#define RT_DEBUG_PHYSETUP  0x00000002
+#define RT_DEBUG_PHYCHANGE 0x00000004
+
+int rtPhyDebug = RT_DEBUG_ERROR;
+
+#define RT_PRINT(FLG, X)                            \
+{                                                   \
+    if (rtPhyDebug & (FLG)) {                       \
+        DEBUG_PRINTF X;                             \
+    }                                               \
+}
+#else
+#define RT_PRINT(FLG, X)
+#endif
+
+/*
+ * Track per-PHY port information.
+ */
+typedef struct {
+    BOOL   phyAlive;    /* last known state of link */
+    UINT32 phyBase;
+    UINT32 phyAddr;
+} rtPhyInfo_t;
+
+#define ETH_PHY_ADDR		1
+
+/*
+ * This table defines the mapping from phy units to
+ * per-PHY information.
+ *
+ * This table is somewhat board-dependent.
+ */
+rtPhyInfo_t rtPhyInfo[] = {
+    {phyAlive: FALSE,  /* PHY 0 */
+     phyBase: 0,       /* filled in by rt_phySetup */
+     phyAddr: ETH_PHY_ADDR},                             
+
+    {phyAlive: FALSE,  /* PHY 1 */
+     phyBase: 0,       /* filled in by rt_phySetup */
+     phyAddr: ETH_PHY_ADDR}
+};
+
+/* Convert from phy unit# to (phyBase, phyAddr) pair */
+#define RT_PHYBASE(phyUnit) (rtPhyInfo[phyUnit].phyBase)
+#define RT_PHYADDR(phyUnit) (rtPhyInfo[phyUnit].phyAddr)
+
+
+/******************************************************************************
+*
+* rt_phySetup - reset and setup the PHY associated with
+* the specified MAC unit number.
+*
+* Resets the associated PHY port.
+*
+* RETURNS:
+*    TRUE  --> associated PHY is alive
+*    FALSE --> no LINKs on this ethernet unit
+*/
+
+BOOL
+rt_phySetup(int ethUnit, UINT32 phyBase)
+{
+    BOOL    linkAlive = FALSE;
+    UINT32  phyAddr;
+
+    RT_PHYBASE(ethUnit) = phyBase;
+
+    phyAddr = RT_PHYADDR(ethUnit);
+
+    /* Reset phy */
+    phyRegWrite(phyBase, phyAddr, GEN_ctl, PHY_SW_RST | AUTONEGENA);
+
+    sysMsDelay(1500);
+
+    return linkAlive;
+}
+
+/******************************************************************************
+*
+* rt_phyIsDuplexFull - Determines whether the phy ports associated with the
+* specified device are FULL or HALF duplex.
+*
+* RETURNS:
+*    1  --> FULL
+*    0 --> HALF
+*/
+int
+rt_phyIsFullDuplex(int ethUnit)
+{
+    UINT16  phyCtl;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    phyBase = RT_PHYBASE(ethUnit);
+    phyAddr = RT_PHYADDR(ethUnit);
+
+    phyCtl = phyRegRead(phyBase, phyAddr, GEN_ctl);
+
+    if (phyCtl & DUPLEX) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+/******************************************************************************
+*
+* rt_phyIsSpeed100 - Determines the speed of phy ports associated with the
+* specified device.
+*
+* RETURNS:
+*    TRUE --> 100Mbit
+*    FALSE --> 10Mbit
+*/
+BOOL
+rt_phyIsSpeed100(int phyUnit)
+{
+    UINT16  phyLpa;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    phyBase = RT_PHYBASE(phyUnit);
+    phyAddr = RT_PHYADDR(phyUnit);
+
+    phyLpa = phyRegRead(phyBase, phyAddr, AN_lpa);
+
+    if (phyLpa & (LPA_TXFD | LPA_TX)) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+/*****************************************************************************
+*
+* rt_phyCheckStatusChange -- checks for significant changes in PHY state.
+*
+* A "significant change" is:
+*     dropped link (e.g. ethernet cable unplugged) OR
+*     autonegotiation completed + link (e.g. ethernet cable plugged in)
+*
+* On AR5311, there is a 1-to-1 mapping of ethernet units to PHYs.
+* When a PHY is plugged in, phyLinkGained is called.
+* When a PHY is unplugged, phyLinkLost is called.
+*/
+void
+rt_phyCheckStatusChange(int ethUnit)
+{
+    UINT16          phyHwStatus;
+    rtPhyInfo_t     *lastStatus = &rtPhyInfo[ethUnit];
+    UINT32          phyBase;
+    UINT32          phyAddr;
+
+    phyBase = RT_PHYBASE(ethUnit);
+    phyAddr = RT_PHYADDR(ethUnit);
+
+    phyHwStatus = phyRegRead(phyBase, phyAddr, GEN_sts);
+
+    if (lastStatus->phyAlive) { /* last known status was ALIVE */
+        /* See if we've lost link */
+        if (!(phyHwStatus & LINK)) {
+            RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link down\n", ethUnit));
+            lastStatus->phyAlive = FALSE;
+            phyLinkLost(ethUnit);
+        }
+    } else { /* last known status was DEAD */
+        /* Check for AN complete */
+        if ((phyHwStatus & (AUTOCMPLT | LINK)) == (AUTOCMPLT | LINK)) {
+            RT_PRINT(RT_DEBUG_PHYCHANGE,("\nethmac%d link up\n", ethUnit));
+            lastStatus->phyAlive = TRUE;
+            phyLinkGained(ethUnit);
+        }
+    }
+}
+
+#if DEBUG
+
+/* Define the PHY registers of interest for a phyShow command */
+struct rtRegisterTable_s {
+    UINT32 regNum;
+    char  *regIdString;
+} rtRegisterTable[] =
+{
+    {GEN_ctl,    "Basic Mode Control (GEN_ctl)    "},
+    {GEN_sts,    "Basic Mode Status (GEN_sts)     "},
+    {GEN_id_hi,  "PHY Identifier 1 (GET_id_hi)    "},
+    {GEN_id_lo,  "PHY Identifier 2 (GET_id_lo)    "},
+    {AN_adv,     "Auto-Neg Advertisement (AN_adv) "},
+    {AN_lpa,     "Auto-Neg Link Partner Ability   "},
+    {AN_exp,     "Auto-Neg Expansion              "},
+};
+
+int rtNumRegs = sizeof(rtRegisterTable) / sizeof(rtRegisterTable[0]);
+
+/*
+ * Dump the state of a PHY.
+ */
+void
+rt_phyShow(int phyUnit)
+{
+    int i;
+    UINT16  value;
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    phyBase = RT_PHYBASE(phyUnit);
+    phyAddr = RT_PHYADDR(phyUnit);
+
+    printf("PHY state for ethphy%d\n", phyUnit);
+
+    for (i=0; i<rtNumRegs; i++) {
+
+        value = phyRegRead(phyBase, phyAddr, rtRegisterTable[i].regNum);
+
+        printf("Reg %02d (0x%02x) %s = 0x%08x\n",
+            rtRegisterTable[i].regNum, rtRegisterTable[i].regNum,
+            rtRegisterTable[i].regIdString, value);
+    }
+}
+
+/*
+ * Modify the value of a PHY register.
+ * This makes it a bit easier to modify PHY values during debug.
+ */
+void
+rt_phySet(int phyUnit, UINT32 regnum, UINT32 value)
+{
+    UINT32  phyBase;
+    UINT32  phyAddr;
+
+    phyBase = RT_PHYBASE(phyUnit);
+    phyAddr = RT_PHYADDR(phyUnit);
+
+    phyRegWrite(phyBase, phyAddr, regnum, value);
+}
+#endif
diff -urN linux-mips-orig/drivers/net/ath/rtPhy.h linux-mips-new/drivers/net/ath/rtPhy.h
--- linux-mips-orig/drivers/net/ath/rtPhy.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-mips-new/drivers/net/ath/rtPhy.h	2005-12-31 12:33:57.727530616 +0000
@@ -0,0 +1,50 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ */
+
+/*
+ * rtPhy.h - definitions for the ethernet PHY.
+ * This code supports a simple 1-port ethernet phy, Realtek RTL8201BL,
+ * and compatible PHYs, such as the Kendin KS8721B.
+ * All definitions in this file are operating system independent!
+ */
+
+#ifndef RTPHY_H
+#define RTPHY_H
+
+/* MII Registers */
+
+#define	GEN_ctl		00
+#define	GEN_sts		01
+#define	GEN_id_hi	02
+#define	GEN_id_lo	03
+#define	AN_adv		04
+#define	AN_lpa		05
+#define	AN_exp		06
+
+/* GEN_ctl */ 
+#define	PHY_SW_RST	0x8000
+#define	LOOPBACK	0x4000
+#define	SPEED		0x2000	/* 100 Mbit/s */
+#define	AUTONEGENA	0x1000
+#define	DUPLEX		0x0100	/* Duplex mode */
+
+		
+/* GEN_sts */
+#define	AUTOCMPLT	0x0020	/* Autonegotiation completed */
+#define	LINK		0x0004	/* Link status */
+
+/* GEN_ids */
+#define RT_PHY_ID1_EXPECTATION  0x22
+
+/* AN_lpa */
+#define	LPA_TXFD	0x0100	/* Link partner supports 100 TX Full Duplex */
+#define	LPA_TX		0x0080	/* Link partner supports 100 TX Half Duplex */
+#define	LPA_10FD	0x0040	/* Link partner supports 10 BT Full Duplex */
+#define	LPA_10		0x0020	/* Link partner supports 10 BT Half Duplex */
+
+#endif /* RTPHY_H */
diff -urN linux-mips/include/linux/raid/md_p.h mips-linux-2.4.25/include/linux/raid/md_p.h
--- linux-mips/include/linux/raid/md_p.h	2005-12-24 15:12:07.189098448 +0000
+++ mips-linux-2.4.25/include/linux/raid/md_p.h	2005-12-30 17:28:10.345721232 +0000
@@ -151,10 +151,12 @@
 	 */
 	mdp_disk_t disks[MD_SB_DISKS];
 
+#if MD_SB_RESERVED_WORDS
 	/*
 	 * Reserved
 	 */
 	__u32 reserved[MD_SB_RESERVED_WORDS];
+#endif
 
 	/*
 	 * Active descriptor