Louis, This submission has several style issues. I suggest you read this: http://www.denx.de/wiki/UBoot/CodingStyle
Louis wrote: > Resubmit the driver for the ASIX AX88180 gigabit ethernet chip. > > Signed-off-by: Louis Su [EMAIL PROTECTED] > --- > 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 */ > +/* Multi-line comments are done like: /* * Comment */ > + 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 This is unnecessary. You're already compiling conditionally in Makefile > + > +/* > +=========================================================================== > > +<<<<<< 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); Indentation with TABs, 8 characters wide. > +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; > + Again, serious indentation problems. I won't mention it again. > +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"); We don't need yet another way to print debug information. Please use debug() or printf() only. > + for (i = 0xFC00; i <= 0xFCFF; i += 4) { > + READ_MACREG (i, tmpval); > + PRINTK (DEBUG_MSG, "0x%04x=0x%08lx ", i, tmpval); > + if ((i & 0xF) == 0xC) This is a silly obfuscated way of saying 'if (i%12 == 0)' > + 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) I think you mean to call this 'media_config'. Several function names are misspelled this way. > +{ > + 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: Please don't put default first. I'm sure it compiles correctly, but looks awkward. > + 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 >>>>>> > +=========================================================================== > Please don't do things this way. Only one function should be exported globally, something like: int ax88180_initialize(bd_t *bis) This function should fill in a 'struct eth_device' with init(), halt(), send() and recv() function pointers, and register the struct. There are many examples in the source tree of drivers that do this properly. > +*/ > +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 > + Unnecessary #ifdef. You should have a #ifdef guard around this file, though, as with all header files. > +#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 > + s/INIFINIT/INFINITE/ > +#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 > + <snip> > > + > +/* 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) > + As I mentioned earlier, please get rid of this and use debug() instead. > +/* > + 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) > + This macro is evil. There's no reason why you need to pass the return varible when the following will do: #define Read_Rx_buf(addr) *(volatile unsigned short *)(AX88180_base + (addr)) val = Read_Rx_buf(RXBUFFER_START); Also, please don't use ALL_CAPS names. > +#define WRITE_TXBUF(data) \ > + do { \ > + *(volatile unsigned short *)(AX88180_BASE + TXBUFFER_START) \ > + = data; \ > + } while (0) > + In this case, the do{...}while(0) is unnecessary. Just make the assignment. > +#define READ_MACREG(regaddr, regdata) \ > + do { \ > + regdata = *(volatile unsigned short *) \ > + (AX88180_BASE + regaddr); \ > + } while (0) > + Here, regdata shouldn't be in the macro. I think you get the idea... > +#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) > + I know you wrote your macros this way because you want to support different bus widths, but there are cleaner ways of doing it. > +#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 */ Please clean up the issues and re-submit. regards, Ben ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ U-Boot-Users mailing list U-Boot-Users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/u-boot-users