ARM Sunxi Platform Development
 help / color / mirror / Atom feed
From: Andre Przywara <andre.przywara@arm.com>
To: Lee Jones <lee@kernel.org>, Chen-Yu Tsai <wens@kernel.org>,
	Liam Girdwood <lgirdwood@gmail.com>,
	Mark Brown <broonie@kernel.org>,
	Samuel Holland <samuel@sholland.org>,
	Jernej Skrabec <jernej.skrabec@gmail.com>
Cc: Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>, Yixun Lan <dlan@gentoo.org>,
	devicetree@vger.kernel.org, linux-sunxi@lists.linux.dev,
	linux-kernel@vger.kernel.org
Subject: [PATCH 3/3] regulator: axp20x: add support for the AXP318W
Date: Tue, 21 Oct 2025 12:20:12 +0100	[thread overview]
Message-ID: <20251021112013.2710903-4-andre.przywara@arm.com> (raw)
In-Reply-To: <20251021112013.2710903-1-andre.przywara@arm.com>

The X-Powers AXP318W is a typical PMIC from X-Powers, featuring nine
DC/DC converters and 28 LDOs, on the regulator side.

Describe the chip's voltage settings and switch registers, how the
voltages are encoded, and connect this to the MFD device via its
regulator ID.
We use just "318" for the internal identifiers, for easier typing and
less churn. If something else other than the "AXP318W" shows up, that's
an easy change, externally visible strings carry the additional letter
already.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/regulator/axp20x-regulator.c | 170 ++++++++++++++++++++++++++-
 include/linux/mfd/axp20x.h           |  43 +++++++
 2 files changed, 211 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index da891415efc0b..1576bf4178f8f 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -138,6 +138,15 @@
 #define AXP313A_DCDC_V_OUT_MASK		GENMASK(6, 0)
 #define AXP313A_LDO_V_OUT_MASK		GENMASK(4, 0)
 
+#define AXP318_DCDC1_V_OUT_MASK		GENMASK(4, 0)
+#define AXP318_DCDC2_V_OUT_MASK		GENMASK(6, 0)
+#define AXP318_LDO_V_OUT_MASK		GENMASK(4, 0)
+#define AXP318_ELDO_V_OUT_MASK		GENMASK(5, 0)
+#define AXP318_DCDC2_NUM_VOLTAGES	88
+#define AXP318_DCDC6_NUM_VOLTAGES	128
+#define AXP318_DCDC7_NUM_VOLTAGES	103
+#define AXP318_DCDC8_NUM_VOLTAGES	119
+
 #define AXP717_DCDC1_NUM_VOLTAGES	88
 #define AXP717_DCDC2_NUM_VOLTAGES	107
 #define AXP717_DCDC3_NUM_VOLTAGES	103
@@ -765,6 +774,155 @@ static const struct regulator_desc axp313a_regulators[] = {
 	AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800),
 };
 
