drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c

Source file repositories/reference/linux-study-clean/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c

File Facts

System
Linux kernel
Corpus path
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
Extension
.c
Size
45400 bytes
Lines
1705
Domain
Driver Families
Bucket
drivers/dma
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (chan->id >= DMAC_CHAN_16) {
			val &= ~((u64)(BIT(chan->id) >> DMAC_CHAN_16)
				<< (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
			val |=   (u64)(BIT(chan->id) >> DMAC_CHAN_16)
				<< (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
		} else {
			val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
			val |=   BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
		}
		axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
	} else {
		val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
		val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
		if (chan->chip->dw->hdata->reg_map_8_channels)
			val |=   BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
		else
			val |=   BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
		axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
	}
}

static inline void axi_chan_enable(struct axi_dma_chan *chan)
{
	u64 val;

	if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
		val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
		if (chan->id >= DMAC_CHAN_16) {
			val |= (u64)(BIT(chan->id) >> DMAC_CHAN_16)
				<< (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
				(u64)(BIT(chan->id) >> DMAC_CHAN_16)
				<< (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
		} else {
			val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
			BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
		}
		axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
	} else {
		val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
		if (chan->chip->dw->hdata->reg_map_8_channels) {
			val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
			BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
		} else {
			val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
				BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
		}
		axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
	}
}

static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
{
	u64 val;

	if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16)
		val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
	else
		val = axi_dma_ioread32(chan->chip, DMAC_CHEN);

	if (chan->id >= DMAC_CHAN_16)
		return !!(val & ((u64)(BIT(chan->id) >> DMAC_CHAN_16) << DMAC_CHAN_BLOCK_SHIFT));
	else
		return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
}

static void axi_dma_hw_init(struct axi_dma_chip *chip)
{
	int ret;
	u32 i;

	for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
		axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
		axi_chan_disable(&chip->dw->chan[i]);
	}
	ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
	if (ret)
		dev_warn(chip->dev, "Unable to set coherent mask\n");
}

static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src,
				   dma_addr_t dst, size_t len)
{
	u32 max_width = chan->chip->dw->hdata->m_data_width;

	return __ffs(src | dst | len | BIT(max_width));
}

static inline const char *axi_chan_name(struct axi_dma_chan *chan)
{
	return dma_chan_name(&chan->vc.chan);

Annotation

Implementation Notes