On Fri, Mar 12, 2021 at 08:28:04PM -0500, Michael G. Katzmann wrote: > On 3/12/21 8:44 AM, Johan Hovold wrote: > > > Let me try that patch in the right format 8-) That's better, but we also need a commit message and and Signed-off-by line from you. Take a look at the general format of the patches I CCed you on and there's some more information under Documentation/: Documentation/process/submitting-patches.rst The easiest is probably to use git-format-patch and git-send-email to prevent the patch from being corrupted (e.g. the tabs below have been replaced by spaces). > --- a/drivers/usb/serial/pl2303.c 2021-03-12 09:30:22.963992109 -0500 > +++ b/drivers/usb/serial/pl2303.c 2021-03-12 20:00:20.003526891 -0500 > @@ -188,6 +188,7 @@ > unsigned long quirks; > unsigned int no_autoxonxoff:1; > unsigned int no_divisors:1; > + unsigned int alt_divisors:1; > }; > > struct pl2303_serial_private { > @@ -217,10 +218,12 @@ > [TYPE_TA] = { > .name = "TA", > .max_baud_rate = 6000000, > + .alt_divisors = true, > }, > [TYPE_TB] = { > .name = "TB", > .max_baud_rate = 12000000, > + .alt_divisors = true, Are you sure that the TB uses the alternate encoding? Charles, could you help us out here? Which other device types use the alternate encoding (e.g. HX(A) or TB) if any? > }, > [TYPE_HXD] = { > .name = "HXD", > @@ -618,6 +621,46 @@ > return baud; > } > > +static speed_t pl2303_encode_baud_rate_divisor_alt(unsigned char buf[4], > + speed_t baud) > +{ > + unsigned int baseline, mantissa, exponent; > + > + /* > + * Apparently, for the TA version the formula is: > + * baudrate = 12M * 32 / (mantissa * 2^exponent) > + * where > + * mantissa = buf[10:0] > + * exponent = buf[15:13 16] > + */ > + baseline = 12000000 * 32; > + mantissa = baseline / baud; > + if (mantissa == 0) > + mantissa = 1; /* Avoid dividing by zero if baud > 32*12M. */ > + exponent = 0; > + while (mantissa >= 2048) { > + if (exponent < 15) { > + mantissa >>= 1; /* divide by 2 */ > + exponent++; > + } else { > + /* Exponent is maxed. Trim mantissa and leave. */ > + mantissa = 2047; > + break; > + } > + } > + > + buf[3] = 0x80; > + buf[2] = exponent & 0x01; // LS bit of exponent > + buf[1] = (exponent & ~0x01) << 4 | mantissa >> 8; // 3 bits of the exponent and MS 3 bits of the mantissa > + buf[0] = mantissa & 0xff; // LS 8 bits of the mantissa Please avoid c99-style comments, but perhaps the comment at the start of function is sufficient here. Looks great otherwise. > + > + /* Calculate and return the exact baud rate. */ > + baud = (baseline / mantissa) >> exponent; > + > + return baud; > +} > + > + > static void pl2303_encode_baud_rate(struct tty_struct *tty, > struct usb_serial_port *port, > u8 buf[4]) > @@ -645,6 +688,8 @@ > > if (baud == baud_sup) > baud = pl2303_encode_baud_rate_direct(buf, baud); > + else if (spriv->type->alt_divisors) > + baud = pl2303_encode_baud_rate_divisor_alt(buf, baud); > else > baud = pl2303_encode_baud_rate_divisor(buf, baud); This works too if you don't want to pass in the port to pl2303_encode_baud_rate_divisor() and hide the device-type differences there (e.g. to make the logic in pl2303_encode_baud_rate() easier to follow). Johan