drivers/regulator/rt4801-regulator.c

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

File Facts

System
Linux kernel
Corpus path
drivers/regulator/rt4801-regulator.c
Extension
.c
Size
6095 bytes
Lines
252
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 rt4801_priv {
	struct device *dev;
	struct gpio_desc *enable_gpios[DSV_OUT_MAX];
	unsigned int enable_flag;
	unsigned int volt_sel[DSV_OUT_MAX];
};

static int rt4801_of_parse_cb(struct device_node *np,
			      const struct regulator_desc *desc,
			      struct regulator_config *config)
{
	struct rt4801_priv *priv = config->driver_data;
	int id = desc->id;

	if (priv->enable_gpios[id]) {
		dev_warn(priv->dev, "duplicated enable-gpios property\n");
		return 0;
	}
	priv->enable_gpios[id] = devm_fwnode_gpiod_get_index(priv->dev,
							     of_fwnode_handle(np),
							     "enable", 0,
							     GPIOD_OUT_HIGH,
							     "rt4801");
	if (IS_ERR(priv->enable_gpios[id]))
		priv->enable_gpios[id] = NULL;

	return 0;
}

static int rt4801_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
{
	struct rt4801_priv *priv = rdev_get_drvdata(rdev);
	int id = rdev_get_id(rdev), ret;

	if (priv->enable_flag & BIT(id)) {
		ret = regulator_set_voltage_sel_regmap(rdev, selector);
		if (ret)
			return ret;
	}

	priv->volt_sel[id] = selector;
	return 0;
}

static int rt4801_get_voltage_sel(struct regulator_dev *rdev)
{
	struct rt4801_priv *priv = rdev_get_drvdata(rdev);
	int id = rdev_get_id(rdev);

	if (priv->enable_flag & BIT(id))
		return regulator_get_voltage_sel_regmap(rdev);

	return priv->volt_sel[id];
}

static int rt4801_enable(struct regulator_dev *rdev)
{
	struct rt4801_priv *priv = rdev_get_drvdata(rdev);
	int id = rdev_get_id(rdev), ret;

	if (!priv->enable_gpios[id]) {
		dev_warn(&rdev->dev, "no dedicated gpio can control\n");
		goto bypass_gpio;
	}

	gpiod_set_value(priv->enable_gpios[id], 1);

bypass_gpio:
	ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, priv->volt_sel[id]);
	if (ret)
		return ret;

	priv->enable_flag |= BIT(id);
	return 0;
}

static int rt4801_disable(struct regulator_dev *rdev)
{
	struct rt4801_priv *priv = rdev_get_drvdata(rdev);
	int id = rdev_get_id(rdev);

	if (!priv->enable_gpios[id]) {
		dev_warn(&rdev->dev, "no dedicated gpio can control\n");
		goto bypass_gpio;
	}

	gpiod_set_value(priv->enable_gpios[id], 0);

bypass_gpio:
	priv->enable_flag &= ~BIT(id);

Annotation

Implementation Notes