Commit 94d13317 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/ctrl/dwc-edma'

- Remove unused struct dw_edma_chip.irq (Frank Li)

- Move eDMA private data from struct dw_edma to struct dw_edma_chip (Frank
  Li)

- Convert "struct dw_edma_region rg_region" to "void __iomem *reg_base"
  since only the virtual address (not physical address or size) is used
  (Frank Li)

- Rename "*_ch_cnt" to "ll_*_cnt" to reflect actual usage (Frank Li)

- Drop dma_slave_config.direction field usage (Serge Semin)

- Fix eDMA Rd/Wr-channels and DMA-direction semantics (Serge Semin)

- Add chip-specific DW_EDMA_CHIP_LOCAL flag to indicate that local eDMA
  doesn't require generating MSIs to remote (Frank Li)

- Enable DMA tests for endpoints that support it (Frank Li)

* pci/ctrl/dwc-edma:
  PCI: endpoint: Enable DMA tests for endpoints with DMA capabilities
  dmaengine: dw-edma: Add support for chip-specific flags
  dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics
  dmaengine: dw-edma: Drop dma_slave_config.direction field usage
  dmaengine: dw-edma: Rename wr(rd)_ch_cnt to ll_wr(rd)_cnt in struct dw_edma_chip
  dmaengine: dw-edma: Change rg_region to reg_base in struct dw_edma_chip
  dmaengine: dw-edma: Detach the private data and chip info structures
  dmaengine: dw-edma: Remove unused irq field in struct dw_edma_chip
parents 964db794 8353813c
Loading
Loading
Loading
Loading
+84 −57
Original line number Diff line number Diff line
@@ -64,8 +64,8 @@ static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)

static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
{
	struct dw_edma_chip *chip = desc->chan->dw->chip;
	struct dw_edma_chan *chan = desc->chan;
	struct dw_edma *dw = chan->chip->dw;
	struct dw_edma_chunk *chunk;

	chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT);
@@ -82,11 +82,11 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
	 */
	chunk->cb = !(desc->chunks_alloc % 2);
	if (chan->dir == EDMA_DIR_WRITE) {
		chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
		chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
		chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr;
		chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr;
	} else {
		chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
		chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
		chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr;
		chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr;
	}

	if (desc->chunk) {
@@ -339,20 +339,39 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
	if (!chan->configured)
		return NULL;

	switch (chan->config.direction) {
	case DMA_DEV_TO_MEM: /* local DMA */
		if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ)
			break;
		return NULL;
	case DMA_MEM_TO_DEV: /* local DMA */
		if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE)
			break;
	/*
	 * Local Root Port/End-point              Remote End-point
	 * +-----------------------+ PCIe bus +----------------------+
	 * |                       |    +-+   |                      |
	 * |    DEV_TO_MEM   Rx Ch <----+ +---+ Tx Ch  DEV_TO_MEM    |
	 * |                       |    | |   |                      |
	 * |    MEM_TO_DEV   Tx Ch +----+ +---> Rx Ch  MEM_TO_DEV    |
	 * |                       |    +-+   |                      |
	 * +-----------------------+          +----------------------+
	 *
	 * 1. Normal logic:
	 * If eDMA is embedded into the DW PCIe RP/EP and controlled from the
	 * CPU/Application side, the Rx channel (EDMA_DIR_READ) will be used
	 * for the device read operations (DEV_TO_MEM) and the Tx channel
	 * (EDMA_DIR_WRITE) - for the write operations (MEM_TO_DEV).
	 *
	 * 2. Inverted logic:
	 * If eDMA is embedded into a Remote PCIe EP and is controlled by the
	 * MWr/MRd TLPs sent from the CPU's PCIe host controller, the Tx
	 * channel (EDMA_DIR_WRITE) will be used for the device read operations
	 * (DEV_TO_MEM) and the Rx channel (EDMA_DIR_READ) - for the write
	 * operations (MEM_TO_DEV).
	 *
	 * It is the client driver responsibility to choose a proper channel
	 * for the DMA transfers.
	 */
	if (chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
		if ((chan->dir == EDMA_DIR_READ && dir != DMA_DEV_TO_MEM) ||
		    (chan->dir == EDMA_DIR_WRITE && dir != DMA_MEM_TO_DEV))
			return NULL;
	default: /* remote DMA */
		if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_READ)
			break;
		if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_WRITE)
			break;
	} else {
		if ((chan->dir == EDMA_DIR_WRITE && dir != DMA_DEV_TO_MEM) ||
		    (chan->dir == EDMA_DIR_READ && dir != DMA_MEM_TO_DEV))
			return NULL;
	}

