serial: sh-sci: Fix (AUTO)RTS in sci_init_pins()
If a UART has dedicated RTS/CTS pins, and hardware control flow is disabled (or AUTORTS is not yet effective), changing any serial port configuration deasserts RTS, as .set_termios() calls sci_init_pins(). To fix this, consider the current (AUTO)RTS state when (re)initializing the pins. Note that for SCIFA/SCIFB, AUTORTS needs explicit configuration of the RTS# pin function, while (H)SCIF handles this automatically. Fixes:d2b9775d79
("serial: sh-sci: Correct pin initialization on (H)SCIF") Fixes:e9d7a45a03
("serial: sh-sci: Add pin initialization for SCIFA/SCIFB") Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
5f76895e4c
Коммит
cfa6eb2391
|
@ -683,24 +683,37 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||||
|
u16 data = serial_port_in(port, SCPDR);
|
||||||
u16 ctrl = serial_port_in(port, SCPCR);
|
u16 ctrl = serial_port_in(port, SCPCR);
|
||||||
|
|
||||||
/* Enable RXD and TXD pin functions */
|
/* Enable RXD and TXD pin functions */
|
||||||
ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
|
ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
|
||||||
if (to_sci_port(port)->has_rtscts) {
|
if (to_sci_port(port)->has_rtscts) {
|
||||||
/* RTS# is output, driven 1 */
|
/* RTS# is output, active low, unless autorts */
|
||||||
ctrl |= SCPCR_RTSC;
|
if (!(port->mctrl & TIOCM_RTS)) {
|
||||||
serial_port_out(port, SCPDR,
|
ctrl |= SCPCR_RTSC;
|
||||||
serial_port_in(port, SCPDR) | SCPDR_RTSD);
|
data |= SCPDR_RTSD;
|
||||||
|
} else if (!s->autorts) {
|
||||||
|
ctrl |= SCPCR_RTSC;
|
||||||
|
data &= ~SCPDR_RTSD;
|
||||||
|
} else {
|
||||||
|
/* Enable RTS# pin function */
|
||||||
|
ctrl &= ~SCPCR_RTSC;
|
||||||
|
}
|
||||||
/* Enable CTS# pin function */
|
/* Enable CTS# pin function */
|
||||||
ctrl &= ~SCPCR_CTSC;
|
ctrl &= ~SCPCR_CTSC;
|
||||||
}
|
}
|
||||||
|
serial_port_out(port, SCPDR, data);
|
||||||
serial_port_out(port, SCPCR, ctrl);
|
serial_port_out(port, SCPCR, ctrl);
|
||||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||||
u16 status = serial_port_in(port, SCSPTR);
|
u16 status = serial_port_in(port, SCSPTR);
|
||||||
|
|
||||||
/* RTS# is output, driven 1 */
|
/* RTS# is always output; and active low, unless autorts */
|
||||||
status |= SCSPTR_RTSIO | SCSPTR_RTSDT;
|
status |= SCSPTR_RTSIO;
|
||||||
|
if (!(port->mctrl & TIOCM_RTS))
|
||||||
|
status |= SCSPTR_RTSDT;
|
||||||
|
else if (!s->autorts)
|
||||||
|
status &= ~SCSPTR_RTSDT;
|
||||||
/* CTS# and SCK are inputs */
|
/* CTS# and SCK are inputs */
|
||||||
status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
|
status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
|
||||||
serial_port_out(port, SCSPTR, status);
|
serial_port_out(port, SCSPTR, status);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче