[PATCH v2 5/7] mfd: qcom-pm8008: Add PM8010 support

From: Jishnu Prakash

Date: Wed Oct 14 2026 - 06:35:39 EST


From: Konrad Dybcio <konrad.dybcio@xxxxxxxxxxxxxxxx>

PM8010 is effectively the next generation of PM8008. The device is
generally designed to serve the exact same function - power camera
sensors and the associated supporting hardware.

PM8010 supports both I2C and SPMI communications. The latter case is
already handled, since it reuses the same peripherals as other PMICs.
The I2C front-end is more less the same to the one of PM8008.

Plumb in the necessary changes to support it.

Signed-off-by: Konrad Dybcio <konrad.dybcio@xxxxxxxxxxxxxxxx>
Co-developed-by: Dhruvin Rajpura <drajpura@xxxxxxxxxxxxxxxx>
Signed-off-by: Dhruvin Rajpura <drajpura@xxxxxxxxxxxxxxxx>
Co-developed-by: Jishnu Prakash <jishnu.prakash@xxxxxxxxxxxxxxxx>
Signed-off-by: Jishnu Prakash <jishnu.prakash@xxxxxxxxxxxxxxxx>
---
drivers/mfd/qcom-pm8008.c | 69 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 65 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c
index 2d6c01cf54f3..4179427f3891 100644
--- a/drivers/mfd/qcom-pm8008.c
+++ b/drivers/mfd/qcom-pm8008.c
@@ -34,6 +34,11 @@ enum {
PM8008_NUM_PERIPHS,
};

+enum pm8008_chip_type {
+ TYPE_PM8008,
+ TYPE_PM8010,
+};
+
#define PM8008_PERIPH_0_BASE 0x900
#define PM8008_PERIPH_1_BASE 0x2400

@@ -47,6 +52,9 @@ enum {
#define PM8008_IRQ_MISC_LDO_OCP 4
#define PM8008_IRQ_TEMP_ALARM 5

+#define PM8010_IRQ_MISC_MBG_FAULT 0
+#define PM8010_IRQ_MISC_LDO_OCP 4
+
enum {
SET_TYPE_INDEX,
POLARITY_HI_INDEX,
@@ -78,6 +86,12 @@ static const struct regmap_irq pm8008_irqs[] = {
_IRQ(PM8008_IRQ_TEMP_ALARM, PM8008_TEMP_ALARM,BIT(0), IRQ_TYPE_SENSE_MASK),
};

+static const struct regmap_irq pm8010_irqs[] = {
+ _IRQ(PM8010_IRQ_MISC_MBG_FAULT, PM8008_MISC, BIT(0), IRQ_TYPE_EDGE_RISING),
+ _IRQ(PM8010_IRQ_MISC_LDO_OCP, PM8008_MISC, BIT(4), IRQ_TYPE_EDGE_RISING),
+ _IRQ(PM8008_IRQ_TEMP_ALARM, PM8008_TEMP_ALARM, BIT(0), IRQ_TYPE_SENSE_MASK),
+};
+
static const unsigned int pm8008_periph_base[] = {
PM8008_PERIPH_0_BASE,
PM8008_PERIPH_1_BASE,
@@ -146,6 +160,25 @@ static const struct regmap_irq_chip pm8008_irq_chip = {
.get_irq_reg = pm8008_get_irq_reg,
};

+static const struct regmap_irq_chip pm8010_irq_chip = {
+ .name = "pm8010",
+ .main_status = I2C_INTR_STATUS_BASE,
+ .num_main_regs = 1,
+ .irqs = pm8010_irqs,
+ .num_irqs = ARRAY_SIZE(pm8010_irqs),
+ .num_regs = PM8008_NUM_PERIPHS,
+ .status_base = INT_LATCHED_STS_OFFSET,
+ .mask_base = INT_EN_CLR_OFFSET,
+ .unmask_base = INT_EN_SET_OFFSET,
+ .mask_unmask_non_inverted = true,
+ .ack_base = INT_LATCHED_CLR_OFFSET,
+ .config_base = pm8008_config_regs,
+ .num_config_bases = ARRAY_SIZE(pm8008_config_regs),
+ .num_config_regs = PM8008_NUM_PERIPHS,
+ .set_type_config = pm8008_set_type_config,
+ .get_irq_reg = pm8008_get_irq_reg,
+};
+
static const struct regmap_config qcom_mfd_regmap_cfg = {
.name = "primary",
.reg_bits = 16,
@@ -170,6 +203,11 @@ static const struct mfd_cell pm8008_cells[] = {
MFD_CELL_RES("qpnp-temp-alarm", pm8008_temp_res),
};

+static const struct mfd_cell pm8010_cells[] = {
+ MFD_CELL_NAME("pm8010-regulator"),
+ MFD_CELL_RES("qpnp-temp-alarm", pm8008_temp_res),
+};
+
static void devm_irq_domain_fwnode_release(void *data)
{
struct fwnode_handle *fwnode = data;
@@ -180,14 +218,36 @@ static void devm_irq_domain_fwnode_release(void *data)
static int pm8008_probe(struct i2c_client *client)
{
struct regmap_irq_chip_data *irq_data;
+ const struct regmap_irq_chip *irq_chip_desc;
struct device *dev = &client->dev;
+ const struct mfd_cell *mfd_cells;
struct regmap *regmap, *regmap2;
struct fwnode_handle *fwnode;
struct i2c_client *dummy;
struct gpio_desc *reset;
+ unsigned long pmic_type;
+ int num_mfd_cells;
char *name;
int ret;

+ pmic_type = (unsigned long)of_device_get_match_data(dev);
+
+ switch (pmic_type) {
+ case TYPE_PM8008:
+ irq_chip_desc = &pm8008_irq_chip;
+ mfd_cells = pm8008_cells;
+ num_mfd_cells = ARRAY_SIZE(pm8008_cells);
+ break;
+ case TYPE_PM8010:
+ irq_chip_desc = &pm8010_irq_chip;
+ mfd_cells = pm8010_cells;
+ num_mfd_cells = ARRAY_SIZE(pm8010_cells);
+ break;
+ default:
+ dev_err(dev, "Unknown device type: %lu\n", pmic_type);
+ return -EINVAL;
+ }
+
dummy = devm_i2c_new_dummy_device(dev, client->adapter, client->addr + 1);
if (IS_ERR(dummy)) {
ret = PTR_ERR(dummy);
@@ -233,19 +293,20 @@ static int pm8008_probe(struct i2c_client *client)
return ret;

ret = devm_regmap_add_irq_chip_fwnode(dev, fwnode, regmap, client->irq,
- IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data);
+ IRQF_SHARED, 0, irq_chip_desc, &irq_data);
if (ret) {
dev_err(dev, "failed to add IRQ chip: %d\n", ret);
return ret;
}

- return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, pm8008_cells,
- ARRAY_SIZE(pm8008_cells), NULL, 0,
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, mfd_cells,
+ num_mfd_cells, NULL, 0,
regmap_irq_get_domain(irq_data));
}

static const struct of_device_id pm8008_match[] = {
- { .compatible = "qcom,pm8008", },
+ { .compatible = "qcom,pm8008", .data = (void *)TYPE_PM8008, },
+ { .compatible = "qcom,pm8010-i2c", .data = (void *)TYPE_PM8010, },
{ },
};
MODULE_DEVICE_TABLE(of, pm8008_match);

--
2.43.0