Hi Alexander, On 06/07/2016 08:59 AM, Alexander Shiyan wrote: > The patch adds a barrier between two sequential read/write cycles > to provide the required minimum High-CS time. Which is how long? 100ns? The commit log should include this information. > 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 } > }; I'm wondering if this delay should be implemented in the i/o accessors instead. Otherwise, the delay may be skipped; eg., sccnxp_start_tx(), sccnxp_handle_rx(), sccnxp_handle_events(), ... > +static inline void sccnxp_barrier(void) > +{ > + /* Barrier between read and/or write cycles */ > + cpu_relax(); ndelay(100 /* ns */); > +} > + > 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); Note 7 on pg 19 of the 2698 datasheet [1] says: "Consecutive write operations to the command register require at least three edges of the X1 clock between writes" By my math, that should be 360ns. Agree? Regards, Peter Hurley [1] http://www.nxp.com/documents/data_sheet/SCC2698B.pdf > + 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; > } > -- 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