drivers/regulator/vctrl-regulator.c

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

File Facts

System
Linux kernel
Corpus path
drivers/regulator/vctrl-regulator.c
Extension
.c
Size
13527 bytes
Lines
556
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 vctrl_voltage_range {
	int min_uV;
	int max_uV;
};

struct vctrl_voltage_ranges {
	struct vctrl_voltage_range ctrl;
	struct vctrl_voltage_range out;
};

struct vctrl_voltage_table {
	int ctrl;
	int out;
	int ovp_min_sel;
};

struct vctrl_data {
	struct regulator_dev *rdev;
	struct regulator_desc desc;
	bool enabled;
	unsigned int min_slew_down_rate;
	unsigned int ovp_threshold;
	struct vctrl_voltage_ranges vrange;
	struct vctrl_voltage_table *vtable;
	unsigned int sel;
};

static int vctrl_calc_ctrl_voltage(struct vctrl_data *vctrl, int out_uV)
{
	struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl;
	struct vctrl_voltage_range *out = &vctrl->vrange.out;

	return ctrl->min_uV +
		DIV_ROUND_CLOSEST_ULL((s64)(out_uV - out->min_uV) *
				      (ctrl->max_uV - ctrl->min_uV),
				      out->max_uV - out->min_uV);
}

static int vctrl_calc_output_voltage(struct vctrl_data *vctrl, int ctrl_uV)
{
	struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl;
	struct vctrl_voltage_range *out = &vctrl->vrange.out;

	if (ctrl_uV < 0) {
		pr_err("vctrl: failed to get control voltage\n");
		return ctrl_uV;
	}

	if (ctrl_uV < ctrl->min_uV)
		return out->min_uV;

	if (ctrl_uV > ctrl->max_uV)
		return out->max_uV;

	return out->min_uV +
		DIV_ROUND_CLOSEST_ULL((s64)(ctrl_uV - ctrl->min_uV) *
				      (out->max_uV - out->min_uV),
				      ctrl->max_uV - ctrl->min_uV);
}

static int vctrl_get_voltage(struct regulator_dev *rdev)
{
	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
	int ctrl_uV;

	if (!rdev->supply)
		return -EPROBE_DEFER;

	ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev);

	return vctrl_calc_output_voltage(vctrl, ctrl_uV);
}

static int vctrl_set_voltage(struct regulator_dev *rdev,
			     int req_min_uV, int req_max_uV,
			     unsigned int *selector)
{
	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
	int orig_ctrl_uV;
	int uV;
	int ret;

	if (!rdev->supply)
		return -EPROBE_DEFER;

	orig_ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
	uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV);

	if (req_min_uV >= uV || !vctrl->ovp_threshold)
		/* voltage rising or no OVP */

Annotation

Implementation Notes