drivers/iio/adc/ad7266.c

Source file repositories/reference/linux-study-clean/drivers/iio/adc/ad7266.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ad7266.c
Extension
.c
Size
12300 bytes
Lines
474
Domain
Driver Families
Bucket
drivers/iio
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 ad7266_state {
	struct spi_device	*spi;
	unsigned long		vref_mv;

	struct spi_transfer	single_xfer[3];
	struct spi_message	single_msg;

	enum ad7266_range	range;
	enum ad7266_mode	mode;
	bool			fixed_addr;
	struct gpio_desc	*gpios[3];

	/*
	 * DMA (thus cache coherency maintenance) may require the
	 * transfer buffers to live in their own cache lines.
	 * The buffer needs to be large enough to hold two samples (4 bytes) and
	 * the naturally aligned timestamp (8 bytes).
	 */
	struct {
		__be16 sample[2];
		aligned_s64 timestamp;
	} data __aligned(IIO_DMA_MINALIGN);
};

static int ad7266_wakeup(struct ad7266_state *st)
{
	/* Any read with >= 2 bytes will wake the device */
	return spi_read(st->spi, &st->data.sample[0], 2);
}

static int ad7266_powerdown(struct ad7266_state *st)
{
	/* Any read with < 2 bytes will powerdown the device */
	return spi_read(st->spi, &st->data.sample[0], 1);
}

static int ad7266_preenable(struct iio_dev *indio_dev)
{
	struct ad7266_state *st = iio_priv(indio_dev);
	return ad7266_wakeup(st);
}

static int ad7266_postdisable(struct iio_dev *indio_dev)
{
	struct ad7266_state *st = iio_priv(indio_dev);
	return ad7266_powerdown(st);
}

static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
	.preenable = &ad7266_preenable,
	.postdisable = &ad7266_postdisable,
};

static irqreturn_t ad7266_trigger_handler(int irq, void *p)
{
	struct iio_poll_func *pf = p;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct ad7266_state *st = iio_priv(indio_dev);
	int ret;

	ret = spi_read(st->spi, st->data.sample, 4);
	if (ret == 0)
		iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data),
					    pf->timestamp);

	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
{
	unsigned int i;

	if (st->fixed_addr)
		return;

	switch (st->mode) {
	case AD7266_MODE_SINGLE_ENDED:
		nr >>= 1;
		break;
	case AD7266_MODE_PSEUDO_DIFF:
		nr |= 1;
		break;
	case AD7266_MODE_DIFF:
		nr &= ~1;
		break;
	}

	for (i = 0; i < 3; ++i)

Annotation

Implementation Notes