diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/power/pmic/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/power/pmic/Makefile | 1 | ||||
| -rw-r--r-- | drivers/power/pmic/cpcap.c | 90 |
3 files changed, 101 insertions, 0 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 4232cb4f5f9..2210b1a64ae 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -37,6 +37,7 @@ 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_$(PHASE_)POWER_LEGACY),y) obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o diff --git a/drivers/power/pmic/cpcap.c b/drivers/power/pmic/cpcap.c new file mode 100644 index 00000000000..4923255f0a7 --- /dev/null +++ b/drivers/power/pmic/cpcap.c @@ -0,0 +1,90 @@ +// 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 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_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, + .probe = cpcap_probe, + .ops = &cpcap_ops, +}; |
