drivers/iio/pressure/adp810.c

Source file repositories/reference/linux-study-clean/drivers/iio/pressure/adp810.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/pressure/adp810.c
Extension
.c
Size
5451 bytes
Lines
226
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 adp810_read_buf {
	__be16 dp;
	u8 dp_crc;
	__be16 tmp;
	u8 tmp_crc;
	__be16 sf;
	u8 sf_crc;
} __packed;

struct adp810_data {
	struct i2c_client *client;
	/* Use lock to synchronize access to device during read sequence */
	struct mutex lock;
};

static int adp810_measure(struct adp810_data *data, struct adp810_read_buf *buf)
{
	struct i2c_client *client = data->client;
	struct device *dev = &client->dev;
	int ret;
	u8 trig_cmd[2] = {0x37, 0x2d};

	/* Send trigger command to the sensor for measurement */
	ret = i2c_master_send(client, trig_cmd, sizeof(trig_cmd));
	if (ret < 0) {
		dev_err(dev, "Error sending trigger command\n");
		return ret;
	}
	if (ret != sizeof(trig_cmd))
		return -EIO;

	/*
	 * Wait for the sensor to acquire data. As per datasheet section 5.3.1,
	 * at least 10ms delay before reading from the sensor is recommended.
	 * Here, we wait for 20ms to have some safe margin on the top
	 * of recommendation and to compensate for any possible variations.
	 */
	msleep(20);

	/* Read sensor values */
	ret = i2c_master_recv(client, (char *)buf, sizeof(*buf));
	if (ret < 0) {
		dev_err(dev, "Error reading from sensor\n");
		return ret;
	}
	if (ret != sizeof(*buf))
		return -EIO;

	/* CRC checks */
	crc8_populate_msb(crc_table, ADP810_CRC8_POLYNOMIAL);
	if (buf->dp_crc != crc8(crc_table, (u8 *)&buf->dp, 0x2, CRC8_INIT_VALUE)) {
		dev_err(dev, "CRC error for pressure\n");
		return -EIO;
	}

	if (buf->tmp_crc != crc8(crc_table, (u8 *)&buf->tmp, 0x2, CRC8_INIT_VALUE)) {
		dev_err(dev, "CRC error for temperature\n");
		return -EIO;
	}

	if (buf->sf_crc != crc8(crc_table, (u8 *)&buf->sf, 0x2, CRC8_INIT_VALUE)) {
		dev_err(dev, "CRC error for scale\n");
		return -EIO;
	}

	return 0;
}

static int adp810_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	struct adp810_data *data = iio_priv(indio_dev);
	struct device *dev = &data->client->dev;
	struct adp810_read_buf buf = { };
	int ret;

	scoped_guard(mutex, &data->lock) {
		ret = adp810_measure(data, &buf);
		if (ret) {
			dev_err(dev, "Failed to read from device\n");
			return ret;
		}
	}

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		switch (chan->type) {
		case IIO_PRESSURE:
			*val = get_unaligned_be16(&buf.dp);

Annotation

Implementation Notes