[Sound-open-firmware] [PATCH] drivers: dw-dma: move register macros into platform specific header.

Liam Girdwood liam.r.girdwood at linux.intel.com
Tue Jun 6 21:35:38 CEST 2017


Clean up the DW-DMA rsgisters so that it can be more easily integrated
into other platforms.

Signed-off-by: Liam Girdwood <liam.r.girdwood at linux.intel.com>
---
 src/drivers/dw-dma.c                         | 106 ++++++++++++++++++---------
 src/platform/baytrail/include/platform/dma.h |  26 +++++++
 2 files changed, 99 insertions(+), 33 deletions(-)

diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c
index 16f59d1..e851e54 100644
--- a/src/drivers/dw-dma.c
+++ b/src/drivers/dw-dma.c
@@ -62,6 +62,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <string.h>
+#include <config.h>
 
 /* channel registers */
 #define DW_MAX_CHAN			8
@@ -108,20 +109,16 @@
 #define DW_INTR_STATUS			0x0360
 #define DW_DMA_CFG			0x0398
 #define DW_DMA_CHAN_EN			0x03A0
-#define DW_FIFO_PART0_LO		0x0400
-#define DW_FIFO_PART0_HI		0x0404
-#define DW_FIFO_PART1_LO		0x0408
-#define DW_FIFO_PART1_HI		0x040C
-#define DW_CH_SAI_ERR			0x0410
 
 /* channel bits */
 #define INT_MASK(chan)			(0x100 << chan)
 #define INT_UNMASK(chan)		(0x101 << chan)
+#define INT_MASK_ALL			0xFF00
+#define INT_UNMASK_ALL			0xFFFF
 #define CHAN_ENABLE(chan)		(0x101 << chan)
 #define CHAN_DISABLE(chan)		(0x100 << chan)
 
 #define DW_CFG_CH_SUSPEND		0x100
-#define DW_CFG_CH_DRAIN			0x400
 #define DW_CFG_CH_FIFO_EMPTY		0x200
 
 /* CTL_LO */
@@ -136,8 +133,6 @@
 #define DW_CTLL_SRC_FIX			(2 << 9)
 #define DW_CTLL_DST_MSIZE(x)		(x << 11)
 #define DW_CTLL_SRC_MSIZE(x)		(x << 14)
-#define DW_CTLL_S_GATH_EN		(1 << 17)
-#define DW_CTLL_D_SCAT_EN		(1 << 18)
 #define DW_CTLL_FC(x)			(x << 20)
 #define DW_CTLL_FC_M2M			(0 << 20)
 #define DW_CTLL_FC_M2P			(1 << 20)
@@ -150,16 +145,6 @@
 #define DW_CTLL_RELOAD_SRC		(1 << 30)
 #define DW_CTLL_RELOAD_DST		(1 << 31)
 
-/* CTL_HI */
-#define DW_CTLH_DONE			0x00020000
-#define DW_CTLH_BLOCK_TS_MASK		0x0001ffff
-#define DW_CTLH_CLASS(x)		(x << 29)
-#define DW_CTLH_WEIGHT(x)		(x << 18)
-
-/* CFG_HI */
-#define DW_CFGH_SRC_PER(x)		(x << 0)
-#define DW_CFGH_DST_PER(x)		(x << 4)
-
 /* tracing */
 #define trace_dma(__e)	trace_event(TRACE_CLASS_DMA, __e)
 #define trace_dma_error(__e)	trace_error(TRACE_CLASS_DMA, __e)
@@ -168,6 +153,9 @@
 /* HW Linked list support currently disabled - needs debug for missing IRQs !!! */
 #define DW_USE_HW_LLI	0
 
+/* number of tries to wait for reset */
+#define DW_DMA_CFG_TRIES	10000
+
 /* data for each DMA channel */
 struct dma_chan_data {
 	uint32_t status;
@@ -264,7 +252,7 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel)
 		return;
 	}
 
-
+#ifdef DW_CFG_CH_DRAIN /* have drain feature */
 	if (p->chan[channel].status == DMA_STATUS_PAUSED) {
 
 		dw_update_bits(dma, DW_CFG_LOW(channel),
@@ -276,6 +264,7 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel)
 		work_schedule_default(&p->chan[channel].work, 100);
 		return;
 	}
+#endif
 
 	/* mask block, transfer and error interrupts for channel */
 	dw_write(dma, DW_MASK_TFR, INT_MASK(channel));
@@ -456,8 +445,11 @@ static uint32_t dw_dma_fifo_work(void *data, uint32_t udelay)
 
 		/* clear suspend */
 		dw_update_bits(dma, DW_CFG_LOW(cd->channel),
+#ifdef DW_CFG_CH_DRAIN /* have drain feature */
 				DW_CFG_CH_SUSPEND | DW_CFG_CH_DRAIN, 0);
