From: Raymond Mao <[email protected]>

Spacemit's PMIC is used by Spacemit K1 SoC. It contains voltage
regulators, GPIOs and Watchdog.

Signed-off-by: Raymond Mao <[email protected]>
---
 drivers/power/pmic/Kconfig            |  17 +++
 drivers/power/pmic/Makefile           |   1 +
 drivers/power/pmic/pmic_spacemit_p1.c |  95 +++++++++++++++
 include/power/spacemit_p1.h           | 162 ++++++++++++++++++++++++++
 4 files changed, 275 insertions(+)
 create mode 100644 drivers/power/pmic/pmic_spacemit_p1.c
 create mode 100644 include/power/spacemit_p1.h

diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index b1a5b1c2a1f..19a0c4a77dd 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -433,6 +433,23 @@ config PMIC_RAA215300
          support and several voltage regulators. For now, this driver simply
          allows register access and will bind the sysreset driver
          (CONFIG_SYSRESET_RAA215300) if it is enabled.
+
+config PMIC_SPACEMIT_P1
+       bool "Enable driver for Spacemit P1 power management chip"
+       depends on DM_PMIC
+       help
+         The P1 PMIC integrates multiple functions including
+         voltage regulators, a watchdog timer, GPIO interfaces, and a
+         real-time clock.
+
+config SPL_PMIC_SPACEMIT_P1
+       bool "Enable driver for Spacemit P1 power management chip in SPL"
+       depends on SPL_DM_PMIC
+       help
+         The P1 PMIC integrates multiple functions including
+         voltage regulators, a watchdog timer, GPIO interfaces, and a
+         real-time clock.
+
 endif
 
 config PMIC_TPS65217
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 6bebffb05a6..dfe60223f00 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_PMIC_TPS65941) += tps65941.o
 obj-$(CONFIG_PMIC_RAA215300) += raa215300.o
 obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
 obj-$(CONFIG_$(PHASE_)DM_PMIC_CPCAP) += cpcap.o
+obj-$(CONFIG_$(PHASE_)PMIC_SPACEMIT_P1) += pmic_spacemit_p1.o
 
 ifeq ($(CONFIG_$(PHASE_)POWER_LEGACY),y)
 obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
