All of lore.kernel.org
 help / color / mirror / Atom feed
From: Troy Kisky <troy.kisky@boundarydevices.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH V3 5/9] phy: add phy_find_by_mask/phy_connect_dev
Date: Mon, 22 Oct 2012 19:40:43 -0700	[thread overview]
Message-ID: <1350960047-23404-6-git-send-email-troy.kisky@boundarydevices.com> (raw)
In-Reply-To: <1350960047-23404-1-git-send-email-troy.kisky@boundarydevices.com>

It is useful to be able to try a range of
possible phy addresses to connect.

Also, an ethernet device is not required
to use phy_find_by_mask leading to better
separation of mii vs ethernet, as suggested
by Andy Fleming.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>

---
v2: no change
---
 drivers/net/phy/phy.c |  128 ++++++++++++++++++++++++++++++-------------------
 include/phy.h         |    3 ++
 2 files changed, 81 insertions(+), 50 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index baef60f..c51b309 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
 #include <miiphy.h>
 #include <phy.h>
 #include <errno.h>
+#include <linux/err.h>
 
 /* Generic PHY support and helper functions */
 
@@ -573,6 +574,61 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
 	return 0;
 }
 
+static struct phy_device *create_phy_by_mask(struct mii_dev *bus,
+		unsigned phy_mask, int devad, phy_interface_t interface)
+{
+	u32 phy_id = 0xffffffff;
+	while (phy_mask) {
+		int addr = ffs(phy_mask) - 1;
+		int r = get_phy_id(bus, addr, devad, &phy_id);
+		if (r < 0)
+			return ERR_PTR(r);
+		/* If the PHY ID is mostly f's, we didn't find anything */
+		if ((phy_id & 0x1fffffff) != 0x1fffffff)
+			return phy_device_create(bus, addr, phy_id, interface);
+		phy_mask &= ~(1 << addr);
+	}
+	return NULL;
+}
+
+static struct phy_device *search_for_existing_phy(struct mii_dev *bus,
+		unsigned phy_mask, phy_interface_t interface)
+{
+	/* If we have one, return the existing device, with new interface */
+	while (phy_mask) {
+		int addr = ffs(phy_mask) - 1;
+		if (bus->phymap[addr]) {
+			bus->phymap[addr]->interface = interface;
+			return bus->phymap[addr];
+		}
+		phy_mask &= ~(1 << addr);
+	}
+	return NULL;
+}
+
+static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus,
+		unsigned phy_mask, phy_interface_t interface)
+{
+	int i;
+	struct phy_device *phydev;
+
+	phydev = search_for_existing_phy(bus, phy_mask, interface);
+	if (phydev)
+		return phydev;
+	/* Try Standard (ie Clause 22) access */
+	/* Otherwise we have to try Clause 45 */
+	for (i = 0; i < 5; i++) {
+		phydev = create_phy_by_mask(bus, phy_mask,
+				i ? i : MDIO_DEVAD_NONE, interface);
+		if (IS_ERR(phydev))
+			return NULL;
+		if (phydev)
+			return phydev;
+	}
+	printf("Phy not found\n");
+	return phy_device_create(bus, ffs(phy_mask) - 1, 0xffffffff, interface);
+}
+
 /**
  * get_phy_device - reads the specified PHY device and returns its @phy_device struct
  * @bus: the target MII bus
@@ -584,38 +640,7 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
 struct phy_device *get_phy_device(struct mii_dev *bus, int addr,
 				phy_interface_t interface)
 {
-	u32 phy_id = 0x1fffffff;
-	int i;
-	int r;
-
-	/* If we have one, return the existing device, with new interface */
-	if (bus->phymap[addr]) {
-		bus->phymap[addr]->interface = interface;
-
-		return bus->phymap[addr];
-	}
-
-	/* Try Standard (ie Clause 22) access */
-	r = get_phy_id(bus, addr, MDIO_DEVAD_NONE, &phy_id);
-	if (r)
-		return NULL;
-
-	/* If the PHY ID is mostly f's, we didn't find anything */
-	if ((phy_id & 0x1fffffff) != 0x1fffffff)
-		return phy_device_create(bus, addr, phy_id, interface);
-
-	/* Otherwise we have to try Clause 45 */
-	for (i = 1; i < 5; i++) {
-		r = get_phy_id(bus, addr, i, &phy_id);
-		if (r)
-			return NULL;
-
-		/* If the phy_id is mostly Fs, there is no device there */
-		if ((phy_id & 0x1fffffff) != 0x1fffffff)
-			break;
-	}
-
-	return phy_device_create(bus, addr, phy_id, interface);
+	return get_phy_device_by_mask(bus, 1 << addr, interface);
 }
 
 int phy_reset(struct phy_device *phydev)
@@ -688,38 +713,41 @@ int miiphy_reset(const char *devname, unsigned char addr)
 	return phy_reset(phydev);
 }
 
-struct phy_device *phy_connect(struct mii_dev *bus, int addr,
-				struct eth_device *dev,
-				phy_interface_t interface)
+struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask,
+		phy_interface_t interface)
 {
-	struct phy_device *phydev;
-
 	/* Reset the bus */
 	if (bus->reset)
 		bus->reset(bus);
 
 	/* Wait 15ms to make sure the PHY has come out of hard reset */
 	udelay(15000);
+	return get_phy_device_by_mask(bus, phy_mask, interface);
+}
 
