]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mfd: pf1550: Add core driver for the PF1550 PMIC
authorSamuel Kayode <samuel.kayode@savoirfairelinux.com>
Wed, 1 Oct 2025 15:42:38 +0000 (11:42 -0400)
committerLee Jones <lee@kernel.org>
Tue, 21 Oct 2025 15:43:32 +0000 (16:43 +0100)
There are 3 sub-devices for which the drivers will be added in
subsequent patches.

Signed-off-by: Samuel Kayode <samuel.kayode@savoirfairelinux.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Tested-by: Sean Nyekjaer <sean@geanix.com>
Link: https://patch.msgid.link/20251001-pf1550-v12-2-a3302aa41687@savoirfairelinux.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/pf1550.c [new file with mode: 0644]
include/linux/mfd/pf1550.h [new file with mode: 0644]

index 6cec1858947bf7ab5ee78beb730c95dabcb43a98..219ee6ddf5161b38e63660029a5ca5d1e61d1350 100644 (file)
@@ -605,6 +605,22 @@ config MFD_MX25_TSADC
          i.MX25 processors. They consist of a conversion queue for general
          purpose ADC and a queue for Touchscreens.
 
+config MFD_PF1550
+       tristate "NXP PF1550 PMIC Support"
+       depends on I2C=y && OF
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+         Say yes here to add support for NXP PF1550. This is a companion Power
+         Management IC with regulators, onkey, and charger control on chip.
+         This driver provides common support for accessing the device;
+         additional drivers must be enabled in order to use the functionality
+         of the device.
+
+         This driver can also be built as a module and if so will be called
+         pf1550.
+
 config MFD_HI6421_PMIC
        tristate "HiSilicon Hi6421 PMU/Codec IC"
        depends on OF
index 865e9f12faff02723c74541481840c6e3b4471e5..566952f191b519f9c2f570868feeb717ce68e738 100644 (file)
@@ -122,6 +122,8 @@ obj-$(CONFIG_MFD_MC13XXX)   += mc13xxx-core.o
 obj-$(CONFIG_MFD_MC13XXX_SPI)  += mc13xxx-spi.o
 obj-$(CONFIG_MFD_MC13XXX_I2C)  += mc13xxx-i2c.o
 
+obj-$(CONFIG_MFD_PF1550)       += pf1550.o
+
 obj-$(CONFIG_MFD_NCT6694)      += nct6694.o
 
 obj-$(CONFIG_MFD_CORE)         += mfd-core.o
