summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-01-02 16:44:53 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2012-01-04 11:45:54 +0530
commita212471b7476e819cd6e37c350e9857bbce37e75 (patch)
treecdc649acb807df1d44a854c8582c0885f6c8d862
parentd8eab4e2cccc3a48444f1c6bcba04440c99233ca (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>
-rw-r--r--drivers/tty/serial/tegra_hsuart.c38
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);
}
}