summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2011-10-07 15:35:21 -0500
committerKumar Gala <galak@kernel.crashing.org>2011-10-13 23:38:11 -0500
commit2339e4972f55c9daa0d0e297ad3378c53e2f6fc3 (patch)
tree7fcf05f0505e59393d4352d411bcb84d0eb5f937
parent7f92c3a27553e63ffb0efcff40573fb23a3e29ce (diff)
downloadu-boot-imx-2339e4972f55c9daa0d0e297ad3378c53e2f6fc3.zip
u-boot-imx-2339e4972f55c9daa0d0e297ad3378c53e2f6fc3.tar.gz
u-boot-imx-2339e4972f55c9daa0d0e297ad3378c53e2f6fc3.tar.bz2
phylib: wait for TN2020 to achieve SERDES lane alignment at startup
Before the Teranetics TN2020 PHY can be used, the SERDES lanes need to be aligned, so wait for lane alignment before completing the startup sequence. Note that this process can take up to three seconds. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r--drivers/net/phy/teranetics.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
index a13b48c..9d9397a 100644
--- a/drivers/net/phy/teranetics.c
+++ b/drivers/net/phy/teranetics.c
@@ -21,6 +21,7 @@
*
*/
#include <config.h>
+#include <common.h>
#include <phy.h>
#ifndef CONFIG_PHYLIB_10G
@@ -43,6 +44,38 @@ int tn2020_config(struct phy_device *phydev)
int tn2020_startup(struct phy_device *phydev)
{
+ unsigned int timeout = 5 * 1000; /* 5 second timeout */
+
+#define MDIO_PHYXS_LANE_READY (MDIO_PHYXS_LNSTAT_SYNC0 | \
+ MDIO_PHYXS_LNSTAT_SYNC1 | \
+ MDIO_PHYXS_LNSTAT_SYNC2 | \
+ MDIO_PHYXS_LNSTAT_SYNC3 | \
+ MDIO_PHYXS_LNSTAT_ALIGN)
+
+ /*
+ * Wait for the XAUI-SERDES lanes to align first. Under normal
+ * circumstances, this can take up to three seconds.
+ */
+ while (--timeout) {
+ int reg = phy_read(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_LNSTAT);
+ if (reg < 0) {
+ printf("TN2020: Error reading from PHY at "
+ "address %u\n", phydev->addr);
+ break;
+ }
+ if ((reg & MDIO_PHYXS_LANE_READY) == MDIO_PHYXS_LANE_READY)
+ break;
+ udelay(1000);
+ }
+ if (!timeout) {
+ /*
+ * A timeout is bad, but it may not be fatal, so don't
+ * return an error. Display a warning instead.
+ */
+ printf("TN2020: Timeout waiting for PHY at address %u to "
+ "align.\n", phydev->addr);
+ }
+
if (phydev->port != PORT_FIBRE)
return gen10g_startup(phydev);