All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Warren <bwarren@qstreams.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [PATCH][resubmit] AX88180: new gigabit network driver
Date: Wed, 02 Jul 2008 00:07:28 -0700	[thread overview]
Message-ID: <486B2930.30404@qstreams.com> (raw)
In-Reply-To: <003f01c8db64$76c343a0$0100a8c0@louis>

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 louis at 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 */
> +/*
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

  reply	other threads:[~2008-07-02  7:07 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-01 10:23 [U-Boot-Users] [PATCH][resubmit] AX88180: new gigabit network driver Louis
2008-07-02  7:07 ` Ben Warren [this message]
2008-07-02  7:49   ` Ben Warren
2008-07-02 11:29     ` Louis
2008-07-02 16:21       ` Ben Warren
2008-07-09  3:01         ` [U-Boot-Users] [resubmit] " Louis Su
2008-07-09  3:01           ` [U-Boot-Users] [PATCH] " Louis Su
2008-09-05 22:38             ` [U-Boot] " Wolfgang Denk
2008-09-06  3:18               ` Ben Warren
2008-09-06 23:32                 ` Wolfgang Denk
2008-10-12 22:02                 ` Wolfgang Denk
2008-10-13  3:51                   ` Ben Warren
2008-10-20  5:57                     ` Mike Frysinger
  -- strict thread matches above, loose matches on Subject: below --
2008-07-07  7:23 [U-Boot-Users] [PATCH] [resubmit]AX88180: " Louis Su

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=486B2930.30404@qstreams.com \
    --to=bwarren@qstreams.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.