Re: [PATCH 1/4] serial: meson: add Amlogic S4 UART support

Lucas Tanure <[email protected]>
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <e8d19994-1236-4984-be2a-058cc317d10b__41267.3190164909$1786890023$gmane$org@linux.com>
On 10/08/2026 15:01, Ferass El Hafidi wrote:
> On Thu, 06 Aug 2026 10:18, "Lucas Tanure via groups.io" 
> <[email protected]> wrote:
>> The S4-generation UART (S4, T7, ...) derives its baud rate from the
>> 24 MHz crystal divided by 2, selected via the XTAL_DIV2 bit in the
>> baud rate register, while older SoCs divide the crystal by 3. Add the
>> "amlogic,meson-s4-uart" compatible with driver data selecting the
>> div-by-2 scheme, matching the Linux driver (meson_s4_uart_data) and
>> the configuration the vendor BL2 programs on T7 hardware.
>>
>> Older SoCs keep the existing div-by-3 behaviour: Linux also uses
>> div-by-2 on G12A, but both modes work there and switching would risk
>> regressing boards that have shipped with div-by-3 for years.
>>
>> Also drain the transmitter before changing the baud rate so in-flight
>> characters are not garbled, as the Linux driver does.
>>
>> Assisted-by: Claude:claude-fable-5
> 
> As I understand it, LLM-assisted patches are not welcome in U-Boot right
> now: https://lore.kernel.org/u-boot/20260515220758.GM1858239@bill-the-cat/
> 
> AFAIK there isn't an official AI policy yet, but it seems the concensus
> on that matter is currently "please don't". Sorry.

Ok, I will drop this line.

