drivers/hwmon/ltc4283.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/ltc4283.c
Extension
.c
Size
50789 bytes
Lines
1796
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 ltc4283_hwmon {
	struct regmap *map;
	struct i2c_client *client;
	unsigned long gpio_mask;
	unsigned long ch_enable_mask;
	/* in microwatt */
	unsigned long power_max;
	/* in millivolt */
	u32 vsense_max;
	/* in tenths of microohm*/
	u32 rsense;
	bool energy_en;
	bool ext_fault;
};

static int ltc4283_read_voltage_word(const struct ltc4283_hwmon *st,
				     u32 reg, u32 fs, long *val)
{
	unsigned int __raw;
	int ret;

	ret = regmap_read(st->map, reg, &__raw);
	if (ret)
		return ret;

	*val = DIV_ROUND_CLOSEST(__raw * fs, BIT(16));
	return 0;
}

static int ltc4283_read_voltage_byte(const struct ltc4283_hwmon *st,
				     u32 reg, u32 fs, long *val)
{
	int ret;
	u32 in;

	ret = regmap_read(st->map, reg, &in);
	if (ret)
		return ret;

	*val = DIV_ROUND_CLOSEST(in * fs, BIT(8));
	return 0;
}

static u32 ltc4283_in_reg(u32 attr, u32 channel)
{
	switch (attr) {
	case hwmon_in_input:
		if (channel == LTC4283_CHAN_VPWR)
			return LTC4283_VPWR;
		if (channel >= LTC4283_CHAN_ADI_1 && channel <= LTC4283_CHAN_DRAIN)
			return LTC4283_ADC_2(channel - LTC4283_CHAN_ADI_1);
		return LTC4283_ADC_2_DIFF(channel - LTC4283_CHAN_ADIN12);
	case hwmon_in_highest:
		if (channel == LTC4283_CHAN_VPWR)
			return LTC4283_VPWR_MAX;
		if (channel >= LTC4283_CHAN_ADI_1 && channel <= LTC4283_CHAN_DRAIN)
			return LTC4283_ADC_2_MAX(channel - LTC4283_CHAN_ADI_1);
		return LTC4283_ADC_2_MAX_DIFF(channel - LTC4283_CHAN_ADIN12);
	case hwmon_in_lowest:
		if (channel == LTC4283_CHAN_VPWR)
			return LTC4283_VPWR_MIN;
		if (channel >= LTC4283_CHAN_ADI_1 && channel <= LTC4283_CHAN_DRAIN)
			return LTC4283_ADC_2_MIN(channel - LTC4283_CHAN_ADI_1);
		return LTC4283_ADC_2_MIN_DIFF(channel - LTC4283_CHAN_ADIN12);
	case hwmon_in_max:
		if (channel == LTC4283_CHAN_VPWR)
			return LTC4283_VPWR_MAX_TH;
		if (channel >= LTC4283_CHAN_ADI_1 && channel <= LTC4283_CHAN_DRAIN)
			return LTC4283_ADC_2_MAX_TH(channel - LTC4283_CHAN_ADI_1);
		return LTC4283_ADC_2_MAX_TH_DIFF(channel - LTC4283_CHAN_ADIN12);
	default:
		if (channel == LTC4283_CHAN_VPWR)
			return LTC4283_VPWR_MIN_TH;
		if (channel >= LTC4283_CHAN_ADI_1 && channel <= LTC4283_CHAN_DRAIN)
			return LTC4283_ADC_2_MIN_TH(channel - LTC4283_CHAN_ADI_1);
		return LTC4283_ADC_2_MIN_TH_DIFF(channel - LTC4283_CHAN_ADIN12);
	}
}

static int ltc4283_read_in_vals(const struct ltc4283_hwmon *st,
				u32 attr, u32 channel, long *val)
{
	u32 reg = ltc4283_in_reg(attr, channel);
	int ret;

	if (channel < LTC4283_CHAN_ADIN12) {
		if (attr != hwmon_in_max && attr != hwmon_in_min)
			return ltc4283_read_voltage_word(st, reg,
							 LTC4283_ADC2_FS_mV,
							 val);

Annotation

Implementation Notes