All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] USB: serial: xr: Add TIOCGRS485 and TIOCSRS485 ioctls
@ 2023-03-13  1:04 Jarkko Sonninen
  2023-03-13  7:00 ` Greg Kroah-Hartman
  2023-03-14  7:00 ` [PATCH v3] " Jarkko Sonninen
  0 siblings, 2 replies; 29+ messages in thread
From: Jarkko Sonninen @ 2023-03-13  1:04 UTC (permalink / raw)
  Cc: kasper, Johan Hovold, Greg Kroah-Hartman, linux-usb, linux-kernel

Add support for RS-485 in Exar USB adapters.
RS-485 mode is controlled by TIOCGRS485 and TIOCSRS485 ioctls.
Gpio mode register is set to enable RS-485.

Signed-off-by: Jarkko Sonninen <kasper@iki.fi>
---
 drivers/usb/serial/xr_serial.c | 72 +++++++++++++++++++++++++++++++++-
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/serial/xr_serial.c b/drivers/usb/serial/xr_serial.c
index fdb0aae546c3..edbb6add087c 100644
--- a/drivers/usb/serial/xr_serial.c
+++ b/drivers/usb/serial/xr_serial.c
@@ -93,6 +93,7 @@ struct xr_txrx_clk_mask {
 #define XR_GPIO_MODE_SEL_DTR_DSR	0x2
 #define XR_GPIO_MODE_SEL_RS485		0x3
 #define XR_GPIO_MODE_SEL_RS485_ADDR	0x4
+#define XR_GPIO_MODE_RS485_TX_H		0x8
 #define XR_GPIO_MODE_TX_TOGGLE		0x100
 #define XR_GPIO_MODE_RX_TOGGLE		0x200
 
@@ -237,6 +238,8 @@ static const struct xr_type xr_types[] = {
 struct xr_data {
 	const struct xr_type *type;
 	u8 channel;			/* zero-based index or interface number */
+	struct serial_rs485 rs485;
+	spinlock_t lock;
 };
 
 static int xr_set_reg(struct usb_serial_port *port, u8 channel, u16 reg, u16 val)
@@ -629,6 +632,7 @@ static void xr_set_flow_mode(struct tty_struct *tty,
 	struct xr_data *data = usb_get_serial_port_data(port);
 	const struct xr_type *type = data->type;
 	u16 flow, gpio_mode;
+	unsigned long flags, rs485_flags;
 	int ret;
 
 	ret = xr_get_reg_uart(port, type->gpio_mode, &gpio_mode);
@@ -645,9 +649,16 @@ static void xr_set_flow_mode(struct tty_struct *tty,
 	/* Set GPIO mode for controlling the pins manually by default. */
 	gpio_mode &= ~XR_GPIO_MODE_SEL_MASK;
 
+	spin_lock_irqsave(&data->lock, flags);
+	rs485_flags = data->rs485.flags;
+	spin_unlock_irqrestore(&data->lock, flags);
+	if (rs485_flags & SER_RS485_ENABLED)
+		gpio_mode |= XR_GPIO_MODE_SEL_RS485 | XR_GPIO_MODE_RS485_TX_H;
+	else if (C_CRTSCTS(tty) && C_BAUD(tty) != B0)
+		gpio_mode |= XR_GPIO_MODE_SEL_RTS_CTS;
+
 	if (C_CRTSCTS(tty) && C_BAUD(tty) != B0) {
 		dev_dbg(&port->dev, "Enabling hardware flow ctrl\n");
-		gpio_mode |= XR_GPIO_MODE_SEL_RTS_CTS;
 		flow = XR_UART_FLOW_MODE_HW;
 	} else if (I_IXON(tty)) {
 		u8 start_char = START_CHAR(tty);
@@ -827,6 +838,64 @@ static void xr_set_termios(struct tty_struct *tty,
 	xr_set_flow_mode(tty, port, old_termios);
 }
 
+static int xr_get_rs485_config(struct tty_struct *tty,
+			 unsigned int __user *argp)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct xr_data *data = usb_get_serial_port_data(port);
+	unsigned long flags;
+	struct serial_rs485 rs485;
+
+	spin_lock_irqsave(&data->lock, flags);
+	memcpy(&rs485, &data->rs485, sizeof(rs485));
+	spin_unlock_irqrestore(&data->lock, flags);
+	dev_dbg(tty->dev, "%s flags %02x\n", __func__, rs485.flags);
+
+	if (copy_to_user(argp, &rs485, sizeof(rs485)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int xr_set_rs485_config(struct tty_struct *tty,
+			 unsigned long __user *argp)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct xr_data *data = usb_get_serial_port_data(port);
+	struct serial_rs485 rs485;
+	unsigned long flags;
+
+	if (copy_from_user(&rs485, argp, sizeof(rs485)))
+		return -EFAULT;
+
+	dev_dbg(tty->dev, "%s flags %02x\n", __func__, rs485.flags);
+	rs485.flags &= SER_RS485_ENABLED;
+	spin_lock_irqsave(&data->lock, flags);
+	memcpy(&data->rs485, &rs485, sizeof(rs485));
+	spin_unlock_irqrestore(&data->lock, flags);
+	xr_set_flow_mode(tty, port, 0);
+
+	if (copy_to_user(argp, &data->rs485, sizeof(data->rs485)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int xr_ioctl(struct tty_struct *tty,
+					unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+
+	switch (cmd) {
+	case TIOCGRS485:
+		return xr_get_rs485_config(tty, argp);
+	case TIOCSRS485:
+		return xr_set_rs485_config(tty, argp);
+	}
+	return -ENOIOCTLCMD;
+}
+
 static int xr_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	int ret;
@@ -1010,6 +1079,7 @@ static struct usb_serial_driver xr_device = {
 	.set_termios		= xr_set_termios,
 	.tiocmget		= xr_tiocmget,
 	.tiocmset		= xr_tiocmset,
+	.ioctl			= xr_ioctl,
 	.dtr_rts		= xr_dtr_rts
 };
 
-- 
2.34.1


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

end of thread, other threads:[~2023-07-20 13:52 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-13  1:04 [PATCH] USB: serial: xr: Add TIOCGRS485 and TIOCSRS485 ioctls Jarkko Sonninen
2023-03-13  7:00 ` Greg Kroah-Hartman
2023-03-13  7:49   ` Jarkko Sonninen
2023-03-13  7:53     ` Greg Kroah-Hartman
2023-03-13  8:27       ` [PATCH v2] " Jarkko Sonninen
2023-03-13  8:45         ` Greg Kroah-Hartman
2023-03-13  9:54         ` Oliver Neukum
2023-03-13 10:47           ` Jarkko Sonninen
2023-03-13 11:27             ` Oliver Neukum
2023-03-13 23:02         ` David Laight
2023-03-14  6:19         ` kernel test robot
2023-03-13 15:07       ` [PATCH] " Jarkko Sonninen
2023-03-13 15:50         ` Greg Kroah-Hartman
2023-03-13 15:53           ` Jarkko Sonninen
2023-03-13 20:18           ` Oliver Neukum
2023-03-14  7:00 ` [PATCH v3] " Jarkko Sonninen
2023-03-14  7:37   ` Greg Kroah-Hartman
2023-03-14  8:00     ` Jarkko Sonninen
2023-04-13  8:57     ` Johan Hovold
2023-04-13  8:53   ` Johan Hovold
2023-04-16  8:40     ` Jarkko Sonninen
2023-04-17 14:50       ` Johan Hovold
2023-04-23 18:59         ` [PATCH v4] " Jarkko Sonninen
2023-04-24  5:32           ` kernel test robot
2023-06-20 12:38           ` Johan Hovold
2023-07-06 19:37             ` Jarkko Sonninen
2023-07-20 13:46               ` Johan Hovold
2023-07-08 14:56             ` [PATCH v5] " Jarkko Sonninen
2023-07-20 13:52               ` Johan Hovold

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.