drivers/iio/adc/ti-adc161s626.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ti-adc161s626.c
Extension
.c
Size
5608 bytes
Lines
252
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 ti_adc_data {
	struct iio_dev *indio_dev;
	struct spi_device *spi;
	struct regulator *ref;

	u8 read_size;
	u8 shift;
	u8 buf[3] __aligned(IIO_DMA_MINALIGN);
};

static int ti_adc_read_measurement(struct ti_adc_data *data,
				   struct iio_chan_spec const *chan, int *val)
{
	int ret;

	switch (data->read_size) {
	case 2:
		ret = spi_read(data->spi, data->buf, 2);
		if (ret)
			return ret;

		*val = get_unaligned_be16(data->buf);
		break;
	case 3:
		ret = spi_read(data->spi, data->buf, 3);
		if (ret)
			return ret;

		*val = get_unaligned_be24(data->buf);
		break;
	default:
		return -EINVAL;
	}

	*val = sign_extend32(*val >> data->shift, chan->scan_type.realbits - 1);

	return 0;
}

static irqreturn_t ti_adc_trigger_handler(int irq, void *private)
{
	struct iio_poll_func *pf = private;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct ti_adc_data *data = iio_priv(indio_dev);
	struct {
		s16 data;
		aligned_s64 timestamp;
	} scan = { };
	int ret, val;

	ret = ti_adc_read_measurement(data, &indio_dev->channels[0], &val);
	if (ret)
		goto exit_notify_done;

	scan.data = val;
	iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev));

 exit_notify_done:
	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static int ti_adc_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	struct ti_adc_data *data = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		if (!iio_device_claim_direct(indio_dev))
			return -EBUSY;
		ret = ti_adc_read_measurement(data, chan, val);
		iio_device_release_direct(indio_dev);
		if (ret)
			return ret;
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		ret = regulator_get_voltage(data->ref);
		if (ret < 0)
			return ret;

		*val = ret / 1000;
		*val2 = chan->scan_type.realbits;

		return IIO_VAL_FRACTIONAL_LOG2;
	case IIO_CHAN_INFO_OFFSET:
		*val = 1 << (chan->scan_type.realbits - 1);

Annotation

Implementation Notes