diff options
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 43 | ||||
-rw-r--r-- | include/linux/serial_reg.h | 2 |
2 files changed, 45 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); diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index c75bda3..e8046c7 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h @@ -362,5 +362,7 @@ #define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */ #define UART_OMAP_MDR1_DISABLE 0x07 /* Disable (default state) */ +#define UART_OMAP_SCR_DMA_MODE_MASK 0xF9 + #endif /* _LINUX_SERIAL_REG_H */ |