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; }
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); } }
/***************************************************************************//** * 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; }
/***************************************************************************//** * 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; } } }
/***************************************************************************//** * 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; }
/***************************************************************************//** * 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; }
/***************************************************************************//** * 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 ); }
/***************************************************************************//** * 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; }