6dfec893360693b55eca1ea5e0c1cd15d5242595
[oweals/u-boot.git] / drivers / power / regulator / tps65090_regulator.c
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 <log.h>
10 #include <power/pmic.h>
11 #include <power/regulator.h>
12 #include <power/tps65090.h>
13
14 static 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
26 static int 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  */
50 static 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
86 static 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
128 static const struct dm_regulator_ops tps65090_fet_ops = {
129         .get_enable = tps65090_fet_get_enable,
130         .set_enable = tps65090_fet_set_enable,
131 };
132
133 U_BOOT_DRIVER(tps65090_fet) = {
134         .name = TPS65090_FET_DRIVER,
135         .id = UCLASS_REGULATOR,
136         .ops = &tps65090_fet_ops,
137         .probe = tps65090_fet_probe,
138 };