drivers/comedi/drivers/mite.c

Source file repositories/reference/linux-study-clean/drivers/comedi/drivers/mite.c

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/mite.c
Extension
.c
Size
27255 bytes
Lines
927
Domain
Driver Families
Bucket
drivers/comedi
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

if (!mite_chan->ring) {
			mite_chan->ring = ring;
			break;
		}
		mite_chan = NULL;
	}
	spin_unlock_irqrestore(&mite->lock, flags);
	return mite_chan;
}
EXPORT_SYMBOL_GPL(mite_request_channel_in_range);

/**
 * mite_request_channel() - Request a MITE dma channel.
 * @mite: MITE device.
 * @ring: MITE dma ring.
 */
struct mite_channel *mite_request_channel(struct mite *mite,
					  struct mite_ring *ring)
{
	return mite_request_channel_in_range(mite, ring, 0,
					     mite->num_channels - 1);
}
EXPORT_SYMBOL_GPL(mite_request_channel);

/**
 * mite_release_channel() - Release a MITE dma channel.
 * @mite_chan: MITE dma channel.
 */
void mite_release_channel(struct mite_channel *mite_chan)
{
	struct mite *mite = mite_chan->mite;
	unsigned long flags;

	/* spin lock to prevent races with mite_request_channel */
	spin_lock_irqsave(&mite->lock, flags);
	if (mite_chan->ring) {
		mite_dma_disarm(mite_chan);
		mite_dma_reset(mite_chan);
		/*
		 * disable all channel's interrupts (do it after disarm/reset so
		 * MITE_CHCR reg isn't changed while dma is still active!)
		 */
		writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE |
		       CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE |
		       CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE |
		       CHCR_CLR_LC_IE | CHCR_CLR_CONT_RB_IE,
		       mite->mmio + MITE_CHCR(mite_chan->channel));
		mite_chan->ring = NULL;
	}
	spin_unlock_irqrestore(&mite->lock, flags);
}
EXPORT_SYMBOL_GPL(mite_release_channel);

/**
 * mite_init_ring_descriptors() - Initialize a MITE dma ring descriptors.
 * @ring: MITE dma ring.
 * @s: COMEDI subdevice.
 * @nbytes: the size of the dma ring (in bytes).
 *
 * Initializes the ring buffer descriptors to provide correct DMA transfer
 * links to the exact amount of memory required. When the ring buffer is
 * allocated by mite_buf_change(), the default is to initialize the ring
 * to refer to the entire DMA data buffer. A command may call this function
 * later to re-initialize and shorten the amount of memory that will be
 * transferred.
 */
int mite_init_ring_descriptors(struct mite_ring *ring,
			       struct comedi_subdevice *s,
			       unsigned int nbytes)
{
	struct comedi_async *async = s->async;
	struct mite_dma_desc *desc = NULL;
	unsigned int n_full_links = nbytes >> PAGE_SHIFT;
	unsigned int remainder = nbytes % PAGE_SIZE;
	int i;

	dev_dbg(s->device->class_dev,
		"mite: init ring buffer to %u bytes\n", nbytes);

	if ((n_full_links + (remainder > 0 ? 1 : 0)) > ring->n_links) {
		dev_err(s->device->class_dev,
			"mite: ring buffer too small for requested init\n");
		return -ENOMEM;
	}

	/* We set the descriptors for all full links. */
	for (i = 0; i < n_full_links; ++i) {
		desc = &ring->descs[i];
		desc->count = cpu_to_le32(PAGE_SIZE);
		desc->addr = cpu_to_le32(async->buf_map->page_list[i].dma_addr);

Annotation

Implementation Notes