-	phydev = get_phy_device(bus, addr, interface);
-
-	if (!phydev) {
-		printf("Could not get PHY for %s:%d\n", bus->name, addr);
-
-		return NULL;
-	}
-
+void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev)
+{
 	/* Soft Reset the PHY */
 	phy_reset(phydev);
-
-	if (phydev->dev)
+	if (phydev->dev) {
 		printf("%s:%d is connected to %s.  Reconnecting to %s\n",
-			bus->name, addr, phydev->dev->name, dev->name);
-
+				phydev->bus->name, phydev->addr,
+				phydev->dev->name, dev->name);
+	}
 	phydev->dev = dev;
-
 	debug("%s connected to %s\n", dev->name, phydev->drv->name);
+}
+
+struct phy_device *phy_connect(struct mii_dev *bus, int addr,
+		struct eth_device *dev, phy_interface_t interface)
+{
+	struct phy_device *phydev;
 
+	phydev = phy_find_by_mask(bus, 1 << addr, interface);
+	if (phydev)
+		phy_connect_dev(phydev, dev);
+	else
+		printf("Could not get PHY for %s: addr %d\n", bus->name, addr);
 	return phydev;
 }
 
diff --git a/include/phy.h b/include/phy.h
index 3c30f11..58ca273 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -199,6 +199,9 @@ static inline int is_10g_interface(phy_interface_t interface)
 
 int phy_init(void);
 int phy_reset(struct phy_device *phydev);
+struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask,
+		phy_interface_t interface);
+void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev);
 struct phy_device *phy_connect(struct mii_dev *bus, int addr,
 				struct eth_device *dev,
 				phy_interface_t interface);
-- 
1.7.9.5

  parent reply	other threads:[~2012-10-23  2:40 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-20 22:48 [U-Boot] [PATCH V1 1/3] phy: add phy_connect_by_mask Troy Kisky
2012-08-20 22:48 ` [U-Boot] [PATCH V1 2/3] fec_mxc: use phy_connect_by_mask Troy Kisky
2012-08-20 22:48 ` [U-Boot] [PATCH V1 3/3] mx6qsabrelite: set CONFIG_FEC_MXC_PHYMASK Troy Kisky
2012-08-20 23:07 ` [U-Boot] [PATCH V1 1/3] phy: add phy_connect_by_mask Troy Kisky
2012-08-21  0:35   ` Andy Fleming
2012-08-22 19:59     ` Troy Kisky
2012-08-22 20:40       ` Andy Fleming
2012-08-22 20:50         ` Joe Hershberger
2012-08-22 21:21         ` Troy Kisky
2012-09-26 17:26           ` Joe Hershberger
2012-09-26 17:47             ` Troy Kisky
2012-08-22 20:11     ` Eric Nelson
2012-08-22 20:50       ` Andy Fleming
2012-08-22 20:56         ` Eric Nelson
2012-10-23  2:40 ` [U-Boot] [PATCH V3 0/9] separate miiphy from ethernet Troy Kisky
2012-10-23  2:40   ` [U-Boot] [PATCH V3 1/9] doc/README.fec_mxc: add documentation Troy Kisky
2012-10-23  2:40   ` [U-Boot] [PATCH V3 2/9] net: fec_mxc: delete CONFIG_FEC_MXC_MULTI Troy Kisky
2012-10-23  2:40   ` [U-Boot] [PATCH V3 3/9] net: fec_mxc: change fec_mii_setspeed parameter Troy Kisky
2012-10-23  2:40   ` [U-Boot] [PATCH V3 4/9] net: fec_mxc: have fecmxc_initialize call fecmxc_initialize_multi Troy Kisky
2012-10-23  2:40   ` Troy Kisky [this message]
2012-10-23  2:40   ` [U-Boot] [PATCH V3 6/9] net: fec_mxc: use fec_set_dev_name to set name Troy Kisky
2012-10-23  2:40   ` [U-Boot] [PATCH V3 7/9] net: fec_mxc: only call phy_connect in fec_probe Troy Kisky
2012-10-23  2:40   ` [U-Boot] [PATCH V3 8/9] net: fec_mxc: get phydev before fec_probe Troy Kisky
2012-10-23  2:40   ` [U-Boot] [PATCH V3 9/9] mx6qsabrelite: search mii phy address 4-7 Troy Kisky
2012-11-10  7:28   ` [U-Boot] [PATCH V3 0/9] separate miiphy from ethernet Stefano Babic
2013-01-22 23:48     ` Troy Kisky
2013-01-23  8:48       ` Stefano Babic
2013-01-23 19:06         ` Troy Kisky
2013-01-24  9:09           ` Stefano Babic
2013-01-23 22:35         ` Troy Kisky
2013-01-03 22:00   ` Troy Kisky
2013-01-28  6:00   ` Stefano Babic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1350960047-23404-6-git-send-email-troy.kisky@boundarydevices.com \
    --to=troy.kisky@boundarydevices.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.