@@ -423,7 +442,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
		chunk->ll_region.sz += burst->sz;
		desc->alloc_sz += burst->sz;

		if (chan->dir == EDMA_DIR_WRITE) {
		if (dir == DMA_DEV_TO_MEM) {
			burst->sar = src_addr;
			if (xfer->type == EDMA_XFER_CYCLIC) {
				burst->dar = xfer->xfer.cyclic.paddr;
@@ -663,7 +682,7 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
	if (chan->status != EDMA_ST_IDLE)
		return -EBUSY;

	pm_runtime_get(chan->chip->dev);
	pm_runtime_get(chan->dw->chip->dev);

	return 0;
}
@@ -685,15 +704,15 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
		cpu_relax();
	}

	pm_runtime_put(chan->chip->dev);
	pm_runtime_put(chan->dw->chip->dev);
}

static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
				 u32 wr_alloc, u32 rd_alloc)
{
	struct dw_edma_chip *chip = dw->chip;
	struct dw_edma_region *dt_region;
	struct device *dev = chip->dev;
	struct dw_edma *dw = chip->dw;
	struct dw_edma_chan *chan;
	struct dw_edma_irq *irq;
	struct dma_device *dma;
@@ -726,7 +745,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,

		chan->vc.chan.private = dt_region;

		chan->chip = chip;
		chan->dw = dw;
		chan->id = j;
		chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
		chan->configured = false;
@@ -734,9 +753,9 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
		chan->status = EDMA_ST_IDLE;

		if (write)
			chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
			chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
		else
			chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
			chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
		chan->ll_max -= 1;

		dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
@@ -766,13 +785,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
		vchan_init(&chan->vc, dma);

		if (write) {
			dt_region->paddr = dw->dt_region_wr[j].paddr;
			dt_region->vaddr = dw->dt_region_wr[j].vaddr;
			dt_region->sz = dw->dt_region_wr[j].sz;
			dt_region->paddr = chip->dt_region_wr[j].paddr;
			dt_region->vaddr = chip->dt_region_wr[j].vaddr;
			dt_region->sz = chip->dt_region_wr[j].sz;
		} else {
			dt_region->paddr = dw->dt_region_rd[j].paddr;
			dt_region->vaddr = dw->dt_region_rd[j].vaddr;
			dt_region->sz = dw->dt_region_rd[j].sz;
			dt_region->paddr = chip->dt_region_rd[j].paddr;
			dt_region->vaddr = chip->dt_region_rd[j].vaddr;
			dt_region->sz = chip->dt_region_rd[j].sz;
		}

		dw_edma_v0_core_device_config(chan);
@@ -826,11 +845,11 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt)
		(*mask)++;
}

