aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPreston Fick <preston.fick@silabs.com>2012-01-16 19:14:09 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-24 14:45:10 -0500
commit7f482fc88ac47662228d6b1f05759797c8936a30 (patch)
tree7b659184136407b76bde346f870f62860e083b15
parent55b2afbb92ad92e9f6b0aa4354eb1c94589280c3 (diff)
USB: cp210x: fix CP2104 baudrate usage
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: http://www.silabs.com/pages/DownloadDoc.aspx?FILEURL=Support%20Documents/TechnicalDocs/AN571.pdf&src=DocumentationWebPart 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" method. 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@silabs.com> [duplicate patch also sent by Johan - gregkh] Signed-off-by: Johan Hovold <jhovold@gmail.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/serial/cp210x.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index bb4290bfe59d..f4267886e255 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -202,6 +202,8 @@ static struct usb_serial_driver cp210x_device = {
202#define CP210X_EMBED_EVENTS 0x15 202#define CP210X_EMBED_EVENTS 0x15
203#define CP210X_GET_EVENTSTATE 0x16 203#define CP210X_GET_EVENTSTATE 0x16
204#define CP210X_SET_CHARS 0x19 204#define CP210X_SET_CHARS 0x19
205#define CP210X_GET_BAUDRATE 0x1D
206#define CP210X_SET_BAUDRATE 0x1E
205 207
206/* CP210X_IFC_ENABLE */ 208/* CP210X_IFC_ENABLE */
207#define UART_ENABLE 0x0001 209#define UART_ENABLE 0x0001
@@ -465,10 +467,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
465 467
466 dbg("%s - port %d", __func__, port->number); 468 dbg("%s - port %d", __func__, port->number);
467 469
468 cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2); 470 cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
469 /* Convert to baudrate */
470 if (baud)
471 baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
472 471
473 dbg("%s - baud rate = %d", __func__, baud); 472 dbg("%s - baud rate = %d", __func__, baud);
474 *baudp = baud; 473 *baudp = baud;
@@ -597,8 +596,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
597 if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { 596 if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
598 dbg("%s - Setting baud rate to %d baud", __func__, 597 dbg("%s - Setting baud rate to %d baud", __func__,
599 baud); 598 baud);
600 if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, 599 if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, 4)) {
601 ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
602 dbg("Baud rate requested not supported by device"); 600 dbg("Baud rate requested not supported by device");
603 baud = tty_termios_baud_rate(old_termios); 601 baud = tty_termios_baud_rate(old_termios);
604 } 602 }