mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Stefan Kerkmann <s.kerkmann@pengutronix.de>
To: Sascha Hauer <s.hauer@pengutronix.de>,
	 "open list:BAREBOX" <barebox@lists.infradead.org>
Cc: Stefan Kerkmann <s.kerkmann@pengutronix.de>
Subject: [PATCH] regulator: pca9450: add pmic driver
Date: Mon, 24 Aug 2026 17:07:48 +0200	[thread overview]
Message-ID: <20260824-feature-pca9450-pmic-v1-1-8db9945555ce@pengutronix.de> (raw)

Extend the existing mfd driver for the pca9450 pmic to provide proper
regulator capabilties. The driver is based on the linux kernel driver
and was modified for barebox.

Signed-off-by: Stefan Kerkmann <s.kerkmann@pengutronix.de>
---
 drivers/mfd/pca9450.c                 |  48 +-
 drivers/regulator/Kconfig             |   7 +
 drivers/regulator/Makefile            |   1 +
 drivers/regulator/pca9450-regulator.c | 871 ++++++++++++++++++++++++++++++++++
 include/mfd/pca9450.h                 | 230 +++++++++
 5 files changed, 1147 insertions(+), 10 deletions(-)

diff --git a/drivers/mfd/pca9450.c b/drivers/mfd/pca9450.c
index 5d5d3d8e01..523071bf12 100644
--- a/drivers/mfd/pca9450.c
+++ b/drivers/mfd/pca9450.c
@@ -8,6 +8,7 @@
 #include <errno.h>
 #include <i2c/i2c.h>
 #include <init.h>
+#include <linux/mfd/core.h>
 #include <mfd/pca9450.h>
 #include <of.h>
 #include <regmap.h>
@@ -24,6 +25,10 @@ static const struct regmap_config pca9450_regmap_i2c_config = {
 	.max_register = 0x2E,
 };
 
+static const struct mfd_cell pca9450_cells[] = {
+	{ .name = "pca9450-regulator", },
+};
+
 static int pca9450_get_reset_source(struct device *dev, struct regmap *map)
 {
 	enum reset_src_type type;
@@ -82,22 +87,34 @@ int pca9450_register_init_callback(void(*callback)(struct regmap *map))
 
 static int __init pca9450_probe(struct device *dev)
 {
+	struct pca9450 *pca9450;
 	struct regmap *regmap;
 	int reg;
 	int ret;
 
+	pca9450 = devm_kzalloc(dev, sizeof(*pca9450), GFP_KERNEL);
+	if (!pca9450)
+		return -ENOMEM;
+
+	pca9450->dev = dev;
+	pca9450->type = (enum pca9450_chip_type)(uintptr_t)device_get_match_data(dev);
+
 	regmap = regmap_init_i2c(to_i2c_client(dev), &pca9450_regmap_i2c_config);
-	if (IS_ERR(regmap))
-		return PTR_ERR(regmap);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		goto free;
+	}
+
+	pca9450->regmap = regmap;
 
 	ret = regmap_register_cdev(regmap, NULL);
 	if (ret)
-		return ret;
+		goto free;
 
 	ret = regmap_read(regmap, PCA9450_REG_DEV_ID, &reg);
 	if (ret) {
 		dev_err(dev, "Unable to read PMIC Chip ID\n");
-		return ret;
+		goto free;
 	}
 
 	/* Chip ID defined in bits [7:4] */
@@ -117,16 +134,27 @@ static int __init pca9450_probe(struct device *dev)
 		pca9450_init_callback(regmap);
 	pca9450_map = regmap;
 
-	pca9450_get_reset_source(dev,regmap);
+	dev->priv = pca9450;
 
-	return of_platform_populate(dev->of_node, NULL, dev);
+	pca9450_get_reset_source(dev, regmap);
+
+	ret = mfd_add_devices(dev, pca9450_cells, ARRAY_SIZE(pca9450_cells));
+	if (ret)
+		goto free;
+
+	return 0;
+
+free:
+	free(pca9450);
+	return ret;
 }
 
 static __maybe_unused struct of_device_id pca9450_dt_ids[] = {
-	{ .compatible = "nxp,pca9450a" },
-	{ .compatible = "nxp,pca9450b" },
-	{ .compatible = "nxp,pca9450c" },
-	{ .compatible = "nxp,pca9451a" },
+	{ .compatible = "nxp,pca9450a", .data = (void *)PCA9450_TYPE_PCA9450A, },
+	{ .compatible = "nxp,pca9450b", .data = (void *)PCA9450_TYPE_PCA9450BC, },
+	{ .compatible = "nxp,pca9450c", .data = (void *)PCA9450_TYPE_PCA9450BC, },
+	{ .compatible = "nxp,pca9451a", .data = (void *)PCA9450_TYPE_PCA9451A, },
+	{ .compatible = "nxp,pca9452", .data = (void *)PCA9450_TYPE_PCA9452, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, pca9450_dt_ids);
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 3374a511f8..9b1a3fec98 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -90,4 +90,11 @@ config REGULATOR_RK808
 	  through regulator interface. The device supports multiple DCDC/LDO
 	  outputs which can be controlled by i2c communication.
 
+config REGULATOR_PCA9450
+	tristate "NXP PCA9450A/PCA9450B/PCA9450C regulator driver"
+	depends on MFD_PCA9450
+	help
+	  Say y here to support the NXP PCA9450A/PCA9450B/PCA9450C PMIC
+	  regulator driver.
+
 endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index a6f5b5b734..3569c1778c 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
 obj-$(CONFIG_REGULATOR_ARM_SCMI) += scmi-regulator.o
 obj-$(CONFIG_REGULATOR_RK808)   += rk808-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65219) += tps65219-regulator.o
