[PATCH 4/5] openfirmware: Add OF phylib support code

Previous thread: Passive OS fingerprint xtables match. by Evgeniy Polyakov on Tuesday, March 10, 2009 - 8:13 am. (11 messages)

Next thread: Re: net_device_ops support in bridging and fec_mpc52xx.c by David Miller on Tuesday, March 10, 2009 - 10:19 am. (2 messages)
From: Grant Likely
Date: Tuesday, March 10, 2009 - 8:21 am

Hi all,

This series reworks some of the phylib code to allow PHY descriptions and
connections to be extracted from the OF device tree.  MDIO bus drivers gain
a common helper function for parsing the PHY data and registering new
phy_devices to match.  Ethernet controller drivers gain the ability to
resolve to a phy_device from a device tree phandle.

One notable aspect is that the Ethernet controller driver doesn't know
if the phy_device is registered before or after the Ethernet driver.  This
series adds a function to the device model core code to make it simple for
the driver to register a bus notifier (mdio_bus in this case), which gets
called both for existing devices and for future device registrations.  The
advantage of this is that the driver doesn't need to know or care when the
device actually shows up.  It just knows that its callback will get called
when the device is available.  I think this is a good approach, but I'd
appreciate some feedback on it.

Cheers,
g.

drivers/base/bus.c            |   47 +++++++++
 drivers/net/Kconfig           |    2 +-
 drivers/net/fec_mpc52xx.c     |  220 ++++++++++++++++++-----------------------
 drivers/net/fec_mpc52xx_phy.c |   30 +++---
 drivers/net/phy/mdio_bus.c    |   29 +-----
 drivers/net/phy/phy_device.c  |  161 +++++++++++++++++++++++-------
 drivers/of/Kconfig            |    6 +
 drivers/of/Makefile           |    1 +
 drivers/of/of_mdio.c          |   70 +++++++++++++
 include/linux/device.h        |    2 +
 include/linux/of_mdio.h       |   20 ++++
 include/linux/phy.h           |    6 +
 12 files changed, 388 insertions(+), 206 deletions(-)

--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
--

From: Grant Likely
Date: Tuesday, March 10, 2009 - 8:22 am

From: Grant Likely <grant.likely@secretlab.ca>

bus_register_notifier_alldev() is a variation on bus_register_notifier()
which also triggers the notifier callback for devices already on the bus
and already bound to drivers.

This function is useful for the case where a driver needs to get a
reference to a struct device other than the one it is bound to and
it is not known if the device will be bound before or after this
function is called.  For example, an Ethernet device connected to
a PHY that is probed separately.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
CC: linux-kernel@vger.kernel.org
CC: linuxppc-dev@ozlabs.org
CC: Greg Kroah-Hartman <gregkh@suse.de>
---

 drivers/base/bus.c     |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/device.h |    2 ++
 2 files changed, 49 insertions(+), 0 deletions(-)


diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 83f32b8..6edde85 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -962,6 +962,53 @@ int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(bus_register_notifier);
 
