All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class
@ 2019-06-18 14:58 Alexandru Marginean
  2019-06-18 14:58 ` [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes Alexandru Marginean
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Alexandru Marginean @ 2019-06-18 14:58 UTC (permalink / raw)
  To: u-boot

Adds a class for MDIO MUXes, which control access to a series of
downstream child MDIOs.
MDIO MUX drivers are required to implement a select function used to switch
between child buses.
MUX children are registered as MDIO buses and they can be used just like
regular MDIOs.

Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
---

Changes in v2:
	- no change
Changes in v3:
	- no change, just fighting with the email server

 drivers/net/Kconfig    |  12 +++
 include/dm/uclass-id.h |   1 +
 include/miiphy.h       |  20 ++++
 net/Makefile           |   1 +
 net/mdio-mux-uclass.c  | 232 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 266 insertions(+)
 create mode 100644 net/mdio-mux-uclass.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 635f8d72c2..0dc26ac254 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -24,6 +24,18 @@ config DM_MDIO
 	  This is currently implemented in net/mdio-uclass.c
 	  Look in include/miiphy.h for details.
 
+config DM_MDIO_MUX
+	bool "Enable Driver Model for MDIO MUX devices"
+	depends on DM_MDIO
+	help
+	  Enable driver model for MDIO MUX devices
+
+	  Adds UCLASS_MDIO_MUX DM class supporting MDIO MUXes.  Useful for
+	  systems that support DM_MDIO and integrate one or multiple muxes on
+	  the MDIO bus.
+	  This is currently implemented in net/mdio-mux-uclass.c
+	  Look in include/miiphy.h for details.
+
 config MDIO_SANDBOX
 	depends on DM_MDIO && SANDBOX
 	default y
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 90667e62cf..b859a9ec04 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -59,6 +59,7 @@ enum uclass_id {
 	UCLASS_MAILBOX,		/* Mailbox controller */
 	UCLASS_MASS_STORAGE,	/* Mass storage device */
 	UCLASS_MDIO,		/* MDIO bus */
+	UCLASS_MDIO_MUX,	/* MDIO MUX/switch */
 	UCLASS_MISC,		/* Miscellaneous device */
 	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
diff --git a/include/miiphy.h b/include/miiphy.h
index e6dd441983..9b97d09f18 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -167,4 +167,24 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
 
 #endif
 
+#ifdef CONFIG_DM_MDIO_MUX
+
+/* indicates none of the child buses is selected */
+#define MDIO_MUX_SELECT_NONE	-1
+
+/**
+ * struct mdio_mux_ops - MDIO MUX operations
+ *
+ * @select: Selects a child bus
+ * @deselect: Clean up selection.  Optional, can be NULL
+ */
+struct mdio_mux_ops {
+	int (*select)(struct udevice *mux, int cur, int sel);
+	int (*deselect)(struct udevice *mux, int sel);
+};
+
+#define mdio_mux_get_ops(dev) ((struct mdio_mux_ops *)(dev)->driver->ops)
+
+#endif
+
 #endif
diff --git a/net/Makefile b/net/Makefile
index 6251ff3991..826544f05f 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -16,6 +16,7 @@ else
 obj-$(CONFIG_NET)      += eth_legacy.o
 endif
 obj-$(CONFIG_DM_MDIO)  += mdio-uclass.o
+obj-$(CONFIG_DM_MDIO_MUX) += mdio-mux-uclass.o
 obj-$(CONFIG_NET)      += eth_common.o
 obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
 obj-$(CONFIG_NET)      += net.o
diff --git a/net/mdio-mux-uclass.c b/net/mdio-mux-uclass.c
new file mode 100644
index 0000000000..e3fe12a531
--- /dev/null
+++ b/net/mdio-mux-uclass.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <dm/lists.h>
+
+#define MDIO_MUX_CHILD_DRV_NAME	"mdio-mux-bus-drv"
+
+/**
+ * struct mdio_mux_perdev_priv - Per-device class data for MDIO MUX DM
+ *
+ * @parent_mdio: Parent DM MDIO device, this is called for actual MDIO I/O after
+ *               setting up the mux.  Typically this is a real MDIO device,
+ *               unless there are cascaded muxes.
+ * @selected:    Current child bus selection.  Defaults to -1
+ */
+struct mdio_mux_perdev_priv {
+	struct udevice *mdio_parent;
+	int selected;
+};
+
+/*
+ * This source file uses three types of devices, as follows:
+ * - mux is the hardware MDIO MUX which selects between the existing child MDIO
+ * buses, this is the device relevant for MDIO MUX class of drivers.
+ * - ch is a child MDIO bus, this is just a representation of an mux selection,
+ * not a real piece of hardware.
+ * - mdio_parent is the actual MDIO bus called to perform reads/writes  after
+ * the MUX is configured.  Typically this is a real MDIO device, unless there
+ * are cascaded muxes.
+ */
+
+/**
+ * struct mdio_mux_ch_data - Per-device data for child MDIOs
+ *
+ * @sel: Selection value used by the MDIO MUX to access this child MDIO bus
+ */
+struct mdio_mux_ch_data {
+	int sel;
+};
+
+static struct udevice *mmux_get_parent_mdio(struct udevice *mux)
+{
+	struct mdio_mux_perdev_priv *pdata = dev_get_uclass_priv(mux);
+
+	return pdata->mdio_parent;
+}
+
+static struct mdio_ops *mmux_get_mdio_parent_ops(struct udevice *mux)
+{
+	return mdio_get_ops(mmux_get_parent_mdio(mux));
+}
+
+/* call driver select function before performing MDIO r/w */
+static int mmux_change_sel(struct udevice *ch, bool sel)
+{
+	struct udevice *mux = ch->parent;
+	struct mdio_mux_perdev_priv *priv = dev_get_uclass_priv(mux);
+	struct mdio_mux_ops *ops = mdio_mux_get_ops(mux);
+	struct mdio_mux_ch_data *ch_data = dev_get_parent_platdata(ch);
+	int err = 0;
+
+	if (sel) {
+		err = ops->select(mux, priv->selected, ch_data->sel);
+		if (err)
+			return err;
+
+		priv->selected = ch_data->sel;
+	} else {
+		if (ops->deselect) {
+			ops->deselect(mux, ch_data->sel);
+			priv->selected = MDIO_MUX_SELECT_NONE;
+		}
+	}
+
+	return 0;
+}
+
+/* Read wrapper, sets up the mux before issuing a read on parent MDIO bus */
+static int mmux_read(struct udevice *ch, int addr, int devad,
+		     int reg)
+{
+	struct udevice *mux = ch->parent;
+	struct udevice *parent_mdio = mmux_get_parent_mdio(mux);
+	struct mdio_ops *parent_ops = mmux_get_mdio_parent_ops(mux);
+	int err;
+
+	err = mmux_change_sel(ch, true);
+	if (err)
+		return err;
+
+	err = parent_ops->read(parent_mdio, addr, devad, reg);
+	mmux_change_sel(ch, false);
+
+	return err;
+}
+
+/* Write wrapper, sets up the mux before issuing a write on parent MDIO bus */
+static int mmux_write(struct udevice *ch, int addr, int devad,
+		      int reg, u16 val)
+{
+	struct udevice *mux = ch->parent;
+	struct udevice *parent_mdio = mmux_get_parent_mdio(mux);
+	struct mdio_ops *parent_ops = mmux_get_mdio_parent_ops(mux);
+	int err;
+
+	err = mmux_change_sel(ch, true);
+	if (err)
+		return err;
+
+	err = parent_ops->write(parent_mdio, addr, devad, reg, val);
+	mmux_change_sel(ch, false);
+
+	return err;
+}
+
+/* Reset wrapper, sets up the mux before issuing a reset on parent MDIO bus */
+static int mmux_reset(struct udevice *ch)
+{
+	struct udevice *mux = ch->parent;
+	struct udevice *parent_mdio = mmux_get_parent_mdio(mux);
+	struct mdio_ops *parent_ops = mmux_get_mdio_parent_ops(mux);
+	int err;
+
+	/* reset is optional, if it's not implemented just exit */
+	if (!parent_ops->reset)
+		return 0;
+
+	err = mmux_change_sel(ch, true);
+	if (err)
+		return err;
+
+	err = parent_ops->reset(parent_mdio);
+	mmux_change_sel(ch, false);
+
+	return err;
+}
+
+/* Picks up the mux selection value for each child */
+static int dm_mdio_mux_child_post_bind(struct udevice *ch)
+{
+	struct mdio_mux_ch_data *ch_data = dev_get_parent_platdata(ch);
+
+	ch_data->sel = dev_read_u32_default(ch, "reg", MDIO_MUX_SELECT_NONE);
+
+	if (ch_data->sel == MDIO_MUX_SELECT_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Explicitly bind child MDIOs after binding the mux */
+static int dm_mdio_mux_post_bind(struct udevice *mux)
+{
+	ofnode ch_node;
+	int err, first_err = 0;
+
+	if (!ofnode_valid(mux->node)) {
+		debug("%s: no mux node found, no child MDIO busses set up\n",
+		      __func__);
+		return 0;
+	}
+
+	/*
+	 * we're going by Linux bindings so the child nodes do not have
+	 * compatible strings.  We're going through them here and binding to
+	 * them.
+	 */
+	dev_for_each_subnode(ch_node, mux) {
+		struct udevice *ch_dev;
+		const char *ch_name;
+
+		ch_name = ofnode_get_name(ch_node);
+
+		err = device_bind_driver_to_node(mux, MDIO_MUX_CHILD_DRV_NAME,
+						 ch_name, ch_node, &ch_dev);
+		/* try to bind all, but keep 1st error */
+		if (err && !first_err)
+			first_err = err;
+	}
+
+	return first_err;
+}
+
+/* Get a reference to the parent MDIO bus, it should be bound by now */
+static int dm_mdio_mux_post_probe(struct udevice *mux)
+{
+	struct mdio_mux_perdev_priv *priv = dev_get_uclass_priv(mux);
+	int err;
+
+	priv->selected = MDIO_MUX_SELECT_NONE;
+
+	/* pick up mdio parent from device tree */
+	err = uclass_get_device_by_phandle(UCLASS_MDIO, mux, "mdio-parent-bus",
+					   &priv->mdio_parent);
+	if (err) {
+		debug("%s: didn't find mdio-parent-bus\n", __func__);
+		return err;
+	}
+
+	return 0;
+}
+
+const struct mdio_ops mmux_child_mdio_ops = {
+	.read = mmux_read,
+	.write = mmux_write,
+	.reset = mmux_reset,
+};
+
+/* MDIO class driver used for MUX child MDIO buses */
+U_BOOT_DRIVER(mdio_mux_child) = {
+	.name		= MDIO_MUX_CHILD_DRV_NAME,
+	.id		= UCLASS_MDIO,
+	.ops		= &mmux_child_mdio_ops,
+};
+
+UCLASS_DRIVER(mdio_mux) = {
+	.id = UCLASS_MDIO_MUX,
+	.name = "mdio-mux",
+	.child_post_bind = dm_mdio_mux_child_post_bind,
+	.post_bind  = dm_mdio_mux_post_bind,
+	.post_probe = dm_mdio_mux_post_probe,
+	.per_device_auto_alloc_size = sizeof(struct mdio_mux_perdev_priv),
+	.per_child_platdata_auto_alloc_size = sizeof(struct mdio_mux_ch_data),
+};
-- 
2.17.1

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

* [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes
  2019-06-18 14:58 [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Alexandru Marginean
@ 2019-06-18 14:58 ` Alexandru Marginean
  2019-07-08  7:40   ` Bin Meng
  2019-06-18 14:58 ` [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY Alexandru Marginean
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Alexandru Marginean @ 2019-06-18 14:58 UTC (permalink / raw)
  To: u-boot

Adds a short bindings document describing the expected structure of a MDIO
MUX dts node.  This is based on Linux binding and the example is in fact
copied from there.

Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
---

Changes in v2:
	- no change
Changes in v3:
	- no change, just fighting with the email server

 doc/device-tree-bindings/net/mdio-mux.txt | 61 +++++++++++++++++++++++
 1 file changed, 61 insertions(+)
 create mode 100644 doc/device-tree-bindings/net/mdio-mux.txt

diff --git a/doc/device-tree-bindings/net/mdio-mux.txt b/doc/device-tree-bindings/net/mdio-mux.txt
new file mode 100644
index 0000000000..fdf817fd93
--- /dev/null
+++ b/doc/device-tree-bindings/net/mdio-mux.txt
@@ -0,0 +1,61 @@
+The expected structure of an MDIO MUX device tree node is described here.  This
+is heavily based on current Linux specification.
+The MDIO buses downstream of the MUX should be described in the device tree as
+child nodes as indicated below.
+
+Required properties:
+mdio-parent-bus = a phandle to the MDIO bus used to perform actual I/O.  This is
+                  typically a real MDIO device, unless there are cascaded MUXes.
+#address-cells = <1>, each MDIO group is identified by one 32b value.
+#size-cells = <0>
+
+Other properties:
+The properties described here are sufficient for MDIO MUX DM class code, but
+MUX drivers may define additional properties, either required or optional.
+
+Required properties in child nodes:
+reg = value to be configured on the MUX to select the respective downstream
+      MDIO.
+
+Child nodes should normally contain PHY nodes, referenced by phandle from
+ethernet nodes of the eth interfaces using these PHYs.
+
+Example structure, extracted from Linux bindings document:
+
+	/* The parent MDIO bus. */
+	smi1: mdio at 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 = "mdio-mux-gpio";
+		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+		mdio-parent-bus = <&smi1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio at 2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			phy11: ethernet-phy at 1 {
+				reg = <1>;
+				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 */
+			};
+		};
+	};
+
-- 
2.17.1

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

