diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-01-15 18:36:51 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2012-01-24 14:57:53 -0500 |
commit | e5990874e511d5bbca23b3396419480cb2ca0ee7 (patch) | |
tree | 319c31118c83549098f7c0d8cdf1e2de7e301b7e /drivers/usb | |
parent | be125d9c8d59560e7cc2d6e2b65c8fd233498ab7 (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.c | 71 |
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); |
40 | static void cp210x_get_termios_port(struct usb_serial_port *port, | 40 | static void cp210x_get_termios_port(struct usb_serial_port *port, |
41 | unsigned int *cflagp, unsigned int *baudp); | 41 | unsigned int *cflagp, unsigned int *baudp); |
42 | static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, | ||
43 | struct ktermios *); | ||
42 | static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, | 44 | static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, |
43 | struct ktermios*); | 45 | struct ktermios*); |
44 | static int cp210x_tiocmget(struct tty_struct *); | 46 | static 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 | */ | ||
607 | static 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 | |||
579 | static void cp210x_set_termios(struct tty_struct *tty, | 633 | static 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)) { |