Am 08.07.2015 um 12:51 schrieb Michał Pecio: > This commit fixes the following issues: > > 1. The 9th bit of buf was believed to be the LSB of divisor's > exponent, but the hardware interprets it as MSB (9th bit) of the > mantissa. The exponent is actually one bit shorter and applies > to base 4, not 2 as previously believed. > > 2. Loop iterations doubled the exponent instead of incrementing. > > 3. The exponent wasn't checked for overflow. > > 4. The function returned requested rate instead of actual rate. > > Due to issue #2, the old code deviated from the wrong formula > described in #1 and actually yielded correct rates when divisor > was lower than 4096 by giving exponents of 0, 2 or 4 base-2, > interpreted as 0, 1, 2 base-4 with the 9th mantissa bit clear. > However, at 93.75 kbaud or less the rate turned out too slow > due to #1 and #2 or too fast due to #2 with #3. > > I tested this patch by sending and validating 0x00,0x01,..,0xff > to an FTDI dongle at 234, 987, 2401, 9601, 31415, 115199, 250k, > 500k, 750k, 1M, 1.5M, 3M+1 baud. All rates passed. > > I also used pv to check speed at some rates unsupported by FTDI: > 45 (the lowest possible), 2M, 4M, 5M and 6M-1. Looked sane. > > Signed-off-by: Michal Pecio <michal.pecio@xxxxxxxxx> > --- > drivers/usb/serial/pl2303.c | 32 ++++++++++++++++++++++---------- > 1 file changed, 22 insertions(+), 10 deletions(-) > > diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c > index f5257af..8141ccc 100644 > --- a/drivers/usb/serial/pl2303.c > +++ b/drivers/usb/serial/pl2303.c > @@ -362,22 +362,34 @@ static speed_t pl2303_encode_baud_rate_direct(unsigned char buf[4], > static speed_t pl2303_encode_baud_rate_divisor(unsigned char buf[4], > speed_t baud) > { > - unsigned int tmp; > - > /* > * Apparently the formula is: > - * baudrate = 12M * 32 / (2^buf[1]) / buf[0] > + * baudrate = 12M * 32 / (mantissa * 4^exponent) > + * where > + * mantissa = buf[8:0] > + * exponent = buf[11:9] > */ > - tmp = 12000000 * 32 / baud; > + u32 baseline = 12000000 * 32; > + u32 mantissa = baseline / baud; > + u32 exponent = 0; > + while (mantissa >= 512) { > + if (likely(exponent < 7)) { > + mantissa >>= 2; /* divide by 4 */ > + exponent++; > + } else { > + /* Exponent is maxed. Trim mantissa and leave. */ > + mantissa = 511; > + break; > + } > + } > + > buf[3] = 0x80; > buf[2] = 0; > - buf[1] = (tmp >= 256); > - while (tmp >= 256) { > - tmp >>= 2; > - buf[1] <<= 1; > - } > - buf[0] = tmp; > + buf[1] = (exponent << 1) | (mantissa >> 8); > + buf[0] = (mantissa & 0xff); > > + /* Calculate and return the exact baud rate. */ > + baud = (baseline / mantissa) >> (exponent << 1); > return baud; > } > Commit 57ce61aad748 might be helpful... ;) Good luck, Frank -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html