diff --git a/drivers/mfd/pf1550.c b/drivers/mfd/pf1550.c
new file mode 100644 (file)
index 0000000..c4f567c
--- /dev/null
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Core driver for the PF1550
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Robin Gong <yibin.gong@freescale.com>
+ *
+ * Portions Copyright (c) 2025 Savoir-faire Linux Inc.
+ * Samuel Kayode <samuel.kayode@savoirfairelinux.com>
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/pf1550.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+static const struct regmap_config pf1550_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = PF1550_PMIC_REG_END,
+};
+
+static const struct regmap_irq pf1550_irqs[] = {
+       REGMAP_IRQ_REG(PF1550_IRQ_CHG, 0, IRQ_CHG),
+       REGMAP_IRQ_REG(PF1550_IRQ_REGULATOR, 0, IRQ_REGULATOR),
+       REGMAP_IRQ_REG(PF1550_IRQ_ONKEY, 0, IRQ_ONKEY),
+};
+
+static const struct regmap_irq_chip pf1550_irq_chip = {
+       .name = "pf1550",
+       .status_base = PF1550_PMIC_REG_INT_CATEGORY,
+       .init_ack_masked = 1,
+       .num_regs = 1,
+       .irqs = pf1550_irqs,
+       .num_irqs = ARRAY_SIZE(pf1550_irqs),
+};
+
+static const struct regmap_irq pf1550_regulator_irqs[] = {
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW1_LS, 0, PMIC_IRQ_SW1_LS),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW2_LS, 0, PMIC_IRQ_SW2_LS),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW3_LS, 0, PMIC_IRQ_SW3_LS),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW1_HS, 3, PMIC_IRQ_SW1_HS),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW2_HS, 3, PMIC_IRQ_SW2_HS),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW3_HS, 3, PMIC_IRQ_SW3_HS),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO1_FAULT, 16, PMIC_IRQ_LDO1_FAULT),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO2_FAULT, 16, PMIC_IRQ_LDO2_FAULT),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO3_FAULT, 16, PMIC_IRQ_LDO3_FAULT),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_TEMP_110, 24, PMIC_IRQ_TEMP_110),
+       REGMAP_IRQ_REG(PF1550_PMIC_IRQ_TEMP_125, 24, PMIC_IRQ_TEMP_125),
+};
+
+static const struct regmap_irq_chip pf1550_regulator_irq_chip = {
+       .name = "pf1550-regulator",
+       .status_base = PF1550_PMIC_REG_SW_INT_STAT0,
+       .ack_base = PF1550_PMIC_REG_SW_INT_STAT0,
+       .mask_base = PF1550_PMIC_REG_SW_INT_MASK0,
+       .use_ack = 1,
+       .init_ack_masked = 1,
+       .num_regs = 25,
+       .irqs = pf1550_regulator_irqs,
+       .num_irqs = ARRAY_SIZE(pf1550_regulator_irqs),
+};
+
+static const struct resource regulator_resources[] = {
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW1_LS),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW2_LS),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW3_LS),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW1_HS),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW2_HS),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW3_HS),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO1_FAULT),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO2_FAULT),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO3_FAULT),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_TEMP_110),
+       DEFINE_RES_IRQ(PF1550_PMIC_IRQ_TEMP_125),
+};
+
+static const struct regmap_irq pf1550_onkey_irqs[] = {
+       REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_PUSHI, 0, ONKEY_IRQ_PUSHI),
+       REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_1SI, 0, ONKEY_IRQ_1SI),
+       REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_2SI, 0, ONKEY_IRQ_2SI),
+       REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_3SI, 0, ONKEY_IRQ_3SI),
+       REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_4SI, 0, ONKEY_IRQ_4SI),
+       REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_8SI, 0, ONKEY_IRQ_8SI),
+};
+
+static const struct regmap_irq_chip pf1550_onkey_irq_chip = {
+       .name = "pf1550-onkey",
+       .status_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
+       .ack_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
+       .mask_base = PF1550_PMIC_REG_ONKEY_INT_MASK0,
+       .use_ack = 1,
+       .init_ack_masked = 1,
+       .num_regs = 1,
+       .irqs = pf1550_onkey_irqs,
+       .num_irqs = ARRAY_SIZE(pf1550_onkey_irqs),
+};
+
+static const struct resource onkey_resources[] = {
+       DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_PUSHI),
+       DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_1SI),
+       DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_2SI),
+       DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_3SI),
+       DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_4SI),
+       DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_8SI),
+};
+
+static const struct regmap_irq pf1550_charger_irqs[] = {
+       REGMAP_IRQ_REG(PF1550_CHARG_IRQ_BAT2SOCI, 0, CHARG_IRQ_BAT2SOCI),
+       REGMAP_IRQ_REG(PF1550_CHARG_IRQ_BATI, 0, CHARG_IRQ_BATI),
+       REGMAP_IRQ_REG(PF1550_CHARG_IRQ_CHGI, 0, CHARG_IRQ_CHGI),
+       REGMAP_IRQ_REG(PF1550_CHARG_IRQ_VBUSI, 0, CHARG_IRQ_VBUSI),
+       REGMAP_IRQ_REG(PF1550_CHARG_IRQ_THMI, 0, CHARG_IRQ_THMI),
+};
+
+static const struct regmap_irq_chip pf1550_charger_irq_chip = {
+       .name = "pf1550-charger",
+       .status_base = PF1550_CHARG_REG_CHG_INT,
+       .ack_base = PF1550_CHARG_REG_CHG_INT,
+       .mask_base = PF1550_CHARG_REG_CHG_INT_MASK,
+       .use_ack = 1,
+       .init_ack_masked = 1,
+       .num_regs = 1,
+       .irqs = pf1550_charger_irqs,
+       .num_irqs = ARRAY_SIZE(pf1550_charger_irqs),
+};
+
+static const struct resource charger_resources[] = {
+       DEFINE_RES_IRQ(PF1550_CHARG_IRQ_BAT2SOCI),
+       DEFINE_RES_IRQ(PF1550_CHARG_IRQ_BATI),
+       DEFINE_RES_IRQ(PF1550_CHARG_IRQ_CHGI),
+       DEFINE_RES_IRQ(PF1550_CHARG_IRQ_VBUSI),
+       DEFINE_RES_IRQ(PF1550_CHARG_IRQ_THMI),
+};
+
+static const struct mfd_cell pf1550_regulator_cell = {
+       .name = "pf1550-regulator",
+       .num_resources = ARRAY_SIZE(regulator_resources),
+       .resources = regulator_resources,
+};
+
+static const struct mfd_cell pf1550_onkey_cell = {
+       .name = "pf1550-onkey",
+       .num_resources = ARRAY_SIZE(onkey_resources),
+       .resources = onkey_resources,
+};
+
+static const struct mfd_cell pf1550_charger_cell = {
+       .name = "pf1550-charger",
+       .num_resources = ARRAY_SIZE(charger_resources),
+       .resources = charger_resources,
+};
+
+/*
+ * The PF1550 is shipped in variants of A0, A1,...A9. Each variant defines a
+ * configuration of the PMIC in a One-Time Programmable (OTP) memory.
+ * This memory is accessed indirectly by writing valid keys to specific
+ * registers of the PMIC. To read the OTP memory after writing the valid keys,
+ * the OTP register address to be read is written to pf1550 register 0xc4 and
+ * its value read from pf1550 register 0xc5.
+ */
+static int pf1550_read_otp(const struct pf1550_ddata *pf1550, unsigned int index,
+                          unsigned int *val)
+{
+       int ret = 0;
+
+       ret = regmap_write(pf1550->regmap, PF1550_PMIC_REG_KEY, PF1550_OTP_PMIC_KEY);
+       if (ret)
+               goto read_err;
+
+       ret = regmap_write(pf1550->regmap, PF1550_CHARG_REG_CHGR_KEY2, PF1550_OTP_CHGR_KEY);
+       if (ret)
+               goto read_err;
+
+       ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_KEY3, PF1550_OTP_TEST_KEY);
+       if (ret)
+               goto read_err;
+
+       ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_FMRADDR, index);
+       if (ret)
+               goto read_err;
+
+       ret = regmap_read(pf1550->regmap, PF1550_TEST_REG_FMRDATA, val);
+       if (ret)
+               goto read_err;
+
+       return 0;
+
+read_err:
+       return dev_err_probe(pf1550->dev, ret, "OTP reg %x not found!\n", index);
+}
+
+static int pf1550_i2c_probe(struct i2c_client *i2c)
+{
+       const struct mfd_cell *regulator = &pf1550_regulator_cell;
+       const struct mfd_cell *charger = &pf1550_charger_cell;
+       const struct mfd_cell *onkey = &pf1550_onkey_cell;
+       unsigned int reg_data = 0, otp_data = 0;
+       struct pf1550_ddata *pf1550;
+       struct irq_domain *domain;
+       int irq, ret = 0;
+
+       pf1550 = devm_kzalloc(&i2c->dev, sizeof(*pf1550), GFP_KERNEL);
+       if (!pf1550)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, pf1550);
+       pf1550->dev = &i2c->dev;
+       pf1550->irq = i2c->irq;
+
+       pf1550->regmap = devm_regmap_init_i2c(i2c, &pf1550_regmap_config);
+       if (IS_ERR(pf1550->regmap))
+               return dev_err_probe(pf1550->dev, PTR_ERR(pf1550->regmap),
+                                    "failed to allocate register map\n");
+
+       ret = regmap_read(pf1550->regmap, PF1550_PMIC_REG_DEVICE_ID, &reg_data);
+       if (ret < 0)
+               return dev_err_probe(pf1550->dev, ret, "cannot read chip ID\n");
+       if (reg_data != PF1550_DEVICE_ID)
+               return dev_err_probe(pf1550->dev, -ENODEV, "invalid device ID: 0x%02x\n", reg_data);
+
+       /* Regulator DVS for SW2 */
+       ret = pf1550_read_otp(pf1550, PF1550_OTP_SW2_SW3, &otp_data);
+       if (ret)
+               return ret;
+
+       /* When clear, DVS should be enabled */
+       if (!(otp_data & OTP_SW2_DVS_ENB))
+               pf1550->dvs2_enable = true;
+
+       /* Regulator DVS for SW1 */
+       ret = pf1550_read_otp(pf1550, PF1550_OTP_SW1_SW2, &otp_data);
+       if (ret)
+               return ret;
+
+       if (!(otp_data & OTP_SW1_DVS_ENB))
+               pf1550->dvs1_enable = true;
+
+       /* Add top level interrupts */
+       ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, pf1550->irq,
+                                      IRQF_ONESHOT | IRQF_SHARED |
+                                      IRQF_TRIGGER_FALLING,
+                                      0, &pf1550_irq_chip,
+                                      &pf1550->irq_data);
+       if (ret)
+               return ret;
+
+       /* Add regulator */
+       irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_REGULATOR);
+       if (irq < 0)
+               return dev_err_probe(pf1550->dev, irq,
+                                    "Failed to get parent vIRQ(%d) for chip %s\n",
+                                    PF1550_IRQ_REGULATOR, pf1550_irq_chip.name);
+
+       ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
+                                      IRQF_ONESHOT | IRQF_SHARED |
+                                      IRQF_TRIGGER_FALLING, 0,
+                                      &pf1550_regulator_irq_chip,
+                                      &pf1550->irq_data_regulator);
+       if (ret)
+               return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
+                                    pf1550_regulator_irq_chip.name);
+
+       domain = regmap_irq_get_domain(pf1550->irq_data_regulator);
+
+       ret = devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, regulator, 1, NULL, 0, domain);
+       if (ret)
+               return ret;
+
+       /* Add onkey */
+       irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_ONKEY);
+       if (irq < 0)
+               return dev_err_probe(pf1550->dev, irq,
+                                    "Failed to get parent vIRQ(%d) for chip %s\n",
+                                    PF1550_IRQ_ONKEY, pf1550_irq_chip.name);
+
+       ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
+                                      IRQF_ONESHOT | IRQF_SHARED |
+                                      IRQF_TRIGGER_FALLING, 0,
+                                      &pf1550_onkey_irq_chip,
+                                      &pf1550->irq_data_onkey);
+       if (ret)
+               return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
+                                    pf1550_onkey_irq_chip.name);
+
+       domain = regmap_irq_get_domain(pf1550->irq_data_onkey);
+
+       ret = devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, onkey, 1, NULL, 0, domain);
+       if (ret)
+               return ret;
+
+       /* Add battery charger */
+       irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_CHG);
+       if (irq < 0)
+               return dev_err_probe(pf1550->dev, irq,
+                                    "Failed to get parent vIRQ(%d) for chip %s\n",
+                                    PF1550_IRQ_CHG, pf1550_irq_chip.name);
+
+       ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
+                                      IRQF_ONESHOT | IRQF_SHARED |
+                                      IRQF_TRIGGER_FALLING, 0,
+                                      &pf1550_charger_irq_chip,
+                                      &pf1550->irq_data_charger);
+       if (ret)
+               return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
+                                    pf1550_charger_irq_chip.name);
+
+       domain = regmap_irq_get_domain(pf1550->irq_data_charger);
+
+       return devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, charger, 1, NULL, 0, domain);
+}
+
+static int pf1550_suspend(struct device *dev)
+{
+       struct pf1550_ddata *pf1550 = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev)) {
+               enable_irq_wake(pf1550->irq);
+               disable_irq(pf1550->irq);
+       }
+
+       return 0;
+}
+
+static int pf1550_resume(struct device *dev)
+{
+       struct pf1550_ddata *pf1550 = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev)) {
+               disable_irq_wake(pf1550->irq);
+               enable_irq(pf1550->irq);
+       }
+
+       return 0;
+}
+static DEFINE_SIMPLE_DEV_PM_OPS(pf1550_pm, pf1550_suspend, pf1550_resume);
+
+static const struct i2c_device_id pf1550_i2c_id[] = {
+       { "pf1550" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, pf1550_i2c_id);
+
+static const struct of_device_id pf1550_dt_match[] = {
+       { .compatible = "nxp,pf1550" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pf1550_dt_match);
+
+static struct i2c_driver pf1550_i2c_driver = {
+       .driver = {
+                  .name = "pf1550",
+                  .pm = pm_sleep_ptr(&pf1550_pm),
+                  .of_match_table = pf1550_dt_match,
+       },
+       .probe = pf1550_i2c_probe,
+       .id_table = pf1550_i2c_id,
+};
+module_i2c_driver(pf1550_i2c_driver);
+
+MODULE_DESCRIPTION("NXP PF1550 core driver");
+MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/pf1550.h b/include/linux/mfd/pf1550.h
new file mode 100644 (file)
index 0000000..7cb2340
--- /dev/null
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Declarations for the PF1550 PMIC
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Robin Gong <yibin.gong@freescale.com>
+ *
+ * Portions Copyright (c) 2025 Savoir-faire Linux Inc.
+ * Samuel Kayode <samuel.kayode@savoirfairelinux.com>
+ */
+
+#ifndef __LINUX_MFD_PF1550_H
+#define __LINUX_MFD_PF1550_H
+
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+enum pf1550_pmic_reg {
+       /* PMIC regulator part */
+       PF1550_PMIC_REG_DEVICE_ID               = 0x00,
+       PF1550_PMIC_REG_OTP_FLAVOR              = 0x01,
+       PF1550_PMIC_REG_SILICON_REV             = 0x02,
+
+       PF1550_PMIC_REG_INT_CATEGORY            = 0x06,
+       PF1550_PMIC_REG_SW_INT_STAT0            = 0x08,
+       PF1550_PMIC_REG_SW_INT_MASK0            = 0x09,
+       PF1550_PMIC_REG_SW_INT_SENSE0           = 0x0a,
+       PF1550_PMIC_REG_SW_INT_STAT1            = 0x0b,
+       PF1550_PMIC_REG_SW_INT_MASK1            = 0x0c,
+       PF1550_PMIC_REG_SW_INT_SENSE1           = 0x0d,
+       PF1550_PMIC_REG_SW_INT_STAT2            = 0x0e,
+       PF1550_PMIC_REG_SW_INT_MASK2            = 0x0f,
+       PF1550_PMIC_REG_SW_INT_SENSE2           = 0x10,
+       PF1550_PMIC_REG_LDO_INT_STAT0           = 0x18,
+       PF1550_PMIC_REG_LDO_INT_MASK0           = 0x19,
+       PF1550_PMIC_REG_LDO_INT_SENSE0          = 0x1a,
+       PF1550_PMIC_REG_TEMP_INT_STAT0          = 0x20,
+       PF1550_PMIC_REG_TEMP_INT_MASK0          = 0x21,
+       PF1550_PMIC_REG_TEMP_INT_SENSE0         = 0x22,
+       PF1550_PMIC_REG_ONKEY_INT_STAT0         = 0x24,
+       PF1550_PMIC_REG_ONKEY_INT_MASK0         = 0x25,
+       PF1550_PMIC_REG_ONKEY_INT_SENSE0        = 0x26,
+       PF1550_PMIC_REG_MISC_INT_STAT0          = 0x28,
+       PF1550_PMIC_REG_MISC_INT_MASK0          = 0x29,
+       PF1550_PMIC_REG_MISC_INT_SENSE0         = 0x2a,
+
+       PF1550_PMIC_REG_COINCELL_CONTROL        = 0x30,
+
+       PF1550_PMIC_REG_SW1_VOLT                = 0x32,
+       PF1550_PMIC_REG_SW1_STBY_VOLT           = 0x33,
+       PF1550_PMIC_REG_SW1_SLP_VOLT            = 0x34,
+       PF1550_PMIC_REG_SW1_CTRL                = 0x35,
+       PF1550_PMIC_REG_SW1_CTRL1               = 0x36,
+       PF1550_PMIC_REG_SW2_VOLT                = 0x38,
+       PF1550_PMIC_REG_SW2_STBY_VOLT           = 0x39,
+       PF1550_PMIC_REG_SW2_SLP_VOLT            = 0x3a,
+       PF1550_PMIC_REG_SW2_CTRL                = 0x3b,
+       PF1550_PMIC_REG_SW2_CTRL1               = 0x3c,
+       PF1550_PMIC_REG_SW3_VOLT                = 0x3e,
+       PF1550_PMIC_REG_SW3_STBY_VOLT           = 0x3f,
+       PF1550_PMIC_REG_SW3_SLP_VOLT            = 0x40,
+       PF1550_PMIC_REG_SW3_CTRL                = 0x41,
+       PF1550_PMIC_REG_SW3_CTRL1               = 0x42,
+       PF1550_PMIC_REG_VSNVS_CTRL              = 0x48,
+       PF1550_PMIC_REG_VREFDDR_CTRL            = 0x4a,
+       PF1550_PMIC_REG_LDO1_VOLT               = 0x4c,
+       PF1550_PMIC_REG_LDO1_CTRL               = 0x4d,
+       PF1550_PMIC_REG_LDO2_VOLT               = 0x4f,
+       PF1550_PMIC_REG_LDO2_CTRL               = 0x50,
+       PF1550_PMIC_REG_LDO3_VOLT               = 0x52,
+       PF1550_PMIC_REG_LDO3_CTRL               = 0x53,
+       PF1550_PMIC_REG_PWRCTRL0                = 0x58,
+       PF1550_PMIC_REG_PWRCTRL1                = 0x59,
+       PF1550_PMIC_REG_PWRCTRL2                = 0x5a,
+       PF1550_PMIC_REG_PWRCTRL3                = 0x5b,
+       PF1550_PMIC_REG_SW1_PWRDN_SEQ           = 0x5f,
+       PF1550_PMIC_REG_SW2_PWRDN_SEQ           = 0x60,
+       PF1550_PMIC_REG_SW3_PWRDN_SEQ           = 0x61,
+       PF1550_PMIC_REG_LDO1_PWRDN_SEQ          = 0x62,
+       PF1550_PMIC_REG_LDO2_PWRDN_SEQ          = 0x63,
+       PF1550_PMIC_REG_LDO3_PWRDN_SEQ          = 0x64,
+       PF1550_PMIC_REG_VREFDDR_PWRDN_SEQ       = 0x65,
+
+       PF1550_PMIC_REG_STATE_INFO              = 0x67,
+       PF1550_PMIC_REG_I2C_ADDR                = 0x68,
+       PF1550_PMIC_REG_IO_DRV0                 = 0x69,
+       PF1550_PMIC_REG_IO_DRV1                 = 0x6a,
+       PF1550_PMIC_REG_RC_16MHZ                = 0x6b,
+       PF1550_PMIC_REG_KEY                     = 0x6f,
+
+       /* Charger part */
+       PF1550_CHARG_REG_CHG_INT                = 0x80,
+       PF1550_CHARG_REG_CHG_INT_MASK           = 0x82,
+       PF1550_CHARG_REG_CHG_INT_OK             = 0x84,
+       PF1550_CHARG_REG_VBUS_SNS               = 0x86,
+       PF1550_CHARG_REG_CHG_SNS                = 0x87,
+       PF1550_CHARG_REG_BATT_SNS               = 0x88,
+       PF1550_CHARG_REG_CHG_OPER               = 0x89,
+       PF1550_CHARG_REG_CHG_TMR                = 0x8a,
+       PF1550_CHARG_REG_CHG_EOC_CNFG           = 0x8d,
+       PF1550_CHARG_REG_CHG_CURR_CNFG          = 0x8e,
+       PF1550_CHARG_REG_BATT_REG               = 0x8f,
+       PF1550_CHARG_REG_BATFET_CNFG            = 0x91,
+       PF1550_CHARG_REG_THM_REG_CNFG           = 0x92,
+       PF1550_CHARG_REG_VBUS_INLIM_CNFG        = 0x94,
+       PF1550_CHARG_REG_VBUS_LIN_DPM           = 0x95,
+       PF1550_CHARG_REG_USB_PHY_LDO_CNFG       = 0x96,
+       PF1550_CHARG_REG_DBNC_DELAY_TIME        = 0x98,
+       PF1550_CHARG_REG_CHG_INT_CNFG           = 0x99,
+       PF1550_CHARG_REG_THM_ADJ_SETTING        = 0x9a,
+       PF1550_CHARG_REG_VBUS2SYS_CNFG          = 0x9b,
+       PF1550_CHARG_REG_LED_PWM                = 0x9c,
+       PF1550_CHARG_REG_FAULT_BATFET_CNFG      = 0x9d,
+       PF1550_CHARG_REG_LED_CNFG               = 0x9e,
+       PF1550_CHARG_REG_CHGR_KEY2              = 0x9f,
+
+       PF1550_TEST_REG_FMRADDR                 = 0xc4,
+       PF1550_TEST_REG_FMRDATA                 = 0xc5,
+       PF1550_TEST_REG_KEY3                    = 0xdf,
+
+       PF1550_PMIC_REG_END                     = 0xff,
+};
+
+/* One-Time Programmable(OTP) memory */
+enum pf1550_otp_reg {
+       PF1550_OTP_SW1_SW2                      = 0x1e,
+       PF1550_OTP_SW2_SW3                      = 0x1f,
+};
+
+#define PF1550_DEVICE_ID               0x7c
+
+/* Keys for reading OTP */
+#define PF1550_OTP_PMIC_KEY            0x15
+#define PF1550_OTP_CHGR_KEY            0x50
+#define PF1550_OTP_TEST_KEY            0xab
+
+/* Supported charger modes */
+#define PF1550_CHG_BAT_OFF             1
+#define PF1550_CHG_BAT_ON              2
+
+#define PF1550_CHG_PRECHARGE           0
+#define PF1550_CHG_CONSTANT_CURRENT    1
+#define PF1550_CHG_CONSTANT_VOL                2
+#define PF1550_CHG_EOC                 3
+#define PF1550_CHG_DONE                        4
+#define PF1550_CHG_TIMER_FAULT         6
+#define PF1550_CHG_SUSPEND             7
+#define PF1550_CHG_OFF_INV             8
+#define PF1550_CHG_BAT_OVER            9
+#define PF1550_CHG_OFF_TEMP            10
+#define PF1550_CHG_LINEAR_ONLY         12
+#define PF1550_CHG_SNS_MASK            0xf
+#define PF1550_CHG_INT_MASK            0x51
+
+#define PF1550_BAT_NO_VBUS             0
+#define PF1550_BAT_LOW_THAN_PRECHARG   1
+#define PF1550_BAT_CHARG_FAIL          2
+#define PF1550_BAT_HIGH_THAN_PRECHARG  4
+#define PF1550_BAT_OVER_VOL            5
+#define PF1550_BAT_NO_DETECT           6
+#define PF1550_BAT_SNS_MASK            0x7
+
+#define PF1550_VBUS_UVLO               BIT(2)
+#define PF1550_VBUS_IN2SYS             BIT(3)
+#define PF1550_VBUS_OVLO               BIT(4)
+#define PF1550_VBUS_VALID              BIT(5)
+
+#define PF1550_CHARG_REG_BATT_REG_CHGCV_MASK           0x3f
+#define PF1550_CHARG_REG_BATT_REG_VMINSYS_SHIFT                6
+#define PF1550_CHARG_REG_BATT_REG_VMINSYS_MASK         GENMASK(7, 6)
+#define PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_SHIFT    2
+#define PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_MASK     GENMASK(3, 2)
+
+#define PF1550_ONKEY_RST_EN            BIT(7)
+
+/* DVS enable masks */
+#define OTP_SW1_DVS_ENB                BIT(1)
+#define OTP_SW2_DVS_ENB                BIT(3)
+
+/* Top level interrupt masks */
+#define IRQ_REGULATOR          (BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(6))
+#define IRQ_ONKEY              BIT(5)
+#define IRQ_CHG                        BIT(0)
+
+/* Regulator interrupt masks */
+#define PMIC_IRQ_SW1_LS                BIT(0)
+#define PMIC_IRQ_SW2_LS                BIT(1)
+#define PMIC_IRQ_SW3_LS                BIT(2)
+#define PMIC_IRQ_SW1_HS                BIT(0)
+#define PMIC_IRQ_SW2_HS                BIT(1)
+#define PMIC_IRQ_SW3_HS                BIT(2)
+#define PMIC_IRQ_LDO1_FAULT    BIT(0)
+#define PMIC_IRQ_LDO2_FAULT    BIT(1)
+#define PMIC_IRQ_LDO3_FAULT    BIT(2)
+#define PMIC_IRQ_TEMP_110      BIT(0)
+#define PMIC_IRQ_TEMP_125      BIT(1)
+
+/* Onkey interrupt masks */
+#define ONKEY_IRQ_PUSHI                BIT(0)
+#define ONKEY_IRQ_1SI          BIT(1)
+#define ONKEY_IRQ_2SI          BIT(2)
+#define ONKEY_IRQ_3SI          BIT(3)
+#define ONKEY_IRQ_4SI          BIT(4)
+#define ONKEY_IRQ_8SI          BIT(5)
+
+/* Charger interrupt masks */
+#define CHARG_IRQ_BAT2SOCI     BIT(1)
+#define CHARG_IRQ_BATI         BIT(2)
+#define CHARG_IRQ_CHGI         BIT(3)
+#define CHARG_IRQ_VBUSI                BIT(5)
+#define CHARG_IRQ_DPMI         BIT(6)
+#define CHARG_IRQ_THMI         BIT(7)
+
+enum pf1550_irq {
+       PF1550_IRQ_CHG,
+       PF1550_IRQ_REGULATOR,
+       PF1550_IRQ_ONKEY,
+};
+
+enum pf1550_pmic_irq {
+       PF1550_PMIC_IRQ_SW1_LS,
+       PF1550_PMIC_IRQ_SW2_LS,
+       PF1550_PMIC_IRQ_SW3_LS,
+       PF1550_PMIC_IRQ_SW1_HS,
+       PF1550_PMIC_IRQ_SW2_HS,
+       PF1550_PMIC_IRQ_SW3_HS,
+       PF1550_PMIC_IRQ_LDO1_FAULT,
+       PF1550_PMIC_IRQ_LDO2_FAULT,
+       PF1550_PMIC_IRQ_LDO3_FAULT,
+       PF1550_PMIC_IRQ_TEMP_110,
+       PF1550_PMIC_IRQ_TEMP_125,
+};
+
+enum pf1550_onkey_irq {
+       PF1550_ONKEY_IRQ_PUSHI,
+       PF1550_ONKEY_IRQ_1SI,
+       PF1550_ONKEY_IRQ_2SI,
+       PF1550_ONKEY_IRQ_3SI,
+       PF1550_ONKEY_IRQ_4SI,
+       PF1550_ONKEY_IRQ_8SI,
+};
+
+enum pf1550_charg_irq {
+       PF1550_CHARG_IRQ_BAT2SOCI,
+       PF1550_CHARG_IRQ_BATI,
+       PF1550_CHARG_IRQ_CHGI,
+       PF1550_CHARG_IRQ_VBUSI,
+       PF1550_CHARG_IRQ_THMI,
+};
+
+enum pf1550_regulators {
+       PF1550_SW1,
+       PF1550_SW2,
+       PF1550_SW3,
+       PF1550_VREFDDR,
+       PF1550_LDO1,
+       PF1550_LDO2,
+       PF1550_LDO3,
+};
+
+struct pf1550_ddata {
+       struct regmap_irq_chip_data *irq_data_regulator;
+       struct regmap_irq_chip_data *irq_data_charger;
+       struct regmap_irq_chip_data *irq_data_onkey;
+       struct regmap_irq_chip_data *irq_data;
+       struct regmap *regmap;
+       struct device *dev;
+       bool dvs1_enable;
+       bool dvs2_enable;
+       int irq;
+};
+
+#endif /* __LINUX_MFD_PF1550_H */