lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260122105654.105600-16-vladimir.oltean@nxp.com>
Date: Thu, 22 Jan 2026 12:56:54 +0200
From: Vladimir Oltean <vladimir.oltean@....com>
To: netdev@...r.kernel.org
Cc: Andrew Lunn <andrew@...n.ch>,
	Heiner Kallweit <hkallweit1@...il.com>,
	Russell King <linux@...linux.org.uk>,
	"David S. Miller" <davem@...emloft.net>,
	Eric Dumazet <edumazet@...gle.com>,
	Jakub Kicinski <kuba@...nel.org>,
	Paolo Abeni <pabeni@...hat.com>,
	linux-kernel@...r.kernel.org,
	Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
	Herve Codina <herve.codina@...tlin.com>,
	Mark Brown <broonie@...nel.org>,
	Serge Semin <fancer.lancer@...il.com>,
	Maxime Chevallier <maxime.chevallier@...tlin.com>,
	Lee Jones <lee@...nel.org>,
	Rob Herring <robh@...nel.org>,
	Krzysztof Kozlowski <krzk+dt@...nel.org>,
	Conor Dooley <conor+dt@...nel.org>,
	devicetree@...r.kernel.org,
	Choong Yong Liang <yong.liang.choong@...ux.intel.com>,
	Jiawen Wu <jiawenwu@...stnetic.com>
Subject: [PATCH v2 net-next 15/15] net: pcs: xpcs: allow generic polarity inversion

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.

By using the "manual" helpers, we default to PHY_POL_NORMAL, and support
normal and inverted polarities in the RX and TX directions.

Note that for NXP SJA1105, to get a functional data path with
non-inverted signals at the device pins, we have to apply TX polarity
inversion in the PCS, due to its integration with a custom PMA.

Since the SJA1105 was only recently made to describe the XPCS in the
device tree, we can require that this hardware quirk is described there,
and this avoids having custom handling for it in the driver.

Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
v1->v2:
- use phy_get_manual_rx_polarity() and phy_get_manual_tx_polarity(),
  which are simpler helpers that assume the default polarity is
  PHY_POL_NORMAL. There is a slight regression risk if some XPCS
  integrations rely on custom polarity set in the bootloader.
- drop custom handling for SJA1105.

 drivers/net/pcs/Kconfig        |  1 +
 drivers/net/pcs/pcs-xpcs-nxp.c | 11 --------
 drivers/net/pcs/pcs-xpcs.c     | 46 ++++++++++++++++++++++++++++------
 drivers/net/pcs/pcs-xpcs.h     |  1 -
 4 files changed, 39 insertions(+), 20 deletions(-)

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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