drivers/hwmon/ltc2991.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/ltc2991.c
Extension
.c
Size
9655 bytes
Lines
431
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 ltc2991_state {
	struct regmap		*regmap;
	u32			r_sense_uohm[LTC2991_MAX_CHANNEL];
	bool			temp_en[LTC2991_MAX_CHANNEL];
};

static int ltc2991_read_reg(struct ltc2991_state *st, u8 addr, u8 reg_len,
			    int *val)
{
	__be16 regvals;
	int ret;

	if (reg_len < 2)
		return regmap_read(st->regmap, addr, val);

	ret = regmap_bulk_read(st->regmap, addr, &regvals, reg_len);
	if (ret)
		return ret;

	*val = be16_to_cpu(regvals);

	return 0;
}

static int ltc2991_get_voltage(struct ltc2991_state *st, u32 reg, long *val)
{
	int reg_val, ret, offset = 0;

	ret = ltc2991_read_reg(st, reg, 2, &reg_val);
	if (ret)
		return ret;

	if (reg == LTC2991_VCC_MSB)
		/* Vcc 2.5V offset */
		offset = 2500;

	/* Vx, 305.18uV/LSB */
	*val = DIV_ROUND_CLOSEST(sign_extend32(reg_val, 14) * 30518,
				 1000 * 100) + offset;

	return 0;
}

static int ltc2991_read_in(struct device *dev, u32 attr, int channel, long *val)
{
	struct ltc2991_state *st = dev_get_drvdata(dev);
	u32 reg;

	switch (attr) {
	case hwmon_in_input:
		if (channel == LTC2991_VCC_CH_NR)
			reg = LTC2991_VCC_MSB;
		else
			reg = LTC2991_CHANNEL_V_MSB(channel - 1);

		return ltc2991_get_voltage(st, reg, val);
	default:
		return -EOPNOTSUPP;
	}
}

static int ltc2991_get_curr(struct ltc2991_state *st, u32 reg, int channel,
			    long *val)
{
	int reg_val, ret;

	ret = ltc2991_read_reg(st, reg, 2, &reg_val);
	if (ret)
		return ret;

	/* Vx-Vy, 19.075uV/LSB */
	*val = DIV_ROUND_CLOSEST(sign_extend32(reg_val, 14) * 19075,
				 (s32)st->r_sense_uohm[channel]);

	return 0;
}

static int ltc2991_read_curr(struct device *dev, u32 attr, int channel,
			     long *val)
{
	struct ltc2991_state *st = dev_get_drvdata(dev);
	u32 reg;

	switch (attr) {
	case hwmon_curr_input:
		reg = LTC2991_CHANNEL_C_MSB(channel);
		return ltc2991_get_curr(st, reg, channel, val);
	default:
		return -EOPNOTSUPP;
	}

Annotation

Implementation Notes