diff options
Diffstat (limited to 'drivers/power/pmic')
-rw-r--r-- | drivers/power/pmic/Kconfig | 8 | ||||
-rw-r--r-- | drivers/power/pmic/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/pmic/pmic-uclass.c | 11 | ||||
-rw-r--r-- | drivers/power/pmic/pmic_tps65910_dm.c | 98 |
4 files changed, 116 insertions, 2 deletions
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index e3f9e4dfc0..5d49c93f32 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -201,3 +201,11 @@ config POWER_MC34VR500 The MC34VR500 is used in conjunction with the FSL T1 and LS1 series SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed via an I2C interface. + +config DM_PMIC_TPS65910 + bool "Enable driver for Texas Instruments TPS65910 PMIC" + depends on DM_PMIC + ---help--- + The TPS65910 is a PMIC containing 3 buck DC-DC converters, one boost + DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO + pmic children. diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index f7bdfa5609..7d6c583d34 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o obj-$(CONFIG_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_$(SPL_)PMIC_PALMAS) += palmas.o obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o diff --git a/drivers/power/pmic/pmic-uclass.c b/drivers/power/pmic/pmic-uclass.c index 64964e4e96..9347b40688 100644 --- a/drivers/power/pmic/pmic-uclass.c +++ b/drivers/power/pmic/pmic-uclass.c @@ -26,6 +26,7 @@ int pmic_bind_children(struct udevice *pmic, ofnode parent, struct driver *drv; struct udevice *child; const char *node_name; + const char *reg_name; int bind_count = 0; ofnode node; int prefix_len; @@ -44,8 +45,14 @@ int pmic_bind_children(struct udevice *pmic, ofnode parent, debug(" - compatible prefix: '%s'\n", info->prefix); prefix_len = strlen(info->prefix); - if (strncmp(info->prefix, node_name, prefix_len)) - continue; + if (strncmp(info->prefix, node_name, prefix_len)) { + reg_name = ofnode_read_string(node, + "regulator-name"); + if (!reg_name) + continue; + if (strncmp(info->prefix, reg_name, prefix_len)) + continue; + } drv = lists_driver_lookup_name(info->driver); if (!drv) { diff --git a/drivers/power/pmic/pmic_tps65910_dm.c b/drivers/power/pmic/pmic_tps65910_dm.c new file mode 100644 index 0000000000..0127ce3aa0 --- /dev/null +++ b/drivers/power/pmic/pmic_tps65910_dm.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <i2c.h> +#include <power/pmic.h> +#include <power/regulator.h> +#include <power/tps65910_pmic.h> + +DECLARE_GLOBAL_DATA_PTR; + +static const struct pmic_child_info pmic_children_info[] = { + { .prefix = "ldo_", .driver = TPS65910_LDO_DRIVER }, + { .prefix = "buck_", .driver = TPS65910_BUCK_DRIVER }, + { .prefix = "boost_", .driver = TPS65910_BOOST_DRIVER }, + { }, +}; + +static int pmic_tps65910_reg_count(struct udevice *dev) +{ + return TPS65910_NUM_REGS; +} + +static int pmic_tps65910_write(struct udevice *dev, uint reg, const u8 *buffer, + int len) +{ + int ret; + + ret = dm_i2c_write(dev, reg, buffer, len); + if (ret) + error("%s write error on register %02x\n", dev->name, reg); + + return ret; +} + +static int pmic_tps65910_read(struct udevice *dev, uint reg, u8 *buffer, + int len) +{ + int ret; + + ret = dm_i2c_read(dev, reg, buffer, len); + if (ret) + error("%s read error on register %02x\n", dev->name, reg); + + return ret; +} + +static int pmic_tps65910_bind(struct udevice *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, pmic_children_info); + if (!children) + debug("%s has no children (regulators)\n", dev->name); + + return 0; +} + +static int pmic_tps65910_probe(struct udevice *dev) +{ + /* use I2C control interface instead of I2C smartreflex interface to + * access smartrefelex registers VDD1_OP_REG, VDD1_SR_REG, VDD2_OP_REG + * and VDD2_SR_REG + */ + return pmic_clrsetbits(dev, TPS65910_REG_DEVICE_CTRL, 0, + TPS65910_I2C_SEL_MASK); +} + +static struct dm_pmic_ops pmic_tps65910_ops = { + .reg_count = pmic_tps65910_reg_count, + .read = pmic_tps65910_read, + .write = pmic_tps65910_write, +}; + +static const struct udevice_id pmic_tps65910_match[] = { + { .compatible = "ti,tps65910" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(pmic_tps65910) = { + .name = "pmic_tps65910", + .id = UCLASS_PMIC, + .of_match = pmic_tps65910_match, + .bind = pmic_tps65910_bind, + .probe = pmic_tps65910_probe, + .ops = &pmic_tps65910_ops, +}; |