Message ID | 20230321114753.75038-4-biju.das.jz@bp.renesas.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Geert Uytterhoeven |
Headers | show |
Series | Renesas SCI fixes | expand |
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.jz@bp.renesas.com/T/#u [2] https://lore.kernel.org/linux-renesas-soc/20230331113346.170602-4-biju.das.jz@bp.renesas.com/T/#md8ae156345aed10bdeba764dcf2253f00b02e38c [3] https://lore.kernel.org/linux-renesas-soc/20230331113346.170602-4-biju.das.jz@bp.renesas.com/T/#me7f60560fbf24bf361d70ccb6ba223e92a60de9b 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
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)) {
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(-)