summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Jelonek2026-01-11 10:12:00 +0000
committerRobert Marko2026-01-25 11:12:15 +0000
commit322041ffeb9076b1fbc753176723100c0a630976 (patch)
tree4f0f643953e5d509108c15dc26e237b61b17b980
parent12fd85eb7951e689c31144a308ffff8e49f50a97 (diff)
downloadxback-322041ffeb9076b1fbc753176723100c0a630976.tar.gz
realtek: mdio: enhance reading phy id
Reading the PHY ID to assign a PHY config is currently simple. For C45 two MDIO reads of a hardcoded MMD are done to get the standard PHY ID registers. MMD 31 (MMD_VEND2) is used for that purpose, assuming there will be a valid PHY ID stored in this MMD in all cases. However, with Aquantia AQR813 there's at least one example for which this isn't true. This PHY returns 0 for the PHY ID in MMD_VEND2, instead MMD_VEND1 would have the correct ID. Enhance reading the PHY by accessing a common set of MMDs of which most PHY at least implement one and have a valid PHY ID in. To keep overhead low, do not scan all MMDs. As soon as a valid PHY ID is found, exit and use that. This is similar to the kernel logic, jsut reduced to fewer MMDs. Also handle possible errors coming from MDIO reads to avoid reading garbage. While at it, move reading the PHY ID to a separate function to not pollute the poll fixup retrievel function. Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com> Link: https://github.com/openwrt/openwrt/pull/21515 Signed-off-by: Robert Marko <robert.marko@sartura.hr>
-rw-r--r--target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c b/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c
index 9ff2a91a17..8e97e21c3f 100644
--- a/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c
+++ b/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c
@@ -532,6 +532,52 @@ static int rtmdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
return 0;
}
+static int rtmdio_read_phy_id(struct mii_bus *bus, u8 addr, unsigned int *phy_id)
+{
+ static const int common_mmds[] = {
+ MDIO_MMD_PMAPMD, MDIO_MMD_PCS, MDIO_MMD_AN,
+ MDIO_MMD_VEND1, MDIO_MMD_VEND2
+ };
+ struct rtmdio_bus_priv *priv = bus->priv;
+ int devid1 = 0, devid2 = 0;
+ unsigned int id = 0;
+
+ /* Clause 22 */
+ if (!priv->smi_bus_isc45[priv->smi_bus[addr]]) {
+ devid1 = rtmdio_read(bus, addr, MDIO_DEVID1);
+ devid2 = rtmdio_read(bus, addr, MDIO_DEVID2);
+ if (devid1 < 0 || devid2 < 0)
+ return -EIO;
+
+ id = (devid1 << 16) | devid2;
+ if (!id || (id & 0x1fffffff) == 0x1fffffff)
+ return -ENODEV;
+
+ *phy_id = id;
+ return 0;
+ }
+
+
+ /* Clause 45
+ * only scan some MMDs which can be considered as common i.e.
+ * implemented by most PHYs.
+ */
+ for (int i = 0; i < ARRAY_SIZE(common_mmds); i++) {
+ devid1 = rtmdio_read_c45(bus, addr, common_mmds[i], MDIO_DEVID1);
+ devid2 = rtmdio_read_c45(bus, addr, common_mmds[i], MDIO_DEVID2);
+ if (devid1 < 0 || devid2 < 0)
+ continue;
+
+ id = (devid1 << 16) | devid2;
+ if (id && id != 0xffffffff) {
+ *phy_id = id;
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
static void rtmdio_get_phy_info(struct mii_bus *bus, int addr, struct rtmdio_phy_info *phyinfo)
{
struct rtmdio_bus_priv *priv = bus->priv;
@@ -547,12 +593,10 @@ static void rtmdio_get_phy_info(struct mii_bus *bus, int addr, struct rtmdio_phy
return;
}
- if (priv->smi_bus_isc45[priv->smi_bus[addr]])
- phyinfo->phy_id = (rtmdio_read_c45(bus, addr, 31, 2) << 16) +
- rtmdio_read_c45(bus, addr, 31, 3);
- else
- phyinfo->phy_id = (rtmdio_read(bus, addr, 2) << 16) +
- rtmdio_read(bus, addr, 3);
+ if (rtmdio_read_phy_id(bus, addr, &phyinfo->phy_id) < 0) {
+ phyinfo->phy_unknown = true;
+ return;
+ }
switch(phyinfo->phy_id) {
case RTMDIO_PHY_AQR113C: