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