11412 lines
379 KiB
Diff
11412 lines
379 KiB
Diff
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 *)®s->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 *)®s->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 <20> 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 <20> 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 <20> 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
|