drivers/hwmon/lm95234.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/lm95234.c
Extension
.c
Size
14584 bytes
Lines
557
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 lm95234_data {
	struct regmap *regmap;
	enum chips type;
};

static int lm95234_read_temp(struct regmap *regmap, int index, long *t)
{
	unsigned int regs[2];
	int temp = 0, ret;
	u8 regvals[2];

	if (index) {
		regs[0] = LM95234_REG_UTEMPH(index - 1);
		regs[1] = LM95234_REG_UTEMPL(index - 1);
		ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
		if (ret)
			return ret;
		temp = (regvals[0] << 8) | regvals[1];
	}
	/*
	 * Read signed temperature if unsigned temperature is 0,
	 * or if this is the local sensor.
	 */
	if (!temp) {
		regs[0] = LM95234_REG_TEMPH(index);
		regs[1] = LM95234_REG_TEMPL(index);
		ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
		if (ret)
			return ret;
		temp = (regvals[0] << 8) | regvals[1];
		temp = sign_extend32(temp, 15);
	}
	*t = DIV_ROUND_CLOSEST(temp * 125, 32);
	return 0;
}

static int lm95234_hyst_get(struct regmap *regmap, int reg, long *val)
{
	unsigned int regs[2] = {reg, LM95234_REG_TCRIT_HYST};
	u8 regvals[2];
	int ret;

	ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
	if (ret)
		return ret;
	*val = (regvals[0] - regvals[1]) * 1000;
	return 0;
}

static ssize_t lm95234_hyst_set(struct lm95234_data *data, long val)
{
	u32 tcrit;
	int ret;

	ret = regmap_read(data->regmap, LM95234_REG_TCRIT1(0), &tcrit);
	if (ret)
		return ret;

	val = DIV_ROUND_CLOSEST(clamp_val(val, -255000, 255000), 1000);
	val = clamp_val((int)tcrit - val, 0, 31);

	return regmap_write(data->regmap, LM95234_REG_TCRIT_HYST, val);
}

static int lm95234_crit_reg(int channel)
{
	if (channel == 1 || channel == 2)
		return LM95234_REG_TCRIT2(channel - 1);
	return LM95234_REG_TCRIT1(channel);
}

static int lm95234_temp_write(struct device *dev, u32 attr, int channel, long val)
{
	struct lm95234_data *data = dev_get_drvdata(dev);
	struct regmap *regmap = data->regmap;

	switch (attr) {
	case hwmon_temp_enable:
		if (val && val != 1)
			return -EINVAL;
		return regmap_update_bits(regmap, LM95234_REG_ENABLE,
					  BIT(channel), val ? BIT(channel) : 0);
	case hwmon_temp_type:
		if (val != 1 && val != 2)
			return -EINVAL;
		return regmap_update_bits(regmap, LM95234_REG_REM_MODEL,
					  BIT(channel),
					  val == 1 ? BIT(channel) : 0);
	case hwmon_temp_offset:
		val = DIV_ROUND_CLOSEST(clamp_val(val, -64000, 63500), 500);

Annotation

Implementation Notes