#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/cache.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
                spi->master->set_cs(spi, !enable);
 }
 
+static int spi_map_msg(struct spi_master *master, struct spi_message *msg)
+{
+       struct device *dev = master->dev.parent;
+       struct device *tx_dev, *rx_dev;
+       struct spi_transfer *xfer;
+
+       if (msg->is_dma_mapped || !master->can_dma)
+               return 0;
+
+       tx_dev = &master->dma_tx->dev->device;
+       rx_dev = &master->dma_rx->dev->device;
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (!master->can_dma(master, msg->spi, xfer))
+                       continue;
+
+               if (xfer->tx_buf != NULL) {
+                       xfer->tx_dma = dma_map_single(tx_dev,
+                                                     (void *)xfer->tx_buf,
+                                                     xfer->len,
+                                                     DMA_TO_DEVICE);
+                       if (dma_mapping_error(dev, xfer->tx_dma)) {
+                               dev_err(dev, "dma_map_single Tx failed\n");
+                               return -ENOMEM;
+                       }
+               }
+
+               if (xfer->rx_buf != NULL) {
+                       xfer->rx_dma = dma_map_single(rx_dev,
+                                                     xfer->rx_buf, xfer->len,
+                                                     DMA_FROM_DEVICE);
+                       if (dma_mapping_error(dev, xfer->rx_dma)) {
+                               dev_err(dev, "dma_map_single Rx failed\n");
+                               dma_unmap_single(tx_dev, xfer->tx_dma,
+                                                xfer->len, DMA_TO_DEVICE);
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       master->cur_msg_mapped = true;
+
+       return 0;
+}
+
+static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
+{
+       struct spi_transfer *xfer;
+       struct device *tx_dev, *rx_dev;
+
+       if (!master->cur_msg_mapped || msg->is_dma_mapped || !master->can_dma)
+               return 0;
+
+       tx_dev = &master->dma_tx->dev->device;
+       rx_dev = &master->dma_rx->dev->device;
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (!master->can_dma(master, msg->spi, xfer))
+                       continue;
+
+               if (xfer->rx_buf)
+                       dma_unmap_single(rx_dev, xfer->rx_dma, xfer->len,
+                                        DMA_FROM_DEVICE);
+               if (xfer->tx_buf)
+                       dma_unmap_single(tx_dev, xfer->tx_dma, xfer->len,
+                                        DMA_TO_DEVICE);
+       }
+
+       return 0;
+}
+
 /*
  * spi_transfer_one_message - Default implementation of transfer_one_message()
  *
                master->cur_msg_prepared = true;
        }
 
+       ret = spi_map_msg(master, master->cur_msg);
+       if (ret) {
+               master->cur_msg->status = ret;
+               spi_finalize_current_message(master);
+               return;
+       }
+
        ret = master->transfer_one_message(master, master->cur_msg);
        if (ret) {
                dev_err(&master->dev,
        queue_kthread_work(&master->kworker, &master->pump_messages);
        spin_unlock_irqrestore(&master->queue_lock, flags);
 
+       spi_unmap_msg(master, mesg);
+
        if (master->cur_msg_prepared && master->unprepare_message) {
                ret = master->unprepare_message(master, mesg);
                if (ret) {
 
 #include <linux/kthread.h>
 #include <linux/completion.h>
 
+struct dma_chan;
+
 /*
  * INTERFACES between SPI master-side drivers and SPI infrastructure.
  * (There's no SPI slave support for Linux yet...)
        /* called on release() to free memory provided by spi_master */
        void                    (*cleanup)(struct spi_device *spi);
 
+       /*
+        * Used to enable core support for DMA handling, if can_dma()
+        * exists and returns true then the transfer will be mapped
+        * prior to transfer_one() being called.  The driver should
+        * not modify or store xfer and dma_tx and dma_rx must be set
+        * while the device is prepared.
+        */
+       bool                    (*can_dma)(struct spi_master *master,
+                                          struct spi_device *spi,
+                                          struct spi_transfer *xfer);
+
        /*
         * These hooks are for drivers that want to use the generic
         * master transfer queueing mechanism. If these are used, the
        bool                            rt;
        bool                            auto_runtime_pm;
        bool                            cur_msg_prepared;
+       bool                            cur_msg_mapped;
        struct completion               xfer_completion;
 
        int (*prepare_transfer_hardware)(struct spi_master *master);
 
        /* gpio chip select */
        int                     *cs_gpios;
+
+       /* DMA channels for use with core dmaengine helpers */
+       struct dma_chan         *dma_tx;
+       struct dma_chan         *dma_rx;
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)