[d-kernel] [PATCH 10/32] net: fwnode_get_phy_id: consider all compatible strings
Alexey Sheplyakov
asheplyakov на basealt.ru
Ср Дек 14 16:18:57 MSK 2022
Commit cf99686072a1b7037a1d782b66037b2b722bf2c9 ("of: mdio:
Refactor of_get_phy_id()") has broken Ethernet on TF307 board
(and possibly other boards based on Baikal-M/T1 SoCs).
That commit replaces `of_get_phy_id` with `fwnode_get_phy_id`.
And `fwnode_get_phy_id` considers only the 1st compatible string
to find out phy_id. This works well for all schema compliant device
trees, since the `compatible` property of PHY nodes is supposed
to be "ethernet-phy-idNNNN.MMMM".
However DTB embedded in TF307 firmware describes PHY like this:
gmac0_phy: ethernet-phy на 3 {
compatible = "micrel,ksz9031", "ethernet-phy-id0022.1620", "ethernet-phy-ieee802.3-c22";
reg = <0x3>;
};
That is, the 1st compatible string is "micrel,ksz9031". Thus
`fwnode_get_phy_id` is unable to parse phy_id, and
`stmmac_mdio_register` fails. As a result Ethernet driver is
unable to attach to PHY, and can't send/receive anything.
To avoid the problem this patch adjusts `fwnode_get_phy_id`
to consider *all* compatible strings.
Signed-off-by: Alexey Sheplyakov <asheplyakov на basealt.ru>
X-DONTUPSTREAM
X-feature-Baikal-M
---
drivers/net/phy/phy_device.c | 41 ++++++++++++++++++++++++++----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 8cff61dbc4b5..2431a320c5ee 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -875,18 +875,37 @@ static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id)
{
unsigned int upper, lower;
- const char *cp;
- int ret;
-
- ret = fwnode_property_read_string(fwnode, "compatible", &cp);
- if (ret)
- return ret;
-
- if (sscanf(cp, "ethernet-phy-id%4x.%4x", &upper, &lower) != 2)
- return -EINVAL;
+ const char **compat;
+ int ret, count, i;
+
+ /* FIXME: where is fwnode_property_for_each_string? */
+ count = fwnode_property_read_string_array(fwnode, "compatible", NULL, 0);
+ if (count < 0)
+ return count;
+ else if (count == 0)
+ return -ENODATA;
+
+ compat = kcalloc(count, sizeof(*compat), GFP_KERNEL);
+ if (!compat)
+ return -ENOMEM;
+ ret = fwnode_property_read_string_array(fwnode, "compatible", compat, count);
+ if (ret < 0)
+ goto out;
- *phy_id = ((upper & GENMASK(15, 0)) << 16) | (lower & GENMASK(15, 0));
- return 0;
+ ret = -EINVAL;
+ for (i = 0; i < count; i++) {
+ pr_info("%s: considering '%s'\n", __func__, compat[i]);
+ if (sscanf(compat[i], "ethernet-phy-id%4x.%4x", &upper, &lower) != 2)
+ continue;
+ else {
+ *phy_id = ((upper & GENMASK(15, 0)) << 16) | (lower & GENMASK(15, 0));
+ ret = 0;
+ break;
+ }
+ }
+out:
+ kfree(compat);
+ return ret;
}
EXPORT_SYMBOL(fwnode_get_phy_id);
--
2.33.5
Подробная информация о списке рассылки devel-kernel