All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] SPI bus multiplexing
@ 2020-01-14 23:38 ` Chris Packham
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Packham @ 2020-01-14 23:38 UTC (permalink / raw)
  To: broonie, robh+dt, mark.rutland
  Cc: anthony.derosa, linux-spi, devicetree, linux-kernel, Chris Packham

This is a revisit of two earlier efforts to add more complex mutliplexing to
SPI busses.

https://patchwork.kernel.org/patch/2706151/
https://patchwork.kernel.org/patch/10897255/

This version makes use of the general purpose mux controller which simplifies
things greatly.

Chris Packham (2):
  dt-bindings: spi: Document binding for generic SPI multiplexer
  spi: Add generic SPI multiplexer

 .../devicetree/bindings/spi/spi-mux.yaml      |  82 ++++++++
 drivers/spi/Kconfig                           |  12 ++
 drivers/spi/Makefile                          |   1 +
 drivers/spi/spi-mux.c                         | 189 ++++++++++++++++++
 4 files changed, 284 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-mux.yaml
 create mode 100644 drivers/spi/spi-mux.c

-- 
2.25.0


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

* [PATCH 0/2] SPI bus multiplexing
@ 2020-01-14 23:38 ` Chris Packham
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Packham @ 2020-01-14 23:38 UTC (permalink / raw)
  To: broonie-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8
  Cc: anthony.derosa-ZdkzgDXte25Wk0Htik3J/w,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Chris Packham

This is a revisit of two earlier efforts to add more complex mutliplexing to
SPI busses.

https://patchwork.kernel.org/patch/2706151/
https://patchwork.kernel.org/patch/10897255/

This version makes use of the general purpose mux controller which simplifies
things greatly.

Chris Packham (2):
  dt-bindings: spi: Document binding for generic SPI multiplexer
  spi: Add generic SPI multiplexer

 .../devicetree/bindings/spi/spi-mux.yaml      |  82 ++++++++
 drivers/spi/Kconfig                           |  12 ++
 drivers/spi/Makefile                          |   1 +
 drivers/spi/spi-mux.c                         | 189 ++++++++++++++++++
 4 files changed, 284 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-mux.yaml
 create mode 100644 drivers/spi/spi-mux.c

-- 
2.25.0

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

* [PATCH 1/2] dt-bindings: spi: Document binding for generic SPI multiplexer
  2020-01-14 23:38 ` Chris Packham
  (?)
@ 2020-01-14 23:38 ` Chris Packham
  2020-01-15 18:45     ` Rob Herring
  -1 siblings, 1 reply; 9+ messages in thread
From: Chris Packham @ 2020-01-14 23:38 UTC (permalink / raw)
  To: broonie, robh+dt, mark.rutland
  Cc: anthony.derosa, linux-spi, devicetree, linux-kernel, Chris Packham

Add binding documentation for the spi-mux driver. This allows a generic
multiplexer to be used to provide access to multiple SPI devices.

Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
 .../devicetree/bindings/spi/spi-mux.yaml      | 82 +++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-mux.yaml

diff --git a/Documentation/devicetree/bindings/spi/spi-mux.yaml b/Documentation/devicetree/bindings/spi/spi-mux.yaml
new file mode 100644
index 000000000000..1026d03a69c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-mux.yaml
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/spi-mux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic SPI Multiplexer
+
+description: |
+  This binding describes a SPI bus multiplexer to route the SPI chip select
+  signals. This can be used when you need more devices than the SPI controller
+  has chip selects available. An example setup is shown in ASCII art; the actual
+  setting of the multiplexer to a channel needs to be done by a specific SPI mux
+  driver.
+
+        MOSI /--------------------------------+--------+--------+--------\
+        MISO |/------------------------------+|-------+|-------+|-------\|
+         SCL ||/----------------------------+||------+||------+||------\||
+             |||                            |||      |||      |||      |||
+      +------------+                        |||      |||      |||      |||
+      | SoC  |||   |                      +-+++-+  +-+++-+  +-+++-+  +-+++-+
+      |      |||   |                      | dev |  | dev |  | dev |  | dev |
+      |   +--+++-+ | CS-X  +------+\      +--+--+  +--+--+  +--+--+  +--+--+
+      |   | SPI  +-|-------+ Mux  |\\   CS-0 |        |        |        |
+      |   +------+ |       +--+---+\\\-------/   CS-1 |        |        |
+      |            |          |    \\\----------------/   CS-2 |        |
+      |   +------+ |          |     \\-------------------------/   CS-3 |
+      |   | ?    +-|----------/      \----------------------------------/
+      |   +------+ |
+      +------------+
+
+allOf:
+  - $ref: "/schemas/spi/spi-controller.yaml#"
+
+properties:
+  compatible:
+    const: spi-mux
+
+  mux-control:
+    $ref: "/schemas/mux/mux-controller.yaml#"
+
+required:
+   - compatible
+   - reg
+   - spi-max-frequency
+   - mux-control
+
+examples:
+   - |
+     mux: mux-controller {
+       compatible = "gpio-mux";
+       #mux-control-cells = <0>;
+
+       mux-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+     };
+
+     spi {
+       spi-mux {
+         compatible = "spi-mux";
+         #address-cells = <1>;
+         #size-cells = <0>;
+         reg = <0>;
+         spi-max-frequency = <100000000>;
+
+         mux-control = <&mux>
+         mux-control-names = "spi";
+
+         spi-flash@0 {
+           compatible = "jedec,spi-nor";
+           #address-cells = <1>;
+           #size-cells = <1>;
+           reg = <0>;
+           spi-max-frequency = <40000000>;
+         };
+
+         spi-device@1 {
+           compatible = "spidev";
+           reg = <1>;
+           spi-max-frequency = <10000000>;
+         };
+       };
+     };
-- 
2.25.0


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

* [PATCH 2/2] spi: Add generic SPI multiplexer
@ 2020-01-14 23:38   ` Chris Packham
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Packham @ 2020-01-14 23:38 UTC (permalink / raw)
  To: broonie, robh+dt, mark.rutland
  Cc: anthony.derosa, linux-spi, devicetree, linux-kernel, Chris Packham

