Commit 2a22b7ae authored by Jiawen Wu's avatar Jiawen Wu Committed by David S. Miller

net: pcs: xpcs: adapt Wangxun NICs for SGMII mode

Wangxun NICs support the connection with SFP to RJ45 module. In this case,
PCS need to be configured in SGMII mode.

According to chapter 6.11.1 "SGMII Auto-Negitiation" of DesignWare Cores
Ethernet PCS (version 3.20a) and custom design manual, do the following
configuration when the interface mode is SGMII.

1. program VR_MII_AN_CTRL bit(3) [TX_CONFIG] = 1b (PHY side SGMII)
2. program VR_MII_AN_CTRL bit(8) [MII_CTRL] = 1b (8-bit MII)
3. program VR_MII_DIG_CTRL1 bit(0) [PHY_MODE_CTRL] = 1b

Also CL37 AN in backplane configurations need to be enabled because of the
special hardware design. Another thing to note is that PMA needs to be
reconfigured before each CL37 AN configuration for SGMII, otherwise AN will
fail, although we don't know why.

On this device, CL37_ANSGM_STS (bit[4:1] of VR_MII_AN_INTR_STS) indicates
the status received from remote link during the auto-negotiation, and
self-clear after the auto-negotiation is complete.
Meanwhile, CL37_ANCMPLT_INTR will be set to 1, to indicate CL37 AN is
complete. So add another way to get the state for CL37 SGMII.
Signed-off-by: default avatarJiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2deea43f
...@@ -162,8 +162,9 @@ static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs) ...@@ -162,8 +162,9 @@ static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs)
/* When txgbe do LAN reset, PCS will change to default 10GBASE-R mode */ /* When txgbe do LAN reset, PCS will change to default 10GBASE-R mode */
ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL2); ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL2);
ret &= MDIO_PCS_CTRL2_TYPE; ret &= MDIO_PCS_CTRL2_TYPE;
if (ret == MDIO_PCS_CTRL2_10GBR && if ((ret == MDIO_PCS_CTRL2_10GBR &&
xpcs->interface != PHY_INTERFACE_MODE_10GBASER) xpcs->interface != PHY_INTERFACE_MODE_10GBASER) ||
xpcs->interface == PHY_INTERFACE_MODE_SGMII)
return true; return true;
return false; return false;
......
...@@ -683,7 +683,10 @@ EXPORT_SYMBOL_GPL(xpcs_config_eee); ...@@ -683,7 +683,10 @@ EXPORT_SYMBOL_GPL(xpcs_config_eee);
static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
unsigned int neg_mode) unsigned int neg_mode)
{ {
int ret, mdio_ctrl; int ret, mdio_ctrl, tx_conf;
if (xpcs->dev_flag == DW_DEV_TXGBE)
xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_CL37_BP | DW_EN_VSMMD1);
/* For AN for C37 SGMII mode, the settings are :- /* For AN for C37 SGMII mode, the settings are :-
* 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case * 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case
...@@ -720,9 +723,15 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, ...@@ -720,9 +723,15 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
ret |= (DW_VR_MII_PCS_MODE_C37_SGMII << ret |= (DW_VR_MII_PCS_MODE_C37_SGMII <<
DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT & DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT &
DW_VR_MII_PCS_MODE_MASK); DW_VR_MII_PCS_MODE_MASK);
ret |= (DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII << if (xpcs->dev_flag == DW_DEV_TXGBE) {
DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT & ret |= DW_VR_MII_AN_CTRL_8BIT;
DW_VR_MII_TX_CONFIG_MASK); /* Hardware requires it to be PHY side SGMII */
tx_conf = DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII;
} else {
tx_conf = DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII;
}
ret |= tx_conf << DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT &
DW_VR_MII_TX_CONFIG_MASK;
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret); ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -736,6 +745,9 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, ...@@ -736,6 +745,9 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
else else
ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
if (xpcs->dev_flag == DW_DEV_TXGBE)
ret |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret); ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1011,6 +1023,33 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs, ...@@ -1011,6 +1023,33 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
state->duplex = DUPLEX_FULL; state->duplex = DUPLEX_FULL;
else else
state->duplex = DUPLEX_HALF; state->duplex = DUPLEX_HALF;
} else if (ret == DW_VR_MII_AN_STS_C37_ANCMPLT_INTR) {
int speed, duplex;
state->link = true;
speed = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
if (speed < 0)
return speed;
speed &= SGMII_SPEED_SS13 | SGMII_SPEED_SS6;
if (speed == SGMII_SPEED_SS6)
state->speed = SPEED_1000;
else if (speed == SGMII_SPEED_SS13)
state->speed = SPEED_100;
else if (speed == 0)
state->speed = SPEED_10;
duplex = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_ADVERTISE);
if (duplex < 0)
return duplex;
if (duplex & DW_FULL_DUPLEX)
state->duplex = DUPLEX_FULL;
else if (duplex & DW_HALF_DUPLEX)
state->duplex = DUPLEX_HALF;
xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
} }
return 0; return 0;
......
...@@ -67,12 +67,14 @@ ...@@ -67,12 +67,14 @@
/* VR_MII_DIG_CTRL1 */ /* VR_MII_DIG_CTRL1 */
#define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9) #define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9)
#define DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL BIT(0)
/* VR_MII_DIG_CTRL2 */ /* VR_MII_DIG_CTRL2 */
#define DW_VR_MII_DIG_CTRL2_TX_POL_INV BIT(4) #define DW_VR_MII_DIG_CTRL2_TX_POL_INV BIT(4)
#define DW_VR_MII_DIG_CTRL2_RX_POL_INV BIT(0) #define DW_VR_MII_DIG_CTRL2_RX_POL_INV BIT(0)
/* VR_MII_AN_CTRL */ /* VR_MII_AN_CTRL */
#define DW_VR_MII_AN_CTRL_8BIT BIT(8)
#define DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT 3 #define DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT 3
#define DW_VR_MII_TX_CONFIG_MASK BIT(3) #define DW_VR_MII_TX_CONFIG_MASK BIT(3)
#define DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII 0x1 #define DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII 0x1
...@@ -98,6 +100,10 @@ ...@@ -98,6 +100,10 @@
#define SGMII_SPEED_SS13 BIT(13) /* SGMII speed along with SS6 */ #define SGMII_SPEED_SS13 BIT(13) /* SGMII speed along with SS6 */
#define SGMII_SPEED_SS6 BIT(6) /* SGMII speed along with SS13 */ #define SGMII_SPEED_SS6 BIT(6) /* SGMII speed along with SS13 */
/* SR MII MMD AN Advertisement defines */
#define DW_HALF_DUPLEX BIT(6)
#define DW_FULL_DUPLEX BIT(5)
/* VR MII EEE Control 0 defines */ /* VR MII EEE Control 0 defines */
#define DW_VR_MII_EEE_LTX_EN BIT(0) /* LPI Tx Enable */ #define DW_VR_MII_EEE_LTX_EN BIT(0) /* LPI Tx Enable */
#define DW_VR_MII_EEE_LRX_EN BIT(1) /* LPI Rx Enable */ #define DW_VR_MII_EEE_LRX_EN BIT(1) /* LPI Rx Enable */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment