We're doing the same sort of thing, and it seems to work... sort of.
First of all, on boot we have the big two second delay as noted above..
Assuming that hardware autonegotiation is failing, we will have a software task that runs occasionally check the link and reinitialize the phy if the link is down.. Since we don't know why the link went down, we periodically switch between the two forced speeds until we get a link. So if I plug the device into a 10Mbps hub on boot, then unplug it after its been initialized, when I plug it back in, it will be unknown whether it's checking for a 10 or 100Mbps link. So if then plugged into a 10/100 hub, it might still connect at 10Mbps.
Here's our periodic function:
if(autonegotiation_status <= 0)
{
fec_mii_read_b(FEC_PHY0, PHY_REG_PSR, &mii_psr_reg);
if((mii_psr_reg & 0x0500) == 0x0400)
{
autonegotiation_status = 1;
return;
}
if(link_speed == 0)
{
if(phy_check_count++ > 800)
{
fec_mii_read_b(FEC_PHY0, 1, &mii_cr_reg);
/* Check link status */
if((mii_cr_reg & 0x0004) == 0)
{
fec_mii_read_b(FEC_PHY0, 0, &mii_cr_reg);
mii_cr_reg &= ~0x1100; /* Manual half-duplex */
mii_cr_reg ^= 0x2000; /* Change data rate */
fec_mii_write_b(FEC_PHY0, 0, mii_cr_reg);
fec_mii_write_b(FEC_PHY0, 0, (mii_cr_reg|0x0200)); // Force re-negotiate
}
phy_check_count = 0;
}
}
else
{
phy_check_count = 0;
}
}
link_speed is filled in in the ePhy interrupt.
Chris