]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/dma/fsldma.c
Merge branch 'for-3.16-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...
[karo-tx-linux.git] / drivers / dma / fsldma.c
index f157c6f76b32b8c98dce28eed6253db033acc258..e0fec68aed2511220206960a1b0930cf65e696b8 100644 (file)
@@ -61,6 +61,16 @@ static u32 get_sr(struct fsldma_chan *chan)
        return DMA_IN(chan, &chan->regs->sr, 32);
 }
 
+static void set_mr(struct fsldma_chan *chan, u32 val)
+{
+       DMA_OUT(chan, &chan->regs->mr, val, 32);
+}
+
+static u32 get_mr(struct fsldma_chan *chan)
+{
+       return DMA_IN(chan, &chan->regs->mr, 32);
+}
+
 static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
 {
        DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
@@ -71,6 +81,11 @@ static dma_addr_t get_cdar(struct fsldma_chan *chan)
        return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
 }
 
+static void set_bcr(struct fsldma_chan *chan, u32 val)
+{
+       DMA_OUT(chan, &chan->regs->bcr, val, 32);
+}
+
 static u32 get_bcr(struct fsldma_chan *chan)
 {
        return DMA_IN(chan, &chan->regs->bcr, 32);
@@ -135,7 +150,7 @@ static void set_ld_eol(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
 static void dma_init(struct fsldma_chan *chan)
 {
        /* Reset the channel */
-       DMA_OUT(chan, &chan->regs->mr, 0, 32);
+       set_mr(chan, 0);
 
        switch (chan->feature & FSL_DMA_IP_MASK) {
        case FSL_DMA_IP_85XX:
@@ -144,16 +159,15 @@ static void dma_init(struct fsldma_chan *chan)
                 * EOLNIE - End of links interrupt enable
                 * BWC - Bandwidth sharing among channels
                 */
-               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
-                               | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE, 32);
+               set_mr(chan, FSL_DMA_MR_BWC | FSL_DMA_MR_EIE
+                       | FSL_DMA_MR_EOLNIE);
                break;
        case FSL_DMA_IP_83XX:
                /* Set the channel to below modes:
                 * EOTIE - End-of-transfer interrupt enable
                 * PRC_RM - PCI read multiple
                 */
-               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
-                               | FSL_DMA_MR_PRC_RM, 32);
+               set_mr(chan, FSL_DMA_MR_EOTIE | FSL_DMA_MR_PRC_RM);
                break;
        }
 }
@@ -175,10 +189,10 @@ static void dma_start(struct fsldma_chan *chan)
 {
        u32 mode;
 
-       mode = DMA_IN(chan, &chan->regs->mr, 32);
+       mode = get_mr(chan);
 
        if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
-               DMA_OUT(chan, &chan->regs->bcr, 0, 32);
+               set_bcr(chan, 0);
                mode |= FSL_DMA_MR_EMP_EN;
        } else {
                mode &= ~FSL_DMA_MR_EMP_EN;
@@ -191,7 +205,7 @@ static void dma_start(struct fsldma_chan *chan)
                mode |= FSL_DMA_MR_CS;
        }
 
-       DMA_OUT(chan, &chan->regs->mr, mode, 32);
+       set_mr(chan, mode);
 }
 
 static void dma_halt(struct fsldma_chan *chan)
@@ -200,7 +214,7 @@ static void dma_halt(struct fsldma_chan *chan)
        int i;
 
        /* read the mode register */
-       mode = DMA_IN(chan, &chan->regs->mr, 32);
+       mode = get_mr(chan);
 
        /*
         * The 85xx controller supports channel abort, which will stop
@@ -209,14 +223,14 @@ static void dma_halt(struct fsldma_chan *chan)
         */
        if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
                mode |= FSL_DMA_MR_CA;
-               DMA_OUT(chan, &chan->regs->mr, mode, 32);
+               set_mr(chan, mode);
 
                mode &= ~FSL_DMA_MR_CA;
        }
 
        /* stop the DMA controller */
        mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN);
-       DMA_OUT(chan, &chan->regs->mr, mode, 32);
+       set_mr(chan, mode);
 
        /* wait for the DMA controller to become idle */
        for (i = 0; i < 100; i++) {
@@ -245,7 +259,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *chan, int size)
 {
        u32 mode;
 
-       mode = DMA_IN(chan, &chan->regs->mr, 32);
+       mode = get_mr(chan);
 
        switch (size) {
        case 0:
@@ -259,7 +273,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *chan, int size)
                break;
        }
 