Add a SPI device driver that sits in-band and provides a SPI controller
which supports chip selects via a mux-control. This enables extra SPI
devices to be connected with limited native chip selects.

Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
 drivers/spi/Kconfig   |  12 +++
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-mux.c | 189 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 202 insertions(+)
 create mode 100644 drivers/spi/spi-mux.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 870f7797b56b..90df945490d9 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -880,6 +880,18 @@ config SPI_ZYNQMP_GQSPI
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
+#
+
+comment "SPI Multiplexer support"
+
+config SPI_MUX
+	tristate "SPI multiplexer support"
+	select MULTIPLEXER
+	help
+	  This adds support for SPI multiplexers. Each SPI mux will be
+	  accessible as a SPI controller, the devices behind the mux will appear
+	  to be chip selects on this controller. It is still necessary to
+	  select one or more specific mux-controller drivers.
 
 #
 # There are lots of SPI device types, with sensors and memory
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index bb49c9e6d0a0..5f7593c84210 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SPI_MASTER)		+= spi.o
 obj-$(CONFIG_SPI_MEM)			+= spi-mem.o
 obj-$(CONFIG_SPI_SPIDEV)		+= spidev.o
 obj-$(CONFIG_SPI_LOOPBACK_TEST)		+= spi-loopback-test.o
+obj-$(CONFIG_SPI_MUX)			+= spi-mux.o
 
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_ALTERA)		+= spi-altera.o
diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c
new file mode 100644
index 000000000000..8481067be5ae
--- /dev/null
+++ b/drivers/spi/spi-mux.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * General Purpose SPI multiplexer
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/mux/consumer.h>
+
+#define SPI_MUX_NO_CS	((unsigned int)-1)
+
+/**
+ * DOC: Driver description
+ *
+ * This driver supports a MUX on an SPI bus. This can be useful when you need
+ * more chip selects than the hardware peripherals support, or than are
+ * available in a particular board setup.
+ *
+ * The driver will create an additional SPI controller. Devices added under the
+ * mux will be handled as 'chip selects' on this controller.
+ */
+
+/**
+ * struct spi_mux_priv - the basic spi_mux structure
+ * @spi:		pointer to the device struct attached to the parent
+ *			spi controller
+ * @current_cs:		The current chip select set in the mux
+ * @child_mesg_complete: The mux replaces the complete callback in the child's
+ *			message to its own callback; this field is used by the
+ *			driver to store the child's callback during a transfer
+ * @child_mesg_context: Used to store the child's context to the callback
+ * @child_mesg_dev:	Used to store the spi_device pointer to the child
+ * @mux:		mux_control structure used to provide chip selects for
+ *			downstream spi devices
+ */
+struct spi_mux_priv {
+	struct spi_device	*spi;
+	unsigned int		current_cs;
+
+	void			(*child_mesg_complete)(void *context);
+	void			*child_mesg_context;
+	struct spi_device	*child_mesg_dev;
+	struct mux_control	*mux;
+};
+
+/* should not get called when the parent controller is doing a transfer */
+static int spi_mux_select(struct spi_device *spi)
+{
+	struct spi_mux_priv *priv = spi_controller_get_devdata(spi->controller);
+	int ret = 0;
+
+	if (priv->current_cs != spi->chip_select) {
+		dev_dbg(&priv->spi->dev,
+			"setting up the mux for cs %d\n",
+			spi->chip_select);
+
+		/* copy the child device's settings except for the cs */
+		priv->spi->max_speed_hz = spi->max_speed_hz;
+		priv->spi->mode = spi->mode;
+		priv->spi->bits_per_word = spi->bits_per_word;
+
+		ret = mux_control_select(priv->mux, spi->chip_select);
+		if (ret)
+			return ret;
+
+		priv->current_cs = spi->chip_select;
+	}
+
+	return ret;
+}
+
+static int spi_mux_setup(struct spi_device *spi)
+{
+	struct spi_mux_priv *priv = spi_controller_get_devdata(spi->controller);
+
+	/*
+	 * can be called multiple times, won't do a valid setup now but we will
+	 * change the settings when we do a transfer (necessary because we
+	 * can't predict from which device it will be anyway)
+	 */
+	return spi_setup(priv->spi);
+}
+
+static void spi_mux_complete_cb(void *context)
+{
+	struct spi_mux_priv *priv = (struct spi_mux_priv *)context;
+	struct spi_controller *ctlr = spi_get_drvdata(priv->spi);
+	struct spi_message *m = ctlr->cur_msg;
+
+	m->complete = priv->child_mesg_complete;
+	m->context = priv->child_mesg_context;
+	m->spi = priv->child_mesg_dev;
+	spi_finalize_current_message(ctlr);
+	mux_control_deselect(priv->mux);
+}
+
+static int spi_mux_transfer_one_message(struct spi_controller *ctlr,
+						struct spi_message *m)
+{
+	struct spi_mux_priv *priv = spi_controller_get_devdata(ctlr);
+	struct spi_device *spi = m->spi;
+	int ret;
+
+	ret = spi_mux_select(spi);
+	if (ret)
+		return ret;
+
+	/*
+	 * Replace the complete callback, context and spi_device with our own
+	 * pointers. Save originals
+	 */
+	priv->child_mesg_complete = m->complete;
+	priv->child_mesg_context = m->context;
+	priv->child_mesg_dev = m->spi;
+
+	m->complete = spi_mux_complete_cb;
+	m->context = priv;
+	m->spi = priv->spi;
+
+	/* do the transfer */
+	ret = spi_async(priv->spi, m);
+	return ret;
+}
+
+static int spi_mux_probe(struct spi_device *spi)
+{
+	struct spi_controller *ctlr;
+	struct spi_mux_priv *priv;
+	int ret;
+
+	ctlr = spi_alloc_master(&spi->dev, sizeof(*priv));
+	if (!ctlr)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, ctlr);
+	priv = spi_controller_get_devdata(ctlr);
+	priv->spi = spi;
+
+	priv->mux = devm_mux_control_get(&spi->dev, NULL);
+	ret = PTR_ERR_OR_ZERO(priv->mux);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(&spi->dev, "failed to get control-mux\n");
+		goto err_put_ctlr;
+	}
+
+	priv->current_cs = SPI_MUX_NO_CS;
+
+	/* supported modes are the same as our parent's */
+	ctlr->mode_bits = spi->controller->mode_bits;
+	ctlr->flags = spi->controller->flags;
+	ctlr->transfer_one_message = spi_mux_transfer_one_message;
+	ctlr->setup = spi_mux_setup;
+	ctlr->num_chipselect = mux_control_states(priv->mux);
+	ctlr->bus_num = -1;
+	ctlr->dev.of_node = spi->dev.of_node;
+
+	ret = devm_spi_register_controller(&spi->dev, ctlr);
+	if (ret)
+		goto err_put_ctlr;
+
+	return ret;
+
+err_put_ctlr:
+	spi_controller_put(ctlr);
+
+	return ret;
+}
+
+static const struct of_device_id spi_mux_of_match[] = {
+	{ .compatible = "spi-mux" },
+	{ },
+};
+
+static struct spi_driver spi_mux_driver = {
+	.probe  = spi_mux_probe,
+	.driver = {
+		.name   = "spi-mux",
+		.of_match_table = spi_mux_of_match,
+	},
+};
+
+module_spi_driver(spi_mux_driver);
+
+MODULE_DESCRIPTION("SPI multiplexer");
+MODULE_LICENSE("GPL");
-- 
2.25.0


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