+/**
+ * bus_register_notifier_alldev_helper - internal support function
+ * Used by bus_register_notifier_alldev() to create ADD and BOUND events
+ * for devices.
+ */
+static int bus_register_notifier_alldev_helper(struct device *dev, void *data)
+{
+	struct notifier_block *nb = data;
+	nb->notifier_call(nb, BUS_NOTIFY_ADD_DEVICE, dev);
+	if (dev->driver)
+		nb->notifier_call(nb, BUS_NOTIFY_BOUND_DRIVER, dev);
+	return 0;
+}
+
+/**
+ * bus_register_notifier_alldev - Register for bus events; include existing devs
+ * @bus: pointer to bus_type
+ * @nb: pointer to notifier block to register with the bus
+ *
+ * Similar to bus_register_notifier() except it also generates events for
+ * devices already on the bus when the notifier is registered.  When this
+ * function is called the notifier is called once for each device with
+ * the ...
From: Grant Likely
Date: Tuesday, March 10, 2009 - 8:22 am

From: Grant Likely <grant.likely@secretlab.ca>

This patch makes changes in preparation for supporting open firmware
device tree descriptions of MDIO busses.  Changes include:
- Cleanup handling of phy_map[] entries; they are already NULLed when
  registering and so don't need to be re-cleared, and it is good practice
  to clear them out when unregistering.
- Split phy_device registration out into a new function so that the
  OF helpers can do two stage registration (separate allocation and
  registration steps).

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
CC: linuxppc-dev@ozlabs.org
CC: netdev@vger.kernel.org
CC: Andy Fleming <afleming@freescale.com>
---

 drivers/net/phy/mdio_bus.c   |   29 +++-------------------------
 drivers/net/phy/phy_device.c |   43 ++++++++++++++++++++++++++++++++++++++----
 include/linux/phy.h          |    1 +
 3 files changed, 43 insertions(+), 30 deletions(-)


diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 811a637..3c39c7b 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -112,7 +112,6 @@ int mdiobus_register(struct mii_bus *bus)
 		bus->reset(bus);
 
 	for (i = 0; i < PHY_MAX_ADDR; i++) {
-		bus->phy_map[i] = NULL;
 		if ((bus->phy_mask & (1 << i)) == 0) {
 			struct phy_device *phydev;
 
@@ -149,6 +148,7 @@ void mdiobus_unregister(struct mii_bus *bus)
 	for (i = 0; i < PHY_MAX_ADDR; i++) {
 		if (bus->phy_map[i])
 			device_unregister(&bus->phy_map[i]->dev);
+		bus->phy_map[i] = NULL;
 	}
 }
 EXPORT_SYMBOL(mdiobus_unregister);
@@ -187,35 +187,12 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
 	if (IS_ERR(phydev) || phydev == NULL)
 		return phydev;
 
-	/* There's a PHY at this address
-	 * We need to set:
-	 * 1) IRQ
-	 * 2) bus_id
-	 * 3) parent
-	 * 4) bus
-	 * 5) mii_bus
-	 * And, we need to register it */
-
-	phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
-
-	phydev->dev.parent = bus->parent;
-	phydev->dev.bus = ...
From: Grant Likely
Date: Tuesday, March 10, 2009 - 8:22 am

From: Grant Likely <grant.likely@secretlab.ca>

Add phy_connect_direct() and phy_attach_direct() functions so that
drivers can use a pointer to the phy_device instead of trying to determine
the phy's bus_id string.

This patch is useful for OF device tree descriptions of phy devices where
the driver doesn't need or know what the bus_id value in order to get a
phy_device pointer.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 drivers/net/phy/phy_device.c |  118 ++++++++++++++++++++++++++++++------------
 include/linux/phy.h          |    5 ++
 2 files changed, 90 insertions(+), 33 deletions(-)


diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 793332f..238d21e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -290,6 +290,33 @@ void phy_prepare_link(struct phy_device *phydev,
 }
 
 /**
+ * phy_connect_direct - connect an ethernet device to a specific phy_device
+ * @dev: the network device to connect
+ * @phydev: the pointer to the phy device
+ * @handler: callback function for state change notifications
+ * @flags: PHY device's dev_flags
+ * @interface: PHY device's interface
+ */
+int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
+		       void (*handler)(struct net_device *), u32 flags,
+		       phy_interface_t interface)
+{
+	int rc;
+
+	rc = phy_attach_direct(dev, phydev, flags, interface);
+	if (rc)
+		return rc;
+
+	phy_prepare_link(phydev, handler);
+	phy_start_machine(phydev, NULL);
+	if (phydev->irq > 0)
+		phy_start_interrupts(phydev);
+
+	return 0;
+}
+EXPORT_SYMBOL(phy_connect_direct);
+
+/**
  * phy_connect - connect an ethernet device to a PHY device
  * @dev: the network device to connect
  * @bus_id: the id string of the PHY device to connect
@@ -310,18 +337,21 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
 		phy_interface_t interface)
 {
 	struct phy_device *phydev;
+	struct device *d;
+	int rc;
 ...
From: Grant Likely
Date: Tuesday, March 10, 2009 - 8:22 am

From: Grant Likely <grant.likely@secretlab.ca>

Add support for parsing the device tree for PHY devices on an MDIO bus

CC: Andy Fleming <afleming@freescale.com>
CC: linuxppc-dev@ozlabs.org
CC: devtree-discuss@ozlabs.org

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 drivers/of/Kconfig      |    6 ++++
 drivers/of/Makefile     |    1 +
 drivers/of/of_mdio.c    |   70 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_mdio.h |   20 +++++++++++++
 4 files changed, 97 insertions(+), 0 deletions(-)
 create mode 100644 drivers/of/of_mdio.c
 create mode 100644 include/linux/of_mdio.h


diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index f821dbc..6fe043b 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -19,3 +19,9 @@ config OF_SPI
 	depends on OF && PPC_OF && SPI
 	help
 	  OpenFirmware SPI accessors
+
+config OF_MDIO
+	def_tristate PHYLIB
+	depends on OF && PHYLIB
+	help
+	  OpenFirmware MDIO bus (Ethernet PHY) accessors
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 4c3c6f8..bdfb5f5 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_OF_DEVICE) += device.o platform.o
 obj-$(CONFIG_OF_GPIO)   += gpio.o
 obj-$(CONFIG_OF_I2C)	+= of_i2c.o
 obj-$(CONFIG_OF_SPI)	+= of_spi.o
+obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
new file mode 100644
index 0000000..6a7d4b2
--- /dev/null
+++ b/drivers/of/of_mdio.c
@@ -0,0 +1,70 @@
+/*
+ * OF helpers for the MDIO (Ethernet PHY) API
+ *
+ * Copyright (c) 2009 Secret Lab Technologies, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file provides helper functions for extracting PHY device information
+ * out of the OpenFirmware device tree and using it to ...
From: Grant Likely
Date: Tuesday, March 10, 2009 - 8:22 am

From: Grant Likely <grant.likely@secretlab.ca>

The patch reworks the MPC5200 Fast Ethernet Controller (FEC) driver to
use the of_mdio infrastructure for registering PHY devices from data out
openfirmware device tree, and eliminates the assumption that the PHY
for the FEC is always attached to the FEC's own MDIO bus.  With this
patch, the FEC can use a PHY attached to any MDIO bus if it is described
in the device tree.
---

 drivers/net/Kconfig           |    2 
 drivers/net/fec_mpc52xx.c     |  220 ++++++++++++++++++-----------------------
 drivers/net/fec_mpc52xx_phy.c |   30 ++----
 3 files changed, 109 insertions(+), 143 deletions(-)


diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6bdfd47..5b74a9a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1854,7 +1854,7 @@ config FEC_MPC52xx
 
 config FEC_MPC52xx_MDIO
 	bool "MPC52xx FEC MDIO bus driver"
-	depends on FEC_MPC52xx
+	depends on FEC_MPC52xx && OF_MDIO
 	default y
 	---help---
 	  The MPC5200's FEC can connect to the Ethernet either with
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 049b0a7..4efcd47 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -43,11 +43,9 @@
 
 #define DRIVER_NAME "mpc52xx-fec"
 
-#define FEC5200_PHYADDR_NONE	(-1)
-#define FEC5200_PHYADDR_7WIRE	(-2)
-
 /* Private driver data structure */
 struct mpc52xx_fec_priv {
+	struct net_device *ndev;
 	int duplex;
 	int speed;
 	int r_irq;
@@ -59,10 +57,12 @@ struct mpc52xx_fec_priv {
 	int msg_enable;
 
 	/* MDIO link details */
-	int phy_addr;
-	unsigned int phy_speed;
+	struct notifier_block notifier;
+	unsigned int mdio_speed;
+	struct device_node *phy_node;
 	struct phy_device *phydev;
 	enum phy_state link;
+	int seven_wire_mode;
 };
 
 
@@ -210,66 +210,6 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev)
 		phy_print_status(phydev);
 }
 
