[PATCH 4/8] dmaengine: tegra: Use struct for register offsets

Akhil R posted 8 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH 4/8] dmaengine: tegra: Use struct for register offsets
Posted by Akhil R 1 month, 2 weeks ago
Repurpose tegra_dma_channel_regs struct to define offsets for all the
channel registers. Previously, the struct only held the register values
for each transfer and was wrapped within tegra_dma_sg_req. Now, let
struct tegra_dma_sg_req hold the values directly and use channel_regs
for storing the register offsets. Update all register read/write to use
channel_regs struct. This is to accommodate the register offset change
in Tegra264.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
 drivers/dma/tegra186-gpc-dma.c | 280 +++++++++++++++++----------------
 1 file changed, 147 insertions(+), 133 deletions(-)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 236a298c26a1..72701b543ceb 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -22,7 +22,6 @@
 #include "virt-dma.h"
 
 /* CSR register */
-#define TEGRA_GPCDMA_CHAN_CSR			0x00
 #define TEGRA_GPCDMA_CSR_ENB			BIT(31)
 #define TEGRA_GPCDMA_CSR_IE_EOC			BIT(30)
 #define TEGRA_GPCDMA_CSR_ONCE			BIT(27)
@@ -58,7 +57,6 @@
 #define TEGRA_GPCDMA_CSR_WEIGHT			GENMASK(13, 10)
 
 /* STATUS register */
-#define TEGRA_GPCDMA_CHAN_STATUS		0x004
 #define TEGRA_GPCDMA_STATUS_BUSY		BIT(31)
 #define TEGRA_GPCDMA_STATUS_ISE_EOC		BIT(30)
 #define TEGRA_GPCDMA_STATUS_PING_PONG		BIT(28)
@@ -70,22 +68,13 @@
 #define TEGRA_GPCDMA_STATUS_IRQ_STA		BIT(21)
 #define TEGRA_GPCDMA_STATUS_IRQ_TRIG_STA	BIT(20)
 
-#define TEGRA_GPCDMA_CHAN_CSRE			0x008
 #define TEGRA_GPCDMA_CHAN_CSRE_PAUSE		BIT(31)
 
-/* Source address */
-#define TEGRA_GPCDMA_CHAN_SRC_PTR		0x00C
-
-/* Destination address */
-#define TEGRA_GPCDMA_CHAN_DST_PTR		0x010
-
 /* High address pointer */
-#define TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR		0x014
 #define TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR		GENMASK(7, 0)
 #define TEGRA_GPCDMA_HIGH_ADDR_DST_PTR		GENMASK(23, 16)
 
 /* MC sequence register */
-#define TEGRA_GPCDMA_CHAN_MCSEQ			0x18
 #define TEGRA_GPCDMA_MCSEQ_DATA_SWAP		BIT(31)
 #define TEGRA_GPCDMA_MCSEQ_REQ_COUNT		GENMASK(30, 25)
 #define TEGRA_GPCDMA_MCSEQ_BURST		GENMASK(24, 23)
@@ -101,7 +90,6 @@
 #define TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK	GENMASK(6, 0)
 
 /* MMIO sequence register */
-#define TEGRA_GPCDMA_CHAN_MMIOSEQ			0x01c
 #define TEGRA_GPCDMA_MMIOSEQ_DBL_BUF		BIT(31)
 #define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH		GENMASK(30, 28)
 #define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_8	\
@@ -120,17 +108,7 @@
 #define TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD		GENMASK(18, 16)
 #define TEGRA_GPCDMA_MMIOSEQ_MMIO_PROT		GENMASK(8, 7)
 
-/* Channel WCOUNT */
-#define TEGRA_GPCDMA_CHAN_WCOUNT		0x20
-
-/* Transfer count */
-#define TEGRA_GPCDMA_CHAN_XFER_COUNT		0x24
-
-/* DMA byte count status */
-#define TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS	0x28
-
 /* Error Status Register */
-#define TEGRA_GPCDMA_CHAN_ERR_STATUS		0x30
 #define TEGRA_GPCDMA_CHAN_ERR_TYPE_SHIFT	8
 #define TEGRA_GPCDMA_CHAN_ERR_TYPE_MASK	0xF
 #define TEGRA_GPCDMA_CHAN_ERR_TYPE(err)	(			\
@@ -143,14 +121,9 @@
 #define TEGRA_DMA_MC_SLAVE_ERR			0xB
 #define TEGRA_DMA_MMIO_SLAVE_ERR		0xA
 
-/* Fixed Pattern */
-#define TEGRA_GPCDMA_CHAN_FIXED_PATTERN		0x34
-
-#define TEGRA_GPCDMA_CHAN_TZ			0x38
 #define TEGRA_GPCDMA_CHAN_TZ_MMIO_PROT_1	BIT(0)
 #define TEGRA_GPCDMA_CHAN_TZ_MC_PROT_1		BIT(1)
 
