[PATCH 2/2] net/ucc_geth: Add SGMII support for UCC GETH driver

2009-06-17 Thread Grant Likely
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

2009-06-17 Thread Grant Likely
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,