]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/power/pmic/pmic_tps65090.c
Merge branch 'u-boot-samsung/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / drivers / power / pmic / pmic_tps65090.c
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
14 DECLARE_GLOBAL_DATA_PTR;
15
16 #define TPS65090_NAME "TPS65090_PMIC"
17
18 /* TPS65090 register addresses */
19 enum {
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
33 enum {
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  */
54 static 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  */
74 static 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
107 int 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
154 int 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
171 int 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
193 int 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
210 static 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
232 int 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
249 static 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
261 static struct power_chrg power_chrg_pmic_ops = {
262         .chrg_bat_present = tps65090_charger_bat_present,
263         .chrg_state = tps65090_charger_state,
264 };
265
266 int 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 (p->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 }