diff options
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
| -rw-r--r-- | drivers/usb/serial/pl2303.c | 35 | 
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index f5257af33ecf..ae682e4eeaef 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -362,21 +362,38 @@ 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; +	unsigned int baseline, mantissa, exponent;  	/*  	 * 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; +	baseline = 12000000 * 32; +	mantissa = baseline / baud; +	if (mantissa == 0) +		mantissa = 1;	/* Avoid dividing by zero if baud > 32*12M. */ +	exponent = 0; +	while (mantissa >= 512) { +		if (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;  }  |