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 | |
| 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>
| -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)) { |
