Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf3a5f93 authored by Abhijeet Dharmapurikar's avatar Abhijeet Dharmapurikar
Browse files

msm: krait-regulator: add support for reduced coeff1 load



The krait cpu can be made to run in a state where the coeff1 component
of the load is reduced.

Create a separate regulator per cpu to indicate if the reduced load
state is active. Recompute the phase count when this state changes.

Change-Id: I1fc52698aebef6255fa0276f106d1e125da3f167
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent faefe1ea
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -69,6 +69,20 @@ Optional properties:
Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.

[Third Level Nodes]
This Third level node represents a regulator which when enabled reduces
coeff1 component of the load by a defined percentage amount. This Third Level
Node is optional.
Required properties:
- regulator-name:		A string used as a descriptive name for the regulator
Optional properties:
- qcom,coeff1-reduction:	percentage to reduce the coeff1 component
				of the load by. If this is not specified
				a default of 75 percent is assumed.

Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.

Example:
	krait_pdn: krait-pdn@f9011000 {
		reg = <0xf9011000 0x1000>,
@@ -99,5 +113,9 @@ Example:
			qcom,ldo-threshold-voltage = <850000>;
			qcom,ldo-delta-voltage = <50000>;
			qcom,cpu-num = <0>;
			krait0_adj_reg: regulator@0 {
				regulator-name = "krait-adjustment0";
				qcom,coeff1-reduction = <75>;
			};
		};
	};
+126 −4
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -213,7 +213,9 @@ enum krait_supply_mode {
struct krait_power_vreg {
	struct list_head		link;
	struct regulator_desc		desc;
	struct regulator_desc		adj_desc;
	struct regulator_dev		*rdev;
	struct regulator_dev		*adj_rdev;
	const char			*name;
	struct pmic_gang_vreg		*pvreg;
	int				uV;
@@ -233,6 +235,8 @@ struct krait_power_vreg {
	bool				reg_en;
	int				online_at_probe;
	bool				force_bhs;
	bool				adj;
	int				coeff1_reduction;
};

DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
@@ -362,20 +366,24 @@ static int get_coeff2(int krait_uV, int phase_scaling_factor)
	return  coeff2;
}

static int get_coeff1(int actual_uV, int requested_uV, int load)
static int get_coeff1(int actual_uV, int requested_uV, int load, int reduction)
{
	int ratio = actual_uV * 1000 / requested_uV;
	int coeff1 = 330 * load + (load * 673 * ratio / 1000);

	coeff1 = reduction * coeff1 / 100;

	return coeff1;
}

#define NON_ACTIVE_REDUCTION_PERCENTAGE	100
static int get_coeff_total(struct krait_power_vreg *from)
{
	int coeff_total = 0;
	struct krait_power_vreg *kvreg;
	struct pmic_gang_vreg *pvreg = from->pvreg;
	int phase_scaling_factor = PHASE_SCALING_REF;
	int coeff1_reduction;

	if (use_efuse_phase_scaling_factor)
		phase_scaling_factor = pvreg->efuse_phase_scaling_factor;
@@ -383,21 +391,29 @@ static int get_coeff_total(struct krait_power_vreg *from)
	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
		if (!kvreg->reg_en)
			continue;
		if (kvreg->adj)
			coeff1_reduction = kvreg->coeff1_reduction;
		else
			coeff1_reduction = NON_ACTIVE_REDUCTION_PERCENTAGE;

		if (kvreg->mode == LDO_MODE) {
			kvreg->coeff1 =
				get_coeff1(kvreg->uV - kvreg->ldo_delta_uV,
							kvreg->uV, kvreg->load);
							kvreg->uV, kvreg->load,
							coeff1_reduction);
			kvreg->coeff2 =
				get_coeff2(kvreg->uV - kvreg->ldo_delta_uV,
							phase_scaling_factor);
		} else {
			kvreg->coeff1 =
				get_coeff1(pvreg->pmic_vmax_uV,
							kvreg->uV, kvreg->load);
							kvreg->uV, kvreg->load,
							coeff1_reduction);
			kvreg->coeff2 = get_coeff2(pvreg->pmic_vmax_uV,
							phase_scaling_factor);
		}
		pr_debug("%s coeff1=%d coeff2=%d\n", kvreg->name,
						kvreg->coeff1, kvreg->coeff2);
		coeff_total += kvreg->coeff1 + kvreg->coeff2;
	}

