[PATCH v4 0/7] drivers: Add a framework for MUX drivers

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v4 0/7] drivers: Add a framework for MUX drivers

Pratyush Yadav
Hi,

This series is a re-roll of Jean-Jacques' earlier effort. It adds a new
minimalistic subsystem that handles multiplexer controllers. It provides
the same API as Linux and mux drivers should be portable with a minimum
effort. This series also includes a port of the Linux's mmio-mux driver
and an emulated mux driver for sandbox testing.

Travis CI run: https://travis-ci.org/github/prati0100/uboot/builds/736133605

Changes in v4:
- Drop the call to sandbox_set_enable_memio(). Use an emulated mux
  driver to test the default state instead.

Other changes are mentioned in individual patches.

Changes in v3:
- Add a new command called 'mux' that allows listing, selecting, and
  deselecting muxes on the fly.
- Move call to dm_mux_init() to initr_dm_devices().
- Enable mmio operations in sandbox on board_init() to dm_mux_init() can
  initialize muxes to their idle state and allow the tests to pass.
- Add help for CONFIG_MULTIPLEXER.
- Change dev_err() in mmio_mux_probe() to log_msg_ret() or log_err().
- Add comments on static functions in mux-class.c
- Make mux_uclass_post_probe() static.
- Make dm_mux_init() return an integer to signal failure.
- Change ifdef of mux-internal.h to _HUX_INTERNAL_H.
- Remove unused include from mux-internal.h
- Remove comments for non-existent members in struct mux_chip.
- Add missing comments for some members in struct mux_control.
- Add missing comments for some functions in mux.h
- Split up the mux_mmio test into two parts. More would lead to a lot of
  boilerplate.
- Change ut_assertok(IS_ERR(ptr)) to ut_assertok_ptr(ptr).
- Fix mis-spellings and capitalize comments.
- Rebase on latest master.

Changes in v2:
- Fixed warning in mux_of_xlate_default()
- Improved documentation
- Fixed SPL build
- insert the mux initialization in init_sequence_r[], just before the
console is initialized as its serial port may be muxed
- moved the definition of dm_mux_init() in this commit
- Call sandbox_set_enable_memio(true) before running the test

Jean-Jacques Hiblot (4):
  drivers: Add a new framework for multiplexer devices
  dm: board: complete the initialization of the muxes in initr_dm()
  drivers: mux: mmio-based syscon mux controller
  test: Add tests for the multiplexer framework

Pratyush Yadav (3):
  Kconfig: Increase the pre-relocation memory
  cmd: Add a mux command
  test: mux-cmd: Add tests for the 'mux' command

 Kconfig                       |   2 +-
 arch/sandbox/dts/test.dts     |  33 ++++
 cmd/Kconfig                   |   6 +
 cmd/Makefile                  |   1 +
 cmd/mux.c                     | 183 +++++++++++++++++++
 common/board_r.c              |  12 ++
 configs/sandbox_defconfig     |   3 +
 drivers/Kconfig               |   2 +
 drivers/Makefile              |   1 +
 drivers/mux/Kconfig           |  25 +++
 drivers/mux/Makefile          |   7 +
 drivers/mux/mmio.c            | 141 ++++++++++++++
 drivers/mux/mux-uclass.c      | 334 ++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h        |   1 +
 include/dt-bindings/mux/mux.h |  17 ++
 include/mux-internal.h        | 109 +++++++++++
 include/mux.h                 | 159 ++++++++++++++++
 test/dm/Makefile              |   3 +
 test/dm/mux-cmd.c             | 177 ++++++++++++++++++
 test/dm/mux-emul.c            | 105 +++++++++++
 test/dm/mux-mmio.c            | 138 ++++++++++++++
 21 files changed, 1458 insertions(+), 1 deletion(-)
 create mode 100644 cmd/mux.c
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mmio.c
 create mode 100644 drivers/mux/mux-uclass.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/mux-internal.h
 create mode 100644 include/mux.h
 create mode 100644 test/dm/mux-cmd.c
 create mode 100644 test/dm/mux-emul.c
 create mode 100644 test/dm/mux-mmio.c

--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 1/7] drivers: Add a new framework for multiplexer devices

Pratyush Yadav
From: Jean-Jacques Hiblot <[hidden email]>

Add a new subsystem that handles multiplexer controllers. The API is the
same as in Linux.

Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
Reviewed-by: Simon Glass <[hidden email]>
Signed-off-by: Pratyush Yadav <[hidden email]>
---

Notes:
    No changes on v4.

 drivers/Kconfig               |   2 +
 drivers/Makefile              |   1 +
 drivers/mux/Kconfig           |  11 ++
 drivers/mux/Makefile          |   6 +
 drivers/mux/mux-uclass.c      | 311 ++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h        |   1 +
 include/dt-bindings/mux/mux.h |  17 ++
 include/mux-internal.h        | 109 ++++++++++++
 include/mux.h                 | 147 ++++++++++++++++
 9 files changed, 605 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-uclass.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/mux-internal.h
 create mode 100644 include/mux.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 613669cb38..ed8a39c994 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -64,6 +64,8 @@ source "drivers/mmc/Kconfig"
 
 source "drivers/mtd/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 source "drivers/net/Kconfig"
 
 source "drivers/nvme/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9eb51453e5..33f1d536cd 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
 obj-$(CONFIG_$(SPL_TPL_)LED) += led/
 obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
 obj-y += mtd/
+obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux/
 obj-$(CONFIG_$(SPL_TPL_)PCH_SUPPORT) += pch/
 obj-$(CONFIG_$(SPL_TPL_)PCI) += pci/
 obj-$(CONFIG_$(SPL_TPL_)PHY) += phy/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index 0000000000..35c1c5673c
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,11 @@
+menu "Multiplexer drivers"
+
+config MULTIPLEXER
+ bool "Multiplexer Support"
+ depends on DM
+ help
+ The mux framework is a minimalistic subsystem that handles multiplexer
+ controllers. It provides the same API as Linux and mux drivers should
+ be portable with a minimum effort.
+
+endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index 0000000000..351e4363d3
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2019
+# Jean-Jacques Hiblot <[hidden email]>
+
+obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c
new file mode 100644
index 0000000000..3c89e0a389
--- /dev/null
+++ b/drivers/mux/mux-uclass.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Multiplexer subsystem
+ *
+ * Based on the linux multiplexer framework
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ * Author: Peter Rosin <[hidden email]>
+ *
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot <[hidden email]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mux-internal.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dt-bindings/mux/mux.h>
+#include <linux/bug.h>
+
+/*
+ * The idle-as-is "state" is not an actual state that may be selected, it
+ * only implies that the state should not be changed. So, use that state
+ * as indication that the cached state of the multiplexer is unknown.
+ */
+#define MUX_CACHE_UNKNOWN MUX_IDLE_AS_IS
+
+/**
+ * mux_control_ops() - Get the mux_control ops.
+ * @dev: The client device.
+ *
+ * Return: A pointer to the 'mux_control_ops' of the device.
+ */
+static inline const struct mux_control_ops *mux_dev_ops(struct udevice *dev)
+{
+ return (const struct mux_control_ops *)dev->driver->ops;
+}
+
+/**
+ * mux_control_set() - Set the state of the given mux controller.
+ * @mux: A multiplexer control
+ * @state: The new requested state.
+ *
+ * Return: 0 if OK, or a negative error code.
+ */
+static int mux_control_set(struct mux_control *mux, int state)
+{
+ int ret = mux_dev_ops(mux->dev)->set(mux, state);
+
+ mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state;
+
+ return ret;
+}
+
+unsigned int mux_control_states(struct mux_control *mux)
+{
+ return mux->states;
+}
+
+/**
+ * __mux_control_select() - Select the given multiplexer state.
+ * @mux: The mux-control to request a change of state from.
+ * @state: The new requested state.
+ *
+ * Try to set the mux to the requested state. If not, try to revert if
+ * appropriate.
+ */
+static int __mux_control_select(struct mux_control *mux, int state)
+{
+ int ret;
+
+ if (WARN_ON(state < 0 || state >= mux->states))
+ return -EINVAL;
+
+ if (mux->cached_state == state)
+ return 0;
+
+ ret = mux_control_set(mux, state);
+ if (ret >= 0)
+ return 0;
+
+ /* The mux update failed, try to revert if appropriate... */
+ if (mux->idle_state != MUX_IDLE_AS_IS)
+ mux_control_set(mux, mux->idle_state);
+
+ return ret;
+}
+
+int mux_control_select(struct mux_control *mux, unsigned int state)
+{
+ int ret;
+
+ if (mux->in_use)
+ return -EBUSY;
+
+ ret = __mux_control_select(mux, state);
+
+ if (ret < 0)
+ return ret;
+
+ mux->in_use = true;
+
+ return 0;
+}
+
+int mux_control_deselect(struct mux_control *mux)
+{
+ int ret = 0;
+
+ if (mux->idle_state != MUX_IDLE_AS_IS &&
+    mux->idle_state != mux->cached_state)
+ ret = mux_control_set(mux, mux->idle_state);
+
+ mux->in_use = false;
+
+ return ret;
+}
+
+static int mux_of_xlate_default(struct mux_chip *mux_chip,
+ struct ofnode_phandle_args *args,
+ struct mux_control **muxp)
+{
+ struct mux_control *mux;
+ int id;
+
+ log_debug("%s(muxp=%p)\n", __func__, muxp);
+
+ if (args->args_count > 1) {
+ debug("Invaild args_count: %d\n", args->args_count);
+ return -EINVAL;
+ }
+
+ if (args->args_count)
+ id = args->args[0];
+ else
+ id = 0;
+
+ if (id >= mux_chip->controllers) {
+ dev_err(dev, "bad mux controller %u specified in %s\n",
+ id, ofnode_get_name(args->node));
+ return -ERANGE;
+ }
+
+ mux = &mux_chip->mux[id];
+ mux->id = id;
+ *muxp = mux;
+ return 0;
+}
+
+/**
+ * mux_get_by_indexed_prop() - Get a mux control by integer index
+ * @dev: The client device.
+ * @prop_name: Name of the device tree property.
+ * @index: The index of the mux to get
+ * @mux: A pointer to the 'mux_control' struct to initialize.
+ *
+ * Return: 0 of OK, -errno otherwise.
+ */
+static int mux_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
+   int index, struct mux_control **mux)
+{
+ int ret;
+ struct ofnode_phandle_args args;
+ struct udevice *dev_mux;
+ const struct mux_control_ops *ops;
+ struct mux_chip *mux_chip;
+
+ log_debug("%s(dev=%p, index=%d, mux=%p)\n", __func__, dev, index, mux);
+
+ ret = dev_read_phandle_with_args(dev, prop_name, "#mux-control-cells",
+ 0, index, &args);
+ if (ret) {
+ debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+      __func__, ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_ofnode(UCLASS_MUX, args.node, &dev_mux);
+ if (ret) {
+ debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
+      __func__, ret);
+ return ret;
+ }
+
+ mux_chip = dev_get_uclass_priv(dev_mux);
+
+ ops = mux_dev_ops(dev_mux);
+ if (ops->of_xlate)
+ ret = ops->of_xlate(mux_chip, &args, mux);
+ else
+ ret = mux_of_xlate_default(mux_chip, &args, mux);
+ if (ret) {
+ debug("of_xlate() failed: %d\n", ret);
+ return ret;
+ }
+ (*mux)->dev = dev_mux;
+
+ return 0;
+}
+
+int mux_get_by_index(struct udevice *dev, int index, struct mux_control **mux)
+{
+ return mux_get_by_indexed_prop(dev, "mux-controls", index, mux);
+}
+
+int mux_control_get(struct udevice *dev, const char *name,
+    struct mux_control **mux)
+{
+ int index;
+
+ debug("%s(dev=%p, name=%s, mux=%p)\n", __func__, dev, name, mux);
+
+ index = dev_read_stringlist_search(dev, "mux-control-names", name);
+ if (index < 0) {
+ debug("fdt_stringlist_search() failed: %d\n", index);
+ return index;
+ }
+
+ return mux_get_by_index(dev, index, mux);
+}
+
+void mux_control_put(struct mux_control *mux)
+{
+ mux_control_deselect(mux);
+}
+
+/**
+ * devm_mux_control_release() - Release the given managed mux.
+ * @dev: The client device.
+ * @res: Pointer to the mux to be released.
+ *
+ * This function is called by devres to release the mux. It reverses the
+ * effects of mux_control_get().
+ */
+static void devm_mux_control_release(struct udevice *dev, void *res)
+{
+ mux_control_put(*(struct mux_control **)res);
+}
+
+struct mux_control *devm_mux_control_get(struct udevice *dev, const char *id)
+{
+ int rc;
+ struct mux_control **mux;
+
+ mux = devres_alloc(devm_mux_control_release,
+   sizeof(struct mux_control *), __GFP_ZERO);
+ if (unlikely(!mux))
+ return ERR_PTR(-ENOMEM);
+
+ rc = mux_control_get(dev, id, mux);
+ if (rc)
+ return ERR_PTR(rc);
+
+ devres_add(dev, mux);
+ return *mux;
+}
+
+int mux_alloc_controllers(struct udevice *dev, unsigned int controllers)
+{
+ int i;
+ struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
+
+ mux_chip->mux = devm_kmalloc(dev,
+     sizeof(struct mux_control) * controllers,
+     __GFP_ZERO);
+ if (!mux_chip->mux)
+ return -ENOMEM;
+
+ mux_chip->controllers = controllers;
+
+ for (i = 0; i < mux_chip->controllers; ++i) {
+ struct mux_control *mux = &mux_chip->mux[i];
+
+ mux->dev = dev;
+ mux->cached_state = MUX_CACHE_UNKNOWN;
+ mux->idle_state = MUX_IDLE_AS_IS;
+ mux->in_use = false;
+ mux->id = i;
+ }
+
+ return 0;
+}
+
+static int mux_uclass_post_probe(struct udevice *dev)
+{
+ int i, ret;
+ struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
+
+ /* Set all mux controllers to their idle state. */
+ for (i = 0; i < mux_chip->controllers; ++i) {
+ struct mux_control *mux = &mux_chip->mux[i];
+
+ if (mux->idle_state == mux->cached_state)
+ continue;
+
+ ret = mux_control_set(mux, mux->idle_state);
+ if (ret < 0) {
+ dev_err(&mux_chip->dev, "unable to set idle state\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+UCLASS_DRIVER(mux) = {
+ .id = UCLASS_MUX,
+ .name = "mux",
+ .post_probe = mux_uclass_post_probe,
+ .per_device_auto_alloc_size = sizeof(struct mux_chip),
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 88f10c4622..17542de2f3 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -71,6 +71,7 @@ enum uclass_id {
  UCLASS_MMC, /* SD / MMC card or chip */
  UCLASS_MOD_EXP, /* RSA Mod Exp device */
  UCLASS_MTD, /* Memory Technology Device (MTD) device */
+ UCLASS_MUX, /* Multiplexer device */
  UCLASS_NOP, /* No-op devices */
  UCLASS_NORTHBRIDGE, /* Intel Northbridge / SDRAM controller */
  UCLASS_NVME, /* NVM Express device */
diff --git a/include/dt-bindings/mux/mux.h b/include/dt-bindings/mux/mux.h
new file mode 100644
index 0000000000..042719218d
--- /dev/null
+++ b/include/dt-bindings/mux/mux.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for most Multiplexer bindings.
+ *
+ * Most Multiplexer bindings specify an idle state. In most cases, the
+ * the multiplexer can be left as is when idle, and in some cases it can
+ * disconnect the input/output and leave the multiplexer in a high
+ * impedance state.
+ */
+
+#ifndef _DT_BINDINGS_MUX_MUX_H
+#define _DT_BINDINGS_MUX_MUX_H
+
+#define MUX_IDLE_AS_IS      (-1)
+#define MUX_IDLE_DISCONNECT (-2)
+
+#endif
diff --git a/include/mux-internal.h b/include/mux-internal.h
new file mode 100644
index 0000000000..93e3a5cdd7
--- /dev/null
+++ b/include/mux-internal.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Based on the linux multiplexer framework
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ * Author: Peter Rosin <[hidden email]>
+ *
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot <[hidden email]>
+ */
+
+#ifndef _MUX_INTERNAL_H
+#define _MUX_INTERNAL_H
+
+/* See mux.h for background documentation. */
+
+struct ofnode_phandle_args;
+
+/**
+ * struct mux_chip - Represents a chip holding mux controllers.
+ * @controllers: Number of mux controllers handled by the chip.
+ * @mux: Array of mux controllers that are handled.
+ *
+ * This a per-device uclass-private data.
+ */
+struct mux_chip {
+ unsigned int controllers;
+ struct mux_control *mux;
+};
+
+/**
+ * struct mux_control_ops - Mux controller operations for a mux chip.
+ * @set: Set the state of the given mux controller.
+ */
+struct mux_control_ops {
+ /**
+ * set - Apply a state to a multiplexer control
+ *
+ * @mux: A multiplexer control
+ * @return 0 if OK, or a negative error code.
+ */
+ int (*set)(struct mux_control *mux, int state);
+
+ /**
+ * of_xlate - Translate a client's device-tree (OF) multiplexer
+ * specifier.
+ *
+ * If this function pointer is set to NULL, the multiplexer core will
+ * use a default implementation, which assumes #mux-control-cells = <1>
+ * and that the DT cell contains a simple integer channel ID.
+ *
+ * @dev_mux: The multiplexer device. A single device may handle
+ *              several multiplexer controls.
+ * @args: The multiplexer specifier values from device tree.
+ * @muxp: (out) A multiplexer control
+ * @return 0 if OK, or a negative error code.
+ */
+ int (*of_xlate)(struct mux_chip *dev_mux,
+ struct ofnode_phandle_args *args,
+ struct mux_control **muxp);
+};
+
+/**
+ * struct mux_control - Represents a mux controller.
+ * @in_use: Whether the mux controller is in use or not.
+ * @dev: The client device.
+ * @cached_state: The current mux controller state, or -1 if none.
+ * @states: The number of mux controller states.
+ * @idle_state: The mux controller state to use when inactive, or one
+ * of MUX_IDLE_AS_IS and MUX_IDLE_DISCONNECT.
+ * @id: The index of the mux controller within the mux chip
+ * it is a part of.
+ *
+ * Mux drivers may only change @states and @idle_state, and may only do so
+ * between allocation and registration of the mux controller. Specifically,
+ * @cached_state is internal to the mux core and should never be written by
+ * mux drivers.
+ */
+struct mux_control {
+ bool in_use;
+ struct udevice *dev;
+ int cached_state;
+ unsigned int states;
+ int idle_state;
+ int id;
+};
+
+/**
+ * mux_control_get_index() - Get the index of the given mux controller
+ * @mux: The mux-control to get the index for.
+ *
+ * Return: The index of the mux controller within the mux chip the mux
+ * controller is a part of.
+ */
+static inline unsigned int mux_control_get_index(struct mux_control *mux)
+{
+ return mux->id;
+}
+
+/**
+ * mux_alloc_controllers() - Allocate the given number of mux controllers.
+ * @dev: The client device.
+ * controllers: Number of controllers to allocate.
+ *
+ * Return: 0 of OK, -errno otherwise.
+ */
+int mux_alloc_controllers(struct udevice *dev, unsigned int controllers);
+
+#endif
diff --git a/include/mux.h b/include/mux.h
new file mode 100644
index 0000000000..85eb7d42fc
--- /dev/null
+++ b/include/mux.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Based on the linux multiplexer framework
+ *
+ * At its core, a multiplexer (or mux), also known as a data selector, is a
+ * device that selects between several analog or digital input signals and
+ * forwards it to a single output line. This notion can be extended to work
+ * with buses, like a I2C bus multiplexer for example.
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ * Author: Peter Rosin <[hidden email]>
+ *
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot <[hidden email]>
+ */
+
+#ifndef _MUX_H_
+#define _MUX_H_
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+struct udevice;
+struct mux_control;
+
+#if CONFIG_IS_ENABLED(MULTIPLEXER)
+/**
+ * mux_control_states() - Query the number of multiplexer states.
+ * @mux: The mux-control to query.
+ *
+ * Return: The number of multiplexer states.
+ */
+unsigned int mux_control_states(struct mux_control *mux);
+
+/**
+ * mux_control_select() - Select the given multiplexer state.
+ * @mux: The mux-control to request a change of state from.
+ * @state: The new requested state.
+ *
+ * On successfully selecting the mux-control state, it will be locked until
+ * there is a call to mux_control_deselect(). If the mux-control is already
+ * selected when mux_control_select() is called, the function will indicate
+ * -EBUSY
+ *
+ * Therefore, make sure to call mux_control_deselect() when the operation is
+ * complete and the mux-control is free for others to use, but do not call
+ * mux_control_deselect() if mux_control_select() fails.
+ *
+ * Return: 0 when the mux-control state has the requested state or a negative
+ * errno on error.
+ */
+int __must_check mux_control_select(struct mux_control *mux,
+    unsigned int state);
+#define mux_control_try_select(mux) mux_control_select(mux)
+
+/**
+ * mux_control_deselect() - Deselect the previously selected multiplexer state.
+ * @mux: The mux-control to deselect.
+ *
+ * It is required that a single call is made to mux_control_deselect() for
+ * each and every successful call made to either of mux_control_select() or
+ * mux_control_try_select().
+ *
+ * Return: 0 on success and a negative errno on error. An error can only
+ * occur if the mux has an idle state. Note that even if an error occurs, the
+ * mux-control is unlocked and is thus free for the next access.
+ */
+int mux_control_deselect(struct mux_control *mux);
+
+/**
+ * mux_get_by_index() = Get a mux by integer index.
+ * @dev: The client device.
+ * @index: The index of the mux to get.
+ * @mux: A pointer to the 'mux_control' struct to initialize.
+ *
+ * This looks up and initializes a mux. The index is relative to the client
+ * device.
+ *
+ * Return: 0 if OK, or a negative error code.
+ */
+int mux_get_by_index(struct udevice *dev, int index, struct mux_control **mux);
+
+/**
+ * mux_control_get() - Get the mux-control for a device.
+ * @dev: The device that needs a mux-control.
+ * @mux_name: The name identifying the mux-control.
+ * @mux: A pointer to the mux-control pointer.
+ *
+ * Return: 0 of OK, or a negative error code.
+ */
+int mux_control_get(struct udevice *dev, const char *name,
+    struct mux_control **mux);
+
+/**
+ * mux_control_put() - Put away the mux-control for good.
+ * @mux: The mux-control to put away.
+ *
+ * mux_control_put() reverses the effects of mux_control_get().
+ */
+void mux_control_put(struct mux_control *mux);
+
+/**
+ * devm_mux_control_get() - Get the mux-control for a device, with resource
+ *    management.
+ * @dev: The device that needs a mux-control.
+ * @mux_name: The name identifying the mux-control.
+ *
+ * Return: Pointer to the mux-control, or an ERR_PTR with a negative errno.
+ */
+struct mux_control *devm_mux_control_get(struct udevice *dev,
+ const char *mux_name);
+#else
+unsigned int mux_control_states(struct mux_control *mux)
+{
+ return -ENOSYS;
+}
+
+int __must_check mux_control_select(struct mux_control *mux,
+    unsigned int state)
+{
+ return -ENOSYS;
+}
+
+#define mux_control_try_select(mux) mux_control_select(mux)
+
+int mux_control_deselect(struct mux_control *mux)
+{
+ return -ENOSYS;
+}
+
+struct mux_control *mux_control_get(struct udevice *dev, const char *mux_name)
+{
+ return NULL;
+}
+
+void mux_control_put(struct mux_control *mux)
+{
+}
+
+struct mux_control *devm_mux_control_get(struct udevice *dev,
+ const char *mux_name)
+{
+ return NULL;
+}
+#endif
+
+#endif
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 2/7] dm: board: complete the initialization of the muxes in initr_dm()

Pratyush Yadav
In reply to this post by Pratyush Yadav
From: Jean-Jacques Hiblot <[hidden email]>

This will probe the multiplexer devices that have a "u-boot,mux-autoprobe"
property. As a consequence they will be put in their idle state.

Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
Reviewed-by: Simon Glass <[hidden email]>
Signed-off-by: Pratyush Yadav <[hidden email]>
---

Notes:
    No changes in v4.

 common/board_r.c         | 12 ++++++++++++
 drivers/mux/mux-uclass.c | 23 +++++++++++++++++++++++
 include/mux.h            | 12 ++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index 9b2fec701a..b9217b2e27 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -46,6 +46,7 @@
 #include <miiphy.h>
 #endif
 #include <mmc.h>
+#include <mux.h>
 #include <nand.h>
 #include <of_live.h>
 #include <onenand_uboot.h>
@@ -341,6 +342,17 @@ static int initr_dm_devices(void)
  return ret;
  }
 
+ if (IS_ENABLED(CONFIG_MULTIPLEXER)) {
+ /*
+ * Initialize the multiplexer controls to their default state.
+ * This must be done early as other drivers may unknowingly
+ * rely on it.
+ */
+ ret = dm_mux_init();
+ if (ret)
+ return ret;
+ }
+
  return 0;
 }
 
diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c
index 3c89e0a389..3dad466101 100644
--- a/drivers/mux/mux-uclass.c
+++ b/drivers/mux/mux-uclass.c
@@ -303,6 +303,29 @@ static int mux_uclass_post_probe(struct udevice *dev)
  return 0;
 }
 
+int dm_mux_init(void)
+{
+ struct uclass *uc;
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_get(UCLASS_MUX, &uc);
+ if (ret < 0) {
+ log_debug("unable to get MUX uclass\n");
+ return ret;
+ }
+ uclass_foreach_dev(dev, uc) {
+ if (dev_read_bool(dev, "u-boot,mux-autoprobe")) {
+ ret = device_probe(dev);
+ if (ret)
+ log_debug("unable to probe device %s\n",
+  dev->name);
+ }
+ }
+
+ return 0;
+}
+
 UCLASS_DRIVER(mux) = {
  .id = UCLASS_MUX,
  .name = "mux",
diff --git a/include/mux.h b/include/mux.h
index 85eb7d42fc..23844f480a 100644
--- a/include/mux.h
+++ b/include/mux.h
@@ -109,6 +109,13 @@ void mux_control_put(struct mux_control *mux);
  */
 struct mux_control *devm_mux_control_get(struct udevice *dev,
  const char *mux_name);
+/**
+ * dm_mux_init() - Initialize the multiplexer controls to their default state.
+ *
+ * Return: 0 if OK, -errno otherwise.
+ */
+int dm_mux_init(void);
+
 #else
 unsigned int mux_control_states(struct mux_control *mux)
 {
@@ -142,6 +149,11 @@ struct mux_control *devm_mux_control_get(struct udevice *dev,
 {
  return NULL;
 }
+
+int dm_mux_init(void)
+{
+ return -ENOSYS;
+}
 #endif
 
 #endif
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 3/7] drivers: mux: mmio-based syscon mux controller

Pratyush Yadav
In reply to this post by Pratyush Yadav
From: Jean-Jacques Hiblot <[hidden email]>

This adds a driver for mmio-based syscon multiplexers controlled by
bitfields in a syscon register range.
This is heavily based on the linux mmio-mux driver.

Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
Reviewed-by: Simon Glass <[hidden email]>
Signed-off-by: Pratyush Yadav <[hidden email]>
---

Notes:
    Changes in v4:
   
    - Make strings in log messages smaller to reduce memory footprint.

 drivers/mux/Kconfig  |  14 +++++
 drivers/mux/Makefile |   1 +
 drivers/mux/mmio.c   | 141 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+)
 create mode 100644 drivers/mux/mmio.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 35c1c5673c..f15ee4f833 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -8,4 +8,18 @@ config MULTIPLEXER
  controllers. It provides the same API as Linux and mux drivers should
  be portable with a minimum effort.
 
+if MULTIPLEXER
+
+config MUX_MMIO
+ bool "MMIO register bitfield-controlled Multiplexer"
+ depends on MULTIPLEXER && SYSCON
+ help
+  MMIO register bitfield-controlled Multiplexer controller.
+
+  The driver builds multiplexer controllers for bitfields in a syscon
+  register. For N bit wide bitfields, there will be 2^N possible
+  multiplexer states.
+
+endif
+
 endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 351e4363d3..78ebf04c7a 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -4,3 +4,4 @@
 # Jean-Jacques Hiblot <[hidden email]>
 
 obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
+obj-$(CONFIG_$(SPL_)MUX_MMIO) += mmio.o
diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c
new file mode 100644
index 0000000000..654fff26f7
--- /dev/null
+++ b/drivers/mux/mmio.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MMIO register bitfield-controlled multiplexer driver
+ * Based on the linux mmio multiplexer driver
+ *
+ * Copyright (C) 2017 Pengutronix, Philipp Zabel <[hidden email]>
+ * Copyright (C) 2019 Texas Instrument, Jean-jacques Hiblot <[hidden email]>
+ */
+#include <common.h>
+#include <dm.h>
+#include <mux-internal.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <dm/device.h>
+#include <dm/read.h>
+#include <dm/devres.h>
+#include <dt-bindings/mux/mux.h>
+#include <linux/bitops.h>
+
+static int mux_mmio_set(struct mux_control *mux, int state)
+{
+ struct regmap_field **fields = dev_get_priv(mux->dev);
+
+ return regmap_field_write(fields[mux_control_get_index(mux)], state);
+}
+
+static const struct mux_control_ops mux_mmio_ops = {
+ .set = mux_mmio_set,
+};
+
+static const struct udevice_id mmio_mux_of_match[] = {
+ { .compatible = "mmio-mux" },
+ { /* sentinel */ },
+};
+
+static int mmio_mux_probe(struct udevice *dev)
+{
+ struct regmap_field **fields;
+ struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
+ struct regmap *regmap;
+ u32 *mux_reg_masks;
+ u32 *idle_states;
+ int num_fields;
+ int ret;
+ int i;
+
+ regmap = syscon_node_to_regmap(dev_ofnode(dev->parent));
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(dev, "failed to get regmap: %d\n", ret);
+ return ret;
+ }
+
+ num_fields = dev_read_size(dev, "mux-reg-masks");
+ if (num_fields < 0)
+ return log_msg_ret("mux-reg-masks missing", -EINVAL);
+
+ num_fields /= sizeof(u32);
+ if (num_fields == 0 || num_fields % 2)
+ ret = -EINVAL;
+ num_fields = num_fields / 2;
+
+ ret = mux_alloc_controllers(dev, num_fields);
+ if (ret < 0)
+ return log_msg_ret("mux_alloc_controllers", ret);
+
+ fields = devm_kmalloc(dev, num_fields * sizeof(*fields), __GFP_ZERO);
+ if (!fields)
+ return -ENOMEM;
+ dev->priv = fields;
+
+ mux_reg_masks = devm_kmalloc(dev, num_fields * 2 * sizeof(u32),
+     __GFP_ZERO);
+ if (!mux_reg_masks)
+ return -ENOMEM;
+
+ ret = dev_read_u32_array(dev, "mux-reg-masks", mux_reg_masks,
+ num_fields * 2);
+ if (ret < 0)
+ return log_msg_ret("mux-reg-masks read", ret);
+
+ idle_states = devm_kmalloc(dev, num_fields * sizeof(u32), __GFP_ZERO);
+ if (!idle_states)
+ return -ENOMEM;
+
+ ret = dev_read_u32_array(dev, "idle-states", idle_states, num_fields);
+ if (ret < 0) {
+ log_err("idle-states");
+ devm_kfree(dev, idle_states);
+ idle_states = NULL;
+ }
+
+ for (i = 0; i < num_fields; i++) {
+ struct mux_control *mux = &mux_chip->mux[i];
+ struct reg_field field;
+ u32 reg, mask;
+ int bits;
+
+ reg = mux_reg_masks[2 * i];
+ mask = mux_reg_masks[2 * i + 1];
+
+ field.reg = reg;
+ field.msb = fls(mask) - 1;
+ field.lsb = ffs(mask) - 1;
+
+ if (mask != GENMASK(field.msb, field.lsb))
+ return log_msg_ret("invalid mask", -EINVAL);
+
+ fields[i] = devm_regmap_field_alloc(dev, regmap, field);
+ if (IS_ERR(fields[i])) {
+ ret = PTR_ERR(fields[i]);
+ return log_msg_ret("regmap_field_alloc", ret);
+ }
+
+ bits = 1 + field.msb - field.lsb;
+ mux->states = 1 << bits;
+
+ if (!idle_states)
+ continue;
+
+ if (idle_states[i] != MUX_IDLE_AS_IS &&
+    idle_states[i] >= mux->states)
+ return log_msg_ret("idle-states range", -EINVAL);
+
+ mux->idle_state = idle_states[i];
+ }
+
+ devm_kfree(dev, mux_reg_masks);
+ if (idle_states)
+ devm_kfree(dev, idle_states);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(mmio_mux) = {
+ .name = "mmio-mux",
+ .id = UCLASS_MUX,
+ .of_match = mmio_mux_of_match,
+ .probe = mmio_mux_probe,
+ .ops = &mux_mmio_ops,
+};
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 4/7] Kconfig: Increase the pre-relocation memory

Pratyush Yadav
In reply to this post by Pratyush Yadav
The memory is close to full and adding a syscon node in test.dts makes
it go over the limit and makes malloc() fail on startup.

Signed-off-by: Pratyush Yadav <[hidden email]>
---

Notes:
    New in v4.

 Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Kconfig b/Kconfig
index 520679f57e..b2165c1c49 100644
--- a/Kconfig
+++ b/Kconfig
@@ -196,7 +196,7 @@ config SYS_MALLOC_F_LEN
  hex "Size of malloc() pool before relocation"
  depends on SYS_MALLOC_F
  default 0x1000 if AM33XX
- default 0x2800 if SANDBOX
+ default 0x4000 if SANDBOX
  default 0x2000 if (ARCH_IMX8 || ARCH_IMX8M || ARCH_MX7 || \
    ARCH_MX7ULP || ARCH_MX6 || ARCH_MX5 || \
    ARCH_LS1012A || ARCH_LS1021A || ARCH_LS1043A || \
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 5/7] test: Add tests for the multiplexer framework

Pratyush Yadav
In reply to this post by Pratyush Yadav
From: Jean-Jacques Hiblot <[hidden email]>

Provide tests to check the behavior of the multiplexer framework.

Two sets of tests are added. One is using an emulated multiplexer driver
that can be used to test basic functionality like select, deselect, etc.
The other is using the mmio mux which adds tests specific to it.

Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
Signed-off-by: Pratyush Yadav <[hidden email]>
---

Notes:
    Changes in v4:
   
    - Add an emulated mux driver that makes it easier to test some basic
      functionality. It is used to test basic things like setting default
      state, and simple set/unset functionality. The MMIO test is still kept
      around for testing the mmio mux driver.
   
    - Add a node for the emulated mux driver in test.dts
   
    - Drop dm_test_mux_mmio_default_state(). This functionality is
      exercised by the emulated mux test.
   
    - Drop some unused includes from mux-mmio.c
   
    - s/DM_TESTF/UT_TESTF/g

 arch/sandbox/dts/test.dts |  33 +++++++++
 configs/sandbox_defconfig |   2 +
 test/dm/Makefile          |   2 +
 test/dm/mux-emul.c        | 105 +++++++++++++++++++++++++++++
 test/dm/mux-mmio.c        | 138 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 280 insertions(+)
 create mode 100644 test/dm/mux-emul.c
 create mode 100644 test/dm/mux-mmio.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fa84b2c10f..70ccb4951a 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -3,6 +3,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/sandbox-gpio.h>
 #include <dt-bindings/pinctrl/sandbox-pinmux.h>
+#include <dt-bindings/mux/mux.h>
 
 / {
  model = "sandbox";
@@ -133,6 +134,12 @@
  interrupts-extended = <&irq 3 0>;
  acpi,name = "GHIJ";
  phandle-value = <&gpio_c 10>, <0xFFFFFFFF 20>, <&gpio_a 30>;
+
+ mux-controls = <&muxcontroller0 0>, <&muxcontroller0 1>,
+       <&muxcontroller0 2>, <&muxcontroller0 3>,
+       <&muxcontroller1>;
+ mux-control-names = "mux0", "mux1", "mux2", "mux3", "mux4";
+ mux-syscon = <&syscon3>;
  };
 
  junk {
@@ -170,6 +177,9 @@
  compatible = "denx,u-boot-fdt-test";
  ping-expect = <3>;
  ping-add = <3>;
+
+ mux-controls = <&muxcontroller0 0>;
+ mux-control-names = "mux0";
  };
 
  phy_provider0: gen_phy@0 {
@@ -884,6 +894,29 @@
  0x58 8>;
  };
 
+ syscon3: syscon@3 {
+ compatible = "simple-mfd", "syscon";
+ reg = <0x000100 0x10>;
+
+ muxcontroller0: a-mux-controller {
+ compatible = "mmio-mux";
+ #mux-control-cells = <1>;
+
+ mux-reg-masks = <0x0 0x30>, /* 0: reg 0x0, bits 5:4 */
+ <0xc 0x1E>, /* 1: reg 0xc, bits 4:1 */
+ <0x4 0xFF>; /* 2: reg 0x4, bits 7:0 */
+ idle-states = <MUX_IDLE_AS_IS>, <0x02>, <0x73>;
+ u-boot,mux-autoprobe;
+ };
+ };
+
+ muxcontroller1: emul-mux-controller {
+ compatible = "mux-emul";
+ #mux-control-cells = <0>;
+ u-boot,mux-autoprobe;
+ idle-state = <0xabcd>;
+ };
+
  timer@0 {
  compatible = "sandbox,timer";
  clock-frequency = <1000000>;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 6ac2919977..f3c4883032 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -179,6 +179,8 @@ CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_SST=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_MULTIPLEXER=y
+CONFIG_MUX_MMIO=y
 CONFIG_DM_ETH=y
 CONFIG_NVME=y
 CONFIG_PCI=y
diff --git a/test/dm/Makefile b/test/dm/Makefile
index e2b0798388..93484b48eb 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -57,6 +57,8 @@ obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_SMEM) += smem.o
 obj-$(CONFIG_DM_SPI) += spi.o
 obj-y += syscon.o
+obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
+obj-$(CONFIG_MULTIPLEXER) += mux-emul.o
 obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_REGULATOR) += regulator.o
