Re: [PATCH 4/4] serial: 8250: Add Airoha SoC UART and HSUART support

Benjamin Larsson <[email protected]>
Newsgroups org.kernel.vger.linux-serial,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 10/07/2026 09:13, Jiri Slaby wrote:
>> +static void airoha_set_termios(struct uart_port *port, struct 
>> ktermios *termios,
>> +                            const struct ktermios *old)
>> +{
>> +     const struct airoha_8250_clk_div_info *clk_div_info;
>> +     struct uart_8250_port *up = up_to_u8250p(port);
>> +     unsigned int xyd_x, nom, denom;
>> +     unsigned int baud;
>> +     int i;
>> +
>> +     serial8250_do_set_termios(port, termios, old);
>> +
>> +     baud = serial8250_get_baud_rate(port, termios, old);
>> +
>> +     /* Set DLAB to access the baud rate divider registers (BRDH, 
>> BRDL) */
>> +     serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
>> +
>> +     /* Set baud rate calculation defaults (BRDIV ([BRDH,BRDL]) to 1) */
>> +     serial_port_out(port, UART_AIROHA_BRDL, UART_BRDL_20M);
>> +     serial_port_out(port, UART_AIROHA_BRDH, UART_BRDH_20M);
>> +
>> +     /*
>> +      * Calculate XYD_x and XINCLKDR register by searching
>> +      * through a table of crystal_clock divisors.
>> +      */
>> +     for (i = 0 ; i < ARRAY_SIZE(airoha_clk_div_info) ; i++) {
>> +             clk_div_info = &airoha_clk_div_info[i];
>> +
>> +             denom = (XINDIV_CLOCK / 40) / clk_div_info->div;
>> +             nom = baud * (XYD_Y / 40);
> 
> Are these "/ 40" to avoid overflow? Add a comment.

Yes, this is to keep it in 32bits.

> 
>> +             xyd_x = ((nom / denom) << 4);
> 
> * don't you want to round to closest instead of down?
> * I don't understand the purpose of the shift though.

IIRC this is the vendor calculation logic scaled to fit 32bits. With 
this rounding/calculation we hit the baud rate exactly for the baud 
rates that people actually use.

> 
>> +             /* For the HSUART xyd_x needs to be scaled by a factor 
>> of 2 */
>> +             if (port->type == UART_PORT_AIROHA_HS)
>> +                     xyd_x = xyd_x >> 1;
> 
> Do not use shifts for div/mul.
> 
>> +             if (xyd_x < XYD_Y)
>> +                     break;
>> +     }
>> +
>> +     serial_port_out(port, UART_AIROHA_XINCLKDR, clk_div_info->mask);
>> +     serial_port_out(port, UART_AIROHA_XYD, (xyd_x << 16) | XYD_Y);
>> +
>> +     /* unset DLAB */
>> +     serial_port_out(port, UART_LCR, up->lcr);
>> +}
> 
> thanks,
> -- 
> js
> suse labs

MvH
Benjamin Larsson
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.