drivers/iio/humidity/ens210.c

Source file repositories/reference/linux-study-clean/drivers/iio/humidity/ens210.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/humidity/ens210.c
Extension
.c
Size
8828 bytes
Lines
340
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 ens210_chip_info {
	const char *name;
	enum ens210_partnumber part_id;
	unsigned int conv_time_msec;
};

/**
 * struct ens210_data - Humidity/Temperature sensor device structure
 * @client:	i2c client
 * @chip_info:	chip specific information
 * @lock:	lock protecting against simultaneous callers of get_measurement
 *		since multiple uninterrupted transactions are required
 */
struct ens210_data {
	struct i2c_client *client;
	const struct ens210_chip_info *chip_info;
	struct mutex lock;
};

/* calculate 17-bit crc7 */
static u8 ens210_crc7(u32 val)
{
	unsigned int val_be = (val & 0x1ffff) >> 0x8;

	return crc7_be(0xde, (u8 *)&val_be, 3) >> 1;
}

static int ens210_get_measurement(struct iio_dev *indio_dev, bool temp, int *val)
{
	struct ens210_data *data = iio_priv(indio_dev);
	struct device *dev = &data->client->dev;
	u32 regval;
	u8 regval_le[3];
	int ret;

	/* assert read */
	ret = i2c_smbus_write_byte_data(data->client, ENS210_REG_SENS_START,
					temp ? ENS210_SENS_START_T_START :
					       ENS210_SENS_START_H_START);
	if (ret)
		return ret;

	/* wait for conversion to be ready */
	msleep(data->chip_info->conv_time_msec);

	ret = i2c_smbus_read_byte_data(data->client, ENS210_REG_SENS_STAT);
	if (ret < 0)
		return ret;

	/* perform read */
	ret = i2c_smbus_read_i2c_block_data(
		data->client, temp ? ENS210_REG_T_VAL : ENS210_REG_H_VAL, 3,
		regval_le);
	if (ret < 0) {
		dev_err(dev, "failed to read register");
		return -EIO;
	}
	if (ret != 3) {
		dev_err(dev, "expected 3 bytes, received %d\n", ret);
		return -EIO;
	}

	regval = get_unaligned_le24(regval_le);
	if (ens210_crc7(regval) != ((regval >> 17) & 0x7f)) {
		dev_err(dev, "invalid crc\n");
		return -EIO;
	}

	if (!((regval >> 16) & 0x1)) {
		dev_err(dev, "data is not valid");
		return -EIO;
	}

	*val = regval & GENMASK(15, 0);
	return IIO_VAL_INT;
}

static int ens210_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *channel, int *val,
			   int *val2, long mask)
{
	struct ens210_data *data = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		scoped_guard(mutex, &data->lock) {
			ret = ens210_get_measurement(
				indio_dev, channel->type == IIO_TEMP, val);
			if (ret)

Annotation

Implementation Notes