uboot/drivers/power/regulator/tps65090_regulator.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2015 Google, Inc
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <power/pmic.h>
  11#include <power/regulator.h>
  12#include <power/tps65090.h>
  13
  14static int tps65090_fet_probe(struct udevice *dev)
  15{
  16        struct dm_regulator_uclass_platdata *uc_pdata;
  17
  18        uc_pdata = dev_get_uclass_platdata(dev);
  19
  20        uc_pdata->type = REGULATOR_TYPE_OTHER;
  21        uc_pdata->mode_count = 0;
  22
  23        return 0;
  24}
  25
  26static bool tps65090_fet_get_enable(struct udevice *dev)
  27{
  28        struct udevice *pmic = dev_get_parent(dev);
  29        int ret, fet_id;
  30
  31        fet_id = dev->driver_data;
  32        debug("%s: fet_id=%d\n", __func__, fet_id);
  33
  34        ret = pmic_reg_read(pmic, REG_FET_BASE + fet_id);
  35        if (ret < 0)
  36                return ret;
  37
  38        return ret & FET_CTRL_ENFET;
  39}
  40
  41/**
  42 * Set the power state for a FET
  43 *
  44 * @param pmic          pmic structure for the tps65090
  45 * @param fet_id        FET number to set (1..MAX_FET_NUM)
  46 * @param set           1 to power on FET, 0 to power off
  47 * @return -EIO if we got a comms error, -EAGAIN if the FET failed to
  48 * change state. If all is ok, returns 0.
  49 */
  50static int tps65090_fet_set(struct udevice *pmic, int fet_id, bool set)
  51{
  52        int retry;
  53        u32 value;
  54        int ret;
  55
  56        value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
  57        if (set)
  58                value |= FET_CTRL_ENFET;
  59
  60        if (pmic_reg_write(pmic, REG_FET_BASE + fet_id, value))
  61                return -EIO;
  62
  63        /* Try reading until we get a result */
  64        for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
  65                ret = pmic_reg_read(pmic, REG_FET_BASE + fet_id);
  66                if (ret < 0)
  67                        return ret;
  68
  69                /* Check that the FET went into the expected state */
  70                debug("%s: flags=%x\n", __func__, ret);
  71                if (!!(ret & FET_CTRL_PGFET) == set)
  72                        return 0;
  73
  74                /* If we got a timeout, there is no point in waiting longer */
  75                if (ret & FET_CTRL_TOFET)
  76                        break;
  77
  78                mdelay(1);
  79        }
  80
  81        debug("FET %d: Power good should have set to %d but reg=%#02x\n",
  82              fet_id, set, ret);
  83        return -EAGAIN;
  84}
  85
  86static int tps65090_fet_set_enable(struct udevice *dev, bool enable)
  87{
  88        struct udevice *pmic = dev_get_parent(dev);
  89        int ret, fet_id;
  90        ulong start;
  91        int loops;
  92
  93        fet_id = dev->driver_data;
  94        debug("%s: fet_id=%d, enable=%d\n", __func__, fet_id, enable);
  95
  96        start = get_timer(0);
  97        for (loops = 0;; loops++) {
  98                ret = tps65090_fet_set(pmic, fet_id, enable);
  99                if (!ret)
 100                        break;
 101
 102                if (get_timer(start) > 100)
 103                        break;
 104
 105                /* Turn it off and try again until we time out */
 106                tps65090_fet_set(pmic, fet_id, false);
 107        }
 108
 109        if (ret)
 110                debug("%s: FET%d failed to power on: time=%lums, loops=%d\n",
 111                      __func__, fet_id, get_timer(start), loops);
 112        else if (loops)
 113                debug("%s: FET%d powered on after %lums, loops=%d\n",
 114                      __func__, fet_id, get_timer(start), loops);
 115
 116        /*
 117         * Unfortunately there are some conditions where the power-good bit
 118         * will be 0, but the FET still comes up. One such case occurs with
 119         * the LCD backlight on snow. We'll just return 0 here and assume
 120         * that the FET will eventually come up.
 121         */
 122        if (ret == -EAGAIN)
 123                ret = 0;
 124
 125        return ret;
 126}
 127
 128static const struct dm_regulator_ops tps65090_fet_ops = {
 129        .get_enable = tps65090_fet_get_enable,
 130        .set_enable = tps65090_fet_set_enable,
 131};
 132
 133U_BOOT_DRIVER(tps65090_fet) = {
 134        .name = TPS65090_FET_DRIVER,
 135        .id = UCLASS_REGULATOR,
 136        .ops = &tps65090_fet_ops,
 137        .probe = tps65090_fet_probe,
 138};
 139