diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index e417fd66f660..c95e24c895df 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -8,6 +8,7 @@ menu "PCS device drivers"
config PCS_XPCS
tristate "Synopsys DesignWare Ethernet XPCS"
select PHYLINK
+ select PHY_COMMON_PROPS
help
This module provides a driver and helper functions for Synopsys
DesignWare XPCS controllers.
diff --git a/drivers/net/pcs/pcs-xpcs-nxp.c b/drivers/net/pcs/pcs-xpcs-nxp.c
index e8efe94cf4ec..37708b28a7aa 100644
--- a/drivers/net/pcs/pcs-xpcs-nxp.c
+++ b/drivers/net/pcs/pcs-xpcs-nxp.c
@@ -64,17 +64,6 @@
/* RX_CDR_CTLE register */
#define SJA1110_RX_CDR_CTLE 0x8042
-/* In NXP SJA1105, the PCS is integrated with a PMA that has the TX lane
- * polarity inverted by default (PLUS is MINUS, MINUS is PLUS). To obtain
- * normal non-inverted behavior, the TX lane polarity must be inverted in the
- * PCS, via the DIGITAL_CONTROL_2 register.
- */
-int nxp_sja1105_sgmii_pma_config(struct dw_xpcs *xpcs)
-{
- return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL2,
- DW_VR_MII_DIG_CTRL2_TX_POL_INV);
-}
-
static int nxp_sja1110_pma_config(struct dw_xpcs *xpcs,
u16 txpll_fbdiv, u16 txpll_refdiv,
u16 rxpll_fbdiv, u16 rxpll_refdiv,diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 910fd8b23d41..eeddd0b1f3da 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -11,6 +11,7 @@
#include <linux/pcs/pcs-xpcs.h>
#include <linux/mdio.h>
#include <linux/phy.h>
+#include <linux/phy/phy-common-props.h>
#include <linux/phylink.h>
#include <linux/property.h>
@@ -908,6 +909,42 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
BMCR_SPEED1000);
}
+static int xpcs_pma_config(struct dw_xpcs *xpcs, const struct dw_xpcs_compat *compat)
+{
+ struct fwnode_handle *fwnode = dev_fwnode(&xpcs->mdiodev->dev);
+ u32 val = 0, mask;
+ unsigned int pol;
+ int ret;
+
+ mask = DW_VR_MII_DIG_CTRL2_TX_POL_INV | DW_VR_MII_DIG_CTRL2_RX_POL_INV;
+
+ ret = phy_get_manual_rx_polarity(fwnode, phy_modes(compat->interface),
+ &pol);
+ if (ret)
+ return ret;
+ if (pol == PHY_POL_INVERT)
+ val |= DW_VR_MII_DIG_CTRL2_RX_POL_INV;
+
+ ret = phy_get_manual_tx_polarity(fwnode, phy_modes(compat->interface),
+ &pol);
+ if (ret)
+ return ret;
+ if (pol == PHY_POL_INVERT)
+ val |= DW_VR_MII_DIG_CTRL2_TX_POL_INV;
+
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL2, mask, val);
+ if (ret < 0)
+ return ret;
+
+ if (compat->pma_config) {
+ ret = compat->pma_config(xpcs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
const unsigned long *advertising,
unsigned int neg_mode)@@ -959,13 +996,7 @@ static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
return -EINVAL;
}
- if (compat->pma_config) {
- ret = compat->pma_config(xpcs);
- if (ret)
- return ret;
- }
-
- return 0;
+ return xpcs_pma_config(xpcs, compat);
}
static int xpcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,@@ -1456,7 +1487,6 @@ static const struct dw_xpcs_compat nxp_sja1105_xpcs_compat[] = {
.interface = PHY_INTERFACE_MODE_SGMII,
.supported = xpcs_sgmii_features,
.an_mode = DW_AN_C37_SGMII,
- .pma_config = nxp_sja1105_sgmii_pma_config,
}, {
}
};diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h
index 929fa238445e..56fd170a8736 100644
--- a/drivers/net/pcs/pcs-xpcs.h
+++ b/drivers/net/pcs/pcs-xpcs.h
@@ -121,7 +121,6 @@ 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);
int nxp_sja1110_sgmii_pma_config(struct dw_xpcs *xpcs);
int nxp_sja1110_2500basex_pma_config(struct dw_xpcs *xpcs);
int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface);
--
2.34.1