+static const struct linear_range axp318_dcdc2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000,   0, 70, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000),
+};
+
+static const struct linear_range axp318_dcdc6_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000,    0,  70,  10000),
+	REGULATOR_LINEAR_RANGE(1220000,  71,  87,  20000),
+	REGULATOR_LINEAR_RANGE(1800000,  88, 118,  20000),
+	REGULATOR_LINEAR_RANGE(2440000, 119, 127,  40000),
+};
+
+static const struct linear_range axp318_dcdc7_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000,   0,  70, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000),
+};
+
+static const struct linear_range axp318_dcdc8_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000,    0,  70,  10000),
+	REGULATOR_LINEAR_RANGE(1220000,  71, 102,  20000),
+	REGULATOR_LINEAR_RANGE(1900000, 103, 118, 100000),
+};
+
+static const struct regulator_desc axp318_regulators[] = {
+	AXP_DESC(AXP318, DCDC1, "dcdc1", "vin19", 1000, 3400, 100,
+		 AXP318_DCDC1_CONTROL, AXP318_DCDC1_V_OUT_MASK,
+		 AXP318_DCDC_OUTPUT_CONTROL1, BIT(0)),
+	AXP_DESC_RANGES(AXP318, DCDC2, "dcdc2", "vin23",
+			axp318_dcdc2_ranges, AXP318_DCDC2_NUM_VOLTAGES,
+			AXP318_DCDC2_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL1, BIT(1)),
+	AXP_DESC_RANGES(AXP318, DCDC3, "dcdc3", "vin23",
+			axp318_dcdc2_ranges, AXP318_DCDC2_NUM_VOLTAGES,
+			AXP318_DCDC3_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL1, BIT(2)),
+	AXP_DESC_RANGES(AXP318, DCDC4, "dcdc4", "vin45",
+			axp318_dcdc2_ranges, AXP318_DCDC2_NUM_VOLTAGES,
+			AXP318_DCDC4_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL1, BIT(3)),
+	AXP_DESC_RANGES(AXP318, DCDC5, "dcdc5", "vin45",
+			axp318_dcdc2_ranges, AXP318_DCDC2_NUM_VOLTAGES,
+			AXP318_DCDC5_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL1, BIT(4)),
+	AXP_DESC_RANGES(AXP318, DCDC6, "dcdc6", "vin678",
+			axp318_dcdc6_ranges, AXP318_DCDC6_NUM_VOLTAGES,
+			AXP318_DCDC6_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL1, BIT(5)),
+	AXP_DESC_RANGES(AXP318, DCDC7, "dcdc7", "vin678",
+			axp318_dcdc7_ranges, AXP318_DCDC7_NUM_VOLTAGES,
+			AXP318_DCDC7_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL1, BIT(6)),
+	AXP_DESC_RANGES(AXP318, DCDC8, "dcdc8", "vin678",
+			axp318_dcdc8_ranges, AXP318_DCDC8_NUM_VOLTAGES,
+			AXP318_DCDC8_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL1, BIT(7)),
+	AXP_DESC_RANGES(AXP318, DCDC9, "dcdc9", "vin19",
+			axp318_dcdc8_ranges, AXP318_DCDC8_NUM_VOLTAGES,
+			AXP318_DCDC9_CONTROL, AXP318_DCDC2_V_OUT_MASK,
+			AXP318_DCDC_OUTPUT_CONTROL2, BIT(0)),
+	AXP_DESC_SW(AXP318, SWOUT1, "swout1", NULL,
+		    AXP318_DCDC_OUTPUT_CONTROL2, BIT(3)),
+	AXP_DESC_SW(AXP318, SWOUT2, "swout2", NULL,
+		    AXP318_DCDC_OUTPUT_CONTROL2, BIT(4)),
+	AXP_DESC(AXP318, ALDO1, "aldo1", "aldo156in", 500, 3400, 100,
+		 AXP318_ALDO1_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(0)),
+	AXP_DESC(AXP318, ALDO2, "aldo2", "aldo234in", 500, 3400, 100,
+		 AXP318_ALDO2_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(1)),
+	AXP_DESC(AXP318, ALDO3, "aldo3", "aldo234in", 500, 3400, 100,
+		 AXP318_ALDO3_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(2)),
+	AXP_DESC(AXP318, ALDO4, "aldo4", "aldo234in", 500, 3400, 100,
+		 AXP318_ALDO4_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(3)),
+	AXP_DESC(AXP318, ALDO5, "aldo5", "aldo156in", 500, 3400, 100,
+		 AXP318_ALDO5_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(4)),
+	AXP_DESC(AXP318, ALDO6, "aldo6", "aldo156in", 500, 3400, 100,
+		 AXP318_ALDO6_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(5)),
+	AXP_DESC(AXP318, BLDO1, "bldo1", "bldoin", 500, 3400, 100,
+		 AXP318_BLDO1_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(6)),
+	AXP_DESC(AXP318, BLDO2, "bldo2", "bldoin", 500, 3400, 100,
+		 AXP318_BLDO2_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL1, BIT(7)),
+	AXP_DESC(AXP318, BLDO3, "bldo3", "bldoin", 500, 3400, 100,
+		 AXP318_BLDO3_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(0)),
+	AXP_DESC(AXP318, BLDO4, "bldo4", "bldoin", 500, 3400, 100,
+		 AXP318_BLDO4_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(1)),
+	AXP_DESC(AXP318, BLDO5, "bldo5", "bldoin", 500, 3400, 100,
+		 AXP318_BLDO5_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(2)),
+	AXP_DESC(AXP318, CLDO1, "cldo1", "cldoin", 500, 3400, 100,
+		 AXP318_CLDO1_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(3)),
+	AXP_DESC(AXP318, CLDO2, "cldo2", "cldoin", 500, 3400, 100,
+		 AXP318_CLDO2_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(4)),
+	AXP_DESC(AXP318, CLDO3, "cldo3", "cldoin", 500, 3400, 100,
+		 AXP318_CLDO3_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(5)),
+	AXP_DESC(AXP318, CLDO4, "cldo4", "cldoin", 500, 3400, 100,
+		 AXP318_CLDO4_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(6)),
+	AXP_DESC(AXP318, CLDO5, "cldo5", "cldoin", 500, 3400, 100,
+		 AXP318_CLDO5_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL2, BIT(7)),
+	AXP_DESC(AXP318, DLDO1, "dldo1", "dldoin", 500, 3400, 100,
+		 AXP318_DLDO1_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(0)),
+	AXP_DESC(AXP318, DLDO2, "dldo2", "dldoin", 500, 3400, 100,
+		 AXP318_DLDO2_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(1)),
+	AXP_DESC(AXP318, DLDO3, "dldo3", "dldoin", 500, 3400, 100,
+		 AXP318_DLDO3_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(2)),
+	AXP_DESC(AXP318, DLDO4, "dldo4", "dldoin", 500, 3400, 100,
+		 AXP318_DLDO4_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(3)),
+	AXP_DESC(AXP318, DLDO5, "dldo5", "dldoin", 500, 3400, 100,
+		 AXP318_DLDO5_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(4)),
+	AXP_DESC(AXP318, DLDO6, "dldo6", "dldoin", 500, 3400, 100,
+		 AXP318_DLDO6_CONTROL, AXP318_LDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(5)),
+	AXP_DESC(AXP318, ELDO1, "eldo1", "eldoin", 500, 1500, 25,
+		 AXP318_ELDO1_CONTROL, AXP318_ELDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(6)),
+	AXP_DESC(AXP318, ELDO2, "eldo2", "eldoin", 500, 1500, 25,
+		 AXP318_ELDO2_CONTROL, AXP318_ELDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL3, BIT(7)),
+	AXP_DESC(AXP318, ELDO3, "eldo3", "eldoin", 500, 1500, 25,
+		 AXP318_ELDO3_CONTROL, AXP318_ELDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL4, BIT(0)),
+	AXP_DESC(AXP318, ELDO4, "eldo4", "eldoin", 500, 1500, 25,
+		 AXP318_ELDO4_CONTROL, AXP318_ELDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL4, BIT(1)),
+	AXP_DESC(AXP318, ELDO5, "eldo5", "eldoin", 500, 1500, 25,
+		 AXP318_ELDO5_CONTROL, AXP318_ELDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL4, BIT(2)),
+	AXP_DESC(AXP318, ELDO6, "eldo6", "eldoin", 500, 1500, 25,
+		 AXP318_ELDO6_CONTROL, AXP318_ELDO_V_OUT_MASK,
+		 AXP318_LDO_OUTPUT_CONTROL4, BIT(3)),
+};
+
 static const struct linear_range axp717_dcdc1_ranges[] = {
 	REGULATOR_LINEAR_RANGE(500000,   0, 70, 10000),
 	REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000),