-
+#else
+				DW_CFG_CH_SUSPEND, 0);
+#endif
 		cd->status = DMA_STATUS_IDLE;
 		goto out;
 	}
@@ -470,8 +462,11 @@ static uint32_t dw_dma_fifo_work(void *data, uint32_t udelay)
 
 			/* clear suspend */
 			dw_update_bits(dma, DW_CFG_LOW(cd->channel),
+#ifdef DW_CFG_CH_DRAIN /* have drain feature */
 				DW_CFG_CH_SUSPEND | DW_CFG_CH_DRAIN, 0);
-
+#else
+				DW_CFG_CH_SUSPEND, 0);
+#endif
 			/* do we need to free it ? */
 			if (cd->status == DMA_STATUS_CLOSING)
 				dw_dma_channel_put_unlocked(dma, cd->channel);
@@ -512,15 +507,17 @@ static int dw_dma_stop(struct dma *dma, int channel, int drain)
 	}
 
 	/* suspend and drain */
+	bits = DW_CFG_CH_SUSPEND;
+	p->chan[channel].drain_count = 3;
+	p->chan[channel].status = DMA_STATUS_STOPPING;
+
+#ifdef DW_CFG_CH_DRAIN /* have drain feature, then may drain */
 	if (drain) {
-		bits = DW_CFG_CH_SUSPEND | DW_CFG_CH_DRAIN;
+		bits |= DW_CFG_CH_DRAIN;
 		p->chan[channel].drain_count = 14;
 		p->chan[channel].status = DMA_STATUS_DRAINING;
-	} else {
-		bits = DW_CFG_CH_SUSPEND;
-		p->chan[channel].drain_count = 3;
-		p->chan[channel].status = DMA_STATUS_STOPPING;
 	}
+#endif
 
 	dw_update_bits(dma, DW_CFG_LOW(channel), bits, bits);
 	schedule = 1;