@@ -1206,6 +1222,102 @@ static void glb_init(void __iomem *apcs_gcc_base)
		writel_relaxed(0x0008736E, apcs_gcc_base + PWR_GATE_CONFIG);
}

static int krait_adj_enable(struct regulator_dev *rdev)
{
	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
	struct pmic_gang_vreg *pvreg = kvreg->pvreg;

	mutex_lock(&pvreg->krait_power_vregs_lock);
	kvreg->adj = true;
	_get_optimum_mode(rdev, 0, 0, kvreg->load);
	mutex_unlock(&pvreg->krait_power_vregs_lock);
	return 0;
}

static int krait_adj_disable(struct regulator_dev *rdev)
{
	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
	struct pmic_gang_vreg *pvreg = kvreg->pvreg;

	mutex_lock(&pvreg->krait_power_vregs_lock);
	kvreg->adj = false;
	_get_optimum_mode(rdev, 0, 0, kvreg->load);
	mutex_unlock(&pvreg->krait_power_vregs_lock);
	return 0;
}

static int krait_adj_is_enabled(struct regulator_dev *rdev)
{
	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);

	return kvreg->adj;
}

static struct regulator_ops krait_adj_ops = {
	.enable			= krait_adj_enable,
	.disable		= krait_adj_disable,
	.is_enabled		= krait_adj_is_enabled,
};

#define DEFAULT_REDUCTION_PERCENTAGE	75
static int krait_adj_init(struct krait_power_vreg *kvreg,
						struct platform_device *pdev,
						struct device_node *adj_node)
{
	struct regulator_init_data *init_data;
	struct regulator_config reg_config = {};
	int rc;
	int coeff1_reduction;

	if (kvreg->adj_rdev) {
		dev_err(&pdev->dev, "Only one coeff1 adjustment regulator node allowed.\n");
		return -EINVAL;
	}

	init_data = of_get_regulator_init_data(&pdev->dev, adj_node);
	if (!init_data) {
		dev_err(&pdev->dev, "init data required.\n");
		return -EINVAL;
	}

	if (!init_data->constraints.name) {
		dev_err(&pdev->dev,
			"regulator name must be specified in constraints.\n");
		return -EINVAL;
	}

	init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS;
	init_data->constraints.input_uV = init_data->constraints.max_uV;
	rc = of_property_read_u32(pdev->dev.of_node,
				"qcom,coeff1-reduction",
				&coeff1_reduction);
	if (rc) {
		dev_err(&pdev->dev,
			"qcom,coeff1-reduction missing in %s assuming %d\n",
			adj_node->name,
			DEFAULT_REDUCTION_PERCENTAGE);
		coeff1_reduction = DEFAULT_REDUCTION_PERCENTAGE;
	}

	kvreg->coeff1_reduction = coeff1_reduction;
	kvreg->adj_desc.name = init_data->constraints.name;
	kvreg->adj_desc.ops = &krait_adj_ops;
	kvreg->adj_desc.type = REGULATOR_VOLTAGE;
	kvreg->adj_desc.owner = THIS_MODULE;

	reg_config.dev = &pdev->dev;
	reg_config.init_data = init_data;
	reg_config.driver_data = kvreg;
	reg_config.of_node = adj_node;
	kvreg->adj_rdev = regulator_register(&kvreg->adj_desc, &reg_config);
	if (IS_ERR(kvreg->adj_rdev)) {
		rc = PTR_ERR(kvreg->rdev);
		pr_err("regulator_register failed, rc=%d.\n", rc);
		return rc;
	}
	return 0;
}

static int krait_power_probe(struct platform_device *pdev)
{
	struct regulator_config reg_config = {};
@@ -1217,6 +1329,7 @@ static int krait_power_probe(struct platform_device *pdev)
	int ldo_delta_uV;
	int cpu_num;
	bool ldo_disable = false;
	struct device_node *child;

	if (pdev->dev.of_node) {
		/* Get init_data from device tree. */
@@ -1368,6 +1481,15 @@ static int krait_power_probe(struct platform_device *pdev)
	list_add_tail(&kvreg->link, &the_gang->krait_power_vregs);
	mutex_unlock(&the_gang->krait_power_vregs_lock);

	for_each_child_of_node(pdev->dev.of_node, child) {
		rc = krait_adj_init(kvreg, pdev, child);
		if (rc) {
			dev_err(&pdev->dev, "Couldn't add child nodes, rc=%d\n",
					rc);
			goto out;
		}
	}

	online_at_probe(kvreg);
	kvreg_ldo_voltage_init(kvreg);