blob: fc34a8c992dccb5650a8420d3cff316389de802c [file] [log] [blame]
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "FG: %s: " fmt, __func__
14
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -080015#include <linux/ktime.h>
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070016#include <linux/of.h>
17#include <linux/of_irq.h>
18#include <linux/of_platform.h>
19#include <linux/of_batterydata.h>
20#include <linux/platform_device.h>
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070021#include <linux/iio/consumer.h>
22#include <linux/qpnp/qpnp-revid.h>
23#include "fg-core.h"
24#include "fg-reg.h"
25
26#define FG_GEN3_DEV_NAME "qcom,fg-gen3"
27
28#define PERPH_SUBTYPE_REG 0x05
Harry Yang2452b272017-03-06 13:56:14 -080029#define FG_BATT_SOC_PMI8998 0x10
30#define FG_BATT_INFO_PMI8998 0x11
31#define FG_MEM_INFO_PMI8998 0x0D
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070032
33/* SRAM address and offset in ascending order */
Subbaraman Narayanamurthye14037f2017-03-16 19:14:58 -070034#define ESR_PULSE_THRESH_WORD 2
35#define ESR_PULSE_THRESH_OFFSET 3
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -080036#define SLOPE_LIMIT_WORD 3
37#define SLOPE_LIMIT_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070038#define CUTOFF_VOLT_WORD 5
39#define CUTOFF_VOLT_OFFSET 0
40#define SYS_TERM_CURR_WORD 6
41#define SYS_TERM_CURR_OFFSET 0
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -070042#define VBATT_FULL_WORD 7
43#define VBATT_FULL_OFFSET 0
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -080044#define ESR_FILTER_WORD 8
45#define ESR_UPD_TIGHT_OFFSET 0
46#define ESR_UPD_BROAD_OFFSET 1
47#define ESR_UPD_TIGHT_LOW_TEMP_OFFSET 2
48#define ESR_UPD_BROAD_LOW_TEMP_OFFSET 3
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -070049#define KI_COEFF_MED_DISCHG_WORD 9
Anirudh Ghayalddabeee2017-04-04 06:13:48 +053050#define TIMEBASE_OFFSET 1
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -070051#define KI_COEFF_MED_DISCHG_OFFSET 3
52#define KI_COEFF_HI_DISCHG_WORD 10
53#define KI_COEFF_HI_DISCHG_OFFSET 0
54#define KI_COEFF_LOW_DISCHG_WORD 10
55#define KI_COEFF_LOW_DISCHG_OFFSET 2
Subbaraman Narayanamurthy1bf973e2017-04-04 19:24:20 -070056#define KI_COEFF_FULL_SOC_WORD 12
57#define KI_COEFF_FULL_SOC_OFFSET 2
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -080058#define DELTA_MSOC_THR_WORD 12
59#define DELTA_MSOC_THR_OFFSET 3
60#define DELTA_BSOC_THR_WORD 13
61#define DELTA_BSOC_THR_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070062#define RECHARGE_SOC_THR_WORD 14
63#define RECHARGE_SOC_THR_OFFSET 0
64#define CHG_TERM_CURR_WORD 14
65#define CHG_TERM_CURR_OFFSET 1
66#define EMPTY_VOLT_WORD 15
67#define EMPTY_VOLT_OFFSET 0
68#define VBATT_LOW_WORD 15
69#define VBATT_LOW_OFFSET 1
Nicholas Troastdcf8fe62016-08-04 14:30:02 -070070#define ESR_TIMER_DISCHG_MAX_WORD 17
71#define ESR_TIMER_DISCHG_MAX_OFFSET 0
72#define ESR_TIMER_DISCHG_INIT_WORD 17
73#define ESR_TIMER_DISCHG_INIT_OFFSET 2
74#define ESR_TIMER_CHG_MAX_WORD 18
75#define ESR_TIMER_CHG_MAX_OFFSET 0
76#define ESR_TIMER_CHG_INIT_WORD 18
77#define ESR_TIMER_CHG_INIT_OFFSET 2
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -070078#define ESR_EXTRACTION_ENABLE_WORD 19
79#define ESR_EXTRACTION_ENABLE_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070080#define PROFILE_LOAD_WORD 24
81#define PROFILE_LOAD_OFFSET 0
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -080082#define ESR_RSLOW_DISCHG_WORD 34
83#define ESR_RSLOW_DISCHG_OFFSET 0
84#define ESR_RSLOW_CHG_WORD 51
85#define ESR_RSLOW_CHG_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070086#define NOM_CAP_WORD 58
87#define NOM_CAP_OFFSET 0
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -070088#define ACT_BATT_CAP_BKUP_WORD 74
89#define ACT_BATT_CAP_BKUP_OFFSET 0
Nicholas Troaste29dec92016-08-24 09:35:11 -070090#define CYCLE_COUNT_WORD 75
91#define CYCLE_COUNT_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070092#define PROFILE_INTEGRITY_WORD 79
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -080093#define SW_CONFIG_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070094#define PROFILE_INTEGRITY_OFFSET 3
95#define BATT_SOC_WORD 91
96#define BATT_SOC_OFFSET 0
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -070097#define FULL_SOC_WORD 93
98#define FULL_SOC_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070099#define MONOTONIC_SOC_WORD 94
100#define MONOTONIC_SOC_OFFSET 2
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700101#define CC_SOC_WORD 95
102#define CC_SOC_OFFSET 0
103#define CC_SOC_SW_WORD 96
104#define CC_SOC_SW_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700105#define VOLTAGE_PRED_WORD 97
106#define VOLTAGE_PRED_OFFSET 0
107#define OCV_WORD 97
108#define OCV_OFFSET 2
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -0800109#define ESR_WORD 99
110#define ESR_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700111#define RSLOW_WORD 101
112#define RSLOW_OFFSET 0
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700113#define ACT_BATT_CAP_WORD 117
114#define ACT_BATT_CAP_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700115#define LAST_BATT_SOC_WORD 119
116#define LAST_BATT_SOC_OFFSET 0
117#define LAST_MONOTONIC_SOC_WORD 119
118#define LAST_MONOTONIC_SOC_OFFSET 2
Nicholas Troast69da2252016-09-07 16:17:47 -0700119#define ALG_FLAGS_WORD 120
120#define ALG_FLAGS_OFFSET 1
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700121
Nicholas Troasta2b40372016-08-15 10:45:39 -0700122/* v2 SRAM address and offset in ascending order */
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700123#define KI_COEFF_LOW_DISCHG_v2_WORD 9
124#define KI_COEFF_LOW_DISCHG_v2_OFFSET 3
125#define KI_COEFF_MED_DISCHG_v2_WORD 10
126#define KI_COEFF_MED_DISCHG_v2_OFFSET 0
127#define KI_COEFF_HI_DISCHG_v2_WORD 10
128#define KI_COEFF_HI_DISCHG_v2_OFFSET 1
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -0800129#define DELTA_BSOC_THR_v2_WORD 12
130#define DELTA_BSOC_THR_v2_OFFSET 3
131#define DELTA_MSOC_THR_v2_WORD 13
132#define DELTA_MSOC_THR_v2_OFFSET 0
Nicholas Troasta2b40372016-08-15 10:45:39 -0700133#define RECHARGE_SOC_THR_v2_WORD 14
134#define RECHARGE_SOC_THR_v2_OFFSET 1
135#define CHG_TERM_CURR_v2_WORD 15
Subbaraman Narayanamurthya4e18882017-04-04 20:28:03 -0700136#define CHG_TERM_BASE_CURR_v2_OFFSET 0
Nicholas Troasta2b40372016-08-15 10:45:39 -0700137#define CHG_TERM_CURR_v2_OFFSET 1
138#define EMPTY_VOLT_v2_WORD 15
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700139#define EMPTY_VOLT_v2_OFFSET 3
Nicholas Troasta2b40372016-08-15 10:45:39 -0700140#define VBATT_LOW_v2_WORD 16
141#define VBATT_LOW_v2_OFFSET 0
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -0800142#define RECHARGE_VBATT_THR_v2_WORD 16
143#define RECHARGE_VBATT_THR_v2_OFFSET 1
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700144#define FLOAT_VOLT_v2_WORD 16
145#define FLOAT_VOLT_v2_OFFSET 2
Nicholas Troasta2b40372016-08-15 10:45:39 -0700146
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700147static int fg_decode_voltage_15b(struct fg_sram_param *sp,
148 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700149static int fg_decode_value_16b(struct fg_sram_param *sp,
150 enum fg_sram_param_id id, int val);
151static int fg_decode_default(struct fg_sram_param *sp,
152 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700153static int fg_decode_cc_soc(struct fg_sram_param *sp,
154 enum fg_sram_param_id id, int value);
Nicholas Troasta2b40372016-08-15 10:45:39 -0700155static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700156 enum fg_sram_param_id id, int val_mv, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700157static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700158 enum fg_sram_param_id id, int val_ma, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700159static void fg_encode_default(struct fg_sram_param *sp,
160 enum fg_sram_param_id id, int val, u8 *buf);
161
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -0800162static struct fg_irq_info fg_irqs[FG_IRQ_MAX];
163
Nicholas Troasta2b40372016-08-15 10:45:39 -0700164#define PARAM(_id, _addr_word, _addr_byte, _len, _num, _den, _offset, \
165 _enc, _dec) \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700166 [FG_SRAM_##_id] = { \
Nicholas Troasta2b40372016-08-15 10:45:39 -0700167 .addr_word = _addr_word, \
168 .addr_byte = _addr_byte, \
169 .len = _len, \
170 .numrtr = _num, \
171 .denmtr = _den, \
172 .offset = _offset, \
173 .encode = _enc, \
174 .decode = _dec, \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700175 } \
176
Harry Yang2452b272017-03-06 13:56:14 -0800177static struct fg_sram_param pmi8998_v1_sram_params[] = {
Nicholas Troasta2b40372016-08-15 10:45:39 -0700178 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700179 fg_decode_default),
Nicholas Troast1769fd32016-09-07 09:20:58 -0700180 PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL,
181 fg_decode_default),
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800182 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 1000,
183 244141, 0, NULL, fg_decode_voltage_15b),
184 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 1000, 244141, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700185 fg_decode_voltage_15b),
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -0800186 PARAM(ESR, ESR_WORD, ESR_OFFSET, 2, 1000, 244141, 0, fg_encode_default,
187 fg_decode_value_16b),
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800188 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 1000, 244141, 0, NULL,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700189 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700190 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
191 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700192 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
193 fg_decode_cc_soc),
194 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
195 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700196 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
197 1, 1, 0, NULL, fg_decode_default),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700198 /* Entries below here are configurable during initialization */
199 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700200 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700201 PARAM(EMPTY_VOLT, EMPTY_VOLT_WORD, EMPTY_VOLT_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700202 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700203 PARAM(VBATT_LOW, VBATT_LOW_WORD, VBATT_LOW_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700204 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800205 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000,
206 244141, 0, fg_encode_voltage, fg_decode_voltage_15b),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700207 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700208 1000000, 122070, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700209 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700210 100000, 390625, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -0800211 PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_WORD, DELTA_MSOC_THR_OFFSET, 1,
212 2048, 100, 0, fg_encode_default, NULL),
213 PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_WORD, DELTA_BSOC_THR_OFFSET, 1,
214 2048, 100, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700215 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_WORD, RECHARGE_SOC_THR_OFFSET,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700216 1, 256, 100, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700217 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700218 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
219 NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700220 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700221 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700222 NULL),
223 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700224 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700225 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700226 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthye14037f2017-03-16 19:14:58 -0700227 PARAM(ESR_PULSE_THRESH, ESR_PULSE_THRESH_WORD, ESR_PULSE_THRESH_OFFSET,
228 1, 100000, 390625, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700229 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD,
230 KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 244141, 0,
231 fg_encode_default, NULL),
232 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD,
233 KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 244141, 0,
234 fg_encode_default, NULL),
Subbaraman Narayanamurthy1bf973e2017-04-04 19:24:20 -0700235 PARAM(KI_COEFF_FULL_SOC, KI_COEFF_FULL_SOC_WORD,
236 KI_COEFF_FULL_SOC_OFFSET, 1, 1000, 244141, 0,
237 fg_encode_default, NULL),
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -0800238 PARAM(ESR_TIGHT_FILTER, ESR_FILTER_WORD, ESR_UPD_TIGHT_OFFSET,
239 1, 512, 1000000, 0, fg_encode_default, NULL),
240 PARAM(ESR_BROAD_FILTER, ESR_FILTER_WORD, ESR_UPD_BROAD_OFFSET,
241 1, 512, 1000000, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -0800242 PARAM(SLOPE_LIMIT, SLOPE_LIMIT_WORD, SLOPE_LIMIT_OFFSET, 1, 8192, 1000,
243 0, fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700244};
245
Harry Yang2452b272017-03-06 13:56:14 -0800246static struct fg_sram_param pmi8998_v2_sram_params[] = {
Nicholas Troasta2b40372016-08-15 10:45:39 -0700247 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700248 fg_decode_default),
Nicholas Troast1769fd32016-09-07 09:20:58 -0700249 PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL,
250 fg_decode_default),
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800251 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 1000,
252 244141, 0, NULL, fg_decode_voltage_15b),
253 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 1000, 244141, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700254 fg_decode_voltage_15b),
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -0800255 PARAM(ESR, ESR_WORD, ESR_OFFSET, 2, 1000, 244141, 0, fg_encode_default,
256 fg_decode_value_16b),
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800257 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 1000, 244141, 0, NULL,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700258 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700259 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
260 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700261 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
262 fg_decode_cc_soc),
263 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
264 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700265 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
266 1, 1, 0, NULL, fg_decode_default),
Anirudh Ghayalddabeee2017-04-04 06:13:48 +0530267 PARAM(TIMEBASE, KI_COEFF_MED_DISCHG_WORD, TIMEBASE_OFFSET, 2, 1000,
268 61000, 0, fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700269 /* Entries below here are configurable during initialization */
270 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
271 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700272 PARAM(EMPTY_VOLT, EMPTY_VOLT_v2_WORD, EMPTY_VOLT_v2_OFFSET, 1, 1000,
273 15625, -2000, fg_encode_voltage, NULL),
274 PARAM(VBATT_LOW, VBATT_LOW_v2_WORD, VBATT_LOW_v2_OFFSET, 1, 1000,
275 15625, -2000, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700276 PARAM(FLOAT_VOLT, FLOAT_VOLT_v2_WORD, FLOAT_VOLT_v2_OFFSET, 1, 1000,
277 15625, -2000, fg_encode_voltage, NULL),
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800278 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000,
279 244141, 0, fg_encode_voltage, fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700280 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
281 1000000, 122070, 0, fg_encode_current, NULL),
282 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_v2_WORD, CHG_TERM_CURR_v2_OFFSET, 1,
283 100000, 390625, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthya4e18882017-04-04 20:28:03 -0700284 PARAM(CHG_TERM_BASE_CURR, CHG_TERM_CURR_v2_WORD,
285 CHG_TERM_BASE_CURR_v2_OFFSET, 1, 1024, 1000, 0,
286 fg_encode_current, NULL),
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -0800287 PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_v2_WORD, DELTA_MSOC_THR_v2_OFFSET,
288 1, 2048, 100, 0, fg_encode_default, NULL),
289 PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_v2_WORD, DELTA_BSOC_THR_v2_OFFSET,
290 1, 2048, 100, 0, fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700291 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD,
292 RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default,
293 NULL),
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -0800294 PARAM(RECHARGE_VBATT_THR, RECHARGE_VBATT_THR_v2_WORD,
295 RECHARGE_VBATT_THR_v2_OFFSET, 1, 1000, 15625, -2000,
296 fg_encode_voltage, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700297 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
298 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
299 NULL),
300 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
301 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
302 NULL),
303 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
304 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
305 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
306 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthye14037f2017-03-16 19:14:58 -0700307 PARAM(ESR_PULSE_THRESH, ESR_PULSE_THRESH_WORD, ESR_PULSE_THRESH_OFFSET,
308 1, 100000, 390625, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700309 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_v2_WORD,
310 KI_COEFF_MED_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
311 fg_encode_default, NULL),
312 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_v2_WORD,
313 KI_COEFF_HI_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
314 fg_encode_default, NULL),
Subbaraman Narayanamurthy1bf973e2017-04-04 19:24:20 -0700315 PARAM(KI_COEFF_FULL_SOC, KI_COEFF_FULL_SOC_WORD,
316 KI_COEFF_FULL_SOC_OFFSET, 1, 1000, 244141, 0,
317 fg_encode_default, NULL),
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -0800318 PARAM(ESR_TIGHT_FILTER, ESR_FILTER_WORD, ESR_UPD_TIGHT_OFFSET,
319 1, 512, 1000000, 0, fg_encode_default, NULL),
320 PARAM(ESR_BROAD_FILTER, ESR_FILTER_WORD, ESR_UPD_BROAD_OFFSET,
321 1, 512, 1000000, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -0800322 PARAM(SLOPE_LIMIT, SLOPE_LIMIT_WORD, SLOPE_LIMIT_OFFSET, 1, 8192, 1000,
323 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700324};
325
Harry Yang2452b272017-03-06 13:56:14 -0800326static struct fg_alg_flag pmi8998_v1_alg_flags[] = {
Nicholas Troast69da2252016-09-07 16:17:47 -0700327 [ALG_FLAG_SOC_LT_OTG_MIN] = {
328 .name = "SOC_LT_OTG_MIN",
329 .bit = BIT(0),
330 },
331 [ALG_FLAG_SOC_LT_RECHARGE] = {
332 .name = "SOC_LT_RECHARGE",
333 .bit = BIT(1),
334 },
335 [ALG_FLAG_IBATT_LT_ITERM] = {
336 .name = "IBATT_LT_ITERM",
337 .bit = BIT(2),
338 },
339 [ALG_FLAG_IBATT_GT_HPM] = {
340 .name = "IBATT_GT_HPM",
341 .bit = BIT(3),
342 },
343 [ALG_FLAG_IBATT_GT_UPM] = {
344 .name = "IBATT_GT_UPM",
345 .bit = BIT(4),
346 },
347 [ALG_FLAG_VBATT_LT_RECHARGE] = {
348 .name = "VBATT_LT_RECHARGE",
349 .bit = BIT(5),
350 },
351 [ALG_FLAG_VBATT_GT_VFLOAT] = {
352 .invalid = true,
353 },
354};
355
Harry Yang2452b272017-03-06 13:56:14 -0800356static struct fg_alg_flag pmi8998_v2_alg_flags[] = {
Nicholas Troast69da2252016-09-07 16:17:47 -0700357 [ALG_FLAG_SOC_LT_OTG_MIN] = {
358 .name = "SOC_LT_OTG_MIN",
359 .bit = BIT(0),
360 },
361 [ALG_FLAG_SOC_LT_RECHARGE] = {
362 .name = "SOC_LT_RECHARGE",
363 .bit = BIT(1),
364 },
365 [ALG_FLAG_IBATT_LT_ITERM] = {
366 .name = "IBATT_LT_ITERM",
367 .bit = BIT(2),
368 },
369 [ALG_FLAG_IBATT_GT_HPM] = {
370 .name = "IBATT_GT_HPM",
371 .bit = BIT(4),
372 },
373 [ALG_FLAG_IBATT_GT_UPM] = {
374 .name = "IBATT_GT_UPM",
375 .bit = BIT(5),
376 },
377 [ALG_FLAG_VBATT_LT_RECHARGE] = {
378 .name = "VBATT_LT_RECHARGE",
379 .bit = BIT(6),
380 },
381 [ALG_FLAG_VBATT_GT_VFLOAT] = {
382 .name = "VBATT_GT_VFLOAT",
383 .bit = BIT(7),
384 },
385};
386
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700387static int fg_gen3_debug_mask;
388module_param_named(
389 debug_mask, fg_gen3_debug_mask, int, 0600
390);
391
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800392static bool fg_profile_dump;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700393module_param_named(
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800394 profile_dump, fg_profile_dump, bool, 0600
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700395);
396
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800397static int fg_sram_dump_period_ms = 20000;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700398module_param_named(
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800399 sram_dump_period_ms, fg_sram_dump_period_ms, int, 0600
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700400);
401
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -0700402static int fg_restart;
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -0800403static bool fg_sram_dump;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700404
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700405/* All getters HERE */
406
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700407#define VOLTAGE_15BIT_MASK GENMASK(14, 0)
408static int fg_decode_voltage_15b(struct fg_sram_param *sp,
409 enum fg_sram_param_id id, int value)
410{
411 value &= VOLTAGE_15BIT_MASK;
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800412 sp[id].value = div_u64((u64)value * sp[id].denmtr, sp[id].numrtr);
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700413 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
414 sp[id].value);
415 return sp[id].value;
416}
417
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700418static int fg_decode_cc_soc(struct fg_sram_param *sp,
419 enum fg_sram_param_id id, int value)
420{
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800421 sp[id].value = div_s64((s64)value * sp[id].denmtr, sp[id].numrtr);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700422 sp[id].value = sign_extend32(sp[id].value, 31);
423 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
424 sp[id].value);
425 return sp[id].value;
426}
427
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700428static int fg_decode_value_16b(struct fg_sram_param *sp,
429 enum fg_sram_param_id id, int value)
430{
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -0800431 sp[id].value = div_u64((u64)(u16)value * sp[id].denmtr, sp[id].numrtr);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700432 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
433 sp[id].value);
434 return sp[id].value;
435}
436
Nicholas Troaste29dec92016-08-24 09:35:11 -0700437static int fg_decode_default(struct fg_sram_param *sp, enum fg_sram_param_id id,
438 int value)
439{
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700440 sp[id].value = value;
441 return sp[id].value;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700442}
443
444static int fg_decode(struct fg_sram_param *sp, enum fg_sram_param_id id,
445 int value)
446{
447 if (!sp[id].decode) {
448 pr_err("No decoding function for parameter %d\n", id);
449 return -EINVAL;
450 }
451
452 return sp[id].decode(sp, id, value);
453}
454
Nicholas Troasta2b40372016-08-15 10:45:39 -0700455static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700456 enum fg_sram_param_id id, int val_mv, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700457{
458 int i, mask = 0xff;
459 int64_t temp;
460
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700461 val_mv += sp[id].offset;
462 temp = (int64_t)div_u64((u64)val_mv * sp[id].numrtr, sp[id].denmtr);
463 pr_debug("temp: %llx id: %d, val_mv: %d, buf: [ ", temp, id, val_mv);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700464 for (i = 0; i < sp[id].len; i++) {
465 buf[i] = temp & mask;
466 temp >>= 8;
467 pr_debug("%x ", buf[i]);
468 }
469 pr_debug("]\n");
470}
471
472static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700473 enum fg_sram_param_id id, int val_ma, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700474{
475 int i, mask = 0xff;
476 int64_t temp;
477 s64 current_ma;
478
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700479 current_ma = val_ma;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700480 temp = (int64_t)div_s64(current_ma * sp[id].numrtr, sp[id].denmtr);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700481 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val_ma);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700482 for (i = 0; i < sp[id].len; i++) {
483 buf[i] = temp & mask;
484 temp >>= 8;
485 pr_debug("%x ", buf[i]);
486 }
487 pr_debug("]\n");
488}
489
490static void fg_encode_default(struct fg_sram_param *sp,
491 enum fg_sram_param_id id, int val, u8 *buf)
492{
493 int i, mask = 0xff;
494 int64_t temp;
495
Subbaraman Narayanamurthy3cf60ee2017-06-02 11:38:58 -0700496 temp = (int64_t)div_s64((s64)val * sp[id].numrtr, sp[id].denmtr);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700497 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val);
498 for (i = 0; i < sp[id].len; i++) {
499 buf[i] = temp & mask;
500 temp >>= 8;
501 pr_debug("%x ", buf[i]);
502 }
503 pr_debug("]\n");
504}
505
506static void fg_encode(struct fg_sram_param *sp, enum fg_sram_param_id id,
507 int val, u8 *buf)
508{
509 if (!sp[id].encode) {
510 pr_err("No encoding function for parameter %d\n", id);
511 return;
512 }
513
514 sp[id].encode(sp, id, val, buf);
515}
516
517/*
518 * Please make sure *_sram_params table has the entry for the parameter
519 * obtained through this function. In addition to address, offset,
520 * length from where this SRAM parameter is read, a decode function
521 * need to be specified.
522 */
523static int fg_get_sram_prop(struct fg_chip *chip, enum fg_sram_param_id id,
524 int *val)
525{
526 int temp, rc, i;
527 u8 buf[4];
528
529 if (id < 0 || id > FG_SRAM_MAX || chip->sp[id].len > sizeof(buf))
530 return -EINVAL;
531
Subbaraman Narayanamurthy0a749db2016-10-03 18:33:19 -0700532 if (chip->battery_missing)
533 return -ENODATA;
534
Nicholas Troasta2b40372016-08-15 10:45:39 -0700535 rc = fg_sram_read(chip, chip->sp[id].addr_word, chip->sp[id].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700536 buf, chip->sp[id].len, FG_IMA_DEFAULT);
537 if (rc < 0) {
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -0700538 pr_err("Error reading address %d[%d] rc=%d\n",
Nicholas Troasta2b40372016-08-15 10:45:39 -0700539 chip->sp[id].addr_word, chip->sp[id].addr_byte, rc);
Nicholas Troastb2d71742016-08-04 14:31:41 -0700540 return rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700541 }
542
543 for (i = 0, temp = 0; i < chip->sp[id].len; i++)
544 temp |= buf[i] << (8 * i);
545
546 *val = fg_decode(chip->sp, id, temp);
547 return 0;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700548}
549
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700550#define CC_SOC_30BIT GENMASK(29, 0)
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -0700551static int fg_get_charge_raw(struct fg_chip *chip, int *val)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700552{
553 int rc, cc_soc;
554
555 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC, &cc_soc);
556 if (rc < 0) {
557 pr_err("Error in getting CC_SOC, rc=%d\n", rc);
558 return rc;
559 }
560
561 *val = div_s64(cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
562 return 0;
563}
564
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -0700565static int fg_get_charge_counter(struct fg_chip *chip, int *val)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700566{
567 int rc, cc_soc;
568
569 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc);
570 if (rc < 0) {
571 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
572 return rc;
573 }
574
575 *val = div_s64(cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
576 return 0;
577}
578
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -0700579static int fg_get_jeita_threshold(struct fg_chip *chip,
580 enum jeita_levels level, int *temp_decidegC)
581{
582 int rc;
583 u8 val;
584 u16 reg;
585
586 switch (level) {
587 case JEITA_COLD:
588 reg = BATT_INFO_JEITA_TOO_COLD(chip);
589 break;
590 case JEITA_COOL:
591 reg = BATT_INFO_JEITA_COLD(chip);
592 break;
593 case JEITA_WARM:
594 reg = BATT_INFO_JEITA_HOT(chip);
595 break;
596 case JEITA_HOT:
597 reg = BATT_INFO_JEITA_TOO_HOT(chip);
598 break;
599 default:
600 return -EINVAL;
601 }
602
603 rc = fg_read(chip, reg, &val, 1);
604 if (rc < 0) {
605 pr_err("Error in reading jeita level %d, rc=%d\n", level, rc);
606 return rc;
607 }
608
609 /* Resolution is 0.5C. Base is -30C. */
610 *temp_decidegC = (((5 * val) / 10) - 30) * 10;
611 return 0;
612}
613
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700614#define BATT_TEMP_NUMR 1
615#define BATT_TEMP_DENR 1
616static int fg_get_battery_temp(struct fg_chip *chip, int *val)
617{
Subbaraman Narayanamurthyfabbb8e2016-10-21 16:55:09 -0700618 int rc = 0, temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700619 u8 buf[2];
620
621 rc = fg_read(chip, BATT_INFO_BATT_TEMP_LSB(chip), buf, 2);
622 if (rc < 0) {
623 pr_err("failed to read addr=0x%04x, rc=%d\n",
624 BATT_INFO_BATT_TEMP_LSB(chip), rc);
625 return rc;
626 }
627
628 temp = ((buf[1] & BATT_TEMP_MSB_MASK) << 8) |
629 (buf[0] & BATT_TEMP_LSB_MASK);
630 temp = DIV_ROUND_CLOSEST(temp, 4);
631
632 /* Value is in Kelvin; Convert it to deciDegC */
633 temp = (temp - 273) * 10;
634 *val = temp;
635 return 0;
636}
637
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700638static int fg_get_battery_resistance(struct fg_chip *chip, int *val)
639{
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -0800640 int rc, esr_uohms, rslow_uohms;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700641
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -0800642 rc = fg_get_sram_prop(chip, FG_SRAM_ESR, &esr_uohms);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700643 if (rc < 0) {
644 pr_err("failed to get ESR, rc=%d\n", rc);
645 return rc;
646 }
647
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -0800648 rc = fg_get_sram_prop(chip, FG_SRAM_RSLOW, &rslow_uohms);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700649 if (rc < 0) {
650 pr_err("failed to get Rslow, rc=%d\n", rc);
651 return rc;
652 }
653
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -0800654 *val = esr_uohms + rslow_uohms;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700655 return 0;
656}
657
658#define BATT_CURRENT_NUMR 488281
659#define BATT_CURRENT_DENR 1000
660static int fg_get_battery_current(struct fg_chip *chip, int *val)
661{
662 int rc = 0;
663 int64_t temp = 0;
664 u8 buf[2];
665
666 rc = fg_read(chip, BATT_INFO_IBATT_LSB(chip), buf, 2);
667 if (rc < 0) {
668 pr_err("failed to read addr=0x%04x, rc=%d\n",
669 BATT_INFO_IBATT_LSB(chip), rc);
670 return rc;
671 }
672
Ashay Jaiswal63d486e2016-12-07 11:21:32 +0530673 if (chip->wa_flags & PMI8998_V1_REV_WA)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700674 temp = buf[0] << 8 | buf[1];
675 else
676 temp = buf[1] << 8 | buf[0];
677
678 pr_debug("buf: %x %x temp: %llx\n", buf[0], buf[1], temp);
679 /* Sign bit is bit 15 */
680 temp = twos_compliment_extend(temp, 15);
681 *val = div_s64((s64)temp * BATT_CURRENT_NUMR, BATT_CURRENT_DENR);
682 return 0;
683}
684
685#define BATT_VOLTAGE_NUMR 122070
686#define BATT_VOLTAGE_DENR 1000
687static int fg_get_battery_voltage(struct fg_chip *chip, int *val)
688{
689 int rc = 0;
690 u16 temp = 0;
691 u8 buf[2];
692
693 rc = fg_read(chip, BATT_INFO_VBATT_LSB(chip), buf, 2);
694 if (rc < 0) {
695 pr_err("failed to read addr=0x%04x, rc=%d\n",
696 BATT_INFO_VBATT_LSB(chip), rc);
697 return rc;
698 }
699
Ashay Jaiswal63d486e2016-12-07 11:21:32 +0530700 if (chip->wa_flags & PMI8998_V1_REV_WA)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700701 temp = buf[0] << 8 | buf[1];
702 else
703 temp = buf[1] << 8 | buf[0];
704
705 pr_debug("buf: %x %x temp: %x\n", buf[0], buf[1], temp);
706 *val = div_u64((u64)temp * BATT_VOLTAGE_NUMR, BATT_VOLTAGE_DENR);
707 return 0;
708}
709
710#define MAX_TRIES_SOC 5
711static int fg_get_msoc_raw(struct fg_chip *chip, int *val)
712{
713 u8 cap[2];
714 int rc, tries = 0;
715
716 while (tries < MAX_TRIES_SOC) {
717 rc = fg_read(chip, BATT_SOC_FG_MONOTONIC_SOC(chip), cap, 2);
718 if (rc < 0) {
719 pr_err("failed to read addr=0x%04x, rc=%d\n",
720 BATT_SOC_FG_MONOTONIC_SOC(chip), rc);
721 return rc;
722 }
723
724 if (cap[0] == cap[1])
725 break;
726
727 tries++;
728 }
729
730 if (tries == MAX_TRIES_SOC) {
731 pr_err("shadow registers do not match\n");
732 return -EINVAL;
733 }
734
735 fg_dbg(chip, FG_POWER_SUPPLY, "raw: 0x%02x\n", cap[0]);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700736 *val = cap[0];
737 return 0;
738}
739
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -0800740#define FULL_CAPACITY 100
741#define FULL_SOC_RAW 255
742static int fg_get_msoc(struct fg_chip *chip, int *msoc)
743{
744 int rc;
745
746 rc = fg_get_msoc_raw(chip, msoc);
747 if (rc < 0)
748 return rc;
749
750 *msoc = DIV_ROUND_CLOSEST(*msoc * FULL_CAPACITY, FULL_SOC_RAW);
751 return 0;
752}
753
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800754static bool is_batt_empty(struct fg_chip *chip)
755{
756 u8 status;
757 int rc, vbatt_uv, msoc;
758
759 rc = fg_read(chip, BATT_SOC_INT_RT_STS(chip), &status, 1);
760 if (rc < 0) {
761 pr_err("failed to read addr=0x%04x, rc=%d\n",
762 BATT_SOC_INT_RT_STS(chip), rc);
763 return false;
764 }
765
766 if (!(status & MSOC_EMPTY_BIT))
767 return false;
768
769 rc = fg_get_battery_voltage(chip, &vbatt_uv);
770 if (rc < 0) {
771 pr_err("failed to get battery voltage, rc=%d\n", rc);
772 return false;
773 }
774
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -0800775 rc = fg_get_msoc(chip, &msoc);
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800776 if (!rc)
777 pr_warn("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", status,
778 vbatt_uv, msoc);
779
780 return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false);
781}
782
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800783static int fg_get_debug_batt_id(struct fg_chip *chip, int *batt_id)
784{
785 int rc;
786 u64 temp;
787 u8 buf[2];
788
789 rc = fg_read(chip, ADC_RR_FAKE_BATT_LOW_LSB(chip), buf, 2);
790 if (rc < 0) {
791 pr_err("failed to read addr=0x%04x, rc=%d\n",
792 ADC_RR_FAKE_BATT_LOW_LSB(chip), rc);
793 return rc;
794 }
795
796 /*
797 * Fake battery threshold is encoded in the following format.
798 * Threshold (code) = (battery_id in Ohms) * 0.00015 * 2^10 / 2.5
799 */
800 temp = (buf[1] << 8 | buf[0]) * 2500000;
801 do_div(temp, 150 * 1024);
802 batt_id[0] = temp;
803 rc = fg_read(chip, ADC_RR_FAKE_BATT_HIGH_LSB(chip), buf, 2);
804 if (rc < 0) {
805 pr_err("failed to read addr=0x%04x, rc=%d\n",
806 ADC_RR_FAKE_BATT_HIGH_LSB(chip), rc);
807 return rc;
808 }
809
810 temp = (buf[1] << 8 | buf[0]) * 2500000;
811 do_div(temp, 150 * 1024);
812 batt_id[1] = temp;
813 pr_debug("debug batt_id range: [%d %d]\n", batt_id[0], batt_id[1]);
814 return 0;
815}
816
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700817static bool is_debug_batt_id(struct fg_chip *chip)
818{
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800819 int debug_batt_id[2], rc;
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700820
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800821 if (!chip->batt_id_ohms)
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700822 return false;
823
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -0800824 rc = fg_get_debug_batt_id(chip, debug_batt_id);
825 if (rc < 0) {
826 pr_err("Failed to get debug batt_id, rc=%d\n", rc);
827 return false;
828 }
829
830 if (is_between(debug_batt_id[0], debug_batt_id[1],
831 chip->batt_id_ohms)) {
832 fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dohms\n",
833 chip->batt_id_ohms);
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700834 return true;
835 }
836
837 return false;
838}
839
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700840#define DEBUG_BATT_SOC 67
Subbaraman Narayanamurthye55a6aa2017-01-24 18:45:14 -0800841#define BATT_MISS_SOC 50
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700842#define EMPTY_SOC 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700843static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
844{
845 int rc, msoc;
846
Subbaraman Narayanamurthy2d65d5b2016-11-03 12:02:52 -0700847 if (is_debug_batt_id(chip)) {
848 *val = DEBUG_BATT_SOC;
849 return 0;
850 }
851
Subbaraman Narayanamurthye55a6aa2017-01-24 18:45:14 -0800852 if (chip->fg_restarting) {
853 *val = chip->last_soc;
854 return 0;
855 }
856
857 if (chip->battery_missing) {
858 *val = BATT_MISS_SOC;
859 return 0;
860 }
861
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800862 if (is_batt_empty(chip)) {
Subbaraman Narayanamurthyc7b33322016-11-01 16:29:46 -0700863 *val = EMPTY_SOC;
864 return 0;
865 }
866
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700867 if (chip->charge_full) {
868 *val = FULL_CAPACITY;
869 return 0;
870 }
871
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -0800872 rc = fg_get_msoc(chip, &msoc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700873 if (rc < 0)
874 return rc;
875
Subbaraman Narayanamurthy50fb7fd2017-07-25 20:01:25 -0700876 if (chip->dt.linearize_soc && chip->delta_soc > 0)
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -0800877 *val = chip->maint_soc;
878 else
879 *val = msoc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700880 return 0;
881}
882
883#define DEFAULT_BATT_TYPE "Unknown Battery"
884#define MISSING_BATT_TYPE "Missing Battery"
885#define LOADING_BATT_TYPE "Loading Battery"
886static const char *fg_get_battery_type(struct fg_chip *chip)
887{
888 if (chip->battery_missing)
889 return MISSING_BATT_TYPE;
890
891 if (chip->bp.batt_type_str) {
892 if (chip->profile_loaded)
893 return chip->bp.batt_type_str;
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -0800894 else if (chip->profile_available)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700895 return LOADING_BATT_TYPE;
896 }
897
898 return DEFAULT_BATT_TYPE;
899}
900
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800901static int fg_batt_missing_config(struct fg_chip *chip, bool enable)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700902{
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800903 int rc;
904
905 rc = fg_masked_write(chip, BATT_INFO_BATT_MISS_CFG(chip),
906 BM_FROM_BATT_ID_BIT, enable ? BM_FROM_BATT_ID_BIT : 0);
907 if (rc < 0)
908 pr_err("Error in writing to %04x, rc=%d\n",
909 BATT_INFO_BATT_MISS_CFG(chip), rc);
910 return rc;
911}
912
913static int fg_get_batt_id(struct fg_chip *chip)
914{
915 int rc, ret, batt_id = 0;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700916
917 if (!chip->batt_id_chan)
918 return -EINVAL;
919
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800920 rc = fg_batt_missing_config(chip, false);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700921 if (rc < 0) {
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800922 pr_err("Error in disabling BMD, rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700923 return rc;
924 }
925
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800926 rc = iio_read_channel_processed(chip->batt_id_chan, &batt_id);
927 if (rc < 0) {
928 pr_err("Error in reading batt_id channel, rc:%d\n", rc);
929 goto out;
930 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700931
Fenglin Wud10ccf12017-08-10 15:43:41 +0800932 /* Wait for BATT_ID to settle down before enabling BMD again */
933 msleep(chip->dt.bmd_en_delay_ms);
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800934
935 fg_dbg(chip, FG_STATUS, "batt_id: %d\n", batt_id);
936 chip->batt_id_ohms = batt_id;
937out:
938 ret = fg_batt_missing_config(chip, true);
939 if (ret < 0) {
940 pr_err("Error in enabling BMD, ret=%d\n", ret);
941 return ret;
942 }
943
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -0700944 vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, true, 0);
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800945 return rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700946}
947
948static int fg_get_batt_profile(struct fg_chip *chip)
949{
950 struct device_node *node = chip->dev->of_node;
951 struct device_node *batt_node, *profile_node;
952 const char *data;
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800953 int rc, len;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700954
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700955 batt_node = of_find_node_by_name(node, "qcom,battery-data");
956 if (!batt_node) {
957 pr_err("Batterydata not available\n");
958 return -ENXIO;
959 }
960
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -0800961 profile_node = of_batterydata_get_best_profile(batt_node,
962 chip->batt_id_ohms / 1000, NULL);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700963 if (IS_ERR(profile_node))
964 return PTR_ERR(profile_node);
965
966 if (!profile_node) {
967 pr_err("couldn't find profile handle\n");
968 return -ENODATA;
969 }
970
971 rc = of_property_read_string(profile_node, "qcom,battery-type",
972 &chip->bp.batt_type_str);
973 if (rc < 0) {
974 pr_err("battery type unavailable, rc:%d\n", rc);
975 return rc;
976 }
977
978 rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv",
979 &chip->bp.float_volt_uv);
980 if (rc < 0) {
981 pr_err("battery float voltage unavailable, rc:%d\n", rc);
982 chip->bp.float_volt_uv = -EINVAL;
983 }
984
Subbaraman Narayanamurthy5f653bb2016-12-09 15:24:12 -0800985 rc = of_property_read_u32(profile_node, "qcom,fastchg-current-ma",
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700986 &chip->bp.fastchg_curr_ma);
987 if (rc < 0) {
Subbaraman Narayanamurthy5f653bb2016-12-09 15:24:12 -0800988 pr_err("battery fastchg current unavailable, rc:%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700989 chip->bp.fastchg_curr_ma = -EINVAL;
990 }
991
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700992 rc = of_property_read_u32(profile_node, "qcom,fg-cc-cv-threshold-mv",
993 &chip->bp.vbatt_full_mv);
994 if (rc < 0) {
995 pr_err("battery cc_cv threshold unavailable, rc:%d\n", rc);
996 chip->bp.vbatt_full_mv = -EINVAL;
997 }
998
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700999 data = of_get_property(profile_node, "qcom,fg-profile-data", &len);
1000 if (!data) {
1001 pr_err("No profile data available\n");
1002 return -ENODATA;
1003 }
1004
1005 if (len != PROFILE_LEN) {
1006 pr_err("battery profile incorrect size: %d\n", len);
1007 return -EINVAL;
1008 }
1009
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07001010 chip->profile_available = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001011 memcpy(chip->batt_profile, data, len);
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -08001012
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001013 return 0;
1014}
1015
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07001016static inline void get_batt_temp_delta(int delta, u8 *val)
1017{
1018 switch (delta) {
1019 case 2:
1020 *val = BTEMP_DELTA_2K;
1021 break;
1022 case 4:
1023 *val = BTEMP_DELTA_4K;
1024 break;
1025 case 6:
1026 *val = BTEMP_DELTA_6K;
1027 break;
1028 case 10:
1029 *val = BTEMP_DELTA_10K;
1030 break;
1031 default:
1032 *val = BTEMP_DELTA_2K;
1033 break;
1034 };
1035}
1036
Subbaraman Narayanamurthye14037f2017-03-16 19:14:58 -07001037static inline void get_esr_meas_current(int curr_ma, u8 *val)
1038{
1039 switch (curr_ma) {
1040 case 60:
1041 *val = ESR_MEAS_CUR_60MA;
1042 break;
1043 case 120:
1044 *val = ESR_MEAS_CUR_120MA;
1045 break;
1046 case 180:
1047 *val = ESR_MEAS_CUR_180MA;
1048 break;
1049 case 240:
1050 *val = ESR_MEAS_CUR_240MA;
1051 break;
1052 default:
1053 *val = ESR_MEAS_CUR_120MA;
1054 break;
1055 };
1056
1057 *val <<= ESR_PULL_DOWN_IVAL_SHIFT;
1058}
1059
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07001060static int fg_set_esr_timer(struct fg_chip *chip, int cycles_init,
1061 int cycles_max, bool charging, int flags)
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07001062{
1063 u8 buf[2];
1064 int rc, timer_max, timer_init;
1065
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07001066 if (cycles_init < 0 || cycles_max < 0)
1067 return 0;
1068
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07001069 if (charging) {
1070 timer_max = FG_SRAM_ESR_TIMER_CHG_MAX;
1071 timer_init = FG_SRAM_ESR_TIMER_CHG_INIT;
1072 } else {
1073 timer_max = FG_SRAM_ESR_TIMER_DISCHG_MAX;
1074 timer_init = FG_SRAM_ESR_TIMER_DISCHG_INIT;
1075 }
1076
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07001077 fg_encode(chip->sp, timer_max, cycles_max, buf);
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07001078 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -07001079 chip->sp[timer_max].addr_word,
1080 chip->sp[timer_max].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07001081 chip->sp[timer_max].len, flags);
1082 if (rc < 0) {
1083 pr_err("Error in writing esr_timer_dischg_max, rc=%d\n",
1084 rc);
1085 return rc;
1086 }
1087
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07001088 fg_encode(chip->sp, timer_init, cycles_init, buf);
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07001089 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -07001090 chip->sp[timer_init].addr_word,
1091 chip->sp[timer_init].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07001092 chip->sp[timer_init].len, flags);
1093 if (rc < 0) {
1094 pr_err("Error in writing esr_timer_dischg_init, rc=%d\n",
1095 rc);
1096 return rc;
1097 }
1098
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07001099 fg_dbg(chip, FG_STATUS, "esr_%s_timer set to %d/%d\n",
1100 charging ? "charging" : "discharging", cycles_init, cycles_max);
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07001101 return 0;
1102}
1103
Nicholas Troaste29dec92016-08-24 09:35:11 -07001104/* Other functions HERE */
1105
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001106static void fg_notify_charger(struct fg_chip *chip)
1107{
1108 union power_supply_propval prop = {0, };
1109 int rc;
1110
1111 if (!chip->batt_psy)
1112 return;
1113
1114 if (!chip->profile_available)
1115 return;
1116
1117 prop.intval = chip->bp.float_volt_uv;
1118 rc = power_supply_set_property(chip->batt_psy,
1119 POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
1120 if (rc < 0) {
1121 pr_err("Error in setting voltage_max property on batt_psy, rc=%d\n",
1122 rc);
1123 return;
1124 }
1125
1126 prop.intval = chip->bp.fastchg_curr_ma * 1000;
1127 rc = power_supply_set_property(chip->batt_psy,
1128 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &prop);
1129 if (rc < 0) {
1130 pr_err("Error in setting constant_charge_current_max property on batt_psy, rc=%d\n",
1131 rc);
1132 return;
1133 }
1134
1135 fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
1136}
1137
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -07001138static int fg_batt_miss_irq_en_cb(struct votable *votable, void *data,
1139 int enable, const char *client)
1140{
1141 struct fg_chip *chip = data;
1142
1143 if (!chip->irqs[BATT_MISSING_IRQ].irq)
1144 return 0;
1145
1146 if (enable) {
1147 enable_irq(chip->irqs[BATT_MISSING_IRQ].irq);
1148 enable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
1149 } else {
1150 disable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
1151 disable_irq(chip->irqs[BATT_MISSING_IRQ].irq);
1152 }
1153
1154 return 0;
1155}
1156
Subbaraman Narayanamurthy53448172017-03-15 12:47:00 -07001157static int fg_delta_bsoc_irq_en_cb(struct votable *votable, void *data,
1158 int enable, const char *client)
1159{
1160 struct fg_chip *chip = data;
1161
1162 if (!chip->irqs[BSOC_DELTA_IRQ].irq)
1163 return 0;
1164
1165 if (enable) {
1166 enable_irq(chip->irqs[BSOC_DELTA_IRQ].irq);
1167 enable_irq_wake(chip->irqs[BSOC_DELTA_IRQ].irq);
1168 } else {
1169 disable_irq_wake(chip->irqs[BSOC_DELTA_IRQ].irq);
1170 disable_irq(chip->irqs[BSOC_DELTA_IRQ].irq);
1171 }
1172
1173 return 0;
1174}
1175
Nicholas Troaste29dec92016-08-24 09:35:11 -07001176static int fg_awake_cb(struct votable *votable, void *data, int awake,
1177 const char *client)
1178{
1179 struct fg_chip *chip = data;
1180
1181 if (awake)
1182 pm_stay_awake(chip->dev);
1183 else
1184 pm_relax(chip->dev);
1185
1186 pr_debug("client: %s awake: %d\n", client, awake);
1187 return 0;
1188}
1189
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001190static bool batt_psy_initialized(struct fg_chip *chip)
Nicholas Troaste29dec92016-08-24 09:35:11 -07001191{
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001192 if (chip->batt_psy)
1193 return true;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001194
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001195 chip->batt_psy = power_supply_get_by_name("battery");
Nicholas Troaste29dec92016-08-24 09:35:11 -07001196 if (!chip->batt_psy)
1197 return false;
1198
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001199 /* batt_psy is initialized, set the fcc and fv */
1200 fg_notify_charger(chip);
1201
Nicholas Troaste29dec92016-08-24 09:35:11 -07001202 return true;
1203}
1204
Nicholas Troast805c2422017-07-06 14:53:46 -07001205static bool usb_psy_initialized(struct fg_chip *chip)
1206{
1207 if (chip->usb_psy)
1208 return true;
1209
1210 chip->usb_psy = power_supply_get_by_name("usb");
1211 if (!chip->usb_psy)
1212 return false;
1213
1214 return true;
1215}
1216
1217static bool pc_port_psy_initialized(struct fg_chip *chip)
1218{
1219 if (chip->pc_port_psy)
1220 return true;
1221
1222 chip->pc_port_psy = power_supply_get_by_name("pc_port");
1223 if (!chip->pc_port_psy)
1224 return false;
1225
1226 return true;
1227}
1228
1229static bool dc_psy_initialized(struct fg_chip *chip)
1230{
1231 if (chip->dc_psy)
1232 return true;
1233
1234 chip->dc_psy = power_supply_get_by_name("dc");
1235 if (!chip->dc_psy)
1236 return false;
1237
1238 return true;
1239}
1240
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07001241static bool is_parallel_charger_available(struct fg_chip *chip)
1242{
1243 if (!chip->parallel_psy)
1244 chip->parallel_psy = power_supply_get_by_name("parallel");
1245
1246 if (!chip->parallel_psy)
1247 return false;
1248
1249 return true;
1250}
1251
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001252static int fg_save_learned_cap_to_sram(struct fg_chip *chip)
1253{
1254 int16_t cc_mah;
1255 int rc;
1256
1257 if (chip->battery_missing || !chip->cl.learned_cc_uah)
1258 return -EPERM;
1259
1260 cc_mah = div64_s64(chip->cl.learned_cc_uah, 1000);
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001261 /* Write to a backup register to use across reboot */
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001262 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ACT_BATT_CAP].addr_word,
1263 chip->sp[FG_SRAM_ACT_BATT_CAP].addr_byte, (u8 *)&cc_mah,
1264 chip->sp[FG_SRAM_ACT_BATT_CAP].len, FG_IMA_DEFAULT);
1265 if (rc < 0) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001266 pr_err("Error in writing act_batt_cap_bkup, rc=%d\n", rc);
1267 return rc;
1268 }
1269
1270 /* Write to actual capacity register for coulomb counter operation */
1271 rc = fg_sram_write(chip, ACT_BATT_CAP_WORD, ACT_BATT_CAP_OFFSET,
1272 (u8 *)&cc_mah, chip->sp[FG_SRAM_ACT_BATT_CAP].len,
1273 FG_IMA_DEFAULT);
1274 if (rc < 0) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001275 pr_err("Error in writing act_batt_cap, rc=%d\n", rc);
1276 return rc;
1277 }
1278
1279 fg_dbg(chip, FG_CAP_LEARN, "learned capacity %llduah/%dmah stored\n",
1280 chip->cl.learned_cc_uah, cc_mah);
1281 return 0;
1282}
1283
1284#define CAPACITY_DELTA_DECIPCT 500
1285static int fg_load_learned_cap_from_sram(struct fg_chip *chip)
1286{
1287 int rc, act_cap_mah;
1288 int64_t delta_cc_uah, pct_nom_cap_uah;
1289
1290 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
1291 if (rc < 0) {
1292 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
1293 return rc;
1294 }
1295
1296 chip->cl.learned_cc_uah = act_cap_mah * 1000;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001297
1298 if (chip->cl.learned_cc_uah != chip->cl.nom_cap_uah) {
Subbaraman Narayanamurthy51d3c902016-10-24 14:05:44 -07001299 if (chip->cl.learned_cc_uah == 0)
1300 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
1301
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001302 delta_cc_uah = abs(chip->cl.learned_cc_uah -
1303 chip->cl.nom_cap_uah);
1304 pct_nom_cap_uah = div64_s64((int64_t)chip->cl.nom_cap_uah *
1305 CAPACITY_DELTA_DECIPCT, 1000);
1306 /*
1307 * If the learned capacity is out of range by 50% from the
1308 * nominal capacity, then overwrite the learned capacity with
1309 * the nominal capacity.
1310 */
1311 if (chip->cl.nom_cap_uah && delta_cc_uah > pct_nom_cap_uah) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001312 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah: %lld is higher than expected, capping it to nominal: %lld\n",
1313 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001314 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001315 }
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -07001316
1317 rc = fg_save_learned_cap_to_sram(chip);
1318 if (rc < 0)
1319 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001320 }
1321
1322 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah:%lld nom_cap_uah: %lld\n",
1323 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
1324 return 0;
1325}
1326
1327static bool is_temp_valid_cap_learning(struct fg_chip *chip)
1328{
1329 int rc, batt_temp;
1330
1331 rc = fg_get_battery_temp(chip, &batt_temp);
1332 if (rc < 0) {
1333 pr_err("Error in getting batt_temp\n");
1334 return false;
1335 }
1336
1337 if (batt_temp > chip->dt.cl_max_temp ||
1338 batt_temp < chip->dt.cl_min_temp) {
1339 fg_dbg(chip, FG_CAP_LEARN, "batt temp %d out of range [%d %d]\n",
1340 batt_temp, chip->dt.cl_min_temp, chip->dt.cl_max_temp);
1341 return false;
1342 }
1343
1344 return true;
1345}
1346
Subbaraman Narayanamurthyd1190cf2017-06-23 18:25:09 -07001347#define QNOVO_CL_SKEW_DECIPCT -30
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001348static void fg_cap_learning_post_process(struct fg_chip *chip)
1349{
1350 int64_t max_inc_val, min_dec_val, old_cap;
1351 int rc;
1352
Subbaraman Narayanamurthyd1190cf2017-06-23 18:25:09 -07001353 if (is_qnovo_en(chip)) {
1354 fg_dbg(chip, FG_CAP_LEARN, "applying skew %d on current learnt capacity %lld\n",
1355 QNOVO_CL_SKEW_DECIPCT, chip->cl.final_cc_uah);
1356 chip->cl.final_cc_uah = chip->cl.final_cc_uah *
1357 (1000 + QNOVO_CL_SKEW_DECIPCT);
1358 do_div(chip->cl.final_cc_uah, 1000);
1359 }
1360
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001361 max_inc_val = chip->cl.learned_cc_uah
1362 * (1000 + chip->dt.cl_max_cap_inc);
1363 do_div(max_inc_val, 1000);
1364
1365 min_dec_val = chip->cl.learned_cc_uah
1366 * (1000 - chip->dt.cl_max_cap_dec);
1367 do_div(min_dec_val, 1000);
1368
1369 old_cap = chip->cl.learned_cc_uah;
1370 if (chip->cl.final_cc_uah > max_inc_val)
1371 chip->cl.learned_cc_uah = max_inc_val;
1372 else if (chip->cl.final_cc_uah < min_dec_val)
1373 chip->cl.learned_cc_uah = min_dec_val;
1374 else
1375 chip->cl.learned_cc_uah =
1376 chip->cl.final_cc_uah;
1377
1378 if (chip->dt.cl_max_cap_limit) {
1379 max_inc_val = (int64_t)chip->cl.nom_cap_uah * (1000 +
1380 chip->dt.cl_max_cap_limit);
1381 do_div(max_inc_val, 1000);
1382 if (chip->cl.final_cc_uah > max_inc_val) {
1383 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes above max limit %lld\n",
1384 chip->cl.final_cc_uah, max_inc_val);
1385 chip->cl.learned_cc_uah = max_inc_val;
1386 }
1387 }
1388
1389 if (chip->dt.cl_min_cap_limit) {
1390 min_dec_val = (int64_t)chip->cl.nom_cap_uah * (1000 -
1391 chip->dt.cl_min_cap_limit);
1392 do_div(min_dec_val, 1000);
1393 if (chip->cl.final_cc_uah < min_dec_val) {
1394 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes below min limit %lld\n",
1395 chip->cl.final_cc_uah, min_dec_val);
1396 chip->cl.learned_cc_uah = min_dec_val;
1397 }
1398 }
1399
1400 rc = fg_save_learned_cap_to_sram(chip);
1401 if (rc < 0)
1402 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
1403
1404 fg_dbg(chip, FG_CAP_LEARN, "final cc_uah = %lld, learned capacity %lld -> %lld uah\n",
1405 chip->cl.final_cc_uah, old_cap, chip->cl.learned_cc_uah);
1406}
1407
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001408static int fg_cap_learning_process_full_data(struct fg_chip *chip)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001409{
1410 int rc, cc_soc_sw, cc_soc_delta_pct;
1411 int64_t delta_cc_uah;
1412
1413 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1414 if (rc < 0) {
1415 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1416 return rc;
1417 }
1418
Subbaraman Narayanamurthy3cf60ee2017-06-02 11:38:58 -07001419 cc_soc_delta_pct =
1420 div64_s64((int64_t)(cc_soc_sw - chip->cl.init_cc_soc_sw) * 100,
1421 CC_SOC_30BIT);
1422
1423 /* If the delta is < 50%, then skip processing full data */
1424 if (cc_soc_delta_pct < 50) {
1425 pr_err("cc_soc_delta_pct: %d\n", cc_soc_delta_pct);
1426 return -ERANGE;
1427 }
1428
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001429 delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
1430 100);
1431 chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
1432 fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%d total_cc_uah=%lld\n",
1433 cc_soc_sw, cc_soc_delta_pct, chip->cl.final_cc_uah);
1434 return 0;
1435}
1436
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001437#define BATT_SOC_32BIT GENMASK(31, 0)
1438static int fg_cap_learning_begin(struct fg_chip *chip, u32 batt_soc)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001439{
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001440 int rc, cc_soc_sw, batt_soc_msb;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001441
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001442 batt_soc_msb = batt_soc >> 24;
1443 if (DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW) >
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001444 chip->dt.cl_start_soc) {
1445 fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n",
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001446 batt_soc_msb);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001447 return -EINVAL;
1448 }
1449
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001450 chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc_msb,
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001451 FULL_SOC_RAW);
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001452
1453 /* Prime cc_soc_sw with battery SOC when capacity learning begins */
1454 cc_soc_sw = div64_s64((int64_t)batt_soc * CC_SOC_30BIT,
1455 BATT_SOC_32BIT);
1456 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
1457 chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
1458 chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001459 if (rc < 0) {
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001460 pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
1461 goto out;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001462 }
1463
1464 chip->cl.init_cc_soc_sw = cc_soc_sw;
1465 chip->cl.active = true;
1466 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001467 batt_soc_msb, chip->cl.init_cc_soc_sw);
1468out:
1469 return rc;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001470}
1471
1472static int fg_cap_learning_done(struct fg_chip *chip)
1473{
1474 int rc, cc_soc_sw;
1475
1476 rc = fg_cap_learning_process_full_data(chip);
1477 if (rc < 0) {
1478 pr_err("Error in processing cap learning full data, rc=%d\n",
1479 rc);
1480 goto out;
1481 }
1482
1483 /* Write a FULL value to cc_soc_sw */
1484 cc_soc_sw = CC_SOC_30BIT;
1485 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
1486 chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001487 chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001488 if (rc < 0) {
1489 pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
1490 goto out;
1491 }
1492
1493 fg_cap_learning_post_process(chip);
1494out:
1495 return rc;
1496}
1497
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001498static void fg_cap_learning_update(struct fg_chip *chip)
1499{
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001500 int rc, batt_soc, batt_soc_msb;
Abhijeet Dharmapurikar86a5e172017-07-05 13:58:04 -07001501 bool input_present = is_input_present(chip);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001502
1503 mutex_lock(&chip->cl.lock);
1504
1505 if (!is_temp_valid_cap_learning(chip) || !chip->cl.learned_cc_uah ||
1506 chip->battery_missing) {
1507 fg_dbg(chip, FG_CAP_LEARN, "Aborting cap_learning %lld\n",
1508 chip->cl.learned_cc_uah);
1509 chip->cl.active = false;
1510 chip->cl.init_cc_uah = 0;
1511 goto out;
1512 }
1513
1514 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1515 if (rc < 0) {
1516 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
1517 goto out;
1518 }
1519
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001520 batt_soc_msb = (u32)batt_soc >> 24;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001521 fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n",
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07001522 chip->charge_status, chip->cl.active, batt_soc_msb);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001523
1524 /* Initialize the starting point of learning capacity */
1525 if (!chip->cl.active) {
Nicholas Troast1769fd32016-09-07 09:20:58 -07001526 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001527 rc = fg_cap_learning_begin(chip, batt_soc);
1528 chip->cl.active = (rc == 0);
1529 }
1530
1531 } else {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001532 if (chip->charge_done) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001533 rc = fg_cap_learning_done(chip);
1534 if (rc < 0)
1535 pr_err("Error in completing capacity learning, rc=%d\n",
1536 rc);
1537
1538 chip->cl.active = false;
1539 chip->cl.init_cc_uah = 0;
1540 }
1541
Abhijeet Dharmapurikar86a5e172017-07-05 13:58:04 -07001542 if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
1543 if (!input_present) {
1544 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
1545 batt_soc_msb);
1546 chip->cl.active = false;
1547 chip->cl.init_cc_uah = 0;
1548 }
1549 }
1550
Nicholas Troast1769fd32016-09-07 09:20:58 -07001551 if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
Abhijeet Dharmapurikar86a5e172017-07-05 13:58:04 -07001552 if (is_qnovo_en(chip) && input_present) {
1553 /*
1554 * Don't abort the capacity learning when qnovo
1555 * is enabled and input is present where the
1556 * charging status can go to "not charging"
1557 * intermittently.
1558 */
1559 } else {
1560 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
1561 batt_soc_msb);
1562 chip->cl.active = false;
1563 chip->cl.init_cc_uah = 0;
1564 }
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001565 }
1566 }
1567
1568out:
1569 mutex_unlock(&chip->cl.lock);
1570}
1571
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001572#define KI_COEFF_MED_DISCHG_DEFAULT 1500
1573#define KI_COEFF_HI_DISCHG_DEFAULT 2200
1574static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
1575{
1576 int rc, i, msoc;
1577 int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
1578 int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
1579 u8 val;
1580
1581 if (!chip->ki_coeff_dischg_en)
1582 return 0;
1583
1584 rc = fg_get_prop_capacity(chip, &msoc);
1585 if (rc < 0) {
1586 pr_err("Error in getting capacity, rc=%d\n", rc);
1587 return rc;
1588 }
1589
Nicholas Troast1769fd32016-09-07 09:20:58 -07001590 if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001591 for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
1592 if (msoc < chip->dt.ki_coeff_soc[i]) {
1593 ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
1594 ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
1595 }
1596 }
1597 }
1598
1599 fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
1600 rc = fg_sram_write(chip,
1601 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
1602 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
1603 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
1604 FG_IMA_DEFAULT);
1605 if (rc < 0) {
1606 pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
1607 return rc;
1608 }
1609
1610 fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
1611 rc = fg_sram_write(chip,
1612 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
1613 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
1614 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
1615 FG_IMA_DEFAULT);
1616 if (rc < 0) {
1617 pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
1618 return rc;
1619 }
1620
1621 fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
1622 ki_coeff_med, ki_coeff_hi);
1623 return 0;
1624}
1625
Subbaraman Narayanamurthy1bf973e2017-04-04 19:24:20 -07001626#define KI_COEFF_FULL_SOC_DEFAULT 733
1627static int fg_adjust_ki_coeff_full_soc(struct fg_chip *chip, int batt_temp)
1628{
1629 int rc, ki_coeff_full_soc;
1630 u8 val;
1631
1632 if (batt_temp < 0)
1633 ki_coeff_full_soc = 0;
Subbaraman Narayanamurthye17be582017-08-08 19:28:37 -07001634 else if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)
1635 ki_coeff_full_soc = chip->dt.ki_coeff_full_soc_dischg;
Subbaraman Narayanamurthy1bf973e2017-04-04 19:24:20 -07001636 else
1637 ki_coeff_full_soc = KI_COEFF_FULL_SOC_DEFAULT;
1638
1639 if (chip->ki_coeff_full_soc == ki_coeff_full_soc)
1640 return 0;
1641
1642 fg_encode(chip->sp, FG_SRAM_KI_COEFF_FULL_SOC, ki_coeff_full_soc, &val);
1643 rc = fg_sram_write(chip,
1644 chip->sp[FG_SRAM_KI_COEFF_FULL_SOC].addr_word,
1645 chip->sp[FG_SRAM_KI_COEFF_FULL_SOC].addr_byte, &val,
1646 chip->sp[FG_SRAM_KI_COEFF_FULL_SOC].len,
1647 FG_IMA_DEFAULT);
1648 if (rc < 0) {
1649 pr_err("Error in writing ki_coeff_full_soc, rc=%d\n", rc);
1650 return rc;
1651 }
1652
1653 chip->ki_coeff_full_soc = ki_coeff_full_soc;
1654 fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_full_soc %d\n",
1655 ki_coeff_full_soc);
1656 return 0;
1657}
1658
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001659static int fg_set_recharge_voltage(struct fg_chip *chip, int voltage_mv)
1660{
1661 u8 buf;
1662 int rc;
1663
1664 if (chip->dt.auto_recharge_soc)
1665 return 0;
1666
1667 /* This configuration is available only for pmicobalt v2.0 and above */
1668 if (chip->wa_flags & PMI8998_V1_REV_WA)
1669 return 0;
1670
Subbaraman Narayanamurthyfdca8c22017-08-04 12:25:49 -07001671 if (voltage_mv == chip->last_recharge_volt_mv)
1672 return 0;
1673
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001674 fg_dbg(chip, FG_STATUS, "Setting recharge voltage to %dmV\n",
1675 voltage_mv);
1676 fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, voltage_mv, &buf);
1677 rc = fg_sram_write(chip,
1678 chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word,
1679 chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte,
1680 &buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len,
1681 FG_IMA_DEFAULT);
1682 if (rc < 0) {
1683 pr_err("Error in writing recharge_vbatt_thr, rc=%d\n",
1684 rc);
1685 return rc;
1686 }
1687
Subbaraman Narayanamurthyfdca8c22017-08-04 12:25:49 -07001688 chip->last_recharge_volt_mv = voltage_mv;
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001689 return 0;
1690}
1691
Subbaraman Narayanamurthy9b6c38a2017-07-26 16:46:41 -07001692static int fg_configure_full_soc(struct fg_chip *chip, int bsoc)
1693{
1694 int rc;
1695 u8 full_soc[2] = {0xFF, 0xFF};
1696
1697 /*
1698 * Once SOC masking condition is cleared, FULL_SOC and MONOTONIC_SOC
1699 * needs to be updated to reflect the same. Write battery SOC to
1700 * FULL_SOC and write a full value to MONOTONIC_SOC.
1701 */
1702 rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET,
1703 (u8 *)&bsoc, 2, FG_IMA_ATOMIC);
1704 if (rc < 0) {
1705 pr_err("failed to write full_soc rc=%d\n", rc);
1706 return rc;
1707 }
1708
1709 rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
1710 full_soc, 2, FG_IMA_ATOMIC);
1711 if (rc < 0) {
1712 pr_err("failed to write monotonic_soc rc=%d\n", rc);
1713 return rc;
1714 }
1715
1716 return 0;
1717}
1718
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001719#define AUTO_RECHG_VOLT_LOW_LIMIT_MV 3700
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001720static int fg_charge_full_update(struct fg_chip *chip)
1721{
1722 union power_supply_propval prop = {0, };
Anirudh Ghayale2b26cc2017-07-12 10:12:24 +05301723 int rc, msoc, bsoc, recharge_soc, msoc_raw;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001724
1725 if (!chip->dt.hold_soc_while_full)
1726 return 0;
1727
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08001728 if (!batt_psy_initialized(chip))
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001729 return 0;
1730
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001731 mutex_lock(&chip->charge_full_lock);
Subbaraman Narayanamurthy53448172017-03-15 12:47:00 -07001732 vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER,
1733 chip->charge_done, 0);
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001734 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
1735 &prop);
1736 if (rc < 0) {
1737 pr_err("Error in getting battery health, rc=%d\n", rc);
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001738 goto out;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001739 }
1740
1741 chip->health = prop.intval;
1742 recharge_soc = chip->dt.recharge_soc_thr;
1743 recharge_soc = DIV_ROUND_CLOSEST(recharge_soc * FULL_SOC_RAW,
1744 FULL_CAPACITY);
1745 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
1746 if (rc < 0) {
1747 pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001748 goto out;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001749 }
1750
1751 /* We need 2 most significant bytes here */
1752 bsoc = (u32)bsoc >> 16;
Anirudh Ghayal5f556652017-08-08 14:47:56 +05301753 rc = fg_get_msoc_raw(chip, &msoc_raw);
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001754 if (rc < 0) {
Anirudh Ghayal5f556652017-08-08 14:47:56 +05301755 pr_err("Error in getting msoc_raw, rc=%d\n", rc);
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001756 goto out;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001757 }
Anirudh Ghayal5f556652017-08-08 14:47:56 +05301758 msoc = DIV_ROUND_CLOSEST(msoc_raw * FULL_CAPACITY, FULL_SOC_RAW);
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001759
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001760 fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d full: %d\n",
1761 msoc, bsoc, chip->health, chip->charge_status,
1762 chip->charge_full);
1763 if (chip->charge_done && !chip->charge_full) {
1764 if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD) {
1765 fg_dbg(chip, FG_STATUS, "Setting charge_full to true\n");
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001766 chip->charge_full = true;
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001767 /*
1768 * Lower the recharge voltage so that VBAT_LT_RECHG
1769 * signal will not be asserted soon.
1770 */
1771 rc = fg_set_recharge_voltage(chip,
1772 AUTO_RECHG_VOLT_LOW_LIMIT_MV);
1773 if (rc < 0) {
1774 pr_err("Error in reducing recharge voltage, rc=%d\n",
1775 rc);
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001776 goto out;
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001777 }
1778 } else {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001779 fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
1780 msoc);
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001781 }
Subbaraman Narayanamurthy50fb7fd2017-07-25 20:01:25 -07001782 } else if (msoc_raw <= recharge_soc && chip->charge_full) {
1783 if (chip->dt.linearize_soc) {
1784 chip->delta_soc = FULL_CAPACITY - msoc;
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001785
Subbaraman Narayanamurthy50fb7fd2017-07-25 20:01:25 -07001786 /*
1787 * We're spreading out the delta SOC over every 10%
1788 * change in monotonic SOC. We cannot spread more than
1789 * 9% in the range of 0-100 skipping the first 10%.
1790 */
1791 if (chip->delta_soc > 9) {
1792 chip->delta_soc = 0;
1793 chip->maint_soc = 0;
1794 } else {
1795 chip->maint_soc = FULL_CAPACITY;
1796 chip->last_msoc = msoc;
1797 }
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001798 }
1799
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001800 /*
1801 * Raise the recharge voltage so that VBAT_LT_RECHG signal
1802 * will be asserted soon as battery SOC had dropped below
1803 * the recharge SOC threshold.
1804 */
1805 rc = fg_set_recharge_voltage(chip,
1806 chip->dt.recharge_volt_thr_mv);
1807 if (rc < 0) {
1808 pr_err("Error in setting recharge voltage, rc=%d\n",
1809 rc);
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001810 goto out;
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001811 }
Subbaraman Narayanamurthy9b6c38a2017-07-26 16:46:41 -07001812
1813 /*
1814 * If charge_done is still set, wait for recharging or
1815 * discharging to happen.
1816 */
1817 if (chip->charge_done)
1818 goto out;
1819
1820 rc = fg_configure_full_soc(chip, bsoc);
1821 if (rc < 0)
1822 goto out;
1823
1824 chip->charge_full = false;
Anirudh Ghayale2b26cc2017-07-12 10:12:24 +05301825 fg_dbg(chip, FG_STATUS, "msoc_raw = %d bsoc: %d recharge_soc: %d delta_soc: %d\n",
1826 msoc_raw, bsoc >> 8, recharge_soc, chip->delta_soc);
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001827 }
1828
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08001829out:
1830 mutex_unlock(&chip->charge_full_lock);
1831 return rc;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001832}
1833
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08001834#define RCONN_CONFIG_BIT BIT(0)
1835static int fg_rconn_config(struct fg_chip *chip)
1836{
1837 int rc, esr_uohms;
1838 u64 scaling_factor;
1839 u32 val = 0;
1840
Subbaraman Narayanamurthy8909f372017-03-14 19:50:57 -07001841 if (!chip->dt.rconn_mohms)
1842 return 0;
1843
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08001844 rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
1845 SW_CONFIG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1846 if (rc < 0) {
1847 pr_err("Error in reading SW_CONFIG_OFFSET, rc=%d\n", rc);
1848 return rc;
1849 }
1850
1851 if (val & RCONN_CONFIG_BIT) {
1852 fg_dbg(chip, FG_STATUS, "Rconn already configured: %x\n", val);
1853 return 0;
1854 }
1855
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -08001856 rc = fg_get_sram_prop(chip, FG_SRAM_ESR, &esr_uohms);
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08001857 if (rc < 0) {
1858 pr_err("failed to get ESR, rc=%d\n", rc);
1859 return rc;
1860 }
1861
1862 scaling_factor = div64_u64((u64)esr_uohms * 1000,
1863 esr_uohms + (chip->dt.rconn_mohms * 1000));
1864
1865 rc = fg_sram_read(chip, ESR_RSLOW_CHG_WORD,
1866 ESR_RSLOW_CHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1867 if (rc < 0) {
1868 pr_err("Error in reading ESR_RSLOW_CHG_OFFSET, rc=%d\n", rc);
1869 return rc;
1870 }
1871
1872 val *= scaling_factor;
1873 do_div(val, 1000);
1874 rc = fg_sram_write(chip, ESR_RSLOW_CHG_WORD,
1875 ESR_RSLOW_CHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1876 if (rc < 0) {
1877 pr_err("Error in writing ESR_RSLOW_CHG_OFFSET, rc=%d\n", rc);
1878 return rc;
1879 }
1880 fg_dbg(chip, FG_STATUS, "esr_rslow_chg modified to %x\n", val & 0xFF);
1881
1882 rc = fg_sram_read(chip, ESR_RSLOW_DISCHG_WORD,
1883 ESR_RSLOW_DISCHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1884 if (rc < 0) {
1885 pr_err("Error in reading ESR_RSLOW_DISCHG_OFFSET, rc=%d\n", rc);
1886 return rc;
1887 }
1888
1889 val *= scaling_factor;
1890 do_div(val, 1000);
1891 rc = fg_sram_write(chip, ESR_RSLOW_DISCHG_WORD,
1892 ESR_RSLOW_DISCHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1893 if (rc < 0) {
1894 pr_err("Error in writing ESR_RSLOW_DISCHG_OFFSET, rc=%d\n", rc);
1895 return rc;
1896 }
1897 fg_dbg(chip, FG_STATUS, "esr_rslow_dischg modified to %x\n",
1898 val & 0xFF);
1899
1900 val = RCONN_CONFIG_BIT;
1901 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
1902 SW_CONFIG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT);
1903 if (rc < 0) {
1904 pr_err("Error in writing SW_CONFIG_OFFSET, rc=%d\n", rc);
1905 return rc;
1906 }
1907
1908 return 0;
1909}
1910
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07001911static int fg_set_jeita_threshold(struct fg_chip *chip,
1912 enum jeita_levels level, int temp_decidegC)
1913{
1914 int rc;
1915 u8 val;
1916 u16 reg;
1917
1918 if (temp_decidegC < -300 || temp_decidegC > 970)
1919 return -EINVAL;
1920
1921 /* Resolution is 0.5C. Base is -30C. */
1922 val = DIV_ROUND_CLOSEST(((temp_decidegC / 10) + 30) * 10, 5);
1923 switch (level) {
1924 case JEITA_COLD:
1925 reg = BATT_INFO_JEITA_TOO_COLD(chip);
1926 break;
1927 case JEITA_COOL:
1928 reg = BATT_INFO_JEITA_COLD(chip);
1929 break;
1930 case JEITA_WARM:
1931 reg = BATT_INFO_JEITA_HOT(chip);
1932 break;
1933 case JEITA_HOT:
1934 reg = BATT_INFO_JEITA_TOO_HOT(chip);
1935 break;
1936 default:
1937 return -EINVAL;
1938 }
1939
1940 rc = fg_write(chip, reg, &val, 1);
1941 if (rc < 0) {
1942 pr_err("Error in setting jeita level %d, rc=%d\n", level, rc);
1943 return rc;
1944 }
1945
1946 return 0;
1947}
1948
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -08001949static int fg_set_constant_chg_voltage(struct fg_chip *chip, int volt_uv)
1950{
1951 u8 buf[2];
1952 int rc;
1953
1954 if (volt_uv <= 0 || volt_uv > 15590000) {
1955 pr_err("Invalid voltage %d\n", volt_uv);
1956 return -EINVAL;
1957 }
1958
1959 fg_encode(chip->sp, FG_SRAM_VBATT_FULL, volt_uv, buf);
1960
1961 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_FULL].addr_word,
1962 chip->sp[FG_SRAM_VBATT_FULL].addr_byte, buf,
1963 chip->sp[FG_SRAM_VBATT_FULL].len, FG_IMA_DEFAULT);
1964 if (rc < 0) {
1965 pr_err("Error in writing vbatt_full, rc=%d\n", rc);
1966 return rc;
1967 }
1968
1969 return 0;
1970}
1971
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001972static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
1973{
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001974 u8 buf;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001975 int rc;
1976
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001977 if (!chip->dt.auto_recharge_soc)
1978 return 0;
1979
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07001980 if (recharge_soc < 0 || recharge_soc > FULL_CAPACITY)
1981 return 0;
1982
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001983 fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, &buf);
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001984 rc = fg_sram_write(chip,
1985 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08001986 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, &buf,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001987 chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
1988 if (rc < 0) {
1989 pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
1990 return rc;
1991 }
1992
1993 return 0;
1994}
1995
1996static int fg_adjust_recharge_soc(struct fg_chip *chip)
1997{
1998 int rc, msoc, recharge_soc, new_recharge_soc = 0;
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07001999 bool recharge_soc_status;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002000
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08002001 if (!chip->dt.auto_recharge_soc)
2002 return 0;
2003
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002004 recharge_soc = chip->dt.recharge_soc_thr;
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07002005 recharge_soc_status = chip->recharge_soc_adjusted;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002006 /*
2007 * If the input is present and charging had been terminated, adjust
2008 * the recharge SOC threshold based on the monotonic SOC at which
2009 * the charge termination had happened.
2010 */
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07002011 if (is_input_present(chip)) {
2012 if (chip->charge_done) {
2013 if (!chip->recharge_soc_adjusted) {
2014 /* Get raw monotonic SOC for calculation */
2015 rc = fg_get_msoc(chip, &msoc);
2016 if (rc < 0) {
2017 pr_err("Error in getting msoc, rc=%d\n",
2018 rc);
2019 return rc;
2020 }
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002021
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07002022 /* Adjust the recharge_soc threshold */
2023 new_recharge_soc = msoc - (FULL_CAPACITY -
2024 recharge_soc);
2025 chip->recharge_soc_adjusted = true;
2026 } else {
2027 /* adjusted already, do nothing */
2028 return 0;
2029 }
2030 } else {
2031 /* Charging, do nothing */
2032 return 0;
2033 }
2034 } else {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002035 /* Restore the default value */
2036 new_recharge_soc = recharge_soc;
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07002037 chip->recharge_soc_adjusted = false;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002038 }
2039
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07002040 rc = fg_set_recharge_soc(chip, new_recharge_soc);
2041 if (rc < 0) {
2042 chip->recharge_soc_adjusted = recharge_soc_status;
2043 pr_err("Couldn't set resume SOC for FG, rc=%d\n", rc);
2044 return rc;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002045 }
2046
Subbaraman Narayanamurthyebe7e2b2017-03-13 12:50:12 -07002047 fg_dbg(chip, FG_STATUS, "resume soc set to %d\n", new_recharge_soc);
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002048 return 0;
2049}
2050
Subbaraman Narayanamurthyfdca8c22017-08-04 12:25:49 -07002051static int fg_adjust_recharge_voltage(struct fg_chip *chip)
2052{
2053 int rc, recharge_volt_mv;
2054
2055 if (chip->dt.auto_recharge_soc)
2056 return 0;
2057
2058 fg_dbg(chip, FG_STATUS, "health: %d chg_status: %d chg_done: %d\n",
2059 chip->health, chip->charge_status, chip->charge_done);
2060
2061 recharge_volt_mv = chip->dt.recharge_volt_thr_mv;
2062
2063 /* Lower the recharge voltage in soft JEITA */
2064 if (chip->health == POWER_SUPPLY_HEALTH_WARM ||
2065 chip->health == POWER_SUPPLY_HEALTH_COOL)
2066 recharge_volt_mv -= 200;
2067
2068 rc = fg_set_recharge_voltage(chip, recharge_volt_mv);
2069 if (rc < 0) {
2070 pr_err("Error in setting recharge_voltage, rc=%d\n",
2071 rc);
2072 return rc;
2073 }
2074
2075 return 0;
2076}
2077
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -08002078static int fg_slope_limit_config(struct fg_chip *chip, int batt_temp)
2079{
2080 enum slope_limit_status status;
2081 int rc;
2082 u8 buf;
2083
2084 if (!chip->slope_limit_en)
2085 return 0;
2086
2087 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING ||
2088 chip->charge_status == POWER_SUPPLY_STATUS_FULL) {
2089 if (batt_temp < chip->dt.slope_limit_temp)
2090 status = LOW_TEMP_CHARGE;
2091 else
2092 status = HIGH_TEMP_CHARGE;
2093 } else {
2094 if (batt_temp < chip->dt.slope_limit_temp)
2095 status = LOW_TEMP_DISCHARGE;
2096 else
2097 status = HIGH_TEMP_DISCHARGE;
2098 }
2099
2100 if (chip->slope_limit_sts == status)
2101 return 0;
2102
2103 fg_encode(chip->sp, FG_SRAM_SLOPE_LIMIT,
2104 chip->dt.slope_limit_coeffs[status], &buf);
2105 rc = fg_sram_write(chip, chip->sp[FG_SRAM_SLOPE_LIMIT].addr_word,
2106 chip->sp[FG_SRAM_SLOPE_LIMIT].addr_byte, &buf,
2107 chip->sp[FG_SRAM_SLOPE_LIMIT].len, FG_IMA_DEFAULT);
2108 if (rc < 0) {
2109 pr_err("Error in configuring slope_limit coefficient, rc=%d\n",
2110 rc);
2111 return rc;
2112 }
2113
2114 chip->slope_limit_sts = status;
2115 fg_dbg(chip, FG_STATUS, "Slope limit status: %d value: %x\n", status,
2116 buf);
2117 return 0;
2118}
2119
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08002120static int fg_esr_filter_config(struct fg_chip *chip, int batt_temp)
2121{
2122 u8 esr_tight_lt_flt, esr_broad_lt_flt;
2123 bool cold_temp = false;
2124 int rc;
2125
2126 /*
2127 * If the battery temperature is lower than -20 C, then skip modifying
2128 * ESR filter.
2129 */
2130 if (batt_temp < -210)
2131 return 0;
2132
2133 /*
2134 * If battery temperature is lesser than 10 C (default), then apply the
Subbaraman Narayanamurthy5000eb62017-02-08 20:39:16 -08002135 * ESR low temperature tight and broad filter values to ESR room
2136 * temperature tight and broad filters. If battery temperature is higher
2137 * than 10 C, then apply back the room temperature ESR filter
2138 * coefficients to ESR room temperature tight and broad filters.
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08002139 */
2140 if (batt_temp > chip->dt.esr_flt_switch_temp
2141 && chip->esr_flt_cold_temp_en) {
2142 fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08002143 chip->dt.esr_tight_flt_upct, &esr_tight_lt_flt);
2144 fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
2145 chip->dt.esr_broad_flt_upct, &esr_broad_lt_flt);
Subbaraman Narayanamurthy5000eb62017-02-08 20:39:16 -08002146 } else if (batt_temp <= chip->dt.esr_flt_switch_temp
2147 && !chip->esr_flt_cold_temp_en) {
2148 fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
2149 chip->dt.esr_tight_lt_flt_upct, &esr_tight_lt_flt);
2150 fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
2151 chip->dt.esr_broad_lt_flt_upct, &esr_broad_lt_flt);
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08002152 cold_temp = true;
2153 } else {
2154 return 0;
2155 }
2156
Subbaraman Narayanamurthy5000eb62017-02-08 20:39:16 -08002157 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_word,
2158 chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_byte,
2159 &esr_tight_lt_flt,
2160 chip->sp[FG_SRAM_ESR_TIGHT_FILTER].len, FG_IMA_DEFAULT);
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08002161 if (rc < 0) {
2162 pr_err("Error in writing ESR LT tight filter, rc=%d\n", rc);
2163 return rc;
2164 }
2165
Subbaraman Narayanamurthy5000eb62017-02-08 20:39:16 -08002166 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_word,
2167 chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_byte,
2168 &esr_broad_lt_flt,
2169 chip->sp[FG_SRAM_ESR_BROAD_FILTER].len, FG_IMA_DEFAULT);
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08002170 if (rc < 0) {
2171 pr_err("Error in writing ESR LT broad filter, rc=%d\n", rc);
2172 return rc;
2173 }
2174
2175 chip->esr_flt_cold_temp_en = cold_temp;
2176 fg_dbg(chip, FG_STATUS, "applied %s ESR filter values\n",
2177 cold_temp ? "cold" : "normal");
2178 return 0;
2179}
2180
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07002181static int fg_esr_fcc_config(struct fg_chip *chip)
2182{
2183 union power_supply_propval prop = {0, };
2184 int rc;
Abhijeet Dharmapurikar86a5e172017-07-05 13:58:04 -07002185 bool parallel_en = false, qnovo_en;
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07002186
2187 if (is_parallel_charger_available(chip)) {
2188 rc = power_supply_get_property(chip->parallel_psy,
2189 POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
2190 if (rc < 0) {
2191 pr_err("Error in reading charging_enabled from parallel_psy, rc=%d\n",
2192 rc);
2193 return rc;
2194 }
2195 parallel_en = prop.intval;
2196 }
2197
Abhijeet Dharmapurikar86a5e172017-07-05 13:58:04 -07002198 qnovo_en = is_qnovo_en(chip);
Subbaraman Narayanamurthyf6357232017-04-19 14:55:35 -07002199
2200 fg_dbg(chip, FG_POWER_SUPPLY, "chg_sts: %d par_en: %d qnov_en: %d esr_fcc_ctrl_en: %d\n",
2201 chip->charge_status, parallel_en, qnovo_en,
2202 chip->esr_fcc_ctrl_en);
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07002203
Nicholas Troast1769fd32016-09-07 09:20:58 -07002204 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
Subbaraman Narayanamurthyf6357232017-04-19 14:55:35 -07002205 (parallel_en || qnovo_en)) {
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07002206 if (chip->esr_fcc_ctrl_en)
2207 return 0;
2208
2209 /*
Subbaraman Narayanamurthyf6357232017-04-19 14:55:35 -07002210 * When parallel charging or Qnovo is enabled, configure ESR
2211 * FCC to 300mA to trigger an ESR pulse. Without this, FG can
2212 * request the main charger to increase FCC when it is supposed
2213 * to decrease it.
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07002214 */
2215 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
2216 ESR_FAST_CRG_IVAL_MASK |
2217 ESR_FAST_CRG_CTL_EN_BIT,
2218 ESR_FCC_300MA | ESR_FAST_CRG_CTL_EN_BIT);
2219 if (rc < 0) {
2220 pr_err("Error in writing to %04x, rc=%d\n",
2221 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
2222 return rc;
2223 }
2224
2225 chip->esr_fcc_ctrl_en = true;
2226 } else {
2227 if (!chip->esr_fcc_ctrl_en)
2228 return 0;
2229
2230 /*
2231 * If we're here, then it means either the device is not in
Subbaraman Narayanamurthyf6357232017-04-19 14:55:35 -07002232 * charging state or parallel charging / Qnovo is disabled.
2233 * Disable ESR fast charge current control in SW.
Subbaraman Narayanamurthya9aacae2016-11-01 19:31:44 -07002234 */
2235 rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
2236 ESR_FAST_CRG_CTL_EN_BIT, 0);
2237 if (rc < 0) {
2238 pr_err("Error in writing to %04x, rc=%d\n",
2239 BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
2240 return rc;
2241 }
2242
2243 chip->esr_fcc_ctrl_en = false;
2244 }
2245
2246 fg_dbg(chip, FG_STATUS, "esr_fcc_ctrl_en set to %d\n",
2247 chip->esr_fcc_ctrl_en);
2248 return 0;
2249}
2250
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07002251static int fg_esr_timer_config(struct fg_chip *chip, bool sleep)
2252{
2253 int rc, cycles_init, cycles_max;
2254 bool end_of_charge = false;
2255
2256 end_of_charge = is_input_present(chip) && chip->charge_done;
2257 fg_dbg(chip, FG_STATUS, "sleep: %d eoc: %d\n", sleep, end_of_charge);
2258
2259 /* ESR discharging timer configuration */
2260 cycles_init = sleep ? chip->dt.esr_timer_asleep[TIMER_RETRY] :
2261 chip->dt.esr_timer_awake[TIMER_RETRY];
2262 if (end_of_charge)
2263 cycles_init = 0;
2264
2265 cycles_max = sleep ? chip->dt.esr_timer_asleep[TIMER_MAX] :
2266 chip->dt.esr_timer_awake[TIMER_MAX];
2267
2268 rc = fg_set_esr_timer(chip, cycles_init, cycles_max, false,
2269 sleep ? FG_IMA_NO_WLOCK : FG_IMA_DEFAULT);
2270 if (rc < 0) {
2271 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2272 return rc;
2273 }
2274
2275 /* ESR charging timer configuration */
2276 cycles_init = cycles_max = -EINVAL;
2277 if (end_of_charge || sleep) {
2278 cycles_init = chip->dt.esr_timer_charging[TIMER_RETRY];
2279 cycles_max = chip->dt.esr_timer_charging[TIMER_MAX];
2280 } else if (is_input_present(chip)) {
2281 cycles_init = chip->esr_timer_charging_default[TIMER_RETRY];
2282 cycles_max = chip->esr_timer_charging_default[TIMER_MAX];
2283 }
2284
2285 rc = fg_set_esr_timer(chip, cycles_init, cycles_max, true,
2286 sleep ? FG_IMA_NO_WLOCK : FG_IMA_DEFAULT);
2287 if (rc < 0) {
2288 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2289 return rc;
2290 }
2291
2292 return 0;
2293}
2294
Nicholas Troast805c2422017-07-06 14:53:46 -07002295static void fg_ttf_update(struct fg_chip *chip)
Nicholas Troast1769fd32016-09-07 09:20:58 -07002296{
Nicholas Troast805c2422017-07-06 14:53:46 -07002297 int rc;
2298 int delay_ms;
2299 union power_supply_propval prop = {0, };
2300 int online = 0;
2301
2302 if (usb_psy_initialized(chip)) {
2303 rc = power_supply_get_property(chip->usb_psy,
2304 POWER_SUPPLY_PROP_ONLINE, &prop);
2305 if (rc < 0) {
2306 pr_err("Couldn't read usb ONLINE prop rc=%d\n", rc);
2307 return;
2308 }
2309
2310 online = online || prop.intval;
2311 }
2312
2313 if (pc_port_psy_initialized(chip)) {
2314 rc = power_supply_get_property(chip->pc_port_psy,
2315 POWER_SUPPLY_PROP_ONLINE, &prop);
2316 if (rc < 0) {
2317 pr_err("Couldn't read pc_port ONLINE prop rc=%d\n", rc);
2318 return;
2319 }
2320
2321 online = online || prop.intval;
2322 }
2323
2324 if (dc_psy_initialized(chip)) {
2325 rc = power_supply_get_property(chip->dc_psy,
2326 POWER_SUPPLY_PROP_ONLINE, &prop);
2327 if (rc < 0) {
2328 pr_err("Couldn't read dc ONLINE prop rc=%d\n", rc);
2329 return;
2330 }
2331
2332 online = online || prop.intval;
2333 }
2334
2335
2336 if (chip->online_status == online)
Nicholas Troast1769fd32016-09-07 09:20:58 -07002337 return;
2338
Nicholas Troast805c2422017-07-06 14:53:46 -07002339 chip->online_status = online;
2340 if (online)
2341 /* wait 35 seconds for the input to settle */
2342 delay_ms = 35000;
2343 else
2344 /* wait 5 seconds for current to settle during discharge */
2345 delay_ms = 5000;
Nicholas Troast1769fd32016-09-07 09:20:58 -07002346
Nicholas Troast805c2422017-07-06 14:53:46 -07002347 vote(chip->awake_votable, TTF_PRIMING, true, 0);
2348 cancel_delayed_work_sync(&chip->ttf_work);
2349 mutex_lock(&chip->ttf.lock);
2350 fg_circ_buf_clr(&chip->ttf.ibatt);
2351 fg_circ_buf_clr(&chip->ttf.vbatt);
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07002352 chip->ttf.last_ttf = 0;
2353 chip->ttf.last_ms = 0;
Nicholas Troast805c2422017-07-06 14:53:46 -07002354 mutex_unlock(&chip->ttf.lock);
2355 schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(delay_ms));
Nicholas Troast1769fd32016-09-07 09:20:58 -07002356}
2357
Nicholas Troaste29dec92016-08-24 09:35:11 -07002358static void restore_cycle_counter(struct fg_chip *chip)
2359{
2360 int rc = 0, i;
2361 u8 data[2];
2362
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002363 if (!chip->cyc_ctr.en)
2364 return;
2365
Nicholas Troaste29dec92016-08-24 09:35:11 -07002366 mutex_lock(&chip->cyc_ctr.lock);
2367 for (i = 0; i < BUCKET_COUNT; i++) {
2368 rc = fg_sram_read(chip, CYCLE_COUNT_WORD + (i / 2),
2369 CYCLE_COUNT_OFFSET + (i % 2) * 2, data, 2,
2370 FG_IMA_DEFAULT);
2371 if (rc < 0)
2372 pr_err("failed to read bucket %d rc=%d\n", i, rc);
2373 else
2374 chip->cyc_ctr.count[i] = data[0] | data[1] << 8;
2375 }
2376 mutex_unlock(&chip->cyc_ctr.lock);
2377}
2378
2379static void clear_cycle_counter(struct fg_chip *chip)
2380{
2381 int rc = 0, i;
2382
2383 if (!chip->cyc_ctr.en)
2384 return;
2385
2386 mutex_lock(&chip->cyc_ctr.lock);
2387 memset(chip->cyc_ctr.count, 0, sizeof(chip->cyc_ctr.count));
2388 for (i = 0; i < BUCKET_COUNT; i++) {
2389 chip->cyc_ctr.started[i] = false;
2390 chip->cyc_ctr.last_soc[i] = 0;
2391 }
2392 rc = fg_sram_write(chip, CYCLE_COUNT_WORD, CYCLE_COUNT_OFFSET,
2393 (u8 *)&chip->cyc_ctr.count,
2394 sizeof(chip->cyc_ctr.count) / sizeof(u8 *),
2395 FG_IMA_DEFAULT);
2396 if (rc < 0)
2397 pr_err("failed to clear cycle counter rc=%d\n", rc);
2398
2399 mutex_unlock(&chip->cyc_ctr.lock);
2400}
2401
2402static int fg_inc_store_cycle_ctr(struct fg_chip *chip, int bucket)
2403{
2404 int rc = 0;
2405 u16 cyc_count;
2406 u8 data[2];
2407
2408 if (bucket < 0 || (bucket > BUCKET_COUNT - 1))
2409 return 0;
2410
2411 cyc_count = chip->cyc_ctr.count[bucket];
2412 cyc_count++;
2413 data[0] = cyc_count & 0xFF;
2414 data[1] = cyc_count >> 8;
2415
2416 rc = fg_sram_write(chip, CYCLE_COUNT_WORD + (bucket / 2),
2417 CYCLE_COUNT_OFFSET + (bucket % 2) * 2, data, 2,
2418 FG_IMA_DEFAULT);
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002419 if (rc < 0) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002420 pr_err("failed to write BATT_CYCLE[%d] rc=%d\n",
2421 bucket, rc);
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002422 return rc;
2423 }
2424
2425 chip->cyc_ctr.count[bucket] = cyc_count;
2426 fg_dbg(chip, FG_STATUS, "Stored count %d in bucket %d\n", cyc_count,
2427 bucket);
2428
Nicholas Troaste29dec92016-08-24 09:35:11 -07002429 return rc;
2430}
2431
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002432static void fg_cycle_counter_update(struct fg_chip *chip)
Nicholas Troaste29dec92016-08-24 09:35:11 -07002433{
2434 int rc = 0, bucket, i, batt_soc;
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002435
2436 if (!chip->cyc_ctr.en)
2437 return;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002438
2439 mutex_lock(&chip->cyc_ctr.lock);
2440 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
2441 if (rc < 0) {
2442 pr_err("Failed to read battery soc rc: %d\n", rc);
2443 goto out;
2444 }
2445
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002446 /* We need only the most significant byte here */
2447 batt_soc = (u32)batt_soc >> 24;
2448
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002449 /* Find out which bucket the SOC falls in */
2450 bucket = batt_soc / BUCKET_SOC_PCT;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002451
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002452 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002453 if (!chip->cyc_ctr.started[bucket]) {
2454 chip->cyc_ctr.started[bucket] = true;
2455 chip->cyc_ctr.last_soc[bucket] = batt_soc;
2456 }
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002457 } else if (chip->charge_done || !is_input_present(chip)) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002458 for (i = 0; i < BUCKET_COUNT; i++) {
2459 if (chip->cyc_ctr.started[i] &&
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002460 batt_soc > chip->cyc_ctr.last_soc[i] + 2) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002461 rc = fg_inc_store_cycle_ctr(chip, i);
2462 if (rc < 0)
2463 pr_err("Error in storing cycle_ctr rc: %d\n",
2464 rc);
2465 chip->cyc_ctr.last_soc[i] = 0;
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002466 chip->cyc_ctr.started[i] = false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002467 }
Nicholas Troaste29dec92016-08-24 09:35:11 -07002468 }
2469 }
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002470
2471 fg_dbg(chip, FG_STATUS, "batt_soc: %d bucket: %d chg_status: %d\n",
2472 batt_soc, bucket, chip->charge_status);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002473out:
2474 mutex_unlock(&chip->cyc_ctr.lock);
2475}
2476
2477static int fg_get_cycle_count(struct fg_chip *chip)
2478{
2479 int count;
2480
2481 if (!chip->cyc_ctr.en)
2482 return 0;
2483
2484 if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT))
2485 return -EINVAL;
2486
2487 mutex_lock(&chip->cyc_ctr.lock);
2488 count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1];
2489 mutex_unlock(&chip->cyc_ctr.lock);
2490 return count;
2491}
2492
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002493static void status_change_work(struct work_struct *work)
2494{
2495 struct fg_chip *chip = container_of(work,
2496 struct fg_chip, status_change_work);
2497 union power_supply_propval prop = {0, };
2498 int rc, batt_temp;
2499
2500 if (!batt_psy_initialized(chip)) {
2501 fg_dbg(chip, FG_STATUS, "Charger not available?!\n");
2502 goto out;
2503 }
2504
2505 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS,
2506 &prop);
2507 if (rc < 0) {
2508 pr_err("Error in getting charging status, rc=%d\n", rc);
2509 goto out;
2510 }
2511
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002512 chip->charge_status = prop.intval;
2513 rc = power_supply_get_property(chip->batt_psy,
2514 POWER_SUPPLY_PROP_CHARGE_TYPE, &prop);
2515 if (rc < 0) {
2516 pr_err("Error in getting charge type, rc=%d\n", rc);
2517 goto out;
2518 }
2519
2520 chip->charge_type = prop.intval;
2521 rc = power_supply_get_property(chip->batt_psy,
2522 POWER_SUPPLY_PROP_CHARGE_DONE, &prop);
2523 if (rc < 0) {
2524 pr_err("Error in getting charge_done, rc=%d\n", rc);
2525 goto out;
2526 }
2527
2528 chip->charge_done = prop.intval;
2529 fg_cycle_counter_update(chip);
2530 fg_cap_learning_update(chip);
2531
2532 rc = fg_charge_full_update(chip);
2533 if (rc < 0)
2534 pr_err("Error in charge_full_update, rc=%d\n", rc);
2535
2536 rc = fg_adjust_recharge_soc(chip);
2537 if (rc < 0)
2538 pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
2539
Subbaraman Narayanamurthyfdca8c22017-08-04 12:25:49 -07002540 rc = fg_adjust_recharge_voltage(chip);
2541 if (rc < 0)
2542 pr_err("Error in adjusting recharge_voltage, rc=%d\n", rc);
2543
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07002544 rc = fg_adjust_ki_coeff_dischg(chip);
2545 if (rc < 0)
2546 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
2547
2548 rc = fg_esr_fcc_config(chip);
2549 if (rc < 0)
2550 pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);
2551
2552 rc = fg_get_battery_temp(chip, &batt_temp);
2553 if (!rc) {
2554 rc = fg_slope_limit_config(chip, batt_temp);
2555 if (rc < 0)
2556 pr_err("Error in configuring slope limiter rc:%d\n",
2557 rc);
2558
2559 rc = fg_adjust_ki_coeff_full_soc(chip, batt_temp);
2560 if (rc < 0)
2561 pr_err("Error in configuring ki_coeff_full_soc rc:%d\n",
2562 rc);
2563 }
2564
2565 fg_ttf_update(chip);
2566
2567out:
2568 fg_dbg(chip, FG_POWER_SUPPLY, "charge_status:%d charge_type:%d charge_done:%d\n",
2569 chip->charge_status, chip->charge_type, chip->charge_done);
2570 pm_relax(chip->dev);
2571}
2572
Subbaraman Narayanamurthy3a0d1732017-03-27 14:05:51 -07002573static int fg_bp_params_config(struct fg_chip *chip)
2574{
2575 int rc = 0;
2576 u8 buf;
2577
2578 /* This SRAM register is only present in v2.0 and above */
2579 if (!(chip->wa_flags & PMI8998_V1_REV_WA) &&
2580 chip->bp.float_volt_uv > 0) {
2581 fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT,
2582 chip->bp.float_volt_uv / 1000, &buf);
2583 rc = fg_sram_write(chip, chip->sp[FG_SRAM_FLOAT_VOLT].addr_word,
2584 chip->sp[FG_SRAM_FLOAT_VOLT].addr_byte, &buf,
2585 chip->sp[FG_SRAM_FLOAT_VOLT].len, FG_IMA_DEFAULT);
2586 if (rc < 0) {
2587 pr_err("Error in writing float_volt, rc=%d\n", rc);
2588 return rc;
2589 }
2590 }
2591
2592 if (chip->bp.vbatt_full_mv > 0) {
2593 rc = fg_set_constant_chg_voltage(chip,
2594 chip->bp.vbatt_full_mv * 1000);
2595 if (rc < 0)
2596 return rc;
2597 }
2598
2599 return rc;
2600}
2601
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07002602#define PROFILE_LOAD_BIT BIT(0)
2603#define BOOTLOADER_LOAD_BIT BIT(1)
2604#define BOOTLOADER_RESTART_BIT BIT(2)
2605#define HLOS_RESTART_BIT BIT(3)
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002606static bool is_profile_load_required(struct fg_chip *chip)
2607{
Nicholas Troaste29dec92016-08-24 09:35:11 -07002608 u8 buf[PROFILE_COMP_LEN], val;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002609 bool profiles_same = false;
2610 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002611
Nicholas Troaste29dec92016-08-24 09:35:11 -07002612 rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
2613 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
2614 if (rc < 0) {
2615 pr_err("failed to read profile integrity rc=%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002616 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002617 }
2618
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002619 /* Check if integrity bit is set */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07002620 if (val & PROFILE_LOAD_BIT) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07002621 fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
Subbaraman Narayanamurthy73616e12017-03-20 14:37:54 -07002622
2623 /* Whitelist the values */
2624 val &= ~PROFILE_LOAD_BIT;
2625 if (val != HLOS_RESTART_BIT && val != BOOTLOADER_LOAD_BIT &&
2626 val != (BOOTLOADER_LOAD_BIT | BOOTLOADER_RESTART_BIT)) {
2627 val |= PROFILE_LOAD_BIT;
2628 pr_warn("Garbage value in profile integrity word: 0x%x\n",
2629 val);
2630 return true;
2631 }
2632
Nicholas Troaste29dec92016-08-24 09:35:11 -07002633 rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
2634 buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
2635 if (rc < 0) {
2636 pr_err("Error in reading battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002637 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002638 }
2639 profiles_same = memcmp(chip->batt_profile, buf,
2640 PROFILE_COMP_LEN) == 0;
2641 if (profiles_same) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002642 fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
2643 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002644 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002645
2646 if (!chip->dt.force_load_profile) {
2647 pr_warn("Profiles doesn't match, skipping loading it since force_load_profile is disabled\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002648 if (fg_profile_dump) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002649 pr_info("FG: loaded profile:\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002650 dump_sram(buf, PROFILE_LOAD_WORD,
2651 PROFILE_COMP_LEN);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002652 pr_info("FG: available profile:\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002653 dump_sram(chip->batt_profile, PROFILE_LOAD_WORD,
2654 PROFILE_LEN);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002655 }
2656 return false;
2657 }
2658
2659 fg_dbg(chip, FG_STATUS, "Profiles are different, loading the correct one\n");
2660 } else {
2661 fg_dbg(chip, FG_STATUS, "Profile integrity bit is not set\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002662 if (fg_profile_dump) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002663 pr_info("FG: profile to be loaded:\n");
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002664 dump_sram(chip->batt_profile, PROFILE_LOAD_WORD,
2665 PROFILE_LEN);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002666 }
Nicholas Troaste29dec92016-08-24 09:35:11 -07002667 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002668 return true;
2669}
2670
Subbaraman Narayanamurthy76cce8d2016-12-22 15:09:38 -08002671static void clear_battery_profile(struct fg_chip *chip)
2672{
2673 u8 val = 0;
2674 int rc;
2675
2676 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
2677 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
2678 if (rc < 0)
2679 pr_err("failed to write profile integrity rc=%d\n", rc);
2680}
2681
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002682#define SOC_READY_WAIT_MS 2000
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002683static int __fg_restart(struct fg_chip *chip)
2684{
2685 int rc, msoc;
2686 bool tried_again = false;
2687
2688 rc = fg_get_prop_capacity(chip, &msoc);
2689 if (rc < 0) {
2690 pr_err("Error in getting capacity, rc=%d\n", rc);
2691 return rc;
2692 }
2693
2694 chip->last_soc = msoc;
2695 chip->fg_restarting = true;
2696 reinit_completion(&chip->soc_ready);
2697 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT,
2698 RESTART_GO_BIT);
2699 if (rc < 0) {
2700 pr_err("Error in writing to %04x, rc=%d\n",
2701 BATT_SOC_RESTART(chip), rc);
2702 goto out;
2703 }
2704
2705wait:
2706 rc = wait_for_completion_interruptible_timeout(&chip->soc_ready,
2707 msecs_to_jiffies(SOC_READY_WAIT_MS));
2708
2709 /* If we were interrupted wait again one more time. */
2710 if (rc == -ERESTARTSYS && !tried_again) {
2711 tried_again = true;
2712 goto wait;
2713 } else if (rc <= 0) {
2714 pr_err("wait for soc_ready timed out rc=%d\n", rc);
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002715 }
2716
2717 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
2718 if (rc < 0) {
2719 pr_err("Error in writing to %04x, rc=%d\n",
2720 BATT_SOC_RESTART(chip), rc);
2721 goto out;
2722 }
2723out:
2724 chip->fg_restarting = false;
2725 return rc;
2726}
2727
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002728static void profile_load_work(struct work_struct *work)
2729{
2730 struct fg_chip *chip = container_of(work,
2731 struct fg_chip,
2732 profile_load_work.work);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002733 u8 buf[2], val;
2734 int rc;
2735
2736 vote(chip->awake_votable, PROFILE_LOAD, true, 0);
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -07002737
2738 rc = fg_get_batt_id(chip);
2739 if (rc < 0) {
2740 pr_err("Error in getting battery id, rc:%d\n", rc);
2741 goto out;
2742 }
2743
2744 rc = fg_get_batt_profile(chip);
2745 if (rc < 0) {
2746 pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
2747 chip->batt_id_ohms / 1000, rc);
2748 goto out;
2749 }
2750
2751 if (!chip->profile_available)
2752 goto out;
2753
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002754 if (!is_profile_load_required(chip))
2755 goto done;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002756
2757 clear_cycle_counter(chip);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002758 mutex_lock(&chip->cl.lock);
2759 chip->cl.learned_cc_uah = 0;
2760 chip->cl.active = false;
2761 mutex_unlock(&chip->cl.lock);
2762
Nicholas Troaste29dec92016-08-24 09:35:11 -07002763 fg_dbg(chip, FG_STATUS, "profile loading started\n");
2764 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
2765 if (rc < 0) {
2766 pr_err("Error in writing to %04x, rc=%d\n",
2767 BATT_SOC_RESTART(chip), rc);
2768 goto out;
2769 }
2770
2771 /* load battery profile */
2772 rc = fg_sram_write(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
2773 chip->batt_profile, PROFILE_LEN, FG_IMA_ATOMIC);
2774 if (rc < 0) {
2775 pr_err("Error in writing battery profile, rc:%d\n", rc);
2776 goto out;
2777 }
2778
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002779 rc = __fg_restart(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002780 if (rc < 0) {
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002781 pr_err("Error in restarting FG, rc=%d\n", rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002782 goto out;
2783 }
2784
2785 fg_dbg(chip, FG_STATUS, "SOC is ready\n");
2786
2787 /* Set the profile integrity bit */
Subbaraman Narayanamurthy402a6722016-10-26 18:12:10 -07002788 val = HLOS_RESTART_BIT | PROFILE_LOAD_BIT;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002789 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
2790 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
2791 if (rc < 0) {
2792 pr_err("failed to write profile integrity rc=%d\n", rc);
2793 goto out;
2794 }
2795
Nicholas Troaste29dec92016-08-24 09:35:11 -07002796done:
Subbaraman Narayanamurthy3a0d1732017-03-27 14:05:51 -07002797 rc = fg_bp_params_config(chip);
2798 if (rc < 0)
2799 pr_err("Error in configuring battery profile params, rc:%d\n",
2800 rc);
2801
Nicholas Troaste29dec92016-08-24 09:35:11 -07002802 rc = fg_sram_read(chip, NOM_CAP_WORD, NOM_CAP_OFFSET, buf, 2,
2803 FG_IMA_DEFAULT);
2804 if (rc < 0) {
2805 pr_err("Error in reading %04x[%d] rc=%d\n", NOM_CAP_WORD,
2806 NOM_CAP_OFFSET, rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002807 } else {
2808 chip->cl.nom_cap_uah = (int)(buf[0] | buf[1] << 8) * 1000;
2809 rc = fg_load_learned_cap_from_sram(chip);
2810 if (rc < 0)
2811 pr_err("Error in loading capacity learning data, rc:%d\n",
2812 rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002813 }
2814
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08002815 batt_psy_initialized(chip);
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07002816 fg_notify_charger(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002817 chip->profile_loaded = true;
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002818 fg_dbg(chip, FG_STATUS, "profile loaded successfully");
Nicholas Troaste29dec92016-08-24 09:35:11 -07002819out:
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -07002820 chip->soc_reporting_ready = true;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002821 vote(chip->awake_votable, PROFILE_LOAD, false, 0);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002822}
2823
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002824static void sram_dump_work(struct work_struct *work)
2825{
2826 struct fg_chip *chip = container_of(work, struct fg_chip,
2827 sram_dump_work.work);
2828 u8 buf[FG_SRAM_LEN];
2829 int rc;
Tirupathi Reddyce65d002017-02-10 18:06:40 +05302830 s64 timestamp_ms, quotient;
2831 s32 remainder;
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002832
2833 rc = fg_sram_read(chip, 0, 0, buf, FG_SRAM_LEN, FG_IMA_DEFAULT);
2834 if (rc < 0) {
2835 pr_err("Error in reading FG SRAM, rc:%d\n", rc);
2836 goto resched;
2837 }
2838
2839 timestamp_ms = ktime_to_ms(ktime_get_boottime());
Tirupathi Reddyce65d002017-02-10 18:06:40 +05302840 quotient = div_s64_rem(timestamp_ms, 1000, &remainder);
2841 fg_dbg(chip, FG_STATUS, "SRAM Dump Started at %lld.%d\n",
2842 quotient, remainder);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002843 dump_sram(buf, 0, FG_SRAM_LEN);
2844 timestamp_ms = ktime_to_ms(ktime_get_boottime());
Tirupathi Reddyce65d002017-02-10 18:06:40 +05302845 quotient = div_s64_rem(timestamp_ms, 1000, &remainder);
2846 fg_dbg(chip, FG_STATUS, "SRAM Dump done at %lld.%d\n",
2847 quotient, remainder);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08002848resched:
2849 schedule_delayed_work(&chip->sram_dump_work,
2850 msecs_to_jiffies(fg_sram_dump_period_ms));
2851}
2852
2853static int fg_sram_dump_sysfs(const char *val, const struct kernel_param *kp)
2854{
2855 int rc;
2856 struct power_supply *bms_psy;
2857 struct fg_chip *chip;
2858 bool old_val = fg_sram_dump;
2859
2860 rc = param_set_bool(val, kp);
2861 if (rc) {
2862 pr_err("Unable to set fg_sram_dump: %d\n", rc);
2863 return rc;
2864 }
2865
2866 if (fg_sram_dump == old_val)
2867 return 0;
2868
2869 bms_psy = power_supply_get_by_name("bms");
2870 if (!bms_psy) {
2871 pr_err("bms psy not found\n");
2872 return -ENODEV;
2873 }
2874
2875 chip = power_supply_get_drvdata(bms_psy);
2876 if (fg_sram_dump)
2877 schedule_delayed_work(&chip->sram_dump_work,
2878 msecs_to_jiffies(fg_sram_dump_period_ms));
2879 else
2880 cancel_delayed_work_sync(&chip->sram_dump_work);
2881
2882 return 0;
2883}
2884
2885static struct kernel_param_ops fg_sram_dump_ops = {
2886 .set = fg_sram_dump_sysfs,
2887 .get = param_get_bool,
2888};
2889
2890module_param_cb(sram_dump_en, &fg_sram_dump_ops, &fg_sram_dump, 0644);
2891
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07002892static int fg_restart_sysfs(const char *val, const struct kernel_param *kp)
2893{
2894 int rc;
2895 struct power_supply *bms_psy;
2896 struct fg_chip *chip;
2897
2898 rc = param_set_int(val, kp);
2899 if (rc) {
2900 pr_err("Unable to set fg_restart: %d\n", rc);
2901 return rc;
2902 }
2903
2904 if (fg_restart != 1) {
2905 pr_err("Bad value %d\n", fg_restart);
2906 return -EINVAL;
2907 }
2908
2909 bms_psy = power_supply_get_by_name("bms");
2910 if (!bms_psy) {
2911 pr_err("bms psy not found\n");
2912 return 0;
2913 }
2914
2915 chip = power_supply_get_drvdata(bms_psy);
2916 rc = __fg_restart(chip);
2917 if (rc < 0) {
2918 pr_err("Error in restarting FG, rc=%d\n", rc);
2919 return rc;
2920 }
2921
2922 pr_info("FG restart done\n");
2923 return rc;
2924}
2925
2926static struct kernel_param_ops fg_restart_ops = {
2927 .set = fg_restart_sysfs,
2928 .get = param_get_int,
2929};
2930
2931module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
2932
Nicholas Troast1769fd32016-09-07 09:20:58 -07002933#define HOURS_TO_SECONDS 3600
2934#define OCV_SLOPE_UV 10869
2935#define MILLI_UNIT 1000
2936#define MICRO_UNIT 1000000
Nicholas Troast805c2422017-07-06 14:53:46 -07002937#define NANO_UNIT 1000000000
2938static int fg_get_time_to_full_locked(struct fg_chip *chip, int *val)
Nicholas Troast1769fd32016-09-07 09:20:58 -07002939{
Nicholas Troast805c2422017-07-06 14:53:46 -07002940 int rc, ibatt_avg, vbatt_avg, rbatt, msoc, full_soc, act_cap_mah,
Nicholas Troastb8cb40c2017-06-21 11:10:40 -07002941 i_cc2cv = 0, soc_cc2cv, tau, divisor, iterm, ttf_mode,
2942 i, soc_per_step, msoc_this_step, msoc_next_step,
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07002943 ibatt_this_step, t_predicted_this_step, ttf_slope,
Nicholas Troast805c2422017-07-06 14:53:46 -07002944 t_predicted_cv, t_predicted = 0;
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07002945 s64 delta_ms;
Nicholas Troast1769fd32016-09-07 09:20:58 -07002946
Subbaraman Narayanamurthy476e8372017-08-25 13:38:36 -07002947 if (!chip->soc_reporting_ready)
2948 return -ENODATA;
2949
Nicholas Troast1769fd32016-09-07 09:20:58 -07002950 if (chip->bp.float_volt_uv <= 0) {
2951 pr_err("battery profile is not loaded\n");
2952 return -ENODATA;
2953 }
2954
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08002955 if (!batt_psy_initialized(chip)) {
Nicholas Troast1769fd32016-09-07 09:20:58 -07002956 fg_dbg(chip, FG_TTF, "charger is not available\n");
2957 return -ENODATA;
2958 }
2959
Nicholas Troast32a22d32016-12-14 16:12:04 -08002960 rc = fg_get_prop_capacity(chip, &msoc);
2961 if (rc < 0) {
2962 pr_err("failed to get msoc rc=%d\n", rc);
2963 return rc;
2964 }
2965 fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc);
2966
Nicholas Troast805c2422017-07-06 14:53:46 -07002967 /* the battery is considered full if the SOC is 100% */
Nicholas Troast32a22d32016-12-14 16:12:04 -08002968 if (msoc >= 100) {
Nicholas Troast1769fd32016-09-07 09:20:58 -07002969 *val = 0;
2970 return 0;
2971 }
2972
Nicholas Troastb8cb40c2017-06-21 11:10:40 -07002973 if (is_qnovo_en(chip))
2974 ttf_mode = TTF_MODE_QNOVO;
2975 else
2976 ttf_mode = TTF_MODE_NORMAL;
2977
2978 /* when switching TTF algorithms the TTF needs to be reset */
2979 if (chip->ttf.mode != ttf_mode) {
2980 fg_circ_buf_clr(&chip->ttf.ibatt);
2981 fg_circ_buf_clr(&chip->ttf.vbatt);
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07002982 chip->ttf.last_ttf = 0;
2983 chip->ttf.last_ms = 0;
Nicholas Troastb8cb40c2017-06-21 11:10:40 -07002984 chip->ttf.mode = ttf_mode;
2985 }
2986
Nicholas Troast805c2422017-07-06 14:53:46 -07002987 /* at least 10 samples are required to produce a stable IBATT */
2988 if (chip->ttf.ibatt.size < 10) {
2989 *val = -1;
2990 return 0;
Nicholas Troast1769fd32016-09-07 09:20:58 -07002991 }
2992
Nicholas Troast805c2422017-07-06 14:53:46 -07002993 rc = fg_circ_buf_median(&chip->ttf.ibatt, &ibatt_avg);
Nicholas Troast1769fd32016-09-07 09:20:58 -07002994 if (rc < 0) {
Nicholas Troast805c2422017-07-06 14:53:46 -07002995 pr_err("failed to get IBATT AVG rc=%d\n", rc);
2996 return rc;
Nicholas Troast1769fd32016-09-07 09:20:58 -07002997 }
2998
Nicholas Troast805c2422017-07-06 14:53:46 -07002999 rc = fg_circ_buf_median(&chip->ttf.vbatt, &vbatt_avg);
3000 if (rc < 0) {
3001 pr_err("failed to get VBATT AVG rc=%d\n", rc);
3002 return rc;
3003 }
Nicholas Troast1769fd32016-09-07 09:20:58 -07003004
Nicholas Troast805c2422017-07-06 14:53:46 -07003005 ibatt_avg = -ibatt_avg / MILLI_UNIT;
3006 vbatt_avg /= MILLI_UNIT;
3007
3008 /* clamp ibatt_avg to iterm */
3009 if (ibatt_avg < abs(chip->dt.sys_term_curr_ma))
3010 ibatt_avg = abs(chip->dt.sys_term_curr_ma);
3011
Nicholas Troast1769fd32016-09-07 09:20:58 -07003012 fg_dbg(chip, FG_TTF, "ibatt_avg=%d\n", ibatt_avg);
Nicholas Troast805c2422017-07-06 14:53:46 -07003013 fg_dbg(chip, FG_TTF, "vbatt_avg=%d\n", vbatt_avg);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003014
3015 rc = fg_get_battery_resistance(chip, &rbatt);
3016 if (rc < 0) {
3017 pr_err("failed to get battery resistance rc=%d\n", rc);
3018 return rc;
3019 }
3020
Nicholas Troast805c2422017-07-06 14:53:46 -07003021 rbatt /= MILLI_UNIT;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003022 fg_dbg(chip, FG_TTF, "rbatt=%d\n", rbatt);
3023
Nicholas Troast805c2422017-07-06 14:53:46 -07003024 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003025 if (rc < 0) {
3026 pr_err("failed to get ACT_BATT_CAP rc=%d\n", rc);
3027 return rc;
3028 }
Nicholas Troast1769fd32016-09-07 09:20:58 -07003029
Nicholas Troast1769fd32016-09-07 09:20:58 -07003030 rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc);
3031 if (rc < 0) {
3032 pr_err("failed to get full soc rc=%d\n", rc);
3033 return rc;
3034 }
3035 full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY,
3036 FULL_SOC_RAW);
Nicholas Troast805c2422017-07-06 14:53:46 -07003037 act_cap_mah = full_soc * act_cap_mah / 100;
3038 fg_dbg(chip, FG_TTF, "act_cap_mah=%d\n", act_cap_mah);
3039
3040 /* estimated battery current at the CC to CV transition */
3041 switch (chip->ttf.mode) {
3042 case TTF_MODE_NORMAL:
3043 i_cc2cv = ibatt_avg * vbatt_avg /
3044 max(MILLI_UNIT, chip->bp.float_volt_uv / MILLI_UNIT);
3045 break;
Nicholas Troastb8cb40c2017-06-21 11:10:40 -07003046 case TTF_MODE_QNOVO:
3047 i_cc2cv = min(
3048 chip->ttf.cc_step.arr[MAX_CC_STEPS - 1] / MILLI_UNIT,
3049 ibatt_avg * vbatt_avg /
3050 max(MILLI_UNIT, chip->bp.float_volt_uv / MILLI_UNIT));
3051 break;
Nicholas Troast805c2422017-07-06 14:53:46 -07003052 default:
3053 pr_err("TTF mode %d is not supported\n", chip->ttf.mode);
3054 break;
3055 }
3056 fg_dbg(chip, FG_TTF, "i_cc2cv=%d\n", i_cc2cv);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003057
3058 /* if we are already in CV state then we can skip estimating CC */
3059 if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
Nicholas Troast805c2422017-07-06 14:53:46 -07003060 goto cv_estimate;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003061
Nicholas Troast1769fd32016-09-07 09:20:58 -07003062 /* estimated SOC at the CC to CV transition */
Nicholas Troast805c2422017-07-06 14:53:46 -07003063 soc_cc2cv = DIV_ROUND_CLOSEST(rbatt * i_cc2cv, OCV_SLOPE_UV);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003064 soc_cc2cv = 100 - soc_cc2cv;
3065 fg_dbg(chip, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv);
3066
Nicholas Troast805c2422017-07-06 14:53:46 -07003067 switch (chip->ttf.mode) {
3068 case TTF_MODE_NORMAL:
3069 if (soc_cc2cv - msoc <= 0)
3070 goto cv_estimate;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003071
Nicholas Troast805c2422017-07-06 14:53:46 -07003072 divisor = max(100, (ibatt_avg + i_cc2cv) / 2 * 100);
3073 t_predicted = div_s64((s64)act_cap_mah * (soc_cc2cv - msoc) *
3074 HOURS_TO_SECONDS, divisor);
3075 break;
Nicholas Troastb8cb40c2017-06-21 11:10:40 -07003076 case TTF_MODE_QNOVO:
3077 soc_per_step = 100 / MAX_CC_STEPS;
3078 for (i = msoc / soc_per_step; i < MAX_CC_STEPS - 1; ++i) {
3079 msoc_next_step = (i + 1) * soc_per_step;
3080 if (i == msoc / soc_per_step)
3081 msoc_this_step = msoc;
3082 else
3083 msoc_this_step = i * soc_per_step;
3084
3085 /* scale ibatt by 85% to account for discharge pulses */
3086 ibatt_this_step = min(
3087 chip->ttf.cc_step.arr[i] / MILLI_UNIT,
3088 ibatt_avg) * 85 / 100;
3089 divisor = max(100, ibatt_this_step * 100);
3090 t_predicted_this_step = div_s64((s64)act_cap_mah *
3091 (msoc_next_step - msoc_this_step) *
3092 HOURS_TO_SECONDS, divisor);
3093 t_predicted += t_predicted_this_step;
3094 fg_dbg(chip, FG_TTF, "[%d, %d] ma=%d t=%d\n",
3095 msoc_this_step, msoc_next_step,
3096 ibatt_this_step, t_predicted_this_step);
3097 }
3098 break;
Nicholas Troast805c2422017-07-06 14:53:46 -07003099 default:
3100 pr_err("TTF mode %d is not supported\n", chip->ttf.mode);
3101 break;
3102 }
Nicholas Troast1769fd32016-09-07 09:20:58 -07003103
Nicholas Troast805c2422017-07-06 14:53:46 -07003104cv_estimate:
3105 fg_dbg(chip, FG_TTF, "t_predicted_cc=%d\n", t_predicted);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003106
Nicholas Troast805c2422017-07-06 14:53:46 -07003107 iterm = max(100, abs(chip->dt.sys_term_curr_ma) + 200);
3108 fg_dbg(chip, FG_TTF, "iterm=%d\n", iterm);
3109
3110 if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
3111 tau = max(MILLI_UNIT, ibatt_avg * MILLI_UNIT / iterm);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003112 else
Nicholas Troast805c2422017-07-06 14:53:46 -07003113 tau = max(MILLI_UNIT, i_cc2cv * MILLI_UNIT / iterm);
Nicholas Troastde5d42f2017-01-20 16:47:31 -08003114
Nicholas Troast805c2422017-07-06 14:53:46 -07003115 rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), tau, &tau);
3116 if (rc < 0) {
3117 pr_err("failed to interpolate tau rc=%d\n", rc);
3118 return rc;
3119 }
Nicholas Troast1769fd32016-09-07 09:20:58 -07003120
Nicholas Troast805c2422017-07-06 14:53:46 -07003121 /* tau is scaled linearly from 95% to 100% SOC */
3122 if (msoc >= 95)
3123 tau = tau * 2 * (100 - msoc) / 10;
3124
3125 fg_dbg(chip, FG_TTF, "tau=%d\n", tau);
3126 t_predicted_cv = div_s64((s64)act_cap_mah * rbatt * tau *
3127 HOURS_TO_SECONDS, NANO_UNIT);
3128 fg_dbg(chip, FG_TTF, "t_predicted_cv=%d\n", t_predicted_cv);
3129 t_predicted += t_predicted_cv;
3130
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07003131 fg_dbg(chip, FG_TTF, "t_predicted_prefilter=%d\n", t_predicted);
3132 if (chip->ttf.last_ms != 0) {
3133 delta_ms = ktime_ms_delta(ktime_get_boottime(),
3134 ms_to_ktime(chip->ttf.last_ms));
3135 if (delta_ms > 10000) {
3136 ttf_slope = div64_s64(
3137 (s64)(t_predicted - chip->ttf.last_ttf) *
3138 MICRO_UNIT, delta_ms);
3139 if (ttf_slope > -100)
3140 ttf_slope = -100;
3141 else if (ttf_slope < -2000)
3142 ttf_slope = -2000;
3143
3144 t_predicted = div_s64(
3145 (s64)ttf_slope * delta_ms, MICRO_UNIT) +
3146 chip->ttf.last_ttf;
3147 fg_dbg(chip, FG_TTF, "ttf_slope=%d\n", ttf_slope);
3148 } else {
3149 t_predicted = chip->ttf.last_ttf;
3150 }
3151 }
3152
Nicholas Troast805c2422017-07-06 14:53:46 -07003153 /* clamp the ttf to 0 */
3154 if (t_predicted < 0)
3155 t_predicted = 0;
3156
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07003157 fg_dbg(chip, FG_TTF, "t_predicted_postfilter=%d\n", t_predicted);
Nicholas Troast805c2422017-07-06 14:53:46 -07003158 *val = t_predicted;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003159 return 0;
3160}
3161
Nicholas Troast805c2422017-07-06 14:53:46 -07003162static int fg_get_time_to_full(struct fg_chip *chip, int *val)
3163{
3164 int rc;
3165
3166 mutex_lock(&chip->ttf.lock);
3167 rc = fg_get_time_to_full_locked(chip, val);
3168 mutex_unlock(&chip->ttf.lock);
3169 return rc;
3170}
3171
Nicholas Troast1769fd32016-09-07 09:20:58 -07003172#define CENTI_ICORRECT_C0 105
3173#define CENTI_ICORRECT_C1 20
3174static int fg_get_time_to_empty(struct fg_chip *chip, int *val)
3175{
Nicholas Troast805c2422017-07-06 14:53:46 -07003176 int rc, ibatt_avg, msoc, full_soc, act_cap_mah, divisor;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003177
Nicholas Troast805c2422017-07-06 14:53:46 -07003178 rc = fg_circ_buf_median(&chip->ttf.ibatt, &ibatt_avg);
Nicholas Troast1769fd32016-09-07 09:20:58 -07003179 if (rc < 0) {
3180 /* try to get instantaneous current */
3181 rc = fg_get_battery_current(chip, &ibatt_avg);
3182 if (rc < 0) {
3183 pr_err("failed to get battery current, rc=%d\n", rc);
3184 return rc;
3185 }
3186 }
3187
Nicholas Troast805c2422017-07-06 14:53:46 -07003188 ibatt_avg /= MILLI_UNIT;
3189 /* clamp ibatt_avg to 100mA */
3190 if (ibatt_avg < 100)
3191 ibatt_avg = 100;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003192
3193 rc = fg_get_prop_capacity(chip, &msoc);
3194 if (rc < 0) {
3195 pr_err("Error in getting capacity, rc=%d\n", rc);
3196 return rc;
3197 }
3198
Nicholas Troast805c2422017-07-06 14:53:46 -07003199 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
3200 if (rc < 0) {
3201 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
3202 return rc;
3203 }
Nicholas Troast1769fd32016-09-07 09:20:58 -07003204
Nicholas Troast805c2422017-07-06 14:53:46 -07003205 rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc);
3206 if (rc < 0) {
3207 pr_err("failed to get full soc rc=%d\n", rc);
3208 return rc;
3209 }
3210 full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY,
3211 FULL_SOC_RAW);
3212 act_cap_mah = full_soc * act_cap_mah / 100;
3213
3214 divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc;
3215 divisor = ibatt_avg * divisor / 100;
3216 divisor = max(100, divisor);
3217 *val = act_cap_mah * msoc * HOURS_TO_SECONDS / divisor;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003218 return 0;
3219}
3220
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08003221static int fg_update_maint_soc(struct fg_chip *chip)
3222{
3223 int rc = 0, msoc;
3224
Subbaraman Narayanamurthy50fb7fd2017-07-25 20:01:25 -07003225 if (!chip->dt.linearize_soc)
3226 return 0;
3227
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08003228 mutex_lock(&chip->charge_full_lock);
3229 if (chip->delta_soc <= 0)
3230 goto out;
3231
3232 rc = fg_get_msoc(chip, &msoc);
3233 if (rc < 0) {
3234 pr_err("Error in getting msoc, rc=%d\n", rc);
3235 goto out;
3236 }
3237
3238 if (msoc > chip->maint_soc) {
3239 /*
3240 * When the monotonic SOC goes above maintenance SOC, we should
3241 * stop showing the maintenance SOC.
3242 */
3243 chip->delta_soc = 0;
3244 chip->maint_soc = 0;
3245 } else if (msoc <= chip->last_msoc) {
3246 /* MSOC is decreasing. Decrease maintenance SOC as well */
3247 chip->maint_soc -= 1;
3248 if (!(msoc % 10)) {
3249 /*
3250 * Reduce the maintenance SOC additionally by 1 whenever
3251 * it crosses a SOC multiple of 10.
3252 */
3253 chip->maint_soc -= 1;
3254 chip->delta_soc -= 1;
3255 }
3256 }
3257
3258 fg_dbg(chip, FG_IRQ, "msoc: %d last_msoc: %d maint_soc: %d delta_soc: %d\n",
3259 msoc, chip->last_msoc, chip->maint_soc, chip->delta_soc);
3260 chip->last_msoc = msoc;
3261out:
3262 mutex_unlock(&chip->charge_full_lock);
3263 return rc;
3264}
3265
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -08003266static int fg_esr_validate(struct fg_chip *chip)
3267{
3268 int rc, esr_uohms;
3269 u8 buf[2];
3270
3271 if (chip->dt.esr_clamp_mohms <= 0)
3272 return 0;
3273
3274 rc = fg_get_sram_prop(chip, FG_SRAM_ESR, &esr_uohms);
3275 if (rc < 0) {
3276 pr_err("failed to get ESR, rc=%d\n", rc);
3277 return rc;
3278 }
3279
3280 if (esr_uohms >= chip->dt.esr_clamp_mohms * 1000) {
3281 pr_debug("ESR %d is > ESR_clamp\n", esr_uohms);
3282 return 0;
3283 }
3284
3285 esr_uohms = chip->dt.esr_clamp_mohms * 1000;
3286 fg_encode(chip->sp, FG_SRAM_ESR, esr_uohms, buf);
3287 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR].addr_word,
3288 chip->sp[FG_SRAM_ESR].addr_byte, buf,
3289 chip->sp[FG_SRAM_ESR].len, FG_IMA_DEFAULT);
3290 if (rc < 0) {
3291 pr_err("Error in writing ESR, rc=%d\n", rc);
3292 return rc;
3293 }
3294
3295 fg_dbg(chip, FG_STATUS, "ESR clamped to %duOhms\n", esr_uohms);
3296 return 0;
3297}
3298
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003299static int fg_force_esr_meas(struct fg_chip *chip)
3300{
3301 int rc;
3302 int esr_uohms;
3303
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003304 mutex_lock(&chip->qnovo_esr_ctrl_lock);
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003305 /* force esr extraction enable */
3306 rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
3307 ESR_EXTRACTION_ENABLE_OFFSET, BIT(0), BIT(0),
3308 FG_IMA_DEFAULT);
3309 if (rc < 0) {
3310 pr_err("failed to enable esr extn rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003311 goto out;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003312 }
3313
3314 rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
3315 LD_REG_CTRL_BIT, 0);
3316 if (rc < 0) {
3317 pr_err("Error in configuring qnovo_cfg rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003318 goto out;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003319 }
3320
3321 rc = fg_masked_write(chip, BATT_INFO_TM_MISC1(chip),
3322 ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT,
3323 ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT);
3324 if (rc < 0) {
3325 pr_err("Error in configuring force ESR rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003326 goto out;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003327 }
3328
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003329 /*
3330 * Release and grab the lock again after 1.5 seconds so that prepare
3331 * callback can succeed if the request comes in between.
3332 */
3333 mutex_unlock(&chip->qnovo_esr_ctrl_lock);
3334
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003335 /* wait 1.5 seconds for hw to measure ESR */
3336 msleep(1500);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003337
3338 mutex_lock(&chip->qnovo_esr_ctrl_lock);
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003339 rc = fg_masked_write(chip, BATT_INFO_TM_MISC1(chip),
3340 ESR_REQ_CTL_BIT | ESR_REQ_CTL_EN_BIT,
3341 0);
3342 if (rc < 0) {
3343 pr_err("Error in restoring force ESR rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003344 goto out;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003345 }
3346
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003347 /* If qnovo is disabled, then leave ESR extraction enabled */
3348 if (!chip->qnovo_enable)
3349 goto done;
3350
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003351 rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
3352 LD_REG_CTRL_BIT, LD_REG_CTRL_BIT);
3353 if (rc < 0) {
3354 pr_err("Error in restoring qnovo_cfg rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003355 goto out;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003356 }
3357
3358 /* force esr extraction disable */
3359 rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
3360 ESR_EXTRACTION_ENABLE_OFFSET, BIT(0), 0,
3361 FG_IMA_DEFAULT);
3362 if (rc < 0) {
3363 pr_err("failed to disable esr extn rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003364 goto out;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003365 }
3366
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003367done:
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003368 fg_get_battery_resistance(chip, &esr_uohms);
3369 fg_dbg(chip, FG_STATUS, "ESR uohms = %d\n", esr_uohms);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003370out:
3371 mutex_unlock(&chip->qnovo_esr_ctrl_lock);
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003372 return rc;
3373}
3374
3375static int fg_prepare_for_qnovo(struct fg_chip *chip, int qnovo_enable)
3376{
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003377 int rc = 0;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003378
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003379 mutex_lock(&chip->qnovo_esr_ctrl_lock);
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003380 /* force esr extraction disable when qnovo enables */
3381 rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD,
3382 ESR_EXTRACTION_ENABLE_OFFSET,
3383 BIT(0), qnovo_enable ? 0 : BIT(0),
3384 FG_IMA_DEFAULT);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003385 if (rc < 0) {
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003386 pr_err("Error in configuring esr extraction rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003387 goto out;
3388 }
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003389
3390 rc = fg_masked_write(chip, BATT_INFO_QNOVO_CFG(chip),
3391 LD_REG_CTRL_BIT,
3392 qnovo_enable ? LD_REG_CTRL_BIT : 0);
3393 if (rc < 0) {
3394 pr_err("Error in configuring qnovo_cfg rc=%d\n", rc);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003395 goto out;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003396 }
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07003397
3398 fg_dbg(chip, FG_STATUS, "%s for Qnovo\n",
3399 qnovo_enable ? "Prepared" : "Unprepared");
3400 chip->qnovo_enable = qnovo_enable;
3401out:
3402 mutex_unlock(&chip->qnovo_esr_ctrl_lock);
3403 return rc;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003404}
Nicholas Troast805c2422017-07-06 14:53:46 -07003405
3406static void ttf_work(struct work_struct *work)
3407{
3408 struct fg_chip *chip = container_of(work, struct fg_chip,
3409 ttf_work.work);
3410 int rc, ibatt_now, vbatt_now, ttf;
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07003411 ktime_t ktime_now;
Nicholas Troast805c2422017-07-06 14:53:46 -07003412
3413 mutex_lock(&chip->ttf.lock);
3414 if (chip->charge_status != POWER_SUPPLY_STATUS_CHARGING &&
3415 chip->charge_status != POWER_SUPPLY_STATUS_DISCHARGING)
3416 goto end_work;
3417
3418 rc = fg_get_battery_current(chip, &ibatt_now);
3419 if (rc < 0) {
3420 pr_err("failed to get battery current, rc=%d\n", rc);
3421 goto end_work;
3422 }
3423
3424 rc = fg_get_battery_voltage(chip, &vbatt_now);
3425 if (rc < 0) {
3426 pr_err("failed to get battery voltage, rc=%d\n", rc);
3427 goto end_work;
3428 }
3429
3430 fg_circ_buf_add(&chip->ttf.ibatt, ibatt_now);
3431 fg_circ_buf_add(&chip->ttf.vbatt, vbatt_now);
3432
3433 if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
3434 rc = fg_get_time_to_full_locked(chip, &ttf);
3435 if (rc < 0) {
3436 pr_err("failed to get ttf, rc=%d\n", rc);
3437 goto end_work;
3438 }
3439
3440 /* keep the wake lock and prime the IBATT and VBATT buffers */
3441 if (ttf < 0) {
3442 /* delay for one FG cycle */
3443 schedule_delayed_work(&chip->ttf_work,
3444 msecs_to_jiffies(1500));
3445 mutex_unlock(&chip->ttf.lock);
3446 return;
3447 }
Nicholas Troastb8c0b9a2017-07-10 13:14:28 -07003448
3449 /* update the TTF reference point every minute */
3450 ktime_now = ktime_get_boottime();
3451 if (ktime_ms_delta(ktime_now,
3452 ms_to_ktime(chip->ttf.last_ms)) > 60000 ||
3453 chip->ttf.last_ms == 0) {
3454 chip->ttf.last_ttf = ttf;
3455 chip->ttf.last_ms = ktime_to_ms(ktime_now);
3456 }
Nicholas Troast805c2422017-07-06 14:53:46 -07003457 }
3458
3459 /* recurse every 10 seconds */
3460 schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(10000));
3461end_work:
3462 vote(chip->awake_votable, TTF_PRIMING, false, 0);
3463 mutex_unlock(&chip->ttf.lock);
3464}
3465
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003466/* PSY CALLBACKS STAY HERE */
3467
3468static int fg_psy_get_property(struct power_supply *psy,
3469 enum power_supply_property psp,
3470 union power_supply_propval *pval)
3471{
3472 struct fg_chip *chip = power_supply_get_drvdata(psy);
3473 int rc = 0;
3474
3475 switch (psp) {
3476 case POWER_SUPPLY_PROP_CAPACITY:
Subbaraman Narayanamurthye55a6aa2017-01-24 18:45:14 -08003477 rc = fg_get_prop_capacity(chip, &pval->intval);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003478 break;
Subbaraman Narayanamurthy50fb7fd2017-07-25 20:01:25 -07003479 case POWER_SUPPLY_PROP_CAPACITY_RAW:
3480 rc = fg_get_msoc_raw(chip, &pval->intval);
3481 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003482 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Subbaraman Narayanamurthye55a6aa2017-01-24 18:45:14 -08003483 if (chip->battery_missing)
3484 pval->intval = 3700000;
3485 else
3486 rc = fg_get_battery_voltage(chip, &pval->intval);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003487 break;
3488 case POWER_SUPPLY_PROP_CURRENT_NOW:
3489 rc = fg_get_battery_current(chip, &pval->intval);
3490 break;
3491 case POWER_SUPPLY_PROP_TEMP:
3492 rc = fg_get_battery_temp(chip, &pval->intval);
3493 break;
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003494 case POWER_SUPPLY_PROP_COLD_TEMP:
3495 rc = fg_get_jeita_threshold(chip, JEITA_COLD, &pval->intval);
3496 if (rc < 0) {
3497 pr_err("Error in reading jeita_cold, rc=%d\n", rc);
3498 return rc;
3499 }
3500 break;
3501 case POWER_SUPPLY_PROP_COOL_TEMP:
3502 rc = fg_get_jeita_threshold(chip, JEITA_COOL, &pval->intval);
3503 if (rc < 0) {
3504 pr_err("Error in reading jeita_cool, rc=%d\n", rc);
3505 return rc;
3506 }
3507 break;
3508 case POWER_SUPPLY_PROP_WARM_TEMP:
3509 rc = fg_get_jeita_threshold(chip, JEITA_WARM, &pval->intval);
3510 if (rc < 0) {
3511 pr_err("Error in reading jeita_warm, rc=%d\n", rc);
3512 return rc;
3513 }
3514 break;
3515 case POWER_SUPPLY_PROP_HOT_TEMP:
3516 rc = fg_get_jeita_threshold(chip, JEITA_HOT, &pval->intval);
3517 if (rc < 0) {
3518 pr_err("Error in reading jeita_hot, rc=%d\n", rc);
3519 return rc;
3520 }
3521 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003522 case POWER_SUPPLY_PROP_RESISTANCE:
3523 rc = fg_get_battery_resistance(chip, &pval->intval);
3524 break;
3525 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
3526 rc = fg_get_sram_prop(chip, FG_SRAM_OCV, &pval->intval);
3527 break;
3528 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003529 pval->intval = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003530 break;
3531 case POWER_SUPPLY_PROP_RESISTANCE_ID:
Subbaraman Narayanamurthy76cce8d2016-12-22 15:09:38 -08003532 pval->intval = chip->batt_id_ohms;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003533 break;
3534 case POWER_SUPPLY_PROP_BATTERY_TYPE:
3535 pval->strval = fg_get_battery_type(chip);
3536 break;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07003537 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
3538 pval->intval = chip->bp.float_volt_uv;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07003539 break;
Nicholas Troaste29dec92016-08-24 09:35:11 -07003540 case POWER_SUPPLY_PROP_CYCLE_COUNT:
3541 pval->intval = fg_get_cycle_count(chip);
3542 break;
3543 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
3544 pval->intval = chip->cyc_ctr.id;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07003545 break;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003546 case POWER_SUPPLY_PROP_CHARGE_NOW_RAW:
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07003547 rc = fg_get_charge_raw(chip, &pval->intval);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003548 break;
3549 case POWER_SUPPLY_PROP_CHARGE_NOW:
3550 pval->intval = chip->cl.init_cc_uah;
3551 break;
3552 case POWER_SUPPLY_PROP_CHARGE_FULL:
3553 pval->intval = chip->cl.learned_cc_uah;
3554 break;
3555 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
Subbaraman Narayanamurthydd6ea382017-03-15 13:15:31 -07003556 rc = fg_get_charge_counter(chip, &pval->intval);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003557 break;
Nicholas Troast1769fd32016-09-07 09:20:58 -07003558 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
3559 rc = fg_get_time_to_full(chip, &pval->intval);
3560 break;
3561 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
3562 rc = fg_get_time_to_empty(chip, &pval->intval);
3563 break;
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08003564 case POWER_SUPPLY_PROP_SOC_REPORTING_READY:
3565 pval->intval = chip->soc_reporting_ready;
3566 break;
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05303567 case POWER_SUPPLY_PROP_DEBUG_BATTERY:
3568 pval->intval = is_debug_batt_id(chip);
3569 break;
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -08003570 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
3571 rc = fg_get_sram_prop(chip, FG_SRAM_VBATT_FULL, &pval->intval);
3572 break;
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003573 case POWER_SUPPLY_PROP_CC_STEP:
Nicholas Troast805c2422017-07-06 14:53:46 -07003574 if ((chip->ttf.cc_step.sel >= 0) &&
3575 (chip->ttf.cc_step.sel < MAX_CC_STEPS)) {
3576 pval->intval =
3577 chip->ttf.cc_step.arr[chip->ttf.cc_step.sel];
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003578 } else {
3579 pr_err("cc_step_sel is out of bounds [0, %d]\n",
Nicholas Troast805c2422017-07-06 14:53:46 -07003580 chip->ttf.cc_step.sel);
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003581 return -EINVAL;
3582 }
3583 break;
3584 case POWER_SUPPLY_PROP_CC_STEP_SEL:
Nicholas Troast805c2422017-07-06 14:53:46 -07003585 pval->intval = chip->ttf.cc_step.sel;
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003586 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003587 default:
Nicholas Troast1769fd32016-09-07 09:20:58 -07003588 pr_err("unsupported property %d\n", psp);
3589 rc = -EINVAL;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003590 break;
3591 }
3592
Nicholas Troast1769fd32016-09-07 09:20:58 -07003593 if (rc < 0)
3594 return -ENODATA;
3595
3596 return 0;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003597}
3598
3599static int fg_psy_set_property(struct power_supply *psy,
3600 enum power_supply_property psp,
3601 const union power_supply_propval *pval)
3602{
Nicholas Troaste29dec92016-08-24 09:35:11 -07003603 struct fg_chip *chip = power_supply_get_drvdata(psy);
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -08003604 int rc = 0;
Nicholas Troaste29dec92016-08-24 09:35:11 -07003605
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003606 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07003607 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
3608 if ((pval->intval > 0) && (pval->intval <= BUCKET_COUNT)) {
3609 chip->cyc_ctr.id = pval->intval;
3610 } else {
3611 pr_err("rejecting invalid cycle_count_id = %d\n",
3612 pval->intval);
3613 return -EINVAL;
3614 }
Nicholas Troast60242812017-06-20 09:33:21 -07003615 break;
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -08003616 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
3617 rc = fg_set_constant_chg_voltage(chip, pval->intval);
Nicholas Troaste29dec92016-08-24 09:35:11 -07003618 break;
Abhijeet Dharmapurikard29bc602017-07-06 18:45:32 -07003619 case POWER_SUPPLY_PROP_RESISTANCE:
3620 rc = fg_force_esr_meas(chip);
3621 break;
3622 case POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE:
3623 rc = fg_prepare_for_qnovo(chip, pval->intval);
3624 break;
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003625 case POWER_SUPPLY_PROP_CC_STEP:
Nicholas Troast805c2422017-07-06 14:53:46 -07003626 if ((chip->ttf.cc_step.sel >= 0) &&
3627 (chip->ttf.cc_step.sel < MAX_CC_STEPS)) {
3628 chip->ttf.cc_step.arr[chip->ttf.cc_step.sel] =
3629 pval->intval;
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003630 } else {
3631 pr_err("cc_step_sel is out of bounds [0, %d]\n",
Nicholas Troast805c2422017-07-06 14:53:46 -07003632 chip->ttf.cc_step.sel);
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003633 return -EINVAL;
3634 }
3635 break;
3636 case POWER_SUPPLY_PROP_CC_STEP_SEL:
3637 if ((pval->intval >= 0) && (pval->intval < MAX_CC_STEPS)) {
Nicholas Troast805c2422017-07-06 14:53:46 -07003638 chip->ttf.cc_step.sel = pval->intval;
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003639 } else {
3640 pr_err("cc_step_sel is out of bounds [0, %d]\n",
3641 pval->intval);
3642 return -EINVAL;
3643 }
3644 break;
Subbaraman Narayanamurthy677e7252017-08-11 18:27:08 -07003645 case POWER_SUPPLY_PROP_CHARGE_FULL:
3646 if (chip->cl.active) {
3647 pr_warn("Capacity learning active!\n");
3648 return 0;
3649 }
3650 if (pval->intval <= 0 || pval->intval > chip->cl.nom_cap_uah) {
3651 pr_err("charge_full is out of bounds\n");
3652 return -EINVAL;
3653 }
3654 chip->cl.learned_cc_uah = pval->intval;
3655 rc = fg_save_learned_cap_to_sram(chip);
3656 if (rc < 0)
3657 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
3658 break;
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003659 case POWER_SUPPLY_PROP_COLD_TEMP:
3660 rc = fg_set_jeita_threshold(chip, JEITA_COLD, pval->intval);
3661 if (rc < 0) {
3662 pr_err("Error in writing jeita_cold, rc=%d\n", rc);
3663 return rc;
3664 }
3665 break;
3666 case POWER_SUPPLY_PROP_COOL_TEMP:
3667 rc = fg_set_jeita_threshold(chip, JEITA_COOL, pval->intval);
3668 if (rc < 0) {
3669 pr_err("Error in writing jeita_cool, rc=%d\n", rc);
3670 return rc;
3671 }
3672 break;
3673 case POWER_SUPPLY_PROP_WARM_TEMP:
3674 rc = fg_set_jeita_threshold(chip, JEITA_WARM, pval->intval);
3675 if (rc < 0) {
3676 pr_err("Error in writing jeita_warm, rc=%d\n", rc);
3677 return rc;
3678 }
3679 break;
3680 case POWER_SUPPLY_PROP_HOT_TEMP:
3681 rc = fg_set_jeita_threshold(chip, JEITA_HOT, pval->intval);
3682 if (rc < 0) {
3683 pr_err("Error in writing jeita_hot, rc=%d\n", rc);
3684 return rc;
3685 }
3686 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003687 default:
3688 break;
3689 }
3690
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -08003691 return rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003692}
3693
3694static int fg_property_is_writeable(struct power_supply *psy,
3695 enum power_supply_property psp)
3696{
3697 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07003698 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -08003699 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003700 case POWER_SUPPLY_PROP_CC_STEP:
3701 case POWER_SUPPLY_PROP_CC_STEP_SEL:
Subbaraman Narayanamurthy677e7252017-08-11 18:27:08 -07003702 case POWER_SUPPLY_PROP_CHARGE_FULL:
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003703 case POWER_SUPPLY_PROP_COLD_TEMP:
3704 case POWER_SUPPLY_PROP_COOL_TEMP:
3705 case POWER_SUPPLY_PROP_WARM_TEMP:
3706 case POWER_SUPPLY_PROP_HOT_TEMP:
Nicholas Troaste29dec92016-08-24 09:35:11 -07003707 return 1;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003708 default:
3709 break;
3710 }
3711
3712 return 0;
3713}
3714
3715static void fg_external_power_changed(struct power_supply *psy)
3716{
3717 pr_debug("power supply changed\n");
3718}
3719
3720static int fg_notifier_cb(struct notifier_block *nb,
3721 unsigned long event, void *data)
3722{
3723 struct power_supply *psy = data;
3724 struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
3725
3726 if (event != PSY_EVENT_PROP_CHANGED)
3727 return NOTIFY_OK;
3728
Subbaraman Narayanamurthy58dac182016-12-06 14:41:29 -08003729 if (work_pending(&chip->status_change_work))
3730 return NOTIFY_OK;
3731
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003732 if ((strcmp(psy->desc->name, "battery") == 0)
Subbaraman Narayanamurthya7249ef2017-10-03 20:34:38 -07003733 || (strcmp(psy->desc->name, "parallel") == 0)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003734 || (strcmp(psy->desc->name, "usb") == 0)) {
3735 /*
3736 * We cannot vote for awake votable here as that takes
3737 * a mutex lock and this is executed in an atomic context.
3738 */
3739 pm_stay_awake(chip->dev);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003740 schedule_work(&chip->status_change_work);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003741 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003742
3743 return NOTIFY_OK;
3744}
3745
3746static enum power_supply_property fg_psy_props[] = {
3747 POWER_SUPPLY_PROP_CAPACITY,
Subbaraman Narayanamurthy50fb7fd2017-07-25 20:01:25 -07003748 POWER_SUPPLY_PROP_CAPACITY_RAW,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003749 POWER_SUPPLY_PROP_TEMP,
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003750 POWER_SUPPLY_PROP_COLD_TEMP,
3751 POWER_SUPPLY_PROP_COOL_TEMP,
3752 POWER_SUPPLY_PROP_WARM_TEMP,
3753 POWER_SUPPLY_PROP_HOT_TEMP,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003754 POWER_SUPPLY_PROP_VOLTAGE_NOW,
3755 POWER_SUPPLY_PROP_VOLTAGE_OCV,
3756 POWER_SUPPLY_PROP_CURRENT_NOW,
3757 POWER_SUPPLY_PROP_RESISTANCE_ID,
3758 POWER_SUPPLY_PROP_RESISTANCE,
3759 POWER_SUPPLY_PROP_BATTERY_TYPE,
3760 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07003761 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Nicholas Troaste29dec92016-08-24 09:35:11 -07003762 POWER_SUPPLY_PROP_CYCLE_COUNT,
3763 POWER_SUPPLY_PROP_CYCLE_COUNT_ID,
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07003764 POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
3765 POWER_SUPPLY_PROP_CHARGE_NOW,
3766 POWER_SUPPLY_PROP_CHARGE_FULL,
3767 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Nicholas Troast1769fd32016-09-07 09:20:58 -07003768 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
3769 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08003770 POWER_SUPPLY_PROP_SOC_REPORTING_READY,
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05303771 POWER_SUPPLY_PROP_DEBUG_BATTERY,
Subbaraman Narayanamurthyef825812017-02-01 18:46:30 -08003772 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
Abhijeet Dharmapurikar19258922017-07-31 19:27:16 -07003773 POWER_SUPPLY_PROP_CC_STEP,
3774 POWER_SUPPLY_PROP_CC_STEP_SEL,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003775};
3776
3777static const struct power_supply_desc fg_psy_desc = {
3778 .name = "bms",
3779 .type = POWER_SUPPLY_TYPE_BMS,
3780 .properties = fg_psy_props,
3781 .num_properties = ARRAY_SIZE(fg_psy_props),
3782 .get_property = fg_psy_get_property,
3783 .set_property = fg_psy_set_property,
3784 .external_power_changed = fg_external_power_changed,
3785 .property_is_writeable = fg_property_is_writeable,
3786};
3787
3788/* INIT FUNCTIONS STAY HERE */
3789
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07003790#define DEFAULT_ESR_CHG_TIMER_RETRY 8
3791#define DEFAULT_ESR_CHG_TIMER_MAX 16
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003792static int fg_hw_init(struct fg_chip *chip)
3793{
3794 int rc;
3795 u8 buf[4], val;
3796
3797 fg_encode(chip->sp, FG_SRAM_CUTOFF_VOLT, chip->dt.cutoff_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07003798 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CUTOFF_VOLT].addr_word,
3799 chip->sp[FG_SRAM_CUTOFF_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003800 chip->sp[FG_SRAM_CUTOFF_VOLT].len, FG_IMA_DEFAULT);
3801 if (rc < 0) {
3802 pr_err("Error in writing cutoff_volt, rc=%d\n", rc);
3803 return rc;
3804 }
3805
3806 fg_encode(chip->sp, FG_SRAM_EMPTY_VOLT, chip->dt.empty_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07003807 rc = fg_sram_write(chip, chip->sp[FG_SRAM_EMPTY_VOLT].addr_word,
3808 chip->sp[FG_SRAM_EMPTY_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003809 chip->sp[FG_SRAM_EMPTY_VOLT].len, FG_IMA_DEFAULT);
3810 if (rc < 0) {
3811 pr_err("Error in writing empty_volt, rc=%d\n", rc);
3812 return rc;
3813 }
3814
3815 fg_encode(chip->sp, FG_SRAM_CHG_TERM_CURR, chip->dt.chg_term_curr_ma,
3816 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07003817 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CHG_TERM_CURR].addr_word,
3818 chip->sp[FG_SRAM_CHG_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003819 chip->sp[FG_SRAM_CHG_TERM_CURR].len, FG_IMA_DEFAULT);
3820 if (rc < 0) {
3821 pr_err("Error in writing chg_term_curr, rc=%d\n", rc);
3822 return rc;
3823 }
3824
3825 fg_encode(chip->sp, FG_SRAM_SYS_TERM_CURR, chip->dt.sys_term_curr_ma,
3826 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07003827 rc = fg_sram_write(chip, chip->sp[FG_SRAM_SYS_TERM_CURR].addr_word,
3828 chip->sp[FG_SRAM_SYS_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003829 chip->sp[FG_SRAM_SYS_TERM_CURR].len, FG_IMA_DEFAULT);
3830 if (rc < 0) {
3831 pr_err("Error in writing sys_term_curr, rc=%d\n", rc);
3832 return rc;
3833 }
3834
Subbaraman Narayanamurthya4e18882017-04-04 20:28:03 -07003835 if (!(chip->wa_flags & PMI8998_V1_REV_WA)) {
3836 fg_encode(chip->sp, FG_SRAM_CHG_TERM_BASE_CURR,
3837 chip->dt.chg_term_base_curr_ma, buf);
3838 rc = fg_sram_write(chip,
3839 chip->sp[FG_SRAM_CHG_TERM_BASE_CURR].addr_word,
3840 chip->sp[FG_SRAM_CHG_TERM_BASE_CURR].addr_byte,
3841 buf, chip->sp[FG_SRAM_CHG_TERM_BASE_CURR].len,
3842 FG_IMA_DEFAULT);
3843 if (rc < 0) {
3844 pr_err("Error in writing chg_term_base_curr, rc=%d\n",
3845 rc);
3846 return rc;
3847 }
3848 }
3849
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003850 if (chip->dt.vbatt_low_thr_mv > 0) {
3851 fg_encode(chip->sp, FG_SRAM_VBATT_LOW,
3852 chip->dt.vbatt_low_thr_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07003853 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_LOW].addr_word,
3854 chip->sp[FG_SRAM_VBATT_LOW].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003855 chip->sp[FG_SRAM_VBATT_LOW].len,
3856 FG_IMA_DEFAULT);
3857 if (rc < 0) {
3858 pr_err("Error in writing vbatt_low_thr, rc=%d\n", rc);
3859 return rc;
3860 }
3861 }
3862
3863 if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) {
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -08003864 fg_encode(chip->sp, FG_SRAM_DELTA_MSOC_THR,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003865 chip->dt.delta_soc_thr, buf);
3866 rc = fg_sram_write(chip,
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -08003867 chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_word,
3868 chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_byte,
3869 buf, chip->sp[FG_SRAM_DELTA_MSOC_THR].len,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003870 FG_IMA_DEFAULT);
3871 if (rc < 0) {
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -08003872 pr_err("Error in writing delta_msoc_thr, rc=%d\n", rc);
3873 return rc;
3874 }
3875
3876 fg_encode(chip->sp, FG_SRAM_DELTA_BSOC_THR,
3877 chip->dt.delta_soc_thr, buf);
3878 rc = fg_sram_write(chip,
3879 chip->sp[FG_SRAM_DELTA_BSOC_THR].addr_word,
3880 chip->sp[FG_SRAM_DELTA_BSOC_THR].addr_byte,
3881 buf, chip->sp[FG_SRAM_DELTA_BSOC_THR].len,
3882 FG_IMA_DEFAULT);
3883 if (rc < 0) {
3884 pr_err("Error in writing delta_bsoc_thr, rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003885 return rc;
3886 }
3887 }
3888
cyizhaofb3eec52017-01-24 17:08:55 +08003889 /*
3890 * configure battery thermal coefficients c1,c2,c3
3891 * if its value is not zero.
3892 */
3893 if (chip->dt.batt_therm_coeffs[0] > 0) {
3894 rc = fg_write(chip, BATT_INFO_THERM_C1(chip),
3895 chip->dt.batt_therm_coeffs, BATT_THERM_NUM_COEFFS);
3896 if (rc < 0) {
3897 pr_err("Error in writing battery thermal coefficients, rc=%d\n",
3898 rc);
3899 return rc;
3900 }
3901 }
3902
3903
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003904 if (chip->dt.recharge_soc_thr > 0 && chip->dt.recharge_soc_thr < 100) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07003905 rc = fg_set_recharge_soc(chip, chip->dt.recharge_soc_thr);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003906 if (rc < 0) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07003907 pr_err("Error in setting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003908 return rc;
3909 }
3910 }
3911
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08003912 if (chip->dt.recharge_volt_thr_mv > 0) {
3913 rc = fg_set_recharge_voltage(chip,
3914 chip->dt.recharge_volt_thr_mv);
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08003915 if (rc < 0) {
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08003916 pr_err("Error in setting recharge_voltage, rc=%d\n",
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08003917 rc);
3918 return rc;
3919 }
3920 }
3921
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003922 if (chip->dt.rsense_sel >= SRC_SEL_BATFET &&
3923 chip->dt.rsense_sel < SRC_SEL_RESERVED) {
3924 rc = fg_masked_write(chip, BATT_INFO_IBATT_SENSING_CFG(chip),
3925 SOURCE_SELECT_MASK, chip->dt.rsense_sel);
3926 if (rc < 0) {
3927 pr_err("Error in writing rsense_sel, rc=%d\n", rc);
3928 return rc;
3929 }
3930 }
3931
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003932 rc = fg_set_jeita_threshold(chip, JEITA_COLD,
3933 chip->dt.jeita_thresholds[JEITA_COLD] * 10);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003934 if (rc < 0) {
3935 pr_err("Error in writing jeita_cold, rc=%d\n", rc);
3936 return rc;
3937 }
3938
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003939 rc = fg_set_jeita_threshold(chip, JEITA_COOL,
3940 chip->dt.jeita_thresholds[JEITA_COOL] * 10);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003941 if (rc < 0) {
3942 pr_err("Error in writing jeita_cool, rc=%d\n", rc);
3943 return rc;
3944 }
3945
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003946 rc = fg_set_jeita_threshold(chip, JEITA_WARM,
3947 chip->dt.jeita_thresholds[JEITA_WARM] * 10);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003948 if (rc < 0) {
3949 pr_err("Error in writing jeita_warm, rc=%d\n", rc);
3950 return rc;
3951 }
3952
Subbaraman Narayanamurthyedff8902017-08-11 19:24:24 -07003953 rc = fg_set_jeita_threshold(chip, JEITA_HOT,
3954 chip->dt.jeita_thresholds[JEITA_HOT] * 10);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07003955 if (rc < 0) {
3956 pr_err("Error in writing jeita_hot, rc=%d\n", rc);
3957 return rc;
3958 }
3959
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07003960 if (chip->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE) {
3961 chip->esr_timer_charging_default[TIMER_RETRY] =
3962 DEFAULT_ESR_CHG_TIMER_RETRY;
3963 chip->esr_timer_charging_default[TIMER_MAX] =
3964 DEFAULT_ESR_CHG_TIMER_MAX;
3965 } else {
3966 /* We don't need this for pm660 at present */
3967 chip->esr_timer_charging_default[TIMER_RETRY] = -EINVAL;
3968 chip->esr_timer_charging_default[TIMER_MAX] = -EINVAL;
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003969 }
3970
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07003971 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_charging[TIMER_RETRY],
3972 chip->dt.esr_timer_charging[TIMER_MAX], true, FG_IMA_DEFAULT);
3973 if (rc < 0) {
3974 pr_err("Error in setting ESR timer, rc=%d\n", rc);
3975 return rc;
3976 }
3977
3978 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake[TIMER_RETRY],
3979 chip->dt.esr_timer_awake[TIMER_MAX], false, FG_IMA_DEFAULT);
3980 if (rc < 0) {
3981 pr_err("Error in setting ESR timer, rc=%d\n", rc);
3982 return rc;
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07003983 }
3984
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07003985 restore_cycle_counter(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07003986
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07003987 if (chip->dt.jeita_hyst_temp >= 0) {
3988 val = chip->dt.jeita_hyst_temp << JEITA_TEMP_HYST_SHIFT;
3989 rc = fg_masked_write(chip, BATT_INFO_BATT_TEMP_CFG(chip),
3990 JEITA_TEMP_HYST_MASK, val);
3991 if (rc < 0) {
3992 pr_err("Error in writing batt_temp_cfg, rc=%d\n", rc);
3993 return rc;
3994 }
3995 }
3996
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07003997 get_batt_temp_delta(chip->dt.batt_temp_delta, &val);
3998 rc = fg_masked_write(chip, BATT_INFO_BATT_TMPR_INTR(chip),
3999 CHANGE_THOLD_MASK, val);
4000 if (rc < 0) {
4001 pr_err("Error in writing batt_temp_delta, rc=%d\n", rc);
4002 return rc;
4003 }
4004
Subbaraman Narayanamurthy8909f372017-03-14 19:50:57 -07004005 rc = fg_rconn_config(chip);
4006 if (rc < 0) {
4007 pr_err("Error in configuring Rconn, rc=%d\n", rc);
4008 return rc;
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08004009 }
4010
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08004011 fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
4012 chip->dt.esr_tight_flt_upct, buf);
4013 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_word,
4014 chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_byte, buf,
4015 chip->sp[FG_SRAM_ESR_TIGHT_FILTER].len, FG_IMA_DEFAULT);
4016 if (rc < 0) {
4017 pr_err("Error in writing ESR tight filter, rc=%d\n", rc);
4018 return rc;
4019 }
4020
4021 fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
4022 chip->dt.esr_broad_flt_upct, buf);
4023 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_word,
4024 chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_byte, buf,
4025 chip->sp[FG_SRAM_ESR_BROAD_FILTER].len, FG_IMA_DEFAULT);
4026 if (rc < 0) {
4027 pr_err("Error in writing ESR broad filter, rc=%d\n", rc);
4028 return rc;
4029 }
4030
Subbaraman Narayanamurthye14037f2017-03-16 19:14:58 -07004031 fg_encode(chip->sp, FG_SRAM_ESR_PULSE_THRESH,
4032 chip->dt.esr_pulse_thresh_ma, buf);
4033 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_PULSE_THRESH].addr_word,
4034 chip->sp[FG_SRAM_ESR_PULSE_THRESH].addr_byte, buf,
4035 chip->sp[FG_SRAM_ESR_PULSE_THRESH].len, FG_IMA_DEFAULT);
4036 if (rc < 0) {
4037 pr_err("Error in writing esr_pulse_thresh_ma, rc=%d\n", rc);
4038 return rc;
4039 }
4040
4041 get_esr_meas_current(chip->dt.esr_meas_curr_ma, &val);
4042 rc = fg_masked_write(chip, BATT_INFO_ESR_PULL_DN_CFG(chip),
4043 ESR_PULL_DOWN_IVAL_MASK, val);
4044 if (rc < 0) {
4045 pr_err("Error in writing esr_meas_curr_ma, rc=%d\n", rc);
4046 return rc;
4047 }
4048
Subbaraman Narayanamurthy401a1d32017-05-05 14:07:53 -07004049 if (is_debug_batt_id(chip)) {
4050 val = ESR_NO_PULL_DOWN;
4051 rc = fg_masked_write(chip, BATT_INFO_ESR_PULL_DN_CFG(chip),
4052 ESR_PULL_DOWN_MODE_MASK, val);
4053 if (rc < 0) {
4054 pr_err("Error in writing esr_pull_down, rc=%d\n", rc);
4055 return rc;
4056 }
4057 }
4058
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004059 return 0;
4060}
4061
4062static int fg_memif_init(struct fg_chip *chip)
4063{
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -07004064 if (chip->use_dma)
4065 return fg_dma_init(chip);
4066
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004067 return fg_ima_init(chip);
4068}
4069
Anirudh Ghayalddabeee2017-04-04 06:13:48 +05304070static int fg_adjust_timebase(struct fg_chip *chip)
4071{
4072 int rc = 0, die_temp;
4073 s32 time_base = 0;
4074 u8 buf[2] = {0};
4075
4076 if ((chip->wa_flags & PM660_TSMC_OSC_WA) && chip->die_temp_chan) {
4077 rc = iio_read_channel_processed(chip->die_temp_chan, &die_temp);
4078 if (rc < 0) {
4079 pr_err("Error in reading die_temp, rc:%d\n", rc);
4080 return rc;
4081 }
4082
4083 rc = fg_lerp(fg_tsmc_osc_table, ARRAY_SIZE(fg_tsmc_osc_table),
4084 die_temp / 1000, &time_base);
4085 if (rc < 0) {
4086 pr_err("Error to lookup fg_tsmc_osc_table rc=%d\n", rc);
4087 return rc;
4088 }
4089
4090 fg_encode(chip->sp, FG_SRAM_TIMEBASE, time_base, buf);
4091 rc = fg_sram_write(chip,
4092 chip->sp[FG_SRAM_TIMEBASE].addr_word,
4093 chip->sp[FG_SRAM_TIMEBASE].addr_byte, buf,
4094 chip->sp[FG_SRAM_TIMEBASE].len, FG_IMA_DEFAULT);
4095 if (rc < 0) {
4096 pr_err("Error in writing timebase, rc=%d\n", rc);
4097 return rc;
4098 }
4099 }
4100
4101 return 0;
4102}
4103
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004104/* INTERRUPT HANDLERS STAY HERE */
4105
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -07004106static irqreturn_t fg_dma_grant_irq_handler(int irq, void *data)
4107{
4108 struct fg_chip *chip = data;
4109 u8 status;
4110 int rc;
4111
4112 rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1);
4113 if (rc < 0) {
4114 pr_err("failed to read addr=0x%04x, rc=%d\n",
4115 MEM_IF_INT_RT_STS(chip), rc);
4116 return IRQ_HANDLED;
4117 }
4118
4119 fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status);
Subbaraman Narayanamurthy2d385062017-09-14 20:23:13 -07004120 complete_all(&chip->mem_grant);
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -07004121
4122 return IRQ_HANDLED;
4123}
4124
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07004125static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
4126{
4127 struct fg_chip *chip = data;
4128 u8 status;
4129 int rc;
4130
4131 rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1);
4132 if (rc < 0) {
4133 pr_err("failed to read addr=0x%04x, rc=%d\n",
4134 MEM_IF_INT_RT_STS(chip), rc);
4135 return IRQ_HANDLED;
4136 }
4137
4138 fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status);
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07004139
Subbaraman Narayanamurthy3f3040a2017-03-14 20:30:47 -07004140 mutex_lock(&chip->sram_rw_lock);
4141 rc = fg_clear_dma_errors_if_any(chip);
4142 if (rc < 0)
4143 pr_err("Error in clearing DMA error, rc=%d\n", rc);
4144
4145 if (status & MEM_XCP_BIT) {
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07004146 rc = fg_clear_ima_errors_if_any(chip, true);
4147 if (rc < 0 && rc != -EAGAIN)
4148 pr_err("Error in checking IMA errors rc:%d\n", rc);
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07004149 }
4150
Subbaraman Narayanamurthy3f3040a2017-03-14 20:30:47 -07004151 mutex_unlock(&chip->sram_rw_lock);
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07004152 return IRQ_HANDLED;
4153}
4154
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004155static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
4156{
4157 struct fg_chip *chip = data;
4158
4159 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
4160 return IRQ_HANDLED;
4161}
4162
4163static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
4164{
4165 struct fg_chip *chip = data;
4166 u8 status;
4167 int rc;
4168
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004169 rc = fg_read(chip, BATT_INFO_INT_RT_STS(chip), &status, 1);
4170 if (rc < 0) {
4171 pr_err("failed to read addr=0x%04x, rc=%d\n",
4172 BATT_INFO_INT_RT_STS(chip), rc);
4173 return IRQ_HANDLED;
4174 }
4175
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -08004176 fg_dbg(chip, FG_IRQ, "irq %d triggered sts:%d\n", irq, status);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004177 chip->battery_missing = (status & BT_MISS_BIT);
4178
4179 if (chip->battery_missing) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07004180 chip->profile_available = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004181 chip->profile_loaded = false;
Subbaraman Narayanamurthyfd7f07b2016-12-14 15:10:15 -08004182 chip->soc_reporting_ready = false;
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -08004183 return IRQ_HANDLED;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004184 }
4185
Subbaraman Narayanamurthy34af21c2016-12-15 18:03:09 -08004186 clear_battery_profile(chip);
4187 schedule_delayed_work(&chip->profile_load_work, 0);
4188
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05304189 if (chip->fg_psy)
4190 power_supply_changed(chip->fg_psy);
4191
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004192 return IRQ_HANDLED;
4193}
4194
4195static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data)
4196{
4197 struct fg_chip *chip = data;
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07004198 union power_supply_propval prop = {0, };
4199 int rc, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004200
4201 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07004202 rc = fg_get_battery_temp(chip, &batt_temp);
4203 if (rc < 0) {
4204 pr_err("Error in getting batt_temp\n");
4205 return IRQ_HANDLED;
4206 }
4207
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08004208 rc = fg_esr_filter_config(chip, batt_temp);
4209 if (rc < 0)
4210 pr_err("Error in configuring ESR filter rc:%d\n", rc);
4211
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -08004212 rc = fg_slope_limit_config(chip, batt_temp);
4213 if (rc < 0)
4214 pr_err("Error in configuring slope limiter rc:%d\n", rc);
4215
Subbaraman Narayanamurthy1bf973e2017-04-04 19:24:20 -07004216 rc = fg_adjust_ki_coeff_full_soc(chip, batt_temp);
4217 if (rc < 0)
4218 pr_err("Error in configuring ki_coeff_full_soc rc:%d\n", rc);
4219
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08004220 if (!batt_psy_initialized(chip)) {
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07004221 chip->last_batt_temp = batt_temp;
4222 return IRQ_HANDLED;
4223 }
4224
4225 power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
4226 &prop);
4227 chip->health = prop.intval;
4228
4229 if (chip->last_batt_temp != batt_temp) {
Anirudh Ghayalddabeee2017-04-04 06:13:48 +05304230 rc = fg_adjust_timebase(chip);
4231 if (rc < 0)
4232 pr_err("Error in adjusting timebase, rc=%d\n", rc);
4233
Subbaraman Narayanamurthyfdca8c22017-08-04 12:25:49 -07004234 rc = fg_adjust_recharge_voltage(chip);
4235 if (rc < 0)
4236 pr_err("Error in adjusting recharge_voltage, rc=%d\n",
4237 rc);
4238
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07004239 chip->last_batt_temp = batt_temp;
4240 power_supply_changed(chip->batt_psy);
4241 }
4242
4243 if (abs(chip->last_batt_temp - batt_temp) > 30)
4244 pr_warn("Battery temperature last:%d current: %d\n",
4245 chip->last_batt_temp, batt_temp);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004246 return IRQ_HANDLED;
4247}
4248
4249static irqreturn_t fg_first_est_irq_handler(int irq, void *data)
4250{
4251 struct fg_chip *chip = data;
4252
4253 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
4254 complete_all(&chip->soc_ready);
4255 return IRQ_HANDLED;
4256}
4257
4258static irqreturn_t fg_soc_update_irq_handler(int irq, void *data)
4259{
4260 struct fg_chip *chip = data;
4261
4262 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
4263 complete_all(&chip->soc_update);
4264 return IRQ_HANDLED;
4265}
4266
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -08004267static irqreturn_t fg_delta_bsoc_irq_handler(int irq, void *data)
4268{
4269 struct fg_chip *chip = data;
4270 int rc;
4271
4272 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
4273 rc = fg_charge_full_update(chip);
4274 if (rc < 0)
4275 pr_err("Error in charge_full_update, rc=%d\n", rc);
4276
4277 return IRQ_HANDLED;
4278}
4279
4280static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004281{
4282 struct fg_chip *chip = data;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07004283 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004284
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08004285 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthyf9c0b872017-06-09 15:09:11 -07004286 fg_cycle_counter_update(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07004287
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07004288 if (chip->cl.active)
4289 fg_cap_learning_update(chip);
4290
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07004291 rc = fg_charge_full_update(chip);
4292 if (rc < 0)
4293 pr_err("Error in charge_full_update, rc=%d\n", rc);
4294
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004295 rc = fg_adjust_ki_coeff_dischg(chip);
4296 if (rc < 0)
4297 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
4298
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08004299 rc = fg_update_maint_soc(chip);
4300 if (rc < 0)
4301 pr_err("Error in updating maint_soc, rc=%d\n", rc);
4302
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -08004303 rc = fg_esr_validate(chip);
4304 if (rc < 0)
4305 pr_err("Error in validating ESR, rc=%d\n", rc);
4306
Anirudh Ghayalddabeee2017-04-04 06:13:48 +05304307 rc = fg_adjust_timebase(chip);
4308 if (rc < 0)
4309 pr_err("Error in adjusting timebase, rc=%d\n", rc);
4310
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08004311 if (batt_psy_initialized(chip))
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08004312 power_supply_changed(chip->batt_psy);
4313
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004314 return IRQ_HANDLED;
4315}
4316
4317static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data)
4318{
4319 struct fg_chip *chip = data;
4320
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08004321 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Abhijeet Dharmapurikar2cdd1402017-01-10 15:38:27 -08004322 if (batt_psy_initialized(chip))
Nicholas Troast65e29652016-09-22 11:27:04 -07004323 power_supply_changed(chip->batt_psy);
4324
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004325 return IRQ_HANDLED;
4326}
4327
4328static irqreturn_t fg_soc_irq_handler(int irq, void *data)
4329{
4330 struct fg_chip *chip = data;
4331
4332 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
4333 return IRQ_HANDLED;
4334}
4335
4336static irqreturn_t fg_dummy_irq_handler(int irq, void *data)
4337{
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08004338 pr_debug("irq %d triggered\n", irq);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004339 return IRQ_HANDLED;
4340}
4341
4342static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
4343 /* BATT_SOC irqs */
4344 [MSOC_FULL_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004345 .name = "msoc-full",
4346 .handler = fg_soc_irq_handler,
4347 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004348 [MSOC_HIGH_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004349 .name = "msoc-high",
4350 .handler = fg_soc_irq_handler,
4351 .wakeable = true,
4352 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004353 [MSOC_EMPTY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004354 .name = "msoc-empty",
4355 .handler = fg_empty_soc_irq_handler,
4356 .wakeable = true,
4357 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004358 [MSOC_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004359 .name = "msoc-low",
4360 .handler = fg_soc_irq_handler,
4361 .wakeable = true,
4362 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004363 [MSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004364 .name = "msoc-delta",
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -08004365 .handler = fg_delta_msoc_irq_handler,
Nicholas Troast3cc97182016-09-23 08:54:13 -07004366 .wakeable = true,
4367 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004368 [BSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004369 .name = "bsoc-delta",
Subbaraman Narayanamurthyfbf25372017-01-03 15:39:08 -08004370 .handler = fg_delta_bsoc_irq_handler,
4371 .wakeable = true,
Nicholas Troast3cc97182016-09-23 08:54:13 -07004372 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004373 [SOC_READY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004374 .name = "soc-ready",
4375 .handler = fg_first_est_irq_handler,
4376 .wakeable = true,
4377 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004378 [SOC_UPDATE_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004379 .name = "soc-update",
4380 .handler = fg_soc_update_irq_handler,
4381 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004382 /* BATT_INFO irqs */
4383 [BATT_TEMP_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004384 .name = "batt-temp-delta",
4385 .handler = fg_delta_batt_temp_irq_handler,
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07004386 .wakeable = true,
Nicholas Troast3cc97182016-09-23 08:54:13 -07004387 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004388 [BATT_MISSING_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004389 .name = "batt-missing",
4390 .handler = fg_batt_missing_irq_handler,
4391 .wakeable = true,
4392 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004393 [ESR_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004394 .name = "esr-delta",
4395 .handler = fg_dummy_irq_handler,
4396 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004397 [VBATT_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004398 .name = "vbatt-low",
4399 .handler = fg_vbatt_low_irq_handler,
4400 .wakeable = true,
4401 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004402 [VBATT_PRED_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004403 .name = "vbatt-pred-delta",
4404 .handler = fg_dummy_irq_handler,
4405 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004406 /* MEM_IF irqs */
4407 [DMA_GRANT_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004408 .name = "dma-grant",
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -07004409 .handler = fg_dma_grant_irq_handler,
4410 .wakeable = true,
Nicholas Troast3cc97182016-09-23 08:54:13 -07004411 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004412 [MEM_XCP_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004413 .name = "mem-xcp",
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -07004414 .handler = fg_mem_xcp_irq_handler,
Nicholas Troast3cc97182016-09-23 08:54:13 -07004415 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004416 [IMA_RDY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07004417 .name = "ima-rdy",
4418 .handler = fg_dummy_irq_handler,
4419 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004420};
4421
4422static int fg_get_irq_index_byname(const char *name)
4423{
4424 int i;
4425
4426 for (i = 0; i < ARRAY_SIZE(fg_irqs); i++) {
4427 if (strcmp(fg_irqs[i].name, name) == 0)
4428 return i;
4429 }
4430
4431 pr_err("%s is not in irq list\n", name);
4432 return -ENOENT;
4433}
4434
4435static int fg_register_interrupts(struct fg_chip *chip)
4436{
4437 struct device_node *child, *node = chip->dev->of_node;
4438 struct property *prop;
4439 const char *name;
4440 int rc, irq, irq_index;
4441
4442 for_each_available_child_of_node(node, child) {
4443 of_property_for_each_string(child, "interrupt-names", prop,
4444 name) {
4445 irq = of_irq_get_byname(child, name);
4446 if (irq < 0) {
4447 dev_err(chip->dev, "failed to get irq %s irq:%d\n",
4448 name, irq);
4449 return irq;
4450 }
4451
4452 irq_index = fg_get_irq_index_byname(name);
4453 if (irq_index < 0)
4454 return irq_index;
4455
4456 rc = devm_request_threaded_irq(chip->dev, irq, NULL,
4457 fg_irqs[irq_index].handler,
4458 IRQF_ONESHOT, name, chip);
4459 if (rc < 0) {
4460 dev_err(chip->dev, "failed to register irq handler for %s rc:%d\n",
4461 name, rc);
4462 return rc;
4463 }
4464
4465 fg_irqs[irq_index].irq = irq;
4466 if (fg_irqs[irq_index].wakeable)
4467 enable_irq_wake(fg_irqs[irq_index].irq);
4468 }
4469 }
4470
4471 return 0;
4472}
4473
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004474static int fg_parse_dt_property_u32_array(struct device_node *node,
4475 const char *prop_name, int *buf, int len)
4476{
4477 int rc;
4478
4479 rc = of_property_count_elems_of_size(node, prop_name, sizeof(u32));
4480 if (rc < 0) {
4481 if (rc == -EINVAL)
4482 return 0;
4483 else
4484 return rc;
4485 } else if (rc != len) {
4486 pr_err("Incorrect length %d for %s, rc=%d\n", len, prop_name,
4487 rc);
4488 return -EINVAL;
4489 }
4490
4491 rc = of_property_read_u32_array(node, prop_name, buf, len);
4492 if (rc < 0) {
4493 pr_err("Error in reading %s, rc=%d\n", prop_name, rc);
4494 return rc;
4495 }
4496
4497 return 0;
4498}
4499
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -08004500static int fg_parse_slope_limit_coefficients(struct fg_chip *chip)
4501{
4502 struct device_node *node = chip->dev->of_node;
4503 int rc, i;
4504
4505 rc = of_property_read_u32(node, "qcom,slope-limit-temp-threshold",
4506 &chip->dt.slope_limit_temp);
4507 if (rc < 0)
4508 return 0;
4509
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004510 rc = fg_parse_dt_property_u32_array(node, "qcom,slope-limit-coeffs",
4511 chip->dt.slope_limit_coeffs, SLOPE_LIMIT_NUM_COEFFS);
4512 if (rc < 0)
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -08004513 return rc;
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -08004514
4515 for (i = 0; i < SLOPE_LIMIT_NUM_COEFFS; i++) {
4516 if (chip->dt.slope_limit_coeffs[i] > SLOPE_LIMIT_COEFF_MAX ||
4517 chip->dt.slope_limit_coeffs[i] < 0) {
4518 pr_err("Incorrect slope limit coefficient\n");
4519 return -EINVAL;
4520 }
4521 }
4522
4523 chip->slope_limit_en = true;
4524 return 0;
4525}
4526
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004527static int fg_parse_ki_coefficients(struct fg_chip *chip)
4528{
4529 struct device_node *node = chip->dev->of_node;
Subbaraman Narayanamurthye17be582017-08-08 19:28:37 -07004530 int rc, i, temp;
4531
4532 rc = of_property_read_u32(node, "qcom,ki-coeff-full-dischg", &temp);
4533 if (!rc)
4534 chip->dt.ki_coeff_full_soc_dischg = temp;
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004535
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004536 rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-soc-dischg",
4537 chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
4538 if (rc < 0)
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004539 return rc;
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004540
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004541 rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-med-dischg",
4542 chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
4543 if (rc < 0)
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004544 return rc;
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004545
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004546 rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-hi-dischg",
4547 chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
4548 if (rc < 0)
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004549 return rc;
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004550
4551 for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
4552 if (chip->dt.ki_coeff_soc[i] < 0 ||
4553 chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
4554 pr_err("Error in ki_coeff_soc_dischg values\n");
4555 return -EINVAL;
4556 }
4557
4558 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
4559 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
4560 pr_err("Error in ki_coeff_med_dischg values\n");
4561 return -EINVAL;
4562 }
4563
4564 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
4565 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
4566 pr_err("Error in ki_coeff_med_dischg values\n");
4567 return -EINVAL;
4568 }
4569 }
4570 chip->ki_coeff_dischg_en = true;
4571 return 0;
4572}
4573
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004574#define DEFAULT_CUTOFF_VOLT_MV 3200
Subbaraman Narayanamurthy8b249942017-05-19 13:50:44 -07004575#define DEFAULT_EMPTY_VOLT_MV 2850
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08004576#define DEFAULT_RECHARGE_VOLT_MV 4250
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004577#define DEFAULT_CHG_TERM_CURR_MA 100
Subbaraman Narayanamurthya4e18882017-04-04 20:28:03 -07004578#define DEFAULT_CHG_TERM_BASE_CURR_MA 75
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -07004579#define DEFAULT_SYS_TERM_CURR_MA -125
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004580#define DEFAULT_DELTA_SOC_THR 1
4581#define DEFAULT_RECHARGE_SOC_THR 95
4582#define DEFAULT_BATT_TEMP_COLD 0
4583#define DEFAULT_BATT_TEMP_COOL 5
4584#define DEFAULT_BATT_TEMP_WARM 45
4585#define DEFAULT_BATT_TEMP_HOT 50
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07004586#define DEFAULT_CL_START_SOC 15
4587#define DEFAULT_CL_MIN_TEMP_DECIDEGC 150
4588#define DEFAULT_CL_MAX_TEMP_DECIDEGC 450
4589#define DEFAULT_CL_MAX_INC_DECIPERC 5
4590#define DEFAULT_CL_MAX_DEC_DECIPERC 100
4591#define DEFAULT_CL_MIN_LIM_DECIPERC 0
4592#define DEFAULT_CL_MAX_LIM_DECIPERC 0
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07004593#define BTEMP_DELTA_LOW 2
4594#define BTEMP_DELTA_HIGH 10
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08004595#define DEFAULT_ESR_FLT_TEMP_DECIDEGC 100
4596#define DEFAULT_ESR_TIGHT_FLT_UPCT 3907
4597#define DEFAULT_ESR_BROAD_FLT_UPCT 99610
4598#define DEFAULT_ESR_TIGHT_LT_FLT_UPCT 48829
4599#define DEFAULT_ESR_BROAD_LT_FLT_UPCT 148438
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -08004600#define DEFAULT_ESR_CLAMP_MOHMS 20
Subbaraman Narayanamurthye14037f2017-03-16 19:14:58 -07004601#define DEFAULT_ESR_PULSE_THRESH_MA 110
4602#define DEFAULT_ESR_MEAS_CURR_MA 120
Fenglin Wud10ccf12017-08-10 15:43:41 +08004603#define DEFAULT_BMD_EN_DELAY_MS 200
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004604static int fg_parse_dt(struct fg_chip *chip)
4605{
4606 struct device_node *child, *revid_node, *node = chip->dev->of_node;
4607 u32 base, temp;
4608 u8 subtype;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07004609 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004610
4611 if (!node) {
4612 dev_err(chip->dev, "device tree node missing\n");
4613 return -ENXIO;
4614 }
4615
4616 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
4617 if (!revid_node) {
4618 pr_err("Missing qcom,pmic-revid property - driver failed\n");
4619 return -EINVAL;
4620 }
4621
4622 chip->pmic_rev_id = get_revid_data(revid_node);
4623 if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
4624 pr_err("Unable to get pmic_revid rc=%ld\n",
4625 PTR_ERR(chip->pmic_rev_id));
4626 /*
4627 * the revid peripheral must be registered, any failure
4628 * here only indicates that the rev-id module has not
4629 * probed yet.
4630 */
4631 return -EPROBE_DEFER;
4632 }
4633
4634 pr_debug("PMIC subtype %d Digital major %d\n",
4635 chip->pmic_rev_id->pmic_subtype, chip->pmic_rev_id->rev4);
4636
4637 switch (chip->pmic_rev_id->pmic_subtype) {
Harry Yang2452b272017-03-06 13:56:14 -08004638 case PMI8998_SUBTYPE:
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -07004639 chip->use_dma = true;
Harry Yang2452b272017-03-06 13:56:14 -08004640 if (chip->pmic_rev_id->rev4 < PMI8998_V2P0_REV4) {
4641 chip->sp = pmi8998_v1_sram_params;
4642 chip->alg_flags = pmi8998_v1_alg_flags;
Ashay Jaiswal63d486e2016-12-07 11:21:32 +05304643 chip->wa_flags |= PMI8998_V1_REV_WA;
Harry Yang2452b272017-03-06 13:56:14 -08004644 } else if (chip->pmic_rev_id->rev4 == PMI8998_V2P0_REV4) {
4645 chip->sp = pmi8998_v2_sram_params;
4646 chip->alg_flags = pmi8998_v2_alg_flags;
Nicholas Troast69da2252016-09-07 16:17:47 -07004647 } else {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004648 return -EINVAL;
Nicholas Troast69da2252016-09-07 16:17:47 -07004649 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004650 break;
Harry Yange4e731b2017-03-06 14:35:09 -08004651 case PM660_SUBTYPE:
Ashay Jaiswal63d486e2016-12-07 11:21:32 +05304652 chip->sp = pmi8998_v2_sram_params;
4653 chip->alg_flags = pmi8998_v2_alg_flags;
Subbaraman Narayanamurthy9b866452017-03-27 16:29:25 -07004654 chip->use_ima_single_mode = true;
Anirudh Ghayalddabeee2017-04-04 06:13:48 +05304655 if (chip->pmic_rev_id->fab_id == PM660_FAB_ID_TSMC)
4656 chip->wa_flags |= PM660_TSMC_OSC_WA;
Ashay Jaiswal63d486e2016-12-07 11:21:32 +05304657 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004658 default:
4659 return -EINVAL;
4660 }
4661
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004662 if (of_get_available_child_count(node) == 0) {
4663 dev_err(chip->dev, "No child nodes specified!\n");
4664 return -ENXIO;
4665 }
4666
4667 for_each_available_child_of_node(node, child) {
4668 rc = of_property_read_u32(child, "reg", &base);
4669 if (rc < 0) {
4670 dev_err(chip->dev, "reg not specified in node %s, rc=%d\n",
4671 child->full_name, rc);
4672 return rc;
4673 }
4674
4675 rc = fg_read(chip, base + PERPH_SUBTYPE_REG, &subtype, 1);
4676 if (rc < 0) {
4677 dev_err(chip->dev, "Couldn't read subtype for base %d, rc=%d\n",
4678 base, rc);
4679 return rc;
4680 }
4681
4682 switch (subtype) {
Harry Yang2452b272017-03-06 13:56:14 -08004683 case FG_BATT_SOC_PMI8998:
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004684 chip->batt_soc_base = base;
4685 break;
Harry Yang2452b272017-03-06 13:56:14 -08004686 case FG_BATT_INFO_PMI8998:
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004687 chip->batt_info_base = base;
4688 break;
Harry Yang2452b272017-03-06 13:56:14 -08004689 case FG_MEM_INFO_PMI8998:
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004690 chip->mem_if_base = base;
4691 break;
4692 default:
4693 dev_err(chip->dev, "Invalid peripheral subtype 0x%x\n",
4694 subtype);
4695 return -ENXIO;
4696 }
4697 }
4698
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -08004699 rc = of_property_read_u32(node, "qcom,rradc-base", &base);
4700 if (rc < 0) {
4701 dev_err(chip->dev, "rradc-base not specified, rc=%d\n", rc);
4702 return rc;
4703 }
4704 chip->rradc_base = base;
4705
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004706 /* Read all the optional properties below */
4707 rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp);
4708 if (rc < 0)
4709 chip->dt.cutoff_volt_mv = DEFAULT_CUTOFF_VOLT_MV;
4710 else
4711 chip->dt.cutoff_volt_mv = temp;
4712
4713 rc = of_property_read_u32(node, "qcom,fg-empty-voltage", &temp);
4714 if (rc < 0)
4715 chip->dt.empty_volt_mv = DEFAULT_EMPTY_VOLT_MV;
4716 else
4717 chip->dt.empty_volt_mv = temp;
4718
4719 rc = of_property_read_u32(node, "qcom,fg-vbatt-low-thr", &temp);
4720 if (rc < 0)
4721 chip->dt.vbatt_low_thr_mv = -EINVAL;
4722 else
4723 chip->dt.vbatt_low_thr_mv = temp;
4724
4725 rc = of_property_read_u32(node, "qcom,fg-chg-term-current", &temp);
4726 if (rc < 0)
4727 chip->dt.chg_term_curr_ma = DEFAULT_CHG_TERM_CURR_MA;
4728 else
4729 chip->dt.chg_term_curr_ma = temp;
4730
4731 rc = of_property_read_u32(node, "qcom,fg-sys-term-current", &temp);
4732 if (rc < 0)
4733 chip->dt.sys_term_curr_ma = DEFAULT_SYS_TERM_CURR_MA;
4734 else
4735 chip->dt.sys_term_curr_ma = temp;
4736
Subbaraman Narayanamurthya4e18882017-04-04 20:28:03 -07004737 rc = of_property_read_u32(node, "qcom,fg-chg-term-base-current", &temp);
4738 if (rc < 0)
4739 chip->dt.chg_term_base_curr_ma = DEFAULT_CHG_TERM_BASE_CURR_MA;
4740 else
4741 chip->dt.chg_term_base_curr_ma = temp;
4742
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004743 rc = of_property_read_u32(node, "qcom,fg-delta-soc-thr", &temp);
4744 if (rc < 0)
4745 chip->dt.delta_soc_thr = DEFAULT_DELTA_SOC_THR;
4746 else
4747 chip->dt.delta_soc_thr = temp;
4748
4749 rc = of_property_read_u32(node, "qcom,fg-recharge-soc-thr", &temp);
4750 if (rc < 0)
4751 chip->dt.recharge_soc_thr = DEFAULT_RECHARGE_SOC_THR;
4752 else
4753 chip->dt.recharge_soc_thr = temp;
4754
Subbaraman Narayanamurthy4cf5c1c2016-11-17 13:58:06 -08004755 rc = of_property_read_u32(node, "qcom,fg-recharge-voltage", &temp);
4756 if (rc < 0)
4757 chip->dt.recharge_volt_thr_mv = DEFAULT_RECHARGE_VOLT_MV;
4758 else
4759 chip->dt.recharge_volt_thr_mv = temp;
4760
Subbaraman Narayanamurthydeeaec722016-12-22 18:55:25 -08004761 chip->dt.auto_recharge_soc = of_property_read_bool(node,
4762 "qcom,fg-auto-recharge-soc");
4763
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004764 rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp);
4765 if (rc < 0)
4766 chip->dt.rsense_sel = SRC_SEL_BATFET_SMB;
4767 else
4768 chip->dt.rsense_sel = (u8)temp & SOURCE_SELECT_MASK;
4769
4770 chip->dt.jeita_thresholds[JEITA_COLD] = DEFAULT_BATT_TEMP_COLD;
4771 chip->dt.jeita_thresholds[JEITA_COOL] = DEFAULT_BATT_TEMP_COOL;
4772 chip->dt.jeita_thresholds[JEITA_WARM] = DEFAULT_BATT_TEMP_WARM;
4773 chip->dt.jeita_thresholds[JEITA_HOT] = DEFAULT_BATT_TEMP_HOT;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07004774 if (of_property_count_elems_of_size(node, "qcom,fg-jeita-thresholds",
4775 sizeof(u32)) == NUM_JEITA_LEVELS) {
4776 rc = of_property_read_u32_array(node,
4777 "qcom,fg-jeita-thresholds",
4778 chip->dt.jeita_thresholds, NUM_JEITA_LEVELS);
4779 if (rc < 0)
4780 pr_warn("Error reading Jeita thresholds, default values will be used rc:%d\n",
4781 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004782 }
4783
cyizhaofb3eec52017-01-24 17:08:55 +08004784 if (of_property_count_elems_of_size(node,
4785 "qcom,battery-thermal-coefficients",
4786 sizeof(u8)) == BATT_THERM_NUM_COEFFS) {
4787 rc = of_property_read_u8_array(node,
4788 "qcom,battery-thermal-coefficients",
4789 chip->dt.batt_therm_coeffs,
4790 BATT_THERM_NUM_COEFFS);
4791 if (rc < 0)
4792 pr_warn("Error reading battery thermal coefficients, rc:%d\n",
4793 rc);
4794 }
4795
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004796 rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-timer-charging",
4797 chip->dt.esr_timer_charging, NUM_ESR_TIMERS);
4798 if (rc < 0) {
4799 chip->dt.esr_timer_charging[TIMER_RETRY] = -EINVAL;
4800 chip->dt.esr_timer_charging[TIMER_MAX] = -EINVAL;
4801 }
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07004802
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004803 rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-timer-awake",
4804 chip->dt.esr_timer_awake, NUM_ESR_TIMERS);
4805 if (rc < 0) {
4806 chip->dt.esr_timer_awake[TIMER_RETRY] = -EINVAL;
4807 chip->dt.esr_timer_awake[TIMER_MAX] = -EINVAL;
4808 }
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07004809
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07004810 rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-timer-asleep",
4811 chip->dt.esr_timer_asleep, NUM_ESR_TIMERS);
4812 if (rc < 0) {
4813 chip->dt.esr_timer_asleep[TIMER_RETRY] = -EINVAL;
4814 chip->dt.esr_timer_asleep[TIMER_MAX] = -EINVAL;
4815 }
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07004816
Nicholas Troaste29dec92016-08-24 09:35:11 -07004817 chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
4818 if (chip->cyc_ctr.en)
4819 chip->cyc_ctr.id = 1;
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07004820
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07004821 chip->dt.force_load_profile = of_property_read_bool(node,
4822 "qcom,fg-force-load-profile");
4823
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07004824 rc = of_property_read_u32(node, "qcom,cl-start-capacity", &temp);
4825 if (rc < 0)
4826 chip->dt.cl_start_soc = DEFAULT_CL_START_SOC;
4827 else
4828 chip->dt.cl_start_soc = temp;
4829
4830 rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp);
4831 if (rc < 0)
4832 chip->dt.cl_min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC;
4833 else
4834 chip->dt.cl_min_temp = temp;
4835
4836 rc = of_property_read_u32(node, "qcom,cl-max-temp", &temp);
4837 if (rc < 0)
4838 chip->dt.cl_max_temp = DEFAULT_CL_MAX_TEMP_DECIDEGC;
4839 else
4840 chip->dt.cl_max_temp = temp;
4841
4842 rc = of_property_read_u32(node, "qcom,cl-max-increment", &temp);
4843 if (rc < 0)
4844 chip->dt.cl_max_cap_inc = DEFAULT_CL_MAX_INC_DECIPERC;
4845 else
4846 chip->dt.cl_max_cap_inc = temp;
4847
4848 rc = of_property_read_u32(node, "qcom,cl-max-decrement", &temp);
4849 if (rc < 0)
4850 chip->dt.cl_max_cap_dec = DEFAULT_CL_MAX_DEC_DECIPERC;
4851 else
4852 chip->dt.cl_max_cap_dec = temp;
4853
4854 rc = of_property_read_u32(node, "qcom,cl-min-limit", &temp);
4855 if (rc < 0)
4856 chip->dt.cl_min_cap_limit = DEFAULT_CL_MIN_LIM_DECIPERC;
4857 else
4858 chip->dt.cl_min_cap_limit = temp;
4859
4860 rc = of_property_read_u32(node, "qcom,cl-max-limit", &temp);
4861 if (rc < 0)
4862 chip->dt.cl_max_cap_limit = DEFAULT_CL_MAX_LIM_DECIPERC;
4863 else
4864 chip->dt.cl_max_cap_limit = temp;
4865
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07004866 rc = of_property_read_u32(node, "qcom,fg-jeita-hyst-temp", &temp);
4867 if (rc < 0)
4868 chip->dt.jeita_hyst_temp = -EINVAL;
4869 else
4870 chip->dt.jeita_hyst_temp = temp;
4871
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07004872 rc = of_property_read_u32(node, "qcom,fg-batt-temp-delta", &temp);
4873 if (rc < 0)
4874 chip->dt.batt_temp_delta = -EINVAL;
4875 else if (temp > BTEMP_DELTA_LOW && temp <= BTEMP_DELTA_HIGH)
4876 chip->dt.batt_temp_delta = temp;
4877
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07004878 chip->dt.hold_soc_while_full = of_property_read_bool(node,
4879 "qcom,hold-soc-while-full");
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004880
Subbaraman Narayanamurthy50fb7fd2017-07-25 20:01:25 -07004881 chip->dt.linearize_soc = of_property_read_bool(node,
4882 "qcom,linearize-soc");
4883
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07004884 rc = fg_parse_ki_coefficients(chip);
4885 if (rc < 0)
4886 pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
4887
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08004888 rc = of_property_read_u32(node, "qcom,fg-rconn-mohms", &temp);
Subbaraman Narayanamurthy8909f372017-03-14 19:50:57 -07004889 if (!rc)
Subbaraman Narayanamurthyc297f6de2016-11-28 18:05:20 -08004890 chip->dt.rconn_mohms = temp;
4891
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08004892 rc = of_property_read_u32(node, "qcom,fg-esr-filter-switch-temp",
4893 &temp);
4894 if (rc < 0)
4895 chip->dt.esr_flt_switch_temp = DEFAULT_ESR_FLT_TEMP_DECIDEGC;
4896 else
4897 chip->dt.esr_flt_switch_temp = temp;
4898
4899 rc = of_property_read_u32(node, "qcom,fg-esr-tight-filter-micro-pct",
4900 &temp);
4901 if (rc < 0)
4902 chip->dt.esr_tight_flt_upct = DEFAULT_ESR_TIGHT_FLT_UPCT;
4903 else
4904 chip->dt.esr_tight_flt_upct = temp;
4905
4906 rc = of_property_read_u32(node, "qcom,fg-esr-broad-filter-micro-pct",
4907 &temp);
4908 if (rc < 0)
4909 chip->dt.esr_broad_flt_upct = DEFAULT_ESR_BROAD_FLT_UPCT;
4910 else
4911 chip->dt.esr_broad_flt_upct = temp;
4912
4913 rc = of_property_read_u32(node, "qcom,fg-esr-tight-lt-filter-micro-pct",
4914 &temp);
4915 if (rc < 0)
4916 chip->dt.esr_tight_lt_flt_upct = DEFAULT_ESR_TIGHT_LT_FLT_UPCT;
4917 else
4918 chip->dt.esr_tight_lt_flt_upct = temp;
4919
4920 rc = of_property_read_u32(node, "qcom,fg-esr-broad-lt-filter-micro-pct",
4921 &temp);
4922 if (rc < 0)
4923 chip->dt.esr_broad_lt_flt_upct = DEFAULT_ESR_BROAD_LT_FLT_UPCT;
4924 else
4925 chip->dt.esr_broad_lt_flt_upct = temp;
Subbaraman Narayanamurthy94e63052017-02-09 18:06:14 -08004926
4927 rc = fg_parse_slope_limit_coefficients(chip);
4928 if (rc < 0)
4929 pr_err("Error in parsing slope limit coeffs, rc=%d\n", rc);
4930
Subbaraman Narayanamurthydcfc8662017-02-24 16:04:46 -08004931 rc = of_property_read_u32(node, "qcom,fg-esr-clamp-mohms", &temp);
4932 if (rc < 0)
4933 chip->dt.esr_clamp_mohms = DEFAULT_ESR_CLAMP_MOHMS;
4934 else
4935 chip->dt.esr_clamp_mohms = temp;
4936
Subbaraman Narayanamurthye14037f2017-03-16 19:14:58 -07004937 chip->dt.esr_pulse_thresh_ma = DEFAULT_ESR_PULSE_THRESH_MA;
4938 rc = of_property_read_u32(node, "qcom,fg-esr-pulse-thresh-ma", &temp);
4939 if (!rc) {
4940 /* ESR pulse qualification threshold range is 1-997 mA */
4941 if (temp > 0 && temp < 997)
4942 chip->dt.esr_pulse_thresh_ma = temp;
4943 }
4944
4945 chip->dt.esr_meas_curr_ma = DEFAULT_ESR_MEAS_CURR_MA;
4946 rc = of_property_read_u32(node, "qcom,fg-esr-meas-curr-ma", &temp);
4947 if (!rc) {
4948 /* ESR measurement current range is 60-240 mA */
4949 if (temp >= 60 || temp <= 240)
4950 chip->dt.esr_meas_curr_ma = temp;
4951 }
4952
Fenglin Wud10ccf12017-08-10 15:43:41 +08004953 chip->dt.bmd_en_delay_ms = DEFAULT_BMD_EN_DELAY_MS;
4954 rc = of_property_read_u32(node, "qcom,fg-bmd-en-delay-ms", &temp);
4955 if (!rc) {
4956 if (temp > DEFAULT_BMD_EN_DELAY_MS)
4957 chip->dt.bmd_en_delay_ms = temp;
4958 }
4959
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004960 return 0;
4961}
4962
4963static void fg_cleanup(struct fg_chip *chip)
4964{
Subbaraman Narayanamurthyf580cb92017-08-30 20:27:41 -07004965 int i;
4966
4967 for (i = 0; i < FG_IRQ_MAX; i++) {
4968 if (fg_irqs[i].irq)
4969 devm_free_irq(chip->dev, fg_irqs[i].irq, chip);
4970 }
4971
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004972 power_supply_unreg_notifier(&chip->nb);
Nicholas Troast69da2252016-09-07 16:17:47 -07004973 debugfs_remove_recursive(chip->dfs_root);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004974 if (chip->awake_votable)
4975 destroy_votable(chip->awake_votable);
4976
Subbaraman Narayanamurthy53448172017-03-15 12:47:00 -07004977 if (chip->delta_bsoc_irq_en_votable)
4978 destroy_votable(chip->delta_bsoc_irq_en_votable);
4979
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -07004980 if (chip->batt_miss_irq_en_votable)
4981 destroy_votable(chip->batt_miss_irq_en_votable);
4982
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004983 if (chip->batt_id_chan)
4984 iio_channel_release(chip->batt_id_chan);
4985
4986 dev_set_drvdata(chip->dev, NULL);
4987}
4988
4989static int fg_gen3_probe(struct platform_device *pdev)
4990{
4991 struct fg_chip *chip;
4992 struct power_supply_config fg_psy_cfg;
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08004993 int rc, msoc, volt_uv, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07004994
4995 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
4996 if (!chip)
4997 return -ENOMEM;
4998
4999 chip->dev = &pdev->dev;
5000 chip->debug_mask = &fg_gen3_debug_mask;
5001 chip->irqs = fg_irqs;
Nicholas Troast1769fd32016-09-07 09:20:58 -07005002 chip->charge_status = -EINVAL;
Subbaraman Narayanamurthy1bf973e2017-04-04 19:24:20 -07005003 chip->ki_coeff_full_soc = -EINVAL;
Nicholas Troast805c2422017-07-06 14:53:46 -07005004 chip->online_status = -EINVAL;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005005 chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
5006 if (!chip->regmap) {
5007 dev_err(chip->dev, "Parent regmap is unavailable\n");
5008 return -ENXIO;
5009 }
5010
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -08005011 chip->batt_id_chan = iio_channel_get(chip->dev, "rradc_batt_id");
5012 if (IS_ERR(chip->batt_id_chan)) {
5013 if (PTR_ERR(chip->batt_id_chan) != -EPROBE_DEFER)
5014 pr_err("batt_id_chan unavailable %ld\n",
5015 PTR_ERR(chip->batt_id_chan));
5016 rc = PTR_ERR(chip->batt_id_chan);
5017 chip->batt_id_chan = NULL;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005018 return rc;
5019 }
5020
Anirudh Ghayalddabeee2017-04-04 06:13:48 +05305021 rc = of_property_match_string(chip->dev->of_node,
5022 "io-channel-names", "rradc_die_temp");
5023 if (rc >= 0) {
5024 chip->die_temp_chan = iio_channel_get(chip->dev,
5025 "rradc_die_temp");
5026 if (IS_ERR(chip->die_temp_chan)) {
5027 if (PTR_ERR(chip->die_temp_chan) != -EPROBE_DEFER)
5028 pr_err("rradc_die_temp unavailable %ld\n",
5029 PTR_ERR(chip->die_temp_chan));
5030 rc = PTR_ERR(chip->die_temp_chan);
5031 chip->die_temp_chan = NULL;
5032 return rc;
5033 }
5034 }
5035
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005036 chip->awake_votable = create_votable("FG_WS", VOTE_SET_ANY, fg_awake_cb,
5037 chip);
5038 if (IS_ERR(chip->awake_votable)) {
5039 rc = PTR_ERR(chip->awake_votable);
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -07005040 chip->awake_votable = NULL;
Subbaraman Narayanamurthy53448172017-03-15 12:47:00 -07005041 goto exit;
5042 }
5043
5044 chip->delta_bsoc_irq_en_votable = create_votable("FG_DELTA_BSOC_IRQ",
5045 VOTE_SET_ANY,
5046 fg_delta_bsoc_irq_en_cb, chip);
5047 if (IS_ERR(chip->delta_bsoc_irq_en_votable)) {
5048 rc = PTR_ERR(chip->delta_bsoc_irq_en_votable);
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -07005049 chip->delta_bsoc_irq_en_votable = NULL;
5050 goto exit;
5051 }
5052
5053 chip->batt_miss_irq_en_votable = create_votable("FG_BATT_MISS_IRQ",
5054 VOTE_SET_ANY,
5055 fg_batt_miss_irq_en_cb, chip);
5056 if (IS_ERR(chip->batt_miss_irq_en_votable)) {
5057 rc = PTR_ERR(chip->batt_miss_irq_en_votable);
5058 chip->batt_miss_irq_en_votable = NULL;
Subbaraman Narayanamurthy53448172017-03-15 12:47:00 -07005059 goto exit;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005060 }
5061
Subbaraman Narayanamurthy7d333512017-01-20 18:34:28 -08005062 rc = fg_parse_dt(chip);
5063 if (rc < 0) {
5064 dev_err(chip->dev, "Error in reading DT parameters, rc:%d\n",
5065 rc);
5066 goto exit;
5067 }
5068
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005069 mutex_init(&chip->bus_lock);
5070 mutex_init(&chip->sram_rw_lock);
Nicholas Troaste29dec92016-08-24 09:35:11 -07005071 mutex_init(&chip->cyc_ctr.lock);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07005072 mutex_init(&chip->cl.lock);
Nicholas Troast805c2422017-07-06 14:53:46 -07005073 mutex_init(&chip->ttf.lock);
Subbaraman Narayanamurthy03f7d452017-01-06 15:47:24 -08005074 mutex_init(&chip->charge_full_lock);
Subbaraman Narayanamurthy3fbcbe92017-09-12 20:19:17 -07005075 mutex_init(&chip->qnovo_esr_ctrl_lock);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005076 init_completion(&chip->soc_update);
5077 init_completion(&chip->soc_ready);
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -07005078 init_completion(&chip->mem_grant);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005079 INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
5080 INIT_WORK(&chip->status_change_work, status_change_work);
Nicholas Troast805c2422017-07-06 14:53:46 -07005081 INIT_DELAYED_WORK(&chip->ttf_work, ttf_work);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08005082 INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005083
5084 rc = fg_memif_init(chip);
5085 if (rc < 0) {
5086 dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n",
5087 rc);
5088 goto exit;
5089 }
5090
Subbaraman Narayanamurthy2d62e9e2017-06-02 17:40:28 -07005091 platform_set_drvdata(pdev, chip);
5092
5093 rc = fg_register_interrupts(chip);
5094 if (rc < 0) {
5095 dev_err(chip->dev, "Error in registering interrupts, rc:%d\n",
5096 rc);
5097 goto exit;
5098 }
5099
5100 /* Keep SOC_UPDATE irq disabled until we require it */
5101 if (fg_irqs[SOC_UPDATE_IRQ].irq)
5102 disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
5103
5104 /* Keep BSOC_DELTA_IRQ disabled until we require it */
5105 vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER, false, 0);
5106
5107 /* Keep BATT_MISSING_IRQ disabled until we require it */
5108 vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, false, 0);
5109
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005110 rc = fg_hw_init(chip);
5111 if (rc < 0) {
5112 dev_err(chip->dev, "Error in initializing FG hardware, rc:%d\n",
5113 rc);
5114 goto exit;
5115 }
5116
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005117 /* Register the power supply */
5118 fg_psy_cfg.drv_data = chip;
5119 fg_psy_cfg.of_node = NULL;
5120 fg_psy_cfg.supplied_to = NULL;
5121 fg_psy_cfg.num_supplicants = 0;
5122 chip->fg_psy = devm_power_supply_register(chip->dev, &fg_psy_desc,
5123 &fg_psy_cfg);
5124 if (IS_ERR(chip->fg_psy)) {
5125 pr_err("failed to register fg_psy rc = %ld\n",
5126 PTR_ERR(chip->fg_psy));
5127 goto exit;
5128 }
5129
5130 chip->nb.notifier_call = fg_notifier_cb;
5131 rc = power_supply_reg_notifier(&chip->nb);
5132 if (rc < 0) {
5133 pr_err("Couldn't register psy notifier rc = %d\n", rc);
5134 goto exit;
5135 }
5136
Nicholas Troast69da2252016-09-07 16:17:47 -07005137 rc = fg_debugfs_create(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005138 if (rc < 0) {
5139 dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n",
5140 rc);
5141 goto exit;
5142 }
5143
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08005144 rc = fg_get_battery_voltage(chip, &volt_uv);
5145 if (!rc)
5146 rc = fg_get_prop_capacity(chip, &msoc);
5147
5148 if (!rc)
5149 rc = fg_get_battery_temp(chip, &batt_temp);
5150
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08005151 if (!rc) {
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08005152 pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n",
Subbaraman Narayanamurthy243fc3f2016-11-28 16:05:09 -08005153 msoc, volt_uv, batt_temp, chip->batt_id_ohms / 1000);
Subbaraman Narayanamurthyb99ea4c2016-12-22 15:10:09 -08005154 rc = fg_esr_filter_config(chip, batt_temp);
5155 if (rc < 0)
5156 pr_err("Error in configuring ESR filter rc:%d\n", rc);
5157 }
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08005158
5159 device_init_wakeup(chip->dev, true);
Subbaraman Narayanamurthyecc06022017-04-04 16:10:35 -07005160 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005161
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -08005162 pr_debug("FG GEN3 driver probed successfully\n");
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005163 return 0;
5164exit:
5165 fg_cleanup(chip);
5166 return rc;
5167}
5168
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07005169static int fg_gen3_suspend(struct device *dev)
5170{
5171 struct fg_chip *chip = dev_get_drvdata(dev);
5172 int rc;
5173
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07005174 rc = fg_esr_timer_config(chip, true);
5175 if (rc < 0)
5176 pr_err("Error in configuring ESR timer, rc=%d\n", rc);
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07005177
Nicholas Troast805c2422017-07-06 14:53:46 -07005178 cancel_delayed_work_sync(&chip->ttf_work);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08005179 if (fg_sram_dump)
5180 cancel_delayed_work_sync(&chip->sram_dump_work);
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07005181 return 0;
5182}
5183
5184static int fg_gen3_resume(struct device *dev)
5185{
5186 struct fg_chip *chip = dev_get_drvdata(dev);
5187 int rc;
5188
Subbaraman Narayanamurthy784bd5b2017-05-17 17:43:22 -07005189 rc = fg_esr_timer_config(chip, false);
5190 if (rc < 0)
5191 pr_err("Error in configuring ESR timer, rc=%d\n", rc);
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07005192
Nicholas Troast805c2422017-07-06 14:53:46 -07005193 schedule_delayed_work(&chip->ttf_work, 0);
Subbaraman Narayanamurthyeca9bb32016-12-09 16:43:52 -08005194 if (fg_sram_dump)
5195 schedule_delayed_work(&chip->sram_dump_work,
5196 msecs_to_jiffies(fg_sram_dump_period_ms));
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07005197 return 0;
5198}
5199
5200static const struct dev_pm_ops fg_gen3_pm_ops = {
5201 .suspend = fg_gen3_suspend,
5202 .resume = fg_gen3_resume,
5203};
5204
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005205static int fg_gen3_remove(struct platform_device *pdev)
5206{
5207 struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
5208
5209 fg_cleanup(chip);
5210 return 0;
5211}
5212
Subbaraman Narayanamurthy9b6c38a2017-07-26 16:46:41 -07005213static void fg_gen3_shutdown(struct platform_device *pdev)
5214{
5215 struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
5216 int rc, bsoc;
5217
5218 if (chip->charge_full) {
5219 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
5220 if (rc < 0) {
5221 pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
5222 return;
5223 }
5224
5225 /* We need 2 most significant bytes here */
5226 bsoc = (u32)bsoc >> 16;
5227
5228 rc = fg_configure_full_soc(chip, bsoc);
5229 if (rc < 0) {
5230 pr_err("Error in configuring full_soc, rc=%d\n", rc);
5231 return;
5232 }
5233 }
5234}
5235
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005236static const struct of_device_id fg_gen3_match_table[] = {
5237 {.compatible = FG_GEN3_DEV_NAME},
5238 {},
5239};
5240
5241static struct platform_driver fg_gen3_driver = {
5242 .driver = {
5243 .name = FG_GEN3_DEV_NAME,
5244 .owner = THIS_MODULE,
5245 .of_match_table = fg_gen3_match_table,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07005246 .pm = &fg_gen3_pm_ops,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005247 },
5248 .probe = fg_gen3_probe,
5249 .remove = fg_gen3_remove,
Subbaraman Narayanamurthy9b6c38a2017-07-26 16:46:41 -07005250 .shutdown = fg_gen3_shutdown,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07005251};
5252
5253static int __init fg_gen3_init(void)
5254{
5255 return platform_driver_register(&fg_gen3_driver);
5256}
5257
5258static void __exit fg_gen3_exit(void)
5259{
5260 return platform_driver_unregister(&fg_gen3_driver);
5261}
5262
5263module_init(fg_gen3_init);
5264module_exit(fg_gen3_exit);
5265
5266MODULE_DESCRIPTION("QPNP Fuel gauge GEN3 driver");
5267MODULE_LICENSE("GPL v2");
5268MODULE_ALIAS("platform:" FG_GEN3_DEV_NAME);