Skip to content

Commit e917ba0

Browse files
Frank Schäfergregkh
authored andcommitted
usb: pl2303: move the two baud rate encoding methods to separate functions
Signed-off-by: Frank Schäfer <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b9208c7 commit e917ba0

File tree

1 file changed

+114
-101
lines changed

1 file changed

+114
-101
lines changed

drivers/usb/serial/pl2303.c

Lines changed: 114 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -269,115 +269,128 @@ static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)
269269
return retval;
270270
}
271271

272+
static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type,
273+
u8 buf[4])
274+
{
275+
/*
276+
* NOTE: Only the values defined in baud_sup are supported !
277+
* => if unsupported values are set, the PL2303 seems to
278+
* use 9600 baud (at least my PL2303X always does)
279+
*/
280+
const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
281+
4800, 7200, 9600, 14400, 19200, 28800, 38400,
282+
57600, 115200, 230400, 460800, 614400, 921600,
283+
1228800, 2457600, 3000000, 6000000 };
284+
int i;
285+
286+
/* Set baudrate to nearest supported value */
287+
for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) {
288+
if (baud_sup[i] > baud)
289+
break;
290+
}
291+
if (i == ARRAY_SIZE(baud_sup))
292+
baud = baud_sup[i - 1];
293+
else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1]))
294+
baud = baud_sup[i - 1];
295+
else
296+
baud = baud_sup[i];
297+
/* type_0, type_1 only support up to 1228800 baud */
298+
if (type != HX)
299+
baud = min_t(int, baud, 1228800);
300+
/* Direct (standard) baud rate encoding method */
301+
put_unaligned_le32(baud, buf);
302+
303+
return baud;
304+
}
305+
306+
static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type,
307+
u8 buf[4])
308+
{
309+
/*
310+
* Divisor based baud rate encoding method
311+
*
312+
* NOTE: it's not clear if the type_0/1 chips support this method
313+
*
314+
* divisor = 12MHz * 32 / baudrate = 2^A * B
315+
*
316+
* with
317+
*
318+
* A = buf[1] & 0x0e
319+
* B = buf[0] + (buf[1] & 0x01) << 8
320+
*
321+
* Special cases:
322+
* => 8 < B < 16: device seems to work not properly
323+
* => B <= 8: device uses the max. value B = 512 instead
324+
*/
325+
unsigned int A, B;
326+
327+
/* Respect the specified baud rate limits */
328+
baud = max_t(int, baud, 75);
329+
if (type == HX)
330+
baud = min_t(int, baud, 6000000);
331+
else
332+
baud = min_t(int, baud, 1228800);
333+
/* Determine factors A and B */
334+
A = 0;
335+
B = 12000000 * 32 / baud; /* 12MHz */
336+
B <<= 1; /* Add one bit for rounding */
337+
while (B > (512 << 1) && A <= 14) {
338+
A += 2;
339+
B >>= 2;
340+
}
341+
if (A > 14) { /* max. divisor = min. baudrate reached */
342+
A = 14;
343+
B = 512;
344+
/* => ~45.78 baud */
345+
} else {
346+
B = (B + 1) >> 1; /* Round the last bit */
347+
}
348+
/* Handle special cases */
349+
if (B == 512)
350+
B = 0; /* also: 1 to 8 */
351+
else if (B < 16)
352+
/*
353+
* NOTE: With the current algorithm this happens
354+
* only for A=0 and means that the min. divisor
355+
* (respectively: the max. baudrate) is reached.
356+
*/
357+
B = 16; /* => 24 MBaud */
358+
/* Encode the baud rate */
359+
buf[3] = 0x80; /* Select divisor encoding method */
360+
buf[2] = 0;
361+
buf[1] = (A & 0x0e); /* A */
362+
buf[1] |= ((B & 0x100) >> 8); /* MSB of B */
363+
buf[0] = B & 0xff; /* 8 LSBs of B */
364+
/* Calculate the actual/resulting baud rate */
365+
if (B <= 8)
366+
B = 512;
367+
baud = 12000000 * 32 / ((1 << A) * B);
368+
369+
return baud;
370+
}
371+
272372
static void pl2303_encode_baudrate(struct tty_struct *tty,
273373
struct usb_serial_port *port,
374+
enum pl2303_type type,
274375
u8 buf[4])
275376
{
276-
struct usb_serial *serial = port->serial;
277-
struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
278377
int baud;
279378

280379
baud = tty_get_baud_rate(tty);
281380
dev_dbg(&port->dev, "baud requested = %d\n", baud);
282381
if (!baud)
283382
return;
284-
285-
if (spriv->type != HX || baud <= 115200) {
286-
/*
287-
* NOTE: Only the values defined in baud_sup are supported !
288-
* => if unsupported values are set, the PL2303 seems to
289-
* use 9600 baud (at least my PL2303X always does)
290-
*/
291-
const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400,
292-
3600, 4800, 7200, 9600, 14400, 19200,
293-
28800, 38400, 57600, 115200, 230400,
294-
460800, 614400, 921600, 1228800,
295-
2457600, 3000000, 6000000 };
296-
int i;
297-
298-
/* Set baudrate to nearest supported value */
299-
for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) {
300-
if (baud_sup[i] > baud)
301-
break;
302-
}
303-
304-
if (i == ARRAY_SIZE(baud_sup))
305-
baud = baud_sup[i - 1];
306-
else if (i > 0
307-
&& (baud_sup[i] - baud) > (baud - baud_sup[i - 1]))
308-
baud = baud_sup[i - 1];
309-
else
310-
baud = baud_sup[i];
311-
312-
/* type_0, type_1 only support up to 1228800 baud */
313-
if (spriv->type != HX)
314-
baud = min_t(int, baud, 1228800);
315-
316-
/* Direct (standard) baud rate encoding method */
317-
put_unaligned_le32(baud, buf);
318-
} else {
319-
/*
320-
* Divisor based baud rate encoding method
321-
*
322-
* NOTE: it's not clear if the type_0/1 chips
323-
* support this method
324-
*
325-
* divisor = 12MHz * 32 / baudrate = 2^A * B
326-
*
327-
* with
328-
*
329-
* A = buf[1] & 0x0e
330-
* B = buf[0] + (buf[1] & 0x01) << 8
331-
*
332-
* Special cases:
333-
* => 8 < B < 16: device seems to work not properly
334-
* => B <= 8: device uses the max. value B = 512 instead
335-
*/
336-
unsigned int A, B;
337-
338-
/* Respect the specified baud rate limits */
339-
baud = max_t(int, baud, 75);
340-
if (spriv->type == HX)
341-
baud = min_t(int, baud, 6000000);
342-
else
343-
baud = min_t(int, baud, 1228800);
344-
/* Determine factors A and B */
345-
A = 0;
346-
B = 12000000 * 32 / baud; /* 12MHz */
347-
B <<= 1; /* Add one bit for rounding */
348-
while (B > (512 << 1) && A <= 14) {
349-
A += 2;
350-
B >>= 2;
351-
}
352-
if (A > 14) { /* max. divisor = min. baudrate reached */
353-
A = 14;
354-
B = 512;
355-
/* => ~45.78 baud */
356-
} else {
357-
B = (B + 1) >> 1; /* Round the last bit */
358-
}
359-
/* Handle special cases */
360-
if (B == 512)
361-
B = 0; /* also: 1 to 8 */
362-
else if (B < 16)
363-
/*
364-
* NOTE: With the current algorithm this happens
365-
* only for A=0 and means that the min. divisor
366-
* (respectively: the max. baudrate) is reached.
367-
*/
368-
B = 16; /* => 24 MBaud */
369-
/* Encode the baud rate */
370-
buf[3] = 0x80; /* Select divisor encoding method */
371-
buf[2] = 0;
372-
buf[1] = (A & 0x0e); /* A */
373-
buf[1] |= ((B & 0x100) >> 8); /* MSB of B */
374-
buf[0] = B & 0xff; /* 8 LSBs of B */
375-
/* Calculate the actual/resulting baud rate */
376-
if (B <= 8)
377-
B = 512;
378-
baud = 12000000 * 32 / ((1 << A) * B);
379-
}
380-
383+
/*
384+
* There are two methods for setting/encoding the baud rate
385+
* 1) Direct method: encodes the baud rate value directly
386+
* => supported by all chip types
387+
* 2) Divisor based method: encodes a divisor to a base value (12MHz*32)
388+
* => supported by HX chips (and likely not by type_0/1 chips)
389+
*/
390+
if (type != HX || baud <= 115200)
391+
baud = pl2303_baudrate_encode_direct(baud, type, buf);
392+
else
393+
baud = pl2303_baudrate_encode_divisor(baud, type, buf);
381394
/* Save resulting baud rate */
382395
tty_encode_baud_rate(tty, baud, baud);
383396
dev_dbg(&port->dev, "baud set = %d\n", baud);
@@ -434,8 +447,8 @@ static void pl2303_set_termios(struct tty_struct *tty,
434447
dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
435448
}
436449

437-
/* For reference buf[0]:buf[3] baud rate value */
438-
pl2303_encode_baudrate(tty, port, &buf[0]);
450+
/* For reference: buf[0]:buf[3] baud rate value */
451+
pl2303_encode_baudrate(tty, port, spriv->type, buf);
439452

440453
/* For reference buf[4]=0 is 1 stop bits */
441454
/* For reference buf[4]=1 is 1.5 stop bits */

0 commit comments

Comments
 (0)