⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smsc9118.c

📁 SMSC LAN device linux Uboot code
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
//
// File name:      smsc9118.c
//
// Abstract:      Driver for SMSC LAN9118 ethernet controller.
//
// Start Automated RH
// *** Do not edit between "Start Automated RH" and "End Automated RH" ***
//
// Copyright 2005, Seagate Technology LLC
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that 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
//
// Revision History
//
// *** Do not edit between "Start Automated RH" and "End Automated RH" ***
// End Automated RH
//
//--------------------------------------------------------------------------
/*---------------------------------------------------------------------------
 * Copyright(c) 2005-2006 SMSC
 *
 *  Use of this source code is subject to the terms of the SMSC Software
 *  License Agreement (SLA) under which you licensed this software product.	 
 *  If you did not accept the terms of the SLA, you are not authorized to use
 *  this source code. 
 *  
 *  This code and information is provided as is without warranty of any kind,
 *  either expressed or implied, including but not limited to the implied
 *  warranties of merchantability and/or fitness for a particular purpose.
 *   
 *  File name   : smsc9118.c 
 *  Description : smsc9118 polled driver (non-interrupt driven)
 *  
 *  History	    :
 *  	09-27-06 MDG		v1.0 (First Release)
 *			modified for ARM platform
 *----------------------------------------------------------------------------*/

#include <common.h>
#include <command.h>
#include <config.h>
#include "smsc9118.h"
#include <net.h>

#ifdef CONFIG_DRIVER_SMSC9118

//*************************************************************************
 //  FUNCTION PROTOTYPES

//*************************************************************************
int	eth_init(bd_t *bd);
void eth_halt(void);
int	eth_rx(void);
int	eth_send(volatile void *packet, int length);
extern void *malloc( unsigned ); // <stdlib.h>
extern void free( void * ); // <stdlib.h>

//*************************************************************************
 //  LOCAL DEFINITIONS AND MACROS

//*************************************************************************
//#define	DEBUG
#define 	GPIO_OUT(val)	  		(*GPIO_CFG = ((*GPIO_CFG & ~GPIO_CFG_GPIOD_MSK) | (val & GPIO_CFG_GPIOD_MSK)))
#define 	ENET_MAX_MTU			PKTSIZE
#define 	ENET_MAX_MTU_ALIGNED	PKTSIZE_ALIGN
#define 	NUM_RX_BUFF 	  		PKTBUFSRX
#define		ENET_ADDR_LENGTH		6
#define		TX_TIMEOUT_COUNT		30	// waiting for TX_FIFO to drain


//*************************************************************************
 // GLOBAL DATA

//*************************************************************************
static const char date_code[] = BUILD_NUMBER;

static char * txbp; 				// TX buffer pointer (only 1 buffer)
static volatile char * rxbp[PKTBUFSRX];   // Receiver buffer queue (IP layers)
static struct rxQue rxAvlQue[PKTBUFSRX]; // Receive buffer available queue
static int rxNdx = 0;				// Current receive buffer index
static int rxNdxIn = 0; 			// Used for input
static int rxNdxOut = 0;			// Used for output to protocol layer
static ushort lastTxTag = 0x0;
static unsigned char macAddr[ENET_ADDR_LENGTH];

// Temp variables
//#ifdef		DEBUG
ulong MaxRxFifoSz;
ulong TotalInts = 0;
ulong TotalRXE = 0;
ulong TotalRxPackets = 0;
ulong TotalBytes = 0;
ulong EmptyReads = 0;

ulong RxPacketBuf[400];
ulong SWIntTriggered = FALSE;
ulong TotalRxDrop = 0;
ulong TotalPackets = 0;
ulong TotalWords = 0;
ulong TBLower1, TBLower2;
//#endif
// Temp variables


//*************************************************************************
 // EXTERNS

//*************************************************************************
#ifdef		DEBUG
extern int use_smsc9118;
#endif