* [PATCH 2/2] spi: Add generic SPI multiplexer
@ 2020-01-14 23:38   ` Chris Packham
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Packham @ 2020-01-14 23:38 UTC (permalink / raw)
  To: broonie-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8
  Cc: anthony.derosa-ZdkzgDXte25Wk0Htik3J/w,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Chris Packham

Add a SPI device driver that sits in-band and provides a SPI controller
which supports chip selects via a mux-control. This enables extra SPI
devices to be connected with limited native chip selects.

Signed-off-by: Chris Packham <chris.packham-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
---
 drivers/spi/Kconfig   |  12 +++
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-mux.c | 189 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 202 insertions(+)
 create mode 100644 drivers/spi/spi-mux.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 870f7797b56b..90df945490d9 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -880,6 +880,18 @@ config SPI_ZYNQMP_GQSPI
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
+#
+
+comment "SPI Multiplexer support"
+
+config SPI_MUX
+	tristate "SPI multiplexer support"
+	select MULTIPLEXER
+	help
+	  This adds support for SPI multiplexers. Each SPI mux will be
+	  accessible as a SPI controller, the devices behind the mux will appear
+	  to be chip selects on this controller. It is still necessary to
+	  select one or more specific mux-controller drivers.
 
 #
 # There are lots of SPI device types, with sensors and memory
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index bb49c9e6d0a0..5f7593c84210 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SPI_MASTER)		+= spi.o
 obj-$(CONFIG_SPI_MEM)			+= spi-mem.o
 obj-$(CONFIG_SPI_SPIDEV)		+= spidev.o
 obj-$(CONFIG_SPI_LOOPBACK_TEST)		+= spi-loopback-test.o
+obj-$(CONFIG_SPI_MUX)			+= spi-mux.o
 
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_ALTERA)		+= spi-altera.o
diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c
new file mode 100644
index 000000000000..8481067be5ae
--- /dev/null
+++ b/drivers/spi/spi-mux.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * General Purpose SPI multiplexer
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/mux/consumer.h>
+
+#define SPI_MUX_NO_CS	((unsigned int)-1)
+
+/**
+ * DOC: Driver description
+ *
+ * This driver supports a MUX on an SPI bus. This can be useful when you need
+ * more chip selects than the hardware peripherals support, or than are
+ * available in a particular board setup.
+ *
+ * The driver will create an additional SPI controller. Devices added under the
+ * mux will be handled as 'chip selects' on this controller.
+ */
+
+/**
+ * struct spi_mux_priv - the basic spi_mux structure
+ * @spi:		pointer to the device struct attached to the parent
+ *			spi controller
+ * @current_cs:		The current chip select set in the mux
+ * @child_mesg_complete: The mux replaces the complete callback in the child's
+ *			message to its own callback; this field is used by the
+ *			driver to store the child's callback during a transfer
+ * @child_mesg_context: Used to store the child's context to the callback
+ * @child_mesg_dev:	Used to store the spi_device pointer to the child
+ * @mux:		mux_control structure used to provide chip selects for
+ *			downstream spi devices
+ */
+struct spi_mux_priv {
+	struct spi_device	*spi;
+	unsigned int		current_cs;
+
+	void			(*child_mesg_complete)(void *context);
+	void			*child_mesg_context;
+	struct spi_device	*child_mesg_dev;
+	struct mux_control	*mux;
+};
+
+/* should not get called when the parent controller is doing a transfer */
+static int spi_mux_select(struct spi_device *spi)
+{
+	struct spi_mux_priv *priv = spi_controller_get_devdata(spi->controller);
+	int ret = 0;
+
+	if (priv->current_cs != spi->chip_select) {
+		dev_dbg(&priv->spi->dev,
+			"setting up the mux for cs %d\n",
+			spi->chip_select);
+
+		/* copy the child device's settings except for the cs */
+		priv->spi->max_speed_hz = spi->max_speed_hz;
+		priv->spi->mode = spi->mode;
+		priv->spi->bits_per_word = spi->bits_per_word;
+
+		ret = mux_control_select(priv->mux, spi->chip_select);
+		if (ret)
+			return ret;
+
+		priv->current_cs = spi->chip_select;
+	}
+
+	return ret;
+}
+
+static int spi_mux_setup(struct spi_device *spi)
+{
+	struct spi_mux_priv *priv = spi_controller_get_devdata(spi->controller);
+
+	/*
+	 * can be called multiple times, won't do a valid setup now but we will
+	 * change the settings when we do a transfer (necessary because we
+	 * can't predict from which device it will be anyway)
+	 */
+	return spi_setup(priv->spi);
+}
+
+static void spi_mux_complete_cb(void *context)
+{
+	struct spi_mux_priv *priv = (struct spi_mux_priv *)context;
+	struct spi_controller *ctlr = spi_get_drvdata(priv->spi);
+	struct spi_message *m = ctlr->cur_msg;
+
+	m->complete = priv->child_mesg_complete;
+	m->context = priv->child_mesg_context;
+	m->spi = priv->child_mesg_dev;
+	spi_finalize_current_message(ctlr);
+	mux_control_deselect(priv->mux);
+}
+
+static int spi_mux_transfer_one_message(struct spi_controller *ctlr,
+						struct spi_message *m)
+{
+	struct spi_mux_priv *priv = spi_controller_get_devdata(ctlr);
+	struct spi_device *spi = m->spi;
+	int ret;
+
+	ret = spi_mux_select(spi);
+	if (ret)
+		return ret;
+
+	/*
+	 * Replace the complete callback, context and spi_device with our own
+	 * pointers. Save originals
+	 */
+	priv->child_mesg_complete = m->complete;
+	priv->child_mesg_context = m->context;
+	priv->child_mesg_dev = m->spi;
+
+	m->complete = spi_mux_complete_cb;
+	m->context = priv;
+	m->spi = priv->spi;
+
+	/* do the transfer */
+	ret = spi_async(priv->spi, m);
+	return ret;
+}
+
+static int spi_mux_probe(struct spi_device *spi)
+{
+	struct spi_controller *ctlr;
+	struct spi_mux_priv *priv;
+	int ret;
+
+	ctlr = spi_alloc_master(&spi->dev, sizeof(*priv));
+	if (!ctlr)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, ctlr);
+	priv = spi_controller_get_devdata(ctlr);
+	priv->spi = spi;
+
+	priv->mux = devm_mux_control_get(&spi->dev, NULL);
+	ret = PTR_ERR_OR_ZERO(priv->mux);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(&spi->dev, "failed to get control-mux\n");
+		goto err_put_ctlr;
+	}
+
+	priv->current_cs = SPI_MUX_NO_CS;
+
+	/* supported modes are the same as our parent's */
+	ctlr->mode_bits = spi->controller->mode_bits;
+	ctlr->flags = spi->controller->flags;
+	ctlr->transfer_one_message = spi_mux_transfer_one_message;
+	ctlr->setup = spi_mux_setup;
+	ctlr->num_chipselect = mux_control_states(priv->mux);
+	ctlr->bus_num = -1;
+	ctlr->dev.of_node = spi->dev.of_node;
+
+	ret = devm_spi_register_controller(&spi->dev, ctlr);
+	if (ret)
+		goto err_put_ctlr;
+
+	return ret;
+
+err_put_ctlr:
+	spi_controller_put(ctlr);
+
+	return ret;
+}
+
+static const struct of_device_id spi_mux_of_match[] = {
+	{ .compatible = "spi-mux" },
+	{ },
+};
+
+static struct spi_driver spi_mux_driver = {
+	.probe  = spi_mux_probe,
+	.driver = {
+		.name   = "spi-mux",
+		.of_match_table = spi_mux_of_match,
+	},
+};
+
+module_spi_driver(spi_mux_driver);
+
+MODULE_DESCRIPTION("SPI multiplexer");
+MODULE_LICENSE("GPL");
-- 
2.25.0

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

* Re: [PATCH 1/2] dt-bindings: spi: Document binding for generic SPI multiplexer
@ 2020-01-15 18:45     ` Rob Herring
  0 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2020-01-15 18:45 UTC (permalink / raw)
  To: Chris Packham
  Cc: Mark Brown, Mark Rutland, anthony.derosa, linux-spi, devicetree,
	linux-kernel

