[PATCH 2/2] net/ucc_geth: Add SGMII support for UCC GETH driver
From: Haiying Wang haiying.w...@freescale.com -- derived from reverted commit 047584ce94108012288554a5f84585d792cc7f8f -- reworked by Grant Likely to play nice with commit: net: Rework ucc_geth driver to use of_mdio infrastructure (0b9da337dca972e7a4144e298ec3adb8f244d4a4) Signed-off-by: Haiying Wang haiying.w...@freescale.com Signed-off-by: David S. Miller da...@davemloft.net Signed-off-by: Grant Likely grant.lik...@secretlab.ca --- arch/powerpc/include/asm/qe.h |2 + drivers/net/ucc_geth.c| 58 - drivers/net/ucc_geth.h| 28 +++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index e0faf33..157c5ca 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h @@ -675,6 +675,8 @@ struct ucc_slow_pram { #define UCC_GETH_UPSMR_RMM 0x1000 #define UCC_GETH_UPSMR_CAM 0x0400 #define UCC_GETH_UPSMR_BRO 0x0200 +#define UCC_GETH_UPSMR_SMM 0x0080 +#define UCC_GETH_UPSMR_SGMM0x0020 /* UCC Transmit On Demand Register (UTODR) */ #define UCC_SLOW_TOD 0x8000 diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 5118993..40c6eba 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved. + * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved. * * Author: Shlomi Gridish grid...@freescale.com *Li Yang le...@freescale.com @@ -1410,6 +1410,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) (ugeth-phy_interface == PHY_INTERFACE_MODE_RTBI)) { upsmr |= UCC_GETH_UPSMR_TBIM; } + if ((ugeth-phy_interface == PHY_INTERFACE_MODE_SGMII)) + upsmr |= UCC_GETH_UPSMR_SGMM; + out_be32(uf_regs-upsmr, upsmr); /* Disable autonegotiation in tbi mode, because by default it @@ -1531,6 +1534,49 @@ static void adjust_link(struct net_device *dev) spin_unlock_irqrestore(ugeth-lock, flags); } +/* Initialize TBI PHY interface for communicating with the + * SERDES lynx PHY on the chip. We communicate with this PHY + * through the MDIO bus on each controller, treating it as a + * normal PHY at the address found in the UTBIPA register. We assume + * that the UTBIPA register is valid. Either the MDIO bus code will set + * it to a value that doesn't conflict with other PHYs on the bus, or the + * value doesn't matter, as there are no other PHYs on the bus. + */ +static void uec_configure_serdes(struct net_device *dev) +{ + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct ucc_geth_info *ug_info = ugeth-ug_info; + struct phy_device *tbiphy; + + if (!ug_info-tbi_node) { + dev_warn(dev-dev, SGMII mode requires that the device + tree specify a tbi-handle\n); + return; + } + + tbiphy = of_phy_find_device(ug_info-tbi_node); + if (!tbiphy) { + dev_err(dev-dev, error: Could not get TBI device\n); + return; + } + + /* +* If the link is already up, we must already be ok, and don't need to +* configure and reset the TBI-SerDes link. Maybe U-Boot configured +* everything for us? Resetting it takes the link down and requires +* several seconds for it to come back. +*/ + if (phy_read(tbiphy, ENET_TBI_MII_SR) TBISR_LSTATUS) + return; + + /* Single clk mode, mii mode off(for serdes communication) */ + phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS); + + phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT); + + phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS); +} + /* Configure the PHY for dev. * returns 0 if success. -1 if failure */ @@ -1554,6 +1600,9 @@ static int init_phy(struct net_device *dev) return -ENODEV; } + if (priv-phy_interface == PHY_INTERFACE_MODE_SGMII) + uec_configure_serdes(dev); + phydev-supported = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | @@ -3531,6 +3580,8 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type) return PHY_INTERFACE_MODE_RGMII_RXID; if (strcasecmp(phy_connection_type, rtbi) == 0) return PHY_INTERFACE_MODE_RTBI; + if (strcasecmp(phy_connection_type, sgmii) == 0) + return PHY_INTERFACE_MODE_SGMII; return PHY_INTERFACE_MODE_MII; } @@ -3575,6 +3626,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_GMII,
[PATCH 2/2] net/ucc_geth: Add SGMII support for UCC GETH driver
From: Haiying Wang haiying.w...@freescale.com -- derived from reverted commit 047584ce94108012288554a5f84585d792cc7f8f -- reworked by Grant Likely to play nice with commit: net: Rework ucc_geth driver to use of_mdio infrastructure (0b9da337dca972e7a4144e298ec3adb8f244d4a4) Signed-off-by: Haiying Wang haiying.w...@freescale.com Signed-off-by: David S. Miller da...@davemloft.net Signed-off-by: Grant Likely grant.lik...@secretlab.ca --- arch/powerpc/include/asm/qe.h |2 + drivers/net/ucc_geth.c| 58 - drivers/net/ucc_geth.h| 28 +++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index e0faf33..157c5ca 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h @@ -675,6 +675,8 @@ struct ucc_slow_pram { #define UCC_GETH_UPSMR_RMM 0x1000 #define UCC_GETH_UPSMR_CAM 0x0400 #define UCC_GETH_UPSMR_BRO 0x0200 +#define UCC_GETH_UPSMR_SMM 0x0080 +#define UCC_GETH_UPSMR_SGMM0x0020 /* UCC Transmit On Demand Register (UTODR) */ #define UCC_SLOW_TOD 0x8000 diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 5118993..40c6eba 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved. + * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved. * * Author: Shlomi Gridish grid...@freescale.com *Li Yang le...@freescale.com @@ -1410,6 +1410,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) (ugeth-phy_interface == PHY_INTERFACE_MODE_RTBI)) { upsmr |= UCC_GETH_UPSMR_TBIM; } + if ((ugeth-phy_interface == PHY_INTERFACE_MODE_SGMII)) + upsmr |= UCC_GETH_UPSMR_SGMM; + out_be32(uf_regs-upsmr, upsmr); /* Disable autonegotiation in tbi mode, because by default it @@ -1531,6 +1534,49 @@ static void adjust_link(struct net_device *dev) spin_unlock_irqrestore(ugeth-lock, flags); } +/* Initialize TBI PHY interface for communicating with the + * SERDES lynx PHY on the chip. We communicate with this PHY + * through the MDIO bus on each controller, treating it as a + * normal PHY at the address found in the UTBIPA register. We assume + * that the UTBIPA register is valid. Either the MDIO bus code will set + * it to a value that doesn't conflict with other PHYs on the bus, or the + * value doesn't matter, as there are no other PHYs on the bus. + */ +static void uec_configure_serdes(struct net_device *dev) +{ + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct ucc_geth_info *ug_info = ugeth-ug_info; + struct phy_device *tbiphy; + + if (!ug_info-tbi_node) { + dev_warn(dev-dev, SGMII mode requires that the device + tree specify a tbi-handle\n); + return; + } + + tbiphy = of_phy_find_device(ug_info-tbi_node); + if (!tbiphy) { + dev_err(dev-dev, error: Could not get TBI device\n); + return; + } + + /* +* If the link is already up, we must already be ok, and don't need to +* configure and reset the TBI-SerDes link. Maybe U-Boot configured +* everything for us? Resetting it takes the link down and requires +* several seconds for it to come back. +*/ + if (phy_read(tbiphy, ENET_TBI_MII_SR) TBISR_LSTATUS) + return; + + /* Single clk mode, mii mode off(for serdes communication) */ + phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS); + + phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT); + + phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS); +} + /* Configure the PHY for dev. * returns 0 if success. -1 if failure */ @@ -1554,6 +1600,9 @@ static int init_phy(struct net_device *dev) return -ENODEV; } + if (priv-phy_interface == PHY_INTERFACE_MODE_SGMII) + uec_configure_serdes(dev); + phydev-supported = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | @@ -3531,6 +3580,8 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type) return PHY_INTERFACE_MODE_RGMII_RXID; if (strcasecmp(phy_connection_type, rtbi) == 0) return PHY_INTERFACE_MODE_RTBI; + if (strcasecmp(phy_connection_type, sgmii) == 0) + return PHY_INTERFACE_MODE_SGMII; return PHY_INTERFACE_MODE_MII; } @@ -3575,6 +3626,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_GMII,