static int dw_edma_irq_request(struct dw_edma_chip *chip,
static int dw_edma_irq_request(struct dw_edma *dw,
			       u32 *wr_alloc, u32 *rd_alloc)
{
	struct device *dev = chip->dev;
	struct dw_edma *dw = chip->dw;
	struct dw_edma_chip *chip = dw->chip;
	struct device *dev = dw->chip->dev;
	u32 wr_mask = 1;
	u32 rd_mask = 1;
	int i, err = 0;
@@ -839,12 +858,16 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,

	ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt;

	if (dw->nr_irqs < 1)
	if (chip->nr_irqs < 1 || !chip->ops->irq_vector)
		return -EINVAL;

	if (dw->nr_irqs == 1) {
	dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
	if (!dw->irq)
		return -ENOMEM;

	if (chip->nr_irqs == 1) {
		/* Common IRQ shared among all channels */
		irq = dw->ops->irq_vector(dev, 0);
		irq = chip->ops->irq_vector(dev, 0);
		err = request_irq(irq, dw_edma_interrupt_common,
				  IRQF_SHARED, dw->name, &dw->irq[0]);
		if (err) {
@@ -854,9 +877,11 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,

		if (irq_get_msi_desc(irq))
			get_cached_msi_msg(irq, &dw->irq[0].msi);

		dw->nr_irqs = 1;
	} else {
		/* Distribute IRQs equally among all channels */
		int tmp = dw->nr_irqs;
		int tmp = chip->nr_irqs;

		while (tmp && (*wr_alloc + *rd_alloc) < ch_cnt) {
			dw_edma_dec_irq_alloc(&tmp, wr_alloc, dw->wr_ch_cnt);
@@ -867,7 +892,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
		dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);

		for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
			irq = dw->ops->irq_vector(dev, i);
			irq = chip->ops->irq_vector(dev, i);
			err = request_irq(irq,
					  i < *wr_alloc ?
						dw_edma_interrupt_write :
@@ -901,20 +926,22 @@ int dw_edma_probe(struct dw_edma_chip *chip)
		return -EINVAL;

	dev = chip->dev;
	if (!dev)
	if (!dev || !chip->ops)
		return -EINVAL;

	dw = chip->dw;
	if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
		return -EINVAL;
	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
	if (!dw)
		return -ENOMEM;

	dw->chip = chip;

	raw_spin_lock_init(&dw->lock);

	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
	dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt,
			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);

	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
	dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt,
			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);

@@ -936,17 +963,17 @@ int dw_edma_probe(struct dw_edma_chip *chip)
	dw_edma_v0_core_off(dw);

	/* Request IRQs */
	err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc);
	err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
	if (err)
		return err;

	/* Setup write channels */
	err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc);
	err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
	if (err)
		goto err_irq_free;

	/* Setup read channels */
	err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc);
	err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
	if (err)
		goto err_irq_free;

@@ -954,15 +981,15 @@ int dw_edma_probe(struct dw_edma_chip *chip)
	pm_runtime_enable(dev);

	/* Turn debugfs on */
	dw_edma_v0_core_debugfs_on(chip);
	dw_edma_v0_core_debugfs_on(dw);

	chip->dw = dw;

	return 0;

err_irq_free:
	for (i = (dw->nr_irqs - 1); i >= 0; i--)
		free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);

	dw->nr_irqs = 0;
		free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);

	return err;
}
@@ -980,7 +1007,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)

	/* Free irqs */
	for (i = (dw->nr_irqs - 1); i >= 0; i--)
		free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
		free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);

	/* Power management */
	pm_runtime_disable(dev);
@@ -1001,7 +1028,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
	}

	/* Turn debugfs off */
	dw_edma_v0_core_debugfs_off(chip);
	dw_edma_v0_core_debugfs_off(dw);

	return 0;
}
+3 −28
Original line number Diff line number Diff line
@@ -15,20 +15,12 @@
#include "../virt-dma.h"

#define EDMA_LL_SZ					24
#define EDMA_MAX_WR_CH					8
#define EDMA_MAX_RD_CH					8

enum dw_edma_dir {
	EDMA_DIR_WRITE = 0,
	EDMA_DIR_READ
};

enum dw_edma_map_format {
	EDMA_MF_EDMA_LEGACY = 0x0,
	EDMA_MF_EDMA_UNROLL = 0x1,
	EDMA_MF_HDMA_COMPAT = 0x5
};

enum dw_edma_request {
	EDMA_REQ_NONE = 0,
	EDMA_REQ_STOP,
@@ -57,12 +49,6 @@ struct dw_edma_burst {
	u32				sz;
};

struct dw_edma_region {
	phys_addr_t			paddr;
	void				__iomem *vaddr;
	size_t				sz;
};

struct dw_edma_chunk {
	struct list_head		list;
	struct dw_edma_chan		*chan;
@@ -87,7 +73,7 @@ struct dw_edma_desc {

struct dw_edma_chan {
	struct virt_dma_chan		vc;
	struct dw_edma_chip		*chip;
	struct dw_edma			*dw;
	int				id;
	enum dw_edma_dir		dir;

@@ -109,10 +95,6 @@ struct dw_edma_irq {
	struct dw_edma			*dw;
};

struct dw_edma_core_ops {
	int	(*irq_vector)(struct device *dev, unsigned int nr);
};

struct dw_edma {
	char				name[20];

@@ -122,21 +104,14 @@ struct dw_edma {
	struct dma_device		rd_edma;
	u16				rd_ch_cnt;

	struct dw_edma_region		rg_region;	/* Registers */
	struct dw_edma_region		ll_region_wr[EDMA_MAX_WR_CH];
	struct dw_edma_region		ll_region_rd[EDMA_MAX_RD_CH];
	struct dw_edma_region		dt_region_wr[EDMA_MAX_WR_CH];
	struct dw_edma_region		dt_region_rd[EDMA_MAX_RD_CH];

	struct dw_edma_irq		*irq;
	int				nr_irqs;

	enum dw_edma_map_format		mf;

	struct dw_edma_chan		*chan;
	const struct dw_edma_core_ops	*ops;

	raw_spinlock_t			lock;		/* Only for legacy */

	struct dw_edma_chip             *chip;
#ifdef CONFIG_DEBUG_FS
	struct dentry			*debugfs;
#endif /* CONFIG_DEBUG_FS */
+34 −49
Original line number Diff line number Diff line
@@ -148,7 +148,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
	struct dw_edma_pcie_data vsec_data;
	struct device *dev = &pdev->dev;
	struct dw_edma_chip *chip;
	struct dw_edma *dw;
	int err, nr_irqs;
	int i, mask;

@@ -197,10 +196,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
	if (!chip)
		return -ENOMEM;

	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
	if (!dw)
		return -ENOMEM;

	/* IRQs allocation */
	nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
					PCI_IRQ_MSI | PCI_IRQ_MSIX);
@@ -211,29 +206,23 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
	}

	/* Data structure initialization */
	chip->dw = dw;
	chip->dev = dev;
	chip->id = pdev->devfn;
	chip->irq = pdev->irq;

	dw->mf = vsec_data.mf;
	dw->nr_irqs = nr_irqs;
	dw->ops = &dw_edma_pcie_core_ops;
	dw->wr_ch_cnt = vsec_data.wr_ch_cnt;
	dw->rd_ch_cnt = vsec_data.rd_ch_cnt;
	chip->mf = vsec_data.mf;
	chip->nr_irqs = nr_irqs;
	chip->ops = &dw_edma_pcie_core_ops;

	dw->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
	if (!dw->rg_region.vaddr)
		return -ENOMEM;
	chip->ll_wr_cnt = vsec_data.wr_ch_cnt;
	chip->ll_rd_cnt = vsec_data.rd_ch_cnt;

	dw->rg_region.vaddr += vsec_data.rg.off;
	dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start;
	dw->rg_region.paddr += vsec_data.rg.off;
	dw->rg_region.sz = vsec_data.rg.sz;
	chip->reg_base = pcim_iomap_table(pdev)[vsec_data.rg.bar];
	if (!chip->reg_base)
		return -ENOMEM;

	for (i = 0; i < dw->wr_ch_cnt; i++) {
		struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
		struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
	for (i = 0; i < chip->ll_wr_cnt; i++) {
		struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
		struct dw_edma_region *dt_region = &chip->dt_region_wr[i];
		struct dw_edma_block *ll_block = &vsec_data.ll_wr[i];
		struct dw_edma_block *dt_block = &vsec_data.dt_wr[i];

@@ -256,9 +245,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
		dt_region->sz = dt_block->sz;
	}

	for (i = 0; i < dw->rd_ch_cnt; i++) {
		struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
		struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
	for (i = 0; i < chip->ll_rd_cnt; i++) {
		struct dw_edma_region *ll_region = &chip->ll_region_rd[i];
		struct dw_edma_region *dt_region = &chip->dt_region_rd[i];
		struct dw_edma_block *ll_block = &vsec_data.ll_rd[i];
		struct dw_edma_block *dt_block = &vsec_data.dt_rd[i];

@@ -282,45 +271,45 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
	}

	/* Debug info */
	if (dw->mf == EDMA_MF_EDMA_LEGACY)
		pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", dw->mf);
	else if (dw->mf == EDMA_MF_EDMA_UNROLL)
		pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", dw->mf);
	else if (dw->mf == EDMA_MF_HDMA_COMPAT)
		pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", dw->mf);
	if (chip->mf == EDMA_MF_EDMA_LEGACY)
		pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", chip->mf);
	else if (chip->mf == EDMA_MF_EDMA_UNROLL)
		pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", chip->mf);
	else if (chip->mf == EDMA_MF_HDMA_COMPAT)
		pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", chip->mf);
	else
		pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", dw->mf);
		pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", chip->mf);

	pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
	pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p)\n",
		vsec_data.rg.bar, vsec_data.rg.off, vsec_data.rg.sz,
		dw->rg_region.vaddr, &dw->rg_region.paddr);
		chip->reg_base);


	for (i = 0; i < dw->wr_ch_cnt; i++) {
	for (i = 0; i < chip->ll_wr_cnt; i++) {
		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, dw->ll_region_wr[i].sz,
			dw->ll_region_wr[i].vaddr, &dw->ll_region_wr[i].paddr);
			vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
			chip->ll_region_wr[i].vaddr, &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, dw->dt_region_wr[i].sz,
			dw->dt_region_wr[i].vaddr, &dw->dt_region_wr[i].paddr);
			vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
			chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
	}

