diff options
author | Khoronzhuk, Ivan <ivan.khoronzhuk@ti.com> | 2014-10-17 21:01:15 +0300 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2014-10-23 11:27:29 -0400 |
commit | c05d05e7202b01a1b461c78ba6c5b06545621620 (patch) | |
tree | 756357fd5a48e134019f794992a5f085b9cfafa0 /drivers/net | |
parent | ff11c7697cee84d03e8020cc6198554550cd3ea2 (diff) | |
download | u-boot-imx-c05d05e7202b01a1b461c78ba6c5b06545621620.zip u-boot-imx-c05d05e7202b01a1b461c78ba6c5b06545621620.tar.gz u-boot-imx-c05d05e7202b01a1b461c78ba6c5b06545621620.tar.bz2 |
net: keystone_net: increase PHY auto negotiate time
The new Marvel PHY (88E1514) used on K2L/K2E EVM requires longer time
to auto negotiate with SoC's SGMII port.
It can take about 3 sec to up the PHY after reset, so add code to
expose sgmii auto negotiation waiting process.
Acked-by: Vitaly Andrianov <vitalya@ti.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/keystone_net.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 1186188..c8681d0 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -11,6 +11,7 @@ #include <net.h> #include <phy.h> +#include <errno.h> #include <miiphy.h> #include <malloc.h> #include <asm/ti-common/keystone_nav.h> @@ -30,6 +31,7 @@ static unsigned int sys_has_mdio = 1; #define RX_BUFF_NUMS 24 #define RX_BUFF_LEN 1520 #define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN +#define SGMII_ANEG_TIMEOUT 4000 static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16); @@ -169,7 +171,7 @@ int keystone_sgmii_link_status(int port) (status & SGMII_REG_STATUS_LINK); } -int keystone_sgmii_config(int port, int interface) +int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface) { unsigned int i, status, mask; unsigned int mr_adv_ability, control; @@ -230,11 +232,35 @@ int keystone_sgmii_config(int port, int interface) if (control & SGMII_REG_CONTROL_AUTONEG) mask |= SGMII_REG_STATUS_AUTONEG; - for (i = 0; i < 1000; i++) { + status = __raw_readl(SGMII_STATUS_REG(port)); + if ((status & mask) == mask) + return 0; + + printf("\n%s Waiting for SGMII auto negotiation to complete", + phy_dev->dev->name); + while ((status & mask) != mask) { + /* + * Timeout reached ? + */ + if (i > SGMII_ANEG_TIMEOUT) { + puts(" TIMEOUT !\n"); + phy_dev->link = 0; + return 0; + } + + if (ctrlc()) { + puts("user interrupt!\n"); + phy_dev->link = 0; + return -EINTR; + } + + if ((i++ % 500) == 0) + printf("."); + + udelay(1000); /* 1 ms */ status = __raw_readl(SGMII_STATUS_REG(port)); - if ((status & mask) == mask) - break; } + puts(" done\n"); return 0; } @@ -374,7 +400,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) keystone2_net_serdes_setup(); - keystone_sgmii_config(eth_priv->slave_port - 1, + keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1, eth_priv->sgmii_link_type); udelay(10000); |