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

From: Benjamin Larsson

Date: Tue Jul 14 2026 - 10:55:46 EST


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