aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorVitaly Chernooky <vitaly.chernooky@ti.com>2012-10-31 16:58:27 +0200
committerZiyann <jaraidaniel@gmail.com>2014-11-26 11:18:20 +0100
commitda82942bbd6a40cf7ddd3edc52352610905137ce (patch)
tree598911eb9a0cfa1a5ecee50f58b6638ace196aa5 /drivers/tty
parent8e55657b47cc5266af30525c58a7fa0a3d6f0160 (diff)
downloadkernel_samsung_tuna-da82942bbd6a40cf7ddd3edc52352610905137ce.zip
kernel_samsung_tuna-da82942bbd6a40cf7ddd3edc52352610905137ce.tar.gz
kernel_samsung_tuna-da82942bbd6a40cf7ddd3edc52352610905137ce.tar.bz2
tty: omap-serial: Disabling DMA on suspend path
In case of bug UART can't suspend with TX DMA enabled. So here is implemented WA: TX DMA is disabled on runtime suspend path and re-enabled on runtime resume path. Change-Id: Iabc726ca93a5e354eb53efdacedf3261d4e02763 Signed-off-by: Vitaly Chernooky <vitaly.chernooky@ti.com>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/omap-serial.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 71b73a3..7de7589 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1825,8 +1825,37 @@ static int omap_serial_runtime_suspend(struct device *dev)
udelay(300);
}
if (up->use_dma) {
+ u32 iscr, ifcr, ilsr;
struct omap_device *od;
+ /* Stop baud clock */
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_out(up, UART_DLL, 0);
+ serial_out(up, UART_DLM, 0);
+
+ /* A DMA disabling sequence for DMA mode 1 set by FCR[3] = 1, SCR[0] = 0 */
+ iscr = serial_in(up, UART_OMAP_SCR) & UART_OMAP_SCR_DMA_MODE_MASK;
+ serial_out(up, UART_OMAP_SCR, iscr | 0x02);
+ serial_out(up, UART_OMAP_SCR, iscr | 0x03);
+ ifcr = up->fcr & ~UART_FCR_DMA_SELECT;
+ serial_out(up, UART_FCR, ifcr);
+ ilsr = serial_in(up, UART_LSR);
+ while ((ilsr & 0x01) == 1) {
+ serial_in(up, UART_RX);
+ ilsr = serial_in(up, UART_LSR);
+ }
+ serial_out(up, UART_FCR, ifcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ iscr = serial_in(up, UART_OMAP_SCR) & UART_OMAP_SCR_DMA_MODE_MASK;
+ serial_out(up, UART_OMAP_SCR, iscr | 0x04);
+ serial_out(up, UART_FCR, ifcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ iscr = serial_in(up, UART_OMAP_SCR) & UART_OMAP_SCR_DMA_MODE_MASK;
+ serial_out(up, UART_OMAP_SCR, iscr);
+
+ /* Restart baud clock */
+ serial_out(up, UART_DLL, up->dll); /* LS of divisor */
+ serial_out(up, UART_DLM, up->dlh); /* MS of divisor */
+ serial_out(up, UART_LCR, up->lcr);
+
/* ENABLE IDLE MODE */
od = to_omap_device(up->pdev);
omap_hwmod_set_slave_idlemode(od->hwmods[0],
@@ -1855,6 +1884,20 @@ static int omap_serial_runtime_resume(struct device *dev)
od = to_omap_device(up->pdev);
omap_hwmod_set_slave_idlemode(od->hwmods[0],
HWMOD_IDLEMODE_NO);
+
+ /* Stop baud clock */
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_out(up, UART_DLL, 0);
+ serial_out(up, UART_DLM, 0);
+
+ /* re-enable DMA */
+ serial_out(up, UART_OMAP_SCR, up->scr);
+ serial_out(up, UART_FCR, up->fcr);
+
+ /* re-start baud clock */
+ serial_out(up, UART_DLL, up->dll); /* LS of divisor */
+ serial_out(up, UART_DLM, up->dlh); /* MS of divisor */
+ serial_out(up, UART_LCR, up->lcr);
}
if (up->rts_mux_driver_control && (!up->rts_pullup_in_suspend))
omap_rts_mux_write(0, up->port.line);