-#define TEGRA_GPCDMA_CHAN_SPARE			0x3c
 #define TEGRA_GPCDMA_CHAN_SPARE_EN_LEGACY_FC	BIT(16)
 
 /*
@@ -181,19 +154,27 @@ struct tegra_dma_chip_data {
 	unsigned int nr_channels;
 	unsigned int channel_reg_size;
 	unsigned int max_dma_count;
+	const struct tegra_dma_channel_regs *channel_regs;
 	int (*terminate)(struct tegra_dma_channel *tdc);
 };
 
 /* DMA channel registers */
 struct tegra_dma_channel_regs {
 	u32 csr;
-	u32 src_ptr;
-	u32 dst_ptr;
-	u32 high_addr_ptr;
+	u32 status;
+	u32 csre;
+	u32 src;
+	u32 dst;
+	u32 high_addr;
 	u32 mc_seq;
 	u32 mmio_seq;
 	u32 wcount;
+	u32 wxfer;
+	u32 wstatus;
+	u32 err_status;
 	u32 fixed_pattern;
+	u32 tz;
+	u32 spare;
 };
 
 /*
@@ -205,7 +186,14 @@ struct tegra_dma_channel_regs {
  */
 struct tegra_dma_sg_req {
 	unsigned int len;
-	struct tegra_dma_channel_regs ch_regs;
+	u32 csr;
+	u32 src;
+	u32 dst;
+	u32 high_addr;
+	u32 mc_seq;
+	u32 mmio_seq;
+	u32 wcount;
+	u32 fixed_pattern;
 };
 
 /*
@@ -228,19 +216,20 @@ struct tegra_dma_desc {
  * tegra_dma_channel: Channel specific information
  */
 struct tegra_dma_channel {
-	bool config_init;
-	char name[30];
-	enum dma_transfer_direction sid_dir;
-	enum dma_status status;
-	int id;
-	int irq;
-	int slave_id;
+	const struct tegra_dma_channel_regs *regs;
 	struct tegra_dma *tdma;
 	struct virt_dma_chan vc;
 	struct tegra_dma_desc *dma_desc;
 	struct dma_slave_config dma_sconfig;
+	enum dma_transfer_direction sid_dir;
+	enum dma_status status;
 	unsigned int stream_id;
 	unsigned long chan_base_offset;
+	bool config_init;
+	char name[30];
+	int id;
+	int irq;
+	int slave_id;
 };
 
 /*
@@ -288,22 +277,25 @@ static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
 {
 	dev_dbg(tdc2dev(tdc), "DMA Channel %d name %s register dump:\n",
 		tdc->id, tdc->name);
-	dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x SRC %x DST %x\n",
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_DST_PTR)
+	dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x\n",
+		tdc_read(tdc, tdc->regs->csr),
+		tdc_read(tdc, tdc->regs->status),
+		tdc_read(tdc, tdc->regs->csre)
 	);
-	dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x BSTA %x\n",
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_WCOUNT),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT),
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS)
+	dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
+		tdc_read(tdc, tdc->regs->src),
+		tdc_read(tdc, tdc->regs->dst),
+		tdc_read(tdc, tdc->regs->high_addr)
+	);
+	dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x WSTA %x\n",
+		tdc_read(tdc, tdc->regs->mc_seq),
+		tdc_read(tdc, tdc->regs->mmio_seq),
+		tdc_read(tdc, tdc->regs->wcount),
+		tdc_read(tdc, tdc->regs->wxfer),
+		tdc_read(tdc, tdc->regs->wstatus)
 	);
 	dev_dbg(tdc2dev(tdc), "DMA ERR_STA %x\n",
-		tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS));
+		tdc_read(tdc, tdc->regs->err_status));
 }
 
 static int tegra_dma_sid_reserve(struct tegra_dma_channel *tdc,
@@ -377,13 +369,13 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc)
 	int ret;
 	u32 val;
 
-	val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
+	val = tdc_read(tdc, tdc->regs->csre);
 	val |= TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
+	tdc_write(tdc, tdc->regs->csre, val);
 
 	/* Wait until busy bit is de-asserted */
 	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
-			tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
+			tdc->chan_base_offset + tdc->regs->status,
 			val,
 			!(val & TEGRA_GPCDMA_STATUS_BUSY),
 			TEGRA_GPCDMA_BURST_COMPLETE_TIME,
@@ -419,9 +411,9 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc)
 {
 	u32 val;
 
-	val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
+	val = tdc_read(tdc, tdc->regs->csre);
 	val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
+	tdc_write(tdc, tdc->regs->csre, val);
 
 	tdc->status = DMA_IN_PROGRESS;
 }
@@ -456,27 +448,27 @@ static void tegra_dma_disable(struct tegra_dma_channel *tdc)
 {
 	u32 csr, status;
 
-	csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
+	csr = tdc_read(tdc, tdc->regs->csr);
 
 	/* Disable interrupts */
 	csr &= ~TEGRA_GPCDMA_CSR_IE_EOC;
 
 	/* Disable DMA */
 	csr &= ~TEGRA_GPCDMA_CSR_ENB;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
+	tdc_write(tdc, tdc->regs->csr, csr);
 
 	/* Clear interrupt status if it is there */
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+	status = tdc_read(tdc, tdc->regs->status);
 	if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) {
 		dev_dbg(tdc2dev(tdc), "%s():clearing interrupt\n", __func__);
-		tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, status);
+		tdc_write(tdc, tdc->regs->status, status);
 	}
 }
 
 static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
 {
 	struct tegra_dma_desc *dma_desc = tdc->dma_desc;
-	struct tegra_dma_channel_regs *ch_regs;
+	struct tegra_dma_sg_req *sg_req;
 	int ret;
 	u32 val;
 
@@ -488,29 +480,29 @@ static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
 
 	/* Configure next transfer immediately after DMA is busy */
 	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
-			tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
+			tdc->chan_base_offset + tdc->regs->status,
 			val,
 			(val & TEGRA_GPCDMA_STATUS_BUSY), 0,
 			TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT);
 	if (ret)
 		return;
 
-	ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
+	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
+	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
+	tdc_write(tdc, tdc->regs->src, sg_req->src);
+	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
+	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
 
 	/* Start DMA */
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
-		  ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
+	tdc_write(tdc, tdc->regs->csr,
+		  sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
 }
 
 static void tegra_dma_start(struct tegra_dma_channel *tdc)
 {
 	struct tegra_dma_desc *dma_desc = tdc->dma_desc;
-	struct tegra_dma_channel_regs *ch_regs;
+	struct tegra_dma_sg_req *sg_req;
 	struct virt_dma_desc *vdesc;
 
 	if (!dma_desc) {
@@ -526,21 +518,21 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc)
 		tegra_dma_resume(tdc);
 	}
 
-	ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
+	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, 0);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_FIXED_PATTERN, ch_regs->fixed_pattern);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ, ch_regs->mmio_seq);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, ch_regs->mc_seq);
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, ch_regs->csr);
+	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
+	tdc_write(tdc, tdc->regs->csr, 0);
+	tdc_write(tdc, tdc->regs->src, sg_req->src);
+	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
+	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
+	tdc_write(tdc, tdc->regs->fixed_pattern, sg_req->fixed_pattern);
+	tdc_write(tdc, tdc->regs->mmio_seq, sg_req->mmio_seq);
+	tdc_write(tdc, tdc->regs->mc_seq, sg_req->mc_seq);
+	tdc_write(tdc, tdc->regs->csr, sg_req->csr);
 
 	/* Start DMA */
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
-		  ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
+	tdc_write(tdc, tdc->regs->csr,
+		  sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
 }
 
 static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc)
@@ -601,19 +593,19 @@ static irqreturn_t tegra_dma_isr(int irq, void *dev_id)
 	u32 status;
 
 	/* Check channel error status register */
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS);
+	status = tdc_read(tdc, tdc->regs->err_status);
 	if (status) {
 		tegra_dma_chan_decode_error(tdc, status);
 		tegra_dma_dump_chan_regs(tdc);
-		tdc_write(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS, 0xFFFFFFFF);
+		tdc_write(tdc, tdc->regs->err_status, 0xFFFFFFFF);
 	}
 
 	spin_lock(&tdc->vc.lock);
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+	status = tdc_read(tdc, tdc->regs->status);
 	if (!(status & TEGRA_GPCDMA_STATUS_ISE_EOC))
 		goto irq_done;
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS,
+	tdc_write(tdc, tdc->regs->status,
 		  TEGRA_GPCDMA_STATUS_ISE_EOC);
 
 	if (!dma_desc)
@@ -673,10 +665,10 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
 	 * to stop DMA engine from starting any more bursts for
 	 * the given client and wait for in flight bursts to complete
 	 */
-	csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
+	csr = tdc_read(tdc, tdc->regs->csr);
 	csr &= ~(TEGRA_GPCDMA_CSR_REQ_SEL_MASK);
 	csr |= TEGRA_GPCDMA_CSR_REQ_SEL_UNUSED;
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
+	tdc_write(tdc, tdc->regs->csr, csr);
 
 	/* Wait for in flight data transfer to finish */
 	udelay(TEGRA_GPCDMA_BURST_COMPLETE_TIME);
@@ -687,7 +679,7 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
 
 	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
 				tdc->chan_base_offset +
-				TEGRA_GPCDMA_CHAN_STATUS,
+				tdc->regs->status,
 				status,
 				!(status & (TEGRA_GPCDMA_STATUS_CHANNEL_TX |
 				TEGRA_GPCDMA_STATUS_CHANNEL_RX)),
@@ -739,14 +731,14 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
 	unsigned int bytes_xfer, residual;
 	u32 wcount = 0, status;
 
-	wcount = tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT);
+	wcount = tdc_read(tdc, tdc->regs->wxfer);
 
 	/*
 	 * Set wcount = 0 if EOC bit is set. The transfer would have
 	 * already completed and the CHAN_XFER_COUNT could have updated
 	 * for the next transfer, specifically in case of cyclic transfers.
 	 */
-	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+	status = tdc_read(tdc, tdc->regs->status);
 	if (status & TEGRA_GPCDMA_STATUS_ISE_EOC)
 		wcount = 0;
 
@@ -893,7 +885,7 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
 	/* Configure default priority weight for the channel */
 	csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
 
@@ -916,16 +908,16 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
 	dma_desc->sg_count = 1;
 	sg_req = dma_desc->sg_req;
 
-	sg_req[0].ch_regs.src_ptr = 0;
-	sg_req[0].ch_regs.dst_ptr = dest;
-	sg_req[0].ch_regs.high_addr_ptr =
+	sg_req[0].src = 0;
+	sg_req[0].dst = dest;
+	sg_req[0].high_addr =
 			FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
-	sg_req[0].ch_regs.fixed_pattern = value;
+	sg_req[0].fixed_pattern = value;
 	/* Word count reg takes value as (N +1) words */
-	sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
-	sg_req[0].ch_regs.csr = csr;
-	sg_req[0].ch_regs.mmio_seq = 0;
-	sg_req[0].ch_regs.mc_seq = mc_seq;
+	sg_req[0].wcount = ((len - 4) >> 2);
+	sg_req[0].csr = csr;
+	sg_req[0].mmio_seq = 0;
+	sg_req[0].mc_seq = mc_seq;
 	sg_req[0].len = len;
 
 	dma_desc->cyclic = false;
@@ -961,7 +953,7 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
 	/* Configure default priority weight for the channel */
 	csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= (TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK) |
 		  (TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
@@ -985,17 +977,17 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
 	dma_desc->sg_count = 1;
 	sg_req = dma_desc->sg_req;
 
-	sg_req[0].ch_regs.src_ptr = src;
-	sg_req[0].ch_regs.dst_ptr = dest;
-	sg_req[0].ch_regs.high_addr_ptr =
+	sg_req[0].src = src;
+	sg_req[0].dst = dest;
+	sg_req[0].high_addr =
 		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (src >> 32));
-	sg_req[0].ch_regs.high_addr_ptr |=
+	sg_req[0].high_addr |=
 		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
 	/* Word count reg takes value as (N +1) words */
-	sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
-	sg_req[0].ch_regs.csr = csr;
-	sg_req[0].ch_regs.mmio_seq = 0;
-	sg_req[0].ch_regs.mc_seq = mc_seq;
+	sg_req[0].wcount = ((len - 4) >> 2);
+	sg_req[0].csr = csr;
+	sg_req[0].mmio_seq = 0;
+	sg_req[0].mc_seq = mc_seq;
 	sg_req[0].len = len;
 
 	dma_desc->cyclic = false;
@@ -1049,7 +1041,7 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 	if (flags & DMA_PREP_INTERRUPT)
 		csr |= TEGRA_GPCDMA_CSR_IE_EOC;
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
 