@@ -568,8 +565,8 @@ static int dw_dma_set_config(struct dma *dma, int channel,
 
 	/* default channel config */
 	p->chan[channel].direction = config->direction;
-	p->chan[channel].cfg_lo = 0x00000003;
-	p->chan[channel].cfg_hi = 0x0;
+	p->chan[channel].cfg_lo = DW_CFG_LOW_DEF;
+	p->chan[channel].cfg_hi = DW_CFG_HIGH_DEF;
 
 	/* get number of SG elems */
 	list_for_item(plist, &config->elem_list)
@@ -666,9 +663,19 @@ static int dw_dma_set_config(struct dma *dma, int channel,
 			break;
 		}
 
+		if (sg_elem->size > DW_CTLH_BLOCK_TS_MASK) {
+				trace_dma_error("eDS");
+				return -EINVAL;
+		}
 		/* set transfer size of element */
+#if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL
 		lli_desc->ctrl_hi = DW_CTLH_CLASS(p->class) |
 			(sg_elem->size & DW_CTLH_BLOCK_TS_MASK);
+#else
+		/* for the unit is transaction--TR_WIDTH. */
+		lli_desc->ctrl_hi = (sg_elem->size / (1 << (lli_desc->ctrl_lo >> 4 & 0x7)))
+			& DW_CTLH_BLOCK_TS_MASK;
+#endif
 
 		/* set next descriptor in list */
 		lli_desc->llp = (uint32_t)(lli_desc + 1);
@@ -768,8 +775,14 @@ static inline void dw_dma_chan_reload_next(struct dma *dma, int channel,
 	dw_write(dma, DW_DAR(channel), next->dest);
 
 	/* set transfer size of element */
+#if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL
 	lli->ctrl_hi = DW_CTLH_CLASS(p->class) |
 		(next->size & DW_CTLH_BLOCK_TS_MASK);
+#else
+	/* for the unit is transaction--TR_WIDTH. */
+	lli->ctrl_hi = (next->size / (1 << (lli->ctrl_lo >> 4 & 0x7)))
+		& DW_CTLH_BLOCK_TS_MASK;
+#endif
 
 	/* program CTLn */
 	dw_write(dma, DW_CTRL_LOW(channel), lli->ctrl_lo);
@@ -872,16 +885,38 @@ static void dw_dma_setup(struct dma *dma)
 	struct dw_drv_plat_data *dp = dma->plat_data.drv_plat_data;
 	int i;
 
+	/* we cannot config DMAC if DMAC has been already enabled by host */
+	if (dw_read(dma, DW_DMA_CFG) != 0)
+		dw_write(dma, DW_DMA_CFG, 0x0);
+
+	/* now check that it's 0 */
+	for (i = DW_DMA_CFG_TRIES; i > 0; i--) {
+		if (dw_read(dma, DW_DMA_CFG) == 0)
+			goto found;
+	}
+	trace_dma_error("eDs");
+	return;
+
+found:
+	for (i = 0; i <  DW_MAX_CHAN; i++)
+		dw_read(dma, DW_DMA_CHAN_EN);
+
+#ifdef HAVE_HDDA
+	/* enable HDDA before DMAC */
+	shim_write(SHIM_HMDC, SHIM_HMDC_HDDA_ALLCH);
+#endif
+
 	/* enable the DMA controller */
 	dw_write(dma, DW_DMA_CFG, 1);
 
 	/* mask all interrupts for all 8 channels */
-	dw_write(dma, DW_MASK_TFR, 0x0000ff00);
-	dw_write(dma, DW_MASK_BLOCK, 0x0000ff00);
-	dw_write(dma, DW_MASK_SRC_TRAN, 0x0000ff00);
-	dw_write(dma, DW_MASK_DST_TRAN, 0x0000ff00);
-	dw_write(dma, DW_MASK_ERR, 0x0000ff00);
+	dw_write(dma, DW_MASK_TFR, INT_MASK_ALL);
+	dw_write(dma, DW_MASK_BLOCK, INT_MASK_ALL);
+	dw_write(dma, DW_MASK_SRC_TRAN, INT_MASK_ALL);
+	dw_write(dma, DW_MASK_DST_TRAN, INT_MASK_ALL);
+	dw_write(dma, DW_MASK_ERR, INT_MASK_ALL);
 
+#ifdef DW_FIFO_PARTITION
 	/* TODO: we cannot config DMA FIFOs if DMAC has been already */
 	/* allocate FIFO partitions, 128 bytes for each ch */
 	dw_write(dma, DW_FIFO_PART1_LO, 0x100080);
@@ -889,10 +924,15 @@ static void dw_dma_setup(struct dma *dma)
 	dw_write(dma, DW_FIFO_PART0_HI, 0x100080);
 	dw_write(dma, DW_FIFO_PART0_LO, 0x100080 | (1 << 26));
 	dw_write(dma, DW_FIFO_PART0_LO, 0x100080);
+#endif
 
 	/* set channel priorities */
 	for (i = 0; i <  DW_MAX_CHAN; i++) {
+#if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL
 		dw_write(dma, DW_CTRL_HIGH(i), DW_CTLH_CLASS(dp->chan[i].class));
+#else
+		dw_write(dma, DW_CFG_LOW(i), DW_CFG_CLASS(dp->chan[i].class));
+#endif
 	}
 
 }
diff --git a/src/platform/baytrail/include/platform/dma.h b/src/platform/baytrail/include/platform/dma.h
index eec501a..5f5c52a 100644
--- a/src/platform/baytrail/include/platform/dma.h
+++ b/src/platform/baytrail/include/platform/dma.h
@@ -38,6 +38,32 @@
 #define DMA_ID_DMAC1	1
 #define DMA_ID_DMAC2	2
 
+/* baytrail specific registers */
+/* CTL_LO */
+#define DW_CTLL_S_GATH_EN		(1 << 17)
+#define DW_CTLL_D_SCAT_EN		(1 << 18)
+/* CTL_HI */
+#define DW_CTLH_DONE			0x00020000
+#define DW_CTLH_BLOCK_TS_MASK		0x0001ffff
+#define DW_CTLH_CLASS(x)		(x << 29)
+#define DW_CTLH_WEIGHT(x)		(x << 18)
+/* CFG_LO */
+#define DW_CFG_CH_DRAIN			0x400
+/* CFG_HI */
+#define DW_CFGH_SRC_PER(x)		(x << 0)
+#define DW_CFGH_DST_PER(x)		(x << 4)
+/* FIFO Partition */
+#define DW_FIFO_PARTITION
+#define DW_FIFO_PART0_LO		0x0400
+#define DW_FIFO_PART0_HI		0x0404
+#define DW_FIFO_PART1_LO		0x0408
+#define DW_FIFO_PART1_HI		0x040C
+#define DW_CH_SAI_ERR			0x0410
+
+/* default initial setup register values */
+#define DW_CFG_LOW_DEF	0x00000003
+#define DW_CFG_HIGH_DEF	0x0
+
 #define DMA_HANDSHAKE_SSP0_RX	0
 #define DMA_HANDSHAKE_SSP0_TX	1
 #define DMA_HANDSHAKE_SSP1_RX	2
-- 
2.11.0



More information about the Sound-open-firmware mailing list