drivers/dma/xilinx/xilinx_dpdma.c

Source file repositories/reference/linux-study-clean/drivers/dma/xilinx/xilinx_dpdma.c

File Facts

System
Linux kernel
Corpus path
drivers/dma/xilinx/xilinx_dpdma.c
Extension
.c
Size
53659 bytes
Lines
1878
Domain
Driver Families
Bucket
drivers/dma
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations fops_xilinx_dpdma_dbgfs = {
	.owner = THIS_MODULE,
	.read = xilinx_dpdma_debugfs_read,
	.write = xilinx_dpdma_debugfs_write,
};

static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev)
{
	struct dentry *dent;

	dpdma_debugfs.testcase = DPDMA_TC_NONE;

	dent = debugfs_create_file("testcase", 0444, xdev->common.dbg_dev_root,
				   NULL, &fops_xilinx_dpdma_dbgfs);
	if (IS_ERR(dent))
		dev_err(xdev->dev, "Failed to create debugfs testcase file\n");
}

/* -----------------------------------------------------------------------------
 * I/O Accessors
 */

static inline u32 dpdma_read(void __iomem *base, u32 offset)
{
	return ioread32(base + offset);
}

static inline void dpdma_write(void __iomem *base, u32 offset, u32 val)
{
	iowrite32(val, base + offset);
}

static inline void dpdma_clr(void __iomem *base, u32 offset, u32 clr)
{
	dpdma_write(base, offset, dpdma_read(base, offset) & ~clr);
}

static inline void dpdma_set(void __iomem *base, u32 offset, u32 set)
{
	dpdma_write(base, offset, dpdma_read(base, offset) | set);
}

/* -----------------------------------------------------------------------------
 * Descriptor Operations
 */

/**
 * xilinx_dpdma_sw_desc_set_dma_addrs - Set DMA addresses in the descriptor
 * @xdev: DPDMA device
 * @sw_desc: The software descriptor in which to set DMA addresses
 * @prev: The previous descriptor
 * @dma_addr: array of dma addresses
 * @num_src_addr: number of addresses in @dma_addr
 *
 * Set all the DMA addresses in the hardware descriptor corresponding to @dev
 * from @dma_addr. If a previous descriptor is specified in @prev, its next
 * descriptor DMA address is set to the DMA address of @sw_desc. @prev may be
 * identical to @sw_desc for cyclic transfers.
 */
static void xilinx_dpdma_sw_desc_set_dma_addrs(struct xilinx_dpdma_device *xdev,
					       struct xilinx_dpdma_sw_desc *sw_desc,
					       struct xilinx_dpdma_sw_desc *prev,
					       dma_addr_t dma_addr[],
					       unsigned int num_src_addr)
{
	struct xilinx_dpdma_hw_desc *hw_desc = &sw_desc->hw;
	unsigned int i;

	hw_desc->src_addr = lower_32_bits(dma_addr[0]);
	if (xdev->ext_addr)
		hw_desc->addr_ext |=
			FIELD_PREP(XILINX_DPDMA_DESC_ADDR_EXT_SRC_ADDR_MASK,
				   upper_32_bits(dma_addr[0]));

	for (i = 1; i < num_src_addr; i++) {
		u32 *addr = &hw_desc->src_addr2;

		addr[i - 1] = lower_32_bits(dma_addr[i]);

		if (xdev->ext_addr) {
			u32 *addr_ext = &hw_desc->addr_ext_23;
			u32 addr_msb;

			addr_msb = upper_32_bits(dma_addr[i]) & GENMASK(15, 0);
			addr_msb <<= 16 * ((i - 1) % 2);
			addr_ext[(i - 1) / 2] |= addr_msb;
		}
	}

	if (!prev)

Annotation

Implementation Notes