mirror of
https://abf.rosa.ru/djam/kernel-5.15.git
synced 2025-02-23 10:32:54 +00:00
93 lines
2.8 KiB
Diff
93 lines
2.8 KiB
Diff
![]() |
From 7d549f458db381baca4c38d27c984b57514b971f Mon Sep 17 00:00:00 2001
|
||
|
From: Alexey Sheplyakov <asheplyakov@altlinux.org>
|
||
|
Date: Mon, 16 Aug 2021 15:01:41 +0400
|
||
|
Subject: [PATCH 625/634] net: fwnode_get_phy_id: consider all compatible
|
||
|
strings
|
||
|
|
||
|
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.
|
||
|
|
||
|
X-DONTUPSTREAM
|
||
|
---
|
||
|
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 28f4a383a..68bd0dbc9 100644
|
||
|
--- a/drivers/net/phy/phy_device.c
|
||
|
+++ b/drivers/net/phy/phy_device.c
|
||
|
@@ -840,18 +840,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.2
|
||
|
|