diff --git a/test/dm/mux-emul.c b/test/dm/mux-emul.c
new file mode 100644
index 0000000000..141fd4d908
--- /dev/null
+++ b/test/dm/mux-emul.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+ * Pratyush Yadav <[hidden email]>
+ */
+#include <common.h>
+#include <dm.h>
+#include <mux.h>
+#include <mux-internal.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+struct mux_emul_priv {
+ u32 state;
+};
+
+static int mux_emul_set(struct mux_control *mux, int state)
+{
+ struct mux_emul_priv *priv = dev_get_priv(mux->dev);
+
+ priv->state = state;
+ return 0;
+}
+
+static int mux_emul_probe(struct udevice *dev)
+{
+ struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
+ struct mux_control *mux;
+ u32 idle_state;
+ int ret;
+
+ ret = mux_alloc_controllers(dev, 1);
+ if (ret < 0)
+ return ret;
+
+ mux = &mux_chip->mux[0];
+
+ ret = dev_read_u32(dev, "idle-state", &idle_state);
+ if (ret)
+ return ret;
+
+ mux->idle_state = idle_state;
+ mux->states = 0x100000;
+
+ return 0;
+}
+
+static const struct mux_control_ops mux_emul_ops = {
+ .set = mux_emul_set,
+};
+
+static const struct udevice_id mux_emul_of_match[] = {
+ { .compatible = "mux-emul" },
+ { /* sentinel */ },
+};
+
+U_BOOT_DRIVER(emul_mux) = {
+ .name = "mux-emul",
+ .id = UCLASS_MUX,
+ .of_match = mux_emul_of_match,
+ .ops = &mux_emul_ops,
+ .probe = mux_emul_probe,
+ .priv_auto_alloc_size = sizeof(struct mux_emul_priv),
+};
+
+static int dm_test_mux_emul_default_state(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct mux_control *mux;
+ struct mux_emul_priv *priv;
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test",
+      &dev));
+ ut_assertok(mux_control_get(dev, "mux4", &mux));
+
+ priv = dev_get_priv(mux->dev);
+
+ ut_asserteq(0xabcd, priv->state);
+
+ return 0;
+}
+DM_TEST(dm_test_mux_emul_default_state, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_mux_emul_select_deselect(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct mux_control *mux;
+ struct mux_emul_priv *priv;
+
+ gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
+ ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test",
+      &dev));
+ ut_assertok(mux_control_get(dev, "mux4", &mux));
+
+ priv = dev_get_priv(mux->dev);
+
+ ut_assertok(mux_control_select(mux, 0x1234));
+ ut_asserteq(priv->state, 0x1234);
+
+ ut_assertok(mux_control_deselect(mux));
+ ut_asserteq(priv->state, 0xabcd);
+
+ return 0;
+}
+DM_TEST(dm_test_mux_emul_select_deselect, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
diff --git a/test/dm/mux-mmio.c b/test/dm/mux-mmio.c
new file mode 100644
index 0000000000..fd353d8b15
--- /dev/null
+++ b/test/dm/mux-mmio.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot <[hidden email]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mux.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <dm/device-internal.h>
+#include <test/ut.h>
+
+static int dm_test_mux_mmio_select(struct unit_test_state *uts)
+{
+ struct udevice *dev, *dev_b;
+ struct regmap *map;
+ struct mux_control *ctl0_a, *ctl0_b;
+ struct mux_control *ctl1;
+ struct mux_control *ctl_err;
+ u32 val;
+ int i;
+
+ sandbox_set_enable_memio(true);
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test",
+      &dev));
+ ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "b-test",
+      &dev_b));
+ map = syscon_regmap_lookup_by_phandle(dev, "mux-syscon");
+ ut_assertok_ptr(map);
+ ut_assert(map);
+
+ ut_assertok(mux_control_get(dev, "mux0", &ctl0_a));
+ ut_assertok(mux_control_get(dev, "mux1", &ctl1));
+ ut_asserteq(-ERANGE, mux_control_get(dev, "mux3", &ctl_err));
+ ut_asserteq(-ENODATA, mux_control_get(dev, "dummy", &ctl_err));
+ ut_assertok(mux_control_get(dev_b, "mux0", &ctl0_b));
+
+ for (i = 0; i < mux_control_states(ctl0_a); i++) {
+ /* Select a new state and verify the value in the regmap. */
+ ut_assertok(mux_control_select(ctl0_a, i));
+ ut_assertok(regmap_read(map, 0, &val));
+ ut_asserteq(i, (val & 0x30) >> 4);
+ /*
+ * Deselect the mux and verify that the value in the regmap
+ * reflects the idle state (fixed to MUX_IDLE_AS_IS).
+ */
+ ut_assertok(mux_control_deselect(ctl0_a));
+ ut_assertok(regmap_read(map, 0, &val));
+ ut_asserteq(i, (val & 0x30) >> 4);
+ }
+
+ for (i = 0; i < mux_control_states(ctl1); i++) {
+ /* Select a new state and verify the value in the regmap. */
+ ut_assertok(mux_control_select(ctl1, i));
+ ut_assertok(regmap_read(map, 0xc, &val));
+ ut_asserteq(i, (val & 0x1E) >> 1);
+ /*
+ * Deselect the mux and verify that the value in the regmap
+ * reflects the idle state (fixed to 2).
+ */
+ ut_assertok(mux_control_deselect(ctl1));
+ ut_assertok(regmap_read(map, 0xc, &val));
+ ut_asserteq(2, (val & 0x1E) >> 1);
+ }
+
+ /* Try unbalanced selection/deselection. */
+ ut_assertok(mux_control_select(ctl0_a, 0));
+ ut_asserteq(-EBUSY, mux_control_select(ctl0_a, 1));
+ ut_asserteq(-EBUSY, mux_control_select(ctl0_a, 0));
+ ut_assertok(mux_control_deselect(ctl0_a));
+
+ /* Try concurrent selection. */
+ ut_assertok(mux_control_select(ctl0_a, 0));
+ ut_assert(mux_control_select(ctl0_b, 0));
+ ut_assertok(mux_control_deselect(ctl0_a));
+ ut_assertok(mux_control_select(ctl0_b, 0));
+ ut_assert(mux_control_select(ctl0_a, 0));
+ ut_assertok(mux_control_deselect(ctl0_b));
+ ut_assertok(mux_control_select(ctl0_a, 0));
+ ut_assertok(mux_control_deselect(ctl0_a));
+
+ return 0;
+}
+DM_TEST(dm_test_mux_mmio_select, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Test that managed API for mux work correctly */
+static int dm_test_devm_mux_mmio(struct unit_test_state *uts)
+{
+ struct udevice *dev, *dev_b;
+ struct mux_control *ctl0_a, *ctl0_b;
+ struct mux_control *ctl1;
+ struct mux_control *ctl_err;
+
+ sandbox_set_enable_memio(true);
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test",
+      &dev));
+ ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "b-test",
+      &dev_b));
+
+ ctl0_a = devm_mux_control_get(dev, "mux0");
+ ut_assertok_ptr(ctl0_a);
+ ut_assert(ctl0_a);
+ ctl1 = devm_mux_control_get(dev, "mux1");
+ ut_assertok_ptr(ctl1);
+ ut_assert(ctl1);
+ ctl_err = devm_mux_control_get(dev, "mux3");
+ ut_asserteq(-ERANGE, PTR_ERR(ctl_err));
+ ctl_err = devm_mux_control_get(dev, "dummy");
+ ut_asserteq(-ENODATA, PTR_ERR(ctl_err));
+
+ ctl0_b = devm_mux_control_get(dev_b, "mux0");
+ ut_assertok_ptr(ctl0_b);
+ ut_assert(ctl0_b);
+
+ /* Try concurrent selection. */
+ ut_assertok(mux_control_select(ctl0_a, 0));
+ ut_assert(mux_control_select(ctl0_b, 0));
+ ut_assertok(mux_control_deselect(ctl0_a));
+ ut_assertok(mux_control_select(ctl0_b, 0));
+ ut_assert(mux_control_select(ctl0_a, 0));
+ ut_assertok(mux_control_deselect(ctl0_b));
+
+ /* Remove one device and check that the mux is released. */
+ ut_assertok(mux_control_select(ctl0_a, 0));
+ ut_assert(mux_control_select(ctl0_b, 0));
+ device_remove(dev, DM_REMOVE_NORMAL);
+ ut_assertok(mux_control_select(ctl0_b, 0));
+
+ device_remove(dev_b, DM_REMOVE_NORMAL);
+ return 0;
+}
+DM_TEST(dm_test_devm_mux_mmio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 6/7] cmd: Add a mux command

