mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-15 23:25:07 +00:00
USB: serial: xr: add support for XR21B1411
The single-port XR21B1411 is similar to the XR21B142X type but uses 12-bit registers and 16-bit register addresses, the register requests are different and are directed at the device rather than interface, and 5 and 6-bit words are not supported. The register layout is very similar to XR21B142X except that most registers are offset by 0xc00 (corresponding to a channel index of 12 in the MSB of wIndex). As the device is single-port so that the derived channel index is 0, the current register accessors can be reused after simply changing the address width. Signed-off-by: Johan Hovold <johan@kernel.org>
This commit is contained in:
parent
607f671837
commit
4099d4ba47
1 changed files with 47 additions and 15 deletions
|
@ -108,18 +108,19 @@ struct xr_type {
|
|||
u8 set_reg;
|
||||
u8 get_reg;
|
||||
|
||||
u8 uart_enable;
|
||||
u8 flow_control;
|
||||
u8 xon_char;
|
||||
u8 xoff_char;
|
||||
u8 tx_break;
|
||||
u8 gpio_mode;
|
||||
u8 gpio_direction;
|
||||
u8 gpio_set;
|
||||
u8 gpio_clear;
|
||||
u8 gpio_status;
|
||||
u8 custom_driver;
|
||||
u16 uart_enable;
|
||||
u16 flow_control;
|
||||
u16 xon_char;
|
||||
u16 xoff_char;
|
||||
u16 tx_break;
|
||||
u16 gpio_mode;
|
||||
u16 gpio_direction;
|
||||
u16 gpio_set;
|
||||
u16 gpio_clear;
|
||||
u16 gpio_status;
|
||||
u16 custom_driver;
|
||||
|
||||
bool have_5_6_bit_mode;
|
||||
bool have_xmit_toggle;
|
||||
|
||||
int (*enable)(struct usb_serial_port *port);
|
||||
|
@ -132,6 +133,7 @@ struct xr_type {
|
|||
enum xr_type_id {
|
||||
XR21V141X,
|
||||
XR21B142X,
|
||||
XR21B1411,
|
||||
XR_TYPE_COUNT,
|
||||
};
|
||||
|
||||
|
@ -175,8 +177,27 @@ static const struct xr_type xr_types[] = {
|
|||
.gpio_status = 0x10,
|
||||
.custom_driver = 0x60,
|
||||
|
||||
.have_5_6_bit_mode = true,
|
||||
.have_xmit_toggle = true,
|
||||
},
|
||||
[XR21B1411] = {
|
||||
.reg_width = 12,
|
||||
.reg_recipient = USB_RECIP_DEVICE,
|
||||
.set_reg = 0x00,
|
||||
.get_reg = 0x01,
|
||||
|
||||
.uart_enable = 0xc00,
|
||||
.flow_control = 0xc06,
|
||||
.xon_char = 0xc07,
|
||||
.xoff_char = 0xc08,
|
||||
.tx_break = 0xc0a,
|
||||
.gpio_mode = 0xc0c,
|
||||
.gpio_direction = 0xc0d,
|
||||
.gpio_set = 0xc0e,
|
||||
.gpio_clear = 0xc0f,
|
||||
.gpio_status = 0xc10,
|
||||
.custom_driver = 0x20d,
|
||||
},
|
||||
};
|
||||
|
||||
struct xr_data {
|
||||
|
@ -184,7 +205,7 @@ struct xr_data {
|
|||
u8 channel; /* zero-based index or interface number */
|
||||
};
|
||||
|
||||
static int xr_set_reg(struct usb_serial_port *port, u8 channel, u8 reg, u16 val)
|
||||
static int xr_set_reg(struct usb_serial_port *port, u8 channel, u16 reg, u16 val)
|
||||
{
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
const struct xr_type *type = data->type;
|
||||
|
@ -204,7 +225,7 @@ static int xr_set_reg(struct usb_serial_port *port, u8 channel, u8 reg, u16 val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xr_get_reg(struct usb_serial_port *port, u8 channel, u8 reg, u16 *val)
|
||||
static int xr_get_reg(struct usb_serial_port *port, u8 channel, u16 reg, u16 *val)
|
||||
{
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
const struct xr_type *type = data->type;
|
||||
|
@ -243,14 +264,14 @@ static int xr_get_reg(struct usb_serial_port *port, u8 channel, u8 reg, u16 *val
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int xr_set_reg_uart(struct usb_serial_port *port, u8 reg, u16 val)
|
||||
static int xr_set_reg_uart(struct usb_serial_port *port, u16 reg, u16 val)
|
||||
{
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
|
||||
return xr_set_reg(port, data->channel, reg, val);
|
||||
}
|
||||
|
||||
static int xr_get_reg_uart(struct usb_serial_port *port, u8 reg, u16 *val)
|
||||
static int xr_get_reg_uart(struct usb_serial_port *port, u16 reg, u16 *val)
|
||||
{
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
|
||||
|
@ -646,6 +667,7 @@ static void xr21v141x_set_line_settings(struct tty_struct *tty,
|
|||
static void xr_cdc_set_line_coding(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct ktermios *old_termios)
|
||||
{
|
||||
struct xr_data *data = usb_get_serial_port_data(port);
|
||||
struct usb_host_interface *alt = port->serial->interface->cur_altsetting;
|
||||
struct usb_device *udev = port->serial->dev;
|
||||
struct usb_cdc_line_coding *lc;
|
||||
|
@ -683,6 +705,15 @@ static void xr_cdc_set_line_coding(struct tty_struct *tty,
|
|||
lc->bParityType = USB_CDC_NO_PARITY;
|
||||
}
|
||||
|
||||
if (!data->type->have_5_6_bit_mode &&
|
||||
(C_CSIZE(tty) == CS5 || C_CSIZE(tty) == CS6)) {
|
||||
tty->termios.c_cflag &= ~CSIZE;
|
||||
if (old_termios)
|
||||
tty->termios.c_cflag |= old_termios->c_cflag & CSIZE;
|
||||
else
|
||||
tty->termios.c_cflag |= CS8;
|
||||
}
|
||||
|
||||
switch (C_CSIZE(tty)) {
|
||||
case CS5:
|
||||
lc->bDataBits = 5;
|
||||
|
@ -876,6 +907,7 @@ static void xr_port_remove(struct usb_serial_port *port)
|
|||
|
||||
static const struct usb_device_id id_table[] = {
|
||||
{ XR_DEVICE(0x04e2, 0x1410, XR21V141X) },
|
||||
{ XR_DEVICE(0x04e2, 0x1411, XR21B1411) },
|
||||
{ XR_DEVICE(0x04e2, 0x1412, XR21V141X) },
|
||||
{ XR_DEVICE(0x04e2, 0x1414, XR21V141X) },
|
||||
{ XR_DEVICE(0x04e2, 0x1420, XR21B142X) },
|
||||
|
|
Loading…
Reference in a new issue