[U-Boot] [PATCH 1/3] phylib: Work around bug in Teranetics PHY

From: Andy Fleming afleming@freescale.com
The Teranetics PHY does not properly report the link state for fiber connections. The new PHY code actually checked the link, and so the FM driver would refuse to talk over a linkless PHY.
But the link may actually be up, so now we always report it as up for fiber connections on the tn2020.
Signed-off-by: Andy Fleming afleming@freescale.com --- drivers/net/phy/teranetics.c | 23 +++++++++++++++++++++-- 1 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index a771791..5932bf0 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -20,7 +20,7 @@ * author Andy Fleming * */ -#include <config.h> +#include <common.h> #include <phy.h>
#ifndef CONFIG_PHYLIB_10G @@ -41,6 +41,25 @@ int tn2020_config(struct phy_device *phydev) return 0; }
+int tn2020_startup(struct phy_device *phydev) +{ + if (phydev->port != PORT_FIBRE) + return gen10g_startup(phydev); + + /* + * The TN2020 only pretends to support fiber. + * It works, but it doesn't look like it works, + * so the link status reports no link. + */ + phydev->link = 1; + + /* For now just lie and say it's 10G all the time */ + phydev->speed = SPEED_10000; + phydev->duplex = DUPLEX_FULL; + + return 0; +} + struct phy_driver tn2020_driver = { .name = "Teranetics TN2020", .uid = 0x00a19410, @@ -50,7 +69,7 @@ struct phy_driver tn2020_driver = { MDIO_DEVS_PHYXS | MDIO_DEVS_AN | MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2), .config = &tn2020_config, - .startup = &gen10g_startup, + .startup = &tn2020_startup, .shutdown = &gen10g_shutdown, };

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 --- drivers/net/phy/teranetics.c | 32 ++++++++++++++++++++++++++++++++ 1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 5932bf0..97fe5f4 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -43,6 +43,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);

The work-around for P4080 erratum SERDES9 says that the SERDES receiver lanes should be reset after the XAUI starts tranmitting alignment signals.
Signed-off-by: Timur Tabi timur@freescale.com --- arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 10 ------ board/freescale/corenet_ds/eth_p4080.c | 40 ++++++++++++++++++++---- 2 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index 07e58ed..89ed5b4 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -504,9 +504,6 @@ void fsl_serdes_init(void) const char *srds_lpd_arg; size_t arglen; #endif -#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 - enum srds_prtcl device; -#endif #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 int need_serdes_a001; /* TRUE == need work-around for SERDES A001 */ #endif @@ -787,11 +784,4 @@ void fsl_serdes_init(void) SRDS_RSTCTL_SDPD); } #endif - -#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 - for (device = XAUI_FM1; device <= XAUI_FM2; device++) { - if (is_serdes_configured(device)) - __serdes_reset_rx(srds_regs, cfg, device); - } -#endif } diff --git a/board/freescale/corenet_ds/eth_p4080.c b/board/freescale/corenet_ds/eth_p4080.c index d4657f7..a724ffc 100644 --- a/board/freescale/corenet_ds/eth_p4080.c +++ b/board/freescale/corenet_ds/eth_p4080.c @@ -96,18 +96,43 @@ struct mii_dev *mii_dev_for_muxval(u32 muxval) #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 int board_phy_config(struct phy_device *phydev) { - /* - * If this is the 10G PHY, and we switched it to fiber, - * we need to reset the serdes link for SERDES9 - */ - if ((phydev->port == PORT_FIBRE) && (phydev->drv->uid == 0x00a19410)) { +#ifdef CONFIG_PHY_TERANETICS + extern struct phy_driver tn2020_driver; + + if (phydev->drv->uid == tn2020_driver.uid) { + unsigned long timeout = 1 * 1000; /* 1 seconds */ enum srds_prtcl device;
+ /* + * Wait for the XAUI to come out of reset. This is when it + * starts transmitting alignment signals. + */ + while (--timeout) { + int reg = phy_read(phydev, MDIO_MMD_PHYXS, MDIO_CTRL1); + if (reg < 0) { + printf("TN2020: Error reading from PHY at " + "address %u\n", phydev->addr); + break; + } + /* + * Note that we've never actually seen + * MDIO_CTRL1_RESET set to 1. + */ + if ((reg & MDIO_CTRL1_RESET) == 0) + break; + udelay(1000); + } + + if (!timeout) { + printf("TN2020: Timeout waiting for PHY at address %u " + " to reset.\n", phydev->addr); + } + switch (phydev->addr) { - case 4: + case CONFIG_SYS_FM1_10GEC1_PHY_ADDR: device = XAUI_FM1; break; - case 0: + case CONFIG_SYS_FM2_10GEC1_PHY_ADDR: device = XAUI_FM2; break; default: @@ -116,6 +141,7 @@ int board_phy_config(struct phy_device *phydev)
serdes_reset_rx(device); } +#endif
return 0; }

Dear Timur Tabi,
In message 1317841251-27295-3-git-send-email-timur@freescale.com you wrote:
The work-around for P4080 erratum SERDES9 says that the SERDES receiver lanes should be reset after the XAUI starts tranmitting alignment signals.
Signed-off-by: Timur Tabi timur@freescale.com
arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 10 ------ board/freescale/corenet_ds/eth_p4080.c | 40 ++++++++++++++++++++---- 2 files changed, 33 insertions(+), 17 deletions(-)
Checkpatch says:
WARNING: externs should be avoided in .c files #114: FILE: board/freescale/corenet_ds/eth_p4080.c:100: + extern struct phy_driver tn2020_driver;
Please clean up and resubmit. Thanks.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
WARNING: externs should be avoided in .c files #114: FILE: board/freescale/corenet_ds/eth_p4080.c:100:
extern struct phy_driver tn2020_driver;
This is intentional. There's no header file for the teranetics driver, and referencing the structure allows me to avoid a hard-coded number.
Are you suggesting that I create a header file just to contain this line:
extern struct phy_driver tn2020_driver;
because that seems silly.

Dear Timur Tabi,
In message 4E8E1881.5030902@freescale.com you wrote:
WARNING: externs should be avoided in .c files #114: FILE: board/freescale/corenet_ds/eth_p4080.c:100:
extern struct phy_driver tn2020_driver;
This is intentional. There's no header file for the teranetics driver, and
Maybe it's intentional on your side. I don't accept it anyway.
Best regards,
Wolfgang Denk
participants (2)
-
Timur Tabi
-
Wolfgang Denk