mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
dmaengine: tegra: Use struct for register offsets
Repurpose the struct tegra_dma_channel_regs 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. Move the values directly into tegra_dma_sg_req and use channel_regs for storing the register offsets. Update all register reads/writes to use the struct channel_regs. This prepares for the register offset change in Tegra264. Signed-off-by: Akhil R <akhilrajeev@nvidia.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Acked-by: Thierry Reding <treding@nvidia.com> Reviewed-by: Jon Hunter <jonathanh@nvidia.com> Link: https://patch.msgid.link/20260331102303.33181-6-akhilrajeev@nvidia.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
@@ -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,16 +121,6 @@
|
||||
#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)
|
||||
|
||||
/*
|
||||
* If any burst is in flight and DMA paused then this is the time to complete
|
||||
* on-flight burst and update DMA status register.
|
||||
@@ -181,18 +149,24 @@ 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;
|
||||
};
|
||||
|
||||
@@ -205,7 +179,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 +209,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 +270,22 @@ 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), "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), "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), "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 +359,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 +401,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 +438,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 +470,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 +508,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 +583,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 +655,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 +669,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 +721,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 +875,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 +898,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 +943,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 +967,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 +1031,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 +1078,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 +1093,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 +1168,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;
|
||||
|
||||
@@ -1217,24 +1199,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;
|
||||
@@ -1304,11 +1286,28 @@ 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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
@@ -1317,6 +1316,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,
|
||||
};
|
||||
|
||||
@@ -1325,6 +1325,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,
|
||||
};
|
||||
|
||||
@@ -1345,7 +1346,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);
|
||||
@@ -1353,7 +1354,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;
|
||||
}
|
||||
|
||||
@@ -1419,6 +1420,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;
|
||||
|
||||
Reference in New Issue
Block a user