dmaengine: pl330: add support for interlace size config
Change-Id: Ia1008d689591f80ee2b3c08e1596b83ccd762f63 Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com> Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
This commit is contained in:
@ -460,6 +460,8 @@ struct dma_pl330_chan {
|
||||
/* DMA-mapped view of the FIFO; may differ if an IOMMU is present */
|
||||
dma_addr_t fifo_dma;
|
||||
enum dma_data_direction dir;
|
||||
unsigned int src_interlace_size;
|
||||
unsigned int dst_interlace_size;
|
||||
|
||||
/* for runtime pm tracking */
|
||||
bool active;
|
||||
@ -552,6 +554,9 @@ struct dma_pl330_desc {
|
||||
/* For cyclic capability */
|
||||
bool cyclic;
|
||||
size_t num_periods;
|
||||
/* interlace size */
|
||||
unsigned int src_interlace_size;
|
||||
unsigned int dst_interlace_size;
|
||||
};
|
||||
|
||||
struct _xfer_spec {
|
||||
@ -580,6 +585,22 @@ static inline u32 get_revision(u32 periph_id)
|
||||
return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
|
||||
}
|
||||
|
||||
static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
|
||||
enum pl330_dst da, u16 val)
|
||||
{
|
||||
if (dry_run)
|
||||
return SZ_DMAADDH;
|
||||
|
||||
buf[0] = CMD_DMAADDH;
|
||||
buf[0] |= (da << 1);
|
||||
*((__le16 *)&buf[1]) = cpu_to_le16(val);
|
||||
|
||||
PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
|
||||
da == 1 ? "DA" : "SA", val);
|
||||
|
||||
return SZ_DMAADDH;
|
||||
}
|
||||
|
||||
static inline u32 _emit_END(unsigned dry_run, u8 buf[])
|
||||
{
|
||||
if (dry_run)
|
||||
@ -1206,6 +1227,21 @@ static inline int _ldst_peripheral(struct pl330_dmac *pl330,
|
||||
pxs->desc->peri);
|
||||
off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype,
|
||||
pxs->desc->peri);
|
||||
switch (pxs->desc->rqtype) {
|
||||
case DMA_DEV_TO_MEM:
|
||||
if (pxs->desc->dst_interlace_size)
|
||||
off += _emit_ADDH(dry_run, &buf[off], DST,
|
||||
pxs->desc->dst_interlace_size);
|
||||
break;
|
||||
case DMA_MEM_TO_DEV:
|
||||
if (pxs->desc->src_interlace_size)
|
||||
off += _emit_ADDH(dry_run, &buf[off], SRC,
|
||||
pxs->desc->src_interlace_size);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return off;
|
||||
@ -1421,11 +1457,14 @@ static int _period(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
|
||||
off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||||
}
|
||||
|
||||
num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
|
||||
if (!pxs->desc->src_interlace_size &&
|
||||
!pxs->desc->dst_interlace_size) {
|
||||
num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
|
||||
|
||||
if (num_dregs) {
|
||||
off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||||
if (num_dregs) {
|
||||
off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||||
}
|
||||
}
|
||||
|
||||
off += _emit_SEV(dry_run, &buf[off], ev);
|
||||
@ -1494,12 +1533,20 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||||
BRST_SIZE(ccr);
|
||||
int off = 0;
|
||||
|
||||
if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
|
||||
pxs->desc->dst_interlace_size);
|
||||
else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
|
||||
pxs->desc->src_interlace_size);
|
||||
while (bursts) {
|
||||
c = bursts;
|
||||
off += _loop(pl330, dry_run, &buf[off], &c, pxs);
|
||||
bursts -= c;
|
||||
}
|
||||
off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||||
if (!pxs->desc->src_interlace_size &&
|
||||
!pxs->desc->dst_interlace_size)
|
||||
off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||||
|
||||
return off;
|
||||
}
|
||||
@ -1531,6 +1578,12 @@ static inline int _setup_xfer_cyclic(struct pl330_dmac *pl330,
|
||||
unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr);
|
||||
int off = 0;
|
||||
|
||||
if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
|
||||
+ pxs->desc->dst_interlace_size);
|
||||
else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
|
||||
+ pxs->desc->src_interlace_size);
|
||||
/* Setup Loop(s) */
|
||||
off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev);
|
||||
|
||||
@ -2390,6 +2443,8 @@ static int pl330_config(struct dma_chan *chan,
|
||||
pch->fifo_addr = slave_config->dst_addr;
|
||||
if (slave_config->dst_addr_width)
|
||||
pch->burst_sz = __ffs(slave_config->dst_addr_width);
|
||||
if (slave_config->src_interlace_size)
|
||||
pch->src_interlace_size = slave_config->src_interlace_size;
|
||||
pch->burst_len = fixup_burst_len(slave_config->dst_maxburst,
|
||||
pch->dmac->quirks);
|
||||
} else if (slave_config->direction == DMA_DEV_TO_MEM) {
|
||||
@ -2397,6 +2452,8 @@ static int pl330_config(struct dma_chan *chan,
|
||||
pch->fifo_addr = slave_config->src_addr;
|
||||
if (slave_config->src_addr_width)
|
||||
pch->burst_sz = __ffs(slave_config->src_addr_width);
|
||||
if (slave_config->dst_interlace_size)
|
||||
pch->dst_interlace_size = slave_config->dst_interlace_size;
|
||||
pch->burst_len = fixup_burst_len(slave_config->src_maxburst,
|
||||
pch->dmac->quirks);
|
||||
}
|
||||
@ -2854,6 +2911,9 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||||
desc->num_periods = len / period_len;
|
||||
desc->txd.flags = flags;
|
||||
|
||||
desc->src_interlace_size = pch->src_interlace_size;
|
||||
desc->dst_interlace_size = pch->dst_interlace_size;
|
||||
|
||||
return &desc->txd;
|
||||
}
|
||||
|
||||
@ -2984,6 +3044,8 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
desc->rqcfg.brst_len = pch->burst_len;
|
||||
desc->rqtype = direction;
|
||||
desc->bytes_requested = sg_dma_len(sg);
|
||||
desc->src_interlace_size = pch->src_interlace_size;
|
||||
desc->dst_interlace_size = pch->dst_interlace_size;
|
||||
}
|
||||
|
||||
/* Return the last desc in the chain */
|
||||
|
||||
@ -376,6 +376,8 @@ struct dma_slave_config {
|
||||
u32 dst_port_window_size;
|
||||
bool device_fc;
|
||||
unsigned int slave_id;
|
||||
unsigned int src_interlace_size;
|
||||
unsigned int dst_interlace_size;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user