📄 c6455_mdio.c
字号:
if( pd->phyState != PHYSTATE_MDIOINIT )
if( ++pd->phyAddr == 32 )
pd->phyAddr = 0;
ltmp1 = MDIO_REGS->ALIVE;
for( tmp1=0; tmp1<32; tmp1++ )
{
if( ltmp1 & (1<<pd->phyAddr) )
{
if( MDIO_initPHY( pd, pd->phyAddr ) )
break;
}
if( ++pd->phyAddr == 32 )
pd->phyAddr = 0;
}
// If we didn't find a PHY, try again
if( tmp1 == 32 )
{
pd->phyAddr = 0;
pd->phyState = PHYSTATE_MDIOINIT;
pd->phyStateTicks = 0;
RetVal = MDIO_EVENT_PHYERROR;
}
}
break;
case PHYSTATE_NWAYSTART:
/*
// Here we started NWAY. We check to see if NWAY is done.
// If not done and timeout occured, we find another PHY.
*/
/* Read the CONTROL reg to verify "restart" is not set */
PHYREG_read( PHYREG_CONTROL, pd->phyAddr );
PHYREG_waitResultsAck( tmp1, ack );
if( !ack )
{
MDIO_initStateMachine( pd );
break;
}
if( tmp1 & PHYREG_CONTROL_AUTORESTART )
goto CheckTimeout;
/* Flush latched "link status" from the STATUS reg */
PHYREG_read( PHYREG_STATUS, pd->phyAddr );
PHYREG_wait();
pd->phyState = PHYSTATE_NWAYWAIT;
/* Fallthrough */
case PHYSTATE_NWAYWAIT:
/*
// Here we are waiting for NWAY to complete.
*/
/* Read the STATUS reg to check for "complete" */
PHYREG_read( PHYREG_STATUS, pd->phyAddr );
PHYREG_waitResultsAck( tmp1, ack );
if( !ack )
{
MDIO_initStateMachine( pd );
break;
}
if( !(tmp1 & PHYREG_STATUS_AUTOCOMPLETE) )
goto CheckTimeout;
/* We can now check the negotiation results */
if ( (macsel == CSL_DEV_DEVSTAT_MACSEL_GMII) || (macsel == CSL_DEV_DEVSTAT_MACSEL_RGMII) )
{
PHYREG_read( PHYREG_1000CONTROL, pd->phyAddr );
PHYREG_waitResults( tmp1gig );
PHYREG_read( PHYREG_1000STATUS, pd->phyAddr );
PHYREG_waitResults( tmp2gig );
}
PHYREG_read( PHYREG_ADVERTISE, pd->phyAddr );
PHYREG_waitResults( tmp1 );
PHYREG_read( PHYREG_PARTNER, pd->phyAddr );
PHYREG_waitResults( tmp2 );
/*
// Use the "best" results
*/
tmp2 &= tmp1;
/* Check first for 1 Gigabit */
if( (tmp1gig & PHYREG_ADVERTISE_FD1000) && (tmp2gig & PHYREG_PARTNER_FD1000) )
pd->PendingStatus = MDIO_LINKSTATUS_FD1000;
else if( tmp2 & PHYREG_ADVERTISE_FD100 )
pd->PendingStatus = MDIO_LINKSTATUS_FD100;
else if( tmp2 & PHYREG_ADVERTISE_HD100 )
pd->PendingStatus = MDIO_LINKSTATUS_HD100;
else if( tmp2 & PHYREG_ADVERTISE_FD10 )
pd->PendingStatus = MDIO_LINKSTATUS_FD10;
else if( tmp2 & PHYREG_ADVERTISE_HD10 )
pd->PendingStatus = MDIO_LINKSTATUS_HD10;
/*
// If we get here the negotiation failed
// We just use HD 100 or 10 - the best we think we can do
*/
else if( tmp1 & PHYREG_ADVERTISE_HD100 )
pd->PendingStatus = MDIO_LINKSTATUS_HD100;
else
pd->PendingStatus = MDIO_LINKSTATUS_HD10;
pd->phyState = PHYSTATE_LINKWAIT;
/* Fallthrough */
case PHYSTATE_LINKWAIT:
/*
// Here we are waiting for LINK
*/
/* Read the STATUS reg to check for "link" */
PHYREG_read( PHYREG_STATUS, pd->phyAddr );
PHYREG_waitResultsAck( tmp1, ack );
if( !ack )
{
MDIO_initStateMachine( pd );
break;
}
if( !(tmp1 & PHYREG_STATUS_LINKSTATUS) )
goto CheckTimeout;
/* Make sure we're linked in the MDIO module as well */
ltmp1 = MDIO_REGS->LINK;
if( !(ltmp1&(1<<pd->phyAddr)) )
goto CheckTimeout;
/* Start monitoring this PHY */
MDIO_REGS->USERPHYSEL0 = pd->phyAddr;
/* Clear the link change flag so we can detect a "re-link" later */
MDIO_REGS->LINKINTRAW = 1;
/* Setup our linked state */
pd->phyState = PHYSTATE_LINKED;
pd->LinkStatus = pd->PendingStatus;
RetVal = MDIO_EVENT_LINKUP;
break;
}
}
return( RetVal );
}
/*-----------------------------------------------------------------------*\
* MDIO_initPHY()
*
* Force a switch to the specified PHY, and start the negotiation process.
*
* Returns 1 if the PHY selection completed OK, else 0
\*-----------------------------------------------------------------------*/
uint MDIO_initPHY( Handle hMDIO, volatile uint phyAddr )
{
MDIO_Device *pd = (MDIO_Device *)hMDIO;
Uint32 ltmp1;
uint i;
/* Switch the PHY */
pd->phyAddr = phyAddr;
/* There will be no link when we're done with this PHY */
pd->LinkStatus = MDIO_LINKSTATUS_NOLINK;
/* Shutdown all other PHYs */
ltmp1 = MDIO_REGS->ALIVE ;
for( i=0; ltmp1; i++,ltmp1>>=1 )
{
if( (ltmp1 & 1) && (i != phyAddr) )
{
PHYREG_write( PHYREG_CONTROL, i, PHYREG_CONTROL_ISOLATE |
PHYREG_CONTROL_POWERDOWN );
PHYREG_wait();
}
}
/* Reset the PHY we plan to use */
PHYREG_write( PHYREG_CONTROL, phyAddr, PHYREG_CONTROL_RESET );
PHYREG_wait( );
/* Settings for Broadcom phys */
if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RGMII )
{
//Put phy in copper mode
PHYREG_write( PHYREG_ACCESS, phyAddr, PHYREG_ACCESS_COPPER );
PHYREG_wait( );
PHYREG_write( 0x10, phyAddr, 0x0000 ); //GMII Interface
PHYREG_wait();
// Put phy in RGMII mode/in-band status data for PG 1.1
if (EMAC_REGS->TXIDVER != 0x000C1207) {
PHYREG_write(PHYREG_SHADOW, phyAddr, PHYREG_SHADOW_INBAND);
PHYREG_wait( );
}
}
if ( macsel == CSL_DEV_DEVSTAT_MACSEL_GMII )
{
//Put phy in copper mode
PHYREG_write( PHYREG_ACCESS, phyAddr, PHYREG_ACCESS_COPPER );
PHYREG_wait();
}
/* Setup for our next state */
pd->phyState = PHYSTATE_RESET;
pd->phyStateTicks = 0; /* Reset timeout */
return(1);
}
/*-----------------------------------------------------------------------*\
* MDIO_initContinue()
*
* Continues the initialization process started in MDIO_initPHY()
*
* Returns 0 on an error, 1 on success
\*-----------------------------------------------------------------------*/
static uint MDIO_initContinue( MDIO_Device *pd )
{
Uint16 tmp1,tmp2;
Uint16 tmp1gig = 0;
/* Read the STATUS reg to check autonegotiation capability */
PHYREG_read( PHYREG_STATUS, pd->phyAddr );
PHYREG_waitResults( tmp1 );
if ( (macsel == CSL_DEV_DEVSTAT_MACSEL_GMII) || (macsel == CSL_DEV_DEVSTAT_MACSEL_RGMII) )
{
PHYREG_read( PHYREG_EXTSTATUS, pd->phyAddr );
PHYREG_waitResults( tmp1gig );
}
/* See if we auto-neg or not */
if( (pd->ModeFlags & MDIO_MODEFLG_AUTONEG) &&
(tmp1 & PHYREG_STATUS_AUTOCAPABLE) )
{
/* We will use NWAY */
/* Advertise 1000 for supported interfaces */
if ( (macsel == CSL_DEV_DEVSTAT_MACSEL_GMII) || (macsel == CSL_DEV_DEVSTAT_MACSEL_RGMII) )
{
tmp1gig >>= 4;
tmp1gig &= PHYREG_ADVERTISE_FD1000;
PHYREG_write( PHYREG_1000CONTROL, pd->phyAddr, tmp1gig );
PHYREG_wait();
}
/* Shift down the capability bits */
tmp1 >>= 6;
/* Mask with the capabilities */
tmp1 &= ( PHYREG_ADVERTISE_FD100 | PHYREG_ADVERTISE_HD100 |
PHYREG_ADVERTISE_FD10 | PHYREG_ADVERTISE_HD10 );
/* Set Ethernet message bit */
tmp1 |= PHYREG_ADVERTISE_MSG;
/* Write out advertisement */
PHYREG_write( PHYREG_ADVERTISE, pd->phyAddr, tmp1 );
PHYREG_wait();
/* Start NWAY */
PHYREG_write( PHYREG_CONTROL, pd->phyAddr, PHYREG_CONTROL_AUTONEGEN );
PHYREG_wait();
PHYREG_write( PHYREG_CONTROL, pd->phyAddr,
PHYREG_CONTROL_AUTONEGEN|PHYREG_CONTROL_AUTORESTART );
PHYREG_wait();
/* Setup current state */
pd->ModeFlags |= MDIO_MODEFLG_NWAYACTIVE;
pd->phyState = PHYSTATE_NWAYSTART;
pd->phyStateTicks = 0; /* Reset timeout */
}
else
{
/* We will use a fixed configuration */
/* Shift down the capability bits */
tmp1 >>= 10;
/* Mask with possible modes */
tmp1 &= ( MDIO_MODEFLG_HD10 | MDIO_MODEFLG_FD10 |
MDIO_MODEFLG_HD100 | MDIO_MODEFLG_FD100 );
if ( (macsel == CSL_DEV_DEVSTAT_MACSEL_GMII) || (macsel == CSL_DEV_DEVSTAT_MACSEL_RGMII) )
{
tmp1gig >>= 8;
tmp1gig&= MDIO_MODEFLG_FD1000;
/* Mask with what the User wants to allow */
tmp1gig &= pd->ModeFlags;
}
/* Mask with what the User wants to allow */
tmp1 &= pd->ModeFlags;
/* If nothing if left, move on */
if( (!tmp1) && (!tmp1gig) )
return(0);
/* Setup Control word and pending status */
if( tmp1gig ) {
tmp2 = PHYREG_CONTROL_SPEEDMSB | PHYREG_CONTROL_DUPLEXFULL;
pd->PendingStatus = MDIO_LINKSTATUS_FD1000;
}
else if( tmp1 & MDIO_MODEFLG_FD100 )
{
tmp2 = PHYREG_CONTROL_SPEEDLSB | PHYREG_CONTROL_DUPLEXFULL;
pd->PendingStatus = MDIO_LINKSTATUS_FD100;
}
else if( tmp1 & MDIO_MODEFLG_HD100 )
{
tmp2 = PHYREG_CONTROL_SPEEDLSB;
pd->PendingStatus = MDIO_LINKSTATUS_HD100;
}
else if( tmp1 & MDIO_MODEFLG_FD10 )
{
tmp2 = PHYREG_CONTROL_DUPLEXFULL;
pd->PendingStatus = MDIO_LINKSTATUS_FD10;
}
else
{
tmp2 = 0;
pd->PendingStatus = MDIO_LINKSTATUS_HD10;
}
/* Add in internal phy loopback if user wanted it */
if( pd->ModeFlags & MDIO_MODEFLG_LOOPBACK )
tmp2 |= PHYREG_CONTROL_LOOPBACK;
/* Configure PHY */
PHYREG_write( PHYREG_CONTROL, pd->phyAddr, tmp2 );
PHYREG_wait();
/* Add in external phy loopback with plug if user wanted it */
if( pd->ModeFlags & MDIO_MODEFLG_EXTLOOPBACK ) {
PHYREG_write( PHYREG_SHADOW, pd->phyAddr, PHYREG_SHADOW_EXTLOOPBACK );
PHYREG_wait();
}
/* Setup current state */
pd->ModeFlags &= ~MDIO_MODEFLG_NWAYACTIVE;
pd->phyState = PHYSTATE_LINKWAIT;
pd->phyStateTicks = 0; /* Reset timeout */
}
return(1);
}
/*-----------------------------------------------------------------------*\
* MDIO_phyRegRead()
*
* Raw data read of a PHY register.
*
* Returns 1 if the PHY ACK'd the read, else 0
\*-----------------------------------------------------------------------*/
uint MDIO_phyRegRead( volatile uint phyIdx, volatile uint phyReg, Uint16 *pData )
{
uint data,ack;
PHYREG_read( phyReg, phyIdx );
PHYREG_waitResultsAck( data, ack );
if( !ack )
return(0);
if( pData )
*pData = data;
return(1);
}
/*-----------------------------------------------------------------------*\
* MDIO_phyRegWrite()
*
* Raw data write of a PHY register.
*
* Returns 1 if the PHY ACK'd the write, else 0
\*-----------------------------------------------------------------------*/
uint MDIO_phyRegWrite( volatile uint phyIdx, volatile uint phyReg, Uint16 data )
{
PHYREG_write( phyReg, phyIdx, data );
PHYREG_wait( );
return(1);
}
/******************************************************************************\
* End of c6455_mdio.c
\******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -