tty: serial: sh-sci: Fix TE setting on SCI IP
authorBiju Das <biju.das.jz@bp.renesas.com>
Wed, 12 Apr 2023 14:50:51 +0000 (15:50 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Apr 2023 11:47:33 +0000 (13:47 +0200)
As per the RZ/G2L users hardware manual (Rev.1.20 Sep, 2022), section
23.3.7 Serial Data Transmission (Asynchronous Mode) it is mentioned
that the TE (transmit enable) must be set after setting TIE (transmit
interrupt enable) or these 2 bits are set to 1 simultaneously by a
single instruction. So set these 2 bits in single instruction.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20230412145053.114847-4-biju.das.jz@bp.renesas.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sh-sci.c

index 15743c2..32f5c1f 100644 (file)
@@ -601,6 +601,15 @@ static void sci_start_tx(struct uart_port *port)
            port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
                ctrl = serial_port_in(port, SCSCR);
+
+               /*
+                * For SCI, TE (transmit enable) must be set after setting TIE
+                * (transmit interrupt enable) or in the same instruction to start
+                * the transmit process.
+                */
+               if (port->type == PORT_SCI)
+                       ctrl |= SCSCR_TE;
+
                serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
        }
 }
@@ -2600,8 +2609,14 @@ done:
                sci_set_mctrl(port, port->mctrl);
        }
 
-       scr_val |= SCSCR_RE | SCSCR_TE |
-                  (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
+       /*
+        * For SCI, TE (transmit enable) must be set after setting TIE
+        * (transmit interrupt enable) or in the same instruction to
+        * start the transmitting process. So skip setting TE here for SCI.
+        */
+       if (port->type != PORT_SCI)
+               scr_val |= SCSCR_TE;
+       scr_val |= SCSCR_RE | (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
        serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
        if ((srr + 1 == 5) &&
            (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) {