blob: 37ac7b53b7149f3c92375cd700697bd22cb4860c [file] [log] [blame]
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Xiaozhe Shi73a65692012-09-18 17:51:57 -070013#define pr_fmt(fmt) "BMS: %s: " fmt, __func__
Xiaozhe Shib19f7032012-08-16 12:14:16 -070014
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <linux/err.h>
20#include <linux/of.h>
21#include <linux/of_device.h>
22#include <linux/power_supply.h>
23#include <linux/spmi.h>
Xiaozhe Shie118c692012-09-24 15:17:43 -070024#include <linux/rtc.h>
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -070025#include <linux/delay.h>
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070026#include <linux/qpnp/qpnp-adc.h>
Xiaozhe Shi73a65692012-09-18 17:51:57 -070027#include <linux/mfd/pm8xxx/batterydata-lib.h>
Xiaozhe Shib19f7032012-08-16 12:14:16 -070028
Xiaozhe Shib19f7032012-08-16 12:14:16 -070029/* BMS Register Offsets */
30#define BMS1_REVISION1 0x0
31#define BMS1_REVISION2 0x1
32#define BMS1_STATUS1 0x8
33#define BMS1_MODE_CTL 0X40
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070034/* Coulomb counter clear registers */
Xiaozhe Shib19f7032012-08-16 12:14:16 -070035#define BMS1_CC_DATA_CTL 0x42
Xiaozhe Shia045a562012-11-28 16:55:39 -080036#define BMS1_CC_CLEAR_CTL 0x43
Xiaozhe Shi20640b52013-01-03 11:49:30 -080037/* BMS Tolerances */
38#define BMS1_TOL_CTL 0X44
Xiaozhe Shib19f7032012-08-16 12:14:16 -070039/* OCV limit registers */
40#define BMS1_OCV_USE_LOW_LIMIT_THR0 0x48
41#define BMS1_OCV_USE_LOW_LIMIT_THR1 0x49
42#define BMS1_OCV_USE_HIGH_LIMIT_THR0 0x4A
43#define BMS1_OCV_USE_HIGH_LIMIT_THR1 0x4B
44#define BMS1_OCV_USE_LIMIT_CTL 0x4C
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -070045/* Delay control */
46#define BMS1_S1_DELAY_CTL 0x5A
Xiaozhe Shib19f7032012-08-16 12:14:16 -070047/* CC interrupt threshold */
48#define BMS1_CC_THR0 0x7A
49#define BMS1_CC_THR1 0x7B
50#define BMS1_CC_THR2 0x7C
51#define BMS1_CC_THR3 0x7D
52#define BMS1_CC_THR4 0x7E
53/* OCV for r registers */
54#define BMS1_OCV_FOR_R_DATA0 0x80
55#define BMS1_OCV_FOR_R_DATA1 0x81
56#define BMS1_VSENSE_FOR_R_DATA0 0x82
57#define BMS1_VSENSE_FOR_R_DATA1 0x83
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070058/* Coulomb counter data */
Xiaozhe Shib19f7032012-08-16 12:14:16 -070059#define BMS1_CC_DATA0 0x8A
60#define BMS1_CC_DATA1 0x8B
61#define BMS1_CC_DATA2 0x8C
62#define BMS1_CC_DATA3 0x8D
63#define BMS1_CC_DATA4 0x8E
64/* OCV for soc data */
65#define BMS1_OCV_FOR_SOC_DATA0 0x90
66#define BMS1_OCV_FOR_SOC_DATA1 0x91
67#define BMS1_VSENSE_PON_DATA0 0x94
68#define BMS1_VSENSE_PON_DATA1 0x95
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070069#define BMS1_VSENSE_AVG_DATA0 0x98
70#define BMS1_VSENSE_AVG_DATA1 0x99
Xiaozhe Shib19f7032012-08-16 12:14:16 -070071#define BMS1_VBAT_AVG_DATA0 0x9E
72#define BMS1_VBAT_AVG_DATA1 0x9F
73/* Extra bms registers */
Xiaozhe Shi57058942013-03-27 16:54:54 -070074#define SOC_STORAGE_REG 0xB0
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070075#define IAVG_STORAGE_REG 0xB1
Xiaozhe Shi57058942013-03-27 16:54:54 -070076#define BMS1_BMS_DATA_REG_2 0xB2
Xiaozhe Shib19f7032012-08-16 12:14:16 -070077#define BMS1_BMS_DATA_REG_3 0xB3
Xiaozhe Shic40b3972012-11-30 14:11:16 -080078/* IADC Channel Select */
79#define IADC1_BMS_ADC_CH_SEL_CTL 0x48
Xiaozhe Shib19f7032012-08-16 12:14:16 -070080
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070081/* Configuration for saving of shutdown soc/iavg */
82#define IGNORE_SOC_TEMP_DECIDEG 50
83#define IAVG_STEP_SIZE_MA 50
84#define IAVG_START 600
Xiaozhe Shif5f966d2013-02-19 14:23:11 -080085#define IAVG_INVALID 0xFF
Xiaozhe Shic7cbd052013-03-29 12:03:11 -070086#define SOC_INVALID 0xFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070087
Xiaozhe Shie118c692012-09-24 15:17:43 -070088#define IAVG_SAMPLES 16
89
Xiaozhe Shib19f7032012-08-16 12:14:16 -070090#define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
91
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070092struct soc_params {
93 int fcc_uah;
94 int cc_uah;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -080095 int rbatt_mohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070096 int iavg_ua;
97 int uuc_uah;
98 int ocv_charge_uah;
Xiaozhe Shif36d2862013-01-04 10:17:35 -080099 int delta_time_s;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700100};
101
102struct raw_soc_params {
103 uint16_t last_good_ocv_raw;
104 int64_t cc;
105 int last_good_ocv_uv;
106};
107
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700108struct qpnp_bms_chip {
109 struct device *dev;
110 struct power_supply bms_psy;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700111 struct power_supply *batt_psy;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700112 struct spmi_device *spmi;
113 u16 base;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800114 u16 iadc_base;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700115
116 u8 revision1;
117 u8 revision2;
Xiaozhe Shid5d21412013-02-06 17:14:41 -0800118 int battery_present;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800119 bool new_battery;
120 bool last_soc_invalid;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700121 /* platform data */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -0800122 int r_sense_uohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700123 unsigned int v_cutoff_uv;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -0800124 int max_voltage_uv;
125 int r_conn_mohm;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700126 int shutdown_soc_valid_limit;
127 int adjust_soc_low_threshold;
128 int adjust_soc_high_threshold;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700129 int chg_term_ua;
Xiaozhe Shi73a65692012-09-18 17:51:57 -0700130 enum battery_type batt_type;
131 unsigned int fcc;
132 struct single_row_lut *fcc_temp_lut;
133 struct single_row_lut *fcc_sf_lut;
134 struct pc_temp_ocv_lut *pc_temp_ocv_lut;
135 struct sf_lut *pc_sf_lut;
136 struct sf_lut *rbatt_sf_lut;
137 int default_rbatt_mohm;
Xiaozhe Shi1a10aff2013-04-01 15:40:05 -0700138 int rbatt_capacitive_mohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700139
140 struct delayed_work calculate_soc_delayed_work;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800141 struct work_struct recalc_work;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700142
143 struct mutex bms_output_lock;
144 struct mutex last_ocv_uv_mutex;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700145 struct mutex soc_invalidation_mutex;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700146
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800147 bool use_external_rsense;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800148 bool use_ocv_thresholds;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800149
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700150 bool ignore_shutdown_soc;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800151 bool shutdown_soc_invalid;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700152 int shutdown_soc;
153 int shutdown_iavg_ma;
154
Xiaozhe Shi4be85782013-02-22 17:33:40 -0800155 struct wake_lock low_voltage_wake_lock;
156 bool low_voltage_wake_lock_held;
157 int low_voltage_threshold;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700158 int low_soc_calc_threshold;
159 int low_soc_calculate_soc_ms;
160 int calculate_soc_ms;
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -0800161 struct wake_lock soc_wake_lock;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700162
Xiaozhe Shie118c692012-09-24 15:17:43 -0700163 uint16_t ocv_reading_at_100;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700164 uint16_t prev_last_good_ocv_raw;
165 int last_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800166 int last_ocv_temp;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700167 int last_cc_uah;
168 unsigned long tm_sec;
169 bool first_time_calc_soc;
170 bool first_time_calc_uuc;
171 int pon_ocv_uv;
172
173 int iavg_samples_ma[IAVG_SAMPLES];
174 int iavg_index;
175 int iavg_num_samples;
176 struct timespec t_soc_queried;
177 int last_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700178 int last_soc_est;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700179
180 int charge_time_us;
181 int catch_up_time_us;
182 struct single_row_lut *adjusted_fcc_temp_lut;
183
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700184 unsigned int vadc_v0625;
185 unsigned int vadc_v1250;
186
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800187 int ibat_max_ua;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700188 int prev_uuc_iavg_ma;
189 int prev_pc_unusable;
190 int ibat_at_cv_ua;
191 int soc_at_cv;
192 int prev_chg_soc;
193 int calculated_soc;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -0800194 int prev_voltage_based_soc;
195 bool use_voltage_soc;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800196
197 int ocv_high_threshold_uv;
198 int ocv_low_threshold_uv;
Xiaozhe Shicdeee312012-12-18 15:10:18 -0800199 unsigned long last_recalc_time;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700200};
201
202static struct of_device_id qpnp_bms_match_table[] = {
203 { .compatible = QPNP_BMS_DEV_NAME },
204 {}
205};
206
207static char *qpnp_bms_supplicants[] = {
208 "battery"
209};
210
211static enum power_supply_property msm_bms_power_props[] = {
Xiaozhe Shid5d21412013-02-06 17:14:41 -0800212 POWER_SUPPLY_PROP_PRESENT,
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700213 POWER_SUPPLY_PROP_CAPACITY,
214 POWER_SUPPLY_PROP_CURRENT_NOW,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800215 POWER_SUPPLY_PROP_CURRENT_MAX,
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700216 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
217};
218
Xiaozhe Shi20640b52013-01-03 11:49:30 -0800219static bool bms_reset;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -0800220
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700221static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
222 u16 base, int count)
223{
224 int rc;
225 struct spmi_device *spmi = chip->spmi;
226
227 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700228 if (rc) {
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700229 pr_err("SPMI read failed rc=%d\n", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700230 return rc;
231 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700232 return 0;
233}
234
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700235static int qpnp_write_wrapper(struct qpnp_bms_chip *chip, u8 *val,
236 u16 base, int count)
237{
238 int rc;
239 struct spmi_device *spmi = chip->spmi;
240
241 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
242 if (rc) {
243 pr_err("SPMI write failed rc=%d\n", rc);
244 return rc;
245 }
246 return 0;
247}
248
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800249static int qpnp_masked_write_base(struct qpnp_bms_chip *chip, u16 addr,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700250 u8 mask, u8 val)
251{
252 int rc;
253 u8 reg;
254
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800255 rc = qpnp_read_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700256 if (rc) {
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800257 pr_err("read failed addr = %03X, rc = %d\n", addr, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700258 return rc;
259 }
260 reg &= ~mask;
261 reg |= val & mask;
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800262 rc = qpnp_write_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700263 if (rc) {
264 pr_err("write failed addr = %03X, val = %02x, mask = %02x, reg = %02x, rc = %d\n",
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800265 addr, val, mask, reg, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700266 return rc;
267 }
268 return 0;
269}
270
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800271static int qpnp_masked_write_iadc(struct qpnp_bms_chip *chip, u16 addr,
272 u8 mask, u8 val)
273{
274 return qpnp_masked_write_base(chip, chip->iadc_base + addr, mask, val);
275}
276
277static int qpnp_masked_write(struct qpnp_bms_chip *chip, u16 addr,
278 u8 mask, u8 val)
279{
280 return qpnp_masked_write_base(chip, chip->base + addr, mask, val);
281}
282
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700283#define HOLD_OREG_DATA BIT(0)
284static int lock_output_data(struct qpnp_bms_chip *chip)
285{
286 int rc;
287
288 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL,
289 HOLD_OREG_DATA, HOLD_OREG_DATA);
290 if (rc) {
291 pr_err("couldnt lock bms output rc = %d\n", rc);
292 return rc;
293 }
294 return 0;
295}
296
297static int unlock_output_data(struct qpnp_bms_chip *chip)
298{
299 int rc;
300
301 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL, HOLD_OREG_DATA, 0);
302 if (rc) {
303 pr_err("fail to unlock BMS_CONTROL rc = %d\n", rc);
304 return rc;
305 }
306 return 0;
307}
308
309#define V_PER_BIT_MUL_FACTOR 97656
310#define V_PER_BIT_DIV_FACTOR 1000
311#define VADC_INTRINSIC_OFFSET 0x6000
312
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800313static int vadc_reading_to_uv(int reading)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700314{
315 if (reading <= VADC_INTRINSIC_OFFSET)
316 return 0;
317
318 return (reading - VADC_INTRINSIC_OFFSET)
319 * V_PER_BIT_MUL_FACTOR / V_PER_BIT_DIV_FACTOR;
320}
321
322#define VADC_CALIB_UV 625000
323#define VBATT_MUL_FACTOR 3
324
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800325static int adjust_vbatt_reading(struct qpnp_bms_chip *chip, int reading_uv)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700326{
327 s64 numerator, denominator;
328
329 if (reading_uv == 0)
330 return 0;
331
332 /* don't adjust if not calibrated */
333 if (chip->vadc_v0625 == 0 || chip->vadc_v1250 == 0) {
334 pr_debug("No cal yet return %d\n",
335 VBATT_MUL_FACTOR * reading_uv);
336 return VBATT_MUL_FACTOR * reading_uv;
337 }
338
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700339 numerator = ((s64)reading_uv - chip->vadc_v0625) * VADC_CALIB_UV;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700340 denominator = (s64)chip->vadc_v1250 - chip->vadc_v0625;
341 if (denominator == 0)
342 return reading_uv * VBATT_MUL_FACTOR;
343 return (VADC_CALIB_UV + div_s64(numerator, denominator))
344 * VBATT_MUL_FACTOR;
345}
346
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800347static int convert_vbatt_uv_to_raw(struct qpnp_bms_chip *chip,
348 int unadjusted_vbatt)
349{
350 int scaled_vbatt = unadjusted_vbatt / VBATT_MUL_FACTOR;
351
352 if (scaled_vbatt <= 0)
353 return VADC_INTRINSIC_OFFSET;
354 return ((scaled_vbatt * V_PER_BIT_DIV_FACTOR) / V_PER_BIT_MUL_FACTOR)
355 + VADC_INTRINSIC_OFFSET;
356}
357
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700358static inline int convert_vbatt_raw_to_uv(struct qpnp_bms_chip *chip,
359 uint16_t reading)
360{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700361 int uv;
362
363 uv = vadc_reading_to_uv(reading);
364 pr_debug("%u raw converted into %d uv\n", reading, uv);
365 uv = adjust_vbatt_reading(chip, uv);
366 pr_debug("adjusted into %d uv\n", uv);
367 return uv;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700368}
369
370#define CC_READING_RESOLUTION_N 542535
371#define CC_READING_RESOLUTION_D 100000
372static int cc_reading_to_uv(int16_t reading)
373{
374 return div_s64(reading * CC_READING_RESOLUTION_N,
375 CC_READING_RESOLUTION_D);
376}
377
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800378#define QPNP_ADC_GAIN_IDEAL 3291LL
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700379static s64 cc_adjust_for_gain(s64 uv, uint16_t gain)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700380{
381 s64 result_uv;
382
383 pr_debug("adjusting_uv = %lld\n", uv);
Xiaozhe Shi820a47a2012-11-27 13:23:27 -0800384 if (gain == 0) {
385 pr_debug("gain is %d, not adjusting\n", gain);
386 return uv;
387 }
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700388 pr_debug("adjusting by factor: %lld/%hu = %lld%%\n",
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800389 QPNP_ADC_GAIN_IDEAL, gain,
390 div_s64(QPNP_ADC_GAIN_IDEAL * 100LL, (s64)gain));
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700391
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800392 result_uv = div_s64(uv * QPNP_ADC_GAIN_IDEAL, (s64)gain);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700393 pr_debug("result_uv = %lld\n", result_uv);
394 return result_uv;
395}
396
397static int convert_vsense_to_uv(struct qpnp_bms_chip *chip,
398 int16_t reading)
399{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700400 struct qpnp_iadc_calib calibration;
401
402 qpnp_iadc_get_gain_and_offset(&calibration);
403 return cc_adjust_for_gain(cc_reading_to_uv(reading),
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800404 calibration.gain_raw - calibration.offset_raw);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700405}
406
407static int read_vsense_avg(struct qpnp_bms_chip *chip, int *result_uv)
408{
409 int rc;
410 int16_t reading;
411
412 rc = qpnp_read_wrapper(chip, (u8 *)&reading,
413 chip->base + BMS1_VSENSE_AVG_DATA0, 2);
414
415 if (rc) {
416 pr_err("fail to read VSENSE_AVG rc = %d\n", rc);
417 return rc;
418 }
419
420 *result_uv = convert_vsense_to_uv(chip, reading);
421 return 0;
422}
423
424static int get_battery_current(struct qpnp_bms_chip *chip, int *result_ua)
425{
426 int vsense_uv = 0;
427
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800428 if (chip->r_sense_uohm == 0) {
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700429 pr_err("r_sense is zero\n");
430 return -EINVAL;
431 }
432
433 mutex_lock(&chip->bms_output_lock);
434 lock_output_data(chip);
435 read_vsense_avg(chip, &vsense_uv);
436 unlock_output_data(chip);
437 mutex_unlock(&chip->bms_output_lock);
438
439 pr_debug("vsense_uv=%duV\n", vsense_uv);
440 /* cast for signed division */
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800441 *result_ua = div_s64((vsense_uv * 1000000LL), (int)chip->r_sense_uohm);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700442 pr_debug("ibat=%duA\n", *result_ua);
443 return 0;
444}
445
446static int get_battery_voltage(int *result_uv)
447{
448 int rc;
449 struct qpnp_vadc_result adc_result;
450
451 rc = qpnp_vadc_read(VBAT_SNS, &adc_result);
452 if (rc) {
453 pr_err("error reading adc channel = %d, rc = %d\n",
454 VBAT_SNS, rc);
455 return rc;
456 }
457 pr_debug("mvolts phy = %lld meas = 0x%llx\n", adc_result.physical,
458 adc_result.measurement);
459 *result_uv = (int)adc_result.physical;
460 return 0;
461}
462
Xiaozhe Shie118c692012-09-24 15:17:43 -0700463#define CC_36_BIT_MASK 0xFFFFFFFFFLL
464
465static int read_cc_raw(struct qpnp_bms_chip *chip, int64_t *reading)
466{
467 int64_t raw_reading;
468 int rc;
469
470 rc = qpnp_read_wrapper(chip, (u8 *)&raw_reading,
471 chip->base + BMS1_CC_DATA0, 5);
472 if (rc) {
473 pr_err("Error reading cc: rc = %d\n", rc);
474 return -ENXIO;
475 }
476
477 raw_reading = raw_reading & CC_36_BIT_MASK;
478 /* convert 36 bit signed value into 64 signed value */
479 *reading = (raw_reading >> 35) == 0LL ?
480 raw_reading : ((-1LL ^ CC_36_BIT_MASK) | raw_reading);
481 pr_debug("before conversion: %llx, after conversion: %llx\n",
482 raw_reading, *reading);
483
484 return 0;
485}
486
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700487static int calib_vadc(struct qpnp_bms_chip *chip)
488{
Xiaozhe Shif62c0152013-03-28 17:57:19 -0700489 int rc, raw_0625, raw_1250;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700490 struct qpnp_vadc_result result;
491
492 rc = qpnp_vadc_read(REF_625MV, &result);
493 if (rc) {
494 pr_debug("vadc read failed with rc = %d\n", rc);
495 return rc;
496 }
Xiaozhe Shif62c0152013-03-28 17:57:19 -0700497 raw_0625 = result.adc_code;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700498
499 rc = qpnp_vadc_read(REF_125V, &result);
500 if (rc) {
501 pr_debug("vadc read failed with rc = %d\n", rc);
502 return rc;
503 }
Xiaozhe Shif62c0152013-03-28 17:57:19 -0700504 raw_1250 = result.adc_code;
505 chip->vadc_v0625 = vadc_reading_to_uv(raw_0625);
506 chip->vadc_v1250 = vadc_reading_to_uv(raw_1250);
507 pr_debug("vadc calib: 0625 = %d raw (%d uv), 1250 = %d raw (%d uv)\n",
508 raw_0625, chip->vadc_v0625,
509 raw_1250, chip->vadc_v1250);
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700510 return 0;
511}
512
Xiaozhe Shie118c692012-09-24 15:17:43 -0700513static void convert_and_store_ocv(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800514 struct raw_soc_params *raw,
515 int batt_temp)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700516{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700517 int rc;
518
519 pr_debug("prev_last_good_ocv_raw = %d, last_good_ocv_raw = %d\n",
520 chip->prev_last_good_ocv_raw,
521 raw->last_good_ocv_raw);
522 rc = calib_vadc(chip);
523 if (rc)
524 pr_err("Vadc reference voltage read failed, rc = %d\n", rc);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700525 chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
526 raw->last_good_ocv_uv = convert_vbatt_raw_to_uv(chip,
527 raw->last_good_ocv_raw);
528 chip->last_ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800529 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700530 pr_debug("last_good_ocv_uv = %d\n", raw->last_good_ocv_uv);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700531}
532
Xiaozhe Shia045a562012-11-28 16:55:39 -0800533#define CLEAR_CC BIT(7)
534#define CLEAR_SW_CC BIT(6)
535/**
536 * reset both cc and sw-cc.
537 * note: this should only be ever called from one thread
538 * or there may be a race condition where CC is never enabled
539 * again
540 */
541static void reset_cc(struct qpnp_bms_chip *chip)
542{
543 int rc;
544
545 pr_debug("resetting cc manually\n");
546 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
547 CLEAR_CC | CLEAR_SW_CC,
548 CLEAR_CC | CLEAR_SW_CC);
549 if (rc)
550 pr_err("cc reset failed: %d\n", rc);
551
552 /* wait for 100us for cc to reset */
553 udelay(100);
554
555 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
556 CLEAR_CC | CLEAR_SW_CC, 0);
557 if (rc)
558 pr_err("cc reenable failed: %d\n", rc);
559}
560
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800561static bool is_battery_charging(struct qpnp_bms_chip *chip)
562{
563 union power_supply_propval ret = {0,};
564
565 if (chip->batt_psy == NULL)
566 chip->batt_psy = power_supply_get_by_name("battery");
567 if (chip->batt_psy) {
568 /* if battery has been registered, use the status property */
569 chip->batt_psy->get_property(chip->batt_psy,
570 POWER_SUPPLY_PROP_STATUS, &ret);
571 return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
572 }
573
574 /* Default to false if the battery power supply is not registered. */
575 pr_debug("battery power supply is not registered\n");
576 return false;
577}
578
579static bool is_batfet_open(struct qpnp_bms_chip *chip)
580{
581 union power_supply_propval ret = {0,};
582
583 if (chip->batt_psy == NULL)
584 chip->batt_psy = power_supply_get_by_name("battery");
585 if (chip->batt_psy) {
586 /* if battery has been registered, use the status property */
587 chip->batt_psy->get_property(chip->batt_psy,
588 POWER_SUPPLY_PROP_STATUS, &ret);
589 return ret.intval == POWER_SUPPLY_STATUS_FULL;
590 }
591
592 /* Default to true if the battery power supply is not registered. */
593 pr_debug("battery power supply is not registered\n");
594 return true;
595}
596
597static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
598 int *ibat_ua, int *vbat_uv)
599{
600 struct qpnp_iadc_result i_result;
601 struct qpnp_vadc_result v_result;
602 enum qpnp_iadc_channels iadc_channel;
603 int rc;
604
605 iadc_channel = chip->use_external_rsense ?
606 EXTERNAL_RSENSE : INTERNAL_RSENSE;
607 rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
608 VBAT_SNS, &v_result);
609 if (rc) {
610 pr_err("vadc read failed with rc: %d\n", rc);
611 return rc;
612 }
613 /*
614 * reverse the current read by the iadc, since the bms uses
615 * flipped battery current polarity.
616 */
617 *ibat_ua = -1 * (int)i_result.result_ua;
618 *vbat_uv = (int)v_result.physical;
619
620 return 0;
621}
622
623static int estimate_ocv(struct qpnp_bms_chip *chip)
624{
625 int ibat_ua, vbat_uv, ocv_est_uv;
626 int rc;
Xiaozhe Shi1a10aff2013-04-01 15:40:05 -0700627 int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm
628 + chip->rbatt_capacitive_mohm;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800629
630 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
631 if (rc) {
632 pr_err("simultaneous failed rc = %d\n", rc);
633 return rc;
634 }
635
636 ocv_est_uv = vbat_uv + (ibat_ua * rbatt_mohm) / 1000;
637 pr_debug("estimated pon ocv = %d\n", ocv_est_uv);
638 return ocv_est_uv;
639}
640
641static void reset_for_new_battery(struct qpnp_bms_chip *chip, int batt_temp)
642{
643 chip->last_ocv_uv = estimate_ocv(chip);
644 chip->last_soc = -EINVAL;
645 chip->soc_at_cv = -EINVAL;
646 chip->shutdown_soc_invalid = true;
647 chip->shutdown_soc = 0;
648 chip->shutdown_iavg_ma = 0;
649 chip->prev_pc_unusable = -EINVAL;
650 reset_cc(chip);
651 chip->last_cc_uah = INT_MIN;
652 chip->last_ocv_temp = batt_temp;
653 chip->last_soc_invalid = true;
654}
655
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800656#define OCV_RAW_UNINITIALIZED 0xFFFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700657static int read_soc_params_raw(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800658 struct raw_soc_params *raw,
659 int batt_temp)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700660{
Xiaozhe Shie118c692012-09-24 15:17:43 -0700661 int rc;
662
663 mutex_lock(&chip->bms_output_lock);
Xiaozhe Shia045a562012-11-28 16:55:39 -0800664
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800665 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Xiaozhe Shia045a562012-11-28 16:55:39 -0800666 /* software workaround for BMS 1.0
667 * The coulomb counter does not reset upon PON, so reset it
668 * manually upon probe. */
669 if (chip->revision1 == 0 && chip->revision2 == 0)
670 reset_cc(chip);
671 }
672
Xiaozhe Shie118c692012-09-24 15:17:43 -0700673 lock_output_data(chip);
674
675 rc = qpnp_read_wrapper(chip, (u8 *)&raw->last_good_ocv_raw,
676 chip->base + BMS1_OCV_FOR_SOC_DATA0, 2);
677 if (rc) {
678 pr_err("Error reading ocv: rc = %d\n", rc);
679 return -ENXIO;
680 }
681
682 rc = read_cc_raw(chip, &raw->cc);
683 if (rc) {
684 pr_err("Failed to read raw cc data, rc = %d\n", rc);
685 return rc;
686 }
687
688 unlock_output_data(chip);
689 mutex_unlock(&chip->bms_output_lock);
690
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800691 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800692 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700693 pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800694 } else if (chip->new_battery) {
695 /* if a new battery was inserted, estimate the ocv */
696 reset_for_new_battery(chip, batt_temp);
697 raw->cc = 0;
698 raw->last_good_ocv_uv = chip->last_ocv_uv;
699 chip->new_battery = false;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700700 } else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800701 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700702 /* forget the old cc value upon ocv */
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800703 chip->last_cc_uah = INT_MIN;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700704 } else {
705 raw->last_good_ocv_uv = chip->last_ocv_uv;
706 }
707
708 /* fake a high OCV if done charging */
709 if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800710 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700711 } else {
712 /*
713 * force 100% ocv by selecting the highest voltage the
714 * battery could ever reach
715 */
716 raw->last_good_ocv_uv = chip->max_voltage_uv;
717 chip->last_ocv_uv = chip->max_voltage_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800718 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi1c63a892013-02-13 15:49:40 -0800719 reset_cc(chip);
720 raw->cc = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700721 }
722 pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
723 raw->last_good_ocv_raw, raw->last_good_ocv_uv);
724 pr_debug("cc_raw= 0x%llx\n", raw->cc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700725 return 0;
726}
727
Xiaozhe Shie118c692012-09-24 15:17:43 -0700728static int calculate_pc(struct qpnp_bms_chip *chip, int ocv_uv,
729 int batt_temp)
730{
731 int pc;
732
733 pc = interpolate_pc(chip->pc_temp_ocv_lut,
734 batt_temp / 10, ocv_uv / 1000);
735 pr_debug("pc = %u %% for ocv = %d uv batt_temp = %d\n",
736 pc, ocv_uv, batt_temp);
737 /* Multiply the initial FCC value by the scale factor. */
738 return pc;
739}
740
741static int calculate_fcc(struct qpnp_bms_chip *chip, int batt_temp)
742{
743 int fcc_uah;
744
745 if (chip->adjusted_fcc_temp_lut == NULL) {
746 /* interpolate_fcc returns a mv value. */
747 fcc_uah = interpolate_fcc(chip->fcc_temp_lut,
748 batt_temp) * 1000;
749 pr_debug("fcc = %d uAh\n", fcc_uah);
750 return fcc_uah;
751 } else {
752 return 1000 * interpolate_fcc(chip->adjusted_fcc_temp_lut,
753 batt_temp);
754 }
755}
756
757/* calculate remaining charge at the time of ocv */
758static int calculate_ocv_charge(struct qpnp_bms_chip *chip,
759 struct raw_soc_params *raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800760 int fcc_uah)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700761{
762 int ocv_uv, pc;
763
764 ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800765 pc = calculate_pc(chip, ocv_uv, chip->last_ocv_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700766 pr_debug("ocv_uv = %d pc = %d\n", ocv_uv, pc);
767 return (fcc_uah * pc) / 100;
768}
769
770#define CC_RESOLUTION_N 542535
771#define CC_RESOLUTION_D 100000
772
773static s64 cc_to_uv(s64 cc)
774{
775 return div_s64(cc * CC_RESOLUTION_N, CC_RESOLUTION_D);
776}
777
778#define CC_READING_TICKS 56
779#define SLEEP_CLK_HZ 32764
780#define SECONDS_PER_HOUR 3600
781
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800782static s64 cc_uv_to_pvh(s64 cc_uv)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700783{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800784 /* Note that it is necessary need to multiply by 1000000 to convert
785 * from uvh to pvh here.
786 * However, the maximum Coulomb Counter value is 2^35, which can cause
787 * an over flow.
788 * Multiply by 100000 first to perserve as much precision as possible
789 * then multiply by 10 after doing the division in order to avoid
790 * overflow on the maximum Coulomb Counter value.
791 */
792 return div_s64(cc_uv * CC_READING_TICKS * 100000,
793 SLEEP_CLK_HZ * SECONDS_PER_HOUR) * 10;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700794}
795
796/**
797 * calculate_cc-
798 * @chip: the bms chip pointer
799 * @cc: the cc reading from bms h/w
800 * @val: return value
801 * @coulomb_counter: adjusted coulomb counter for 100%
802 *
803 * RETURNS: in val pointer coulomb counter based charger in uAh
804 * (micro Amp hour)
805 */
806static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
807{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800808 int64_t cc_voltage_uv, cc_pvh, cc_uah;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700809 struct qpnp_iadc_calib calibration;
810
811 qpnp_iadc_get_gain_and_offset(&calibration);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -0800812 pr_debug("cc = %lld\n", cc);
813 cc_voltage_uv = cc_to_uv(cc);
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800814 cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
815 calibration.gain_raw
816 - calibration.offset_raw);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700817 pr_debug("cc_voltage_uv = %lld uv\n", cc_voltage_uv);
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800818 cc_pvh = cc_uv_to_pvh(cc_voltage_uv);
819 pr_debug("cc_pvh = %lld pvh\n", cc_pvh);
820 cc_uah = div_s64(cc_pvh, chip->r_sense_uohm);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700821 /* cc_raw had 4 bits of extra precision.
822 By now it should be within 32 bit range */
823 return (int)cc_uah;
824}
825
826static int get_rbatt(struct qpnp_bms_chip *chip,
827 int soc_rbatt_mohm, int batt_temp)
828{
829 int rbatt_mohm, scalefactor;
830
831 rbatt_mohm = chip->default_rbatt_mohm;
832 pr_debug("rbatt before scaling = %d\n", rbatt_mohm);
833 if (chip->rbatt_sf_lut == NULL) {
834 pr_debug("RBATT = %d\n", rbatt_mohm);
835 return rbatt_mohm;
836 }
837 /* Convert the batt_temp to DegC from deciDegC */
838 batt_temp = batt_temp / 10;
839 scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
840 batt_temp, soc_rbatt_mohm);
841 pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
842 scalefactor, batt_temp, soc_rbatt_mohm);
843 rbatt_mohm = (rbatt_mohm * scalefactor) / 100;
844
845 rbatt_mohm += chip->r_conn_mohm;
846 pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
847 chip->r_conn_mohm, rbatt_mohm);
Xiaozhe Shi1a10aff2013-04-01 15:40:05 -0700848 rbatt_mohm += chip->rbatt_capacitive_mohm;
849 pr_debug("adding rbatt_capacitive_mohm = %d rbatt = %d\n",
850 chip->rbatt_capacitive_mohm, rbatt_mohm);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700851
852 pr_debug("RBATT = %d\n", rbatt_mohm);
853 return rbatt_mohm;
854}
855
Xiaozhe Shi06b67cc2013-03-29 12:07:40 -0700856#define IAVG_MINIMAL_TIME 2
Xiaozhe Shie118c692012-09-24 15:17:43 -0700857static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800858 int *iavg_ua, int delta_time_s)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700859{
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800860 int delta_cc_uah = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700861
Xiaozhe Shi06b67cc2013-03-29 12:07:40 -0700862 /*
863 * use the battery current if called too quickly
864 */
865 if (delta_time_s < IAVG_MINIMAL_TIME
866 || chip->last_cc_uah == INT_MIN) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700867 get_battery_current(chip, iavg_ua);
868 goto out;
869 }
870
Xiaozhe Shie118c692012-09-24 15:17:43 -0700871 delta_cc_uah = cc_uah - chip->last_cc_uah;
872
873 *iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
874
Xiaozhe Shie118c692012-09-24 15:17:43 -0700875out:
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800876 pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700877
878 /* remember cc_uah */
879 chip->last_cc_uah = cc_uah;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700880}
881
882static int calculate_termination_uuc(struct qpnp_bms_chip *chip,
883 struct soc_params *params,
884 int batt_temp, int uuc_iavg_ma,
885 int *ret_pc_unusable)
886{
887 int unusable_uv, pc_unusable, uuc_uah;
888 int i = 0;
889 int ocv_mv;
890 int batt_temp_degc = batt_temp / 10;
891 int rbatt_mohm;
892 int delta_uv;
893 int prev_delta_uv = 0;
894 int prev_rbatt_mohm = 0;
895 int uuc_rbatt_mohm;
896
897 for (i = 0; i <= 100; i++) {
898 ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
899 batt_temp_degc, i);
900 rbatt_mohm = get_rbatt(chip, i, batt_temp);
901 unusable_uv = (rbatt_mohm * uuc_iavg_ma)
902 + (chip->v_cutoff_uv);
903 delta_uv = ocv_mv * 1000 - unusable_uv;
904
905 pr_debug("soc = %d ocv = %d rbat = %d u_uv = %d delta_v = %d\n",
906 i, ocv_mv, rbatt_mohm, unusable_uv, delta_uv);
907
908 if (delta_uv > 0)
909 break;
910
911 prev_delta_uv = delta_uv;
912 prev_rbatt_mohm = rbatt_mohm;
913 }
914
915 uuc_rbatt_mohm = linear_interpolate(rbatt_mohm, delta_uv,
916 prev_rbatt_mohm, prev_delta_uv,
917 0);
918
919 unusable_uv = (uuc_rbatt_mohm * uuc_iavg_ma) + (chip->v_cutoff_uv);
920
921 pc_unusable = calculate_pc(chip, unusable_uv, batt_temp);
922 uuc_uah = (params->fcc_uah * pc_unusable) / 100;
923 pr_debug("For uuc_iavg_ma = %d, unusable_rbatt = %d unusable_uv = %d unusable_pc = %d uuc = %d\n",
924 uuc_iavg_ma,
925 uuc_rbatt_mohm, unusable_uv,
926 pc_unusable, uuc_uah);
927 *ret_pc_unusable = pc_unusable;
928 return uuc_uah;
929}
930
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800931#define TIME_PER_PERCENT_UUC 60
Xiaozhe Shie118c692012-09-24 15:17:43 -0700932static int adjust_uuc(struct qpnp_bms_chip *chip,
933 struct soc_params *params,
934 int new_pc_unusable,
935 int new_uuc_uah,
936 int batt_temp)
937{
938 int new_unusable_mv, new_iavg_ma;
939 int batt_temp_degc = batt_temp / 10;
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800940 int max_percent_change;
941
942 max_percent_change = max(params->delta_time_s
943 / TIME_PER_PERCENT_UUC, 1);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700944
945 if (chip->prev_pc_unusable == -EINVAL
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800946 || abs(chip->prev_pc_unusable - new_pc_unusable)
947 <= max_percent_change) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700948 chip->prev_pc_unusable = new_pc_unusable;
949 return new_uuc_uah;
950 }
951
952 /* the uuc is trying to change more than 1% restrict it */
953 if (new_pc_unusable > chip->prev_pc_unusable)
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800954 chip->prev_pc_unusable += max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700955 else
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800956 chip->prev_pc_unusable -= max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700957
958 new_uuc_uah = (params->fcc_uah * chip->prev_pc_unusable) / 100;
959
960 /* also find update the iavg_ma accordingly */
961 new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
962 batt_temp_degc, chip->prev_pc_unusable);
963 if (new_unusable_mv < chip->v_cutoff_uv/1000)
964 new_unusable_mv = chip->v_cutoff_uv/1000;
965
966 new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800967 / params->rbatt_mohm;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700968 if (new_iavg_ma == 0)
969 new_iavg_ma = 1;
970 chip->prev_uuc_iavg_ma = new_iavg_ma;
971 pr_debug("Restricting UUC to %d (%d%%) unusable_mv = %d iavg_ma = %d\n",
972 new_uuc_uah, chip->prev_pc_unusable,
973 new_unusable_mv, new_iavg_ma);
974
975 return new_uuc_uah;
976}
977
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800978#define MIN_IAVG_MA 250
Xiaozhe Shie118c692012-09-24 15:17:43 -0700979#define MIN_SECONDS_FOR_VALID_SAMPLE 20
980static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
981 struct soc_params *params,
982 int batt_temp)
983{
984 int uuc_uah_iavg;
985 int i;
986 int uuc_iavg_ma = params->iavg_ua / 1000;
987 int pc_unusable;
988
989 /*
990 * if called first time, fill all the samples with
991 * the shutdown_iavg_ma
992 */
993 if (chip->first_time_calc_uuc && chip->shutdown_iavg_ma != 0) {
994 pr_debug("Using shutdown_iavg_ma = %d in all samples\n",
995 chip->shutdown_iavg_ma);
996 for (i = 0; i < IAVG_SAMPLES; i++)
997 chip->iavg_samples_ma[i] = chip->shutdown_iavg_ma;
998
999 chip->iavg_index = 0;
1000 chip->iavg_num_samples = IAVG_SAMPLES;
1001 }
1002
1003 /*
1004 * if charging use a nominal avg current to keep
1005 * a reasonable UUC while charging
1006 */
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -08001007 if (uuc_iavg_ma < MIN_IAVG_MA)
1008 uuc_iavg_ma = MIN_IAVG_MA;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001009 chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
1010 chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
1011 chip->iavg_num_samples++;
1012 if (chip->iavg_num_samples >= IAVG_SAMPLES)
1013 chip->iavg_num_samples = IAVG_SAMPLES;
1014
1015 /* now that this sample is added calcualte the average */
1016 uuc_iavg_ma = 0;
1017 if (chip->iavg_num_samples != 0) {
1018 for (i = 0; i < chip->iavg_num_samples; i++) {
1019 pr_debug("iavg_samples_ma[%d] = %d\n", i,
1020 chip->iavg_samples_ma[i]);
1021 uuc_iavg_ma += chip->iavg_samples_ma[i];
1022 }
1023
1024 uuc_iavg_ma = DIV_ROUND_CLOSEST(uuc_iavg_ma,
1025 chip->iavg_num_samples);
1026 }
1027
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001028 /*
1029 * if we're in bms reset mode, force uuc to be 3% of fcc
1030 */
1031 if (bms_reset)
1032 return (params->fcc_uah * 3) / 100;
1033
Xiaozhe Shi75e5efe2013-02-07 09:51:43 -08001034 uuc_uah_iavg = calculate_termination_uuc(chip, params, batt_temp,
1035 uuc_iavg_ma, &pc_unusable);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001036 pr_debug("uuc_iavg_ma = %d uuc with iavg = %d\n",
1037 uuc_iavg_ma, uuc_uah_iavg);
1038
1039 chip->prev_uuc_iavg_ma = uuc_iavg_ma;
1040 /* restrict the uuc such that it can increase only by one percent */
1041 uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
1042 uuc_uah_iavg, batt_temp);
1043
1044 chip->first_time_calc_uuc = 0;
1045 return uuc_uah_iavg;
1046}
1047
1048static void find_ocv_for_soc(struct qpnp_bms_chip *chip,
1049 struct soc_params *params,
1050 int batt_temp,
1051 int shutdown_soc,
1052 int *ret_ocv_uv)
1053{
1054 s64 ocv_charge_uah;
1055 int pc, new_pc;
1056 int batt_temp_degc = batt_temp / 10;
1057 int ocv_uv;
1058
1059 ocv_charge_uah = (s64)shutdown_soc
1060 * (params->fcc_uah - params->uuc_uah);
1061 ocv_charge_uah = div_s64(ocv_charge_uah, 100)
1062 + params->cc_uah + params->uuc_uah;
1063 pc = DIV_ROUND_CLOSEST((int)ocv_charge_uah * 100, params->fcc_uah);
1064 pc = clamp(pc, 0, 100);
1065
1066 ocv_uv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
1067
1068 pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
1069 shutdown_soc, params->fcc_uah,
1070 params->uuc_uah, (int)ocv_charge_uah,
1071 pc, ocv_uv);
1072 new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv_uv);
1073 pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv_uv);
1074
1075 while (abs(new_pc - pc) > 1) {
1076 int delta_mv = 5;
1077
1078 if (new_pc > pc)
1079 delta_mv = -1 * delta_mv;
1080
1081 ocv_uv = ocv_uv + delta_mv;
1082 new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
1083 batt_temp_degc, ocv_uv);
1084 pr_debug("test revlookup pc = %d for ocv = %d\n",
1085 new_pc, ocv_uv);
1086 }
1087
1088 *ret_ocv_uv = ocv_uv * 1000;
1089 params->ocv_charge_uah = (int)ocv_charge_uah;
1090}
1091
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001092static int get_current_time(unsigned long *now_tm_sec)
1093{
1094 struct rtc_time tm;
1095 struct rtc_device *rtc;
1096 int rc;
1097
1098 rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
1099 if (rtc == NULL) {
1100 pr_err("%s: unable to open rtc device (%s)\n",
1101 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
1102 rc = -EINVAL;
1103 goto close_time;
1104 }
1105
1106 rc = rtc_read_time(rtc, &tm);
1107 if (rc) {
1108 pr_err("Error reading rtc device (%s) : %d\n",
1109 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1110 goto close_time;
1111 }
1112
1113 rc = rtc_valid_tm(&tm);
1114 if (rc) {
1115 pr_err("Invalid RTC time (%s): %d\n",
1116 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1117 goto close_time;
1118 }
1119 rtc_tm_to_time(&tm, now_tm_sec);
1120
1121close_time:
1122 rtc_class_close(rtc);
1123 return rc;
1124}
1125
1126static int calculate_delta_time(struct qpnp_bms_chip *chip, int *delta_time_s)
1127{
1128 unsigned long now_tm_sec = 0;
1129
1130 /* default to delta time = 0 if anything fails */
1131 *delta_time_s = 0;
1132
1133 get_current_time(&now_tm_sec);
1134
1135 *delta_time_s = (now_tm_sec - chip->tm_sec);
1136 pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
1137 chip->tm_sec, now_tm_sec, *delta_time_s);
1138
1139 /* remember this time */
1140 chip->tm_sec = now_tm_sec;
1141 return 0;
1142}
1143
Xiaozhe Shie118c692012-09-24 15:17:43 -07001144static void calculate_soc_params(struct qpnp_bms_chip *chip,
1145 struct raw_soc_params *raw,
1146 struct soc_params *params,
1147 int batt_temp)
1148{
1149 int soc_rbatt;
1150
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001151 calculate_delta_time(chip, &params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001152 params->fcc_uah = calculate_fcc(chip, batt_temp);
1153 pr_debug("FCC = %uuAh batt_temp = %d\n", params->fcc_uah, batt_temp);
1154
1155 /* calculate remainging charge */
1156 params->ocv_charge_uah = calculate_ocv_charge(
1157 chip, raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001158 params->fcc_uah);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001159 pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
1160
1161 /* calculate cc micro_volt_hour */
1162 params->cc_uah = calculate_cc(chip, raw->cc);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -08001163 pr_debug("cc_uah = %duAh raw->cc = %llx\n", params->cc_uah, raw->cc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001164
1165 soc_rbatt = ((params->ocv_charge_uah - params->cc_uah) * 100)
1166 / params->fcc_uah;
1167 if (soc_rbatt < 0)
1168 soc_rbatt = 0;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001169 params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001170
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001171 calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
1172 params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001173
1174 params->uuc_uah = calculate_unusable_charge_uah(chip, params,
1175 batt_temp);
1176 pr_debug("UUC = %uuAh\n", params->uuc_uah);
1177}
1178
1179static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
1180{
1181 if (chip->shutdown_soc_invalid) {
1182 pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
1183 return 0;
1184 }
1185
1186 if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
1187 pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
1188 chip->shutdown_soc, soc,
1189 chip->shutdown_soc_valid_limit);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001190 chip->shutdown_soc_invalid = true;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001191 return 0;
1192 }
1193
1194 return 1;
1195}
1196
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001197static int bound_soc(int soc)
1198{
1199 soc = max(0, soc);
1200 soc = min(100, soc);
1201 return soc;
1202}
1203
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001204#define IBAT_TOL_MASK 0x0F
1205#define OCV_TOL_MASK 0xF0
1206#define IBAT_TOL_DEFAULT 0x03
1207#define IBAT_TOL_NOCHG 0x0F
1208#define OCV_TOL_DEFAULT 0x20
1209#define OCV_TOL_NO_OCV 0x00
1210static int stop_ocv_updates(struct qpnp_bms_chip *chip)
1211{
1212 pr_debug("stopping ocv updates\n");
1213 return qpnp_masked_write(chip, BMS1_TOL_CTL,
1214 OCV_TOL_MASK, OCV_TOL_NO_OCV);
1215}
1216
1217static int reset_bms_for_test(struct qpnp_bms_chip *chip)
1218{
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001219 int ibat_ua = 0, vbat_uv = 0, rc;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001220 int ocv_est_uv;
1221
1222 if (!chip) {
1223 pr_err("BMS driver has not been initialized yet!\n");
1224 return -EINVAL;
1225 }
1226
1227 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1228
Xiaozhe Shi1a10aff2013-04-01 15:40:05 -07001229 /*
1230 * Don't include rbatt and rbatt_capacitative since we expect this to
1231 * be used with a fake battery which does not have internal resistances
1232 */
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001233 ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
1234 pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
1235 chip->last_ocv_uv = ocv_est_uv;
1236 chip->last_soc = -EINVAL;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001237 chip->last_soc_invalid = true;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001238 reset_cc(chip);
1239 chip->last_cc_uah = INT_MIN;
1240 stop_ocv_updates(chip);
1241
1242 pr_debug("bms reset to ocv = %duv vbat_ua = %d ibat_ua = %d\n",
1243 chip->last_ocv_uv, vbat_uv, ibat_ua);
1244
1245 return rc;
1246}
1247
1248static int bms_reset_set(const char *val, const struct kernel_param *kp)
1249{
1250 int rc;
1251
1252 rc = param_set_bool(val, kp);
1253 if (rc) {
1254 pr_err("Unable to set bms_reset: %d\n", rc);
1255 return rc;
1256 }
1257
1258 if (*(bool *)kp->arg) {
1259 struct power_supply *bms_psy = power_supply_get_by_name("bms");
1260 struct qpnp_bms_chip *chip = container_of(bms_psy,
1261 struct qpnp_bms_chip, bms_psy);
1262
1263 rc = reset_bms_for_test(chip);
1264 if (rc) {
1265 pr_err("Unable to modify bms_reset: %d\n", rc);
1266 return rc;
1267 }
1268 }
1269 return 0;
1270}
1271
1272static struct kernel_param_ops bms_reset_ops = {
1273 .set = bms_reset_set,
1274 .get = param_get_bool,
1275};
1276
1277module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
1278
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001279static int charging_adjustments(struct qpnp_bms_chip *chip,
1280 struct soc_params *params, int soc,
1281 int vbat_uv, int ibat_ua, int batt_temp)
1282{
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001283 int chg_soc;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001284 int batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001285
1286 if (chip->soc_at_cv == -EINVAL) {
1287 /* In constant current charging return the calc soc */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001288 if (batt_terminal_uv <= chip->max_voltage_uv)
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001289 pr_debug("CC CHG SOC %d\n", soc);
1290
1291 /* Note the CC to CV point */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001292 if (batt_terminal_uv >= chip->max_voltage_uv) {
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001293 chip->soc_at_cv = soc;
1294 chip->prev_chg_soc = soc;
1295 chip->ibat_at_cv_ua = ibat_ua;
1296 pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
1297 ibat_ua, soc);
1298 }
1299 return soc;
1300 }
1301
1302 /*
1303 * battery is in CV phase - begin liner inerpolation of soc based on
1304 * battery charge current
1305 */
1306
1307 /*
1308 * if voltage lessened (possibly because of a system load)
1309 * keep reporting the prev chg soc
1310 */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001311 if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
1312 pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
1313 batt_terminal_uv,
1314 chip->max_voltage_uv, chip->prev_chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001315 return chip->prev_chg_soc;
1316 }
1317
1318 chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001319 100, -1 * chip->chg_term_ua,
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001320 ibat_ua);
Xiaozhe Shi78d0c532012-12-10 13:02:14 -08001321 chg_soc = bound_soc(chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001322
1323 /* always report a higher soc */
1324 if (chg_soc > chip->prev_chg_soc) {
1325 int new_ocv_uv;
1326
1327 chip->prev_chg_soc = chg_soc;
1328
1329 find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
1330 chip->last_ocv_uv = new_ocv_uv;
1331 pr_debug("CC CHG ADJ OCV = %d CHG SOC %d\n",
1332 new_ocv_uv,
1333 chip->prev_chg_soc);
1334 }
1335
1336 pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
1337 return chip->prev_chg_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001338}
1339
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001340static void very_low_voltage_check(struct qpnp_bms_chip *chip, int vbat_uv)
1341{
1342 /*
1343 * if battery is very low (v_cutoff voltage + 20mv) hold
1344 * a wakelock untill soc = 0%
1345 */
1346 if (vbat_uv <= chip->low_voltage_threshold
1347 && !chip->low_voltage_wake_lock_held) {
1348 pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
1349 wake_lock(&chip->low_voltage_wake_lock);
1350 chip->low_voltage_wake_lock_held = 1;
1351 } else if (vbat_uv > chip->low_voltage_threshold
1352 && chip->low_voltage_wake_lock_held) {
1353 pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
1354 chip->low_voltage_wake_lock_held = 0;
1355 wake_unlock(&chip->low_voltage_wake_lock);
1356 }
1357}
1358
Xiaozhe Shie118c692012-09-24 15:17:43 -07001359static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
1360 int soc, int batt_temp)
1361{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001362 int ibat_ua = 0, vbat_uv = 0;
1363 int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
1364 int delta_ocv_uv = 0;
1365 int n = 0;
1366 int rc_new_uah = 0;
1367 int pc_new = 0;
1368 int soc_new = 0;
1369 int slope = 0;
1370 int rc = 0;
1371 int delta_ocv_uv_limit = 0;
1372
1373 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1374 if (rc < 0) {
1375 pr_err("simultaneous vbat ibat failed err = %d\n", rc);
1376 goto out;
1377 }
1378
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001379 very_low_voltage_check(chip, vbat_uv);
1380
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001381 delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
1382
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001383 ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
1384
1385 chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
1386 / (params->rbatt_mohm);
1387
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001388 pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
1389 soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
1390 (s64)params->fcc_uah - params->uuc_uah);
1391 soc_est = bound_soc(soc_est);
1392
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001393 /* never adjust during bms reset mode */
1394 if (bms_reset) {
1395 pr_debug("bms reset mode, SOC adjustment skipped\n");
1396 goto out;
1397 }
1398
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001399 if (ibat_ua < 0 && !is_batfet_open(chip)) {
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001400 soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
1401 batt_temp);
1402 goto out;
1403 }
1404
1405 /*
1406 * do not adjust
1407 * if soc is same as what bms calculated
1408 * if soc_est is between 45 and 25, this is the flat portion of the
1409 * curve where soc_est is not so accurate. We generally don't want to
1410 * adjust when soc_est is inaccurate except for the cases when soc is
1411 * way far off (higher than 50 or lesser than 20).
1412 * Also don't adjust soc if it is above 90 becuase it might be pulled
1413 * low and cause a bad user experience
1414 */
1415 if (soc_est == soc
1416 || (is_between(45, chip->adjust_soc_low_threshold, soc_est)
1417 && is_between(50, chip->adjust_soc_low_threshold - 5, soc))
1418 || soc >= 90)
1419 goto out;
1420
1421 if (chip->last_soc_est == -EINVAL)
1422 chip->last_soc_est = soc;
1423
1424 n = min(200, max(1 , soc + soc_est + chip->last_soc_est));
1425 chip->last_soc_est = soc_est;
1426
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001427 pc = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001428 if (pc > 0) {
1429 pc_new = calculate_pc(chip,
1430 chip->last_ocv_uv - (++slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001431 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001432 while (pc_new == pc) {
1433 /* start taking 10mV steps */
1434 slope = slope + 10;
1435 pc_new = calculate_pc(chip,
1436 chip->last_ocv_uv - (slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001437 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001438 }
1439 } else {
1440 /*
1441 * pc is already at the lowest point,
1442 * assume 1 millivolt translates to 1% pc
1443 */
1444 pc = 1;
1445 pc_new = 0;
1446 slope = 1;
1447 }
1448
1449 delta_ocv_uv = div_s64((soc - soc_est) * (s64)slope * 1000,
1450 n * (pc - pc_new));
1451
1452 if (abs(delta_ocv_uv) > delta_ocv_uv_limit) {
1453 pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
1454 delta_ocv_uv_limit);
1455
1456 if (delta_ocv_uv > 0)
1457 delta_ocv_uv = delta_ocv_uv_limit;
1458 else
1459 delta_ocv_uv = -1 * delta_ocv_uv_limit;
1460 pr_debug("new delta ocv = %d\n", delta_ocv_uv);
1461 }
1462
1463 chip->last_ocv_uv -= delta_ocv_uv;
1464
1465 if (chip->last_ocv_uv >= chip->max_voltage_uv)
1466 chip->last_ocv_uv = chip->max_voltage_uv;
1467
1468 /* calculate the soc based on this new ocv */
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001469 pc_new = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001470 rc_new_uah = (params->fcc_uah * pc_new) / 100;
1471 soc_new = (rc_new_uah - params->cc_uah - params->uuc_uah)*100
1472 / (params->fcc_uah - params->uuc_uah);
1473 soc_new = bound_soc(soc_new);
1474
1475 /*
1476 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
1477 * soc = 0 should happen only when soc_est == 0
1478 */
1479 if (soc_new == 0 && soc_est != 0)
1480 soc_new = 1;
1481
1482 soc = soc_new;
1483
1484out:
1485 pr_debug("ibat_ua = %d, vbat_uv = %d, ocv_est_uv = %d, pc_est = %d, soc_est = %d, n = %d, delta_ocv_uv = %d, last_ocv_uv = %d, pc_new = %d, soc_new = %d, rbatt = %d, slope = %d\n",
1486 ibat_ua, vbat_uv, ocv_est_uv, pc_est,
1487 soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001488 pc_new, soc_new, params->rbatt_mohm, slope);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001489
Xiaozhe Shie118c692012-09-24 15:17:43 -07001490 return soc;
1491}
1492
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001493static int clamp_soc_based_on_voltage(struct qpnp_bms_chip *chip, int soc)
1494{
1495 int rc, vbat_uv;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001496
Xiaozhe Shi36458962013-02-06 16:19:57 -08001497 rc = get_battery_voltage(&vbat_uv);
1498 if (rc < 0) {
1499 pr_err("adc vbat failed err = %d\n", rc);
1500 return soc;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001501 }
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001502 if (soc == 0 && vbat_uv > chip->v_cutoff_uv) {
1503 pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
1504 vbat_uv, chip->v_cutoff_uv);
1505 return 1;
1506 } else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
1507 pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
1508 vbat_uv, chip->v_cutoff_uv);
1509 return 0;
1510 } else {
1511 pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
1512 soc, vbat_uv, chip->v_cutoff_uv);
1513 return soc;
1514 }
1515}
1516
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001517static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
1518 struct raw_soc_params *raw,
1519 int batt_temp)
1520{
Xiaozhe Shie118c692012-09-24 15:17:43 -07001521 int soc, new_ocv_uv;
1522 int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
1523 struct soc_params params;
1524
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001525 if (!chip->battery_present) {
Xiaozhe Shi026fa9b2013-03-22 17:00:50 -07001526 pr_debug("battery gone, reporting 100\n");
1527 new_calculated_soc = 100;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001528 goto done_calculating;
1529 }
Xiaozhe Shie118c692012-09-24 15:17:43 -07001530 calculate_soc_params(chip, raw, &params, batt_temp);
1531 /* calculate remaining usable charge */
1532 remaining_usable_charge_uah = params.ocv_charge_uah
1533 - params.cc_uah
1534 - params.uuc_uah;
1535
1536 pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
1537 if (params.fcc_uah - params.uuc_uah <= 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001538 pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001539 params.fcc_uah,
1540 params.uuc_uah);
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001541 new_calculated_soc = 0;
1542 goto done_calculating;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001543 }
1544
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001545 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1546 (params.fcc_uah - params.uuc_uah));
1547
Xiaozhe Shie118c692012-09-24 15:17:43 -07001548 if (chip->first_time_calc_soc && soc < 0) {
1549 /*
1550 * first time calcualtion and the pon ocv is too low resulting
1551 * in a bad soc. Adjust ocv to get 0 soc
1552 */
1553 pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
1554 find_ocv_for_soc(chip, &params, batt_temp, 0, &new_ocv_uv);
1555 chip->last_ocv_uv = new_ocv_uv;
1556
1557 remaining_usable_charge_uah = params.ocv_charge_uah
1558 - params.cc_uah
1559 - params.uuc_uah;
1560
1561 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1562 (params.fcc_uah
1563 - params.uuc_uah));
1564 pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
1565 soc, chip->last_ocv_uv);
1566 }
1567
1568 if (soc > 100)
1569 soc = 100;
1570
1571 if (soc < 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001572 pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001573 remaining_usable_charge_uah,
1574 params.ocv_charge_uah,
1575 params.cc_uah, params.uuc_uah);
1576
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001577 pr_debug("for bad rem_usb_chg last_ocv_uv = %d batt_temp = %d fcc = %d soc =%d\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001578 chip->last_ocv_uv, batt_temp,
1579 params.fcc_uah, soc);
1580 soc = 0;
1581 }
1582
1583 mutex_lock(&chip->soc_invalidation_mutex);
1584 shutdown_soc = chip->shutdown_soc;
1585
1586 if (chip->first_time_calc_soc && soc != shutdown_soc
1587 && is_shutdown_soc_within_limits(chip, soc)) {
1588 /*
1589 * soc for the first time - use shutdown soc
1590 * to adjust pon ocv since it is a small percent away from
1591 * the real soc
1592 */
1593 pr_debug("soc = %d before forcing shutdown_soc = %d\n",
1594 soc, shutdown_soc);
1595 find_ocv_for_soc(chip, &params, batt_temp,
1596 shutdown_soc, &new_ocv_uv);
1597 chip->pon_ocv_uv = chip->last_ocv_uv;
1598 chip->last_ocv_uv = new_ocv_uv;
1599
1600 remaining_usable_charge_uah = params.ocv_charge_uah
1601 - params.cc_uah
1602 - params.uuc_uah;
1603
1604 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1605 (params.fcc_uah
1606 - params.uuc_uah));
1607
1608 pr_debug("DONE for shutdown_soc = %d soc is %d, adjusted ocv to %duV\n",
1609 shutdown_soc, soc, chip->last_ocv_uv);
1610 }
1611 mutex_unlock(&chip->soc_invalidation_mutex);
1612
1613 pr_debug("SOC before adjustment = %d\n", soc);
1614 new_calculated_soc = adjust_soc(chip, &params, soc, batt_temp);
1615
Xiaozhe Shi445d2492013-03-27 18:10:18 -07001616 /* always clamp soc due to BMS hw/sw immaturities */
1617 new_calculated_soc = clamp_soc_based_on_voltage(chip,
1618 new_calculated_soc);
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001619
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001620done_calculating:
Xiaozhe Shie118c692012-09-24 15:17:43 -07001621 if (new_calculated_soc != chip->calculated_soc
1622 && chip->bms_psy.name != NULL) {
1623 power_supply_changed(&chip->bms_psy);
1624 pr_debug("power supply changed\n");
1625 }
1626
1627 chip->calculated_soc = new_calculated_soc;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001628 if (chip->last_soc_invalid) {
1629 chip->last_soc_invalid = false;
1630 chip->last_soc = -EINVAL;
1631 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001632 pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001633 chip->first_time_calc_soc = 0;
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001634 get_current_time(&chip->last_recalc_time);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001635 return chip->calculated_soc;
1636}
1637
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001638static int calculate_soc_from_voltage(struct qpnp_bms_chip *chip)
1639{
1640 int voltage_range_uv, voltage_remaining_uv, voltage_based_soc;
Xiaozhe Shi36458962013-02-06 16:19:57 -08001641 int rc, vbat_uv;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001642
Xiaozhe Shi36458962013-02-06 16:19:57 -08001643 rc = get_battery_voltage(&vbat_uv);
1644 if (rc < 0) {
1645 pr_err("adc vbat failed err = %d\n", rc);
1646 return rc;
1647 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001648 voltage_range_uv = chip->max_voltage_uv - chip->v_cutoff_uv;
1649 voltage_remaining_uv = vbat_uv - chip->v_cutoff_uv;
1650 voltage_based_soc = voltage_remaining_uv * 100 / voltage_range_uv;
1651
1652 voltage_based_soc = clamp(voltage_based_soc, 0, 100);
1653
1654 if (chip->prev_voltage_based_soc != voltage_based_soc
1655 && chip->bms_psy.name != NULL) {
1656 power_supply_changed(&chip->bms_psy);
1657 pr_debug("power supply changed\n");
1658 }
1659 chip->prev_voltage_based_soc = voltage_based_soc;
1660
1661 pr_debug("vbat used = %duv\n", vbat_uv);
1662 pr_debug("Calculated voltage based soc = %d\n", voltage_based_soc);
1663 return voltage_based_soc;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001664}
1665
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001666static int recalculate_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001667{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001668 int batt_temp, rc, soc;
1669 struct qpnp_vadc_result result;
1670 struct raw_soc_params raw;
1671
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001672 wake_lock(&chip->soc_wake_lock);
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001673 if (chip->use_voltage_soc) {
1674 soc = calculate_soc_from_voltage(chip);
1675 } else {
1676 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1677 if (rc) {
1678 pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
1679 LR_MUX1_BATT_THERM, rc);
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001680 soc = chip->calculated_soc;
1681 } else {
1682 pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
1683 result.physical,
1684 result.measurement);
1685 batt_temp = (int)result.physical;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001686
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001687 mutex_lock(&chip->last_ocv_uv_mutex);
1688 read_soc_params_raw(chip, &raw, batt_temp);
1689 soc = calculate_state_of_charge(chip, &raw, batt_temp);
1690 mutex_unlock(&chip->last_ocv_uv_mutex);
1691 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001692 }
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001693 wake_unlock(&chip->soc_wake_lock);
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001694 return soc;
1695}
1696
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001697static void recalculate_work(struct work_struct *work)
1698{
1699 struct qpnp_bms_chip *chip = container_of(work,
1700 struct qpnp_bms_chip,
1701 recalc_work);
1702
1703 recalculate_soc(chip);
1704}
1705
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001706static void calculate_soc_work(struct work_struct *work)
1707{
1708 struct qpnp_bms_chip *chip = container_of(work,
1709 struct qpnp_bms_chip,
1710 calculate_soc_delayed_work.work);
1711 int soc = recalculate_soc(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001712
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001713 if (soc < chip->low_soc_calc_threshold
1714 || chip->low_voltage_wake_lock_held)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001715 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1716 round_jiffies_relative(msecs_to_jiffies
1717 (chip->low_soc_calculate_soc_ms)));
1718 else
1719 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1720 round_jiffies_relative(msecs_to_jiffies
1721 (chip->calculate_soc_ms)));
1722}
1723
Xiaozhe Shie118c692012-09-24 15:17:43 -07001724static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
1725 int soc)
1726{
1727 u8 temp;
1728 int rc;
1729 int iavg_ma = chip->prev_uuc_iavg_ma;
1730
1731 if (iavg_ma > IAVG_START)
1732 temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
1733 else
1734 temp = 0;
1735
1736 rc = qpnp_write_wrapper(chip, &temp,
1737 chip->base + IAVG_STORAGE_REG, 1);
1738
Xiaozhe Shic7cbd052013-03-29 12:03:11 -07001739 temp = soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001740
1741 /* don't store soc if temperature is below 5degC */
1742 if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
1743 rc = qpnp_write_wrapper(chip, &temp,
1744 chip->base + SOC_STORAGE_REG, 1);
1745}
1746
1747#define SOC_CATCHUP_SEC_MAX 600
1748#define SOC_CATCHUP_SEC_PER_PERCENT 60
1749#define MAX_CATCHUP_SOC (SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
1750static int scale_soc_while_chg(struct qpnp_bms_chip *chip,
1751 int delta_time_us, int new_soc, int prev_soc)
1752{
1753 int chg_time_sec;
1754 int catch_up_sec;
1755 int scaled_soc;
1756 int numerator;
1757
1758 /*
1759 * The device must be charging for reporting a higher soc, if
1760 * not ignore this soc and continue reporting the prev_soc.
1761 * Also don't report a high value immediately slowly scale the
1762 * value from prev_soc to the new soc based on a charge time
1763 * weighted average
1764 */
1765
1766 /* if not charging, return last soc */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001767 if (!is_battery_charging(chip))
Xiaozhe Shie118c692012-09-24 15:17:43 -07001768 return prev_soc;
1769
1770 chg_time_sec = DIV_ROUND_UP(chip->charge_time_us, USEC_PER_SEC);
1771 catch_up_sec = DIV_ROUND_UP(chip->catch_up_time_us, USEC_PER_SEC);
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001772 if (catch_up_sec == 0)
1773 return new_soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001774 pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
1775
1776 /*
1777 * if charging for more than catch_up time, simply return
1778 * new soc
1779 */
1780 if (chg_time_sec > catch_up_sec)
1781 return new_soc;
1782
1783 numerator = (catch_up_sec - chg_time_sec) * prev_soc
1784 + chg_time_sec * new_soc;
1785 scaled_soc = numerator / catch_up_sec;
1786
1787 pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
1788 chg_time_sec, new_soc, prev_soc, scaled_soc);
1789
1790 return scaled_soc;
1791}
1792
1793/*
1794 * bms_fake_battery is set in setups where a battery emulator is used instead
1795 * of a real battery. This makes the bms driver report a different/fake value
1796 * regardless of the calculated state of charge.
1797 */
1798static int bms_fake_battery = -EINVAL;
1799module_param(bms_fake_battery, int, 0644);
1800
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001801static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
1802{
1803 pr_debug("Reported voltage based soc = %d\n",
1804 chip->prev_voltage_based_soc);
1805 return chip->prev_voltage_based_soc;
1806}
1807
1808static int report_cc_based_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001809{
1810 int soc;
1811 int delta_time_us;
1812 struct timespec now;
1813 struct qpnp_vadc_result result;
1814 int batt_temp;
1815 int rc;
1816
Xiaozhe Shie118c692012-09-24 15:17:43 -07001817 soc = chip->calculated_soc;
1818
1819 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1820
1821 if (rc) {
1822 pr_err("error reading adc channel = %d, rc = %d\n",
1823 LR_MUX1_BATT_THERM, rc);
1824 return rc;
1825 }
1826 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1827 result.measurement);
1828 batt_temp = (int)result.physical;
1829
1830 do_posix_clock_monotonic_gettime(&now);
1831 if (chip->t_soc_queried.tv_sec != 0) {
1832 delta_time_us
1833 = (now.tv_sec - chip->t_soc_queried.tv_sec) * USEC_PER_SEC
1834 + (now.tv_nsec - chip->t_soc_queried.tv_nsec) / 1000;
1835 } else {
1836 /* calculation for the first time */
1837 delta_time_us = 0;
1838 }
1839
1840 /*
1841 * account for charge time - limit it to SOC_CATCHUP_SEC to
1842 * avoid overflows when charging continues for extended periods
1843 */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001844 if (is_battery_charging(chip)) {
Xiaozhe Shie118c692012-09-24 15:17:43 -07001845 if (chip->charge_time_us == 0) {
1846 /*
1847 * calculating soc for the first time
1848 * after start of chg. Initialize catchup time
1849 */
1850 if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
1851 chip->catch_up_time_us =
1852 (soc - chip->last_soc)
1853 * SOC_CATCHUP_SEC_PER_PERCENT
1854 * USEC_PER_SEC;
1855 else
1856 chip->catch_up_time_us =
1857 SOC_CATCHUP_SEC_MAX * USEC_PER_SEC;
1858
1859 if (chip->catch_up_time_us < 0)
1860 chip->catch_up_time_us = 0;
1861 }
1862
1863 /* add charge time */
1864 if (chip->charge_time_us < SOC_CATCHUP_SEC_MAX * USEC_PER_SEC)
1865 chip->charge_time_us += delta_time_us;
1866
1867 /* end catchup if calculated soc and last soc are same */
1868 if (chip->last_soc == soc)
1869 chip->catch_up_time_us = 0;
1870 }
1871
1872 /* last_soc < soc ... scale and catch up */
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001873 if (chip->last_soc != -EINVAL && chip->last_soc < soc && soc != 100)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001874 soc = scale_soc_while_chg(chip, delta_time_us,
1875 soc, chip->last_soc);
1876
1877 pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
1878 chip->last_soc, chip->calculated_soc, soc);
1879 chip->last_soc = soc;
1880 backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
1881 pr_debug("Reported SOC = %d\n", chip->last_soc);
1882 chip->t_soc_queried = now;
1883
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001884 return soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001885}
1886
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001887static int report_state_of_charge(struct qpnp_bms_chip *chip)
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001888{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001889 if (bms_fake_battery != -EINVAL) {
1890 pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
1891 return bms_fake_battery;
1892 } else if (chip->use_voltage_soc)
1893 return report_voltage_based_soc(chip);
1894 else
1895 return report_cc_based_soc(chip);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001896}
1897
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001898/* Returns capacity as a SoC percentage between 0 and 100 */
1899static int get_prop_bms_capacity(struct qpnp_bms_chip *chip)
1900{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001901 return report_state_of_charge(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001902}
1903
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001904/* Returns estimated max current that the battery can supply in uA */
1905static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
1906{
1907 return chip->ibat_max_ua;
1908}
1909
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001910/* Returns instantaneous current in uA */
1911static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
1912{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001913 int rc, result_ua;
1914
1915 rc = get_battery_current(chip, &result_ua);
1916 if (rc) {
1917 pr_err("failed to get current: %d\n", rc);
1918 return rc;
1919 }
1920 return result_ua;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001921}
1922
1923/* Returns full charge design in uAh */
1924static int get_prop_bms_charge_full_design(struct qpnp_bms_chip *chip)
1925{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001926 return chip->fcc;
1927}
1928
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001929static int get_prop_bms_present(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001930{
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001931 return chip->battery_present;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001932}
1933
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001934static void set_prop_bms_present(struct qpnp_bms_chip *chip, int present)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001935{
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001936 if (chip->battery_present != present) {
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001937 chip->battery_present = present;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001938 if (present)
1939 chip->new_battery = true;
1940 /* a new battery was inserted or removed, so force a soc
1941 * recalculation to update the SoC */
1942 schedule_work(&chip->recalc_work);
1943 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001944}
1945
1946static void qpnp_bms_external_power_changed(struct power_supply *psy)
1947{
1948}
1949
1950static int qpnp_bms_power_get_property(struct power_supply *psy,
1951 enum power_supply_property psp,
1952 union power_supply_propval *val)
1953{
1954 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1955 bms_psy);
1956
1957 switch (psp) {
1958 case POWER_SUPPLY_PROP_CAPACITY:
1959 val->intval = get_prop_bms_capacity(chip);
1960 break;
1961 case POWER_SUPPLY_PROP_CURRENT_NOW:
1962 val->intval = get_prop_bms_current_now(chip);
1963 break;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001964 case POWER_SUPPLY_PROP_CURRENT_MAX:
1965 val->intval = get_prop_bms_current_max(chip);
1966 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001967 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1968 val->intval = get_prop_bms_charge_full_design(chip);
1969 break;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001970 case POWER_SUPPLY_PROP_PRESENT:
1971 val->intval = get_prop_bms_present(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001972 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001973 default:
1974 return -EINVAL;
1975 }
1976 return 0;
1977}
1978
1979static int qpnp_bms_power_set_property(struct power_supply *psy,
1980 enum power_supply_property psp,
1981 const union power_supply_propval *val)
1982{
1983 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1984 bms_psy);
1985
1986 switch (psp) {
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001987 case POWER_SUPPLY_PROP_PRESENT:
1988 set_prop_bms_present(chip, val->intval);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001989 break;
1990 default:
1991 return -EINVAL;
1992 }
1993 return 0;
1994}
1995
Xiaozhe Shibdf14742012-12-05 12:41:48 -08001996#define OCV_USE_LIMIT_EN BIT(7)
1997static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
1998 int low_voltage_threshold,
1999 int high_voltage_threshold)
2000{
2001 uint16_t low_voltage_raw, high_voltage_raw;
2002 int rc;
2003
2004 low_voltage_raw = convert_vbatt_uv_to_raw(chip,
2005 low_voltage_threshold);
2006 high_voltage_raw = convert_vbatt_uv_to_raw(chip,
2007 high_voltage_threshold);
2008 rc = qpnp_write_wrapper(chip, (u8 *)&low_voltage_raw,
2009 chip->base + BMS1_OCV_USE_LOW_LIMIT_THR0, 2);
2010 if (rc) {
2011 pr_err("Failed to set ocv low voltage threshold: %d\n", rc);
2012 return rc;
2013 }
2014 rc = qpnp_write_wrapper(chip, (u8 *)&high_voltage_raw,
2015 chip->base + BMS1_OCV_USE_HIGH_LIMIT_THR0, 2);
2016 if (rc) {
2017 pr_err("Failed to set ocv high voltage threshold: %d\n", rc);
2018 return rc;
2019 }
2020 rc = qpnp_masked_write(chip, BMS1_OCV_USE_LIMIT_CTL,
2021 OCV_USE_LIMIT_EN, OCV_USE_LIMIT_EN);
2022 if (rc) {
2023 pr_err("Failed to enabled ocv voltage thresholds: %d\n", rc);
2024 return rc;
2025 }
2026 pr_debug("ocv low threshold set to %d uv or 0x%x raw\n",
2027 low_voltage_threshold, low_voltage_raw);
2028 pr_debug("ocv high threshold set to %d uv or 0x%x raw\n",
2029 high_voltage_threshold, high_voltage_raw);
2030 return 0;
2031}
2032
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002033static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
2034{
2035 int rc;
2036 u8 temp;
2037
2038 if (chip->ignore_shutdown_soc) {
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002039 chip->shutdown_soc_invalid = true;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002040 chip->shutdown_soc = 0;
2041 chip->shutdown_iavg_ma = 0;
2042 } else {
2043 rc = qpnp_read_wrapper(chip, &temp,
2044 chip->base + IAVG_STORAGE_REG, 1);
2045 if (rc) {
2046 pr_err("failed to read addr = %d %d assuming %d\n",
2047 chip->base + IAVG_STORAGE_REG, rc,
2048 IAVG_START);
2049 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shif5f966d2013-02-19 14:23:11 -08002050 } else if (temp == IAVG_INVALID) {
2051 pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
2052 IAVG_START);
2053 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002054 } else {
2055 if (temp == 0) {
2056 chip->shutdown_iavg_ma = IAVG_START;
2057 } else {
2058 chip->shutdown_iavg_ma = IAVG_START
2059 + IAVG_STEP_SIZE_MA * (temp + 1);
2060 }
2061 }
2062
2063 rc = qpnp_read_wrapper(chip, &temp,
2064 chip->base + SOC_STORAGE_REG, 1);
2065 if (rc) {
2066 pr_err("failed to read addr = %d %d\n",
2067 chip->base + SOC_STORAGE_REG, rc);
2068 } else {
2069 chip->shutdown_soc = temp;
2070
Xiaozhe Shic7cbd052013-03-29 12:03:11 -07002071 if (chip->shutdown_soc == SOC_INVALID) {
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002072 pr_debug("No shutdown soc available\n");
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002073 chip->shutdown_soc_invalid = true;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002074 chip->shutdown_iavg_ma = 0;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002075 }
2076 }
2077 }
2078
2079 pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
2080 chip->shutdown_soc,
2081 chip->shutdown_iavg_ma,
2082 chip->shutdown_soc_invalid);
2083}
2084
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002085#define PALLADIUM_ID_MIN 0x7F40
2086#define PALLADIUM_ID_MAX 0x7F5A
2087#define DESAY_5200_ID_MIN 0x7F7F
2088#define DESAY_5200_ID_MAX 0x802F
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002089static int32_t read_battery_id(struct qpnp_bms_chip *chip)
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002090{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002091 int rc;
2092 struct qpnp_vadc_result result;
2093
2094 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2095 if (rc) {
2096 pr_err("error reading batt id channel = %d, rc = %d\n",
2097 LR_MUX2_BAT_ID, rc);
2098 return rc;
2099 }
2100 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
2101 result.measurement);
2102 pr_debug("raw_code = 0x%x\n", result.adc_code);
2103 return result.adc_code;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002104}
2105
2106static int set_battery_data(struct qpnp_bms_chip *chip)
2107{
2108 int64_t battery_id;
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002109 struct bms_battery_data *batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002110
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002111 if (chip->batt_type == BATT_DESAY) {
2112 batt_data = &desay_5200_data;
2113 } else if (chip->batt_type == BATT_PALLADIUM) {
2114 batt_data = &palladium_1500_data;
2115 } else if (chip->batt_type == BATT_OEM) {
2116 batt_data = &oem_batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002117 } else {
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002118 battery_id = read_battery_id(chip);
2119 if (battery_id < 0) {
2120 pr_err("cannot read battery id err = %lld\n",
2121 battery_id);
2122 return battery_id;
2123 }
2124
2125 if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
2126 battery_id)) {
2127 batt_data = &palladium_1500_data;
2128 } else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
2129 battery_id)) {
2130 batt_data = &desay_5200_data;
2131 } else {
2132 pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
2133 battery_id);
2134 batt_data = &palladium_1500_data;
2135 }
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002136 }
2137
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002138 chip->fcc = batt_data->fcc;
2139 chip->fcc_temp_lut = batt_data->fcc_temp_lut;
2140 chip->fcc_sf_lut = batt_data->fcc_sf_lut;
2141 chip->pc_temp_ocv_lut = batt_data->pc_temp_ocv_lut;
2142 chip->pc_sf_lut = batt_data->pc_sf_lut;
2143 chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
2144 chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
Xiaozhe Shi1a10aff2013-04-01 15:40:05 -07002145 chip->rbatt_capacitive_mohm = batt_data->rbatt_capacitive_mohm;
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002146
2147 if (chip->pc_temp_ocv_lut == NULL) {
2148 pr_err("temp ocv lut table is NULL\n");
2149 return -EINVAL;
2150 }
2151 return 0;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002152}
2153
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002154#define SPMI_PROP_READ(chip_prop, qpnp_spmi_property, retval) \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002155do { \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002156 retval = of_property_read_u32(chip->spmi->dev.of_node, \
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002157 "qcom," qpnp_spmi_property, \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002158 &chip->chip_prop); \
2159 if (retval) { \
2160 pr_err("Error reading " #qpnp_spmi_property \
2161 " property %d\n", rc); \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002162 return -EINVAL; \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002163 } \
2164} while (0)
2165
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002166static inline int bms_read_properties(struct qpnp_bms_chip *chip)
2167{
2168 int rc;
2169
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002170 SPMI_PROP_READ(r_sense_uohm, "r-sense-uohm", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002171 SPMI_PROP_READ(v_cutoff_uv, "v-cutoff-uv", rc);
2172 SPMI_PROP_READ(max_voltage_uv, "max-voltage-uv", rc);
2173 SPMI_PROP_READ(r_conn_mohm, "r-conn-mohm", rc);
2174 SPMI_PROP_READ(chg_term_ua, "chg-term-ua", rc);
2175 SPMI_PROP_READ(shutdown_soc_valid_limit,
2176 "shutdown-soc-valid-limit", rc);
2177 SPMI_PROP_READ(adjust_soc_high_threshold,
2178 "adjust-soc-high-threshold", rc);
2179 SPMI_PROP_READ(adjust_soc_low_threshold,
2180 "adjust-soc-low-threshold", rc);
2181 SPMI_PROP_READ(batt_type, "batt-type", rc);
2182 SPMI_PROP_READ(low_soc_calc_threshold,
2183 "low-soc-calculate-soc-threshold", rc);
2184 SPMI_PROP_READ(low_soc_calculate_soc_ms,
2185 "low-soc-calculate-soc-ms", rc);
2186 SPMI_PROP_READ(calculate_soc_ms, "calculate-soc-ms", rc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002187 chip->use_external_rsense = of_property_read_bool(
2188 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002189 "qcom,use-external-rsense");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002190 chip->ignore_shutdown_soc = of_property_read_bool(
2191 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002192 "qcom,ignore-shutdown-soc");
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002193 chip->use_voltage_soc = of_property_read_bool(chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002194 "qcom,use-voltage-soc");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002195 chip->use_ocv_thresholds = of_property_read_bool(
2196 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002197 "qcom,use-ocv-thresholds");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002198 SPMI_PROP_READ(ocv_high_threshold_uv,
2199 "ocv-voltage-high-threshold-uv", rc);
2200 SPMI_PROP_READ(ocv_low_threshold_uv,
2201 "ocv-voltage-low-threshold-uv", rc);
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002202 SPMI_PROP_READ(low_voltage_threshold, "low-voltage-threshold", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002203
2204 if (chip->adjust_soc_low_threshold >= 45)
2205 chip->adjust_soc_low_threshold = 45;
2206
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002207 pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
2208 chip->r_sense_uohm, chip->v_cutoff_uv,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002209 chip->max_voltage_uv);
2210 pr_debug("r_conn:%d, shutdown_soc: %d, adjust_soc_low:%d\n",
2211 chip->r_conn_mohm, chip->shutdown_soc_valid_limit,
2212 chip->adjust_soc_low_threshold);
2213 pr_debug("adjust_soc_high:%d, chg_term_ua:%d, batt_type:%d\n",
2214 chip->adjust_soc_high_threshold, chip->chg_term_ua,
2215 chip->batt_type);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08002216 pr_debug("ignore_shutdown_soc:%d, use_voltage_soc:%d\n",
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002217 chip->ignore_shutdown_soc, chip->use_voltage_soc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002218 pr_debug("use external rsense: %d\n", chip->use_external_rsense);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002219 return 0;
2220}
2221
2222static inline void bms_initialize_constants(struct qpnp_bms_chip *chip)
2223{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002224 chip->prev_pc_unusable = -EINVAL;
2225 chip->soc_at_cv = -EINVAL;
2226 chip->calculated_soc = -EINVAL;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002227 chip->last_soc = -EINVAL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07002228 chip->last_soc_est = -EINVAL;
Xiaozhe Shif36d2862013-01-04 10:17:35 -08002229 chip->last_cc_uah = INT_MIN;
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -08002230 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
2231 chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002232 chip->first_time_calc_soc = 1;
2233 chip->first_time_calc_uuc = 1;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002234}
2235
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002236#define REG_OFFSET_PERP_TYPE 0x04
2237#define REG_OFFSET_PERP_SUBTYPE 0x05
2238#define BMS_BMS_TYPE 0xD
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002239#define BMS_BMS1_SUBTYPE 0x1
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002240#define BMS_IADC_TYPE 0x8
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002241#define BMS_IADC1_SUBTYPE 0x3
2242#define BMS_IADC2_SUBTYPE 0x5
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002243
2244static int register_spmi(struct qpnp_bms_chip *chip, struct spmi_device *spmi)
2245{
2246 struct spmi_resource *spmi_resource;
2247 struct resource *resource;
2248 int rc;
2249 u8 type, subtype;
2250
2251 chip->dev = &(spmi->dev);
2252 chip->spmi = spmi;
2253
2254 spmi_for_each_container_dev(spmi_resource, spmi) {
2255 if (!spmi_resource) {
2256 pr_err("qpnp_bms: spmi resource absent\n");
2257 return -ENXIO;
2258 }
2259
2260 resource = spmi_get_resource(spmi, spmi_resource,
2261 IORESOURCE_MEM, 0);
2262 if (!(resource && resource->start)) {
2263 pr_err("node %s IO resource absent!\n",
2264 spmi->dev.of_node->full_name);
2265 return -ENXIO;
2266 }
2267
2268 rc = qpnp_read_wrapper(chip, &type,
2269 resource->start + REG_OFFSET_PERP_TYPE, 1);
2270 if (rc) {
2271 pr_err("Peripheral type read failed rc=%d\n", rc);
2272 return rc;
2273 }
2274 rc = qpnp_read_wrapper(chip, &subtype,
2275 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2276 if (rc) {
2277 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2278 return rc;
2279 }
2280
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002281 if (type == BMS_BMS_TYPE && subtype == BMS_BMS1_SUBTYPE) {
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002282 chip->base = resource->start;
2283 } else if (type == BMS_IADC_TYPE
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002284 && (subtype == BMS_IADC1_SUBTYPE
2285 || subtype == BMS_IADC2_SUBTYPE)) {
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002286 chip->iadc_base = resource->start;
2287 } else {
2288 pr_err("Invalid peripheral start=0x%x type=0x%x, subtype=0x%x\n",
2289 resource->start, type, subtype);
2290 }
2291 }
2292
2293 if (chip->base == 0) {
2294 dev_err(&spmi->dev, "BMS peripheral was not registered\n");
2295 return -EINVAL;
2296 }
2297 if (chip->iadc_base == 0) {
2298 dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
2299 return -EINVAL;
2300 }
2301
2302 return 0;
2303}
2304
2305#define ADC_CH_SEL_MASK 0x7
2306static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
2307{
2308 u8 iadc_channel_select;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002309 int32_t rds_rsense_nohm;
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002310 int rc;
2311
2312 rc = qpnp_read_wrapper(chip, &iadc_channel_select,
2313 chip->iadc_base + IADC1_BMS_ADC_CH_SEL_CTL, 1);
2314 if (rc) {
2315 pr_err("Error reading bms_iadc channel register %d\n", rc);
2316 return rc;
2317 }
2318
2319 iadc_channel_select &= ADC_CH_SEL_MASK;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002320 if (iadc_channel_select != EXTERNAL_RSENSE
2321 && iadc_channel_select != INTERNAL_RSENSE) {
2322 pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
2323 iadc_channel_select);
2324 return -EINVAL;
2325 }
2326
2327 if (chip->use_external_rsense) {
2328 pr_debug("External rsense selected\n");
2329 if (iadc_channel_select == INTERNAL_RSENSE) {
2330 pr_debug("Internal rsense detected; Changing rsense to external\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002331 rc = qpnp_masked_write_iadc(chip,
2332 IADC1_BMS_ADC_CH_SEL_CTL,
2333 ADC_CH_SEL_MASK,
2334 EXTERNAL_RSENSE);
2335 if (rc) {
2336 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2337 IADC1_BMS_ADC_CH_SEL_CTL,
2338 EXTERNAL_RSENSE, rc);
2339 return rc;
2340 }
2341 reset_cc(chip);
2342 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002343 } else {
2344 pr_debug("Internal rsense selected\n");
2345 if (iadc_channel_select == EXTERNAL_RSENSE) {
2346 pr_debug("External rsense detected; Changing rsense to internal\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002347 rc = qpnp_masked_write_iadc(chip,
2348 IADC1_BMS_ADC_CH_SEL_CTL,
2349 ADC_CH_SEL_MASK,
2350 INTERNAL_RSENSE);
2351 if (rc) {
2352 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2353 IADC1_BMS_ADC_CH_SEL_CTL,
2354 INTERNAL_RSENSE, rc);
2355 return rc;
2356 }
2357 reset_cc(chip);
2358 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002359
2360 rc = qpnp_iadc_get_rsense(&rds_rsense_nohm);
2361 if (rc) {
2362 pr_err("Unable to read RDS resistance value from IADC; rc = %d\n",
2363 rc);
2364 return rc;
2365 }
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002366 chip->r_sense_uohm = rds_rsense_nohm/1000;
2367 pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
2368 rds_rsense_nohm, chip->r_sense_uohm);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002369 }
2370 return 0;
2371}
2372
2373static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002374{
2375 struct qpnp_bms_chip *chip;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002376 union power_supply_propval retval = {0,};
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002377 int rc, vbatt;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002378
2379 chip = kzalloc(sizeof *chip, GFP_KERNEL);
2380
2381 if (chip == NULL) {
2382 pr_err("kzalloc() failed.\n");
2383 return -ENOMEM;
2384 }
2385
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002386 rc = qpnp_vadc_is_ready();
2387 if (rc) {
2388 pr_info("vadc not ready: %d, deferring probe\n", rc);
2389 goto error_read;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002390 }
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002391
2392 rc = qpnp_iadc_is_ready();
2393 if (rc) {
2394 pr_info("iadc not ready: %d, deferring probe\n", rc);
2395 goto error_read;
2396 }
2397
2398 rc = register_spmi(chip, spmi);
2399 if (rc) {
2400 pr_err("error registering spmi resource %d\n", rc);
2401 goto error_resource;
2402 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002403
2404 rc = qpnp_read_wrapper(chip, &chip->revision1,
2405 chip->base + BMS1_REVISION1, 1);
2406 if (rc) {
2407 pr_err("error reading version register %d\n", rc);
2408 goto error_read;
2409 }
2410
2411 rc = qpnp_read_wrapper(chip, &chip->revision2,
2412 chip->base + BMS1_REVISION2, 1);
2413 if (rc) {
2414 pr_err("Error reading version register %d\n", rc);
2415 goto error_read;
2416 }
Xiaozhe Shia045a562012-11-28 16:55:39 -08002417 pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002418
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002419 rc = bms_read_properties(chip);
2420 if (rc) {
2421 pr_err("Unable to read all bms properties, rc = %d\n", rc);
2422 goto error_read;
2423 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002424
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002425 rc = read_iadc_channel_select(chip);
2426 if (rc) {
2427 pr_err("Unable to get iadc selected channel = %d\n", rc);
2428 goto error_read;
2429 }
2430
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002431 if (chip->use_ocv_thresholds) {
2432 rc = set_ocv_voltage_thresholds(chip,
2433 chip->ocv_low_threshold_uv,
2434 chip->ocv_high_threshold_uv);
2435 if (rc) {
2436 pr_err("Could not set ocv voltage thresholds: %d\n",
2437 rc);
2438 goto error_read;
2439 }
2440 }
2441
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002442 rc = set_battery_data(chip);
2443 if (rc) {
2444 pr_err("Bad battery data %d\n", rc);
2445 goto error_read;
2446 }
2447
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002448 bms_initialize_constants(chip);
2449
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002450 mutex_init(&chip->bms_output_lock);
2451 mutex_init(&chip->last_ocv_uv_mutex);
2452 mutex_init(&chip->soc_invalidation_mutex);
2453
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002454 wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
2455 "qpnp_soc_lock");
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002456 wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
2457 "qpnp_low_voltage_lock");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002458 INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
2459 calculate_soc_work);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002460 INIT_WORK(&chip->recalc_work, recalculate_work);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002461
2462 read_shutdown_soc_and_iavg(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002463
2464 dev_set_drvdata(&spmi->dev, chip);
2465 device_init_wakeup(&spmi->dev, 1);
2466
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002467 if (!chip->batt_psy)
2468 chip->batt_psy = power_supply_get_by_name("battery");
2469 if (chip->batt_psy) {
2470 chip->batt_psy->get_property(chip->batt_psy,
2471 POWER_SUPPLY_PROP_PRESENT, &retval);
2472 chip->battery_present = retval.intval;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002473 pr_debug("present = %d\n", chip->battery_present);
2474 } else {
2475 chip->battery_present = 1;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002476 }
2477
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002478 calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
2479
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002480 /* setup & register the battery power supply */
2481 chip->bms_psy.name = "bms";
2482 chip->bms_psy.type = POWER_SUPPLY_TYPE_BMS;
2483 chip->bms_psy.properties = msm_bms_power_props;
2484 chip->bms_psy.num_properties = ARRAY_SIZE(msm_bms_power_props);
2485 chip->bms_psy.get_property = qpnp_bms_power_get_property;
2486 chip->bms_psy.set_property = qpnp_bms_power_set_property;
2487 chip->bms_psy.external_power_changed =
2488 qpnp_bms_external_power_changed;
2489 chip->bms_psy.supplied_to = qpnp_bms_supplicants;
2490 chip->bms_psy.num_supplicants = ARRAY_SIZE(qpnp_bms_supplicants);
2491
2492 rc = power_supply_register(chip->dev, &chip->bms_psy);
2493
2494 if (rc < 0) {
2495 pr_err("power_supply_register bms failed rc = %d\n", rc);
2496 goto unregister_dc;
2497 }
2498
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002499 vbatt = 0;
Xiaozhe Shi36458962013-02-06 16:19:57 -08002500 rc = get_battery_voltage(&vbatt);
2501 if (rc) {
2502 pr_err("error reading vbat_sns adc channel = %d, rc = %d\n",
2503 VBAT_SNS, rc);
2504 goto unregister_dc;
2505 }
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002506
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002507 pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u\n",
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002508 get_prop_bms_capacity(chip),
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002509 vbatt, chip->last_ocv_uv, chip->r_sense_uohm);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002510 return 0;
2511
2512unregister_dc:
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002513 wake_lock_destroy(&chip->soc_wake_lock);
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002514 wake_lock_destroy(&chip->low_voltage_wake_lock);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002515 power_supply_unregister(&chip->bms_psy);
2516 dev_set_drvdata(&spmi->dev, NULL);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002517error_resource:
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002518error_read:
2519 kfree(chip);
2520 return rc;
2521}
2522
2523static int __devexit
2524qpnp_bms_remove(struct spmi_device *spmi)
2525{
2526 struct qpnp_bms_chip *chip = dev_get_drvdata(&spmi->dev);
2527
2528 dev_set_drvdata(&spmi->dev, NULL);
2529 kfree(chip);
2530 return 0;
2531}
2532
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002533static int bms_resume(struct device *dev)
2534{
2535 int rc;
2536 unsigned long soc_calc_period;
2537 unsigned long time_since_last_recalc;
2538 unsigned long tm_now_sec;
2539 struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
2540
2541 rc = get_current_time(&tm_now_sec);
2542 if (rc) {
2543 pr_err("Could not read current time: %d\n", rc);
2544 } else if (tm_now_sec > chip->last_recalc_time) {
2545 time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
2546 pr_debug("Time since last recalc: %lu\n",
2547 time_since_last_recalc);
2548 if (chip->calculated_soc < chip->low_soc_calc_threshold)
2549 soc_calc_period = chip->low_soc_calculate_soc_ms;
2550 else
2551 soc_calc_period = chip->calculate_soc_ms;
2552
2553 if (time_since_last_recalc >= soc_calc_period) {
2554 chip->last_recalc_time = tm_now_sec;
2555 recalculate_soc(chip);
2556 }
2557 }
2558 return 0;
2559}
2560
2561static const struct dev_pm_ops qpnp_bms_pm_ops = {
2562 .resume = bms_resume,
2563};
2564
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002565static struct spmi_driver qpnp_bms_driver = {
2566 .probe = qpnp_bms_probe,
2567 .remove = __devexit_p(qpnp_bms_remove),
2568 .driver = {
2569 .name = QPNP_BMS_DEV_NAME,
2570 .owner = THIS_MODULE,
2571 .of_match_table = qpnp_bms_match_table,
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002572 .pm = &qpnp_bms_pm_ops,
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002573 },
2574};
2575
2576static int __init qpnp_bms_init(void)
2577{
2578 pr_info("QPNP BMS INIT\n");
2579 return spmi_driver_register(&qpnp_bms_driver);
2580}
2581
2582static void __exit qpnp_bms_exit(void)
2583{
2584 pr_info("QPNP BMS EXIT\n");
2585 return spmi_driver_unregister(&qpnp_bms_driver);
2586}
2587
2588module_init(qpnp_bms_init);
2589module_exit(qpnp_bms_exit);
2590
2591MODULE_DESCRIPTION("QPNP BMS Driver");
2592MODULE_LICENSE("GPL v2");
2593MODULE_ALIAS("platform:" QPNP_BMS_DEV_NAME);