Example #1
0
int InitPhy(PHY_cfg *cfg)
{
	u32 d;

	// Check PHY presence
	d=MDIO_read(cfg, PHY_REG_IDH);
	if(d!=M88E1111_IDH)
		return -1;

	// Enable RGMII clock delay
	d=MDIO_read(cfg, PHY_REG_EPSC);
	d|=PHY_REG_EPSC_RRTC|PHY_REG_EPSC_RTTC;
	MDIO_write(cfg, PHY_REG_EPSC, d);

	//d=MDIO_read(cfg, PHY_REG_PSCR);
	//d|=PHY_REG_PSCR_TFD_MAX | PHY_REG_PSCR_RFD_MAX;
	//d|=PHY_REG_PSCR_EXT;
	//MDIO_write(cfg, PHY_REG_PSCR, d);

	d=0xFFFF;
	MDIO_write(cfg, PHY_REG_IER, d);

	d=PHY_REG_LEDC_DISABLE;
	MDIO_write(cfg, PHY_REG_LEDC, d);

	// Soft Reset
	d=MDIO_read(cfg, PHY_REG_CTRL);
	d|=PHY_REG_CTRL_RST;
	MDIO_write(cfg, PHY_REG_CTRL, d);

	return 0;
}
Example #2
0
void UpdateChannelStatus(void)
{
	int i;
	for(i=0;i<3;i++)
	{
		u16 d;
		d=MDIO_read(&phyCfg[i], PHY_REG_PSSR);
		// WORKAROUND: Add a delay to avoid the short unstable period after link setup
		if(PHY_REG_PSSR_LINK(d))
		{
			if(phy[i].link_time<LINK_HOLDOFF)
			{
				phy[i].link_time++;
			}
			else
			{
				if(phy[i].link!=1 || phy[i].speed!=PHY_REG_PSSR_SPEED(d) ||
						phy[i].duplex!=PHY_REG_PSSR_DUPLEX(d))
					phy[i].changed=1;

				phy[i].link = 1;
				phy[i].speed = PHY_REG_PSSR_SPEED(d);
				phy[i].duplex = PHY_REG_PSSR_DUPLEX(d);
				phy[i].length = PHY_REG_PSSR_LENGTH(d);

				d=MDIO_read(&phyCfg[i], PHY_REG_RECR);
				phy[i].rx_err = d;

				if(phy[i].rx_err>ERROR_THRESHOLD)
				{
					phy[i].link=0;
					phy[i].link_time=0;
					phy[i].changed=1;
				}

			}
		}
		else
		{
			if(phy[i].link)
				phy[i].changed=1;

			phy[i].link=0;
			phy[i].link_time=0;
			//phy[i].speed=0;
			//phy[i].duplex=0;
			//phy[i].length=0;
			//phy[i].rx_err=0;
		}

		if(phy[i].changed)
		{
			IO_SetBit(phyCfg[i].link_offset, phy[i].link);
			IO_SetBit(phyCfg[i].speed_offset, phy[i].speed&0x1);
			IO_SetBit(phyCfg[i].speed_offset+1, (phy[i].speed&0x2)>>1);
			IO_SetBit(phyCfg[i].duplex_offset, phy[i].duplex);
		}
	}
Example #3
0
/***************************************************************************//**
 * Returns link status.
 *
 * @return          #MAC_LINK_STATUS_LINK if link is up.
 */
uint8_t PHY_link_status( void )
{
	uint8_t retval = 0;
	if(( MDIO_read( PHYREG_MIIMSR ) & MIIMSR_LINK ) != 0 ){
		retval = MSS_MAC_LINK_STATUS_LINK;
	}
	return retval;
}
Example #4
0
/***************************************************************************//**
 * Restarts PHY auto-negotiation and wait until it's over.
 */
void PHY_auto_negotiate( void )
{
	int32_t a;
	uint16_t reg;
    int32_t exit = 1;

	reg = MDIO_read( PHYREG_MIIMCR );
	MDIO_write( PHYREG_MIIMCR,
		(uint16_t)( MIIMCR_ENABLE_AUTONEGOTIATION |
		MIIMCR_RESTART_AUTONEGOTIATION |
		reg) );

	for(a=0; (a<1000) && (exit); a++) {
		reg = MDIO_read( PHYREG_MIIMSR );
		if( (reg & MIIMSR_ANC) != 0 ) {
			exit = 0;
		}
	}
}
Example #5
0
/***************************************************************************//**
 * Puts the Phy in Loopback mode
 */
uint16_t
PHY_set_loopback
(
   uint8_t enable
)
{

	uint16_t reg = 0;   
	

	reg = MDIO_read( PHYREG_MIIMCR );
	// If set to one we need to set the LOCAL Phy loopback
	if(enable == 1)
		reg |= MIIMCR_LOOPBACK;
	else // else we want to clear the bit..
		reg ^= MIIMCR_LOOPBACK;
	
	
	MDIO_write( PHYREG_MIIMCR,reg );
	reg = MDIO_read( PHYREG_MIIMCR );
	
	return reg;
	
}
Example #6
0
/***************************************************************************//**
 * Returns link type.
 *
 * @return          the logical OR of the following values:
 *      #MAC_LINK_STATUS_100MB   - Connection is 100Mb
 *      #MAC_LINK_STATUS_FDX     - Connection is full duplex
 */
uint8_t PHY_link_type( void )
{
	uint16_t diagnostic;
	uint8_t type = 0;

	diagnostic = MDIO_read( PHYREG_DR );

    if( (diagnostic & DR_DPLX) != 0 ) {
    	type = MSS_MAC_LINK_STATUS_FDX;
    }

    if( (diagnostic & DR_DATA_RATE) != 0 ) {
    	type |= MSS_MAC_LINK_STATUS_100MB;
    }

    return type;
}
Example #7
0
/***************************************************************************//**
 * Sets link type.
 */
void
PHY_set_link_type
(
    uint8_t type
)
{
	uint16_t reg;

	reg = MDIO_read( PHYREG_ANAR );
	reg |= ANAR_100FD | ANAR_100HD | ANAR_10FD | ANAR_10HD;

	if( (type & MSS_MAC_LINK_STATUS_100MB) == 0 ) {
		reg &= ~(ANAR_100FD | ANAR_100HD);
	}

	if( (type & MSS_MAC_LINK_STATUS_FDX) == 0 ) {
		reg &= ~(ANAR_100FD | ANAR_10FD);
	}

	MDIO_write( PHYREG_ANAR, reg );
}
Example #8
0
/***************************************************************************//**
 * Probe used PHY.
 *
 * return	PHY address. If PHY don't fount, returns 255.
 */
uint8_t PHY_probe( void )
{
	uint8_t phy;
	uint8_t phy_found;
	uint16_t reg;

	phy_found = 0;
	for (phy = MSS_PHY_ADDRESS_MIN; phy <= MSS_PHY_ADDRESS_MAX; phy++) {
		g_mss_mac.phy_address = phy;

        reg = MDIO_read( PHYREG_PHYID1R );

        if ((reg != 0x0000ffffUL) && (reg != 0x00000000UL)) {
        	phy_found = 1;
        	phy = MSS_PHY_ADDRESS_MAX + 1;
        }
    }

    if( phy_found == 0 ) {
    	g_mss_mac.phy_address = MSS_PHY_ADDRESS_AUTO_DETECT;
    }
    return g_mss_mac.phy_address;
}