1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * rk817 battery driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2018 Rockchip Corporation
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
7*4882a593Smuzhiyun * it under the terms of the GNU General Public License as published by
8*4882a593Smuzhiyun * the Free Software Foundation; either version 2 of the License, or
9*4882a593Smuzhiyun * (at your option) any later version.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful,
12*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FR A PARTICULAR PURPOSE. See the
14*4882a593Smuzhiyun * GNU General Public License for more details.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun */
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #define pr_fmt(fmt) "rk817-bat: " fmt
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <linux/delay.h>
21*4882a593Smuzhiyun #include <linux/extcon.h>
22*4882a593Smuzhiyun #include <linux/fb.h>
23*4882a593Smuzhiyun #include <linux/gpio.h>
24*4882a593Smuzhiyun #include <linux/iio/consumer.h>
25*4882a593Smuzhiyun #include <linux/iio/iio.h>
26*4882a593Smuzhiyun #include <linux/irq.h>
27*4882a593Smuzhiyun #include <linux/jiffies.h>
28*4882a593Smuzhiyun #include <linux/mfd/rk808.h>
29*4882a593Smuzhiyun #include <linux/module.h>
30*4882a593Smuzhiyun #include <linux/of_device.h>
31*4882a593Smuzhiyun #include <linux/of_gpio.h>
32*4882a593Smuzhiyun #include <linux/platform_device.h>
33*4882a593Smuzhiyun #include <linux/power_supply.h>
34*4882a593Smuzhiyun #include <linux/power/rk_usbbc.h>
35*4882a593Smuzhiyun #include <linux/regmap.h>
36*4882a593Smuzhiyun #include <linux/rk_keys.h>
37*4882a593Smuzhiyun #include <linux/rtc.h>
38*4882a593Smuzhiyun #include <linux/timer.h>
39*4882a593Smuzhiyun #include <linux/wakelock.h>
40*4882a593Smuzhiyun #include <linux/workqueue.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static int dbg_enable;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun module_param_named(dbg_level, dbg_enable, int, 0644);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define DBG(args...) \
47*4882a593Smuzhiyun do { \
48*4882a593Smuzhiyun if (dbg_enable) { \
49*4882a593Smuzhiyun pr_info(args); \
50*4882a593Smuzhiyun } \
51*4882a593Smuzhiyun } while (0)
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #define BAT_INFO(fmt, args...) pr_info(fmt, ##args)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #define DRIVER_VERSION "1.00"
56*4882a593Smuzhiyun #define SFT_SET_KB 1
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #define DIV(x) ((x) ? (x) : 1)
59*4882a593Smuzhiyun #define ENABLE 0x01
60*4882a593Smuzhiyun #define DISABLE 0x00
61*4882a593Smuzhiyun #define MAX_INTERPOLATE 1000
62*4882a593Smuzhiyun #define MAX_PERCENTAGE 100
63*4882a593Smuzhiyun #define MAX_INT 0x7FFF
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* RK818_GGCON */
66*4882a593Smuzhiyun #define OCV_SAMP_MIN_MSK 0x0c
67*4882a593Smuzhiyun #define OCV_SAMP_8MIN (0x00 << 2)
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define ADC_CAL_8MIN 0x00
70*4882a593Smuzhiyun #define RELAX_VOL12_UPD_MSK (RELAX_VOL1_UPD | RELAX_VOL2_UPD)
71*4882a593Smuzhiyun #define MINUTE(x) \
72*4882a593Smuzhiyun ((x) * 60)
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #define ADC_TO_CURRENT(adc_value, samp_res) \
75*4882a593Smuzhiyun (adc_value * 172 / 1000 / samp_res)
76*4882a593Smuzhiyun #define CURRENT_TO_ADC(current, samp_res) \
77*4882a593Smuzhiyun (current * 1000 * samp_res / 172)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #define ADC_TO_CAPACITY(adc_value, samp_res) \
80*4882a593Smuzhiyun (adc_value / 1000 * 172 / 3600 / samp_res)
81*4882a593Smuzhiyun #define CAPACITY_TO_ADC(capacity, samp_res) \
82*4882a593Smuzhiyun (capacity * samp_res * 3600 / 172 * 1000)
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun #define ADC_TO_CAPACITY_UAH(adc_value, samp_res) \
85*4882a593Smuzhiyun (adc_value / 3600 * 172 / samp_res)
86*4882a593Smuzhiyun #define ADC_TO_CAPACITY_MAH(adc_value, samp_res) \
87*4882a593Smuzhiyun (adc_value / 1000 * 172 / 3600 / samp_res)
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* THREAML_REG */
90*4882a593Smuzhiyun #define TEMP_85C (0x00 << 2)
91*4882a593Smuzhiyun #define TEMP_95C (0x01 << 2)
92*4882a593Smuzhiyun #define TEMP_105C (0x02 << 2)
93*4882a593Smuzhiyun #define TEMP_115C (0x03 << 2)
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun #define ZERO_LOAD_LVL1 1400
96*4882a593Smuzhiyun #define ZERO_LOAD_LVL2 600
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* zero algorithm */
99*4882a593Smuzhiyun #define PWROFF_THRESD 3400
100*4882a593Smuzhiyun #define MIN_ZERO_DSOC_ACCURACY 10 /*0.01%*/
101*4882a593Smuzhiyun #define MIN_ZERO_OVERCNT 100
102*4882a593Smuzhiyun #define MIN_ACCURACY 1
103*4882a593Smuzhiyun #define DEF_PWRPATH_RES 50
104*4882a593Smuzhiyun #define WAIT_DSOC_DROP_SEC 15
105*4882a593Smuzhiyun #define WAIT_SHTD_DROP_SEC 30
106*4882a593Smuzhiyun #define MIN_ZERO_GAP_XSOC1 10
107*4882a593Smuzhiyun #define MIN_ZERO_GAP_XSOC2 5
108*4882a593Smuzhiyun #define MIN_ZERO_GAP_XSOC3 3
109*4882a593Smuzhiyun #define MIN_ZERO_GAP_CALIB 5
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun #define ADC_CALIB_THRESHOLD 4
112*4882a593Smuzhiyun #define ADC_CALIB_LMT_MIN 3
113*4882a593Smuzhiyun #define ADC_CALIB_CNT 5
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* default param */
116*4882a593Smuzhiyun #define DEFAULT_BAT_RES 135
117*4882a593Smuzhiyun #define DEFAULT_SLP_ENTER_CUR 300
118*4882a593Smuzhiyun #define DEFAULT_SLP_EXIT_CUR 300
119*4882a593Smuzhiyun #define DEFAULT_SLP_FILTER_CUR 100
120*4882a593Smuzhiyun #define DEFAULT_PWROFF_VOL_THRESD 3400
121*4882a593Smuzhiyun #define DEFAULT_MONITOR_SEC 5
122*4882a593Smuzhiyun #define DEFAULT_ALGR_VOL_THRESD1 3850
123*4882a593Smuzhiyun #define DEFAULT_ALGR_VOL_THRESD2 3950
124*4882a593Smuzhiyun #define DEFAULT_CHRG_VOL_SEL CHRG_VOL4200MV
125*4882a593Smuzhiyun #define DEFAULT_CHRG_CUR_SEL CHRG_CUR1400MA
126*4882a593Smuzhiyun #define DEFAULT_CHRG_CUR_INPUT INPUT_CUR2000MA
127*4882a593Smuzhiyun #define DEFAULT_POFFSET 42
128*4882a593Smuzhiyun #define DEFAULT_MAX_SOC_OFFSET 60
129*4882a593Smuzhiyun #define DEFAULT_FB_TEMP TEMP_115C
130*4882a593Smuzhiyun #define DEFAULT_ENERGY_MODE 0
131*4882a593Smuzhiyun #define DEFAULT_ZERO_RESERVE_DSOC 10
132*4882a593Smuzhiyun #define DEFAULT_SAMPLE_RES 20
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* sample resistor and division */
135*4882a593Smuzhiyun #define SAMPLE_RES_10MR 10
136*4882a593Smuzhiyun #define SAMPLE_RES_20MR 20
137*4882a593Smuzhiyun #define SAMPLE_RES_DIV1 1
138*4882a593Smuzhiyun #define SAMPLE_RES_DIV2 2
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* sleep */
141*4882a593Smuzhiyun #define SLP_CURR_MAX 40
142*4882a593Smuzhiyun #define SLP_CURR_MIN 6
143*4882a593Smuzhiyun #define LOW_PWR_SLP_CURR_MAX 20
144*4882a593Smuzhiyun #define LOW_PWR_SLP_CURR_MIN 1
145*4882a593Smuzhiyun #define DISCHRG_TIME_STEP1 MINUTE(10)
146*4882a593Smuzhiyun #define DISCHRG_TIME_STEP2 MINUTE(60)
147*4882a593Smuzhiyun #define SLP_DSOC_VOL_THRESD 3600
148*4882a593Smuzhiyun #define REBOOT_PERIOD_SEC 180
149*4882a593Smuzhiyun #define REBOOT_MAX_CNT 80
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun #define TIMER_MS_COUNTS 1000
152*4882a593Smuzhiyun /* fcc */
153*4882a593Smuzhiyun #define MIN_FCC 500
154*4882a593Smuzhiyun #define CAP_INVALID 0x80
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /* virtual params */
157*4882a593Smuzhiyun #define VIRTUAL_CURRENT 1000
158*4882a593Smuzhiyun #define VIRTUAL_VOLTAGE 3888
159*4882a593Smuzhiyun #define VIRTUAL_SOC 66
160*4882a593Smuzhiyun #define VIRTUAL_PRESET 1
161*4882a593Smuzhiyun #define VIRTUAL_TEMPERATURE 188
162*4882a593Smuzhiyun #define VIRTUAL_STATUS POWER_SUPPLY_STATUS_CHARGING
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun #define FINISH_CHRG_CUR1 1000
165*4882a593Smuzhiyun #define FINISH_CHRG_CUR2 1500
166*4882a593Smuzhiyun #define FINISH_MAX_SOC_DELAY 20
167*4882a593Smuzhiyun #define TERM_CHRG_DSOC 88
168*4882a593Smuzhiyun #define TERM_CHRG_CURR 600
169*4882a593Smuzhiyun #define TERM_CHRG_K 650
170*4882a593Smuzhiyun #define SIMULATE_CHRG_INTV 8
171*4882a593Smuzhiyun #define SIMULATE_CHRG_CURR 400
172*4882a593Smuzhiyun #define SIMULATE_CHRG_K 1500
173*4882a593Smuzhiyun #define FULL_CHRG_K 400
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun enum work_mode {
176*4882a593Smuzhiyun MODE_ZERO = 0,
177*4882a593Smuzhiyun MODE_FINISH,
178*4882a593Smuzhiyun MODE_SMOOTH_CHRG,
179*4882a593Smuzhiyun MODE_SMOOTH_DISCHRG,
180*4882a593Smuzhiyun MODE_SMOOTH,
181*4882a593Smuzhiyun };
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun enum charge_status {
184*4882a593Smuzhiyun CHRG_OFF,
185*4882a593Smuzhiyun DEAD_CHRG,
186*4882a593Smuzhiyun TRICKLE_CHRG,
187*4882a593Smuzhiyun CC_OR_CV_CHRG,
188*4882a593Smuzhiyun CHARGE_FINISH,
189*4882a593Smuzhiyun USB_OVER_VOL,
190*4882a593Smuzhiyun BAT_TMP_ERR,
191*4882a593Smuzhiyun BAT_TIM_ERR,
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun enum bat_mode {
195*4882a593Smuzhiyun MODE_BATTARY = 0,
196*4882a593Smuzhiyun MODE_VIRTUAL,
197*4882a593Smuzhiyun };
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun enum rk817_sample_time {
200*4882a593Smuzhiyun S_8_MIN,
201*4882a593Smuzhiyun S_16_MIN,
202*4882a593Smuzhiyun S_32_MIN,
203*4882a593Smuzhiyun S_48_MIN,
204*4882a593Smuzhiyun };
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun enum rk817_output_mode {
207*4882a593Smuzhiyun AVERAGE_MODE,
208*4882a593Smuzhiyun INSTANT_MODE,
209*4882a593Smuzhiyun };
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun enum rk817_battery_fields {
212*4882a593Smuzhiyun ADC_SLP_RATE, BAT_CUR_ADC_EN, BAT_VOL_ADC_EN,
213*4882a593Smuzhiyun USB_VOL_ADC_EN, TS_ADC_EN, SYS_VOL_ADC_EN, GG_EN, /*ADC_CONFIG0*/
214*4882a593Smuzhiyun CUR_ADC_DITH_SEL, CUR_ADC_DIH_EN, CUR_ADC_CHOP_EN,
215*4882a593Smuzhiyun CUR_ADC_CHOP_SEL, CUR_ADC_CHOP_VREF_EN, /*CUR_ADC_CFG0*/
216*4882a593Smuzhiyun CUR_ADC_VCOM_SEL, CUR_ADC_VCOM_BUF_INC, CUR_ADC_VREF_BUF_INC,
217*4882a593Smuzhiyun CUR_ADC_BIAS_DEC, CUR_ADC_IBIAS_SEL,/*CUR_ADC_CFG1*/
218*4882a593Smuzhiyun VOL_ADC_EXT_VREF_EN, VOL_ADC_DITH_SEL, VOL_ADC_DITH_EN,
219*4882a593Smuzhiyun VOL_ADC_CHOP_EN, VOL_ADC_CHOP_SEL, VOL_ADC_CHOP_VREF_EN,
220*4882a593Smuzhiyun VOL_ADC_VCOM_SEL, VOL_ADC_VCOM_BUF_INC, VOL_ADC_VREF_BUF_INC,
221*4882a593Smuzhiyun VOL_ADC_IBIAS_SEL, /*VOL_ADC_CFG1*/
222*4882a593Smuzhiyun RLX_CUR_FILTER, TS_FUN, VOL_ADC_TSCUR_SEL,
223*4882a593Smuzhiyun VOL_CALIB_UPD, CUR_CALIB_UPD, /*ADC_CONFIG1*/
224*4882a593Smuzhiyun CUR_OUT_MOD, VOL_OUT_MOD, FRAME_SMP_INTERV,
225*4882a593Smuzhiyun ADC_OFF_CAL_INTERV, RLX_SPT, /*GG_CON*/
226*4882a593Smuzhiyun OCV_UPD, RELAX_STS, RELAX_VOL2_UPD, RELAX_VOL1_UPD, BAT_CON,
227*4882a593Smuzhiyun QMAX_UPD_SOFT, TERM_UPD, OCV_STS, /*GG_STS*/
228*4882a593Smuzhiyun RELAX_THRE_H, RELAX_THRE_L, /*RELAX_THRE*/
229*4882a593Smuzhiyun RELAX_VOL1_H, RELAX_VOL1_L,
230*4882a593Smuzhiyun RELAX_VOL2_H, RELAX_VOL2_L,
231*4882a593Smuzhiyun RELAX_CUR1_H, RELAX_CUR1_L,
232*4882a593Smuzhiyun RELAX_CUR2_H, RELAX_CUR2_L,
233*4882a593Smuzhiyun OCV_THRE_VOL,
234*4882a593Smuzhiyun OCV_VOL_H, OCV_VOL_L,
235*4882a593Smuzhiyun OCV_VOL0_H, OCV_VOL0_L,
236*4882a593Smuzhiyun OCV_CUR_H, OCV_CUR_L,
237*4882a593Smuzhiyun OCV_CUR0_H, OCV_CUR0_L,
238*4882a593Smuzhiyun PWRON_VOL_H, PWRON_VOL_L,
239*4882a593Smuzhiyun PWRON_CUR_H, PWRON_CUR_L,
240*4882a593Smuzhiyun OFF_CNT,
241*4882a593Smuzhiyun Q_INIT_H3, Q_INIT_H2, Q_INIT_L1, Q_INIT_L0,
242*4882a593Smuzhiyun Q_PRESS_H3, Q_PRESS_H2, Q_PRESS_L1, Q_PRESS_L0,
243*4882a593Smuzhiyun BAT_VOL_H, BAT_VOL_L,
244*4882a593Smuzhiyun BAT_CUR_H, BAT_CUR_L,
245*4882a593Smuzhiyun BAT_TS_H, BAT_TS_L,
246*4882a593Smuzhiyun USB_VOL_H, USB_VOL_L,
247*4882a593Smuzhiyun SYS_VOL_H, SYS_VOL_L,
248*4882a593Smuzhiyun Q_MAX_H3, Q_MAX_H2, Q_MAX_L1, Q_MAX_L0,
249*4882a593Smuzhiyun Q_TERM_H3, Q_TERM_H2, Q_TERM_L1, Q_TERM_L0,
250*4882a593Smuzhiyun Q_OCV_H3, Q_OCV_H2, Q_OCV_L1, Q_OCV_L0,
251*4882a593Smuzhiyun OCV_CNT,
252*4882a593Smuzhiyun SLEEP_CON_SAMP_CUR_H, SLEEP_CON_SAMP_CUR_L,
253*4882a593Smuzhiyun CAL_OFFSET_H, CAL_OFFSET_L,
254*4882a593Smuzhiyun VCALIB0_H, VCALIB0_L,
255*4882a593Smuzhiyun VCALIB1_H, VCALIB1_L,
256*4882a593Smuzhiyun IOFFSET_H, IOFFSET_L,
257*4882a593Smuzhiyun BAT_R0, SOC_REG0, SOC_REG1, SOC_REG2,
258*4882a593Smuzhiyun REMAIN_CAP_REG2, REMAIN_CAP_REG1, REMAIN_CAP_REG0,
259*4882a593Smuzhiyun NEW_FCC_REG2, NEW_FCC_REG1, NEW_FCC_REG0,
260*4882a593Smuzhiyun RESET_MODE,
261*4882a593Smuzhiyun FG_INIT, HALT_CNT_REG, CALC_REST_REGL, CALC_REST_REGH,
262*4882a593Smuzhiyun VOL_ADC_B3, VOL_ADC_B2, VOL_ADC_B1, VOL_ADC_B0,
263*4882a593Smuzhiyun VOL_ADC_K3, VOL_ADC_K2, VOL_ADC_K1, VOL_ADC_K0,
264*4882a593Smuzhiyun BAT_EXS, CHG_STS, BAT_OVP_STS, CHRG_IN_CLAMP,
265*4882a593Smuzhiyun CHIP_NAME_H, CHIP_NAME_L,
266*4882a593Smuzhiyun PLUG_IN_STS,
267*4882a593Smuzhiyun F_MAX_FIELDS
268*4882a593Smuzhiyun };
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun static const struct reg_field rk817_battery_reg_fields[] = {
271*4882a593Smuzhiyun [ADC_SLP_RATE] = REG_FIELD(0x50, 0, 0),
272*4882a593Smuzhiyun [BAT_CUR_ADC_EN] = REG_FIELD(0x50, 2, 2),
273*4882a593Smuzhiyun [BAT_VOL_ADC_EN] = REG_FIELD(0x50, 3, 3),
274*4882a593Smuzhiyun [USB_VOL_ADC_EN] = REG_FIELD(0x50, 4, 4),
275*4882a593Smuzhiyun [TS_ADC_EN] = REG_FIELD(0x50, 5, 5),
276*4882a593Smuzhiyun [SYS_VOL_ADC_EN] = REG_FIELD(0x50, 6, 6),
277*4882a593Smuzhiyun [GG_EN] = REG_FIELD(0x50, 7, 7),/*ADC_CONFIG0*/
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun [CUR_ADC_DITH_SEL] = REG_FIELD(0x51, 1, 3),
280*4882a593Smuzhiyun [CUR_ADC_DIH_EN] = REG_FIELD(0x51, 4, 4),
281*4882a593Smuzhiyun [CUR_ADC_CHOP_EN] = REG_FIELD(0x51, 5, 5),
282*4882a593Smuzhiyun [CUR_ADC_CHOP_SEL] = REG_FIELD(0x51, 6, 6),
283*4882a593Smuzhiyun [CUR_ADC_CHOP_VREF_EN] = REG_FIELD(0x51, 7, 7), /*CUR_ADC_COFG0*/
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun [CUR_ADC_VCOM_SEL] = REG_FIELD(0x52, 0, 1),
286*4882a593Smuzhiyun [CUR_ADC_VCOM_BUF_INC] = REG_FIELD(0x52, 2, 2),
287*4882a593Smuzhiyun [CUR_ADC_VREF_BUF_INC] = REG_FIELD(0x52, 3, 3),
288*4882a593Smuzhiyun [CUR_ADC_BIAS_DEC] = REG_FIELD(0x52, 4, 4),
289*4882a593Smuzhiyun [CUR_ADC_IBIAS_SEL] = REG_FIELD(0x52, 5, 6), /*CUR_ADC_COFG1*/
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun [VOL_ADC_EXT_VREF_EN] = REG_FIELD(0x53, 0, 0),
292*4882a593Smuzhiyun [VOL_ADC_DITH_SEL] = REG_FIELD(0x53, 1, 3),
293*4882a593Smuzhiyun [VOL_ADC_DITH_EN] = REG_FIELD(0x53, 4, 4),
294*4882a593Smuzhiyun [VOL_ADC_CHOP_EN] = REG_FIELD(0x53, 5, 5),
295*4882a593Smuzhiyun [VOL_ADC_CHOP_SEL] = REG_FIELD(0x53, 6, 6),
296*4882a593Smuzhiyun [VOL_ADC_CHOP_VREF_EN] = REG_FIELD(0x53, 7, 7),/*VOL_ADC_COFG0*/
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun [VOL_ADC_VCOM_SEL] = REG_FIELD(0x54, 0, 1),
299*4882a593Smuzhiyun [VOL_ADC_VCOM_BUF_INC] = REG_FIELD(0x54, 2, 2),
300*4882a593Smuzhiyun [VOL_ADC_VREF_BUF_INC] = REG_FIELD(0x54, 3, 3),
301*4882a593Smuzhiyun [VOL_ADC_IBIAS_SEL] = REG_FIELD(0x54, 5, 6), /*VOL_ADC_COFG1*/
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun [RLX_CUR_FILTER] = REG_FIELD(0x55, 0, 1),
304*4882a593Smuzhiyun [TS_FUN] = REG_FIELD(0x55, 3, 3),
305*4882a593Smuzhiyun [VOL_ADC_TSCUR_SEL] = REG_FIELD(0x55, 4, 5),
306*4882a593Smuzhiyun [VOL_CALIB_UPD] = REG_FIELD(0x55, 6, 6),
307*4882a593Smuzhiyun [CUR_CALIB_UPD] = REG_FIELD(0x55, 7, 7), /*ADC_CONFIG1*/
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun [CUR_OUT_MOD] = REG_FIELD(0x56, 0, 0),
310*4882a593Smuzhiyun [VOL_OUT_MOD] = REG_FIELD(0x56, 1, 1),
311*4882a593Smuzhiyun [FRAME_SMP_INTERV] = REG_FIELD(0x56, 2, 3),
312*4882a593Smuzhiyun [ADC_OFF_CAL_INTERV] = REG_FIELD(0x56, 4, 5),
313*4882a593Smuzhiyun [RLX_SPT] = REG_FIELD(0x56, 6, 7), /*GG_CON*/
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun [OCV_UPD] = REG_FIELD(0x57, 0, 0),
316*4882a593Smuzhiyun [RELAX_STS] = REG_FIELD(0x57, 1, 1),
317*4882a593Smuzhiyun [RELAX_VOL2_UPD] = REG_FIELD(0x57, 2, 2),
318*4882a593Smuzhiyun [RELAX_VOL1_UPD] = REG_FIELD(0x57, 3, 3),
319*4882a593Smuzhiyun [BAT_CON] = REG_FIELD(0x57, 4, 4),
320*4882a593Smuzhiyun [QMAX_UPD_SOFT] = REG_FIELD(0x57, 5, 5),
321*4882a593Smuzhiyun [TERM_UPD] = REG_FIELD(0x57, 6, 6),
322*4882a593Smuzhiyun [OCV_STS] = REG_FIELD(0x57, 7, 7), /*GG_STS*/
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun [RELAX_THRE_H] = REG_FIELD(0x58, 0, 7),
325*4882a593Smuzhiyun [RELAX_THRE_L] = REG_FIELD(0x59, 0, 7),
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun [RELAX_VOL1_H] = REG_FIELD(0x5A, 0, 7),
328*4882a593Smuzhiyun [RELAX_VOL1_L] = REG_FIELD(0x5B, 0, 7),
329*4882a593Smuzhiyun [RELAX_VOL2_H] = REG_FIELD(0x5C, 0, 7),
330*4882a593Smuzhiyun [RELAX_VOL2_L] = REG_FIELD(0x5D, 0, 7),
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun [RELAX_CUR1_H] = REG_FIELD(0x5E, 0, 7),
333*4882a593Smuzhiyun [RELAX_CUR1_L] = REG_FIELD(0x5F, 0, 7),
334*4882a593Smuzhiyun [RELAX_CUR2_H] = REG_FIELD(0x60, 0, 7),
335*4882a593Smuzhiyun [RELAX_CUR2_L] = REG_FIELD(0x61, 0, 7),
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun [OCV_THRE_VOL] = REG_FIELD(0x62, 0, 7),
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun [OCV_VOL_H] = REG_FIELD(0x63, 0, 7),
340*4882a593Smuzhiyun [OCV_VOL_L] = REG_FIELD(0x64, 0, 7),
341*4882a593Smuzhiyun [OCV_VOL0_H] = REG_FIELD(0x65, 0, 7),
342*4882a593Smuzhiyun [OCV_VOL0_L] = REG_FIELD(0x66, 0, 7),
343*4882a593Smuzhiyun [OCV_CUR_H] = REG_FIELD(0x67, 0, 7),
344*4882a593Smuzhiyun [OCV_CUR_L] = REG_FIELD(0x68, 0, 7),
345*4882a593Smuzhiyun [OCV_CUR0_H] = REG_FIELD(0x69, 0, 7),
346*4882a593Smuzhiyun [OCV_CUR0_L] = REG_FIELD(0x6A, 0, 7),
347*4882a593Smuzhiyun [PWRON_VOL_H] = REG_FIELD(0x6B, 0, 7),
348*4882a593Smuzhiyun [PWRON_VOL_L] = REG_FIELD(0x6C, 0, 7),
349*4882a593Smuzhiyun [PWRON_CUR_H] = REG_FIELD(0x6D, 0, 7),
350*4882a593Smuzhiyun [PWRON_CUR_L] = REG_FIELD(0x6E, 0, 7),
351*4882a593Smuzhiyun [OFF_CNT] = REG_FIELD(0x6F, 0, 7),
352*4882a593Smuzhiyun [Q_INIT_H3] = REG_FIELD(0x70, 0, 7),
353*4882a593Smuzhiyun [Q_INIT_H2] = REG_FIELD(0x71, 0, 7),
354*4882a593Smuzhiyun [Q_INIT_L1] = REG_FIELD(0x72, 0, 7),
355*4882a593Smuzhiyun [Q_INIT_L0] = REG_FIELD(0x73, 0, 7),
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun [Q_PRESS_H3] = REG_FIELD(0x74, 0, 7),
358*4882a593Smuzhiyun [Q_PRESS_H2] = REG_FIELD(0x75, 0, 7),
359*4882a593Smuzhiyun [Q_PRESS_L1] = REG_FIELD(0x76, 0, 7),
360*4882a593Smuzhiyun [Q_PRESS_L0] = REG_FIELD(0x77, 0, 7),
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun [BAT_VOL_H] = REG_FIELD(0x78, 0, 7),
363*4882a593Smuzhiyun [BAT_VOL_L] = REG_FIELD(0x79, 0, 7),
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun [BAT_CUR_H] = REG_FIELD(0x7A, 0, 7),
366*4882a593Smuzhiyun [BAT_CUR_L] = REG_FIELD(0x7B, 0, 7),
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun [BAT_TS_H] = REG_FIELD(0x7C, 0, 7),
369*4882a593Smuzhiyun [BAT_TS_L] = REG_FIELD(0x7D, 0, 7),
370*4882a593Smuzhiyun [USB_VOL_H] = REG_FIELD(0x7E, 0, 7),
371*4882a593Smuzhiyun [USB_VOL_L] = REG_FIELD(0x7F, 0, 7),
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun [SYS_VOL_H] = REG_FIELD(0x80, 0, 7),
374*4882a593Smuzhiyun [SYS_VOL_L] = REG_FIELD(0x81, 0, 7),
375*4882a593Smuzhiyun [Q_MAX_H3] = REG_FIELD(0x82, 0, 7),
376*4882a593Smuzhiyun [Q_MAX_H2] = REG_FIELD(0x83, 0, 7),
377*4882a593Smuzhiyun [Q_MAX_L1] = REG_FIELD(0x84, 0, 7),
378*4882a593Smuzhiyun [Q_MAX_L0] = REG_FIELD(0x85, 0, 7),
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun [Q_TERM_H3] = REG_FIELD(0x86, 0, 7),
381*4882a593Smuzhiyun [Q_TERM_H2] = REG_FIELD(0x87, 0, 7),
382*4882a593Smuzhiyun [Q_TERM_L1] = REG_FIELD(0x88, 0, 7),
383*4882a593Smuzhiyun [Q_TERM_L0] = REG_FIELD(0x89, 0, 7),
384*4882a593Smuzhiyun [Q_OCV_H3] = REG_FIELD(0x8A, 0, 7),
385*4882a593Smuzhiyun [Q_OCV_H2] = REG_FIELD(0x8B, 0, 7),
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun [Q_OCV_L1] = REG_FIELD(0x8C, 0, 7),
388*4882a593Smuzhiyun [Q_OCV_L0] = REG_FIELD(0x8D, 0, 7),
389*4882a593Smuzhiyun [OCV_CNT] = REG_FIELD(0x8E, 0, 7),
390*4882a593Smuzhiyun [SLEEP_CON_SAMP_CUR_H] = REG_FIELD(0x8F, 0, 7),
391*4882a593Smuzhiyun [SLEEP_CON_SAMP_CUR_L] = REG_FIELD(0x90, 0, 7),
392*4882a593Smuzhiyun [CAL_OFFSET_H] = REG_FIELD(0x91, 0, 7),
393*4882a593Smuzhiyun [CAL_OFFSET_L] = REG_FIELD(0x92, 0, 7),
394*4882a593Smuzhiyun [VCALIB0_H] = REG_FIELD(0x93, 0, 7),
395*4882a593Smuzhiyun [VCALIB0_L] = REG_FIELD(0x94, 0, 7),
396*4882a593Smuzhiyun [VCALIB1_H] = REG_FIELD(0x95, 0, 7),
397*4882a593Smuzhiyun [VCALIB1_L] = REG_FIELD(0x96, 0, 7),
398*4882a593Smuzhiyun [IOFFSET_H] = REG_FIELD(0x97, 0, 7),
399*4882a593Smuzhiyun [IOFFSET_L] = REG_FIELD(0x98, 0, 7),
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun [BAT_R0] = REG_FIELD(0x99, 0, 7),
402*4882a593Smuzhiyun [SOC_REG0] = REG_FIELD(0x9A, 0, 7),
403*4882a593Smuzhiyun [SOC_REG1] = REG_FIELD(0x9B, 0, 7),
404*4882a593Smuzhiyun [SOC_REG2] = REG_FIELD(0x9C, 0, 7),
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun [REMAIN_CAP_REG0] = REG_FIELD(0x9D, 0, 7),
407*4882a593Smuzhiyun [REMAIN_CAP_REG1] = REG_FIELD(0x9E, 0, 7),
408*4882a593Smuzhiyun [REMAIN_CAP_REG2] = REG_FIELD(0x9F, 0, 7),
409*4882a593Smuzhiyun [NEW_FCC_REG0] = REG_FIELD(0xA0, 0, 7),
410*4882a593Smuzhiyun [NEW_FCC_REG1] = REG_FIELD(0xA1, 0, 7),
411*4882a593Smuzhiyun [NEW_FCC_REG2] = REG_FIELD(0xA2, 0, 7),
412*4882a593Smuzhiyun [RESET_MODE] = REG_FIELD(0xA3, 0, 3),
413*4882a593Smuzhiyun [FG_INIT] = REG_FIELD(0xA5, 7, 7),
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun [HALT_CNT_REG] = REG_FIELD(0xA6, 0, 7),
416*4882a593Smuzhiyun [CALC_REST_REGL] = REG_FIELD(0xA7, 0, 7),
417*4882a593Smuzhiyun [CALC_REST_REGH] = REG_FIELD(0xA8, 0, 7),
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun [VOL_ADC_B3] = REG_FIELD(0xA9, 0, 7),
420*4882a593Smuzhiyun [VOL_ADC_B2] = REG_FIELD(0xAA, 0, 7),
421*4882a593Smuzhiyun [VOL_ADC_B1] = REG_FIELD(0xAB, 0, 7),
422*4882a593Smuzhiyun [VOL_ADC_B0] = REG_FIELD(0xAC, 0, 7),
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun [VOL_ADC_K3] = REG_FIELD(0xAD, 0, 7),
425*4882a593Smuzhiyun [VOL_ADC_K2] = REG_FIELD(0xAE, 0, 7),
426*4882a593Smuzhiyun [VOL_ADC_K1] = REG_FIELD(0xAF, 0, 7),
427*4882a593Smuzhiyun [VOL_ADC_K0] = REG_FIELD(0xB0, 0, 7),
428*4882a593Smuzhiyun [BAT_EXS] = REG_FIELD(0xEB, 7, 7),
429*4882a593Smuzhiyun [CHG_STS] = REG_FIELD(0xEB, 4, 6),
430*4882a593Smuzhiyun [BAT_OVP_STS] = REG_FIELD(0xEB, 3, 3),
431*4882a593Smuzhiyun [CHRG_IN_CLAMP] = REG_FIELD(0xEB, 2, 2),
432*4882a593Smuzhiyun [CHIP_NAME_H] = REG_FIELD(0xED, 0, 7),
433*4882a593Smuzhiyun [CHIP_NAME_L] = REG_FIELD(0xEE, 0, 7),
434*4882a593Smuzhiyun [PLUG_IN_STS] = REG_FIELD(0xF0, 6, 6),
435*4882a593Smuzhiyun };
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun struct battery_platform_data {
438*4882a593Smuzhiyun u32 *ocv_table;
439*4882a593Smuzhiyun u32 *zero_table;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun u32 table_t[4][21];
442*4882a593Smuzhiyun int temp_t[4];
443*4882a593Smuzhiyun u32 temp_t_num;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun u32 *ntc_table;
446*4882a593Smuzhiyun u32 ocv_size;
447*4882a593Smuzhiyun u32 ntc_size;
448*4882a593Smuzhiyun int ntc_degree_from;
449*4882a593Smuzhiyun u32 ntc_factor;
450*4882a593Smuzhiyun u32 max_input_current;
451*4882a593Smuzhiyun u32 max_chrg_current;
452*4882a593Smuzhiyun u32 max_chrg_voltage;
453*4882a593Smuzhiyun u32 lp_input_current;
454*4882a593Smuzhiyun u32 lp_soc_min;
455*4882a593Smuzhiyun u32 lp_soc_max;
456*4882a593Smuzhiyun u32 pwroff_vol;
457*4882a593Smuzhiyun u32 monitor_sec;
458*4882a593Smuzhiyun u32 zero_algorithm_vol;
459*4882a593Smuzhiyun u32 zero_reserve_dsoc;
460*4882a593Smuzhiyun u32 bat_res;
461*4882a593Smuzhiyun u32 design_capacity;
462*4882a593Smuzhiyun u32 design_qmax;
463*4882a593Smuzhiyun u32 sleep_enter_current;
464*4882a593Smuzhiyun u32 sleep_exit_current;
465*4882a593Smuzhiyun u32 sleep_filter_current;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun u32 power_dc2otg;
468*4882a593Smuzhiyun u32 max_soc_offset;
469*4882a593Smuzhiyun u32 bat_mode;
470*4882a593Smuzhiyun u32 fb_temp;
471*4882a593Smuzhiyun u32 energy_mode;
472*4882a593Smuzhiyun u32 cccv_hour;
473*4882a593Smuzhiyun u32 dc_det_adc;
474*4882a593Smuzhiyun int dc_det_pin;
475*4882a593Smuzhiyun u8 dc_det_level;
476*4882a593Smuzhiyun u32 sample_res;
477*4882a593Smuzhiyun u32 bat_res_up;
478*4882a593Smuzhiyun u32 bat_res_down;
479*4882a593Smuzhiyun u32 design_max_voltage;
480*4882a593Smuzhiyun bool extcon;
481*4882a593Smuzhiyun u32 low_pwr_sleep;
482*4882a593Smuzhiyun };
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun struct rk817_battery_device {
485*4882a593Smuzhiyun struct platform_device *pdev;
486*4882a593Smuzhiyun struct device *dev;
487*4882a593Smuzhiyun struct i2c_client *client;
488*4882a593Smuzhiyun struct rk808 *rk817;
489*4882a593Smuzhiyun struct power_supply *bat;
490*4882a593Smuzhiyun struct power_supply *chg_psy;
491*4882a593Smuzhiyun struct power_supply *usb_psy;
492*4882a593Smuzhiyun struct power_supply *ac_psy;
493*4882a593Smuzhiyun struct regmap *regmap;
494*4882a593Smuzhiyun struct regmap_field *rmap_fields[F_MAX_FIELDS];
495*4882a593Smuzhiyun struct battery_platform_data *pdata;
496*4882a593Smuzhiyun struct workqueue_struct *bat_monitor_wq;
497*4882a593Smuzhiyun struct delayed_work bat_delay_work;
498*4882a593Smuzhiyun struct delayed_work calib_delay_work;
499*4882a593Smuzhiyun struct work_struct resume_work;
500*4882a593Smuzhiyun struct wake_lock wake_lock;
501*4882a593Smuzhiyun struct timer_list caltimer;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun int res_div;
504*4882a593Smuzhiyun int bat_res;
505*4882a593Smuzhiyun bool is_first_power_on;
506*4882a593Smuzhiyun int chrg_status;
507*4882a593Smuzhiyun int res_fac;
508*4882a593Smuzhiyun int over_20mR;
509*4882a593Smuzhiyun bool is_initialized;
510*4882a593Smuzhiyun bool bat_first_power_on;
511*4882a593Smuzhiyun u8 ac_in;
512*4882a593Smuzhiyun u8 usb_in;
513*4882a593Smuzhiyun u8 otg_in;
514*4882a593Smuzhiyun u8 dc_in;
515*4882a593Smuzhiyun u8 prop_status;
516*4882a593Smuzhiyun int cvtlmt_irq;
517*4882a593Smuzhiyun int current_avg;
518*4882a593Smuzhiyun int current_relax;
519*4882a593Smuzhiyun int voltage_usb;
520*4882a593Smuzhiyun int voltage_sys;
521*4882a593Smuzhiyun int voltage_avg;
522*4882a593Smuzhiyun int voltage_ocv;
523*4882a593Smuzhiyun int voltage_relax;
524*4882a593Smuzhiyun int voltage_k;/* VCALIB0 VCALIB1 */
525*4882a593Smuzhiyun int voltage_b;
526*4882a593Smuzhiyun u32 remain_cap;
527*4882a593Smuzhiyun int design_cap;
528*4882a593Smuzhiyun int nac;
529*4882a593Smuzhiyun int fcc;
530*4882a593Smuzhiyun int lock_fcc;
531*4882a593Smuzhiyun int qmax;
532*4882a593Smuzhiyun int dsoc;
533*4882a593Smuzhiyun int rsoc;
534*4882a593Smuzhiyun int poffset;
535*4882a593Smuzhiyun int fake_offline;
536*4882a593Smuzhiyun int age_ocv_soc;
537*4882a593Smuzhiyun bool age_allow_update;
538*4882a593Smuzhiyun int age_level;
539*4882a593Smuzhiyun int age_ocv_cap;
540*4882a593Smuzhiyun int pwron_voltage;
541*4882a593Smuzhiyun int age_voltage;
542*4882a593Smuzhiyun int age_adjust_cap;
543*4882a593Smuzhiyun unsigned long age_keep_sec;
544*4882a593Smuzhiyun int zero_timeout_cnt;
545*4882a593Smuzhiyun int zero_remain_cap;
546*4882a593Smuzhiyun int zero_dsoc;
547*4882a593Smuzhiyun int zero_linek;
548*4882a593Smuzhiyun u64 zero_drop_sec;
549*4882a593Smuzhiyun u64 shtd_drop_sec;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun int powerpatch_res;
552*4882a593Smuzhiyun int zero_voltage_avg;
553*4882a593Smuzhiyun int zero_current_avg;
554*4882a593Smuzhiyun int zero_vsys;
555*4882a593Smuzhiyun int zero_dead_voltage;
556*4882a593Smuzhiyun int zero_dead_soc;
557*4882a593Smuzhiyun int zero_dead_cap;
558*4882a593Smuzhiyun int zero_batvol_to_ocv;
559*4882a593Smuzhiyun int zero_batocv_to_soc;
560*4882a593Smuzhiyun int zero_batocv_to_cap;
561*4882a593Smuzhiyun int zero_xsoc;
562*4882a593Smuzhiyun unsigned long finish_base;
563*4882a593Smuzhiyun time64_t rtc_base;
564*4882a593Smuzhiyun int sm_remain_cap;
565*4882a593Smuzhiyun int sm_linek;
566*4882a593Smuzhiyun int sm_chrg_dsoc;
567*4882a593Smuzhiyun int sm_dischrg_dsoc;
568*4882a593Smuzhiyun int smooth_soc;
569*4882a593Smuzhiyun int algo_rest_val;
570*4882a593Smuzhiyun int algo_rest_mode;
571*4882a593Smuzhiyun int sleep_sum_cap;
572*4882a593Smuzhiyun int sleep_remain_cap;
573*4882a593Smuzhiyun unsigned long sleep_dischrg_sec;
574*4882a593Smuzhiyun unsigned long sleep_sum_sec;
575*4882a593Smuzhiyun bool sleep_chrg_online;
576*4882a593Smuzhiyun u8 sleep_chrg_status;
577*4882a593Smuzhiyun bool adc_allow_update;
578*4882a593Smuzhiyun int fb_blank;
579*4882a593Smuzhiyun bool s2r; /*suspend to resume*/
580*4882a593Smuzhiyun u32 work_mode;
581*4882a593Smuzhiyun int temperature;
582*4882a593Smuzhiyun int chrg_cur_lp_input;
583*4882a593Smuzhiyun int chrg_vol_sel;
584*4882a593Smuzhiyun int chrg_cur_input;
585*4882a593Smuzhiyun int chrg_cur_sel;
586*4882a593Smuzhiyun u32 monitor_ms;
587*4882a593Smuzhiyun u32 pwroff_min;
588*4882a593Smuzhiyun u32 adc_calib_cnt;
589*4882a593Smuzhiyun unsigned long chrg_finish_base;
590*4882a593Smuzhiyun unsigned long boot_base;
591*4882a593Smuzhiyun unsigned long flat_match_sec;
592*4882a593Smuzhiyun unsigned long plug_in_base;
593*4882a593Smuzhiyun unsigned long plug_out_base;
594*4882a593Smuzhiyun u8 halt_cnt;
595*4882a593Smuzhiyun bool is_halt;
596*4882a593Smuzhiyun bool is_max_soc_offset;
597*4882a593Smuzhiyun bool is_sw_reset;
598*4882a593Smuzhiyun bool is_ocv_calib;
599*4882a593Smuzhiyun bool is_first_on;
600*4882a593Smuzhiyun bool is_force_calib;
601*4882a593Smuzhiyun int last_dsoc;
602*4882a593Smuzhiyun u8 cvtlmt_int_event;
603*4882a593Smuzhiyun u8 slp_dcdc_en_reg;
604*4882a593Smuzhiyun int ocv_pre_dsoc;
605*4882a593Smuzhiyun int ocv_new_dsoc;
606*4882a593Smuzhiyun int max_pre_dsoc;
607*4882a593Smuzhiyun int max_new_dsoc;
608*4882a593Smuzhiyun int force_pre_dsoc;
609*4882a593Smuzhiyun int force_new_dsoc;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun int dbg_cap_low0;
612*4882a593Smuzhiyun int dbg_pwr_dsoc;
613*4882a593Smuzhiyun int dbg_pwr_rsoc;
614*4882a593Smuzhiyun int dbg_pwr_vol;
615*4882a593Smuzhiyun int dbg_chrg_min[10];
616*4882a593Smuzhiyun int dbg_meet_soc;
617*4882a593Smuzhiyun int dbg_calc_dsoc;
618*4882a593Smuzhiyun int dbg_calc_rsoc;
619*4882a593Smuzhiyun int is_charging;
620*4882a593Smuzhiyun unsigned long charge_count;
621*4882a593Smuzhiyun u8 plugin_trigger;
622*4882a593Smuzhiyun u8 plugout_trigger;
623*4882a593Smuzhiyun int plugin_irq;
624*4882a593Smuzhiyun int plugout_irq;
625*4882a593Smuzhiyun int chip_id;
626*4882a593Smuzhiyun int is_register_chg_psy;
627*4882a593Smuzhiyun bool change; /* Battery status change, report information */
628*4882a593Smuzhiyun };
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun static void rk817_bat_resume_work(struct work_struct *work);
631*4882a593Smuzhiyun
get_boot_sec(void)632*4882a593Smuzhiyun static u64 get_boot_sec(void)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun struct timespec64 ts;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun ktime_get_boottime_ts64(&ts);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun return ts.tv_sec;
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun
base2sec(unsigned long x)641*4882a593Smuzhiyun static unsigned long base2sec(unsigned long x)
642*4882a593Smuzhiyun {
643*4882a593Smuzhiyun if (x)
644*4882a593Smuzhiyun return (get_boot_sec() > x) ? (get_boot_sec() - x) : 0;
645*4882a593Smuzhiyun else
646*4882a593Smuzhiyun return 0;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun
interpolate(int value,u32 * table,int size)649*4882a593Smuzhiyun static u32 interpolate(int value, u32 *table, int size)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun u8 i;
652*4882a593Smuzhiyun u16 d;
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun for (i = 0; i < size; i++) {
655*4882a593Smuzhiyun if (value < table[i])
656*4882a593Smuzhiyun break;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if ((i > 0) && (i < size)) {
660*4882a593Smuzhiyun d = (value - table[i - 1]) * (MAX_INTERPOLATE / (size - 1));
661*4882a593Smuzhiyun d /= table[i] - table[i - 1];
662*4882a593Smuzhiyun d = d + (i - 1) * (MAX_INTERPOLATE / (size - 1));
663*4882a593Smuzhiyun } else {
664*4882a593Smuzhiyun d = i * ((MAX_INTERPOLATE + size / 2) / size);
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun if (d > 1000)
668*4882a593Smuzhiyun d = 1000;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun return d;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun /* (a * b) / c */
ab_div_c(u32 a,u32 b,u32 c)674*4882a593Smuzhiyun static int32_t ab_div_c(u32 a, u32 b, u32 c)
675*4882a593Smuzhiyun {
676*4882a593Smuzhiyun bool sign;
677*4882a593Smuzhiyun u32 ans = MAX_INT;
678*4882a593Smuzhiyun int tmp;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun sign = ((((a ^ b) ^ c) & 0x80000000) != 0);
681*4882a593Smuzhiyun if (c != 0) {
682*4882a593Smuzhiyun if (sign)
683*4882a593Smuzhiyun c = -c;
684*4882a593Smuzhiyun tmp = (a * b + (c >> 1)) / c;
685*4882a593Smuzhiyun if (tmp < MAX_INT)
686*4882a593Smuzhiyun ans = tmp;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun if (sign)
690*4882a593Smuzhiyun ans = -ans;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun return ans;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
rk817_bat_field_read(struct rk817_battery_device * battery,enum rk817_battery_fields field_id)695*4882a593Smuzhiyun static int rk817_bat_field_read(struct rk817_battery_device *battery,
696*4882a593Smuzhiyun enum rk817_battery_fields field_id)
697*4882a593Smuzhiyun {
698*4882a593Smuzhiyun int val;
699*4882a593Smuzhiyun int ret;
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun ret = regmap_field_read(battery->rmap_fields[field_id], &val);
702*4882a593Smuzhiyun if (ret < 0)
703*4882a593Smuzhiyun return ret;
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun return val;
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun
rk817_bat_field_write(struct rk817_battery_device * battery,enum rk817_battery_fields field_id,unsigned int val)708*4882a593Smuzhiyun static int rk817_bat_field_write(struct rk817_battery_device *battery,
709*4882a593Smuzhiyun enum rk817_battery_fields field_id,
710*4882a593Smuzhiyun unsigned int val)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun return regmap_field_write(battery->rmap_fields[field_id], val);
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun /*cal_offset: current offset value*/
rk817_bat_get_coffset(struct rk817_battery_device * battery)716*4882a593Smuzhiyun static int rk817_bat_get_coffset(struct rk817_battery_device *battery)
717*4882a593Smuzhiyun {
718*4882a593Smuzhiyun int coffset_value = 0;
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun coffset_value |= rk817_bat_field_read(battery, CAL_OFFSET_H) << 8;
721*4882a593Smuzhiyun coffset_value |= rk817_bat_field_read(battery, CAL_OFFSET_L);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun return coffset_value;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
rk817_bat_set_coffset(struct rk817_battery_device * battery,int val)726*4882a593Smuzhiyun static void rk817_bat_set_coffset(struct rk817_battery_device *battery, int val)
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun u8 buf = 0;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun buf = (val >> 8) & 0xff;
731*4882a593Smuzhiyun rk817_bat_field_write(battery, CAL_OFFSET_H, buf);
732*4882a593Smuzhiyun buf = (val >> 0) & 0xff;
733*4882a593Smuzhiyun rk817_bat_field_write(battery, CAL_OFFSET_L, buf);
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun /* current offset value calculated */
rk817_bat_get_ioffset(struct rk817_battery_device * battery)737*4882a593Smuzhiyun static int rk817_bat_get_ioffset(struct rk817_battery_device *battery)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun int ioffset_value = 0;
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun ioffset_value |= rk817_bat_field_read(battery, IOFFSET_H) << 8;
742*4882a593Smuzhiyun ioffset_value |= rk817_bat_field_read(battery, IOFFSET_L);
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun return ioffset_value;
745*4882a593Smuzhiyun }
746*4882a593Smuzhiyun
rk817_bat_current_calibration(struct rk817_battery_device * battery)747*4882a593Smuzhiyun static void rk817_bat_current_calibration(struct rk817_battery_device *battery)
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun int pwron_value, ioffset, cal_offset;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun pwron_value = rk817_bat_field_read(battery, PWRON_CUR_H) << 8;
752*4882a593Smuzhiyun pwron_value |= rk817_bat_field_read(battery, PWRON_CUR_L);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun ioffset = rk817_bat_get_ioffset(battery);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun DBG("Caloffset: 0x%x\n", rk817_bat_get_coffset(battery));
757*4882a593Smuzhiyun DBG("IOFFSET: 0x%x\n", ioffset);
758*4882a593Smuzhiyun if (0)
759*4882a593Smuzhiyun cal_offset = pwron_value + ioffset;
760*4882a593Smuzhiyun else
761*4882a593Smuzhiyun cal_offset = ioffset;
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun rk817_bat_set_coffset(battery, cal_offset);
764*4882a593Smuzhiyun DBG("Caloffset: 0x%x\n", rk817_bat_get_coffset(battery));
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun
rk817_bat_get_vaclib0(struct rk817_battery_device * battery)768*4882a593Smuzhiyun static int rk817_bat_get_vaclib0(struct rk817_battery_device *battery)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun int vcalib_value = 0;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun vcalib_value |= rk817_bat_field_read(battery, VCALIB0_H) << 8;
773*4882a593Smuzhiyun vcalib_value |= rk817_bat_field_read(battery, VCALIB0_L);
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun return vcalib_value;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun
rk817_bat_get_vaclib1(struct rk817_battery_device * battery)778*4882a593Smuzhiyun static int rk817_bat_get_vaclib1(struct rk817_battery_device *battery)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun int vcalib_value = 0;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun vcalib_value |= rk817_bat_field_read(battery, VCALIB1_H) << 8;
783*4882a593Smuzhiyun vcalib_value |= rk817_bat_field_read(battery, VCALIB1_L);
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun return vcalib_value;
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun
rk817_bat_init_voltage_kb(struct rk817_battery_device * battery)788*4882a593Smuzhiyun static void rk817_bat_init_voltage_kb(struct rk817_battery_device *battery)
789*4882a593Smuzhiyun {
790*4882a593Smuzhiyun int vcalib0, vcalib1;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun vcalib0 = rk817_bat_get_vaclib0(battery);
793*4882a593Smuzhiyun vcalib1 = rk817_bat_get_vaclib1(battery);
794*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
795*4882a593Smuzhiyun battery->voltage_k = (1050 - 600) * 1000 / DIV(vcalib1 - vcalib0);
796*4882a593Smuzhiyun battery->voltage_b = 1050 - (battery->voltage_k * vcalib1) / 1000;
797*4882a593Smuzhiyun } else {
798*4882a593Smuzhiyun battery->voltage_k = (4025 - 2300) * 1000 / DIV(vcalib1 - vcalib0);
799*4882a593Smuzhiyun battery->voltage_b = 4025 - (battery->voltage_k * vcalib1) / 1000;
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
rk817_bat_restart_relax(struct rk817_battery_device * battery)803*4882a593Smuzhiyun static void rk817_bat_restart_relax(struct rk817_battery_device *battery)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun rk817_bat_field_write(battery, RELAX_VOL1_UPD, 0x00);
806*4882a593Smuzhiyun rk817_bat_field_write(battery, RELAX_VOL2_UPD, 0x00);
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun
is_rk817_bat_relax_mode(struct rk817_battery_device * battery)809*4882a593Smuzhiyun static bool is_rk817_bat_relax_mode(struct rk817_battery_device *battery)
810*4882a593Smuzhiyun {
811*4882a593Smuzhiyun u8 relax_sts, relax_vol1_upd, relax_vol2_upd;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun relax_sts = rk817_bat_field_read(battery, RELAX_STS);
814*4882a593Smuzhiyun relax_vol1_upd = rk817_bat_field_read(battery, RELAX_VOL1_UPD);
815*4882a593Smuzhiyun relax_vol2_upd = rk817_bat_field_read(battery, RELAX_VOL2_UPD);
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun DBG("RELAX_STS: %d\n", relax_sts);
818*4882a593Smuzhiyun DBG("RELAX_VOL1_UPD: %d\n", relax_vol1_upd);
819*4882a593Smuzhiyun DBG("RELAX_VOL2_UPD: %d\n", relax_vol2_upd);
820*4882a593Smuzhiyun if (relax_sts && relax_vol1_upd && relax_vol2_upd)
821*4882a593Smuzhiyun return true;
822*4882a593Smuzhiyun else
823*4882a593Smuzhiyun return false;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun
rk817_bat_get_relax_vol1(struct rk817_battery_device * battery)826*4882a593Smuzhiyun static u16 rk817_bat_get_relax_vol1(struct rk817_battery_device *battery)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun u16 vol, val = 0;
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun val = rk817_bat_field_read(battery, RELAX_VOL1_H) << 8;
831*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, RELAX_VOL1_L);
832*4882a593Smuzhiyun vol = battery->voltage_k * val / 1000 + battery->voltage_b;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun return vol;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun
rk817_bat_get_relax_vol2(struct rk817_battery_device * battery)837*4882a593Smuzhiyun static u16 rk817_bat_get_relax_vol2(struct rk817_battery_device *battery)
838*4882a593Smuzhiyun {
839*4882a593Smuzhiyun u16 vol, val = 0;
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun val = rk817_bat_field_read(battery, RELAX_VOL2_H) << 8;
842*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, RELAX_VOL2_L);
843*4882a593Smuzhiyun vol = battery->voltage_k * val / 1000 + battery->voltage_b;
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun return vol;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
rk817_bat_get_relax_voltage(struct rk817_battery_device * battery)848*4882a593Smuzhiyun static u16 rk817_bat_get_relax_voltage(struct rk817_battery_device *battery)
849*4882a593Smuzhiyun {
850*4882a593Smuzhiyun u16 relax_vol1, relax_vol2;
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun if (!is_rk817_bat_relax_mode(battery))
853*4882a593Smuzhiyun return 0;
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun relax_vol1 = rk817_bat_get_relax_vol1(battery);
856*4882a593Smuzhiyun relax_vol2 = rk817_bat_get_relax_vol2(battery);
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun return relax_vol1 > relax_vol2 ? relax_vol1 : relax_vol2;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun
rk817_bat_set_relax_sample(struct rk817_battery_device * battery)861*4882a593Smuzhiyun static void rk817_bat_set_relax_sample(struct rk817_battery_device *battery)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun u8 buf;
864*4882a593Smuzhiyun int enter_thres, filter_thres;
865*4882a593Smuzhiyun struct battery_platform_data *pdata = battery->pdata;
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun filter_thres = pdata->sleep_filter_current * 1000 / 1506;
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun enter_thres = CURRENT_TO_ADC(pdata->sleep_enter_current,
870*4882a593Smuzhiyun battery->res_div);
871*4882a593Smuzhiyun filter_thres = CURRENT_TO_ADC(pdata->sleep_filter_current,
872*4882a593Smuzhiyun battery->res_div);
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun /* set relax enter and exit threshold */
875*4882a593Smuzhiyun buf = (enter_thres >> 8) & 0xff;
876*4882a593Smuzhiyun rk817_bat_field_write(battery, RELAX_THRE_H, buf);
877*4882a593Smuzhiyun buf = enter_thres & 0xff;
878*4882a593Smuzhiyun rk817_bat_field_write(battery, RELAX_THRE_L, buf);
879*4882a593Smuzhiyun /* set sample current threshold */
880*4882a593Smuzhiyun buf = (filter_thres >> 8) & 0xff;
881*4882a593Smuzhiyun rk817_bat_field_write(battery, SLEEP_CON_SAMP_CUR_H, buf);
882*4882a593Smuzhiyun buf = filter_thres & 0xff;
883*4882a593Smuzhiyun rk817_bat_field_write(battery, SLEEP_CON_SAMP_CUR_L, buf);
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun /* reset relax update state */
886*4882a593Smuzhiyun rk817_bat_restart_relax(battery);
887*4882a593Smuzhiyun DBG("<%s>. sleep_enter_current = %d, sleep_exit_current = %d\n",
888*4882a593Smuzhiyun __func__, pdata->sleep_enter_current, pdata->sleep_exit_current);
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun /* runtime OCV voltage, |RLX_VOL2 - RLX_VOL1| < OCV_THRE,
892*4882a593Smuzhiyun * the OCV reg update every 120s
893*4882a593Smuzhiyun */
rk817_bat_ocv_thre(struct rk817_battery_device * battery,int value)894*4882a593Smuzhiyun static void rk817_bat_ocv_thre(struct rk817_battery_device *battery, int value)
895*4882a593Smuzhiyun {
896*4882a593Smuzhiyun rk817_bat_field_write(battery, OCV_THRE_VOL, value);
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun
rk817_bat_get_ocv_voltage(struct rk817_battery_device * battery)899*4882a593Smuzhiyun static int rk817_bat_get_ocv_voltage(struct rk817_battery_device *battery)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun int vol, val = 0, vol_temp;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun val = rk817_bat_field_read(battery, OCV_VOL_H) << 8;
904*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, OCV_VOL_L);
905*4882a593Smuzhiyun vol = battery->voltage_k * val / 1000 + battery->voltage_b;
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
908*4882a593Smuzhiyun vol_temp = vol * battery->pdata->bat_res_up /
909*4882a593Smuzhiyun battery->pdata->bat_res_down + vol;
910*4882a593Smuzhiyun vol = vol_temp;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun return vol;
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun
rk817_bat_get_ocv0_voltage0(struct rk817_battery_device * battery)916*4882a593Smuzhiyun static int rk817_bat_get_ocv0_voltage0(struct rk817_battery_device *battery)
917*4882a593Smuzhiyun {
918*4882a593Smuzhiyun int vol, val = 0, vol_temp;
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun val = rk817_bat_field_read(battery, OCV_VOL0_H) << 8;
921*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, OCV_VOL0_L);
922*4882a593Smuzhiyun vol = battery->voltage_k * val / 1000 + battery->voltage_b;
923*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
924*4882a593Smuzhiyun vol_temp = vol * battery->pdata->bat_res_up /
925*4882a593Smuzhiyun battery->pdata->bat_res_down + vol;
926*4882a593Smuzhiyun vol = vol_temp;
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun return vol;
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun /* power on battery voltage */
rk817_bat_get_pwron_voltage(struct rk817_battery_device * battery)933*4882a593Smuzhiyun static int rk817_bat_get_pwron_voltage(struct rk817_battery_device *battery)
934*4882a593Smuzhiyun {
935*4882a593Smuzhiyun int vol, val = 0, vol_temp;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun val = rk817_bat_field_read(battery, PWRON_VOL_H) << 8;
938*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, PWRON_VOL_L);
939*4882a593Smuzhiyun vol = battery->voltage_k * val / 1000 + battery->voltage_b;
940*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
941*4882a593Smuzhiyun vol_temp = vol * battery->pdata->bat_res_up /
942*4882a593Smuzhiyun battery->pdata->bat_res_down + vol;
943*4882a593Smuzhiyun vol = vol_temp;
944*4882a593Smuzhiyun }
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun return vol;
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
rk817_bat_get_battery_voltage(struct rk817_battery_device * battery)949*4882a593Smuzhiyun static int rk817_bat_get_battery_voltage(struct rk817_battery_device *battery)
950*4882a593Smuzhiyun {
951*4882a593Smuzhiyun int vol, val = 0, vol_temp;
952*4882a593Smuzhiyun int vcalib0, vcalib1;
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun vcalib0 = rk817_bat_get_vaclib0(battery);
955*4882a593Smuzhiyun vcalib1 = rk817_bat_get_vaclib1(battery);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun val = rk817_bat_field_read(battery, BAT_VOL_H) << 8;
959*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, BAT_VOL_L) << 0;
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun vol = battery->voltage_k * val / 1000 + battery->voltage_b;
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
964*4882a593Smuzhiyun vol_temp = vol * battery->pdata->bat_res_up /
965*4882a593Smuzhiyun battery->pdata->bat_res_down + vol;
966*4882a593Smuzhiyun vol = vol_temp;
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun return vol;
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun
rk817_bat_get_USB_voltage(struct rk817_battery_device * battery)972*4882a593Smuzhiyun static int rk817_bat_get_USB_voltage(struct rk817_battery_device *battery)
973*4882a593Smuzhiyun {
974*4882a593Smuzhiyun int vol, val = 0, vol_temp;
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun rk817_bat_field_write(battery, USB_VOL_ADC_EN, 0x01);
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun val = rk817_bat_field_read(battery, USB_VOL_H) << 8;
979*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, USB_VOL_L) << 0;
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun vol = (battery->voltage_k * val / 1000 + battery->voltage_b) * 60 / 46;
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
984*4882a593Smuzhiyun vol_temp = vol * battery->pdata->bat_res_up /
985*4882a593Smuzhiyun battery->pdata->bat_res_down + vol;
986*4882a593Smuzhiyun vol = vol_temp;
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun return vol;
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun
rk817_bat_get_sys_voltage(struct rk817_battery_device * battery)992*4882a593Smuzhiyun static int rk817_bat_get_sys_voltage(struct rk817_battery_device *battery)
993*4882a593Smuzhiyun {
994*4882a593Smuzhiyun int vol, val = 0, vol_temp;
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun val = rk817_bat_field_read(battery, SYS_VOL_H) << 8;
997*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, SYS_VOL_L) << 0;
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun vol = (battery->voltage_k * val / 1000 + battery->voltage_b) * 60 / 46;
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
1002*4882a593Smuzhiyun vol_temp = vol * battery->pdata->bat_res_up /
1003*4882a593Smuzhiyun battery->pdata->bat_res_down + vol;
1004*4882a593Smuzhiyun vol = vol_temp;
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun return vol;
1008*4882a593Smuzhiyun }
1009*4882a593Smuzhiyun
rk817_bat_get_avg_current(struct rk817_battery_device * battery)1010*4882a593Smuzhiyun static int rk817_bat_get_avg_current(struct rk817_battery_device *battery)
1011*4882a593Smuzhiyun {
1012*4882a593Smuzhiyun int cur, val = 0;
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun val = rk817_bat_field_read(battery, BAT_CUR_H) << 8;
1015*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, BAT_CUR_L);
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun if (val & 0x8000)
1018*4882a593Smuzhiyun val -= 0x10000;
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun cur = ADC_TO_CURRENT(val, battery->res_div);
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun return cur;
1023*4882a593Smuzhiyun }
1024*4882a593Smuzhiyun
rk817_bat_get_relax_cur1(struct rk817_battery_device * battery)1025*4882a593Smuzhiyun static int rk817_bat_get_relax_cur1(struct rk817_battery_device *battery)
1026*4882a593Smuzhiyun {
1027*4882a593Smuzhiyun int cur, val = 0;
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun val = rk817_bat_field_read(battery, RELAX_CUR1_H) << 8;
1030*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, RELAX_CUR1_L);
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun if (val & 0x8000)
1033*4882a593Smuzhiyun val -= 0x10000;
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun cur = ADC_TO_CURRENT(val, battery->res_div);
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun return cur;
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun
rk817_bat_get_relax_cur2(struct rk817_battery_device * battery)1040*4882a593Smuzhiyun static int rk817_bat_get_relax_cur2(struct rk817_battery_device *battery)
1041*4882a593Smuzhiyun {
1042*4882a593Smuzhiyun int cur, val = 0;
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, RELAX_CUR2_H) << 8;
1045*4882a593Smuzhiyun val = rk817_bat_field_read(battery, RELAX_CUR2_L);
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun if (val & 0x8000)
1048*4882a593Smuzhiyun val -= 0x10000;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun cur = ADC_TO_CURRENT(val, battery->res_div);
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun return cur;
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
rk817_bat_get_relax_current(struct rk817_battery_device * battery)1055*4882a593Smuzhiyun static int rk817_bat_get_relax_current(struct rk817_battery_device *battery)
1056*4882a593Smuzhiyun {
1057*4882a593Smuzhiyun int relax_cur1, relax_cur2;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun if (!is_rk817_bat_relax_mode(battery))
1060*4882a593Smuzhiyun return 0;
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun relax_cur1 = rk817_bat_get_relax_cur1(battery);
1063*4882a593Smuzhiyun relax_cur2 = rk817_bat_get_relax_cur2(battery);
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun return (relax_cur1 < relax_cur2) ? relax_cur1 : relax_cur2;
1066*4882a593Smuzhiyun }
1067*4882a593Smuzhiyun
rk817_bat_get_ocv_current(struct rk817_battery_device * battery)1068*4882a593Smuzhiyun static int rk817_bat_get_ocv_current(struct rk817_battery_device *battery)
1069*4882a593Smuzhiyun {
1070*4882a593Smuzhiyun int cur, val = 0;
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun val = rk817_bat_field_read(battery, OCV_CUR_H) << 8;
1073*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, OCV_CUR_L);
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun if (val & 0x8000)
1076*4882a593Smuzhiyun val -= 0x10000;
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun cur = ADC_TO_CURRENT(val, battery->res_div);
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun return cur;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun
rk817_bat_get_ocv_current0(struct rk817_battery_device * battery)1083*4882a593Smuzhiyun static int rk817_bat_get_ocv_current0(struct rk817_battery_device *battery)
1084*4882a593Smuzhiyun {
1085*4882a593Smuzhiyun int cur, val = 0;
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun val = rk817_bat_field_read(battery, OCV_CUR0_H) << 8;
1088*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, OCV_CUR0_L);
1089*4882a593Smuzhiyun
1090*4882a593Smuzhiyun if (val & 0x8000)
1091*4882a593Smuzhiyun val -= 0x10000;
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun cur = ADC_TO_CURRENT(val, battery->res_div);
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun return cur;
1096*4882a593Smuzhiyun }
1097*4882a593Smuzhiyun
rk817_bat_get_pwron_current(struct rk817_battery_device * battery)1098*4882a593Smuzhiyun static int rk817_bat_get_pwron_current(struct rk817_battery_device *battery)
1099*4882a593Smuzhiyun {
1100*4882a593Smuzhiyun int cur, val = 0;
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun val = rk817_bat_field_read(battery, PWRON_CUR_H) << 8;
1103*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, PWRON_CUR_L);
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun if (val & 0x8000)
1106*4882a593Smuzhiyun val -= 0x10000;
1107*4882a593Smuzhiyun cur = ADC_TO_CURRENT(val, battery->res_div);
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun return cur;
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun
rk817_bat_remain_cap_is_valid(struct rk817_battery_device * battery)1112*4882a593Smuzhiyun static bool rk817_bat_remain_cap_is_valid(struct rk817_battery_device *battery)
1113*4882a593Smuzhiyun {
1114*4882a593Smuzhiyun return !(rk817_bat_field_read(battery, Q_PRESS_H3) & CAP_INVALID);
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun
rk817_bat_get_capacity_uah(struct rk817_battery_device * battery)1117*4882a593Smuzhiyun static u32 rk817_bat_get_capacity_uah(struct rk817_battery_device *battery)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun u32 val = 0, capacity = 0;
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun if (rk817_bat_remain_cap_is_valid(battery)) {
1122*4882a593Smuzhiyun val = rk817_bat_field_read(battery, Q_PRESS_H3) << 24;
1123*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_PRESS_H2) << 16;
1124*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_PRESS_L1) << 8;
1125*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_PRESS_L0) << 0;
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun capacity = ADC_TO_CAPACITY_UAH(val, battery->res_div);
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun DBG("xxxxxxxxxxxxx capacity = %d\n", capacity);
1131*4882a593Smuzhiyun return capacity;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun
rk817_bat_get_capacity_mah(struct rk817_battery_device * battery)1134*4882a593Smuzhiyun static u32 rk817_bat_get_capacity_mah(struct rk817_battery_device *battery)
1135*4882a593Smuzhiyun {
1136*4882a593Smuzhiyun u32 val, capacity = 0;
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun if (rk817_bat_remain_cap_is_valid(battery)) {
1139*4882a593Smuzhiyun val = rk817_bat_field_read(battery, Q_PRESS_H3) << 24;
1140*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_PRESS_H2) << 16;
1141*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_PRESS_L1) << 8;
1142*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_PRESS_L0) << 0;
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun capacity = ADC_TO_CAPACITY(val, battery->res_div);
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun DBG("Q_PRESS_H3 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_H3));
1147*4882a593Smuzhiyun DBG("Q_PRESS_H2 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_H2));
1148*4882a593Smuzhiyun DBG("Q_PRESS_H1 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_L1));
1149*4882a593Smuzhiyun DBG("Q_PRESS_H0 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_L0));
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun DBG("xxxxxxxxxxxxx capacity = %d\n", capacity);
1152*4882a593Smuzhiyun return capacity;
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun
fuel_gauge_q_init_info(struct rk817_battery_device * battery)1155*4882a593Smuzhiyun static void fuel_gauge_q_init_info(struct rk817_battery_device *battery)
1156*4882a593Smuzhiyun {
1157*4882a593Smuzhiyun DBG("Q_INIT_H3 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_H3));
1158*4882a593Smuzhiyun DBG("Q_INIT_H2 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_H2));
1159*4882a593Smuzhiyun DBG("Q_INIT_L1 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_L1));
1160*4882a593Smuzhiyun DBG("Q_INIT_L0 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_L0));
1161*4882a593Smuzhiyun }
1162*4882a593Smuzhiyun
rk817_bat_init_coulomb_cap(struct rk817_battery_device * battery,u32 capacity)1163*4882a593Smuzhiyun static void rk817_bat_init_coulomb_cap(struct rk817_battery_device *battery,
1164*4882a593Smuzhiyun u32 capacity)
1165*4882a593Smuzhiyun {
1166*4882a593Smuzhiyun u8 buf;
1167*4882a593Smuzhiyun u32 cap;
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun fuel_gauge_q_init_info(battery);
1170*4882a593Smuzhiyun cap = CAPACITY_TO_ADC(capacity, battery->res_div);
1171*4882a593Smuzhiyun DBG("new cap: 0x%x\n", cap);
1172*4882a593Smuzhiyun buf = (cap >> 24) & 0xff;
1173*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_INIT_H3, buf);
1174*4882a593Smuzhiyun buf = (cap >> 16) & 0xff;
1175*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_INIT_H2, buf);
1176*4882a593Smuzhiyun buf = (cap >> 8) & 0xff;
1177*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_INIT_L1, buf);
1178*4882a593Smuzhiyun buf = (cap >> 0) & 0xff;
1179*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_INIT_L0, buf);
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun battery->rsoc = capacity * 1000 * 100 / DIV(battery->fcc);
1182*4882a593Smuzhiyun battery->remain_cap = capacity * 1000;
1183*4882a593Smuzhiyun DBG("new remaincap: %d\n", battery->remain_cap);
1184*4882a593Smuzhiyun fuel_gauge_q_init_info(battery);
1185*4882a593Smuzhiyun }
1186*4882a593Smuzhiyun
rk817_bat_save_cap(struct rk817_battery_device * battery,int capacity)1187*4882a593Smuzhiyun static void rk817_bat_save_cap(struct rk817_battery_device *battery,
1188*4882a593Smuzhiyun int capacity)
1189*4882a593Smuzhiyun {
1190*4882a593Smuzhiyun u8 buf;
1191*4882a593Smuzhiyun static u32 old_cap;
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun if (capacity >= battery->qmax)
1194*4882a593Smuzhiyun capacity = battery->qmax;
1195*4882a593Smuzhiyun if (capacity <= 0)
1196*4882a593Smuzhiyun capacity = 0;
1197*4882a593Smuzhiyun if (old_cap == capacity)
1198*4882a593Smuzhiyun return;
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun old_cap = capacity;
1201*4882a593Smuzhiyun buf = (capacity >> 16) & 0xff;
1202*4882a593Smuzhiyun rk817_bat_field_write(battery, REMAIN_CAP_REG2, buf);
1203*4882a593Smuzhiyun buf = (capacity >> 8) & 0xff;
1204*4882a593Smuzhiyun rk817_bat_field_write(battery, REMAIN_CAP_REG1, buf);
1205*4882a593Smuzhiyun buf = (capacity >> 0) & 0xff;
1206*4882a593Smuzhiyun rk817_bat_field_write(battery, REMAIN_CAP_REG0, buf);
1207*4882a593Smuzhiyun }
1208*4882a593Smuzhiyun
rk817_bat_update_qmax(struct rk817_battery_device * battery,u32 capacity)1209*4882a593Smuzhiyun static void rk817_bat_update_qmax(struct rk817_battery_device *battery,
1210*4882a593Smuzhiyun u32 capacity)
1211*4882a593Smuzhiyun {
1212*4882a593Smuzhiyun u8 buf;
1213*4882a593Smuzhiyun u32 cap_adc;
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun cap_adc = CAPACITY_TO_ADC(capacity, battery->res_div);
1216*4882a593Smuzhiyun buf = (cap_adc >> 24) & 0xff;
1217*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_MAX_H3, buf);
1218*4882a593Smuzhiyun buf = (cap_adc >> 16) & 0xff;
1219*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_MAX_H2, buf);
1220*4882a593Smuzhiyun buf = (cap_adc >> 8) & 0xff;
1221*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_MAX_L1, buf);
1222*4882a593Smuzhiyun buf = (cap_adc >> 0) & 0xff;
1223*4882a593Smuzhiyun rk817_bat_field_write(battery, Q_MAX_L0, buf);
1224*4882a593Smuzhiyun battery->qmax = capacity;
1225*4882a593Smuzhiyun }
1226*4882a593Smuzhiyun
rk817_bat_get_qmax(struct rk817_battery_device * battery)1227*4882a593Smuzhiyun static int rk817_bat_get_qmax(struct rk817_battery_device *battery)
1228*4882a593Smuzhiyun {
1229*4882a593Smuzhiyun u32 capacity;
1230*4882a593Smuzhiyun int val = 0;
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun val = rk817_bat_field_read(battery, Q_MAX_H3) << 24;
1233*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_MAX_H2) << 16;
1234*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_MAX_L1) << 8;
1235*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, Q_MAX_L0) << 0;
1236*4882a593Smuzhiyun capacity = ADC_TO_CAPACITY(val, battery->res_div);
1237*4882a593Smuzhiyun battery->qmax = capacity;
1238*4882a593Smuzhiyun return capacity;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun
rk817_bat_save_fcc(struct rk817_battery_device * battery,int fcc)1241*4882a593Smuzhiyun static void rk817_bat_save_fcc(struct rk817_battery_device *battery, int fcc)
1242*4882a593Smuzhiyun {
1243*4882a593Smuzhiyun u8 buf;
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun buf = (fcc >> 16) & 0xff;
1246*4882a593Smuzhiyun rk817_bat_field_write(battery, NEW_FCC_REG2, buf);
1247*4882a593Smuzhiyun buf = (fcc >> 8) & 0xff;
1248*4882a593Smuzhiyun rk817_bat_field_write(battery, NEW_FCC_REG1, buf);
1249*4882a593Smuzhiyun buf = (fcc >> 0) & 0xff;
1250*4882a593Smuzhiyun rk817_bat_field_write(battery, NEW_FCC_REG0, buf);
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun
rk817_bat_get_fcc(struct rk817_battery_device * battery)1253*4882a593Smuzhiyun static int rk817_bat_get_fcc(struct rk817_battery_device *battery)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun u32 fcc = 0;
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun fcc |= rk817_bat_field_read(battery, NEW_FCC_REG2) << 16;
1258*4882a593Smuzhiyun fcc |= rk817_bat_field_read(battery, NEW_FCC_REG1) << 8;
1259*4882a593Smuzhiyun fcc |= rk817_bat_field_read(battery, NEW_FCC_REG0) << 0;
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun if (fcc < MIN_FCC) {
1262*4882a593Smuzhiyun DBG("invalid fcc(%d), use design cap", fcc);
1263*4882a593Smuzhiyun fcc = battery->pdata->design_capacity;
1264*4882a593Smuzhiyun rk817_bat_save_fcc(battery, fcc);
1265*4882a593Smuzhiyun } else if (fcc > battery->pdata->design_qmax) {
1266*4882a593Smuzhiyun DBG("invalid fcc(%d), use qmax", fcc);
1267*4882a593Smuzhiyun fcc = battery->pdata->design_qmax;
1268*4882a593Smuzhiyun rk817_bat_save_fcc(battery, fcc);
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun
1271*4882a593Smuzhiyun return fcc;
1272*4882a593Smuzhiyun }
1273*4882a593Smuzhiyun
rk817_bat_get_rsoc(struct rk817_battery_device * battery)1274*4882a593Smuzhiyun static int rk817_bat_get_rsoc(struct rk817_battery_device *battery)
1275*4882a593Smuzhiyun {
1276*4882a593Smuzhiyun int remain_cap;
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun remain_cap = rk817_bat_get_capacity_uah(battery);
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun return remain_cap * 100 / DIV(battery->fcc);
1281*4882a593Smuzhiyun }
1282*4882a593Smuzhiyun
rk817_bat_get_off_count(struct rk817_battery_device * battery)1283*4882a593Smuzhiyun static int rk817_bat_get_off_count(struct rk817_battery_device *battery)
1284*4882a593Smuzhiyun {
1285*4882a593Smuzhiyun return rk817_bat_field_read(battery, OFF_CNT);
1286*4882a593Smuzhiyun }
1287*4882a593Smuzhiyun
rk817_bat_get_ocv_count(struct rk817_battery_device * battery)1288*4882a593Smuzhiyun static int rk817_bat_get_ocv_count(struct rk817_battery_device *battery)
1289*4882a593Smuzhiyun {
1290*4882a593Smuzhiyun return rk817_bat_field_read(battery, OCV_CNT);
1291*4882a593Smuzhiyun }
1292*4882a593Smuzhiyun
rk817_bat_vol_to_soc(struct rk817_battery_device * battery,int voltage)1293*4882a593Smuzhiyun static int rk817_bat_vol_to_soc(struct rk817_battery_device *battery,
1294*4882a593Smuzhiyun int voltage)
1295*4882a593Smuzhiyun {
1296*4882a593Smuzhiyun u32 *ocv_table, temp;
1297*4882a593Smuzhiyun int ocv_size, ocv_soc;
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun ocv_table = battery->pdata->ocv_table;
1300*4882a593Smuzhiyun ocv_size = battery->pdata->ocv_size;
1301*4882a593Smuzhiyun temp = interpolate(voltage, ocv_table, ocv_size);
1302*4882a593Smuzhiyun ocv_soc = ab_div_c(temp, MAX_PERCENTAGE, MAX_INTERPOLATE);
1303*4882a593Smuzhiyun
1304*4882a593Smuzhiyun return ocv_soc;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun
rk817_bat_vol_to_cap(struct rk817_battery_device * battery,int voltage)1307*4882a593Smuzhiyun static int rk817_bat_vol_to_cap(struct rk817_battery_device *battery,
1308*4882a593Smuzhiyun int voltage)
1309*4882a593Smuzhiyun {
1310*4882a593Smuzhiyun u32 *ocv_table, temp;
1311*4882a593Smuzhiyun int ocv_size, capacity;
1312*4882a593Smuzhiyun
1313*4882a593Smuzhiyun ocv_table = battery->pdata->ocv_table;
1314*4882a593Smuzhiyun ocv_size = battery->pdata->ocv_size;
1315*4882a593Smuzhiyun temp = interpolate(voltage, ocv_table, ocv_size);
1316*4882a593Smuzhiyun capacity = ab_div_c(temp, battery->fcc, MAX_INTERPOLATE);
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun return capacity;
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun
rk817_bat_save_dsoc(struct rk817_battery_device * battery,int save_soc)1321*4882a593Smuzhiyun static void rk817_bat_save_dsoc(struct rk817_battery_device *battery,
1322*4882a593Smuzhiyun int save_soc)
1323*4882a593Smuzhiyun {
1324*4882a593Smuzhiyun static int last_soc = -1;
1325*4882a593Smuzhiyun
1326*4882a593Smuzhiyun if (last_soc != save_soc) {
1327*4882a593Smuzhiyun rk817_bat_field_write(battery, SOC_REG0,
1328*4882a593Smuzhiyun save_soc & 0xff);
1329*4882a593Smuzhiyun rk817_bat_field_write(battery, SOC_REG1,
1330*4882a593Smuzhiyun (save_soc >> 8) & 0xff);
1331*4882a593Smuzhiyun rk817_bat_field_write(battery, SOC_REG2,
1332*4882a593Smuzhiyun (save_soc >> 16) & 0xff);
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun last_soc = save_soc;
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun }
1337*4882a593Smuzhiyun
rk817_bat_get_prev_dsoc(struct rk817_battery_device * battery)1338*4882a593Smuzhiyun static int rk817_bat_get_prev_dsoc(struct rk817_battery_device *battery)
1339*4882a593Smuzhiyun {
1340*4882a593Smuzhiyun int soc_save;
1341*4882a593Smuzhiyun
1342*4882a593Smuzhiyun soc_save = rk817_bat_field_read(battery, SOC_REG0);
1343*4882a593Smuzhiyun soc_save |= (rk817_bat_field_read(battery, SOC_REG1) << 8);
1344*4882a593Smuzhiyun soc_save |= (rk817_bat_field_read(battery, SOC_REG2) << 16);
1345*4882a593Smuzhiyun
1346*4882a593Smuzhiyun return soc_save;
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun
is_rk817_bat_first_pwron(struct rk817_battery_device * battery)1349*4882a593Smuzhiyun static bool is_rk817_bat_first_pwron(struct rk817_battery_device *battery)
1350*4882a593Smuzhiyun {
1351*4882a593Smuzhiyun if (rk817_bat_field_read(battery, BAT_CON)) {
1352*4882a593Smuzhiyun rk817_bat_field_write(battery, BAT_CON, 0x00);
1353*4882a593Smuzhiyun return true;
1354*4882a593Smuzhiyun }
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun return false;
1357*4882a593Smuzhiyun }
1358*4882a593Smuzhiyun
rk817_bat_get_charge_status(struct rk817_battery_device * battery)1359*4882a593Smuzhiyun static int rk817_bat_get_charge_status(struct rk817_battery_device *battery)
1360*4882a593Smuzhiyun {
1361*4882a593Smuzhiyun int status;
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
1364*4882a593Smuzhiyun if ((battery->voltage_avg > battery->pdata->design_max_voltage) &&
1365*4882a593Smuzhiyun (battery->current_avg > 0) &&
1366*4882a593Smuzhiyun ((battery->current_avg < 500) ||
1367*4882a593Smuzhiyun (battery->rsoc / 1000 == 100)))
1368*4882a593Smuzhiyun return CHARGE_FINISH;
1369*4882a593Smuzhiyun
1370*4882a593Smuzhiyun if (battery->plugin_trigger)
1371*4882a593Smuzhiyun return CC_OR_CV_CHRG;
1372*4882a593Smuzhiyun else
1373*4882a593Smuzhiyun return CHRG_OFF;
1374*4882a593Smuzhiyun }
1375*4882a593Smuzhiyun status = rk817_bat_field_read(battery, CHG_STS);
1376*4882a593Smuzhiyun
1377*4882a593Smuzhiyun if (status == CC_OR_CV_CHRG) {
1378*4882a593Smuzhiyun if (battery->rsoc == 100 * 1000) {
1379*4882a593Smuzhiyun DBG("charge to finish\n");
1380*4882a593Smuzhiyun status = CHARGE_FINISH;
1381*4882a593Smuzhiyun }
1382*4882a593Smuzhiyun }
1383*4882a593Smuzhiyun
1384*4882a593Smuzhiyun switch (status) {
1385*4882a593Smuzhiyun case CHRG_OFF:
1386*4882a593Smuzhiyun DBG("charge off...\n");
1387*4882a593Smuzhiyun break;
1388*4882a593Smuzhiyun case DEAD_CHRG:
1389*4882a593Smuzhiyun DBG("dead charge...\n");
1390*4882a593Smuzhiyun break;
1391*4882a593Smuzhiyun case TRICKLE_CHRG:
1392*4882a593Smuzhiyun DBG("trickle charge...\n");
1393*4882a593Smuzhiyun break;
1394*4882a593Smuzhiyun case CC_OR_CV_CHRG:
1395*4882a593Smuzhiyun DBG("CC or CV charge...\n");
1396*4882a593Smuzhiyun break;
1397*4882a593Smuzhiyun case CHARGE_FINISH:
1398*4882a593Smuzhiyun DBG("charge finish...\n");
1399*4882a593Smuzhiyun break;
1400*4882a593Smuzhiyun case USB_OVER_VOL:
1401*4882a593Smuzhiyun DBG("USB over voltage...\n");
1402*4882a593Smuzhiyun break;
1403*4882a593Smuzhiyun case BAT_TMP_ERR:
1404*4882a593Smuzhiyun DBG("battery temperature error...\n");
1405*4882a593Smuzhiyun break;
1406*4882a593Smuzhiyun case BAT_TIM_ERR:
1407*4882a593Smuzhiyun DBG("battery timer error..\n");
1408*4882a593Smuzhiyun break;
1409*4882a593Smuzhiyun default:
1410*4882a593Smuzhiyun break;
1411*4882a593Smuzhiyun }
1412*4882a593Smuzhiyun
1413*4882a593Smuzhiyun return status;
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun
1416*4882a593Smuzhiyun /*
1417*4882a593Smuzhiyun * cccv and finish switch all the time will cause dsoc freeze,
1418*4882a593Smuzhiyun * if so, do finish chrg, 100ma is less than min finish_ma.
1419*4882a593Smuzhiyun */
rk817_bat_fake_finish_mode(struct rk817_battery_device * battery)1420*4882a593Smuzhiyun static bool rk817_bat_fake_finish_mode(struct rk817_battery_device *battery)
1421*4882a593Smuzhiyun {
1422*4882a593Smuzhiyun if ((battery->rsoc == 100) &&
1423*4882a593Smuzhiyun (rk817_bat_get_charge_status(battery) == CC_OR_CV_CHRG) &&
1424*4882a593Smuzhiyun (abs(battery->current_avg) <= 100))
1425*4882a593Smuzhiyun return true;
1426*4882a593Smuzhiyun else
1427*4882a593Smuzhiyun return false;
1428*4882a593Smuzhiyun }
1429*4882a593Smuzhiyun
get_charge_status(struct rk817_battery_device * battery)1430*4882a593Smuzhiyun static int get_charge_status(struct rk817_battery_device *battery)
1431*4882a593Smuzhiyun {
1432*4882a593Smuzhiyun return rk817_bat_get_charge_status(battery);
1433*4882a593Smuzhiyun }
1434*4882a593Smuzhiyun
is_rk817_bat_ocv_valid(struct rk817_battery_device * battery)1435*4882a593Smuzhiyun static bool is_rk817_bat_ocv_valid(struct rk817_battery_device *battery)
1436*4882a593Smuzhiyun {
1437*4882a593Smuzhiyun return (!battery->is_initialized && battery->pwroff_min >= 30);
1438*4882a593Smuzhiyun }
1439*4882a593Smuzhiyun
rk817_bat_gas_gaugle_enable(struct rk817_battery_device * battery)1440*4882a593Smuzhiyun static void rk817_bat_gas_gaugle_enable(struct rk817_battery_device *battery)
1441*4882a593Smuzhiyun {
1442*4882a593Smuzhiyun rk817_bat_field_write(battery, GG_EN, ENABLE);
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
rk817_bat_gg_con_init(struct rk817_battery_device * battery)1445*4882a593Smuzhiyun static void rk817_bat_gg_con_init(struct rk817_battery_device *battery)
1446*4882a593Smuzhiyun {
1447*4882a593Smuzhiyun rk817_bat_field_write(battery, RLX_SPT, S_8_MIN);
1448*4882a593Smuzhiyun rk817_bat_field_write(battery, ADC_OFF_CAL_INTERV, S_8_MIN);
1449*4882a593Smuzhiyun rk817_bat_field_write(battery, VOL_OUT_MOD, AVERAGE_MODE);
1450*4882a593Smuzhiyun rk817_bat_field_write(battery, CUR_OUT_MOD, AVERAGE_MODE);
1451*4882a593Smuzhiyun }
1452*4882a593Smuzhiyun
rk817_bat_adc_init(struct rk817_battery_device * battery)1453*4882a593Smuzhiyun static void rk817_bat_adc_init(struct rk817_battery_device *battery)
1454*4882a593Smuzhiyun {
1455*4882a593Smuzhiyun rk817_bat_field_write(battery, SYS_VOL_ADC_EN, ENABLE);
1456*4882a593Smuzhiyun rk817_bat_field_write(battery, TS_ADC_EN, ENABLE);
1457*4882a593Smuzhiyun rk817_bat_field_write(battery, USB_VOL_ADC_EN, ENABLE);
1458*4882a593Smuzhiyun rk817_bat_field_write(battery, BAT_VOL_ADC_EN, ENABLE);
1459*4882a593Smuzhiyun rk817_bat_field_write(battery, BAT_CUR_ADC_EN, ENABLE);
1460*4882a593Smuzhiyun }
1461*4882a593Smuzhiyun
rk817_bat_init_info(struct rk817_battery_device * battery)1462*4882a593Smuzhiyun static void rk817_bat_init_info(struct rk817_battery_device *battery)
1463*4882a593Smuzhiyun {
1464*4882a593Smuzhiyun battery->design_cap = battery->pdata->design_capacity;
1465*4882a593Smuzhiyun battery->qmax = battery->pdata->design_qmax;
1466*4882a593Smuzhiyun battery->bat_res = battery->pdata->bat_res;
1467*4882a593Smuzhiyun battery->monitor_ms = battery->pdata->monitor_sec * TIMER_MS_COUNTS;
1468*4882a593Smuzhiyun battery->res_div = (battery->pdata->sample_res == SAMPLE_RES_20MR) ?
1469*4882a593Smuzhiyun SAMPLE_RES_DIV2 : SAMPLE_RES_DIV1;
1470*4882a593Smuzhiyun DBG("battery->qmax :%d\n", battery->qmax);
1471*4882a593Smuzhiyun }
1472*4882a593Smuzhiyun
rk817_bat_get_prev_cap(struct rk817_battery_device * battery)1473*4882a593Smuzhiyun static int rk817_bat_get_prev_cap(struct rk817_battery_device *battery)
1474*4882a593Smuzhiyun {
1475*4882a593Smuzhiyun int val = 0;
1476*4882a593Smuzhiyun
1477*4882a593Smuzhiyun val = rk817_bat_field_read(battery, REMAIN_CAP_REG2) << 16;
1478*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, REMAIN_CAP_REG1) << 8;
1479*4882a593Smuzhiyun val |= rk817_bat_field_read(battery, REMAIN_CAP_REG0) << 0;
1480*4882a593Smuzhiyun
1481*4882a593Smuzhiyun return val;
1482*4882a593Smuzhiyun }
1483*4882a593Smuzhiyun
rk817_bat_get_halt_cnt(struct rk817_battery_device * battery)1484*4882a593Smuzhiyun static u8 rk817_bat_get_halt_cnt(struct rk817_battery_device *battery)
1485*4882a593Smuzhiyun {
1486*4882a593Smuzhiyun return rk817_bat_field_read(battery, HALT_CNT_REG);
1487*4882a593Smuzhiyun }
1488*4882a593Smuzhiyun
rk817_bat_inc_halt_cnt(struct rk817_battery_device * battery)1489*4882a593Smuzhiyun static void rk817_bat_inc_halt_cnt(struct rk817_battery_device *battery)
1490*4882a593Smuzhiyun {
1491*4882a593Smuzhiyun u8 cnt;
1492*4882a593Smuzhiyun
1493*4882a593Smuzhiyun cnt = rk817_bat_field_read(battery, HALT_CNT_REG);
1494*4882a593Smuzhiyun rk817_bat_field_write(battery, HALT_CNT_REG, ++cnt);
1495*4882a593Smuzhiyun }
1496*4882a593Smuzhiyun
is_rk817_bat_last_halt(struct rk817_battery_device * battery)1497*4882a593Smuzhiyun static bool is_rk817_bat_last_halt(struct rk817_battery_device *battery)
1498*4882a593Smuzhiyun {
1499*4882a593Smuzhiyun int pre_cap = rk817_bat_get_prev_cap(battery);
1500*4882a593Smuzhiyun int now_cap = rk817_bat_get_capacity_mah(battery);
1501*4882a593Smuzhiyun
1502*4882a593Smuzhiyun /* over 10%: system halt last time */
1503*4882a593Smuzhiyun if (abs(now_cap - pre_cap) > (battery->fcc / 10)) {
1504*4882a593Smuzhiyun rk817_bat_inc_halt_cnt(battery);
1505*4882a593Smuzhiyun return true;
1506*4882a593Smuzhiyun } else {
1507*4882a593Smuzhiyun return false;
1508*4882a593Smuzhiyun }
1509*4882a593Smuzhiyun }
1510*4882a593Smuzhiyun
is_rk817_bat_initialized(struct rk817_battery_device * battery)1511*4882a593Smuzhiyun static u8 is_rk817_bat_initialized(struct rk817_battery_device *battery)
1512*4882a593Smuzhiyun {
1513*4882a593Smuzhiyun u8 val = rk817_bat_field_read(battery, FG_INIT);
1514*4882a593Smuzhiyun
1515*4882a593Smuzhiyun if (val) {
1516*4882a593Smuzhiyun rk817_bat_field_write(battery, FG_INIT, 0x00);
1517*4882a593Smuzhiyun return true;
1518*4882a593Smuzhiyun } else {
1519*4882a593Smuzhiyun return false;
1520*4882a593Smuzhiyun }
1521*4882a593Smuzhiyun }
1522*4882a593Smuzhiyun
rk817_bat_calc_sm_linek(struct rk817_battery_device * battery)1523*4882a593Smuzhiyun static void rk817_bat_calc_sm_linek(struct rk817_battery_device *battery)
1524*4882a593Smuzhiyun {
1525*4882a593Smuzhiyun int linek;
1526*4882a593Smuzhiyun int diff, delta;
1527*4882a593Smuzhiyun int current_avg = rk817_bat_get_avg_current(battery);
1528*4882a593Smuzhiyun
1529*4882a593Smuzhiyun delta = abs(battery->dsoc - battery->rsoc);
1530*4882a593Smuzhiyun diff = delta * 3;/* speed:3/4 */
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun if (current_avg > 0) {
1533*4882a593Smuzhiyun if (battery->dsoc < battery->rsoc)
1534*4882a593Smuzhiyun linek = 1000 * (delta + diff) / DIV(diff);
1535*4882a593Smuzhiyun else if (battery->dsoc > battery->rsoc)
1536*4882a593Smuzhiyun linek = 1000 * diff / DIV(delta + diff);
1537*4882a593Smuzhiyun else
1538*4882a593Smuzhiyun linek = 1000;
1539*4882a593Smuzhiyun } else {
1540*4882a593Smuzhiyun if (battery->dsoc < battery->rsoc)
1541*4882a593Smuzhiyun linek = -1000 * diff / DIV(delta + diff);
1542*4882a593Smuzhiyun else if (battery->dsoc > battery->rsoc)
1543*4882a593Smuzhiyun linek = -1000 * (delta + diff) / DIV(diff);
1544*4882a593Smuzhiyun else
1545*4882a593Smuzhiyun linek = -1000;
1546*4882a593Smuzhiyun }
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun battery->dbg_meet_soc = (battery->dsoc >= battery->rsoc) ?
1549*4882a593Smuzhiyun (battery->dsoc - diff) : (battery->rsoc - diff);
1550*4882a593Smuzhiyun
1551*4882a593Smuzhiyun battery->sm_linek = linek;
1552*4882a593Smuzhiyun battery->sm_remain_cap = battery->remain_cap;
1553*4882a593Smuzhiyun battery->dbg_calc_dsoc = battery->dsoc;
1554*4882a593Smuzhiyun battery->dbg_calc_rsoc = battery->rsoc;
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun
rk817_bat_smooth_algo_prepare(struct rk817_battery_device * battery)1557*4882a593Smuzhiyun static void rk817_bat_smooth_algo_prepare(struct rk817_battery_device *battery)
1558*4882a593Smuzhiyun {
1559*4882a593Smuzhiyun battery->smooth_soc = battery->dsoc;
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun DBG("<%s>. dsoc=%d, dsoc:smooth_soc=%d\n",
1562*4882a593Smuzhiyun __func__, battery->dsoc, battery->smooth_soc);
1563*4882a593Smuzhiyun rk817_bat_calc_sm_linek(battery);
1564*4882a593Smuzhiyun }
1565*4882a593Smuzhiyun
rk817_bat_finish_algo_prepare(struct rk817_battery_device * battery)1566*4882a593Smuzhiyun static void rk817_bat_finish_algo_prepare(struct rk817_battery_device *battery)
1567*4882a593Smuzhiyun {
1568*4882a593Smuzhiyun battery->finish_base = get_boot_sec();
1569*4882a593Smuzhiyun
1570*4882a593Smuzhiyun if (!battery->finish_base)
1571*4882a593Smuzhiyun battery->finish_base = 1;
1572*4882a593Smuzhiyun }
1573*4882a593Smuzhiyun
rk817_bat_init_dsoc_algorithm(struct rk817_battery_device * battery)1574*4882a593Smuzhiyun static void rk817_bat_init_dsoc_algorithm(struct rk817_battery_device *battery)
1575*4882a593Smuzhiyun {
1576*4882a593Smuzhiyun if (battery->dsoc >= 100 * 1000)
1577*4882a593Smuzhiyun battery->dsoc = 100 * 1000;
1578*4882a593Smuzhiyun else if (battery->dsoc <= 0)
1579*4882a593Smuzhiyun battery->dsoc = 0;
1580*4882a593Smuzhiyun /* init current mode */
1581*4882a593Smuzhiyun battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
1582*4882a593Smuzhiyun battery->current_avg = rk817_bat_get_avg_current(battery);
1583*4882a593Smuzhiyun
1584*4882a593Smuzhiyun if (get_charge_status(battery) == CHARGE_FINISH) {
1585*4882a593Smuzhiyun rk817_bat_finish_algo_prepare(battery);
1586*4882a593Smuzhiyun battery->work_mode = MODE_FINISH;
1587*4882a593Smuzhiyun } else {
1588*4882a593Smuzhiyun rk817_bat_smooth_algo_prepare(battery);
1589*4882a593Smuzhiyun battery->work_mode = MODE_SMOOTH;
1590*4882a593Smuzhiyun }
1591*4882a593Smuzhiyun DBG("%s, sm_remain_cap = %d, smooth_soc = %d\n",
1592*4882a593Smuzhiyun __func__, battery->sm_remain_cap, battery->smooth_soc);
1593*4882a593Smuzhiyun }
1594*4882a593Smuzhiyun
rk817_bat_first_pwron(struct rk817_battery_device * battery)1595*4882a593Smuzhiyun static void rk817_bat_first_pwron(struct rk817_battery_device *battery)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun battery->rsoc =
1598*4882a593Smuzhiyun rk817_bat_vol_to_soc(battery,
1599*4882a593Smuzhiyun battery->pwron_voltage) * 1000;/* uAH */
1600*4882a593Smuzhiyun battery->dsoc = battery->rsoc;
1601*4882a593Smuzhiyun battery->fcc = battery->pdata->design_capacity;
1602*4882a593Smuzhiyun battery->nac = rk817_bat_vol_to_cap(battery, battery->pwron_voltage);
1603*4882a593Smuzhiyun
1604*4882a593Smuzhiyun rk817_bat_update_qmax(battery, battery->qmax);
1605*4882a593Smuzhiyun rk817_bat_save_fcc(battery, battery->fcc);
1606*4882a593Smuzhiyun DBG("%s, rsoc = %d, dsoc = %d, fcc = %d, nac = %d\n",
1607*4882a593Smuzhiyun __func__, battery->rsoc, battery->dsoc, battery->fcc, battery->nac);
1608*4882a593Smuzhiyun }
1609*4882a593Smuzhiyun
rk817_bat_not_first_pwron(struct rk817_battery_device * battery)1610*4882a593Smuzhiyun static void rk817_bat_not_first_pwron(struct rk817_battery_device *battery)
1611*4882a593Smuzhiyun {
1612*4882a593Smuzhiyun int now_cap, pre_soc, pre_cap, ocv_cap, ocv_soc, ocv_vol;
1613*4882a593Smuzhiyun
1614*4882a593Smuzhiyun battery->fcc = rk817_bat_get_fcc(battery);
1615*4882a593Smuzhiyun pre_soc = rk817_bat_get_prev_dsoc(battery);
1616*4882a593Smuzhiyun pre_cap = rk817_bat_get_prev_cap(battery);
1617*4882a593Smuzhiyun now_cap = rk817_bat_get_capacity_mah(battery);
1618*4882a593Smuzhiyun battery->remain_cap = pre_cap * 1000;
1619*4882a593Smuzhiyun battery->is_halt = is_rk817_bat_last_halt(battery);
1620*4882a593Smuzhiyun battery->halt_cnt = rk817_bat_get_halt_cnt(battery);
1621*4882a593Smuzhiyun battery->is_initialized = is_rk817_bat_initialized(battery);
1622*4882a593Smuzhiyun battery->is_ocv_calib = is_rk817_bat_ocv_valid(battery);
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun if (battery->is_halt) {
1625*4882a593Smuzhiyun BAT_INFO("system halt last time... cap: pre=%d, now=%d\n",
1626*4882a593Smuzhiyun pre_cap, now_cap);
1627*4882a593Smuzhiyun if (now_cap < 0)
1628*4882a593Smuzhiyun now_cap = 0;
1629*4882a593Smuzhiyun rk817_bat_init_coulomb_cap(battery, now_cap);
1630*4882a593Smuzhiyun pre_cap = now_cap;
1631*4882a593Smuzhiyun pre_soc = battery->rsoc;
1632*4882a593Smuzhiyun goto finish;
1633*4882a593Smuzhiyun } else if (battery->is_initialized) {
1634*4882a593Smuzhiyun /* uboot initialized */
1635*4882a593Smuzhiyun BAT_INFO("initialized yet..\n");
1636*4882a593Smuzhiyun goto finish;
1637*4882a593Smuzhiyun } else if (battery->is_ocv_calib) {
1638*4882a593Smuzhiyun /* not initialized and poweroff_cnt above 30 min */
1639*4882a593Smuzhiyun ocv_vol = rk817_bat_get_ocv_voltage(battery);
1640*4882a593Smuzhiyun ocv_soc = rk817_bat_vol_to_soc(battery, ocv_vol);
1641*4882a593Smuzhiyun ocv_cap = rk817_bat_vol_to_cap(battery, ocv_vol);
1642*4882a593Smuzhiyun pre_cap = ocv_cap;
1643*4882a593Smuzhiyun battery->ocv_pre_dsoc = pre_soc;
1644*4882a593Smuzhiyun battery->ocv_new_dsoc = ocv_soc;
1645*4882a593Smuzhiyun if (abs(ocv_soc - pre_soc) >= battery->pdata->max_soc_offset) {
1646*4882a593Smuzhiyun battery->ocv_pre_dsoc = pre_soc;
1647*4882a593Smuzhiyun battery->ocv_new_dsoc = ocv_soc;
1648*4882a593Smuzhiyun battery->is_max_soc_offset = true;
1649*4882a593Smuzhiyun BAT_INFO("trigger max soc offset, dsoc: %d -> %d\n",
1650*4882a593Smuzhiyun pre_soc, ocv_soc);
1651*4882a593Smuzhiyun pre_soc = ocv_soc;
1652*4882a593Smuzhiyun }
1653*4882a593Smuzhiyun BAT_INFO("OCV calib: cap=%d, rsoc=%d\n", ocv_cap, ocv_soc);
1654*4882a593Smuzhiyun } else if (battery->pwroff_min > 0) {
1655*4882a593Smuzhiyun ocv_vol = rk817_bat_get_ocv_voltage(battery);
1656*4882a593Smuzhiyun ocv_soc = rk817_bat_vol_to_soc(battery, ocv_vol);
1657*4882a593Smuzhiyun ocv_cap = rk817_bat_vol_to_cap(battery, ocv_vol);
1658*4882a593Smuzhiyun battery->force_pre_dsoc = pre_soc;
1659*4882a593Smuzhiyun battery->force_new_dsoc = ocv_soc;
1660*4882a593Smuzhiyun if (abs(ocv_soc - pre_soc) >= 80) {
1661*4882a593Smuzhiyun battery->is_force_calib = true;
1662*4882a593Smuzhiyun BAT_INFO("dsoc force calib: %d -> %d\n",
1663*4882a593Smuzhiyun pre_soc, ocv_soc);
1664*4882a593Smuzhiyun pre_soc = ocv_soc;
1665*4882a593Smuzhiyun pre_cap = ocv_cap;
1666*4882a593Smuzhiyun }
1667*4882a593Smuzhiyun }
1668*4882a593Smuzhiyun finish:
1669*4882a593Smuzhiyun battery->dsoc = pre_soc;
1670*4882a593Smuzhiyun battery->nac = pre_cap;
1671*4882a593Smuzhiyun if (battery->nac < 0)
1672*4882a593Smuzhiyun battery->nac = 0;
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun DBG("dsoc=%d cap=%d v=%d ov=%d rv=%d min=%d psoc=%d pcap=%d\n",
1675*4882a593Smuzhiyun battery->dsoc, battery->nac, rk817_bat_get_battery_voltage(battery),
1676*4882a593Smuzhiyun rk817_bat_get_ocv_voltage(battery),
1677*4882a593Smuzhiyun rk817_bat_get_relax_voltage(battery),
1678*4882a593Smuzhiyun battery->pwroff_min, rk817_bat_get_prev_dsoc(battery),
1679*4882a593Smuzhiyun rk817_bat_get_prev_cap(battery));
1680*4882a593Smuzhiyun }
1681*4882a593Smuzhiyun
rk817_bat_rsoc_init(struct rk817_battery_device * battery)1682*4882a593Smuzhiyun static void rk817_bat_rsoc_init(struct rk817_battery_device *battery)
1683*4882a593Smuzhiyun {
1684*4882a593Smuzhiyun battery->is_first_power_on = is_rk817_bat_first_pwron(battery);
1685*4882a593Smuzhiyun battery->pwroff_min = rk817_bat_get_off_count(battery);
1686*4882a593Smuzhiyun battery->pwron_voltage = rk817_bat_get_pwron_voltage(battery);
1687*4882a593Smuzhiyun
1688*4882a593Smuzhiyun DBG("%s, is_first_power_on = %d, pwroff_min = %d, pwron_voltage = %d\n",
1689*4882a593Smuzhiyun __func__, battery->is_first_power_on,
1690*4882a593Smuzhiyun battery->pwroff_min, battery->pwron_voltage);
1691*4882a593Smuzhiyun
1692*4882a593Smuzhiyun if (battery->is_first_power_on)
1693*4882a593Smuzhiyun rk817_bat_first_pwron(battery);
1694*4882a593Smuzhiyun else
1695*4882a593Smuzhiyun rk817_bat_not_first_pwron(battery);
1696*4882a593Smuzhiyun
1697*4882a593Smuzhiyun rk817_bat_save_dsoc(battery, battery->dsoc);
1698*4882a593Smuzhiyun }
1699*4882a593Smuzhiyun
rk817_bat_caltimer_isr(struct timer_list * t)1700*4882a593Smuzhiyun static void rk817_bat_caltimer_isr(struct timer_list *t)
1701*4882a593Smuzhiyun {
1702*4882a593Smuzhiyun struct rk817_battery_device *battery =
1703*4882a593Smuzhiyun from_timer(battery, t, caltimer);
1704*4882a593Smuzhiyun
1705*4882a593Smuzhiyun mod_timer(&battery->caltimer, jiffies + MINUTE(8) * HZ);
1706*4882a593Smuzhiyun queue_delayed_work(battery->bat_monitor_wq,
1707*4882a593Smuzhiyun &battery->calib_delay_work,
1708*4882a593Smuzhiyun msecs_to_jiffies(10));
1709*4882a593Smuzhiyun }
1710*4882a593Smuzhiyun
rk817_bat_internal_calib(struct work_struct * work)1711*4882a593Smuzhiyun static void rk817_bat_internal_calib(struct work_struct *work)
1712*4882a593Smuzhiyun {
1713*4882a593Smuzhiyun struct rk817_battery_device *battery = container_of(work,
1714*4882a593Smuzhiyun struct rk817_battery_device, calib_delay_work.work);
1715*4882a593Smuzhiyun
1716*4882a593Smuzhiyun return;
1717*4882a593Smuzhiyun
1718*4882a593Smuzhiyun rk817_bat_current_calibration(battery);
1719*4882a593Smuzhiyun /* calib voltage kb */
1720*4882a593Smuzhiyun rk817_bat_init_voltage_kb(battery);
1721*4882a593Smuzhiyun
1722*4882a593Smuzhiyun DBG("caltimer:coffset=0x%x\n", rk817_bat_get_coffset(battery));
1723*4882a593Smuzhiyun }
1724*4882a593Smuzhiyun
rk817_bat_init_caltimer(struct rk817_battery_device * battery)1725*4882a593Smuzhiyun static void rk817_bat_init_caltimer(struct rk817_battery_device *battery)
1726*4882a593Smuzhiyun {
1727*4882a593Smuzhiyun timer_setup(&battery->caltimer,
1728*4882a593Smuzhiyun rk817_bat_caltimer_isr,
1729*4882a593Smuzhiyun 0);
1730*4882a593Smuzhiyun battery->caltimer.expires = jiffies + MINUTE(8) * HZ;
1731*4882a593Smuzhiyun add_timer(&battery->caltimer);
1732*4882a593Smuzhiyun INIT_DELAYED_WORK(&battery->calib_delay_work, rk817_bat_internal_calib);
1733*4882a593Smuzhiyun }
1734*4882a593Smuzhiyun
rk817_bat_init_fg(struct rk817_battery_device * battery)1735*4882a593Smuzhiyun static void rk817_bat_init_fg(struct rk817_battery_device *battery)
1736*4882a593Smuzhiyun {
1737*4882a593Smuzhiyun rk817_bat_adc_init(battery);
1738*4882a593Smuzhiyun rk817_bat_gas_gaugle_enable(battery);
1739*4882a593Smuzhiyun rk817_bat_gg_con_init(battery);
1740*4882a593Smuzhiyun rk817_bat_init_voltage_kb(battery);
1741*4882a593Smuzhiyun rk817_bat_set_relax_sample(battery);
1742*4882a593Smuzhiyun rk817_bat_ocv_thre(battery, 0xff);
1743*4882a593Smuzhiyun rk817_bat_init_caltimer(battery);
1744*4882a593Smuzhiyun rk817_bat_rsoc_init(battery);
1745*4882a593Smuzhiyun rk817_bat_init_coulomb_cap(battery, battery->nac);
1746*4882a593Smuzhiyun DBG("rsoc%d, fcc = %d\n", battery->rsoc, battery->fcc);
1747*4882a593Smuzhiyun rk817_bat_init_dsoc_algorithm(battery);
1748*4882a593Smuzhiyun battery->qmax = rk817_bat_get_qmax(battery);
1749*4882a593Smuzhiyun battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
1750*4882a593Smuzhiyun battery->voltage_sys = rk817_bat_get_sys_voltage(battery);
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun battery->voltage_ocv = rk817_bat_get_ocv_voltage(battery);
1753*4882a593Smuzhiyun battery->voltage_relax = rk817_bat_get_relax_voltage(battery);
1754*4882a593Smuzhiyun battery->current_avg = rk817_bat_get_avg_current(battery);
1755*4882a593Smuzhiyun battery->dbg_pwr_dsoc = battery->dsoc;
1756*4882a593Smuzhiyun battery->dbg_pwr_rsoc = battery->rsoc;
1757*4882a593Smuzhiyun battery->dbg_pwr_vol = battery->voltage_avg;
1758*4882a593Smuzhiyun battery->temperature = VIRTUAL_TEMPERATURE;
1759*4882a593Smuzhiyun
1760*4882a593Smuzhiyun DBG("probe init: battery->dsoc = %d, rsoc = %d\n"
1761*4882a593Smuzhiyun "remain_cap = %d\n, battery_vol = %d\n, system_vol = %d, qmax = %d\n",
1762*4882a593Smuzhiyun battery->dsoc, battery->rsoc, battery->remain_cap,
1763*4882a593Smuzhiyun battery->voltage_avg, battery->voltage_sys, battery->qmax);
1764*4882a593Smuzhiyun DBG("OCV_THRE_VOL: 0x%x", rk817_bat_field_read(battery, OCV_THRE_VOL));
1765*4882a593Smuzhiyun }
1766*4882a593Smuzhiyun
rk817_bat_parse_dt(struct rk817_battery_device * battery)1767*4882a593Smuzhiyun static int rk817_bat_parse_dt(struct rk817_battery_device *battery)
1768*4882a593Smuzhiyun {
1769*4882a593Smuzhiyun u32 out_value;
1770*4882a593Smuzhiyun int length, ret;
1771*4882a593Smuzhiyun size_t size;
1772*4882a593Smuzhiyun struct battery_platform_data *pdata;
1773*4882a593Smuzhiyun struct device *dev = battery->dev;
1774*4882a593Smuzhiyun struct device_node *np = battery->dev->of_node;
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyun pdata = devm_kzalloc(battery->dev, sizeof(*pdata), GFP_KERNEL);
1777*4882a593Smuzhiyun if (!pdata)
1778*4882a593Smuzhiyun return -ENOMEM;
1779*4882a593Smuzhiyun
1780*4882a593Smuzhiyun battery->pdata = pdata;
1781*4882a593Smuzhiyun /* init default param */
1782*4882a593Smuzhiyun pdata->bat_res = DEFAULT_BAT_RES;
1783*4882a593Smuzhiyun pdata->monitor_sec = DEFAULT_MONITOR_SEC;
1784*4882a593Smuzhiyun pdata->pwroff_vol = DEFAULT_PWROFF_VOL_THRESD;
1785*4882a593Smuzhiyun pdata->sleep_exit_current = DEFAULT_SLP_EXIT_CUR;
1786*4882a593Smuzhiyun pdata->sleep_enter_current = DEFAULT_SLP_ENTER_CUR;
1787*4882a593Smuzhiyun
1788*4882a593Smuzhiyun pdata->sleep_filter_current = DEFAULT_SLP_FILTER_CUR;
1789*4882a593Smuzhiyun pdata->bat_mode = MODE_BATTARY;
1790*4882a593Smuzhiyun pdata->max_soc_offset = DEFAULT_MAX_SOC_OFFSET;
1791*4882a593Smuzhiyun pdata->fb_temp = DEFAULT_FB_TEMP;
1792*4882a593Smuzhiyun pdata->energy_mode = DEFAULT_ENERGY_MODE;
1793*4882a593Smuzhiyun pdata->zero_reserve_dsoc = DEFAULT_ZERO_RESERVE_DSOC * 1000;
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun pdata->sample_res = DEFAULT_SAMPLE_RES;
1796*4882a593Smuzhiyun
1797*4882a593Smuzhiyun /* parse necessary param */
1798*4882a593Smuzhiyun if (!of_find_property(np, "ocv_table", &length)) {
1799*4882a593Smuzhiyun dev_err(dev, "ocv_table not found!\n");
1800*4882a593Smuzhiyun return -EINVAL;
1801*4882a593Smuzhiyun }
1802*4882a593Smuzhiyun
1803*4882a593Smuzhiyun pdata->ocv_size = length / sizeof(u32);
1804*4882a593Smuzhiyun if (pdata->ocv_size <= 0) {
1805*4882a593Smuzhiyun dev_err(dev, "invalid ocv table\n");
1806*4882a593Smuzhiyun return -EINVAL;
1807*4882a593Smuzhiyun }
1808*4882a593Smuzhiyun
1809*4882a593Smuzhiyun size = sizeof(*pdata->ocv_table) * pdata->ocv_size;
1810*4882a593Smuzhiyun pdata->ocv_table = devm_kzalloc(battery->dev, size, GFP_KERNEL);
1811*4882a593Smuzhiyun if (!pdata->ocv_table)
1812*4882a593Smuzhiyun return -ENOMEM;
1813*4882a593Smuzhiyun
1814*4882a593Smuzhiyun ret = of_property_read_u32_array(np, "ocv_table", pdata->ocv_table,
1815*4882a593Smuzhiyun pdata->ocv_size);
1816*4882a593Smuzhiyun if (ret < 0)
1817*4882a593Smuzhiyun return ret;
1818*4882a593Smuzhiyun
1819*4882a593Smuzhiyun ret = of_property_read_u32(np, "design_capacity", &out_value);
1820*4882a593Smuzhiyun if (ret < 0) {
1821*4882a593Smuzhiyun dev_err(dev, "design_capacity not found!\n");
1822*4882a593Smuzhiyun return ret;
1823*4882a593Smuzhiyun }
1824*4882a593Smuzhiyun pdata->design_capacity = out_value;
1825*4882a593Smuzhiyun
1826*4882a593Smuzhiyun ret = of_property_read_u32(np, "design_qmax", &out_value);
1827*4882a593Smuzhiyun if (ret < 0) {
1828*4882a593Smuzhiyun dev_err(dev, "design_qmax not found!\n");
1829*4882a593Smuzhiyun return ret;
1830*4882a593Smuzhiyun }
1831*4882a593Smuzhiyun pdata->design_qmax = out_value;
1832*4882a593Smuzhiyun
1833*4882a593Smuzhiyun /* parse unnecessary param */
1834*4882a593Smuzhiyun ret = of_property_read_u32(np, "sample_res", &pdata->sample_res);
1835*4882a593Smuzhiyun if (ret < 0)
1836*4882a593Smuzhiyun dev_err(dev, "sample_res missing!\n");
1837*4882a593Smuzhiyun
1838*4882a593Smuzhiyun ret = of_property_read_u32(np, "fb_temperature", &pdata->fb_temp);
1839*4882a593Smuzhiyun if (ret < 0)
1840*4882a593Smuzhiyun dev_err(dev, "fb_temperature missing!\n");
1841*4882a593Smuzhiyun
1842*4882a593Smuzhiyun ret = of_property_read_u32(np, "energy_mode", &pdata->energy_mode);
1843*4882a593Smuzhiyun if (ret < 0)
1844*4882a593Smuzhiyun dev_err(dev, "energy_mode missing!\n");
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun ret = of_property_read_u32(np, "max_soc_offset",
1847*4882a593Smuzhiyun &pdata->max_soc_offset);
1848*4882a593Smuzhiyun if (ret < 0)
1849*4882a593Smuzhiyun dev_err(dev, "max_soc_offset missing!\n");
1850*4882a593Smuzhiyun
1851*4882a593Smuzhiyun ret = of_property_read_u32(np, "monitor_sec", &pdata->monitor_sec);
1852*4882a593Smuzhiyun if (ret < 0)
1853*4882a593Smuzhiyun dev_err(dev, "monitor_sec missing!\n");
1854*4882a593Smuzhiyun
1855*4882a593Smuzhiyun ret = of_property_read_u32(np, "zero_algorithm_vol",
1856*4882a593Smuzhiyun &pdata->zero_algorithm_vol);
1857*4882a593Smuzhiyun if (ret < 0)
1858*4882a593Smuzhiyun dev_err(dev, "zero_algorithm_vol missing!\n");
1859*4882a593Smuzhiyun
1860*4882a593Smuzhiyun ret = of_property_read_u32(np, "zero_reserve_dsoc",
1861*4882a593Smuzhiyun &pdata->zero_reserve_dsoc);
1862*4882a593Smuzhiyun if (ret < 0)
1863*4882a593Smuzhiyun dev_err(dev, "zero_reserve_dsoc missing!\n");
1864*4882a593Smuzhiyun pdata->zero_reserve_dsoc *= 1000;
1865*4882a593Smuzhiyun
1866*4882a593Smuzhiyun ret = of_property_read_u32(np, "virtual_power", &pdata->bat_mode);
1867*4882a593Smuzhiyun if (ret < 0)
1868*4882a593Smuzhiyun dev_err(dev, "virtual_power missing!\n");
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun ret = of_property_read_u32(np, "bat_res", &pdata->bat_res);
1871*4882a593Smuzhiyun if (ret < 0)
1872*4882a593Smuzhiyun dev_err(dev, "bat_res missing!\n");
1873*4882a593Smuzhiyun
1874*4882a593Smuzhiyun ret = of_property_read_u32(np, "sleep_enter_current",
1875*4882a593Smuzhiyun &pdata->sleep_enter_current);
1876*4882a593Smuzhiyun if (ret < 0)
1877*4882a593Smuzhiyun dev_err(dev, "sleep_enter_current missing!\n");
1878*4882a593Smuzhiyun
1879*4882a593Smuzhiyun ret = of_property_read_u32(np, "sleep_exit_current",
1880*4882a593Smuzhiyun &pdata->sleep_exit_current);
1881*4882a593Smuzhiyun if (ret < 0)
1882*4882a593Smuzhiyun dev_err(dev, "sleep_exit_current missing!\n");
1883*4882a593Smuzhiyun
1884*4882a593Smuzhiyun ret = of_property_read_u32(np, "sleep_filter_current",
1885*4882a593Smuzhiyun &pdata->sleep_filter_current);
1886*4882a593Smuzhiyun if (ret < 0)
1887*4882a593Smuzhiyun dev_err(dev, "sleep_filter_current missing!\n");
1888*4882a593Smuzhiyun
1889*4882a593Smuzhiyun ret = of_property_read_u32(np, "power_off_thresd", &pdata->pwroff_vol);
1890*4882a593Smuzhiyun if (ret < 0)
1891*4882a593Smuzhiyun dev_err(dev, "power_off_thresd missing!\n");
1892*4882a593Smuzhiyun
1893*4882a593Smuzhiyun ret = of_property_read_u32(np, "low_power_sleep", &pdata->low_pwr_sleep);
1894*4882a593Smuzhiyun if (ret < 0)
1895*4882a593Smuzhiyun dev_info(dev, "low_power_sleep missing!\n");
1896*4882a593Smuzhiyun
1897*4882a593Smuzhiyun if (battery->chip_id == RK809_ID) {
1898*4882a593Smuzhiyun ret = of_property_read_u32(np, "bat_res_up",
1899*4882a593Smuzhiyun &pdata->bat_res_up);
1900*4882a593Smuzhiyun if (ret < 0)
1901*4882a593Smuzhiyun dev_err(dev, "battery res_up missing\n");
1902*4882a593Smuzhiyun
1903*4882a593Smuzhiyun ret = of_property_read_u32(np, "bat_res_down",
1904*4882a593Smuzhiyun &pdata->bat_res_down);
1905*4882a593Smuzhiyun if (ret < 0)
1906*4882a593Smuzhiyun dev_err(dev, "battery res_down missing!\n");
1907*4882a593Smuzhiyun
1908*4882a593Smuzhiyun ret = of_property_read_u32(np, "design_max_voltage",
1909*4882a593Smuzhiyun &pdata->design_max_voltage);
1910*4882a593Smuzhiyun if (ret < 0)
1911*4882a593Smuzhiyun dev_err(dev, "battery design_max_voltage missing!\n");
1912*4882a593Smuzhiyun
1913*4882a593Smuzhiyun ret = of_property_read_u32(np, "register_chg_psy",
1914*4882a593Smuzhiyun &battery->is_register_chg_psy);
1915*4882a593Smuzhiyun if (ret < 0 || !battery->is_register_chg_psy)
1916*4882a593Smuzhiyun dev_err(dev, "not have to register chg psy!\n");
1917*4882a593Smuzhiyun }
1918*4882a593Smuzhiyun
1919*4882a593Smuzhiyun DBG("the battery dts info dump:\n"
1920*4882a593Smuzhiyun "bat_res:%d\n"
1921*4882a593Smuzhiyun "res_sample:%d\n"
1922*4882a593Smuzhiyun "design_capacity:%d\n"
1923*4882a593Smuzhiyun "design_qmax :%d\n"
1924*4882a593Smuzhiyun "sleep_enter_current:%d\n"
1925*4882a593Smuzhiyun "sleep_exit_current:%d\n"
1926*4882a593Smuzhiyun "sleep_filter_current:%d\n"
1927*4882a593Smuzhiyun "zero_algorithm_vol:%d\n"
1928*4882a593Smuzhiyun "zero_reserve_dsoc:%d\n"
1929*4882a593Smuzhiyun "monitor_sec:%d\n"
1930*4882a593Smuzhiyun "max_soc_offset:%d\n"
1931*4882a593Smuzhiyun "virtual_power:%d\n"
1932*4882a593Smuzhiyun "pwroff_vol:%d\n",
1933*4882a593Smuzhiyun pdata->bat_res,
1934*4882a593Smuzhiyun pdata->sample_res,
1935*4882a593Smuzhiyun pdata->design_capacity,
1936*4882a593Smuzhiyun pdata->design_qmax,
1937*4882a593Smuzhiyun pdata->sleep_enter_current,
1938*4882a593Smuzhiyun pdata->sleep_exit_current,
1939*4882a593Smuzhiyun pdata->sleep_filter_current,
1940*4882a593Smuzhiyun pdata->zero_algorithm_vol,
1941*4882a593Smuzhiyun pdata->zero_reserve_dsoc,
1942*4882a593Smuzhiyun pdata->monitor_sec,
1943*4882a593Smuzhiyun pdata->max_soc_offset,
1944*4882a593Smuzhiyun pdata->bat_mode,
1945*4882a593Smuzhiyun pdata->pwroff_vol);
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun return 0;
1948*4882a593Smuzhiyun }
1949*4882a593Smuzhiyun
1950*4882a593Smuzhiyun static enum power_supply_property rk817_bat_props[] = {
1951*4882a593Smuzhiyun POWER_SUPPLY_PROP_STATUS,
1952*4882a593Smuzhiyun POWER_SUPPLY_PROP_CURRENT_NOW,
1953*4882a593Smuzhiyun POWER_SUPPLY_PROP_VOLTAGE_NOW,
1954*4882a593Smuzhiyun POWER_SUPPLY_PROP_HEALTH,
1955*4882a593Smuzhiyun POWER_SUPPLY_PROP_CAPACITY,
1956*4882a593Smuzhiyun POWER_SUPPLY_PROP_CAPACITY_LEVEL,
1957*4882a593Smuzhiyun POWER_SUPPLY_PROP_TEMP,
1958*4882a593Smuzhiyun POWER_SUPPLY_PROP_CHARGE_COUNTER,
1959*4882a593Smuzhiyun POWER_SUPPLY_PROP_CHARGE_FULL,
1960*4882a593Smuzhiyun POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
1961*4882a593Smuzhiyun POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
1962*4882a593Smuzhiyun };
1963*4882a593Smuzhiyun
rk817_bat_get_usb_psy(struct device * dev,void * data)1964*4882a593Smuzhiyun static int rk817_bat_get_usb_psy(struct device *dev, void *data)
1965*4882a593Smuzhiyun {
1966*4882a593Smuzhiyun struct rk817_battery_device *battery = data;
1967*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1968*4882a593Smuzhiyun
1969*4882a593Smuzhiyun if (psy->desc->type == POWER_SUPPLY_TYPE_USB) {
1970*4882a593Smuzhiyun battery->usb_psy = psy;
1971*4882a593Smuzhiyun return 1;
1972*4882a593Smuzhiyun }
1973*4882a593Smuzhiyun
1974*4882a593Smuzhiyun return 0;
1975*4882a593Smuzhiyun }
1976*4882a593Smuzhiyun
rk817_bat_get_ac_psy(struct device * dev,void * data)1977*4882a593Smuzhiyun static int rk817_bat_get_ac_psy(struct device *dev, void *data)
1978*4882a593Smuzhiyun {
1979*4882a593Smuzhiyun struct rk817_battery_device *battery = data;
1980*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1981*4882a593Smuzhiyun
1982*4882a593Smuzhiyun if (psy->desc->type == POWER_SUPPLY_TYPE_MAINS) {
1983*4882a593Smuzhiyun battery->ac_psy = psy;
1984*4882a593Smuzhiyun return 1;
1985*4882a593Smuzhiyun }
1986*4882a593Smuzhiyun
1987*4882a593Smuzhiyun return 0;
1988*4882a593Smuzhiyun }
1989*4882a593Smuzhiyun
rk817_bat_get_chrg_psy(struct rk817_battery_device * battery)1990*4882a593Smuzhiyun static void rk817_bat_get_chrg_psy(struct rk817_battery_device *battery)
1991*4882a593Smuzhiyun {
1992*4882a593Smuzhiyun if (!battery->usb_psy)
1993*4882a593Smuzhiyun class_for_each_device(power_supply_class, NULL, (void *)battery,
1994*4882a593Smuzhiyun rk817_bat_get_usb_psy);
1995*4882a593Smuzhiyun if (!battery->ac_psy)
1996*4882a593Smuzhiyun class_for_each_device(power_supply_class, NULL, (void *)battery,
1997*4882a593Smuzhiyun rk817_bat_get_ac_psy);
1998*4882a593Smuzhiyun }
1999*4882a593Smuzhiyun
rk817_bat_get_charge_state(struct rk817_battery_device * battery)2000*4882a593Smuzhiyun static int rk817_bat_get_charge_state(struct rk817_battery_device *battery)
2001*4882a593Smuzhiyun {
2002*4882a593Smuzhiyun union power_supply_propval val;
2003*4882a593Smuzhiyun int ret;
2004*4882a593Smuzhiyun struct power_supply *psy;
2005*4882a593Smuzhiyun
2006*4882a593Smuzhiyun if (!battery->usb_psy || !battery->ac_psy)
2007*4882a593Smuzhiyun rk817_bat_get_chrg_psy(battery);
2008*4882a593Smuzhiyun
2009*4882a593Smuzhiyun psy = battery->usb_psy;
2010*4882a593Smuzhiyun if (psy) {
2011*4882a593Smuzhiyun ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
2012*4882a593Smuzhiyun &val);
2013*4882a593Smuzhiyun if (!ret)
2014*4882a593Smuzhiyun battery->usb_in = val.intval;
2015*4882a593Smuzhiyun }
2016*4882a593Smuzhiyun
2017*4882a593Smuzhiyun psy = battery->ac_psy;
2018*4882a593Smuzhiyun if (psy) {
2019*4882a593Smuzhiyun ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
2020*4882a593Smuzhiyun &val);
2021*4882a593Smuzhiyun if (!ret)
2022*4882a593Smuzhiyun battery->ac_in = val.intval;
2023*4882a593Smuzhiyun }
2024*4882a593Smuzhiyun
2025*4882a593Smuzhiyun DBG("%s: ac_online=%d, usb_online=%d\n",
2026*4882a593Smuzhiyun __func__, battery->ac_in, battery->usb_in);
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun return (battery->usb_in || battery->ac_in);
2029*4882a593Smuzhiyun }
2030*4882a593Smuzhiyun
rk817_get_capacity_leve(struct rk817_battery_device * battery)2031*4882a593Smuzhiyun static int rk817_get_capacity_leve(struct rk817_battery_device *battery)
2032*4882a593Smuzhiyun {
2033*4882a593Smuzhiyun int dsoc;
2034*4882a593Smuzhiyun
2035*4882a593Smuzhiyun if (battery->pdata->bat_mode == MODE_VIRTUAL)
2036*4882a593Smuzhiyun return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
2037*4882a593Smuzhiyun
2038*4882a593Smuzhiyun dsoc = (battery->dsoc + 500) / 1000;
2039*4882a593Smuzhiyun if (dsoc < 1)
2040*4882a593Smuzhiyun return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
2041*4882a593Smuzhiyun else if (dsoc <= 20)
2042*4882a593Smuzhiyun return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
2043*4882a593Smuzhiyun else if (dsoc <= 70)
2044*4882a593Smuzhiyun return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
2045*4882a593Smuzhiyun else if (dsoc <= 90)
2046*4882a593Smuzhiyun return POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
2047*4882a593Smuzhiyun else
2048*4882a593Smuzhiyun return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
2049*4882a593Smuzhiyun }
2050*4882a593Smuzhiyun
rk817_battery_time_to_full(struct rk817_battery_device * battery)2051*4882a593Smuzhiyun static int rk817_battery_time_to_full(struct rk817_battery_device *battery)
2052*4882a593Smuzhiyun {
2053*4882a593Smuzhiyun int time_sec;
2054*4882a593Smuzhiyun int cap_temp;
2055*4882a593Smuzhiyun
2056*4882a593Smuzhiyun if (battery->pdata->bat_mode == MODE_VIRTUAL) {
2057*4882a593Smuzhiyun time_sec = 3600;
2058*4882a593Smuzhiyun } else if (battery->voltage_avg > 0) {
2059*4882a593Smuzhiyun cap_temp = battery->design_cap - (battery->remain_cap / 1000);
2060*4882a593Smuzhiyun if (cap_temp < 0)
2061*4882a593Smuzhiyun cap_temp = 0;
2062*4882a593Smuzhiyun time_sec = (3600 * cap_temp) / battery->voltage_avg;
2063*4882a593Smuzhiyun } else {
2064*4882a593Smuzhiyun time_sec = 3600 * 24; /* One day */
2065*4882a593Smuzhiyun }
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun return time_sec;
2068*4882a593Smuzhiyun }
2069*4882a593Smuzhiyun
rk817_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)2070*4882a593Smuzhiyun static int rk817_battery_get_property(struct power_supply *psy,
2071*4882a593Smuzhiyun enum power_supply_property psp,
2072*4882a593Smuzhiyun union power_supply_propval *val)
2073*4882a593Smuzhiyun {
2074*4882a593Smuzhiyun struct rk817_battery_device *battery = power_supply_get_drvdata(psy);
2075*4882a593Smuzhiyun
2076*4882a593Smuzhiyun switch (psp) {
2077*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CURRENT_NOW:
2078*4882a593Smuzhiyun val->intval = battery->current_avg * 1000;/*uA*/
2079*4882a593Smuzhiyun if (battery->pdata->bat_mode == MODE_VIRTUAL)
2080*4882a593Smuzhiyun val->intval = VIRTUAL_CURRENT * 1000;
2081*4882a593Smuzhiyun break;
2082*4882a593Smuzhiyun case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2083*4882a593Smuzhiyun val->intval = battery->voltage_avg * 1000;/*uV*/
2084*4882a593Smuzhiyun if (battery->pdata->bat_mode == MODE_VIRTUAL)
2085*4882a593Smuzhiyun val->intval = VIRTUAL_VOLTAGE * 1000;
2086*4882a593Smuzhiyun break;
2087*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CAPACITY:
2088*4882a593Smuzhiyun val->intval = (battery->dsoc + 500) / 1000;
2089*4882a593Smuzhiyun if (battery->pdata->bat_mode == MODE_VIRTUAL)
2090*4882a593Smuzhiyun val->intval = VIRTUAL_SOC;
2091*4882a593Smuzhiyun break;
2092*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
2093*4882a593Smuzhiyun val->intval = rk817_get_capacity_leve(battery);
2094*4882a593Smuzhiyun break;
2095*4882a593Smuzhiyun case POWER_SUPPLY_PROP_HEALTH:
2096*4882a593Smuzhiyun val->intval = POWER_SUPPLY_HEALTH_GOOD;
2097*4882a593Smuzhiyun break;
2098*4882a593Smuzhiyun case POWER_SUPPLY_PROP_TEMP:
2099*4882a593Smuzhiyun val->intval = battery->temperature;
2100*4882a593Smuzhiyun if (battery->pdata->bat_mode == MODE_VIRTUAL)
2101*4882a593Smuzhiyun val->intval = VIRTUAL_TEMPERATURE;
2102*4882a593Smuzhiyun break;
2103*4882a593Smuzhiyun case POWER_SUPPLY_PROP_STATUS:
2104*4882a593Smuzhiyun if (battery->pdata->bat_mode == MODE_VIRTUAL)
2105*4882a593Smuzhiyun val->intval = VIRTUAL_STATUS;
2106*4882a593Smuzhiyun else if (battery->dsoc == 100 * 1000)
2107*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_FULL;
2108*4882a593Smuzhiyun else {
2109*4882a593Smuzhiyun if ((battery->chip_id != RK809_ID) &&
2110*4882a593Smuzhiyun rk817_bat_get_charge_state(battery))
2111*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_CHARGING;
2112*4882a593Smuzhiyun else if (battery->chip_id == RK809_ID &&
2113*4882a593Smuzhiyun battery->plugin_trigger)
2114*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_CHARGING;
2115*4882a593Smuzhiyun else
2116*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2117*4882a593Smuzhiyun }
2118*4882a593Smuzhiyun break;
2119*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_COUNTER:
2120*4882a593Smuzhiyun val->intval = battery->charge_count;
2121*4882a593Smuzhiyun break;
2122*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_FULL:
2123*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2124*4882a593Smuzhiyun val->intval = battery->pdata->design_capacity * 1000;/* uAh */
2125*4882a593Smuzhiyun break;
2126*4882a593Smuzhiyun case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
2127*4882a593Smuzhiyun val->intval = rk817_battery_time_to_full(battery);
2128*4882a593Smuzhiyun break;
2129*4882a593Smuzhiyun case POWER_SUPPLY_PROP_VOLTAGE_MAX:
2130*4882a593Smuzhiyun val->intval = 4500 * 1000;
2131*4882a593Smuzhiyun break;
2132*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CURRENT_MAX:
2133*4882a593Smuzhiyun val->intval = 5000 * 1000;
2134*4882a593Smuzhiyun break;
2135*4882a593Smuzhiyun default:
2136*4882a593Smuzhiyun return -EINVAL;
2137*4882a593Smuzhiyun }
2138*4882a593Smuzhiyun
2139*4882a593Smuzhiyun return 0;
2140*4882a593Smuzhiyun }
2141*4882a593Smuzhiyun
2142*4882a593Smuzhiyun static const struct power_supply_desc rk817_bat_desc = {
2143*4882a593Smuzhiyun .name = "battery",
2144*4882a593Smuzhiyun .type = POWER_SUPPLY_TYPE_BATTERY,
2145*4882a593Smuzhiyun .properties = rk817_bat_props,
2146*4882a593Smuzhiyun .num_properties = ARRAY_SIZE(rk817_bat_props),
2147*4882a593Smuzhiyun .get_property = rk817_battery_get_property,
2148*4882a593Smuzhiyun };
2149*4882a593Smuzhiyun
rk817_bat_init_power_supply(struct rk817_battery_device * battery)2150*4882a593Smuzhiyun static int rk817_bat_init_power_supply(struct rk817_battery_device *battery)
2151*4882a593Smuzhiyun {
2152*4882a593Smuzhiyun struct power_supply_config psy_cfg = { .drv_data = battery, };
2153*4882a593Smuzhiyun
2154*4882a593Smuzhiyun battery->bat = devm_power_supply_register(battery->dev,
2155*4882a593Smuzhiyun &rk817_bat_desc,
2156*4882a593Smuzhiyun &psy_cfg);
2157*4882a593Smuzhiyun if (IS_ERR(battery->bat)) {
2158*4882a593Smuzhiyun dev_err(battery->dev, "register bat power supply fail\n");
2159*4882a593Smuzhiyun return PTR_ERR(battery->bat);
2160*4882a593Smuzhiyun }
2161*4882a593Smuzhiyun
2162*4882a593Smuzhiyun return 0;
2163*4882a593Smuzhiyun }
2164*4882a593Smuzhiyun
2165*4882a593Smuzhiyun static enum power_supply_property rk809_chg_props[] = {
2166*4882a593Smuzhiyun POWER_SUPPLY_PROP_ONLINE,
2167*4882a593Smuzhiyun POWER_SUPPLY_PROP_STATUS,
2168*4882a593Smuzhiyun };
2169*4882a593Smuzhiyun
rk809_chg_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)2170*4882a593Smuzhiyun static int rk809_chg_get_property(struct power_supply *psy,
2171*4882a593Smuzhiyun enum power_supply_property psp,
2172*4882a593Smuzhiyun union power_supply_propval *val)
2173*4882a593Smuzhiyun {
2174*4882a593Smuzhiyun struct rk817_battery_device *battery = power_supply_get_drvdata(psy);
2175*4882a593Smuzhiyun int online = 0;
2176*4882a593Smuzhiyun int ret = 0;
2177*4882a593Smuzhiyun
2178*4882a593Smuzhiyun if (battery->plugin_trigger)
2179*4882a593Smuzhiyun online = 1;
2180*4882a593Smuzhiyun switch (psp) {
2181*4882a593Smuzhiyun case POWER_SUPPLY_PROP_ONLINE:
2182*4882a593Smuzhiyun val->intval = online;
2183*4882a593Smuzhiyun dev_dbg(battery->dev, "report online: %d\n", val->intval);
2184*4882a593Smuzhiyun break;
2185*4882a593Smuzhiyun case POWER_SUPPLY_PROP_STATUS:
2186*4882a593Smuzhiyun if (online)
2187*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_CHARGING;
2188*4882a593Smuzhiyun else
2189*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2190*4882a593Smuzhiyun dev_dbg(battery->dev, "report prop: %d\n", val->intval);
2191*4882a593Smuzhiyun break;
2192*4882a593Smuzhiyun default:
2193*4882a593Smuzhiyun ret = -EINVAL;
2194*4882a593Smuzhiyun break;
2195*4882a593Smuzhiyun }
2196*4882a593Smuzhiyun
2197*4882a593Smuzhiyun return ret;
2198*4882a593Smuzhiyun }
2199*4882a593Smuzhiyun
2200*4882a593Smuzhiyun static const struct power_supply_desc rk809_chg_desc = {
2201*4882a593Smuzhiyun .name = "charger",
2202*4882a593Smuzhiyun .type = POWER_SUPPLY_TYPE_USB,
2203*4882a593Smuzhiyun .properties = rk809_chg_props,
2204*4882a593Smuzhiyun .num_properties = ARRAY_SIZE(rk809_chg_props),
2205*4882a593Smuzhiyun .get_property = rk809_chg_get_property,
2206*4882a593Smuzhiyun };
2207*4882a593Smuzhiyun
rk809_chg_init_power_supply(struct rk817_battery_device * battery)2208*4882a593Smuzhiyun static int rk809_chg_init_power_supply(struct rk817_battery_device *battery)
2209*4882a593Smuzhiyun {
2210*4882a593Smuzhiyun struct power_supply_config psy_cfg = { .drv_data = battery, };
2211*4882a593Smuzhiyun
2212*4882a593Smuzhiyun battery->chg_psy =
2213*4882a593Smuzhiyun devm_power_supply_register(battery->dev, &rk809_chg_desc,
2214*4882a593Smuzhiyun &psy_cfg);
2215*4882a593Smuzhiyun if (IS_ERR(battery->chg_psy)) {
2216*4882a593Smuzhiyun dev_err(battery->dev, "register chg psy power supply fail\n");
2217*4882a593Smuzhiyun return PTR_ERR(battery->chg_psy);
2218*4882a593Smuzhiyun }
2219*4882a593Smuzhiyun
2220*4882a593Smuzhiyun return 0;
2221*4882a593Smuzhiyun }
2222*4882a593Smuzhiyun
rk817_bat_power_supply_changed(struct rk817_battery_device * battery)2223*4882a593Smuzhiyun static void rk817_bat_power_supply_changed(struct rk817_battery_device *battery)
2224*4882a593Smuzhiyun {
2225*4882a593Smuzhiyun static int old_soc = -1;
2226*4882a593Smuzhiyun
2227*4882a593Smuzhiyun if (battery->dsoc > 100 * 1000)
2228*4882a593Smuzhiyun battery->dsoc = 100 * 1000;
2229*4882a593Smuzhiyun else if (battery->dsoc < 0)
2230*4882a593Smuzhiyun battery->dsoc = 0;
2231*4882a593Smuzhiyun
2232*4882a593Smuzhiyun if (battery->dsoc == old_soc && !battery->change)
2233*4882a593Smuzhiyun return;
2234*4882a593Smuzhiyun
2235*4882a593Smuzhiyun battery->change = false;
2236*4882a593Smuzhiyun old_soc = battery->dsoc;
2237*4882a593Smuzhiyun battery->last_dsoc = battery->dsoc;
2238*4882a593Smuzhiyun power_supply_changed(battery->bat);
2239*4882a593Smuzhiyun DBG("changed: dsoc=%d, rsoc=%d, v=%d, ov=%d c=%d, cap=%d, f=%d\n",
2240*4882a593Smuzhiyun battery->dsoc, battery->rsoc, battery->voltage_avg,
2241*4882a593Smuzhiyun battery->voltage_ocv, battery->current_avg,
2242*4882a593Smuzhiyun battery->remain_cap, battery->fcc);
2243*4882a593Smuzhiyun
2244*4882a593Smuzhiyun DBG("dl=%d, rl=%d, v=%d, halt=%d, halt_n=%d, max=%d\n"
2245*4882a593Smuzhiyun "init=%d, sw=%d, calib=%d, below0=%d, force=%d\n",
2246*4882a593Smuzhiyun battery->dbg_pwr_dsoc, battery->dbg_pwr_rsoc,
2247*4882a593Smuzhiyun battery->dbg_pwr_vol,
2248*4882a593Smuzhiyun battery->is_halt, battery->halt_cnt,
2249*4882a593Smuzhiyun battery->is_max_soc_offset,
2250*4882a593Smuzhiyun battery->is_initialized, battery->is_sw_reset,
2251*4882a593Smuzhiyun battery->is_ocv_calib,
2252*4882a593Smuzhiyun battery->dbg_cap_low0, battery->is_force_calib);
2253*4882a593Smuzhiyun }
2254*4882a593Smuzhiyun
rk817_battery_debug_info(struct rk817_battery_device * battery)2255*4882a593Smuzhiyun static void rk817_battery_debug_info(struct rk817_battery_device *battery)
2256*4882a593Smuzhiyun {
2257*4882a593Smuzhiyun rk817_bat_get_battery_voltage(battery);
2258*4882a593Smuzhiyun rk817_bat_get_sys_voltage(battery);
2259*4882a593Smuzhiyun rk817_bat_get_USB_voltage(battery);
2260*4882a593Smuzhiyun rk817_bat_get_pwron_voltage(battery);
2261*4882a593Smuzhiyun rk817_bat_get_ocv_voltage(battery);
2262*4882a593Smuzhiyun rk817_bat_get_ocv0_voltage0(battery);
2263*4882a593Smuzhiyun
2264*4882a593Smuzhiyun rk817_bat_current_calibration(battery);
2265*4882a593Smuzhiyun rk817_bat_get_avg_current(battery);
2266*4882a593Smuzhiyun rk817_bat_get_relax_cur1(battery);
2267*4882a593Smuzhiyun rk817_bat_get_relax_cur2(battery);
2268*4882a593Smuzhiyun rk817_bat_get_relax_current(battery);
2269*4882a593Smuzhiyun rk817_bat_get_ocv_current(battery);
2270*4882a593Smuzhiyun rk817_bat_get_ocv_current0(battery);
2271*4882a593Smuzhiyun rk817_bat_get_pwron_current(battery);
2272*4882a593Smuzhiyun rk817_bat_get_ocv_count(battery);
2273*4882a593Smuzhiyun rk817_bat_save_dsoc(battery, battery->dsoc);
2274*4882a593Smuzhiyun DBG("capactiy = %d\n", rk817_bat_get_capacity_mah(battery));
2275*4882a593Smuzhiyun }
2276*4882a593Smuzhiyun
2277*4882a593Smuzhiyun static void
rk817_bat_update_charging_status(struct rk817_battery_device * battery)2278*4882a593Smuzhiyun rk817_bat_update_charging_status(struct rk817_battery_device *battery)
2279*4882a593Smuzhiyun {
2280*4882a593Smuzhiyun int is_charging;
2281*4882a593Smuzhiyun
2282*4882a593Smuzhiyun is_charging = rk817_bat_get_charge_state(battery);
2283*4882a593Smuzhiyun if (is_charging == battery->is_charging)
2284*4882a593Smuzhiyun return;
2285*4882a593Smuzhiyun
2286*4882a593Smuzhiyun battery->change = true;
2287*4882a593Smuzhiyun battery->is_charging = is_charging;
2288*4882a593Smuzhiyun if (is_charging)
2289*4882a593Smuzhiyun battery->charge_count++;
2290*4882a593Smuzhiyun }
2291*4882a593Smuzhiyun
rk817_bat_update_info(struct rk817_battery_device * battery)2292*4882a593Smuzhiyun static void rk817_bat_update_info(struct rk817_battery_device *battery)
2293*4882a593Smuzhiyun {
2294*4882a593Smuzhiyun battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
2295*4882a593Smuzhiyun battery->voltage_sys = rk817_bat_get_sys_voltage(battery);
2296*4882a593Smuzhiyun battery->current_avg = rk817_bat_get_avg_current(battery);
2297*4882a593Smuzhiyun battery->voltage_relax = rk817_bat_get_relax_voltage(battery);
2298*4882a593Smuzhiyun battery->rsoc = rk817_bat_get_rsoc(battery);
2299*4882a593Smuzhiyun battery->remain_cap = rk817_bat_get_capacity_uah(battery);
2300*4882a593Smuzhiyun battery->voltage_usb = rk817_bat_get_USB_voltage(battery);
2301*4882a593Smuzhiyun battery->chrg_status = get_charge_status(battery);
2302*4882a593Smuzhiyun rk817_bat_update_charging_status(battery);
2303*4882a593Smuzhiyun DBG("valtage usb: %d\n", battery->voltage_usb);
2304*4882a593Smuzhiyun DBG("UPDATE: voltage_avg = %d\n"
2305*4882a593Smuzhiyun "voltage_sys = %d\n"
2306*4882a593Smuzhiyun "curren_avg = %d\n"
2307*4882a593Smuzhiyun "rsoc = %d\n"
2308*4882a593Smuzhiyun "chrg_status = %d\n"
2309*4882a593Smuzhiyun "PWRON_CUR = %d\n"
2310*4882a593Smuzhiyun "remain_cap = %d\n",
2311*4882a593Smuzhiyun battery->voltage_avg,
2312*4882a593Smuzhiyun battery->voltage_sys,
2313*4882a593Smuzhiyun battery->current_avg,
2314*4882a593Smuzhiyun battery->rsoc,
2315*4882a593Smuzhiyun battery->chrg_status,
2316*4882a593Smuzhiyun rk817_bat_get_pwron_current(battery),
2317*4882a593Smuzhiyun battery->remain_cap);
2318*4882a593Smuzhiyun
2319*4882a593Smuzhiyun /* smooth charge */
2320*4882a593Smuzhiyun if (battery->remain_cap / 1000 > battery->fcc) {
2321*4882a593Smuzhiyun /*battery->sm_remain_cap -=*/
2322*4882a593Smuzhiyun /*(battery->remain_cap - battery->fcc * 1000);*/
2323*4882a593Smuzhiyun battery->sm_remain_cap = battery->fcc * 1000;
2324*4882a593Smuzhiyun DBG("<%s>. cap: remain=%d, sm_remain=%d\n",
2325*4882a593Smuzhiyun __func__, battery->remain_cap, battery->sm_remain_cap);
2326*4882a593Smuzhiyun DBG("fcc: %d\n", battery->fcc);
2327*4882a593Smuzhiyun rk817_bat_init_coulomb_cap(battery, battery->fcc + 100);
2328*4882a593Smuzhiyun rk817_bat_init_coulomb_cap(battery, battery->fcc);
2329*4882a593Smuzhiyun rk817_bat_get_capacity_mah(battery);
2330*4882a593Smuzhiyun }
2331*4882a593Smuzhiyun
2332*4882a593Smuzhiyun if (battery->chrg_status != CHARGE_FINISH)
2333*4882a593Smuzhiyun battery->finish_base = get_boot_sec();
2334*4882a593Smuzhiyun }
2335*4882a593Smuzhiyun
rk817_bat_save_data(struct rk817_battery_device * battery)2336*4882a593Smuzhiyun static void rk817_bat_save_data(struct rk817_battery_device *battery)
2337*4882a593Smuzhiyun {
2338*4882a593Smuzhiyun rk817_bat_save_dsoc(battery, battery->dsoc);
2339*4882a593Smuzhiyun rk817_bat_save_cap(battery, battery->remain_cap / 1000);
2340*4882a593Smuzhiyun }
2341*4882a593Smuzhiyun
2342*4882a593Smuzhiyun /* high load: current < 0 with charger in.
2343*4882a593Smuzhiyun * System will not shutdown while dsoc=0% with charging state(ac_in),
2344*4882a593Smuzhiyun * which will cause over discharge, so oppose status before report states.
2345*4882a593Smuzhiyun */
rk817_bat_lowpwr_check(struct rk817_battery_device * battery)2346*4882a593Smuzhiyun static void rk817_bat_lowpwr_check(struct rk817_battery_device *battery)
2347*4882a593Smuzhiyun {
2348*4882a593Smuzhiyun static u64 time;
2349*4882a593Smuzhiyun int pwr_off_thresd = battery->pdata->pwroff_vol;
2350*4882a593Smuzhiyun
2351*4882a593Smuzhiyun if (battery->current_avg < 0 && battery->voltage_avg < pwr_off_thresd) {
2352*4882a593Smuzhiyun if (!time)
2353*4882a593Smuzhiyun time = get_boot_sec();
2354*4882a593Smuzhiyun
2355*4882a593Smuzhiyun if ((base2sec(time) > MINUTE(1)) ||
2356*4882a593Smuzhiyun (battery->voltage_avg <= pwr_off_thresd - 50)) {
2357*4882a593Smuzhiyun battery->fake_offline = 1;
2358*4882a593Smuzhiyun if (battery->voltage_avg <= pwr_off_thresd - 50)
2359*4882a593Smuzhiyun battery->dsoc -= 1000;
2360*4882a593Smuzhiyun DBG("low power, soc=%d, current=%d\n",
2361*4882a593Smuzhiyun battery->dsoc, battery->current_avg);
2362*4882a593Smuzhiyun }
2363*4882a593Smuzhiyun } else {
2364*4882a593Smuzhiyun time = 0;
2365*4882a593Smuzhiyun battery->fake_offline = 0;
2366*4882a593Smuzhiyun }
2367*4882a593Smuzhiyun
2368*4882a593Smuzhiyun DBG("<%s>. t=%lu, dsoc=%d, current=%d, fake_offline=%d\n",
2369*4882a593Smuzhiyun __func__, base2sec(time), battery->dsoc,
2370*4882a593Smuzhiyun battery->current_avg, battery->fake_offline);
2371*4882a593Smuzhiyun }
2372*4882a593Smuzhiyun
rk817_bat_calc_smooth_dischrg(struct rk817_battery_device * battery)2373*4882a593Smuzhiyun static void rk817_bat_calc_smooth_dischrg(struct rk817_battery_device *battery)
2374*4882a593Smuzhiyun {
2375*4882a593Smuzhiyun int tmp_soc = 0;
2376*4882a593Smuzhiyun
2377*4882a593Smuzhiyun /* check new dsoc */
2378*4882a593Smuzhiyun if (battery->smooth_soc < 0)
2379*4882a593Smuzhiyun battery->smooth_soc = 0;
2380*4882a593Smuzhiyun
2381*4882a593Smuzhiyun tmp_soc = battery->smooth_soc / 1000;
2382*4882a593Smuzhiyun
2383*4882a593Smuzhiyun if (tmp_soc != battery->dsoc / 1000) {
2384*4882a593Smuzhiyun if (battery->smooth_soc > battery->dsoc)
2385*4882a593Smuzhiyun return;
2386*4882a593Smuzhiyun
2387*4882a593Smuzhiyun if (battery->smooth_soc + 1000 > battery->dsoc)
2388*4882a593Smuzhiyun battery->dsoc = battery->smooth_soc;
2389*4882a593Smuzhiyun else
2390*4882a593Smuzhiyun battery->dsoc -= 1000;
2391*4882a593Smuzhiyun
2392*4882a593Smuzhiyun if (battery->dsoc <= 0)
2393*4882a593Smuzhiyun battery->dsoc = 0;
2394*4882a593Smuzhiyun }
2395*4882a593Smuzhiyun }
2396*4882a593Smuzhiyun
rk817_bat_smooth_algorithm(struct rk817_battery_device * battery)2397*4882a593Smuzhiyun static void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery)
2398*4882a593Smuzhiyun {
2399*4882a593Smuzhiyun int ydsoc = 0, delta_cap = 0, old_cap = 0, tmp_soc;
2400*4882a593Smuzhiyun /*int linek;*/
2401*4882a593Smuzhiyun int diff, delta;
2402*4882a593Smuzhiyun /*int current_avg = rk817_bat_get_avg_current(battery);*/
2403*4882a593Smuzhiyun
2404*4882a593Smuzhiyun delta = abs(battery->dsoc - battery->rsoc);
2405*4882a593Smuzhiyun diff = delta * 3;/* speed:3/4 */
2406*4882a593Smuzhiyun
2407*4882a593Smuzhiyun /* charge and discharge switch */
2408*4882a593Smuzhiyun if ((battery->sm_linek * battery->current_avg <= 0)) {
2409*4882a593Smuzhiyun DBG("<%s>. linek mode, retinit sm linek..\n", __func__);
2410*4882a593Smuzhiyun rk817_bat_calc_sm_linek(battery);
2411*4882a593Smuzhiyun }
2412*4882a593Smuzhiyun
2413*4882a593Smuzhiyun /*battery->sm_linek = linek;*/
2414*4882a593Smuzhiyun
2415*4882a593Smuzhiyun battery->remain_cap = rk817_bat_get_capacity_uah(battery);
2416*4882a593Smuzhiyun
2417*4882a593Smuzhiyun old_cap = battery->sm_remain_cap;
2418*4882a593Smuzhiyun DBG("smooth: smooth_soc = %d, dsoc = %d, battery->sm_linek = %d\n",
2419*4882a593Smuzhiyun battery->smooth_soc, battery->dsoc, battery->sm_linek);
2420*4882a593Smuzhiyun
2421*4882a593Smuzhiyun /* discharge status: sm_remain_cap > remain_cap, delta_cap > 0 */
2422*4882a593Smuzhiyun /* from charge to discharge:
2423*4882a593Smuzhiyun * remain_cap may be above sm_remain_cap, delta_cap <= 0
2424*4882a593Smuzhiyun */
2425*4882a593Smuzhiyun delta_cap = battery->remain_cap - battery->sm_remain_cap;
2426*4882a593Smuzhiyun DBG("smooth: sm_remain_cap = %d, remain_cap = %d\n",
2427*4882a593Smuzhiyun battery->sm_remain_cap, battery->remain_cap);
2428*4882a593Smuzhiyun DBG("smooth: delta_cap = %d, dsoc = %d\n",
2429*4882a593Smuzhiyun delta_cap, battery->dsoc);
2430*4882a593Smuzhiyun
2431*4882a593Smuzhiyun if (delta_cap == 0) {
2432*4882a593Smuzhiyun DBG("<%s>. delta_cap = 0\n", __func__);
2433*4882a593Smuzhiyun return;
2434*4882a593Smuzhiyun }
2435*4882a593Smuzhiyun
2436*4882a593Smuzhiyun /* discharge: sm_linek < 0, if delate_cap <0, ydsoc > 0 */
2437*4882a593Smuzhiyun ydsoc = battery->sm_linek * abs(delta_cap / 10) / DIV(battery->fcc);
2438*4882a593Smuzhiyun
2439*4882a593Smuzhiyun DBG("smooth: ydsoc = %d, fcc = %d\n", ydsoc, battery->fcc);
2440*4882a593Smuzhiyun if (ydsoc == 0) {
2441*4882a593Smuzhiyun DBG("<%s>. ydsoc = 0\n", __func__);
2442*4882a593Smuzhiyun return;
2443*4882a593Smuzhiyun }
2444*4882a593Smuzhiyun battery->sm_remain_cap = battery->remain_cap;
2445*4882a593Smuzhiyun
2446*4882a593Smuzhiyun DBG("<%s>. k=%d, ydsoc=%d; cap:old=%d, new:%d; delta_cap=%d\n",
2447*4882a593Smuzhiyun __func__, battery->sm_linek, ydsoc, old_cap,
2448*4882a593Smuzhiyun battery->sm_remain_cap, delta_cap);
2449*4882a593Smuzhiyun
2450*4882a593Smuzhiyun /* discharge mode */
2451*4882a593Smuzhiyun /* discharge mode, but ydsoc > 0,
2452*4882a593Smuzhiyun * from charge status to dischrage
2453*4882a593Smuzhiyun */
2454*4882a593Smuzhiyun battery->smooth_soc += ydsoc;
2455*4882a593Smuzhiyun if (ydsoc < 0) {
2456*4882a593Smuzhiyun rk817_bat_calc_smooth_dischrg(battery);
2457*4882a593Smuzhiyun } else {
2458*4882a593Smuzhiyun if (battery->smooth_soc < 0)
2459*4882a593Smuzhiyun battery->smooth_soc = 0;
2460*4882a593Smuzhiyun
2461*4882a593Smuzhiyun tmp_soc = battery->smooth_soc / 1000;
2462*4882a593Smuzhiyun
2463*4882a593Smuzhiyun if (tmp_soc != battery->dsoc / 1000) {
2464*4882a593Smuzhiyun if (battery->smooth_soc < battery->dsoc)
2465*4882a593Smuzhiyun return;
2466*4882a593Smuzhiyun
2467*4882a593Smuzhiyun battery->dsoc = battery->smooth_soc;
2468*4882a593Smuzhiyun if (battery->dsoc <= 0)
2469*4882a593Smuzhiyun battery->dsoc = 0;
2470*4882a593Smuzhiyun }
2471*4882a593Smuzhiyun }
2472*4882a593Smuzhiyun
2473*4882a593Smuzhiyun if (battery->s2r) {
2474*4882a593Smuzhiyun battery->s2r = false;
2475*4882a593Smuzhiyun rk817_bat_calc_sm_linek(battery);
2476*4882a593Smuzhiyun }
2477*4882a593Smuzhiyun
2478*4882a593Smuzhiyun DBG("smooth: smooth_soc = %d, dsoc = %d\n",
2479*4882a593Smuzhiyun battery->smooth_soc, battery->dsoc);
2480*4882a593Smuzhiyun DBG("smooth: delta_cap = %d, dsoc = %d\n",
2481*4882a593Smuzhiyun delta_cap, battery->dsoc);
2482*4882a593Smuzhiyun }
2483*4882a593Smuzhiyun
rk817_bat_calc_zero_linek(struct rk817_battery_device * battery)2484*4882a593Smuzhiyun static void rk817_bat_calc_zero_linek(struct rk817_battery_device *battery)
2485*4882a593Smuzhiyun {
2486*4882a593Smuzhiyun int dead_voltage, ocv_voltage;
2487*4882a593Smuzhiyun int voltage_avg, current_avg, vsys;
2488*4882a593Smuzhiyun int ocv_cap, dead_cap, xsoc;
2489*4882a593Smuzhiyun int ocv_soc, dead_soc;
2490*4882a593Smuzhiyun int pwroff_vol;
2491*4882a593Smuzhiyun int min_gap_xsoc;
2492*4882a593Smuzhiyun int powerpatch_res;
2493*4882a593Smuzhiyun
2494*4882a593Smuzhiyun if ((abs(battery->current_avg) < 400) && (battery->dsoc / 1000 > 5))
2495*4882a593Smuzhiyun pwroff_vol = battery->pdata->pwroff_vol + 50;
2496*4882a593Smuzhiyun else
2497*4882a593Smuzhiyun pwroff_vol = battery->pdata->pwroff_vol;
2498*4882a593Smuzhiyun
2499*4882a593Smuzhiyun /* calc estimate ocv voltage */
2500*4882a593Smuzhiyun voltage_avg = rk817_bat_get_battery_voltage(battery);
2501*4882a593Smuzhiyun current_avg = rk817_bat_get_avg_current(battery);
2502*4882a593Smuzhiyun vsys = voltage_avg + (current_avg * DEF_PWRPATH_RES) / 1000;
2503*4882a593Smuzhiyun
2504*4882a593Smuzhiyun powerpatch_res = (voltage_avg - vsys) * 1000 / current_avg;
2505*4882a593Smuzhiyun
2506*4882a593Smuzhiyun battery->zero_voltage_avg = voltage_avg;
2507*4882a593Smuzhiyun battery->zero_current_avg = current_avg;
2508*4882a593Smuzhiyun battery->zero_vsys = vsys;
2509*4882a593Smuzhiyun
2510*4882a593Smuzhiyun DBG("Zero: voltage_avg = %d, Vsys = %d\n", voltage_avg, vsys);
2511*4882a593Smuzhiyun DBG("Zero: powerpatch_res = %d\n", powerpatch_res);
2512*4882a593Smuzhiyun DBG("ZERO0: shtd_vol: poweroff_vol(usr) = %d\n"
2513*4882a593Smuzhiyun "pwroff_vol = %d\n"
2514*4882a593Smuzhiyun "zero_reserve_dsoc = %d\n",
2515*4882a593Smuzhiyun battery->pdata->pwroff_vol,
2516*4882a593Smuzhiyun pwroff_vol,
2517*4882a593Smuzhiyun battery->pdata->zero_reserve_dsoc);
2518*4882a593Smuzhiyun
2519*4882a593Smuzhiyun /* get the dead ocv voltage, pwroff_vol is vsys */
2520*4882a593Smuzhiyun dead_voltage = pwroff_vol - current_avg *
2521*4882a593Smuzhiyun (battery->bat_res + DEF_PWRPATH_RES) / 1000;
2522*4882a593Smuzhiyun
2523*4882a593Smuzhiyun ocv_voltage = voltage_avg - (current_avg * battery->bat_res) / 1000;
2524*4882a593Smuzhiyun DBG("ZERO0: dead_voltage(shtd) = %d, ocv_voltage(now) = %d\n",
2525*4882a593Smuzhiyun dead_voltage, ocv_voltage);
2526*4882a593Smuzhiyun
2527*4882a593Smuzhiyun /* calc estimate soc and cap */
2528*4882a593Smuzhiyun dead_soc = rk817_bat_vol_to_soc(battery, dead_voltage);
2529*4882a593Smuzhiyun dead_cap = rk817_bat_vol_to_cap(battery, dead_voltage);
2530*4882a593Smuzhiyun DBG("ZERO0: dead_soc = %d, dead_cap = %d\n",
2531*4882a593Smuzhiyun dead_soc, dead_cap);
2532*4882a593Smuzhiyun
2533*4882a593Smuzhiyun ocv_soc = rk817_bat_vol_to_soc(battery, ocv_voltage);
2534*4882a593Smuzhiyun ocv_cap = rk817_bat_vol_to_cap(battery, ocv_voltage);
2535*4882a593Smuzhiyun DBG("ZERO0: ocv_soc = %d, ocv_cap = %d\n",
2536*4882a593Smuzhiyun ocv_soc, ocv_cap);
2537*4882a593Smuzhiyun
2538*4882a593Smuzhiyun /* xsoc: available rsoc */
2539*4882a593Smuzhiyun xsoc = ocv_soc - dead_soc;
2540*4882a593Smuzhiyun
2541*4882a593Smuzhiyun battery->zero_dead_voltage = dead_voltage;
2542*4882a593Smuzhiyun battery->zero_dead_soc = dead_soc;
2543*4882a593Smuzhiyun battery->zero_dead_cap = dead_cap;
2544*4882a593Smuzhiyun
2545*4882a593Smuzhiyun battery->zero_batvol_to_ocv = ocv_voltage;
2546*4882a593Smuzhiyun battery->zero_batocv_to_soc = ocv_soc;
2547*4882a593Smuzhiyun battery->zero_batocv_to_cap = ocv_cap;
2548*4882a593Smuzhiyun
2549*4882a593Smuzhiyun battery->zero_xsoc = xsoc;
2550*4882a593Smuzhiyun
2551*4882a593Smuzhiyun DBG("Zero: xsoc = %d\n", xsoc);
2552*4882a593Smuzhiyun /* min_gap_xsoc: reserve xsoc */
2553*4882a593Smuzhiyun if (abs(current_avg) > ZERO_LOAD_LVL1)
2554*4882a593Smuzhiyun min_gap_xsoc = MIN_ZERO_GAP_XSOC3;
2555*4882a593Smuzhiyun else if (abs(current_avg) > ZERO_LOAD_LVL2)
2556*4882a593Smuzhiyun min_gap_xsoc = MIN_ZERO_GAP_XSOC2;
2557*4882a593Smuzhiyun else
2558*4882a593Smuzhiyun min_gap_xsoc = MIN_ZERO_GAP_XSOC1;
2559*4882a593Smuzhiyun
2560*4882a593Smuzhiyun if ((xsoc <= 30) &&
2561*4882a593Smuzhiyun (battery->dsoc >= battery->pdata->zero_reserve_dsoc))
2562*4882a593Smuzhiyun min_gap_xsoc = min_gap_xsoc + MIN_ZERO_GAP_CALIB;
2563*4882a593Smuzhiyun
2564*4882a593Smuzhiyun battery->zero_remain_cap = battery->remain_cap;
2565*4882a593Smuzhiyun battery->zero_timeout_cnt = 0;
2566*4882a593Smuzhiyun if ((battery->dsoc / 1000 <= 1) && (xsoc > 0)) {
2567*4882a593Smuzhiyun battery->zero_linek = 400;
2568*4882a593Smuzhiyun battery->zero_drop_sec = 0;
2569*4882a593Smuzhiyun } else if (xsoc >= 0) {
2570*4882a593Smuzhiyun battery->zero_drop_sec = 0;
2571*4882a593Smuzhiyun battery->zero_linek =
2572*4882a593Smuzhiyun (battery->zero_dsoc + xsoc / 2) / DIV(xsoc);
2573*4882a593Smuzhiyun /* battery energy mode to use up voltage */
2574*4882a593Smuzhiyun if ((battery->pdata->energy_mode) &&
2575*4882a593Smuzhiyun (xsoc - battery->dsoc / 1000 >= MIN_ZERO_GAP_XSOC3) &&
2576*4882a593Smuzhiyun (battery->dsoc / 1000 <= 10) && (battery->zero_linek < 300)) {
2577*4882a593Smuzhiyun battery->zero_linek = 300;
2578*4882a593Smuzhiyun DBG("ZERO-new: zero_linek adjust step0...\n");
2579*4882a593Smuzhiyun /* reserve enough power yet, slow down any way */
2580*4882a593Smuzhiyun } else if ((xsoc - battery->dsoc / 1000 >= min_gap_xsoc) ||
2581*4882a593Smuzhiyun ((xsoc - battery->dsoc / 1000 >= MIN_ZERO_GAP_XSOC2) &&
2582*4882a593Smuzhiyun (battery->dsoc / 1000 <= 10) && (xsoc > 15))) {
2583*4882a593Smuzhiyun if (xsoc <= 20 &&
2584*4882a593Smuzhiyun battery->dsoc / 1000 >= battery->pdata->zero_reserve_dsoc)
2585*4882a593Smuzhiyun battery->zero_linek = 1200;
2586*4882a593Smuzhiyun else if (xsoc - battery->dsoc / 1000 >= 2 * min_gap_xsoc)
2587*4882a593Smuzhiyun battery->zero_linek = 400;
2588*4882a593Smuzhiyun else if (xsoc - battery->dsoc / 1000 >= 3 + min_gap_xsoc)
2589*4882a593Smuzhiyun battery->zero_linek = 600;
2590*4882a593Smuzhiyun else
2591*4882a593Smuzhiyun battery->zero_linek = 800;
2592*4882a593Smuzhiyun DBG("ZERO-new: zero_linek adjust step1...\n");
2593*4882a593Smuzhiyun /* control zero mode beginning enter */
2594*4882a593Smuzhiyun } else if ((battery->zero_linek > 1800) &&
2595*4882a593Smuzhiyun (battery->dsoc / 1000 > 70)) {
2596*4882a593Smuzhiyun battery->zero_linek = 1800;
2597*4882a593Smuzhiyun DBG("ZERO-new: zero_linek adjust step2...\n");
2598*4882a593Smuzhiyun /* dsoc close to xsoc: it must reserve power */
2599*4882a593Smuzhiyun } else if ((battery->zero_linek > 1000) &&
2600*4882a593Smuzhiyun (battery->zero_linek < 1200)) {
2601*4882a593Smuzhiyun battery->zero_linek = 1200;
2602*4882a593Smuzhiyun DBG("ZERO-new: zero_linek adjust step3...\n");
2603*4882a593Smuzhiyun /* dsoc[5~15], dsoc < xsoc */
2604*4882a593Smuzhiyun } else if ((battery->dsoc / 1000 <= 15 && battery->dsoc > 5) &&
2605*4882a593Smuzhiyun (battery->zero_linek <= 1200)) {
2606*4882a593Smuzhiyun /* slow down */
2607*4882a593Smuzhiyun if ((xsoc - battery->dsoc / 1000) >= min_gap_xsoc)
2608*4882a593Smuzhiyun battery->zero_linek = 800;
2609*4882a593Smuzhiyun /* reserve power */
2610*4882a593Smuzhiyun else
2611*4882a593Smuzhiyun battery->zero_linek = 1200;
2612*4882a593Smuzhiyun DBG("ZERO-new: zero_linek adjust step4...\n");
2613*4882a593Smuzhiyun /* dsoc[5, 100], dsoc < xsoc */
2614*4882a593Smuzhiyun } else if ((battery->zero_linek < 1000) &&
2615*4882a593Smuzhiyun (battery->dsoc / 1000 >= 5)) {
2616*4882a593Smuzhiyun if ((xsoc - battery->dsoc / 1000) < min_gap_xsoc) {
2617*4882a593Smuzhiyun /* reserve power */
2618*4882a593Smuzhiyun battery->zero_linek = 1200;
2619*4882a593Smuzhiyun } else {
2620*4882a593Smuzhiyun if (abs(battery->current_avg) > 500)/* heavy */
2621*4882a593Smuzhiyun battery->zero_linek = 900;
2622*4882a593Smuzhiyun else
2623*4882a593Smuzhiyun battery->zero_linek = 1000;
2624*4882a593Smuzhiyun }
2625*4882a593Smuzhiyun DBG("ZERO-new: zero_linek adjust step5...\n");
2626*4882a593Smuzhiyun /* dsoc[0~5], dsoc < xsoc */
2627*4882a593Smuzhiyun } else if ((battery->zero_linek < 1000) &&
2628*4882a593Smuzhiyun (battery->dsoc / 1000 <= 5)) {
2629*4882a593Smuzhiyun if ((xsoc - battery->dsoc / 1000) <= 3)
2630*4882a593Smuzhiyun battery->zero_linek = 1200;
2631*4882a593Smuzhiyun else
2632*4882a593Smuzhiyun battery->zero_linek = 800;
2633*4882a593Smuzhiyun DBG("ZERO-new: zero_linek adjust step6...\n");
2634*4882a593Smuzhiyun }
2635*4882a593Smuzhiyun } else {
2636*4882a593Smuzhiyun /* xsoc < 0 */
2637*4882a593Smuzhiyun battery->zero_linek = 1000;
2638*4882a593Smuzhiyun if (!battery->zero_drop_sec)
2639*4882a593Smuzhiyun battery->zero_drop_sec = get_boot_sec();
2640*4882a593Smuzhiyun if (base2sec(battery->zero_drop_sec) >= WAIT_DSOC_DROP_SEC) {
2641*4882a593Smuzhiyun DBG("ZERO0: t=%lu\n", base2sec(battery->zero_drop_sec));
2642*4882a593Smuzhiyun battery->zero_drop_sec = 0;
2643*4882a593Smuzhiyun battery->dsoc -= 1000;
2644*4882a593Smuzhiyun if (battery->dsoc < 0)
2645*4882a593Smuzhiyun battery->dsoc = 0;
2646*4882a593Smuzhiyun battery->zero_dsoc = battery->dsoc;
2647*4882a593Smuzhiyun }
2648*4882a593Smuzhiyun }
2649*4882a593Smuzhiyun
2650*4882a593Smuzhiyun if (voltage_avg < pwroff_vol - 70) {
2651*4882a593Smuzhiyun if (!battery->shtd_drop_sec)
2652*4882a593Smuzhiyun battery->shtd_drop_sec = get_boot_sec();
2653*4882a593Smuzhiyun if (base2sec(battery->shtd_drop_sec) > WAIT_SHTD_DROP_SEC) {
2654*4882a593Smuzhiyun DBG("voltage extreme low...soc:%d->0\n", battery->dsoc);
2655*4882a593Smuzhiyun battery->shtd_drop_sec = 0;
2656*4882a593Smuzhiyun battery->dsoc = 0;
2657*4882a593Smuzhiyun }
2658*4882a593Smuzhiyun } else {
2659*4882a593Smuzhiyun battery->shtd_drop_sec = 0;
2660*4882a593Smuzhiyun }
2661*4882a593Smuzhiyun
2662*4882a593Smuzhiyun DBG("Zero: zero_linek = %d\n", battery->zero_linek);
2663*4882a593Smuzhiyun }
2664*4882a593Smuzhiyun
rk817_bat_zero_algo_prepare(struct rk817_battery_device * battery)2665*4882a593Smuzhiyun static void rk817_bat_zero_algo_prepare(struct rk817_battery_device *battery)
2666*4882a593Smuzhiyun {
2667*4882a593Smuzhiyun int tmp_dsoc;
2668*4882a593Smuzhiyun
2669*4882a593Smuzhiyun tmp_dsoc = battery->zero_dsoc / 1000;
2670*4882a593Smuzhiyun
2671*4882a593Smuzhiyun if (tmp_dsoc != battery->smooth_soc / 1000)
2672*4882a593Smuzhiyun battery->zero_dsoc = battery->smooth_soc;
2673*4882a593Smuzhiyun
2674*4882a593Smuzhiyun DBG("zero_smooth: zero_dsoc = %d\n", battery->zero_dsoc);
2675*4882a593Smuzhiyun
2676*4882a593Smuzhiyun rk817_bat_calc_zero_linek(battery);
2677*4882a593Smuzhiyun }
2678*4882a593Smuzhiyun
rk817_bat_calc_zero_algorithm(struct rk817_battery_device * battery)2679*4882a593Smuzhiyun static void rk817_bat_calc_zero_algorithm(struct rk817_battery_device *battery)
2680*4882a593Smuzhiyun {
2681*4882a593Smuzhiyun int tmp_soc;
2682*4882a593Smuzhiyun
2683*4882a593Smuzhiyun tmp_soc = battery->zero_dsoc / 1000;
2684*4882a593Smuzhiyun
2685*4882a593Smuzhiyun if (tmp_soc == battery->dsoc / 1000)
2686*4882a593Smuzhiyun return;
2687*4882a593Smuzhiyun
2688*4882a593Smuzhiyun if (battery->zero_dsoc > battery->dsoc)
2689*4882a593Smuzhiyun return;
2690*4882a593Smuzhiyun
2691*4882a593Smuzhiyun if (battery->zero_dsoc < battery->dsoc - 1000)
2692*4882a593Smuzhiyun battery->dsoc -= 1000;
2693*4882a593Smuzhiyun else
2694*4882a593Smuzhiyun battery->dsoc = battery->zero_dsoc;
2695*4882a593Smuzhiyun }
2696*4882a593Smuzhiyun
rk817_bat_zero_algorithm(struct rk817_battery_device * battery)2697*4882a593Smuzhiyun static void rk817_bat_zero_algorithm(struct rk817_battery_device *battery)
2698*4882a593Smuzhiyun {
2699*4882a593Smuzhiyun int delta_cap = 0, delta_soc = 0;
2700*4882a593Smuzhiyun
2701*4882a593Smuzhiyun battery->zero_timeout_cnt++;
2702*4882a593Smuzhiyun delta_cap = battery->zero_remain_cap - battery->remain_cap;
2703*4882a593Smuzhiyun delta_soc = battery->zero_linek * delta_cap / DIV(battery->fcc) / 10;
2704*4882a593Smuzhiyun
2705*4882a593Smuzhiyun DBG("zero algorithm start\n");
2706*4882a593Smuzhiyun DBG("DEAD: dead_voltage: %d\n"
2707*4882a593Smuzhiyun "dead_soc: %d\n"
2708*4882a593Smuzhiyun "dead_cap: %d\n"
2709*4882a593Smuzhiyun "powoff_vol: %d\n",
2710*4882a593Smuzhiyun battery->zero_dead_voltage,
2711*4882a593Smuzhiyun battery->zero_dead_soc,
2712*4882a593Smuzhiyun battery->zero_dead_cap,
2713*4882a593Smuzhiyun battery->pdata->pwroff_vol);
2714*4882a593Smuzhiyun DBG("DEAD: bat_voltage: %d\n"
2715*4882a593Smuzhiyun "bat_current: %d\n"
2716*4882a593Smuzhiyun "batvol_to_ocv: %d\n"
2717*4882a593Smuzhiyun "batocv_to_soc: %d\n"
2718*4882a593Smuzhiyun "batocv_to_cap: %d\n",
2719*4882a593Smuzhiyun battery->zero_voltage_avg,
2720*4882a593Smuzhiyun battery->zero_current_avg,
2721*4882a593Smuzhiyun battery->zero_batvol_to_ocv,
2722*4882a593Smuzhiyun battery->zero_batocv_to_soc,
2723*4882a593Smuzhiyun battery->zero_batocv_to_cap);
2724*4882a593Smuzhiyun DBG("DEAD: Xsoc: %d, zero_reserve_dsoc: %d\n",
2725*4882a593Smuzhiyun battery->zero_xsoc, battery->pdata->zero_reserve_dsoc);
2726*4882a593Smuzhiyun DBG("CAP: zero_remain_cap = %d, remain_cap = %d\n",
2727*4882a593Smuzhiyun battery->zero_remain_cap, battery->remain_cap);
2728*4882a593Smuzhiyun DBG("Zero: zero_delta_cap = %d, zero_link = %d, delta_soc = %d\n",
2729*4882a593Smuzhiyun delta_cap, battery->zero_linek, delta_soc);
2730*4882a593Smuzhiyun DBG("zero algorithm end\n");
2731*4882a593Smuzhiyun
2732*4882a593Smuzhiyun if ((delta_soc >= MIN_ZERO_DSOC_ACCURACY) ||
2733*4882a593Smuzhiyun (battery->zero_timeout_cnt > MIN_ZERO_OVERCNT) ||
2734*4882a593Smuzhiyun (battery->zero_linek == 0)) {
2735*4882a593Smuzhiyun DBG("ZERO1:--------- enter calc -----------\n");
2736*4882a593Smuzhiyun battery->zero_timeout_cnt = 0;
2737*4882a593Smuzhiyun battery->zero_dsoc -= delta_soc;
2738*4882a593Smuzhiyun rk817_bat_calc_zero_algorithm(battery);
2739*4882a593Smuzhiyun DBG("Zero: dsoc: %d\n", battery->dsoc);
2740*4882a593Smuzhiyun rk817_bat_calc_zero_linek(battery);
2741*4882a593Smuzhiyun }
2742*4882a593Smuzhiyun
2743*4882a593Smuzhiyun if ((battery->rsoc / 1000 < 1) &&
2744*4882a593Smuzhiyun (battery->zero_batocv_to_cap > battery->fcc / 100)) {
2745*4882a593Smuzhiyun DBG("ZERO2:---------check step1 -----------\n");
2746*4882a593Smuzhiyun rk817_bat_init_coulomb_cap(battery,
2747*4882a593Smuzhiyun battery->zero_batocv_to_cap);
2748*4882a593Smuzhiyun rk817_bat_calc_zero_linek(battery);
2749*4882a593Smuzhiyun }
2750*4882a593Smuzhiyun }
2751*4882a593Smuzhiyun
rk817_bat_finish_algorithm(struct rk817_battery_device * battery)2752*4882a593Smuzhiyun static void rk817_bat_finish_algorithm(struct rk817_battery_device *battery)
2753*4882a593Smuzhiyun {
2754*4882a593Smuzhiyun unsigned long finish_sec, soc_sec;
2755*4882a593Smuzhiyun int plus_soc, finish_current, rest = 0;
2756*4882a593Smuzhiyun
2757*4882a593Smuzhiyun /* rsoc */
2758*4882a593Smuzhiyun if ((battery->remain_cap != battery->fcc) &&
2759*4882a593Smuzhiyun (get_charge_status(battery) == CHARGE_FINISH)) {
2760*4882a593Smuzhiyun battery->age_adjust_cap +=
2761*4882a593Smuzhiyun (battery->fcc * 1000 - battery->remain_cap);
2762*4882a593Smuzhiyun rk817_bat_init_coulomb_cap(battery, battery->fcc);
2763*4882a593Smuzhiyun rk817_bat_get_capacity_mah(battery);
2764*4882a593Smuzhiyun }
2765*4882a593Smuzhiyun
2766*4882a593Smuzhiyun /* dsoc */
2767*4882a593Smuzhiyun if (battery->dsoc < 100 * 1000) {
2768*4882a593Smuzhiyun if (!battery->finish_base)
2769*4882a593Smuzhiyun battery->finish_base = get_boot_sec();
2770*4882a593Smuzhiyun
2771*4882a593Smuzhiyun finish_current = (battery->rsoc - battery->dsoc) > FINISH_MAX_SOC_DELAY ?
2772*4882a593Smuzhiyun FINISH_CHRG_CUR2 : FINISH_CHRG_CUR1;
2773*4882a593Smuzhiyun finish_sec = base2sec(battery->finish_base);
2774*4882a593Smuzhiyun
2775*4882a593Smuzhiyun soc_sec = battery->fcc * 3600 / 100 / DIV(finish_current);
2776*4882a593Smuzhiyun plus_soc = finish_sec / DIV(soc_sec);
2777*4882a593Smuzhiyun if (finish_sec > soc_sec) {
2778*4882a593Smuzhiyun rest = finish_sec % soc_sec;
2779*4882a593Smuzhiyun battery->dsoc += plus_soc * 1000;
2780*4882a593Smuzhiyun battery->finish_base = get_boot_sec();
2781*4882a593Smuzhiyun if (battery->finish_base > rest)
2782*4882a593Smuzhiyun battery->finish_base = get_boot_sec() - rest;
2783*4882a593Smuzhiyun }
2784*4882a593Smuzhiyun DBG("CHARGE_FINISH:dsoc<100,dsoc=%d\n"
2785*4882a593Smuzhiyun "soc_time=%lu, sec_finish=%lu, plus_soc=%d, rest=%d\n",
2786*4882a593Smuzhiyun battery->dsoc, soc_sec, finish_sec, plus_soc, rest);
2787*4882a593Smuzhiyun DBG("battery->age_adjust_cap = %d\n", battery->age_adjust_cap);
2788*4882a593Smuzhiyun }
2789*4882a593Smuzhiyun }
2790*4882a593Smuzhiyun
rk817_bat_display_smooth(struct rk817_battery_device * battery)2791*4882a593Smuzhiyun static void rk817_bat_display_smooth(struct rk817_battery_device *battery)
2792*4882a593Smuzhiyun {
2793*4882a593Smuzhiyun /* discharge: reinit "zero & smooth" algorithm to avoid handling dsoc */
2794*4882a593Smuzhiyun if (battery->s2r && !battery->sleep_chrg_online) {
2795*4882a593Smuzhiyun DBG("s2r: discharge, reset algorithm...\n");
2796*4882a593Smuzhiyun battery->s2r = false;
2797*4882a593Smuzhiyun rk817_bat_zero_algo_prepare(battery);
2798*4882a593Smuzhiyun rk817_bat_smooth_algo_prepare(battery);
2799*4882a593Smuzhiyun return;
2800*4882a593Smuzhiyun }
2801*4882a593Smuzhiyun
2802*4882a593Smuzhiyun if (battery->work_mode == MODE_FINISH) {
2803*4882a593Smuzhiyun DBG("step1: charge finish...\n");
2804*4882a593Smuzhiyun rk817_bat_finish_algorithm(battery);
2805*4882a593Smuzhiyun
2806*4882a593Smuzhiyun if ((get_charge_status(battery) != CHARGE_FINISH) &&
2807*4882a593Smuzhiyun !rk817_bat_fake_finish_mode(battery)) {
2808*4882a593Smuzhiyun if ((battery->current_avg < 0) &&
2809*4882a593Smuzhiyun (battery->voltage_avg < battery->pdata->zero_algorithm_vol)) {
2810*4882a593Smuzhiyun DBG("step1: change to zero mode...\n");
2811*4882a593Smuzhiyun rk817_bat_zero_algo_prepare(battery);
2812*4882a593Smuzhiyun battery->work_mode = MODE_ZERO;
2813*4882a593Smuzhiyun } else {
2814*4882a593Smuzhiyun DBG("step1: change to smooth mode...\n");
2815*4882a593Smuzhiyun rk817_bat_smooth_algo_prepare(battery);
2816*4882a593Smuzhiyun battery->work_mode = MODE_SMOOTH;
2817*4882a593Smuzhiyun }
2818*4882a593Smuzhiyun }
2819*4882a593Smuzhiyun } else if (battery->work_mode == MODE_ZERO) {
2820*4882a593Smuzhiyun DBG("step2: zero algorithm...\n");
2821*4882a593Smuzhiyun rk817_bat_zero_algorithm(battery);
2822*4882a593Smuzhiyun if ((battery->voltage_avg >=
2823*4882a593Smuzhiyun battery->pdata->zero_algorithm_vol + 50) ||
2824*4882a593Smuzhiyun (battery->current_avg >= 0)) {
2825*4882a593Smuzhiyun DBG("step2: change to smooth mode...\n");
2826*4882a593Smuzhiyun rk817_bat_smooth_algo_prepare(battery);
2827*4882a593Smuzhiyun battery->work_mode = MODE_SMOOTH;
2828*4882a593Smuzhiyun } else if ((get_charge_status(battery) == CHARGE_FINISH) ||
2829*4882a593Smuzhiyun rk817_bat_fake_finish_mode(battery)) {
2830*4882a593Smuzhiyun DBG("step2: change to finish mode...\n");
2831*4882a593Smuzhiyun rk817_bat_finish_algo_prepare(battery);
2832*4882a593Smuzhiyun battery->work_mode = MODE_FINISH;
2833*4882a593Smuzhiyun }
2834*4882a593Smuzhiyun } else {
2835*4882a593Smuzhiyun DBG("step3: smooth algorithm...\n");
2836*4882a593Smuzhiyun rk817_bat_smooth_algorithm(battery);
2837*4882a593Smuzhiyun if ((battery->current_avg < 0) &&
2838*4882a593Smuzhiyun (battery->voltage_avg <
2839*4882a593Smuzhiyun battery->pdata->zero_algorithm_vol)) {
2840*4882a593Smuzhiyun DBG("step3: change to zero mode...\n");
2841*4882a593Smuzhiyun rk817_bat_zero_algo_prepare(battery);
2842*4882a593Smuzhiyun battery->work_mode = MODE_ZERO;
2843*4882a593Smuzhiyun } else if ((get_charge_status(battery) == CHARGE_FINISH) ||
2844*4882a593Smuzhiyun rk817_bat_fake_finish_mode(battery)) {
2845*4882a593Smuzhiyun DBG("step3: change to finish mode...\n");
2846*4882a593Smuzhiyun rk817_bat_finish_algo_prepare(battery);
2847*4882a593Smuzhiyun battery->work_mode = MODE_FINISH;
2848*4882a593Smuzhiyun }
2849*4882a593Smuzhiyun }
2850*4882a593Smuzhiyun }
2851*4882a593Smuzhiyun
rk817_bat_output_info(struct rk817_battery_device * battery)2852*4882a593Smuzhiyun static void rk817_bat_output_info(struct rk817_battery_device *battery)
2853*4882a593Smuzhiyun {
2854*4882a593Smuzhiyun DBG("info start:\n");
2855*4882a593Smuzhiyun DBG("info: voltage_k = %d\n", battery->voltage_k);
2856*4882a593Smuzhiyun DBG("info: voltage_b = %d\n", battery->voltage_b);
2857*4882a593Smuzhiyun DBG("info: voltage = %d\n", battery->voltage_avg);
2858*4882a593Smuzhiyun DBG("info: voltage_sys = %d\n", battery->voltage_sys);
2859*4882a593Smuzhiyun DBG("info: current = %d\n", battery->current_avg);
2860*4882a593Smuzhiyun
2861*4882a593Smuzhiyun DBG("info: FCC = %d\n", battery->fcc);
2862*4882a593Smuzhiyun DBG("info: remain_cap = %d\n", battery->remain_cap);
2863*4882a593Smuzhiyun DBG("info: sm_remain_cap = %d\n", battery->sm_remain_cap);
2864*4882a593Smuzhiyun DBG("info: sm_link = %d\n", battery->sm_linek);
2865*4882a593Smuzhiyun DBG("info: smooth_soc = %d\n", battery->smooth_soc);
2866*4882a593Smuzhiyun
2867*4882a593Smuzhiyun DBG("info: zero_remain_cap = %d\n", battery->zero_remain_cap);
2868*4882a593Smuzhiyun DBG("info: zero_link = %d\n", battery->zero_linek);
2869*4882a593Smuzhiyun DBG("info: zero_dsoc = %d\n", battery->zero_dsoc);
2870*4882a593Smuzhiyun
2871*4882a593Smuzhiyun DBG("info: remain_cap = %d\n", battery->remain_cap);
2872*4882a593Smuzhiyun DBG("info: dsoc = %d, dsoc/1000 = %d\n",
2873*4882a593Smuzhiyun battery->dsoc, battery->dsoc / 1000);
2874*4882a593Smuzhiyun DBG("info: rsoc = %d\n", battery->rsoc);
2875*4882a593Smuzhiyun DBG("info END.\n");
2876*4882a593Smuzhiyun }
2877*4882a593Smuzhiyun
rk817_battery_work(struct work_struct * work)2878*4882a593Smuzhiyun static void rk817_battery_work(struct work_struct *work)
2879*4882a593Smuzhiyun {
2880*4882a593Smuzhiyun struct rk817_battery_device *battery =
2881*4882a593Smuzhiyun container_of(work,
2882*4882a593Smuzhiyun struct rk817_battery_device,
2883*4882a593Smuzhiyun bat_delay_work.work);
2884*4882a593Smuzhiyun
2885*4882a593Smuzhiyun rk817_bat_update_info(battery);
2886*4882a593Smuzhiyun rk817_bat_lowpwr_check(battery);
2887*4882a593Smuzhiyun rk817_bat_display_smooth(battery);
2888*4882a593Smuzhiyun rk817_bat_power_supply_changed(battery);
2889*4882a593Smuzhiyun rk817_bat_save_data(battery);
2890*4882a593Smuzhiyun rk817_bat_output_info(battery);
2891*4882a593Smuzhiyun
2892*4882a593Smuzhiyun if (rk817_bat_field_read(battery, CUR_CALIB_UPD)) {
2893*4882a593Smuzhiyun rk817_bat_current_calibration(battery);
2894*4882a593Smuzhiyun rk817_bat_init_voltage_kb(battery);
2895*4882a593Smuzhiyun rk817_bat_field_write(battery, CUR_CALIB_UPD, 0x01);
2896*4882a593Smuzhiyun }
2897*4882a593Smuzhiyun
2898*4882a593Smuzhiyun queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work,
2899*4882a593Smuzhiyun msecs_to_jiffies(battery->monitor_ms));
2900*4882a593Smuzhiyun }
2901*4882a593Smuzhiyun
rk809_plug_in_isr(int irq,void * cg)2902*4882a593Smuzhiyun static irqreturn_t rk809_plug_in_isr(int irq, void *cg)
2903*4882a593Smuzhiyun {
2904*4882a593Smuzhiyun struct rk817_battery_device *battery;
2905*4882a593Smuzhiyun
2906*4882a593Smuzhiyun battery = (struct rk817_battery_device *)cg;
2907*4882a593Smuzhiyun battery->plugin_trigger = 1;
2908*4882a593Smuzhiyun battery->plugout_trigger = 0;
2909*4882a593Smuzhiyun power_supply_changed(battery->bat);
2910*4882a593Smuzhiyun if (battery->is_register_chg_psy)
2911*4882a593Smuzhiyun power_supply_changed(battery->chg_psy);
2912*4882a593Smuzhiyun
2913*4882a593Smuzhiyun return IRQ_HANDLED;
2914*4882a593Smuzhiyun }
2915*4882a593Smuzhiyun
rk809_plug_out_isr(int irq,void * cg)2916*4882a593Smuzhiyun static irqreturn_t rk809_plug_out_isr(int irq, void *cg)
2917*4882a593Smuzhiyun {
2918*4882a593Smuzhiyun struct rk817_battery_device *battery;
2919*4882a593Smuzhiyun
2920*4882a593Smuzhiyun battery = (struct rk817_battery_device *)cg;
2921*4882a593Smuzhiyun battery->plugin_trigger = 0;
2922*4882a593Smuzhiyun battery->plugout_trigger = 1;
2923*4882a593Smuzhiyun power_supply_changed(battery->bat);
2924*4882a593Smuzhiyun if (battery->is_register_chg_psy)
2925*4882a593Smuzhiyun power_supply_changed(battery->chg_psy);
2926*4882a593Smuzhiyun
2927*4882a593Smuzhiyun return IRQ_HANDLED;
2928*4882a593Smuzhiyun }
2929*4882a593Smuzhiyun
rk809_charge_init_irqs(struct rk817_battery_device * battery)2930*4882a593Smuzhiyun static int rk809_charge_init_irqs(struct rk817_battery_device *battery)
2931*4882a593Smuzhiyun {
2932*4882a593Smuzhiyun struct rk808 *rk817 = battery->rk817;
2933*4882a593Smuzhiyun struct platform_device *pdev = battery->pdev;
2934*4882a593Smuzhiyun int ret, plug_in_irq, plug_out_irq;
2935*4882a593Smuzhiyun
2936*4882a593Smuzhiyun battery->plugin_trigger = 0;
2937*4882a593Smuzhiyun battery->plugout_trigger = 0;
2938*4882a593Smuzhiyun
2939*4882a593Smuzhiyun plug_in_irq = regmap_irq_get_virq(rk817->irq_data, RK817_IRQ_PLUG_IN);
2940*4882a593Smuzhiyun if (plug_in_irq < 0) {
2941*4882a593Smuzhiyun dev_err(battery->dev, "plug_in_irq request failed!\n");
2942*4882a593Smuzhiyun return plug_in_irq;
2943*4882a593Smuzhiyun }
2944*4882a593Smuzhiyun
2945*4882a593Smuzhiyun plug_out_irq = regmap_irq_get_virq(rk817->irq_data, RK817_IRQ_PLUG_OUT);
2946*4882a593Smuzhiyun if (plug_out_irq < 0) {
2947*4882a593Smuzhiyun dev_err(battery->dev, "plug_out_irq request failed!\n");
2948*4882a593Smuzhiyun return plug_out_irq;
2949*4882a593Smuzhiyun }
2950*4882a593Smuzhiyun
2951*4882a593Smuzhiyun ret = devm_request_threaded_irq(battery->dev, plug_in_irq, NULL,
2952*4882a593Smuzhiyun rk809_plug_in_isr,
2953*4882a593Smuzhiyun IRQF_TRIGGER_RISING | IRQF_ONESHOT,
2954*4882a593Smuzhiyun "rk817_plug_in", battery);
2955*4882a593Smuzhiyun if (ret) {
2956*4882a593Smuzhiyun dev_err(&pdev->dev, "plug_in_irq request failed!\n");
2957*4882a593Smuzhiyun return ret;
2958*4882a593Smuzhiyun }
2959*4882a593Smuzhiyun
2960*4882a593Smuzhiyun ret = devm_request_threaded_irq(battery->dev, plug_out_irq, NULL,
2961*4882a593Smuzhiyun rk809_plug_out_isr,
2962*4882a593Smuzhiyun IRQF_TRIGGER_RISING | IRQF_ONESHOT,
2963*4882a593Smuzhiyun "rk817_plug_out", battery);
2964*4882a593Smuzhiyun if (ret) {
2965*4882a593Smuzhiyun dev_err(&pdev->dev, "plug_out_irq request failed!\n");
2966*4882a593Smuzhiyun return ret;
2967*4882a593Smuzhiyun }
2968*4882a593Smuzhiyun
2969*4882a593Smuzhiyun if (rk817_bat_field_read(battery, PLUG_IN_STS)) {
2970*4882a593Smuzhiyun battery->plugin_trigger = 1;
2971*4882a593Smuzhiyun battery->plugout_trigger = 0;
2972*4882a593Smuzhiyun }
2973*4882a593Smuzhiyun
2974*4882a593Smuzhiyun return 0;
2975*4882a593Smuzhiyun }
2976*4882a593Smuzhiyun
2977*4882a593Smuzhiyun #ifdef CONFIG_OF
2978*4882a593Smuzhiyun static const struct of_device_id rk817_bat_of_match[] = {
2979*4882a593Smuzhiyun { .compatible = "rk817,battery", },
2980*4882a593Smuzhiyun { },
2981*4882a593Smuzhiyun };
2982*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk817_bat_of_match);
2983*4882a593Smuzhiyun #else
2984*4882a593Smuzhiyun static const struct of_device_id rk817_bat_of_match[] = {
2985*4882a593Smuzhiyun { },
2986*4882a593Smuzhiyun };
2987*4882a593Smuzhiyun #endif
2988*4882a593Smuzhiyun
rk817_battery_probe(struct platform_device * pdev)2989*4882a593Smuzhiyun static int rk817_battery_probe(struct platform_device *pdev)
2990*4882a593Smuzhiyun {
2991*4882a593Smuzhiyun const struct of_device_id *of_id =
2992*4882a593Smuzhiyun of_match_device(rk817_bat_of_match, &pdev->dev);
2993*4882a593Smuzhiyun struct rk817_battery_device *battery;
2994*4882a593Smuzhiyun struct rk808 *rk817 = dev_get_drvdata(pdev->dev.parent);
2995*4882a593Smuzhiyun struct i2c_client *client = rk817->i2c;
2996*4882a593Smuzhiyun int i, ret;
2997*4882a593Smuzhiyun
2998*4882a593Smuzhiyun if (!of_id) {
2999*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to find matching dt id\n");
3000*4882a593Smuzhiyun return -ENODEV;
3001*4882a593Smuzhiyun }
3002*4882a593Smuzhiyun
3003*4882a593Smuzhiyun battery = devm_kzalloc(&client->dev, sizeof(*battery), GFP_KERNEL);
3004*4882a593Smuzhiyun if (!battery)
3005*4882a593Smuzhiyun return -EINVAL;
3006*4882a593Smuzhiyun
3007*4882a593Smuzhiyun battery->rk817 = rk817;
3008*4882a593Smuzhiyun battery->client = client;
3009*4882a593Smuzhiyun battery->dev = &pdev->dev;
3010*4882a593Smuzhiyun platform_set_drvdata(pdev, battery);
3011*4882a593Smuzhiyun battery->chip_id = rk817->variant;
3012*4882a593Smuzhiyun
3013*4882a593Smuzhiyun battery->regmap = rk817->regmap;
3014*4882a593Smuzhiyun if (IS_ERR(battery->regmap)) {
3015*4882a593Smuzhiyun dev_err(battery->dev, "Failed to initialize regmap\n");
3016*4882a593Smuzhiyun return -EINVAL;
3017*4882a593Smuzhiyun }
3018*4882a593Smuzhiyun
3019*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(rk817_battery_reg_fields); i++) {
3020*4882a593Smuzhiyun const struct reg_field *reg_fields = rk817_battery_reg_fields;
3021*4882a593Smuzhiyun
3022*4882a593Smuzhiyun battery->rmap_fields[i] =
3023*4882a593Smuzhiyun devm_regmap_field_alloc(battery->dev,
3024*4882a593Smuzhiyun battery->regmap,
3025*4882a593Smuzhiyun reg_fields[i]);
3026*4882a593Smuzhiyun if (IS_ERR(battery->rmap_fields[i])) {
3027*4882a593Smuzhiyun dev_err(battery->dev, "cannot allocate regmap field\n");
3028*4882a593Smuzhiyun return PTR_ERR(battery->rmap_fields[i]);
3029*4882a593Smuzhiyun }
3030*4882a593Smuzhiyun }
3031*4882a593Smuzhiyun
3032*4882a593Smuzhiyun ret = rk817_bat_parse_dt(battery);
3033*4882a593Smuzhiyun if (ret < 0) {
3034*4882a593Smuzhiyun dev_err(battery->dev, "battery parse dt failed!\n");
3035*4882a593Smuzhiyun return ret;
3036*4882a593Smuzhiyun }
3037*4882a593Smuzhiyun
3038*4882a593Smuzhiyun rk817_bat_init_info(battery);
3039*4882a593Smuzhiyun rk817_bat_init_fg(battery);
3040*4882a593Smuzhiyun
3041*4882a593Smuzhiyun rk817_battery_debug_info(battery);
3042*4882a593Smuzhiyun rk817_bat_update_info(battery);
3043*4882a593Smuzhiyun
3044*4882a593Smuzhiyun rk817_bat_output_info(battery);
3045*4882a593Smuzhiyun battery->bat_monitor_wq = alloc_ordered_workqueue("%s",
3046*4882a593Smuzhiyun WQ_MEM_RECLAIM | WQ_FREEZABLE, "rk817-bat-monitor-wq");
3047*4882a593Smuzhiyun INIT_DELAYED_WORK(&battery->bat_delay_work, rk817_battery_work);
3048*4882a593Smuzhiyun queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work,
3049*4882a593Smuzhiyun msecs_to_jiffies(TIMER_MS_COUNTS * 5));
3050*4882a593Smuzhiyun INIT_WORK(&battery->resume_work, rk817_bat_resume_work);
3051*4882a593Smuzhiyun
3052*4882a593Smuzhiyun ret = rk817_bat_init_power_supply(battery);
3053*4882a593Smuzhiyun if (ret) {
3054*4882a593Smuzhiyun dev_err(battery->dev, "rk817 power supply register failed!\n");
3055*4882a593Smuzhiyun return ret;
3056*4882a593Smuzhiyun }
3057*4882a593Smuzhiyun if (battery->is_register_chg_psy) {
3058*4882a593Smuzhiyun ret = rk809_chg_init_power_supply(battery);
3059*4882a593Smuzhiyun if (ret) {
3060*4882a593Smuzhiyun dev_err(battery->dev, "rk809 chg psy init failed!\n");
3061*4882a593Smuzhiyun return ret;
3062*4882a593Smuzhiyun }
3063*4882a593Smuzhiyun }
3064*4882a593Smuzhiyun
3065*4882a593Smuzhiyun if (battery->chip_id == RK809_ID)
3066*4882a593Smuzhiyun rk809_charge_init_irqs(battery);
3067*4882a593Smuzhiyun
3068*4882a593Smuzhiyun wake_lock_init(&battery->wake_lock, WAKE_LOCK_SUSPEND,
3069*4882a593Smuzhiyun "rk817_bat_lock");
3070*4882a593Smuzhiyun
3071*4882a593Smuzhiyun DBG("name: 0x%x", rk817_bat_field_read(battery, CHIP_NAME_H));
3072*4882a593Smuzhiyun DBG("%x\n", rk817_bat_field_read(battery, CHIP_NAME_L));
3073*4882a593Smuzhiyun DBG("driver version %s\n", DRIVER_VERSION);
3074*4882a593Smuzhiyun
3075*4882a593Smuzhiyun return 0;
3076*4882a593Smuzhiyun }
3077*4882a593Smuzhiyun
rk817_battery_shutdown(struct platform_device * dev)3078*4882a593Smuzhiyun static void rk817_battery_shutdown(struct platform_device *dev)
3079*4882a593Smuzhiyun {
3080*4882a593Smuzhiyun }
3081*4882a593Smuzhiyun
rk817_get_rtc_sec(void)3082*4882a593Smuzhiyun static time64_t rk817_get_rtc_sec(void)
3083*4882a593Smuzhiyun {
3084*4882a593Smuzhiyun int err;
3085*4882a593Smuzhiyun struct rtc_time tm;
3086*4882a593Smuzhiyun struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
3087*4882a593Smuzhiyun
3088*4882a593Smuzhiyun err = rtc_read_time(rtc, &tm);
3089*4882a593Smuzhiyun if (err) {
3090*4882a593Smuzhiyun dev_err(rtc->dev.parent, "read hardware clk failed\n");
3091*4882a593Smuzhiyun return 0;
3092*4882a593Smuzhiyun }
3093*4882a593Smuzhiyun
3094*4882a593Smuzhiyun err = rtc_valid_tm(&tm);
3095*4882a593Smuzhiyun if (err) {
3096*4882a593Smuzhiyun dev_err(rtc->dev.parent, "invalid date time\n");
3097*4882a593Smuzhiyun return 0;
3098*4882a593Smuzhiyun }
3099*4882a593Smuzhiyun
3100*4882a593Smuzhiyun return rtc_tm_to_time64(&tm);
3101*4882a593Smuzhiyun }
3102*4882a593Smuzhiyun
3103*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
rk817_bat_pm_suspend(struct device * dev)3104*4882a593Smuzhiyun static int rk817_bat_pm_suspend(struct device *dev)
3105*4882a593Smuzhiyun {
3106*4882a593Smuzhiyun struct platform_device *pdev = to_platform_device(dev);
3107*4882a593Smuzhiyun struct rk817_battery_device *battery = dev_get_drvdata(&pdev->dev);
3108*4882a593Smuzhiyun
3109*4882a593Smuzhiyun cancel_delayed_work_sync(&battery->bat_delay_work);
3110*4882a593Smuzhiyun
3111*4882a593Smuzhiyun battery->s2r = false;
3112*4882a593Smuzhiyun battery->sleep_chrg_status = get_charge_status(battery);
3113*4882a593Smuzhiyun battery->current_avg = rk817_bat_get_avg_current(battery);
3114*4882a593Smuzhiyun if (battery->current_avg > 0 ||
3115*4882a593Smuzhiyun (battery->sleep_chrg_status == CC_OR_CV_CHRG) ||
3116*4882a593Smuzhiyun (battery->sleep_chrg_status == CHARGE_FINISH))
3117*4882a593Smuzhiyun battery->sleep_chrg_online = 1;
3118*4882a593Smuzhiyun else
3119*4882a593Smuzhiyun battery->sleep_chrg_online = 0;
3120*4882a593Smuzhiyun
3121*4882a593Smuzhiyun battery->remain_cap = rk817_bat_get_capacity_uah(battery);
3122*4882a593Smuzhiyun battery->rsoc = rk817_bat_get_rsoc(battery);
3123*4882a593Smuzhiyun
3124*4882a593Smuzhiyun battery->rtc_base = rk817_get_rtc_sec();
3125*4882a593Smuzhiyun rk817_bat_save_data(battery);
3126*4882a593Smuzhiyun
3127*4882a593Smuzhiyun if (battery->sleep_chrg_status != CHARGE_FINISH)
3128*4882a593Smuzhiyun battery->finish_base = get_boot_sec();
3129*4882a593Smuzhiyun
3130*4882a593Smuzhiyun if ((battery->work_mode == MODE_ZERO) &&
3131*4882a593Smuzhiyun (battery->current_avg >= 0)) {
3132*4882a593Smuzhiyun DBG("suspend: MODE_ZERO exit...\n");
3133*4882a593Smuzhiyun /* it need't do prepare for mode finish and smooth, it will
3134*4882a593Smuzhiyun * be done in display_smooth
3135*4882a593Smuzhiyun */
3136*4882a593Smuzhiyun if (battery->sleep_chrg_status == CHARGE_FINISH) {
3137*4882a593Smuzhiyun battery->work_mode = MODE_FINISH;
3138*4882a593Smuzhiyun if (!battery->finish_base)
3139*4882a593Smuzhiyun battery->finish_base = get_boot_sec();
3140*4882a593Smuzhiyun } else {
3141*4882a593Smuzhiyun battery->work_mode = MODE_SMOOTH;
3142*4882a593Smuzhiyun rk817_bat_smooth_algo_prepare(battery);
3143*4882a593Smuzhiyun }
3144*4882a593Smuzhiyun }
3145*4882a593Smuzhiyun
3146*4882a593Smuzhiyun DBG("suspend get_boot_sec: %lld\n", get_boot_sec());
3147*4882a593Smuzhiyun
3148*4882a593Smuzhiyun DBG("suspend: dl=%d rl=%d c=%d v=%d cap=%d at=%ld ch=%d\n",
3149*4882a593Smuzhiyun battery->dsoc, battery->rsoc, battery->current_avg,
3150*4882a593Smuzhiyun rk817_bat_get_battery_voltage(battery),
3151*4882a593Smuzhiyun rk817_bat_get_capacity_uah(battery),
3152*4882a593Smuzhiyun battery->sleep_dischrg_sec, battery->sleep_chrg_online);
3153*4882a593Smuzhiyun DBG("battery->sleep_chrg_status=%d\n", battery->sleep_chrg_status);
3154*4882a593Smuzhiyun
3155*4882a593Smuzhiyun return 0;
3156*4882a593Smuzhiyun }
3157*4882a593Smuzhiyun
rk817_bat_rtc_sleep_sec(struct rk817_battery_device * battery)3158*4882a593Smuzhiyun static int rk817_bat_rtc_sleep_sec(struct rk817_battery_device *battery)
3159*4882a593Smuzhiyun {
3160*4882a593Smuzhiyun int interval_sec;
3161*4882a593Smuzhiyun
3162*4882a593Smuzhiyun interval_sec = rk817_get_rtc_sec() - battery->rtc_base;
3163*4882a593Smuzhiyun
3164*4882a593Smuzhiyun return (interval_sec > 0) ? interval_sec : 0;
3165*4882a593Smuzhiyun }
3166*4882a593Smuzhiyun
rk817_bat_relife_age_flag(struct rk817_battery_device * battery)3167*4882a593Smuzhiyun static void rk817_bat_relife_age_flag(struct rk817_battery_device *battery)
3168*4882a593Smuzhiyun {
3169*4882a593Smuzhiyun u8 ocv_soc, ocv_cap, soc_level;
3170*4882a593Smuzhiyun
3171*4882a593Smuzhiyun if (battery->voltage_relax <= 0)
3172*4882a593Smuzhiyun return;
3173*4882a593Smuzhiyun
3174*4882a593Smuzhiyun ocv_soc = rk817_bat_vol_to_soc(battery, battery->voltage_relax);
3175*4882a593Smuzhiyun ocv_cap = rk817_bat_vol_to_cap(battery, battery->voltage_relax);
3176*4882a593Smuzhiyun DBG("<%s>. ocv_soc=%d, min=%lu, vol=%d\n", __func__,
3177*4882a593Smuzhiyun ocv_soc, battery->sleep_dischrg_sec / 60, battery->voltage_relax);
3178*4882a593Smuzhiyun
3179*4882a593Smuzhiyun /* sleep enough time and ocv_soc enough low */
3180*4882a593Smuzhiyun if (!battery->age_allow_update && ocv_soc <= 10) {
3181*4882a593Smuzhiyun battery->age_voltage = battery->voltage_relax;
3182*4882a593Smuzhiyun battery->age_ocv_cap = ocv_cap;
3183*4882a593Smuzhiyun battery->age_ocv_soc = ocv_soc;
3184*4882a593Smuzhiyun battery->age_adjust_cap = 0;
3185*4882a593Smuzhiyun
3186*4882a593Smuzhiyun if (ocv_soc <= 1)
3187*4882a593Smuzhiyun battery->age_level = 100;
3188*4882a593Smuzhiyun else if (ocv_soc < 5)
3189*4882a593Smuzhiyun battery->age_level = 90;
3190*4882a593Smuzhiyun else
3191*4882a593Smuzhiyun battery->age_level = 80;
3192*4882a593Smuzhiyun
3193*4882a593Smuzhiyun /*soc_level = rk818_bat_get_age_level(battery);*/
3194*4882a593Smuzhiyun soc_level = 0;
3195*4882a593Smuzhiyun if (soc_level > battery->age_level) {
3196*4882a593Smuzhiyun battery->age_allow_update = false;
3197*4882a593Smuzhiyun } else {
3198*4882a593Smuzhiyun battery->age_allow_update = true;
3199*4882a593Smuzhiyun battery->age_keep_sec = get_boot_sec();
3200*4882a593Smuzhiyun }
3201*4882a593Smuzhiyun
3202*4882a593Smuzhiyun BAT_INFO("resume: age_vol:%d, age_ocv_cap:%d, age_ocv_soc:%d, "
3203*4882a593Smuzhiyun "soc_level:%d, age_allow_update:%d, "
3204*4882a593Smuzhiyun "age_level:%d\n",
3205*4882a593Smuzhiyun battery->age_voltage, battery->age_ocv_cap,
3206*4882a593Smuzhiyun ocv_soc, soc_level,
3207*4882a593Smuzhiyun battery->age_allow_update, battery->age_level);
3208*4882a593Smuzhiyun }
3209*4882a593Smuzhiyun }
3210*4882a593Smuzhiyun
rk817_bat_init_capacity(struct rk817_battery_device * battery,u32 cap)3211*4882a593Smuzhiyun static void rk817_bat_init_capacity(struct rk817_battery_device *battery,
3212*4882a593Smuzhiyun u32 cap)
3213*4882a593Smuzhiyun {
3214*4882a593Smuzhiyun int delta_cap;
3215*4882a593Smuzhiyun
3216*4882a593Smuzhiyun delta_cap = cap - battery->remain_cap;
3217*4882a593Smuzhiyun if (!delta_cap)
3218*4882a593Smuzhiyun return;
3219*4882a593Smuzhiyun
3220*4882a593Smuzhiyun battery->age_adjust_cap += delta_cap;
3221*4882a593Smuzhiyun rk817_bat_init_coulomb_cap(battery, cap);
3222*4882a593Smuzhiyun rk817_bat_smooth_algo_prepare(battery);
3223*4882a593Smuzhiyun rk817_bat_zero_algo_prepare(battery);
3224*4882a593Smuzhiyun }
3225*4882a593Smuzhiyun
rk817_bat_relax_vol_calib(struct rk817_battery_device * battery)3226*4882a593Smuzhiyun static void rk817_bat_relax_vol_calib(struct rk817_battery_device *battery)
3227*4882a593Smuzhiyun {
3228*4882a593Smuzhiyun int soc, cap, vol;
3229*4882a593Smuzhiyun
3230*4882a593Smuzhiyun vol = battery->voltage_relax;
3231*4882a593Smuzhiyun soc = rk817_bat_vol_to_soc(battery, vol);
3232*4882a593Smuzhiyun cap = rk817_bat_vol_to_cap(battery, vol);
3233*4882a593Smuzhiyun rk817_bat_init_capacity(battery, cap);
3234*4882a593Smuzhiyun BAT_INFO("sleep ocv calib: rsoc=%d, cap=%d\n", soc, cap);
3235*4882a593Smuzhiyun }
3236*4882a593Smuzhiyun
rk817_bat_sleep_dischrg(struct rk817_battery_device * battery)3237*4882a593Smuzhiyun static int rk817_bat_sleep_dischrg(struct rk817_battery_device *battery)
3238*4882a593Smuzhiyun {
3239*4882a593Smuzhiyun bool ocv_soc_updated = false;
3240*4882a593Smuzhiyun int tgt_dsoc, gap_soc, sleep_soc = 0;
3241*4882a593Smuzhiyun int pwroff_vol = battery->pdata->pwroff_vol;
3242*4882a593Smuzhiyun unsigned long sleep_sec = battery->sleep_dischrg_sec;
3243*4882a593Smuzhiyun int sleep_cur;
3244*4882a593Smuzhiyun
3245*4882a593Smuzhiyun DBG("<%s>. enter: dsoc=%d, rsoc=%d, rv=%d, v=%d, sleep_min=%lu\n",
3246*4882a593Smuzhiyun __func__, battery->dsoc, battery->rsoc, battery->voltage_relax,
3247*4882a593Smuzhiyun battery->voltage_avg, sleep_sec / 60);
3248*4882a593Smuzhiyun
3249*4882a593Smuzhiyun if (battery->voltage_relax >= battery->voltage_avg) {
3250*4882a593Smuzhiyun rk817_bat_relax_vol_calib(battery);
3251*4882a593Smuzhiyun rk817_bat_restart_relax(battery);
3252*4882a593Smuzhiyun rk817_bat_relife_age_flag(battery);
3253*4882a593Smuzhiyun ocv_soc_updated = true;
3254*4882a593Smuzhiyun }
3255*4882a593Smuzhiyun
3256*4882a593Smuzhiyun /* handle dsoc */
3257*4882a593Smuzhiyun if (battery->dsoc <= battery->rsoc) {
3258*4882a593Smuzhiyun if (battery->pdata->low_pwr_sleep)
3259*4882a593Smuzhiyun sleep_cur = LOW_PWR_SLP_CURR_MIN;
3260*4882a593Smuzhiyun else
3261*4882a593Smuzhiyun sleep_cur = SLP_CURR_MIN;
3262*4882a593Smuzhiyun battery->sleep_sum_cap = (sleep_cur * sleep_sec / 3600);
3263*4882a593Smuzhiyun sleep_soc = battery->sleep_sum_cap * 100 / DIV(battery->fcc);
3264*4882a593Smuzhiyun tgt_dsoc = battery->dsoc - sleep_soc * 1000;
3265*4882a593Smuzhiyun if (sleep_soc > 0) {
3266*4882a593Smuzhiyun BAT_INFO("calib0: rl=%d, dl=%d, intval=%d\n",
3267*4882a593Smuzhiyun battery->rsoc, battery->dsoc, sleep_soc);
3268*4882a593Smuzhiyun if (battery->dsoc / 1000 < 5) {
3269*4882a593Smuzhiyun battery->dsoc -= 1000;
3270*4882a593Smuzhiyun } else if ((tgt_dsoc / 1000 < 5) &&
3271*4882a593Smuzhiyun (battery->dsoc / 1000 >= 5)) {
3272*4882a593Smuzhiyun if (battery->dsoc / 1000 == 5)
3273*4882a593Smuzhiyun battery->dsoc -= 1000;
3274*4882a593Smuzhiyun else
3275*4882a593Smuzhiyun battery->dsoc = 5 * 1000;
3276*4882a593Smuzhiyun } else if (tgt_dsoc / 1000 > 5) {
3277*4882a593Smuzhiyun battery->dsoc = tgt_dsoc;
3278*4882a593Smuzhiyun }
3279*4882a593Smuzhiyun }
3280*4882a593Smuzhiyun
3281*4882a593Smuzhiyun DBG("%s: dsoc<=rsoc, sum_cap=%d==>sleep_soc=%d, tgt_dsoc=%d\n",
3282*4882a593Smuzhiyun __func__, battery->sleep_sum_cap, sleep_soc, tgt_dsoc);
3283*4882a593Smuzhiyun } else {
3284*4882a593Smuzhiyun /* di->dsoc > di->rsoc */
3285*4882a593Smuzhiyun if (battery->pdata->low_pwr_sleep)
3286*4882a593Smuzhiyun sleep_cur = LOW_PWR_SLP_CURR_MAX;
3287*4882a593Smuzhiyun else
3288*4882a593Smuzhiyun sleep_cur = SLP_CURR_MAX;
3289*4882a593Smuzhiyun battery->sleep_sum_cap = (sleep_cur * sleep_sec / 3600);
3290*4882a593Smuzhiyun sleep_soc = battery->sleep_sum_cap / DIV(battery->fcc / 100);
3291*4882a593Smuzhiyun gap_soc = battery->dsoc - battery->rsoc;
3292*4882a593Smuzhiyun
3293*4882a593Smuzhiyun DBG("calib1: rsoc=%d, dsoc=%d, intval=%d\n",
3294*4882a593Smuzhiyun battery->rsoc, battery->dsoc, sleep_soc);
3295*4882a593Smuzhiyun if (gap_soc / 1000 > sleep_soc) {
3296*4882a593Smuzhiyun if ((gap_soc - 5000) > (sleep_soc * 2 * 1000))
3297*4882a593Smuzhiyun battery->dsoc -= (sleep_soc * 2 * 1000);
3298*4882a593Smuzhiyun else
3299*4882a593Smuzhiyun battery->dsoc -= sleep_soc * 1000;
3300*4882a593Smuzhiyun } else {
3301*4882a593Smuzhiyun battery->dsoc = battery->rsoc;
3302*4882a593Smuzhiyun }
3303*4882a593Smuzhiyun
3304*4882a593Smuzhiyun DBG("%s: dsoc>rsoc, sum_cap=%d=>sleep_soc=%d, gap_soc=%d\n",
3305*4882a593Smuzhiyun __func__, battery->sleep_sum_cap, sleep_soc, gap_soc);
3306*4882a593Smuzhiyun }
3307*4882a593Smuzhiyun
3308*4882a593Smuzhiyun if (battery->voltage_avg <= pwroff_vol - 70) {
3309*4882a593Smuzhiyun battery->dsoc = 0;
3310*4882a593Smuzhiyun DBG("low power sleeping, shutdown... %d\n", battery->dsoc);
3311*4882a593Smuzhiyun }
3312*4882a593Smuzhiyun
3313*4882a593Smuzhiyun if (ocv_soc_updated && sleep_soc &&
3314*4882a593Smuzhiyun (battery->rsoc - battery->dsoc) < 5000 &&
3315*4882a593Smuzhiyun battery->dsoc < 40 * 1000) {
3316*4882a593Smuzhiyun battery->dsoc -= 1000;
3317*4882a593Smuzhiyun DBG("low power sleeping, reserved... %d\n", battery->dsoc);
3318*4882a593Smuzhiyun }
3319*4882a593Smuzhiyun
3320*4882a593Smuzhiyun if (battery->dsoc <= 0) {
3321*4882a593Smuzhiyun battery->dsoc = 0;
3322*4882a593Smuzhiyun DBG("sleep dsoc is %d...\n", battery->dsoc);
3323*4882a593Smuzhiyun }
3324*4882a593Smuzhiyun
3325*4882a593Smuzhiyun DBG("<%s>. out: dsoc=%d, rsoc=%d, sum_cap=%d\n",
3326*4882a593Smuzhiyun __func__, battery->dsoc, battery->rsoc, battery->sleep_sum_cap);
3327*4882a593Smuzhiyun
3328*4882a593Smuzhiyun return sleep_soc;
3329*4882a593Smuzhiyun }
3330*4882a593Smuzhiyun
rk817_bat_resume_work(struct work_struct * work)3331*4882a593Smuzhiyun static void rk817_bat_resume_work(struct work_struct *work)
3332*4882a593Smuzhiyun {
3333*4882a593Smuzhiyun struct rk817_battery_device *battery = container_of(work, struct rk817_battery_device, resume_work);
3334*4882a593Smuzhiyun int interval_sec = 0, time_step = 0, pwroff_vol;
3335*4882a593Smuzhiyun
3336*4882a593Smuzhiyun battery->s2r = true;
3337*4882a593Smuzhiyun battery->current_avg = rk817_bat_get_avg_current(battery);
3338*4882a593Smuzhiyun battery->voltage_relax = rk817_bat_get_relax_voltage(battery);
3339*4882a593Smuzhiyun battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
3340*4882a593Smuzhiyun battery->remain_cap = rk817_bat_get_capacity_uah(battery);
3341*4882a593Smuzhiyun battery->rsoc = rk817_bat_get_rsoc(battery);
3342*4882a593Smuzhiyun interval_sec = rk817_bat_rtc_sleep_sec(battery);
3343*4882a593Smuzhiyun battery->sleep_sum_sec += interval_sec;
3344*4882a593Smuzhiyun pwroff_vol = battery->pdata->pwroff_vol;
3345*4882a593Smuzhiyun
3346*4882a593Smuzhiyun if (!battery->sleep_chrg_online) {
3347*4882a593Smuzhiyun /* only add up discharge sleep seconds */
3348*4882a593Smuzhiyun battery->sleep_dischrg_sec += interval_sec;
3349*4882a593Smuzhiyun if (battery->voltage_avg <= pwroff_vol + 50)
3350*4882a593Smuzhiyun time_step = DISCHRG_TIME_STEP1;
3351*4882a593Smuzhiyun else
3352*4882a593Smuzhiyun time_step = DISCHRG_TIME_STEP2;
3353*4882a593Smuzhiyun }
3354*4882a593Smuzhiyun
3355*4882a593Smuzhiyun DBG("resume: dl=%d rl=%d c=%d v=%d rv=%d "
3356*4882a593Smuzhiyun "cap=%d dt=%d at=%ld ch=%d, sec = %d\n",
3357*4882a593Smuzhiyun battery->dsoc, battery->rsoc, battery->current_avg,
3358*4882a593Smuzhiyun battery->voltage_avg, battery->voltage_relax,
3359*4882a593Smuzhiyun rk817_bat_get_capacity_uah(battery), interval_sec,
3360*4882a593Smuzhiyun battery->sleep_dischrg_sec, battery->sleep_chrg_online,
3361*4882a593Smuzhiyun interval_sec);
3362*4882a593Smuzhiyun
3363*4882a593Smuzhiyun /* sleep: enough time and discharge */
3364*4882a593Smuzhiyun if ((!battery->sleep_chrg_online) &&
3365*4882a593Smuzhiyun (battery->sleep_dischrg_sec > time_step)) {
3366*4882a593Smuzhiyun if (rk817_bat_sleep_dischrg(battery))
3367*4882a593Smuzhiyun battery->sleep_dischrg_sec = 0;
3368*4882a593Smuzhiyun }
3369*4882a593Smuzhiyun
3370*4882a593Smuzhiyun rk817_bat_save_data(battery);
3371*4882a593Smuzhiyun
3372*4882a593Smuzhiyun /* charge/lowpower lock: for battery work to update dsoc and rsoc */
3373*4882a593Smuzhiyun if ((battery->sleep_chrg_online) ||
3374*4882a593Smuzhiyun (!battery->sleep_chrg_online &&
3375*4882a593Smuzhiyun battery->voltage_avg < battery->pdata->pwroff_vol))
3376*4882a593Smuzhiyun wake_lock_timeout(&battery->wake_lock, msecs_to_jiffies(2000));
3377*4882a593Smuzhiyun
3378*4882a593Smuzhiyun queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work,
3379*4882a593Smuzhiyun msecs_to_jiffies(1000));
3380*4882a593Smuzhiyun }
3381*4882a593Smuzhiyun
rk817_bat_pm_resume(struct device * dev)3382*4882a593Smuzhiyun static int rk817_bat_pm_resume(struct device *dev)
3383*4882a593Smuzhiyun {
3384*4882a593Smuzhiyun struct rk817_battery_device *battery = dev_get_drvdata(dev);
3385*4882a593Smuzhiyun
3386*4882a593Smuzhiyun queue_work(battery->bat_monitor_wq, &battery->resume_work);
3387*4882a593Smuzhiyun
3388*4882a593Smuzhiyun return 0;
3389*4882a593Smuzhiyun }
3390*4882a593Smuzhiyun #endif
3391*4882a593Smuzhiyun
3392*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(rk817_bat_pm_ops,
3393*4882a593Smuzhiyun rk817_bat_pm_suspend,
3394*4882a593Smuzhiyun rk817_bat_pm_resume);
3395*4882a593Smuzhiyun
3396*4882a593Smuzhiyun static struct platform_driver rk817_battery_driver = {
3397*4882a593Smuzhiyun .probe = rk817_battery_probe,
3398*4882a593Smuzhiyun .shutdown = rk817_battery_shutdown,
3399*4882a593Smuzhiyun .driver = {
3400*4882a593Smuzhiyun .name = "rk817-battery",
3401*4882a593Smuzhiyun .pm = &rk817_bat_pm_ops,
3402*4882a593Smuzhiyun .of_match_table = of_match_ptr(rk817_bat_of_match),
3403*4882a593Smuzhiyun },
3404*4882a593Smuzhiyun };
3405*4882a593Smuzhiyun
rk817_battery_init(void)3406*4882a593Smuzhiyun static int __init rk817_battery_init(void)
3407*4882a593Smuzhiyun {
3408*4882a593Smuzhiyun return platform_driver_register(&rk817_battery_driver);
3409*4882a593Smuzhiyun }
3410*4882a593Smuzhiyun fs_initcall_sync(rk817_battery_init);
3411*4882a593Smuzhiyun
rk817_battery_exit(void)3412*4882a593Smuzhiyun static void __exit rk817_battery_exit(void)
3413*4882a593Smuzhiyun {
3414*4882a593Smuzhiyun platform_driver_unregister(&rk817_battery_driver);
3415*4882a593Smuzhiyun }
3416*4882a593Smuzhiyun module_exit(rk817_battery_exit);
3417*4882a593Smuzhiyun
3418*4882a593Smuzhiyun MODULE_DESCRIPTION("RK817 Battery driver");
3419*4882a593Smuzhiyun MODULE_LICENSE("GPL");
3420