All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
@ 2011-09-27 23:26 ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2011-09-27 23:26 UTC (permalink / raw)
  To: devicetree-discuss, grant.likely, linux-kernel, netdev, davem; +Cc: David Daney

v2: Update bindings to use "reg" and "mdio-parent-bus" insutead of
    "cell-index" and "parent-bus"

v1:

We have several different boards with a multiplexer in the MDIO bus.
There is an MDIO bus controller connected to a switching device with
several child MDIO busses.

Everything is wired up using device tree bindings.

 1/3 - New of_mdio_find_bus() function used to help configuring the
       driver topology.

 2/3 - MDIO bus multiplexer framework.

 3/3 - A driver for a GPIO controlled multiplexer.


David Daney (3):
  netdev/of/phy: New function: of_mdio_find_bus().
  netdev/of/phy: Add MDIO bus multiplexer support.
  netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.

 .../devicetree/bindings/net/mdio-mux-gpio.txt      |  129 ++++++++++++++
 Documentation/devicetree/bindings/net/mdio-mux.txt |  136 +++++++++++++++
 drivers/net/phy/Kconfig                            |   17 ++
 drivers/net/phy/Makefile                           |    2 +
 drivers/net/phy/mdio-mux-gpio.c                    |  143 +++++++++++++++
 drivers/net/phy/mdio-mux.c                         |  182 ++++++++++++++++++++
 drivers/net/phy/mdio_bus.c                         |    3 +-
 drivers/of/of_mdio.c                               |   26 +++
 include/linux/mdio-mux.h                           |   18 ++
 include/linux/of_mdio.h                            |    2 +
 include/linux/phy.h                                |    1 +
 11 files changed, 658 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
 create mode 100644 drivers/net/phy/mdio-mux-gpio.c
 create mode 100644 drivers/net/phy/mdio-mux.c
 create mode 100644 include/linux/mdio-mux.h

-- 
1.7.2.3


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
@ 2011-09-27 23:26 ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2011-09-27 23:26 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

v2: Update bindings to use "reg" and "mdio-parent-bus" insutead of
    "cell-index" and "parent-bus"

v1:

We have several different boards with a multiplexer in the MDIO bus.
There is an MDIO bus controller connected to a switching device with
several child MDIO busses.

Everything is wired up using device tree bindings.

 1/3 - New of_mdio_find_bus() function used to help configuring the
       driver topology.

 2/3 - MDIO bus multiplexer framework.

 3/3 - A driver for a GPIO controlled multiplexer.


