Using the linux/phy/phy-common-props.h helpers, get the 'rx-polarity' and 'tx-polarity' device tree properties, and apply them to hardware in the newly introduced xpcs_pma_config(), called from phylink_pcs_ops :: pcs_config(). This is the right place to do it, as the generic PHY helpers require knowing the phy_interface_t for which we want the polarity known, and that comes from phylink. Default to PHY_POL_NORMAL, and support normal and inverted polarities in the RX and TX directions. Note that for SJA1105, 'normal' in the TX direction is inverted in the PCS, and 'inverted' is 'normal' in the PCS. This is because the device tree property refers to the effect as visible at the device's pinout. Signed-off-by: Vladimir Oltean --- drivers/net/pcs/Kconfig | 1 + drivers/net/pcs/pcs-xpcs.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig index ecbc3530e780..3598747d6c53 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 GENERIC_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.c b/drivers/net/pcs/pcs-xpcs.c index 670441186cc6..7625dc29d2ee 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -810,14 +811,34 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs) 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; + int pol; int ret; - if (xpcs->need_opposite_tx_polarity) { - ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL2, - DW_VR_MII_DIG_CTRL2_TX_POL_INV); - if (ret) - return ret; - } + mask = DW_VR_MII_DIG_CTRL2_TX_POL_INV | DW_VR_MII_DIG_CTRL2_RX_POL_INV; + + pol = phy_get_rx_polarity(fwnode, phy_modes(compat->interface), + PHY_POL_NORMAL | PHY_POL_INVERT, + PHY_POL_NORMAL); + if (pol < 0) + return pol; + if (pol == PHY_POL_INVERT) + val |= DW_VR_MII_DIG_CTRL2_RX_POL_INV; + + pol = phy_get_tx_polarity(fwnode, phy_modes(compat->interface), + PHY_POL_NORMAL | PHY_POL_INVERT, + PHY_POL_NORMAL); + if (pol < 0) + return pol; + if (xpcs->need_opposite_tx_polarity) + pol = !pol; + 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); -- 2.34.1