1 From 385ef48f468696d6d172eb367656a3466fa0408d Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Tue, 6 Feb 2024 18:31:05 +0100
4 Subject: [PATCH 02/10] net: phy: add support for scanning PHY in PHY packages
7 Add support for scanning PHY in PHY package nodes. PHY packages nodes
8 are just container for actual PHY on the MDIO bus.
10 Their PHY address defined in the PHY package node are absolute and
11 reflect the address on the MDIO bus.
13 mdio_bus.c and of_mdio.c is updated to now support and parse also
14 PHY package subnode by checking if the node name match
15 "ethernet-phy-package".
17 As PHY package reg is mandatory and each PHY in the PHY package must
18 have a reg, every invalid PHY Package node is ignored and will be
19 skipped by the autoscan fallback.
21 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
22 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
23 Signed-off-by: David S. Miller <davem@davemloft.net>
25 drivers/net/mdio/of_mdio.c | 79 +++++++++++++++++++++++++++-----------
26 drivers/net/phy/mdio_bus.c | 44 +++++++++++++++++----
27 2 files changed, 92 insertions(+), 31 deletions(-)
29 --- a/drivers/net/mdio/of_mdio.c
30 +++ b/drivers/net/mdio/of_mdio.c
31 @@ -138,6 +138,53 @@ bool of_mdiobus_child_is_phy(struct devi
33 EXPORT_SYMBOL(of_mdiobus_child_is_phy);
35 +static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np,
38 + struct device_node *child;
41 + /* Loop over the child nodes and register a phy_device for each phy */
42 + for_each_available_child_of_node(np, child) {
43 + if (of_node_name_eq(child, "ethernet-phy-package")) {
44 + /* Ignore invalid ethernet-phy-package node */
45 + if (!of_find_property(child, "reg", NULL))
48 + rc = __of_mdiobus_parse_phys(mdio, child, NULL);
49 + if (rc && rc != -ENODEV)
55 + addr = of_mdio_parse_addr(&mdio->dev, child);
57 + /* Skip scanning for invalid ethernet-phy-package node */
63 + if (of_mdiobus_child_is_phy(child))
64 + rc = of_mdiobus_register_phy(mdio, child, addr);
66 + rc = of_mdiobus_register_device(mdio, child, addr);
70 + "MDIO device at address %d is missing.\n",
83 * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree
84 * @mdio: pointer to mii_bus structure
85 @@ -179,33 +226,18 @@ int __of_mdiobus_register(struct mii_bus
88 /* Loop over the child nodes and register a phy_device for each phy */
89 - for_each_available_child_of_node(np, child) {
90 - addr = of_mdio_parse_addr(&mdio->dev, child);
96 - if (of_mdiobus_child_is_phy(child))
97 - rc = of_mdiobus_register_phy(mdio, child, addr);
99 - rc = of_mdiobus_register_device(mdio, child, addr);
102 - dev_err(&mdio->dev,
103 - "MDIO device at address %d is missing.\n",
108 + rc = __of_mdiobus_parse_phys(mdio, np, &scanphys);
115 /* auto scan for PHYs with empty reg property */
116 for_each_available_child_of_node(np, child) {
117 - /* Skip PHYs with reg property set */
118 - if (of_property_present(child, "reg"))
119 + /* Skip PHYs with reg property set or ethernet-phy-package node */
120 + if (of_property_present(child, "reg") ||
121 + of_node_name_eq(child, "ethernet-phy-package"))
124 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
125 @@ -226,15 +258,16 @@ int __of_mdiobus_register(struct mii_bus
130 + goto put_unregister;
141 mdiobus_unregister(mdio);
144 --- a/drivers/net/phy/mdio_bus.c
145 +++ b/drivers/net/phy/mdio_bus.c
146 @@ -455,19 +455,34 @@ EXPORT_SYMBOL(of_mdio_find_bus);
147 * found, set the of_node pointer for the mdio device. This allows
148 * auto-probed phy devices to be supplied with information passed in
150 + * If a PHY package is found, PHY is searched also there.
152 -static void of_mdiobus_link_mdiodev(struct mii_bus *bus,
153 - struct mdio_device *mdiodev)
154 +static int of_mdiobus_find_phy(struct device *dev, struct mdio_device *mdiodev,
155 + struct device_node *np)
157 - struct device *dev = &mdiodev->dev;
158 struct device_node *child;
160 - if (dev->of_node || !bus->dev.of_node)
163 - for_each_available_child_of_node(bus->dev.of_node, child) {
164 + for_each_available_child_of_node(np, child) {
167 + if (of_node_name_eq(child, "ethernet-phy-package")) {
168 + /* Validate PHY package reg presence */
169 + if (!of_find_property(child, "reg", NULL)) {
170 + of_node_put(child);
174 + if (!of_mdiobus_find_phy(dev, mdiodev, child)) {
175 + /* The refcount for the PHY package will be
176 + * incremented later when PHY join the Package.
178 + of_node_put(child);
185 addr = of_mdio_parse_addr(dev, child);
188 @@ -477,9 +492,22 @@ static void of_mdiobus_link_mdiodev(stru
189 /* The refcount on "child" is passed to the mdio
190 * device. Do _not_ use of_node_put(child) here.
200 +static void of_mdiobus_link_mdiodev(struct mii_bus *bus,
201 + struct mdio_device *mdiodev)
203 + struct device *dev = &mdiodev->dev;
205 + if (dev->of_node || !bus->dev.of_node)
208 + of_mdiobus_find_phy(dev, mdiodev, bus->dev.of_node);
210 #else /* !IS_ENABLED(CONFIG_OF_MDIO) */
211 static inline void of_mdiobus_link_mdiodev(struct mii_bus *mdio,