blob: 7650e215e298ebba34cc56eea9358e44c25a2fb4 [file] [log] [blame]
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "FG: %s: " fmt, __func__
14
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -080015#include <linux/ktime.h>
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070016#include <linux/of.h>
17#include <linux/of_irq.h>
18#include <linux/of_platform.h>
19#include <linux/of_batterydata.h>
20#include <linux/platform_device.h>
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070021#include <linux/iio/consumer.h>
22#include <linux/qpnp/qpnp-revid.h>
23#include "fg-core.h"
24#include "fg-reg.h"
25
26#define FG_GEN3_DEV_NAME "qcom,fg-gen3"
27
28#define PERPH_SUBTYPE_REG 0x05
Harry Yang2452b272017-03-06 13:56:14 -080029#define FG_BATT_SOC_PMI8998 0x10
30#define FG_BATT_INFO_PMI8998 0x11
31#define FG_MEM_INFO_PMI8998 0x0D
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070032
33/* SRAM address and offset in ascending order */
34#define CUTOFF_VOLT_WORD 5
35#define CUTOFF_VOLT_OFFSET 0
36#define SYS_TERM_CURR_WORD 6
37#define SYS_TERM_CURR_OFFSET 0
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -070038#define VBATT_FULL_WORD 7
39#define VBATT_FULL_OFFSET 0
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -080040#define ESR_FILTER_WORD 8
41#define ESR_UPD_TIGHT_OFFSET 0
42#define ESR_UPD_BROAD_OFFSET 1
43#define ESR_UPD_TIGHT_LOW_TEMP_OFFSET 2
44#define ESR_UPD_BROAD_LOW_TEMP_OFFSET 3
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -070045#define KI_COEFF_MED_DISCHG_WORD 9
46#define KI_COEFF_MED_DISCHG_OFFSET 3
47#define KI_COEFF_HI_DISCHG_WORD 10
48#define KI_COEFF_HI_DISCHG_OFFSET 0
49#define KI_COEFF_LOW_DISCHG_WORD 10
50#define KI_COEFF_LOW_DISCHG_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070051#define DELTA_SOC_THR_WORD 12
52#define DELTA_SOC_THR_OFFSET 3
53#define RECHARGE_SOC_THR_WORD 14
54#define RECHARGE_SOC_THR_OFFSET 0
55#define CHG_TERM_CURR_WORD 14
56#define CHG_TERM_CURR_OFFSET 1
57#define EMPTY_VOLT_WORD 15
58#define EMPTY_VOLT_OFFSET 0
59#define VBATT_LOW_WORD 15
60#define VBATT_LOW_OFFSET 1
Nicholas Troastdcf8fe62016-08-04 14:30:02 -070061#define ESR_TIMER_DISCHG_MAX_WORD 17
62#define ESR_TIMER_DISCHG_MAX_OFFSET 0
63#define ESR_TIMER_DISCHG_INIT_WORD 17
64#define ESR_TIMER_DISCHG_INIT_OFFSET 2
65#define ESR_TIMER_CHG_MAX_WORD 18
66#define ESR_TIMER_CHG_MAX_OFFSET 0
67#define ESR_TIMER_CHG_INIT_WORD 18
68#define ESR_TIMER_CHG_INIT_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070069#define PROFILE_LOAD_WORD 24
70#define PROFILE_LOAD_OFFSET 0
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -080071#define ESR_RSLOW_DISCHG_WORD 34
72#define ESR_RSLOW_DISCHG_OFFSET 0
73#define ESR_RSLOW_CHG_WORD 51
74#define ESR_RSLOW_CHG_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070075#define NOM_CAP_WORD 58
76#define NOM_CAP_OFFSET 0
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -070077#define ACT_BATT_CAP_BKUP_WORD 74
78#define ACT_BATT_CAP_BKUP_OFFSET 0
Nicholas Troaste29dec92016-08-24 09:35:11 -070079#define CYCLE_COUNT_WORD 75
80#define CYCLE_COUNT_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070081#define PROFILE_INTEGRITY_WORD 79
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -080082#define SW_CONFIG_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070083#define PROFILE_INTEGRITY_OFFSET 3
84#define BATT_SOC_WORD 91
85#define BATT_SOC_OFFSET 0
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -070086#define FULL_SOC_WORD 93
87#define FULL_SOC_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070088#define MONOTONIC_SOC_WORD 94
89#define MONOTONIC_SOC_OFFSET 2
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -070090#define CC_SOC_WORD 95
91#define CC_SOC_OFFSET 0
92#define CC_SOC_SW_WORD 96
93#define CC_SOC_SW_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070094#define VOLTAGE_PRED_WORD 97
95#define VOLTAGE_PRED_OFFSET 0
96#define OCV_WORD 97
97#define OCV_OFFSET 2
98#define RSLOW_WORD 101
99#define RSLOW_OFFSET 0
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700100#define ACT_BATT_CAP_WORD 117
101#define ACT_BATT_CAP_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700102#define LAST_BATT_SOC_WORD 119
103#define LAST_BATT_SOC_OFFSET 0
104#define LAST_MONOTONIC_SOC_WORD 119
105#define LAST_MONOTONIC_SOC_OFFSET 2
Nicholas Troast69da2252016-09-07 16:17:47 -0700106#define ALG_FLAGS_WORD 120
107#define ALG_FLAGS_OFFSET 1
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700108
Nicholas Troasta2b40372016-08-15 10:45:39 -0700109/* v2 SRAM address and offset in ascending order */
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700110#define KI_COEFF_LOW_DISCHG_v2_WORD 9
111#define KI_COEFF_LOW_DISCHG_v2_OFFSET 3
112#define KI_COEFF_MED_DISCHG_v2_WORD 10
113#define KI_COEFF_MED_DISCHG_v2_OFFSET 0
114#define KI_COEFF_HI_DISCHG_v2_WORD 10
115#define KI_COEFF_HI_DISCHG_v2_OFFSET 1
Nicholas Troasta2b40372016-08-15 10:45:39 -0700116#define DELTA_SOC_THR_v2_WORD 13
117#define DELTA_SOC_THR_v2_OFFSET 0
118#define RECHARGE_SOC_THR_v2_WORD 14
119#define RECHARGE_SOC_THR_v2_OFFSET 1
120#define CHG_TERM_CURR_v2_WORD 15
121#define CHG_TERM_CURR_v2_OFFSET 1
122#define EMPTY_VOLT_v2_WORD 15
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700123#define EMPTY_VOLT_v2_OFFSET 3
Nicholas Troasta2b40372016-08-15 10:45:39 -0700124#define VBATT_LOW_v2_WORD 16
125#define VBATT_LOW_v2_OFFSET 0
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -0800126#define RECHARGE_VBATT_THR_v2_WORD 16
127#define RECHARGE_VBATT_THR_v2_OFFSET 1
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700128#define FLOAT_VOLT_v2_WORD 16
129#define FLOAT_VOLT_v2_OFFSET 2
Nicholas Troasta2b40372016-08-15 10:45:39 -0700130
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700131static int fg_decode_voltage_15b(struct fg_sram_param *sp,
132 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700133static int fg_decode_value_16b(struct fg_sram_param *sp,
134 enum fg_sram_param_id id, int val);
135static int fg_decode_default(struct fg_sram_param *sp,
136 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700137static int fg_decode_cc_soc(struct fg_sram_param *sp,
138 enum fg_sram_param_id id, int value);
Nicholas Troasta2b40372016-08-15 10:45:39 -0700139static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700140 enum fg_sram_param_id id, int val_mv, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700141static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700142 enum fg_sram_param_id id, int val_ma, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700143static void fg_encode_default(struct fg_sram_param *sp,
144 enum fg_sram_param_id id, int val, u8 *buf);
145
Nicholas Troasta2b40372016-08-15 10:45:39 -0700146#define PARAM(_id, _addr_word, _addr_byte, _len, _num, _den, _offset, \
147 _enc, _dec) \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700148 [FG_SRAM_##_id] = { \
Nicholas Troasta2b40372016-08-15 10:45:39 -0700149 .addr_word = _addr_word, \
150 .addr_byte = _addr_byte, \
151 .len = _len, \
152 .numrtr = _num, \
153 .denmtr = _den, \
154 .offset = _offset, \
155 .encode = _enc, \
156 .decode = _dec, \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700157 } \
158
Harry Yang2452b272017-03-06 13:56:14 -0800159static struct fg_sram_param pmi8998_v1_sram_params[] = {
Nicholas Troasta2b40372016-08-15 10:45:39 -0700160 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700161 fg_decode_default),
Nicholas Troast1769fd32016-09-07 09:20:58 -0700162 PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL,
163 fg_decode_default),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700164 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700165 1000, 0, NULL, fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700166 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700167 fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700168 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700169 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700170 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
171 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700172 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
173 fg_decode_cc_soc),
174 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
175 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700176 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
177 1, 1, 0, NULL, fg_decode_default),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700178 /* Entries below here are configurable during initialization */
179 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700180 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700181 PARAM(EMPTY_VOLT, EMPTY_VOLT_WORD, EMPTY_VOLT_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700182 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700183 PARAM(VBATT_LOW, VBATT_LOW_WORD, VBATT_LOW_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700184 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700185 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
186 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700187 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700188 1000000, 122070, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700189 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700190 100000, 390625, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthy6234f342016-09-22 18:11:42 -0700191 PARAM(DELTA_SOC_THR, DELTA_SOC_THR_WORD, DELTA_SOC_THR_OFFSET, 1, 2048,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700192 100, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700193 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_WORD, RECHARGE_SOC_THR_OFFSET,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700194 1, 256, 100, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700195 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700196 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
197 NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700198 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700199 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700200 NULL),
201 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700202 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700203 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700204 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700205 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD,
206 KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 244141, 0,
207 fg_encode_default, NULL),
208 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD,
209 KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 244141, 0,
210 fg_encode_default, NULL),
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -0800211 PARAM(ESR_TIGHT_FILTER, ESR_FILTER_WORD, ESR_UPD_TIGHT_OFFSET,
212 1, 512, 1000000, 0, fg_encode_default, NULL),
213 PARAM(ESR_BROAD_FILTER, ESR_FILTER_WORD, ESR_UPD_BROAD_OFFSET,
214 1, 512, 1000000, 0, fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700215};
216
Harry Yang2452b272017-03-06 13:56:14 -0800217static struct fg_sram_param pmi8998_v2_sram_params[] = {
Nicholas Troasta2b40372016-08-15 10:45:39 -0700218 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700219 fg_decode_default),
Nicholas Troast1769fd32016-09-07 09:20:58 -0700220 PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL,
221 fg_decode_default),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700222 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700223 1000, 0, NULL, fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700224 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700225 fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700226 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
227 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700228 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
229 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700230 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
231 fg_decode_cc_soc),
232 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
233 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700234 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
235 1, 1, 0, NULL, fg_decode_default),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700236 /* Entries below here are configurable during initialization */
237 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
238 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700239 PARAM(EMPTY_VOLT, EMPTY_VOLT_v2_WORD, EMPTY_VOLT_v2_OFFSET, 1, 1000,
240 15625, -2000, fg_encode_voltage, NULL),
241 PARAM(VBATT_LOW, VBATT_LOW_v2_WORD, VBATT_LOW_v2_OFFSET, 1, 1000,
242 15625, -2000, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700243 PARAM(FLOAT_VOLT, FLOAT_VOLT_v2_WORD, FLOAT_VOLT_v2_OFFSET, 1, 1000,
244 15625, -2000, fg_encode_voltage, NULL),
245 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
246 244141, 0, fg_encode_voltage, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700247 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
248 1000000, 122070, 0, fg_encode_current, NULL),
249 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_v2_WORD, CHG_TERM_CURR_v2_OFFSET, 1,
250 100000, 390625, 0, fg_encode_current, NULL),
251 PARAM(DELTA_SOC_THR, DELTA_SOC_THR_v2_WORD, DELTA_SOC_THR_v2_OFFSET, 1,
Subbaraman Narayanamurthy6234f342016-09-22 18:11:42 -0700252 2048, 100, 0, fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700253 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD,
254 RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default,
255 NULL),
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -0800256 PARAM(RECHARGE_VBATT_THR, RECHARGE_VBATT_THR_v2_WORD,
257 RECHARGE_VBATT_THR_v2_OFFSET, 1, 1000, 15625, -2000,
258 fg_encode_voltage, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700259 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
260 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
261 NULL),
262 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
263 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
264 NULL),
265 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
266 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
267 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
268 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700269 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_v2_WORD,
270 KI_COEFF_MED_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
271 fg_encode_default, NULL),
272 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_v2_WORD,
273 KI_COEFF_HI_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
274 fg_encode_default, NULL),
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -0800275 PARAM(ESR_TIGHT_FILTER, ESR_FILTER_WORD, ESR_UPD_TIGHT_OFFSET,
276 1, 512, 1000000, 0, fg_encode_default, NULL),
277 PARAM(ESR_BROAD_FILTER, ESR_FILTER_WORD, ESR_UPD_BROAD_OFFSET,
278 1, 512, 1000000, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700279};
280
Harry Yang2452b272017-03-06 13:56:14 -0800281static struct fg_alg_flag pmi8998_v1_alg_flags[] = {
Nicholas Troast69da2252016-09-07 16:17:47 -0700282 [ALG_FLAG_SOC_LT_OTG_MIN] = {
283 .name = "SOC_LT_OTG_MIN",
284 .bit = BIT(0),
285 },
286 [ALG_FLAG_SOC_LT_RECHARGE] = {
287 .name = "SOC_LT_RECHARGE",
288 .bit = BIT(1),
289 },
290 [ALG_FLAG_IBATT_LT_ITERM] = {
291 .name = "IBATT_LT_ITERM",
292 .bit = BIT(2),
293 },
294 [ALG_FLAG_IBATT_GT_HPM] = {
295 .name = "IBATT_GT_HPM",
296 .bit = BIT(3),
297 },
298 [ALG_FLAG_IBATT_GT_UPM] = {
299 .name = "IBATT_GT_UPM",
300 .bit = BIT(4),
301 },
302 [ALG_FLAG_VBATT_LT_RECHARGE] = {
303 .name = "VBATT_LT_RECHARGE",
304 .bit = BIT(5),
305 },
306 [ALG_FLAG_VBATT_GT_VFLOAT] = {
307 .invalid = true,
308 },
309};
310
Harry Yang2452b272017-03-06 13:56:14 -0800311static struct fg_alg_flag pmi8998_v2_alg_flags[] = {
Nicholas Troast69da2252016-09-07 16:17:47 -0700312 [ALG_FLAG_SOC_LT_OTG_MIN] = {
313 .name = "SOC_LT_OTG_MIN",
314 .bit = BIT(0),
315 },
316 [ALG_FLAG_SOC_LT_RECHARGE] = {
317 .name = "SOC_LT_RECHARGE",
318 .bit = BIT(1),
319 },
320 [ALG_FLAG_IBATT_LT_ITERM] = {
321 .name = "IBATT_LT_ITERM",
322 .bit = BIT(2),
323 },
324 [ALG_FLAG_IBATT_GT_HPM] = {
325 .name = "IBATT_GT_HPM",
326 .bit = BIT(4),
327 },
328 [ALG_FLAG_IBATT_GT_UPM] = {
329 .name = "IBATT_GT_UPM",
330 .bit = BIT(5),
331 },
332 [ALG_FLAG_VBATT_LT_RECHARGE] = {
333 .name = "VBATT_LT_RECHARGE",
334 .bit = BIT(6),
335 },
336 [ALG_FLAG_VBATT_GT_VFLOAT] = {
337 .name = "VBATT_GT_VFLOAT",
338 .bit = BIT(7),
339 },
340};
341
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700342static int fg_gen3_debug_mask;
343module_param_named(
344 debug_mask, fg_gen3_debug_mask, int, 0600
345);
346
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800347static bool fg_profile_dump;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700348module_param_named(
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800349 profile_dump, fg_profile_dump, bool, 0600
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700350);
351
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800352static int fg_sram_dump_period_ms = 20000;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700353module_param_named(
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800354 sram_dump_period_ms, fg_sram_dump_period_ms, int, 0600
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700355);
356
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -0700357static int fg_restart;
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800358static bool fg_sram_dump;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700359
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700360/* All getters HERE */
361
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700362#define VOLTAGE_15BIT_MASK GENMASK(14, 0)
363static int fg_decode_voltage_15b(struct fg_sram_param *sp,
364 enum fg_sram_param_id id, int value)
365{
366 value &= VOLTAGE_15BIT_MASK;
367 sp[id].value = div_u64((u64)value * sp[id].numrtr, sp[id].denmtr);
368 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
369 sp[id].value);
370 return sp[id].value;
371}
372
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700373static int fg_decode_cc_soc(struct fg_sram_param *sp,
374 enum fg_sram_param_id id, int value)
375{
376 sp[id].value = div_s64((s64)value * sp[id].numrtr, sp[id].denmtr);
377 sp[id].value = sign_extend32(sp[id].value, 31);
378 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
379 sp[id].value);
380 return sp[id].value;
381}
382
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700383static int fg_decode_value_16b(struct fg_sram_param *sp,
384 enum fg_sram_param_id id, int value)
385{
386 sp[id].value = div_u64((u64)(u16)value * sp[id].numrtr, sp[id].denmtr);
387 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
388 sp[id].value);
389 return sp[id].value;
390}
391
Nicholas Troaste29dec92016-08-24 09:35:11 -0700392static int fg_decode_default(struct fg_sram_param *sp, enum fg_sram_param_id id,
393 int value)
394{
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700395 sp[id].value = value;
396 return sp[id].value;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700397}
398
399static int fg_decode(struct fg_sram_param *sp, enum fg_sram_param_id id,
400 int value)
401{
402 if (!sp[id].decode) {
403 pr_err("No decoding function for parameter %d\n", id);
404 return -EINVAL;
405 }
406
407 return sp[id].decode(sp, id, value);
408}
409
Nicholas Troasta2b40372016-08-15 10:45:39 -0700410static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700411 enum fg_sram_param_id id, int val_mv, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700412{
413 int i, mask = 0xff;
414 int64_t temp;
415
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700416 val_mv += sp[id].offset;
417 temp = (int64_t)div_u64((u64)val_mv * sp[id].numrtr, sp[id].denmtr);
418 pr_debug("temp: %llx id: %d, val_mv: %d, buf: [ ", temp, id, val_mv);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700419 for (i = 0; i < sp[id].len; i++) {
420 buf[i] = temp & mask;
421 temp >>= 8;
422 pr_debug("%x ", buf[i]);
423 }
424 pr_debug("]\n");
425}
426
427static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700428 enum fg_sram_param_id id, int val_ma, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700429{
430 int i, mask = 0xff;
431 int64_t temp;
432 s64 current_ma;
433
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700434 current_ma = val_ma;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700435 temp = (int64_t)div_s64(current_ma * sp[id].numrtr, sp[id].denmtr);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700436 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val_ma);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700437 for (i = 0; i < sp[id].len; i++) {
438 buf[i] = temp & mask;
439 temp >>= 8;
440 pr_debug("%x ", buf[i]);
441 }
442 pr_debug("]\n");
443}
444
445static void fg_encode_default(struct fg_sram_param *sp,
446 enum fg_sram_param_id id, int val, u8 *buf)
447{
448 int i, mask = 0xff;
449 int64_t temp;
450
451 temp = DIV_ROUND_CLOSEST(val * sp[id].numrtr, sp[id].denmtr);
452 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val);
453 for (i = 0; i < sp[id].len; i++) {
454 buf[i] = temp & mask;
455 temp >>= 8;
456 pr_debug("%x ", buf[i]);
457 }
458 pr_debug("]\n");
459}
460
461static void fg_encode(struct fg_sram_param *sp, enum fg_sram_param_id id,
462 int val, u8 *buf)
463{
464 if (!sp[id].encode) {
465 pr_err("No encoding function for parameter %d\n", id);
466 return;
467 }
468
469 sp[id].encode(sp, id, val, buf);
470}
471
472/*
473 * Please make sure *_sram_params table has the entry for the parameter
474 * obtained through this function. In addition to address, offset,
475 * length from where this SRAM parameter is read, a decode function
476 * need to be specified.
477 */
478static int fg_get_sram_prop(struct fg_chip *chip, enum fg_sram_param_id id,
479 int *val)
480{
481 int temp, rc, i;
482 u8 buf[4];
483
484 if (id < 0 || id > FG_SRAM_MAX || chip->sp[id].len > sizeof(buf))
485 return -EINVAL;
486
Subbaraman Narayanamurthy0a749db2016-10-03 18:33:19 -0700487 if (chip->battery_missing)
488 return -ENODATA;
489
Nicholas Troasta2b40372016-08-15 10:45:39 -0700490 rc = fg_sram_read(chip, chip->sp[id].addr_word, chip->sp[id].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700491 buf, chip->sp[id].len, FG_IMA_DEFAULT);
492 if (rc < 0) {
493 pr_err("Error reading address 0x%04x[%d] rc=%d\n",
Nicholas Troasta2b40372016-08-15 10:45:39 -0700494 chip->sp[id].addr_word, chip->sp[id].addr_byte, rc);
Nicholas Troastb2d71742016-08-04 14:31:41 -0700495 return rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700496 }
497
498 for (i = 0, temp = 0; i < chip->sp[id].len; i++)
499 temp |= buf[i] << (8 * i);
500
501 *val = fg_decode(chip->sp, id, temp);
502 return 0;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700503}
504
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700505#define CC_SOC_30BIT GENMASK(29, 0)
506static int fg_get_cc_soc(struct fg_chip *chip, int *val)
507{
508 int rc, cc_soc;
509
510 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC, &cc_soc);
511 if (rc < 0) {
512 pr_err("Error in getting CC_SOC, rc=%d\n", rc);
513 return rc;
514 }
515
516 *val = div_s64(cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
517 return 0;
518}
519
520static int fg_get_cc_soc_sw(struct fg_chip *chip, int *val)
521{
522 int rc, cc_soc;
523
524 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc);
525 if (rc < 0) {
526 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
527 return rc;
528 }
529
530 *val = div_s64(cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
531 return 0;
532}
533
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700534#define BATT_TEMP_NUMR 1
535#define BATT_TEMP_DENR 1
536static int fg_get_battery_temp(struct fg_chip *chip, int *val)
537{
Subbaraman Narayanamurthyfabbb8e2016-10-21 16:55:09 -0700538 int rc = 0, temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700539 u8 buf[2];
540
541 rc = fg_read(chip, BATT_INFO_BATT_TEMP_LSB(chip), buf, 2);
542 if (rc < 0) {
543 pr_err("failed to read addr=0x%04x, rc=%d\n",
544 BATT_INFO_BATT_TEMP_LSB(chip), rc);
545 return rc;
546 }
547
548 temp = ((buf[1] & BATT_TEMP_MSB_MASK) << 8) |
549 (buf[0] & BATT_TEMP_LSB_MASK);
550 temp = DIV_ROUND_CLOSEST(temp, 4);
551
552 /* Value is in Kelvin; Convert it to deciDegC */
553 temp = (temp - 273) * 10;
554 *val = temp;
555 return 0;
556}
557
558#define BATT_ESR_NUMR 244141
559#define BATT_ESR_DENR 1000
560static int fg_get_battery_esr(struct fg_chip *chip, int *val)
561{
562 int rc = 0;
563 u16 temp = 0;
564 u8 buf[2];
565
566 rc = fg_read(chip, BATT_INFO_ESR_LSB(chip), buf, 2);
567 if (rc < 0) {
568 pr_err("failed to read addr=0x%04x, rc=%d\n",
569 BATT_INFO_ESR_LSB(chip), rc);
570 return rc;
571 }
572
Ashay Jaiswal63d486e2016-12-07 11:21:32 +0530573 if (chip->wa_flags & PMI8998_V1_REV_WA)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700574 temp = ((buf[0] & ESR_MSB_MASK) << 8) |
575 (buf[1] & ESR_LSB_MASK);
576 else
577 temp = ((buf[1] & ESR_MSB_MASK) << 8) |
578 (buf[0] & ESR_LSB_MASK);
579
580 pr_debug("buf: %x %x temp: %x\n", buf[0], buf[1], temp);
581 *val = div_u64((u64)temp * BATT_ESR_NUMR, BATT_ESR_DENR);
582 return 0;
583}
584
585static int fg_get_battery_resistance(struct fg_chip *chip, int *val)
586{
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -0800587 int rc, esr_uohms, rslow_uohms;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700588
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -0800589 rc = fg_get_battery_esr(chip, &esr_uohms);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700590 if (rc < 0) {
591 pr_err("failed to get ESR, rc=%d\n", rc);
592 return rc;
593 }
594
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -0800595 rc = fg_get_sram_prop(chip, FG_SRAM_RSLOW, &rslow_uohms);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700596 if (rc < 0) {
597 pr_err("failed to get Rslow, rc=%d\n", rc);
598 return rc;
599 }
600
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -0800601 *val = esr_uohms + rslow_uohms;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700602 return 0;
603}
604
605#define BATT_CURRENT_NUMR 488281
606#define BATT_CURRENT_DENR 1000
607static int fg_get_battery_current(struct fg_chip *chip, int *val)
608{
609 int rc = 0;
610 int64_t temp = 0;
611 u8 buf[2];
612
613 rc = fg_read(chip, BATT_INFO_IBATT_LSB(chip), buf, 2);
614 if (rc < 0) {
615 pr_err("failed to read addr=0x%04x, rc=%d\n",
616 BATT_INFO_IBATT_LSB(chip), rc);
617 return rc;
618 }
619
Ashay Jaiswal63d486e2016-12-07 11:21:32 +0530620 if (chip->wa_flags & PMI8998_V1_REV_WA)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700621 temp = buf[0] << 8 | buf[1];
622 else
623 temp = buf[1] << 8 | buf[0];
624
625 pr_debug("buf: %x %x temp: %llx\n", buf[0], buf[1], temp);
626 /* Sign bit is bit 15 */
627 temp = twos_compliment_extend(temp, 15);
628 *val = div_s64((s64)temp * BATT_CURRENT_NUMR, BATT_CURRENT_DENR);
629 return 0;
630}
631
632#define BATT_VOLTAGE_NUMR 122070
633#define BATT_VOLTAGE_DENR 1000
634static int fg_get_battery_voltage(struct fg_chip *chip, int *val)
635{
636 int rc = 0;
637 u16 temp = 0;
638 u8 buf[2];
639
640 rc = fg_read(chip, BATT_INFO_VBATT_LSB(chip), buf, 2);
641 if (rc < 0) {
642 pr_err("failed to read addr=0x%04x, rc=%d\n",
643 BATT_INFO_VBATT_LSB(chip), rc);
644 return rc;
645 }
646
Ashay Jaiswal63d486e2016-12-07 11:21:32 +0530647 if (chip->wa_flags & PMI8998_V1_REV_WA)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700648 temp = buf[0] << 8 | buf[1];
649 else
650 temp = buf[1] << 8 | buf[0];
651
652 pr_debug("buf: %x %x temp: %x\n", buf[0], buf[1], temp);
653 *val = div_u64((u64)temp * BATT_VOLTAGE_NUMR, BATT_VOLTAGE_DENR);
654 return 0;
655}
656
657#define MAX_TRIES_SOC 5
658static int fg_get_msoc_raw(struct fg_chip *chip, int *val)
659{
660 u8 cap[2];
661 int rc, tries = 0;
662
663 while (tries < MAX_TRIES_SOC) {
664 rc = fg_read(chip, BATT_SOC_FG_MONOTONIC_SOC(chip), cap, 2);
665 if (rc < 0) {
666 pr_err("failed to read addr=0x%04x, rc=%d\n",
667 BATT_SOC_FG_MONOTONIC_SOC(chip), rc);
668 return rc;
669 }
670
671 if (cap[0] == cap[1])
672 break;
673
674 tries++;
675 }
676
677 if (tries == MAX_TRIES_SOC) {
678 pr_err("shadow registers do not match\n");
679 return -EINVAL;
680 }
681
682 fg_dbg(chip, FG_POWER_SUPPLY, "raw: 0x%02x\n", cap[0]);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700683 *val = cap[0];
684 return 0;
685}
686
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800687static bool is_batt_empty(struct fg_chip *chip)
688{
689 u8 status;
690 int rc, vbatt_uv, msoc;
691
692 rc = fg_read(chip, BATT_SOC_INT_RT_STS(chip), &status, 1);
693 if (rc < 0) {
694 pr_err("failed to read addr=0x%04x, rc=%d\n",
695 BATT_SOC_INT_RT_STS(chip), rc);
696 return false;
697 }
698
699 if (!(status & MSOC_EMPTY_BIT))
700 return false;
701
702 rc = fg_get_battery_voltage(chip, &vbatt_uv);
703 if (rc < 0) {
704 pr_err("failed to get battery voltage, rc=%d\n", rc);
705 return false;
706 }
707
708 rc = fg_get_msoc_raw(chip, &msoc);
709 if (!rc)
710 pr_warn("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", status,
711 vbatt_uv, msoc);
712
713 return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false);
714}
715
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800716static int fg_get_debug_batt_id(struct fg_chip *chip, int *batt_id)
717{
718 int rc;
719 u64 temp;
720 u8 buf[2];
721
722 rc = fg_read(chip, ADC_RR_FAKE_BATT_LOW_LSB(chip), buf, 2);
723 if (rc < 0) {
724 pr_err("failed to read addr=0x%04x, rc=%d\n",
725 ADC_RR_FAKE_BATT_LOW_LSB(chip), rc);
726 return rc;
727 }
728
729 /*
730 * Fake battery threshold is encoded in the following format.
731 * Threshold (code) = (battery_id in Ohms) * 0.00015 * 2^10 / 2.5
732 */
733 temp = (buf[1] << 8 | buf[0]) * 2500000;
734 do_div(temp, 150 * 1024);
735 batt_id[0] = temp;
736 rc = fg_read(chip, ADC_RR_FAKE_BATT_HIGH_LSB(chip), buf, 2);
737 if (rc < 0) {
738 pr_err("failed to read addr=0x%04x, rc=%d\n",
739 ADC_RR_FAKE_BATT_HIGH_LSB(chip), rc);
740 return rc;
741 }
742
743 temp = (buf[1] << 8 | buf[0]) * 2500000;
744 do_div(temp, 150 * 1024);
745 batt_id[1] = temp;
746 pr_debug("debug batt_id range: [%d %d]\n", batt_id[0], batt_id[1]);
747 return 0;
748}
749
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700750static bool is_debug_batt_id(struct fg_chip *chip)
751{
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800752 int debug_batt_id[2], rc;
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700753
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800754 if (!chip->batt_id_ohms)
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700755 return false;
756
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800757 rc = fg_get_debug_batt_id(chip, debug_batt_id);
758 if (rc < 0) {
759 pr_err("Failed to get debug batt_id, rc=%d\n", rc);
760 return false;
761 }
762
763 if (is_between(debug_batt_id[0], debug_batt_id[1],
764 chip->batt_id_ohms)) {
765 fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dohms\n",
766 chip->batt_id_ohms);
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700767 return true;
768 }
769
770 return false;
771}
772
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700773#define FULL_CAPACITY 100
774#define FULL_SOC_RAW 255
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700775#define DEBUG_BATT_SOC 67
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700776#define EMPTY_SOC 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700777static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
778{
779 int rc, msoc;
780
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700781 if (is_debug_batt_id(chip)) {
782 *val = DEBUG_BATT_SOC;
783 return 0;
784 }
785
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800786 if (is_batt_empty(chip)) {
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700787 *val = EMPTY_SOC;
788 return 0;
789 }
790
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700791 if (chip->charge_full) {
792 *val = FULL_CAPACITY;
793 return 0;
794 }
795
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700796 rc = fg_get_msoc_raw(chip, &msoc);
797 if (rc < 0)
798 return rc;
799
800 *val = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
801 return 0;
802}
803
804#define DEFAULT_BATT_TYPE "Unknown Battery"
805#define MISSING_BATT_TYPE "Missing Battery"
806#define LOADING_BATT_TYPE "Loading Battery"
807static const char *fg_get_battery_type(struct fg_chip *chip)
808{
809 if (chip->battery_missing)
810 return MISSING_BATT_TYPE;
811
812 if (chip->bp.batt_type_str) {
813 if (chip->profile_loaded)
814 return chip->bp.batt_type_str;
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -0800815 else if (chip->profile_available)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700816 return LOADING_BATT_TYPE;
817 }
818
819 return DEFAULT_BATT_TYPE;
820}
821
822static int fg_get_batt_id(struct fg_chip *chip, int *val)
823{
824 int rc, batt_id = -EINVAL;
825
826 if (!chip->batt_id_chan)
827 return -EINVAL;
828
829 rc = iio_read_channel_processed(chip->batt_id_chan, &batt_id);
830 if (rc < 0) {
831 pr_err("Error in reading batt_id channel, rc:%d\n", rc);
832 return rc;
833 }
834
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700835 fg_dbg(chip, FG_STATUS, "batt_id: %d\n", batt_id);
836
837 *val = batt_id;
838 return 0;
839}
840
841static int fg_get_batt_profile(struct fg_chip *chip)
842{
843 struct device_node *node = chip->dev->of_node;
844 struct device_node *batt_node, *profile_node;
845 const char *data;
846 int rc, len, batt_id;
847
848 rc = fg_get_batt_id(chip, &batt_id);
849 if (rc < 0) {
850 pr_err("Error in getting batt_id rc:%d\n", rc);
851 return rc;
852 }
853
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800854 chip->batt_id_ohms = batt_id;
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700855 batt_id /= 1000;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700856 batt_node = of_find_node_by_name(node, "qcom,battery-data");
857 if (!batt_node) {
858 pr_err("Batterydata not available\n");
859 return -ENXIO;
860 }
861
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700862 profile_node = of_batterydata_get_best_profile(batt_node, batt_id,
863 NULL);
864 if (IS_ERR(profile_node))
865 return PTR_ERR(profile_node);
866
867 if (!profile_node) {
868 pr_err("couldn't find profile handle\n");
869 return -ENODATA;
870 }
871
872 rc = of_property_read_string(profile_node, "qcom,battery-type",
873 &chip->bp.batt_type_str);
874 if (rc < 0) {
875 pr_err("battery type unavailable, rc:%d\n", rc);
876 return rc;
877 }
878
879 rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv",
880 &chip->bp.float_volt_uv);
881 if (rc < 0) {
882 pr_err("battery float voltage unavailable, rc:%d\n", rc);
883 chip->bp.float_volt_uv = -EINVAL;
884 }
885
Subbaraman Narayanamurthy5f653bb2016-12-09 15:24:12 -0800886 rc = of_property_read_u32(profile_node, "qcom,fastchg-current-ma",
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700887 &chip->bp.fastchg_curr_ma);
888 if (rc < 0) {
Subbaraman Narayanamurthy5f653bb2016-12-09 15:24:12 -0800889 pr_err("battery fastchg current unavailable, rc:%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700890 chip->bp.fastchg_curr_ma = -EINVAL;
891 }
892
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700893 rc = of_property_read_u32(profile_node, "qcom,fg-cc-cv-threshold-mv",
894 &chip->bp.vbatt_full_mv);
895 if (rc < 0) {
896 pr_err("battery cc_cv threshold unavailable, rc:%d\n", rc);
897 chip->bp.vbatt_full_mv = -EINVAL;
898 }
899
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700900 data = of_get_property(profile_node, "qcom,fg-profile-data", &len);
901 if (!data) {
902 pr_err("No profile data available\n");
903 return -ENODATA;
904 }
905
906 if (len != PROFILE_LEN) {
907 pr_err("battery profile incorrect size: %d\n", len);
908 return -EINVAL;
909 }
910
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700911 chip->profile_available = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700912 memcpy(chip->batt_profile, data, len);
913 return 0;
914}
915
916static inline void get_temp_setpoint(int threshold, u8 *val)
917{
918 /* Resolution is 0.5C. Base is -30C. */
919 *val = DIV_ROUND_CLOSEST((threshold + 30) * 10, 5);
920}
921
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -0700922static inline void get_batt_temp_delta(int delta, u8 *val)
923{
924 switch (delta) {
925 case 2:
926 *val = BTEMP_DELTA_2K;
927 break;
928 case 4:
929 *val = BTEMP_DELTA_4K;
930 break;
931 case 6:
932 *val = BTEMP_DELTA_6K;
933 break;
934 case 10:
935 *val = BTEMP_DELTA_10K;
936 break;
937 default:
938 *val = BTEMP_DELTA_2K;
939 break;
940 };
941}
942
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700943static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
944 int flags)
945{
946 u8 buf[2];
947 int rc, timer_max, timer_init;
948
949 if (charging) {
950 timer_max = FG_SRAM_ESR_TIMER_CHG_MAX;
951 timer_init = FG_SRAM_ESR_TIMER_CHG_INIT;
952 } else {
953 timer_max = FG_SRAM_ESR_TIMER_DISCHG_MAX;
954 timer_init = FG_SRAM_ESR_TIMER_DISCHG_INIT;
955 }
956
957 fg_encode(chip->sp, timer_max, cycles, buf);
958 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700959 chip->sp[timer_max].addr_word,
960 chip->sp[timer_max].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700961 chip->sp[timer_max].len, flags);
962 if (rc < 0) {
963 pr_err("Error in writing esr_timer_dischg_max, rc=%d\n",
964 rc);
965 return rc;
966 }
967
968 fg_encode(chip->sp, timer_init, cycles, buf);
969 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700970 chip->sp[timer_init].addr_word,
971 chip->sp[timer_init].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700972 chip->sp[timer_init].len, flags);
973 if (rc < 0) {
974 pr_err("Error in writing esr_timer_dischg_init, rc=%d\n",
975 rc);
976 return rc;
977 }
978
979 return 0;
980}
981
Nicholas Troaste29dec92016-08-24 09:35:11 -0700982/* Other functions HERE */
983
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -0800984static void fg_notify_charger(struct fg_chip *chip)
985{
986 union power_supply_propval prop = {0, };
987 int rc;
988
989 if (!chip->batt_psy)
990 return;
991
992 if (!chip->profile_available)
993 return;
994
995 prop.intval = chip->bp.float_volt_uv;
996 rc = power_supply_set_property(chip->batt_psy,
997 POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
998 if (rc < 0) {
999 pr_err("Error in setting voltage_max property on batt_psy, rc=%d\n",
1000 rc);
1001 return;
1002 }
1003
1004 prop.intval = chip->bp.fastchg_curr_ma * 1000;
1005 rc = power_supply_set_property(chip->batt_psy,
1006 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &prop);
1007 if (rc < 0) {
1008 pr_err("Error in setting constant_charge_current_max property on batt_psy, rc=%d\n",
1009 rc);
1010 return;
1011 }
1012
1013 fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
1014}
1015
Nicholas Troaste29dec92016-08-24 09:35:11 -07001016static int fg_awake_cb(struct votable *votable, void *data, int awake,
1017 const char *client)
1018{
1019 struct fg_chip *chip = data;
1020
1021 if (awake)
1022 pm_stay_awake(chip->dev);
1023 else
1024 pm_relax(chip->dev);
1025
1026 pr_debug("client: %s awake: %d\n", client, awake);
1027 return 0;
1028}
1029
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001030static bool batt_psy_initialized(struct fg_chip *chip)
Nicholas Troaste29dec92016-08-24 09:35:11 -07001031{
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001032 if (chip->batt_psy)
1033 return true;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001034
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001035 chip->batt_psy = power_supply_get_by_name("battery");
Nicholas Troaste29dec92016-08-24 09:35:11 -07001036 if (!chip->batt_psy)
1037 return false;
1038
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001039 /* batt_psy is initialized, set the fcc and fv */
1040 fg_notify_charger(chip);
1041
Nicholas Troaste29dec92016-08-24 09:35:11 -07001042 return true;
1043}
1044
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001045static bool is_parallel_charger_available(struct fg_chip *chip)
1046{
1047 if (!chip->parallel_psy)
1048 chip->parallel_psy = power_supply_get_by_name("parallel");
1049
1050 if (!chip->parallel_psy)
1051 return false;
1052
1053 return true;
1054}
1055
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001056static int fg_save_learned_cap_to_sram(struct fg_chip *chip)
1057{
1058 int16_t cc_mah;
1059 int rc;
1060
1061 if (chip->battery_missing || !chip->cl.learned_cc_uah)
1062 return -EPERM;
1063
1064 cc_mah = div64_s64(chip->cl.learned_cc_uah, 1000);
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001065 /* Write to a backup register to use across reboot */
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001066 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ACT_BATT_CAP].addr_word,
1067 chip->sp[FG_SRAM_ACT_BATT_CAP].addr_byte, (u8 *)&cc_mah,
1068 chip->sp[FG_SRAM_ACT_BATT_CAP].len, FG_IMA_DEFAULT);
1069 if (rc < 0) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001070 pr_err("Error in writing act_batt_cap_bkup, rc=%d\n", rc);
1071 return rc;
1072 }
1073
1074 /* Write to actual capacity register for coulomb counter operation */
1075 rc = fg_sram_write(chip, ACT_BATT_CAP_WORD, ACT_BATT_CAP_OFFSET,
1076 (u8 *)&cc_mah, chip->sp[FG_SRAM_ACT_BATT_CAP].len,
1077 FG_IMA_DEFAULT);
1078 if (rc < 0) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001079 pr_err("Error in writing act_batt_cap, rc=%d\n", rc);
1080 return rc;
1081 }
1082
1083 fg_dbg(chip, FG_CAP_LEARN, "learned capacity %llduah/%dmah stored\n",
1084 chip->cl.learned_cc_uah, cc_mah);
1085 return 0;
1086}
1087
1088#define CAPACITY_DELTA_DECIPCT 500
1089static int fg_load_learned_cap_from_sram(struct fg_chip *chip)
1090{
1091 int rc, act_cap_mah;
1092 int64_t delta_cc_uah, pct_nom_cap_uah;
1093
1094 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
1095 if (rc < 0) {
1096 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
1097 return rc;
1098 }
1099
1100 chip->cl.learned_cc_uah = act_cap_mah * 1000;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001101
1102 if (chip->cl.learned_cc_uah != chip->cl.nom_cap_uah) {
Subbaraman Narayanamurthy51d3c902016-10-24 14:05:44 -07001103 if (chip->cl.learned_cc_uah == 0)
1104 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
1105
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001106 delta_cc_uah = abs(chip->cl.learned_cc_uah -
1107 chip->cl.nom_cap_uah);
1108 pct_nom_cap_uah = div64_s64((int64_t)chip->cl.nom_cap_uah *
1109 CAPACITY_DELTA_DECIPCT, 1000);
1110 /*
1111 * If the learned capacity is out of range by 50% from the
1112 * nominal capacity, then overwrite the learned capacity with
1113 * the nominal capacity.
1114 */
1115 if (chip->cl.nom_cap_uah && delta_cc_uah > pct_nom_cap_uah) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001116 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah: %lld is higher than expected, capping it to nominal: %lld\n",
1117 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001118 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001119 }
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001120
1121 rc = fg_save_learned_cap_to_sram(chip);
1122 if (rc < 0)
1123 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001124 }
1125
1126 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah:%lld nom_cap_uah: %lld\n",
1127 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
1128 return 0;
1129}
1130
1131static bool is_temp_valid_cap_learning(struct fg_chip *chip)
1132{
1133 int rc, batt_temp;
1134
1135 rc = fg_get_battery_temp(chip, &batt_temp);
1136 if (rc < 0) {
1137 pr_err("Error in getting batt_temp\n");
1138 return false;
1139 }
1140
1141 if (batt_temp > chip->dt.cl_max_temp ||
1142 batt_temp < chip->dt.cl_min_temp) {
1143 fg_dbg(chip, FG_CAP_LEARN, "batt temp %d out of range [%d %d]\n",
1144 batt_temp, chip->dt.cl_min_temp, chip->dt.cl_max_temp);
1145 return false;
1146 }
1147
1148 return true;
1149}
1150
1151static void fg_cap_learning_post_process(struct fg_chip *chip)
1152{
1153 int64_t max_inc_val, min_dec_val, old_cap;
1154 int rc;
1155
1156 max_inc_val = chip->cl.learned_cc_uah
1157 * (1000 + chip->dt.cl_max_cap_inc);
1158 do_div(max_inc_val, 1000);
1159
1160 min_dec_val = chip->cl.learned_cc_uah
1161 * (1000 - chip->dt.cl_max_cap_dec);
1162 do_div(min_dec_val, 1000);
1163
1164 old_cap = chip->cl.learned_cc_uah;
1165 if (chip->cl.final_cc_uah > max_inc_val)
1166 chip->cl.learned_cc_uah = max_inc_val;
1167 else if (chip->cl.final_cc_uah < min_dec_val)
1168 chip->cl.learned_cc_uah = min_dec_val;
1169 else
1170 chip->cl.learned_cc_uah =
1171 chip->cl.final_cc_uah;
1172
1173 if (chip->dt.cl_max_cap_limit) {
1174 max_inc_val = (int64_t)chip->cl.nom_cap_uah * (1000 +
1175 chip->dt.cl_max_cap_limit);
1176 do_div(max_inc_val, 1000);
1177 if (chip->cl.final_cc_uah > max_inc_val) {
1178 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes above max limit %lld\n",
1179 chip->cl.final_cc_uah, max_inc_val);
1180 chip->cl.learned_cc_uah = max_inc_val;
1181 }
1182 }
1183
1184 if (chip->dt.cl_min_cap_limit) {
1185 min_dec_val = (int64_t)chip->cl.nom_cap_uah * (1000 -
1186 chip->dt.cl_min_cap_limit);
1187 do_div(min_dec_val, 1000);
1188 if (chip->cl.final_cc_uah < min_dec_val) {
1189 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes below min limit %lld\n",
1190 chip->cl.final_cc_uah, min_dec_val);
1191 chip->cl.learned_cc_uah = min_dec_val;
1192 }
1193 }
1194
1195 rc = fg_save_learned_cap_to_sram(chip);
1196 if (rc < 0)
1197 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
1198
1199 fg_dbg(chip, FG_CAP_LEARN, "final cc_uah = %lld, learned capacity %lld -> %lld uah\n",
1200 chip->cl.final_cc_uah, old_cap, chip->cl.learned_cc_uah);
1201}
1202
1203static int fg_cap_learning_process_full_data(struct fg_chip *chip)
1204{
1205 int rc, cc_soc_sw, cc_soc_delta_pct;
1206 int64_t delta_cc_uah;
1207
1208 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1209 if (rc < 0) {
1210 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1211 return rc;
1212 }
1213
1214 cc_soc_delta_pct = DIV_ROUND_CLOSEST(
1215 abs(cc_soc_sw - chip->cl.init_cc_soc_sw) * 100,
1216 CC_SOC_30BIT);
1217 delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
1218 100);
1219 chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
1220 fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%d total_cc_uah=%lld\n",
1221 cc_soc_sw, cc_soc_delta_pct, chip->cl.final_cc_uah);
1222 return 0;
1223}
1224
1225static int fg_cap_learning_begin(struct fg_chip *chip, int batt_soc)
1226{
1227 int rc, cc_soc_sw;
1228
1229 if (DIV_ROUND_CLOSEST(batt_soc * 100, FULL_SOC_RAW) >
1230 chip->dt.cl_start_soc) {
1231 fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n",
1232 batt_soc);
1233 return -EINVAL;
1234 }
1235
1236 chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc,
1237 FULL_SOC_RAW);
1238 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1239 if (rc < 0) {
1240 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1241 return rc;
1242 }
1243
1244 chip->cl.init_cc_soc_sw = cc_soc_sw;
1245 chip->cl.active = true;
1246 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
1247 batt_soc, chip->cl.init_cc_soc_sw);
1248 return 0;
1249}
1250
1251static int fg_cap_learning_done(struct fg_chip *chip)
1252{
1253 int rc, cc_soc_sw;
1254
1255 rc = fg_cap_learning_process_full_data(chip);
1256 if (rc < 0) {
1257 pr_err("Error in processing cap learning full data, rc=%d\n",
1258 rc);
1259 goto out;
1260 }
1261
1262 /* Write a FULL value to cc_soc_sw */
1263 cc_soc_sw = CC_SOC_30BIT;
1264 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
1265 chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001266 chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001267 if (rc < 0) {
1268 pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
1269 goto out;
1270 }
1271
1272 fg_cap_learning_post_process(chip);
1273out:
1274 return rc;
1275}
1276
1277#define FULL_SOC_RAW 255
1278static void fg_cap_learning_update(struct fg_chip *chip)
1279{
1280 int rc, batt_soc;
1281
1282 mutex_lock(&chip->cl.lock);
1283
1284 if (!is_temp_valid_cap_learning(chip) || !chip->cl.learned_cc_uah ||
1285 chip->battery_missing) {
1286 fg_dbg(chip, FG_CAP_LEARN, "Aborting cap_learning %lld\n",
1287 chip->cl.learned_cc_uah);
1288 chip->cl.active = false;
1289 chip->cl.init_cc_uah = 0;
1290 goto out;
1291 }
1292
1293 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1294 if (rc < 0) {
1295 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
1296 goto out;
1297 }
1298
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001299 /* We need only the most significant byte here */
1300 batt_soc = (u32)batt_soc >> 24;
1301
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001302 fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n",
Nicholas Troast1769fd32016-09-07 09:20:58 -07001303 chip->charge_status, chip->cl.active, batt_soc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001304
1305 /* Initialize the starting point of learning capacity */
1306 if (!chip->cl.active) {
Nicholas Troast1769fd32016-09-07 09:20:58 -07001307 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001308 rc = fg_cap_learning_begin(chip, batt_soc);
1309 chip->cl.active = (rc == 0);
1310 }
1311
1312 } else {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001313 if (chip->charge_done) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001314 rc = fg_cap_learning_done(chip);
1315 if (rc < 0)
1316 pr_err("Error in completing capacity learning, rc=%d\n",
1317 rc);
1318
1319 chip->cl.active = false;
1320 chip->cl.init_cc_uah = 0;
1321 }
1322
Nicholas Troast1769fd32016-09-07 09:20:58 -07001323 if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001324 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
1325 batt_soc);
1326 chip->cl.active = false;
1327 chip->cl.init_cc_uah = 0;
1328 }
1329 }
1330
1331out:
1332 mutex_unlock(&chip->cl.lock);
1333}
1334
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001335#define KI_COEFF_MED_DISCHG_DEFAULT 1500
1336#define KI_COEFF_HI_DISCHG_DEFAULT 2200
1337static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
1338{
1339 int rc, i, msoc;
1340 int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
1341 int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
1342 u8 val;
1343
1344 if (!chip->ki_coeff_dischg_en)
1345 return 0;
1346
1347 rc = fg_get_prop_capacity(chip, &msoc);
1348 if (rc < 0) {
1349 pr_err("Error in getting capacity, rc=%d\n", rc);
1350 return rc;
1351 }
1352
Nicholas Troast1769fd32016-09-07 09:20:58 -07001353 if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001354 for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
1355 if (msoc < chip->dt.ki_coeff_soc[i]) {
1356 ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
1357 ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
1358 }
1359 }
1360 }
1361
1362 fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
1363 rc = fg_sram_write(chip,
1364 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
1365 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
1366 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
1367 FG_IMA_DEFAULT);
1368 if (rc < 0) {
1369 pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
1370 return rc;
1371 }
1372
1373 fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
1374 rc = fg_sram_write(chip,
1375 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
1376 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
1377 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
1378 FG_IMA_DEFAULT);
1379 if (rc < 0) {
1380 pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
1381 return rc;
1382 }
1383
1384 fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
1385 ki_coeff_med, ki_coeff_hi);
1386 return 0;
1387}
1388
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001389static int fg_charge_full_update(struct fg_chip *chip)
1390{
1391 union power_supply_propval prop = {0, };
1392 int rc, msoc, bsoc, recharge_soc;
1393 u8 full_soc[2] = {0xFF, 0xFF};
1394
1395 if (!chip->dt.hold_soc_while_full)
1396 return 0;
1397
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001398 if (!batt_psy_initialized(chip))
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001399 return 0;
1400
1401 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
1402 &prop);
1403 if (rc < 0) {
1404 pr_err("Error in getting battery health, rc=%d\n", rc);
1405 return rc;
1406 }
1407
1408 chip->health = prop.intval;
1409 recharge_soc = chip->dt.recharge_soc_thr;
1410 recharge_soc = DIV_ROUND_CLOSEST(recharge_soc * FULL_SOC_RAW,
1411 FULL_CAPACITY);
1412 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
1413 if (rc < 0) {
1414 pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
1415 return rc;
1416 }
1417
1418 /* We need 2 most significant bytes here */
1419 bsoc = (u32)bsoc >> 16;
1420 rc = fg_get_prop_capacity(chip, &msoc);
1421 if (rc < 0) {
1422 pr_err("Error in getting capacity, rc=%d\n", rc);
1423 return rc;
1424 }
1425
1426 fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc,
Nicholas Troast1769fd32016-09-07 09:20:58 -07001427 chip->health, chip->charge_status);
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001428 if (chip->charge_done) {
1429 if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD)
1430 chip->charge_full = true;
1431 else
1432 fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
1433 msoc);
1434 } else if ((bsoc >> 8) <= recharge_soc) {
1435 fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d\n",
1436 bsoc >> 8, recharge_soc);
1437 chip->charge_full = false;
1438 }
1439
1440 if (!chip->charge_full)
1441 return 0;
1442
1443 /*
1444 * During JEITA conditions, charge_full can happen early. FULL_SOC
1445 * and MONOTONIC_SOC needs to be updated to reflect the same. Write
1446 * battery SOC to FULL_SOC and write a full value to MONOTONIC_SOC.
1447 */
1448 rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET, (u8 *)&bsoc, 2,
1449 FG_IMA_ATOMIC);
1450 if (rc < 0) {
1451 pr_err("failed to write full_soc rc=%d\n", rc);
1452 return rc;
1453 }
1454
1455 rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
1456 full_soc, 2, FG_IMA_ATOMIC);
1457 if (rc < 0) {
1458 pr_err("failed to write monotonic_soc rc=%d\n", rc);
1459 return rc;
1460 }
1461
1462 fg_dbg(chip, FG_STATUS, "Set charge_full to true @ soc %d\n", msoc);
1463 return 0;
1464}
1465
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08001466#define RCONN_CONFIG_BIT BIT(0)
1467static int fg_rconn_config(struct fg_chip *chip)
1468{
1469 int rc, esr_uohms;
1470 u64 scaling_factor;
1471 u32 val = 0;
1472
1473 rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
1474 SW_CONFIG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1475 if (rc < 0) {
1476 pr_err("Error in reading SW_CONFIG_OFFSET, rc=%d\n", rc);
1477 return rc;
1478 }
1479
1480 if (val & RCONN_CONFIG_BIT) {
1481 fg_dbg(chip, FG_STATUS, "Rconn already configured: %x\n", val);
1482 return 0;
1483 }
1484
1485 rc = fg_get_battery_esr(chip, &esr_uohms);
1486 if (rc < 0) {
1487 pr_err("failed to get ESR, rc=%d\n", rc);
1488 return rc;
1489 }
1490
1491 scaling_factor = div64_u64((u64)esr_uohms * 1000,
1492 esr_uohms + (chip->dt.rconn_mohms * 1000));
1493
1494 rc = fg_sram_read(chip, ESR_RSLOW_CHG_WORD,
1495 ESR_RSLOW_CHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1496 if (rc < 0) {
1497 pr_err("Error in reading ESR_RSLOW_CHG_OFFSET, rc=%d\n", rc);
1498 return rc;
1499 }
1500
1501 val *= scaling_factor;
1502 do_div(val, 1000);
1503 rc = fg_sram_write(chip, ESR_RSLOW_CHG_WORD,
1504 ESR_RSLOW_CHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1505 if (rc < 0) {
1506 pr_err("Error in writing ESR_RSLOW_CHG_OFFSET, rc=%d\n", rc);
1507 return rc;
1508 }
1509 fg_dbg(chip, FG_STATUS, "esr_rslow_chg modified to %x\n", val & 0xFF);
1510
1511 rc = fg_sram_read(chip, ESR_RSLOW_DISCHG_WORD,
1512 ESR_RSLOW_DISCHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1513 if (rc < 0) {
1514 pr_err("Error in reading ESR_RSLOW_DISCHG_OFFSET, rc=%d\n", rc);
1515 return rc;
1516 }
1517
1518 val *= scaling_factor;
1519 do_div(val, 1000);
1520 rc = fg_sram_write(chip, ESR_RSLOW_DISCHG_WORD,
1521 ESR_RSLOW_DISCHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1522 if (rc < 0) {
1523 pr_err("Error in writing ESR_RSLOW_DISCHG_OFFSET, rc=%d\n", rc);
1524 return rc;
1525 }
1526 fg_dbg(chip, FG_STATUS, "esr_rslow_dischg modified to %x\n",
1527 val & 0xFF);
1528
1529 val = RCONN_CONFIG_BIT;
1530 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
1531 SW_CONFIG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1532 if (rc < 0) {
1533 pr_err("Error in writing SW_CONFIG_OFFSET, rc=%d\n", rc);
1534 return rc;
1535 }
1536
1537 return 0;
1538}
1539
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001540static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
1541{
1542 u8 buf[4];
1543 int rc;
1544
1545 fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf);
1546 rc = fg_sram_write(chip,
1547 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
1548 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, buf,
1549 chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
1550 if (rc < 0) {
1551 pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
1552 return rc;
1553 }
1554
1555 return 0;
1556}
1557
1558static int fg_adjust_recharge_soc(struct fg_chip *chip)
1559{
1560 int rc, msoc, recharge_soc, new_recharge_soc = 0;
1561
1562 recharge_soc = chip->dt.recharge_soc_thr;
1563 /*
1564 * If the input is present and charging had been terminated, adjust
1565 * the recharge SOC threshold based on the monotonic SOC at which
1566 * the charge termination had happened.
1567 */
1568 if (is_input_present(chip) && !chip->recharge_soc_adjusted
1569 && chip->charge_done) {
1570 /* Get raw monotonic SOC for calculation */
1571 rc = fg_get_msoc_raw(chip, &msoc);
1572 if (rc < 0) {
1573 pr_err("Error in getting msoc, rc=%d\n", rc);
1574 return rc;
1575 }
1576
1577 msoc = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
1578 /* Adjust the recharge_soc threshold */
1579 new_recharge_soc = msoc - (FULL_CAPACITY - recharge_soc);
1580 } else if (chip->recharge_soc_adjusted && (!is_input_present(chip)
1581 || chip->health == POWER_SUPPLY_HEALTH_GOOD)) {
1582 /* Restore the default value */
1583 new_recharge_soc = recharge_soc;
1584 }
1585
1586 if (new_recharge_soc > 0 && new_recharge_soc < FULL_CAPACITY) {
1587 rc = fg_set_recharge_soc(chip, new_recharge_soc);
1588 if (rc) {
1589 pr_err("Couldn't set resume SOC for FG, rc=%d\n", rc);
1590 return rc;
1591 }
1592
1593 chip->recharge_soc_adjusted = (new_recharge_soc !=
1594 recharge_soc);
1595 fg_dbg(chip, FG_STATUS, "resume soc set to %d\n",
1596 new_recharge_soc);
1597 }
1598
1599 return 0;
1600}
1601
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08001602static int fg_esr_filter_config(struct fg_chip *chip, int batt_temp)
1603{
1604 u8 esr_tight_lt_flt, esr_broad_lt_flt;
1605 bool cold_temp = false;
1606 int rc;
1607
1608 /*
1609 * If the battery temperature is lower than -20 C, then skip modifying
1610 * ESR filter.
1611 */
1612 if (batt_temp < -210)
1613 return 0;
1614
1615 /*
1616 * If battery temperature is lesser than 10 C (default), then apply the
1617 * normal ESR tight and broad filter values to ESR low temperature tight
1618 * and broad filters. If battery temperature is higher than 10 C, then
1619 * apply back the low temperature ESR filter coefficients to ESR low
1620 * temperature tight and broad filters.
1621 */
1622 if (batt_temp > chip->dt.esr_flt_switch_temp
1623 && chip->esr_flt_cold_temp_en) {
1624 fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
1625 chip->dt.esr_tight_lt_flt_upct, &esr_tight_lt_flt);
1626 fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
1627 chip->dt.esr_broad_lt_flt_upct, &esr_broad_lt_flt);
1628 } else if (batt_temp <= chip->dt.esr_flt_switch_temp
1629 && !chip->esr_flt_cold_temp_en) {
1630 fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
1631 chip->dt.esr_tight_flt_upct, &esr_tight_lt_flt);
1632 fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
1633 chip->dt.esr_broad_flt_upct, &esr_broad_lt_flt);
1634 cold_temp = true;
1635 } else {
1636 return 0;
1637 }
1638
1639 rc = fg_sram_write(chip, ESR_FILTER_WORD,
1640 ESR_UPD_TIGHT_LOW_TEMP_OFFSET, &esr_tight_lt_flt, 1,
1641 FG_IMA_DEFAULT);
1642 if (rc < 0) {
1643 pr_err("Error in writing ESR LT tight filter, rc=%d\n", rc);
1644 return rc;
1645 }
1646
1647 rc = fg_sram_write(chip, ESR_FILTER_WORD,
1648 ESR_UPD_BROAD_LOW_TEMP_OFFSET, &esr_broad_lt_flt, 1,
1649 FG_IMA_DEFAULT);
1650 if (rc < 0) {
1651 pr_err("Error in writing ESR LT broad filter, rc=%d\n", rc);
1652 return rc;
1653 }
1654
1655 chip->esr_flt_cold_temp_en = cold_temp;
1656 fg_dbg(chip, FG_STATUS, "applied %s ESR filter values\n",
1657 cold_temp ? "cold" : "normal");
1658 return 0;
1659}
1660
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001661static int fg_esr_fcc_config(struct fg_chip *chip)
1662{
1663 union power_supply_propval prop = {0, };
1664 int rc;
1665 bool parallel_en = false;
1666
1667 if (is_parallel_charger_available(chip)) {
1668 rc = power_supply_get_property(chip->parallel_psy,
1669 POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
1670 if (rc < 0) {
1671 pr_err("Error in reading charging_enabled from parallel_psy, rc=%d\n",
1672 rc);
1673 return rc;
1674 }
1675 parallel_en = prop.intval;
1676 }
1677
Nicholas Troast1769fd32016-09-07 09:20:58 -07001678 fg_dbg(chip, FG_POWER_SUPPLY, "charge_status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n",
1679 chip->charge_status, parallel_en, chip->esr_fcc_ctrl_en);
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001680
Nicholas Troast1769fd32016-09-07 09:20:58 -07001681 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
1682 parallel_en) {
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001683 if (chip->esr_fcc_ctrl_en)
1684 return 0;
1685
1686 /*
1687 * When parallel charging is enabled, configure ESR FCC to
1688 * 300mA to trigger an ESR pulse. Without this, FG can ask
1689 * the main charger to increase FCC when it is supposed to
1690 * decrease it.
1691 */
1692 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
1693 ESR_FAST_CRG_IVAL_MASK |
1694 ESR_FAST_CRG_CTL_EN_BIT,
1695 ESR_FCC_300MA | ESR_FAST_CRG_CTL_EN_BIT);
1696 if (rc < 0) {
1697 pr_err("Error in writing to %04x, rc=%d\n",
1698 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
1699 return rc;
1700 }
1701
1702 chip->esr_fcc_ctrl_en = true;
1703 } else {
1704 if (!chip->esr_fcc_ctrl_en)
1705 return 0;
1706
1707 /*
1708 * If we're here, then it means either the device is not in
1709 * charging state or parallel charging is disabled. Disable
1710 * ESR fast charge current control in SW.
1711 */
1712 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
1713 ESR_FAST_CRG_CTL_EN_BIT, 0);
1714 if (rc < 0) {
1715 pr_err("Error in writing to %04x, rc=%d\n",
1716 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
1717 return rc;
1718 }
1719
1720 chip->esr_fcc_ctrl_en = false;
1721 }
1722
1723 fg_dbg(chip, FG_STATUS, "esr_fcc_ctrl_en set to %d\n",
1724 chip->esr_fcc_ctrl_en);
1725 return 0;
1726}
1727
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -08001728static int fg_batt_missing_config(struct fg_chip *chip, bool enable)
1729{
1730 int rc;
1731
1732 rc = fg_masked_write(chip, BATT_INFO_BATT_MISS_CFG(chip),
1733 BM_FROM_BATT_ID_BIT, enable ? BM_FROM_BATT_ID_BIT : 0);
1734 if (rc < 0)
1735 pr_err("Error in writing to %04x, rc=%d\n",
1736 BATT_INFO_BATT_MISS_CFG(chip), rc);
1737 return rc;
1738}
1739
Nicholas Troast1769fd32016-09-07 09:20:58 -07001740static void fg_batt_avg_update(struct fg_chip *chip)
1741{
1742 if (chip->charge_status == chip->prev_charge_status)
1743 return;
1744
1745 cancel_delayed_work_sync(&chip->batt_avg_work);
1746 fg_circ_buf_clr(&chip->ibatt_circ_buf);
1747 fg_circ_buf_clr(&chip->vbatt_circ_buf);
1748
1749 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING ||
1750 chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)
1751 schedule_delayed_work(&chip->batt_avg_work,
1752 msecs_to_jiffies(2000));
1753}
1754
Nicholas Troaste29dec92016-08-24 09:35:11 -07001755static void status_change_work(struct work_struct *work)
1756{
1757 struct fg_chip *chip = container_of(work,
1758 struct fg_chip, status_change_work);
1759 union power_supply_propval prop = {0, };
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001760 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001761
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001762 if (!batt_psy_initialized(chip)) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001763 fg_dbg(chip, FG_STATUS, "Charger not available?!\n");
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001764 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001765 }
1766
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001767 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS,
Nicholas Troaste29dec92016-08-24 09:35:11 -07001768 &prop);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001769 if (rc < 0) {
1770 pr_err("Error in getting charging status, rc=%d\n", rc);
1771 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001772 }
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001773
Nicholas Troast1769fd32016-09-07 09:20:58 -07001774 chip->prev_charge_status = chip->charge_status;
1775 chip->charge_status = prop.intval;
1776 rc = power_supply_get_property(chip->batt_psy,
1777 POWER_SUPPLY_PROP_CHARGE_TYPE, &prop);
1778 if (rc < 0) {
1779 pr_err("Error in getting charge type, rc=%d\n", rc);
1780 goto out;
1781 }
1782
1783 chip->charge_type = prop.intval;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001784 rc = power_supply_get_property(chip->batt_psy,
1785 POWER_SUPPLY_PROP_CHARGE_DONE, &prop);
1786 if (rc < 0) {
1787 pr_err("Error in getting charge_done, rc=%d\n", rc);
1788 goto out;
1789 }
1790
1791 chip->charge_done = prop.intval;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001792 if (chip->cyc_ctr.en)
1793 schedule_work(&chip->cycle_count_work);
1794
1795 fg_cap_learning_update(chip);
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001796
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001797 rc = fg_charge_full_update(chip);
1798 if (rc < 0)
1799 pr_err("Error in charge_full_update, rc=%d\n", rc);
1800
1801 rc = fg_adjust_recharge_soc(chip);
1802 if (rc < 0)
1803 pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001804
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001805 rc = fg_adjust_ki_coeff_dischg(chip);
1806 if (rc < 0)
1807 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001808
1809 rc = fg_esr_fcc_config(chip);
1810 if (rc < 0)
1811 pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);
Nicholas Troast1769fd32016-09-07 09:20:58 -07001812
1813 fg_batt_avg_update(chip);
1814
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001815out:
Nicholas Troast1769fd32016-09-07 09:20:58 -07001816 fg_dbg(chip, FG_POWER_SUPPLY, "charge_status:%d charge_type:%d charge_done:%d\n",
1817 chip->charge_status, chip->charge_type, chip->charge_done);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001818 pm_relax(chip->dev);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001819}
1820
1821static void restore_cycle_counter(struct fg_chip *chip)
1822{
1823 int rc = 0, i;
1824 u8 data[2];
1825
1826 mutex_lock(&chip->cyc_ctr.lock);
1827 for (i = 0; i < BUCKET_COUNT; i++) {
1828 rc = fg_sram_read(chip, CYCLE_COUNT_WORD + (i / 2),
1829 CYCLE_COUNT_OFFSET + (i % 2) * 2, data, 2,
1830 FG_IMA_DEFAULT);
1831 if (rc < 0)
1832 pr_err("failed to read bucket %d rc=%d\n", i, rc);
1833 else
1834 chip->cyc_ctr.count[i] = data[0] | data[1] << 8;
1835 }
1836 mutex_unlock(&chip->cyc_ctr.lock);
1837}
1838
1839static void clear_cycle_counter(struct fg_chip *chip)
1840{
1841 int rc = 0, i;
1842
1843 if (!chip->cyc_ctr.en)
1844 return;
1845
1846 mutex_lock(&chip->cyc_ctr.lock);
1847 memset(chip->cyc_ctr.count, 0, sizeof(chip->cyc_ctr.count));
1848 for (i = 0; i < BUCKET_COUNT; i++) {
1849 chip->cyc_ctr.started[i] = false;
1850 chip->cyc_ctr.last_soc[i] = 0;
1851 }
1852 rc = fg_sram_write(chip, CYCLE_COUNT_WORD, CYCLE_COUNT_OFFSET,
1853 (u8 *)&chip->cyc_ctr.count,
1854 sizeof(chip->cyc_ctr.count) / sizeof(u8 *),
1855 FG_IMA_DEFAULT);
1856 if (rc < 0)
1857 pr_err("failed to clear cycle counter rc=%d\n", rc);
1858
1859 mutex_unlock(&chip->cyc_ctr.lock);
1860}
1861
1862static int fg_inc_store_cycle_ctr(struct fg_chip *chip, int bucket)
1863{
1864 int rc = 0;
1865 u16 cyc_count;
1866 u8 data[2];
1867
1868 if (bucket < 0 || (bucket > BUCKET_COUNT - 1))
1869 return 0;
1870
1871 cyc_count = chip->cyc_ctr.count[bucket];
1872 cyc_count++;
1873 data[0] = cyc_count & 0xFF;
1874 data[1] = cyc_count >> 8;
1875
1876 rc = fg_sram_write(chip, CYCLE_COUNT_WORD + (bucket / 2),
1877 CYCLE_COUNT_OFFSET + (bucket % 2) * 2, data, 2,
1878 FG_IMA_DEFAULT);
1879 if (rc < 0)
1880 pr_err("failed to write BATT_CYCLE[%d] rc=%d\n",
1881 bucket, rc);
1882 else
1883 chip->cyc_ctr.count[bucket] = cyc_count;
1884 return rc;
1885}
1886
1887static void cycle_count_work(struct work_struct *work)
1888{
1889 int rc = 0, bucket, i, batt_soc;
1890 struct fg_chip *chip = container_of(work,
1891 struct fg_chip,
1892 cycle_count_work);
1893
1894 mutex_lock(&chip->cyc_ctr.lock);
1895 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1896 if (rc < 0) {
1897 pr_err("Failed to read battery soc rc: %d\n", rc);
1898 goto out;
1899 }
1900
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001901 /* We need only the most significant byte here */
1902 batt_soc = (u32)batt_soc >> 24;
1903
Nicholas Troast1769fd32016-09-07 09:20:58 -07001904 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001905 /* Find out which bucket the SOC falls in */
1906 bucket = batt_soc / BUCKET_SOC_PCT;
1907 pr_debug("batt_soc: %d bucket: %d\n", batt_soc, bucket);
1908
1909 /*
1910 * If we've started counting for the previous bucket,
1911 * then store the counter for that bucket if the
1912 * counter for current bucket is getting started.
1913 */
1914 if (bucket > 0 && chip->cyc_ctr.started[bucket - 1] &&
1915 !chip->cyc_ctr.started[bucket]) {
1916 rc = fg_inc_store_cycle_ctr(chip, bucket - 1);
1917 if (rc < 0) {
1918 pr_err("Error in storing cycle_ctr rc: %d\n",
1919 rc);
1920 goto out;
1921 } else {
1922 chip->cyc_ctr.started[bucket - 1] = false;
1923 chip->cyc_ctr.last_soc[bucket - 1] = 0;
1924 }
1925 }
1926 if (!chip->cyc_ctr.started[bucket]) {
1927 chip->cyc_ctr.started[bucket] = true;
1928 chip->cyc_ctr.last_soc[bucket] = batt_soc;
1929 }
1930 } else {
1931 for (i = 0; i < BUCKET_COUNT; i++) {
1932 if (chip->cyc_ctr.started[i] &&
1933 batt_soc > chip->cyc_ctr.last_soc[i]) {
1934 rc = fg_inc_store_cycle_ctr(chip, i);
1935 if (rc < 0)
1936 pr_err("Error in storing cycle_ctr rc: %d\n",
1937 rc);
1938 chip->cyc_ctr.last_soc[i] = 0;
1939 }
1940 chip->cyc_ctr.started[i] = false;
1941 }
1942 }
1943out:
1944 mutex_unlock(&chip->cyc_ctr.lock);
1945}
1946
1947static int fg_get_cycle_count(struct fg_chip *chip)
1948{
1949 int count;
1950
1951 if (!chip->cyc_ctr.en)
1952 return 0;
1953
1954 if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT))
1955 return -EINVAL;
1956
1957 mutex_lock(&chip->cyc_ctr.lock);
1958 count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1];
1959 mutex_unlock(&chip->cyc_ctr.lock);
1960 return count;
1961}
1962
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001963#define PROFILE_LOAD_BIT BIT(0)
1964#define BOOTLOADER_LOAD_BIT BIT(1)
1965#define BOOTLOADER_RESTART_BIT BIT(2)
1966#define HLOS_RESTART_BIT BIT(3)
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001967static bool is_profile_load_required(struct fg_chip *chip)
1968{
Nicholas Troaste29dec92016-08-24 09:35:11 -07001969 u8 buf[PROFILE_COMP_LEN], val;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001970 bool profiles_same = false;
1971 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001972
Nicholas Troaste29dec92016-08-24 09:35:11 -07001973 rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
1974 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
1975 if (rc < 0) {
1976 pr_err("failed to read profile integrity rc=%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001977 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001978 }
1979
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001980 /* Check if integrity bit is set */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001981 if (val & PROFILE_LOAD_BIT) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001982 fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
1983 rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
1984 buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
1985 if (rc < 0) {
1986 pr_err("Error in reading battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001987 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001988 }
1989 profiles_same = memcmp(chip->batt_profile, buf,
1990 PROFILE_COMP_LEN) == 0;
1991 if (profiles_same) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001992 fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
1993 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001994 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001995
1996 if (!chip->dt.force_load_profile) {
1997 pr_warn("Profiles doesn't match, skipping loading it since force_load_profile is disabled\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08001998 if (fg_profile_dump) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001999 pr_info("FG: loaded profile:\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002000 dump_sram(buf, PROFILE_LOAD_WORD,
2001 PROFILE_COMP_LEN);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002002 pr_info("FG: available profile:\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002003 dump_sram(chip->batt_profile, PROFILE_LOAD_WORD,
2004 PROFILE_LEN);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002005 }
2006 return false;
2007 }
2008
2009 fg_dbg(chip, FG_STATUS, "Profiles are different, loading the correct one\n");
2010 } else {
2011 fg_dbg(chip, FG_STATUS, "Profile integrity bit is not set\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002012 if (fg_profile_dump) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002013 pr_info("FG: profile to be loaded:\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002014 dump_sram(chip->batt_profile, PROFILE_LOAD_WORD,
2015 PROFILE_LEN);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002016 }
Nicholas Troaste29dec92016-08-24 09:35:11 -07002017 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002018 return true;
2019}
2020
Subbaraman Narayanamurthy76cce8d2016-12-22 15:09:38 -08002021static void clear_battery_profile(struct fg_chip *chip)
2022{
2023 u8 val = 0;
2024 int rc;
2025
2026 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
2027 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
2028 if (rc < 0)
2029 pr_err("failed to write profile integrity rc=%d\n", rc);
2030}
2031
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002032#define SOC_READY_WAIT_MS 2000
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002033static int __fg_restart(struct fg_chip *chip)
2034{
2035 int rc, msoc;
2036 bool tried_again = false;
2037
2038 rc = fg_get_prop_capacity(chip, &msoc);
2039 if (rc < 0) {
2040 pr_err("Error in getting capacity, rc=%d\n", rc);
2041 return rc;
2042 }
2043
2044 chip->last_soc = msoc;
2045 chip->fg_restarting = true;
2046 reinit_completion(&chip->soc_ready);
2047 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT,
2048 RESTART_GO_BIT);
2049 if (rc < 0) {
2050 pr_err("Error in writing to %04x, rc=%d\n",
2051 BATT_SOC_RESTART(chip), rc);
2052 goto out;
2053 }
2054
2055wait:
2056 rc = wait_for_completion_interruptible_timeout(&chip->soc_ready,
2057 msecs_to_jiffies(SOC_READY_WAIT_MS));
2058
2059 /* If we were interrupted wait again one more time. */
2060 if (rc == -ERESTARTSYS && !tried_again) {
2061 tried_again = true;
2062 goto wait;
2063 } else if (rc <= 0) {
2064 pr_err("wait for soc_ready timed out rc=%d\n", rc);
2065 goto out;
2066 }
2067
2068 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
2069 if (rc < 0) {
2070 pr_err("Error in writing to %04x, rc=%d\n",
2071 BATT_SOC_RESTART(chip), rc);
2072 goto out;
2073 }
2074out:
2075 chip->fg_restarting = false;
2076 return rc;
2077}
2078
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002079static void profile_load_work(struct work_struct *work)
2080{
2081 struct fg_chip *chip = container_of(work,
2082 struct fg_chip,
2083 profile_load_work.work);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002084 u8 buf[2], val;
2085 int rc;
2086
2087 vote(chip->awake_votable, PROFILE_LOAD, true, 0);
2088 if (!is_profile_load_required(chip))
2089 goto done;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002090
2091 clear_cycle_counter(chip);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002092 mutex_lock(&chip->cl.lock);
2093 chip->cl.learned_cc_uah = 0;
2094 chip->cl.active = false;
2095 mutex_unlock(&chip->cl.lock);
2096
Nicholas Troaste29dec92016-08-24 09:35:11 -07002097 fg_dbg(chip, FG_STATUS, "profile loading started\n");
2098 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
2099 if (rc < 0) {
2100 pr_err("Error in writing to %04x, rc=%d\n",
2101 BATT_SOC_RESTART(chip), rc);
2102 goto out;
2103 }
2104
2105 /* load battery profile */
2106 rc = fg_sram_write(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
2107 chip->batt_profile, PROFILE_LEN, FG_IMA_ATOMIC);
2108 if (rc < 0) {
2109 pr_err("Error in writing battery profile, rc:%d\n", rc);
2110 goto out;
2111 }
2112
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002113 rc = __fg_restart(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002114 if (rc < 0) {
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002115 pr_err("Error in restarting FG, rc=%d\n", rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002116 goto out;
2117 }
2118
2119 fg_dbg(chip, FG_STATUS, "SOC is ready\n");
2120
2121 /* Set the profile integrity bit */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07002122 val = HLOS_RESTART_BIT | PROFILE_LOAD_BIT;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002123 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
2124 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
2125 if (rc < 0) {
2126 pr_err("failed to write profile integrity rc=%d\n", rc);
2127 goto out;
2128 }
2129
Nicholas Troaste29dec92016-08-24 09:35:11 -07002130done:
2131 rc = fg_sram_read(chip, NOM_CAP_WORD, NOM_CAP_OFFSET, buf, 2,
2132 FG_IMA_DEFAULT);
2133 if (rc < 0) {
2134 pr_err("Error in reading %04x[%d] rc=%d\n", NOM_CAP_WORD,
2135 NOM_CAP_OFFSET, rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002136 } else {
2137 chip->cl.nom_cap_uah = (int)(buf[0] | buf[1] << 8) * 1000;
2138 rc = fg_load_learned_cap_from_sram(chip);
2139 if (rc < 0)
2140 pr_err("Error in loading capacity learning data, rc:%d\n",
2141 rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002142 }
2143
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08002144 batt_psy_initialized(chip);
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07002145 fg_notify_charger(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002146 chip->profile_loaded = true;
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08002147 chip->soc_reporting_ready = true;
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002148 fg_dbg(chip, FG_STATUS, "profile loaded successfully");
Nicholas Troaste29dec92016-08-24 09:35:11 -07002149out:
2150 vote(chip->awake_votable, PROFILE_LOAD, false, 0);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002151}
2152
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002153static void sram_dump_work(struct work_struct *work)
2154{
2155 struct fg_chip *chip = container_of(work, struct fg_chip,
2156 sram_dump_work.work);
2157 u8 buf[FG_SRAM_LEN];
2158 int rc;
2159 s64 timestamp_ms;
2160
2161 rc = fg_sram_read(chip, 0, 0, buf, FG_SRAM_LEN, FG_IMA_DEFAULT);
2162 if (rc < 0) {
2163 pr_err("Error in reading FG SRAM, rc:%d\n", rc);
2164 goto resched;
2165 }
2166
2167 timestamp_ms = ktime_to_ms(ktime_get_boottime());
2168 fg_dbg(chip, FG_STATUS, "SRAM Dump Started at %lld.%lld\n",
2169 timestamp_ms / 1000, timestamp_ms % 1000);
2170 dump_sram(buf, 0, FG_SRAM_LEN);
2171 timestamp_ms = ktime_to_ms(ktime_get_boottime());
2172 fg_dbg(chip, FG_STATUS, "SRAM Dump done at %lld.%lld\n",
2173 timestamp_ms / 1000, timestamp_ms % 1000);
2174resched:
2175 schedule_delayed_work(&chip->sram_dump_work,
2176 msecs_to_jiffies(fg_sram_dump_period_ms));
2177}
2178
2179static int fg_sram_dump_sysfs(const char *val, const struct kernel_param *kp)
2180{
2181 int rc;
2182 struct power_supply *bms_psy;
2183 struct fg_chip *chip;
2184 bool old_val = fg_sram_dump;
2185
2186 rc = param_set_bool(val, kp);
2187 if (rc) {
2188 pr_err("Unable to set fg_sram_dump: %d\n", rc);
2189 return rc;
2190 }
2191
2192 if (fg_sram_dump == old_val)
2193 return 0;
2194
2195 bms_psy = power_supply_get_by_name("bms");
2196 if (!bms_psy) {
2197 pr_err("bms psy not found\n");
2198 return -ENODEV;
2199 }
2200
2201 chip = power_supply_get_drvdata(bms_psy);
2202 if (fg_sram_dump)
2203 schedule_delayed_work(&chip->sram_dump_work,
2204 msecs_to_jiffies(fg_sram_dump_period_ms));
2205 else
2206 cancel_delayed_work_sync(&chip->sram_dump_work);
2207
2208 return 0;
2209}
2210
2211static struct kernel_param_ops fg_sram_dump_ops = {
2212 .set = fg_sram_dump_sysfs,
2213 .get = param_get_bool,
2214};
2215
2216module_param_cb(sram_dump_en, &fg_sram_dump_ops, &fg_sram_dump, 0644);
2217
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002218static int fg_restart_sysfs(const char *val, const struct kernel_param *kp)
2219{
2220 int rc;
2221 struct power_supply *bms_psy;
2222 struct fg_chip *chip;
2223
2224 rc = param_set_int(val, kp);
2225 if (rc) {
2226 pr_err("Unable to set fg_restart: %d\n", rc);
2227 return rc;
2228 }
2229
2230 if (fg_restart != 1) {
2231 pr_err("Bad value %d\n", fg_restart);
2232 return -EINVAL;
2233 }
2234
2235 bms_psy = power_supply_get_by_name("bms");
2236 if (!bms_psy) {
2237 pr_err("bms psy not found\n");
2238 return 0;
2239 }
2240
2241 chip = power_supply_get_drvdata(bms_psy);
2242 rc = __fg_restart(chip);
2243 if (rc < 0) {
2244 pr_err("Error in restarting FG, rc=%d\n", rc);
2245 return rc;
2246 }
2247
2248 pr_info("FG restart done\n");
2249 return rc;
2250}
2251
2252static struct kernel_param_ops fg_restart_ops = {
2253 .set = fg_restart_sysfs,
2254 .get = param_get_int,
2255};
2256
2257module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
2258
Nicholas Troast1769fd32016-09-07 09:20:58 -07002259#define BATT_AVG_POLL_PERIOD_MS 10000
2260static void batt_avg_work(struct work_struct *work)
2261{
2262 struct fg_chip *chip = container_of(work, struct fg_chip,
2263 batt_avg_work.work);
2264 int rc, ibatt_now, vbatt_now;
2265
2266 mutex_lock(&chip->batt_avg_lock);
2267 rc = fg_get_battery_current(chip, &ibatt_now);
2268 if (rc < 0) {
2269 pr_err("failed to get battery current, rc=%d\n", rc);
2270 goto reschedule;
2271 }
2272
2273 rc = fg_get_battery_voltage(chip, &vbatt_now);
2274 if (rc < 0) {
2275 pr_err("failed to get battery voltage, rc=%d\n", rc);
2276 goto reschedule;
2277 }
2278
2279 fg_circ_buf_add(&chip->ibatt_circ_buf, ibatt_now);
2280 fg_circ_buf_add(&chip->vbatt_circ_buf, vbatt_now);
2281
2282reschedule:
2283 mutex_unlock(&chip->batt_avg_lock);
2284 schedule_delayed_work(&chip->batt_avg_work,
2285 msecs_to_jiffies(BATT_AVG_POLL_PERIOD_MS));
2286}
2287
Nicholas Troast1769fd32016-09-07 09:20:58 -07002288#define HOURS_TO_SECONDS 3600
2289#define OCV_SLOPE_UV 10869
2290#define MILLI_UNIT 1000
2291#define MICRO_UNIT 1000000
2292static int fg_get_time_to_full(struct fg_chip *chip, int *val)
2293{
2294 int rc, ibatt_avg, vbatt_avg, rbatt, msoc, ocv_cc2cv, full_soc,
2295 act_cap_uah;
Nicholas Troastde5d42f2017-01-20 16:47:31 -08002296 s32 i_cc2cv, soc_cc2cv, ln_val, centi_tau_scale;
Nicholas Troast1769fd32016-09-07 09:20:58 -07002297 s64 t_predicted_cc = 0, t_predicted_cv = 0;
2298
2299 if (chip->bp.float_volt_uv <= 0) {
2300 pr_err("battery profile is not loaded\n");
2301 return -ENODATA;
2302 }
2303
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08002304 if (!batt_psy_initialized(chip)) {
Nicholas Troast1769fd32016-09-07 09:20:58 -07002305 fg_dbg(chip, FG_TTF, "charger is not available\n");
2306 return -ENODATA;
2307 }
2308
Nicholas Troast32a22d32016-12-14 16:12:04 -08002309 rc = fg_get_prop_capacity(chip, &msoc);
2310 if (rc < 0) {
2311 pr_err("failed to get msoc rc=%d\n", rc);
2312 return rc;
2313 }
2314 fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc);
2315
2316 if (msoc >= 100) {
Nicholas Troast1769fd32016-09-07 09:20:58 -07002317 *val = 0;
2318 return 0;
2319 }
2320
2321 mutex_lock(&chip->batt_avg_lock);
2322 rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg);
2323 if (rc < 0) {
2324 /* try to get instantaneous current */
2325 rc = fg_get_battery_current(chip, &ibatt_avg);
2326 if (rc < 0) {
2327 mutex_unlock(&chip->batt_avg_lock);
2328 pr_err("failed to get battery current, rc=%d\n", rc);
2329 return rc;
2330 }
2331 }
2332
2333 rc = fg_circ_buf_avg(&chip->vbatt_circ_buf, &vbatt_avg);
2334 if (rc < 0) {
2335 /* try to get instantaneous voltage */
2336 rc = fg_get_battery_voltage(chip, &vbatt_avg);
2337 if (rc < 0) {
2338 mutex_unlock(&chip->batt_avg_lock);
2339 pr_err("failed to get battery voltage, rc=%d\n", rc);
2340 return rc;
2341 }
2342 }
2343
2344 mutex_unlock(&chip->batt_avg_lock);
2345 fg_dbg(chip, FG_TTF, "vbatt_avg=%d\n", vbatt_avg);
2346
2347 /* clamp ibatt_avg to -150mA */
2348 if (ibatt_avg > -150000)
2349 ibatt_avg = -150000;
2350 fg_dbg(chip, FG_TTF, "ibatt_avg=%d\n", ibatt_avg);
2351
2352 /* reverse polarity to be consistent with unsigned current settings */
2353 ibatt_avg = abs(ibatt_avg);
2354
2355 /* estimated battery current at the CC to CV transition */
2356 i_cc2cv = div_s64((s64)ibatt_avg * vbatt_avg, chip->bp.float_volt_uv);
2357 fg_dbg(chip, FG_TTF, "i_cc2cv=%d\n", i_cc2cv);
2358
2359 rc = fg_get_battery_resistance(chip, &rbatt);
2360 if (rc < 0) {
2361 pr_err("failed to get battery resistance rc=%d\n", rc);
2362 return rc;
2363 }
2364
2365 /* clamp rbatt to 50mOhms */
2366 if (rbatt < 50000)
2367 rbatt = 50000;
2368
2369 fg_dbg(chip, FG_TTF, "rbatt=%d\n", rbatt);
2370
2371 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah);
2372 if (rc < 0) {
2373 pr_err("failed to get ACT_BATT_CAP rc=%d\n", rc);
2374 return rc;
2375 }
2376 act_cap_uah *= MILLI_UNIT;
2377 fg_dbg(chip, FG_TTF, "actual_capacity_uah=%d\n", act_cap_uah);
2378
Nicholas Troast1769fd32016-09-07 09:20:58 -07002379 rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc);
2380 if (rc < 0) {
2381 pr_err("failed to get full soc rc=%d\n", rc);
2382 return rc;
2383 }
2384 full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY,
2385 FULL_SOC_RAW);
2386 fg_dbg(chip, FG_TTF, "full_soc=%d\n", full_soc);
2387
2388 /* if we are already in CV state then we can skip estimating CC */
2389 if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
2390 goto skip_cc_estimate;
2391
2392 /* if the charger is current limited then use power approximation */
2393 if (ibatt_avg > chip->bp.fastchg_curr_ma * MILLI_UNIT - 50000)
2394 ocv_cc2cv = div_s64((s64)rbatt * ibatt_avg, MICRO_UNIT);
2395 else
2396 ocv_cc2cv = div_s64((s64)rbatt * i_cc2cv, MICRO_UNIT);
2397 ocv_cc2cv = chip->bp.float_volt_uv - ocv_cc2cv;
2398 fg_dbg(chip, FG_TTF, "ocv_cc2cv=%d\n", ocv_cc2cv);
2399
2400 soc_cc2cv = div_s64(chip->bp.float_volt_uv - ocv_cc2cv, OCV_SLOPE_UV);
2401 /* estimated SOC at the CC to CV transition */
2402 soc_cc2cv = 100 - soc_cc2cv;
2403 fg_dbg(chip, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv);
2404
2405 /* the esimated SOC may be lower than the current SOC */
2406 if (soc_cc2cv - msoc <= 0)
2407 goto skip_cc_estimate;
2408
2409 t_predicted_cc = div_s64((s64)full_soc * act_cap_uah, 100);
2410 t_predicted_cc = div_s64(t_predicted_cc * (soc_cc2cv - msoc), 100);
2411 t_predicted_cc *= HOURS_TO_SECONDS;
2412 t_predicted_cc = div_s64(t_predicted_cc, (ibatt_avg + i_cc2cv) / 2);
2413
2414skip_cc_estimate:
2415 fg_dbg(chip, FG_TTF, "t_predicted_cc=%lld\n", t_predicted_cc);
2416
2417 /* CV estimate starts here */
Nicholas Troast32a22d32016-12-14 16:12:04 -08002418 if (chip->charge_type >= POWER_SUPPLY_CHARGE_TYPE_TAPER)
Nicholas Troastde5d42f2017-01-20 16:47:31 -08002419 ln_val = ibatt_avg / (abs(chip->dt.sys_term_curr_ma) + 200);
Nicholas Troast1769fd32016-09-07 09:20:58 -07002420 else
Nicholas Troastde5d42f2017-01-20 16:47:31 -08002421 ln_val = i_cc2cv / (abs(chip->dt.sys_term_curr_ma) + 200);
2422
2423 if (msoc < 95)
2424 centi_tau_scale = 100;
2425 else
2426 centi_tau_scale = 20 * (100 - msoc);
Nicholas Troast1769fd32016-09-07 09:20:58 -07002427
2428 fg_dbg(chip, FG_TTF, "ln_in=%d\n", ln_val);
2429 rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), ln_val, &ln_val);
2430 fg_dbg(chip, FG_TTF, "ln_out=%d\n", ln_val);
2431 t_predicted_cv = div_s64((s64)act_cap_uah * rbatt, MICRO_UNIT);
Nicholas Troastde5d42f2017-01-20 16:47:31 -08002432 t_predicted_cv = div_s64(t_predicted_cv * centi_tau_scale, 100);
Nicholas Troast1769fd32016-09-07 09:20:58 -07002433 t_predicted_cv = div_s64(t_predicted_cv * ln_val, MILLI_UNIT);
2434 t_predicted_cv = div_s64(t_predicted_cv * HOURS_TO_SECONDS, MICRO_UNIT);
2435 fg_dbg(chip, FG_TTF, "t_predicted_cv=%lld\n", t_predicted_cv);
2436 *val = t_predicted_cc + t_predicted_cv;
2437 return 0;
2438}
2439
2440#define CENTI_ICORRECT_C0 105
2441#define CENTI_ICORRECT_C1 20
2442static int fg_get_time_to_empty(struct fg_chip *chip, int *val)
2443{
2444 int rc, ibatt_avg, msoc, act_cap_uah;
2445 s32 divisor;
2446 s64 t_predicted;
2447
2448 rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg);
2449 if (rc < 0) {
2450 /* try to get instantaneous current */
2451 rc = fg_get_battery_current(chip, &ibatt_avg);
2452 if (rc < 0) {
2453 pr_err("failed to get battery current, rc=%d\n", rc);
2454 return rc;
2455 }
2456 }
2457
2458 /* clamp ibatt_avg to 150mA */
2459 if (ibatt_avg < 150000)
2460 ibatt_avg = 150000;
2461
2462 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah);
2463 if (rc < 0) {
2464 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
2465 return rc;
2466 }
2467 act_cap_uah *= MILLI_UNIT;
2468
2469 rc = fg_get_prop_capacity(chip, &msoc);
2470 if (rc < 0) {
2471 pr_err("Error in getting capacity, rc=%d\n", rc);
2472 return rc;
2473 }
2474
2475 t_predicted = div_s64((s64)msoc * act_cap_uah, 100);
2476 t_predicted *= HOURS_TO_SECONDS;
2477 divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc;
2478 divisor = div_s64((s64)divisor * ibatt_avg, 10000);
2479 if (divisor > 0)
2480 t_predicted = div_s64(t_predicted, divisor);
2481
2482 *val = t_predicted;
2483 return 0;
2484}
2485
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002486/* PSY CALLBACKS STAY HERE */
2487
2488static int fg_psy_get_property(struct power_supply *psy,
2489 enum power_supply_property psp,
2490 union power_supply_propval *pval)
2491{
2492 struct fg_chip *chip = power_supply_get_drvdata(psy);
2493 int rc = 0;
2494
2495 switch (psp) {
2496 case POWER_SUPPLY_PROP_CAPACITY:
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002497 if (chip->fg_restarting)
2498 pval->intval = chip->last_soc;
2499 else
2500 rc = fg_get_prop_capacity(chip, &pval->intval);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002501 break;
2502 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2503 rc = fg_get_battery_voltage(chip, &pval->intval);
2504 break;
2505 case POWER_SUPPLY_PROP_CURRENT_NOW:
2506 rc = fg_get_battery_current(chip, &pval->intval);
2507 break;
2508 case POWER_SUPPLY_PROP_TEMP:
2509 rc = fg_get_battery_temp(chip, &pval->intval);
2510 break;
2511 case POWER_SUPPLY_PROP_RESISTANCE:
2512 rc = fg_get_battery_resistance(chip, &pval->intval);
2513 break;
2514 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2515 rc = fg_get_sram_prop(chip, FG_SRAM_OCV, &pval->intval);
2516 break;
2517 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002518 pval->intval = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002519 break;
2520 case POWER_SUPPLY_PROP_RESISTANCE_ID:
Subbaraman Narayanamurthy76cce8d2016-12-22 15:09:38 -08002521 pval->intval = chip->batt_id_ohms;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002522 break;
2523 case POWER_SUPPLY_PROP_BATTERY_TYPE:
2524 pval->strval = fg_get_battery_type(chip);
2525 break;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07002526 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2527 pval->intval = chip->bp.float_volt_uv;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07002528 break;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002529 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2530 pval->intval = fg_get_cycle_count(chip);
2531 break;
2532 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
2533 pval->intval = chip->cyc_ctr.id;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07002534 break;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002535 case POWER_SUPPLY_PROP_CHARGE_NOW_RAW:
2536 rc = fg_get_cc_soc(chip, &pval->intval);
2537 break;
2538 case POWER_SUPPLY_PROP_CHARGE_NOW:
2539 pval->intval = chip->cl.init_cc_uah;
2540 break;
2541 case POWER_SUPPLY_PROP_CHARGE_FULL:
2542 pval->intval = chip->cl.learned_cc_uah;
2543 break;
2544 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
2545 rc = fg_get_cc_soc_sw(chip, &pval->intval);
2546 break;
Nicholas Troast1769fd32016-09-07 09:20:58 -07002547 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
2548 rc = fg_get_time_to_full(chip, &pval->intval);
2549 break;
2550 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
2551 rc = fg_get_time_to_empty(chip, &pval->intval);
2552 break;
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08002553 case POWER_SUPPLY_PROP_SOC_REPORTING_READY:
2554 pval->intval = chip->soc_reporting_ready;
2555 break;
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05302556 case POWER_SUPPLY_PROP_DEBUG_BATTERY:
2557 pval->intval = is_debug_batt_id(chip);
2558 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002559 default:
Nicholas Troast1769fd32016-09-07 09:20:58 -07002560 pr_err("unsupported property %d\n", psp);
2561 rc = -EINVAL;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002562 break;
2563 }
2564
Nicholas Troast1769fd32016-09-07 09:20:58 -07002565 if (rc < 0)
2566 return -ENODATA;
2567
2568 return 0;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002569}
2570
2571static int fg_psy_set_property(struct power_supply *psy,
2572 enum power_supply_property psp,
2573 const union power_supply_propval *pval)
2574{
Nicholas Troaste29dec92016-08-24 09:35:11 -07002575 struct fg_chip *chip = power_supply_get_drvdata(psy);
2576
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002577 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002578 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
2579 if ((pval->intval > 0) && (pval->intval <= BUCKET_COUNT)) {
2580 chip->cyc_ctr.id = pval->intval;
2581 } else {
2582 pr_err("rejecting invalid cycle_count_id = %d\n",
2583 pval->intval);
2584 return -EINVAL;
2585 }
2586 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002587 default:
2588 break;
2589 }
2590
2591 return 0;
2592}
2593
2594static int fg_property_is_writeable(struct power_supply *psy,
2595 enum power_supply_property psp)
2596{
2597 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002598 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
2599 return 1;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002600 default:
2601 break;
2602 }
2603
2604 return 0;
2605}
2606
2607static void fg_external_power_changed(struct power_supply *psy)
2608{
2609 pr_debug("power supply changed\n");
2610}
2611
2612static int fg_notifier_cb(struct notifier_block *nb,
2613 unsigned long event, void *data)
2614{
2615 struct power_supply *psy = data;
2616 struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
2617
2618 if (event != PSY_EVENT_PROP_CHANGED)
2619 return NOTIFY_OK;
2620
Subbaraman Narayanamurthy58dac182016-12-06 14:41:29 -08002621 if (work_pending(&chip->status_change_work))
2622 return NOTIFY_OK;
2623
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002624 if ((strcmp(psy->desc->name, "battery") == 0)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002625 || (strcmp(psy->desc->name, "usb") == 0)) {
2626 /*
2627 * We cannot vote for awake votable here as that takes
2628 * a mutex lock and this is executed in an atomic context.
2629 */
2630 pm_stay_awake(chip->dev);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002631 schedule_work(&chip->status_change_work);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002632 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002633
2634 return NOTIFY_OK;
2635}
2636
2637static enum power_supply_property fg_psy_props[] = {
2638 POWER_SUPPLY_PROP_CAPACITY,
2639 POWER_SUPPLY_PROP_TEMP,
2640 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2641 POWER_SUPPLY_PROP_VOLTAGE_OCV,
2642 POWER_SUPPLY_PROP_CURRENT_NOW,
2643 POWER_SUPPLY_PROP_RESISTANCE_ID,
2644 POWER_SUPPLY_PROP_RESISTANCE,
2645 POWER_SUPPLY_PROP_BATTERY_TYPE,
2646 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07002647 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Nicholas Troaste29dec92016-08-24 09:35:11 -07002648 POWER_SUPPLY_PROP_CYCLE_COUNT,
2649 POWER_SUPPLY_PROP_CYCLE_COUNT_ID,
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002650 POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
2651 POWER_SUPPLY_PROP_CHARGE_NOW,
2652 POWER_SUPPLY_PROP_CHARGE_FULL,
2653 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Nicholas Troast1769fd32016-09-07 09:20:58 -07002654 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
2655 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08002656 POWER_SUPPLY_PROP_SOC_REPORTING_READY,
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05302657 POWER_SUPPLY_PROP_DEBUG_BATTERY,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002658};
2659
2660static const struct power_supply_desc fg_psy_desc = {
2661 .name = "bms",
2662 .type = POWER_SUPPLY_TYPE_BMS,
2663 .properties = fg_psy_props,
2664 .num_properties = ARRAY_SIZE(fg_psy_props),
2665 .get_property = fg_psy_get_property,
2666 .set_property = fg_psy_set_property,
2667 .external_power_changed = fg_external_power_changed,
2668 .property_is_writeable = fg_property_is_writeable,
2669};
2670
2671/* INIT FUNCTIONS STAY HERE */
2672
2673static int fg_hw_init(struct fg_chip *chip)
2674{
2675 int rc;
2676 u8 buf[4], val;
2677
2678 fg_encode(chip->sp, FG_SRAM_CUTOFF_VOLT, chip->dt.cutoff_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002679 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CUTOFF_VOLT].addr_word,
2680 chip->sp[FG_SRAM_CUTOFF_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002681 chip->sp[FG_SRAM_CUTOFF_VOLT].len, FG_IMA_DEFAULT);
2682 if (rc < 0) {
2683 pr_err("Error in writing cutoff_volt, rc=%d\n", rc);
2684 return rc;
2685 }
2686
2687 fg_encode(chip->sp, FG_SRAM_EMPTY_VOLT, chip->dt.empty_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002688 rc = fg_sram_write(chip, chip->sp[FG_SRAM_EMPTY_VOLT].addr_word,
2689 chip->sp[FG_SRAM_EMPTY_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002690 chip->sp[FG_SRAM_EMPTY_VOLT].len, FG_IMA_DEFAULT);
2691 if (rc < 0) {
2692 pr_err("Error in writing empty_volt, rc=%d\n", rc);
2693 return rc;
2694 }
2695
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08002696 /* This SRAM register is only present in v2.0 and above */
Ashay Jaiswal63d486e2016-12-07 11:21:32 +05302697 if (!(chip->wa_flags & PMI8998_V1_REV_WA) &&
2698 chip->bp.float_volt_uv > 0) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002699 fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT,
2700 chip->bp.float_volt_uv / 1000, buf);
2701 rc = fg_sram_write(chip, chip->sp[FG_SRAM_FLOAT_VOLT].addr_word,
2702 chip->sp[FG_SRAM_FLOAT_VOLT].addr_byte, buf,
2703 chip->sp[FG_SRAM_FLOAT_VOLT].len, FG_IMA_DEFAULT);
2704 if (rc < 0) {
2705 pr_err("Error in writing float_volt, rc=%d\n", rc);
2706 return rc;
2707 }
2708 }
2709
2710 if (chip->bp.vbatt_full_mv > 0) {
2711 fg_encode(chip->sp, FG_SRAM_VBATT_FULL, chip->bp.vbatt_full_mv,
2712 buf);
2713 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_FULL].addr_word,
2714 chip->sp[FG_SRAM_VBATT_FULL].addr_byte, buf,
2715 chip->sp[FG_SRAM_VBATT_FULL].len, FG_IMA_DEFAULT);
2716 if (rc < 0) {
2717 pr_err("Error in writing vbatt_full, rc=%d\n", rc);
2718 return rc;
2719 }
2720 }
2721
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002722 fg_encode(chip->sp, FG_SRAM_CHG_TERM_CURR, chip->dt.chg_term_curr_ma,
2723 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002724 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CHG_TERM_CURR].addr_word,
2725 chip->sp[FG_SRAM_CHG_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002726 chip->sp[FG_SRAM_CHG_TERM_CURR].len, FG_IMA_DEFAULT);
2727 if (rc < 0) {
2728 pr_err("Error in writing chg_term_curr, rc=%d\n", rc);
2729 return rc;
2730 }
2731
2732 fg_encode(chip->sp, FG_SRAM_SYS_TERM_CURR, chip->dt.sys_term_curr_ma,
2733 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002734 rc = fg_sram_write(chip, chip->sp[FG_SRAM_SYS_TERM_CURR].addr_word,
2735 chip->sp[FG_SRAM_SYS_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002736 chip->sp[FG_SRAM_SYS_TERM_CURR].len, FG_IMA_DEFAULT);
2737 if (rc < 0) {
2738 pr_err("Error in writing sys_term_curr, rc=%d\n", rc);
2739 return rc;
2740 }
2741
2742 if (chip->dt.vbatt_low_thr_mv > 0) {
2743 fg_encode(chip->sp, FG_SRAM_VBATT_LOW,
2744 chip->dt.vbatt_low_thr_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002745 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_LOW].addr_word,
2746 chip->sp[FG_SRAM_VBATT_LOW].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002747 chip->sp[FG_SRAM_VBATT_LOW].len,
2748 FG_IMA_DEFAULT);
2749 if (rc < 0) {
2750 pr_err("Error in writing vbatt_low_thr, rc=%d\n", rc);
2751 return rc;
2752 }
2753 }
2754
2755 if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) {
2756 fg_encode(chip->sp, FG_SRAM_DELTA_SOC_THR,
2757 chip->dt.delta_soc_thr, buf);
2758 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -07002759 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_word,
2760 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002761 buf, chip->sp[FG_SRAM_DELTA_SOC_THR].len,
2762 FG_IMA_DEFAULT);
2763 if (rc < 0) {
2764 pr_err("Error in writing delta_soc_thr, rc=%d\n", rc);
2765 return rc;
2766 }
2767 }
2768
2769 if (chip->dt.recharge_soc_thr > 0 && chip->dt.recharge_soc_thr < 100) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002770 rc = fg_set_recharge_soc(chip, chip->dt.recharge_soc_thr);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002771 if (rc < 0) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002772 pr_err("Error in setting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002773 return rc;
2774 }
2775 }
2776
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08002777 /* This configuration is available only for pmicobalt v2.0 and above */
Ashay Jaiswal63d486e2016-12-07 11:21:32 +05302778 if (!(chip->wa_flags & PMI8998_V1_REV_WA) &&
2779 chip->dt.recharge_volt_thr_mv > 0) {
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08002780 fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR,
2781 chip->dt.recharge_volt_thr_mv, buf);
2782 rc = fg_sram_write(chip,
2783 chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word,
2784 chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte,
2785 buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len,
2786 FG_IMA_DEFAULT);
2787 if (rc < 0) {
2788 pr_err("Error in writing recharge_vbatt_thr, rc=%d\n",
2789 rc);
2790 return rc;
2791 }
2792 }
2793
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002794 if (chip->dt.rsense_sel >= SRC_SEL_BATFET &&
2795 chip->dt.rsense_sel < SRC_SEL_RESERVED) {
2796 rc = fg_masked_write(chip, BATT_INFO_IBATT_SENSING_CFG(chip),
2797 SOURCE_SELECT_MASK, chip->dt.rsense_sel);
2798 if (rc < 0) {
2799 pr_err("Error in writing rsense_sel, rc=%d\n", rc);
2800 return rc;
2801 }
2802 }
2803
2804 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COLD], &val);
2805 rc = fg_write(chip, BATT_INFO_JEITA_TOO_COLD(chip), &val, 1);
2806 if (rc < 0) {
2807 pr_err("Error in writing jeita_cold, rc=%d\n", rc);
2808 return rc;
2809 }
2810
2811 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COOL], &val);
2812 rc = fg_write(chip, BATT_INFO_JEITA_COLD(chip), &val, 1);
2813 if (rc < 0) {
2814 pr_err("Error in writing jeita_cool, rc=%d\n", rc);
2815 return rc;
2816 }
2817
2818 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_WARM], &val);
2819 rc = fg_write(chip, BATT_INFO_JEITA_HOT(chip), &val, 1);
2820 if (rc < 0) {
2821 pr_err("Error in writing jeita_warm, rc=%d\n", rc);
2822 return rc;
2823 }
2824
2825 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_HOT], &val);
2826 rc = fg_write(chip, BATT_INFO_JEITA_TOO_HOT(chip), &val, 1);
2827 if (rc < 0) {
2828 pr_err("Error in writing jeita_hot, rc=%d\n", rc);
2829 return rc;
2830 }
2831
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002832 if (chip->dt.esr_timer_charging > 0) {
2833 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_charging, true,
2834 FG_IMA_DEFAULT);
2835 if (rc < 0) {
2836 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2837 return rc;
2838 }
2839 }
2840
2841 if (chip->dt.esr_timer_awake > 0) {
2842 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
2843 FG_IMA_DEFAULT);
2844 if (rc < 0) {
2845 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2846 return rc;
2847 }
2848 }
2849
Nicholas Troaste29dec92016-08-24 09:35:11 -07002850 if (chip->cyc_ctr.en)
2851 restore_cycle_counter(chip);
2852
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002853 if (chip->dt.jeita_hyst_temp >= 0) {
2854 val = chip->dt.jeita_hyst_temp << JEITA_TEMP_HYST_SHIFT;
2855 rc = fg_masked_write(chip, BATT_INFO_BATT_TEMP_CFG(chip),
2856 JEITA_TEMP_HYST_MASK, val);
2857 if (rc < 0) {
2858 pr_err("Error in writing batt_temp_cfg, rc=%d\n", rc);
2859 return rc;
2860 }
2861 }
2862
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002863 get_batt_temp_delta(chip->dt.batt_temp_delta, &val);
2864 rc = fg_masked_write(chip, BATT_INFO_BATT_TMPR_INTR(chip),
2865 CHANGE_THOLD_MASK, val);
2866 if (rc < 0) {
2867 pr_err("Error in writing batt_temp_delta, rc=%d\n", rc);
2868 return rc;
2869 }
2870
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08002871 if (chip->dt.rconn_mohms > 0) {
2872 rc = fg_rconn_config(chip);
2873 if (rc < 0) {
2874 pr_err("Error in configuring Rconn, rc=%d\n", rc);
2875 return rc;
2876 }
2877 }
2878
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08002879 fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
2880 chip->dt.esr_tight_flt_upct, buf);
2881 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_word,
2882 chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_byte, buf,
2883 chip->sp[FG_SRAM_ESR_TIGHT_FILTER].len, FG_IMA_DEFAULT);
2884 if (rc < 0) {
2885 pr_err("Error in writing ESR tight filter, rc=%d\n", rc);
2886 return rc;
2887 }
2888
2889 fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
2890 chip->dt.esr_broad_flt_upct, buf);
2891 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_word,
2892 chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_byte, buf,
2893 chip->sp[FG_SRAM_ESR_BROAD_FILTER].len, FG_IMA_DEFAULT);
2894 if (rc < 0) {
2895 pr_err("Error in writing ESR broad filter, rc=%d\n", rc);
2896 return rc;
2897 }
2898
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002899 return 0;
2900}
2901
2902static int fg_memif_init(struct fg_chip *chip)
2903{
2904 return fg_ima_init(chip);
2905}
2906
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002907/* INTERRUPT HANDLERS STAY HERE */
2908
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07002909static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
2910{
2911 struct fg_chip *chip = data;
2912 u8 status;
2913 int rc;
2914
2915 rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1);
2916 if (rc < 0) {
2917 pr_err("failed to read addr=0x%04x, rc=%d\n",
2918 MEM_IF_INT_RT_STS(chip), rc);
2919 return IRQ_HANDLED;
2920 }
2921
2922 fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status);
2923 if (status & MEM_XCP_BIT) {
2924 rc = fg_clear_dma_errors_if_any(chip);
2925 if (rc < 0) {
2926 pr_err("Error in clearing DMA error, rc=%d\n", rc);
2927 return IRQ_HANDLED;
2928 }
2929
2930 mutex_lock(&chip->sram_rw_lock);
2931 rc = fg_clear_ima_errors_if_any(chip, true);
2932 if (rc < 0 && rc != -EAGAIN)
2933 pr_err("Error in checking IMA errors rc:%d\n", rc);
2934 mutex_unlock(&chip->sram_rw_lock);
2935 }
2936
2937 return IRQ_HANDLED;
2938}
2939
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002940static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
2941{
2942 struct fg_chip *chip = data;
2943
2944 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2945 return IRQ_HANDLED;
2946}
2947
2948static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
2949{
2950 struct fg_chip *chip = data;
2951 u8 status;
2952 int rc;
2953
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002954 rc = fg_read(chip, BATT_INFO_INT_RT_STS(chip), &status, 1);
2955 if (rc < 0) {
2956 pr_err("failed to read addr=0x%04x, rc=%d\n",
2957 BATT_INFO_INT_RT_STS(chip), rc);
2958 return IRQ_HANDLED;
2959 }
2960
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -08002961 fg_dbg(chip, FG_IRQ, "irq %d triggered sts:%d\n", irq, status);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002962 chip->battery_missing = (status & BT_MISS_BIT);
2963
2964 if (chip->battery_missing) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002965 chip->profile_available = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002966 chip->profile_loaded = false;
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08002967 chip->soc_reporting_ready = false;
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -08002968 return IRQ_HANDLED;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002969 }
2970
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -08002971 rc = fg_batt_missing_config(chip, false);
2972 if (rc < 0) {
2973 pr_err("Error in disabling BMD, rc=%d\n", rc);
2974 return IRQ_HANDLED;
2975 }
2976
2977 rc = fg_get_batt_profile(chip);
2978 if (rc < 0) {
2979 chip->soc_reporting_ready = true;
2980 pr_err("Error in getting battery profile, rc:%d\n", rc);
2981 goto enable_bmd;
2982 }
2983
2984 clear_battery_profile(chip);
2985 schedule_delayed_work(&chip->profile_load_work, 0);
2986
2987enable_bmd:
2988 /* Wait for 200ms before enabling BMD again */
2989 msleep(200);
2990 rc = fg_batt_missing_config(chip, true);
2991 if (rc < 0)
2992 pr_err("Error in enabling BMD, rc=%d\n", rc);
2993
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05302994 if (chip->fg_psy)
2995 power_supply_changed(chip->fg_psy);
2996
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002997 return IRQ_HANDLED;
2998}
2999
3000static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data)
3001{
3002 struct fg_chip *chip = data;
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07003003 union power_supply_propval prop = {0, };
3004 int rc, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003005
3006 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07003007 rc = fg_get_battery_temp(chip, &batt_temp);
3008 if (rc < 0) {
3009 pr_err("Error in getting batt_temp\n");
3010 return IRQ_HANDLED;
3011 }
3012
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08003013 rc = fg_esr_filter_config(chip, batt_temp);
3014 if (rc < 0)
3015 pr_err("Error in configuring ESR filter rc:%d\n", rc);
3016
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08003017 if (!batt_psy_initialized(chip)) {
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07003018 chip->last_batt_temp = batt_temp;
3019 return IRQ_HANDLED;
3020 }
3021
3022 power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
3023 &prop);
3024 chip->health = prop.intval;
3025
3026 if (chip->last_batt_temp != batt_temp) {
3027 chip->last_batt_temp = batt_temp;
3028 power_supply_changed(chip->batt_psy);
3029 }
3030
3031 if (abs(chip->last_batt_temp - batt_temp) > 30)
3032 pr_warn("Battery temperature last:%d current: %d\n",
3033 chip->last_batt_temp, batt_temp);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003034 return IRQ_HANDLED;
3035}
3036
3037static irqreturn_t fg_first_est_irq_handler(int irq, void *data)
3038{
3039 struct fg_chip *chip = data;
3040
3041 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
3042 complete_all(&chip->soc_ready);
3043 return IRQ_HANDLED;
3044}
3045
3046static irqreturn_t fg_soc_update_irq_handler(int irq, void *data)
3047{
3048 struct fg_chip *chip = data;
3049
3050 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
3051 complete_all(&chip->soc_update);
3052 return IRQ_HANDLED;
3053}
3054
3055static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
3056{
3057 struct fg_chip *chip = data;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07003058 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003059
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003060 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Nicholas Troaste29dec92016-08-24 09:35:11 -07003061 if (chip->cyc_ctr.en)
3062 schedule_work(&chip->cycle_count_work);
3063
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003064 if (chip->cl.active)
3065 fg_cap_learning_update(chip);
3066
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07003067 rc = fg_charge_full_update(chip);
3068 if (rc < 0)
3069 pr_err("Error in charge_full_update, rc=%d\n", rc);
3070
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07003071 rc = fg_adjust_ki_coeff_dischg(chip);
3072 if (rc < 0)
3073 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
3074
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08003075 if (batt_psy_initialized(chip))
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003076 power_supply_changed(chip->batt_psy);
3077
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003078 return IRQ_HANDLED;
3079}
3080
3081static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data)
3082{
3083 struct fg_chip *chip = data;
3084
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003085 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08003086 if (batt_psy_initialized(chip))
Nicholas Troast65e29652016-09-22 11:27:04 -07003087 power_supply_changed(chip->batt_psy);
3088
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003089 return IRQ_HANDLED;
3090}
3091
3092static irqreturn_t fg_soc_irq_handler(int irq, void *data)
3093{
3094 struct fg_chip *chip = data;
3095
3096 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
3097 return IRQ_HANDLED;
3098}
3099
3100static irqreturn_t fg_dummy_irq_handler(int irq, void *data)
3101{
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003102 pr_debug("irq %d triggered\n", irq);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003103 return IRQ_HANDLED;
3104}
3105
3106static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
3107 /* BATT_SOC irqs */
3108 [MSOC_FULL_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003109 .name = "msoc-full",
3110 .handler = fg_soc_irq_handler,
3111 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003112 [MSOC_HIGH_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003113 .name = "msoc-high",
3114 .handler = fg_soc_irq_handler,
3115 .wakeable = true,
3116 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003117 [MSOC_EMPTY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003118 .name = "msoc-empty",
3119 .handler = fg_empty_soc_irq_handler,
3120 .wakeable = true,
3121 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003122 [MSOC_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003123 .name = "msoc-low",
3124 .handler = fg_soc_irq_handler,
3125 .wakeable = true,
3126 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003127 [MSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003128 .name = "msoc-delta",
3129 .handler = fg_delta_soc_irq_handler,
3130 .wakeable = true,
3131 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003132 [BSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003133 .name = "bsoc-delta",
3134 .handler = fg_dummy_irq_handler,
3135 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003136 [SOC_READY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003137 .name = "soc-ready",
3138 .handler = fg_first_est_irq_handler,
3139 .wakeable = true,
3140 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003141 [SOC_UPDATE_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003142 .name = "soc-update",
3143 .handler = fg_soc_update_irq_handler,
3144 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003145 /* BATT_INFO irqs */
3146 [BATT_TEMP_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003147 .name = "batt-temp-delta",
3148 .handler = fg_delta_batt_temp_irq_handler,
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07003149 .wakeable = true,
Nicholas Troast3cc97182016-09-23 08:54:13 -07003150 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003151 [BATT_MISSING_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003152 .name = "batt-missing",
3153 .handler = fg_batt_missing_irq_handler,
3154 .wakeable = true,
3155 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003156 [ESR_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003157 .name = "esr-delta",
3158 .handler = fg_dummy_irq_handler,
3159 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003160 [VBATT_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003161 .name = "vbatt-low",
3162 .handler = fg_vbatt_low_irq_handler,
3163 .wakeable = true,
3164 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003165 [VBATT_PRED_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003166 .name = "vbatt-pred-delta",
3167 .handler = fg_dummy_irq_handler,
3168 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003169 /* MEM_IF irqs */
3170 [DMA_GRANT_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003171 .name = "dma-grant",
3172 .handler = fg_dummy_irq_handler,
3173 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003174 [MEM_XCP_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003175 .name = "mem-xcp",
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07003176 .handler = fg_mem_xcp_irq_handler,
Nicholas Troast3cc97182016-09-23 08:54:13 -07003177 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003178 [IMA_RDY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07003179 .name = "ima-rdy",
3180 .handler = fg_dummy_irq_handler,
3181 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003182};
3183
3184static int fg_get_irq_index_byname(const char *name)
3185{
3186 int i;
3187
3188 for (i = 0; i < ARRAY_SIZE(fg_irqs); i++) {
3189 if (strcmp(fg_irqs[i].name, name) == 0)
3190 return i;
3191 }
3192
3193 pr_err("%s is not in irq list\n", name);
3194 return -ENOENT;
3195}
3196
3197static int fg_register_interrupts(struct fg_chip *chip)
3198{
3199 struct device_node *child, *node = chip->dev->of_node;
3200 struct property *prop;
3201 const char *name;
3202 int rc, irq, irq_index;
3203
3204 for_each_available_child_of_node(node, child) {
3205 of_property_for_each_string(child, "interrupt-names", prop,
3206 name) {
3207 irq = of_irq_get_byname(child, name);
3208 if (irq < 0) {
3209 dev_err(chip->dev, "failed to get irq %s irq:%d\n",
3210 name, irq);
3211 return irq;
3212 }
3213
3214 irq_index = fg_get_irq_index_byname(name);
3215 if (irq_index < 0)
3216 return irq_index;
3217
3218 rc = devm_request_threaded_irq(chip->dev, irq, NULL,
3219 fg_irqs[irq_index].handler,
3220 IRQF_ONESHOT, name, chip);
3221 if (rc < 0) {
3222 dev_err(chip->dev, "failed to register irq handler for %s rc:%d\n",
3223 name, rc);
3224 return rc;
3225 }
3226
3227 fg_irqs[irq_index].irq = irq;
3228 if (fg_irqs[irq_index].wakeable)
3229 enable_irq_wake(fg_irqs[irq_index].irq);
3230 }
3231 }
3232
3233 return 0;
3234}
3235
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07003236static int fg_parse_ki_coefficients(struct fg_chip *chip)
3237{
3238 struct device_node *node = chip->dev->of_node;
3239 int rc, i;
3240
3241 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-soc-dischg",
3242 sizeof(u32));
3243 if (rc != KI_COEFF_SOC_LEVELS)
3244 return 0;
3245
3246 rc = of_property_read_u32_array(node, "qcom,ki-coeff-soc-dischg",
3247 chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
3248 if (rc < 0) {
3249 pr_err("Error in reading ki-coeff-soc-dischg, rc=%d\n",
3250 rc);
3251 return rc;
3252 }
3253
3254 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-med-dischg",
3255 sizeof(u32));
3256 if (rc != KI_COEFF_SOC_LEVELS)
3257 return 0;
3258
3259 rc = of_property_read_u32_array(node, "qcom,ki-coeff-med-dischg",
3260 chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
3261 if (rc < 0) {
3262 pr_err("Error in reading ki-coeff-med-dischg, rc=%d\n",
3263 rc);
3264 return rc;
3265 }
3266
3267 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-hi-dischg",
3268 sizeof(u32));
3269 if (rc != KI_COEFF_SOC_LEVELS)
3270 return 0;
3271
3272 rc = of_property_read_u32_array(node, "qcom,ki-coeff-hi-dischg",
3273 chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
3274 if (rc < 0) {
3275 pr_err("Error in reading ki-coeff-hi-dischg, rc=%d\n",
3276 rc);
3277 return rc;
3278 }
3279
3280 for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
3281 if (chip->dt.ki_coeff_soc[i] < 0 ||
3282 chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
3283 pr_err("Error in ki_coeff_soc_dischg values\n");
3284 return -EINVAL;
3285 }
3286
3287 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
3288 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
3289 pr_err("Error in ki_coeff_med_dischg values\n");
3290 return -EINVAL;
3291 }
3292
3293 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
3294 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
3295 pr_err("Error in ki_coeff_med_dischg values\n");
3296 return -EINVAL;
3297 }
3298 }
3299 chip->ki_coeff_dischg_en = true;
3300 return 0;
3301}
3302
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003303#define DEFAULT_CUTOFF_VOLT_MV 3200
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -07003304#define DEFAULT_EMPTY_VOLT_MV 2800
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08003305#define DEFAULT_RECHARGE_VOLT_MV 4250
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003306#define DEFAULT_CHG_TERM_CURR_MA 100
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -07003307#define DEFAULT_SYS_TERM_CURR_MA -125
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003308#define DEFAULT_DELTA_SOC_THR 1
3309#define DEFAULT_RECHARGE_SOC_THR 95
3310#define DEFAULT_BATT_TEMP_COLD 0
3311#define DEFAULT_BATT_TEMP_COOL 5
3312#define DEFAULT_BATT_TEMP_WARM 45
3313#define DEFAULT_BATT_TEMP_HOT 50
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003314#define DEFAULT_CL_START_SOC 15
3315#define DEFAULT_CL_MIN_TEMP_DECIDEGC 150
3316#define DEFAULT_CL_MAX_TEMP_DECIDEGC 450
3317#define DEFAULT_CL_MAX_INC_DECIPERC 5
3318#define DEFAULT_CL_MAX_DEC_DECIPERC 100
3319#define DEFAULT_CL_MIN_LIM_DECIPERC 0
3320#define DEFAULT_CL_MAX_LIM_DECIPERC 0
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07003321#define BTEMP_DELTA_LOW 2
3322#define BTEMP_DELTA_HIGH 10
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08003323#define DEFAULT_ESR_FLT_TEMP_DECIDEGC 100
3324#define DEFAULT_ESR_TIGHT_FLT_UPCT 3907
3325#define DEFAULT_ESR_BROAD_FLT_UPCT 99610
3326#define DEFAULT_ESR_TIGHT_LT_FLT_UPCT 48829
3327#define DEFAULT_ESR_BROAD_LT_FLT_UPCT 148438
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003328static int fg_parse_dt(struct fg_chip *chip)
3329{
3330 struct device_node *child, *revid_node, *node = chip->dev->of_node;
3331 u32 base, temp;
3332 u8 subtype;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07003333 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003334
3335 if (!node) {
3336 dev_err(chip->dev, "device tree node missing\n");
3337 return -ENXIO;
3338 }
3339
3340 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
3341 if (!revid_node) {
3342 pr_err("Missing qcom,pmic-revid property - driver failed\n");
3343 return -EINVAL;
3344 }
3345
3346 chip->pmic_rev_id = get_revid_data(revid_node);
3347 if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
3348 pr_err("Unable to get pmic_revid rc=%ld\n",
3349 PTR_ERR(chip->pmic_rev_id));
3350 /*
3351 * the revid peripheral must be registered, any failure
3352 * here only indicates that the rev-id module has not
3353 * probed yet.
3354 */
3355 return -EPROBE_DEFER;
3356 }
3357
3358 pr_debug("PMIC subtype %d Digital major %d\n",
3359 chip->pmic_rev_id->pmic_subtype, chip->pmic_rev_id->rev4);
3360
3361 switch (chip->pmic_rev_id->pmic_subtype) {
Harry Yang2452b272017-03-06 13:56:14 -08003362 case PMI8998_SUBTYPE:
3363 if (chip->pmic_rev_id->rev4 < PMI8998_V2P0_REV4) {
3364 chip->sp = pmi8998_v1_sram_params;
3365 chip->alg_flags = pmi8998_v1_alg_flags;
Ashay Jaiswal63d486e2016-12-07 11:21:32 +05303366 chip->wa_flags |= PMI8998_V1_REV_WA;
Harry Yang2452b272017-03-06 13:56:14 -08003367 } else if (chip->pmic_rev_id->rev4 == PMI8998_V2P0_REV4) {
3368 chip->sp = pmi8998_v2_sram_params;
3369 chip->alg_flags = pmi8998_v2_alg_flags;
Nicholas Troast69da2252016-09-07 16:17:47 -07003370 } else {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003371 return -EINVAL;
Nicholas Troast69da2252016-09-07 16:17:47 -07003372 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003373 break;
Harry Yange4e731b2017-03-06 14:35:09 -08003374 case PM660_SUBTYPE:
Ashay Jaiswal63d486e2016-12-07 11:21:32 +05303375 chip->sp = pmi8998_v2_sram_params;
3376 chip->alg_flags = pmi8998_v2_alg_flags;
3377 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003378 default:
3379 return -EINVAL;
3380 }
3381
3382 chip->batt_id_chan = iio_channel_get(chip->dev, "rradc_batt_id");
3383 if (IS_ERR(chip->batt_id_chan)) {
3384 if (PTR_ERR(chip->batt_id_chan) != -EPROBE_DEFER)
3385 pr_err("batt_id_chan unavailable %ld\n",
3386 PTR_ERR(chip->batt_id_chan));
3387 rc = PTR_ERR(chip->batt_id_chan);
3388 chip->batt_id_chan = NULL;
3389 return rc;
3390 }
3391
3392 if (of_get_available_child_count(node) == 0) {
3393 dev_err(chip->dev, "No child nodes specified!\n");
3394 return -ENXIO;
3395 }
3396
3397 for_each_available_child_of_node(node, child) {
3398 rc = of_property_read_u32(child, "reg", &base);
3399 if (rc < 0) {
3400 dev_err(chip->dev, "reg not specified in node %s, rc=%d\n",
3401 child->full_name, rc);
3402 return rc;
3403 }
3404
3405 rc = fg_read(chip, base + PERPH_SUBTYPE_REG, &subtype, 1);
3406 if (rc < 0) {
3407 dev_err(chip->dev, "Couldn't read subtype for base %d, rc=%d\n",
3408 base, rc);
3409 return rc;
3410 }
3411
3412 switch (subtype) {
Harry Yang2452b272017-03-06 13:56:14 -08003413 case FG_BATT_SOC_PMI8998:
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003414 chip->batt_soc_base = base;
3415 break;
Harry Yang2452b272017-03-06 13:56:14 -08003416 case FG_BATT_INFO_PMI8998:
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003417 chip->batt_info_base = base;
3418 break;
Harry Yang2452b272017-03-06 13:56:14 -08003419 case FG_MEM_INFO_PMI8998:
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003420 chip->mem_if_base = base;
3421 break;
3422 default:
3423 dev_err(chip->dev, "Invalid peripheral subtype 0x%x\n",
3424 subtype);
3425 return -ENXIO;
3426 }
3427 }
3428
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -08003429 rc = of_property_read_u32(node, "qcom,rradc-base", &base);
3430 if (rc < 0) {
3431 dev_err(chip->dev, "rradc-base not specified, rc=%d\n", rc);
3432 return rc;
3433 }
3434 chip->rradc_base = base;
3435
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07003436 rc = fg_get_batt_profile(chip);
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08003437 if (rc < 0) {
3438 chip->soc_reporting_ready = true;
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07003439 pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -08003440 chip->batt_id_ohms / 1000, rc);
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08003441 }
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07003442
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003443 /* Read all the optional properties below */
3444 rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp);
3445 if (rc < 0)
3446 chip->dt.cutoff_volt_mv = DEFAULT_CUTOFF_VOLT_MV;
3447 else
3448 chip->dt.cutoff_volt_mv = temp;
3449
3450 rc = of_property_read_u32(node, "qcom,fg-empty-voltage", &temp);
3451 if (rc < 0)
3452 chip->dt.empty_volt_mv = DEFAULT_EMPTY_VOLT_MV;
3453 else
3454 chip->dt.empty_volt_mv = temp;
3455
3456 rc = of_property_read_u32(node, "qcom,fg-vbatt-low-thr", &temp);
3457 if (rc < 0)
3458 chip->dt.vbatt_low_thr_mv = -EINVAL;
3459 else
3460 chip->dt.vbatt_low_thr_mv = temp;
3461
3462 rc = of_property_read_u32(node, "qcom,fg-chg-term-current", &temp);
3463 if (rc < 0)
3464 chip->dt.chg_term_curr_ma = DEFAULT_CHG_TERM_CURR_MA;
3465 else
3466 chip->dt.chg_term_curr_ma = temp;
3467
3468 rc = of_property_read_u32(node, "qcom,fg-sys-term-current", &temp);
3469 if (rc < 0)
3470 chip->dt.sys_term_curr_ma = DEFAULT_SYS_TERM_CURR_MA;
3471 else
3472 chip->dt.sys_term_curr_ma = temp;
3473
3474 rc = of_property_read_u32(node, "qcom,fg-delta-soc-thr", &temp);
3475 if (rc < 0)
3476 chip->dt.delta_soc_thr = DEFAULT_DELTA_SOC_THR;
3477 else
3478 chip->dt.delta_soc_thr = temp;
3479
3480 rc = of_property_read_u32(node, "qcom,fg-recharge-soc-thr", &temp);
3481 if (rc < 0)
3482 chip->dt.recharge_soc_thr = DEFAULT_RECHARGE_SOC_THR;
3483 else
3484 chip->dt.recharge_soc_thr = temp;
3485
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08003486 rc = of_property_read_u32(node, "qcom,fg-recharge-voltage", &temp);
3487 if (rc < 0)
3488 chip->dt.recharge_volt_thr_mv = DEFAULT_RECHARGE_VOLT_MV;
3489 else
3490 chip->dt.recharge_volt_thr_mv = temp;
3491
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003492 rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp);
3493 if (rc < 0)
3494 chip->dt.rsense_sel = SRC_SEL_BATFET_SMB;
3495 else
3496 chip->dt.rsense_sel = (u8)temp & SOURCE_SELECT_MASK;
3497
3498 chip->dt.jeita_thresholds[JEITA_COLD] = DEFAULT_BATT_TEMP_COLD;
3499 chip->dt.jeita_thresholds[JEITA_COOL] = DEFAULT_BATT_TEMP_COOL;
3500 chip->dt.jeita_thresholds[JEITA_WARM] = DEFAULT_BATT_TEMP_WARM;
3501 chip->dt.jeita_thresholds[JEITA_HOT] = DEFAULT_BATT_TEMP_HOT;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07003502 if (of_property_count_elems_of_size(node, "qcom,fg-jeita-thresholds",
3503 sizeof(u32)) == NUM_JEITA_LEVELS) {
3504 rc = of_property_read_u32_array(node,
3505 "qcom,fg-jeita-thresholds",
3506 chip->dt.jeita_thresholds, NUM_JEITA_LEVELS);
3507 if (rc < 0)
3508 pr_warn("Error reading Jeita thresholds, default values will be used rc:%d\n",
3509 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003510 }
3511
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003512 rc = of_property_read_u32(node, "qcom,fg-esr-timer-charging", &temp);
3513 if (rc < 0)
3514 chip->dt.esr_timer_charging = -EINVAL;
3515 else
3516 chip->dt.esr_timer_charging = temp;
3517
3518 rc = of_property_read_u32(node, "qcom,fg-esr-timer-awake", &temp);
3519 if (rc < 0)
3520 chip->dt.esr_timer_awake = -EINVAL;
3521 else
3522 chip->dt.esr_timer_awake = temp;
3523
3524 rc = of_property_read_u32(node, "qcom,fg-esr-timer-asleep", &temp);
3525 if (rc < 0)
3526 chip->dt.esr_timer_asleep = -EINVAL;
3527 else
3528 chip->dt.esr_timer_asleep = temp;
3529
Nicholas Troaste29dec92016-08-24 09:35:11 -07003530 chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
3531 if (chip->cyc_ctr.en)
3532 chip->cyc_ctr.id = 1;
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003533
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07003534 chip->dt.force_load_profile = of_property_read_bool(node,
3535 "qcom,fg-force-load-profile");
3536
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003537 rc = of_property_read_u32(node, "qcom,cl-start-capacity", &temp);
3538 if (rc < 0)
3539 chip->dt.cl_start_soc = DEFAULT_CL_START_SOC;
3540 else
3541 chip->dt.cl_start_soc = temp;
3542
3543 rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp);
3544 if (rc < 0)
3545 chip->dt.cl_min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC;
3546 else
3547 chip->dt.cl_min_temp = temp;
3548
3549 rc = of_property_read_u32(node, "qcom,cl-max-temp", &temp);
3550 if (rc < 0)
3551 chip->dt.cl_max_temp = DEFAULT_CL_MAX_TEMP_DECIDEGC;
3552 else
3553 chip->dt.cl_max_temp = temp;
3554
3555 rc = of_property_read_u32(node, "qcom,cl-max-increment", &temp);
3556 if (rc < 0)
3557 chip->dt.cl_max_cap_inc = DEFAULT_CL_MAX_INC_DECIPERC;
3558 else
3559 chip->dt.cl_max_cap_inc = temp;
3560
3561 rc = of_property_read_u32(node, "qcom,cl-max-decrement", &temp);
3562 if (rc < 0)
3563 chip->dt.cl_max_cap_dec = DEFAULT_CL_MAX_DEC_DECIPERC;
3564 else
3565 chip->dt.cl_max_cap_dec = temp;
3566
3567 rc = of_property_read_u32(node, "qcom,cl-min-limit", &temp);
3568 if (rc < 0)
3569 chip->dt.cl_min_cap_limit = DEFAULT_CL_MIN_LIM_DECIPERC;
3570 else
3571 chip->dt.cl_min_cap_limit = temp;
3572
3573 rc = of_property_read_u32(node, "qcom,cl-max-limit", &temp);
3574 if (rc < 0)
3575 chip->dt.cl_max_cap_limit = DEFAULT_CL_MAX_LIM_DECIPERC;
3576 else
3577 chip->dt.cl_max_cap_limit = temp;
3578
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07003579 rc = of_property_read_u32(node, "qcom,fg-jeita-hyst-temp", &temp);
3580 if (rc < 0)
3581 chip->dt.jeita_hyst_temp = -EINVAL;
3582 else
3583 chip->dt.jeita_hyst_temp = temp;
3584
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07003585 rc = of_property_read_u32(node, "qcom,fg-batt-temp-delta", &temp);
3586 if (rc < 0)
3587 chip->dt.batt_temp_delta = -EINVAL;
3588 else if (temp > BTEMP_DELTA_LOW && temp <= BTEMP_DELTA_HIGH)
3589 chip->dt.batt_temp_delta = temp;
3590
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07003591 chip->dt.hold_soc_while_full = of_property_read_bool(node,
3592 "qcom,hold-soc-while-full");
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07003593
3594 rc = fg_parse_ki_coefficients(chip);
3595 if (rc < 0)
3596 pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
3597
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08003598 rc = of_property_read_u32(node, "qcom,fg-rconn-mohms", &temp);
3599 if (rc < 0)
3600 chip->dt.rconn_mohms = -EINVAL;
3601 else
3602 chip->dt.rconn_mohms = temp;
3603
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08003604 rc = of_property_read_u32(node, "qcom,fg-esr-filter-switch-temp",
3605 &temp);
3606 if (rc < 0)
3607 chip->dt.esr_flt_switch_temp = DEFAULT_ESR_FLT_TEMP_DECIDEGC;
3608 else
3609 chip->dt.esr_flt_switch_temp = temp;
3610
3611 rc = of_property_read_u32(node, "qcom,fg-esr-tight-filter-micro-pct",
3612 &temp);
3613 if (rc < 0)
3614 chip->dt.esr_tight_flt_upct = DEFAULT_ESR_TIGHT_FLT_UPCT;
3615 else
3616 chip->dt.esr_tight_flt_upct = temp;
3617
3618 rc = of_property_read_u32(node, "qcom,fg-esr-broad-filter-micro-pct",
3619 &temp);
3620 if (rc < 0)
3621 chip->dt.esr_broad_flt_upct = DEFAULT_ESR_BROAD_FLT_UPCT;
3622 else
3623 chip->dt.esr_broad_flt_upct = temp;
3624
3625 rc = of_property_read_u32(node, "qcom,fg-esr-tight-lt-filter-micro-pct",
3626 &temp);
3627 if (rc < 0)
3628 chip->dt.esr_tight_lt_flt_upct = DEFAULT_ESR_TIGHT_LT_FLT_UPCT;
3629 else
3630 chip->dt.esr_tight_lt_flt_upct = temp;
3631
3632 rc = of_property_read_u32(node, "qcom,fg-esr-broad-lt-filter-micro-pct",
3633 &temp);
3634 if (rc < 0)
3635 chip->dt.esr_broad_lt_flt_upct = DEFAULT_ESR_BROAD_LT_FLT_UPCT;
3636 else
3637 chip->dt.esr_broad_lt_flt_upct = temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003638 return 0;
3639}
3640
3641static void fg_cleanup(struct fg_chip *chip)
3642{
3643 power_supply_unreg_notifier(&chip->nb);
Nicholas Troast69da2252016-09-07 16:17:47 -07003644 debugfs_remove_recursive(chip->dfs_root);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003645 if (chip->awake_votable)
3646 destroy_votable(chip->awake_votable);
3647
3648 if (chip->batt_id_chan)
3649 iio_channel_release(chip->batt_id_chan);
3650
3651 dev_set_drvdata(chip->dev, NULL);
3652}
3653
3654static int fg_gen3_probe(struct platform_device *pdev)
3655{
3656 struct fg_chip *chip;
3657 struct power_supply_config fg_psy_cfg;
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003658 int rc, msoc, volt_uv, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003659
3660 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
3661 if (!chip)
3662 return -ENOMEM;
3663
3664 chip->dev = &pdev->dev;
3665 chip->debug_mask = &fg_gen3_debug_mask;
3666 chip->irqs = fg_irqs;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003667 chip->charge_status = -EINVAL;
3668 chip->prev_charge_status = -EINVAL;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003669 chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
3670 if (!chip->regmap) {
3671 dev_err(chip->dev, "Parent regmap is unavailable\n");
3672 return -ENXIO;
3673 }
3674
3675 rc = fg_parse_dt(chip);
3676 if (rc < 0) {
3677 dev_err(chip->dev, "Error in reading DT parameters, rc:%d\n",
3678 rc);
3679 return rc;
3680 }
3681
3682 chip->awake_votable = create_votable("FG_WS", VOTE_SET_ANY, fg_awake_cb,
3683 chip);
3684 if (IS_ERR(chip->awake_votable)) {
3685 rc = PTR_ERR(chip->awake_votable);
3686 return rc;
3687 }
3688
3689 mutex_init(&chip->bus_lock);
3690 mutex_init(&chip->sram_rw_lock);
Nicholas Troaste29dec92016-08-24 09:35:11 -07003691 mutex_init(&chip->cyc_ctr.lock);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003692 mutex_init(&chip->cl.lock);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003693 mutex_init(&chip->batt_avg_lock);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003694 init_completion(&chip->soc_update);
3695 init_completion(&chip->soc_ready);
3696 INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
3697 INIT_WORK(&chip->status_change_work, status_change_work);
Nicholas Troaste29dec92016-08-24 09:35:11 -07003698 INIT_WORK(&chip->cycle_count_work, cycle_count_work);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003699 INIT_DELAYED_WORK(&chip->batt_avg_work, batt_avg_work);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08003700 INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003701
3702 rc = fg_memif_init(chip);
3703 if (rc < 0) {
3704 dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n",
3705 rc);
3706 goto exit;
3707 }
3708
3709 rc = fg_hw_init(chip);
3710 if (rc < 0) {
3711 dev_err(chip->dev, "Error in initializing FG hardware, rc:%d\n",
3712 rc);
3713 goto exit;
3714 }
3715
3716 platform_set_drvdata(pdev, chip);
3717
3718 /* Register the power supply */
3719 fg_psy_cfg.drv_data = chip;
3720 fg_psy_cfg.of_node = NULL;
3721 fg_psy_cfg.supplied_to = NULL;
3722 fg_psy_cfg.num_supplicants = 0;
3723 chip->fg_psy = devm_power_supply_register(chip->dev, &fg_psy_desc,
3724 &fg_psy_cfg);
3725 if (IS_ERR(chip->fg_psy)) {
3726 pr_err("failed to register fg_psy rc = %ld\n",
3727 PTR_ERR(chip->fg_psy));
3728 goto exit;
3729 }
3730
3731 chip->nb.notifier_call = fg_notifier_cb;
3732 rc = power_supply_reg_notifier(&chip->nb);
3733 if (rc < 0) {
3734 pr_err("Couldn't register psy notifier rc = %d\n", rc);
3735 goto exit;
3736 }
3737
3738 rc = fg_register_interrupts(chip);
3739 if (rc < 0) {
3740 dev_err(chip->dev, "Error in registering interrupts, rc:%d\n",
3741 rc);
3742 goto exit;
3743 }
3744
3745 /* Keep SOC_UPDATE irq disabled until we require it */
3746 if (fg_irqs[SOC_UPDATE_IRQ].irq)
3747 disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
3748
Nicholas Troast69da2252016-09-07 16:17:47 -07003749 rc = fg_debugfs_create(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003750 if (rc < 0) {
3751 dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n",
3752 rc);
3753 goto exit;
3754 }
3755
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003756 rc = fg_get_battery_voltage(chip, &volt_uv);
3757 if (!rc)
3758 rc = fg_get_prop_capacity(chip, &msoc);
3759
3760 if (!rc)
3761 rc = fg_get_battery_temp(chip, &batt_temp);
3762
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08003763 if (!rc) {
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003764 pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n",
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -08003765 msoc, volt_uv, batt_temp, chip->batt_id_ohms / 1000);
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08003766 rc = fg_esr_filter_config(chip, batt_temp);
3767 if (rc < 0)
3768 pr_err("Error in configuring ESR filter rc:%d\n", rc);
3769 }
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003770
3771 device_init_wakeup(chip->dev, true);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07003772 if (chip->profile_available)
3773 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003774
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003775 pr_debug("FG GEN3 driver probed successfully\n");
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003776 return 0;
3777exit:
3778 fg_cleanup(chip);
3779 return rc;
3780}
3781
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003782static int fg_gen3_suspend(struct device *dev)
3783{
3784 struct fg_chip *chip = dev_get_drvdata(dev);
3785 int rc;
3786
3787 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
3788 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_asleep, false,
3789 FG_IMA_NO_WLOCK);
3790 if (rc < 0) {
3791 pr_err("Error in setting ESR timer during suspend, rc=%d\n",
3792 rc);
3793 return rc;
3794 }
3795 }
3796
Nicholas Troast1769fd32016-09-07 09:20:58 -07003797 cancel_delayed_work_sync(&chip->batt_avg_work);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08003798 if (fg_sram_dump)
3799 cancel_delayed_work_sync(&chip->sram_dump_work);
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003800 return 0;
3801}
3802
3803static int fg_gen3_resume(struct device *dev)
3804{
3805 struct fg_chip *chip = dev_get_drvdata(dev);
3806 int rc;
3807
3808 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
3809 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
3810 FG_IMA_DEFAULT);
3811 if (rc < 0) {
3812 pr_err("Error in setting ESR timer during resume, rc=%d\n",
3813 rc);
3814 return rc;
3815 }
3816 }
3817
Nicholas Troast1769fd32016-09-07 09:20:58 -07003818 fg_circ_buf_clr(&chip->ibatt_circ_buf);
3819 fg_circ_buf_clr(&chip->vbatt_circ_buf);
3820 schedule_delayed_work(&chip->batt_avg_work, 0);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08003821 if (fg_sram_dump)
3822 schedule_delayed_work(&chip->sram_dump_work,
3823 msecs_to_jiffies(fg_sram_dump_period_ms));
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003824 return 0;
3825}
3826
3827static const struct dev_pm_ops fg_gen3_pm_ops = {
3828 .suspend = fg_gen3_suspend,
3829 .resume = fg_gen3_resume,
3830};
3831
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003832static int fg_gen3_remove(struct platform_device *pdev)
3833{
3834 struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
3835
3836 fg_cleanup(chip);
3837 return 0;
3838}
3839
3840static const struct of_device_id fg_gen3_match_table[] = {
3841 {.compatible = FG_GEN3_DEV_NAME},
3842 {},
3843};
3844
3845static struct platform_driver fg_gen3_driver = {
3846 .driver = {
3847 .name = FG_GEN3_DEV_NAME,
3848 .owner = THIS_MODULE,
3849 .of_match_table = fg_gen3_match_table,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003850 .pm = &fg_gen3_pm_ops,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003851 },
3852 .probe = fg_gen3_probe,
3853 .remove = fg_gen3_remove,
3854};
3855
3856static int __init fg_gen3_init(void)
3857{
3858 return platform_driver_register(&fg_gen3_driver);
3859}
3860
3861static void __exit fg_gen3_exit(void)
3862{
3863 return platform_driver_unregister(&fg_gen3_driver);
3864}
3865
3866module_init(fg_gen3_init);
3867module_exit(fg_gen3_exit);
3868
3869MODULE_DESCRIPTION("QPNP Fuel gauge GEN3 driver");
3870MODULE_LICENSE("GPL v2");
3871MODULE_ALIAS("platform:" FG_GEN3_DEV_NAME);