blob: 85a310ac14ebb53c896d1f22810d8fea04c25128 [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 Shid0a79542012-11-06 10:00:38 -0800673static s64 cc_uv_to_uvh(s64 cc_uv)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700674{
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800675 return div_s64(cc_uv * CC_READING_TICKS,
Xiaozhe Shie118c692012-09-24 15:17:43 -0700676 SLEEP_CLK_HZ * SECONDS_PER_HOUR);
677}
678
679/**
680 * calculate_cc-
681 * @chip: the bms chip pointer
682 * @cc: the cc reading from bms h/w
683 * @val: return value
684 * @coulomb_counter: adjusted coulomb counter for 100%
685 *
686 * RETURNS: in val pointer coulomb counter based charger in uAh
687 * (micro Amp hour)
688 */
689static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
690{
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800691 int64_t cc_voltage_uv, cc_uvh, cc_uah;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700692 struct qpnp_iadc_calib calibration;
693
694 qpnp_iadc_get_gain_and_offset(&calibration);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700695 cc_voltage_uv = cc;
696 cc_voltage_uv -= chip->cc_reading_at_100;
697 pr_debug("cc = %lld. after subtracting 0x%llx cc = %lld\n",
698 cc, chip->cc_reading_at_100,
699 cc_voltage_uv);
700 cc_voltage_uv = cc_to_uv(cc_voltage_uv);
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800701 cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
702 calibration.gain_raw
703 - calibration.offset_raw);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700704 pr_debug("cc_voltage_uv = %lld uv\n", cc_voltage_uv);
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800705 cc_uvh = cc_uv_to_uvh(cc_voltage_uv);
706 pr_debug("cc_uvh = %lld micro_volt_hour\n", cc_uvh);
707 cc_uah = div_s64(cc_uvh * 1000000LL, chip->r_sense_uohm);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700708 /* cc_raw had 4 bits of extra precision.
709 By now it should be within 32 bit range */
710 return (int)cc_uah;
711}
712
713static int get_rbatt(struct qpnp_bms_chip *chip,
714 int soc_rbatt_mohm, int batt_temp)
715{
716 int rbatt_mohm, scalefactor;
717
718 rbatt_mohm = chip->default_rbatt_mohm;
719 pr_debug("rbatt before scaling = %d\n", rbatt_mohm);
720 if (chip->rbatt_sf_lut == NULL) {
721 pr_debug("RBATT = %d\n", rbatt_mohm);
722 return rbatt_mohm;
723 }
724 /* Convert the batt_temp to DegC from deciDegC */
725 batt_temp = batt_temp / 10;
726 scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
727 batt_temp, soc_rbatt_mohm);
728 pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
729 scalefactor, batt_temp, soc_rbatt_mohm);
730 rbatt_mohm = (rbatt_mohm * scalefactor) / 100;
731
732 rbatt_mohm += chip->r_conn_mohm;
733 pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
734 chip->r_conn_mohm, rbatt_mohm);
735
736 pr_debug("RBATT = %d\n", rbatt_mohm);
737 return rbatt_mohm;
738}
739
740static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800741 int *iavg_ua, int delta_time_s)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700742{
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800743 int delta_cc_uah = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700744
Xiaozhe Shie118c692012-09-24 15:17:43 -0700745 /* if anything fails report the previous iavg_ua */
746 *iavg_ua = chip->prev_iavg_ua;
747
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800748 if (chip->last_cc_uah == INT_MIN) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700749 get_battery_current(chip, iavg_ua);
750 goto out;
751 }
752
Xiaozhe Shie118c692012-09-24 15:17:43 -0700753 /* use the previous iavg if called within 15 seconds */
754 if (delta_time_s < 15) {
755 *iavg_ua = chip->prev_iavg_ua;
756 goto out;
757 }
758
759 delta_cc_uah = cc_uah - chip->last_cc_uah;
760
761 *iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
762
Xiaozhe Shie118c692012-09-24 15:17:43 -0700763out:
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800764 pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700765 /* remember the iavg */
766 chip->prev_iavg_ua = *iavg_ua;
767
768 /* remember cc_uah */
769 chip->last_cc_uah = cc_uah;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700770}
771
772static int calculate_termination_uuc(struct qpnp_bms_chip *chip,
773 struct soc_params *params,
774 int batt_temp, int uuc_iavg_ma,
775 int *ret_pc_unusable)
776{
777 int unusable_uv, pc_unusable, uuc_uah;
778 int i = 0;
779 int ocv_mv;
780 int batt_temp_degc = batt_temp / 10;
781 int rbatt_mohm;
782 int delta_uv;
783 int prev_delta_uv = 0;
784 int prev_rbatt_mohm = 0;
785 int uuc_rbatt_mohm;
786
787 for (i = 0; i <= 100; i++) {
788 ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
789 batt_temp_degc, i);
790 rbatt_mohm = get_rbatt(chip, i, batt_temp);
791 unusable_uv = (rbatt_mohm * uuc_iavg_ma)
792 + (chip->v_cutoff_uv);
793 delta_uv = ocv_mv * 1000 - unusable_uv;
794
795 pr_debug("soc = %d ocv = %d rbat = %d u_uv = %d delta_v = %d\n",
796 i, ocv_mv, rbatt_mohm, unusable_uv, delta_uv);
797
798 if (delta_uv > 0)
799 break;
800
801 prev_delta_uv = delta_uv;
802 prev_rbatt_mohm = rbatt_mohm;
803 }
804
805 uuc_rbatt_mohm = linear_interpolate(rbatt_mohm, delta_uv,
806 prev_rbatt_mohm, prev_delta_uv,
807 0);
808
809 unusable_uv = (uuc_rbatt_mohm * uuc_iavg_ma) + (chip->v_cutoff_uv);
810
811 pc_unusable = calculate_pc(chip, unusable_uv, batt_temp);
812 uuc_uah = (params->fcc_uah * pc_unusable) / 100;
813 pr_debug("For uuc_iavg_ma = %d, unusable_rbatt = %d unusable_uv = %d unusable_pc = %d uuc = %d\n",
814 uuc_iavg_ma,
815 uuc_rbatt_mohm, unusable_uv,
816 pc_unusable, uuc_uah);
817 *ret_pc_unusable = pc_unusable;
818 return uuc_uah;
819}
820
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800821#define TIME_PER_PERCENT_UUC 60
Xiaozhe Shie118c692012-09-24 15:17:43 -0700822static int adjust_uuc(struct qpnp_bms_chip *chip,
823 struct soc_params *params,
824 int new_pc_unusable,
825 int new_uuc_uah,
826 int batt_temp)
827{
828 int new_unusable_mv, new_iavg_ma;
829 int batt_temp_degc = batt_temp / 10;
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800830 int max_percent_change;
831
832 max_percent_change = max(params->delta_time_s
833 / TIME_PER_PERCENT_UUC, 1);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700834
835 if (chip->prev_pc_unusable == -EINVAL
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800836 || abs(chip->prev_pc_unusable - new_pc_unusable)
837 <= max_percent_change) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700838 chip->prev_pc_unusable = new_pc_unusable;
839 return new_uuc_uah;
840 }
841
842 /* the uuc is trying to change more than 1% restrict it */
843 if (new_pc_unusable > chip->prev_pc_unusable)
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800844 chip->prev_pc_unusable += max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700845 else
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800846 chip->prev_pc_unusable -= max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700847
848 new_uuc_uah = (params->fcc_uah * chip->prev_pc_unusable) / 100;
849
850 /* also find update the iavg_ma accordingly */
851 new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
852 batt_temp_degc, chip->prev_pc_unusable);
853 if (new_unusable_mv < chip->v_cutoff_uv/1000)
854 new_unusable_mv = chip->v_cutoff_uv/1000;
855
856 new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800857 / params->rbatt_mohm;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700858 if (new_iavg_ma == 0)
859 new_iavg_ma = 1;
860 chip->prev_uuc_iavg_ma = new_iavg_ma;
861 pr_debug("Restricting UUC to %d (%d%%) unusable_mv = %d iavg_ma = %d\n",
862 new_uuc_uah, chip->prev_pc_unusable,
863 new_unusable_mv, new_iavg_ma);
864
865 return new_uuc_uah;
866}
867
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800868#define MIN_IAVG_MA 250
Xiaozhe Shie118c692012-09-24 15:17:43 -0700869#define MIN_SECONDS_FOR_VALID_SAMPLE 20
870static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
871 struct soc_params *params,
872 int batt_temp)
873{
874 int uuc_uah_iavg;
875 int i;
876 int uuc_iavg_ma = params->iavg_ua / 1000;
877 int pc_unusable;
878
879 /*
880 * if called first time, fill all the samples with
881 * the shutdown_iavg_ma
882 */
883 if (chip->first_time_calc_uuc && chip->shutdown_iavg_ma != 0) {
884 pr_debug("Using shutdown_iavg_ma = %d in all samples\n",
885 chip->shutdown_iavg_ma);
886 for (i = 0; i < IAVG_SAMPLES; i++)
887 chip->iavg_samples_ma[i] = chip->shutdown_iavg_ma;
888
889 chip->iavg_index = 0;
890 chip->iavg_num_samples = IAVG_SAMPLES;
891 }
892
893 /*
894 * if charging use a nominal avg current to keep
895 * a reasonable UUC while charging
896 */
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800897 if (uuc_iavg_ma < MIN_IAVG_MA)
898 uuc_iavg_ma = MIN_IAVG_MA;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700899 chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
900 chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
901 chip->iavg_num_samples++;
902 if (chip->iavg_num_samples >= IAVG_SAMPLES)
903 chip->iavg_num_samples = IAVG_SAMPLES;
904
905 /* now that this sample is added calcualte the average */
906 uuc_iavg_ma = 0;
907 if (chip->iavg_num_samples != 0) {
908 for (i = 0; i < chip->iavg_num_samples; i++) {
909 pr_debug("iavg_samples_ma[%d] = %d\n", i,
910 chip->iavg_samples_ma[i]);
911 uuc_iavg_ma += chip->iavg_samples_ma[i];
912 }
913
914 uuc_iavg_ma = DIV_ROUND_CLOSEST(uuc_iavg_ma,
915 chip->iavg_num_samples);
916 }
917
Xiaozhe Shi20640b52013-01-03 11:49:30 -0800918 /*
919 * if we're in bms reset mode, force uuc to be 3% of fcc
920 */
921 if (bms_reset)
922 return (params->fcc_uah * 3) / 100;
923
Xiaozhe Shi75e5efe2013-02-07 09:51:43 -0800924 uuc_uah_iavg = calculate_termination_uuc(chip, params, batt_temp,
925 uuc_iavg_ma, &pc_unusable);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700926 pr_debug("uuc_iavg_ma = %d uuc with iavg = %d\n",
927 uuc_iavg_ma, uuc_uah_iavg);
928
929 chip->prev_uuc_iavg_ma = uuc_iavg_ma;
930 /* restrict the uuc such that it can increase only by one percent */
931 uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
932 uuc_uah_iavg, batt_temp);
933
934 chip->first_time_calc_uuc = 0;
935 return uuc_uah_iavg;
936}
937
938static void find_ocv_for_soc(struct qpnp_bms_chip *chip,
939 struct soc_params *params,
940 int batt_temp,
941 int shutdown_soc,
942 int *ret_ocv_uv)
943{
944 s64 ocv_charge_uah;
945 int pc, new_pc;
946 int batt_temp_degc = batt_temp / 10;
947 int ocv_uv;
948
949 ocv_charge_uah = (s64)shutdown_soc
950 * (params->fcc_uah - params->uuc_uah);
951 ocv_charge_uah = div_s64(ocv_charge_uah, 100)
952 + params->cc_uah + params->uuc_uah;
953 pc = DIV_ROUND_CLOSEST((int)ocv_charge_uah * 100, params->fcc_uah);
954 pc = clamp(pc, 0, 100);
955
956 ocv_uv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
957
958 pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
959 shutdown_soc, params->fcc_uah,
960 params->uuc_uah, (int)ocv_charge_uah,
961 pc, ocv_uv);
962 new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv_uv);
963 pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv_uv);
964
965 while (abs(new_pc - pc) > 1) {
966 int delta_mv = 5;
967
968 if (new_pc > pc)
969 delta_mv = -1 * delta_mv;
970
971 ocv_uv = ocv_uv + delta_mv;
972 new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
973 batt_temp_degc, ocv_uv);
974 pr_debug("test revlookup pc = %d for ocv = %d\n",
975 new_pc, ocv_uv);
976 }
977
978 *ret_ocv_uv = ocv_uv * 1000;
979 params->ocv_charge_uah = (int)ocv_charge_uah;
980}
981
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800982static int get_current_time(unsigned long *now_tm_sec)
983{
984 struct rtc_time tm;
985 struct rtc_device *rtc;
986 int rc;
987
988 rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
989 if (rtc == NULL) {
990 pr_err("%s: unable to open rtc device (%s)\n",
991 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
992 rc = -EINVAL;
993 goto close_time;
994 }
995
996 rc = rtc_read_time(rtc, &tm);
997 if (rc) {
998 pr_err("Error reading rtc device (%s) : %d\n",
999 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1000 goto close_time;
1001 }
1002
1003 rc = rtc_valid_tm(&tm);
1004 if (rc) {
1005 pr_err("Invalid RTC time (%s): %d\n",
1006 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1007 goto close_time;
1008 }
1009 rtc_tm_to_time(&tm, now_tm_sec);
1010
1011close_time:
1012 rtc_class_close(rtc);
1013 return rc;
1014}
1015
1016static int calculate_delta_time(struct qpnp_bms_chip *chip, int *delta_time_s)
1017{
1018 unsigned long now_tm_sec = 0;
1019
1020 /* default to delta time = 0 if anything fails */
1021 *delta_time_s = 0;
1022
1023 get_current_time(&now_tm_sec);
1024
1025 *delta_time_s = (now_tm_sec - chip->tm_sec);
1026 pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
1027 chip->tm_sec, now_tm_sec, *delta_time_s);
1028
1029 /* remember this time */
1030 chip->tm_sec = now_tm_sec;
1031 return 0;
1032}
1033
Xiaozhe Shie118c692012-09-24 15:17:43 -07001034static void calculate_soc_params(struct qpnp_bms_chip *chip,
1035 struct raw_soc_params *raw,
1036 struct soc_params *params,
1037 int batt_temp)
1038{
1039 int soc_rbatt;
1040
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001041 calculate_delta_time(chip, &params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001042 params->fcc_uah = calculate_fcc(chip, batt_temp);
1043 pr_debug("FCC = %uuAh batt_temp = %d\n", params->fcc_uah, batt_temp);
1044
1045 /* calculate remainging charge */
1046 params->ocv_charge_uah = calculate_ocv_charge(
1047 chip, raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001048 params->fcc_uah);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001049 pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
1050
1051 /* calculate cc micro_volt_hour */
1052 params->cc_uah = calculate_cc(chip, raw->cc);
1053 pr_debug("cc_uah = %duAh raw->cc = %llx cc = %lld after subtracting %llx\n",
1054 params->cc_uah, raw->cc,
1055 (int64_t)raw->cc - chip->cc_reading_at_100,
1056 chip->cc_reading_at_100);
1057
1058 soc_rbatt = ((params->ocv_charge_uah - params->cc_uah) * 100)
1059 / params->fcc_uah;
1060 if (soc_rbatt < 0)
1061 soc_rbatt = 0;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001062 params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001063
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001064 calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
1065 params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001066
1067 params->uuc_uah = calculate_unusable_charge_uah(chip, params,
1068 batt_temp);
1069 pr_debug("UUC = %uuAh\n", params->uuc_uah);
1070}
1071
1072static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
1073{
1074 if (chip->shutdown_soc_invalid) {
1075 pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
1076 return 0;
1077 }
1078
1079 if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
1080 pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
1081 chip->shutdown_soc, soc,
1082 chip->shutdown_soc_valid_limit);
1083 chip->shutdown_soc_invalid = 1;
1084 return 0;
1085 }
1086
1087 return 1;
1088}
1089
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001090#define BMS_OVERRIDE_MODE_EN_BIT BIT(7)
1091#define EN_VBAT_BIT BIT(0)
1092#define OVERRIDE_MODE_DELAY_MS 20
1093static int override_mode_batt_v_and_i(
1094 struct qpnp_bms_chip *chip, int *ibat_ua, int *vbat_uv)
1095{
1096 int16_t vsense_raw, vbat_raw;
1097 int vsense_uv, rc;
1098 u8 delay;
1099
1100 mutex_lock(&chip->bms_output_lock);
1101
1102 delay = 0x00;
1103 rc = qpnp_write_wrapper(chip, &delay,
1104 chip->base + BMS1_S1_DELAY_CTL, 1);
1105 if (rc)
1106 pr_err("unable to write into BMS1_S1_DELAY, rc: %d\n", rc);
1107
1108 rc = qpnp_masked_write(chip, BMS1_MODE_CTL,
1109 BMS_OVERRIDE_MODE_EN_BIT | EN_VBAT_BIT,
1110 BMS_OVERRIDE_MODE_EN_BIT | EN_VBAT_BIT);
1111 if (rc)
1112 pr_err("unable to write into BMS1_MODE_CTL, rc: %d\n", rc);
1113
1114 msleep(OVERRIDE_MODE_DELAY_MS);
1115
1116 lock_output_data(chip);
1117 qpnp_read_wrapper(chip, (u8 *)&vsense_raw,
1118 chip->base + BMS1_VSENSE_AVG_DATA0, 2);
1119 qpnp_read_wrapper(chip, (u8 *)&vbat_raw,
1120 chip->base + BMS1_VBAT_AVG_DATA0, 2);
1121 unlock_output_data(chip);
1122
1123 rc = qpnp_masked_write(chip, BMS1_MODE_CTL,
1124 BMS_OVERRIDE_MODE_EN_BIT | EN_VBAT_BIT, 0);
1125
1126 delay = 0x0B;
1127 rc = qpnp_write_wrapper(chip, &delay,
1128 chip->base + BMS1_S1_DELAY_CTL, 1);
1129 if (rc)
1130 pr_err("unable to write into BMS1_S1_DELAY, rc: %d\n", rc);
1131
1132 mutex_unlock(&chip->bms_output_lock);
1133
1134 *vbat_uv = convert_vbatt_raw_to_uv(chip, vbat_raw);
1135 vsense_uv = convert_vsense_to_uv(chip, vsense_raw);
Xiaozhe Shid0a79542012-11-06 10:00:38 -08001136 *ibat_ua = div_s64(vsense_uv * 1000000LL, (int)chip->r_sense_uohm);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001137
1138 pr_debug("vsense_raw = 0x%x vbat_raw = 0x%x ibat_ua = %d vbat_uv = %d\n",
1139 (uint16_t)vsense_raw, (uint16_t)vbat_raw,
1140 *ibat_ua, *vbat_uv);
1141 return 0;
1142}
1143
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001144static bool is_battery_charging(struct qpnp_bms_chip *chip)
1145{
1146 union power_supply_propval ret = {0,};
1147
1148 if (chip->batt_psy == NULL)
1149 chip->batt_psy = power_supply_get_by_name("battery");
1150 if (chip->batt_psy) {
1151 /* if battery has been registered, use the status property */
1152 chip->batt_psy->get_property(chip->batt_psy,
1153 POWER_SUPPLY_PROP_STATUS, &ret);
1154 return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
1155 }
1156
1157 /* Default to false if the battery power supply is not registered. */
1158 pr_debug("battery power supply is not registered\n");
1159 return false;
1160}
1161
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001162static bool is_batfet_open(struct qpnp_bms_chip *chip)
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001163{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001164 union power_supply_propval ret = {0,};
1165
1166 if (chip->batt_psy == NULL)
1167 chip->batt_psy = power_supply_get_by_name("battery");
1168 if (chip->batt_psy) {
1169 /* if battery has been registered, use the status property */
1170 chip->batt_psy->get_property(chip->batt_psy,
1171 POWER_SUPPLY_PROP_STATUS, &ret);
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001172 return ret.intval == POWER_SUPPLY_STATUS_FULL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001173 }
1174
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001175 /* Default to true if the battery power supply is not registered. */
1176 pr_debug("battery power supply is not registered\n");
1177 return true;
1178}
1179
1180static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
1181 int *ibat_ua, int *vbat_uv)
1182{
1183 int rc;
1184
1185 if (is_batfet_open(chip)) {
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001186 pr_debug("batfet is open using separate vbat and ibat meas\n");
1187 rc = get_battery_voltage(vbat_uv);
1188 if (rc < 0) {
1189 pr_err("adc vbat failed err = %d\n", rc);
1190 return rc;
1191 }
1192 rc = get_battery_current(chip, ibat_ua);
1193 if (rc < 0) {
1194 pr_err("bms ibat failed err = %d\n", rc);
1195 return rc;
1196 }
1197 } else {
1198 return override_mode_batt_v_and_i(chip, ibat_ua, vbat_uv);
1199 }
1200
1201 return 0;
1202}
1203
1204static int bound_soc(int soc)
1205{
1206 soc = max(0, soc);
1207 soc = min(100, soc);
1208 return soc;
1209}
1210
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001211#define IBAT_TOL_MASK 0x0F
1212#define OCV_TOL_MASK 0xF0
1213#define IBAT_TOL_DEFAULT 0x03
1214#define IBAT_TOL_NOCHG 0x0F
1215#define OCV_TOL_DEFAULT 0x20
1216#define OCV_TOL_NO_OCV 0x00
1217static int stop_ocv_updates(struct qpnp_bms_chip *chip)
1218{
1219 pr_debug("stopping ocv updates\n");
1220 return qpnp_masked_write(chip, BMS1_TOL_CTL,
1221 OCV_TOL_MASK, OCV_TOL_NO_OCV);
1222}
1223
1224static int reset_bms_for_test(struct qpnp_bms_chip *chip)
1225{
1226 int ibat_ua, vbat_uv, rc;
1227 int ocv_est_uv;
1228
1229 if (!chip) {
1230 pr_err("BMS driver has not been initialized yet!\n");
1231 return -EINVAL;
1232 }
1233
1234 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1235
1236 ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
1237 pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
1238 chip->last_ocv_uv = ocv_est_uv;
1239 chip->last_soc = -EINVAL;
1240 reset_cc(chip);
1241 chip->last_cc_uah = INT_MIN;
1242 stop_ocv_updates(chip);
1243
1244 pr_debug("bms reset to ocv = %duv vbat_ua = %d ibat_ua = %d\n",
1245 chip->last_ocv_uv, vbat_uv, ibat_ua);
1246
1247 return rc;
1248}
1249
1250static int bms_reset_set(const char *val, const struct kernel_param *kp)
1251{
1252 int rc;
1253
1254 rc = param_set_bool(val, kp);
1255 if (rc) {
1256 pr_err("Unable to set bms_reset: %d\n", rc);
1257 return rc;
1258 }
1259
1260 if (*(bool *)kp->arg) {
1261 struct power_supply *bms_psy = power_supply_get_by_name("bms");
1262 struct qpnp_bms_chip *chip = container_of(bms_psy,
1263 struct qpnp_bms_chip, bms_psy);
1264
1265 rc = reset_bms_for_test(chip);
1266 if (rc) {
1267 pr_err("Unable to modify bms_reset: %d\n", rc);
1268 return rc;
1269 }
1270 }
1271 return 0;
1272}
1273
1274static struct kernel_param_ops bms_reset_ops = {
1275 .set = bms_reset_set,
1276 .get = param_get_bool,
1277};
1278
1279module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
1280
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001281static int charging_adjustments(struct qpnp_bms_chip *chip,
1282 struct soc_params *params, int soc,
1283 int vbat_uv, int ibat_ua, int batt_temp)
1284{
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001285 int chg_soc;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001286 int batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001287
1288 if (chip->soc_at_cv == -EINVAL) {
1289 /* In constant current charging return the calc soc */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001290 if (batt_terminal_uv <= chip->max_voltage_uv)
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001291 pr_debug("CC CHG SOC %d\n", soc);
1292
1293 /* Note the CC to CV point */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001294 if (batt_terminal_uv >= chip->max_voltage_uv) {
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001295 chip->soc_at_cv = soc;
1296 chip->prev_chg_soc = soc;
1297 chip->ibat_at_cv_ua = ibat_ua;
1298 pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
1299 ibat_ua, soc);
1300 }
1301 return soc;
1302 }
1303
1304 /*
1305 * battery is in CV phase - begin liner inerpolation of soc based on
1306 * battery charge current
1307 */
1308
1309 /*
1310 * if voltage lessened (possibly because of a system load)
1311 * keep reporting the prev chg soc
1312 */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001313 if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
1314 pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
1315 batt_terminal_uv,
1316 chip->max_voltage_uv, chip->prev_chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001317 return chip->prev_chg_soc;
1318 }
1319
1320 chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001321 100, -1 * chip->chg_term_ua,
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001322 ibat_ua);
Xiaozhe Shi78d0c532012-12-10 13:02:14 -08001323 chg_soc = bound_soc(chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001324
1325 /* always report a higher soc */
1326 if (chg_soc > chip->prev_chg_soc) {
1327 int new_ocv_uv;
1328
1329 chip->prev_chg_soc = chg_soc;
1330
1331 find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
1332 chip->last_ocv_uv = new_ocv_uv;
1333 pr_debug("CC CHG ADJ OCV = %d CHG SOC %d\n",
1334 new_ocv_uv,
1335 chip->prev_chg_soc);
1336 }
1337
1338 pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
1339 return chip->prev_chg_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001340}
1341
Xiaozhe Shie118c692012-09-24 15:17:43 -07001342static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
1343 int soc, int batt_temp)
1344{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001345 int ibat_ua = 0, vbat_uv = 0;
1346 int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
1347 int delta_ocv_uv = 0;
1348 int n = 0;
1349 int rc_new_uah = 0;
1350 int pc_new = 0;
1351 int soc_new = 0;
1352 int slope = 0;
1353 int rc = 0;
1354 int delta_ocv_uv_limit = 0;
1355
1356 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1357 if (rc < 0) {
1358 pr_err("simultaneous vbat ibat failed err = %d\n", rc);
1359 goto out;
1360 }
1361
1362 delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
1363
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001364 ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
1365
1366 chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
1367 / (params->rbatt_mohm);
1368
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001369 pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
1370 soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
1371 (s64)params->fcc_uah - params->uuc_uah);
1372 soc_est = bound_soc(soc_est);
1373
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001374 /* never adjust during bms reset mode */
1375 if (bms_reset) {
1376 pr_debug("bms reset mode, SOC adjustment skipped\n");
1377 goto out;
1378 }
1379
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001380 if (ibat_ua < 0 && !is_batfet_open(chip)) {
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001381 soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
1382 batt_temp);
1383 goto out;
1384 }
1385
1386 /*
1387 * do not adjust
1388 * if soc is same as what bms calculated
1389 * if soc_est is between 45 and 25, this is the flat portion of the
1390 * curve where soc_est is not so accurate. We generally don't want to
1391 * adjust when soc_est is inaccurate except for the cases when soc is
1392 * way far off (higher than 50 or lesser than 20).
1393 * Also don't adjust soc if it is above 90 becuase it might be pulled
1394 * low and cause a bad user experience
1395 */
1396 if (soc_est == soc
1397 || (is_between(45, chip->adjust_soc_low_threshold, soc_est)
1398 && is_between(50, chip->adjust_soc_low_threshold - 5, soc))
1399 || soc >= 90)
1400 goto out;
1401
1402 if (chip->last_soc_est == -EINVAL)
1403 chip->last_soc_est = soc;
1404
1405 n = min(200, max(1 , soc + soc_est + chip->last_soc_est));
1406 chip->last_soc_est = soc_est;
1407
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001408 pc = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001409 if (pc > 0) {
1410 pc_new = calculate_pc(chip,
1411 chip->last_ocv_uv - (++slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001412 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001413 while (pc_new == pc) {
1414 /* start taking 10mV steps */
1415 slope = slope + 10;
1416 pc_new = calculate_pc(chip,
1417 chip->last_ocv_uv - (slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001418 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001419 }
1420 } else {
1421 /*
1422 * pc is already at the lowest point,
1423 * assume 1 millivolt translates to 1% pc
1424 */
1425 pc = 1;
1426 pc_new = 0;
1427 slope = 1;
1428 }
1429
1430 delta_ocv_uv = div_s64((soc - soc_est) * (s64)slope * 1000,
1431 n * (pc - pc_new));
1432
1433 if (abs(delta_ocv_uv) > delta_ocv_uv_limit) {
1434 pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
1435 delta_ocv_uv_limit);
1436
1437 if (delta_ocv_uv > 0)
1438 delta_ocv_uv = delta_ocv_uv_limit;
1439 else
1440 delta_ocv_uv = -1 * delta_ocv_uv_limit;
1441 pr_debug("new delta ocv = %d\n", delta_ocv_uv);
1442 }
1443
1444 chip->last_ocv_uv -= delta_ocv_uv;
1445
1446 if (chip->last_ocv_uv >= chip->max_voltage_uv)
1447 chip->last_ocv_uv = chip->max_voltage_uv;
1448
1449 /* calculate the soc based on this new ocv */
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001450 pc_new = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001451 rc_new_uah = (params->fcc_uah * pc_new) / 100;
1452 soc_new = (rc_new_uah - params->cc_uah - params->uuc_uah)*100
1453 / (params->fcc_uah - params->uuc_uah);
1454 soc_new = bound_soc(soc_new);
1455
1456 /*
1457 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
1458 * soc = 0 should happen only when soc_est == 0
1459 */
1460 if (soc_new == 0 && soc_est != 0)
1461 soc_new = 1;
1462
1463 soc = soc_new;
1464
1465out:
1466 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",
1467 ibat_ua, vbat_uv, ocv_est_uv, pc_est,
1468 soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001469 pc_new, soc_new, params->rbatt_mohm, slope);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001470
Xiaozhe Shie118c692012-09-24 15:17:43 -07001471 return soc;
1472}
1473
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001474static int clamp_soc_based_on_voltage(struct qpnp_bms_chip *chip, int soc)
1475{
1476 int rc, vbat_uv;
1477 struct qpnp_vadc_result result;
1478
1479 rc = qpnp_vadc_read(VBAT_SNS, &result);
1480 if (rc) {
1481 pr_err("error reading vbat_sns adc channel = %d, rc = %d\n",
1482 VBAT_SNS, rc);
1483 return rc;
1484 }
1485
1486 vbat_uv = (int)result.physical;
1487 if (soc == 0 && vbat_uv > chip->v_cutoff_uv) {
1488 pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
1489 vbat_uv, chip->v_cutoff_uv);
1490 return 1;
1491 } else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
1492 pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
1493 vbat_uv, chip->v_cutoff_uv);
1494 return 0;
1495 } else {
1496 pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
1497 soc, vbat_uv, chip->v_cutoff_uv);
1498 return soc;
1499 }
1500}
1501
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001502static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
1503 struct raw_soc_params *raw,
1504 int batt_temp)
1505{
Xiaozhe Shie118c692012-09-24 15:17:43 -07001506 int soc, new_ocv_uv;
1507 int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
1508 struct soc_params params;
1509
1510 calculate_soc_params(chip, raw, &params, batt_temp);
1511 /* calculate remaining usable charge */
1512 remaining_usable_charge_uah = params.ocv_charge_uah
1513 - params.cc_uah
1514 - params.uuc_uah;
1515
1516 pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
1517 if (params.fcc_uah - params.uuc_uah <= 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001518 pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001519 params.fcc_uah,
1520 params.uuc_uah);
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001521 new_calculated_soc = 0;
1522 goto done_calculating;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001523 }
1524
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001525 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1526 (params.fcc_uah - params.uuc_uah));
1527
Xiaozhe Shie118c692012-09-24 15:17:43 -07001528 if (chip->first_time_calc_soc && soc < 0) {
1529 /*
1530 * first time calcualtion and the pon ocv is too low resulting
1531 * in a bad soc. Adjust ocv to get 0 soc
1532 */
1533 pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
1534 find_ocv_for_soc(chip, &params, batt_temp, 0, &new_ocv_uv);
1535 chip->last_ocv_uv = new_ocv_uv;
1536
1537 remaining_usable_charge_uah = params.ocv_charge_uah
1538 - params.cc_uah
1539 - params.uuc_uah;
1540
1541 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1542 (params.fcc_uah
1543 - params.uuc_uah));
1544 pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
1545 soc, chip->last_ocv_uv);
1546 }
1547
1548 if (soc > 100)
1549 soc = 100;
1550
1551 if (soc < 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001552 pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001553 remaining_usable_charge_uah,
1554 params.ocv_charge_uah,
1555 params.cc_uah, params.uuc_uah);
1556
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001557 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 -07001558 chip->last_ocv_uv, batt_temp,
1559 params.fcc_uah, soc);
1560 soc = 0;
1561 }
1562
1563 mutex_lock(&chip->soc_invalidation_mutex);
1564 shutdown_soc = chip->shutdown_soc;
1565
1566 if (chip->first_time_calc_soc && soc != shutdown_soc
1567 && is_shutdown_soc_within_limits(chip, soc)) {
1568 /*
1569 * soc for the first time - use shutdown soc
1570 * to adjust pon ocv since it is a small percent away from
1571 * the real soc
1572 */
1573 pr_debug("soc = %d before forcing shutdown_soc = %d\n",
1574 soc, shutdown_soc);
1575 find_ocv_for_soc(chip, &params, batt_temp,
1576 shutdown_soc, &new_ocv_uv);
1577 chip->pon_ocv_uv = chip->last_ocv_uv;
1578 chip->last_ocv_uv = new_ocv_uv;
1579
1580 remaining_usable_charge_uah = params.ocv_charge_uah
1581 - params.cc_uah
1582 - params.uuc_uah;
1583
1584 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1585 (params.fcc_uah
1586 - params.uuc_uah));
1587
1588 pr_debug("DONE for shutdown_soc = %d soc is %d, adjusted ocv to %duV\n",
1589 shutdown_soc, soc, chip->last_ocv_uv);
1590 }
1591 mutex_unlock(&chip->soc_invalidation_mutex);
1592
1593 pr_debug("SOC before adjustment = %d\n", soc);
1594 new_calculated_soc = adjust_soc(chip, &params, soc, batt_temp);
1595
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001596 /* clamp soc due to BMS HW inaccuracies in pm8941v2.0 */
1597 if (chip->revision1 == 0 && chip->revision2 == 0)
1598 new_calculated_soc = clamp_soc_based_on_voltage(chip,
1599 new_calculated_soc);
1600
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001601done_calculating:
Xiaozhe Shie118c692012-09-24 15:17:43 -07001602 if (new_calculated_soc != chip->calculated_soc
1603 && chip->bms_psy.name != NULL) {
1604 power_supply_changed(&chip->bms_psy);
1605 pr_debug("power supply changed\n");
1606 }
1607
1608 chip->calculated_soc = new_calculated_soc;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001609 pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001610 chip->first_time_calc_soc = 0;
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001611 get_current_time(&chip->last_recalc_time);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001612 return chip->calculated_soc;
1613}
1614
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001615static int read_vbat(struct qpnp_bms_chip *chip)
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001616{
1617 int rc;
1618 struct qpnp_vadc_result result;
1619
1620 rc = qpnp_vadc_read(VBAT_SNS, &result);
1621 if (rc) {
1622 pr_err("error reading vadc VBAT_SNS = %d, rc = %d\n",
1623 VBAT_SNS, rc);
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001624 return rc;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001625 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001626 pr_debug("read %duv from vadc\n", (int)result.physical);
1627 return (int)result.physical;
1628}
1629
1630static int calculate_soc_from_voltage(struct qpnp_bms_chip *chip)
1631{
1632 int voltage_range_uv, voltage_remaining_uv, voltage_based_soc;
1633 int vbat_uv;
1634
1635 vbat_uv = read_vbat(chip);
1636
1637 voltage_range_uv = chip->max_voltage_uv - chip->v_cutoff_uv;
1638 voltage_remaining_uv = vbat_uv - chip->v_cutoff_uv;
1639 voltage_based_soc = voltage_remaining_uv * 100 / voltage_range_uv;
1640
1641 voltage_based_soc = clamp(voltage_based_soc, 0, 100);
1642
1643 if (chip->prev_voltage_based_soc != voltage_based_soc
1644 && chip->bms_psy.name != NULL) {
1645 power_supply_changed(&chip->bms_psy);
1646 pr_debug("power supply changed\n");
1647 }
1648 chip->prev_voltage_based_soc = voltage_based_soc;
1649
1650 pr_debug("vbat used = %duv\n", vbat_uv);
1651 pr_debug("Calculated voltage based soc = %d\n", voltage_based_soc);
1652 return voltage_based_soc;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001653}
1654
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001655static int recalculate_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001656{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001657 int batt_temp, rc, soc;
1658 struct qpnp_vadc_result result;
1659 struct raw_soc_params raw;
1660
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001661 wake_lock(&chip->soc_wake_lock);
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001662 if (chip->use_voltage_soc) {
1663 soc = calculate_soc_from_voltage(chip);
1664 } else {
1665 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1666 if (rc) {
1667 pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
1668 LR_MUX1_BATT_THERM, rc);
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001669 soc = chip->calculated_soc;
1670 } else {
1671 pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
1672 result.physical,
1673 result.measurement);
1674 batt_temp = (int)result.physical;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001675
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001676 mutex_lock(&chip->last_ocv_uv_mutex);
1677 read_soc_params_raw(chip, &raw, batt_temp);
1678 soc = calculate_state_of_charge(chip, &raw, batt_temp);
1679 mutex_unlock(&chip->last_ocv_uv_mutex);
1680 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001681 }
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001682 wake_unlock(&chip->soc_wake_lock);
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001683 return soc;
1684}
1685
1686static void calculate_soc_work(struct work_struct *work)
1687{
1688 struct qpnp_bms_chip *chip = container_of(work,
1689 struct qpnp_bms_chip,
1690 calculate_soc_delayed_work.work);
1691 int soc = recalculate_soc(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001692
1693 if (soc < chip->low_soc_calc_threshold)
1694 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1695 round_jiffies_relative(msecs_to_jiffies
1696 (chip->low_soc_calculate_soc_ms)));
1697 else
1698 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1699 round_jiffies_relative(msecs_to_jiffies
1700 (chip->calculate_soc_ms)));
1701}
1702
Xiaozhe Shie118c692012-09-24 15:17:43 -07001703static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
1704 int soc)
1705{
1706 u8 temp;
1707 int rc;
1708 int iavg_ma = chip->prev_uuc_iavg_ma;
1709
1710 if (iavg_ma > IAVG_START)
1711 temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
1712 else
1713 temp = 0;
1714
1715 rc = qpnp_write_wrapper(chip, &temp,
1716 chip->base + IAVG_STORAGE_REG, 1);
1717
1718 if (soc == 0)
1719 temp = SOC_ZERO;
1720 else
1721 temp = soc;
1722
1723 /* don't store soc if temperature is below 5degC */
1724 if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
1725 rc = qpnp_write_wrapper(chip, &temp,
1726 chip->base + SOC_STORAGE_REG, 1);
1727}
1728
1729#define SOC_CATCHUP_SEC_MAX 600
1730#define SOC_CATCHUP_SEC_PER_PERCENT 60
1731#define MAX_CATCHUP_SOC (SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
1732static int scale_soc_while_chg(struct qpnp_bms_chip *chip,
1733 int delta_time_us, int new_soc, int prev_soc)
1734{
1735 int chg_time_sec;
1736 int catch_up_sec;
1737 int scaled_soc;
1738 int numerator;
1739
1740 /*
1741 * The device must be charging for reporting a higher soc, if
1742 * not ignore this soc and continue reporting the prev_soc.
1743 * Also don't report a high value immediately slowly scale the
1744 * value from prev_soc to the new soc based on a charge time
1745 * weighted average
1746 */
1747
1748 /* if not charging, return last soc */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001749 if (!is_battery_charging(chip))
Xiaozhe Shie118c692012-09-24 15:17:43 -07001750 return prev_soc;
1751
1752 chg_time_sec = DIV_ROUND_UP(chip->charge_time_us, USEC_PER_SEC);
1753 catch_up_sec = DIV_ROUND_UP(chip->catch_up_time_us, USEC_PER_SEC);
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001754 if (catch_up_sec == 0)
1755 return new_soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001756 pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
1757
1758 /*
1759 * if charging for more than catch_up time, simply return
1760 * new soc
1761 */
1762 if (chg_time_sec > catch_up_sec)
1763 return new_soc;
1764
1765 numerator = (catch_up_sec - chg_time_sec) * prev_soc
1766 + chg_time_sec * new_soc;
1767 scaled_soc = numerator / catch_up_sec;
1768
1769 pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
1770 chg_time_sec, new_soc, prev_soc, scaled_soc);
1771
1772 return scaled_soc;
1773}
1774
1775/*
1776 * bms_fake_battery is set in setups where a battery emulator is used instead
1777 * of a real battery. This makes the bms driver report a different/fake value
1778 * regardless of the calculated state of charge.
1779 */
1780static int bms_fake_battery = -EINVAL;
1781module_param(bms_fake_battery, int, 0644);
1782
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001783static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
1784{
1785 pr_debug("Reported voltage based soc = %d\n",
1786 chip->prev_voltage_based_soc);
1787 return chip->prev_voltage_based_soc;
1788}
1789
1790static int report_cc_based_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001791{
1792 int soc;
1793 int delta_time_us;
1794 struct timespec now;
1795 struct qpnp_vadc_result result;
1796 int batt_temp;
1797 int rc;
1798
Xiaozhe Shie118c692012-09-24 15:17:43 -07001799 soc = chip->calculated_soc;
1800
1801 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1802
1803 if (rc) {
1804 pr_err("error reading adc channel = %d, rc = %d\n",
1805 LR_MUX1_BATT_THERM, rc);
1806 return rc;
1807 }
1808 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1809 result.measurement);
1810 batt_temp = (int)result.physical;
1811
1812 do_posix_clock_monotonic_gettime(&now);
1813 if (chip->t_soc_queried.tv_sec != 0) {
1814 delta_time_us
1815 = (now.tv_sec - chip->t_soc_queried.tv_sec) * USEC_PER_SEC
1816 + (now.tv_nsec - chip->t_soc_queried.tv_nsec) / 1000;
1817 } else {
1818 /* calculation for the first time */
1819 delta_time_us = 0;
1820 }
1821
1822 /*
1823 * account for charge time - limit it to SOC_CATCHUP_SEC to
1824 * avoid overflows when charging continues for extended periods
1825 */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001826 if (is_battery_charging(chip)) {
Xiaozhe Shie118c692012-09-24 15:17:43 -07001827 if (chip->charge_time_us == 0) {
1828 /*
1829 * calculating soc for the first time
1830 * after start of chg. Initialize catchup time
1831 */
1832 if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
1833 chip->catch_up_time_us =
1834 (soc - chip->last_soc)
1835 * SOC_CATCHUP_SEC_PER_PERCENT
1836 * USEC_PER_SEC;
1837 else
1838 chip->catch_up_time_us =
1839 SOC_CATCHUP_SEC_MAX * USEC_PER_SEC;
1840
1841 if (chip->catch_up_time_us < 0)
1842 chip->catch_up_time_us = 0;
1843 }
1844
1845 /* add charge time */
1846 if (chip->charge_time_us < SOC_CATCHUP_SEC_MAX * USEC_PER_SEC)
1847 chip->charge_time_us += delta_time_us;
1848
1849 /* end catchup if calculated soc and last soc are same */
1850 if (chip->last_soc == soc)
1851 chip->catch_up_time_us = 0;
1852 }
1853
1854 /* last_soc < soc ... scale and catch up */
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001855 if (chip->last_soc != -EINVAL && chip->last_soc < soc && soc != 100)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001856 soc = scale_soc_while_chg(chip, delta_time_us,
1857 soc, chip->last_soc);
1858
1859 pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
1860 chip->last_soc, chip->calculated_soc, soc);
1861 chip->last_soc = soc;
1862 backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
1863 pr_debug("Reported SOC = %d\n", chip->last_soc);
1864 chip->t_soc_queried = now;
1865
1866 return chip->last_soc;
1867}
1868
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001869static int report_state_of_charge(struct qpnp_bms_chip *chip)
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001870{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001871 if (bms_fake_battery != -EINVAL) {
1872 pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
1873 return bms_fake_battery;
1874 } else if (chip->use_voltage_soc)
1875 return report_voltage_based_soc(chip);
1876 else
1877 return report_cc_based_soc(chip);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001878}
1879
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001880/* Returns capacity as a SoC percentage between 0 and 100 */
1881static int get_prop_bms_capacity(struct qpnp_bms_chip *chip)
1882{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001883 return report_state_of_charge(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001884}
1885
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001886/* Returns estimated max current that the battery can supply in uA */
1887static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
1888{
1889 return chip->ibat_max_ua;
1890}
1891
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001892/* Returns instantaneous current in uA */
1893static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
1894{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001895 int rc, result_ua;
1896
1897 rc = get_battery_current(chip, &result_ua);
1898 if (rc) {
1899 pr_err("failed to get current: %d\n", rc);
1900 return rc;
1901 }
1902 return result_ua;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001903}
1904
1905/* Returns full charge design in uAh */
1906static int get_prop_bms_charge_full_design(struct qpnp_bms_chip *chip)
1907{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001908 return chip->fcc;
1909}
1910
1911static bool get_prop_bms_online(struct qpnp_bms_chip *chip)
1912{
1913 return chip->online;
1914}
1915
1916static int get_prop_bms_status(struct qpnp_bms_chip *chip)
1917{
1918 return chip->charger_status;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001919}
1920
1921static void set_prop_bms_online(struct qpnp_bms_chip *chip, bool online)
1922{
1923 chip->online = online;
1924}
1925
1926static void set_prop_bms_status(struct qpnp_bms_chip *chip, int status)
1927{
1928 chip->charger_status = status;
1929}
1930
1931static void qpnp_bms_external_power_changed(struct power_supply *psy)
1932{
1933}
1934
1935static int qpnp_bms_power_get_property(struct power_supply *psy,
1936 enum power_supply_property psp,
1937 union power_supply_propval *val)
1938{
1939 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1940 bms_psy);
1941
1942 switch (psp) {
1943 case POWER_SUPPLY_PROP_CAPACITY:
1944 val->intval = get_prop_bms_capacity(chip);
1945 break;
1946 case POWER_SUPPLY_PROP_CURRENT_NOW:
1947 val->intval = get_prop_bms_current_now(chip);
1948 break;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001949 case POWER_SUPPLY_PROP_CURRENT_MAX:
1950 val->intval = get_prop_bms_current_max(chip);
1951 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001952 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1953 val->intval = get_prop_bms_charge_full_design(chip);
1954 break;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001955 case POWER_SUPPLY_PROP_STATUS:
1956 val->intval = get_prop_bms_status(chip);
1957 break;
1958 case POWER_SUPPLY_PROP_ONLINE:
1959 val->intval = get_prop_bms_online(chip);
1960 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001961 default:
1962 return -EINVAL;
1963 }
1964 return 0;
1965}
1966
1967static int qpnp_bms_power_set_property(struct power_supply *psy,
1968 enum power_supply_property psp,
1969 const union power_supply_propval *val)
1970{
1971 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1972 bms_psy);
1973
1974 switch (psp) {
1975 case POWER_SUPPLY_PROP_ONLINE:
1976 set_prop_bms_online(chip, val->intval);
1977 break;
1978 case POWER_SUPPLY_PROP_STATUS:
1979 set_prop_bms_status(chip, (bool)val->intval);
1980 break;
1981 default:
1982 return -EINVAL;
1983 }
1984 return 0;
1985}
1986
Xiaozhe Shibdf14742012-12-05 12:41:48 -08001987#define OCV_USE_LIMIT_EN BIT(7)
1988static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
1989 int low_voltage_threshold,
1990 int high_voltage_threshold)
1991{
1992 uint16_t low_voltage_raw, high_voltage_raw;
1993 int rc;
1994
1995 low_voltage_raw = convert_vbatt_uv_to_raw(chip,
1996 low_voltage_threshold);
1997 high_voltage_raw = convert_vbatt_uv_to_raw(chip,
1998 high_voltage_threshold);
1999 rc = qpnp_write_wrapper(chip, (u8 *)&low_voltage_raw,
2000 chip->base + BMS1_OCV_USE_LOW_LIMIT_THR0, 2);
2001 if (rc) {
2002 pr_err("Failed to set ocv low voltage threshold: %d\n", rc);
2003 return rc;
2004 }
2005 rc = qpnp_write_wrapper(chip, (u8 *)&high_voltage_raw,
2006 chip->base + BMS1_OCV_USE_HIGH_LIMIT_THR0, 2);
2007 if (rc) {
2008 pr_err("Failed to set ocv high voltage threshold: %d\n", rc);
2009 return rc;
2010 }
2011 rc = qpnp_masked_write(chip, BMS1_OCV_USE_LIMIT_CTL,
2012 OCV_USE_LIMIT_EN, OCV_USE_LIMIT_EN);
2013 if (rc) {
2014 pr_err("Failed to enabled ocv voltage thresholds: %d\n", rc);
2015 return rc;
2016 }
2017 pr_debug("ocv low threshold set to %d uv or 0x%x raw\n",
2018 low_voltage_threshold, low_voltage_raw);
2019 pr_debug("ocv high threshold set to %d uv or 0x%x raw\n",
2020 high_voltage_threshold, high_voltage_raw);
2021 return 0;
2022}
2023
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002024static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
2025{
2026 int rc;
2027 u8 temp;
2028
2029 if (chip->ignore_shutdown_soc) {
2030 chip->shutdown_soc_invalid = 1;
2031 chip->shutdown_soc = 0;
2032 chip->shutdown_iavg_ma = 0;
2033 } else {
2034 rc = qpnp_read_wrapper(chip, &temp,
2035 chip->base + IAVG_STORAGE_REG, 1);
2036 if (rc) {
2037 pr_err("failed to read addr = %d %d assuming %d\n",
2038 chip->base + IAVG_STORAGE_REG, rc,
2039 IAVG_START);
2040 chip->shutdown_iavg_ma = IAVG_START;
2041 } else {
2042 if (temp == 0) {
2043 chip->shutdown_iavg_ma = IAVG_START;
2044 } else {
2045 chip->shutdown_iavg_ma = IAVG_START
2046 + IAVG_STEP_SIZE_MA * (temp + 1);
2047 }
2048 }
2049
2050 rc = qpnp_read_wrapper(chip, &temp,
2051 chip->base + SOC_STORAGE_REG, 1);
2052 if (rc) {
2053 pr_err("failed to read addr = %d %d\n",
2054 chip->base + SOC_STORAGE_REG, rc);
2055 } else {
2056 chip->shutdown_soc = temp;
2057
2058 if (chip->shutdown_soc == 0) {
2059 pr_debug("No shutdown soc available\n");
2060 chip->shutdown_soc_invalid = 1;
2061 chip->shutdown_iavg_ma = 0;
2062 } else if (chip->shutdown_soc == SOC_ZERO) {
2063 chip->shutdown_soc = 0;
2064 }
2065 }
2066 }
2067
2068 pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
2069 chip->shutdown_soc,
2070 chip->shutdown_iavg_ma,
2071 chip->shutdown_soc_invalid);
2072}
2073
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002074#define PALLADIUM_ID_MIN 0x7F40
2075#define PALLADIUM_ID_MAX 0x7F5A
2076#define DESAY_5200_ID_MIN 0x7F7F
2077#define DESAY_5200_ID_MAX 0x802F
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002078static int32_t read_battery_id(struct qpnp_bms_chip *chip)
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002079{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002080 int rc;
2081 struct qpnp_vadc_result result;
2082
2083 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2084 if (rc) {
2085 pr_err("error reading batt id channel = %d, rc = %d\n",
2086 LR_MUX2_BAT_ID, rc);
2087 return rc;
2088 }
2089 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
2090 result.measurement);
2091 pr_debug("raw_code = 0x%x\n", result.adc_code);
2092 return result.adc_code;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002093}
2094
2095static int set_battery_data(struct qpnp_bms_chip *chip)
2096{
2097 int64_t battery_id;
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002098 struct bms_battery_data *batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002099
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002100 if (chip->batt_type == BATT_DESAY) {
2101 batt_data = &desay_5200_data;
2102 } else if (chip->batt_type == BATT_PALLADIUM) {
2103 batt_data = &palladium_1500_data;
2104 } else if (chip->batt_type == BATT_OEM) {
2105 batt_data = &oem_batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002106 } else {
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002107 battery_id = read_battery_id(chip);
2108 if (battery_id < 0) {
2109 pr_err("cannot read battery id err = %lld\n",
2110 battery_id);
2111 return battery_id;
2112 }
2113
2114 if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
2115 battery_id)) {
2116 batt_data = &palladium_1500_data;
2117 } else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
2118 battery_id)) {
2119 batt_data = &desay_5200_data;
2120 } else {
2121 pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
2122 battery_id);
2123 batt_data = &palladium_1500_data;
2124 }
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002125 }
2126
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002127 chip->fcc = batt_data->fcc;
2128 chip->fcc_temp_lut = batt_data->fcc_temp_lut;
2129 chip->fcc_sf_lut = batt_data->fcc_sf_lut;
2130 chip->pc_temp_ocv_lut = batt_data->pc_temp_ocv_lut;
2131 chip->pc_sf_lut = batt_data->pc_sf_lut;
2132 chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
2133 chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
2134
2135 if (chip->pc_temp_ocv_lut == NULL) {
2136 pr_err("temp ocv lut table is NULL\n");
2137 return -EINVAL;
2138 }
2139 return 0;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002140}
2141
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002142#define SPMI_PROP_READ(chip_prop, qpnp_spmi_property, retval) \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002143do { \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002144 retval = of_property_read_u32(chip->spmi->dev.of_node, \
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002145 "qcom," qpnp_spmi_property, \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002146 &chip->chip_prop); \
2147 if (retval) { \
2148 pr_err("Error reading " #qpnp_spmi_property \
2149 " property %d\n", rc); \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002150 return -EINVAL; \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002151 } \
2152} while (0)
2153
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002154static inline int bms_read_properties(struct qpnp_bms_chip *chip)
2155{
2156 int rc;
2157
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002158 SPMI_PROP_READ(r_sense_uohm, "r-sense-uohm", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002159 SPMI_PROP_READ(v_cutoff_uv, "v-cutoff-uv", rc);
2160 SPMI_PROP_READ(max_voltage_uv, "max-voltage-uv", rc);
2161 SPMI_PROP_READ(r_conn_mohm, "r-conn-mohm", rc);
2162 SPMI_PROP_READ(chg_term_ua, "chg-term-ua", rc);
2163 SPMI_PROP_READ(shutdown_soc_valid_limit,
2164 "shutdown-soc-valid-limit", rc);
2165 SPMI_PROP_READ(adjust_soc_high_threshold,
2166 "adjust-soc-high-threshold", rc);
2167 SPMI_PROP_READ(adjust_soc_low_threshold,
2168 "adjust-soc-low-threshold", rc);
2169 SPMI_PROP_READ(batt_type, "batt-type", rc);
2170 SPMI_PROP_READ(low_soc_calc_threshold,
2171 "low-soc-calculate-soc-threshold", rc);
2172 SPMI_PROP_READ(low_soc_calculate_soc_ms,
2173 "low-soc-calculate-soc-ms", rc);
2174 SPMI_PROP_READ(calculate_soc_ms, "calculate-soc-ms", rc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002175 chip->use_external_rsense = of_property_read_bool(
2176 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002177 "qcom,use-external-rsense");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002178 chip->ignore_shutdown_soc = of_property_read_bool(
2179 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002180 "qcom,ignore-shutdown-soc");
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002181 chip->use_voltage_soc = of_property_read_bool(chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002182 "qcom,use-voltage-soc");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002183 chip->use_ocv_thresholds = of_property_read_bool(
2184 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002185 "qcom,use-ocv-thresholds");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002186 SPMI_PROP_READ(ocv_high_threshold_uv,
2187 "ocv-voltage-high-threshold-uv", rc);
2188 SPMI_PROP_READ(ocv_low_threshold_uv,
2189 "ocv-voltage-low-threshold-uv", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002190
2191 if (chip->adjust_soc_low_threshold >= 45)
2192 chip->adjust_soc_low_threshold = 45;
2193
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002194 pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
2195 chip->r_sense_uohm, chip->v_cutoff_uv,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002196 chip->max_voltage_uv);
2197 pr_debug("r_conn:%d, shutdown_soc: %d, adjust_soc_low:%d\n",
2198 chip->r_conn_mohm, chip->shutdown_soc_valid_limit,
2199 chip->adjust_soc_low_threshold);
2200 pr_debug("adjust_soc_high:%d, chg_term_ua:%d, batt_type:%d\n",
2201 chip->adjust_soc_high_threshold, chip->chg_term_ua,
2202 chip->batt_type);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08002203 pr_debug("ignore_shutdown_soc:%d, use_voltage_soc:%d\n",
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002204 chip->ignore_shutdown_soc, chip->use_voltage_soc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002205 pr_debug("use external rsense: %d\n", chip->use_external_rsense);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002206 return 0;
2207}
2208
2209static inline void bms_initialize_constants(struct qpnp_bms_chip *chip)
2210{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002211 chip->prev_pc_unusable = -EINVAL;
2212 chip->soc_at_cv = -EINVAL;
2213 chip->calculated_soc = -EINVAL;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002214 chip->last_soc = -EINVAL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07002215 chip->last_soc_est = -EINVAL;
Xiaozhe Shif36d2862013-01-04 10:17:35 -08002216 chip->last_cc_uah = INT_MIN;
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -08002217 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
2218 chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002219 chip->first_time_calc_soc = 1;
2220 chip->first_time_calc_uuc = 1;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002221}
2222
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002223#define REG_OFFSET_PERP_TYPE 0x04
2224#define REG_OFFSET_PERP_SUBTYPE 0x05
2225#define BMS_BMS_TYPE 0xD
2226#define BMS_BMS_SUBTYPE 0x1
2227#define BMS_IADC_TYPE 0x8
2228#define BMS_IADC_SUBTYPE 0x3
2229
2230static int register_spmi(struct qpnp_bms_chip *chip, struct spmi_device *spmi)
2231{
2232 struct spmi_resource *spmi_resource;
2233 struct resource *resource;
2234 int rc;
2235 u8 type, subtype;
2236
2237 chip->dev = &(spmi->dev);
2238 chip->spmi = spmi;
2239
2240 spmi_for_each_container_dev(spmi_resource, spmi) {
2241 if (!spmi_resource) {
2242 pr_err("qpnp_bms: spmi resource absent\n");
2243 return -ENXIO;
2244 }
2245
2246 resource = spmi_get_resource(spmi, spmi_resource,
2247 IORESOURCE_MEM, 0);
2248 if (!(resource && resource->start)) {
2249 pr_err("node %s IO resource absent!\n",
2250 spmi->dev.of_node->full_name);
2251 return -ENXIO;
2252 }
2253
2254 rc = qpnp_read_wrapper(chip, &type,
2255 resource->start + REG_OFFSET_PERP_TYPE, 1);
2256 if (rc) {
2257 pr_err("Peripheral type read failed rc=%d\n", rc);
2258 return rc;
2259 }
2260 rc = qpnp_read_wrapper(chip, &subtype,
2261 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2262 if (rc) {
2263 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2264 return rc;
2265 }
2266
2267 if (type == BMS_BMS_TYPE && subtype == BMS_BMS_SUBTYPE) {
2268 chip->base = resource->start;
2269 } else if (type == BMS_IADC_TYPE
2270 && subtype == BMS_IADC_SUBTYPE) {
2271 chip->iadc_base = resource->start;
2272 } else {
2273 pr_err("Invalid peripheral start=0x%x type=0x%x, subtype=0x%x\n",
2274 resource->start, type, subtype);
2275 }
2276 }
2277
2278 if (chip->base == 0) {
2279 dev_err(&spmi->dev, "BMS peripheral was not registered\n");
2280 return -EINVAL;
2281 }
2282 if (chip->iadc_base == 0) {
2283 dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
2284 return -EINVAL;
2285 }
2286
2287 return 0;
2288}
2289
2290#define ADC_CH_SEL_MASK 0x7
2291static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
2292{
2293 u8 iadc_channel_select;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002294 int32_t rds_rsense_nohm;
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002295 int rc;
2296
2297 rc = qpnp_read_wrapper(chip, &iadc_channel_select,
2298 chip->iadc_base + IADC1_BMS_ADC_CH_SEL_CTL, 1);
2299 if (rc) {
2300 pr_err("Error reading bms_iadc channel register %d\n", rc);
2301 return rc;
2302 }
2303
2304 iadc_channel_select &= ADC_CH_SEL_MASK;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002305 if (iadc_channel_select != EXTERNAL_RSENSE
2306 && iadc_channel_select != INTERNAL_RSENSE) {
2307 pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
2308 iadc_channel_select);
2309 return -EINVAL;
2310 }
2311
2312 if (chip->use_external_rsense) {
2313 pr_debug("External rsense selected\n");
2314 if (iadc_channel_select == INTERNAL_RSENSE) {
2315 pr_debug("Internal rsense detected; Changing rsense to external\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002316 rc = qpnp_masked_write_iadc(chip,
2317 IADC1_BMS_ADC_CH_SEL_CTL,
2318 ADC_CH_SEL_MASK,
2319 EXTERNAL_RSENSE);
2320 if (rc) {
2321 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2322 IADC1_BMS_ADC_CH_SEL_CTL,
2323 EXTERNAL_RSENSE, rc);
2324 return rc;
2325 }
2326 reset_cc(chip);
2327 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002328 } else {
2329 pr_debug("Internal rsense selected\n");
2330 if (iadc_channel_select == EXTERNAL_RSENSE) {
2331 pr_debug("External rsense detected; Changing rsense to internal\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002332 rc = qpnp_masked_write_iadc(chip,
2333 IADC1_BMS_ADC_CH_SEL_CTL,
2334 ADC_CH_SEL_MASK,
2335 INTERNAL_RSENSE);
2336 if (rc) {
2337 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2338 IADC1_BMS_ADC_CH_SEL_CTL,
2339 INTERNAL_RSENSE, rc);
2340 return rc;
2341 }
2342 reset_cc(chip);
2343 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002344
2345 rc = qpnp_iadc_get_rsense(&rds_rsense_nohm);
2346 if (rc) {
2347 pr_err("Unable to read RDS resistance value from IADC; rc = %d\n",
2348 rc);
2349 return rc;
2350 }
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002351 chip->r_sense_uohm = rds_rsense_nohm/1000;
2352 pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
2353 rds_rsense_nohm, chip->r_sense_uohm);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002354 }
2355 return 0;
2356}
2357
2358static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002359{
2360 struct qpnp_bms_chip *chip;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002361 int rc, vbatt;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002362
2363 chip = kzalloc(sizeof *chip, GFP_KERNEL);
2364
2365 if (chip == NULL) {
2366 pr_err("kzalloc() failed.\n");
2367 return -ENOMEM;
2368 }
2369
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002370 rc = qpnp_vadc_is_ready();
2371 if (rc) {
2372 pr_info("vadc not ready: %d, deferring probe\n", rc);
2373 goto error_read;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002374 }
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002375
2376 rc = qpnp_iadc_is_ready();
2377 if (rc) {
2378 pr_info("iadc not ready: %d, deferring probe\n", rc);
2379 goto error_read;
2380 }
2381
2382 rc = register_spmi(chip, spmi);
2383 if (rc) {
2384 pr_err("error registering spmi resource %d\n", rc);
2385 goto error_resource;
2386 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002387
2388 rc = qpnp_read_wrapper(chip, &chip->revision1,
2389 chip->base + BMS1_REVISION1, 1);
2390 if (rc) {
2391 pr_err("error reading version register %d\n", rc);
2392 goto error_read;
2393 }
2394
2395 rc = qpnp_read_wrapper(chip, &chip->revision2,
2396 chip->base + BMS1_REVISION2, 1);
2397 if (rc) {
2398 pr_err("Error reading version register %d\n", rc);
2399 goto error_read;
2400 }
Xiaozhe Shia045a562012-11-28 16:55:39 -08002401 pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002402
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002403 rc = bms_read_properties(chip);
2404 if (rc) {
2405 pr_err("Unable to read all bms properties, rc = %d\n", rc);
2406 goto error_read;
2407 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002408
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002409 rc = read_iadc_channel_select(chip);
2410 if (rc) {
2411 pr_err("Unable to get iadc selected channel = %d\n", rc);
2412 goto error_read;
2413 }
2414
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002415 if (chip->use_ocv_thresholds) {
2416 rc = set_ocv_voltage_thresholds(chip,
2417 chip->ocv_low_threshold_uv,
2418 chip->ocv_high_threshold_uv);
2419 if (rc) {
2420 pr_err("Could not set ocv voltage thresholds: %d\n",
2421 rc);
2422 goto error_read;
2423 }
2424 }
2425
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002426 rc = set_battery_data(chip);
2427 if (rc) {
2428 pr_err("Bad battery data %d\n", rc);
2429 goto error_read;
2430 }
2431
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002432 bms_initialize_constants(chip);
2433
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002434 mutex_init(&chip->bms_output_lock);
2435 mutex_init(&chip->last_ocv_uv_mutex);
2436 mutex_init(&chip->soc_invalidation_mutex);
2437
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002438 wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
2439 "qpnp_soc_lock");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002440 INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
2441 calculate_soc_work);
2442
2443 read_shutdown_soc_and_iavg(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002444
2445 dev_set_drvdata(&spmi->dev, chip);
2446 device_init_wakeup(&spmi->dev, 1);
2447
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002448 calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
2449
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002450 /* setup & register the battery power supply */
2451 chip->bms_psy.name = "bms";
2452 chip->bms_psy.type = POWER_SUPPLY_TYPE_BMS;
2453 chip->bms_psy.properties = msm_bms_power_props;
2454 chip->bms_psy.num_properties = ARRAY_SIZE(msm_bms_power_props);
2455 chip->bms_psy.get_property = qpnp_bms_power_get_property;
2456 chip->bms_psy.set_property = qpnp_bms_power_set_property;
2457 chip->bms_psy.external_power_changed =
2458 qpnp_bms_external_power_changed;
2459 chip->bms_psy.supplied_to = qpnp_bms_supplicants;
2460 chip->bms_psy.num_supplicants = ARRAY_SIZE(qpnp_bms_supplicants);
2461
2462 rc = power_supply_register(chip->dev, &chip->bms_psy);
2463
2464 if (rc < 0) {
2465 pr_err("power_supply_register bms failed rc = %d\n", rc);
2466 goto unregister_dc;
2467 }
2468
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002469 vbatt = 0;
2470 get_battery_voltage(&vbatt);
2471
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002472 pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u\n",
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002473 get_prop_bms_capacity(chip),
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002474 vbatt, chip->last_ocv_uv, chip->r_sense_uohm);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002475 return 0;
2476
2477unregister_dc:
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002478 wake_lock_destroy(&chip->soc_wake_lock);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002479 power_supply_unregister(&chip->bms_psy);
2480 dev_set_drvdata(&spmi->dev, NULL);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002481error_resource:
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002482error_read:
2483 kfree(chip);
2484 return rc;
2485}
2486
2487static int __devexit
2488qpnp_bms_remove(struct spmi_device *spmi)
2489{
2490 struct qpnp_bms_chip *chip = dev_get_drvdata(&spmi->dev);
2491
2492 dev_set_drvdata(&spmi->dev, NULL);
2493 kfree(chip);
2494 return 0;
2495}
2496
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002497static int bms_resume(struct device *dev)
2498{
2499 int rc;
2500 unsigned long soc_calc_period;
2501 unsigned long time_since_last_recalc;
2502 unsigned long tm_now_sec;
2503 struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
2504
2505 rc = get_current_time(&tm_now_sec);
2506 if (rc) {
2507 pr_err("Could not read current time: %d\n", rc);
2508 } else if (tm_now_sec > chip->last_recalc_time) {
2509 time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
2510 pr_debug("Time since last recalc: %lu\n",
2511 time_since_last_recalc);
2512 if (chip->calculated_soc < chip->low_soc_calc_threshold)
2513 soc_calc_period = chip->low_soc_calculate_soc_ms;
2514 else
2515 soc_calc_period = chip->calculate_soc_ms;
2516
2517 if (time_since_last_recalc >= soc_calc_period) {
2518 chip->last_recalc_time = tm_now_sec;
2519 recalculate_soc(chip);
2520 }
2521 }
2522 return 0;
2523}
2524
2525static const struct dev_pm_ops qpnp_bms_pm_ops = {
2526 .resume = bms_resume,
2527};
2528
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002529static struct spmi_driver qpnp_bms_driver = {
2530 .probe = qpnp_bms_probe,
2531 .remove = __devexit_p(qpnp_bms_remove),
2532 .driver = {
2533 .name = QPNP_BMS_DEV_NAME,
2534 .owner = THIS_MODULE,
2535 .of_match_table = qpnp_bms_match_table,
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002536 .pm = &qpnp_bms_pm_ops,
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002537 },
2538};
2539
2540static int __init qpnp_bms_init(void)
2541{
2542 pr_info("QPNP BMS INIT\n");
2543 return spmi_driver_register(&qpnp_bms_driver);
2544}
2545
2546static void __exit qpnp_bms_exit(void)
2547{
2548 pr_info("QPNP BMS EXIT\n");
2549 return spmi_driver_unregister(&qpnp_bms_driver);
2550}
2551
2552module_init(qpnp_bms_init);
2553module_exit(qpnp_bms_exit);
2554
2555MODULE_DESCRIPTION("QPNP BMS Driver");
2556MODULE_LICENSE("GPL v2");
2557MODULE_ALIAS("platform:" QPNP_BMS_DEV_NAME);