drivers/iio/adc/ti-tlc4541.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ti-tlc4541.c
Extension
.c
Size
6714 bytes
Lines
264
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 tlc4541_state {
	struct spi_device               *spi;
	struct regulator                *reg;
	struct spi_transfer             scan_single_xfer[3];
	struct spi_message              scan_single_msg;

	/*
	 * DMA (thus cache coherency maintenance) may require the
	 * transfer buffers to live in their own cache lines.
	 * 2 bytes data + 6 bytes padding + 8 bytes timestamp when
	 * call iio_push_to_buffers_with_timestamp.
	 */
	__be16                          rx_buf[8] __aligned(IIO_DMA_MINALIGN);
};

struct tlc4541_chip_info {
	const struct iio_chan_spec *channels;
	unsigned int num_channels;
};

enum tlc4541_id {
	TLC3541,
	TLC4541,
};

#define TLC4541_V_CHAN(bits, bitshift) {                              \
		.type = IIO_VOLTAGE,                                  \
		.info_mask_separate       = BIT(IIO_CHAN_INFO_RAW),   \
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
		.scan_type = {                                        \
			.sign = 'u',                                  \
			.realbits = (bits),                           \
			.storagebits = 16,                            \
			.shift = (bitshift),                          \
			.endianness = IIO_BE,                         \
		},                                                    \
	}

#define DECLARE_TLC4541_CHANNELS(name, bits, bitshift) \
const struct iio_chan_spec name ## _channels[] = { \
	TLC4541_V_CHAN(bits, bitshift), \
	IIO_CHAN_SOFT_TIMESTAMP(1), \
}

static DECLARE_TLC4541_CHANNELS(tlc3541, 14, 2);
static DECLARE_TLC4541_CHANNELS(tlc4541, 16, 0);

static const struct tlc4541_chip_info tlc4541_chip_info[] = {
	[TLC3541] = {
		.channels = tlc3541_channels,
		.num_channels = ARRAY_SIZE(tlc3541_channels),
	},
	[TLC4541] = {
		.channels = tlc4541_channels,
		.num_channels = ARRAY_SIZE(tlc4541_channels),
	},
};

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

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

	iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf),
				    iio_get_time_ns(indio_dev));

done:
	iio_trigger_notify_done(indio_dev->trig);
	return IRQ_HANDLED;
}

static int tlc4541_get_range(struct tlc4541_state *st)
{
	int vref;

	vref = regulator_get_voltage(st->reg);
	if (vref < 0)
		return vref;

	vref /= 1000;

	return vref;
}

Annotation

Implementation Notes