diff --git a/drivers/power/pmic/pmic_spacemit_p1.c 
b/drivers/power/pmic/pmic_spacemit_p1.c
new file mode 100644
index 00000000000..88c8a375de1
--- /dev/null
+++ b/drivers/power/pmic/pmic_spacemit_p1.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025-2026 RISCStar Ltd.
+ */
+
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/spacemit_p1.h>
+
+static int pmic_p1_reg_count(struct udevice *dev)
+{
+       return P1_MAX_REGS;
+}
+
+static int pmic_p1_write(struct udevice *dev, uint reg, const u8 *buffer,
+                        int len)
+{
+       int ret;
+
+       ret = dm_i2c_write(dev, reg, buffer, len);
+       if (ret)
+               pr_err("%s write error on register %02x\n", dev->name, reg);
+
+       return ret;
+}
+
+static int pmic_p1_read(struct udevice *dev, uint reg, u8 *buffer,
+                       int len)
+{
+       int ret;
+
+       ret = dm_i2c_read(dev, reg, buffer, len);
+       if (ret)
+               pr_err("%s read error on register %02x\n", dev->name, reg);
+
+       return ret;
+}
+
+static const struct pmic_child_info p1_children_info[] = {
+       { .prefix = "buck",             .driver = P1_BUCK_DRIVER },
+       { .prefix = "aldo",             .driver = P1_LDO_DRIVER },
+       { .prefix = "dldo",             .driver = P1_LDO_DRIVER },
+       { },
+};
+
+static int pmic_p1_bind(struct udevice *dev)
+{
+       const struct pmic_child_info *p1_children_info =
+                       (struct pmic_child_info *)dev_get_driver_data(dev);
+       ofnode regulators_node;
+       int children;
+
+       regulators_node = dev_read_subnode(dev, "regulators");
+       if (!ofnode_valid(regulators_node)) {
+               debug("%s regulators subnode not found\n", dev->name);
+               return -EINVAL;
+       }
+
+       children = pmic_bind_children(dev, regulators_node,
+                                     p1_children_info);
+       if (!children)
+               debug("%s has no children (regulators)\n", dev->name);
+
+       return 0;
+}
+
+static int pmic_p1_probe(struct udevice *dev)
+{
+       return 0;
+}
+
+static struct dm_pmic_ops pmic_p1_ops = {
+       .reg_count      = pmic_p1_reg_count,
+       .read           = pmic_p1_read,
+       .write          = pmic_p1_write,
+};
+
+static const struct udevice_id pmic_p1_match[] = {
+       {
+               .compatible = "spacemit,p1",
+               .data = (ulong)&p1_children_info,
+       }, {
+               /* sentinel */
+       }
+};
+
+U_BOOT_DRIVER(pmic_p1) = {
+       .name           = "pmic_p1",
+       .id             = UCLASS_PMIC,
+       .of_match       = pmic_p1_match,
+       .bind           = pmic_p1_bind,
+       .probe          = pmic_p1_probe,
+       .ops            = &pmic_p1_ops,
+       //.priv_auto    = sizeof(struct p1_pdata),
+};
diff --git a/include/power/spacemit_p1.h b/include/power/spacemit_p1.h
new file mode 100644
index 00000000000..848bb469305
--- /dev/null
+++ b/include/power/spacemit_p1.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2025-2026 RISCStar Ltd.
+ */
+
+#ifndef __SPACEMIT_P1_H_
+#define __SPACEMIT_P1_H_
+
+#define P1_MAX_REGS                    0xA8
+
+#define P1_REG_ID                      0x0
+
+#define P1_ID                          0x2
+
+#define P1_REG_BUCK1_CTRL              0x47
+#define P1_REG_BUCK2_CTRL              0x4a
+#define P1_REG_BUCK3_CTRL              0x4d
+#define P1_REG_BUCK4_CTRL              0x50
+#define P1_REG_BUCK5_CTRL              0x53
+#define P1_REG_BUCK6_CTRL              0x56
+
+#define P1_REG_BUCK1_VSEL              0x48
+#define P1_REG_BUCK2_VSEL              0x4b
+#define P1_REG_BUCK3_VSEL              0x4e
+#define P1_REG_BUCK4_VSEL              0x51
+#define P1_REG_BUCK5_VSEL              0x54
+#define P1_REG_BUCK6_VSEL              0x57
+
+#define P1_REG_BUCK1_SVSEL             0x49
+#define P1_REG_BUCK2_SVSEL             0x4c
+#define P1_REG_BUCK3_SVSEL             0x4f
+#define P1_REG_BUCK4_SVSEL             0x52
+#define P1_REG_BUCK5_SVSEL             0x55
+#define P1_REG_BUCK6_SVSEL             0x58
+
+#define P1_BUCK_CTRL(x)                        (0x47 + ((x) - 1) * 3)
+#define P1_BUCK_VSEL(x)                        (0x48 + ((x) - 1) * 3)
+#define P1_BUCK_SVSEL(x)               (0x49 + ((x) - 1) * 3)
+
+#define BUCK_VSEL_MASK                 0xff
+#define BUCK_EN_MASK                   0x1
+#define BUCK_SVSEL_MASK                        0xff
+
+#define P1_REG_ALDO1_CTRL              0x5b
+#define P1_REG_ALDO2_CTRL              0x5e
+#define P1_REG_ALDO3_CTRL              0x61
+#define P1_REG_ALDO4_CTRL              0x64
+
+#define P1_REG_ALDO1_VOLT              0x5c
+#define P1_REG_ALDO2_VOLT              0x5f
+#define P1_REG_ALDO3_VOLT              0x62
+#define P1_REG_ALDO4_VOLT              0x65
+
+#define P1_REG_ALDO1_SVOLT             0x5d
+#define P1_REG_ALDO2_SVOLT             0x60
+#define P1_REG_ALDO3_SVOLT             0x63
+#define P1_REG_ALDO4_SVOLT             0x66
+
+#define P1_ALDO_CTRL(x)                        (0x5b + ((x) - 1) * 3)
+#define P1_ALDO_VOLT(x)                        (0x5c + ((x) - 1) * 3)
+#define P1_ALDO_SVOLT(x)               (0x5d + ((x) - 1) * 3)
+
+#define ALDO_SVSEL_MASK                        0x7f
+#define ALDO_EN_MASK                   0x1
+#define ALDO_VSEL_MASK                 0x7f
+
+#define P1_REG_DLDO1_CTRL              0x67
+#define P1_REG_DLDO2_CTRL              0x6a
+#define P1_REG_DLDO3_CTRL              0x6d
+#define P1_REG_DLDO4_CTRL              0x70
+#define P1_REG_DLDO5_CTRL              0x73
+#define P1_REG_DLDO6_CTRL              0x76
+#define P1_REG_DLDO7_CTRL              0x79
+
+#define P1_REG_DLDO1_VOLT              0x68
+#define P1_REG_DLDO2_VOLT              0x6b
+#define P1_REG_DLDO3_VOLT              0x6e
+#define P1_REG_DLDO4_VOLT              0x71
+#define P1_REG_DLDO5_VOLT              0x74
+#define P1_REG_DLDO6_VOLT              0x77
+#define P1_REG_DLDO7_VOLT              0x7a
+
+#define P1_REG_DLDO1_SVOLT             0x69
+#define P1_REG_DLDO2_SVOLT             0x6c
+#define P1_REG_DLDO3_SVOLT             0x6f
+#define P1_REG_DLDO4_SVOLT             0x72
+#define P1_REG_DLDO5_SVOLT             0x75
+#define P1_REG_DLDO6_SVOLT             0x78
+#define P1_REG_DLDO7_SVOLT             0x7b
+
+#define P1_DLDO_CTRL(x)                        (0x67 + ((x) - 1) * 3)
+#define P1_DLDO_VOLT(x)                        (0x68 + ((x) - 1) * 3)
+#define P1_DLDO_SVOLT(x)               (0x69 + ((x) - 1) * 3)
+
+#define DLDO_SVSEL_MASK                        0x7f
+#define DLDO_EN_MASK                   0x1
+#define DLDO_VSEL_MASK                 0x7f
+
+#define P1_REG_SWITCH_CTRL             0x59
+#define P1_SWTICH_EN_MASK              0x1
+
+#define P1_REG_SWITCH_PWRKEY_EVENT_CTRL        0x97
+#define P1_SWITCH_PWRKEY_EVENT_EN_MSK  0xf
+
+#define P1_REG_SWITCH_PWRKEY_INIT_CTRL 0x9e
+#define P1_SWITCH_PWRKEY_INT_EN_MSK    0xf
+
+/* Watchdog Timer Registers */
+#define P1_WDT_CTRL                    0x44
+#define P1_PWR_CTRL0                   0x7C
+#define P1_PWR_CTRL2                   0x7E
+#define P1_PWR_CTRL2_MSK               0xff
+
+/* Watchdog Timer Control Bits */
+#define P1_WDT_CLEAR_STATUS            0x1
+#define P1_SW_RST                      0x2
+#define P1_WDT_RESET_ENABLE            0x80
+#define P1_WDT_ENABLE                  0x8
+#define P1_WDT_TIMEOUT_1S              0x0
+#define P1_WDT_TIMEOUT_4S              0x1
+#define P1_WDT_TIMEOUT_8S              0x2
+#define P1_WDT_TIMEOUT_16S             0x3
+
+#define P1_RTC_TICK_CTRL               0x1d
+#define P1_RTC_TICK_CTRL_MSK           0x7f
+
+#define P1_RTC_TICK_EVENT              0x92
+#define P1_RTC_TICK_EVENT_MSK          0x3f
+
+#define P1_RTC_TICK_IRQ                        0x99
+#define P1_RTC_TICK_IRQ_MSK            0x3f
+
+#define P1_REG_ALIVE                   0xab
+#define P1_ALIVE_MSK                   0x7
+#define SYS_REBOOT_FLAG_BIT            0x2
+
+/* SWITCH ID */
+enum {
+       P1_ID_SWITCH1,
+       P1_ID_SWITCH1_PWRKEY_EVENT,
+       P1_ID_SWITCH1_PWRKEY_INT,
+       P1_ID_SWITCH_RTC_TICK_CTRL,
+       P1_ID_SWITCH_RTC_TICK_EVENT,
+       P1_ID_SWITCH_RTC_TCK_IRQ,
+       P1_ID_SWITCH_POWER_DOWN,
+       P1_ID_SWITCH_CHARGING_FLAG,
+};
+
+/* POWERKEY events */
+enum {
+       PWRKEY_RISING_EVENT = 1,
+       PWRKEY_FAILING_EVENT = 2,
+       PWRKEY_SHORT_PRESS_EVENT = 4,
+       PWRKEY_LONG_PRESS_EVENT = 8,
+};
+
+#define P1_BUCK_DRIVER                 "p1_buck"
+#define P1_LDO_DRIVER                  "p1_ldo"
+#define P1_SWITCH_DRIVER               "p1_switch"
+#define P1_WDT_DRIVER                  "p1_wdt"
+
+#endif /* __SPACEMIT_P1_H_ */
-- 
2.25.1

Reply via email to