On Tue, Jan 14, 2020 at 5:39 PM Chris Packham
<chris.packham@alliedtelesis.co.nz> wrote:
>
> Add binding documentation for the spi-mux driver. This allows a generic
> multiplexer to be used to provide access to multiple SPI devices.
>
> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
> ---
>  .../devicetree/bindings/spi/spi-mux.yaml      | 82 +++++++++++++++++++
>  1 file changed, 82 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/spi/spi-mux.yaml

Be sure to run 'make dt_binding_check'.

>
> diff --git a/Documentation/devicetree/bindings/spi/spi-mux.yaml b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> new file mode 100644
> index 000000000000..1026d03a69c7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> @@ -0,0 +1,82 @@
> +# SPDX-License-Identifier: GPL-2.0

Dual license new bindings please:

(GPL-2.0-only OR BSD-2-Clause)

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/spi/spi-mux.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Generic SPI Multiplexer
> +
> +description: |
> +  This binding describes a SPI bus multiplexer to route the SPI chip select
> +  signals. This can be used when you need more devices than the SPI controller
> +  has chip selects available. An example setup is shown in ASCII art; the actual
> +  setting of the multiplexer to a channel needs to be done by a specific SPI mux
> +  driver.
> +
> +        MOSI /--------------------------------+--------+--------+--------\
> +        MISO |/------------------------------+|-------+|-------+|-------\|
> +         SCL ||/----------------------------+||------+||------+||------\||
> +             |||                            |||      |||      |||      |||
> +      +------------+                        |||      |||      |||      |||
> +      | SoC  |||   |                      +-+++-+  +-+++-+  +-+++-+  +-+++-+
> +      |      |||   |                      | dev |  | dev |  | dev |  | dev |
> +      |   +--+++-+ | CS-X  +------+\      +--+--+  +--+--+  +--+--+  +--+--+
> +      |   | SPI  +-|-------+ Mux  |\\   CS-0 |        |        |        |
> +      |   +------+ |       +--+---+\\\-------/   CS-1 |        |        |
> +      |            |          |    \\\----------------/   CS-2 |        |
> +      |   +------+ |          |     \\-------------------------/   CS-3 |
> +      |   | ?    +-|----------/      \----------------------------------/
> +      |   +------+ |
> +      +------------+
> +
> +allOf:
> +  - $ref: "/schemas/spi/spi-controller.yaml#"
> +
> +properties:
> +  compatible:
> +    const: spi-mux
> +
> +  mux-control:
> +    $ref: "/schemas/mux/mux-controller.yaml#"