* [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY
  2019-06-18 14:58 [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Alexandru Marginean
  2019-06-18 14:58 ` [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes Alexandru Marginean
@ 2019-06-18 14:58 ` Alexandru Marginean
  2019-07-08  7:40   ` Bin Meng
  2019-07-09 23:54   ` Joe Hershberger
  2019-06-18 14:58 ` [U-Boot] [PATCH 4/4 v3] test: dm: add a test for MDIO MUX DM uclass Alexandru Marginean
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 12+ messages in thread
From: Alexandru Marginean @ 2019-06-18 14:58 UTC (permalink / raw)
  To: u-boot

This 2nd register is used by the follow-up MDIO MUX test.

Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
---

Changes in v2:
	- no change
Changes in v3:
	- no change, just fighting with the email server

 drivers/net/mdio_sandbox.c | 16 +++++++++-------
 test/dm/mdio.c             |  3 +++
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mdio_sandbox.c b/drivers/net/mdio_sandbox.c
index 07515e078c..df053f5381 100644
--- a/drivers/net/mdio_sandbox.c
+++ b/drivers/net/mdio_sandbox.c
@@ -9,11 +9,11 @@
 #include <miiphy.h>
 
 #define SANDBOX_PHY_ADDR	5
-#define SANDBOX_PHY_REG		0
+#define SANDBOX_PHY_REG_CNT	2
 
 struct mdio_sandbox_priv {
 	int enabled;
-	u16 reg;
+	u16 reg[SANDBOX_PHY_REG_CNT];
 };
 
 static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
@@ -27,10 +27,10 @@ static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
 		return -ENODEV;
 	if (devad != MDIO_DEVAD_NONE)
 		return -ENODEV;
-	if (reg != SANDBOX_PHY_REG)
+	if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
 		return -ENODEV;
 
-	return priv->reg;
+	return priv->reg[reg];
 }
 
 static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
@@ -45,10 +45,10 @@ static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
 		return -ENODEV;
 	if (devad != MDIO_DEVAD_NONE)
 		return -ENODEV;
-	if (reg != SANDBOX_PHY_REG)
+	if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
 		return -ENODEV;
 
-	priv->reg = val;
+	priv->reg[reg] = val;
 
 	return 0;
 }
@@ -56,8 +56,10 @@ static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
 static int mdio_sandbox_reset(struct udevice *dev)
 {
 	struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+	int i;
 
-	priv->reg = 0;
+	for (i = 0; i < SANDBOX_PHY_REG_CNT; i++)
+		priv->reg[i] = 0;
 
 	return 0;
 }
diff --git a/test/dm/mdio.c b/test/dm/mdio.c
index 5b66255f7d..dc229aed6d 100644
--- a/test/dm/mdio.c
+++ b/test/dm/mdio.c
@@ -13,6 +13,9 @@
 
 /* macros copied over from mdio_sandbox.c */
 #define SANDBOX_PHY_ADDR	5
+#define SANDBOX_PHY_REG_CNT	2
+
+/* test using 1st register, 0 */
 #define SANDBOX_PHY_REG		0
 
 #define TEST_REG_VALUE		0xabcd
-- 
2.17.1

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

* [U-Boot] [PATCH 4/4 v3] test: dm: add a test for MDIO MUX DM uclass
  2019-06-18 14:58 [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Alexandru Marginean
  2019-06-18 14:58 ` [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes Alexandru Marginean
  2019-06-18 14:58 ` [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY Alexandru Marginean
@ 2019-06-18 14:58 ` Alexandru Marginean
  2019-07-08  7:40   ` Bin Meng
  2019-07-08  7:40 ` [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Bin Meng
  2019-07-09 23:49 ` Joe Hershberger
  4 siblings, 1 reply; 12+ messages in thread
From: Alexandru Marginean @ 2019-06-18 14:58 UTC (permalink / raw)
  To: u-boot

Adds a test using a makeshift MDIO MUX.  The test is based on the existing
MDIO test.  It uses the last emulated PHY register to verify MUX selection.

Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
---

Changes in v2:
	- no change
Changes in v3:
	- no change, just fighting with the email server

 arch/Kconfig                   |  1 +
 arch/sandbox/dts/test.dts      | 21 +++++++-
 drivers/net/Kconfig            | 10 ++++
 drivers/net/Makefile           |  1 +
 drivers/net/mdio_mux_sandbox.c | 97 ++++++++++++++++++++++++++++++++++
 test/dm/Makefile               |  1 +
 test/dm/mdio_mux.c             | 80 ++++++++++++++++++++++++++++
 7 files changed, 210 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/mdio_mux_sandbox.c
 create mode 100644 test/dm/mdio_mux.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 1e62a7615d..1a0f1ab8a7 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -122,6 +122,7 @@ config SANDBOX
 	imply PCH
 	imply PHYLIB
 	imply DM_MDIO
+	imply DM_MDIO_MUX
 
 config SH
 	bool "SuperH architecture"
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index dd50a951a8..a05e437abf 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -808,7 +808,26 @@
 		dma-names = "m2m", "tx0", "rx0";
 	};
 
-	mdio-test {
+	/*
+	 * keep mdio-mux ahead of mdio, u-boot doesn't do reference count on
+	 * these devices and we don't want mdio-parent-bus to be released before
+	 * the mux.
+	 */
+	mdio-mux-test {
+		compatible = "sandbox,mdio-mux";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mdio-parent-bus = <&mdio>;
+
+		mdio-ch-test at 0 {
+			reg = <0>;
+		};
+		mdio-ch-test at 1 {
+			reg = <1>;
+		};
+	};
+
+	mdio: mdio-test {
 		compatible = "sandbox,mdio";
 	};
 };
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0dc26ac254..403df5e960 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -46,6 +46,16 @@ config MDIO_SANDBOX
 
 	  This driver is used in for testing in test/dm/mdio.c
 
+config MDIO_MUX_SANDBOX
+	depends on DM_MDIO_MUX && MDIO_SANDBOX
+	default y
+	bool "Sandbox: Mocked MDIO-MUX driver"
+	help
+	  This driver implements dummy select/deselect ops mimicking a MUX on
+	  the MDIO bux.  It uses mdio_sandbox driver as parent MDIO.
+
+	  This driver is used for testing in test/dm/mdio.c
+
 menuconfig NETDEVICES
 	bool "Network device support"
 	depends on NET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 40038427db..a3706ca27b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -78,3 +78,4 @@ obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
 obj-y += mscc_eswitch/
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o
+obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
diff --git a/drivers/net/mdio_mux_sandbox.c b/drivers/net/mdio_mux_sandbox.c
new file mode 100644
index 0000000000..3dba4d18a1
--- /dev/null
+++ b/drivers/net/mdio_mux_sandbox.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <miiphy.h>
+
+/* macros copied over from mdio_sandbox.c */
+#define SANDBOX_PHY_ADDR	5
+#define SANDBOX_PHY_REG_CNT	2
+
+struct mdio_mux_sandbox_priv {
+	int enabled;
+	int sel;
+};
+
+static int mdio_mux_sandbox_mark_selection(struct udevice *dev, int sel)
+{
+	struct udevice *mdio;
+	struct mdio_ops *ops;
+	int err;
+
+	/*
+	 * find the sandbox parent mdio and write a register on the PHY there
+	 * so the mux test can verify selection.
+	 */
+	err = uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &mdio);
+	if (err)
+		return err;
+	ops = mdio_get_ops(mdio);
+	return ops->write(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			  SANDBOX_PHY_REG_CNT - 1, (u16)sel);
+}
+
+static int mdio_mux_sandbox_select(struct udevice *dev, int cur, int sel)
+{
+	struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (!priv->enabled)
+		return -ENODEV;
+
+	if (cur != priv->sel)
+		return -EINVAL;
+
+	priv->sel = sel;
+	mdio_mux_sandbox_mark_selection(dev, priv->sel);
+
+	return 0;
+}
+
+static int mdio_mux_sandbox_deselect(struct udevice *dev, int sel)
+{
+	struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (!priv->enabled)
+		return -ENODEV;
+
+	if (sel != priv->sel)
+		return -EINVAL;
+
+	priv->sel = -1;
+	mdio_mux_sandbox_mark_selection(dev, priv->sel);
+
+	return 0;
+}
+
+static const struct mdio_mux_ops mdio_mux_sandbox_ops = {
+	.select = mdio_mux_sandbox_select,
+	.deselect = mdio_mux_sandbox_deselect,
+};
+
+static int mdio_mux_sandbox_probe(struct udevice *dev)
+{
+	struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+	priv->enabled = 1;
+	priv->sel = -1;
+
+	return 0;
+}
+
+static const struct udevice_id mdio_mux_sandbox_ids[] = {
+	{ .compatible = "sandbox,mdio-mux" },
+	{ }
+};
+
+U_BOOT_DRIVER(mdio_mux_sandbox) = {
+	.name		= "mdio_mux_sandbox",
+	.id		= UCLASS_MDIO_MUX,
+	.of_match	= mdio_mux_sandbox_ids,
+	.probe		= mdio_mux_sandbox_probe,
+	.ops		= &mdio_mux_sandbox_ops,
+	.priv_auto_alloc_size = sizeof(struct mdio_mux_sandbox_priv),
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3f042e3ab4..8b3477c136 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -61,4 +61,5 @@ obj-$(CONFIG_TEE) += tee.o
 obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
 obj-$(CONFIG_DMA) += dma.o
 obj-$(CONFIG_DM_MDIO) += mdio.o
+obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o
 endif
diff --git a/test/dm/mdio_mux.c b/test/dm/mdio_mux.c
new file mode 100644
index 0000000000..f962e09dbc
--- /dev/null
+++ b/test/dm/mdio_mux.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <misc.h>
+#include <test/ut.h>
+#include <miiphy.h>
+
+/* macros copied over from mdio_sandbox.c */
+#define SANDBOX_PHY_ADDR	5
+#define SANDBOX_PHY_REG_CNT	2
+
+#define TEST_REG_VALUE		0xabcd
+
+static int dm_test_mdio_mux(struct unit_test_state *uts)
+{
+	struct uclass *uc;
+	struct udevice *mux;
+	struct udevice *mdio_ch0, *mdio_ch1, *mdio;
+	struct mdio_ops *ops, *ops_parent;
+	struct mdio_mux_ops *mmops;
+	u16 reg;
+
+	ut_assertok(uclass_get(UCLASS_MDIO_MUX, &uc));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO_MUX, "mdio-mux-test",
+					      &mux));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-ch-test at 0",
+					      &mdio_ch0));
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-ch-test at 1",
+					      &mdio_ch1));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &mdio));
+
+	ops = mdio_get_ops(mdio_ch0);
+	ut_assertnonnull(ops);
+	ut_assertnonnull(ops->read);
+	ut_assertnonnull(ops->write);
+
+	mmops = mdio_mux_get_ops(mux);
+	ut_assertnonnull(mmops);
+	ut_assertnonnull(mmops->select);
+
+	ops_parent = mdio_get_ops(mdio);
+	ut_assertnonnull(ops);
+	ut_assertnonnull(ops->read);
+
+	/*
+	 * mux driver sets last register on the emulated PHY whenever a group
+	 * is selected to the selection #.  Just reading that register from
+	 * either of the child buses should return the id of the child bus
+	 */
+	reg = ops->read(mdio_ch0, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, 0);
+
+	reg = ops->read(mdio_ch1, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, 1);
+
+	mmops->select(mux, MDIO_MUX_SELECT_NONE, 5);
+	reg = ops_parent->read(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, 5);
+
+	mmops->deselect(mux, 5);
+	reg = ops_parent->read(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, (u16)MDIO_MUX_SELECT_NONE);
+
+	return 0;
+}
+
+DM_TEST(dm_test_mdio_mux, DM_TESTF_SCAN_FDT);
-- 
2.17.1

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

* [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class
  2019-06-18 14:58 [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Alexandru Marginean
                   ` (2 preceding siblings ...)
  2019-06-18 14:58 ` [U-Boot] [PATCH 4/4 v3] test: dm: add a test for MDIO MUX DM uclass Alexandru Marginean
@ 2019-07-08  7:40 ` Bin Meng
  2019-07-09 23:49 ` Joe Hershberger
  4 siblings, 0 replies; 12+ messages in thread
From: Bin Meng @ 2019-07-08  7:40 UTC (permalink / raw)
  To: u-boot

On Tue, Jun 18, 2019 at 10:58 PM Alexandru Marginean
<alexandru.marginean@nxp.com> wrote:
>
> Adds a class for MDIO MUXes, which control access to a series of
> downstream child MDIOs.
> MDIO MUX drivers are required to implement a select function used to switch
> between child buses.
> MUX children are registered as MDIO buses and they can be used just like
> regular MDIOs.
>
> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
> ---
>
> Changes in v2:
>         - no change
> Changes in v3:
>         - no change, just fighting with the email server
>
>  drivers/net/Kconfig    |  12 +++
>  include/dm/uclass-id.h |   1 +
>  include/miiphy.h       |  20 ++++
>  net/Makefile           |   1 +
>  net/mdio-mux-uclass.c  | 232 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 266 insertions(+)
>  create mode 100644 net/mdio-mux-uclass.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 635f8d72c2..0dc26ac254 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -24,6 +24,18 @@ config DM_MDIO
>           This is currently implemented in net/mdio-uclass.c
>           Look in include/miiphy.h for details.
>
> +config DM_MDIO_MUX
> +       bool "Enable Driver Model for MDIO MUX devices"
> +       depends on DM_MDIO
> +       help
> +         Enable driver model for MDIO MUX devices
> +
> +         Adds UCLASS_MDIO_MUX DM class supporting MDIO MUXes.  Useful for
> +         systems that support DM_MDIO and integrate one or multiple muxes on
> +         the MDIO bus.
> +         This is currently implemented in net/mdio-mux-uclass.c
> +         Look in include/miiphy.h for details.
> +
>  config MDIO_SANDBOX
>         depends on DM_MDIO && SANDBOX
>         default y
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 90667e62cf..b859a9ec04 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -59,6 +59,7 @@ enum uclass_id {
>         UCLASS_MAILBOX,         /* Mailbox controller */
>         UCLASS_MASS_STORAGE,    /* Mass storage device */
>         UCLASS_MDIO,            /* MDIO bus */
> +       UCLASS_MDIO_MUX,        /* MDIO MUX/switch */
>         UCLASS_MISC,            /* Miscellaneous device */
>         UCLASS_MMC,             /* SD / MMC card or chip */
>         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
> diff --git a/include/miiphy.h b/include/miiphy.h
> index e6dd441983..9b97d09f18 100644
> --- a/include/miiphy.h
> +++ b/include/miiphy.h
> @@ -167,4 +167,24 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
>
>  #endif
>
> +#ifdef CONFIG_DM_MDIO_MUX
> +
> +/* indicates none of the child buses is selected */
> +#define MDIO_MUX_SELECT_NONE   -1
> +
> +/**
> + * struct mdio_mux_ops - MDIO MUX operations
> + *
> + * @select: Selects a child bus
> + * @deselect: Clean up selection.  Optional, can be NULL
> + */
> +struct mdio_mux_ops {
> +       int (*select)(struct udevice *mux, int cur, int sel);
> +       int (*deselect)(struct udevice *mux, int sel);
> +};
> +
> +#define mdio_mux_get_ops(dev) ((struct mdio_mux_ops *)(dev)->driver->ops)
> +
> +#endif
> +
>  #endif
> diff --git a/net/Makefile b/net/Makefile
> index 6251ff3991..826544f05f 100644
> --- a/net/Makefile
> +++ b/net/Makefile
> @@ -16,6 +16,7 @@ else
>  obj-$(CONFIG_NET)      += eth_legacy.o
>  endif
>  obj-$(CONFIG_DM_MDIO)  += mdio-uclass.o
> +obj-$(CONFIG_DM_MDIO_MUX) += mdio-mux-uclass.o
>  obj-$(CONFIG_NET)      += eth_common.o
>  obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
>  obj-$(CONFIG_NET)      += net.o
> diff --git a/net/mdio-mux-uclass.c b/net/mdio-mux-uclass.c
> new file mode 100644
> index 0000000000..e3fe12a531
> --- /dev/null
> +++ b/net/mdio-mux-uclass.c
> @@ -0,0 +1,232 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2019
> + * Alex Marginean, NXP
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <miiphy.h>
> +#include <dm/device-internal.h>
> +#include <dm/uclass-internal.h>
> +#include <dm/lists.h>
> +
> +#define MDIO_MUX_CHILD_DRV_NAME        "mdio-mux-bus-drv"
> +
> +/**
> + * struct mdio_mux_perdev_priv - Per-device class data for MDIO MUX DM
> + *
> + * @parent_mdio: Parent DM MDIO device, this is called for actual MDIO I/O after
> + *               setting up the mux.  Typically this is a real MDIO device,
> + *               unless there are cascaded muxes.
> + * @selected:    Current child bus selection.  Defaults to -1
> + */
> +struct mdio_mux_perdev_priv {
> +       struct udevice *mdio_parent;
> +       int selected;
> +};
> +
> +/*
> + * This source file uses three types of devices, as follows:
> + * - mux is the hardware MDIO MUX which selects between the existing child MDIO
> + * buses, this is the device relevant for MDIO MUX class of drivers.
> + * - ch is a child MDIO bus, this is just a representation of an mux selection,

nits: a mux selection

> + * not a real piece of hardware.
> + * - mdio_parent is the actual MDIO bus called to perform reads/writes  after

nits: 2 spaces before "after"

> + * the MUX is configured.  Typically this is a real MDIO device, unless there
> + * are cascaded muxes.
> + */
> +

[snip]

Other than above,
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Regards,
Bin

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

* [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes
  2019-06-18 14:58 ` [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes Alexandru Marginean
@ 2019-07-08  7:40   ` Bin Meng
  2019-07-08 14:33     ` Alex Marginean
  0 siblings, 1 reply; 12+ messages in thread
From: Bin Meng @ 2019-07-08  7:40 UTC (permalink / raw)
  To: u-boot

On Tue, Jun 18, 2019 at 10:58 PM Alexandru Marginean
<alexandru.marginean@nxp.com> wrote:
>
> Adds a short bindings document describing the expected structure of a MDIO
> MUX dts node.  This is based on Linux binding and the example is in fact
> copied from there.
>
> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
> ---
>
> Changes in v2:
>         - no change
> Changes in v3:
>         - no change, just fighting with the email server
>
>  doc/device-tree-bindings/net/mdio-mux.txt | 61 +++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
>  create mode 100644 doc/device-tree-bindings/net/mdio-mux.txt
>
> diff --git a/doc/device-tree-bindings/net/mdio-mux.txt b/doc/device-tree-bindings/net/mdio-mux.txt
> new file mode 100644
> index 0000000000..fdf817fd93
> --- /dev/null
> +++ b/doc/device-tree-bindings/net/mdio-mux.txt
> @@ -0,0 +1,61 @@
> +The expected structure of an MDIO MUX device tree node is described here.  This
> +is heavily based on current Linux specification.
> +The MDIO buses downstream of the MUX should be described in the device tree as
> +child nodes as indicated below.
> +
> +Required properties:
> +mdio-parent-bus = a phandle to the MDIO bus used to perform actual I/O.  This is
> +                  typically a real MDIO device, unless there are cascaded MUXes.

In Linux, "mdio-parent-bus" is optional, but in U-Boot this is required?

> +#address-cells = <1>, each MDIO group is identified by one 32b value.
> +#size-cells = <0>
> +
> +Other properties:
> +The properties described here are sufficient for MDIO MUX DM class code, but
> +MUX drivers may define additional properties, either required or optional.
> +
> +Required properties in child nodes:
> +reg = value to be configured on the MUX to select the respective downstream
> +      MDIO.
> +
> +Child nodes should normally contain PHY nodes, referenced by phandle from
> +ethernet nodes of the eth interfaces using these PHYs.
> +
> +Example structure, extracted from Linux bindings document:
> +
> +       /* The parent MDIO bus. */
> +       smi1: mdio at 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.
> +        */

It looks the example is not complete, which makes it hard for people
to understand (ie: only bus 2 is listed below) without reading the
Linux bindings doc.

> +       mdio-mux {
> +               compatible = "mdio-mux-gpio";
> +               gpios = <&gpio1 3 0>, <&gpio1 4 0>;
> +               mdio-parent-bus = <&smi1>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               mdio at 2 {
> +                       reg = <2>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +
> +                       phy11: ethernet-phy at 1 {
> +                               reg = <1>;
> +                               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 */
> +                       };
> +               };
> +       };
> +

Regards,
Bin

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

* [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY
  2019-06-18 14:58 ` [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY Alexandru Marginean
@ 2019-07-08  7:40   ` Bin Meng
  2019-07-09 23:54   ` Joe Hershberger
  1 sibling, 0 replies; 12+ messages in thread
From: Bin Meng @ 2019-07-08  7:40 UTC (permalink / raw)
  To: u-boot

On Tue, Jun 18, 2019 at 10:58 PM Alexandru Marginean
<alexandru.marginean@nxp.com> wrote:
>
> This 2nd register is used by the follow-up MDIO MUX test.
>
> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
> ---
>
> Changes in v2:
>         - no change
> Changes in v3:
>         - no change, just fighting with the email server
>
>  drivers/net/mdio_sandbox.c | 16 +++++++++-------
>  test/dm/mdio.c             |  3 +++
>  2 files changed, 12 insertions(+), 7 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

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

* [U-Boot] [PATCH 4/4 v3] test: dm: add a test for MDIO MUX DM uclass
  2019-06-18 14:58 ` [U-Boot] [PATCH 4/4 v3] test: dm: add a test for MDIO MUX DM uclass Alexandru Marginean
@ 2019-07-08  7:40   ` Bin Meng
  2019-07-08 15:43     ` Alex Marginean
  0 siblings, 1 reply; 12+ messages in thread
From: Bin Meng @ 2019-07-08  7:40 UTC (permalink / raw)
  To: u-boot

On Tue, Jun 18, 2019 at 10:58 PM Alexandru Marginean
<alexandru.marginean@nxp.com> wrote:
>
> Adds a test using a makeshift MDIO MUX.  The test is based on the existing
> MDIO test.  It uses the last emulated PHY register to verify MUX selection.
>
> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
> ---
>
> Changes in v2:
>         - no change
> Changes in v3:
>         - no change, just fighting with the email server
>
>  arch/Kconfig                   |  1 +
>  arch/sandbox/dts/test.dts      | 21 +++++++-
>  drivers/net/Kconfig            | 10 ++++
>  drivers/net/Makefile           |  1 +
>  drivers/net/mdio_mux_sandbox.c | 97 ++++++++++++++++++++++++++++++++++
>  test/dm/Makefile               |  1 +
>  test/dm/mdio_mux.c             | 80 ++++++++++++++++++++++++++++
>  7 files changed, 210 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/mdio_mux_sandbox.c
>  create mode 100644 test/dm/mdio_mux.c
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index 1e62a7615d..1a0f1ab8a7 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -122,6 +122,7 @@ config SANDBOX
>         imply PCH
>         imply PHYLIB
>         imply DM_MDIO
> +       imply DM_MDIO_MUX
>
>  config SH
>         bool "SuperH architecture"
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index dd50a951a8..a05e437abf 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -808,7 +808,26 @@
>                 dma-names = "m2m", "tx0", "rx0";
>         };
>
> -       mdio-test {
> +       /*
> +        * keep mdio-mux ahead of mdio, u-boot doesn't do reference count on

nits: U-Boot

> +        * these devices and we don't want mdio-parent-bus to be released before
> +        * the mux.

I did not get it why there is a ordering issue? Could you please elaborate?

> +        */
> +       mdio-mux-test {
> +               compatible = "sandbox,mdio-mux";
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               mdio-parent-bus = <&mdio>;
> +
> +               mdio-ch-test at 0 {
> +                       reg = <0>;
> +               };
> +               mdio-ch-test at 1 {
> +                       reg = <1>;
> +               };
> +       };
> +

Test codes looks good to me though.

Regards,
Bin

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

* [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes
  2019-07-08  7:40   ` Bin Meng
@ 2019-07-08 14:33     ` Alex Marginean
  0 siblings, 0 replies; 12+ messages in thread
From: Alex Marginean @ 2019-07-08 14:33 UTC (permalink / raw)
  To: u-boot

On 7/8/2019 10:40 AM, Bin Meng wrote:
> On Tue, Jun 18, 2019 at 10:58 PM Alexandru Marginean
> <alexandru.marginean@nxp.com> wrote:
>>
>> Adds a short bindings document describing the expected structure of a MDIO
>> MUX dts node.  This is based on Linux binding and the example is in fact
>> copied from there.
>>
>> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
>> ---
>>
>> Changes in v2:
>>          - no change
>> Changes in v3:
>>          - no change, just fighting with the email server
>>
>>   doc/device-tree-bindings/net/mdio-mux.txt | 61 +++++++++++++++++++++++
>>   1 file changed, 61 insertions(+)
>>   create mode 100644 doc/device-tree-bindings/net/mdio-mux.txt
>>
>> diff --git a/doc/device-tree-bindings/net/mdio-mux.txt b/doc/device-tree-bindings/net/mdio-mux.txt
>> new file mode 100644
>> index 0000000000..fdf817fd93
>> --- /dev/null
>> +++ b/doc/device-tree-bindings/net/mdio-mux.txt
>> @@ -0,0 +1,61 @@
>> +The expected structure of an MDIO MUX device tree node is described here.  This
>> +is heavily based on current Linux specification.
>> +The MDIO buses downstream of the MUX should be described in the device tree as
>> +child nodes as indicated below.
>> +
>> +Required properties:
>> +mdio-parent-bus = a phandle to the MDIO bus used to perform actual I/O.  This is
>> +                  typically a real MDIO device, unless there are cascaded MUXes.
> 
> In Linux, "mdio-parent-bus" is optional, but in U-Boot this is required?

That was my plan, making it optional requires some extra code that I
didn't put in.  I could put that code in but it would be unused for now.
I can do it, or the change can be done whenever someone adds a MUX which
is driven over parent MDIO.

>> +#address-cells = <1>, each MDIO group is identified by one 32b value.
>> +#size-cells = <0>
>> +
>> +Other properties:
>> +The properties described here are sufficient for MDIO MUX DM class code, but
>> +MUX drivers may define additional properties, either required or optional.
>> +
>> +Required properties in child nodes:
>> +reg = value to be configured on the MUX to select the respective downstream
>> +      MDIO.
>> +
>> +Child nodes should normally contain PHY nodes, referenced by phandle from
>> +ethernet nodes of the eth interfaces using these PHYs.
>> +
>> +Example structure, extracted from Linux bindings document:
>> +
>> +       /* The parent MDIO bus. */
>> +       smi1: mdio at 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.
>> +        */
> 
> It looks the example is not complete, which makes it hard for people
> to understand (ie: only bus 2 is listed below) without reading the
> Linux bindings doc.

I did chop it down to the piece I though it's relevant, I can pull in
the full example.  Or I can replace it with the definition of the device
I'm working on, that way the example is practical.  'mdio-mux-gpio' is
not something I was planning to add to u-boot now.

Thank you!
Alex

> 
>> +       mdio-mux {
>> +               compatible = "mdio-mux-gpio";
>> +               gpios = <&gpio1 3 0>, <&gpio1 4 0>;
>> +               mdio-parent-bus = <&smi1>;
>> +               #address-cells = <1>;
>> +               #size-cells = <0>;
>> +
>> +               mdio at 2 {
>> +                       reg = <2>;
>> +                       #address-cells = <1>;
>> +                       #size-cells = <0>;
>> +
>> +                       phy11: ethernet-phy at 1 {
>> +                               reg = <1>;
>> +                               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 */
>> +                       };
>> +               };
>> +       };
>> +
> 
> Regards,
> Bin
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
> 

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

* [U-Boot] [PATCH 4/4 v3] test: dm: add a test for MDIO MUX DM uclass
  2019-07-08  7:40   ` Bin Meng
@ 2019-07-08 15:43     ` Alex Marginean
  0 siblings, 0 replies; 12+ messages in thread
From: Alex Marginean @ 2019-07-08 15:43 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 7/8/2019 10:40 AM, Bin Meng wrote:
> On Tue, Jun 18, 2019 at 10:58 PM Alexandru Marginean
> <alexandru.marginean@nxp.com> wrote:
>>
>> Adds a test using a makeshift MDIO MUX.  The test is based on the existing
>> MDIO test.  It uses the last emulated PHY register to verify MUX selection.
>>
>> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
>> ---
>>
>> Changes in v2:
>>          - no change
>> Changes in v3:
>>          - no change, just fighting with the email server
>>
>>   arch/Kconfig                   |  1 +
>>   arch/sandbox/dts/test.dts      | 21 +++++++-
>>   drivers/net/Kconfig            | 10 ++++
>>   drivers/net/Makefile           |  1 +
>>   drivers/net/mdio_mux_sandbox.c | 97 ++++++++++++++++++++++++++++++++++
>>   test/dm/Makefile               |  1 +
>>   test/dm/mdio_mux.c             | 80 ++++++++++++++++++++++++++++
>>   7 files changed, 210 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/net/mdio_mux_sandbox.c
>>   create mode 100644 test/dm/mdio_mux.c
>>
>> diff --git a/arch/Kconfig b/arch/Kconfig
>> index 1e62a7615d..1a0f1ab8a7 100644
>> --- a/arch/Kconfig
>> +++ b/arch/Kconfig
>> @@ -122,6 +122,7 @@ config SANDBOX
>>          imply PCH
>>          imply PHYLIB
>>          imply DM_MDIO
>> +       imply DM_MDIO_MUX
>>
>>   config SH
>>          bool "SuperH architecture"
>> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
>> index dd50a951a8..a05e437abf 100644
>> --- a/arch/sandbox/dts/test.dts
>> +++ b/arch/sandbox/dts/test.dts
>> @@ -808,7 +808,26 @@
>>                  dma-names = "m2m", "tx0", "rx0";
>>          };
>>
>> -       mdio-test {
>> +       /*
>> +        * keep mdio-mux ahead of mdio, u-boot doesn't do reference count on
> 
> nits: U-Boot
> 
>> +        * these devices and we don't want mdio-parent-bus to be released before
>> +        * the mux.
> 
> I did not get it why there is a ordering issue? Could you please elaborate?

I can try.  At the end of 'ut dm' classes and devices are removed, which
by itself is fine.  When MDIO buses are removed there's a reset issued,
which is also fine.  There is no explicit dependency between the mux and
parent MDIO though, not described in the way that the code removing
these devices would understand.  If parent MDIO is removed first, then
removal/reset of mux child MDIOs triggers a new probe of the parent MDIO
device to execute reset on child MDIO buses.  This leaves parent MDIO
probed at the end of the test and test-main doesn't like that as it
can't remove the MDIO class with parent MDIO left active.  The call
sequence looks like this:

Parent MDIO dev is removed first:
dm_mdio_pre_remove: mdio-test
mdio_sandbox_reset: mdio-test
mdio_sandbox_remove: mdio-test

Then MUX is removed, along with its children:
dm_mdio_pre_remove: mdio-ch-test at 0
mmux_reset: mdio-mux-test/mdio-ch-test at 0
mdio_sandbox_probe: mdio-test
dm_mdio_post_probe: mdio-test
mdio_sandbox_reset: mdio-test
dm_mdio_pre_remove: mdio-ch-test at 1
mmux_reset: mdio-mux-test/mdio-ch-test at 1
mdio_sandbox_reset: mdio-test
test/dm/test-main.c:72, dm_test_destroy(): 0 == uclass_destroy(uc): 
Expected 0, got -22

I think I can add a uclass device post_remove API and use that in MUX
uclass to remove parent MDIO device, but that looks like an unsafe thing
to do.  There is no way for the MUX uclass code to know whether any
other piece of software still holds a reference to parent MDIO device.

I could skip calling remove for child MDIOs during removal of the MUX,
to avoid probing parent MDIO again, but that looks like a hack.

The fix to the general problem would involve some form of reference
counting per device, but it doesn't make sense to add that just for a
MDIO MUX test.  In practice not removing a device that's no longer used
isn't a big deal for u-boot I think.

Keeping dts nodes in that order works, but it is also a hack, it's
pretty obscure, I'm not super happy with that either.

Any suggestions?

Thank you!
Alex
> 
>> +        */
>> +       mdio-mux-test {
>> +               compatible = "sandbox,mdio-mux";
>> +               #address-cells = <1>;
>> +               #size-cells = <0>;
>> +               mdio-parent-bus = <&mdio>;
>> +
>> +               mdio-ch-test at 0 {
>> +                       reg = <0>;
>> +               };
>> +               mdio-ch-test at 1 {
>> +                       reg = <1>;
>> +               };
>> +       };
>> +
> 
> Test codes looks good to me though.
> 
> Regards,
> Bin
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
> 

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

* [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class
  2019-06-18 14:58 [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Alexandru Marginean
                   ` (3 preceding siblings ...)
  2019-07-08  7:40 ` [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Bin Meng
@ 2019-07-09 23:49 ` Joe Hershberger
  4 siblings, 0 replies; 12+ messages in thread
From: Joe Hershberger @ 2019-07-09 23:49 UTC (permalink / raw)
  To: u-boot

On Tue, Jun 18, 2019 at 10:01 AM Alexandru Marginean
<alexandru.marginean@nxp.com> wrote:
>
> Adds a class for MDIO MUXes, which control access to a series of
> downstream child MDIOs.
> MDIO MUX drivers are required to implement a select function used to switch
> between child buses.
> MUX children are registered as MDIO buses and they can be used just like
> regular MDIOs.
>
> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>

After addressing Bin's comments,

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

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

* [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY
  2019-06-18 14:58 ` [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY Alexandru Marginean
  2019-07-08  7:40   ` Bin Meng
@ 2019-07-09 23:54   ` Joe Hershberger
  1 sibling, 0 replies; 12+ messages in thread
From: Joe Hershberger @ 2019-07-09 23:54 UTC (permalink / raw)
  To: u-boot

On Tue, Jun 18, 2019 at 10:01 AM Alexandru Marginean
<alexandru.marginean@nxp.com> wrote:
>
> This 2nd register is used by the follow-up MDIO MUX test.
>
> Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

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

end of thread, other threads:[~2019-07-09 23:54 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-18 14:58 [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Alexandru Marginean
2019-06-18 14:58 ` [U-Boot] [PATCH 2/4 v3] doc: bindings: Add description for MDIO MUX dts nodes Alexandru Marginean
2019-07-08  7:40   ` Bin Meng
2019-07-08 14:33     ` Alex Marginean
2019-06-18 14:58 ` [U-Boot] [PATCH 3/4 v3] test: dm_mdio: add a 2nd register to the emulated PHY Alexandru Marginean
2019-07-08  7:40   ` Bin Meng
2019-07-09 23:54   ` Joe Hershberger
2019-06-18 14:58 ` [U-Boot] [PATCH 4/4 v3] test: dm: add a test for MDIO MUX DM uclass Alexandru Marginean
2019-07-08  7:40   ` Bin Meng
2019-07-08 15:43     ` Alex Marginean
2019-07-08  7:40 ` [U-Boot] [PATCH 1/4 v3] net: add MDIO_MUX DM class Bin Meng
2019-07-09 23:49 ` Joe Hershberger

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.