blob: 3f4baf26e94371db1d6a1273021ac91635a95684 [file] [log] [blame]
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
2 *
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
15#include <linux/of.h>
16#include <linux/of_irq.h>
17#include <linux/of_platform.h>
18#include <linux/of_batterydata.h>
19#include <linux/platform_device.h>
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070020#include <linux/iio/consumer.h>
21#include <linux/qpnp/qpnp-revid.h>
22#include "fg-core.h"
23#include "fg-reg.h"
24
25#define FG_GEN3_DEV_NAME "qcom,fg-gen3"
26
27#define PERPH_SUBTYPE_REG 0x05
28#define FG_BATT_SOC_PMICOBALT 0x10
29#define FG_BATT_INFO_PMICOBALT 0x11
30#define FG_MEM_INFO_PMICOBALT 0x0D
31
32/* SRAM address and offset in ascending order */
33#define CUTOFF_VOLT_WORD 5
34#define CUTOFF_VOLT_OFFSET 0
35#define SYS_TERM_CURR_WORD 6
36#define SYS_TERM_CURR_OFFSET 0
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -070037#define VBATT_FULL_WORD 7
38#define VBATT_FULL_OFFSET 0
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -070039#define KI_COEFF_MED_DISCHG_WORD 9
40#define KI_COEFF_MED_DISCHG_OFFSET 3
41#define KI_COEFF_HI_DISCHG_WORD 10
42#define KI_COEFF_HI_DISCHG_OFFSET 0
43#define KI_COEFF_LOW_DISCHG_WORD 10
44#define KI_COEFF_LOW_DISCHG_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070045#define DELTA_SOC_THR_WORD 12
46#define DELTA_SOC_THR_OFFSET 3
47#define RECHARGE_SOC_THR_WORD 14
48#define RECHARGE_SOC_THR_OFFSET 0
49#define CHG_TERM_CURR_WORD 14
50#define CHG_TERM_CURR_OFFSET 1
51#define EMPTY_VOLT_WORD 15
52#define EMPTY_VOLT_OFFSET 0
53#define VBATT_LOW_WORD 15
54#define VBATT_LOW_OFFSET 1
Nicholas Troastdcf8fe62016-08-04 14:30:02 -070055#define ESR_TIMER_DISCHG_MAX_WORD 17
56#define ESR_TIMER_DISCHG_MAX_OFFSET 0
57#define ESR_TIMER_DISCHG_INIT_WORD 17
58#define ESR_TIMER_DISCHG_INIT_OFFSET 2
59#define ESR_TIMER_CHG_MAX_WORD 18
60#define ESR_TIMER_CHG_MAX_OFFSET 0
61#define ESR_TIMER_CHG_INIT_WORD 18
62#define ESR_TIMER_CHG_INIT_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070063#define PROFILE_LOAD_WORD 24
64#define PROFILE_LOAD_OFFSET 0
65#define NOM_CAP_WORD 58
66#define NOM_CAP_OFFSET 0
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -070067#define ACT_BATT_CAP_BKUP_WORD 74
68#define ACT_BATT_CAP_BKUP_OFFSET 0
Nicholas Troaste29dec92016-08-24 09:35:11 -070069#define CYCLE_COUNT_WORD 75
70#define CYCLE_COUNT_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070071#define PROFILE_INTEGRITY_WORD 79
72#define PROFILE_INTEGRITY_OFFSET 3
73#define BATT_SOC_WORD 91
74#define BATT_SOC_OFFSET 0
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -070075#define FULL_SOC_WORD 93
76#define FULL_SOC_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070077#define MONOTONIC_SOC_WORD 94
78#define MONOTONIC_SOC_OFFSET 2
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -070079#define CC_SOC_WORD 95
80#define CC_SOC_OFFSET 0
81#define CC_SOC_SW_WORD 96
82#define CC_SOC_SW_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070083#define VOLTAGE_PRED_WORD 97
84#define VOLTAGE_PRED_OFFSET 0
85#define OCV_WORD 97
86#define OCV_OFFSET 2
87#define RSLOW_WORD 101
88#define RSLOW_OFFSET 0
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -070089#define ACT_BATT_CAP_WORD 117
90#define ACT_BATT_CAP_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070091#define LAST_BATT_SOC_WORD 119
92#define LAST_BATT_SOC_OFFSET 0
93#define LAST_MONOTONIC_SOC_WORD 119
94#define LAST_MONOTONIC_SOC_OFFSET 2
Nicholas Troast69da2252016-09-07 16:17:47 -070095#define ALG_FLAGS_WORD 120
96#define ALG_FLAGS_OFFSET 1
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070097
Nicholas Troasta2b40372016-08-15 10:45:39 -070098/* v2 SRAM address and offset in ascending order */
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -070099#define KI_COEFF_LOW_DISCHG_v2_WORD 9
100#define KI_COEFF_LOW_DISCHG_v2_OFFSET 3
101#define KI_COEFF_MED_DISCHG_v2_WORD 10
102#define KI_COEFF_MED_DISCHG_v2_OFFSET 0
103#define KI_COEFF_HI_DISCHG_v2_WORD 10
104#define KI_COEFF_HI_DISCHG_v2_OFFSET 1
Nicholas Troasta2b40372016-08-15 10:45:39 -0700105#define DELTA_SOC_THR_v2_WORD 13
106#define DELTA_SOC_THR_v2_OFFSET 0
107#define RECHARGE_SOC_THR_v2_WORD 14
108#define RECHARGE_SOC_THR_v2_OFFSET 1
109#define CHG_TERM_CURR_v2_WORD 15
110#define CHG_TERM_CURR_v2_OFFSET 1
111#define EMPTY_VOLT_v2_WORD 15
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700112#define EMPTY_VOLT_v2_OFFSET 3
Nicholas Troasta2b40372016-08-15 10:45:39 -0700113#define VBATT_LOW_v2_WORD 16
114#define VBATT_LOW_v2_OFFSET 0
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700115#define FLOAT_VOLT_v2_WORD 16
116#define FLOAT_VOLT_v2_OFFSET 2
Nicholas Troasta2b40372016-08-15 10:45:39 -0700117
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700118static int fg_decode_voltage_15b(struct fg_sram_param *sp,
119 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700120static int fg_decode_value_16b(struct fg_sram_param *sp,
121 enum fg_sram_param_id id, int val);
122static int fg_decode_default(struct fg_sram_param *sp,
123 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700124static int fg_decode_cc_soc(struct fg_sram_param *sp,
125 enum fg_sram_param_id id, int value);
Nicholas Troasta2b40372016-08-15 10:45:39 -0700126static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700127 enum fg_sram_param_id id, int val_mv, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700128static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700129 enum fg_sram_param_id id, int val_ma, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700130static void fg_encode_default(struct fg_sram_param *sp,
131 enum fg_sram_param_id id, int val, u8 *buf);
132
Nicholas Troasta2b40372016-08-15 10:45:39 -0700133#define PARAM(_id, _addr_word, _addr_byte, _len, _num, _den, _offset, \
134 _enc, _dec) \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700135 [FG_SRAM_##_id] = { \
Nicholas Troasta2b40372016-08-15 10:45:39 -0700136 .addr_word = _addr_word, \
137 .addr_byte = _addr_byte, \
138 .len = _len, \
139 .numrtr = _num, \
140 .denmtr = _den, \
141 .offset = _offset, \
142 .encode = _enc, \
143 .decode = _dec, \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700144 } \
145
146static struct fg_sram_param pmicobalt_v1_sram_params[] = {
Nicholas Troasta2b40372016-08-15 10:45:39 -0700147 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700148 fg_decode_default),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700149 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700150 1000, 0, NULL, fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700151 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700152 fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700153 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700154 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700155 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
156 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700157 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
158 fg_decode_cc_soc),
159 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
160 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700161 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
162 1, 1, 0, NULL, fg_decode_default),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700163 /* Entries below here are configurable during initialization */
164 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700165 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700166 PARAM(EMPTY_VOLT, EMPTY_VOLT_WORD, EMPTY_VOLT_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700167 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700168 PARAM(VBATT_LOW, VBATT_LOW_WORD, VBATT_LOW_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700169 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700170 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
171 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700172 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700173 1000000, 122070, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700174 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700175 100000, 390625, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthy6234f342016-09-22 18:11:42 -0700176 PARAM(DELTA_SOC_THR, DELTA_SOC_THR_WORD, DELTA_SOC_THR_OFFSET, 1, 2048,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700177 100, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700178 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_WORD, RECHARGE_SOC_THR_OFFSET,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700179 1, 256, 100, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700180 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700181 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
182 NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700183 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700184 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700185 NULL),
186 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700187 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700188 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700189 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700190 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD,
191 KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 244141, 0,
192 fg_encode_default, NULL),
193 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD,
194 KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 244141, 0,
195 fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700196};
197
198static struct fg_sram_param pmicobalt_v2_sram_params[] = {
199 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700200 fg_decode_default),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700201 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700202 1000, 0, NULL, fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700203 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700204 fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700205 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
206 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700207 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
208 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700209 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
210 fg_decode_cc_soc),
211 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
212 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700213 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
214 1, 1, 0, NULL, fg_decode_default),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700215 /* Entries below here are configurable during initialization */
216 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
217 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700218 PARAM(EMPTY_VOLT, EMPTY_VOLT_v2_WORD, EMPTY_VOLT_v2_OFFSET, 1, 1000,
219 15625, -2000, fg_encode_voltage, NULL),
220 PARAM(VBATT_LOW, VBATT_LOW_v2_WORD, VBATT_LOW_v2_OFFSET, 1, 1000,
221 15625, -2000, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700222 PARAM(FLOAT_VOLT, FLOAT_VOLT_v2_WORD, FLOAT_VOLT_v2_OFFSET, 1, 1000,
223 15625, -2000, fg_encode_voltage, NULL),
224 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
225 244141, 0, fg_encode_voltage, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700226 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
227 1000000, 122070, 0, fg_encode_current, NULL),
228 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_v2_WORD, CHG_TERM_CURR_v2_OFFSET, 1,
229 100000, 390625, 0, fg_encode_current, NULL),
230 PARAM(DELTA_SOC_THR, DELTA_SOC_THR_v2_WORD, DELTA_SOC_THR_v2_OFFSET, 1,
Subbaraman Narayanamurthy6234f342016-09-22 18:11:42 -0700231 2048, 100, 0, fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700232 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD,
233 RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default,
234 NULL),
235 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
236 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
237 NULL),
238 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
239 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
240 NULL),
241 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
242 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
243 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
244 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700245 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_v2_WORD,
246 KI_COEFF_MED_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
247 fg_encode_default, NULL),
248 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_v2_WORD,
249 KI_COEFF_HI_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
250 fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700251};
252
Nicholas Troast69da2252016-09-07 16:17:47 -0700253static struct fg_alg_flag pmicobalt_v1_alg_flags[] = {
254 [ALG_FLAG_SOC_LT_OTG_MIN] = {
255 .name = "SOC_LT_OTG_MIN",
256 .bit = BIT(0),
257 },
258 [ALG_FLAG_SOC_LT_RECHARGE] = {
259 .name = "SOC_LT_RECHARGE",
260 .bit = BIT(1),
261 },
262 [ALG_FLAG_IBATT_LT_ITERM] = {
263 .name = "IBATT_LT_ITERM",
264 .bit = BIT(2),
265 },
266 [ALG_FLAG_IBATT_GT_HPM] = {
267 .name = "IBATT_GT_HPM",
268 .bit = BIT(3),
269 },
270 [ALG_FLAG_IBATT_GT_UPM] = {
271 .name = "IBATT_GT_UPM",
272 .bit = BIT(4),
273 },
274 [ALG_FLAG_VBATT_LT_RECHARGE] = {
275 .name = "VBATT_LT_RECHARGE",
276 .bit = BIT(5),
277 },
278 [ALG_FLAG_VBATT_GT_VFLOAT] = {
279 .invalid = true,
280 },
281};
282
283static struct fg_alg_flag pmicobalt_v2_alg_flags[] = {
284 [ALG_FLAG_SOC_LT_OTG_MIN] = {
285 .name = "SOC_LT_OTG_MIN",
286 .bit = BIT(0),
287 },
288 [ALG_FLAG_SOC_LT_RECHARGE] = {
289 .name = "SOC_LT_RECHARGE",
290 .bit = BIT(1),
291 },
292 [ALG_FLAG_IBATT_LT_ITERM] = {
293 .name = "IBATT_LT_ITERM",
294 .bit = BIT(2),
295 },
296 [ALG_FLAG_IBATT_GT_HPM] = {
297 .name = "IBATT_GT_HPM",
298 .bit = BIT(4),
299 },
300 [ALG_FLAG_IBATT_GT_UPM] = {
301 .name = "IBATT_GT_UPM",
302 .bit = BIT(5),
303 },
304 [ALG_FLAG_VBATT_LT_RECHARGE] = {
305 .name = "VBATT_LT_RECHARGE",
306 .bit = BIT(6),
307 },
308 [ALG_FLAG_VBATT_GT_VFLOAT] = {
309 .name = "VBATT_GT_VFLOAT",
310 .bit = BIT(7),
311 },
312};
313
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700314static int fg_gen3_debug_mask;
315module_param_named(
316 debug_mask, fg_gen3_debug_mask, int, 0600
317);
318
319static int fg_sram_update_period_ms = 30000;
320module_param_named(
321 sram_update_period_ms, fg_sram_update_period_ms, int, 0600
322);
323
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700324static bool fg_sram_dump;
325module_param_named(
326 sram_dump, fg_sram_dump, bool, 0600
327);
328
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -0700329static int fg_restart;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700330
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700331/* All getters HERE */
332
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700333#define VOLTAGE_15BIT_MASK GENMASK(14, 0)
334static int fg_decode_voltage_15b(struct fg_sram_param *sp,
335 enum fg_sram_param_id id, int value)
336{
337 value &= VOLTAGE_15BIT_MASK;
338 sp[id].value = div_u64((u64)value * sp[id].numrtr, sp[id].denmtr);
339 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
340 sp[id].value);
341 return sp[id].value;
342}
343
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700344static int fg_decode_cc_soc(struct fg_sram_param *sp,
345 enum fg_sram_param_id id, int value)
346{
347 sp[id].value = div_s64((s64)value * sp[id].numrtr, sp[id].denmtr);
348 sp[id].value = sign_extend32(sp[id].value, 31);
349 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
350 sp[id].value);
351 return sp[id].value;
352}
353
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700354static int fg_decode_value_16b(struct fg_sram_param *sp,
355 enum fg_sram_param_id id, int value)
356{
357 sp[id].value = div_u64((u64)(u16)value * sp[id].numrtr, sp[id].denmtr);
358 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
359 sp[id].value);
360 return sp[id].value;
361}
362
Nicholas Troaste29dec92016-08-24 09:35:11 -0700363static int fg_decode_default(struct fg_sram_param *sp, enum fg_sram_param_id id,
364 int value)
365{
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700366 sp[id].value = value;
367 return sp[id].value;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700368}
369
370static int fg_decode(struct fg_sram_param *sp, enum fg_sram_param_id id,
371 int value)
372{
373 if (!sp[id].decode) {
374 pr_err("No decoding function for parameter %d\n", id);
375 return -EINVAL;
376 }
377
378 return sp[id].decode(sp, id, value);
379}
380
Nicholas Troasta2b40372016-08-15 10:45:39 -0700381static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700382 enum fg_sram_param_id id, int val_mv, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700383{
384 int i, mask = 0xff;
385 int64_t temp;
386
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700387 val_mv += sp[id].offset;
388 temp = (int64_t)div_u64((u64)val_mv * sp[id].numrtr, sp[id].denmtr);
389 pr_debug("temp: %llx id: %d, val_mv: %d, buf: [ ", temp, id, val_mv);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700390 for (i = 0; i < sp[id].len; i++) {
391 buf[i] = temp & mask;
392 temp >>= 8;
393 pr_debug("%x ", buf[i]);
394 }
395 pr_debug("]\n");
396}
397
398static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700399 enum fg_sram_param_id id, int val_ma, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700400{
401 int i, mask = 0xff;
402 int64_t temp;
403 s64 current_ma;
404
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700405 current_ma = val_ma;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700406 temp = (int64_t)div_s64(current_ma * sp[id].numrtr, sp[id].denmtr);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700407 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val_ma);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700408 for (i = 0; i < sp[id].len; i++) {
409 buf[i] = temp & mask;
410 temp >>= 8;
411 pr_debug("%x ", buf[i]);
412 }
413 pr_debug("]\n");
414}
415
416static void fg_encode_default(struct fg_sram_param *sp,
417 enum fg_sram_param_id id, int val, u8 *buf)
418{
419 int i, mask = 0xff;
420 int64_t temp;
421
422 temp = DIV_ROUND_CLOSEST(val * sp[id].numrtr, sp[id].denmtr);
423 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val);
424 for (i = 0; i < sp[id].len; i++) {
425 buf[i] = temp & mask;
426 temp >>= 8;
427 pr_debug("%x ", buf[i]);
428 }
429 pr_debug("]\n");
430}
431
432static void fg_encode(struct fg_sram_param *sp, enum fg_sram_param_id id,
433 int val, u8 *buf)
434{
435 if (!sp[id].encode) {
436 pr_err("No encoding function for parameter %d\n", id);
437 return;
438 }
439
440 sp[id].encode(sp, id, val, buf);
441}
442
443/*
444 * Please make sure *_sram_params table has the entry for the parameter
445 * obtained through this function. In addition to address, offset,
446 * length from where this SRAM parameter is read, a decode function
447 * need to be specified.
448 */
449static int fg_get_sram_prop(struct fg_chip *chip, enum fg_sram_param_id id,
450 int *val)
451{
452 int temp, rc, i;
453 u8 buf[4];
454
455 if (id < 0 || id > FG_SRAM_MAX || chip->sp[id].len > sizeof(buf))
456 return -EINVAL;
457
Subbaraman Narayanamurthy0a749db2016-10-03 18:33:19 -0700458 if (chip->battery_missing)
459 return -ENODATA;
460
Nicholas Troasta2b40372016-08-15 10:45:39 -0700461 rc = fg_sram_read(chip, chip->sp[id].addr_word, chip->sp[id].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700462 buf, chip->sp[id].len, FG_IMA_DEFAULT);
463 if (rc < 0) {
464 pr_err("Error reading address 0x%04x[%d] rc=%d\n",
Nicholas Troasta2b40372016-08-15 10:45:39 -0700465 chip->sp[id].addr_word, chip->sp[id].addr_byte, rc);
Nicholas Troastb2d71742016-08-04 14:31:41 -0700466 return rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700467 }
468
469 for (i = 0, temp = 0; i < chip->sp[id].len; i++)
470 temp |= buf[i] << (8 * i);
471
472 *val = fg_decode(chip->sp, id, temp);
473 return 0;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700474}
475
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700476#define CC_SOC_30BIT GENMASK(29, 0)
477static int fg_get_cc_soc(struct fg_chip *chip, int *val)
478{
479 int rc, cc_soc;
480
481 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC, &cc_soc);
482 if (rc < 0) {
483 pr_err("Error in getting CC_SOC, rc=%d\n", rc);
484 return rc;
485 }
486
487 *val = div_s64(cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
488 return 0;
489}
490
491static int fg_get_cc_soc_sw(struct fg_chip *chip, int *val)
492{
493 int rc, cc_soc;
494
495 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc);
496 if (rc < 0) {
497 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
498 return rc;
499 }
500
501 *val = div_s64(cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
502 return 0;
503}
504
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700505#define BATT_TEMP_NUMR 1
506#define BATT_TEMP_DENR 1
507static int fg_get_battery_temp(struct fg_chip *chip, int *val)
508{
Subbaraman Narayanamurthyfabbb8e2016-10-21 16:55:09 -0700509 int rc = 0, temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700510 u8 buf[2];
511
512 rc = fg_read(chip, BATT_INFO_BATT_TEMP_LSB(chip), buf, 2);
513 if (rc < 0) {
514 pr_err("failed to read addr=0x%04x, rc=%d\n",
515 BATT_INFO_BATT_TEMP_LSB(chip), rc);
516 return rc;
517 }
518
519 temp = ((buf[1] & BATT_TEMP_MSB_MASK) << 8) |
520 (buf[0] & BATT_TEMP_LSB_MASK);
521 temp = DIV_ROUND_CLOSEST(temp, 4);
522
523 /* Value is in Kelvin; Convert it to deciDegC */
524 temp = (temp - 273) * 10;
525 *val = temp;
526 return 0;
527}
528
529#define BATT_ESR_NUMR 244141
530#define BATT_ESR_DENR 1000
531static int fg_get_battery_esr(struct fg_chip *chip, int *val)
532{
533 int rc = 0;
534 u16 temp = 0;
535 u8 buf[2];
536
537 rc = fg_read(chip, BATT_INFO_ESR_LSB(chip), buf, 2);
538 if (rc < 0) {
539 pr_err("failed to read addr=0x%04x, rc=%d\n",
540 BATT_INFO_ESR_LSB(chip), rc);
541 return rc;
542 }
543
544 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4)
545 temp = ((buf[0] & ESR_MSB_MASK) << 8) |
546 (buf[1] & ESR_LSB_MASK);
547 else
548 temp = ((buf[1] & ESR_MSB_MASK) << 8) |
549 (buf[0] & ESR_LSB_MASK);
550
551 pr_debug("buf: %x %x temp: %x\n", buf[0], buf[1], temp);
552 *val = div_u64((u64)temp * BATT_ESR_NUMR, BATT_ESR_DENR);
553 return 0;
554}
555
556static int fg_get_battery_resistance(struct fg_chip *chip, int *val)
557{
558 int rc, esr, rslow;
559
560 rc = fg_get_battery_esr(chip, &esr);
561 if (rc < 0) {
562 pr_err("failed to get ESR, rc=%d\n", rc);
563 return rc;
564 }
565
566 rc = fg_get_sram_prop(chip, FG_SRAM_RSLOW, &rslow);
567 if (rc < 0) {
568 pr_err("failed to get Rslow, rc=%d\n", rc);
569 return rc;
570 }
571
572 *val = esr + rslow;
573 return 0;
574}
575
576#define BATT_CURRENT_NUMR 488281
577#define BATT_CURRENT_DENR 1000
578static int fg_get_battery_current(struct fg_chip *chip, int *val)
579{
580 int rc = 0;
581 int64_t temp = 0;
582 u8 buf[2];
583
584 rc = fg_read(chip, BATT_INFO_IBATT_LSB(chip), buf, 2);
585 if (rc < 0) {
586 pr_err("failed to read addr=0x%04x, rc=%d\n",
587 BATT_INFO_IBATT_LSB(chip), rc);
588 return rc;
589 }
590
591 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4)
592 temp = buf[0] << 8 | buf[1];
593 else
594 temp = buf[1] << 8 | buf[0];
595
596 pr_debug("buf: %x %x temp: %llx\n", buf[0], buf[1], temp);
597 /* Sign bit is bit 15 */
598 temp = twos_compliment_extend(temp, 15);
599 *val = div_s64((s64)temp * BATT_CURRENT_NUMR, BATT_CURRENT_DENR);
600 return 0;
601}
602
603#define BATT_VOLTAGE_NUMR 122070
604#define BATT_VOLTAGE_DENR 1000
605static int fg_get_battery_voltage(struct fg_chip *chip, int *val)
606{
607 int rc = 0;
608 u16 temp = 0;
609 u8 buf[2];
610
611 rc = fg_read(chip, BATT_INFO_VBATT_LSB(chip), buf, 2);
612 if (rc < 0) {
613 pr_err("failed to read addr=0x%04x, rc=%d\n",
614 BATT_INFO_VBATT_LSB(chip), rc);
615 return rc;
616 }
617
618 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4)
619 temp = buf[0] << 8 | buf[1];
620 else
621 temp = buf[1] << 8 | buf[0];
622
623 pr_debug("buf: %x %x temp: %x\n", buf[0], buf[1], temp);
624 *val = div_u64((u64)temp * BATT_VOLTAGE_NUMR, BATT_VOLTAGE_DENR);
625 return 0;
626}
627
628#define MAX_TRIES_SOC 5
629static int fg_get_msoc_raw(struct fg_chip *chip, int *val)
630{
631 u8 cap[2];
632 int rc, tries = 0;
633
634 while (tries < MAX_TRIES_SOC) {
635 rc = fg_read(chip, BATT_SOC_FG_MONOTONIC_SOC(chip), cap, 2);
636 if (rc < 0) {
637 pr_err("failed to read addr=0x%04x, rc=%d\n",
638 BATT_SOC_FG_MONOTONIC_SOC(chip), rc);
639 return rc;
640 }
641
642 if (cap[0] == cap[1])
643 break;
644
645 tries++;
646 }
647
648 if (tries == MAX_TRIES_SOC) {
649 pr_err("shadow registers do not match\n");
650 return -EINVAL;
651 }
652
653 fg_dbg(chip, FG_POWER_SUPPLY, "raw: 0x%02x\n", cap[0]);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700654 *val = cap[0];
655 return 0;
656}
657
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800658static bool is_batt_empty(struct fg_chip *chip)
659{
660 u8 status;
661 int rc, vbatt_uv, msoc;
662
663 rc = fg_read(chip, BATT_SOC_INT_RT_STS(chip), &status, 1);
664 if (rc < 0) {
665 pr_err("failed to read addr=0x%04x, rc=%d\n",
666 BATT_SOC_INT_RT_STS(chip), rc);
667 return false;
668 }
669
670 if (!(status & MSOC_EMPTY_BIT))
671 return false;
672
673 rc = fg_get_battery_voltage(chip, &vbatt_uv);
674 if (rc < 0) {
675 pr_err("failed to get battery voltage, rc=%d\n", rc);
676 return false;
677 }
678
679 rc = fg_get_msoc_raw(chip, &msoc);
680 if (!rc)
681 pr_warn("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", status,
682 vbatt_uv, msoc);
683
684 return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false);
685}
686
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700687#define DEBUG_BATT_ID_KOHMS 7
688static bool is_debug_batt_id(struct fg_chip *chip)
689{
690 int batt_id_delta = 0;
691
692 if (!chip->batt_id_kohms)
693 return false;
694
695 batt_id_delta = abs(chip->batt_id_kohms - DEBUG_BATT_ID_KOHMS);
696 if (batt_id_delta <= 1) {
697 fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dKohms\n",
698 chip->batt_id_kohms);
699 return true;
700 }
701
702 return false;
703}
704
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700705#define FULL_CAPACITY 100
706#define FULL_SOC_RAW 255
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700707#define DEBUG_BATT_SOC 67
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700708#define EMPTY_SOC 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700709static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
710{
711 int rc, msoc;
712
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700713 if (is_debug_batt_id(chip)) {
714 *val = DEBUG_BATT_SOC;
715 return 0;
716 }
717
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800718 if (is_batt_empty(chip)) {
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700719 *val = EMPTY_SOC;
720 return 0;
721 }
722
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700723 if (chip->charge_full) {
724 *val = FULL_CAPACITY;
725 return 0;
726 }
727
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700728 rc = fg_get_msoc_raw(chip, &msoc);
729 if (rc < 0)
730 return rc;
731
732 *val = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
733 return 0;
734}
735
736#define DEFAULT_BATT_TYPE "Unknown Battery"
737#define MISSING_BATT_TYPE "Missing Battery"
738#define LOADING_BATT_TYPE "Loading Battery"
739static const char *fg_get_battery_type(struct fg_chip *chip)
740{
741 if (chip->battery_missing)
742 return MISSING_BATT_TYPE;
743
744 if (chip->bp.batt_type_str) {
745 if (chip->profile_loaded)
746 return chip->bp.batt_type_str;
747 else
748 return LOADING_BATT_TYPE;
749 }
750
751 return DEFAULT_BATT_TYPE;
752}
753
754static int fg_get_batt_id(struct fg_chip *chip, int *val)
755{
756 int rc, batt_id = -EINVAL;
757
758 if (!chip->batt_id_chan)
759 return -EINVAL;
760
761 rc = iio_read_channel_processed(chip->batt_id_chan, &batt_id);
762 if (rc < 0) {
763 pr_err("Error in reading batt_id channel, rc:%d\n", rc);
764 return rc;
765 }
766
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700767 fg_dbg(chip, FG_STATUS, "batt_id: %d\n", batt_id);
768
769 *val = batt_id;
770 return 0;
771}
772
773static int fg_get_batt_profile(struct fg_chip *chip)
774{
775 struct device_node *node = chip->dev->of_node;
776 struct device_node *batt_node, *profile_node;
777 const char *data;
778 int rc, len, batt_id;
779
780 rc = fg_get_batt_id(chip, &batt_id);
781 if (rc < 0) {
782 pr_err("Error in getting batt_id rc:%d\n", rc);
783 return rc;
784 }
785
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700786 batt_id /= 1000;
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700787 chip->batt_id_kohms = batt_id;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700788 batt_node = of_find_node_by_name(node, "qcom,battery-data");
789 if (!batt_node) {
790 pr_err("Batterydata not available\n");
791 return -ENXIO;
792 }
793
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700794 profile_node = of_batterydata_get_best_profile(batt_node, batt_id,
795 NULL);
796 if (IS_ERR(profile_node))
797 return PTR_ERR(profile_node);
798
799 if (!profile_node) {
800 pr_err("couldn't find profile handle\n");
801 return -ENODATA;
802 }
803
804 rc = of_property_read_string(profile_node, "qcom,battery-type",
805 &chip->bp.batt_type_str);
806 if (rc < 0) {
807 pr_err("battery type unavailable, rc:%d\n", rc);
808 return rc;
809 }
810
811 rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv",
812 &chip->bp.float_volt_uv);
813 if (rc < 0) {
814 pr_err("battery float voltage unavailable, rc:%d\n", rc);
815 chip->bp.float_volt_uv = -EINVAL;
816 }
817
818 rc = of_property_read_u32(profile_node, "qcom,nom-batt-capacity-mah",
819 &chip->bp.fastchg_curr_ma);
820 if (rc < 0) {
821 pr_err("battery nominal capacity unavailable, rc:%d\n", rc);
822 chip->bp.fastchg_curr_ma = -EINVAL;
823 }
824
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700825 rc = of_property_read_u32(profile_node, "qcom,fg-cc-cv-threshold-mv",
826 &chip->bp.vbatt_full_mv);
827 if (rc < 0) {
828 pr_err("battery cc_cv threshold unavailable, rc:%d\n", rc);
829 chip->bp.vbatt_full_mv = -EINVAL;
830 }
831
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700832 data = of_get_property(profile_node, "qcom,fg-profile-data", &len);
833 if (!data) {
834 pr_err("No profile data available\n");
835 return -ENODATA;
836 }
837
838 if (len != PROFILE_LEN) {
839 pr_err("battery profile incorrect size: %d\n", len);
840 return -EINVAL;
841 }
842
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700843 chip->profile_available = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700844 memcpy(chip->batt_profile, data, len);
845 return 0;
846}
847
848static inline void get_temp_setpoint(int threshold, u8 *val)
849{
850 /* Resolution is 0.5C. Base is -30C. */
851 *val = DIV_ROUND_CLOSEST((threshold + 30) * 10, 5);
852}
853
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -0700854static inline void get_batt_temp_delta(int delta, u8 *val)
855{
856 switch (delta) {
857 case 2:
858 *val = BTEMP_DELTA_2K;
859 break;
860 case 4:
861 *val = BTEMP_DELTA_4K;
862 break;
863 case 6:
864 *val = BTEMP_DELTA_6K;
865 break;
866 case 10:
867 *val = BTEMP_DELTA_10K;
868 break;
869 default:
870 *val = BTEMP_DELTA_2K;
871 break;
872 };
873}
874
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700875static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
876 int flags)
877{
878 u8 buf[2];
879 int rc, timer_max, timer_init;
880
881 if (charging) {
882 timer_max = FG_SRAM_ESR_TIMER_CHG_MAX;
883 timer_init = FG_SRAM_ESR_TIMER_CHG_INIT;
884 } else {
885 timer_max = FG_SRAM_ESR_TIMER_DISCHG_MAX;
886 timer_init = FG_SRAM_ESR_TIMER_DISCHG_INIT;
887 }
888
889 fg_encode(chip->sp, timer_max, cycles, buf);
890 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700891 chip->sp[timer_max].addr_word,
892 chip->sp[timer_max].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700893 chip->sp[timer_max].len, flags);
894 if (rc < 0) {
895 pr_err("Error in writing esr_timer_dischg_max, rc=%d\n",
896 rc);
897 return rc;
898 }
899
900 fg_encode(chip->sp, timer_init, cycles, buf);
901 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700902 chip->sp[timer_init].addr_word,
903 chip->sp[timer_init].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700904 chip->sp[timer_init].len, flags);
905 if (rc < 0) {
906 pr_err("Error in writing esr_timer_dischg_init, rc=%d\n",
907 rc);
908 return rc;
909 }
910
911 return 0;
912}
913
Nicholas Troaste29dec92016-08-24 09:35:11 -0700914/* Other functions HERE */
915
916static int fg_awake_cb(struct votable *votable, void *data, int awake,
917 const char *client)
918{
919 struct fg_chip *chip = data;
920
921 if (awake)
922 pm_stay_awake(chip->dev);
923 else
924 pm_relax(chip->dev);
925
926 pr_debug("client: %s awake: %d\n", client, awake);
927 return 0;
928}
929
930static bool is_charger_available(struct fg_chip *chip)
931{
932 if (!chip->batt_psy)
933 chip->batt_psy = power_supply_get_by_name("battery");
934
935 if (!chip->batt_psy)
936 return false;
937
938 return true;
939}
940
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -0700941static bool is_parallel_charger_available(struct fg_chip *chip)
942{
943 if (!chip->parallel_psy)
944 chip->parallel_psy = power_supply_get_by_name("parallel");
945
946 if (!chip->parallel_psy)
947 return false;
948
949 return true;
950}
951
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700952static int fg_save_learned_cap_to_sram(struct fg_chip *chip)
953{
954 int16_t cc_mah;
955 int rc;
956
957 if (chip->battery_missing || !chip->cl.learned_cc_uah)
958 return -EPERM;
959
960 cc_mah = div64_s64(chip->cl.learned_cc_uah, 1000);
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700961 /* Write to a backup register to use across reboot */
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700962 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ACT_BATT_CAP].addr_word,
963 chip->sp[FG_SRAM_ACT_BATT_CAP].addr_byte, (u8 *)&cc_mah,
964 chip->sp[FG_SRAM_ACT_BATT_CAP].len, FG_IMA_DEFAULT);
965 if (rc < 0) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700966 pr_err("Error in writing act_batt_cap_bkup, rc=%d\n", rc);
967 return rc;
968 }
969
970 /* Write to actual capacity register for coulomb counter operation */
971 rc = fg_sram_write(chip, ACT_BATT_CAP_WORD, ACT_BATT_CAP_OFFSET,
972 (u8 *)&cc_mah, chip->sp[FG_SRAM_ACT_BATT_CAP].len,
973 FG_IMA_DEFAULT);
974 if (rc < 0) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700975 pr_err("Error in writing act_batt_cap, rc=%d\n", rc);
976 return rc;
977 }
978
979 fg_dbg(chip, FG_CAP_LEARN, "learned capacity %llduah/%dmah stored\n",
980 chip->cl.learned_cc_uah, cc_mah);
981 return 0;
982}
983
984#define CAPACITY_DELTA_DECIPCT 500
985static int fg_load_learned_cap_from_sram(struct fg_chip *chip)
986{
987 int rc, act_cap_mah;
988 int64_t delta_cc_uah, pct_nom_cap_uah;
989
990 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
991 if (rc < 0) {
992 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
993 return rc;
994 }
995
996 chip->cl.learned_cc_uah = act_cap_mah * 1000;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700997
998 if (chip->cl.learned_cc_uah != chip->cl.nom_cap_uah) {
Subbaraman Narayanamurthy51d3c902016-10-24 14:05:44 -0700999 if (chip->cl.learned_cc_uah == 0)
1000 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
1001
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001002 delta_cc_uah = abs(chip->cl.learned_cc_uah -
1003 chip->cl.nom_cap_uah);
1004 pct_nom_cap_uah = div64_s64((int64_t)chip->cl.nom_cap_uah *
1005 CAPACITY_DELTA_DECIPCT, 1000);
1006 /*
1007 * If the learned capacity is out of range by 50% from the
1008 * nominal capacity, then overwrite the learned capacity with
1009 * the nominal capacity.
1010 */
1011 if (chip->cl.nom_cap_uah && delta_cc_uah > pct_nom_cap_uah) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001012 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah: %lld is higher than expected, capping it to nominal: %lld\n",
1013 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001014 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001015 }
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001016
1017 rc = fg_save_learned_cap_to_sram(chip);
1018 if (rc < 0)
1019 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001020 }
1021
1022 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah:%lld nom_cap_uah: %lld\n",
1023 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
1024 return 0;
1025}
1026
1027static bool is_temp_valid_cap_learning(struct fg_chip *chip)
1028{
1029 int rc, batt_temp;
1030
1031 rc = fg_get_battery_temp(chip, &batt_temp);
1032 if (rc < 0) {
1033 pr_err("Error in getting batt_temp\n");
1034 return false;
1035 }
1036
1037 if (batt_temp > chip->dt.cl_max_temp ||
1038 batt_temp < chip->dt.cl_min_temp) {
1039 fg_dbg(chip, FG_CAP_LEARN, "batt temp %d out of range [%d %d]\n",
1040 batt_temp, chip->dt.cl_min_temp, chip->dt.cl_max_temp);
1041 return false;
1042 }
1043
1044 return true;
1045}
1046
1047static void fg_cap_learning_post_process(struct fg_chip *chip)
1048{
1049 int64_t max_inc_val, min_dec_val, old_cap;
1050 int rc;
1051
1052 max_inc_val = chip->cl.learned_cc_uah
1053 * (1000 + chip->dt.cl_max_cap_inc);
1054 do_div(max_inc_val, 1000);
1055
1056 min_dec_val = chip->cl.learned_cc_uah
1057 * (1000 - chip->dt.cl_max_cap_dec);
1058 do_div(min_dec_val, 1000);
1059
1060 old_cap = chip->cl.learned_cc_uah;
1061 if (chip->cl.final_cc_uah > max_inc_val)
1062 chip->cl.learned_cc_uah = max_inc_val;
1063 else if (chip->cl.final_cc_uah < min_dec_val)
1064 chip->cl.learned_cc_uah = min_dec_val;
1065 else
1066 chip->cl.learned_cc_uah =
1067 chip->cl.final_cc_uah;
1068
1069 if (chip->dt.cl_max_cap_limit) {
1070 max_inc_val = (int64_t)chip->cl.nom_cap_uah * (1000 +
1071 chip->dt.cl_max_cap_limit);
1072 do_div(max_inc_val, 1000);
1073 if (chip->cl.final_cc_uah > max_inc_val) {
1074 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes above max limit %lld\n",
1075 chip->cl.final_cc_uah, max_inc_val);
1076 chip->cl.learned_cc_uah = max_inc_val;
1077 }
1078 }
1079
1080 if (chip->dt.cl_min_cap_limit) {
1081 min_dec_val = (int64_t)chip->cl.nom_cap_uah * (1000 -
1082 chip->dt.cl_min_cap_limit);
1083 do_div(min_dec_val, 1000);
1084 if (chip->cl.final_cc_uah < min_dec_val) {
1085 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes below min limit %lld\n",
1086 chip->cl.final_cc_uah, min_dec_val);
1087 chip->cl.learned_cc_uah = min_dec_val;
1088 }
1089 }
1090
1091 rc = fg_save_learned_cap_to_sram(chip);
1092 if (rc < 0)
1093 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
1094
1095 fg_dbg(chip, FG_CAP_LEARN, "final cc_uah = %lld, learned capacity %lld -> %lld uah\n",
1096 chip->cl.final_cc_uah, old_cap, chip->cl.learned_cc_uah);
1097}
1098
1099static int fg_cap_learning_process_full_data(struct fg_chip *chip)
1100{
1101 int rc, cc_soc_sw, cc_soc_delta_pct;
1102 int64_t delta_cc_uah;
1103
1104 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1105 if (rc < 0) {
1106 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1107 return rc;
1108 }
1109
1110 cc_soc_delta_pct = DIV_ROUND_CLOSEST(
1111 abs(cc_soc_sw - chip->cl.init_cc_soc_sw) * 100,
1112 CC_SOC_30BIT);
1113 delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
1114 100);
1115 chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
1116 fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%d total_cc_uah=%lld\n",
1117 cc_soc_sw, cc_soc_delta_pct, chip->cl.final_cc_uah);
1118 return 0;
1119}
1120
1121static int fg_cap_learning_begin(struct fg_chip *chip, int batt_soc)
1122{
1123 int rc, cc_soc_sw;
1124
1125 if (DIV_ROUND_CLOSEST(batt_soc * 100, FULL_SOC_RAW) >
1126 chip->dt.cl_start_soc) {
1127 fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n",
1128 batt_soc);
1129 return -EINVAL;
1130 }
1131
1132 chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc,
1133 FULL_SOC_RAW);
1134 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1135 if (rc < 0) {
1136 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1137 return rc;
1138 }
1139
1140 chip->cl.init_cc_soc_sw = cc_soc_sw;
1141 chip->cl.active = true;
1142 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
1143 batt_soc, chip->cl.init_cc_soc_sw);
1144 return 0;
1145}
1146
1147static int fg_cap_learning_done(struct fg_chip *chip)
1148{
1149 int rc, cc_soc_sw;
1150
1151 rc = fg_cap_learning_process_full_data(chip);
1152 if (rc < 0) {
1153 pr_err("Error in processing cap learning full data, rc=%d\n",
1154 rc);
1155 goto out;
1156 }
1157
1158 /* Write a FULL value to cc_soc_sw */
1159 cc_soc_sw = CC_SOC_30BIT;
1160 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
1161 chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001162 chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001163 if (rc < 0) {
1164 pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
1165 goto out;
1166 }
1167
1168 fg_cap_learning_post_process(chip);
1169out:
1170 return rc;
1171}
1172
1173#define FULL_SOC_RAW 255
1174static void fg_cap_learning_update(struct fg_chip *chip)
1175{
1176 int rc, batt_soc;
1177
1178 mutex_lock(&chip->cl.lock);
1179
1180 if (!is_temp_valid_cap_learning(chip) || !chip->cl.learned_cc_uah ||
1181 chip->battery_missing) {
1182 fg_dbg(chip, FG_CAP_LEARN, "Aborting cap_learning %lld\n",
1183 chip->cl.learned_cc_uah);
1184 chip->cl.active = false;
1185 chip->cl.init_cc_uah = 0;
1186 goto out;
1187 }
1188
1189 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1190 if (rc < 0) {
1191 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
1192 goto out;
1193 }
1194
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001195 /* We need only the most significant byte here */
1196 batt_soc = (u32)batt_soc >> 24;
1197
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001198 fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n",
1199 chip->status, chip->cl.active, batt_soc);
1200
1201 /* Initialize the starting point of learning capacity */
1202 if (!chip->cl.active) {
1203 if (chip->status == POWER_SUPPLY_STATUS_CHARGING) {
1204 rc = fg_cap_learning_begin(chip, batt_soc);
1205 chip->cl.active = (rc == 0);
1206 }
1207
1208 } else {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001209 if (chip->charge_done) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001210 rc = fg_cap_learning_done(chip);
1211 if (rc < 0)
1212 pr_err("Error in completing capacity learning, rc=%d\n",
1213 rc);
1214
1215 chip->cl.active = false;
1216 chip->cl.init_cc_uah = 0;
1217 }
1218
1219 if (chip->status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
1220 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
1221 batt_soc);
1222 chip->cl.active = false;
1223 chip->cl.init_cc_uah = 0;
1224 }
1225 }
1226
1227out:
1228 mutex_unlock(&chip->cl.lock);
1229}
1230
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001231#define KI_COEFF_MED_DISCHG_DEFAULT 1500
1232#define KI_COEFF_HI_DISCHG_DEFAULT 2200
1233static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
1234{
1235 int rc, i, msoc;
1236 int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
1237 int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
1238 u8 val;
1239
1240 if (!chip->ki_coeff_dischg_en)
1241 return 0;
1242
1243 rc = fg_get_prop_capacity(chip, &msoc);
1244 if (rc < 0) {
1245 pr_err("Error in getting capacity, rc=%d\n", rc);
1246 return rc;
1247 }
1248
1249 if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
1250 for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
1251 if (msoc < chip->dt.ki_coeff_soc[i]) {
1252 ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
1253 ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
1254 }
1255 }
1256 }
1257
1258 fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
1259 rc = fg_sram_write(chip,
1260 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
1261 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
1262 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
1263 FG_IMA_DEFAULT);
1264 if (rc < 0) {
1265 pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
1266 return rc;
1267 }
1268
1269 fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
1270 rc = fg_sram_write(chip,
1271 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
1272 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
1273 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
1274 FG_IMA_DEFAULT);
1275 if (rc < 0) {
1276 pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
1277 return rc;
1278 }
1279
1280 fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
1281 ki_coeff_med, ki_coeff_hi);
1282 return 0;
1283}
1284
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001285static int fg_charge_full_update(struct fg_chip *chip)
1286{
1287 union power_supply_propval prop = {0, };
1288 int rc, msoc, bsoc, recharge_soc;
1289 u8 full_soc[2] = {0xFF, 0xFF};
1290
1291 if (!chip->dt.hold_soc_while_full)
1292 return 0;
1293
1294 if (!is_charger_available(chip))
1295 return 0;
1296
1297 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
1298 &prop);
1299 if (rc < 0) {
1300 pr_err("Error in getting battery health, rc=%d\n", rc);
1301 return rc;
1302 }
1303
1304 chip->health = prop.intval;
1305 recharge_soc = chip->dt.recharge_soc_thr;
1306 recharge_soc = DIV_ROUND_CLOSEST(recharge_soc * FULL_SOC_RAW,
1307 FULL_CAPACITY);
1308 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
1309 if (rc < 0) {
1310 pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
1311 return rc;
1312 }
1313
1314 /* We need 2 most significant bytes here */
1315 bsoc = (u32)bsoc >> 16;
1316 rc = fg_get_prop_capacity(chip, &msoc);
1317 if (rc < 0) {
1318 pr_err("Error in getting capacity, rc=%d\n", rc);
1319 return rc;
1320 }
1321
1322 fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc,
1323 chip->health, chip->status);
1324 if (chip->charge_done) {
1325 if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD)
1326 chip->charge_full = true;
1327 else
1328 fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
1329 msoc);
1330 } else if ((bsoc >> 8) <= recharge_soc) {
1331 fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d\n",
1332 bsoc >> 8, recharge_soc);
1333 chip->charge_full = false;
1334 }
1335
1336 if (!chip->charge_full)
1337 return 0;
1338
1339 /*
1340 * During JEITA conditions, charge_full can happen early. FULL_SOC
1341 * and MONOTONIC_SOC needs to be updated to reflect the same. Write
1342 * battery SOC to FULL_SOC and write a full value to MONOTONIC_SOC.
1343 */
1344 rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET, (u8 *)&bsoc, 2,
1345 FG_IMA_ATOMIC);
1346 if (rc < 0) {
1347 pr_err("failed to write full_soc rc=%d\n", rc);
1348 return rc;
1349 }
1350
1351 rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
1352 full_soc, 2, FG_IMA_ATOMIC);
1353 if (rc < 0) {
1354 pr_err("failed to write monotonic_soc rc=%d\n", rc);
1355 return rc;
1356 }
1357
1358 fg_dbg(chip, FG_STATUS, "Set charge_full to true @ soc %d\n", msoc);
1359 return 0;
1360}
1361
1362static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
1363{
1364 u8 buf[4];
1365 int rc;
1366
1367 fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf);
1368 rc = fg_sram_write(chip,
1369 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
1370 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, buf,
1371 chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
1372 if (rc < 0) {
1373 pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
1374 return rc;
1375 }
1376
1377 return 0;
1378}
1379
1380static int fg_adjust_recharge_soc(struct fg_chip *chip)
1381{
1382 int rc, msoc, recharge_soc, new_recharge_soc = 0;
1383
1384 recharge_soc = chip->dt.recharge_soc_thr;
1385 /*
1386 * If the input is present and charging had been terminated, adjust
1387 * the recharge SOC threshold based on the monotonic SOC at which
1388 * the charge termination had happened.
1389 */
1390 if (is_input_present(chip) && !chip->recharge_soc_adjusted
1391 && chip->charge_done) {
1392 /* Get raw monotonic SOC for calculation */
1393 rc = fg_get_msoc_raw(chip, &msoc);
1394 if (rc < 0) {
1395 pr_err("Error in getting msoc, rc=%d\n", rc);
1396 return rc;
1397 }
1398
1399 msoc = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
1400 /* Adjust the recharge_soc threshold */
1401 new_recharge_soc = msoc - (FULL_CAPACITY - recharge_soc);
1402 } else if (chip->recharge_soc_adjusted && (!is_input_present(chip)
1403 || chip->health == POWER_SUPPLY_HEALTH_GOOD)) {
1404 /* Restore the default value */
1405 new_recharge_soc = recharge_soc;
1406 }
1407
1408 if (new_recharge_soc > 0 && new_recharge_soc < FULL_CAPACITY) {
1409 rc = fg_set_recharge_soc(chip, new_recharge_soc);
1410 if (rc) {
1411 pr_err("Couldn't set resume SOC for FG, rc=%d\n", rc);
1412 return rc;
1413 }
1414
1415 chip->recharge_soc_adjusted = (new_recharge_soc !=
1416 recharge_soc);
1417 fg_dbg(chip, FG_STATUS, "resume soc set to %d\n",
1418 new_recharge_soc);
1419 }
1420
1421 return 0;
1422}
1423
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001424static int fg_esr_fcc_config(struct fg_chip *chip)
1425{
1426 union power_supply_propval prop = {0, };
1427 int rc;
1428 bool parallel_en = false;
1429
1430 if (is_parallel_charger_available(chip)) {
1431 rc = power_supply_get_property(chip->parallel_psy,
1432 POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
1433 if (rc < 0) {
1434 pr_err("Error in reading charging_enabled from parallel_psy, rc=%d\n",
1435 rc);
1436 return rc;
1437 }
1438 parallel_en = prop.intval;
1439 }
1440
1441 fg_dbg(chip, FG_POWER_SUPPLY, "status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n",
1442 chip->status, parallel_en, chip->esr_fcc_ctrl_en);
1443
1444 if (chip->status == POWER_SUPPLY_STATUS_CHARGING && parallel_en) {
1445 if (chip->esr_fcc_ctrl_en)
1446 return 0;
1447
1448 /*
1449 * When parallel charging is enabled, configure ESR FCC to
1450 * 300mA to trigger an ESR pulse. Without this, FG can ask
1451 * the main charger to increase FCC when it is supposed to
1452 * decrease it.
1453 */
1454 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
1455 ESR_FAST_CRG_IVAL_MASK |
1456 ESR_FAST_CRG_CTL_EN_BIT,
1457 ESR_FCC_300MA | ESR_FAST_CRG_CTL_EN_BIT);
1458 if (rc < 0) {
1459 pr_err("Error in writing to %04x, rc=%d\n",
1460 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
1461 return rc;
1462 }
1463
1464 chip->esr_fcc_ctrl_en = true;
1465 } else {
1466 if (!chip->esr_fcc_ctrl_en)
1467 return 0;
1468
1469 /*
1470 * If we're here, then it means either the device is not in
1471 * charging state or parallel charging is disabled. Disable
1472 * ESR fast charge current control in SW.
1473 */
1474 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
1475 ESR_FAST_CRG_CTL_EN_BIT, 0);
1476 if (rc < 0) {
1477 pr_err("Error in writing to %04x, rc=%d\n",
1478 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
1479 return rc;
1480 }
1481
1482 chip->esr_fcc_ctrl_en = false;
1483 }
1484
1485 fg_dbg(chip, FG_STATUS, "esr_fcc_ctrl_en set to %d\n",
1486 chip->esr_fcc_ctrl_en);
1487 return 0;
1488}
1489
Nicholas Troaste29dec92016-08-24 09:35:11 -07001490static void status_change_work(struct work_struct *work)
1491{
1492 struct fg_chip *chip = container_of(work,
1493 struct fg_chip, status_change_work);
1494 union power_supply_propval prop = {0, };
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001495 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001496
1497 if (!is_charger_available(chip)) {
1498 fg_dbg(chip, FG_STATUS, "Charger not available?!\n");
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001499 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001500 }
1501
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001502 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS,
Nicholas Troaste29dec92016-08-24 09:35:11 -07001503 &prop);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001504 if (rc < 0) {
1505 pr_err("Error in getting charging status, rc=%d\n", rc);
1506 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001507 }
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001508
1509 chip->status = prop.intval;
1510 rc = power_supply_get_property(chip->batt_psy,
1511 POWER_SUPPLY_PROP_CHARGE_DONE, &prop);
1512 if (rc < 0) {
1513 pr_err("Error in getting charge_done, rc=%d\n", rc);
1514 goto out;
1515 }
1516
1517 chip->charge_done = prop.intval;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001518 fg_dbg(chip, FG_POWER_SUPPLY, "curr_status:%d charge_done: %d\n",
1519 chip->status, chip->charge_done);
1520
1521 if (chip->cyc_ctr.en)
1522 schedule_work(&chip->cycle_count_work);
1523
1524 fg_cap_learning_update(chip);
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001525
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001526 rc = fg_charge_full_update(chip);
1527 if (rc < 0)
1528 pr_err("Error in charge_full_update, rc=%d\n", rc);
1529
1530 rc = fg_adjust_recharge_soc(chip);
1531 if (rc < 0)
1532 pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001533
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001534 rc = fg_adjust_ki_coeff_dischg(chip);
1535 if (rc < 0)
1536 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001537
1538 rc = fg_esr_fcc_config(chip);
1539 if (rc < 0)
1540 pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001541out:
1542 pm_relax(chip->dev);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001543}
1544
1545static void restore_cycle_counter(struct fg_chip *chip)
1546{
1547 int rc = 0, i;
1548 u8 data[2];
1549
1550 mutex_lock(&chip->cyc_ctr.lock);
1551 for (i = 0; i < BUCKET_COUNT; i++) {
1552 rc = fg_sram_read(chip, CYCLE_COUNT_WORD + (i / 2),
1553 CYCLE_COUNT_OFFSET + (i % 2) * 2, data, 2,
1554 FG_IMA_DEFAULT);
1555 if (rc < 0)
1556 pr_err("failed to read bucket %d rc=%d\n", i, rc);
1557 else
1558 chip->cyc_ctr.count[i] = data[0] | data[1] << 8;
1559 }
1560 mutex_unlock(&chip->cyc_ctr.lock);
1561}
1562
1563static void clear_cycle_counter(struct fg_chip *chip)
1564{
1565 int rc = 0, i;
1566
1567 if (!chip->cyc_ctr.en)
1568 return;
1569
1570 mutex_lock(&chip->cyc_ctr.lock);
1571 memset(chip->cyc_ctr.count, 0, sizeof(chip->cyc_ctr.count));
1572 for (i = 0; i < BUCKET_COUNT; i++) {
1573 chip->cyc_ctr.started[i] = false;
1574 chip->cyc_ctr.last_soc[i] = 0;
1575 }
1576 rc = fg_sram_write(chip, CYCLE_COUNT_WORD, CYCLE_COUNT_OFFSET,
1577 (u8 *)&chip->cyc_ctr.count,
1578 sizeof(chip->cyc_ctr.count) / sizeof(u8 *),
1579 FG_IMA_DEFAULT);
1580 if (rc < 0)
1581 pr_err("failed to clear cycle counter rc=%d\n", rc);
1582
1583 mutex_unlock(&chip->cyc_ctr.lock);
1584}
1585
1586static int fg_inc_store_cycle_ctr(struct fg_chip *chip, int bucket)
1587{
1588 int rc = 0;
1589 u16 cyc_count;
1590 u8 data[2];
1591
1592 if (bucket < 0 || (bucket > BUCKET_COUNT - 1))
1593 return 0;
1594
1595 cyc_count = chip->cyc_ctr.count[bucket];
1596 cyc_count++;
1597 data[0] = cyc_count & 0xFF;
1598 data[1] = cyc_count >> 8;
1599
1600 rc = fg_sram_write(chip, CYCLE_COUNT_WORD + (bucket / 2),
1601 CYCLE_COUNT_OFFSET + (bucket % 2) * 2, data, 2,
1602 FG_IMA_DEFAULT);
1603 if (rc < 0)
1604 pr_err("failed to write BATT_CYCLE[%d] rc=%d\n",
1605 bucket, rc);
1606 else
1607 chip->cyc_ctr.count[bucket] = cyc_count;
1608 return rc;
1609}
1610
1611static void cycle_count_work(struct work_struct *work)
1612{
1613 int rc = 0, bucket, i, batt_soc;
1614 struct fg_chip *chip = container_of(work,
1615 struct fg_chip,
1616 cycle_count_work);
1617
1618 mutex_lock(&chip->cyc_ctr.lock);
1619 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1620 if (rc < 0) {
1621 pr_err("Failed to read battery soc rc: %d\n", rc);
1622 goto out;
1623 }
1624
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001625 /* We need only the most significant byte here */
1626 batt_soc = (u32)batt_soc >> 24;
1627
Nicholas Troaste29dec92016-08-24 09:35:11 -07001628 if (chip->status == POWER_SUPPLY_STATUS_CHARGING) {
1629 /* Find out which bucket the SOC falls in */
1630 bucket = batt_soc / BUCKET_SOC_PCT;
1631 pr_debug("batt_soc: %d bucket: %d\n", batt_soc, bucket);
1632
1633 /*
1634 * If we've started counting for the previous bucket,
1635 * then store the counter for that bucket if the
1636 * counter for current bucket is getting started.
1637 */
1638 if (bucket > 0 && chip->cyc_ctr.started[bucket - 1] &&
1639 !chip->cyc_ctr.started[bucket]) {
1640 rc = fg_inc_store_cycle_ctr(chip, bucket - 1);
1641 if (rc < 0) {
1642 pr_err("Error in storing cycle_ctr rc: %d\n",
1643 rc);
1644 goto out;
1645 } else {
1646 chip->cyc_ctr.started[bucket - 1] = false;
1647 chip->cyc_ctr.last_soc[bucket - 1] = 0;
1648 }
1649 }
1650 if (!chip->cyc_ctr.started[bucket]) {
1651 chip->cyc_ctr.started[bucket] = true;
1652 chip->cyc_ctr.last_soc[bucket] = batt_soc;
1653 }
1654 } else {
1655 for (i = 0; i < BUCKET_COUNT; i++) {
1656 if (chip->cyc_ctr.started[i] &&
1657 batt_soc > chip->cyc_ctr.last_soc[i]) {
1658 rc = fg_inc_store_cycle_ctr(chip, i);
1659 if (rc < 0)
1660 pr_err("Error in storing cycle_ctr rc: %d\n",
1661 rc);
1662 chip->cyc_ctr.last_soc[i] = 0;
1663 }
1664 chip->cyc_ctr.started[i] = false;
1665 }
1666 }
1667out:
1668 mutex_unlock(&chip->cyc_ctr.lock);
1669}
1670
1671static int fg_get_cycle_count(struct fg_chip *chip)
1672{
1673 int count;
1674
1675 if (!chip->cyc_ctr.en)
1676 return 0;
1677
1678 if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT))
1679 return -EINVAL;
1680
1681 mutex_lock(&chip->cyc_ctr.lock);
1682 count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1];
1683 mutex_unlock(&chip->cyc_ctr.lock);
1684 return count;
1685}
1686
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001687static void dump_sram(u8 *buf, int len)
Nicholas Troaste29dec92016-08-24 09:35:11 -07001688{
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001689 int i;
1690 char str[16];
1691
1692 for (i = 0; i < len; i += 4) {
1693 str[0] = '\0';
1694 fill_string(str, sizeof(str), buf + i, 4);
1695 pr_info("%03d %s\n", PROFILE_LOAD_WORD + (i / 4), str);
1696 }
1697}
1698
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001699#define PROFILE_LOAD_BIT BIT(0)
1700#define BOOTLOADER_LOAD_BIT BIT(1)
1701#define BOOTLOADER_RESTART_BIT BIT(2)
1702#define HLOS_RESTART_BIT BIT(3)
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001703static bool is_profile_load_required(struct fg_chip *chip)
1704{
Nicholas Troaste29dec92016-08-24 09:35:11 -07001705 u8 buf[PROFILE_COMP_LEN], val;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001706 bool profiles_same = false;
1707 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001708
Nicholas Troaste29dec92016-08-24 09:35:11 -07001709 rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
1710 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
1711 if (rc < 0) {
1712 pr_err("failed to read profile integrity rc=%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001713 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001714 }
1715
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001716 /* Check if integrity bit is set */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001717 if (val & PROFILE_LOAD_BIT) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001718 fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
1719 rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
1720 buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
1721 if (rc < 0) {
1722 pr_err("Error in reading battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001723 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001724 }
1725 profiles_same = memcmp(chip->batt_profile, buf,
1726 PROFILE_COMP_LEN) == 0;
1727 if (profiles_same) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001728 fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
1729 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001730 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001731
1732 if (!chip->dt.force_load_profile) {
1733 pr_warn("Profiles doesn't match, skipping loading it since force_load_profile is disabled\n");
1734 if (fg_sram_dump) {
1735 pr_info("FG: loaded profile:\n");
1736 dump_sram(buf, PROFILE_COMP_LEN);
1737 pr_info("FG: available profile:\n");
1738 dump_sram(chip->batt_profile, PROFILE_LEN);
1739 }
1740 return false;
1741 }
1742
1743 fg_dbg(chip, FG_STATUS, "Profiles are different, loading the correct one\n");
1744 } else {
1745 fg_dbg(chip, FG_STATUS, "Profile integrity bit is not set\n");
1746 if (fg_sram_dump) {
1747 pr_info("FG: profile to be loaded:\n");
1748 dump_sram(chip->batt_profile, PROFILE_LEN);
1749 }
Nicholas Troaste29dec92016-08-24 09:35:11 -07001750 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001751 return true;
1752}
1753
1754#define SOC_READY_WAIT_MS 2000
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001755static int __fg_restart(struct fg_chip *chip)
1756{
1757 int rc, msoc;
1758 bool tried_again = false;
1759
1760 rc = fg_get_prop_capacity(chip, &msoc);
1761 if (rc < 0) {
1762 pr_err("Error in getting capacity, rc=%d\n", rc);
1763 return rc;
1764 }
1765
1766 chip->last_soc = msoc;
1767 chip->fg_restarting = true;
1768 reinit_completion(&chip->soc_ready);
1769 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT,
1770 RESTART_GO_BIT);
1771 if (rc < 0) {
1772 pr_err("Error in writing to %04x, rc=%d\n",
1773 BATT_SOC_RESTART(chip), rc);
1774 goto out;
1775 }
1776
1777wait:
1778 rc = wait_for_completion_interruptible_timeout(&chip->soc_ready,
1779 msecs_to_jiffies(SOC_READY_WAIT_MS));
1780
1781 /* If we were interrupted wait again one more time. */
1782 if (rc == -ERESTARTSYS && !tried_again) {
1783 tried_again = true;
1784 goto wait;
1785 } else if (rc <= 0) {
1786 pr_err("wait for soc_ready timed out rc=%d\n", rc);
1787 goto out;
1788 }
1789
1790 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
1791 if (rc < 0) {
1792 pr_err("Error in writing to %04x, rc=%d\n",
1793 BATT_SOC_RESTART(chip), rc);
1794 goto out;
1795 }
1796out:
1797 chip->fg_restarting = false;
1798 return rc;
1799}
1800
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001801static void fg_notify_charger(struct fg_chip *chip)
1802{
1803 union power_supply_propval prop = {0, };
1804 int rc;
1805
1806 if (!is_charger_available(chip)) {
1807 pr_warn("Charger not available yet?\n");
1808 return;
1809 }
1810
1811 prop.intval = chip->bp.float_volt_uv;
1812 rc = power_supply_set_property(chip->batt_psy,
1813 POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
1814 if (rc < 0) {
1815 pr_err("Error in setting voltage_max property on batt_psy, rc=%d\n",
1816 rc);
1817 return;
1818 }
1819
Subbaraman Narayanamurthya5d12622016-10-20 12:04:02 -07001820 prop.intval = chip->bp.fastchg_curr_ma * 1000;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001821 rc = power_supply_set_property(chip->batt_psy,
1822 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &prop);
1823 if (rc < 0) {
1824 pr_err("Error in setting constant_charge_current_max property on batt_psy, rc=%d\n",
1825 rc);
1826 return;
1827 }
1828
1829 fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
1830}
1831
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001832static void profile_load_work(struct work_struct *work)
1833{
1834 struct fg_chip *chip = container_of(work,
1835 struct fg_chip,
1836 profile_load_work.work);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001837 u8 buf[2], val;
1838 int rc;
1839
1840 vote(chip->awake_votable, PROFILE_LOAD, true, 0);
1841 if (!is_profile_load_required(chip))
1842 goto done;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001843
1844 clear_cycle_counter(chip);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001845 mutex_lock(&chip->cl.lock);
1846 chip->cl.learned_cc_uah = 0;
1847 chip->cl.active = false;
1848 mutex_unlock(&chip->cl.lock);
1849
Nicholas Troaste29dec92016-08-24 09:35:11 -07001850 fg_dbg(chip, FG_STATUS, "profile loading started\n");
1851 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
1852 if (rc < 0) {
1853 pr_err("Error in writing to %04x, rc=%d\n",
1854 BATT_SOC_RESTART(chip), rc);
1855 goto out;
1856 }
1857
1858 /* load battery profile */
1859 rc = fg_sram_write(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
1860 chip->batt_profile, PROFILE_LEN, FG_IMA_ATOMIC);
1861 if (rc < 0) {
1862 pr_err("Error in writing battery profile, rc:%d\n", rc);
1863 goto out;
1864 }
1865
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001866 rc = __fg_restart(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001867 if (rc < 0) {
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001868 pr_err("Error in restarting FG, rc=%d\n", rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001869 goto out;
1870 }
1871
1872 fg_dbg(chip, FG_STATUS, "SOC is ready\n");
1873
1874 /* Set the profile integrity bit */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001875 val = HLOS_RESTART_BIT | PROFILE_LOAD_BIT;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001876 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
1877 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
1878 if (rc < 0) {
1879 pr_err("failed to write profile integrity rc=%d\n", rc);
1880 goto out;
1881 }
1882
Nicholas Troaste29dec92016-08-24 09:35:11 -07001883done:
1884 rc = fg_sram_read(chip, NOM_CAP_WORD, NOM_CAP_OFFSET, buf, 2,
1885 FG_IMA_DEFAULT);
1886 if (rc < 0) {
1887 pr_err("Error in reading %04x[%d] rc=%d\n", NOM_CAP_WORD,
1888 NOM_CAP_OFFSET, rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001889 } else {
1890 chip->cl.nom_cap_uah = (int)(buf[0] | buf[1] << 8) * 1000;
1891 rc = fg_load_learned_cap_from_sram(chip);
1892 if (rc < 0)
1893 pr_err("Error in loading capacity learning data, rc:%d\n",
1894 rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001895 }
1896
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001897 fg_notify_charger(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001898 chip->profile_loaded = true;
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001899 fg_dbg(chip, FG_STATUS, "profile loaded successfully");
Nicholas Troaste29dec92016-08-24 09:35:11 -07001900out:
1901 vote(chip->awake_votable, PROFILE_LOAD, false, 0);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001902}
1903
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001904static int fg_restart_sysfs(const char *val, const struct kernel_param *kp)
1905{
1906 int rc;
1907 struct power_supply *bms_psy;
1908 struct fg_chip *chip;
1909
1910 rc = param_set_int(val, kp);
1911 if (rc) {
1912 pr_err("Unable to set fg_restart: %d\n", rc);
1913 return rc;
1914 }
1915
1916 if (fg_restart != 1) {
1917 pr_err("Bad value %d\n", fg_restart);
1918 return -EINVAL;
1919 }
1920
1921 bms_psy = power_supply_get_by_name("bms");
1922 if (!bms_psy) {
1923 pr_err("bms psy not found\n");
1924 return 0;
1925 }
1926
1927 chip = power_supply_get_drvdata(bms_psy);
1928 rc = __fg_restart(chip);
1929 if (rc < 0) {
1930 pr_err("Error in restarting FG, rc=%d\n", rc);
1931 return rc;
1932 }
1933
1934 pr_info("FG restart done\n");
1935 return rc;
1936}
1937
1938static struct kernel_param_ops fg_restart_ops = {
1939 .set = fg_restart_sysfs,
1940 .get = param_get_int,
1941};
1942
1943module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
1944
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001945/* PSY CALLBACKS STAY HERE */
1946
1947static int fg_psy_get_property(struct power_supply *psy,
1948 enum power_supply_property psp,
1949 union power_supply_propval *pval)
1950{
1951 struct fg_chip *chip = power_supply_get_drvdata(psy);
1952 int rc = 0;
1953
1954 switch (psp) {
1955 case POWER_SUPPLY_PROP_CAPACITY:
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001956 if (chip->fg_restarting)
1957 pval->intval = chip->last_soc;
1958 else
1959 rc = fg_get_prop_capacity(chip, &pval->intval);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001960 break;
1961 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1962 rc = fg_get_battery_voltage(chip, &pval->intval);
1963 break;
1964 case POWER_SUPPLY_PROP_CURRENT_NOW:
1965 rc = fg_get_battery_current(chip, &pval->intval);
1966 break;
1967 case POWER_SUPPLY_PROP_TEMP:
1968 rc = fg_get_battery_temp(chip, &pval->intval);
1969 break;
1970 case POWER_SUPPLY_PROP_RESISTANCE:
1971 rc = fg_get_battery_resistance(chip, &pval->intval);
1972 break;
1973 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
1974 rc = fg_get_sram_prop(chip, FG_SRAM_OCV, &pval->intval);
1975 break;
1976 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001977 pval->intval = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001978 break;
1979 case POWER_SUPPLY_PROP_RESISTANCE_ID:
1980 rc = fg_get_batt_id(chip, &pval->intval);
1981 break;
1982 case POWER_SUPPLY_PROP_BATTERY_TYPE:
1983 pval->strval = fg_get_battery_type(chip);
1984 break;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07001985 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1986 pval->intval = chip->bp.float_volt_uv;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001987 break;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001988 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1989 pval->intval = fg_get_cycle_count(chip);
1990 break;
1991 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
1992 pval->intval = chip->cyc_ctr.id;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07001993 break;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001994 case POWER_SUPPLY_PROP_CHARGE_NOW_RAW:
1995 rc = fg_get_cc_soc(chip, &pval->intval);
1996 break;
1997 case POWER_SUPPLY_PROP_CHARGE_NOW:
1998 pval->intval = chip->cl.init_cc_uah;
1999 break;
2000 case POWER_SUPPLY_PROP_CHARGE_FULL:
2001 pval->intval = chip->cl.learned_cc_uah;
2002 break;
2003 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
2004 rc = fg_get_cc_soc_sw(chip, &pval->intval);
2005 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002006 default:
2007 break;
2008 }
2009
2010 return rc;
2011}
2012
2013static int fg_psy_set_property(struct power_supply *psy,
2014 enum power_supply_property psp,
2015 const union power_supply_propval *pval)
2016{
Nicholas Troaste29dec92016-08-24 09:35:11 -07002017 struct fg_chip *chip = power_supply_get_drvdata(psy);
2018
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002019 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002020 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
2021 if ((pval->intval > 0) && (pval->intval <= BUCKET_COUNT)) {
2022 chip->cyc_ctr.id = pval->intval;
2023 } else {
2024 pr_err("rejecting invalid cycle_count_id = %d\n",
2025 pval->intval);
2026 return -EINVAL;
2027 }
2028 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002029 default:
2030 break;
2031 }
2032
2033 return 0;
2034}
2035
2036static int fg_property_is_writeable(struct power_supply *psy,
2037 enum power_supply_property psp)
2038{
2039 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002040 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
2041 return 1;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002042 default:
2043 break;
2044 }
2045
2046 return 0;
2047}
2048
2049static void fg_external_power_changed(struct power_supply *psy)
2050{
2051 pr_debug("power supply changed\n");
2052}
2053
2054static int fg_notifier_cb(struct notifier_block *nb,
2055 unsigned long event, void *data)
2056{
2057 struct power_supply *psy = data;
2058 struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
2059
2060 if (event != PSY_EVENT_PROP_CHANGED)
2061 return NOTIFY_OK;
2062
2063 if ((strcmp(psy->desc->name, "battery") == 0)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002064 || (strcmp(psy->desc->name, "usb") == 0)) {
2065 /*
2066 * We cannot vote for awake votable here as that takes
2067 * a mutex lock and this is executed in an atomic context.
2068 */
2069 pm_stay_awake(chip->dev);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002070 schedule_work(&chip->status_change_work);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002071 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002072
2073 return NOTIFY_OK;
2074}
2075
2076static enum power_supply_property fg_psy_props[] = {
2077 POWER_SUPPLY_PROP_CAPACITY,
2078 POWER_SUPPLY_PROP_TEMP,
2079 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2080 POWER_SUPPLY_PROP_VOLTAGE_OCV,
2081 POWER_SUPPLY_PROP_CURRENT_NOW,
2082 POWER_SUPPLY_PROP_RESISTANCE_ID,
2083 POWER_SUPPLY_PROP_RESISTANCE,
2084 POWER_SUPPLY_PROP_BATTERY_TYPE,
2085 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07002086 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Nicholas Troaste29dec92016-08-24 09:35:11 -07002087 POWER_SUPPLY_PROP_CYCLE_COUNT,
2088 POWER_SUPPLY_PROP_CYCLE_COUNT_ID,
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002089 POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
2090 POWER_SUPPLY_PROP_CHARGE_NOW,
2091 POWER_SUPPLY_PROP_CHARGE_FULL,
2092 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002093};
2094
2095static const struct power_supply_desc fg_psy_desc = {
2096 .name = "bms",
2097 .type = POWER_SUPPLY_TYPE_BMS,
2098 .properties = fg_psy_props,
2099 .num_properties = ARRAY_SIZE(fg_psy_props),
2100 .get_property = fg_psy_get_property,
2101 .set_property = fg_psy_set_property,
2102 .external_power_changed = fg_external_power_changed,
2103 .property_is_writeable = fg_property_is_writeable,
2104};
2105
2106/* INIT FUNCTIONS STAY HERE */
2107
2108static int fg_hw_init(struct fg_chip *chip)
2109{
2110 int rc;
2111 u8 buf[4], val;
2112
2113 fg_encode(chip->sp, FG_SRAM_CUTOFF_VOLT, chip->dt.cutoff_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002114 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CUTOFF_VOLT].addr_word,
2115 chip->sp[FG_SRAM_CUTOFF_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002116 chip->sp[FG_SRAM_CUTOFF_VOLT].len, FG_IMA_DEFAULT);
2117 if (rc < 0) {
2118 pr_err("Error in writing cutoff_volt, rc=%d\n", rc);
2119 return rc;
2120 }
2121
2122 fg_encode(chip->sp, FG_SRAM_EMPTY_VOLT, chip->dt.empty_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002123 rc = fg_sram_write(chip, chip->sp[FG_SRAM_EMPTY_VOLT].addr_word,
2124 chip->sp[FG_SRAM_EMPTY_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002125 chip->sp[FG_SRAM_EMPTY_VOLT].len, FG_IMA_DEFAULT);
2126 if (rc < 0) {
2127 pr_err("Error in writing empty_volt, rc=%d\n", rc);
2128 return rc;
2129 }
2130
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002131 /* This SRAM register is only present in v2.0 */
2132 if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4 &&
2133 chip->bp.float_volt_uv > 0) {
2134 fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT,
2135 chip->bp.float_volt_uv / 1000, buf);
2136 rc = fg_sram_write(chip, chip->sp[FG_SRAM_FLOAT_VOLT].addr_word,
2137 chip->sp[FG_SRAM_FLOAT_VOLT].addr_byte, buf,
2138 chip->sp[FG_SRAM_FLOAT_VOLT].len, FG_IMA_DEFAULT);
2139 if (rc < 0) {
2140 pr_err("Error in writing float_volt, rc=%d\n", rc);
2141 return rc;
2142 }
2143 }
2144
2145 if (chip->bp.vbatt_full_mv > 0) {
2146 fg_encode(chip->sp, FG_SRAM_VBATT_FULL, chip->bp.vbatt_full_mv,
2147 buf);
2148 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_FULL].addr_word,
2149 chip->sp[FG_SRAM_VBATT_FULL].addr_byte, buf,
2150 chip->sp[FG_SRAM_VBATT_FULL].len, FG_IMA_DEFAULT);
2151 if (rc < 0) {
2152 pr_err("Error in writing vbatt_full, rc=%d\n", rc);
2153 return rc;
2154 }
2155 }
2156
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002157 fg_encode(chip->sp, FG_SRAM_CHG_TERM_CURR, chip->dt.chg_term_curr_ma,
2158 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002159 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CHG_TERM_CURR].addr_word,
2160 chip->sp[FG_SRAM_CHG_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002161 chip->sp[FG_SRAM_CHG_TERM_CURR].len, FG_IMA_DEFAULT);
2162 if (rc < 0) {
2163 pr_err("Error in writing chg_term_curr, rc=%d\n", rc);
2164 return rc;
2165 }
2166
2167 fg_encode(chip->sp, FG_SRAM_SYS_TERM_CURR, chip->dt.sys_term_curr_ma,
2168 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002169 rc = fg_sram_write(chip, chip->sp[FG_SRAM_SYS_TERM_CURR].addr_word,
2170 chip->sp[FG_SRAM_SYS_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002171 chip->sp[FG_SRAM_SYS_TERM_CURR].len, FG_IMA_DEFAULT);
2172 if (rc < 0) {
2173 pr_err("Error in writing sys_term_curr, rc=%d\n", rc);
2174 return rc;
2175 }
2176
2177 if (chip->dt.vbatt_low_thr_mv > 0) {
2178 fg_encode(chip->sp, FG_SRAM_VBATT_LOW,
2179 chip->dt.vbatt_low_thr_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002180 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_LOW].addr_word,
2181 chip->sp[FG_SRAM_VBATT_LOW].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002182 chip->sp[FG_SRAM_VBATT_LOW].len,
2183 FG_IMA_DEFAULT);
2184 if (rc < 0) {
2185 pr_err("Error in writing vbatt_low_thr, rc=%d\n", rc);
2186 return rc;
2187 }
2188 }
2189
2190 if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) {
2191 fg_encode(chip->sp, FG_SRAM_DELTA_SOC_THR,
2192 chip->dt.delta_soc_thr, buf);
2193 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -07002194 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_word,
2195 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002196 buf, chip->sp[FG_SRAM_DELTA_SOC_THR].len,
2197 FG_IMA_DEFAULT);
2198 if (rc < 0) {
2199 pr_err("Error in writing delta_soc_thr, rc=%d\n", rc);
2200 return rc;
2201 }
2202 }
2203
2204 if (chip->dt.recharge_soc_thr > 0 && chip->dt.recharge_soc_thr < 100) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002205 rc = fg_set_recharge_soc(chip, chip->dt.recharge_soc_thr);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002206 if (rc < 0) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002207 pr_err("Error in setting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002208 return rc;
2209 }
2210 }
2211
2212 if (chip->dt.rsense_sel >= SRC_SEL_BATFET &&
2213 chip->dt.rsense_sel < SRC_SEL_RESERVED) {
2214 rc = fg_masked_write(chip, BATT_INFO_IBATT_SENSING_CFG(chip),
2215 SOURCE_SELECT_MASK, chip->dt.rsense_sel);
2216 if (rc < 0) {
2217 pr_err("Error in writing rsense_sel, rc=%d\n", rc);
2218 return rc;
2219 }
2220 }
2221
2222 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COLD], &val);
2223 rc = fg_write(chip, BATT_INFO_JEITA_TOO_COLD(chip), &val, 1);
2224 if (rc < 0) {
2225 pr_err("Error in writing jeita_cold, rc=%d\n", rc);
2226 return rc;
2227 }
2228
2229 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COOL], &val);
2230 rc = fg_write(chip, BATT_INFO_JEITA_COLD(chip), &val, 1);
2231 if (rc < 0) {
2232 pr_err("Error in writing jeita_cool, rc=%d\n", rc);
2233 return rc;
2234 }
2235
2236 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_WARM], &val);
2237 rc = fg_write(chip, BATT_INFO_JEITA_HOT(chip), &val, 1);
2238 if (rc < 0) {
2239 pr_err("Error in writing jeita_warm, rc=%d\n", rc);
2240 return rc;
2241 }
2242
2243 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_HOT], &val);
2244 rc = fg_write(chip, BATT_INFO_JEITA_TOO_HOT(chip), &val, 1);
2245 if (rc < 0) {
2246 pr_err("Error in writing jeita_hot, rc=%d\n", rc);
2247 return rc;
2248 }
2249
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002250 if (chip->dt.esr_timer_charging > 0) {
2251 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_charging, true,
2252 FG_IMA_DEFAULT);
2253 if (rc < 0) {
2254 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2255 return rc;
2256 }
2257 }
2258
2259 if (chip->dt.esr_timer_awake > 0) {
2260 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
2261 FG_IMA_DEFAULT);
2262 if (rc < 0) {
2263 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2264 return rc;
2265 }
2266 }
2267
Nicholas Troaste29dec92016-08-24 09:35:11 -07002268 if (chip->cyc_ctr.en)
2269 restore_cycle_counter(chip);
2270
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002271 if (chip->dt.jeita_hyst_temp >= 0) {
2272 val = chip->dt.jeita_hyst_temp << JEITA_TEMP_HYST_SHIFT;
2273 rc = fg_masked_write(chip, BATT_INFO_BATT_TEMP_CFG(chip),
2274 JEITA_TEMP_HYST_MASK, val);
2275 if (rc < 0) {
2276 pr_err("Error in writing batt_temp_cfg, rc=%d\n", rc);
2277 return rc;
2278 }
2279 }
2280
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002281 get_batt_temp_delta(chip->dt.batt_temp_delta, &val);
2282 rc = fg_masked_write(chip, BATT_INFO_BATT_TMPR_INTR(chip),
2283 CHANGE_THOLD_MASK, val);
2284 if (rc < 0) {
2285 pr_err("Error in writing batt_temp_delta, rc=%d\n", rc);
2286 return rc;
2287 }
2288
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002289 return 0;
2290}
2291
2292static int fg_memif_init(struct fg_chip *chip)
2293{
2294 return fg_ima_init(chip);
2295}
2296
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002297/* INTERRUPT HANDLERS STAY HERE */
2298
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07002299static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
2300{
2301 struct fg_chip *chip = data;
2302 u8 status;
2303 int rc;
2304
2305 rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1);
2306 if (rc < 0) {
2307 pr_err("failed to read addr=0x%04x, rc=%d\n",
2308 MEM_IF_INT_RT_STS(chip), rc);
2309 return IRQ_HANDLED;
2310 }
2311
2312 fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status);
2313 if (status & MEM_XCP_BIT) {
2314 rc = fg_clear_dma_errors_if_any(chip);
2315 if (rc < 0) {
2316 pr_err("Error in clearing DMA error, rc=%d\n", rc);
2317 return IRQ_HANDLED;
2318 }
2319
2320 mutex_lock(&chip->sram_rw_lock);
2321 rc = fg_clear_ima_errors_if_any(chip, true);
2322 if (rc < 0 && rc != -EAGAIN)
2323 pr_err("Error in checking IMA errors rc:%d\n", rc);
2324 mutex_unlock(&chip->sram_rw_lock);
2325 }
2326
2327 return IRQ_HANDLED;
2328}
2329
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002330static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
2331{
2332 struct fg_chip *chip = data;
2333
2334 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2335 return IRQ_HANDLED;
2336}
2337
2338static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
2339{
2340 struct fg_chip *chip = data;
2341 u8 status;
2342 int rc;
2343
2344 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2345 rc = fg_read(chip, BATT_INFO_INT_RT_STS(chip), &status, 1);
2346 if (rc < 0) {
2347 pr_err("failed to read addr=0x%04x, rc=%d\n",
2348 BATT_INFO_INT_RT_STS(chip), rc);
2349 return IRQ_HANDLED;
2350 }
2351
2352 chip->battery_missing = (status & BT_MISS_BIT);
2353
2354 if (chip->battery_missing) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002355 chip->profile_available = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002356 chip->profile_loaded = false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002357 clear_cycle_counter(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002358 } else {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002359 rc = fg_get_batt_profile(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002360 if (rc < 0) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002361 pr_err("Error in getting battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002362 return IRQ_HANDLED;
2363 }
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002364 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002365 }
2366
2367 return IRQ_HANDLED;
2368}
2369
2370static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data)
2371{
2372 struct fg_chip *chip = data;
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002373 union power_supply_propval prop = {0, };
2374 int rc, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002375
2376 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002377 rc = fg_get_battery_temp(chip, &batt_temp);
2378 if (rc < 0) {
2379 pr_err("Error in getting batt_temp\n");
2380 return IRQ_HANDLED;
2381 }
2382
2383 if (!is_charger_available(chip)) {
2384 chip->last_batt_temp = batt_temp;
2385 return IRQ_HANDLED;
2386 }
2387
2388 power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
2389 &prop);
2390 chip->health = prop.intval;
2391
2392 if (chip->last_batt_temp != batt_temp) {
2393 chip->last_batt_temp = batt_temp;
2394 power_supply_changed(chip->batt_psy);
2395 }
2396
2397 if (abs(chip->last_batt_temp - batt_temp) > 30)
2398 pr_warn("Battery temperature last:%d current: %d\n",
2399 chip->last_batt_temp, batt_temp);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002400 return IRQ_HANDLED;
2401}
2402
2403static irqreturn_t fg_first_est_irq_handler(int irq, void *data)
2404{
2405 struct fg_chip *chip = data;
2406
2407 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2408 complete_all(&chip->soc_ready);
2409 return IRQ_HANDLED;
2410}
2411
2412static irqreturn_t fg_soc_update_irq_handler(int irq, void *data)
2413{
2414 struct fg_chip *chip = data;
2415
2416 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2417 complete_all(&chip->soc_update);
2418 return IRQ_HANDLED;
2419}
2420
2421static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
2422{
2423 struct fg_chip *chip = data;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002424 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002425
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08002426 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002427 if (chip->cyc_ctr.en)
2428 schedule_work(&chip->cycle_count_work);
2429
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002430 if (chip->cl.active)
2431 fg_cap_learning_update(chip);
2432
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002433 rc = fg_charge_full_update(chip);
2434 if (rc < 0)
2435 pr_err("Error in charge_full_update, rc=%d\n", rc);
2436
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002437 rc = fg_adjust_ki_coeff_dischg(chip);
2438 if (rc < 0)
2439 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
2440
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08002441 if (is_charger_available(chip))
2442 power_supply_changed(chip->batt_psy);
2443
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002444 return IRQ_HANDLED;
2445}
2446
2447static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data)
2448{
2449 struct fg_chip *chip = data;
2450
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08002451 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Nicholas Troast65e29652016-09-22 11:27:04 -07002452 if (is_charger_available(chip))
2453 power_supply_changed(chip->batt_psy);
2454
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002455 return IRQ_HANDLED;
2456}
2457
2458static irqreturn_t fg_soc_irq_handler(int irq, void *data)
2459{
2460 struct fg_chip *chip = data;
2461
2462 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2463 return IRQ_HANDLED;
2464}
2465
2466static irqreturn_t fg_dummy_irq_handler(int irq, void *data)
2467{
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08002468 pr_debug("irq %d triggered\n", irq);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002469 return IRQ_HANDLED;
2470}
2471
2472static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
2473 /* BATT_SOC irqs */
2474 [MSOC_FULL_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002475 .name = "msoc-full",
2476 .handler = fg_soc_irq_handler,
2477 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002478 [MSOC_HIGH_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002479 .name = "msoc-high",
2480 .handler = fg_soc_irq_handler,
2481 .wakeable = true,
2482 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002483 [MSOC_EMPTY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002484 .name = "msoc-empty",
2485 .handler = fg_empty_soc_irq_handler,
2486 .wakeable = true,
2487 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002488 [MSOC_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002489 .name = "msoc-low",
2490 .handler = fg_soc_irq_handler,
2491 .wakeable = true,
2492 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002493 [MSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002494 .name = "msoc-delta",
2495 .handler = fg_delta_soc_irq_handler,
2496 .wakeable = true,
2497 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002498 [BSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002499 .name = "bsoc-delta",
2500 .handler = fg_dummy_irq_handler,
2501 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002502 [SOC_READY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002503 .name = "soc-ready",
2504 .handler = fg_first_est_irq_handler,
2505 .wakeable = true,
2506 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002507 [SOC_UPDATE_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002508 .name = "soc-update",
2509 .handler = fg_soc_update_irq_handler,
2510 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002511 /* BATT_INFO irqs */
2512 [BATT_TEMP_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002513 .name = "batt-temp-delta",
2514 .handler = fg_delta_batt_temp_irq_handler,
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002515 .wakeable = true,
Nicholas Troast3cc97182016-09-23 08:54:13 -07002516 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002517 [BATT_MISSING_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002518 .name = "batt-missing",
2519 .handler = fg_batt_missing_irq_handler,
2520 .wakeable = true,
2521 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002522 [ESR_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002523 .name = "esr-delta",
2524 .handler = fg_dummy_irq_handler,
2525 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002526 [VBATT_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002527 .name = "vbatt-low",
2528 .handler = fg_vbatt_low_irq_handler,
2529 .wakeable = true,
2530 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002531 [VBATT_PRED_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002532 .name = "vbatt-pred-delta",
2533 .handler = fg_dummy_irq_handler,
2534 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002535 /* MEM_IF irqs */
2536 [DMA_GRANT_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002537 .name = "dma-grant",
2538 .handler = fg_dummy_irq_handler,
2539 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002540 [MEM_XCP_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002541 .name = "mem-xcp",
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07002542 .handler = fg_mem_xcp_irq_handler,
Nicholas Troast3cc97182016-09-23 08:54:13 -07002543 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002544 [IMA_RDY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002545 .name = "ima-rdy",
2546 .handler = fg_dummy_irq_handler,
2547 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002548};
2549
2550static int fg_get_irq_index_byname(const char *name)
2551{
2552 int i;
2553
2554 for (i = 0; i < ARRAY_SIZE(fg_irqs); i++) {
2555 if (strcmp(fg_irqs[i].name, name) == 0)
2556 return i;
2557 }
2558
2559 pr_err("%s is not in irq list\n", name);
2560 return -ENOENT;
2561}
2562
2563static int fg_register_interrupts(struct fg_chip *chip)
2564{
2565 struct device_node *child, *node = chip->dev->of_node;
2566 struct property *prop;
2567 const char *name;
2568 int rc, irq, irq_index;
2569
2570 for_each_available_child_of_node(node, child) {
2571 of_property_for_each_string(child, "interrupt-names", prop,
2572 name) {
2573 irq = of_irq_get_byname(child, name);
2574 if (irq < 0) {
2575 dev_err(chip->dev, "failed to get irq %s irq:%d\n",
2576 name, irq);
2577 return irq;
2578 }
2579
2580 irq_index = fg_get_irq_index_byname(name);
2581 if (irq_index < 0)
2582 return irq_index;
2583
2584 rc = devm_request_threaded_irq(chip->dev, irq, NULL,
2585 fg_irqs[irq_index].handler,
2586 IRQF_ONESHOT, name, chip);
2587 if (rc < 0) {
2588 dev_err(chip->dev, "failed to register irq handler for %s rc:%d\n",
2589 name, rc);
2590 return rc;
2591 }
2592
2593 fg_irqs[irq_index].irq = irq;
2594 if (fg_irqs[irq_index].wakeable)
2595 enable_irq_wake(fg_irqs[irq_index].irq);
2596 }
2597 }
2598
2599 return 0;
2600}
2601
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002602static int fg_parse_ki_coefficients(struct fg_chip *chip)
2603{
2604 struct device_node *node = chip->dev->of_node;
2605 int rc, i;
2606
2607 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-soc-dischg",
2608 sizeof(u32));
2609 if (rc != KI_COEFF_SOC_LEVELS)
2610 return 0;
2611
2612 rc = of_property_read_u32_array(node, "qcom,ki-coeff-soc-dischg",
2613 chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
2614 if (rc < 0) {
2615 pr_err("Error in reading ki-coeff-soc-dischg, rc=%d\n",
2616 rc);
2617 return rc;
2618 }
2619
2620 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-med-dischg",
2621 sizeof(u32));
2622 if (rc != KI_COEFF_SOC_LEVELS)
2623 return 0;
2624
2625 rc = of_property_read_u32_array(node, "qcom,ki-coeff-med-dischg",
2626 chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
2627 if (rc < 0) {
2628 pr_err("Error in reading ki-coeff-med-dischg, rc=%d\n",
2629 rc);
2630 return rc;
2631 }
2632
2633 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-hi-dischg",
2634 sizeof(u32));
2635 if (rc != KI_COEFF_SOC_LEVELS)
2636 return 0;
2637
2638 rc = of_property_read_u32_array(node, "qcom,ki-coeff-hi-dischg",
2639 chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
2640 if (rc < 0) {
2641 pr_err("Error in reading ki-coeff-hi-dischg, rc=%d\n",
2642 rc);
2643 return rc;
2644 }
2645
2646 for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
2647 if (chip->dt.ki_coeff_soc[i] < 0 ||
2648 chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
2649 pr_err("Error in ki_coeff_soc_dischg values\n");
2650 return -EINVAL;
2651 }
2652
2653 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
2654 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
2655 pr_err("Error in ki_coeff_med_dischg values\n");
2656 return -EINVAL;
2657 }
2658
2659 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
2660 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
2661 pr_err("Error in ki_coeff_med_dischg values\n");
2662 return -EINVAL;
2663 }
2664 }
2665 chip->ki_coeff_dischg_en = true;
2666 return 0;
2667}
2668
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002669#define DEFAULT_CUTOFF_VOLT_MV 3200
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -07002670#define DEFAULT_EMPTY_VOLT_MV 2800
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002671#define DEFAULT_CHG_TERM_CURR_MA 100
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -07002672#define DEFAULT_SYS_TERM_CURR_MA -125
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002673#define DEFAULT_DELTA_SOC_THR 1
2674#define DEFAULT_RECHARGE_SOC_THR 95
2675#define DEFAULT_BATT_TEMP_COLD 0
2676#define DEFAULT_BATT_TEMP_COOL 5
2677#define DEFAULT_BATT_TEMP_WARM 45
2678#define DEFAULT_BATT_TEMP_HOT 50
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002679#define DEFAULT_CL_START_SOC 15
2680#define DEFAULT_CL_MIN_TEMP_DECIDEGC 150
2681#define DEFAULT_CL_MAX_TEMP_DECIDEGC 450
2682#define DEFAULT_CL_MAX_INC_DECIPERC 5
2683#define DEFAULT_CL_MAX_DEC_DECIPERC 100
2684#define DEFAULT_CL_MIN_LIM_DECIPERC 0
2685#define DEFAULT_CL_MAX_LIM_DECIPERC 0
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002686#define BTEMP_DELTA_LOW 2
2687#define BTEMP_DELTA_HIGH 10
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002688static int fg_parse_dt(struct fg_chip *chip)
2689{
2690 struct device_node *child, *revid_node, *node = chip->dev->of_node;
2691 u32 base, temp;
2692 u8 subtype;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002693 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002694
2695 if (!node) {
2696 dev_err(chip->dev, "device tree node missing\n");
2697 return -ENXIO;
2698 }
2699
2700 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
2701 if (!revid_node) {
2702 pr_err("Missing qcom,pmic-revid property - driver failed\n");
2703 return -EINVAL;
2704 }
2705
2706 chip->pmic_rev_id = get_revid_data(revid_node);
2707 if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
2708 pr_err("Unable to get pmic_revid rc=%ld\n",
2709 PTR_ERR(chip->pmic_rev_id));
2710 /*
2711 * the revid peripheral must be registered, any failure
2712 * here only indicates that the rev-id module has not
2713 * probed yet.
2714 */
2715 return -EPROBE_DEFER;
2716 }
2717
2718 pr_debug("PMIC subtype %d Digital major %d\n",
2719 chip->pmic_rev_id->pmic_subtype, chip->pmic_rev_id->rev4);
2720
2721 switch (chip->pmic_rev_id->pmic_subtype) {
2722 case PMICOBALT_SUBTYPE:
Nicholas Troast69da2252016-09-07 16:17:47 -07002723 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4) {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002724 chip->sp = pmicobalt_v1_sram_params;
Nicholas Troast69da2252016-09-07 16:17:47 -07002725 chip->alg_flags = pmicobalt_v1_alg_flags;
2726 } else if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4) {
Nicholas Troasta2b40372016-08-15 10:45:39 -07002727 chip->sp = pmicobalt_v2_sram_params;
Nicholas Troast69da2252016-09-07 16:17:47 -07002728 chip->alg_flags = pmicobalt_v2_alg_flags;
2729 } else {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002730 return -EINVAL;
Nicholas Troast69da2252016-09-07 16:17:47 -07002731 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002732 break;
2733 default:
2734 return -EINVAL;
2735 }
2736
2737 chip->batt_id_chan = iio_channel_get(chip->dev, "rradc_batt_id");
2738 if (IS_ERR(chip->batt_id_chan)) {
2739 if (PTR_ERR(chip->batt_id_chan) != -EPROBE_DEFER)
2740 pr_err("batt_id_chan unavailable %ld\n",
2741 PTR_ERR(chip->batt_id_chan));
2742 rc = PTR_ERR(chip->batt_id_chan);
2743 chip->batt_id_chan = NULL;
2744 return rc;
2745 }
2746
2747 if (of_get_available_child_count(node) == 0) {
2748 dev_err(chip->dev, "No child nodes specified!\n");
2749 return -ENXIO;
2750 }
2751
2752 for_each_available_child_of_node(node, child) {
2753 rc = of_property_read_u32(child, "reg", &base);
2754 if (rc < 0) {
2755 dev_err(chip->dev, "reg not specified in node %s, rc=%d\n",
2756 child->full_name, rc);
2757 return rc;
2758 }
2759
2760 rc = fg_read(chip, base + PERPH_SUBTYPE_REG, &subtype, 1);
2761 if (rc < 0) {
2762 dev_err(chip->dev, "Couldn't read subtype for base %d, rc=%d\n",
2763 base, rc);
2764 return rc;
2765 }
2766
2767 switch (subtype) {
2768 case FG_BATT_SOC_PMICOBALT:
2769 chip->batt_soc_base = base;
2770 break;
2771 case FG_BATT_INFO_PMICOBALT:
2772 chip->batt_info_base = base;
2773 break;
2774 case FG_MEM_INFO_PMICOBALT:
2775 chip->mem_if_base = base;
2776 break;
2777 default:
2778 dev_err(chip->dev, "Invalid peripheral subtype 0x%x\n",
2779 subtype);
2780 return -ENXIO;
2781 }
2782 }
2783
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002784 rc = fg_get_batt_profile(chip);
2785 if (rc < 0)
2786 pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -07002787 chip->batt_id_kohms, rc);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002788
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002789 /* Read all the optional properties below */
2790 rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp);
2791 if (rc < 0)
2792 chip->dt.cutoff_volt_mv = DEFAULT_CUTOFF_VOLT_MV;
2793 else
2794 chip->dt.cutoff_volt_mv = temp;
2795
2796 rc = of_property_read_u32(node, "qcom,fg-empty-voltage", &temp);
2797 if (rc < 0)
2798 chip->dt.empty_volt_mv = DEFAULT_EMPTY_VOLT_MV;
2799 else
2800 chip->dt.empty_volt_mv = temp;
2801
2802 rc = of_property_read_u32(node, "qcom,fg-vbatt-low-thr", &temp);
2803 if (rc < 0)
2804 chip->dt.vbatt_low_thr_mv = -EINVAL;
2805 else
2806 chip->dt.vbatt_low_thr_mv = temp;
2807
2808 rc = of_property_read_u32(node, "qcom,fg-chg-term-current", &temp);
2809 if (rc < 0)
2810 chip->dt.chg_term_curr_ma = DEFAULT_CHG_TERM_CURR_MA;
2811 else
2812 chip->dt.chg_term_curr_ma = temp;
2813
2814 rc = of_property_read_u32(node, "qcom,fg-sys-term-current", &temp);
2815 if (rc < 0)
2816 chip->dt.sys_term_curr_ma = DEFAULT_SYS_TERM_CURR_MA;
2817 else
2818 chip->dt.sys_term_curr_ma = temp;
2819
2820 rc = of_property_read_u32(node, "qcom,fg-delta-soc-thr", &temp);
2821 if (rc < 0)
2822 chip->dt.delta_soc_thr = DEFAULT_DELTA_SOC_THR;
2823 else
2824 chip->dt.delta_soc_thr = temp;
2825
2826 rc = of_property_read_u32(node, "qcom,fg-recharge-soc-thr", &temp);
2827 if (rc < 0)
2828 chip->dt.recharge_soc_thr = DEFAULT_RECHARGE_SOC_THR;
2829 else
2830 chip->dt.recharge_soc_thr = temp;
2831
2832 rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp);
2833 if (rc < 0)
2834 chip->dt.rsense_sel = SRC_SEL_BATFET_SMB;
2835 else
2836 chip->dt.rsense_sel = (u8)temp & SOURCE_SELECT_MASK;
2837
2838 chip->dt.jeita_thresholds[JEITA_COLD] = DEFAULT_BATT_TEMP_COLD;
2839 chip->dt.jeita_thresholds[JEITA_COOL] = DEFAULT_BATT_TEMP_COOL;
2840 chip->dt.jeita_thresholds[JEITA_WARM] = DEFAULT_BATT_TEMP_WARM;
2841 chip->dt.jeita_thresholds[JEITA_HOT] = DEFAULT_BATT_TEMP_HOT;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002842 if (of_property_count_elems_of_size(node, "qcom,fg-jeita-thresholds",
2843 sizeof(u32)) == NUM_JEITA_LEVELS) {
2844 rc = of_property_read_u32_array(node,
2845 "qcom,fg-jeita-thresholds",
2846 chip->dt.jeita_thresholds, NUM_JEITA_LEVELS);
2847 if (rc < 0)
2848 pr_warn("Error reading Jeita thresholds, default values will be used rc:%d\n",
2849 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002850 }
2851
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002852 rc = of_property_read_u32(node, "qcom,fg-esr-timer-charging", &temp);
2853 if (rc < 0)
2854 chip->dt.esr_timer_charging = -EINVAL;
2855 else
2856 chip->dt.esr_timer_charging = temp;
2857
2858 rc = of_property_read_u32(node, "qcom,fg-esr-timer-awake", &temp);
2859 if (rc < 0)
2860 chip->dt.esr_timer_awake = -EINVAL;
2861 else
2862 chip->dt.esr_timer_awake = temp;
2863
2864 rc = of_property_read_u32(node, "qcom,fg-esr-timer-asleep", &temp);
2865 if (rc < 0)
2866 chip->dt.esr_timer_asleep = -EINVAL;
2867 else
2868 chip->dt.esr_timer_asleep = temp;
2869
Nicholas Troaste29dec92016-08-24 09:35:11 -07002870 chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
2871 if (chip->cyc_ctr.en)
2872 chip->cyc_ctr.id = 1;
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002873
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002874 chip->dt.force_load_profile = of_property_read_bool(node,
2875 "qcom,fg-force-load-profile");
2876
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002877 rc = of_property_read_u32(node, "qcom,cl-start-capacity", &temp);
2878 if (rc < 0)
2879 chip->dt.cl_start_soc = DEFAULT_CL_START_SOC;
2880 else
2881 chip->dt.cl_start_soc = temp;
2882
2883 rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp);
2884 if (rc < 0)
2885 chip->dt.cl_min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC;
2886 else
2887 chip->dt.cl_min_temp = temp;
2888
2889 rc = of_property_read_u32(node, "qcom,cl-max-temp", &temp);
2890 if (rc < 0)
2891 chip->dt.cl_max_temp = DEFAULT_CL_MAX_TEMP_DECIDEGC;
2892 else
2893 chip->dt.cl_max_temp = temp;
2894
2895 rc = of_property_read_u32(node, "qcom,cl-max-increment", &temp);
2896 if (rc < 0)
2897 chip->dt.cl_max_cap_inc = DEFAULT_CL_MAX_INC_DECIPERC;
2898 else
2899 chip->dt.cl_max_cap_inc = temp;
2900
2901 rc = of_property_read_u32(node, "qcom,cl-max-decrement", &temp);
2902 if (rc < 0)
2903 chip->dt.cl_max_cap_dec = DEFAULT_CL_MAX_DEC_DECIPERC;
2904 else
2905 chip->dt.cl_max_cap_dec = temp;
2906
2907 rc = of_property_read_u32(node, "qcom,cl-min-limit", &temp);
2908 if (rc < 0)
2909 chip->dt.cl_min_cap_limit = DEFAULT_CL_MIN_LIM_DECIPERC;
2910 else
2911 chip->dt.cl_min_cap_limit = temp;
2912
2913 rc = of_property_read_u32(node, "qcom,cl-max-limit", &temp);
2914 if (rc < 0)
2915 chip->dt.cl_max_cap_limit = DEFAULT_CL_MAX_LIM_DECIPERC;
2916 else
2917 chip->dt.cl_max_cap_limit = temp;
2918
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002919 rc = of_property_read_u32(node, "qcom,fg-jeita-hyst-temp", &temp);
2920 if (rc < 0)
2921 chip->dt.jeita_hyst_temp = -EINVAL;
2922 else
2923 chip->dt.jeita_hyst_temp = temp;
2924
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002925 rc = of_property_read_u32(node, "qcom,fg-batt-temp-delta", &temp);
2926 if (rc < 0)
2927 chip->dt.batt_temp_delta = -EINVAL;
2928 else if (temp > BTEMP_DELTA_LOW && temp <= BTEMP_DELTA_HIGH)
2929 chip->dt.batt_temp_delta = temp;
2930
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002931 chip->dt.hold_soc_while_full = of_property_read_bool(node,
2932 "qcom,hold-soc-while-full");
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002933
2934 rc = fg_parse_ki_coefficients(chip);
2935 if (rc < 0)
2936 pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
2937
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002938 return 0;
2939}
2940
2941static void fg_cleanup(struct fg_chip *chip)
2942{
2943 power_supply_unreg_notifier(&chip->nb);
Nicholas Troast69da2252016-09-07 16:17:47 -07002944 debugfs_remove_recursive(chip->dfs_root);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002945 if (chip->awake_votable)
2946 destroy_votable(chip->awake_votable);
2947
2948 if (chip->batt_id_chan)
2949 iio_channel_release(chip->batt_id_chan);
2950
2951 dev_set_drvdata(chip->dev, NULL);
2952}
2953
2954static int fg_gen3_probe(struct platform_device *pdev)
2955{
2956 struct fg_chip *chip;
2957 struct power_supply_config fg_psy_cfg;
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08002958 int rc, msoc, volt_uv, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002959
2960 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2961 if (!chip)
2962 return -ENOMEM;
2963
2964 chip->dev = &pdev->dev;
2965 chip->debug_mask = &fg_gen3_debug_mask;
2966 chip->irqs = fg_irqs;
2967 chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
2968 if (!chip->regmap) {
2969 dev_err(chip->dev, "Parent regmap is unavailable\n");
2970 return -ENXIO;
2971 }
2972
2973 rc = fg_parse_dt(chip);
2974 if (rc < 0) {
2975 dev_err(chip->dev, "Error in reading DT parameters, rc:%d\n",
2976 rc);
2977 return rc;
2978 }
2979
2980 chip->awake_votable = create_votable("FG_WS", VOTE_SET_ANY, fg_awake_cb,
2981 chip);
2982 if (IS_ERR(chip->awake_votable)) {
2983 rc = PTR_ERR(chip->awake_votable);
2984 return rc;
2985 }
2986
2987 mutex_init(&chip->bus_lock);
2988 mutex_init(&chip->sram_rw_lock);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002989 mutex_init(&chip->cyc_ctr.lock);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002990 mutex_init(&chip->cl.lock);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002991 init_completion(&chip->soc_update);
2992 init_completion(&chip->soc_ready);
2993 INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
2994 INIT_WORK(&chip->status_change_work, status_change_work);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002995 INIT_WORK(&chip->cycle_count_work, cycle_count_work);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002996
2997 rc = fg_memif_init(chip);
2998 if (rc < 0) {
2999 dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n",
3000 rc);
3001 goto exit;
3002 }
3003
3004 rc = fg_hw_init(chip);
3005 if (rc < 0) {
3006 dev_err(chip->dev, "Error in initializing FG hardware, rc:%d\n",
3007 rc);
3008 goto exit;
3009 }
3010
3011 platform_set_drvdata(pdev, chip);
3012
3013 /* Register the power supply */
3014 fg_psy_cfg.drv_data = chip;
3015 fg_psy_cfg.of_node = NULL;
3016 fg_psy_cfg.supplied_to = NULL;
3017 fg_psy_cfg.num_supplicants = 0;
3018 chip->fg_psy = devm_power_supply_register(chip->dev, &fg_psy_desc,
3019 &fg_psy_cfg);
3020 if (IS_ERR(chip->fg_psy)) {
3021 pr_err("failed to register fg_psy rc = %ld\n",
3022 PTR_ERR(chip->fg_psy));
3023 goto exit;
3024 }
3025
3026 chip->nb.notifier_call = fg_notifier_cb;
3027 rc = power_supply_reg_notifier(&chip->nb);
3028 if (rc < 0) {
3029 pr_err("Couldn't register psy notifier rc = %d\n", rc);
3030 goto exit;
3031 }
3032
3033 rc = fg_register_interrupts(chip);
3034 if (rc < 0) {
3035 dev_err(chip->dev, "Error in registering interrupts, rc:%d\n",
3036 rc);
3037 goto exit;
3038 }
3039
3040 /* Keep SOC_UPDATE irq disabled until we require it */
3041 if (fg_irqs[SOC_UPDATE_IRQ].irq)
3042 disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
3043
Nicholas Troast69da2252016-09-07 16:17:47 -07003044 rc = fg_debugfs_create(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003045 if (rc < 0) {
3046 dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n",
3047 rc);
3048 goto exit;
3049 }
3050
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003051 rc = fg_get_battery_voltage(chip, &volt_uv);
3052 if (!rc)
3053 rc = fg_get_prop_capacity(chip, &msoc);
3054
3055 if (!rc)
3056 rc = fg_get_battery_temp(chip, &batt_temp);
3057
3058 if (!rc)
3059 pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n",
3060 msoc, volt_uv, batt_temp, chip->batt_id_kohms);
3061
3062 device_init_wakeup(chip->dev, true);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07003063 if (chip->profile_available)
3064 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003065
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08003066 pr_debug("FG GEN3 driver probed successfully\n");
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003067 return 0;
3068exit:
3069 fg_cleanup(chip);
3070 return rc;
3071}
3072
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003073static int fg_gen3_suspend(struct device *dev)
3074{
3075 struct fg_chip *chip = dev_get_drvdata(dev);
3076 int rc;
3077
3078 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
3079 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_asleep, false,
3080 FG_IMA_NO_WLOCK);
3081 if (rc < 0) {
3082 pr_err("Error in setting ESR timer during suspend, rc=%d\n",
3083 rc);
3084 return rc;
3085 }
3086 }
3087
3088 return 0;
3089}
3090
3091static int fg_gen3_resume(struct device *dev)
3092{
3093 struct fg_chip *chip = dev_get_drvdata(dev);
3094 int rc;
3095
3096 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
3097 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
3098 FG_IMA_DEFAULT);
3099 if (rc < 0) {
3100 pr_err("Error in setting ESR timer during resume, rc=%d\n",
3101 rc);
3102 return rc;
3103 }
3104 }
3105
3106 return 0;
3107}
3108
3109static const struct dev_pm_ops fg_gen3_pm_ops = {
3110 .suspend = fg_gen3_suspend,
3111 .resume = fg_gen3_resume,
3112};
3113
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003114static int fg_gen3_remove(struct platform_device *pdev)
3115{
3116 struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
3117
3118 fg_cleanup(chip);
3119 return 0;
3120}
3121
3122static const struct of_device_id fg_gen3_match_table[] = {
3123 {.compatible = FG_GEN3_DEV_NAME},
3124 {},
3125};
3126
3127static struct platform_driver fg_gen3_driver = {
3128 .driver = {
3129 .name = FG_GEN3_DEV_NAME,
3130 .owner = THIS_MODULE,
3131 .of_match_table = fg_gen3_match_table,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003132 .pm = &fg_gen3_pm_ops,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003133 },
3134 .probe = fg_gen3_probe,
3135 .remove = fg_gen3_remove,
3136};
3137
3138static int __init fg_gen3_init(void)
3139{
3140 return platform_driver_register(&fg_gen3_driver);
3141}
3142
3143static void __exit fg_gen3_exit(void)
3144{
3145 return platform_driver_unregister(&fg_gen3_driver);
3146}
3147
3148module_init(fg_gen3_init);
3149module_exit(fg_gen3_exit);
3150
3151MODULE_DESCRIPTION("QPNP Fuel gauge GEN3 driver");
3152MODULE_LICENSE("GPL v2");
3153MODULE_ALIAS("platform:" FG_GEN3_DEV_NAME);