[PATCH] OMAP3: Serial: Improved sleep logic

Tero Kristo
2010-02-02T09:41:09Z

From: Tero Kristo <tero.kristo@nokia.com>

Only RX interrupt will now kick the sleep prevent timer. In addition, TX
fifo status is checked before disabling clocks, this will prevent occasional
garbage being printed on serial line. Smartidle is also disabled while
entering idle if we have data in the transmit buffer, because having this
enabled will prevent wakeups from the TX interrupt, and this causes
pauses while sending large blocks of data.

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
---
arch/arm/mach-omap2/serial.c | 19 +++++++++++++++----
1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 777e802..e11dfe9 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -317,7 +317,8 @@ static void omap_uart_allow_sleep(struct omap_uart_state *uart)
if (!uart->clocked)
return;

- omap_uart_smart_idle_enable(uart, 1);
+ if (serial_read_reg(uart->p, UART_LSR) & UART_LSR_TEMT)
+ omap_uart_smart_idle_enable(uart, 1);
uart->can_sleep = 1;
del_timer(&uart->timer);
}
@@ -335,7 +336,11 @@ void omap_uart_prepare_idle(int num)

list_for_each_entry(uart, &uart_list, node) {
if (num == uart->num && uart->can_sleep) {
- omap_uart_disable_clocks(uart);
+ if (serial_read_reg(uart->p, UART_LSR) &
+ UART_LSR_TEMT)
+ omap_uart_disable_clocks(uart);
+ else
+ omap_uart_smart_idle_enable(uart, 0);
return;
}
}
@@ -407,8 +412,14 @@ int omap_uart_can_sleep(void)
static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
{
struct omap_uart_state *uart = dev_id;
+ u8 lsr;

- omap_uart_block_sleep(uart);
+ lsr = serial_read_reg(uart->p, UART_LSR);
+ /* Check for receive interrupt */
+ if (lsr & UART_LSR_DR)
+ omap_uart_block_sleep(uart);
+ if (lsr & UART_LSR_TEMT && uart->can_sleep)
+ omap_uart_smart_idle_enable(uart, 1);

return IRQ_NONE;
}
--
1.5.4.3