summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2018-01-23 13:28:05 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commitbb4258bafba2c01f27816a7a1dc26baf386636ce (patch)
tree8ec5d4e71c45c95dbc45031252d72f428da4e0e8 /drivers/dma
parenteb968dee63e383b8a78f60c22c393dc92978158e (diff)
MLK-16224-5: dma: imx-sdma: support mulit fifo script
The type IMX_DMATYPE_MULTI_SAI is used for SAI multi-fifo mode, in this mode, the fifo num parameter is configured through dma_slave_config The watermark definition is: bit0~7: wartermark level bit8~11: fifo number bit16~19: fifo offset bit27~24: sw done selector bit23: sw done enabled Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Reviewed-by: Robin Gong<yibin.gong@nxp.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/imx-sdma.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 4ddf03369cb8..d31d744336e7 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -193,6 +193,10 @@
BIT(DMA_MEM_TO_DEV) | \
BIT(DMA_DEV_TO_DEV))
+#define SDMA_WATERMARK_LEVEL_FIFOS_OFF 8
+#define SDMA_WATERMARK_LEVEL_SW_DONE BIT(23)
+#define SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF 24
+
/*
* Mode/Count of data node descriptors - IPCv2
*/
@@ -358,6 +362,7 @@ struct sdma_channel {
u32 bd_size_sum;
bool src_dualfifo;
bool dst_dualfifo;
+ unsigned int fifo_num;
struct dma_pool *bd_pool;
};
@@ -970,6 +975,9 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
case IMX_DMATYPE_HDMI:
emi_2_per = sdma->script_addrs->hdmi_dma_addr;
break;
+ case IMX_DMATYPE_MULTI_SAI:
+ per_2_emi = sdma->script_addrs->sai_2_mcu_addr;
+ emi_2_per = sdma->script_addrs->mcu_2_sai_addr;
default:
break;
}
@@ -1132,6 +1140,20 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DD;
}
+static void sdma_set_watermarklevel_for_sais(struct sdma_channel *sdmac)
+{
+ sdmac->watermark_level &= ~(0xFFF << SDMA_WATERMARK_LEVEL_FIFOS_OFF |
+ SDMA_WATERMARK_LEVEL_SW_DONE);
+
+ /* For fifo_num
+ * bit 0-7 is the fifo number;
+ * bit 8-11 is the fifo offset,
+ * so here only need to shift left fifo_num 8 bit for watermake_level
+ */
+ sdmac->watermark_level |= sdmac->fifo_num<<
+ SDMA_WATERMARK_LEVEL_FIFOS_OFF;
+}
+
static int sdma_config_channel(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
@@ -1181,6 +1203,9 @@ static int sdma_config_channel(struct dma_chan *chan)
sdmac->direction == DMA_MEM_TO_DEV &&
sdmac->sdma->drvdata == &sdma_imx6ul)
__set_bit(31, &sdmac->watermark_level);
+ else if (sdmac->peripheral_type ==
+ IMX_DMATYPE_MULTI_SAI)
+ sdma_set_watermarklevel_for_sais(sdmac);
__set_bit(sdmac->event_id0, sdmac->event_mask);
}
@@ -1776,12 +1801,14 @@ static int sdma_config(struct dma_chan *chan,
struct dma_slave_config *dmaengine_cfg)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
-
+ /* clear watermark_level before setting */
+ sdmac->watermark_level = 0;
if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
sdmac->per_address = dmaengine_cfg->src_addr;
sdmac->watermark_level = dmaengine_cfg->src_maxburst *
dmaengine_cfg->src_addr_width;
sdmac->word_size = dmaengine_cfg->src_addr_width;
+ sdmac->fifo_num = dmaengine_cfg->src_fifo_num;
} else if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) {
sdmac->per_address2 = dmaengine_cfg->src_addr;
sdmac->per_address = dmaengine_cfg->dst_addr;
@@ -1801,6 +1828,7 @@ static int sdma_config(struct dma_chan *chan,
sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
dmaengine_cfg->dst_addr_width;
sdmac->word_size = dmaengine_cfg->dst_addr_width;
+ sdmac->fifo_num = dmaengine_cfg->dst_fifo_num;
}
sdmac->direction = dmaengine_cfg->direction;
return sdma_config_channel(chan);