-       DMA_OUT(chan, &chan->regs->mr, mode, 32);
+       set_mr(chan, mode);
 }
 
 /**
@@ -277,7 +291,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *chan, int size)
 {
        u32 mode;
 
-       mode = DMA_IN(chan, &chan->regs->mr, 32);
+       mode = get_mr(chan);
 
        switch (size) {
        case 0:
@@ -291,7 +305,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *chan, int size)
                break;
        }
 
-       DMA_OUT(chan, &chan->regs->mr, mode, 32);
+       set_mr(chan, mode);
 }
 
 /**
@@ -312,10 +326,10 @@ static void fsl_chan_set_request_count(struct fsldma_chan *chan, int size)
 
        BUG_ON(size > 1024);
 
-       mode = DMA_IN(chan, &chan->regs->mr, 32);
+       mode = get_mr(chan);
        mode |= (__ilog2(size) << 24) & 0x0f000000;
 
-       DMA_OUT(chan, &chan->regs->mr, mode, 32);
+       set_mr(chan, mode);
 }
 
 /**
@@ -403,6 +417,19 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        return cookie;
 }
 
+/**
+ * fsl_dma_free_descriptor - Free descriptor from channel's DMA pool.
+ * @chan : Freescale DMA channel
+ * @desc: descriptor to be freed
+ */
+static void fsl_dma_free_descriptor(struct fsldma_chan *chan,
+               struct fsl_desc_sw *desc)
+{
+       list_del(&desc->node);
+       chan_dbg(chan, "LD %p free\n", desc);
+       dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+}
+
 /**
  * fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool.
  * @chan : Freescale DMA channel
@@ -426,13 +453,106 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
        desc->async_tx.tx_submit = fsl_dma_tx_submit;
        desc->async_tx.phys = pdesc;
 
-#ifdef FSL_DMA_LD_DEBUG
        chan_dbg(chan, "LD %p allocated\n", desc);
-#endif
 
        return desc;
 }
 
+/**
+ * fsl_chan_xfer_ld_queue - transfer any pending transactions
+ * @chan : Freescale DMA channel
+ *
+ * HARDWARE STATE: idle
+ * LOCKING: must hold chan->desc_lock
+ */
+static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+{
+       struct fsl_desc_sw *desc;
+
+       /*
+        * If the list of pending descriptors is empty, then we
+        * don't need to do any work at all
+        */
+       if (list_empty(&chan->ld_pending)) {
+               chan_dbg(chan, "no pending LDs\n");
+               return;
+       }
+
+       /*
+        * The DMA controller is not idle, which means that the interrupt
+        * handler will start any queued transactions when it runs after
+        * this transaction finishes
+        */
+       if (!chan->idle) {
+               chan_dbg(chan, "DMA controller still busy\n");
+               return;
+       }
+
+       /*
+        * If there are some link descriptors which have not been
+        * transferred, we need to start the controller
+        */
+
+       /*
+        * Move all elements from the queue of pending transactions
+        * onto the list of running transactions
+        */
+       chan_dbg(chan, "idle, starting controller\n");
+       desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
+       list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
+
+       /*
+        * The 85xx DMA controller doesn't clear the channel start bit
+        * automatically at the end of a transfer. Therefore we must clear
+        * it in software before starting the transfer.
+        */
+       if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+               u32 mode;
+
+               mode = get_mr(chan);
+               mode &= ~FSL_DMA_MR_CS;
+               set_mr(chan, mode);
+       }
+
+       /*
+        * Program the descriptor's address into the DMA controller,
+        * then start the DMA transaction
+        */
+       set_cdar(chan, desc->async_tx.phys);
+       get_cdar(chan);
+
+       dma_start(chan);
+       chan->idle = false;
+}
+
+/**
+ * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
+ * @chan: Freescale DMA channel
+ * @desc: descriptor to cleanup and free
+ *
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, and then
+ * free the descriptor.
+ */
+static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
+                                     struct fsl_desc_sw *desc)
+{
+       struct dma_async_tx_descriptor *txd = &desc->async_tx;
+
+       /* Run the link descriptor callback function */
+       if (txd->callback) {
+               chan_dbg(chan, "LD %p callback\n", desc);
+               txd->callback(txd->callback_param);
+       }
+
+       /* Run any dependencies */
+       dma_run_dependencies(txd);
+
+       dma_descriptor_unmap(txd);
+       chan_dbg(chan, "LD %p free\n", desc);
+       dma_pool_free(chan->desc_pool, desc, txd->phys);
+}
+
 /**
  * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
  * @chan : Freescale DMA channel
@@ -477,13 +597,8 @@ static void fsldma_free_desc_list(struct fsldma_chan *chan,
 {
        struct fsl_desc_sw *desc, *_desc;
 
-       list_for_each_entry_safe(desc, _desc, list, node) {
-               list_del(&desc->node);
-#ifdef FSL_DMA_LD_DEBUG
-               chan_dbg(chan, "LD %p free\n", desc);
-#endif
-               dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
-       }
+       list_for_each_entry_safe(desc, _desc, list, node)
+               fsl_dma_free_descriptor(chan, desc);
 }
 
 static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
@@ -491,13 +606,8 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
 {
        struct fsl_desc_sw *desc, *_desc;
 
-       list_for_each_entry_safe_reverse(desc, _desc, list, node) {
-               list_del(&desc->node);
-#ifdef FSL_DMA_LD_DEBUG
-               chan_dbg(chan, "LD %p free\n", desc);
-#endif
-               dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
-       }
+       list_for_each_entry_safe_reverse(desc, _desc, list, node)
+               fsl_dma_free_descriptor(chan, desc);
 }
 
 /**
@@ -519,35 +629,6 @@ static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
        chan->desc_pool = NULL;
 }
 
-static struct dma_async_tx_descriptor *
-fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
-{
-       struct fsldma_chan *chan;
-       struct fsl_desc_sw *new;
-
-       if (!dchan)
-               return NULL;
-
-       chan = to_fsl_chan(dchan);
-
-       new = fsl_dma_alloc_descriptor(chan);
-       if (!new) {
-               chan_err(chan, "%s\n", msg_ld_oom);
-               return NULL;
-       }
-
-       new->async_tx.cookie = -EBUSY;
-       new->async_tx.flags = flags;
-
-       /* Insert the link descriptor to the LD ring */
-       list_add_tail(&new->node, &new->tx_list);
-
-       /* Set End-of-link to the last link descriptor of new list */
-       set_ld_eol(chan, new);
-
-       return &new->async_tx;
-}
-
 static struct dma_async_tx_descriptor *
 fsl_dma_prep_memcpy(struct dma_chan *dchan,
        dma_addr_t dma_dst, dma_addr_t dma_src,
@@ -816,105 +897,6 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
        return 0;
 }
 
