From fe428b909b83f0ef83d1fbc7a446bfb60bc4fe01 Mon Sep 17 00:00:00 2001
From: Troy Kisky <troy.kisky@boundarydevices.com>
Date: Mon, 22 Oct 2012 16:40:46 +0000
Subject: [PATCH] net: fec_mxc: get phydev before fec_probe

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/fec_mxc.c | 117 +++++++++++++++++++++++++++---------------
 drivers/net/fec_mxc.h |   2 +-
 include/netdev.h      |   7 +++
 3 files changed, 83 insertions(+), 43 deletions(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 913c5617b2..4dbcdca4a0 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -901,12 +901,16 @@ static void fec_set_dev_name(char *dest, int dev_id)
 	sprintf(dest, (dev_id == -1) ? "FEC" : "FEC%i", dev_id);
 }
 
-static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
+#ifdef CONFIG_PHYLIB
+int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
+		struct mii_dev *bus, struct phy_device *phydev)
+#else
+static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
+		struct mii_dev *bus, int phy_id)
+#endif
 {
-	struct phy_device *phydev;
 	struct eth_device *edev;
 	struct fec_priv *fec;
-	struct mii_dev *bus;
 	unsigned char ethaddr[6];
 	uint32_t start;
 	int ret = 0;
@@ -953,69 +957,98 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 	}
 
 	fec_reg_setup(fec);
-
 	fec_set_dev_name(edev->name, dev_id);
 	fec->dev_id = (dev_id == -1) ? 0 : dev_id;
+	fec->bus = bus;
+	fec_mii_setspeed(bus->priv);
+#ifdef CONFIG_PHYLIB
+	fec->phydev = phydev;
+	phy_connect_dev(phydev, edev);
+	/* Configure phy */
+	phy_config(phydev);
+#else
 	fec->phy_id = phy_id;
+#endif
+	eth_register(edev);
+
+	if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {
+		debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
+		memcpy(edev->enetaddr, ethaddr, 6);
+	}
+	return ret;
+err3:
+	free(fec);
+err2:
+	free(edev);
+err1:
+	return ret;
+}
+
+struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
+{
+	struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
+	struct mii_dev *bus;
+	int ret;
 
 	bus = mdio_alloc();
 	if (!bus) {
 		printf("mdio_alloc failed\n");
-		ret = -ENOMEM;
-		goto err3;
+		return NULL;
 	}
 	bus->read = fec_phy_read;
 	bus->write = fec_phy_write;
+	bus->priv = eth;
 	fec_set_dev_name(bus->name, dev_id);
+
+	ret = mdio_register(bus);
+	if (ret) {
+		printf("mdio_register failed\n");
+		free(bus);
+		return NULL;
+	}
+	fec_mii_setspeed(eth);
+	return bus;
+}
+
+int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
+{
+	uint32_t base_mii;
+	struct mii_dev *bus = NULL;
+#ifdef CONFIG_PHYLIB
+	struct phy_device *phydev = NULL;
+#endif
+	int ret;
+
 #ifdef CONFIG_MX28
 	/*
 	 * The i.MX28 has two ethernet interfaces, but they are not equal.
 	 * Only the first one can access the MDIO bus.
 	 */
-	bus->priv = (struct ethernet_regs *)MXS_ENET0_BASE;
+	base_mii = MXS_ENET0_BASE;
 #else
-	bus->priv = fec->eth;
+	base_mii = addr;
 #endif
-	fec_mii_setspeed(bus->priv);
-	ret = mdio_register(bus);
-	if (ret) {
-		printf("mdio_register failed\n");
-		free(bus);
-		ret = -ENOMEM;
-		goto err3;
-	}
-	fec->bus = bus;
-	eth_register(edev);
-
-	if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {
-		debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
-		memcpy(edev->enetaddr, ethaddr, 6);
-	}
-	/* Configure phy */
+	debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);
+	bus = fec_get_miibus(base_mii, dev_id);
+	if (!bus)
+		return -ENOMEM;
 #ifdef CONFIG_PHYLIB
-	phydev = phy_connect(fec->bus, phy_id, edev, PHY_INTERFACE_MODE_RGMII);
+	phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
 	if (!phydev) {
 		free(bus);
-		ret = -ENOMEM;
-		goto err3;
+		return -ENOMEM;
 	}
-	fec->phydev = phydev;
-	phy_config(phydev);
+	ret = fec_probe(bd, dev_id, addr, bus, phydev);
+#else
+	ret = fec_probe(bd, dev_id, addr, bus, phy_id);
 #endif
+	if (ret) {
+#ifdef CONFIG_PHYLIB
+		free(phydev);
+#endif
+		free(bus);
+	}
 	return ret;
-
-err3:
-	free(fec);
-err2:
-	free(edev);
-err1:
-	return ret;
-}
-
-int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
-{
-	debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);
-	return fec_probe(bd, dev_id, phy_id, addr);
 }
 
 #ifdef CONFIG_FEC_MXC_PHYADDR
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index 203285af9a..b8f0da36cd 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -271,11 +271,11 @@ struct fec_priv {
 	bd_t *bd;
 	uint8_t *tdb_ptr;
 	int dev_id;
-	int phy_id;
 	struct mii_dev *bus;
 #ifdef CONFIG_PHYLIB
 	struct phy_device *phydev;
 #else
+	int phy_id;
 	int (*mii_postcall)(int);
 #endif
 };
diff --git a/include/netdev.h b/include/netdev.h
index 7f158d433b..fd3e243c71 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -215,9 +215,16 @@ struct mv88e61xx_config {
 int mv88e61xx_switch_initialize(struct mv88e61xx_config *swconfig);
 #endif /* CONFIG_MV88E61XX_SWITCH */
 
+struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id);
+#ifdef CONFIG_PHYLIB
+struct phy_device;
+int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
+		struct mii_dev *bus, struct phy_device *phydev);
+#else
 /*
  * Allow FEC to fine-tune MII configuration on boards which require this.
  */
 int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int));
+#endif
 
 #endif /* _NETDEV_H_ */
-- 
2.39.5