From: Joy Zou <joy....@nxp.com>

Support NXP pmic pf5300

Signed-off-by: Joy Zou <joy....@nxp.com>
Reviewed-by: Ye Li <ye...@nxp.com>
Signed-off-by: Peng Fan <peng....@nxp.com>
---
 drivers/power/pmic/Kconfig  |  15 ++++
 drivers/power/pmic/Makefile |   1 +
 drivers/power/pmic/pf5300.c | 168 ++++++++++++++++++++++++++++++++++++
 include/power/pf5300.h      | 100 +++++++++++++++++++++
 4 files changed, 284 insertions(+)
 create mode 100644 drivers/power/pmic/pf5300.c
 create mode 100644 include/power/pf5300.h

diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 1a5ef279ed6..420c4099937 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -186,6 +186,21 @@ config SPL_DM_PMIC_PF0900
          This config enables implementation of driver-model pmic uclass 
features
          for PMIC PF0900 in SPL. The driver implements read/write operations.
 
+config DM_PMIC_PF5300
+       bool "Enable Driver Model for PMIC PF5300"
+       depends on DM_I2C
+       help
+         This config enables implementation of driver-model pmic uclass 
features
+         for PMIC PF5300. The driver implements read/write operations.
+
+config SPL_DM_PMIC_PF5300
+       bool "Enable Driver Model for PMIC PF5300 in SPL"
+       depends on SPL_DM_PMIC
+       depends on SPL_DM_I2C
+       help
+         This config enables implementation of driver-model pmic uclass 
features
+         for PMIC PF5300 in SPL. The driver implements read/write operations.
+
 config DM_PMIC_PFUZE100
        bool "Enable Driver Model for PMIC PFUZE100"
        ---help---
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 0041ab59406..74ace69daf5 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)DM_PMIC_MP5416) += mp5416.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_PCA9450) += pca9450.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_PF0900) += pf0900.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_PF5300) += pf5300.o
 obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
 obj-$(CONFIG_PMIC_AB8500) += ab8500.o
