This change adds a new function to support for preparing DMA descriptor for custom data. Signed-off-by: Ram Chandra Jangir <rjangir@codeaurora.org>master
parent
ea9e0cf2ce
commit
35307c0bbf
@ -0,0 +1,217 @@ |
||||
From 5a7ccdf845d64b385affdcffaf2defbe9848be15 Mon Sep 17 00:00:00 2001
|
||||
From: Ram Chandra Jangir <rjangir@codeaurora.org>
|
||||
Date: Thu, 20 Apr 2017 10:39:00 +0530
|
||||
Subject: [PATCH] dmaengine: qcom: bam_dma: Add custom data mapping
|
||||
|
||||
Add a new function to support for preparing DMA descriptor
|
||||
for custom data.
|
||||
|
||||
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
|
||||
Signed-off-by: Ram Chandra Jangir <rjangir@codeaurora.org>
|
||||
---
|
||||
drivers/dma/qcom/bam_dma.c | 97 +++++++++++++++++++++++++++++++++++++---
|
||||
include/linux/dma/qcom_bam_dma.h | 14 ++++++
|
||||
include/linux/dmaengine.h | 14 ++++++
|
||||
3 files changed, 119 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
|
||||
index 03c4eb3..bde8d70 100644
|
||||
--- a/drivers/dma/qcom/bam_dma.c
|
||||
+++ b/drivers/dma/qcom/bam_dma.c
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
+#include <linux/dma/qcom_bam_dma.h>
|
||||
|
||||
#include "../dmaengine.h"
|
||||
#include "../virt-dma.h"
|
||||
@@ -61,11 +62,6 @@ struct bam_desc_hw {
|
||||
|
||||
#define BAM_DMA_AUTOSUSPEND_DELAY 100
|
||||
|
||||
-#define DESC_FLAG_INT BIT(15)
|
||||
-#define DESC_FLAG_EOT BIT(14)
|
||||
-#define DESC_FLAG_EOB BIT(13)
|
||||
-#define DESC_FLAG_NWD BIT(12)
|
||||
-
|
||||
struct bam_async_desc {
|
||||
struct virt_dma_desc vd;
|
||||
|
||||
@@ -670,6 +666,93 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan,
|
||||
}
|
||||
|
||||
/**
|
||||
+ * bam_prep_dma_custom_mapping - Prep DMA descriptor from custom data
|
||||
+ *
|
||||
+ * @chan: dma channel
|
||||
+ * @data: custom data
|
||||
+ * @flags: DMA flags
|
||||
+ */
|
||||
+static struct dma_async_tx_descriptor *bam_prep_dma_custom_mapping(
|
||||
+ struct dma_chan *chan,
|
||||
+ void *data, unsigned long flags)
|
||||
+{
|
||||
+ struct bam_chan *bchan = to_bam_chan(chan);
|
||||
+ struct bam_device *bdev = bchan->bdev;
|
||||
+ struct bam_async_desc *async_desc;
|
||||
+ struct qcom_bam_custom_data *desc_data = data;
|
||||
+ u32 i;
|
||||
+ struct bam_desc_hw *desc;
|
||||
+ unsigned int num_alloc = 0;
|
||||
+
|
||||
+
|
||||
+ if (!is_slave_direction(desc_data->dir)) {
|
||||
+ dev_err(bdev->dev, "invalid dma direction\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* calculate number of required entries */
|
||||
+ for (i = 0; i < desc_data->sgl_cnt; i++)
|
||||
+ num_alloc += DIV_ROUND_UP(
|
||||
+ sg_dma_len(&desc_data->bam_sgl[i].sgl), BAM_FIFO_SIZE);
|
||||
+
|
||||
+ /* allocate enough room to accommodate the number of entries */
|
||||
+ async_desc = kzalloc(sizeof(*async_desc) +
|
||||
+ (num_alloc * sizeof(struct bam_desc_hw)), GFP_NOWAIT);
|
||||
+
|
||||
+ if (!async_desc)
|
||||
+ goto err_out;
|
||||
+
|
||||
+ if (flags & DMA_PREP_FENCE)
|
||||
+ async_desc->flags |= DESC_FLAG_NWD;
|
||||
+
|
||||
+ if (flags & DMA_PREP_INTERRUPT)
|
||||
+ async_desc->flags |= DESC_FLAG_EOT;
|
||||
+ else
|
||||
+ async_desc->flags |= DESC_FLAG_INT;
|
||||
+
|
||||
+ async_desc->num_desc = num_alloc;
|
||||
+ async_desc->curr_desc = async_desc->desc;
|
||||
+ async_desc->dir = desc_data->dir;
|
||||
+
|
||||
+ /* fill in temporary descriptors */
|
||||
+ desc = async_desc->desc;
|
||||
+ for (i = 0; i < desc_data->sgl_cnt; i++) {
|
||||
+ unsigned int remainder;
|
||||
+ unsigned int curr_offset = 0;
|
||||
+
|
||||
+ remainder = sg_dma_len(&desc_data->bam_sgl[i].sgl);
|
||||
+
|
||||
+ do {
|
||||
+ desc->addr = cpu_to_le32(
|
||||
+ sg_dma_address(&desc_data->bam_sgl[i].sgl) +
|
||||
+ curr_offset);
|
||||
+
|
||||
+ if (desc_data->bam_sgl[i].dma_flags)
|
||||
+ desc->flags |= cpu_to_le16(
|
||||
+ desc_data->bam_sgl[i].dma_flags);
|
||||
+
|
||||
+ if (remainder > BAM_FIFO_SIZE) {
|
||||
+ desc->size = cpu_to_le16(BAM_FIFO_SIZE);
|
||||
+ remainder -= BAM_FIFO_SIZE;
|
||||
+ curr_offset += BAM_FIFO_SIZE;
|
||||
+ } else {
|
||||
+ desc->size = cpu_to_le16(remainder);
|
||||
+ remainder = 0;
|
||||
+ }
|
||||
+
|
||||
+ async_desc->length += desc->size;
|
||||
+ desc++;
|
||||
+ } while (remainder > 0);
|
||||
+ }
|
||||
+
|
||||
+ return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags);
|
||||
+
|
||||
+err_out:
|
||||
+ kfree(async_desc);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* bam_dma_terminate_all - terminate all transactions on a channel
|
||||
* @bchan: bam dma channel
|
||||
*
|
||||
@@ -960,7 +1043,7 @@ static void bam_start_dma(struct bam_chan *bchan)
|
||||
|
||||
/* set any special flags on the last descriptor */
|
||||
if (async_desc->num_desc == async_desc->xfer_len)
|
||||
- desc[async_desc->xfer_len - 1].flags =
|
||||
+ desc[async_desc->xfer_len - 1].flags |=
|
||||
cpu_to_le16(async_desc->flags);
|
||||
else
|
||||
desc[async_desc->xfer_len - 1].flags |=
|
||||
@@ -1237,6 +1320,8 @@ static int bam_dma_probe(struct platform_device *pdev)
|
||||
bdev->common.device_alloc_chan_resources = bam_alloc_chan;
|
||||
bdev->common.device_free_chan_resources = bam_free_chan;
|
||||
bdev->common.device_prep_slave_sg = bam_prep_slave_sg;
|
||||
+ bdev->common.device_prep_dma_custom_mapping =
|
||||
+ bam_prep_dma_custom_mapping;
|
||||
bdev->common.device_config = bam_slave_config;
|
||||
bdev->common.device_pause = bam_pause;
|
||||
bdev->common.device_resume = bam_resume;
|
||||
diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h
|
||||
index 7e87a85..7113c77 100644
|
||||
--- a/include/linux/dma/qcom_bam_dma.h
|
||||
+++ b/include/linux/dma/qcom_bam_dma.h
|
||||
@@ -65,6 +65,19 @@ enum bam_command_type {
|
||||
};
|
||||
|
||||
/*
|
||||
+ * QCOM BAM DMA custom data
|
||||
+ *
|
||||
+ * @sgl_cnt: number of sgl in bam_sgl
|
||||
+ * @dir: DMA data transfer direction
|
||||
+ * @bam_sgl: BAM SGL pointer
|
||||
+ */
|
||||
+struct qcom_bam_custom_data {
|
||||
+ u32 sgl_cnt;
|
||||
+ enum dma_transfer_direction dir;
|
||||
+ struct qcom_bam_sgl *bam_sgl;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
* qcom_bam_sg_init_table - Init QCOM BAM SGL
|
||||
* @bam_sgl: bam sgl
|
||||
* @nents: number of entries in bam sgl
|
||||
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
|
||||
index cc535a4..627c125 100644
|
||||
--- a/include/linux/dmaengine.h
|
||||
+++ b/include/linux/dmaengine.h
|
||||
@@ -692,6 +692,8 @@ struct dma_filter {
|
||||
* be called after period_len bytes have been transferred.
|
||||
* @device_prep_interleaved_dma: Transfer expression in a generic way.
|
||||
* @device_prep_dma_imm_data: DMA's 8 byte immediate data to the dst address
|
||||
+ * @device_prep_dma_custom_mapping: prepares a dma operation from dma driver
|
||||
+ * specific custom data
|
||||
* @device_config: Pushes a new configuration to a channel, return 0 or an error
|
||||
* code
|
||||
* @device_pause: Pauses any transfer happening on a channel. Returns
|
||||
@@ -783,6 +785,9 @@ struct dma_device {
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_imm_data)(
|
||||
struct dma_chan *chan, dma_addr_t dst, u64 data,
|
||||
unsigned long flags);
|
||||
+ struct dma_async_tx_descriptor *(*device_prep_dma_custom_mapping)(
|
||||
+ struct dma_chan *chan, void *data,
|
||||
+ unsigned long flags);
|
||||
|
||||
int (*device_config)(struct dma_chan *chan,
|
||||
struct dma_slave_config *config);
|
||||
@@ -899,6 +904,15 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_sg(
|
||||
src_sg, src_nents, flags);
|
||||
}
|
||||
|
||||
+static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_custom_mapping(
|
||||
+ struct dma_chan *chan,
|
||||
+ void *data,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ return chan->device->device_prep_dma_custom_mapping(chan, data,
|
||||
+ flags);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* dmaengine_terminate_all() - Terminate all active DMA transfers
|
||||
* @chan: The channel for which to terminate the transfers
|
||||
--
|
||||
2.7.2
|
Loading…
Reference in new issue