drivers/dma/pxa_dma.c

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

File Facts

System
Linux kernel
Corpus path
drivers/dma/pxa_dma.c
Extension
.c
Size
40425 bytes
Lines
1464
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 pxad_desc_hw {
	u32 ddadr;	/* Points to the next descriptor + flags */
	u32 dsadr;	/* DSADR value for the current transfer */
	u32 dtadr;	/* DTADR value for the current transfer */
	u32 dcmd;	/* DCMD value for the current transfer */
} __aligned(16);

struct pxad_desc_sw {
	struct virt_dma_desc	vd;		/* Virtual descriptor */
	int			nb_desc;	/* Number of hw. descriptors */
	size_t			len;		/* Number of bytes xfered */
	dma_addr_t		first;		/* First descriptor's addr */

	/* At least one descriptor has an src/dst address not multiple of 8 */
	bool			misaligned;
	bool			cyclic;
	struct dma_pool		*desc_pool;	/* Channel's used allocator */

	struct pxad_desc_hw	*hw_desc[] __counted_by(nb_desc);
						/* DMA coherent descriptors */
};

struct pxad_phy {
	int			idx;
	void __iomem		*base;
	struct pxad_chan	*vchan;
};

struct pxad_chan {
	struct virt_dma_chan	vc;		/* Virtual channel */
	u32			drcmr;		/* Requestor of the channel */
	enum pxad_chan_prio	prio;		/* Required priority of phy */
	/*
	 * At least one desc_sw in submitted or issued transfers on this channel
	 * has one address such as: addr % 8 != 0. This implies the DALGN
	 * setting on the phy.
	 */
	bool			misaligned;
	struct dma_slave_config	cfg;		/* Runtime config */

	/* protected by vc->lock */
	struct pxad_phy		*phy;
	struct dma_pool		*desc_pool;	/* Descriptors pool */
	dma_cookie_t		bus_error;

	wait_queue_head_t	wq_state;
};

struct pxad_device {
	struct dma_device		slave;
	int				nr_chans;
	int				nr_requestors;
	void __iomem			*base;
	struct pxad_phy			*phys;
	spinlock_t			phy_lock;	/* Phy association */
#ifdef CONFIG_DEBUG_FS
	struct dentry			*dbgfs_root;
	struct dentry			**dbgfs_chan;
#endif
};

#define tx_to_pxad_desc(tx)					\
	container_of(tx, struct pxad_desc_sw, async_tx)
#define to_pxad_chan(dchan)					\
	container_of(dchan, struct pxad_chan, vc.chan)
#define to_pxad_dev(dmadev)					\
	container_of(dmadev, struct pxad_device, slave)
#define to_pxad_sw_desc(_vd)				\
	container_of((_vd), struct pxad_desc_sw, vd)

#define _phy_readl_relaxed(phy, _reg)					\
	readl_relaxed((phy)->base + _reg((phy)->idx))
#define phy_readl_relaxed(phy, _reg)					\
	({								\
		u32 _v;							\
		_v = readl_relaxed((phy)->base + _reg((phy)->idx));	\
		dev_vdbg(&phy->vchan->vc.chan.dev->device,		\
			 "%s(): readl(%s): 0x%08x\n", __func__, #_reg,	\
			  _v);						\
		_v;							\
	})
#define phy_writel(phy, val, _reg)					\
	do {								\
		writel((val), (phy)->base + _reg((phy)->idx));		\
		dev_vdbg(&phy->vchan->vc.chan.dev->device,		\
			 "%s(): writel(0x%08x, %s)\n",			\
			 __func__, (u32)(val), #_reg);			\
	} while (0)
#define phy_writel_relaxed(phy, val, _reg)				\
	do {								\

Annotation

Implementation Notes