Removes use of the DaVinci EDMA private DMA API and replaces
it with use of the DMA engine API.

Signed-off-by: Matt Porter <mpor...@ti.com>
---
 drivers/mmc/host/davinci_mmc.c |  271 ++++++++++++----------------------------
 1 file changed, 82 insertions(+), 189 deletions(-)

diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 7cf6c62..c5e1eeb 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -30,11 +30,12 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
+#include <linux/edma.h>
 #include <linux/mmc/mmc.h>
 
 #include <mach/mmc.h>
-#include <mach/edma.h>
 
 /*
  * Register Definitions
@@ -200,21 +201,13 @@ struct mmc_davinci_host {
        u32 bytes_left;
 
        u32 rxdma, txdma;
+       struct dma_chan *dma_tx;
+       struct dma_chan *dma_rx;
        bool use_dma;
        bool do_dma;
        bool sdio_int;
        bool active_request;
 
-       /* Scatterlist DMA uses one or more parameter RAM entries:
-        * the main one (associated with rxdma or txdma) plus zero or
-        * more links.  The entries for a given transfer differ only
-        * by memory buffer (address, length) and link field.
-        */
-       struct edmacc_param     tx_template;
-       struct edmacc_param     rx_template;
-       unsigned                n_link;
-       u32                     links[MAX_NR_SG - 1];
-
        /* For PIO we walk scatterlists one segment at a time. */
        unsigned int            sg_len;
        struct scatterlist *sg;
@@ -410,153 +403,74 @@ static void mmc_davinci_start_command(struct 
mmc_davinci_host *host,
 
 static void davinci_abort_dma(struct mmc_davinci_host *host)
 {
-       int sync_dev;
+       struct dma_chan *sync_dev;
 
        if (host->data_dir == DAVINCI_MMC_DATADIR_READ)
-               sync_dev = host->rxdma;
+               sync_dev = host->dma_rx;
        else
-               sync_dev = host->txdma;
-
-       edma_stop(sync_dev);
-       edma_clean_channel(sync_dev);
-}
-
-static void
-mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data);
-
-static void mmc_davinci_dma_cb(unsigned channel, u16 ch_status, void *data)
-{
-       if (DMA_COMPLETE != ch_status) {
-               struct mmc_davinci_host *host = data;
-
-               /* Currently means:  DMA Event Missed, or "null" transfer
-                * request was seen.  In the future, TC errors (like bad
-                * addresses) might be presented too.
-                */
-               dev_warn(mmc_dev(host->mmc), "DMA %s error\n",
-                       (host->data->flags & MMC_DATA_WRITE)
-                               ? "write" : "read");
-               host->data->error = -EIO;
-               mmc_davinci_xfer_done(host, host->data);
-       }
-}
-
-/* Set up tx or rx template, to be modified and updated later */
-static void __init mmc_davinci_dma_setup(struct mmc_davinci_host *host,
-               bool tx, struct edmacc_param *template)
-{
-       unsigned        sync_dev;
-       const u16       acnt = 4;
-       const u16       bcnt = rw_threshold >> 2;
-       const u16       ccnt = 0;
-       u32             src_port = 0;
-       u32             dst_port = 0;
-       s16             src_bidx, dst_bidx;
-       s16             src_cidx, dst_cidx;
-
-       /*
-        * A-B Sync transfer:  each DMA request is for one "frame" of
-        * rw_threshold bytes, broken into "acnt"-size chunks repeated
-        * "bcnt" times.  Each segment needs "ccnt" such frames; since
-        * we tell the block layer our mmc->max_seg_size limit, we can
-        * trust (later) that it's within bounds.
-        *
-        * The FIFOs are read/written in 4-byte chunks (acnt == 4) and
-        * EDMA will optimize memory operations to use larger bursts.
-        */
-       if (tx) {
-               sync_dev = host->txdma;
-
-               /* src_prt, ccnt, and link to be set up later */
-               src_bidx = acnt;
-               src_cidx = acnt * bcnt;
-
-               dst_port = host->mem_res->start + DAVINCI_MMCDXR;
-               dst_bidx = 0;
-               dst_cidx = 0;
-       } else {
-               sync_dev = host->rxdma;
-
-               src_port = host->mem_res->start + DAVINCI_MMCDRR;
-               src_bidx = 0;
-               src_cidx = 0;
-
-               /* dst_prt, ccnt, and link to be set up later */
-               dst_bidx = acnt;
-               dst_cidx = acnt * bcnt;
-       }
-
-       /*
-        * We can't use FIFO mode for the FIFOs because MMC FIFO addresses
-        * are not 256-bit (32-byte) aligned.  So we use INCR, and the W8BIT
-        * parameter is ignored.
-        */
-       edma_set_src(sync_dev, src_port, INCR, W8BIT);
-       edma_set_dest(sync_dev, dst_port, INCR, W8BIT);
+               sync_dev = host->dma_tx;
 
-       edma_set_src_index(sync_dev, src_bidx, src_cidx);
-       edma_set_dest_index(sync_dev, dst_bidx, dst_cidx);
-
-       edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC);
-
-       edma_read_slot(sync_dev, template);
-
-       /* don't bother with irqs or chaining */
-       template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12;
+       dmaengine_terminate_all(sync_dev);
 }
 
