blob: 109ad4a0176d2229f33017da29202810aafd0f1c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
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 */
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/platform_device.h>
18#include <linux/errno.h>
19#include <linux/mfd/pm8xxx/pm8921-charger.h>
20#include <linux/mfd/pm8xxx/pm8921-bms.h>
Siddartha Mohanadoss77d106e2011-09-20 16:25:59 -070021#include <linux/mfd/pm8xxx/pm8921-adc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070022#include <linux/mfd/pm8xxx/core.h>
23#include <linux/interrupt.h>
24#include <linux/power_supply.h>
25#include <linux/delay.h>
26#include <linux/bitops.h>
27#include <linux/workqueue.h>
28#include <linux/debugfs.h>
29#include <linux/slab.h>
30
31#include <mach/msm_xo.h>
32#include <mach/msm_hsusb.h>
33
34#define CHG_BUCK_CLOCK_CTRL 0x14
35
36#define PBL_ACCESS1 0x04
37#define PBL_ACCESS2 0x05
38#define SYS_CONFIG_1 0x06
39#define SYS_CONFIG_2 0x07
40#define CHG_CNTRL 0x204
41#define CHG_IBAT_MAX 0x205
42#define CHG_TEST 0x206
43#define CHG_BUCK_CTRL_TEST1 0x207
44#define CHG_BUCK_CTRL_TEST2 0x208
45#define CHG_BUCK_CTRL_TEST3 0x209
46#define COMPARATOR_OVERRIDE 0x20A
47#define PSI_TXRX_SAMPLE_DATA_0 0x20B
48#define PSI_TXRX_SAMPLE_DATA_1 0x20C
49#define PSI_TXRX_SAMPLE_DATA_2 0x20D
50#define PSI_TXRX_SAMPLE_DATA_3 0x20E
51#define PSI_CONFIG_STATUS 0x20F
52#define CHG_IBAT_SAFE 0x210
53#define CHG_ITRICKLE 0x211
54#define CHG_CNTRL_2 0x212
55#define CHG_VBAT_DET 0x213
56#define CHG_VTRICKLE 0x214
57#define CHG_ITERM 0x215
58#define CHG_CNTRL_3 0x216
59#define CHG_VIN_MIN 0x217
60#define CHG_TWDOG 0x218
61#define CHG_TTRKL_MAX 0x219
62#define CHG_TEMP_THRESH 0x21A
63#define CHG_TCHG_MAX 0x21B
64#define USB_OVP_CONTROL 0x21C
65#define DC_OVP_CONTROL 0x21D
66#define USB_OVP_TEST 0x21E
67#define DC_OVP_TEST 0x21F
68#define CHG_VDD_MAX 0x220
69#define CHG_VDD_SAFE 0x221
70#define CHG_VBAT_BOOT_THRESH 0x222
71#define USB_OVP_TRIM 0x355
72#define BUCK_CONTROL_TRIM1 0x356
73#define BUCK_CONTROL_TRIM2 0x357
74#define BUCK_CONTROL_TRIM3 0x358
75#define BUCK_CONTROL_TRIM4 0x359
76#define CHG_DEFAULTS_TRIM 0x35A
77#define CHG_ITRIM 0x35B
78#define CHG_TTRIM 0x35C
79#define CHG_COMP_OVR 0x20A
80
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -070081/* check EOC every 10 seconds */
82#define EOC_CHECK_PERIOD_MS 10000
83
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084enum chg_fsm_state {
85 FSM_STATE_OFF_0 = 0,
86 FSM_STATE_BATFETDET_START_12 = 12,
87 FSM_STATE_BATFETDET_END_16 = 16,
88 FSM_STATE_ON_CHG_HIGHI_1 = 1,
89 FSM_STATE_ATC_2A = 2,
90 FSM_STATE_ATC_2B = 18,
91 FSM_STATE_ON_BAT_3 = 3,
92 FSM_STATE_ATC_FAIL_4 = 4 ,
93 FSM_STATE_DELAY_5 = 5,
94 FSM_STATE_ON_CHG_AND_BAT_6 = 6,
95 FSM_STATE_FAST_CHG_7 = 7,
96 FSM_STATE_TRKL_CHG_8 = 8,
97 FSM_STATE_CHG_FAIL_9 = 9,
98 FSM_STATE_EOC_10 = 10,
99 FSM_STATE_ON_CHG_VREGOK_11 = 11,
100 FSM_STATE_ATC_PAUSE_13 = 13,
101 FSM_STATE_FAST_CHG_PAUSE_14 = 14,
102 FSM_STATE_TRKL_CHG_PAUSE_15 = 15,
103 FSM_STATE_START_BOOT = 20,
104 FSM_STATE_FLCB_VREGOK = 21,
105 FSM_STATE_FLCB = 22,
106};
107
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700108enum chg_regulation_loop {
109 VDD_LOOP = BIT(3),
110 BAT_CURRENT_LOOP = BIT(2),
111 INPUT_CURRENT_LOOP = BIT(1),
112 INPUT_VOLTAGE_LOOP = BIT(0),
113 CHG_ALL_LOOPS = VDD_LOOP | BAT_CURRENT_LOOP
114 | INPUT_CURRENT_LOOP | INPUT_VOLTAGE_LOOP,
115};
116
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117enum pmic_chg_interrupts {
118 USBIN_VALID_IRQ = 0,
119 USBIN_OV_IRQ,
120 BATT_INSERTED_IRQ,
121 VBATDET_LOW_IRQ,
122 USBIN_UV_IRQ,
123 VBAT_OV_IRQ,
124 CHGWDOG_IRQ,
125 VCP_IRQ,
126 ATCDONE_IRQ,
127 ATCFAIL_IRQ,
128 CHGDONE_IRQ,
129 CHGFAIL_IRQ,
130 CHGSTATE_IRQ,
131 LOOP_CHANGE_IRQ,
132 FASTCHG_IRQ,
133 TRKLCHG_IRQ,
134 BATT_REMOVED_IRQ,
135 BATTTEMP_HOT_IRQ,
136 CHGHOT_IRQ,
137 BATTTEMP_COLD_IRQ,
138 CHG_GONE_IRQ,
139 BAT_TEMP_OK_IRQ,
140 COARSE_DET_LOW_IRQ,
141 VDD_LOOP_IRQ,
142 VREG_OV_IRQ,
143 VBATDET_IRQ,
144 BATFET_IRQ,
145 PSI_IRQ,
146 DCIN_VALID_IRQ,
147 DCIN_OV_IRQ,
148 DCIN_UV_IRQ,
149 PM_CHG_MAX_INTS,
150};
151
152struct bms_notify {
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700153 int is_battery_full;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154 int is_charging;
155 struct work_struct work;
156};
157
158/**
159 * struct pm8921_chg_chip -device information
160 * @dev: device pointer to access the parent
161 * @is_usb_path_used: indicates whether USB charging is used at all
162 * @is_usb_path_used: indicates whether DC charging is used at all
163 * @usb_present: present status of usb
164 * @dc_present: present status of dc
165 * @usb_charger_current: usb current to charge the battery with used when
166 * the usb path is enabled or charging is resumed
167 * @safety_time: max time for which charging will happen
168 * @update_time: how frequently the userland needs to be updated
169 * @max_voltage: the max volts the batt should be charged up to
170 * @min_voltage: the min battery voltage before turning the FETon
171 * @resume_voltage: the voltage at which the battery should resume
172 * charging
173 * @term_current: The charging based term current
174 *
175 */
176struct pm8921_chg_chip {
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700177 struct device *dev;
178 unsigned int usb_present;
179 unsigned int dc_present;
180 unsigned int usb_charger_current;
181 unsigned int max_bat_chg_current;
182 unsigned int pmic_chg_irq[PM_CHG_MAX_INTS];
183 unsigned int safety_time;
184 unsigned int ttrkl_time;
185 unsigned int update_time;
186 unsigned int max_voltage;
187 unsigned int min_voltage;
188 unsigned int cool_temp;
189 unsigned int warm_temp;
190 unsigned int temp_check_period;
191 unsigned int cool_bat_chg_current;
192 unsigned int warm_bat_chg_current;
193 unsigned int cool_bat_voltage;
194 unsigned int warm_bat_voltage;
195 unsigned int resume_voltage;
196 unsigned int term_current;
197 unsigned int vbat_channel;
198 unsigned int batt_temp_channel;
199 unsigned int batt_id_channel;
200 struct power_supply usb_psy;
201 struct power_supply dc_psy;
202 struct power_supply batt_psy;
203 struct dentry *dent;
204 struct bms_notify bms_notify;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700205 DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700206 struct work_struct battery_id_valid_work;
207 int64_t batt_id_min;
208 int64_t batt_id_max;
209 int trkl_voltage;
210 int weak_voltage;
211 int trkl_current;
212 int weak_current;
213 int vin_min;
214 int *thermal_mitigation;
215 int thermal_levels;
216 struct delayed_work update_heartbeat_work;
217 struct delayed_work eoc_work;
218 struct wake_lock eoc_wake_lock;
219 enum pm8921_chg_cold_thr cold_thr;
220 enum pm8921_chg_hot_thr hot_thr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221};
222
223static int charging_disabled;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -0700224static int thermal_mitigation;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225
226static struct pm8921_chg_chip *the_chip;
227
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -0700228static struct pm8921_adc_arb_btm_param btm_config;
229
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700230static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr,
231 u8 mask, u8 val)
232{
233 int rc;
234 u8 reg;
235
236 rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
237 if (rc) {
238 pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n", addr, rc);
239 return rc;
240 }
241 reg &= ~mask;
242 reg |= val & mask;
243 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
244 if (rc) {
245 pr_err("pm8xxx_writeb failed: addr=%03X, rc=%d\n", addr, rc);
246 return rc;
247 }
248 return 0;
249}
250
251#define CAPTURE_FSM_STATE_CMD 0xC2
252#define READ_BANK_7 0x70
253#define READ_BANK_4 0x40
254static int pm_chg_get_fsm_state(struct pm8921_chg_chip *chip)
255{
256 u8 temp;
257 int err, ret = 0;
258
259 temp = CAPTURE_FSM_STATE_CMD;
260 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
261 if (err) {
262 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
263 return err;
264 }
265
266 temp = READ_BANK_7;
267 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
268 if (err) {
269 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
270 return err;
271 }
272
273 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
274 if (err) {
275 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
276 return err;
277 }
278 /* get the lower 4 bits */
279 ret = temp & 0xF;
280
281 temp = READ_BANK_4;
282 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
283 if (err) {
284 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
285 return err;
286 }
287
288 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
289 if (err) {
290 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
291 return err;
292 }
293 /* get the upper 1 bit */
294 ret |= (temp & 0x1) << 4;
295 return ret;
296}
297
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700298#define READ_BANK_6 0x60
299static int pm_chg_get_regulation_loop(struct pm8921_chg_chip *chip)
300{
301 u8 temp;
302 int err;
303
304 temp = READ_BANK_6;
305 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
306 if (err) {
307 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
308 return err;
309 }
310
311 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
312 if (err) {
313 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
314 return err;
315 }
316
317 /* return the lower 4 bits */
318 return temp & CHG_ALL_LOOPS;
319}
320
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321#define CHG_USB_SUSPEND_BIT BIT(2)
322static int pm_chg_usb_suspend_enable(struct pm8921_chg_chip *chip, int enable)
323{
324 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_USB_SUSPEND_BIT,
325 enable ? CHG_USB_SUSPEND_BIT : 0);
326}
327
328#define CHG_EN_BIT BIT(7)
329static int pm_chg_auto_enable(struct pm8921_chg_chip *chip, int enable)
330{
331 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_EN_BIT,
332 enable ? CHG_EN_BIT : 0);
333}
334
335#define CHG_CHARGE_DIS_BIT BIT(1)
336static int pm_chg_charge_dis(struct pm8921_chg_chip *chip, int disable)
337{
338 return pm_chg_masked_write(chip, CHG_CNTRL, CHG_CHARGE_DIS_BIT,
339 disable ? CHG_CHARGE_DIS_BIT : 0);
340}
341
342#define PM8921_CHG_V_MIN_MV 3240
343#define PM8921_CHG_V_STEP_MV 20
344#define PM8921_CHG_VDDMAX_MAX 4500
345#define PM8921_CHG_VDDMAX_MIN 3400
346#define PM8921_CHG_V_MASK 0x7F
347static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
348{
349 u8 temp;
350
351 if (voltage < PM8921_CHG_VDDMAX_MIN
352 || voltage > PM8921_CHG_VDDMAX_MAX) {
353 pr_err("bad mV=%d asked to set\n", voltage);
354 return -EINVAL;
355 }
356 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
357 pr_debug("voltage=%d setting %02x\n", voltage, temp);
358 return pm_chg_masked_write(chip, CHG_VDD_MAX, PM8921_CHG_V_MASK, temp);
359}
360
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700361static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
362{
363 u8 temp;
364 int rc;
365
366 rc = pm8xxx_readb(chip->dev->parent, CHG_VDD_MAX, &temp);
367 if (rc) {
368 pr_err("rc = %d while reading vdd max\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700369 *voltage = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700370 return rc;
371 }
372 temp &= PM8921_CHG_V_MASK;
373 *voltage = (int)temp * PM8921_CHG_V_STEP_MV + PM8921_CHG_V_MIN_MV;
374 return 0;
375}
376
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377#define PM8921_CHG_VDDSAFE_MIN 3400
378#define PM8921_CHG_VDDSAFE_MAX 4500
379static int pm_chg_vddsafe_set(struct pm8921_chg_chip *chip, int voltage)
380{
381 u8 temp;
382
383 if (voltage < PM8921_CHG_VDDSAFE_MIN
384 || voltage > PM8921_CHG_VDDSAFE_MAX) {
385 pr_err("bad mV=%d asked to set\n", voltage);
386 return -EINVAL;
387 }
388 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
389 pr_debug("voltage=%d setting %02x\n", voltage, temp);
390 return pm_chg_masked_write(chip, CHG_VDD_SAFE, PM8921_CHG_V_MASK, temp);
391}
392
393#define PM8921_CHG_VBATDET_MIN 3240
394#define PM8921_CHG_VBATDET_MAX 5780
395static int pm_chg_vbatdet_set(struct pm8921_chg_chip *chip, int voltage)
396{
397 u8 temp;
398
399 if (voltage < PM8921_CHG_VBATDET_MIN
400 || voltage > PM8921_CHG_VBATDET_MAX) {
401 pr_err("bad mV=%d asked to set\n", voltage);
402 return -EINVAL;
403 }
404 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
405 pr_debug("voltage=%d setting %02x\n", voltage, temp);
406 return pm_chg_masked_write(chip, CHG_VBAT_DET, PM8921_CHG_V_MASK, temp);
407}
408
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -0700409#define PM8921_CHG_VINMIN_MIN_MV 3800
410#define PM8921_CHG_VINMIN_STEP_MV 100
411#define PM8921_CHG_VINMIN_USABLE_MAX 6500
412#define PM8921_CHG_VINMIN_USABLE_MIN 4300
413#define PM8921_CHG_VINMIN_MASK 0x1F
414static int pm_chg_vinmin_set(struct pm8921_chg_chip *chip, int voltage)
415{
416 u8 temp;
417
418 if (voltage < PM8921_CHG_VINMIN_USABLE_MIN
419 || voltage > PM8921_CHG_VINMIN_USABLE_MAX) {
420 pr_err("bad mV=%d asked to set\n", voltage);
421 return -EINVAL;
422 }
423 temp = (voltage - PM8921_CHG_VINMIN_MIN_MV) / PM8921_CHG_VINMIN_STEP_MV;
424 pr_debug("voltage=%d setting %02x\n", voltage, temp);
425 return pm_chg_masked_write(chip, CHG_VIN_MIN, PM8921_CHG_VINMIN_MASK,
426 temp);
427}
428
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429#define PM8921_CHG_IBATMAX_MIN 325
430#define PM8921_CHG_IBATMAX_MAX 2000
431#define PM8921_CHG_I_MIN_MA 225
432#define PM8921_CHG_I_STEP_MA 50
433#define PM8921_CHG_I_MASK 0x3F
434static int pm_chg_ibatmax_set(struct pm8921_chg_chip *chip, int chg_current)
435{
436 u8 temp;
437
438 if (chg_current < PM8921_CHG_IBATMAX_MIN
439 || chg_current > PM8921_CHG_IBATMAX_MAX) {
440 pr_err("bad mA=%d asked to set\n", chg_current);
441 return -EINVAL;
442 }
443 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
444 return pm_chg_masked_write(chip, CHG_IBAT_MAX, PM8921_CHG_I_MASK, temp);
445}
446
447#define PM8921_CHG_IBATSAFE_MIN 225
448#define PM8921_CHG_IBATSAFE_MAX 3375
449static int pm_chg_ibatsafe_set(struct pm8921_chg_chip *chip, int chg_current)
450{
451 u8 temp;
452
453 if (chg_current < PM8921_CHG_IBATSAFE_MIN
454 || chg_current > PM8921_CHG_IBATSAFE_MAX) {
455 pr_err("bad mA=%d asked to set\n", chg_current);
456 return -EINVAL;
457 }
458 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
459 return pm_chg_masked_write(chip, CHG_IBAT_SAFE,
460 PM8921_CHG_I_MASK, temp);
461}
462
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700463#define PM8921_CHG_ITERM_MIN_MA 50
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700464#define PM8921_CHG_ITERM_MAX_MA 200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700465#define PM8921_CHG_ITERM_STEP_MA 10
466#define PM8921_CHG_ITERM_MASK 0xF
467static int pm_chg_iterm_set(struct pm8921_chg_chip *chip, int chg_current)
468{
469 u8 temp;
470
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700471 if (chg_current < PM8921_CHG_ITERM_MIN_MA
472 || chg_current > PM8921_CHG_ITERM_MAX_MA) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700473 pr_err("bad mA=%d asked to set\n", chg_current);
474 return -EINVAL;
475 }
476
477 temp = (chg_current - PM8921_CHG_ITERM_MIN_MA)
478 / PM8921_CHG_ITERM_STEP_MA;
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700479 return pm_chg_masked_write(chip, CHG_ITERM, PM8921_CHG_ITERM_MASK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700480 temp);
481}
482
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700483static int pm_chg_iterm_get(struct pm8921_chg_chip *chip, int *chg_current)
484{
485 u8 temp;
486 int rc;
487
488 rc = pm8xxx_readb(chip->dev->parent, CHG_ITERM, &temp);
489 if (rc) {
490 pr_err("err=%d reading CHG_ITEM\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700491 *chg_current = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700492 return rc;
493 }
494 temp &= PM8921_CHG_ITERM_MASK;
495 *chg_current = (int)temp * PM8921_CHG_ITERM_STEP_MA
496 + PM8921_CHG_ITERM_MIN_MA;
497 return 0;
498}
499
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500#define PM8921_CHG_IUSB_MASK 0x1C
501#define PM8921_CHG_IUSB_MAX 7
502#define PM8921_CHG_IUSB_MIN 0
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700503static int pm_chg_iusbmax_set(struct pm8921_chg_chip *chip, int reg_val)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700504{
505 u8 temp;
506
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700507 if (reg_val < PM8921_CHG_IUSB_MIN || reg_val > PM8921_CHG_IUSB_MAX) {
508 pr_err("bad mA=%d asked to set\n", reg_val);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509 return -EINVAL;
510 }
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700511 temp = reg_val << 2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700512 return pm_chg_masked_write(chip, PBL_ACCESS2, PM8921_CHG_IUSB_MASK,
513 temp);
514}
515
516#define PM8921_CHG_WD_MASK 0x1F
517static int pm_chg_disable_wd(struct pm8921_chg_chip *chip)
518{
519 /* writing 0 to the wd timer disables it */
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700520 return pm_chg_masked_write(chip, CHG_TWDOG, PM8921_CHG_WD_MASK, 0);
521}
522
523#define PM8921_CHG_TCHG_MASK 0x3F
524#define PM8921_CHG_TCHG_MIN 4
525#define PM8921_CHG_TCHG_MAX 512
526#define PM8921_CHG_TCHG_STEP 4
527static int pm_chg_tchg_max_set(struct pm8921_chg_chip *chip, int minutes)
528{
529 u8 temp;
530
531 if (minutes < PM8921_CHG_TCHG_MIN || minutes > PM8921_CHG_TCHG_MAX) {
532 pr_err("bad max minutes =%d asked to set\n", minutes);
533 return -EINVAL;
534 }
535
536 temp = (minutes - 1)/PM8921_CHG_TCHG_STEP;
537 return pm_chg_masked_write(chip, CHG_TCHG_MAX, PM8921_CHG_TCHG_MASK,
538 temp);
539}
540
541#define PM8921_CHG_TTRKL_MASK 0x1F
542#define PM8921_CHG_TTRKL_MIN 1
543#define PM8921_CHG_TTRKL_MAX 64
544static int pm_chg_ttrkl_max_set(struct pm8921_chg_chip *chip, int minutes)
545{
546 u8 temp;
547
548 if (minutes < PM8921_CHG_TTRKL_MIN || minutes > PM8921_CHG_TTRKL_MAX) {
549 pr_err("bad max minutes =%d asked to set\n", minutes);
550 return -EINVAL;
551 }
552
553 temp = minutes - 1;
554 return pm_chg_masked_write(chip, CHG_TTRKL_MAX, PM8921_CHG_TTRKL_MASK,
555 temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700556}
557
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -0700558#define PM8921_CHG_VTRKL_MIN_MV 2050
559#define PM8921_CHG_VTRKL_MAX_MV 2800
560#define PM8921_CHG_VTRKL_STEP_MV 50
561#define PM8921_CHG_VTRKL_SHIFT 4
562#define PM8921_CHG_VTRKL_MASK 0xF0
563static int pm_chg_vtrkl_low_set(struct pm8921_chg_chip *chip, int millivolts)
564{
565 u8 temp;
566
567 if (millivolts < PM8921_CHG_VTRKL_MIN_MV
568 || millivolts > PM8921_CHG_VTRKL_MAX_MV) {
569 pr_err("bad voltage = %dmV asked to set\n", millivolts);
570 return -EINVAL;
571 }
572
573 temp = (millivolts - PM8921_CHG_VTRKL_MIN_MV)/PM8921_CHG_VTRKL_STEP_MV;
574 temp = temp << PM8921_CHG_VTRKL_SHIFT;
575 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VTRKL_MASK,
576 temp);
577}
578
579#define PM8921_CHG_VWEAK_MIN_MV 2100
580#define PM8921_CHG_VWEAK_MAX_MV 3600
581#define PM8921_CHG_VWEAK_STEP_MV 100
582#define PM8921_CHG_VWEAK_MASK 0x0F
583static int pm_chg_vweak_set(struct pm8921_chg_chip *chip, int millivolts)
584{
585 u8 temp;
586
587 if (millivolts < PM8921_CHG_VWEAK_MIN_MV
588 || millivolts > PM8921_CHG_VWEAK_MAX_MV) {
589 pr_err("bad voltage = %dmV asked to set\n", millivolts);
590 return -EINVAL;
591 }
592
593 temp = (millivolts - PM8921_CHG_VWEAK_MIN_MV)/PM8921_CHG_VWEAK_STEP_MV;
594 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VWEAK_MASK,
595 temp);
596}
597
598#define PM8921_CHG_ITRKL_MIN_MA 50
599#define PM8921_CHG_ITRKL_MAX_MA 200
600#define PM8921_CHG_ITRKL_MASK 0x0F
601#define PM8921_CHG_ITRKL_STEP_MA 10
602static int pm_chg_itrkl_set(struct pm8921_chg_chip *chip, int milliamps)
603{
604 u8 temp;
605
606 if (milliamps < PM8921_CHG_ITRKL_MIN_MA
607 || milliamps > PM8921_CHG_ITRKL_MAX_MA) {
608 pr_err("bad current = %dmA asked to set\n", milliamps);
609 return -EINVAL;
610 }
611
612 temp = (milliamps - PM8921_CHG_ITRKL_MIN_MA)/PM8921_CHG_ITRKL_STEP_MA;
613
614 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_ITRKL_MASK,
615 temp);
616}
617
618#define PM8921_CHG_IWEAK_MIN_MA 325
619#define PM8921_CHG_IWEAK_MAX_MA 525
620#define PM8921_CHG_IWEAK_SHIFT 7
621#define PM8921_CHG_IWEAK_MASK 0x80
622static int pm_chg_iweak_set(struct pm8921_chg_chip *chip, int milliamps)
623{
624 u8 temp;
625
626 if (milliamps < PM8921_CHG_IWEAK_MIN_MA
627 || milliamps > PM8921_CHG_IWEAK_MAX_MA) {
628 pr_err("bad current = %dmA asked to set\n", milliamps);
629 return -EINVAL;
630 }
631
632 if (milliamps < PM8921_CHG_IWEAK_MAX_MA)
633 temp = 0;
634 else
635 temp = 1;
636
637 temp = temp << PM8921_CHG_IWEAK_SHIFT;
638 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_IWEAK_MASK,
639 temp);
640}
641
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700642#define PM8921_CHG_BATT_TEMP_THR_COLD BIT(1)
643#define PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT 1
644static int pm_chg_batt_cold_temp_config(struct pm8921_chg_chip *chip,
645 enum pm8921_chg_cold_thr cold_thr)
646{
647 u8 temp;
648
649 temp = cold_thr << PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT;
650 temp = temp & PM8921_CHG_BATT_TEMP_THR_COLD;
651 return pm_chg_masked_write(chip, CHG_CNTRL_2,
652 PM8921_CHG_BATT_TEMP_THR_COLD,
653 temp);
654}
655
656#define PM8921_CHG_BATT_TEMP_THR_HOT BIT(0)
657#define PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT 0
658static int pm_chg_batt_hot_temp_config(struct pm8921_chg_chip *chip,
659 enum pm8921_chg_hot_thr hot_thr)
660{
661 u8 temp;
662
663 temp = hot_thr << PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT;
664 temp = temp & PM8921_CHG_BATT_TEMP_THR_HOT;
665 return pm_chg_masked_write(chip, CHG_CNTRL_2,
666 PM8921_CHG_BATT_TEMP_THR_HOT,
667 temp);
668}
669
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -0700670static int64_t read_battery_id(struct pm8921_chg_chip *chip)
671{
672 int rc;
673 struct pm8921_adc_chan_result result;
674
675 rc = pm8921_adc_read(chip->batt_id_channel, &result);
676 if (rc) {
677 pr_err("error reading batt id channel = %d, rc = %d\n",
678 chip->vbat_channel, rc);
679 return rc;
680 }
681 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
682 result.measurement);
683 return result.physical;
684}
685
686static int is_battery_valid(struct pm8921_chg_chip *chip)
687{
688 int64_t rc;
689
690 if (chip->batt_id_min == 0 && chip->batt_id_max == 0)
691 return 1;
692
693 rc = read_battery_id(chip);
694 if (rc < 0) {
695 pr_err("error reading batt id channel = %d, rc = %lld\n",
696 chip->vbat_channel, rc);
697 /* assume battery id is valid when adc error happens */
698 return 1;
699 }
700
701 if (rc < chip->batt_id_min || rc > chip->batt_id_max) {
702 pr_err("batt_id phy =%lld is not valid\n", rc);
703 return 0;
704 }
705 return 1;
706}
707
708static void check_battery_valid(struct pm8921_chg_chip *chip)
709{
710 if (is_battery_valid(chip) == 0) {
711 pr_err("batt_id not valid, disbling charging\n");
712 pm_chg_auto_enable(chip, 0);
713 } else {
714 pm_chg_auto_enable(chip, !charging_disabled);
715 }
716}
717
718static void battery_id_valid(struct work_struct *work)
719{
720 struct pm8921_chg_chip *chip = container_of(work,
721 struct pm8921_chg_chip, battery_id_valid_work);
722
723 check_battery_valid(chip);
724}
725
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726static void pm8921_chg_enable_irq(struct pm8921_chg_chip *chip, int interrupt)
727{
728 if (!__test_and_set_bit(interrupt, chip->enabled_irqs)) {
729 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
730 enable_irq(chip->pmic_chg_irq[interrupt]);
731 }
732}
733
734static void pm8921_chg_disable_irq(struct pm8921_chg_chip *chip, int interrupt)
735{
736 if (__test_and_clear_bit(interrupt, chip->enabled_irqs)) {
737 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
738 disable_irq_nosync(chip->pmic_chg_irq[interrupt]);
739 }
740}
741
742static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
743{
744 return pm8xxx_read_irq_stat(chip->dev->parent,
745 chip->pmic_chg_irq[irq_id]);
746}
747
748/* Treat OverVoltage/UnderVoltage as source missing */
749static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
750{
751 int pres, ov, uv;
752
753 pres = pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
754 ov = pm_chg_get_rt_status(chip, USBIN_OV_IRQ);
755 uv = pm_chg_get_rt_status(chip, USBIN_UV_IRQ);
756
757 return pres && !ov && !uv;
758}
759
760/* Treat OverVoltage/UnderVoltage as source missing */
761static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
762{
763 int pres, ov, uv;
764
765 pres = pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
766 ov = pm_chg_get_rt_status(chip, DCIN_OV_IRQ);
767 uv = pm_chg_get_rt_status(chip, DCIN_UV_IRQ);
768
769 return pres && !ov && !uv;
770}
771
772static int is_battery_charging(int fsm_state)
773{
774 switch (fsm_state) {
775 case FSM_STATE_ATC_2A:
776 case FSM_STATE_ATC_2B:
777 case FSM_STATE_ON_CHG_AND_BAT_6:
778 case FSM_STATE_FAST_CHG_7:
779 case FSM_STATE_TRKL_CHG_8:
780 return 1;
781 }
782 return 0;
783}
784
785static void bms_notify(struct work_struct *work)
786{
787 struct bms_notify *n = container_of(work, struct bms_notify, work);
788
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700789 if (n->is_charging) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790 pm8921_bms_charging_began();
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700791 } else {
792 pm8921_bms_charging_end(n->is_battery_full);
793 n->is_battery_full = 0;
794 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700795}
796
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -0700797static void bms_notify_check(struct pm8921_chg_chip *chip)
798{
799 int fsm_state, new_is_charging;
800
801 fsm_state = pm_chg_get_fsm_state(chip);
802 new_is_charging = is_battery_charging(fsm_state);
803
804 if (chip->bms_notify.is_charging ^ new_is_charging) {
805 chip->bms_notify.is_charging = new_is_charging;
806 schedule_work(&(chip->bms_notify.work));
807 }
808}
809
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810static enum power_supply_property pm_power_props[] = {
811 POWER_SUPPLY_PROP_PRESENT,
Willie Ruan9ad6d832011-08-19 11:58:42 -0700812 POWER_SUPPLY_PROP_ONLINE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813};
814
815static char *pm_power_supplied_to[] = {
816 "battery",
817};
818
819static int pm_power_get_property(struct power_supply *psy,
820 enum power_supply_property psp,
821 union power_supply_propval *val)
822{
823 struct pm8921_chg_chip *chip;
824
825 switch (psp) {
826 case POWER_SUPPLY_PROP_PRESENT:
Willie Ruan9ad6d832011-08-19 11:58:42 -0700827 case POWER_SUPPLY_PROP_ONLINE:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828 if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
829 chip = container_of(psy, struct pm8921_chg_chip,
830 dc_psy);
831 val->intval = is_dc_chg_plugged_in(chip);
832 }
833 if (psy->type == POWER_SUPPLY_TYPE_USB) {
834 chip = container_of(psy, struct pm8921_chg_chip,
835 usb_psy);
836 val->intval = is_usb_chg_plugged_in(chip);
837 }
838 break;
839 default:
840 return -EINVAL;
841 }
842 return 0;
843}
844
845static enum power_supply_property msm_batt_power_props[] = {
846 POWER_SUPPLY_PROP_STATUS,
847 POWER_SUPPLY_PROP_CHARGE_TYPE,
848 POWER_SUPPLY_PROP_HEALTH,
849 POWER_SUPPLY_PROP_PRESENT,
850 POWER_SUPPLY_PROP_TECHNOLOGY,
851 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
852 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
853 POWER_SUPPLY_PROP_VOLTAGE_NOW,
854 POWER_SUPPLY_PROP_CAPACITY,
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -0700855 POWER_SUPPLY_PROP_CURRENT_NOW,
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700856 POWER_SUPPLY_PROP_TEMP,
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -0700857 POWER_SUPPLY_PROP_ENERGY_FULL,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700858};
859
860static int get_prop_battery_mvolts(struct pm8921_chg_chip *chip)
861{
862 int rc;
863 struct pm8921_adc_chan_result result;
864
865 rc = pm8921_adc_read(chip->vbat_channel, &result);
866 if (rc) {
867 pr_err("error reading adc channel = %d, rc = %d\n",
868 chip->vbat_channel, rc);
869 return rc;
870 }
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -0700871 pr_debug("mvolts phy = %lld meas = 0x%llx\n", result.physical,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872 result.measurement);
873 return (int)result.physical;
874}
875
876static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
877{
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -0700878 int percent_soc = pm8921_bms_get_percent_charge();
879
880 if (percent_soc <= 10)
881 pr_warn("low battery charge = %d%%\n", percent_soc);
882
883 return percent_soc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700884}
885
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -0700886static int get_prop_batt_current(struct pm8921_chg_chip *chip)
887{
888 int result_ma, rc;
889
890 rc = pm8921_bms_get_battery_current(&result_ma);
891 if (rc) {
892 pr_err("unable to get batt current rc = %d\n", rc);
893 return rc;
894 } else {
895 return result_ma;
896 }
897}
898
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -0700899static int get_prop_batt_fcc(struct pm8921_chg_chip *chip)
900{
901 int rc;
902
903 rc = pm8921_bms_get_fcc();
904 if (rc < 0)
905 pr_err("unable to get batt fcc rc = %d\n", rc);
906 return rc;
907}
908
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700909static int get_prop_batt_health(struct pm8921_chg_chip *chip)
910{
911 int temp;
912
913 temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
914 if (temp)
915 return POWER_SUPPLY_HEALTH_OVERHEAT;
916
917 temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
918 if (temp)
919 return POWER_SUPPLY_HEALTH_COLD;
920
921 return POWER_SUPPLY_HEALTH_GOOD;
922}
923
924static int get_prop_batt_present(struct pm8921_chg_chip *chip)
925{
926 return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
927}
928
929static int get_prop_charge_type(struct pm8921_chg_chip *chip)
930{
931 int temp;
932
933 temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
934 if (temp)
935 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
936
937 temp = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
938 if (temp)
939 return POWER_SUPPLY_CHARGE_TYPE_FAST;
940
941 return POWER_SUPPLY_CHARGE_TYPE_NONE;
942}
943
944static int get_prop_batt_status(struct pm8921_chg_chip *chip)
945{
946 int temp = 0;
947
948 /* TODO reading the FSM state is more reliable */
949 temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
950
951 temp |= pm_chg_get_rt_status(chip, FASTCHG_IRQ);
952 if (temp)
953 return POWER_SUPPLY_STATUS_CHARGING;
954 /*
955 * The battery is not charging
956 * check the FET - if on battery is discharging
957 * - if off battery is isolated(full) and the system
958 * is being driven from a charger
959 */
960 temp = pm_chg_get_rt_status(chip, BATFET_IRQ);
961 if (temp)
962 return POWER_SUPPLY_STATUS_DISCHARGING;
963
964 return POWER_SUPPLY_STATUS_FULL;
965}
966
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700967static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
968{
969 int rc;
970 struct pm8921_adc_chan_result result;
971
972 rc = pm8921_adc_read(chip->batt_temp_channel, &result);
973 if (rc) {
974 pr_err("error reading adc channel = %d, rc = %d\n",
975 chip->vbat_channel, rc);
976 return rc;
977 }
978 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
979 result.measurement);
980 return (int)result.physical;
981}
982
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700983static int pm_batt_power_get_property(struct power_supply *psy,
984 enum power_supply_property psp,
985 union power_supply_propval *val)
986{
987 struct pm8921_chg_chip *chip = container_of(psy, struct pm8921_chg_chip,
988 batt_psy);
989
990 switch (psp) {
991 case POWER_SUPPLY_PROP_STATUS:
992 val->intval = get_prop_batt_status(chip);
993 break;
994 case POWER_SUPPLY_PROP_CHARGE_TYPE:
995 val->intval = get_prop_charge_type(chip);
996 break;
997 case POWER_SUPPLY_PROP_HEALTH:
998 val->intval = get_prop_batt_health(chip);
999 break;
1000 case POWER_SUPPLY_PROP_PRESENT:
1001 val->intval = get_prop_batt_present(chip);
1002 break;
1003 case POWER_SUPPLY_PROP_TECHNOLOGY:
1004 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1005 break;
1006 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1007 val->intval = chip->max_voltage;
1008 break;
1009 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
1010 val->intval = chip->min_voltage;
1011 break;
1012 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1013 val->intval = get_prop_battery_mvolts(chip);
1014 break;
1015 case POWER_SUPPLY_PROP_CAPACITY:
1016 val->intval = get_prop_batt_capacity(chip);
1017 break;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001018 case POWER_SUPPLY_PROP_CURRENT_NOW:
1019 val->intval = get_prop_batt_current(chip);
1020 break;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001021 case POWER_SUPPLY_PROP_TEMP:
1022 val->intval = get_prop_batt_temp(chip);
1023 break;
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001024 case POWER_SUPPLY_PROP_ENERGY_FULL:
1025 val->intval = get_prop_batt_fcc(chip);
1026 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001027 default:
1028 return -EINVAL;
1029 }
1030
1031 return 0;
1032}
1033
1034static void (*notify_vbus_state_func_ptr)(int);
1035static int usb_chg_current;
1036static DEFINE_SPINLOCK(vbus_lock);
1037
1038int pm8921_charger_register_vbus_sn(void (*callback)(int))
1039{
1040 pr_debug("%p\n", callback);
1041 notify_vbus_state_func_ptr = callback;
1042 return 0;
1043}
1044EXPORT_SYMBOL_GPL(pm8921_charger_register_vbus_sn);
1045
1046/* this is passed to the hsusb via platform_data msm_otg_pdata */
1047void pm8921_charger_unregister_vbus_sn(void (*callback)(int))
1048{
1049 pr_debug("%p\n", callback);
1050 notify_vbus_state_func_ptr = NULL;
1051}
1052EXPORT_SYMBOL_GPL(pm8921_charger_unregister_vbus_sn);
1053
1054static void notify_usb_of_the_plugin_event(int plugin)
1055{
1056 plugin = !!plugin;
1057 if (notify_vbus_state_func_ptr) {
1058 pr_debug("notifying plugin\n");
1059 (*notify_vbus_state_func_ptr) (plugin);
1060 } else {
1061 pr_debug("unable to notify plugin\n");
1062 }
1063}
1064
1065struct usb_ma_limit_entry {
1066 int usb_ma;
1067 u8 chg_iusb_value;
1068};
1069
1070static struct usb_ma_limit_entry usb_ma_table[] = {
1071 {100, 0},
1072 {500, 1},
1073 {700, 2},
1074 {850, 3},
1075 {900, 4},
1076 {1100, 5},
1077 {1300, 6},
1078 {1500, 7},
1079};
1080
1081/* assumes vbus_lock is held */
1082static void __pm8921_charger_vbus_draw(unsigned int mA)
1083{
1084 int i, rc;
1085
1086 if (mA > 0 && mA <= 2) {
1087 usb_chg_current = 0;
1088 rc = pm_chg_iusbmax_set(the_chip,
1089 usb_ma_table[0].chg_iusb_value);
1090 if (rc) {
1091 pr_err("unable to set iusb to %d rc = %d\n",
1092 usb_ma_table[0].chg_iusb_value, rc);
1093 }
1094 rc = pm_chg_usb_suspend_enable(the_chip, 1);
1095 if (rc)
1096 pr_err("fail to set suspend bit rc=%d\n", rc);
1097 } else {
1098 rc = pm_chg_usb_suspend_enable(the_chip, 0);
1099 if (rc)
1100 pr_err("fail to reset suspend bit rc=%d\n", rc);
1101 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
1102 if (usb_ma_table[i].usb_ma <= mA)
1103 break;
1104 }
1105 if (i < 0)
1106 i = 0;
1107 rc = pm_chg_iusbmax_set(the_chip,
1108 usb_ma_table[i].chg_iusb_value);
1109 if (rc) {
1110 pr_err("unable to set iusb to %d rc = %d\n",
1111 usb_ma_table[i].chg_iusb_value, rc);
1112 }
1113 }
1114}
1115
1116/* USB calls these to tell us how much max usb current the system can draw */
1117void pm8921_charger_vbus_draw(unsigned int mA)
1118{
1119 unsigned long flags;
1120
1121 pr_debug("Enter charge=%d\n", mA);
1122 spin_lock_irqsave(&vbus_lock, flags);
1123 if (the_chip) {
1124 __pm8921_charger_vbus_draw(mA);
1125 } else {
1126 /*
1127 * called before pmic initialized,
1128 * save this value and use it at probe
1129 */
1130 usb_chg_current = mA;
1131 }
1132 spin_unlock_irqrestore(&vbus_lock, flags);
1133}
1134EXPORT_SYMBOL_GPL(pm8921_charger_vbus_draw);
1135
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07001136int pm8921_charger_enable(bool enable)
1137{
1138 int rc;
1139
1140 if (!the_chip) {
1141 pr_err("called before init\n");
1142 return -EINVAL;
1143 }
1144 enable = !!enable;
1145 rc = pm_chg_auto_enable(the_chip, enable);
1146 if (rc)
1147 pr_err("Failed rc=%d\n", rc);
1148 return rc;
1149}
1150EXPORT_SYMBOL(pm8921_charger_enable);
1151
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001152int pm8921_is_usb_chg_plugged_in(void)
1153{
1154 if (!the_chip) {
1155 pr_err("called before init\n");
1156 return -EINVAL;
1157 }
1158 return is_usb_chg_plugged_in(the_chip);
1159}
1160EXPORT_SYMBOL(pm8921_is_usb_chg_plugged_in);
1161
1162int pm8921_is_dc_chg_plugged_in(void)
1163{
1164 if (!the_chip) {
1165 pr_err("called before init\n");
1166 return -EINVAL;
1167 }
1168 return is_dc_chg_plugged_in(the_chip);
1169}
1170EXPORT_SYMBOL(pm8921_is_dc_chg_plugged_in);
1171
1172int pm8921_is_battery_present(void)
1173{
1174 if (!the_chip) {
1175 pr_err("called before init\n");
1176 return -EINVAL;
1177 }
1178 return get_prop_batt_present(the_chip);
1179}
1180EXPORT_SYMBOL(pm8921_is_battery_present);
1181
1182int pm8921_set_max_battery_charge_current(int ma)
1183{
1184 if (!the_chip) {
1185 pr_err("called before init\n");
1186 return -EINVAL;
1187 }
1188 return pm_chg_ibatmax_set(the_chip, ma);
1189}
1190EXPORT_SYMBOL(pm8921_set_max_battery_charge_current);
1191
1192int pm8921_disable_source_current(bool disable)
1193{
1194 if (!the_chip) {
1195 pr_err("called before init\n");
1196 return -EINVAL;
1197 }
1198 if (disable)
1199 pr_warn("current drawn from chg=0, battery provides current\n");
1200 return pm_chg_charge_dis(the_chip, disable);
1201}
1202EXPORT_SYMBOL(pm8921_disable_source_current);
1203
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07001204int pm8921_regulate_input_voltage(int voltage)
1205{
1206 if (!the_chip) {
1207 pr_err("called before init\n");
1208 return -EINVAL;
1209 }
1210 return pm_chg_vinmin_set(the_chip, voltage);
1211}
1212
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001213bool pm8921_is_battery_charging(int *source)
1214{
1215 int fsm_state, is_charging, dc_present, usb_present;
1216
1217 if (!the_chip) {
1218 pr_err("called before init\n");
1219 return -EINVAL;
1220 }
1221 fsm_state = pm_chg_get_fsm_state(the_chip);
1222 is_charging = is_battery_charging(fsm_state);
1223 if (is_charging == 0) {
1224 *source = PM8921_CHG_SRC_NONE;
1225 return is_charging;
1226 }
1227
1228 if (source == NULL)
1229 return is_charging;
1230
1231 /* the battery is charging, the source is requested, find it */
1232 dc_present = is_dc_chg_plugged_in(the_chip);
1233 usb_present = is_usb_chg_plugged_in(the_chip);
1234
1235 if (dc_present && !usb_present)
1236 *source = PM8921_CHG_SRC_DC;
1237
1238 if (usb_present && !dc_present)
1239 *source = PM8921_CHG_SRC_USB;
1240
1241 if (usb_present && dc_present)
1242 /*
1243 * The system always chooses dc for charging since it has
1244 * higher priority.
1245 */
1246 *source = PM8921_CHG_SRC_DC;
1247
1248 return is_charging;
1249}
1250EXPORT_SYMBOL(pm8921_is_battery_charging);
1251
1252int pm8921_batt_temperature(void)
1253{
1254 if (!the_chip) {
1255 pr_err("called before init\n");
1256 return -EINVAL;
1257 }
1258 return get_prop_batt_temp(the_chip);
1259}
1260
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001261static void handle_usb_insertion_removal(struct pm8921_chg_chip *chip)
1262{
1263 int usb_present;
1264
1265 usb_present = is_usb_chg_plugged_in(chip);
1266 if (chip->usb_present ^ usb_present) {
1267 notify_usb_of_the_plugin_event(usb_present);
1268 chip->usb_present = usb_present;
1269 power_supply_changed(&chip->usb_psy);
1270 }
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001271 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001272}
1273
1274static void handle_dc_removal_insertion(struct pm8921_chg_chip *chip)
1275{
1276 int dc_present;
1277
1278 dc_present = is_dc_chg_plugged_in(chip);
1279 if (chip->dc_present ^ dc_present) {
1280 chip->dc_present = dc_present;
1281 power_supply_changed(&chip->dc_psy);
1282 }
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001283 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001284}
1285
1286static irqreturn_t usbin_valid_irq_handler(int irq, void *data)
1287{
1288 handle_usb_insertion_removal(data);
1289 return IRQ_HANDLED;
1290}
1291
1292static irqreturn_t usbin_ov_irq_handler(int irq, void *data)
1293{
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -07001294 pr_err("USB OverVoltage\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001295 handle_usb_insertion_removal(data);
1296 return IRQ_HANDLED;
1297}
1298
1299static irqreturn_t batt_inserted_irq_handler(int irq, void *data)
1300{
1301 struct pm8921_chg_chip *chip = data;
1302 int status;
1303
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001304 status = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1305 schedule_work(&chip->battery_id_valid_work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001306 pr_debug("battery present=%d", status);
1307 power_supply_changed(&chip->batt_psy);
1308 return IRQ_HANDLED;
1309}
1310/* this interrupt used to restart charging a battery */
1311static irqreturn_t vbatdet_low_irq_handler(int irq, void *data)
1312{
1313 struct pm8921_chg_chip *chip = data;
1314
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001315 pm8921_chg_disable_irq(chip, VBATDET_LOW_IRQ);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07001316
1317 /* enable auto charging */
1318 pm_chg_auto_enable(chip, !charging_disabled);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001319 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001320
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001321 power_supply_changed(&chip->batt_psy);
1322 power_supply_changed(&chip->usb_psy);
1323 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001324
1325 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001326 return IRQ_HANDLED;
1327}
1328
1329static irqreturn_t usbin_uv_irq_handler(int irq, void *data)
1330{
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -07001331 pr_err("USB UnderVoltage\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001332 handle_usb_insertion_removal(data);
1333 return IRQ_HANDLED;
1334}
1335
1336static irqreturn_t vbat_ov_irq_handler(int irq, void *data)
1337{
1338 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1339 return IRQ_HANDLED;
1340}
1341
1342static irqreturn_t chgwdog_irq_handler(int irq, void *data)
1343{
1344 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1345 return IRQ_HANDLED;
1346}
1347
1348static irqreturn_t vcp_irq_handler(int irq, void *data)
1349{
1350 pr_warning("VCP triggered BATDET forced on\n");
1351 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1352 return IRQ_HANDLED;
1353}
1354
1355static irqreturn_t atcdone_irq_handler(int irq, void *data)
1356{
1357 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1358 return IRQ_HANDLED;
1359}
1360
1361static irqreturn_t atcfail_irq_handler(int irq, void *data)
1362{
1363 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1364 return IRQ_HANDLED;
1365}
1366
1367static irqreturn_t chgdone_irq_handler(int irq, void *data)
1368{
1369 struct pm8921_chg_chip *chip = data;
1370
1371 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1372 power_supply_changed(&chip->batt_psy);
1373 power_supply_changed(&chip->usb_psy);
1374 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001375
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07001376 chip->bms_notify.is_battery_full = 1;
1377 bms_notify_check(chip);
1378
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001379 /*
1380 * since charging is now done, start monitoring for
1381 * battery voltage below resume voltage
1382 */
1383 pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
1384
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001385 return IRQ_HANDLED;
1386}
1387
1388static irqreturn_t chgfail_irq_handler(int irq, void *data)
1389{
1390 struct pm8921_chg_chip *chip = data;
1391
1392 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1393 power_supply_changed(&chip->batt_psy);
1394 power_supply_changed(&chip->usb_psy);
1395 power_supply_changed(&chip->dc_psy);
1396 return IRQ_HANDLED;
1397}
1398
1399static irqreturn_t chgstate_irq_handler(int irq, void *data)
1400{
1401 struct pm8921_chg_chip *chip = data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001402
1403 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1404 power_supply_changed(&chip->batt_psy);
1405 power_supply_changed(&chip->usb_psy);
1406 power_supply_changed(&chip->dc_psy);
1407
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001408 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001409
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001410 return IRQ_HANDLED;
1411}
1412
1413static irqreturn_t loop_change_irq_handler(int irq, void *data)
1414{
1415 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1416 return IRQ_HANDLED;
1417}
1418
1419static irqreturn_t fastchg_irq_handler(int irq, void *data)
1420{
1421 struct pm8921_chg_chip *chip = data;
1422
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001423 /* disable this irq now, reenable it when resuming charging */
1424 pm8921_chg_disable_irq(chip, FASTCHG_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001425 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001426 wake_lock(&chip->eoc_wake_lock);
1427 schedule_delayed_work(&chip->eoc_work,
1428 round_jiffies_relative(msecs_to_jiffies
1429 (EOC_CHECK_PERIOD_MS)));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001430 return IRQ_HANDLED;
1431}
1432
1433static irqreturn_t trklchg_irq_handler(int irq, void *data)
1434{
1435 struct pm8921_chg_chip *chip = data;
1436
1437 power_supply_changed(&chip->batt_psy);
1438 return IRQ_HANDLED;
1439}
1440
1441static irqreturn_t batt_removed_irq_handler(int irq, void *data)
1442{
1443 struct pm8921_chg_chip *chip = data;
1444 int status;
1445
1446 status = pm_chg_get_rt_status(chip, BATT_REMOVED_IRQ);
1447 pr_debug("battery present=%d state=%d", !status,
1448 pm_chg_get_fsm_state(data));
1449 power_supply_changed(&chip->batt_psy);
1450 return IRQ_HANDLED;
1451}
1452
1453static irqreturn_t batttemp_hot_irq_handler(int irq, void *data)
1454{
1455 struct pm8921_chg_chip *chip = data;
1456
1457 power_supply_changed(&chip->batt_psy);
1458 return IRQ_HANDLED;
1459}
1460
1461static irqreturn_t chghot_irq_handler(int irq, void *data)
1462{
1463 struct pm8921_chg_chip *chip = data;
1464
1465 pr_debug("Chg hot fsm_state=%d\n", pm_chg_get_fsm_state(data));
1466 power_supply_changed(&chip->batt_psy);
1467 power_supply_changed(&chip->usb_psy);
1468 power_supply_changed(&chip->dc_psy);
1469 return IRQ_HANDLED;
1470}
1471
1472static irqreturn_t batttemp_cold_irq_handler(int irq, void *data)
1473{
1474 struct pm8921_chg_chip *chip = data;
1475
1476 pr_debug("Batt cold fsm_state=%d\n", pm_chg_get_fsm_state(data));
1477 power_supply_changed(&chip->batt_psy);
1478 power_supply_changed(&chip->usb_psy);
1479 power_supply_changed(&chip->dc_psy);
1480 return IRQ_HANDLED;
1481}
1482
1483static irqreturn_t chg_gone_irq_handler(int irq, void *data)
1484{
1485 struct pm8921_chg_chip *chip = data;
1486
1487 pr_debug("Chg gone fsm_state=%d\n", pm_chg_get_fsm_state(data));
1488 power_supply_changed(&chip->batt_psy);
1489 power_supply_changed(&chip->usb_psy);
1490 power_supply_changed(&chip->dc_psy);
1491 return IRQ_HANDLED;
1492}
1493
1494static irqreturn_t bat_temp_ok_irq_handler(int irq, void *data)
1495{
1496 struct pm8921_chg_chip *chip = data;
1497
1498 pr_debug("batt temp ok fsm_state=%d\n", pm_chg_get_fsm_state(data));
1499 power_supply_changed(&chip->batt_psy);
1500 power_supply_changed(&chip->usb_psy);
1501 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001502 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001503 return IRQ_HANDLED;
1504}
1505
1506static irqreturn_t coarse_det_low_irq_handler(int irq, void *data)
1507{
1508 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1509 return IRQ_HANDLED;
1510}
1511
1512static irqreturn_t vdd_loop_irq_handler(int irq, void *data)
1513{
1514 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1515 return IRQ_HANDLED;
1516}
1517
1518static irqreturn_t vreg_ov_irq_handler(int irq, void *data)
1519{
1520 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1521 return IRQ_HANDLED;
1522}
1523
1524static irqreturn_t vbatdet_irq_handler(int irq, void *data)
1525{
1526 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1527 return IRQ_HANDLED;
1528}
1529
1530static irqreturn_t batfet_irq_handler(int irq, void *data)
1531{
1532 struct pm8921_chg_chip *chip = data;
1533
1534 pr_debug("vreg ov\n");
1535 power_supply_changed(&chip->batt_psy);
1536 return IRQ_HANDLED;
1537}
1538
1539static irqreturn_t dcin_valid_irq_handler(int irq, void *data)
1540{
1541 handle_dc_removal_insertion(data);
1542 return IRQ_HANDLED;
1543}
1544
1545static irqreturn_t dcin_ov_irq_handler(int irq, void *data)
1546{
1547 handle_dc_removal_insertion(data);
1548 return IRQ_HANDLED;
1549}
1550
1551static irqreturn_t dcin_uv_irq_handler(int irq, void *data)
1552{
1553 handle_dc_removal_insertion(data);
1554 return IRQ_HANDLED;
1555}
1556
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07001557/**
1558 * update_heartbeat - internal function to update userspace
1559 * per update_time minutes
1560 *
1561 */
1562static void update_heartbeat(struct work_struct *work)
1563{
1564 struct delayed_work *dwork = to_delayed_work(work);
1565 struct pm8921_chg_chip *chip = container_of(dwork,
1566 struct pm8921_chg_chip, update_heartbeat_work);
1567
1568 power_supply_changed(&chip->batt_psy);
1569 schedule_delayed_work(&chip->update_heartbeat_work,
1570 round_jiffies_relative(msecs_to_jiffies
1571 (chip->update_time)));
1572}
1573
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001574/**
1575 * eoc_work - internal function to check if battery EOC
1576 * has happened
1577 *
1578 * If all conditions favouring, if the charge current is
1579 * less than the term current for three consecutive times
1580 * an EOC has happened.
1581 * The wakelock is released if there is no need to reshedule
1582 * - this happens when the battery is removed or EOC has
1583 * happened
1584 */
1585#define CONSECUTIVE_COUNT 3
1586#define VBAT_TOLERANCE_MV 70
1587#define CHG_DISABLE_MSLEEP 100
1588static void eoc_work(struct work_struct *work)
1589{
1590 struct delayed_work *dwork = to_delayed_work(work);
1591 struct pm8921_chg_chip *chip = container_of(dwork,
1592 struct pm8921_chg_chip, eoc_work);
1593 int vbat_meas, vbat_programmed;
1594 int ichg_meas, iterm_programmed;
1595 int regulation_loop, fast_chg, vcp;
1596 int rc;
1597 static int count;
1598
1599 /* return if the battery is not being fastcharged */
1600 fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
1601 pr_debug("fast_chg = %d\n", fast_chg);
1602 if (fast_chg == 0) {
1603 /* enable fastchg irq */
1604 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
1605 count = 0;
1606 wake_unlock(&chip->eoc_wake_lock);
1607 return;
1608 }
1609
1610 vcp = pm_chg_get_rt_status(chip, VCP_IRQ);
1611 pr_debug("vcp = %d\n", vcp);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07001612 if (vcp == 1)
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001613 goto reset_and_reschedule;
1614
1615 /* reset count if battery is hot/cold */
1616 rc = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
1617 pr_debug("batt_temp_ok = %d\n", rc);
1618 if (rc == 0)
1619 goto reset_and_reschedule;
1620
1621 /* reset count if battery voltage is less than vddmax */
1622 vbat_meas = get_prop_battery_mvolts(chip);
1623 if (vbat_meas < 0)
1624 goto reset_and_reschedule;
1625
1626 rc = pm_chg_vddmax_get(chip, &vbat_programmed);
1627 if (rc) {
1628 pr_err("couldnt read vddmax rc = %d\n", rc);
1629 goto reset_and_reschedule;
1630 }
1631 pr_debug("vddmax = %d vbat_meas=%d\n", vbat_programmed, vbat_meas);
1632 if (vbat_meas < vbat_programmed - VBAT_TOLERANCE_MV)
1633 goto reset_and_reschedule;
1634
1635 /* reset count if battery chg current is more than iterm */
1636 rc = pm_chg_iterm_get(chip, &iterm_programmed);
1637 if (rc) {
1638 pr_err("couldnt read iterm rc = %d\n", rc);
1639 goto reset_and_reschedule;
1640 }
1641
1642 ichg_meas = get_prop_batt_current(chip);
1643 pr_debug("iterm_programmed = %d ichg_meas=%d\n",
1644 iterm_programmed, ichg_meas);
1645 /*
1646 * ichg_meas < 0 means battery is drawing current
1647 * ichg_meas > 0 means battery is providing current
1648 */
1649 if (ichg_meas > 0)
1650 goto reset_and_reschedule;
1651
1652 if (ichg_meas * -1 > iterm_programmed)
1653 goto reset_and_reschedule;
1654
1655 /*
1656 * TODO if charging from an external charger check SOC instead of
1657 * regulation loop
1658 */
1659 regulation_loop = pm_chg_get_regulation_loop(chip);
1660 if (regulation_loop < 0) {
1661 pr_err("couldnt read the regulation loop err=%d\n",
1662 regulation_loop);
1663 goto reset_and_reschedule;
1664 }
1665 pr_debug("regulation_loop=%d\n", regulation_loop);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07001666
1667 if (regulation_loop != 0 && regulation_loop != VDD_LOOP)
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001668 goto reset_and_reschedule;
1669
1670 count++;
1671 if (count == CONSECUTIVE_COUNT) {
1672 count = 0;
1673 pr_info("End of Charging\n");
1674
1675 pm_chg_auto_enable(chip, 0);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001676
1677 /* declare end of charging by invoking chgdone interrupt */
1678 chgdone_irq_handler(chip->pmic_chg_irq[CHGDONE_IRQ], chip);
1679 wake_unlock(&chip->eoc_wake_lock);
1680 return;
1681 } else {
1682 pr_debug("EOC count = %d\n", count);
1683 goto reschedule;
1684 }
1685
1686reset_and_reschedule:
1687 count = 0;
1688reschedule:
1689 schedule_delayed_work(&chip->eoc_work,
1690 round_jiffies_relative(msecs_to_jiffies
1691 (EOC_CHECK_PERIOD_MS)));
1692}
1693
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07001694static void btm_configure_work(struct work_struct *work)
1695{
1696 int rc;
1697
1698 rc = pm8921_adc_btm_configure(&btm_config);
1699 if (rc)
1700 pr_err("failed to configure btm rc=%d", rc);
1701}
1702
1703DECLARE_WORK(btm_config_work, btm_configure_work);
1704
1705#define TEMP_HYSTERISIS_DEGC 2
1706static void battery_cool(bool enter)
1707{
1708 pr_debug("enter = %d\n", enter);
1709 if (enter) {
1710 btm_config.low_thr_temp =
1711 the_chip->cool_temp + TEMP_HYSTERISIS_DEGC;
1712 pm_chg_ibatmax_set(the_chip, the_chip->cool_bat_chg_current);
1713 pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
1714 } else {
1715 btm_config.low_thr_temp = the_chip->cool_temp;
1716 pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
1717 pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
1718 }
1719 schedule_work(&btm_config_work);
1720}
1721
1722static void battery_warm(bool enter)
1723{
1724 pr_debug("enter = %d\n", enter);
1725 if (enter) {
1726 btm_config.high_thr_temp =
1727 the_chip->warm_temp - TEMP_HYSTERISIS_DEGC;
1728 pm_chg_ibatmax_set(the_chip, the_chip->warm_bat_chg_current);
1729 pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
1730 } else {
1731 btm_config.high_thr_temp = the_chip->warm_temp;
1732 pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
1733 pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
1734 }
1735 schedule_work(&btm_config_work);
1736}
1737
1738static int configure_btm(struct pm8921_chg_chip *chip)
1739{
1740 int rc;
1741
1742 btm_config.btm_warm_fn = battery_warm;
1743 btm_config.btm_cool_fn = battery_cool;
1744 btm_config.low_thr_temp = chip->cool_temp;
1745 btm_config.high_thr_temp = chip->warm_temp;
1746 btm_config.interval = chip->temp_check_period;
1747 rc = pm8921_adc_btm_configure(&btm_config);
1748 if (rc)
1749 pr_err("failed to configure btm rc = %d\n", rc);
1750 rc = pm8921_adc_btm_start();
1751 if (rc)
1752 pr_err("failed to start btm rc = %d\n", rc);
1753
1754 return rc;
1755}
1756
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07001757/**
1758 * set_disable_status_param -
1759 *
1760 * Internal function to disable battery charging and also disable drawing
1761 * any current from the source. The device is forced to run on a battery
1762 * after this.
1763 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001764static int set_disable_status_param(const char *val, struct kernel_param *kp)
1765{
1766 int ret;
1767 struct pm8921_chg_chip *chip = the_chip;
1768
1769 ret = param_set_int(val, kp);
1770 if (ret) {
1771 pr_err("error setting value %d\n", ret);
1772 return ret;
1773 }
1774 pr_info("factory set disable param to %d\n", charging_disabled);
1775 if (chip) {
1776 pm_chg_auto_enable(chip, !charging_disabled);
1777 pm_chg_charge_dis(chip, charging_disabled);
1778 }
1779 return 0;
1780}
1781module_param_call(disabled, set_disable_status_param, param_get_uint,
1782 &charging_disabled, 0644);
1783
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07001784/**
1785 * set_thermal_mitigation_level -
1786 *
1787 * Internal function to control battery charging current to reduce
1788 * temperature
1789 */
1790static int set_therm_mitigation_level(const char *val, struct kernel_param *kp)
1791{
1792 int ret;
1793 struct pm8921_chg_chip *chip = the_chip;
1794
1795 ret = param_set_int(val, kp);
1796 if (ret) {
1797 pr_err("error setting value %d\n", ret);
1798 return ret;
1799 }
1800
1801 if (!chip) {
1802 pr_err("called before init\n");
1803 return -EINVAL;
1804 }
1805
1806 if (!chip->thermal_mitigation) {
1807 pr_err("no thermal mitigation\n");
1808 return -EINVAL;
1809 }
1810
1811 if (thermal_mitigation < 0
1812 || thermal_mitigation >= chip->thermal_levels) {
1813 pr_err("out of bound level selected\n");
1814 return -EINVAL;
1815 }
1816
1817 ret = pm_chg_ibatmax_set(chip,
1818 chip->thermal_mitigation[thermal_mitigation]);
1819 return ret;
1820}
1821module_param_call(thermal_mitigation, set_therm_mitigation_level,
1822 param_get_uint,
1823 &thermal_mitigation, 0644);
1824
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001825static void free_irqs(struct pm8921_chg_chip *chip)
1826{
1827 int i;
1828
1829 for (i = 0; i < PM_CHG_MAX_INTS; i++)
1830 if (chip->pmic_chg_irq[i]) {
1831 free_irq(chip->pmic_chg_irq[i], chip);
1832 chip->pmic_chg_irq[i] = 0;
1833 }
1834}
1835
1836/* determines the initial present states and notifies msm_charger */
1837static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
1838{
1839 unsigned long flags;
1840 int fsm_state;
1841
1842 chip->dc_present = !!is_dc_chg_plugged_in(chip);
1843 chip->usb_present = !!is_usb_chg_plugged_in(chip);
1844
1845 notify_usb_of_the_plugin_event(chip->usb_present);
1846
1847 pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
1848 pm8921_chg_enable_irq(chip, USBIN_VALID_IRQ);
1849 pm8921_chg_enable_irq(chip, BATT_REMOVED_IRQ);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001850 pm8921_chg_enable_irq(chip, BATT_INSERTED_IRQ);
1851 pm8921_chg_enable_irq(chip, USBIN_OV_IRQ);
1852 pm8921_chg_enable_irq(chip, USBIN_UV_IRQ);
1853 pm8921_chg_enable_irq(chip, DCIN_OV_IRQ);
1854 pm8921_chg_enable_irq(chip, DCIN_UV_IRQ);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001855 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
1856 pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001857
1858 spin_lock_irqsave(&vbus_lock, flags);
1859 if (usb_chg_current) {
1860 /* reissue a vbus draw call */
1861 __pm8921_charger_vbus_draw(usb_chg_current);
1862 }
1863 spin_unlock_irqrestore(&vbus_lock, flags);
1864
1865 fsm_state = pm_chg_get_fsm_state(chip);
1866 if (is_battery_charging(fsm_state)) {
1867 chip->bms_notify.is_charging = 1;
1868 pm8921_bms_charging_began();
1869 }
1870
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001871 check_battery_valid(chip);
1872
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001873 pr_debug("usb = %d, dc = %d batt = %d state=%d\n",
1874 chip->usb_present,
1875 chip->dc_present,
1876 get_prop_batt_present(chip),
1877 fsm_state);
1878}
1879
1880struct pm_chg_irq_init_data {
1881 unsigned int irq_id;
1882 char *name;
1883 unsigned long flags;
1884 irqreturn_t (*handler)(int, void *);
1885};
1886
1887#define CHG_IRQ(_id, _flags, _handler) \
1888{ \
1889 .irq_id = _id, \
1890 .name = #_id, \
1891 .flags = _flags, \
1892 .handler = _handler, \
1893}
1894struct pm_chg_irq_init_data chg_irq_data[] = {
1895 CHG_IRQ(USBIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1896 usbin_valid_irq_handler),
1897 CHG_IRQ(USBIN_OV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1898 usbin_ov_irq_handler),
1899 CHG_IRQ(BATT_INSERTED_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1900 batt_inserted_irq_handler),
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001901 CHG_IRQ(VBATDET_LOW_IRQ, IRQF_TRIGGER_HIGH, vbatdet_low_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001902 CHG_IRQ(USBIN_UV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1903 usbin_uv_irq_handler),
1904 CHG_IRQ(VBAT_OV_IRQ, IRQF_TRIGGER_RISING, vbat_ov_irq_handler),
1905 CHG_IRQ(CHGWDOG_IRQ, IRQF_TRIGGER_RISING, chgwdog_irq_handler),
1906 CHG_IRQ(VCP_IRQ, IRQF_TRIGGER_RISING, vcp_irq_handler),
1907 CHG_IRQ(ATCDONE_IRQ, IRQF_TRIGGER_RISING, atcdone_irq_handler),
1908 CHG_IRQ(ATCFAIL_IRQ, IRQF_TRIGGER_RISING, atcfail_irq_handler),
1909 CHG_IRQ(CHGDONE_IRQ, IRQF_TRIGGER_RISING, chgdone_irq_handler),
1910 CHG_IRQ(CHGFAIL_IRQ, IRQF_TRIGGER_RISING, chgfail_irq_handler),
1911 CHG_IRQ(CHGSTATE_IRQ, IRQF_TRIGGER_RISING, chgstate_irq_handler),
1912 CHG_IRQ(LOOP_CHANGE_IRQ, IRQF_TRIGGER_RISING, loop_change_irq_handler),
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001913 CHG_IRQ(FASTCHG_IRQ, IRQF_TRIGGER_HIGH, fastchg_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001914 CHG_IRQ(TRKLCHG_IRQ, IRQF_TRIGGER_RISING, trklchg_irq_handler),
1915 CHG_IRQ(BATT_REMOVED_IRQ, IRQF_TRIGGER_RISING,
1916 batt_removed_irq_handler),
1917 CHG_IRQ(BATTTEMP_HOT_IRQ, IRQF_TRIGGER_RISING,
1918 batttemp_hot_irq_handler),
1919 CHG_IRQ(CHGHOT_IRQ, IRQF_TRIGGER_RISING, chghot_irq_handler),
1920 CHG_IRQ(BATTTEMP_COLD_IRQ, IRQF_TRIGGER_RISING,
1921 batttemp_cold_irq_handler),
1922 CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING, chg_gone_irq_handler),
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001923 CHG_IRQ(BAT_TEMP_OK_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1924 bat_temp_ok_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001925 CHG_IRQ(COARSE_DET_LOW_IRQ, IRQF_TRIGGER_RISING,
1926 coarse_det_low_irq_handler),
1927 CHG_IRQ(VDD_LOOP_IRQ, IRQF_TRIGGER_RISING, vdd_loop_irq_handler),
1928 CHG_IRQ(VREG_OV_IRQ, IRQF_TRIGGER_RISING, vreg_ov_irq_handler),
1929 CHG_IRQ(VBATDET_IRQ, IRQF_TRIGGER_RISING, vbatdet_irq_handler),
1930 CHG_IRQ(BATFET_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1931 batfet_irq_handler),
1932 CHG_IRQ(DCIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1933 dcin_valid_irq_handler),
1934 CHG_IRQ(DCIN_OV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1935 dcin_ov_irq_handler),
1936 CHG_IRQ(DCIN_UV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1937 dcin_uv_irq_handler),
1938};
1939
1940static int __devinit request_irqs(struct pm8921_chg_chip *chip,
1941 struct platform_device *pdev)
1942{
1943 struct resource *res;
1944 int ret, i;
1945
1946 ret = 0;
1947 bitmap_fill(chip->enabled_irqs, PM_CHG_MAX_INTS);
1948
1949 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
1950 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1951 chg_irq_data[i].name);
1952 if (res == NULL) {
1953 pr_err("couldn't find %s\n", chg_irq_data[i].name);
1954 goto err_out;
1955 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001956 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = res->start;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 ret = request_irq(res->start, chg_irq_data[i].handler,
1958 chg_irq_data[i].flags,
1959 chg_irq_data[i].name, chip);
1960 if (ret < 0) {
1961 pr_err("couldn't request %d (%s) %d\n", res->start,
1962 chg_irq_data[i].name, ret);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001963 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001964 goto err_out;
1965 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001966 pm8921_chg_disable_irq(chip, chg_irq_data[i].irq_id);
1967 }
1968 return 0;
1969
1970err_out:
1971 free_irqs(chip);
1972 return -EINVAL;
1973}
1974
1975#define ENUM_TIMER_STOP_BIT BIT(1)
1976#define BOOT_DONE_BIT BIT(6)
1977#define CHG_BATFET_ON_BIT BIT(3)
1978#define CHG_VCP_EN BIT(0)
1979#define CHG_BAT_TEMP_DIS_BIT BIT(2)
1980#define SAFE_CURRENT_MA 1500
1981static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
1982{
1983 int rc;
1984
1985 rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
1986 BOOT_DONE_BIT, BOOT_DONE_BIT);
1987 if (rc) {
1988 pr_err("Failed to set BOOT_DONE_BIT rc=%d\n", rc);
1989 return rc;
1990 }
1991
1992 rc = pm_chg_vddsafe_set(chip, chip->max_voltage);
1993 if (rc) {
1994 pr_err("Failed to set safe voltage to %d rc=%d\n",
1995 chip->max_voltage, rc);
1996 return rc;
1997 }
1998 rc = pm_chg_vbatdet_set(chip, chip->resume_voltage);
1999 if (rc) {
2000 pr_err("Failed to set vbatdet comprator voltage to %d rc=%d\n",
2001 chip->resume_voltage, rc);
2002 return rc;
2003 }
2004
2005 rc = pm_chg_vddmax_set(chip, chip->max_voltage);
2006 if (rc) {
2007 pr_err("Failed to set max voltage to %d rc=%d\n",
2008 chip->max_voltage, rc);
2009 return rc;
2010 }
2011 rc = pm_chg_ibatsafe_set(chip, SAFE_CURRENT_MA);
2012 if (rc) {
2013 pr_err("Failed to set max voltage to %d rc=%d\n",
2014 SAFE_CURRENT_MA, rc);
2015 return rc;
2016 }
2017
2018 /* TODO needs to be changed as per the temeperature of the battery */
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002019 rc = pm_chg_ibatmax_set(chip, chip->max_bat_chg_current);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002020 if (rc) {
2021 pr_err("Failed to set max current to 400 rc=%d\n", rc);
2022 return rc;
2023 }
2024
2025 rc = pm_chg_iterm_set(chip, chip->term_current);
2026 if (rc) {
2027 pr_err("Failed to set term current to %d rc=%d\n",
2028 chip->term_current, rc);
2029 return rc;
2030 }
2031
2032 /* Disable the ENUM TIMER */
2033 rc = pm_chg_masked_write(chip, PBL_ACCESS2, ENUM_TIMER_STOP_BIT,
2034 ENUM_TIMER_STOP_BIT);
2035 if (rc) {
2036 pr_err("Failed to set enum timer stop rc=%d\n", rc);
2037 return rc;
2038 }
2039
2040 /* init with the lowest USB current */
2041 rc = pm_chg_iusbmax_set(chip, usb_ma_table[0].chg_iusb_value);
2042 if (rc) {
2043 pr_err("Failed to set usb max to %d rc=%d\n",
2044 usb_ma_table[0].chg_iusb_value, rc);
2045 return rc;
2046 }
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002047
2048 if (chip->safety_time != 0) {
2049 rc = pm_chg_tchg_max_set(chip, chip->safety_time);
2050 if (rc) {
2051 pr_err("Failed to set max time to %d minutes rc=%d\n",
2052 chip->safety_time, rc);
2053 return rc;
2054 }
2055 }
2056
2057 if (chip->ttrkl_time != 0) {
2058 rc = pm_chg_ttrkl_max_set(chip, chip->safety_time);
2059 if (rc) {
2060 pr_err("Failed to set trkl time to %d minutes rc=%d\n",
2061 chip->safety_time, rc);
2062 return rc;
2063 }
2064 }
2065
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002066 if (chip->vin_min != 0) {
2067 rc = pm_chg_vinmin_set(chip, chip->vin_min);
2068 if (rc) {
2069 pr_err("Failed to set vin min to %d mV rc=%d\n",
2070 chip->vin_min, rc);
2071 return rc;
2072 }
2073 }
2074
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002075 rc = pm_chg_disable_wd(chip);
2076 if (rc) {
2077 pr_err("Failed to disable wd rc=%d\n", rc);
2078 return rc;
2079 }
2080
2081 rc = pm_chg_masked_write(chip, CHG_CNTRL_2,
2082 CHG_BAT_TEMP_DIS_BIT, 0);
2083 if (rc) {
2084 pr_err("Failed to enable temp control chg rc=%d\n", rc);
2085 return rc;
2086 }
2087 /* switch to a 3.2Mhz for the buck */
2088 rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CLOCK_CTRL, 0x15);
2089 if (rc) {
2090 pr_err("Failed to switch buck clk rc=%d\n", rc);
2091 return rc;
2092 }
2093
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07002094 if (chip->trkl_voltage != 0) {
2095 rc = pm_chg_vtrkl_low_set(chip, chip->trkl_voltage);
2096 if (rc) {
2097 pr_err("Failed to set trkl voltage to %dmv rc=%d\n",
2098 chip->trkl_voltage, rc);
2099 return rc;
2100 }
2101 }
2102
2103 if (chip->weak_voltage != 0) {
2104 rc = pm_chg_vweak_set(chip, chip->weak_voltage);
2105 if (rc) {
2106 pr_err("Failed to set weak voltage to %dmv rc=%d\n",
2107 chip->weak_voltage, rc);
2108 return rc;
2109 }
2110 }
2111
2112 if (chip->trkl_current != 0) {
2113 rc = pm_chg_itrkl_set(chip, chip->trkl_current);
2114 if (rc) {
2115 pr_err("Failed to set trkl current to %dmA rc=%d\n",
2116 chip->trkl_voltage, rc);
2117 return rc;
2118 }
2119 }
2120
2121 if (chip->weak_current != 0) {
2122 rc = pm_chg_iweak_set(chip, chip->weak_current);
2123 if (rc) {
2124 pr_err("Failed to set weak current to %dmA rc=%d\n",
2125 chip->weak_current, rc);
2126 return rc;
2127 }
2128 }
2129
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07002130 rc = pm_chg_batt_cold_temp_config(chip, chip->cold_thr);
2131 if (rc) {
2132 pr_err("Failed to set cold config %d rc=%d\n",
2133 chip->cold_thr, rc);
2134 }
2135
2136 rc = pm_chg_batt_hot_temp_config(chip, chip->hot_thr);
2137 if (rc) {
2138 pr_err("Failed to set hot config %d rc=%d\n",
2139 chip->hot_thr, rc);
2140 }
2141
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002142 /* Workarounds for die 1.1 and 1.0 */
2143 if (pm8xxx_get_revision(chip->dev->parent) < PM8XXX_REVISION_8921_2p0) {
2144 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST2, 0xF1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002145 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xCE);
2146 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD8);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002147
2148 /* software workaround for correct battery_id detection */
2149 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_0, 0xFF);
2150 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_1, 0xFF);
2151 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_2, 0xFF);
2152 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_3, 0xFF);
2153 pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0D);
2154 udelay(100);
2155 pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0C);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002156 }
2157
2158 rc = pm_chg_charge_dis(chip, charging_disabled);
2159 if (rc) {
2160 pr_err("Failed to disable CHG_CHARGE_DIS bit rc=%d\n", rc);
2161 return rc;
2162 }
2163
2164 rc = pm_chg_auto_enable(chip, !charging_disabled);
2165 if (rc) {
2166 pr_err("Failed to enable charging rc=%d\n", rc);
2167 return rc;
2168 }
2169
2170 return 0;
2171}
2172
2173static int get_rt_status(void *data, u64 * val)
2174{
2175 int i = (int)data;
2176 int ret;
2177
2178 /* global irq number is passed in via data */
2179 ret = pm_chg_get_rt_status(the_chip, i);
2180 *val = ret;
2181 return 0;
2182}
2183DEFINE_SIMPLE_ATTRIBUTE(rt_fops, get_rt_status, NULL, "%llu\n");
2184
2185static int get_fsm_status(void *data, u64 * val)
2186{
2187 u8 temp;
2188
2189 temp = pm_chg_get_fsm_state(the_chip);
2190 *val = temp;
2191 return 0;
2192}
2193DEFINE_SIMPLE_ATTRIBUTE(fsm_fops, get_fsm_status, NULL, "%llu\n");
2194
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002195static int get_reg_loop(void *data, u64 * val)
2196{
2197 u8 temp;
2198
2199 if (!the_chip) {
2200 pr_err("%s called before init\n", __func__);
2201 return -EINVAL;
2202 }
2203 temp = pm_chg_get_regulation_loop(the_chip);
2204 *val = temp;
2205 return 0;
2206}
2207DEFINE_SIMPLE_ATTRIBUTE(reg_loop_fops, get_reg_loop, NULL, "0x%02llx\n");
2208
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002209static int get_reg(void *data, u64 * val)
2210{
2211 int addr = (int)data;
2212 int ret;
2213 u8 temp;
2214
2215 ret = pm8xxx_readb(the_chip->dev->parent, addr, &temp);
2216 if (ret) {
2217 pr_err("pm8xxx_readb to %x value =%d errored = %d\n",
2218 addr, temp, ret);
2219 return -EAGAIN;
2220 }
2221 *val = temp;
2222 return 0;
2223}
2224
2225static int set_reg(void *data, u64 val)
2226{
2227 int addr = (int)data;
2228 int ret;
2229 u8 temp;
2230
2231 temp = (u8) val;
2232 ret = pm8xxx_writeb(the_chip->dev->parent, addr, temp);
2233 if (ret) {
2234 pr_err("pm8xxx_writeb to %x value =%d errored = %d\n",
2235 addr, temp, ret);
2236 return -EAGAIN;
2237 }
2238 return 0;
2239}
2240DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
2241
2242static void create_debugfs_entries(struct pm8921_chg_chip *chip)
2243{
2244 int i;
2245
2246 chip->dent = debugfs_create_dir("pm8921_chg", NULL);
2247
2248 if (IS_ERR(chip->dent)) {
2249 pr_err("pmic charger couldnt create debugfs dir\n");
2250 return;
2251 }
2252
2253 debugfs_create_file("CHG_CNTRL", 0644, chip->dent,
2254 (void *)CHG_CNTRL, &reg_fops);
2255 debugfs_create_file("CHG_CNTRL_2", 0644, chip->dent,
2256 (void *)CHG_CNTRL_2, &reg_fops);
2257 debugfs_create_file("CHG_CNTRL_3", 0644, chip->dent,
2258 (void *)CHG_CNTRL_3, &reg_fops);
2259 debugfs_create_file("PBL_ACCESS1", 0644, chip->dent,
2260 (void *)PBL_ACCESS1, &reg_fops);
2261 debugfs_create_file("PBL_ACCESS2", 0644, chip->dent,
2262 (void *)PBL_ACCESS2, &reg_fops);
2263 debugfs_create_file("SYS_CONFIG_1", 0644, chip->dent,
2264 (void *)SYS_CONFIG_1, &reg_fops);
2265 debugfs_create_file("SYS_CONFIG_2", 0644, chip->dent,
2266 (void *)SYS_CONFIG_2, &reg_fops);
2267 debugfs_create_file("CHG_VDD_MAX", 0644, chip->dent,
2268 (void *)CHG_VDD_MAX, &reg_fops);
2269 debugfs_create_file("CHG_VDD_SAFE", 0644, chip->dent,
2270 (void *)CHG_VDD_SAFE, &reg_fops);
2271 debugfs_create_file("CHG_VBAT_DET", 0644, chip->dent,
2272 (void *)CHG_VBAT_DET, &reg_fops);
2273 debugfs_create_file("CHG_IBAT_MAX", 0644, chip->dent,
2274 (void *)CHG_IBAT_MAX, &reg_fops);
2275 debugfs_create_file("CHG_IBAT_SAFE", 0644, chip->dent,
2276 (void *)CHG_IBAT_SAFE, &reg_fops);
2277 debugfs_create_file("CHG_VIN_MIN", 0644, chip->dent,
2278 (void *)CHG_VIN_MIN, &reg_fops);
2279 debugfs_create_file("CHG_VTRICKLE", 0644, chip->dent,
2280 (void *)CHG_VTRICKLE, &reg_fops);
2281 debugfs_create_file("CHG_ITRICKLE", 0644, chip->dent,
2282 (void *)CHG_ITRICKLE, &reg_fops);
2283 debugfs_create_file("CHG_ITERM", 0644, chip->dent,
2284 (void *)CHG_ITERM, &reg_fops);
2285 debugfs_create_file("CHG_TCHG_MAX", 0644, chip->dent,
2286 (void *)CHG_TCHG_MAX, &reg_fops);
2287 debugfs_create_file("CHG_TWDOG", 0644, chip->dent,
2288 (void *)CHG_TWDOG, &reg_fops);
2289 debugfs_create_file("CHG_TEMP_THRESH", 0644, chip->dent,
2290 (void *)CHG_TEMP_THRESH, &reg_fops);
2291 debugfs_create_file("CHG_COMP_OVR", 0644, chip->dent,
2292 (void *)CHG_COMP_OVR, &reg_fops);
2293 debugfs_create_file("CHG_BUCK_CTRL_TEST1", 0644, chip->dent,
2294 (void *)CHG_BUCK_CTRL_TEST1, &reg_fops);
2295 debugfs_create_file("CHG_BUCK_CTRL_TEST2", 0644, chip->dent,
2296 (void *)CHG_BUCK_CTRL_TEST2, &reg_fops);
2297 debugfs_create_file("CHG_BUCK_CTRL_TEST3", 0644, chip->dent,
2298 (void *)CHG_BUCK_CTRL_TEST3, &reg_fops);
2299 debugfs_create_file("CHG_TEST", 0644, chip->dent,
2300 (void *)CHG_TEST, &reg_fops);
2301
2302 debugfs_create_file("FSM_STATE", 0644, chip->dent, NULL,
2303 &fsm_fops);
2304
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002305 debugfs_create_file("REGULATION_LOOP_CONTROL", 0644, chip->dent, NULL,
2306 &reg_loop_fops);
2307
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002308 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
2309 if (chip->pmic_chg_irq[chg_irq_data[i].irq_id])
2310 debugfs_create_file(chg_irq_data[i].name, 0444,
2311 chip->dent,
2312 (void *)chg_irq_data[i].irq_id,
2313 &rt_fops);
2314 }
2315}
2316
2317static int __devinit pm8921_charger_probe(struct platform_device *pdev)
2318{
2319 int rc = 0;
2320 struct pm8921_chg_chip *chip;
2321 const struct pm8921_charger_platform_data *pdata
2322 = pdev->dev.platform_data;
2323
2324 if (!pdata) {
2325 pr_err("missing platform data\n");
2326 return -EINVAL;
2327 }
2328
2329 chip = kzalloc(sizeof(struct pm8921_chg_chip),
2330 GFP_KERNEL);
2331 if (!chip) {
2332 pr_err("Cannot allocate pm_chg_chip\n");
2333 return -ENOMEM;
2334 }
2335
2336 chip->dev = &pdev->dev;
2337 chip->safety_time = pdata->safety_time;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002338 chip->ttrkl_time = pdata->ttrkl_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002339 chip->update_time = pdata->update_time;
2340 chip->max_voltage = pdata->max_voltage;
2341 chip->min_voltage = pdata->min_voltage;
2342 chip->resume_voltage = pdata->resume_voltage;
2343 chip->term_current = pdata->term_current;
2344 chip->vbat_channel = pdata->charger_cdata.vbat_channel;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002345 chip->batt_temp_channel = pdata->charger_cdata.batt_temp_channel;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002346 chip->batt_id_channel = pdata->charger_cdata.batt_id_channel;
2347 chip->batt_id_min = pdata->batt_id_min;
2348 chip->batt_id_max = pdata->batt_id_max;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002349 chip->cool_temp = pdata->cool_temp;
2350 chip->warm_temp = pdata->warm_temp;
2351 chip->temp_check_period = pdata->temp_check_period;
2352 chip->max_bat_chg_current = pdata->max_bat_chg_current;
2353 chip->cool_bat_chg_current = pdata->cool_bat_chg_current;
2354 chip->warm_bat_chg_current = pdata->warm_bat_chg_current;
2355 chip->cool_bat_voltage = pdata->cool_bat_voltage;
2356 chip->warm_bat_voltage = pdata->warm_bat_voltage;
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07002357 chip->trkl_voltage = pdata->trkl_voltage;
2358 chip->weak_voltage = pdata->weak_voltage;
2359 chip->trkl_current = pdata->trkl_current;
2360 chip->weak_current = pdata->weak_current;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002361 chip->vin_min = pdata->vin_min;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07002362 chip->thermal_mitigation = pdata->thermal_mitigation;
2363 chip->thermal_levels = pdata->thermal_levels;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002364
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07002365 chip->cold_thr = pdata->cold_thr;
2366 chip->hot_thr = pdata->hot_thr;
2367
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002368 rc = pm8921_chg_hw_init(chip);
2369 if (rc) {
2370 pr_err("couldn't init hardware rc=%d\n", rc);
2371 goto free_chip;
2372 }
2373
2374 chip->usb_psy.name = "usb",
2375 chip->usb_psy.type = POWER_SUPPLY_TYPE_USB,
2376 chip->usb_psy.supplied_to = pm_power_supplied_to,
2377 chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
2378 chip->usb_psy.properties = pm_power_props,
2379 chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props),
2380 chip->usb_psy.get_property = pm_power_get_property,
2381
2382 chip->dc_psy.name = "ac",
2383 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS,
2384 chip->dc_psy.supplied_to = pm_power_supplied_to,
2385 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
2386 chip->dc_psy.properties = pm_power_props,
2387 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props),
2388 chip->dc_psy.get_property = pm_power_get_property,
2389
2390 chip->batt_psy.name = "battery",
2391 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY,
2392 chip->batt_psy.properties = msm_batt_power_props,
2393 chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props),
2394 chip->batt_psy.get_property = pm_batt_power_get_property,
2395
2396 rc = power_supply_register(chip->dev, &chip->usb_psy);
2397 if (rc < 0) {
2398 pr_err("power_supply_register usb failed rc = %d\n", rc);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002399 goto free_chip;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002400 }
2401
2402 rc = power_supply_register(chip->dev, &chip->dc_psy);
2403 if (rc < 0) {
2404 pr_err("power_supply_register dc failed rc = %d\n", rc);
2405 goto unregister_usb;
2406 }
2407
2408 rc = power_supply_register(chip->dev, &chip->batt_psy);
2409 if (rc < 0) {
2410 pr_err("power_supply_register batt failed rc = %d\n", rc);
2411 goto unregister_dc;
2412 }
2413
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002414 platform_set_drvdata(pdev, chip);
2415 the_chip = chip;
2416
2417 wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
2418 INIT_DELAYED_WORK(&chip->eoc_work, eoc_work);
2419
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002420 rc = request_irqs(chip, pdev);
2421 if (rc) {
2422 pr_err("couldn't register interrupts rc=%d\n", rc);
2423 goto unregister_batt;
2424 }
2425
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07002426 enable_irq_wake(chip->pmic_chg_irq[USBIN_VALID_IRQ]);
2427 enable_irq_wake(chip->pmic_chg_irq[USBIN_OV_IRQ]);
2428 enable_irq_wake(chip->pmic_chg_irq[USBIN_UV_IRQ]);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002429 /*
2430 * if both the cool_temp and warm_temp are zero the device doesnt
2431 * care for jeita compliance
2432 */
2433 if (!(chip->cool_temp == 0 && chip->warm_temp == 0)) {
2434 rc = configure_btm(chip);
2435 if (rc) {
2436 pr_err("couldn't register with btm rc=%d\n", rc);
2437 goto free_irq;
2438 }
2439 }
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07002440
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002441 create_debugfs_entries(chip);
2442
2443 INIT_WORK(&chip->bms_notify.work, bms_notify);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002444 INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002445
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002446 /* determine what state the charger is in */
2447 determine_initial_state(chip);
2448
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07002449 if (chip->update_time) {
2450 INIT_DELAYED_WORK(&chip->update_heartbeat_work,
2451 update_heartbeat);
2452 schedule_delayed_work(&chip->update_heartbeat_work,
2453 round_jiffies_relative(msecs_to_jiffies
2454 (chip->update_time)));
2455 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002456 return 0;
2457
2458free_irq:
2459 free_irqs(chip);
2460unregister_batt:
2461 power_supply_unregister(&chip->batt_psy);
2462unregister_dc:
2463 power_supply_unregister(&chip->dc_psy);
2464unregister_usb:
2465 power_supply_unregister(&chip->usb_psy);
2466free_chip:
2467 kfree(chip);
2468 return rc;
2469}
2470
2471static int __devexit pm8921_charger_remove(struct platform_device *pdev)
2472{
2473 struct pm8921_chg_chip *chip = platform_get_drvdata(pdev);
2474
2475 free_irqs(chip);
2476 platform_set_drvdata(pdev, NULL);
2477 the_chip = NULL;
2478 kfree(chip);
2479 return 0;
2480}
2481
2482static struct platform_driver pm8921_charger_driver = {
2483 .probe = pm8921_charger_probe,
2484 .remove = __devexit_p(pm8921_charger_remove),
2485 .driver = {
2486 .name = PM8921_CHARGER_DEV_NAME,
2487 .owner = THIS_MODULE,
2488 },
2489};
2490
2491static int __init pm8921_charger_init(void)
2492{
2493 return platform_driver_register(&pm8921_charger_driver);
2494}
2495
2496static void __exit pm8921_charger_exit(void)
2497{
2498 platform_driver_unregister(&pm8921_charger_driver);
2499}
2500
2501late_initcall(pm8921_charger_init);
2502module_exit(pm8921_charger_exit);
2503
2504MODULE_LICENSE("GPL v2");
2505MODULE_DESCRIPTION("PMIC8921 charger/battery driver");
2506MODULE_VERSION("1.0");
2507MODULE_ALIAS("platform:" PM8921_CHARGER_DEV_NAME);