All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lucas Tanure <tanure@linux.com>
To: u-boot@lists.u-boot-project.org
Cc: neil.armstrong@linaro.org, trini@konsulko.com,
	ilias.apalodimas@linaro.org, funderscore@postmasteros.org,
	u-boot-amlogic@groups.io, Lucas Tanure <tanure@linux.com>
Subject: [PATCH 1/4] serial: meson: add Amlogic S4 UART support
Date: Thu,  6 Aug 2026 11:18:06 +0100	[thread overview]
Message-ID: <20260806101809.72526-2-tanure@linux.com> (raw)
In-Reply-To: <20260806101809.72526-1-tanure@linux.com>

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
Signed-off-by: Lucas Tanure <tanure@linux.com>
---
 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


  reply	other threads:[~2026-08-06 11:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-06 10:18 [PATCH 0/4] Add Amlogic T7 (A311D2) and Khadas VIM4 support Lucas Tanure
2026-08-06 10:18 ` Lucas Tanure [this message]
2026-08-10 14:01   ` [PATCH 1/4] serial: meson: add Amlogic S4 UART support Ferass El Hafidi
2026-08-06 10:18 ` [PATCH 2/4] arm: meson: add Amlogic T7 SoC family support Lucas Tanure
2026-08-10 14:15   ` Ferass El Hafidi
2026-08-06 10:18 ` [PATCH 3/4] board: amlogic: add Khadas VIM4 support Lucas Tanure
2026-08-10 14:30   ` Ferass El Hafidi
2026-08-06 10:18 ` [PATCH 4/4] doc: board: amlogic: add Khadas VIM4 documentation Lucas Tanure
2026-08-10  8:13 ` [PATCH 0/4] Add Amlogic T7 (A311D2) and Khadas VIM4 support neil.armstrong
2026-08-10 14:12 ` Ferass El Hafidi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260806101809.72526-2-tanure@linux.com \
    --to=tanure@linux.com \
    --cc=funderscore@postmasteros.org \
    --cc=ilias.apalodimas@linaro.org \
    --cc=neil.armstrong@linaro.org \
    --cc=trini@konsulko.com \
    --cc=u-boot-amlogic@groups.io \
    --cc=u-boot@lists.u-boot-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.