@@ -1347,6 +1505,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 		step = 150;
 		break;
 	case AXP313A_ID:
+	case AXP318_ID:
 	case AXP323_ID:
 	case AXP717_ID:
 	case AXP15060_ID:
@@ -1585,6 +1744,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		regulators = axp313a_regulators;
 		nregulators = AXP313A_REG_ID_MAX;
 		break;
+	case AXP318_ID:
+		regulators = axp318_regulators;
+		nregulators = AXP318_REG_ID_MAX;
+		break;
 	case AXP717_ID:
 		regulators = axp717_regulators;
 		nregulators = AXP717_REG_ID_MAX;
@@ -1651,7 +1814,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
 		    (regulators == axp803_regulators && i == AXP803_DC1SW) ||
 		    (regulators == axp809_regulators && i == AXP809_DC1SW) ||
-		    (regulators == axp15060_regulators && i == AXP15060_SW)) {
+		    (regulators == axp15060_regulators && i == AXP15060_SW) ||
+		    (regulators == axp318_regulators && i == AXP318_SWOUT1) ||
+		    (regulators == axp318_regulators && i == AXP318_SWOUT2)) {
 			new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
 						GFP_KERNEL);
 			if (!new_desc)
@@ -1709,7 +1874,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		 */
 		if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
 		    (regulators == axp809_regulators && i == AXP809_DCDC1) ||
