blob: a194c4927b6d883fc69ac35294407b5bfc62d99e [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 */
74#define BMS1_BMS_DATA_REG_0 0xB0
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070075#define IAVG_STORAGE_REG 0xB1
76#define SOC_STORAGE_REG 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 Shicd7e5302012-10-17 12:29:53 -070086#define SOC_ZERO 0xFF
87
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 Shicd7e5302012-10-17 12:29:53 -0700138
139 struct delayed_work calculate_soc_delayed_work;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800140 struct work_struct recalc_work;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700141
142 struct mutex bms_output_lock;
143 struct mutex last_ocv_uv_mutex;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700144 struct mutex soc_invalidation_mutex;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700145
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800146 bool use_external_rsense;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800147 bool use_ocv_thresholds;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800148
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700149 bool ignore_shutdown_soc;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800150 bool shutdown_soc_invalid;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700151 int shutdown_soc;
152 int shutdown_iavg_ma;
153
Xiaozhe Shi4be85782013-02-22 17:33:40 -0800154 struct wake_lock low_voltage_wake_lock;
155 bool low_voltage_wake_lock_held;
156 int low_voltage_threshold;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700157 int low_soc_calc_threshold;
158 int low_soc_calculate_soc_ms;
159 int calculate_soc_ms;
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -0800160 struct wake_lock soc_wake_lock;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700161
Xiaozhe Shie118c692012-09-24 15:17:43 -0700162 uint16_t ocv_reading_at_100;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700163 uint16_t prev_last_good_ocv_raw;
164 int last_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800165 int last_ocv_temp;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700166 int last_cc_uah;
167 unsigned long tm_sec;
168 bool first_time_calc_soc;
169 bool first_time_calc_uuc;
170 int pon_ocv_uv;
171
172 int iavg_samples_ma[IAVG_SAMPLES];
173 int iavg_index;
174 int iavg_num_samples;
175 struct timespec t_soc_queried;
176 int last_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700177 int last_soc_est;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700178
179 int charge_time_us;
180 int catch_up_time_us;
181 struct single_row_lut *adjusted_fcc_temp_lut;
182
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700183 unsigned int vadc_v0625;
184 unsigned int vadc_v1250;
185
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800186 int ibat_max_ua;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700187 int prev_iavg_ua;
188 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{
489 int rc;
490 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 }
497 chip->vadc_v0625 = result.physical;
498
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 }
504 chip->vadc_v1250 = result.physical;
505 pr_debug("vadc calib: 0625 = %d, 1250 = %d\n",
506 chip->vadc_v0625, chip->vadc_v1250);
507 return 0;
508}
509
Xiaozhe Shie118c692012-09-24 15:17:43 -0700510static void convert_and_store_ocv(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800511 struct raw_soc_params *raw,
512 int batt_temp)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700513{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700514 int rc;
515
516 pr_debug("prev_last_good_ocv_raw = %d, last_good_ocv_raw = %d\n",
517 chip->prev_last_good_ocv_raw,
518 raw->last_good_ocv_raw);
519 rc = calib_vadc(chip);
520 if (rc)
521 pr_err("Vadc reference voltage read failed, rc = %d\n", rc);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700522 chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
523 raw->last_good_ocv_uv = convert_vbatt_raw_to_uv(chip,
524 raw->last_good_ocv_raw);
525 chip->last_ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800526 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700527 pr_debug("last_good_ocv_uv = %d\n", raw->last_good_ocv_uv);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700528}
529
Xiaozhe Shia045a562012-11-28 16:55:39 -0800530#define CLEAR_CC BIT(7)
531#define CLEAR_SW_CC BIT(6)
532/**
533 * reset both cc and sw-cc.
534 * note: this should only be ever called from one thread
535 * or there may be a race condition where CC is never enabled
536 * again
537 */
538static void reset_cc(struct qpnp_bms_chip *chip)
539{
540 int rc;
541
542 pr_debug("resetting cc manually\n");
543 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
544 CLEAR_CC | CLEAR_SW_CC,
545 CLEAR_CC | CLEAR_SW_CC);
546 if (rc)
547 pr_err("cc reset failed: %d\n", rc);
548
549 /* wait for 100us for cc to reset */
550 udelay(100);
551
552 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
553 CLEAR_CC | CLEAR_SW_CC, 0);
554 if (rc)
555 pr_err("cc reenable failed: %d\n", rc);
556}
557
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800558static bool is_battery_charging(struct qpnp_bms_chip *chip)
559{
560 union power_supply_propval ret = {0,};
561
562 if (chip->batt_psy == NULL)
563 chip->batt_psy = power_supply_get_by_name("battery");
564 if (chip->batt_psy) {
565 /* if battery has been registered, use the status property */
566 chip->batt_psy->get_property(chip->batt_psy,
567 POWER_SUPPLY_PROP_STATUS, &ret);
568 return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
569 }
570
571 /* Default to false if the battery power supply is not registered. */
572 pr_debug("battery power supply is not registered\n");
573 return false;
574}
575
576static bool is_batfet_open(struct qpnp_bms_chip *chip)
577{
578 union power_supply_propval ret = {0,};
579
580 if (chip->batt_psy == NULL)
581 chip->batt_psy = power_supply_get_by_name("battery");
582 if (chip->batt_psy) {
583 /* if battery has been registered, use the status property */
584 chip->batt_psy->get_property(chip->batt_psy,
585 POWER_SUPPLY_PROP_STATUS, &ret);
586 return ret.intval == POWER_SUPPLY_STATUS_FULL;
587 }
588
589 /* Default to true if the battery power supply is not registered. */
590 pr_debug("battery power supply is not registered\n");
591 return true;
592}
593
594static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
595 int *ibat_ua, int *vbat_uv)
596{
597 struct qpnp_iadc_result i_result;
598 struct qpnp_vadc_result v_result;
599 enum qpnp_iadc_channels iadc_channel;
600 int rc;
601
602 iadc_channel = chip->use_external_rsense ?
603 EXTERNAL_RSENSE : INTERNAL_RSENSE;
604 rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
605 VBAT_SNS, &v_result);
606 if (rc) {
607 pr_err("vadc read failed with rc: %d\n", rc);
608 return rc;
609 }
610 /*
611 * reverse the current read by the iadc, since the bms uses
612 * flipped battery current polarity.
613 */
614 *ibat_ua = -1 * (int)i_result.result_ua;
615 *vbat_uv = (int)v_result.physical;
616
617 return 0;
618}
619
620static int estimate_ocv(struct qpnp_bms_chip *chip)
621{
622 int ibat_ua, vbat_uv, ocv_est_uv;
623 int rc;
624 int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm;
625
626 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
627 if (rc) {
628 pr_err("simultaneous failed rc = %d\n", rc);
629 return rc;
630 }
631
632 ocv_est_uv = vbat_uv + (ibat_ua * rbatt_mohm) / 1000;
633 pr_debug("estimated pon ocv = %d\n", ocv_est_uv);
634 return ocv_est_uv;
635}
636
637static void reset_for_new_battery(struct qpnp_bms_chip *chip, int batt_temp)
638{
639 chip->last_ocv_uv = estimate_ocv(chip);
640 chip->last_soc = -EINVAL;
641 chip->soc_at_cv = -EINVAL;
642 chip->shutdown_soc_invalid = true;
643 chip->shutdown_soc = 0;
644 chip->shutdown_iavg_ma = 0;
645 chip->prev_pc_unusable = -EINVAL;
646 reset_cc(chip);
647 chip->last_cc_uah = INT_MIN;
648 chip->last_ocv_temp = batt_temp;
649 chip->last_soc_invalid = true;
650}
651
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800652#define OCV_RAW_UNINITIALIZED 0xFFFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700653static int read_soc_params_raw(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800654 struct raw_soc_params *raw,
655 int batt_temp)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700656{
Xiaozhe Shie118c692012-09-24 15:17:43 -0700657 int rc;
658
659 mutex_lock(&chip->bms_output_lock);
Xiaozhe Shia045a562012-11-28 16:55:39 -0800660
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800661 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Xiaozhe Shia045a562012-11-28 16:55:39 -0800662 /* software workaround for BMS 1.0
663 * The coulomb counter does not reset upon PON, so reset it
664 * manually upon probe. */
665 if (chip->revision1 == 0 && chip->revision2 == 0)
666 reset_cc(chip);
667 }
668
Xiaozhe Shie118c692012-09-24 15:17:43 -0700669 lock_output_data(chip);
670
671 rc = qpnp_read_wrapper(chip, (u8 *)&raw->last_good_ocv_raw,
672 chip->base + BMS1_OCV_FOR_SOC_DATA0, 2);
673 if (rc) {
674 pr_err("Error reading ocv: rc = %d\n", rc);
675 return -ENXIO;
676 }
677
678 rc = read_cc_raw(chip, &raw->cc);
679 if (rc) {
680 pr_err("Failed to read raw cc data, rc = %d\n", rc);
681 return rc;
682 }
683
684 unlock_output_data(chip);
685 mutex_unlock(&chip->bms_output_lock);
686
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800687 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800688 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700689 pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800690 } else if (chip->new_battery) {
691 /* if a new battery was inserted, estimate the ocv */
692 reset_for_new_battery(chip, batt_temp);
693 raw->cc = 0;
694 raw->last_good_ocv_uv = chip->last_ocv_uv;
695 chip->new_battery = false;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700696 } else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800697 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700698 /* forget the old cc value upon ocv */
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800699 chip->last_cc_uah = INT_MIN;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700700 } else {
701 raw->last_good_ocv_uv = chip->last_ocv_uv;
702 }
703
704 /* fake a high OCV if done charging */
705 if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800706 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700707 } else {
708 /*
709 * force 100% ocv by selecting the highest voltage the
710 * battery could ever reach
711 */
712 raw->last_good_ocv_uv = chip->max_voltage_uv;
713 chip->last_ocv_uv = chip->max_voltage_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800714 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi1c63a892013-02-13 15:49:40 -0800715 reset_cc(chip);
716 raw->cc = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700717 }
718 pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
719 raw->last_good_ocv_raw, raw->last_good_ocv_uv);
720 pr_debug("cc_raw= 0x%llx\n", raw->cc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700721 return 0;
722}
723
Xiaozhe Shie118c692012-09-24 15:17:43 -0700724static int calculate_pc(struct qpnp_bms_chip *chip, int ocv_uv,
725 int batt_temp)
726{
727 int pc;
728
729 pc = interpolate_pc(chip->pc_temp_ocv_lut,
730 batt_temp / 10, ocv_uv / 1000);
731 pr_debug("pc = %u %% for ocv = %d uv batt_temp = %d\n",
732 pc, ocv_uv, batt_temp);
733 /* Multiply the initial FCC value by the scale factor. */
734 return pc;
735}
736
737static int calculate_fcc(struct qpnp_bms_chip *chip, int batt_temp)
738{
739 int fcc_uah;
740
741 if (chip->adjusted_fcc_temp_lut == NULL) {
742 /* interpolate_fcc returns a mv value. */
743 fcc_uah = interpolate_fcc(chip->fcc_temp_lut,
744 batt_temp) * 1000;
745 pr_debug("fcc = %d uAh\n", fcc_uah);
746 return fcc_uah;
747 } else {
748 return 1000 * interpolate_fcc(chip->adjusted_fcc_temp_lut,
749 batt_temp);
750 }
751}
752
753/* calculate remaining charge at the time of ocv */
754static int calculate_ocv_charge(struct qpnp_bms_chip *chip,
755 struct raw_soc_params *raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800756 int fcc_uah)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700757{
758 int ocv_uv, pc;
759
760 ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800761 pc = calculate_pc(chip, ocv_uv, chip->last_ocv_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700762 pr_debug("ocv_uv = %d pc = %d\n", ocv_uv, pc);
763 return (fcc_uah * pc) / 100;
764}
765
766#define CC_RESOLUTION_N 542535
767#define CC_RESOLUTION_D 100000
768
769static s64 cc_to_uv(s64 cc)
770{
771 return div_s64(cc * CC_RESOLUTION_N, CC_RESOLUTION_D);
772}
773
774#define CC_READING_TICKS 56
775#define SLEEP_CLK_HZ 32764
776#define SECONDS_PER_HOUR 3600
777
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800778static s64 cc_uv_to_pvh(s64 cc_uv)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700779{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800780 /* Note that it is necessary need to multiply by 1000000 to convert
781 * from uvh to pvh here.
782 * However, the maximum Coulomb Counter value is 2^35, which can cause
783 * an over flow.
784 * Multiply by 100000 first to perserve as much precision as possible
785 * then multiply by 10 after doing the division in order to avoid
786 * overflow on the maximum Coulomb Counter value.
787 */
788 return div_s64(cc_uv * CC_READING_TICKS * 100000,
789 SLEEP_CLK_HZ * SECONDS_PER_HOUR) * 10;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700790}
791
792/**
793 * calculate_cc-
794 * @chip: the bms chip pointer
795 * @cc: the cc reading from bms h/w
796 * @val: return value
797 * @coulomb_counter: adjusted coulomb counter for 100%
798 *
799 * RETURNS: in val pointer coulomb counter based charger in uAh
800 * (micro Amp hour)
801 */
802static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
803{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800804 int64_t cc_voltage_uv, cc_pvh, cc_uah;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700805 struct qpnp_iadc_calib calibration;
806
807 qpnp_iadc_get_gain_and_offset(&calibration);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -0800808 pr_debug("cc = %lld\n", cc);
809 cc_voltage_uv = cc_to_uv(cc);
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800810 cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
811 calibration.gain_raw
812 - calibration.offset_raw);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700813 pr_debug("cc_voltage_uv = %lld uv\n", cc_voltage_uv);
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800814 cc_pvh = cc_uv_to_pvh(cc_voltage_uv);
815 pr_debug("cc_pvh = %lld pvh\n", cc_pvh);
816 cc_uah = div_s64(cc_pvh, chip->r_sense_uohm);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700817 /* cc_raw had 4 bits of extra precision.
818 By now it should be within 32 bit range */
819 return (int)cc_uah;
820}
821
822static int get_rbatt(struct qpnp_bms_chip *chip,
823 int soc_rbatt_mohm, int batt_temp)
824{
825 int rbatt_mohm, scalefactor;
826
827 rbatt_mohm = chip->default_rbatt_mohm;
828 pr_debug("rbatt before scaling = %d\n", rbatt_mohm);
829 if (chip->rbatt_sf_lut == NULL) {
830 pr_debug("RBATT = %d\n", rbatt_mohm);
831 return rbatt_mohm;
832 }
833 /* Convert the batt_temp to DegC from deciDegC */
834 batt_temp = batt_temp / 10;
835 scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
836 batt_temp, soc_rbatt_mohm);
837 pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
838 scalefactor, batt_temp, soc_rbatt_mohm);
839 rbatt_mohm = (rbatt_mohm * scalefactor) / 100;
840
841 rbatt_mohm += chip->r_conn_mohm;
842 pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
843 chip->r_conn_mohm, rbatt_mohm);
844
845 pr_debug("RBATT = %d\n", rbatt_mohm);
846 return rbatt_mohm;
847}
848
849static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800850 int *iavg_ua, int delta_time_s)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700851{
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800852 int delta_cc_uah = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700853
Xiaozhe Shie118c692012-09-24 15:17:43 -0700854 /* if anything fails report the previous iavg_ua */
855 *iavg_ua = chip->prev_iavg_ua;
856
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800857 if (chip->last_cc_uah == INT_MIN) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700858 get_battery_current(chip, iavg_ua);
859 goto out;
860 }
861
Xiaozhe Shie118c692012-09-24 15:17:43 -0700862 /* use the previous iavg if called within 15 seconds */
863 if (delta_time_s < 15) {
864 *iavg_ua = chip->prev_iavg_ua;
865 goto out;
866 }
867
868 delta_cc_uah = cc_uah - chip->last_cc_uah;
869
870 *iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
871
Xiaozhe Shie118c692012-09-24 15:17:43 -0700872out:
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800873 pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700874 /* remember the iavg */
875 chip->prev_iavg_ua = *iavg_ua;
876
877 /* remember cc_uah */
878 chip->last_cc_uah = cc_uah;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700879}
880
881static int calculate_termination_uuc(struct qpnp_bms_chip *chip,
882 struct soc_params *params,
883 int batt_temp, int uuc_iavg_ma,
884 int *ret_pc_unusable)
885{
886 int unusable_uv, pc_unusable, uuc_uah;
887 int i = 0;
888 int ocv_mv;
889 int batt_temp_degc = batt_temp / 10;
890 int rbatt_mohm;
891 int delta_uv;
892 int prev_delta_uv = 0;
893 int prev_rbatt_mohm = 0;
894 int uuc_rbatt_mohm;
895
896 for (i = 0; i <= 100; i++) {
897 ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
898 batt_temp_degc, i);
899 rbatt_mohm = get_rbatt(chip, i, batt_temp);
900 unusable_uv = (rbatt_mohm * uuc_iavg_ma)
901 + (chip->v_cutoff_uv);
902 delta_uv = ocv_mv * 1000 - unusable_uv;
903
904 pr_debug("soc = %d ocv = %d rbat = %d u_uv = %d delta_v = %d\n",
905 i, ocv_mv, rbatt_mohm, unusable_uv, delta_uv);
906
907 if (delta_uv > 0)
908 break;
909
910 prev_delta_uv = delta_uv;
911 prev_rbatt_mohm = rbatt_mohm;
912 }
913
914 uuc_rbatt_mohm = linear_interpolate(rbatt_mohm, delta_uv,
915 prev_rbatt_mohm, prev_delta_uv,
916 0);
917
918 unusable_uv = (uuc_rbatt_mohm * uuc_iavg_ma) + (chip->v_cutoff_uv);
919
920 pc_unusable = calculate_pc(chip, unusable_uv, batt_temp);
921 uuc_uah = (params->fcc_uah * pc_unusable) / 100;
922 pr_debug("For uuc_iavg_ma = %d, unusable_rbatt = %d unusable_uv = %d unusable_pc = %d uuc = %d\n",
923 uuc_iavg_ma,
924 uuc_rbatt_mohm, unusable_uv,
925 pc_unusable, uuc_uah);
926 *ret_pc_unusable = pc_unusable;
927 return uuc_uah;
928}
929
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800930#define TIME_PER_PERCENT_UUC 60
Xiaozhe Shie118c692012-09-24 15:17:43 -0700931static int adjust_uuc(struct qpnp_bms_chip *chip,
932 struct soc_params *params,
933 int new_pc_unusable,
934 int new_uuc_uah,
935 int batt_temp)
936{
937 int new_unusable_mv, new_iavg_ma;
938 int batt_temp_degc = batt_temp / 10;
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800939 int max_percent_change;
940
941 max_percent_change = max(params->delta_time_s
942 / TIME_PER_PERCENT_UUC, 1);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700943
944 if (chip->prev_pc_unusable == -EINVAL
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800945 || abs(chip->prev_pc_unusable - new_pc_unusable)
946 <= max_percent_change) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700947 chip->prev_pc_unusable = new_pc_unusable;
948 return new_uuc_uah;
949 }
950
951 /* the uuc is trying to change more than 1% restrict it */
952 if (new_pc_unusable > chip->prev_pc_unusable)
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800953 chip->prev_pc_unusable += max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700954 else
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800955 chip->prev_pc_unusable -= max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700956
957 new_uuc_uah = (params->fcc_uah * chip->prev_pc_unusable) / 100;
958
959 /* also find update the iavg_ma accordingly */
960 new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
961 batt_temp_degc, chip->prev_pc_unusable);
962 if (new_unusable_mv < chip->v_cutoff_uv/1000)
963 new_unusable_mv = chip->v_cutoff_uv/1000;
964
965 new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800966 / params->rbatt_mohm;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700967 if (new_iavg_ma == 0)
968 new_iavg_ma = 1;
969 chip->prev_uuc_iavg_ma = new_iavg_ma;
970 pr_debug("Restricting UUC to %d (%d%%) unusable_mv = %d iavg_ma = %d\n",
971 new_uuc_uah, chip->prev_pc_unusable,
972 new_unusable_mv, new_iavg_ma);
973
974 return new_uuc_uah;
975}
976
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800977#define MIN_IAVG_MA 250
Xiaozhe Shie118c692012-09-24 15:17:43 -0700978#define MIN_SECONDS_FOR_VALID_SAMPLE 20
979static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
980 struct soc_params *params,
981 int batt_temp)
982{
983 int uuc_uah_iavg;
984 int i;
985 int uuc_iavg_ma = params->iavg_ua / 1000;
986 int pc_unusable;
987
988 /*
989 * if called first time, fill all the samples with
990 * the shutdown_iavg_ma
991 */
992 if (chip->first_time_calc_uuc && chip->shutdown_iavg_ma != 0) {
993 pr_debug("Using shutdown_iavg_ma = %d in all samples\n",
994 chip->shutdown_iavg_ma);
995 for (i = 0; i < IAVG_SAMPLES; i++)
996 chip->iavg_samples_ma[i] = chip->shutdown_iavg_ma;
997
998 chip->iavg_index = 0;
999 chip->iavg_num_samples = IAVG_SAMPLES;
1000 }
1001
1002 /*
1003 * if charging use a nominal avg current to keep
1004 * a reasonable UUC while charging
1005 */
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -08001006 if (uuc_iavg_ma < MIN_IAVG_MA)
1007 uuc_iavg_ma = MIN_IAVG_MA;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001008 chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
1009 chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
1010 chip->iavg_num_samples++;
1011 if (chip->iavg_num_samples >= IAVG_SAMPLES)
1012 chip->iavg_num_samples = IAVG_SAMPLES;
1013
1014 /* now that this sample is added calcualte the average */
1015 uuc_iavg_ma = 0;
1016 if (chip->iavg_num_samples != 0) {
1017 for (i = 0; i < chip->iavg_num_samples; i++) {
1018 pr_debug("iavg_samples_ma[%d] = %d\n", i,
1019 chip->iavg_samples_ma[i]);
1020 uuc_iavg_ma += chip->iavg_samples_ma[i];
1021 }
1022
1023 uuc_iavg_ma = DIV_ROUND_CLOSEST(uuc_iavg_ma,
1024 chip->iavg_num_samples);
1025 }
1026
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001027 /*
1028 * if we're in bms reset mode, force uuc to be 3% of fcc
1029 */
1030 if (bms_reset)
1031 return (params->fcc_uah * 3) / 100;
1032
Xiaozhe Shi75e5efe2013-02-07 09:51:43 -08001033 uuc_uah_iavg = calculate_termination_uuc(chip, params, batt_temp,
1034 uuc_iavg_ma, &pc_unusable);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001035 pr_debug("uuc_iavg_ma = %d uuc with iavg = %d\n",
1036 uuc_iavg_ma, uuc_uah_iavg);
1037
1038 chip->prev_uuc_iavg_ma = uuc_iavg_ma;
1039 /* restrict the uuc such that it can increase only by one percent */
1040 uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
1041 uuc_uah_iavg, batt_temp);
1042
1043 chip->first_time_calc_uuc = 0;
1044 return uuc_uah_iavg;
1045}
1046
1047static void find_ocv_for_soc(struct qpnp_bms_chip *chip,
1048 struct soc_params *params,
1049 int batt_temp,
1050 int shutdown_soc,
1051 int *ret_ocv_uv)
1052{
1053 s64 ocv_charge_uah;
1054 int pc, new_pc;
1055 int batt_temp_degc = batt_temp / 10;
1056 int ocv_uv;
1057
1058 ocv_charge_uah = (s64)shutdown_soc
1059 * (params->fcc_uah - params->uuc_uah);
1060 ocv_charge_uah = div_s64(ocv_charge_uah, 100)
1061 + params->cc_uah + params->uuc_uah;
1062 pc = DIV_ROUND_CLOSEST((int)ocv_charge_uah * 100, params->fcc_uah);
1063 pc = clamp(pc, 0, 100);
1064
1065 ocv_uv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
1066
1067 pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
1068 shutdown_soc, params->fcc_uah,
1069 params->uuc_uah, (int)ocv_charge_uah,
1070 pc, ocv_uv);
1071 new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv_uv);
1072 pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv_uv);
1073
1074 while (abs(new_pc - pc) > 1) {
1075 int delta_mv = 5;
1076
1077 if (new_pc > pc)
1078 delta_mv = -1 * delta_mv;
1079
1080 ocv_uv = ocv_uv + delta_mv;
1081 new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
1082 batt_temp_degc, ocv_uv);
1083 pr_debug("test revlookup pc = %d for ocv = %d\n",
1084 new_pc, ocv_uv);
1085 }
1086
1087 *ret_ocv_uv = ocv_uv * 1000;
1088 params->ocv_charge_uah = (int)ocv_charge_uah;
1089}
1090
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001091static int get_current_time(unsigned long *now_tm_sec)
1092{
1093 struct rtc_time tm;
1094 struct rtc_device *rtc;
1095 int rc;
1096
1097 rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
1098 if (rtc == NULL) {
1099 pr_err("%s: unable to open rtc device (%s)\n",
1100 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
1101 rc = -EINVAL;
1102 goto close_time;
1103 }
1104
1105 rc = rtc_read_time(rtc, &tm);
1106 if (rc) {
1107 pr_err("Error reading rtc device (%s) : %d\n",
1108 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1109 goto close_time;
1110 }
1111
1112 rc = rtc_valid_tm(&tm);
1113 if (rc) {
1114 pr_err("Invalid RTC time (%s): %d\n",
1115 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1116 goto close_time;
1117 }
1118 rtc_tm_to_time(&tm, now_tm_sec);
1119
1120close_time:
1121 rtc_class_close(rtc);
1122 return rc;
1123}
1124
1125static int calculate_delta_time(struct qpnp_bms_chip *chip, int *delta_time_s)
1126{
1127 unsigned long now_tm_sec = 0;
1128
1129 /* default to delta time = 0 if anything fails */
1130 *delta_time_s = 0;
1131
1132 get_current_time(&now_tm_sec);
1133
1134 *delta_time_s = (now_tm_sec - chip->tm_sec);
1135 pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
1136 chip->tm_sec, now_tm_sec, *delta_time_s);
1137
1138 /* remember this time */
1139 chip->tm_sec = now_tm_sec;
1140 return 0;
1141}
1142
Xiaozhe Shie118c692012-09-24 15:17:43 -07001143static void calculate_soc_params(struct qpnp_bms_chip *chip,
1144 struct raw_soc_params *raw,
1145 struct soc_params *params,
1146 int batt_temp)
1147{
1148 int soc_rbatt;
1149
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001150 calculate_delta_time(chip, &params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001151 params->fcc_uah = calculate_fcc(chip, batt_temp);
1152 pr_debug("FCC = %uuAh batt_temp = %d\n", params->fcc_uah, batt_temp);
1153
1154 /* calculate remainging charge */
1155 params->ocv_charge_uah = calculate_ocv_charge(
1156 chip, raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001157 params->fcc_uah);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001158 pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
1159
1160 /* calculate cc micro_volt_hour */
1161 params->cc_uah = calculate_cc(chip, raw->cc);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -08001162 pr_debug("cc_uah = %duAh raw->cc = %llx\n", params->cc_uah, raw->cc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001163
1164 soc_rbatt = ((params->ocv_charge_uah - params->cc_uah) * 100)
1165 / params->fcc_uah;
1166 if (soc_rbatt < 0)
1167 soc_rbatt = 0;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001168 params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001169
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001170 calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
1171 params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001172
1173 params->uuc_uah = calculate_unusable_charge_uah(chip, params,
1174 batt_temp);
1175 pr_debug("UUC = %uuAh\n", params->uuc_uah);
1176}
1177
1178static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
1179{
1180 if (chip->shutdown_soc_invalid) {
1181 pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
1182 return 0;
1183 }
1184
1185 if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
1186 pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
1187 chip->shutdown_soc, soc,
1188 chip->shutdown_soc_valid_limit);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001189 chip->shutdown_soc_invalid = true;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001190 return 0;
1191 }
1192
1193 return 1;
1194}
1195
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001196static int bound_soc(int soc)
1197{
1198 soc = max(0, soc);
1199 soc = min(100, soc);
1200 return soc;
1201}
1202
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001203#define IBAT_TOL_MASK 0x0F
1204#define OCV_TOL_MASK 0xF0
1205#define IBAT_TOL_DEFAULT 0x03
1206#define IBAT_TOL_NOCHG 0x0F
1207#define OCV_TOL_DEFAULT 0x20
1208#define OCV_TOL_NO_OCV 0x00
1209static int stop_ocv_updates(struct qpnp_bms_chip *chip)
1210{
1211 pr_debug("stopping ocv updates\n");
1212 return qpnp_masked_write(chip, BMS1_TOL_CTL,
1213 OCV_TOL_MASK, OCV_TOL_NO_OCV);
1214}
1215
1216static int reset_bms_for_test(struct qpnp_bms_chip *chip)
1217{
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001218 int ibat_ua = 0, vbat_uv = 0, rc;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001219 int ocv_est_uv;
1220
1221 if (!chip) {
1222 pr_err("BMS driver has not been initialized yet!\n");
1223 return -EINVAL;
1224 }
1225
1226 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1227
1228 ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
1229 pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
1230 chip->last_ocv_uv = ocv_est_uv;
1231 chip->last_soc = -EINVAL;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001232 chip->last_soc_invalid = true;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001233 reset_cc(chip);
1234 chip->last_cc_uah = INT_MIN;
1235 stop_ocv_updates(chip);
1236
1237 pr_debug("bms reset to ocv = %duv vbat_ua = %d ibat_ua = %d\n",
1238 chip->last_ocv_uv, vbat_uv, ibat_ua);
1239
1240 return rc;
1241}
1242
1243static int bms_reset_set(const char *val, const struct kernel_param *kp)
1244{
1245 int rc;
1246
1247 rc = param_set_bool(val, kp);
1248 if (rc) {
1249 pr_err("Unable to set bms_reset: %d\n", rc);
1250 return rc;
1251 }
1252
1253 if (*(bool *)kp->arg) {
1254 struct power_supply *bms_psy = power_supply_get_by_name("bms");
1255 struct qpnp_bms_chip *chip = container_of(bms_psy,
1256 struct qpnp_bms_chip, bms_psy);
1257
1258 rc = reset_bms_for_test(chip);
1259 if (rc) {
1260 pr_err("Unable to modify bms_reset: %d\n", rc);
1261 return rc;
1262 }
1263 }
1264 return 0;
1265}
1266
1267static struct kernel_param_ops bms_reset_ops = {
1268 .set = bms_reset_set,
1269 .get = param_get_bool,
1270};
1271
1272module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
1273
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001274static int charging_adjustments(struct qpnp_bms_chip *chip,
1275 struct soc_params *params, int soc,
1276 int vbat_uv, int ibat_ua, int batt_temp)
1277{
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001278 int chg_soc;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001279 int batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001280
1281 if (chip->soc_at_cv == -EINVAL) {
1282 /* In constant current charging return the calc soc */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001283 if (batt_terminal_uv <= chip->max_voltage_uv)
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001284 pr_debug("CC CHG SOC %d\n", soc);
1285
1286 /* Note the CC to CV point */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001287 if (batt_terminal_uv >= chip->max_voltage_uv) {
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001288 chip->soc_at_cv = soc;
1289 chip->prev_chg_soc = soc;
1290 chip->ibat_at_cv_ua = ibat_ua;
1291 pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
1292 ibat_ua, soc);
1293 }
1294 return soc;
1295 }
1296
1297 /*
1298 * battery is in CV phase - begin liner inerpolation of soc based on
1299 * battery charge current
1300 */
1301
1302 /*
1303 * if voltage lessened (possibly because of a system load)
1304 * keep reporting the prev chg soc
1305 */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001306 if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
1307 pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
1308 batt_terminal_uv,
1309 chip->max_voltage_uv, chip->prev_chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001310 return chip->prev_chg_soc;
1311 }
1312
1313 chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001314 100, -1 * chip->chg_term_ua,
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001315 ibat_ua);
Xiaozhe Shi78d0c532012-12-10 13:02:14 -08001316 chg_soc = bound_soc(chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001317
1318 /* always report a higher soc */
1319 if (chg_soc > chip->prev_chg_soc) {
1320 int new_ocv_uv;
1321
1322 chip->prev_chg_soc = chg_soc;
1323
1324 find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
1325 chip->last_ocv_uv = new_ocv_uv;
1326 pr_debug("CC CHG ADJ OCV = %d CHG SOC %d\n",
1327 new_ocv_uv,
1328 chip->prev_chg_soc);
1329 }
1330
1331 pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
1332 return chip->prev_chg_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001333}
1334
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001335static void very_low_voltage_check(struct qpnp_bms_chip *chip, int vbat_uv)
1336{
1337 /*
1338 * if battery is very low (v_cutoff voltage + 20mv) hold
1339 * a wakelock untill soc = 0%
1340 */
1341 if (vbat_uv <= chip->low_voltage_threshold
1342 && !chip->low_voltage_wake_lock_held) {
1343 pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
1344 wake_lock(&chip->low_voltage_wake_lock);
1345 chip->low_voltage_wake_lock_held = 1;
1346 } else if (vbat_uv > chip->low_voltage_threshold
1347 && chip->low_voltage_wake_lock_held) {
1348 pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
1349 chip->low_voltage_wake_lock_held = 0;
1350 wake_unlock(&chip->low_voltage_wake_lock);
1351 }
1352}
1353
Xiaozhe Shie118c692012-09-24 15:17:43 -07001354static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
1355 int soc, int batt_temp)
1356{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001357 int ibat_ua = 0, vbat_uv = 0;
1358 int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
1359 int delta_ocv_uv = 0;
1360 int n = 0;
1361 int rc_new_uah = 0;
1362 int pc_new = 0;
1363 int soc_new = 0;
1364 int slope = 0;
1365 int rc = 0;
1366 int delta_ocv_uv_limit = 0;
1367
1368 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1369 if (rc < 0) {
1370 pr_err("simultaneous vbat ibat failed err = %d\n", rc);
1371 goto out;
1372 }
1373
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001374 very_low_voltage_check(chip, vbat_uv);
1375
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001376 delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
1377
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001378 ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
1379
1380 chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
1381 / (params->rbatt_mohm);
1382
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001383 pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
1384 soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
1385 (s64)params->fcc_uah - params->uuc_uah);
1386 soc_est = bound_soc(soc_est);
1387
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001388 /* never adjust during bms reset mode */
1389 if (bms_reset) {
1390 pr_debug("bms reset mode, SOC adjustment skipped\n");
1391 goto out;
1392 }
1393
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001394 if (ibat_ua < 0 && !is_batfet_open(chip)) {
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001395 soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
1396 batt_temp);
1397 goto out;
1398 }
1399
1400 /*
1401 * do not adjust
1402 * if soc is same as what bms calculated
1403 * if soc_est is between 45 and 25, this is the flat portion of the
1404 * curve where soc_est is not so accurate. We generally don't want to
1405 * adjust when soc_est is inaccurate except for the cases when soc is
1406 * way far off (higher than 50 or lesser than 20).
1407 * Also don't adjust soc if it is above 90 becuase it might be pulled
1408 * low and cause a bad user experience
1409 */
1410 if (soc_est == soc
1411 || (is_between(45, chip->adjust_soc_low_threshold, soc_est)
1412 && is_between(50, chip->adjust_soc_low_threshold - 5, soc))
1413 || soc >= 90)
1414 goto out;
1415
1416 if (chip->last_soc_est == -EINVAL)
1417 chip->last_soc_est = soc;
1418
1419 n = min(200, max(1 , soc + soc_est + chip->last_soc_est));
1420 chip->last_soc_est = soc_est;
1421
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001422 pc = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001423 if (pc > 0) {
1424 pc_new = calculate_pc(chip,
1425 chip->last_ocv_uv - (++slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001426 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001427 while (pc_new == pc) {
1428 /* start taking 10mV steps */
1429 slope = slope + 10;
1430 pc_new = calculate_pc(chip,
1431 chip->last_ocv_uv - (slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001432 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001433 }
1434 } else {
1435 /*
1436 * pc is already at the lowest point,
1437 * assume 1 millivolt translates to 1% pc
1438 */
1439 pc = 1;
1440 pc_new = 0;
1441 slope = 1;
1442 }
1443
1444 delta_ocv_uv = div_s64((soc - soc_est) * (s64)slope * 1000,
1445 n * (pc - pc_new));
1446
1447 if (abs(delta_ocv_uv) > delta_ocv_uv_limit) {
1448 pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
1449 delta_ocv_uv_limit);
1450
1451 if (delta_ocv_uv > 0)
1452 delta_ocv_uv = delta_ocv_uv_limit;
1453 else
1454 delta_ocv_uv = -1 * delta_ocv_uv_limit;
1455 pr_debug("new delta ocv = %d\n", delta_ocv_uv);
1456 }
1457
1458 chip->last_ocv_uv -= delta_ocv_uv;
1459
1460 if (chip->last_ocv_uv >= chip->max_voltage_uv)
1461 chip->last_ocv_uv = chip->max_voltage_uv;
1462
1463 /* calculate the soc based on this new ocv */
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001464 pc_new = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001465 rc_new_uah = (params->fcc_uah * pc_new) / 100;
1466 soc_new = (rc_new_uah - params->cc_uah - params->uuc_uah)*100
1467 / (params->fcc_uah - params->uuc_uah);
1468 soc_new = bound_soc(soc_new);
1469
1470 /*
1471 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
1472 * soc = 0 should happen only when soc_est == 0
1473 */
1474 if (soc_new == 0 && soc_est != 0)
1475 soc_new = 1;
1476
1477 soc = soc_new;
1478
1479out:
1480 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",
1481 ibat_ua, vbat_uv, ocv_est_uv, pc_est,
1482 soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001483 pc_new, soc_new, params->rbatt_mohm, slope);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001484
Xiaozhe Shie118c692012-09-24 15:17:43 -07001485 return soc;
1486}
1487
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001488static int clamp_soc_based_on_voltage(struct qpnp_bms_chip *chip, int soc)
1489{
1490 int rc, vbat_uv;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001491
Xiaozhe Shi36458962013-02-06 16:19:57 -08001492 rc = get_battery_voltage(&vbat_uv);
1493 if (rc < 0) {
1494 pr_err("adc vbat failed err = %d\n", rc);
1495 return soc;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001496 }
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001497 if (soc == 0 && vbat_uv > chip->v_cutoff_uv) {
1498 pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
1499 vbat_uv, chip->v_cutoff_uv);
1500 return 1;
1501 } else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
1502 pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
1503 vbat_uv, chip->v_cutoff_uv);
1504 return 0;
1505 } else {
1506 pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
1507 soc, vbat_uv, chip->v_cutoff_uv);
1508 return soc;
1509 }
1510}
1511
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001512static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
1513 struct raw_soc_params *raw,
1514 int batt_temp)
1515{
Xiaozhe Shie118c692012-09-24 15:17:43 -07001516 int soc, new_ocv_uv;
1517 int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
1518 struct soc_params params;
1519
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001520 if (!chip->battery_present) {
1521 pr_debug("battery gone, reporting 0\n");
1522 new_calculated_soc = 0;
1523 goto done_calculating;
1524 }
Xiaozhe Shie118c692012-09-24 15:17:43 -07001525 calculate_soc_params(chip, raw, &params, batt_temp);
1526 /* calculate remaining usable charge */
1527 remaining_usable_charge_uah = params.ocv_charge_uah
1528 - params.cc_uah
1529 - params.uuc_uah;
1530
1531 pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
1532 if (params.fcc_uah - params.uuc_uah <= 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001533 pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001534 params.fcc_uah,
1535 params.uuc_uah);
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001536 new_calculated_soc = 0;
1537 goto done_calculating;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001538 }
1539
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001540 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1541 (params.fcc_uah - params.uuc_uah));
1542
Xiaozhe Shie118c692012-09-24 15:17:43 -07001543 if (chip->first_time_calc_soc && soc < 0) {
1544 /*
1545 * first time calcualtion and the pon ocv is too low resulting
1546 * in a bad soc. Adjust ocv to get 0 soc
1547 */
1548 pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
1549 find_ocv_for_soc(chip, &params, batt_temp, 0, &new_ocv_uv);
1550 chip->last_ocv_uv = new_ocv_uv;
1551
1552 remaining_usable_charge_uah = params.ocv_charge_uah
1553 - params.cc_uah
1554 - params.uuc_uah;
1555
1556 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1557 (params.fcc_uah
1558 - params.uuc_uah));
1559 pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
1560 soc, chip->last_ocv_uv);
1561 }
1562
1563 if (soc > 100)
1564 soc = 100;
1565
1566 if (soc < 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001567 pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001568 remaining_usable_charge_uah,
1569 params.ocv_charge_uah,
1570 params.cc_uah, params.uuc_uah);
1571
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001572 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 -07001573 chip->last_ocv_uv, batt_temp,
1574 params.fcc_uah, soc);
1575 soc = 0;
1576 }
1577
1578 mutex_lock(&chip->soc_invalidation_mutex);
1579 shutdown_soc = chip->shutdown_soc;
1580
1581 if (chip->first_time_calc_soc && soc != shutdown_soc
1582 && is_shutdown_soc_within_limits(chip, soc)) {
1583 /*
1584 * soc for the first time - use shutdown soc
1585 * to adjust pon ocv since it is a small percent away from
1586 * the real soc
1587 */
1588 pr_debug("soc = %d before forcing shutdown_soc = %d\n",
1589 soc, shutdown_soc);
1590 find_ocv_for_soc(chip, &params, batt_temp,
1591 shutdown_soc, &new_ocv_uv);
1592 chip->pon_ocv_uv = chip->last_ocv_uv;
1593 chip->last_ocv_uv = new_ocv_uv;
1594
1595 remaining_usable_charge_uah = params.ocv_charge_uah
1596 - params.cc_uah
1597 - params.uuc_uah;
1598
1599 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1600 (params.fcc_uah
1601 - params.uuc_uah));
1602
1603 pr_debug("DONE for shutdown_soc = %d soc is %d, adjusted ocv to %duV\n",
1604 shutdown_soc, soc, chip->last_ocv_uv);
1605 }
1606 mutex_unlock(&chip->soc_invalidation_mutex);
1607
1608 pr_debug("SOC before adjustment = %d\n", soc);
1609 new_calculated_soc = adjust_soc(chip, &params, soc, batt_temp);
1610
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001611 /* clamp soc due to BMS HW inaccuracies in pm8941v2.0 */
1612 if (chip->revision1 == 0 && chip->revision2 == 0)
1613 new_calculated_soc = clamp_soc_based_on_voltage(chip,
1614 new_calculated_soc);
1615
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001616done_calculating:
Xiaozhe Shie118c692012-09-24 15:17:43 -07001617 if (new_calculated_soc != chip->calculated_soc
1618 && chip->bms_psy.name != NULL) {
1619 power_supply_changed(&chip->bms_psy);
1620 pr_debug("power supply changed\n");
1621 }
1622
1623 chip->calculated_soc = new_calculated_soc;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001624 if (chip->last_soc_invalid) {
1625 chip->last_soc_invalid = false;
1626 chip->last_soc = -EINVAL;
1627 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001628 pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001629 chip->first_time_calc_soc = 0;
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001630 get_current_time(&chip->last_recalc_time);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001631 return chip->calculated_soc;
1632}
1633
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001634static int calculate_soc_from_voltage(struct qpnp_bms_chip *chip)
1635{
1636 int voltage_range_uv, voltage_remaining_uv, voltage_based_soc;
Xiaozhe Shi36458962013-02-06 16:19:57 -08001637 int rc, vbat_uv;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001638
Xiaozhe Shi36458962013-02-06 16:19:57 -08001639 rc = get_battery_voltage(&vbat_uv);
1640 if (rc < 0) {
1641 pr_err("adc vbat failed err = %d\n", rc);
1642 return rc;
1643 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001644 voltage_range_uv = chip->max_voltage_uv - chip->v_cutoff_uv;
1645 voltage_remaining_uv = vbat_uv - chip->v_cutoff_uv;
1646 voltage_based_soc = voltage_remaining_uv * 100 / voltage_range_uv;
1647
1648 voltage_based_soc = clamp(voltage_based_soc, 0, 100);
1649
1650 if (chip->prev_voltage_based_soc != voltage_based_soc
1651 && chip->bms_psy.name != NULL) {
1652 power_supply_changed(&chip->bms_psy);
1653 pr_debug("power supply changed\n");
1654 }
1655 chip->prev_voltage_based_soc = voltage_based_soc;
1656
1657 pr_debug("vbat used = %duv\n", vbat_uv);
1658 pr_debug("Calculated voltage based soc = %d\n", voltage_based_soc);
1659 return voltage_based_soc;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001660}
1661
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001662static int recalculate_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001663{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001664 int batt_temp, rc, soc;
1665 struct qpnp_vadc_result result;
1666 struct raw_soc_params raw;
1667
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001668 wake_lock(&chip->soc_wake_lock);
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001669 if (chip->use_voltage_soc) {
1670 soc = calculate_soc_from_voltage(chip);
1671 } else {
1672 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1673 if (rc) {
1674 pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
1675 LR_MUX1_BATT_THERM, rc);
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001676 soc = chip->calculated_soc;
1677 } else {
1678 pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
1679 result.physical,
1680 result.measurement);
1681 batt_temp = (int)result.physical;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001682
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001683 mutex_lock(&chip->last_ocv_uv_mutex);
1684 read_soc_params_raw(chip, &raw, batt_temp);
1685 soc = calculate_state_of_charge(chip, &raw, batt_temp);
1686 mutex_unlock(&chip->last_ocv_uv_mutex);
1687 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001688 }
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001689 wake_unlock(&chip->soc_wake_lock);
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001690 return soc;
1691}
1692
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001693static void recalculate_work(struct work_struct *work)
1694{
1695 struct qpnp_bms_chip *chip = container_of(work,
1696 struct qpnp_bms_chip,
1697 recalc_work);
1698
1699 recalculate_soc(chip);
1700}
1701
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001702static void calculate_soc_work(struct work_struct *work)
1703{
1704 struct qpnp_bms_chip *chip = container_of(work,
1705 struct qpnp_bms_chip,
1706 calculate_soc_delayed_work.work);
1707 int soc = recalculate_soc(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001708
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001709 if (soc < chip->low_soc_calc_threshold
1710 || chip->low_voltage_wake_lock_held)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001711 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1712 round_jiffies_relative(msecs_to_jiffies
1713 (chip->low_soc_calculate_soc_ms)));
1714 else
1715 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1716 round_jiffies_relative(msecs_to_jiffies
1717 (chip->calculate_soc_ms)));
1718}
1719
Xiaozhe Shie118c692012-09-24 15:17:43 -07001720static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
1721 int soc)
1722{
1723 u8 temp;
1724 int rc;
1725 int iavg_ma = chip->prev_uuc_iavg_ma;
1726
1727 if (iavg_ma > IAVG_START)
1728 temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
1729 else
1730 temp = 0;
1731
1732 rc = qpnp_write_wrapper(chip, &temp,
1733 chip->base + IAVG_STORAGE_REG, 1);
1734
1735 if (soc == 0)
1736 temp = SOC_ZERO;
1737 else
1738 temp = soc;
1739
1740 /* don't store soc if temperature is below 5degC */
1741 if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
1742 rc = qpnp_write_wrapper(chip, &temp,
1743 chip->base + SOC_STORAGE_REG, 1);
1744}
1745
1746#define SOC_CATCHUP_SEC_MAX 600
1747#define SOC_CATCHUP_SEC_PER_PERCENT 60
1748#define MAX_CATCHUP_SOC (SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
1749static int scale_soc_while_chg(struct qpnp_bms_chip *chip,
1750 int delta_time_us, int new_soc, int prev_soc)
1751{
1752 int chg_time_sec;
1753 int catch_up_sec;
1754 int scaled_soc;
1755 int numerator;
1756
1757 /*
1758 * The device must be charging for reporting a higher soc, if
1759 * not ignore this soc and continue reporting the prev_soc.
1760 * Also don't report a high value immediately slowly scale the
1761 * value from prev_soc to the new soc based on a charge time
1762 * weighted average
1763 */
1764
1765 /* if not charging, return last soc */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001766 if (!is_battery_charging(chip))
Xiaozhe Shie118c692012-09-24 15:17:43 -07001767 return prev_soc;
1768
1769 chg_time_sec = DIV_ROUND_UP(chip->charge_time_us, USEC_PER_SEC);
1770 catch_up_sec = DIV_ROUND_UP(chip->catch_up_time_us, USEC_PER_SEC);
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001771 if (catch_up_sec == 0)
1772 return new_soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001773 pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
1774
1775 /*
1776 * if charging for more than catch_up time, simply return
1777 * new soc
1778 */
1779 if (chg_time_sec > catch_up_sec)
1780 return new_soc;
1781
1782 numerator = (catch_up_sec - chg_time_sec) * prev_soc
1783 + chg_time_sec * new_soc;
1784 scaled_soc = numerator / catch_up_sec;
1785
1786 pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
1787 chg_time_sec, new_soc, prev_soc, scaled_soc);
1788
1789 return scaled_soc;
1790}
1791
1792/*
1793 * bms_fake_battery is set in setups where a battery emulator is used instead
1794 * of a real battery. This makes the bms driver report a different/fake value
1795 * regardless of the calculated state of charge.
1796 */
1797static int bms_fake_battery = -EINVAL;
1798module_param(bms_fake_battery, int, 0644);
1799
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001800static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
1801{
1802 pr_debug("Reported voltage based soc = %d\n",
1803 chip->prev_voltage_based_soc);
1804 return chip->prev_voltage_based_soc;
1805}
1806
1807static int report_cc_based_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001808{
1809 int soc;
1810 int delta_time_us;
1811 struct timespec now;
1812 struct qpnp_vadc_result result;
1813 int batt_temp;
1814 int rc;
1815
Xiaozhe Shie118c692012-09-24 15:17:43 -07001816 soc = chip->calculated_soc;
1817
1818 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1819
1820 if (rc) {
1821 pr_err("error reading adc channel = %d, rc = %d\n",
1822 LR_MUX1_BATT_THERM, rc);
1823 return rc;
1824 }
1825 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1826 result.measurement);
1827 batt_temp = (int)result.physical;
1828
1829 do_posix_clock_monotonic_gettime(&now);
1830 if (chip->t_soc_queried.tv_sec != 0) {
1831 delta_time_us
1832 = (now.tv_sec - chip->t_soc_queried.tv_sec) * USEC_PER_SEC
1833 + (now.tv_nsec - chip->t_soc_queried.tv_nsec) / 1000;
1834 } else {
1835 /* calculation for the first time */
1836 delta_time_us = 0;
1837 }
1838
1839 /*
1840 * account for charge time - limit it to SOC_CATCHUP_SEC to
1841 * avoid overflows when charging continues for extended periods
1842 */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001843 if (is_battery_charging(chip)) {
Xiaozhe Shie118c692012-09-24 15:17:43 -07001844 if (chip->charge_time_us == 0) {
1845 /*
1846 * calculating soc for the first time
1847 * after start of chg. Initialize catchup time
1848 */
1849 if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
1850 chip->catch_up_time_us =
1851 (soc - chip->last_soc)
1852 * SOC_CATCHUP_SEC_PER_PERCENT
1853 * USEC_PER_SEC;
1854 else
1855 chip->catch_up_time_us =
1856 SOC_CATCHUP_SEC_MAX * USEC_PER_SEC;
1857
1858 if (chip->catch_up_time_us < 0)
1859 chip->catch_up_time_us = 0;
1860 }
1861
1862 /* add charge time */
1863 if (chip->charge_time_us < SOC_CATCHUP_SEC_MAX * USEC_PER_SEC)
1864 chip->charge_time_us += delta_time_us;
1865
1866 /* end catchup if calculated soc and last soc are same */
1867 if (chip->last_soc == soc)
1868 chip->catch_up_time_us = 0;
1869 }
1870
1871 /* last_soc < soc ... scale and catch up */
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001872 if (chip->last_soc != -EINVAL && chip->last_soc < soc && soc != 100)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001873 soc = scale_soc_while_chg(chip, delta_time_us,
1874 soc, chip->last_soc);
1875
1876 pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
1877 chip->last_soc, chip->calculated_soc, soc);
1878 chip->last_soc = soc;
1879 backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
1880 pr_debug("Reported SOC = %d\n", chip->last_soc);
1881 chip->t_soc_queried = now;
1882
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001883 return soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001884}
1885
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001886static int report_state_of_charge(struct qpnp_bms_chip *chip)
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001887{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001888 if (bms_fake_battery != -EINVAL) {
1889 pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
1890 return bms_fake_battery;
1891 } else if (chip->use_voltage_soc)
1892 return report_voltage_based_soc(chip);
1893 else
1894 return report_cc_based_soc(chip);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001895}
1896
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001897/* Returns capacity as a SoC percentage between 0 and 100 */
1898static int get_prop_bms_capacity(struct qpnp_bms_chip *chip)
1899{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001900 return report_state_of_charge(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001901}
1902
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001903/* Returns estimated max current that the battery can supply in uA */
1904static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
1905{
1906 return chip->ibat_max_ua;
1907}
1908
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001909/* Returns instantaneous current in uA */
1910static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
1911{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001912 int rc, result_ua;
1913
1914 rc = get_battery_current(chip, &result_ua);
1915 if (rc) {
1916 pr_err("failed to get current: %d\n", rc);
1917 return rc;
1918 }
1919 return result_ua;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001920}
1921
1922/* Returns full charge design in uAh */
1923static int get_prop_bms_charge_full_design(struct qpnp_bms_chip *chip)
1924{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001925 return chip->fcc;
1926}
1927
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001928static int get_prop_bms_present(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001929{
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001930 return chip->battery_present;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001931}
1932
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001933static void set_prop_bms_present(struct qpnp_bms_chip *chip, int present)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001934{
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001935 if (chip->battery_present != present) {
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001936 chip->battery_present = present;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001937 if (present)
1938 chip->new_battery = true;
1939 /* a new battery was inserted or removed, so force a soc
1940 * recalculation to update the SoC */
1941 schedule_work(&chip->recalc_work);
1942 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001943}
1944
1945static void qpnp_bms_external_power_changed(struct power_supply *psy)
1946{
1947}
1948
1949static int qpnp_bms_power_get_property(struct power_supply *psy,
1950 enum power_supply_property psp,
1951 union power_supply_propval *val)
1952{
1953 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1954 bms_psy);
1955
1956 switch (psp) {
1957 case POWER_SUPPLY_PROP_CAPACITY:
1958 val->intval = get_prop_bms_capacity(chip);
1959 break;
1960 case POWER_SUPPLY_PROP_CURRENT_NOW:
1961 val->intval = get_prop_bms_current_now(chip);
1962 break;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001963 case POWER_SUPPLY_PROP_CURRENT_MAX:
1964 val->intval = get_prop_bms_current_max(chip);
1965 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001966 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1967 val->intval = get_prop_bms_charge_full_design(chip);
1968 break;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001969 case POWER_SUPPLY_PROP_PRESENT:
1970 val->intval = get_prop_bms_present(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001971 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001972 default:
1973 return -EINVAL;
1974 }
1975 return 0;
1976}
1977
1978static int qpnp_bms_power_set_property(struct power_supply *psy,
1979 enum power_supply_property psp,
1980 const union power_supply_propval *val)
1981{
1982 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1983 bms_psy);
1984
1985 switch (psp) {
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001986 case POWER_SUPPLY_PROP_PRESENT:
1987 set_prop_bms_present(chip, val->intval);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001988 break;
1989 default:
1990 return -EINVAL;
1991 }
1992 return 0;
1993}
1994
Xiaozhe Shibdf14742012-12-05 12:41:48 -08001995#define OCV_USE_LIMIT_EN BIT(7)
1996static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
1997 int low_voltage_threshold,
1998 int high_voltage_threshold)
1999{
2000 uint16_t low_voltage_raw, high_voltage_raw;
2001 int rc;
2002
2003 low_voltage_raw = convert_vbatt_uv_to_raw(chip,
2004 low_voltage_threshold);
2005 high_voltage_raw = convert_vbatt_uv_to_raw(chip,
2006 high_voltage_threshold);
2007 rc = qpnp_write_wrapper(chip, (u8 *)&low_voltage_raw,
2008 chip->base + BMS1_OCV_USE_LOW_LIMIT_THR0, 2);
2009 if (rc) {
2010 pr_err("Failed to set ocv low voltage threshold: %d\n", rc);
2011 return rc;
2012 }
2013 rc = qpnp_write_wrapper(chip, (u8 *)&high_voltage_raw,
2014 chip->base + BMS1_OCV_USE_HIGH_LIMIT_THR0, 2);
2015 if (rc) {
2016 pr_err("Failed to set ocv high voltage threshold: %d\n", rc);
2017 return rc;
2018 }
2019 rc = qpnp_masked_write(chip, BMS1_OCV_USE_LIMIT_CTL,
2020 OCV_USE_LIMIT_EN, OCV_USE_LIMIT_EN);
2021 if (rc) {
2022 pr_err("Failed to enabled ocv voltage thresholds: %d\n", rc);
2023 return rc;
2024 }
2025 pr_debug("ocv low threshold set to %d uv or 0x%x raw\n",
2026 low_voltage_threshold, low_voltage_raw);
2027 pr_debug("ocv high threshold set to %d uv or 0x%x raw\n",
2028 high_voltage_threshold, high_voltage_raw);
2029 return 0;
2030}
2031
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002032static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
2033{
2034 int rc;
2035 u8 temp;
2036
2037 if (chip->ignore_shutdown_soc) {
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002038 chip->shutdown_soc_invalid = true;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002039 chip->shutdown_soc = 0;
2040 chip->shutdown_iavg_ma = 0;
2041 } else {
2042 rc = qpnp_read_wrapper(chip, &temp,
2043 chip->base + IAVG_STORAGE_REG, 1);
2044 if (rc) {
2045 pr_err("failed to read addr = %d %d assuming %d\n",
2046 chip->base + IAVG_STORAGE_REG, rc,
2047 IAVG_START);
2048 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shif5f966d2013-02-19 14:23:11 -08002049 } else if (temp == IAVG_INVALID) {
2050 pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
2051 IAVG_START);
2052 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002053 } else {
2054 if (temp == 0) {
2055 chip->shutdown_iavg_ma = IAVG_START;
2056 } else {
2057 chip->shutdown_iavg_ma = IAVG_START
2058 + IAVG_STEP_SIZE_MA * (temp + 1);
2059 }
2060 }
2061
2062 rc = qpnp_read_wrapper(chip, &temp,
2063 chip->base + SOC_STORAGE_REG, 1);
2064 if (rc) {
2065 pr_err("failed to read addr = %d %d\n",
2066 chip->base + SOC_STORAGE_REG, rc);
2067 } else {
2068 chip->shutdown_soc = temp;
2069
2070 if (chip->shutdown_soc == 0) {
2071 pr_debug("No shutdown soc available\n");
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002072 chip->shutdown_soc_invalid = true;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002073 chip->shutdown_iavg_ma = 0;
2074 } else if (chip->shutdown_soc == SOC_ZERO) {
2075 chip->shutdown_soc = 0;
2076 }
2077 }
2078 }
2079
2080 pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
2081 chip->shutdown_soc,
2082 chip->shutdown_iavg_ma,
2083 chip->shutdown_soc_invalid);
2084}
2085
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002086#define PALLADIUM_ID_MIN 0x7F40
2087#define PALLADIUM_ID_MAX 0x7F5A
2088#define DESAY_5200_ID_MIN 0x7F7F
2089#define DESAY_5200_ID_MAX 0x802F
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002090static int32_t read_battery_id(struct qpnp_bms_chip *chip)
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002091{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002092 int rc;
2093 struct qpnp_vadc_result result;
2094
2095 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2096 if (rc) {
2097 pr_err("error reading batt id channel = %d, rc = %d\n",
2098 LR_MUX2_BAT_ID, rc);
2099 return rc;
2100 }
2101 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
2102 result.measurement);
2103 pr_debug("raw_code = 0x%x\n", result.adc_code);
2104 return result.adc_code;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002105}
2106
2107static int set_battery_data(struct qpnp_bms_chip *chip)
2108{
2109 int64_t battery_id;
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002110 struct bms_battery_data *batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002111
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002112 if (chip->batt_type == BATT_DESAY) {
2113 batt_data = &desay_5200_data;
2114 } else if (chip->batt_type == BATT_PALLADIUM) {
2115 batt_data = &palladium_1500_data;
2116 } else if (chip->batt_type == BATT_OEM) {
2117 batt_data = &oem_batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002118 } else {
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002119 battery_id = read_battery_id(chip);
2120 if (battery_id < 0) {
2121 pr_err("cannot read battery id err = %lld\n",
2122 battery_id);
2123 return battery_id;
2124 }
2125
2126 if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
2127 battery_id)) {
2128 batt_data = &palladium_1500_data;
2129 } else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
2130 battery_id)) {
2131 batt_data = &desay_5200_data;
2132 } else {
2133 pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
2134 battery_id);
2135 batt_data = &palladium_1500_data;
2136 }
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002137 }
2138
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002139 chip->fcc = batt_data->fcc;
2140 chip->fcc_temp_lut = batt_data->fcc_temp_lut;
2141 chip->fcc_sf_lut = batt_data->fcc_sf_lut;
2142 chip->pc_temp_ocv_lut = batt_data->pc_temp_ocv_lut;
2143 chip->pc_sf_lut = batt_data->pc_sf_lut;
2144 chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
2145 chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
2146
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);