drivers/dma/mmp_tdma.c

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

File Facts

System
Linux kernel
Corpus path
drivers/dma/mmp_tdma.c
Extension
.c
Size
18463 bytes
Lines
747
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

struct mmp_tdma_desc {
	u32 byte_cnt;
	u32 src_addr;
	u32 dst_addr;
	u32 nxt_desc;
};

enum mmp_tdma_type {
	MMP_AUD_TDMA = 0,
	PXA910_SQU,
};

#define TDMA_MAX_XFER_BYTES    SZ_64K

struct mmp_tdma_chan {
	struct device			*dev;
	struct dma_chan			chan;
	struct dma_async_tx_descriptor	desc;
	struct tasklet_struct		tasklet;

	struct mmp_tdma_desc		*desc_arr;
	dma_addr_t			desc_arr_phys;
	int				desc_num;
	enum dma_transfer_direction	dir;
	dma_addr_t			dev_addr;
	u32				burst_sz;
	enum dma_slave_buswidth		buswidth;
	enum dma_status			status;
	struct dma_slave_config		slave_config;

	int				idx;
	enum mmp_tdma_type		type;
	int				irq;
	void __iomem			*reg_base;

	size_t				buf_len;
	size_t				period_len;
	size_t				pos;

	struct gen_pool			*pool;
};

#define TDMA_CHANNEL_NUM 2
struct mmp_tdma_device {
	struct device			*dev;
	void __iomem			*base;
	struct dma_device		device;
	struct mmp_tdma_chan		*tdmac[TDMA_CHANNEL_NUM];
};

#define to_mmp_tdma_chan(dchan) container_of(dchan, struct mmp_tdma_chan, chan)

static int mmp_tdma_config_write(struct dma_chan *chan,
				 enum dma_transfer_direction dir,
				 struct dma_slave_config *dmaengine_cfg);

static void mmp_tdma_chan_set_desc(struct mmp_tdma_chan *tdmac, dma_addr_t phys)
{
	writel(phys, tdmac->reg_base + TDNDPR);
	writel(readl(tdmac->reg_base + TDCR) | TDCR_FETCHND,
					tdmac->reg_base + TDCR);
}

static void mmp_tdma_enable_irq(struct mmp_tdma_chan *tdmac, bool enable)
{
	if (enable)
		writel(TDIMR_COMP, tdmac->reg_base + TDIMR);
	else
		writel(0, tdmac->reg_base + TDIMR);
}

static void mmp_tdma_enable_chan(struct mmp_tdma_chan *tdmac)
{
	/* enable dma chan */
	writel(readl(tdmac->reg_base + TDCR) | TDCR_CHANEN,
					tdmac->reg_base + TDCR);
	tdmac->status = DMA_IN_PROGRESS;
}

static int mmp_tdma_disable_chan(struct dma_chan *chan)
{
	struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
	u32 tdcr;

	tdcr = readl(tdmac->reg_base + TDCR);
	tdcr |= TDCR_ABR;
	tdcr &= ~TDCR_CHANEN;
	writel(tdcr, tdmac->reg_base + TDCR);

	tdmac->status = DMA_COMPLETE;

Annotation

Implementation Notes