blob: da4b5481b12ea7748790c0536778d9ac46abb185 [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 Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700658#define DEBUG_BATT_ID_KOHMS 7
659static bool is_debug_batt_id(struct fg_chip *chip)
660{
661 int batt_id_delta = 0;
662
663 if (!chip->batt_id_kohms)
664 return false;
665
666 batt_id_delta = abs(chip->batt_id_kohms - DEBUG_BATT_ID_KOHMS);
667 if (batt_id_delta <= 1) {
668 fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dKohms\n",
669 chip->batt_id_kohms);
670 return true;
671 }
672
673 return false;
674}
675
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700676#define FULL_CAPACITY 100
677#define FULL_SOC_RAW 255
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700678#define DEBUG_BATT_SOC 67
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700679#define EMPTY_SOC 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700680static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
681{
682 int rc, msoc;
683
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700684 if (is_debug_batt_id(chip)) {
685 *val = DEBUG_BATT_SOC;
686 return 0;
687 }
688
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700689 if (chip->charge_empty) {
690 *val = EMPTY_SOC;
691 return 0;
692 }
693
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700694 if (chip->charge_full) {
695 *val = FULL_CAPACITY;
696 return 0;
697 }
698
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700699 rc = fg_get_msoc_raw(chip, &msoc);
700 if (rc < 0)
701 return rc;
702
703 *val = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
704 return 0;
705}
706
707#define DEFAULT_BATT_TYPE "Unknown Battery"
708#define MISSING_BATT_TYPE "Missing Battery"
709#define LOADING_BATT_TYPE "Loading Battery"
710static const char *fg_get_battery_type(struct fg_chip *chip)
711{
712 if (chip->battery_missing)
713 return MISSING_BATT_TYPE;
714
715 if (chip->bp.batt_type_str) {
716 if (chip->profile_loaded)
717 return chip->bp.batt_type_str;
718 else
719 return LOADING_BATT_TYPE;
720 }
721
722 return DEFAULT_BATT_TYPE;
723}
724
725static int fg_get_batt_id(struct fg_chip *chip, int *val)
726{
727 int rc, batt_id = -EINVAL;
728
729 if (!chip->batt_id_chan)
730 return -EINVAL;
731
732 rc = iio_read_channel_processed(chip->batt_id_chan, &batt_id);
733 if (rc < 0) {
734 pr_err("Error in reading batt_id channel, rc:%d\n", rc);
735 return rc;
736 }
737
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700738 fg_dbg(chip, FG_STATUS, "batt_id: %d\n", batt_id);
739
740 *val = batt_id;
741 return 0;
742}
743
744static int fg_get_batt_profile(struct fg_chip *chip)
745{
746 struct device_node *node = chip->dev->of_node;
747 struct device_node *batt_node, *profile_node;
748 const char *data;
749 int rc, len, batt_id;
750
751 rc = fg_get_batt_id(chip, &batt_id);
752 if (rc < 0) {
753 pr_err("Error in getting batt_id rc:%d\n", rc);
754 return rc;
755 }
756
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700757 batt_id /= 1000;
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700758 chip->batt_id_kohms = batt_id;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700759 batt_node = of_find_node_by_name(node, "qcom,battery-data");
760 if (!batt_node) {
761 pr_err("Batterydata not available\n");
762 return -ENXIO;
763 }
764
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700765 profile_node = of_batterydata_get_best_profile(batt_node, batt_id,
766 NULL);
767 if (IS_ERR(profile_node))
768 return PTR_ERR(profile_node);
769
770 if (!profile_node) {
771 pr_err("couldn't find profile handle\n");
772 return -ENODATA;
773 }
774
775 rc = of_property_read_string(profile_node, "qcom,battery-type",
776 &chip->bp.batt_type_str);
777 if (rc < 0) {
778 pr_err("battery type unavailable, rc:%d\n", rc);
779 return rc;
780 }
781
782 rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv",
783 &chip->bp.float_volt_uv);
784 if (rc < 0) {
785 pr_err("battery float voltage unavailable, rc:%d\n", rc);
786 chip->bp.float_volt_uv = -EINVAL;
787 }
788
789 rc = of_property_read_u32(profile_node, "qcom,nom-batt-capacity-mah",
790 &chip->bp.fastchg_curr_ma);
791 if (rc < 0) {
792 pr_err("battery nominal capacity unavailable, rc:%d\n", rc);
793 chip->bp.fastchg_curr_ma = -EINVAL;
794 }
795
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700796 rc = of_property_read_u32(profile_node, "qcom,fg-cc-cv-threshold-mv",
797 &chip->bp.vbatt_full_mv);
798 if (rc < 0) {
799 pr_err("battery cc_cv threshold unavailable, rc:%d\n", rc);
800 chip->bp.vbatt_full_mv = -EINVAL;
801 }
802
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700803 data = of_get_property(profile_node, "qcom,fg-profile-data", &len);
804 if (!data) {
805 pr_err("No profile data available\n");
806 return -ENODATA;
807 }
808
809 if (len != PROFILE_LEN) {
810 pr_err("battery profile incorrect size: %d\n", len);
811 return -EINVAL;
812 }
813
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700814 chip->profile_available = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700815 memcpy(chip->batt_profile, data, len);
816 return 0;
817}
818
819static inline void get_temp_setpoint(int threshold, u8 *val)
820{
821 /* Resolution is 0.5C. Base is -30C. */
822 *val = DIV_ROUND_CLOSEST((threshold + 30) * 10, 5);
823}
824
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -0700825static inline void get_batt_temp_delta(int delta, u8 *val)
826{
827 switch (delta) {
828 case 2:
829 *val = BTEMP_DELTA_2K;
830 break;
831 case 4:
832 *val = BTEMP_DELTA_4K;
833 break;
834 case 6:
835 *val = BTEMP_DELTA_6K;
836 break;
837 case 10:
838 *val = BTEMP_DELTA_10K;
839 break;
840 default:
841 *val = BTEMP_DELTA_2K;
842 break;
843 };
844}
845
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700846static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
847 int flags)
848{
849 u8 buf[2];
850 int rc, timer_max, timer_init;
851
852 if (charging) {
853 timer_max = FG_SRAM_ESR_TIMER_CHG_MAX;
854 timer_init = FG_SRAM_ESR_TIMER_CHG_INIT;
855 } else {
856 timer_max = FG_SRAM_ESR_TIMER_DISCHG_MAX;
857 timer_init = FG_SRAM_ESR_TIMER_DISCHG_INIT;
858 }
859
860 fg_encode(chip->sp, timer_max, cycles, buf);
861 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700862 chip->sp[timer_max].addr_word,
863 chip->sp[timer_max].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700864 chip->sp[timer_max].len, flags);
865 if (rc < 0) {
866 pr_err("Error in writing esr_timer_dischg_max, rc=%d\n",
867 rc);
868 return rc;
869 }
870
871 fg_encode(chip->sp, timer_init, cycles, buf);
872 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700873 chip->sp[timer_init].addr_word,
874 chip->sp[timer_init].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700875 chip->sp[timer_init].len, flags);
876 if (rc < 0) {
877 pr_err("Error in writing esr_timer_dischg_init, rc=%d\n",
878 rc);
879 return rc;
880 }
881
882 return 0;
883}
884
Nicholas Troaste29dec92016-08-24 09:35:11 -0700885/* Other functions HERE */
886
887static int fg_awake_cb(struct votable *votable, void *data, int awake,
888 const char *client)
889{
890 struct fg_chip *chip = data;
891
892 if (awake)
893 pm_stay_awake(chip->dev);
894 else
895 pm_relax(chip->dev);
896
897 pr_debug("client: %s awake: %d\n", client, awake);
898 return 0;
899}
900
901static bool is_charger_available(struct fg_chip *chip)
902{
903 if (!chip->batt_psy)
904 chip->batt_psy = power_supply_get_by_name("battery");
905
906 if (!chip->batt_psy)
907 return false;
908
909 return true;
910}
911
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -0700912static bool is_parallel_charger_available(struct fg_chip *chip)
913{
914 if (!chip->parallel_psy)
915 chip->parallel_psy = power_supply_get_by_name("parallel");
916
917 if (!chip->parallel_psy)
918 return false;
919
920 return true;
921}
922
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700923static int fg_save_learned_cap_to_sram(struct fg_chip *chip)
924{
925 int16_t cc_mah;
926 int rc;
927
928 if (chip->battery_missing || !chip->cl.learned_cc_uah)
929 return -EPERM;
930
931 cc_mah = div64_s64(chip->cl.learned_cc_uah, 1000);
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700932 /* Write to a backup register to use across reboot */
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700933 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ACT_BATT_CAP].addr_word,
934 chip->sp[FG_SRAM_ACT_BATT_CAP].addr_byte, (u8 *)&cc_mah,
935 chip->sp[FG_SRAM_ACT_BATT_CAP].len, FG_IMA_DEFAULT);
936 if (rc < 0) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700937 pr_err("Error in writing act_batt_cap_bkup, rc=%d\n", rc);
938 return rc;
939 }
940
941 /* Write to actual capacity register for coulomb counter operation */
942 rc = fg_sram_write(chip, ACT_BATT_CAP_WORD, ACT_BATT_CAP_OFFSET,
943 (u8 *)&cc_mah, chip->sp[FG_SRAM_ACT_BATT_CAP].len,
944 FG_IMA_DEFAULT);
945 if (rc < 0) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700946 pr_err("Error in writing act_batt_cap, rc=%d\n", rc);
947 return rc;
948 }
949
950 fg_dbg(chip, FG_CAP_LEARN, "learned capacity %llduah/%dmah stored\n",
951 chip->cl.learned_cc_uah, cc_mah);
952 return 0;
953}
954
955#define CAPACITY_DELTA_DECIPCT 500
956static int fg_load_learned_cap_from_sram(struct fg_chip *chip)
957{
958 int rc, act_cap_mah;
959 int64_t delta_cc_uah, pct_nom_cap_uah;
960
961 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
962 if (rc < 0) {
963 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
964 return rc;
965 }
966
967 chip->cl.learned_cc_uah = act_cap_mah * 1000;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700968
969 if (chip->cl.learned_cc_uah != chip->cl.nom_cap_uah) {
Subbaraman Narayanamurthy51d3c902016-10-24 14:05:44 -0700970 if (chip->cl.learned_cc_uah == 0)
971 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
972
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700973 delta_cc_uah = abs(chip->cl.learned_cc_uah -
974 chip->cl.nom_cap_uah);
975 pct_nom_cap_uah = div64_s64((int64_t)chip->cl.nom_cap_uah *
976 CAPACITY_DELTA_DECIPCT, 1000);
977 /*
978 * If the learned capacity is out of range by 50% from the
979 * nominal capacity, then overwrite the learned capacity with
980 * the nominal capacity.
981 */
982 if (chip->cl.nom_cap_uah && delta_cc_uah > pct_nom_cap_uah) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700983 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah: %lld is higher than expected, capping it to nominal: %lld\n",
984 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700985 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700986 }
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700987
988 rc = fg_save_learned_cap_to_sram(chip);
989 if (rc < 0)
990 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700991 }
992
993 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah:%lld nom_cap_uah: %lld\n",
994 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
995 return 0;
996}
997
998static bool is_temp_valid_cap_learning(struct fg_chip *chip)
999{
1000 int rc, batt_temp;
1001
1002 rc = fg_get_battery_temp(chip, &batt_temp);
1003 if (rc < 0) {
1004 pr_err("Error in getting batt_temp\n");
1005 return false;
1006 }
1007
1008 if (batt_temp > chip->dt.cl_max_temp ||
1009 batt_temp < chip->dt.cl_min_temp) {
1010 fg_dbg(chip, FG_CAP_LEARN, "batt temp %d out of range [%d %d]\n",
1011 batt_temp, chip->dt.cl_min_temp, chip->dt.cl_max_temp);
1012 return false;
1013 }
1014
1015 return true;
1016}
1017
1018static void fg_cap_learning_post_process(struct fg_chip *chip)
1019{
1020 int64_t max_inc_val, min_dec_val, old_cap;
1021 int rc;
1022
1023 max_inc_val = chip->cl.learned_cc_uah
1024 * (1000 + chip->dt.cl_max_cap_inc);
1025 do_div(max_inc_val, 1000);
1026
1027 min_dec_val = chip->cl.learned_cc_uah
1028 * (1000 - chip->dt.cl_max_cap_dec);
1029 do_div(min_dec_val, 1000);
1030
1031 old_cap = chip->cl.learned_cc_uah;
1032 if (chip->cl.final_cc_uah > max_inc_val)
1033 chip->cl.learned_cc_uah = max_inc_val;
1034 else if (chip->cl.final_cc_uah < min_dec_val)
1035 chip->cl.learned_cc_uah = min_dec_val;
1036 else
1037 chip->cl.learned_cc_uah =
1038 chip->cl.final_cc_uah;
1039
1040 if (chip->dt.cl_max_cap_limit) {
1041 max_inc_val = (int64_t)chip->cl.nom_cap_uah * (1000 +
1042 chip->dt.cl_max_cap_limit);
1043 do_div(max_inc_val, 1000);
1044 if (chip->cl.final_cc_uah > max_inc_val) {
1045 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes above max limit %lld\n",
1046 chip->cl.final_cc_uah, max_inc_val);
1047 chip->cl.learned_cc_uah = max_inc_val;
1048 }
1049 }
1050
1051 if (chip->dt.cl_min_cap_limit) {
1052 min_dec_val = (int64_t)chip->cl.nom_cap_uah * (1000 -
1053 chip->dt.cl_min_cap_limit);
1054 do_div(min_dec_val, 1000);
1055 if (chip->cl.final_cc_uah < min_dec_val) {
1056 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes below min limit %lld\n",
1057 chip->cl.final_cc_uah, min_dec_val);
1058 chip->cl.learned_cc_uah = min_dec_val;
1059 }
1060 }
1061
1062 rc = fg_save_learned_cap_to_sram(chip);
1063 if (rc < 0)
1064 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
1065
1066 fg_dbg(chip, FG_CAP_LEARN, "final cc_uah = %lld, learned capacity %lld -> %lld uah\n",
1067 chip->cl.final_cc_uah, old_cap, chip->cl.learned_cc_uah);
1068}
1069
1070static int fg_cap_learning_process_full_data(struct fg_chip *chip)
1071{
1072 int rc, cc_soc_sw, cc_soc_delta_pct;
1073 int64_t delta_cc_uah;
1074
1075 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1076 if (rc < 0) {
1077 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1078 return rc;
1079 }
1080
1081 cc_soc_delta_pct = DIV_ROUND_CLOSEST(
1082 abs(cc_soc_sw - chip->cl.init_cc_soc_sw) * 100,
1083 CC_SOC_30BIT);
1084 delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
1085 100);
1086 chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
1087 fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%d total_cc_uah=%lld\n",
1088 cc_soc_sw, cc_soc_delta_pct, chip->cl.final_cc_uah);
1089 return 0;
1090}
1091
1092static int fg_cap_learning_begin(struct fg_chip *chip, int batt_soc)
1093{
1094 int rc, cc_soc_sw;
1095
1096 if (DIV_ROUND_CLOSEST(batt_soc * 100, FULL_SOC_RAW) >
1097 chip->dt.cl_start_soc) {
1098 fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n",
1099 batt_soc);
1100 return -EINVAL;
1101 }
1102
1103 chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc,
1104 FULL_SOC_RAW);
1105 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1106 if (rc < 0) {
1107 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1108 return rc;
1109 }
1110
1111 chip->cl.init_cc_soc_sw = cc_soc_sw;
1112 chip->cl.active = true;
1113 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
1114 batt_soc, chip->cl.init_cc_soc_sw);
1115 return 0;
1116}
1117
1118static int fg_cap_learning_done(struct fg_chip *chip)
1119{
1120 int rc, cc_soc_sw;
1121
1122 rc = fg_cap_learning_process_full_data(chip);
1123 if (rc < 0) {
1124 pr_err("Error in processing cap learning full data, rc=%d\n",
1125 rc);
1126 goto out;
1127 }
1128
1129 /* Write a FULL value to cc_soc_sw */
1130 cc_soc_sw = CC_SOC_30BIT;
1131 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
1132 chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001133 chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001134 if (rc < 0) {
1135 pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
1136 goto out;
1137 }
1138
1139 fg_cap_learning_post_process(chip);
1140out:
1141 return rc;
1142}
1143
1144#define FULL_SOC_RAW 255
1145static void fg_cap_learning_update(struct fg_chip *chip)
1146{
1147 int rc, batt_soc;
1148
1149 mutex_lock(&chip->cl.lock);
1150
1151 if (!is_temp_valid_cap_learning(chip) || !chip->cl.learned_cc_uah ||
1152 chip->battery_missing) {
1153 fg_dbg(chip, FG_CAP_LEARN, "Aborting cap_learning %lld\n",
1154 chip->cl.learned_cc_uah);
1155 chip->cl.active = false;
1156 chip->cl.init_cc_uah = 0;
1157 goto out;
1158 }
1159
1160 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1161 if (rc < 0) {
1162 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
1163 goto out;
1164 }
1165
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001166 /* We need only the most significant byte here */
1167 batt_soc = (u32)batt_soc >> 24;
1168
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001169 fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n",
1170 chip->status, chip->cl.active, batt_soc);
1171
1172 /* Initialize the starting point of learning capacity */
1173 if (!chip->cl.active) {
1174 if (chip->status == POWER_SUPPLY_STATUS_CHARGING) {
1175 rc = fg_cap_learning_begin(chip, batt_soc);
1176 chip->cl.active = (rc == 0);
1177 }
1178
1179 } else {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001180 if (chip->charge_done) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001181 rc = fg_cap_learning_done(chip);
1182 if (rc < 0)
1183 pr_err("Error in completing capacity learning, rc=%d\n",
1184 rc);
1185
1186 chip->cl.active = false;
1187 chip->cl.init_cc_uah = 0;
1188 }
1189
1190 if (chip->status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
1191 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
1192 batt_soc);
1193 chip->cl.active = false;
1194 chip->cl.init_cc_uah = 0;
1195 }
1196 }
1197
1198out:
1199 mutex_unlock(&chip->cl.lock);
1200}
1201
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001202#define KI_COEFF_MED_DISCHG_DEFAULT 1500
1203#define KI_COEFF_HI_DISCHG_DEFAULT 2200
1204static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
1205{
1206 int rc, i, msoc;
1207 int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
1208 int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
1209 u8 val;
1210
1211 if (!chip->ki_coeff_dischg_en)
1212 return 0;
1213
1214 rc = fg_get_prop_capacity(chip, &msoc);
1215 if (rc < 0) {
1216 pr_err("Error in getting capacity, rc=%d\n", rc);
1217 return rc;
1218 }
1219
1220 if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
1221 for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
1222 if (msoc < chip->dt.ki_coeff_soc[i]) {
1223 ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
1224 ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
1225 }
1226 }
1227 }
1228
1229 fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
1230 rc = fg_sram_write(chip,
1231 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
1232 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
1233 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
1234 FG_IMA_DEFAULT);
1235 if (rc < 0) {
1236 pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
1237 return rc;
1238 }
1239
1240 fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
1241 rc = fg_sram_write(chip,
1242 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
1243 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
1244 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
1245 FG_IMA_DEFAULT);
1246 if (rc < 0) {
1247 pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
1248 return rc;
1249 }
1250
1251 fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
1252 ki_coeff_med, ki_coeff_hi);
1253 return 0;
1254}
1255
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001256static int fg_charge_full_update(struct fg_chip *chip)
1257{
1258 union power_supply_propval prop = {0, };
1259 int rc, msoc, bsoc, recharge_soc;
1260 u8 full_soc[2] = {0xFF, 0xFF};
1261
1262 if (!chip->dt.hold_soc_while_full)
1263 return 0;
1264
1265 if (!is_charger_available(chip))
1266 return 0;
1267
1268 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
1269 &prop);
1270 if (rc < 0) {
1271 pr_err("Error in getting battery health, rc=%d\n", rc);
1272 return rc;
1273 }
1274
1275 chip->health = prop.intval;
1276 recharge_soc = chip->dt.recharge_soc_thr;
1277 recharge_soc = DIV_ROUND_CLOSEST(recharge_soc * FULL_SOC_RAW,
1278 FULL_CAPACITY);
1279 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
1280 if (rc < 0) {
1281 pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
1282 return rc;
1283 }
1284
1285 /* We need 2 most significant bytes here */
1286 bsoc = (u32)bsoc >> 16;
1287 rc = fg_get_prop_capacity(chip, &msoc);
1288 if (rc < 0) {
1289 pr_err("Error in getting capacity, rc=%d\n", rc);
1290 return rc;
1291 }
1292
1293 fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc,
1294 chip->health, chip->status);
1295 if (chip->charge_done) {
1296 if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD)
1297 chip->charge_full = true;
1298 else
1299 fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
1300 msoc);
1301 } else if ((bsoc >> 8) <= recharge_soc) {
1302 fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d\n",
1303 bsoc >> 8, recharge_soc);
1304 chip->charge_full = false;
1305 }
1306
1307 if (!chip->charge_full)
1308 return 0;
1309
1310 /*
1311 * During JEITA conditions, charge_full can happen early. FULL_SOC
1312 * and MONOTONIC_SOC needs to be updated to reflect the same. Write
1313 * battery SOC to FULL_SOC and write a full value to MONOTONIC_SOC.
1314 */
1315 rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET, (u8 *)&bsoc, 2,
1316 FG_IMA_ATOMIC);
1317 if (rc < 0) {
1318 pr_err("failed to write full_soc rc=%d\n", rc);
1319 return rc;
1320 }
1321
1322 rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
1323 full_soc, 2, FG_IMA_ATOMIC);
1324 if (rc < 0) {
1325 pr_err("failed to write monotonic_soc rc=%d\n", rc);
1326 return rc;
1327 }
1328
1329 fg_dbg(chip, FG_STATUS, "Set charge_full to true @ soc %d\n", msoc);
1330 return 0;
1331}
1332
1333static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
1334{
1335 u8 buf[4];
1336 int rc;
1337
1338 fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf);
1339 rc = fg_sram_write(chip,
1340 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
1341 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, buf,
1342 chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
1343 if (rc < 0) {
1344 pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
1345 return rc;
1346 }
1347
1348 return 0;
1349}
1350
1351static int fg_adjust_recharge_soc(struct fg_chip *chip)
1352{
1353 int rc, msoc, recharge_soc, new_recharge_soc = 0;
1354
1355 recharge_soc = chip->dt.recharge_soc_thr;
1356 /*
1357 * If the input is present and charging had been terminated, adjust
1358 * the recharge SOC threshold based on the monotonic SOC at which
1359 * the charge termination had happened.
1360 */
1361 if (is_input_present(chip) && !chip->recharge_soc_adjusted
1362 && chip->charge_done) {
1363 /* Get raw monotonic SOC for calculation */
1364 rc = fg_get_msoc_raw(chip, &msoc);
1365 if (rc < 0) {
1366 pr_err("Error in getting msoc, rc=%d\n", rc);
1367 return rc;
1368 }
1369
1370 msoc = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
1371 /* Adjust the recharge_soc threshold */
1372 new_recharge_soc = msoc - (FULL_CAPACITY - recharge_soc);
1373 } else if (chip->recharge_soc_adjusted && (!is_input_present(chip)
1374 || chip->health == POWER_SUPPLY_HEALTH_GOOD)) {
1375 /* Restore the default value */
1376 new_recharge_soc = recharge_soc;
1377 }
1378
1379 if (new_recharge_soc > 0 && new_recharge_soc < FULL_CAPACITY) {
1380 rc = fg_set_recharge_soc(chip, new_recharge_soc);
1381 if (rc) {
1382 pr_err("Couldn't set resume SOC for FG, rc=%d\n", rc);
1383 return rc;
1384 }
1385
1386 chip->recharge_soc_adjusted = (new_recharge_soc !=
1387 recharge_soc);
1388 fg_dbg(chip, FG_STATUS, "resume soc set to %d\n",
1389 new_recharge_soc);
1390 }
1391
1392 return 0;
1393}
1394
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001395static int fg_esr_fcc_config(struct fg_chip *chip)
1396{
1397 union power_supply_propval prop = {0, };
1398 int rc;
1399 bool parallel_en = false;
1400
1401 if (is_parallel_charger_available(chip)) {
1402 rc = power_supply_get_property(chip->parallel_psy,
1403 POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
1404 if (rc < 0) {
1405 pr_err("Error in reading charging_enabled from parallel_psy, rc=%d\n",
1406 rc);
1407 return rc;
1408 }
1409 parallel_en = prop.intval;
1410 }
1411
1412 fg_dbg(chip, FG_POWER_SUPPLY, "status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n",
1413 chip->status, parallel_en, chip->esr_fcc_ctrl_en);
1414
1415 if (chip->status == POWER_SUPPLY_STATUS_CHARGING && parallel_en) {
1416 if (chip->esr_fcc_ctrl_en)
1417 return 0;
1418
1419 /*
1420 * When parallel charging is enabled, configure ESR FCC to
1421 * 300mA to trigger an ESR pulse. Without this, FG can ask
1422 * the main charger to increase FCC when it is supposed to
1423 * decrease it.
1424 */
1425 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
1426 ESR_FAST_CRG_IVAL_MASK |
1427 ESR_FAST_CRG_CTL_EN_BIT,
1428 ESR_FCC_300MA | ESR_FAST_CRG_CTL_EN_BIT);
1429 if (rc < 0) {
1430 pr_err("Error in writing to %04x, rc=%d\n",
1431 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
1432 return rc;
1433 }
1434
1435 chip->esr_fcc_ctrl_en = true;
1436 } else {
1437 if (!chip->esr_fcc_ctrl_en)
1438 return 0;
1439
1440 /*
1441 * If we're here, then it means either the device is not in
1442 * charging state or parallel charging is disabled. Disable
1443 * ESR fast charge current control in SW.
1444 */
1445 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
1446 ESR_FAST_CRG_CTL_EN_BIT, 0);
1447 if (rc < 0) {
1448 pr_err("Error in writing to %04x, rc=%d\n",
1449 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
1450 return rc;
1451 }
1452
1453 chip->esr_fcc_ctrl_en = false;
1454 }
1455
1456 fg_dbg(chip, FG_STATUS, "esr_fcc_ctrl_en set to %d\n",
1457 chip->esr_fcc_ctrl_en);
1458 return 0;
1459}
1460
Nicholas Troaste29dec92016-08-24 09:35:11 -07001461static void status_change_work(struct work_struct *work)
1462{
1463 struct fg_chip *chip = container_of(work,
1464 struct fg_chip, status_change_work);
1465 union power_supply_propval prop = {0, };
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001466 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001467
1468 if (!is_charger_available(chip)) {
1469 fg_dbg(chip, FG_STATUS, "Charger not available?!\n");
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001470 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001471 }
1472
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001473 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS,
Nicholas Troaste29dec92016-08-24 09:35:11 -07001474 &prop);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001475 if (rc < 0) {
1476 pr_err("Error in getting charging status, rc=%d\n", rc);
1477 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001478 }
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001479
1480 chip->status = prop.intval;
1481 rc = power_supply_get_property(chip->batt_psy,
1482 POWER_SUPPLY_PROP_CHARGE_DONE, &prop);
1483 if (rc < 0) {
1484 pr_err("Error in getting charge_done, rc=%d\n", rc);
1485 goto out;
1486 }
1487
1488 chip->charge_done = prop.intval;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001489 fg_dbg(chip, FG_POWER_SUPPLY, "curr_status:%d charge_done: %d\n",
1490 chip->status, chip->charge_done);
1491
1492 if (chip->cyc_ctr.en)
1493 schedule_work(&chip->cycle_count_work);
1494
1495 fg_cap_learning_update(chip);
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001496
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001497 rc = fg_charge_full_update(chip);
1498 if (rc < 0)
1499 pr_err("Error in charge_full_update, rc=%d\n", rc);
1500
1501 rc = fg_adjust_recharge_soc(chip);
1502 if (rc < 0)
1503 pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001504
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001505 rc = fg_adjust_ki_coeff_dischg(chip);
1506 if (rc < 0)
1507 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001508
1509 rc = fg_esr_fcc_config(chip);
1510 if (rc < 0)
1511 pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001512out:
1513 pm_relax(chip->dev);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001514}
1515
1516static void restore_cycle_counter(struct fg_chip *chip)
1517{
1518 int rc = 0, i;
1519 u8 data[2];
1520
1521 mutex_lock(&chip->cyc_ctr.lock);
1522 for (i = 0; i < BUCKET_COUNT; i++) {
1523 rc = fg_sram_read(chip, CYCLE_COUNT_WORD + (i / 2),
1524 CYCLE_COUNT_OFFSET + (i % 2) * 2, data, 2,
1525 FG_IMA_DEFAULT);
1526 if (rc < 0)
1527 pr_err("failed to read bucket %d rc=%d\n", i, rc);
1528 else
1529 chip->cyc_ctr.count[i] = data[0] | data[1] << 8;
1530 }
1531 mutex_unlock(&chip->cyc_ctr.lock);
1532}
1533
1534static void clear_cycle_counter(struct fg_chip *chip)
1535{
1536 int rc = 0, i;
1537
1538 if (!chip->cyc_ctr.en)
1539 return;
1540
1541 mutex_lock(&chip->cyc_ctr.lock);
1542 memset(chip->cyc_ctr.count, 0, sizeof(chip->cyc_ctr.count));
1543 for (i = 0; i < BUCKET_COUNT; i++) {
1544 chip->cyc_ctr.started[i] = false;
1545 chip->cyc_ctr.last_soc[i] = 0;
1546 }
1547 rc = fg_sram_write(chip, CYCLE_COUNT_WORD, CYCLE_COUNT_OFFSET,
1548 (u8 *)&chip->cyc_ctr.count,
1549 sizeof(chip->cyc_ctr.count) / sizeof(u8 *),
1550 FG_IMA_DEFAULT);
1551 if (rc < 0)
1552 pr_err("failed to clear cycle counter rc=%d\n", rc);
1553
1554 mutex_unlock(&chip->cyc_ctr.lock);
1555}
1556
1557static int fg_inc_store_cycle_ctr(struct fg_chip *chip, int bucket)
1558{
1559 int rc = 0;
1560 u16 cyc_count;
1561 u8 data[2];
1562
1563 if (bucket < 0 || (bucket > BUCKET_COUNT - 1))
1564 return 0;
1565
1566 cyc_count = chip->cyc_ctr.count[bucket];
1567 cyc_count++;
1568 data[0] = cyc_count & 0xFF;
1569 data[1] = cyc_count >> 8;
1570
1571 rc = fg_sram_write(chip, CYCLE_COUNT_WORD + (bucket / 2),
1572 CYCLE_COUNT_OFFSET + (bucket % 2) * 2, data, 2,
1573 FG_IMA_DEFAULT);
1574 if (rc < 0)
1575 pr_err("failed to write BATT_CYCLE[%d] rc=%d\n",
1576 bucket, rc);
1577 else
1578 chip->cyc_ctr.count[bucket] = cyc_count;
1579 return rc;
1580}
1581
1582static void cycle_count_work(struct work_struct *work)
1583{
1584 int rc = 0, bucket, i, batt_soc;
1585 struct fg_chip *chip = container_of(work,
1586 struct fg_chip,
1587 cycle_count_work);
1588
1589 mutex_lock(&chip->cyc_ctr.lock);
1590 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1591 if (rc < 0) {
1592 pr_err("Failed to read battery soc rc: %d\n", rc);
1593 goto out;
1594 }
1595
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001596 /* We need only the most significant byte here */
1597 batt_soc = (u32)batt_soc >> 24;
1598
Nicholas Troaste29dec92016-08-24 09:35:11 -07001599 if (chip->status == POWER_SUPPLY_STATUS_CHARGING) {
1600 /* Find out which bucket the SOC falls in */
1601 bucket = batt_soc / BUCKET_SOC_PCT;
1602 pr_debug("batt_soc: %d bucket: %d\n", batt_soc, bucket);
1603
1604 /*
1605 * If we've started counting for the previous bucket,
1606 * then store the counter for that bucket if the
1607 * counter for current bucket is getting started.
1608 */
1609 if (bucket > 0 && chip->cyc_ctr.started[bucket - 1] &&
1610 !chip->cyc_ctr.started[bucket]) {
1611 rc = fg_inc_store_cycle_ctr(chip, bucket - 1);
1612 if (rc < 0) {
1613 pr_err("Error in storing cycle_ctr rc: %d\n",
1614 rc);
1615 goto out;
1616 } else {
1617 chip->cyc_ctr.started[bucket - 1] = false;
1618 chip->cyc_ctr.last_soc[bucket - 1] = 0;
1619 }
1620 }
1621 if (!chip->cyc_ctr.started[bucket]) {
1622 chip->cyc_ctr.started[bucket] = true;
1623 chip->cyc_ctr.last_soc[bucket] = batt_soc;
1624 }
1625 } else {
1626 for (i = 0; i < BUCKET_COUNT; i++) {
1627 if (chip->cyc_ctr.started[i] &&
1628 batt_soc > chip->cyc_ctr.last_soc[i]) {
1629 rc = fg_inc_store_cycle_ctr(chip, i);
1630 if (rc < 0)
1631 pr_err("Error in storing cycle_ctr rc: %d\n",
1632 rc);
1633 chip->cyc_ctr.last_soc[i] = 0;
1634 }
1635 chip->cyc_ctr.started[i] = false;
1636 }
1637 }
1638out:
1639 mutex_unlock(&chip->cyc_ctr.lock);
1640}
1641
1642static int fg_get_cycle_count(struct fg_chip *chip)
1643{
1644 int count;
1645
1646 if (!chip->cyc_ctr.en)
1647 return 0;
1648
1649 if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT))
1650 return -EINVAL;
1651
1652 mutex_lock(&chip->cyc_ctr.lock);
1653 count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1];
1654 mutex_unlock(&chip->cyc_ctr.lock);
1655 return count;
1656}
1657
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001658static void dump_sram(u8 *buf, int len)
Nicholas Troaste29dec92016-08-24 09:35:11 -07001659{
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001660 int i;
1661 char str[16];
1662
1663 for (i = 0; i < len; i += 4) {
1664 str[0] = '\0';
1665 fill_string(str, sizeof(str), buf + i, 4);
1666 pr_info("%03d %s\n", PROFILE_LOAD_WORD + (i / 4), str);
1667 }
1668}
1669
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001670#define PROFILE_LOAD_BIT BIT(0)
1671#define BOOTLOADER_LOAD_BIT BIT(1)
1672#define BOOTLOADER_RESTART_BIT BIT(2)
1673#define HLOS_RESTART_BIT BIT(3)
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001674static bool is_profile_load_required(struct fg_chip *chip)
1675{
Nicholas Troaste29dec92016-08-24 09:35:11 -07001676 u8 buf[PROFILE_COMP_LEN], val;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001677 bool profiles_same = false;
1678 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001679
Nicholas Troaste29dec92016-08-24 09:35:11 -07001680 rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
1681 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
1682 if (rc < 0) {
1683 pr_err("failed to read profile integrity rc=%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001684 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001685 }
1686
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001687 /* Check if integrity bit is set */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001688 if (val & PROFILE_LOAD_BIT) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001689 fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
1690 rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
1691 buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
1692 if (rc < 0) {
1693 pr_err("Error in reading battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001694 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001695 }
1696 profiles_same = memcmp(chip->batt_profile, buf,
1697 PROFILE_COMP_LEN) == 0;
1698 if (profiles_same) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001699 fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
1700 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001701 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001702
1703 if (!chip->dt.force_load_profile) {
1704 pr_warn("Profiles doesn't match, skipping loading it since force_load_profile is disabled\n");
1705 if (fg_sram_dump) {
1706 pr_info("FG: loaded profile:\n");
1707 dump_sram(buf, PROFILE_COMP_LEN);
1708 pr_info("FG: available profile:\n");
1709 dump_sram(chip->batt_profile, PROFILE_LEN);
1710 }
1711 return false;
1712 }
1713
1714 fg_dbg(chip, FG_STATUS, "Profiles are different, loading the correct one\n");
1715 } else {
1716 fg_dbg(chip, FG_STATUS, "Profile integrity bit is not set\n");
1717 if (fg_sram_dump) {
1718 pr_info("FG: profile to be loaded:\n");
1719 dump_sram(chip->batt_profile, PROFILE_LEN);
1720 }
Nicholas Troaste29dec92016-08-24 09:35:11 -07001721 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001722 return true;
1723}
1724
1725#define SOC_READY_WAIT_MS 2000
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001726static int __fg_restart(struct fg_chip *chip)
1727{
1728 int rc, msoc;
1729 bool tried_again = false;
1730
1731 rc = fg_get_prop_capacity(chip, &msoc);
1732 if (rc < 0) {
1733 pr_err("Error in getting capacity, rc=%d\n", rc);
1734 return rc;
1735 }
1736
1737 chip->last_soc = msoc;
1738 chip->fg_restarting = true;
1739 reinit_completion(&chip->soc_ready);
1740 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT,
1741 RESTART_GO_BIT);
1742 if (rc < 0) {
1743 pr_err("Error in writing to %04x, rc=%d\n",
1744 BATT_SOC_RESTART(chip), rc);
1745 goto out;
1746 }
1747
1748wait:
1749 rc = wait_for_completion_interruptible_timeout(&chip->soc_ready,
1750 msecs_to_jiffies(SOC_READY_WAIT_MS));
1751
1752 /* If we were interrupted wait again one more time. */
1753 if (rc == -ERESTARTSYS && !tried_again) {
1754 tried_again = true;
1755 goto wait;
1756 } else if (rc <= 0) {
1757 pr_err("wait for soc_ready timed out rc=%d\n", rc);
1758 goto out;
1759 }
1760
1761 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
1762 if (rc < 0) {
1763 pr_err("Error in writing to %04x, rc=%d\n",
1764 BATT_SOC_RESTART(chip), rc);
1765 goto out;
1766 }
1767out:
1768 chip->fg_restarting = false;
1769 return rc;
1770}
1771
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001772static void fg_notify_charger(struct fg_chip *chip)
1773{
1774 union power_supply_propval prop = {0, };
1775 int rc;
1776
1777 if (!is_charger_available(chip)) {
1778 pr_warn("Charger not available yet?\n");
1779 return;
1780 }
1781
1782 prop.intval = chip->bp.float_volt_uv;
1783 rc = power_supply_set_property(chip->batt_psy,
1784 POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
1785 if (rc < 0) {
1786 pr_err("Error in setting voltage_max property on batt_psy, rc=%d\n",
1787 rc);
1788 return;
1789 }
1790
Subbaraman Narayanamurthya5d12622016-10-20 12:04:02 -07001791 prop.intval = chip->bp.fastchg_curr_ma * 1000;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001792 rc = power_supply_set_property(chip->batt_psy,
1793 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &prop);
1794 if (rc < 0) {
1795 pr_err("Error in setting constant_charge_current_max property on batt_psy, rc=%d\n",
1796 rc);
1797 return;
1798 }
1799
1800 fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
1801}
1802
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001803static void profile_load_work(struct work_struct *work)
1804{
1805 struct fg_chip *chip = container_of(work,
1806 struct fg_chip,
1807 profile_load_work.work);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001808 u8 buf[2], val;
1809 int rc;
1810
1811 vote(chip->awake_votable, PROFILE_LOAD, true, 0);
1812 if (!is_profile_load_required(chip))
1813 goto done;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001814
1815 clear_cycle_counter(chip);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001816 mutex_lock(&chip->cl.lock);
1817 chip->cl.learned_cc_uah = 0;
1818 chip->cl.active = false;
1819 mutex_unlock(&chip->cl.lock);
1820
Nicholas Troaste29dec92016-08-24 09:35:11 -07001821 fg_dbg(chip, FG_STATUS, "profile loading started\n");
1822 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
1823 if (rc < 0) {
1824 pr_err("Error in writing to %04x, rc=%d\n",
1825 BATT_SOC_RESTART(chip), rc);
1826 goto out;
1827 }
1828
1829 /* load battery profile */
1830 rc = fg_sram_write(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
1831 chip->batt_profile, PROFILE_LEN, FG_IMA_ATOMIC);
1832 if (rc < 0) {
1833 pr_err("Error in writing battery profile, rc:%d\n", rc);
1834 goto out;
1835 }
1836
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001837 rc = __fg_restart(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001838 if (rc < 0) {
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001839 pr_err("Error in restarting FG, rc=%d\n", rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001840 goto out;
1841 }
1842
1843 fg_dbg(chip, FG_STATUS, "SOC is ready\n");
1844
1845 /* Set the profile integrity bit */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07001846 val = HLOS_RESTART_BIT | PROFILE_LOAD_BIT;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001847 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
1848 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
1849 if (rc < 0) {
1850 pr_err("failed to write profile integrity rc=%d\n", rc);
1851 goto out;
1852 }
1853
Nicholas Troaste29dec92016-08-24 09:35:11 -07001854done:
1855 rc = fg_sram_read(chip, NOM_CAP_WORD, NOM_CAP_OFFSET, buf, 2,
1856 FG_IMA_DEFAULT);
1857 if (rc < 0) {
1858 pr_err("Error in reading %04x[%d] rc=%d\n", NOM_CAP_WORD,
1859 NOM_CAP_OFFSET, rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001860 } else {
1861 chip->cl.nom_cap_uah = (int)(buf[0] | buf[1] << 8) * 1000;
1862 rc = fg_load_learned_cap_from_sram(chip);
1863 if (rc < 0)
1864 pr_err("Error in loading capacity learning data, rc:%d\n",
1865 rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001866 }
1867
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001868 fg_notify_charger(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001869 chip->profile_loaded = true;
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001870 fg_dbg(chip, FG_STATUS, "profile loaded successfully");
Nicholas Troaste29dec92016-08-24 09:35:11 -07001871out:
1872 vote(chip->awake_votable, PROFILE_LOAD, false, 0);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001873}
1874
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001875static int fg_restart_sysfs(const char *val, const struct kernel_param *kp)
1876{
1877 int rc;
1878 struct power_supply *bms_psy;
1879 struct fg_chip *chip;
1880
1881 rc = param_set_int(val, kp);
1882 if (rc) {
1883 pr_err("Unable to set fg_restart: %d\n", rc);
1884 return rc;
1885 }
1886
1887 if (fg_restart != 1) {
1888 pr_err("Bad value %d\n", fg_restart);
1889 return -EINVAL;
1890 }
1891
1892 bms_psy = power_supply_get_by_name("bms");
1893 if (!bms_psy) {
1894 pr_err("bms psy not found\n");
1895 return 0;
1896 }
1897
1898 chip = power_supply_get_drvdata(bms_psy);
1899 rc = __fg_restart(chip);
1900 if (rc < 0) {
1901 pr_err("Error in restarting FG, rc=%d\n", rc);
1902 return rc;
1903 }
1904
1905 pr_info("FG restart done\n");
1906 return rc;
1907}
1908
1909static struct kernel_param_ops fg_restart_ops = {
1910 .set = fg_restart_sysfs,
1911 .get = param_get_int,
1912};
1913
1914module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
1915
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001916/* PSY CALLBACKS STAY HERE */
1917
1918static int fg_psy_get_property(struct power_supply *psy,
1919 enum power_supply_property psp,
1920 union power_supply_propval *pval)
1921{
1922 struct fg_chip *chip = power_supply_get_drvdata(psy);
1923 int rc = 0;
1924
1925 switch (psp) {
1926 case POWER_SUPPLY_PROP_CAPACITY:
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001927 if (chip->fg_restarting)
1928 pval->intval = chip->last_soc;
1929 else
1930 rc = fg_get_prop_capacity(chip, &pval->intval);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001931 break;
1932 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1933 rc = fg_get_battery_voltage(chip, &pval->intval);
1934 break;
1935 case POWER_SUPPLY_PROP_CURRENT_NOW:
1936 rc = fg_get_battery_current(chip, &pval->intval);
1937 break;
1938 case POWER_SUPPLY_PROP_TEMP:
1939 rc = fg_get_battery_temp(chip, &pval->intval);
1940 break;
1941 case POWER_SUPPLY_PROP_RESISTANCE:
1942 rc = fg_get_battery_resistance(chip, &pval->intval);
1943 break;
1944 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
1945 rc = fg_get_sram_prop(chip, FG_SRAM_OCV, &pval->intval);
1946 break;
1947 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001948 pval->intval = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001949 break;
1950 case POWER_SUPPLY_PROP_RESISTANCE_ID:
1951 rc = fg_get_batt_id(chip, &pval->intval);
1952 break;
1953 case POWER_SUPPLY_PROP_BATTERY_TYPE:
1954 pval->strval = fg_get_battery_type(chip);
1955 break;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07001956 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1957 pval->intval = chip->bp.float_volt_uv;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001958 break;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001959 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1960 pval->intval = fg_get_cycle_count(chip);
1961 break;
1962 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
1963 pval->intval = chip->cyc_ctr.id;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07001964 break;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001965 case POWER_SUPPLY_PROP_CHARGE_NOW_RAW:
1966 rc = fg_get_cc_soc(chip, &pval->intval);
1967 break;
1968 case POWER_SUPPLY_PROP_CHARGE_NOW:
1969 pval->intval = chip->cl.init_cc_uah;
1970 break;
1971 case POWER_SUPPLY_PROP_CHARGE_FULL:
1972 pval->intval = chip->cl.learned_cc_uah;
1973 break;
1974 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
1975 rc = fg_get_cc_soc_sw(chip, &pval->intval);
1976 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001977 default:
1978 break;
1979 }
1980
1981 return rc;
1982}
1983
1984static int fg_psy_set_property(struct power_supply *psy,
1985 enum power_supply_property psp,
1986 const union power_supply_propval *pval)
1987{
Nicholas Troaste29dec92016-08-24 09:35:11 -07001988 struct fg_chip *chip = power_supply_get_drvdata(psy);
1989
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001990 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001991 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
1992 if ((pval->intval > 0) && (pval->intval <= BUCKET_COUNT)) {
1993 chip->cyc_ctr.id = pval->intval;
1994 } else {
1995 pr_err("rejecting invalid cycle_count_id = %d\n",
1996 pval->intval);
1997 return -EINVAL;
1998 }
1999 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002000 default:
2001 break;
2002 }
2003
2004 return 0;
2005}
2006
2007static int fg_property_is_writeable(struct power_supply *psy,
2008 enum power_supply_property psp)
2009{
2010 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002011 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
2012 return 1;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002013 default:
2014 break;
2015 }
2016
2017 return 0;
2018}
2019
2020static void fg_external_power_changed(struct power_supply *psy)
2021{
2022 pr_debug("power supply changed\n");
2023}
2024
2025static int fg_notifier_cb(struct notifier_block *nb,
2026 unsigned long event, void *data)
2027{
2028 struct power_supply *psy = data;
2029 struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
2030
2031 if (event != PSY_EVENT_PROP_CHANGED)
2032 return NOTIFY_OK;
2033
2034 if ((strcmp(psy->desc->name, "battery") == 0)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002035 || (strcmp(psy->desc->name, "usb") == 0)) {
2036 /*
2037 * We cannot vote for awake votable here as that takes
2038 * a mutex lock and this is executed in an atomic context.
2039 */
2040 pm_stay_awake(chip->dev);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002041 schedule_work(&chip->status_change_work);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002042 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002043
2044 return NOTIFY_OK;
2045}
2046
2047static enum power_supply_property fg_psy_props[] = {
2048 POWER_SUPPLY_PROP_CAPACITY,
2049 POWER_SUPPLY_PROP_TEMP,
2050 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2051 POWER_SUPPLY_PROP_VOLTAGE_OCV,
2052 POWER_SUPPLY_PROP_CURRENT_NOW,
2053 POWER_SUPPLY_PROP_RESISTANCE_ID,
2054 POWER_SUPPLY_PROP_RESISTANCE,
2055 POWER_SUPPLY_PROP_BATTERY_TYPE,
2056 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07002057 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Nicholas Troaste29dec92016-08-24 09:35:11 -07002058 POWER_SUPPLY_PROP_CYCLE_COUNT,
2059 POWER_SUPPLY_PROP_CYCLE_COUNT_ID,
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002060 POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
2061 POWER_SUPPLY_PROP_CHARGE_NOW,
2062 POWER_SUPPLY_PROP_CHARGE_FULL,
2063 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002064};
2065
2066static const struct power_supply_desc fg_psy_desc = {
2067 .name = "bms",
2068 .type = POWER_SUPPLY_TYPE_BMS,
2069 .properties = fg_psy_props,
2070 .num_properties = ARRAY_SIZE(fg_psy_props),
2071 .get_property = fg_psy_get_property,
2072 .set_property = fg_psy_set_property,
2073 .external_power_changed = fg_external_power_changed,
2074 .property_is_writeable = fg_property_is_writeable,
2075};
2076
2077/* INIT FUNCTIONS STAY HERE */
2078
2079static int fg_hw_init(struct fg_chip *chip)
2080{
2081 int rc;
2082 u8 buf[4], val;
2083
2084 fg_encode(chip->sp, FG_SRAM_CUTOFF_VOLT, chip->dt.cutoff_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002085 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CUTOFF_VOLT].addr_word,
2086 chip->sp[FG_SRAM_CUTOFF_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002087 chip->sp[FG_SRAM_CUTOFF_VOLT].len, FG_IMA_DEFAULT);
2088 if (rc < 0) {
2089 pr_err("Error in writing cutoff_volt, rc=%d\n", rc);
2090 return rc;
2091 }
2092
2093 fg_encode(chip->sp, FG_SRAM_EMPTY_VOLT, chip->dt.empty_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002094 rc = fg_sram_write(chip, chip->sp[FG_SRAM_EMPTY_VOLT].addr_word,
2095 chip->sp[FG_SRAM_EMPTY_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002096 chip->sp[FG_SRAM_EMPTY_VOLT].len, FG_IMA_DEFAULT);
2097 if (rc < 0) {
2098 pr_err("Error in writing empty_volt, rc=%d\n", rc);
2099 return rc;
2100 }
2101
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002102 /* This SRAM register is only present in v2.0 */
2103 if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4 &&
2104 chip->bp.float_volt_uv > 0) {
2105 fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT,
2106 chip->bp.float_volt_uv / 1000, buf);
2107 rc = fg_sram_write(chip, chip->sp[FG_SRAM_FLOAT_VOLT].addr_word,
2108 chip->sp[FG_SRAM_FLOAT_VOLT].addr_byte, buf,
2109 chip->sp[FG_SRAM_FLOAT_VOLT].len, FG_IMA_DEFAULT);
2110 if (rc < 0) {
2111 pr_err("Error in writing float_volt, rc=%d\n", rc);
2112 return rc;
2113 }
2114 }
2115
2116 if (chip->bp.vbatt_full_mv > 0) {
2117 fg_encode(chip->sp, FG_SRAM_VBATT_FULL, chip->bp.vbatt_full_mv,
2118 buf);
2119 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_FULL].addr_word,
2120 chip->sp[FG_SRAM_VBATT_FULL].addr_byte, buf,
2121 chip->sp[FG_SRAM_VBATT_FULL].len, FG_IMA_DEFAULT);
2122 if (rc < 0) {
2123 pr_err("Error in writing vbatt_full, rc=%d\n", rc);
2124 return rc;
2125 }
2126 }
2127
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002128 fg_encode(chip->sp, FG_SRAM_CHG_TERM_CURR, chip->dt.chg_term_curr_ma,
2129 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002130 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CHG_TERM_CURR].addr_word,
2131 chip->sp[FG_SRAM_CHG_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002132 chip->sp[FG_SRAM_CHG_TERM_CURR].len, FG_IMA_DEFAULT);
2133 if (rc < 0) {
2134 pr_err("Error in writing chg_term_curr, rc=%d\n", rc);
2135 return rc;
2136 }
2137
2138 fg_encode(chip->sp, FG_SRAM_SYS_TERM_CURR, chip->dt.sys_term_curr_ma,
2139 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002140 rc = fg_sram_write(chip, chip->sp[FG_SRAM_SYS_TERM_CURR].addr_word,
2141 chip->sp[FG_SRAM_SYS_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002142 chip->sp[FG_SRAM_SYS_TERM_CURR].len, FG_IMA_DEFAULT);
2143 if (rc < 0) {
2144 pr_err("Error in writing sys_term_curr, rc=%d\n", rc);
2145 return rc;
2146 }
2147
2148 if (chip->dt.vbatt_low_thr_mv > 0) {
2149 fg_encode(chip->sp, FG_SRAM_VBATT_LOW,
2150 chip->dt.vbatt_low_thr_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002151 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_LOW].addr_word,
2152 chip->sp[FG_SRAM_VBATT_LOW].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002153 chip->sp[FG_SRAM_VBATT_LOW].len,
2154 FG_IMA_DEFAULT);
2155 if (rc < 0) {
2156 pr_err("Error in writing vbatt_low_thr, rc=%d\n", rc);
2157 return rc;
2158 }
2159 }
2160
2161 if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) {
2162 fg_encode(chip->sp, FG_SRAM_DELTA_SOC_THR,
2163 chip->dt.delta_soc_thr, buf);
2164 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -07002165 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_word,
2166 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002167 buf, chip->sp[FG_SRAM_DELTA_SOC_THR].len,
2168 FG_IMA_DEFAULT);
2169 if (rc < 0) {
2170 pr_err("Error in writing delta_soc_thr, rc=%d\n", rc);
2171 return rc;
2172 }
2173 }
2174
2175 if (chip->dt.recharge_soc_thr > 0 && chip->dt.recharge_soc_thr < 100) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002176 rc = fg_set_recharge_soc(chip, chip->dt.recharge_soc_thr);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002177 if (rc < 0) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002178 pr_err("Error in setting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002179 return rc;
2180 }
2181 }
2182
2183 if (chip->dt.rsense_sel >= SRC_SEL_BATFET &&
2184 chip->dt.rsense_sel < SRC_SEL_RESERVED) {
2185 rc = fg_masked_write(chip, BATT_INFO_IBATT_SENSING_CFG(chip),
2186 SOURCE_SELECT_MASK, chip->dt.rsense_sel);
2187 if (rc < 0) {
2188 pr_err("Error in writing rsense_sel, rc=%d\n", rc);
2189 return rc;
2190 }
2191 }
2192
2193 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COLD], &val);
2194 rc = fg_write(chip, BATT_INFO_JEITA_TOO_COLD(chip), &val, 1);
2195 if (rc < 0) {
2196 pr_err("Error in writing jeita_cold, rc=%d\n", rc);
2197 return rc;
2198 }
2199
2200 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COOL], &val);
2201 rc = fg_write(chip, BATT_INFO_JEITA_COLD(chip), &val, 1);
2202 if (rc < 0) {
2203 pr_err("Error in writing jeita_cool, rc=%d\n", rc);
2204 return rc;
2205 }
2206
2207 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_WARM], &val);
2208 rc = fg_write(chip, BATT_INFO_JEITA_HOT(chip), &val, 1);
2209 if (rc < 0) {
2210 pr_err("Error in writing jeita_warm, rc=%d\n", rc);
2211 return rc;
2212 }
2213
2214 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_HOT], &val);
2215 rc = fg_write(chip, BATT_INFO_JEITA_TOO_HOT(chip), &val, 1);
2216 if (rc < 0) {
2217 pr_err("Error in writing jeita_hot, rc=%d\n", rc);
2218 return rc;
2219 }
2220
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002221 if (chip->dt.esr_timer_charging > 0) {
2222 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_charging, true,
2223 FG_IMA_DEFAULT);
2224 if (rc < 0) {
2225 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2226 return rc;
2227 }
2228 }
2229
2230 if (chip->dt.esr_timer_awake > 0) {
2231 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
2232 FG_IMA_DEFAULT);
2233 if (rc < 0) {
2234 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2235 return rc;
2236 }
2237 }
2238
Nicholas Troaste29dec92016-08-24 09:35:11 -07002239 if (chip->cyc_ctr.en)
2240 restore_cycle_counter(chip);
2241
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002242 if (chip->dt.jeita_hyst_temp >= 0) {
2243 val = chip->dt.jeita_hyst_temp << JEITA_TEMP_HYST_SHIFT;
2244 rc = fg_masked_write(chip, BATT_INFO_BATT_TEMP_CFG(chip),
2245 JEITA_TEMP_HYST_MASK, val);
2246 if (rc < 0) {
2247 pr_err("Error in writing batt_temp_cfg, rc=%d\n", rc);
2248 return rc;
2249 }
2250 }
2251
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002252 get_batt_temp_delta(chip->dt.batt_temp_delta, &val);
2253 rc = fg_masked_write(chip, BATT_INFO_BATT_TMPR_INTR(chip),
2254 CHANGE_THOLD_MASK, val);
2255 if (rc < 0) {
2256 pr_err("Error in writing batt_temp_delta, rc=%d\n", rc);
2257 return rc;
2258 }
2259
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002260 return 0;
2261}
2262
2263static int fg_memif_init(struct fg_chip *chip)
2264{
2265 return fg_ima_init(chip);
2266}
2267
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002268/* INTERRUPT HANDLERS STAY HERE */
2269
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07002270static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
2271{
2272 struct fg_chip *chip = data;
2273 u8 status;
2274 int rc;
2275
2276 rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1);
2277 if (rc < 0) {
2278 pr_err("failed to read addr=0x%04x, rc=%d\n",
2279 MEM_IF_INT_RT_STS(chip), rc);
2280 return IRQ_HANDLED;
2281 }
2282
2283 fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status);
2284 if (status & MEM_XCP_BIT) {
2285 rc = fg_clear_dma_errors_if_any(chip);
2286 if (rc < 0) {
2287 pr_err("Error in clearing DMA error, rc=%d\n", rc);
2288 return IRQ_HANDLED;
2289 }
2290
2291 mutex_lock(&chip->sram_rw_lock);
2292 rc = fg_clear_ima_errors_if_any(chip, true);
2293 if (rc < 0 && rc != -EAGAIN)
2294 pr_err("Error in checking IMA errors rc:%d\n", rc);
2295 mutex_unlock(&chip->sram_rw_lock);
2296 }
2297
2298 return IRQ_HANDLED;
2299}
2300
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002301static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
2302{
2303 struct fg_chip *chip = data;
2304
2305 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2306 return IRQ_HANDLED;
2307}
2308
2309static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
2310{
2311 struct fg_chip *chip = data;
2312 u8 status;
2313 int rc;
2314
2315 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2316 rc = fg_read(chip, BATT_INFO_INT_RT_STS(chip), &status, 1);
2317 if (rc < 0) {
2318 pr_err("failed to read addr=0x%04x, rc=%d\n",
2319 BATT_INFO_INT_RT_STS(chip), rc);
2320 return IRQ_HANDLED;
2321 }
2322
2323 chip->battery_missing = (status & BT_MISS_BIT);
2324
2325 if (chip->battery_missing) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002326 chip->profile_available = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002327 chip->profile_loaded = false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002328 clear_cycle_counter(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002329 } else {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002330 rc = fg_get_batt_profile(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002331 if (rc < 0) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002332 pr_err("Error in getting battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002333 return IRQ_HANDLED;
2334 }
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002335 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002336 }
2337
2338 return IRQ_HANDLED;
2339}
2340
2341static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data)
2342{
2343 struct fg_chip *chip = data;
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002344 union power_supply_propval prop = {0, };
2345 int rc, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002346
2347 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002348 rc = fg_get_battery_temp(chip, &batt_temp);
2349 if (rc < 0) {
2350 pr_err("Error in getting batt_temp\n");
2351 return IRQ_HANDLED;
2352 }
2353
2354 if (!is_charger_available(chip)) {
2355 chip->last_batt_temp = batt_temp;
2356 return IRQ_HANDLED;
2357 }
2358
2359 power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
2360 &prop);
2361 chip->health = prop.intval;
2362
2363 if (chip->last_batt_temp != batt_temp) {
2364 chip->last_batt_temp = batt_temp;
2365 power_supply_changed(chip->batt_psy);
2366 }
2367
2368 if (abs(chip->last_batt_temp - batt_temp) > 30)
2369 pr_warn("Battery temperature last:%d current: %d\n",
2370 chip->last_batt_temp, batt_temp);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002371 return IRQ_HANDLED;
2372}
2373
2374static irqreturn_t fg_first_est_irq_handler(int irq, void *data)
2375{
2376 struct fg_chip *chip = data;
2377
2378 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2379 complete_all(&chip->soc_ready);
2380 return IRQ_HANDLED;
2381}
2382
2383static irqreturn_t fg_soc_update_irq_handler(int irq, void *data)
2384{
2385 struct fg_chip *chip = data;
2386
2387 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2388 complete_all(&chip->soc_update);
2389 return IRQ_HANDLED;
2390}
2391
2392static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
2393{
2394 struct fg_chip *chip = data;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002395 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002396
Nicholas Troaste29dec92016-08-24 09:35:11 -07002397 if (chip->cyc_ctr.en)
2398 schedule_work(&chip->cycle_count_work);
2399
Nicholas Troast65e29652016-09-22 11:27:04 -07002400 if (is_charger_available(chip))
2401 power_supply_changed(chip->batt_psy);
2402
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002403 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002404
2405 if (chip->cl.active)
2406 fg_cap_learning_update(chip);
2407
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002408 rc = fg_charge_full_update(chip);
2409 if (rc < 0)
2410 pr_err("Error in charge_full_update, rc=%d\n", rc);
2411
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002412 rc = fg_adjust_ki_coeff_dischg(chip);
2413 if (rc < 0)
2414 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
2415
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002416 return IRQ_HANDLED;
2417}
2418
2419static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data)
2420{
2421 struct fg_chip *chip = data;
2422
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -07002423 chip->charge_empty = true;
Nicholas Troast65e29652016-09-22 11:27:04 -07002424 if (is_charger_available(chip))
2425 power_supply_changed(chip->batt_psy);
2426
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002427 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2428 return IRQ_HANDLED;
2429}
2430
2431static irqreturn_t fg_soc_irq_handler(int irq, void *data)
2432{
2433 struct fg_chip *chip = data;
2434
2435 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2436 return IRQ_HANDLED;
2437}
2438
2439static irqreturn_t fg_dummy_irq_handler(int irq, void *data)
2440{
2441 struct fg_chip *chip = data;
2442
2443 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2444 return IRQ_HANDLED;
2445}
2446
2447static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
2448 /* BATT_SOC irqs */
2449 [MSOC_FULL_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002450 .name = "msoc-full",
2451 .handler = fg_soc_irq_handler,
2452 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002453 [MSOC_HIGH_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002454 .name = "msoc-high",
2455 .handler = fg_soc_irq_handler,
2456 .wakeable = true,
2457 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002458 [MSOC_EMPTY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002459 .name = "msoc-empty",
2460 .handler = fg_empty_soc_irq_handler,
2461 .wakeable = true,
2462 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002463 [MSOC_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002464 .name = "msoc-low",
2465 .handler = fg_soc_irq_handler,
2466 .wakeable = true,
2467 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002468 [MSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002469 .name = "msoc-delta",
2470 .handler = fg_delta_soc_irq_handler,
2471 .wakeable = true,
2472 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002473 [BSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002474 .name = "bsoc-delta",
2475 .handler = fg_dummy_irq_handler,
2476 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002477 [SOC_READY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002478 .name = "soc-ready",
2479 .handler = fg_first_est_irq_handler,
2480 .wakeable = true,
2481 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002482 [SOC_UPDATE_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002483 .name = "soc-update",
2484 .handler = fg_soc_update_irq_handler,
2485 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002486 /* BATT_INFO irqs */
2487 [BATT_TEMP_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002488 .name = "batt-temp-delta",
2489 .handler = fg_delta_batt_temp_irq_handler,
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002490 .wakeable = true,
Nicholas Troast3cc97182016-09-23 08:54:13 -07002491 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002492 [BATT_MISSING_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002493 .name = "batt-missing",
2494 .handler = fg_batt_missing_irq_handler,
2495 .wakeable = true,
2496 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002497 [ESR_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002498 .name = "esr-delta",
2499 .handler = fg_dummy_irq_handler,
2500 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002501 [VBATT_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002502 .name = "vbatt-low",
2503 .handler = fg_vbatt_low_irq_handler,
2504 .wakeable = true,
2505 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002506 [VBATT_PRED_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002507 .name = "vbatt-pred-delta",
2508 .handler = fg_dummy_irq_handler,
2509 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002510 /* MEM_IF irqs */
2511 [DMA_GRANT_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002512 .name = "dma-grant",
2513 .handler = fg_dummy_irq_handler,
2514 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002515 [MEM_XCP_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002516 .name = "mem-xcp",
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07002517 .handler = fg_mem_xcp_irq_handler,
Nicholas Troast3cc97182016-09-23 08:54:13 -07002518 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002519 [IMA_RDY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002520 .name = "ima-rdy",
2521 .handler = fg_dummy_irq_handler,
2522 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002523};
2524
2525static int fg_get_irq_index_byname(const char *name)
2526{
2527 int i;
2528
2529 for (i = 0; i < ARRAY_SIZE(fg_irqs); i++) {
2530 if (strcmp(fg_irqs[i].name, name) == 0)
2531 return i;
2532 }
2533
2534 pr_err("%s is not in irq list\n", name);
2535 return -ENOENT;
2536}
2537
2538static int fg_register_interrupts(struct fg_chip *chip)
2539{
2540 struct device_node *child, *node = chip->dev->of_node;
2541 struct property *prop;
2542 const char *name;
2543 int rc, irq, irq_index;
2544
2545 for_each_available_child_of_node(node, child) {
2546 of_property_for_each_string(child, "interrupt-names", prop,
2547 name) {
2548 irq = of_irq_get_byname(child, name);
2549 if (irq < 0) {
2550 dev_err(chip->dev, "failed to get irq %s irq:%d\n",
2551 name, irq);
2552 return irq;
2553 }
2554
2555 irq_index = fg_get_irq_index_byname(name);
2556 if (irq_index < 0)
2557 return irq_index;
2558
2559 rc = devm_request_threaded_irq(chip->dev, irq, NULL,
2560 fg_irqs[irq_index].handler,
2561 IRQF_ONESHOT, name, chip);
2562 if (rc < 0) {
2563 dev_err(chip->dev, "failed to register irq handler for %s rc:%d\n",
2564 name, rc);
2565 return rc;
2566 }
2567
2568 fg_irqs[irq_index].irq = irq;
2569 if (fg_irqs[irq_index].wakeable)
2570 enable_irq_wake(fg_irqs[irq_index].irq);
2571 }
2572 }
2573
2574 return 0;
2575}
2576
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002577static int fg_parse_ki_coefficients(struct fg_chip *chip)
2578{
2579 struct device_node *node = chip->dev->of_node;
2580 int rc, i;
2581
2582 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-soc-dischg",
2583 sizeof(u32));
2584 if (rc != KI_COEFF_SOC_LEVELS)
2585 return 0;
2586
2587 rc = of_property_read_u32_array(node, "qcom,ki-coeff-soc-dischg",
2588 chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
2589 if (rc < 0) {
2590 pr_err("Error in reading ki-coeff-soc-dischg, rc=%d\n",
2591 rc);
2592 return rc;
2593 }
2594
2595 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-med-dischg",
2596 sizeof(u32));
2597 if (rc != KI_COEFF_SOC_LEVELS)
2598 return 0;
2599
2600 rc = of_property_read_u32_array(node, "qcom,ki-coeff-med-dischg",
2601 chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
2602 if (rc < 0) {
2603 pr_err("Error in reading ki-coeff-med-dischg, rc=%d\n",
2604 rc);
2605 return rc;
2606 }
2607
2608 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-hi-dischg",
2609 sizeof(u32));
2610 if (rc != KI_COEFF_SOC_LEVELS)
2611 return 0;
2612
2613 rc = of_property_read_u32_array(node, "qcom,ki-coeff-hi-dischg",
2614 chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
2615 if (rc < 0) {
2616 pr_err("Error in reading ki-coeff-hi-dischg, rc=%d\n",
2617 rc);
2618 return rc;
2619 }
2620
2621 for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
2622 if (chip->dt.ki_coeff_soc[i] < 0 ||
2623 chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
2624 pr_err("Error in ki_coeff_soc_dischg values\n");
2625 return -EINVAL;
2626 }
2627
2628 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
2629 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
2630 pr_err("Error in ki_coeff_med_dischg values\n");
2631 return -EINVAL;
2632 }
2633
2634 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
2635 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
2636 pr_err("Error in ki_coeff_med_dischg values\n");
2637 return -EINVAL;
2638 }
2639 }
2640 chip->ki_coeff_dischg_en = true;
2641 return 0;
2642}
2643
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002644#define DEFAULT_CUTOFF_VOLT_MV 3200
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -07002645#define DEFAULT_EMPTY_VOLT_MV 2800
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002646#define DEFAULT_CHG_TERM_CURR_MA 100
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -07002647#define DEFAULT_SYS_TERM_CURR_MA -125
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002648#define DEFAULT_DELTA_SOC_THR 1
2649#define DEFAULT_RECHARGE_SOC_THR 95
2650#define DEFAULT_BATT_TEMP_COLD 0
2651#define DEFAULT_BATT_TEMP_COOL 5
2652#define DEFAULT_BATT_TEMP_WARM 45
2653#define DEFAULT_BATT_TEMP_HOT 50
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002654#define DEFAULT_CL_START_SOC 15
2655#define DEFAULT_CL_MIN_TEMP_DECIDEGC 150
2656#define DEFAULT_CL_MAX_TEMP_DECIDEGC 450
2657#define DEFAULT_CL_MAX_INC_DECIPERC 5
2658#define DEFAULT_CL_MAX_DEC_DECIPERC 100
2659#define DEFAULT_CL_MIN_LIM_DECIPERC 0
2660#define DEFAULT_CL_MAX_LIM_DECIPERC 0
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002661#define BTEMP_DELTA_LOW 2
2662#define BTEMP_DELTA_HIGH 10
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002663static int fg_parse_dt(struct fg_chip *chip)
2664{
2665 struct device_node *child, *revid_node, *node = chip->dev->of_node;
2666 u32 base, temp;
2667 u8 subtype;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002668 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002669
2670 if (!node) {
2671 dev_err(chip->dev, "device tree node missing\n");
2672 return -ENXIO;
2673 }
2674
2675 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
2676 if (!revid_node) {
2677 pr_err("Missing qcom,pmic-revid property - driver failed\n");
2678 return -EINVAL;
2679 }
2680
2681 chip->pmic_rev_id = get_revid_data(revid_node);
2682 if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
2683 pr_err("Unable to get pmic_revid rc=%ld\n",
2684 PTR_ERR(chip->pmic_rev_id));
2685 /*
2686 * the revid peripheral must be registered, any failure
2687 * here only indicates that the rev-id module has not
2688 * probed yet.
2689 */
2690 return -EPROBE_DEFER;
2691 }
2692
2693 pr_debug("PMIC subtype %d Digital major %d\n",
2694 chip->pmic_rev_id->pmic_subtype, chip->pmic_rev_id->rev4);
2695
2696 switch (chip->pmic_rev_id->pmic_subtype) {
2697 case PMICOBALT_SUBTYPE:
Nicholas Troast69da2252016-09-07 16:17:47 -07002698 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4) {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002699 chip->sp = pmicobalt_v1_sram_params;
Nicholas Troast69da2252016-09-07 16:17:47 -07002700 chip->alg_flags = pmicobalt_v1_alg_flags;
2701 } else if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4) {
Nicholas Troasta2b40372016-08-15 10:45:39 -07002702 chip->sp = pmicobalt_v2_sram_params;
Nicholas Troast69da2252016-09-07 16:17:47 -07002703 chip->alg_flags = pmicobalt_v2_alg_flags;
2704 } else {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002705 return -EINVAL;
Nicholas Troast69da2252016-09-07 16:17:47 -07002706 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002707 break;
2708 default:
2709 return -EINVAL;
2710 }
2711
2712 chip->batt_id_chan = iio_channel_get(chip->dev, "rradc_batt_id");
2713 if (IS_ERR(chip->batt_id_chan)) {
2714 if (PTR_ERR(chip->batt_id_chan) != -EPROBE_DEFER)
2715 pr_err("batt_id_chan unavailable %ld\n",
2716 PTR_ERR(chip->batt_id_chan));
2717 rc = PTR_ERR(chip->batt_id_chan);
2718 chip->batt_id_chan = NULL;
2719 return rc;
2720 }
2721
2722 if (of_get_available_child_count(node) == 0) {
2723 dev_err(chip->dev, "No child nodes specified!\n");
2724 return -ENXIO;
2725 }
2726
2727 for_each_available_child_of_node(node, child) {
2728 rc = of_property_read_u32(child, "reg", &base);
2729 if (rc < 0) {
2730 dev_err(chip->dev, "reg not specified in node %s, rc=%d\n",
2731 child->full_name, rc);
2732 return rc;
2733 }
2734
2735 rc = fg_read(chip, base + PERPH_SUBTYPE_REG, &subtype, 1);
2736 if (rc < 0) {
2737 dev_err(chip->dev, "Couldn't read subtype for base %d, rc=%d\n",
2738 base, rc);
2739 return rc;
2740 }
2741
2742 switch (subtype) {
2743 case FG_BATT_SOC_PMICOBALT:
2744 chip->batt_soc_base = base;
2745 break;
2746 case FG_BATT_INFO_PMICOBALT:
2747 chip->batt_info_base = base;
2748 break;
2749 case FG_MEM_INFO_PMICOBALT:
2750 chip->mem_if_base = base;
2751 break;
2752 default:
2753 dev_err(chip->dev, "Invalid peripheral subtype 0x%x\n",
2754 subtype);
2755 return -ENXIO;
2756 }
2757 }
2758
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002759 rc = fg_get_batt_profile(chip);
2760 if (rc < 0)
2761 pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -07002762 chip->batt_id_kohms, rc);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002763
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002764 /* Read all the optional properties below */
2765 rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp);
2766 if (rc < 0)
2767 chip->dt.cutoff_volt_mv = DEFAULT_CUTOFF_VOLT_MV;
2768 else
2769 chip->dt.cutoff_volt_mv = temp;
2770
2771 rc = of_property_read_u32(node, "qcom,fg-empty-voltage", &temp);
2772 if (rc < 0)
2773 chip->dt.empty_volt_mv = DEFAULT_EMPTY_VOLT_MV;
2774 else
2775 chip->dt.empty_volt_mv = temp;
2776
2777 rc = of_property_read_u32(node, "qcom,fg-vbatt-low-thr", &temp);
2778 if (rc < 0)
2779 chip->dt.vbatt_low_thr_mv = -EINVAL;
2780 else
2781 chip->dt.vbatt_low_thr_mv = temp;
2782
2783 rc = of_property_read_u32(node, "qcom,fg-chg-term-current", &temp);
2784 if (rc < 0)
2785 chip->dt.chg_term_curr_ma = DEFAULT_CHG_TERM_CURR_MA;
2786 else
2787 chip->dt.chg_term_curr_ma = temp;
2788
2789 rc = of_property_read_u32(node, "qcom,fg-sys-term-current", &temp);
2790 if (rc < 0)
2791 chip->dt.sys_term_curr_ma = DEFAULT_SYS_TERM_CURR_MA;
2792 else
2793 chip->dt.sys_term_curr_ma = temp;
2794
2795 rc = of_property_read_u32(node, "qcom,fg-delta-soc-thr", &temp);
2796 if (rc < 0)
2797 chip->dt.delta_soc_thr = DEFAULT_DELTA_SOC_THR;
2798 else
2799 chip->dt.delta_soc_thr = temp;
2800
2801 rc = of_property_read_u32(node, "qcom,fg-recharge-soc-thr", &temp);
2802 if (rc < 0)
2803 chip->dt.recharge_soc_thr = DEFAULT_RECHARGE_SOC_THR;
2804 else
2805 chip->dt.recharge_soc_thr = temp;
2806
2807 rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp);
2808 if (rc < 0)
2809 chip->dt.rsense_sel = SRC_SEL_BATFET_SMB;
2810 else
2811 chip->dt.rsense_sel = (u8)temp & SOURCE_SELECT_MASK;
2812
2813 chip->dt.jeita_thresholds[JEITA_COLD] = DEFAULT_BATT_TEMP_COLD;
2814 chip->dt.jeita_thresholds[JEITA_COOL] = DEFAULT_BATT_TEMP_COOL;
2815 chip->dt.jeita_thresholds[JEITA_WARM] = DEFAULT_BATT_TEMP_WARM;
2816 chip->dt.jeita_thresholds[JEITA_HOT] = DEFAULT_BATT_TEMP_HOT;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002817 if (of_property_count_elems_of_size(node, "qcom,fg-jeita-thresholds",
2818 sizeof(u32)) == NUM_JEITA_LEVELS) {
2819 rc = of_property_read_u32_array(node,
2820 "qcom,fg-jeita-thresholds",
2821 chip->dt.jeita_thresholds, NUM_JEITA_LEVELS);
2822 if (rc < 0)
2823 pr_warn("Error reading Jeita thresholds, default values will be used rc:%d\n",
2824 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002825 }
2826
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002827 rc = of_property_read_u32(node, "qcom,fg-esr-timer-charging", &temp);
2828 if (rc < 0)
2829 chip->dt.esr_timer_charging = -EINVAL;
2830 else
2831 chip->dt.esr_timer_charging = temp;
2832
2833 rc = of_property_read_u32(node, "qcom,fg-esr-timer-awake", &temp);
2834 if (rc < 0)
2835 chip->dt.esr_timer_awake = -EINVAL;
2836 else
2837 chip->dt.esr_timer_awake = temp;
2838
2839 rc = of_property_read_u32(node, "qcom,fg-esr-timer-asleep", &temp);
2840 if (rc < 0)
2841 chip->dt.esr_timer_asleep = -EINVAL;
2842 else
2843 chip->dt.esr_timer_asleep = temp;
2844
Nicholas Troaste29dec92016-08-24 09:35:11 -07002845 chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
2846 if (chip->cyc_ctr.en)
2847 chip->cyc_ctr.id = 1;
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002848
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002849 chip->dt.force_load_profile = of_property_read_bool(node,
2850 "qcom,fg-force-load-profile");
2851
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002852 rc = of_property_read_u32(node, "qcom,cl-start-capacity", &temp);
2853 if (rc < 0)
2854 chip->dt.cl_start_soc = DEFAULT_CL_START_SOC;
2855 else
2856 chip->dt.cl_start_soc = temp;
2857
2858 rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp);
2859 if (rc < 0)
2860 chip->dt.cl_min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC;
2861 else
2862 chip->dt.cl_min_temp = temp;
2863
2864 rc = of_property_read_u32(node, "qcom,cl-max-temp", &temp);
2865 if (rc < 0)
2866 chip->dt.cl_max_temp = DEFAULT_CL_MAX_TEMP_DECIDEGC;
2867 else
2868 chip->dt.cl_max_temp = temp;
2869
2870 rc = of_property_read_u32(node, "qcom,cl-max-increment", &temp);
2871 if (rc < 0)
2872 chip->dt.cl_max_cap_inc = DEFAULT_CL_MAX_INC_DECIPERC;
2873 else
2874 chip->dt.cl_max_cap_inc = temp;
2875
2876 rc = of_property_read_u32(node, "qcom,cl-max-decrement", &temp);
2877 if (rc < 0)
2878 chip->dt.cl_max_cap_dec = DEFAULT_CL_MAX_DEC_DECIPERC;
2879 else
2880 chip->dt.cl_max_cap_dec = temp;
2881
2882 rc = of_property_read_u32(node, "qcom,cl-min-limit", &temp);
2883 if (rc < 0)
2884 chip->dt.cl_min_cap_limit = DEFAULT_CL_MIN_LIM_DECIPERC;
2885 else
2886 chip->dt.cl_min_cap_limit = temp;
2887
2888 rc = of_property_read_u32(node, "qcom,cl-max-limit", &temp);
2889 if (rc < 0)
2890 chip->dt.cl_max_cap_limit = DEFAULT_CL_MAX_LIM_DECIPERC;
2891 else
2892 chip->dt.cl_max_cap_limit = temp;
2893
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002894 rc = of_property_read_u32(node, "qcom,fg-jeita-hyst-temp", &temp);
2895 if (rc < 0)
2896 chip->dt.jeita_hyst_temp = -EINVAL;
2897 else
2898 chip->dt.jeita_hyst_temp = temp;
2899
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002900 rc = of_property_read_u32(node, "qcom,fg-batt-temp-delta", &temp);
2901 if (rc < 0)
2902 chip->dt.batt_temp_delta = -EINVAL;
2903 else if (temp > BTEMP_DELTA_LOW && temp <= BTEMP_DELTA_HIGH)
2904 chip->dt.batt_temp_delta = temp;
2905
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002906 chip->dt.hold_soc_while_full = of_property_read_bool(node,
2907 "qcom,hold-soc-while-full");
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002908
2909 rc = fg_parse_ki_coefficients(chip);
2910 if (rc < 0)
2911 pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
2912
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002913 return 0;
2914}
2915
2916static void fg_cleanup(struct fg_chip *chip)
2917{
2918 power_supply_unreg_notifier(&chip->nb);
Nicholas Troast69da2252016-09-07 16:17:47 -07002919 debugfs_remove_recursive(chip->dfs_root);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002920 if (chip->awake_votable)
2921 destroy_votable(chip->awake_votable);
2922
2923 if (chip->batt_id_chan)
2924 iio_channel_release(chip->batt_id_chan);
2925
2926 dev_set_drvdata(chip->dev, NULL);
2927}
2928
2929static int fg_gen3_probe(struct platform_device *pdev)
2930{
2931 struct fg_chip *chip;
2932 struct power_supply_config fg_psy_cfg;
2933 int rc;
2934
2935 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2936 if (!chip)
2937 return -ENOMEM;
2938
2939 chip->dev = &pdev->dev;
2940 chip->debug_mask = &fg_gen3_debug_mask;
2941 chip->irqs = fg_irqs;
2942 chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
2943 if (!chip->regmap) {
2944 dev_err(chip->dev, "Parent regmap is unavailable\n");
2945 return -ENXIO;
2946 }
2947
2948 rc = fg_parse_dt(chip);
2949 if (rc < 0) {
2950 dev_err(chip->dev, "Error in reading DT parameters, rc:%d\n",
2951 rc);
2952 return rc;
2953 }
2954
2955 chip->awake_votable = create_votable("FG_WS", VOTE_SET_ANY, fg_awake_cb,
2956 chip);
2957 if (IS_ERR(chip->awake_votable)) {
2958 rc = PTR_ERR(chip->awake_votable);
2959 return rc;
2960 }
2961
2962 mutex_init(&chip->bus_lock);
2963 mutex_init(&chip->sram_rw_lock);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002964 mutex_init(&chip->cyc_ctr.lock);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002965 mutex_init(&chip->cl.lock);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002966 init_completion(&chip->soc_update);
2967 init_completion(&chip->soc_ready);
2968 INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
2969 INIT_WORK(&chip->status_change_work, status_change_work);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002970 INIT_WORK(&chip->cycle_count_work, cycle_count_work);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002971
2972 rc = fg_memif_init(chip);
2973 if (rc < 0) {
2974 dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n",
2975 rc);
2976 goto exit;
2977 }
2978
2979 rc = fg_hw_init(chip);
2980 if (rc < 0) {
2981 dev_err(chip->dev, "Error in initializing FG hardware, rc:%d\n",
2982 rc);
2983 goto exit;
2984 }
2985
2986 platform_set_drvdata(pdev, chip);
2987
2988 /* Register the power supply */
2989 fg_psy_cfg.drv_data = chip;
2990 fg_psy_cfg.of_node = NULL;
2991 fg_psy_cfg.supplied_to = NULL;
2992 fg_psy_cfg.num_supplicants = 0;
2993 chip->fg_psy = devm_power_supply_register(chip->dev, &fg_psy_desc,
2994 &fg_psy_cfg);
2995 if (IS_ERR(chip->fg_psy)) {
2996 pr_err("failed to register fg_psy rc = %ld\n",
2997 PTR_ERR(chip->fg_psy));
2998 goto exit;
2999 }
3000
3001 chip->nb.notifier_call = fg_notifier_cb;
3002 rc = power_supply_reg_notifier(&chip->nb);
3003 if (rc < 0) {
3004 pr_err("Couldn't register psy notifier rc = %d\n", rc);
3005 goto exit;
3006 }
3007
3008 rc = fg_register_interrupts(chip);
3009 if (rc < 0) {
3010 dev_err(chip->dev, "Error in registering interrupts, rc:%d\n",
3011 rc);
3012 goto exit;
3013 }
3014
3015 /* Keep SOC_UPDATE irq disabled until we require it */
3016 if (fg_irqs[SOC_UPDATE_IRQ].irq)
3017 disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
3018
Nicholas Troast69da2252016-09-07 16:17:47 -07003019 rc = fg_debugfs_create(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003020 if (rc < 0) {
3021 dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n",
3022 rc);
3023 goto exit;
3024 }
3025
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07003026 if (chip->profile_available)
3027 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003028
3029 device_init_wakeup(chip->dev, true);
3030 pr_debug("FG GEN3 driver successfully probed\n");
3031 return 0;
3032exit:
3033 fg_cleanup(chip);
3034 return rc;
3035}
3036
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003037static int fg_gen3_suspend(struct device *dev)
3038{
3039 struct fg_chip *chip = dev_get_drvdata(dev);
3040 int rc;
3041
3042 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
3043 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_asleep, false,
3044 FG_IMA_NO_WLOCK);
3045 if (rc < 0) {
3046 pr_err("Error in setting ESR timer during suspend, rc=%d\n",
3047 rc);
3048 return rc;
3049 }
3050 }
3051
3052 return 0;
3053}
3054
3055static int fg_gen3_resume(struct device *dev)
3056{
3057 struct fg_chip *chip = dev_get_drvdata(dev);
3058 int rc;
3059
3060 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
3061 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
3062 FG_IMA_DEFAULT);
3063 if (rc < 0) {
3064 pr_err("Error in setting ESR timer during resume, rc=%d\n",
3065 rc);
3066 return rc;
3067 }
3068 }
3069
3070 return 0;
3071}
3072
3073static const struct dev_pm_ops fg_gen3_pm_ops = {
3074 .suspend = fg_gen3_suspend,
3075 .resume = fg_gen3_resume,
3076};
3077
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003078static int fg_gen3_remove(struct platform_device *pdev)
3079{
3080 struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
3081
3082 fg_cleanup(chip);
3083 return 0;
3084}
3085
3086static const struct of_device_id fg_gen3_match_table[] = {
3087 {.compatible = FG_GEN3_DEV_NAME},
3088 {},
3089};
3090
3091static struct platform_driver fg_gen3_driver = {
3092 .driver = {
3093 .name = FG_GEN3_DEV_NAME,
3094 .owner = THIS_MODULE,
3095 .of_match_table = fg_gen3_match_table,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003096 .pm = &fg_gen3_pm_ops,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003097 },
3098 .probe = fg_gen3_probe,
3099 .remove = fg_gen3_remove,
3100};
3101
3102static int __init fg_gen3_init(void)
3103{
3104 return platform_driver_register(&fg_gen3_driver);
3105}
3106
3107static void __exit fg_gen3_exit(void)
3108{
3109 return platform_driver_unregister(&fg_gen3_driver);
3110}
3111
3112module_init(fg_gen3_init);
3113module_exit(fg_gen3_exit);
3114
3115MODULE_DESCRIPTION("QPNP Fuel gauge GEN3 driver");
3116MODULE_LICENSE("GPL v2");
3117MODULE_ALIAS("platform:" FG_GEN3_DEV_NAME);