blob: bc6f2893473a2b4fcab239a57d6b7cbcea8379a9 [file] [log] [blame]
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Xiaozhe Shi73a65692012-09-18 17:51:57 -070013#define pr_fmt(fmt) "BMS: %s: " fmt, __func__
Xiaozhe Shib19f7032012-08-16 12:14:16 -070014
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <linux/err.h>
20#include <linux/of.h>
21#include <linux/of_device.h>
22#include <linux/power_supply.h>
23#include <linux/spmi.h>
Xiaozhe Shie118c692012-09-24 15:17:43 -070024#include <linux/rtc.h>
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -070025#include <linux/delay.h>
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070026#include <linux/qpnp/qpnp-adc.h>
Xiaozhe Shi73a65692012-09-18 17:51:57 -070027#include <linux/mfd/pm8xxx/batterydata-lib.h>
Xiaozhe Shib19f7032012-08-16 12:14:16 -070028
Xiaozhe Shib19f7032012-08-16 12:14:16 -070029/* BMS Register Offsets */
30#define BMS1_REVISION1 0x0
31#define BMS1_REVISION2 0x1
32#define BMS1_STATUS1 0x8
33#define BMS1_MODE_CTL 0X40
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070034/* Coulomb counter clear registers */
Xiaozhe Shib19f7032012-08-16 12:14:16 -070035#define BMS1_CC_DATA_CTL 0x42
Xiaozhe Shia045a562012-11-28 16:55:39 -080036#define BMS1_CC_CLEAR_CTL 0x43
Xiaozhe Shi20640b52013-01-03 11:49:30 -080037/* BMS Tolerances */
38#define BMS1_TOL_CTL 0X44
Xiaozhe Shib19f7032012-08-16 12:14:16 -070039/* OCV limit registers */
40#define BMS1_OCV_USE_LOW_LIMIT_THR0 0x48
41#define BMS1_OCV_USE_LOW_LIMIT_THR1 0x49
42#define BMS1_OCV_USE_HIGH_LIMIT_THR0 0x4A
43#define BMS1_OCV_USE_HIGH_LIMIT_THR1 0x4B
44#define BMS1_OCV_USE_LIMIT_CTL 0x4C
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -070045/* Delay control */
46#define BMS1_S1_DELAY_CTL 0x5A
Xiaozhe Shib19f7032012-08-16 12:14:16 -070047/* CC interrupt threshold */
48#define BMS1_CC_THR0 0x7A
49#define BMS1_CC_THR1 0x7B
50#define BMS1_CC_THR2 0x7C
51#define BMS1_CC_THR3 0x7D
52#define BMS1_CC_THR4 0x7E
53/* OCV for r registers */
54#define BMS1_OCV_FOR_R_DATA0 0x80
55#define BMS1_OCV_FOR_R_DATA1 0x81
56#define BMS1_VSENSE_FOR_R_DATA0 0x82
57#define BMS1_VSENSE_FOR_R_DATA1 0x83
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070058/* Coulomb counter data */
Xiaozhe Shib19f7032012-08-16 12:14:16 -070059#define BMS1_CC_DATA0 0x8A
60#define BMS1_CC_DATA1 0x8B
61#define BMS1_CC_DATA2 0x8C
62#define BMS1_CC_DATA3 0x8D
63#define BMS1_CC_DATA4 0x8E
64/* OCV for soc data */
65#define BMS1_OCV_FOR_SOC_DATA0 0x90
66#define BMS1_OCV_FOR_SOC_DATA1 0x91
67#define BMS1_VSENSE_PON_DATA0 0x94
68#define BMS1_VSENSE_PON_DATA1 0x95
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070069#define BMS1_VSENSE_AVG_DATA0 0x98
70#define BMS1_VSENSE_AVG_DATA1 0x99
Xiaozhe Shib19f7032012-08-16 12:14:16 -070071#define BMS1_VBAT_AVG_DATA0 0x9E
72#define BMS1_VBAT_AVG_DATA1 0x9F
73/* Extra bms registers */
74#define BMS1_BMS_DATA_REG_0 0xB0
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070075#define IAVG_STORAGE_REG 0xB1
76#define SOC_STORAGE_REG 0xB2
Xiaozhe Shib19f7032012-08-16 12:14:16 -070077#define BMS1_BMS_DATA_REG_3 0xB3
Xiaozhe Shic40b3972012-11-30 14:11:16 -080078/* IADC Channel Select */
79#define IADC1_BMS_ADC_CH_SEL_CTL 0x48
Xiaozhe Shib19f7032012-08-16 12:14:16 -070080
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070081/* Configuration for saving of shutdown soc/iavg */
82#define IGNORE_SOC_TEMP_DECIDEG 50
83#define IAVG_STEP_SIZE_MA 50
84#define IAVG_START 600
Xiaozhe Shif5f966d2013-02-19 14:23:11 -080085#define IAVG_INVALID 0xFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070086#define SOC_ZERO 0xFF
87
Xiaozhe Shie118c692012-09-24 15:17:43 -070088#define IAVG_SAMPLES 16
89
Xiaozhe Shib19f7032012-08-16 12:14:16 -070090#define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
91
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070092struct soc_params {
93 int fcc_uah;
94 int cc_uah;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -080095 int rbatt_mohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070096 int iavg_ua;
97 int uuc_uah;
98 int ocv_charge_uah;
Xiaozhe Shif36d2862013-01-04 10:17:35 -080099 int delta_time_s;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700100};
101
102struct raw_soc_params {
103 uint16_t last_good_ocv_raw;
104 int64_t cc;
105 int last_good_ocv_uv;
106};
107
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700108struct qpnp_bms_chip {
109 struct device *dev;
110 struct power_supply bms_psy;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700111 struct power_supply *batt_psy;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700112 struct spmi_device *spmi;
113 u16 base;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800114 u16 iadc_base;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700115
116 u8 revision1;
117 u8 revision2;
Xiaozhe Shid5d21412013-02-06 17:14:41 -0800118 int battery_present;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700119 /* 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
Xiaozhe Shi4be85782013-02-22 17:33:40 -0800151 struct wake_lock low_voltage_wake_lock;
152 bool low_voltage_wake_lock_held;
153 int low_voltage_threshold;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700154 int low_soc_calc_threshold;
155 int low_soc_calculate_soc_ms;
156 int calculate_soc_ms;
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -0800157 struct wake_lock soc_wake_lock;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700158
Xiaozhe Shie118c692012-09-24 15:17:43 -0700159 uint16_t ocv_reading_at_100;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700160 uint16_t prev_last_good_ocv_raw;
161 int last_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800162 int last_ocv_temp;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700163 int last_cc_uah;
164 unsigned long tm_sec;
165 bool first_time_calc_soc;
166 bool first_time_calc_uuc;
167 int pon_ocv_uv;
168
169 int iavg_samples_ma[IAVG_SAMPLES];
170 int iavg_index;
171 int iavg_num_samples;
172 struct timespec t_soc_queried;
173 int last_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700174 int last_soc_est;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700175
176 int charge_time_us;
177 int catch_up_time_us;
178 struct single_row_lut *adjusted_fcc_temp_lut;
179
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700180 unsigned int vadc_v0625;
181 unsigned int vadc_v1250;
182
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800183 int ibat_max_ua;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700184 int prev_iavg_ua;
185 int prev_uuc_iavg_ma;
186 int prev_pc_unusable;
187 int ibat_at_cv_ua;
188 int soc_at_cv;
189 int prev_chg_soc;
190 int calculated_soc;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -0800191 int prev_voltage_based_soc;
192 bool use_voltage_soc;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800193
194 int ocv_high_threshold_uv;
195 int ocv_low_threshold_uv;
Xiaozhe Shicdeee312012-12-18 15:10:18 -0800196 unsigned long last_recalc_time;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700197};
198
199static struct of_device_id qpnp_bms_match_table[] = {
200 { .compatible = QPNP_BMS_DEV_NAME },
201 {}
202};
203
204static char *qpnp_bms_supplicants[] = {
205 "battery"
206};
207
208static enum power_supply_property msm_bms_power_props[] = {
Xiaozhe Shid5d21412013-02-06 17:14:41 -0800209 POWER_SUPPLY_PROP_PRESENT,
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700210 POWER_SUPPLY_PROP_CAPACITY,
211 POWER_SUPPLY_PROP_CURRENT_NOW,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800212 POWER_SUPPLY_PROP_CURRENT_MAX,
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700213 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
214};
215
Xiaozhe Shi20640b52013-01-03 11:49:30 -0800216static bool bms_reset;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -0800217
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700218static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
219 u16 base, int count)
220{
221 int rc;
222 struct spmi_device *spmi = chip->spmi;
223
224 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700225 if (rc) {
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700226 pr_err("SPMI read failed rc=%d\n", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700227 return rc;
228 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700229 return 0;
230}
231
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700232static int qpnp_write_wrapper(struct qpnp_bms_chip *chip, u8 *val,
233 u16 base, int count)
234{
235 int rc;
236 struct spmi_device *spmi = chip->spmi;
237
238 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
239 if (rc) {
240 pr_err("SPMI write failed rc=%d\n", rc);
241 return rc;
242 }
243 return 0;
244}
245
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800246static int qpnp_masked_write_base(struct qpnp_bms_chip *chip, u16 addr,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700247 u8 mask, u8 val)
248{
249 int rc;
250 u8 reg;
251
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800252 rc = qpnp_read_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700253 if (rc) {
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800254 pr_err("read failed addr = %03X, rc = %d\n", addr, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700255 return rc;
256 }
257 reg &= ~mask;
258 reg |= val & mask;
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800259 rc = qpnp_write_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700260 if (rc) {
261 pr_err("write failed addr = %03X, val = %02x, mask = %02x, reg = %02x, rc = %d\n",
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800262 addr, val, mask, reg, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700263 return rc;
264 }
265 return 0;
266}
267
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800268static int qpnp_masked_write_iadc(struct qpnp_bms_chip *chip, u16 addr,
269 u8 mask, u8 val)
270{
271 return qpnp_masked_write_base(chip, chip->iadc_base + addr, mask, val);
272}
273
274static int qpnp_masked_write(struct qpnp_bms_chip *chip, u16 addr,
275 u8 mask, u8 val)
276{
277 return qpnp_masked_write_base(chip, chip->base + addr, mask, val);
278}
279
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700280#define HOLD_OREG_DATA BIT(0)
281static int lock_output_data(struct qpnp_bms_chip *chip)
282{
283 int rc;
284
285 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL,
286 HOLD_OREG_DATA, HOLD_OREG_DATA);
287 if (rc) {
288 pr_err("couldnt lock bms output rc = %d\n", rc);
289 return rc;
290 }
291 return 0;
292}
293
294static int unlock_output_data(struct qpnp_bms_chip *chip)
295{
296 int rc;
297
298 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL, HOLD_OREG_DATA, 0);
299 if (rc) {
300 pr_err("fail to unlock BMS_CONTROL rc = %d\n", rc);
301 return rc;
302 }
303 return 0;
304}
305
306#define V_PER_BIT_MUL_FACTOR 97656
307#define V_PER_BIT_DIV_FACTOR 1000
308#define VADC_INTRINSIC_OFFSET 0x6000
309
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800310static int vadc_reading_to_uv(int reading)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700311{
312 if (reading <= VADC_INTRINSIC_OFFSET)
313 return 0;
314
315 return (reading - VADC_INTRINSIC_OFFSET)
316 * V_PER_BIT_MUL_FACTOR / V_PER_BIT_DIV_FACTOR;
317}
318
319#define VADC_CALIB_UV 625000
320#define VBATT_MUL_FACTOR 3
321
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800322static int adjust_vbatt_reading(struct qpnp_bms_chip *chip, int reading_uv)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700323{
324 s64 numerator, denominator;
325
326 if (reading_uv == 0)
327 return 0;
328
329 /* don't adjust if not calibrated */
330 if (chip->vadc_v0625 == 0 || chip->vadc_v1250 == 0) {
331 pr_debug("No cal yet return %d\n",
332 VBATT_MUL_FACTOR * reading_uv);
333 return VBATT_MUL_FACTOR * reading_uv;
334 }
335
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700336 numerator = ((s64)reading_uv - chip->vadc_v0625) * VADC_CALIB_UV;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700337 denominator = (s64)chip->vadc_v1250 - chip->vadc_v0625;
338 if (denominator == 0)
339 return reading_uv * VBATT_MUL_FACTOR;
340 return (VADC_CALIB_UV + div_s64(numerator, denominator))
341 * VBATT_MUL_FACTOR;
342}
343
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800344static int convert_vbatt_uv_to_raw(struct qpnp_bms_chip *chip,
345 int unadjusted_vbatt)
346{
347 int scaled_vbatt = unadjusted_vbatt / VBATT_MUL_FACTOR;
348
349 if (scaled_vbatt <= 0)
350 return VADC_INTRINSIC_OFFSET;
351 return ((scaled_vbatt * V_PER_BIT_DIV_FACTOR) / V_PER_BIT_MUL_FACTOR)
352 + VADC_INTRINSIC_OFFSET;
353}
354
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700355static inline int convert_vbatt_raw_to_uv(struct qpnp_bms_chip *chip,
356 uint16_t reading)
357{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700358 int uv;
359
360 uv = vadc_reading_to_uv(reading);
361 pr_debug("%u raw converted into %d uv\n", reading, uv);
362 uv = adjust_vbatt_reading(chip, uv);
363 pr_debug("adjusted into %d uv\n", uv);
364 return uv;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700365}
366
367#define CC_READING_RESOLUTION_N 542535
368#define CC_READING_RESOLUTION_D 100000
369static int cc_reading_to_uv(int16_t reading)
370{
371 return div_s64(reading * CC_READING_RESOLUTION_N,
372 CC_READING_RESOLUTION_D);
373}
374
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800375#define QPNP_ADC_GAIN_IDEAL 3291LL
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700376static s64 cc_adjust_for_gain(s64 uv, uint16_t gain)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700377{
378 s64 result_uv;
379
380 pr_debug("adjusting_uv = %lld\n", uv);
Xiaozhe Shi820a47a2012-11-27 13:23:27 -0800381 if (gain == 0) {
382 pr_debug("gain is %d, not adjusting\n", gain);
383 return uv;
384 }
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700385 pr_debug("adjusting by factor: %lld/%hu = %lld%%\n",
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800386 QPNP_ADC_GAIN_IDEAL, gain,
387 div_s64(QPNP_ADC_GAIN_IDEAL * 100LL, (s64)gain));
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700388
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800389 result_uv = div_s64(uv * QPNP_ADC_GAIN_IDEAL, (s64)gain);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700390 pr_debug("result_uv = %lld\n", result_uv);
391 return result_uv;
392}
393
394static int convert_vsense_to_uv(struct qpnp_bms_chip *chip,
395 int16_t reading)
396{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700397 struct qpnp_iadc_calib calibration;
398
399 qpnp_iadc_get_gain_and_offset(&calibration);
400 return cc_adjust_for_gain(cc_reading_to_uv(reading),
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800401 calibration.gain_raw - calibration.offset_raw);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700402}
403
404static int read_vsense_avg(struct qpnp_bms_chip *chip, int *result_uv)
405{
406 int rc;
407 int16_t reading;
408
409 rc = qpnp_read_wrapper(chip, (u8 *)&reading,
410 chip->base + BMS1_VSENSE_AVG_DATA0, 2);
411
412 if (rc) {
413 pr_err("fail to read VSENSE_AVG rc = %d\n", rc);
414 return rc;
415 }
416
417 *result_uv = convert_vsense_to_uv(chip, reading);
418 return 0;
419}
420
421static int get_battery_current(struct qpnp_bms_chip *chip, int *result_ua)
422{
423 int vsense_uv = 0;
424
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800425 if (chip->r_sense_uohm == 0) {
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700426 pr_err("r_sense is zero\n");
427 return -EINVAL;
428 }
429
430 mutex_lock(&chip->bms_output_lock);
431 lock_output_data(chip);
432 read_vsense_avg(chip, &vsense_uv);
433 unlock_output_data(chip);
434 mutex_unlock(&chip->bms_output_lock);
435
436 pr_debug("vsense_uv=%duV\n", vsense_uv);
437 /* cast for signed division */
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800438 *result_ua = div_s64((vsense_uv * 1000000LL), (int)chip->r_sense_uohm);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700439 pr_debug("ibat=%duA\n", *result_ua);
440 return 0;
441}
442
443static int get_battery_voltage(int *result_uv)
444{
445 int rc;
446 struct qpnp_vadc_result adc_result;
447
448 rc = qpnp_vadc_read(VBAT_SNS, &adc_result);
449 if (rc) {
450 pr_err("error reading adc channel = %d, rc = %d\n",
451 VBAT_SNS, rc);
452 return rc;
453 }
454 pr_debug("mvolts phy = %lld meas = 0x%llx\n", adc_result.physical,
455 adc_result.measurement);
456 *result_uv = (int)adc_result.physical;
457 return 0;
458}
459
Xiaozhe Shie118c692012-09-24 15:17:43 -0700460#define CC_36_BIT_MASK 0xFFFFFFFFFLL
461
462static int read_cc_raw(struct qpnp_bms_chip *chip, int64_t *reading)
463{
464 int64_t raw_reading;
465 int rc;
466
467 rc = qpnp_read_wrapper(chip, (u8 *)&raw_reading,
468 chip->base + BMS1_CC_DATA0, 5);
469 if (rc) {
470 pr_err("Error reading cc: rc = %d\n", rc);
471 return -ENXIO;
472 }
473
474 raw_reading = raw_reading & CC_36_BIT_MASK;
475 /* convert 36 bit signed value into 64 signed value */
476 *reading = (raw_reading >> 35) == 0LL ?
477 raw_reading : ((-1LL ^ CC_36_BIT_MASK) | raw_reading);
478 pr_debug("before conversion: %llx, after conversion: %llx\n",
479 raw_reading, *reading);
480
481 return 0;
482}
483
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700484static int calib_vadc(struct qpnp_bms_chip *chip)
485{
486 int rc;
487 struct qpnp_vadc_result result;
488
489 rc = qpnp_vadc_read(REF_625MV, &result);
490 if (rc) {
491 pr_debug("vadc read failed with rc = %d\n", rc);
492 return rc;
493 }
494 chip->vadc_v0625 = result.physical;
495
496 rc = qpnp_vadc_read(REF_125V, &result);
497 if (rc) {
498 pr_debug("vadc read failed with rc = %d\n", rc);
499 return rc;
500 }
501 chip->vadc_v1250 = result.physical;
502 pr_debug("vadc calib: 0625 = %d, 1250 = %d\n",
503 chip->vadc_v0625, chip->vadc_v1250);
504 return 0;
505}
506
Xiaozhe Shie118c692012-09-24 15:17:43 -0700507static void convert_and_store_ocv(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800508 struct raw_soc_params *raw,
509 int batt_temp)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700510{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700511 int rc;
512
513 pr_debug("prev_last_good_ocv_raw = %d, last_good_ocv_raw = %d\n",
514 chip->prev_last_good_ocv_raw,
515 raw->last_good_ocv_raw);
516 rc = calib_vadc(chip);
517 if (rc)
518 pr_err("Vadc reference voltage read failed, rc = %d\n", rc);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700519 chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
520 raw->last_good_ocv_uv = convert_vbatt_raw_to_uv(chip,
521 raw->last_good_ocv_raw);
522 chip->last_ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800523 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700524 pr_debug("last_good_ocv_uv = %d\n", raw->last_good_ocv_uv);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700525}
526
Xiaozhe Shia045a562012-11-28 16:55:39 -0800527#define CLEAR_CC BIT(7)
528#define CLEAR_SW_CC BIT(6)
529/**
530 * reset both cc and sw-cc.
531 * note: this should only be ever called from one thread
532 * or there may be a race condition where CC is never enabled
533 * again
534 */
535static void reset_cc(struct qpnp_bms_chip *chip)
536{
537 int rc;
538
539 pr_debug("resetting cc manually\n");
540 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
541 CLEAR_CC | CLEAR_SW_CC,
542 CLEAR_CC | CLEAR_SW_CC);
543 if (rc)
544 pr_err("cc reset failed: %d\n", rc);
545
546 /* wait for 100us for cc to reset */
547 udelay(100);
548
549 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
550 CLEAR_CC | CLEAR_SW_CC, 0);
551 if (rc)
552 pr_err("cc reenable failed: %d\n", rc);
553}
554
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800555#define OCV_RAW_UNINITIALIZED 0xFFFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700556static int read_soc_params_raw(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800557 struct raw_soc_params *raw,
558 int batt_temp)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700559{
Xiaozhe Shie118c692012-09-24 15:17:43 -0700560 int rc;
561
562 mutex_lock(&chip->bms_output_lock);
Xiaozhe Shia045a562012-11-28 16:55:39 -0800563
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800564 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Xiaozhe Shia045a562012-11-28 16:55:39 -0800565 /* software workaround for BMS 1.0
566 * The coulomb counter does not reset upon PON, so reset it
567 * manually upon probe. */
568 if (chip->revision1 == 0 && chip->revision2 == 0)
569 reset_cc(chip);
570 }
571
Xiaozhe Shie118c692012-09-24 15:17:43 -0700572 lock_output_data(chip);
573
574 rc = qpnp_read_wrapper(chip, (u8 *)&raw->last_good_ocv_raw,
575 chip->base + BMS1_OCV_FOR_SOC_DATA0, 2);
576 if (rc) {
577 pr_err("Error reading ocv: rc = %d\n", rc);
578 return -ENXIO;
579 }
580
581 rc = read_cc_raw(chip, &raw->cc);
582 if (rc) {
583 pr_err("Failed to read raw cc data, rc = %d\n", rc);
584 return rc;
585 }
586
587 unlock_output_data(chip);
588 mutex_unlock(&chip->bms_output_lock);
589
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800590 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800591 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700592 pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
593 } else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800594 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700595 /* forget the old cc value upon ocv */
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800596 chip->last_cc_uah = INT_MIN;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700597 } else {
598 raw->last_good_ocv_uv = chip->last_ocv_uv;
599 }
600
601 /* fake a high OCV if done charging */
602 if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800603 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700604 } 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 Shi1c63a892013-02-13 15:49:40 -0800612 reset_cc(chip);
613 raw->cc = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700614 }
615 pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
616 raw->last_good_ocv_raw, raw->last_good_ocv_uv);
617 pr_debug("cc_raw= 0x%llx\n", raw->cc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700618 return 0;
619}
620
Xiaozhe Shie118c692012-09-24 15:17:43 -0700621static int calculate_pc(struct qpnp_bms_chip *chip, int ocv_uv,
622 int batt_temp)
623{
624 int pc;
625
626 pc = interpolate_pc(chip->pc_temp_ocv_lut,
627 batt_temp / 10, ocv_uv / 1000);
628 pr_debug("pc = %u %% for ocv = %d uv batt_temp = %d\n",
629 pc, ocv_uv, batt_temp);
630 /* Multiply the initial FCC value by the scale factor. */
631 return pc;
632}
633
634static int calculate_fcc(struct qpnp_bms_chip *chip, int batt_temp)
635{
636 int fcc_uah;
637
638 if (chip->adjusted_fcc_temp_lut == NULL) {
639 /* interpolate_fcc returns a mv value. */
640 fcc_uah = interpolate_fcc(chip->fcc_temp_lut,
641 batt_temp) * 1000;
642 pr_debug("fcc = %d uAh\n", fcc_uah);
643 return fcc_uah;
644 } else {
645 return 1000 * interpolate_fcc(chip->adjusted_fcc_temp_lut,
646 batt_temp);
647 }
648}
649
650/* calculate remaining charge at the time of ocv */
651static int calculate_ocv_charge(struct qpnp_bms_chip *chip,
652 struct raw_soc_params *raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800653 int fcc_uah)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700654{
655 int ocv_uv, pc;
656
657 ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800658 pc = calculate_pc(chip, ocv_uv, chip->last_ocv_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700659 pr_debug("ocv_uv = %d pc = %d\n", ocv_uv, pc);
660 return (fcc_uah * pc) / 100;
661}
662
663#define CC_RESOLUTION_N 542535
664#define CC_RESOLUTION_D 100000
665
666static s64 cc_to_uv(s64 cc)
667{
668 return div_s64(cc * CC_RESOLUTION_N, CC_RESOLUTION_D);
669}
670
671#define CC_READING_TICKS 56
672#define SLEEP_CLK_HZ 32764
673#define SECONDS_PER_HOUR 3600
674
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800675static s64 cc_uv_to_pvh(s64 cc_uv)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700676{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800677 /* Note that it is necessary need to multiply by 1000000 to convert
678 * from uvh to pvh here.
679 * However, the maximum Coulomb Counter value is 2^35, which can cause
680 * an over flow.
681 * Multiply by 100000 first to perserve as much precision as possible
682 * then multiply by 10 after doing the division in order to avoid
683 * overflow on the maximum Coulomb Counter value.
684 */
685 return div_s64(cc_uv * CC_READING_TICKS * 100000,
686 SLEEP_CLK_HZ * SECONDS_PER_HOUR) * 10;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700687}
688
689/**
690 * calculate_cc-
691 * @chip: the bms chip pointer
692 * @cc: the cc reading from bms h/w
693 * @val: return value
694 * @coulomb_counter: adjusted coulomb counter for 100%
695 *
696 * RETURNS: in val pointer coulomb counter based charger in uAh
697 * (micro Amp hour)
698 */
699static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
700{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800701 int64_t cc_voltage_uv, cc_pvh, cc_uah;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700702 struct qpnp_iadc_calib calibration;
703
704 qpnp_iadc_get_gain_and_offset(&calibration);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -0800705 pr_debug("cc = %lld\n", cc);
706 cc_voltage_uv = cc_to_uv(cc);
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800707 cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
708 calibration.gain_raw
709 - calibration.offset_raw);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700710 pr_debug("cc_voltage_uv = %lld uv\n", cc_voltage_uv);
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800711 cc_pvh = cc_uv_to_pvh(cc_voltage_uv);
712 pr_debug("cc_pvh = %lld pvh\n", cc_pvh);
713 cc_uah = div_s64(cc_pvh, chip->r_sense_uohm);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700714 /* cc_raw had 4 bits of extra precision.
715 By now it should be within 32 bit range */
716 return (int)cc_uah;
717}
718
719static int get_rbatt(struct qpnp_bms_chip *chip,
720 int soc_rbatt_mohm, int batt_temp)
721{
722 int rbatt_mohm, scalefactor;
723
724 rbatt_mohm = chip->default_rbatt_mohm;
725 pr_debug("rbatt before scaling = %d\n", rbatt_mohm);
726 if (chip->rbatt_sf_lut == NULL) {
727 pr_debug("RBATT = %d\n", rbatt_mohm);
728 return rbatt_mohm;
729 }
730 /* Convert the batt_temp to DegC from deciDegC */
731 batt_temp = batt_temp / 10;
732 scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
733 batt_temp, soc_rbatt_mohm);
734 pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
735 scalefactor, batt_temp, soc_rbatt_mohm);
736 rbatt_mohm = (rbatt_mohm * scalefactor) / 100;
737
738 rbatt_mohm += chip->r_conn_mohm;
739 pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
740 chip->r_conn_mohm, rbatt_mohm);
741
742 pr_debug("RBATT = %d\n", rbatt_mohm);
743 return rbatt_mohm;
744}
745
746static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800747 int *iavg_ua, int delta_time_s)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700748{
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800749 int delta_cc_uah = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700750
Xiaozhe Shie118c692012-09-24 15:17:43 -0700751 /* if anything fails report the previous iavg_ua */
752 *iavg_ua = chip->prev_iavg_ua;
753
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800754 if (chip->last_cc_uah == INT_MIN) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700755 get_battery_current(chip, iavg_ua);
756 goto out;
757 }
758
Xiaozhe Shie118c692012-09-24 15:17:43 -0700759 /* use the previous iavg if called within 15 seconds */
760 if (delta_time_s < 15) {
761 *iavg_ua = chip->prev_iavg_ua;
762 goto out;
763 }
764
765 delta_cc_uah = cc_uah - chip->last_cc_uah;
766
767 *iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
768
Xiaozhe Shie118c692012-09-24 15:17:43 -0700769out:
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800770 pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700771 /* remember the iavg */
772 chip->prev_iavg_ua = *iavg_ua;
773
774 /* remember cc_uah */
775 chip->last_cc_uah = cc_uah;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700776}
777
778static int calculate_termination_uuc(struct qpnp_bms_chip *chip,
779 struct soc_params *params,
780 int batt_temp, int uuc_iavg_ma,
781 int *ret_pc_unusable)
782{
783 int unusable_uv, pc_unusable, uuc_uah;
784 int i = 0;
785 int ocv_mv;
786 int batt_temp_degc = batt_temp / 10;
787 int rbatt_mohm;
788 int delta_uv;
789 int prev_delta_uv = 0;
790 int prev_rbatt_mohm = 0;
791 int uuc_rbatt_mohm;
792
793 for (i = 0; i <= 100; i++) {
794 ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
795 batt_temp_degc, i);
796 rbatt_mohm = get_rbatt(chip, i, batt_temp);
797 unusable_uv = (rbatt_mohm * uuc_iavg_ma)
798 + (chip->v_cutoff_uv);
799 delta_uv = ocv_mv * 1000 - unusable_uv;
800
801 pr_debug("soc = %d ocv = %d rbat = %d u_uv = %d delta_v = %d\n",
802 i, ocv_mv, rbatt_mohm, unusable_uv, delta_uv);
803
804 if (delta_uv > 0)
805 break;
806
807 prev_delta_uv = delta_uv;
808 prev_rbatt_mohm = rbatt_mohm;
809 }
810
811 uuc_rbatt_mohm = linear_interpolate(rbatt_mohm, delta_uv,
812 prev_rbatt_mohm, prev_delta_uv,
813 0);
814
815 unusable_uv = (uuc_rbatt_mohm * uuc_iavg_ma) + (chip->v_cutoff_uv);
816
817 pc_unusable = calculate_pc(chip, unusable_uv, batt_temp);
818 uuc_uah = (params->fcc_uah * pc_unusable) / 100;
819 pr_debug("For uuc_iavg_ma = %d, unusable_rbatt = %d unusable_uv = %d unusable_pc = %d uuc = %d\n",
820 uuc_iavg_ma,
821 uuc_rbatt_mohm, unusable_uv,
822 pc_unusable, uuc_uah);
823 *ret_pc_unusable = pc_unusable;
824 return uuc_uah;
825}
826
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800827#define TIME_PER_PERCENT_UUC 60
Xiaozhe Shie118c692012-09-24 15:17:43 -0700828static int adjust_uuc(struct qpnp_bms_chip *chip,
829 struct soc_params *params,
830 int new_pc_unusable,
831 int new_uuc_uah,
832 int batt_temp)
833{
834 int new_unusable_mv, new_iavg_ma;
835 int batt_temp_degc = batt_temp / 10;
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800836 int max_percent_change;
837
838 max_percent_change = max(params->delta_time_s
839 / TIME_PER_PERCENT_UUC, 1);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700840
841 if (chip->prev_pc_unusable == -EINVAL
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800842 || abs(chip->prev_pc_unusable - new_pc_unusable)
843 <= max_percent_change) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700844 chip->prev_pc_unusable = new_pc_unusable;
845 return new_uuc_uah;
846 }
847
848 /* the uuc is trying to change more than 1% restrict it */
849 if (new_pc_unusable > chip->prev_pc_unusable)
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800850 chip->prev_pc_unusable += max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700851 else
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800852 chip->prev_pc_unusable -= max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700853
854 new_uuc_uah = (params->fcc_uah * chip->prev_pc_unusable) / 100;
855
856 /* also find update the iavg_ma accordingly */
857 new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
858 batt_temp_degc, chip->prev_pc_unusable);
859 if (new_unusable_mv < chip->v_cutoff_uv/1000)
860 new_unusable_mv = chip->v_cutoff_uv/1000;
861
862 new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800863 / params->rbatt_mohm;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700864 if (new_iavg_ma == 0)
865 new_iavg_ma = 1;
866 chip->prev_uuc_iavg_ma = new_iavg_ma;
867 pr_debug("Restricting UUC to %d (%d%%) unusable_mv = %d iavg_ma = %d\n",
868 new_uuc_uah, chip->prev_pc_unusable,
869 new_unusable_mv, new_iavg_ma);
870
871 return new_uuc_uah;
872}
873
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800874#define MIN_IAVG_MA 250
Xiaozhe Shie118c692012-09-24 15:17:43 -0700875#define MIN_SECONDS_FOR_VALID_SAMPLE 20
876static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
877 struct soc_params *params,
878 int batt_temp)
879{
880 int uuc_uah_iavg;
881 int i;
882 int uuc_iavg_ma = params->iavg_ua / 1000;
883 int pc_unusable;
884
885 /*
886 * if called first time, fill all the samples with
887 * the shutdown_iavg_ma
888 */
889 if (chip->first_time_calc_uuc && chip->shutdown_iavg_ma != 0) {
890 pr_debug("Using shutdown_iavg_ma = %d in all samples\n",
891 chip->shutdown_iavg_ma);
892 for (i = 0; i < IAVG_SAMPLES; i++)
893 chip->iavg_samples_ma[i] = chip->shutdown_iavg_ma;
894
895 chip->iavg_index = 0;
896 chip->iavg_num_samples = IAVG_SAMPLES;
897 }
898
899 /*
900 * if charging use a nominal avg current to keep
901 * a reasonable UUC while charging
902 */
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800903 if (uuc_iavg_ma < MIN_IAVG_MA)
904 uuc_iavg_ma = MIN_IAVG_MA;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700905 chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
906 chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
907 chip->iavg_num_samples++;
908 if (chip->iavg_num_samples >= IAVG_SAMPLES)
909 chip->iavg_num_samples = IAVG_SAMPLES;
910
911 /* now that this sample is added calcualte the average */
912 uuc_iavg_ma = 0;
913 if (chip->iavg_num_samples != 0) {
914 for (i = 0; i < chip->iavg_num_samples; i++) {
915 pr_debug("iavg_samples_ma[%d] = %d\n", i,
916 chip->iavg_samples_ma[i]);
917 uuc_iavg_ma += chip->iavg_samples_ma[i];
918 }
919
920 uuc_iavg_ma = DIV_ROUND_CLOSEST(uuc_iavg_ma,
921 chip->iavg_num_samples);
922 }
923
Xiaozhe Shi20640b52013-01-03 11:49:30 -0800924 /*
925 * if we're in bms reset mode, force uuc to be 3% of fcc
926 */
927 if (bms_reset)
928 return (params->fcc_uah * 3) / 100;
929
Xiaozhe Shi75e5efe2013-02-07 09:51:43 -0800930 uuc_uah_iavg = calculate_termination_uuc(chip, params, batt_temp,
931 uuc_iavg_ma, &pc_unusable);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700932 pr_debug("uuc_iavg_ma = %d uuc with iavg = %d\n",
933 uuc_iavg_ma, uuc_uah_iavg);
934
935 chip->prev_uuc_iavg_ma = uuc_iavg_ma;
936 /* restrict the uuc such that it can increase only by one percent */
937 uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
938 uuc_uah_iavg, batt_temp);
939
940 chip->first_time_calc_uuc = 0;
941 return uuc_uah_iavg;
942}
943
944static void find_ocv_for_soc(struct qpnp_bms_chip *chip,
945 struct soc_params *params,
946 int batt_temp,
947 int shutdown_soc,
948 int *ret_ocv_uv)
949{
950 s64 ocv_charge_uah;
951 int pc, new_pc;
952 int batt_temp_degc = batt_temp / 10;
953 int ocv_uv;
954
955 ocv_charge_uah = (s64)shutdown_soc
956 * (params->fcc_uah - params->uuc_uah);
957 ocv_charge_uah = div_s64(ocv_charge_uah, 100)
958 + params->cc_uah + params->uuc_uah;
959 pc = DIV_ROUND_CLOSEST((int)ocv_charge_uah * 100, params->fcc_uah);
960 pc = clamp(pc, 0, 100);
961
962 ocv_uv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
963
964 pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
965 shutdown_soc, params->fcc_uah,
966 params->uuc_uah, (int)ocv_charge_uah,
967 pc, ocv_uv);
968 new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv_uv);
969 pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv_uv);
970
971 while (abs(new_pc - pc) > 1) {
972 int delta_mv = 5;
973
974 if (new_pc > pc)
975 delta_mv = -1 * delta_mv;
976
977 ocv_uv = ocv_uv + delta_mv;
978 new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
979 batt_temp_degc, ocv_uv);
980 pr_debug("test revlookup pc = %d for ocv = %d\n",
981 new_pc, ocv_uv);
982 }
983
984 *ret_ocv_uv = ocv_uv * 1000;
985 params->ocv_charge_uah = (int)ocv_charge_uah;
986}
987
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800988static int get_current_time(unsigned long *now_tm_sec)
989{
990 struct rtc_time tm;
991 struct rtc_device *rtc;
992 int rc;
993
994 rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
995 if (rtc == NULL) {
996 pr_err("%s: unable to open rtc device (%s)\n",
997 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
998 rc = -EINVAL;
999 goto close_time;
1000 }
1001
1002 rc = rtc_read_time(rtc, &tm);
1003 if (rc) {
1004 pr_err("Error reading rtc device (%s) : %d\n",
1005 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1006 goto close_time;
1007 }
1008
1009 rc = rtc_valid_tm(&tm);
1010 if (rc) {
1011 pr_err("Invalid RTC time (%s): %d\n",
1012 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1013 goto close_time;
1014 }
1015 rtc_tm_to_time(&tm, now_tm_sec);
1016
1017close_time:
1018 rtc_class_close(rtc);
1019 return rc;
1020}
1021
1022static int calculate_delta_time(struct qpnp_bms_chip *chip, int *delta_time_s)
1023{
1024 unsigned long now_tm_sec = 0;
1025
1026 /* default to delta time = 0 if anything fails */
1027 *delta_time_s = 0;
1028
1029 get_current_time(&now_tm_sec);
1030
1031 *delta_time_s = (now_tm_sec - chip->tm_sec);
1032 pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
1033 chip->tm_sec, now_tm_sec, *delta_time_s);
1034
1035 /* remember this time */
1036 chip->tm_sec = now_tm_sec;
1037 return 0;
1038}
1039
Xiaozhe Shie118c692012-09-24 15:17:43 -07001040static void calculate_soc_params(struct qpnp_bms_chip *chip,
1041 struct raw_soc_params *raw,
1042 struct soc_params *params,
1043 int batt_temp)
1044{
1045 int soc_rbatt;
1046
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001047 calculate_delta_time(chip, &params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001048 params->fcc_uah = calculate_fcc(chip, batt_temp);
1049 pr_debug("FCC = %uuAh batt_temp = %d\n", params->fcc_uah, batt_temp);
1050
1051 /* calculate remainging charge */
1052 params->ocv_charge_uah = calculate_ocv_charge(
1053 chip, raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001054 params->fcc_uah);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001055 pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
1056
1057 /* calculate cc micro_volt_hour */
1058 params->cc_uah = calculate_cc(chip, raw->cc);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -08001059 pr_debug("cc_uah = %duAh raw->cc = %llx\n", params->cc_uah, raw->cc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001060
1061 soc_rbatt = ((params->ocv_charge_uah - params->cc_uah) * 100)
1062 / params->fcc_uah;
1063 if (soc_rbatt < 0)
1064 soc_rbatt = 0;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001065 params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001066
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001067 calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
1068 params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001069
1070 params->uuc_uah = calculate_unusable_charge_uah(chip, params,
1071 batt_temp);
1072 pr_debug("UUC = %uuAh\n", params->uuc_uah);
1073}
1074
1075static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
1076{
1077 if (chip->shutdown_soc_invalid) {
1078 pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
1079 return 0;
1080 }
1081
1082 if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
1083 pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
1084 chip->shutdown_soc, soc,
1085 chip->shutdown_soc_valid_limit);
1086 chip->shutdown_soc_invalid = 1;
1087 return 0;
1088 }
1089
1090 return 1;
1091}
1092
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001093static bool is_battery_charging(struct qpnp_bms_chip *chip)
1094{
1095 union power_supply_propval ret = {0,};
1096
1097 if (chip->batt_psy == NULL)
1098 chip->batt_psy = power_supply_get_by_name("battery");
1099 if (chip->batt_psy) {
1100 /* if battery has been registered, use the status property */
1101 chip->batt_psy->get_property(chip->batt_psy,
1102 POWER_SUPPLY_PROP_STATUS, &ret);
1103 return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
1104 }
1105
1106 /* Default to false if the battery power supply is not registered. */
1107 pr_debug("battery power supply is not registered\n");
1108 return false;
1109}
1110
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001111static bool is_batfet_open(struct qpnp_bms_chip *chip)
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001112{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001113 union power_supply_propval ret = {0,};
1114
1115 if (chip->batt_psy == NULL)
1116 chip->batt_psy = power_supply_get_by_name("battery");
1117 if (chip->batt_psy) {
1118 /* if battery has been registered, use the status property */
1119 chip->batt_psy->get_property(chip->batt_psy,
1120 POWER_SUPPLY_PROP_STATUS, &ret);
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001121 return ret.intval == POWER_SUPPLY_STATUS_FULL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001122 }
1123
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001124 /* Default to true if the battery power supply is not registered. */
1125 pr_debug("battery power supply is not registered\n");
1126 return true;
1127}
1128
1129static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
1130 int *ibat_ua, int *vbat_uv)
1131{
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001132 struct qpnp_iadc_result i_result;
1133 struct qpnp_vadc_result v_result;
1134 enum qpnp_iadc_channels iadc_channel;
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001135 int rc;
1136
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001137 iadc_channel = chip->use_external_rsense ?
1138 EXTERNAL_RSENSE : INTERNAL_RSENSE;
1139 rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
1140 VBAT_SNS, &v_result);
1141 if (rc) {
1142 pr_err("vadc read failed with rc: %d\n", rc);
1143 return rc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001144 }
Xiaozhe Shic9f92dc2013-03-15 11:26:25 -07001145 /*
1146 * reverse the current read by the iadc, since the bms uses
1147 * flipped battery current polarity.
1148 */
1149 *ibat_ua = -1 * (int)i_result.result_ua;
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001150 *vbat_uv = (int)v_result.physical;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001151
1152 return 0;
1153}
1154
1155static int bound_soc(int soc)
1156{
1157 soc = max(0, soc);
1158 soc = min(100, soc);
1159 return soc;
1160}
1161
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001162#define IBAT_TOL_MASK 0x0F
1163#define OCV_TOL_MASK 0xF0
1164#define IBAT_TOL_DEFAULT 0x03
1165#define IBAT_TOL_NOCHG 0x0F
1166#define OCV_TOL_DEFAULT 0x20
1167#define OCV_TOL_NO_OCV 0x00
1168static int stop_ocv_updates(struct qpnp_bms_chip *chip)
1169{
1170 pr_debug("stopping ocv updates\n");
1171 return qpnp_masked_write(chip, BMS1_TOL_CTL,
1172 OCV_TOL_MASK, OCV_TOL_NO_OCV);
1173}
1174
1175static int reset_bms_for_test(struct qpnp_bms_chip *chip)
1176{
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001177 int ibat_ua = 0, vbat_uv = 0, rc;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001178 int ocv_est_uv;
1179
1180 if (!chip) {
1181 pr_err("BMS driver has not been initialized yet!\n");
1182 return -EINVAL;
1183 }
1184
1185 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1186
1187 ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
1188 pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
1189 chip->last_ocv_uv = ocv_est_uv;
1190 chip->last_soc = -EINVAL;
1191 reset_cc(chip);
1192 chip->last_cc_uah = INT_MIN;
1193 stop_ocv_updates(chip);
1194
1195 pr_debug("bms reset to ocv = %duv vbat_ua = %d ibat_ua = %d\n",
1196 chip->last_ocv_uv, vbat_uv, ibat_ua);
1197
1198 return rc;
1199}
1200
1201static int bms_reset_set(const char *val, const struct kernel_param *kp)
1202{
1203 int rc;
1204
1205 rc = param_set_bool(val, kp);
1206 if (rc) {
1207 pr_err("Unable to set bms_reset: %d\n", rc);
1208 return rc;
1209 }
1210
1211 if (*(bool *)kp->arg) {
1212 struct power_supply *bms_psy = power_supply_get_by_name("bms");
1213 struct qpnp_bms_chip *chip = container_of(bms_psy,
1214 struct qpnp_bms_chip, bms_psy);
1215
1216 rc = reset_bms_for_test(chip);
1217 if (rc) {
1218 pr_err("Unable to modify bms_reset: %d\n", rc);
1219 return rc;
1220 }
1221 }
1222 return 0;
1223}
1224
1225static struct kernel_param_ops bms_reset_ops = {
1226 .set = bms_reset_set,
1227 .get = param_get_bool,
1228};
1229
1230module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
1231
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001232static int charging_adjustments(struct qpnp_bms_chip *chip,
1233 struct soc_params *params, int soc,
1234 int vbat_uv, int ibat_ua, int batt_temp)
1235{
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001236 int chg_soc;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001237 int batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001238
1239 if (chip->soc_at_cv == -EINVAL) {
1240 /* In constant current charging return the calc soc */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001241 if (batt_terminal_uv <= chip->max_voltage_uv)
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001242 pr_debug("CC CHG SOC %d\n", soc);
1243
1244 /* Note the CC to CV point */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001245 if (batt_terminal_uv >= chip->max_voltage_uv) {
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001246 chip->soc_at_cv = soc;
1247 chip->prev_chg_soc = soc;
1248 chip->ibat_at_cv_ua = ibat_ua;
1249 pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
1250 ibat_ua, soc);
1251 }
1252 return soc;
1253 }
1254
1255 /*
1256 * battery is in CV phase - begin liner inerpolation of soc based on
1257 * battery charge current
1258 */
1259
1260 /*
1261 * if voltage lessened (possibly because of a system load)
1262 * keep reporting the prev chg soc
1263 */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001264 if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
1265 pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
1266 batt_terminal_uv,
1267 chip->max_voltage_uv, chip->prev_chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001268 return chip->prev_chg_soc;
1269 }
1270
1271 chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001272 100, -1 * chip->chg_term_ua,
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001273 ibat_ua);
Xiaozhe Shi78d0c532012-12-10 13:02:14 -08001274 chg_soc = bound_soc(chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001275
1276 /* always report a higher soc */
1277 if (chg_soc > chip->prev_chg_soc) {
1278 int new_ocv_uv;
1279
1280 chip->prev_chg_soc = chg_soc;
1281
1282 find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
1283 chip->last_ocv_uv = new_ocv_uv;
1284 pr_debug("CC CHG ADJ OCV = %d CHG SOC %d\n",
1285 new_ocv_uv,
1286 chip->prev_chg_soc);
1287 }
1288
1289 pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
1290 return chip->prev_chg_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001291}
1292
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001293static void very_low_voltage_check(struct qpnp_bms_chip *chip, int vbat_uv)
1294{
1295 /*
1296 * if battery is very low (v_cutoff voltage + 20mv) hold
1297 * a wakelock untill soc = 0%
1298 */
1299 if (vbat_uv <= chip->low_voltage_threshold
1300 && !chip->low_voltage_wake_lock_held) {
1301 pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
1302 wake_lock(&chip->low_voltage_wake_lock);
1303 chip->low_voltage_wake_lock_held = 1;
1304 } else if (vbat_uv > chip->low_voltage_threshold
1305 && chip->low_voltage_wake_lock_held) {
1306 pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
1307 chip->low_voltage_wake_lock_held = 0;
1308 wake_unlock(&chip->low_voltage_wake_lock);
1309 }
1310}
1311
Xiaozhe Shie118c692012-09-24 15:17:43 -07001312static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
1313 int soc, int batt_temp)
1314{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001315 int ibat_ua = 0, vbat_uv = 0;
1316 int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
1317 int delta_ocv_uv = 0;
1318 int n = 0;
1319 int rc_new_uah = 0;
1320 int pc_new = 0;
1321 int soc_new = 0;
1322 int slope = 0;
1323 int rc = 0;
1324 int delta_ocv_uv_limit = 0;
1325
1326 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1327 if (rc < 0) {
1328 pr_err("simultaneous vbat ibat failed err = %d\n", rc);
1329 goto out;
1330 }
1331
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001332 very_low_voltage_check(chip, vbat_uv);
1333
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001334 delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
1335
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001336 ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
1337
1338 chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
1339 / (params->rbatt_mohm);
1340
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001341 pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
1342 soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
1343 (s64)params->fcc_uah - params->uuc_uah);
1344 soc_est = bound_soc(soc_est);
1345
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001346 /* never adjust during bms reset mode */
1347 if (bms_reset) {
1348 pr_debug("bms reset mode, SOC adjustment skipped\n");
1349 goto out;
1350 }
1351
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001352 if (ibat_ua < 0 && !is_batfet_open(chip)) {
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001353 soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
1354 batt_temp);
1355 goto out;
1356 }
1357
1358 /*
1359 * do not adjust
1360 * if soc is same as what bms calculated
1361 * if soc_est is between 45 and 25, this is the flat portion of the
1362 * curve where soc_est is not so accurate. We generally don't want to
1363 * adjust when soc_est is inaccurate except for the cases when soc is
1364 * way far off (higher than 50 or lesser than 20).
1365 * Also don't adjust soc if it is above 90 becuase it might be pulled
1366 * low and cause a bad user experience
1367 */
1368 if (soc_est == soc
1369 || (is_between(45, chip->adjust_soc_low_threshold, soc_est)
1370 && is_between(50, chip->adjust_soc_low_threshold - 5, soc))
1371 || soc >= 90)
1372 goto out;
1373
1374 if (chip->last_soc_est == -EINVAL)
1375 chip->last_soc_est = soc;
1376
1377 n = min(200, max(1 , soc + soc_est + chip->last_soc_est));
1378 chip->last_soc_est = soc_est;
1379
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001380 pc = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001381 if (pc > 0) {
1382 pc_new = calculate_pc(chip,
1383 chip->last_ocv_uv - (++slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001384 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001385 while (pc_new == pc) {
1386 /* start taking 10mV steps */
1387 slope = slope + 10;
1388 pc_new = calculate_pc(chip,
1389 chip->last_ocv_uv - (slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001390 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001391 }
1392 } else {
1393 /*
1394 * pc is already at the lowest point,
1395 * assume 1 millivolt translates to 1% pc
1396 */
1397 pc = 1;
1398 pc_new = 0;
1399 slope = 1;
1400 }
1401
1402 delta_ocv_uv = div_s64((soc - soc_est) * (s64)slope * 1000,
1403 n * (pc - pc_new));
1404
1405 if (abs(delta_ocv_uv) > delta_ocv_uv_limit) {
1406 pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
1407 delta_ocv_uv_limit);
1408
1409 if (delta_ocv_uv > 0)
1410 delta_ocv_uv = delta_ocv_uv_limit;
1411 else
1412 delta_ocv_uv = -1 * delta_ocv_uv_limit;
1413 pr_debug("new delta ocv = %d\n", delta_ocv_uv);
1414 }
1415
1416 chip->last_ocv_uv -= delta_ocv_uv;
1417
1418 if (chip->last_ocv_uv >= chip->max_voltage_uv)
1419 chip->last_ocv_uv = chip->max_voltage_uv;
1420
1421 /* calculate the soc based on this new ocv */
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001422 pc_new = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001423 rc_new_uah = (params->fcc_uah * pc_new) / 100;
1424 soc_new = (rc_new_uah - params->cc_uah - params->uuc_uah)*100
1425 / (params->fcc_uah - params->uuc_uah);
1426 soc_new = bound_soc(soc_new);
1427
1428 /*
1429 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
1430 * soc = 0 should happen only when soc_est == 0
1431 */
1432 if (soc_new == 0 && soc_est != 0)
1433 soc_new = 1;
1434
1435 soc = soc_new;
1436
1437out:
1438 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",
1439 ibat_ua, vbat_uv, ocv_est_uv, pc_est,
1440 soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001441 pc_new, soc_new, params->rbatt_mohm, slope);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001442
Xiaozhe Shie118c692012-09-24 15:17:43 -07001443 return soc;
1444}
1445
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001446static int clamp_soc_based_on_voltage(struct qpnp_bms_chip *chip, int soc)
1447{
1448 int rc, vbat_uv;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001449
Xiaozhe Shi36458962013-02-06 16:19:57 -08001450 rc = get_battery_voltage(&vbat_uv);
1451 if (rc < 0) {
1452 pr_err("adc vbat failed err = %d\n", rc);
1453 return soc;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001454 }
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001455 if (soc == 0 && vbat_uv > chip->v_cutoff_uv) {
1456 pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
1457 vbat_uv, chip->v_cutoff_uv);
1458 return 1;
1459 } else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
1460 pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
1461 vbat_uv, chip->v_cutoff_uv);
1462 return 0;
1463 } else {
1464 pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
1465 soc, vbat_uv, chip->v_cutoff_uv);
1466 return soc;
1467 }
1468}
1469
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001470static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
1471 struct raw_soc_params *raw,
1472 int batt_temp)
1473{
Xiaozhe Shie118c692012-09-24 15:17:43 -07001474 int soc, new_ocv_uv;
1475 int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
1476 struct soc_params params;
1477
1478 calculate_soc_params(chip, raw, &params, batt_temp);
1479 /* calculate remaining usable charge */
1480 remaining_usable_charge_uah = params.ocv_charge_uah
1481 - params.cc_uah
1482 - params.uuc_uah;
1483
1484 pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
1485 if (params.fcc_uah - params.uuc_uah <= 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001486 pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001487 params.fcc_uah,
1488 params.uuc_uah);
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001489 new_calculated_soc = 0;
1490 goto done_calculating;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001491 }
1492
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001493 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1494 (params.fcc_uah - params.uuc_uah));
1495
Xiaozhe Shie118c692012-09-24 15:17:43 -07001496 if (chip->first_time_calc_soc && soc < 0) {
1497 /*
1498 * first time calcualtion and the pon ocv is too low resulting
1499 * in a bad soc. Adjust ocv to get 0 soc
1500 */
1501 pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
1502 find_ocv_for_soc(chip, &params, batt_temp, 0, &new_ocv_uv);
1503 chip->last_ocv_uv = new_ocv_uv;
1504
1505 remaining_usable_charge_uah = params.ocv_charge_uah
1506 - params.cc_uah
1507 - params.uuc_uah;
1508
1509 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1510 (params.fcc_uah
1511 - params.uuc_uah));
1512 pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
1513 soc, chip->last_ocv_uv);
1514 }
1515
1516 if (soc > 100)
1517 soc = 100;
1518
1519 if (soc < 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001520 pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001521 remaining_usable_charge_uah,
1522 params.ocv_charge_uah,
1523 params.cc_uah, params.uuc_uah);
1524
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001525 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 -07001526 chip->last_ocv_uv, batt_temp,
1527 params.fcc_uah, soc);
1528 soc = 0;
1529 }
1530
1531 mutex_lock(&chip->soc_invalidation_mutex);
1532 shutdown_soc = chip->shutdown_soc;
1533
1534 if (chip->first_time_calc_soc && soc != shutdown_soc
1535 && is_shutdown_soc_within_limits(chip, soc)) {
1536 /*
1537 * soc for the first time - use shutdown soc
1538 * to adjust pon ocv since it is a small percent away from
1539 * the real soc
1540 */
1541 pr_debug("soc = %d before forcing shutdown_soc = %d\n",
1542 soc, shutdown_soc);
1543 find_ocv_for_soc(chip, &params, batt_temp,
1544 shutdown_soc, &new_ocv_uv);
1545 chip->pon_ocv_uv = chip->last_ocv_uv;
1546 chip->last_ocv_uv = new_ocv_uv;
1547
1548 remaining_usable_charge_uah = params.ocv_charge_uah
1549 - params.cc_uah
1550 - params.uuc_uah;
1551
1552 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1553 (params.fcc_uah
1554 - params.uuc_uah));
1555
1556 pr_debug("DONE for shutdown_soc = %d soc is %d, adjusted ocv to %duV\n",
1557 shutdown_soc, soc, chip->last_ocv_uv);
1558 }
1559 mutex_unlock(&chip->soc_invalidation_mutex);
1560
1561 pr_debug("SOC before adjustment = %d\n", soc);
1562 new_calculated_soc = adjust_soc(chip, &params, soc, batt_temp);
1563
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001564 /* clamp soc due to BMS HW inaccuracies in pm8941v2.0 */
1565 if (chip->revision1 == 0 && chip->revision2 == 0)
1566 new_calculated_soc = clamp_soc_based_on_voltage(chip,
1567 new_calculated_soc);
1568
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001569done_calculating:
Xiaozhe Shie118c692012-09-24 15:17:43 -07001570 if (new_calculated_soc != chip->calculated_soc
1571 && chip->bms_psy.name != NULL) {
1572 power_supply_changed(&chip->bms_psy);
1573 pr_debug("power supply changed\n");
1574 }
1575
1576 chip->calculated_soc = new_calculated_soc;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001577 pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001578 chip->first_time_calc_soc = 0;
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001579 get_current_time(&chip->last_recalc_time);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001580 return chip->calculated_soc;
1581}
1582
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001583static int calculate_soc_from_voltage(struct qpnp_bms_chip *chip)
1584{
1585 int voltage_range_uv, voltage_remaining_uv, voltage_based_soc;
Xiaozhe Shi36458962013-02-06 16:19:57 -08001586 int rc, vbat_uv;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001587
Xiaozhe Shi36458962013-02-06 16:19:57 -08001588 rc = get_battery_voltage(&vbat_uv);
1589 if (rc < 0) {
1590 pr_err("adc vbat failed err = %d\n", rc);
1591 return rc;
1592 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001593 voltage_range_uv = chip->max_voltage_uv - chip->v_cutoff_uv;
1594 voltage_remaining_uv = vbat_uv - chip->v_cutoff_uv;
1595 voltage_based_soc = voltage_remaining_uv * 100 / voltage_range_uv;
1596
1597 voltage_based_soc = clamp(voltage_based_soc, 0, 100);
1598
1599 if (chip->prev_voltage_based_soc != voltage_based_soc
1600 && chip->bms_psy.name != NULL) {
1601 power_supply_changed(&chip->bms_psy);
1602 pr_debug("power supply changed\n");
1603 }
1604 chip->prev_voltage_based_soc = voltage_based_soc;
1605
1606 pr_debug("vbat used = %duv\n", vbat_uv);
1607 pr_debug("Calculated voltage based soc = %d\n", voltage_based_soc);
1608 return voltage_based_soc;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001609}
1610
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001611static int recalculate_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001612{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001613 int batt_temp, rc, soc;
1614 struct qpnp_vadc_result result;
1615 struct raw_soc_params raw;
1616
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001617 wake_lock(&chip->soc_wake_lock);
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001618 if (chip->use_voltage_soc) {
1619 soc = calculate_soc_from_voltage(chip);
1620 } else {
1621 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1622 if (rc) {
1623 pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
1624 LR_MUX1_BATT_THERM, rc);
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001625 soc = chip->calculated_soc;
1626 } else {
1627 pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
1628 result.physical,
1629 result.measurement);
1630 batt_temp = (int)result.physical;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001631
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001632 mutex_lock(&chip->last_ocv_uv_mutex);
1633 read_soc_params_raw(chip, &raw, batt_temp);
1634 soc = calculate_state_of_charge(chip, &raw, batt_temp);
1635 mutex_unlock(&chip->last_ocv_uv_mutex);
1636 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001637 }
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001638 wake_unlock(&chip->soc_wake_lock);
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001639 return soc;
1640}
1641
1642static void calculate_soc_work(struct work_struct *work)
1643{
1644 struct qpnp_bms_chip *chip = container_of(work,
1645 struct qpnp_bms_chip,
1646 calculate_soc_delayed_work.work);
1647 int soc = recalculate_soc(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001648
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001649 if (soc < chip->low_soc_calc_threshold
1650 || chip->low_voltage_wake_lock_held)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001651 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1652 round_jiffies_relative(msecs_to_jiffies
1653 (chip->low_soc_calculate_soc_ms)));
1654 else
1655 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1656 round_jiffies_relative(msecs_to_jiffies
1657 (chip->calculate_soc_ms)));
1658}
1659
Xiaozhe Shie118c692012-09-24 15:17:43 -07001660static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
1661 int soc)
1662{
1663 u8 temp;
1664 int rc;
1665 int iavg_ma = chip->prev_uuc_iavg_ma;
1666
1667 if (iavg_ma > IAVG_START)
1668 temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
1669 else
1670 temp = 0;
1671
1672 rc = qpnp_write_wrapper(chip, &temp,
1673 chip->base + IAVG_STORAGE_REG, 1);
1674
1675 if (soc == 0)
1676 temp = SOC_ZERO;
1677 else
1678 temp = soc;
1679
1680 /* don't store soc if temperature is below 5degC */
1681 if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
1682 rc = qpnp_write_wrapper(chip, &temp,
1683 chip->base + SOC_STORAGE_REG, 1);
1684}
1685
1686#define SOC_CATCHUP_SEC_MAX 600
1687#define SOC_CATCHUP_SEC_PER_PERCENT 60
1688#define MAX_CATCHUP_SOC (SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
1689static int scale_soc_while_chg(struct qpnp_bms_chip *chip,
1690 int delta_time_us, int new_soc, int prev_soc)
1691{
1692 int chg_time_sec;
1693 int catch_up_sec;
1694 int scaled_soc;
1695 int numerator;
1696
1697 /*
1698 * The device must be charging for reporting a higher soc, if
1699 * not ignore this soc and continue reporting the prev_soc.
1700 * Also don't report a high value immediately slowly scale the
1701 * value from prev_soc to the new soc based on a charge time
1702 * weighted average
1703 */
1704
1705 /* if not charging, return last soc */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001706 if (!is_battery_charging(chip))
Xiaozhe Shie118c692012-09-24 15:17:43 -07001707 return prev_soc;
1708
1709 chg_time_sec = DIV_ROUND_UP(chip->charge_time_us, USEC_PER_SEC);
1710 catch_up_sec = DIV_ROUND_UP(chip->catch_up_time_us, USEC_PER_SEC);
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001711 if (catch_up_sec == 0)
1712 return new_soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001713 pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
1714
1715 /*
1716 * if charging for more than catch_up time, simply return
1717 * new soc
1718 */
1719 if (chg_time_sec > catch_up_sec)
1720 return new_soc;
1721
1722 numerator = (catch_up_sec - chg_time_sec) * prev_soc
1723 + chg_time_sec * new_soc;
1724 scaled_soc = numerator / catch_up_sec;
1725
1726 pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
1727 chg_time_sec, new_soc, prev_soc, scaled_soc);
1728
1729 return scaled_soc;
1730}
1731
1732/*
1733 * bms_fake_battery is set in setups where a battery emulator is used instead
1734 * of a real battery. This makes the bms driver report a different/fake value
1735 * regardless of the calculated state of charge.
1736 */
1737static int bms_fake_battery = -EINVAL;
1738module_param(bms_fake_battery, int, 0644);
1739
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001740static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
1741{
1742 pr_debug("Reported voltage based soc = %d\n",
1743 chip->prev_voltage_based_soc);
1744 return chip->prev_voltage_based_soc;
1745}
1746
1747static int report_cc_based_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001748{
1749 int soc;
1750 int delta_time_us;
1751 struct timespec now;
1752 struct qpnp_vadc_result result;
1753 int batt_temp;
1754 int rc;
1755
Xiaozhe Shie118c692012-09-24 15:17:43 -07001756 soc = chip->calculated_soc;
1757
1758 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1759
1760 if (rc) {
1761 pr_err("error reading adc channel = %d, rc = %d\n",
1762 LR_MUX1_BATT_THERM, rc);
1763 return rc;
1764 }
1765 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1766 result.measurement);
1767 batt_temp = (int)result.physical;
1768
1769 do_posix_clock_monotonic_gettime(&now);
1770 if (chip->t_soc_queried.tv_sec != 0) {
1771 delta_time_us
1772 = (now.tv_sec - chip->t_soc_queried.tv_sec) * USEC_PER_SEC
1773 + (now.tv_nsec - chip->t_soc_queried.tv_nsec) / 1000;
1774 } else {
1775 /* calculation for the first time */
1776 delta_time_us = 0;
1777 }
1778
1779 /*
1780 * account for charge time - limit it to SOC_CATCHUP_SEC to
1781 * avoid overflows when charging continues for extended periods
1782 */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001783 if (is_battery_charging(chip)) {
Xiaozhe Shie118c692012-09-24 15:17:43 -07001784 if (chip->charge_time_us == 0) {
1785 /*
1786 * calculating soc for the first time
1787 * after start of chg. Initialize catchup time
1788 */
1789 if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
1790 chip->catch_up_time_us =
1791 (soc - chip->last_soc)
1792 * SOC_CATCHUP_SEC_PER_PERCENT
1793 * USEC_PER_SEC;
1794 else
1795 chip->catch_up_time_us =
1796 SOC_CATCHUP_SEC_MAX * USEC_PER_SEC;
1797
1798 if (chip->catch_up_time_us < 0)
1799 chip->catch_up_time_us = 0;
1800 }
1801
1802 /* add charge time */
1803 if (chip->charge_time_us < SOC_CATCHUP_SEC_MAX * USEC_PER_SEC)
1804 chip->charge_time_us += delta_time_us;
1805
1806 /* end catchup if calculated soc and last soc are same */
1807 if (chip->last_soc == soc)
1808 chip->catch_up_time_us = 0;
1809 }
1810
1811 /* last_soc < soc ... scale and catch up */
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001812 if (chip->last_soc != -EINVAL && chip->last_soc < soc && soc != 100)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001813 soc = scale_soc_while_chg(chip, delta_time_us,
1814 soc, chip->last_soc);
1815
1816 pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
1817 chip->last_soc, chip->calculated_soc, soc);
1818 chip->last_soc = soc;
1819 backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
1820 pr_debug("Reported SOC = %d\n", chip->last_soc);
1821 chip->t_soc_queried = now;
1822
1823 return chip->last_soc;
1824}
1825
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001826static int report_state_of_charge(struct qpnp_bms_chip *chip)
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001827{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001828 if (bms_fake_battery != -EINVAL) {
1829 pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
1830 return bms_fake_battery;
1831 } else if (chip->use_voltage_soc)
1832 return report_voltage_based_soc(chip);
1833 else
1834 return report_cc_based_soc(chip);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001835}
1836
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001837/* Returns capacity as a SoC percentage between 0 and 100 */
1838static int get_prop_bms_capacity(struct qpnp_bms_chip *chip)
1839{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001840 return report_state_of_charge(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001841}
1842
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001843/* Returns estimated max current that the battery can supply in uA */
1844static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
1845{
1846 return chip->ibat_max_ua;
1847}
1848
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001849/* Returns instantaneous current in uA */
1850static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
1851{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001852 int rc, result_ua;
1853
1854 rc = get_battery_current(chip, &result_ua);
1855 if (rc) {
1856 pr_err("failed to get current: %d\n", rc);
1857 return rc;
1858 }
1859 return result_ua;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001860}
1861
1862/* Returns full charge design in uAh */
1863static int get_prop_bms_charge_full_design(struct qpnp_bms_chip *chip)
1864{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001865 return chip->fcc;
1866}
1867
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001868static int get_prop_bms_present(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001869{
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001870 return chip->battery_present;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001871}
1872
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001873static void set_prop_bms_present(struct qpnp_bms_chip *chip, int present)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001874{
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001875 if (chip->battery_present != present)
1876 chip->battery_present = present;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001877}
1878
1879static void qpnp_bms_external_power_changed(struct power_supply *psy)
1880{
1881}
1882
1883static int qpnp_bms_power_get_property(struct power_supply *psy,
1884 enum power_supply_property psp,
1885 union power_supply_propval *val)
1886{
1887 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1888 bms_psy);
1889
1890 switch (psp) {
1891 case POWER_SUPPLY_PROP_CAPACITY:
1892 val->intval = get_prop_bms_capacity(chip);
1893 break;
1894 case POWER_SUPPLY_PROP_CURRENT_NOW:
1895 val->intval = get_prop_bms_current_now(chip);
1896 break;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001897 case POWER_SUPPLY_PROP_CURRENT_MAX:
1898 val->intval = get_prop_bms_current_max(chip);
1899 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001900 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1901 val->intval = get_prop_bms_charge_full_design(chip);
1902 break;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001903 case POWER_SUPPLY_PROP_PRESENT:
1904 val->intval = get_prop_bms_present(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001905 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001906 default:
1907 return -EINVAL;
1908 }
1909 return 0;
1910}
1911
1912static int qpnp_bms_power_set_property(struct power_supply *psy,
1913 enum power_supply_property psp,
1914 const union power_supply_propval *val)
1915{
1916 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1917 bms_psy);
1918
1919 switch (psp) {
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001920 case POWER_SUPPLY_PROP_PRESENT:
1921 set_prop_bms_present(chip, val->intval);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001922 break;
1923 default:
1924 return -EINVAL;
1925 }
1926 return 0;
1927}
1928
Xiaozhe Shibdf14742012-12-05 12:41:48 -08001929#define OCV_USE_LIMIT_EN BIT(7)
1930static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
1931 int low_voltage_threshold,
1932 int high_voltage_threshold)
1933{
1934 uint16_t low_voltage_raw, high_voltage_raw;
1935 int rc;
1936
1937 low_voltage_raw = convert_vbatt_uv_to_raw(chip,
1938 low_voltage_threshold);
1939 high_voltage_raw = convert_vbatt_uv_to_raw(chip,
1940 high_voltage_threshold);
1941 rc = qpnp_write_wrapper(chip, (u8 *)&low_voltage_raw,
1942 chip->base + BMS1_OCV_USE_LOW_LIMIT_THR0, 2);
1943 if (rc) {
1944 pr_err("Failed to set ocv low voltage threshold: %d\n", rc);
1945 return rc;
1946 }
1947 rc = qpnp_write_wrapper(chip, (u8 *)&high_voltage_raw,
1948 chip->base + BMS1_OCV_USE_HIGH_LIMIT_THR0, 2);
1949 if (rc) {
1950 pr_err("Failed to set ocv high voltage threshold: %d\n", rc);
1951 return rc;
1952 }
1953 rc = qpnp_masked_write(chip, BMS1_OCV_USE_LIMIT_CTL,
1954 OCV_USE_LIMIT_EN, OCV_USE_LIMIT_EN);
1955 if (rc) {
1956 pr_err("Failed to enabled ocv voltage thresholds: %d\n", rc);
1957 return rc;
1958 }
1959 pr_debug("ocv low threshold set to %d uv or 0x%x raw\n",
1960 low_voltage_threshold, low_voltage_raw);
1961 pr_debug("ocv high threshold set to %d uv or 0x%x raw\n",
1962 high_voltage_threshold, high_voltage_raw);
1963 return 0;
1964}
1965
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001966static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
1967{
1968 int rc;
1969 u8 temp;
1970
1971 if (chip->ignore_shutdown_soc) {
1972 chip->shutdown_soc_invalid = 1;
1973 chip->shutdown_soc = 0;
1974 chip->shutdown_iavg_ma = 0;
1975 } else {
1976 rc = qpnp_read_wrapper(chip, &temp,
1977 chip->base + IAVG_STORAGE_REG, 1);
1978 if (rc) {
1979 pr_err("failed to read addr = %d %d assuming %d\n",
1980 chip->base + IAVG_STORAGE_REG, rc,
1981 IAVG_START);
1982 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shif5f966d2013-02-19 14:23:11 -08001983 } else if (temp == IAVG_INVALID) {
1984 pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
1985 IAVG_START);
1986 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001987 } else {
1988 if (temp == 0) {
1989 chip->shutdown_iavg_ma = IAVG_START;
1990 } else {
1991 chip->shutdown_iavg_ma = IAVG_START
1992 + IAVG_STEP_SIZE_MA * (temp + 1);
1993 }
1994 }
1995
1996 rc = qpnp_read_wrapper(chip, &temp,
1997 chip->base + SOC_STORAGE_REG, 1);
1998 if (rc) {
1999 pr_err("failed to read addr = %d %d\n",
2000 chip->base + SOC_STORAGE_REG, rc);
2001 } else {
2002 chip->shutdown_soc = temp;
2003
2004 if (chip->shutdown_soc == 0) {
2005 pr_debug("No shutdown soc available\n");
2006 chip->shutdown_soc_invalid = 1;
2007 chip->shutdown_iavg_ma = 0;
2008 } else if (chip->shutdown_soc == SOC_ZERO) {
2009 chip->shutdown_soc = 0;
2010 }
2011 }
2012 }
2013
2014 pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
2015 chip->shutdown_soc,
2016 chip->shutdown_iavg_ma,
2017 chip->shutdown_soc_invalid);
2018}
2019
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002020#define PALLADIUM_ID_MIN 0x7F40
2021#define PALLADIUM_ID_MAX 0x7F5A
2022#define DESAY_5200_ID_MIN 0x7F7F
2023#define DESAY_5200_ID_MAX 0x802F
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002024static int32_t read_battery_id(struct qpnp_bms_chip *chip)
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002025{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002026 int rc;
2027 struct qpnp_vadc_result result;
2028
2029 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2030 if (rc) {
2031 pr_err("error reading batt id channel = %d, rc = %d\n",
2032 LR_MUX2_BAT_ID, rc);
2033 return rc;
2034 }
2035 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
2036 result.measurement);
2037 pr_debug("raw_code = 0x%x\n", result.adc_code);
2038 return result.adc_code;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002039}
2040
2041static int set_battery_data(struct qpnp_bms_chip *chip)
2042{
2043 int64_t battery_id;
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002044 struct bms_battery_data *batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002045
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002046 if (chip->batt_type == BATT_DESAY) {
2047 batt_data = &desay_5200_data;
2048 } else if (chip->batt_type == BATT_PALLADIUM) {
2049 batt_data = &palladium_1500_data;
2050 } else if (chip->batt_type == BATT_OEM) {
2051 batt_data = &oem_batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002052 } else {
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002053 battery_id = read_battery_id(chip);
2054 if (battery_id < 0) {
2055 pr_err("cannot read battery id err = %lld\n",
2056 battery_id);
2057 return battery_id;
2058 }
2059
2060 if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
2061 battery_id)) {
2062 batt_data = &palladium_1500_data;
2063 } else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
2064 battery_id)) {
2065 batt_data = &desay_5200_data;
2066 } else {
2067 pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
2068 battery_id);
2069 batt_data = &palladium_1500_data;
2070 }
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002071 }
2072
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002073 chip->fcc = batt_data->fcc;
2074 chip->fcc_temp_lut = batt_data->fcc_temp_lut;
2075 chip->fcc_sf_lut = batt_data->fcc_sf_lut;
2076 chip->pc_temp_ocv_lut = batt_data->pc_temp_ocv_lut;
2077 chip->pc_sf_lut = batt_data->pc_sf_lut;
2078 chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
2079 chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
2080
2081 if (chip->pc_temp_ocv_lut == NULL) {
2082 pr_err("temp ocv lut table is NULL\n");
2083 return -EINVAL;
2084 }
2085 return 0;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002086}
2087
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002088#define SPMI_PROP_READ(chip_prop, qpnp_spmi_property, retval) \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002089do { \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002090 retval = of_property_read_u32(chip->spmi->dev.of_node, \
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002091 "qcom," qpnp_spmi_property, \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002092 &chip->chip_prop); \
2093 if (retval) { \
2094 pr_err("Error reading " #qpnp_spmi_property \
2095 " property %d\n", rc); \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002096 return -EINVAL; \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002097 } \
2098} while (0)
2099
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002100static inline int bms_read_properties(struct qpnp_bms_chip *chip)
2101{
2102 int rc;
2103
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002104 SPMI_PROP_READ(r_sense_uohm, "r-sense-uohm", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002105 SPMI_PROP_READ(v_cutoff_uv, "v-cutoff-uv", rc);
2106 SPMI_PROP_READ(max_voltage_uv, "max-voltage-uv", rc);
2107 SPMI_PROP_READ(r_conn_mohm, "r-conn-mohm", rc);
2108 SPMI_PROP_READ(chg_term_ua, "chg-term-ua", rc);
2109 SPMI_PROP_READ(shutdown_soc_valid_limit,
2110 "shutdown-soc-valid-limit", rc);
2111 SPMI_PROP_READ(adjust_soc_high_threshold,
2112 "adjust-soc-high-threshold", rc);
2113 SPMI_PROP_READ(adjust_soc_low_threshold,
2114 "adjust-soc-low-threshold", rc);
2115 SPMI_PROP_READ(batt_type, "batt-type", rc);
2116 SPMI_PROP_READ(low_soc_calc_threshold,
2117 "low-soc-calculate-soc-threshold", rc);
2118 SPMI_PROP_READ(low_soc_calculate_soc_ms,
2119 "low-soc-calculate-soc-ms", rc);
2120 SPMI_PROP_READ(calculate_soc_ms, "calculate-soc-ms", rc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002121 chip->use_external_rsense = of_property_read_bool(
2122 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002123 "qcom,use-external-rsense");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002124 chip->ignore_shutdown_soc = of_property_read_bool(
2125 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002126 "qcom,ignore-shutdown-soc");
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002127 chip->use_voltage_soc = of_property_read_bool(chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002128 "qcom,use-voltage-soc");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002129 chip->use_ocv_thresholds = of_property_read_bool(
2130 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002131 "qcom,use-ocv-thresholds");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002132 SPMI_PROP_READ(ocv_high_threshold_uv,
2133 "ocv-voltage-high-threshold-uv", rc);
2134 SPMI_PROP_READ(ocv_low_threshold_uv,
2135 "ocv-voltage-low-threshold-uv", rc);
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002136 SPMI_PROP_READ(low_voltage_threshold, "low-voltage-threshold", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002137
2138 if (chip->adjust_soc_low_threshold >= 45)
2139 chip->adjust_soc_low_threshold = 45;
2140
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002141 pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
2142 chip->r_sense_uohm, chip->v_cutoff_uv,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002143 chip->max_voltage_uv);
2144 pr_debug("r_conn:%d, shutdown_soc: %d, adjust_soc_low:%d\n",
2145 chip->r_conn_mohm, chip->shutdown_soc_valid_limit,
2146 chip->adjust_soc_low_threshold);
2147 pr_debug("adjust_soc_high:%d, chg_term_ua:%d, batt_type:%d\n",
2148 chip->adjust_soc_high_threshold, chip->chg_term_ua,
2149 chip->batt_type);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08002150 pr_debug("ignore_shutdown_soc:%d, use_voltage_soc:%d\n",
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002151 chip->ignore_shutdown_soc, chip->use_voltage_soc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002152 pr_debug("use external rsense: %d\n", chip->use_external_rsense);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002153 return 0;
2154}
2155
2156static inline void bms_initialize_constants(struct qpnp_bms_chip *chip)
2157{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002158 chip->prev_pc_unusable = -EINVAL;
2159 chip->soc_at_cv = -EINVAL;
2160 chip->calculated_soc = -EINVAL;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002161 chip->last_soc = -EINVAL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07002162 chip->last_soc_est = -EINVAL;
Xiaozhe Shif36d2862013-01-04 10:17:35 -08002163 chip->last_cc_uah = INT_MIN;
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -08002164 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
2165 chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002166 chip->first_time_calc_soc = 1;
2167 chip->first_time_calc_uuc = 1;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002168}
2169
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002170#define REG_OFFSET_PERP_TYPE 0x04
2171#define REG_OFFSET_PERP_SUBTYPE 0x05
2172#define BMS_BMS_TYPE 0xD
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002173#define BMS_BMS1_SUBTYPE 0x1
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002174#define BMS_IADC_TYPE 0x8
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002175#define BMS_IADC1_SUBTYPE 0x3
2176#define BMS_IADC2_SUBTYPE 0x5
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002177
2178static int register_spmi(struct qpnp_bms_chip *chip, struct spmi_device *spmi)
2179{
2180 struct spmi_resource *spmi_resource;
2181 struct resource *resource;
2182 int rc;
2183 u8 type, subtype;
2184
2185 chip->dev = &(spmi->dev);
2186 chip->spmi = spmi;
2187
2188 spmi_for_each_container_dev(spmi_resource, spmi) {
2189 if (!spmi_resource) {
2190 pr_err("qpnp_bms: spmi resource absent\n");
2191 return -ENXIO;
2192 }
2193
2194 resource = spmi_get_resource(spmi, spmi_resource,
2195 IORESOURCE_MEM, 0);
2196 if (!(resource && resource->start)) {
2197 pr_err("node %s IO resource absent!\n",
2198 spmi->dev.of_node->full_name);
2199 return -ENXIO;
2200 }
2201
2202 rc = qpnp_read_wrapper(chip, &type,
2203 resource->start + REG_OFFSET_PERP_TYPE, 1);
2204 if (rc) {
2205 pr_err("Peripheral type read failed rc=%d\n", rc);
2206 return rc;
2207 }
2208 rc = qpnp_read_wrapper(chip, &subtype,
2209 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2210 if (rc) {
2211 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2212 return rc;
2213 }
2214
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002215 if (type == BMS_BMS_TYPE && subtype == BMS_BMS1_SUBTYPE) {
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002216 chip->base = resource->start;
2217 } else if (type == BMS_IADC_TYPE
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002218 && (subtype == BMS_IADC1_SUBTYPE
2219 || subtype == BMS_IADC2_SUBTYPE)) {
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002220 chip->iadc_base = resource->start;
2221 } else {
2222 pr_err("Invalid peripheral start=0x%x type=0x%x, subtype=0x%x\n",
2223 resource->start, type, subtype);
2224 }
2225 }
2226
2227 if (chip->base == 0) {
2228 dev_err(&spmi->dev, "BMS peripheral was not registered\n");
2229 return -EINVAL;
2230 }
2231 if (chip->iadc_base == 0) {
2232 dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
2233 return -EINVAL;
2234 }
2235
2236 return 0;
2237}
2238
2239#define ADC_CH_SEL_MASK 0x7
2240static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
2241{
2242 u8 iadc_channel_select;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002243 int32_t rds_rsense_nohm;
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002244 int rc;
2245
2246 rc = qpnp_read_wrapper(chip, &iadc_channel_select,
2247 chip->iadc_base + IADC1_BMS_ADC_CH_SEL_CTL, 1);
2248 if (rc) {
2249 pr_err("Error reading bms_iadc channel register %d\n", rc);
2250 return rc;
2251 }
2252
2253 iadc_channel_select &= ADC_CH_SEL_MASK;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002254 if (iadc_channel_select != EXTERNAL_RSENSE
2255 && iadc_channel_select != INTERNAL_RSENSE) {
2256 pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
2257 iadc_channel_select);
2258 return -EINVAL;
2259 }
2260
2261 if (chip->use_external_rsense) {
2262 pr_debug("External rsense selected\n");
2263 if (iadc_channel_select == INTERNAL_RSENSE) {
2264 pr_debug("Internal rsense detected; Changing rsense to external\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002265 rc = qpnp_masked_write_iadc(chip,
2266 IADC1_BMS_ADC_CH_SEL_CTL,
2267 ADC_CH_SEL_MASK,
2268 EXTERNAL_RSENSE);
2269 if (rc) {
2270 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2271 IADC1_BMS_ADC_CH_SEL_CTL,
2272 EXTERNAL_RSENSE, rc);
2273 return rc;
2274 }
2275 reset_cc(chip);
2276 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002277 } else {
2278 pr_debug("Internal rsense selected\n");
2279 if (iadc_channel_select == EXTERNAL_RSENSE) {
2280 pr_debug("External rsense detected; Changing rsense to internal\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002281 rc = qpnp_masked_write_iadc(chip,
2282 IADC1_BMS_ADC_CH_SEL_CTL,
2283 ADC_CH_SEL_MASK,
2284 INTERNAL_RSENSE);
2285 if (rc) {
2286 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2287 IADC1_BMS_ADC_CH_SEL_CTL,
2288 INTERNAL_RSENSE, rc);
2289 return rc;
2290 }
2291 reset_cc(chip);
2292 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002293
2294 rc = qpnp_iadc_get_rsense(&rds_rsense_nohm);
2295 if (rc) {
2296 pr_err("Unable to read RDS resistance value from IADC; rc = %d\n",
2297 rc);
2298 return rc;
2299 }
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002300 chip->r_sense_uohm = rds_rsense_nohm/1000;
2301 pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
2302 rds_rsense_nohm, chip->r_sense_uohm);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002303 }
2304 return 0;
2305}
2306
2307static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002308{
2309 struct qpnp_bms_chip *chip;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002310 union power_supply_propval retval = {0,};
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002311 int rc, vbatt;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002312
2313 chip = kzalloc(sizeof *chip, GFP_KERNEL);
2314
2315 if (chip == NULL) {
2316 pr_err("kzalloc() failed.\n");
2317 return -ENOMEM;
2318 }
2319
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002320 rc = qpnp_vadc_is_ready();
2321 if (rc) {
2322 pr_info("vadc not ready: %d, deferring probe\n", rc);
2323 goto error_read;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002324 }
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002325
2326 rc = qpnp_iadc_is_ready();
2327 if (rc) {
2328 pr_info("iadc not ready: %d, deferring probe\n", rc);
2329 goto error_read;
2330 }
2331
2332 rc = register_spmi(chip, spmi);
2333 if (rc) {
2334 pr_err("error registering spmi resource %d\n", rc);
2335 goto error_resource;
2336 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002337
2338 rc = qpnp_read_wrapper(chip, &chip->revision1,
2339 chip->base + BMS1_REVISION1, 1);
2340 if (rc) {
2341 pr_err("error reading version register %d\n", rc);
2342 goto error_read;
2343 }
2344
2345 rc = qpnp_read_wrapper(chip, &chip->revision2,
2346 chip->base + BMS1_REVISION2, 1);
2347 if (rc) {
2348 pr_err("Error reading version register %d\n", rc);
2349 goto error_read;
2350 }
Xiaozhe Shia045a562012-11-28 16:55:39 -08002351 pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002352
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002353 rc = bms_read_properties(chip);
2354 if (rc) {
2355 pr_err("Unable to read all bms properties, rc = %d\n", rc);
2356 goto error_read;
2357 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002358
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002359 rc = read_iadc_channel_select(chip);
2360 if (rc) {
2361 pr_err("Unable to get iadc selected channel = %d\n", rc);
2362 goto error_read;
2363 }
2364
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002365 if (chip->use_ocv_thresholds) {
2366 rc = set_ocv_voltage_thresholds(chip,
2367 chip->ocv_low_threshold_uv,
2368 chip->ocv_high_threshold_uv);
2369 if (rc) {
2370 pr_err("Could not set ocv voltage thresholds: %d\n",
2371 rc);
2372 goto error_read;
2373 }
2374 }
2375
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002376 rc = set_battery_data(chip);
2377 if (rc) {
2378 pr_err("Bad battery data %d\n", rc);
2379 goto error_read;
2380 }
2381
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002382 bms_initialize_constants(chip);
2383
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002384 mutex_init(&chip->bms_output_lock);
2385 mutex_init(&chip->last_ocv_uv_mutex);
2386 mutex_init(&chip->soc_invalidation_mutex);
2387
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002388 wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
2389 "qpnp_soc_lock");
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002390 wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
2391 "qpnp_low_voltage_lock");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002392 INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
2393 calculate_soc_work);
2394
2395 read_shutdown_soc_and_iavg(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002396
2397 dev_set_drvdata(&spmi->dev, chip);
2398 device_init_wakeup(&spmi->dev, 1);
2399
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002400 if (!chip->batt_psy)
2401 chip->batt_psy = power_supply_get_by_name("battery");
2402 if (chip->batt_psy) {
2403 chip->batt_psy->get_property(chip->batt_psy,
2404 POWER_SUPPLY_PROP_PRESENT, &retval);
2405 chip->battery_present = retval.intval;
2406 }
2407
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002408 calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
2409
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002410 /* setup & register the battery power supply */
2411 chip->bms_psy.name = "bms";
2412 chip->bms_psy.type = POWER_SUPPLY_TYPE_BMS;
2413 chip->bms_psy.properties = msm_bms_power_props;
2414 chip->bms_psy.num_properties = ARRAY_SIZE(msm_bms_power_props);
2415 chip->bms_psy.get_property = qpnp_bms_power_get_property;
2416 chip->bms_psy.set_property = qpnp_bms_power_set_property;
2417 chip->bms_psy.external_power_changed =
2418 qpnp_bms_external_power_changed;
2419 chip->bms_psy.supplied_to = qpnp_bms_supplicants;
2420 chip->bms_psy.num_supplicants = ARRAY_SIZE(qpnp_bms_supplicants);
2421
2422 rc = power_supply_register(chip->dev, &chip->bms_psy);
2423
2424 if (rc < 0) {
2425 pr_err("power_supply_register bms failed rc = %d\n", rc);
2426 goto unregister_dc;
2427 }
2428
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002429 vbatt = 0;
Xiaozhe Shi36458962013-02-06 16:19:57 -08002430 rc = get_battery_voltage(&vbatt);
2431 if (rc) {
2432 pr_err("error reading vbat_sns adc channel = %d, rc = %d\n",
2433 VBAT_SNS, rc);
2434 goto unregister_dc;
2435 }
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002436
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002437 pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u\n",
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002438 get_prop_bms_capacity(chip),
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002439 vbatt, chip->last_ocv_uv, chip->r_sense_uohm);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002440 return 0;
2441
2442unregister_dc:
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002443 wake_lock_destroy(&chip->soc_wake_lock);
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002444 wake_lock_destroy(&chip->low_voltage_wake_lock);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002445 power_supply_unregister(&chip->bms_psy);
2446 dev_set_drvdata(&spmi->dev, NULL);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002447error_resource:
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002448error_read:
2449 kfree(chip);
2450 return rc;
2451}
2452
2453static int __devexit
2454qpnp_bms_remove(struct spmi_device *spmi)
2455{
2456 struct qpnp_bms_chip *chip = dev_get_drvdata(&spmi->dev);
2457
2458 dev_set_drvdata(&spmi->dev, NULL);
2459 kfree(chip);
2460 return 0;
2461}
2462
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002463static int bms_resume(struct device *dev)
2464{
2465 int rc;
2466 unsigned long soc_calc_period;
2467 unsigned long time_since_last_recalc;
2468 unsigned long tm_now_sec;
2469 struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
2470
2471 rc = get_current_time(&tm_now_sec);
2472 if (rc) {
2473 pr_err("Could not read current time: %d\n", rc);
2474 } else if (tm_now_sec > chip->last_recalc_time) {
2475 time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
2476 pr_debug("Time since last recalc: %lu\n",
2477 time_since_last_recalc);
2478 if (chip->calculated_soc < chip->low_soc_calc_threshold)
2479 soc_calc_period = chip->low_soc_calculate_soc_ms;
2480 else
2481 soc_calc_period = chip->calculate_soc_ms;
2482
2483 if (time_since_last_recalc >= soc_calc_period) {
2484 chip->last_recalc_time = tm_now_sec;
2485 recalculate_soc(chip);
2486 }
2487 }
2488 return 0;
2489}
2490
2491static const struct dev_pm_ops qpnp_bms_pm_ops = {
2492 .resume = bms_resume,
2493};
2494
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002495static struct spmi_driver qpnp_bms_driver = {
2496 .probe = qpnp_bms_probe,
2497 .remove = __devexit_p(qpnp_bms_remove),
2498 .driver = {
2499 .name = QPNP_BMS_DEV_NAME,
2500 .owner = THIS_MODULE,
2501 .of_match_table = qpnp_bms_match_table,
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002502 .pm = &qpnp_bms_pm_ops,
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002503 },
2504};
2505
2506static int __init qpnp_bms_init(void)
2507{
2508 pr_info("QPNP BMS INIT\n");
2509 return spmi_driver_register(&qpnp_bms_driver);
2510}
2511
2512static void __exit qpnp_bms_exit(void)
2513{
2514 pr_info("QPNP BMS EXIT\n");
2515 return spmi_driver_unregister(&qpnp_bms_driver);
2516}
2517
2518module_init(qpnp_bms_init);
2519module_exit(qpnp_bms_exit);
2520
2521MODULE_DESCRIPTION("QPNP BMS Driver");
2522MODULE_LICENSE("GPL v2");
2523MODULE_ALIAS("platform:" QPNP_BMS_DEV_NAME);