-static int mpc52xx_fec_init_phy(struct net_device *dev)
-{
-	struct mpc52xx_fec_priv *priv ...
From: Anton Vorontsov
Date: Tuesday, March 10, 2009 - 12:16 pm

[...]

Two registration points for the netdev... That's ugly. :-/

What problem are you trying to solve w/ these patches, btw?

`ifconfig ethX up` is safe even w/o PHY attached.

All the (user-visible) changes is that we no longer have "ethX"
until PHY is registered, and I can't say that this is good either.

Previously you'd have ethX all the time, and `ifconfig ethX up`
would report user-friendly "PHY not attached" error. Now we have
to guess why ethX isn't there.

I can't say that the probing code is much prettier or easier to
understand... But maybe there are some other problems that you're
solving, which I don't see so far?

That is, can you explain why the changes are needed? Did you
consider other solutions?


Thanks!


AFAIK, Gianfar and UCC Geth drivers can do this too, so I'm assuming
that this isn't the cause for these major changes.

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
--

From: Grant Likely
Date: Tuesday, March 10, 2009 - 12:48 pm

On Tue, Mar 10, 2009 at 1:16 PM, Anton Vorontsov

Fair enough.  If it is okay to register the PHY after registering the

Primary problem is that this driver currently does not work for a PHY
on a different MDIO bus.  Secondary is that current code depends on

Yes, I considered doing some kind of platform function to call and get
the name of the PHY, but any such thing turned out to be fragile and
rather platform specific.  The bus notifier approach seemed to be the
simplest way to defer part of initialization while waiting for the PHY
to become available.  I want to be using common code here as I've got
another Ethernet driver (ll_temac; not posted yet) that needs to do

Certainly the mpc5200-fec driver's original phy code certainly wasn't
as robust as the ucc_geth and gianfar phy handling.

ucc_geth open codes a solution to decode the phy_device name from
several nodes in the device tree and doesn't handle the case where the
ucc_geth is initialized before the phy_device is registered.  gianfar
open codes the same thing.  This solution uses common code to locate
the phy_device, and it works regardless of what order devices are
registered in.

That being said, the 5200 driver originally using probe() time to
connect to the phy.  If I change it to be connected at open time, then
does the registration order issue become irrelevant?  Regardless, I
think all the drivers should be using common code for obtaining the
phy_device from the device tree.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
--

From: Anton Vorontsov
Date: Tuesday, March 10, 2009 - 1:29 pm

On Tue, Mar 10, 2009 at 01:48:26PM -0600, Grant Likely wrote:

Yup. `ifconfig ethX up' calls ->open(). If it fails (and prints

Not necessary `struct phy_device'. All we need is some common
routine for translating PHY's "mdio_node->full_name + phy id" to
phy_bus_id.

That is, you can just factor out this code from the gianfar driver,

void gfar_mdio_bus_name(char *name, struct device_node *np)
{
        const u32 *reg;

        reg = of_get_property(np, "reg", NULL);

        snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0);
}

...
        gfar_mdio_bus_name(bus_name, mdio);
        snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x",
                 bus_name, *id);
...

And make sure FEC MDIO driver does mdio_bus->parent = &ofdev->dev;

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
--

From: Grant Likely
Date: Wednesday, March 18, 2009 - 9:35 pm

On Tue, Mar 10, 2009 at 2:29 PM, Anton Vorontsov

This only works if the network driver knows how the MDIO bus is named.
 The current code assumes that the MDIO bus name is the register
address, but this is a driver implementation detail and MDIO bus
drivers can deviate from this.  What about MDIO busses that don't have
a reg property?  For example, fs_enet/mii-bitbang.c sets the bus name
to "CPM2 Bitbanged MII".  There is no one-size-fits-all way to figure
out the phy bus id from the ethernet driver side of things.

The sure and simple way to guarantee a match between the PHY device
node and the phy_device is to use the PHY device_node pointer itself
as the search key.

I concede that my first attempt at this was overly complex, but I've
reworked the code and I think it makes thinks considerably simpler.
I'll post a new series tomorrow.  I've got patches to make the
ucc_eth, gianfar and fs_enet drivers to use the device_node method
also.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
--

Previous thread: Passive OS fingerprint xtables match. by Evgeniy Polyakov on Tuesday, March 10, 2009 - 8:13 am. (11 messages)

Next thread: Re: net_device_ops support in bridging and fec_mpc52xx.c by David Miller on Tuesday, March 10, 2009 - 10:19 am. (2 messages)