mirror of https://gitee.com/openkylin/linux.git
net/ucc_geth: Add SGMII support for UCC GETH driver
-- derived from reverted commit047584ce94
-- reworked by Grant Likely to play nice with commit: "net: Rework ucc_geth driver to use of_mdio infrastructure" (0b9da337dc
) 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>
This commit is contained in:
parent
f3a32500ba
commit
fb1001f3de
|
@ -668,6 +668,8 @@ struct ucc_slow_pram {
|
||||||
#define UCC_GETH_UPSMR_RMM 0x00001000
|
#define UCC_GETH_UPSMR_RMM 0x00001000
|
||||||
#define UCC_GETH_UPSMR_CAM 0x00000400
|
#define UCC_GETH_UPSMR_CAM 0x00000400
|
||||||
#define UCC_GETH_UPSMR_BRO 0x00000200
|
#define UCC_GETH_UPSMR_BRO 0x00000200
|
||||||
|
#define UCC_GETH_UPSMR_SMM 0x00000080
|
||||||
|
#define UCC_GETH_UPSMR_SGMM 0x00000020
|
||||||
|
|
||||||
/* UCC Transmit On Demand Register (UTODR) */
|
/* UCC Transmit On Demand Register (UTODR) */
|
||||||
#define UCC_SLOW_TOD 0x8000
|
#define UCC_SLOW_TOD 0x8000
|
||||||
|
|
|
@ -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 <gridish@freescale.com>
|
* Author: Shlomi Gridish <gridish@freescale.com>
|
||||||
* Li Yang <leoli@freescale.com>
|
* Li Yang <leoli@freescale.com>
|
||||||
|
@ -1410,6 +1410,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
|
||||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
|
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
|
||||||
upsmr |= UCC_GETH_UPSMR_TBIM;
|
upsmr |= UCC_GETH_UPSMR_TBIM;
|
||||||
}
|
}
|
||||||
|
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII))
|
||||||
|
upsmr |= UCC_GETH_UPSMR_SGMM;
|
||||||
|
|
||||||
out_be32(&uf_regs->upsmr, upsmr);
|
out_be32(&uf_regs->upsmr, upsmr);
|
||||||
|
|
||||||
/* Disable autonegotiation in tbi mode, because by default it
|
/* 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);
|
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.
|
/* Configure the PHY for dev.
|
||||||
* returns 0 if success. -1 if failure
|
* returns 0 if success. -1 if failure
|
||||||
*/
|
*/
|
||||||
|
@ -1554,6 +1600,9 @@ static int init_phy(struct net_device *dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
|
||||||
|
uec_configure_serdes(dev);
|
||||||
|
|
||||||
phydev->supported &= (ADVERTISED_10baseT_Half |
|
phydev->supported &= (ADVERTISED_10baseT_Half |
|
||||||
ADVERTISED_10baseT_Full |
|
ADVERTISED_10baseT_Full |
|
||||||
ADVERTISED_100baseT_Half |
|
ADVERTISED_100baseT_Half |
|
||||||
|
@ -3523,6 +3572,8 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type)
|
||||||
return PHY_INTERFACE_MODE_RGMII_RXID;
|
return PHY_INTERFACE_MODE_RGMII_RXID;
|
||||||
if (strcasecmp(phy_connection_type, "rtbi") == 0)
|
if (strcasecmp(phy_connection_type, "rtbi") == 0)
|
||||||
return PHY_INTERFACE_MODE_RTBI;
|
return PHY_INTERFACE_MODE_RTBI;
|
||||||
|
if (strcasecmp(phy_connection_type, "sgmii") == 0)
|
||||||
|
return PHY_INTERFACE_MODE_SGMII;
|
||||||
|
|
||||||
return PHY_INTERFACE_MODE_MII;
|
return PHY_INTERFACE_MODE_MII;
|
||||||
}
|
}
|
||||||
|
@ -3567,6 +3618,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_RMII, PHY_INTERFACE_MODE_RGMII,
|
||||||
PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
|
PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
|
||||||
PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
|
PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
|
||||||
|
PHY_INTERFACE_MODE_SGMII,
|
||||||
};
|
};
|
||||||
|
|
||||||
ugeth_vdbg("%s: IN", __func__);
|
ugeth_vdbg("%s: IN", __func__);
|
||||||
|
@ -3658,6 +3710,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
|
||||||
}
|
}
|
||||||
ug_info->phy_node = phy;
|
ug_info->phy_node = phy;
|
||||||
|
|
||||||
|
/* Find the TBI PHY node. If it's not there, we don't support SGMII */
|
||||||
|
ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
|
||||||
|
|
||||||
/* get the phy interface type, or default to MII */
|
/* get the phy interface type, or default to MII */
|
||||||
prop = of_get_property(np, "phy-connection-type", NULL);
|
prop = of_get_property(np, "phy-connection-type", NULL);
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
|
@ -3682,6 +3737,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
|
||||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||||
case PHY_INTERFACE_MODE_TBI:
|
case PHY_INTERFACE_MODE_TBI:
|
||||||
case PHY_INTERFACE_MODE_RTBI:
|
case PHY_INTERFACE_MODE_RTBI:
|
||||||
|
case PHY_INTERFACE_MODE_SGMII:
|
||||||
max_speed = SPEED_1000;
|
max_speed = SPEED_1000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
|
* Copyright (C) Freescale Semicondutor, Inc. 2006-2009. All rights reserved.
|
||||||
*
|
*
|
||||||
* Author: Shlomi Gridish <gridish@freescale.com>
|
* Author: Shlomi Gridish <gridish@freescale.com>
|
||||||
*
|
*
|
||||||
|
@ -193,6 +193,31 @@ struct ucc_geth {
|
||||||
#define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */
|
#define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */
|
||||||
#define ENET_TBI_MII_TBICON 0x11 /* TBI control */
|
#define ENET_TBI_MII_TBICON 0x11 /* TBI control */
|
||||||
|
|
||||||
|
/* TBI MDIO register bit fields*/
|
||||||
|
#define TBISR_LSTATUS 0x0004
|
||||||
|
#define TBICON_CLK_SELECT 0x0020
|
||||||
|
#define TBIANA_ASYMMETRIC_PAUSE 0x0100
|
||||||
|
#define TBIANA_SYMMETRIC_PAUSE 0x0080
|
||||||
|
#define TBIANA_HALF_DUPLEX 0x0040
|
||||||
|
#define TBIANA_FULL_DUPLEX 0x0020
|
||||||
|
#define TBICR_PHY_RESET 0x8000
|
||||||
|
#define TBICR_ANEG_ENABLE 0x1000
|
||||||
|
#define TBICR_RESTART_ANEG 0x0200
|
||||||
|
#define TBICR_FULL_DUPLEX 0x0100
|
||||||
|
#define TBICR_SPEED1_SET 0x0040
|
||||||
|
|
||||||
|
#define TBIANA_SETTINGS ( \
|
||||||
|
TBIANA_ASYMMETRIC_PAUSE \
|
||||||
|
| TBIANA_SYMMETRIC_PAUSE \
|
||||||
|
| TBIANA_FULL_DUPLEX \
|
||||||
|
)
|
||||||
|
#define TBICR_SETTINGS ( \
|
||||||
|
TBICR_PHY_RESET \
|
||||||
|
| TBICR_ANEG_ENABLE \
|
||||||
|
| TBICR_FULL_DUPLEX \
|
||||||
|
| TBICR_SPEED1_SET \
|
||||||
|
)
|
||||||
|
|
||||||
/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
|
/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
|
||||||
#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control
|
#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control
|
||||||
Rx */
|
Rx */
|
||||||
|
@ -1100,6 +1125,7 @@ struct ucc_geth_info {
|
||||||
u16 pausePeriod;
|
u16 pausePeriod;
|
||||||
u16 extensionField;
|
u16 extensionField;
|
||||||
struct device_node *phy_node;
|
struct device_node *phy_node;
|
||||||
|
struct device_node *tbi_node;
|
||||||
u8 weightfactor[NUM_TX_QUEUES];
|
u8 weightfactor[NUM_TX_QUEUES];
|
||||||
u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
|
u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
|
||||||
u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
|
u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
|
||||||
|
|
Loading…
Reference in New Issue