blob: ec0b0e785fce14f152178ecc000fe99f90f417d3 [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
85#define SOC_ZERO 0xFF
86
Xiaozhe Shie118c692012-09-24 15:17:43 -070087#define IAVG_SAMPLES 16
88
Xiaozhe Shib19f7032012-08-16 12:14:16 -070089#define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
90
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070091struct soc_params {
92 int fcc_uah;
93 int cc_uah;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -080094 int rbatt_mohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070095 int iavg_ua;
96 int uuc_uah;
97 int ocv_charge_uah;
Xiaozhe Shif36d2862013-01-04 10:17:35 -080098 int delta_time_s;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070099};
100
101struct raw_soc_params {
102 uint16_t last_good_ocv_raw;
103 int64_t cc;
104 int last_good_ocv_uv;
105};
106
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700107struct qpnp_bms_chip {
108 struct device *dev;
109 struct power_supply bms_psy;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700110 struct power_supply *batt_psy;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700111 struct spmi_device *spmi;
112 u16 base;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800113 u16 iadc_base;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700114
115 u8 revision1;
116 u8 revision2;
117 int charger_status;
118 bool online;
119 /* platform data */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -0800120 int r_sense_uohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700121 unsigned int v_cutoff_uv;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -0800122 int max_voltage_uv;
123 int r_conn_mohm;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700124 int shutdown_soc_valid_limit;
125 int adjust_soc_low_threshold;
126 int adjust_soc_high_threshold;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700127 int chg_term_ua;
Xiaozhe Shi73a65692012-09-18 17:51:57 -0700128 enum battery_type batt_type;
129 unsigned int fcc;
130 struct single_row_lut *fcc_temp_lut;
131 struct single_row_lut *fcc_sf_lut;
132 struct pc_temp_ocv_lut *pc_temp_ocv_lut;
133 struct sf_lut *pc_sf_lut;
134 struct sf_lut *rbatt_sf_lut;
135 int default_rbatt_mohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700136
137 struct delayed_work calculate_soc_delayed_work;
138
139 struct mutex bms_output_lock;
140 struct mutex last_ocv_uv_mutex;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700141 struct mutex soc_invalidation_mutex;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700142
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800143 bool use_external_rsense;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800144 bool use_ocv_thresholds;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800145
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700146 bool ignore_shutdown_soc;
147 int shutdown_soc_invalid;
148 int shutdown_soc;
149 int shutdown_iavg_ma;
150
151 int low_soc_calc_threshold;
152 int low_soc_calculate_soc_ms;
153 int calculate_soc_ms;
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -0800154 struct wake_lock soc_wake_lock;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700155
Xiaozhe Shie118c692012-09-24 15:17:43 -0700156 uint16_t ocv_reading_at_100;
157 int64_t cc_reading_at_100;
158 uint16_t prev_last_good_ocv_raw;
159 int last_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800160 int last_ocv_temp;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700161 int last_cc_uah;
162 unsigned long tm_sec;
163 bool first_time_calc_soc;
164 bool first_time_calc_uuc;
165 int pon_ocv_uv;
166
167 int iavg_samples_ma[IAVG_SAMPLES];
168 int iavg_index;
169 int iavg_num_samples;
170 struct timespec t_soc_queried;
171 int last_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700172 int last_soc_est;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700173
174 int charge_time_us;
175 int catch_up_time_us;
176 struct single_row_lut *adjusted_fcc_temp_lut;
177
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700178 unsigned int vadc_v0625;
179 unsigned int vadc_v1250;
180
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800181 int ibat_max_ua;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700182 int prev_iavg_ua;
183 int prev_uuc_iavg_ma;
184 int prev_pc_unusable;
185 int ibat_at_cv_ua;
186 int soc_at_cv;
187 int prev_chg_soc;
188 int calculated_soc;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -0800189 int prev_voltage_based_soc;
190 bool use_voltage_soc;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800191
192 int ocv_high_threshold_uv;
193 int ocv_low_threshold_uv;
Xiaozhe Shicdeee312012-12-18 15:10:18 -0800194 unsigned long last_recalc_time;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700195};
196
197static struct of_device_id qpnp_bms_match_table[] = {
198 { .compatible = QPNP_BMS_DEV_NAME },
199 {}
200};
201
202static char *qpnp_bms_supplicants[] = {
203 "battery"
204};
205
206static enum power_supply_property msm_bms_power_props[] = {
207 POWER_SUPPLY_PROP_STATUS,
208 POWER_SUPPLY_PROP_ONLINE,
209 POWER_SUPPLY_PROP_CAPACITY,
210 POWER_SUPPLY_PROP_CURRENT_NOW,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800211 POWER_SUPPLY_PROP_CURRENT_MAX,
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700212 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
213};
214
Xiaozhe Shi20640b52013-01-03 11:49:30 -0800215static bool bms_reset;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -0800216
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700217static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
218 u16 base, int count)
219{
220 int rc;
221 struct spmi_device *spmi = chip->spmi;
222
223 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700224 if (rc) {
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700225 pr_err("SPMI read failed rc=%d\n", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700226 return rc;
227 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700228 return 0;
229}
230
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700231static int qpnp_write_wrapper(struct qpnp_bms_chip *chip, u8 *val,
232 u16 base, int count)
233{
234 int rc;
235 struct spmi_device *spmi = chip->spmi;
236
237 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
238 if (rc) {
239 pr_err("SPMI write failed rc=%d\n", rc);
240 return rc;
241 }
242 return 0;
243}
244
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800245static int qpnp_masked_write_base(struct qpnp_bms_chip *chip, u16 addr,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700246 u8 mask, u8 val)
247{
248 int rc;
249 u8 reg;
250
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800251 rc = qpnp_read_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700252 if (rc) {
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800253 pr_err("read failed addr = %03X, rc = %d\n", addr, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700254 return rc;
255 }
256 reg &= ~mask;
257 reg |= val & mask;
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800258 rc = qpnp_write_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700259 if (rc) {
260 pr_err("write failed addr = %03X, val = %02x, mask = %02x, reg = %02x, rc = %d\n",
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800261 addr, val, mask, reg, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700262 return rc;
263 }
264 return 0;
265}
266
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800267static int qpnp_masked_write_iadc(struct qpnp_bms_chip *chip, u16 addr,
268 u8 mask, u8 val)
269{
270 return qpnp_masked_write_base(chip, chip->iadc_base + addr, mask, val);
271}
272
273static int qpnp_masked_write(struct qpnp_bms_chip *chip, u16 addr,
274 u8 mask, u8 val)
275{
276 return qpnp_masked_write_base(chip, chip->base + addr, mask, val);
277}
278
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700279#define HOLD_OREG_DATA BIT(0)
280static int lock_output_data(struct qpnp_bms_chip *chip)
281{
282 int rc;
283
284 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL,
285 HOLD_OREG_DATA, HOLD_OREG_DATA);
286 if (rc) {
287 pr_err("couldnt lock bms output rc = %d\n", rc);
288 return rc;
289 }
290 return 0;
291}
292
293static int unlock_output_data(struct qpnp_bms_chip *chip)
294{
295 int rc;
296
297 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL, HOLD_OREG_DATA, 0);
298 if (rc) {
299 pr_err("fail to unlock BMS_CONTROL rc = %d\n", rc);
300 return rc;
301 }
302 return 0;
303}
304
305#define V_PER_BIT_MUL_FACTOR 97656
306#define V_PER_BIT_DIV_FACTOR 1000
307#define VADC_INTRINSIC_OFFSET 0x6000
308
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800309static int vadc_reading_to_uv(int reading)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700310{
311 if (reading <= VADC_INTRINSIC_OFFSET)
312 return 0;
313
314 return (reading - VADC_INTRINSIC_OFFSET)
315 * V_PER_BIT_MUL_FACTOR / V_PER_BIT_DIV_FACTOR;
316}
317
318#define VADC_CALIB_UV 625000
319#define VBATT_MUL_FACTOR 3
320
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800321static int adjust_vbatt_reading(struct qpnp_bms_chip *chip, int reading_uv)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700322{
323 s64 numerator, denominator;
324
325 if (reading_uv == 0)
326 return 0;
327
328 /* don't adjust if not calibrated */
329 if (chip->vadc_v0625 == 0 || chip->vadc_v1250 == 0) {
330 pr_debug("No cal yet return %d\n",
331 VBATT_MUL_FACTOR * reading_uv);
332 return VBATT_MUL_FACTOR * reading_uv;
333 }
334
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700335 numerator = ((s64)reading_uv - chip->vadc_v0625) * VADC_CALIB_UV;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700336 denominator = (s64)chip->vadc_v1250 - chip->vadc_v0625;
337 if (denominator == 0)
338 return reading_uv * VBATT_MUL_FACTOR;
339 return (VADC_CALIB_UV + div_s64(numerator, denominator))
340 * VBATT_MUL_FACTOR;
341}
342
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800343static int convert_vbatt_uv_to_raw(struct qpnp_bms_chip *chip,
344 int unadjusted_vbatt)
345{
346 int scaled_vbatt = unadjusted_vbatt / VBATT_MUL_FACTOR;
347
348 if (scaled_vbatt <= 0)
349 return VADC_INTRINSIC_OFFSET;
350 return ((scaled_vbatt * V_PER_BIT_DIV_FACTOR) / V_PER_BIT_MUL_FACTOR)
351 + VADC_INTRINSIC_OFFSET;
352}
353
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700354static inline int convert_vbatt_raw_to_uv(struct qpnp_bms_chip *chip,
355 uint16_t reading)
356{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700357 int uv;
358
359 uv = vadc_reading_to_uv(reading);
360 pr_debug("%u raw converted into %d uv\n", reading, uv);
361 uv = adjust_vbatt_reading(chip, uv);
362 pr_debug("adjusted into %d uv\n", uv);
363 return uv;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700364}
365
366#define CC_READING_RESOLUTION_N 542535
367#define CC_READING_RESOLUTION_D 100000
368static int cc_reading_to_uv(int16_t reading)
369{
370 return div_s64(reading * CC_READING_RESOLUTION_N,
371 CC_READING_RESOLUTION_D);
372}
373
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800374#define QPNP_ADC_GAIN_IDEAL 3291LL
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700375static s64 cc_adjust_for_gain(s64 uv, uint16_t gain)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700376{
377 s64 result_uv;
378
379 pr_debug("adjusting_uv = %lld\n", uv);
Xiaozhe Shi820a47a2012-11-27 13:23:27 -0800380 if (gain == 0) {
381 pr_debug("gain is %d, not adjusting\n", gain);
382 return uv;
383 }
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700384 pr_debug("adjusting by factor: %lld/%hu = %lld%%\n",
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800385 QPNP_ADC_GAIN_IDEAL, gain,
386 div_s64(QPNP_ADC_GAIN_IDEAL * 100LL, (s64)gain));
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700387
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800388 result_uv = div_s64(uv * QPNP_ADC_GAIN_IDEAL, (s64)gain);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700389 pr_debug("result_uv = %lld\n", result_uv);
390 return result_uv;
391}
392
393static int convert_vsense_to_uv(struct qpnp_bms_chip *chip,
394 int16_t reading)
395{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700396 struct qpnp_iadc_calib calibration;
397
398 qpnp_iadc_get_gain_and_offset(&calibration);
399 return cc_adjust_for_gain(cc_reading_to_uv(reading),
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800400 calibration.gain_raw - calibration.offset_raw);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700401}
402
403static int read_vsense_avg(struct qpnp_bms_chip *chip, int *result_uv)
404{
405 int rc;
406 int16_t reading;
407
408 rc = qpnp_read_wrapper(chip, (u8 *)&reading,
409 chip->base + BMS1_VSENSE_AVG_DATA0, 2);
410
411 if (rc) {
412 pr_err("fail to read VSENSE_AVG rc = %d\n", rc);
413 return rc;
414 }
415
416 *result_uv = convert_vsense_to_uv(chip, reading);
417 return 0;
418}
419
420static int get_battery_current(struct qpnp_bms_chip *chip, int *result_ua)
421{
422 int vsense_uv = 0;
423
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800424 if (chip->r_sense_uohm == 0) {
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700425 pr_err("r_sense is zero\n");
426 return -EINVAL;
427 }
428
429 mutex_lock(&chip->bms_output_lock);
430 lock_output_data(chip);
431 read_vsense_avg(chip, &vsense_uv);
432 unlock_output_data(chip);
433 mutex_unlock(&chip->bms_output_lock);
434
435 pr_debug("vsense_uv=%duV\n", vsense_uv);
436 /* cast for signed division */
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800437 *result_ua = div_s64((vsense_uv * 1000000LL), (int)chip->r_sense_uohm);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700438 pr_debug("ibat=%duA\n", *result_ua);
439 return 0;
440}
441
442static int get_battery_voltage(int *result_uv)
443{
444 int rc;
445 struct qpnp_vadc_result adc_result;
446
447 rc = qpnp_vadc_read(VBAT_SNS, &adc_result);
448 if (rc) {
449 pr_err("error reading adc channel = %d, rc = %d\n",
450 VBAT_SNS, rc);
451 return rc;
452 }
453 pr_debug("mvolts phy = %lld meas = 0x%llx\n", adc_result.physical,
454 adc_result.measurement);
455 *result_uv = (int)adc_result.physical;
456 return 0;
457}
458
Xiaozhe Shie118c692012-09-24 15:17:43 -0700459#define CC_36_BIT_MASK 0xFFFFFFFFFLL
460
461static int read_cc_raw(struct qpnp_bms_chip *chip, int64_t *reading)
462{
463 int64_t raw_reading;
464 int rc;
465
466 rc = qpnp_read_wrapper(chip, (u8 *)&raw_reading,
467 chip->base + BMS1_CC_DATA0, 5);
468 if (rc) {
469 pr_err("Error reading cc: rc = %d\n", rc);
470 return -ENXIO;
471 }
472
473 raw_reading = raw_reading & CC_36_BIT_MASK;
474 /* convert 36 bit signed value into 64 signed value */
475 *reading = (raw_reading >> 35) == 0LL ?
476 raw_reading : ((-1LL ^ CC_36_BIT_MASK) | raw_reading);
477 pr_debug("before conversion: %llx, after conversion: %llx\n",
478 raw_reading, *reading);
479
480 return 0;
481}
482
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700483static int calib_vadc(struct qpnp_bms_chip *chip)
484{
485 int rc;
486 struct qpnp_vadc_result result;
487
488 rc = qpnp_vadc_read(REF_625MV, &result);
489 if (rc) {
490 pr_debug("vadc read failed with rc = %d\n", rc);
491 return rc;
492 }
493 chip->vadc_v0625 = result.physical;
494
495 rc = qpnp_vadc_read(REF_125V, &result);
496 if (rc) {
497 pr_debug("vadc read failed with rc = %d\n", rc);
498 return rc;
499 }
500 chip->vadc_v1250 = result.physical;
501 pr_debug("vadc calib: 0625 = %d, 1250 = %d\n",
502 chip->vadc_v0625, chip->vadc_v1250);
503 return 0;
504}
505
Xiaozhe Shie118c692012-09-24 15:17:43 -0700506static void convert_and_store_ocv(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800507 struct raw_soc_params *raw,
508 int batt_temp)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700509{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700510 int rc;
511
512 pr_debug("prev_last_good_ocv_raw = %d, last_good_ocv_raw = %d\n",
513 chip->prev_last_good_ocv_raw,
514 raw->last_good_ocv_raw);
515 rc = calib_vadc(chip);
516 if (rc)
517 pr_err("Vadc reference voltage read failed, rc = %d\n", rc);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700518 chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
519 raw->last_good_ocv_uv = convert_vbatt_raw_to_uv(chip,
520 raw->last_good_ocv_raw);
521 chip->last_ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800522 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700523 pr_debug("last_good_ocv_uv = %d\n", raw->last_good_ocv_uv);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700524}
525
Xiaozhe Shia045a562012-11-28 16:55:39 -0800526#define CLEAR_CC BIT(7)
527#define CLEAR_SW_CC BIT(6)
528/**
529 * reset both cc and sw-cc.
530 * note: this should only be ever called from one thread
531 * or there may be a race condition where CC is never enabled
532 * again
533 */
534static void reset_cc(struct qpnp_bms_chip *chip)
535{
536 int rc;
537
538 pr_debug("resetting cc manually\n");
539 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
540 CLEAR_CC | CLEAR_SW_CC,
541 CLEAR_CC | CLEAR_SW_CC);
542 if (rc)
543 pr_err("cc reset failed: %d\n", rc);
544
545 /* wait for 100us for cc to reset */
546 udelay(100);
547
548 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
549 CLEAR_CC | CLEAR_SW_CC, 0);
550 if (rc)
551 pr_err("cc reenable failed: %d\n", rc);
552}
553
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800554#define OCV_RAW_UNINITIALIZED 0xFFFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700555static int read_soc_params_raw(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800556 struct raw_soc_params *raw,
557 int batt_temp)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700558{
Xiaozhe Shie118c692012-09-24 15:17:43 -0700559 int rc;
560
561 mutex_lock(&chip->bms_output_lock);
Xiaozhe Shia045a562012-11-28 16:55:39 -0800562
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800563 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Xiaozhe Shia045a562012-11-28 16:55:39 -0800564 /* software workaround for BMS 1.0
565 * The coulomb counter does not reset upon PON, so reset it
566 * manually upon probe. */
567 if (chip->revision1 == 0 && chip->revision2 == 0)
568 reset_cc(chip);
569 }
570
Xiaozhe Shie118c692012-09-24 15:17:43 -0700571 lock_output_data(chip);
572
573 rc = qpnp_read_wrapper(chip, (u8 *)&raw->last_good_ocv_raw,
574 chip->base + BMS1_OCV_FOR_SOC_DATA0, 2);
575 if (rc) {
576 pr_err("Error reading ocv: rc = %d\n", rc);
577 return -ENXIO;
578 }
579
580 rc = read_cc_raw(chip, &raw->cc);
581 if (rc) {
582 pr_err("Failed to read raw cc data, rc = %d\n", rc);
583 return rc;
584 }
585
586 unlock_output_data(chip);
587 mutex_unlock(&chip->bms_output_lock);
588
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800589 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800590 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700591 pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
592 } else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800593 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700594 /* forget the old cc value upon ocv */
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800595 chip->last_cc_uah = INT_MIN;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700596 } else {
597 raw->last_good_ocv_uv = chip->last_ocv_uv;
598 }
599
600 /* fake a high OCV if done charging */
601 if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800602 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700603 chip->cc_reading_at_100 = 0;
604 } else {
605 /*
606 * force 100% ocv by selecting the highest voltage the
607 * battery could ever reach
608 */
609 raw->last_good_ocv_uv = chip->max_voltage_uv;
610 chip->last_ocv_uv = chip->max_voltage_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800611 chip->last_ocv_temp = batt_temp;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700612 }
613 pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
614 raw->last_good_ocv_raw, raw->last_good_ocv_uv);
615 pr_debug("cc_raw= 0x%llx\n", raw->cc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700616 return 0;
617}
618
Xiaozhe Shie118c692012-09-24 15:17:43 -0700619static int calculate_pc(struct qpnp_bms_chip *chip, int ocv_uv,
620 int batt_temp)
621{
622 int pc;
623
624 pc = interpolate_pc(chip->pc_temp_ocv_lut,
625 batt_temp / 10, ocv_uv / 1000);
626 pr_debug("pc = %u %% for ocv = %d uv batt_temp = %d\n",
627 pc, ocv_uv, batt_temp);
628 /* Multiply the initial FCC value by the scale factor. */
629 return pc;
630}
631
632static int calculate_fcc(struct qpnp_bms_chip *chip, int batt_temp)
633{
634 int fcc_uah;
635
636 if (chip->adjusted_fcc_temp_lut == NULL) {
637 /* interpolate_fcc returns a mv value. */
638 fcc_uah = interpolate_fcc(chip->fcc_temp_lut,
639 batt_temp) * 1000;
640 pr_debug("fcc = %d uAh\n", fcc_uah);
641 return fcc_uah;
642 } else {
643 return 1000 * interpolate_fcc(chip->adjusted_fcc_temp_lut,
644 batt_temp);
645 }
646}
647
648/* calculate remaining charge at the time of ocv */
649static int calculate_ocv_charge(struct qpnp_bms_chip *chip,
650 struct raw_soc_params *raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800651 int fcc_uah)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700652{
653 int ocv_uv, pc;
654
655 ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800656 pc = calculate_pc(chip, ocv_uv, chip->last_ocv_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700657 pr_debug("ocv_uv = %d pc = %d\n", ocv_uv, pc);
658 return (fcc_uah * pc) / 100;
659}
660
661#define CC_RESOLUTION_N 542535
662#define CC_RESOLUTION_D 100000
663
664static s64 cc_to_uv(s64 cc)
665{
666 return div_s64(cc * CC_RESOLUTION_N, CC_RESOLUTION_D);
667}
668
669#define CC_READING_TICKS 56
670#define SLEEP_CLK_HZ 32764
671#define SECONDS_PER_HOUR 3600
672
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800673static s64 cc_uv_to_pvh(s64 cc_uv)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700674{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800675 /* Note that it is necessary need to multiply by 1000000 to convert
676 * from uvh to pvh here.
677 * However, the maximum Coulomb Counter value is 2^35, which can cause
678 * an over flow.
679 * Multiply by 100000 first to perserve as much precision as possible
680 * then multiply by 10 after doing the division in order to avoid
681 * overflow on the maximum Coulomb Counter value.
682 */
683 return div_s64(cc_uv * CC_READING_TICKS * 100000,
684 SLEEP_CLK_HZ * SECONDS_PER_HOUR) * 10;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700685}
686
687/**
688 * calculate_cc-
689 * @chip: the bms chip pointer
690 * @cc: the cc reading from bms h/w
691 * @val: return value
692 * @coulomb_counter: adjusted coulomb counter for 100%
693 *
694 * RETURNS: in val pointer coulomb counter based charger in uAh
695 * (micro Amp hour)
696 */
697static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
698{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800699 int64_t cc_voltage_uv, cc_pvh, cc_uah;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700700 struct qpnp_iadc_calib calibration;
701
702 qpnp_iadc_get_gain_and_offset(&calibration);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700703 cc_voltage_uv = cc;
704 cc_voltage_uv -= chip->cc_reading_at_100;
705 pr_debug("cc = %lld. after subtracting 0x%llx cc = %lld\n",
706 cc, chip->cc_reading_at_100,
707 cc_voltage_uv);
708 cc_voltage_uv = cc_to_uv(cc_voltage_uv);
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800709 cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
710 calibration.gain_raw
711 - calibration.offset_raw);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700712 pr_debug("cc_voltage_uv = %lld uv\n", cc_voltage_uv);
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800713 cc_pvh = cc_uv_to_pvh(cc_voltage_uv);
714 pr_debug("cc_pvh = %lld pvh\n", cc_pvh);
715 cc_uah = div_s64(cc_pvh, chip->r_sense_uohm);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700716 /* cc_raw had 4 bits of extra precision.
717 By now it should be within 32 bit range */
718 return (int)cc_uah;
719}
720
721static int get_rbatt(struct qpnp_bms_chip *chip,
722 int soc_rbatt_mohm, int batt_temp)
723{
724 int rbatt_mohm, scalefactor;
725
726 rbatt_mohm = chip->default_rbatt_mohm;
727 pr_debug("rbatt before scaling = %d\n", rbatt_mohm);
728 if (chip->rbatt_sf_lut == NULL) {
729 pr_debug("RBATT = %d\n", rbatt_mohm);
730 return rbatt_mohm;
731 }
732 /* Convert the batt_temp to DegC from deciDegC */
733 batt_temp = batt_temp / 10;
734 scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
735 batt_temp, soc_rbatt_mohm);
736 pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
737 scalefactor, batt_temp, soc_rbatt_mohm);
738 rbatt_mohm = (rbatt_mohm * scalefactor) / 100;
739
740 rbatt_mohm += chip->r_conn_mohm;
741 pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
742 chip->r_conn_mohm, rbatt_mohm);
743
744 pr_debug("RBATT = %d\n", rbatt_mohm);
745 return rbatt_mohm;
746}
747
748static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800749 int *iavg_ua, int delta_time_s)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700750{
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800751 int delta_cc_uah = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700752
Xiaozhe Shie118c692012-09-24 15:17:43 -0700753 /* if anything fails report the previous iavg_ua */
754 *iavg_ua = chip->prev_iavg_ua;
755
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800756 if (chip->last_cc_uah == INT_MIN) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700757 get_battery_current(chip, iavg_ua);
758 goto out;
759 }
760
Xiaozhe Shie118c692012-09-24 15:17:43 -0700761 /* use the previous iavg if called within 15 seconds */
762 if (delta_time_s < 15) {
763 *iavg_ua = chip->prev_iavg_ua;
764 goto out;
765 }
766
767 delta_cc_uah = cc_uah - chip->last_cc_uah;
768
769 *iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
770
Xiaozhe Shie118c692012-09-24 15:17:43 -0700771out:
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800772 pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700773 /* remember the iavg */
774 chip->prev_iavg_ua = *iavg_ua;
775
776 /* remember cc_uah */
777 chip->last_cc_uah = cc_uah;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700778}
779
780static int calculate_termination_uuc(struct qpnp_bms_chip *chip,
781 struct soc_params *params,
782 int batt_temp, int uuc_iavg_ma,
783 int *ret_pc_unusable)
784{
785 int unusable_uv, pc_unusable, uuc_uah;
786 int i = 0;
787 int ocv_mv;
788 int batt_temp_degc = batt_temp / 10;
789 int rbatt_mohm;
790 int delta_uv;
791 int prev_delta_uv = 0;
792 int prev_rbatt_mohm = 0;
793 int uuc_rbatt_mohm;
794
795 for (i = 0; i <= 100; i++) {
796 ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
797 batt_temp_degc, i);
798 rbatt_mohm = get_rbatt(chip, i, batt_temp);
799 unusable_uv = (rbatt_mohm * uuc_iavg_ma)
800 + (chip->v_cutoff_uv);
801 delta_uv = ocv_mv * 1000 - unusable_uv;
802
803 pr_debug("soc = %d ocv = %d rbat = %d u_uv = %d delta_v = %d\n",
804 i, ocv_mv, rbatt_mohm, unusable_uv, delta_uv);
805
806 if (delta_uv > 0)
807 break;
808
809 prev_delta_uv = delta_uv;
810 prev_rbatt_mohm = rbatt_mohm;
811 }
812
813 uuc_rbatt_mohm = linear_interpolate(rbatt_mohm, delta_uv,
814 prev_rbatt_mohm, prev_delta_uv,
815 0);
816
817 unusable_uv = (uuc_rbatt_mohm * uuc_iavg_ma) + (chip->v_cutoff_uv);
818
819 pc_unusable = calculate_pc(chip, unusable_uv, batt_temp);
820 uuc_uah = (params->fcc_uah * pc_unusable) / 100;
821 pr_debug("For uuc_iavg_ma = %d, unusable_rbatt = %d unusable_uv = %d unusable_pc = %d uuc = %d\n",
822 uuc_iavg_ma,
823 uuc_rbatt_mohm, unusable_uv,
824 pc_unusable, uuc_uah);
825 *ret_pc_unusable = pc_unusable;
826 return uuc_uah;
827}
828
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800829#define TIME_PER_PERCENT_UUC 60
Xiaozhe Shie118c692012-09-24 15:17:43 -0700830static int adjust_uuc(struct qpnp_bms_chip *chip,
831 struct soc_params *params,
832 int new_pc_unusable,
833 int new_uuc_uah,
834 int batt_temp)
835{
836 int new_unusable_mv, new_iavg_ma;
837 int batt_temp_degc = batt_temp / 10;
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800838 int max_percent_change;
839
840 max_percent_change = max(params->delta_time_s
841 / TIME_PER_PERCENT_UUC, 1);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700842
843 if (chip->prev_pc_unusable == -EINVAL
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800844 || abs(chip->prev_pc_unusable - new_pc_unusable)
845 <= max_percent_change) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700846 chip->prev_pc_unusable = new_pc_unusable;
847 return new_uuc_uah;
848 }
849
850 /* the uuc is trying to change more than 1% restrict it */
851 if (new_pc_unusable > chip->prev_pc_unusable)
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800852 chip->prev_pc_unusable += max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700853 else
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800854 chip->prev_pc_unusable -= max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700855
856 new_uuc_uah = (params->fcc_uah * chip->prev_pc_unusable) / 100;
857
858 /* also find update the iavg_ma accordingly */
859 new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
860 batt_temp_degc, chip->prev_pc_unusable);
861 if (new_unusable_mv < chip->v_cutoff_uv/1000)
862 new_unusable_mv = chip->v_cutoff_uv/1000;
863
864 new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800865 / params->rbatt_mohm;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700866 if (new_iavg_ma == 0)
867 new_iavg_ma = 1;
868 chip->prev_uuc_iavg_ma = new_iavg_ma;
869 pr_debug("Restricting UUC to %d (%d%%) unusable_mv = %d iavg_ma = %d\n",
870 new_uuc_uah, chip->prev_pc_unusable,
871 new_unusable_mv, new_iavg_ma);
872
873 return new_uuc_uah;
874}
875
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800876#define MIN_IAVG_MA 250
Xiaozhe Shie118c692012-09-24 15:17:43 -0700877#define MIN_SECONDS_FOR_VALID_SAMPLE 20
878static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
879 struct soc_params *params,
880 int batt_temp)
881{
882 int uuc_uah_iavg;
883 int i;
884 int uuc_iavg_ma = params->iavg_ua / 1000;
885 int pc_unusable;
886
887 /*
888 * if called first time, fill all the samples with
889 * the shutdown_iavg_ma
890 */
891 if (chip->first_time_calc_uuc && chip->shutdown_iavg_ma != 0) {
892 pr_debug("Using shutdown_iavg_ma = %d in all samples\n",
893 chip->shutdown_iavg_ma);
894 for (i = 0; i < IAVG_SAMPLES; i++)
895 chip->iavg_samples_ma[i] = chip->shutdown_iavg_ma;
896
897 chip->iavg_index = 0;
898 chip->iavg_num_samples = IAVG_SAMPLES;
899 }
900
901 /*
902 * if charging use a nominal avg current to keep
903 * a reasonable UUC while charging
904 */
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800905 if (uuc_iavg_ma < MIN_IAVG_MA)
906 uuc_iavg_ma = MIN_IAVG_MA;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700907 chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
908 chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
909 chip->iavg_num_samples++;
910 if (chip->iavg_num_samples >= IAVG_SAMPLES)
911 chip->iavg_num_samples = IAVG_SAMPLES;
912
913 /* now that this sample is added calcualte the average */
914 uuc_iavg_ma = 0;
915 if (chip->iavg_num_samples != 0) {
916 for (i = 0; i < chip->iavg_num_samples; i++) {
917 pr_debug("iavg_samples_ma[%d] = %d\n", i,
918 chip->iavg_samples_ma[i]);
919 uuc_iavg_ma += chip->iavg_samples_ma[i];
920 }
921
922 uuc_iavg_ma = DIV_ROUND_CLOSEST(uuc_iavg_ma,
923 chip->iavg_num_samples);
924 }
925
Xiaozhe Shi20640b52013-01-03 11:49:30 -0800926 /*
927 * if we're in bms reset mode, force uuc to be 3% of fcc
928 */
929 if (bms_reset)
930 return (params->fcc_uah * 3) / 100;
931
Xiaozhe Shi75e5efe2013-02-07 09:51:43 -0800932 uuc_uah_iavg = calculate_termination_uuc(chip, params, batt_temp,
933 uuc_iavg_ma, &pc_unusable);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700934 pr_debug("uuc_iavg_ma = %d uuc with iavg = %d\n",
935 uuc_iavg_ma, uuc_uah_iavg);
936
937 chip->prev_uuc_iavg_ma = uuc_iavg_ma;
938 /* restrict the uuc such that it can increase only by one percent */
939 uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
940 uuc_uah_iavg, batt_temp);
941
942 chip->first_time_calc_uuc = 0;
943 return uuc_uah_iavg;
944}
945
946static void find_ocv_for_soc(struct qpnp_bms_chip *chip,
947 struct soc_params *params,
948 int batt_temp,
949 int shutdown_soc,
950 int *ret_ocv_uv)
951{
952 s64 ocv_charge_uah;
953 int pc, new_pc;
954 int batt_temp_degc = batt_temp / 10;
955 int ocv_uv;
956
957 ocv_charge_uah = (s64)shutdown_soc
958 * (params->fcc_uah - params->uuc_uah);
959 ocv_charge_uah = div_s64(ocv_charge_uah, 100)
960 + params->cc_uah + params->uuc_uah;
961 pc = DIV_ROUND_CLOSEST((int)ocv_charge_uah * 100, params->fcc_uah);
962 pc = clamp(pc, 0, 100);
963
964 ocv_uv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
965
966 pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
967 shutdown_soc, params->fcc_uah,
968 params->uuc_uah, (int)ocv_charge_uah,
969 pc, ocv_uv);
970 new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv_uv);
971 pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv_uv);
972
973 while (abs(new_pc - pc) > 1) {
974 int delta_mv = 5;
975
976 if (new_pc > pc)
977 delta_mv = -1 * delta_mv;
978
979 ocv_uv = ocv_uv + delta_mv;
980 new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
981 batt_temp_degc, ocv_uv);
982 pr_debug("test revlookup pc = %d for ocv = %d\n",
983 new_pc, ocv_uv);
984 }
985
986 *ret_ocv_uv = ocv_uv * 1000;
987 params->ocv_charge_uah = (int)ocv_charge_uah;
988}
989
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800990static int get_current_time(unsigned long *now_tm_sec)
991{
992 struct rtc_time tm;
993 struct rtc_device *rtc;
994 int rc;
995
996 rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
997 if (rtc == NULL) {
998 pr_err("%s: unable to open rtc device (%s)\n",
999 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
1000 rc = -EINVAL;
1001 goto close_time;
1002 }
1003
1004 rc = rtc_read_time(rtc, &tm);
1005 if (rc) {
1006 pr_err("Error reading rtc device (%s) : %d\n",
1007 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1008 goto close_time;
1009 }
1010
1011 rc = rtc_valid_tm(&tm);
1012 if (rc) {
1013 pr_err("Invalid RTC time (%s): %d\n",
1014 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1015 goto close_time;
1016 }
1017 rtc_tm_to_time(&tm, now_tm_sec);
1018
1019close_time:
1020 rtc_class_close(rtc);
1021 return rc;
1022}
1023
1024static int calculate_delta_time(struct qpnp_bms_chip *chip, int *delta_time_s)
1025{
1026 unsigned long now_tm_sec = 0;
1027
1028 /* default to delta time = 0 if anything fails */
1029 *delta_time_s = 0;
1030
1031 get_current_time(&now_tm_sec);
1032
1033 *delta_time_s = (now_tm_sec - chip->tm_sec);
1034 pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
1035 chip->tm_sec, now_tm_sec, *delta_time_s);
1036
1037 /* remember this time */
1038 chip->tm_sec = now_tm_sec;
1039 return 0;
1040}
1041
Xiaozhe Shie118c692012-09-24 15:17:43 -07001042static void calculate_soc_params(struct qpnp_bms_chip *chip,
1043 struct raw_soc_params *raw,
1044 struct soc_params *params,
1045 int batt_temp)
1046{
1047 int soc_rbatt;
1048
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001049 calculate_delta_time(chip, &params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001050 params->fcc_uah = calculate_fcc(chip, batt_temp);
1051 pr_debug("FCC = %uuAh batt_temp = %d\n", params->fcc_uah, batt_temp);
1052
1053 /* calculate remainging charge */
1054 params->ocv_charge_uah = calculate_ocv_charge(
1055 chip, raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001056 params->fcc_uah);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001057 pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
1058
1059 /* calculate cc micro_volt_hour */
1060 params->cc_uah = calculate_cc(chip, raw->cc);
1061 pr_debug("cc_uah = %duAh raw->cc = %llx cc = %lld after subtracting %llx\n",
1062 params->cc_uah, raw->cc,
1063 (int64_t)raw->cc - chip->cc_reading_at_100,
1064 chip->cc_reading_at_100);
1065
1066 soc_rbatt = ((params->ocv_charge_uah - params->cc_uah) * 100)
1067 / params->fcc_uah;
1068 if (soc_rbatt < 0)
1069 soc_rbatt = 0;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001070 params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001071
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001072 calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
1073 params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001074
1075 params->uuc_uah = calculate_unusable_charge_uah(chip, params,
1076 batt_temp);
1077 pr_debug("UUC = %uuAh\n", params->uuc_uah);
1078}
1079
1080static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
1081{
1082 if (chip->shutdown_soc_invalid) {
1083 pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
1084 return 0;
1085 }
1086
1087 if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
1088 pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
1089 chip->shutdown_soc, soc,
1090 chip->shutdown_soc_valid_limit);
1091 chip->shutdown_soc_invalid = 1;
1092 return 0;
1093 }
1094
1095 return 1;
1096}
1097
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001098static bool is_battery_charging(struct qpnp_bms_chip *chip)
1099{
1100 union power_supply_propval ret = {0,};
1101
1102 if (chip->batt_psy == NULL)
1103 chip->batt_psy = power_supply_get_by_name("battery");
1104 if (chip->batt_psy) {
1105 /* if battery has been registered, use the status property */
1106 chip->batt_psy->get_property(chip->batt_psy,
1107 POWER_SUPPLY_PROP_STATUS, &ret);
1108 return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
1109 }
1110
1111 /* Default to false if the battery power supply is not registered. */
1112 pr_debug("battery power supply is not registered\n");
1113 return false;
1114}
1115
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001116static bool is_batfet_open(struct qpnp_bms_chip *chip)
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001117{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001118 union power_supply_propval ret = {0,};
1119
1120 if (chip->batt_psy == NULL)
1121 chip->batt_psy = power_supply_get_by_name("battery");
1122 if (chip->batt_psy) {
1123 /* if battery has been registered, use the status property */
1124 chip->batt_psy->get_property(chip->batt_psy,
1125 POWER_SUPPLY_PROP_STATUS, &ret);
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001126 return ret.intval == POWER_SUPPLY_STATUS_FULL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001127 }
1128
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001129 /* Default to true if the battery power supply is not registered. */
1130 pr_debug("battery power supply is not registered\n");
1131 return true;
1132}
1133
1134static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
1135 int *ibat_ua, int *vbat_uv)
1136{
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001137 struct qpnp_iadc_result i_result;
1138 struct qpnp_vadc_result v_result;
1139 enum qpnp_iadc_channels iadc_channel;
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001140 int rc;
1141
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001142 iadc_channel = chip->use_external_rsense ?
1143 EXTERNAL_RSENSE : INTERNAL_RSENSE;
1144 rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
1145 VBAT_SNS, &v_result);
1146 if (rc) {
1147 pr_err("vadc read failed with rc: %d\n", rc);
1148 return rc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001149 }
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001150 *ibat_ua = (int)i_result.result_ua;
1151 *vbat_uv = (int)v_result.physical;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001152
1153 return 0;
1154}
1155
1156static int bound_soc(int soc)
1157{
1158 soc = max(0, soc);
1159 soc = min(100, soc);
1160 return soc;
1161}
1162
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001163#define IBAT_TOL_MASK 0x0F
1164#define OCV_TOL_MASK 0xF0
1165#define IBAT_TOL_DEFAULT 0x03
1166#define IBAT_TOL_NOCHG 0x0F
1167#define OCV_TOL_DEFAULT 0x20
1168#define OCV_TOL_NO_OCV 0x00
1169static int stop_ocv_updates(struct qpnp_bms_chip *chip)
1170{
1171 pr_debug("stopping ocv updates\n");
1172 return qpnp_masked_write(chip, BMS1_TOL_CTL,
1173 OCV_TOL_MASK, OCV_TOL_NO_OCV);
1174}
1175
1176static int reset_bms_for_test(struct qpnp_bms_chip *chip)
1177{
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001178 int ibat_ua = 0, vbat_uv = 0, rc;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001179 int ocv_est_uv;
1180
1181 if (!chip) {
1182 pr_err("BMS driver has not been initialized yet!\n");
1183 return -EINVAL;
1184 }
1185
1186 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1187
1188 ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
1189 pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
1190 chip->last_ocv_uv = ocv_est_uv;
1191 chip->last_soc = -EINVAL;
1192 reset_cc(chip);
1193 chip->last_cc_uah = INT_MIN;
1194 stop_ocv_updates(chip);
1195
1196 pr_debug("bms reset to ocv = %duv vbat_ua = %d ibat_ua = %d\n",
1197 chip->last_ocv_uv, vbat_uv, ibat_ua);
1198
1199 return rc;
1200}
1201
1202static int bms_reset_set(const char *val, const struct kernel_param *kp)
1203{
1204 int rc;
1205
1206 rc = param_set_bool(val, kp);
1207 if (rc) {
1208 pr_err("Unable to set bms_reset: %d\n", rc);
1209 return rc;
1210 }
1211
1212 if (*(bool *)kp->arg) {
1213 struct power_supply *bms_psy = power_supply_get_by_name("bms");
1214 struct qpnp_bms_chip *chip = container_of(bms_psy,
1215 struct qpnp_bms_chip, bms_psy);
1216
1217 rc = reset_bms_for_test(chip);
1218 if (rc) {
1219 pr_err("Unable to modify bms_reset: %d\n", rc);
1220 return rc;
1221 }
1222 }
1223 return 0;
1224}
1225
1226static struct kernel_param_ops bms_reset_ops = {
1227 .set = bms_reset_set,
1228 .get = param_get_bool,
1229};
1230
1231module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
1232
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001233static int charging_adjustments(struct qpnp_bms_chip *chip,
1234 struct soc_params *params, int soc,
1235 int vbat_uv, int ibat_ua, int batt_temp)
1236{
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001237 int chg_soc;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001238 int batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001239
1240 if (chip->soc_at_cv == -EINVAL) {
1241 /* In constant current charging return the calc soc */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001242 if (batt_terminal_uv <= chip->max_voltage_uv)
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001243 pr_debug("CC CHG SOC %d\n", soc);
1244
1245 /* Note the CC to CV point */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001246 if (batt_terminal_uv >= chip->max_voltage_uv) {
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001247 chip->soc_at_cv = soc;
1248 chip->prev_chg_soc = soc;
1249 chip->ibat_at_cv_ua = ibat_ua;
1250 pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
1251 ibat_ua, soc);
1252 }
1253 return soc;
1254 }
1255
1256 /*
1257 * battery is in CV phase - begin liner inerpolation of soc based on
1258 * battery charge current
1259 */
1260
1261 /*
1262 * if voltage lessened (possibly because of a system load)
1263 * keep reporting the prev chg soc
1264 */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001265 if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
1266 pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
1267 batt_terminal_uv,
1268 chip->max_voltage_uv, chip->prev_chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001269 return chip->prev_chg_soc;
1270 }
1271
1272 chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001273 100, -1 * chip->chg_term_ua,
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001274 ibat_ua);
Xiaozhe Shi78d0c532012-12-10 13:02:14 -08001275 chg_soc = bound_soc(chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001276
1277 /* always report a higher soc */
1278 if (chg_soc > chip->prev_chg_soc) {
1279 int new_ocv_uv;
1280
1281 chip->prev_chg_soc = chg_soc;
1282
1283 find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
1284 chip->last_ocv_uv = new_ocv_uv;
1285 pr_debug("CC CHG ADJ OCV = %d CHG SOC %d\n",
1286 new_ocv_uv,
1287 chip->prev_chg_soc);
1288 }
1289
1290 pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
1291 return chip->prev_chg_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001292}
1293
Xiaozhe Shie118c692012-09-24 15:17:43 -07001294static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
1295 int soc, int batt_temp)
1296{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001297 int ibat_ua = 0, vbat_uv = 0;
1298 int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
1299 int delta_ocv_uv = 0;
1300 int n = 0;
1301 int rc_new_uah = 0;
1302 int pc_new = 0;
1303 int soc_new = 0;
1304 int slope = 0;
1305 int rc = 0;
1306 int delta_ocv_uv_limit = 0;
1307
1308 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1309 if (rc < 0) {
1310 pr_err("simultaneous vbat ibat failed err = %d\n", rc);
1311 goto out;
1312 }
1313
1314 delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
1315
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001316 ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
1317
1318 chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
1319 / (params->rbatt_mohm);
1320
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001321 pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
1322 soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
1323 (s64)params->fcc_uah - params->uuc_uah);
1324 soc_est = bound_soc(soc_est);
1325
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001326 /* never adjust during bms reset mode */
1327 if (bms_reset) {
1328 pr_debug("bms reset mode, SOC adjustment skipped\n");
1329 goto out;
1330 }
1331
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001332 if (ibat_ua < 0 && !is_batfet_open(chip)) {
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001333 soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
1334 batt_temp);
1335 goto out;
1336 }
1337
1338 /*
1339 * do not adjust
1340 * if soc is same as what bms calculated
1341 * if soc_est is between 45 and 25, this is the flat portion of the
1342 * curve where soc_est is not so accurate. We generally don't want to
1343 * adjust when soc_est is inaccurate except for the cases when soc is
1344 * way far off (higher than 50 or lesser than 20).
1345 * Also don't adjust soc if it is above 90 becuase it might be pulled
1346 * low and cause a bad user experience
1347 */
1348 if (soc_est == soc
1349 || (is_between(45, chip->adjust_soc_low_threshold, soc_est)
1350 && is_between(50, chip->adjust_soc_low_threshold - 5, soc))
1351 || soc >= 90)
1352 goto out;
1353
1354 if (chip->last_soc_est == -EINVAL)
1355 chip->last_soc_est = soc;
1356
1357 n = min(200, max(1 , soc + soc_est + chip->last_soc_est));
1358 chip->last_soc_est = soc_est;
1359
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001360 pc = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001361 if (pc > 0) {
1362 pc_new = calculate_pc(chip,
1363 chip->last_ocv_uv - (++slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001364 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001365 while (pc_new == pc) {
1366 /* start taking 10mV steps */
1367 slope = slope + 10;
1368 pc_new = calculate_pc(chip,
1369 chip->last_ocv_uv - (slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001370 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001371 }
1372 } else {
1373 /*
1374 * pc is already at the lowest point,
1375 * assume 1 millivolt translates to 1% pc
1376 */
1377 pc = 1;
1378 pc_new = 0;
1379 slope = 1;
1380 }
1381
1382 delta_ocv_uv = div_s64((soc - soc_est) * (s64)slope * 1000,
1383 n * (pc - pc_new));
1384
1385 if (abs(delta_ocv_uv) > delta_ocv_uv_limit) {
1386 pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
1387 delta_ocv_uv_limit);
1388
1389 if (delta_ocv_uv > 0)
1390 delta_ocv_uv = delta_ocv_uv_limit;
1391 else
1392 delta_ocv_uv = -1 * delta_ocv_uv_limit;
1393 pr_debug("new delta ocv = %d\n", delta_ocv_uv);
1394 }
1395
1396 chip->last_ocv_uv -= delta_ocv_uv;
1397
1398 if (chip->last_ocv_uv >= chip->max_voltage_uv)
1399 chip->last_ocv_uv = chip->max_voltage_uv;
1400
1401 /* calculate the soc based on this new ocv */
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001402 pc_new = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001403 rc_new_uah = (params->fcc_uah * pc_new) / 100;
1404 soc_new = (rc_new_uah - params->cc_uah - params->uuc_uah)*100
1405 / (params->fcc_uah - params->uuc_uah);
1406 soc_new = bound_soc(soc_new);
1407
1408 /*
1409 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
1410 * soc = 0 should happen only when soc_est == 0
1411 */
1412 if (soc_new == 0 && soc_est != 0)
1413 soc_new = 1;
1414
1415 soc = soc_new;
1416
1417out:
1418 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",
1419 ibat_ua, vbat_uv, ocv_est_uv, pc_est,
1420 soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001421 pc_new, soc_new, params->rbatt_mohm, slope);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001422
Xiaozhe Shie118c692012-09-24 15:17:43 -07001423 return soc;
1424}
1425
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001426static int clamp_soc_based_on_voltage(struct qpnp_bms_chip *chip, int soc)
1427{
1428 int rc, vbat_uv;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001429
Xiaozhe Shi36458962013-02-06 16:19:57 -08001430 rc = get_battery_voltage(&vbat_uv);
1431 if (rc < 0) {
1432 pr_err("adc vbat failed err = %d\n", rc);
1433 return soc;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001434 }
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001435 if (soc == 0 && vbat_uv > chip->v_cutoff_uv) {
1436 pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
1437 vbat_uv, chip->v_cutoff_uv);
1438 return 1;
1439 } else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
1440 pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
1441 vbat_uv, chip->v_cutoff_uv);
1442 return 0;
1443 } else {
1444 pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
1445 soc, vbat_uv, chip->v_cutoff_uv);
1446 return soc;
1447 }
1448}
1449
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001450static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
1451 struct raw_soc_params *raw,
1452 int batt_temp)
1453{
Xiaozhe Shie118c692012-09-24 15:17:43 -07001454 int soc, new_ocv_uv;
1455 int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
1456 struct soc_params params;
1457
1458 calculate_soc_params(chip, raw, &params, batt_temp);
1459 /* calculate remaining usable charge */
1460 remaining_usable_charge_uah = params.ocv_charge_uah
1461 - params.cc_uah
1462 - params.uuc_uah;
1463
1464 pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
1465 if (params.fcc_uah - params.uuc_uah <= 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001466 pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001467 params.fcc_uah,
1468 params.uuc_uah);
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001469 new_calculated_soc = 0;
1470 goto done_calculating;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001471 }
1472
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001473 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1474 (params.fcc_uah - params.uuc_uah));
1475
Xiaozhe Shie118c692012-09-24 15:17:43 -07001476 if (chip->first_time_calc_soc && soc < 0) {
1477 /*
1478 * first time calcualtion and the pon ocv is too low resulting
1479 * in a bad soc. Adjust ocv to get 0 soc
1480 */
1481 pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
1482 find_ocv_for_soc(chip, &params, batt_temp, 0, &new_ocv_uv);
1483 chip->last_ocv_uv = new_ocv_uv;
1484
1485 remaining_usable_charge_uah = params.ocv_charge_uah
1486 - params.cc_uah
1487 - params.uuc_uah;
1488
1489 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1490 (params.fcc_uah
1491 - params.uuc_uah));
1492 pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
1493 soc, chip->last_ocv_uv);
1494 }
1495
1496 if (soc > 100)
1497 soc = 100;
1498
1499 if (soc < 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001500 pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001501 remaining_usable_charge_uah,
1502 params.ocv_charge_uah,
1503 params.cc_uah, params.uuc_uah);
1504
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001505 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 -07001506 chip->last_ocv_uv, batt_temp,
1507 params.fcc_uah, soc);
1508 soc = 0;
1509 }
1510
1511 mutex_lock(&chip->soc_invalidation_mutex);
1512 shutdown_soc = chip->shutdown_soc;
1513
1514 if (chip->first_time_calc_soc && soc != shutdown_soc
1515 && is_shutdown_soc_within_limits(chip, soc)) {
1516 /*
1517 * soc for the first time - use shutdown soc
1518 * to adjust pon ocv since it is a small percent away from
1519 * the real soc
1520 */
1521 pr_debug("soc = %d before forcing shutdown_soc = %d\n",
1522 soc, shutdown_soc);
1523 find_ocv_for_soc(chip, &params, batt_temp,
1524 shutdown_soc, &new_ocv_uv);
1525 chip->pon_ocv_uv = chip->last_ocv_uv;
1526 chip->last_ocv_uv = new_ocv_uv;
1527
1528 remaining_usable_charge_uah = params.ocv_charge_uah
1529 - params.cc_uah
1530 - params.uuc_uah;
1531
1532 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1533 (params.fcc_uah
1534 - params.uuc_uah));
1535
1536 pr_debug("DONE for shutdown_soc = %d soc is %d, adjusted ocv to %duV\n",
1537 shutdown_soc, soc, chip->last_ocv_uv);
1538 }
1539 mutex_unlock(&chip->soc_invalidation_mutex);
1540
1541 pr_debug("SOC before adjustment = %d\n", soc);
1542 new_calculated_soc = adjust_soc(chip, &params, soc, batt_temp);
1543
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001544 /* clamp soc due to BMS HW inaccuracies in pm8941v2.0 */
1545 if (chip->revision1 == 0 && chip->revision2 == 0)
1546 new_calculated_soc = clamp_soc_based_on_voltage(chip,
1547 new_calculated_soc);
1548
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001549done_calculating:
Xiaozhe Shie118c692012-09-24 15:17:43 -07001550 if (new_calculated_soc != chip->calculated_soc
1551 && chip->bms_psy.name != NULL) {
1552 power_supply_changed(&chip->bms_psy);
1553 pr_debug("power supply changed\n");
1554 }
1555
1556 chip->calculated_soc = new_calculated_soc;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001557 pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001558 chip->first_time_calc_soc = 0;
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001559 get_current_time(&chip->last_recalc_time);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001560 return chip->calculated_soc;
1561}
1562
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001563static int calculate_soc_from_voltage(struct qpnp_bms_chip *chip)
1564{
1565 int voltage_range_uv, voltage_remaining_uv, voltage_based_soc;
Xiaozhe Shi36458962013-02-06 16:19:57 -08001566 int rc, vbat_uv;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001567
Xiaozhe Shi36458962013-02-06 16:19:57 -08001568 rc = get_battery_voltage(&vbat_uv);
1569 if (rc < 0) {
1570 pr_err("adc vbat failed err = %d\n", rc);
1571 return rc;
1572 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001573 voltage_range_uv = chip->max_voltage_uv - chip->v_cutoff_uv;
1574 voltage_remaining_uv = vbat_uv - chip->v_cutoff_uv;
1575 voltage_based_soc = voltage_remaining_uv * 100 / voltage_range_uv;
1576
1577 voltage_based_soc = clamp(voltage_based_soc, 0, 100);
1578
1579 if (chip->prev_voltage_based_soc != voltage_based_soc
1580 && chip->bms_psy.name != NULL) {
1581 power_supply_changed(&chip->bms_psy);
1582 pr_debug("power supply changed\n");
1583 }
1584 chip->prev_voltage_based_soc = voltage_based_soc;
1585
1586 pr_debug("vbat used = %duv\n", vbat_uv);
1587 pr_debug("Calculated voltage based soc = %d\n", voltage_based_soc);
1588 return voltage_based_soc;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001589}
1590
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001591static int recalculate_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001592{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001593 int batt_temp, rc, soc;
1594 struct qpnp_vadc_result result;
1595 struct raw_soc_params raw;
1596
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001597 wake_lock(&chip->soc_wake_lock);
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001598 if (chip->use_voltage_soc) {
1599 soc = calculate_soc_from_voltage(chip);
1600 } else {
1601 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1602 if (rc) {
1603 pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
1604 LR_MUX1_BATT_THERM, rc);
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001605 soc = chip->calculated_soc;
1606 } else {
1607 pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
1608 result.physical,
1609 result.measurement);
1610 batt_temp = (int)result.physical;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001611
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001612 mutex_lock(&chip->last_ocv_uv_mutex);
1613 read_soc_params_raw(chip, &raw, batt_temp);
1614 soc = calculate_state_of_charge(chip, &raw, batt_temp);
1615 mutex_unlock(&chip->last_ocv_uv_mutex);
1616 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001617 }
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001618 wake_unlock(&chip->soc_wake_lock);
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001619 return soc;
1620}
1621
1622static void calculate_soc_work(struct work_struct *work)
1623{
1624 struct qpnp_bms_chip *chip = container_of(work,
1625 struct qpnp_bms_chip,
1626 calculate_soc_delayed_work.work);
1627 int soc = recalculate_soc(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001628
1629 if (soc < chip->low_soc_calc_threshold)
1630 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1631 round_jiffies_relative(msecs_to_jiffies
1632 (chip->low_soc_calculate_soc_ms)));
1633 else
1634 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1635 round_jiffies_relative(msecs_to_jiffies
1636 (chip->calculate_soc_ms)));
1637}
1638
Xiaozhe Shie118c692012-09-24 15:17:43 -07001639static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
1640 int soc)
1641{
1642 u8 temp;
1643 int rc;
1644 int iavg_ma = chip->prev_uuc_iavg_ma;
1645
1646 if (iavg_ma > IAVG_START)
1647 temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
1648 else
1649 temp = 0;
1650
1651 rc = qpnp_write_wrapper(chip, &temp,
1652 chip->base + IAVG_STORAGE_REG, 1);
1653
1654 if (soc == 0)
1655 temp = SOC_ZERO;
1656 else
1657 temp = soc;
1658
1659 /* don't store soc if temperature is below 5degC */
1660 if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
1661 rc = qpnp_write_wrapper(chip, &temp,
1662 chip->base + SOC_STORAGE_REG, 1);
1663}
1664
1665#define SOC_CATCHUP_SEC_MAX 600
1666#define SOC_CATCHUP_SEC_PER_PERCENT 60
1667#define MAX_CATCHUP_SOC (SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
1668static int scale_soc_while_chg(struct qpnp_bms_chip *chip,
1669 int delta_time_us, int new_soc, int prev_soc)
1670{
1671 int chg_time_sec;
1672 int catch_up_sec;
1673 int scaled_soc;
1674 int numerator;
1675
1676 /*
1677 * The device must be charging for reporting a higher soc, if
1678 * not ignore this soc and continue reporting the prev_soc.
1679 * Also don't report a high value immediately slowly scale the
1680 * value from prev_soc to the new soc based on a charge time
1681 * weighted average
1682 */
1683
1684 /* if not charging, return last soc */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001685 if (!is_battery_charging(chip))
Xiaozhe Shie118c692012-09-24 15:17:43 -07001686 return prev_soc;
1687
1688 chg_time_sec = DIV_ROUND_UP(chip->charge_time_us, USEC_PER_SEC);
1689 catch_up_sec = DIV_ROUND_UP(chip->catch_up_time_us, USEC_PER_SEC);
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001690 if (catch_up_sec == 0)
1691 return new_soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001692 pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
1693
1694 /*
1695 * if charging for more than catch_up time, simply return
1696 * new soc
1697 */
1698 if (chg_time_sec > catch_up_sec)
1699 return new_soc;
1700
1701 numerator = (catch_up_sec - chg_time_sec) * prev_soc
1702 + chg_time_sec * new_soc;
1703 scaled_soc = numerator / catch_up_sec;
1704
1705 pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
1706 chg_time_sec, new_soc, prev_soc, scaled_soc);
1707
1708 return scaled_soc;
1709}
1710
1711/*
1712 * bms_fake_battery is set in setups where a battery emulator is used instead
1713 * of a real battery. This makes the bms driver report a different/fake value
1714 * regardless of the calculated state of charge.
1715 */
1716static int bms_fake_battery = -EINVAL;
1717module_param(bms_fake_battery, int, 0644);
1718
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001719static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
1720{
1721 pr_debug("Reported voltage based soc = %d\n",
1722 chip->prev_voltage_based_soc);
1723 return chip->prev_voltage_based_soc;
1724}
1725
1726static int report_cc_based_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001727{
1728 int soc;
1729 int delta_time_us;
1730 struct timespec now;
1731 struct qpnp_vadc_result result;
1732 int batt_temp;
1733 int rc;
1734
Xiaozhe Shie118c692012-09-24 15:17:43 -07001735 soc = chip->calculated_soc;
1736
1737 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1738
1739 if (rc) {
1740 pr_err("error reading adc channel = %d, rc = %d\n",
1741 LR_MUX1_BATT_THERM, rc);
1742 return rc;
1743 }
1744 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1745 result.measurement);
1746 batt_temp = (int)result.physical;
1747
1748 do_posix_clock_monotonic_gettime(&now);
1749 if (chip->t_soc_queried.tv_sec != 0) {
1750 delta_time_us
1751 = (now.tv_sec - chip->t_soc_queried.tv_sec) * USEC_PER_SEC
1752 + (now.tv_nsec - chip->t_soc_queried.tv_nsec) / 1000;
1753 } else {
1754 /* calculation for the first time */
1755 delta_time_us = 0;
1756 }
1757
1758 /*
1759 * account for charge time - limit it to SOC_CATCHUP_SEC to
1760 * avoid overflows when charging continues for extended periods
1761 */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001762 if (is_battery_charging(chip)) {
Xiaozhe Shie118c692012-09-24 15:17:43 -07001763 if (chip->charge_time_us == 0) {
1764 /*
1765 * calculating soc for the first time
1766 * after start of chg. Initialize catchup time
1767 */
1768 if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
1769 chip->catch_up_time_us =
1770 (soc - chip->last_soc)
1771 * SOC_CATCHUP_SEC_PER_PERCENT
1772 * USEC_PER_SEC;
1773 else
1774 chip->catch_up_time_us =
1775 SOC_CATCHUP_SEC_MAX * USEC_PER_SEC;
1776
1777 if (chip->catch_up_time_us < 0)
1778 chip->catch_up_time_us = 0;
1779 }
1780
1781 /* add charge time */
1782 if (chip->charge_time_us < SOC_CATCHUP_SEC_MAX * USEC_PER_SEC)
1783 chip->charge_time_us += delta_time_us;
1784
1785 /* end catchup if calculated soc and last soc are same */
1786 if (chip->last_soc == soc)
1787 chip->catch_up_time_us = 0;
1788 }
1789
1790 /* last_soc < soc ... scale and catch up */
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001791 if (chip->last_soc != -EINVAL && chip->last_soc < soc && soc != 100)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001792 soc = scale_soc_while_chg(chip, delta_time_us,
1793 soc, chip->last_soc);
1794
1795 pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
1796 chip->last_soc, chip->calculated_soc, soc);
1797 chip->last_soc = soc;
1798 backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
1799 pr_debug("Reported SOC = %d\n", chip->last_soc);
1800 chip->t_soc_queried = now;
1801
1802 return chip->last_soc;
1803}
1804
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001805static int report_state_of_charge(struct qpnp_bms_chip *chip)
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001806{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001807 if (bms_fake_battery != -EINVAL) {
1808 pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
1809 return bms_fake_battery;
1810 } else if (chip->use_voltage_soc)
1811 return report_voltage_based_soc(chip);
1812 else
1813 return report_cc_based_soc(chip);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001814}
1815
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001816/* Returns capacity as a SoC percentage between 0 and 100 */
1817static int get_prop_bms_capacity(struct qpnp_bms_chip *chip)
1818{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001819 return report_state_of_charge(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001820}
1821
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001822/* Returns estimated max current that the battery can supply in uA */
1823static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
1824{
1825 return chip->ibat_max_ua;
1826}
1827
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001828/* Returns instantaneous current in uA */
1829static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
1830{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001831 int rc, result_ua;
1832
1833 rc = get_battery_current(chip, &result_ua);
1834 if (rc) {
1835 pr_err("failed to get current: %d\n", rc);
1836 return rc;
1837 }
1838 return result_ua;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001839}
1840
1841/* Returns full charge design in uAh */
1842static int get_prop_bms_charge_full_design(struct qpnp_bms_chip *chip)
1843{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001844 return chip->fcc;
1845}
1846
1847static bool get_prop_bms_online(struct qpnp_bms_chip *chip)
1848{
1849 return chip->online;
1850}
1851
1852static int get_prop_bms_status(struct qpnp_bms_chip *chip)
1853{
1854 return chip->charger_status;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001855}
1856
1857static void set_prop_bms_online(struct qpnp_bms_chip *chip, bool online)
1858{
1859 chip->online = online;
1860}
1861
1862static void set_prop_bms_status(struct qpnp_bms_chip *chip, int status)
1863{
1864 chip->charger_status = status;
1865}
1866
1867static void qpnp_bms_external_power_changed(struct power_supply *psy)
1868{
1869}
1870
1871static int qpnp_bms_power_get_property(struct power_supply *psy,
1872 enum power_supply_property psp,
1873 union power_supply_propval *val)
1874{
1875 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1876 bms_psy);
1877
1878 switch (psp) {
1879 case POWER_SUPPLY_PROP_CAPACITY:
1880 val->intval = get_prop_bms_capacity(chip);
1881 break;
1882 case POWER_SUPPLY_PROP_CURRENT_NOW:
1883 val->intval = get_prop_bms_current_now(chip);
1884 break;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001885 case POWER_SUPPLY_PROP_CURRENT_MAX:
1886 val->intval = get_prop_bms_current_max(chip);
1887 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001888 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1889 val->intval = get_prop_bms_charge_full_design(chip);
1890 break;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001891 case POWER_SUPPLY_PROP_STATUS:
1892 val->intval = get_prop_bms_status(chip);
1893 break;
1894 case POWER_SUPPLY_PROP_ONLINE:
1895 val->intval = get_prop_bms_online(chip);
1896 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001897 default:
1898 return -EINVAL;
1899 }
1900 return 0;
1901}
1902
1903static int qpnp_bms_power_set_property(struct power_supply *psy,
1904 enum power_supply_property psp,
1905 const union power_supply_propval *val)
1906{
1907 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1908 bms_psy);
1909
1910 switch (psp) {
1911 case POWER_SUPPLY_PROP_ONLINE:
1912 set_prop_bms_online(chip, val->intval);
1913 break;
1914 case POWER_SUPPLY_PROP_STATUS:
1915 set_prop_bms_status(chip, (bool)val->intval);
1916 break;
1917 default:
1918 return -EINVAL;
1919 }
1920 return 0;
1921}
1922
Xiaozhe Shibdf14742012-12-05 12:41:48 -08001923#define OCV_USE_LIMIT_EN BIT(7)
1924static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
1925 int low_voltage_threshold,
1926 int high_voltage_threshold)
1927{
1928 uint16_t low_voltage_raw, high_voltage_raw;
1929 int rc;
1930
1931 low_voltage_raw = convert_vbatt_uv_to_raw(chip,
1932 low_voltage_threshold);
1933 high_voltage_raw = convert_vbatt_uv_to_raw(chip,
1934 high_voltage_threshold);
1935 rc = qpnp_write_wrapper(chip, (u8 *)&low_voltage_raw,
1936 chip->base + BMS1_OCV_USE_LOW_LIMIT_THR0, 2);
1937 if (rc) {
1938 pr_err("Failed to set ocv low voltage threshold: %d\n", rc);
1939 return rc;
1940 }
1941 rc = qpnp_write_wrapper(chip, (u8 *)&high_voltage_raw,
1942 chip->base + BMS1_OCV_USE_HIGH_LIMIT_THR0, 2);
1943 if (rc) {
1944 pr_err("Failed to set ocv high voltage threshold: %d\n", rc);
1945 return rc;
1946 }
1947 rc = qpnp_masked_write(chip, BMS1_OCV_USE_LIMIT_CTL,
1948 OCV_USE_LIMIT_EN, OCV_USE_LIMIT_EN);
1949 if (rc) {
1950 pr_err("Failed to enabled ocv voltage thresholds: %d\n", rc);
1951 return rc;
1952 }
1953 pr_debug("ocv low threshold set to %d uv or 0x%x raw\n",
1954 low_voltage_threshold, low_voltage_raw);
1955 pr_debug("ocv high threshold set to %d uv or 0x%x raw\n",
1956 high_voltage_threshold, high_voltage_raw);
1957 return 0;
1958}
1959
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001960static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
1961{
1962 int rc;
1963 u8 temp;
1964
1965 if (chip->ignore_shutdown_soc) {
1966 chip->shutdown_soc_invalid = 1;
1967 chip->shutdown_soc = 0;
1968 chip->shutdown_iavg_ma = 0;
1969 } else {
1970 rc = qpnp_read_wrapper(chip, &temp,
1971 chip->base + IAVG_STORAGE_REG, 1);
1972 if (rc) {
1973 pr_err("failed to read addr = %d %d assuming %d\n",
1974 chip->base + IAVG_STORAGE_REG, rc,
1975 IAVG_START);
1976 chip->shutdown_iavg_ma = IAVG_START;
1977 } else {
1978 if (temp == 0) {
1979 chip->shutdown_iavg_ma = IAVG_START;
1980 } else {
1981 chip->shutdown_iavg_ma = IAVG_START
1982 + IAVG_STEP_SIZE_MA * (temp + 1);
1983 }
1984 }
1985
1986 rc = qpnp_read_wrapper(chip, &temp,
1987 chip->base + SOC_STORAGE_REG, 1);
1988 if (rc) {
1989 pr_err("failed to read addr = %d %d\n",
1990 chip->base + SOC_STORAGE_REG, rc);
1991 } else {
1992 chip->shutdown_soc = temp;
1993
1994 if (chip->shutdown_soc == 0) {
1995 pr_debug("No shutdown soc available\n");
1996 chip->shutdown_soc_invalid = 1;
1997 chip->shutdown_iavg_ma = 0;
1998 } else if (chip->shutdown_soc == SOC_ZERO) {
1999 chip->shutdown_soc = 0;
2000 }
2001 }
2002 }
2003
2004 pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
2005 chip->shutdown_soc,
2006 chip->shutdown_iavg_ma,
2007 chip->shutdown_soc_invalid);
2008}
2009
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002010#define PALLADIUM_ID_MIN 0x7F40
2011#define PALLADIUM_ID_MAX 0x7F5A
2012#define DESAY_5200_ID_MIN 0x7F7F
2013#define DESAY_5200_ID_MAX 0x802F
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002014static int32_t read_battery_id(struct qpnp_bms_chip *chip)
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002015{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002016 int rc;
2017 struct qpnp_vadc_result result;
2018
2019 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2020 if (rc) {
2021 pr_err("error reading batt id channel = %d, rc = %d\n",
2022 LR_MUX2_BAT_ID, rc);
2023 return rc;
2024 }
2025 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
2026 result.measurement);
2027 pr_debug("raw_code = 0x%x\n", result.adc_code);
2028 return result.adc_code;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002029}
2030
2031static int set_battery_data(struct qpnp_bms_chip *chip)
2032{
2033 int64_t battery_id;
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002034 struct bms_battery_data *batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002035
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002036 if (chip->batt_type == BATT_DESAY) {
2037 batt_data = &desay_5200_data;
2038 } else if (chip->batt_type == BATT_PALLADIUM) {
2039 batt_data = &palladium_1500_data;
2040 } else if (chip->batt_type == BATT_OEM) {
2041 batt_data = &oem_batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002042 } else {
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002043 battery_id = read_battery_id(chip);
2044 if (battery_id < 0) {
2045 pr_err("cannot read battery id err = %lld\n",
2046 battery_id);
2047 return battery_id;
2048 }
2049
2050 if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
2051 battery_id)) {
2052 batt_data = &palladium_1500_data;
2053 } else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
2054 battery_id)) {
2055 batt_data = &desay_5200_data;
2056 } else {
2057 pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
2058 battery_id);
2059 batt_data = &palladium_1500_data;
2060 }
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002061 }
2062
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002063 chip->fcc = batt_data->fcc;
2064 chip->fcc_temp_lut = batt_data->fcc_temp_lut;
2065 chip->fcc_sf_lut = batt_data->fcc_sf_lut;
2066 chip->pc_temp_ocv_lut = batt_data->pc_temp_ocv_lut;
2067 chip->pc_sf_lut = batt_data->pc_sf_lut;
2068 chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
2069 chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
2070
2071 if (chip->pc_temp_ocv_lut == NULL) {
2072 pr_err("temp ocv lut table is NULL\n");
2073 return -EINVAL;
2074 }
2075 return 0;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002076}
2077
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002078#define SPMI_PROP_READ(chip_prop, qpnp_spmi_property, retval) \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002079do { \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002080 retval = of_property_read_u32(chip->spmi->dev.of_node, \
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002081 "qcom," qpnp_spmi_property, \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002082 &chip->chip_prop); \
2083 if (retval) { \
2084 pr_err("Error reading " #qpnp_spmi_property \
2085 " property %d\n", rc); \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002086 return -EINVAL; \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002087 } \
2088} while (0)
2089
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002090static inline int bms_read_properties(struct qpnp_bms_chip *chip)
2091{
2092 int rc;
2093
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002094 SPMI_PROP_READ(r_sense_uohm, "r-sense-uohm", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002095 SPMI_PROP_READ(v_cutoff_uv, "v-cutoff-uv", rc);
2096 SPMI_PROP_READ(max_voltage_uv, "max-voltage-uv", rc);
2097 SPMI_PROP_READ(r_conn_mohm, "r-conn-mohm", rc);
2098 SPMI_PROP_READ(chg_term_ua, "chg-term-ua", rc);
2099 SPMI_PROP_READ(shutdown_soc_valid_limit,
2100 "shutdown-soc-valid-limit", rc);
2101 SPMI_PROP_READ(adjust_soc_high_threshold,
2102 "adjust-soc-high-threshold", rc);
2103 SPMI_PROP_READ(adjust_soc_low_threshold,
2104 "adjust-soc-low-threshold", rc);
2105 SPMI_PROP_READ(batt_type, "batt-type", rc);
2106 SPMI_PROP_READ(low_soc_calc_threshold,
2107 "low-soc-calculate-soc-threshold", rc);
2108 SPMI_PROP_READ(low_soc_calculate_soc_ms,
2109 "low-soc-calculate-soc-ms", rc);
2110 SPMI_PROP_READ(calculate_soc_ms, "calculate-soc-ms", rc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002111 chip->use_external_rsense = of_property_read_bool(
2112 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002113 "qcom,use-external-rsense");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002114 chip->ignore_shutdown_soc = of_property_read_bool(
2115 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002116 "qcom,ignore-shutdown-soc");
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002117 chip->use_voltage_soc = of_property_read_bool(chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002118 "qcom,use-voltage-soc");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002119 chip->use_ocv_thresholds = of_property_read_bool(
2120 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002121 "qcom,use-ocv-thresholds");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002122 SPMI_PROP_READ(ocv_high_threshold_uv,
2123 "ocv-voltage-high-threshold-uv", rc);
2124 SPMI_PROP_READ(ocv_low_threshold_uv,
2125 "ocv-voltage-low-threshold-uv", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002126
2127 if (chip->adjust_soc_low_threshold >= 45)
2128 chip->adjust_soc_low_threshold = 45;
2129
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002130 pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
2131 chip->r_sense_uohm, chip->v_cutoff_uv,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002132 chip->max_voltage_uv);
2133 pr_debug("r_conn:%d, shutdown_soc: %d, adjust_soc_low:%d\n",
2134 chip->r_conn_mohm, chip->shutdown_soc_valid_limit,
2135 chip->adjust_soc_low_threshold);
2136 pr_debug("adjust_soc_high:%d, chg_term_ua:%d, batt_type:%d\n",
2137 chip->adjust_soc_high_threshold, chip->chg_term_ua,
2138 chip->batt_type);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08002139 pr_debug("ignore_shutdown_soc:%d, use_voltage_soc:%d\n",
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002140 chip->ignore_shutdown_soc, chip->use_voltage_soc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002141 pr_debug("use external rsense: %d\n", chip->use_external_rsense);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002142 return 0;
2143}
2144
2145static inline void bms_initialize_constants(struct qpnp_bms_chip *chip)
2146{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002147 chip->prev_pc_unusable = -EINVAL;
2148 chip->soc_at_cv = -EINVAL;
2149 chip->calculated_soc = -EINVAL;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002150 chip->last_soc = -EINVAL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07002151 chip->last_soc_est = -EINVAL;
Xiaozhe Shif36d2862013-01-04 10:17:35 -08002152 chip->last_cc_uah = INT_MIN;
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -08002153 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
2154 chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002155 chip->first_time_calc_soc = 1;
2156 chip->first_time_calc_uuc = 1;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002157}
2158
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002159#define REG_OFFSET_PERP_TYPE 0x04
2160#define REG_OFFSET_PERP_SUBTYPE 0x05
2161#define BMS_BMS_TYPE 0xD
2162#define BMS_BMS_SUBTYPE 0x1
2163#define BMS_IADC_TYPE 0x8
2164#define BMS_IADC_SUBTYPE 0x3
2165
2166static int register_spmi(struct qpnp_bms_chip *chip, struct spmi_device *spmi)
2167{
2168 struct spmi_resource *spmi_resource;
2169 struct resource *resource;
2170 int rc;
2171 u8 type, subtype;
2172
2173 chip->dev = &(spmi->dev);
2174 chip->spmi = spmi;
2175
2176 spmi_for_each_container_dev(spmi_resource, spmi) {
2177 if (!spmi_resource) {
2178 pr_err("qpnp_bms: spmi resource absent\n");
2179 return -ENXIO;
2180 }
2181
2182 resource = spmi_get_resource(spmi, spmi_resource,
2183 IORESOURCE_MEM, 0);
2184 if (!(resource && resource->start)) {
2185 pr_err("node %s IO resource absent!\n",
2186 spmi->dev.of_node->full_name);
2187 return -ENXIO;
2188 }
2189
2190 rc = qpnp_read_wrapper(chip, &type,
2191 resource->start + REG_OFFSET_PERP_TYPE, 1);
2192 if (rc) {
2193 pr_err("Peripheral type read failed rc=%d\n", rc);
2194 return rc;
2195 }
2196 rc = qpnp_read_wrapper(chip, &subtype,
2197 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2198 if (rc) {
2199 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2200 return rc;
2201 }
2202
2203 if (type == BMS_BMS_TYPE && subtype == BMS_BMS_SUBTYPE) {
2204 chip->base = resource->start;
2205 } else if (type == BMS_IADC_TYPE
2206 && subtype == BMS_IADC_SUBTYPE) {
2207 chip->iadc_base = resource->start;
2208 } else {
2209 pr_err("Invalid peripheral start=0x%x type=0x%x, subtype=0x%x\n",
2210 resource->start, type, subtype);
2211 }
2212 }
2213
2214 if (chip->base == 0) {
2215 dev_err(&spmi->dev, "BMS peripheral was not registered\n");
2216 return -EINVAL;
2217 }
2218 if (chip->iadc_base == 0) {
2219 dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
2220 return -EINVAL;
2221 }
2222
2223 return 0;
2224}
2225
2226#define ADC_CH_SEL_MASK 0x7
2227static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
2228{
2229 u8 iadc_channel_select;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002230 int32_t rds_rsense_nohm;
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002231 int rc;
2232
2233 rc = qpnp_read_wrapper(chip, &iadc_channel_select,
2234 chip->iadc_base + IADC1_BMS_ADC_CH_SEL_CTL, 1);
2235 if (rc) {
2236 pr_err("Error reading bms_iadc channel register %d\n", rc);
2237 return rc;
2238 }
2239
2240 iadc_channel_select &= ADC_CH_SEL_MASK;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002241 if (iadc_channel_select != EXTERNAL_RSENSE
2242 && iadc_channel_select != INTERNAL_RSENSE) {
2243 pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
2244 iadc_channel_select);
2245 return -EINVAL;
2246 }
2247
2248 if (chip->use_external_rsense) {
2249 pr_debug("External rsense selected\n");
2250 if (iadc_channel_select == INTERNAL_RSENSE) {
2251 pr_debug("Internal rsense detected; Changing rsense to external\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002252 rc = qpnp_masked_write_iadc(chip,
2253 IADC1_BMS_ADC_CH_SEL_CTL,
2254 ADC_CH_SEL_MASK,
2255 EXTERNAL_RSENSE);
2256 if (rc) {
2257 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2258 IADC1_BMS_ADC_CH_SEL_CTL,
2259 EXTERNAL_RSENSE, rc);
2260 return rc;
2261 }
2262 reset_cc(chip);
2263 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002264 } else {
2265 pr_debug("Internal rsense selected\n");
2266 if (iadc_channel_select == EXTERNAL_RSENSE) {
2267 pr_debug("External rsense detected; Changing rsense to internal\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002268 rc = qpnp_masked_write_iadc(chip,
2269 IADC1_BMS_ADC_CH_SEL_CTL,
2270 ADC_CH_SEL_MASK,
2271 INTERNAL_RSENSE);
2272 if (rc) {
2273 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2274 IADC1_BMS_ADC_CH_SEL_CTL,
2275 INTERNAL_RSENSE, rc);
2276 return rc;
2277 }
2278 reset_cc(chip);
2279 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002280
2281 rc = qpnp_iadc_get_rsense(&rds_rsense_nohm);
2282 if (rc) {
2283 pr_err("Unable to read RDS resistance value from IADC; rc = %d\n",
2284 rc);
2285 return rc;
2286 }
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002287 chip->r_sense_uohm = rds_rsense_nohm/1000;
2288 pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
2289 rds_rsense_nohm, chip->r_sense_uohm);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002290 }
2291 return 0;
2292}
2293
2294static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002295{
2296 struct qpnp_bms_chip *chip;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002297 int rc, vbatt;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002298
2299 chip = kzalloc(sizeof *chip, GFP_KERNEL);
2300
2301 if (chip == NULL) {
2302 pr_err("kzalloc() failed.\n");
2303 return -ENOMEM;
2304 }
2305
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002306 rc = qpnp_vadc_is_ready();
2307 if (rc) {
2308 pr_info("vadc not ready: %d, deferring probe\n", rc);
2309 goto error_read;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002310 }
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002311
2312 rc = qpnp_iadc_is_ready();
2313 if (rc) {
2314 pr_info("iadc not ready: %d, deferring probe\n", rc);
2315 goto error_read;
2316 }
2317
2318 rc = register_spmi(chip, spmi);
2319 if (rc) {
2320 pr_err("error registering spmi resource %d\n", rc);
2321 goto error_resource;
2322 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002323
2324 rc = qpnp_read_wrapper(chip, &chip->revision1,
2325 chip->base + BMS1_REVISION1, 1);
2326 if (rc) {
2327 pr_err("error reading version register %d\n", rc);
2328 goto error_read;
2329 }
2330
2331 rc = qpnp_read_wrapper(chip, &chip->revision2,
2332 chip->base + BMS1_REVISION2, 1);
2333 if (rc) {
2334 pr_err("Error reading version register %d\n", rc);
2335 goto error_read;
2336 }
Xiaozhe Shia045a562012-11-28 16:55:39 -08002337 pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002338
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002339 rc = bms_read_properties(chip);
2340 if (rc) {
2341 pr_err("Unable to read all bms properties, rc = %d\n", rc);
2342 goto error_read;
2343 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002344
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002345 rc = read_iadc_channel_select(chip);
2346 if (rc) {
2347 pr_err("Unable to get iadc selected channel = %d\n", rc);
2348 goto error_read;
2349 }
2350
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002351 if (chip->use_ocv_thresholds) {
2352 rc = set_ocv_voltage_thresholds(chip,
2353 chip->ocv_low_threshold_uv,
2354 chip->ocv_high_threshold_uv);
2355 if (rc) {
2356 pr_err("Could not set ocv voltage thresholds: %d\n",
2357 rc);
2358 goto error_read;
2359 }
2360 }
2361
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002362 rc = set_battery_data(chip);
2363 if (rc) {
2364 pr_err("Bad battery data %d\n", rc);
2365 goto error_read;
2366 }
2367
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002368 bms_initialize_constants(chip);
2369
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002370 mutex_init(&chip->bms_output_lock);
2371 mutex_init(&chip->last_ocv_uv_mutex);
2372 mutex_init(&chip->soc_invalidation_mutex);
2373
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002374 wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
2375 "qpnp_soc_lock");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002376 INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
2377 calculate_soc_work);
2378
2379 read_shutdown_soc_and_iavg(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002380
2381 dev_set_drvdata(&spmi->dev, chip);
2382 device_init_wakeup(&spmi->dev, 1);
2383
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002384 calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
2385
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002386 /* setup & register the battery power supply */
2387 chip->bms_psy.name = "bms";
2388 chip->bms_psy.type = POWER_SUPPLY_TYPE_BMS;
2389 chip->bms_psy.properties = msm_bms_power_props;
2390 chip->bms_psy.num_properties = ARRAY_SIZE(msm_bms_power_props);
2391 chip->bms_psy.get_property = qpnp_bms_power_get_property;
2392 chip->bms_psy.set_property = qpnp_bms_power_set_property;
2393 chip->bms_psy.external_power_changed =
2394 qpnp_bms_external_power_changed;
2395 chip->bms_psy.supplied_to = qpnp_bms_supplicants;
2396 chip->bms_psy.num_supplicants = ARRAY_SIZE(qpnp_bms_supplicants);
2397
2398 rc = power_supply_register(chip->dev, &chip->bms_psy);
2399
2400 if (rc < 0) {
2401 pr_err("power_supply_register bms failed rc = %d\n", rc);
2402 goto unregister_dc;
2403 }
2404
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002405 vbatt = 0;
Xiaozhe Shi36458962013-02-06 16:19:57 -08002406 rc = get_battery_voltage(&vbatt);
2407 if (rc) {
2408 pr_err("error reading vbat_sns adc channel = %d, rc = %d\n",
2409 VBAT_SNS, rc);
2410 goto unregister_dc;
2411 }
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002412
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002413 pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u\n",
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002414 get_prop_bms_capacity(chip),
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002415 vbatt, chip->last_ocv_uv, chip->r_sense_uohm);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002416 return 0;
2417
2418unregister_dc:
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002419 wake_lock_destroy(&chip->soc_wake_lock);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002420 power_supply_unregister(&chip->bms_psy);
2421 dev_set_drvdata(&spmi->dev, NULL);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002422error_resource:
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002423error_read:
2424 kfree(chip);
2425 return rc;
2426}
2427
2428static int __devexit
2429qpnp_bms_remove(struct spmi_device *spmi)
2430{
2431 struct qpnp_bms_chip *chip = dev_get_drvdata(&spmi->dev);
2432
2433 dev_set_drvdata(&spmi->dev, NULL);
2434 kfree(chip);
2435 return 0;
2436}
2437
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002438static int bms_resume(struct device *dev)
2439{
2440 int rc;
2441 unsigned long soc_calc_period;
2442 unsigned long time_since_last_recalc;
2443 unsigned long tm_now_sec;
2444 struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
2445
2446 rc = get_current_time(&tm_now_sec);
2447 if (rc) {
2448 pr_err("Could not read current time: %d\n", rc);
2449 } else if (tm_now_sec > chip->last_recalc_time) {
2450 time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
2451 pr_debug("Time since last recalc: %lu\n",
2452 time_since_last_recalc);
2453 if (chip->calculated_soc < chip->low_soc_calc_threshold)
2454 soc_calc_period = chip->low_soc_calculate_soc_ms;
2455 else
2456 soc_calc_period = chip->calculate_soc_ms;
2457
2458 if (time_since_last_recalc >= soc_calc_period) {
2459 chip->last_recalc_time = tm_now_sec;
2460 recalculate_soc(chip);
2461 }
2462 }
2463 return 0;
2464}
2465
2466static const struct dev_pm_ops qpnp_bms_pm_ops = {
2467 .resume = bms_resume,
2468};
2469
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002470static struct spmi_driver qpnp_bms_driver = {
2471 .probe = qpnp_bms_probe,
2472 .remove = __devexit_p(qpnp_bms_remove),
2473 .driver = {
2474 .name = QPNP_BMS_DEV_NAME,
2475 .owner = THIS_MODULE,
2476 .of_match_table = qpnp_bms_match_table,
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002477 .pm = &qpnp_bms_pm_ops,
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002478 },
2479};
2480
2481static int __init qpnp_bms_init(void)
2482{
2483 pr_info("QPNP BMS INIT\n");
2484 return spmi_driver_register(&qpnp_bms_driver);
2485}
2486
2487static void __exit qpnp_bms_exit(void)
2488{
2489 pr_info("QPNP BMS EXIT\n");
2490 return spmi_driver_unregister(&qpnp_bms_driver);
2491}
2492
2493module_init(qpnp_bms_init);
2494module_exit(qpnp_bms_exit);
2495
2496MODULE_DESCRIPTION("QPNP BMS Driver");
2497MODULE_LICENSE("GPL v2");
2498MODULE_ALIAS("platform:" QPNP_BMS_DEV_NAME);