[U-Boot] [PATCH v2 1/3] net: add dm_eth_phy_connect helper to link eth/PHY based on DT

Alex Marginean alexandru.marginean at nxp.com
Mon Aug 12 09:14:41 UTC 2019


The helper is useful for platforms that link ethernet interfaces and PHYs
in device tree using current bindings.  Drivers could do this directly, but
the code is generic enough and helps keep drivers simpler.
The patch also adds dm_mdio_phy_scan useful to scan a MDIO bus for PHYs.

Signed-off-by: Alex Marginean <alexm.osslist at gmail.com>
---

Changes in v2:
	- Moved MDIO scan code into dm_mdio_phy_scan which is also exported
	- Use interface instead of if_type for consistency

 include/miiphy.h  |  25 +++++++++
 net/mdio-uclass.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 151 insertions(+)

diff --git a/include/miiphy.h b/include/miiphy.h
index 9b97d09f18..727d5ceeef 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -165,6 +165,31 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
 				       struct udevice *ethdev,
 				       phy_interface_t interface);
 
+/**
+ * dm_mdio_phy_scan - Scan for a PHY on the given MDIO bus
+ *
+ * @dev: mdio dev
+ * @ethdev: ethernet device to connect to the PHY
+ * @interface: MAC-PHY protocol
+ * @mask: bitmask of PHY addresses to scan, use all Fs to scan all addresses
+ *
+ * @return pointer to phy_device, or 0 on error
+ */
+struct phy_device *dm_mdio_phy_scan(struct udevice *dev, struct udevice *ethdev,
+				    phy_interface_t interface, uint mask);
+
+/**
+ * dm_eth_phy_connect - Connect an Eth device to a PHY based on device tree
+ *
+ * Picks up the DT phy-handle/mdio-handle and phy-mode from ethernet device node
+ * and connects the ethernet device to the linked PHY.
+ *
+ * @dev: ethernet device
+ *
+ * @return pointer to phy_device, or 0 on error
+ */
+struct phy_device *dm_eth_phy_connect(struct udevice *dev);
+
 #endif
 
 #ifdef CONFIG_DM_MDIO_MUX
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
index 36a404ff44..bac3144514 100644
--- a/net/mdio-uclass.c
+++ b/net/mdio-uclass.c
@@ -105,6 +105,132 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
 	return phy_connect(pdata->mii_bus, addr, ethdev, interface);
 }
 
+struct phy_device *dm_mdio_phy_scan(struct udevice *dev, struct udevice *ethdev,
+				    phy_interface_t interface, uint mask)
+{
+	struct mdio_perdev_priv *pdata;
+	struct phy_device *phy;
+
+	pdata = dev_get_uclass_priv(dev);
+
+	phy = phy_find_by_mask(pdata->mii_bus, mask, interface);
+	if (phy)
+		phy_connect_dev(phy, ethdev);
+	else
+		dev_dbg(dev, "no PHY detected on bus\n");
+
+	return phy;
+}
+
+static struct phy_device *dm_eth_connect_phy_handle(struct udevice *dev,
+						    phy_interface_t interface)
+{
+	u32 phy_phandle, phy_addr;
+	struct udevice *mdio_dev;
+	struct phy_device *phy;
+	ofnode phy_node;
+
+	if (ofnode_read_u32(dev->node, "phy-handle", &phy_phandle)) {
+		dev_dbg(dev, "phy-handle missing in ethernet node\n");
+		return NULL;
+	}
+
+	phy_node = ofnode_get_by_phandle(phy_phandle);
+	if (!ofnode_valid(phy_node)) {
+		dev_dbg(dev, "invalid phy node\n");
+		return NULL;
+	}
+
+	if (ofnode_read_u32(phy_node, "reg", &phy_addr)) {
+		dev_dbg(dev, "missing reg property in phy node\n");
+		return NULL;
+	}
+
+	if (uclass_get_device_by_ofnode(UCLASS_MDIO,
+					ofnode_get_parent(phy_node),
+					&mdio_dev)) {
+		dev_dbg(dev, "can't find MDIO bus for node %s\n",
+			ofnode_get_name(ofnode_get_parent(phy_node)));
+		return NULL;
+	}
+
+	phy = dm_mdio_phy_connect(mdio_dev, phy_addr, dev, interface);
+	phy->node = phy_node;
+
+	return phy;
+}
+
+static struct phy_device *dm_eth_connect_mdio_handle(struct udevice *dev,
+						     phy_interface_t interface)
+{
+	u32 mdio_phandle;
+	ofnode mdio_node;
+	struct udevice *mdio_dev;
+	uint mask = 0xffffffff;
+
+	if (ofnode_read_u32(dev->node, "mdio-handle", &mdio_phandle)) {
+		dev_dbg(dev, "mdio-handle missing in ethernet node\n");
+		return NULL;
+	}
+
+	mdio_node = ofnode_get_by_phandle(mdio_phandle);
+	if (!ofnode_valid(mdio_node)) {
+		dev_dbg(dev, "invalid mdio node\n");
+		return NULL;
+	}
+
+	if (uclass_get_device_by_ofnode(UCLASS_MDIO, mdio_node, &mdio_dev)) {
+		dev_dbg(dev, "can't find MDIO bus for node %s\n",
+			ofnode_get_name(mdio_node));
+		return NULL;
+	}
+
+	return dm_mdio_phy_scan(mdio_dev, dev, interface, mask);
+}
+
+/* Connect to a PHY linked in eth DT node */
+struct phy_device *dm_eth_phy_connect(struct udevice *dev)
+{
+	const char *if_str;
+	phy_interface_t interface;
+	struct phy_device *phy;
+
+	if (!ofnode_valid(dev->node)) {
+		debug("%s: supplied eth dev has no DT node!\n", dev->name);
+		return NULL;
+	}
+
+	/*
+	 * The sequence should be as follows:
+	 * - if there is a phy-handle property, follow that,
+	 * - if there is a mdio-handle property, follow that and scan for the
+	 *   PHY,
+	 * - if the above came out empty, just return NULL.
+	 */
+
+	interface = PHY_INTERFACE_MODE_NONE;
+	if_str = ofnode_read_string(dev->node, "phy-mode");
+	if (if_str)
+		interface = phy_get_interface_by_name(if_str);
+	if (interface < 0)
+		interface = PHY_INTERFACE_MODE_NONE;
+
+	if (interface == PHY_INTERFACE_MODE_NONE)
+		dev_dbg(dev, "can't find interface mode, default to NONE\n");
+
+	phy = dm_eth_connect_phy_handle(dev, interface);
+
+	if (!phy)
+		phy = dm_eth_connect_mdio_handle(dev, interface);
+
+	if (!phy)
+		return NULL;
+
+	phy->interface = interface;
+
+	return phy;
+}
+
 UCLASS_DRIVER(mdio) = {
 	.id = UCLASS_MDIO,
 	.name = "mdio",
-- 
2.17.1



More information about the U-Boot mailing list