-/**
- * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
- * @chan: Freescale DMA channel
- * @desc: descriptor to cleanup and free
- *
- * This function is used on a descriptor which has been executed by the DMA
- * controller. It will run any callbacks, submit any dependencies, and then
- * free the descriptor.
- */
-static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
-                                     struct fsl_desc_sw *desc)
-{
-       struct dma_async_tx_descriptor *txd = &desc->async_tx;
-
-       /* Run the link descriptor callback function */
-       if (txd->callback) {
-#ifdef FSL_DMA_LD_DEBUG
-               chan_dbg(chan, "LD %p callback\n", desc);
-#endif
-               txd->callback(txd->callback_param);
-       }
-
-       /* Run any dependencies */
-       dma_run_dependencies(txd);
-
-       dma_descriptor_unmap(txd);
-#ifdef FSL_DMA_LD_DEBUG
-       chan_dbg(chan, "LD %p free\n", desc);
-#endif
-       dma_pool_free(chan->desc_pool, desc, txd->phys);
-}
-
-/**
- * fsl_chan_xfer_ld_queue - transfer any pending transactions
- * @chan : Freescale DMA channel
- *
- * HARDWARE STATE: idle
- * LOCKING: must hold chan->desc_lock
- */
-static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
-{
-       struct fsl_desc_sw *desc;
-
-       /*
-        * If the list of pending descriptors is empty, then we
-        * don't need to do any work at all
-        */
-       if (list_empty(&chan->ld_pending)) {
-               chan_dbg(chan, "no pending LDs\n");
-               return;
-       }
-
-       /*
-        * The DMA controller is not idle, which means that the interrupt
-        * handler will start any queued transactions when it runs after
-        * this transaction finishes
-        */
-       if (!chan->idle) {
-               chan_dbg(chan, "DMA controller still busy\n");
-               return;
-       }
-
-       /*
-        * If there are some link descriptors which have not been
-        * transferred, we need to start the controller
-        */
-
-       /*
-        * Move all elements from the queue of pending transactions
-        * onto the list of running transactions
-        */
-       chan_dbg(chan, "idle, starting controller\n");
-       desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
-       list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
-
-       /*
-        * The 85xx DMA controller doesn't clear the channel start bit
-        * automatically at the end of a transfer. Therefore we must clear
-        * it in software before starting the transfer.
-        */
-       if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
-               u32 mode;
-
-               mode = DMA_IN(chan, &chan->regs->mr, 32);
-               mode &= ~FSL_DMA_MR_CS;
-               DMA_OUT(chan, &chan->regs->mr, mode, 32);
-       }
-
-       /*
-        * Program the descriptor's address into the DMA controller,
-        * then start the DMA transaction
-        */
-       set_cdar(chan, desc->async_tx.phys);
-       get_cdar(chan);
-
-       dma_start(chan);
-       chan->idle = false;
-}
-
 /**
  * fsl_dma_memcpy_issue_pending - Issue the DMA start command
  * @chan : Freescale DMA channel
@@ -1304,12 +1286,10 @@ static int fsldma_of_probe(struct platform_device *op)
        fdev->irq = irq_of_parse_and_map(op->dev.of_node, 0);
 
        dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
-       dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
        dma_cap_set(DMA_SG, fdev->common.cap_mask);
        dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);
        fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;
        fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;
-       fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt;
        fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
        fdev->common.device_prep_dma_sg = fsl_dma_prep_sg;
        fdev->common.device_tx_status = fsl_tx_status;