aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2012-01-15 18:36:51 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-24 14:57:53 -0500
commite5990874e511d5bbca23b3396419480cb2ca0ee7 (patch)
tree319c31118c83549098f7c0d8cdf1e2de7e301b7e /drivers/usb
parentbe125d9c8d59560e7cc2d6e2b65c8fd233498ab7 (diff)
USB: cp210x: clean up, refactor and document speed handling
Clean up and refactor speed handling. Document baud rate handling for CP210{1,2,4,5,10}. Signed-off-by: Johan Hovold <jhovold@gmail.com> Cc: Preston Fick <preston.fick@silabs.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/cp210x.c71
1 files changed, 57 insertions, 14 deletions
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index ad7599ed5df9..2d2d23933ba6 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -39,6 +39,8 @@ static void cp210x_get_termios(struct tty_struct *,
39 struct usb_serial_port *port); 39 struct usb_serial_port *port);
40static void cp210x_get_termios_port(struct usb_serial_port *port, 40static void cp210x_get_termios_port(struct usb_serial_port *port,
41 unsigned int *cflagp, unsigned int *baudp); 41 unsigned int *cflagp, unsigned int *baudp);
42static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
43 struct ktermios *);
42static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, 44static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
43 struct ktermios*); 45 struct ktermios*);
44static int cp210x_tiocmget(struct tty_struct *); 46static int cp210x_tiocmget(struct tty_struct *);
@@ -576,11 +578,62 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
576 *cflagp = cflag; 578 *cflagp = cflag;
577} 579}
578 580
581/*
582 * CP2101 supports the following baud rates:
583 *
584 * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
585 * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
586 *
587 * CP2102 and CP2103 support the following additional rates:
588 *
589 * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
590 * 576000
591 *
592 * The device will map a requested rate to a supported one, but the result
593 * of requests for rates greater than 1053257 is undefined (see AN205).
594 *
595 * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
596 * respectively, with an error less than 1%. The actual rates are determined
597 * by
598 *
599 * div = round(freq / (2 x prescale x request))
600 * actual = freq / (2 x prescale x div)
601 *
602 * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
603 * or 1 otherwise.
604 * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
605 * otherwise.
606 */
607static void cp210x_change_speed(struct tty_struct *tty,
608 struct usb_serial_port *port, struct ktermios *old_termios)
609{
610 u32 baud;
611
612 baud = tty->termios->c_ospeed;
613
614 /* This maps the requested rate to a rate valid on cp2102 or cp2103.
615 *
616 * NOTE: B0 is not implemented.
617 */
618 baud = cp210x_quantise_baudrate(baud);
619
620 dbg("%s - setting baud rate to %u", __func__, baud);
621 if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
622 sizeof(baud))) {
623 dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
624 if (old_termios)
625 baud = old_termios->c_ospeed;
626 else
627 baud = 9600;
628 }
629
630 tty_encode_baud_rate(tty, baud, baud);
631}
632
579static void cp210x_set_termios(struct tty_struct *tty, 633static void cp210x_set_termios(struct tty_struct *tty,
580 struct usb_serial_port *port, struct ktermios *old_termios) 634 struct usb_serial_port *port, struct ktermios *old_termios)
581{ 635{
582 unsigned int cflag, old_cflag; 636 unsigned int cflag, old_cflag;
583 u32 baud;
584 unsigned int bits; 637 unsigned int bits;
585 unsigned int modem_ctl[4]; 638 unsigned int modem_ctl[4];
586 639
@@ -591,19 +644,9 @@ static void cp210x_set_termios(struct tty_struct *tty,
591 644
592 cflag = tty->termios->c_cflag; 645 cflag = tty->termios->c_cflag;
593 old_cflag = old_termios->c_cflag; 646 old_cflag = old_termios->c_cflag;
594 baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); 647
595 648 if (tty->termios->c_ospeed != old_termios->c_ospeed)
596 /* If the baud rate is to be updated*/ 649 cp210x_change_speed(tty, port, old_termios);
597 if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
598 dbg("%s - Setting baud rate to %d baud", __func__,
599 baud);
600 if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, sizeof(baud))) {
601 dbg("Baud rate requested not supported by device");
602 baud = tty_termios_baud_rate(old_termios);
603 }
604 }
605 /* Report back the resulting baud rate */
606 tty_encode_baud_rate(tty, baud, baud);
607 650
608 /* If the number of data bits is to be updated */ 651 /* If the number of data bits is to be updated */
609 if ((cflag & CSIZE) != (old_cflag & CSIZE)) { 652 if ((cflag & CSIZE) != (old_cflag & CSIZE)) {