blob: 2765836063bd8bc7434932ae29c8e84dc116bc55 [file] [log] [blame]
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Xiaozhe Shi73a65692012-09-18 17:51:57 -070013#define pr_fmt(fmt) "BMS: %s: " fmt, __func__
Xiaozhe Shib19f7032012-08-16 12:14:16 -070014
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <linux/err.h>
20#include <linux/of.h>
21#include <linux/of_device.h>
22#include <linux/power_supply.h>
23#include <linux/spmi.h>
Xiaozhe Shie118c692012-09-24 15:17:43 -070024#include <linux/rtc.h>
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -070025#include <linux/delay.h>
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070026#include <linux/qpnp/qpnp-adc.h>
Xiaozhe Shi73a65692012-09-18 17:51:57 -070027#include <linux/mfd/pm8xxx/batterydata-lib.h>
Xiaozhe Shib19f7032012-08-16 12:14:16 -070028
Xiaozhe Shib19f7032012-08-16 12:14:16 -070029/* BMS Register Offsets */
30#define BMS1_REVISION1 0x0
31#define BMS1_REVISION2 0x1
32#define BMS1_STATUS1 0x8
33#define BMS1_MODE_CTL 0X40
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070034/* Coulomb counter clear registers */
Xiaozhe Shib19f7032012-08-16 12:14:16 -070035#define BMS1_CC_DATA_CTL 0x42
Xiaozhe Shia045a562012-11-28 16:55:39 -080036#define BMS1_CC_CLEAR_CTL 0x43
Xiaozhe Shi20640b52013-01-03 11:49:30 -080037/* BMS Tolerances */
38#define BMS1_TOL_CTL 0X44
Xiaozhe Shib19f7032012-08-16 12:14:16 -070039/* OCV limit registers */
40#define BMS1_OCV_USE_LOW_LIMIT_THR0 0x48
41#define BMS1_OCV_USE_LOW_LIMIT_THR1 0x49
42#define BMS1_OCV_USE_HIGH_LIMIT_THR0 0x4A
43#define BMS1_OCV_USE_HIGH_LIMIT_THR1 0x4B
44#define BMS1_OCV_USE_LIMIT_CTL 0x4C
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -070045/* Delay control */
46#define BMS1_S1_DELAY_CTL 0x5A
Xiaozhe Shib19f7032012-08-16 12:14:16 -070047/* CC interrupt threshold */
48#define BMS1_CC_THR0 0x7A
49#define BMS1_CC_THR1 0x7B
50#define BMS1_CC_THR2 0x7C
51#define BMS1_CC_THR3 0x7D
52#define BMS1_CC_THR4 0x7E
53/* OCV for r registers */
54#define BMS1_OCV_FOR_R_DATA0 0x80
55#define BMS1_OCV_FOR_R_DATA1 0x81
56#define BMS1_VSENSE_FOR_R_DATA0 0x82
57#define BMS1_VSENSE_FOR_R_DATA1 0x83
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070058/* Coulomb counter data */
Xiaozhe Shib19f7032012-08-16 12:14:16 -070059#define BMS1_CC_DATA0 0x8A
60#define BMS1_CC_DATA1 0x8B
61#define BMS1_CC_DATA2 0x8C
62#define BMS1_CC_DATA3 0x8D
63#define BMS1_CC_DATA4 0x8E
64/* OCV for soc data */
65#define BMS1_OCV_FOR_SOC_DATA0 0x90
66#define BMS1_OCV_FOR_SOC_DATA1 0x91
67#define BMS1_VSENSE_PON_DATA0 0x94
68#define BMS1_VSENSE_PON_DATA1 0x95
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070069#define BMS1_VSENSE_AVG_DATA0 0x98
70#define BMS1_VSENSE_AVG_DATA1 0x99
Xiaozhe Shib19f7032012-08-16 12:14:16 -070071#define BMS1_VBAT_AVG_DATA0 0x9E
72#define BMS1_VBAT_AVG_DATA1 0x9F
73/* Extra bms registers */
Xiaozhe Shi57058942013-03-27 16:54:54 -070074#define SOC_STORAGE_REG 0xB0
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070075#define IAVG_STORAGE_REG 0xB1
Xiaozhe Shi57058942013-03-27 16:54:54 -070076#define BMS1_BMS_DATA_REG_2 0xB2
Xiaozhe Shib19f7032012-08-16 12:14:16 -070077#define BMS1_BMS_DATA_REG_3 0xB3
Xiaozhe Shic40b3972012-11-30 14:11:16 -080078/* IADC Channel Select */
79#define IADC1_BMS_ADC_CH_SEL_CTL 0x48
Xiaozhe Shib19f7032012-08-16 12:14:16 -070080
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070081/* Configuration for saving of shutdown soc/iavg */
82#define IGNORE_SOC_TEMP_DECIDEG 50
83#define IAVG_STEP_SIZE_MA 50
84#define IAVG_START 600
Xiaozhe Shif5f966d2013-02-19 14:23:11 -080085#define IAVG_INVALID 0xFF
Xiaozhe Shic7cbd052013-03-29 12:03:11 -070086#define SOC_INVALID 0xFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070087
Xiaozhe Shie118c692012-09-24 15:17:43 -070088#define IAVG_SAMPLES 16
89
Xiaozhe Shib19f7032012-08-16 12:14:16 -070090#define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
91
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070092struct soc_params {
93 int fcc_uah;
94 int cc_uah;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -080095 int rbatt_mohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -070096 int iavg_ua;
97 int uuc_uah;
98 int ocv_charge_uah;
Xiaozhe Shif36d2862013-01-04 10:17:35 -080099 int delta_time_s;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700100};
101
102struct raw_soc_params {
103 uint16_t last_good_ocv_raw;
104 int64_t cc;
105 int last_good_ocv_uv;
106};
107
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700108struct qpnp_bms_chip {
109 struct device *dev;
110 struct power_supply bms_psy;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700111 struct power_supply *batt_psy;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700112 struct spmi_device *spmi;
113 u16 base;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800114 u16 iadc_base;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700115
116 u8 revision1;
117 u8 revision2;
Xiaozhe Shid5d21412013-02-06 17:14:41 -0800118 int battery_present;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800119 bool new_battery;
120 bool last_soc_invalid;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700121 /* platform data */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -0800122 int r_sense_uohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700123 unsigned int v_cutoff_uv;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -0800124 int max_voltage_uv;
125 int r_conn_mohm;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700126 int shutdown_soc_valid_limit;
127 int adjust_soc_low_threshold;
128 int adjust_soc_high_threshold;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700129 int chg_term_ua;
Xiaozhe Shi73a65692012-09-18 17:51:57 -0700130 enum battery_type batt_type;
131 unsigned int fcc;
132 struct single_row_lut *fcc_temp_lut;
133 struct single_row_lut *fcc_sf_lut;
134 struct pc_temp_ocv_lut *pc_temp_ocv_lut;
135 struct sf_lut *pc_sf_lut;
136 struct sf_lut *rbatt_sf_lut;
137 int default_rbatt_mohm;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700138
139 struct delayed_work calculate_soc_delayed_work;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800140 struct work_struct recalc_work;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700141
142 struct mutex bms_output_lock;
143 struct mutex last_ocv_uv_mutex;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700144 struct mutex soc_invalidation_mutex;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700145
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800146 bool use_external_rsense;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800147 bool use_ocv_thresholds;
Xiaozhe Shic40b3972012-11-30 14:11:16 -0800148
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700149 bool ignore_shutdown_soc;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800150 bool shutdown_soc_invalid;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700151 int shutdown_soc;
152 int shutdown_iavg_ma;
153
Xiaozhe Shi4be85782013-02-22 17:33:40 -0800154 struct wake_lock low_voltage_wake_lock;
155 bool low_voltage_wake_lock_held;
156 int low_voltage_threshold;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700157 int low_soc_calc_threshold;
158 int low_soc_calculate_soc_ms;
159 int calculate_soc_ms;
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -0800160 struct wake_lock soc_wake_lock;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700161
Xiaozhe Shie118c692012-09-24 15:17:43 -0700162 uint16_t ocv_reading_at_100;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700163 uint16_t prev_last_good_ocv_raw;
164 int last_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800165 int last_ocv_temp;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700166 int last_cc_uah;
167 unsigned long tm_sec;
168 bool first_time_calc_soc;
169 bool first_time_calc_uuc;
170 int pon_ocv_uv;
171
172 int iavg_samples_ma[IAVG_SAMPLES];
173 int iavg_index;
174 int iavg_num_samples;
175 struct timespec t_soc_queried;
176 int last_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -0700177 int last_soc_est;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700178
179 int charge_time_us;
180 int catch_up_time_us;
181 struct single_row_lut *adjusted_fcc_temp_lut;
182
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700183 unsigned int vadc_v0625;
184 unsigned int vadc_v1250;
185
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800186 int ibat_max_ua;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700187 int prev_uuc_iavg_ma;
188 int prev_pc_unusable;
189 int ibat_at_cv_ua;
190 int soc_at_cv;
191 int prev_chg_soc;
192 int calculated_soc;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -0800193 int prev_voltage_based_soc;
194 bool use_voltage_soc;
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800195
196 int ocv_high_threshold_uv;
197 int ocv_low_threshold_uv;
Xiaozhe Shicdeee312012-12-18 15:10:18 -0800198 unsigned long last_recalc_time;
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700199};
200
201static struct of_device_id qpnp_bms_match_table[] = {
202 { .compatible = QPNP_BMS_DEV_NAME },
203 {}
204};
205
206static char *qpnp_bms_supplicants[] = {
207 "battery"
208};
209
210static enum power_supply_property msm_bms_power_props[] = {
Xiaozhe Shid5d21412013-02-06 17:14:41 -0800211 POWER_SUPPLY_PROP_PRESENT,
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700212 POWER_SUPPLY_PROP_CAPACITY,
213 POWER_SUPPLY_PROP_CURRENT_NOW,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800214 POWER_SUPPLY_PROP_CURRENT_MAX,
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700215 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
216};
217
Xiaozhe Shi20640b52013-01-03 11:49:30 -0800218static bool bms_reset;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -0800219
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700220static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
221 u16 base, int count)
222{
223 int rc;
224 struct spmi_device *spmi = chip->spmi;
225
226 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700227 if (rc) {
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700228 pr_err("SPMI read failed rc=%d\n", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700229 return rc;
230 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -0700231 return 0;
232}
233
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700234static int qpnp_write_wrapper(struct qpnp_bms_chip *chip, u8 *val,
235 u16 base, int count)
236{
237 int rc;
238 struct spmi_device *spmi = chip->spmi;
239
240 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
241 if (rc) {
242 pr_err("SPMI write failed rc=%d\n", rc);
243 return rc;
244 }
245 return 0;
246}
247
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800248static int qpnp_masked_write_base(struct qpnp_bms_chip *chip, u16 addr,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700249 u8 mask, u8 val)
250{
251 int rc;
252 u8 reg;
253
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800254 rc = qpnp_read_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700255 if (rc) {
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800256 pr_err("read failed addr = %03X, rc = %d\n", addr, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700257 return rc;
258 }
259 reg &= ~mask;
260 reg |= val & mask;
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800261 rc = qpnp_write_wrapper(chip, &reg, addr, 1);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700262 if (rc) {
263 pr_err("write failed addr = %03X, val = %02x, mask = %02x, reg = %02x, rc = %d\n",
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800264 addr, val, mask, reg, rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700265 return rc;
266 }
267 return 0;
268}
269
Xiaozhe Shidffbe692012-12-11 15:35:46 -0800270static int qpnp_masked_write_iadc(struct qpnp_bms_chip *chip, u16 addr,
271 u8 mask, u8 val)
272{
273 return qpnp_masked_write_base(chip, chip->iadc_base + addr, mask, val);
274}
275
276static int qpnp_masked_write(struct qpnp_bms_chip *chip, u16 addr,
277 u8 mask, u8 val)
278{
279 return qpnp_masked_write_base(chip, chip->base + addr, mask, val);
280}
281
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700282#define HOLD_OREG_DATA BIT(0)
283static int lock_output_data(struct qpnp_bms_chip *chip)
284{
285 int rc;
286
287 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL,
288 HOLD_OREG_DATA, HOLD_OREG_DATA);
289 if (rc) {
290 pr_err("couldnt lock bms output rc = %d\n", rc);
291 return rc;
292 }
293 return 0;
294}
295
296static int unlock_output_data(struct qpnp_bms_chip *chip)
297{
298 int rc;
299
300 rc = qpnp_masked_write(chip, BMS1_CC_DATA_CTL, HOLD_OREG_DATA, 0);
301 if (rc) {
302 pr_err("fail to unlock BMS_CONTROL rc = %d\n", rc);
303 return rc;
304 }
305 return 0;
306}
307
308#define V_PER_BIT_MUL_FACTOR 97656
309#define V_PER_BIT_DIV_FACTOR 1000
310#define VADC_INTRINSIC_OFFSET 0x6000
311
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800312static int vadc_reading_to_uv(int reading)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700313{
314 if (reading <= VADC_INTRINSIC_OFFSET)
315 return 0;
316
317 return (reading - VADC_INTRINSIC_OFFSET)
318 * V_PER_BIT_MUL_FACTOR / V_PER_BIT_DIV_FACTOR;
319}
320
321#define VADC_CALIB_UV 625000
322#define VBATT_MUL_FACTOR 3
323
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800324static int adjust_vbatt_reading(struct qpnp_bms_chip *chip, int reading_uv)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700325{
326 s64 numerator, denominator;
327
328 if (reading_uv == 0)
329 return 0;
330
331 /* don't adjust if not calibrated */
332 if (chip->vadc_v0625 == 0 || chip->vadc_v1250 == 0) {
333 pr_debug("No cal yet return %d\n",
334 VBATT_MUL_FACTOR * reading_uv);
335 return VBATT_MUL_FACTOR * reading_uv;
336 }
337
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700338 numerator = ((s64)reading_uv - chip->vadc_v0625) * VADC_CALIB_UV;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700339 denominator = (s64)chip->vadc_v1250 - chip->vadc_v0625;
340 if (denominator == 0)
341 return reading_uv * VBATT_MUL_FACTOR;
342 return (VADC_CALIB_UV + div_s64(numerator, denominator))
343 * VBATT_MUL_FACTOR;
344}
345
Xiaozhe Shibdf14742012-12-05 12:41:48 -0800346static int convert_vbatt_uv_to_raw(struct qpnp_bms_chip *chip,
347 int unadjusted_vbatt)
348{
349 int scaled_vbatt = unadjusted_vbatt / VBATT_MUL_FACTOR;
350
351 if (scaled_vbatt <= 0)
352 return VADC_INTRINSIC_OFFSET;
353 return ((scaled_vbatt * V_PER_BIT_DIV_FACTOR) / V_PER_BIT_MUL_FACTOR)
354 + VADC_INTRINSIC_OFFSET;
355}
356
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700357static inline int convert_vbatt_raw_to_uv(struct qpnp_bms_chip *chip,
358 uint16_t reading)
359{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700360 int uv;
361
362 uv = vadc_reading_to_uv(reading);
363 pr_debug("%u raw converted into %d uv\n", reading, uv);
364 uv = adjust_vbatt_reading(chip, uv);
365 pr_debug("adjusted into %d uv\n", uv);
366 return uv;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700367}
368
369#define CC_READING_RESOLUTION_N 542535
370#define CC_READING_RESOLUTION_D 100000
371static int cc_reading_to_uv(int16_t reading)
372{
373 return div_s64(reading * CC_READING_RESOLUTION_N,
374 CC_READING_RESOLUTION_D);
375}
376
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800377#define QPNP_ADC_GAIN_IDEAL 3291LL
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700378static s64 cc_adjust_for_gain(s64 uv, uint16_t gain)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700379{
380 s64 result_uv;
381
382 pr_debug("adjusting_uv = %lld\n", uv);
Xiaozhe Shi820a47a2012-11-27 13:23:27 -0800383 if (gain == 0) {
384 pr_debug("gain is %d, not adjusting\n", gain);
385 return uv;
386 }
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700387 pr_debug("adjusting by factor: %lld/%hu = %lld%%\n",
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800388 QPNP_ADC_GAIN_IDEAL, gain,
389 div_s64(QPNP_ADC_GAIN_IDEAL * 100LL, (s64)gain));
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700390
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800391 result_uv = div_s64(uv * QPNP_ADC_GAIN_IDEAL, (s64)gain);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700392 pr_debug("result_uv = %lld\n", result_uv);
393 return result_uv;
394}
395
396static int convert_vsense_to_uv(struct qpnp_bms_chip *chip,
397 int16_t reading)
398{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700399 struct qpnp_iadc_calib calibration;
400
401 qpnp_iadc_get_gain_and_offset(&calibration);
402 return cc_adjust_for_gain(cc_reading_to_uv(reading),
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800403 calibration.gain_raw - calibration.offset_raw);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700404}
405
406static int read_vsense_avg(struct qpnp_bms_chip *chip, int *result_uv)
407{
408 int rc;
409 int16_t reading;
410
411 rc = qpnp_read_wrapper(chip, (u8 *)&reading,
412 chip->base + BMS1_VSENSE_AVG_DATA0, 2);
413
414 if (rc) {
415 pr_err("fail to read VSENSE_AVG rc = %d\n", rc);
416 return rc;
417 }
418
419 *result_uv = convert_vsense_to_uv(chip, reading);
420 return 0;
421}
422
423static int get_battery_current(struct qpnp_bms_chip *chip, int *result_ua)
424{
425 int vsense_uv = 0;
426
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800427 if (chip->r_sense_uohm == 0) {
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700428 pr_err("r_sense is zero\n");
429 return -EINVAL;
430 }
431
432 mutex_lock(&chip->bms_output_lock);
433 lock_output_data(chip);
434 read_vsense_avg(chip, &vsense_uv);
435 unlock_output_data(chip);
436 mutex_unlock(&chip->bms_output_lock);
437
438 pr_debug("vsense_uv=%duV\n", vsense_uv);
439 /* cast for signed division */
Xiaozhe Shid0a79542012-11-06 10:00:38 -0800440 *result_ua = div_s64((vsense_uv * 1000000LL), (int)chip->r_sense_uohm);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700441 pr_debug("ibat=%duA\n", *result_ua);
442 return 0;
443}
444
445static int get_battery_voltage(int *result_uv)
446{
447 int rc;
448 struct qpnp_vadc_result adc_result;
449
450 rc = qpnp_vadc_read(VBAT_SNS, &adc_result);
451 if (rc) {
452 pr_err("error reading adc channel = %d, rc = %d\n",
453 VBAT_SNS, rc);
454 return rc;
455 }
456 pr_debug("mvolts phy = %lld meas = 0x%llx\n", adc_result.physical,
457 adc_result.measurement);
458 *result_uv = (int)adc_result.physical;
459 return 0;
460}
461
Xiaozhe Shie118c692012-09-24 15:17:43 -0700462#define CC_36_BIT_MASK 0xFFFFFFFFFLL
463
464static int read_cc_raw(struct qpnp_bms_chip *chip, int64_t *reading)
465{
466 int64_t raw_reading;
467 int rc;
468
469 rc = qpnp_read_wrapper(chip, (u8 *)&raw_reading,
470 chip->base + BMS1_CC_DATA0, 5);
471 if (rc) {
472 pr_err("Error reading cc: rc = %d\n", rc);
473 return -ENXIO;
474 }
475
476 raw_reading = raw_reading & CC_36_BIT_MASK;
477 /* convert 36 bit signed value into 64 signed value */
478 *reading = (raw_reading >> 35) == 0LL ?
479 raw_reading : ((-1LL ^ CC_36_BIT_MASK) | raw_reading);
480 pr_debug("before conversion: %llx, after conversion: %llx\n",
481 raw_reading, *reading);
482
483 return 0;
484}
485
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700486static int calib_vadc(struct qpnp_bms_chip *chip)
487{
Xiaozhe Shif62c0152013-03-28 17:57:19 -0700488 int rc, raw_0625, raw_1250;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700489 struct qpnp_vadc_result result;
490
491 rc = qpnp_vadc_read(REF_625MV, &result);
492 if (rc) {
493 pr_debug("vadc read failed with rc = %d\n", rc);
494 return rc;
495 }
Xiaozhe Shif62c0152013-03-28 17:57:19 -0700496 raw_0625 = result.adc_code;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700497
498 rc = qpnp_vadc_read(REF_125V, &result);
499 if (rc) {
500 pr_debug("vadc read failed with rc = %d\n", rc);
501 return rc;
502 }
Xiaozhe Shif62c0152013-03-28 17:57:19 -0700503 raw_1250 = result.adc_code;
504 chip->vadc_v0625 = vadc_reading_to_uv(raw_0625);
505 chip->vadc_v1250 = vadc_reading_to_uv(raw_1250);
506 pr_debug("vadc calib: 0625 = %d raw (%d uv), 1250 = %d raw (%d uv)\n",
507 raw_0625, chip->vadc_v0625,
508 raw_1250, chip->vadc_v1250);
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700509 return 0;
510}
511
Xiaozhe Shie118c692012-09-24 15:17:43 -0700512static void convert_and_store_ocv(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800513 struct raw_soc_params *raw,
514 int batt_temp)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700515{
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700516 int rc;
517
518 pr_debug("prev_last_good_ocv_raw = %d, last_good_ocv_raw = %d\n",
519 chip->prev_last_good_ocv_raw,
520 raw->last_good_ocv_raw);
521 rc = calib_vadc(chip);
522 if (rc)
523 pr_err("Vadc reference voltage read failed, rc = %d\n", rc);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700524 chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
525 raw->last_good_ocv_uv = convert_vbatt_raw_to_uv(chip,
526 raw->last_good_ocv_raw);
527 chip->last_ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800528 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700529 pr_debug("last_good_ocv_uv = %d\n", raw->last_good_ocv_uv);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700530}
531
Xiaozhe Shia045a562012-11-28 16:55:39 -0800532#define CLEAR_CC BIT(7)
533#define CLEAR_SW_CC BIT(6)
534/**
535 * reset both cc and sw-cc.
536 * note: this should only be ever called from one thread
537 * or there may be a race condition where CC is never enabled
538 * again
539 */
540static void reset_cc(struct qpnp_bms_chip *chip)
541{
542 int rc;
543
544 pr_debug("resetting cc manually\n");
545 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
546 CLEAR_CC | CLEAR_SW_CC,
547 CLEAR_CC | CLEAR_SW_CC);
548 if (rc)
549 pr_err("cc reset failed: %d\n", rc);
550
551 /* wait for 100us for cc to reset */
552 udelay(100);
553
554 rc = qpnp_masked_write(chip, BMS1_CC_CLEAR_CTL,
555 CLEAR_CC | CLEAR_SW_CC, 0);
556 if (rc)
557 pr_err("cc reenable failed: %d\n", rc);
558}
559
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800560static bool is_battery_charging(struct qpnp_bms_chip *chip)
561{
562 union power_supply_propval ret = {0,};
563
564 if (chip->batt_psy == NULL)
565 chip->batt_psy = power_supply_get_by_name("battery");
566 if (chip->batt_psy) {
567 /* if battery has been registered, use the status property */
568 chip->batt_psy->get_property(chip->batt_psy,
569 POWER_SUPPLY_PROP_STATUS, &ret);
570 return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
571 }
572
573 /* Default to false if the battery power supply is not registered. */
574 pr_debug("battery power supply is not registered\n");
575 return false;
576}
577
578static bool is_batfet_open(struct qpnp_bms_chip *chip)
579{
580 union power_supply_propval ret = {0,};
581
582 if (chip->batt_psy == NULL)
583 chip->batt_psy = power_supply_get_by_name("battery");
584 if (chip->batt_psy) {
585 /* if battery has been registered, use the status property */
586 chip->batt_psy->get_property(chip->batt_psy,
587 POWER_SUPPLY_PROP_STATUS, &ret);
588 return ret.intval == POWER_SUPPLY_STATUS_FULL;
589 }
590
591 /* Default to true if the battery power supply is not registered. */
592 pr_debug("battery power supply is not registered\n");
593 return true;
594}
595
596static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
597 int *ibat_ua, int *vbat_uv)
598{
599 struct qpnp_iadc_result i_result;
600 struct qpnp_vadc_result v_result;
601 enum qpnp_iadc_channels iadc_channel;
602 int rc;
603
604 iadc_channel = chip->use_external_rsense ?
605 EXTERNAL_RSENSE : INTERNAL_RSENSE;
606 rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
607 VBAT_SNS, &v_result);
608 if (rc) {
609 pr_err("vadc read failed with rc: %d\n", rc);
610 return rc;
611 }
612 /*
613 * reverse the current read by the iadc, since the bms uses
614 * flipped battery current polarity.
615 */
616 *ibat_ua = -1 * (int)i_result.result_ua;
617 *vbat_uv = (int)v_result.physical;
618
619 return 0;
620}
621
622static int estimate_ocv(struct qpnp_bms_chip *chip)
623{
624 int ibat_ua, vbat_uv, ocv_est_uv;
625 int rc;
626 int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm;
627
628 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
629 if (rc) {
630 pr_err("simultaneous failed rc = %d\n", rc);
631 return rc;
632 }
633
634 ocv_est_uv = vbat_uv + (ibat_ua * rbatt_mohm) / 1000;
635 pr_debug("estimated pon ocv = %d\n", ocv_est_uv);
636 return ocv_est_uv;
637}
638
639static void reset_for_new_battery(struct qpnp_bms_chip *chip, int batt_temp)
640{
641 chip->last_ocv_uv = estimate_ocv(chip);
642 chip->last_soc = -EINVAL;
643 chip->soc_at_cv = -EINVAL;
644 chip->shutdown_soc_invalid = true;
645 chip->shutdown_soc = 0;
646 chip->shutdown_iavg_ma = 0;
647 chip->prev_pc_unusable = -EINVAL;
648 reset_cc(chip);
649 chip->last_cc_uah = INT_MIN;
650 chip->last_ocv_temp = batt_temp;
651 chip->last_soc_invalid = true;
652}
653
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800654#define OCV_RAW_UNINITIALIZED 0xFFFF
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700655static int read_soc_params_raw(struct qpnp_bms_chip *chip,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800656 struct raw_soc_params *raw,
657 int batt_temp)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700658{
Xiaozhe Shie118c692012-09-24 15:17:43 -0700659 int rc;
660
661 mutex_lock(&chip->bms_output_lock);
Xiaozhe Shia045a562012-11-28 16:55:39 -0800662
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800663 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Xiaozhe Shia045a562012-11-28 16:55:39 -0800664 /* software workaround for BMS 1.0
665 * The coulomb counter does not reset upon PON, so reset it
666 * manually upon probe. */
667 if (chip->revision1 == 0 && chip->revision2 == 0)
668 reset_cc(chip);
669 }
670
Xiaozhe Shie118c692012-09-24 15:17:43 -0700671 lock_output_data(chip);
672
673 rc = qpnp_read_wrapper(chip, (u8 *)&raw->last_good_ocv_raw,
674 chip->base + BMS1_OCV_FOR_SOC_DATA0, 2);
675 if (rc) {
676 pr_err("Error reading ocv: rc = %d\n", rc);
677 return -ENXIO;
678 }
679
680 rc = read_cc_raw(chip, &raw->cc);
681 if (rc) {
682 pr_err("Failed to read raw cc data, rc = %d\n", rc);
683 return rc;
684 }
685
686 unlock_output_data(chip);
687 mutex_unlock(&chip->bms_output_lock);
688
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800689 if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800690 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700691 pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -0800692 } else if (chip->new_battery) {
693 /* if a new battery was inserted, estimate the ocv */
694 reset_for_new_battery(chip, batt_temp);
695 raw->cc = 0;
696 raw->last_good_ocv_uv = chip->last_ocv_uv;
697 chip->new_battery = false;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700698 } else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800699 convert_and_store_ocv(chip, raw, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700700 /* forget the old cc value upon ocv */
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800701 chip->last_cc_uah = INT_MIN;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700702 } else {
703 raw->last_good_ocv_uv = chip->last_ocv_uv;
704 }
705
706 /* fake a high OCV if done charging */
707 if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -0800708 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700709 } else {
710 /*
711 * force 100% ocv by selecting the highest voltage the
712 * battery could ever reach
713 */
714 raw->last_good_ocv_uv = chip->max_voltage_uv;
715 chip->last_ocv_uv = chip->max_voltage_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800716 chip->last_ocv_temp = batt_temp;
Xiaozhe Shi1c63a892013-02-13 15:49:40 -0800717 reset_cc(chip);
718 raw->cc = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700719 }
720 pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
721 raw->last_good_ocv_raw, raw->last_good_ocv_uv);
722 pr_debug("cc_raw= 0x%llx\n", raw->cc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -0700723 return 0;
724}
725
Xiaozhe Shie118c692012-09-24 15:17:43 -0700726static int calculate_pc(struct qpnp_bms_chip *chip, int ocv_uv,
727 int batt_temp)
728{
729 int pc;
730
731 pc = interpolate_pc(chip->pc_temp_ocv_lut,
732 batt_temp / 10, ocv_uv / 1000);
733 pr_debug("pc = %u %% for ocv = %d uv batt_temp = %d\n",
734 pc, ocv_uv, batt_temp);
735 /* Multiply the initial FCC value by the scale factor. */
736 return pc;
737}
738
739static int calculate_fcc(struct qpnp_bms_chip *chip, int batt_temp)
740{
741 int fcc_uah;
742
743 if (chip->adjusted_fcc_temp_lut == NULL) {
744 /* interpolate_fcc returns a mv value. */
745 fcc_uah = interpolate_fcc(chip->fcc_temp_lut,
746 batt_temp) * 1000;
747 pr_debug("fcc = %d uAh\n", fcc_uah);
748 return fcc_uah;
749 } else {
750 return 1000 * interpolate_fcc(chip->adjusted_fcc_temp_lut,
751 batt_temp);
752 }
753}
754
755/* calculate remaining charge at the time of ocv */
756static int calculate_ocv_charge(struct qpnp_bms_chip *chip,
757 struct raw_soc_params *raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800758 int fcc_uah)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700759{
760 int ocv_uv, pc;
761
762 ocv_uv = raw->last_good_ocv_uv;
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -0800763 pc = calculate_pc(chip, ocv_uv, chip->last_ocv_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700764 pr_debug("ocv_uv = %d pc = %d\n", ocv_uv, pc);
765 return (fcc_uah * pc) / 100;
766}
767
768#define CC_RESOLUTION_N 542535
769#define CC_RESOLUTION_D 100000
770
771static s64 cc_to_uv(s64 cc)
772{
773 return div_s64(cc * CC_RESOLUTION_N, CC_RESOLUTION_D);
774}
775
776#define CC_READING_TICKS 56
777#define SLEEP_CLK_HZ 32764
778#define SECONDS_PER_HOUR 3600
779
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800780static s64 cc_uv_to_pvh(s64 cc_uv)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700781{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800782 /* Note that it is necessary need to multiply by 1000000 to convert
783 * from uvh to pvh here.
784 * However, the maximum Coulomb Counter value is 2^35, which can cause
785 * an over flow.
786 * Multiply by 100000 first to perserve as much precision as possible
787 * then multiply by 10 after doing the division in order to avoid
788 * overflow on the maximum Coulomb Counter value.
789 */
790 return div_s64(cc_uv * CC_READING_TICKS * 100000,
791 SLEEP_CLK_HZ * SECONDS_PER_HOUR) * 10;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700792}
793
794/**
795 * calculate_cc-
796 * @chip: the bms chip pointer
797 * @cc: the cc reading from bms h/w
798 * @val: return value
799 * @coulomb_counter: adjusted coulomb counter for 100%
800 *
801 * RETURNS: in val pointer coulomb counter based charger in uAh
802 * (micro Amp hour)
803 */
804static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
805{
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800806 int64_t cc_voltage_uv, cc_pvh, cc_uah;
Xiaozhe Shi4e376652012-10-25 12:38:50 -0700807 struct qpnp_iadc_calib calibration;
808
809 qpnp_iadc_get_gain_and_offset(&calibration);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -0800810 pr_debug("cc = %lld\n", cc);
811 cc_voltage_uv = cc_to_uv(cc);
Xiaozhe Shi0c484932013-02-05 16:14:10 -0800812 cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
813 calibration.gain_raw
814 - calibration.offset_raw);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700815 pr_debug("cc_voltage_uv = %lld uv\n", cc_voltage_uv);
Xiaozhe Shia9b597d2013-02-12 11:00:39 -0800816 cc_pvh = cc_uv_to_pvh(cc_voltage_uv);
817 pr_debug("cc_pvh = %lld pvh\n", cc_pvh);
818 cc_uah = div_s64(cc_pvh, chip->r_sense_uohm);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700819 /* cc_raw had 4 bits of extra precision.
820 By now it should be within 32 bit range */
821 return (int)cc_uah;
822}
823
824static int get_rbatt(struct qpnp_bms_chip *chip,
825 int soc_rbatt_mohm, int batt_temp)
826{
827 int rbatt_mohm, scalefactor;
828
829 rbatt_mohm = chip->default_rbatt_mohm;
830 pr_debug("rbatt before scaling = %d\n", rbatt_mohm);
831 if (chip->rbatt_sf_lut == NULL) {
832 pr_debug("RBATT = %d\n", rbatt_mohm);
833 return rbatt_mohm;
834 }
835 /* Convert the batt_temp to DegC from deciDegC */
836 batt_temp = batt_temp / 10;
837 scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
838 batt_temp, soc_rbatt_mohm);
839 pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
840 scalefactor, batt_temp, soc_rbatt_mohm);
841 rbatt_mohm = (rbatt_mohm * scalefactor) / 100;
842
843 rbatt_mohm += chip->r_conn_mohm;
844 pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
845 chip->r_conn_mohm, rbatt_mohm);
846
847 pr_debug("RBATT = %d\n", rbatt_mohm);
848 return rbatt_mohm;
849}
850
Xiaozhe Shi06b67cc2013-03-29 12:07:40 -0700851#define IAVG_MINIMAL_TIME 2
Xiaozhe Shie118c692012-09-24 15:17:43 -0700852static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800853 int *iavg_ua, int delta_time_s)
Xiaozhe Shie118c692012-09-24 15:17:43 -0700854{
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800855 int delta_cc_uah = 0;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700856
Xiaozhe Shi06b67cc2013-03-29 12:07:40 -0700857 /*
858 * use the battery current if called too quickly
859 */
860 if (delta_time_s < IAVG_MINIMAL_TIME
861 || chip->last_cc_uah == INT_MIN) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700862 get_battery_current(chip, iavg_ua);
863 goto out;
864 }
865
Xiaozhe Shie118c692012-09-24 15:17:43 -0700866 delta_cc_uah = cc_uah - chip->last_cc_uah;
867
868 *iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
869
Xiaozhe Shie118c692012-09-24 15:17:43 -0700870out:
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800871 pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700872
873 /* remember cc_uah */
874 chip->last_cc_uah = cc_uah;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700875}
876
877static int calculate_termination_uuc(struct qpnp_bms_chip *chip,
878 struct soc_params *params,
879 int batt_temp, int uuc_iavg_ma,
880 int *ret_pc_unusable)
881{
882 int unusable_uv, pc_unusable, uuc_uah;
883 int i = 0;
884 int ocv_mv;
885 int batt_temp_degc = batt_temp / 10;
886 int rbatt_mohm;
887 int delta_uv;
888 int prev_delta_uv = 0;
889 int prev_rbatt_mohm = 0;
890 int uuc_rbatt_mohm;
891
892 for (i = 0; i <= 100; i++) {
893 ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
894 batt_temp_degc, i);
895 rbatt_mohm = get_rbatt(chip, i, batt_temp);
896 unusable_uv = (rbatt_mohm * uuc_iavg_ma)
897 + (chip->v_cutoff_uv);
898 delta_uv = ocv_mv * 1000 - unusable_uv;
899
900 pr_debug("soc = %d ocv = %d rbat = %d u_uv = %d delta_v = %d\n",
901 i, ocv_mv, rbatt_mohm, unusable_uv, delta_uv);
902
903 if (delta_uv > 0)
904 break;
905
906 prev_delta_uv = delta_uv;
907 prev_rbatt_mohm = rbatt_mohm;
908 }
909
910 uuc_rbatt_mohm = linear_interpolate(rbatt_mohm, delta_uv,
911 prev_rbatt_mohm, prev_delta_uv,
912 0);
913
914 unusable_uv = (uuc_rbatt_mohm * uuc_iavg_ma) + (chip->v_cutoff_uv);
915
916 pc_unusable = calculate_pc(chip, unusable_uv, batt_temp);
917 uuc_uah = (params->fcc_uah * pc_unusable) / 100;
918 pr_debug("For uuc_iavg_ma = %d, unusable_rbatt = %d unusable_uv = %d unusable_pc = %d uuc = %d\n",
919 uuc_iavg_ma,
920 uuc_rbatt_mohm, unusable_uv,
921 pc_unusable, uuc_uah);
922 *ret_pc_unusable = pc_unusable;
923 return uuc_uah;
924}
925
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800926#define TIME_PER_PERCENT_UUC 60
Xiaozhe Shie118c692012-09-24 15:17:43 -0700927static int adjust_uuc(struct qpnp_bms_chip *chip,
928 struct soc_params *params,
929 int new_pc_unusable,
930 int new_uuc_uah,
931 int batt_temp)
932{
933 int new_unusable_mv, new_iavg_ma;
934 int batt_temp_degc = batt_temp / 10;
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800935 int max_percent_change;
936
937 max_percent_change = max(params->delta_time_s
938 / TIME_PER_PERCENT_UUC, 1);
Xiaozhe Shie118c692012-09-24 15:17:43 -0700939
940 if (chip->prev_pc_unusable == -EINVAL
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800941 || abs(chip->prev_pc_unusable - new_pc_unusable)
942 <= max_percent_change) {
Xiaozhe Shie118c692012-09-24 15:17:43 -0700943 chip->prev_pc_unusable = new_pc_unusable;
944 return new_uuc_uah;
945 }
946
947 /* the uuc is trying to change more than 1% restrict it */
948 if (new_pc_unusable > chip->prev_pc_unusable)
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800949 chip->prev_pc_unusable += max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700950 else
Xiaozhe Shif36d2862013-01-04 10:17:35 -0800951 chip->prev_pc_unusable -= max_percent_change;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700952
953 new_uuc_uah = (params->fcc_uah * chip->prev_pc_unusable) / 100;
954
955 /* also find update the iavg_ma accordingly */
956 new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
957 batt_temp_degc, chip->prev_pc_unusable);
958 if (new_unusable_mv < chip->v_cutoff_uv/1000)
959 new_unusable_mv = chip->v_cutoff_uv/1000;
960
961 new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
Xiaozhe Shi904f1f72012-12-04 12:47:21 -0800962 / params->rbatt_mohm;
Xiaozhe Shie118c692012-09-24 15:17:43 -0700963 if (new_iavg_ma == 0)
964 new_iavg_ma = 1;
965 chip->prev_uuc_iavg_ma = new_iavg_ma;
966 pr_debug("Restricting UUC to %d (%d%%) unusable_mv = %d iavg_ma = %d\n",
967 new_uuc_uah, chip->prev_pc_unusable,
968 new_unusable_mv, new_iavg_ma);
969
970 return new_uuc_uah;
971}
972
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -0800973#define MIN_IAVG_MA 250
Xiaozhe Shie118c692012-09-24 15:17:43 -0700974#define MIN_SECONDS_FOR_VALID_SAMPLE 20
975static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
976 struct soc_params *params,
977 int batt_temp)
978{
979 int uuc_uah_iavg;
980 int i;
981 int uuc_iavg_ma = params->iavg_ua / 1000;
982 int pc_unusable;
983
984 /*
985 * if called first time, fill all the samples with
986 * the shutdown_iavg_ma
987 */
988 if (chip->first_time_calc_uuc && chip->shutdown_iavg_ma != 0) {
989 pr_debug("Using shutdown_iavg_ma = %d in all samples\n",
990 chip->shutdown_iavg_ma);
991 for (i = 0; i < IAVG_SAMPLES; i++)
992 chip->iavg_samples_ma[i] = chip->shutdown_iavg_ma;
993
994 chip->iavg_index = 0;
995 chip->iavg_num_samples = IAVG_SAMPLES;
996 }
997
998 /*
999 * if charging use a nominal avg current to keep
1000 * a reasonable UUC while charging
1001 */
Abhijeet Dharmapurikarbdf8ba82012-12-20 18:33:56 -08001002 if (uuc_iavg_ma < MIN_IAVG_MA)
1003 uuc_iavg_ma = MIN_IAVG_MA;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001004 chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
1005 chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
1006 chip->iavg_num_samples++;
1007 if (chip->iavg_num_samples >= IAVG_SAMPLES)
1008 chip->iavg_num_samples = IAVG_SAMPLES;
1009
1010 /* now that this sample is added calcualte the average */
1011 uuc_iavg_ma = 0;
1012 if (chip->iavg_num_samples != 0) {
1013 for (i = 0; i < chip->iavg_num_samples; i++) {
1014 pr_debug("iavg_samples_ma[%d] = %d\n", i,
1015 chip->iavg_samples_ma[i]);
1016 uuc_iavg_ma += chip->iavg_samples_ma[i];
1017 }
1018
1019 uuc_iavg_ma = DIV_ROUND_CLOSEST(uuc_iavg_ma,
1020 chip->iavg_num_samples);
1021 }
1022
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001023 /*
1024 * if we're in bms reset mode, force uuc to be 3% of fcc
1025 */
1026 if (bms_reset)
1027 return (params->fcc_uah * 3) / 100;
1028
Xiaozhe Shi75e5efe2013-02-07 09:51:43 -08001029 uuc_uah_iavg = calculate_termination_uuc(chip, params, batt_temp,
1030 uuc_iavg_ma, &pc_unusable);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001031 pr_debug("uuc_iavg_ma = %d uuc with iavg = %d\n",
1032 uuc_iavg_ma, uuc_uah_iavg);
1033
1034 chip->prev_uuc_iavg_ma = uuc_iavg_ma;
1035 /* restrict the uuc such that it can increase only by one percent */
1036 uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
1037 uuc_uah_iavg, batt_temp);
1038
1039 chip->first_time_calc_uuc = 0;
1040 return uuc_uah_iavg;
1041}
1042
1043static void find_ocv_for_soc(struct qpnp_bms_chip *chip,
1044 struct soc_params *params,
1045 int batt_temp,
1046 int shutdown_soc,
1047 int *ret_ocv_uv)
1048{
1049 s64 ocv_charge_uah;
1050 int pc, new_pc;
1051 int batt_temp_degc = batt_temp / 10;
1052 int ocv_uv;
1053
1054 ocv_charge_uah = (s64)shutdown_soc
1055 * (params->fcc_uah - params->uuc_uah);
1056 ocv_charge_uah = div_s64(ocv_charge_uah, 100)
1057 + params->cc_uah + params->uuc_uah;
1058 pc = DIV_ROUND_CLOSEST((int)ocv_charge_uah * 100, params->fcc_uah);
1059 pc = clamp(pc, 0, 100);
1060
1061 ocv_uv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
1062
1063 pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
1064 shutdown_soc, params->fcc_uah,
1065 params->uuc_uah, (int)ocv_charge_uah,
1066 pc, ocv_uv);
1067 new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv_uv);
1068 pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv_uv);
1069
1070 while (abs(new_pc - pc) > 1) {
1071 int delta_mv = 5;
1072
1073 if (new_pc > pc)
1074 delta_mv = -1 * delta_mv;
1075
1076 ocv_uv = ocv_uv + delta_mv;
1077 new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
1078 batt_temp_degc, ocv_uv);
1079 pr_debug("test revlookup pc = %d for ocv = %d\n",
1080 new_pc, ocv_uv);
1081 }
1082
1083 *ret_ocv_uv = ocv_uv * 1000;
1084 params->ocv_charge_uah = (int)ocv_charge_uah;
1085}
1086
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001087static int get_current_time(unsigned long *now_tm_sec)
1088{
1089 struct rtc_time tm;
1090 struct rtc_device *rtc;
1091 int rc;
1092
1093 rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
1094 if (rtc == NULL) {
1095 pr_err("%s: unable to open rtc device (%s)\n",
1096 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
1097 rc = -EINVAL;
1098 goto close_time;
1099 }
1100
1101 rc = rtc_read_time(rtc, &tm);
1102 if (rc) {
1103 pr_err("Error reading rtc device (%s) : %d\n",
1104 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1105 goto close_time;
1106 }
1107
1108 rc = rtc_valid_tm(&tm);
1109 if (rc) {
1110 pr_err("Invalid RTC time (%s): %d\n",
1111 CONFIG_RTC_HCTOSYS_DEVICE, rc);
1112 goto close_time;
1113 }
1114 rtc_tm_to_time(&tm, now_tm_sec);
1115
1116close_time:
1117 rtc_class_close(rtc);
1118 return rc;
1119}
1120
1121static int calculate_delta_time(struct qpnp_bms_chip *chip, int *delta_time_s)
1122{
1123 unsigned long now_tm_sec = 0;
1124
1125 /* default to delta time = 0 if anything fails */
1126 *delta_time_s = 0;
1127
1128 get_current_time(&now_tm_sec);
1129
1130 *delta_time_s = (now_tm_sec - chip->tm_sec);
1131 pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
1132 chip->tm_sec, now_tm_sec, *delta_time_s);
1133
1134 /* remember this time */
1135 chip->tm_sec = now_tm_sec;
1136 return 0;
1137}
1138
Xiaozhe Shie118c692012-09-24 15:17:43 -07001139static void calculate_soc_params(struct qpnp_bms_chip *chip,
1140 struct raw_soc_params *raw,
1141 struct soc_params *params,
1142 int batt_temp)
1143{
1144 int soc_rbatt;
1145
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001146 calculate_delta_time(chip, &params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001147 params->fcc_uah = calculate_fcc(chip, batt_temp);
1148 pr_debug("FCC = %uuAh batt_temp = %d\n", params->fcc_uah, batt_temp);
1149
1150 /* calculate remainging charge */
1151 params->ocv_charge_uah = calculate_ocv_charge(
1152 chip, raw,
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001153 params->fcc_uah);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001154 pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
1155
1156 /* calculate cc micro_volt_hour */
1157 params->cc_uah = calculate_cc(chip, raw->cc);
Xiaozhe Shi1c63a892013-02-13 15:49:40 -08001158 pr_debug("cc_uah = %duAh raw->cc = %llx\n", params->cc_uah, raw->cc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001159
1160 soc_rbatt = ((params->ocv_charge_uah - params->cc_uah) * 100)
1161 / params->fcc_uah;
1162 if (soc_rbatt < 0)
1163 soc_rbatt = 0;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001164 params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001165
Xiaozhe Shif36d2862013-01-04 10:17:35 -08001166 calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
1167 params->delta_time_s);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001168
1169 params->uuc_uah = calculate_unusable_charge_uah(chip, params,
1170 batt_temp);
1171 pr_debug("UUC = %uuAh\n", params->uuc_uah);
1172}
1173
1174static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
1175{
1176 if (chip->shutdown_soc_invalid) {
1177 pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
1178 return 0;
1179 }
1180
1181 if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
1182 pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
1183 chip->shutdown_soc, soc,
1184 chip->shutdown_soc_valid_limit);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001185 chip->shutdown_soc_invalid = true;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001186 return 0;
1187 }
1188
1189 return 1;
1190}
1191
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001192static int bound_soc(int soc)
1193{
1194 soc = max(0, soc);
1195 soc = min(100, soc);
1196 return soc;
1197}
1198
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001199#define IBAT_TOL_MASK 0x0F
1200#define OCV_TOL_MASK 0xF0
1201#define IBAT_TOL_DEFAULT 0x03
1202#define IBAT_TOL_NOCHG 0x0F
1203#define OCV_TOL_DEFAULT 0x20
1204#define OCV_TOL_NO_OCV 0x00
1205static int stop_ocv_updates(struct qpnp_bms_chip *chip)
1206{
1207 pr_debug("stopping ocv updates\n");
1208 return qpnp_masked_write(chip, BMS1_TOL_CTL,
1209 OCV_TOL_MASK, OCV_TOL_NO_OCV);
1210}
1211
1212static int reset_bms_for_test(struct qpnp_bms_chip *chip)
1213{
Xiaozhe Shi95da77f2013-02-20 13:40:06 -08001214 int ibat_ua = 0, vbat_uv = 0, rc;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001215 int ocv_est_uv;
1216
1217 if (!chip) {
1218 pr_err("BMS driver has not been initialized yet!\n");
1219 return -EINVAL;
1220 }
1221
1222 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1223
1224 ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
1225 pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
1226 chip->last_ocv_uv = ocv_est_uv;
1227 chip->last_soc = -EINVAL;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001228 chip->last_soc_invalid = true;
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001229 reset_cc(chip);
1230 chip->last_cc_uah = INT_MIN;
1231 stop_ocv_updates(chip);
1232
1233 pr_debug("bms reset to ocv = %duv vbat_ua = %d ibat_ua = %d\n",
1234 chip->last_ocv_uv, vbat_uv, ibat_ua);
1235
1236 return rc;
1237}
1238
1239static int bms_reset_set(const char *val, const struct kernel_param *kp)
1240{
1241 int rc;
1242
1243 rc = param_set_bool(val, kp);
1244 if (rc) {
1245 pr_err("Unable to set bms_reset: %d\n", rc);
1246 return rc;
1247 }
1248
1249 if (*(bool *)kp->arg) {
1250 struct power_supply *bms_psy = power_supply_get_by_name("bms");
1251 struct qpnp_bms_chip *chip = container_of(bms_psy,
1252 struct qpnp_bms_chip, bms_psy);
1253
1254 rc = reset_bms_for_test(chip);
1255 if (rc) {
1256 pr_err("Unable to modify bms_reset: %d\n", rc);
1257 return rc;
1258 }
1259 }
1260 return 0;
1261}
1262
1263static struct kernel_param_ops bms_reset_ops = {
1264 .set = bms_reset_set,
1265 .get = param_get_bool,
1266};
1267
1268module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
1269
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001270static int charging_adjustments(struct qpnp_bms_chip *chip,
1271 struct soc_params *params, int soc,
1272 int vbat_uv, int ibat_ua, int batt_temp)
1273{
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001274 int chg_soc;
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001275 int batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001276
1277 if (chip->soc_at_cv == -EINVAL) {
1278 /* In constant current charging return the calc soc */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001279 if (batt_terminal_uv <= chip->max_voltage_uv)
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001280 pr_debug("CC CHG SOC %d\n", soc);
1281
1282 /* Note the CC to CV point */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001283 if (batt_terminal_uv >= chip->max_voltage_uv) {
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001284 chip->soc_at_cv = soc;
1285 chip->prev_chg_soc = soc;
1286 chip->ibat_at_cv_ua = ibat_ua;
1287 pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
1288 ibat_ua, soc);
1289 }
1290 return soc;
1291 }
1292
1293 /*
1294 * battery is in CV phase - begin liner inerpolation of soc based on
1295 * battery charge current
1296 */
1297
1298 /*
1299 * if voltage lessened (possibly because of a system load)
1300 * keep reporting the prev chg soc
1301 */
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001302 if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
1303 pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
1304 batt_terminal_uv,
1305 chip->max_voltage_uv, chip->prev_chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001306 return chip->prev_chg_soc;
1307 }
1308
1309 chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
Abhijeet Dharmapurikareef88662012-11-08 17:26:29 -08001310 100, -1 * chip->chg_term_ua,
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001311 ibat_ua);
Xiaozhe Shi78d0c532012-12-10 13:02:14 -08001312 chg_soc = bound_soc(chg_soc);
Xiaozhe Shi41bc1f12012-09-26 16:55:22 -07001313
1314 /* always report a higher soc */
1315 if (chg_soc > chip->prev_chg_soc) {
1316 int new_ocv_uv;
1317
1318 chip->prev_chg_soc = chg_soc;
1319
1320 find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
1321 chip->last_ocv_uv = new_ocv_uv;
1322 pr_debug("CC CHG ADJ OCV = %d CHG SOC %d\n",
1323 new_ocv_uv,
1324 chip->prev_chg_soc);
1325 }
1326
1327 pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
1328 return chip->prev_chg_soc;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001329}
1330
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001331static void very_low_voltage_check(struct qpnp_bms_chip *chip, int vbat_uv)
1332{
1333 /*
1334 * if battery is very low (v_cutoff voltage + 20mv) hold
1335 * a wakelock untill soc = 0%
1336 */
1337 if (vbat_uv <= chip->low_voltage_threshold
1338 && !chip->low_voltage_wake_lock_held) {
1339 pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
1340 wake_lock(&chip->low_voltage_wake_lock);
1341 chip->low_voltage_wake_lock_held = 1;
1342 } else if (vbat_uv > chip->low_voltage_threshold
1343 && chip->low_voltage_wake_lock_held) {
1344 pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
1345 chip->low_voltage_wake_lock_held = 0;
1346 wake_unlock(&chip->low_voltage_wake_lock);
1347 }
1348}
1349
Xiaozhe Shie118c692012-09-24 15:17:43 -07001350static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
1351 int soc, int batt_temp)
1352{
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001353 int ibat_ua = 0, vbat_uv = 0;
1354 int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
1355 int delta_ocv_uv = 0;
1356 int n = 0;
1357 int rc_new_uah = 0;
1358 int pc_new = 0;
1359 int soc_new = 0;
1360 int slope = 0;
1361 int rc = 0;
1362 int delta_ocv_uv_limit = 0;
1363
1364 rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
1365 if (rc < 0) {
1366 pr_err("simultaneous vbat ibat failed err = %d\n", rc);
1367 goto out;
1368 }
1369
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001370 very_low_voltage_check(chip, vbat_uv);
1371
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001372 delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
1373
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001374 ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
1375
1376 chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
1377 / (params->rbatt_mohm);
1378
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001379 pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
1380 soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
1381 (s64)params->fcc_uah - params->uuc_uah);
1382 soc_est = bound_soc(soc_est);
1383
Xiaozhe Shi20640b52013-01-03 11:49:30 -08001384 /* never adjust during bms reset mode */
1385 if (bms_reset) {
1386 pr_debug("bms reset mode, SOC adjustment skipped\n");
1387 goto out;
1388 }
1389
Xiaozhe Shiba3bdd32012-11-29 14:50:53 -08001390 if (ibat_ua < 0 && !is_batfet_open(chip)) {
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001391 soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
1392 batt_temp);
1393 goto out;
1394 }
1395
1396 /*
1397 * do not adjust
1398 * if soc is same as what bms calculated
1399 * if soc_est is between 45 and 25, this is the flat portion of the
1400 * curve where soc_est is not so accurate. We generally don't want to
1401 * adjust when soc_est is inaccurate except for the cases when soc is
1402 * way far off (higher than 50 or lesser than 20).
1403 * Also don't adjust soc if it is above 90 becuase it might be pulled
1404 * low and cause a bad user experience
1405 */
1406 if (soc_est == soc
1407 || (is_between(45, chip->adjust_soc_low_threshold, soc_est)
1408 && is_between(50, chip->adjust_soc_low_threshold - 5, soc))
1409 || soc >= 90)
1410 goto out;
1411
1412 if (chip->last_soc_est == -EINVAL)
1413 chip->last_soc_est = soc;
1414
1415 n = min(200, max(1 , soc + soc_est + chip->last_soc_est));
1416 chip->last_soc_est = soc_est;
1417
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001418 pc = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001419 if (pc > 0) {
1420 pc_new = calculate_pc(chip,
1421 chip->last_ocv_uv - (++slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001422 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001423 while (pc_new == pc) {
1424 /* start taking 10mV steps */
1425 slope = slope + 10;
1426 pc_new = calculate_pc(chip,
1427 chip->last_ocv_uv - (slope * 1000),
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001428 chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001429 }
1430 } else {
1431 /*
1432 * pc is already at the lowest point,
1433 * assume 1 millivolt translates to 1% pc
1434 */
1435 pc = 1;
1436 pc_new = 0;
1437 slope = 1;
1438 }
1439
1440 delta_ocv_uv = div_s64((soc - soc_est) * (s64)slope * 1000,
1441 n * (pc - pc_new));
1442
1443 if (abs(delta_ocv_uv) > delta_ocv_uv_limit) {
1444 pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
1445 delta_ocv_uv_limit);
1446
1447 if (delta_ocv_uv > 0)
1448 delta_ocv_uv = delta_ocv_uv_limit;
1449 else
1450 delta_ocv_uv = -1 * delta_ocv_uv_limit;
1451 pr_debug("new delta ocv = %d\n", delta_ocv_uv);
1452 }
1453
1454 chip->last_ocv_uv -= delta_ocv_uv;
1455
1456 if (chip->last_ocv_uv >= chip->max_voltage_uv)
1457 chip->last_ocv_uv = chip->max_voltage_uv;
1458
1459 /* calculate the soc based on this new ocv */
Abhijeet Dharmapurikar4b97cdd2012-12-26 21:10:53 -08001460 pc_new = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001461 rc_new_uah = (params->fcc_uah * pc_new) / 100;
1462 soc_new = (rc_new_uah - params->cc_uah - params->uuc_uah)*100
1463 / (params->fcc_uah - params->uuc_uah);
1464 soc_new = bound_soc(soc_new);
1465
1466 /*
1467 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
1468 * soc = 0 should happen only when soc_est == 0
1469 */
1470 if (soc_new == 0 && soc_est != 0)
1471 soc_new = 1;
1472
1473 soc = soc_new;
1474
1475out:
1476 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",
1477 ibat_ua, vbat_uv, ocv_est_uv, pc_est,
1478 soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001479 pc_new, soc_new, params->rbatt_mohm, slope);
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07001480
Xiaozhe Shie118c692012-09-24 15:17:43 -07001481 return soc;
1482}
1483
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001484static int clamp_soc_based_on_voltage(struct qpnp_bms_chip *chip, int soc)
1485{
1486 int rc, vbat_uv;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001487
Xiaozhe Shi36458962013-02-06 16:19:57 -08001488 rc = get_battery_voltage(&vbat_uv);
1489 if (rc < 0) {
1490 pr_err("adc vbat failed err = %d\n", rc);
1491 return soc;
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001492 }
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001493 if (soc == 0 && vbat_uv > chip->v_cutoff_uv) {
1494 pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
1495 vbat_uv, chip->v_cutoff_uv);
1496 return 1;
1497 } else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
1498 pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
1499 vbat_uv, chip->v_cutoff_uv);
1500 return 0;
1501 } else {
1502 pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
1503 soc, vbat_uv, chip->v_cutoff_uv);
1504 return soc;
1505 }
1506}
1507
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001508static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
1509 struct raw_soc_params *raw,
1510 int batt_temp)
1511{
Xiaozhe Shie118c692012-09-24 15:17:43 -07001512 int soc, new_ocv_uv;
1513 int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
1514 struct soc_params params;
1515
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001516 if (!chip->battery_present) {
Xiaozhe Shi026fa9b2013-03-22 17:00:50 -07001517 pr_debug("battery gone, reporting 100\n");
1518 new_calculated_soc = 100;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001519 goto done_calculating;
1520 }
Xiaozhe Shie118c692012-09-24 15:17:43 -07001521 calculate_soc_params(chip, raw, &params, batt_temp);
1522 /* calculate remaining usable charge */
1523 remaining_usable_charge_uah = params.ocv_charge_uah
1524 - params.cc_uah
1525 - params.uuc_uah;
1526
1527 pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
1528 if (params.fcc_uah - params.uuc_uah <= 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001529 pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001530 params.fcc_uah,
1531 params.uuc_uah);
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001532 new_calculated_soc = 0;
1533 goto done_calculating;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001534 }
1535
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001536 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1537 (params.fcc_uah - params.uuc_uah));
1538
Xiaozhe Shie118c692012-09-24 15:17:43 -07001539 if (chip->first_time_calc_soc && soc < 0) {
1540 /*
1541 * first time calcualtion and the pon ocv is too low resulting
1542 * in a bad soc. Adjust ocv to get 0 soc
1543 */
1544 pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
1545 find_ocv_for_soc(chip, &params, batt_temp, 0, &new_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 pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
1556 soc, chip->last_ocv_uv);
1557 }
1558
1559 if (soc > 100)
1560 soc = 100;
1561
1562 if (soc < 0) {
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001563 pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
Xiaozhe Shie118c692012-09-24 15:17:43 -07001564 remaining_usable_charge_uah,
1565 params.ocv_charge_uah,
1566 params.cc_uah, params.uuc_uah);
1567
Xiaozhe Shicb386a22012-11-29 12:11:42 -08001568 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 -07001569 chip->last_ocv_uv, batt_temp,
1570 params.fcc_uah, soc);
1571 soc = 0;
1572 }
1573
1574 mutex_lock(&chip->soc_invalidation_mutex);
1575 shutdown_soc = chip->shutdown_soc;
1576
1577 if (chip->first_time_calc_soc && soc != shutdown_soc
1578 && is_shutdown_soc_within_limits(chip, soc)) {
1579 /*
1580 * soc for the first time - use shutdown soc
1581 * to adjust pon ocv since it is a small percent away from
1582 * the real soc
1583 */
1584 pr_debug("soc = %d before forcing shutdown_soc = %d\n",
1585 soc, shutdown_soc);
1586 find_ocv_for_soc(chip, &params, batt_temp,
1587 shutdown_soc, &new_ocv_uv);
1588 chip->pon_ocv_uv = chip->last_ocv_uv;
1589 chip->last_ocv_uv = new_ocv_uv;
1590
1591 remaining_usable_charge_uah = params.ocv_charge_uah
1592 - params.cc_uah
1593 - params.uuc_uah;
1594
1595 soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
1596 (params.fcc_uah
1597 - params.uuc_uah));
1598
1599 pr_debug("DONE for shutdown_soc = %d soc is %d, adjusted ocv to %duV\n",
1600 shutdown_soc, soc, chip->last_ocv_uv);
1601 }
1602 mutex_unlock(&chip->soc_invalidation_mutex);
1603
1604 pr_debug("SOC before adjustment = %d\n", soc);
1605 new_calculated_soc = adjust_soc(chip, &params, soc, batt_temp);
1606
Xiaozhe Shi445d2492013-03-27 18:10:18 -07001607 /* always clamp soc due to BMS hw/sw immaturities */
1608 new_calculated_soc = clamp_soc_based_on_voltage(chip,
1609 new_calculated_soc);
Xiaozhe Shi2542c602012-11-28 10:08:07 -08001610
Xiaozhe Shifd8cd482013-02-12 10:00:38 -08001611done_calculating:
Xiaozhe Shie118c692012-09-24 15:17:43 -07001612 if (new_calculated_soc != chip->calculated_soc
1613 && chip->bms_psy.name != NULL) {
1614 power_supply_changed(&chip->bms_psy);
1615 pr_debug("power supply changed\n");
1616 }
1617
1618 chip->calculated_soc = new_calculated_soc;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001619 if (chip->last_soc_invalid) {
1620 chip->last_soc_invalid = false;
1621 chip->last_soc = -EINVAL;
1622 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001623 pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
Xiaozhe Shie118c692012-09-24 15:17:43 -07001624 chip->first_time_calc_soc = 0;
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001625 get_current_time(&chip->last_recalc_time);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001626 return chip->calculated_soc;
1627}
1628
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001629static int calculate_soc_from_voltage(struct qpnp_bms_chip *chip)
1630{
1631 int voltage_range_uv, voltage_remaining_uv, voltage_based_soc;
Xiaozhe Shi36458962013-02-06 16:19:57 -08001632 int rc, vbat_uv;
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001633
Xiaozhe Shi36458962013-02-06 16:19:57 -08001634 rc = get_battery_voltage(&vbat_uv);
1635 if (rc < 0) {
1636 pr_err("adc vbat failed err = %d\n", rc);
1637 return rc;
1638 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001639 voltage_range_uv = chip->max_voltage_uv - chip->v_cutoff_uv;
1640 voltage_remaining_uv = vbat_uv - chip->v_cutoff_uv;
1641 voltage_based_soc = voltage_remaining_uv * 100 / voltage_range_uv;
1642
1643 voltage_based_soc = clamp(voltage_based_soc, 0, 100);
1644
1645 if (chip->prev_voltage_based_soc != voltage_based_soc
1646 && chip->bms_psy.name != NULL) {
1647 power_supply_changed(&chip->bms_psy);
1648 pr_debug("power supply changed\n");
1649 }
1650 chip->prev_voltage_based_soc = voltage_based_soc;
1651
1652 pr_debug("vbat used = %duv\n", vbat_uv);
1653 pr_debug("Calculated voltage based soc = %d\n", voltage_based_soc);
1654 return voltage_based_soc;
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001655}
1656
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001657static int recalculate_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001658{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001659 int batt_temp, rc, soc;
1660 struct qpnp_vadc_result result;
1661 struct raw_soc_params raw;
1662
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001663 wake_lock(&chip->soc_wake_lock);
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001664 if (chip->use_voltage_soc) {
1665 soc = calculate_soc_from_voltage(chip);
1666 } else {
1667 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1668 if (rc) {
1669 pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
1670 LR_MUX1_BATT_THERM, rc);
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001671 soc = chip->calculated_soc;
1672 } else {
1673 pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
1674 result.physical,
1675 result.measurement);
1676 batt_temp = (int)result.physical;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001677
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001678 mutex_lock(&chip->last_ocv_uv_mutex);
1679 read_soc_params_raw(chip, &raw, batt_temp);
1680 soc = calculate_state_of_charge(chip, &raw, batt_temp);
1681 mutex_unlock(&chip->last_ocv_uv_mutex);
1682 }
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001683 }
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08001684 wake_unlock(&chip->soc_wake_lock);
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001685 return soc;
1686}
1687
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001688static void recalculate_work(struct work_struct *work)
1689{
1690 struct qpnp_bms_chip *chip = container_of(work,
1691 struct qpnp_bms_chip,
1692 recalc_work);
1693
1694 recalculate_soc(chip);
1695}
1696
Xiaozhe Shicdeee312012-12-18 15:10:18 -08001697static void calculate_soc_work(struct work_struct *work)
1698{
1699 struct qpnp_bms_chip *chip = container_of(work,
1700 struct qpnp_bms_chip,
1701 calculate_soc_delayed_work.work);
1702 int soc = recalculate_soc(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001703
Xiaozhe Shi4be85782013-02-22 17:33:40 -08001704 if (soc < chip->low_soc_calc_threshold
1705 || chip->low_voltage_wake_lock_held)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001706 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1707 round_jiffies_relative(msecs_to_jiffies
1708 (chip->low_soc_calculate_soc_ms)));
1709 else
1710 schedule_delayed_work(&chip->calculate_soc_delayed_work,
1711 round_jiffies_relative(msecs_to_jiffies
1712 (chip->calculate_soc_ms)));
1713}
1714
Xiaozhe Shie118c692012-09-24 15:17:43 -07001715static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
1716 int soc)
1717{
1718 u8 temp;
1719 int rc;
1720 int iavg_ma = chip->prev_uuc_iavg_ma;
1721
1722 if (iavg_ma > IAVG_START)
1723 temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
1724 else
1725 temp = 0;
1726
1727 rc = qpnp_write_wrapper(chip, &temp,
1728 chip->base + IAVG_STORAGE_REG, 1);
1729
Xiaozhe Shic7cbd052013-03-29 12:03:11 -07001730 temp = soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001731
1732 /* don't store soc if temperature is below 5degC */
1733 if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
1734 rc = qpnp_write_wrapper(chip, &temp,
1735 chip->base + SOC_STORAGE_REG, 1);
1736}
1737
1738#define SOC_CATCHUP_SEC_MAX 600
1739#define SOC_CATCHUP_SEC_PER_PERCENT 60
1740#define MAX_CATCHUP_SOC (SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
1741static int scale_soc_while_chg(struct qpnp_bms_chip *chip,
1742 int delta_time_us, int new_soc, int prev_soc)
1743{
1744 int chg_time_sec;
1745 int catch_up_sec;
1746 int scaled_soc;
1747 int numerator;
1748
1749 /*
1750 * The device must be charging for reporting a higher soc, if
1751 * not ignore this soc and continue reporting the prev_soc.
1752 * Also don't report a high value immediately slowly scale the
1753 * value from prev_soc to the new soc based on a charge time
1754 * weighted average
1755 */
1756
1757 /* if not charging, return last soc */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001758 if (!is_battery_charging(chip))
Xiaozhe Shie118c692012-09-24 15:17:43 -07001759 return prev_soc;
1760
1761 chg_time_sec = DIV_ROUND_UP(chip->charge_time_us, USEC_PER_SEC);
1762 catch_up_sec = DIV_ROUND_UP(chip->catch_up_time_us, USEC_PER_SEC);
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001763 if (catch_up_sec == 0)
1764 return new_soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001765 pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
1766
1767 /*
1768 * if charging for more than catch_up time, simply return
1769 * new soc
1770 */
1771 if (chg_time_sec > catch_up_sec)
1772 return new_soc;
1773
1774 numerator = (catch_up_sec - chg_time_sec) * prev_soc
1775 + chg_time_sec * new_soc;
1776 scaled_soc = numerator / catch_up_sec;
1777
1778 pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
1779 chg_time_sec, new_soc, prev_soc, scaled_soc);
1780
1781 return scaled_soc;
1782}
1783
1784/*
1785 * bms_fake_battery is set in setups where a battery emulator is used instead
1786 * of a real battery. This makes the bms driver report a different/fake value
1787 * regardless of the calculated state of charge.
1788 */
1789static int bms_fake_battery = -EINVAL;
1790module_param(bms_fake_battery, int, 0644);
1791
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001792static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
1793{
1794 pr_debug("Reported voltage based soc = %d\n",
1795 chip->prev_voltage_based_soc);
1796 return chip->prev_voltage_based_soc;
1797}
1798
1799static int report_cc_based_soc(struct qpnp_bms_chip *chip)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001800{
1801 int soc;
1802 int delta_time_us;
1803 struct timespec now;
1804 struct qpnp_vadc_result result;
1805 int batt_temp;
1806 int rc;
1807
Xiaozhe Shie118c692012-09-24 15:17:43 -07001808 soc = chip->calculated_soc;
1809
1810 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
1811
1812 if (rc) {
1813 pr_err("error reading adc channel = %d, rc = %d\n",
1814 LR_MUX1_BATT_THERM, rc);
1815 return rc;
1816 }
1817 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1818 result.measurement);
1819 batt_temp = (int)result.physical;
1820
1821 do_posix_clock_monotonic_gettime(&now);
1822 if (chip->t_soc_queried.tv_sec != 0) {
1823 delta_time_us
1824 = (now.tv_sec - chip->t_soc_queried.tv_sec) * USEC_PER_SEC
1825 + (now.tv_nsec - chip->t_soc_queried.tv_nsec) / 1000;
1826 } else {
1827 /* calculation for the first time */
1828 delta_time_us = 0;
1829 }
1830
1831 /*
1832 * account for charge time - limit it to SOC_CATCHUP_SEC to
1833 * avoid overflows when charging continues for extended periods
1834 */
Xiaozhe Shi28f5dd52013-01-04 12:19:58 -08001835 if (is_battery_charging(chip)) {
Xiaozhe Shie118c692012-09-24 15:17:43 -07001836 if (chip->charge_time_us == 0) {
1837 /*
1838 * calculating soc for the first time
1839 * after start of chg. Initialize catchup time
1840 */
1841 if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
1842 chip->catch_up_time_us =
1843 (soc - chip->last_soc)
1844 * SOC_CATCHUP_SEC_PER_PERCENT
1845 * USEC_PER_SEC;
1846 else
1847 chip->catch_up_time_us =
1848 SOC_CATCHUP_SEC_MAX * USEC_PER_SEC;
1849
1850 if (chip->catch_up_time_us < 0)
1851 chip->catch_up_time_us = 0;
1852 }
1853
1854 /* add charge time */
1855 if (chip->charge_time_us < SOC_CATCHUP_SEC_MAX * USEC_PER_SEC)
1856 chip->charge_time_us += delta_time_us;
1857
1858 /* end catchup if calculated soc and last soc are same */
1859 if (chip->last_soc == soc)
1860 chip->catch_up_time_us = 0;
1861 }
1862
1863 /* last_soc < soc ... scale and catch up */
Xiaozhe Shi4532d2d2012-12-17 19:34:50 -08001864 if (chip->last_soc != -EINVAL && chip->last_soc < soc && soc != 100)
Xiaozhe Shie118c692012-09-24 15:17:43 -07001865 soc = scale_soc_while_chg(chip, delta_time_us,
1866 soc, chip->last_soc);
1867
1868 pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
1869 chip->last_soc, chip->calculated_soc, soc);
1870 chip->last_soc = soc;
1871 backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
1872 pr_debug("Reported SOC = %d\n", chip->last_soc);
1873 chip->t_soc_queried = now;
1874
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001875 return soc;
Xiaozhe Shie118c692012-09-24 15:17:43 -07001876}
1877
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001878static int report_state_of_charge(struct qpnp_bms_chip *chip)
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001879{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001880 if (bms_fake_battery != -EINVAL) {
1881 pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
1882 return bms_fake_battery;
1883 } else if (chip->use_voltage_soc)
1884 return report_voltage_based_soc(chip);
1885 else
1886 return report_cc_based_soc(chip);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08001887}
1888
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001889/* Returns capacity as a SoC percentage between 0 and 100 */
1890static int get_prop_bms_capacity(struct qpnp_bms_chip *chip)
1891{
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08001892 return report_state_of_charge(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001893}
1894
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001895/* Returns estimated max current that the battery can supply in uA */
1896static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
1897{
1898 return chip->ibat_max_ua;
1899}
1900
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001901/* Returns instantaneous current in uA */
1902static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
1903{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001904 int rc, result_ua;
1905
1906 rc = get_battery_current(chip, &result_ua);
1907 if (rc) {
1908 pr_err("failed to get current: %d\n", rc);
1909 return rc;
1910 }
1911 return result_ua;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001912}
1913
1914/* Returns full charge design in uAh */
1915static int get_prop_bms_charge_full_design(struct qpnp_bms_chip *chip)
1916{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001917 return chip->fcc;
1918}
1919
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001920static int get_prop_bms_present(struct qpnp_bms_chip *chip)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001921{
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001922 return chip->battery_present;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001923}
1924
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001925static void set_prop_bms_present(struct qpnp_bms_chip *chip, int present)
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001926{
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001927 if (chip->battery_present != present) {
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001928 chip->battery_present = present;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08001929 if (present)
1930 chip->new_battery = true;
1931 /* a new battery was inserted or removed, so force a soc
1932 * recalculation to update the SoC */
1933 schedule_work(&chip->recalc_work);
1934 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001935}
1936
1937static void qpnp_bms_external_power_changed(struct power_supply *psy)
1938{
1939}
1940
1941static int qpnp_bms_power_get_property(struct power_supply *psy,
1942 enum power_supply_property psp,
1943 union power_supply_propval *val)
1944{
1945 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1946 bms_psy);
1947
1948 switch (psp) {
1949 case POWER_SUPPLY_PROP_CAPACITY:
1950 val->intval = get_prop_bms_capacity(chip);
1951 break;
1952 case POWER_SUPPLY_PROP_CURRENT_NOW:
1953 val->intval = get_prop_bms_current_now(chip);
1954 break;
Xiaozhe Shi904f1f72012-12-04 12:47:21 -08001955 case POWER_SUPPLY_PROP_CURRENT_MAX:
1956 val->intval = get_prop_bms_current_max(chip);
1957 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001958 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1959 val->intval = get_prop_bms_charge_full_design(chip);
1960 break;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001961 case POWER_SUPPLY_PROP_PRESENT:
1962 val->intval = get_prop_bms_present(chip);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07001963 break;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001964 default:
1965 return -EINVAL;
1966 }
1967 return 0;
1968}
1969
1970static int qpnp_bms_power_set_property(struct power_supply *psy,
1971 enum power_supply_property psp,
1972 const union power_supply_propval *val)
1973{
1974 struct qpnp_bms_chip *chip = container_of(psy, struct qpnp_bms_chip,
1975 bms_psy);
1976
1977 switch (psp) {
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001978 case POWER_SUPPLY_PROP_PRESENT:
1979 set_prop_bms_present(chip, val->intval);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07001980 break;
1981 default:
1982 return -EINVAL;
1983 }
1984 return 0;
1985}
1986
Xiaozhe Shibdf14742012-12-05 12:41:48 -08001987#define OCV_USE_LIMIT_EN BIT(7)
1988static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
1989 int low_voltage_threshold,
1990 int high_voltage_threshold)
1991{
1992 uint16_t low_voltage_raw, high_voltage_raw;
1993 int rc;
1994
1995 low_voltage_raw = convert_vbatt_uv_to_raw(chip,
1996 low_voltage_threshold);
1997 high_voltage_raw = convert_vbatt_uv_to_raw(chip,
1998 high_voltage_threshold);
1999 rc = qpnp_write_wrapper(chip, (u8 *)&low_voltage_raw,
2000 chip->base + BMS1_OCV_USE_LOW_LIMIT_THR0, 2);
2001 if (rc) {
2002 pr_err("Failed to set ocv low voltage threshold: %d\n", rc);
2003 return rc;
2004 }
2005 rc = qpnp_write_wrapper(chip, (u8 *)&high_voltage_raw,
2006 chip->base + BMS1_OCV_USE_HIGH_LIMIT_THR0, 2);
2007 if (rc) {
2008 pr_err("Failed to set ocv high voltage threshold: %d\n", rc);
2009 return rc;
2010 }
2011 rc = qpnp_masked_write(chip, BMS1_OCV_USE_LIMIT_CTL,
2012 OCV_USE_LIMIT_EN, OCV_USE_LIMIT_EN);
2013 if (rc) {
2014 pr_err("Failed to enabled ocv voltage thresholds: %d\n", rc);
2015 return rc;
2016 }
2017 pr_debug("ocv low threshold set to %d uv or 0x%x raw\n",
2018 low_voltage_threshold, low_voltage_raw);
2019 pr_debug("ocv high threshold set to %d uv or 0x%x raw\n",
2020 high_voltage_threshold, high_voltage_raw);
2021 return 0;
2022}
2023
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002024static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
2025{
2026 int rc;
2027 u8 temp;
2028
2029 if (chip->ignore_shutdown_soc) {
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002030 chip->shutdown_soc_invalid = true;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002031 chip->shutdown_soc = 0;
2032 chip->shutdown_iavg_ma = 0;
2033 } else {
2034 rc = qpnp_read_wrapper(chip, &temp,
2035 chip->base + IAVG_STORAGE_REG, 1);
2036 if (rc) {
2037 pr_err("failed to read addr = %d %d assuming %d\n",
2038 chip->base + IAVG_STORAGE_REG, rc,
2039 IAVG_START);
2040 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shif5f966d2013-02-19 14:23:11 -08002041 } else if (temp == IAVG_INVALID) {
2042 pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
2043 IAVG_START);
2044 chip->shutdown_iavg_ma = IAVG_START;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002045 } else {
2046 if (temp == 0) {
2047 chip->shutdown_iavg_ma = IAVG_START;
2048 } else {
2049 chip->shutdown_iavg_ma = IAVG_START
2050 + IAVG_STEP_SIZE_MA * (temp + 1);
2051 }
2052 }
2053
2054 rc = qpnp_read_wrapper(chip, &temp,
2055 chip->base + SOC_STORAGE_REG, 1);
2056 if (rc) {
2057 pr_err("failed to read addr = %d %d\n",
2058 chip->base + SOC_STORAGE_REG, rc);
2059 } else {
2060 chip->shutdown_soc = temp;
2061
Xiaozhe Shic7cbd052013-03-29 12:03:11 -07002062 if (chip->shutdown_soc == SOC_INVALID) {
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002063 pr_debug("No shutdown soc available\n");
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002064 chip->shutdown_soc_invalid = true;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002065 chip->shutdown_iavg_ma = 0;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002066 }
2067 }
2068 }
2069
2070 pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
2071 chip->shutdown_soc,
2072 chip->shutdown_iavg_ma,
2073 chip->shutdown_soc_invalid);
2074}
2075
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002076#define PALLADIUM_ID_MIN 0x7F40
2077#define PALLADIUM_ID_MAX 0x7F5A
2078#define DESAY_5200_ID_MIN 0x7F7F
2079#define DESAY_5200_ID_MAX 0x802F
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002080static int32_t read_battery_id(struct qpnp_bms_chip *chip)
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002081{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002082 int rc;
2083 struct qpnp_vadc_result result;
2084
2085 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2086 if (rc) {
2087 pr_err("error reading batt id channel = %d, rc = %d\n",
2088 LR_MUX2_BAT_ID, rc);
2089 return rc;
2090 }
2091 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
2092 result.measurement);
2093 pr_debug("raw_code = 0x%x\n", result.adc_code);
2094 return result.adc_code;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002095}
2096
2097static int set_battery_data(struct qpnp_bms_chip *chip)
2098{
2099 int64_t battery_id;
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002100 struct bms_battery_data *batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002101
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002102 if (chip->batt_type == BATT_DESAY) {
2103 batt_data = &desay_5200_data;
2104 } else if (chip->batt_type == BATT_PALLADIUM) {
2105 batt_data = &palladium_1500_data;
2106 } else if (chip->batt_type == BATT_OEM) {
2107 batt_data = &oem_batt_data;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002108 } else {
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002109 battery_id = read_battery_id(chip);
2110 if (battery_id < 0) {
2111 pr_err("cannot read battery id err = %lld\n",
2112 battery_id);
2113 return battery_id;
2114 }
2115
2116 if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
2117 battery_id)) {
2118 batt_data = &palladium_1500_data;
2119 } else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
2120 battery_id)) {
2121 batt_data = &desay_5200_data;
2122 } else {
2123 pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
2124 battery_id);
2125 batt_data = &palladium_1500_data;
2126 }
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002127 }
2128
Xiaozhe Shi77a5b052012-12-14 16:37:45 -08002129 chip->fcc = batt_data->fcc;
2130 chip->fcc_temp_lut = batt_data->fcc_temp_lut;
2131 chip->fcc_sf_lut = batt_data->fcc_sf_lut;
2132 chip->pc_temp_ocv_lut = batt_data->pc_temp_ocv_lut;
2133 chip->pc_sf_lut = batt_data->pc_sf_lut;
2134 chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
2135 chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
2136
2137 if (chip->pc_temp_ocv_lut == NULL) {
2138 pr_err("temp ocv lut table is NULL\n");
2139 return -EINVAL;
2140 }
2141 return 0;
Xiaozhe Shi73a65692012-09-18 17:51:57 -07002142}
2143
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002144#define SPMI_PROP_READ(chip_prop, qpnp_spmi_property, retval) \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002145do { \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002146 retval = of_property_read_u32(chip->spmi->dev.of_node, \
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002147 "qcom," qpnp_spmi_property, \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002148 &chip->chip_prop); \
2149 if (retval) { \
2150 pr_err("Error reading " #qpnp_spmi_property \
2151 " property %d\n", rc); \
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002152 return -EINVAL; \
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002153 } \
2154} while (0)
2155
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002156static inline int bms_read_properties(struct qpnp_bms_chip *chip)
2157{
2158 int rc;
2159
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002160 SPMI_PROP_READ(r_sense_uohm, "r-sense-uohm", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002161 SPMI_PROP_READ(v_cutoff_uv, "v-cutoff-uv", rc);
2162 SPMI_PROP_READ(max_voltage_uv, "max-voltage-uv", rc);
2163 SPMI_PROP_READ(r_conn_mohm, "r-conn-mohm", rc);
2164 SPMI_PROP_READ(chg_term_ua, "chg-term-ua", rc);
2165 SPMI_PROP_READ(shutdown_soc_valid_limit,
2166 "shutdown-soc-valid-limit", rc);
2167 SPMI_PROP_READ(adjust_soc_high_threshold,
2168 "adjust-soc-high-threshold", rc);
2169 SPMI_PROP_READ(adjust_soc_low_threshold,
2170 "adjust-soc-low-threshold", rc);
2171 SPMI_PROP_READ(batt_type, "batt-type", rc);
2172 SPMI_PROP_READ(low_soc_calc_threshold,
2173 "low-soc-calculate-soc-threshold", rc);
2174 SPMI_PROP_READ(low_soc_calculate_soc_ms,
2175 "low-soc-calculate-soc-ms", rc);
2176 SPMI_PROP_READ(calculate_soc_ms, "calculate-soc-ms", rc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002177 chip->use_external_rsense = of_property_read_bool(
2178 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002179 "qcom,use-external-rsense");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002180 chip->ignore_shutdown_soc = of_property_read_bool(
2181 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002182 "qcom,ignore-shutdown-soc");
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002183 chip->use_voltage_soc = of_property_read_bool(chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002184 "qcom,use-voltage-soc");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002185 chip->use_ocv_thresholds = of_property_read_bool(
2186 chip->spmi->dev.of_node,
Xiaozhe Shi9bd24622013-01-23 15:54:54 -08002187 "qcom,use-ocv-thresholds");
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002188 SPMI_PROP_READ(ocv_high_threshold_uv,
2189 "ocv-voltage-high-threshold-uv", rc);
2190 SPMI_PROP_READ(ocv_low_threshold_uv,
2191 "ocv-voltage-low-threshold-uv", rc);
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002192 SPMI_PROP_READ(low_voltage_threshold, "low-voltage-threshold", rc);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002193
2194 if (chip->adjust_soc_low_threshold >= 45)
2195 chip->adjust_soc_low_threshold = 45;
2196
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002197 pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
2198 chip->r_sense_uohm, chip->v_cutoff_uv,
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002199 chip->max_voltage_uv);
2200 pr_debug("r_conn:%d, shutdown_soc: %d, adjust_soc_low:%d\n",
2201 chip->r_conn_mohm, chip->shutdown_soc_valid_limit,
2202 chip->adjust_soc_low_threshold);
2203 pr_debug("adjust_soc_high:%d, chg_term_ua:%d, batt_type:%d\n",
2204 chip->adjust_soc_high_threshold, chip->chg_term_ua,
2205 chip->batt_type);
Xiaozhe Shi781b0a22012-11-05 17:18:27 -08002206 pr_debug("ignore_shutdown_soc:%d, use_voltage_soc:%d\n",
Xiaozhe Shi79d6c1d2012-11-26 13:19:50 -08002207 chip->ignore_shutdown_soc, chip->use_voltage_soc);
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002208 pr_debug("use external rsense: %d\n", chip->use_external_rsense);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002209 return 0;
2210}
2211
2212static inline void bms_initialize_constants(struct qpnp_bms_chip *chip)
2213{
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002214 chip->prev_pc_unusable = -EINVAL;
2215 chip->soc_at_cv = -EINVAL;
2216 chip->calculated_soc = -EINVAL;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002217 chip->last_soc = -EINVAL;
Xiaozhe Shi7edde5d2012-09-26 11:23:09 -07002218 chip->last_soc_est = -EINVAL;
Xiaozhe Shif36d2862013-01-04 10:17:35 -08002219 chip->last_cc_uah = INT_MIN;
Abhijeet Dharmapurikar15f30fb2012-12-27 17:20:29 -08002220 chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
2221 chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
Xiaozhe Shie118c692012-09-24 15:17:43 -07002222 chip->first_time_calc_soc = 1;
2223 chip->first_time_calc_uuc = 1;
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002224}
2225
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002226#define REG_OFFSET_PERP_TYPE 0x04
2227#define REG_OFFSET_PERP_SUBTYPE 0x05
2228#define BMS_BMS_TYPE 0xD
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002229#define BMS_BMS1_SUBTYPE 0x1
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002230#define BMS_IADC_TYPE 0x8
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002231#define BMS_IADC1_SUBTYPE 0x3
2232#define BMS_IADC2_SUBTYPE 0x5
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002233
2234static int register_spmi(struct qpnp_bms_chip *chip, struct spmi_device *spmi)
2235{
2236 struct spmi_resource *spmi_resource;
2237 struct resource *resource;
2238 int rc;
2239 u8 type, subtype;
2240
2241 chip->dev = &(spmi->dev);
2242 chip->spmi = spmi;
2243
2244 spmi_for_each_container_dev(spmi_resource, spmi) {
2245 if (!spmi_resource) {
2246 pr_err("qpnp_bms: spmi resource absent\n");
2247 return -ENXIO;
2248 }
2249
2250 resource = spmi_get_resource(spmi, spmi_resource,
2251 IORESOURCE_MEM, 0);
2252 if (!(resource && resource->start)) {
2253 pr_err("node %s IO resource absent!\n",
2254 spmi->dev.of_node->full_name);
2255 return -ENXIO;
2256 }
2257
2258 rc = qpnp_read_wrapper(chip, &type,
2259 resource->start + REG_OFFSET_PERP_TYPE, 1);
2260 if (rc) {
2261 pr_err("Peripheral type read failed rc=%d\n", rc);
2262 return rc;
2263 }
2264 rc = qpnp_read_wrapper(chip, &subtype,
2265 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2266 if (rc) {
2267 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2268 return rc;
2269 }
2270
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002271 if (type == BMS_BMS_TYPE && subtype == BMS_BMS1_SUBTYPE) {
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002272 chip->base = resource->start;
2273 } else if (type == BMS_IADC_TYPE
Xiaozhe Shief6274c2013-03-06 15:23:52 -08002274 && (subtype == BMS_IADC1_SUBTYPE
2275 || subtype == BMS_IADC2_SUBTYPE)) {
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002276 chip->iadc_base = resource->start;
2277 } else {
2278 pr_err("Invalid peripheral start=0x%x type=0x%x, subtype=0x%x\n",
2279 resource->start, type, subtype);
2280 }
2281 }
2282
2283 if (chip->base == 0) {
2284 dev_err(&spmi->dev, "BMS peripheral was not registered\n");
2285 return -EINVAL;
2286 }
2287 if (chip->iadc_base == 0) {
2288 dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
2289 return -EINVAL;
2290 }
2291
2292 return 0;
2293}
2294
2295#define ADC_CH_SEL_MASK 0x7
2296static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
2297{
2298 u8 iadc_channel_select;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002299 int32_t rds_rsense_nohm;
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002300 int rc;
2301
2302 rc = qpnp_read_wrapper(chip, &iadc_channel_select,
2303 chip->iadc_base + IADC1_BMS_ADC_CH_SEL_CTL, 1);
2304 if (rc) {
2305 pr_err("Error reading bms_iadc channel register %d\n", rc);
2306 return rc;
2307 }
2308
2309 iadc_channel_select &= ADC_CH_SEL_MASK;
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002310 if (iadc_channel_select != EXTERNAL_RSENSE
2311 && iadc_channel_select != INTERNAL_RSENSE) {
2312 pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
2313 iadc_channel_select);
2314 return -EINVAL;
2315 }
2316
2317 if (chip->use_external_rsense) {
2318 pr_debug("External rsense selected\n");
2319 if (iadc_channel_select == INTERNAL_RSENSE) {
2320 pr_debug("Internal rsense detected; Changing rsense to external\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002321 rc = qpnp_masked_write_iadc(chip,
2322 IADC1_BMS_ADC_CH_SEL_CTL,
2323 ADC_CH_SEL_MASK,
2324 EXTERNAL_RSENSE);
2325 if (rc) {
2326 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2327 IADC1_BMS_ADC_CH_SEL_CTL,
2328 EXTERNAL_RSENSE, rc);
2329 return rc;
2330 }
2331 reset_cc(chip);
2332 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002333 } else {
2334 pr_debug("Internal rsense selected\n");
2335 if (iadc_channel_select == EXTERNAL_RSENSE) {
2336 pr_debug("External rsense detected; Changing rsense to internal\n");
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002337 rc = qpnp_masked_write_iadc(chip,
2338 IADC1_BMS_ADC_CH_SEL_CTL,
2339 ADC_CH_SEL_MASK,
2340 INTERNAL_RSENSE);
2341 if (rc) {
2342 pr_err("Unable to set IADC1_BMS channel %x to %x: %d\n",
2343 IADC1_BMS_ADC_CH_SEL_CTL,
2344 INTERNAL_RSENSE, rc);
2345 return rc;
2346 }
2347 reset_cc(chip);
2348 }
Xiaozhe Shi767fdb62013-01-10 15:09:08 -08002349
2350 rc = qpnp_iadc_get_rsense(&rds_rsense_nohm);
2351 if (rc) {
2352 pr_err("Unable to read RDS resistance value from IADC; rc = %d\n",
2353 rc);
2354 return rc;
2355 }
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002356 chip->r_sense_uohm = rds_rsense_nohm/1000;
2357 pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
2358 rds_rsense_nohm, chip->r_sense_uohm);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002359 }
2360 return 0;
2361}
2362
2363static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002364{
2365 struct qpnp_bms_chip *chip;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002366 union power_supply_propval retval = {0,};
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002367 int rc, vbatt;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002368
2369 chip = kzalloc(sizeof *chip, GFP_KERNEL);
2370
2371 if (chip == NULL) {
2372 pr_err("kzalloc() failed.\n");
2373 return -ENOMEM;
2374 }
2375
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002376 rc = qpnp_vadc_is_ready();
2377 if (rc) {
2378 pr_info("vadc not ready: %d, deferring probe\n", rc);
2379 goto error_read;
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002380 }
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002381
2382 rc = qpnp_iadc_is_ready();
2383 if (rc) {
2384 pr_info("iadc not ready: %d, deferring probe\n", rc);
2385 goto error_read;
2386 }
2387
2388 rc = register_spmi(chip, spmi);
2389 if (rc) {
2390 pr_err("error registering spmi resource %d\n", rc);
2391 goto error_resource;
2392 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002393
2394 rc = qpnp_read_wrapper(chip, &chip->revision1,
2395 chip->base + BMS1_REVISION1, 1);
2396 if (rc) {
2397 pr_err("error reading version register %d\n", rc);
2398 goto error_read;
2399 }
2400
2401 rc = qpnp_read_wrapper(chip, &chip->revision2,
2402 chip->base + BMS1_REVISION2, 1);
2403 if (rc) {
2404 pr_err("Error reading version register %d\n", rc);
2405 goto error_read;
2406 }
Xiaozhe Shia045a562012-11-28 16:55:39 -08002407 pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002408
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002409 rc = bms_read_properties(chip);
2410 if (rc) {
2411 pr_err("Unable to read all bms properties, rc = %d\n", rc);
2412 goto error_read;
2413 }
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002414
Xiaozhe Shidffbe692012-12-11 15:35:46 -08002415 rc = read_iadc_channel_select(chip);
2416 if (rc) {
2417 pr_err("Unable to get iadc selected channel = %d\n", rc);
2418 goto error_read;
2419 }
2420
Xiaozhe Shibdf14742012-12-05 12:41:48 -08002421 if (chip->use_ocv_thresholds) {
2422 rc = set_ocv_voltage_thresholds(chip,
2423 chip->ocv_low_threshold_uv,
2424 chip->ocv_high_threshold_uv);
2425 if (rc) {
2426 pr_err("Could not set ocv voltage thresholds: %d\n",
2427 rc);
2428 goto error_read;
2429 }
2430 }
2431
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002432 rc = set_battery_data(chip);
2433 if (rc) {
2434 pr_err("Bad battery data %d\n", rc);
2435 goto error_read;
2436 }
2437
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002438 bms_initialize_constants(chip);
2439
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002440 mutex_init(&chip->bms_output_lock);
2441 mutex_init(&chip->last_ocv_uv_mutex);
2442 mutex_init(&chip->soc_invalidation_mutex);
2443
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002444 wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
2445 "qpnp_soc_lock");
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002446 wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
2447 "qpnp_low_voltage_lock");
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002448 INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
2449 calculate_soc_work);
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002450 INIT_WORK(&chip->recalc_work, recalculate_work);
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002451
2452 read_shutdown_soc_and_iavg(chip);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002453
2454 dev_set_drvdata(&spmi->dev, chip);
2455 device_init_wakeup(&spmi->dev, 1);
2456
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002457 if (!chip->batt_psy)
2458 chip->batt_psy = power_supply_get_by_name("battery");
2459 if (chip->batt_psy) {
2460 chip->batt_psy->get_property(chip->batt_psy,
2461 POWER_SUPPLY_PROP_PRESENT, &retval);
2462 chip->battery_present = retval.intval;
Xiaozhe Shi5cf7a672013-02-06 17:18:05 -08002463 pr_debug("present = %d\n", chip->battery_present);
2464 } else {
2465 chip->battery_present = 1;
Xiaozhe Shid5d21412013-02-06 17:14:41 -08002466 }
2467
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002468 calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
2469
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002470 /* setup & register the battery power supply */
2471 chip->bms_psy.name = "bms";
2472 chip->bms_psy.type = POWER_SUPPLY_TYPE_BMS;
2473 chip->bms_psy.properties = msm_bms_power_props;
2474 chip->bms_psy.num_properties = ARRAY_SIZE(msm_bms_power_props);
2475 chip->bms_psy.get_property = qpnp_bms_power_get_property;
2476 chip->bms_psy.set_property = qpnp_bms_power_set_property;
2477 chip->bms_psy.external_power_changed =
2478 qpnp_bms_external_power_changed;
2479 chip->bms_psy.supplied_to = qpnp_bms_supplicants;
2480 chip->bms_psy.num_supplicants = ARRAY_SIZE(qpnp_bms_supplicants);
2481
2482 rc = power_supply_register(chip->dev, &chip->bms_psy);
2483
2484 if (rc < 0) {
2485 pr_err("power_supply_register bms failed rc = %d\n", rc);
2486 goto unregister_dc;
2487 }
2488
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002489 vbatt = 0;
Xiaozhe Shi36458962013-02-06 16:19:57 -08002490 rc = get_battery_voltage(&vbatt);
2491 if (rc) {
2492 pr_err("error reading vbat_sns adc channel = %d, rc = %d\n",
2493 VBAT_SNS, rc);
2494 goto unregister_dc;
2495 }
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002496
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002497 pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u\n",
Xiaozhe Shicd7e5302012-10-17 12:29:53 -07002498 get_prop_bms_capacity(chip),
Xiaozhe Shid0a79542012-11-06 10:00:38 -08002499 vbatt, chip->last_ocv_uv, chip->r_sense_uohm);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002500 return 0;
2501
2502unregister_dc:
Abhijeet Dharmapurikar713b60a2012-12-26 21:30:05 -08002503 wake_lock_destroy(&chip->soc_wake_lock);
Xiaozhe Shi4be85782013-02-22 17:33:40 -08002504 wake_lock_destroy(&chip->low_voltage_wake_lock);
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002505 power_supply_unregister(&chip->bms_psy);
2506 dev_set_drvdata(&spmi->dev, NULL);
Xiaozhe Shic40b3972012-11-30 14:11:16 -08002507error_resource:
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002508error_read:
2509 kfree(chip);
2510 return rc;
2511}
2512
2513static int __devexit
2514qpnp_bms_remove(struct spmi_device *spmi)
2515{
2516 struct qpnp_bms_chip *chip = dev_get_drvdata(&spmi->dev);
2517
2518 dev_set_drvdata(&spmi->dev, NULL);
2519 kfree(chip);
2520 return 0;
2521}
2522
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002523static int bms_resume(struct device *dev)
2524{
2525 int rc;
2526 unsigned long soc_calc_period;
2527 unsigned long time_since_last_recalc;
2528 unsigned long tm_now_sec;
2529 struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
2530
2531 rc = get_current_time(&tm_now_sec);
2532 if (rc) {
2533 pr_err("Could not read current time: %d\n", rc);
2534 } else if (tm_now_sec > chip->last_recalc_time) {
2535 time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
2536 pr_debug("Time since last recalc: %lu\n",
2537 time_since_last_recalc);
2538 if (chip->calculated_soc < chip->low_soc_calc_threshold)
2539 soc_calc_period = chip->low_soc_calculate_soc_ms;
2540 else
2541 soc_calc_period = chip->calculate_soc_ms;
2542
2543 if (time_since_last_recalc >= soc_calc_period) {
2544 chip->last_recalc_time = tm_now_sec;
2545 recalculate_soc(chip);
2546 }
2547 }
2548 return 0;
2549}
2550
2551static const struct dev_pm_ops qpnp_bms_pm_ops = {
2552 .resume = bms_resume,
2553};
2554
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002555static struct spmi_driver qpnp_bms_driver = {
2556 .probe = qpnp_bms_probe,
2557 .remove = __devexit_p(qpnp_bms_remove),
2558 .driver = {
2559 .name = QPNP_BMS_DEV_NAME,
2560 .owner = THIS_MODULE,
2561 .of_match_table = qpnp_bms_match_table,
Xiaozhe Shicdeee312012-12-18 15:10:18 -08002562 .pm = &qpnp_bms_pm_ops,
Xiaozhe Shib19f7032012-08-16 12:14:16 -07002563 },
2564};
2565
2566static int __init qpnp_bms_init(void)
2567{
2568 pr_info("QPNP BMS INIT\n");
2569 return spmi_driver_register(&qpnp_bms_driver);
2570}
2571
2572static void __exit qpnp_bms_exit(void)
2573{
2574 pr_info("QPNP BMS EXIT\n");
2575 return spmi_driver_unregister(&qpnp_bms_driver);
2576}
2577
2578module_init(qpnp_bms_init);
2579module_exit(qpnp_bms_exit);
2580
2581MODULE_DESCRIPTION("QPNP BMS Driver");
2582MODULE_LICENSE("GPL v2");
2583MODULE_ALIAS("platform:" QPNP_BMS_DEV_NAME);