
Resubmit the driver for the ASIX AX88180 gigabit ethernet chip.
Signed-off-by: Louis Su louis@asix.com.tw --- drivers/net/Makefile | 1 + drivers/net/ax88180.c | 842 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ax88180.h | 415 ++++++++++++++++++++++++ 3 files changed, 1258 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 84be288..3a574e0 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o COBJS-$(CONFIG_DRIVER_CS8900) += cs8900.o diff --git a/drivers/net/ax88180.c b/drivers/net/ax88180.c new file mode 100644 index 0000000..5579ef0 --- /dev/null +++ b/drivers/net/ax88180.c @@ -0,0 +1,842 @@ +/* ax88180: 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. +*/ + +/* + ======================================================================== + ASIX AX88180 Non-PCI 16/32-bit Gigabit Ethernet Linux Driver + + The AX88180 Ethernet controller is a high performance and highly + integrated local CPU bus Ethernet controller 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 + Date : 2008-07-01 + History + 09/06/2006 : New release for AX88180 US2 chip. + 07/01/2008 : Fix up the coding style and using functions + instead of most macros + ======================================================================== +*/ +#include <common.h> +#include <command.h> +#include <net.h> + +#include "ax88180.h" + +#ifdef CONFIG_DRIVER_AX88180 + +/* +=========================================================================== +<<<<<< Local SubProgram Declaration >>>>>> +=========================================================================== +*/ +static void ax88180_rx_handler (void); +static int ax88180_PHY_initial (void); +static void ax88180_meida_config (void); +static unsigned long get_CicadaPHY_meida_mode (void); +static unsigned long get_MarvellPHY_meida_mode (void); +static unsigned short ax88180_mdio_read (unsigned long phyaddr, + unsigned long regaddr); +static void ax88180_mdio_write (unsigned long phyaddr, + unsigned long regaddr, + unsigned short regdata); + +/* +=========================================================================== +<<<<<< Declare Macro/Structure Definition >>>>>> +=========================================================================== +*/ +typedef enum _AX88180_LINK_STATE { + INS_LINK_DOWN, + INS_LINK_UP, + INS_LINK_UNKNOWN +} AX88180_LINK_STATE; + +typedef struct _AX88180_PRIVATE { + unsigned long PhyAddr; + unsigned long PhyID0; + unsigned long FirstTxDesc; + unsigned long NextTxDesc; + unsigned long rxbuf_overflow_count; + AX88180_LINK_STATE LinkState; +} AX88180_PRIVATE; + +AX88180_PRIVATE axlocal; + +#if (DEBUG_FLAGS & DEBUG_MSG) +static inline void ax88180_disp_all_reg (void) +{ + unsigned long tmpval; + int i; + PRINTK (DEBUG_MSG, "ax88180: AX88180 MAC Registers:\n"); + for (i = 0xFC00; i <= 0xFCFF; i += 4) { + READ_MACREG (i, tmpval); + PRINTK (DEBUG_MSG, "0x%04x=0x%08lx ", i, tmpval); + if ((i & 0xF) == 0xC) + PRINTK (DEBUG_MSG, "\n"); + } + PRINTK (DEBUG_MSG, "\n"); +} + +static inline void ax88180_disp_phy_reg (void) +{ + unsigned long tmpval; + tmpval = ax88180_mdio_read (axlocal.PhyAddr, BMCR); + PRINTK (DEBUG_MSG, "BMCR=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, BMSR); + PRINTK (DEBUG_MSG, "BMSR=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, PHYIDR0); + PRINTK (DEBUG_MSG, "PHYIDR0=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, PHYIDR1); + PRINTK (DEBUG_MSG, "PHYIDR1=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, ANAR); + PRINTK (DEBUG_MSG, "ANAR=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, ANLPAR); + PRINTK (DEBUG_MSG, "ANLPAR=0x%04x \n", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, ANER); + PRINTK (DEBUG_MSG, "ANER=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, AUX_1000_CTRL); + PRINTK (DEBUG_MSG, "1G_CTRL=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, AUX_1000_STATUS); + PRINTK (DEBUG_MSG, "1G_STATUS=0x%04x \n", (unsigned int)tmpval); + if (axlocal.PhyID0 == MARVELL_88E1111_PHYIDR0) { + tmpval = ax88180_mdio_read (axlocal.PhyAddr, M88_SSR); + PRINTK (DEBUG_MSG, "M88_SSR=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, M88_IER); + PRINTK (DEBUG_MSG, "M88_IER=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, M88_ISR); + PRINTK (DEBUG_MSG, "M88_ISR=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, M88_EXT_SCR); + PRINTK (DEBUG_MSG, "M88_EXT_SCR=0x%04x ", + (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, M88_EXT_SSR); + PRINTK (DEBUG_MSG, "M88_EXT_SSR=0x%04x \n", + (unsigned int)tmpval); + } else if (axlocal.PhyID0 == CICADA_CIS8201_PHYIDR0) { + tmpval = ax88180_mdio_read (axlocal.PhyAddr, CIS_IMR); + PRINTK (DEBUG_MSG, "CIS_IMR=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, CIS_ISR); + PRINTK (DEBUG_MSG, "CIS_ISR=0x%04x ", (unsigned int)tmpval); + tmpval = ax88180_mdio_read (axlocal.PhyAddr, + CIS_AUX_CTRL_STATUS); + PRINTK (DEBUG_MSG, "CIS_AUX=0x%04x \n", + (unsigned int)tmpval); + } + READ_MACREG (RXCFG, tmpval); + PRINTK (DEBUG_MSG, "RXCFG=0x%08lx ", tmpval); + READ_MACREG (MACCFG0, tmpval); + PRINTK (DEBUG_MSG, "MACCFG0=0x%08lx ", tmpval); + READ_MACREG (MACCFG1, tmpval); + PRINTK (DEBUG_MSG, "MACCFG1=0x%08lx ", tmpval); + READ_MACREG (MACCFG2, tmpval); + PRINTK (DEBUG_MSG, "MACCFG2=0x%08lx \n\n", tmpval); +} +#else +static inline void ax88180_disp_all_reg (void) {} +static inline void ax88180_disp_phy_reg (void) {} +#endif + +/* +=========================================================================== +<<<<<< Local SubProgram Bodies >>>>>> +=========================================================================== +*/ +static int +ax88180_mdio_check_complete (void) +{ + int us_cnt = 10000; + unsigned long tmpval; + + /* MDIO read/write should not take more than 10 ms */ + while (--us_cnt) { + READ_MACREG (MDIOCTRL, tmpval); + if (((tmpval & READ_PHY) == 0) && ((tmpval & WRITE_PHY) == 0)) + break; + } + + return us_cnt; +} + +static unsigned short +ax88180_mdio_read (unsigned long phyaddr, unsigned long regaddr) +{ + unsigned long tmpval = 0; + + WRITE_MACREG (MDIOCTRL, READ_PHY | (regaddr << 8) | phyaddr); + + if (ax88180_mdio_check_complete ()) + READ_MACREG (MDIODP, tmpval); + else + printf("Failed to read PHY register!\n"); + return (unsigned short)(tmpval & 0xFFFF); +} + +static void +ax88180_mdio_write (unsigned long phyaddr, unsigned long regaddr, + unsigned short regdata) +{ + WRITE_MACREG (MDIODP, regdata); + WRITE_MACREG (MDIOCTRL, WRITE_PHY | (regaddr << 8) | phyaddr); + + if(!ax88180_mdio_check_complete ()) + printf("Failed to write PHY register!\n"); +} + +static int ax88180_phy_reset (void) +{ + unsigned short delay_cnt = 500; + + ax88180_mdio_write (axlocal.PhyAddr, BMCR, PHY_RESET | AUTONEG_EN); + + /* Wait for the reset to complete, or time out (500 ms) */ + while (ax88180_mdio_read (axlocal.PhyAddr, BMCR) & PHY_RESET) { + udelay (1000); + if (--delay_cnt == 0) { + printf("Failed to reset PHY!\n"); + return -1; + } + } + + return 0; +} + +static void ax88180_mac_reset (void) +{ + unsigned long tmpval; + + WRITE_MACREG (MISC, MISC_RESET_MAC); + READ_MACREG (MISC, tmpval); + 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 (RXBTHD0, DEFAULT_RXBTHD0); + WRITE_MACREG (RXBTHD1, DEFAULT_RXBTHD1); + WRITE_MACREG (RXFULTHD, DEFAULT_RXFULTHD); + WRITE_MACREG (DOGTHD0, DEFAULT_DOGTHD0); + WRITE_MACREG (DOGTHD1, DEFAULT_DOGTHD1); +} + +static int ax88180_poll_tx_complete (void) +{ + unsigned long tmp_data, txbs_txdp; + int TimeOutCnt = 10000; + + txbs_txdp = 1 << axlocal.NextTxDesc; + + while (TimeOutCnt--) { + + READ_MACREG (TXBS, tmp_data); + if ((tmp_data & txbs_txdp) == 0) + break; + + udelay (100); + } + + if (TimeOutCnt) + return 0; + else + return -TimeOutCnt; +} + +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) { + WRITE_MACREG (RXINDICATOR, RX_START_READ); + READ_RXBUF (rx_packet_len); + if ((rx_packet_len == 0) || (rx_packet_len > MAX_RX_SIZE)) { + WRITE_MACREG (RXINDICATOR, RX_STOP_READ); + ax88180_mac_reset (); + printf ("ax88180: Invalid Rx packet length!" + " (len=0x%08lx)\n", rx_packet_len); + + printf ("ax88180: RX RXBOUND=0x%08lx," + "RXCURT=0x%08lx\n", rxbound_ptr, rxcurt_ptr); + 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]; + +#if defined (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); +#if defined (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)); + } + } + + WRITE_MACREG (RXINDICATOR, RX_STOP_READ); + + /* 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; +} + +static int ax88180_PHY_initial (void) +{ + unsigned long tmp_regval; + int i; + int ret; + + /* Check avaliable PHY chipset */ + axlocal.PhyAddr = MARVELL_88E1111_PHYADDR; + axlocal.PhyID0 = ax88180_mdio_read (axlocal.PhyAddr, PHYIDR0); + + if (axlocal.PhyID0 == MARVELL_88E1111_PHYIDR0) { + PRINTK (DEBUG_MSG, "ax88180: Found Marvell 88E1111 PHY." + " (PHY Addr=0x%lx)\n", axlocal.PhyAddr); + tmp_regval = ax88180_mdio_read (axlocal.PhyAddr, M88_EXT_SSR); + if ((tmp_regval & HWCFG_MODE_MASK) == RGMII_COPPER_MODE) { + ax88180_mdio_write (axlocal.PhyAddr, M88_EXT_SCR, + DEFAULT_EXT_SCR); + if ((ret = ax88180_phy_reset ()) < 0) + return ret; + ax88180_mdio_write (axlocal.PhyAddr, M88_IER, + LINK_CHANGE_INT); + } + } else { + axlocal.PhyAddr = CICADA_CIS8201_PHYADDR; + axlocal.PhyID0 = ax88180_mdio_read (axlocal.PhyAddr, PHYIDR0); + if (axlocal.PhyID0 == CICADA_CIS8201_PHYIDR0) { + PRINTK (DEBUG_MSG, "ax88180: Found CICADA CIS8201 PHY" + " chipset. (PHY Addr=0x%lx)\n", + axlocal.PhyAddr); + ax88180_mdio_write (axlocal.PhyAddr, CIS_IMR, + (CIS_INT_ENABLE | LINK_CHANGE_INT)); + + /* + Set CIS_SMI_PRIORITY bit before force the media mode + */ + tmp_regval = ax88180_mdio_read (axlocal.PhyAddr, + CIS_AUX_CTRL_STATUS); + tmp_regval &= ~CIS_SMI_PRIORITY; + ax88180_mdio_write (axlocal.PhyAddr, + CIS_AUX_CTRL_STATUS, tmp_regval); + } else { + printf ("ax88180: Unknown PHY chipset!!\n"); + return -1; + } + } + + /* Waiting for auto-negotiation complete. */ + /* This may take up to 5 seconds */ + PRINTK (DEBUG_MSG, + "ax88180: Waiting for auto-negotiation completion......\n"); + for (i = 0; i < 5000; i++) { + tmp_regval = ax88180_mdio_read (axlocal.PhyAddr, BMSR); + if (tmp_regval & AUTONEG_COMPLETE) { + break; + } + udelay (1000); + } + + return 0; +} + +static void ax88180_meida_config (void) +{ + unsigned long bmcr_val, bmsr_val; + unsigned long rxcfg_val, maccfg0_val, maccfg1_val; + unsigned long RealMediaMode; + int i; + + /* Waiting 200 msecs for PHY link stable */ + for (i = 0; i < 200; i++) { + bmsr_val = ax88180_mdio_read (axlocal.PhyAddr, BMSR); + if (bmsr_val & LINKOK) { + break; + } + udelay (1000); + } + + bmsr_val = ax88180_mdio_read (axlocal.PhyAddr, BMSR); + PRINTK (DEBUG_MSG, "ax88180: BMSR=0x%04x\n", (unsigned int)bmsr_val); + + if (bmsr_val & LINKOK) { + bmcr_val = ax88180_mdio_read (axlocal.PhyAddr, BMCR); + if (bmcr_val & AUTONEG_EN) { + /* Waiting for Auto-negotiation completion */ + /* This may take up to 5 seconds */ + PRINTK (DEBUG_MSG, "ax88180: Auto-negotiation is " + "enabled. Waiting for NWay completion..\n"); + for (i = 0; i < 5000; i++) { + bmsr_val = ax88180_mdio_read (axlocal.PhyAddr, + BMSR); + if (bmsr_val & AUTONEG_COMPLETE) { + break; + } + udelay (1000); + } + } else + PRINTK (DEBUG_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) { + RealMediaMode = get_MarvellPHY_meida_mode (); + } else if (axlocal.PhyID0 == CICADA_CIS8201_PHYIDR0) { + RealMediaMode = get_CicadaPHY_meida_mode (); + } else { + RealMediaMode = MEDIA_1000FULL; + } + + switch (RealMediaMode) { + default: + case MEDIA_1000FULL: + PRINTK (DEBUG_MSG, + "ax88180: 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 (DEBUG_MSG, + "ax88180: 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 (DEBUG_MSG, + "ax88180: 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 (DEBUG_MSG, + "ax88180: 100Mbps Half-duplex mode.\n"); + rxcfg_val = DEFAULT_RXCFG; + maccfg0_val = SPEED100 | DEFAULT_MACCFG0; + maccfg1_val = DEFAULT_MACCFG1; + break; + + case MEDIA_10FULL: + PRINTK (DEBUG_MSG, + "ax88180: 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 (DEBUG_MSG, + "ax88180: 10Mbps Half-duplex mode.\n"); + rxcfg_val = DEFAULT_RXCFG; + maccfg0_val = DEFAULT_MACCFG0; + maccfg1_val = DEFAULT_MACCFG1; + break; + } + + axlocal.LinkState = INS_LINK_UP; + } else { + rxcfg_val = DEFAULT_RXCFG; + maccfg0_val = DEFAULT_MACCFG0; + maccfg1_val = DEFAULT_MACCFG1; + + axlocal.LinkState = INS_LINK_DOWN; + } + + WRITE_MACREG (RXCFG, rxcfg_val); + WRITE_MACREG (MACCFG0, maccfg0_val); + WRITE_MACREG (MACCFG1, maccfg1_val); + + return; +} + +static unsigned long +get_MarvellPHY_meida_mode (void) +{ + unsigned long m88_ssr; + unsigned long MediaMode; + + m88_ssr = ax88180_mdio_read (axlocal.PhyAddr, M88_SSR); + switch (m88_ssr & SSR_MEDIA_MASK) { + default: + case SSR_1000FULL: + MediaMode = MEDIA_1000FULL; + break; + case SSR_1000HALF: + MediaMode = MEDIA_1000HALF; + break; + case SSR_100FULL: + MediaMode = MEDIA_100FULL; + break; + case SSR_100HALF: + MediaMode = MEDIA_100HALF; + break; + case SSR_10FULL: + MediaMode = MEDIA_10FULL; + break; + case SSR_10HALF: + MediaMode = MEDIA_10HALF; + break; + } + + return MediaMode; +} + +static unsigned long +get_CicadaPHY_meida_mode (void) +{ + unsigned long tmp_regval; + unsigned long MediaMode; + + tmp_regval = ax88180_mdio_read (axlocal.PhyAddr, + CIS_AUX_CTRL_STATUS); + switch (tmp_regval & CIS_MEDIA_MASK) { + default: + case CIS_1000FULL: + MediaMode = MEDIA_1000FULL; + break; + case CIS_1000HALF: + MediaMode = MEDIA_1000HALF; + break; + case CIS_100FULL: + MediaMode = MEDIA_100FULL; + break; + case CIS_100HALF: + MediaMode = MEDIA_100HALF; + break; + case CIS_10FULL: + MediaMode = MEDIA_10FULL; + break; + case CIS_10HALF: + MediaMode = MEDIA_10HALF; + break; + } + + return MediaMode; +} + +/* +=========================================================================== +<<<<<< Exported SubProgram Bodies >>>>>> +=========================================================================== +*/ +void eth_halt (void) +{ + /* Disable AX88180 TX/RX functions */ + WRITE_MACREG (CMD, WAKEMOD); +} + +int eth_init (bd_t *bd) +{ + unsigned long tmp_regval; + unsigned long macid0_val, macid1_val, macid2_val; + int ret, i; + +#if defined (CONFIG_DRIVER_AX88180_16BIT) + *((volatile unsigned short *)(AX88180_BASE + 6)) = (START_BASE >> 8); + *((volatile unsigned short *)AX88180_BASE ) = 1; +#endif + memset (&axlocal, 0, sizeof (AX88180_PRIVATE)); + + ax88180_mac_reset (); + + /* Disable AX88180 interrupt */ + WRITE_MACREG (IMR, CLEAR_IMR); + + /* Disable AX88180 TX/RX functions */ + WRITE_MACREG (CMD, WAKEMOD); + + axlocal.LinkState = INS_LINK_UNKNOWN; + + /* Initial PHY registers */ + if ((ret = ax88180_PHY_initial ()) < 0) + return ret; + ax88180_meida_config (); + + /* Reload MAC address from EEPROM */ + WRITE_MACREG (PROMCTRL, RELOAD_EEPROM); + + /* Waiting for reload eeprom completion */ + for (i = 0; i < 500; i++) { + READ_MACREG (PROMCTRL, tmp_regval); + if ((tmp_regval & RELOAD_EEPROM) == 0) + break; + udelay (1000); + } + + /* Get MAC addresses */ + READ_MACREG (MACID0, macid0_val); + READ_MACREG (MACID1, macid1_val); + READ_MACREG (MACID2, macid2_val); + + bd->bi_enetaddr[0] = (unsigned char)macid0_val; + bd->bi_enetaddr[1] = (unsigned char)(macid0_val >> 8); + bd->bi_enetaddr[2] = (unsigned char)macid1_val; + bd->bi_enetaddr[3] = (unsigned char)(macid1_val >> 8); + bd->bi_enetaddr[4] = (unsigned char)macid2_val; + bd->bi_enetaddr[5] = (unsigned char)(macid2_val >> 8); + + if (((macid0_val | macid1_val | macid2_val) == 0) || + (bd->bi_enetaddr[0] & 0x01)) { + /* try to get MAC address from environment */ + u8 i; + char *s, *e; + unsigned short tmp16; + + s = getenv ("ethaddr"); + for (i = 0; i < 6; ++i) { + bd->bi_enetaddr[i] = s ? + simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + + 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); + } + + WRITE_MACREG (RXFILTER, DEFAULT_RXFILTER); + + /* Initial variables here */ + axlocal.FirstTxDesc = TXDP0; + axlocal.NextTxDesc = TXDP0; + axlocal.rxbuf_overflow_count = 0; + + ax88180_disp_all_reg (); + + /* Check if there is any invalid interrupt status. If yes, clear it. */ + READ_MACREG (ISR, tmp_regval); + PRINTK (DEBUG_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 */ +int eth_rx (void) +{ + unsigned long ISR_Status; + unsigned long rxcurt_ptr, rxbound_ptr; + unsigned long tmp_regval; + + /* 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, + "\nax88180: The interrupt status = 0x%08lx\n", + ISR_Status); + + if (ISR_Status & ISR_PHY) { + /* Read ISR register once to clear PHY interrupt bit */ + tmp_regval = ax88180_mdio_read (axlocal.PhyAddr, + M88_ISR); + ax88180_meida_config (); + ax88180_disp_phy_reg (); + } + + if (ISR_Status & ISR_RXBUFFOVR) { + axlocal.rxbuf_overflow_count++; + READ_MACREG (RXCURT, rxcurt_ptr); + READ_MACREG (RXBOUND, rxbound_ptr); + PRINTK (INT_MSG, "ax88180: RX Buffer overflow! " + "count=%d, RXBOUND=0x%08lx, RXCURT=0x%08lx\n", + (int)axlocal.rxbuf_overflow_count, rxbound_ptr, + rxcurt_ptr); + + if (axlocal.rxbuf_overflow_count > 10) { + ax88180_mac_reset (); + axlocal.FirstTxDesc = TXDP0; + axlocal.NextTxDesc = TXDP0; + axlocal.rxbuf_overflow_count = 0; + } + } + + 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. */ +int eth_send (volatile void *packet, int length) +{ + volatile unsigned char *txdata; + unsigned long TXDES_addr; + unsigned long txcmd_txdp, txbs_txdp; + unsigned long tmp_data; + int i; + + if (axlocal.LinkState != INS_LINK_UP) { + return 0; + } + + txdata = (volatile unsigned char *)packet; + + axlocal.FirstTxDesc = axlocal.NextTxDesc; + txbs_txdp = 1 << axlocal.FirstTxDesc; + + READ_MACREG (TXBS, tmp_data); + READ_MACREG (TXBS, tmp_data); + PRINTK (TX_MSG, "ax88180: Checking available TXDP (TXBS=0x%08lx)\n", + tmp_data); + + /* check the available transmit descriptor */ + if (tmp_data & txbs_txdp) { + /* we should never get here. */ + /* we are running out of resource */ + return 0; + } + + PRINTK (TX_MSG, "ax88180: TXDP%d is available, i=%d\n", + (int)axlocal.FirstTxDesc, i); + + txcmd_txdp = axlocal.FirstTxDesc << 13; + TXDES_addr = TXDES0 + (axlocal.FirstTxDesc << 2); + + WRITE_MACREG (TXCMD, txcmd_txdp | length | TX_START_WRITE); + +#if defined (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 + 1) & TXDP_MASK; + + /* + Check the available transmit descriptor, if we had exhausted all + transmit descriptor ,then we have to wait for at least one free + descriptor + */ + txbs_txdp = 1 << axlocal.NextTxDesc; + READ_MACREG (TXBS, tmp_data); + if (tmp_data & txbs_txdp) { + if (ax88180_poll_tx_complete () < 0) { + ax88180_mac_reset (); + axlocal.FirstTxDesc = TXDP0; + axlocal.NextTxDesc = TXDP0; + printf ("ax88180: Transmit time out occurred!\n"); + } + } + + return 0; +} +#endif /* CONFIG_DRIVER_AX88180 */ + diff --git a/drivers/net/ax88180.h b/drivers/net/ax88180.h new file mode 100644 index 0000000..ae4b1b3 --- /dev/null +++ b/drivers/net/ax88180.h @@ -0,0 +1,415 @@ +/* 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 ENABLE_JUMBO 1 +#define DISABLE_JUMBO 0 + +#define ENABLE_BURST 1 +#define DISABLE_BURST 0 + +#define NORMAL_RX_MODE 0 +#define RX_LOOPBACK_MODE 1 +#define RX_INIFINIT_LOOP_MODE 2 +#define TX_INIFINIT_LOOP_MODE 3 + +#define DEFAULT_ETH_MTU 1500 + +/* Jumbo packet size 4086 bytes included 4 bytes CRC*/ +#define MAX_JUMBO_MTU 4072 + +/* Max Tx Jumbo size 4086 bytes included 4 bytes CRC */ +#define MAX_TX_JUMBO_SIZE 4086 + +/* Max Rx Jumbo size is 15K Bytes */ +#define MAX_RX_SIZE 0x3C00 + +#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 + +#define CMD_MAP_SIZE 0x100 + +#if defined (CONFIG_DRIVER_AX88180_16BIT) + #define AX88180_MEMORY_SIZE 0x00004000 + #define START_BASE 0x1000 + + #define RX_BUF_SIZE 0x1000 + #define TX_BUF_SIZE 0x0F00 + + #define TX_BASE START_BASE + #define CMD_BASE (TX_BASE + TX_BUF_SIZE) + #define RX_BASE (CMD_BASE + CMD_MAP_SIZE) +#else + #define AX88180_MEMORY_SIZE 0x00010000 + + #define RX_BUF_SIZE 0x8000 + #define TX_BUF_SIZE 0x7C00 + + #define RX_BASE 0x0000 + #define TX_BASE (RX_BASE + RX_BUF_SIZE) + #define CMD_BASE (TX_BASE + TX_BUF_SIZE) +#endif + +/* AX88180 Memory Mapping Definition */ +#define RXBUFFER_START RX_BASE + #define RX_PACKET_LEN_OFFSET 0 + #define RX_PAGE_NUM_MASK 0x7FF //RX pages 0~7FFh +#define TXBUFFER_START TX_BASE + +/* AX88180 MAC Register Definition */ +#define CMD (CMD_BASE + 0x0000) + #define WAKEMOD 0x00000001 + #define TXEN 0x00000100 + #define RXEN 0x00000200 + #define DEFAULT_CMD WAKEMOD +#define IMR (CMD_BASE + 0x0004) + #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_TX |\ + IMR_RXBUFFOVR | IMR_WATCHDOG) +#define ISR (CMD_BASE + 0x0008) + #define ISR_RXBUFFOVR 0x00000001 + #define ISR_WATCHDOG 0x00000002 + #define ISR_TX 0x00000008 + #define ISR_RX 0x00000010 + #define ISR_PHY 0x00000020 +#define TXCFG (CMD_BASE + 0x0010) + #define AUTOPAD_CRC 0x00000050 + #define DEFAULT_TXCFG AUTOPAD_CRC +#define TXCMD (CMD_BASE + 0x0014) + #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 (CMD_BASE + 0x0018) + #define TXDP0_USED 0x00000001 + #define TXDP1_USED 0x00000002 + #define TXDP2_USED 0x00000004 + #define TXDP3_USED 0x00000008 + #define DEFAULT_TXBS 0x00000000 +#define TXDES0 (CMD_BASE + 0x0020) + #define TXDPx_ENABLE 0x00008000 + #define TXDPx_LEN_MASK 0x00001FFF + #define DEFAULT_TXDES0 0x00000000 +#define TXDES1 (CMD_BASE + 0x0024) + #define TXDPx_ENABLE 0x00008000 + #define TXDPx_LEN_MASK 0x00001FFF + #define DEFAULT_TXDES1 0x00000000 +#define TXDES2 (CMD_BASE + 0x0028) + #define TXDPx_ENABLE 0x00008000 + #define TXDPx_LEN_MASK 0x00001FFF + #define DEFAULT_TXDES2 0x00000000 +#define TXDES3 (CMD_BASE + 0x002C) + #define TXDPx_ENABLE 0x00008000 + #define TXDPx_LEN_MASK 0x00001FFF + #define DEFAULT_TXDES3 0x00000000 +#define RXCFG (CMD_BASE + 0x0030) + #define RXBUFF_PROTECT 0x00000001 + #define RXTCPCRC_CHECK 0x00000010 + #define RXFLOW_ENABLE 0x00000100 + #define DEFAULT_RXCFG RXBUFF_PROTECT +#define RXCURT (CMD_BASE + 0x0034) + #define DEFAULT_RXCURT 0x00000000 +#define RXBOUND (CMD_BASE + 0x0038) + #define DEFAULT_RXBOUND 0x7FF //RX pages 0~7FFh +#define MACCFG0 (CMD_BASE + 0x0040) + #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 (CMD_BASE + 0x0044) + #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 CICADA_DEFAULT_MACCFG1 (RXCRC_CHECK | RXPAUSE_DA_CHECK) +#define MACCFG2 (CMD_BASE + 0x0048) + #define MACCFG2_BIT15_8 0x00000100 + #define JAM_LIMIT_MASK 0x000000FC + #define DEFAULT_JAM_LIMIT 0x00000064 + #define DEFAULT_MACCFG2 MACCFG2_BIT15_8 +#define MACCFG3 (CMD_BASE + 0x004C) + #define IPGR2_VAL 0x0000000E + #define IPGR1_VAL 0x00000600 + #define NOABORT 0x00008000 + #define DEFAULT_MACCFG3 (IPGR1_VAL | IPGR2_VAL) +#define TXPAUT (CMD_BASE + 0x0054) + #define DEFAULT_TXPAUT 0x001FE000 +#define RXBTHD0 (CMD_BASE + 0x0058) + #define DEFAULT_RXBTHD0 0x00000300 +#define RXBTHD1 (CMD_BASE + 0x005C) + #define DEFAULT_RXBTHD1 0x00000600 +#define RXFULTHD (CMD_BASE + 0x0060) + #define DEFAULT_RXFULTHD 0x00000100 +#define MISC (CMD_BASE + 0x0068) + /* Normal operation mode */ + #define MISC_NORMAL 0x00000003 + /* Clear bit 0 to reset MAC */ + #define MISC_RESET_MAC 0x00000002 + /* Clear bit 1 to reset PHY */ + #define MISC_RESET_PHY 0x00000001 + /* Clear bit 0 and 1 to reset MAC and PHY */ + #define MISC_RESET_MAC_PHY 0x00000000 + #define DEFAULT_MISC MISC_NORMAL +#define MACID0 (CMD_BASE + 0x0070) +#define MACID1 (CMD_BASE + 0x0074) +#define MACID2 (CMD_BASE + 0x0078) +#define TXLEN (CMD_BASE + 0x007C) + #define DEFAULT_TXLEN 0x000005FC +#define RXFILTER (CMD_BASE + 0x0080) + #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) +#define MDIOCTRL (CMD_BASE + 0x0084) + #define PHY_ADDR_MASK 0x0000001F + #define REG_ADDR_MASK 0x00001F00 + #define READ_PHY 0x00004000 + #define WRITE_PHY 0x00008000 +#define MDIODP (CMD_BASE + 0x0088) +#define GPIOCTRL (CMD_BASE + 0x008C) +#define RXINDICATOR (CMD_BASE + 0x0090) + #define RX_START_READ 0x00000001 + #define RX_STOP_READ 0x00000000 + #define DEFAULT_RXINDICATOR RX_STOP_READ +#define TXST (CMD_BASE + 0x0094) +#define MDCCLKPAT (CMD_BASE + 0x00A0) +#define RXIPCRCCNT (CMD_BASE + 0x00A4) +#define RXCRCCNT (CMD_BASE + 0x00A8) +#define TXFAILCNT (CMD_BASE + 0x00AC) +#define PROMDP (CMD_BASE + 0x00B0) +#define PROMCTRL (CMD_BASE + 0x00B4) + #define RELOAD_EEPROM 0x00000200 +#define MAXRXLEN (CMD_BASE + 0x00B8) +#define HASHTAB0 (CMD_BASE + 0x00C0) +#define HASHTAB1 (CMD_BASE + 0x00C4) +#define HASHTAB2 (CMD_BASE + 0x00C8) +#define HASHTAB3 (CMD_BASE + 0x00CC) +#define DOGTHD0 (CMD_BASE + 0x00E0) + #define DEFAULT_DOGTHD0 0x0000FFFF +#define DOGTHD1 (CMD_BASE + 0x00E4) + #define START_WATCHDOG_TIMER 0x00008000 + #define DEFAULT_DOGTHD1 0x00000FFF +#define SOFTRST (CMD_BASE + 0x00EC) + #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 + +/* Debug Message Display Level Definition */ +#define TX_MSG 0x0001 +#define RX_MSG 0x0002 +#define INT_MSG 0x0004 +#define DEBUG_MSG 0x0008 +#define NO_MSG 0x0000 +#define DEBUG_FLAGS (NO_MSG) + +#define PRINTK(flag, args...) if (flag & DEBUG_FLAGS) printf (args) + +/* + Access RXBUFFER_START/TXBUFFER_START to read RX buffer/write TX buffer +*/ +#if defined (CONFIG_DRIVER_AX88180_16BIT) +#define READ_RXBUF(data) \ + do { \ + data = *(volatile unsigned short *) \ + (AX88180_BASE + RXBUFFER_START); \ + } while (0) + +#define WRITE_TXBUF(data) \ + do { \ + *(volatile unsigned short *)(AX88180_BASE + TXBUFFER_START) \ + = data; \ + } while (0) + +#define READ_MACREG(regaddr, regdata) \ + do { \ + regdata = *(volatile unsigned short *) \ + (AX88180_BASE + regaddr); \ + } while (0) + +#define WRITE_MACREG(regaddr, regdata) \ + do { \ + *(volatile unsigned short*)(AX88180_BASE + regaddr) \ + = regdata; \ + } while (0) +#else +#define READ_RXBUF(data) \ + do { \ + data = *(volatile unsigned long *) \ + (AX88180_BASE + RXBUFFER_START); \ + } while (0) + +#define WRITE_TXBUF(data) \ + do { \ + *(volatile unsigned long *)(AX88180_BASE + TXBUFFER_START) \ + = data; \ + } while (0) + +#define READ_MACREG(regaddr, regdata) \ + do { \ + regdata = *(volatile unsigned long*)(AX88180_BASE + regaddr); \ + } while (0) + +#define WRITE_MACREG(regaddr, regdata) \ + do { \ + *(volatile unsigned long*)(AX88180_BASE + regaddr) \ + = regdata; \ + } while (0) +#endif /* end of CONFIG_DRIVER_AX88180_16BIT */ + +#endif /*end of CONFIG_DRIVER_AX88180 */