]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
restore upstream ns16550
authorDuje Mihanović <duje.mihanovic@skole.hr>
Tue, 24 Dec 2024 17:41:46 +0000 (18:41 +0100)
committerDuje Mihanović <duje.mihanovic@skole.hr>
Wed, 25 Dec 2024 14:00:05 +0000 (15:00 +0100)
drivers/serial/ns16550.c

index 860b695e3127c05d2843e4f71f5939ce5bfc8b7d..3f6860f39162df74c3d1f03d3f9aa90090216646 100644 (file)
@@ -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)