test: dm: add a test for MDIO MUX DM uclass
authorAlex Marginean <alexandru.marginean@nxp.com>
Fri, 12 Jul 2019 07:13:53 +0000 (10:13 +0300)
committerJoe Hershberger <joe.hershberger@ni.com>
Thu, 18 Jul 2019 21:37:13 +0000 (16:37 -0500)
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>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
arch/Kconfig
arch/sandbox/dts/test.dts
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/mdio_mux_sandbox.c [new file with mode: 0644]
test/dm/Makefile
test/dm/mdio_mux.c [new file with mode: 0644]

index a946af8..949eb28 100644 (file)
@@ -125,6 +125,7 @@ config SANDBOX
        imply PCH
        imply PHYLIB
        imply DM_MDIO
+       imply DM_MDIO_MUX
 
 config SH
        bool "SuperH architecture"
index 531c1af..a085676 100644 (file)
                dma-names = "m2m", "tx0", "rx0";
        };
 
-       mdio-test {
+       /*
+        * keep mdio-mux ahead of mdio so that the mux is removed first at the
+        * end of the test.  If parent mdio is removed first, clean-up of the
+        * mux will trigger a 2nd probe of parent-mdio, leaving parent-mdio
+        * active at the end of the test.  That it turn doesn't allow the mdio
+        * class to be destroyed, triggering an error.
+        */
+       mdio-mux-test {
+               compatible = "sandbox,mdio-mux";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               mdio-parent-bus = <&mdio>;
+
+               mdio-ch-test@0 {
+                       reg = <0>;
+               };
+               mdio-ch-test@1 {
+                       reg = <1>;
+               };
+       };
+
+       mdio: mdio-test {
                compatible = "sandbox,mdio";
        };
 };
index 0dc26ac..403df5e 100644 (file)
@@ -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
index 4003842..3c473b2 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_LAN91C96) += lan91c96.o
 obj-$(CONFIG_LPC32XX_ETH) += lpc32xx_eth.o
 obj-$(CONFIG_MACB) += macb.o
 obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
+obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
 obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
 obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o
 obj-$(CONFIG_MVGBE) += mvgbe.o
diff --git a/drivers/net/mdio_mux_sandbox.c b/drivers/net/mdio_mux_sandbox.c
new file mode 100644 (file)
index 0000000..3dba4d1
--- /dev/null
@@ -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),
+};
index 6a36cc0..7b4dd6e 100644 (file)
@@ -63,4 +63,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 (file)
index 0000000..f962e09
--- /dev/null
@@ -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@0",
+                                             &mdio_ch0));
+       ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-ch-test@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);