drivers/iio/adc/ad7476.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ad7476.c
Extension
.c
Size
13266 bytes
Lines
466
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 ad7476_chip_info {
	unsigned int			int_vref_mv;
	struct iio_chan_spec		channel[2];
	void (*reset)(struct ad7476_state *);
	void (*conversion_pre_op)(struct ad7476_state *st);
	void (*conversion_post_op)(struct ad7476_state *st);
	bool				has_vref;
	bool				has_vdrive;
	bool				convstart_required;
};

struct ad7476_state {
	struct spi_device		*spi;
	const struct ad7476_chip_info	*chip_info;
	struct gpio_desc		*convst_gpio;
	struct spi_transfer		xfer;
	struct spi_message		msg;
	struct iio_chan_spec		channel[2];
	int				scale_mv;
	/*
	 * DMA (thus cache coherency maintenance) may require the
	 * transfer buffers to live in their own cache lines.
	 * Make the buffer large enough for one 16 bit sample and one 64 bit
	 * aligned 64 bit timestamp.
	 */
	unsigned char data[ALIGN(2, sizeof(s64)) + sizeof(s64)] __aligned(IIO_DMA_MINALIGN);
};

static void ad7091_convst(struct ad7476_state *st)
{
	if (!st->convst_gpio)
		return;

	gpiod_set_value_cansleep(st->convst_gpio, 0);
	udelay(1); /* CONVST pulse width: 10 ns min */
	gpiod_set_value_cansleep(st->convst_gpio, 1);
	udelay(1); /* Conversion time: 650 ns max */
}

static void bd79105_convst_disable(struct ad7476_state *st)
{
	gpiod_set_value_cansleep(st->convst_gpio, 0);
}

static void bd79105_convst_enable(struct ad7476_state *st)
{
	gpiod_set_value_cansleep(st->convst_gpio, 1);
	/* Worst case, 2790 ns required for conversion */
	ndelay(2790);
}

static irqreturn_t ad7476_trigger_handler(int irq, void  *p)
{
	struct iio_poll_func *pf = p;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct ad7476_state *st = iio_priv(indio_dev);
	int b_sent;

	if (st->chip_info->conversion_pre_op)
		st->chip_info->conversion_pre_op(st);

	b_sent = spi_sync(st->spi, &st->msg);
	if (b_sent < 0)
		goto done;

	iio_push_to_buffers_with_ts(indio_dev, st->data, sizeof(st->data),
				    iio_get_time_ns(indio_dev));
done:
	if (st->chip_info->conversion_post_op)
		st->chip_info->conversion_post_op(st);
	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static void ad7091_reset(struct ad7476_state *st)
{
	/* Any transfers with 8 scl cycles will reset the device */
	spi_read(st->spi, st->data, 1);
}

static int ad7476_scan_direct(struct ad7476_state *st)
{
	int ret;

	if (st->chip_info->conversion_pre_op)
		st->chip_info->conversion_pre_op(st);

	ret = spi_sync(st->spi, &st->msg);
	if (ret)

Annotation

Implementation Notes