blob: a07cb81ed7db50eaf21ae7e2379e04b3d67c3df7 [file] [log] [blame]
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "FG: %s: " fmt, __func__
14
15#include <linux/of.h>
16#include <linux/of_irq.h>
17#include <linux/of_platform.h>
18#include <linux/of_batterydata.h>
19#include <linux/platform_device.h>
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070020#include <linux/iio/consumer.h>
21#include <linux/qpnp/qpnp-revid.h>
22#include "fg-core.h"
23#include "fg-reg.h"
24
25#define FG_GEN3_DEV_NAME "qcom,fg-gen3"
26
27#define PERPH_SUBTYPE_REG 0x05
28#define FG_BATT_SOC_PMICOBALT 0x10
29#define FG_BATT_INFO_PMICOBALT 0x11
30#define FG_MEM_INFO_PMICOBALT 0x0D
31
32/* SRAM address and offset in ascending order */
33#define CUTOFF_VOLT_WORD 5
34#define CUTOFF_VOLT_OFFSET 0
35#define SYS_TERM_CURR_WORD 6
36#define SYS_TERM_CURR_OFFSET 0
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -070037#define VBATT_FULL_WORD 7
38#define VBATT_FULL_OFFSET 0
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -070039#define KI_COEFF_MED_DISCHG_WORD 9
40#define KI_COEFF_MED_DISCHG_OFFSET 3
41#define KI_COEFF_HI_DISCHG_WORD 10
42#define KI_COEFF_HI_DISCHG_OFFSET 0
43#define KI_COEFF_LOW_DISCHG_WORD 10
44#define KI_COEFF_LOW_DISCHG_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070045#define DELTA_SOC_THR_WORD 12
46#define DELTA_SOC_THR_OFFSET 3
47#define RECHARGE_SOC_THR_WORD 14
48#define RECHARGE_SOC_THR_OFFSET 0
49#define CHG_TERM_CURR_WORD 14
50#define CHG_TERM_CURR_OFFSET 1
51#define EMPTY_VOLT_WORD 15
52#define EMPTY_VOLT_OFFSET 0
53#define VBATT_LOW_WORD 15
54#define VBATT_LOW_OFFSET 1
Nicholas Troastdcf8fe62016-08-04 14:30:02 -070055#define ESR_TIMER_DISCHG_MAX_WORD 17
56#define ESR_TIMER_DISCHG_MAX_OFFSET 0
57#define ESR_TIMER_DISCHG_INIT_WORD 17
58#define ESR_TIMER_DISCHG_INIT_OFFSET 2
59#define ESR_TIMER_CHG_MAX_WORD 18
60#define ESR_TIMER_CHG_MAX_OFFSET 0
61#define ESR_TIMER_CHG_INIT_WORD 18
62#define ESR_TIMER_CHG_INIT_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070063#define PROFILE_LOAD_WORD 24
64#define PROFILE_LOAD_OFFSET 0
65#define NOM_CAP_WORD 58
66#define NOM_CAP_OFFSET 0
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -070067#define ACT_BATT_CAP_BKUP_WORD 74
68#define ACT_BATT_CAP_BKUP_OFFSET 0
Nicholas Troaste29dec92016-08-24 09:35:11 -070069#define CYCLE_COUNT_WORD 75
70#define CYCLE_COUNT_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070071#define PROFILE_INTEGRITY_WORD 79
72#define PROFILE_INTEGRITY_OFFSET 3
73#define BATT_SOC_WORD 91
74#define BATT_SOC_OFFSET 0
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -070075#define FULL_SOC_WORD 93
76#define FULL_SOC_OFFSET 2
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070077#define MONOTONIC_SOC_WORD 94
78#define MONOTONIC_SOC_OFFSET 2
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -070079#define CC_SOC_WORD 95
80#define CC_SOC_OFFSET 0
81#define CC_SOC_SW_WORD 96
82#define CC_SOC_SW_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070083#define VOLTAGE_PRED_WORD 97
84#define VOLTAGE_PRED_OFFSET 0
85#define OCV_WORD 97
86#define OCV_OFFSET 2
87#define RSLOW_WORD 101
88#define RSLOW_OFFSET 0
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -070089#define ACT_BATT_CAP_WORD 117
90#define ACT_BATT_CAP_OFFSET 0
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070091#define LAST_BATT_SOC_WORD 119
92#define LAST_BATT_SOC_OFFSET 0
93#define LAST_MONOTONIC_SOC_WORD 119
94#define LAST_MONOTONIC_SOC_OFFSET 2
Nicholas Troast69da2252016-09-07 16:17:47 -070095#define ALG_FLAGS_WORD 120
96#define ALG_FLAGS_OFFSET 1
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070097
Nicholas Troasta2b40372016-08-15 10:45:39 -070098/* v2 SRAM address and offset in ascending order */
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -070099#define KI_COEFF_LOW_DISCHG_v2_WORD 9
100#define KI_COEFF_LOW_DISCHG_v2_OFFSET 3
101#define KI_COEFF_MED_DISCHG_v2_WORD 10
102#define KI_COEFF_MED_DISCHG_v2_OFFSET 0
103#define KI_COEFF_HI_DISCHG_v2_WORD 10
104#define KI_COEFF_HI_DISCHG_v2_OFFSET 1
Nicholas Troasta2b40372016-08-15 10:45:39 -0700105#define DELTA_SOC_THR_v2_WORD 13
106#define DELTA_SOC_THR_v2_OFFSET 0
107#define RECHARGE_SOC_THR_v2_WORD 14
108#define RECHARGE_SOC_THR_v2_OFFSET 1
109#define CHG_TERM_CURR_v2_WORD 15
110#define CHG_TERM_CURR_v2_OFFSET 1
111#define EMPTY_VOLT_v2_WORD 15
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700112#define EMPTY_VOLT_v2_OFFSET 3
Nicholas Troasta2b40372016-08-15 10:45:39 -0700113#define VBATT_LOW_v2_WORD 16
114#define VBATT_LOW_v2_OFFSET 0
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700115#define FLOAT_VOLT_v2_WORD 16
116#define FLOAT_VOLT_v2_OFFSET 2
Nicholas Troasta2b40372016-08-15 10:45:39 -0700117
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700118static int fg_decode_voltage_15b(struct fg_sram_param *sp,
119 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700120static int fg_decode_value_16b(struct fg_sram_param *sp,
121 enum fg_sram_param_id id, int val);
122static int fg_decode_default(struct fg_sram_param *sp,
123 enum fg_sram_param_id id, int val);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700124static int fg_decode_cc_soc(struct fg_sram_param *sp,
125 enum fg_sram_param_id id, int value);
Nicholas Troasta2b40372016-08-15 10:45:39 -0700126static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700127 enum fg_sram_param_id id, int val_mv, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700128static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700129 enum fg_sram_param_id id, int val_ma, u8 *buf);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700130static void fg_encode_default(struct fg_sram_param *sp,
131 enum fg_sram_param_id id, int val, u8 *buf);
132
Nicholas Troasta2b40372016-08-15 10:45:39 -0700133#define PARAM(_id, _addr_word, _addr_byte, _len, _num, _den, _offset, \
134 _enc, _dec) \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700135 [FG_SRAM_##_id] = { \
Nicholas Troasta2b40372016-08-15 10:45:39 -0700136 .addr_word = _addr_word, \
137 .addr_byte = _addr_byte, \
138 .len = _len, \
139 .numrtr = _num, \
140 .denmtr = _den, \
141 .offset = _offset, \
142 .encode = _enc, \
143 .decode = _dec, \
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700144 } \
145
146static struct fg_sram_param pmicobalt_v1_sram_params[] = {
Nicholas Troasta2b40372016-08-15 10:45:39 -0700147 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700148 fg_decode_default),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700149 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700150 1000, 0, NULL, fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700151 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700152 fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700153 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700154 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700155 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
156 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700157 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
158 fg_decode_cc_soc),
159 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
160 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700161 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
162 1, 1, 0, NULL, fg_decode_default),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700163 /* Entries below here are configurable during initialization */
164 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700165 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700166 PARAM(EMPTY_VOLT, EMPTY_VOLT_WORD, EMPTY_VOLT_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700167 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700168 PARAM(VBATT_LOW, VBATT_LOW_WORD, VBATT_LOW_OFFSET, 1, 100000, 390625,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700169 -2500, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700170 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
171 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700172 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700173 1000000, 122070, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700174 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700175 100000, 390625, 0, fg_encode_current, NULL),
Subbaraman Narayanamurthy6234f342016-09-22 18:11:42 -0700176 PARAM(DELTA_SOC_THR, DELTA_SOC_THR_WORD, DELTA_SOC_THR_OFFSET, 1, 2048,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700177 100, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700178 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_WORD, RECHARGE_SOC_THR_OFFSET,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700179 1, 256, 100, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700180 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700181 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
182 NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700183 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700184 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700185 NULL),
186 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700187 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700188 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700189 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700190 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD,
191 KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 244141, 0,
192 fg_encode_default, NULL),
193 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD,
194 KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 244141, 0,
195 fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700196};
197
198static struct fg_sram_param pmicobalt_v2_sram_params[] = {
199 PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700200 fg_decode_default),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700201 PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700202 1000, 0, NULL, fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700203 PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700204 fg_decode_voltage_15b),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700205 PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
206 fg_decode_value_16b),
Nicholas Troast69da2252016-09-07 16:17:47 -0700207 PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
208 fg_decode_default),
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700209 PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL,
210 fg_decode_cc_soc),
211 PARAM(CC_SOC_SW, CC_SOC_SW_WORD, CC_SOC_SW_OFFSET, 4, 1, 1, 0, NULL,
212 fg_decode_cc_soc),
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700213 PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
214 1, 1, 0, NULL, fg_decode_default),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700215 /* Entries below here are configurable during initialization */
216 PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
217 244141, 0, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -0700218 PARAM(EMPTY_VOLT, EMPTY_VOLT_v2_WORD, EMPTY_VOLT_v2_OFFSET, 1, 1000,
219 15625, -2000, fg_encode_voltage, NULL),
220 PARAM(VBATT_LOW, VBATT_LOW_v2_WORD, VBATT_LOW_v2_OFFSET, 1, 1000,
221 15625, -2000, fg_encode_voltage, NULL),
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700222 PARAM(FLOAT_VOLT, FLOAT_VOLT_v2_WORD, FLOAT_VOLT_v2_OFFSET, 1, 1000,
223 15625, -2000, fg_encode_voltage, NULL),
224 PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
225 244141, 0, fg_encode_voltage, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700226 PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
227 1000000, 122070, 0, fg_encode_current, NULL),
228 PARAM(CHG_TERM_CURR, CHG_TERM_CURR_v2_WORD, CHG_TERM_CURR_v2_OFFSET, 1,
229 100000, 390625, 0, fg_encode_current, NULL),
230 PARAM(DELTA_SOC_THR, DELTA_SOC_THR_v2_WORD, DELTA_SOC_THR_v2_OFFSET, 1,
Subbaraman Narayanamurthy6234f342016-09-22 18:11:42 -0700231 2048, 100, 0, fg_encode_default, NULL),
Nicholas Troasta2b40372016-08-15 10:45:39 -0700232 PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD,
233 RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default,
234 NULL),
235 PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD,
236 ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default,
237 NULL),
238 PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD,
239 ESR_TIMER_DISCHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default,
240 NULL),
241 PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD,
242 ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
243 PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
244 ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -0700245 PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_v2_WORD,
246 KI_COEFF_MED_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
247 fg_encode_default, NULL),
248 PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_v2_WORD,
249 KI_COEFF_HI_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
250 fg_encode_default, NULL),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700251};
252
Nicholas Troast69da2252016-09-07 16:17:47 -0700253static struct fg_alg_flag pmicobalt_v1_alg_flags[] = {
254 [ALG_FLAG_SOC_LT_OTG_MIN] = {
255 .name = "SOC_LT_OTG_MIN",
256 .bit = BIT(0),
257 },
258 [ALG_FLAG_SOC_LT_RECHARGE] = {
259 .name = "SOC_LT_RECHARGE",
260 .bit = BIT(1),
261 },
262 [ALG_FLAG_IBATT_LT_ITERM] = {
263 .name = "IBATT_LT_ITERM",
264 .bit = BIT(2),
265 },
266 [ALG_FLAG_IBATT_GT_HPM] = {
267 .name = "IBATT_GT_HPM",
268 .bit = BIT(3),
269 },
270 [ALG_FLAG_IBATT_GT_UPM] = {
271 .name = "IBATT_GT_UPM",
272 .bit = BIT(4),
273 },
274 [ALG_FLAG_VBATT_LT_RECHARGE] = {
275 .name = "VBATT_LT_RECHARGE",
276 .bit = BIT(5),
277 },
278 [ALG_FLAG_VBATT_GT_VFLOAT] = {
279 .invalid = true,
280 },
281};
282
283static struct fg_alg_flag pmicobalt_v2_alg_flags[] = {
284 [ALG_FLAG_SOC_LT_OTG_MIN] = {
285 .name = "SOC_LT_OTG_MIN",
286 .bit = BIT(0),
287 },
288 [ALG_FLAG_SOC_LT_RECHARGE] = {
289 .name = "SOC_LT_RECHARGE",
290 .bit = BIT(1),
291 },
292 [ALG_FLAG_IBATT_LT_ITERM] = {
293 .name = "IBATT_LT_ITERM",
294 .bit = BIT(2),
295 },
296 [ALG_FLAG_IBATT_GT_HPM] = {
297 .name = "IBATT_GT_HPM",
298 .bit = BIT(4),
299 },
300 [ALG_FLAG_IBATT_GT_UPM] = {
301 .name = "IBATT_GT_UPM",
302 .bit = BIT(5),
303 },
304 [ALG_FLAG_VBATT_LT_RECHARGE] = {
305 .name = "VBATT_LT_RECHARGE",
306 .bit = BIT(6),
307 },
308 [ALG_FLAG_VBATT_GT_VFLOAT] = {
309 .name = "VBATT_GT_VFLOAT",
310 .bit = BIT(7),
311 },
312};
313
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700314static int fg_gen3_debug_mask;
315module_param_named(
316 debug_mask, fg_gen3_debug_mask, int, 0600
317);
318
319static int fg_sram_update_period_ms = 30000;
320module_param_named(
321 sram_update_period_ms, fg_sram_update_period_ms, int, 0600
322);
323
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700324static bool fg_sram_dump;
325module_param_named(
326 sram_dump, fg_sram_dump, bool, 0600
327);
328
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -0700329static int fg_restart;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -0700330
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700331/* All getters HERE */
332
Subbaraman Narayanamurthy68d105c2016-10-03 18:30:32 -0700333#define VOLTAGE_15BIT_MASK GENMASK(14, 0)
334static int fg_decode_voltage_15b(struct fg_sram_param *sp,
335 enum fg_sram_param_id id, int value)
336{
337 value &= VOLTAGE_15BIT_MASK;
338 sp[id].value = div_u64((u64)value * sp[id].numrtr, sp[id].denmtr);
339 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
340 sp[id].value);
341 return sp[id].value;
342}
343
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700344static int fg_decode_cc_soc(struct fg_sram_param *sp,
345 enum fg_sram_param_id id, int value)
346{
347 sp[id].value = div_s64((s64)value * sp[id].numrtr, sp[id].denmtr);
348 sp[id].value = sign_extend32(sp[id].value, 31);
349 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
350 sp[id].value);
351 return sp[id].value;
352}
353
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700354static int fg_decode_value_16b(struct fg_sram_param *sp,
355 enum fg_sram_param_id id, int value)
356{
357 sp[id].value = div_u64((u64)(u16)value * sp[id].numrtr, sp[id].denmtr);
358 pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
359 sp[id].value);
360 return sp[id].value;
361}
362
Nicholas Troaste29dec92016-08-24 09:35:11 -0700363static int fg_decode_default(struct fg_sram_param *sp, enum fg_sram_param_id id,
364 int value)
365{
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700366 sp[id].value = value;
367 return sp[id].value;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700368}
369
370static int fg_decode(struct fg_sram_param *sp, enum fg_sram_param_id id,
371 int value)
372{
373 if (!sp[id].decode) {
374 pr_err("No decoding function for parameter %d\n", id);
375 return -EINVAL;
376 }
377
378 return sp[id].decode(sp, id, value);
379}
380
Nicholas Troasta2b40372016-08-15 10:45:39 -0700381static void fg_encode_voltage(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700382 enum fg_sram_param_id id, int val_mv, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700383{
384 int i, mask = 0xff;
385 int64_t temp;
386
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700387 val_mv += sp[id].offset;
388 temp = (int64_t)div_u64((u64)val_mv * sp[id].numrtr, sp[id].denmtr);
389 pr_debug("temp: %llx id: %d, val_mv: %d, buf: [ ", temp, id, val_mv);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700390 for (i = 0; i < sp[id].len; i++) {
391 buf[i] = temp & mask;
392 temp >>= 8;
393 pr_debug("%x ", buf[i]);
394 }
395 pr_debug("]\n");
396}
397
398static void fg_encode_current(struct fg_sram_param *sp,
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700399 enum fg_sram_param_id id, int val_ma, u8 *buf)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700400{
401 int i, mask = 0xff;
402 int64_t temp;
403 s64 current_ma;
404
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700405 current_ma = val_ma;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700406 temp = (int64_t)div_s64(current_ma * sp[id].numrtr, sp[id].denmtr);
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700407 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val_ma);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700408 for (i = 0; i < sp[id].len; i++) {
409 buf[i] = temp & mask;
410 temp >>= 8;
411 pr_debug("%x ", buf[i]);
412 }
413 pr_debug("]\n");
414}
415
416static void fg_encode_default(struct fg_sram_param *sp,
417 enum fg_sram_param_id id, int val, u8 *buf)
418{
419 int i, mask = 0xff;
420 int64_t temp;
421
422 temp = DIV_ROUND_CLOSEST(val * sp[id].numrtr, sp[id].denmtr);
423 pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val);
424 for (i = 0; i < sp[id].len; i++) {
425 buf[i] = temp & mask;
426 temp >>= 8;
427 pr_debug("%x ", buf[i]);
428 }
429 pr_debug("]\n");
430}
431
432static void fg_encode(struct fg_sram_param *sp, enum fg_sram_param_id id,
433 int val, u8 *buf)
434{
435 if (!sp[id].encode) {
436 pr_err("No encoding function for parameter %d\n", id);
437 return;
438 }
439
440 sp[id].encode(sp, id, val, buf);
441}
442
443/*
444 * Please make sure *_sram_params table has the entry for the parameter
445 * obtained through this function. In addition to address, offset,
446 * length from where this SRAM parameter is read, a decode function
447 * need to be specified.
448 */
449static int fg_get_sram_prop(struct fg_chip *chip, enum fg_sram_param_id id,
450 int *val)
451{
452 int temp, rc, i;
453 u8 buf[4];
454
455 if (id < 0 || id > FG_SRAM_MAX || chip->sp[id].len > sizeof(buf))
456 return -EINVAL;
457
Subbaraman Narayanamurthy0a749db2016-10-03 18:33:19 -0700458 if (chip->battery_missing)
459 return -ENODATA;
460
Nicholas Troasta2b40372016-08-15 10:45:39 -0700461 rc = fg_sram_read(chip, chip->sp[id].addr_word, chip->sp[id].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700462 buf, chip->sp[id].len, FG_IMA_DEFAULT);
463 if (rc < 0) {
464 pr_err("Error reading address 0x%04x[%d] rc=%d\n",
Nicholas Troasta2b40372016-08-15 10:45:39 -0700465 chip->sp[id].addr_word, chip->sp[id].addr_byte, rc);
Nicholas Troastb2d71742016-08-04 14:31:41 -0700466 return rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700467 }
468
469 for (i = 0, temp = 0; i < chip->sp[id].len; i++)
470 temp |= buf[i] << (8 * i);
471
472 *val = fg_decode(chip->sp, id, temp);
473 return 0;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700474}
475
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700476#define CC_SOC_30BIT GENMASK(29, 0)
477static int fg_get_cc_soc(struct fg_chip *chip, int *val)
478{
479 int rc, cc_soc;
480
481 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC, &cc_soc);
482 if (rc < 0) {
483 pr_err("Error in getting CC_SOC, rc=%d\n", rc);
484 return rc;
485 }
486
487 *val = div_s64(cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
488 return 0;
489}
490
491static int fg_get_cc_soc_sw(struct fg_chip *chip, int *val)
492{
493 int rc, cc_soc;
494
495 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc);
496 if (rc < 0) {
497 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
498 return rc;
499 }
500
501 *val = div_s64(cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
502 return 0;
503}
504
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700505#define BATT_TEMP_NUMR 1
506#define BATT_TEMP_DENR 1
507static int fg_get_battery_temp(struct fg_chip *chip, int *val)
508{
Subbaraman Narayanamurthyfabbb8e2016-10-21 16:55:09 -0700509 int rc = 0, temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700510 u8 buf[2];
511
512 rc = fg_read(chip, BATT_INFO_BATT_TEMP_LSB(chip), buf, 2);
513 if (rc < 0) {
514 pr_err("failed to read addr=0x%04x, rc=%d\n",
515 BATT_INFO_BATT_TEMP_LSB(chip), rc);
516 return rc;
517 }
518
519 temp = ((buf[1] & BATT_TEMP_MSB_MASK) << 8) |
520 (buf[0] & BATT_TEMP_LSB_MASK);
521 temp = DIV_ROUND_CLOSEST(temp, 4);
522
523 /* Value is in Kelvin; Convert it to deciDegC */
524 temp = (temp - 273) * 10;
525 *val = temp;
526 return 0;
527}
528
529#define BATT_ESR_NUMR 244141
530#define BATT_ESR_DENR 1000
531static int fg_get_battery_esr(struct fg_chip *chip, int *val)
532{
533 int rc = 0;
534 u16 temp = 0;
535 u8 buf[2];
536
537 rc = fg_read(chip, BATT_INFO_ESR_LSB(chip), buf, 2);
538 if (rc < 0) {
539 pr_err("failed to read addr=0x%04x, rc=%d\n",
540 BATT_INFO_ESR_LSB(chip), rc);
541 return rc;
542 }
543
544 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4)
545 temp = ((buf[0] & ESR_MSB_MASK) << 8) |
546 (buf[1] & ESR_LSB_MASK);
547 else
548 temp = ((buf[1] & ESR_MSB_MASK) << 8) |
549 (buf[0] & ESR_LSB_MASK);
550
551 pr_debug("buf: %x %x temp: %x\n", buf[0], buf[1], temp);
552 *val = div_u64((u64)temp * BATT_ESR_NUMR, BATT_ESR_DENR);
553 return 0;
554}
555
556static int fg_get_battery_resistance(struct fg_chip *chip, int *val)
557{
558 int rc, esr, rslow;
559
560 rc = fg_get_battery_esr(chip, &esr);
561 if (rc < 0) {
562 pr_err("failed to get ESR, rc=%d\n", rc);
563 return rc;
564 }
565
566 rc = fg_get_sram_prop(chip, FG_SRAM_RSLOW, &rslow);
567 if (rc < 0) {
568 pr_err("failed to get Rslow, rc=%d\n", rc);
569 return rc;
570 }
571
572 *val = esr + rslow;
573 return 0;
574}
575
576#define BATT_CURRENT_NUMR 488281
577#define BATT_CURRENT_DENR 1000
578static int fg_get_battery_current(struct fg_chip *chip, int *val)
579{
580 int rc = 0;
581 int64_t temp = 0;
582 u8 buf[2];
583
584 rc = fg_read(chip, BATT_INFO_IBATT_LSB(chip), buf, 2);
585 if (rc < 0) {
586 pr_err("failed to read addr=0x%04x, rc=%d\n",
587 BATT_INFO_IBATT_LSB(chip), rc);
588 return rc;
589 }
590
591 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4)
592 temp = buf[0] << 8 | buf[1];
593 else
594 temp = buf[1] << 8 | buf[0];
595
596 pr_debug("buf: %x %x temp: %llx\n", buf[0], buf[1], temp);
597 /* Sign bit is bit 15 */
598 temp = twos_compliment_extend(temp, 15);
599 *val = div_s64((s64)temp * BATT_CURRENT_NUMR, BATT_CURRENT_DENR);
600 return 0;
601}
602
603#define BATT_VOLTAGE_NUMR 122070
604#define BATT_VOLTAGE_DENR 1000
605static int fg_get_battery_voltage(struct fg_chip *chip, int *val)
606{
607 int rc = 0;
608 u16 temp = 0;
609 u8 buf[2];
610
611 rc = fg_read(chip, BATT_INFO_VBATT_LSB(chip), buf, 2);
612 if (rc < 0) {
613 pr_err("failed to read addr=0x%04x, rc=%d\n",
614 BATT_INFO_VBATT_LSB(chip), rc);
615 return rc;
616 }
617
618 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4)
619 temp = buf[0] << 8 | buf[1];
620 else
621 temp = buf[1] << 8 | buf[0];
622
623 pr_debug("buf: %x %x temp: %x\n", buf[0], buf[1], temp);
624 *val = div_u64((u64)temp * BATT_VOLTAGE_NUMR, BATT_VOLTAGE_DENR);
625 return 0;
626}
627
628#define MAX_TRIES_SOC 5
629static int fg_get_msoc_raw(struct fg_chip *chip, int *val)
630{
631 u8 cap[2];
632 int rc, tries = 0;
633
634 while (tries < MAX_TRIES_SOC) {
635 rc = fg_read(chip, BATT_SOC_FG_MONOTONIC_SOC(chip), cap, 2);
636 if (rc < 0) {
637 pr_err("failed to read addr=0x%04x, rc=%d\n",
638 BATT_SOC_FG_MONOTONIC_SOC(chip), rc);
639 return rc;
640 }
641
642 if (cap[0] == cap[1])
643 break;
644
645 tries++;
646 }
647
648 if (tries == MAX_TRIES_SOC) {
649 pr_err("shadow registers do not match\n");
650 return -EINVAL;
651 }
652
653 fg_dbg(chip, FG_POWER_SUPPLY, "raw: 0x%02x\n", cap[0]);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700654 *val = cap[0];
655 return 0;
656}
657
658#define FULL_CAPACITY 100
659#define FULL_SOC_RAW 255
660static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
661{
662 int rc, msoc;
663
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -0700664 if (chip->charge_full) {
665 *val = FULL_CAPACITY;
666 return 0;
667 }
668
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700669 rc = fg_get_msoc_raw(chip, &msoc);
670 if (rc < 0)
671 return rc;
672
673 *val = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
674 return 0;
675}
676
677#define DEFAULT_BATT_TYPE "Unknown Battery"
678#define MISSING_BATT_TYPE "Missing Battery"
679#define LOADING_BATT_TYPE "Loading Battery"
680static const char *fg_get_battery_type(struct fg_chip *chip)
681{
682 if (chip->battery_missing)
683 return MISSING_BATT_TYPE;
684
685 if (chip->bp.batt_type_str) {
686 if (chip->profile_loaded)
687 return chip->bp.batt_type_str;
688 else
689 return LOADING_BATT_TYPE;
690 }
691
692 return DEFAULT_BATT_TYPE;
693}
694
695static int fg_get_batt_id(struct fg_chip *chip, int *val)
696{
697 int rc, batt_id = -EINVAL;
698
699 if (!chip->batt_id_chan)
700 return -EINVAL;
701
702 rc = iio_read_channel_processed(chip->batt_id_chan, &batt_id);
703 if (rc < 0) {
704 pr_err("Error in reading batt_id channel, rc:%d\n", rc);
705 return rc;
706 }
707
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700708 fg_dbg(chip, FG_STATUS, "batt_id: %d\n", batt_id);
709
710 *val = batt_id;
711 return 0;
712}
713
714static int fg_get_batt_profile(struct fg_chip *chip)
715{
716 struct device_node *node = chip->dev->of_node;
717 struct device_node *batt_node, *profile_node;
718 const char *data;
719 int rc, len, batt_id;
720
721 rc = fg_get_batt_id(chip, &batt_id);
722 if (rc < 0) {
723 pr_err("Error in getting batt_id rc:%d\n", rc);
724 return rc;
725 }
726
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700727 batt_id /= 1000;
728 chip->batt_id = batt_id;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700729 batt_node = of_find_node_by_name(node, "qcom,battery-data");
730 if (!batt_node) {
731 pr_err("Batterydata not available\n");
732 return -ENXIO;
733 }
734
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700735 profile_node = of_batterydata_get_best_profile(batt_node, batt_id,
736 NULL);
737 if (IS_ERR(profile_node))
738 return PTR_ERR(profile_node);
739
740 if (!profile_node) {
741 pr_err("couldn't find profile handle\n");
742 return -ENODATA;
743 }
744
745 rc = of_property_read_string(profile_node, "qcom,battery-type",
746 &chip->bp.batt_type_str);
747 if (rc < 0) {
748 pr_err("battery type unavailable, rc:%d\n", rc);
749 return rc;
750 }
751
752 rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv",
753 &chip->bp.float_volt_uv);
754 if (rc < 0) {
755 pr_err("battery float voltage unavailable, rc:%d\n", rc);
756 chip->bp.float_volt_uv = -EINVAL;
757 }
758
759 rc = of_property_read_u32(profile_node, "qcom,nom-batt-capacity-mah",
760 &chip->bp.fastchg_curr_ma);
761 if (rc < 0) {
762 pr_err("battery nominal capacity unavailable, rc:%d\n", rc);
763 chip->bp.fastchg_curr_ma = -EINVAL;
764 }
765
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700766 rc = of_property_read_u32(profile_node, "qcom,fg-cc-cv-threshold-mv",
767 &chip->bp.vbatt_full_mv);
768 if (rc < 0) {
769 pr_err("battery cc_cv threshold unavailable, rc:%d\n", rc);
770 chip->bp.vbatt_full_mv = -EINVAL;
771 }
772
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700773 data = of_get_property(profile_node, "qcom,fg-profile-data", &len);
774 if (!data) {
775 pr_err("No profile data available\n");
776 return -ENODATA;
777 }
778
779 if (len != PROFILE_LEN) {
780 pr_err("battery profile incorrect size: %d\n", len);
781 return -EINVAL;
782 }
783
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -0700784 chip->profile_available = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700785 memcpy(chip->batt_profile, data, len);
786 return 0;
787}
788
789static inline void get_temp_setpoint(int threshold, u8 *val)
790{
791 /* Resolution is 0.5C. Base is -30C. */
792 *val = DIV_ROUND_CLOSEST((threshold + 30) * 10, 5);
793}
794
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -0700795static inline void get_batt_temp_delta(int delta, u8 *val)
796{
797 switch (delta) {
798 case 2:
799 *val = BTEMP_DELTA_2K;
800 break;
801 case 4:
802 *val = BTEMP_DELTA_4K;
803 break;
804 case 6:
805 *val = BTEMP_DELTA_6K;
806 break;
807 case 10:
808 *val = BTEMP_DELTA_10K;
809 break;
810 default:
811 *val = BTEMP_DELTA_2K;
812 break;
813 };
814}
815
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700816static int fg_set_esr_timer(struct fg_chip *chip, int cycles, bool charging,
817 int flags)
818{
819 u8 buf[2];
820 int rc, timer_max, timer_init;
821
822 if (charging) {
823 timer_max = FG_SRAM_ESR_TIMER_CHG_MAX;
824 timer_init = FG_SRAM_ESR_TIMER_CHG_INIT;
825 } else {
826 timer_max = FG_SRAM_ESR_TIMER_DISCHG_MAX;
827 timer_init = FG_SRAM_ESR_TIMER_DISCHG_INIT;
828 }
829
830 fg_encode(chip->sp, timer_max, cycles, buf);
831 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700832 chip->sp[timer_max].addr_word,
833 chip->sp[timer_max].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700834 chip->sp[timer_max].len, flags);
835 if (rc < 0) {
836 pr_err("Error in writing esr_timer_dischg_max, rc=%d\n",
837 rc);
838 return rc;
839 }
840
841 fg_encode(chip->sp, timer_init, cycles, buf);
842 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -0700843 chip->sp[timer_init].addr_word,
844 chip->sp[timer_init].addr_byte, buf,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -0700845 chip->sp[timer_init].len, flags);
846 if (rc < 0) {
847 pr_err("Error in writing esr_timer_dischg_init, rc=%d\n",
848 rc);
849 return rc;
850 }
851
852 return 0;
853}
854
Nicholas Troaste29dec92016-08-24 09:35:11 -0700855/* Other functions HERE */
856
857static int fg_awake_cb(struct votable *votable, void *data, int awake,
858 const char *client)
859{
860 struct fg_chip *chip = data;
861
862 if (awake)
863 pm_stay_awake(chip->dev);
864 else
865 pm_relax(chip->dev);
866
867 pr_debug("client: %s awake: %d\n", client, awake);
868 return 0;
869}
870
871static bool is_charger_available(struct fg_chip *chip)
872{
873 if (!chip->batt_psy)
874 chip->batt_psy = power_supply_get_by_name("battery");
875
876 if (!chip->batt_psy)
877 return false;
878
879 return true;
880}
881
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700882static int fg_save_learned_cap_to_sram(struct fg_chip *chip)
883{
884 int16_t cc_mah;
885 int rc;
886
887 if (chip->battery_missing || !chip->cl.learned_cc_uah)
888 return -EPERM;
889
890 cc_mah = div64_s64(chip->cl.learned_cc_uah, 1000);
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700891 /* Write to a backup register to use across reboot */
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700892 rc = fg_sram_write(chip, chip->sp[FG_SRAM_ACT_BATT_CAP].addr_word,
893 chip->sp[FG_SRAM_ACT_BATT_CAP].addr_byte, (u8 *)&cc_mah,
894 chip->sp[FG_SRAM_ACT_BATT_CAP].len, FG_IMA_DEFAULT);
895 if (rc < 0) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700896 pr_err("Error in writing act_batt_cap_bkup, rc=%d\n", rc);
897 return rc;
898 }
899
900 /* Write to actual capacity register for coulomb counter operation */
901 rc = fg_sram_write(chip, ACT_BATT_CAP_WORD, ACT_BATT_CAP_OFFSET,
902 (u8 *)&cc_mah, chip->sp[FG_SRAM_ACT_BATT_CAP].len,
903 FG_IMA_DEFAULT);
904 if (rc < 0) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700905 pr_err("Error in writing act_batt_cap, rc=%d\n", rc);
906 return rc;
907 }
908
909 fg_dbg(chip, FG_CAP_LEARN, "learned capacity %llduah/%dmah stored\n",
910 chip->cl.learned_cc_uah, cc_mah);
911 return 0;
912}
913
914#define CAPACITY_DELTA_DECIPCT 500
915static int fg_load_learned_cap_from_sram(struct fg_chip *chip)
916{
917 int rc, act_cap_mah;
918 int64_t delta_cc_uah, pct_nom_cap_uah;
919
920 rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
921 if (rc < 0) {
922 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
923 return rc;
924 }
925
926 chip->cl.learned_cc_uah = act_cap_mah * 1000;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700927
928 if (chip->cl.learned_cc_uah != chip->cl.nom_cap_uah) {
Subbaraman Narayanamurthy51d3c902016-10-24 14:05:44 -0700929 if (chip->cl.learned_cc_uah == 0)
930 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
931
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700932 delta_cc_uah = abs(chip->cl.learned_cc_uah -
933 chip->cl.nom_cap_uah);
934 pct_nom_cap_uah = div64_s64((int64_t)chip->cl.nom_cap_uah *
935 CAPACITY_DELTA_DECIPCT, 1000);
936 /*
937 * If the learned capacity is out of range by 50% from the
938 * nominal capacity, then overwrite the learned capacity with
939 * the nominal capacity.
940 */
941 if (chip->cl.nom_cap_uah && delta_cc_uah > pct_nom_cap_uah) {
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700942 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah: %lld is higher than expected, capping it to nominal: %lld\n",
943 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700944 chip->cl.learned_cc_uah = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700945 }
Subbaraman Narayanamurthy2932f602016-10-17 14:01:34 -0700946
947 rc = fg_save_learned_cap_to_sram(chip);
948 if (rc < 0)
949 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -0700950 }
951
952 fg_dbg(chip, FG_CAP_LEARN, "learned_cc_uah:%lld nom_cap_uah: %lld\n",
953 chip->cl.learned_cc_uah, chip->cl.nom_cap_uah);
954 return 0;
955}
956
957static bool is_temp_valid_cap_learning(struct fg_chip *chip)
958{
959 int rc, batt_temp;
960
961 rc = fg_get_battery_temp(chip, &batt_temp);
962 if (rc < 0) {
963 pr_err("Error in getting batt_temp\n");
964 return false;
965 }
966
967 if (batt_temp > chip->dt.cl_max_temp ||
968 batt_temp < chip->dt.cl_min_temp) {
969 fg_dbg(chip, FG_CAP_LEARN, "batt temp %d out of range [%d %d]\n",
970 batt_temp, chip->dt.cl_min_temp, chip->dt.cl_max_temp);
971 return false;
972 }
973
974 return true;
975}
976
977static void fg_cap_learning_post_process(struct fg_chip *chip)
978{
979 int64_t max_inc_val, min_dec_val, old_cap;
980 int rc;
981
982 max_inc_val = chip->cl.learned_cc_uah
983 * (1000 + chip->dt.cl_max_cap_inc);
984 do_div(max_inc_val, 1000);
985
986 min_dec_val = chip->cl.learned_cc_uah
987 * (1000 - chip->dt.cl_max_cap_dec);
988 do_div(min_dec_val, 1000);
989
990 old_cap = chip->cl.learned_cc_uah;
991 if (chip->cl.final_cc_uah > max_inc_val)
992 chip->cl.learned_cc_uah = max_inc_val;
993 else if (chip->cl.final_cc_uah < min_dec_val)
994 chip->cl.learned_cc_uah = min_dec_val;
995 else
996 chip->cl.learned_cc_uah =
997 chip->cl.final_cc_uah;
998
999 if (chip->dt.cl_max_cap_limit) {
1000 max_inc_val = (int64_t)chip->cl.nom_cap_uah * (1000 +
1001 chip->dt.cl_max_cap_limit);
1002 do_div(max_inc_val, 1000);
1003 if (chip->cl.final_cc_uah > max_inc_val) {
1004 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes above max limit %lld\n",
1005 chip->cl.final_cc_uah, max_inc_val);
1006 chip->cl.learned_cc_uah = max_inc_val;
1007 }
1008 }
1009
1010 if (chip->dt.cl_min_cap_limit) {
1011 min_dec_val = (int64_t)chip->cl.nom_cap_uah * (1000 -
1012 chip->dt.cl_min_cap_limit);
1013 do_div(min_dec_val, 1000);
1014 if (chip->cl.final_cc_uah < min_dec_val) {
1015 fg_dbg(chip, FG_CAP_LEARN, "learning capacity %lld goes below min limit %lld\n",
1016 chip->cl.final_cc_uah, min_dec_val);
1017 chip->cl.learned_cc_uah = min_dec_val;
1018 }
1019 }
1020
1021 rc = fg_save_learned_cap_to_sram(chip);
1022 if (rc < 0)
1023 pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
1024
1025 fg_dbg(chip, FG_CAP_LEARN, "final cc_uah = %lld, learned capacity %lld -> %lld uah\n",
1026 chip->cl.final_cc_uah, old_cap, chip->cl.learned_cc_uah);
1027}
1028
1029static int fg_cap_learning_process_full_data(struct fg_chip *chip)
1030{
1031 int rc, cc_soc_sw, cc_soc_delta_pct;
1032 int64_t delta_cc_uah;
1033
1034 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1035 if (rc < 0) {
1036 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1037 return rc;
1038 }
1039
1040 cc_soc_delta_pct = DIV_ROUND_CLOSEST(
1041 abs(cc_soc_sw - chip->cl.init_cc_soc_sw) * 100,
1042 CC_SOC_30BIT);
1043 delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
1044 100);
1045 chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
1046 fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%d total_cc_uah=%lld\n",
1047 cc_soc_sw, cc_soc_delta_pct, chip->cl.final_cc_uah);
1048 return 0;
1049}
1050
1051static int fg_cap_learning_begin(struct fg_chip *chip, int batt_soc)
1052{
1053 int rc, cc_soc_sw;
1054
1055 if (DIV_ROUND_CLOSEST(batt_soc * 100, FULL_SOC_RAW) >
1056 chip->dt.cl_start_soc) {
1057 fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n",
1058 batt_soc);
1059 return -EINVAL;
1060 }
1061
1062 chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc,
1063 FULL_SOC_RAW);
1064 rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
1065 if (rc < 0) {
1066 pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
1067 return rc;
1068 }
1069
1070 chip->cl.init_cc_soc_sw = cc_soc_sw;
1071 chip->cl.active = true;
1072 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
1073 batt_soc, chip->cl.init_cc_soc_sw);
1074 return 0;
1075}
1076
1077static int fg_cap_learning_done(struct fg_chip *chip)
1078{
1079 int rc, cc_soc_sw;
1080
1081 rc = fg_cap_learning_process_full_data(chip);
1082 if (rc < 0) {
1083 pr_err("Error in processing cap learning full data, rc=%d\n",
1084 rc);
1085 goto out;
1086 }
1087
1088 /* Write a FULL value to cc_soc_sw */
1089 cc_soc_sw = CC_SOC_30BIT;
1090 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
1091 chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001092 chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001093 if (rc < 0) {
1094 pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
1095 goto out;
1096 }
1097
1098 fg_cap_learning_post_process(chip);
1099out:
1100 return rc;
1101}
1102
1103#define FULL_SOC_RAW 255
1104static void fg_cap_learning_update(struct fg_chip *chip)
1105{
1106 int rc, batt_soc;
1107
1108 mutex_lock(&chip->cl.lock);
1109
1110 if (!is_temp_valid_cap_learning(chip) || !chip->cl.learned_cc_uah ||
1111 chip->battery_missing) {
1112 fg_dbg(chip, FG_CAP_LEARN, "Aborting cap_learning %lld\n",
1113 chip->cl.learned_cc_uah);
1114 chip->cl.active = false;
1115 chip->cl.init_cc_uah = 0;
1116 goto out;
1117 }
1118
1119 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1120 if (rc < 0) {
1121 pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
1122 goto out;
1123 }
1124
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001125 /* We need only the most significant byte here */
1126 batt_soc = (u32)batt_soc >> 24;
1127
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001128 fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n",
1129 chip->status, chip->cl.active, batt_soc);
1130
1131 /* Initialize the starting point of learning capacity */
1132 if (!chip->cl.active) {
1133 if (chip->status == POWER_SUPPLY_STATUS_CHARGING) {
1134 rc = fg_cap_learning_begin(chip, batt_soc);
1135 chip->cl.active = (rc == 0);
1136 }
1137
1138 } else {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001139 if (chip->charge_done) {
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001140 rc = fg_cap_learning_done(chip);
1141 if (rc < 0)
1142 pr_err("Error in completing capacity learning, rc=%d\n",
1143 rc);
1144
1145 chip->cl.active = false;
1146 chip->cl.init_cc_uah = 0;
1147 }
1148
1149 if (chip->status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
1150 fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
1151 batt_soc);
1152 chip->cl.active = false;
1153 chip->cl.init_cc_uah = 0;
1154 }
1155 }
1156
1157out:
1158 mutex_unlock(&chip->cl.lock);
1159}
1160
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001161#define KI_COEFF_MED_DISCHG_DEFAULT 1500
1162#define KI_COEFF_HI_DISCHG_DEFAULT 2200
1163static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
1164{
1165 int rc, i, msoc;
1166 int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
1167 int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
1168 u8 val;
1169
1170 if (!chip->ki_coeff_dischg_en)
1171 return 0;
1172
1173 rc = fg_get_prop_capacity(chip, &msoc);
1174 if (rc < 0) {
1175 pr_err("Error in getting capacity, rc=%d\n", rc);
1176 return rc;
1177 }
1178
1179 if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
1180 for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
1181 if (msoc < chip->dt.ki_coeff_soc[i]) {
1182 ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
1183 ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
1184 }
1185 }
1186 }
1187
1188 fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
1189 rc = fg_sram_write(chip,
1190 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
1191 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
1192 chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
1193 FG_IMA_DEFAULT);
1194 if (rc < 0) {
1195 pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
1196 return rc;
1197 }
1198
1199 fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
1200 rc = fg_sram_write(chip,
1201 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
1202 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
1203 chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
1204 FG_IMA_DEFAULT);
1205 if (rc < 0) {
1206 pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
1207 return rc;
1208 }
1209
1210 fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
1211 ki_coeff_med, ki_coeff_hi);
1212 return 0;
1213}
1214
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001215static int fg_charge_full_update(struct fg_chip *chip)
1216{
1217 union power_supply_propval prop = {0, };
1218 int rc, msoc, bsoc, recharge_soc;
1219 u8 full_soc[2] = {0xFF, 0xFF};
1220
1221 if (!chip->dt.hold_soc_while_full)
1222 return 0;
1223
1224 if (!is_charger_available(chip))
1225 return 0;
1226
1227 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
1228 &prop);
1229 if (rc < 0) {
1230 pr_err("Error in getting battery health, rc=%d\n", rc);
1231 return rc;
1232 }
1233
1234 chip->health = prop.intval;
1235 recharge_soc = chip->dt.recharge_soc_thr;
1236 recharge_soc = DIV_ROUND_CLOSEST(recharge_soc * FULL_SOC_RAW,
1237 FULL_CAPACITY);
1238 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
1239 if (rc < 0) {
1240 pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
1241 return rc;
1242 }
1243
1244 /* We need 2 most significant bytes here */
1245 bsoc = (u32)bsoc >> 16;
1246 rc = fg_get_prop_capacity(chip, &msoc);
1247 if (rc < 0) {
1248 pr_err("Error in getting capacity, rc=%d\n", rc);
1249 return rc;
1250 }
1251
1252 fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc,
1253 chip->health, chip->status);
1254 if (chip->charge_done) {
1255 if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD)
1256 chip->charge_full = true;
1257 else
1258 fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
1259 msoc);
1260 } else if ((bsoc >> 8) <= recharge_soc) {
1261 fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d\n",
1262 bsoc >> 8, recharge_soc);
1263 chip->charge_full = false;
1264 }
1265
1266 if (!chip->charge_full)
1267 return 0;
1268
1269 /*
1270 * During JEITA conditions, charge_full can happen early. FULL_SOC
1271 * and MONOTONIC_SOC needs to be updated to reflect the same. Write
1272 * battery SOC to FULL_SOC and write a full value to MONOTONIC_SOC.
1273 */
1274 rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET, (u8 *)&bsoc, 2,
1275 FG_IMA_ATOMIC);
1276 if (rc < 0) {
1277 pr_err("failed to write full_soc rc=%d\n", rc);
1278 return rc;
1279 }
1280
1281 rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
1282 full_soc, 2, FG_IMA_ATOMIC);
1283 if (rc < 0) {
1284 pr_err("failed to write monotonic_soc rc=%d\n", rc);
1285 return rc;
1286 }
1287
1288 fg_dbg(chip, FG_STATUS, "Set charge_full to true @ soc %d\n", msoc);
1289 return 0;
1290}
1291
1292static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
1293{
1294 u8 buf[4];
1295 int rc;
1296
1297 fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf);
1298 rc = fg_sram_write(chip,
1299 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
1300 chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, buf,
1301 chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
1302 if (rc < 0) {
1303 pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
1304 return rc;
1305 }
1306
1307 return 0;
1308}
1309
1310static int fg_adjust_recharge_soc(struct fg_chip *chip)
1311{
1312 int rc, msoc, recharge_soc, new_recharge_soc = 0;
1313
1314 recharge_soc = chip->dt.recharge_soc_thr;
1315 /*
1316 * If the input is present and charging had been terminated, adjust
1317 * the recharge SOC threshold based on the monotonic SOC at which
1318 * the charge termination had happened.
1319 */
1320 if (is_input_present(chip) && !chip->recharge_soc_adjusted
1321 && chip->charge_done) {
1322 /* Get raw monotonic SOC for calculation */
1323 rc = fg_get_msoc_raw(chip, &msoc);
1324 if (rc < 0) {
1325 pr_err("Error in getting msoc, rc=%d\n", rc);
1326 return rc;
1327 }
1328
1329 msoc = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
1330 /* Adjust the recharge_soc threshold */
1331 new_recharge_soc = msoc - (FULL_CAPACITY - recharge_soc);
1332 } else if (chip->recharge_soc_adjusted && (!is_input_present(chip)
1333 || chip->health == POWER_SUPPLY_HEALTH_GOOD)) {
1334 /* Restore the default value */
1335 new_recharge_soc = recharge_soc;
1336 }
1337
1338 if (new_recharge_soc > 0 && new_recharge_soc < FULL_CAPACITY) {
1339 rc = fg_set_recharge_soc(chip, new_recharge_soc);
1340 if (rc) {
1341 pr_err("Couldn't set resume SOC for FG, rc=%d\n", rc);
1342 return rc;
1343 }
1344
1345 chip->recharge_soc_adjusted = (new_recharge_soc !=
1346 recharge_soc);
1347 fg_dbg(chip, FG_STATUS, "resume soc set to %d\n",
1348 new_recharge_soc);
1349 }
1350
1351 return 0;
1352}
1353
Nicholas Troaste29dec92016-08-24 09:35:11 -07001354static void status_change_work(struct work_struct *work)
1355{
1356 struct fg_chip *chip = container_of(work,
1357 struct fg_chip, status_change_work);
1358 union power_supply_propval prop = {0, };
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001359 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001360
1361 if (!is_charger_available(chip)) {
1362 fg_dbg(chip, FG_STATUS, "Charger not available?!\n");
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001363 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001364 }
1365
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001366 rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS,
Nicholas Troaste29dec92016-08-24 09:35:11 -07001367 &prop);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001368 if (rc < 0) {
1369 pr_err("Error in getting charging status, rc=%d\n", rc);
1370 goto out;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001371 }
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001372
1373 chip->status = prop.intval;
1374 rc = power_supply_get_property(chip->batt_psy,
1375 POWER_SUPPLY_PROP_CHARGE_DONE, &prop);
1376 if (rc < 0) {
1377 pr_err("Error in getting charge_done, rc=%d\n", rc);
1378 goto out;
1379 }
1380
1381 chip->charge_done = prop.intval;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001382 fg_dbg(chip, FG_POWER_SUPPLY, "curr_status:%d charge_done: %d\n",
1383 chip->status, chip->charge_done);
1384
1385 if (chip->cyc_ctr.en)
1386 schedule_work(&chip->cycle_count_work);
1387
1388 fg_cap_learning_update(chip);
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001389
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001390 rc = fg_charge_full_update(chip);
1391 if (rc < 0)
1392 pr_err("Error in charge_full_update, rc=%d\n", rc);
1393
1394 rc = fg_adjust_recharge_soc(chip);
1395 if (rc < 0)
1396 pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001397
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07001398 rc = fg_adjust_ki_coeff_dischg(chip);
1399 if (rc < 0)
1400 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001401out:
1402 pm_relax(chip->dev);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001403}
1404
1405static void restore_cycle_counter(struct fg_chip *chip)
1406{
1407 int rc = 0, i;
1408 u8 data[2];
1409
1410 mutex_lock(&chip->cyc_ctr.lock);
1411 for (i = 0; i < BUCKET_COUNT; i++) {
1412 rc = fg_sram_read(chip, CYCLE_COUNT_WORD + (i / 2),
1413 CYCLE_COUNT_OFFSET + (i % 2) * 2, data, 2,
1414 FG_IMA_DEFAULT);
1415 if (rc < 0)
1416 pr_err("failed to read bucket %d rc=%d\n", i, rc);
1417 else
1418 chip->cyc_ctr.count[i] = data[0] | data[1] << 8;
1419 }
1420 mutex_unlock(&chip->cyc_ctr.lock);
1421}
1422
1423static void clear_cycle_counter(struct fg_chip *chip)
1424{
1425 int rc = 0, i;
1426
1427 if (!chip->cyc_ctr.en)
1428 return;
1429
1430 mutex_lock(&chip->cyc_ctr.lock);
1431 memset(chip->cyc_ctr.count, 0, sizeof(chip->cyc_ctr.count));
1432 for (i = 0; i < BUCKET_COUNT; i++) {
1433 chip->cyc_ctr.started[i] = false;
1434 chip->cyc_ctr.last_soc[i] = 0;
1435 }
1436 rc = fg_sram_write(chip, CYCLE_COUNT_WORD, CYCLE_COUNT_OFFSET,
1437 (u8 *)&chip->cyc_ctr.count,
1438 sizeof(chip->cyc_ctr.count) / sizeof(u8 *),
1439 FG_IMA_DEFAULT);
1440 if (rc < 0)
1441 pr_err("failed to clear cycle counter rc=%d\n", rc);
1442
1443 mutex_unlock(&chip->cyc_ctr.lock);
1444}
1445
1446static int fg_inc_store_cycle_ctr(struct fg_chip *chip, int bucket)
1447{
1448 int rc = 0;
1449 u16 cyc_count;
1450 u8 data[2];
1451
1452 if (bucket < 0 || (bucket > BUCKET_COUNT - 1))
1453 return 0;
1454
1455 cyc_count = chip->cyc_ctr.count[bucket];
1456 cyc_count++;
1457 data[0] = cyc_count & 0xFF;
1458 data[1] = cyc_count >> 8;
1459
1460 rc = fg_sram_write(chip, CYCLE_COUNT_WORD + (bucket / 2),
1461 CYCLE_COUNT_OFFSET + (bucket % 2) * 2, data, 2,
1462 FG_IMA_DEFAULT);
1463 if (rc < 0)
1464 pr_err("failed to write BATT_CYCLE[%d] rc=%d\n",
1465 bucket, rc);
1466 else
1467 chip->cyc_ctr.count[bucket] = cyc_count;
1468 return rc;
1469}
1470
1471static void cycle_count_work(struct work_struct *work)
1472{
1473 int rc = 0, bucket, i, batt_soc;
1474 struct fg_chip *chip = container_of(work,
1475 struct fg_chip,
1476 cycle_count_work);
1477
1478 mutex_lock(&chip->cyc_ctr.lock);
1479 rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
1480 if (rc < 0) {
1481 pr_err("Failed to read battery soc rc: %d\n", rc);
1482 goto out;
1483 }
1484
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07001485 /* We need only the most significant byte here */
1486 batt_soc = (u32)batt_soc >> 24;
1487
Nicholas Troaste29dec92016-08-24 09:35:11 -07001488 if (chip->status == POWER_SUPPLY_STATUS_CHARGING) {
1489 /* Find out which bucket the SOC falls in */
1490 bucket = batt_soc / BUCKET_SOC_PCT;
1491 pr_debug("batt_soc: %d bucket: %d\n", batt_soc, bucket);
1492
1493 /*
1494 * If we've started counting for the previous bucket,
1495 * then store the counter for that bucket if the
1496 * counter for current bucket is getting started.
1497 */
1498 if (bucket > 0 && chip->cyc_ctr.started[bucket - 1] &&
1499 !chip->cyc_ctr.started[bucket]) {
1500 rc = fg_inc_store_cycle_ctr(chip, bucket - 1);
1501 if (rc < 0) {
1502 pr_err("Error in storing cycle_ctr rc: %d\n",
1503 rc);
1504 goto out;
1505 } else {
1506 chip->cyc_ctr.started[bucket - 1] = false;
1507 chip->cyc_ctr.last_soc[bucket - 1] = 0;
1508 }
1509 }
1510 if (!chip->cyc_ctr.started[bucket]) {
1511 chip->cyc_ctr.started[bucket] = true;
1512 chip->cyc_ctr.last_soc[bucket] = batt_soc;
1513 }
1514 } else {
1515 for (i = 0; i < BUCKET_COUNT; i++) {
1516 if (chip->cyc_ctr.started[i] &&
1517 batt_soc > chip->cyc_ctr.last_soc[i]) {
1518 rc = fg_inc_store_cycle_ctr(chip, i);
1519 if (rc < 0)
1520 pr_err("Error in storing cycle_ctr rc: %d\n",
1521 rc);
1522 chip->cyc_ctr.last_soc[i] = 0;
1523 }
1524 chip->cyc_ctr.started[i] = false;
1525 }
1526 }
1527out:
1528 mutex_unlock(&chip->cyc_ctr.lock);
1529}
1530
1531static int fg_get_cycle_count(struct fg_chip *chip)
1532{
1533 int count;
1534
1535 if (!chip->cyc_ctr.en)
1536 return 0;
1537
1538 if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT))
1539 return -EINVAL;
1540
1541 mutex_lock(&chip->cyc_ctr.lock);
1542 count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1];
1543 mutex_unlock(&chip->cyc_ctr.lock);
1544 return count;
1545}
1546
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001547static void dump_sram(u8 *buf, int len)
Nicholas Troaste29dec92016-08-24 09:35:11 -07001548{
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001549 int i;
1550 char str[16];
1551
1552 for (i = 0; i < len; i += 4) {
1553 str[0] = '\0';
1554 fill_string(str, sizeof(str), buf + i, 4);
1555 pr_info("%03d %s\n", PROFILE_LOAD_WORD + (i / 4), str);
1556 }
1557}
1558
1559static bool is_profile_load_required(struct fg_chip *chip)
1560{
Nicholas Troaste29dec92016-08-24 09:35:11 -07001561 u8 buf[PROFILE_COMP_LEN], val;
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001562 bool profiles_same = false;
1563 int rc;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001564
Nicholas Troaste29dec92016-08-24 09:35:11 -07001565 rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
1566 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
1567 if (rc < 0) {
1568 pr_err("failed to read profile integrity rc=%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001569 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001570 }
1571
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001572 /* Check if integrity bit is set */
Nicholas Troaste29dec92016-08-24 09:35:11 -07001573 if (val == 0x01) {
1574 fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
1575 rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
1576 buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
1577 if (rc < 0) {
1578 pr_err("Error in reading battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001579 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001580 }
1581 profiles_same = memcmp(chip->batt_profile, buf,
1582 PROFILE_COMP_LEN) == 0;
1583 if (profiles_same) {
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001584 fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
1585 return false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001586 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001587
1588 if (!chip->dt.force_load_profile) {
1589 pr_warn("Profiles doesn't match, skipping loading it since force_load_profile is disabled\n");
1590 if (fg_sram_dump) {
1591 pr_info("FG: loaded profile:\n");
1592 dump_sram(buf, PROFILE_COMP_LEN);
1593 pr_info("FG: available profile:\n");
1594 dump_sram(chip->batt_profile, PROFILE_LEN);
1595 }
1596 return false;
1597 }
1598
1599 fg_dbg(chip, FG_STATUS, "Profiles are different, loading the correct one\n");
1600 } else {
1601 fg_dbg(chip, FG_STATUS, "Profile integrity bit is not set\n");
1602 if (fg_sram_dump) {
1603 pr_info("FG: profile to be loaded:\n");
1604 dump_sram(chip->batt_profile, PROFILE_LEN);
1605 }
Nicholas Troaste29dec92016-08-24 09:35:11 -07001606 }
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001607 return true;
1608}
1609
1610#define SOC_READY_WAIT_MS 2000
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001611static int __fg_restart(struct fg_chip *chip)
1612{
1613 int rc, msoc;
1614 bool tried_again = false;
1615
1616 rc = fg_get_prop_capacity(chip, &msoc);
1617 if (rc < 0) {
1618 pr_err("Error in getting capacity, rc=%d\n", rc);
1619 return rc;
1620 }
1621
1622 chip->last_soc = msoc;
1623 chip->fg_restarting = true;
1624 reinit_completion(&chip->soc_ready);
1625 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT,
1626 RESTART_GO_BIT);
1627 if (rc < 0) {
1628 pr_err("Error in writing to %04x, rc=%d\n",
1629 BATT_SOC_RESTART(chip), rc);
1630 goto out;
1631 }
1632
1633wait:
1634 rc = wait_for_completion_interruptible_timeout(&chip->soc_ready,
1635 msecs_to_jiffies(SOC_READY_WAIT_MS));
1636
1637 /* If we were interrupted wait again one more time. */
1638 if (rc == -ERESTARTSYS && !tried_again) {
1639 tried_again = true;
1640 goto wait;
1641 } else if (rc <= 0) {
1642 pr_err("wait for soc_ready timed out rc=%d\n", rc);
1643 goto out;
1644 }
1645
1646 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
1647 if (rc < 0) {
1648 pr_err("Error in writing to %04x, rc=%d\n",
1649 BATT_SOC_RESTART(chip), rc);
1650 goto out;
1651 }
1652out:
1653 chip->fg_restarting = false;
1654 return rc;
1655}
1656
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001657static void fg_notify_charger(struct fg_chip *chip)
1658{
1659 union power_supply_propval prop = {0, };
1660 int rc;
1661
1662 if (!is_charger_available(chip)) {
1663 pr_warn("Charger not available yet?\n");
1664 return;
1665 }
1666
1667 prop.intval = chip->bp.float_volt_uv;
1668 rc = power_supply_set_property(chip->batt_psy,
1669 POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
1670 if (rc < 0) {
1671 pr_err("Error in setting voltage_max property on batt_psy, rc=%d\n",
1672 rc);
1673 return;
1674 }
1675
Subbaraman Narayanamurthya5d12622016-10-20 12:04:02 -07001676 prop.intval = chip->bp.fastchg_curr_ma * 1000;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001677 rc = power_supply_set_property(chip->batt_psy,
1678 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &prop);
1679 if (rc < 0) {
1680 pr_err("Error in setting constant_charge_current_max property on batt_psy, rc=%d\n",
1681 rc);
1682 return;
1683 }
1684
1685 fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
1686}
1687
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001688static void profile_load_work(struct work_struct *work)
1689{
1690 struct fg_chip *chip = container_of(work,
1691 struct fg_chip,
1692 profile_load_work.work);
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07001693 u8 buf[2], val;
1694 int rc;
1695
1696 vote(chip->awake_votable, PROFILE_LOAD, true, 0);
1697 if (!is_profile_load_required(chip))
1698 goto done;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001699
1700 clear_cycle_counter(chip);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001701 mutex_lock(&chip->cl.lock);
1702 chip->cl.learned_cc_uah = 0;
1703 chip->cl.active = false;
1704 mutex_unlock(&chip->cl.lock);
1705
Nicholas Troaste29dec92016-08-24 09:35:11 -07001706 fg_dbg(chip, FG_STATUS, "profile loading started\n");
1707 rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
1708 if (rc < 0) {
1709 pr_err("Error in writing to %04x, rc=%d\n",
1710 BATT_SOC_RESTART(chip), rc);
1711 goto out;
1712 }
1713
1714 /* load battery profile */
1715 rc = fg_sram_write(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
1716 chip->batt_profile, PROFILE_LEN, FG_IMA_ATOMIC);
1717 if (rc < 0) {
1718 pr_err("Error in writing battery profile, rc:%d\n", rc);
1719 goto out;
1720 }
1721
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001722 rc = __fg_restart(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001723 if (rc < 0) {
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001724 pr_err("Error in restarting FG, rc=%d\n", rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001725 goto out;
1726 }
1727
1728 fg_dbg(chip, FG_STATUS, "SOC is ready\n");
1729
1730 /* Set the profile integrity bit */
1731 val = 0x1;
1732 rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
1733 PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
1734 if (rc < 0) {
1735 pr_err("failed to write profile integrity rc=%d\n", rc);
1736 goto out;
1737 }
1738
Nicholas Troaste29dec92016-08-24 09:35:11 -07001739done:
1740 rc = fg_sram_read(chip, NOM_CAP_WORD, NOM_CAP_OFFSET, buf, 2,
1741 FG_IMA_DEFAULT);
1742 if (rc < 0) {
1743 pr_err("Error in reading %04x[%d] rc=%d\n", NOM_CAP_WORD,
1744 NOM_CAP_OFFSET, rc);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001745 } else {
1746 chip->cl.nom_cap_uah = (int)(buf[0] | buf[1] << 8) * 1000;
1747 rc = fg_load_learned_cap_from_sram(chip);
1748 if (rc < 0)
1749 pr_err("Error in loading capacity learning data, rc:%d\n",
1750 rc);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001751 }
1752
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001753 fg_notify_charger(chip);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001754 chip->profile_loaded = true;
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001755 fg_dbg(chip, FG_STATUS, "profile loaded successfully");
Nicholas Troaste29dec92016-08-24 09:35:11 -07001756out:
1757 vote(chip->awake_votable, PROFILE_LOAD, false, 0);
Nicholas Troaste29dec92016-08-24 09:35:11 -07001758}
1759
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001760static int fg_restart_sysfs(const char *val, const struct kernel_param *kp)
1761{
1762 int rc;
1763 struct power_supply *bms_psy;
1764 struct fg_chip *chip;
1765
1766 rc = param_set_int(val, kp);
1767 if (rc) {
1768 pr_err("Unable to set fg_restart: %d\n", rc);
1769 return rc;
1770 }
1771
1772 if (fg_restart != 1) {
1773 pr_err("Bad value %d\n", fg_restart);
1774 return -EINVAL;
1775 }
1776
1777 bms_psy = power_supply_get_by_name("bms");
1778 if (!bms_psy) {
1779 pr_err("bms psy not found\n");
1780 return 0;
1781 }
1782
1783 chip = power_supply_get_drvdata(bms_psy);
1784 rc = __fg_restart(chip);
1785 if (rc < 0) {
1786 pr_err("Error in restarting FG, rc=%d\n", rc);
1787 return rc;
1788 }
1789
1790 pr_info("FG restart done\n");
1791 return rc;
1792}
1793
1794static struct kernel_param_ops fg_restart_ops = {
1795 .set = fg_restart_sysfs,
1796 .get = param_get_int,
1797};
1798
1799module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
1800
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001801/* PSY CALLBACKS STAY HERE */
1802
1803static int fg_psy_get_property(struct power_supply *psy,
1804 enum power_supply_property psp,
1805 union power_supply_propval *pval)
1806{
1807 struct fg_chip *chip = power_supply_get_drvdata(psy);
1808 int rc = 0;
1809
1810 switch (psp) {
1811 case POWER_SUPPLY_PROP_CAPACITY:
Subbaraman Narayanamurthy4f8e7d22016-09-22 19:36:39 -07001812 if (chip->fg_restarting)
1813 pval->intval = chip->last_soc;
1814 else
1815 rc = fg_get_prop_capacity(chip, &pval->intval);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001816 break;
1817 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1818 rc = fg_get_battery_voltage(chip, &pval->intval);
1819 break;
1820 case POWER_SUPPLY_PROP_CURRENT_NOW:
1821 rc = fg_get_battery_current(chip, &pval->intval);
1822 break;
1823 case POWER_SUPPLY_PROP_TEMP:
1824 rc = fg_get_battery_temp(chip, &pval->intval);
1825 break;
1826 case POWER_SUPPLY_PROP_RESISTANCE:
1827 rc = fg_get_battery_resistance(chip, &pval->intval);
1828 break;
1829 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
1830 rc = fg_get_sram_prop(chip, FG_SRAM_OCV, &pval->intval);
1831 break;
1832 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001833 pval->intval = chip->cl.nom_cap_uah;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001834 break;
1835 case POWER_SUPPLY_PROP_RESISTANCE_ID:
1836 rc = fg_get_batt_id(chip, &pval->intval);
1837 break;
1838 case POWER_SUPPLY_PROP_BATTERY_TYPE:
1839 pval->strval = fg_get_battery_type(chip);
1840 break;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07001841 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1842 pval->intval = chip->bp.float_volt_uv;
Subbaraman Narayanamurthya6b1fd82016-10-17 20:08:59 -07001843 break;
Nicholas Troaste29dec92016-08-24 09:35:11 -07001844 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1845 pval->intval = fg_get_cycle_count(chip);
1846 break;
1847 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
1848 pval->intval = chip->cyc_ctr.id;
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07001849 break;
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001850 case POWER_SUPPLY_PROP_CHARGE_NOW_RAW:
1851 rc = fg_get_cc_soc(chip, &pval->intval);
1852 break;
1853 case POWER_SUPPLY_PROP_CHARGE_NOW:
1854 pval->intval = chip->cl.init_cc_uah;
1855 break;
1856 case POWER_SUPPLY_PROP_CHARGE_FULL:
1857 pval->intval = chip->cl.learned_cc_uah;
1858 break;
1859 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
1860 rc = fg_get_cc_soc_sw(chip, &pval->intval);
1861 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001862 default:
1863 break;
1864 }
1865
1866 return rc;
1867}
1868
1869static int fg_psy_set_property(struct power_supply *psy,
1870 enum power_supply_property psp,
1871 const union power_supply_propval *pval)
1872{
Nicholas Troaste29dec92016-08-24 09:35:11 -07001873 struct fg_chip *chip = power_supply_get_drvdata(psy);
1874
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001875 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001876 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
1877 if ((pval->intval > 0) && (pval->intval <= BUCKET_COUNT)) {
1878 chip->cyc_ctr.id = pval->intval;
1879 } else {
1880 pr_err("rejecting invalid cycle_count_id = %d\n",
1881 pval->intval);
1882 return -EINVAL;
1883 }
1884 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001885 default:
1886 break;
1887 }
1888
1889 return 0;
1890}
1891
1892static int fg_property_is_writeable(struct power_supply *psy,
1893 enum power_supply_property psp)
1894{
1895 switch (psp) {
Nicholas Troaste29dec92016-08-24 09:35:11 -07001896 case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
1897 return 1;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001898 default:
1899 break;
1900 }
1901
1902 return 0;
1903}
1904
1905static void fg_external_power_changed(struct power_supply *psy)
1906{
1907 pr_debug("power supply changed\n");
1908}
1909
1910static int fg_notifier_cb(struct notifier_block *nb,
1911 unsigned long event, void *data)
1912{
1913 struct power_supply *psy = data;
1914 struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
1915
1916 if (event != PSY_EVENT_PROP_CHANGED)
1917 return NOTIFY_OK;
1918
1919 if ((strcmp(psy->desc->name, "battery") == 0)
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001920 || (strcmp(psy->desc->name, "usb") == 0)) {
1921 /*
1922 * We cannot vote for awake votable here as that takes
1923 * a mutex lock and this is executed in an atomic context.
1924 */
1925 pm_stay_awake(chip->dev);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001926 schedule_work(&chip->status_change_work);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001927 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001928
1929 return NOTIFY_OK;
1930}
1931
1932static enum power_supply_property fg_psy_props[] = {
1933 POWER_SUPPLY_PROP_CAPACITY,
1934 POWER_SUPPLY_PROP_TEMP,
1935 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1936 POWER_SUPPLY_PROP_VOLTAGE_OCV,
1937 POWER_SUPPLY_PROP_CURRENT_NOW,
1938 POWER_SUPPLY_PROP_RESISTANCE_ID,
1939 POWER_SUPPLY_PROP_RESISTANCE,
1940 POWER_SUPPLY_PROP_BATTERY_TYPE,
1941 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Abhijeet Dharmapurikar3d8b2262016-08-25 13:50:42 -07001942 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Nicholas Troaste29dec92016-08-24 09:35:11 -07001943 POWER_SUPPLY_PROP_CYCLE_COUNT,
1944 POWER_SUPPLY_PROP_CYCLE_COUNT_ID,
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07001945 POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
1946 POWER_SUPPLY_PROP_CHARGE_NOW,
1947 POWER_SUPPLY_PROP_CHARGE_FULL,
1948 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001949};
1950
1951static const struct power_supply_desc fg_psy_desc = {
1952 .name = "bms",
1953 .type = POWER_SUPPLY_TYPE_BMS,
1954 .properties = fg_psy_props,
1955 .num_properties = ARRAY_SIZE(fg_psy_props),
1956 .get_property = fg_psy_get_property,
1957 .set_property = fg_psy_set_property,
1958 .external_power_changed = fg_external_power_changed,
1959 .property_is_writeable = fg_property_is_writeable,
1960};
1961
1962/* INIT FUNCTIONS STAY HERE */
1963
1964static int fg_hw_init(struct fg_chip *chip)
1965{
1966 int rc;
1967 u8 buf[4], val;
1968
1969 fg_encode(chip->sp, FG_SRAM_CUTOFF_VOLT, chip->dt.cutoff_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07001970 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CUTOFF_VOLT].addr_word,
1971 chip->sp[FG_SRAM_CUTOFF_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001972 chip->sp[FG_SRAM_CUTOFF_VOLT].len, FG_IMA_DEFAULT);
1973 if (rc < 0) {
1974 pr_err("Error in writing cutoff_volt, rc=%d\n", rc);
1975 return rc;
1976 }
1977
1978 fg_encode(chip->sp, FG_SRAM_EMPTY_VOLT, chip->dt.empty_volt_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07001979 rc = fg_sram_write(chip, chip->sp[FG_SRAM_EMPTY_VOLT].addr_word,
1980 chip->sp[FG_SRAM_EMPTY_VOLT].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07001981 chip->sp[FG_SRAM_EMPTY_VOLT].len, FG_IMA_DEFAULT);
1982 if (rc < 0) {
1983 pr_err("Error in writing empty_volt, rc=%d\n", rc);
1984 return rc;
1985 }
1986
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07001987 /* This SRAM register is only present in v2.0 */
1988 if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4 &&
1989 chip->bp.float_volt_uv > 0) {
1990 fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT,
1991 chip->bp.float_volt_uv / 1000, buf);
1992 rc = fg_sram_write(chip, chip->sp[FG_SRAM_FLOAT_VOLT].addr_word,
1993 chip->sp[FG_SRAM_FLOAT_VOLT].addr_byte, buf,
1994 chip->sp[FG_SRAM_FLOAT_VOLT].len, FG_IMA_DEFAULT);
1995 if (rc < 0) {
1996 pr_err("Error in writing float_volt, rc=%d\n", rc);
1997 return rc;
1998 }
1999 }
2000
2001 if (chip->bp.vbatt_full_mv > 0) {
2002 fg_encode(chip->sp, FG_SRAM_VBATT_FULL, chip->bp.vbatt_full_mv,
2003 buf);
2004 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_FULL].addr_word,
2005 chip->sp[FG_SRAM_VBATT_FULL].addr_byte, buf,
2006 chip->sp[FG_SRAM_VBATT_FULL].len, FG_IMA_DEFAULT);
2007 if (rc < 0) {
2008 pr_err("Error in writing vbatt_full, rc=%d\n", rc);
2009 return rc;
2010 }
2011 }
2012
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002013 fg_encode(chip->sp, FG_SRAM_CHG_TERM_CURR, chip->dt.chg_term_curr_ma,
2014 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002015 rc = fg_sram_write(chip, chip->sp[FG_SRAM_CHG_TERM_CURR].addr_word,
2016 chip->sp[FG_SRAM_CHG_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002017 chip->sp[FG_SRAM_CHG_TERM_CURR].len, FG_IMA_DEFAULT);
2018 if (rc < 0) {
2019 pr_err("Error in writing chg_term_curr, rc=%d\n", rc);
2020 return rc;
2021 }
2022
2023 fg_encode(chip->sp, FG_SRAM_SYS_TERM_CURR, chip->dt.sys_term_curr_ma,
2024 buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002025 rc = fg_sram_write(chip, chip->sp[FG_SRAM_SYS_TERM_CURR].addr_word,
2026 chip->sp[FG_SRAM_SYS_TERM_CURR].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002027 chip->sp[FG_SRAM_SYS_TERM_CURR].len, FG_IMA_DEFAULT);
2028 if (rc < 0) {
2029 pr_err("Error in writing sys_term_curr, rc=%d\n", rc);
2030 return rc;
2031 }
2032
2033 if (chip->dt.vbatt_low_thr_mv > 0) {
2034 fg_encode(chip->sp, FG_SRAM_VBATT_LOW,
2035 chip->dt.vbatt_low_thr_mv, buf);
Nicholas Troasta2b40372016-08-15 10:45:39 -07002036 rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_LOW].addr_word,
2037 chip->sp[FG_SRAM_VBATT_LOW].addr_byte, buf,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002038 chip->sp[FG_SRAM_VBATT_LOW].len,
2039 FG_IMA_DEFAULT);
2040 if (rc < 0) {
2041 pr_err("Error in writing vbatt_low_thr, rc=%d\n", rc);
2042 return rc;
2043 }
2044 }
2045
2046 if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) {
2047 fg_encode(chip->sp, FG_SRAM_DELTA_SOC_THR,
2048 chip->dt.delta_soc_thr, buf);
2049 rc = fg_sram_write(chip,
Nicholas Troasta2b40372016-08-15 10:45:39 -07002050 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_word,
2051 chip->sp[FG_SRAM_DELTA_SOC_THR].addr_byte,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002052 buf, chip->sp[FG_SRAM_DELTA_SOC_THR].len,
2053 FG_IMA_DEFAULT);
2054 if (rc < 0) {
2055 pr_err("Error in writing delta_soc_thr, rc=%d\n", rc);
2056 return rc;
2057 }
2058 }
2059
2060 if (chip->dt.recharge_soc_thr > 0 && chip->dt.recharge_soc_thr < 100) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002061 rc = fg_set_recharge_soc(chip, chip->dt.recharge_soc_thr);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002062 if (rc < 0) {
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002063 pr_err("Error in setting recharge_soc, rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002064 return rc;
2065 }
2066 }
2067
2068 if (chip->dt.rsense_sel >= SRC_SEL_BATFET &&
2069 chip->dt.rsense_sel < SRC_SEL_RESERVED) {
2070 rc = fg_masked_write(chip, BATT_INFO_IBATT_SENSING_CFG(chip),
2071 SOURCE_SELECT_MASK, chip->dt.rsense_sel);
2072 if (rc < 0) {
2073 pr_err("Error in writing rsense_sel, rc=%d\n", rc);
2074 return rc;
2075 }
2076 }
2077
2078 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COLD], &val);
2079 rc = fg_write(chip, BATT_INFO_JEITA_TOO_COLD(chip), &val, 1);
2080 if (rc < 0) {
2081 pr_err("Error in writing jeita_cold, rc=%d\n", rc);
2082 return rc;
2083 }
2084
2085 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COOL], &val);
2086 rc = fg_write(chip, BATT_INFO_JEITA_COLD(chip), &val, 1);
2087 if (rc < 0) {
2088 pr_err("Error in writing jeita_cool, rc=%d\n", rc);
2089 return rc;
2090 }
2091
2092 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_WARM], &val);
2093 rc = fg_write(chip, BATT_INFO_JEITA_HOT(chip), &val, 1);
2094 if (rc < 0) {
2095 pr_err("Error in writing jeita_warm, rc=%d\n", rc);
2096 return rc;
2097 }
2098
2099 get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_HOT], &val);
2100 rc = fg_write(chip, BATT_INFO_JEITA_TOO_HOT(chip), &val, 1);
2101 if (rc < 0) {
2102 pr_err("Error in writing jeita_hot, rc=%d\n", rc);
2103 return rc;
2104 }
2105
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002106 if (chip->dt.esr_timer_charging > 0) {
2107 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_charging, true,
2108 FG_IMA_DEFAULT);
2109 if (rc < 0) {
2110 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2111 return rc;
2112 }
2113 }
2114
2115 if (chip->dt.esr_timer_awake > 0) {
2116 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
2117 FG_IMA_DEFAULT);
2118 if (rc < 0) {
2119 pr_err("Error in setting ESR timer, rc=%d\n", rc);
2120 return rc;
2121 }
2122 }
2123
Nicholas Troaste29dec92016-08-24 09:35:11 -07002124 if (chip->cyc_ctr.en)
2125 restore_cycle_counter(chip);
2126
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002127 if (chip->dt.jeita_hyst_temp >= 0) {
2128 val = chip->dt.jeita_hyst_temp << JEITA_TEMP_HYST_SHIFT;
2129 rc = fg_masked_write(chip, BATT_INFO_BATT_TEMP_CFG(chip),
2130 JEITA_TEMP_HYST_MASK, val);
2131 if (rc < 0) {
2132 pr_err("Error in writing batt_temp_cfg, rc=%d\n", rc);
2133 return rc;
2134 }
2135 }
2136
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002137 get_batt_temp_delta(chip->dt.batt_temp_delta, &val);
2138 rc = fg_masked_write(chip, BATT_INFO_BATT_TMPR_INTR(chip),
2139 CHANGE_THOLD_MASK, val);
2140 if (rc < 0) {
2141 pr_err("Error in writing batt_temp_delta, rc=%d\n", rc);
2142 return rc;
2143 }
2144
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002145 return 0;
2146}
2147
2148static int fg_memif_init(struct fg_chip *chip)
2149{
2150 return fg_ima_init(chip);
2151}
2152
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002153/* INTERRUPT HANDLERS STAY HERE */
2154
2155static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
2156{
2157 struct fg_chip *chip = data;
2158
2159 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2160 return IRQ_HANDLED;
2161}
2162
2163static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
2164{
2165 struct fg_chip *chip = data;
2166 u8 status;
2167 int rc;
2168
2169 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2170 rc = fg_read(chip, BATT_INFO_INT_RT_STS(chip), &status, 1);
2171 if (rc < 0) {
2172 pr_err("failed to read addr=0x%04x, rc=%d\n",
2173 BATT_INFO_INT_RT_STS(chip), rc);
2174 return IRQ_HANDLED;
2175 }
2176
2177 chip->battery_missing = (status & BT_MISS_BIT);
2178
2179 if (chip->battery_missing) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002180 chip->profile_available = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002181 chip->profile_loaded = false;
Nicholas Troaste29dec92016-08-24 09:35:11 -07002182 clear_cycle_counter(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002183 } else {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002184 rc = fg_get_batt_profile(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002185 if (rc < 0) {
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002186 pr_err("Error in getting battery profile, rc:%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002187 return IRQ_HANDLED;
2188 }
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002189 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002190 }
2191
2192 return IRQ_HANDLED;
2193}
2194
2195static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data)
2196{
2197 struct fg_chip *chip = data;
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002198 union power_supply_propval prop = {0, };
2199 int rc, batt_temp;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002200
2201 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002202 rc = fg_get_battery_temp(chip, &batt_temp);
2203 if (rc < 0) {
2204 pr_err("Error in getting batt_temp\n");
2205 return IRQ_HANDLED;
2206 }
2207
2208 if (!is_charger_available(chip)) {
2209 chip->last_batt_temp = batt_temp;
2210 return IRQ_HANDLED;
2211 }
2212
2213 power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
2214 &prop);
2215 chip->health = prop.intval;
2216
2217 if (chip->last_batt_temp != batt_temp) {
2218 chip->last_batt_temp = batt_temp;
2219 power_supply_changed(chip->batt_psy);
2220 }
2221
2222 if (abs(chip->last_batt_temp - batt_temp) > 30)
2223 pr_warn("Battery temperature last:%d current: %d\n",
2224 chip->last_batt_temp, batt_temp);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002225 return IRQ_HANDLED;
2226}
2227
2228static irqreturn_t fg_first_est_irq_handler(int irq, void *data)
2229{
2230 struct fg_chip *chip = data;
2231
2232 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2233 complete_all(&chip->soc_ready);
2234 return IRQ_HANDLED;
2235}
2236
2237static irqreturn_t fg_soc_update_irq_handler(int irq, void *data)
2238{
2239 struct fg_chip *chip = data;
2240
2241 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2242 complete_all(&chip->soc_update);
2243 return IRQ_HANDLED;
2244}
2245
2246static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
2247{
2248 struct fg_chip *chip = data;
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002249 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002250
Nicholas Troaste29dec92016-08-24 09:35:11 -07002251 if (chip->cyc_ctr.en)
2252 schedule_work(&chip->cycle_count_work);
2253
Nicholas Troast65e29652016-09-22 11:27:04 -07002254 if (is_charger_available(chip))
2255 power_supply_changed(chip->batt_psy);
2256
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002257 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002258
2259 if (chip->cl.active)
2260 fg_cap_learning_update(chip);
2261
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002262 rc = fg_charge_full_update(chip);
2263 if (rc < 0)
2264 pr_err("Error in charge_full_update, rc=%d\n", rc);
2265
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002266 rc = fg_adjust_ki_coeff_dischg(chip);
2267 if (rc < 0)
2268 pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
2269
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002270 return IRQ_HANDLED;
2271}
2272
2273static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data)
2274{
2275 struct fg_chip *chip = data;
2276
Nicholas Troast65e29652016-09-22 11:27:04 -07002277 if (is_charger_available(chip))
2278 power_supply_changed(chip->batt_psy);
2279
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002280 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2281 return IRQ_HANDLED;
2282}
2283
2284static irqreturn_t fg_soc_irq_handler(int irq, void *data)
2285{
2286 struct fg_chip *chip = data;
2287
2288 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2289 return IRQ_HANDLED;
2290}
2291
2292static irqreturn_t fg_dummy_irq_handler(int irq, void *data)
2293{
2294 struct fg_chip *chip = data;
2295
2296 fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
2297 return IRQ_HANDLED;
2298}
2299
2300static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
2301 /* BATT_SOC irqs */
2302 [MSOC_FULL_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002303 .name = "msoc-full",
2304 .handler = fg_soc_irq_handler,
2305 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002306 [MSOC_HIGH_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002307 .name = "msoc-high",
2308 .handler = fg_soc_irq_handler,
2309 .wakeable = true,
2310 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002311 [MSOC_EMPTY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002312 .name = "msoc-empty",
2313 .handler = fg_empty_soc_irq_handler,
2314 .wakeable = true,
2315 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002316 [MSOC_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002317 .name = "msoc-low",
2318 .handler = fg_soc_irq_handler,
2319 .wakeable = true,
2320 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002321 [MSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002322 .name = "msoc-delta",
2323 .handler = fg_delta_soc_irq_handler,
2324 .wakeable = true,
2325 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002326 [BSOC_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002327 .name = "bsoc-delta",
2328 .handler = fg_dummy_irq_handler,
2329 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002330 [SOC_READY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002331 .name = "soc-ready",
2332 .handler = fg_first_est_irq_handler,
2333 .wakeable = true,
2334 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002335 [SOC_UPDATE_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002336 .name = "soc-update",
2337 .handler = fg_soc_update_irq_handler,
2338 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002339 /* BATT_INFO irqs */
2340 [BATT_TEMP_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002341 .name = "batt-temp-delta",
2342 .handler = fg_delta_batt_temp_irq_handler,
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002343 .wakeable = true,
Nicholas Troast3cc97182016-09-23 08:54:13 -07002344 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002345 [BATT_MISSING_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002346 .name = "batt-missing",
2347 .handler = fg_batt_missing_irq_handler,
2348 .wakeable = true,
2349 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002350 [ESR_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002351 .name = "esr-delta",
2352 .handler = fg_dummy_irq_handler,
2353 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002354 [VBATT_LOW_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002355 .name = "vbatt-low",
2356 .handler = fg_vbatt_low_irq_handler,
2357 .wakeable = true,
2358 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002359 [VBATT_PRED_DELTA_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002360 .name = "vbatt-pred-delta",
2361 .handler = fg_dummy_irq_handler,
2362 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002363 /* MEM_IF irqs */
2364 [DMA_GRANT_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002365 .name = "dma-grant",
2366 .handler = fg_dummy_irq_handler,
2367 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002368 [MEM_XCP_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002369 .name = "mem-xcp",
2370 .handler = fg_dummy_irq_handler,
2371 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002372 [IMA_RDY_IRQ] = {
Nicholas Troast3cc97182016-09-23 08:54:13 -07002373 .name = "ima-rdy",
2374 .handler = fg_dummy_irq_handler,
2375 },
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002376};
2377
2378static int fg_get_irq_index_byname(const char *name)
2379{
2380 int i;
2381
2382 for (i = 0; i < ARRAY_SIZE(fg_irqs); i++) {
2383 if (strcmp(fg_irqs[i].name, name) == 0)
2384 return i;
2385 }
2386
2387 pr_err("%s is not in irq list\n", name);
2388 return -ENOENT;
2389}
2390
2391static int fg_register_interrupts(struct fg_chip *chip)
2392{
2393 struct device_node *child, *node = chip->dev->of_node;
2394 struct property *prop;
2395 const char *name;
2396 int rc, irq, irq_index;
2397
2398 for_each_available_child_of_node(node, child) {
2399 of_property_for_each_string(child, "interrupt-names", prop,
2400 name) {
2401 irq = of_irq_get_byname(child, name);
2402 if (irq < 0) {
2403 dev_err(chip->dev, "failed to get irq %s irq:%d\n",
2404 name, irq);
2405 return irq;
2406 }
2407
2408 irq_index = fg_get_irq_index_byname(name);
2409 if (irq_index < 0)
2410 return irq_index;
2411
2412 rc = devm_request_threaded_irq(chip->dev, irq, NULL,
2413 fg_irqs[irq_index].handler,
2414 IRQF_ONESHOT, name, chip);
2415 if (rc < 0) {
2416 dev_err(chip->dev, "failed to register irq handler for %s rc:%d\n",
2417 name, rc);
2418 return rc;
2419 }
2420
2421 fg_irqs[irq_index].irq = irq;
2422 if (fg_irqs[irq_index].wakeable)
2423 enable_irq_wake(fg_irqs[irq_index].irq);
2424 }
2425 }
2426
2427 return 0;
2428}
2429
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002430static int fg_parse_ki_coefficients(struct fg_chip *chip)
2431{
2432 struct device_node *node = chip->dev->of_node;
2433 int rc, i;
2434
2435 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-soc-dischg",
2436 sizeof(u32));
2437 if (rc != KI_COEFF_SOC_LEVELS)
2438 return 0;
2439
2440 rc = of_property_read_u32_array(node, "qcom,ki-coeff-soc-dischg",
2441 chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
2442 if (rc < 0) {
2443 pr_err("Error in reading ki-coeff-soc-dischg, rc=%d\n",
2444 rc);
2445 return rc;
2446 }
2447
2448 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-med-dischg",
2449 sizeof(u32));
2450 if (rc != KI_COEFF_SOC_LEVELS)
2451 return 0;
2452
2453 rc = of_property_read_u32_array(node, "qcom,ki-coeff-med-dischg",
2454 chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
2455 if (rc < 0) {
2456 pr_err("Error in reading ki-coeff-med-dischg, rc=%d\n",
2457 rc);
2458 return rc;
2459 }
2460
2461 rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-hi-dischg",
2462 sizeof(u32));
2463 if (rc != KI_COEFF_SOC_LEVELS)
2464 return 0;
2465
2466 rc = of_property_read_u32_array(node, "qcom,ki-coeff-hi-dischg",
2467 chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
2468 if (rc < 0) {
2469 pr_err("Error in reading ki-coeff-hi-dischg, rc=%d\n",
2470 rc);
2471 return rc;
2472 }
2473
2474 for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
2475 if (chip->dt.ki_coeff_soc[i] < 0 ||
2476 chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
2477 pr_err("Error in ki_coeff_soc_dischg values\n");
2478 return -EINVAL;
2479 }
2480
2481 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
2482 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
2483 pr_err("Error in ki_coeff_med_dischg values\n");
2484 return -EINVAL;
2485 }
2486
2487 if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
2488 chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
2489 pr_err("Error in ki_coeff_med_dischg values\n");
2490 return -EINVAL;
2491 }
2492 }
2493 chip->ki_coeff_dischg_en = true;
2494 return 0;
2495}
2496
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002497#define DEFAULT_CUTOFF_VOLT_MV 3200
2498#define DEFAULT_EMPTY_VOLT_MV 3100
2499#define DEFAULT_CHG_TERM_CURR_MA 100
Subbaraman Narayanamurthy4bf3ce22016-09-19 11:17:59 -07002500#define DEFAULT_SYS_TERM_CURR_MA -125
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002501#define DEFAULT_DELTA_SOC_THR 1
2502#define DEFAULT_RECHARGE_SOC_THR 95
2503#define DEFAULT_BATT_TEMP_COLD 0
2504#define DEFAULT_BATT_TEMP_COOL 5
2505#define DEFAULT_BATT_TEMP_WARM 45
2506#define DEFAULT_BATT_TEMP_HOT 50
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002507#define DEFAULT_CL_START_SOC 15
2508#define DEFAULT_CL_MIN_TEMP_DECIDEGC 150
2509#define DEFAULT_CL_MAX_TEMP_DECIDEGC 450
2510#define DEFAULT_CL_MAX_INC_DECIPERC 5
2511#define DEFAULT_CL_MAX_DEC_DECIPERC 100
2512#define DEFAULT_CL_MIN_LIM_DECIPERC 0
2513#define DEFAULT_CL_MAX_LIM_DECIPERC 0
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002514#define BTEMP_DELTA_LOW 2
2515#define BTEMP_DELTA_HIGH 10
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002516static int fg_parse_dt(struct fg_chip *chip)
2517{
2518 struct device_node *child, *revid_node, *node = chip->dev->of_node;
2519 u32 base, temp;
2520 u8 subtype;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002521 int rc;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002522
2523 if (!node) {
2524 dev_err(chip->dev, "device tree node missing\n");
2525 return -ENXIO;
2526 }
2527
2528 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
2529 if (!revid_node) {
2530 pr_err("Missing qcom,pmic-revid property - driver failed\n");
2531 return -EINVAL;
2532 }
2533
2534 chip->pmic_rev_id = get_revid_data(revid_node);
2535 if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
2536 pr_err("Unable to get pmic_revid rc=%ld\n",
2537 PTR_ERR(chip->pmic_rev_id));
2538 /*
2539 * the revid peripheral must be registered, any failure
2540 * here only indicates that the rev-id module has not
2541 * probed yet.
2542 */
2543 return -EPROBE_DEFER;
2544 }
2545
2546 pr_debug("PMIC subtype %d Digital major %d\n",
2547 chip->pmic_rev_id->pmic_subtype, chip->pmic_rev_id->rev4);
2548
2549 switch (chip->pmic_rev_id->pmic_subtype) {
2550 case PMICOBALT_SUBTYPE:
Nicholas Troast69da2252016-09-07 16:17:47 -07002551 if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4) {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002552 chip->sp = pmicobalt_v1_sram_params;
Nicholas Troast69da2252016-09-07 16:17:47 -07002553 chip->alg_flags = pmicobalt_v1_alg_flags;
2554 } else if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4) {
Nicholas Troasta2b40372016-08-15 10:45:39 -07002555 chip->sp = pmicobalt_v2_sram_params;
Nicholas Troast69da2252016-09-07 16:17:47 -07002556 chip->alg_flags = pmicobalt_v2_alg_flags;
2557 } else {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002558 return -EINVAL;
Nicholas Troast69da2252016-09-07 16:17:47 -07002559 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002560 break;
2561 default:
2562 return -EINVAL;
2563 }
2564
2565 chip->batt_id_chan = iio_channel_get(chip->dev, "rradc_batt_id");
2566 if (IS_ERR(chip->batt_id_chan)) {
2567 if (PTR_ERR(chip->batt_id_chan) != -EPROBE_DEFER)
2568 pr_err("batt_id_chan unavailable %ld\n",
2569 PTR_ERR(chip->batt_id_chan));
2570 rc = PTR_ERR(chip->batt_id_chan);
2571 chip->batt_id_chan = NULL;
2572 return rc;
2573 }
2574
2575 if (of_get_available_child_count(node) == 0) {
2576 dev_err(chip->dev, "No child nodes specified!\n");
2577 return -ENXIO;
2578 }
2579
2580 for_each_available_child_of_node(node, child) {
2581 rc = of_property_read_u32(child, "reg", &base);
2582 if (rc < 0) {
2583 dev_err(chip->dev, "reg not specified in node %s, rc=%d\n",
2584 child->full_name, rc);
2585 return rc;
2586 }
2587
2588 rc = fg_read(chip, base + PERPH_SUBTYPE_REG, &subtype, 1);
2589 if (rc < 0) {
2590 dev_err(chip->dev, "Couldn't read subtype for base %d, rc=%d\n",
2591 base, rc);
2592 return rc;
2593 }
2594
2595 switch (subtype) {
2596 case FG_BATT_SOC_PMICOBALT:
2597 chip->batt_soc_base = base;
2598 break;
2599 case FG_BATT_INFO_PMICOBALT:
2600 chip->batt_info_base = base;
2601 break;
2602 case FG_MEM_INFO_PMICOBALT:
2603 chip->mem_if_base = base;
2604 break;
2605 default:
2606 dev_err(chip->dev, "Invalid peripheral subtype 0x%x\n",
2607 subtype);
2608 return -ENXIO;
2609 }
2610 }
2611
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002612 rc = fg_get_batt_profile(chip);
2613 if (rc < 0)
2614 pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
2615 chip->batt_id, rc);
2616
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002617 /* Read all the optional properties below */
2618 rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp);
2619 if (rc < 0)
2620 chip->dt.cutoff_volt_mv = DEFAULT_CUTOFF_VOLT_MV;
2621 else
2622 chip->dt.cutoff_volt_mv = temp;
2623
2624 rc = of_property_read_u32(node, "qcom,fg-empty-voltage", &temp);
2625 if (rc < 0)
2626 chip->dt.empty_volt_mv = DEFAULT_EMPTY_VOLT_MV;
2627 else
2628 chip->dt.empty_volt_mv = temp;
2629
2630 rc = of_property_read_u32(node, "qcom,fg-vbatt-low-thr", &temp);
2631 if (rc < 0)
2632 chip->dt.vbatt_low_thr_mv = -EINVAL;
2633 else
2634 chip->dt.vbatt_low_thr_mv = temp;
2635
2636 rc = of_property_read_u32(node, "qcom,fg-chg-term-current", &temp);
2637 if (rc < 0)
2638 chip->dt.chg_term_curr_ma = DEFAULT_CHG_TERM_CURR_MA;
2639 else
2640 chip->dt.chg_term_curr_ma = temp;
2641
2642 rc = of_property_read_u32(node, "qcom,fg-sys-term-current", &temp);
2643 if (rc < 0)
2644 chip->dt.sys_term_curr_ma = DEFAULT_SYS_TERM_CURR_MA;
2645 else
2646 chip->dt.sys_term_curr_ma = temp;
2647
2648 rc = of_property_read_u32(node, "qcom,fg-delta-soc-thr", &temp);
2649 if (rc < 0)
2650 chip->dt.delta_soc_thr = DEFAULT_DELTA_SOC_THR;
2651 else
2652 chip->dt.delta_soc_thr = temp;
2653
2654 rc = of_property_read_u32(node, "qcom,fg-recharge-soc-thr", &temp);
2655 if (rc < 0)
2656 chip->dt.recharge_soc_thr = DEFAULT_RECHARGE_SOC_THR;
2657 else
2658 chip->dt.recharge_soc_thr = temp;
2659
2660 rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp);
2661 if (rc < 0)
2662 chip->dt.rsense_sel = SRC_SEL_BATFET_SMB;
2663 else
2664 chip->dt.rsense_sel = (u8)temp & SOURCE_SELECT_MASK;
2665
2666 chip->dt.jeita_thresholds[JEITA_COLD] = DEFAULT_BATT_TEMP_COLD;
2667 chip->dt.jeita_thresholds[JEITA_COOL] = DEFAULT_BATT_TEMP_COOL;
2668 chip->dt.jeita_thresholds[JEITA_WARM] = DEFAULT_BATT_TEMP_WARM;
2669 chip->dt.jeita_thresholds[JEITA_HOT] = DEFAULT_BATT_TEMP_HOT;
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002670 if (of_property_count_elems_of_size(node, "qcom,fg-jeita-thresholds",
2671 sizeof(u32)) == NUM_JEITA_LEVELS) {
2672 rc = of_property_read_u32_array(node,
2673 "qcom,fg-jeita-thresholds",
2674 chip->dt.jeita_thresholds, NUM_JEITA_LEVELS);
2675 if (rc < 0)
2676 pr_warn("Error reading Jeita thresholds, default values will be used rc:%d\n",
2677 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002678 }
2679
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002680 rc = of_property_read_u32(node, "qcom,fg-esr-timer-charging", &temp);
2681 if (rc < 0)
2682 chip->dt.esr_timer_charging = -EINVAL;
2683 else
2684 chip->dt.esr_timer_charging = temp;
2685
2686 rc = of_property_read_u32(node, "qcom,fg-esr-timer-awake", &temp);
2687 if (rc < 0)
2688 chip->dt.esr_timer_awake = -EINVAL;
2689 else
2690 chip->dt.esr_timer_awake = temp;
2691
2692 rc = of_property_read_u32(node, "qcom,fg-esr-timer-asleep", &temp);
2693 if (rc < 0)
2694 chip->dt.esr_timer_asleep = -EINVAL;
2695 else
2696 chip->dt.esr_timer_asleep = temp;
2697
Nicholas Troaste29dec92016-08-24 09:35:11 -07002698 chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
2699 if (chip->cyc_ctr.en)
2700 chip->cyc_ctr.id = 1;
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002701
Subbaraman Narayanamurthy6da170e2016-09-21 12:36:03 -07002702 chip->dt.force_load_profile = of_property_read_bool(node,
2703 "qcom,fg-force-load-profile");
2704
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002705 rc = of_property_read_u32(node, "qcom,cl-start-capacity", &temp);
2706 if (rc < 0)
2707 chip->dt.cl_start_soc = DEFAULT_CL_START_SOC;
2708 else
2709 chip->dt.cl_start_soc = temp;
2710
2711 rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp);
2712 if (rc < 0)
2713 chip->dt.cl_min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC;
2714 else
2715 chip->dt.cl_min_temp = temp;
2716
2717 rc = of_property_read_u32(node, "qcom,cl-max-temp", &temp);
2718 if (rc < 0)
2719 chip->dt.cl_max_temp = DEFAULT_CL_MAX_TEMP_DECIDEGC;
2720 else
2721 chip->dt.cl_max_temp = temp;
2722
2723 rc = of_property_read_u32(node, "qcom,cl-max-increment", &temp);
2724 if (rc < 0)
2725 chip->dt.cl_max_cap_inc = DEFAULT_CL_MAX_INC_DECIPERC;
2726 else
2727 chip->dt.cl_max_cap_inc = temp;
2728
2729 rc = of_property_read_u32(node, "qcom,cl-max-decrement", &temp);
2730 if (rc < 0)
2731 chip->dt.cl_max_cap_dec = DEFAULT_CL_MAX_DEC_DECIPERC;
2732 else
2733 chip->dt.cl_max_cap_dec = temp;
2734
2735 rc = of_property_read_u32(node, "qcom,cl-min-limit", &temp);
2736 if (rc < 0)
2737 chip->dt.cl_min_cap_limit = DEFAULT_CL_MIN_LIM_DECIPERC;
2738 else
2739 chip->dt.cl_min_cap_limit = temp;
2740
2741 rc = of_property_read_u32(node, "qcom,cl-max-limit", &temp);
2742 if (rc < 0)
2743 chip->dt.cl_max_cap_limit = DEFAULT_CL_MAX_LIM_DECIPERC;
2744 else
2745 chip->dt.cl_max_cap_limit = temp;
2746
Subbaraman Narayanamurthy65ff45e2016-09-23 19:11:17 -07002747 rc = of_property_read_u32(node, "qcom,fg-jeita-hyst-temp", &temp);
2748 if (rc < 0)
2749 chip->dt.jeita_hyst_temp = -EINVAL;
2750 else
2751 chip->dt.jeita_hyst_temp = temp;
2752
Subbaraman Narayanamurthy11bddec2016-09-26 11:27:24 -07002753 rc = of_property_read_u32(node, "qcom,fg-batt-temp-delta", &temp);
2754 if (rc < 0)
2755 chip->dt.batt_temp_delta = -EINVAL;
2756 else if (temp > BTEMP_DELTA_LOW && temp <= BTEMP_DELTA_HIGH)
2757 chip->dt.batt_temp_delta = temp;
2758
Subbaraman Narayanamurthyf9611e32016-09-26 11:12:47 -07002759 chip->dt.hold_soc_while_full = of_property_read_bool(node,
2760 "qcom,hold-soc-while-full");
Subbaraman Narayanamurthyc1a94ed2016-10-05 19:58:58 -07002761
2762 rc = fg_parse_ki_coefficients(chip);
2763 if (rc < 0)
2764 pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
2765
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002766 return 0;
2767}
2768
2769static void fg_cleanup(struct fg_chip *chip)
2770{
2771 power_supply_unreg_notifier(&chip->nb);
Nicholas Troast69da2252016-09-07 16:17:47 -07002772 debugfs_remove_recursive(chip->dfs_root);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002773 if (chip->awake_votable)
2774 destroy_votable(chip->awake_votable);
2775
2776 if (chip->batt_id_chan)
2777 iio_channel_release(chip->batt_id_chan);
2778
2779 dev_set_drvdata(chip->dev, NULL);
2780}
2781
2782static int fg_gen3_probe(struct platform_device *pdev)
2783{
2784 struct fg_chip *chip;
2785 struct power_supply_config fg_psy_cfg;
2786 int rc;
2787
2788 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2789 if (!chip)
2790 return -ENOMEM;
2791
2792 chip->dev = &pdev->dev;
2793 chip->debug_mask = &fg_gen3_debug_mask;
2794 chip->irqs = fg_irqs;
2795 chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
2796 if (!chip->regmap) {
2797 dev_err(chip->dev, "Parent regmap is unavailable\n");
2798 return -ENXIO;
2799 }
2800
2801 rc = fg_parse_dt(chip);
2802 if (rc < 0) {
2803 dev_err(chip->dev, "Error in reading DT parameters, rc:%d\n",
2804 rc);
2805 return rc;
2806 }
2807
2808 chip->awake_votable = create_votable("FG_WS", VOTE_SET_ANY, fg_awake_cb,
2809 chip);
2810 if (IS_ERR(chip->awake_votable)) {
2811 rc = PTR_ERR(chip->awake_votable);
2812 return rc;
2813 }
2814
2815 mutex_init(&chip->bus_lock);
2816 mutex_init(&chip->sram_rw_lock);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002817 mutex_init(&chip->cyc_ctr.lock);
Subbaraman Narayanamurthy07be9192016-09-14 14:48:49 -07002818 mutex_init(&chip->cl.lock);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002819 init_completion(&chip->soc_update);
2820 init_completion(&chip->soc_ready);
2821 INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
2822 INIT_WORK(&chip->status_change_work, status_change_work);
Nicholas Troaste29dec92016-08-24 09:35:11 -07002823 INIT_WORK(&chip->cycle_count_work, cycle_count_work);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002824
2825 rc = fg_memif_init(chip);
2826 if (rc < 0) {
2827 dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n",
2828 rc);
2829 goto exit;
2830 }
2831
2832 rc = fg_hw_init(chip);
2833 if (rc < 0) {
2834 dev_err(chip->dev, "Error in initializing FG hardware, rc:%d\n",
2835 rc);
2836 goto exit;
2837 }
2838
2839 platform_set_drvdata(pdev, chip);
2840
2841 /* Register the power supply */
2842 fg_psy_cfg.drv_data = chip;
2843 fg_psy_cfg.of_node = NULL;
2844 fg_psy_cfg.supplied_to = NULL;
2845 fg_psy_cfg.num_supplicants = 0;
2846 chip->fg_psy = devm_power_supply_register(chip->dev, &fg_psy_desc,
2847 &fg_psy_cfg);
2848 if (IS_ERR(chip->fg_psy)) {
2849 pr_err("failed to register fg_psy rc = %ld\n",
2850 PTR_ERR(chip->fg_psy));
2851 goto exit;
2852 }
2853
2854 chip->nb.notifier_call = fg_notifier_cb;
2855 rc = power_supply_reg_notifier(&chip->nb);
2856 if (rc < 0) {
2857 pr_err("Couldn't register psy notifier rc = %d\n", rc);
2858 goto exit;
2859 }
2860
2861 rc = fg_register_interrupts(chip);
2862 if (rc < 0) {
2863 dev_err(chip->dev, "Error in registering interrupts, rc:%d\n",
2864 rc);
2865 goto exit;
2866 }
2867
2868 /* Keep SOC_UPDATE irq disabled until we require it */
2869 if (fg_irqs[SOC_UPDATE_IRQ].irq)
2870 disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
2871
Nicholas Troast69da2252016-09-07 16:17:47 -07002872 rc = fg_debugfs_create(chip);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002873 if (rc < 0) {
2874 dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n",
2875 rc);
2876 goto exit;
2877 }
2878
Subbaraman Narayanamurthy6e7053e2016-09-19 14:52:12 -07002879 if (chip->profile_available)
2880 schedule_delayed_work(&chip->profile_load_work, 0);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002881
2882 device_init_wakeup(chip->dev, true);
2883 pr_debug("FG GEN3 driver successfully probed\n");
2884 return 0;
2885exit:
2886 fg_cleanup(chip);
2887 return rc;
2888}
2889
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002890static int fg_gen3_suspend(struct device *dev)
2891{
2892 struct fg_chip *chip = dev_get_drvdata(dev);
2893 int rc;
2894
2895 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
2896 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_asleep, false,
2897 FG_IMA_NO_WLOCK);
2898 if (rc < 0) {
2899 pr_err("Error in setting ESR timer during suspend, rc=%d\n",
2900 rc);
2901 return rc;
2902 }
2903 }
2904
2905 return 0;
2906}
2907
2908static int fg_gen3_resume(struct device *dev)
2909{
2910 struct fg_chip *chip = dev_get_drvdata(dev);
2911 int rc;
2912
2913 if (chip->dt.esr_timer_awake > 0 && chip->dt.esr_timer_asleep > 0) {
2914 rc = fg_set_esr_timer(chip, chip->dt.esr_timer_awake, false,
2915 FG_IMA_DEFAULT);
2916 if (rc < 0) {
2917 pr_err("Error in setting ESR timer during resume, rc=%d\n",
2918 rc);
2919 return rc;
2920 }
2921 }
2922
2923 return 0;
2924}
2925
2926static const struct dev_pm_ops fg_gen3_pm_ops = {
2927 .suspend = fg_gen3_suspend,
2928 .resume = fg_gen3_resume,
2929};
2930
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002931static int fg_gen3_remove(struct platform_device *pdev)
2932{
2933 struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
2934
2935 fg_cleanup(chip);
2936 return 0;
2937}
2938
2939static const struct of_device_id fg_gen3_match_table[] = {
2940 {.compatible = FG_GEN3_DEV_NAME},
2941 {},
2942};
2943
2944static struct platform_driver fg_gen3_driver = {
2945 .driver = {
2946 .name = FG_GEN3_DEV_NAME,
2947 .owner = THIS_MODULE,
2948 .of_match_table = fg_gen3_match_table,
Nicholas Troastdcf8fe62016-08-04 14:30:02 -07002949 .pm = &fg_gen3_pm_ops,
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002950 },
2951 .probe = fg_gen3_probe,
2952 .remove = fg_gen3_remove,
2953};
2954
2955static int __init fg_gen3_init(void)
2956{
2957 return platform_driver_register(&fg_gen3_driver);
2958}
2959
2960static void __exit fg_gen3_exit(void)
2961{
2962 return platform_driver_unregister(&fg_gen3_driver);
2963}
2964
2965module_init(fg_gen3_init);
2966module_exit(fg_gen3_exit);
2967
2968MODULE_DESCRIPTION("QPNP Fuel gauge GEN3 driver");
2969MODULE_LICENSE("GPL v2");
2970MODULE_ALIAS("platform:" FG_GEN3_DEV_NAME);