aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cp210x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/cp210x.c')
-rw-r--r--drivers/usb/serial/cp210x.c289
1 files changed, 6 insertions, 283 deletions
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index ad134e517849..bb9c3d7ccaee 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -31,9 +31,6 @@
*/
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
static void cp210x_close(struct usb_serial_port *);
-static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);
-static void cp210x_get_termios_port(struct usb_serial_port *port,
- tcflag_t *cflagp, unsigned int *baudp);
static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
struct ktermios *);
static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
@@ -267,7 +264,6 @@ enum cp210x_event_state {
struct cp210x_port_private {
u8 bInterfaceNumber;
- bool has_swapped_line_ctl;
bool event_mode;
enum cp210x_event_state event_state;
u8 lsr;
@@ -594,46 +590,6 @@ static int cp210x_read_reg_block(struct usb_serial_port *port, u8 req,
}
/*
- * Reads any 32-bit CP210X_ register identified by req.
- */
-static int cp210x_read_u32_reg(struct usb_serial_port *port, u8 req, u32 *val)
-{
- __le32 le32_val;
- int err;
-
- err = cp210x_read_reg_block(port, req, &le32_val, sizeof(le32_val));
- if (err) {
- /*
- * FIXME Some callers don't bother to check for error,
- * at least give them consistent junk until they are fixed
- */
- *val = 0;
- return err;
- }
-
- *val = le32_to_cpu(le32_val);
-
- return 0;
-}
-
-/*
- * Reads any 16-bit CP210X_ register identified by req.
- */
-static int cp210x_read_u16_reg(struct usb_serial_port *port, u8 req, u16 *val)
-{
- __le16 le16_val;
- int err;
-
- err = cp210x_read_reg_block(port, req, &le16_val, sizeof(le16_val));
- if (err)
- return err;
-
- *val = le16_to_cpu(le16_val);
-
- return 0;
-}
-
-/*
* Reads any 8-bit CP210X_ register identified by req.
*/
static int cp210x_read_u8_reg(struct usb_serial_port *port, u8 req, u8 *val)
@@ -780,59 +736,6 @@ static int cp210x_write_vendor_block(struct usb_serial *serial, u8 type,
}
#endif
-/*
- * Detect CP2108 GET_LINE_CTL bug and activate workaround.
- * Write a known good value 0x800, read it back.
- * If it comes back swapped the bug is detected.
- * Preserve the original register value.
- */
-static int cp210x_detect_swapped_line_ctl(struct usb_serial_port *port)
-{
- struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
- u16 line_ctl_save;
- u16 line_ctl_test;
- int err;
-
- err = cp210x_read_u16_reg(port, CP210X_GET_LINE_CTL, &line_ctl_save);
- if (err)
- return err;
-
- err = cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, 0x800);
- if (err)
- return err;
-
- err = cp210x_read_u16_reg(port, CP210X_GET_LINE_CTL, &line_ctl_test);
- if (err)
- return err;
-
- if (line_ctl_test == 8) {
- port_priv->has_swapped_line_ctl = true;
- line_ctl_save = swab16(line_ctl_save);
- }
-
- return cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, line_ctl_save);
-}
-
-/*
- * Must always be called instead of cp210x_read_u16_reg(CP210X_GET_LINE_CTL)
- * to workaround cp2108 bug and get correct value.
- */
-static int cp210x_get_line_ctl(struct usb_serial_port *port, u16 *ctl)
-{
- struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
- int err;
-
- err = cp210x_read_u16_reg(port, CP210X_GET_LINE_CTL, ctl);
- if (err)
- return err;
-
- /* Workaround swapped bytes in 16-bit value from CP210X_GET_LINE_CTL */
- if (port_priv->has_swapped_line_ctl)
- *ctl = swab16(*ctl);
-
- return 0;
-}
-
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
@@ -844,16 +747,8 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
return result;
}
- /* Configure the termios structure */
- cp210x_get_termios(tty, port);
-
- if (tty) {
- /* The baud rate must be initialised on cp2104 */
- cp210x_change_speed(tty, port, NULL);
-
- if (I_INPCK(tty))
- cp210x_enable_event_mode(port);
- }
+ if (tty)
+ cp210x_set_termios(tty, port, NULL);
result = usb_serial_generic_open(tty, port);
if (result)
@@ -1032,167 +927,6 @@ static bool cp210x_tx_empty(struct usb_serial_port *port)
return !count;
}
-/*
- * cp210x_get_termios
- * Reads the baud rate, data bits, parity, stop bits and flow control mode
- * from the device, corrects any unsupported values, and configures the
- * termios structure to reflect the state of the device
- */
-static void cp210x_get_termios(struct tty_struct *tty,
- struct usb_serial_port *port)
-{
- unsigned int baud;
-
- if (tty) {
- cp210x_get_termios_port(tty->driver_data,
- &tty->termios.c_cflag, &baud);
- tty_encode_baud_rate(tty, baud, baud);
- } else {
- tcflag_t cflag;
- cflag = 0;
- cp210x_get_termios_port(port, &cflag, &baud);
- }
-}
-
-/*
- * cp210x_get_termios_port
- * This is the heart of cp210x_get_termios which always uses a &usb_serial_port.
- */
-static void cp210x_get_termios_port(struct usb_serial_port *port,
- tcflag_t *cflagp, unsigned int *baudp)
-{
- struct device *dev = &port->dev;
- tcflag_t cflag;
- struct cp210x_flow_ctl flow_ctl;
- u32 baud;
- u16 bits;
- u32 ctl_hs;
- u32 flow_repl;
-
- cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud);
-
- dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud);
- *baudp = baud;
-
- cflag = *cflagp;
-
- cp210x_get_line_ctl(port, &bits);
- cflag &= ~CSIZE;
- switch (bits & BITS_DATA_MASK) {
- case BITS_DATA_5:
- dev_dbg(dev, "%s - data bits = 5\n", __func__);
- cflag |= CS5;
- break;
- case BITS_DATA_6:
- dev_dbg(dev, "%s - data bits = 6\n", __func__);
- cflag |= CS6;
- break;
- case BITS_DATA_7:
- dev_dbg(dev, "%s - data bits = 7\n", __func__);
- cflag |= CS7;
- break;
- case BITS_DATA_8:
- dev_dbg(dev, "%s - data bits = 8\n", __func__);
- cflag |= CS8;
- break;
- case BITS_DATA_9:
- dev_dbg(dev, "%s - data bits = 9 (not supported, using 8 data bits)\n", __func__);
- cflag |= CS8;
- bits &= ~BITS_DATA_MASK;
- bits |= BITS_DATA_8;
- cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits);
- break;
- default:
- dev_dbg(dev, "%s - Unknown number of data bits, using 8\n", __func__);
- cflag |= CS8;
- bits &= ~BITS_DATA_MASK;
- bits |= BITS_DATA_8;
- cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits);
- break;
- }
-
- switch (bits & BITS_PARITY_MASK) {
- case BITS_PARITY_NONE:
- dev_dbg(dev, "%s - parity = NONE\n", __func__);
- cflag &= ~PARENB;
- break;
- case BITS_PARITY_ODD:
- dev_dbg(dev, "%s - parity = ODD\n", __func__);
- cflag |= (PARENB|PARODD);
- break;
- case BITS_PARITY_EVEN:
- dev_dbg(dev, "%s - parity = EVEN\n", __func__);
- cflag &= ~PARODD;
- cflag |= PARENB;
- break;
- case BITS_PARITY_MARK:
- dev_dbg(dev, "%s - parity = MARK\n", __func__);
- cflag |= (PARENB|PARODD|CMSPAR);
- break;
- case BITS_PARITY_SPACE:
- dev_dbg(dev, "%s - parity = SPACE\n", __func__);
- cflag &= ~PARODD;
- cflag |= (PARENB|CMSPAR);
- break;
- default:
- dev_dbg(dev, "%s - Unknown parity mode, disabling parity\n", __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits);
- break;
- }
-
- cflag &= ~CSTOPB;
- switch (bits & BITS_STOP_MASK) {
- case BITS_STOP_1:
- dev_dbg(dev, "%s - stop bits = 1\n", __func__);
- break;
- case BITS_STOP_1_5:
- dev_dbg(dev, "%s - stop bits = 1.5 (not supported, using 1 stop bit)\n", __func__);
- bits &= ~BITS_STOP_MASK;
- cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits);
- break;
- case BITS_STOP_2:
- dev_dbg(dev, "%s - stop bits = 2\n", __func__);
- cflag |= CSTOPB;
- break;
- default:
- dev_dbg(dev, "%s - Unknown number of stop bits, using 1 stop bit\n", __func__);
- bits &= ~BITS_STOP_MASK;
- cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits);
- break;
- }
-
- cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
- sizeof(flow_ctl));
- ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
- if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) {
- dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
- /*
- * When the port is closed, the CP210x hardware disables
- * auto-RTS and RTS is deasserted but it leaves auto-CTS when
- * in hardware flow control mode. When re-opening the port, if
- * auto-CTS is enabled on the cp210x, then auto-RTS must be
- * re-enabled in the driver.
- */
- flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace);
- flow_repl &= ~CP210X_SERIAL_RTS_MASK;
- flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_FLOW_CTL);
- flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
- cp210x_write_reg_block(port,
- CP210X_SET_FLOW,
- &flow_ctl,
- sizeof(flow_ctl));
-
- cflag |= CRTSCTS;
- } else {
- dev_dbg(dev, "%s - flow control = NONE\n", __func__);
- cflag &= ~CRTSCTS;
- }
-
- *cflagp = cflag;
-}
-
struct cp210x_rate {
speed_t rate;
speed_t high;
@@ -1366,17 +1100,13 @@ static void cp210x_set_termios(struct tty_struct *tty,
{
struct cp210x_serial_private *priv = usb_get_serial_data(port->serial);
struct device *dev = &port->dev;
- unsigned int cflag, old_cflag;
u16 bits;
int ret;
- if (!cp210x_termios_change(&tty->termios, old_termios))
+ if (old_termios && !cp210x_termios_change(&tty->termios, old_termios))
return;
- cflag = tty->termios.c_cflag;
- old_cflag = old_termios->c_cflag;
-
- if (tty->termios.c_ospeed != old_termios->c_ospeed)
+ if (!old_termios || tty->termios.c_ospeed != old_termios->c_ospeed)
cp210x_change_speed(tty, port, old_termios);
/* CP2101 only supports CS8, 1 stop bit and non-stick parity. */
@@ -1426,7 +1156,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
if (ret)
dev_err(&port->dev, "failed to set line control: %d\n", ret);
- if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
+ if (!old_termios || C_CRTSCTS(tty) != (old_termios->c_cflag & CRTSCTS)) {
struct cp210x_flow_ctl flow_ctl;
u32 ctl_hs;
u32 flow_repl;
@@ -1443,7 +1173,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
ctl_hs &= ~CP210X_SERIAL_DSR_SENSITIVITY;
ctl_hs &= ~CP210X_SERIAL_DTR_MASK;
ctl_hs |= CP210X_SERIAL_DTR_SHIFT(CP210X_SERIAL_DTR_ACTIVE);
- if (cflag & CRTSCTS) {
+ if (C_CRTSCTS(tty)) {
ctl_hs |= CP210X_SERIAL_CTS_HANDSHAKE;
flow_repl &= ~CP210X_SERIAL_RTS_MASK;
@@ -1979,7 +1709,6 @@ static int cp210x_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct cp210x_port_private *port_priv;
- int ret;
port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
if (!port_priv)
@@ -1989,12 +1718,6 @@ static int cp210x_port_probe(struct usb_serial_port *port)
usb_set_serial_port_data(port, port_priv);
- ret = cp210x_detect_swapped_line_ctl(port);
- if (ret) {
- kfree(port_priv);
- return ret;
- }
-
return 0;
}