Skip to content

Commit 974e2f6

Browse files
kasbertjhovold
authored andcommitted
USB: serial: xr: add TIOCGRS485 and TIOCSRS485 ioctls
Exar devices like XR21B1411 can control an RS485 transceiver by automatically asserting the RTS#/RS485 pin before sending data and deasserting it when the last stop bit has been transmitted. The polarity of the RST#/RS485 signal is configurable and the hardware also supports half-duplex turn-around delay and address matching mode. Add support for enabling and disabling RS-485 mode and configuring the RST#/RS485 signal polarity using the TIOCGRS485 and TIOCSRS485 ioctls. Support for half-duplex turn-around delay and address matching mode are left unimplemented for now. User enables RS-485 mode by setting SER_RS485_ENABLED flag in struct serial_rs485 flags. User should also set either SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND to select the behaviour of the RTS#/RS485 pin. Setting SER_RS485_RTS_ON_SEND will drive RTS#/RS485 low during transmission. Signed-off-by: Jarkko Sonninen <[email protected]> [ johan: let SER_RS485_RTS_ON_SEND determine SER_RS485_RTS_AFTER_SEND ] Signed-off-by: Johan Hovold <[email protected]>
1 parent fdf0eaf commit 974e2f6

File tree

1 file changed

+88
-1
lines changed

1 file changed

+88
-1
lines changed

drivers/usb/serial/xr_serial.c

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ struct xr_txrx_clk_mask {
9393
#define XR_GPIO_MODE_SEL_DTR_DSR 0x2
9494
#define XR_GPIO_MODE_SEL_RS485 0x3
9595
#define XR_GPIO_MODE_SEL_RS485_ADDR 0x4
96+
#define XR_GPIO_MODE_RS485_TX_H 0x8
9697
#define XR_GPIO_MODE_TX_TOGGLE 0x100
9798
#define XR_GPIO_MODE_RX_TOGGLE 0x200
9899

@@ -237,6 +238,7 @@ static const struct xr_type xr_types[] = {
237238
struct xr_data {
238239
const struct xr_type *type;
239240
u8 channel; /* zero-based index or interface number */
241+
struct serial_rs485 rs485;
240242
};
241243

242244
static int xr_set_reg(struct usb_serial_port *port, u8 channel, u16 reg, u16 val)
@@ -629,6 +631,7 @@ static void xr_set_flow_mode(struct tty_struct *tty,
629631
struct xr_data *data = usb_get_serial_port_data(port);
630632
const struct xr_type *type = data->type;
631633
u16 flow, gpio_mode;
634+
bool rs485_enabled;
632635
int ret;
633636

634637
ret = xr_get_reg_uart(port, type->gpio_mode, &gpio_mode);
@@ -645,7 +648,17 @@ static void xr_set_flow_mode(struct tty_struct *tty,
645648
/* Set GPIO mode for controlling the pins manually by default. */
646649
gpio_mode &= ~XR_GPIO_MODE_SEL_MASK;
647650

648-
if (C_CRTSCTS(tty) && C_BAUD(tty) != B0) {
651+
rs485_enabled = !!(data->rs485.flags & SER_RS485_ENABLED);
652+
if (rs485_enabled) {
653+
dev_dbg(&port->dev, "Enabling RS-485\n");
654+
gpio_mode |= XR_GPIO_MODE_SEL_RS485;
655+
if (data->rs485.flags & SER_RS485_RTS_ON_SEND)
656+
gpio_mode &= ~XR_GPIO_MODE_RS485_TX_H;
657+
else
658+
gpio_mode |= XR_GPIO_MODE_RS485_TX_H;
659+
}
660+
661+
if (C_CRTSCTS(tty) && C_BAUD(tty) != B0 && !rs485_enabled) {
649662
dev_dbg(&port->dev, "Enabling hardware flow ctrl\n");
650663
gpio_mode |= XR_GPIO_MODE_SEL_RTS_CTS;
651664
flow = XR_UART_FLOW_MODE_HW;
@@ -809,6 +822,79 @@ static void xr_cdc_set_line_coding(struct tty_struct *tty,
809822
kfree(lc);
810823
}
811824

825+
static void xr_sanitize_serial_rs485(struct serial_rs485 *rs485)
826+
{
827+
if (!(rs485->flags & SER_RS485_ENABLED)) {
828+
memset(rs485, 0, sizeof(*rs485));
829+
return;
830+
}
831+
832+
/* RTS always toggles after TX */
833+
if (rs485->flags & SER_RS485_RTS_ON_SEND)
834+
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
835+
else
836+
rs485->flags |= SER_RS485_RTS_AFTER_SEND;
837+
838+
/* Only the flags are implemented at the moment */
839+
rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
840+
SER_RS485_RTS_AFTER_SEND;
841+
rs485->delay_rts_before_send = 0;
842+
rs485->delay_rts_after_send = 0;
843+
memset(rs485->padding, 0, sizeof(rs485->padding));
844+
}
845+
846+
static int xr_get_rs485_config(struct tty_struct *tty,
847+
struct serial_rs485 __user *argp)
848+
{
849+
struct usb_serial_port *port = tty->driver_data;
850+
struct xr_data *data = usb_get_serial_port_data(port);
851+
852+
down_read(&tty->termios_rwsem);
853+
if (copy_to_user(argp, &data->rs485, sizeof(data->rs485))) {
854+
up_read(&tty->termios_rwsem);
855+
return -EFAULT;
856+
}
857+
up_read(&tty->termios_rwsem);
858+
859+
return 0;
860+
}
861+
862+
static int xr_set_rs485_config(struct tty_struct *tty,
863+
struct serial_rs485 __user *argp)
864+
{
865+
struct usb_serial_port *port = tty->driver_data;
866+
struct xr_data *data = usb_get_serial_port_data(port);
867+
struct serial_rs485 rs485;
868+
869+
if (copy_from_user(&rs485, argp, sizeof(rs485)))
870+
return -EFAULT;
871+
xr_sanitize_serial_rs485(&rs485);
872+
873+
down_write(&tty->termios_rwsem);
874+
data->rs485 = rs485;
875+
xr_set_flow_mode(tty, port, NULL);
876+
up_write(&tty->termios_rwsem);
877+
878+
if (copy_to_user(argp, &rs485, sizeof(rs485)))
879+
return -EFAULT;
880+
881+
return 0;
882+
}
883+
884+
static int xr_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
885+
{
886+
void __user *argp = (void __user *)arg;
887+
888+
switch (cmd) {
889+
case TIOCGRS485:
890+
return xr_get_rs485_config(tty, argp);
891+
case TIOCSRS485:
892+
return xr_set_rs485_config(tty, argp);
893+
}
894+
895+
return -ENOIOCTLCMD;
896+
}
897+
812898
static void xr_set_termios(struct tty_struct *tty,
813899
struct usb_serial_port *port,
814900
const struct ktermios *old_termios)
@@ -1010,6 +1096,7 @@ static struct usb_serial_driver xr_device = {
10101096
.set_termios = xr_set_termios,
10111097
.tiocmget = xr_tiocmget,
10121098
.tiocmset = xr_tiocmset,
1099+
.ioctl = xr_ioctl,
10131100
.dtr_rts = xr_dtr_rts
10141101
};
10151102

0 commit comments

Comments
 (0)