David Daney (3):
  netdev/of/phy: New function: of_mdio_find_bus().
  netdev/of/phy: Add MDIO bus multiplexer support.
  netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.

 .../devicetree/bindings/net/mdio-mux-gpio.txt      |  129 ++++++++++++++
 Documentation/devicetree/bindings/net/mdio-mux.txt |  136 +++++++++++++++
 drivers/net/phy/Kconfig                            |   17 ++
 drivers/net/phy/Makefile                           |    2 +
 drivers/net/phy/mdio-mux-gpio.c                    |  143 +++++++++++++++
 drivers/net/phy/mdio-mux.c                         |  182 ++++++++++++++++++++
 drivers/net/phy/mdio_bus.c                         |    3 +-
 drivers/of/of_mdio.c                               |   26 +++
 include/linux/mdio-mux.h                           |   18 ++
 include/linux/of_mdio.h                            |    2 +
 include/linux/phy.h                                |    1 +
 11 files changed, 658 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
 create mode 100644 drivers/net/phy/mdio-mux-gpio.c
 create mode 100644 drivers/net/phy/mdio-mux.c
 create mode 100644 include/linux/mdio-mux.h

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 1/3] netdev/of/phy: New function: of_mdio_find_bus().
  2011-09-27 23:26 ` David Daney
  (?)
@ 2011-09-27 23:26 ` David Daney
  2011-09-29 21:41   ` Grant Likely
  -1 siblings, 1 reply; 24+ messages in thread
From: David Daney @ 2011-09-27 23:26 UTC (permalink / raw)
  To: devicetree-discuss, grant.likely, linux-kernel, netdev, davem; +Cc: David Daney

Add of_mdio_find_bus() which allows an mii_bus to be located given its
associated the device tree node.

This is needed by the follow-on patch to add a driver for MDIO bus
multiplexers.

The of_mdiobus_register() function is modified so that the device tree
node is recorded in the mii_bus.  Then we can find it again by
iterating over all mdio_bus_class devices.

Signed-off-by: David Daney <david.daney@cavium.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: "David S. Miller" <davem@davemloft.net>
---
 drivers/net/phy/mdio_bus.c |    3 ++-
 drivers/of/of_mdio.c       |   26 ++++++++++++++++++++++++++
 include/linux/of_mdio.h    |    2 ++
 include/linux/phy.h        |    1 +
 4 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 6c58da2..227a060 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -70,10 +70,11 @@ static void mdiobus_release(struct device *d)
 	kfree(bus);
 }
 
-static struct class mdio_bus_class = {
+struct class mdio_bus_class = {
 	.name		= "mdio_bus",
 	.dev_release	= mdiobus_release,
 };
+EXPORT_SYMBOL(mdio_bus_class);
 
 /**
  * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index d35e300..7c28e8c 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -45,6 +45,8 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 		for (i=0; i<PHY_MAX_ADDR; i++)
 			mdio->irq[i] = PHY_POLL;
 
+	mdio->dev.of_node = np;
+
 	/* Register the MDIO bus */
 	rc = mdiobus_register(mdio);
 	if (rc)
@@ -189,3 +191,27 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
 	return IS_ERR(phy) ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect_fixed_link);
+
+/**
+ * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
+ * @mdio_np: Pointer to the mii_bus.
+ *
+ * Returns a pointer to the mii_bus, or NULL if none found.
+ *
+ * Because the association of a device_node and mii_bus is made via
+ * of_mdiobus_register(), the mii_bus cannot be found before it is
+ * registered with of_mdiobus_register().
+ *
+ */
+struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np)
+{
+	struct device *d;
+
+	if (!mdio_np)
+		return NULL;
+
+	d = class_find_device(&mdio_bus_class, NULL,  mdio_np, of_phy_match);
+
+	return d ? to_mii_bus(d) : NULL;
+}
+EXPORT_SYMBOL(of_mdio_find_bus);
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h
index 53b94e0..912c27a 100644
--- a/include/linux/of_mdio.h
+++ b/include/linux/of_mdio.h
@@ -22,4 +22,6 @@ extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
 					 void (*hndlr)(struct net_device *),
 					 phy_interface_t iface);
 
+extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
+
 #endif /* __LINUX_OF_MDIO_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 54fc413..e4c3844 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -528,4 +528,5 @@ int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
 
 extern struct bus_type mdio_bus_type;
+extern struct class mdio_bus_class;
 #endif /* __PHY_H */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
@ 2011-09-27 23:26   ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2011-09-27 23:26 UTC (permalink / raw)
  To: devicetree-discuss, grant.likely, linux-kernel, netdev, davem; +Cc: David Daney

This patch adds a somewhat generic framework for MDIO bus
multiplexers.  It is modeled on the I2C multiplexer.

The multiplexer is needed if there are multiple PHYs with the same
address connected to the same MDIO bus adepter, or if there is
insufficient electrical drive capability for all the connected PHY
devices.

Conceptually it could look something like this:

                   ------------------
                   | Control Signal |
                   --------+---------
                           |
 ---------------   --------+------
 | MDIO MASTER |---| Multiplexer |
 ---------------   --+-------+----
                     |       |
                     C       C
                     h       h
                     i       i
                     l       l
                     d       d
                     |       |
     ---------       A       B   ---------
     |       |       |       |   |       |
     | PHY@1 +-------+       +---+ PHY@1 |
     |       |       |       |   |       |
     ---------       |       |   ---------
     ---------       |       |   ---------
     |       |       |       |   |       |
     | PHY@2 +-------+       +---+ PHY@2 |
     |       |                   |       |
     ---------                   ---------

This framework configures the bus topology from device tree data.  The
mechanics of switching the multiplexer is left to device specific
drivers.

The follow-on patch contains a multiplexer driven by GPIO lines.

Signed-off-by: David Daney <david.daney@cavium.com>
Acked-by: Andy Fleming <afleming@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: "David S. Miller" <davem@davemloft.net>
---
 Documentation/devicetree/bindings/net/mdio-mux.txt |  136 +++++++++++++++
 drivers/net/phy/Kconfig                            |    8 +
 drivers/net/phy/Makefile                           |    1 +
 drivers/net/phy/mdio-mux.c                         |  182 ++++++++++++++++++++
 include/linux/mdio-mux.h                           |   18 ++
 5 files changed, 345 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
 create mode 100644 drivers/net/phy/mdio-mux.c
 create mode 100644 include/linux/mdio-mux.h

diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt b/Documentation/devicetree/bindings/net/mdio-mux.txt
new file mode 100644
index 0000000..5acba65
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
@@ -0,0 +1,136 @@
+Common MDIO bus multiplexer/switch properties.
+
+An MDIO bus multiplexer/switch will have several child busses that are
+numbered uniquely in a device dependent manner.  The nodes for an MDIO
+bus multiplexer/switch will have one child node for each child bus.
+
+Required properties:
+- mdio-parent-bus : phandle to the parent MDIO bus.
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Other properties specific to the multiplexer/switch hardware.
+
+Required properties for child nodes:
+- #address-cells = <1>;
+- #size-cells = <0>;
+- reg : The sub-bus number.
+
+
+Example :
+
+	/* The parent MDIO bus. */
+	smi1: mdio@1180000001900 {
+		compatible = "cavium,octeon-3860-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x11800 0x00001900 0x0 0x40>;
+	};
+
+	/*
+	   An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
+	   pair of GPIO lines.  Child busses 2 and 3 populated with 4
+	   PHYs each.
+	 */
+	mdio-mux {
+		compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
+		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+		mdio-parent-bus = <&smi1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy11: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy12: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy13: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy14: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+		};
+
+		mdio@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy21: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy22: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy23: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy24: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+		};
+	};
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index a702443..59848bc 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -119,6 +119,14 @@ config MDIO_GPIO
 	  To compile this driver as a module, choose M here: the module
 	  will be called mdio-gpio.
 
+config MDIO_BUS_MUX
+	tristate "Support for MDIO bus multiplexers"
+	help
+	  This module provides a driver framework for MDIO bus
+	  multiplexers which connect one of several child MDIO busses
+	  to a parent bus.  Switching between child busses is done by
+	  device specific drivers.
+
 config MDIO_OCTEON
 	tristate "Support for MDIO buses on Octeon SOCs"
 	depends on  CPU_CAVIUM_OCTEON
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 2333215..0c081d5 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_DP83640_PHY)	+= dp83640.o
 obj-$(CONFIG_STE10XP)		+= ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)	+= micrel.o
 obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
+obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
new file mode 100644
index 0000000..a940296
--- /dev/null
+++ b/drivers/net/phy/mdio-mux.c
@@ -0,0 +1,182 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Cavium Networks
+ */
+
+#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/phy.h>
+#include <linux/mdio-mux.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "MDIO bus multiplexer driver"
+
+struct mdio_mux_parent_bus {
+	struct mii_bus *mii_bus;
+	int current_child;
+	int parent_id;
+	void *switch_data;
+	int (*switch_fn)(int current_child, int desired_child, void *data);
+};
+
+struct mdio_mux_child_bus {
+	struct mii_bus *mii_bus;
+	struct mdio_mux_parent_bus *parent;
+	int bus_number;
+	int phy_irq[PHY_MAX_ADDR];
+};
+
+/*
+ * The parent bus' lock is used to order access to the switch_fn.
+ */
+static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
+{
+	struct mdio_mux_child_bus *cb = bus->priv;
+	struct mdio_mux_parent_bus *pb = cb->parent;
+	int r;
+
+	mutex_lock(&pb->mii_bus->mdio_lock);
+	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+	if (r)
+		goto out;
+
+	pb->current_child = cb->bus_number;
+
+	r = pb->mii_bus->read(pb->mii_bus, phy_id, regnum);
+out:
+	mutex_unlock(&pb->mii_bus->mdio_lock);
+
+	return r;
+}
+
+/*
+ * The parent bus' lock is used to order access to the switch_fn.
+ */
+static int mdio_mux_write(struct mii_bus *bus, int phy_id,
+			  int regnum, u16 val)
+{
+	struct mdio_mux_child_bus *cb = bus->priv;
+	struct mdio_mux_parent_bus *pb = cb->parent;
+
+	int r;
+
+	mutex_lock(&pb->mii_bus->mdio_lock);
+	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+	if (r)
+		goto out;
+
+	pb->current_child = cb->bus_number;
+
+	r = pb->mii_bus->write(pb->mii_bus, phy_id, regnum, val);
+out:
+	mutex_unlock(&pb->mii_bus->mdio_lock);
+
+	return r;
+}
+
+static int parent_count;
+
+int mdio_mux_probe(struct platform_device *pdev,
+		   int (*switch_fn)(int cur, int desired, void *data),
+		   void *data)
+{
+	struct device_node *parent_bus_node;
+	struct device_node *child_bus_node;
+	int r, n, ret_val;
+	struct mii_bus *parent_bus;
+	struct mdio_mux_parent_bus *pb;
+	struct mdio_mux_child_bus *cb;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	parent_bus_node = of_parse_phandle(pdev->dev.of_node, "mdio-parent-bus", 0);
+
+	if (!parent_bus_node)
+		return -ENODEV;
+
+	parent_bus = of_mdio_find_bus(parent_bus_node);
+
+	pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
+	if (pb == NULL) {
+		ret_val = -ENOMEM;
+		goto err_parent_bus;
+	}
+
+	pb->switch_data = data;
+	pb->switch_fn = switch_fn;
+	pb->current_child = -1;
+	pb->parent_id = parent_count++;
+	pb->mii_bus = parent_bus;
+
+	n = 0;
+	for_each_child_of_node(pdev->dev.of_node, child_bus_node) {
+		u32 v;
+
+		r = of_property_read_u32(child_bus_node, "reg", &v);
+		if (r == 0) {
+			cb = devm_kzalloc(&pdev->dev, sizeof(*cb), GFP_KERNEL);
+			if (cb == NULL)
+				break;
+			cb->bus_number = v;
+			cb->parent = pb;
+			cb->mii_bus = mdiobus_alloc();
+			cb->mii_bus->priv = cb;
+
+			cb->mii_bus->irq = cb->phy_irq;
+			cb->mii_bus->name = "mdio_mux";
+			snprintf(cb->mii_bus->id, MII_BUS_ID_SIZE, "%x.%x",
+				 pb->parent_id, v);
+			cb->mii_bus->parent = &pdev->dev;
+			cb->mii_bus->read = mdio_mux_read;
+			cb->mii_bus->write = mdio_mux_write;
+			r = of_mdiobus_register(cb->mii_bus, child_bus_node);
+			if (r) {
+				of_node_put(child_bus_node);
+				devm_kfree(&pdev->dev, cb);
+			} else {
+				n++;
+			}
+
+		} else {
+			of_node_put(child_bus_node);
+		}
+	}
+	if (n) {
+		dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
+		return 0;
+	}
+	ret_val = -ENOMEM;
+	devm_kfree(&pdev->dev, pb);
+err_parent_bus:
+	of_node_put(parent_bus_node);
+	return ret_val;
+}
+EXPORT_SYMBOL(mdio_mux_probe);
+
+static int __devexit mdio_mux_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int __init mdio_mux_mod_init(void)
+{
+	return 0;
+}
+module_init(mdio_mux_mod_init);
+
+static void __exit mdio_mux_mod_exit(void)
+{
+}
+module_exit(mdio_mux_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h
new file mode 100644
index 0000000..522992a
--- /dev/null
+++ b/include/linux/mdio-mux.h
@@ -0,0 +1,18 @@
+/*
+ * MDIO bus multiplexer framwork.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Cavium Networks
+ */
+#ifndef __LINUX_MDIO_MUX_H
+#define __LINUX_MDIO_MUX_H
+#include <linux/platform_device.h>
+
+int mdio_mux_probe(struct platform_device *pdev,
+		   int (*switch_fn) (int cur, int desired, void *data),
+		   void *data);
+
+#endif /* __LINUX_MDIO_MUX_H */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
@ 2011-09-27 23:26   ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2011-09-27 23:26 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

This patch adds a somewhat generic framework for MDIO bus
multiplexers.  It is modeled on the I2C multiplexer.

The multiplexer is needed if there are multiple PHYs with the same
address connected to the same MDIO bus adepter, or if there is
insufficient electrical drive capability for all the connected PHY
devices.

Conceptually it could look something like this:

                   ------------------
                   | Control Signal |
                   --------+---------
                           |
 ---------------   --------+------
 | MDIO MASTER |---| Multiplexer |
 ---------------   --+-------+----
                     |       |
                     C       C
                     h       h
                     i       i
                     l       l
                     d       d
                     |       |
     ---------       A       B   ---------
     |       |       |       |   |       |
     | PHY@1 +-------+       +---+ PHY@1 |
     |       |       |       |   |       |
     ---------       |       |   ---------
     ---------       |       |   ---------
     |       |       |       |   |       |
     | PHY@2 +-------+       +---+ PHY@2 |
     |       |                   |       |
     ---------                   ---------

This framework configures the bus topology from device tree data.  The
mechanics of switching the multiplexer is left to device specific
drivers.

The follow-on patch contains a multiplexer driven by GPIO lines.

Signed-off-by: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
Acked-by: Andy Fleming <afleming-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
---
 Documentation/devicetree/bindings/net/mdio-mux.txt |  136 +++++++++++++++
 drivers/net/phy/Kconfig                            |    8 +
 drivers/net/phy/Makefile                           |    1 +
 drivers/net/phy/mdio-mux.c                         |  182 ++++++++++++++++++++
 include/linux/mdio-mux.h                           |   18 ++
 5 files changed, 345 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
 create mode 100644 drivers/net/phy/mdio-mux.c
 create mode 100644 include/linux/mdio-mux.h

diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt b/Documentation/devicetree/bindings/net/mdio-mux.txt
new file mode 100644
index 0000000..5acba65
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
@@ -0,0 +1,136 @@
+Common MDIO bus multiplexer/switch properties.
+
+An MDIO bus multiplexer/switch will have several child busses that are
+numbered uniquely in a device dependent manner.  The nodes for an MDIO
+bus multiplexer/switch will have one child node for each child bus.
+
+Required properties:
+- mdio-parent-bus : phandle to the parent MDIO bus.
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Other properties specific to the multiplexer/switch hardware.
+
+Required properties for child nodes:
+- #address-cells = <1>;
+- #size-cells = <0>;
+- reg : The sub-bus number.
+
+
+Example :
+
+	/* The parent MDIO bus. */
+	smi1: mdio@1180000001900 {
+		compatible = "cavium,octeon-3860-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x11800 0x00001900 0x0 0x40>;
+	};
+
+	/*
+	   An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
+	   pair of GPIO lines.  Child busses 2 and 3 populated with 4
+	   PHYs each.
+	 */
+	mdio-mux {
+		compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
+		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+		mdio-parent-bus = <&smi1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy11: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy12: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy13: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy14: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+		};
+
+		mdio@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy21: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy22: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy23: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy24: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+		};
+	};
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index a702443..59848bc 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -119,6 +119,14 @@ config MDIO_GPIO
 	  To compile this driver as a module, choose M here: the module
 	  will be called mdio-gpio.
 
+config MDIO_BUS_MUX
+	tristate "Support for MDIO bus multiplexers"
+	help
+	  This module provides a driver framework for MDIO bus
+	  multiplexers which connect one of several child MDIO busses
+	  to a parent bus.  Switching between child busses is done by
+	  device specific drivers.
+
 config MDIO_OCTEON
 	tristate "Support for MDIO buses on Octeon SOCs"
 	depends on  CPU_CAVIUM_OCTEON
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 2333215..0c081d5 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_DP83640_PHY)	+= dp83640.o
 obj-$(CONFIG_STE10XP)		+= ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)	+= micrel.o
 obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
+obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
new file mode 100644
index 0000000..a940296
--- /dev/null
+++ b/drivers/net/phy/mdio-mux.c
@@ -0,0 +1,182 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Cavium Networks
+ */
+
+#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/phy.h>
+#include <linux/mdio-mux.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "MDIO bus multiplexer driver"
+
+struct mdio_mux_parent_bus {
+	struct mii_bus *mii_bus;
+	int current_child;
+	int parent_id;
+	void *switch_data;
+	int (*switch_fn)(int current_child, int desired_child, void *data);
+};
+
+struct mdio_mux_child_bus {
+	struct mii_bus *mii_bus;
+	struct mdio_mux_parent_bus *parent;
+	int bus_number;
+	int phy_irq[PHY_MAX_ADDR];
+};
+
+/*
+ * The parent bus' lock is used to order access to the switch_fn.
+ */
+static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
+{
+	struct mdio_mux_child_bus *cb = bus->priv;
+	struct mdio_mux_parent_bus *pb = cb->parent;
+	int r;
+
+	mutex_lock(&pb->mii_bus->mdio_lock);
+	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+	if (r)
+		goto out;
+
+	pb->current_child = cb->bus_number;
+
+	r = pb->mii_bus->read(pb->mii_bus, phy_id, regnum);
+out:
+	mutex_unlock(&pb->mii_bus->mdio_lock);
+
+	return r;
+}
+
+/*
+ * The parent bus' lock is used to order access to the switch_fn.
+ */
+static int mdio_mux_write(struct mii_bus *bus, int phy_id,
+			  int regnum, u16 val)
+{
+	struct mdio_mux_child_bus *cb = bus->priv;
+	struct mdio_mux_parent_bus *pb = cb->parent;
+
+	int r;
+
+	mutex_lock(&pb->mii_bus->mdio_lock);
+	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+	if (r)
+		goto out;
+
+	pb->current_child = cb->bus_number;
+
+	r = pb->mii_bus->write(pb->mii_bus, phy_id, regnum, val);
+out:
+	mutex_unlock(&pb->mii_bus->mdio_lock);
+
+	return r;
+}
+
+static int parent_count;
+
+int mdio_mux_probe(struct platform_device *pdev,
+		   int (*switch_fn)(int cur, int desired, void *data),
+		   void *data)
+{
+	struct device_node *parent_bus_node;
+	struct device_node *child_bus_node;
+	int r, n, ret_val;
+	struct mii_bus *parent_bus;
+	struct mdio_mux_parent_bus *pb;
+	struct mdio_mux_child_bus *cb;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	parent_bus_node = of_parse_phandle(pdev->dev.of_node, "mdio-parent-bus", 0);
+
+	if (!parent_bus_node)
+		return -ENODEV;
+
+	parent_bus = of_mdio_find_bus(parent_bus_node);
+
+	pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
+	if (pb == NULL) {
+		ret_val = -ENOMEM;
+		goto err_parent_bus;
+	}
+
+	pb->switch_data = data;
+	pb->switch_fn = switch_fn;
+	pb->current_child = -1;
+	pb->parent_id = parent_count++;
+	pb->mii_bus = parent_bus;
+
+	n = 0;
+	for_each_child_of_node(pdev->dev.of_node, child_bus_node) {
+		u32 v;
+
+		r = of_property_read_u32(child_bus_node, "reg", &v);
+		if (r == 0) {
+			cb = devm_kzalloc(&pdev->dev, sizeof(*cb), GFP_KERNEL);
+			if (cb == NULL)
+				break;
+			cb->bus_number = v;
+			cb->parent = pb;
+			cb->mii_bus = mdiobus_alloc();
+			cb->mii_bus->priv = cb;
+
+			cb->mii_bus->irq = cb->phy_irq;
+			cb->mii_bus->name = "mdio_mux";
+			snprintf(cb->mii_bus->id, MII_BUS_ID_SIZE, "%x.%x",
+				 pb->parent_id, v);
+			cb->mii_bus->parent = &pdev->dev;
+			cb->mii_bus->read = mdio_mux_read;
+			cb->mii_bus->write = mdio_mux_write;
+			r = of_mdiobus_register(cb->mii_bus, child_bus_node);
+			if (r) {
+				of_node_put(child_bus_node);
+				devm_kfree(&pdev->dev, cb);
+			} else {
+				n++;
+			}
+
+		} else {
+			of_node_put(child_bus_node);
+		}
+	}
+	if (n) {
+		dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
+		return 0;
+	}
+	ret_val = -ENOMEM;
+	devm_kfree(&pdev->dev, pb);
+err_parent_bus:
+	of_node_put(parent_bus_node);
+	return ret_val;
+}
+EXPORT_SYMBOL(mdio_mux_probe);
+
+static int __devexit mdio_mux_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int __init mdio_mux_mod_init(void)
+{
+	return 0;
+}
+module_init(mdio_mux_mod_init);
+
+static void __exit mdio_mux_mod_exit(void)
+{
+}
+module_exit(mdio_mux_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h
new file mode 100644
index 0000000..522992a
--- /dev/null
+++ b/include/linux/mdio-mux.h
@@ -0,0 +1,18 @@
+/*
+ * MDIO bus multiplexer framwork.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Cavium Networks
+ */
+#ifndef __LINUX_MDIO_MUX_H
+#define __LINUX_MDIO_MUX_H
+#include <linux/platform_device.h>
+
+int mdio_mux_probe(struct platform_device *pdev,
+		   int (*switch_fn) (int cur, int desired, void *data),
+		   void *data);
+
+#endif /* __LINUX_MDIO_MUX_H */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 3/3] netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.
@ 2011-09-27 23:26   ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2011-09-27 23:26 UTC (permalink / raw)
  To: devicetree-discuss, grant.likely, linux-kernel, netdev, davem; +Cc: David Daney

The GPIO pins select which sub bus is connected to the master.

Initially tested with an sn74cbtlv3253 switch device wired into the
MDIO bus.

Signed-off-by: David Daney <david.daney@cavium.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: "David S. Miller" <davem@davemloft.net>
---
 .../devicetree/bindings/net/mdio-mux-gpio.txt      |  129 ++++++++++++++++++
 drivers/net/phy/Kconfig                            |    9 ++
 drivers/net/phy/Makefile                           |    1 +
 drivers/net/phy/mdio-mux-gpio.c                    |  143 ++++++++++++++++++++
 4 files changed, 282 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
 create mode 100644 drivers/net/phy/mdio-mux-gpio.c

diff --git a/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
new file mode 100644
index 0000000..8d0f945
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
@@ -0,0 +1,129 @@
+Properties for an MDIO bus multiplexer/switch controlled by GPIO pins.
+
+This is a special case of a MDIO bus multiplexer.  One or more GPIO
+lines are used to control which child bus is connected.
+
+Required properties in addition to the generic multiplexer properties:
+
+- compatible : Should define the compatible device type for the
+               multiplexer.  Currently "cavium,mdio-mux-sn74cbtlv3253"
+               is defined, others are possible.
+- gpios : GPIO specifiers for each GPIO line.  One or more must be specified.
+
+
+Example :
+
+	/* The parent MDIO bus. */
+	smi1: mdio@1180000001900 {
+		compatible = "cavium,octeon-3860-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x11800 0x00001900 0x0 0x40>;
+	};
+
+	/*
+	   An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
+	   pair of GPIO lines.  Child busses 2 and 3 populated with 4
+	   PHYs each.
+	 */
+	mdio-mux {
+		compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
+		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+		mdio-parent-bus = <&smi1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy11: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy12: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy13: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy14: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+		};
+
+		mdio@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy21: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy22: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy23: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy24: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+		};
+	};
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 59848bc..59b3b17 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -127,6 +127,15 @@ config MDIO_BUS_MUX
 	  to a parent bus.  Switching between child busses is done by
 	  device specific drivers.
 
+config MDIO_BUS_MUX_GPIO
+	tristate "Support for GPIO controlled MDIO bus multiplexers"
+	depends on MDIO_BUS_MUX && GENERIC_GPIO
+	help
+	  This module provides a driver for MDIO bus multiplexers that
+	  are controlled via GPIO lines.  The multiplexer connects one of
+	  several child MDIO busses to a parent bus.  Child bus
+	  selection is under the control of GPIO lines.
+
 config MDIO_OCTEON
 	tristate "Support for MDIO buses on Octeon SOCs"
 	depends on  CPU_CAVIUM_OCTEON
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 0c081d5..d1a1927 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_STE10XP)		+= ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)	+= micrel.o
 obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
 obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
+obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
new file mode 100644
index 0000000..3cdad35
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -0,0 +1,143 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Cavium Networks
+ */
+
+#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/phy.h>
+#include <linux/mdio-mux.h>
+#include <linux/of_gpio.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
+
+#define MDIO_MUX_GPIO_MAX_BITS 8
+
+struct mdio_mux_gpio_state {
+	int gpio[MDIO_MUX_GPIO_MAX_BITS];
+	unsigned int num_gpios;
+};
+
+static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
+				   void *data)
+{
+	int change;
+	unsigned int n;
+	struct mdio_mux_gpio_state *s = data;
+
+	if (current_child == desired_child)
+		return 0;
+
+	change = current_child == -1 ? -1 : current_child ^ desired_child;
+
+	for (n = 0; n < s->num_gpios; n++) {
+		if (change & 1)
+			gpio_set_value_cansleep(s->gpio[n],
+						(desired_child & 1) != 0);
+		change >>= 1;
+		desired_child >>= 1;
+	}
+
+	return 0;
+}
+
+static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
+{
+	enum of_gpio_flags f;
+	struct mdio_mux_gpio_state *s;
+	unsigned int num_gpios;
+	unsigned int n;
+	int r;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	num_gpios = of_gpio_count(pdev->dev.of_node);
+	if (num_gpios == 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS)
+		return -ENODEV;
+
+	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+
+	s->num_gpios = num_gpios;
+
+	for (n = 0; n < num_gpios; ) {
+		int gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+						   "gpios", n, &f);
+		s->gpio[n] = gpio;
+		if (gpio < 0) {
+			r = -ENODEV;
+			goto err;
+		}
+
+		n++;
+
+		r = gpio_request(gpio, "mdio_mux_gpio");
+		if (r)
+			goto err;
+
+		r = gpio_direction_output(gpio, 0);
+		if (r)
+			goto err;
+	}
+
+	r = mdio_mux_probe(pdev, mdio_mux_gpio_switch_fn, s);
+
+	if (r == 0)
+		return 0;
+err:
+	while (n) {
+		n--;
+		gpio_free(s->gpio[n]);
+	}
+	devm_kfree(&pdev->dev, s);
+	return r;
+}
+
+static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id mdio_mux_gpio_match[] = {
+	{
+		.compatible = "cavium,mdio-mux-sn74cbtlv3253",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_match);
+
+static struct platform_driver mdio_mux_gpio_driver = {
+	.driver = {
+		.name		= "mdio-mux-gpio",
+		.owner		= THIS_MODULE,
+		.of_match_table = mdio_mux_gpio_match,
+	},
+	.probe		= mdio_mux_gpio_probe,
+	.remove		= __devexit_p(mdio_mux_gpio_remove),
+};
+
+static int __init mdio_mux_gpio_mod_init(void)
+{
+	return platform_driver_register(&mdio_mux_gpio_driver);
+}
+late_initcall(mdio_mux_gpio_mod_init);
+
+static void __exit mdio_mux_gpio_mod_exit(void)
+{
+	platform_driver_unregister(&mdio_mux_gpio_driver);
+}
+module_exit(mdio_mux_gpio_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 3/3] netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.
@ 2011-09-27 23:26   ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2011-09-27 23:26 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

The GPIO pins select which sub bus is connected to the master.

Initially tested with an sn74cbtlv3253 switch device wired into the
MDIO bus.

Signed-off-by: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
---
 .../devicetree/bindings/net/mdio-mux-gpio.txt      |  129 ++++++++++++++++++
 drivers/net/phy/Kconfig                            |    9 ++
 drivers/net/phy/Makefile                           |    1 +
 drivers/net/phy/mdio-mux-gpio.c                    |  143 ++++++++++++++++++++
 4 files changed, 282 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
 create mode 100644 drivers/net/phy/mdio-mux-gpio.c

diff --git a/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
new file mode 100644
index 0000000..8d0f945
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
@@ -0,0 +1,129 @@
+Properties for an MDIO bus multiplexer/switch controlled by GPIO pins.
+
+This is a special case of a MDIO bus multiplexer.  One or more GPIO
+lines are used to control which child bus is connected.
+
+Required properties in addition to the generic multiplexer properties:
+
+- compatible : Should define the compatible device type for the
+               multiplexer.  Currently "cavium,mdio-mux-sn74cbtlv3253"
+               is defined, others are possible.
+- gpios : GPIO specifiers for each GPIO line.  One or more must be specified.
+
+
+Example :
+
+	/* The parent MDIO bus. */
+	smi1: mdio@1180000001900 {
+		compatible = "cavium,octeon-3860-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x11800 0x00001900 0x0 0x40>;
+	};
+
+	/*
+	   An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
+	   pair of GPIO lines.  Child busses 2 and 3 populated with 4
+	   PHYs each.
+	 */
+	mdio-mux {
+		compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
+		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+		mdio-parent-bus = <&smi1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy11: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy12: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy13: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy14: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+		};
+
+		mdio@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy21: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy22: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy23: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy24: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+		};
+	};
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 59848bc..59b3b17 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -127,6 +127,15 @@ config MDIO_BUS_MUX
 	  to a parent bus.  Switching between child busses is done by
 	  device specific drivers.
 
+config MDIO_BUS_MUX_GPIO
+	tristate "Support for GPIO controlled MDIO bus multiplexers"
+	depends on MDIO_BUS_MUX && GENERIC_GPIO
+	help
+	  This module provides a driver for MDIO bus multiplexers that
+	  are controlled via GPIO lines.  The multiplexer connects one of
+	  several child MDIO busses to a parent bus.  Child bus
+	  selection is under the control of GPIO lines.
+
 config MDIO_OCTEON
 	tristate "Support for MDIO buses on Octeon SOCs"
 	depends on  CPU_CAVIUM_OCTEON
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 0c081d5..d1a1927 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_STE10XP)		+= ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)	+= micrel.o
 obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
 obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
+obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
new file mode 100644
index 0000000..3cdad35
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -0,0 +1,143 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011 Cavium Networks
+ */
+
+#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/phy.h>
+#include <linux/mdio-mux.h>
+#include <linux/of_gpio.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
+
+#define MDIO_MUX_GPIO_MAX_BITS 8
+
+struct mdio_mux_gpio_state {
+	int gpio[MDIO_MUX_GPIO_MAX_BITS];
+	unsigned int num_gpios;
+};
+
+static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
+				   void *data)
+{
+	int change;
+	unsigned int n;
+	struct mdio_mux_gpio_state *s = data;
+
+	if (current_child == desired_child)
+		return 0;
+
+	change = current_child == -1 ? -1 : current_child ^ desired_child;
+
+	for (n = 0; n < s->num_gpios; n++) {
+		if (change & 1)
+			gpio_set_value_cansleep(s->gpio[n],
+						(desired_child & 1) != 0);
+		change >>= 1;
+		desired_child >>= 1;
+	}
+
+	return 0;
+}
+
+static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
+{
+	enum of_gpio_flags f;
+	struct mdio_mux_gpio_state *s;
+	unsigned int num_gpios;
+	unsigned int n;
+	int r;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	num_gpios = of_gpio_count(pdev->dev.of_node);
+	if (num_gpios == 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS)
+		return -ENODEV;
+
+	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+
+	s->num_gpios = num_gpios;
+
+	for (n = 0; n < num_gpios; ) {
+		int gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+						   "gpios", n, &f);
+		s->gpio[n] = gpio;
+		if (gpio < 0) {
+			r = -ENODEV;
+			goto err;
+		}
+
+		n++;
+
+		r = gpio_request(gpio, "mdio_mux_gpio");
+		if (r)
+			goto err;
+
+		r = gpio_direction_output(gpio, 0);
+		if (r)
+			goto err;
+	}
+
+	r = mdio_mux_probe(pdev, mdio_mux_gpio_switch_fn, s);
+
+	if (r == 0)
+		return 0;
+err:
+	while (n) {
+		n--;
+		gpio_free(s->gpio[n]);
+	}
+	devm_kfree(&pdev->dev, s);
+	return r;
+}
+
+static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id mdio_mux_gpio_match[] = {
+	{
+		.compatible = "cavium,mdio-mux-sn74cbtlv3253",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_match);
+
+static struct platform_driver mdio_mux_gpio_driver = {
+	.driver = {
+		.name		= "mdio-mux-gpio",
+		.owner		= THIS_MODULE,
+		.of_match_table = mdio_mux_gpio_match,
+	},
+	.probe		= mdio_mux_gpio_probe,
+	.remove		= __devexit_p(mdio_mux_gpio_remove),
+};
+
+static int __init mdio_mux_gpio_mod_init(void)
+{
+	return platform_driver_register(&mdio_mux_gpio_driver);
+}
+late_initcall(mdio_mux_gpio_mod_init);
+
+static void __exit mdio_mux_gpio_mod_exit(void)
+{
+	platform_driver_unregister(&mdio_mux_gpio_driver);
+}
+module_exit(mdio_mux_gpio_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
  2011-09-27 23:26   ` David Daney
