All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adam Ward <adam.ward@diasemi.com>
To: Mark Brown <broonie@kernel.org>, Rob Herring <robh+dt@kernel.org>
Cc: Liam Girdwood <lgirdwood@gmail.com>,
	Vincent Whitchurch <vincent.whitchurch@axis.com>,
	<linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>
Subject: [PATCH 7/9] regulator: da9121: add current support
Date: Fri, 20 Nov 2020 12:14:57 +0000	[thread overview]
Message-ID: <a9b30f4aa8813bf262fd0eb8e007253582f61602.1605868780.git.Adam.Ward.opensource@diasemi.com> (raw)
In-Reply-To: <cover.1605868780.git.Adam.Ward.opensource@diasemi.com>

This commit adds support for getting/setting current for all supported
variants. Limits are adjusted per variant to match HW implementation.

Signed-off-by: Adam Ward <Adam.Ward.opensource@diasemi.com>
---
 drivers/regulator/da9121-regulator.c | 140 +++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c
index 13b0aad..5d11c22 100644
--- a/drivers/regulator/da9121-regulator.c
+++ b/drivers/regulator/da9121-regulator.c
@@ -92,6 +92,144 @@ struct da9121_variant_info {
 	{ 1, 2, &da9121_6A_2phase_current  },	//DA9121_TYPE_DA9217
 };
 
+static bool da9121_rdev_to_buck_reg_mask(struct regulator_dev *rdev, bool mode,
+					 unsigned int *reg, unsigned int *msk)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	int id = rdev_get_id(rdev);
+
+	switch (id) {
+	case DA9121_IDX_BUCK1:
+		if (mode) {
+			*reg = DA9121_REG_BUCK_BUCK1_4;
+			*msk = DA9121_MASK_BUCK_BUCKx_4_CHx_A_MODE;
+		} else {
+			*reg = DA9121_REG_BUCK_BUCK1_2;
+			*msk = DA9121_MASK_BUCK_BUCKx_2_CHx_ILIM;
+		}
+		break;
+	case DA9121_IDX_BUCK2:
+		if (mode) {
+			*reg = DA9xxx_REG_BUCK_BUCK2_4;
+			*msk = DA9121_MASK_BUCK_BUCKx_4_CHx_A_MODE;
+		} else {
+			*reg = DA9xxx_REG_BUCK_BUCK2_2;
+			*msk = DA9121_MASK_BUCK_BUCKx_2_CHx_ILIM;
+		}
+		break;
+	default:
+		dev_err(chip->dev, "Invalid regulator ID\n");
+		return false;
+	}
+	return true;
+}
+
+static int da9121_get_current_limit(struct regulator_dev *rdev)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	struct da9121_range *range =
+		variant_parameters[chip->variant_id].current_range;
+	unsigned int reg = 0;
+	unsigned int msk = 0;
+	unsigned int val = 0;
+	int ret = 0;
+
+	if (!da9121_rdev_to_buck_reg_mask(rdev, false, &reg, &msk))
+		return -EINVAL;
+
+	ret = regmap_read(chip->regmap, reg, &val);
+	if (ret < 0) {
+		dev_err(chip->dev, "Cannot read BUCK register: %d\n", ret);
+		goto error;
+	}
+
+	if (val < range->reg_min) {
+		ret = -EACCES;
+		goto error;
+	}
+
+	if (val > range->reg_max) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	return range->val_min + (range->val_stp * (val - range->reg_min));
+error:
+	return ret;
+}
+
+static int da9121_ceiling_selector(struct regulator_dev *rdev,
+		int min, int max,
+		unsigned int *selector)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	struct da9121_range *range =
+		variant_parameters[chip->variant_id].current_range;
+	unsigned int level;
+	unsigned int i = 0;
+	unsigned int sel = 0;
+	int ret = 0;
+
+	if (range->val_min > max || range->val_max < min) {
+		dev_err(chip->dev,
+			"Requested current out of regulator capability\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	level = range->val_max;
+	for (i = range->reg_max; i >= range->reg_min; i--) {
+		if (level <= max) {
+			sel = i;
+			break;
+		}
+		level -= range->val_stp;
+	}
+
+	if (level < min) {
+		dev_err(chip->dev,
+			"Best match falls below minimum requested current\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	*selector = sel;
+error:
+	return ret;
+}
+
+static int da9121_set_current_limit(struct regulator_dev *rdev,
+				int min_ua, int max_ua)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	struct da9121_range *range =
+		variant_parameters[chip->variant_id].current_range;
+	unsigned int sel = 0;
+	unsigned int reg = 0;
+	unsigned int msk = 0;
+	int ret = 0;
+
+	if (min_ua < range->val_min ||
+	    max_ua > range->val_max) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = da9121_ceiling_selector(rdev, min_ua, max_ua, &sel);
+	if (ret < 0)
+		goto error;
+
+	if (!da9121_rdev_to_buck_reg_mask(rdev, false, &reg, &msk))
+		return -EINVAL;
+
+	ret = regmap_update_bits(chip->regmap, reg, msk, (unsigned int)sel);
+	if (ret < 0)
+		dev_err(chip->dev, "Cannot update BUCK register %02x, err: %d\n", reg, ret);
+
+error:
+	return ret;
+}
+
 static const struct regulator_ops da9121_buck_ops = {
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -99,6 +237,8 @@ struct da9121_variant_info {
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.list_voltage = regulator_list_voltage_linear,
+	.get_current_limit = da9121_get_current_limit,
+	.set_current_limit = da9121_set_current_limit,
 };
 
 static struct of_regulator_match da9121_matches[] = {
-- 
1.9.1


  parent reply	other threads:[~2020-11-20 12:15 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-20 12:14 [PATCH 0/9] regulator: da9121: extend support to variants, add features Adam Ward
2020-11-20 12:14 ` [PATCH 1/9] regulator: Update DA9121 dt-bindings Adam Ward
2020-11-20 13:47   ` Vincent Whitchurch
2020-11-25  9:21     ` Vincent Whitchurch
2020-11-27 13:01       ` Adam Ward
2020-11-27 14:59         ` Mark Brown
2020-11-20 12:14 ` [PATCH 2/9] regulator: da9121: Add header file Adam Ward
2020-11-20 12:14 ` [PATCH 3/9] regulator: da9121: Add device variants Adam Ward
2020-11-20 12:14 ` [PATCH 4/9] regulator: da9121: Add device variant details and respective regmaps Adam Ward
2020-11-20 12:45   ` Mark Brown
2020-11-20 12:14 ` [PATCH 5/9] regulator: da9121: Add support for device variants via devicetree Adam Ward
2020-11-20 12:51   ` Mark Brown
2020-11-20 12:14 ` [PATCH 6/9] regulator: da9121: Update registration to support multiple buck variants Adam Ward
2020-11-20 13:06   ` Mark Brown
2020-11-20 12:14 ` Adam Ward [this message]
2020-11-20 13:17   ` [PATCH 7/9] regulator: da9121: add current support Mark Brown
2020-11-20 12:14 ` [PATCH 8/9] regulator: da9121: add mode support Adam Ward
2020-11-20 12:14 ` [PATCH 9/9] regulator: da9121: add interrupt support Adam Ward
2020-11-20 13:45   ` Mark Brown

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=a9b30f4aa8813bf262fd0eb8e007253582f61602.1605868780.git.Adam.Ward.opensource@diasemi.com \
    --to=adam.ward@diasemi.com \
    --cc=broonie@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=vincent.whitchurch@axis.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.