diff --git a/drivers/power/pmic/pf5300.c b/drivers/power/pmic/pf5300.c
new file mode 100644
index 00000000000..b66fa756109
--- /dev/null
+++ b/drivers/power/pmic/pf5300.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2023 NXP
+ */
+
+#include <asm/global_data.h>
+#include <asm-generic/gpio.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <i2c.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/err.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/pf5300.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+       /* sw */
+       { .prefix = "S", .driver = PF5300_REGULATOR_DRIVER},
+       { },
+};
+
+static int pf5300_reg_count(struct udevice *dev)
+{
+       return PF5300_MAX_REGISTER;
+}
+
+static u8 crc8_j1850(u8 *data, u8 length)
+{
+       u8 t_crc;
+       u8 i, j;
+
+       t_crc = 0xFF;
+       for (i = 0; i < length; i++) {
+               t_crc ^= data[i];
+               for (j = 0; j < 8; j++) {
+                       if ((t_crc & 0x80) != 0) {
+                               t_crc <<= 1;
+                               t_crc ^= 0x1D;
+                       } else {
+                               t_crc <<= 1;
+                       }
+               }
+       }
+       return t_crc;
+}
+
+static int pf5300_read(struct udevice *dev, uint reg, u8 *buff,
+                      int len)
+{
+       u8 crcBuf[3];
+       u8 data[2], crc;
+       int ret;
+       struct pf5300_priv *priv = dev_get_priv(dev);
+
+       if (reg < PF5300_MAX_REGISTER) {
+               ret = dm_i2c_read(dev, reg, data,
+                                 priv->crc_en ? 2U : 1U);
+               if (ret)
+                       return ret;
+               buff[0] = data[0];
+               if (priv->crc_en) {
+                       /* Get CRC */
+                       crcBuf[0] = priv->addr << 1U | 0x1U;
+                       crcBuf[1] = reg;
+                       crcBuf[2] = data[0];
+                       crc = crc8_j1850(crcBuf, 3U);
+                       if (crc != data[1])
+                               return -EINVAL;
+               }
+       } else {
+               return -EINVAL;
+       }
+       return ret;
+}
+
+static int pf5300_write(struct udevice *dev, uint reg, const u8 *buff,
+                       int len)
+{
+       u8 crcBuf[3];
+       u8 data[2];
+       int ret;
+       struct pf5300_priv *priv = dev_get_priv(dev);
+
+       if (reg < PF5300_MAX_REGISTER) {
+               data[0] = buff[0];
+               if (priv->crc_en) {
+                       /* Get CRC */
+                       crcBuf[0] = priv->addr << 1U;
+                       crcBuf[1] = reg;
+                       crcBuf[2] = data[0];
+                       data[1] = crc8_j1850(crcBuf, 3U);
+               }
+               /* Write data */
+               ret = dm_i2c_write(dev, reg, data,
+                                  priv->crc_en ? 2U : 1U);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+static int pf5300_bind(struct udevice *dev)
+{
+       int children;
+       ofnode regulators_node;
+
+       regulators_node = dev_read_subnode(dev, "regulators");
+       if (!ofnode_valid(regulators_node)) {
+               debug("%s: %s regulators subnode not found!", __func__,
+                     dev->name);
+               return -ENXIO;
+       }
+
+       debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+       children = pmic_bind_children(dev, regulators_node,
+                                     pmic_children_info);
+       if (!children)
+               debug("%s: %s - no child found\n", __func__, dev->name);
+
+       /* Always return success for this device */
+       return 0;
+}
+
+static int pf5300_probe(struct udevice *dev)
+{
+       struct pf5300_priv *priv = dev_get_priv(dev);
+       unsigned int reg;
+       int ret = 0;
+
+       ret = ofnode_read_u32(dev_ofnode(dev), "reg", &reg);
+       if (ret)
+               return ret;
+       priv->addr = reg;
+
+       if (ofnode_read_bool(dev_ofnode(dev), "i2c-crc-enable"))
+               priv->crc_en = true;
+
+       return ret;
+}
+
+static struct dm_pmic_ops pf5300_ops = {
+       .reg_count = pf5300_reg_count,
+       .read = pf5300_read,
+       .write = pf5300_write,
+};
+
+static const struct udevice_id pf5300_ids[] = {
+       { .compatible = "nxp,pf5300", .data = PF5300_TYPE_PF5300, },
+       { .compatible = "nxp,pf5301", .data = PF5300_TYPE_PF5301, },
+       { .compatible = "nxp,pf5302", .data = PF5300_TYPE_PF5302, },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_pf5300) = {
+       .name = "pf5300 pmic",
+       .id = UCLASS_PMIC,
+       .of_match = pf5300_ids,
+       .bind = pf5300_bind,
+       .probe = pf5300_probe,
+       .ops = &pf5300_ops,
+       .priv_auto = sizeof(struct pf5300_priv),
+};
diff --git a/include/power/pf5300.h b/include/power/pf5300.h
new file mode 100644
index 00000000000..0d2fa548a70
--- /dev/null
+++ b/include/power/pf5300.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2023 NXP
+ */
+
+#ifndef PF5300_H_
+#define PF5300_H_
+
+#define PF5300_REGULATOR_DRIVER "pf5300_regulator"
+
+struct pf5300_priv {
+       u8 addr;
+       bool crc_en;
+};
+
+enum pf5300_chip_type {
+       PF5300_TYPE_PF5300 = 0,
+       PF5300_TYPE_PF5301 = 1,
+       PF5300_TYPE_PF5302 = 2,
+       PF5300_TYPE_AMOUNT,
+};
+
+enum {
+       PF5300_SW1 = 0,
+       PF5300_REGULATOR_CNT,
+};
+
+enum {
+       PF5300_DVS_LEVEL_RUN = 0,
+       PF5300_DVS_LEVEL_STANDBY,
+       PF5300_DVS_LEVEL_MAX,
+};
+
+#define PF5300_SW1_VOLTAGE_NUM 0x100
+
+enum {
+       PF5300_REG_DEV_ID           = 0x00,
+       PF5300_REG_REV_ID           = 0x01,
+       PF5300_REG_EMREV            = 0x02,
+       PF5300_REG_PROG_ID          = 0x03,
+       PF5300_REG_CONFIG1          = 0x04,
+       PF5300_REG_INT_STATUS1      = 0x05,
+       PF5300_REG_INT_SENSE1       = 0x06,
+       PF5300_REG_INT_STATUS2      = 0x07,
+       PF5300_REG_INT_SENSE2       = 0x08,
+       PF5300_REG_BIST_STAT1       = 0x09,
+       PF5300_REG_BIST_CTRL        = 0x0A,
+       PF5300_REG_STATE            = 0x0B,
+       PF5300_REG_STATE_CTRL       = 0x0C,
+       PF5300_REG_SW1_VOLT         = 0x0D,
+       PF5300_REG_SW1_STBY_VOLT    = 0x0E,
+       PF5300_REG_SW1_CTRL1        = 0x0F,
+       PF5300_REG_SW1_CTRL2        = 0x10,
+       PF5300_REG_CLK_CTRL         = 0x11,
+       PF5300_REG_SEQ_CTRL1        = 0x12,
+       PF5300_REG_SEQ_CTRL2        = 0x13,
+       PF5300_REG_RANDOM_CHK       = 0x14,
+       PF5300_REG_RANDOM_GEN       = 0x15,
+       PF5300_REG_WD_CTRL          = 0x16,
+       PF5300_REG_WD_SEED          = 0x17,
+       PF5300_REG_WD_ANSWER        = 0x18,
+       PF5300_REG_FLT_CNT1         = 0x19,
+       PF5300_REG_FLT_CNT2         = 0x1A,
+       PF5300_MAX_REGISTER,
+};
+
+/* PF5300 SW1_CTRL1 */
+#define SW_MODE_OFF                    0x00
+#define SW_MODE_PWM                    0x0c
+
+#define SW1_MODE_MASK                  0x0C
+#define SW1_STBY_MODE_MASK             0x30
+
+#define SW1_RAMP_MASK                  0x03
+
+/* PF5300 SW1_VOLT/SW1_STBY_VOLT MASK */
+#define SW1_VOLT_MASK                  0xFF
+#define SW1_STBY_VOLT_MASK             0xFF
+
+/* PF5300_REG_INT_STATUS1 bits */
+#define IRQ_SDWN                       0x80
+#define IRQ_BG_ERR                     0x40
+#define IRQ_CRC                                0x20
+#define IRQ_SW1_DVS_DONE               0x10
+#define IRQ_SW1_ILIM                   0x08
+#define IRQ_VMON_UV                    0x04
+#define IRQ_VMON_OV                    0x02
+#define IRQ_VIN_OVLO                   0x01
+
+/* PF5300_REG_INT_STATUS2 bits */
+#define IRQ_PGOOD_STUCK_AT0            0x80
+#define IRQ_PGOOD_STUCK_AT1            0x40
+#define IRQ_DVS_ERR                    0x20
+#define IRQ_FSYNC                      0x10
+#define IRQ_THERM_155                  0x08
+#define IRQ_THERM_140                  0x04
+#define IRQ_THERM_125                  0x02
+#define IRQ_THERM_110                  0x01
+
+#endif
-- 
2.35.3

Reply via email to