@ 2011-09-28  7:25     ` Michał Mirosław
  -1 siblings, 0 replies; 24+ messages in thread
From: Michał Mirosław @ 2011-09-28  7:25 UTC (permalink / raw)
  To: David Daney; +Cc: devicetree-discuss, grant.likely, linux-kernel, netdev, davem

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 1184 bytes --]

2011/9/28 David Daney <david.daney@cavium.com>:
[...]
> +Example :
> +
> +       /* The parent MDIO bus. */
> +       smi1: mdio@1180000001900 {
> +               compatible = "cavium,octeon-3860-mdio";
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               reg = <0x11800 0x00001900 0x0 0x40>;
> +       };
> +
> +       /*
> +          An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
> +          pair of GPIO lines.  Child busses 2 and 3 populated with 4
> +          PHYs each.
> +        */
> +       mdio-mux {
> +               compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
> +               gpios = <&gpio1 3 0>, <&gpio1 4 0>;
> +               mdio-parent-bus = <&smi1>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;

This should probably have 'compatible = "nxp,sn74cbtlv3253";' here.

Best Regards,
Michał Mirosław
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
@ 2011-09-28  7:25     ` Michał Mirosław
  0 siblings, 0 replies; 24+ messages in thread
From: Michał Mirosław @ 2011-09-28  7:25 UTC (permalink / raw)
  To: David Daney; +Cc: devicetree-discuss, grant.likely, linux-kernel, netdev, davem

