📄 c6455_mdio-oldboard.c
字号:
/* ***********************************************************
* THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
* REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
* COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
* TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
* POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
* INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
* YOUR USE OF THE PROGRAM.
*
* IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
* THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
* OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
* EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
* REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
* OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
* USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
* AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
* YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
* (U.S.$500).
*
* Unless otherwise stated, the Program written and copyrighted
* by Texas Instruments is distributed as "freeware". You may,
* only under TI's copyright in the Program, use and modify the
* Program without any charge or restriction. You may
* distribute to third parties, provided that you transfer a
* copy of this license to the third party and the third party
* agrees to these terms by its first use of the Program. You
* must reproduce the copyright notice and any other legend of
* ownership on each copy or partial copy, of the Program.
*
* You acknowledge and agree that the Program contains
* copyrighted material, trade secrets and other TI proprietary
* information and is protected by copyright laws,
* international copyright treaties, and trade secret laws, as
* well as other intellectual property laws. To protect TI's
* rights in the Program, you agree not to decompile, reverse
* engineer, disassemble or otherwise translate any object code
* versions of the Program to a human-readable form. You agree
* that in no event will you alter, remove or destroy any
* copyright notice included in the Program. TI reserves all
* rights not specifically granted under this license. Except
* as specifically provided herein, nothing in this agreement
* shall be construed as conferring by implication, estoppel,
* or otherwise, upon you, any license or other right under any
* TI patents, copyrights or trade secrets.
*
* You may not use the Program in non-TI devices.
* ********************************************************* */
/*****************************************************************************\
* Copyright (C) 1999-2003 Texas Instruments Incorporated.
* All Rights Reserved
*------------------------------------------------------------------------------
* FILENAME...... c6455_mdio.c
* DATE CREATED.. 12/09/2005 - ported to c6455
* LAST MODIFIED.
*------------------------------------------------------------------------------
* NOTE:
* When used in an multitasking environment, no MDIO function may be
* called while another MDIO function is operating on the same device
* handle in another thread. It is the responsibility of the application
* to assure adherence to this restriction.
*
\******************************************************************************/
/* Include the MDIO header file */
#include <c6455_mdio.h>
/*
* Standard defines/assumptions for MDIO interface
*/
#define VBUSCLK 165
/*-----------------------------------------------------------------------*\
* PHY Control Registers
*
* Used by MDIO to configure a MII compliant PHY
\*-----------------------------------------------------------------------*/
#define PHYREG_CONTROL 0
#define PHYREG_CONTROL_RESET (1<<15)
#define PHYREG_CONTROL_LOOPBACK (1<<14)
#define PHYREG_CONTROL_SPEEDLSB (1<<13)
#define PHYREG_CONTROL_AUTONEGEN (1<<12)
#define PHYREG_CONTROL_POWERDOWN (1<<11)
#define PHYREG_CONTROL_ISOLATE (1<<10)
#define PHYREG_CONTROL_AUTORESTART (1<<9)
#define PHYREG_CONTROL_DUPLEXFULL (1<<8)
#define PHYREG_CONTROL_SPEEDMSB (1<<6)
#define PHYREG_STATUS 1
#define PHYREG_STATUS_FD100 (1<<14)
#define PHYREG_STATUS_HD100 (1<<13)
#define PHYREG_STATUS_FD10 (1<<12)
#define PHYREG_STATUS_HD10 (1<<11)
#define PHYREG_STATUS_EXTSTATUS (1<<8)
#define PHYREG_STATUS_NOPREAMBLE (1<<6)
#define PHYREG_STATUS_AUTOCOMPLETE (1<<5)
#define PHYREG_STATUS_REMOTEFAULT (1<<4)
#define PHYREG_STATUS_AUTOCAPABLE (1<<3)
#define PHYREG_STATUS_LINKSTATUS (1<<2)
#define PHYREG_STATUS_JABBER (1<<1)
#define PHYREG_STATUS_EXTENDED (1<<0)
#define PHYREG_ID1 2
#define PHYREG_ID2 3
#define PHYREG_ADVERTISE 4
#define PHYREG_ADVERTISE_NEXTPAGE (1<<15)
#define PHYREG_ADVERTISE_FAULT (1<<13)
#define PHYREG_ADVERTISE_PAUSE (1<<10)
#define PHYREG_ADVERTISE_FD100 (1<<8)
#define PHYREG_ADVERTISE_HD100 (1<<7)
#define PHYREG_ADVERTISE_FD10 (1<<6)
#define PHYREG_ADVERTISE_HD10 (1<<5)
#define PHYREG_ADVERTISE_MSGMASK (0x1F)
#define PHYREG_ADVERTISE_MSG (1)
#define PHYREG_PARTNER 5
#define PHYREG_PARTNER_NEXTPAGE (1<<15)
#define PHYREG_PARTNER_ACK (1<<14)
#define PHYREG_PARTNER_FAULT (1<<13)
#define PHYREG_PARTNER_PAUSE (1<<10)
#define PHYREG_PARTNER_FD100 (1<<8)
#define PHYREG_PARTNER_HD100 (1<<7)
#define PHYREG_PARTNER_FD10 (1<<6)
#define PHYREG_PARTNER_HD10 (1<<5)
#define PHYREG_PARTNER_MSGMASK (0x1F)
#define PHYREG_1000CONTROL 9
#define PHYREG_ADVERTISE_FD1000 (1<<9)
#define PHYREG_1000STATUS 0xA
#define PHYREG_PARTNER_FD1000 (1<<11)
#define PHYREG_EXTSTATUS 0x0F
#define PHYREG_EXTSTATUS_FD1000 (1<<13)
#define PHYREG_SHADOW 0x18
#define PHYREG_SHADOW_EXTLOOPBACK 0x8400
#define PHYREG_SHADOW_RGMIIMODE 0xF080
#define PHYREG_SHADOW_INBAND 0xF1C7
#define PHYREG_ACCESS 0x1C
#define PHYREG_ACCESS_COPPER 0xFC00
/*-----------------------------------------------------------------------*\
* PHY State Machine
*
* When using auto-negotiation, the software must keep the MAC in
* sync with the PHY (for duplex). This module will also attempt to
* "auto-select" the PHY from a potential list of 32 based on which is
* first to get a link.
*
* On detection of a good link, the link speed and duplex settings will be
* used to update the EMAC configuration (done external to this module).
\*-----------------------------------------------------------------------*/
/* States in the PHY State Machine */
#define PHYSTATE_MDIOINIT 0
#define PHYSTATE_RESET 1
#define PHYSTATE_NWAYSTART 2
#define PHYSTATE_NWAYWAIT 3
#define PHYSTATE_LINKWAIT 4
#define PHYSTATE_LINKED 5
/*
// Tick counts for timeout of each state
// Note that NWAYSTART falls through to NWAYWAIT which falls through
// to LINKWAIT. The timeout is not reset progressing from one state
// to the next, so the system has 5 seconds total to find a link.
*/
static uint PhyStateTimeout[] = { 2, /* PHYSTATE_MDIOINIT - min-delay */
6, /* PHYSTATE_RESET - 0.5 sec max */
41, /* PHYSTATE_NWAYSTART - 4 seconds */
41, /* PHYSTATE_NWAYWAIT - 4 seconds */
51, /* PHYSTATE_LINKWAIT - 5 seconds */
0 };/* PHYSTATE_LINKED - no timeout*/
typedef struct _MDIO_Device {
uint ModeFlags; /* User specified configuration flags */
uint phyAddr; /* Current (or next) PHY addr (0-31) */
uint phyState; /* PHY State */
uint phyStateTicks; /* Ticks elapsed in this PHY state */
uint PendingStatus; /* Pending Link Status */
uint LinkStatus; /* Link State PHYREG_STATUS_LINKSTATUS */
} MDIO_Device;
static void MDIO_initStateMachine( MDIO_Device *pd );
static uint MDIO_initContinue( MDIO_Device *pd );
Uint32 macsel = 0;
/*-----------------------------------------------------------------------*\
* MDIO_initStateMachine()
*
* Internal function to initialize the state machine. It is referred to
* often in the code as it is called in case of a PHY error
\*-----------------------------------------------------------------------*/
static void MDIO_initStateMachine( MDIO_Device *pd )
{
/* Setup the state machine defaults */
pd->phyAddr = 0; /* The next PHY to try */
pd->phyState = PHYSTATE_MDIOINIT; /* PHY State */
pd->phyStateTicks = 0; /* Ticks elapsed */
pd->LinkStatus = MDIO_LINKSTATUS_NOLINK;
}
/*-----------------------------------------------------------------------*\
* MDIO_open()
*
* Opens the MDIO peripheral and start searching for a PHY device.
*
* It is assumed that the MDIO module is reset prior to calling this
* function.
\*-----------------------------------------------------------------------*/
Handle MDIO_open( uint mdioModeFlags )
{
/*
// Note: In a multi-instance environment, we'd have to allocate "localDev"
*/
static MDIO_Device localDev;
/* Find out what interface we are working with */
macsel = CSL_FEXT(DEV_REGS->DEVSTAT, DEV_DEVSTAT_MACSEL);
/* Get the mode flags from the user - clear our reserved flag */
localDev.ModeFlags = mdioModeFlags & ~MDIO_MODEFLG_NWAYACTIVE;
/* Setup the MDIO state machine */
MDIO_initStateMachine( &localDev );
/* Enable MDIO and setup divider */
MDIO_REGS->CONTROL = CSL_FMKT(MDIO_CONTROL_ENABLE,YES) |
CSL_FMK(MDIO_CONTROL_CLKDIV,VBUSCLK) ;
/* We're done for now - all the rest is done via MDIO_event() */
return( &localDev );
}
/*-----------------------------------------------------------------------*\
* MDIO_close()
*
* Close the MDIO peripheral and disable further operation.
\*-----------------------------------------------------------------------*/
void MDIO_close( Handle hMDIO )
{
Uint32 ltmp1;
uint i;
(void)hMDIO;
/*
// We really don't care what state anything is in at this point,
// but to be safe, we'll isolate all the PHY devices.
*/
ltmp1 = MDIO_REGS->ALIVE;
for( i=0; ltmp1; i++,ltmp1>>=1 )
{
if( ltmp1 & 1 )
{
PHYREG_write( PHYREG_CONTROL, i, PHYREG_CONTROL_ISOLATE |
PHYREG_CONTROL_POWERDOWN );
PHYREG_wait();
}
}
}
/*-----------------------------------------------------------------------*\
* MDIO_getStatus()
*
* Called to get the status of the MDIO/PHY
\*-----------------------------------------------------------------------*/
void MDIO_getStatus( Handle hMDIO, uint *pPhy, uint *pLinkStatus )
{
MDIO_Device *pd = (MDIO_Device *)hMDIO;
if( pPhy )
*pPhy = pd->phyAddr;
if( pLinkStatus )
*pLinkStatus = pd->LinkStatus;
}
/*-----------------------------------------------------------------------*\
* MDIO_timerTick()
*
* Called to signify that approx 100mS have elapsed
*
* Returns an MDIO event code (see MDIO Events in C6455_MDIO.H).
\*-----------------------------------------------------------------------*/
uint MDIO_timerTick( Handle hMDIO )
{
MDIO_Device *pd = (MDIO_Device *)hMDIO;
Uint16 tmp1,tmp2,tmp1gig = 0, tmp2gig = 0, ack;
Uint32 ltmp1 = 0;
uint RetVal = MDIO_EVENT_NOCHANGE;
/*
// If we are linked, we just check to see if we lost link. Otherwise;
// we keep treking through our state machine.
*/
if( pd->phyState == PHYSTATE_LINKED )
{
/*
// Here we check for a "link-change" status indication or a link
// down indication.
*/
ltmp1 = MDIO_REGS->LINKINTRAW & 1;
MDIO_REGS->LINKINTRAW = ltmp1;
if( ltmp1 || !(MDIO_REGS->LINK)&(1<<pd->phyAddr) )
{
/*
// There has been a change in link (or it is down)
// If we do not auto-neg, then we just wait for a new link
// Otherwise, we enter NWAYSTART or NWAYWAIT
*/
pd->LinkStatus = MDIO_LINKSTATUS_NOLINK;
RetVal = MDIO_EVENT_LINKDOWN;
pd->phyStateTicks = 0; /* Reset timeout */
/* If not NWAY, just wait for link */
if( !(pd->ModeFlags & MDIO_MODEFLG_NWAYACTIVE) )
pd->phyState = PHYSTATE_LINKWAIT;
else
{
/* Handle NWAY condition */
/* First see if link is really down */
PHYREG_read( PHYREG_STATUS, pd->phyAddr );
PHYREG_wait();
PHYREG_read( PHYREG_STATUS, pd->phyAddr );
PHYREG_waitResultsAck( tmp1, ack );
if( !ack )
{
/* No PHY response, maybe it was unplugged */
MDIO_initStateMachine( pd );
}
else if( !(tmp1 & PHYREG_STATUS_LINKSTATUS) )
{
/* No Link - restart NWAY */
pd->phyState = PHYSTATE_NWAYSTART;
PHYREG_write( PHYREG_CONTROL, pd->phyAddr,
PHYREG_CONTROL_AUTONEGEN |
PHYREG_CONTROL_AUTORESTART );
PHYREG_wait();
}
else
{
/* We have a Link - re-read NWAY params */
pd->phyState = PHYSTATE_NWAYWAIT;
}
}
}
}
/*
// If running in a non-linked state, execute the next
// state of the state machine.
*/
if( pd->phyState != PHYSTATE_LINKED )
{
/* Bump the time counter */
pd->phyStateTicks++;
/* Process differently based on state */
switch( pd->phyState )
{
case PHYSTATE_RESET:
/* Don't try to read reset status for the first 100 to 200 ms */
if( pd->phyStateTicks < 2 )
break;
/* See if the PHY has come out of reset */
PHYREG_read( PHYREG_CONTROL, pd->phyAddr );
PHYREG_waitResultsAck( tmp1, ack );
if( ack && !(tmp1 & PHYREG_CONTROL_RESET) )
{
/* PHY is not reset. If the PHY init is going well, break out */
if( MDIO_initContinue( pd ) )
break;
/* Else, this PHY is toast. Manually trigger a timeout */
pd->phyStateTicks = PhyStateTimeout[pd->phyState];
}
/* Fall through to timeout check */
case PHYSTATE_MDIOINIT:
CheckTimeout:
/* Here we just check timeout and try to find a PHY */
if( pd->phyStateTicks >= PhyStateTimeout[pd->phyState] )
{
// Try the next PHY if anything but a MDIOINIT condition
if( pd->phyState != PHYSTATE_MDIOINIT )
if( ++pd->phyAddr == 32 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -