drivers/iio/temperature/maxim_thermocouple.c

Source file repositories/reference/linux-study-clean/drivers/iio/temperature/maxim_thermocouple.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/temperature/maxim_thermocouple.c
Extension
.c
Size
7638 bytes
Lines
306
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 maxim_thermocouple_chip {
	const struct iio_chan_spec *channels;
	const unsigned long *scan_masks;
	u8 num_channels;
	u8 read_size;

	/* bit-check for valid input */
	u32 status_bit;
};

static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
	[MAX6675] = {
			.channels = max6675_channels,
			.num_channels = ARRAY_SIZE(max6675_channels),
			.read_size = 2,
			.status_bit = BIT(2),
		},
	[MAX31855] = {
			.channels = max31855_channels,
			.num_channels = ARRAY_SIZE(max31855_channels),
			.read_size = 4,
			.scan_masks = max31855_scan_masks,
			.status_bit = BIT(16),
		},
};

struct maxim_thermocouple_data {
	struct spi_device *spi;
	const struct maxim_thermocouple_chip *chip;
	char tc_type;
	/* Buffer for reading up to 2 hardware channels. */
	struct {
		union {
			__be16 raw16;
			__be32 raw32;
			__be16 raw[2];
		};
		aligned_s64 timestamp;
	} buffer __aligned(IIO_DMA_MINALIGN);
};

static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
				   struct iio_chan_spec const *chan, int *val)
{
	unsigned int storage_bytes = data->chip->read_size;
	unsigned int shift = chan->scan_type.shift + (chan->address * 8);
	int ret;

	switch (storage_bytes) {
	case 2:
		ret = spi_read(data->spi, &data->buffer.raw16, storage_bytes);
		*val = be16_to_cpu(data->buffer.raw16);
		break;
	case 4:
		ret = spi_read(data->spi, &data->buffer.raw32, storage_bytes);
		*val = be32_to_cpu(data->buffer.raw32);
		break;
	default:
		ret = -EINVAL;
	}

	if (ret)
		return ret;

	/* check to be sure this is a valid reading */
	if (*val & data->chip->status_bit)
		return -EINVAL;

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

	return 0;
}

static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private)
{
	struct iio_poll_func *pf = private;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct maxim_thermocouple_data *data = iio_priv(indio_dev);
	int ret;

	ret = spi_read(data->spi, data->buffer.raw, data->chip->read_size);
	if (!ret) {
		iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
					    sizeof(data->buffer),
					    iio_get_time_ns(indio_dev));
	}

	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;

Annotation

Implementation Notes