2011/9/28 David Daney <david.daney@cavium.com>:
[...]
> +Example :
> +
> +       /* The parent MDIO bus. */
> +       smi1: mdio@1180000001900 {
> +               compatible = "cavium,octeon-3860-mdio";
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               reg = <0x11800 0x00001900 0x0 0x40>;
> +       };
> +
> +       /*
> +          An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
> +          pair of GPIO lines.  Child busses 2 and 3 populated with 4
> +          PHYs each.
> +        */
> +       mdio-mux {
> +               compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
> +               gpios = <&gpio1 3 0>, <&gpio1 4 0>;
> +               mdio-parent-bus = <&smi1>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;

This should probably have 'compatible = "nxp,sn74cbtlv3253";' here.

Best Regards,
Michał Mirosław

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
  2011-09-28  7:25     ` Michał Mirosław
  (?)
@ 2011-09-28 16:51     ` David Daney
  2011-09-28 17:32       ` Michał Mirosław
  -1 siblings, 1 reply; 24+ messages in thread
From: David Daney @ 2011-09-28 16:51 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: devicetree-discuss, grant.likely, linux-kernel, netdev, davem

On 09/28/2011 12:25 AM, Michał Mirosław wrote:
> 2011/9/28 David Daney<david.daney@cavium.com>:
> [...]
>> +Example :
>> +
>> +       /* The parent MDIO bus. */
>> +       smi1: mdio@1180000001900 {
>> +               compatible = "cavium,octeon-3860-mdio";
>> +               #address-cells =<1>;
>> +               #size-cells =<0>;
>> +               reg =<0x11800 0x00001900 0x0 0x40>;
>> +       };
>> +
>> +       /*
>> +          An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
>> +          pair of GPIO lines.  Child busses 2 and 3 populated with 4
>> +          PHYs each.
>> +        */
>> +       mdio-mux {
>> +               compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
>> +               gpios =<&gpio1 3 0>,<&gpio1 4 0>;
>> +               mdio-parent-bus =<&smi1>;
>> +               #address-cells =<1>;
>> +               #size-cells =<0>;
>
> This should probably have 'compatible = "nxp,sn74cbtlv3253";' here.
>

No, the sn74cbtlv3253 is a general purpose part that could be used to 
multiplex anything (I2C, SPI, random analog signals, etc.).  Only when 
it is in the "cavium,mdio-mux-sn74cbtlv3253" configuration is it an MDIO 
bus multiplexer.

David Daney.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
  2011-09-28 16:51     ` David Daney
@ 2011-09-28 17:32       ` Michał Mirosław
  2011-09-28 17:42         ` David Daney
  0 siblings, 1 reply; 24+ messages in thread
From: Michał Mirosław @ 2011-09-28 17:32 UTC (permalink / raw)
  To: David Daney; +Cc: devicetree-discuss, grant.likely, linux-kernel, netdev, davem

W dniu 28 września 2011 18:51 użytkownik David Daney
<david.daney@cavium.com> napisał:
> On 09/28/2011 12:25 AM, Michał Mirosław wrote:
>>
>> 2011/9/28 David Daney<david.daney@cavium.com>:
>> [...]
>>>
>>> +Example :
>>> +
>>> +       /* The parent MDIO bus. */
>>> +       smi1: mdio@1180000001900 {
>>> +               compatible = "cavium,octeon-3860-mdio";
>>> +               #address-cells =<1>;
>>> +               #size-cells =<0>;
>>> +               reg =<0x11800 0x00001900 0x0 0x40>;
>>> +       };
>>> +
>>> +       /*
>>> +          An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
>>> +          pair of GPIO lines.  Child busses 2 and 3 populated with 4
>>> +          PHYs each.
>>> +        */
>>> +       mdio-mux {
>>> +               compatible = "cavium,mdio-mux-sn74cbtlv3253",
>>> "cavium,mdio-mux";
>>> +               gpios =<&gpio1 3 0>,<&gpio1 4 0>;
>>> +               mdio-parent-bus =<&smi1>;
>>> +               #address-cells =<1>;
>>> +               #size-cells =<0>;
>>
>> This should probably have 'compatible = "nxp,sn74cbtlv3253";' here.
>>
>
> No, the sn74cbtlv3253 is a general purpose part that could be used to
> multiplex anything (I2C, SPI, random analog signals, etc.).  Only when it is
> in the "cavium,mdio-mux-sn74cbtlv3253" configuration is it an MDIO bus
> multiplexer.

This should use some generic name then. 'mdio-mux-gpio' or something.
There's no point in introducing chip's model for a gate-like discrete
device.

Best Regards,
Michał Mirosław

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
  2011-09-28 17:32       ` Michał Mirosław
@ 2011-09-28 17:42         ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2011-09-28 17:42 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: devicetree-discuss, grant.likely, linux-kernel, netdev, davem

On 09/28/2011 10:32 AM, Michał Mirosław wrote:
> W dniu 28 września 2011 18:51 użytkownik David Daney
> <david.daney@cavium.com>  napisał:
>> On 09/28/2011 12:25 AM, Michał Mirosław wrote:
>>>
>>> 2011/9/28 David Daney<david.daney@cavium.com>:
>>> [...]
>>>>
>>>> +Example :
>>>> +
>>>> +       /* The parent MDIO bus. */
>>>> +       smi1: mdio@1180000001900 {
>>>> +               compatible = "cavium,octeon-3860-mdio";
>>>> +               #address-cells =<1>;
>>>> +               #size-cells =<0>;
>>>> +               reg =<0x11800 0x00001900 0x0 0x40>;
>>>> +       };
>>>> +
>>>> +       /*
>>>> +          An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
>>>> +          pair of GPIO lines.  Child busses 2 and 3 populated with 4
>>>> +          PHYs each.
>>>> +        */
>>>> +       mdio-mux {
>>>> +               compatible = "cavium,mdio-mux-sn74cbtlv3253",
>>>> "cavium,mdio-mux";
>>>> +               gpios =<&gpio1 3 0>,<&gpio1 4 0>;
>>>> +               mdio-parent-bus =<&smi1>;
>>>> +               #address-cells =<1>;
>>>> +               #size-cells =<0>;
>>>
>>> This should probably have 'compatible = "nxp,sn74cbtlv3253";' here.
>>>
>>
>> No, the sn74cbtlv3253 is a general purpose part that could be used to
>> multiplex anything (I2C, SPI, random analog signals, etc.).  Only when it is
>> in the "cavium,mdio-mux-sn74cbtlv3253" configuration is it an MDIO bus
>> multiplexer.
>
> This should use some generic name then. 'mdio-mux-gpio' or something.
> There's no point in introducing chip's model for a gate-like discrete
> device.

That could be.  We could define an "mdio-mux-gpio" as something that 
selects the child bus based on the binary encoded value presented on the 
GPIO lines.

I will regenerate the patch set with this in mind.  Note that the only 
part of this patch that will change is this mdio-mux.txt file, no actual 
code is affected.  In patch 3/3 I will add "mdio-mux-gpio" to the 
.of_match_table.

Thanks,
David Daney

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
  2011-09-27 23:26 ` David Daney
                   ` (3 preceding siblings ...)
  (?)
@ 2011-09-29 20:31 ` David Miller
  2011-09-30  0:32   ` Grant Likely
  -1 siblings, 1 reply; 24+ messages in thread
From: David Miller @ 2011-09-29 20:31 UTC (permalink / raw)
  To: david.daney; +Cc: devicetree-discuss, grant.likely, linux-kernel, netdev

From: David Daney <david.daney@cavium.com>
Date: Tue, 27 Sep 2011 16:26:52 -0700

> v2: Update bindings to use "reg" and "mdio-parent-bus" insutead of
>     "cell-index" and "parent-bus"

Grant, when the final version of this patch set is ready how do
you want to handle merging it in?

I think it would be safe to merge this via your tree, since the
changes made to existing network driver files are rather trivial and
thus merge conflict friendly.

Actually, I feel like we've discussed this before :-)

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 1/3] netdev/of/phy: New function: of_mdio_find_bus().
  2011-09-27 23:26 ` [PATCH v2 1/3] netdev/of/phy: New function: of_mdio_find_bus() David Daney
@ 2011-09-29 21:41   ` Grant Likely
  0 siblings, 0 replies; 24+ messages in thread
From: Grant Likely @ 2011-09-29 21:41 UTC (permalink / raw)
  To: David Daney; +Cc: devicetree-discuss, linux-kernel, netdev, davem

On Tue, Sep 27, 2011 at 04:26:53PM -0700, David Daney wrote:
> Add of_mdio_find_bus() which allows an mii_bus to be located given its
> associated the device tree node.
> 
> This is needed by the follow-on patch to add a driver for MDIO bus
> multiplexers.
> 
> The of_mdiobus_register() function is modified so that the device tree
> node is recorded in the mii_bus.  Then we can find it again by
> iterating over all mdio_bus_class devices.
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: "David S. Miller" <davem@davemloft.net>
> ---
>  drivers/net/phy/mdio_bus.c |    3 ++-
>  drivers/of/of_mdio.c       |   26 ++++++++++++++++++++++++++
>  include/linux/of_mdio.h    |    2 ++
>  include/linux/phy.h        |    1 +
>  4 files changed, 31 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
> index 6c58da2..227a060 100644
> --- a/drivers/net/phy/mdio_bus.c
> +++ b/drivers/net/phy/mdio_bus.c
> @@ -70,10 +70,11 @@ static void mdiobus_release(struct device *d)
>  	kfree(bus);
>  }
>  
> -static struct class mdio_bus_class = {
> +struct class mdio_bus_class = {
>  	.name		= "mdio_bus",
>  	.dev_release	= mdiobus_release,
>  };
> +EXPORT_SYMBOL(mdio_bus_class);

Instead of exporting this, move the iterator into this file. Assuming
Andy and David are okay with it, I don't see any reason to continue to
keep the MDIO DT support outside of drivers/net/phy.

Bonus points if you craft a patch to move the existing MDIO DT
support code.

Otherwise, the patch looks good.

g.

>  
>  /**
>   * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
> diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
> index d35e300..7c28e8c 100644
> --- a/drivers/of/of_mdio.c
> +++ b/drivers/of/of_mdio.c
> @@ -45,6 +45,8 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
>  		for (i=0; i<PHY_MAX_ADDR; i++)
>  			mdio->irq[i] = PHY_POLL;
>  
> +	mdio->dev.of_node = np;
> +
>  	/* Register the MDIO bus */
>  	rc = mdiobus_register(mdio);
>  	if (rc)
> @@ -189,3 +191,27 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
>  	return IS_ERR(phy) ? NULL : phy;
>  }
>  EXPORT_SYMBOL(of_phy_connect_fixed_link);
> +
> +/**
> + * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
> + * @mdio_np: Pointer to the mii_bus.
> + *
> + * Returns a pointer to the mii_bus, or NULL if none found.
> + *
> + * Because the association of a device_node and mii_bus is made via
> + * of_mdiobus_register(), the mii_bus cannot be found before it is
> + * registered with of_mdiobus_register().
> + *
> + */
> +struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np)
> +{
> +	struct device *d;
> +
> +	if (!mdio_np)
> +		return NULL;
> +
> +	d = class_find_device(&mdio_bus_class, NULL,  mdio_np, of_phy_match);
> +
> +	return d ? to_mii_bus(d) : NULL;
> +}
> +EXPORT_SYMBOL(of_mdio_find_bus);
> diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h
> index 53b94e0..912c27a 100644
> --- a/include/linux/of_mdio.h
> +++ b/include/linux/of_mdio.h
> @@ -22,4 +22,6 @@ extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
>  					 void (*hndlr)(struct net_device *),
>  					 phy_interface_t iface);
>  
> +extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
> +
>  #endif /* __LINUX_OF_MDIO_H */
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index 54fc413..e4c3844 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -528,4 +528,5 @@ int __init mdio_bus_init(void);
>  void mdio_bus_exit(void);
>  
>  extern struct bus_type mdio_bus_type;
> +extern struct class mdio_bus_class;
>  #endif /* __PHY_H */
> -- 
> 1.7.2.3
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
  2011-09-27 23:26   ` David Daney
  (?)
  (?)
@ 2011-09-29 21:56   ` Grant Likely
  -1 siblings, 0 replies; 24+ messages in thread
From: Grant Likely @ 2011-09-29 21:56 UTC (permalink / raw)
  To: David Daney; +Cc: devicetree-discuss, linux-kernel, netdev, davem

On Tue, Sep 27, 2011 at 04:26:54PM -0700, David Daney wrote:
> This patch adds a somewhat generic framework for MDIO bus
> multiplexers.  It is modeled on the I2C multiplexer.
> 
> The multiplexer is needed if there are multiple PHYs with the same
> address connected to the same MDIO bus adepter, or if there is
> insufficient electrical drive capability for all the connected PHY
> devices.
> 
> Conceptually it could look something like this:
> 
>                    ------------------
>                    | Control Signal |
>                    --------+---------
>                            |
>  ---------------   --------+------
>  | MDIO MASTER |---| Multiplexer |
>  ---------------   --+-------+----
>                      |       |
>                      C       C
>                      h       h
>                      i       i
>                      l       l
>                      d       d
>                      |       |
>      ---------       A       B   ---------
>      |       |       |       |   |       |
>      | PHY@1 +-------+       +---+ PHY@1 |
>      |       |       |       |   |       |
>      ---------       |       |   ---------
>      ---------       |       |   ---------
>      |       |       |       |   |       |
>      | PHY@2 +-------+       +---+ PHY@2 |
>      |       |                   |       |
>      ---------                   ---------
> 
> This framework configures the bus topology from device tree data.  The
> mechanics of switching the multiplexer is left to device specific
> drivers.
> 
> The follow-on patch contains a multiplexer driven by GPIO lines.
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Acked-by: Andy Fleming <afleming@freescale.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: "David S. Miller" <davem@davemloft.net>
> ---
>  Documentation/devicetree/bindings/net/mdio-mux.txt |  136 +++++++++++++++
>  drivers/net/phy/Kconfig                            |    8 +
>  drivers/net/phy/Makefile                           |    1 +
>  drivers/net/phy/mdio-mux.c                         |  182 ++++++++++++++++++++
>  include/linux/mdio-mux.h                           |   18 ++
>  5 files changed, 345 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
>  create mode 100644 drivers/net/phy/mdio-mux.c
>  create mode 100644 include/linux/mdio-mux.h
> 
> diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt b/Documentation/devicetree/bindings/net/mdio-mux.txt
> new file mode 100644
> index 0000000..5acba65
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
> @@ -0,0 +1,136 @@
> +Common MDIO bus multiplexer/switch properties.
> +
> +An MDIO bus multiplexer/switch will have several child busses that are
> +numbered uniquely in a device dependent manner.  The nodes for an MDIO
> +bus multiplexer/switch will have one child node for each child bus.
> +
> +Required properties:
> +- mdio-parent-bus : phandle to the parent MDIO bus.
> +- #address-cells = <1>;
> +- #size-cells = <0>;
> +
> +Optional properties:
> +- Other properties specific to the multiplexer/switch hardware.
> +
> +Required properties for child nodes:
> +- #address-cells = <1>;
> +- #size-cells = <0>;
> +- reg : The sub-bus number.
> +
> +
> +Example :
> +
> +	/* The parent MDIO bus. */
> +	smi1: mdio@1180000001900 {
> +		compatible = "cavium,octeon-3860-mdio";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		reg = <0x11800 0x00001900 0x0 0x40>;
> +	};
> +
> +	/*
> +	   An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
> +	   pair of GPIO lines.  Child busses 2 and 3 populated with 4
> +	   PHYs each.
> +	 */
> +	mdio-mux {
> +		compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
> +		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
> +		mdio-parent-bus = <&smi1>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		mdio@2 {
> +			reg = <2>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			phy11: ethernet-phy@1 {
> +				reg = <1>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy12: ethernet-phy@2 {
> +				reg = <2>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy13: ethernet-phy@3 {
> +				reg = <3>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy14: ethernet-phy@4 {
> +				reg = <4>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +		};
> +
> +		mdio@3 {
> +			reg = <3>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			phy21: ethernet-phy@1 {
> +				reg = <1>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy22: ethernet-phy@2 {
> +				reg = <2>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy23: ethernet-phy@3 {
> +				reg = <3>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy24: ethernet-phy@4 {
> +				reg = <4>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +		};
> +	};
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index a702443..59848bc 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -119,6 +119,14 @@ config MDIO_GPIO
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called mdio-gpio.
>  
> +config MDIO_BUS_MUX
> +	tristate "Support for MDIO bus multiplexers"
> +	help
> +	  This module provides a driver framework for MDIO bus
> +	  multiplexers which connect one of several child MDIO busses
> +	  to a parent bus.  Switching between child busses is done by
> +	  device specific drivers.
> +

Don't make this a user visible option.  Make the bus driver select it.

>  config MDIO_OCTEON
>  	tristate "Support for MDIO buses on Octeon SOCs"
>  	depends on  CPU_CAVIUM_OCTEON
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index 2333215..0c081d5 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -23,3 +23,4 @@ obj-$(CONFIG_DP83640_PHY)	+= dp83640.o
>  obj-$(CONFIG_STE10XP)		+= ste10Xp.o
>  obj-$(CONFIG_MICREL_PHY)	+= micrel.o
>  obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
> +obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
> diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
> new file mode 100644
> index 0000000..a940296
> --- /dev/null
> +++ b/drivers/net/phy/mdio-mux.c
> @@ -0,0 +1,182 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2011 Cavium Networks
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/of_mdio.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/gfp.h>
> +#include <linux/phy.h>
> +#include <linux/mdio-mux.h>
> +
> +#define DRV_VERSION "1.0"
> +#define DRV_DESCRIPTION "MDIO bus multiplexer driver"
> +
> +struct mdio_mux_parent_bus {
> +	struct mii_bus *mii_bus;
> +	int current_child;
> +	int parent_id;
> +	void *switch_data;
> +	int (*switch_fn)(int current_child, int desired_child, void *data);
> +};
> +
> +struct mdio_mux_child_bus {
> +	struct mii_bus *mii_bus;
> +	struct mdio_mux_parent_bus *parent;
> +	int bus_number;
> +	int phy_irq[PHY_MAX_ADDR];
> +};
> +
> +/*
> + * The parent bus' lock is used to order access to the switch_fn.
> + */
> +static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
> +{
> +	struct mdio_mux_child_bus *cb = bus->priv;
> +	struct mdio_mux_parent_bus *pb = cb->parent;
> +	int r;
> +
> +	mutex_lock(&pb->mii_bus->mdio_lock);
> +	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
> +	if (r)
> +		goto out;
> +
> +	pb->current_child = cb->bus_number;
> +
> +	r = pb->mii_bus->read(pb->mii_bus, phy_id, regnum);
> +out:
> +	mutex_unlock(&pb->mii_bus->mdio_lock);
> +
> +	return r;
> +}
> +
> +/*
> + * The parent bus' lock is used to order access to the switch_fn.
> + */
> +static int mdio_mux_write(struct mii_bus *bus, int phy_id,
> +			  int regnum, u16 val)
> +{
> +	struct mdio_mux_child_bus *cb = bus->priv;
> +	struct mdio_mux_parent_bus *pb = cb->parent;
> +
> +	int r;
> +
> +	mutex_lock(&pb->mii_bus->mdio_lock);
> +	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
> +	if (r)
> +		goto out;
> +
> +	pb->current_child = cb->bus_number;
> +
> +	r = pb->mii_bus->write(pb->mii_bus, phy_id, regnum, val);
> +out:
> +	mutex_unlock(&pb->mii_bus->mdio_lock);
> +
> +	return r;
> +}
> +
> +static int parent_count;
> +
> +int mdio_mux_probe(struct platform_device *pdev,
> +		   int (*switch_fn)(int cur, int desired, void *data),
> +		   void *data)
> +{

Don't call this probe.  Probe typically means top level driver, but
this module is a library used by MDIO mux drivers.  Call this
functions something like init.  Also, passing it a platform_device
looks wrong since it might be a platform_device, but it might be an
i2c_client or an spi_device.  Pass in struct device instead.

Also, this function should return the pointer to the allocated
mdio_mux_parent_bus so that the calling driver has a reference to it.

> +	struct device_node *parent_bus_node;
> +	struct device_node *child_bus_node;
> +	int r, n, ret_val;
> +	struct mii_bus *parent_bus;
> +	struct mdio_mux_parent_bus *pb;
> +	struct mdio_mux_child_bus *cb;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	parent_bus_node = of_parse_phandle(pdev->dev.of_node, "mdio-parent-bus", 0);
> +
> +	if (!parent_bus_node)
> +		return -ENODEV;
> +
> +	parent_bus = of_mdio_find_bus(parent_bus_node);

What if of_mdio_find_bus() fails?

> +
> +	pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
> +	if (pb == NULL) {
> +		ret_val = -ENOMEM;
> +		goto err_parent_bus;
> +	}
> +
> +	pb->switch_data = data;
> +	pb->switch_fn = switch_fn;
> +	pb->current_child = -1;
> +	pb->parent_id = parent_count++;
> +	pb->mii_bus = parent_bus;
> +
> +	n = 0;
> +	for_each_child_of_node(pdev->dev.of_node, child_bus_node) {
> +		u32 v;
> +
> +		r = of_property_read_u32(child_bus_node, "reg", &v);
> +		if (r == 0) {
> +			cb = devm_kzalloc(&pdev->dev, sizeof(*cb), GFP_KERNEL);
> +			if (cb == NULL)
> +				break;
> +			cb->bus_number = v;
> +			cb->parent = pb;
> +			cb->mii_bus = mdiobus_alloc();
> +			cb->mii_bus->priv = cb;
> +
> +			cb->mii_bus->irq = cb->phy_irq;
> +			cb->mii_bus->name = "mdio_mux";
> +			snprintf(cb->mii_bus->id, MII_BUS_ID_SIZE, "%x.%x",
> +				 pb->parent_id, v);
> +			cb->mii_bus->parent = &pdev->dev;
> +			cb->mii_bus->read = mdio_mux_read;
> +			cb->mii_bus->write = mdio_mux_write;

The parent bus should probably maintain a list of all child busses so
that a shutdown function can tear it all down again.

> +			r = of_mdiobus_register(cb->mii_bus, child_bus_node);
> +			if (r) {
> +				of_node_put(child_bus_node);
> +				devm_kfree(&pdev->dev, cb);
> +			} else {
> +				n++;
> +			}
> +
> +		} else {
> +			of_node_put(child_bus_node);
> +		}
> +	}
> +	if (n) {
> +		dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
> +		return 0;
> +	}
> +	ret_val = -ENOMEM;
> +	devm_kfree(&pdev->dev, pb);
> +err_parent_bus:
> +	of_node_put(parent_bus_node);
> +	return ret_val;
> +}
> +EXPORT_SYMBOL(mdio_mux_probe);
> +
> +static int __devexit mdio_mux_remove(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static int __init mdio_mux_mod_init(void)
> +{
> +	return 0;
> +}
> +module_init(mdio_mux_mod_init);
> +
> +static void __exit mdio_mux_mod_exit(void)
> +{
> +}
> +module_exit(mdio_mux_mod_exit);

I don't believe that you need module empty module init/exit/remove
routines.  Just drop them.

> +
> +MODULE_DESCRIPTION(DRV_DESCRIPTION);
> +MODULE_VERSION(DRV_VERSION);
> +MODULE_AUTHOR("David Daney");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h
> new file mode 100644
> index 0000000..522992a
> --- /dev/null
> +++ b/include/linux/mdio-mux.h
> @@ -0,0 +1,18 @@
> +/*
> + * MDIO bus multiplexer framwork.
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2011 Cavium Networks
> + */
> +#ifndef __LINUX_MDIO_MUX_H
> +#define __LINUX_MDIO_MUX_H
> +#include <linux/platform_device.h>
> +
> +int mdio_mux_probe(struct platform_device *pdev,
> +		   int (*switch_fn) (int cur, int desired, void *data),
> +		   void *data);
> +
> +#endif /* __LINUX_MDIO_MUX_H */
> -- 
> 1.7.2.3
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 3/3] netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.
@ 2011-09-29 22:01     ` Grant Likely
  0 siblings, 0 replies; 24+ messages in thread
From: Grant Likely @ 2011-09-29 22:01 UTC (permalink / raw)
  To: David Daney; +Cc: devicetree-discuss, linux-kernel, netdev, davem

On Tue, Sep 27, 2011 at 04:26:55PM -0700, David Daney wrote:
> The GPIO pins select which sub bus is connected to the master.
> 
> Initially tested with an sn74cbtlv3253 switch device wired into the
> MDIO bus.
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: "David S. Miller" <davem@davemloft.net>
> ---
>  .../devicetree/bindings/net/mdio-mux-gpio.txt      |  129 ++++++++++++++++++
>  drivers/net/phy/Kconfig                            |    9 ++
>  drivers/net/phy/Makefile                           |    1 +
>  drivers/net/phy/mdio-mux-gpio.c                    |  143 ++++++++++++++++++++
>  4 files changed, 282 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
>  create mode 100644 drivers/net/phy/mdio-mux-gpio.c
> 
> diff --git a/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
> new file mode 100644
> index 0000000..8d0f945
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
> @@ -0,0 +1,129 @@
> +Properties for an MDIO bus multiplexer/switch controlled by GPIO pins.
> +
> +This is a special case of a MDIO bus multiplexer.  One or more GPIO
> +lines are used to control which child bus is connected.
> +
> +Required properties in addition to the generic multiplexer properties:
> +
> +- compatible : Should define the compatible device type for the
> +               multiplexer.  Currently "cavium,mdio-mux-sn74cbtlv3253"
> +               is defined, others are possible.
> +- gpios : GPIO specifiers for each GPIO line.  One or more must be specified.
> +
> +
> +Example :
> +
> +	/* The parent MDIO bus. */
> +	smi1: mdio@1180000001900 {
> +		compatible = "cavium,octeon-3860-mdio";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		reg = <0x11800 0x00001900 0x0 0x40>;
> +	};
> +
> +	/*
> +	   An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
> +	   pair of GPIO lines.  Child busses 2 and 3 populated with 4
> +	   PHYs each.
> +	 */
> +	mdio-mux {
> +		compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
> +		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
> +		mdio-parent-bus = <&smi1>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		mdio@2 {
> +			reg = <2>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			phy11: ethernet-phy@1 {
> +				reg = <1>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy12: ethernet-phy@2 {
> +				reg = <2>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy13: ethernet-phy@3 {
> +				reg = <3>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy14: ethernet-phy@4 {
> +				reg = <4>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +		};
> +
> +		mdio@3 {
> +			reg = <3>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			phy21: ethernet-phy@1 {
> +				reg = <1>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy22: ethernet-phy@2 {
> +				reg = <2>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy23: ethernet-phy@3 {
> +				reg = <3>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy24: ethernet-phy@4 {
> +				reg = <4>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +		};
> +	};
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 59848bc..59b3b17 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -127,6 +127,15 @@ config MDIO_BUS_MUX
>  	  to a parent bus.  Switching between child busses is done by
>  	  device specific drivers.
>  
> +config MDIO_BUS_MUX_GPIO
> +	tristate "Support for GPIO controlled MDIO bus multiplexers"
> +	depends on MDIO_BUS_MUX && GENERIC_GPIO
> +	help
> +	  This module provides a driver for MDIO bus multiplexers that
> +	  are controlled via GPIO lines.  The multiplexer connects one of
> +	  several child MDIO busses to a parent bus.  Child bus
> +	  selection is under the control of GPIO lines.
> +
>  config MDIO_OCTEON
>  	tristate "Support for MDIO buses on Octeon SOCs"
>  	depends on  CPU_CAVIUM_OCTEON
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index 0c081d5..d1a1927 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -24,3 +24,4 @@ obj-$(CONFIG_STE10XP)		+= ste10Xp.o
>  obj-$(CONFIG_MICREL_PHY)	+= micrel.o
>  obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
>  obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
> +obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o
> diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
> new file mode 100644
> index 0000000..3cdad35
> --- /dev/null
> +++ b/drivers/net/phy/mdio-mux-gpio.c
> @@ -0,0 +1,143 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2011 Cavium Networks
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/of_mdio.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/gfp.h>
> +#include <linux/phy.h>
> +#include <linux/mdio-mux.h>
> +#include <linux/of_gpio.h>
> +
> +#define DRV_VERSION "1.0"
> +#define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
> +
> +#define MDIO_MUX_GPIO_MAX_BITS 8
> +
> +struct mdio_mux_gpio_state {
> +	int gpio[MDIO_MUX_GPIO_MAX_BITS];
> +	unsigned int num_gpios;
> +};
> +
> +static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
> +				   void *data)
> +{
> +	int change;
> +	unsigned int n;
> +	struct mdio_mux_gpio_state *s = data;
> +
> +	if (current_child == desired_child)
> +		return 0;
> +
> +	change = current_child == -1 ? -1 : current_child ^ desired_child;
> +
> +	for (n = 0; n < s->num_gpios; n++) {
> +		if (change & 1)
> +			gpio_set_value_cansleep(s->gpio[n],
> +						(desired_child & 1) != 0);
> +		change >>= 1;
> +		desired_child >>= 1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
> +{
> +	enum of_gpio_flags f;
> +	struct mdio_mux_gpio_state *s;
> +	unsigned int num_gpios;
> +	unsigned int n;
> +	int r;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	num_gpios = of_gpio_count(pdev->dev.of_node);
> +	if (num_gpios == 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS)
> +		return -ENODEV;
> +
> +	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
> +	if (!s)
> +		return -ENOMEM;
> +
> +	s->num_gpios = num_gpios;
> +
> +	for (n = 0; n < num_gpios; ) {
> +		int gpio = of_get_named_gpio_flags(pdev->dev.of_node,
> +						   "gpios", n, &f);
> +		s->gpio[n] = gpio;
> +		if (gpio < 0) {
> +			r = -ENODEV;
> +			goto err;
> +		}
> +
> +		n++;
> +
> +		r = gpio_request(gpio, "mdio_mux_gpio");
> +		if (r)
> +			goto err;
> +
> +		r = gpio_direction_output(gpio, 0);
> +		if (r)
> +			goto err;
> +	}
> +
> +	r = mdio_mux_probe(pdev, mdio_mux_gpio_switch_fn, s);
> +
> +	if (r == 0)
> +		return 0;
> +err:
> +	while (n) {
> +		n--;
> +		gpio_free(s->gpio[n]);
> +	}
> +	devm_kfree(&pdev->dev, s);

Don't need to do this.  The probe failed, so the free will automatically happen because devm_kzalloc was used.

> +	return r;
> +}
> +
> +static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
> +{
> +	return 0;
> +}

Don't do empty remove functions.

This driver looks okay, but it needs the unwind stuff for removal, or
it needs to be explicit that it cannot be removed (which also means
that the mdio parent driver becomes unremovable too).

g.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 3/3] netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.
@ 2011-09-29 22:01     ` Grant Likely
  0 siblings, 0 replies; 24+ messages in thread
From: Grant Likely @ 2011-09-29 22:01 UTC (permalink / raw)
  To: David Daney
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q

On Tue, Sep 27, 2011 at 04:26:55PM -0700, David Daney wrote:
> The GPIO pins select which sub bus is connected to the master.
> 
> Initially tested with an sn74cbtlv3253 switch device wired into the
> MDIO bus.
> 
> Signed-off-by: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
> ---
>  .../devicetree/bindings/net/mdio-mux-gpio.txt      |  129 ++++++++++++++++++
>  drivers/net/phy/Kconfig                            |    9 ++
>  drivers/net/phy/Makefile                           |    1 +
>  drivers/net/phy/mdio-mux-gpio.c                    |  143 ++++++++++++++++++++
>  4 files changed, 282 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
>  create mode 100644 drivers/net/phy/mdio-mux-gpio.c
> 
> diff --git a/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
> new file mode 100644
> index 0000000..8d0f945
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
> @@ -0,0 +1,129 @@
> +Properties for an MDIO bus multiplexer/switch controlled by GPIO pins.
> +
> +This is a special case of a MDIO bus multiplexer.  One or more GPIO
> +lines are used to control which child bus is connected.
> +
> +Required properties in addition to the generic multiplexer properties:
> +
> +- compatible : Should define the compatible device type for the
> +               multiplexer.  Currently "cavium,mdio-mux-sn74cbtlv3253"
> +               is defined, others are possible.
> +- gpios : GPIO specifiers for each GPIO line.  One or more must be specified.
> +
> +
> +Example :
> +
> +	/* The parent MDIO bus. */
> +	smi1: mdio@1180000001900 {
> +		compatible = "cavium,octeon-3860-mdio";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		reg = <0x11800 0x00001900 0x0 0x40>;
> +	};
> +
> +	/*
> +	   An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
> +	   pair of GPIO lines.  Child busses 2 and 3 populated with 4
> +	   PHYs each.
> +	 */
> +	mdio-mux {
> +		compatible = "cavium,mdio-mux-sn74cbtlv3253", "cavium,mdio-mux";
> +		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
> +		mdio-parent-bus = <&smi1>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		mdio@2 {
> +			reg = <2>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			phy11: ethernet-phy@1 {
> +				reg = <1>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy12: ethernet-phy@2 {
> +				reg = <2>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy13: ethernet-phy@3 {
> +				reg = <3>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +			phy14: ethernet-phy@4 {
> +				reg = <4>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <10 8>; /* Pin 10, active low */
> +			};
> +		};
> +
> +		mdio@3 {
> +			reg = <3>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			phy21: ethernet-phy@1 {
> +				reg = <1>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy22: ethernet-phy@2 {
> +				reg = <2>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy23: ethernet-phy@3 {
> +				reg = <3>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +			phy24: ethernet-phy@4 {
> +				reg = <4>;
> +				compatible = "marvell,88e1149r";
> +				marvell,reg-init = <3 0x10 0 0x5777>,
> +					<3 0x11 0 0x00aa>,
> +					<3 0x12 0 0x4105>,
> +					<3 0x13 0 0x0a60>;
> +				interrupt-parent = <&gpio>;
> +				interrupts = <12 8>; /* Pin 12, active low */
> +			};
> +		};
> +	};
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 59848bc..59b3b17 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -127,6 +127,15 @@ config MDIO_BUS_MUX
>  	  to a parent bus.  Switching between child busses is done by
>  	  device specific drivers.
>  
> +config MDIO_BUS_MUX_GPIO
> +	tristate "Support for GPIO controlled MDIO bus multiplexers"
> +	depends on MDIO_BUS_MUX && GENERIC_GPIO
> +	help
> +	  This module provides a driver for MDIO bus multiplexers that
> +	  are controlled via GPIO lines.  The multiplexer connects one of
> +	  several child MDIO busses to a parent bus.  Child bus
> +	  selection is under the control of GPIO lines.
> +
>  config MDIO_OCTEON
>  	tristate "Support for MDIO buses on Octeon SOCs"
>  	depends on  CPU_CAVIUM_OCTEON
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index 0c081d5..d1a1927 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -24,3 +24,4 @@ obj-$(CONFIG_STE10XP)		+= ste10Xp.o
>  obj-$(CONFIG_MICREL_PHY)	+= micrel.o
>  obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
>  obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
> +obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o
> diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
> new file mode 100644
> index 0000000..3cdad35
> --- /dev/null
> +++ b/drivers/net/phy/mdio-mux-gpio.c
> @@ -0,0 +1,143 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2011 Cavium Networks
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/of_mdio.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/gfp.h>
> +#include <linux/phy.h>
> +#include <linux/mdio-mux.h>
> +#include <linux/of_gpio.h>
> +
> +#define DRV_VERSION "1.0"
> +#define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
> +
> +#define MDIO_MUX_GPIO_MAX_BITS 8
> +
> +struct mdio_mux_gpio_state {
> +	int gpio[MDIO_MUX_GPIO_MAX_BITS];
> +	unsigned int num_gpios;
> +};
> +
> +static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
> +				   void *data)
> +{
> +	int change;
> +	unsigned int n;
> +	struct mdio_mux_gpio_state *s = data;
> +
> +	if (current_child == desired_child)
> +		return 0;
> +
> +	change = current_child == -1 ? -1 : current_child ^ desired_child;
> +
> +	for (n = 0; n < s->num_gpios; n++) {
> +		if (change & 1)
> +			gpio_set_value_cansleep(s->gpio[n],
> +						(desired_child & 1) != 0);
> +		change >>= 1;
> +		desired_child >>= 1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
> +{
> +	enum of_gpio_flags f;
> +	struct mdio_mux_gpio_state *s;
> +	unsigned int num_gpios;
> +	unsigned int n;
> +	int r;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	num_gpios = of_gpio_count(pdev->dev.of_node);
> +	if (num_gpios == 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS)
> +		return -ENODEV;
> +
> +	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
> +	if (!s)
> +		return -ENOMEM;
> +
> +	s->num_gpios = num_gpios;
> +
> +	for (n = 0; n < num_gpios; ) {
> +		int gpio = of_get_named_gpio_flags(pdev->dev.of_node,
> +						   "gpios", n, &f);
> +		s->gpio[n] = gpio;
> +		if (gpio < 0) {
> +			r = -ENODEV;
> +			goto err;
> +		}
> +
> +		n++;
> +
> +		r = gpio_request(gpio, "mdio_mux_gpio");
> +		if (r)
> +			goto err;
> +
> +		r = gpio_direction_output(gpio, 0);
> +		if (r)
> +			goto err;
> +	}
> +
> +	r = mdio_mux_probe(pdev, mdio_mux_gpio_switch_fn, s);
> +
> +	if (r == 0)
> +		return 0;
> +err:
> +	while (n) {
> +		n--;
> +		gpio_free(s->gpio[n]);
> +	}
> +	devm_kfree(&pdev->dev, s);

Don't need to do this.  The probe failed, so the free will automatically happen because devm_kzalloc was used.

> +	return r;
> +}
> +
> +static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
> +{
> +	return 0;
> +}

Don't do empty remove functions.

This driver looks okay, but it needs the unwind stuff for removal, or
it needs to be explicit that it cannot be removed (which also means
that the mdio parent driver becomes unremovable too).

g.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
  2011-09-29 20:31 ` [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support David Miller
@ 2011-09-30  0:32   ` Grant Likely
  2011-10-17 14:48       ` Kumar Gala
  0 siblings, 1 reply; 24+ messages in thread
From: Grant Likely @ 2011-09-30  0:32 UTC (permalink / raw)
  To: David Miller; +Cc: david.daney, devicetree-discuss, linux-kernel, netdev

On Thu, Sep 29, 2011 at 04:31:12PM -0400, David Miller wrote:
> From: David Daney <david.daney@cavium.com>
> Date: Tue, 27 Sep 2011 16:26:52 -0700
> 
> > v2: Update bindings to use "reg" and "mdio-parent-bus" insutead of
> >     "cell-index" and "parent-bus"
> 
> Grant, when the final version of this patch set is ready how do
> you want to handle merging it in?
> 
> I think it would be safe to merge this via your tree, since the
> changes made to existing network driver files are rather trivial and
> thus merge conflict friendly.

Your tree or mine, I'm happy either way.  Even if there were
conflicts, they would be trivial.

Sure, I'll take care of merging it when I see an ack from you.

> Actually, I feel like we've discussed this before :-)

:)

g.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
@ 2011-10-17 14:48       ` Kumar Gala
  0 siblings, 0 replies; 24+ messages in thread
From: Kumar Gala @ 2011-10-17 14:48 UTC (permalink / raw)
  To: Grant Likely
  Cc: David Miller, david.daney, devicetree-discuss, linux-kernel, netdev


On Sep 29, 2011, at 7:32 PM, Grant Likely wrote:

> On Thu, Sep 29, 2011 at 04:31:12PM -0400, David Miller wrote:
>> From: David Daney <david.daney@cavium.com>
>> Date: Tue, 27 Sep 2011 16:26:52 -0700
>> 
>>> v2: Update bindings to use "reg" and "mdio-parent-bus" insutead of
>>>    "cell-index" and "parent-bus"
>> 
>> Grant, when the final version of this patch set is ready how do
>> you want to handle merging it in?
>> 
>> I think it would be safe to merge this via your tree, since the
>> changes made to existing network driver files are rather trivial and
>> thus merge conflict friendly.
> 
> Your tree or mine, I'm happy either way.  Even if there were
> conflicts, they would be trivial.
> 
> Sure, I'll take care of merging it when I see an ack from you.
> 
>> Actually, I feel like we've discussed this before :-)
> 
> :)
> 
> g.

Any updates to these patches?

- k

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
@ 2011-10-17 14:48       ` Kumar Gala
  0 siblings, 0 replies; 24+ messages in thread
From: Kumar Gala @ 2011-10-17 14:48 UTC (permalink / raw)
  To: Grant Likely
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	netdev-u79uwXL29TY76Z2rM5mHXA, David Miller


On Sep 29, 2011, at 7:32 PM, Grant Likely wrote:

> On Thu, Sep 29, 2011 at 04:31:12PM -0400, David Miller wrote:
>> From: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
>> Date: Tue, 27 Sep 2011 16:26:52 -0700
>> 
>>> v2: Update bindings to use "reg" and "mdio-parent-bus" insutead of
>>>    "cell-index" and "parent-bus"
>> 
>> Grant, when the final version of this patch set is ready how do
>> you want to handle merging it in?
>> 
>> I think it would be safe to merge this via your tree, since the
>> changes made to existing network driver files are rather trivial and
>> thus merge conflict friendly.
> 
> Your tree or mine, I'm happy either way.  Even if there were
> conflicts, they would be trivial.
> 
> Sure, I'll take care of merging it when I see an ack from you.
> 
>> Actually, I feel like we've discussed this before :-)
> 
> :)
> 
> g.

Any updates to these patches?

- k

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
  2011-10-17 14:48       ` Kumar Gala
  (?)
@ 2011-10-17 15:41       ` David Daney
  2012-04-13 19:08         ` Andy Fleming
  -1 siblings, 1 reply; 24+ messages in thread
From: David Daney @ 2011-10-17 15:41 UTC (permalink / raw)
  To: Kumar Gala
  Cc: Grant Likely, David Miller, devicetree-discuss, linux-kernel, netdev

On 10/17/2011 07:48 AM, Kumar Gala wrote:
>
> On Sep 29, 2011, at 7:32 PM, Grant Likely wrote:
>
>> On Thu, Sep 29, 2011 at 04:31:12PM -0400, David Miller wrote:
>>> From: David Daney<david.daney@cavium.com>
>>> Date: Tue, 27 Sep 2011 16:26:52 -0700
>>>
>>>> v2: Update bindings to use "reg" and "mdio-parent-bus" insutead of
>>>>     "cell-index" and "parent-bus"
>>>
>>> Grant, when the final version of this patch set is ready how do
>>> you want to handle merging it in?
>>>
>>> I think it would be safe to merge this via your tree, since the
>>> changes made to existing network driver files are rather trivial and
>>> thus merge conflict friendly.
>>
>> Your tree or mine, I'm happy either way.  Even if there were
>> conflicts, they would be trivial.
>>
>> Sure, I'll take care of merging it when I see an ack from you.
>>
>>> Actually, I feel like we've discussed this before :-)
>>
>> :)
>>
>> g.
>
> Any updates to these patches?

Not yet, so you didn't miss anything.

They are on my to-do list though

David Daney

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
  2011-10-17 15:41       ` David Daney
@ 2012-04-13 19:08         ` Andy Fleming
  2012-04-13 19:51             ` David Daney
  0 siblings, 1 reply; 24+ messages in thread
From: Andy Fleming @ 2012-04-13 19:08 UTC (permalink / raw)
  To: David Daney
  Cc: Kumar Gala, Grant Likely, David Miller, devicetree-discuss,
	linux-kernel, netdev

On Mon, Oct 17, 2011 at 10:41 AM, David Daney <david.daney@cavium.com> wrote:
> On 10/17/2011 07:48 AM, Kumar Gala wrote:
>>
>>
>> On Sep 29, 2011, at 7:32 PM, Grant Likely wrote:
>>
>>> On Thu, Sep 29, 2011 at 04:31:12PM -0400, David Miller wrote:
>>>>
>>>> From: David Daney<david.daney@cavium.com>

>>> Your tree or mine, I'm happy either way.  Even if there were
>>> conflicts, they would be trivial.
>>>
>>> Sure, I'll take care of merging it when I see an ack from you.

>> Any updates to these patches?
>
>
> Not yet, so you didn't miss anything.
>
> They are on my to-do list though

Pinging on this, again, as we'd like to leverage it for current and
future boards. :)

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
  2012-04-13 19:08         ` Andy Fleming
@ 2012-04-13 19:51             ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2012-04-13 19:51 UTC (permalink / raw)
  To: Andy Fleming
  Cc: Kumar Gala, Grant Likely, David Miller, devicetree-discuss,
	linux-kernel, netdev

On 04/13/2012 12:08 PM, Andy Fleming wrote:
> On Mon, Oct 17, 2011 at 10:41 AM, David Daney<david.daney@cavium.com>  wrote:
>> On 10/17/2011 07:48 AM, Kumar Gala wrote:
>>>
>>>
>>> On Sep 29, 2011, at 7:32 PM, Grant Likely wrote:
>>>
>>>> On Thu, Sep 29, 2011 at 04:31:12PM -0400, David Miller wrote:
>>>>>
>>>>> From: David Daney<david.daney@cavium.com>
>
>>>> Your tree or mine, I'm happy either way.  Even if there were
>>>> conflicts, they would be trivial.
>>>>
>>>> Sure, I'll take care of merging it when I see an ack from you.
>
>>> Any updates to these patches?
>>
>>
>> Not yet, so you didn't miss anything.
>>
>> They are on my to-do list though
>
> Pinging on this, again, as we'd like to leverage it for current and
> future boards. :)
>

Today I am working on it, so I will have new patches within a couple of 
days.

David Daney

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support.
@ 2012-04-13 19:51             ` David Daney
  0 siblings, 0 replies; 24+ messages in thread
From: David Daney @ 2012-04-13 19:51 UTC (permalink / raw)
  To: Andy Fleming
  Cc: Kumar Gala, Grant Likely, David Miller, devicetree-discuss,
	linux-kernel, netdev

On 04/13/2012 12:08 PM, Andy Fleming wrote:
> On Mon, Oct 17, 2011 at 10:41 AM, David Daney<david.daney@cavium.com>  wrote:
>> On 10/17/2011 07:48 AM, Kumar Gala wrote:
>>>
>>>
>>> On Sep 29, 2011, at 7:32 PM, Grant Likely wrote:
>>>
>>>> On Thu, Sep 29, 2011 at 04:31:12PM -0400, David Miller wrote:
>>>>>
>>>>> From: David Daney<david.daney@cavium.com>
>
>>>> Your tree or mine, I'm happy either way.  Even if there were
>>>> conflicts, they would be trivial.
>>>>
>>>> Sure, I'll take care of merging it when I see an ack from you.
>
>>> Any updates to these patches?
>>
>>
>> Not yet, so you didn't miss anything.
>>
>> They are on my to-do list though
>
> Pinging on this, again, as we'd like to leverage it for current and
> future boards. :)
>

Today I am working on it, so I will have new patches within a couple of 
days.

David Daney

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2012-04-13 19:51 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-27 23:26 [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support David Daney
2011-09-27 23:26 ` David Daney
2011-09-27 23:26 ` [PATCH v2 1/3] netdev/of/phy: New function: of_mdio_find_bus() David Daney
2011-09-29 21:41   ` Grant Likely
2011-09-27 23:26 ` [PATCH v2 2/3] netdev/of/phy: Add MDIO bus multiplexer support David Daney
2011-09-27 23:26   ` David Daney
2011-09-28  7:25   ` Michał Mirosław
2011-09-28  7:25     ` Michał Mirosław
2011-09-28 16:51     ` David Daney
2011-09-28 17:32       ` Michał Mirosław
2011-09-28 17:42         ` David Daney
2011-09-29 21:56   ` Grant Likely
2011-09-27 23:26 ` [PATCH v2 3/3] netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines David Daney
2011-09-27 23:26   ` David Daney
2011-09-29 22:01   ` Grant Likely
2011-09-29 22:01     ` Grant Likely
2011-09-29 20:31 ` [PATCH v2 0/3] netdev/of/phy: MDIO bus multiplexer support David Miller
2011-09-30  0:32   ` Grant Likely
2011-10-17 14:48     ` Kumar Gala
2011-10-17 14:48       ` Kumar Gala
2011-10-17 15:41       ` David Daney
2012-04-13 19:08         ` Andy Fleming
2012-04-13 19:51           ` David Daney
2012-04-13 19:51             ` David Daney

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.