diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 409000a836ddb5868612f88b5bc6448094b0e6fc..e7a84f0f517969fec4bbb59ac270eeb97fbf22d3 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -134,10 +134,17 @@ MODULE_DEVICE_TABLE(usb, id_table); enum pl2303_type { - type_0, /* don't know the difference between type 0 and */ - type_1, /* type 1, until someone from prolific tells us... */ - HX, /* HX version of the pl2303 chip */ + type_0, /* H version ? */ + type_1, /* H version ? */ + HX_TA, /* HX(A) / X(A) / TA version */ /* TODO: improve */ + HXD_EA_RA_SA, /* HXD / EA / RA / SA version */ /* TODO: improve */ + TB, /* TB version */ }; +/* + * NOTE: don't know the difference between type 0 and type 1, + * until someone from Prolific tells us... + * TODO: distinguish between X/HX, TA and HXD, EA, RA, SA variants + */ struct pl2303_serial_private { enum pl2303_type type; @@ -194,8 +201,28 @@ static int pl2303_startup(struct usb_serial *serial) type = type_0; type_str = "type_0"; } else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) { - type = HX; - type_str = "X/HX"; + /* + * NOTE: The bcdDevice version is the only difference between + * the device descriptors of the X/HX, HXD, EA, RA, SA, TA, TB + */ + if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x300) { + type = HX_TA; + type_str = "X/HX/TA"; + } else if (le16_to_cpu(serial->dev->descriptor.bcdDevice) + == 0x400) { + type = HXD_EA_RA_SA; + type_str = "HXD/EA/RA/SA"; + } else if (le16_to_cpu(serial->dev->descriptor.bcdDevice) + == 0x500) { + type = TB; + type_str = "TB"; + } else { + dev_info(&serial->interface->dev, + "unknown/unsupported device type\n"); + kfree(spriv); + kfree(buf); + return -ENODEV; + } } else if (serial->dev->descriptor.bDeviceClass == 0x00 || serial->dev->descriptor.bDeviceClass == 0xFF) { type = type_1; @@ -216,10 +243,10 @@ static int pl2303_startup(struct usb_serial *serial) pl2303_vendor_read(0x8383, 0, serial, buf); pl2303_vendor_write(0, 1, serial); pl2303_vendor_write(1, 0, serial); - if (type == HX) - pl2303_vendor_write(2, 0x44, serial); - else + if (type == type_0 || type == type_1) pl2303_vendor_write(2, 0x24, serial); + else + pl2303_vendor_write(2, 0x44, serial); kfree(buf); return 0; @@ -284,12 +311,19 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type, const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, 614400, 921600, - 1228800, 2457600, 3000000, 6000000 }; + 1228800, 2457600, 3000000, 6000000, 12000000 }; /* - * NOTE: The PL2303HX (tested with rev. 3A) also supports the following - * baud rates: 128000, 134400, 161280, 201600, 268800, 403200, 806400. - * As long as we are not using this encoding method for them, there is - * no point in complicating the code to support them. + * NOTE: With the exception of type_0/1 devices, the following + * additional baud rates are supported (tested with HX rev. 3A only): + * 110*, 56000*, 128000, 134400, 161280, 201600, 256000*, 268800, + * 403200, 806400. (*: not HX) + * + * Maximum values: HXD, TB: 12000000; HX, TA: 6000000; + * type_0+1: 1228800; RA: 921600; SA: 115200 + * + * As long as we are not using this encoding method for anything else + * than the type_0+1 and HX chips, there is no point in complicating + * the code to support them. */ int i; @@ -304,8 +338,14 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type, baud = baud_sup[i - 1]; else baud = baud_sup[i]; - /* type_0, type_1 only support up to 1228800 baud */ - if (type != HX) + /* Respect the chip type specific baud rate limits */ + /* + * FIXME: as long as we don't know how to distinguish between the + * HXD, EA, RA, and SA chip variants, allow the max. value of 12M. + */ + if (type == HX_TA) + baud = min_t(int, baud, 6000000); + else if (type == type_0 || type == type_1) baud = min_t(int, baud, 1228800); /* Direct (standard) baud rate encoding method */ put_unaligned_le32(baud, buf); @@ -344,10 +384,19 @@ static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type, * Baud rates smaller than the specified 75 baud are definitely working * fine. */ - if (type == HX) - baud = min_t(int, baud, 6000000 * 1.1); - else + if (type == type_0 || type == type_1) baud = min_t(int, baud, 1228800 * 1.1); + else if (type == HX_TA) + baud = min_t(int, baud, 6000000 * 1.1); + else if (type == HXD_EA_RA_SA) + /* HXD, EA: 12Mbps; RA: 1Mbps; SA: 115200 bps */ + /* + * FIXME: as long as we don't know how to distinguish between + * these chip variants, allow the max. of these values + */ + baud = min_t(int, baud, 12000000 * 1.1); + else if (type == TB) + baud = min_t(int, baud, 12000000 * 1.1); /* Determine factors A and B */ A = 0; B = 12000000 * 32 / baud; /* 12MHz */ @@ -411,7 +460,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty, * the device likely uses the same baud rate generator for both methods * so that there is likley no difference. */ - if (type != HX) + if (type == type_0 || type == type_1) baud = pl2303_baudrate_encode_direct(baud, type, buf); else baud = pl2303_baudrate_encode_divisor(baud, type, buf); @@ -549,10 +598,10 @@ static void pl2303_set_termios(struct tty_struct *tty, dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); if (C_CRTSCTS(tty)) { - if (spriv->type == HX) - pl2303_vendor_write(0x0, 0x61, serial); - else + if (spriv->type == type_0 || spriv->type == type_1) pl2303_vendor_write(0x0, 0x41, serial); + else + pl2303_vendor_write(0x0, 0x61, serial); } else { pl2303_vendor_write(0x0, 0x0, serial); } @@ -589,7 +638,7 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int result; - if (spriv->type != HX) { + if (spriv->type == type_0 || spriv->type == type_1) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); } else {