From: Duje Mihanović <duje.mihanovic@skole.hr>
Date: Tue, 24 Dec 2024 17:41:46 +0000 (+0100)
Subject: restore upstream ns16550
X-Git-Tag: v2025.01-rc5-pxa1908~22
X-Git-Url: http://git.dujemihanovic.xyz/html/static/gitweb.css?a=commitdiff_plain;h=5bb53cd3a5cb3f7f229b37966fc19ce390a83d38;p=u-boot.git

restore upstream ns16550
---

diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 860b695e31..3f6860f391 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -108,7 +108,9 @@ static inline int serial_in_shift(void *addr, int shift)
 static void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr,
 			       int value)
 {
-	if (plat->reg_width == 4) {
+	if (plat->flags & NS16550_FLAG_IO) {
+		outb(value, addr);
+	} else if (plat->reg_width == 4) {
 		if (plat->flags & NS16550_FLAG_ENDIAN) {
 			if (plat->flags & NS16550_FLAG_BE)
 				out_be32(addr, value);
@@ -126,7 +128,9 @@ static void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr,
 
 static int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr)
 {
-	if (plat->reg_width == 4) {
+	if (plat->flags & NS16550_FLAG_IO) {
+		return inb(addr);
+	} else if (plat->reg_width == 4) {
 		if (plat->flags & NS16550_FLAG_ENDIAN) {
 			if (plat->flags & NS16550_FLAG_BE)
 				return in_be32(addr);
@@ -223,6 +227,49 @@ static void ns16550_setbrg(struct ns16550 *com_port, int baud_divisor)
 
 void ns16550_init(struct ns16550 *com_port, int baud_divisor)
 {
+#if defined(CONFIG_XPL_BUILD) && defined(CONFIG_OMAP34XX)
+	/*
+	 * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode
+	 * before SPL starts only THRE bit is set. We have to empty the
+	 * transmitter before initialization starts.
+	 */
+	if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE))
+	     == UART_LSR_THRE) {
+		if (baud_divisor != -1)
+			ns16550_setbrg(com_port, baud_divisor);
+		else {
+			// Re-use old baud rate divisor to flush transmit reg.
+			const int dll = serial_in(&com_port->dll);
+			const int dlm = serial_in(&com_port->dlm);
+			const int divisor = dll | (dlm << 8);
+			ns16550_setbrg(com_port, divisor);
+		}
+		serial_out(0, &com_port->mdr1);
+	}
+#endif
+
+	while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT))
+		;
+
+	serial_out(CFG_SYS_NS16550_IER, &com_port->ier);
+#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_OMAP_SERIAL)
+	serial_out(0x7, &com_port->mdr1);	/* mode select reset TL16C750*/
+#endif
+
+	serial_out(UART_MCRVAL, &com_port->mcr);
+	serial_out(ns16550_getfcr(com_port), &com_port->fcr);
+	/* initialize serial config to 8N1 before writing baudrate */
+	serial_out(UART_LCRVAL, &com_port->lcr);
+	if (baud_divisor != -1)
+		ns16550_setbrg(com_port, baud_divisor);
+#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_SOC_DA8XX) || \
+	defined(CONFIG_OMAP_SERIAL)
+	/* /16 is proper to hit 115200 with 48MHz */
+	serial_out(0, &com_port->mdr1);
+#endif
+#if defined(CONFIG_ARCH_KEYSTONE)
+	serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC);
+#endif
 }
 
 #if !CONFIG_IS_ENABLED(NS16550_MIN_FUNCTIONS)
@@ -278,21 +325,19 @@ int ns16550_tstc(struct ns16550 *com_port)
 
 static inline void _debug_uart_init(void)
 {
-	//struct ns16550 *com_port = (struct ns16550 *)CONFIG_VAL(DEBUG_UART_BASE);
-	//int baud_divisor;
+	struct ns16550 *com_port = (struct ns16550 *)CONFIG_VAL(DEBUG_UART_BASE);
+	int baud_divisor;
 
 	/* Wait until tx buffer is empty */
-	/*
 	while (!(serial_din(&com_port->lsr) & UART_LSR_TEMT))
 		;
-	*/
+
 	/*
 	 * We copy the code from above because it is already horribly messy.
 	 * Trying to refactor to nicely remove the duplication doesn't seem
 	 * feasible. The better fix is to move all users of this driver to
 	 * driver model.
 	 */
-	/*
 	baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
 					    CONFIG_BAUDRATE);
 	serial_dout(&com_port->ier, CFG_SYS_NS16550_IER);
@@ -303,7 +348,6 @@ static inline void _debug_uart_init(void)
 	serial_dout(&com_port->dll, baud_divisor & 0xff);
 	serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
 	serial_dout(&com_port->lcr, UART_LCRVAL);
-	*/
 }
 
 static inline int NS16550_read_baud_divisor(struct ns16550 *com_port)