blob: 58bb3ce95d00bff6bf8dc82ea3b6a7736d9a456c [file] [log] [blame]
David Hendricks6e877ec2013-04-09 16:58:02 -07001/*
David Hendricks765ff762013-04-09 17:20:07 -07002 * Copyright 2012, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
David Hendricks6e877ec2013-04-09 16:58:02 -070030 *
31 * Alternatively, this software may be distributed under the terms of the
32 * GNU General Public License ("GPL") version 2 as published by the Free
33 * Software Foundation.
34 */
35
David Hendricks765ff762013-04-09 17:20:07 -070036#include <delay.h>
37#include <types.h>
38#include <console/console.h>
39#include <device/i2c.h>
40#include "tps65090.h"
David Hendricks6e877ec2013-04-09 16:58:02 -070041
42/* TPS65090 register addresses */
43enum {
44 REG_CG_CTRL0 = 4,
45 REG_CG_STATUS1 = 0xa,
David Hendricks6e877ec2013-04-09 16:58:02 -070046};
47
48enum {
49 CG_CTRL0_ENC_MASK = 0x01,
50
51 MAX_FET_NUM = 7,
52 MAX_CTRL_READ_TRIES = 5,
53
54 /* TPS65090 FET_CTRL register values */
55 FET_CTRL_TOFET = 1 << 7, /* Timeout, startup, overload */
56 FET_CTRL_PGFET = 1 << 4, /* Power good for FET status */
57 FET_CTRL_WAIT = 3 << 2, /* Overcurrent timeout max */
58 FET_CTRL_ADENFET = 1 << 1, /* Enable output auto discharge */
59 FET_CTRL_ENFET = 1 << 0, /* Enable FET */
60};
61
David Hendricks765ff762013-04-09 17:20:07 -070062static int tps65090_i2c_write(unsigned int bus,
63 unsigned int reg_addr, unsigned char value)
David Hendricks6e877ec2013-04-09 16:58:02 -070064{
65 int ret;
66
Gabe Blackcdb61a62014-04-07 18:45:14 -070067 ret = i2c_writeb(bus, TPS65090_I2C_ADDR, reg_addr, value);
David Hendricks765ff762013-04-09 17:20:07 -070068 printk(BIOS_DEBUG, "%s: reg=%#x, value=%#x, ret=%d\n",
69 __func__, reg_addr, value, ret);
David Hendricks6e877ec2013-04-09 16:58:02 -070070 return ret;
71}
72
David Hendricks765ff762013-04-09 17:20:07 -070073static int tps65090_i2c_read(unsigned int bus,
74 unsigned int reg_addr, unsigned char *value)
David Hendricks6e877ec2013-04-09 16:58:02 -070075{
76 int ret;
77
David Hendricks765ff762013-04-09 17:20:07 -070078 printk(BIOS_DEBUG, "%s: reg=%#x, ", __func__, reg_addr);
Gabe Blackcdb61a62014-04-07 18:45:14 -070079 ret = i2c_readb(bus, TPS65090_I2C_ADDR, reg_addr, value);
David Hendricks6e877ec2013-04-09 16:58:02 -070080 if (ret)
David Hendricks765ff762013-04-09 17:20:07 -070081 printk(BIOS_DEBUG, "fail, ret=%d\n", ret);
David Hendricks6e877ec2013-04-09 16:58:02 -070082 else
David Hendricks765ff762013-04-09 17:20:07 -070083 printk(BIOS_DEBUG, "value=%#x, ret=%d\n", *value, ret);
David Hendricks6e877ec2013-04-09 16:58:02 -070084 return ret;
85}
86
David Hendricks6e877ec2013-04-09 16:58:02 -070087/**
88 * Set the power state for a FET
89 *
Martin Roth5f066b22015-01-04 16:47:39 -070090 * @param bus
91 * @param fet_id Fet number to set (1..MAX_FET_NUM)
92 * @param set 1 to power on FET, 0 to power off
David Hendricks6e877ec2013-04-09 16:58:02 -070093 * @return FET_ERR_COMMS if we got a comms error, FET_ERR_NOT_READY if the
94 * FET failed to change state. If all is ok, returns 0.
95 */
David Hendricks765ff762013-04-09 17:20:07 -070096static int tps65090_fet_set(unsigned int bus, enum fet_id fet_id, int set)
David Hendricks6e877ec2013-04-09 16:58:02 -070097{
98 int retry, value;
David Hendricks765ff762013-04-09 17:20:07 -070099 uint8_t reg;
David Hendricks6e877ec2013-04-09 16:58:02 -0700100
101 value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
102 if (set)
103 value |= FET_CTRL_ENFET;
104
David Hendricks765ff762013-04-09 17:20:07 -0700105 if (tps65090_i2c_write(bus, fet_id, value))
David Hendricks6e877ec2013-04-09 16:58:02 -0700106 return FET_ERR_COMMS;
107 /* Try reading until we get a result */
108 for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
David Hendricks765ff762013-04-09 17:20:07 -0700109 if (tps65090_i2c_read(bus, fet_id, &reg))
David Hendricks6e877ec2013-04-09 16:58:02 -0700110 return FET_ERR_COMMS;
111
112 /* Check that the fet went into the expected state */
113 if (!!(reg & FET_CTRL_PGFET) == set)
114 return 0;
115
116 /* If we got a timeout, there is no point in waiting longer */
117 if (reg & FET_CTRL_TOFET)
118 break;
119
David Hendricks765ff762013-04-09 17:20:07 -0700120 udelay(1000);
David Hendricks6e877ec2013-04-09 16:58:02 -0700121 }
122
David Hendricks765ff762013-04-09 17:20:07 -0700123 printk(BIOS_DEBUG, "FET %d: Power good should have set to %d but "
124 "reg=%#02x\n", fet_id, set, reg);
David Hendricks6e877ec2013-04-09 16:58:02 -0700125 return FET_ERR_NOT_READY;
126}
127
David Hendricks765ff762013-04-09 17:20:07 -0700128/* FIXME(dhendrix): add timer API */
129#if 0
130int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id)
David Hendricks6e877ec2013-04-09 16:58:02 -0700131{
132 int loops;
David Hendricks765ff762013-04-09 17:20:07 -0700133 unsigned long start;
David Hendricks6e877ec2013-04-09 16:58:02 -0700134 int ret = 0;
135
David Hendricks6e877ec2013-04-09 16:58:02 -0700136 start = get_timer(0);
137 for (loops = 0; ; loops++) {
David Hendricks765ff762013-04-09 17:20:07 -0700138 ret = tps65090_fet_set(bus, fet_id, 1);
David Hendricks6e877ec2013-04-09 16:58:02 -0700139 if (!ret)
140 break;
141
142 if (get_timer(start) > 100)
143 break;
144
145 /* Turn it off and try again until we time out */
David Hendricks765ff762013-04-09 17:20:07 -0700146 tps65090_fet_set(bus, fet_id, 0);
David Hendricks6e877ec2013-04-09 16:58:02 -0700147 }
David Hendricks6e877ec2013-04-09 16:58:02 -0700148
149 if (ret) {
David Hendricks765ff762013-04-09 17:20:07 -0700150 printk(BIOS_DEBUG, "%s: FET%d failed to power on: time=%lums, "
151 "loops=%d\n", __func__, fet_id,
152 get_timer(start), loops);
David Hendricks6e877ec2013-04-09 16:58:02 -0700153 } else if (loops) {
David Hendricks765ff762013-04-09 17:20:07 -0700154 printk(BIOS_DEBUG, "%s: FET%d powered on after %lums, "
155 "loops=%d\n", __func__, fet_id,
156 get_timer(start), loops);
157 }
158 /*
159 * Unfortunately, there are some conditions where the power
160 * good bit will be 0, but the fet still comes up. One such
161 * case occurs with the lcd backlight. We'll just return 0 here
162 * and assume that the fet will eventually come up.
163 */
164 if (ret == FET_ERR_NOT_READY)
165 ret = 0;
166
167 return ret;
168}
169#endif
170int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id)
171{
172 int loops;
173 int ret = 0;
174
175 for (loops = 0; loops < 100; loops++) {
176 ret = tps65090_fet_set(bus, fet_id, 1);
177 if (!ret)
178 break;
179
180 /* Turn it off and try again until we time out */
181 tps65090_fet_set(bus, fet_id, 0);
182 udelay(1000);
183 }
184
185 if (ret) {
186 printk(BIOS_DEBUG, "%s: FET%d failed to power on\n",
187 __func__, fet_id);
188 } else if (loops) {
189 printk(BIOS_DEBUG, "%s: FET%d powered on\n",
190 __func__, fet_id);
David Hendricks6e877ec2013-04-09 16:58:02 -0700191 }
192 /*
193 * Unfortunately, there are some conditions where the power
194 * good bit will be 0, but the fet still comes up. One such
195 * case occurs with the lcd backlight. We'll just return 0 here
196 * and assume that the fet will eventually come up.
197 */
198 if (ret == FET_ERR_NOT_READY)
199 ret = 0;
200
201 return ret;
202}
203
David Hendricks765ff762013-04-09 17:20:07 -0700204int tps65090_fet_disable(unsigned int bus, enum fet_id fet_id)
David Hendricks6e877ec2013-04-09 16:58:02 -0700205{
David Hendricks765ff762013-04-09 17:20:07 -0700206 return tps65090_fet_set(bus, fet_id, 0);
David Hendricks6e877ec2013-04-09 16:58:02 -0700207}
208
David Hendricks765ff762013-04-09 17:20:07 -0700209int tps65090_fet_is_enabled(unsigned int bus, enum fet_id fet_id)
David Hendricks6e877ec2013-04-09 16:58:02 -0700210{
211 unsigned char reg;
212 int ret;
213
David Hendricks765ff762013-04-09 17:20:07 -0700214 ret = tps65090_i2c_read(bus, fet_id, &reg);
David Hendricks6e877ec2013-04-09 16:58:02 -0700215 if (ret) {
David Hendricks765ff762013-04-09 17:20:07 -0700216 printk(BIOS_DEBUG, "fail to read FET%u_CTRL", fet_id);
David Hendricks6e877ec2013-04-09 16:58:02 -0700217 return -2;
218 }
219
220 return reg & FET_CTRL_ENFET;
221}
222
David Hendricks765ff762013-04-09 17:20:07 -0700223int tps65090_is_charging(unsigned int bus)
David Hendricks6e877ec2013-04-09 16:58:02 -0700224{
225 unsigned char val;
226 int ret;
227
David Hendricks765ff762013-04-09 17:20:07 -0700228 ret = tps65090_i2c_read(bus, REG_CG_CTRL0, &val);
David Hendricks6e877ec2013-04-09 16:58:02 -0700229 if (ret)
230 return ret;
231 return val & CG_CTRL0_ENC_MASK ? 1 : 0;
232}
233
David Hendricks765ff762013-04-09 17:20:07 -0700234int tps65090_set_charge_enable(unsigned int bus, int enable)
David Hendricks6e877ec2013-04-09 16:58:02 -0700235{
236 unsigned char val;
237 int ret;
238
David Hendricks765ff762013-04-09 17:20:07 -0700239 ret = tps65090_i2c_read(bus, REG_CG_CTRL0, &val);
David Hendricks6e877ec2013-04-09 16:58:02 -0700240 if (!ret) {
241 if (enable)
242 val |= CG_CTRL0_ENC_MASK;
243 else
244 val &= ~CG_CTRL0_ENC_MASK;
David Hendricks765ff762013-04-09 17:20:07 -0700245 ret = tps65090_i2c_write(bus, REG_CG_CTRL0, val);
David Hendricks6e877ec2013-04-09 16:58:02 -0700246 }
David Hendricks6e877ec2013-04-09 16:58:02 -0700247 if (ret) {
David Hendricks765ff762013-04-09 17:20:07 -0700248 printk(BIOS_DEBUG, "%s: Failed to enable\n", __func__);
David Hendricks6e877ec2013-04-09 16:58:02 -0700249 return ret;
250 }
251 return 0;
252}
253
David Hendricks765ff762013-04-09 17:20:07 -0700254int tps65090_get_status(unsigned int bus)
David Hendricks6e877ec2013-04-09 16:58:02 -0700255{
256 unsigned char val;
257 int ret;
258
David Hendricks765ff762013-04-09 17:20:07 -0700259 ret = tps65090_i2c_read(bus, REG_CG_STATUS1, &val);
David Hendricks6e877ec2013-04-09 16:58:02 -0700260 if (ret)
261 return ret;
262 return val;
263}