aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ucc_geth.c
diff options
context:
space:
mode:
authorHaiying Wang <Haiying.Wang@freescale.com>2009-06-02 00:04:15 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-03 05:52:47 -0400
commit047584ce94108012288554a5f84585d792cc7f8f (patch)
tree9529f6cd517e283d6df062aeb658938d1bd9ff5e /drivers/net/ucc_geth.c
parentfbcc0e2ce5a4fde63c7f33153bd7e3a4791e01c8 (diff)
net/ucc_geth: Add SGMII support for UEC GETH driver
Signed-off-by: Haiying Wang <Haiying.Wang@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r--drivers/net/ucc_geth.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 0cf22c4f123b..fd6140bd9aae 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved. 2 * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved.
3 * 3 *
4 * Author: Shlomi Gridish <gridish@freescale.com> 4 * Author: Shlomi Gridish <gridish@freescale.com>
5 * Li Yang <leoli@freescale.com> 5 * Li Yang <leoli@freescale.com>
@@ -65,6 +65,8 @@
65 65
66static DEFINE_SPINLOCK(ugeth_lock); 66static DEFINE_SPINLOCK(ugeth_lock);
67 67
68static void uec_configure_serdes(struct net_device *dev);
69
68static struct { 70static struct {
69 u32 msg_enable; 71 u32 msg_enable;
70} debug = { -1 }; 72} debug = { -1 };
@@ -1410,6 +1412,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
1410 (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { 1412 (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
1411 upsmr |= UCC_GETH_UPSMR_TBIM; 1413 upsmr |= UCC_GETH_UPSMR_TBIM;
1412 } 1414 }
1415 if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII))
1416 upsmr |= UCC_GETH_UPSMR_SGMM;
1417
1413 out_be32(&uf_regs->upsmr, upsmr); 1418 out_be32(&uf_regs->upsmr, upsmr);
1414 1419
1415 /* Disable autonegotiation in tbi mode, because by default it 1420 /* Disable autonegotiation in tbi mode, because by default it
@@ -1554,6 +1559,9 @@ static int init_phy(struct net_device *dev)
1554 return -ENODEV; 1559 return -ENODEV;
1555 } 1560 }
1556 1561
1562 if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
1563 uec_configure_serdes(dev);
1564
1557 phydev->supported &= (ADVERTISED_10baseT_Half | 1565 phydev->supported &= (ADVERTISED_10baseT_Half |
1558 ADVERTISED_10baseT_Full | 1566 ADVERTISED_10baseT_Full |
1559 ADVERTISED_100baseT_Half | 1567 ADVERTISED_100baseT_Half |
@@ -1569,7 +1577,41 @@ static int init_phy(struct net_device *dev)
1569 return 0; 1577 return 0;
1570} 1578}
1571 1579
1580/* Initialize TBI PHY interface for communicating with the
1581 * SERDES lynx PHY on the chip. We communicate with this PHY
1582 * through the MDIO bus on each controller, treating it as a
1583 * "normal" PHY at the address found in the UTBIPA register. We assume
1584 * that the UTBIPA register is valid. Either the MDIO bus code will set
1585 * it to a value that doesn't conflict with other PHYs on the bus, or the
1586 * value doesn't matter, as there are no other PHYs on the bus.
1587 */
1588static void uec_configure_serdes(struct net_device *dev)
1589{
1590 struct ucc_geth_private *ugeth = netdev_priv(dev);
1591
1592 if (!ugeth->tbiphy) {
1593 printk(KERN_WARNING "SGMII mode requires that the device "
1594 "tree specify a tbi-handle\n");
1595 return;
1596 }
1597
1598 /*
1599 * If the link is already up, we must already be ok, and don't need to
1600 * configure and reset the TBI<->SerDes link. Maybe U-Boot configured
1601 * everything for us? Resetting it takes the link down and requires
1602 * several seconds for it to come back.
1603 */
1604 if (phy_read(ugeth->tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS)
1605 return;
1606
1607 /* Single clk mode, mii mode off(for serdes communication) */
1608 phy_write(ugeth->tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
1572 1609
1610 phy_write(ugeth->tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
1611
1612 phy_write(ugeth->tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
1613
1614}
1573 1615
1574static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) 1616static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
1575{ 1617{
@@ -3523,6 +3565,8 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type)
3523 return PHY_INTERFACE_MODE_RGMII_RXID; 3565 return PHY_INTERFACE_MODE_RGMII_RXID;
3524 if (strcasecmp(phy_connection_type, "rtbi") == 0) 3566 if (strcasecmp(phy_connection_type, "rtbi") == 0)
3525 return PHY_INTERFACE_MODE_RTBI; 3567 return PHY_INTERFACE_MODE_RTBI;
3568 if (strcasecmp(phy_connection_type, "sgmii") == 0)
3569 return PHY_INTERFACE_MODE_SGMII;
3526 3570
3527 return PHY_INTERFACE_MODE_MII; 3571 return PHY_INTERFACE_MODE_MII;
3528} 3572}
@@ -3567,6 +3611,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3567 PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, 3611 PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII,
3568 PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII, 3612 PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
3569 PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, 3613 PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
3614 PHY_INTERFACE_MODE_SGMII,
3570 }; 3615 };
3571 3616
3572 ugeth_vdbg("%s: IN", __func__); 3617 ugeth_vdbg("%s: IN", __func__);
@@ -3682,6 +3727,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3682 case PHY_INTERFACE_MODE_RGMII_TXID: 3727 case PHY_INTERFACE_MODE_RGMII_TXID:
3683 case PHY_INTERFACE_MODE_TBI: 3728 case PHY_INTERFACE_MODE_TBI:
3684 case PHY_INTERFACE_MODE_RTBI: 3729 case PHY_INTERFACE_MODE_RTBI:
3730 case PHY_INTERFACE_MODE_SGMII:
3685 max_speed = SPEED_1000; 3731 max_speed = SPEED_1000;
3686 break; 3732 break;
3687 default: 3733 default:
@@ -3756,6 +3802,37 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3756 ugeth->ndev = dev; 3802 ugeth->ndev = dev;
3757 ugeth->node = np; 3803 ugeth->node = np;
3758 3804
3805 /* Find the TBI PHY. If it's not there, we don't support SGMII */
3806 ph = of_get_property(np, "tbi-handle", NULL);
3807 if (ph) {
3808 struct device_node *tbi = of_find_node_by_phandle(*ph);
3809 struct of_device *ofdev;
3810 struct mii_bus *bus;
3811 const unsigned int *id;
3812
3813 if (!tbi)
3814 return 0;
3815
3816 mdio = of_get_parent(tbi);
3817 if (!mdio)
3818 return 0;
3819
3820 ofdev = of_find_device_by_node(mdio);
3821
3822 of_node_put(mdio);
3823
3824 id = of_get_property(tbi, "reg", NULL);
3825 if (!id)
3826 return 0;
3827 of_node_put(tbi);
3828
3829 bus = dev_get_drvdata(&ofdev->dev);
3830 if (!bus)
3831 return 0;
3832
3833 ugeth->tbiphy = bus->phy_map[*id];
3834 }
3835
3759 return 0; 3836 return 0;
3760} 3837}
3761 3838