diff mbox series

[U-Boot,v3,3/5] net: mdio-uclass: Add helper functions for scanning the MDIO bus

Message ID 20191101134145.19500-4-alexandru.marginean@nxp.com
State Superseded
Delegated to: Joe Hershberger
Headers show
Series Add helper function for linking a DM Eth device to a PHY | expand

Commit Message

Alexandru Marginean Nov. 1, 2019, 1:41 p.m. UTC
The patch introduces dm_mdio_phy_scan which is a DM wrapper over
phy_find_by_mask.  It also updates dm_eth_phy_connect to scan a MDIO bus
for PHYs if the ethernet node contains a mdio-handle property.

Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
---
 include/miiphy.h  | 14 ++++++++++++
 net/mdio-uclass.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)
diff mbox series

Patch

diff --git a/include/miiphy.h b/include/miiphy.h
index e591d93416..a5bdc29a47 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -165,6 +165,20 @@  struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr,
 				       struct udevice *ethdev,
 				       phy_interface_t interface);
 
+/**
+ * dm_mdio_phy_scan - Scan for a PHY on the given MDIO bus
+ *
+ * @mdiodev: mdio device to scan
+ * @ethdev: ethernet device to connect to the PHY
+ * @interface: MAC-PHY protocol
+ * @addrmask: 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 *mdiodev,
+				    struct udevice *ethdev,
+				    phy_interface_t interface, uint addrmask);
+
 /**
  * dm_eth_phy_connect - Connect an Eth device to a PHY based on device tree
  *
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
index cf736a3ae5..9ca462edb2 100644
--- a/net/mdio-uclass.c
+++ b/net/mdio-uclass.c
@@ -116,6 +116,24 @@  struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr,
 	return phy_connect(pdata->mii_bus, phyaddr, ethdev, interface);
 }
 
+struct phy_device *dm_mdio_phy_scan(struct udevice *mdiodev,
+				    struct udevice *ethdev,
+				    phy_interface_t interface, uint addrmask)
+{
+	struct mdio_perdev_priv *pdata;
+	struct phy_device *phy;
+
+	pdata = dev_get_uclass_priv(mdiodev);
+
+	phy = phy_find_by_mask(pdata->mii_bus, addrmask, interface);
+	if (phy)
+		phy_connect_dev(phy, ethdev);
+	else
+		dev_dbg(mdiodev, "no PHY detected on bus\n");
+
+	return phy;
+}
+
 static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev,
 						    phy_interface_t interface)
 {
@@ -156,6 +174,34 @@  static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev,
 	return phy;
 }
 
+static struct phy_device *dm_eth_connect_mdio_handle(struct udevice *ethdev,
+						     phy_interface_t interface)
+{
+	u32 mdio_phandle;
+	ofnode mdio_node;
+	struct udevice *mdiodev;
+	uint mask = 0xffffffff;
+
+	if (ofnode_read_u32(ethdev->node, "mdio-handle", &mdio_phandle)) {
+		dev_dbg(ethdev, "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, &mdiodev)) {
+		dev_dbg(ethdev, "can't find MDIO bus for node %s\n",
+			ofnode_get_name(mdio_node));
+		return NULL;
+	}
+
+	return dm_mdio_phy_scan(mdiodev, ethdev, interface, mask);
+}
+
 /* Connect to a PHY linked in eth DT node */
 struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
 {
@@ -178,8 +224,19 @@  struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
 	if (interface == PHY_INTERFACE_MODE_NONE)
 		dev_dbg(ethdev, "can't find interface mode, default to NONE\n");
 
+	/*
+	 * The sequence is:
+	 * - 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, return NULL.
+	 */
+
 	phy = dm_eth_connect_phy_handle(ethdev, interface);
 
+	if (!phy)
+		phy = dm_eth_connect_mdio_handle(ethdev, interface);
+
 	if (!phy)
 		return NULL;