[PATCH net-next v2 5/5] net: phy: mxl-gpy: support MxL86211C lane mapping
From: Robert Marko
Date: Fri Oct 16 2026 - 07:24:38 EST
Configure the MxL86211C mapping from physical TPI lanes to analog
front ends (ASPs) when specified in DTS.
Leave the hardware reset mapping untouched when the optional property
is absent.
Signed-off-by: Robert Marko <robert.marko@xxxxxxxxxx>
---
Changes in v2:
- Preserve unrelated register bits when updating the lane map.
drivers/net/phy/mxl-gpy.c | 47 +++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c
index 8bc119655f104..acd5ad01a285d 100644
--- a/drivers/net/phy/mxl-gpy.c
+++ b/drivers/net/phy/mxl-gpy.c
@@ -116,6 +116,13 @@
#define VSPEC1_PM_CTRL_MDIO_VOL BIT(14)
#define VSPEC1_PM_CTRL_SI BIT(12) /* Super Isolate */
+/* TPI lane to ASP map */
+#define VSPEC1_LANE_ASP_MAP 0x14
+#define VSPEC1_LANE_ASP_MAP_A GENMASK(1, 0)
+#define VSPEC1_LANE_ASP_MAP_B GENMASK(3, 2)
+#define VSPEC1_LANE_ASP_MAP_C GENMASK(5, 4)
+#define VSPEC1_LANE_ASP_MAP_D GENMASK(7, 6)
+
/* Temperature sensor */
#define VSPEC1_TEMP_STA 0x0E
#define VSPEC1_TEMP_STA_DATA GENMASK(9, 0)
@@ -423,6 +430,42 @@ static int mxl86211c_configure_mdio_voltage(struct phy_device *phydev,
VSPEC1_PM_CTRL_MDIO_VOL, val);
}
+static int mxl86211c_configure_lane_asp_map(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ u32 lane_asp_map[4];
+ u16 val;
+ unsigned int seen = 0;
+ int i, ret;
+
+ if (!device_property_present(dev, "maxlinear,lane-asp-map"))
+ return 0;
+
+ ret = device_property_read_u32_array(dev, "maxlinear,lane-asp-map",
+ lane_asp_map,
+ ARRAY_SIZE(lane_asp_map));
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(lane_asp_map); i++) {
+ if (lane_asp_map[i] > 3 || seen & BIT(lane_asp_map[i]))
+ return -EINVAL;
+
+ seen |= BIT(lane_asp_map[i]);
+ }
+
+ val = FIELD_PREP(VSPEC1_LANE_ASP_MAP_A, lane_asp_map[0]) |
+ FIELD_PREP(VSPEC1_LANE_ASP_MAP_B, lane_asp_map[1]) |
+ FIELD_PREP(VSPEC1_LANE_ASP_MAP_C, lane_asp_map[2]) |
+ FIELD_PREP(VSPEC1_LANE_ASP_MAP_D, lane_asp_map[3]);
+
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LANE_ASP_MAP,
+ VSPEC1_LANE_ASP_MAP_A |
+ VSPEC1_LANE_ASP_MAP_B |
+ VSPEC1_LANE_ASP_MAP_C |
+ VSPEC1_LANE_ASP_MAP_D, val);
+}
+
static int mxl86211c_config_init(struct phy_device *phydev)
{
struct gpy_priv *priv = phydev->priv;
@@ -432,6 +475,10 @@ static int mxl86211c_config_init(struct phy_device *phydev)
if (ret)
return ret;
+ ret = mxl86211c_configure_lane_asp_map(phydev);
+ if (ret)
+ return ret;
+
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_PM_CTRL,
VSPEC1_PM_CTRL_SI, 0);
if (ret)
--
2.56.0