From nobody Mon Feb 9 08:29:29 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 35B622F5A12; Tue, 21 Oct 2025 11:20:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761045632; cv=none; b=ghuoL52/L3cO2v0prqltMsJ9abPahl8eBpRgPnaMu7XM4T7cc8tlcQ58pwGxBSCQVEVLo4G+MfPK4DXRUhlK7Hcl2QmW65+7kgDgleUI23zqdQmdhXjzRYkwJAVv9Qk2XBAXaP8DAkxKzMgN7SzHYp+QpBCMIQUKCsnAaUghqrg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761045632; c=relaxed/simple; bh=57DjMLvyluK+RPMb+DZBpBd69QssS/ngcLXxNsgXYbM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hLutHcqqDBn6d9R7t0Rv9REV3HcGmxWnVLza33reX/k5FV7khDIaBWfMS1kRDD/h8DqC4HP7uW1OI157OZrne140QMT2QarCSJnP5n96AWMmT8Z5xNypQiLKiyS6KrFOzhq0tFQJvnqjfw/mAIow1KpDl34AR8IUGBJNfaPtcG0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 958E7150C; Tue, 21 Oct 2025 04:20:21 -0700 (PDT) Received: from donnerap.arm.com (donnerap.manchester.arm.com [10.33.8.67]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B285A3F63F; Tue, 21 Oct 2025 04:20:27 -0700 (PDT) From: Andre Przywara To: Lee Jones , Chen-Yu Tsai , Liam Girdwood , Mark Brown , Samuel Holland , Jernej Skrabec Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Yixun Lan , 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 Message-Id: <20251021112013.2710903-4-andre.przywara@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20251021112013.2710903-1-andre.przywara@arm.com> References: <20251021112013.2710903-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Mark Brown --- 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/axp20= x-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) =20 +#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= [] =3D { AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800), }; =20 +static const struct linear_range axp318_dcdc2_ranges[] =3D { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), +}; + +static const struct linear_range axp318_dcdc6_ranges[] =3D { + 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[] =3D { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), +}; + +static const struct linear_range axp318_dcdc8_ranges[] =3D { + 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[] =3D { + 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[] =3D { 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_devic= e *pdev, u32 dcdcfreq) step =3D 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_de= vice *pdev) regulators =3D axp313a_regulators; nregulators =3D AXP313A_REG_ID_MAX; break; + case AXP318_ID: + regulators =3D axp318_regulators; + nregulators =3D AXP318_REG_ID_MAX; + break; case AXP717_ID: regulators =3D axp717_regulators; nregulators =3D AXP717_REG_ID_MAX; @@ -1651,7 +1814,9 @@ static int axp20x_regulator_probe(struct platform_dev= ice *pdev) if ((regulators =3D=3D axp22x_regulators && i =3D=3D AXP22X_DC1SW) || (regulators =3D=3D axp803_regulators && i =3D=3D AXP803_DC1SW) || (regulators =3D=3D axp809_regulators && i =3D=3D AXP809_DC1SW) || - (regulators =3D=3D axp15060_regulators && i =3D=3D AXP15060_SW)) { + (regulators =3D=3D axp15060_regulators && i =3D=3D AXP15060_SW) || + (regulators =3D=3D axp318_regulators && i =3D=3D AXP318_SWOUT1) || + (regulators =3D=3D axp318_regulators && i =3D=3D AXP318_SWOUT2)) { new_desc =3D devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); if (!new_desc) @@ -1709,7 +1874,8 @@ static int axp20x_regulator_probe(struct platform_dev= ice *pdev) */ if ((regulators =3D=3D axp22x_regulators && i =3D=3D AXP22X_DCDC1) || (regulators =3D=3D axp809_regulators && i =3D=3D AXP809_DCDC1) || - (regulators =3D=3D axp15060_regulators && i =3D=3D AXP15060_DCDC1)) + (regulators =3D=3D axp15060_regulators && i =3D=3D AXP15060_DCDC1) || + (regulators =3D=3D axp318_regulators && i =3D=3D 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, }; =20 +enum { + AXP318_DCDC1 =3D 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 =3D 0, AXP717_DCDC2, --=20 2.25.1