All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] serdev multiplexing support
@ 2017-08-16 13:22 Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 1/6] serdev: add method to set parity Ulrich Hecht
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Ulrich Hecht @ 2017-08-16 13:22 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh,
	peda, geert, linux-i2c, Ulrich Hecht

Hi!

Here's a new version of serdev multiplexing support. Thanks to everybody who
commented; I think I have included all non-optional suggestions. :)
Changes are manifold, please refer to the changelog below.

This version drops "mux: include compiler.h from mux/consumer.h",
which is on its way upstream by now.

CU
Uli


Changes since RFC v2:
- parity: use an enum instead of the traditional enable/odd flags
- mux: include it in the serdev core, remove option
- mux: add "select MULTIPLEXER" to Kconfig
- serdev: use device "reg" node as serdev_device::nr
- mux: check if device has an of_node before trying to register mux
- serdev: remove check for !serdev->ops in,
  serdev_controller_write_wakeup(), it is not needed
- max9260: replace register numbers, magic protocol bytes and device ID with
  macros
- max9260: use enum instead of macros for the rx_state
- max9260: use wait_event_timeout() instead of
  wait_event_interruptible_timeout()
- max9260: pass all parameters for max9260_transact() as arguments
- max9260: add "max9260_" prefix to max9260_wait_for_transaction()
- max9260: return -ENODEV instead of -EINVAL if the device does not respond
  correctly
- max9260: change a number of length-bearing variables to size_t
- dt: number max9260 devices according to their "reg" node


Ulrich Hecht (6):
  serdev: add method to set parity
  serdev: add multiplexer support
  serial: core: support deferring serdev controller registration
  max9260: add driver for i2c over GMSL passthrough
  ARM: dts: blanche: add SCIF1 and MAX9260 deserializer
  dt-bindings: slave-device: add reg property

 .../devicetree/bindings/serial/slave-device.txt    |   2 +
 arch/arm/boot/dts/r8a7792-blanche.dts              |  52 ++++
 drivers/media/i2c/Kconfig                          |   6 +
 drivers/media/i2c/Makefile                         |   1 +
 drivers/media/i2c/max9260.c                        | 300 +++++++++++++++++++++
 drivers/tty/serdev/Kconfig                         |   1 +
 drivers/tty/serdev/Makefile                        |   2 +-
 drivers/tty/serdev/core.c                          |  25 +-
 drivers/tty/serdev/mux.c                           |  66 +++++
 drivers/tty/serdev/serdev-ttyport.c                |  18 ++
 drivers/tty/serial/serial_core.c                   |   4 +
 include/linux/serdev.h                             |  24 +-
 12 files changed, 497 insertions(+), 4 deletions(-)
 create mode 100644 drivers/media/i2c/max9260.c
 create mode 100644 drivers/tty/serdev/mux.c

-- 
2.7.4

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

* [PATCH 1/6] serdev: add method to set parity
  2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
