drivers/hwmon/adm1031.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/adm1031.c
Extension
.c
Size
32562 bytes
Lines
1080
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 adm1031_data {
	struct i2c_client *client;
	const struct attribute_group *groups[3];
	struct mutex update_lock;
	int chip_type;
	bool valid;		/* true if following fields are valid */
	unsigned long last_updated;	/* In jiffies */
	unsigned int update_interval;	/* In milliseconds */
	/*
	 * The chan_select_table contains the possible configurations for
	 * auto fan control.
	 */
	const auto_chan_table_t *chan_select_table;
	u16 alarm;
	u8 conf1;
	u8 conf2;
	u8 fan[2];
	u8 fan_div[2];
	u8 fan_min[2];
	u8 pwm[2];
	u8 old_pwm[2];
	s8 temp[3];
	u8 ext_temp[3];
	u8 auto_temp[3];
	u8 auto_temp_min[3];
	u8 auto_temp_off[3];
	u8 auto_temp_max[3];
	s8 temp_offset[3];
	s8 temp_min[3];
	s8 temp_max[3];
	s8 temp_crit[3];
};

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

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

static struct adm1031_data *adm1031_update_device(struct device *dev)
{
	struct adm1031_data *data = dev_get_drvdata(dev);
	struct i2c_client *client = data->client;
	unsigned long next_update;
	int chan;

	mutex_lock(&data->update_lock);

	next_update = data->last_updated
	  + msecs_to_jiffies(data->update_interval);
	if (time_after(jiffies, next_update) || !data->valid) {

		dev_dbg(&client->dev, "Starting adm1031 update\n");
		for (chan = 0;
		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
			u8 oldh, newh;

			oldh =
			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
			data->ext_temp[chan] =
			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
			newh =
			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
			if (newh != oldh) {
				data->ext_temp[chan] =
				    adm1031_read_value(client,
						       ADM1031_REG_EXT_TEMP);
#ifdef DEBUG
				oldh =
				    adm1031_read_value(client,
						       ADM1031_REG_TEMP(chan));

				/* oldh is actually newer */
				if (newh != oldh)
					dev_warn(&client->dev,
					  "Remote temperature may be wrong.\n");
#endif
			}
			data->temp[chan] = newh;

			data->temp_offset[chan] =
			    adm1031_read_value(client,
					       ADM1031_REG_TEMP_OFFSET(chan));
			data->temp_min[chan] =
			    adm1031_read_value(client,

Annotation

Implementation Notes