@@ -1096,14 +1088,14 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 		dma_desc->bytes_req += len;
 
 		if (direction == DMA_MEM_TO_DEV) {
-			sg_req[i].ch_regs.src_ptr = mem;
-			sg_req[i].ch_regs.dst_ptr = apb_ptr;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = mem;
+			sg_req[i].dst = apb_ptr;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
 		} else if (direction == DMA_DEV_TO_MEM) {
-			sg_req[i].ch_regs.src_ptr = apb_ptr;
-			sg_req[i].ch_regs.dst_ptr = mem;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = apb_ptr;
+			sg_req[i].dst = mem;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
 		}
 
@@ -1111,10 +1103,10 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
 		 * Word count register takes input in words. Writing a value
 		 * of N into word count register means a req of (N+1) words.
 		 */
-		sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
-		sg_req[i].ch_regs.csr = csr;
-		sg_req[i].ch_regs.mmio_seq = mmio_seq;
-		sg_req[i].ch_regs.mc_seq = mc_seq;
+		sg_req[i].wcount = ((len - 4) >> 2);
+		sg_req[i].csr = csr;
+		sg_req[i].mmio_seq = mmio_seq;
+		sg_req[i].mc_seq = mc_seq;
 		sg_req[i].len = len;
 	}
 
@@ -1186,7 +1178,7 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
 
 	mmio_seq |= FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD, 1);
 
-	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
 	/* retain stream-id and clean rest */
 	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
 
@@ -1218,24 +1210,24 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
 	for (i = 0; i < period_count; i++) {
 		mmio_seq |= get_burst_size(tdc, burst_size, slave_bw, len);
 		if (direction == DMA_MEM_TO_DEV) {
-			sg_req[i].ch_regs.src_ptr = mem;
-			sg_req[i].ch_regs.dst_ptr = apb_ptr;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = mem;
+			sg_req[i].dst = apb_ptr;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
 		} else if (direction == DMA_DEV_TO_MEM) {
-			sg_req[i].ch_regs.src_ptr = apb_ptr;
-			sg_req[i].ch_regs.dst_ptr = mem;
-			sg_req[i].ch_regs.high_addr_ptr =
+			sg_req[i].src = apb_ptr;
+			sg_req[i].dst = mem;
+			sg_req[i].high_addr =
 				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
 		}
 		/*
 		 * Word count register takes input in words. Writing a value
 		 * of N into word count register means a req of (N+1) words.
 		 */
-		sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
-		sg_req[i].ch_regs.csr = csr;
-		sg_req[i].ch_regs.mmio_seq = mmio_seq;
-		sg_req[i].ch_regs.mc_seq = mc_seq;
+		sg_req[i].wcount = ((len - 4) >> 2);
+		sg_req[i].csr = csr;
+		sg_req[i].mmio_seq = mmio_seq;
+		sg_req[i].mc_seq = mc_seq;
 		sg_req[i].len = len;
 
 		mem += len;
@@ -1305,11 +1297,30 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
 	return chan;
 }
 
+static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
+	.csr = 0x0,
+	.status = 0x4,
+	.csre = 0x8,
+	.src = 0xc,
+	.dst = 0x10,
+	.high_addr = 0x14,
+	.mc_seq = 0x18,
+	.mmio_seq = 0x1c,
+	.wcount = 0x20,
+	.wxfer = 0x24,
+	.wstatus = 0x28,
+	.err_status = 0x30,
+	.fixed_pattern = 0x34,
+	.tz = 0x38,
+	.spare = 0x40,
+};
+
 static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
 	.nr_channels = 32,
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = false,
+	.channel_regs = &tegra186_reg_offsets,
 	.terminate = tegra_dma_stop_client,
 };
 
@@ -1318,6 +1329,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = true,
+	.channel_regs = &tegra186_reg_offsets,
 	.terminate = tegra_dma_pause,
 };
 
@@ -1326,6 +1338,7 @@ static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
 	.channel_reg_size = SZ_64K,
 	.max_dma_count = SZ_1G,
 	.hw_support_pause = true,
+	.channel_regs = &tegra186_reg_offsets,
 	.terminate = tegra_dma_pause_noerr,
 };
 
@@ -1346,7 +1359,7 @@ MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
 
 static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
 {
-	unsigned int reg_val =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+	unsigned int reg_val =  tdc_read(tdc, tdc->regs->mc_seq);
 
 	reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK);
 	reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
@@ -1354,7 +1367,7 @@ static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
 	reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK, stream_id);
 	reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK, stream_id);
 
-	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, reg_val);
+	tdc_write(tdc, tdc->regs->mc_seq, reg_val);
 	return 0;
 }
 
@@ -1420,6 +1433,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
 		tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET +
 					i * cdata->channel_reg_size;
 		snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i);
+		tdc->regs = cdata->channel_regs;
 		tdc->tdma = tdma;
 		tdc->id = i;
 		tdc->slave_id = -1;