-static void mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
+static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
                struct mmc_data *data)
 {
-       struct edmacc_param     *template;
-       int                     channel, slot;
-       unsigned                link;
-       struct scatterlist      *sg;
-       unsigned                sg_len;
-       unsigned                bytes_left = host->bytes_left;
-       const unsigned          shift = ffs(rw_threshold) - 1;
+       struct dma_chan *chan;
+       struct dma_async_tx_descriptor *desc;
+       int ret = 0;
 
        if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
-               template = &host->tx_template;
-               channel = host->txdma;
+               struct dma_slave_config dma_tx_conf = {
+                       .direction = DMA_MEM_TO_DEV,
+                       .dst_addr = host->mem_res->start + DAVINCI_MMCDXR,
+                       .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+                       .dst_maxburst =
+                               rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+               };
+               chan = host->dma_tx;
+               dmaengine_slave_config(host->dma_tx, &dma_tx_conf);
+
+               desc = dmaengine_prep_slave_sg(host->dma_tx,
+                               data->sg,
+                               host->sg_len,
+                               DMA_MEM_TO_DEV,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc) {
+                       dev_dbg(mmc_dev(host->mmc),
+                               "failed to allocate DMA TX descriptor");
+                       ret = -1;
+                       goto out;
+               }
        } else {
-               template = &host->rx_template;
-               channel = host->rxdma;
-       }
-
-       /* We know sg_len and ccnt will never be out of range because
-        * we told the mmc layer which in turn tells the block layer
-        * to ensure that it only hands us one scatterlist segment
-        * per EDMA PARAM entry.  Update the PARAM
-        * entries needed for each segment of this scatterlist.
-        */
-       for (slot = channel, link = 0, sg = data->sg, sg_len = host->sg_len;
-                       sg_len-- != 0 && bytes_left;
-                       sg = sg_next(sg), slot = host->links[link++]) {
-               u32             buf = sg_dma_address(sg);
-               unsigned        count = sg_dma_len(sg);
-
-               template->link_bcntrld = sg_len
-                               ? (EDMA_CHAN_SLOT(host->links[link]) << 5)
-                               : 0xffff;
-
-               if (count > bytes_left)
-                       count = bytes_left;
-               bytes_left -= count;
-
-               if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
-                       template->src = buf;
-               else
-                       template->dst = buf;
-               template->ccnt = count >> shift;
-
-               edma_write_slot(slot, template);
+               struct dma_slave_config dma_rx_conf = {
+                       .direction = DMA_DEV_TO_MEM,
+                       .src_addr = host->mem_res->start + DAVINCI_MMCDRR,
+                       .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+                       .src_maxburst =
+                               rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+               };
+               chan = host->dma_rx;
+               dmaengine_slave_config(host->dma_rx, &dma_rx_conf);
+
+               desc = dmaengine_prep_slave_sg(host->dma_rx,
+                               data->sg,
+                               host->sg_len,
+                               DMA_DEV_TO_MEM,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc) {
+                       dev_dbg(mmc_dev(host->mmc),
+                               "failed to allocate DMA RX descriptor");
+                       ret = -1;
+                       goto out;
+               }
        }
 
