[Concept,1/8] serial: ns16550: Add skip-init devicetree property

Message ID 20251019072313.3235339-2-sjg@u-boot.org
State New
Headers
Series tkey: Provide basic support for Tillitis TKey |

Commit Message

Simon Glass Oct. 19, 2025, 7:23 a.m. UTC
  From: Simon Glass <sjg@chromium.org>

Add support for a 'skip-init' property in the device tree that preserves
UART settings from a previous boot phase.

This is useful when the UART is already configured by firmware (e.g.,
EFI firmware on x86 platforms) and changing the settings would disrupt
console output or cause communication issues.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/serial/ns16550.c | 12 +++++++++++-
 include/ns16550.h        |  2 ++
 2 files changed, 13 insertions(+), 1 deletion(-)
  

Patch

diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 5126cf8bc1a..1f0d1c894cb 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -426,6 +426,9 @@  static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
 	struct ns16550_plat *plat = com_port->plat;
 	int clock_divisor;
 
+	if (plat->skip_init)
+		return 0;
+
 	clock_divisor = ns16550_calc_divisor(com_port, plat->clock, baudrate);
 
 	ns16550_setbrg(com_port, clock_divisor);
@@ -436,11 +439,15 @@  static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
 static int ns16550_serial_setconfig(struct udevice *dev, uint serial_config)
 {
 	struct ns16550 *const com_port = dev_get_priv(dev);
+	struct ns16550_plat *plat = com_port->plat;
 	int lcr_val = UART_LCR_WLS_8;
 	uint parity = SERIAL_GET_PARITY(serial_config);
 	uint bits = SERIAL_GET_BITS(serial_config);
 	uint stop = SERIAL_GET_STOP(serial_config);
 
+	if (plat->skip_init)
+		return 0;
+
 	/*
 	 * only parity config is implemented, check if other serial settings
 	 * are the default one.
@@ -533,7 +540,8 @@  int ns16550_serial_probe(struct udevice *dev)
 		reset_deassert_bulk(&reset_bulk);
 
 	com_port->plat = dev_get_plat(dev);
-	ns16550_init(com_port, -1);
+	if (!plat->skip_init)
+		ns16550_init(com_port, -1);
 
 	return 0;
 }
@@ -589,6 +597,8 @@  int ns16550_serial_of_to_plat(struct udevice *dev)
 	if (port_type == PORT_JZ4780)
 		plat->fcr |= UART_FCR_UME;
 
+	plat->skip_init = dev_read_bool(dev, "skip-init");
+
 	return 0;
 }
 #endif
diff --git a/include/ns16550.h b/include/ns16550.h
index 7f481300083..787680853c7 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -66,6 +66,7 @@  enum ns16550_flags {
  * @fcr:		Offset of FCR register (normally UART_FCR_DEFVAL)
  * @flags:		A few flags (enum ns16550_flags)
  * @bdf:		PCI slot/function (pci_dev_t)
+ * @skip_init:		Skip UART initialization (preserve existing settings)
  */
 struct ns16550_plat {
 	ulong base;
@@ -79,6 +80,7 @@  struct ns16550_plat {
 #if defined(CONFIG_PCI) && defined(CONFIG_SPL)
 	int bdf;
 #endif
+	bool skip_init;
 };
 
 struct udevice;