drivers/iio/adc/ad7292.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ad7292.c
Extension
.c
Size
8037 bytes
Lines
327
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 ad7292_state {
	struct spi_device *spi;
	unsigned short vref_mv;

	__be16 d16 __aligned(IIO_DMA_MINALIGN);
	u8 d8[2];
};

static int ad7292_spi_reg_read(struct ad7292_state *st, unsigned int addr)
{
	int ret;

	st->d8[0] = AD7292_RD_FLAG_MSK(addr);

	ret = spi_write_then_read(st->spi, st->d8, 1, &st->d16, 2);
	if (ret < 0)
		return ret;

	return be16_to_cpu(st->d16);
}

static int ad7292_spi_subreg_read(struct ad7292_state *st, unsigned int addr,
				  unsigned int sub_addr, unsigned int len)
{
	unsigned int shift = 16 - (8 * len);
	int ret;

	st->d8[0] = AD7292_RD_FLAG_MSK(addr);
	st->d8[1] = sub_addr;

	ret = spi_write_then_read(st->spi, st->d8, 2, &st->d16, len);
	if (ret < 0)
		return ret;

	return (be16_to_cpu(st->d16) >> shift);
}

static int ad7292_single_conversion(struct ad7292_state *st,
				    unsigned int chan_addr)
{
	int ret;

	struct spi_transfer t[] = {
		{
			.tx_buf = &st->d8,
			.len = 4,
			.delay = {
				.value = 6,
				.unit = SPI_DELAY_UNIT_USECS
			},
		}, {
			.rx_buf = &st->d16,
			.len = 2,
		},
	};

	st->d8[0] = chan_addr;
	st->d8[1] = AD7292_RD_FLAG_MSK(AD7292_REG_CONV_COMM);

	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));

	if (ret < 0)
		return ret;

	return be16_to_cpu(st->d16);
}

static int ad7292_vin_range_multiplier(struct ad7292_state *st, int channel)
{
	int samp_mode, range0, range1, factor = 1;

	/*
	 * Every AD7292 ADC channel may have its input range adjusted according
	 * to the settings at the ADC sampling mode and VIN range subregisters.
	 * For a given channel, the minimum input range is equal to Vref, and it
	 * may be increased by a multiplier factor of 2 or 4 according to the
	 * following rule:
	 * If channel is being sampled with respect to AGND:
	 *	factor = 4 if VIN range0 and VIN range1 equal 0
	 *	factor = 2 if only one of VIN ranges equal 1
	 *	factor = 1 if both VIN range0 and VIN range1 equal 1
	 * If channel is being sampled with respect to AVDD:
	 *	factor = 4 if VIN range0 and VIN range1 equal 0
	 *	Behavior is undefined if any of VIN range doesn't equal 0
	 */

	samp_mode = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK,
					   AD7292_BANK_REG_SAMP_MODE, 2);

	if (samp_mode < 0)

Annotation

Implementation Notes