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>
This commit is contained in:
Andy Shevchenko 2026-01-22 11:19:48 +01:00 committed by Greg Kroah-Hartman
parent 1250ebacd4
commit 3f0716c604
2 changed files with 38 additions and 73 deletions

View file

@ -89,31 +89,7 @@ With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX
limitation imposed by ``serial8250_get_baud_rate`` standard baud rates
below 300bps become unavailable in the regular way, e.g. the rate of
200bps requires the baud base to be divided by 78125 and that is beyond
the unsigned 16-bit range. The historic spd_cust feature can still be
used by encoding the values for, the prescaler, the oversampling rate
and the clock divisor (DLM/DLL) as follows to obtain such rates if so
required:
::
31 29 28 20 19 16 15 0
+-----+-----------------+-------+-------------------------------+
|0 0 0| CPR2:CPR | TCR | DLM:DLL |
+-----+-----------------+-------+-------------------------------+
Use a value such encoded for the ``custom_divisor`` field along with the
ASYNC_SPD_CUST flag set in the ``flags`` field in ``struct serial_struct``
passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8)
utility and its ``divisor`` and ``spd_cust`` parameters, and then select
the baud rate of 38400bps. Note that the value of 0 in TCR sets the
oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are
clamped by the driver to 1.
For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL
respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value,
the oversampling rate and the clock divisor of 62.500, 16 and 1250
respectively. These parameters will set the baud rate for the serial
port to 62500000 / 62.500 / 1250 / 16 = 50bps.
the unsigned 16-bit range.
Maciej W. Rozycki <macro@orcam.me.uk>

View file

@ -1205,60 +1205,49 @@ static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port,
u8 tcr;
int i;
/* Old custom speed handling. */
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
unsigned int cust_div = port->custom_divisor;
best_squot = quot_scale;
for (i = 0; i < ARRAY_SIZE(p); i++) {
unsigned int spre;
unsigned int srem;
u8 cp;
u8 tc;
quot = cust_div & UART_DIV_MAX;
tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK;
cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK;
if (cpr < OXSEMI_TORNADO_CPR_MIN)
cpr = OXSEMI_TORNADO_CPR_DEF;
} else {
best_squot = quot_scale;
for (i = 0; i < ARRAY_SIZE(p); i++) {
unsigned int spre;
unsigned int srem;
u8 cp;
u8 tc;
tc = p[i][0];
cp = p[i][1];
spre = tc * cp;
tc = p[i][0];
cp = p[i][1];
spre = tc * cp;
srem = sdiv % spre;
if (srem > spre / 2)
srem = spre - srem;
squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre);
srem = sdiv % spre;
if (srem > spre / 2)
srem = spre - srem;
squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre);
if (srem == 0) {
tcr = tc;
cpr = cp;
quot = sdiv / spre;
break;
} else if (squot < best_squot) {
best_squot = squot;
tcr = tc;
cpr = cp;
quot = DIV_ROUND_CLOSEST(sdiv, spre);
}
if (srem == 0) {
tcr = tc;
cpr = cp;
quot = sdiv / spre;
break;
} else if (squot < best_squot) {
best_squot = squot;
tcr = tc;
cpr = cp;
quot = DIV_ROUND_CLOSEST(sdiv, spre);
}
while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 &&
quot % 2 == 0) {
}
while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 &&
quot % 2 == 0) {
quot >>= 1;
tcr <<= 1;
}
while (quot > UART_DIV_MAX) {
if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) {
quot >>= 1;
tcr <<= 1;
}
while (quot > UART_DIV_MAX) {
if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) {
quot >>= 1;
tcr <<= 1;
} else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) {
quot >>= 1;
cpr <<= 1;
} else {
quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK;
cpr = OXSEMI_TORNADO_CPR_MASK;
}
} else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) {
quot >>= 1;
cpr <<= 1;
} else {
quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK;
cpr = OXSEMI_TORNADO_CPR_MASK;
}
}