static void lan9118_udelay(unsigned long delta)	// Arg is really microseconds
{
	const unsigned long	start = *FREE_RUN,	// Start timing
						usec = delta * (25000000/1000000);

	// usec adjusted for 25MHz on-chip clock, 1 microsecond (1/1000000) scaling
	do {
		delta = *FREE_RUN;
		if (delta >= start)
			delta = (delta - start);
		else
			delta = (delta - start) + 1;	// use 0x100000000, not 0xffffffff
	} while (delta < usec);
}

static int MacBusy(int ReqTO)
{
	  int timeout = ReqTO;
	  int RetVal = FALSE;	  // No timeout

	  while (timeout--) {
			if (!(*MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY)) {
				  goto done;
			}
	  }
	  RetVal = TRUE;		  // Timeout
done:
	  return (RetVal);
}

static ulong
GetMacReg(int Reg)
{
	  ulong RegVal = 0xffffffff;

	  if (*MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY) {
			LAN9118_WARN("GetMacReg: previous command not complete\n");
			goto done;
	  }

	  *MAC_CSR_CMD = MAC_RD_CMD(Reg);
	  DELAY(1);

	  if (MacBusy(MAC_TIMEOUT) == TRUE) {
			LAN9118_WARN("GetMacReg: timeout waiting for response "
				  "from MAC\n");
			goto done;
	  }

	  RegVal = *MAC_CSR_DATA;
done:
	  return (RegVal);
}

static int
PhyBusy(int ReqTO)
{
	  int timeout = ReqTO;
	  int RetVal = FALSE;	  // No timeout

	  while (timeout--) {
			if (!(GetMacReg(MAC_MIIACC) & MAC_MIIACC_MII_BUSY)) {
				  goto done;
			}
	  }

	  RetVal = TRUE;		  // Timeout
done:
	  return (RetVal);
}

static int
SetMacReg(int Reg, ulong Value)
{
	  int RetVal = FALSE;

	  if (*MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY) {
			LAN9118_WARN("SetMacReg: previous command not complete\n");
			goto done;
	  }

	  *MAC_CSR_DATA = Value;
	  DELAY(1);
	  *MAC_CSR_CMD = MAC_WR_CMD(Reg);
	  DELAY(1);

	  if (MacBusy(MAC_TIMEOUT) == TRUE) {
			LAN9118_WARN("SetMacReg: timeout waiting for response "
				  "from MAC\n");
				  goto done;
	  }

	  RetVal = TRUE;
done:
	  return (RetVal);
}

static ushort
GetPhyReg(unchar Reg)
{
	  ushort RegVal = 0xffff;

	  if (GetMacReg(MAC_MIIACC) & MAC_MIIACC_MII_BUSY) {
			LAN9118_WARN("GetPhyReg: MII busy\n");
			RegVal = 0;
			goto done;
	  }

	  SetMacReg(MAC_MIIACC, MAC_MII_RD_CMD((unchar)PHY_ADDR, Reg));
	  DELAY(1);

	  if (PhyBusy(PHY_TIMEOUT) == TRUE) {
			LAN9118_WARN("GetPhyReg: timeout waiting for MII command\n");
			goto done;
	  }

	  RegVal = (ushort)GetMacReg(MAC_MIIDATA);
done:
	  return (RegVal);
}

static int
SetPhyReg(unchar Reg, ushort Value)
{
	  int RetVal = FALSE;

	  if (GetMacReg(MAC_MIIACC) & MAC_MIIACC_MII_BUSY) {
			LAN9118_WARN("SetPhyReg: MII busy\n");
			goto done;
	  }

	  SetMacReg(MAC_MIIDATA, Value);
	  DELAY(1);
	  SetMacReg(MAC_MIIACC, MAC_MII_WR_CMD((unchar)PHY_ADDR, Reg));
	  DELAY(1);

	  if (PhyBusy(PHY_TIMEOUT) == TRUE) {
			LAN9118_WARN("SetPhyReg: timeout waiting for MII command\n");
			goto done;
	  }

	  RetVal = TRUE;
done:
	  return (RetVal);
}