Pratyush Yadav
In reply to this post by Pratyush Yadav
This command lets the user list, select, and deselect mux controllers
introduced with the mux framework on the fly. It has 3 subcommands:
list, select, and deselect.

List: Lists all the mux present on the system. The muxes are listed for
each chip. The chip is identified by its device name. Each chip can have
a number of mux controllers. Each is listed in sequence and is assigned
a sequential ID based on its position in the mux chip. It lists details
like ID, whether the mux is currently selected or not, the current
state, the idle state, and the number of states.

A sample output would look something like:

=> mux list
a-mux-controller:
        ID Selected Current State Idle State Num States
        0 no         unknown   as-is     0x4
        1 no         0x2       0x2       0x10
        2 no         0x73       0x73       0x100

another-mux-controller:
        ID Selected Current State Idle State Num States
        0       no              0x1             0x1             0x4
        1       no              0x2             0x2             0x4

Select: Selects a given mux and puts it in the specified state. This
subcommand takes 3 arguments: mux chip, mux ID, state to set
the mux in. The arguments mux chip and mux ID are used to identify which
mux needs to be selected, and then it is selected to the given state.
The mux needs to be deselected before it can be selected again in
another state. The state should be a hexadecimal number.

For example:
=> mux list
a-mux-controller:
        ID      Selected        Current State   Idle State      Num States
        0       no              0x1             0x1             0x4
        1       no              0x1             0x1             0x4
