[60/65] USB: cp210x: fix CP2104 baudrate usage

From: Greg KH
Date: Wed Feb 01 2012 - 16:43:33 EST

3.0-stable review patch. If anyone has any objections, please let me know.


From: Preston Fick <preston.fick@xxxxxxxxxx>

commit 7f482fc88ac47662228d6b1f05759797c8936a30 upstream.

This fix changes the way baudrates are set on the CP210x devices from
Silicon Labs. The CP2101/2/3 will respond to both a GET/SET_BAUDDIV
command, and GET/SET_BAUDRATE command, while CP2104 and higher devices
only respond to GET/SET_BAUDRATE. The current cp210x.ko driver in
kernel version 3.2.0 only implements the GET/SET_BAUDDIV command.

This patch implements the two new codes for the GET/SET_BAUDRATE
commands. Then there is a change in the way that the baudrate is
assigned or retrieved. This is done according to the CP210x USB
specification in AN571. This document can be found here:

Sections 5.3/5.4 describe the USB packets for the old baudrate method.
Sections 5.5/5.6 describe the USB packets for the new method. This
patch also implements the new request scheme, and eliminates the
unnecessary baudrate calculations since it uses the "actual baudrate"

This patch solves the problem reported for the CP2104 in bug 42586,
and also keeps support for all other devices (CP2101/2/3).

This patchfile is also attached to the bug report on
bugzilla.kernel.org. This patch has been developed and test on the
3.2.0 mainline kernel version under Ubuntu 10.11.

Signed-off-by: Preston Fick <preston.fick@xxxxxxxxxx>
[duplicate patch also sent by Johan - gregkh]
Signed-off-by: Johan Hovold <jhovold@xxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

drivers/usb/serial/cp210x.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)

--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -202,6 +202,8 @@ static struct usb_serial_driver cp210x_d
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
+#define CP210X_GET_BAUDRATE 0x1D
+#define CP210X_SET_BAUDRATE 0x1E

#define UART_ENABLE 0x0001
@@ -456,10 +458,7 @@ static void cp210x_get_termios_port(stru

dbg("%s - port %d", __func__, port->number);

- cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
- /* Convert to baudrate */
- if (baud)
- baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
+ cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);

dbg("%s - baud rate = %d", __func__, baud);
*baudp = baud;
@@ -594,8 +593,7 @@ static void cp210x_set_termios(struct tt
if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
dbg("%s - Setting baud rate to %d baud", __func__,
- if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
- ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
+ if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, 4)) {
dbg("Baud rate requested not supported by device");
baud = tty_termios_baud_rate(old_termios);

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/