drivers/iio/temperature/tsys01.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/temperature/tsys01.c
Extension
.c
Size
5594 bytes
Lines
236
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 tsys01_dev {
	void *client;
	struct mutex lock; /* lock during conversion */

	int (*reset)(void *cli, u8 cmd, unsigned int delay);
	int (*convert_and_read)(void *cli, u8 conv, u8 rd,
				unsigned int delay, u32 *adc);
	int (*read_prom_word)(void *cli, int cmd, u16 *word);

	u16 prom[TSYS01_PROM_WORDS_NB];
};

/* Multiplication coefficients for temperature computation */
static const int coeff_mul[] = { -1500000, 1000000, -2000000,
				 4000000, -2000000 };

static int tsys01_read_temperature(struct iio_dev *indio_dev,
				   s32 *temperature)
{
	int ret, i;
	u32 adc;
	s64 temp = 0;
	struct tsys01_dev *dev_data = iio_priv(indio_dev);

	mutex_lock(&dev_data->lock);
	ret = dev_data->convert_and_read(dev_data->client,
					 TSYS01_CONVERSION_START,
					 TSYS01_ADC_READ, 9000, &adc);
	mutex_unlock(&dev_data->lock);
	if (ret)
		return ret;

	adc >>= 8;

	/* Temperature algorithm */
	for (i = 4; i > 0; i--) {
		temp += coeff_mul[i] *
			(s64)dev_data->prom[5 - i];
		temp *= (s64)adc;
		temp = div64_s64(temp, 100000);
	}
	temp *= 10;
	temp += coeff_mul[0] * (s64)dev_data->prom[5];
	temp = div64_s64(temp, 100000);

	*temperature = temp;

	return 0;
}

static int tsys01_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *channel, int *val,
			   int *val2, long mask)
{
	int ret;
	s32 temperature;

	switch (mask) {
	case IIO_CHAN_INFO_PROCESSED:
		switch (channel->type) {
		case IIO_TEMP:	/* in milli °C */
			ret = tsys01_read_temperature(indio_dev, &temperature);
			if (ret)
				return ret;
			*val = temperature;

			return IIO_VAL_INT;
		default:
			return -EINVAL;
		}
	default:
		return -EINVAL;
	}
}

static const struct iio_chan_spec tsys01_channels[] = {
	{
		.type = IIO_TEMP,
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_PROCESSED),
	}
};

static const struct iio_info tsys01_info = {
	.read_raw = tsys01_read_raw,
};

static bool tsys01_crc_valid(u16 *n_prom)
{
	u8 cnt;
	u8 sum = 0;

Annotation

Implementation Notes