	for (i = 0; i < dw->rd_ch_cnt; i++) {
	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, dw->ll_region_rd[i].sz,
			dw->ll_region_rd[i].vaddr, &dw->ll_region_rd[i].paddr);
			vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
			chip->ll_region_rd[i].vaddr, &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, dw->dt_region_rd[i].sz,
			dw->dt_region_rd[i].vaddr, &dw->dt_region_rd[i].paddr);
			vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
			chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
	}

	pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
	pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);

	/* Validating if PCI interrupts were enabled */
	if (!pci_dev_msi_enabled(pdev)) {
@@ -328,10 +317,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
		return -EPERM;
	}

	dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
	if (!dw->irq)
		return -ENOMEM;

	/* Starting eDMA driver */
	err = dw_edma_probe(chip);
	if (err) {
+22 −19
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ enum dw_edma_control {

static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
{
	return dw->rg_region.vaddr;
	return dw->chip->reg_base;
}

#define SET_32(dw, name, value)				\
@@ -96,7 +96,7 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
static inline struct dw_edma_v0_ch_regs __iomem *
__dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
{
	if (dw->mf == EDMA_MF_EDMA_LEGACY)
	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
		return &(__dw_regs(dw)->type.legacy.ch);

	if (dir == EDMA_DIR_WRITE)
@@ -108,7 +108,7 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
static inline void writel_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
			     u32 value, void __iomem *addr)
{
	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
		u32 viewport_sel;
		unsigned long flags;

@@ -133,7 +133,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
{
	u32 value;

	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
		u32 viewport_sel;
		unsigned long flags;

@@ -169,7 +169,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
			     u64 value, void __iomem *addr)
{
	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
		u32 viewport_sel;
		unsigned long flags;

@@ -194,7 +194,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
{
	u32 value;

	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
		u32 viewport_sel;
		unsigned long flags;

@@ -256,7 +256,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)

enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
{
	struct dw_edma *dw = chan->chip->dw;
	struct dw_edma *dw = chan->dw;
	u32 tmp;

	tmp = FIELD_GET(EDMA_V0_CH_STATUS_MASK,
@@ -272,7 +272,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)

void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
{
	struct dw_edma *dw = chan->chip->dw;
	struct dw_edma *dw = chan->dw;

	SET_RW_32(dw, chan->dir, int_clear,
		  FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
@@ -280,7 +280,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)

void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
{
	struct dw_edma *dw = chan->chip->dw;
	struct dw_edma *dw = chan->dw;

	SET_RW_32(dw, chan->dir, int_clear,
		  FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
@@ -301,6 +301,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
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;
@@ -314,9 +315,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
	j = chunk->bursts_alloc;
	list_for_each_entry(child, &chunk->burst->list, list) {
		j--;
		if (!j)
			control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);

		if (!j) {
			control |= DW_EDMA_V0_LIE;
			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 */
@@ -357,7 +360,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
{
	struct dw_edma_chan *chan = chunk->chan;
	struct dw_edma *dw = chan->chip->dw;
	struct dw_edma *dw = chan->dw;
	u32 tmp;

	dw_edma_v0_core_write_chunk(chunk);
@@ -365,7 +368,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
	if (first) {
		/* Enable engine */
		SET_RW_32(dw, chan->dir, engine_en, BIT(0));
		if (dw->mf == EDMA_MF_HDMA_COMPAT) {
		if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
			switch (chan->id) {
			case 0:
				SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en,
@@ -435,7 +438,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)

int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
{
	struct dw_edma *dw = chan->chip->dw;
	struct dw_edma *dw = chan->dw;
	u32 tmp = 0;

	/* MSI done addr - low, high */
@@ -505,12 +508,12 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
}

/* eDMA debugfs callbacks */
void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)
void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
{
	dw_edma_v0_debugfs_on(chip);
	dw_edma_v0_debugfs_on(dw);
}

void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip)
void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
{
	dw_edma_v0_debugfs_off(chip);
	dw_edma_v0_debugfs_off(dw);
}
+2 −2
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir)
void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
/* eDMA debug fs callbacks */
void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip);
void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip);
void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);

#endif /* _DW_EDMA_V0_CORE_H */
Loading