drivers/hwmon/lm80.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/lm80.c
Extension
.c
Size
18710 bytes
Lines
648
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 lm80_data {
	struct i2c_client *client;
	struct mutex update_lock;
	char error;		/* !=0 if error occurred during last update */
	bool valid;		/* true if following fields are valid */
	unsigned long last_updated;	/* In jiffies */

	u8 in[i_num_in][7];	/* Register value, 1st index is enum in_index */
	u8 fan[f_num_fan][2];	/* Register value, 1st index enum fan_index */
	u8 fan_div[2];		/* Register encoding, shifted right */
	s16 temp[t_num_temp];	/* Register values, normalized to 16 bit */
	u16 alarms;		/* Register encoding, combined */
};

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

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

/* Called when we have found a new LM80 and after read errors */
static void lm80_init_client(struct i2c_client *client)
{
	/*
	 * Reset all except Watchdog values and last conversion values
	 * This sets fan-divs to 2, among others. This makes most other
	 * initializations unnecessary
	 */
	lm80_write_value(client, LM80_REG_CONFIG, 0x80);
	/* Set 11-bit temperature resolution */
	lm80_write_value(client, LM80_REG_RES, 0x08);

	/* Start monitoring */
	lm80_write_value(client, LM80_REG_CONFIG, 0x01);
}

static struct lm80_data *lm80_update_device(struct device *dev)
{
	struct lm80_data *data = dev_get_drvdata(dev);
	struct i2c_client *client = data->client;
	int i;
	int rv;
	int prev_rv;
	struct lm80_data *ret = data;

	mutex_lock(&data->update_lock);

	if (data->error)
		lm80_init_client(client);

	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
		dev_dbg(dev, "Starting lm80 update\n");
		for (i = 0; i <= 6; i++) {
			rv = lm80_read_value(client, LM80_REG_IN(i));
			if (rv < 0)
				goto abort;
			data->in[i_input][i] = rv;

			rv = lm80_read_value(client, LM80_REG_IN_MIN(i));
			if (rv < 0)
				goto abort;
			data->in[i_min][i] = rv;

			rv = lm80_read_value(client, LM80_REG_IN_MAX(i));
			if (rv < 0)
				goto abort;
			data->in[i_max][i] = rv;
		}

		rv = lm80_read_value(client, LM80_REG_FAN1);
		if (rv < 0)
			goto abort;
		data->fan[f_input][0] = rv;

		rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
		if (rv < 0)
			goto abort;
		data->fan[f_min][0] = rv;

		rv = lm80_read_value(client, LM80_REG_FAN2);
		if (rv < 0)
			goto abort;
		data->fan[f_input][1] = rv;

		rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
		if (rv < 0)

Annotation

Implementation Notes