> 
>> Signed-off-by: Lucas Tanure <[email protected]>
>> ---
>> drivers/serial/serial_meson.c | 51 ++++++++++++++++++++++++++---------
>> 1 file changed, 38 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/serial/serial_meson.c b/drivers/serial/ 
>> serial_meson.c
>> index cc71381f87e..d909fedcfc4 100644
>> --- a/drivers/serial/serial_meson.c
>> +++ b/drivers/serial/serial_meson.c
>> @@ -62,26 +62,49 @@ struct meson_serial_plat {
>> #define AML_UART_REG5_USE_NEW_BAUD    BIT(23) /* default 1 (use new 
>> baud rate register) */
>> #define AML_UART_REG5_BAUD_MASK        0x7fffff
>>
>> +/* Driver data flags */
>> +#define MESON_UART_XTAL_DIV2    BIT(0)
>> +
>> #if CONFIG_IS_ENABLED(DM_SERIAL)
>> -static u32 meson_calc_baud_divisor(ulong src_rate, u32 baud)
>> +static u32 meson_uart_xtal_div(struct udevice *dev)
>> +{
>> +    /*
>> +     * S4-generation UARTs (S4, T7, ...) derive the baud rate from the
>> +     * crystal divided by 2, older ones divide by 3.
>> +     */
>> +    return (dev_get_driver_data(dev) & MESON_UART_XTAL_DIV2) ? 2 : 3;
>> +}
>> +
>> +static u32 meson_calc_baud_divisor(struct udevice *dev, ulong 
>> src_rate, u32 baud)
>> {
>>     /*
>>      * Usually src_rate is 24 MHz (from crystal) as clock source for 
>> serial
>> -     * device. Since 8 Mb/s is the maximum supported baud rate, use 
>> div by 3
>> -     * to derive baud rate. This choice is used also in 
>> meson_serial_setbrg.
>> +     * device. Since 8 Mb/s is the maximum supported baud rate, use a
>> +     * divided crystal to derive the baud rate. This choice is used 
>> also in
>> +     * meson_serial_setbrg.
>>      */
>> -    return DIV_ROUND_CLOSEST(src_rate / 3, baud) - 1;
>> +    return DIV_ROUND_CLOSEST(src_rate / meson_uart_xtal_div(dev), 
>> baud) - 1;
>> }
>>
>> -static void meson_serial_set_baud(struct meson_uart *uart, ulong 
>> src_rate, u32 baud)
>> +static void meson_serial_set_baud(struct udevice *dev, struct 
>> meson_uart *uart,
>> +                  ulong src_rate, u32 baud)
>> {
>>     /*
>> -     * Set crystal divided by 3 (regardless of device tree clock 
>> property)
>> +     * Set the divided crystal (regardless of device tree clock 
>> property)
>>      * as clock source and the corresponding divisor to approximate baud
>>      */
>> -    u32 divisor = meson_calc_baud_divisor(src_rate, baud);
>> +    u32 divisor = meson_calc_baud_divisor(dev, src_rate, baud);
>>     u32 val = AML_UART_REG5_USE_XTAL_CLK | AML_UART_REG5_USE_NEW_BAUD |
>>         (divisor & AML_UART_REG5_BAUD_MASK);
>> +
>> +    if (meson_uart_xtal_div(dev) == 2)
>> +        val |= AML_UART_REG5_XTAL_DIV2;
>> +
>> +    /* Drain the transmitter before changing the baud rate */
>> +    while ((readl(&uart->status) & (AML_UART_TX_EMPTY | 
>> AML_UART_XMIT_BUSY))
>> +           != AML_UART_TX_EMPTY)
>> +        ;
>> +
>>     writel(val, &uart->reg5);
>> }
>>
>> @@ -109,7 +132,7 @@ static int meson_serial_probe(struct udevice *dev)
>>         return ret;
>>     ulong rate = clk_get_rate(&per_clk);
>>
>> -    meson_serial_set_baud(uart, rate, CONFIG_BAUDRATE);
>> +    meson_serial_set_baud(dev, uart, rate, CONFIG_BAUDRATE);
>>     meson_serial_init(uart);
>>
>>     return 0;
>> @@ -165,8 +188,9 @@ static int meson_serial_setbrg(struct udevice 
>> *dev, const int baud)
>> {
>>     /*
>>      * Change device baud rate if baud is reasonable (considering a 23 
>> bit
>> -     * counter with an 8 MHz clock input) and the actual baud
>> -     * rate is within 2% of the requested value (2% is arbitrary).
>> +     * counter with an 8 MHz, or 12 MHz for XTAL_DIV2 devices, clock 
>> input)
>> +     * and the actual baud rate is within 2% of the requested value 
>> (2% is
>> +     * arbitrary).
>>      */
>>     if (baud < 1 || baud > 8000000)
>>         return -EINVAL;
>> @@ -179,14 +203,14 @@ static int meson_serial_setbrg(struct udevice 
>> *dev, const int baud)
>>     if (ret)
>>         return ret;
>>     ulong rate = clk_get_rate(&per_clk);
>> -    u32 divisor = meson_calc_baud_divisor(rate, baud);
>> -    u32 calc_baud = (rate / 3) / (divisor + 1);
>> +    u32 divisor = meson_calc_baud_divisor(dev, rate, baud);
>> +    u32 calc_baud = (rate / meson_uart_xtal_div(dev)) / (divisor + 1);
>>     u32 calc_err = baud > calc_baud ? baud - calc_baud : calc_baud - 
>> baud;
>>
>>     if (((calc_err * 100) / baud) > 2)
>>         return -EINVAL;
>>
>> -    meson_serial_set_baud(uart, rate, baud);
>> +    meson_serial_set_baud(dev, uart, rate, baud);
>>
>>     return 0;
>> }
>> @@ -244,6 +268,7 @@ static const struct udevice_id meson_serial_ids[] = {
>>     { .compatible = "amlogic,meson-uart" },
>>     { .compatible = "amlogic,meson-gx-uart" },
>>     { .compatible = "amlogic,meson-a1-uart" },
>> +    { .compatible = "amlogic,meson-s4-uart", .data = 
>> MESON_UART_XTAL_DIV2 },
>>     { }
>> };
>>
>> -- 
>> 2.55.0
> 
> Best regards,
> Ferass
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.