Commit 151b223b9c4e309d65166558afdfa0ce3c3b3213

Authored by Simon Glass
1 parent 7fb57396e6

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 <sjg@chromium.org>
Acked-by: Przemyslaw Marczak <p.marczak@samsung.com>

Showing 4 changed files with 160 additions and 0 deletions Side-by-side Diff

drivers/power/pmic/Kconfig
... ... @@ -41,4 +41,13 @@
41 41 - set by i2c emul driver's probe() (defaults in header)
42 42  
43 43 Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt
  44 +
  45 +config PMIC_TPS65090
  46 + bool "Enable driver for Texas Instruments TPS65090 PMIC"
  47 + depends on DM_PMIC
  48 + ---help---
  49 + The TPS65090 is a PMIC containing several LDOs, DC to DC convertors,
  50 + FETs and a battery charger. This driver provides register access
  51 + only, and you can enable the regulator/charger drivers separately if
  52 + required.
drivers/power/pmic/Makefile
... ... @@ -8,6 +8,7 @@
8 8 obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
9 9 obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
10 10 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
  11 +obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
11 12 obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
12 13 obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
13 14 obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
drivers/power/pmic/tps65090.c
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc
  3 + * Written by Simon Glass <sjg@chromium.org>
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +#include <common.h>
  9 +#include <dm.h>
  10 +#include <errno.h>
  11 +#include <fdtdec.h>
  12 +#include <i2c.h>
  13 +#include <power/pmic.h>
  14 +#include <power/tps65090.h>
  15 +
  16 +DECLARE_GLOBAL_DATA_PTR;
  17 +
  18 +static const struct pmic_child_info pmic_children_info[] = {
  19 + { .prefix = "fet", .driver = TPS65090_FET_DRIVER },
  20 + { },
  21 +};
  22 +
  23 +static int tps65090_reg_count(struct udevice *dev)
  24 +{
  25 + return TPS65090_NUM_REGS;
  26 +}
  27 +
  28 +static int tps65090_write(struct udevice *dev, uint reg, const uint8_t *buff,
  29 + int len)
  30 +{
  31 + if (dm_i2c_write(dev, reg, buff, len)) {
  32 + error("write error to device: %p register: %#x!", dev, reg);
  33 + return -EIO;
  34 + }
  35 +
  36 + return 0;
  37 +}
  38 +
  39 +static int tps65090_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
  40 +{
  41 + int ret;
  42 +
  43 + ret = dm_i2c_read(dev, reg, buff, len);
  44 + if (ret) {
  45 + error("read error %d from device: %p register: %#x!", ret, dev,
  46 + reg);
  47 + return -EIO;
  48 + }
  49 +
  50 + return 0;
  51 +}
  52 +
  53 +static int tps65090_bind(struct udevice *dev)
  54 +{
  55 + int regulators_node;
  56 + const void *blob = gd->fdt_blob;
  57 + int children;
  58 +
  59 + regulators_node = fdt_subnode_offset(blob, dev->of_offset,
  60 + "regulators");
  61 + if (regulators_node <= 0) {
  62 + debug("%s: %s regulators subnode not found!", __func__,
  63 + dev->name);
  64 + return -ENXIO;
  65 + }
  66 +
  67 + debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
  68 +
  69 + children = pmic_bind_children(dev, regulators_node, pmic_children_info);
  70 + if (!children)
  71 + debug("%s: %s - no child found\n", __func__, dev->name);
  72 +
  73 + /* Always return success for this device */
  74 + return 0;
  75 +}
  76 +
  77 +static struct dm_pmic_ops tps65090_ops = {
  78 + .reg_count = tps65090_reg_count,
  79 + .read = tps65090_read,
  80 + .write = tps65090_write,
  81 +};
  82 +
  83 +static const struct udevice_id tps65090_ids[] = {
  84 + { .compatible = "ti,tps65090" },
  85 + { }
  86 +};
  87 +
  88 +U_BOOT_DRIVER(pmic_tps65090) = {
  89 + .name = "tps65090 pmic",
  90 + .id = UCLASS_PMIC,
  91 + .of_match = tps65090_ids,
  92 + .bind = tps65090_bind,
  93 + .ops = &tps65090_ops,
  94 +};
include/power/tps65090.h
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc
  3 + * Written by Simon Glass <sjg@chromium.org>
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +#ifndef __TPS65090_PMIC_H_
  9 +#define __TPS65090_PMIC_H_
  10 +
  11 +/* I2C device address for TPS65090 PMU */
  12 +#define TPS65090_I2C_ADDR 0x48
  13 +
  14 +/* TPS65090 register addresses */
  15 +enum {
  16 + REG_IRQ1 = 0,
  17 + REG_CG_CTRL0 = 4,
  18 + REG_CG_STATUS1 = 0xa,
  19 + REG_FET_BASE = 0xe, /* Not a real register, FETs count from here */
  20 + REG_FET1_CTRL,
  21 + REG_FET2_CTRL,
  22 + REG_FET3_CTRL,
  23 + REG_FET4_CTRL,
  24 + REG_FET5_CTRL,
  25 + REG_FET6_CTRL,
  26 + REG_FET7_CTRL,
  27 + TPS65090_NUM_REGS,
  28 +};
  29 +
  30 +enum {
  31 + IRQ1_VBATG = 1 << 3,
  32 + CG_CTRL0_ENC_MASK = 0x01,
  33 +
  34 + MAX_FET_NUM = 7,
  35 + MAX_CTRL_READ_TRIES = 5,
  36 +
  37 + /* TPS65090 FET_CTRL register values */
  38 + FET_CTRL_TOFET = 1 << 7, /* Timeout, startup, overload */
  39 + FET_CTRL_PGFET = 1 << 4, /* Power good for FET status */
  40 + FET_CTRL_WAIT = 3 << 2, /* Overcurrent timeout max */
  41 + FET_CTRL_ADENFET = 1 << 1, /* Enable output auto discharge */
  42 + FET_CTRL_ENFET = 1 << 0, /* Enable FET */
  43 +};
  44 +
  45 +enum {
  46 + /* Status register fields */
  47 + TPS65090_ST1_OTC = 1 << 0,
  48 + TPS65090_ST1_OCC = 1 << 1,
  49 + TPS65090_ST1_STATE_SHIFT = 4,
  50 + TPS65090_ST1_STATE_MASK = 0xf << TPS65090_ST1_STATE_SHIFT,
  51 +};
  52 +
  53 +/* Drivers name */
  54 +#define TPS65090_FET_DRIVER "tps65090_fet"
  55 +
  56 +#endif /* __TPS65090_PMIC_H_ */