Commit f806bea3 authored by Vignesh Raghavendra's avatar Vignesh Raghavendra Committed by Vinod Koul
Browse files

dmaengine: ti: k3-udma: Workaround errata i2234

Per [1], UDMA TR15 transactions may hang if ICNT0 is less than 64B
Work around is to set EOL flag is to 1 for ICNT0.

Since, there is no performance penalty / side effects of setting EOL
flag event ICNTO > 64B, just set the flag for all UDMAP TR15
descriptors.

[1] https://www.ti.com/lit/er/sprz455a/sprz455a.pdf


Errata doc for J721E DRA829/TDA4VM Processors Silicon Revision 1.1/1.0
(Rev. A)

Signed-off-by: default avatarVignesh Raghavendra <vigneshr@ti.com>
[j-choudhary@ti.com: minor cleanups]
Signed-off-by: default avatarJayesh Choudhary <j-choudhary@ti.com>
Link: https://lore.kernel.org/r/20230323120107.27638-1-j-choudhary@ti.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 86de3bbf
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -2966,6 +2966,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
	struct scatterlist *sgent;
	struct cppi5_tr_type15_t *tr_req = NULL;
	enum dma_slave_buswidth dev_width;
	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
	u16 tr_cnt0, tr_cnt1;
	dma_addr_t dev_addr;
	struct udma_desc *d;
@@ -3036,6 +3037,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,

	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
		asel = 0;
		csf |= CPPI5_TR_CSF_EOL_ICNT0;
	} else {
		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
		dev_addr |= asel;
@@ -3059,7 +3061,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,

		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15, false,
			      true, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
		cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
				     uc->config.tr_trigger_type,
				     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC, 0, 0);
@@ -3105,8 +3107,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15,
				      false, true,
				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
					 CPPI5_TR_CSF_SUPR_EVT);
			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
			cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
					     uc->config.tr_trigger_type,
					     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC,
@@ -3150,8 +3151,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
		d->residue += sg_len;
	}

	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);

	return d;
}
@@ -3680,6 +3680,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
	int num_tr;
	size_t tr_size = sizeof(struct cppi5_tr_type15_t);
	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
	u32 csf = CPPI5_TR_CSF_SUPR_EVT;

	if (uc->config.dir != DMA_MEM_TO_MEM) {
		dev_err(chan->device->dev,
@@ -3710,13 +3711,15 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
	if (uc->ud->match_data->type != DMA_TYPE_UDMA) {
		src |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
		dest |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
	} else {
		csf |= CPPI5_TR_CSF_EOL_ICNT0;
	}

	tr_req = d->hwdesc[0].tr_req_base;

	cppi5_tr_init(&tr_req[0].flags, CPPI5_TR_TYPE15, false, true,
		      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
	cppi5_tr_csf_set(&tr_req[0].flags, CPPI5_TR_CSF_SUPR_EVT);
	cppi5_tr_csf_set(&tr_req[0].flags, csf);

	tr_req[0].addr = src;
	tr_req[0].icnt0 = tr0_cnt0;
@@ -3735,7 +3738,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
	if (num_tr == 2) {
		cppi5_tr_init(&tr_req[1].flags, CPPI5_TR_TYPE15, false, true,
			      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
		cppi5_tr_csf_set(&tr_req[1].flags, CPPI5_TR_CSF_SUPR_EVT);
		cppi5_tr_csf_set(&tr_req[1].flags, csf);

		tr_req[1].addr = src + tr0_cnt1 * tr0_cnt0;
		tr_req[1].icnt0 = tr1_cnt0;
@@ -3750,8 +3753,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
		tr_req[1].dicnt3 = 1;
	}

	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags,
			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags, csf | CPPI5_TR_CSF_EOP);

	if (uc->config.metadata_size)
		d->vd.tx.metadata_ops = &metadata_ops;
+1 −0
Original line number Diff line number Diff line
@@ -616,6 +616,7 @@ static inline void *cppi5_hdesc_get_swdata(struct cppi5_host_desc_t *desc)
#define   CPPI5_TR_CSF_SUPR_EVT			BIT(2)
#define   CPPI5_TR_CSF_EOL_ADV_SHIFT		(4U)
#define   CPPI5_TR_CSF_EOL_ADV_MASK		GENMASK(6, 4)
#define   CPPI5_TR_CSF_EOL_ICNT0		BIT(4)
#define   CPPI5_TR_CSF_EOP			BIT(7)

/**