Subject: [PATCH v2 1/4] of/mdio: Add support function for Ethernet fixed-link property

From: Grant Likely <[email-masked]>
Date: Fri, 17 Jul 2009 01:31:31 -0600

From: Anton Vorontsov <[email-masked]>

Fixed-link support is broken for the ucc_eth, gianfar, and fs_enet
device drivers.  The "OF MDIO rework" patches removed most of the
support. Instead of re-adding fixed-link stuff to the drivers, this
patch adds a support function for parsing the fixed-link property
and obtaining a dummy phy to match.

Note: the dummy phy handling in arch/powerpc is a bit of a hack and
needs to be reworked.  This function is being added now to solve the
regression in the Ethernet drivers, but it should be considered a
temporary measure until the fixed link handling can be reworked.

Signed-off-by: Anton Vorontsov <[email-masked]>
Signed-off-by: Grant Likely <[email-masked]>
---

 drivers/of/of_mdio.c    |   42 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_mdio.h |    3 +++
 2 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index aee967d..bacaa53 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -9,6 +9,10 @@
  * out of the OpenFirmware device tree and using it to populate an mii_bus.
  */
 
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/err.h>
 #include <linux/phy.h>
 #include <linux/of.h>
 #include <linux/of_mdio.h>
@@ -137,3 +141,41 @@ struct phy_device *of_phy_connect(struct net_device *dev,
 	return phy_connect_direct(dev, phy, hndlr, flags, iface) ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect);
+
+/**
+ * of_phy_connect_fixed_link - Parse fixed-link property and return a dummy phy
+ * @dev: pointer to net_device claiming the phy
+ * @hndlr: Link state callback for the network device
+ * @iface: PHY data interface type
+ *
+ * This function is a temporary stop-gap and will be removed soon.  It is
+ * only to support the fs_enet, ucc_geth and gianfar Ethernet drivers.  Do
+ * not call this function from new drivers.
+ */
+struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
+					     void (*hndlr)(struct net_device *),
+					     phy_interface_t iface)
+{
+	struct device_node *net_np;
+	char bus_id[MII_BUS_ID_SIZE + 3];
+	struct phy_device *phy;
+	const u32 *phy_id;
+	int sz;
+
+	if (!dev->dev.parent)
+		return NULL;
+
+	net_np = dev_archdata_get_node(&dev->dev.parent->archdata);
+	if (!net_np)
+		return NULL;
+
+	phy_id = of_get_property(net_np, "fixed-link", &sz);
+	if (!phy_id || sz < sizeof(*phy_id))
+		return NULL;
+
+	sprintf(bus_id, PHY_ID_FMT, "0", phy_id[0]);
+
+	phy = phy_connect(dev, bus_id, hndlr, 0, iface);
+	return IS_ERR(phy) ? NULL : phy;
+}
+EXPORT_SYMBOL(of_phy_connect_fixed_link);
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h
index c9663c6..53b94e0 100644
--- a/include/linux/of_mdio.h
+++ b/include/linux/of_mdio.h
@@ -18,5 +18,8 @@ extern struct phy_device *of_phy_connect(struct net_device *dev,
 					 struct device_node *phy_np,
 					 void (*hndlr)(struct net_device *),
 					 u32 flags, phy_interface_t iface);
+extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
+					 void (*hndlr)(struct net_device *),
+					 phy_interface_t iface);
 
 #endif /* __LINUX_OF_MDIO_H */