aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2012-01-25 21:50:52 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-09 13:48:34 -0500
commitbe4b0281956c5cae4f63f31f11d07625a6988766 (patch)
treec75f6d88a142889eec90c5ae2e023b31fb3445df /arch
parent0ba5f66836c9253c67c469fb4016f94ea30ff2ce (diff)
tty: serial: OMAP: block idle while the UART is transferring data in PIO mode
Prevent OMAP UARTs from going idle while they are still transferring data in PIO mode. This works around an oversight in the OMAP UART hardware present in OMAP34xx and earlier: an idle UART won't send a wakeup when the TX FIFO threshold is reached. This causes long delays during data transmission when the MPU powerdomain enters a low-power mode. The MPU interrupt controller is not able to respond to interrupts when it's in a low-power state, so the TX buffer is not refilled until another wakeup event occurs. This fix changes the erratum i291 DMA idle workaround. Rather than toggling between force-idle and no-idle, it will toggle between smart-idle and no-idle. The important part of the workaround is the no-idle part, so this shouldn't result in any change in behavior. This fix should work on all OMAP UARTs. Future patches intended for the 3.4 merge window will make this workaround conditional on a "feature" flag, and will use the OMAP36xx+ TX event wakeup support. Thanks to Kevin Hilman <khilman@ti.com> for mentioning the erratum i291 workaround, which led to the development of this approach. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Alan Cox <alan@linux.intel.com> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com> Acked-by: Govindraj.R <govindraj.raja@ti.com> Reviewed-by: Kevin Hilman <khilman@ti.com> Tested-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/serial.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 247d89478f24..f590afc1f673 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -107,18 +107,18 @@ static void omap_uart_set_noidle(struct platform_device *pdev)
107 omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO); 107 omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
108} 108}
109 109
110static void omap_uart_set_forceidle(struct platform_device *pdev) 110static void omap_uart_set_smartidle(struct platform_device *pdev)
111{ 111{
112 struct omap_device *od = to_omap_device(pdev); 112 struct omap_device *od = to_omap_device(pdev);
113 113
114 omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE); 114 omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
115} 115}
116 116
117#else 117#else
118static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) 118static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
119{} 119{}
120static void omap_uart_set_noidle(struct platform_device *pdev) {} 120static void omap_uart_set_noidle(struct platform_device *pdev) {}
121static void omap_uart_set_forceidle(struct platform_device *pdev) {} 121static void omap_uart_set_smartidle(struct platform_device *pdev) {}
122#endif /* CONFIG_PM */ 122#endif /* CONFIG_PM */
123 123
124#ifdef CONFIG_OMAP_MUX 124#ifdef CONFIG_OMAP_MUX
@@ -349,7 +349,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
349 omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; 349 omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
350 omap_up.flags = UPF_BOOT_AUTOCONF; 350 omap_up.flags = UPF_BOOT_AUTOCONF;
351 omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count; 351 omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
352 omap_up.set_forceidle = omap_uart_set_forceidle; 352 omap_up.set_forceidle = omap_uart_set_smartidle;
353 omap_up.set_noidle = omap_uart_set_noidle; 353 omap_up.set_noidle = omap_uart_set_noidle;
354 omap_up.enable_wakeup = omap_uart_enable_wakeup; 354 omap_up.enable_wakeup = omap_uart_enable_wakeup;
355 omap_up.dma_rx_buf_size = info->dma_rx_buf_size; 355 omap_up.dma_rx_buf_size = info->dma_rx_buf_size;