summaryrefslogtreecommitdiff
path: root/drivers/power/pmic
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/pmic')
-rw-r--r--drivers/power/pmic/Kconfig10
-rw-r--r--drivers/power/pmic/Makefile31
-rw-r--r--drivers/power/pmic/axp.c1
-rw-r--r--drivers/power/pmic/cpcap.c125
4 files changed, 152 insertions, 15 deletions
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index bbcbcee4c35..5a61cd45b8c 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -295,6 +295,16 @@ config DM_PMIC_SANDBOX
Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt
+config DM_PMIC_CPCAP
+ bool "Enable Driver Model for Motorola CPCAP"
+ help
+ The CPCAP is a Motorola/ST-Ericsson creation, a multifunctional IC
+ whose main purpose is power control. It was used in a wide variety of
+ Motorola products, both Tegra and OMAP based. The most notable devices
+ using this PMIC are the Motorola Droid 4, Atrix 4G, and Droid X2.
+ Unlike most PMICs, this one is not I2C based; it uses the SPI bus. The
+ core driver provides both read and write access to the device registers.
+
config PMIC_S5M8767
bool "Enable Driver Model for the Samsung S5M8767 PMIC"
---help---
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index bc138f563ff..2210b1a64ae 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -4,41 +4,42 @@
# Lukasz Majewski <l.majewski@samsung.com>
obj-$(CONFIG_$(PHASE_)DM_PMIC) += pmic-uclass.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_FAN53555) += fan53555.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_DA9063) += da9063.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_MAX77663) += max77663.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_FAN53555) += fan53555.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_DA9063) += da9063.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_MAX77663) += max77663.o
obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_BD71837) += bd71837.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_MP5416) += mp5416.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_PFUZE100) += pfuze100.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_PCA9450) += pca9450.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_BD71837) += bd71837.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_MP5416) += mp5416.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_PFUZE100) += pfuze100.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_PCA9450) += pca9450.o
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
obj-$(CONFIG_PMIC_AB8500) += ab8500.o
obj-$(CONFIG_PMIC_ACT8846) += act8846.o
obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
-obj-$(CONFIG_$(XPL_)PMIC_AXP) += axp.o
+obj-$(CONFIG_$(PHASE_)PMIC_AXP) += axp.o
obj-$(CONFIG_PMIC_MAX8997) += max8997.o
obj-$(CONFIG_PMIC_QCOM) += pmic_qcom.o
obj-$(CONFIG_$(PHASE_)PMIC_RK8XX) += rk8xx.o
-obj-$(CONFIG_$(XPL_)PMIC_RN5T567) += rn5t567.o
+obj-$(CONFIG_$(PHASE_)PMIC_RN5T567) += rn5t567.o
obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
obj-$(CONFIG_DM_PMIC_TPS65910) += pmic_tps65910_dm.o
-obj-$(CONFIG_$(XPL_)DM_PMIC_TPS80031) += tps80031.o
-obj-$(CONFIG_$(XPL_)PMIC_PALMAS) += palmas.o
-obj-$(CONFIG_$(XPL_)PMIC_LP873X) += lp873x.o
-obj-$(CONFIG_$(XPL_)PMIC_LP87565) += lp87565.o
+obj-$(CONFIG_$(PHASE_)DM_PMIC_TPS80031) += tps80031.o
+obj-$(CONFIG_$(PHASE_)PMIC_PALMAS) += palmas.o
+obj-$(CONFIG_$(PHASE_)PMIC_LP873X) += lp873x.o
+obj-$(CONFIG_$(PHASE_)PMIC_LP87565) += lp87565.o
obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
obj-$(CONFIG_PMIC_TPS65217) += pmic_tps65217.o
obj-$(CONFIG_PMIC_TPS65219) += tps65219.o
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
-ifeq ($(CONFIG_$(XPL_)POWER_LEGACY),y)
+ifeq ($(CONFIG_$(PHASE_)POWER_LEGACY),y)
obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
obj-$(CONFIG_POWER_PCA9450) += pmic_pca9450.o
obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
@@ -47,5 +48,5 @@ obj-$(CONFIG_POWER_HI6553) += pmic_hi6553.o
obj-$(CONFIG_POWER_MC34VR500) += pmic_mc34vr500.o
endif
-obj-$(CONFIG_$(XPL_)POWER_TPS62362) += pmic_tps62362.o
+obj-$(CONFIG_$(PHASE_)POWER_TPS62362) += pmic_tps62362.o
obj-$(CONFIG_SPL_POWER_TPS65910) += pmic_tps65910.o
diff --git a/drivers/power/pmic/axp.c b/drivers/power/pmic/axp.c
index 521a39dd566..c300fd2bbc2 100644
--- a/drivers/power/pmic/axp.c
+++ b/drivers/power/pmic/axp.c
@@ -51,6 +51,7 @@ static const struct pmic_child_info axp_pmic_child_info[] = {
{ "cldo", "axp_regulator" },
{ "dc", "axp_regulator" },
{ "dldo", "axp_regulator" },
+ { "drivevbus", "axp_drivevbus" },
{ "eldo", "axp_regulator" },
{ "fldo", "axp_regulator" },
{ "ldo", "axp_regulator" },
diff --git a/drivers/power/pmic/cpcap.c b/drivers/power/pmic/cpcap.c
new file mode 100644
index 00000000000..f2076afff43
--- /dev/null
+++ b/drivers/power/pmic/cpcap.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <dm.h>
+#include <dm/lists.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/cpcap.h>
+#include <spi.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "sw", .driver = CPCAP_SW_DRIVER },
+ { .prefix = "v", .driver = CPCAP_LDO_DRIVER },
+ { },
+};
+
+static int cpcap_write(struct udevice *dev, uint reg, const uint8_t *buff, int len)
+{
+ u8 buf[4];
+ u16 data = *(u16 *)buff;
+ int ret;
+
+ buf[0] = ((reg >> 8) & 0xff) | 0x80;
+ buf[1] = reg & 0xff;
+ buf[2] = data >> 8 & 0xff;
+ buf[3] = data & 0xff;
+
+ ret = dm_spi_xfer(dev, 32, buf, NULL, SPI_XFER_ONCE);
+
+ log_debug("%s: reg 0x%x, data 0x%04x, ret %d\n", __func__, reg, data, ret);
+
+ return ret;
+}
+
+static int cpcap_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ u8 buf[4];
+ int ret;
+
+ buf[0] = (reg >> 8) & 0xff;
+ buf[1] = reg & 0xff;
+ buf[2] = 0;
+ buf[3] = 0;
+
+ ret = dm_spi_xfer(dev, 32, buf, buf, SPI_XFER_ONCE);
+ *buff = (buf[2] << 8) | buf[3];
+
+ log_debug("%s: reg 0x%x, data 0x%04x, ret %d\n", __func__, reg, *buff, ret);
+ return ret;
+}
+
+static int cpcap_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ /* Regulator device node of PMIC */
+ regulators_node = dev_read_subnode(dev, "regulator");
+ if (!ofnode_valid(regulators_node)) {
+ log_err("%s regulator subnode not found!\n", dev->name);
+ return -ENXIO;
+ }
+
+ /* Actual regulators container */
+ regulators_node = ofnode_find_subnode(regulators_node, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ log_err("%s regulators subnode not found!\n", 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)
+ log_err("%s - no child found\n", dev->name);
+
+ return dm_scan_fdt_dev(dev);
+}
+
+static int cpcap_probe(struct udevice *dev)
+{
+ struct spi_slave *slave = dev_get_parent_priv(dev);
+ int ret;
+
+ ret = spi_claim_bus(slave);
+ if (ret) {
+ log_err("SPI bus allocation failed (%d)\n", ret);
+ return ret;
+ }
+
+ u16 id = pmic_reg_read(dev, CPCAP_REG_VERSC1);
+
+ u16 ven = (id >> 6) & 0x7;
+ u16 rev = ((id >> 3) & 0x7) | ((id << 3) & 0x38);
+
+ log_debug("%s: vendor %s rev: %i.%i (%x)\n", __func__,
+ ven == CPCAP_VENDOR_ST ? "ST" : "TI",
+ CPCAP_REVISION_MAJOR(rev), CPCAP_REVISION_MINOR(rev),
+ rev);
+ return 0;
+}
+
+static struct dm_pmic_ops cpcap_ops = {
+ .read = cpcap_read,
+ .write = cpcap_write,
+};
+
+static const struct udevice_id cpcap_ids[] = {
+ { .compatible = "motorola,cpcap" },
+ { .compatible = "st,6556002" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_cpcap) = {
+ .name = "cpcap_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = cpcap_ids,
+ .bind = cpcap_bind,
+ .probe = cpcap_probe,
+ .ops = &cpcap_ops,
+};