diff options
author | Mitja Spes <mitja@lxnav.com> | 2015-08-27 09:03:06 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2015-11-02 22:16:32 +0100 |
commit | a2d16785572f10d08693b3cb6d45555909fc7b83 (patch) | |
tree | b1ad09e2bfda8fcc624a680c9bf8c2566cf6eda5 /drivers | |
parent | 9351043ca9b70e20b05ae86a4ce70c8d2deadb1c (diff) |
Various Tegra HS UART backports
Various Tegra HS UART backports
Signed-off-by: Mitja Spes <mitja@lxnav.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/serial/tegra_hsuart.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/drivers/tty/serial/tegra_hsuart.c b/drivers/tty/serial/tegra_hsuart.c index 369bdf0dcf89..c2d2499601c9 100644 --- a/drivers/tty/serial/tegra_hsuart.c +++ b/drivers/tty/serial/tegra_hsuart.c @@ -359,9 +359,11 @@ static void tegra_rx_dma_complete_callback(struct tegra_dma_req *req) if (req->status == -TEGRA_DMA_REQ_ERROR_ABORTED) return; - spin_unlock(&u->lock); - tty_flip_buffer_push(u->state->port.tty); - spin_lock(&u->lock); + if (tty) { + spin_unlock(&u->lock); + tty_flip_buffer_push(tty); + spin_lock(&u->lock); + } } /* Lock already taken */ @@ -379,6 +381,22 @@ static void do_handle_rx_dma(struct tegra_uart_port *t) tty_flip_buffer_push(u->state->port.tty); } +/** + * tegra_uart_wait_cycle_time: Wait for N UART clock periods + * + * @tup: Tegra serial port data structure. + * @cycles: Number of clock periods to wait. + * + * Tegra UARTs are clocked at 16X the baud/bit rate and hence the UART + * clock speed is 16X the current baud rate. + */ +static void tegra_uart_wait_cycle_time(struct tegra_uart_port *tup, + unsigned int cycles) +{ + if (tup->baud) + udelay(DIV_ROUND_UP(cycles * 1000000, tup->baud * 16)); +} + /* Wait for a symbol-time. */ static void wait_sym_time(struct tegra_uart_port *t, unsigned int syms) { @@ -432,7 +450,13 @@ static void tegra_fifo_reset(struct tegra_uart_port *t, u8 fcr_bits) uart_writeb(t, fcr, UART_FCR); #endif uart_readb(t, UART_SCR); /* Dummy read to ensure the write is posted */ - wait_sym_time(t, 1); /* Wait for the flush to propagate. */ + //wait_sym_time(t, 1); /* Wait for the flush to propagate. */ + /* + * For all tegra devices (up to t210), there is a hardware issue that + * requires software to wait for 32 UART clock periods for the flush + * to propagate, otherwise data could be lost. + */ + tegra_uart_wait_cycle_time(t, 32); } static char do_decode_rx_error(struct tegra_uart_port *t, u8 lsr) @@ -811,13 +835,21 @@ static int tegra_uart_hw_init(struct tegra_uart_port *t) t->fcr_shadow |= UART_FCR_R_TRIG_01; t->fcr_shadow |= TEGRA_UART_TX_TRIG_8B; uart_writeb(t, t->fcr_shadow, UART_FCR); + uart_readb(t, UART_SCR); /* Dummy read to ensure the write is posted */ + + /* + * For all tegra devices (up to t210), there is a hardware issue that + * requires software to wait for 3 UART clock periods after enabling + * the TX fifo, otherwise data could be lost. + */ + tegra_uart_wait_cycle_time(t, 3); if (t->use_rx_dma) { /* * Initialize the UART for a simple default configuration * so that the receive DMA buffer may be enqueued */ - t->lcr_shadow = 3; /* no parity, stop, 8 data bits */ - tegra_set_baudrate(t, 9600); + t->lcr_shadow = UART_LCR_WLEN8; /* no parity, stop, 8 data bits */ + tegra_set_baudrate(t, 115200); t->fcr_shadow |= UART_FCR_DMA_SELECT; uart_writeb(t, t->fcr_shadow, UART_FCR); if (tegra_start_dma_rx(t)) { @@ -825,6 +857,8 @@ static int tegra_uart_hw_init(struct tegra_uart_port *t) tegra_uart_free_rx_dma(t); t->fcr_shadow &= ~UART_FCR_DMA_SELECT; uart_writeb(t, t->fcr_shadow, UART_FCR); + } else { + dev_info(t->uport.dev, "Rx DMA enabled\n"); } } else { uart_writeb(t, t->fcr_shadow, UART_FCR); @@ -1413,6 +1447,7 @@ static void tegra_set_termios(struct uart_port *u, struct ktermios *termios, t->mcr_shadow = mcr; uart_writeb(t, mcr, UART_MCR); t->use_cts_control = false; + t->rts_active=false; } /* update the port timeout based on new settings */ |