drivers/iio/temperature/mlx90614.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/temperature/mlx90614.c
Extension
.c
Size
21919 bytes
Lines
784
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 mlx_chip_info {
	/* EEPROM offsets with 16-bit data, MSB first */
	/* emissivity correction coefficient */
	u8			op_eeprom_emissivity;
	u8			op_eeprom_config1;
	/* RAM offsets with 16-bit data, MSB first */
	/* ambient temperature */
	u8			op_ram_ta;
	/* object 1 temperature */
	u8			op_ram_tobj1;
	/* object 2 temperature */
	u8			op_ram_tobj2;
	u8			op_sleep;
	/* support for two input channels (MLX90614 only) */
	u8			dual_channel;
	u8			wakeup_delay_ms;
	u16			emissivity_max;
	u16			fir_config_mask;
	u16			iir_config_mask;
	int			iir_valid_offset;
	u16			iir_values[8];
	int			iir_freqs[8][2];
};

struct mlx90614_data {
	struct i2c_client *client;
	struct mutex lock; /* for EEPROM access only */
	struct gpio_desc *wakeup_gpio; /* NULL to disable sleep/wake-up */
	const struct mlx_chip_info *chip_info; /* Chip hardware details */
	unsigned long ready_timestamp; /* in jiffies */
};

/*
 * Erase an address and write word.
 * The mutex must be locked before calling.
 */
static s32 mlx90614_write_word(const struct i2c_client *client, u8 command,
			       u16 value)
{
	/*
	 * Note: The mlx90614 requires a PEC on writing but does not send us a
	 * valid PEC on reading.  Hence, we cannot set I2C_CLIENT_PEC in
	 * i2c_client.flags.  As a workaround, we use i2c_smbus_xfer here.
	 */
	union i2c_smbus_data data;
	s32 ret;

	dev_dbg(&client->dev, "Writing 0x%x to address 0x%x", value, command);

	data.word = 0x0000; /* erase command */
	ret = i2c_smbus_xfer(client->adapter, client->addr,
			     client->flags | I2C_CLIENT_PEC,
			     I2C_SMBUS_WRITE, command,
			     I2C_SMBUS_WORD_DATA, &data);
	if (ret < 0)
		return ret;

	msleep(MLX90614_TIMING_EEPROM);

	data.word = value; /* actual write */
	ret = i2c_smbus_xfer(client->adapter, client->addr,
			     client->flags | I2C_CLIENT_PEC,
			     I2C_SMBUS_WRITE, command,
			     I2C_SMBUS_WORD_DATA, &data);

	msleep(MLX90614_TIMING_EEPROM);

	return ret;
}

/*
 * Find the IIR value inside iir_values array and return its position
 * which is equivalent to the bit value in sensor register
 */
static inline s32 mlx90614_iir_search(const struct i2c_client *client,
				      int value)
{
	struct iio_dev *indio_dev = i2c_get_clientdata(client);
	struct mlx90614_data *data = iio_priv(indio_dev);
	const struct mlx_chip_info *chip_info = data->chip_info;
	int i;
	s32 ret;

	for (i = chip_info->iir_valid_offset;
	     i < ARRAY_SIZE(chip_info->iir_values);
	     i++) {
		if (value == chip_info->iir_values[i])
			break;
	}

Annotation

Implementation Notes