lkml.org 
[lkml]   [2021]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 125/130] serial: 8250_pci: rewrite pericom_do_set_divisor()
    Date
    From: Jay Dolan <jay.dolan@accesio.com>

    commit bb1201d4b38ec67bd9a871cf86b0cc10f28b15b5 upstream.

    Have pericom_do_set_divisor() use the uartclk instead of a hard coded
    value to work with different speed crystals. Tested with 14.7456 and 24
    MHz crystals.

    Have pericom_do_set_divisor() always calculate the divisor rather than
    call serial8250_do_set_divisor() for rates below baud_base.

    Do not write registers or call serial8250_do_set_divisor() if valid
    divisors could not be found.

    Fixes: 6bf4e42f1d19 ("serial: 8250: Add support for higher baud rates to Pericom chips")
    Cc: stable <stable@vger.kernel.org>
    Signed-off-by: Jay Dolan <jay.dolan@accesio.com>
    Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Link: https://lore.kernel.org/r/20211122120604.3909-3-andriy.shevchenko@linux.intel.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/tty/serial/8250/8250_pci.c | 30 +++++++++++++++++-------------
    1 file changed, 17 insertions(+), 13 deletions(-)

    --- a/drivers/tty/serial/8250/8250_pci.c
    +++ b/drivers/tty/serial/8250/8250_pci.c
    @@ -1349,29 +1349,33 @@ pericom_do_set_divisor(struct uart_port
    {
    int scr;
    int lcr;
    - int actual_baud;
    - int tolerance;

    - for (scr = 5 ; scr <= 15 ; scr++) {
    - actual_baud = 921600 * 16 / scr;
    - tolerance = actual_baud / 50;
    + for (scr = 16; scr > 4; scr--) {
    + unsigned int maxrate = port->uartclk / scr;
    + unsigned int divisor = max(maxrate / baud, 1U);
    + int delta = maxrate / divisor - baud;

    - if ((baud < actual_baud + tolerance) &&
    - (baud > actual_baud - tolerance)) {
    + if (baud > maxrate + baud / 50)
    + continue;

    + if (delta > baud / 50)
    + divisor++;
    +
    + if (divisor > 0xffff)
    + continue;
    +
    + /* Update delta due to possible divisor change */
    + delta = maxrate / divisor - baud;
    + if (abs(delta) < baud / 50) {
    lcr = serial_port_in(port, UART_LCR);
    serial_port_out(port, UART_LCR, lcr | 0x80);
    -
    - serial_port_out(port, UART_DLL, 1);
    - serial_port_out(port, UART_DLM, 0);
    + serial_port_out(port, UART_DLL, divisor & 0xff);
    + serial_port_out(port, UART_DLM, divisor >> 8 & 0xff);
    serial_port_out(port, 2, 16 - scr);
    serial_port_out(port, UART_LCR, lcr);
    return;
    - } else if (baud > actual_baud) {
    - break;
    }
    }
    - serial8250_do_set_divisor(port, baud, quot, quot_frac);
    }
    static int pci_pericom_setup(struct serial_private *priv,
    const struct pciserial_board *board,

    \
     
     \ /
      Last update: 2021-12-06 16:49    [W:5.075 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site