drivers/hwmon/lm87.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/lm87.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/lm87.c
Extension
.c
Size
29840 bytes
Lines
1014
Domain
Driver Families
Bucket
drivers/hwmon
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 lm87_data {
	struct mutex update_lock;
	bool valid; /* false until following fields are valid */
	unsigned long last_updated; /* In jiffies */

	u8 channel;		/* register value */
	u8 config;		/* original register value */

	u8 in[8];		/* register value */
	u8 in_max[8];		/* register value */
	u8 in_min[8];		/* register value */
	u16 in_scale[8];

	s8 temp[3];		/* register value */
	s8 temp_high[3];	/* register value */
	s8 temp_low[3];		/* register value */
	s8 temp_crit_int;	/* min of two register values */
	s8 temp_crit_ext;	/* min of two register values */

	u8 fan[2];		/* register value */
	u8 fan_min[2];		/* register value */
	u8 fan_div[2];		/* register value, shifted right */
	u8 aout;		/* register value */

	u16 alarms;		/* register values, combined */
	u8 vid;			/* register values, combined */
	u8 vrm;

	const struct attribute_group *attr_groups[6];
};

static inline int lm87_read_value(struct i2c_client *client, u8 reg)
{
	return i2c_smbus_read_byte_data(client, reg);
}

static inline int lm87_write_value(struct i2c_client *client, u8 reg, u8 value)
{
	return i2c_smbus_write_byte_data(client, reg, value);
}

static struct lm87_data *lm87_update_device(struct device *dev)
{
	struct i2c_client *client = dev_get_drvdata(dev);
	struct lm87_data *data = i2c_get_clientdata(client);

	mutex_lock(&data->update_lock);

	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
		int i, j;

		dev_dbg(&client->dev, "Updating data.\n");

		i = (data->channel & CHAN_TEMP3) ? 1 : 0;
		j = (data->channel & CHAN_TEMP3) ? 5 : 6;
		for (; i < j; i++) {
			data->in[i] = lm87_read_value(client,
				      LM87_REG_IN(i));
			data->in_min[i] = lm87_read_value(client,
					  LM87_REG_IN_MIN(i));
			data->in_max[i] = lm87_read_value(client,
					  LM87_REG_IN_MAX(i));
		}

		for (i = 0; i < 2; i++) {
			if (data->channel & CHAN_NO_FAN(i)) {
				data->in[6+i] = lm87_read_value(client,
						LM87_REG_AIN(i));
				data->in_max[6+i] = lm87_read_value(client,
						    LM87_REG_AIN_MAX(i));
				data->in_min[6+i] = lm87_read_value(client,
						    LM87_REG_AIN_MIN(i));

			} else {
				data->fan[i] = lm87_read_value(client,
					       LM87_REG_FAN(i));
				data->fan_min[i] = lm87_read_value(client,
						   LM87_REG_FAN_MIN(i));
			}
		}

		j = (data->channel & CHAN_TEMP3) ? 3 : 2;
		for (i = 0 ; i < j; i++) {
			data->temp[i] = lm87_read_value(client,
					LM87_REG_TEMP[i]);
			data->temp_high[i] = lm87_read_value(client,
					     LM87_REG_TEMP_HIGH[i]);
			data->temp_low[i] = lm87_read_value(client,
					    LM87_REG_TEMP_LOW[i]);
		}

Annotation

Implementation Notes