xref: /OK3568_Linux_fs/kernel/drivers/power/supply/cw221x_battery.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Chrager driver for cw221x
4  *
5  * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
6  *
7  * Author: Xu Shengfei <xsf@rock-chips.com>
8  */
9 #include <linux/delay.h>
10 #include <linux/init.h>
11 #include <linux/i2c.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/power_supply.h>
16 #include <linux/sizes.h>
17 #include <linux/time.h>
18 #include <linux/workqueue.h>
19 
20 /* Module parameters. */
21 static int debug;
22 module_param_named(debug, debug, int, 0644);
23 MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
24 
25 #define cw_printk(fmt, arg...)	\
26 	{	\
27 		if (debug)	\
28 			pr_info("FG_CW221X: %s-%d:" fmt, __func__, __LINE__, ##arg);	\
29 	}
30 
31 #define CW_PROPERTIES "cw221X-bat"
32 
33 #define REG_CHIP_ID		0x00
34 #define REG_VCELL_H		0x02
35 #define REG_VCELL_L		0x03
36 #define REG_SOC_INT		0x04
37 #define REG_SOC_DECIMAL		0x05
38 #define REG_TEMP		0x06
39 #define REG_MODE_CONFIG		0x08
40 #define REG_GPIO_CONFIG		0x0A
41 #define REG_SOC_ALERT		0x0B
42 #define REG_TEMP_MAX		0x0C
43 #define REG_TEMP_MIN		0x0D
44 #define REG_CURRENT_H		0x0E
45 #define REG_CURRENT_L		0x0F
46 #define REG_T_HOST_H		0xA0
47 #define REG_T_HOST_L		0xA1
48 #define REG_USER_CONF		0xA2
49 #define REG_CYCLE_H		0xA4
50 #define REG_CYCLE_L		0xA5
51 #define REG_SOH			0xA6
52 #define REG_IC_STATE		0xA7
53 #define REG_FW_VERSION		0xAB
54 #define REG_BAT_PROFILE		0x10
55 
56 #define CONFIG_MODE_RESTART	0x30
57 #define CONFIG_MODE_ACTIVE	0x00
58 #define CONFIG_MODE_SLEEP	0xF0
59 #define CONFIG_UPDATE_FLG	0x80
60 #define IC_VCHIP_ID		0xA0
61 #define IC_READY_MARK		0x0C
62 
63 #define GPIO_ENABLE_MIN_TEMP	0
64 #define GPIO_ENABLE_MAX_TEMP	0
65 #define GPIO_ENABLE_SOC_CHANGE		0
66 #define GPIO_SOC_IRQ_VALUE		0x0 /* 0x7F */
67 #define DEFINED_MAX_TEMP		45
68 #define DEFINED_MIN_TEMP		0
69 
70 #define CWFG_NAME			"cw221X"
71 #define SIZE_OF_PROFILE			80
72 
73 /* mhom rsense * 1000 for convenience calculation */
74 #define USER_RSENSE			1500
75 
76 #define queue_delayed_work_time		5000
77 #define queue_start_work_time		50
78 
79 #define CW_SLEEP_20MS			20
80 #define CW_SLEEP_10MS			10
81 #define CW_UI_FULL			100
82 #define COMPLEMENT_CODE_U16		0x8000
83 #define CW_SLEEP_100MS			100
84 #define CW_SLEEP_200MS			200
85 #define CW_SLEEP_COUNTS			50
86 #define CW_TRUE				1
87 #define CW_RETRY_COUNT			3
88 #define CW_VOL_UNIT			1000
89 #define CW_LOW_VOLTAGE_REF		2500
90 #define CW_LOW_VOLTAGE			3000
91 #define CW_LOW_VOLTAGE_STEP		10
92 
93 #define CW221X_NOT_ACTIVE		1
94 #define CW221X_PROFILE_NOT_READY	2
95 #define CW221X_PROFILE_NEED_UPDATE	3
96 
97 #define CW2215_MARK			0x80
98 #define CW2217_MARK			0x40
99 #define CW2218_MARK			0x00
100 
101 static unsigned char config_profile_info[SIZE_OF_PROFILE] = {
102 	0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xB2,
103 	0xC2, 0xCA, 0xC2, 0xBD, 0x9C, 0x5C, 0x38, 0xFF, 0xFF, 0xC4,
104 	0x86, 0x74, 0x60, 0x55, 0x4F, 0x4D, 0x4B, 0x80, 0xC0, 0xDB,
105 	0xCD, 0xD0, 0xCE, 0xD2, 0xD3, 0xD2, 0xD0, 0xCE, 0xC3, 0xD5,
106 	0xB9, 0xC9, 0xC5, 0xA3, 0x92, 0x8A, 0x80, 0x72, 0x63, 0x62,
107 	0x74, 0x90, 0xA6, 0x7E, 0x5F, 0x48, 0x80, 0x00, 0xAB, 0x10,
108 	0x00, 0xA1, 0xFB, 0x00, 0x00, 0x00, 0x64, 0x1E, 0xB1, 0x04,
109 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D,
110 };
111 
112 struct cw_battery {
113 	struct i2c_client *client;
114 	struct device *dev;
115 	struct workqueue_struct *cwfg_workqueue;
116 	struct delayed_work battery_delay_work;
117 
118 	struct power_supply *cw_bat;
119 	u8 *bat_profile;
120 	int chip_id;
121 	int voltage;
122 	int ic_soc_h;
123 	int ic_soc_l;
124 	int ui_soc;
125 	int temp;
126 	long cw_current;
127 	int cycle;
128 	int soh;
129 	int fw_version;
130 };
131 
132 /* CW221X iic read function */
cw_read(struct i2c_client * client,unsigned char reg,unsigned char buf[])133 static int cw_read(struct i2c_client *client,
134 		   unsigned char reg,
135 		   unsigned char buf[])
136 {
137 	int ret;
138 
139 	ret = i2c_smbus_read_i2c_block_data(client, reg, 1, buf);
140 	if (ret < 0)
141 		dev_err(&client->dev, "IIC error %d\n", ret);
142 
143 	return ret;
144 }
145 
146 /* CW221X iic write function */
cw_write(struct i2c_client * client,unsigned char reg,unsigned char const buf[])147 static int cw_write(struct i2c_client *client,
148 		    unsigned char reg,
149 		    unsigned char const buf[])
150 {
151 	int ret;
152 
153 	ret = i2c_smbus_write_i2c_block_data(client, reg, 1, &buf[0]);
154 	if (ret < 0)
155 		dev_err(&client->dev, "IIC error %d\n", ret);
156 
157 	return ret;
158 }
159 
160 /* CW221X iic read word function */
cw_read_word(struct i2c_client * client,unsigned char reg,unsigned char buf[])161 static int cw_read_word(struct i2c_client *client,
162 			unsigned char reg,
163 			unsigned char buf[])
164 {
165 	unsigned char reg_val[2] = {0, 0};
166 	unsigned int temp_val_buff;
167 	unsigned int temp_val_second;
168 	int ret;
169 
170 	ret = i2c_smbus_read_i2c_block_data(client, reg, 2, reg_val);
171 	if (ret < 0)
172 		dev_err(&client->dev, "IIC error %d\n", ret);
173 	temp_val_buff = (reg_val[0] << 8) + reg_val[1];
174 
175 	msleep(CW_SLEEP_10MS);
176 	ret = i2c_smbus_read_i2c_block_data(client, reg, 2, reg_val);
177 	if (ret < 0)
178 		dev_err(&client->dev, "IIC error %d\n", ret);
179 	temp_val_second = (reg_val[0] << 8) + reg_val[1];
180 
181 	if (temp_val_buff != temp_val_second) {
182 		msleep(CW_SLEEP_10MS);
183 		ret = i2c_smbus_read_i2c_block_data(client, reg, 2, reg_val);
184 		if (ret < 0) {
185 			dev_err(&client->dev, "IIC error %d\n", ret);
186 			return ret;
187 		}
188 	}
189 
190 	buf[0] = reg_val[0];
191 	buf[1] = reg_val[1];
192 
193 	return ret;
194 }
195 
196 /* CW221X iic write profile function */
cw_write_profile(struct i2c_client * client,unsigned char const buf[])197 static int cw_write_profile(struct i2c_client *client, unsigned char const buf[])
198 {
199 	int ret;
200 	int i;
201 
202 	for (i = 0; i < SIZE_OF_PROFILE; i++) {
203 		ret = cw_write(client, REG_BAT_PROFILE + i, &buf[i]);
204 		if (ret < 0) {
205 			dev_err(&client->dev, "IIC error %d\n", ret);
206 			return ret;
207 		}
208 	}
209 
210 	return ret;
211 }
212 
213 /*
214  * CW221X Active function
215  * The CONFIG register is used for the host MCU to configure the fuel gauge IC.
216  * The default value is 0xF0, SLEEP and RESTART bits are set. To power up the IC,
217  * the host MCU needs to write 0x30 to exit shutdown mode, and then write 0x00 to
218  * restart the gauge to enter active mode. To reset the IC, the host MCU needs
219  * to write 0xF0, 0x30 and 0x00 in sequence to this register to complete the
220  * restart procedure. The CW221X will reload relevant parameters and settings and
221  * restart SOC calculation. Note that the SOC may be a different value after reset
222  * operation since it is a brand-new calculation based on the latest battery status.
223  * CONFIG [3:0] is reserved. Don't do any operation with it.
224  */
cw221X_active(struct cw_battery * cw_bat)225 static int cw221X_active(struct cw_battery *cw_bat)
226 {
227 	unsigned char reg_val = CONFIG_MODE_RESTART;
228 	int ret;
229 
230 	ret = cw_write(cw_bat->client, REG_MODE_CONFIG, &reg_val);
231 	if (ret < 0)
232 		return ret;
233 	msleep(CW_SLEEP_20MS); /* Here delay must >= 20 ms */
234 
235 	reg_val = CONFIG_MODE_ACTIVE;
236 	ret = cw_write(cw_bat->client, REG_MODE_CONFIG, &reg_val);
237 	if (ret < 0)
238 		return ret;
239 	msleep(CW_SLEEP_10MS);
240 
241 	return 0;
242 }
243 
244 /*
245  * CW221X Sleep function
246  * The CONFIG register is used for the host MCU to configure the fuel gauge IC.
247  * The default value is 0xF0,SLEEP and RESTART bits are set. To power up the IC,
248  * the host MCU needs to write 0x30 to exit shutdown mode, and then write 0x00
249  * to restart the gauge to enter active mode. To reset the IC, the host MCU needs
250  * to write 0xF0, 0x30 and 0x00 in sequence to this register to complete the restart
251  * procedure. The CW221X will reload relevant parameters and settings and restart SOC
252  * calculation. Note that the SOC may be a different value after reset operation since
253  * it is a brand-new calculation based on the latest battery status.
254  * CONFIG [3:0] is reserved. Don't do any operation with it.
255  */
cw221X_sleep(struct cw_battery * cw_bat)256 static int cw221X_sleep(struct cw_battery *cw_bat)
257 {
258 	unsigned char reg_val = CONFIG_MODE_RESTART;
259 	int ret;
260 
261 	ret = cw_write(cw_bat->client, REG_MODE_CONFIG, &reg_val);
262 	if (ret < 0)
263 		return ret;
264 	msleep(CW_SLEEP_20MS); /* Here delay must >= 20 ms */
265 
266 	reg_val = CONFIG_MODE_SLEEP;
267 	ret = cw_write(cw_bat->client, REG_MODE_CONFIG, &reg_val);
268 	if (ret < 0)
269 		return ret;
270 	msleep(CW_SLEEP_10MS);
271 
272 	return 0;
273 }
274 
275 /*
276  * The 0x00 register is an UNSIGNED 8bit read-only register. Its value is
277  * fixed to 0xA0 in shutdown mode and active mode.
278  */
cw_get_chip_id(struct cw_battery * cw_bat)279 static int cw_get_chip_id(struct cw_battery *cw_bat)
280 {
281 	unsigned char reg_val;
282 	int chip_id;
283 	int ret;
284 
285 	ret = cw_read(cw_bat->client, REG_CHIP_ID, &reg_val);
286 	if (ret < 0)
287 		return ret;
288 
289 	chip_id = reg_val; /* This value must be 0xA0! */
290 	pr_info("CW: chip_id = 0x%x\n", chip_id);
291 	cw_bat->chip_id = chip_id;
292 
293 	return 0;
294 }
295 
296 /*
297  * The VCELL register(0x02 0x03) is an UNSIGNED 14bit read-only register that
298  * updates the battery voltage continuously. Battery voltage is measured between
299  * the VCELL pin and VSS pin, which is the ground reference. A 14bit
300  * sigma-delta A/D converter is used and the voltage resolution is 312.5uV. (0.3125mV is *5/16)
301  */
cw_get_voltage(struct cw_battery * cw_bat)302 static int cw_get_voltage(struct cw_battery *cw_bat)
303 {
304 	unsigned char reg_val[2] = {0, 0};
305 	unsigned int voltage;
306 	int ret;
307 
308 	ret = cw_read_word(cw_bat->client, REG_VCELL_H, reg_val);
309 	if (ret < 0)
310 		return ret;
311 
312 	voltage = (reg_val[0] << 8) + reg_val[1];
313 	voltage = voltage * 5 / 16;
314 	cw_bat->voltage = voltage;
315 
316 	return 0;
317 }
318 
319 /*
320  * The SOC register(0x04 0x05) is an UNSIGNED 16bit read-only register that indicates
321  * the SOC of the battery. The SOC shows in % format, which means how much percent of
322  * the battery's total available capacity is remaining in the battery now. The SOC can
323  * intrinsically adjust itself to cater to the change of battery status,
324  * including load, temperature and aging etc.
325  * The high byte(0x04) contains the SOC in 1% unit which can be directly used if
326  * this resolution is good enough for the application. The low byte(0x05) provides
327  * more accurate fractional part of the SOC and its
328  * LSB is (1/256) %.
329  */
cw_get_capacity(struct cw_battery * cw_bat)330 static int cw_get_capacity(struct cw_battery *cw_bat)
331 {
332 	unsigned char reg_val[2] = {0, 0};
333 	int ui_100 = CW_UI_FULL;
334 	int ui_soc;
335 	int soc_h;
336 	int soc_l;
337 	int ret;
338 
339 	ret = cw_read_word(cw_bat->client, REG_SOC_INT, reg_val);
340 	if (ret < 0)
341 		return ret;
342 	soc_h = reg_val[0];
343 	soc_l = reg_val[1];
344 	ui_soc = ((soc_h * 256 + soc_l) * 100) / (ui_100 * 256);
345 	/* remainder = (((soc_h * 256 + soc_l) * 100 * 100) / (ui_100 * 256)) % 100; */
346 	if (ui_soc >= 100) {
347 		cw_printk("CW221x[%d]: UI_SOC = %d larger 100!\n", __LINE__, ui_soc);
348 		ui_soc = 100;
349 	}
350 	cw_bat->ic_soc_h = soc_h;
351 	cw_bat->ic_soc_l = soc_l;
352 	cw_bat->ui_soc = ui_soc;
353 
354 	return 0;
355 }
356 
357 /*
358  * The TEMP register is an UNSIGNED 8bit read only register.
359  * It reports the real-time battery temperature
360  * measured at TS pin. The scope is from -40 to 87.5 degrees Celsius,
361  * LSB is 0.5 degree Celsius. TEMP(C) = - 40 + Value(0x06 Reg) / 2
362  */
cw_get_temp(struct cw_battery * cw_bat)363 static int cw_get_temp(struct cw_battery *cw_bat)
364 {
365 	unsigned char reg_val;
366 	int temp;
367 	int ret;
368 
369 	ret = cw_read(cw_bat->client, REG_TEMP, &reg_val);
370 	if (ret < 0)
371 		return ret;
372 
373 	temp = (int)reg_val * 10 / 2 - 400;
374 	cw_bat->temp = temp;
375 
376 	return 0;
377 }
378 
379 /* get complement code function, unsigned short must be U16 */
get_complement_code(unsigned short raw_code)380 static long get_complement_code(unsigned short raw_code)
381 {
382 	long complement_code;
383 	int dir;
384 
385 	if (0 != (raw_code & COMPLEMENT_CODE_U16)) {
386 		dir = -1;
387 		raw_code =  (0xFFFF - raw_code) + 1;
388 	} else {
389 		dir = 1;
390 	}
391 	complement_code = (long)raw_code * dir;
392 
393 	return complement_code;
394 }
395 
396 /*
397  * CURRENT is a SIGNED 16bit register(0x0E 0x0F) that reports current A/D converter
398  * result of the voltage across the current sense resistor, 10mohm typical.
399  * The result is stored as a two's complement value to show positive and negative current.
400  * Voltages outside the minimum and maximum register values are reported as the
401  * minimum or maximum value. The register value should be divided by the sense
402  * resistance to convert to amperes. The value of the sense resistor determines
403  * the resolution and the full-scale range of the current readings. The LSB of 0x0F
404  * is (52.4/32768)uV for CW2215 and CW2217. The LSB of 0x0F is (125/32768)uV for CW2218.
405  * The default value is 0x0000, stands for 0mA. 0x7FFF stands for the maximum charging
406  * current and 0x8001 stands for the maximum discharging current.
407  */
cw_get_current(struct cw_battery * cw_bat)408 static int cw_get_current(struct cw_battery *cw_bat)
409 {
410 	unsigned char reg_val[2] = {0, 0};
411 	unsigned short current_reg; /* unsigned short must u16 */
412 	long long cw_current; /* use long long type to guarantee 8 bytes space */
413 	int ret;
414 
415 	ret = cw_read_word(cw_bat->client, REG_CURRENT_H, reg_val);
416 	if (ret < 0)
417 		return ret;
418 
419 	current_reg = (reg_val[0] << 8) + reg_val[1];
420 	cw_current = get_complement_code(current_reg);
421 
422 	if (((cw_bat->fw_version & CW2215_MARK) != 0) || ((cw_bat->fw_version & CW2217_MARK) != 0))
423 		cw_current = cw_current * 1600 / USER_RSENSE;
424 	else if ((cw_bat->fw_version != 0) && ((cw_bat->fw_version & 0xC0) == CW2218_MARK))
425 		cw_current = cw_current * 3815 / USER_RSENSE;
426 	else {
427 		cw_bat->cw_current = 0;
428 		dev_err(cw_bat->dev, "error! cw221x firmware read error!\n");
429 	}
430 
431 	cw_bat->cw_current = cw_current;
432 
433 	return 0;
434 }
435 
436 /*
437  * CYCLECNT is an UNSIGNED 16bit register(0xA4 0xA5) that counts cycle life of the battery.
438  * The LSB of 0xA5 stands for 1/16 cycle. This register will be clear after enters shutdown mode
439  */
cw_get_cycle_count(struct cw_battery * cw_bat)440 static int cw_get_cycle_count(struct cw_battery *cw_bat)
441 {
442 	unsigned char reg_val[2] = {0, 0};
443 	int cycle;
444 	int ret;
445 
446 	ret = cw_read_word(cw_bat->client, REG_CYCLE_H, reg_val);
447 	if (ret < 0)
448 		return ret;
449 
450 	cycle = (reg_val[0] << 8) + reg_val[1];
451 	cw_bat->cycle = cycle / 16;
452 
453 	return 0;
454 }
455 
456 /*
457  * SOH (State of Health) is an UNSIGNED 8bit register(0xA6) that represents the level of
458  * battery aging by tracking battery internal impedance increment. When the device enters
459  * active mode, this register refresh to 0x64 by default. Its range is 0x00 to 0x64,
460  * indicating 0 to 100%. This register will be clear after enters shutdown mode.
461  */
cw_get_soh(struct cw_battery * cw_bat)462 static int cw_get_soh(struct cw_battery *cw_bat)
463 {
464 	int ret;
465 	unsigned char reg_val;
466 	int soh;
467 
468 	ret = cw_read(cw_bat->client, REG_SOH, &reg_val);
469 	if (ret < 0)
470 		return ret;
471 
472 	soh = reg_val;
473 	cw_bat->soh = soh;
474 
475 	return 0;
476 }
477 
478 /*
479  * FW_VERSION register reports the firmware (FW) running in the chip. It is fixed to
480  * 0x00 when the chip is in shutdown mode. When in active mode, Bit [7:6] = '01' stand
481  * for the CW2217, Bit [7:6] = '00' stand for the CW2218 and Bit [7:6] = '10' stand for CW2215.
482  * Bit[5:0] stand for the FW version running in the chip. Note that the FW version is
483  * subject to update and contact sales office for confirmation when necessary.
484  */
cw_get_fw_version(struct cw_battery * cw_bat)485 static int cw_get_fw_version(struct cw_battery *cw_bat)
486 {
487 	int ret;
488 	unsigned char reg_val;
489 	int fw_version;
490 
491 	ret = cw_read(cw_bat->client, REG_FW_VERSION, &reg_val);
492 	if (ret < 0)
493 		return ret;
494 
495 	fw_version = reg_val;
496 	cw_bat->fw_version = fw_version;
497 
498 	return 0;
499 }
500 
cw_update_data(struct cw_battery * cw_bat)501 static int cw_update_data(struct cw_battery *cw_bat)
502 {
503 	int ret = 0;
504 
505 	ret += cw_get_voltage(cw_bat);
506 	ret += cw_get_capacity(cw_bat);
507 	ret += cw_get_temp(cw_bat);
508 	ret += cw_get_current(cw_bat);
509 	ret += cw_get_cycle_count(cw_bat);
510 	ret += cw_get_soh(cw_bat);
511 	cw_printk("vol = %d  current = %ld cap = %d temp = %d\n",
512 		  cw_bat->voltage, cw_bat->cw_current, cw_bat->ui_soc, cw_bat->temp);
513 
514 	return ret;
515 }
516 
cw_init_data(struct cw_battery * cw_bat)517 static int cw_init_data(struct cw_battery *cw_bat)
518 {
519 	int ret = 0;
520 
521 	ret = cw_get_fw_version(cw_bat);
522 	if (ret != 0)
523 		return ret;
524 
525 	ret += cw_get_chip_id(cw_bat);
526 	ret += cw_get_voltage(cw_bat);
527 	ret += cw_get_capacity(cw_bat);
528 	ret += cw_get_temp(cw_bat);
529 	ret += cw_get_current(cw_bat);
530 	ret += cw_get_cycle_count(cw_bat);
531 	ret += cw_get_soh(cw_bat);
532 
533 	cw_printk("chip_id = %d vol = %d  cur = %ld cap = %d temp = %d  fw_version = %d\n",
534 		  cw_bat->chip_id, cw_bat->voltage, cw_bat->cw_current,
535 		  cw_bat->ui_soc, cw_bat->temp, cw_bat->fw_version);
536 
537 	return ret;
538 }
539 
cw221x_parse_properties(struct cw_battery * cw_bat)540 static int cw221x_parse_properties(struct cw_battery *cw_bat)
541 {
542 	struct device *dev = cw_bat->dev;
543 	int length;
544 	int ret;
545 
546 	length = device_property_count_u8(dev, "cellwise,battery-profile");
547 	if (length < 0) {
548 		dev_warn(cw_bat->dev,
549 			 "No battery-profile found, using current flash contents\n");
550 	} else if (length != SIZE_OF_PROFILE) {
551 		dev_err(cw_bat->dev, "battery-profile must be %d bytes\n",
552 			SIZE_OF_PROFILE);
553 		return -EINVAL;
554 	}
555 
556 	cw_bat->bat_profile = devm_kzalloc(dev, length, GFP_KERNEL);
557 	if (!cw_bat->bat_profile)
558 		return -ENOMEM;
559 
560 	ret = device_property_read_u8_array(dev,
561 					    "cellwise,battery-profile",
562 					    cw_bat->bat_profile,
563 					    length);
564 
565 	return ret;
566 }
567 
cw_config_profile_init(struct cw_battery * cw_bat)568 static void cw_config_profile_init(struct cw_battery *cw_bat)
569 {
570 	int i, ret;
571 
572 	ret = cw221x_parse_properties(cw_bat);
573 	if (ret) {
574 		/* update new battery info */
575 		cw_bat->bat_profile = config_profile_info;
576 		cw_printk("the driver profile:\n");
577 	}
578 
579 	for (i = 0; i < SIZE_OF_PROFILE; i++)
580 		cw_printk("[%d]: 0x%x\n", i, cw_bat->bat_profile[i]);
581 }
582 
583 /*CW221X update profile function, Often called during initialization*/
cw_config_start_ic(struct cw_battery * cw_bat)584 static int cw_config_start_ic(struct cw_battery *cw_bat)
585 {
586 	unsigned char reg_val;
587 	int count = 0;
588 	int i, ret;
589 
590 	ret = cw221X_sleep(cw_bat);
591 	if (ret < 0)
592 		return ret;
593 
594 	/* update new battery info */
595 	ret = cw_write_profile(cw_bat->client, cw_bat->bat_profile);
596 	if (ret < 0)
597 		return ret;
598 
599 	cw_printk("the driver profile:\n");
600 	for (i = 0; i < SIZE_OF_PROFILE; i++)
601 		cw_printk("[%d]: 0x%x\n", i, cw_bat->bat_profile[i]);
602 
603 	/* set UPDATE_FLAG AND SOC INTTERRUP VALUE */
604 	reg_val = CONFIG_UPDATE_FLG | GPIO_SOC_IRQ_VALUE;
605 	ret = cw_write(cw_bat->client, REG_SOC_ALERT, &reg_val);
606 	if (ret < 0)
607 		return ret;
608 
609 	/* close all interruptes */
610 	reg_val = 0;
611 	ret = cw_write(cw_bat->client, REG_GPIO_CONFIG, &reg_val);
612 	if (ret < 0)
613 		return ret;
614 
615 	ret = cw221X_active(cw_bat);
616 	if (ret < 0)
617 		return ret;
618 
619 	while (CW_TRUE) {
620 		msleep(CW_SLEEP_100MS);
621 		cw_read(cw_bat->client, REG_IC_STATE, &reg_val);
622 		if (IC_READY_MARK == (reg_val & IC_READY_MARK))
623 			break;
624 		count++;
625 		if (count >= CW_SLEEP_COUNTS) {
626 			cw221X_sleep(cw_bat);
627 			return -1;
628 		}
629 	}
630 
631 	return 0;
632 }
633 
634 /*
635  * Get the cw221X running state
636  * Determine whether the profile needs to be updated
637  */
cw221X_get_state(struct cw_battery * cw_bat)638 static int cw221X_get_state(struct cw_battery *cw_bat)
639 {
640 	int ret;
641 	unsigned char reg_val;
642 	int i;
643 	int reg_profile;
644 
645 	ret = cw_read(cw_bat->client, REG_MODE_CONFIG, &reg_val);
646 	if (ret < 0)
647 		return ret;
648 	if (reg_val != CONFIG_MODE_ACTIVE)
649 		return CW221X_NOT_ACTIVE;
650 
651 	ret = cw_read(cw_bat->client, REG_SOC_ALERT, &reg_val);
652 	if (ret < 0)
653 		return ret;
654 	if (0x00 == (reg_val & CONFIG_UPDATE_FLG))
655 		return CW221X_PROFILE_NOT_READY;
656 
657 	for (i = 0; i < SIZE_OF_PROFILE; i++) {
658 		ret = cw_read(cw_bat->client, (REG_BAT_PROFILE + i), &reg_val);
659 		if (ret < 0)
660 			return ret;
661 		reg_profile = REG_BAT_PROFILE + i;
662 		cw_printk("fuelgauge: 0x%2x = 0x%2x\n", reg_profile, reg_val);
663 		if (cw_bat->bat_profile[i] != reg_val)
664 			break;
665 	}
666 	if (i != SIZE_OF_PROFILE)
667 		return CW221X_PROFILE_NEED_UPDATE;
668 
669 	return 0;
670 }
671 
672 /* CW221X init function, Often called during initialization */
cw_init(struct cw_battery * cw_bat)673 static int cw_init(struct cw_battery *cw_bat)
674 {
675 	int ret;
676 
677 	ret = cw_get_chip_id(cw_bat);
678 	if (ret < 0) {
679 		dev_err(cw_bat->dev, "iic read write error");
680 		return ret;
681 	}
682 	if (cw_bat->chip_id != IC_VCHIP_ID) {
683 		dev_err(cw_bat->dev, "not cw221X\n");
684 		return -1;
685 	}
686 
687 	ret = cw221X_get_state(cw_bat);
688 	if (ret < 0) {
689 		dev_err(cw_bat->dev, "iic read write error");
690 		return ret;
691 	}
692 
693 	if (ret != 0) {
694 		cw_printk("need update profile\n");
695 
696 		ret = cw_config_start_ic(cw_bat);
697 		if (ret < 0)
698 			return ret;
699 	} else
700 		cw_printk("not need update profile\n");
701 	cw_printk("cw221X init success!\n");
702 
703 	return 0;
704 }
705 
cw_bat_work(struct work_struct * work)706 static void cw_bat_work(struct work_struct *work)
707 {
708 	struct delayed_work *delay_work;
709 	struct cw_battery *cw_bat;
710 	static int soc;
711 	int ret;
712 
713 	delay_work = container_of(work,
714 				  struct delayed_work,
715 				  work);
716 	cw_bat = container_of(delay_work,
717 			      struct cw_battery,
718 			      battery_delay_work);
719 
720 	ret = cw_update_data(cw_bat);
721 	if (ret < 0)
722 		dev_err(cw_bat->dev, "i2c read error when update data");
723 	if (cw_bat->ui_soc != soc) {
724 		soc = cw_bat->ui_soc;
725 		power_supply_changed(cw_bat->cw_bat);
726 	}
727 	queue_delayed_work(cw_bat->cwfg_workqueue,
728 			   &cw_bat->battery_delay_work,
729 			   msecs_to_jiffies(queue_delayed_work_time));
730 }
731 
cw_battery_set_property(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)732 static int cw_battery_set_property(struct power_supply *psy,
733 				   enum power_supply_property psp,
734 				   const union power_supply_propval *val)
735 {
736 	/* struct cw_battery *cw_bat = power_supply_get_drvdata(psy); */
737 	int ret = 0;
738 
739 	switch (psp) {
740 	default:
741 		ret = -EINVAL;
742 		break;
743 	}
744 
745 	return ret;
746 }
747 
cw_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)748 static int cw_battery_get_property(struct power_supply *psy,
749 				   enum power_supply_property psp,
750 				   union power_supply_propval *val)
751 {
752 	struct cw_battery *cw_bat = power_supply_get_drvdata(psy);
753 	int ret = 0;
754 
755 	switch (psp) {
756 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
757 		val->intval = cw_bat->cycle;
758 		break;
759 	case POWER_SUPPLY_PROP_CAPACITY:
760 		val->intval = cw_bat->ui_soc;
761 		break;
762 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
763 		if ((cw_bat->ui_soc < 1) && (!power_supply_is_system_supplied()))
764 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
765 		else if (cw_bat->ui_soc <= 20)
766 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
767 		else if (cw_bat->ui_soc <= 70)
768 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
769 		else if (cw_bat->ui_soc <= 90)
770 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
771 		else
772 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
773 		break;
774 	case POWER_SUPPLY_PROP_STATUS:
775 		if (cw_bat->ui_soc == 100 * 1000)
776 			val->intval = POWER_SUPPLY_STATUS_FULL;
777 		else {
778 			if (power_supply_is_system_supplied())
779 				val->intval = POWER_SUPPLY_STATUS_CHARGING;
780 			else
781 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
782 		}
783 		break;
784 	case POWER_SUPPLY_PROP_CHARGE_FULL:
785 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
786 		val->intval = 10 * 1000 * 1000;/* uAh */
787 		break;
788 	case POWER_SUPPLY_PROP_HEALTH:
789 		val->intval = POWER_SUPPLY_HEALTH_GOOD;
790 		break;
791 	case POWER_SUPPLY_PROP_PRESENT:
792 		val->intval = (cw_bat->voltage <= 0) ? 0 : 1;
793 		break;
794 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
795 		cw_get_voltage(cw_bat);
796 		val->intval = cw_bat->voltage * CW_VOL_UNIT;
797 		break;
798 	case POWER_SUPPLY_PROP_CURRENT_NOW:
799 		cw_get_current(cw_bat);
800 		val->intval = cw_bat->cw_current * 1000; /* uA */
801 		break;
802 	case POWER_SUPPLY_PROP_TECHNOLOGY:
803 		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
804 		break;
805 	case POWER_SUPPLY_PROP_TEMP:
806 		val->intval = cw_bat->temp;
807 		break;
808 	default:
809 		ret = -EINVAL;
810 		break;
811 	}
812 
813 	return ret;
814 }
815 
816 static enum power_supply_property cw_battery_properties[] = {
817 	POWER_SUPPLY_PROP_CYCLE_COUNT,
818 	POWER_SUPPLY_PROP_CAPACITY,
819 	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
820 	POWER_SUPPLY_PROP_HEALTH,
821 	POWER_SUPPLY_PROP_PRESENT,
822 	POWER_SUPPLY_PROP_CHARGE_FULL,
823 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
824 	POWER_SUPPLY_PROP_CURRENT_NOW,
825 	POWER_SUPPLY_PROP_TECHNOLOGY,
826 	POWER_SUPPLY_PROP_STATUS,
827 	POWER_SUPPLY_PROP_TEMP,
828 };
829 
cw221X_probe(struct i2c_client * client,const struct i2c_device_id * id)830 static int cw221X_probe(struct i2c_client *client, const struct i2c_device_id *id)
831 {
832 	struct power_supply_config psy_cfg = {0};
833 	struct power_supply_desc *psy_desc;
834 	struct cw_battery *cw_bat;
835 	int loop = 0;
836 	int ret;
837 
838 	cw_bat = devm_kzalloc(&client->dev, sizeof(*cw_bat), GFP_KERNEL);
839 	if (!cw_bat)
840 		return -ENOMEM;
841 
842 	i2c_set_clientdata(client, cw_bat);
843 	cw_bat->client = client;
844 	cw_bat->dev = &client->dev;
845 
846 	dev_dbg(cw_bat->dev, "cw221X driver versions-%d\n", 20220830);
847 	cw_config_profile_init(cw_bat);
848 	ret = cw_init(cw_bat);
849 	while ((loop++ < CW_RETRY_COUNT) && (ret != 0)) {
850 		msleep(CW_SLEEP_200MS);
851 		ret = cw_init(cw_bat);
852 	}
853 	if (ret) {
854 		dev_err(cw_bat->dev, "cw221X init fail!\n");
855 		return ret;
856 	}
857 
858 	ret = cw_init_data(cw_bat);
859 	if (ret) {
860 		dev_err(cw_bat->dev, "cw221X init data fail!\n");
861 		return ret;
862 	}
863 
864 	psy_desc = devm_kzalloc(&client->dev, sizeof(*psy_desc), GFP_KERNEL);
865 	if (!psy_desc)
866 		return -ENOMEM;
867 	psy_cfg.drv_data = cw_bat;
868 	psy_desc->name = CW_PROPERTIES;
869 	psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
870 	psy_desc->properties = cw_battery_properties;
871 	psy_desc->num_properties = ARRAY_SIZE(cw_battery_properties);
872 	psy_desc->get_property = cw_battery_get_property;
873 	psy_desc->set_property = cw_battery_set_property;
874 	cw_bat->cw_bat = devm_power_supply_register(&client->dev, psy_desc, &psy_cfg);
875 	if (IS_ERR(cw_bat->cw_bat)) {
876 		ret = PTR_ERR(cw_bat->cw_bat);
877 		dev_err(cw_bat->dev, "failed to register battery: %d\n", ret);
878 		return ret;
879 	}
880 
881 	cw_bat->cwfg_workqueue = create_singlethread_workqueue("cwfg_gauge");
882 	INIT_DELAYED_WORK(&cw_bat->battery_delay_work, cw_bat_work);
883 	queue_delayed_work(cw_bat->cwfg_workqueue,
884 			   &cw_bat->battery_delay_work,
885 			   msecs_to_jiffies(queue_start_work_time));
886 
887 	cw_printk("cw221X driver probe success!\n");
888 
889 	return 0;
890 }
891 
cw221X_remove(struct i2c_client * client)892 static int cw221X_remove(struct i2c_client *client)
893 {
894 	struct cw_battery *cw_bat = i2c_get_clientdata(client);
895 
896 	cancel_delayed_work_sync(&cw_bat->battery_delay_work);
897 	destroy_workqueue(cw_bat->cwfg_workqueue);
898 	return 0;
899 }
900 
901 #ifdef CONFIG_PM
cw_bat_suspend(struct device * dev)902 static int cw_bat_suspend(struct device *dev)
903 {
904 	struct i2c_client *client = to_i2c_client(dev);
905 	struct cw_battery *cw_bat = i2c_get_clientdata(client);
906 
907 	cancel_delayed_work(&cw_bat->battery_delay_work);
908 	return 0;
909 }
910 
cw_bat_resume(struct device * dev)911 static int cw_bat_resume(struct device *dev)
912 {
913 	struct i2c_client *client = to_i2c_client(dev);
914 	struct cw_battery *cw_bat = i2c_get_clientdata(client);
915 
916 	queue_delayed_work(cw_bat->cwfg_workqueue,
917 			   &cw_bat->battery_delay_work,
918 			   msecs_to_jiffies(20));
919 	return 0;
920 }
921 
922 static const struct dev_pm_ops cw_bat_pm_ops = {
923 	.suspend = cw_bat_suspend,
924 	.resume = cw_bat_resume,
925 };
926 #endif
927 
928 static const struct i2c_device_id cw221X_id_table[] = {
929 	{ CWFG_NAME, 0 },
930 	{ }
931 };
932 MODULE_DEVICE_TABLE(i2c, cw221X_id_table);
933 
934 #ifdef CONFIG_OF
935 static const struct of_device_id cw221X_match_table[] = {
936 	{ .compatible = "cellwise,cw221X", },
937 	{ },
938 };
939 MODULE_DEVICE_TABLE(of, cw221X_match_table);
940 #endif
941 
942 static struct i2c_driver cw221X_driver = {
943 	.driver = {
944 		.name = CWFG_NAME,
945 #ifdef CONFIG_PM
946 		.pm = &cw_bat_pm_ops,
947 #endif
948 		.owner = THIS_MODULE,
949 		.of_match_table = of_match_ptr(cw221X_match_table),
950 	},
951 	.probe = cw221X_probe,
952 	.remove = cw221X_remove,
953 	.id_table = cw221X_id_table,
954 };
955 
956 module_i2c_driver(cw221X_driver);
957 
958 MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
959 MODULE_DESCRIPTION("CW221X FGADC Device Driver V0.1");
960 MODULE_LICENSE("GPL");
961