drivers/hwmon/ina3221.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/ina3221.c
Extension
.c
Size
27284 bytes
Lines
1025
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 ina3221_input {
	const char *label;
	int shunt_resistor;
	bool disconnected;
	bool summation_disable;
};

/**
 * struct ina3221_data - device specific information
 * @pm_dev: Device pointer for pm runtime
 * @regmap: Register map of the device
 * @fields: Register fields of the device
 * @inputs: Array of channel input source specific structures
 * @reg_config: Register value of INA3221_CONFIG
 * @summation_shunt_resistor: equivalent shunt resistor value for summation
 * @summation_channel_control: Value written to SCC field in INA3221_MASK_ENABLE
 * @single_shot: running in single-shot operating mode
 */
struct ina3221_data {
	struct device *pm_dev;
	struct regmap *regmap;
	struct regmap_field *fields[F_MAX_FIELDS];
	struct ina3221_input inputs[INA3221_NUM_CHANNELS];
	u32 reg_config;
	int summation_shunt_resistor;
	u32 summation_channel_control;

	bool single_shot;
};

static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel)
{
	/* Summation channel checks shunt resistor values */
	if (channel > INA3221_CHANNEL3)
		return ina->summation_shunt_resistor != 0;

	return pm_runtime_active(ina->pm_dev) &&
	       (ina->reg_config & INA3221_CONFIG_CHx_EN(channel));
}

/*
 * Helper function to return the resistor value for current summation.
 *
 * There is a condition to calculate current summation -- all the shunt
 * resistor values should be the same, so as to simply fit the formula:
 *     current summation = shunt voltage summation / shunt resistor
 *
 * Returns the equivalent shunt resistor value on success or 0 on failure
 */
static inline int ina3221_summation_shunt_resistor(struct ina3221_data *ina)
{
	struct ina3221_input *input = ina->inputs;
	int i, shunt_resistor = 0;

	for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
		if (input[i].disconnected || !input[i].shunt_resistor ||
		    input[i].summation_disable)
			continue;
		if (!shunt_resistor) {
			/* Found the reference shunt resistor value */
			shunt_resistor = input[i].shunt_resistor;
		} else {
			/* No summation if resistor values are different */
			if (shunt_resistor != input[i].shunt_resistor)
				return 0;
		}
	}

	return shunt_resistor;
}

/* Lookup table for Bus and Shunt conversion times in usec */
static const u16 ina3221_conv_time[] = {
	140, 204, 332, 588, 1100, 2116, 4156, 8244,
};

/* Lookup table for number of samples using in averaging mode */
static const int ina3221_avg_samples[] = {
	1, 4, 16, 64, 128, 256, 512, 1024,
};

/* Converting update_interval in msec to conversion time in usec */
static inline u32 ina3221_interval_ms_to_conv_time(u16 config, int interval)
{
	u32 channels = hweight16(config & INA3221_CONFIG_CHs_EN_MASK);
	u32 samples_idx = INA3221_CONFIG_AVG(config);
	u32 samples = ina3221_avg_samples[samples_idx];

	/* Bisect the result to Bus and Shunt conversion times */
	return DIV_ROUND_CLOSEST(interval * 1000 / 2, channels * samples);

Annotation

Implementation Notes