drivers/usb/musb/musb_cppi41.c

Source file repositories/reference/linux-study-clean/drivers/usb/musb/musb_cppi41.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/musb/musb_cppi41.c
Extension
.c
Size
21853 bytes
Lines
812
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 cppi41_dma_controller {
	struct dma_controller controller;
	struct cppi41_dma_channel *rx_channel;
	struct cppi41_dma_channel *tx_channel;
	struct hrtimer early_tx;
	struct list_head early_tx_list;
	u32 rx_mode;
	u32 tx_mode;
	u32 auto_req;

	u32 tdown_reg;
	u32 autoreq_reg;

	void (*set_dma_mode)(struct cppi41_dma_channel *cppi41_channel,
			     unsigned int mode);
	u8 num_channels;
};

static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
{
	u16 csr;
	u8 toggle;

	if (cppi41_channel->is_tx)
		return;
	if (!is_host_active(cppi41_channel->controller->controller.musb))
		return;

	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;

	cppi41_channel->usb_toggle = toggle;
}

static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
{
	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
	struct musb *musb = hw_ep->musb;
	u16 csr;
	u8 toggle;

	if (cppi41_channel->is_tx)
		return;
	if (!is_host_active(musb))
		return;

	musb_ep_select(musb->mregs, hw_ep->epnum);
	csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;

	/*
	 * AM335x Advisory 1.0.13: Due to internal synchronisation error the
	 * data toggle may reset from DATA1 to DATA0 during receiving data from
	 * more than one endpoint.
	 */
	if (!toggle && toggle == cppi41_channel->usb_toggle) {
		csr |= MUSB_RXCSR_H_DATATOGGLE | MUSB_RXCSR_H_WR_DATATOGGLE;
		musb_writew(cppi41_channel->hw_ep->regs, MUSB_RXCSR, csr);
		musb_dbg(musb, "Restoring DATA1 toggle.");
	}

	cppi41_channel->usb_toggle = toggle;
}

static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
{
	u8		epnum = hw_ep->epnum;
	struct musb	*musb = hw_ep->musb;
	void __iomem	*epio = musb->endpoints[epnum].regs;
	u16		csr;

	musb_ep_select(musb->mregs, hw_ep->epnum);
	csr = musb_readw(epio, MUSB_TXCSR);
	if (csr & MUSB_TXCSR_TXPKTRDY)
		return false;
	return true;
}

static void cppi41_dma_callback(void *private_data,
				const struct dmaengine_result *result);

static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
{
	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
	struct musb *musb = hw_ep->musb;
	void __iomem *epio = hw_ep->regs;
	u16 csr;

	if (!cppi41_channel->prog_len ||
	    (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) {

Annotation

Implementation Notes