// Display directly accessed, Control/Status Registers
static int
DumpCsrRegs(void)
{
	  printf("ID_REV:\t\t0x%0.8x\n", *ID_REV);
	  printf("IRQ_CFG:\t0x%0.8x\n", *IRQ_CFG);
	  printf("INT_STS:\t0x%0.8x\n", *INT_STS);
	  printf("INT_EN:\t\t0x%0.8x\n", *INT_EN);
	  printf("BYTE_TEST:\t0x%0.8x\n", *BYTE_TEST);
	  printf("FIFO_INT:\t0x%0.8x\n", *FIFO_INT);
	  printf("RX_CFG:\t\t0x%0.8x\n", *RX_CFG);
	  printf("TX_CFG:\t\t0x%0.8x\n", *TX_CFG);
	  printf("HW_CFG:\t\t0x%0.8x\n", *HW_CFG);
	  printf("RX_DP_CTL:\t0x%0.8x\n", *RX_DP_CTL);
	  printf("RX_FIFO_INF:\t0x%0.8x\n", *RX_FIFO_INF);
	  printf("TX_FIFO_INF:\t0x%0.8x\n", *TX_FIFO_INF);
	  printf("PWR_MGMT:\t0x%0.8x\n", *PWR_MGMT);
	  printf("GPIO_CFG:\t0x%0.8x\n", *GPIO_CFG);
	  printf("GPT_CFG:\t0x%0.8x\n", *GPT_CFG);
	  printf("GPT_CNT:\t0x%0.8x\n", *GPT_CNT);
	  printf("FPGA_REV:\t0x%0.8x\n", *FPGA_REV);
	  printf("ENDIAN:\t\t0x%0.8x\n", *ENDIAN);
	  printf("FREE_RUN\t0x%0.8x\n", *FREE_RUN);
	  printf("RX_DROP\t\t0x%0.8x\n", *RX_DROP);
	  printf("MAC_CSR_CMD\t0x%0.8x\n", *MAC_CSR_CMD);
	  printf("MAC_CSR_DATA\t0x%0.8x\n", *MAC_CSR_DATA);
	  printf("AFC_CFG\t\t0x%0.8x\n", *AFC_CFG);
	  return (0);
}

// Display Media Access Controller Registers
static int
DumpMacRegs(void)
{
	  printf("MAC_CR\t\t0x%0.8x\n", GetMacReg(MAC_CR));
	  printf("MAC_ADDRH\t0x%0.8x\n", GetMacReg(MAC_ADDRH));
	  printf("MAC_ADDRL\t0x%0.8x\n", GetMacReg(MAC_ADDRL));
	  printf("MAC_HASHH\t0x%0.8x\n", GetMacReg(MAC_HASHH));
	  printf("MAC_HASHL\t0x%0.8x\n", GetMacReg(MAC_HASHL));
	  printf("MAC_MIIACC\t0x%0.8x\n", GetMacReg(MAC_MIIACC));
	  printf("MAC_MIIDATA\t0x%0.8x\n", GetMacReg(MAC_MIIDATA));
	  printf("MAC_FLOW\t0x%0.8x\n", GetMacReg(MAC_FLOW));
	  printf("MAC_VLAN1\t0x%0.8x\n", GetMacReg(MAC_VLAN1));
	  printf("MAC_VLAN2\t0x%0.8x\n", GetMacReg(MAC_VLAN2));
	  printf("MAC_WUFF\t0x%0.8x\n", GetMacReg(MAC_WUFF));
	  printf("MAC_WUCSR\t0x%0.8x\n", GetMacReg(MAC_WUCSR));
	  return (0);
}
 