That file doesn't exist. If it did, it would still be wrong as that
would be the provider side and this is the client.

The correct name is also 'mux-controls'.

You can assume it has a schema already and you just need to define how
many entries it has (maxItems: 1).

> +
> +required:
> +   - compatible
> +   - reg
> +   - spi-max-frequency
> +   - mux-control
> +
> +examples:
> +   - |
> +     mux: mux-controller {
> +       compatible = "gpio-mux";
> +       #mux-control-cells = <0>;
> +
> +       mux-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
> +     };
> +
> +     spi {
> +       spi-mux {

spi-mux@0

> +         compatible = "spi-mux";
> +         #address-cells = <1>;
> +         #size-cells = <0>;
> +         reg = <0>;
> +         spi-max-frequency = <100000000>;

I don't think this makes sense here. The mux doesn't really have any
frequency given the clock and data lines aren't routed thru the mux
(though maybe that's possible if some isolation is needed).

> +
> +         mux-control = <&mux>
> +         mux-control-names = "spi";

Not documented. Drop it as it's not all that useful when there's only 1 entry.

> +
> +         spi-flash@0 {
> +           compatible = "jedec,spi-nor";
> +           #address-cells = <1>;
> +           #size-cells = <1>;
> +           reg = <0>;
> +           spi-max-frequency = <40000000>;
> +         };
> +
> +         spi-device@1 {
> +           compatible = "spidev";

Not a valid compatible.

> +           reg = <1>;
> +           spi-max-frequency = <10000000>;
> +         };
> +       };
> +     };
> --
> 2.25.0
>

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

* Re: [PATCH 1/2] dt-bindings: spi: Document binding for generic SPI multiplexer
@ 2020-01-15 18:45     ` Rob Herring
  0 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2020-01-15 18:45 UTC (permalink / raw)
  To: Chris Packham
  Cc: Mark Brown, Mark Rutland, anthony.derosa-ZdkzgDXte25Wk0Htik3J/w,
	linux-spi, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Tue, Jan 14, 2020 at 5:39 PM Chris Packham
<chris.packham-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org> wrote:
>
> Add binding documentation for the spi-mux driver. This allows a generic
> multiplexer to be used to provide access to multiple SPI devices.
>
> Signed-off-by: Chris Packham <chris.packham-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
> ---
>  .../devicetree/bindings/spi/spi-mux.yaml      | 82 +++++++++++++++++++
>  1 file changed, 82 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/spi/spi-mux.yaml

Be sure to run 'make dt_binding_check'.

>
> diff --git a/Documentation/devicetree/bindings/spi/spi-mux.yaml b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> new file mode 100644
> index 000000000000..1026d03a69c7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> @@ -0,0 +1,82 @@
> +# SPDX-License-Identifier: GPL-2.0

Dual license new bindings please:

(GPL-2.0-only OR BSD-2-Clause)

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/spi/spi-mux.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Generic SPI Multiplexer
> +
> +description: |
> +  This binding describes a SPI bus multiplexer to route the SPI chip select
> +  signals. This can be used when you need more devices than the SPI controller
> +  has chip selects available. An example setup is shown in ASCII art; the actual
> +  setting of the multiplexer to a channel needs to be done by a specific SPI mux
> +  driver.
> +
> +        MOSI /--------------------------------+--------+--------+--------\
> +        MISO |/------------------------------+|-------+|-------+|-------\|
> +         SCL ||/----------------------------+||------+||------+||------\||
> +             |||                            |||      |||      |||      |||
> +      +------------+                        |||      |||      |||      |||
> +      | SoC  |||   |                      +-+++-+  +-+++-+  +-+++-+  +-+++-+
> +      |      |||   |                      | dev |  | dev |  | dev |  | dev |
> +      |   +--+++-+ | CS-X  +------+\      +--+--+  +--+--+  +--+--+  +--+--+
> +      |   | SPI  +-|-------+ Mux  |\\   CS-0 |        |        |        |
> +      |   +------+ |       +--+---+\\\-------/   CS-1 |        |        |
> +      |            |          |    \\\----------------/   CS-2 |        |
> +      |   +------+ |          |     \\-------------------------/   CS-3 |
> +      |   | ?    +-|----------/      \----------------------------------/
> +      |   +------+ |
> +      +------------+
> +
> +allOf:
> +  - $ref: "/schemas/spi/spi-controller.yaml#"
> +
> +properties:
> +  compatible:
> +    const: spi-mux
> +
> +  mux-control:
> +    $ref: "/schemas/mux/mux-controller.yaml#"

That file doesn't exist. If it did, it would still be wrong as that
would be the provider side and this is the client.

The correct name is also 'mux-controls'.

You can assume it has a schema already and you just need to define how
many entries it has (maxItems: 1).

> +
> +required:
> +   - compatible
> +   - reg
> +   - spi-max-frequency
> +   - mux-control
> +
> +examples:
> +   - |
> +     mux: mux-controller {
> +       compatible = "gpio-mux";
> +       #mux-control-cells = <0>;
> +
> +       mux-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
> +     };
> +
> +     spi {
> +       spi-mux {

spi-mux@0

> +         compatible = "spi-mux";
> +         #address-cells = <1>;
> +         #size-cells = <0>;
> +         reg = <0>;
> +         spi-max-frequency = <100000000>;

I don't think this makes sense here. The mux doesn't really have any
frequency given the clock and data lines aren't routed thru the mux
(though maybe that's possible if some isolation is needed).

> +
> +         mux-control = <&mux>
> +         mux-control-names = "spi";

Not documented. Drop it as it's not all that useful when there's only 1 entry.

> +
> +         spi-flash@0 {
> +           compatible = "jedec,spi-nor";
> +           #address-cells = <1>;
> +           #size-cells = <1>;
> +           reg = <0>;
> +           spi-max-frequency = <40000000>;
> +         };
> +
> +         spi-device@1 {
> +           compatible = "spidev";

Not a valid compatible.

> +           reg = <1>;
> +           spi-max-frequency = <10000000>;
> +         };
> +       };
> +     };
> --
> 2.25.0
>

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

* Re: [PATCH 1/2] dt-bindings: spi: Document binding for generic SPI multiplexer
@ 2020-01-15 20:49       ` Chris Packham
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Packham @ 2020-01-15 20:49 UTC (permalink / raw)
  To: robh+dt
  Cc: linux-spi, mark.rutland, linux-kernel, broonie, anthony.derosa,
	devicetree

Hi Rob,

On Wed, 2020-01-15 at 12:45 -0600, Rob Herring wrote:
> On Tue, Jan 14, 2020 at 5:39 PM Chris Packham
> <chris.packham@alliedtelesis.co.nz> wrote:
> > 
> > Add binding documentation for the spi-mux driver. This allows a
> > generic
> > multiplexer to be used to provide access to multiple SPI devices.
> > 
> > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
> > ---
> >  .../devicetree/bindings/spi/spi-mux.yaml      | 82
> > +++++++++++++++++++
> >  1 file changed, 82 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/spi/spi-
> > mux.yaml
> 
> Be sure to run 'make dt_binding_check'.
> 

Will do.

> > 
> > diff --git a/Documentation/devicetree/bindings/spi/spi-mux.yaml
> > b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> > new file mode 100644
> > index 000000000000..1026d03a69c7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> > @@ -0,0 +1,82 @@
> > +# SPDX-License-Identifier: GPL-2.0
> 
> Dual license new bindings please:
> 
> (GPL-2.0-only OR BSD-2-Clause)
> 

Done

> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/spi/spi-mux.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Generic SPI Multiplexer
> > +
> > +description: |
> > +  This binding describes a SPI bus multiplexer to route the SPI
> > chip select
> > +  signals. This can be used when you need more devices than the
> > SPI controller
> > +  has chip selects available. An example setup is shown in ASCII
> > art; the actual
> > +  setting of the multiplexer to a channel needs to be done by a
> > specific SPI mux
> > +  driver.
> > +
> > +        MOSI /--------------------------------+--------+--------+-
> > -------\
> > +        MISO |/------------------------------+|-------+|-------+|-
> > ------\|
> > +         SCL ||/----------------------------+||------+||------+||-
> > -----\||
> > +             |||                            |||      |||      ||| 
> >      |||
> > +      +----------
> > --+                        |||      |||      |||      |||
> > +      | SoC  |||   |                      +-+++-+  +-+++-+  +-+++-
> > +  +-+++-+
> > +      |      |||   |                      | dev |  | dev |  | dev
> > |  | dev |
> > +      |   +--+++-+ | CS-X  +------+\      +--+--+  +--+--+  +--+
> > --+  +--+--+
> > +      |   | SPI  +-|-------+ Mux  |\\   CS-0
> > |        |        |        |
> > +      |   +------+ |       +--+---+\\\-------/   CS-1
> > |        |        |
> > +      |            |          |    \\\----------------/   CS-2
> > |        |
> > +      |   +------+ |          |     \\-------------------------
> > /   CS-3 |
> > +      |   | ?    +-|----------/      \--------------------------
> > --------/
> > +      |   +------+ |
> > +      +------------+
> > +
> > +allOf:
> > +  - $ref: "/schemas/spi/spi-controller.yaml#"
> > +
> > +properties:
> > +  compatible:
> > +    const: spi-mux
> > +
> > +  mux-control:
> > +    $ref: "/schemas/mux/mux-controller.yaml#"
> 
> That file doesn't exist. If it did, it would still be wrong as that
> would be the provider side and this is the client.
> 
> The correct name is also 'mux-controls'.
> 
> You can assume it has a schema already and you just need to define
> how
> many entries it has (maxItems: 1).

I might need a little hand holding on this. Should I assume that there
is a separate schema for the consumer? Or leave out the $ref entirely?

> > +
> > +required:
> > +   - compatible
> > +   - reg
> > +   - spi-max-frequency
> > +   - mux-control
> > +
> > +examples:
> > +   - |
> > +     mux: mux-controller {
> > +       compatible = "gpio-mux";
> > +       #mux-control-cells = <0>;
> > +
> > +       mux-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
> > +     };
> > +
> > +     spi {
> > +       spi-mux {
> 
> spi-mux@0
> 

Done.

> > +         compatible = "spi-mux";
> > +         #address-cells = <1>;
> > +         #size-cells = <0>;
> > +         reg = <0>;
> > +         spi-max-frequency = <100000000>;
> 
> I don't think this makes sense here. The mux doesn't really have any
> frequency given the clock and data lines aren't routed thru the mux
> (though maybe that's possible if some isolation is needed).
> 

It's needed to satisfy of_spi_parse_dt().To remove it I'd need to add
an escape hatch to allow this property to be omitted for spi-muxes. Or
change it to be a platform device and take the parent spi bus as a
phandle.

> > +
> > +         mux-control = <&mux>
> > +         mux-control-names = "spi";
> 
> Not documented. Drop it as it's not all that useful when there's only
> 1 entry.

Done. Also updated mux-control -> mux-controls

> > +
> > +         spi-flash@0 {
> > +           compatible = "jedec,spi-nor";
> > +           #address-cells = <1>;
> > +           #size-cells = <1>;
> > +           reg = <0>;
> > +           spi-max-frequency = <40000000>;
> > +         };
> > +
> > +         spi-device@1 {
> > +           compatible = "spidev";
> 
> Not a valid compatible.
> 

Picked a different one.

> > +           reg = <1>;
> > +           spi-max-frequency = <10000000>;
> > +         };
> > +       };
> > +     };
> > --
> > 2.25.0
> > 

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

* Re: [PATCH 1/2] dt-bindings: spi: Document binding for generic SPI multiplexer
@ 2020-01-15 20:49       ` Chris Packham
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Packham @ 2020-01-15 20:49 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A
  Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	broonie-DgEjT+Ai2ygdnm+yROfE0A,
	anthony.derosa-ZdkzgDXte25Wk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Rob,

On Wed, 2020-01-15 at 12:45 -0600, Rob Herring wrote:
> On Tue, Jan 14, 2020 at 5:39 PM Chris Packham
> <chris.packham@alliedtelesis.co.nz> wrote:
> > 
> > Add binding documentation for the spi-mux driver. This allows a
> > generic
> > multiplexer to be used to provide access to multiple SPI devices.
> > 
> > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
> > ---
> >  .../devicetree/bindings/spi/spi-mux.yaml      | 82
> > +++++++++++++++++++
> >  1 file changed, 82 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/spi/spi-
> > mux.yaml
> 
> Be sure to run 'make dt_binding_check'.
> 

Will do.

> > 
> > diff --git a/Documentation/devicetree/bindings/spi/spi-mux.yaml
> > b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> > new file mode 100644
> > index 000000000000..1026d03a69c7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/spi/spi-mux.yaml
> > @@ -0,0 +1,82 @@
> > +# SPDX-License-Identifier: GPL-2.0
> 
> Dual license new bindings please:
> 
> (GPL-2.0-only OR BSD-2-Clause)
> 

Done

> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/spi/spi-mux.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Generic SPI Multiplexer
> > +
> > +description: |
> > +  This binding describes a SPI bus multiplexer to route the SPI
> > chip select
> > +  signals. This can be used when you need more devices than the
> > SPI controller
> > +  has chip selects available. An example setup is shown in ASCII
> > art; the actual
> > +  setting of the multiplexer to a channel needs to be done by a
> > specific SPI mux
> > +  driver.
> > +
> > +        MOSI /--------------------------------+--------+--------+-
> > -------\
> > +        MISO |/------------------------------+|-------+|-------+|-
> > ------\|
> > +         SCL ||/----------------------------+||------+||------+||-
> > -----\||
> > +             |||                            |||      |||      ||| 
> >      |||
> > +      +----------
> > --+                        |||      |||      |||      |||
> > +      | SoC  |||   |                      +-+++-+  +-+++-+  +-+++-
> > +  +-+++-+
> > +      |      |||   |                      | dev |  | dev |  | dev
> > |  | dev |
> > +      |   +--+++-+ | CS-X  +------+\      +--+--+  +--+--+  +--+
> > --+  +--+--+
> > +      |   | SPI  +-|-------+ Mux  |\\   CS-0
> > |        |        |        |
> > +      |   +------+ |       +--+---+\\\-------/   CS-1
> > |        |        |
> > +      |            |          |    \\\----------------/   CS-2
> > |        |
> > +      |   +------+ |          |     \\-------------------------
> > /   CS-3 |
> > +      |   | ?    +-|----------/      \--------------------------
> > --------/
> > +      |   +------+ |
> > +      +------------+
> > +
> > +allOf:
> > +  - $ref: "/schemas/spi/spi-controller.yaml#"
> > +
> > +properties:
> > +  compatible:
> > +    const: spi-mux
> > +
> > +  mux-control:
> > +    $ref: "/schemas/mux/mux-controller.yaml#"
> 
> That file doesn't exist. If it did, it would still be wrong as that
> would be the provider side and this is the client.
> 
> The correct name is also 'mux-controls'.
> 
> You can assume it has a schema already and you just need to define
> how
> many entries it has (maxItems: 1).

I might need a little hand holding on this. Should I assume that there
is a separate schema for the consumer? Or leave out the $ref entirely?

> > +
> > +required:
> > +   - compatible
> > +   - reg
> > +   - spi-max-frequency
> > +   - mux-control
> > +
> > +examples:
> > +   - |
> > +     mux: mux-controller {
> > +       compatible = "gpio-mux";
> > +       #mux-control-cells = <0>;
> > +
> > +       mux-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
> > +     };
> > +
> > +     spi {
> > +       spi-mux {
> 
> spi-mux@0
> 

Done.

> > +         compatible = "spi-mux";
> > +         #address-cells = <1>;
> > +         #size-cells = <0>;
> > +         reg = <0>;
> > +         spi-max-frequency = <100000000>;
> 
> I don't think this makes sense here. The mux doesn't really have any
> frequency given the clock and data lines aren't routed thru the mux
> (though maybe that's possible if some isolation is needed).
> 

It's needed to satisfy of_spi_parse_dt().To remove it I'd need to add
an escape hatch to allow this property to be omitted for spi-muxes. Or
change it to be a platform device and take the parent spi bus as a
phandle.

> > +
> > +         mux-control = <&mux>
> > +         mux-control-names = "spi";
> 
> Not documented. Drop it as it's not all that useful when there's only
> 1 entry.

Done. Also updated mux-control -> mux-controls

> > +
> > +         spi-flash@0 {
> > +           compatible = "jedec,spi-nor";
> > +           #address-cells = <1>;
> > +           #size-cells = <1>;
> > +           reg = <0>;
> > +           spi-max-frequency = <40000000>;
> > +         };
> > +
> > +         spi-device@1 {
> > +           compatible = "spidev";
> 
> Not a valid compatible.
> 

Picked a different one.

> > +           reg = <1>;
> > +           spi-max-frequency = <10000000>;
> > +         };
> > +       };
> > +     };
> > --
> > 2.25.0
> > 

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

end of thread, other threads:[~2020-01-15 20:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-14 23:38 [PATCH 0/2] SPI bus multiplexing Chris Packham
2020-01-14 23:38 ` Chris Packham
2020-01-14 23:38 ` [PATCH 1/2] dt-bindings: spi: Document binding for generic SPI multiplexer Chris Packham
2020-01-15 18:45   ` Rob Herring
2020-01-15 18:45     ` Rob Herring
2020-01-15 20:49     ` Chris Packham
2020-01-15 20:49       ` Chris Packham
2020-01-14 23:38 ` [PATCH 2/2] spi: Add " Chris Packham
2020-01-14 23:38   ` Chris Packham

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.