📄 eth_smsc911x.c
字号:
#include <arch/eth.h>#include <target/io.h>#include <target/mem.h>#include <target/memzero.h>#include <target/net/eth.h>#include <target/net/eth_util.h>#include "eth_smsc911x.h"#include "board.h"#if defined(DEBUG_ETH)#define DEBUG_SMSC911X#endif#if defined(DEBUG_SMSC911X)#define DEBUG_EN_TRACE#define DEBUG_EN_WARNING#define DEBUG_EN_TESTCODE#endif#if defined(DEBUG_EN_TRACE)#define SMSC_TRACE(msg, args...) hprintf("SMSC: " msg "\n", ## args)#else#define SMSC_TRACE(msg, args...)#endif#if defined(DEBUG_EN_WARNING)#define SMSC_WARNING(msg, args...) SMSC_TRACE(msg, ## args)#else#define SMSC_WARNING(msg, args...)#endif#define SMSC_ASSERT(condition)#define TRUE ((BOOLEAN)1)#define FALSE ((BOOLEAN)0)#define HIBYTE(word) ((BYTE)(((WORD)(word))>>8))#define LOBYTE(word) ((BYTE)(((WORD)(word))&0x00FFU))#define HIWORD(dWord) ((WORD)(((DWORD)(dWord))>>16))#define LOWORD(dWord) ((WORD)(((DWORD)(dWord))&0x0000FFFFUL))#define ENODEV 1#define udelay(x) ({volatile int t=50;while(t){t--;};})#define mdelay(x) ({volatile int t=50000;while(t){t--;};})PRIVATE_DATA _privateData;PPRIVATE_DATA privateData = &_privateData;PLATFORM_DATA _platformData;PPLATFORM_DATA platformData = &_platformData;unsigned char *EthTxBuffer = (unsigned char *)0x80000000;unsigned char *EthRxBuffer = (unsigned char *)0x80100000;#define MIN_PACKET_SIZE 60#define OLD_REGISTERS(privData) \ (((privData->dwIdRev&0x0000FFFFUL)==0UL)&& \ ((privData->dwFpgaRev)>=0x01)&& \ ((privData->dwFpgaRev)<=0x25))/************************************************************************* * *************************************************************************/inline void Platform_SetRegDW(DWORD dwLanBase, DWORD dwOffset, DWORD dwVal){#if REVA *(volatile u16 *)((dwLanBase) + ((dwOffset) << 1)) = ((dwVal) & 0xffff); *(volatile u16 *)((dwLanBase) + (((dwOffset) + 2) << 1)) = (((dwVal)>>16) & 0xffff);#else (*(volatile DWORD *)(dwLanBase+dwOffset))=dwVal;#endif}/************************************************************************* * *************************************************************************/inline DWORD Platform_GetRegDW(DWORD dwLanBase, DWORD dwOffset){#if REVA u32 val; val = (*(volatile u16 *)((dwLanBase) + ((dwOffset)<<1))) | ((*(volatile u16 *)((dwLanBase) + (((dwOffset) + 2)<<1)))<<16); return val;#else return (*(volatile DWORD *)(dwLanBase+dwOffset));#endif}/************************************************************************* * *************************************************************************/#include <mx3/ioregs.h>#include <target/htypes.h>static voideth_armadillo5x0_init(void){ mxc_set_mux(MUX_PIN(GPIO1_0), MUX_O_GPIO | MUX_I_GPIO); mxc_set_mux(MUX_PIN(GPIO1_1), MUX_O_GPIO | MUX_I_GPIO); mxc_set_mux(MUX_PIN(CS3), MUX_O_FUNC | MUX_I_FUNC);}DWORDPlatform_Initialize(PPLATFORM_DATA platformData, DWORD dwLanBase,DWORD dwBusWidth){ DWORD mode=0; DWORD test=0; platformData->dwBitWidth=0; platformData->dwIdRev=0; SMSC_TRACE("--> Platform_Initialize()"); eth_armadillo5x0_init(); if(dwLanBase==0x0UL) { dwLanBase=LAN_CSBASE; SMSC_TRACE("Using dwLanBase==%p",dwLanBase); } if(dwLanBase!=LAN_CSBASE) { SMSC_WARNING("PlatformInitialize: resetting dwLanBase from %p to %p", dwLanBase, LAN_CSBASE); dwLanBase=LAN_CSBASE; }#if defined(CONFIG_SUZAKU) /* need to access register before it'll sets endian. */ *(volatile unsigned long *) (dwLanBase+BYTE_TEST); /* Endian Register */ *(volatile unsigned long *) (dwLanBase+ENDIAN) = 0xffffffff;#endif switch(dwBusWidth) { case 16: mode=2; platformData->dwBitWidth=16; test = Platform_GetRegDW(dwLanBase, BYTE_TEST); if(test==0x87654321) { SMSC_TRACE(" 16 bit mode assigned and verified"); } else { SMSC_WARNING(" failed to verify assigned 16 bit mode"); dwLanBase=0; };break; case 32: mode=1; platformData->dwBitWidth=32; test = Platform_GetRegDW(dwLanBase, BYTE_TEST); if(test==0x87654321) { SMSC_TRACE(" 32 bit mode assigned and verified"); } else { SMSC_WARNING(" failed to verify assigned 32 bit mode"); dwLanBase=0; };break; default: mode=1; platformData->dwBitWidth=32; { WORD dummy=0; test = Platform_GetRegDW(dwLanBase, BYTE_TEST); dummy = Platform_GetRegDW(dwLanBase, BYTE_TEST); if(test==0x87654321UL) { SMSC_TRACE(" 32 bit mode detected"); } else { SMSC_TRACE(" 32 bit mode not detected, test=%p",test); platformData->dwBitWidth=16; test = Platform_GetRegDW(dwLanBase, BYTE_TEST); if(test==0x87654321UL) { SMSC_TRACE(" 16 bit mode detected"); mode=2; } else { SMSC_WARNING(" neither 16 nor 32 bit mode detected."); dwLanBase=0; } } dummy=dummy;/* make lint happy */ };break; } if(dwLanBase!=0) { DWORD idRev = Platform_GetRegDW(dwLanBase, ID_REV); platformData->dwIdRev=idRev; switch(idRev&0xFFFF0000) { case 0x01180000UL: case 0x01170000UL: case 0x01120000UL: switch(mode) { case 1:/* 32 bit mode */ platformData->dwBitWidth=32; break; case 2:/* 16 bit mode */ platformData->dwBitWidth=16; break; default: break;/* make lint happy */ }; break; default: break;/* make lint happy */ } } SMSC_TRACE("<-- Platform_Initialize()"); return dwLanBase;}/************************************************************************* * *************************************************************************/#if defined(CONFIG_SUZAKU)static inline unsigned long __dword_swap(unsigned long v){ unsigned long _v; _v = ((v & 0x000000ff) << 24); _v |= ((v & 0x0000ff00) << 8); _v |= ((v & 0x00ff0000) >> 8); _v |= ((v & 0xff000000) >> 24); return _v;}#endif/************************************************************************* * *************************************************************************/static void Platform_WriteFifo(DWORD dwLanBase, DWORD *pdwBuf, DWORD dwDwordCount){ volatile DWORD *pdwReg;#if !REVA pdwReg = (volatile DWORD *)(dwLanBase+TX_DATA_FIFO);#endif while(dwDwordCount) {#if defined(CONFIG_SUZAKU) *pdwReg = __dword_swap(*pdwBuf++);#else#if !REVA *pdwReg = *pdwBuf++;#else /*a500 rev.a*/ Platform_SetRegDW(dwLanBase, TX_DATA_FIFO, *pdwBuf++);#endif#endif dwDwordCount--; }}/************************************************************************* * *************************************************************************/static void Platform_ReadFifo(DWORD dwLanBase, DWORD *pdwBuf, DWORD dwDwordCount){#if !REVA const volatile DWORD * const pdwReg = (const volatile DWORD * const)(dwLanBase+RX_DATA_FIFO);#else /*a500 rev.a*/ const volatile DWORD * const pdwReg = (const volatile DWORD * const)(dwLanBase+(RX_DATA_FIFO<<1));#endif while (dwDwordCount) {#if defined(DEBUG_EN_TESTCODE) if(!(Lan_GetRegDW(RX_FIFO_INF) & RX_FIFO_INF_RXDUSED_)){ SMSC_WARNING("RX_DATA_FIFO underrun\n"); }#endif#if defined(CONFIG_SUZAKU) *pdwBuf++ = __dword_swap(*pdwReg);#else#if !REVA *pdwBuf++ = *pdwReg;#else *pdwBuf++ = Platform_GetRegDW(dwLanBase, RX_DATA_FIFO);#endif#endif dwDwordCount--; }}/************************************************************************* * *************************************************************************/static BOOLEANMacNotBusy(PPRIVATE_DATA privateData, int dummy){ int i=0; /* wait for MAC not busy, w/ timeout */ for(i=0;i<40;i++) { if((Lan_GetRegDW(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY_)==(0UL)) { return TRUE; } } SMSC_WARNING("timeout waiting for MAC not BUSY. MAC_CSR_CMD = %p", Lan_GetRegDW(MAC_CSR_CMD)); return FALSE;}/************************************************************************* * *************************************************************************/static DWORD Mac_GetRegDW(PPRIVATE_DATA privateData,DWORD dwRegOffset){ DWORD result=0xFFFFFFFFUL; DWORD dwTemp=0; /* wait until not busy */ if (Lan_GetRegDW(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY_) { SMSC_WARNING("Mac_GetRegDW() failed, MAC already busy at entry"); goto DONE; } /* send the MAC Cmd w/ offset */ Lan_SetRegDW(MAC_CSR_CMD, ((dwRegOffset & 0x000000FFUL) | MAC_CSR_CMD_CSR_BUSY_ | MAC_CSR_CMD_R_NOT_W_)); dwTemp=Lan_GetRegDW(BYTE_TEST);/* to flush previous write */ dwTemp=dwTemp; /* wait for the read to happen, w/ timeout */ if (!MacNotBusy(privateData,0)) { SMSC_WARNING("Mac_GetRegDW() failed, waiting for MAC not busy after read"); goto DONE; } else { /* finally, return the read data */ result=Lan_GetRegDW(MAC_CSR_DATA); }DONE: return result;}/************************************************************************* * *************************************************************************/static void Mac_SetRegDW(PPRIVATE_DATA privateData,DWORD dwRegOffset,DWORD dwVal){ DWORD dwTemp=0; if (Lan_GetRegDW(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY_) { SMSC_WARNING("Mac_SetRegDW() failed, MAC already busy at entry"); goto DONE; } /* send the data to write */ Lan_SetRegDW(MAC_CSR_DATA,dwVal); /* do the actual write */ Lan_SetRegDW(MAC_CSR_CMD,((dwRegOffset & 0x000000FFUL) | MAC_CSR_CMD_CSR_BUSY_)); dwTemp=Lan_GetRegDW(BYTE_TEST);/* force flush of previous write */ dwTemp=dwTemp; /* wait for the write to complete, w/ timeout */ if (!MacNotBusy(privateData,0)) { SMSC_WARNING("Mac_SetRegDW() failed, waiting for MAC not busy after write"); }DONE: return;}/************************************************************************* * *************************************************************************/static WORD Phy_GetRegW(PPRIVATE_DATA privateData,DWORD dwRegIndex){ DWORD dwAddr=0; int i=0; WORD result=0xFFFFU; SMSC_ASSERT(privateData!=NULL); SMSC_ASSERT(privateData->LanInitialized==TRUE); SMSC_ASSERT(Vl_CheckLock(&(privateData->MacPhyLock),0)); /* confirm MII not busy */ if ((Mac_GetRegDW(privateData, MII_ACC) & MII_ACC_MII_BUSY_) != 0UL) { SMSC_WARNING("MII is busy in Phy_GetRegW???"); result=0; goto DONE; } /* set the address, index & direction (read from PHY) */ dwAddr = ((privateData->dwPhyAddress&0x1FUL)<<11) | ((dwRegIndex & 0x1FUL)<<6); Mac_SetRegDW(privateData, MII_ACC, dwAddr); /* wait for read to complete w/ timeout */ for(i=0;i<100;i++) { /* see if MII is finished yet */ if ((Mac_GetRegDW(privateData, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL) { /* get the read data from the MAC & return i */ result=((WORD)Mac_GetRegDW(privateData, MII_DATA)); goto DONE; } } SMSC_WARNING("timeout waiting for MII write to finish");DONE: return result;}/************************************************************************* * *************************************************************************/static void Phy_SetRegW(PPRIVATE_DATA privateData,DWORD dwRegIndex,WORD wVal){ DWORD dwAddr=0; int i=0; SMSC_ASSERT(privateData!=NULL); SMSC_ASSERT(privateData->LanInitialized==TRUE); SMSC_ASSERT(Vl_CheckLock(&(privateData->MacPhyLock),0)); if(dwRegIndex==0) { if((wVal&0x1200)==0x1200) { privateData->wLastADVatRestart=privateData->wLastADV; } } if(dwRegIndex==4) { privateData->wLastADV=wVal; } /* confirm MII not busy */ if ((Mac_GetRegDW(privateData, MII_ACC) & MII_ACC_MII_BUSY_) != 0UL) { SMSC_WARNING("MII is busy in Phy_SetRegW???"); goto DONE; } /* put the data to write in the MAC */ Mac_SetRegDW(privateData, MII_DATA, (DWORD)wVal); /* set the address, index & direction (write to PHY) */ dwAddr = ((privateData->dwPhyAddress&0x1FUL)<<11) | ((dwRegIndex & 0x1FUL)<<6) | MII_ACC_MII_WRITE_; Mac_SetRegDW(privateData, MII_ACC, dwAddr); /* wait for write to complete w/ timeout */ for(i=0;i<100;i++) { /* see if MII is finished yet */ if ((Mac_GetRegDW(privateData, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL) { goto DONE; } } SMSC_WARNING("timeout waiting for MII write to finish");DONE: return;}/************************************************************************* * *************************************************************************/static DWORD Phy_LBT_GetTxStatus(PPRIVATE_DATA privateData){ DWORD result=Lan_GetRegDW(TX_FIFO_INF); if(OLD_REGISTERS(privateData)) { result&=TX_FIFO_INF_TSFREE_; if(result!=0x00800000UL) { result=Lan_GetRegDW(TX_STATUS_FIFO); } else { result=0; } } else { result&=TX_FIFO_INF_TSUSED_; if(result!=0x00000000UL) { result=Lan_GetRegDW(TX_STATUS_FIFO); } else { result=0; } } return result;}/************************************************************************* * *************************************************************************/#if defined(DEBUG_EN_TESTCODE)static BOOLEAN Phy_TransmitTestPacket(PPRIVATE_DATA privateData){ BYTE LoopBackTxPacket[70]; BOOLEAN result=FALSE; DWORD dwLoopCount=0; DWORD dwTxCmdA=0; DWORD dwTxCmdB=0; DWORD dwStatus=0; /* write Tx Packet to 118 */ dwTxCmdA= ((((DWORD)(LoopBackTxPacket))&0x03UL)<<16) | /* DWORD alignment adjustment */ TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ | ((DWORD)(MIN_PACKET_SIZE)); dwTxCmdB= (((DWORD)(MIN_PACKET_SIZE))<<16) | ((DWORD)(MIN_PACKET_SIZE)); Lan_SetRegDW(TX_DATA_FIFO,dwTxCmdA); Lan_SetRegDW(TX_DATA_FIFO,dwTxCmdB);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -