blob: 337903acec8a56c493c32543cafbe978fd8f3b2e [file] [log] [blame]
Tom Wai-Hong Tam2ab56952014-05-20 06:01:36 -06001/*
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);
Jeroen Hofstee550b42d2014-06-15 17:17:04 +0200288 if (bus < 0) {
Tom Wai-Hong Tam2ab56952014-05-20 06:01:36 -0600289 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}