drivers/hwmon/lm95241.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/lm95241.c
Extension
.c
Size
11356 bytes
Lines
466
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 lm95241_data {
	struct i2c_client *client;
	unsigned long last_updated;	/* in jiffies */
	unsigned long interval;		/* in milli-seconds */
	bool valid;		/* false until following fields are valid */
	/* registers values */
	u8 temp[ARRAY_SIZE(lm95241_reg_address)];
	u8 status, config, model, trutherm;
};

/* Conversions */
static int temp_from_reg_signed(u8 val_h, u8 val_l)
{
	s16 val_hl = (val_h << 8) | val_l;
	return val_hl * 1000 / 256;
}

static int temp_from_reg_unsigned(u8 val_h, u8 val_l)
{
	u16 val_hl = (val_h << 8) | val_l;
	return val_hl * 1000 / 256;
}

static struct lm95241_data *lm95241_update_device(struct device *dev)
{
	struct lm95241_data *data = dev_get_drvdata(dev);
	struct i2c_client *client = data->client;

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

		dev_dbg(dev, "Updating lm95241 data.\n");
		for (i = 0; i < ARRAY_SIZE(lm95241_reg_address); i++)
			data->temp[i]
			  = i2c_smbus_read_byte_data(client,
						     lm95241_reg_address[i]);

		data->status = i2c_smbus_read_byte_data(client,
							LM95241_REG_R_STATUS);
		data->last_updated = jiffies;
		data->valid = true;
	}
	return data;
}

static int lm95241_read_chip(struct device *dev, u32 attr, int channel,
			     long *val)
{
	struct lm95241_data *data = dev_get_drvdata(dev);

	switch (attr) {
	case hwmon_chip_update_interval:
		*val = data->interval;
		return 0;
	default:
		return -EOPNOTSUPP;
	}
}

static int lm95241_read_temp(struct device *dev, u32 attr, int channel,
			     long *val)
{
	struct lm95241_data *data = lm95241_update_device(dev);

	switch (attr) {
	case hwmon_temp_input:
		if (!channel || (data->config & BIT(channel - 1)))
			*val = temp_from_reg_signed(data->temp[channel * 2],
						data->temp[channel * 2 + 1]);
		else
			*val = temp_from_reg_unsigned(data->temp[channel * 2],
						data->temp[channel * 2 + 1]);
		return 0;
	case hwmon_temp_min:
		if (channel == 1)
			*val = (data->config & R1DF_MASK) ? -128000 : 0;
		else
			*val = (data->config & R2DF_MASK) ? -128000 : 0;
		return 0;
	case hwmon_temp_max:
		if (channel == 1)
			*val = (data->config & R1DF_MASK) ? 127875 : 255875;
		else
			*val = (data->config & R2DF_MASK) ? 127875 : 255875;
		return 0;
	case hwmon_temp_type:
		if (channel == 1)
			*val = (data->model & R1MS_MASK) ? 1 : 2;

Annotation

Implementation Notes