diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-01-02 16:44:53 +0530 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2012-01-04 11:45:54 +0530 |
commit | a212471b7476e819cd6e37c350e9857bbce37e75 (patch) | |
tree | cdc649acb807df1d44a854c8582c0885f6c8d862 /drivers | |
parent | d8eab4e2cccc3a48444f1c6bcba04440c99233ca (diff) |
serial: tegra: Wait for tx fifo to be empty on close
Wait tx fifo to be empty on close for the time it is require
to make fifo empty.
bug 921225
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Change-Id: I0ea2ec488e975833103218d86e8dc37aec79ef88
Reviewed-on: http://git-master/r/72858
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Tested-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/serial/tegra_hsuart.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/drivers/tty/serial/tegra_hsuart.c b/drivers/tty/serial/tegra_hsuart.c index ff30a26d53e2..f94dc24b5229 100644 --- a/drivers/tty/serial/tegra_hsuart.c +++ b/drivers/tty/serial/tegra_hsuart.c @@ -90,8 +90,6 @@ const int dma_req_sel[] = { #define TEGRA_UART_TX_TRIG_4B 0x20 #define TEGRA_UART_TX_TRIG_1B 0x30 -#define TX_EMPTY_TIMEOUT_CNT 10000 - struct tegra_uart_port { struct uart_port uport; char port_name[32]; @@ -631,16 +629,40 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *t) { unsigned long flags; int retry = 0; + unsigned long char_time = DIV_ROUND_UP(10000000, t->baud); + unsigned long fifo_empty_time = t->uport.fifosize * char_time; + unsigned long wait_time; + unsigned char lsr; + unsigned char msr; + unsigned char mcr; /* Disable interrupts */ uart_writeb(t, 0, UART_IER); - while ((uart_readb(t, UART_LSR) & UART_LSR_TEMT) != UART_LSR_TEMT) { - udelay(200); - if (retry++ > TX_EMPTY_TIMEOUT_CNT) { - dev_err(t->uport.dev, "%s: Tx Empty timeout! (%d)\n", - __func__, TX_EMPTY_TIMEOUT_CNT); - break; + lsr = uart_readb(t, UART_LSR); + if ((lsr & UART_LSR_TEMT) != UART_LSR_TEMT) { + msr = uart_readb(t, UART_MSR); + mcr = uart_readb(t, UART_MCR); + if ((mcr & UART_MCR_CTS_EN) && (msr & UART_MSR_CTS)) + dev_err(t->uport.dev, "%s: Tx fifo not empty and " + "slave disabled CTS, Waiting for slave to" + " be ready\n", __func__); + + /* Wait for Tx fifo to be empty */ + while ((lsr & UART_LSR_TEMT) != UART_LSR_TEMT) { + wait_time = min(fifo_empty_time, 100); + udelay(wait_time); + fifo_empty_time -= wait_time; + if (!fifo_empty_time) { + msr = uart_readb(t, UART_MSR); + mcr = uart_readb(t, UART_MCR); + if ((mcr & UART_MCR_CTS_EN) && + (msr & UART_MSR_CTS)) + dev_err(t->uport.dev, "%s: Slave is " + "still not ready!\n", __func__); + break; + } + lsr = uart_readb(t, UART_LSR); } } |