+obj-$(CONFIG_REGULATOR_PCA9450)	+= pca9450-regulator.o
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
new file mode 100644
index 0000000000..9f2d9f6f88
--- /dev/null
+++ b/drivers/regulator/pca9450-regulator.c
@@ -0,0 +1,871 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-Comment: Origin-URL: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/regulator/pca9450-regulator.c?id=fbef4191b4961c125585c715407e693f7d0024a9
+
+/*
+ * Copyright 2020 NXP.
+ * NXP PCA9450 pmic driver
+ */
+
+#include <i2c/i2c.h>
+#include <mfd/pca9450.h>
+#include <regulator.h>
+
+static const struct regulator_ops pca9450_dvs_buck_regulator_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_ops pca9450_buck_regulator_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_ops pca9450_ldo_regulator_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static unsigned int pca9450_ldo5_get_reg_voltage_sel(struct regulator_dev *rdev)
+{
+	struct pca9450 *pca9450 = dev_get_drvdata(rdev->dev);
+
+	if (pca9450->sd_vsel_fixed_low)
+		return PCA9450_LDO5CTRL_L;
+
+	if (pca9450->sd_vsel_gpio && !gpiod_get_value(pca9450->sd_vsel_gpio))
+		return PCA9450_LDO5CTRL_L;
+
+	return rdev->desc->vsel_reg;
+}
+
+static int pca9450_ldo5_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(rdev->regmap, pca9450_ldo5_get_reg_voltage_sel(rdev), &val);
+	if (ret != 0)
+		return ret;
+
+	val &= rdev->desc->vsel_mask;
+	val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+	return val;
+}
+
+static int pca9450_ldo5_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned int sel)
+{
+	int ret;
+
+	sel <<= ffs(rdev->desc->vsel_mask) - 1;
+
+	ret = regmap_update_bits(rdev->regmap, pca9450_ldo5_get_reg_voltage_sel(rdev),
+				  rdev->desc->vsel_mask, sel);
+	if (ret)
+		return ret;
+
+	if (rdev->desc->apply_bit)
+		ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
+					 rdev->desc->apply_bit,
+					 rdev->desc->apply_bit);
+	return ret;
+}
+
+static const struct regulator_ops pca9450_ldo5_regulator_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.set_voltage_sel = pca9450_ldo5_set_voltage_sel_regmap,
+	.get_voltage_sel = pca9450_ldo5_get_voltage_sel_regmap,
+};
+
+/*
+ * BUCK1/2/3
+ * 0.60 to 2.1875V (12.5mV step)
+ */
+static const struct regulator_linear_range pca9450_dvs_buck_volts[] = {
+	REGULATOR_LINEAR_RANGE(600000,  0x00, 0x7F, 12500),
+};
+
+/*
+ * BUCK1/3
+ * 0.65 to 2.2375V (12.5mV step)
+ */
+static const struct regulator_linear_range pca9451a_dvs_buck_volts[] = {
+	REGULATOR_LINEAR_RANGE(650000, 0x00, 0x7F, 12500),
+};
+
+/*
+ * BUCK4/5/6
+ * 0.6V to 3.4V (25mV step)
+ */
+static const struct regulator_linear_range pca9450_buck_volts[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0x00, 0x70, 25000),
+	REGULATOR_LINEAR_RANGE(3400000, 0x71, 0x7F, 0),
+};
+
+/*
+ * LDO1
+ * 1.6 to 3.3V ()
+ */
+static const struct regulator_linear_range pca9450_ldo1_volts[] = {
+	REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000),
+	REGULATOR_LINEAR_RANGE(3000000, 0x04, 0x07, 100000),
+};
+
+/*
+ * LDO2
+ * 0.8 to 1.15V (50mV step)
+ */
+static const struct regulator_linear_range pca9450_ldo2_volts[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0x00, 0x07, 50000),
+};
+
+/*
+ * LDO3/4
+ * 0.8 to 3.3V (100mV step)
+ */
+static const struct regulator_linear_range pca9450_ldo34_volts[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0x00, 0x19, 100000),
+	REGULATOR_LINEAR_RANGE(3300000, 0x1A, 0x1F, 0),
+};
+
+/*
+ * LDO5
+ * 1.8 to 3.3V (100mV step)
+ */
+static const struct regulator_linear_range pca9450_ldo5_volts[] = {
+	REGULATOR_LINEAR_RANGE(1800000,  0x00, 0x0F, 100000),
+};
+
+static struct regulator_desc pca9450a_regulators[] = {
+	{
+		.name = "buck1",
+		.supply_name = "inb13",
+		.of_match = of_match_ptr("BUCK1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK1,
+		.ops = &pca9450_dvs_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK1_VOLTAGE_NUM,
+		.linear_ranges = pca9450_dvs_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+		.vsel_reg = PCA9450_BUCK1OUT_DVS0,
+		.vsel_mask = BUCK1OUT_DVS0_MASK,
+		.enable_reg = PCA9450_BUCK1CTRL,
+		.enable_mask = BUCK1_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck2",
+		.supply_name = "inb26",
+		.of_match = of_match_ptr("BUCK2"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK2,
+		.ops = &pca9450_dvs_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK2_VOLTAGE_NUM,
+		.linear_ranges = pca9450_dvs_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+		.vsel_reg = PCA9450_BUCK2OUT_DVS0,
+		.vsel_mask = BUCK2OUT_DVS0_MASK,
+		.enable_reg = PCA9450_BUCK2CTRL,
+		.enable_mask = BUCK2_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ_STBYREQ,
+	},
+	{
+		.name = "buck3",
+		.supply_name = "inb13",
+		.of_match = of_match_ptr("BUCK3"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK3,
+		.ops = &pca9450_dvs_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK3_VOLTAGE_NUM,
+		.linear_ranges = pca9450_dvs_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+		.vsel_reg = PCA9450_BUCK3OUT_DVS0,
+		.vsel_mask = BUCK3OUT_DVS0_MASK,
+		.enable_reg = PCA9450_BUCK3CTRL,
+		.enable_mask = BUCK3_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck4",
+		.supply_name = "inb45",
+		.of_match = of_match_ptr("BUCK4"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK4,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK4_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK4OUT,
+		.vsel_mask = BUCK4OUT_MASK,
+		.enable_reg = PCA9450_BUCK4CTRL,
+		.enable_mask = BUCK4_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck5",
+		.supply_name = "inb45",
+		.of_match = of_match_ptr("BUCK5"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK5,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK5_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK5OUT,
+		.vsel_mask = BUCK5OUT_MASK,
+		.enable_reg = PCA9450_BUCK5CTRL,
+		.enable_mask = BUCK5_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck6",
+		.supply_name = "inb26",
+		.of_match = of_match_ptr("BUCK6"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK6,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK6_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK6OUT,
+		.vsel_mask = BUCK6OUT_MASK,
+		.enable_reg = PCA9450_BUCK6CTRL,
+		.enable_mask = BUCK6_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "ldo1",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO1,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO1_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo1_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts),
+		.vsel_reg = PCA9450_LDO1CTRL,
+		.vsel_mask = LDO1OUT_MASK,
+		.enable_reg = PCA9450_LDO1CTRL,
+		.enable_mask = LDO1_EN_MASK,
+	},
+	{
+		.name = "ldo2",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO2"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO2,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO2_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo2_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts),
+		.vsel_reg = PCA9450_LDO2CTRL,
+		.vsel_mask = LDO2OUT_MASK,
+		.enable_reg = PCA9450_LDO2CTRL,
+		.enable_mask = LDO2_EN_MASK,
+	},
+	{
+		.name = "ldo3",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO3"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO3,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo34_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+		.vsel_reg = PCA9450_LDO3CTRL,
+		.vsel_mask = LDO3OUT_MASK,
+		.enable_reg = PCA9450_LDO3CTRL,
+		.enable_mask = LDO3_EN_MASK,
+	},
+	{
+		.name = "ldo4",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO4"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO4,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo34_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+		.vsel_reg = PCA9450_LDO4CTRL,
+		.vsel_mask = LDO4OUT_MASK,
+		.enable_reg = PCA9450_LDO4CTRL,
+		.enable_mask = LDO4_EN_MASK,
+	},
+	{
+		.name = "ldo5",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO5"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO5,
+		.ops = &pca9450_ldo5_regulator_ops,
+		.n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo5_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts),
+		.vsel_reg = PCA9450_LDO5CTRL_H,
+		.vsel_mask = LDO5HOUT_MASK,
+		.enable_reg = PCA9450_LDO5CTRL_L,
+		.enable_mask = LDO5H_EN_MASK,
+	},
+};
+
+/*
+ * Buck3 removed on PCA9450B and connected with Buck1 internal for dual phase
+ * on PCA9450C as no Buck3.
+ */
+static struct regulator_desc pca9450bc_regulators[] = {
+	{
+		.name = "buck1",
+		.supply_name = "inb13",
+		.of_match = of_match_ptr("BUCK1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK1,
+		.ops = &pca9450_dvs_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK1_VOLTAGE_NUM,
+		.linear_ranges = pca9450_dvs_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+		.vsel_reg = PCA9450_BUCK1OUT_DVS0,
+		.vsel_mask = BUCK1OUT_DVS0_MASK,
+		.enable_reg = PCA9450_BUCK1CTRL,
+		.enable_mask = BUCK1_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck2",
+		.supply_name = "inb26",
+		.of_match = of_match_ptr("BUCK2"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK2,
+		.ops = &pca9450_dvs_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK2_VOLTAGE_NUM,
+		.linear_ranges = pca9450_dvs_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+		.vsel_reg = PCA9450_BUCK2OUT_DVS0,
+		.vsel_mask = BUCK2OUT_DVS0_MASK,
+		.enable_reg = PCA9450_BUCK2CTRL,
+		.enable_mask = BUCK2_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ_STBYREQ,
+	},
+	{
+		.name = "buck4",
+		.supply_name = "inb45",
+		.of_match = of_match_ptr("BUCK4"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK4,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK4_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK4OUT,
+		.vsel_mask = BUCK4OUT_MASK,
+		.enable_reg = PCA9450_BUCK4CTRL,
+		.enable_mask = BUCK4_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck5",
+		.supply_name = "inb45",
+		.of_match = of_match_ptr("BUCK5"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK5,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK5_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK5OUT,
+		.vsel_mask = BUCK5OUT_MASK,
+		.enable_reg = PCA9450_BUCK5CTRL,
+		.enable_mask = BUCK5_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck6",
+		.supply_name = "inb26",
+		.of_match = of_match_ptr("BUCK6"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK6,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK6_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK6OUT,
+		.vsel_mask = BUCK6OUT_MASK,
+		.enable_reg = PCA9450_BUCK6CTRL,
+		.enable_mask = BUCK6_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "ldo1",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO1,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO1_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo1_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts),
+		.vsel_reg = PCA9450_LDO1CTRL,
+		.vsel_mask = LDO1OUT_MASK,
+		.enable_reg = PCA9450_LDO1CTRL,
+		.enable_mask = LDO1_EN_MASK,
+	},
+	{
+		.name = "ldo2",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO2"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO2,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO2_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo2_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts),
+		.vsel_reg = PCA9450_LDO2CTRL,
+		.vsel_mask = LDO2OUT_MASK,
+		.enable_reg = PCA9450_LDO2CTRL,
+		.enable_mask = LDO2_EN_MASK,
+	},
+	{
+		.name = "ldo3",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO3"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO3,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo34_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+		.vsel_reg = PCA9450_LDO3CTRL,
+		.vsel_mask = LDO3OUT_MASK,
+		.enable_reg = PCA9450_LDO3CTRL,
+		.enable_mask = LDO3_EN_MASK,
+	},
+	{
+		.name = "ldo4",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO4"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO4,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo34_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+		.vsel_reg = PCA9450_LDO4CTRL,
+		.vsel_mask = LDO4OUT_MASK,
+		.enable_reg = PCA9450_LDO4CTRL,
+		.enable_mask = LDO4_EN_MASK,
+	},
+	{
+		.name = "ldo5",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO5"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO5,
+		.ops = &pca9450_ldo5_regulator_ops,
+		.n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo5_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts),
+		.vsel_reg = PCA9450_LDO5CTRL_H,
+		.vsel_mask = LDO5HOUT_MASK,
+		.enable_reg = PCA9450_LDO5CTRL_L,
+		.enable_mask = LDO5H_EN_MASK,
+	},
+};
+
+static struct regulator_desc pca9451a_regulators[] = {
+	{
+		.name = "buck1",
+		.supply_name = "inb13",
+		.of_match = of_match_ptr("BUCK1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK1,
+		.ops = &pca9450_dvs_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK1_VOLTAGE_NUM,
+		.linear_ranges = pca9451a_dvs_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9451a_dvs_buck_volts),
+		.vsel_reg = PCA9450_BUCK1OUT_DVS0,
+		.vsel_mask = BUCK1OUT_DVS0_MASK,
+		.enable_reg = PCA9450_BUCK1CTRL,
+		.enable_mask = BUCK1_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck2",
+		.supply_name = "inb26",
+		.of_match = of_match_ptr("BUCK2"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK2,
+		.ops = &pca9450_dvs_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK2_VOLTAGE_NUM,
+		.linear_ranges = pca9450_dvs_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+		.vsel_reg = PCA9450_BUCK2OUT_DVS0,
+		.vsel_mask = BUCK2OUT_DVS0_MASK,
+		.enable_reg = PCA9450_BUCK2CTRL,
+		.enable_mask = BUCK2_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ_STBYREQ,
+	},
+	{
+		.name = "buck4",
+		.supply_name = "inb45",
+		.of_match = of_match_ptr("BUCK4"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK4,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK4_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK4OUT,
+		.vsel_mask = BUCK4OUT_MASK,
+		.enable_reg = PCA9450_BUCK4CTRL,
+		.enable_mask = BUCK4_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck5",
+		.supply_name = "inb45",
+		.of_match = of_match_ptr("BUCK5"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK5,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK5_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK5OUT,
+		.vsel_mask = BUCK5OUT_MASK,
+		.enable_reg = PCA9450_BUCK5CTRL,
+		.enable_mask = BUCK5_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "buck6",
+		.supply_name = "inb26",
+		.of_match = of_match_ptr("BUCK6"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_BUCK6,
+		.ops = &pca9450_buck_regulator_ops,
+		.n_voltages = PCA9450_BUCK6_VOLTAGE_NUM,
+		.linear_ranges = pca9450_buck_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+		.vsel_reg = PCA9450_BUCK6OUT,
+		.vsel_mask = BUCK6OUT_MASK,
+		.enable_reg = PCA9450_BUCK6CTRL,
+		.enable_mask = BUCK6_ENMODE_MASK,
+		.enable_val = BUCK_ENMODE_ONREQ,
+	},
+	{
+		.name = "ldo1",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO1,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO1_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo1_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts),
+		.vsel_reg = PCA9450_LDO1CTRL,
+		.vsel_mask = LDO1OUT_MASK,
+		.enable_reg = PCA9450_LDO1CTRL,
+		.enable_mask = LDO1_EN_MASK,
+	},
+	{
+		.name = "ldo3",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO3"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO3,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo34_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+		.vsel_reg = PCA9450_LDO3CTRL,
+		.vsel_mask = LDO3OUT_MASK,
+		.enable_reg = PCA9450_LDO3CTRL,
+		.enable_mask = LDO3_EN_MASK,
+	},
+	{
+		.name = "ldo4",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO4"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO4,
+		.ops = &pca9450_ldo_regulator_ops,
+		.n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo34_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+		.vsel_reg = PCA9450_LDO4CTRL,
+		.vsel_mask = LDO4OUT_MASK,
+		.enable_reg = PCA9450_LDO4CTRL,
+		.enable_mask = LDO4_EN_MASK,
+	},
+	{
+		.name = "ldo5",
+		.supply_name = "inl1",
+		.of_match = of_match_ptr("LDO5"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = PCA9450_LDO5,
+		.ops = &pca9450_ldo5_regulator_ops,
+		.n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
+		.linear_ranges = pca9450_ldo5_volts,
+		.n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts),
+		.vsel_reg = PCA9450_LDO5CTRL_H,
+		.vsel_mask = LDO5HOUT_MASK,
+		.enable_reg = PCA9450_LDO5CTRL_L,
+		.enable_mask = LDO5H_EN_MASK,
+	},
+};
+
+static int pca9450_of_init(struct pca9450 *pca9450)
+{
+	struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev);
+	int ret;
+	unsigned int val;
+	unsigned int rstb_deb_ctrl;
+	unsigned int t_on_deb, t_off_deb;
+	unsigned int t_on_step, t_off_step;
+	unsigned int t_restart;
+
+	ret = of_property_read_u32(i2c->dev.of_node, "npx,pmic-rst-b-debounce-ms", &val);
+	if (ret == -EINVAL)
+		rstb_deb_ctrl = T_PMIC_RST_DEB_50MS;
+	else if (ret)
+		return ret;
+	else {
+		switch (val) {
+		case 10: rstb_deb_ctrl = T_PMIC_RST_DEB_10MS; break;
+		case 50: rstb_deb_ctrl = T_PMIC_RST_DEB_50MS; break;
+		case 100: rstb_deb_ctrl = T_PMIC_RST_DEB_100MS; break;
+		case 500: rstb_deb_ctrl = T_PMIC_RST_DEB_500MS; break;
+		case 1000: rstb_deb_ctrl = T_PMIC_RST_DEB_1S; break;
+		case 2000: rstb_deb_ctrl = T_PMIC_RST_DEB_2S; break;
+		case 4000: rstb_deb_ctrl = T_PMIC_RST_DEB_4S; break;
+		case 8000: rstb_deb_ctrl = T_PMIC_RST_DEB_8S; break;
+		default: return -EINVAL;
+		}
+	}
+	ret = regmap_update_bits(pca9450->regmap, PCA9450_RESET_CTRL,
+				 T_PMIC_RST_DEB_MASK, rstb_deb_ctrl);
+	if (ret)
+		return dev_err_probe(&i2c->dev, ret, "Failed to set PMIC_RST_B debounce time\n");
+
+	ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-on-debounce-us", &val);
+	if (ret == -EINVAL)
+		t_on_deb = T_ON_DEB_20MS;
+	else if (ret)
+		return ret;
+	else {
+		switch (val) {
+		case 120: t_on_deb = T_ON_DEB_120US; break;
+		case 20000: t_on_deb = T_ON_DEB_20MS; break;
+		case 100000: t_on_deb = T_ON_DEB_100MS; break;
+		case 750000: t_on_deb = T_ON_DEB_750MS; break;
+		default: return -EINVAL;
+		}
+	}
+
+	ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-off-debounce-us", &val);
+	if (ret == -EINVAL)
+		t_off_deb = pca9450->default_t_off_deb;
+	else if (ret)
+		return ret;
+	else {
+		switch (val) {
+		case 120: t_off_deb = T_OFF_DEB_120US; break;
+		case 2000: t_off_deb = T_OFF_DEB_2MS; break;
+		default: return -EINVAL;
+		}
+	}
+
+	ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-on-step-ms", &val);
+	if (ret == -EINVAL)
+		t_on_step = T_ON_STEP_2MS;
+	else if (ret)
+		return ret;
+	else {
+		switch (val) {
+		case 1: t_on_step = T_ON_STEP_1MS; break;
+		case 2: t_on_step = T_ON_STEP_2MS; break;
+		case 4: t_on_step = T_ON_STEP_4MS; break;
+		case 8: t_on_step = T_ON_STEP_8MS; break;
+		default: return -EINVAL;
+		}
+	}
+
+	ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-down-step-ms", &val);
+	if (ret == -EINVAL)
+		t_off_step = T_OFF_STEP_8MS;
+	else if (ret)
+		return ret;
+	else {
+		switch (val) {
+		case 2: t_off_step = T_OFF_STEP_2MS; break;
+		case 4: t_off_step = T_OFF_STEP_4MS; break;
+		case 8: t_off_step = T_OFF_STEP_8MS; break;
+		case 16: t_off_step = T_OFF_STEP_16MS; break;
+		default: return -EINVAL;
+		}
+	}
+
+	ret = of_property_read_u32(i2c->dev.of_node, "nxp,restart-ms", &val);
+	if (ret == -EINVAL)
+		t_restart = T_RESTART_250MS;
+	else if (ret)
+		return ret;
+	else {
+		switch (val) {
+		case 250: t_restart = T_RESTART_250MS; break;
+		case 500: t_restart = T_RESTART_500MS; break;
+		default: return -EINVAL;
+		}
+	}
+
+	ret = regmap_update_bits(pca9450->regmap, PCA9450_PWR_CTRL,
+				 T_ON_DEB_MASK | T_OFF_DEB_MASK | T_ON_STEP_MASK |
+				 T_OFF_STEP_MASK | T_RESTART_MASK,
+				 t_on_deb | t_off_deb | t_on_step |
+				 t_off_step | t_restart);
+	if (ret)
+		return dev_err_probe(&i2c->dev, ret,
+				     "Failed to set PWR_CTRL debounce configuration\n");
+
+	if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) {
+		/* Enable I2C Level Translator */
+		ret = regmap_update_bits(pca9450->regmap, PCA9450_CONFIG2,
+					 I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN);
+		if (ret)
+			return dev_err_probe(&i2c->dev, ret,
+					     "Failed to enable I2C level translator\n");
+	}
+
+	return 0;
+}
+
+static int pca9450_regulator_probe(struct device *dev)
+{
+	struct pca9450 *pca9450 = dev->parent->priv;
+	enum pca9450_chip_type type = pca9450->type;
+	const struct regulator_desc *regulator_desc;
+	struct regulator_config config = { };
+	struct regulator_dev *ldo5 = NULL;
+	unsigned int device_id, i;
+	const char *type_name;
+	int ret;
+
+	switch (type) {
+	case PCA9450_TYPE_PCA9450A:
+		regulator_desc = pca9450a_regulators;
+		pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators);
+		pca9450->default_t_off_deb = T_OFF_DEB_120US;
+		type_name = "pca9450a";
+		break;
+	case PCA9450_TYPE_PCA9450BC:
+		regulator_desc = pca9450bc_regulators;
+		pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators);
+		pca9450->default_t_off_deb = T_OFF_DEB_120US;
+		type_name = "pca9450bc";
+		break;
+	case PCA9450_TYPE_PCA9451A:
+		regulator_desc = pca9451a_regulators;
+		pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators);
+		pca9450->default_t_off_deb = T_OFF_DEB_2MS;
+		type_name = "pca9451a";
+		break;
+	case PCA9450_TYPE_PCA9452:
+		regulator_desc = pca9451a_regulators;
+		pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators);
+		pca9450->default_t_off_deb = T_OFF_DEB_2MS;
+		type_name = "pca9452";
+		break;
+	default:
+		dev_err(pca9450->dev, "Unknown device type");
+		return -EINVAL;
+	}
+
+	ret = regmap_read(pca9450->regmap, PCA9450_REG_DEV_ID, &device_id);
+	if (ret)
+		return dev_err_probe(pca9450->dev, ret, "Read device id error\n");
+
+	/* Check your board and dts for match the right pmic */
+	if (((device_id >> 4) != 0x1 && type == PCA9450_TYPE_PCA9450A) ||
+	    ((device_id >> 4) != 0x3 && type == PCA9450_TYPE_PCA9450BC) ||
+	    ((device_id >> 4) != 0x9 && type == PCA9450_TYPE_PCA9451A) ||
+	    ((device_id >> 4) != 0x9 && type == PCA9450_TYPE_PCA9452))
+		return dev_err_probe(pca9450->dev, -EINVAL,
+				     "Device id(%x) mismatched\n", device_id >> 4);
+
+	for (i = 0; i < pca9450->rcnt; i++) {
+		const struct regulator_desc *desc = &regulator_desc[i];
+		struct regulator_dev *rdev;
+
+		if (type == PCA9450_TYPE_PCA9451A && !strcmp(desc->name, "ldo3"))
+			continue;
+
+		config.regmap = pca9450->regmap;
+		config.dev = pca9450->dev;
+		config.driver_data = pca9450;
+
+		rdev = regulator_register(pca9450->dev, desc, &config);
+		if (!rdev)
+			return dev_err_probe(pca9450->dev, -EINVAL,
+					     "Failed to register regulator(%s)\n", desc->name);
+
+		if (!strcmp(desc->name, "ldo5"))
+			ldo5 = rdev;
+	}
+
+	/* Clear PRESET_EN bit in BUCK123_DVS to use DVS registers */
+	ret = regmap_clear_bits(pca9450->regmap, PCA9450_BUCK123_DVS,
+				BUCK123_PRESET_EN);
+	if (ret)
+		return dev_err_probe(pca9450->dev, ret,  "Failed to clear PRESET_EN bit\n");
+
+	ret = pca9450_of_init(pca9450);
+	if (ret)
+		return dev_err_probe(pca9450->dev, ret, "Unable to parse OF data\n");
+
+	/*
+	 * For LDO5 we need to be able to check the status of the SD_VSEL input in
+	 * order to know which control register is used. Most boards connect SD_VSEL
+	 * to the VSELECT signal, so we can use the GPIO that is internally routed
+	 * to this signal (if SION bit is set in IOMUX).
+	 */
+	pca9450->sd_vsel_gpio = dev_gpiod_get_index(ldo5->dev, ldo5->node,
+						    "sd-vsel", 0, GPIOD_IN, NULL);
+	if (gpiod_not_found(pca9450->sd_vsel_gpio))
+		pca9450->sd_vsel_gpio = NULL;
+	else if (IS_ERR(pca9450->sd_vsel_gpio))
+		return dev_err_probe(pca9450->dev, PTR_ERR(pca9450->sd_vsel_gpio),
+				     "Failed to get SD_VSEL GPIO\n");
+
+	pca9450->sd_vsel_fixed_low =
+		of_property_read_bool(ldo5->dev->of_node, "nxp,sd-vsel-fixed-low");
+
+	dev_info(pca9450->dev, "%s probed.\n", type_name);
+
+	return 0;
+}
+
+static struct driver pca9450_regulator_driver = {
+	.name = "pca9450-regulator",
+	.probe = pca9450_regulator_probe,
+};
+coredevice_platform_driver(pca9450_regulator_driver);
+
+MODULE_AUTHOR("Robin Gong <yibin.gong@nxp.com>");
+MODULE_DESCRIPTION("NXP PCA9450 Power Management IC driver");
+MODULE_LICENSE("GPL");
diff --git a/include/mfd/pca9450.h b/include/mfd/pca9450.h
index af10e40985..02d38557d2 100644
--- a/include/mfd/pca9450.h
+++ b/include/mfd/pca9450.h
@@ -6,8 +6,28 @@
 #ifndef PCA9450_H_
 #define PCA9450_H_
 
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
 #include <linux/regmap.h>
 
+enum pca9450_chip_type {
+	PCA9450_TYPE_PCA9450A = 0,
+	PCA9450_TYPE_PCA9450BC,
+	PCA9450_TYPE_PCA9451A,
+	PCA9450_TYPE_PCA9452,
+	PCA9450_TYPE_AMOUNT,
+};
+
+struct pca9450 {
+	struct device *dev;
+	struct regmap *regmap;
+	enum pca9450_chip_type type;
+	unsigned int rcnt;
+	struct gpio_desc *sd_vsel_gpio;
+	bool sd_vsel_fixed_low;
+	int default_t_off_deb;
+};
+
 enum {
 	PCA9450_REG_DEV_ID      = 0x00,
 	PCA9450_INT1            = 0x01,
@@ -54,6 +74,216 @@ enum {
 	PCA9450_REG_NUM,
 };
 
+enum {
+	PCA9450_BUCK1 = 0,
+	PCA9450_BUCK2,
+	PCA9450_BUCK3,
+	PCA9450_BUCK4,
+	PCA9450_BUCK5,
+	PCA9450_BUCK6,
+	PCA9450_LDO1,
+	PCA9450_LDO2,
+	PCA9450_LDO3,
+	PCA9450_LDO4,
+	PCA9450_LDO5,
+	PCA9450_REGULATOR_CNT,
+};
+
+enum {
+	PCA9450_DVS_LEVEL_RUN = 0,
+	PCA9450_DVS_LEVEL_STANDBY,
+	PCA9450_DVS_LEVEL_MAX,
+};
+
+#define PCA9450_BUCK1_VOLTAGE_NUM	0x80
+#define PCA9450_BUCK2_VOLTAGE_NUM	0x80
+#define PCA9450_BUCK3_VOLTAGE_NUM	0x80
+#define PCA9450_BUCK4_VOLTAGE_NUM	0x80
+
+#define PCA9450_BUCK5_VOLTAGE_NUM	0x80
+#define PCA9450_BUCK6_VOLTAGE_NUM	0x80
+
+#define PCA9450_LDO1_VOLTAGE_NUM	0x08
+#define PCA9450_LDO2_VOLTAGE_NUM	0x08
+#define PCA9450_LDO3_VOLTAGE_NUM	0x20
+#define PCA9450_LDO4_VOLTAGE_NUM	0x20
+#define PCA9450_LDO5_VOLTAGE_NUM	0x10
+
+/* PCA9450 BUCK ENMODE bits */
+#define BUCK_ENMODE_OFF			0x00
+#define BUCK_ENMODE_ONREQ		0x01
+#define BUCK_ENMODE_ONREQ_STBYREQ	0x02
+#define BUCK_ENMODE_ON			0x03
+
+/* PCA9450_REG_BUCK1_CTRL bits */
+#define BUCK1_RAMP_MASK			0xC0
+#define BUCK1_RAMP_25MV			0x0
+#define BUCK1_RAMP_12P5MV		0x1
+#define BUCK1_RAMP_6P25MV		0x2
+#define BUCK1_RAMP_3P125MV		0x3
+#define BUCK1_DVS_CTRL			0x10
+#define BUCK1_AD			0x08
+#define BUCK1_FPWM			0x04
+#define BUCK1_ENMODE_MASK		0x03
+
+/* PCA9450_REG_BUCK2_CTRL bits */
+#define BUCK2_RAMP_MASK			0xC0
+#define BUCK2_RAMP_25MV			0x0
+#define BUCK2_RAMP_12P5MV		0x1
+#define BUCK2_RAMP_6P25MV		0x2
+#define BUCK2_RAMP_3P125MV		0x3
+#define BUCK2_DVS_CTRL			0x10
+#define BUCK2_AD			0x08
+#define BUCK2_FPWM			0x04
+#define BUCK2_ENMODE_MASK		0x03
+
+/* PCA9450_REG_BUCK3_CTRL bits */
+#define BUCK3_RAMP_MASK			0xC0
+#define BUCK3_RAMP_25MV			0x0
+#define BUCK3_RAMP_12P5MV		0x1
+#define BUCK3_RAMP_6P25MV		0x2
+#define BUCK3_RAMP_3P125MV		0x3
+#define BUCK3_DVS_CTRL			0x10
+#define BUCK3_AD			0x08
+#define BUCK3_FPWM			0x04
+#define BUCK3_ENMODE_MASK		0x03
+
+/* PCA9450_REG_BUCK4_CTRL bits */
+#define BUCK4_AD			0x08
+#define BUCK4_FPWM			0x04
+#define BUCK4_ENMODE_MASK		0x03
+
+/* PCA9450_REG_BUCK5_CTRL bits */
+#define BUCK5_AD			0x08
+#define BUCK5_FPWM			0x04
+#define BUCK5_ENMODE_MASK		0x03
+
+/* PCA9450_REG_BUCK6_CTRL bits */
+#define BUCK6_AD			0x08
+#define BUCK6_FPWM			0x04
+#define BUCK6_ENMODE_MASK		0x03
+
+/* PCA9450_REG_BUCK123_PRESET_EN bit */
+#define BUCK123_PRESET_EN		0x80
+
+/* PCA9450_BUCK1OUT_DVS0 bits */
+#define BUCK1OUT_DVS0_MASK		0x7F
+#define BUCK1OUT_DVS0_DEFAULT		0x14
+
+/* PCA9450_BUCK1OUT_DVS1 bits */
+#define BUCK1OUT_DVS1_MASK		0x7F
+#define BUCK1OUT_DVS1_DEFAULT		0x14
+
+/* PCA9450_BUCK2OUT_DVS0 bits */
+#define BUCK2OUT_DVS0_MASK		0x7F
+#define BUCK2OUT_DVS0_DEFAULT		0x14
+
+/* PCA9450_BUCK2OUT_DVS1 bits */
+#define BUCK2OUT_DVS1_MASK		0x7F
+#define BUCK2OUT_DVS1_DEFAULT		0x14
+
+/* PCA9450_BUCK3OUT_DVS0 bits */
+#define BUCK3OUT_DVS0_MASK		0x7F
+#define BUCK3OUT_DVS0_DEFAULT		0x14
+
+/* PCA9450_BUCK3OUT_DVS1 bits */
+#define BUCK3OUT_DVS1_MASK		0x7F
+#define BUCK3OUT_DVS1_DEFAULT		0x14
+
+/* PCA9450_REG_BUCK4OUT bits */
+#define BUCK4OUT_MASK			0x7F
+#define BUCK4OUT_DEFAULT		0x6C
+
+/* PCA9450_REG_BUCK5OUT bits */
+#define BUCK5OUT_MASK			0x7F
+#define BUCK5OUT_DEFAULT		0x30
+
+/* PCA9450_REG_BUCK6OUT bits */
+#define BUCK6OUT_MASK			0x7F
+#define BUCK6OUT_DEFAULT		0x14
+
+/* PCA9450_REG_LDO1_VOLT bits */
+#define LDO1_EN_MASK			0xC0
+#define LDO1OUT_MASK			0x07
+
+/* PCA9450_REG_LDO2_VOLT bits */
+#define LDO2_EN_MASK			0xC0
+#define LDO2OUT_MASK			0x07
+
+/* PCA9450_REG_LDO3_VOLT bits */
+#define LDO3_EN_MASK			0xC0
+#define LDO3OUT_MASK			0x1F
+
+/* PCA9450_REG_LDO4_VOLT bits */
+#define LDO4_EN_MASK			0xC0
+#define LDO4OUT_MASK			0x1F
+
+/* PCA9450_REG_LDO5_VOLT bits */
+#define LDO5L_EN_MASK			0xC0
+#define LDO5LOUT_MASK			0x0F
+
+#define LDO5H_EN_MASK			0xC0
+#define LDO5HOUT_MASK			0x0F
+
+/* PCA9450_REG_IRQ bits */
+#define IRQ_PWRON			0x80
+#define IRQ_WDOGB			0x40
+#define IRQ_RSVD			0x20
+#define IRQ_VR_FLT1			0x10
+#define IRQ_VR_FLT2			0x08
+#define IRQ_LOWVSYS			0x04
+#define IRQ_THERM_105			0x02
+#define IRQ_THERM_125			0x01
+
+/* PCA9450_REG_PWRCTRL bits */
+#define T_ON_DEB_MASK			0xC0
+#define T_ON_DEB_120US			(0 << 6)
+#define T_ON_DEB_20MS			(1 << 6)
+#define T_ON_DEB_100MS			(2 << 6)
+#define T_ON_DEB_750MS			(3 << 6)
+#define T_OFF_DEB_MASK			0x20
+#define T_OFF_DEB_120US			(0 << 5)
+#define T_OFF_DEB_2MS			(1 << 5)
+#define T_ON_STEP_MASK			0x18
+#define T_ON_STEP_1MS			(0 << 3)
+#define T_ON_STEP_2MS			(1 << 3)
+#define T_ON_STEP_4MS			(2 << 3)
+#define T_ON_STEP_8MS			(3 << 3)
+#define T_OFF_STEP_MASK			0x06
+#define T_OFF_STEP_2MS			(0 << 1)
+#define T_OFF_STEP_4MS			(1 << 1)
+#define T_OFF_STEP_8MS			(2 << 1)
+#define T_OFF_STEP_16MS			(3 << 1)
+#define T_RESTART_MASK			0x01
+#define T_RESTART_250MS			0
+#define T_RESTART_500MS			1
+
+/* PCA9450_REG_RESET_CTRL bits */
+#define WDOG_B_CFG_MASK			0xC0
+#define WDOG_B_CFG_NONE			0x00
+#define WDOG_B_CFG_WARM			0x40
+#define WDOG_B_CFG_COLD_LDO12		0x80
+#define WDOG_B_CFG_COLD			0xC0
+#define T_PMIC_RST_DEB_MASK		0x07
+#define T_PMIC_RST_DEB_10MS		0x00
+#define T_PMIC_RST_DEB_50MS		0x01
+#define T_PMIC_RST_DEB_100MS		0x02
+#define T_PMIC_RST_DEB_500MS		0x03
+#define T_PMIC_RST_DEB_1S		0x04
+#define T_PMIC_RST_DEB_2S		0x05
+#define T_PMIC_RST_DEB_4S		0x06
+#define T_PMIC_RST_DEB_8S		0x07
+
+/* PCA9450_REG_CONFIG2 bits */
+#define I2C_LT_MASK			0x03
+#define I2C_LT_FORCE_DISABLE		0x00
+#define I2C_LT_ON_STANDBY_RUN		0x01
+#define I2C_LT_ON_RUN			0x02
+#define I2C_LT_FORCE_ENABLE		0x03
+
+/* PCA9450_REG_SW_RST command */
+#define SW_RST_COMMAND			0x14
+
 #ifdef CONFIG_MFD_PCA9450
 
 int pca9450_register_init_callback(void(*callback)(struct regmap *map));

---
base-commit: 504c7918417a29aad8313fe532329558cd984053
change-id: 20260824-feature-pca9450-pmic-fc2740e5f44c

Best regards,
--  
Stefan Kerkmann <s.kerkmann@pengutronix.de>




             reply	other threads:[~2026-08-24 15:10 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-24 15:07 Stefan Kerkmann [this message]
2026-08-28 13:18 ` Sascha Hauer

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=20260824-feature-pca9450-pmic-v1-1-8db9945555ce@pengutronix.de \
    --to=s.kerkmann@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=s.hauer@pengutronix.de \
    /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