=> mux select a-mux-controller 0 0x3
=> mux list
a-mux-controller:
        ID      Selected        Current State   Idle State      Num States
        0       yes             0x3             0x1             0x4
        1       no              0x1             0x1             0x4

Deselect: Deselects a given mux and puts it in its idle state. This
subcommand takes 2 arguments: the mux chip and mux ID to identify which
mux needs to be deselected. So in the above example, we can deselect mux
0 using:

=> mux deselect a-mux-controller 0
=> mux list
a-mux-controller:
        ID      Selected        Current State   Idle State      Num States
        0       no              0x1             0x1             0x4
        1       no              0x1             0x1             0x4

Signed-off-by: Pratyush Yadav <[hidden email]>
---

Notes:
    Changes in v4:
   
    - Use spaces to print columns in 'mux list' instead of tabs. Tabs don't
      work well with ut_assert_nextline() because it calls
      membuff_readline() down the call chain and tells it to consider
      characters below the space character as EOL. This means
      ut_assert_nextline() can only assert for the next column not the next
      line if a command is using tabs.

 cmd/Kconfig  |   6 ++
 cmd/Makefile |   1 +
 cmd/mux.c    | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 190 insertions(+)
 create mode 100644 cmd/mux.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index a3166e4f31..a25d6d62d0 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1073,6 +1073,12 @@ config CMD_MTD
  help
   MTD commands support.
 
+config CMD_MUX
+ bool "mux"
+ depends on MULTIPLEXER
+ help
+ List, select, and deselect mux controllers on the fly.
+
 config CMD_NAND
  bool "nand"
  default y if NAND_SUNXI
diff --git a/cmd/Makefile b/cmd/Makefile
index 19a891633f..79a57b8482 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -104,6 +104,7 @@ obj-$(CONFIG_CMD_CLONE) += clone.o
 ifneq ($(CONFIG_CMD_NAND)$(CONFIG_CMD_SF),)
 obj-y += legacy-mtd-utils.o
 endif
+obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
diff --git a/cmd/mux.c b/cmd/mux.c
new file mode 100644
index 0000000000..3a0839ec1f
--- /dev/null
+++ b/cmd/mux.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * List, select, and deselect mux controllers on the fly.
+ *
+ * Copyright (c) 2020 Texas Instruments Inc.
+ * Author: Pratyush Yadav <[hidden email]>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <dm.h>
+#include <mux.h>
+#include <mux-internal.h>
+#include <linux/err.h>
+#include <dt-bindings/mux/mux.h>
+
+#define COLUMN_SIZE 16
+
+/*
+ * Print a member of a column. The total size of the text printed, including
+ * trailing whitespace, will always be COLUMN_SIZE.
+ */
+#define PRINT_COLUMN(fmt, args...) do { \
+ char buf[COLUMN_SIZE + 1]; \
+ snprintf(buf, COLUMN_SIZE + 1, fmt, ##args); \
+ printf("%-*s", COLUMN_SIZE, buf); \
+} while (0)
+
+/*
+ * Find a mux based on its device name in argv[1] and index in the chip in
+ * argv[2].
+ */
+static struct mux_control *cmd_mux_find(char *const argv[])
+{
+ struct udevice *dev;
+ struct mux_chip *chip;
+ int ret;
+ unsigned long id;
+
+ ret = strict_strtoul(argv[2], 10, &id);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = uclass_get_device_by_name(UCLASS_MUX, argv[1], &dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ chip = dev_get_uclass_priv(dev);
+ if (!chip)
+ return ERR_PTR(ret);
+
+ if (id >= chip->controllers)
+ return ERR_PTR(-EINVAL);
+
+ return &chip->mux[id];
+}
+
+/*
+ * Print the details of a mux. The columns printed correspond to: "Selected",
+ * "Current State", "Idle State", and "Num States".
+ */
+static void print_mux(struct mux_control *mux)
+{
+ PRINT_COLUMN("%s", mux->in_use ? "yes" : "no");
+
+ if (mux->cached_state == MUX_IDLE_AS_IS)
+ PRINT_COLUMN("%s", "unknown");
+ else
+ PRINT_COLUMN("0x%x", mux->cached_state);
+
+ if (mux->idle_state == MUX_IDLE_AS_IS)
+ PRINT_COLUMN("%s", "as-is");
+ else if (mux->idle_state == MUX_IDLE_DISCONNECT)
+ PRINT_COLUMN("%s", "disconnect");
+ else
+ PRINT_COLUMN("0x%x", mux->idle_state);
+
+ PRINT_COLUMN("0x%x", mux->states);
+
+ printf("\n");
+}
+
+static int do_mux_list(struct cmd_tbl *cmdtp, int flag, int argc,
+       char *const argv[])
+{
+ struct udevice *dev;
+ struct mux_chip *chip;
+ int j;
+
+ for (uclass_first_device(UCLASS_MUX, &dev);
+     dev;
+     uclass_next_device(&dev)) {
+ chip = dev_get_uclass_priv(dev);
+ if (!chip) {
+ dev_err(dev, "can't find mux chip\n");
+ continue;
+ }
+
+ printf("%s:\n", dev->name);
+
+ printf("    ");
+ PRINT_COLUMN("ID");
+ PRINT_COLUMN("Selected");
+ PRINT_COLUMN("Current State");
+ PRINT_COLUMN("Idle State");
+ PRINT_COLUMN("Num States");
+ printf("\n");
+ for (j = 0; j < chip->controllers; j++) {
+ printf("    ");
+ PRINT_COLUMN("%d", j);
+ print_mux(&chip->mux[j]);
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
+
+static int do_mux_select(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct mux_control *mux;
+ int ret;
+ unsigned long state;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ mux = cmd_mux_find(argv);
+ if (IS_ERR_OR_NULL(mux)) {
+ printf("Failed to find the specified mux\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = strict_strtoul(argv[3], 16, &state);
+ if (ret) {
+ printf("Invalid state\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = mux_control_select(mux, state);
+ if (ret) {
+ printf("Failed to select requested state\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mux_deselect(struct cmd_tbl *cmdtp, int flag, int argc,
+   char *const argv[])
+{
+ struct mux_control *mux;
+ int ret;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ mux = cmd_mux_find(argv);
+ if (IS_ERR_OR_NULL(mux)) {
+ printf("Failed to find the specified mux\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = mux_control_deselect(mux);
+ if (ret) {
+ printf("Failed to deselect mux\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static char mux_help_text[] =
+ "list - List all Muxes and their states\n"
+ "select <chip> <id> <state> - Select the given mux state\n"
+ "deselect <chip> <id> - Deselect the given mux and reset it to its idle state";
+
+U_BOOT_CMD_WITH_SUBCMDS(mux, "List, select, and deselect muxes", mux_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mux_list),
+ U_BOOT_SUBCMD_MKENT(select, 4, 0, do_mux_select),
+ U_BOOT_SUBCMD_MKENT(deselect, 3, 0, do_mux_deselect));
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 7/7] test: mux-cmd: Add tests for the 'mux' command

Pratyush Yadav
In reply to this post by Pratyush Yadav
Tests tests run the three mux subcommands: list, select, and deselect,
and verify that the commands do what we expect.

Signed-off-by: Pratyush Yadav <[hidden email]>
---

Notes:
    New in v4.

 configs/sandbox_defconfig |   1 +
 test/dm/Makefile          |   1 +
 test/dm/mux-cmd.c         | 177 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 179 insertions(+)
 create mode 100644 test/dm/mux-cmd.c

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f3c4883032..e573ae075b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -55,6 +55,7 @@ CONFIG_CMD_GPT_RENAME=y
 CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_LSBLK=y
+CONFIG_CMD_MUX=y
 CONFIG_CMD_OSD=y
 CONFIG_CMD_PCI=y
 CONFIG_CMD_READ=y
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 93484b48eb..8b3d77e34e 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -34,6 +34,7 @@ obj-y += irq.o
 obj-$(CONFIG_LED) += led.o
 obj-$(CONFIG_DM_MAILBOX) += mailbox.o
 obj-$(CONFIG_DM_MMC) += mmc.o
+obj-$(CONFIG_CMD_MUX) += mux-cmd.o
 obj-y += fdtdec.o
 obj-y += ofnode.o
 obj-y += ofread.o
diff --git a/test/dm/mux-cmd.c b/test/dm/mux-cmd.c
new file mode 100644
index 0000000000..11c237b5da
--- /dev/null
+++ b/test/dm/mux-cmd.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Texas Instruments Inc.
+ * Pratyush Yadav <[hidden email]>
+ */
+#include <common.h>
+#include <dm.h>
+#include <mux.h>
+#include <mux-internal.h>
+#include <dt-bindings/mux/mux.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+#include <console.h>
+#include <rand.h>
+
+#define BUF_SIZE 256
+
+/* Test 'mux list' */
+static int dm_test_cmd_mux_list(struct unit_test_state *uts)
+{
+ char str[BUF_SIZE], *tok;
+ struct udevice *dev;
+ struct mux_chip *chip;
+ struct mux_control *mux;
+ int i;
+ unsigned long val;
+
+ sandbox_set_enable_memio(true);
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_MUX, "a-mux-controller",
+      &dev));
+ chip = dev_get_uclass_priv(dev);
+ ut_assertnonnull(chip);
+
+ run_command("mux list", 0);
+ ut_assert_nextline("a-mux-controller:");
+
+ /*
+ * Check the table header to make sure we are not out of sync with the
+ * code in the command. If we are, catch it early.
+ */
+ console_record_readline(str, BUF_SIZE);
+ tok = strtok(str, " ");
+ ut_asserteq_str("ID", tok);
+
+ tok = strtok(NULL, " ");
+ ut_asserteq_str("Selected", tok);
+
+ tok = strtok(NULL, " ");
+ ut_asserteq_str("Current", tok);
+ tok = strtok(NULL, " ");
+ ut_asserteq_str("State", tok);
+
+ tok = strtok(NULL, " ");
+ ut_asserteq_str("Idle", tok);
+ tok = strtok(NULL, " ");
+ ut_asserteq_str("State", tok);
+
+ tok = strtok(NULL, " ");
+ ut_asserteq_str("Num", tok);
+ tok = strtok(NULL, " ");
+ ut_asserteq_str("States", tok);
+
+ for (i = 0; i < chip->controllers; i++) {
+ mux = &chip->mux[i];
+
+ console_record_readline(str, BUF_SIZE);
+
+ /*
+ * Check if the ID printed matches with the ID of the chip we
+ * have.
+ */
+ tok = strtok(str, " ");
+ ut_assertok(strict_strtoul(tok, 10, &val));
+ ut_asserteq(i, val);
+
+ /* Check if mux selection state matches. */
+ tok = strtok(NULL, " ");
+ if (mux->in_use) {
+ ut_asserteq_str("yes", tok);
+ } else {
+ ut_asserteq_str("no", tok);
+ }
+
+ /* Check if the current state matches. */
+ tok = strtok(NULL, " ");
+ if (mux->cached_state == MUX_IDLE_AS_IS) {
+ ut_asserteq_str("unknown", tok);
+ } else {
+ ut_assertok(strict_strtoul(tok, 16, &val));
+ ut_asserteq(mux->cached_state, val);
+ }
+
+ /* Check if the idle state matches */
+ tok = strtok(NULL, " ");
+ if (mux->idle_state == MUX_IDLE_AS_IS) {
+ ut_asserteq_str("as-is", tok);
+ } else {
+ ut_assertok(strict_strtoul(tok, 16, &val));
+ ut_asserteq(mux->idle_state, val);
+ }
+
+ /* Check if the number of states matches */
+ tok = strtok(NULL, " ");
+ ut_assertok(strict_strtoul(tok, 16, &val));
+ ut_asserteq(mux->states, val);
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_cmd_mux_list, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_cmd_mux_select(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct mux_chip *chip;
+ struct mux_control *mux;
+ char cmd[BUF_SIZE];
+ unsigned int i, state;
+
+ sandbox_set_enable_memio(true);
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_MUX, "a-mux-controller",
+      &dev));
+ chip = dev_get_uclass_priv(dev);
+ ut_assertnonnull(chip);
+
+ srand(get_ticks() + rand());
+ for (i = 0; i < chip->controllers; i++) {
+ mux = &chip->mux[i];
+
+ state = rand() % mux->states;
+
+ snprintf(cmd, BUF_SIZE, "mux select a-mux-controller %x %x", i,
+ state);
+ run_command(cmd, 0);
+ ut_asserteq(!!mux->in_use, true);
+ ut_asserteq(state, mux->cached_state);
+
+ ut_assertok(mux_control_deselect(mux));
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_cmd_mux_select, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_cmd_mux_deselect(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct mux_chip *chip;
+ struct mux_control *mux;
+ char cmd[BUF_SIZE];
+ unsigned int i, state;
+
+ sandbox_set_enable_memio(true);
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_MUX, "a-mux-controller",
+      &dev));
+ chip = dev_get_uclass_priv(dev);
+ ut_assertnonnull(chip);
+
+ srand(get_ticks() + rand());
+ for (i = 0; i < chip->controllers; i++) {
+ mux = &chip->mux[i];
+
+ state = rand() % mux->states;
+ ut_assertok(mux_control_select(mux, state));
+
+ snprintf(cmd, BUF_SIZE, "mux deselect a-mux-controller %d", i);
+ run_command(cmd, 0);
+ ut_asserteq(!!mux->in_use, false);
+ }
+
+ return 0;
+}
+DM_TEST(dm_test_cmd_mux_deselect, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 4/7] Kconfig: Increase the pre-relocation memory

Simon Glass-3
In reply to this post by Pratyush Yadav
On Fri, 16 Oct 2020 at 04:46, Pratyush Yadav <[hidden email]> wrote:

>
> The memory is close to full and adding a syscon node in test.dts makes
> it go over the limit and makes malloc() fail on startup.
>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> ---
>
> Notes:
>     New in v4.
>
>  Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

Reviewed-by: Simon Glass <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 5/7] test: Add tests for the multiplexer framework

Simon Glass-3
In reply to this post by Pratyush Yadav
Hi Pratyush,

On Fri, 16 Oct 2020 at 04:46, Pratyush Yadav <[hidden email]> wrote:

>
> From: Jean-Jacques Hiblot <[hidden email]>
>
> Provide tests to check the behavior of the multiplexer framework.
>
> Two sets of tests are added. One is using an emulated multiplexer driver
> that can be used to test basic functionality like select, deselect, etc.
> The other is using the mmio mux which adds tests specific to it.
>
> Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> ---
>
> Notes:
>     Changes in v4:
>
>     - Add an emulated mux driver that makes it easier to test some basic
>       functionality. It is used to test basic things like setting default
>       state, and simple set/unset functionality. The MMIO test is still kept
>       around for testing the mmio mux driver.
>
>     - Add a node for the emulated mux driver in test.dts
>
>     - Drop dm_test_mux_mmio_default_state(). This functionality is
>       exercised by the emulated mux test.
>
>     - Drop some unused includes from mux-mmio.c
>
>     - s/DM_TESTF/UT_TESTF/g
>
>  arch/sandbox/dts/test.dts |  33 +++++++++
>  configs/sandbox_defconfig |   2 +
>  test/dm/Makefile          |   2 +
>  test/dm/mux-emul.c        | 105 +++++++++++++++++++++++++++++
>  test/dm/mux-mmio.c        | 138 ++++++++++++++++++++++++++++++++++++++
>  5 files changed, 280 insertions(+)
>  create mode 100644 test/dm/mux-emul.c
>  create mode 100644 test/dm/mux-mmio.c
>

Reviewed-by: Simon Glass <[hidden email]>

nits below

> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index fa84b2c10f..70ccb4951a 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -3,6 +3,7 @@
>  #include <dt-bindings/gpio/gpio.h>
>  #include <dt-bindings/gpio/sandbox-gpio.h>
>  #include <dt-bindings/pinctrl/sandbox-pinmux.h>
> +#include <dt-bindings/mux/mux.h>
>
>  / {
>         model = "sandbox";
> @@ -133,6 +134,12 @@
>                 interrupts-extended = <&irq 3 0>;
>                 acpi,name = "GHIJ";
>                 phandle-value = <&gpio_c 10>, <0xFFFFFFFF 20>, <&gpio_a 30>;
> +
> +               mux-controls = <&muxcontroller0 0>, <&muxcontroller0 1>,
> +                              <&muxcontroller0 2>, <&muxcontroller0 3>,
> +                              <&muxcontroller1>;
> +               mux-control-names = "mux0", "mux1", "mux2", "mux3", "mux4";
> +               mux-syscon = <&syscon3>;
>         };
>
>         junk {
> @@ -170,6 +177,9 @@
>                 compatible = "denx,u-boot-fdt-test";
>                 ping-expect = <3>;
>                 ping-add = <3>;
> +
> +               mux-controls = <&muxcontroller0 0>;
> +               mux-control-names = "mux0";
>         };
>
>         phy_provider0: gen_phy@0 {
> @@ -884,6 +894,29 @@
>                         0x58 8>;
>         };
>
> +       syscon3: syscon@3 {
> +               compatible = "simple-mfd", "syscon";
> +               reg = <0x000100 0x10>;
> +
> +               muxcontroller0: a-mux-controller {
> +                       compatible = "mmio-mux";
> +                       #mux-control-cells = <1>;
> +
> +                       mux-reg-masks = <0x0 0x30>, /* 0: reg 0x0, bits 5:4 */
> +                                       <0xc 0x1E>, /* 1: reg 0xc, bits 4:1 */
> +                                       <0x4 0xFF>; /* 2: reg 0x4, bits 7:0 */
> +                       idle-states = <MUX_IDLE_AS_IS>, <0x02>, <0x73>;
> +                       u-boot,mux-autoprobe;
> +               };
> +       };
> +
> +       muxcontroller1: emul-mux-controller {
> +               compatible = "mux-emul";
> +               #mux-control-cells = <0>;
> +               u-boot,mux-autoprobe;
> +               idle-state = <0xabcd>;
> +       };
> +
>         timer@0 {
>                 compatible = "sandbox,timer";
>                 clock-frequency = <1000000>;
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index 6ac2919977..f3c4883032 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -179,6 +179,8 @@ CONFIG_SPI_FLASH_SPANSION=y
>  CONFIG_SPI_FLASH_STMICRO=y
>  CONFIG_SPI_FLASH_SST=y
>  CONFIG_SPI_FLASH_WINBOND=y
> +CONFIG_MULTIPLEXER=y
> +CONFIG_MUX_MMIO=y
>  CONFIG_DM_ETH=y
>  CONFIG_NVME=y
>  CONFIG_PCI=y
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index e2b0798388..93484b48eb 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -57,6 +57,8 @@ obj-$(CONFIG_DM_SPI_FLASH) += sf.o
>  obj-$(CONFIG_SMEM) += smem.o
>  obj-$(CONFIG_DM_SPI) += spi.o
>  obj-y += syscon.o
> +obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
> +obj-$(CONFIG_MULTIPLEXER) += mux-emul.o
>  obj-$(CONFIG_DM_USB) += usb.o
>  obj-$(CONFIG_DM_PMIC) += pmic.o
>  obj-$(CONFIG_DM_REGULATOR) += regulator.o
> diff --git a/test/dm/mux-emul.c b/test/dm/mux-emul.c
> new file mode 100644
> index 0000000000..141fd4d908
> --- /dev/null
> +++ b/test/dm/mux-emul.c
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
> + * Pratyush Yadav <[hidden email]>
> + */
> +#include <common.h>
> +#include <dm.h>
> +#include <mux.h>
> +#include <mux-internal.h>
> +#include <dm/test.h>
> +#include <test/ut.h>
> +
> +struct mux_emul_priv {
> +       u32 state;
> +};
> +
> +static int mux_emul_set(struct mux_control *mux, int state)
> +{
> +       struct mux_emul_priv *priv = dev_get_priv(mux->dev);
> +
> +       priv->state = state;

blank line before last return

> +       return 0;
> +}
> +

Regards,
Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 7/7] test: mux-cmd: Add tests for the 'mux' command

Simon Glass-3
In reply to this post by Pratyush Yadav
Hi Pratyush,

On Fri, 16 Oct 2020 at 04:46, Pratyush Yadav <[hidden email]> wrote:

>
> Tests tests run the three mux subcommands: list, select, and deselect,
> and verify that the commands do what we expect.
>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> ---
>
> Notes:
>     New in v4.
>
>  configs/sandbox_defconfig |   1 +
>  test/dm/Makefile          |   1 +
>  test/dm/mux-cmd.c         | 177 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 179 insertions(+)
>  create mode 100644 test/dm/mux-cmd.c
>
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index f3c4883032..e573ae075b 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -55,6 +55,7 @@ CONFIG_CMD_GPT_RENAME=y
>  CONFIG_CMD_IDE=y
>  CONFIG_CMD_I2C=y
>  CONFIG_CMD_LSBLK=y
> +CONFIG_CMD_MUX=y
>  CONFIG_CMD_OSD=y
>  CONFIG_CMD_PCI=y
>  CONFIG_CMD_READ=y
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 93484b48eb..8b3d77e34e 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -34,6 +34,7 @@ obj-y += irq.o
>  obj-$(CONFIG_LED) += led.o
>  obj-$(CONFIG_DM_MAILBOX) += mailbox.o
>  obj-$(CONFIG_DM_MMC) += mmc.o
> +obj-$(CONFIG_CMD_MUX) += mux-cmd.o
>  obj-y += fdtdec.o
>  obj-y += ofnode.o
>  obj-y += ofread.o
> diff --git a/test/dm/mux-cmd.c b/test/dm/mux-cmd.c
> new file mode 100644
> index 0000000000..11c237b5da
> --- /dev/null
> +++ b/test/dm/mux-cmd.c
> @@ -0,0 +1,177 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2020 Texas Instruments Inc.
> + * Pratyush Yadav <[hidden email]>
> + */
> +#include <common.h>
> +#include <dm.h>
> +#include <mux.h>
> +#include <mux-internal.h>
> +#include <dt-bindings/mux/mux.h>
> +#include <asm/test.h>
> +#include <dm/test.h>
> +#include <test/ut.h>
> +#include <console.h>
> +#include <rand.h>

Check header order

Reviewed-by: Simon Glass <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 6/7] cmd: Add a mux command

Simon Glass-3
In reply to this post by Pratyush Yadav
Hi Pratyush,

On Fri, 16 Oct 2020 at 04:46, Pratyush Yadav <[hidden email]> wrote:

>
> This command lets the user list, select, and deselect mux controllers
> introduced with the mux framework on the fly. It has 3 subcommands:
> list, select, and deselect.
>
> List: Lists all the mux present on the system. The muxes are listed for
> each chip. The chip is identified by its device name. Each chip can have
> a number of mux controllers. Each is listed in sequence and is assigned
> a sequential ID based on its position in the mux chip. It lists details
> like ID, whether the mux is currently selected or not, the current
> state, the idle state, and the number of states.
>
> A sample output would look something like:
>
> => mux list
> a-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       no              unknown         as-is           0x4
>         1       no              0x2             0x2             0x10
>         2       no              0x73            0x73            0x100
>
> another-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       no              0x1             0x1             0x4
>         1       no              0x2             0x2             0x4
>
> Select: Selects a given mux and puts it in the specified state. This
> subcommand takes 3 arguments: mux chip, mux ID, state to set
> the mux in. The arguments mux chip and mux ID are used to identify which
> mux needs to be selected, and then it is selected to the given state.
> The mux needs to be deselected before it can be selected again in
> another state. The state should be a hexadecimal number.
>
> For example:
> => mux list
> a-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       no              0x1             0x1             0x4
>         1       no              0x1             0x1             0x4
> => mux select a-mux-controller 0 0x3
> => mux list
> a-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       yes             0x3             0x1             0x4
>         1       no              0x1             0x1             0x4
>
> Deselect: Deselects a given mux and puts it in its idle state. This
> subcommand takes 2 arguments: the mux chip and mux ID to identify which
> mux needs to be deselected. So in the above example, we can deselect mux
> 0 using:
>
> => mux deselect a-mux-controller 0
> => mux list
> a-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       no              0x1             0x1             0x4
>         1       no              0x1             0x1             0x4
>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> ---
>
> Notes:
>     Changes in v4:
>
>     - Use spaces to print columns in 'mux list' instead of tabs. Tabs don't
>       work well with ut_assert_nextline() because it calls
>       membuff_readline() down the call chain and tells it to consider
>       characters below the space character as EOL. This means
>       ut_assert_nextline() can only assert for the next column not the next
>       line if a command is using tabs.
>
>  cmd/Kconfig  |   6 ++
>  cmd/Makefile |   1 +
>  cmd/mux.c    | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 190 insertions(+)
>  create mode 100644 cmd/mux.c

Reviewed-by: Simon Glass <[hidden email]>

A few comments below.

>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index a3166e4f31..a25d6d62d0 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -1073,6 +1073,12 @@ config CMD_MTD
>         help
>           MTD commands support.
>
> +config CMD_MUX
> +       bool "mux"
> +       depends on MULTIPLEXER
> +       help
> +        List, select, and deselect mux controllers on the fly.
> +
>  config CMD_NAND
>         bool "nand"
>         default y if NAND_SUNXI
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 19a891633f..79a57b8482 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -104,6 +104,7 @@ obj-$(CONFIG_CMD_CLONE) += clone.o
>  ifneq ($(CONFIG_CMD_NAND)$(CONFIG_CMD_SF),)
>  obj-y += legacy-mtd-utils.o
>  endif
> +obj-$(CONFIG_CMD_MUX) += mux.o
>  obj-$(CONFIG_CMD_NAND) += nand.o
>  obj-$(CONFIG_CMD_NET) += net.o
>  obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
> diff --git a/cmd/mux.c b/cmd/mux.c
> new file mode 100644
> index 0000000000..3a0839ec1f
> --- /dev/null
> +++ b/cmd/mux.c
> @@ -0,0 +1,183 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * List, select, and deselect mux controllers on the fly.
> + *
> + * Copyright (c) 2020 Texas Instruments Inc.
> + * Author: Pratyush Yadav <[hidden email]>
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <errno.h>
> +#include <dm.h>
> +#include <mux.h>
> +#include <mux-internal.h>
> +#include <linux/err.h>
> +#include <dt-bindings/mux/mux.h>
> +
> +#define COLUMN_SIZE 16
> +
> +/*
> + * Print a member of a column. The total size of the text printed, including
> + * trailing whitespace, will always be COLUMN_SIZE.
> + */
> +#define PRINT_COLUMN(fmt, args...) do {                                        \
> +       char buf[COLUMN_SIZE + 1];                                      \
> +       snprintf(buf, COLUMN_SIZE + 1, fmt, ##args);                    \
> +       printf("%-*s", COLUMN_SIZE, buf);                               \
> +} while (0)

This blows out the code size. How about a static function instead?

> +
> +/*
> + * Find a mux based on its device name in argv[1] and index in the chip in
> + * argv[2].
> + */
> +static struct mux_control *cmd_mux_find(char *const argv[])

Is it worth having a pointer here? You could return the argument as an
int and have a struct mux_control** param here. Up to you.

> +{
> +       struct udevice *dev;
> +       struct mux_chip *chip;
> +       int ret;
> +       unsigned long id;
> +
> +       ret = strict_strtoul(argv[2], 10, &id);
> +       if (ret)
> +               return ERR_PTR(ret);
> +
> +       ret = uclass_get_device_by_name(UCLASS_MUX, argv[1], &dev);
> +       if (ret)
> +               return ERR_PTR(ret);
> +
> +       chip = dev_get_uclass_priv(dev);
> +       if (!chip)
> +               return ERR_PTR(ret);
> +
> +       if (id >= chip->controllers)
> +               return ERR_PTR(-EINVAL);
> +
> +       return &chip->mux[id];
> +}
> +
> +/*
> + * Print the details of a mux. The columns printed correspond to: "Selected",
> + * "Current State", "Idle State", and "Num States".
> + */
> +static void print_mux(struct mux_control *mux)
> +{
> +       PRINT_COLUMN("%s", mux->in_use ? "yes" : "no");
> +
> +       if (mux->cached_state == MUX_IDLE_AS_IS)
> +               PRINT_COLUMN("%s", "unknown");
> +       else
> +               PRINT_COLUMN("0x%x", mux->cached_state);
> +
> +       if (mux->idle_state == MUX_IDLE_AS_IS)
> +               PRINT_COLUMN("%s", "as-is");
> +       else if (mux->idle_state == MUX_IDLE_DISCONNECT)
> +               PRINT_COLUMN("%s", "disconnect");
> +       else
> +               PRINT_COLUMN("0x%x", mux->idle_state);
> +
> +       PRINT_COLUMN("0x%x", mux->states);
> +
> +       printf("\n");
> +}
> +
> +static int do_mux_list(struct cmd_tbl *cmdtp, int flag, int argc,
> +                      char *const argv[])
> +{
> +       struct udevice *dev;
> +       struct mux_chip *chip;
> +       int j;
> +
> +       for (uclass_first_device(UCLASS_MUX, &dev);
> +            dev;
> +            uclass_next_device(&dev)) {

uclass_for_each_device() or similar

> +               chip = dev_get_uclass_priv(dev);
> +               if (!chip) {
> +                       dev_err(dev, "can't find mux chip\n");
> +                       continue;
> +               }
> +

Regards,
Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 1/7] drivers: Add a new framework for multiplexer devices

Tom Rini-4
In reply to this post by Pratyush Yadav
On Fri, Oct 16, 2020 at 04:16:30PM +0530, Pratyush Yadav wrote:

> From: Jean-Jacques Hiblot <[hidden email]>
>
> Add a new subsystem that handles multiplexer controllers. The API is the
> same as in Linux.
>
> Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
> Reviewed-by: Simon Glass <[hidden email]>
> Signed-off-by: Pratyush Yadav <[hidden email]>

Applied to u-boot/master, thanks!

--
Tom

signature.asc (673 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 2/7] dm: board: complete the initialization of the muxes in initr_dm()

Tom Rini-4
In reply to this post by Pratyush Yadav
On Fri, Oct 16, 2020 at 04:16:31PM +0530, Pratyush Yadav wrote:

> From: Jean-Jacques Hiblot <[hidden email]>
>
> This will probe the multiplexer devices that have a "u-boot,mux-autoprobe"
> property. As a consequence they will be put in their idle state.
>
> Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
> Reviewed-by: Simon Glass <[hidden email]>
> Signed-off-by: Pratyush Yadav <[hidden email]>

Applied to u-boot/master, thanks!

--
Tom

signature.asc (673 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 3/7] drivers: mux: mmio-based syscon mux controller

Tom Rini-4
In reply to this post by Pratyush Yadav
On Fri, Oct 16, 2020 at 04:16:32PM +0530, Pratyush Yadav wrote:

> From: Jean-Jacques Hiblot <[hidden email]>
>
> This adds a driver for mmio-based syscon multiplexers controlled by
> bitfields in a syscon register range.
> This is heavily based on the linux mmio-mux driver.
>
> Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
> Reviewed-by: Simon Glass <[hidden email]>
> Signed-off-by: Pratyush Yadav <[hidden email]>

Applied to u-boot/master, thanks!

--
Tom

signature.asc (673 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 4/7] Kconfig: Increase the pre-relocation memory

Tom Rini-4
In reply to this post by Pratyush Yadav
On Fri, Oct 16, 2020 at 04:16:33PM +0530, Pratyush Yadav wrote:

> The memory is close to full and adding a syscon node in test.dts makes
> it go over the limit and makes malloc() fail on startup.
>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> Reviewed-by: Simon Glass <[hidden email]>

Applied to u-boot/master, thanks!

--
Tom

signature.asc (673 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 5/7] test: Add tests for the multiplexer framework

Tom Rini-4
In reply to this post by Pratyush Yadav
On Fri, Oct 16, 2020 at 04:16:34PM +0530, Pratyush Yadav wrote:

> From: Jean-Jacques Hiblot <[hidden email]>
>
> Provide tests to check the behavior of the multiplexer framework.
>
> Two sets of tests are added. One is using an emulated multiplexer driver
> that can be used to test basic functionality like select, deselect, etc.
> The other is using the mmio mux which adds tests specific to it.
>
> Signed-off-by: Jean-Jacques Hiblot <[hidden email]>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> Reviewed-by: Simon Glass <[hidden email]>
Applied to u-boot/master, thanks!

--
Tom

signature.asc (673 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 6/7] cmd: Add a mux command

Tom Rini-4
In reply to this post by Pratyush Yadav
On Fri, Oct 16, 2020 at 04:16:35PM +0530, Pratyush Yadav wrote:

> This command lets the user list, select, and deselect mux controllers
> introduced with the mux framework on the fly. It has 3 subcommands:
> list, select, and deselect.
>
> List: Lists all the mux present on the system. The muxes are listed for
> each chip. The chip is identified by its device name. Each chip can have
> a number of mux controllers. Each is listed in sequence and is assigned
> a sequential ID based on its position in the mux chip. It lists details
> like ID, whether the mux is currently selected or not, the current
> state, the idle state, and the number of states.
>
> A sample output would look something like:
>
> => mux list
> a-mux-controller:
> ID Selected Current State Idle State Num States
> 0 no         unknown   as-is     0x4
> 1 no         0x2       0x2       0x10
> 2 no         0x73       0x73       0x100
>
> another-mux-controller:
> ID Selected Current State Idle State Num States
>         0       no              0x1             0x1             0x4
>         1       no              0x2             0x2             0x4
>
> Select: Selects a given mux and puts it in the specified state. This
> subcommand takes 3 arguments: mux chip, mux ID, state to set
> the mux in. The arguments mux chip and mux ID are used to identify which
> mux needs to be selected, and then it is selected to the given state.
> The mux needs to be deselected before it can be selected again in
> another state. The state should be a hexadecimal number.
>
> For example:
> => mux list
> a-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       no              0x1             0x1             0x4
>         1       no              0x1             0x1             0x4
> => mux select a-mux-controller 0 0x3
> => mux list
> a-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       yes             0x3             0x1             0x4
>         1       no              0x1             0x1             0x4
>
> Deselect: Deselects a given mux and puts it in its idle state. This
> subcommand takes 2 arguments: the mux chip and mux ID to identify which
> mux needs to be deselected. So in the above example, we can deselect mux
> 0 using:
>
> => mux deselect a-mux-controller 0
> => mux list
> a-mux-controller:
>         ID      Selected        Current State   Idle State      Num States
>         0       no              0x1             0x1             0x4
>         1       no              0x1             0x1             0x4
>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> Reviewed-by: Simon Glass <[hidden email]>
Applied to u-boot/master, thanks!

--
Tom

signature.asc (673 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v4 7/7] test: mux-cmd: Add tests for the 'mux' command

Tom Rini-4
In reply to this post by Pratyush Yadav
On Fri, Oct 16, 2020 at 04:16:36PM +0530, Pratyush Yadav wrote:

> Tests tests run the three mux subcommands: list, select, and deselect,
> and verify that the commands do what we expect.
>
> Signed-off-by: Pratyush Yadav <[hidden email]>
> Reviewed-by: Simon Glass <[hidden email]>

Applied to u-boot/master, thanks!

--
Tom

signature.asc (673 bytes) Download Attachment