From: Samuel Holland <[email protected]>

Some platforms need the UART clock gates enabled before NS16550
register access. This is required by the downstream Allwinner D1
port used on the MangoPi MQ Pro.

Add CONFIG_NS16550_CLK_ENABLE to enable the UART clocks during
probe when explicitly selected by a platform. The option defaults
to disabled, preserving the existing behavior on other platforms.

The clock-enabling code originates from Samuel Holland's D1 work.
This patch makes that behavior optional through Kconfig.

Link: 
https://github.com/smaeul/u-boot/commit/0617377a2555031f02a459b3451fa33ce53e9b74
Signed-off-by: Samuel Holland <[email protected]>
Co-developed-by: khaliforce <[email protected]>
Signed-off-by: khaliforce <[email protected]>
---
Tested on a MangoPi MQ Pro with the downstream D1 port based on
U-Boot v2026.10:

- With the option enabled, cold boot and warm reboot succeeded
  through SPL, OpenSBI, U-Boot, GRUB and Linux.
- Removing only this patch, without adding diagnostic code,
  resulted in no UART output at all, not even a single character,
  and the board did not become reachable over SSH.

The standalone patch also builds on current upstream main for
RISC-V64, ARM64 and ARM32. An additional RISC-V64 build with CLK and
NS16550_CLK_ENABLE enabled passed.

With the option disabled, the tested ARM64 and ARM32 NS16550
.text sections were unchanged. Checkpatch reports no errors or
warnings.

 drivers/serial/Kconfig   | 7 +++++++
 drivers/serial/ns16550.c | 9 +++++++++
 2 files changed, 16 insertions(+)

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ffc58d663ff..4c5400a3816 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -821,6 +821,13 @@ config SYS_NS16550
          be used. It can be a constant or a function to get clock, eg,
          get_serial_clock().
 
+config NS16550_CLK_ENABLE
+       bool "Enable NS16550 clocks during probe"
+       depends on SYS_NS16550 && DM_SERIAL && CLK
+       help
+         Enable all UART clocks before register access.
+         Select this when firmware does not enable the UART clock gates.
+
 config NS16550_DYNAMIC
        bool "Allow NS16550 to be configured at runtime"
        depends on SYS_NS16550
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 10271f46aa6..217a7cf7238 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -516,6 +516,15 @@ int ns16550_serial_probe(struct udevice *dev)
        if (!ret)
                reset_deassert_bulk(&reset_bulk);
 
+       if (IS_ENABLED(CONFIG_NS16550_CLK_ENABLE) &&
+           CONFIG_IS_ENABLED(CLK)) {
+               struct clk_bulk clk_bulk;
+
+               ret = clk_get_bulk(dev, &clk_bulk);
+               if (!ret)
+                       clk_enable_bulk(&clk_bulk);
+       }
+
        com_port->plat = dev_get_plat(dev);
        ns16550_init(com_port, -1);
 

Reply via email to