xref: /OK3568_Linux_fs/u-boot/drivers/power/fuel_gauge/fg_cw201x.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 #include <common.h>
7 #include <asm/gpio.h>
8 #include <dm.h>
9 #include <dm/device.h>
10 #include <errno.h>
11 #include <fdtdec.h>
12 #include <i2c.h>
13 #include <linux/usb/phy-rockchip-usb2.h>
14 #include <malloc.h>
15 #include <power/battery.h>
16 #include <power/fuel_gauge.h>
17 #include <power/pmic.h>
18 #include "fg_regs.h"
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 #define COMPAT_ROCKCHIP_CW201X "cw201x"
23 
24 #define REG_VERSION		0x0
25 #define REG_VCELL		0x2
26 #define REG_SOC			0x4
27 #define REG_RRT_ALERT		0x6
28 #define REG_CONFIG		0x8
29 #define REG_MODE		0xA
30 #define REG_BATINFO		0x10
31 
32 #define MODE_SLEEP_MASK		(0x3 << 6)
33 #define MODE_SLEEP		(0x3 << 6)
34 #define MODE_NORMAL		(0x0 << 6)
35 #define MODE_QUICK_START	(0x3 << 4)
36 #define MODE_RESTART		(0xf << 0)
37 
38 #define CONFIG_UPDATE_FLG	(0x1 << 1)
39 #define ATHD			(0x0 << 3)
40 
41 enum charger_type {
42 	CHARGER_TYPE_NO = 0,
43 	CHARGER_TYPE_USB,
44 	CHARGER_TYPE_AC,
45 	CHARGER_TYPE_DC,
46 	CHARGER_TYPE_UNDEF,
47 };
48 
49 struct cw201x_info {
50 	struct udevice *dev;
51 	int capacity;
52 	u32 *cw_bat_config_info;
53 	int divider_res1;
54 	int divider_res2;
55 	int hw_id_check;
56 	struct gpio_desc hw_id0;
57 	struct gpio_desc hw_id1;
58 	int support_dc_adp;
59 	struct gpio_desc dc_det_gpio;
60 	int dc_det_flag;
61 	bool dual_cell;
62 };
63 
cw201x_read(struct cw201x_info * cw201x,u8 reg)64 static u8 cw201x_read(struct cw201x_info *cw201x, u8 reg)
65 {
66 	u8 val;
67 	int ret;
68 
69 	ret = dm_i2c_read(cw201x->dev, reg, &val, 1);
70 	if (ret) {
71 		debug("write error to device: %p register: %#x!",
72 		      cw201x->dev, reg);
73 		return ret;
74 	}
75 
76 	return val;
77 }
78 
cw201x_write(struct cw201x_info * cw201x,u8 reg,u8 val)79 static int cw201x_write(struct cw201x_info *cw201x, u8 reg, u8 val)
80 {
81 	int ret;
82 
83 	ret = dm_i2c_write(cw201x->dev, reg, &val, 1);
84 	if (ret) {
85 		debug("write error to device: %p register: %#x!",
86 		      cw201x->dev, reg);
87 		return ret;
88 	}
89 
90 	return 0;
91 }
92 
cw201x_read_half_word(struct cw201x_info * cw201x,int reg)93 static u16 cw201x_read_half_word(struct cw201x_info *cw201x, int reg)
94 {
95 	u8 vall, valh;
96 	u16 val;
97 
98 	valh = cw201x_read(cw201x, reg);
99 	vall = cw201x_read(cw201x, reg + 1);
100 	val = ((u16)valh << 8) | vall;
101 
102 	return val;
103 }
104 
cw201x_parse_config_info(struct cw201x_info * cw201x)105 static int cw201x_parse_config_info(struct cw201x_info *cw201x)
106 {
107 	int ret;
108 	int i, len, size;
109 	const u8 *info;
110 	struct udevice *dev = cw201x->dev;
111 
112 	if (dev_read_prop(dev, "bat_config_info", &len)) {
113 		len /= sizeof(u32);
114 		size = sizeof(*cw201x->cw_bat_config_info) * len;
115 		cw201x->cw_bat_config_info = calloc(size, 1);
116 		if (!cw201x->cw_bat_config_info) {
117 			debug("calloc cw_bat_config_info fail\n");
118 			return -EINVAL;
119 		}
120 		ret = dev_read_u32_array(dev, "bat_config_info",
121 					 cw201x->cw_bat_config_info, len);
122 		if (ret) {
123 			debug("fdtdec_get cw_bat_config_info fail\n");
124 			return -EINVAL;
125 		}
126 
127 		return 0;
128 	}
129 
130 	if (!dev_read_prop(dev, "cellwise,battery-profile", &len))
131 		return -EINVAL;
132 
133 	size = sizeof(*cw201x->cw_bat_config_info) * len;
134 	cw201x->cw_bat_config_info = calloc(size, 1);
135 	if (!cw201x->cw_bat_config_info) {
136 		debug("calloc cw_bat_config_info fail\n");
137 		return -EINVAL;
138 	}
139 
140 	info = dev_read_u8_array_ptr(dev, "cellwise,battery-profile", len);
141 	if (!info) {
142 		debug("fdtdec_get battery profile fail\n");
143 		return -EINVAL;
144 	}
145 	for (i = 0; i < len; i++) {
146 		cw201x->cw_bat_config_info[i] = info[i];
147 		debug("%#x ", cw201x->cw_bat_config_info[i]);
148 		if ((i+1) % 8 == 0)
149 			debug("\n");
150 	}
151 
152 	return 0;
153 }
154 
cw201x_ofdata_to_platdata(struct udevice * dev)155 static int cw201x_ofdata_to_platdata(struct udevice *dev)
156 {
157 	struct cw201x_info *cw201x = dev_get_priv(dev);
158 	int ret;
159 	int hw_id0_val, hw_id1_val;
160 
161 	cw201x->dev = dev;
162 	ret = cw201x_parse_config_info(cw201x);
163 	if (ret)
164 		return ret;
165 
166 	cw201x->dual_cell = dev_read_bool(dev, "cellwise,dual-cell");
167 	ret = gpio_request_by_name_nodev(dev_ofnode(dev), "dc_det_gpio",
168 					 0, &cw201x->dc_det_gpio, GPIOD_IS_IN);
169 	if (!ret) {
170 		cw201x->support_dc_adp = 1;
171 		debug("DC is valid\n");
172 	} else {
173 		debug("DC is invalid, ret=%d\n", ret);
174 	}
175 
176 	cw201x->hw_id_check = dev_read_u32_default(dev, "hw_id_check", 0);
177 	if (cw201x->hw_id_check) {
178 		ret = gpio_request_by_name_nodev(dev_ofnode(dev),
179 						 "hw_id0_gpio", 0,
180 						 &cw201x->hw_id0, GPIOD_IS_IN);
181 		if (ret)
182 			return -EINVAL;
183 		hw_id0_val = dm_gpio_get_value(&cw201x->hw_id0);
184 
185 		ret = gpio_request_by_name_nodev(dev_ofnode(dev),
186 						 "hw_id1_gpio", 0,
187 						 &cw201x->hw_id1, GPIOD_IS_IN);
188 		if (ret)
189 			return -EINVAL;
190 		hw_id1_val = dm_gpio_get_value(&cw201x->hw_id1);
191 
192 		/* ID1 = 0, ID0 = 1 : Battery */
193 		if (!hw_id0_val || hw_id1_val)
194 			return -EINVAL;
195 	}
196 
197 	cw201x->divider_res1 = dev_read_u32_default(dev, "divider_res1", 0);
198 	cw201x->divider_res2 = dev_read_u32_default(dev, "divider_res2", 0);
199 
200 	return 0;
201 }
202 
cw201x_get_vol(struct cw201x_info * cw201x)203 static int cw201x_get_vol(struct cw201x_info *cw201x)
204 {
205 	u16 value16, value16_1, value16_2, value16_3;
206 	int voltage;
207 	int res1, res2;
208 	int retry = 0;
209 
210 __retry:
211 	value16 = cw201x_read_half_word(cw201x, REG_VCELL);
212 	if (value16 < 0)
213 		return -1;
214 
215 	value16_1 = cw201x_read_half_word(cw201x, REG_VCELL);
216 	if (value16_1 < 0)
217 		return -1;
218 
219 	value16_2 = cw201x_read_half_word(cw201x, REG_VCELL);
220 	if (value16_2 < 0)
221 		return -1;
222 
223 	if (value16 > value16_1) {
224 		value16_3 = value16;
225 		value16 = value16_1;
226 		value16_1 = value16_3;
227 	}
228 
229 	if (value16_1 > value16_2) {
230 		value16_3 = value16_1;
231 		value16_1 = value16_2;
232 		value16_2 = value16_3;
233 	}
234 
235 	if (value16 > value16_1) {
236 		value16_3 = value16;
237 		value16 = value16_1;
238 		value16_1 = value16_3;
239 	}
240 
241 	voltage = value16_1 * 312 / 1024;
242 	if (voltage <= 0 && retry < 10) {
243 		retry++;
244 		mdelay(20);
245 		goto __retry;
246 	}
247 
248 	if (cw201x->divider_res1 &&
249 	    cw201x->divider_res2) {
250 		res1 = cw201x->divider_res1;
251 		res2 = cw201x->divider_res2;
252 		voltage = voltage * (res1 + res2) / res2;
253 	}
254 
255 	if (cw201x->dual_cell)
256 		voltage *= 2;
257 
258 	debug("the cw201x voltage=%d\n", voltage);
259 	return voltage;
260 }
261 
cw201x_dwc_otg_check_dpdm(void)262 static int cw201x_dwc_otg_check_dpdm(void)
263 {
264 #if defined(CONFIG_PHY_ROCKCHIP_INNO_USB2) && !defined(CONFIG_SPL_BUILD)
265 	return rockchip_chg_get_type();
266 #else
267 	debug("rockchip_chg_get_type() is not implement\n");
268 	return CHARGER_TYPE_NO;
269 #endif
270 }
271 
cw201x_get_usb_state(struct cw201x_info * cw201x)272 static int cw201x_get_usb_state(struct cw201x_info *cw201x)
273 {
274 	int charger_type;
275 
276 	switch (cw201x_dwc_otg_check_dpdm()) {
277 	case 0:
278 		charger_type = CHARGER_TYPE_NO;
279 		break;
280 	case 1:
281 	case 3:
282 		charger_type = CHARGER_TYPE_USB;
283 		break;
284 	case 2:
285 		charger_type = CHARGER_TYPE_AC;
286 		break;
287 	default:
288 		charger_type = CHARGER_TYPE_NO;
289 		break;
290 	}
291 
292 	return charger_type;
293 }
294 
cw201x_get_dc_state(struct cw201x_info * cw201x)295 static bool cw201x_get_dc_state(struct cw201x_info *cw201x)
296 {
297 	if (dm_gpio_get_value(&cw201x->dc_det_gpio))
298 		return true;
299 
300 	return false;
301 }
302 
cw201x_check_charge(struct cw201x_info * cw201x)303 static bool cw201x_check_charge(struct cw201x_info *cw201x)
304 {
305 	if (cw201x_get_usb_state(cw201x) != CHARGER_TYPE_NO)
306 		return true;
307 	if (cw201x_get_dc_state(cw201x))
308 		return true;
309 
310 	return false;
311 }
312 
cw201x_get_soc(struct cw201x_info * cw201x)313 static int cw201x_get_soc(struct cw201x_info *cw201x)
314 {
315 	int cap, i = 0;
316 
317 	while (i < 10) {
318 		cap = cw201x_read(cw201x, REG_SOC);
319 		if ((cap < 0) || (cap > 100))
320 			cap = cw201x->capacity;
321 		i++;
322 		if (cap)
323 			break;
324 	}
325 	cw201x->capacity = cap;
326 
327 	return cw201x->capacity;
328 }
329 
cw201x_update_get_soc(struct udevice * dev)330 static int cw201x_update_get_soc(struct udevice *dev)
331 {
332 	struct cw201x_info *cw201x = dev_get_priv(dev);
333 
334 	return cw201x_get_soc(cw201x);
335 }
336 
cw201x_update_get_voltage(struct udevice * dev)337 static int cw201x_update_get_voltage(struct udevice *dev)
338 {
339 	struct cw201x_info *cw201x = dev_get_priv(dev);
340 
341 	return cw201x_get_vol(cw201x);
342 }
343 
cw201x_update_get_current(struct udevice * dev)344 static int cw201x_update_get_current(struct udevice *dev)
345 {
346 	return 0;
347 }
348 
cw201x_update_get_chrg_online(struct udevice * dev)349 static bool cw201x_update_get_chrg_online(struct udevice *dev)
350 {
351 	struct cw201x_info *cw201x = dev_get_priv(dev);
352 
353 	return cw201x_check_charge(cw201x);
354 }
355 
cw201x_capability(struct udevice * dev)356 static int cw201x_capability(struct udevice *dev)
357 {
358 	return FG_CAP_FUEL_GAUGE;
359 }
360 
361 static struct dm_fuel_gauge_ops cw201x_fg_ops = {
362 	.capability = cw201x_capability,
363 	.get_soc = cw201x_update_get_soc,
364 	.get_voltage = cw201x_update_get_voltage,
365 	.get_current = cw201x_update_get_current,
366 	.get_chrg_online = cw201x_update_get_chrg_online,
367 };
368 
cw201x_fg_cfg(struct cw201x_info * cw201x)369 static int cw201x_fg_cfg(struct cw201x_info *cw201x)
370 {
371 	u8 val = MODE_SLEEP;
372 	int i;
373 
374 	if ((val & MODE_SLEEP_MASK) == MODE_SLEEP) {
375 		val = MODE_NORMAL;
376 		cw201x_write(cw201x, REG_MODE, val);
377 	}
378 
379 	for (i = 0; i < 64; i++) {
380 		cw201x_write(cw201x, REG_BATINFO + i,
381 			     (u8)cw201x->cw_bat_config_info[i]);
382 	}
383 
384 	return 0;
385 }
386 
cw201x_fg_probe(struct udevice * dev)387 static int cw201x_fg_probe(struct udevice *dev)
388 {
389 	struct cw201x_info *cw201x = dev_get_priv(dev);
390 
391 	cw201x->dev = dev;
392 	cw201x_fg_cfg(cw201x);
393 
394 	debug("vol: %d, soc: %d\n",
395 	      cw201x_get_vol(cw201x), cw201x_get_soc(cw201x));
396 
397 	return 0;
398 }
399 
400 static const struct udevice_id cw201x_ids[] = {
401 	{ .compatible = "cw201x" },
402 	{ .compatible = "cellwise,cw2015" },
403 	{ }
404 };
405 
406 U_BOOT_DRIVER(cw201x_fg) = {
407 	.name = "cw201x_fg",
408 	.id = UCLASS_FG,
409 	.of_match = cw201x_ids,
410 	.probe = cw201x_fg_probe,
411 	.ofdata_to_platdata = cw201x_ofdata_to_platdata,
412 	.ops = &cw201x_fg_ops,
413 	.priv_auto_alloc_size = sizeof(struct cw201x_info),
414 };
415