From cc456bd7df06225819258dec9d4a5047e8da4952 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 3 Aug 2015 08:19:23 -0600 Subject: dm: cros_ec: Convert the I2C tunnel code to use driver model The Chrome OS EC supports tunnelling through to an I2C bus on the EC. This currently uses a copy of the I2C command code and a special 'crosec' sub-command. With driver model we can define an I2C bus which tunnels through to the EC, and use the normal 'i2c' command to access it. This simplifies the code and removes some duplication. Add an I2C driver which tunnels through to the EC. Adjust the EC code to support binding child devices so that it can be set up. Adjust the existing I2C xfer function to fit driver model better. For now the old code remains to allow things to still work. It will be removed in a later patch once the new flow is fully enabled. Signed-off-by: Simon Glass --- drivers/power/pmic/pmic_tps65090_ec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/power/pmic') diff --git a/drivers/power/pmic/pmic_tps65090_ec.c b/drivers/power/pmic/pmic_tps65090_ec.c index ac0d44fec8..f79a8782c9 100644 --- a/drivers/power/pmic/pmic_tps65090_ec.c +++ b/drivers/power/pmic/pmic_tps65090_ec.c @@ -56,8 +56,8 @@ enum { */ static int tps65090_read(u32 reg, u8 *val) { - return cros_ec_i2c_xfer(config.dev, TPS65090_ADDR, reg, 1, - val, 1, true); + return cros_ec_i2c_xfer_old(config.dev, TPS65090_ADDR, reg, 1, + val, 1, true); } /** @@ -69,8 +69,8 @@ static int tps65090_read(u32 reg, u8 *val) */ static int tps65090_write(u32 reg, u8 val) { - return cros_ec_i2c_xfer(config.dev, TPS65090_ADDR, reg, 1, - &val, 1, false); + return cros_ec_i2c_xfer_old(config.dev, TPS65090_ADDR, reg, 1, + &val, 1, false); } /** -- cgit From 151b223b9c4e309d65166558afdfa0ce3c3b3213 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 2 Jul 2015 18:15:58 -0600 Subject: dm: power: Add a new driver for the TPS65090 PMIC The existing TPS65090 driver does not support driver model. Add a new one that does. This can be used as a base for a regulator driver also. It uses the standard device tree binding. Signed-off-by: Simon Glass Acked-by: Przemyslaw Marczak --- drivers/power/pmic/Kconfig | 9 +++++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/tps65090.c | 94 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 drivers/power/pmic/tps65090.c (limited to 'drivers/power/pmic') diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 164f42143f..fd8af8161e 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -41,3 +41,12 @@ config DM_PMIC_SANDBOX - set by i2c emul driver's probe() (defaults in header) Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt + +config PMIC_TPS65090 + bool "Enable driver for Texas Instruments TPS65090 PMIC" + depends on DM_PMIC + ---help--- + The TPS65090 is a PMIC containing several LDOs, DC to DC convertors, + FETs and a battery charger. This driver provides register access + only, and you can enable the regulator/charger drivers separately if + required. diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 4ad6df36c2..43b706b688 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DM_PMIC) += pmic-uclass.o obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o +obj-$(CONFIG_PMIC_TPS65090) += tps65090.o obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o diff --git a/drivers/power/pmic/tps65090.c b/drivers/power/pmic/tps65090.c new file mode 100644 index 0000000000..4797f327fa --- /dev/null +++ b/drivers/power/pmic/tps65090.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015 Google, Inc + * Written by Simon Glass + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static const struct pmic_child_info pmic_children_info[] = { + { .prefix = "fet", .driver = TPS65090_FET_DRIVER }, + { }, +}; + +static int tps65090_reg_count(struct udevice *dev) +{ + return TPS65090_NUM_REGS; +} + +static int tps65090_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) +{ + if (dm_i2c_write(dev, reg, buff, len)) { + error("write error to device: %p register: %#x!", dev, reg); + return -EIO; + } + + return 0; +} + +static int tps65090_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + int ret; + + ret = dm_i2c_read(dev, reg, buff, len); + if (ret) { + error("read error %d from device: %p register: %#x!", ret, dev, + reg); + return -EIO; + } + + return 0; +} + +static int tps65090_bind(struct udevice *dev) +{ + int regulators_node; + const void *blob = gd->fdt_blob; + int children; + + regulators_node = fdt_subnode_offset(blob, dev->of_offset, + "regulators"); + if (regulators_node <= 0) { + 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 struct dm_pmic_ops tps65090_ops = { + .reg_count = tps65090_reg_count, + .read = tps65090_read, + .write = tps65090_write, +}; + +static const struct udevice_id tps65090_ids[] = { + { .compatible = "ti,tps65090" }, + { } +}; + +U_BOOT_DRIVER(pmic_tps65090) = { + .name = "tps65090 pmic", + .id = UCLASS_PMIC, + .of_match = tps65090_ids, + .bind = tps65090_bind, + .ops = &tps65090_ops, +}; -- cgit From d308c0136d8a530d4846ab08ce02e6d40614d7e7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 2 Jul 2015 18:16:00 -0600 Subject: dm: power: Add support for the S5M8767 PMIC This PMIC is used with SoCs which need a combination of BUCKs and LDOs. The driver supports probing and basic register access. It supports the standard device tree binding and supports driver model. A regulator driver can be provided also. Signed-off-by: Simon Glass Acked-by: Przemyslaw Marczak --- drivers/power/pmic/Kconfig | 9 +++++ drivers/power/pmic/Makefile | 2 + drivers/power/pmic/s5m8767.c | 95 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 drivers/power/pmic/s5m8767.c (limited to 'drivers/power/pmic') diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index fd8af8161e..7b98189ad8 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -42,6 +42,15 @@ config DM_PMIC_SANDBOX Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt +config PMIC_S5M8767 + bool "Enable Driver Model for the Samsung S5M8767 PMIC" + depends on DM_PMIC + ---help--- + The S5M8767 PMIC provides a large array of LDOs and BUCKs for use + as a SoC power controller. It also provides 32KHz clock outputs. This + driver provides basic register access and sets up the attached + regulators if regulator support is enabled. + config PMIC_TPS65090 bool "Enable driver for Texas Instruments TPS65090 PMIC" depends on DM_PMIC diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 43b706b688..322c2c6cac 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -9,6 +9,8 @@ obj-$(CONFIG_DM_PMIC) += pmic-uclass.o obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o obj-$(CONFIG_PMIC_TPS65090) += tps65090.o +obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o + obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o diff --git a/drivers/power/pmic/s5m8767.c b/drivers/power/pmic/s5m8767.c new file mode 100644 index 0000000000..075fe7e2f1 --- /dev/null +++ b/drivers/power/pmic/s5m8767.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static const struct pmic_child_info pmic_children_info[] = { + { .prefix = "LDO", .driver = S5M8767_LDO_DRIVER }, + { .prefix = "BUCK", .driver = S5M8767_BUCK_DRIVER }, + { }, +}; + +static int s5m8767_reg_count(struct udevice *dev) +{ + return S5M8767_NUM_OF_REGS; +} + +static int s5m8767_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) +{ + if (dm_i2c_write(dev, reg, buff, len)) { + error("write error to device: %p register: %#x!", dev, reg); + return -EIO; + } + + return 0; +} + +static int s5m8767_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + if (dm_i2c_read(dev, reg, buff, len)) { + error("read error from device: %p register: %#x!", dev, reg); + return -EIO; + } + + return 0; +} + +int s5m8767_enable_32khz_cp(struct udevice *dev) +{ + return pmic_clrsetbits(dev, S5M8767_EN32KHZ_CP, 0, 1 << 1); +} + +static int s5m8767_bind(struct udevice *dev) +{ + int node; + const void *blob = gd->fdt_blob; + int children; + + node = fdt_subnode_offset(blob, dev->of_offset, "regulators"); + if (node <= 0) { + 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, 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 struct dm_pmic_ops s5m8767_ops = { + .reg_count = s5m8767_reg_count, + .read = s5m8767_read, + .write = s5m8767_write, +}; + +static const struct udevice_id s5m8767_ids[] = { + { .compatible = "samsung,s5m8767-pmic" }, + { } +}; + +U_BOOT_DRIVER(pmic_s5m8767) = { + .name = "s5m8767_pmic", + .id = UCLASS_PMIC, + .of_match = s5m8767_ids, + .bind = s5m8767_bind, + .ops = &s5m8767_ops, +}; -- cgit From b5ffa4fdcb656b8995d6800f9c10dad76a44d38b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 2 Jul 2015 18:16:02 -0600 Subject: dm: pmic: max77686: Correct a few nits The driver name should not have a space in it. Also the regulator names should match the case of the device tree. Fix these problems. Signed-off-by: Simon Glass Acked-by: Przemyslaw Marczak --- drivers/power/pmic/max77686.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/power/pmic') diff --git a/drivers/power/pmic/max77686.c b/drivers/power/pmic/max77686.c index 3523b4a2de..dc5a54a6a3 100644 --- a/drivers/power/pmic/max77686.c +++ b/drivers/power/pmic/max77686.c @@ -17,8 +17,8 @@ DECLARE_GLOBAL_DATA_PTR; static const struct pmic_child_info pmic_children_info[] = { - { .prefix = "ldo", .driver = MAX77686_LDO_DRIVER }, - { .prefix = "buck", .driver = MAX77686_BUCK_DRIVER }, + { .prefix = "LDO", .driver = MAX77686_LDO_DRIVER }, + { .prefix = "BUCK", .driver = MAX77686_BUCK_DRIVER }, { }, }; @@ -84,7 +84,7 @@ static const struct udevice_id max77686_ids[] = { }; U_BOOT_DRIVER(pmic_max77686) = { - .name = "max77686 pmic", + .name = "max77686_pmic", .id = UCLASS_PMIC, .of_match = max77686_ids, .bind = max77686_bind, -- cgit From cd367d89979c0476e2fcbca445a49008b372872b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 2 Jul 2015 18:16:03 -0600 Subject: dm: pmic: Correct the pmic_reg_write() implementation This should write the register, not read it. Fix this bug. Signed-off-by: Simon Glass Acked-by: Przemyslaw Marczak --- drivers/power/pmic/pmic-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/power/pmic') diff --git a/drivers/power/pmic/pmic-uclass.c b/drivers/power/pmic/pmic-uclass.c index d99cb9aada..49709f3084 100644 --- a/drivers/power/pmic/pmic-uclass.c +++ b/drivers/power/pmic/pmic-uclass.c @@ -142,7 +142,7 @@ int pmic_reg_write(struct udevice *dev, uint reg, uint value) u8 byte = value; debug("%s: reg=%x, value=%x\n", __func__, reg, value); - return pmic_read(dev, reg, &byte, 1); + return pmic_write(dev, reg, &byte, 1); } int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set) -- cgit From 05bccbcd761e7170e236c982915781b143051abb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 3 Aug 2015 08:19:32 -0600 Subject: power: Remove old TPS65090 drivers Remove the old drivers (both the normal one and the cros_ec one) now that we have new drivers that use driver model. Signed-off-by: Simon Glass --- drivers/power/pmic/Makefile | 2 - drivers/power/pmic/pmic_tps65090.c | 310 ---------------------------------- drivers/power/pmic/pmic_tps65090_ec.c | 218 ------------------------ 3 files changed, 530 deletions(-) delete mode 100644 drivers/power/pmic/pmic_tps65090.c delete mode 100644 drivers/power/pmic/pmic_tps65090_ec.c (limited to 'drivers/power/pmic') diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 322c2c6cac..6ef149aee7 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -18,8 +18,6 @@ obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o -obj-$(CONFIG_POWER_TPS65090_I2C) += pmic_tps65090.o -obj-$(CONFIG_POWER_TPS65090_EC) += pmic_tps65090_ec.o obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o diff --git a/drivers/power/pmic/pmic_tps65090.c b/drivers/power/pmic/pmic_tps65090.c deleted file mode 100644 index 337903acec..0000000000 --- a/drivers/power/pmic/pmic_tps65090.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 2012 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#define TPS65090_NAME "TPS65090_PMIC" - -/* TPS65090 register addresses */ -enum { - REG_IRQ1 = 0, - REG_CG_CTRL0 = 4, - REG_CG_STATUS1 = 0xa, - REG_FET1_CTRL = 0x0f, - REG_FET2_CTRL, - REG_FET3_CTRL, - REG_FET4_CTRL, - REG_FET5_CTRL, - REG_FET6_CTRL, - REG_FET7_CTRL, - TPS65090_NUM_REGS, -}; - -enum { - IRQ1_VBATG = 1 << 3, - CG_CTRL0_ENC_MASK = 0x01, - - MAX_FET_NUM = 7, - MAX_CTRL_READ_TRIES = 5, - - /* TPS65090 FET_CTRL register values */ - FET_CTRL_TOFET = 1 << 7, /* Timeout, startup, overload */ - FET_CTRL_PGFET = 1 << 4, /* Power good for FET status */ - FET_CTRL_WAIT = 3 << 2, /* Overcurrent timeout max */ - FET_CTRL_ADENFET = 1 << 1, /* Enable output auto discharge */ - FET_CTRL_ENFET = 1 << 0, /* Enable FET */ -}; - -/** - * Checks for a valid FET number - * - * @param fet_id FET number to check - * @return 0 if ok, -EINVAL if FET value is out of range - */ -static int tps65090_check_fet(unsigned int fet_id) -{ - if (fet_id == 0 || fet_id > MAX_FET_NUM) { - debug("parameter fet_id is out of range, %u not in 1 ~ %u\n", - fet_id, MAX_FET_NUM); - return -EINVAL; - } - - return 0; -} - -/** - * Set the power state for a FET - * - * @param pmic pmic structure for the tps65090 - * @param fet_id Fet number to set (1..MAX_FET_NUM) - * @param set 1 to power on FET, 0 to power off - * @return -EIO if we got a comms error, -EAGAIN if the FET failed to - * change state. If all is ok, returns 0. - */ -static int tps65090_fet_set(struct pmic *pmic, int fet_id, bool set) -{ - int retry; - u32 reg, value; - - value = FET_CTRL_ADENFET | FET_CTRL_WAIT; - if (set) - value |= FET_CTRL_ENFET; - - if (pmic_reg_write(pmic, REG_FET1_CTRL + fet_id - 1, value)) - return -EIO; - - /* Try reading until we get a result */ - for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) { - if (pmic_reg_read(pmic, REG_FET1_CTRL + fet_id - 1, ®)) - return -EIO; - - /* Check that the fet went into the expected state */ - if (!!(reg & FET_CTRL_PGFET) == set) - return 0; - - /* If we got a timeout, there is no point in waiting longer */ - if (reg & FET_CTRL_TOFET) - break; - - mdelay(1); - } - - debug("FET %d: Power good should have set to %d but reg=%#02x\n", - fet_id, set, reg); - return -EAGAIN; -} - -int tps65090_fet_enable(unsigned int fet_id) -{ - struct pmic *pmic; - ulong start; - int loops; - int ret; - - ret = tps65090_check_fet(fet_id); - if (ret) - return ret; - - pmic = pmic_get(TPS65090_NAME); - if (!pmic) - return -EACCES; - - start = get_timer(0); - for (loops = 0;; loops++) { - ret = tps65090_fet_set(pmic, fet_id, true); - if (!ret) - break; - - if (get_timer(start) > 100) - break; - - /* Turn it off and try again until we time out */ - tps65090_fet_set(pmic, fet_id, false); - } - - if (ret) - debug("%s: FET%d failed to power on: time=%lums, loops=%d\n", - __func__, fet_id, get_timer(start), loops); - else if (loops) - debug("%s: FET%d powered on after %lums, loops=%d\n", - __func__, fet_id, get_timer(start), loops); - - /* - * Unfortunately, there are some conditions where the power - * good bit will be 0, but the fet still comes up. One such - * case occurs with the lcd backlight. We'll just return 0 here - * and assume that the fet will eventually come up. - */ - if (ret == -EAGAIN) - ret = 0; - - return ret; -} - -int tps65090_fet_disable(unsigned int fet_id) -{ - struct pmic *pmic; - int ret; - - ret = tps65090_check_fet(fet_id); - if (ret) - return ret; - - pmic = pmic_get(TPS65090_NAME); - if (!pmic) - return -EACCES; - ret = tps65090_fet_set(pmic, fet_id, false); - - return ret; -} - -int tps65090_fet_is_enabled(unsigned int fet_id) -{ - struct pmic *pmic; - u32 reg; - int ret; - - ret = tps65090_check_fet(fet_id); - if (ret) - return ret; - - pmic = pmic_get(TPS65090_NAME); - if (!pmic) - return -ENODEV; - ret = pmic_reg_read(pmic, REG_FET1_CTRL + fet_id - 1, ®); - if (ret) { - debug("fail to read FET%u_CTRL register over I2C", fet_id); - return -EIO; - } - - return reg & FET_CTRL_ENFET; -} - -int tps65090_get_charging(void) -{ - struct pmic *pmic; - u32 val; - int ret; - - pmic = pmic_get(TPS65090_NAME); - if (!pmic) - return -EACCES; - - ret = pmic_reg_read(pmic, REG_CG_CTRL0, &val); - if (ret) - return ret; - - return !!(val & CG_CTRL0_ENC_MASK); -} - -static int tps65090_charger_state(struct pmic *pmic, int state, - int current) -{ - u32 val; - int ret; - - ret = pmic_reg_read(pmic, REG_CG_CTRL0, &val); - if (!ret) { - if (state == PMIC_CHARGER_ENABLE) - val |= CG_CTRL0_ENC_MASK; - else - val &= ~CG_CTRL0_ENC_MASK; - ret = pmic_reg_write(pmic, REG_CG_CTRL0, val); - } - if (ret) { - debug("%s: Failed to read/write register\n", __func__); - return ret; - } - - return 0; -} - -int tps65090_get_status(void) -{ - struct pmic *pmic; - u32 val; - int ret; - - pmic = pmic_get(TPS65090_NAME); - if (!pmic) - return -EACCES; - - ret = pmic_reg_read(pmic, REG_CG_STATUS1, &val); - if (ret) - return ret; - - return val; -} - -static int tps65090_charger_bat_present(struct pmic *pmic) -{ - u32 val; - int ret; - - ret = pmic_reg_read(pmic, REG_IRQ1, &val); - if (ret) - return ret; - - return !!(val & IRQ1_VBATG); -} - -static struct power_chrg power_chrg_pmic_ops = { - .chrg_bat_present = tps65090_charger_bat_present, - .chrg_state = tps65090_charger_state, -}; - -int tps65090_init(void) -{ - struct pmic *p; - int bus; - int addr; - const void *blob = gd->fdt_blob; - int node, parent; - - node = fdtdec_next_compatible(blob, 0, COMPAT_TI_TPS65090); - if (node < 0) { - debug("PMIC: No node for PMIC Chip in device tree\n"); - debug("node = %d\n", node); - return -ENODEV; - } - - parent = fdt_parent_offset(blob, node); - if (parent < 0) { - debug("%s: Cannot find node parent\n", __func__); - return -EINVAL; - } - - bus = i2c_get_bus_num_fdt(parent); - if (bus < 0) { - debug("%s: Cannot find I2C bus\n", __func__); - return -ENOENT; - } - addr = fdtdec_get_int(blob, node, "reg", TPS65090_I2C_ADDR); - p = pmic_alloc(); - if (!p) { - printf("%s: POWER allocation error!\n", __func__); - return -ENOMEM; - } - - p->name = TPS65090_NAME; - p->bus = bus; - p->interface = PMIC_I2C; - p->number_of_regs = TPS65090_NUM_REGS; - p->hw.i2c.addr = addr; - p->hw.i2c.tx_num = 1; - p->chrg = &power_chrg_pmic_ops; - - puts("TPS65090 PMIC init\n"); - - return 0; -} diff --git a/drivers/power/pmic/pmic_tps65090_ec.c b/drivers/power/pmic/pmic_tps65090_ec.c deleted file mode 100644 index f79a8782c9..0000000000 --- a/drivers/power/pmic/pmic_tps65090_ec.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2013 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#define TPS65090_ADDR 0x48 - -static struct tps65090 { - struct cros_ec_dev *dev; /* The CROS_EC device */ -} config; - -/* TPS65090 register addresses */ -enum { - REG_IRQ1 = 0, - REG_CG_CTRL0 = 4, - REG_CG_STATUS1 = 0xa, - REG_FET1_CTRL = 0x0f, - REG_FET2_CTRL, - REG_FET3_CTRL, - REG_FET4_CTRL, - REG_FET5_CTRL, - REG_FET6_CTRL, - REG_FET7_CTRL, - TPS65090_NUM_REGS, -}; - -enum { - IRQ1_VBATG = 1 << 3, - CG_CTRL0_ENC_MASK = 0x01, - - MAX_FET_NUM = 7, - MAX_CTRL_READ_TRIES = 5, - - /* TPS65090 FET_CTRL register values */ - FET_CTRL_TOFET = 1 << 7, /* Timeout, startup, overload */ - FET_CTRL_PGFET = 1 << 4, /* Power good for FET status */ - FET_CTRL_WAIT = 3 << 2, /* Overcurrent timeout max */ - FET_CTRL_ADENFET = 1 << 1, /* Enable output auto discharge */ - FET_CTRL_ENFET = 1 << 0, /* Enable FET */ -}; - -/** - * tps65090_read - read a byte from tps6090 - * - * @param reg The register address to read from. - * @param val We'll return value value read here. - * @return 0 if ok; error if EC returns failure. - */ -static int tps65090_read(u32 reg, u8 *val) -{ - return cros_ec_i2c_xfer_old(config.dev, TPS65090_ADDR, reg, 1, - val, 1, true); -} - -/** - * tps65090_write - write a byte to tps6090 - * - * @param reg The register address to write to. - * @param val The value to write. - * @return 0 if ok; error if EC returns failure. - */ -static int tps65090_write(u32 reg, u8 val) -{ - return cros_ec_i2c_xfer_old(config.dev, TPS65090_ADDR, reg, 1, - &val, 1, false); -} - -/** - * Checks for a valid FET number - * - * @param fet_id FET number to check - * @return 0 if ok, -EINVAL if FET value is out of range - */ -static int tps65090_check_fet(unsigned int fet_id) -{ - if (fet_id == 0 || fet_id > MAX_FET_NUM) { - debug("parameter fet_id is out of range, %u not in 1 ~ %u\n", - fet_id, MAX_FET_NUM); - return -EINVAL; - } - - return 0; -} - -/** - * Set the power state for a FET - * - * @param fet_id Fet number to set (1..MAX_FET_NUM) - * @param set 1 to power on FET, 0 to power off - * @return -EIO if we got a comms error, -EAGAIN if the FET failed to - * change state. If all is ok, returns 0. - */ -static int tps65090_fet_set(int fet_id, bool set) -{ - int retry; - u8 reg, value; - - value = FET_CTRL_ADENFET | FET_CTRL_WAIT; - if (set) - value |= FET_CTRL_ENFET; - - if (tps65090_write(REG_FET1_CTRL + fet_id - 1, value)) - return -EIO; - - /* Try reading until we get a result */ - for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) { - if (tps65090_read(REG_FET1_CTRL + fet_id - 1, ®)) - return -EIO; - - /* Check that the fet went into the expected state */ - if (!!(reg & FET_CTRL_PGFET) == set) - return 0; - - /* If we got a timeout, there is no point in waiting longer */ - if (reg & FET_CTRL_TOFET) - break; - - mdelay(1); - } - - debug("FET %d: Power good should have set to %d but reg=%#02x\n", - fet_id, set, reg); - return -EAGAIN; -} - -int tps65090_fet_enable(unsigned int fet_id) -{ - ulong start; - int loops; - int ret; - - ret = tps65090_check_fet(fet_id); - if (ret) - return ret; - - start = get_timer(0); - for (loops = 0;; loops++) { - ret = tps65090_fet_set(fet_id, true); - if (!ret) - break; - - if (get_timer(start) > 100) - break; - - /* Turn it off and try again until we time out */ - tps65090_fet_set(fet_id, false); - } - - if (ret) { - debug("%s: FET%d failed to power on: time=%lums, loops=%d\n", - __func__, fet_id, get_timer(start), loops); - } else if (loops) { - debug("%s: FET%d powered on after %lums, loops=%d\n", - __func__, fet_id, get_timer(start), loops); - } - /* - * Unfortunately, there are some conditions where the power - * good bit will be 0, but the fet still comes up. One such - * case occurs with the lcd backlight. We'll just return 0 here - * and assume that the fet will eventually come up. - */ - if (ret == -EAGAIN) - ret = 0; - - return ret; -} - -int tps65090_fet_disable(unsigned int fet_id) -{ - int ret; - - ret = tps65090_check_fet(fet_id); - if (ret) - return ret; - - ret = tps65090_fet_set(fet_id, false); - - return ret; -} - -int tps65090_fet_is_enabled(unsigned int fet_id) -{ - u8 reg = 0; - int ret; - - ret = tps65090_check_fet(fet_id); - if (ret) - return ret; - ret = tps65090_read(REG_FET1_CTRL + fet_id - 1, ®); - if (ret) { - debug("fail to read FET%u_CTRL register over I2C", fet_id); - return -EIO; - } - - return reg & FET_CTRL_ENFET; -} - -int tps65090_init(void) -{ - puts("TPS65090 PMIC EC init\n"); - - config.dev = board_get_cros_ec_dev(); - if (!config.dev) { - debug("%s: no cros_ec device: cannot init tps65090\n", - __func__); - return -ENODEV; - } - - return 0; -} -- cgit