USB: serial: ch341: reimplement line-speed handling
The current ch341 divisor algorithm was known to give inaccurate results for certain higher line speeds. Jonathan Olds <jontio@i4free.co.nz> investigated this, determined the basic equations used to derive the divisors and confirmed them experimentally [1]. The equations Jonathan used could be generalised further to: baudrate = 48000000 / (2^(12 - 3 * ps - fact) * div), where 0 <= ps <= 3, 0 <= fact <= 1, 2 <= div <= 256 if fact = 0, or 9 <= div <= 256 if fact = 1 which will also give better results for lower rates. Notably the error is reduced for the following standard rates: 1152000 (4.0% instead of 15% error) 921600 (0.16% instead of -7.5% error) 576000 (-0.80% instead of -5.6% error) 200 (0.16% instead of -0.69% error) 134 (-0.05% instead of -0.63% error) 110 (0.03% instead of -0.44% error) but also for many non-standard ones. The current algorithm also suffered from rounding issues (e.g. requesting 2950000 Bd resulted in a rate of 2 MBd instead of 3 MBd and thus a -32% instead of 1.7% error). The new algorithm was inspired by the current vendor driver even if that one only handles two higher rates that require fact=1 by hard coding the corresponding divisors [2]. Michael Dreher <michael@5dot1.de> also did a similar generalisation of Jonathan's work and has published his results with a very good summary that provides further insights into how this device works [3]. [1] https://lkml.kernel.org/r/000001d51f34$bad6afd0$30840f70$@co.nz [2] http://www.wch.cn/download/CH341SER_LINUX_ZIP.html [3] https://github.com/nospam2000/ch341-baudrate-calculationReported-by: Jonathan Olds <jontio@i4free.co.nz> Tested-by: Jonathan Olds <jontio@i4free.co.nz> Cc: Michael Dreher <michael@5dot1.de> Signed-off-by: Johan Hovold <johan@kernel.org>
Showing
Please register or sign in to comment