-       if (host->version == MMC_CTLR_VERSION_2)
-               edma_clear_event(channel);
+       dmaengine_submit(desc);
+       dma_async_issue_pending(chan);
 
-       edma_start(channel);
+out:
+       return ret;
 }
 
 static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host,
@@ -564,6 +478,7 @@ static int mmc_davinci_start_dma_transfer(struct 
mmc_davinci_host *host,
 {
        int i;
        int mask = rw_threshold - 1;
+       int ret = 0;
 
        host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
                                ((data->flags & MMC_DATA_WRITE)
@@ -583,70 +498,48 @@ static int mmc_davinci_start_dma_transfer(struct 
mmc_davinci_host *host,
        }
 
        host->do_dma = 1;
-       mmc_davinci_send_dma_request(host, data);
+       ret = mmc_davinci_send_dma_request(host, data);
 
-       return 0;
+       return ret;
 }
 
 static void __init_or_module
 davinci_release_dma_channels(struct mmc_davinci_host *host)
 {
-       unsigned        i;
-
        if (!host->use_dma)
                return;
 
-       for (i = 0; i < host->n_link; i++)
-               edma_free_slot(host->links[i]);
-
-       edma_free_channel(host->txdma);
-       edma_free_channel(host->rxdma);
+       dma_release_channel(host->dma_tx);
+       dma_release_channel(host->dma_rx);
 }
 
 static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host)
 {
-       u32 link_size;
-       int r, i;
-
-       /* Acquire master DMA write channel */
-       r = edma_alloc_channel(host->txdma, mmc_davinci_dma_cb, host,
-                       EVENTQ_DEFAULT);
-       if (r < 0) {
-               dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n",
-                               "tx", r);
-               return r;
-       }
-       mmc_davinci_dma_setup(host, true, &host->tx_template);
-
-       /* Acquire master DMA read channel */
-       r = edma_alloc_channel(host->rxdma, mmc_davinci_dma_cb, host,
-                       EVENTQ_DEFAULT);
-       if (r < 0) {
-               dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n",
-                               "rx", r);
-               goto free_master_write;
+       int r;
+       dma_cap_mask_t mask;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       host->dma_tx =
+               dma_request_channel(mask, edma_filter_fn, &host->txdma);
+       if (!host->dma_tx) {
+               dev_err(mmc_dev(host->mmc), "Can't get dma_tx channel\n");
+               return -ENODEV;
        }
-       mmc_davinci_dma_setup(host, false, &host->rx_template);
 
-       /* Allocate parameter RAM slots, which will later be bound to a
-        * channel as needed to handle a scatterlist.
-        */
-       link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links));
-       for (i = 0; i < link_size; i++) {
-               r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY);
-               if (r < 0) {
-                       dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n",
-                               r);
-                       break;
-               }
-               host->links[i] = r;
+       host->dma_rx =
+               dma_request_channel(mask, edma_filter_fn, &host->rxdma);
+       if (!host->dma_rx) {
+               dev_err(mmc_dev(host->mmc), "Can't get dma_rx channel\n");
+               r = -ENODEV;
+               goto free_master_write;
        }
-       host->n_link = i;
 
        return 0;
 
 free_master_write:
-       edma_free_channel(host->txdma);
+       dma_release_channel(host->dma_tx);
 
        return r;
 }
@@ -1359,7 +1252,7 @@ static int __init davinci_mmcsd_probe(struct 
platform_device *pdev)
         * Each hw_seg uses one EDMA parameter RAM slot, always one
         * channel and then usually some linked slots.
         */
-       mmc->max_segs           = 1 + host->n_link;
+       mmc->max_segs           = MAX_NR_SG;
 
        /* EDMA limit per hw segment (one or two MBytes) */
        mmc->max_seg_size       = MAX_CCNT * rw_threshold;
-- 
1.7.9.5


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

Reply via email to