serial: 8250: reset uart when set baud rate

If external device sends data continuously, then uart is
always busy, and baud rate can't be set. It is useful
to reset uart and set loop back mode to make sure it is
idle.

Change-Id: I87286711870ff685ea29e36e61c97d45be5a6d08
Signed-off-by: Huibin Hong <huibin.hong@rock-chips.com>
This commit is contained in:
Huibin Hong
2018-06-26 15:07:05 +08:00
committed by Steven Liu
parent 81c6726b7d
commit cb6de0208d

View File

@@ -2603,6 +2603,10 @@ void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
{
struct uart_8250_port *up = up_to_u8250p(port);
#ifdef CONFIG_ARCH_ROCKCHIP
serial_port_out(port, UART_MCR, UART_MCR_LOOP);
#endif
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
if (is_omap1510_8250(up)) {
if (baud == 115200) {
@@ -2622,6 +2626,13 @@ void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
serial_dl_write(up, quot);
#ifdef CONFIG_ARCH_ROCKCHIP
serial_port_out(port, UART_MCR, up->mcr);
if (quot != serial_dl_read(up))
pr_warn_ratelimited("ttyS%d set divisor fail, quot:%d != dll,dlh:%d\n",
serial_index(port), quot, serial_dl_read(up));
#endif
}
EXPORT_SYMBOL_GPL(serial8250_do_set_divisor);
@@ -2775,6 +2786,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if ((termios->c_cflag & CREAD) == 0)
port->ignore_status_mask |= UART_LSR_DR;
#ifndef CONFIG_ARCH_ROCKCHIP
/*
* CTS flow control flag and modem status interrupts
*/
@@ -2788,6 +2800,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
up->ier |= UART_IER_RTOIE;
serial_port_out(port, UART_IER, up->ier);
#endif
if (up->capabilities & UART_CAP_EFR) {
unsigned char efr = 0;
@@ -2806,7 +2819,13 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
serial_port_out(port, UART_EFR, efr);
}
#ifdef CONFIG_ARCH_ROCKCHIP
/* Reset uart to make sure it is idle, then set baud rate */
serial_port_out(port, 0x88 >> 2, 0x7);
#endif
serial8250_set_divisor(port, baud, quot, frac);
#ifdef CONFIG_ARCH_ROCKCHIP
up->fcr = UART_FCR_ENABLE_FIFO | UART_FCR_T_TRIG_10 | UART_FCR_R_TRIG_10;
#endif
@@ -2825,6 +2844,23 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
}
serial8250_set_mctrl(port, port->mctrl);
#ifdef CONFIG_ARCH_ROCKCHIP
/*
* CTS flow control flag and modem status interrupts
*/
up->ier &= ~UART_IER_MSI;
if (!(up->bugs & UART_BUG_NOMSR) &&
UART_ENABLE_MS(&up->port, termios->c_cflag))
up->ier |= UART_IER_MSI;
if (up->capabilities & UART_CAP_UUE)
up->ier |= UART_IER_UUE;
if (up->capabilities & UART_CAP_RTOIE)
up->ier |= UART_IER_RTOIE;
serial_port_out(port, UART_IER, up->ier);
#endif
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);