xref: /OK3568_Linux_fs/u-boot/drivers/power/fuel_gauge/fg_rk817.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2018 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun #include <dm.h>
7*4882a593Smuzhiyun #include <errno.h>
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <malloc.h>
10*4882a593Smuzhiyun #include <fdtdec.h>
11*4882a593Smuzhiyun #include <asm/gpio.h>
12*4882a593Smuzhiyun #include <common.h>
13*4882a593Smuzhiyun #include <power/pmic.h>
14*4882a593Smuzhiyun #include <dm/uclass-internal.h>
15*4882a593Smuzhiyun #include <power/charge_display.h>
16*4882a593Smuzhiyun #include <power/charge_animation.h>
17*4882a593Smuzhiyun #include <power/fuel_gauge.h>
18*4882a593Smuzhiyun #include <power/rk8xx_pmic.h>
19*4882a593Smuzhiyun #include <linux/usb/phy-rockchip-usb2.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun static int dbg_enable = 0;
24*4882a593Smuzhiyun #define DBG(args...) \
25*4882a593Smuzhiyun 	do { \
26*4882a593Smuzhiyun 		if (dbg_enable) { \
27*4882a593Smuzhiyun 			printf(args); \
28*4882a593Smuzhiyun 		} \
29*4882a593Smuzhiyun 	} while (0)
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define DIV(value)	((value) ? (value) : 1)
32*4882a593Smuzhiyun #define ENABLE			0x01
33*4882a593Smuzhiyun #define DISABLE			0x00
34*4882a593Smuzhiyun #define MAX_INTERPOLATE		1000
35*4882a593Smuzhiyun #define MAX_PERCENTAGE		100
36*4882a593Smuzhiyun #define MAX_INT			0x7FFF
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #define ADC_CONFIG0		0x0050
39*4882a593Smuzhiyun #define CUR_ADC_CFG0		0x0051
40*4882a593Smuzhiyun #define CUR_ADC_CFG1		0x0052
41*4882a593Smuzhiyun #define VOL_ADC_CFG0		0x0053
42*4882a593Smuzhiyun #define VOL_ADC_CFG1		0x0054
43*4882a593Smuzhiyun #define ADC_CONFIG1		0x0055
44*4882a593Smuzhiyun #define GG_CON			0x0056
45*4882a593Smuzhiyun #define GG_STS			0x0057
46*4882a593Smuzhiyun #define RELAX_THRE_H		0x0058
47*4882a593Smuzhiyun #define RELAX_THRE_L		0x0059
48*4882a593Smuzhiyun #define RELAX_VOL1_H		0x005a
49*4882a593Smuzhiyun #define RELAX_VOL1_L		0x005b
50*4882a593Smuzhiyun #define RELAX_VOL2_H		0x005c
51*4882a593Smuzhiyun #define RELAX_VOL2_L		0x005d
52*4882a593Smuzhiyun #define RELAX_CUR1_H		0x005e
53*4882a593Smuzhiyun #define RELAX_CUR1_L		0x005f
54*4882a593Smuzhiyun #define RELAX_CUR2_H		0x0060
55*4882a593Smuzhiyun #define RELAX_CUR2_L		0x0061
56*4882a593Smuzhiyun #define OCV_THRE_VOL		0x0062
57*4882a593Smuzhiyun #define OCV_VOL_H		0x0063
58*4882a593Smuzhiyun #define OCV_VOL_L		0x0064
59*4882a593Smuzhiyun #define OCV_VOL0_H		0x0065
60*4882a593Smuzhiyun #define OCV_VOL0_L		0x0066
61*4882a593Smuzhiyun #define OCV_CUR_H		0x0067
62*4882a593Smuzhiyun #define OCV_CUR_L		0x0068
63*4882a593Smuzhiyun #define OCV_CUR0_H		0x0069
64*4882a593Smuzhiyun #define OCV_CUR0_L		0x006a
65*4882a593Smuzhiyun #define PWRON_VOL_H		0x006b
66*4882a593Smuzhiyun #define PWRON_VOL_L		0x006c
67*4882a593Smuzhiyun #define PWRON_CUR_H		0x006d
68*4882a593Smuzhiyun #define PWRON_CUR_L		0x006e
69*4882a593Smuzhiyun #define OFF_CNT			0x006f
70*4882a593Smuzhiyun #define Q_INIT_H3		0x0070
71*4882a593Smuzhiyun #define Q_INIT_H2		0x0071
72*4882a593Smuzhiyun #define Q_INIT_L1		0x0072
73*4882a593Smuzhiyun #define Q_INIT_L0		0x0073
74*4882a593Smuzhiyun #define Q_PRES_H3		0x0074
75*4882a593Smuzhiyun #define Q_PRES_H2		0x0075
76*4882a593Smuzhiyun #define Q_PRES_L1		0x0076
77*4882a593Smuzhiyun #define Q_PRES_L0		0x0077
78*4882a593Smuzhiyun #define BAT_VOL_H		0x0078
79*4882a593Smuzhiyun #define BAT_VOL_L		0x0079
80*4882a593Smuzhiyun #define BAT_CUR_H		0x007a
81*4882a593Smuzhiyun #define BAT_CUR			0x007b
82*4882a593Smuzhiyun #define BAT_TS_H		0x007c
83*4882a593Smuzhiyun #define BAT_TS_L		0x007d
84*4882a593Smuzhiyun #define USB_VOL_H		0x007e
85*4882a593Smuzhiyun #define USB_VOL_L		0x007f
86*4882a593Smuzhiyun #define SYS_VOL_H		0x0080
87*4882a593Smuzhiyun #define SYS_VOL_L		0x0081
88*4882a593Smuzhiyun #define Q_MAX_H3		0x0082
89*4882a593Smuzhiyun #define Q_MAX_H2		0x0083
90*4882a593Smuzhiyun #define Q_MAX_L1		0x0084
91*4882a593Smuzhiyun #define Q_MAX_L0		0x0085
92*4882a593Smuzhiyun #define Q_TERM_H3		0x0086
93*4882a593Smuzhiyun #define Q_TERM_H2		0x0087
94*4882a593Smuzhiyun #define Q_TERM_L1		0x0088
95*4882a593Smuzhiyun #define Q_TERM_L0		0x0089
96*4882a593Smuzhiyun #define Q_OCV_H3		0x008a
97*4882a593Smuzhiyun #define Q_OCV_H2		0x008b
98*4882a593Smuzhiyun #define Q_OCV_L1		0x008c
99*4882a593Smuzhiyun #define Q_OCV_L0		0x008d
100*4882a593Smuzhiyun #define OCV_CNT			0x008e
101*4882a593Smuzhiyun #define SLEEP_CON_SAMP_CUR_H	0x008f
102*4882a593Smuzhiyun #define SLEEP_CON_SAMP_CUR	0x0090
103*4882a593Smuzhiyun #define CAL_OFFSET_H		0x0091
104*4882a593Smuzhiyun #define CAL_OFFSET_L		0x0092
105*4882a593Smuzhiyun #define VCALIB0_H		0x0093
106*4882a593Smuzhiyun #define VCALIB0_L		0x0094
107*4882a593Smuzhiyun #define VCALIB1_H		0x0095
108*4882a593Smuzhiyun #define VCALIB1_L		0x0096
109*4882a593Smuzhiyun #define IOFFSET_H		0x0097
110*4882a593Smuzhiyun #define IOFFSET_L		0x0098
111*4882a593Smuzhiyun #define BAT_R0			0x0099
112*4882a593Smuzhiyun #define SOC_REG0		0x009a
113*4882a593Smuzhiyun #define SOC_REG1		0x009b
114*4882a593Smuzhiyun #define SOC_REG2		0x009c
115*4882a593Smuzhiyun #define REMAIN_CAP_REG0		0x9d
116*4882a593Smuzhiyun #define REMAIN_CAP_REG1		0x9e
117*4882a593Smuzhiyun #define REMAIN_CAP_REG2		0x9f
118*4882a593Smuzhiyun #define NEW_FCC_REG0		0x00a0
119*4882a593Smuzhiyun #define NEW_FCC_REG1		0x00a1
120*4882a593Smuzhiyun #define NEW_FCC_REG2		0x00a2
121*4882a593Smuzhiyun #define DRV_VERSION		0x00a3
122*4882a593Smuzhiyun #define DATA7			0x00a4
123*4882a593Smuzhiyun #define FG_INIT			0x00a5
124*4882a593Smuzhiyun #define HALT_CNT_REG		0x00a6
125*4882a593Smuzhiyun #define DATA10			0x00a7
126*4882a593Smuzhiyun #define DATA11			0x00a8
127*4882a593Smuzhiyun #define VOL_ADC_B3		0x00a9
128*4882a593Smuzhiyun #define VOL_ADC_B2		0x00aa
129*4882a593Smuzhiyun #define VOL_ADC_B1		0x00ab
130*4882a593Smuzhiyun #define VOL_ADC_B_7_0		0x00ac
131*4882a593Smuzhiyun #define CUR_ADC_K3		0x00ad
132*4882a593Smuzhiyun #define CUR_ADC_K2		0x00ae
133*4882a593Smuzhiyun #define CUR_ADC_K1		0x00af
134*4882a593Smuzhiyun #define CUR_ADC_K0		0x00b0
135*4882a593Smuzhiyun #define PMIC_CHRG_STS		0x00eb
136*4882a593Smuzhiyun #define BAT_DISCHRG		0x00ec
137*4882a593Smuzhiyun #define BAT_CON			BIT(4)
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #define USB_CTRL_REG		0x00E5
140*4882a593Smuzhiyun #define PMIC_SYS_STS		0x00f0
141*4882a593Smuzhiyun #define PLUG_IN_STS		BIT(6)
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun #define CHRG_TERM_DSOC		90
144*4882a593Smuzhiyun #define CHRG_TERM_K		650
145*4882a593Smuzhiyun #define CHRG_FULL_K		400
146*4882a593Smuzhiyun #define CHARGE_FINISH		(0x04 << 4)
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun /* CALI PARAM */
149*4882a593Smuzhiyun #define FINISH_CALI_CURR	1500
150*4882a593Smuzhiyun #define TERM_CALI_CURR		600
151*4882a593Smuzhiyun #define VIRTUAL_POWER_VOL	4200
152*4882a593Smuzhiyun #define VIRTUAL_POWER_CUR	1000
153*4882a593Smuzhiyun #define VIRTUAL_POWER_SOC	66
154*4882a593Smuzhiyun #define SECONDS(n)		((n) * 1000)
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /* CHRG_CTRL_REG */
157*4882a593Smuzhiyun #define ILIM_450MA		(0x00)
158*4882a593Smuzhiyun #define ILIM_2000MA		(0x07)
159*4882a593Smuzhiyun #define ILIM_1500MA		(0x03)
160*4882a593Smuzhiyun #define VLIM_4500MV		(0x50)
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun /* sample resistor and division */
163*4882a593Smuzhiyun #define SAMPLE_RES_10mR		10
164*4882a593Smuzhiyun #define SAMPLE_RES_20mR		20
165*4882a593Smuzhiyun #define SAMPLE_RES_DIV1		1
166*4882a593Smuzhiyun #define SAMPLE_RES_DIV2		2
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun #define CHRG_CT_EN		BIT(1)
169*4882a593Smuzhiyun #define MIN_FCC			500
170*4882a593Smuzhiyun #define CAP_INVALID		BIT(7)
171*4882a593Smuzhiyun #define DIS_ILIM_EN		BIT(3)
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun /* USB_CTRL_REG */
174*4882a593Smuzhiyun #define INPUT_CUR_MSK		0x0f
175*4882a593Smuzhiyun #define INPUT_VOL_MSK		0xf0
176*4882a593Smuzhiyun #define VOL_OUPUT_INSTANT_MODE	0x02
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun #define ADC_TO_CURRENT(adc_value, samp_res)	\
179*4882a593Smuzhiyun 	(adc_value * 172 / 1000 / samp_res)
180*4882a593Smuzhiyun #define CURRENT_TO_ADC(current, samp_res)	\
181*4882a593Smuzhiyun 	(current * 1000 * samp_res / 172)
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun #define ADC_TO_CAPACITY(adc_value, samp_res)	\
184*4882a593Smuzhiyun 	(adc_value / 1000 * 172 / 3600 / samp_res)
185*4882a593Smuzhiyun #define CAPACITY_TO_ADC(capacity, samp_res)	\
186*4882a593Smuzhiyun 	(capacity * samp_res * 3600 / 172 * 1000)
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun #define ADC_TO_CAPACITY_UAH(adc_value, samp_res)	\
189*4882a593Smuzhiyun 	(adc_value / 3600 * 172 / samp_res)
190*4882a593Smuzhiyun #define ADC_TO_CAPACITY_MAH(adc_value, samp_res)	\
191*4882a593Smuzhiyun 	(adc_value / 1000 * 172 / 3600 / samp_res)
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun /* charger type definition */
194*4882a593Smuzhiyun enum charger_type {
195*4882a593Smuzhiyun 	NO_CHARGER = 0,
196*4882a593Smuzhiyun 	USB_CHARGER,
197*4882a593Smuzhiyun 	AC_CHARGER,
198*4882a593Smuzhiyun 	DC_CHARGER,
199*4882a593Smuzhiyun 	UNDEF_CHARGER,
200*4882a593Smuzhiyun };
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun enum power_supply_type {
203*4882a593Smuzhiyun 	POWER_SUPPLY_TYPE_UNKNOWN = 0,
204*4882a593Smuzhiyun 	POWER_SUPPLY_TYPE_USB,		/* Standard Downstream Port */
205*4882a593Smuzhiyun 	POWER_SUPPLY_TYPE_USB_DCP,	/* Dedicated Charging Port */
206*4882a593Smuzhiyun 	POWER_SUPPLY_TYPE_USB_CDP,	/* Charging Downstream Port */
207*4882a593Smuzhiyun 	POWER_SUPPLY_TYPE_USB_FLOATING,	/* DCP without shorting D+/D- */
208*4882a593Smuzhiyun };
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun struct rk817_battery_device {
211*4882a593Smuzhiyun 	struct udevice *dev;
212*4882a593Smuzhiyun 	int				res_div;
213*4882a593Smuzhiyun 	bool				is_first_power_on;
214*4882a593Smuzhiyun 	bool				is_initialized;
215*4882a593Smuzhiyun 	bool				bat_first_power_on;
216*4882a593Smuzhiyun 	int				current_avg;
217*4882a593Smuzhiyun 	int				current_pwron;
218*4882a593Smuzhiyun 	int				voltage_usb;
219*4882a593Smuzhiyun 	int				voltage_sys;
220*4882a593Smuzhiyun 	int				voltage_avg;
221*4882a593Smuzhiyun 	int				voltage_k;/* VCALIB0 VCALIB1 */
222*4882a593Smuzhiyun 	int				voltage_b;
223*4882a593Smuzhiyun 	u32				remain_cap;
224*4882a593Smuzhiyun 	int				design_cap;
225*4882a593Smuzhiyun 	int				nac;
226*4882a593Smuzhiyun 	int				fcc;
227*4882a593Smuzhiyun 	int				qmax;
228*4882a593Smuzhiyun 	int				dsoc;
229*4882a593Smuzhiyun 	int				rsoc;
230*4882a593Smuzhiyun 	int				pwron_voltage;
231*4882a593Smuzhiyun 	int				sm_linek;
232*4882a593Smuzhiyun 	int				sm_old_cap;
233*4882a593Smuzhiyun 	int				calc_dsoc;
234*4882a593Smuzhiyun 	int				calc_rsoc;
235*4882a593Smuzhiyun 	int				sm_chrg_dsoc;
236*4882a593Smuzhiyun 	u8				halt_cnt;
237*4882a593Smuzhiyun 	bool				is_halt;
238*4882a593Smuzhiyun 	int				dbg_pwr_dsoc;
239*4882a593Smuzhiyun 	int				dbg_pwr_rsoc;
240*4882a593Smuzhiyun 	int				dbg_pwr_vol;
241*4882a593Smuzhiyun 	int				dbg_meet_soc;
242*4882a593Smuzhiyun 	int				dbg_calc_dsoc;
243*4882a593Smuzhiyun 	int				dbg_calc_rsoc;
244*4882a593Smuzhiyun 	int				adc_allow_update;
245*4882a593Smuzhiyun 	int				pwroff_min;
246*4882a593Smuzhiyun 	int				chrg_cur_input;
247*4882a593Smuzhiyun 	u32				*ocv_table;
248*4882a593Smuzhiyun 	int				ocv_size;
249*4882a593Smuzhiyun 	u32				design_capacity;
250*4882a593Smuzhiyun 	u32				max_soc_offset;
251*4882a593Smuzhiyun 	u32				virtual_power;
252*4882a593Smuzhiyun 	u32				chrg_type;
253*4882a593Smuzhiyun 	ulong				finish_chrg_base;
254*4882a593Smuzhiyun 	ulong				term_sig_base;
255*4882a593Smuzhiyun 	int				sm_meet_soc;
256*4882a593Smuzhiyun 	u32				bat_res_up;
257*4882a593Smuzhiyun 	u32				bat_res_down;
258*4882a593Smuzhiyun 	u32				variant;
259*4882a593Smuzhiyun 	int				drv_version;
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun 
interpolate(int value,u32 * table,int size)262*4882a593Smuzhiyun static u32 interpolate(int value, u32 *table, int size)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	u8 i;
265*4882a593Smuzhiyun 	u16 d;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	for (i = 0; i < size; i++) {
268*4882a593Smuzhiyun 		if (value < table[i])
269*4882a593Smuzhiyun 			break;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	if ((i > 0) && (i < size)) {
273*4882a593Smuzhiyun 		d = (value - table[i - 1]) * (MAX_INTERPOLATE / (size - 1));
274*4882a593Smuzhiyun 		d /= table[i] - table[i - 1];
275*4882a593Smuzhiyun 		d = d + (i - 1) * (MAX_INTERPOLATE / (size - 1));
276*4882a593Smuzhiyun 	} else {
277*4882a593Smuzhiyun 		d = i * ((MAX_INTERPOLATE + size / 2) / size);
278*4882a593Smuzhiyun 	}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	if (d > 1000)
281*4882a593Smuzhiyun 		d = 1000;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	return d;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /* (a * b) / c */
ab_div_c(u32 a,u32 b,u32 c)287*4882a593Smuzhiyun static int32_t ab_div_c(u32 a, u32 b, u32 c)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	bool sign;
290*4882a593Smuzhiyun 	u32 ans = MAX_INT;
291*4882a593Smuzhiyun 	int tmp;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	sign = ((((a ^ b) ^ c) & 0x80000000) != 0);
294*4882a593Smuzhiyun 	if (c != 0) {
295*4882a593Smuzhiyun 		if (sign)
296*4882a593Smuzhiyun 			c = -c;
297*4882a593Smuzhiyun 		tmp = (a * b + (c >> 1)) / c;
298*4882a593Smuzhiyun 		if (tmp < MAX_INT)
299*4882a593Smuzhiyun 			ans = tmp;
300*4882a593Smuzhiyun 	}
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	if (sign)
303*4882a593Smuzhiyun 		ans = -ans;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	return ans;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
rk817_bat_read(struct rk817_battery_device * battery,u8 reg)308*4882a593Smuzhiyun static int rk817_bat_read(struct rk817_battery_device *battery, u8 reg)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	return pmic_reg_read(battery->dev->parent, reg);
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun 
rk817_bat_write(struct rk817_battery_device * battery,u8 reg,u8 buf)313*4882a593Smuzhiyun static void rk817_bat_write(struct rk817_battery_device *battery,
314*4882a593Smuzhiyun 			    u8 reg, u8 buf)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	pmic_reg_write(battery->dev->parent, reg, buf);
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
rk817_bat_get_vaclib0(struct rk817_battery_device * battery)319*4882a593Smuzhiyun static int rk817_bat_get_vaclib0(struct rk817_battery_device *battery)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	int vcalib_value = 0;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	vcalib_value |= rk817_bat_read(battery, VCALIB0_H) << 8;
324*4882a593Smuzhiyun 	vcalib_value |= rk817_bat_read(battery, VCALIB0_L);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	return vcalib_value;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
rk817_bat_get_vaclib1(struct rk817_battery_device * battery)329*4882a593Smuzhiyun static int rk817_bat_get_vaclib1(struct rk817_battery_device *battery)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	int vcalib_value = 0;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	vcalib_value |= rk817_bat_read(battery, VCALIB1_H) << 8;
334*4882a593Smuzhiyun 	vcalib_value |= rk817_bat_read(battery, VCALIB1_L);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	return vcalib_value;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun 
rk817_bat_init_voltage_kb(struct rk817_battery_device * battery)339*4882a593Smuzhiyun static void rk817_bat_init_voltage_kb(struct rk817_battery_device *battery)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	int vcalib0, vcalib1;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	vcalib0 = rk817_bat_get_vaclib0(battery);
344*4882a593Smuzhiyun 	vcalib1 =  rk817_bat_get_vaclib1(battery);
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	if (battery->variant == RK809_ID) {
347*4882a593Smuzhiyun 		battery->voltage_k = (1050 - 600) * 1000 / DIV(vcalib1 - vcalib0);
348*4882a593Smuzhiyun 		battery->voltage_b = 1050 - (battery->voltage_k * vcalib1) / 1000;
349*4882a593Smuzhiyun 	} else {
350*4882a593Smuzhiyun 		battery->voltage_k = (4025 - 2300) * 1000 / DIV(vcalib1 - vcalib0);
351*4882a593Smuzhiyun 		battery->voltage_b = 4025 - (battery->voltage_k * vcalib1) / 1000;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun /* power on battery voltage */
rk817_bat_get_pwron_voltage(struct rk817_battery_device * battery)356*4882a593Smuzhiyun static int rk817_bat_get_pwron_voltage(struct rk817_battery_device *battery)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	int vol, val = 0, vol_temp;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	val = rk817_bat_read(battery, PWRON_VOL_H) << 8;
361*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, PWRON_VOL_L);
362*4882a593Smuzhiyun 	vol = battery->voltage_k * val / 1000 + battery->voltage_b;
363*4882a593Smuzhiyun 	if (battery->variant == RK809_ID) {
364*4882a593Smuzhiyun 		vol_temp = (vol * battery->bat_res_up / battery->bat_res_down + vol);
365*4882a593Smuzhiyun 		vol = vol_temp;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	return vol;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun 
rk817_bat_get_USB_voltage(struct rk817_battery_device * battery)371*4882a593Smuzhiyun static int rk817_bat_get_USB_voltage(struct rk817_battery_device *battery)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun 	int vol, val = 0, vol_temp;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	val = rk817_bat_read(battery, USB_VOL_L) << 0;
376*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, USB_VOL_H) << 8;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	vol = (battery->voltage_k * val / 1000 + battery->voltage_b) * 60 / 46;
379*4882a593Smuzhiyun 	if (battery->variant == RK809_ID) {
380*4882a593Smuzhiyun 		vol_temp = vol * battery->bat_res_up / battery->bat_res_down + vol;
381*4882a593Smuzhiyun 		vol = vol_temp;
382*4882a593Smuzhiyun 	}
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	return vol;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
rk817_bat_get_sys_voltage(struct rk817_battery_device * battery)387*4882a593Smuzhiyun static int rk817_bat_get_sys_voltage(struct rk817_battery_device *battery)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	int vol, val = 0, vol_temp;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	val = rk817_bat_read(battery, SYS_VOL_H) << 8;
392*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, SYS_VOL_L) << 0;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	vol = (battery->voltage_k * val / 1000 + battery->voltage_b) * 60 / 46;
395*4882a593Smuzhiyun 	if (battery->variant == RK809_ID) {
396*4882a593Smuzhiyun 		vol_temp = vol * battery->bat_res_up / battery->bat_res_down + vol;
397*4882a593Smuzhiyun 		vol = vol_temp;
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	return vol;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
rk817_bat_get_battery_voltage(struct rk817_battery_device * battery)403*4882a593Smuzhiyun static int rk817_bat_get_battery_voltage(struct rk817_battery_device *battery)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun 	int vol, val = 0, vol_temp;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	val = rk817_bat_read(battery, BAT_VOL_H) << 8;
408*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, BAT_VOL_L) << 0;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	vol = battery->voltage_k * val / 1000 + battery->voltage_b;
411*4882a593Smuzhiyun 	if (battery->variant == RK809_ID) {
412*4882a593Smuzhiyun 		vol_temp = (vol * battery->bat_res_up / battery->bat_res_down + vol);
413*4882a593Smuzhiyun 		vol = vol_temp;
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 	return vol;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
rk817_bat_get_avg_current(struct rk817_battery_device * battery)418*4882a593Smuzhiyun static int rk817_bat_get_avg_current(struct rk817_battery_device *battery)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	int cur, val = 0;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, BAT_CUR);
423*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, BAT_CUR_H) << 8;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	if (val & 0x8000)
426*4882a593Smuzhiyun 		val -= 0x10000;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	cur = ADC_TO_CURRENT(val, battery->res_div);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	return cur;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
rk817_bat_get_pwron_current(struct rk817_battery_device * battery)433*4882a593Smuzhiyun static int rk817_bat_get_pwron_current(struct rk817_battery_device *battery)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun 	int cur, val = 0;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, PWRON_CUR_L);
438*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, PWRON_CUR_H) << 8;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	if (val & 0x8000)
441*4882a593Smuzhiyun 		val -= 0x10000;
442*4882a593Smuzhiyun 	cur = ADC_TO_CURRENT(val, battery->res_div);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	return cur;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
rk817_bat_calibration(struct rk817_battery_device * battery)447*4882a593Smuzhiyun static void rk817_bat_calibration(struct rk817_battery_device *battery)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	int  ioffset_value = 0;
450*4882a593Smuzhiyun 	u8  buf = 0;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	if (rk817_bat_read(battery, ADC_CONFIG1) & 0x80) {
453*4882a593Smuzhiyun 		ioffset_value = rk817_bat_read(battery, IOFFSET_H) << 8;
454*4882a593Smuzhiyun 		ioffset_value |= rk817_bat_read(battery, IOFFSET_L);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 		buf = (ioffset_value >> 8) & 0xff;
457*4882a593Smuzhiyun 		rk817_bat_write(battery, CAL_OFFSET_H, buf);
458*4882a593Smuzhiyun 		buf = (ioffset_value >> 0) & 0xff;
459*4882a593Smuzhiyun 		rk817_bat_write(battery, CAL_OFFSET_L, buf);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 		rk817_bat_init_voltage_kb(battery);
462*4882a593Smuzhiyun 		rk817_bat_write(battery, ADC_CONFIG1, 0x80);
463*4882a593Smuzhiyun 	}
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun static int rk817_bat_get_rsoc(struct rk817_battery_device *battery);
467*4882a593Smuzhiyun 
rk817_bat_init_coulomb_cap(struct rk817_battery_device * battery,u32 capacity)468*4882a593Smuzhiyun static void rk817_bat_init_coulomb_cap(struct rk817_battery_device *battery,
469*4882a593Smuzhiyun 				       u32 capacity)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun 	u8 buf;
472*4882a593Smuzhiyun 	u32 cap;
473*4882a593Smuzhiyun 	u32 val;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	cap = CAPACITY_TO_ADC(capacity, battery->res_div);
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	do {
478*4882a593Smuzhiyun 		buf = (cap >> 24) & 0xff;
479*4882a593Smuzhiyun 		rk817_bat_write(battery, Q_INIT_H3, buf);
480*4882a593Smuzhiyun 		buf = (cap >> 16) & 0xff;
481*4882a593Smuzhiyun 		rk817_bat_write(battery, Q_INIT_H2, buf);
482*4882a593Smuzhiyun 		buf = (cap >> 8) & 0xff;
483*4882a593Smuzhiyun 		rk817_bat_write(battery, Q_INIT_L1, buf);
484*4882a593Smuzhiyun 		buf = (cap >> 0) & 0xff;
485*4882a593Smuzhiyun 		rk817_bat_write(battery, Q_INIT_L0, buf);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 		val = rk817_bat_read(battery, Q_INIT_H3) << 24;
488*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_INIT_H2) << 16;
489*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_INIT_L1) << 8;
490*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_INIT_L0) << 0;
491*4882a593Smuzhiyun 	} while (cap != val);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	battery->rsoc = rk817_bat_get_rsoc(battery);
494*4882a593Smuzhiyun 	battery->remain_cap = capacity * 1000;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun 
rk817_bat_remain_cap_is_valid(struct rk817_battery_device * battery)497*4882a593Smuzhiyun static bool rk817_bat_remain_cap_is_valid(struct rk817_battery_device *battery)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun 	return !(rk817_bat_read(battery, Q_PRES_H3) & CAP_INVALID);
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
rk817_bat_get_capacity_uah(struct rk817_battery_device * battery)502*4882a593Smuzhiyun static u32 rk817_bat_get_capacity_uah(struct rk817_battery_device *battery)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	u32 val = 0, capacity = 0;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	if (rk817_bat_remain_cap_is_valid(battery)) {
507*4882a593Smuzhiyun 		val = rk817_bat_read(battery, Q_PRES_H3) << 24;
508*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_PRES_H2) << 16;
509*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_PRES_L1) << 8;
510*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_PRES_L0) << 0;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 		capacity = ADC_TO_CAPACITY_UAH(val, battery->res_div);
513*4882a593Smuzhiyun 	}
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	return  capacity;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun 
rk817_bat_get_capacity_mah(struct rk817_battery_device * battery)518*4882a593Smuzhiyun static u32 rk817_bat_get_capacity_mah(struct rk817_battery_device *battery)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun 	u32 val, capacity = 0;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	if (rk817_bat_remain_cap_is_valid(battery)) {
523*4882a593Smuzhiyun 		val = rk817_bat_read(battery, Q_PRES_H3) << 24;
524*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_PRES_H2) << 16;
525*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_PRES_L1) << 8;
526*4882a593Smuzhiyun 		val |= rk817_bat_read(battery, Q_PRES_L0) << 0;
527*4882a593Smuzhiyun 		capacity = ADC_TO_CAPACITY(val, battery->res_div);
528*4882a593Smuzhiyun 	}
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	return  capacity;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
rk817_bat_save_cap(struct rk817_battery_device * battery,int capacity)533*4882a593Smuzhiyun static void rk817_bat_save_cap(struct rk817_battery_device *battery,
534*4882a593Smuzhiyun 			       int capacity)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun 	u8 buf;
537*4882a593Smuzhiyun 	static u32 old_cap;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	if (capacity >= battery->qmax)
540*4882a593Smuzhiyun 		capacity = battery->qmax;
541*4882a593Smuzhiyun 	if (capacity <= 0)
542*4882a593Smuzhiyun 		capacity = 0;
543*4882a593Smuzhiyun 	if (old_cap == capacity)
544*4882a593Smuzhiyun 		return;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	old_cap = capacity;
547*4882a593Smuzhiyun 	buf = (capacity >> 16) & 0xff;
548*4882a593Smuzhiyun 	rk817_bat_write(battery, REMAIN_CAP_REG2, buf);
549*4882a593Smuzhiyun 	buf = (capacity >> 8) & 0xff;
550*4882a593Smuzhiyun 	rk817_bat_write(battery, REMAIN_CAP_REG1, buf);
551*4882a593Smuzhiyun 	buf = (capacity >> 0) & 0xff;
552*4882a593Smuzhiyun 	rk817_bat_write(battery, REMAIN_CAP_REG0, buf);
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun 
rk817_bat_get_rsoc(struct rk817_battery_device * battery)555*4882a593Smuzhiyun static int rk817_bat_get_rsoc(struct rk817_battery_device *battery)
556*4882a593Smuzhiyun {
557*4882a593Smuzhiyun 	int remain_cap;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	remain_cap = rk817_bat_get_capacity_uah(battery);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	return remain_cap * 100 / DIV(battery->fcc);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
rk817_bat_vol_to_soc(struct rk817_battery_device * battery,int voltage)564*4882a593Smuzhiyun static int rk817_bat_vol_to_soc(struct rk817_battery_device *battery,
565*4882a593Smuzhiyun 				int voltage)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun 	u32 *ocv_table, temp;
568*4882a593Smuzhiyun 	int ocv_size, ocv_soc;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	ocv_table = battery->ocv_table;
571*4882a593Smuzhiyun 	ocv_size = battery->ocv_size;
572*4882a593Smuzhiyun 	temp = interpolate(voltage, ocv_table, ocv_size);
573*4882a593Smuzhiyun 	ocv_soc = ab_div_c(temp, MAX_PERCENTAGE, MAX_INTERPOLATE);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	return ocv_soc;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun 
rk817_bat_vol_to_cap(struct rk817_battery_device * battery,int voltage)578*4882a593Smuzhiyun static int rk817_bat_vol_to_cap(struct rk817_battery_device *battery,
579*4882a593Smuzhiyun 				int voltage)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun 	u32 *ocv_table, temp;
582*4882a593Smuzhiyun 	int ocv_size, capacity;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	ocv_table = battery->ocv_table;
585*4882a593Smuzhiyun 	ocv_size = battery->ocv_size;
586*4882a593Smuzhiyun 	temp = interpolate(voltage, ocv_table, ocv_size);
587*4882a593Smuzhiyun 	capacity = ab_div_c(temp, battery->fcc, MAX_INTERPOLATE);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	return capacity;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun 
rk817_bat_save_dsoc(struct rk817_battery_device * battery,int save_soc)592*4882a593Smuzhiyun static void rk817_bat_save_dsoc(struct rk817_battery_device *battery,
593*4882a593Smuzhiyun 				int save_soc)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun 	static int last_soc = -1;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	if (last_soc != save_soc) {
598*4882a593Smuzhiyun 		rk817_bat_write(battery, SOC_REG0, save_soc & 0xff);
599*4882a593Smuzhiyun 		rk817_bat_write(battery, SOC_REG1, (save_soc >> 8) & 0xff);
600*4882a593Smuzhiyun 		rk817_bat_write(battery, SOC_REG2, (save_soc >> 16) & 0xff);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 		last_soc = save_soc;
603*4882a593Smuzhiyun 	}
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun 
rk817_bat_get_prev_dsoc(struct rk817_battery_device * battery)606*4882a593Smuzhiyun static int rk817_bat_get_prev_dsoc(struct rk817_battery_device *battery)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun 	int value;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	value = rk817_bat_read(battery, SOC_REG0);
611*4882a593Smuzhiyun 	value |= rk817_bat_read(battery, SOC_REG1) << 8;
612*4882a593Smuzhiyun 	value |= rk817_bat_read(battery, SOC_REG2) << 16;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	return value;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun 
rk817_bat_get_prev_cap(struct rk817_battery_device * battery)617*4882a593Smuzhiyun static int rk817_bat_get_prev_cap(struct rk817_battery_device *battery)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun 	int val = 0;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	val = rk817_bat_read(battery, REMAIN_CAP_REG2) << 16;
622*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, REMAIN_CAP_REG1) << 8;
623*4882a593Smuzhiyun 	val |= rk817_bat_read(battery, REMAIN_CAP_REG0) << 0;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	return val;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun 
rk817_bat_gas_gaugle_enable(struct rk817_battery_device * battery)628*4882a593Smuzhiyun static void rk817_bat_gas_gaugle_enable(struct rk817_battery_device *battery)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun 	int value;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	value = rk817_bat_read(battery, ADC_CONFIG0);
633*4882a593Smuzhiyun 	rk817_bat_write(battery, ADC_CONFIG0, value | 0x80);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun 
is_rk817_bat_first_pwron(struct rk817_battery_device * battery)636*4882a593Smuzhiyun static bool is_rk817_bat_first_pwron(struct rk817_battery_device *battery)
637*4882a593Smuzhiyun {
638*4882a593Smuzhiyun 	int value;
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	value = rk817_bat_read(battery, GG_STS);
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	if (value & BAT_CON) {
643*4882a593Smuzhiyun 		rk817_bat_write(battery, GG_STS, value & (~BAT_CON));
644*4882a593Smuzhiyun 		return true;
645*4882a593Smuzhiyun 	}
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	return false;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun 
rk817_bat_get_off_count(struct rk817_battery_device * battery)650*4882a593Smuzhiyun static int rk817_bat_get_off_count(struct rk817_battery_device *battery)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun 	int value;
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	value = rk817_bat_read(battery, OFF_CNT);
655*4882a593Smuzhiyun 	rk817_bat_write(battery, OFF_CNT, 0x00);
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	return value;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun 
rk817_bat_update_qmax(struct rk817_battery_device * battery,u32 capacity)660*4882a593Smuzhiyun static void rk817_bat_update_qmax(struct rk817_battery_device *battery,
661*4882a593Smuzhiyun 				  u32 capacity)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun 	u8 buf;
664*4882a593Smuzhiyun 	u32 cap_adc;
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	cap_adc = CAPACITY_TO_ADC(capacity, battery->res_div);
667*4882a593Smuzhiyun 	buf = (cap_adc >> 24) & 0xff;
668*4882a593Smuzhiyun 	rk817_bat_write(battery, Q_MAX_H3, buf);
669*4882a593Smuzhiyun 	buf = (cap_adc >> 16) & 0xff;
670*4882a593Smuzhiyun 	rk817_bat_write(battery, Q_MAX_H2, buf);
671*4882a593Smuzhiyun 	buf = (cap_adc >> 8) & 0xff;
672*4882a593Smuzhiyun 	rk817_bat_write(battery, Q_MAX_L1, buf);
673*4882a593Smuzhiyun 	buf = (cap_adc >> 0) & 0xff;
674*4882a593Smuzhiyun 	rk817_bat_write(battery, Q_MAX_L0, buf);
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	battery->qmax = capacity;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun 
rk817_bat_save_fcc(struct rk817_battery_device * battery,int fcc)679*4882a593Smuzhiyun static void rk817_bat_save_fcc(struct rk817_battery_device *battery, int  fcc)
680*4882a593Smuzhiyun {
681*4882a593Smuzhiyun 	u8 buf;
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	buf = (fcc >> 16) & 0xff;
684*4882a593Smuzhiyun 	rk817_bat_write(battery, NEW_FCC_REG2, buf);
685*4882a593Smuzhiyun 	buf = (fcc >> 8) & 0xff;
686*4882a593Smuzhiyun 	rk817_bat_write(battery, NEW_FCC_REG1, buf);
687*4882a593Smuzhiyun 	buf = (fcc >> 0) & 0xff;
688*4882a593Smuzhiyun 	rk817_bat_write(battery, NEW_FCC_REG0, buf);
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun 
rk817_bat_first_pwron(struct rk817_battery_device * battery)691*4882a593Smuzhiyun static void rk817_bat_first_pwron(struct rk817_battery_device *battery)
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun 	battery->rsoc =
694*4882a593Smuzhiyun 		rk817_bat_vol_to_soc(battery,
695*4882a593Smuzhiyun 				     battery->pwron_voltage) * 1000;/* uAH */
696*4882a593Smuzhiyun 	battery->dsoc = battery->rsoc;
697*4882a593Smuzhiyun 	battery->fcc = battery->design_cap;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	battery->nac = rk817_bat_vol_to_cap(battery,
700*4882a593Smuzhiyun 					    battery->pwron_voltage);
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	rk817_bat_update_qmax(battery, battery->qmax);
703*4882a593Smuzhiyun 	rk817_bat_save_fcc(battery, battery->fcc);
704*4882a593Smuzhiyun 	DBG("%s, rsoc = %d, dsoc = %d, fcc = %d, nac = %d\n",
705*4882a593Smuzhiyun 	    __func__, battery->rsoc, battery->dsoc, battery->fcc, battery->nac);
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun 
rk817_bat_get_fcc(struct rk817_battery_device * battery)708*4882a593Smuzhiyun static int rk817_bat_get_fcc(struct rk817_battery_device *battery)
709*4882a593Smuzhiyun {
710*4882a593Smuzhiyun 	u32 fcc = 0;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	fcc = rk817_bat_read(battery, NEW_FCC_REG2) << 16;
713*4882a593Smuzhiyun 	fcc |= rk817_bat_read(battery, NEW_FCC_REG1) << 8;
714*4882a593Smuzhiyun 	fcc |= rk817_bat_read(battery, NEW_FCC_REG0) << 0;
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	if (fcc < MIN_FCC) {
717*4882a593Smuzhiyun 		DBG("invalid fcc(%d), use design cap", fcc);
718*4882a593Smuzhiyun 		fcc = battery->design_capacity;
719*4882a593Smuzhiyun 		rk817_bat_save_fcc(battery, fcc);
720*4882a593Smuzhiyun 	} else if (fcc > battery->qmax) {
721*4882a593Smuzhiyun 		DBG("invalid fcc(%d), use qmax", fcc);
722*4882a593Smuzhiyun 		fcc = battery->qmax;
723*4882a593Smuzhiyun 		rk817_bat_save_fcc(battery, fcc);
724*4882a593Smuzhiyun 	}
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	return fcc;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun 
rk817_bat_inc_halt_cnt(struct rk817_battery_device * battery)729*4882a593Smuzhiyun static void rk817_bat_inc_halt_cnt(struct rk817_battery_device *battery)
730*4882a593Smuzhiyun {
731*4882a593Smuzhiyun 	u8 cnt;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	cnt =  rk817_bat_read(battery, HALT_CNT_REG);
734*4882a593Smuzhiyun 	rk817_bat_write(battery, HALT_CNT_REG, ++cnt);
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun 
is_rk817_bat_last_halt(struct rk817_battery_device * battery)737*4882a593Smuzhiyun static bool is_rk817_bat_last_halt(struct rk817_battery_device *battery)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun 	int pre_cap = rk817_bat_get_prev_cap(battery);
740*4882a593Smuzhiyun 	int now_cap = rk817_bat_get_capacity_mah(battery);
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	battery->nac = rk817_bat_vol_to_cap(battery,
743*4882a593Smuzhiyun 					    battery->pwron_voltage);
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	/* over 10%: system halt last time */
746*4882a593Smuzhiyun 	if (now_cap > pre_cap) {
747*4882a593Smuzhiyun 		if (abs(now_cap - pre_cap) > (battery->fcc / 10)) {
748*4882a593Smuzhiyun 			rk817_bat_inc_halt_cnt(battery);
749*4882a593Smuzhiyun 			return true;
750*4882a593Smuzhiyun 		} else {
751*4882a593Smuzhiyun 			return false;
752*4882a593Smuzhiyun 		}
753*4882a593Smuzhiyun 	} else {
754*4882a593Smuzhiyun 		if (abs(battery->nac - pre_cap) > (battery->fcc / 5)) {
755*4882a593Smuzhiyun 			rk817_bat_inc_halt_cnt(battery);
756*4882a593Smuzhiyun 			return true;
757*4882a593Smuzhiyun 		} else {
758*4882a593Smuzhiyun 			return false;
759*4882a593Smuzhiyun 		}
760*4882a593Smuzhiyun 	}
761*4882a593Smuzhiyun }
762*4882a593Smuzhiyun 
rk817_bat_get_halt_cnt(struct rk817_battery_device * battery)763*4882a593Smuzhiyun static u8 rk817_bat_get_halt_cnt(struct rk817_battery_device *battery)
764*4882a593Smuzhiyun {
765*4882a593Smuzhiyun 	return rk817_bat_read(battery, HALT_CNT_REG);
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun 
rk817_bat_is_initialized(struct rk817_battery_device * battery)768*4882a593Smuzhiyun static int rk817_bat_is_initialized(struct rk817_battery_device *battery)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun 	u8 val = rk817_bat_read(battery, FG_INIT);
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	return (val & 0x80);
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun 
rk817_bat_set_initialized_flag(struct rk817_battery_device * battery)775*4882a593Smuzhiyun static void rk817_bat_set_initialized_flag(struct rk817_battery_device *battery)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun 	u8 val = rk817_bat_read(battery, FG_INIT);
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	rk817_bat_write(battery, FG_INIT, val | (0x80));
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun 
rk817_bat_not_first_pwron(struct rk817_battery_device * battery)782*4882a593Smuzhiyun static void rk817_bat_not_first_pwron(struct rk817_battery_device *battery)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun 	int now_soc, now_cap, pre_soc, pre_cap;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	battery->fcc = rk817_bat_get_fcc(battery);
787*4882a593Smuzhiyun 	pre_soc = rk817_bat_get_prev_dsoc(battery);
788*4882a593Smuzhiyun 	pre_cap = rk817_bat_get_prev_cap(battery);
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	now_cap = rk817_bat_get_capacity_mah(battery);
791*4882a593Smuzhiyun 	battery->halt_cnt = rk817_bat_get_halt_cnt(battery);
792*4882a593Smuzhiyun 	battery->nac = rk817_bat_vol_to_cap(battery,
793*4882a593Smuzhiyun 					    battery->pwron_voltage);
794*4882a593Smuzhiyun 	battery->remain_cap = pre_cap * 1000;
795*4882a593Smuzhiyun 	battery->is_halt = is_rk817_bat_last_halt(battery);
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	DBG("now_cap: %d, pre_cap: %d\n", now_cap, pre_cap);
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	if (now_cap > pre_cap) {
800*4882a593Smuzhiyun 		if (now_cap >= battery->fcc)
801*4882a593Smuzhiyun 			now_cap = battery->fcc;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 		now_soc = now_cap * 1000 * 100 / battery->fcc;
804*4882a593Smuzhiyun 		if (pre_soc < 100 * 1000)
805*4882a593Smuzhiyun 			pre_soc += (now_soc - pre_cap * 1000 * 100 / battery->fcc);
806*4882a593Smuzhiyun 		pre_cap = now_cap;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 		if (pre_soc >= 100 * 1000)
809*4882a593Smuzhiyun 			pre_soc = 100 * 1000;
810*4882a593Smuzhiyun 		if (now_cap >= battery->fcc)
811*4882a593Smuzhiyun 			pre_soc = 100 * 1000;
812*4882a593Smuzhiyun 	}
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	rk817_bat_init_coulomb_cap(battery, pre_cap);
815*4882a593Smuzhiyun 	rk817_bat_init_coulomb_cap(battery, pre_cap + 1);
816*4882a593Smuzhiyun 	rk817_bat_get_capacity_mah(battery);
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun 	battery->dsoc = pre_soc;
819*4882a593Smuzhiyun 	if (battery->dsoc > 100000)
820*4882a593Smuzhiyun 		battery->dsoc = 100000;
821*4882a593Smuzhiyun 	battery->nac = pre_cap;
822*4882a593Smuzhiyun 	if (battery->nac < 0)
823*4882a593Smuzhiyun 		battery->nac = 0;
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	DBG("dsoc=%d cap=%d v=%d pwron_v =%d min=%d psoc=%d pcap=%d\n",
826*4882a593Smuzhiyun 	    battery->dsoc, battery->nac, rk817_bat_get_battery_voltage(battery),
827*4882a593Smuzhiyun 	    rk817_bat_get_pwron_voltage(battery),
828*4882a593Smuzhiyun 	    battery->pwroff_min, rk817_bat_get_prev_dsoc(battery),
829*4882a593Smuzhiyun 	    rk817_bat_get_prev_cap(battery));
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun 
rk817_bat_rsoc_init(struct rk817_battery_device * battery)832*4882a593Smuzhiyun static void rk817_bat_rsoc_init(struct rk817_battery_device *battery)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun 	int version, value;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	battery->is_first_power_on = is_rk817_bat_first_pwron(battery);
837*4882a593Smuzhiyun 	battery->pwroff_min = rk817_bat_get_off_count(battery);
838*4882a593Smuzhiyun 	battery->pwron_voltage = rk817_bat_get_pwron_voltage(battery);
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	value = rk817_bat_read(battery, DRV_VERSION);
841*4882a593Smuzhiyun 	/* drv_version: bit0~bit3 */
842*4882a593Smuzhiyun 	version = value & 0x0f;
843*4882a593Smuzhiyun 	/* drv_version: [0 15] */
844*4882a593Smuzhiyun 	battery->drv_version &= 0x0f;
845*4882a593Smuzhiyun 	DBG("reg read version:%d dts read version:%d\n", version, battery->drv_version);
846*4882a593Smuzhiyun 	if (battery->drv_version != version) {
847*4882a593Smuzhiyun 		battery->is_first_power_on = 1;
848*4882a593Smuzhiyun 		value &= 0xf0;
849*4882a593Smuzhiyun 		value |= battery->drv_version;
850*4882a593Smuzhiyun 		rk817_bat_write(battery, DRV_VERSION, value);
851*4882a593Smuzhiyun 	}
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	DBG("battery = %d\n", rk817_bat_get_battery_voltage(battery));
854*4882a593Smuzhiyun 	DBG("%s: is_first_power_on = %d, pwroff_min = %d, pwron_voltage = %d\n",
855*4882a593Smuzhiyun 	    __func__, battery->is_first_power_on,
856*4882a593Smuzhiyun 	    battery->pwroff_min, battery->pwron_voltage);
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	if (battery->is_first_power_on)
859*4882a593Smuzhiyun 		rk817_bat_first_pwron(battery);
860*4882a593Smuzhiyun 	else
861*4882a593Smuzhiyun 		rk817_bat_not_first_pwron(battery);
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	 rk817_bat_save_dsoc(battery, battery->dsoc);
864*4882a593Smuzhiyun 	 rk817_bat_save_cap(battery, battery->nac);
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun 
rk817_bat_calc_linek(struct rk817_battery_device * battery)867*4882a593Smuzhiyun static int rk817_bat_calc_linek(struct rk817_battery_device *battery)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun 	int linek, diff, delta;
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	battery->calc_dsoc = battery->dsoc;
872*4882a593Smuzhiyun 	battery->calc_rsoc = battery->rsoc;
873*4882a593Smuzhiyun 	battery->sm_old_cap = battery->remain_cap;
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun 	delta = abs(battery->dsoc - battery->rsoc);
876*4882a593Smuzhiyun 	diff = delta * 3;
877*4882a593Smuzhiyun 	battery->sm_meet_soc = (battery->dsoc >= battery->rsoc) ?
878*4882a593Smuzhiyun 			   (battery->dsoc + diff) : (battery->rsoc + diff);
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	if (battery->dsoc < battery->rsoc)
881*4882a593Smuzhiyun 		linek = 1000 * (delta + diff) / DIV(diff);
882*4882a593Smuzhiyun 	else if (battery->dsoc > battery->rsoc)
883*4882a593Smuzhiyun 		linek = 1000 * diff / DIV(delta + diff);
884*4882a593Smuzhiyun 	else
885*4882a593Smuzhiyun 		linek = 1000;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	battery->sm_chrg_dsoc = battery->dsoc;
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	DBG("<%s>. meet=%d, diff=%d, link=%d, calc: dsoc=%d, rsoc=%d\n",
890*4882a593Smuzhiyun 	    __func__, battery->sm_meet_soc, diff, linek,
891*4882a593Smuzhiyun 	    battery->calc_dsoc, battery->calc_rsoc);
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun 	return linek;
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun 
rk817_bat_get_est_voltage(struct rk817_battery_device * battery)896*4882a593Smuzhiyun static int rk817_bat_get_est_voltage(struct rk817_battery_device *battery)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun 	return rk817_bat_get_battery_voltage(battery);
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun 
rk817_bat_update_get_voltage(struct udevice * dev)901*4882a593Smuzhiyun static int rk817_bat_update_get_voltage(struct udevice *dev)
902*4882a593Smuzhiyun {
903*4882a593Smuzhiyun 	struct rk817_battery_device *battery = dev_get_priv(dev);
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	if (!battery->virtual_power && battery->voltage_k)
906*4882a593Smuzhiyun 		return rk817_bat_get_est_voltage(battery);
907*4882a593Smuzhiyun 	else
908*4882a593Smuzhiyun 		return VIRTUAL_POWER_VOL;
909*4882a593Smuzhiyun }
910*4882a593Smuzhiyun 
rk817_bat_update_get_current(struct udevice * dev)911*4882a593Smuzhiyun static int rk817_bat_update_get_current(struct udevice *dev)
912*4882a593Smuzhiyun {
913*4882a593Smuzhiyun 	struct rk817_battery_device *battery = dev_get_priv(dev);
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 	if (!battery->virtual_power && battery->voltage_k)
916*4882a593Smuzhiyun 		return rk817_bat_get_avg_current(battery);
917*4882a593Smuzhiyun 	else
918*4882a593Smuzhiyun 		return VIRTUAL_POWER_CUR;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun 
rk817_bat_dwc_otg_check_dpdm(struct rk817_battery_device * battery)921*4882a593Smuzhiyun static int rk817_bat_dwc_otg_check_dpdm(struct rk817_battery_device *battery)
922*4882a593Smuzhiyun {
923*4882a593Smuzhiyun 	if (battery->variant == RK809_ID) {
924*4882a593Smuzhiyun 		if (rk817_bat_read(battery, PMIC_SYS_STS) & PLUG_IN_STS)
925*4882a593Smuzhiyun 			return AC_CHARGER;
926*4882a593Smuzhiyun 		else
927*4882a593Smuzhiyun 			return NO_CHARGER;
928*4882a593Smuzhiyun 	} else {
929*4882a593Smuzhiyun 		return  rockchip_chg_get_type();
930*4882a593Smuzhiyun 	}
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun 
rk817_bat_update_get_chrg_online(struct udevice * dev)933*4882a593Smuzhiyun static bool rk817_bat_update_get_chrg_online(struct udevice *dev)
934*4882a593Smuzhiyun {
935*4882a593Smuzhiyun 	struct rk817_battery_device *battery = dev_get_priv(dev);
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	return rk817_bat_dwc_otg_check_dpdm(battery);
938*4882a593Smuzhiyun }
939*4882a593Smuzhiyun 
rk817_bat_get_usb_state(struct rk817_battery_device * battery)940*4882a593Smuzhiyun static int rk817_bat_get_usb_state(struct rk817_battery_device *battery)
941*4882a593Smuzhiyun {
942*4882a593Smuzhiyun 	int charger_type;
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun 	switch (rk817_bat_dwc_otg_check_dpdm(battery)) {
945*4882a593Smuzhiyun 	case POWER_SUPPLY_TYPE_UNKNOWN:
946*4882a593Smuzhiyun 		if ((rk817_bat_read(battery, PMIC_SYS_STS) & PLUG_IN_STS) != 0)
947*4882a593Smuzhiyun 			charger_type = DC_CHARGER;
948*4882a593Smuzhiyun 		else
949*4882a593Smuzhiyun 			charger_type = NO_CHARGER;
950*4882a593Smuzhiyun 		break;
951*4882a593Smuzhiyun 	case POWER_SUPPLY_TYPE_USB:
952*4882a593Smuzhiyun 		charger_type = USB_CHARGER;
953*4882a593Smuzhiyun 		break;
954*4882a593Smuzhiyun 	case POWER_SUPPLY_TYPE_USB_DCP:
955*4882a593Smuzhiyun 	case POWER_SUPPLY_TYPE_USB_CDP:
956*4882a593Smuzhiyun 	case POWER_SUPPLY_TYPE_USB_FLOATING:
957*4882a593Smuzhiyun 		charger_type = AC_CHARGER;
958*4882a593Smuzhiyun 		break;
959*4882a593Smuzhiyun 	default:
960*4882a593Smuzhiyun 		charger_type = NO_CHARGER;
961*4882a593Smuzhiyun 	}
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	return charger_type;
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun 
rk817_bat_get_charger_type(struct rk817_battery_device * battery)966*4882a593Smuzhiyun static int rk817_bat_get_charger_type(struct rk817_battery_device *battery)
967*4882a593Smuzhiyun {
968*4882a593Smuzhiyun 	struct rk8xx_priv *rk8xx = dev_get_priv(battery->dev->parent);
969*4882a593Smuzhiyun 	u32 chrg_type;
970*4882a593Smuzhiyun 	u8 val;
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 	/* check by ic hardware: this check make check work safer */
973*4882a593Smuzhiyun 	if ((rk817_bat_read(battery, PMIC_SYS_STS) & PLUG_IN_STS) == 0)
974*4882a593Smuzhiyun 		return NO_CHARGER;
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	/* virtual or bat not exist */
977*4882a593Smuzhiyun 	if (battery->virtual_power)
978*4882a593Smuzhiyun 		return DC_CHARGER;
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 	/* check USB secondly */
981*4882a593Smuzhiyun 	chrg_type = rk817_bat_get_usb_state(battery);
982*4882a593Smuzhiyun 	if (chrg_type != NO_CHARGER && (battery->rsoc + 500) / 1000 >= 100)
983*4882a593Smuzhiyun 		chrg_type = CHARGE_FINISH;
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	if (rk8xx->variant == RK817_ID) {
986*4882a593Smuzhiyun 		val = rk817_bat_read(battery, PMIC_CHRG_STS);
987*4882a593Smuzhiyun 		if ((val & 0x70) == CHARGE_FINISH)
988*4882a593Smuzhiyun 			chrg_type = CHARGE_FINISH;
989*4882a593Smuzhiyun 	}
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	return chrg_type;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun 
rk817_bat_set_input_current(struct rk817_battery_device * battery,int input_current)994*4882a593Smuzhiyun static void rk817_bat_set_input_current(struct rk817_battery_device *battery,
995*4882a593Smuzhiyun 					int input_current)
996*4882a593Smuzhiyun {
997*4882a593Smuzhiyun 	u8 usb_ctrl;
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun 	usb_ctrl = rk817_bat_read(battery, USB_CTRL_REG);
1000*4882a593Smuzhiyun 	usb_ctrl &= ~INPUT_CUR_MSK;
1001*4882a593Smuzhiyun 	usb_ctrl |= ((input_current) | 0x08);
1002*4882a593Smuzhiyun 	rk817_bat_write(battery, USB_CTRL_REG, usb_ctrl);
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun 
rk817_bat_set_input_voltage(struct rk817_battery_device * battery,int input_voltage)1005*4882a593Smuzhiyun static void rk817_bat_set_input_voltage(struct rk817_battery_device *battery,
1006*4882a593Smuzhiyun 					int input_voltage)
1007*4882a593Smuzhiyun {
1008*4882a593Smuzhiyun 	u8 usb_ctrl;
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	usb_ctrl = rk817_bat_read(battery, USB_CTRL_REG);
1011*4882a593Smuzhiyun 	usb_ctrl &= ~INPUT_VOL_MSK;
1012*4882a593Smuzhiyun 	usb_ctrl |= ((input_voltage) | 0x80);
1013*4882a593Smuzhiyun 	rk817_bat_write(battery, USB_CTRL_REG, usb_ctrl);
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun 
rk817_bat_charger_setting(struct rk817_battery_device * battery,int charger)1016*4882a593Smuzhiyun static void rk817_bat_charger_setting(struct rk817_battery_device *battery,
1017*4882a593Smuzhiyun 				      int charger)
1018*4882a593Smuzhiyun {
1019*4882a593Smuzhiyun 	static u8 old_charger = UNDEF_CHARGER;
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 	rk817_bat_set_input_voltage(battery, VLIM_4500MV);
1022*4882a593Smuzhiyun 	/* charger changed */
1023*4882a593Smuzhiyun 	if (old_charger != charger) {
1024*4882a593Smuzhiyun 		if (charger == NO_CHARGER) {
1025*4882a593Smuzhiyun 			DBG("NO_CHARGER\n");
1026*4882a593Smuzhiyun 			rk817_bat_set_input_current(battery, ILIM_450MA);
1027*4882a593Smuzhiyun 		} else if (charger == USB_CHARGER) {
1028*4882a593Smuzhiyun 			DBG("USB_CHARGER\n");
1029*4882a593Smuzhiyun 			rk817_bat_set_input_current(battery, ILIM_450MA);
1030*4882a593Smuzhiyun 		} else if (charger == DC_CHARGER || charger == AC_CHARGER) {
1031*4882a593Smuzhiyun 			DBG("DC OR AC CHARGE\n");
1032*4882a593Smuzhiyun 			rk817_bat_set_input_current(battery, ILIM_1500MA);
1033*4882a593Smuzhiyun 		} else {
1034*4882a593Smuzhiyun 			DBG("charger setting error %d\n", charger);
1035*4882a593Smuzhiyun 		}
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun 		old_charger = charger;
1038*4882a593Smuzhiyun 	}
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun 
rk817_bat_linek_algorithm(struct rk817_battery_device * battery)1041*4882a593Smuzhiyun static void rk817_bat_linek_algorithm(struct rk817_battery_device *battery)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun 	int delta_cap, ydsoc, tmp;
1044*4882a593Smuzhiyun 	u8 chg_st = rk817_bat_get_charger_type(battery);
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun 	/* slow down */
1047*4882a593Smuzhiyun 	if (battery->dsoc / 1000 == 99)
1048*4882a593Smuzhiyun 		battery->sm_linek = CHRG_FULL_K;
1049*4882a593Smuzhiyun 	else if (battery->dsoc / 1000 >= CHRG_TERM_DSOC &&
1050*4882a593Smuzhiyun 		 battery->current_avg > TERM_CALI_CURR)
1051*4882a593Smuzhiyun 		battery->sm_linek = CHRG_TERM_K;
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun 	delta_cap = battery->remain_cap - battery->sm_old_cap;
1054*4882a593Smuzhiyun 	ydsoc = battery->sm_linek * (delta_cap  / DIV(battery->fcc)) / 10;
1055*4882a593Smuzhiyun 	battery->sm_chrg_dsoc += ydsoc;
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	tmp = battery->sm_chrg_dsoc / 1000;
1058*4882a593Smuzhiyun 
1059*4882a593Smuzhiyun 	if (ydsoc > 0) {
1060*4882a593Smuzhiyun 		if (battery->sm_chrg_dsoc < 0)
1061*4882a593Smuzhiyun 			battery->sm_chrg_dsoc = 0;
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun 		tmp = battery->sm_chrg_dsoc / 1000;
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun 		if (tmp != battery->dsoc / 1000) {
1066*4882a593Smuzhiyun 			if (battery->sm_chrg_dsoc < battery->dsoc)
1067*4882a593Smuzhiyun 				return;
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 			battery->dsoc = battery->sm_chrg_dsoc;
1070*4882a593Smuzhiyun 			if (battery->dsoc <= 0)
1071*4882a593Smuzhiyun 				battery->dsoc = 0;
1072*4882a593Smuzhiyun 		}
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun 		battery->sm_old_cap = battery->remain_cap;
1075*4882a593Smuzhiyun 		if (battery->dsoc / 1000 == battery->rsoc / 1000 &&
1076*4882a593Smuzhiyun 		    battery->sm_linek != CHRG_FULL_K &&
1077*4882a593Smuzhiyun 		    battery->sm_linek != CHRG_TERM_K)
1078*4882a593Smuzhiyun 			battery->sm_linek = 1000;
1079*4882a593Smuzhiyun 	}
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 	if ((battery->sm_linek == 1000 || battery->dsoc >= 100 * 1000) &&
1082*4882a593Smuzhiyun 	    (chg_st != CHARGE_FINISH)) {
1083*4882a593Smuzhiyun 		if (battery->sm_linek == 1000)
1084*4882a593Smuzhiyun 			battery->dsoc = battery->rsoc;
1085*4882a593Smuzhiyun 		battery->sm_chrg_dsoc = battery->dsoc;
1086*4882a593Smuzhiyun 	}
1087*4882a593Smuzhiyun }
1088*4882a593Smuzhiyun 
rk817_bat_finish_chrg(struct rk817_battery_device * battery)1089*4882a593Smuzhiyun static void rk817_bat_finish_chrg(struct rk817_battery_device *battery)
1090*4882a593Smuzhiyun {
1091*4882a593Smuzhiyun 	u32 tgt_sec = 0;
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	if (battery->dsoc / 1000 < 100) {
1094*4882a593Smuzhiyun 		tgt_sec = battery->fcc * 3600 / 100 / FINISH_CALI_CURR;
1095*4882a593Smuzhiyun 		if (get_timer(battery->finish_chrg_base) > SECONDS(tgt_sec)) {
1096*4882a593Smuzhiyun 			battery->finish_chrg_base = get_timer(0);
1097*4882a593Smuzhiyun 			battery->dsoc += 1000;
1098*4882a593Smuzhiyun 		}
1099*4882a593Smuzhiyun 	}
1100*4882a593Smuzhiyun }
1101*4882a593Smuzhiyun 
rk817_bat_debug_info(struct rk817_battery_device * battery)1102*4882a593Smuzhiyun static void rk817_bat_debug_info(struct rk817_battery_device *battery)
1103*4882a593Smuzhiyun {
1104*4882a593Smuzhiyun 	DBG("debug info:\n");
1105*4882a593Smuzhiyun 	DBG("CAL_OFFSET = 0x%x", rk817_bat_read(battery, CAL_OFFSET_H));
1106*4882a593Smuzhiyun 	DBG("%x\n", rk817_bat_read(battery, CAL_OFFSET_L));
1107*4882a593Smuzhiyun 	DBG("current_avg = %d\n", rk817_bat_get_avg_current(battery));
1108*4882a593Smuzhiyun 	DBG("k = %d, b = %d\n", battery->voltage_k, battery->voltage_b);
1109*4882a593Smuzhiyun 	DBG("battery: %d\n", rk817_bat_get_battery_voltage(battery));
1110*4882a593Smuzhiyun 	DBG("voltage_sys = %d\n", rk817_bat_get_sys_voltage(battery));
1111*4882a593Smuzhiyun 	DBG("voltage_usb = %d\n", rk817_bat_get_USB_voltage(battery));
1112*4882a593Smuzhiyun 	DBG("current_avg = %d\n", rk817_bat_get_avg_current(battery));
1113*4882a593Smuzhiyun 	DBG("dsoc = %d\n", battery->dsoc);
1114*4882a593Smuzhiyun 	DBG("rsoc = %d\n", rk817_bat_get_rsoc(battery));
1115*4882a593Smuzhiyun 	DBG("remain_cap = %d\n", rk817_bat_get_capacity_uah(battery));
1116*4882a593Smuzhiyun 	DBG("fcc = %d\n", battery->fcc);
1117*4882a593Smuzhiyun 	DBG("qmax = %d\n", battery->qmax);
1118*4882a593Smuzhiyun }
1119*4882a593Smuzhiyun 
rk817_bat_smooth_charge(struct rk817_battery_device * battery)1120*4882a593Smuzhiyun static void rk817_bat_smooth_charge(struct rk817_battery_device *battery)
1121*4882a593Smuzhiyun {
1122*4882a593Smuzhiyun 	u8 chg_st = rk817_bat_get_charger_type(battery);
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun 	rk817_bat_debug_info(battery);
1125*4882a593Smuzhiyun 	rk817_bat_calibration(battery);
1126*4882a593Smuzhiyun 	/* set terminal charge mode */
1127*4882a593Smuzhiyun 	if (battery->term_sig_base &&
1128*4882a593Smuzhiyun 	    get_timer(battery->term_sig_base) > SECONDS(1))
1129*4882a593Smuzhiyun 		battery->term_sig_base = 0;
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 	/* not charge mode and not keep in uboot charge: exit */
1132*4882a593Smuzhiyun 	if ((battery->chrg_type == NO_CHARGER) ||
1133*4882a593Smuzhiyun 	    !rk817_bat_is_initialized(battery)) {
1134*4882a593Smuzhiyun 		DBG("chrg=%d\n", battery->chrg_type);
1135*4882a593Smuzhiyun 		rk817_bat_set_initialized_flag(battery);
1136*4882a593Smuzhiyun 		goto out;
1137*4882a593Smuzhiyun 	}
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	/* update rsoc and remain cap */
1140*4882a593Smuzhiyun 	battery->remain_cap = rk817_bat_get_capacity_uah(battery);
1141*4882a593Smuzhiyun 	battery->rsoc = rk817_bat_get_rsoc(battery);
1142*4882a593Smuzhiyun 	if (battery->remain_cap / 1000 > battery->fcc) {
1143*4882a593Smuzhiyun 		battery->sm_old_cap -=
1144*4882a593Smuzhiyun 			(battery->remain_cap - battery->fcc * 1000);
1145*4882a593Smuzhiyun 		rk817_bat_init_coulomb_cap(battery, battery->fcc + 100);
1146*4882a593Smuzhiyun 		rk817_bat_init_coulomb_cap(battery, battery->fcc);
1147*4882a593Smuzhiyun 	}
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun 	/* finish charge step */
1150*4882a593Smuzhiyun 	if (chg_st == CHARGE_FINISH) {
1151*4882a593Smuzhiyun 		rk817_bat_finish_chrg(battery);
1152*4882a593Smuzhiyun 		rk817_bat_init_coulomb_cap(battery, battery->fcc + 100);
1153*4882a593Smuzhiyun 		rk817_bat_init_coulomb_cap(battery, battery->fcc);
1154*4882a593Smuzhiyun 	} else {
1155*4882a593Smuzhiyun 		DBG("smooth charge step...\n");
1156*4882a593Smuzhiyun 		battery->adc_allow_update = true;
1157*4882a593Smuzhiyun 		battery->finish_chrg_base = get_timer(0);
1158*4882a593Smuzhiyun 		rk817_bat_linek_algorithm(battery);
1159*4882a593Smuzhiyun 	}
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun 	/* dsoc limit */
1162*4882a593Smuzhiyun 	if (battery->dsoc / 1000 > 100)
1163*4882a593Smuzhiyun 		battery->dsoc = 100 * 1000;
1164*4882a593Smuzhiyun 	else if (battery->dsoc < 0)
1165*4882a593Smuzhiyun 		battery->dsoc = 0;
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun 	rk817_bat_save_dsoc(battery, battery->dsoc);
1168*4882a593Smuzhiyun 	rk817_bat_save_cap(battery, battery->remain_cap / 1000);
1169*4882a593Smuzhiyun out:
1170*4882a593Smuzhiyun 	return;
1171*4882a593Smuzhiyun }
1172*4882a593Smuzhiyun 
rk817_bat_update_get_soc(struct udevice * dev)1173*4882a593Smuzhiyun static int rk817_bat_update_get_soc(struct udevice *dev)
1174*4882a593Smuzhiyun {
1175*4882a593Smuzhiyun 	struct rk817_battery_device *battery = dev_get_priv(dev);
1176*4882a593Smuzhiyun 	static ulong seconds;
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun 	rk817_bat_debug_info(battery);
1179*4882a593Smuzhiyun 	/* set charge current */
1180*4882a593Smuzhiyun 	battery->chrg_type =
1181*4882a593Smuzhiyun 		rk817_bat_get_charger_type(battery);
1182*4882a593Smuzhiyun 	rk817_bat_charger_setting(battery, battery->chrg_type);
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 	/* fg calc every 5 seconds */
1185*4882a593Smuzhiyun 	if (!seconds)
1186*4882a593Smuzhiyun 		seconds = get_timer(0);
1187*4882a593Smuzhiyun 	if (get_timer(seconds) >= SECONDS(5)) {
1188*4882a593Smuzhiyun 		seconds = get_timer(0);
1189*4882a593Smuzhiyun 		rk817_bat_smooth_charge(battery);
1190*4882a593Smuzhiyun 	}
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun 	/* bat exist, fg init success(dts pass) and uboot charge: report data */
1193*4882a593Smuzhiyun 	if (!battery->virtual_power && battery->voltage_k)
1194*4882a593Smuzhiyun 		return battery->dsoc / 1000;
1195*4882a593Smuzhiyun 	else
1196*4882a593Smuzhiyun 		return VIRTUAL_POWER_SOC;
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun 
rk817_is_bat_exist(struct rk817_battery_device * battery)1199*4882a593Smuzhiyun static int rk817_is_bat_exist(struct rk817_battery_device *battery)
1200*4882a593Smuzhiyun {
1201*4882a593Smuzhiyun 	struct rk8xx_priv *rk8xx = dev_get_priv(battery->dev->parent);
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	if (rk8xx->variant == RK817_ID)
1204*4882a593Smuzhiyun 		return (rk817_bat_read(battery, PMIC_CHRG_STS) & 0x80) ? 1 : 0;
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun 	return 1;
1207*4882a593Smuzhiyun }
1208*4882a593Smuzhiyun 
rk817_bat_bat_is_exist(struct udevice * dev)1209*4882a593Smuzhiyun static int rk817_bat_bat_is_exist(struct udevice *dev)
1210*4882a593Smuzhiyun {
1211*4882a593Smuzhiyun         struct rk817_battery_device *battery = dev_get_priv(dev);
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun         return rk817_is_bat_exist(battery);
1214*4882a593Smuzhiyun }
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun static struct dm_fuel_gauge_ops fg_ops = {
1218*4882a593Smuzhiyun 	.bat_is_exist = rk817_bat_bat_is_exist,
1219*4882a593Smuzhiyun 	.get_soc = rk817_bat_update_get_soc,
1220*4882a593Smuzhiyun 	.get_voltage = rk817_bat_update_get_voltage,
1221*4882a593Smuzhiyun 	.get_current = rk817_bat_update_get_current,
1222*4882a593Smuzhiyun 	.get_chrg_online = rk817_bat_update_get_chrg_online,
1223*4882a593Smuzhiyun };
1224*4882a593Smuzhiyun 
rk817_fg_ofdata_to_platdata(struct udevice * dev)1225*4882a593Smuzhiyun static int rk817_fg_ofdata_to_platdata(struct udevice *dev)
1226*4882a593Smuzhiyun {
1227*4882a593Smuzhiyun 	struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
1228*4882a593Smuzhiyun 	struct rk817_battery_device *battery = dev_get_priv(dev);
1229*4882a593Smuzhiyun 	const char *prop;
1230*4882a593Smuzhiyun 	int  len, value;
1231*4882a593Smuzhiyun 	int i;
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 	if ((rk8xx->variant != RK817_ID) && (rk8xx->variant != RK809_ID)) {
1234*4882a593Smuzhiyun 		debug("%s: Not support pmic variant: rk%x\n",
1235*4882a593Smuzhiyun 		      __func__, rk8xx->variant);
1236*4882a593Smuzhiyun 		return -EINVAL;
1237*4882a593Smuzhiyun 	}
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun 	battery->dev = dev;
1240*4882a593Smuzhiyun 	battery->variant = rk8xx->variant;
1241*4882a593Smuzhiyun 	/* Parse ocv table */
1242*4882a593Smuzhiyun 	prop = dev_read_prop(dev, "ocv_table", &len);
1243*4882a593Smuzhiyun 	if (!prop) {
1244*4882a593Smuzhiyun 		printf("can't find ocv_table prop\n");
1245*4882a593Smuzhiyun 		return -EINVAL;
1246*4882a593Smuzhiyun 	}
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun 	battery->ocv_table = calloc(len, 1);
1249*4882a593Smuzhiyun 	if (!battery->ocv_table) {
1250*4882a593Smuzhiyun 		printf("can't calloc ocv_table\n");
1251*4882a593Smuzhiyun 		return -ENOMEM;
1252*4882a593Smuzhiyun 	}
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	battery->ocv_size = len / 4;
1255*4882a593Smuzhiyun 	if (dev_read_u32_array(dev, "ocv_table",
1256*4882a593Smuzhiyun 			       battery->ocv_table, battery->ocv_size)) {
1257*4882a593Smuzhiyun 		printf("can't read ocv_table\n");
1258*4882a593Smuzhiyun 		free(battery->ocv_table);
1259*4882a593Smuzhiyun 		return -EINVAL;
1260*4882a593Smuzhiyun 	}
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	/* Parse neccessay */
1263*4882a593Smuzhiyun 	battery->design_cap = dev_read_u32_default(dev, "design_capacity", -1);
1264*4882a593Smuzhiyun 	if (battery->design_cap < 0) {
1265*4882a593Smuzhiyun 		printf("can't read design_capacity\n");
1266*4882a593Smuzhiyun 		return -EINVAL;
1267*4882a593Smuzhiyun 	}
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun 	battery->qmax = dev_read_u32_default(dev, "design_qmax", -1);
1270*4882a593Smuzhiyun 	if (battery->qmax < 0) {
1271*4882a593Smuzhiyun 		printf("can't read design_qmax\n");
1272*4882a593Smuzhiyun 		return -EINVAL;
1273*4882a593Smuzhiyun 	}
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun 	battery->virtual_power = dev_read_u32_default(dev, "virtual_power", 0);
1276*4882a593Smuzhiyun 	if (!rk817_is_bat_exist(battery))
1277*4882a593Smuzhiyun 		battery->virtual_power = 1;
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	if (rk8xx->variant == RK809_ID) {
1280*4882a593Smuzhiyun 		battery->bat_res_up  = dev_read_u32_default(dev, "bat_res_up", -1);
1281*4882a593Smuzhiyun 		if (battery->bat_res_up < 0) {
1282*4882a593Smuzhiyun 			printf("can't read bat_res_up\n");
1283*4882a593Smuzhiyun 			return -EINVAL;
1284*4882a593Smuzhiyun 		}
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 		battery->bat_res_down  = dev_read_u32_default(dev, "bat_res_down", -1);
1287*4882a593Smuzhiyun 		if (battery->bat_res_down < 0) {
1288*4882a593Smuzhiyun 			printf("can't read bat_res_down\n");
1289*4882a593Smuzhiyun 			return -EINVAL;
1290*4882a593Smuzhiyun 		}
1291*4882a593Smuzhiyun 	}
1292*4882a593Smuzhiyun 
1293*4882a593Smuzhiyun 	battery->drv_version  = dev_read_u32_default(dev, "drv_version", -1);
1294*4882a593Smuzhiyun 	if (battery->drv_version < 0)
1295*4882a593Smuzhiyun 		battery->drv_version = 0;
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun 	value = dev_read_u32_default(dev, "sample_res", -1);
1298*4882a593Smuzhiyun 	if (battery->res_div < 0)
1299*4882a593Smuzhiyun 		printf("read sample_res error\n");
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 	battery->res_div = (value == SAMPLE_RES_20mR) ?
1302*4882a593Smuzhiyun 		       SAMPLE_RES_DIV2 : SAMPLE_RES_DIV1;
1303*4882a593Smuzhiyun 
1304*4882a593Smuzhiyun 	DBG("OCV Value:");
1305*4882a593Smuzhiyun 	for (i = 0; i < battery->ocv_size; i++)
1306*4882a593Smuzhiyun 		DBG("%d  ", battery->ocv_table[i]);
1307*4882a593Smuzhiyun 	DBG("ocvsize: %d\n", battery->ocv_size);
1308*4882a593Smuzhiyun 	DBG("battery->design_cap: %d\n", battery->design_cap);
1309*4882a593Smuzhiyun 	DBG("battery->qmax: %d\n", battery->qmax);
1310*4882a593Smuzhiyun 	DBG("battery->bat_res_up: %d\n", battery->bat_res_up);
1311*4882a593Smuzhiyun 	DBG("battery->bat_res_down: %d\n", battery->bat_res_down);
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	return 0;
1314*4882a593Smuzhiyun }
1315*4882a593Smuzhiyun 
rk817_fg_init(struct rk817_battery_device * battery)1316*4882a593Smuzhiyun static int rk817_fg_init(struct rk817_battery_device *battery)
1317*4882a593Smuzhiyun {
1318*4882a593Smuzhiyun 	int value;
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun 	value = rk817_bat_read(battery, GG_CON);
1321*4882a593Smuzhiyun 	rk817_bat_write(battery, GG_CON, value | VOL_OUPUT_INSTANT_MODE);
1322*4882a593Smuzhiyun 	if (battery->variant == RK817_ID) {
1323*4882a593Smuzhiyun 		value =  rk817_bat_read(battery, BAT_DISCHRG);
1324*4882a593Smuzhiyun 		rk817_bat_write(battery, BAT_DISCHRG, value & (~DIS_ILIM_EN));
1325*4882a593Smuzhiyun 	}
1326*4882a593Smuzhiyun 	rk817_bat_gas_gaugle_enable(battery);
1327*4882a593Smuzhiyun 	rk817_bat_init_voltage_kb(battery);
1328*4882a593Smuzhiyun 	rk817_bat_calibration(battery);
1329*4882a593Smuzhiyun 	rk817_bat_rsoc_init(battery);
1330*4882a593Smuzhiyun 	rk817_bat_init_coulomb_cap(battery, battery->nac);
1331*4882a593Smuzhiyun 	rk817_bat_set_initialized_flag(battery);
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun 	battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
1334*4882a593Smuzhiyun 	battery->voltage_sys = rk817_bat_get_sys_voltage(battery);
1335*4882a593Smuzhiyun 	battery->voltage_usb = rk817_bat_get_USB_voltage(battery);
1336*4882a593Smuzhiyun 	battery->current_avg = rk817_bat_get_avg_current(battery);
1337*4882a593Smuzhiyun 	battery->current_pwron = rk817_bat_get_pwron_current(battery);
1338*4882a593Smuzhiyun 	battery->remain_cap = rk817_bat_get_capacity_uah(battery);
1339*4882a593Smuzhiyun 	battery->rsoc = rk817_bat_get_rsoc(battery);
1340*4882a593Smuzhiyun 	battery->sm_linek = rk817_bat_calc_linek(battery);
1341*4882a593Smuzhiyun 	battery->chrg_type = rk817_bat_get_charger_type(battery);
1342*4882a593Smuzhiyun 	battery->finish_chrg_base = get_timer(0);
1343*4882a593Smuzhiyun 	battery->term_sig_base = get_timer(0);
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun 	battery->dbg_pwr_dsoc = battery->dsoc;
1346*4882a593Smuzhiyun 	battery->dbg_pwr_rsoc = battery->rsoc;
1347*4882a593Smuzhiyun 	battery->dbg_pwr_vol = battery->voltage_avg;
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 	if (battery->variant == RK817_ID)
1350*4882a593Smuzhiyun 		rk817_bat_charger_setting(battery, battery->chrg_type);
1351*4882a593Smuzhiyun 
1352*4882a593Smuzhiyun 	DBG("voltage_k = %d, voltage_b = %d\n",
1353*4882a593Smuzhiyun 	    battery->voltage_k, battery->voltage_b);
1354*4882a593Smuzhiyun 	DBG("voltage_sys = %d\n", battery->voltage_sys);
1355*4882a593Smuzhiyun 	DBG("voltage usb: %d\n", battery->voltage_avg);
1356*4882a593Smuzhiyun 	DBG("battery: %d\n", battery->voltage_avg);
1357*4882a593Smuzhiyun 	DBG("current_avg = %d\n", battery->current_avg);
1358*4882a593Smuzhiyun 	DBG("current_pwron = %d\n", battery->current_pwron);
1359*4882a593Smuzhiyun 	DBG("remain_cap = %d\n", battery->remain_cap);
1360*4882a593Smuzhiyun 	DBG("fcc = %d\n", battery->fcc);
1361*4882a593Smuzhiyun 	DBG("qmax = %d\n", battery->qmax);
1362*4882a593Smuzhiyun 	DBG("dsoc = %d\n", battery->dsoc);
1363*4882a593Smuzhiyun 	DBG("rsoc = %d\n", battery->rsoc);
1364*4882a593Smuzhiyun 	DBG("charge type: %d\n", battery->chrg_type);
1365*4882a593Smuzhiyun 
1366*4882a593Smuzhiyun 	return 0;
1367*4882a593Smuzhiyun }
1368*4882a593Smuzhiyun 
rk817_fg_probe(struct udevice * dev)1369*4882a593Smuzhiyun static int rk817_fg_probe(struct udevice *dev)
1370*4882a593Smuzhiyun {
1371*4882a593Smuzhiyun 	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
1372*4882a593Smuzhiyun 	struct rk817_battery_device *battery = dev_get_priv(dev);
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun 	if ((priv->variant != RK817_ID) && ((priv->variant != RK809_ID))) {
1375*4882a593Smuzhiyun 		debug("Not support pmic variant: rk%x\n", priv->variant);
1376*4882a593Smuzhiyun 		return -EINVAL;
1377*4882a593Smuzhiyun 	}
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun 	return rk817_fg_init(battery);
1380*4882a593Smuzhiyun }
1381*4882a593Smuzhiyun 
1382*4882a593Smuzhiyun U_BOOT_DRIVER(rk817_fg) = {
1383*4882a593Smuzhiyun 	.name = "rk817_fg",
1384*4882a593Smuzhiyun 	.id = UCLASS_FG,
1385*4882a593Smuzhiyun 	.probe = rk817_fg_probe,
1386*4882a593Smuzhiyun 	.ops = &fg_ops,
1387*4882a593Smuzhiyun 	.ofdata_to_platdata = rk817_fg_ofdata_to_platdata,
1388*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rk817_battery_device),
1389*4882a593Smuzhiyun };
1390