@ 2017-08-16 13:22 ` Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 2/6] serdev: add multiplexer support Ulrich Hecht
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Ulrich Hecht @ 2017-08-16 13:22 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh,
	peda, geert, linux-i2c, Ulrich Hecht

Adds serdev_device_set_parity() and an implementation for ttyport.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/tty/serdev/core.c           | 12 ++++++++++++
 drivers/tty/serdev/serdev-ttyport.c | 18 ++++++++++++++++++
 include/linux/serdev.h              | 10 ++++++++++
 3 files changed, 40 insertions(+)

diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index ae1aaa0..8491056 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -242,6 +242,18 @@ int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear)
 }
 EXPORT_SYMBOL_GPL(serdev_device_set_tiocm);
 
+int serdev_device_set_parity(struct serdev_device *serdev,
+			     enum serdev_parity parity)
+{
+	struct serdev_controller *ctrl = serdev->ctrl;
+
+	if (!ctrl || !ctrl->ops->set_parity)
+		return -ENOTSUPP;
+
+	return ctrl->ops->set_parity(ctrl, parity);
+}
+EXPORT_SYMBOL_GPL(serdev_device_set_parity);
+
 static int serdev_drv_probe(struct device *dev)
 {
 	const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index 302018d..2883f12 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -195,6 +195,23 @@ static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, u
 	return tty->driver->ops->tiocmset(tty, set, clear);
 }
 
+static int ttyport_set_parity(struct serdev_controller *ctrl,
+			      enum serdev_parity parity)
+{
+	struct serport *serport = serdev_controller_get_drvdata(ctrl);
+	struct tty_struct *tty = serport->tty;
+	struct ktermios ktermios = tty->termios;
+
+	ktermios.c_cflag &= ~(PARENB | PARODD);
+	if (parity != SERDEV_PARITY_NONE) {
+		ktermios.c_cflag |= PARENB;
+		if (parity == SERDEV_PARITY_ODD)
+			ktermios.c_cflag |= PARODD;
+	}
+
+	return tty_set_termios(tty, &ktermios);
+}
+
 static const struct serdev_controller_ops ctrl_ops = {
 	.write_buf = ttyport_write_buf,
 	.write_flush = ttyport_write_flush,
@@ -206,6 +223,7 @@ static const struct serdev_controller_ops ctrl_ops = {
 	.wait_until_sent = ttyport_wait_until_sent,
 	.get_tiocm = ttyport_get_tiocm,
 	.set_tiocm = ttyport_set_tiocm,
+	.set_parity = ttyport_set_parity,
 };
 
 struct device *serdev_tty_port_register(struct tty_port *port,
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index e69402d..8f60f11 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -76,6 +76,12 @@ static inline struct serdev_device_driver *to_serdev_device_driver(struct device
 	return container_of(d, struct serdev_device_driver, driver);
 }
 
+enum serdev_parity {
+	SERDEV_PARITY_NONE,
+	SERDEV_PARITY_EVEN,
+	SERDEV_PARITY_ODD,
+};
+
 /*
  * serdev controller structures
  */
@@ -90,6 +96,7 @@ struct serdev_controller_ops {
 	void (*wait_until_sent)(struct serdev_controller *, long);
 	int (*get_tiocm)(struct serdev_controller *);
 	int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int);
+	int (*set_parity)(struct serdev_controller *, enum serdev_parity);
 };
 
 /**
@@ -298,6 +305,9 @@ static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enabl
 		return serdev_device_set_tiocm(serdev, 0, TIOCM_RTS);
 }
 
+int serdev_device_set_parity(struct serdev_device *serdev,
+			     enum serdev_parity parity);
+
 /*
  * serdev hooks into TTY core
  */
-- 
2.7.4

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

* [PATCH 2/6] serdev: add multiplexer support
  2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 1/6] serdev: add method to set parity Ulrich Hecht
@ 2017-08-16 13:22 ` Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 3/6] serial: core: support deferring serdev controller registration Ulrich Hecht
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Ulrich Hecht @ 2017-08-16 13:22 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh,
	peda, geert, linux-i2c, Ulrich Hecht

Adds an interface for slave device multiplexing using the mux subsystem.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/tty/serdev/Kconfig  |  1 +
 drivers/tty/serdev/Makefile |  2 +-
 drivers/tty/serdev/core.c   | 13 ++++++++-
 drivers/tty/serdev/mux.c    | 66 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/serdev.h      | 14 ++++++++--
 5 files changed, 92 insertions(+), 4 deletions(-)
 create mode 100644 drivers/tty/serdev/mux.c

diff --git a/drivers/tty/serdev/Kconfig b/drivers/tty/serdev/Kconfig
index cdc6b82..8fd75cb 100644
--- a/drivers/tty/serdev/Kconfig
+++ b/drivers/tty/serdev/Kconfig
@@ -3,6 +3,7 @@
 #
 menuconfig SERIAL_DEV_BUS
 	tristate "Serial device bus"
+	select MULTIPLEXER
 	help
 	  Core support for devices connected via a serial port.
 
diff --git a/drivers/tty/serdev/Makefile b/drivers/tty/serdev/Makefile
index 0cbdb94..abe5b2a 100644
--- a/drivers/tty/serdev/Makefile
+++ b/drivers/tty/serdev/Makefile
@@ -1,5 +1,5 @@
 serdev-objs := core.o
 
-obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o
+obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o mux.o
 
 obj-$(CONFIG_SERIAL_DEV_CTRL_TTYPORT) += serdev-ttyport.o
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 8491056..22acd08 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -307,7 +307,8 @@ struct serdev_device *serdev_device_alloc(struct serdev_controller *ctrl)
 		return NULL;
 
 	serdev->ctrl = ctrl;
-	ctrl->serdev = serdev;
+	if (!ctrl->serdev)
+		ctrl->serdev = serdev;
 	device_initialize(&serdev->dev);
 	serdev->dev.parent = &ctrl->dev;
 	serdev->dev.bus = &serdev_bus_type;
@@ -370,6 +371,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
 	struct serdev_device *serdev = NULL;
 	int err;
 	bool found = false;
+	u32 reg;
 
 	for_each_available_child_of_node(ctrl->dev.of_node, node) {
 		if (!of_get_property(node, "compatible", NULL))
@@ -383,6 +385,11 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
 
 		serdev->dev.of_node = node;
 
+		if (!of_property_read_u32(node, "reg", &reg)) {
+			serdev->mux_addr = reg;
+			serdev->nr = reg;
+		}
+
 		err = serdev_device_add(serdev);
 		if (err) {
 			dev_err(&serdev->dev,
@@ -416,6 +423,10 @@ int serdev_controller_add(struct serdev_controller *ctrl)
 	if (ret)
 		return ret;
 
+	if (ctrl->dev.of_node &&
+	    of_serdev_register_mux(ctrl) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
 	ret = of_serdev_register_devices(ctrl);
 	if (ret)
 		goto out_dev_del;
diff --git a/drivers/tty/serdev/mux.c b/drivers/tty/serdev/mux.c
new file mode 100644
index 0000000..fc9405b
--- /dev/null
+++ b/drivers/tty/serdev/mux.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 Ulrich Hecht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mux/consumer.h>
+#include <linux/mux/driver.h>
+#include <linux/of_gpio.h>
+#include <linux/serdev.h>
+#include <linux/slab.h>
+
+int serdev_device_mux_select(struct serdev_device *serdev)
+{
+	struct mux_control *mux = serdev->ctrl->mux;
+	int ret;
+
+	if (!mux)
+		return -EINVAL;
+
+	ret = mux_control_select(mux, serdev->mux_addr);
+	serdev->ctrl->mux_do_not_deselect = ret < 0;
+
+	serdev->ctrl->serdev = serdev;
+
+	return ret;
+}
+
+int serdev_device_mux_deselect(struct serdev_device *serdev)
+{
+	struct mux_control *mux = serdev->ctrl->mux;
+
+	if (!mux)
+		return -EINVAL;
+
+	if (!serdev->ctrl->mux_do_not_deselect)
+		return mux_control_deselect(mux);
+	else
+		return 0;
+}
+
+int of_serdev_register_mux(struct serdev_controller *ctrl)
+{
+	struct mux_control *mux;
+	struct device *dev = &ctrl->dev;
+
+	mux = devm_mux_control_get(dev, NULL);
+
+	if (IS_ERR(mux)) {
+		if (PTR_ERR(mux) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get control mux\n");
+		return PTR_ERR(mux);
+	}
+
+	ctrl->mux = mux;
+
+	return 0;
+}
+
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 8f60f11..3ed0f75 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/termios.h>
 #include <linux/delay.h>
+#include <linux/rtmutex.h>
 
 struct serdev_controller;
 struct serdev_device;
@@ -51,6 +52,7 @@ struct serdev_device {
 	const struct serdev_device_ops *ops;
 	struct completion write_comp;
 	struct mutex write_lock;
+	int mux_addr;
 };
 
 static inline struct serdev_device *to_serdev_device(struct device *d)
@@ -82,6 +84,8 @@ enum serdev_parity {
 	SERDEV_PARITY_ODD,
 };
 
+int of_serdev_register_mux(struct serdev_controller *ctrl);
+
 /*
  * serdev controller structures
  */
@@ -103,14 +107,18 @@ struct serdev_controller_ops {
  * struct serdev_controller - interface to the serdev controller
  * @dev:	Driver model representation of the device.
  * @nr:		number identifier for this controller/bus.
- * @serdev:	Pointer to slave device for this controller.
+ * @serdev:	Pointer to active slave device for this controller.
  * @ops:	Controller operations.
+ * @mux:	Slave multiplexer control.
+ * @mux_do_not_deselect: Set if slave selection failed.
  */
 struct serdev_controller {
 	struct device		dev;
 	unsigned int		nr;
 	struct serdev_device	*serdev;
 	const struct serdev_controller_ops *ops;
+	struct mux_control	*mux;
+	int			mux_do_not_deselect;
 };
 
 static inline struct serdev_controller *to_serdev_controller(struct device *d)
@@ -190,7 +198,7 @@ static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl,
 {
 	struct serdev_device *serdev = ctrl->serdev;
 
-	if (!serdev || !serdev->ops->receive_buf)
+	if (!serdev || !serdev->ops || !serdev->ops->receive_buf)
 		return -EINVAL;
 
 	return serdev->ops->receive_buf(serdev, data, count);
@@ -210,6 +218,8 @@ void serdev_device_write_wakeup(struct serdev_device *);
 int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, unsigned long);
 void serdev_device_write_flush(struct serdev_device *);
 int serdev_device_write_room(struct serdev_device *);
+int serdev_device_mux_select(struct serdev_device *);
+int serdev_device_mux_deselect(struct serdev_device *);
 
 /*
  * serdev device driver functions
-- 
2.7.4

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

* [PATCH 3/6] serial: core: support deferring serdev controller registration
  2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 1/6] serdev: add method to set parity Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 2/6] serdev: add multiplexer support Ulrich Hecht
@ 2017-08-16 13:22 ` Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 4/6] max9260: add driver for i2c over GMSL passthrough Ulrich Hecht
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Ulrich Hecht @ 2017-08-16 13:22 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh,
	peda, geert, linux-i2c, Ulrich Hecht

serdev controllers may depend on other devices (such as multiplexers)
and thus require deferred probing support.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/tty/serial/serial_core.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index f534a40..30a8997 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2785,6 +2785,10 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 			uport->line, uport->dev, port, uport->tty_groups);
 	if (likely(!IS_ERR(tty_dev))) {
 		device_set_wakeup_capable(tty_dev, 1);
+	} else if (PTR_ERR(tty_dev) == -EPROBE_DEFER) {
+		ret = -EPROBE_DEFER;
+		state->uart_port = NULL;
+		goto out;
 	} else {
 		dev_err(uport->dev, "Cannot register tty device on line %d\n",
 		       uport->line);
-- 
2.7.4

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

* [PATCH 4/6] max9260: add driver for i2c over GMSL passthrough
  2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
                   ` (2 preceding siblings ...)
  2017-08-16 13:22 ` [PATCH 3/6] serial: core: support deferring serdev controller registration Ulrich Hecht
@ 2017-08-16 13:22 ` Ulrich Hecht
  2017-08-16 13:22 ` [PATCH 5/6] ARM: dts: blanche: add SCIF1 and MAX9260 deserializer Ulrich Hecht
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Ulrich Hecht @ 2017-08-16 13:22 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh,
	peda, geert, linux-i2c, Ulrich Hecht

This driver implements tunnelling of i2c requests over GMSL via a
MAX9260 deserializer. It provides an i2c adapter that can be used
to reach devices on the far side of the link.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/media/i2c/Kconfig   |   6 +
 drivers/media/i2c/Makefile  |   1 +
 drivers/media/i2c/max9260.c | 300 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 307 insertions(+)
 create mode 100644 drivers/media/i2c/max9260.c

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index fa2e7d8..b85ae78 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -424,6 +424,12 @@ config VIDEO_VPX3220
 	  To compile this driver as a module, choose M here: the
 	  module will be called vpx3220.
 
+config VIDEO_MAX9260
+	tristate "Maxim MAX9260 GMSL deserializer support"
+	depends on I2C
+	---help---
+	  This driver supports the Maxim MAX9260 GMSL deserializer.
+
 comment "Video and audio decoders"
 
 config VIDEO_SAA717X
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 30e856c..3b6f6f2 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
 obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
 obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
 obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
+obj-$(CONFIG_VIDEO_MAX9260) += max9260.o
 obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
 obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o
 obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
diff --git a/drivers/media/i2c/max9260.c b/drivers/media/i2c/max9260.c
new file mode 100644
index 0000000..9c890ab
--- /dev/null
+++ b/drivers/media/i2c/max9260.c
@@ -0,0 +1,300 @@
+/*
+ * Maxim MAX9260 GMSL Deserializer Driver
+ *
+ * Copyright (C) 2017 Ulrich Hecht
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/serdev.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+
+#define SYNC	0x79
+#define ACK	0xc3
+
+#define REG_ID		0x1e
+
+#define ID_MAX9260	0x02
+
+enum max9260_rx_state {
+	RX_FINISHED,
+	RX_FRAME_ERROR,
+	RX_EXPECT_ACK,
+	RX_EXPECT_ACK_DATA,
+	RX_EXPECT_DATA,
+};
+
+struct max9260_device {
+	struct serdev_device *serdev;
+	u8 *rx_buf;
+	size_t rx_len;
+	enum max9260_rx_state rx_state;
+	wait_queue_head_t rx_wq;
+	struct i2c_adapter adap;
+};
+
+static void max9260_wait_for_transaction(struct max9260_device *dev)
+{
+	wait_event_timeout(dev->rx_wq, dev->rx_state <= RX_FRAME_ERROR,
+		HZ/2);
+}
+
+static void max9260_transact(struct max9260_device *dev,
+			     int expect,
+			     const u8 *request, int len,
+			     u8 *rx_buf, int rx_len)
+{
+	dev->rx_buf = rx_buf;
+	dev->rx_len = rx_len;
+
+	serdev_device_mux_select(dev->serdev);
+
+	serdev_device_set_baudrate(dev->serdev, 115200);
+	serdev_device_set_parity(dev->serdev, SERDEV_PARITY_EVEN);
+
+	dev->rx_state = expect;
+	serdev_device_write_buf(dev->serdev, request, len);
+
+	max9260_wait_for_transaction(dev);
+
+	serdev_device_mux_deselect(dev->serdev);
+}
+
+static int max9260_read_reg(struct max9260_device *dev, int reg)
+{
+	u8 request[] = { SYNC, 0x91, reg, 1 };
+	u8 rx;
+
+	dev->rx_len = 1;
+	dev->rx_buf = &rx;
+
+	max9260_transact(dev, RX_EXPECT_ACK_DATA, request,
+			 ARRAY_SIZE(request),
+			 &rx, 1);
+
+	if (dev->rx_state == RX_FINISHED)
+		return rx;
+
+	return -EIO;
+}
+
+static int max9260_setup(struct max9260_device *dev)
+{
+	int ret;
+
+	ret = max9260_read_reg(dev, REG_ID);
+
+	if (ret != ID_MAX9260) {
+		dev_err(&dev->serdev->dev,
+			"device does not identify as MAX9260\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void max9260_uart_write_wakeup(struct serdev_device *serdev)
+{
+}
+
+static int max9260_uart_receive_buf(struct serdev_device *serdev,
+				    const u8 *data, size_t count)
+{
+	struct max9260_device *dev = serdev_device_get_drvdata(serdev);
+	size_t accepted;
+
+	switch (dev->rx_state) {
+	case RX_FINISHED:
+		dev_dbg(&dev->serdev->dev, "excess data ignored\n");
+		return count;
+
+	case RX_EXPECT_ACK:
+	case RX_EXPECT_ACK_DATA:
+		if (data[0] != ACK) {
+			dev_dbg(&dev->serdev->dev, "frame error");
+			dev->rx_state = RX_FRAME_ERROR;
+			wake_up_interruptible(&dev->rx_wq);
+			return 1;
+		}
+
+		if (dev->rx_state == RX_EXPECT_ACK_DATA) {
+			dev->rx_state = RX_EXPECT_DATA;
+		} else {
+			dev->rx_state = RX_FINISHED;
+			wake_up_interruptible(&dev->rx_wq);
+		}
+		return 1;
+
+	case RX_EXPECT_DATA:
+		accepted = min(dev->rx_len, count);
+
+		memcpy(dev->rx_buf, data, accepted);
+
+		dev->rx_len -= accepted;
+		dev->rx_buf += accepted;
+
+		if (!dev->rx_len) {
+			dev->rx_state = RX_FINISHED;
+			wake_up_interruptible(&dev->rx_wq);
+		}
+
+		return accepted;
+
+	case RX_FRAME_ERROR:
+		dev_dbg(&dev->serdev->dev, "%d bytes ignored\n", count);
+		return count;
+
+	}
+	return 0;
+}
+
+static const struct serdev_device_ops max9260_serdev_client_ops = {
+	.receive_buf = max9260_uart_receive_buf,
+	.write_wakeup = max9260_uart_write_wakeup,
+};
+
+static u32 max9260_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static s32 max9260_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+	unsigned short flags, char read_write, u8 command, int size,
+	union i2c_smbus_data *data)
+{
+	u8 request[] = { SYNC,
+			 (addr << 1) + (read_write == I2C_SMBUS_READ),
+			 command, 0, 0 };
+	struct max9260_device *dev = i2c_get_adapdata(adap);
+
+	switch (size) {
+	case I2C_SMBUS_BYTE:
+		if (read_write == I2C_SMBUS_WRITE) {
+			max9260_transact(dev, RX_EXPECT_ACK, request, 4,
+					 NULL, 0);
+			dev_dbg(&adap->dev,
+				"smbus byte - addr 0x%02x, wrote 0x%02x.\n",
+				addr, command);
+		} else {
+			/* TBD */
+			return -EOPNOTSUPP;
+		}
+		break;
+
+	case I2C_SMBUS_BYTE_DATA:
+		request[3] = 1;
+		if (read_write == I2C_SMBUS_WRITE) {
+			request[4] = data->byte;
+			max9260_transact(dev, RX_EXPECT_ACK, request, 5,
+					 NULL, 0);
+			dev_dbg(&adap->dev,
+				"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
+				addr, data->byte, command);
+		} else {
+			max9260_transact(dev, RX_EXPECT_ACK_DATA, request, 4,
+					 &data->byte, 1);
+			dev_dbg(&adap->dev,
+				"smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n",
+				addr, data->byte, command);
+		}
+		break;
+	default:
+		dev_dbg(&adap->dev,
+			"Unsupported I2C/SMBus command %d\n", size);
+		return -EOPNOTSUPP;
+	}
+
+	if (dev->rx_state != RX_FINISHED) {
+		dev_dbg(&adap->dev, "xfer timed out\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static const struct i2c_algorithm max9260_i2c_algorithm = {
+	.functionality	= max9260_i2c_func,
+	.smbus_xfer	= max9260_smbus_xfer,
+};
+
+static int max9260_probe(struct serdev_device *serdev)
+{
+	struct max9260_device *dev;
+	struct i2c_adapter *adap;
+	int ret;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	init_waitqueue_head(&dev->rx_wq);
+
+	dev->serdev = serdev;
+	serdev_device_open(serdev);
+	serdev_device_set_drvdata(serdev, dev);
+
+	serdev_device_set_client_ops(serdev, &max9260_serdev_client_ops);
+
+	ret = max9260_setup(dev);
+	if (ret < 0)
+		goto err_free;
+
+	adap = &dev->adap;
+	i2c_set_adapdata(adap, dev);
+
+	adap->owner = THIS_MODULE;
+	adap->algo = &max9260_i2c_algorithm;
+	adap->dev.parent = &serdev->dev;
+	adap->retries = 5;
+	strlcpy(adap->name, dev_name(&serdev->dev), sizeof(adap->name));
+
+	ret = i2c_add_adapter(adap);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+
+err_free:
+	kfree(dev);
+	return ret;
+}
+
+static void max9260_remove(struct serdev_device *serdev)
+{
+	struct max9260_device *dev = serdev_device_get_drvdata(serdev);
+
+	serdev_device_close(dev->serdev);
+
+	kfree(dev);
+}
+
+static const struct of_device_id max9260_dt_ids[] = {
+	{ .compatible = "maxim,max9260" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, max9260_dt_ids);
+
+static struct serdev_device_driver max9260_driver = {
+	.probe = max9260_probe,
+	.remove = max9260_remove,
+	.driver = {
+		.name = "max9260",
+		.of_match_table = of_match_ptr(max9260_dt_ids),
+	},
+};
+
+module_serdev_device_driver(max9260_driver);
+
+MODULE_DESCRIPTION("Maxim MAX9260 GMSL Deserializer Driver");
+MODULE_AUTHOR("Ulrich Hecht");
+MODULE_LICENSE("GPL");
-- 
2.7.4

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

* [PATCH 5/6] ARM: dts: blanche: add SCIF1 and MAX9260 deserializer
  2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
                   ` (3 preceding siblings ...)
  2017-08-16 13:22 ` [PATCH 4/6] max9260: add driver for i2c over GMSL passthrough Ulrich Hecht
@ 2017-08-16 13:22 ` Ulrich Hecht
  2017-08-21  8:54   ` Simon Horman
  2017-08-16 13:22 ` [PATCH 6/6] dt-bindings: slave-device: add reg property Ulrich Hecht
  2017-08-28 12:55 ` [PATCH 0/6] serdev multiplexing support Greg KH
  6 siblings, 1 reply; 10+ messages in thread
From: Ulrich Hecht @ 2017-08-16 13:22 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh,
	peda, geert, linux-i2c, Ulrich Hecht

Adds serial port SCIF1 and the MAX9260 deserializers connected to it.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 arch/arm/boot/dts/r8a7792-blanche.dts | 52 +++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7792-blanche.dts b/arch/arm/boot/dts/r8a7792-blanche.dts
index 9b67dca..0c1a6a0 100644
--- a/arch/arm/boot/dts/r8a7792-blanche.dts
+++ b/arch/arm/boot/dts/r8a7792-blanche.dts
@@ -21,6 +21,7 @@
 	aliases {
 		serial0 = &scif0;
 		serial1 = &scif3;
+		serial2 = &scif1;
 	};
 
 	chosen {
@@ -186,6 +187,16 @@
 		gpio = <&gpio11 12 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	mux: mux-controller {
+		compatible = "gpio-mux";
+		#mux-control-cells = <0>;
+
+		mux-gpios = <&gpio5 12 GPIO_ACTIVE_HIGH>,
+			    <&gpio5 13 GPIO_ACTIVE_HIGH>,
+			    <&gpio5 14 GPIO_ACTIVE_HIGH>,
+			    <&gpio5 15 GPIO_ACTIVE_HIGH>;
+	};
 };
 
 &extal_clk {
@@ -202,6 +213,11 @@
 		function = "scif0";
 	};
 
+	scif1_pins: scif1 {
+		groups = "scif1_data";
+		function = "scif1";
+	};
+
 	scif3_pins: scif3 {
 		groups = "scif3_data";
 		function = "scif3";
@@ -246,6 +262,42 @@
 	status = "okay";
 };
 
+&scif1 {
+	pinctrl-0 = <&scif1_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	mux-controls = <&mux>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gmsl-deserializer@8 {
+		compatible = "maxim,max9260";
+		reg = <0x8>;
+	};
+	gmsl-deserializer@9 {
+		compatible = "maxim,max9260";
+		reg = <0x9>;
+	};
+	gmsl-deserializer@a {
+		compatible = "maxim,max9260";
+		reg = <0xa>;
+	};
+	gmsl-deserializer@b {
+		compatible = "maxim,max9260";
+		reg = <0xb>;
+	};
+	gmsl-deserializer@4 {
+		compatible = "maxim,max9260";
+		reg = <0x4>;
+	};
+	gmsl-deserializer@5 {
+		compatible = "maxim,max9260";
+		reg = <0x5>;
+	};
+};
+
 &scif3 {
 	pinctrl-0 = <&scif3_pins>;
 	pinctrl-names = "default";
-- 
2.7.4

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

* [PATCH 6/6] dt-bindings: slave-device: add reg property
  2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
                   ` (4 preceding siblings ...)
  2017-08-16 13:22 ` [PATCH 5/6] ARM: dts: blanche: add SCIF1 and MAX9260 deserializer Ulrich Hecht
@ 2017-08-16 13:22 ` Ulrich Hecht
  2017-08-16 13:27   ` Laurent Pinchart
  2017-08-28 12:55 ` [PATCH 0/6] serdev multiplexing support Greg KH
  6 siblings, 1 reply; 10+ messages in thread
From: Ulrich Hecht @ 2017-08-16 13:22 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh,
	peda, geert, linux-i2c, Ulrich Hecht

This adds a new DT property to define the index used by a multiplexer to
select the device.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 Documentation/devicetree/bindings/serial/slave-device.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/slave-device.txt b/Documentation/devicetree/bindings/serial/slave-device.txt
index 40110e0..f9b0783 100644
--- a/Documentation/devicetree/bindings/serial/slave-device.txt
+++ b/Documentation/devicetree/bindings/serial/slave-device.txt
@@ -30,6 +30,8 @@ Optional Properties:
 		      way to reset the device
 		    * device baud rate is configured by its firmware but
 		      there is no way to request the actual settings
+- reg		: Index used to select the device if it is controlled by a
+		  multiplexer.
 
 Example:
 
-- 
2.7.4

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

* Re: [PATCH 6/6] dt-bindings: slave-device: add reg property
  2017-08-16 13:22 ` [PATCH 6/6] dt-bindings: slave-device: add reg property Ulrich Hecht
@ 2017-08-16 13:27   ` Laurent Pinchart
  0 siblings, 0 replies; 10+ messages in thread
From: Laurent Pinchart @ 2017-08-16 13:27 UTC (permalink / raw)
  To: Ulrich Hecht
  Cc: linux-serial, linux-renesas-soc, magnus.damm, wsa, robh, peda,
	geert, linux-i2c

Hi Ulrich,

Thank you for the patch.

On Wednesday 16 Aug 2017 15:22:28 Ulrich Hecht wrote:
> This adds a new DT property to define the index used by a multiplexer to
> select the device.
> 
> Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
> ---
>  Documentation/devicetree/bindings/serial/slave-device.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/serial/slave-device.txt
> b/Documentation/devicetree/bindings/serial/slave-device.txt index
> 40110e0..f9b0783 100644
> --- a/Documentation/devicetree/bindings/serial/slave-device.txt
> +++ b/Documentation/devicetree/bindings/serial/slave-device.txt
> @@ -30,6 +30,8 @@ Optional Properties:
>  		      way to reset the device
>  		    * device baud rate is configured by its firmware but
>  		      there is no way to request the actual settings
> +- reg		: Index used to select the device if it is controlled 
by a
> +		  multiplexer.

The reg property should describe the device address on the bus it is connected 
to. This seems like an abuse of the property to me. The device shouldn't care 
about the multiplexer, I think you should describe the hardware by adding the 
serial device's DT node as a child of the multiplexer's port it is connected 
to.

>  Example:

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 5/6] ARM: dts: blanche: add SCIF1 and MAX9260 deserializer
  2017-08-16 13:22 ` [PATCH 5/6] ARM: dts: blanche: add SCIF1 and MAX9260 deserializer Ulrich Hecht
@ 2017-08-21  8:54   ` Simon Horman
  0 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2017-08-21  8:54 UTC (permalink / raw)
  To: Ulrich Hecht
  Cc: linux-serial, linux-renesas-soc, magnus.damm, laurent.pinchart,
	wsa, robh, peda, geert, linux-i2c

On Wed, Aug 16, 2017 at 03:22:27PM +0200, Ulrich Hecht wrote:
> Adds serial port SCIF1 and the MAX9260 deserializers connected to it.
> 
> Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>

Hi Ulrich,

I am marking this patch as deferred pending progress on the rest of the
series.

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

* Re: [PATCH 0/6] serdev multiplexing support
  2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
                   ` (5 preceding siblings ...)
  2017-08-16 13:22 ` [PATCH 6/6] dt-bindings: slave-device: add reg property Ulrich Hecht
@ 2017-08-28 12:55 ` Greg KH
  6 siblings, 0 replies; 10+ messages in thread
From: Greg KH @ 2017-08-28 12:55 UTC (permalink / raw)
  To: Ulrich Hecht
  Cc: linux-serial, linux-renesas-soc, magnus.damm, laurent.pinchart,
	wsa, robh, peda, geert, linux-i2c

On Wed, Aug 16, 2017 at 03:22:22PM +0200, Ulrich Hecht wrote:
> Hi!
> 
> Here's a new version of serdev multiplexing support. Thanks to everybody who
> commented; I think I have included all non-optional suggestions. :)
> Changes are manifold, please refer to the changelog below.
> 
> This version drops "mux: include compiler.h from mux/consumer.h",
> which is on its way upstream by now.
> 
> CU
> Uli

Rob, any thoughts on this series?

thanks,

greg k-h

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

end of thread, other threads:[~2017-08-28 12:55 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-16 13:22 [PATCH 0/6] serdev multiplexing support Ulrich Hecht
2017-08-16 13:22 ` [PATCH 1/6] serdev: add method to set parity Ulrich Hecht
2017-08-16 13:22 ` [PATCH 2/6] serdev: add multiplexer support Ulrich Hecht
2017-08-16 13:22 ` [PATCH 3/6] serial: core: support deferring serdev controller registration Ulrich Hecht
2017-08-16 13:22 ` [PATCH 4/6] max9260: add driver for i2c over GMSL passthrough Ulrich Hecht
2017-08-16 13:22 ` [PATCH 5/6] ARM: dts: blanche: add SCIF1 and MAX9260 deserializer Ulrich Hecht
2017-08-21  8:54   ` Simon Horman
2017-08-16 13:22 ` [PATCH 6/6] dt-bindings: slave-device: add reg property Ulrich Hecht
2017-08-16 13:27   ` Laurent Pinchart
2017-08-28 12:55 ` [PATCH 0/6] serdev multiplexing support Greg KH

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.