]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
net: sunxi_emac: chase DT nodes to find PHY regulator
authorAndre Przywara <andre.przywara@arm.com>
Tue, 13 Jun 2023 22:35:06 +0000 (23:35 +0100)
committerAndre Przywara <andre.przywara@arm.com>
Sun, 22 Oct 2023 22:40:56 +0000 (23:40 +0100)
At the moment the sun4i EMAC driver relies on hardcoded CONFIG_MACPWR
Kconfig symbols to enable potential PHY regulators. As we want to get rid
of those, we need to find the regulator by chasing up the DT.

The sun4i-emac binding puts the PHY regulator into the MDIO node, which
is the parent of the PHY device. U-Boot does not have (and does not
need) an MDIO driver, so we need to chase down the regulator through the
EMAC node: we follow the "phy-handle" property to find the PHY node,
then go up to its parent, where we find the "phy-supply" link to the
regulator. Let U-Boot find the associated regulator device, and put that
into the private device struct, so we can find and enable the regulator
at probe time, later.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Sam Edwards <CFSworks@gmail.com>
Reviewed-by: Samuel Holland <samuel@sholland.org>
drivers/net/sunxi_emac.c

index 4c90d4b4981d1a726e7804929bfce041b377cca4..b599b84852fbbe3e59f769012f9136e57642fab4 100644 (file)
@@ -17,6 +17,7 @@
 #include <net.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
+#include <power/regulator.h>
 
 /* EMAC register  */
 struct emac_regs {
@@ -165,6 +166,7 @@ struct emac_eth_dev {
        struct phy_device *phydev;
        int link_printed;
        uchar rx_buf[EMAC_RX_BUFSIZE];
+       struct udevice *phy_reg;
 };
 
 struct emac_rxhdr {
@@ -572,6 +574,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
        if (ret)
                return ret;
 
+       if (priv->phy_reg)
+               regulator_set_enable(priv->phy_reg, true);
+
        return sunxi_emac_init_phy(priv, dev);
 }
 
@@ -585,9 +590,42 @@ static const struct eth_ops sunxi_emac_eth_ops = {
 static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_plat(dev);
+       struct emac_eth_dev *priv = dev_get_priv(dev);
+       struct ofnode_phandle_args args;
+       ofnode phy_node, mdio_node;
+       int ret;
 
        pdata->iobase = dev_read_addr(dev);
 
+       phy_node = dev_get_phy_node(dev);
+       if (phy_node == ofnode_null()) {
+               dev_err(dev, "failed to get PHY node\n");
+               return ret;
+       }
+       /*
+        * The PHY regulator is in the MDIO node, not the EMAC or PHY node.
+        * U-Boot does not have (and does not need) a device driver for the
+        * MDIO device, so just "pass through" that DT node to get to the
+        * regulator phandle.
+        * The PHY regulator is optional, though: ignore if we cannot find
+        * a phy-supply property.
+        */
+       mdio_node = ofnode_get_parent(phy_node);
+       ret= ofnode_parse_phandle_with_args(mdio_node, "phy-supply", NULL, 0, 0,
+                                           &args);
+       if (ret && ret != -ENOENT) {
+               dev_err(dev, "failed to get PHY supply node\n");
+               return ret;
+       }
+       if (!ret) {
+               ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR, args.node,
+                                                 &priv->phy_reg);
+               if (ret) {
+                       dev_err(dev, "failed to get PHY regulator node\n");
+                       return ret;
+               }
+       }
+
        return 0;
 }