mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
net: reduce boot latency on QE UEC based boards
actually polling for PHY autonegotiation to finish enables us to remove the 5 second boot prompt latency present on QE based boards. call to qe_set_mii_clk_src in init_phy, and mv call to init_phy from uec_initialize to uec_init by Joakim Tjernlund; autonegotiation wait code shamelessly stolen from tsec driver. also rm unused CONFIG_RMII_MODE code. Signed-off-by: Kim Phillips <kim.phillips@freescale.com> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se> Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
This commit is contained in:
parent
55fe7c57a8
commit
ee62ed3286
2 changed files with 79 additions and 48 deletions
|
@ -512,6 +512,8 @@ static int init_phy(struct eth_device *dev)
|
|||
|
||||
uec->mii_info = mii_info;
|
||||
|
||||
qe_set_mii_clk_src(uec->uec_info->uf_info.ucc_num);
|
||||
|
||||
if (init_mii_management_configuration(umii_regs)) {
|
||||
printf("%s: The MII Bus is stuck!", dev->name);
|
||||
err = -1;
|
||||
|
@ -618,21 +620,12 @@ static void adjust_link(struct eth_device *dev)
|
|||
static void phy_change(struct eth_device *dev)
|
||||
{
|
||||
uec_private_t *uec = (uec_private_t *)dev->priv;
|
||||
uec_t *uec_regs;
|
||||
int result = 0;
|
||||
|
||||
uec_regs = uec->uec_regs;
|
||||
|
||||
/* Delay 5s to give the PHY a chance to change the register state */
|
||||
udelay(5000000);
|
||||
|
||||
/* Update the link, speed, duplex */
|
||||
result = uec->mii_info->phyinfo->read_status(uec->mii_info);
|
||||
uec->mii_info->phyinfo->read_status(uec->mii_info);
|
||||
|
||||
/* Adjust the interface according to speed */
|
||||
if ((0 == result) || (uec->mii_info->link == 0)) {
|
||||
adjust_link(dev);
|
||||
}
|
||||
adjust_link(dev);
|
||||
}
|
||||
|
||||
static int uec_set_mac_address(uec_private_t *uec, u8 *mac_addr)
|
||||
|
@ -1157,27 +1150,59 @@ static int uec_startup(uec_private_t *uec)
|
|||
static int uec_init(struct eth_device* dev, bd_t *bd)
|
||||
{
|
||||
uec_private_t *uec;
|
||||
int err;
|
||||
int err, i;
|
||||
struct phy_info *curphy;
|
||||
|
||||
uec = (uec_private_t *)dev->priv;
|
||||
|
||||
if (uec->the_first_run == 0) {
|
||||
/* Set up the MAC address */
|
||||
if (dev->enetaddr[0] & 0x01) {
|
||||
printf("%s: MacAddress is multcast address\n",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
err = init_phy(dev);
|
||||
if (err) {
|
||||
printf("%s: Cannot initialize PHY, aborting.\n",
|
||||
dev->name);
|
||||
return err;
|
||||
}
|
||||
uec_set_mac_address(uec, dev->enetaddr);
|
||||
|
||||
curphy = uec->mii_info->phyinfo;
|
||||
|
||||
if (curphy->config_aneg) {
|
||||
err = curphy->config_aneg(uec->mii_info);
|
||||
if (err) {
|
||||
printf("%s: Can't negotiate PHY\n", dev->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give PHYs up to 5 sec to report a link */
|
||||
i = 50;
|
||||
do {
|
||||
err = curphy->read_status(uec->mii_info);
|
||||
udelay(100000);
|
||||
} while (((i-- > 0) && !uec->mii_info->link) || err);
|
||||
|
||||
if (err || i <= 0)
|
||||
printf("warning: %s: timeout on PHY link\n", dev->name);
|
||||
|
||||
uec->the_first_run = 1;
|
||||
}
|
||||
|
||||
/* Set up the MAC address */
|
||||
if (dev->enetaddr[0] & 0x01) {
|
||||
printf("%s: MacAddress is multcast address\n",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
uec_set_mac_address(uec, dev->enetaddr);
|
||||
|
||||
|
||||
err = uec_open(uec, COMM_DIR_RX_AND_TX);
|
||||
if (err) {
|
||||
printf("%s: cannot enable UEC device\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
phy_change(dev);
|
||||
|
||||
return (uec->mii_info->link ? 0 : -1);
|
||||
}
|
||||
|
||||
|
@ -1330,14 +1355,6 @@ int uec_initialize(int index)
|
|||
return err;
|
||||
}
|
||||
|
||||
err = init_phy(dev);
|
||||
if (err) {
|
||||
printf("%s: Cannot initialize PHY, aborting.\n", dev->name);
|
||||
return err;
|
||||
}
|
||||
|
||||
phy_change(dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_QE */
|
||||
|
|
|
@ -77,11 +77,10 @@ void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int valu
|
|||
|
||||
/* Setting up the MII Mangement Control Register with the value */
|
||||
out_be32 (&ug_regs->miimcon, (u32) value);
|
||||
sync();
|
||||
|
||||
/* Wait till MII management write is complete */
|
||||
while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY);
|
||||
|
||||
udelay (100000);
|
||||
}
|
||||
|
||||
/* Reads from register regnum in the PHY for device dev, */
|
||||
|
@ -101,16 +100,17 @@ int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum)
|
|||
tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
|
||||
out_be32 (&ug_regs->miimadd, tmp_reg);
|
||||
|
||||
/* Perform an MII management read cycle */
|
||||
/* clear MII management command cycle */
|
||||
out_be32 (&ug_regs->miimcom, 0);
|
||||
sync();
|
||||
|
||||
/* Perform an MII management read cycle */
|
||||
out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
|
||||
|
||||
/* Wait till MII management write is complete */
|
||||
while ((in_be32 (&ug_regs->miimind)) &
|
||||
(MIIMIND_NOT_VALID | MIIMIND_BUSY));
|
||||
|
||||
udelay (100000);
|
||||
|
||||
/* Read MII management status */
|
||||
value = (u16) in_be32 (&ug_regs->miimstat);
|
||||
if (value == 0xffff)
|
||||
|
@ -270,20 +270,38 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
|
|||
{
|
||||
u16 status;
|
||||
|
||||
/* Do a fake read */
|
||||
/* Status is read once to clear old link state */
|
||||
phy_read (mii_info, PHY_BMSR);
|
||||
|
||||
/* Read link and autonegotiation status */
|
||||
status = phy_read (mii_info, PHY_BMSR);
|
||||
if ((status & PHY_BMSR_LS) == 0)
|
||||
mii_info->link = 0;
|
||||
else
|
||||
mii_info->link = 1;
|
||||
/*
|
||||
* Wait if the link is up, and autonegotiation is in progress
|
||||
* (ie - we're capable and it's not done)
|
||||
*/
|
||||
status = phy_read(mii_info, PHY_BMSR);
|
||||
if ((status & PHY_BMSR_LS) && (status & PHY_BMSR_AUTN_ABLE)
|
||||
&& !(status & PHY_BMSR_AUTN_COMP)) {
|
||||
int i = 0;
|
||||
|
||||
/* If we are autonegotiating, and not done,
|
||||
* return an error */
|
||||
if (mii_info->autoneg && !(status & PHY_BMSR_AUTN_COMP))
|
||||
return -EAGAIN;
|
||||
while (!(status & PHY_BMSR_AUTN_COMP)) {
|
||||
/*
|
||||
* Timeout reached ?
|
||||
*/
|
||||
if (i > UGETH_AN_TIMEOUT) {
|
||||
mii_info->link = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
udelay(1000); /* 1 ms */
|
||||
status = phy_read(mii_info, PHY_BMSR);
|
||||
}
|
||||
mii_info->link = 1;
|
||||
udelay(500000); /* another 500 ms (results in faster booting) */
|
||||
} else {
|
||||
if (status & PHY_BMSR_LS)
|
||||
mii_info->link = 1;
|
||||
else
|
||||
mii_info->link = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -389,16 +407,12 @@ static int dm9161_init (struct uec_mii_info *mii_info)
|
|||
/* PHY and MAC connect */
|
||||
phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) &
|
||||
~PHY_BMCR_ISO);
|
||||
#ifdef CONFIG_RMII_MODE
|
||||
phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_RMII_INIT);
|
||||
#else
|
||||
|
||||
phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
|
||||
#endif
|
||||
|
||||
config_genmii_advert (mii_info);
|
||||
/* Start/restart aneg */
|
||||
genmii_config_aneg (mii_info);
|
||||
/* Delay to wait the aneg compeleted */
|
||||
udelay (3000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue