
From: Michael Hennerich michael.hennerich@analog.com
A new driver for the AXIS AX88180 gigabit ethernet chip.
Signed-off-by: Michael Hennerich michael.hennerich@analog.com Signed-off-by: Mike Frysinger vapier@gentoo.org --- drivers/net/Makefile | 1 + drivers/net/ax88180.c | 943 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ax88180.h | 348 ++++++++++++++++++ 3 files changed, 1292 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ax88180.c create mode 100644 drivers/net/ax88180.h
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 5b031c9..26d941a 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-y += 3c589.o +COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o COBJS-y += bcm570x.o bcm570x_autoneg.o 5701rls.o COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o COBJS-y += cs8900.o diff --git a/drivers/net/ax88180.c b/drivers/net/ax88180.c new file mode 100644 index 0000000..e6ad5d9 --- /dev/null +++ b/drivers/net/ax88180.c @@ -0,0 +1,943 @@ +/* ax88180: ASIX AX88180 Non-PCI Gigabit Ethernet u-boot driver + * Licensed under the GPL-2. + */ +/* + * ======================================================================== + * ASIX AX88180 Non-PCI 16/32-bit Gigabit Ethernet Linux Driver + * + * The AX88180 Ethernet controller is high performance and highly + * integrated local CPU bus Ethernet controllers with embedded 40K bytes + * SRAM and supports both 16-bit and 32-bit SRAM-Like interfaces + * for any embedded systems. + * The AX88180 is a single chip 10/100/1000Mbps Gigabit Ethernet controller + * that supports both MII and RGMII interfaces and is compliant to + * IEEE 802.3, IEEE 802.3u and IEEE 802.3z standards. + * + * Please visit ASIX's web site (http://www.asix.com.tw) for more details. + * + * Module Name : ax88180.c + * Purpose : This file is the main file. + * Author : Allan Chou allan@asix.com.tw + * Date : 2006-09-06 + * Notes : + * History : + * $Log:$ + * 1.0.0 2006-09-06 + * New release for AX88180 US2 chip. + * + * ======================================================================== + */ + +#include <common.h> +#include <command.h> +#include <net.h> + +#if defined(CONFIG_S3C2440A_SMDK) +#include <s3c2440.h> +#endif + +#include "ax88180.h" + +/* + * =========================================================================== + * <<<<<< Local SubProgram Declaration >>>>>> + * =========================================================================== + */ +static void ax88180_rx_handler(void); +static void ax88180_PHY_initial(void); +static void ax88180_meida_config(void); +static void get_CicadaPHY_meida_mode(void); +static void get_MarvellPHY_meida_mode(void); + +/* + * =========================================================================== + * <<<<<< Declare Macro/Structure Definition >>>>>> + * =========================================================================== + */ + +typedef struct _AX88180_PRIVATE { + unsigned long PhyAddr; + unsigned long PhyID0; + unsigned int MediaMode; + unsigned int RealMediaMode; + unsigned long RxFilterMode; + unsigned long FirstTxDesc; + unsigned long NextTxDesc; + unsigned long rxbuf_overflow_count; +} AX88180_PRIVATE; + +#define mdelay(n) udelay((n)*1000) + +#define PRINTK(flag, args...) if (flag & DEBUG_FLAGS) printf(args) + +/* Access RXBUFFER_START/TXBUFFER_START to read RX buffer/write TX buffer */ + +#ifdef CONFIG_DRIVER_AX88180_16BIT + +#define MACREG_OFFSET_16BIT (- 0xDD00) +#define RXBUF_OFFSET_16BIT (0x2000) +#define TXBUF_OFFSET_16BIT (- 0x7000) + +#if defined(__bfin__) +#include <asm/io.h> +#define READ_RXBUF(data) data = readw(AX88180_BASE + RXBUFFER_START + RXBUF_OFFSET_16BIT) +#define WRITE_TXBUF(data) writew(data, AX88180_BASE + TXBUFFER_START + TXBUF_OFFSET_16BIT) +#define READ_MACREG(regaddr, regdata) regdata = readw(AX88180_BASE + MACREG_OFFSET_16BIT + regaddr) +#define WRITE_MACREG(regaddr, regdata) writew(regdata, AX88180_BASE + MACREG_OFFSET_16BIT + regaddr); +#else /* defined(__bfin__) */ +#define READ_RXBUF(data) data = *(volatile unsigned short *)(AX88180_BASE + RXBUFFER_START) +#define WRITE_TXBUF(data) *(volatile unsigned short *)(AX88180_BASE + TXBUFFER_START) = data +#define READ_MACREG(regaddr, regdata) regdata = *(volatile unsigned short*)(AX88180_BASE + regaddr) +#define WRITE_MACREG(regaddr, regdata) *(volatile unsigned short*)(AX88180_BASE + regaddr) = regdata; +#endif /* defined(__bfin__) */ + +#else /* CONFIG_DRIVER_AX88180_16BIT */ + +#if defined(__bfin__) +#include <asm/io.h> +#define READ_RXBUF(data) data = readl(AX88180_BASE + RXBUFFER_START) +#define WRITE_TXBUF(data) writel(data, AX88180_BASE + TXBUFFER_START) +#define READ_MACREG(regaddr, regdata) regdata = readl(AX88180_BASE + regaddr) +#define WRITE_MACREG(regaddr, regdata) writel(regdata, AX88180_BASE + regaddr); +#else /* defined(__bfin__) */ +#define READ_RXBUF(data) data = *(volatile unsigned long *)(AX88180_BASE + RXBUFFER_START) +#define WRITE_TXBUF(data) *(volatile unsigned long *)(AX88180_BASE + TXBUFFER_START) = data +#define READ_MACREG(regaddr, regdata) regdata = *(volatile unsigned long*)(AX88180_BASE + regaddr) +#define WRITE_MACREG(regaddr, regdata) *(volatile unsigned long*)(AX88180_BASE + regaddr) = regdata; +#endif /* defined(__bfin__) */ + +#endif /* CONFIG_DRIVER_AX88180_16BIT */ + +#define READ_PHYREG(phyaddr, regaddr, regdata) { \ + unsigned long tmpval1, k1; \ + WRITE_MACREG(MDIOCTRL, READ_PHY | (regaddr << 8) | phyaddr); \ + for (k1 = 0; k1 < 10000; k1++) { \ + READ_MACREG(MDIOCTRL, tmpval1); \ + if ((tmpval1 & READ_PHY) == 0) { \ + break; \ + } \ + udelay(1); \ + } \ + READ_MACREG(MDIODP, regdata); \ +} +#define WRITE_PHYREG(phyaddr, regaddr, regdata) { \ + unsigned long tmpval2, k2; \ + WRITE_MACREG(MDIODP, regdata); \ + WRITE_MACREG(MDIOCTRL, WRITE_PHY | (regaddr << 8) | phyaddr); \ + for (k2 = 0; k2 < 10000; k2++) { \ + READ_MACREG(MDIOCTRL, tmpval2); \ + if ((tmpval2 & WRITE_PHY) == 0) { \ + break; \ + } \ + udelay(1); \ + } \ +} + +#define RESET_MAC { \ + unsigned long tmpval3; \ + WRITE_MACREG(MISC, MISC_RESET_MAC); \ + READ_MACREG(MISC, tmpval3); \ + WRITE_MACREG(MISC, MISC_NORMAL); \ + WRITE_MACREG(RXINDICATOR, DEFAULT_RXINDICATOR); \ + WRITE_MACREG(TXCMD, DEFAULT_TXCMD); \ + WRITE_MACREG(TXBS, DEFAULT_TXBS); \ + WRITE_MACREG(TXDES0, DEFAULT_TXDES0); \ + WRITE_MACREG(TXDES1, DEFAULT_TXDES1); \ + WRITE_MACREG(TXDES2, DEFAULT_TXDES2); \ + WRITE_MACREG(TXDES3, DEFAULT_TXDES3); \ + WRITE_MACREG(TXCFG, DEFAULT_TXCFG); \ + WRITE_MACREG(MACCFG2, DEFAULT_MACCFG2); \ + WRITE_MACREG(MACCFG3, DEFAULT_MACCFG3); \ + WRITE_MACREG(TXLEN, DEFAULT_TXLEN); \ + WRITE_MACREG(TXPAUT, DEFAULT_TXPAUT); \ + WRITE_MACREG(RXBTHD0, DEFAULT_RXBTHD0); \ + WRITE_MACREG(RXBTHD1, DEFAULT_RXBTHD1); \ + WRITE_MACREG(RXFULTHD, DEFAULT_RXFULTHD); \ + WRITE_MACREG(DOGTHD0, DEFAULT_DOGTHD0); \ + WRITE_MACREG(DOGTHD1, DEFAULT_DOGTHD1); \ +} +#define RESET_PHY { \ + unsigned long tmpval3a, k3a; \ + WRITE_PHYREG(axlocal.PhyAddr, BMCR, PHY_RESET); \ + for (k3a = 0; k3a < 500; k3a++) { \ + READ_PHYREG(axlocal.PhyAddr, BMCR, tmpval3a); \ + if (!(tmpval3a & PHY_RESET)) \ + break; \ + mdelay(1); \ + } \ +} + +#define INIT_TXRX_VARIABLES { \ + axlocal.FirstTxDesc = TXDP0; \ + axlocal.NextTxDesc = TXDP0; \ + axlocal.rxbuf_overflow_count = 0; \ +} + +#define ENABLE_INTERRUPT WRITE_MACREG(IMR, DEFAULT_IMR) +#define DISABLE_INTERRUPT WRITE_MACREG(IMR, CLEAR_IMR) + +#define START_READ_RXBUFF WRITE_MACREG(RXINDICATOR, RX_START_READ) +#define STOP_READ_RXBUFF WRITE_MACREG(RXINDICATOR, RX_STOP_READ) + +/* Display all AX88180 MAC registers onto console screen */ +#define DISPLAY_ALLMACREG { \ + unsigned long tmpval4; \ + int k4; \ + PRINTK(DEBUG_MSG, "ax88180: AX88180 MAC Registers:\n"); \ + for (k4 = 0xFC00; k4 <= 0xFCFF; k4 += 4) { \ + READ_MACREG(k4, tmpval4); \ + PRINTK(DEBUG_MSG, "0x%04x=0x%08lx ", k4, tmpval4); \ + if ((k4 & 0xF) == 0xC) \ + PRINTK(DEBUG_MSG, "\n"); \ + } \ + PRINTK(DEBUG_MSG, "\n"); \ +} + +/* Display all AX88180 PHY registers onto console screen */ +#define DISPLAY_ALLPHYREG { \ + unsigned long tmpval5; \ + READ_PHYREG(axlocal.PhyAddr, BMCR, tmpval5); \ + PRINTK(DEBUG_MSG, "BMCR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, BMSR, tmpval5); \ + PRINTK(DEBUG_MSG, "BMSR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, PHYIDR0, tmpval5); \ + PRINTK(DEBUG_MSG, "PHYIDR0=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, PHYIDR1, tmpval5); \ + PRINTK(DEBUG_MSG, "PHYIDR1=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, ANAR, tmpval5); \ + PRINTK(DEBUG_MSG, "ANAR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, ANLPAR, tmpval5); \ + PRINTK(DEBUG_MSG, "ANLPAR=0x%04x \n", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, ANER, tmpval5); \ + PRINTK(DEBUG_MSG, "ANER=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, AUX_1000_CTRL, tmpval5); \ + PRINTK(DEBUG_MSG, "1G_CTRL=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, AUX_1000_STATUS, tmpval5); \ + PRINTK(DEBUG_MSG, "1G_STATUS=0x%04x \n", (unsigned int)tmpval5); \ + if (axlocal.PhyID0 == MARVELL_88E1111_PHYIDR0) { \ + READ_PHYREG(axlocal.PhyAddr, M88_SSR, tmpval5); \ + PRINTK(DEBUG_MSG, "M88_SSR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, M88_IER, tmpval5); \ + PRINTK(DEBUG_MSG, "M88_IER=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, M88_ISR, tmpval5); \ + PRINTK(DEBUG_MSG, "M88_ISR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, M88_EXT_SCR, tmpval5); \ + PRINTK(DEBUG_MSG, "M88_EXT_SCR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, M88_EXT_SSR, tmpval5); \ + PRINTK(DEBUG_MSG, "M88_EXT_SSR=0x%04x \n", (unsigned int)tmpval5); \ + } else if (axlocal.PhyID0 == CICADA_CIS8201_PHYIDR0) { \ + READ_PHYREG(axlocal.PhyAddr, CIS_IMR, tmpval5); \ + PRINTK(DEBUG_MSG, "CIS_IMR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, CIS_ISR, tmpval5); \ + PRINTK(DEBUG_MSG, "CIS_ISR=0x%04x ", (unsigned int)tmpval5); \ + READ_PHYREG(axlocal.PhyAddr, CIS_AUX_CTRL_STATUS, tmpval5); \ + PRINTK(DEBUG_MSG, "CIS_AUX=0x%04x \n", (unsigned int)tmpval5); \ + } \ + READ_MACREG(RXCFG, tmpval5); \ + PRINTK(DEBUG_MSG, "RXCFG=0x%08lx ", tmpval5); \ + READ_MACREG(MACCFG0, tmpval5); \ + PRINTK(DEBUG_MSG, "MACCFG0=0x%08lx ", tmpval5); \ + READ_MACREG(MACCFG1, tmpval5); \ + PRINTK(DEBUG_MSG, "MACCFG1=0x%08lx ", tmpval5); \ + READ_MACREG(MACCFG2, tmpval5); \ + PRINTK(DEBUG_MSG, "MACCFG2=0x%08lx \n\n", tmpval5); \ +} + +/* + * =========================================================================== + * <<<<<< Global Variable Definition >>>>>> + * =========================================================================== + */ + +AX88180_PRIVATE axlocal; + +/* + * =========================================================================== + * <<<<<< Local SubProgram Bodies >>>>>> + * =========================================================================== + */ + +/* + ***************************************************************************** + * ax88180_rx_handler() + * + * Handle packets received completion interrupt event. + * + ***************************************************************************** + */ +static void ax88180_rx_handler(void) +{ + unsigned char *rxdata; + unsigned long tmp_data; + unsigned long rx_packet_len; + unsigned int data_size; + unsigned int dword_count, byte_count; + unsigned long rxcurt_ptr, rxbound_ptr, next_ptr; + int i; + int j; + + READ_MACREG(RXCURT, rxcurt_ptr); + READ_MACREG(RXBOUND, rxbound_ptr); + next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK; + + PRINTK(RX_MSG, + "ax88180: RX original RXBOUND=0x%08lx, RXCURT=0x%08lx\n", + rxbound_ptr, rxcurt_ptr); + + while (next_ptr != rxcurt_ptr) { + START_READ_RXBUFF; + READ_RXBUF(rx_packet_len); + if ((rx_packet_len == 0) || (rx_packet_len > MAX_RX_SIZE)) { + STOP_READ_RXBUFF; + RESET_MAC; + PRINTK(ERROR_MSG, + "ax88180: Invalid Rx packet length!! (len=0x%08lx)\n", + rx_packet_len); + PRINTK(ERROR_MSG, + "ax88180: RX RXBOUND=0x%08lx, RXCURT=0x%08lx\n", + rxbound_ptr, rxcurt_ptr); + PRINTK(RX_MSG, + "ax88180: ax88180_rx_handler fail end ..........\n"); + return; + } + data_size = (unsigned int)rx_packet_len; + rxbound_ptr += (((data_size + 0xF) & 0xFFF0) >> 4) + 1; + rxbound_ptr &= RX_PAGE_NUM_MASK; + + rxdata = (unsigned char *)NetRxPackets[0]; + +#ifdef CONFIG_DRIVER_AX88180_16BIT + dword_count = data_size >> 1; + byte_count = data_size & 0x1; +#else + dword_count = data_size >> 2; + byte_count = data_size & 0x3; +#endif + for (i = 0; i < dword_count; i++) { + READ_RXBUF(tmp_data); +#ifdef CONFIG_DRIVER_AX88180_16BIT + *((unsigned short *)rxdata + i) = tmp_data; +#else + *((unsigned long *)rxdata + i) = tmp_data; +#endif + } + if (byte_count != 0) { + READ_RXBUF(tmp_data); + for (j = 0; j < byte_count; j++) { + *(rxdata + (dword_count * 4) + j) = + (unsigned char)(tmp_data >> (j * 8)); + } + } + + STOP_READ_RXBUFF; + + /* Pass the packet up to the protocol layers. */ + NetReceive(NetRxPackets[0], data_size); + + WRITE_MACREG(RXBOUND, rxbound_ptr); + + READ_MACREG(RXCURT, rxcurt_ptr); + READ_MACREG(RXBOUND, rxbound_ptr); + next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK; + + PRINTK(RX_MSG, + "ax88180: RX updated RXBOUND=0x%08lx, RXCURT=0x%08lx\n", + rxbound_ptr, rxcurt_ptr); + } + + if (axlocal.rxbuf_overflow_count > 0) + axlocal.rxbuf_overflow_count--; + + return; +} + +/* + ***************************************************************************** + * ax88180_PHY_initial() + * + * Initialize PHY registers. + * + ***************************************************************************** + */ +static void ax88180_PHY_initial(void) +{ + unsigned long bmcr_val, anar_val, bmsr_val; + unsigned long aux_1000_ctrl; + unsigned long tmp_regval; + unsigned int i; + + /* Check avaliable PHY chipset */ + axlocal.PhyAddr = MARVELL_88E1111_PHYADDR; + READ_PHYREG(axlocal.PhyAddr, PHYIDR0, axlocal.PhyID0); + + if (axlocal.PhyID0 == MARVELL_88E1111_PHYIDR0) { + PRINTK(DRIVER_MSG, + "ax88180: Found Marvell 88E1111 PHY chipset. (PHY Addr=0x%x)\n", + (unsigned int)axlocal.PhyAddr); + READ_PHYREG(axlocal.PhyAddr, M88_EXT_SSR, tmp_regval); + if ((tmp_regval & HWCFG_MODE_MASK) == RGMII_COPPER_MODE) { + WRITE_PHYREG(axlocal.PhyAddr, M88_EXT_SCR, + DEFAULT_EXT_SCR); + RESET_PHY; + WRITE_PHYREG(axlocal.PhyAddr, M88_IER, LINK_CHANGE_INT); + } + } else { + axlocal.PhyAddr = CICADA_CIS8201_PHYADDR; + READ_PHYREG(axlocal.PhyAddr, PHYIDR0, axlocal.PhyID0); + if (axlocal.PhyID0 == CICADA_CIS8201_PHYIDR0) { + PRINTK(DRIVER_MSG, + "ax88180: Found CICADA CIS8201 PHY chipset. (PHY Addr=0x%x)\n", + (unsigned int)axlocal.PhyAddr); + WRITE_PHYREG(axlocal.PhyAddr, CIS_IMR, + (CIS_INT_ENABLE | LINK_CHANGE_INT)); + + /* Set CIS_SMI_PRIORITY bit before force the media mode */ + READ_PHYREG(axlocal.PhyAddr, CIS_AUX_CTRL_STATUS, + tmp_regval); + tmp_regval &= ~CIS_SMI_PRIORITY; + WRITE_PHYREG(axlocal.PhyAddr, CIS_AUX_CTRL_STATUS, + tmp_regval); + } else { + PRINTK(ERROR_MSG, "ax88180: Unknown PHY chipset!!\n"); + } + } + + /* axlocal.ForceMedia = AUTO_MEDIA; */ + aux_1000_ctrl = DEFAULT_AUX_1000_CTRL; + anar_val = + (ANAR_PAUSE | ANAR_100FULL | ANAR_100HALF | ANAR_10FULL | + ANAR_10HALF | ANAR_8023BIT); + + WRITE_PHYREG(axlocal.PhyAddr, AUX_1000_CTRL, aux_1000_ctrl); + WRITE_PHYREG(axlocal.PhyAddr, ANAR, anar_val); + + /* Enable and restart auto-negotiation operation */ + bmcr_val = (AUTONEG_EN | RESTART_AUTONEG); + WRITE_PHYREG(axlocal.PhyAddr, BMCR, bmcr_val); + + /* Waiting 5 secs for PHY link stable */ + PRINTK(DRIVER_MSG, + "ax88180: Waiting for auto-negotiation completion......\n"); + for (i = 0; i < 5000; i++) { + READ_PHYREG(axlocal.PhyAddr, BMSR, bmsr_val); + if (bmsr_val & LINKOK) { + break; + } + mdelay(1); + } + + return; +} + +/* + ***************************************************************************** + * ax88180_meida_config() + * + * Configure MAC registers (RXCFG, MACCFG0, MACCFG1) to match the real PHY media mode. + * + ***************************************************************************** + */ +static void ax88180_meida_config(void) +{ + unsigned long bmcr_val, bmsr_val; + unsigned long rxcfg_val, maccfg0_val, maccfg1_val; + int i; + + /* Waiting 200 msecs for PHY link stable */ + for (i = 0; i < 200; i++) { + READ_PHYREG(axlocal.PhyAddr, BMSR, bmsr_val); + if (bmsr_val & LINKOK) { + break; + } + mdelay(1); + } + + READ_PHYREG(axlocal.PhyAddr, BMSR, bmsr_val); + if (bmsr_val & LINKOK) { + READ_PHYREG(axlocal.PhyAddr, BMCR, bmcr_val); + if (bmcr_val & AUTONEG_EN) { + /* Waiting for Auto-negotiation completion */ + PRINTK(INIT_MSG, + "ax88180: Auto-negotiation is enabled. Waiting for NWay completion.....\n"); + + for (i = 0; i < 5000; i++) { + if (bmsr_val & AUTONEG_COMPLETE) { + break; + } + mdelay(1); + READ_PHYREG(axlocal.PhyAddr, BMSR, bmsr_val); + } + if (i >= 5000) + PRINTK(INIT_MSG, + "ax88180: Auto-negotiation is NOT completed!!\n"); + } else + PRINTK(INIT_MSG, + "ax88180: Auto-negotiation is disabled.\n"); + + PRINTK(DEBUG_MSG, "ax88180: BMCR=0x%04x, BMSR=0x%04x\n", + (unsigned int)bmcr_val, (unsigned int)bmsr_val); + + /* Get real media mode here */ + if (axlocal.PhyID0 == MARVELL_88E1111_PHYIDR0) { + get_MarvellPHY_meida_mode(); + } else if (axlocal.PhyID0 == CICADA_CIS8201_PHYIDR0) { + get_CicadaPHY_meida_mode(); + } else { + axlocal.RealMediaMode = MEDIA_1000FULL; + } + + switch (axlocal.RealMediaMode) { + default: + case MEDIA_1000FULL: + PRINTK(DRIVER_MSG, + "ax88180: Set to 1000Mbps Full-duplex mode.\n"); + rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG; + maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0; + maccfg1_val = + GIGA_MODE_EN | RXFLOW_EN | FULLDUPLEX | + DEFAULT_MACCFG1; + break; + + case MEDIA_1000HALF: + PRINTK(DRIVER_MSG, + "ax88180: Set to 1000Mbps Half-duplex mode.\n"); + rxcfg_val = DEFAULT_RXCFG; + maccfg0_val = DEFAULT_MACCFG0; + maccfg1_val = GIGA_MODE_EN | DEFAULT_MACCFG1; + break; + + case MEDIA_100FULL: + PRINTK(DRIVER_MSG, + "ax88180: Set to 100Mbps Full-duplex mode.\n"); + rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG; + maccfg0_val = + SPEED100 | TXFLOW_ENABLE | DEFAULT_MACCFG0; + maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1; + break; + + case MEDIA_100HALF: + PRINTK(DRIVER_MSG, + "ax88180: Set to 100Mbps Half-duplex mode.\n"); + rxcfg_val = DEFAULT_RXCFG; + maccfg0_val = SPEED100 | DEFAULT_MACCFG0; + maccfg1_val = DEFAULT_MACCFG1; + break; + + case MEDIA_10FULL: + PRINTK(DRIVER_MSG, + "ax88180: Set to 10Mbps Full-duplex mode.\n"); + rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG; + maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0; + maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1; + break; + + case MEDIA_10HALF: + PRINTK(DRIVER_MSG, + "ax88180: Set to 10Mbps Half-duplex mode.\n"); + rxcfg_val = DEFAULT_RXCFG; + maccfg0_val = DEFAULT_MACCFG0; + maccfg1_val = DEFAULT_MACCFG1; + break; + } + } else { + PRINTK(INIT_MSG, "ax88180: The cable is disconnected!!\n"); + /* Set to default media mode (1000FULL) */ + rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG; + maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0; + maccfg1_val = + GIGA_MODE_EN | RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1; + } + + WRITE_MACREG(RXCFG, rxcfg_val); + WRITE_MACREG(MACCFG0, maccfg0_val); + WRITE_MACREG(MACCFG1, maccfg1_val); + + return; +} + +/* + ***************************************************************************** + * get_MarvellPHY_meida_mode() + * + * Get real media mode of Marvell 88E1111 PHY. + * + ***************************************************************************** + */ +static void get_MarvellPHY_meida_mode(void) +{ + unsigned long m88_ssr; + int i; + + /* Get the real media mode */ + for (i = 0; i < 200; i++) { + READ_PHYREG(axlocal.PhyAddr, M88_SSR, m88_ssr); + if (m88_ssr & SSR_MEDIA_RESOLVED_OK) { + break; + } + mdelay(1); + } + + READ_PHYREG(axlocal.PhyAddr, M88_SSR, m88_ssr); + switch (m88_ssr & SSR_MEDIA_MASK) { + default: + case SSR_1000FULL: + axlocal.RealMediaMode = MEDIA_1000FULL; + break; + + case SSR_1000HALF: + axlocal.RealMediaMode = MEDIA_1000HALF; + break; + + case SSR_100FULL: + axlocal.RealMediaMode = MEDIA_100FULL; + break; + + case SSR_100HALF: + axlocal.RealMediaMode = MEDIA_100HALF; + break; + + case SSR_10FULL: + axlocal.RealMediaMode = MEDIA_10FULL; + break; + + case SSR_10HALF: + axlocal.RealMediaMode = MEDIA_10HALF; + break; + } + + PRINTK(INIT_MSG, "ax88180: get_MarvellPHY_meida_mode end ..........\n"); + return; +} + +/* + ***************************************************************************** + * get_CicadaPHY_meida_mode() + * + * Get real media mode of CICADA CIS8201 PHY. + * + ***************************************************************************** + */ +static void get_CicadaPHY_meida_mode(void) +{ + unsigned long tmp_regval; + + READ_PHYREG(axlocal.PhyAddr, CIS_AUX_CTRL_STATUS, tmp_regval); + switch (tmp_regval & CIS_MEDIA_MASK) { + default: + case CIS_1000FULL: + axlocal.RealMediaMode = MEDIA_1000FULL; + break; + + case CIS_1000HALF: + axlocal.RealMediaMode = MEDIA_1000HALF; + break; + + case CIS_100FULL: + axlocal.RealMediaMode = MEDIA_100FULL; + break; + + case CIS_100HALF: + axlocal.RealMediaMode = MEDIA_100HALF; + break; + + case CIS_10FULL: + axlocal.RealMediaMode = MEDIA_10FULL; + break; + + case CIS_10HALF: + axlocal.RealMediaMode = MEDIA_10HALF; + break; + } + + return; +} + +/* + * =========================================================================== + * <<<<<< Exported SubProgram Bodies >>>>>> + * =========================================================================== + */ + +void eth_halt(void) +{ + /* Disable AX88180 TX/RX functions */ + WRITE_MACREG(CMD, WAKEMOD); +} + +void ax88180_get_enetaddr(uchar * addr) +{ + unsigned long macid0_val, macid1_val, macid2_val; + unsigned long tmp_regval; + unsigned char env_enetaddr[6]; + char *tmp = getenv("ethaddr"); + char *end; + int i; + +#if defined(CONFIG_S3C2440A_SMDK) + /* 32-bit mode */ + BWSCON = (BWSCON & ~(0xf << 4)) | (0x02 << 4); + BANKCON1 = BANKCON1_14CLKS; +#endif + + for (i = 0; i < 6; i++) { + env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end + 1 : end; + } + + RESET_MAC; + + /* Disable AX88180 interrupt */ + DISABLE_INTERRUPT; + + /* Disable AX88180 TX/RX functions */ + WRITE_MACREG(CMD, WAKEMOD); + + /* Reload MAC address from EEPROM */ + WRITE_MACREG(PROMCTRL, RELOAD_EEPROM); + for (i = 0; i < 500; i++) { + READ_MACREG(PROMCTRL, tmp_regval); + if ((tmp_regval & RELOAD_EEPROM) == 0) + break; + mdelay(1); + } + + /* Get MAC addresses */ + READ_MACREG(MACID0, macid0_val); + READ_MACREG(MACID1, macid1_val); + READ_MACREG(MACID2, macid2_val); + if ((macid0_val | macid1_val | macid2_val) != 0) { + *addr = (unsigned char)macid0_val; + *(addr + 1) = (unsigned char)(macid0_val >> 8); + *(addr + 2) = (unsigned char)macid1_val; + *(addr + 3) = (unsigned char)(macid1_val >> 8); + *(addr + 4) = (unsigned char)macid2_val; + *(addr + 5) = (unsigned char)(macid2_val >> 8); + } else { + /* No EEPROM here!! Set MAC address from environment. */ + for (i = 0; i < 6; i++) + addr[i] = env_enetaddr[i]; + } + + printf("MAC: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + *addr, *(addr + 1), *(addr + 2), *(addr + 3), *(addr + 4), + *(addr + 5)); + printf("\n"); + +} + +int eth_init(bd_t *bd) +{ + unsigned long tmp_regval; + unsigned long macid0_val, macid1_val, macid2_val; + unsigned short tmp16; +#if defined(CONFIG_S3C2440A_SMDK) + /* 32-bit mode */ + BWSCON = (BWSCON & ~(0xf << 4)) | (0x02 << 4); + BANKCON1 = BANKCON1_14CLKS; +#endif + +#ifdef CONFIG_DRIVER_AX88180_16BIT + WRITE_MACREG(0xDD00, 0); + WRITE_MACREG(0xDD06, 0x10); + WRITE_MACREG(0xDD00, 1); +#endif + memset(&axlocal, 0, sizeof(AX88180_PRIVATE)); + + RESET_MAC; + + /* Disable AX88180 interrupt */ + DISABLE_INTERRUPT; + + /* Disable AX88180 TX/RX functions */ + WRITE_MACREG(CMD, WAKEMOD); + + tmp16 = bd->bi_enetaddr[1]; + macid0_val = (tmp16 << 8) | bd->bi_enetaddr[0]; + + tmp16 = bd->bi_enetaddr[3]; + macid1_val = (tmp16 << 8) | bd->bi_enetaddr[2]; + + tmp16 = bd->bi_enetaddr[5]; + macid2_val = (tmp16 << 8) | bd->bi_enetaddr[4]; + + WRITE_MACREG(MACID0, macid0_val); + WRITE_MACREG(MACID1, macid1_val); + WRITE_MACREG(MACID2, macid2_val); + + /* Initial PHY registers */ + ax88180_PHY_initial(); + + /* Configure MAC media mode registers */ + ax88180_meida_config(); + + WRITE_MACREG(RXFILTER, DEFAULT_RXFILTER); + + /* Initial variables here */ + INIT_TXRX_VARIABLES; + + DISPLAY_ALLMACREG; + + /* Check if there is any invalid interrupt status. If yes, clear it. */ + READ_MACREG(ISR, tmp_regval); + PRINTK(INIT_MSG, "ax88180: The interrupt status = 0x%08lx\n", + tmp_regval); + if (tmp_regval) + WRITE_MACREG(ISR, tmp_regval); + + /* Start AX88180 TX/RX functions */ + WRITE_MACREG(CMD, RXEN | TXEN | WAKEMOD); + + return 0; +} + +/* Get a data block via Ethernet */ +extern int eth_rx(void) +{ + unsigned long ISR_Status; + unsigned long rxcurt_ptr, rxbound_ptr; + unsigned long bmsr_val; + unsigned long tmp_regval; + int i; + + /* Read and check interrupt status here...... */ + READ_MACREG(ISR, ISR_Status); + + while (ISR_Status) { + /* Clear the interrupt status */ + WRITE_MACREG(ISR, ISR_Status); + + PRINTK(INT_MSG, + "\n\rax88180: The interrupt status = 0x%08lx\n\r", + ISR_Status); + + if (ISR_Status & ISR_PHY) { + /* Read ISR register once to clear Marvell PHY interrupt bit */ + READ_PHYREG(axlocal.PhyAddr, M88_ISR, tmp_regval); + + /* Waiting 200 msecs for PHY link stable */ + for (i = 0; i < 200; i++) { + READ_PHYREG(axlocal.PhyAddr, BMSR, bmsr_val); + if (bmsr_val & LINKOK) { + break; + } + mdelay(1); + } + + if (bmsr_val & LINKOK) { + PRINTK(WARNING_MSG, + "ax88180: The cable is connected.\n"); + ax88180_meida_config(); + } else { + PRINTK(WARNING_MSG, + "ax88180: The cable is disconnected.\n"); + } + DISPLAY_ALLPHYREG; + } + + if (ISR_Status & ISR_RXBUFFOVR) { + axlocal.rxbuf_overflow_count++; + READ_MACREG(RXCURT, rxcurt_ptr); + READ_MACREG(RXBOUND, rxbound_ptr); + PRINTK(ERROR_MSG, + "ax88180: RX Buffer overflow!! (count=%d, RXBOUND=0x%08lx, RXCURT=0x%08lx)\n", + (int)axlocal.rxbuf_overflow_count, rxbound_ptr, + rxcurt_ptr); + PRINTK(ERROR_MSG, + "ax88180: The interrupt status = 0x%08lx\n", + ISR_Status); + + if (axlocal.rxbuf_overflow_count > 10) { + RESET_MAC; + INIT_TXRX_VARIABLES; + } + } + + if (ISR_Status & ISR_RX) { + ax88180_rx_handler(); + } + + /* Read and check interrupt status here...... */ + READ_MACREG(ISR, ISR_Status); + } + + return 0; +} + +/* Send a data block via Ethernet. */ +extern int eth_send(volatile void *packet, int length) +{ + volatile unsigned char *txdata; + unsigned long TXDES_addr; + unsigned long txcmd_txdp, txbs_txdp; + /* unsigned long txdes0_val, txdes1_val, txdes2_val, txdes3_val; */ + unsigned long tmp_data; + int i; + + txdata = (volatile unsigned char *)packet; + + axlocal.FirstTxDesc = axlocal.NextTxDesc; + txbs_txdp = 1 << axlocal.FirstTxDesc; + + /* allan9 add to make sure TX machine is OK */ + i = 0; + READ_MACREG(TXBS, tmp_data); + READ_MACREG(TXBS, tmp_data); + PRINTK(TX_MSG, "ax88180: Checking available TXDP (TXBS=0x%08lx)\n", + tmp_data); + while (tmp_data & txbs_txdp) { + axlocal.NextTxDesc++; + axlocal.NextTxDesc &= TXDP_MASK; + axlocal.FirstTxDesc = axlocal.NextTxDesc; + txbs_txdp = 1 << axlocal.FirstTxDesc; + READ_MACREG(TXBS, tmp_data); + i++; + + if (i > 1000) { + RESET_MAC; + axlocal.NextTxDesc = TXDP0; + axlocal.FirstTxDesc = axlocal.NextTxDesc; + txbs_txdp = 1 << axlocal.FirstTxDesc; + READ_MACREG(TXBS, tmp_data); + i = 0; + PRINTK(ERROR_MSG, "ax88180: No available TXDP!!\n"); + } + } + + PRINTK(TX_MSG, "ax88180: TXDP%d is available, i=%d\n", + (int)axlocal.FirstTxDesc, i); + /* allan9 end */ + + txcmd_txdp = axlocal.FirstTxDesc << 13; + TXDES_addr = TXDES0 + (axlocal.FirstTxDesc << 2); + + WRITE_MACREG(TXCMD, txcmd_txdp | length | TX_START_WRITE); + +#ifdef CONFIG_DRIVER_AX88180_16BIT + for (i = 0; i < length; i += 2) { + tmp_data = + (unsigned short)*(txdata + i) + + (unsigned short)(*(txdata + i + 1) << 8); + WRITE_TXBUF(tmp_data); + } +#else + for (i = 0; i < length; i += 4) { + tmp_data = + (unsigned long)*(txdata + i) + + (unsigned long)(*(txdata + i + 1) << 8) + + (unsigned long)(*(txdata + i + 2) << 16) + + (unsigned long)(*(txdata + i + 3) << 24); + WRITE_TXBUF(tmp_data); + } +#endif + + WRITE_MACREG(TXCMD, txcmd_txdp | length); + WRITE_MACREG(TXBS, txbs_txdp); + WRITE_MACREG(TXDES_addr, TXDPx_ENABLE | length); + + axlocal.NextTxDesc++; + + axlocal.NextTxDesc &= TXDP_MASK; + + return 0; +} diff --git a/drivers/net/ax88180.h b/drivers/net/ax88180.h new file mode 100644 index 0000000..977258f --- /dev/null +++ b/drivers/net/ax88180.h @@ -0,0 +1,348 @@ +/* ax88180.h: ASIX AX88180 Non-PCI Gigabit Ethernet u-boot driver */ +/* + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + */ + +#include <asm/types.h> +#include <config.h> + +#ifdef CONFIG_DRIVER_AX88180 + +#define PLATFORM_MEMBASE 0x08000000 + +#define ENABLE_JUMBO 1 +#define DISABLE_JUMBO 0 + +#define DEFAULT_ETH_MTU 1500 +#define MAX_JUMBO_MTU 4072 /* Jumbo packet size 4086 bytes included 4 bytes CRC */ +#define MAX_TX_JUMBO_SIZE 4086 /* Max Tx Jumbo size 4086 bytes included 4 bytes CRC */ +#define MAX_RX_SIZE 0x3C00 /* Max Rx Jumbo size is 15K Bytes */ + +#define AX88180_MEMORY_SIZE 0x00010000 + +#define MARVELL_88E1111_PHYADDR 0x18 +#define MARVELL_88E1111_PHYIDR0 0x0141 + +#define CICADA_CIS8201_PHYADDR 0x01 +#define CICADA_CIS8201_PHYIDR0 0x000F + +#define MEDIA_AUTO 0 +#define MEDIA_1000FULL 1 +#define MEDIA_1000HALF 2 +#define MEDIA_100FULL 3 +#define MEDIA_100HALF 4 +#define MEDIA_10FULL 5 +#define MEDIA_10HALF 6 + +#define AUTO_MEDIA 0 +#define FORCE_MEDIA 1 + +#define TXDP_MASK 3 +#define TXDP0 0 +#define TXDP1 1 +#define TXDP2 2 +#define TXDP3 3 + +/* AX88180 Memory Mapping Definition */ +#define RXBUFFER_START 0x0000 +#define RX_PACKET_LEN_OFFSET 0 +#define RX_PAGE_NUM_MASK 0x7FF /* RX pages 0~7FFh */ +#define TXBUFFER_START 0x8000 + +/* AX88180 MAC Register Definition */ +#define CMD 0xFC00 +#define WAKEMOD 0x00000001 +#define TXEN 0x00000100 +#define RXEN 0x00000200 +#define DEFAULT_CMD WAKEMOD +#define IMR 0xFC04 +#define IMR_RXBUFFOVR 0x00000001 +#define IMR_WATCHDOG 0x00000002 +#define IMR_TX 0x00000008 +#define IMR_RX 0x00000010 +#define IMR_PHY 0x00000020 +#define CLEAR_IMR 0x00000000 +#define DEFAULT_IMR (IMR_PHY | IMR_RX | IMR_RXBUFFOVR) +#define ISR 0xFC08 +#define ISR_RXBUFFOVR 0x00000001 +#define ISR_WATCHDOG 0x00000002 +#define ISR_TX 0x00000008 +#define ISR_RX 0x00000010 +#define ISR_PHY 0x00000020 +#define TXCFG 0xFC10 +#define AUTOPAD_CRC 0x00000040 +#define DEFAULT_TXCFG AUTOPAD_CRC +#define TXCMD 0xFC14 +#define TXCMD_TXDP_MASK 0x00006000 +#define TXCMD_TXDP0 0x00000000 +#define TXCMD_TXDP1 0x00002000 +#define TXCMD_TXDP2 0x00004000 +#define TXCMD_TXDP3 0x00006000 +#define TX_START_WRITE 0x00008000 +#define TX_STOP_WRITE 0x00000000 +#define DEFAULT_TXCMD 0x00000000 +#define TXBS 0xFC18 +#define TXDP0_USED 0x00000001 +#define TXDP1_USED 0x00000002 +#define TXDP2_USED 0x00000004 +#define TXDP3_USED 0x00000008 +#define DEFAULT_TXBS 0x00000000 +#define TXDES0 0xFC20 +#define TXDPx_ENABLE 0x00008000 +#define TXDPx_LEN_MASK 0x00001FFF +#define DEFAULT_TXDES0 0x00000000 +#define TXDES1 0xFC24 +#define TXDPx_ENABLE 0x00008000 +#define TXDPx_LEN_MASK 0x00001FFF +#define DEFAULT_TXDES1 0x00000000 +#define TXDES2 0xFC28 +#define TXDPx_ENABLE 0x00008000 +#define TXDPx_LEN_MASK 0x00001FFF +#define DEFAULT_TXDES2 0x00000000 +#define TXDES3 0xFC2C +#define TXDPx_ENABLE 0x00008000 +#define TXDPx_LEN_MASK 0x00001FFF +#define DEFAULT_TXDES3 0x00000000 +#define RXCFG 0xFC30 +#define RXBUFF_PROTECT 0x00000001 +#define RXTCPCRC_CHECK 0x00000010 +#define RXFLOW_ENABLE 0x00000100 +#define DEFAULT_RXCFG RXBUFF_PROTECT +#define RXCURT 0xFC34 +#define DEFAULT_RXCURT 0x00000000 +#define RXBOUND 0xFC38 +#define DEFAULT_RXBOUND 0x000007FF +#define MACCFG0 0xFC40 +#define MACCFG0_BIT3_0 0x00000007 +#define IPGT_VAL 0x00000150 +#define TXFLOW_ENABLE 0x00001000 +#define SPEED100 0x00008000 +#define DEFAULT_MACCFG0 (IPGT_VAL | MACCFG0_BIT3_0) +#define MACCFG1 0xFC44 +#define RGMII_EN 0x00000002 +#define RXFLOW_EN 0x00000020 +#define FULLDUPLEX 0x00000040 +#define MAX_JUMBO_LEN_MASK 0x00000780 +#define RXJUMBO_EN 0x00000800 +#define GIGA_MODE_EN 0x00001000 +#define RXCRC_CHECK 0x00002000 +#define RXPAUSE_DA_CHECK 0x00004000 + +#define JUMBO_LEN_4K 0x00000200 +#define JUMBO_LEN_15K 0x00000780 +#define DEFAULT_MACCFG1 (RXCRC_CHECK | RXPAUSE_DA_CHECK | RGMII_EN) +#define MACCFG2 0xFC48 +#define MACCFG2_BIT15_8 0x00000100 +#define JAM_LIMIT_MASK 0x000000FC +#define DEFAULT_JAM_LIMIT 0x00000064 +#define DEFAULT_MACCFG2 MACCFG2_BIT15_8 +#define MACCFG3 0xFC4C +#define IPGR2_VAL 0x0000000E +#define IPGR1_VAL 0x00000600 +#define NOABORT 0x00008000 +#define DEFAULT_MACCFG3 (IPGR1_VAL | IPGR2_VAL) +#define TXPAUT 0xFC54 +#define DEFAULT_TXPAUT 0x001FE000 +#define RXBTHD0 0xFC58 +#define DEFAULT_RXBTHD0 0x00000300 +#define RXBTHD1 0xFC5C +#define DEFAULT_RXBTHD1 0x00000600 +#define RXFULTHD 0xFC60 +#define DEFAULT_RXFULTHD 0x00000100 +#define MISC 0xFC68 +#define MISC_NORMAL 0x00000003 /* Normal operation mode */ +#define MISC_RESET_MAC 0x00000002 /* Clear bit 0 to reset MAC */ +#define MISC_RESET_PHY 0x00000001 /* Clear bit 1 to reset PHY */ +#define MISC_RESET_MAC_PHY 0x00000000 /* Clear bit 0 and 1 to reset MAC and PHY */ +#define DEFAULT_MISC MISC_NORMAL +#define MACID0 0xFC70 +#define MACID1 0xFC74 +#define MACID2 0xFC78 +#define TXLEN 0xFC7C +#define DEFAULT_TXLEN 0x000005FC +#define RXFILTER 0xFC80 +#define RX_RXANY 0x00000001 +#define RX_MULTICAST 0x00000002 +#define RX_UNICAST 0x00000004 +#define RX_BROADCAST 0x00000008 +#define RX_MULTI_HASH 0x00000010 +#define DISABLE_RXFILTER 0x00000000 +#define DEFAULT_RXFILTER (RX_BROADCAST + RX_UNICAST + RX_MULTICAST) +#define MDIOCTRL 0xFC84 +#define PHY_ADDR_MASK 0x0000001F +#define REG_ADDR_MASK 0x00001F00 +#define READ_PHY 0x00004000 +#define WRITE_PHY 0x00008000 +#define MDIODP 0xFC88 +#define GPIOCTRL 0xFC8C +#define RXINDICATOR 0xFC90 +#define RX_START_READ 0x00000001 +#define RX_STOP_READ 0x00000000 +#define DEFAULT_RXINDICATOR RX_STOP_READ +#define TXST 0xFC94 +#define MDCCLKPAT 0xFCA0 +#define RXIPCRCCNT 0xFCA4 +#define RXCRCCNT 0xFCA8 +#define TXFAILCNT 0xFCAC +#define PROMDP 0xFCB0 +#define PROMCTRL 0xFCB4 +#define RELOAD_EEPROM 0x00000200 +#define MAXRXLEN 0xFCB8 +#define HASHTAB0 0xFCC0 +#define HASHTAB1 0xFCC4 +#define HASHTAB2 0xFCC8 +#define HASHTAB3 0xFCCC +#define DOGTHD0 0xFCE0 +#define DEFAULT_DOGTHD0 0x0000FFFF +#define DOGTHD1 0xFCE4 +#define START_WATCHDOG_TIMER 0x00008000 +#define DEFAULT_DOGTHD1 0x00000FFF +#define SOFTRST 0xFCEC +#define SOFTRST_NORMAL 0x00000003 +#define SOFTRST_RESET_MAC 0x00000002 + +/* External PHY Register Definition */ +#define BMCR 0x0000 +#define LINE_SPEED_MSB 0x0040 +#define DUPLEX_MODE 0x0100 +#define RESTART_AUTONEG 0x0200 +#define POWER_DOWN 0x0800 +#define AUTONEG_EN 0x1000 +#define LINE_SPEED_LSB 0x2000 +#define PHY_RESET 0x8000 + +#define MEDIAMODE_MASK (LINE_SPEED_MSB | LINE_SPEED_LSB | DUPLEX_MODE) +#define BMCR_SPEED_1000 LINE_SPEED_MSB +#define BMCR_SPEED_100 LINE_SPEED_LSB +#define BMCR_SPEED_10 0x0000 + +#define BMCR_1000FULL (BMCR_SPEED_1000 | DUPLEX_MODE) +#define BMCR_100FULL (BMCR_SPEED_100 | DUPLEX_MODE) +#define BMCR_100HALF BMCR_SPEED_100 +#define BMCR_10FULL DUPLEX_MODE +#define BMCR_10HALF 0x0000 +#define BMSR 0x0001 +#define LINKOK 0x0004 +#define AUTONEG_ENABLE_STS 0x0008 +#define AUTONEG_COMPLETE 0x0020 +#define PHYIDR0 0x0002 +#define PHYIDR1 0x0003 +#define ANAR 0x0004 +#define ANAR_PAUSE 0x0400 +#define ANAR_100FULL 0x0100 +#define ANAR_100HALF 0x0080 +#define ANAR_10FULL 0x0040 +#define ANAR_10HALF 0x0020 +#define ANAR_8023BIT 0x0001 +#define ANLPAR 0x0005 +#define ANER 0x0006 +#define AUX_1000_CTRL 0x0009 +#define ENABLE_1000HALF 0x0100 +#define ENABLE_1000FULL 0x0200 +#define DEFAULT_AUX_1000_CTRL (ENABLE_1000HALF | ENABLE_1000FULL) +#define AUX_1000_STATUS 0x000A +#define LP_1000HALF 0x0400 +#define LP_1000FULL 0x0800 + +/* Marvell 88E1111 Gigabit PHY Register Definition */ +#define M88_SSR 0x0011 +#define SSR_SPEED_MASK 0xC000 +#define SSR_SPEED_1000 0x8000 +#define SSR_SPEED_100 0x4000 +#define SSR_SPEED_10 0x0000 +#define SSR_DUPLEX 0x2000 +#define SSR_MEDIA_RESOLVED_OK 0x0800 + +#define SSR_MEDIA_MASK (SSR_SPEED_MASK | SSR_DUPLEX) +#define SSR_1000FULL (SSR_SPEED_1000 | SSR_DUPLEX) +#define SSR_1000HALF SSR_SPEED_1000 +#define SSR_100FULL (SSR_SPEED_100 | SSR_DUPLEX) +#define SSR_100HALF SSR_SPEED_100 +#define SSR_10FULL (SSR_SPEED_10 | SSR_DUPLEX) +#define SSR_10HALF SSR_SPEED_10 +#define M88_IER 0x0012 +#define LINK_CHANGE_INT 0x0400 +#define M88_ISR 0x0013 +#define LINK_CHANGE_STATUS 0x0400 +#define M88_EXT_SCR 0x0014 +#define RGMII_RXCLK_DELAY 0x0080 +#define RGMII_TXCLK_DELAY 0x0002 +#define DEFAULT_EXT_SCR (RGMII_TXCLK_DELAY | RGMII_RXCLK_DELAY) +#define M88_EXT_SSR 0x001B +#define HWCFG_MODE_MASK 0x000F +#define RGMII_COPPER_MODE 0x000B + +/* CICADA CIS8201 Gigabit PHY Register Definition */ +#define CIS_IMR 0x0019 +#define CIS_INT_ENABLE 0x8000 +#define CIS_LINK_CHANGE_INT 0x2000 +#define CIS_ISR 0x001A +#define CIS_INT_PENDING 0x8000 +#define CIS_LINK_CHANGE_STATUS 0x2000 +#define CIS_AUX_CTRL_STATUS 0x001C +#define CIS_AUTONEG_COMPLETE 0x8000 +#define CIS_SPEED_MASK 0x0018 +#define CIS_SPEED_1000 0x0010 +#define CIS_SPEED_100 0x0008 +#define CIS_SPEED_10 0x0000 +#define CIS_DUPLEX 0x0020 + +#define CIS_MEDIA_MASK (CIS_SPEED_MASK | CIS_DUPLEX) +#define CIS_1000FULL (CIS_SPEED_1000 | CIS_DUPLEX) +#define CIS_1000HALF CIS_SPEED_1000 +#define CIS_100FULL (CIS_SPEED_100 | CIS_DUPLEX) +#define CIS_100HALF CIS_SPEED_100 +#define CIS_10FULL (CIS_SPEED_10 | CIS_DUPLEX) +#define CIS_10HALF CIS_SPEED_10 +#define CIS_SMI_PRIORITY 0x0004 + +/* SMDK2440 Registers Definition */ +/* SMDK2440 default clocks: FCLK=400MHZ, HCLK=125MHZ, PCLK=62.5MHZ */ +#define CLKDIVN_125MHZ 0x0000000F /* Set HCLK=FCLK/3, PCLK=HCLK/2 when CAMDIVN[8]=0 */ +#define CAMDIVN_125MHZ 0x00000000 /* Set HCLK=FCLK/3, PCLK=HCLK/2 when CAMDIVN[8]=0 */ +#define UBRDIV0_125MHZ 0x00000023 /* Set UART Baud Rate divisor for 125MHZ HCLK */ +#define CLKDIVN_100MHZ 0x0000000D /* Set HCLK=FCLK/4, PCLK=HCLK/2 when CAMDIVN[9]=0 */ +#define CAMDIVN_100MHZ 0x00000000 /* Set HCLK=FCLK/4, PCLK=HCLK/2 when CAMDIVN[9]=0 */ +#define UBRDIV0_100MHZ 0x0000001B /* Set UART Baud Rate divisor for 100MHZ HCLK */ +#define CLKDIVN_50MHZ 0x0000000D /* Set HCLK=FCLK/8, PCLK=HCLK/2 when CAMDIVN[9]=1 */ +#define CAMDIVN_50MHZ 0x00000200 /* Set HCLK=FCLK/8, PCLK=HCLK/2 when CAMDIVN[9]=1 */ +#define UBRDIV0_50MHZ 0x0000000D /* Set UART Baud Rate divisor for 50MHZ HCLK */ +#define BANKCON1_4CLKS 0x00000300 /* Set Bank 1 access timing 4 clocks for AX88180 US1 */ +#define BANKCON1_6CLKS 0x00000400 /* Set Bank 1 access timing 6 clocks for AX88180 US2 */ +#define BANKCON1_6CLKS_PAGE 0x0000040F /* Set Bank 1 access timing 6 clocks with page access for AX88180 US2 */ +#define BANKCON1_14CLKS 0x00000700 /* Set Bank 1 access timing 14 clocks (SMDK2440 H/W default) */ + +/* EINTMASK Register Bit Definition */ +#define EINT11_MASK 0x00000800 /* Clear this bit to enable EINT11 interrupt */ + +/* EXTINT1 Register Bit Definition */ +#define FLTEN11 0x00008000 /* Enable EINT11 signal noise filter */ + +/* Debug Message Display Level Definition */ +#define DRIVER_MSG 0x0001 +#define INIT_MSG 0x0002 +#define TX_MSG 0x0004 +#define RX_MSG 0x0008 +#define INT_MSG 0x0010 +#define ERROR_MSG 0x0020 +#define WARNING_MSG 0x0040 +#define DEBUG_MSG 0x0080 +#define OTHERS_MSG 0x0100 +#define ALL_MSG 0x01FF +#define NO_MSG 0x0000 +#define DEBUG_FLAGS (ERROR_MSG) + +#endif /*end of CONFIG_DRIVER_AX88180 */