Commit 66c79319 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-serial-4.10-rc1' of...

Merge tag 'usb-serial-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next

Johan writes:

USB-serial updates for v4.10-rc1

These updates include a new driver for Fintek F8153x devices, support
for the GPIO functionality on CP2105 devices, and improved support for
CH34X devices.

Included are also some clean ups and fixes for various minor issues.
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
parents 7faf44bf 3c3dd1e0
......@@ -255,6 +255,16 @@ config USB_SERIAL_F81232
To compile this driver as a module, choose M here: the
module will be called f81232.
config USB_SERIAL_F8153X
tristate "USB Fintek F81532/534 Multi-Ports Serial Driver"
help
Say Y here if you want to use the Fintek F81532/534 Multi-Ports
USB to serial adapter.
To compile this driver as a module, choose M here: the
module will be called f81534.
config USB_SERIAL_GARMIN
tristate "USB Garmin GPS driver"
help
......
......@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
obj-$(CONFIG_USB_SERIAL_F81232) += f81232.o
obj-$(CONFIG_USB_SERIAL_F8153X) += f81534.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
......
......@@ -61,13 +61,26 @@
* the Net/FreeBSD uchcom.c driver by Takanori Watanabe. Domo arigato.
*/
#define CH341_REQ_READ_VERSION 0x5F
#define CH341_REQ_WRITE_REG 0x9A
#define CH341_REQ_READ_REG 0x95
#define CH341_REG_BREAK1 0x05
#define CH341_REG_BREAK2 0x18
#define CH341_NBREAK_BITS_REG1 0x01
#define CH341_NBREAK_BITS_REG2 0x40
#define CH341_REQ_SERIAL_INIT 0xA1
#define CH341_REQ_MODEM_CTRL 0xA4
#define CH341_REG_BREAK 0x05
#define CH341_REG_LCR 0x18
#define CH341_NBREAK_BITS 0x01
#define CH341_LCR_ENABLE_RX 0x80
#define CH341_LCR_ENABLE_TX 0x40
#define CH341_LCR_MARK_SPACE 0x20
#define CH341_LCR_PAR_EVEN 0x10
#define CH341_LCR_ENABLE_PAR 0x08
#define CH341_LCR_STOP_BITS_2 0x04
#define CH341_LCR_CS8 0x03
#define CH341_LCR_CS7 0x02
#define CH341_LCR_CS6 0x01
#define CH341_LCR_CS5 0x00
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x4348, 0x5523) },
......@@ -119,10 +132,10 @@ static int ch341_control_in(struct usb_device *dev,
return r;
}
static int ch341_set_baudrate(struct usb_device *dev,
struct ch341_private *priv)
static int ch341_init_set_baudrate(struct usb_device *dev,
struct ch341_private *priv, unsigned ctrl)
{
short a, b;
short a;
int r;
unsigned long factor;
short divisor;
......@@ -142,18 +155,17 @@ static int ch341_set_baudrate(struct usb_device *dev,
factor = 0x10000 - factor;
a = (factor & 0xff00) | divisor;
b = factor & 0xff;
r = ch341_control_out(dev, 0x9a, 0x1312, a);
if (!r)
r = ch341_control_out(dev, 0x9a, 0x0f2c, b);
/* 0x9c is "enable SFR_UART Control register and timer" */
r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT,
0x9c | (ctrl << 8), a | 0x80);
return r;
}
static int ch341_set_handshake(struct usb_device *dev, u8 control)
{
return ch341_control_out(dev, 0xa4, ~control, 0);
return ch341_control_out(dev, CH341_REQ_MODEM_CTRL, ~control, 0);
}
static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
......@@ -167,7 +179,7 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
if (!buffer)
return -ENOMEM;
r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size);
r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x0706, 0, buffer, size);
if (r < 0)
goto out;
......@@ -197,24 +209,21 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
return -ENOMEM;
/* expect two bytes 0x27 0x00 */
r = ch341_control_in(dev, 0x5f, 0, 0, buffer, size);
r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size);
if (r < 0)
goto out;
dev_dbg(&dev->dev, "Chip version: 0x%02x\n", buffer[0]);
r = ch341_control_out(dev, 0xa1, 0, 0);
if (r < 0)
goto out;
r = ch341_set_baudrate(dev, priv);
r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0);
if (r < 0)
goto out;
/* expect two bytes 0x56 0x00 */
r = ch341_control_in(dev, 0x95, 0x2518, 0, buffer, size);
r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x2518, 0, buffer, size);
if (r < 0)
goto out;
r = ch341_control_out(dev, 0x9a, 0x2518, 0x0050);
r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, 0x0050);
if (r < 0)
goto out;
......@@ -223,11 +232,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
if (r < 0)
goto out;
r = ch341_control_out(dev, 0xa1, 0x501f, 0xd90a);
if (r < 0)
goto out;
r = ch341_set_baudrate(dev, priv);
r = ch341_init_set_baudrate(dev, priv, 0);
if (r < 0)
goto out;
......@@ -342,16 +347,53 @@ static void ch341_set_termios(struct tty_struct *tty,
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned baud_rate;
unsigned long flags;
unsigned char ctrl;
int r;
/* redundant changes may cause the chip to lose bytes */
if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
return;
baud_rate = tty_get_baud_rate(tty);
priv->baud_rate = baud_rate;
ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
switch (C_CSIZE(tty)) {
case CS5:
ctrl |= CH341_LCR_CS5;
break;
case CS6:
ctrl |= CH341_LCR_CS6;
break;
case CS7:
ctrl |= CH341_LCR_CS7;
break;
case CS8:
ctrl |= CH341_LCR_CS8;
break;
}
if (C_PARENB(tty)) {
ctrl |= CH341_LCR_ENABLE_PAR;
if (C_PARODD(tty) == 0)
ctrl |= CH341_LCR_PAR_EVEN;
if (C_CMSPAR(tty))
ctrl |= CH341_LCR_MARK_SPACE;
}
if (C_CSTOPB(tty))
ctrl |= CH341_LCR_STOP_BITS_2;
if (baud_rate) {
spin_lock_irqsave(&priv->lock, flags);
priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_baudrate(port->serial->dev, priv);
r = ch341_init_set_baudrate(port->serial->dev, priv, ctrl);
if (r < 0 && old_termios) {
priv->baud_rate = tty_termios_baud_rate(old_termios);
tty_termios_copy_hw(&tty->termios, old_termios);
}
} else {
spin_lock_irqsave(&priv->lock, flags);
priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
......@@ -360,17 +402,12 @@ static void ch341_set_termios(struct tty_struct *tty,
ch341_set_handshake(port->serial->dev, priv->line_control);
/* Unimplemented:
* (cflag & CSIZE) : data bits [5, 8]
* (cflag & PARENB) : parity {NONE, EVEN, ODD}
* (cflag & CSTOPB) : stop bits [1, 2]
*/
}
static void ch341_break_ctl(struct tty_struct *tty, int break_state)
{
const uint16_t ch341_break_reg =
((uint16_t) CH341_REG_BREAK2 << 8) | CH341_REG_BREAK1;
((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK;
struct usb_serial_port *port = tty->driver_data;
int r;
uint16_t reg_contents;
......@@ -391,12 +428,12 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state)
__func__, break_reg[0], break_reg[1]);
if (break_state != 0) {
dev_dbg(&port->dev, "%s - Enter break state requested\n", __func__);
break_reg[0] &= ~CH341_NBREAK_BITS_REG1;
break_reg[1] &= ~CH341_NBREAK_BITS_REG2;
break_reg[0] &= ~CH341_NBREAK_BITS;
break_reg[1] &= ~CH341_LCR_ENABLE_TX;
} else {
dev_dbg(&port->dev, "%s - Leave break state requested\n", __func__);
break_reg[0] |= CH341_NBREAK_BITS_REG1;
break_reg[1] |= CH341_NBREAK_BITS_REG2;
break_reg[0] |= CH341_NBREAK_BITS;
break_reg[1] |= CH341_LCR_ENABLE_TX;
}
dev_dbg(&port->dev, "%s - New ch341 break register contents - reg1: %x, reg2: %x\n",
__func__, break_reg[0], break_reg[1]);
......
This diff is collapsed.
This diff is collapsed.
......@@ -1455,8 +1455,6 @@ static int get_serial_info(struct usb_serial_port *port,
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct serial_struct tmp;
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.flags = priv->flags;
tmp.baud_base = priv->baud_base;
......@@ -1538,9 +1536,6 @@ static int get_lsr_info(struct usb_serial_port *port,
struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned int result = 0;
if (!retinfo)
return -EFAULT;
if (priv->transmit_empty)
result = TIOCSER_TEMT;
......
......@@ -1554,9 +1554,6 @@ static int get_serial_info(struct edgeport_port *edge_port,
{
struct serial_struct tmp;
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_16550A;
......
......@@ -2459,9 +2459,6 @@ static int get_serial_info(struct edgeport_port *edge_port,
struct serial_struct tmp;
unsigned cwait;
if (!retinfo)
return -EFAULT;
cwait = edge_port->port->port.closing_wait;
if (cwait != ASYNC_CLOSING_WAIT_NONE)
cwait = jiffies_to_msecs(cwait) / 10;
......
......@@ -296,7 +296,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
rc = usb_serial_generic_open(tty, port);
if (rc) {
retval = rc;
goto exit;
goto err_free_cfg;
}
rc = usb_control_msg(port->serial->dev,
......@@ -311,21 +311,38 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
if (rc < 0) {
dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc);
retval = rc;
goto err_generic_close;
} else
dev_dbg(&port->dev, "%s - enabled reading\n", __func__);
rc = klsi_105_get_line_state(port, &line_state);
if (rc >= 0) {
spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
spin_unlock_irqrestore(&priv->lock, flags);
dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state);
retval = 0;
} else
if (rc < 0) {
retval = rc;
goto err_disable_read;
}
spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
spin_unlock_irqrestore(&priv->lock, flags);
dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__,
line_state);
return 0;
exit:
err_disable_read:
usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
KL5KUSB105A_SIO_CONFIGURE,
USB_TYPE_VENDOR | USB_DIR_OUT,
KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
0, /* index */
NULL, 0,
KLSI_TIMEOUT);
err_generic_close:
usb_serial_generic_close(port);
err_free_cfg:
kfree(cfg);
return retval;
}
......
......@@ -1861,9 +1861,6 @@ static int get_serial_info(struct moschip_port *mos7720_port,
{
struct serial_struct tmp;
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_16550A;
......
......@@ -1956,9 +1956,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
if (mos7840_port == NULL)
return -1;
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_16550A;
......
......@@ -336,9 +336,6 @@ static int get_serial_info(struct usb_serial_port *port,
{
struct serial_struct tmp;
if (!serial)
return -EFAULT;
memset(&tmp, 0x00, sizeof(tmp));
/* fake emulate a 16550 uart to make userspace code happy */
......
......@@ -463,9 +463,6 @@ static int get_serial_info(struct usb_serial_port *port,
{
struct serial_struct tmp;
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.line = port->minor;
tmp.port = 0;
......
......@@ -318,9 +318,6 @@ static int get_serial_info(struct usb_serial_port *port,
{
struct serial_struct tmp;
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.line = port->minor;
tmp.port = 0;
......
......@@ -1426,9 +1426,6 @@ static int ti_get_serial_info(struct ti_port *tport,
struct serial_struct ret_serial;
unsigned cwait;
if (!ret_arg)
return -EFAULT;
cwait = port->port.closing_wait;
if (cwait != ASYNC_CLOSING_WAIT_NONE)
cwait = jiffies_to_msecs(cwait) / 10;
......
......@@ -140,9 +140,6 @@ static int get_serial_info(struct usb_serial_port *port,
{
struct serial_struct tmp;
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.line = port->minor;
tmp.port = port->port_number;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment