[PATCH 4/6] mfd: qcom-pm8008: Add PM8010 support

From: Jishnu Prakash

Date: Fri Sep 18 2026 - 13:43:14 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 | 67 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c
index 60204cc9a2dc..ed656f0d6df2 100644
--- a/drivers/mfd/qcom-pm8008.c
+++ b/drivers/mfd/qcom-pm8008.c
@@ -34,6 +34,7 @@ enum {
PM8008_GPIO1,
PM8008_GPIO2,
PM8008_NUM_PERIPHS,
+ PM8010_NUM_PERIPHS = 2,
};

#define PM8008_PERIPH_0_BASE 0x900
@@ -55,6 +56,10 @@ enum {
#define PM8008_IRQ_GPIO1 6
#define PM8008_IRQ_GPIO2 7

+#define PM8010_IRQ_MISC_MBG_FAULT 0
+/* 1-3 are unused */
+#define PM8010_IRQ_MISC_LDO_OCP 4
+
enum {
SET_TYPE_INDEX,
POLARITY_HI_INDEX,
@@ -88,6 +93,12 @@ static const struct regmap_irq pm8008_irqs[] = {
_IRQ(PM8008_IRQ_GPIO2, PM8008_GPIO2, 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,
@@ -158,6 +169,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 = PM8010_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 = PM8010_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,
@@ -183,6 +213,17 @@ static const struct mfd_cell pm8008_cells[] = {
MFD_CELL_NAME("pm8008-gpio"),
};

+static const struct mfd_cell pm8010_cells[] = {
+ MFD_CELL_NAME("pm8010-regulator"),
+ MFD_CELL_RES("qpnp-temp-alarm", pm8008_temp_res),
+};
+
+struct pm8008_match_data {
+ const struct regmap_irq_chip *irq_chip_desc;
+ const struct mfd_cell *mfd_cells;
+ int num_mfd_cells;
+};
+
static void devm_irq_domain_fwnode_release(void *data)
{
struct fwnode_handle *fwnode = data;
@@ -193,6 +234,7 @@ 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 pm8008_match_data *data;
struct device *dev = &client->dev;
struct regmap *regmap, *regmap2;
struct fwnode_handle *fwnode;
@@ -201,6 +243,10 @@ static int pm8008_probe(struct i2c_client *client)
char *name;
int ret;

+ data = device_get_match_data(dev);
+ if (!data)
+ return dev_err_probe(dev, -ENODATA, "Missing driver match data\n");
+
dummy = devm_i2c_new_dummy_device(dev, client->adapter, client->addr + 1);
if (IS_ERR(dummy)) {
ret = PTR_ERR(dummy);
@@ -246,7 +292,7 @@ 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, data->irq_chip_desc, &irq_data);
if (ret) {
dev_err(dev, "failed to add IRQ chip: %d\n", ret);
return ret;
@@ -255,13 +301,26 @@ static int pm8008_probe(struct i2c_client *client)
/* Needed by GPIO driver. */
dev_set_drvdata(dev, regmap_irq_get_domain(irq_data));

- 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, data->mfd_cells,
+ data->num_mfd_cells, NULL, 0,
regmap_irq_get_domain(irq_data));
}

+static const struct pm8008_match_data pm8008_data = {
+ .irq_chip_desc = &pm8008_irq_chip,
+ .mfd_cells = pm8008_cells,
+ .num_mfd_cells = ARRAY_SIZE(pm8008_cells),
+};
+
+static const struct pm8008_match_data pm8010_data = {
+ .irq_chip_desc = &pm8010_irq_chip,
+ .mfd_cells = pm8010_cells,
+ .num_mfd_cells = ARRAY_SIZE(pm8010_cells),
+};
+
static const struct of_device_id pm8008_match[] = {
- { .compatible = "qcom,pm8008", },
+ { .compatible = "qcom,pm8008", .data = &pm8008_data },
+ { .compatible = "qcom,pm8010-i2c", .data = &pm8010_data },
{ },
};
MODULE_DEVICE_TABLE(of, pm8008_match);

--
2.43.0