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@sartura.hr>
---
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