#include <linux/pm_runtime.h>
 #include <linux/console.h>
 #include <linux/pm_qos.h>
+#include <linux/dma-mapping.h>
 
 #include "8250.h"
 
 
 #define UART_ERRATA_i202_MDR1_ACCESS   (1 << 0)
 #define OMAP_UART_WER_HAS_TX_WAKEUP    (1 << 1)
+#define OMAP_DMA_TX_KICK               (1 << 2)
 
 #define OMAP_UART_FCR_RX_TRIG          6
 #define OMAP_UART_FCR_TX_TRIG          4
        pm_runtime_put_autosuspend(port->dev);
 }
 
+#ifdef CONFIG_SERIAL_8250_DMA
+static int omap_8250_tx_dma(struct uart_8250_port *p);
+
+static void omap_8250_dma_tx_complete(void *param)
+{
+       struct uart_8250_port   *p = param;
+       struct uart_8250_dma    *dma = p->dma;
+       struct circ_buf         *xmit = &p->port.state->xmit;
+       unsigned long           flags;
+       bool                    en_thri = false;
+
+       dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
+                               UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+       spin_lock_irqsave(&p->port.lock, flags);
+
+       dma->tx_running = 0;
+
+       xmit->tail += dma->tx_size;
+       xmit->tail &= UART_XMIT_SIZE - 1;
+       p->port.icount.tx += dma->tx_size;
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&p->port);
+
+       if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) {
+               int ret;
+
+               ret = omap_8250_tx_dma(p);
+               if (ret)
+                       en_thri = true;
+
+       } else if (p->capabilities & UART_CAP_RPM) {
+               en_thri = true;
+       }
+
+       if (en_thri) {
+               dma->tx_err = 1;
+               p->ier |= UART_IER_THRI;
+               serial_port_out(&p->port, UART_IER, p->ier);
+       }
+
+       spin_unlock_irqrestore(&p->port.lock, flags);
+}
+
+static int omap_8250_tx_dma(struct uart_8250_port *p)
+{
+       struct uart_8250_dma            *dma = p->dma;
+       struct omap8250_priv            *priv = p->port.private_data;
+       struct circ_buf                 *xmit = &p->port.state->xmit;
+       struct dma_async_tx_descriptor  *desc;
+       unsigned int    skip_byte = 0;
+       int ret;
+
+       if (dma->tx_running)
+               return 0;
+       if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
+
+               /*
+                * Even if no data, we need to return an error for the two cases
+                * below so serial8250_tx_chars() is invoked and properly clears
+                * THRI and/or runtime suspend.
+                */
+               if (dma->tx_err || p->capabilities & UART_CAP_RPM) {
+                       ret = -EBUSY;
+                       goto err;
+               }
+               if (p->ier & UART_IER_THRI) {
+                       p->ier &= ~UART_IER_THRI;
+                       serial_out(p, UART_IER, p->ier);
+               }
+               return 0;
+       }
+
+       dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+       if (priv->habit & OMAP_DMA_TX_KICK) {
+               u8 tx_lvl;
+
+               /*
+                * We need to put the first byte into the FIFO in order to start
+                * the DMA transfer. For transfers smaller than four bytes we
+                * don't bother doing DMA at all. It seem not matter if there
+                * are still bytes in the FIFO from the last transfer (in case
+                * we got here directly from omap_8250_dma_tx_complete()). Bytes
+                * leaving the FIFO seem not to trigger the DMA transfer. It is
+                * really the byte that we put into the FIFO.
+                * If the FIFO is already full then we most likely got here from
+                * omap_8250_dma_tx_complete(). And this means the DMA engine
+                * just completed its work. We don't have to wait the complete
+                * 86us at 115200,8n1 but around 60us (not to mention lower
+                * baudrates). So in that case we take the interrupt and try
+                * again with an empty FIFO.
+                */
+               tx_lvl = serial_in(p, UART_OMAP_TX_LVL);
+               if (tx_lvl == p->tx_loadsz) {
+                       ret = -EBUSY;
+                       goto err;
+               }
+               if (dma->tx_size < 4) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+               skip_byte = 1;
+       }
+
+       desc = dmaengine_prep_slave_single(dma->txchan,
+                       dma->tx_addr + xmit->tail + skip_byte,
+                       dma->tx_size - skip_byte, DMA_MEM_TO_DEV,
+                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!desc) {
+               ret = -EBUSY;
+               goto err;
+       }
+
+       dma->tx_running = 1;
+
+       desc->callback = omap_8250_dma_tx_complete;
+       desc->callback_param = p;
+
+       dma->tx_cookie = dmaengine_submit(desc);
+
+       dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
+                                  UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+       dma_async_issue_pending(dma->txchan);
+       if (dma->tx_err)
+               dma->tx_err = 0;
+
+       if (p->ier & UART_IER_THRI) {
+               p->ier &= ~UART_IER_THRI;
+               serial_out(p, UART_IER, p->ier);
+       }
+       if (skip_byte)
+               serial_out(p, UART_TX, xmit->buf[xmit->tail]);
+       return 0;
+err:
+       dma->tx_err = 1;
+       return ret;
+}
+
+#endif
+
 static int omap8250_probe(struct platform_device *pdev)
 {
        struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);