The patch adds a barrier between two sequential read/write cycles to provide the required minimum High-CS time. Signed-off-by: Alexander Shiyan <shc_work@xxxxxxx> --- drivers/tty/serial/sccnxp.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index fcf803f..b3c060d 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -281,6 +281,12 @@ static const struct { { 0, 0, 0, 0 } }; +static inline void sccnxp_barrier(void) +{ + /* Barrier between read and/or write cycles */ + cpu_relax(); +} + static int sccnxp_set_baud(struct uart_port *port, int baud) { struct sccnxp_port *s = dev_get_drvdata(port->dev); @@ -307,10 +313,13 @@ static int sccnxp_set_baud(struct uart_port *port, int baud) mr0 |= MR0_FIFO | MR0_TXLVL; /* Update MR0 */ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR0); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_MR_REG, mr0); + sccnxp_barrier(); } sccnxp_port_write(port, SCCNXP_ACR_REG, acr | ACR_TIMER_MODE); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_CSR_REG, (csr << 4) | csr); if (baud != bestbaud) @@ -620,8 +629,11 @@ static void sccnxp_set_termios(struct uart_port *port, /* Disable RX & TX, reset break condition, status and FIFOs */ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET | CR_RX_DISABLE | CR_TX_DISABLE); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET); /* Word size */ @@ -653,7 +665,9 @@ static void sccnxp_set_termios(struct uart_port *port, /* Update desired format */ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR1); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_MR_REG, mr1); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_MR_REG, mr2); /* Set read status mask */ @@ -705,9 +719,13 @@ static int sccnxp_startup(struct uart_port *port) /* Reset break condition, status and FIFOs */ sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET); + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET); + sccnxp_barrier(); /* Enable RX & TX */ sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE); @@ -803,6 +821,7 @@ static void sccnxp_console_putchar(struct uart_port *port, int c) while (tryes--) { if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXRDY) { + sccnxp_barrier(); sccnxp_port_write(port, SCCNXP_THR_REG, c); break; } -- 2.4.9 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html