uboot/drivers/power/pmic/pmic_tps65090.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012 The Chromium OS Authors.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <errno.h>
   9#include <fdtdec.h>
  10#include <i2c.h>
  11#include <power/pmic.h>
  12#include <power/tps65090_pmic.h>
  13
  14DECLARE_GLOBAL_DATA_PTR;
  15
  16#define TPS65090_NAME "TPS65090_PMIC"
  17
  18/* TPS65090 register addresses */
  19enum {
  20        REG_IRQ1 = 0,
  21        REG_CG_CTRL0 = 4,
  22        REG_CG_STATUS1 = 0xa,
  23        REG_FET1_CTRL = 0x0f,
  24        REG_FET2_CTRL,
  25        REG_FET3_CTRL,
  26        REG_FET4_CTRL,
  27        REG_FET5_CTRL,
  28        REG_FET6_CTRL,
  29        REG_FET7_CTRL,
  30        TPS65090_NUM_REGS,
  31};
  32
  33enum {
  34        IRQ1_VBATG = 1 << 3,
  35        CG_CTRL0_ENC_MASK       = 0x01,
  36
  37        MAX_FET_NUM     = 7,
  38        MAX_CTRL_READ_TRIES = 5,
  39
  40        /* TPS65090 FET_CTRL register values */
  41        FET_CTRL_TOFET          = 1 << 7,  /* Timeout, startup, overload */
  42        FET_CTRL_PGFET          = 1 << 4,  /* Power good for FET status */
  43        FET_CTRL_WAIT           = 3 << 2,  /* Overcurrent timeout max */
  44        FET_CTRL_ADENFET        = 1 << 1,  /* Enable output auto discharge */
  45        FET_CTRL_ENFET          = 1 << 0,  /* Enable FET */
  46};
  47
  48/**
  49 * Checks for a valid FET number
  50 *
  51 * @param fet_id        FET number to check
  52 * @return 0 if ok, -EINVAL if FET value is out of range
  53 */
  54static int tps65090_check_fet(unsigned int fet_id)
  55{
  56        if (fet_id == 0 || fet_id > MAX_FET_NUM) {
  57                debug("parameter fet_id is out of range, %u not in 1 ~ %u\n",
  58                      fet_id, MAX_FET_NUM);
  59                return -EINVAL;
  60        }
  61
  62        return 0;
  63}
  64
  65/**
  66 * Set the power state for a FET
  67 *
  68 * @param pmic          pmic structure for the tps65090
  69 * @param fet_id        Fet number to set (1..MAX_FET_NUM)
  70 * @param set           1 to power on FET, 0 to power off
  71 * @return -EIO if we got a comms error, -EAGAIN if the FET failed to
  72 * change state. If all is ok, returns 0.
  73 */
  74static int tps65090_fet_set(struct pmic *pmic, int fet_id, bool set)
  75{
  76        int retry;
  77        u32 reg, value;
  78
  79        value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
  80        if (set)
  81                value |= FET_CTRL_ENFET;
  82
  83        if (pmic_reg_write(pmic, REG_FET1_CTRL + fet_id - 1, value))
  84                return -EIO;
  85
  86        /* Try reading until we get a result */
  87        for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
  88                if (pmic_reg_read(pmic, REG_FET1_CTRL + fet_id - 1, &reg))
  89                        return -EIO;
  90
  91                /* Check that the fet went into the expected state */
  92                if (!!(reg & FET_CTRL_PGFET) == set)
  93                        return 0;
  94
  95                /* If we got a timeout, there is no point in waiting longer */
  96                if (reg & FET_CTRL_TOFET)
  97                        break;
  98
  99                mdelay(1);
 100        }
 101
 102        debug("FET %d: Power good should have set to %d but reg=%#02x\n",
 103              fet_id, set, reg);
 104        return -EAGAIN;
 105}
 106
 107int tps65090_fet_enable(unsigned int fet_id)
 108{
 109        struct pmic *pmic;
 110        ulong start;
 111        int loops;
 112        int ret;
 113
 114        ret = tps65090_check_fet(fet_id);
 115        if (ret)
 116                return ret;
 117
 118        pmic = pmic_get(TPS65090_NAME);
 119        if (!pmic)
 120                return -EACCES;
 121
 122        start = get_timer(0);
 123        for (loops = 0;; loops++) {
 124                ret = tps65090_fet_set(pmic, fet_id, true);
 125                if (!ret)
 126                        break;
 127
 128                if (get_timer(start) > 100)
 129                        break;
 130
 131                /* Turn it off and try again until we time out */
 132                tps65090_fet_set(pmic, fet_id, false);
 133        }
 134
 135        if (ret)
 136                debug("%s: FET%d failed to power on: time=%lums, loops=%d\n",
 137                      __func__, fet_id, get_timer(start), loops);
 138        else if (loops)
 139                debug("%s: FET%d powered on after %lums, loops=%d\n",
 140                      __func__, fet_id, get_timer(start), loops);
 141
 142        /*
 143         * Unfortunately, there are some conditions where the power
 144         * good bit will be 0, but the fet still comes up. One such
 145         * case occurs with the lcd backlight. We'll just return 0 here
 146         * and assume that the fet will eventually come up.
 147         */
 148        if (ret == -EAGAIN)
 149                ret = 0;
 150
 151        return ret;
 152}
 153
 154int tps65090_fet_disable(unsigned int fet_id)
 155{
 156        struct pmic *pmic;
 157        int ret;
 158
 159        ret = tps65090_check_fet(fet_id);
 160        if (ret)
 161                return ret;
 162
 163        pmic = pmic_get(TPS65090_NAME);
 164        if (!pmic)
 165                return -EACCES;
 166        ret = tps65090_fet_set(pmic, fet_id, false);
 167
 168        return ret;
 169}
 170
 171int tps65090_fet_is_enabled(unsigned int fet_id)
 172{
 173        struct pmic *pmic;
 174        u32 reg;
 175        int ret;
 176
 177        ret = tps65090_check_fet(fet_id);
 178        if (ret)
 179                return ret;
 180
 181        pmic = pmic_get(TPS65090_NAME);
 182        if (!pmic)
 183                return -ENODEV;
 184        ret = pmic_reg_read(pmic, REG_FET1_CTRL + fet_id - 1, &reg);
 185        if (ret) {
 186                debug("fail to read FET%u_CTRL register over I2C", fet_id);
 187                return -EIO;
 188        }
 189
 190        return reg & FET_CTRL_ENFET;
 191}
 192
 193int tps65090_get_charging(void)
 194{
 195        struct pmic *pmic;
 196        u32 val;
 197        int ret;
 198
 199        pmic = pmic_get(TPS65090_NAME);
 200        if (!pmic)
 201                return -EACCES;
 202
 203        ret = pmic_reg_read(pmic, REG_CG_CTRL0, &val);
 204        if (ret)
 205                return ret;
 206
 207        return !!(val & CG_CTRL0_ENC_MASK);
 208}
 209
 210static int tps65090_charger_state(struct pmic *pmic, int state,
 211                                  int current)
 212{
 213        u32 val;
 214        int ret;
 215
 216        ret = pmic_reg_read(pmic, REG_CG_CTRL0, &val);
 217        if (!ret) {
 218                if (state == PMIC_CHARGER_ENABLE)
 219                        val |= CG_CTRL0_ENC_MASK;
 220                else
 221                        val &= ~CG_CTRL0_ENC_MASK;
 222                ret = pmic_reg_write(pmic, REG_CG_CTRL0, val);
 223        }
 224        if (ret) {
 225                debug("%s: Failed to read/write register\n", __func__);
 226                return ret;
 227        }
 228
 229        return 0;
 230}
 231
 232int tps65090_get_status(void)
 233{
 234        struct pmic *pmic;
 235        u32 val;
 236        int ret;
 237
 238        pmic = pmic_get(TPS65090_NAME);
 239        if (!pmic)
 240                return -EACCES;
 241
 242        ret = pmic_reg_read(pmic, REG_CG_STATUS1, &val);
 243        if (ret)
 244                return ret;
 245
 246        return val;
 247}
 248
 249static int tps65090_charger_bat_present(struct pmic *pmic)
 250{
 251        u32 val;
 252        int ret;
 253
 254        ret = pmic_reg_read(pmic, REG_IRQ1, &val);
 255        if (ret)
 256                return ret;
 257
 258        return !!(val & IRQ1_VBATG);
 259}
 260
 261static struct power_chrg power_chrg_pmic_ops = {
 262        .chrg_bat_present = tps65090_charger_bat_present,
 263        .chrg_state = tps65090_charger_state,
 264};
 265
 266int tps65090_init(void)
 267{
 268        struct pmic *p;
 269        int bus;
 270        int addr;
 271        const void *blob = gd->fdt_blob;
 272        int node, parent;
 273
 274        node = fdtdec_next_compatible(blob, 0, COMPAT_TI_TPS65090);
 275        if (node < 0) {
 276                debug("PMIC: No node for PMIC Chip in device tree\n");
 277                debug("node = %d\n", node);
 278                return -ENODEV;
 279        }
 280
 281        parent = fdt_parent_offset(blob, node);
 282        if (parent < 0) {
 283                debug("%s: Cannot find node parent\n", __func__);
 284                return -EINVAL;
 285        }
 286
 287        bus = i2c_get_bus_num_fdt(parent);
 288        if (bus < 0) {
 289                debug("%s: Cannot find I2C bus\n", __func__);
 290                return -ENOENT;
 291        }
 292        addr = fdtdec_get_int(blob, node, "reg", TPS65090_I2C_ADDR);
 293        p = pmic_alloc();
 294        if (!p) {
 295                printf("%s: POWER allocation error!\n", __func__);
 296                return -ENOMEM;
 297        }
 298
 299        p->name = TPS65090_NAME;
 300        p->bus = bus;
 301        p->interface = PMIC_I2C;
 302        p->number_of_regs = TPS65090_NUM_REGS;
 303        p->hw.i2c.addr = addr;
 304        p->hw.i2c.tx_num = 1;
 305        p->chrg = &power_chrg_pmic_ops;
 306
 307        puts("TPS65090 PMIC init\n");
 308
 309        return 0;
 310}
 311