drivers/iio/temperature/tmp006.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/temperature/tmp006.c
Extension
.c
Size
9873 bytes
Lines
413
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 tmp006_data {
	struct i2c_client *client;
	u16 config;
	struct iio_trigger *drdy_trig;
};

static int tmp006_read_measurement(struct tmp006_data *data, u8 reg)
{
	s32 ret;
	int tries = 50;

	while (tries-- > 0) {
		ret = i2c_smbus_read_word_swapped(data->client,
			TMP006_CONFIG);
		if (ret < 0)
			return ret;
		if (ret & TMP006_CONFIG_DRDY)
			break;
		msleep(100);
	}

	if (tries < 0)
		return -EIO;

	return i2c_smbus_read_word_swapped(data->client, reg);
}

static const int tmp006_freqs[5][2] = { {4, 0}, {2, 0}, {1, 0},
					{0, 500000}, {0, 250000} };

static int tmp006_read_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *channel, int *val,
			    int *val2, long mask)
{
	struct tmp006_data *data = iio_priv(indio_dev);
	s32 ret;
	int cr;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		if (channel->type == IIO_VOLTAGE) {
			/* LSB is 156.25 nV */
			if (!iio_device_claim_direct(indio_dev))
				return -EBUSY;

			ret = tmp006_read_measurement(data, TMP006_VOBJECT);
			iio_device_release_direct(indio_dev);
			if (ret < 0)
				return ret;

			*val = sign_extend32(ret, 15);
		} else if (channel->type == IIO_TEMP) {
			/* LSB is 0.03125 degrees Celsius */
			if (!iio_device_claim_direct(indio_dev))
				return -EBUSY;

			ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
			iio_device_release_direct(indio_dev);
			if (ret < 0)
				return ret;

			*val = sign_extend32(ret, 15) >> TMP006_TAMBIENT_SHIFT;
		} else {
			break;
		}
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		if (channel->type == IIO_VOLTAGE) {
			*val = 0;
			*val2 = 156250;
		} else if (channel->type == IIO_TEMP) {
			*val = 31;
			*val2 = 250000;
		} else {
			break;
		}
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_SAMP_FREQ:
		cr = (data->config & TMP006_CONFIG_CR_MASK)
			>> TMP006_CONFIG_CR_SHIFT;
		*val = tmp006_freqs[cr][0];
		*val2 = tmp006_freqs[cr][1];
		return IIO_VAL_INT_PLUS_MICRO;
	default:
		break;
	}

	return -EINVAL;
}

Annotation

Implementation Notes