drivers/regulator/sgm3804-regulator.c

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

File Facts

System
Linux kernel
Corpus path
drivers/regulator/sgm3804-regulator.c
Extension
.c
Size
8286 bytes
Lines
315
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 sgm3804_data {
	struct regmap *regmap;
	/* Protects the regcache state update */
	struct mutex lock;
	struct gpio_desc *gpios[SGM3804_RAIL_COUNT];
};

static const struct linear_range sgm3804_voltages[] = {
	REGULATOR_LINEAR_RANGE(2400000, 0x20, 0x2f, 100000),
	REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x17, 100000),
};

/*
 * The cache is populated with those hardware default values
 * so the regmap_update_bits operation will use the cached
 * value to build a new register value and write it when GPIOs
 * are enabled.
 */
static const struct reg_default sgm3804_reg_defaults[] = {
	{ SGM3804_POS_RAIL_VOLTAGE_REG, RAIL_VOLTAGE_INVALID },
	{ SGM3804_NEG_RAIL_VOLTAGE_REG, RAIL_VOLTAGE_INVALID },
	{ SGM3804_RAIL_DISCHARGE_REG, RAIL_DISCHARGE_REG_DEFAULT },
};

/* Registers are only writable */
static bool sgm3804_writeable_reg(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case SGM3804_POS_RAIL_VOLTAGE_REG:
	case SGM3804_NEG_RAIL_VOLTAGE_REG:
	case SGM3804_RAIL_DISCHARGE_REG:
		return true;
	default:
		return false;
	}
}

/*
 * Since all registers are only writeable, regmap will only read from the cache data.
 */
static bool sgm3804_readable_reg(struct device *dev, unsigned int reg)
{
	return false;
}

static const struct regmap_config sgm3804_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
	.max_register = 0x03,
	.writeable_reg = sgm3804_writeable_reg,
	.readable_reg = sgm3804_readable_reg,
	.cache_type = REGCACHE_MAPLE,
	.reg_defaults = sgm3804_reg_defaults,
	.num_reg_defaults = ARRAY_SIZE(sgm3804_reg_defaults),
};

static int sgm3804_sync_regcache_state(struct sgm3804_data *ctx)
{
	guard(mutex)(&ctx->lock);

	/* If both GPIOs are down, IC is powered down and I2C writes will fail */
	if (!gpiod_get_value_cansleep(ctx->gpios[SGM3804_POS_RAIL]) &&
	    !gpiod_get_value_cansleep(ctx->gpios[SGM3804_NEG_RAIL])) {
		regcache_cache_only(ctx->regmap, true);
		regcache_mark_dirty(ctx->regmap);
	} else {
		int ret;

		/* At least a GPIO is up, we can write registers */
		regcache_cache_only(ctx->regmap, false);
		ret = regcache_sync(ctx->regmap);
		if (ret) {
			regcache_cache_only(ctx->regmap, true);
			return ret;
		}
	}

	return 0;
}

static int sgm3804_get_voltage_sel(struct regulator_dev *rdev)
{
	int ret;

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

	/* Force setting a voltage on probe */
	if (ret == RAIL_VOLTAGE_INVALID)

Annotation

Implementation Notes