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