drivers/regulator/axp20x-regulator.c

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

File Facts

System
Linux kernel
Corpus path
drivers/regulator/axp20x-regulator.c
Extension
.c
Size
64812 bytes
Lines
1760
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

if (id == AXP20X_DCDC2) {
			slew_rates = axp209_dcdc2_ldo3_slew_rates;
			rate_count = ARRAY_SIZE(axp209_dcdc2_ldo3_slew_rates);
			reg = AXP20X_DCDC2_LDO3_V_RAMP;
			mask = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE_MASK |
			       AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN_MASK;
			enable = (ramp > 0) ?
				 AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN : 0;
			break;
		}

		if (id == AXP20X_LDO3) {
			slew_rates = axp209_dcdc2_ldo3_slew_rates;
			rate_count = ARRAY_SIZE(axp209_dcdc2_ldo3_slew_rates);
			reg = AXP20X_DCDC2_LDO3_V_RAMP;
			mask = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE_MASK |
			       AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN_MASK;
			enable = (ramp > 0) ?
				 AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN : 0;
			break;
		}

		if (rate_count > 0)
			break;

		fallthrough;
	default:
		/* Not supported for this regulator */
		return -ENOTSUPP;
	}

	if (ramp == 0) {
		cfg = enable;
	} else {
		int i;

		for (i = 0; i < rate_count; i++) {
			if (ramp > slew_rates[i])
				break;

			if (id == AXP20X_DCDC2)
				cfg = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE(i);
			else
				cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
		}

		if (cfg == 0xff) {
			dev_err(axp20x->dev, "unsupported ramp value %d", ramp);
			return -EINVAL;
		}

		cfg |= enable;
	}

	return regmap_update_bits(axp20x->regmap, reg, mask, cfg);
}

static int axp20x_regulator_enable_regmap(struct regulator_dev *rdev)
{
	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
	int id = rdev_get_id(rdev);

	switch (axp20x->variant) {
	case AXP209_ID:
		if ((id == AXP20X_LDO3) &&
		    rdev->constraints && rdev->constraints->soft_start) {
			int v_out;
			int ret;

			/*
			 * On some boards, the LDO3 can be overloaded when
			 * turning on, causing the entire PMIC to shutdown
			 * without warning. Turning it on at the minimal voltage
			 * and then setting the voltage to the requested value
			 * works reliably.
			 */
			if (regulator_is_enabled_regmap(rdev))
				break;

			v_out = regulator_get_voltage_sel_regmap(rdev);
			if (v_out < 0)
				return v_out;

			if (v_out == 0)
				break;

			ret = regulator_set_voltage_sel_regmap(rdev, 0x00);
			/*
			 * A small pause is needed between
			 * setting the voltage and enabling the LDO to give the

Annotation

Implementation Notes