drivers/regulator/max5970-regulator.c

Source file repositories/reference/linux-study-clean/drivers/regulator/max5970-regulator.c

File Facts

System
Linux kernel
Corpus path
drivers/regulator/max5970-regulator.c
Extension
.c
Size
16257 bytes
Lines
643
Domain
Driver Families
Bucket
drivers/regulator
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 max5970_regulator {
	int num_switches, mon_rng, irng, shunt_micro_ohms, lim_uA;
	struct regmap *regmap;
};

enum max597x_regulator_id {
	MAX597X_sw0,
	MAX597X_sw1,
};

static int max5970_read_adc(struct regmap *regmap, int reg, long *val)
{
	u8 reg_data[2];
	int ret;

	ret = regmap_bulk_read(regmap, reg, &reg_data[0], 2);
	if (ret < 0)
		return ret;

	*val = (reg_data[0] << 2) | (reg_data[1] & 3);

	return 0;
}

static int max5970_read(struct device *dev, enum hwmon_sensor_types type,
			u32 attr, int channel, long *val)
{
	struct regulator_dev **rdevs = dev_get_drvdata(dev);
	struct max5970_regulator *ddata = rdev_get_drvdata(rdevs[channel]);
	struct regmap *regmap = ddata->regmap;
	int ret;

	switch (type) {
	case hwmon_curr:
		switch (attr) {
		case hwmon_curr_input:
			ret = max5970_read_adc(regmap, MAX5970_REG_CURRENT_H(channel), val);
			if (ret < 0)
				return ret;
			/*
			 * Calculate current from ADC value, IRNG range & shunt resistor value.
			 * ddata->irng holds the voltage corresponding to the maximum value the
			 * 10-bit ADC can measure.
			 * To obtain the output, multiply the ADC value by the IRNG range (in
			 * millivolts) and then divide it by the maximum value of the 10-bit ADC.
			 */
			*val = (*val * ddata->irng) >> 10;
			/* Convert the voltage measurement across shunt resistor to current */
			*val = (*val * 1000) / ddata->shunt_micro_ohms;
			return 0;
		default:
			return -EOPNOTSUPP;
		}

	case hwmon_in:
		switch (attr) {
		case hwmon_in_input:
			ret = max5970_read_adc(regmap, MAX5970_REG_VOLTAGE_H(channel), val);
			if (ret < 0)
				return ret;
			/*
			 * Calculate voltage from ADC value and MON range.
			 * ddata->mon_rng holds the voltage corresponding to the maximum value the
			 * 10-bit ADC can measure.
			 * To obtain the output, multiply the ADC value by the MON range (in
			 * microvolts) and then divide it by the maximum value of the 10-bit ADC.
			 */
			*val = mul_u64_u32_shr(*val, ddata->mon_rng, 10);
			/* uV to mV */
			*val = *val / 1000;
			return 0;
		default:
			return -EOPNOTSUPP;
		}
	default:
		return -EOPNOTSUPP;
	}
}

static umode_t max5970_is_visible(const void *data,
				  enum hwmon_sensor_types type,
				  u32 attr, int channel)
{
	struct regulator_dev **rdevs = (struct regulator_dev **)data;
	struct max5970_regulator *ddata;

	if (channel >= MAX5970_NUM_SWITCHES || !rdevs[channel])
		return 0;

	ddata = rdev_get_drvdata(rdevs[channel]);

Annotation

Implementation Notes