-- 
2.50.1
Re: [PATCH 4/8] dmaengine: tegra: Use struct for register offsets
Posted by Frank Li 1 month, 2 weeks ago
On Tue, Feb 17, 2026 at 11:04:53PM +0530, Akhil R wrote:
> Repurpose tegra_dma_channel_regs struct to define offsets for all the
> channel registers. Previously, the struct only held the register values
> for each transfer and was wrapped within tegra_dma_sg_req. Now, let
> struct tegra_dma_sg_req hold the values directly and use channel_regs
> for storing the register offsets. Update all register read/write to use
> channel_regs struct. This is to accommodate the register offset change
> in Tegra264.
>
> Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
>  drivers/dma/tegra186-gpc-dma.c | 280 +++++++++++++++++----------------
>  1 file changed, 147 insertions(+), 133 deletions(-)
>
> diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
> index 236a298c26a1..72701b543ceb 100644
> --- a/drivers/dma/tegra186-gpc-dma.c
> +++ b/drivers/dma/tegra186-gpc-dma.c
> @@ -22,7 +22,6 @@
>  #include "virt-dma.h"
>
>  /* CSR register */
> -#define TEGRA_GPCDMA_CHAN_CSR			0x00
>  #define TEGRA_GPCDMA_CSR_ENB			BIT(31)
>  #define TEGRA_GPCDMA_CSR_IE_EOC			BIT(30)
>  #define TEGRA_GPCDMA_CSR_ONCE			BIT(27)
> @@ -58,7 +57,6 @@
>  #define TEGRA_GPCDMA_CSR_WEIGHT			GENMASK(13, 10)
>
>  /* STATUS register */
> -#define TEGRA_GPCDMA_CHAN_STATUS		0x004
>  #define TEGRA_GPCDMA_STATUS_BUSY		BIT(31)
>  #define TEGRA_GPCDMA_STATUS_ISE_EOC		BIT(30)
>  #define TEGRA_GPCDMA_STATUS_PING_PONG		BIT(28)
> @@ -70,22 +68,13 @@
>  #define TEGRA_GPCDMA_STATUS_IRQ_STA		BIT(21)
>  #define TEGRA_GPCDMA_STATUS_IRQ_TRIG_STA	BIT(20)
>
> -#define TEGRA_GPCDMA_CHAN_CSRE			0x008
>  #define TEGRA_GPCDMA_CHAN_CSRE_PAUSE		BIT(31)
>
> -/* Source address */
> -#define TEGRA_GPCDMA_CHAN_SRC_PTR		0x00C
> -
> -/* Destination address */
> -#define TEGRA_GPCDMA_CHAN_DST_PTR		0x010
> -
>  /* High address pointer */
> -#define TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR		0x014
>  #define TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR		GENMASK(7, 0)
>  #define TEGRA_GPCDMA_HIGH_ADDR_DST_PTR		GENMASK(23, 16)
>
>  /* MC sequence register */
> -#define TEGRA_GPCDMA_CHAN_MCSEQ			0x18
>  #define TEGRA_GPCDMA_MCSEQ_DATA_SWAP		BIT(31)
>  #define TEGRA_GPCDMA_MCSEQ_REQ_COUNT		GENMASK(30, 25)
>  #define TEGRA_GPCDMA_MCSEQ_BURST		GENMASK(24, 23)
> @@ -101,7 +90,6 @@
>  #define TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK	GENMASK(6, 0)
>
>  /* MMIO sequence register */
> -#define TEGRA_GPCDMA_CHAN_MMIOSEQ			0x01c
>  #define TEGRA_GPCDMA_MMIOSEQ_DBL_BUF		BIT(31)
>  #define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH		GENMASK(30, 28)
>  #define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_8	\
> @@ -120,17 +108,7 @@
>  #define TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD		GENMASK(18, 16)
>  #define TEGRA_GPCDMA_MMIOSEQ_MMIO_PROT		GENMASK(8, 7)
>
> -/* Channel WCOUNT */
> -#define TEGRA_GPCDMA_CHAN_WCOUNT		0x20
> -
> -/* Transfer count */
> -#define TEGRA_GPCDMA_CHAN_XFER_COUNT		0x24
> -
> -/* DMA byte count status */
> -#define TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS	0x28
> -
>  /* Error Status Register */
> -#define TEGRA_GPCDMA_CHAN_ERR_STATUS		0x30
>  #define TEGRA_GPCDMA_CHAN_ERR_TYPE_SHIFT	8
>  #define TEGRA_GPCDMA_CHAN_ERR_TYPE_MASK	0xF
>  #define TEGRA_GPCDMA_CHAN_ERR_TYPE(err)	(			\
> @@ -143,14 +121,9 @@
>  #define TEGRA_DMA_MC_SLAVE_ERR			0xB
>  #define TEGRA_DMA_MMIO_SLAVE_ERR		0xA
>
> -/* Fixed Pattern */
> -#define TEGRA_GPCDMA_CHAN_FIXED_PATTERN		0x34
> -
> -#define TEGRA_GPCDMA_CHAN_TZ			0x38
>  #define TEGRA_GPCDMA_CHAN_TZ_MMIO_PROT_1	BIT(0)
>  #define TEGRA_GPCDMA_CHAN_TZ_MC_PROT_1		BIT(1)
>
> -#define TEGRA_GPCDMA_CHAN_SPARE			0x3c
>  #define TEGRA_GPCDMA_CHAN_SPARE_EN_LEGACY_FC	BIT(16)
>
>  /*
> @@ -181,19 +154,27 @@ struct tegra_dma_chip_data {
>  	unsigned int nr_channels;
>  	unsigned int channel_reg_size;
>  	unsigned int max_dma_count;
> +	const struct tegra_dma_channel_regs *channel_regs;
>  	int (*terminate)(struct tegra_dma_channel *tdc);
>  };
>
>  /* DMA channel registers */
>  struct tegra_dma_channel_regs {
>  	u32 csr;
> -	u32 src_ptr;
> -	u32 dst_ptr;
> -	u32 high_addr_ptr;
> +	u32 status;
> +	u32 csre;
> +	u32 src;
> +	u32 dst;
> +	u32 high_addr;
>  	u32 mc_seq;
>  	u32 mmio_seq;
>  	u32 wcount;
> +	u32 wxfer;
> +	u32 wstatus;
> +	u32 err_status;
>  	u32 fixed_pattern;
> +	u32 tz;
> +	u32 spare;
>  };
>
>  /*
> @@ -205,7 +186,14 @@ struct tegra_dma_channel_regs {
>   */
>  struct tegra_dma_sg_req {
>  	unsigned int len;
> -	struct tegra_dma_channel_regs ch_regs;
> +	u32 csr;
> +	u32 src;
> +	u32 dst;
> +	u32 high_addr;
> +	u32 mc_seq;
> +	u32 mmio_seq;
> +	u32 wcount;
> +	u32 fixed_pattern;
>  };
>
>  /*
> @@ -228,19 +216,20 @@ struct tegra_dma_desc {
>   * tegra_dma_channel: Channel specific information
>   */
>  struct tegra_dma_channel {
> -	bool config_init;
> -	char name[30];
> -	enum dma_transfer_direction sid_dir;
> -	enum dma_status status;
> -	int id;
> -	int irq;
> -	int slave_id;
> +	const struct tegra_dma_channel_regs *regs;
>  	struct tegra_dma *tdma;
>  	struct virt_dma_chan vc;
>  	struct tegra_dma_desc *dma_desc;
>  	struct dma_slave_config dma_sconfig;
> +	enum dma_transfer_direction sid_dir;
> +	enum dma_status status;
>  	unsigned int stream_id;
>  	unsigned long chan_base_offset;
> +	bool config_init;
> +	char name[30];
> +	int id;
> +	int irq;
> +	int slave_id;
>  };
>
>  /*
> @@ -288,22 +277,25 @@ static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
>  {
>  	dev_dbg(tdc2dev(tdc), "DMA Channel %d name %s register dump:\n",
>  		tdc->id, tdc->name);
> -	dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x SRC %x DST %x\n",
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_DST_PTR)
> +	dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x\n",
> +		tdc_read(tdc, tdc->regs->csr),
> +		tdc_read(tdc, tdc->regs->status),
> +		tdc_read(tdc, tdc->regs->csre)
>  	);
> -	dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x BSTA %x\n",
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_WCOUNT),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT),
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS)
> +	dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
> +		tdc_read(tdc, tdc->regs->src),
> +		tdc_read(tdc, tdc->regs->dst),
> +		tdc_read(tdc, tdc->regs->high_addr)
> +	);
> +	dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x WSTA %x\n",
> +		tdc_read(tdc, tdc->regs->mc_seq),
> +		tdc_read(tdc, tdc->regs->mmio_seq),
> +		tdc_read(tdc, tdc->regs->wcount),
> +		tdc_read(tdc, tdc->regs->wxfer),
> +		tdc_read(tdc, tdc->regs->wstatus)
>  	);
>  	dev_dbg(tdc2dev(tdc), "DMA ERR_STA %x\n",
> -		tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS));
> +		tdc_read(tdc, tdc->regs->err_status));
>  }
>
>  static int tegra_dma_sid_reserve(struct tegra_dma_channel *tdc,
> @@ -377,13 +369,13 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc)
>  	int ret;
>  	u32 val;
>
> -	val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
> +	val = tdc_read(tdc, tdc->regs->csre);
>  	val |= TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
> +	tdc_write(tdc, tdc->regs->csre, val);
>
>  	/* Wait until busy bit is de-asserted */
>  	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
> -			tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
> +			tdc->chan_base_offset + tdc->regs->status,
>  			val,
>  			!(val & TEGRA_GPCDMA_STATUS_BUSY),
>  			TEGRA_GPCDMA_BURST_COMPLETE_TIME,
> @@ -419,9 +411,9 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc)
>  {
>  	u32 val;
>
> -	val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
> +	val = tdc_read(tdc, tdc->regs->csre);
>  	val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
> +	tdc_write(tdc, tdc->regs->csre, val);
>
>  	tdc->status = DMA_IN_PROGRESS;
>  }
> @@ -456,27 +448,27 @@ static void tegra_dma_disable(struct tegra_dma_channel *tdc)
>  {
>  	u32 csr, status;
>
> -	csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
> +	csr = tdc_read(tdc, tdc->regs->csr);
>
>  	/* Disable interrupts */
>  	csr &= ~TEGRA_GPCDMA_CSR_IE_EOC;
>
>  	/* Disable DMA */
>  	csr &= ~TEGRA_GPCDMA_CSR_ENB;
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
> +	tdc_write(tdc, tdc->regs->csr, csr);
>
>  	/* Clear interrupt status if it is there */
> -	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
> +	status = tdc_read(tdc, tdc->regs->status);
>  	if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) {
>  		dev_dbg(tdc2dev(tdc), "%s():clearing interrupt\n", __func__);
> -		tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, status);
> +		tdc_write(tdc, tdc->regs->status, status);
>  	}
>  }
>
>  static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
>  {
>  	struct tegra_dma_desc *dma_desc = tdc->dma_desc;
> -	struct tegra_dma_channel_regs *ch_regs;
> +	struct tegra_dma_sg_req *sg_req;
>  	int ret;
>  	u32 val;
>
> @@ -488,29 +480,29 @@ static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
>
>  	/* Configure next transfer immediately after DMA is busy */
>  	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
> -			tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
> +			tdc->chan_base_offset + tdc->regs->status,
>  			val,
>  			(val & TEGRA_GPCDMA_STATUS_BUSY), 0,
>  			TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT);
>  	if (ret)
>  		return;
>
> -	ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
> +	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
>
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
> +	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
> +	tdc_write(tdc, tdc->regs->src, sg_req->src);
> +	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
> +	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
>
>  	/* Start DMA */
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
> -		  ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
> +	tdc_write(tdc, tdc->regs->csr,
> +		  sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
>  }
>
>  static void tegra_dma_start(struct tegra_dma_channel *tdc)
>  {
>  	struct tegra_dma_desc *dma_desc = tdc->dma_desc;
> -	struct tegra_dma_channel_regs *ch_regs;
> +	struct tegra_dma_sg_req *sg_req;
>  	struct virt_dma_desc *vdesc;
>
>  	if (!dma_desc) {
> @@ -526,21 +518,21 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc)
>  		tegra_dma_resume(tdc);
>  	}
>
> -	ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
> +	sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
>
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, 0);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_FIXED_PATTERN, ch_regs->fixed_pattern);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ, ch_regs->mmio_seq);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, ch_regs->mc_seq);
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, ch_regs->csr);
> +	tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
> +	tdc_write(tdc, tdc->regs->csr, 0);
> +	tdc_write(tdc, tdc->regs->src, sg_req->src);
> +	tdc_write(tdc, tdc->regs->dst, sg_req->dst);
> +	tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
> +	tdc_write(tdc, tdc->regs->fixed_pattern, sg_req->fixed_pattern);
> +	tdc_write(tdc, tdc->regs->mmio_seq, sg_req->mmio_seq);
> +	tdc_write(tdc, tdc->regs->mc_seq, sg_req->mc_seq);
> +	tdc_write(tdc, tdc->regs->csr, sg_req->csr);
>
>  	/* Start DMA */
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
> -		  ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
> +	tdc_write(tdc, tdc->regs->csr,
> +		  sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
>  }
>
>  static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc)
> @@ -601,19 +593,19 @@ static irqreturn_t tegra_dma_isr(int irq, void *dev_id)
>  	u32 status;
>
>  	/* Check channel error status register */
> -	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS);
> +	status = tdc_read(tdc, tdc->regs->err_status);
>  	if (status) {
>  		tegra_dma_chan_decode_error(tdc, status);
>  		tegra_dma_dump_chan_regs(tdc);
> -		tdc_write(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS, 0xFFFFFFFF);
> +		tdc_write(tdc, tdc->regs->err_status, 0xFFFFFFFF);
>  	}
>
>  	spin_lock(&tdc->vc.lock);
> -	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
> +	status = tdc_read(tdc, tdc->regs->status);
>  	if (!(status & TEGRA_GPCDMA_STATUS_ISE_EOC))
>  		goto irq_done;
>
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS,
> +	tdc_write(tdc, tdc->regs->status,
>  		  TEGRA_GPCDMA_STATUS_ISE_EOC);
>
>  	if (!dma_desc)
> @@ -673,10 +665,10 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
>  	 * to stop DMA engine from starting any more bursts for
>  	 * the given client and wait for in flight bursts to complete
>  	 */
> -	csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
> +	csr = tdc_read(tdc, tdc->regs->csr);
>  	csr &= ~(TEGRA_GPCDMA_CSR_REQ_SEL_MASK);
>  	csr |= TEGRA_GPCDMA_CSR_REQ_SEL_UNUSED;
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
> +	tdc_write(tdc, tdc->regs->csr, csr);
>
>  	/* Wait for in flight data transfer to finish */
>  	udelay(TEGRA_GPCDMA_BURST_COMPLETE_TIME);
> @@ -687,7 +679,7 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
>
>  	ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
>  				tdc->chan_base_offset +
> -				TEGRA_GPCDMA_CHAN_STATUS,
> +				tdc->regs->status,
>  				status,
>  				!(status & (TEGRA_GPCDMA_STATUS_CHANNEL_TX |
>  				TEGRA_GPCDMA_STATUS_CHANNEL_RX)),
> @@ -739,14 +731,14 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
>  	unsigned int bytes_xfer, residual;
>  	u32 wcount = 0, status;
>
> -	wcount = tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT);
> +	wcount = tdc_read(tdc, tdc->regs->wxfer);
>
>  	/*
>  	 * Set wcount = 0 if EOC bit is set. The transfer would have
>  	 * already completed and the CHAN_XFER_COUNT could have updated
>  	 * for the next transfer, specifically in case of cyclic transfers.
>  	 */
> -	status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
> +	status = tdc_read(tdc, tdc->regs->status);
>  	if (status & TEGRA_GPCDMA_STATUS_ISE_EOC)
>  		wcount = 0;
>
> @@ -893,7 +885,7 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
>  	/* Configure default priority weight for the channel */
>  	csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
>
> -	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
> +	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
>  	/* retain stream-id and clean rest */
>  	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
>
> @@ -916,16 +908,16 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
>  	dma_desc->sg_count = 1;
>  	sg_req = dma_desc->sg_req;
>
> -	sg_req[0].ch_regs.src_ptr = 0;
> -	sg_req[0].ch_regs.dst_ptr = dest;
> -	sg_req[0].ch_regs.high_addr_ptr =
> +	sg_req[0].src = 0;
> +	sg_req[0].dst = dest;
> +	sg_req[0].high_addr =
>  			FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
> -	sg_req[0].ch_regs.fixed_pattern = value;
> +	sg_req[0].fixed_pattern = value;
>  	/* Word count reg takes value as (N +1) words */
> -	sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
> -	sg_req[0].ch_regs.csr = csr;
> -	sg_req[0].ch_regs.mmio_seq = 0;
> -	sg_req[0].ch_regs.mc_seq = mc_seq;
> +	sg_req[0].wcount = ((len - 4) >> 2);
> +	sg_req[0].csr = csr;
> +	sg_req[0].mmio_seq = 0;
> +	sg_req[0].mc_seq = mc_seq;
>  	sg_req[0].len = len;
>
>  	dma_desc->cyclic = false;
> @@ -961,7 +953,7 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
>  	/* Configure default priority weight for the channel */
>  	csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
>
> -	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
> +	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
>  	/* retain stream-id and clean rest */
>  	mc_seq &= (TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK) |
>  		  (TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
> @@ -985,17 +977,17 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
>  	dma_desc->sg_count = 1;
>  	sg_req = dma_desc->sg_req;
>
> -	sg_req[0].ch_regs.src_ptr = src;
> -	sg_req[0].ch_regs.dst_ptr = dest;
> -	sg_req[0].ch_regs.high_addr_ptr =
> +	sg_req[0].src = src;
> +	sg_req[0].dst = dest;
> +	sg_req[0].high_addr =
>  		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (src >> 32));
> -	sg_req[0].ch_regs.high_addr_ptr |=
> +	sg_req[0].high_addr |=
>  		FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
>  	/* Word count reg takes value as (N +1) words */
> -	sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
> -	sg_req[0].ch_regs.csr = csr;
> -	sg_req[0].ch_regs.mmio_seq = 0;
> -	sg_req[0].ch_regs.mc_seq = mc_seq;
> +	sg_req[0].wcount = ((len - 4) >> 2);
> +	sg_req[0].csr = csr;
> +	sg_req[0].mmio_seq = 0;
> +	sg_req[0].mc_seq = mc_seq;
>  	sg_req[0].len = len;
>
>  	dma_desc->cyclic = false;
> @@ -1049,7 +1041,7 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
>  	if (flags & DMA_PREP_INTERRUPT)
>  		csr |= TEGRA_GPCDMA_CSR_IE_EOC;
>
> -	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
> +	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
>  	/* retain stream-id and clean rest */
>  	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
>
> @@ -1096,14 +1088,14 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
>  		dma_desc->bytes_req += len;
>
>  		if (direction == DMA_MEM_TO_DEV) {
> -			sg_req[i].ch_regs.src_ptr = mem;
> -			sg_req[i].ch_regs.dst_ptr = apb_ptr;
> -			sg_req[i].ch_regs.high_addr_ptr =
> +			sg_req[i].src = mem;
> +			sg_req[i].dst = apb_ptr;
> +			sg_req[i].high_addr =
>  				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
>  		} else if (direction == DMA_DEV_TO_MEM) {
> -			sg_req[i].ch_regs.src_ptr = apb_ptr;
> -			sg_req[i].ch_regs.dst_ptr = mem;
> -			sg_req[i].ch_regs.high_addr_ptr =
> +			sg_req[i].src = apb_ptr;
> +			sg_req[i].dst = mem;
> +			sg_req[i].high_addr =
>  				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
>  		}
>
> @@ -1111,10 +1103,10 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
>  		 * Word count register takes input in words. Writing a value
>  		 * of N into word count register means a req of (N+1) words.
>  		 */
> -		sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
> -		sg_req[i].ch_regs.csr = csr;
> -		sg_req[i].ch_regs.mmio_seq = mmio_seq;
> -		sg_req[i].ch_regs.mc_seq = mc_seq;
> +		sg_req[i].wcount = ((len - 4) >> 2);
> +		sg_req[i].csr = csr;
> +		sg_req[i].mmio_seq = mmio_seq;
> +		sg_req[i].mc_seq = mc_seq;
>  		sg_req[i].len = len;
>  	}
>
> @@ -1186,7 +1178,7 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
>
>  	mmio_seq |= FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD, 1);
>
> -	mc_seq =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
> +	mc_seq =  tdc_read(tdc, tdc->regs->mc_seq);
>  	/* retain stream-id and clean rest */
>  	mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
>
> @@ -1218,24 +1210,24 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
>  	for (i = 0; i < period_count; i++) {
>  		mmio_seq |= get_burst_size(tdc, burst_size, slave_bw, len);
>  		if (direction == DMA_MEM_TO_DEV) {
> -			sg_req[i].ch_regs.src_ptr = mem;
> -			sg_req[i].ch_regs.dst_ptr = apb_ptr;
> -			sg_req[i].ch_regs.high_addr_ptr =
> +			sg_req[i].src = mem;
> +			sg_req[i].dst = apb_ptr;
> +			sg_req[i].high_addr =
>  				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
>  		} else if (direction == DMA_DEV_TO_MEM) {
> -			sg_req[i].ch_regs.src_ptr = apb_ptr;
> -			sg_req[i].ch_regs.dst_ptr = mem;
> -			sg_req[i].ch_regs.high_addr_ptr =
> +			sg_req[i].src = apb_ptr;
> +			sg_req[i].dst = mem;
> +			sg_req[i].high_addr =
>  				FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
>  		}
>  		/*
>  		 * Word count register takes input in words. Writing a value
>  		 * of N into word count register means a req of (N+1) words.
>  		 */
> -		sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
> -		sg_req[i].ch_regs.csr = csr;
> -		sg_req[i].ch_regs.mmio_seq = mmio_seq;
> -		sg_req[i].ch_regs.mc_seq = mc_seq;
> +		sg_req[i].wcount = ((len - 4) >> 2);
> +		sg_req[i].csr = csr;
> +		sg_req[i].mmio_seq = mmio_seq;
> +		sg_req[i].mc_seq = mc_seq;
>  		sg_req[i].len = len;
>
>  		mem += len;
> @@ -1305,11 +1297,30 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
>  	return chan;
>  }
>
> +static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
> +	.csr = 0x0,
> +	.status = 0x4,
> +	.csre = 0x8,
> +	.src = 0xc,
> +	.dst = 0x10,
> +	.high_addr = 0x14,
> +	.mc_seq = 0x18,
> +	.mmio_seq = 0x1c,
> +	.wcount = 0x20,
> +	.wxfer = 0x24,
> +	.wstatus = 0x28,
> +	.err_status = 0x30,
> +	.fixed_pattern = 0x34,
> +	.tz = 0x38,
> +	.spare = 0x40,
> +};
> +
>  static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
>  	.nr_channels = 32,
>  	.channel_reg_size = SZ_64K,
>  	.max_dma_count = SZ_1G,
>  	.hw_support_pause = false,
> +	.channel_regs = &tegra186_reg_offsets,
>  	.terminate = tegra_dma_stop_client,
>  };
>
> @@ -1318,6 +1329,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
>  	.channel_reg_size = SZ_64K,
>  	.max_dma_count = SZ_1G,
>  	.hw_support_pause = true,
> +	.channel_regs = &tegra186_reg_offsets,
>  	.terminate = tegra_dma_pause,
>  };
>
> @@ -1326,6 +1338,7 @@ static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
>  	.channel_reg_size = SZ_64K,
>  	.max_dma_count = SZ_1G,
>  	.hw_support_pause = true,
> +	.channel_regs = &tegra186_reg_offsets,
>  	.terminate = tegra_dma_pause_noerr,
>  };
>
> @@ -1346,7 +1359,7 @@ MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
>
>  static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
>  {
> -	unsigned int reg_val =  tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
> +	unsigned int reg_val =  tdc_read(tdc, tdc->regs->mc_seq);
>
>  	reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK);
>  	reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
> @@ -1354,7 +1367,7 @@ static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
>  	reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK, stream_id);
>  	reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK, stream_id);
>
> -	tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, reg_val);
> +	tdc_write(tdc, tdc->regs->mc_seq, reg_val);
>  	return 0;
>  }
>
> @@ -1420,6 +1433,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
>  		tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET +
>  					i * cdata->channel_reg_size;
>  		snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i);
> +		tdc->regs = cdata->channel_regs;
>  		tdc->tdma = tdma;
>  		tdc->id = i;
>  		tdc->slave_id = -1;
> --
> 2.50.1
>