USB: serial: pl2303: TA & TB alternate divider
Subsystems (2)
PATCH 1/1 USB: serial: pl2303: TA & TB alternate divider
From: Michael Katzmann <[email protected]>
Use an alternate clock divider algorithm and bit ordering for the TA and TB versions of the pl2303. It was discovered that these variants do not produce the correct baud rates with the existing scheme.
see https://marc.info/?t=161392209800002&r=1&w=2
--- drivers/usb/serial/pl2303.c | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
drivers/usb/serial/pl2303.c +45 -0
@@ -188,6 +188,7 @@ struct pl2303_type_data {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 @@ static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = { [TYPE_TA] = { .name = "TA", .max_baud_rate = 6000000, + .alt_divisors = true, }, [TYPE_TB] = { .name = "TB", .max_baud_rate = 12000000, + .alt_divisors = true, }, [TYPE_HXD] = { .name = "HXD",
@@ -618,6 +621,46 @@ static speed_t pl2303_encode_baud_rate_divisor(unsigned char buf[4],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 ; + buf[1 ] = (exponent & ~0x01 ) <<4 | mantissa >>8 ; + buf[0 ] = mantissa &0xff ; + +/* 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 @@ static void pl2303_encode_baud_rate(struct tty_struct *tty,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);
Signature · 1 line
2.30.2
Quoted 7 lines · On Mon, Mar 15, 2021 at 09:42:05PM -0400, [email protected] wrote:
From: Michael Katzmann <[email protected]>
Use an alternate clock divider algorithm and bit ordering for the TA and TB versions of the pl2303. It was discovered that these variants do not produce the correct baud rates with the existing scheme.
Can you point to a lore.kernel.org thread instead? We (kernel developer community) have control over lore, but not over marc.info or any other archive, so we never know if it will be around or not over time :)
thanks,
greg k-h
Johan Hovold
maintainerQuoted 7 lines · Greg Kroah-Hartman
Quoted 6 lines · On Mon, Mar 15, 2021 at 09:42:05PM -0400, [email protected] wrote:
From: Michael Katzmann <[email protected]>
Use an alternate clock divider algorithm and bit ordering for the TA and TB versions of the pl2303. It was discovered that these variants do not produce the correct baud rates with the existing scheme.
Quoted 5 lines
Quoted 1 line
Can you point to a lore.kernel.org thread instead? We (kernel developer community) have control over lore, but not over marc.info or any other archive, so we never know if it will be around or not over time :)
I was gonna say that I could fix that up when applying, but turns out there are some formatting issues with the patch.
Michael, it looks like you've used tabs instead of spaces for indentation in some places. Try running scripts/checkpatch.pl on the patch before submitting (which would have caught this).
Care to send a v2?
And the lore link would be:
https://lore.kernel.org/r/[email protected]
Johan