summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorKhoronzhuk, Ivan <ivan.khoronzhuk@ti.com>2014-10-17 21:01:15 +0300
committerTom Rini <trini@ti.com>2014-10-23 11:27:29 -0400
commitc05d05e7202b01a1b461c78ba6c5b06545621620 (patch)
tree756357fd5a48e134019f794992a5f085b9cfafa0 /drivers/net
parentff11c7697cee84d03e8020cc6198554550cd3ea2 (diff)
downloadu-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.c36
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);