aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaiying Wang <Haiying.Wang@freescale.com>2009-06-17 09:16:10 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-17 21:46:45 -0400
commitfb1001f3de1a8576b25d929502f1fe7865ff32dc (patch)
treeafb9115df813d278e7747ccfc6c138464fe92a23
parentf3a32500ba8f3ec9ee0c12836fcfd315f1256db4 (diff)
net/ucc_geth: Add SGMII support for UCC GETH driver
-- 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.Wang@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/powerpc/include/asm/qe.h2
-rw-r--r--drivers/net/ucc_geth.c58
-rw-r--r--drivers/net/ucc_geth.h28
3 files changed, 86 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index 2701753d9937..4459d20dc76a 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -668,6 +668,8 @@ struct ucc_slow_pram {
668#define UCC_GETH_UPSMR_RMM 0x00001000 668#define UCC_GETH_UPSMR_RMM 0x00001000
669#define UCC_GETH_UPSMR_CAM 0x00000400 669#define UCC_GETH_UPSMR_CAM 0x00000400
670#define UCC_GETH_UPSMR_BRO 0x00000200 670#define UCC_GETH_UPSMR_BRO 0x00000200
671#define UCC_GETH_UPSMR_SMM 0x00000080
672#define UCC_GETH_UPSMR_SGMM 0x00000020
671 673
672/* UCC Transmit On Demand Register (UTODR) */ 674/* UCC Transmit On Demand Register (UTODR) */
673#define UCC_SLOW_TOD 0x8000 675#define UCC_SLOW_TOD 0x8000
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 0cf22c4f123b..255d28d4f84e 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>
@@ -1410,6 +1410,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
1410 (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { 1410 (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
1411 upsmr |= UCC_GETH_UPSMR_TBIM; 1411 upsmr |= UCC_GETH_UPSMR_TBIM;
1412 } 1412 }
1413 if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII))
1414 upsmr |= UCC_GETH_UPSMR_SGMM;
1415
1413 out_be32(&uf_regs->upsmr, upsmr); 1416 out_be32(&uf_regs->upsmr, upsmr);
1414 1417
1415 /* Disable autonegotiation in tbi mode, because by default it 1418 /* Disable autonegotiation in tbi mode, because by default it
@@ -1531,6 +1534,49 @@ static void adjust_link(struct net_device *dev)
1531 spin_unlock_irqrestore(&ugeth->lock, flags); 1534 spin_unlock_irqrestore(&ugeth->lock, flags);
1532} 1535}
1533 1536
1537/* Initialize TBI PHY interface for communicating with the
1538 * SERDES lynx PHY on the chip. We communicate with this PHY
1539 * through the MDIO bus on each controller, treating it as a
1540 * "normal" PHY at the address found in the UTBIPA register. We assume
1541 * that the UTBIPA register is valid. Either the MDIO bus code will set
1542 * it to a value that doesn't conflict with other PHYs on the bus, or the
1543 * value doesn't matter, as there are no other PHYs on the bus.
1544 */
1545static void uec_configure_serdes(struct net_device *dev)
1546{
1547 struct ucc_geth_private *ugeth = netdev_priv(dev);
1548 struct ucc_geth_info *ug_info = ugeth->ug_info;
1549 struct phy_device *tbiphy;
1550
1551 if (!ug_info->tbi_node) {
1552 dev_warn(&dev->dev, "SGMII mode requires that the device "
1553 "tree specify a tbi-handle\n");
1554 return;
1555 }
1556
1557 tbiphy = of_phy_find_device(ug_info->tbi_node);
1558 if (!tbiphy) {
1559 dev_err(&dev->dev, "error: Could not get TBI device\n");
1560 return;
1561 }
1562
1563 /*
1564 * If the link is already up, we must already be ok, and don't need to
1565 * configure and reset the TBI<->SerDes link. Maybe U-Boot configured
1566 * everything for us? Resetting it takes the link down and requires
1567 * several seconds for it to come back.
1568 */
1569 if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS)
1570 return;
1571
1572 /* Single clk mode, mii mode off(for serdes communication) */
1573 phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
1574
1575 phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
1576
1577 phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
1578}
1579
1534/* Configure the PHY for dev. 1580/* Configure the PHY for dev.
1535 * returns 0 if success. -1 if failure 1581 * returns 0 if success. -1 if failure
1536 */ 1582 */
@@ -1554,6 +1600,9 @@ static int init_phy(struct net_device *dev)
1554 return -ENODEV; 1600 return -ENODEV;
1555 } 1601 }
1556 1602
1603 if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
1604 uec_configure_serdes(dev);
1605
1557 phydev->supported &= (ADVERTISED_10baseT_Half | 1606 phydev->supported &= (ADVERTISED_10baseT_Half |
1558 ADVERTISED_10baseT_Full | 1607 ADVERTISED_10baseT_Full |
1559 ADVERTISED_100baseT_Half | 1608 ADVERTISED_100baseT_Half |
@@ -3523,6 +3572,8 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type)
3523 return PHY_INTERFACE_MODE_RGMII_RXID; 3572 return PHY_INTERFACE_MODE_RGMII_RXID;
3524 if (strcasecmp(phy_connection_type, "rtbi") == 0) 3573 if (strcasecmp(phy_connection_type, "rtbi") == 0)
3525 return PHY_INTERFACE_MODE_RTBI; 3574 return PHY_INTERFACE_MODE_RTBI;
3575 if (strcasecmp(phy_connection_type, "sgmii") == 0)
3576 return PHY_INTERFACE_MODE_SGMII;
3526 3577
3527 return PHY_INTERFACE_MODE_MII; 3578 return PHY_INTERFACE_MODE_MII;
3528} 3579}
@@ -3567,6 +3618,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, 3618 PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII,
3568 PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII, 3619 PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
3569 PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, 3620 PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
3621 PHY_INTERFACE_MODE_SGMII,
3570 }; 3622 };
3571 3623
3572 ugeth_vdbg("%s: IN", __func__); 3624 ugeth_vdbg("%s: IN", __func__);
@@ -3658,6 +3710,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3658 } 3710 }
3659 ug_info->phy_node = phy; 3711 ug_info->phy_node = phy;
3660 3712
3713 /* Find the TBI PHY node. If it's not there, we don't support SGMII */
3714 ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
3715
3661 /* get the phy interface type, or default to MII */ 3716 /* get the phy interface type, or default to MII */
3662 prop = of_get_property(np, "phy-connection-type", NULL); 3717 prop = of_get_property(np, "phy-connection-type", NULL);
3663 if (!prop) { 3718 if (!prop) {
@@ -3682,6 +3737,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3682 case PHY_INTERFACE_MODE_RGMII_TXID: 3737 case PHY_INTERFACE_MODE_RGMII_TXID:
3683 case PHY_INTERFACE_MODE_TBI: 3738 case PHY_INTERFACE_MODE_TBI:
3684 case PHY_INTERFACE_MODE_RTBI: 3739 case PHY_INTERFACE_MODE_RTBI:
3740 case PHY_INTERFACE_MODE_SGMII:
3685 max_speed = SPEED_1000; 3741 max_speed = SPEED_1000;
3686 break; 3742 break;
3687 default: 3743 default:
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index dca628a922ba..1525bf51341c 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. 2 * Copyright (C) Freescale Semicondutor, Inc. 2006-2009. All rights reserved.
3 * 3 *
4 * Author: Shlomi Gridish <gridish@freescale.com> 4 * Author: Shlomi Gridish <gridish@freescale.com>
5 * 5 *
@@ -193,6 +193,31 @@ struct ucc_geth {
193#define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */ 193#define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */
194#define ENET_TBI_MII_TBICON 0x11 /* TBI control */ 194#define ENET_TBI_MII_TBICON 0x11 /* TBI control */
195 195
196/* TBI MDIO register bit fields*/
197#define TBISR_LSTATUS 0x0004
198#define TBICON_CLK_SELECT 0x0020
199#define TBIANA_ASYMMETRIC_PAUSE 0x0100
200#define TBIANA_SYMMETRIC_PAUSE 0x0080
201#define TBIANA_HALF_DUPLEX 0x0040
202#define TBIANA_FULL_DUPLEX 0x0020
203#define TBICR_PHY_RESET 0x8000
204#define TBICR_ANEG_ENABLE 0x1000
205#define TBICR_RESTART_ANEG 0x0200
206#define TBICR_FULL_DUPLEX 0x0100
207#define TBICR_SPEED1_SET 0x0040
208
209#define TBIANA_SETTINGS ( \
210 TBIANA_ASYMMETRIC_PAUSE \
211 | TBIANA_SYMMETRIC_PAUSE \
212 | TBIANA_FULL_DUPLEX \
213 )
214#define TBICR_SETTINGS ( \
215 TBICR_PHY_RESET \
216 | TBICR_ANEG_ENABLE \
217 | TBICR_FULL_DUPLEX \
218 | TBICR_SPEED1_SET \
219 )
220
196/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ 221/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
197#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control 222#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control
198 Rx */ 223 Rx */
@@ -1100,6 +1125,7 @@ struct ucc_geth_info {
1100 u16 pausePeriod; 1125 u16 pausePeriod;
1101 u16 extensionField; 1126 u16 extensionField;
1102 struct device_node *phy_node; 1127 struct device_node *phy_node;
1128 struct device_node *tbi_node;
1103 u8 weightfactor[NUM_TX_QUEUES]; 1129 u8 weightfactor[NUM_TX_QUEUES];
1104 u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; 1130 u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
1105 u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; 1131 u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];