Merge branch 'pcs-xpcs-cleanups-batch-2'
Russell King says: ==================== net: pcs: xpcs: cleanups batch 2 This is the second cleanup series for XPCS. Patch 1 removes the enum indexing the dw_xpcs_compat array. The index is never used except to place entries in the array and to size the array. Patch 2 removes the interface arrays - each of which only contain one interface. Patch 3 makes xpcs_find_compat() take the xpcs structure rather than the ID - the previous series removed the reason for xpcs_find_compat needing to take the ID. Patch 4 provides a helper to convert xpcs structure to a regular phylink_pcs structure, which leads to patch 5. Patch 5 moves the definition of struct dw_xpcs to the private xpcs header - with patch 4 in place, nothing outside of the xpcs driver accesses the contents of the dw_xpcs structure. Patch 6 renames xpcs_get_id() to xpcs_read_id() since it's reading the ID, rather than doing anything further with it. (Prior versions of this series renamed it to xpcs_read_phys_id() since that more accurately described that it was reading the physical ID registers.) Patch 7 moves the searching of the ID list out of line as this is a separate functional block. Patch 8 converts xpcs to use the bitmap macros, which eliminates the need for _SHIFT definitions. Patch 9 adds and uses _modify() accessors as there are a large amount of read-modify-write operations in this driver. This conversion found a bug in xpcs-wx code that has been reported and already fixed. Patch 10 converts xpcs to use read_poll_timeout() rather than open coding that. Patch 11 converts all printed messages to use the dev_*() functions so the driver and devie name are always printed. Patch 12 moves DW_VR_MII_DIG_CTRL1_2G5_EN to the correct place in the header file, rather than amongst another register's definitions. Patch 13 moves the Wangxun workaround to a common location rather than duplicating it in two places. We also reformat this to fit within 80 columns. ==================== Tested-by: Serge Semin <fancer.lancer@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
f31fd0b3b2
6 changed files with 242 additions and 340 deletions
|
@ -451,7 +451,7 @@ static struct phylink_pcs *intel_mgbe_select_pcs(struct stmmac_priv *priv,
|
|||
* should always be an XPCS. The original code would always
|
||||
* return this if present.
|
||||
*/
|
||||
return &priv->hw->xpcs->pcs;
|
||||
return xpcs_to_phylink_pcs(priv->hw->xpcs);
|
||||
}
|
||||
|
||||
static int intel_mgbe_common_data(struct pci_dev *pdev,
|
||||
|
|
|
@ -152,26 +152,18 @@ static int nxp_sja1110_pma_config(struct dw_xpcs *xpcs,
|
|||
/* Enable TX and RX PLLs and circuits.
|
||||
* Release reset of PMA to enable data flow to/from PCS.
|
||||
*/
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = ret & ~(SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
|
||||
SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
|
||||
SJA1110_RESET_SER | SJA1110_RESET_DES);
|
||||
val |= SJA1110_RXPKDETEN | SJA1110_RCVEN;
|
||||
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE, val);
|
||||
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE,
|
||||
SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
|
||||
SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
|
||||
SJA1110_RESET_SER | SJA1110_RESET_DES |
|
||||
SJA1110_RXPKDETEN | SJA1110_RCVEN,
|
||||
SJA1110_RXPKDETEN | SJA1110_RCVEN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Program continuous-time linear equalizer (CTLE) settings. */
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE,
|
||||
rx_cdr_ctle);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE,
|
||||
rx_cdr_ctle);
|
||||
}
|
||||
|
||||
int nxp_sja1110_sgmii_pma_config(struct dw_xpcs *xpcs)
|
||||
|
|
|
@ -46,25 +46,23 @@
|
|||
#define TXGBE_VCO_CAL_LD0 0x72
|
||||
#define TXGBE_VCO_CAL_REF0 0x76
|
||||
|
||||
static int txgbe_read_pma(struct dw_xpcs *xpcs, int reg)
|
||||
{
|
||||
return xpcs_read(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg);
|
||||
}
|
||||
|
||||
static int txgbe_write_pma(struct dw_xpcs *xpcs, int reg, u16 val)
|
||||
{
|
||||
return xpcs_write(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val);
|
||||
}
|
||||
|
||||
static int txgbe_modify_pma(struct dw_xpcs *xpcs, int reg, u16 mask, u16 set)
|
||||
{
|
||||
return xpcs_modify(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, mask,
|
||||
set);
|
||||
}
|
||||
|
||||
static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs)
|
||||
{
|
||||
int val;
|
||||
|
||||
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x21);
|
||||
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0);
|
||||
val = txgbe_read_pma(xpcs, TXGBE_TX_GENCTL1);
|
||||
val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTL1_VBOOST_LVL);
|
||||
txgbe_write_pma(xpcs, TXGBE_TX_GENCTL1, val);
|
||||
txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1, TXGBE_TX_GENCTL1_VBOOST_LVL,
|
||||
FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
|
||||
txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
|
||||
TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
|
||||
txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x549);
|
||||
|
@ -78,38 +76,29 @@ static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs)
|
|||
|
||||
txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_CTLE_POLE(2) |
|
||||
TXGBE_RX_EQ_CTL0_CTLE_BOOST(5));
|
||||
val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL);
|
||||
val &= ~TXGBE_RX_EQ_ATTN_LVL0;
|
||||
txgbe_write_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, val);
|
||||
txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
|
||||
txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0xBE);
|
||||
val = txgbe_read_pma(xpcs, TXGBE_AFE_DFE_ENABLE);
|
||||
val &= ~(TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0);
|
||||
txgbe_write_pma(xpcs, TXGBE_AFE_DFE_ENABLE, val);
|
||||
val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_CTL4);
|
||||
val &= ~TXGBE_RX_EQ_CTL4_CONT_ADAPT0;
|
||||
txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL4, val);
|
||||
txgbe_modify_pma(xpcs, TXGBE_AFE_DFE_ENABLE,
|
||||
TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0, 0);
|
||||
txgbe_modify_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_ADAPT0,
|
||||
0);
|
||||
}
|
||||
|
||||
static void txgbe_pma_config_1g(struct dw_xpcs *xpcs)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = txgbe_read_pma(xpcs, TXGBE_TX_GENCTL1);
|
||||
val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTL1_VBOOST_LVL);
|
||||
val &= ~TXGBE_TX_GENCTL1_VBOOST_EN0;
|
||||
txgbe_write_pma(xpcs, TXGBE_TX_GENCTL1, val);
|
||||
txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1,
|
||||
TXGBE_TX_GENCTL1_VBOOST_LVL |
|
||||
TXGBE_TX_GENCTL1_VBOOST_EN0,
|
||||
FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
|
||||
txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
|
||||
TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
|
||||
|
||||
txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_VGA1_GAIN(7) |
|
||||
TXGBE_RX_EQ_CTL0_VGA2_GAIN(7) | TXGBE_RX_EQ_CTL0_CTLE_BOOST(6));
|
||||
val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL);
|
||||
val &= ~TXGBE_RX_EQ_ATTN_LVL0;
|
||||
txgbe_write_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, val);
|
||||
txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
|
||||
txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0);
|
||||
val = txgbe_read_pma(xpcs, TXGBE_RX_GEN_CTL3);
|
||||
val = u16_replace_bits(val, 0x4, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0);
|
||||
txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL3, val);
|
||||
txgbe_modify_pma(xpcs, TXGBE_RX_GEN_CTL3, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0,
|
||||
FIELD_PREP(TXGBE_RX_GEN_CTL3_LOS_TRSHLD0, 0x4));
|
||||
|
||||
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x20);
|
||||
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0x46);
|
||||
|
@ -172,7 +161,7 @@ static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs)
|
|||
|
||||
int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
|
||||
{
|
||||
int val, ret;
|
||||
int ret;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
|
@ -194,9 +183,8 @@ int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
|
|||
|
||||
if (interface == PHY_INTERFACE_MODE_10GBASER) {
|
||||
xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBR);
|
||||
val = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1);
|
||||
val |= MDIO_CTRL1_SPEED10G;
|
||||
xpcs_write(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1, val);
|
||||
xpcs_modify(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1,
|
||||
MDIO_CTRL1_SPEED10G, MDIO_CTRL1_SPEED10G);
|
||||
txgbe_pma_config_10gbaser(xpcs);
|
||||
} else {
|
||||
xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBX);
|
||||
|
|
|
@ -107,49 +107,9 @@ static const int xpcs_2500basex_features[] = {
|
|||
__ETHTOOL_LINK_MODE_MASK_NBITS,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_usxgmii_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_USXGMII,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_10gkr_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_10GKR,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_xlgmii_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_XLGMII,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_10gbaser_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_10GBASER,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_sgmii_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_SGMII,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_1000basex_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_1000BASEX,
|
||||
};
|
||||
|
||||
static const phy_interface_t xpcs_2500basex_interfaces[] = {
|
||||
PHY_INTERFACE_MODE_2500BASEX,
|
||||
};
|
||||
|
||||
enum {
|
||||
DW_XPCS_USXGMII,
|
||||
DW_XPCS_10GKR,
|
||||
DW_XPCS_XLGMII,
|
||||
DW_XPCS_10GBASER,
|
||||
DW_XPCS_SGMII,
|
||||
DW_XPCS_1000BASEX,
|
||||
DW_XPCS_2500BASEX,
|
||||
DW_XPCS_INTERFACE_MAX,
|
||||
};
|
||||
|
||||
struct dw_xpcs_compat {
|
||||
phy_interface_t interface;
|
||||
const int *supported;
|
||||
const phy_interface_t *interface;
|
||||
int num_interfaces;
|
||||
int an_mode;
|
||||
int (*pma_config)(struct dw_xpcs *xpcs);
|
||||
};
|
||||
|
@ -161,26 +121,28 @@ struct dw_xpcs_desc {
|
|||
};
|
||||
|
||||
static const struct dw_xpcs_compat *
|
||||
xpcs_find_compat(const struct dw_xpcs_desc *desc, phy_interface_t interface)
|
||||
xpcs_find_compat(struct dw_xpcs *xpcs, phy_interface_t interface)
|
||||
{
|
||||
int i, j;
|
||||
const struct dw_xpcs_compat *compat;
|
||||
|
||||
for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
|
||||
const struct dw_xpcs_compat *compat = &desc->compat[i];
|
||||
|
||||
for (j = 0; j < compat->num_interfaces; j++)
|
||||
if (compat->interface[j] == interface)
|
||||
return compat;
|
||||
}
|
||||
for (compat = xpcs->desc->compat; compat->supported; compat++)
|
||||
if (compat->interface == interface)
|
||||
return compat;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct phylink_pcs *xpcs_to_phylink_pcs(struct dw_xpcs *xpcs)
|
||||
{
|
||||
return &xpcs->pcs;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xpcs_to_phylink_pcs);
|
||||
|
||||
int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
|
||||
{
|
||||
const struct dw_xpcs_compat *compat;
|
||||
|
||||
compat = xpcs_find_compat(xpcs->desc, interface);
|
||||
compat = xpcs_find_compat(xpcs, interface);
|
||||
if (!compat)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -213,6 +175,11 @@ int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val)
|
|||
return mdiodev_c45_write(xpcs->mdiodev, dev, reg, val);
|
||||
}
|
||||
|
||||
int xpcs_modify(struct dw_xpcs *xpcs, int dev, u32 reg, u16 mask, u16 set)
|
||||
{
|
||||
return mdiodev_c45_modify(xpcs->mdiodev, dev, reg, mask, set);
|
||||
}
|
||||
|
||||
static int xpcs_modify_changed(struct dw_xpcs *xpcs, int dev, u32 reg,
|
||||
u16 mask, u16 set)
|
||||
{
|
||||
|
@ -230,6 +197,12 @@ static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg,
|
|||
return xpcs_write(xpcs, dev, DW_VENDOR | reg, val);
|
||||
}
|
||||
|
||||
static int xpcs_modify_vendor(struct dw_xpcs *xpcs, int dev, int reg, u16 mask,
|
||||
u16 set)
|
||||
{
|
||||
return xpcs_modify(xpcs, dev, DW_VENDOR | reg, mask, set);
|
||||
}
|
||||
|
||||
int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg)
|
||||
{
|
||||
return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg);
|
||||
|
@ -240,20 +213,22 @@ int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val)
|
|||
return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
|
||||
}
|
||||
|
||||
static int xpcs_modify_vpcs(struct dw_xpcs *xpcs, int reg, u16 mask, u16 val)
|
||||
{
|
||||
return xpcs_modify_vendor(xpcs, MDIO_MMD_PCS, reg, mask, val);
|
||||
}
|
||||
|
||||
static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev)
|
||||
{
|
||||
/* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
|
||||
unsigned int retries = 12;
|
||||
int ret;
|
||||
int ret, val;
|
||||
|
||||
do {
|
||||
msleep(50);
|
||||
ret = xpcs_read(xpcs, dev, MDIO_CTRL1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} while (ret & MDIO_CTRL1_RESET && --retries);
|
||||
ret = read_poll_timeout(xpcs_read, val,
|
||||
val < 0 || !(val & MDIO_CTRL1_RESET),
|
||||
50000, 600000, true, xpcs, dev, MDIO_CTRL1);
|
||||
if (val < 0)
|
||||
ret = val;
|
||||
|
||||
return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xpcs_soft_reset(struct dw_xpcs *xpcs,
|
||||
|
@ -364,37 +339,25 @@ static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
|
|||
return;
|
||||
}
|
||||
|
||||
ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
|
||||
ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_EN, DW_USXGMII_EN);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_EN);
|
||||
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, DW_USXGMII_SS_MASK,
|
||||
speed_sel | DW_USXGMII_FULL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret &= ~DW_USXGMII_SS_MASK;
|
||||
ret |= speed_sel | DW_USXGMII_FULL;
|
||||
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_RST);
|
||||
ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_RST,
|
||||
DW_USXGMII_RST);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
pr_err("%s: XPCS access returned %pe\n", __func__, ERR_PTR(ret));
|
||||
dev_err(&xpcs->mdiodev->dev, "%s: XPCS access returned %pe\n",
|
||||
__func__, ERR_PTR(ret));
|
||||
}
|
||||
|
||||
static int _xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
|
||||
|
@ -451,13 +414,9 @@ static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_CTRL1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
|
||||
|
||||
return xpcs_write(xpcs, MDIO_MMD_AN, MDIO_CTRL1, ret);
|
||||
return xpcs_modify(xpcs, MDIO_MMD_AN, MDIO_CTRL1,
|
||||
MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART,
|
||||
MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
|
||||
}
|
||||
|
||||
static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
|
||||
|
@ -592,7 +551,7 @@ static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
|
|||
int i;
|
||||
|
||||
xpcs = phylink_pcs_to_xpcs(pcs);
|
||||
compat = xpcs_find_compat(xpcs->desc, state->interface);
|
||||
compat = xpcs_find_compat(xpcs, state->interface);
|
||||
if (!compat)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -610,52 +569,40 @@ static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
|
|||
|
||||
void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
|
||||
{
|
||||
int i, j;
|
||||
const struct dw_xpcs_compat *compat;
|
||||
|
||||
for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
|
||||
const struct dw_xpcs_compat *compat = &xpcs->desc->compat[i];
|
||||
|
||||
for (j = 0; j < compat->num_interfaces; j++)
|
||||
__set_bit(compat->interface[j], interfaces);
|
||||
}
|
||||
for (compat = xpcs->desc->compat; compat->supported; compat++)
|
||||
__set_bit(compat->interface, interfaces);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xpcs_get_interfaces);
|
||||
|
||||
int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
|
||||
{
|
||||
u16 mask, val;
|
||||
int ret;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (enable) {
|
||||
/* Enable EEE */
|
||||
ret = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
|
||||
DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
|
||||
DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
|
||||
mult_fact_100ns << DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT;
|
||||
} else {
|
||||
ret &= ~(DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
|
||||
DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
|
||||
DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
|
||||
DW_VR_MII_EEE_MULT_FACT_100NS);
|
||||
}
|
||||
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
mask = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
|
||||
DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
|
||||
DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
|
||||
DW_VR_MII_EEE_MULT_FACT_100NS;
|
||||
|
||||
if (enable)
|
||||
ret |= DW_VR_MII_EEE_TRN_LPI;
|
||||
val = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
|
||||
DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
|
||||
DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
|
||||
FIELD_PREP(DW_VR_MII_EEE_MULT_FACT_100NS,
|
||||
mult_fact_100ns);
|
||||
else
|
||||
ret &= ~DW_VR_MII_EEE_TRN_LPI;
|
||||
val = 0;
|
||||
|
||||
return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1, ret);
|
||||
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, mask,
|
||||
val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1,
|
||||
DW_VR_MII_EEE_TRN_LPI,
|
||||
enable ? DW_VR_MII_EEE_TRN_LPI : 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xpcs_config_eee);
|
||||
|
||||
|
@ -668,7 +615,7 @@ static void xpcs_pre_config(struct phylink_pcs *pcs, phy_interface_t interface)
|
|||
if (!xpcs->need_reset)
|
||||
return;
|
||||
|
||||
compat = xpcs_find_compat(xpcs->desc, interface);
|
||||
compat = xpcs_find_compat(xpcs, interface);
|
||||
if (!compat) {
|
||||
dev_err(&xpcs->mdiodev->dev, "unsupported interface %s\n",
|
||||
phy_modes(interface));
|
||||
|
@ -687,9 +634,7 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
|
|||
unsigned int neg_mode)
|
||||
{
|
||||
int ret, mdio_ctrl, tx_conf;
|
||||
|
||||
if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
|
||||
xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_CL37_BP | DW_EN_VSMMD1);
|
||||
u16 mask, val;
|
||||
|
||||
/* For AN for C37 SGMII mode, the settings are :-
|
||||
* 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case
|
||||
|
@ -718,40 +663,35 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
mask = DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK;
|
||||
val = FIELD_PREP(DW_VR_MII_PCS_MODE_MASK,
|
||||
DW_VR_MII_PCS_MODE_C37_SGMII);
|
||||
|
||||
ret &= ~(DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK);
|
||||
ret |= (DW_VR_MII_PCS_MODE_C37_SGMII <<
|
||||
DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT &
|
||||
DW_VR_MII_PCS_MODE_MASK);
|
||||
if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
|
||||
ret |= DW_VR_MII_AN_CTRL_8BIT;
|
||||
mask |= DW_VR_MII_AN_CTRL_8BIT;
|
||||
val |= DW_VR_MII_AN_CTRL_8BIT;
|
||||
/* 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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
|
||||
|
||||
val |= FIELD_PREP(DW_VR_MII_TX_CONFIG_MASK, tx_conf);
|
||||
|
||||
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mask = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
|
||||
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
|
||||
ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
|
||||
else
|
||||
ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
|
||||
val = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
|
||||
|
||||
if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
|
||||
ret |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
|
||||
if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
|
||||
mask |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
|
||||
val |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
|
||||
}
|
||||
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
|
||||
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, mask, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -769,9 +709,7 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
|
|||
phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX;
|
||||
int ret, mdio_ctrl, adv;
|
||||
bool changed = 0;
|
||||
|
||||
if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
|
||||
xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_CL37_BP | DW_EN_VSMMD1);
|
||||
u16 mask, val;
|
||||
|
||||
/* According to Chap 7.12, to set 1000BASE-X C37 AN, AN must
|
||||
* be disabled first:-
|
||||
|
@ -789,14 +727,16 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
mask = DW_VR_MII_PCS_MODE_MASK;
|
||||
val = FIELD_PREP(DW_VR_MII_PCS_MODE_MASK,
|
||||
DW_VR_MII_PCS_MODE_C37_1000BASEX);
|
||||
|
||||
ret &= ~DW_VR_MII_PCS_MODE_MASK;
|
||||
if (!xpcs->pcs.poll)
|
||||
ret |= DW_VR_MII_AN_INTR_EN;
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
|
||||
if (!xpcs->pcs.poll) {
|
||||
mask |= DW_VR_MII_AN_INTR_EN;
|
||||
val |= DW_VR_MII_AN_INTR_EN;
|
||||
}
|
||||
|
||||
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -833,22 +773,16 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret |= DW_VR_MII_DIG_CTRL1_2G5_EN;
|
||||
ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
|
||||
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1,
|
||||
DW_VR_MII_DIG_CTRL1_2G5_EN |
|
||||
DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW,
|
||||
DW_VR_MII_DIG_CTRL1_2G5_EN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret &= ~AN_CL37_EN;
|
||||
ret |= SGMII_SPEED_SS6;
|
||||
ret &= ~SGMII_SPEED_SS13;
|
||||
return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, ret);
|
||||
return xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
|
||||
AN_CL37_EN | SGMII_SPEED_SS6 | SGMII_SPEED_SS13,
|
||||
SGMII_SPEED_SS6);
|
||||
}
|
||||
|
||||
static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
|
||||
|
@ -858,7 +792,7 @@ static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
|
|||
const struct dw_xpcs_compat *compat;
|
||||
int ret;
|
||||
|
||||
compat = xpcs_find_compat(xpcs->desc, interface);
|
||||
compat = xpcs_find_compat(xpcs, interface);
|
||||
if (!compat)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -866,6 +800,14 @@ static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
|
|||
ret = txgbe_xpcs_switch_mode(xpcs, interface);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Wangxun devices need backplane CL37 AN enabled for
|
||||
* SGMII and 1000base-X
|
||||
*/
|
||||
if (interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
interface == PHY_INTERFACE_MODE_1000BASEX)
|
||||
xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1,
|
||||
DW_CL37_BP | DW_EN_VSMMD1);
|
||||
}
|
||||
|
||||
switch (compat->an_mode) {
|
||||
|
@ -1013,8 +955,7 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
|
|||
|
||||
state->link = true;
|
||||
|
||||
speed_value = (ret & DW_VR_MII_AN_STS_C37_ANSGM_SP) >>
|
||||
DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT;
|
||||
speed_value = FIELD_GET(DW_VR_MII_AN_STS_C37_ANSGM_SP, ret);
|
||||
if (speed_value == DW_VR_MII_C37_ANSGM_SP_1000)
|
||||
state->speed = SPEED_1000;
|
||||
else if (speed_value == DW_VR_MII_C37_ANSGM_SP_100)
|
||||
|
@ -1122,7 +1063,7 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
|
|||
const struct dw_xpcs_compat *compat;
|
||||
int ret;
|
||||
|
||||
compat = xpcs_find_compat(xpcs->desc, state->interface);
|
||||
compat = xpcs_find_compat(xpcs, state->interface);
|
||||
if (!compat)
|
||||
return;
|
||||
|
||||
|
@ -1132,32 +1073,27 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
|
|||
break;
|
||||
case DW_AN_C73:
|
||||
ret = xpcs_get_state_c73(xpcs, state, compat);
|
||||
if (ret) {
|
||||
pr_err("xpcs_get_state_c73 returned %pe\n",
|
||||
ERR_PTR(ret));
|
||||
return;
|
||||
}
|
||||
if (ret)
|
||||
dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
|
||||
"xpcs_get_state_c73", ERR_PTR(ret));
|
||||
break;
|
||||
case DW_AN_C37_SGMII:
|
||||
ret = xpcs_get_state_c37_sgmii(xpcs, state);
|
||||
if (ret) {
|
||||
pr_err("xpcs_get_state_c37_sgmii returned %pe\n",
|
||||
ERR_PTR(ret));
|
||||
}
|
||||
if (ret)
|
||||
dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
|
||||
"xpcs_get_state_c37_sgmii", ERR_PTR(ret));
|
||||
break;
|
||||
case DW_AN_C37_1000BASEX:
|
||||
ret = xpcs_get_state_c37_1000basex(xpcs, state);
|
||||
if (ret) {
|
||||
pr_err("xpcs_get_state_c37_1000basex returned %pe\n",
|
||||
ERR_PTR(ret));
|
||||
}
|
||||
if (ret)
|
||||
dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
|
||||
"xpcs_get_state_c37_1000basex", ERR_PTR(ret));
|
||||
break;
|
||||
case DW_2500BASEX:
|
||||
ret = xpcs_get_state_2500basex(xpcs, state);
|
||||
if (ret) {
|
||||
pr_err("xpcs_get_state_2500basex returned %pe\n",
|
||||
ERR_PTR(ret));
|
||||
}
|
||||
if (ret)
|
||||
dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
|
||||
"xpcs_get_state_2500basex", ERR_PTR(ret));
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@ -1175,7 +1111,8 @@ static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int neg_mode,
|
|||
val = mii_bmcr_encode_fixed(speed, duplex);
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
|
||||
if (ret)
|
||||
pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
|
||||
dev_err(&xpcs->mdiodev->dev, "%s: xpcs_write returned %pe\n",
|
||||
__func__, ERR_PTR(ret));
|
||||
}
|
||||
|
||||
static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int neg_mode,
|
||||
|
@ -1193,18 +1130,21 @@ static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int neg_mode,
|
|||
case SPEED_100:
|
||||
case SPEED_10:
|
||||
default:
|
||||
pr_err("%s: speed = %d\n", __func__, speed);
|
||||
dev_err(&xpcs->mdiodev->dev, "%s: speed = %d\n",
|
||||
__func__, speed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (duplex == DUPLEX_FULL)
|
||||
val |= BMCR_FULLDPLX;
|
||||
else
|
||||
pr_err("%s: half duplex not supported\n", __func__);
|
||||
dev_err(&xpcs->mdiodev->dev, "%s: half duplex not supported\n",
|
||||
__func__);
|
||||
|
||||
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
|
||||
if (ret)
|
||||
pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
|
||||
dev_err(&xpcs->mdiodev->dev, "%s: xpcs_write returned %pe\n",
|
||||
__func__, ERR_PTR(ret));
|
||||
}
|
||||
|
||||
static void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
|
||||
|
@ -1223,16 +1163,12 @@ static void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
|
|||
static void xpcs_an_restart(struct phylink_pcs *pcs)
|
||||
{
|
||||
struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
|
||||
int ret;
|
||||
|
||||
ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
|
||||
if (ret >= 0) {
|
||||
ret |= BMCR_ANRESTART;
|
||||
xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
|
||||
}
|
||||
xpcs_modify(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, BMCR_ANRESTART,
|
||||
BMCR_ANRESTART);
|
||||
}
|
||||
|
||||
static int xpcs_get_id(struct dw_xpcs *xpcs)
|
||||
static int xpcs_read_ids(struct dw_xpcs *xpcs)
|
||||
{
|
||||
int ret;
|
||||
u32 id;
|
||||
|
@ -1298,76 +1234,62 @@ static int xpcs_get_id(struct dw_xpcs *xpcs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct dw_xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
|
||||
[DW_XPCS_USXGMII] = {
|
||||
static const struct dw_xpcs_compat synopsys_xpcs_compat[] = {
|
||||
{
|
||||
.interface = PHY_INTERFACE_MODE_USXGMII,
|
||||
.supported = xpcs_usxgmii_features,
|
||||
.interface = xpcs_usxgmii_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_usxgmii_interfaces),
|
||||
.an_mode = DW_AN_C73,
|
||||
},
|
||||
[DW_XPCS_10GKR] = {
|
||||
}, {
|
||||
.interface = PHY_INTERFACE_MODE_10GKR,
|
||||
.supported = xpcs_10gkr_features,
|
||||
.interface = xpcs_10gkr_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_10gkr_interfaces),
|
||||
.an_mode = DW_AN_C73,
|
||||
},
|
||||
[DW_XPCS_XLGMII] = {
|
||||
}, {
|
||||
.interface = PHY_INTERFACE_MODE_XLGMII,
|
||||
.supported = xpcs_xlgmii_features,
|
||||
.interface = xpcs_xlgmii_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces),
|
||||
.an_mode = DW_AN_C73,
|
||||
},
|
||||
[DW_XPCS_10GBASER] = {
|
||||
}, {
|
||||
.interface = PHY_INTERFACE_MODE_10GBASER,
|
||||
.supported = xpcs_10gbaser_features,
|
||||
.interface = xpcs_10gbaser_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_10gbaser_interfaces),
|
||||
.an_mode = DW_10GBASER,
|
||||
},
|
||||
[DW_XPCS_SGMII] = {
|
||||
}, {
|
||||
.interface = PHY_INTERFACE_MODE_SGMII,
|
||||
.supported = xpcs_sgmii_features,
|
||||
.interface = xpcs_sgmii_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
|
||||
.an_mode = DW_AN_C37_SGMII,
|
||||
},
|
||||
[DW_XPCS_1000BASEX] = {
|
||||
}, {
|
||||
.interface = PHY_INTERFACE_MODE_1000BASEX,
|
||||
.supported = xpcs_1000basex_features,
|
||||
.interface = xpcs_1000basex_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_1000basex_interfaces),
|
||||
.an_mode = DW_AN_C37_1000BASEX,
|
||||
},
|
||||
[DW_XPCS_2500BASEX] = {
|
||||
}, {
|
||||
.interface = PHY_INTERFACE_MODE_2500BASEX,
|
||||
.supported = xpcs_2500basex_features,
|
||||
.interface = xpcs_2500basex_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
|
||||
.an_mode = DW_2500BASEX,
|
||||
},
|
||||
}, {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct dw_xpcs_compat nxp_sja1105_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
|
||||
[DW_XPCS_SGMII] = {
|
||||
static const struct dw_xpcs_compat nxp_sja1105_xpcs_compat[] = {
|
||||
{
|
||||
.interface = PHY_INTERFACE_MODE_SGMII,
|
||||
.supported = xpcs_sgmii_features,
|
||||
.interface = xpcs_sgmii_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
|
||||
.an_mode = DW_AN_C37_SGMII,
|
||||
.pma_config = nxp_sja1105_sgmii_pma_config,
|
||||
},
|
||||
}, {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct dw_xpcs_compat nxp_sja1110_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
|
||||
[DW_XPCS_SGMII] = {
|
||||
static const struct dw_xpcs_compat nxp_sja1110_xpcs_compat[] = {
|
||||
{
|
||||
.interface = PHY_INTERFACE_MODE_SGMII,
|
||||
.supported = xpcs_sgmii_features,
|
||||
.interface = xpcs_sgmii_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
|
||||
.an_mode = DW_AN_C37_SGMII,
|
||||
.pma_config = nxp_sja1110_sgmii_pma_config,
|
||||
},
|
||||
[DW_XPCS_2500BASEX] = {
|
||||
}, {
|
||||
.interface = PHY_INTERFACE_MODE_2500BASEX,
|
||||
.supported = xpcs_2500basex_features,
|
||||
.interface = xpcs_2500basex_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
|
||||
.an_mode = DW_2500BASEX,
|
||||
.pma_config = nxp_sja1110_2500basex_pma_config,
|
||||
},
|
||||
}, {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct dw_xpcs_desc xpcs_desc_list[] = {
|
||||
|
@ -1395,6 +1317,26 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = {
|
|||
.pcs_link_up = xpcs_link_up,
|
||||
};
|
||||
|
||||
static int xpcs_identify(struct dw_xpcs *xpcs)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
ret = xpcs_read_ids(xpcs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(xpcs_desc_list); i++) {
|
||||
const struct dw_xpcs_desc *entry = &xpcs_desc_list[i];
|
||||
|
||||
if ((xpcs->info.pcs & entry->mask) == entry->id) {
|
||||
xpcs->desc = entry;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static struct dw_xpcs *xpcs_create_data(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct dw_xpcs *xpcs;
|
||||
|
@ -1451,7 +1393,6 @@ static void xpcs_clear_clks(struct dw_xpcs *xpcs)
|
|||
static int xpcs_init_id(struct dw_xpcs *xpcs)
|
||||
{
|
||||
const struct dw_xpcs_info *info;
|
||||
int i, ret;
|
||||
|
||||
info = dev_get_platdata(&xpcs->mdiodev->dev);
|
||||
if (!info) {
|
||||
|
@ -1461,25 +1402,7 @@ static int xpcs_init_id(struct dw_xpcs *xpcs)
|
|||
xpcs->info = *info;
|
||||
}
|
||||
|
||||
ret = xpcs_get_id(xpcs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(xpcs_desc_list); i++) {
|
||||
const struct dw_xpcs_desc *desc = &xpcs_desc_list[i];
|
||||
|
||||
if ((xpcs->info.pcs & desc->mask) != desc->id)
|
||||
continue;
|
||||
|
||||
xpcs->desc = desc;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!xpcs->desc)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
return xpcs_identify(xpcs);
|
||||
}
|
||||
|
||||
static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev)
|
||||
|
|
|
@ -60,8 +60,6 @@
|
|||
#define DW_VR_MII_DIG_CTRL1 0x8000
|
||||
#define DW_VR_MII_AN_CTRL 0x8001
|
||||
#define DW_VR_MII_AN_INTR_STS 0x8002
|
||||
/* Enable 2.5G Mode */
|
||||
#define DW_VR_MII_DIG_CTRL1_2G5_EN BIT(2)
|
||||
/* EEE Mode Control Register */
|
||||
#define DW_VR_MII_EEE_MCTRL0 0x8006
|
||||
#define DW_VR_MII_EEE_MCTRL1 0x800b
|
||||
|
@ -69,6 +67,7 @@
|
|||
|
||||
/* VR_MII_DIG_CTRL1 */
|
||||
#define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9)
|
||||
#define DW_VR_MII_DIG_CTRL1_2G5_EN BIT(2)
|
||||
#define DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL BIT(0)
|
||||
|
||||
/* VR_MII_DIG_CTRL2 */
|
||||
|
@ -77,11 +76,9 @@
|
|||
|
||||
/* 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_TX_CONFIG_MASK BIT(3)
|
||||
#define DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII 0x1
|
||||
#define DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII 0x0
|
||||
#define DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT 1
|
||||
#define DW_VR_MII_PCS_MODE_MASK GENMASK(2, 1)
|
||||
#define DW_VR_MII_PCS_MODE_C37_1000BASEX 0x0
|
||||
#define DW_VR_MII_PCS_MODE_C37_SGMII 0x2
|
||||
|
@ -90,7 +87,6 @@
|
|||
/* VR_MII_AN_INTR_STS */
|
||||
#define DW_VR_MII_AN_STS_C37_ANCMPLT_INTR BIT(0)
|
||||
#define DW_VR_MII_AN_STS_C37_ANSGM_FD BIT(1)
|
||||
#define DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT 2
|
||||
#define DW_VR_MII_AN_STS_C37_ANSGM_SP GENMASK(3, 2)
|
||||
#define DW_VR_MII_C37_ANSGM_SP_10 0x0
|
||||
#define DW_VR_MII_C37_ANSGM_SP_100 0x1
|
||||
|
@ -114,7 +110,6 @@
|
|||
#define DW_VR_MII_EEE_TX_EN_CTRL BIT(4) /* Tx Control Enable */
|
||||
#define DW_VR_MII_EEE_RX_EN_CTRL BIT(7) /* Rx Control Enable */
|
||||
|
||||
#define DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT 8
|
||||
#define DW_VR_MII_EEE_MULT_FACT_100NS GENMASK(11, 8)
|
||||
|
||||
/* VR MII EEE Control 1 defines */
|
||||
|
@ -123,8 +118,27 @@
|
|||
#define DW_XPCS_INFO_DECLARE(_name, _pcs, _pma) \
|
||||
static const struct dw_xpcs_info _name = { .pcs = _pcs, .pma = _pma }
|
||||
|
||||
struct dw_xpcs_desc;
|
||||
|
||||
enum dw_xpcs_clock {
|
||||
DW_XPCS_CORE_CLK,
|
||||
DW_XPCS_PAD_CLK,
|
||||
DW_XPCS_NUM_CLKS,
|
||||
};
|
||||
|
||||
struct dw_xpcs {
|
||||
struct dw_xpcs_info info;
|
||||
const struct dw_xpcs_desc *desc;
|
||||
struct mdio_device *mdiodev;
|
||||
struct clk_bulk_data clks[DW_XPCS_NUM_CLKS];
|
||||
struct phylink_pcs pcs;
|
||||
phy_interface_t interface;
|
||||
bool need_reset;
|
||||
};
|
||||
|
||||
int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg);
|
||||
int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val);
|
||||
int xpcs_modify(struct dw_xpcs *xpcs, int dev, u32 reg, u16 mask, u16 set);
|
||||
int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg);
|
||||
int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val);
|
||||
int nxp_sja1105_sgmii_pma_config(struct dw_xpcs *xpcs);
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
#define DW_AN_C37_1000BASEX 4
|
||||
#define DW_10GBASER 5
|
||||
|
||||
struct dw_xpcs_desc;
|
||||
|
||||
enum dw_xpcs_pcs_id {
|
||||
DW_XPCS_ID_NATIVE = 0,
|
||||
NXP_SJA1105_XPCS_ID = 0x00000010,
|
||||
|
@ -48,22 +46,9 @@ struct dw_xpcs_info {
|
|||
u32 pma;
|
||||
};
|
||||
|
||||
enum dw_xpcs_clock {
|
||||
DW_XPCS_CORE_CLK,
|
||||
DW_XPCS_PAD_CLK,
|
||||
DW_XPCS_NUM_CLKS,
|
||||
};
|
||||
|
||||
struct dw_xpcs {
|
||||
struct dw_xpcs_info info;
|
||||
const struct dw_xpcs_desc *desc;
|
||||
struct mdio_device *mdiodev;
|
||||
struct clk_bulk_data clks[DW_XPCS_NUM_CLKS];
|
||||
struct phylink_pcs pcs;
|
||||
phy_interface_t interface;
|
||||
bool need_reset;
|
||||
};
|
||||
struct dw_xpcs;
|
||||
|
||||
struct phylink_pcs *xpcs_to_phylink_pcs(struct dw_xpcs *xpcs);
|
||||
int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface);
|
||||
void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces);
|
||||
int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns,
|
||||
|
|
Loading…
Add table
Reference in a new issue