drivers/iio/adc/ad7949.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ad7949.c
Extension
.c
Size
11407 bytes
Lines
440
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 ad7949_adc_spec {
	u8 num_channels;
	u8 resolution;
};

static const struct ad7949_adc_spec ad7949_adc_spec[] = {
	[ID_AD7949] = { .num_channels = 8, .resolution = 14 },
	[ID_AD7682] = { .num_channels = 4, .resolution = 16 },
	[ID_AD7689] = { .num_channels = 8, .resolution = 16 },
};

/**
 * struct ad7949_adc_chip - AD ADC chip
 * @lock: protects write sequences
 * @vref: regulator generating Vref
 * @indio_dev: reference to iio structure
 * @spi: reference to spi structure
 * @refsel: reference selection
 * @resolution: resolution of the chip
 * @cfg: copy of the configuration register
 * @current_channel: current channel in use
 * @buffer: buffer to send / receive data to / from device
 * @buf8b: be16 buffer to exchange data with the device in 8-bit transfers
 */
struct ad7949_adc_chip {
	struct mutex lock;
	struct regulator *vref;
	struct iio_dev *indio_dev;
	struct spi_device *spi;
	u32 refsel;
	u8 resolution;
	u16 cfg;
	unsigned int current_channel;
	u16 buffer __aligned(IIO_DMA_MINALIGN);
	__be16 buf8b;
};

static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val,
				u16 mask)
{
	int ret;

	ad7949_adc->cfg = (val & mask) | (ad7949_adc->cfg & ~mask);

	switch (ad7949_adc->spi->bits_per_word) {
	case 16:
		ad7949_adc->buffer = ad7949_adc->cfg << 2;
		ret = spi_write(ad7949_adc->spi, &ad7949_adc->buffer, 2);
		break;
	case 14:
		ad7949_adc->buffer = ad7949_adc->cfg;
		ret = spi_write(ad7949_adc->spi, &ad7949_adc->buffer, 2);
		break;
	case 8:
		/* Here, type is big endian as it must be sent in two transfers */
		ad7949_adc->buf8b = cpu_to_be16(ad7949_adc->cfg << 2);
		ret = spi_write(ad7949_adc->spi, &ad7949_adc->buf8b, 2);
		break;
	default:
		dev_err(&ad7949_adc->indio_dev->dev, "unsupported BPW\n");
		return -EINVAL;
	}

	/*
	 * This delay is to avoid a new request before the required time to
	 * send a new command to the device
	 */
	udelay(2);
	return ret;
}

static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
				   unsigned int channel)
{
	int ret;
	int i;

	/*
	 * 1: write CFG for sample N and read old data (sample N-2)
	 * 2: if CFG was not changed since sample N-1 then we'll get good data
	 *    at the next xfer, so we bail out now, otherwise we write something
	 *    and we read garbage (sample N-1 configuration).
	 */
	for (i = 0; i < 2; i++) {
		ret = ad7949_spi_write_cfg(ad7949_adc,
					   FIELD_PREP(AD7949_CFG_MASK_INX, channel),
					   AD7949_CFG_MASK_INX);
		if (ret)
			return ret;
		if (channel == ad7949_adc->current_channel)

Annotation

Implementation Notes