-		    (regulators == axp15060_regulators && i == AXP15060_DCDC1))
+		    (regulators == axp15060_regulators && i == AXP15060_DCDC1) ||
+		    (regulators == axp318_regulators && i == AXP318_DCDC1))
 			of_property_read_string(rdev->dev.of_node,
 						"regulator-name",
 						&dcdc1_name);
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index a871789f6cfa9..9957185458d63 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -559,6 +559,49 @@ enum {
 	AXP313A_REG_ID_MAX,
 };
 
+enum {
+	AXP318_DCDC1 = 0,
+	AXP318_DCDC2,
+	AXP318_DCDC3,
+	AXP318_DCDC4,
+	AXP318_DCDC5,
+	AXP318_DCDC6,
+	AXP318_DCDC7,
+	AXP318_DCDC8,
+	AXP318_DCDC9,
+	AXP318_ALDO1,
+	AXP318_ALDO2,
+	AXP318_ALDO3,
+	AXP318_ALDO4,
+	AXP318_ALDO5,
+	AXP318_ALDO6,
+	AXP318_BLDO1,
+	AXP318_BLDO2,
+	AXP318_BLDO3,
+	AXP318_BLDO4,
+	AXP318_BLDO5,
+	AXP318_CLDO1,
+	AXP318_CLDO2,
+	AXP318_CLDO3,
+	AXP318_CLDO4,
+	AXP318_CLDO5,
+	AXP318_DLDO1,
+	AXP318_DLDO2,
+	AXP318_DLDO3,
+	AXP318_DLDO4,
+	AXP318_DLDO5,
+	AXP318_DLDO6,
+	AXP318_ELDO1,
+	AXP318_ELDO2,
+	AXP318_ELDO3,
+	AXP318_ELDO4,
+	AXP318_ELDO5,
+	AXP318_ELDO6,
+	AXP318_SWOUT1,
+	AXP318_SWOUT2,
+	AXP318_REG_ID_MAX,
+};
+
 enum {
 	AXP717_DCDC1 = 0,
 	AXP717_DCDC2,
-- 
2.25.1


  parent reply	other threads:[~2025-10-21 11:20 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-21 11:20 [PATCH 0/3] regulator: Add X-Powers AXP318W PMIC support Andre Przywara
2025-10-21 11:20 ` [PATCH 1/3] dt-bindings: mfd: x-powers,axp152: Document AXP318W Andre Przywara
2025-10-22 17:38   ` Conor Dooley
2025-11-03 15:31   ` Chen-Yu Tsai
2025-10-21 11:20 ` [PATCH 2/3] mfd: axp20x: Add support for AXP318W PMIC Andre Przywara
2025-11-03 15:49   ` Chen-Yu Tsai
2025-10-21 11:20 ` Andre Przywara [this message]
2025-10-21 14:27   ` [PATCH 3/3] regulator: axp20x: add support for the AXP318W Mark Brown
2025-10-22  0:14   ` Yixun Lan
2025-10-22  0:47     ` Andre Przywara
2025-10-22  7:58       ` Yixun Lan
2025-10-31  1:22         ` Andre Przywara
2025-11-03 16:28     ` Chen-Yu Tsai
2025-11-03 16:54   ` Chen-Yu Tsai
2025-11-03 17:24     ` Horváth Csaba

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=20251021112013.2710903-4-andre.przywara@arm.com \
    --to=andre.przywara@arm.com \
    --cc=broonie@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dlan@gentoo.org \
    --cc=jernej.skrabec@gmail.com \
    --cc=krzk+dt@kernel.org \
    --cc=lee@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sunxi@lists.linux.dev \
    --cc=robh@kernel.org \
    --cc=samuel@sholland.org \
    --cc=wens@kernel.org \
    /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