For SCI, the TE (transmit enable) must be set after setting TIE (transmit interrupt enable) or in the same instruction to start the transmission. Set TE bit in sci_start_tx() instead of set_termios() for SCI and clear TE bit, if circular buffer is empty in sci_transmit_chars().
Fixes: 93bcefd4c6ba ("serial: sh-sci: Fix setting SCSCR_TIE while transferring data") Cc: stable@vger.kernel.org Signed-off-by: Biju Das biju.das.jz@bp.renesas.com --- v3->v4: * Updated fixes tag. v3: * New patch --- drivers/tty/serial/sh-sci.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 15954ca3e9dc..bcc4152ce043 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -596,6 +596,15 @@ static void sci_start_tx(struct uart_port *port) if (!s->chan_tx || 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); } } @@ -834,6 +843,12 @@ static void sci_transmit_chars(struct uart_port *port) c = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); } else { + if (port->type == PORT_SCI) { + ctrl = serial_port_in(port, SCSCR); + ctrl &= ~SCSCR_TE; + serial_port_out(port, SCSCR, ctrl); + return; + } break; }
@@ -2580,8 +2595,14 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, 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)) {
Hi All,
I split this patch into 2([1] & [2]) after fixing commit message and merged with the series[3] to avoid any dependencies.
[1] https://lore.kernel.org/linux-renesas-soc/20230331113346.170602-4-biju.das.j... [2] https://lore.kernel.org/linux-renesas-soc/20230331113346.170602-4-biju.das.j...
[3] https://lore.kernel.org/linux-renesas-soc/20230331113346.170602-4-biju.das.j...
Cheers, Biju
Subject: [PATCH v4 3/5] tty: serial: sh-sci: Fix Tx on SCI IP
For SCI, the TE (transmit enable) must be set after setting TIE (transmit interrupt enable) or in the same instruction to start the transmission. Set TE bit in sci_start_tx() instead of set_termios() for SCI and clear TE bit, if circular buffer is empty in sci_transmit_chars().
Fixes: 93bcefd4c6ba ("serial: sh-sci: Fix setting SCSCR_TIE while transferring data") Cc: stable@vger.kernel.org Signed-off-by: Biju Das biju.das.jz@bp.renesas.com
v3->v4:
- Updated fixes tag.
v3:
- New patch
drivers/tty/serial/sh-sci.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 15954ca3e9dc..bcc4152ce043 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -596,6 +596,15 @@ static void sci_start_tx(struct uart_port *port) if (!s->chan_tx || 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); }
} @@ -834,6 +843,12 @@ static void sci_transmit_chars(struct uart_port *port) c = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); } else {
if (port->type == PORT_SCI) {
ctrl = serial_port_in(port, SCSCR);
ctrl &= ~SCSCR_TE;
serial_port_out(port, SCSCR, ctrl);
return;
}} break;
@@ -2580,8 +2595,14 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, 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)) {
-- 2.25.1
linux-stable-mirror@lists.linaro.org