Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

serial: 8250_pci: Remove custom deprecated baud setting routine

As comments mentioned this is old (and actually deprecated) interface
to set custom baud rates. This interface has limitations as it only
allows to set a single opaque value called "custom_divisor". If the HW
needs more complex settings (like fractional divisor) it must somehow
encode this. This is horrid interface that is very driver specific
and not flexible. Meanwhile Linux has established way to set free
baud rate settings via BOTHER [1]. With all this being said, remove
deprecated interface for good.

Link: https://stackoverflow.com/questions/12646324/how-can-i-set-a-custom-baud-rate-on-linux [1]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260122102349.2395423-3-andriy.shevchenko@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Andy Shevchenko and committed by
Greg Kroah-Hartman
3f0716c6 1250ebac

+38 -73
+1 -25
Documentation/misc-devices/oxsemi-tornado.rst
··· 89 89 limitation imposed by ``serial8250_get_baud_rate`` standard baud rates 90 90 below 300bps become unavailable in the regular way, e.g. the rate of 91 91 200bps requires the baud base to be divided by 78125 and that is beyond 92 - the unsigned 16-bit range. The historic spd_cust feature can still be 93 - used by encoding the values for, the prescaler, the oversampling rate 94 - and the clock divisor (DLM/DLL) as follows to obtain such rates if so 95 - required: 96 - 97 - :: 98 - 99 - 31 29 28 20 19 16 15 0 100 - +-----+-----------------+-------+-------------------------------+ 101 - |0 0 0| CPR2:CPR | TCR | DLM:DLL | 102 - +-----+-----------------+-------+-------------------------------+ 103 - 104 - Use a value such encoded for the ``custom_divisor`` field along with the 105 - ASYNC_SPD_CUST flag set in the ``flags`` field in ``struct serial_struct`` 106 - passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8) 107 - utility and its ``divisor`` and ``spd_cust`` parameters, and then select 108 - the baud rate of 38400bps. Note that the value of 0 in TCR sets the 109 - oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are 110 - clamped by the driver to 1. 111 - 112 - For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL 113 - respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value, 114 - the oversampling rate and the clock divisor of 62.500, 16 and 1250 115 - respectively. These parameters will set the baud rate for the serial 116 - port to 62500000 / 62.500 / 1250 / 16 = 50bps. 92 + the unsigned 16-bit range. 117 93 118 94 Maciej W. Rozycki <macro@orcam.me.uk> 119 95
+37 -48
drivers/tty/serial/8250/8250_pci.c
··· 1205 1205 u8 tcr; 1206 1206 int i; 1207 1207 1208 - /* Old custom speed handling. */ 1209 - if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) { 1210 - unsigned int cust_div = port->custom_divisor; 1208 + best_squot = quot_scale; 1209 + for (i = 0; i < ARRAY_SIZE(p); i++) { 1210 + unsigned int spre; 1211 + unsigned int srem; 1212 + u8 cp; 1213 + u8 tc; 1211 1214 1212 - quot = cust_div & UART_DIV_MAX; 1213 - tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK; 1214 - cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK; 1215 - if (cpr < OXSEMI_TORNADO_CPR_MIN) 1216 - cpr = OXSEMI_TORNADO_CPR_DEF; 1217 - } else { 1218 - best_squot = quot_scale; 1219 - for (i = 0; i < ARRAY_SIZE(p); i++) { 1220 - unsigned int spre; 1221 - unsigned int srem; 1222 - u8 cp; 1223 - u8 tc; 1215 + tc = p[i][0]; 1216 + cp = p[i][1]; 1217 + spre = tc * cp; 1224 1218 1225 - tc = p[i][0]; 1226 - cp = p[i][1]; 1227 - spre = tc * cp; 1219 + srem = sdiv % spre; 1220 + if (srem > spre / 2) 1221 + srem = spre - srem; 1222 + squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre); 1228 1223 1229 - srem = sdiv % spre; 1230 - if (srem > spre / 2) 1231 - srem = spre - srem; 1232 - squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre); 1233 - 1234 - if (srem == 0) { 1235 - tcr = tc; 1236 - cpr = cp; 1237 - quot = sdiv / spre; 1238 - break; 1239 - } else if (squot < best_squot) { 1240 - best_squot = squot; 1241 - tcr = tc; 1242 - cpr = cp; 1243 - quot = DIV_ROUND_CLOSEST(sdiv, spre); 1244 - } 1224 + if (srem == 0) { 1225 + tcr = tc; 1226 + cpr = cp; 1227 + quot = sdiv / spre; 1228 + break; 1229 + } else if (squot < best_squot) { 1230 + best_squot = squot; 1231 + tcr = tc; 1232 + cpr = cp; 1233 + quot = DIV_ROUND_CLOSEST(sdiv, spre); 1245 1234 } 1246 - while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 && 1247 - quot % 2 == 0) { 1235 + } 1236 + while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 && 1237 + quot % 2 == 0) { 1238 + quot >>= 1; 1239 + tcr <<= 1; 1240 + } 1241 + while (quot > UART_DIV_MAX) { 1242 + if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) { 1248 1243 quot >>= 1; 1249 1244 tcr <<= 1; 1250 - } 1251 - while (quot > UART_DIV_MAX) { 1252 - if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) { 1253 - quot >>= 1; 1254 - tcr <<= 1; 1255 - } else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) { 1256 - quot >>= 1; 1257 - cpr <<= 1; 1258 - } else { 1259 - quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK; 1260 - cpr = OXSEMI_TORNADO_CPR_MASK; 1261 - } 1245 + } else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) { 1246 + quot >>= 1; 1247 + cpr <<= 1; 1248 + } else { 1249 + quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK; 1250 + cpr = OXSEMI_TORNADO_CPR_MASK; 1262 1251 } 1263 1252 } 1264 1253