linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Vincent Pelletier <plr.vincent@gmail.com>
To: Support Opensource <support.opensource@diasemi.com>,
	Liam Girdwood <lgirdwood@gmail.com>,
	Mark Brown <broonie@kernel.org>,
	linux-kernel@vger.kernel.org
Subject: [PATCH v4] regulator: da9063: Add support for full-current mode.
Date: Mon,  5 Jul 2021 13:19:44 +0000	[thread overview]
Message-ID: <58a4ef0f70b227a5da820ea51c7b3b60fa453b1e.1625490856.git.plr.vincent@gmail.com> (raw)

In addition to the ability of merging some power outputs, this chip has
an overdrive mode.
BCORE1, BCORE2 and BPRO have this ability, in which case the legal
current draw is increased from 2 amps to 2.5 amps (at the expense of
a quiescent current increase), and the configurable current limits
are doubled.
If a current higher than maximum half-current mode is requested, enable
overdrive, and scale the current limit down.
Symetrically, scale the current limit up when querying a overdrive-enabled
regulator.

Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
---
V3 -> V4:
- complete logic change: my original approach was backwards: the driver
  should take full control the overdrive bit, and not depend on the state
  it find the hardware in.
V2 -> V3:
- ACTUALLY skip DA9063_ID_BCORES_MERGED_OD when not full-current, and
  vice-versa.
- head put in brown paper bag
V1 -> V2:
- skip DA9063_ID_BCORES_MERGED_OD when not full-current, and vice-versa
- cc linux-kernel ML
- fix subject prefix


 drivers/regulator/da9063-regulator.c | 75 +++++++++++++++++++++++++++-
 1 file changed, 73 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index cf7d5341750e..4be7cfd06cd4 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -412,6 +412,77 @@ static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev,
 	return regmap_field_write(regl->suspend_sleep, val);
 }
 
+static unsigned int da9063_get_overdrive_mask(const struct regulator_desc *desc)
+{
+	switch (desc->id) {
+	case DA9063_ID_BCORES_MERGED:
+	case DA9063_ID_BCORE1:
+		return DA9063_BCORE1_OD;
+	case DA9063_ID_BCORE2:
+		return DA9063_BCORE2_OD;
+	case DA9063_ID_BPRO:
+		return DA9063_BPRO_OD;
+	default:
+		return 0;
+	}
+}
+
+static int da9063_buck_set_current_limit(struct regulator_dev *rdev,
+					 int min_uA, int max_uA)
+{
+	struct da9063_regulator *regl = rdev_get_drvdata(rdev);
+	unsigned int mask, n_currents;
+	int ret, overdrive;
+	bool overdrive_changed = false;
+
+	mask = da9063_get_overdrive_mask(rdev->desc);
+	if (mask) {
+		n_currents = rdev->desc->n_current_limits;
+		if (n_currents == 0)
+			return -EINVAL;
+		if (max_uA > rdev->desc->curr_table[n_currents - 1]) {
+			overdrive = mask;
+			min_uA /= 2; // XXX: rounding ?
+			max_uA /= 2;
+		} else {
+			overdrive = 0;
+		}
+		ret = regmap_update_bits_check(regl->hw->regmap,
+					       DA9063_REG_CONFIG_H, mask,
+					       overdrive, &overdrive_changed);
+		if (ret < 0)
+			return ret;
+	}
+	ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA);
+	if (ret < 0 && overdrive_changed)
+		/* attempt to restore original overdrive state, ignore failure-
+		 * on-failure
+		 */
+		regmap_update_bits(regl->hw->regmap, DA9063_REG_CONFIG_H,
+				   mask, ~overdrive);
+	return ret;
+}
+
+static int da9063_buck_get_current_limit(struct regulator_dev *rdev)
+{
+	struct da9063_regulator *regl = rdev_get_drvdata(rdev);
+	int val, ret, limit;
+	unsigned int mask;
+
+	limit = regulator_get_current_limit_regmap(rdev);
+	if (limit < 0)
+		return limit;
+	mask = da9063_get_overdrive_mask(rdev->desc);
+	if (mask) {
+		ret = regmap_read(regl->hw->regmap, DA9063_REG_CONFIG_H, &val);
+		if (ret < 0)
+			return ret;
+		if (val & mask)
+			limit *= 2;
+	}
+	return limit;
+}
+
 static const struct regulator_ops da9063_buck_ops = {
 	.enable			= regulator_enable_regmap,
 	.disable		= regulator_disable_regmap,
@@ -419,8 +490,8 @@ static const struct regulator_ops da9063_buck_ops = {
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
 	.list_voltage		= regulator_list_voltage_linear,
-	.set_current_limit	= regulator_set_current_limit_regmap,
-	.get_current_limit	= regulator_get_current_limit_regmap,
+	.set_current_limit	= da9063_buck_set_current_limit,
+	.get_current_limit	= da9063_buck_get_current_limit,
 	.set_mode		= da9063_buck_set_mode,
 	.get_mode		= da9063_buck_get_mode,
 	.get_status		= da9063_buck_get_status,
-- 
2.32.0


             reply	other threads:[~2021-07-05 13:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-05 13:19 Vincent Pelletier [this message]
2021-07-07  9:05 ` [PATCH v4] regulator: da9063: Add support for full-current mode Adam Thomson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=58a4ef0f70b227a5da820ea51c7b3b60fa453b1e.1625490856.git.plr.vincent@gmail.com \
    --to=plr.vincent@gmail.com \
    --cc=broonie@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=support.opensource@diasemi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).