// Display PHYsical media interface registers
static int
DumpPhyRegs(void)
{
	  printf("PHY_BCR\t\t0x%0.4x\n", GetPhyReg(PHY_BCR));
	  printf("PHY_BSR\t\t0x%0.4x\n", GetPhyReg(PHY_BSR));
	  printf("PHY_ID1\t\t0x%0.4x\n", GetPhyReg(PHY_ID1));
	  printf("PHY_ID2\t\t0x%0.4x\n", GetPhyReg(PHY_ID2));
	  printf("PHY_ANAR\t0x%0.4x\n", GetPhyReg(PHY_ANAR));
	  printf("PHY_ANLPAR\t0x%0.4x\n", GetPhyReg(PHY_ANLPAR));
	  printf("PHY_ANEXPR\t0x%0.4x\n", GetPhyReg(PHY_ANEXPR));
	  printf("PHY_SILREV\t0x%0.4x\n", GetPhyReg(PHY_SILREV));
	  printf("PHY_MCSR\t0x%0.4x\n", GetPhyReg(PHY_MCSR));
	  printf("PHY_SPMODES\t0x%0.4x\n", GetPhyReg(PHY_SPMODES));
	  printf("PHY_CSIR\t0x%0.4x\n", GetPhyReg(PHY_CSIR));
	  printf("PHY_ISR\t\t0x%0.4x\n", GetPhyReg(PHY_ISR));
	  printf("PHY_IMR\t\t0x%0.4x\n", GetPhyReg(PHY_IMR));
	  printf("PHY_PHYSCSR\t0x%0.4x\n", GetPhyReg(PHY_PHYSCSR));
	  return (0);
}

static int
lan9118_open(bd_t *bis)
{
	  int RetVal = TRUE;
	  int timeout;
	  int i;

	  printf("DRIVER_VERSION : %X, ", DRIVER_VERSION);
	  printf("DATECODE : %s\r\n", BUILD_NUMBER);
#ifdef		DEBUG
	  TotalInts = 0;
	  TotalRXE = 0;
	  TotalBytes = 0;

	  if (bis->bi_bootflags & 0x40000000) {
			use_smsc9118 = 1;
	  }
#endif		//DEBUG

	  // Because we just came out of h/w reset we can't be sure that
	  // the chip has completed reset and may have to implement the
	  // workaround for Errata 5, stepping A0.	Therefore we need to
	  // check the ID_REV in little endian, the reset default.
	  if (((*ID_REV & ID_REV_ID_MASK) == ID_REV_CHIP_118) ||
	  	  ((*ID_REV & ID_REV_ID_MASK) == ID_REV_CHIP_218) ||
	  	   ((*ID_REV & ID_REV_ID_MASK) == ID_REV_CHIP_115) ||
	  	   	((*ID_REV & ID_REV_ID_MASK) == ID_REV_CHIP_215) ||
	  	  ) 
	  {
			printf("LAN9x18 (0x%08x) detected.\n", *ID_REV);
	  }
	  else
	  {
			printf("Failed to detect LAN9118. ID_REV = 0x%08x\n", *ID_REV);
		    RetVal = FALSE;
		    goto done;
	  }

	  // Does SoftReset to 118
	  *HW_CFG = HW_CFG_SRST;
	  DELAY(10);

	  // Is the internal PHY running?
	  if ((*PWR_MGMT & PWR_MGMT_PM_MODE_MSK) != 0) {
			// Apparently not...
			*BYTE_TEST = 0x0; // Wake it up
			DELAY(1);
			timeout = PHY_TIMEOUT;
			while (timeout-- && ((*PWR_MGMT & PWR_MGMT_PME_READY) == 0)) {
				  lan9118_udelay(1);
			}
			if ((*PWR_MGMT & PWR_MGMT_PME_READY) == 0) {
				  LAN9118_WARN("LAN9118: PHY not ready");
				  LAN9118_WARN(" - aborting\n");
				  RetVal = FALSE;
				  goto done;
			}
	  }

	  // Setup TX and RX resources.

	  // There is one TX buffer.
	  if ((txbp = (char *)malloc(ENET_MAX_MTU_ALIGNED)) == NULL) {
			LAN9118_WARN("lan9118_open: can't get TX buffer\n");
			goto cleanup;
	  }

	  // The receive buffers are allocated and aligned by upper layer
	  // software.
	  for (i = 0; i < PKTBUFSRX; i++) {
			rxbp[i] = NetRxPackets[i];
			rxAvlQue[i].index = -1;
	  }

	  rxNdx = 0;
	  rxNdxIn = 0;
	  rxNdxOut = 0;
	  lastTxTag = 0x0;

	  // Set TX Fifo Size
	  *HW_CFG = 0x00040000;   // 4K for TX

	  // This value is dependent on TX Fifo Size since there's a limited
	  // amount of Fifo space.
	  MaxRxFifoSz = 13440;			// Decimal

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -