mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-17 13:58:46 +00:00
USB-serial updates for 6.6-rc1
Here are the USB-serial updates for 6.6-rc1, including: - support for the RS485 mode of XR devices - new modem device ids All have been in linux-next with no reported issues. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQHbPq+cpGvN/peuzMLxc3C7H1lCAUCZOsrJgAKCRALxc3C7H1l CHm0AP9djQISOdmrSvZ8XWH6uDn9QGeA3BFgF7c3hCkHW4oKlQEArKbBw1LlPfkU 7gumA9af7BsqTPkta9b5bHOypa8v5Q8= =fdUQ -----END PGP SIGNATURE----- Merge tag 'usb-serial-6.6-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next Johan writes: USB-serial updates for 6.6-rc1 Here are the USB-serial updates for 6.6-rc1, including: - support for the RS485 mode of XR devices - new modem device ids All have been in linux-next with no reported issues. * tag 'usb-serial-6.6-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial: USB: serial: option: add FOXCONN T99W368/T99W373 product USB: serial: option: add Quectel EM05G variant (0x030e) USB: serial: xr: add TIOCGRS485 and TIOCSRS485 ioctls
This commit is contained in:
commit
895ed7eb26
@ -259,6 +259,7 @@ static void option_instat_callback(struct urb *urb);
|
||||
#define QUECTEL_PRODUCT_EM05G 0x030a
|
||||
#define QUECTEL_PRODUCT_EM060K 0x030b
|
||||
#define QUECTEL_PRODUCT_EM05G_CS 0x030c
|
||||
#define QUECTEL_PRODUCT_EM05GV2 0x030e
|
||||
#define QUECTEL_PRODUCT_EM05CN_SG 0x0310
|
||||
#define QUECTEL_PRODUCT_EM05G_SG 0x0311
|
||||
#define QUECTEL_PRODUCT_EM05CN 0x0312
|
||||
@ -1188,6 +1189,8 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = RSVD(6) | ZLP },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff),
|
||||
.driver_info = RSVD(6) | ZLP },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05GV2, 0xff),
|
||||
.driver_info = RSVD(4) | ZLP },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_CS, 0xff),
|
||||
.driver_info = RSVD(6) | ZLP },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_GR, 0xff),
|
||||
@ -2232,6 +2235,10 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0db, 0xff), /* Foxconn T99W265 MBIM */
|
||||
.driver_info = RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0ee, 0xff), /* Foxconn T99W368 MBIM */
|
||||
.driver_info = RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0f0, 0xff), /* Foxconn T99W373 MBIM */
|
||||
.driver_info = RSVD(3) },
|
||||
{ USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
|
||||
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
|
||||
{ USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
|
||||
|
@ -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,7 @@ 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;
|
||||
};
|
||||
|
||||
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,
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
const struct xr_type *type = data->type;
|
||||
u16 flow, gpio_mode;
|
||||
bool rs485_enabled;
|
||||
int ret;
|
||||
|
||||
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,
|
||||
/* Set GPIO mode for controlling the pins manually by default. */
|
||||
gpio_mode &= ~XR_GPIO_MODE_SEL_MASK;
|
||||
|
||||
if (C_CRTSCTS(tty) && C_BAUD(tty) != B0) {
|
||||
rs485_enabled = !!(data->rs485.flags & SER_RS485_ENABLED);
|
||||
if (rs485_enabled) {
|
||||
dev_dbg(&port->dev, "Enabling RS-485\n");
|
||||
gpio_mode |= XR_GPIO_MODE_SEL_RS485;
|
||||
if (data->rs485.flags & SER_RS485_RTS_ON_SEND)
|
||||
gpio_mode &= ~XR_GPIO_MODE_RS485_TX_H;
|
||||
else
|
||||
gpio_mode |= XR_GPIO_MODE_RS485_TX_H;
|
||||
}
|
||||
|
||||
if (C_CRTSCTS(tty) && C_BAUD(tty) != B0 && !rs485_enabled) {
|
||||
dev_dbg(&port->dev, "Enabling hardware flow ctrl\n");
|
||||
gpio_mode |= XR_GPIO_MODE_SEL_RTS_CTS;
|
||||
flow = XR_UART_FLOW_MODE_HW;
|
||||
@ -809,6 +822,79 @@ static void xr_cdc_set_line_coding(struct tty_struct *tty,
|
||||
kfree(lc);
|
||||
}
|
||||
|
||||
static void xr_sanitize_serial_rs485(struct serial_rs485 *rs485)
|
||||
{
|
||||
if (!(rs485->flags & SER_RS485_ENABLED)) {
|
||||
memset(rs485, 0, sizeof(*rs485));
|
||||
return;
|
||||
}
|
||||
|
||||
/* RTS always toggles after TX */
|
||||
if (rs485->flags & SER_RS485_RTS_ON_SEND)
|
||||
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
else
|
||||
rs485->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
|
||||
/* Only the flags are implemented at the moment */
|
||||
rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
|
||||
SER_RS485_RTS_AFTER_SEND;
|
||||
rs485->delay_rts_before_send = 0;
|
||||
rs485->delay_rts_after_send = 0;
|
||||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||
}
|
||||
|
||||
static int xr_get_rs485_config(struct tty_struct *tty,
|
||||
struct serial_rs485 __user *argp)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
|
||||
down_read(&tty->termios_rwsem);
|
||||
if (copy_to_user(argp, &data->rs485, sizeof(data->rs485))) {
|
||||
up_read(&tty->termios_rwsem);
|
||||
return -EFAULT;
|
||||
}
|
||||
up_read(&tty->termios_rwsem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xr_set_rs485_config(struct tty_struct *tty,
|
||||
struct serial_rs485 __user *argp)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
struct serial_rs485 rs485;
|
||||
|
||||
if (copy_from_user(&rs485, argp, sizeof(rs485)))
|
||||
return -EFAULT;
|
||||
xr_sanitize_serial_rs485(&rs485);
|
||||
|
||||
down_write(&tty->termios_rwsem);
|
||||
data->rs485 = rs485;
|
||||
xr_set_flow_mode(tty, port, NULL);
|
||||
up_write(&tty->termios_rwsem);
|
||||
|
||||
if (copy_to_user(argp, &rs485, sizeof(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 void xr_set_termios(struct tty_struct *tty,
|
||||
struct usb_serial_port *port,
|
||||
const struct ktermios *old_termios)
|
||||
@ -1010,6 +1096,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
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user