diff options
| -rw-r--r-- | drivers/dma/dw-edma/dw-edma-pcie.c | 32 | ||||
| -rw-r--r-- | drivers/dma/dw-edma/dw-edma-v0-core.c | 69 | ||||
| -rw-r--r-- | include/linux/dma/edma.h | 5 | 
3 files changed, 64 insertions, 42 deletions
| diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c index 3f9dadc73854..2b40f2b44f5e 100644 --- a/drivers/dma/dw-edma/dw-edma-pcie.c +++ b/drivers/dma/dw-edma/dw-edma-pcie.c @@ -240,20 +240,20 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,  		struct dw_edma_block *ll_block = &vsec_data.ll_wr[i];  		struct dw_edma_block *dt_block = &vsec_data.dt_wr[i]; -		ll_region->vaddr = pcim_iomap_table(pdev)[ll_block->bar]; -		if (!ll_region->vaddr) +		ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar]; +		if (!ll_region->vaddr.io)  			return -ENOMEM; -		ll_region->vaddr += ll_block->off; +		ll_region->vaddr.io += ll_block->off;  		ll_region->paddr = pci_bus_address(pdev, ll_block->bar);  		ll_region->paddr += ll_block->off;  		ll_region->sz = ll_block->sz; -		dt_region->vaddr = pcim_iomap_table(pdev)[dt_block->bar]; -		if (!dt_region->vaddr) +		dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar]; +		if (!dt_region->vaddr.io)  			return -ENOMEM; -		dt_region->vaddr += dt_block->off; +		dt_region->vaddr.io += dt_block->off;  		dt_region->paddr = pci_bus_address(pdev, dt_block->bar);  		dt_region->paddr += dt_block->off;  		dt_region->sz = dt_block->sz; @@ -265,20 +265,20 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,  		struct dw_edma_block *ll_block = &vsec_data.ll_rd[i];  		struct dw_edma_block *dt_block = &vsec_data.dt_rd[i]; -		ll_region->vaddr = pcim_iomap_table(pdev)[ll_block->bar]; -		if (!ll_region->vaddr) +		ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar]; +		if (!ll_region->vaddr.io)  			return -ENOMEM; -		ll_region->vaddr += ll_block->off; +		ll_region->vaddr.io += ll_block->off;  		ll_region->paddr = pci_bus_address(pdev, ll_block->bar);  		ll_region->paddr += ll_block->off;  		ll_region->sz = ll_block->sz; -		dt_region->vaddr = pcim_iomap_table(pdev)[dt_block->bar]; -		if (!dt_region->vaddr) +		dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar]; +		if (!dt_region->vaddr.io)  			return -ENOMEM; -		dt_region->vaddr += dt_block->off; +		dt_region->vaddr.io += dt_block->off;  		dt_region->paddr = pci_bus_address(pdev, dt_block->bar);  		dt_region->paddr += dt_block->off;  		dt_region->sz = dt_block->sz; @@ -303,24 +303,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,  		pci_dbg(pdev, "L. List:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",  			i, vsec_data.ll_wr[i].bar,  			vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz, -			chip->ll_region_wr[i].vaddr, &chip->ll_region_wr[i].paddr); +			chip->ll_region_wr[i].vaddr.io, &chip->ll_region_wr[i].paddr);  		pci_dbg(pdev, "Data:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",  			i, vsec_data.dt_wr[i].bar,  			vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz, -			chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr); +			chip->dt_region_wr[i].vaddr.io, &chip->dt_region_wr[i].paddr);  	}  	for (i = 0; i < chip->ll_rd_cnt; i++) {  		pci_dbg(pdev, "L. List:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",  			i, vsec_data.ll_rd[i].bar,  			vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz, -			chip->ll_region_rd[i].vaddr, &chip->ll_region_rd[i].paddr); +			chip->ll_region_rd[i].vaddr.io, &chip->ll_region_rd[i].paddr);  		pci_dbg(pdev, "Data:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",  			i, vsec_data.dt_rd[i].bar,  			vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz, -			chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr); +			chip->dt_region_rd[i].vaddr.io, &chip->dt_region_rd[i].paddr);  	}  	pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs); diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index 6bcc57512258..72e79a0c0a4e 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -159,9 +159,6 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,  #define GET_CH_32(dw, dir, ch, name) \  	readl_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name)) -#define SET_LL_32(ll, value) \ -	writel(value, ll) -  static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,  			     u64 value, void __iomem *addr)  { @@ -218,9 +215,6 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,  #define GET_CH_64(dw, dir, ch, name) \  	readq_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name)) -#define SET_LL_64(ll, value) \ -	writeq(value, ll) -  /* eDMA management callbacks */  void dw_edma_v0_core_off(struct dw_edma *dw)  { @@ -292,17 +286,53 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)  			 GET_RW_32(dw, dir, int_status));  } +static void dw_edma_v0_write_ll_data(struct dw_edma_chunk *chunk, int i, +				     u32 control, u32 size, u64 sar, u64 dar) +{ +	ptrdiff_t ofs = i * sizeof(struct dw_edma_v0_lli); + +	if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) { +		struct dw_edma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs; + +		lli->control = control; +		lli->transfer_size = size; +		lli->sar.reg = sar; +		lli->dar.reg = dar; +	} else { +		struct dw_edma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io + ofs; + +		writel(control, &lli->control); +		writel(size, &lli->transfer_size); +		writeq(sar, &lli->sar.reg); +		writeq(dar, &lli->dar.reg); +	} +} + +static void dw_edma_v0_write_ll_link(struct dw_edma_chunk *chunk, +				     int i, u32 control, u64 pointer) +{ +	ptrdiff_t ofs = i * sizeof(struct dw_edma_v0_lli); + +	if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) { +		struct dw_edma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs; + +		llp->control = control; +		llp->llp.reg = pointer; +	} else { +		struct dw_edma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io + ofs; + +		writel(control, &llp->control); +		writeq(pointer, &llp->llp.reg); +	} +} +  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)  {  	struct dw_edma_burst *child;  	struct dw_edma_chan *chan = chunk->chan; -	struct dw_edma_v0_lli __iomem *lli; -	struct dw_edma_v0_llp __iomem *llp;  	u32 control = 0, i = 0;  	int j; -	lli = chunk->ll_region.vaddr; -  	if (chunk->cb)  		control = DW_EDMA_V0_CB; @@ -314,27 +344,16 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)  			if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))  				control |= DW_EDMA_V0_RIE;  		} -		/* Channel control */ -		SET_LL_32(&lli[i].control, control); -		/* Transfer size */ -		SET_LL_32(&lli[i].transfer_size, child->sz); -		/* SAR */ -		SET_LL_64(&lli[i].sar.reg, child->sar); -		/* DAR */ -		SET_LL_64(&lli[i].dar.reg, child->dar); - -		i++; + +		dw_edma_v0_write_ll_data(chunk, i++, control, child->sz, +					 child->sar, child->dar);  	} -	llp = (void __iomem *)&lli[i];  	control = DW_EDMA_V0_LLP | DW_EDMA_V0_TCB;  	if (!chunk->cb)  		control |= DW_EDMA_V0_CB; -	/* Channel control */ -	SET_LL_32(&llp->control, control); -	/* Linked list */ -	SET_LL_64(&llp->llp.reg, chunk->ll_region.paddr); +	dw_edma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr);  }  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h index 96bfd0173f3a..3b80040b95cc 100644 --- a/include/linux/dma/edma.h +++ b/include/linux/dma/edma.h @@ -19,7 +19,10 @@ struct dw_edma;  struct dw_edma_region {  	u64		paddr; -	void __iomem	*vaddr; +	union { +		void		*mem; +		void __iomem	*io; +	} vaddr;  	size_t		sz;  }; | 
