drivers/hwmon/lm77.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/lm77.c
Extension
.c
Size
10182 bytes
Lines
362
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 lm77_data {
	struct i2c_client	*client;
	struct mutex		update_lock;
	bool			valid;
	unsigned long		last_updated;	/* In jiffies */
	int			temp[t_num_temp]; /* index using temp_index */
	u8			alarms;
};

/* straight from the datasheet */
#define LM77_TEMP_MIN (-55000)
#define LM77_TEMP_MAX 125000

/*
 * In the temperature registers, the low 3 bits are not part of the
 * temperature values; they are the status bits.
 */
static inline s16 LM77_TEMP_TO_REG(int temp)
{
	return (temp / 500) * 8;
}

static inline int LM77_TEMP_FROM_REG(s16 reg)
{
	return (reg / 8) * 500;
}

/*
 * All registers are word-sized, except for the configuration register.
 * The LM77 uses the high-byte first convention.
 */
static u16 lm77_read_value(struct i2c_client *client, u8 reg)
{
	if (reg == LM77_REG_CONF)
		return i2c_smbus_read_byte_data(client, reg);
	else
		return i2c_smbus_read_word_swapped(client, reg);
}

static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value)
{
	if (reg == LM77_REG_CONF)
		return i2c_smbus_write_byte_data(client, reg, value);
	else
		return i2c_smbus_write_word_swapped(client, reg, value);
}

static struct lm77_data *lm77_update_device(struct device *dev)
{
	struct lm77_data *data = dev_get_drvdata(dev);
	struct i2c_client *client = data->client;
	int i;

	mutex_lock(&data->update_lock);

	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
	    || !data->valid) {
		dev_dbg(&client->dev, "Starting lm77 update\n");
		for (i = 0; i < t_num_temp; i++) {
			data->temp[i] =
			  LM77_TEMP_FROM_REG(lm77_read_value(client,
							     temp_regs[i]));
		}
		data->alarms =
			lm77_read_value(client, LM77_REG_TEMP) & 0x0007;
		data->last_updated = jiffies;
		data->valid = true;
	}

	mutex_unlock(&data->update_lock);

	return data;
}

/* sysfs stuff */

static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
			 char *buf)
{
	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
	struct lm77_data *data = lm77_update_device(dev);

	return sprintf(buf, "%d\n", data->temp[attr->index]);
}

static ssize_t temp_hyst_show(struct device *dev,
			      struct device_attribute *devattr, char *buf)
{
	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
	struct lm77_data *data = lm77_update_device(dev);

Annotation

Implementation Notes