Skip to content

Commit c877ff7

Browse files
Huibin Hongrkhuangtao
authored andcommitted
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>
1 parent 79096fa commit c877ff7

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

drivers/tty/serial/8250/8250_port.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,6 +2207,10 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
22072207
{
22082208
struct uart_8250_port *up = up_to_u8250p(port);
22092209

2210+
#ifdef CONFIG_ARCH_ROCKCHIP
2211+
serial_port_out(port, UART_MCR, UART_MCR_LOOP);
2212+
#endif
2213+
22102214
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
22112215
if (is_omap1510_8250(up)) {
22122216
if (baud == 115200) {
@@ -2227,6 +2231,13 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
22272231

22282232
serial_dl_write(up, quot);
22292233

2234+
#ifdef CONFIG_ARCH_ROCKCHIP
2235+
serial_port_out(port, UART_MCR, up->mcr);
2236+
if (quot != serial_dl_read(up))
2237+
pr_warn_ratelimited("ttyS%d set divisor fail, quot:%d != dll,dlh:%d\n",
2238+
serial_index(port), quot, serial_dl_read(up));
2239+
#endif
2240+
22302241
/* XR17V35x UARTs have an extra fractional divisor register (DLD) */
22312242
if (up->port.type == PORT_XR17V35X) {
22322243
/* Preserve bits not related to baudrate; DLD[7:4]. */
@@ -2330,6 +2341,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
23302341
if ((termios->c_cflag & CREAD) == 0)
23312342
port->ignore_status_mask |= UART_LSR_DR;
23322343

2344+
#ifndef CONFIG_ARCH_ROCKCHIP
23332345
/*
23342346
* CTS flow control flag and modem status interrupts
23352347
*/
@@ -2343,6 +2355,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
23432355
up->ier |= UART_IER_RTOIE;
23442356

23452357
serial_port_out(port, UART_IER, up->ier);
2358+
#endif
23462359

23472360
if (up->capabilities & UART_CAP_EFR) {
23482361
unsigned char efr = 0;
@@ -2361,7 +2374,13 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
23612374
serial_port_out(port, UART_EFR, efr);
23622375
}
23632376

2377+
#ifdef CONFIG_ARCH_ROCKCHIP
2378+
/* Reset uart to make sure it is idle, then set buad rate */
2379+
serial_port_out(port, 0x88 >> 2, 0x7);
2380+
#endif
2381+
23642382
serial8250_set_divisor(port, baud, quot, frac);
2383+
23652384
#ifdef CONFIG_ARCH_ROCKCHIP
23662385
up->fcr = UART_FCR_ENABLE_FIFO | UART_FCR_T_TRIG_10 | UART_FCR_R_TRIG_10;
23672386
#endif
@@ -2380,6 +2399,23 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
23802399
serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
23812400
}
23822401
serial8250_set_mctrl(port, port->mctrl);
2402+
2403+
#ifdef CONFIG_ARCH_ROCKCHIP
2404+
/*
2405+
* CTS flow control flag and modem status interrupts
2406+
*/
2407+
up->ier &= ~UART_IER_MSI;
2408+
if (!(up->bugs & UART_BUG_NOMSR) &&
2409+
UART_ENABLE_MS(&up->port, termios->c_cflag))
2410+
up->ier |= UART_IER_MSI;
2411+
if (up->capabilities & UART_CAP_UUE)
2412+
up->ier |= UART_IER_UUE;
2413+
if (up->capabilities & UART_CAP_RTOIE)
2414+
up->ier |= UART_IER_RTOIE;
2415+
2416+
serial_port_out(port, UART_IER, up->ier);
2417+
#endif
2418+
23832419
spin_unlock_irqrestore(&port->lock, flags);
23842420
serial8250_rpm_put(up);
23852421

0 commit comments

Comments
 (0)