blob: a3ce54d2333e38899b8464839f0123499cf52056 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-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
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/platform_device.h>
17#include <linux/errno.h>
18#include <linux/mfd/pmic8058.h>
19#include <linux/interrupt.h>
20#include <linux/delay.h>
21#include <linux/bitops.h>
22#include <linux/workqueue.h>
23#include <linux/msm-charger.h>
24#include <linux/debugfs.h>
25#include <linux/slab.h>
26#include <linux/msm_adc.h>
27#include <linux/notifier.h>
28#include <linux/pmic8058-batt-alarm.h>
Abhijeet Dharmapurikarf734c672011-08-11 10:20:27 -070029#include <linux/pmic8058-charger.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030
31#include <mach/msm_xo.h>
32#include <mach/msm_hsusb.h>
33
34/* Config Regs and their bits*/
35#define PM8058_CHG_TEST 0x75
36#define IGNORE_LL 2
37#define PM8058_CHG_TEST_2 0xEA
38#define PM8058_CHG_TEST_3 0xEB
39#define PM8058_OVP_TEST_REG 0xF6
40#define FORCE_OVP_OFF 3
41
42#define PM8058_CHG_CNTRL 0x1E
43#define CHG_TRICKLE_EN 7
44#define CHG_USB_SUSPEND 6
45#define CHG_IMON_CAL 5
46#define CHG_IMON_GAIN 4
47#define CHG_CHARGE_BAT 3
48#define CHG_VBUS_FROM_BOOST_OVRD 2
49#define CHG_CHARGE_DIS 1
50#define CHG_VCP_EN 0
51
52#define PM8058_CHG_CNTRL_2 0xD8
53#define ATC_DIS 7 /* coincell backed */
54#define CHARGE_AUTO_DIS 6
55#define DUMB_CHG_OVRD 5 /* coincell backed */
56#define ENUM_DONE 4
57#define CHG_TEMP_MODE 3
58#define CHG_BATT_TEMP_DIS 1 /* coincell backed */
59#define CHG_FAILED_CLEAR 0
60
61#define PM8058_CHG_VMAX_SEL 0x21
62#define PM8058_CHG_VBAT_DET 0xD9
63#define PM8058_CHG_IMAX 0x1F
64#define PM8058_CHG_TRICKLE 0xDB
65#define PM8058_CHG_ITERM 0xDC
66#define PM8058_CHG_TTRKL_MAX 0xE1
67#define PM8058_CHG_TCHG_MAX 0xE4
68#define PM8058_CHG_TEMP_THRESH 0xE2
69#define PM8058_CHG_TEMP_REG 0xE3
70#define PM8058_CHG_PULSE 0x22
71
72/* IRQ STATUS and CLEAR */
73#define PM8058_CHG_STATUS_CLEAR_IRQ_1 0x31
74#define PM8058_CHG_STATUS_CLEAR_IRQ_3 0x33
75#define PM8058_CHG_STATUS_CLEAR_IRQ_10 0xB3
76#define PM8058_CHG_STATUS_CLEAR_IRQ_11 0xB4
77
78/* IRQ MASKS */
79#define PM8058_CHG_MASK_IRQ_1 0x38
80
81#define PM8058_CHG_MASK_IRQ_3 0x3A
82#define PM8058_CHG_MASK_IRQ_10 0xBA
83#define PM8058_CHG_MASK_IRQ_11 0xBB
84
85/* IRQ Real time status regs */
86#define PM8058_CHG_STATUS_RT_1 0x3F
87#define STATUS_RTCHGVAL 7
88#define STATUS_RTCHGINVAL 6
89#define STATUS_RTBATT_REPLACE 5
90#define STATUS_RTVBATDET_LOW 4
91#define STATUS_RTCHGILIM 3
92#define STATUS_RTPCTDONE 1
93#define STATUS_RTVCP 0
94#define PM8058_CHG_STATUS_RT_3 0x41
95#define PM8058_CHG_STATUS_RT_10 0xC1
96#define PM8058_CHG_STATUS_RT_11 0xC2
97
98/* VTRIM */
99#define PM8058_CHG_VTRIM 0x1D
100#define PM8058_CHG_VBATDET_TRIM 0x1E
101#define PM8058_CHG_ITRIM 0x1F
102#define PM8058_CHG_TTRIM 0x20
103
104#define AUTO_CHARGING_VMAXSEL 4200
105#define AUTO_CHARGING_FAST_TIME_MAX_MINUTES 512
106#define AUTO_CHARGING_TRICKLE_TIME_MINUTES 30
107#define AUTO_CHARGING_VEOC_ITERM 100
108#define AUTO_CHARGING_IEOC_ITERM 160
109#define AUTO_CHARGING_RESUME_MV 4100
110
111#define AUTO_CHARGING_VBATDET 4150
112#define AUTO_CHARGING_VBATDET_DEBOUNCE_TIME_MS 3000
113#define AUTO_CHARGING_VEOC_VBATDET 4100
114#define AUTO_CHARGING_VEOC_TCHG 16
115#define AUTO_CHARGING_VEOC_TCHG_FINAL_CYCLE 32
116#define AUTO_CHARGING_VEOC_BEGIN_TIME_MS 5400000
117
118#define AUTO_CHARGING_VEOC_VBAT_LOW_CHECK_TIME_MS 60000
119#define AUTO_CHARGING_RESUME_CHARGE_DETECTION_COUNTER 5
120
121#define AUTO_CHARGING_DONE_CHECK_TIME_MS 1000
122
123#define PM8058_CHG_I_STEP_MA 50
124#define PM8058_CHG_I_MIN_MA 50
125#define PM8058_CHG_T_TCHG_SHIFT 2
126#define PM8058_CHG_I_TERM_STEP_MA 10
127#define PM8058_CHG_V_STEP_MV 25
128#define PM8058_CHG_V_MIN_MV 2400
129/*
130 * enum pmic_chg_interrupts: pmic interrupts
131 * @CHGVAL_IRQ: charger V between 3.3 and 7.9
132 * @CHGINVAL_IRQ: charger V outside 3.3 and 7.9
133 * @VBATDET_LOW_IRQ: VBAT < VBATDET
134 * @VCP_IRQ: VDD went below VBAT: BAT_FET is turned on
135 * @CHGILIM_IRQ: mA consumed>IMAXSEL: chgloop draws less mA
136 * @ATC_DONE_IRQ: Auto Trickle done
137 * @ATCFAIL_IRQ: Auto Trickle fail
138 * @AUTO_CHGDONE_IRQ: Auto chg done
139 * @AUTO_CHGFAIL_IRQ: time exceeded w/o reaching term current
140 * @CHGSTATE_IRQ: something happend causing a state change
141 * @FASTCHG_IRQ: trkl charging completed: moving to fastchg
142 * @CHG_END_IRQ: mA has dropped to termination current
143 * @BATTTEMP_IRQ: batt temp is out of range
144 * @CHGHOT_IRQ: the pass device is too hot
145 * @CHGTLIMIT_IRQ: unused
146 * @CHG_GONE_IRQ: charger was removed
147 * @VCPMAJOR_IRQ: vcp major
148 * @VBATDET_IRQ: VBAT >= VBATDET
149 * @BATFET_IRQ: BATFET closed
150 * @BATT_REPLACE_IRQ:
151 * @BATTCONNECT_IRQ:
152 */
153enum pmic_chg_interrupts {
154 CHGVAL_IRQ,
155 CHGINVAL_IRQ,
156 VBATDET_LOW_IRQ,
157 VCP_IRQ,
158 CHGILIM_IRQ,
159 ATC_DONE_IRQ,
160 ATCFAIL_IRQ,
161 AUTO_CHGDONE_IRQ,
162 AUTO_CHGFAIL_IRQ,
163 CHGSTATE_IRQ,
164 FASTCHG_IRQ,
165 CHG_END_IRQ,
166 BATTTEMP_IRQ,
167 CHGHOT_IRQ,
168 CHGTLIMIT_IRQ,
169 CHG_GONE_IRQ,
170 VCPMAJOR_IRQ,
171 VBATDET_IRQ,
172 BATFET_IRQ,
173 BATT_REPLACE_IRQ,
174 BATTCONNECT_IRQ,
175 PMIC_CHG_MAX_INTS
176};
177
178struct pm8058_charger {
179 struct pmic_charger_pdata *pdata;
180 struct pm8058_chip *pm_chip;
181 struct device *dev;
182
183 int pmic_chg_irq[PMIC_CHG_MAX_INTS];
184 DECLARE_BITMAP(enabled_irqs, PMIC_CHG_MAX_INTS);
185
186 struct delayed_work chg_done_check_work;
187 struct delayed_work check_vbat_low_work;
188 struct delayed_work veoc_begin_work;
189 struct delayed_work charging_check_work;
190 int waiting_for_topoff;
191 int waiting_for_veoc;
192 int vbatdet;
193 struct msm_hardware_charger hw_chg;
194 int current_charger_current;
195 int disabled;
196
197 struct msm_xo_voter *voter;
198 struct dentry *dent;
199
200 int inited;
201 int present;
202};
203
204static struct pm8058_charger pm8058_chg;
205static struct msm_hardware_charger usb_hw_chg;
Terence Hampson13163082011-08-09 10:17:06 -0400206static struct pmic8058_charger_data chg_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207
208static int msm_battery_gauge_alarm_notify(struct notifier_block *nb,
209 unsigned long status, void *unused);
210
211static struct notifier_block alarm_notifier = {
212 .notifier_call = msm_battery_gauge_alarm_notify,
213};
214
215static int resume_mv = AUTO_CHARGING_RESUME_MV;
216static DEFINE_MUTEX(batt_alarm_lock);
217static int resume_mv_set(const char *val, struct kernel_param *kp);
218module_param_call(resume_mv, resume_mv_set, param_get_int,
219 &resume_mv, S_IRUGO | S_IWUSR);
220
221static int resume_mv_set(const char *val, struct kernel_param *kp)
222{
223 int rc;
224
225 mutex_lock(&batt_alarm_lock);
226
227 rc = param_set_int(val, kp);
228 if (rc)
229 goto out;
230
231 rc = pm8058_batt_alarm_threshold_set(resume_mv, 4300);
232
233out:
234 mutex_unlock(&batt_alarm_lock);
235 return rc;
236}
237
238static void pm8058_chg_enable_irq(int interrupt)
239{
240 if (!__test_and_set_bit(interrupt, pm8058_chg.enabled_irqs)) {
241 dev_dbg(pm8058_chg.dev, "%s %d\n", __func__,
242 pm8058_chg.pmic_chg_irq[interrupt]);
243 enable_irq(pm8058_chg.pmic_chg_irq[interrupt]);
244 }
245}
246
247static void pm8058_chg_disable_irq(int interrupt)
248{
249 if (__test_and_clear_bit(interrupt, pm8058_chg.enabled_irqs)) {
250 dev_dbg(pm8058_chg.dev, "%s %d\n", __func__,
251 pm8058_chg.pmic_chg_irq[interrupt]);
252 disable_irq_nosync(pm8058_chg.pmic_chg_irq[interrupt]);
253 }
254}
255
256static int pm_chg_get_rt_status(int irq)
257{
258 int count = 3;
259 int ret;
260
261 while ((ret =
262 pm8058_irq_get_rt_status(pm8058_chg.pm_chip, irq)) == -EAGAIN
263 && count--) {
264 dev_info(pm8058_chg.dev, "%s trycount=%d\n", __func__, count);
265 cpu_relax();
266 }
267 if (ret == -EAGAIN)
268 return 0;
269 else
270 return ret;
271}
272
273static int is_chg_plugged_in(void)
274{
275 return pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGVAL_IRQ]);
276}
277
278#ifdef DEBUG
279static void __dump_chg_regs(void)
280{
281 u8 temp;
282 int temp2;
283
284 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
285 dev_dbg(pm8058_chg.dev, "PM8058_CHG_CNTRL = 0x%x\n", temp);
286 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
287 dev_dbg(pm8058_chg.dev, "PM8058_CHG_CNTRL_2 = 0x%x\n", temp);
288 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_VMAX_SEL, &temp, 1);
289 dev_dbg(pm8058_chg.dev, "PM8058_CHG_VMAX_SEL = 0x%x\n", temp);
290 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_VBAT_DET, &temp, 1);
291 dev_dbg(pm8058_chg.dev, "PM8058_CHG_VBAT_DET = 0x%x\n", temp);
292 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_IMAX, &temp, 1);
293 dev_dbg(pm8058_chg.dev, "PM8058_CHG_IMAX = 0x%x\n", temp);
294 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TRICKLE, &temp, 1);
295 dev_dbg(pm8058_chg.dev, "PM8058_CHG_TRICKLE = 0x%x\n", temp);
296 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_ITERM, &temp, 1);
297 dev_dbg(pm8058_chg.dev, "PM8058_CHG_ITERM = 0x%x\n", temp);
298 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TTRKL_MAX, &temp, 1);
299 dev_dbg(pm8058_chg.dev, "PM8058_CHG_TTRKL_MAX = 0x%x\n", temp);
300 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TCHG_MAX, &temp, 1);
301 dev_dbg(pm8058_chg.dev, "PM8058_CHG_TCHG_MAX = 0x%x\n", temp);
302 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEMP_THRESH, &temp, 1);
303 dev_dbg(pm8058_chg.dev, "PM8058_CHG_TEMP_THRESH = 0x%x\n", temp);
304 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEMP_REG, &temp, 1);
305 dev_dbg(pm8058_chg.dev, "PM8058_CHG_TEMP_REG = 0x%x\n", temp);
306 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_PULSE, &temp, 1);
307 dev_dbg(pm8058_chg.dev, "PM8058_CHG_PULSE = 0x%x\n", temp);
308
309 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_1,
310 &temp, 1);
311 dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_1 = 0x%x\n", temp);
312 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_3,
313 &temp, 1);
314 dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_3 = 0x%x\n", temp);
315 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_10,
316 &temp, 1);
317 dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_10 = 0x%x\n",
318 temp);
319 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_11,
320 &temp, 1);
321 dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_11 = 0x%x\n",
322 temp);
323
324 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_1, &temp, 1);
325 dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_1 = 0x%x\n", temp);
326 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_3, &temp, 1);
327 dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_3 = 0x%x\n", temp);
328 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_10, &temp, 1);
329 dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_10 = 0x%x\n", temp);
330 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_11, &temp, 1);
331 dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_11 = 0x%x\n", temp);
332
333 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGVAL_IRQ]);
334 dev_dbg(pm8058_chg.dev, "CHGVAL_IRQ = %d\n", temp2);
335
336 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGINVAL_IRQ]);
337 dev_dbg(pm8058_chg.dev, "CHGINVAL_IRQ = %d\n", temp2);
338
339 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VBATDET_LOW_IRQ]);
340 dev_dbg(pm8058_chg.dev, "VBATDET_LOW_IRQ= %d\n", temp2);
341
342 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VCP_IRQ]);
343 dev_dbg(pm8058_chg.dev, "VCP_IRQ= %d\n", temp2);
344
345 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGILIM_IRQ]);
346 dev_dbg(pm8058_chg.dev, "CHGILIM_IRQ= %d\n", temp2);
347
348 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[ATC_DONE_IRQ]);
349 dev_dbg(pm8058_chg.dev, "ATC_DONE_IRQ= %d\n", temp2);
350
351 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[ATCFAIL_IRQ]);
352 dev_dbg(pm8058_chg.dev, "ATCFAIL_IRQ= %d\n", temp2);
353
354 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[AUTO_CHGDONE_IRQ]);
355 dev_dbg(pm8058_chg.dev, "AUTO_CHGDONE_IRQ= %d\n", temp2);
356
357 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[AUTO_CHGFAIL_IRQ]);
358 dev_dbg(pm8058_chg.dev, "AUTO_CHGFAIL_IRQ= %d\n", temp2);
359
360 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGSTATE_IRQ]);
361 dev_dbg(pm8058_chg.dev, "CHGSTATE_IRQ= %d\n", temp2);
362
363 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[FASTCHG_IRQ]);
364 dev_dbg(pm8058_chg.dev, "FASTCHG_IRQ= %d\n", temp2);
365
366 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHG_END_IRQ]);
367 dev_dbg(pm8058_chg.dev, "CHG_END_IRQ= %d\n", temp2);
368
369 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ]);
370 dev_dbg(pm8058_chg.dev, "BATTTEMP_IRQ= %d\n", temp2);
371
372 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGHOT_IRQ]);
373 dev_dbg(pm8058_chg.dev, "CHGHOT_IRQ= %d\n", temp2);
374
375 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGTLIMIT_IRQ]);
376 dev_dbg(pm8058_chg.dev, "CHGTLIMIT_IRQ= %d\n", temp2);
377
378 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHG_GONE_IRQ]);
379 dev_dbg(pm8058_chg.dev, "CHG_GONE_IRQ= %d\n", temp2);
380
381 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VCPMAJOR_IRQ]);
382 dev_dbg(pm8058_chg.dev, "VCPMAJOR_IRQ= %d\n", temp2);
383
384 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VBATDET_IRQ]);
385 dev_dbg(pm8058_chg.dev, "VBATDET_IRQ= %d\n", temp2);
386
387 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATFET_IRQ]);
388 dev_dbg(pm8058_chg.dev, "BATFET_IRQ= %d\n", temp2);
389
390 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ]);
391 dev_dbg(pm8058_chg.dev, "BATT_REPLACE_IRQ= %d\n", temp2);
392
393 temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ]);
394 dev_dbg(pm8058_chg.dev, "BATTCONNECT_IRQ= %d\n", temp2);
395}
396#else
397static inline void __dump_chg_regs(void)
398{
399}
400#endif
401
402/* SSBI register access helper functions */
403static int pm_chg_suspend(int value)
404{
405 u8 temp;
406 int ret;
407
408 ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
409 if (ret)
410 return ret;
411 if (value)
412 temp |= BIT(CHG_USB_SUSPEND);
413 else
414 temp &= ~BIT(CHG_USB_SUSPEND);
415
416 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
417}
418
419static int pm_chg_auto_disable(int value)
420{
421 u8 temp;
422 int ret;
423
424 ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
425 if (ret)
426 return ret;
427 if (value)
428 temp |= BIT(CHARGE_AUTO_DIS);
429 else
430 temp &= ~BIT(CHARGE_AUTO_DIS);
431
432 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
433}
434
435static int pm_chg_batt_temp_disable(int value)
436{
437 u8 temp;
438 int ret;
439
440 ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
441 if (ret)
442 return ret;
443 if (value)
444 temp |= BIT(CHG_BATT_TEMP_DIS);
445 else
446 temp &= ~BIT(CHG_BATT_TEMP_DIS);
447
448 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
449}
450
451static int pm_chg_vbatdet_set(int voltage)
452{
453 u8 temp;
454 int diff;
455
456 diff = (voltage - PM8058_CHG_V_MIN_MV);
457 if (diff < 0) {
458 dev_warn(pm8058_chg.dev, "%s bad mV=%d asked to set\n",
459 __func__, voltage);
460 return -EINVAL;
461 }
462
463 temp = diff / PM8058_CHG_V_STEP_MV;
464 dev_dbg(pm8058_chg.dev, "%s voltage=%d setting %02x\n", __func__,
465 voltage, temp);
466 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_VBAT_DET, &temp, 1);
467}
468
469static int pm_chg_imaxsel_set(int chg_current)
470{
471 u8 temp;
472 int diff;
473
474 diff = chg_current - PM8058_CHG_I_MIN_MA;
475 if (diff < 0) {
476 dev_warn(pm8058_chg.dev, "%s bad mA=%d asked to set\n",
477 __func__, chg_current);
478 return -EINVAL;
479 }
480 temp = diff / PM8058_CHG_I_STEP_MA;
481 /* make sure we arent writing more than 5 bits of data */
482 if (temp > 31) {
483 dev_warn(pm8058_chg.dev, "%s max mA=1500 requested mA=%d\n",
484 __func__, chg_current);
485 temp = 31;
486 }
487 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_IMAX, &temp, 1);
488}
489
490#define PM8058_CHG_VMAX_MIN 3300
491#define PM8058_CHG_VMAX_MAX 5500
492static int pm_chg_vmaxsel_set(int voltage)
493{
494 u8 temp;
495
496 if (voltage < PM8058_CHG_VMAX_MIN || voltage > PM8058_CHG_VMAX_MAX) {
497 dev_warn(pm8058_chg.dev, "%s bad mV=%d asked to set\n",
498 __func__, voltage);
499 return -EINVAL;
500 }
501 temp = (voltage - PM8058_CHG_V_MIN_MV) / PM8058_CHG_V_STEP_MV;
502 dev_dbg(pm8058_chg.dev, "%s mV=%d setting %02x\n", __func__, voltage,
503 temp);
504 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_VMAX_SEL, &temp, 1);
505}
506
507static int pm_chg_failed_clear(int value)
508{
509 u8 temp;
510 int ret;
511
512 ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
513 if (ret)
514 return ret;
515 if (value)
516 temp |= BIT(CHG_FAILED_CLEAR);
517 else
518 temp &= ~BIT(CHG_FAILED_CLEAR);
519 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
520}
521
522static int pm_chg_iterm_set(int chg_current)
523{
524 u8 temp;
525
526 temp = (chg_current / PM8058_CHG_I_TERM_STEP_MA) - 1;
527 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_ITERM, &temp, 1);
528}
529
530static int pm_chg_tchg_set(int minutes)
531{
532 u8 temp;
533
534 temp = (minutes >> PM8058_CHG_T_TCHG_SHIFT) - 1;
535 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TCHG_MAX, &temp, 1);
536}
537
538static int pm_chg_ttrkl_set(int minutes)
539{
540 u8 temp;
541
542 temp = minutes - 1;
543 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TTRKL_MAX, &temp, 1);
544}
545
546static int pm_chg_enum_done_enable(int value)
547{
548 u8 temp;
549 int ret;
550
551 ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
552 if (ret)
553 return ret;
554 if (value)
555 temp |= BIT(ENUM_DONE);
556 else
557 temp &= ~BIT(ENUM_DONE);
558
559 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
560}
561
562static uint32_t get_fsm_state(void)
563{
564 u8 temp;
565
566 temp = 0x00;
567 pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
568 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
569 return (uint32_t)temp;
570}
571
572static int get_fsm_status(void *data, u64 * val)
573{
574 *val = get_fsm_state();
575 return 0;
576}
577
Abhijeet Dharmapurikarf734c672011-08-11 10:20:27 -0700578enum pmic8058_chg_state pmic8058_get_fsm_state(void)
579{
580 if (!pm8058_chg.inited) {
581 pr_err("%s: called when not inited\n", __func__);
582 return -EINVAL;
583 }
584
585 return get_fsm_state();
586}
587
Abhijeet Dharmapurikar0758e1e2011-07-14 18:11:41 -0700588static int pm_chg_disable(int value)
589{
590 u8 temp;
591 int ret;
592
593 ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
594 if (ret)
595 return ret;
596 if (value)
597 temp |= BIT(CHG_CHARGE_DIS);
598 else
599 temp &= ~BIT(CHG_CHARGE_DIS);
600
601 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
602}
603
604static void pm8058_start_system_current(struct msm_hardware_charger *hw_chg,
605 int max_current)
606{
607 int ret = 0;
608
609 if (pm8058_chg.disabled)
610 return;
611
612 ret = pm_chg_imaxsel_set(max_current);
613 ret |= pm_chg_enum_done_enable(1);
614 ret |= pm_chg_disable(0);
615 if (ret)
616 pr_err("%s: failed to turn on system power err=%d",
617 __func__, ret);
618}
619
620static void pm8058_stop_system_current(struct msm_hardware_charger *hw_chg)
621{
622 int ret = 0;
623
624 ret = pm_chg_enum_done_enable(0);
625 ret |= pm_chg_disable(1);
626 if (ret)
627 pr_err("%s: failed to turn off system power err=%d",
628 __func__, ret);
629}
630
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700631static int __pm8058_start_charging(int chg_current, int termination_current,
632 int time)
633{
634 int ret = 0;
635
636 if (pm8058_chg.disabled)
637 goto out;
638
639 dev_info(pm8058_chg.dev, "%s %dmA %dmin\n",
640 __func__, chg_current, time);
641
642 ret = pm_chg_auto_disable(1);
643 if (ret)
644 goto out;
645
646 ret = pm_chg_suspend(0);
647 if (ret)
648 goto out;
649
650 ret = pm_chg_imaxsel_set(chg_current);
651 if (ret)
652 goto out;
653
654 ret = pm_chg_failed_clear(1);
655 if (ret)
656 goto out;
657
658 ret = pm_chg_iterm_set(termination_current);
659 if (ret)
660 goto out;
661
662 ret = pm_chg_tchg_set(time);
663 if (ret)
664 goto out;
665
666 ret = pm_chg_ttrkl_set(AUTO_CHARGING_TRICKLE_TIME_MINUTES);
667 if (ret)
668 goto out;
669
670 ret = pm_chg_batt_temp_disable(0);
671 if (ret)
672 goto out;
673
674 if (pm8058_chg.voter == NULL)
675 pm8058_chg.voter = msm_xo_get(MSM_XO_TCXO_D1, "pm8058_charger");
676 msm_xo_mode_vote(pm8058_chg.voter, MSM_XO_MODE_ON);
677
678 ret = pm_chg_enum_done_enable(1);
679 if (ret)
680 goto out;
681
682 wmb();
683
684 ret = pm_chg_auto_disable(0);
685 if (ret)
686 goto out;
687
688 /* wait for the enable to update interrupt status*/
689 msleep(20);
690
691 pm8058_chg_enable_irq(AUTO_CHGFAIL_IRQ);
692 pm8058_chg_enable_irq(CHGHOT_IRQ);
693 pm8058_chg_enable_irq(AUTO_CHGDONE_IRQ);
694 pm8058_chg_enable_irq(CHG_END_IRQ);
695 pm8058_chg_enable_irq(CHGSTATE_IRQ);
696
697out:
698 return ret;
699}
700
701static void chg_done_cleanup(void)
702{
703 dev_info(pm8058_chg.dev, "%s notify pm8058 charging completion"
704 "\n", __func__);
705
706 pm8058_chg_disable_irq(AUTO_CHGDONE_IRQ);
707 cancel_delayed_work_sync(&pm8058_chg.veoc_begin_work);
708 cancel_delayed_work_sync(&pm8058_chg.check_vbat_low_work);
709
710 pm8058_chg_disable_irq(CHG_END_IRQ);
711
712 pm8058_chg_disable_irq(VBATDET_LOW_IRQ);
713 pm8058_chg_disable_irq(VBATDET_IRQ);
714 pm8058_chg.waiting_for_veoc = 0;
715 pm8058_chg.waiting_for_topoff = 0;
716
717 pm_chg_auto_disable(1);
718
719 msm_charger_notify_event(&usb_hw_chg, CHG_DONE_EVENT);
720}
721
722static void chg_done_check_work(struct work_struct *work)
723{
724 chg_done_cleanup();
725}
726
727static void charging_check_work(struct work_struct *work)
728{
729 uint32_t fsm_state = get_fsm_state();
730 int rc;
731
732 switch (fsm_state) {
733 /* We're charging, so disarm alarm */
Abhijeet Dharmapurikarf734c672011-08-11 10:20:27 -0700734 case PMIC8058_CHG_STATE_ATC:
735 case PMIC8058_CHG_STATE_FAST_CHG:
736 case PMIC8058_CHG_STATE_TRKL_CHG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737 rc = pm8058_batt_alarm_state_set(0, 0);
738 if (rc)
739 dev_err(pm8058_chg.dev,
740 "%s: unable to set alarm state\n", __func__);
741 break;
742 default:
743 /* Still not charging, so update driver state */
744 chg_done_cleanup();
745 break;
746 };
747}
748
749static int pm8058_start_charging(struct msm_hardware_charger *hw_chg,
750 int chg_voltage, int chg_current)
751{
752 int vbat_higher_than_vbatdet;
753 int ret = 0;
754
755 cancel_delayed_work_sync(&pm8058_chg.charging_check_work);
756
757 /*
758 * adjust the max current for PC USB connection - set the higher limit
759 * to 450 and make sure we never cross it
760 */
761 if (chg_current == 500)
762 chg_current = 450;
Terence Hampson13163082011-08-09 10:17:06 -0400763
764 if (hw_chg->type == CHG_TYPE_AC && chg_data.max_source_current)
765 chg_current = chg_data.max_source_current;
766
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700767 pm8058_chg.current_charger_current = chg_current;
768 pm8058_chg_enable_irq(FASTCHG_IRQ);
769
770 ret = pm_chg_vmaxsel_set(chg_voltage);
771 if (ret)
772 goto out;
773
774 /* set vbat to CC to CV threshold */
775 ret = pm_chg_vbatdet_set(AUTO_CHARGING_VBATDET);
776 if (ret)
777 goto out;
778
779 pm8058_chg.vbatdet = AUTO_CHARGING_VBATDET;
780 /*
781 * get the state of vbat and if it is higher than
782 * AUTO_CHARGING_VBATDET we start the veoc start timer
783 * else wait for the voltage to go to AUTO_CHARGING_VBATDET
784 * and then start the 90 min timer
785 */
786 vbat_higher_than_vbatdet =
787 pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VBATDET_IRQ]);
788 if (vbat_higher_than_vbatdet) {
789 /*
790 * we are in constant voltage phase of charging
791 * IEOC should happen withing 90 mins of this instant
792 * else we enable VEOC
793 */
794 dev_info(pm8058_chg.dev, "%s begin veoc timer\n", __func__);
795 schedule_delayed_work(&pm8058_chg.veoc_begin_work,
796 round_jiffies_relative(msecs_to_jiffies
797 (AUTO_CHARGING_VEOC_BEGIN_TIME_MS)));
798 } else
799 pm8058_chg_enable_irq(VBATDET_IRQ);
800
801 ret = __pm8058_start_charging(chg_current, AUTO_CHARGING_IEOC_ITERM,
802 AUTO_CHARGING_FAST_TIME_MAX_MINUTES);
803 pm8058_chg.current_charger_current = chg_current;
804
805 /*
806 * We want to check the FSM state to verify we're charging. We must
807 * wait before doing this to allow the VBATDET to settle. The worst
808 * case for this is two seconds. The batt alarm does not have this
809 * delay.
810 */
811 schedule_delayed_work(&pm8058_chg.charging_check_work,
812 round_jiffies_relative(msecs_to_jiffies
813 (AUTO_CHARGING_VBATDET_DEBOUNCE_TIME_MS)));
814
815out:
816 return ret;
817}
818
819static void veoc_begin_work(struct work_struct *work)
820{
821 /* we have been doing CV for 90mins with no signs of IEOC
822 * start checking for VEOC in addition with 16min charges*/
823 dev_info(pm8058_chg.dev, "%s begin veoc detection\n", __func__);
824 pm8058_chg.waiting_for_veoc = 1;
825 /*
826 * disable VBATDET irq we dont need it unless we are at the end of
827 * charge cycle
828 */
829 pm8058_chg_disable_irq(VBATDET_IRQ);
830 __pm8058_start_charging(pm8058_chg.current_charger_current,
831 AUTO_CHARGING_VEOC_ITERM,
832 AUTO_CHARGING_VEOC_TCHG);
833}
834
835static void vbat_low_work(struct work_struct *work)
836{
837 /*
838 * It has been one minute and the battery still holds voltage
839 * start the final topoff - charging is almost done
840 */
841 dev_info(pm8058_chg.dev, "%s vbatt maintains for a minute"
842 "starting topoff\n", __func__);
843 pm8058_chg.waiting_for_veoc = 0;
844 pm8058_chg.waiting_for_topoff = 1;
845 pm8058_chg_disable_irq(VBATDET_LOW_IRQ);
846 pm8058_chg_disable_irq(VBATDET_IRQ);
847 __pm8058_start_charging(pm8058_chg.current_charger_current,
848 AUTO_CHARGING_VEOC_ITERM,
849 AUTO_CHARGING_VEOC_TCHG_FINAL_CYCLE);
850}
851
852
853static irqreturn_t pm8058_chg_chgval_handler(int irq, void *dev_id)
854{
855 u8 old, temp;
856 int ret;
857
858 if (is_chg_plugged_in()) { /* this debounces it */
859 if (!pm8058_chg.present) {
860 msm_charger_notify_event(&usb_hw_chg,
861 CHG_INSERTED_EVENT);
862 pm8058_chg.present = 1;
863 }
864 } else {
865 if (pm8058_chg.present) {
866 ret = pm8058_read(pm8058_chg.pm_chip,
867 PM8058_OVP_TEST_REG,
868 &old, 1);
869 temp = old | BIT(FORCE_OVP_OFF);
870 ret = pm8058_write(pm8058_chg.pm_chip,
871 PM8058_OVP_TEST_REG,
872 &temp, 1);
873 temp = 0xFC;
874 ret = pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST,
875 &temp, 1);
876 /* 10 ms sleep is for the VCHG to discharge */
877 msleep(10);
878 temp = 0xF0;
879 ret = pm8058_write(pm8058_chg.pm_chip,
880 PM8058_CHG_TEST,
881 &temp, 1);
882 ret = pm8058_write(pm8058_chg.pm_chip,
883 PM8058_OVP_TEST_REG,
884 &old, 1);
885
886 pm_chg_enum_done_enable(0);
887 pm_chg_auto_disable(1);
888 msm_charger_notify_event(&usb_hw_chg,
889 CHG_REMOVED_EVENT);
890 pm8058_chg.present = 0;
891 }
892 }
893
894 return IRQ_HANDLED;
895}
896
897static irqreturn_t pm8058_chg_chginval_handler(int irq, void *dev_id)
898{
899 u8 old, temp;
900 int ret;
901
902 if (pm8058_chg.present) {
903 pm8058_chg_disable_irq(CHGINVAL_IRQ);
904
905 pm_chg_enum_done_enable(0);
906 pm_chg_auto_disable(1);
907 ret = pm8058_read(pm8058_chg.pm_chip,
908 PM8058_OVP_TEST_REG, &old, 1);
909 temp = old | BIT(FORCE_OVP_OFF);
910 ret = pm8058_write(pm8058_chg.pm_chip,
911 PM8058_OVP_TEST_REG, &temp, 1);
912 temp = 0xFC;
913 ret = pm8058_write(pm8058_chg.pm_chip,
914 PM8058_CHG_TEST, &temp, 1);
915 /* 10 ms sleep is for the VCHG to discharge */
916 msleep(10);
917 temp = 0xF0;
918 ret = pm8058_write(pm8058_chg.pm_chip,
919 PM8058_CHG_TEST, &temp, 1);
920 ret = pm8058_write(pm8058_chg.pm_chip,
921 PM8058_OVP_TEST_REG, &old, 1);
922
923 if (!is_chg_plugged_in()) {
924 msm_charger_notify_event(&usb_hw_chg,
925 CHG_REMOVED_EVENT);
926 pm8058_chg.present = 0;
927 } else {
928 /* was a fake */
929 pm8058_chg_enable_irq(CHGINVAL_IRQ);
930 }
931 }
932
933 return IRQ_HANDLED;
934}
935
936static irqreturn_t pm8058_chg_auto_chgdone_handler(int irq, void *dev_id)
937{
938 dev_info(pm8058_chg.dev, "%s waiting a sec to confirm\n",
939 __func__);
Abhijeet Dharmapurikar2dae2392011-07-14 18:31:28 -0700940 pm8058_chg_disable_irq(AUTO_CHGDONE_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700941 pm8058_chg_disable_irq(VBATDET_IRQ);
942 if (!delayed_work_pending(&pm8058_chg.chg_done_check_work)) {
943 schedule_delayed_work(&pm8058_chg.chg_done_check_work,
944 round_jiffies_relative(msecs_to_jiffies
945 (AUTO_CHARGING_DONE_CHECK_TIME_MS)));
946 }
947 return IRQ_HANDLED;
948}
949
950/* can only happen with the pmic charger when it has been charing
951 * for either 16 mins wating for VEOC or 32 mins for topoff
952 * without a IEOC indication */
953static irqreturn_t pm8058_chg_auto_chgfail_handler(int irq, void *dev_id)
954{
955 pm8058_chg_disable_irq(AUTO_CHGFAIL_IRQ);
956
957 if (pm8058_chg.waiting_for_topoff == 1) {
958 dev_info(pm8058_chg.dev, "%s topoff done, charging done\n",
959 __func__);
960 pm8058_chg.waiting_for_topoff = 0;
961 /* notify we are done charging */
962 msm_charger_notify_event(&usb_hw_chg, CHG_DONE_EVENT);
963 } else {
964 /* start one minute timer and monitor VBATDET_LOW */
965 dev_info(pm8058_chg.dev, "%s monitoring vbat_low for a"
966 "minute\n", __func__);
967 schedule_delayed_work(&pm8058_chg.check_vbat_low_work,
968 round_jiffies_relative(msecs_to_jiffies
969 (AUTO_CHARGING_VEOC_VBAT_LOW_CHECK_TIME_MS)));
970
971 /* note we are waiting on veoc */
972 pm8058_chg.waiting_for_veoc = 1;
973
974 pm_chg_vbatdet_set(AUTO_CHARGING_VEOC_VBATDET);
975 pm8058_chg.vbatdet = AUTO_CHARGING_VEOC_VBATDET;
976 pm8058_chg_enable_irq(VBATDET_LOW_IRQ);
977 }
978 return IRQ_HANDLED;
979}
980
981static irqreturn_t pm8058_chg_chgstate_handler(int irq, void *dev_id)
982{
983 u8 temp;
984
985 temp = 0x00;
986 if (!pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1)) {
987 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
988 dev_dbg(pm8058_chg.dev, "%s state=%d\n", __func__, temp);
989 }
990 return IRQ_HANDLED;
991}
992
993static irqreturn_t pm8058_chg_fastchg_handler(int irq, void *dev_id)
994{
995 pm8058_chg_disable_irq(FASTCHG_IRQ);
996
997 /* we have begun the fast charging state */
998 dev_info(pm8058_chg.dev, "%s begin fast charging"
999 , __func__);
1000 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_BEGIN_FAST_CHARGING);
1001 return IRQ_HANDLED;
1002}
1003
1004static irqreturn_t pm8058_chg_batttemp_handler(int irq, void *dev_id)
1005{
1006 int ret;
1007
1008 /* we could get temperature
1009 * interrupt when the battery is plugged out
1010 */
1011 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ]);
1012 if (ret) {
1013 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_REMOVED);
1014 } else {
1015 /* read status to determine we are inrange or outofrange */
1016 ret =
1017 pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ]);
1018 if (ret)
1019 msm_charger_notify_event(&usb_hw_chg,
1020 CHG_BATT_TEMP_OUTOFRANGE);
1021 else
1022 msm_charger_notify_event(&usb_hw_chg,
1023 CHG_BATT_TEMP_INRANGE);
1024 }
1025
1026 return IRQ_HANDLED;
1027}
1028
1029static irqreturn_t pm8058_chg_vbatdet_handler(int irq, void *dev_id)
1030{
1031 int ret;
1032
1033 /* settling time */
1034 msleep(20);
1035 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VBATDET_IRQ]);
1036
1037 if (ret) {
1038 if (pm8058_chg.vbatdet == AUTO_CHARGING_VBATDET
1039 && !delayed_work_pending(&pm8058_chg.veoc_begin_work)) {
1040 /*
1041 * we are in constant voltage phase of charging
1042 * IEOC should happen withing 90 mins of this instant
1043 * else we enable VEOC
1044 */
1045 dev_info(pm8058_chg.dev, "%s entered constant voltage"
1046 "begin veoc timer\n", __func__);
1047 schedule_delayed_work(&pm8058_chg.veoc_begin_work,
1048 round_jiffies_relative
1049 (msecs_to_jiffies
1050 (AUTO_CHARGING_VEOC_BEGIN_TIME_MS)));
1051 }
1052 } else {
1053 if (pm8058_chg.vbatdet == AUTO_CHARGING_VEOC_VBATDET) {
1054 cancel_delayed_work_sync(
1055 &pm8058_chg.check_vbat_low_work);
1056
1057 if (pm8058_chg.waiting_for_topoff
1058 || pm8058_chg.waiting_for_veoc) {
1059 /*
1060 * the battery dropped its voltage below 4100
1061 * around a minute charge the battery for 16
1062 * mins and check vbat again for a minute
1063 */
1064 dev_info(pm8058_chg.dev, "%s batt dropped vlt"
1065 "within a minute\n", __func__);
1066 pm8058_chg.waiting_for_topoff = 0;
1067 pm8058_chg.waiting_for_veoc = 1;
1068 pm8058_chg_disable_irq(VBATDET_IRQ);
1069 __pm8058_start_charging(pm8058_chg.
1070 current_charger_current,
1071 AUTO_CHARGING_VEOC_ITERM,
1072 AUTO_CHARGING_VEOC_TCHG);
1073 }
1074 }
1075 }
1076 return IRQ_HANDLED;
1077}
1078
1079static irqreturn_t pm8058_chg_batt_replace_handler(int irq, void *dev_id)
1080{
1081 int ret;
1082
1083 pm8058_chg_disable_irq(BATT_REPLACE_IRQ);
1084 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ]);
1085 if (ret) {
1086 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_INSERTED);
1087 /*
1088 * battery is present enable batt removal
1089 * and batt temperatture interrupt
1090 */
1091 pm8058_chg_enable_irq(BATTCONNECT_IRQ);
1092 }
1093 return IRQ_HANDLED;
1094}
1095
1096static irqreturn_t pm8058_chg_battconnect_handler(int irq, void *dev_id)
1097{
1098 int ret;
1099
1100 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ]);
1101 if (ret) {
1102 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_REMOVED);
1103 } else {
1104 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_INSERTED);
1105 pm8058_chg_enable_irq(BATTTEMP_IRQ);
1106 }
1107
1108 return IRQ_HANDLED;
1109}
1110
1111static int get_rt_status(void *data, u64 * val)
1112{
1113 int i = (int)data;
1114 int ret;
1115
1116 ret = pm_chg_get_rt_status(i);
1117 *val = ret;
1118 return 0;
1119}
1120
1121DEFINE_SIMPLE_ATTRIBUTE(rt_fops, get_rt_status, NULL, "%llu\n");
1122DEFINE_SIMPLE_ATTRIBUTE(fsm_fops, get_fsm_status, NULL, "%llu\n");
1123
1124static void free_irqs(void)
1125{
1126 int i;
1127
1128 for (i = 0; i < PMIC_CHG_MAX_INTS; i++)
1129 if (pm8058_chg.pmic_chg_irq[i]) {
1130 free_irq(pm8058_chg.pmic_chg_irq[i], NULL);
1131 pm8058_chg.pmic_chg_irq[i] = 0;
1132 }
1133}
1134
1135static int __devinit request_irqs(struct platform_device *pdev)
1136{
1137 struct resource *res;
1138 int ret;
1139
1140 ret = 0;
1141 bitmap_fill(pm8058_chg.enabled_irqs, PMIC_CHG_MAX_INTS);
1142
1143 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "CHGVAL");
1144 if (res == NULL) {
1145 dev_err(pm8058_chg.dev,
1146 "%s:couldnt find resource CHGVAL\n", __func__);
1147 goto err_out;
1148 } else {
1149 ret = request_threaded_irq(res->start, NULL,
1150 pm8058_chg_chgval_handler,
1151 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1152 res->name, NULL);
1153 if (ret < 0) {
1154 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1155 __func__, res->start, ret);
1156 goto err_out;
1157 } else {
1158 pm8058_chg.pmic_chg_irq[CHGVAL_IRQ] = res->start;
1159 pm8058_chg_disable_irq(CHGVAL_IRQ);
1160 enable_irq_wake(pm8058_chg.pmic_chg_irq[CHGVAL_IRQ]);
1161 }
1162 }
1163
1164 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "CHGINVAL");
1165 if (res == NULL) {
1166 dev_err(pm8058_chg.dev,
1167 "%s:couldnt find resource CHGINVAL\n", __func__);
1168 goto err_out;
1169 } else {
1170 ret = request_threaded_irq(res->start, NULL,
1171 pm8058_chg_chginval_handler,
1172 IRQF_TRIGGER_RISING, res->name, NULL);
1173 if (ret < 0) {
1174 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1175 __func__, res->start, ret);
1176 goto err_out;
1177 } else {
1178 pm8058_chg.pmic_chg_irq[CHGINVAL_IRQ] = res->start;
1179 pm8058_chg_disable_irq(CHGINVAL_IRQ);
1180 }
1181 }
1182
1183 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1184 "AUTO_CHGDONE");
1185 if (res == NULL) {
1186 dev_err(pm8058_chg.dev,
1187 "%s:couldnt find resource AUTO_CHGDONE\n", __func__);
1188 goto err_out;
1189 } else {
1190 ret = request_threaded_irq(res->start, NULL,
1191 pm8058_chg_auto_chgdone_handler,
Abhijeet Dharmapurikar2dae2392011-07-14 18:31:28 -07001192 IRQF_TRIGGER_RISING,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001193 res->name, NULL);
1194 if (ret < 0) {
1195 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1196 __func__, res->start, ret);
1197 goto err_out;
1198 } else {
1199 pm8058_chg.pmic_chg_irq[AUTO_CHGDONE_IRQ] = res->start;
1200 pm8058_chg_disable_irq(AUTO_CHGDONE_IRQ);
1201 }
1202 }
1203
1204 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1205 "AUTO_CHGFAIL");
1206 if (res == NULL) {
1207 dev_err(pm8058_chg.dev,
1208 "%s:couldnt find resource AUTO_CHGFAIL\n", __func__);
1209 goto err_out;
1210 } else {
1211 ret = request_threaded_irq(res->start, NULL,
1212 pm8058_chg_auto_chgfail_handler,
1213 IRQF_TRIGGER_RISING, res->name, NULL);
1214 if (ret < 0) {
1215 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1216 __func__, res->start, ret);
1217 goto err_out;
1218 } else {
1219 pm8058_chg.pmic_chg_irq[AUTO_CHGFAIL_IRQ] = res->start;
1220 pm8058_chg_disable_irq(AUTO_CHGFAIL_IRQ);
1221 }
1222 }
1223
1224 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "CHGSTATE");
1225 if (res == NULL) {
1226 dev_err(pm8058_chg.dev,
1227 "%s:couldnt find resource CHGSTATE\n", __func__);
1228 goto err_out;
1229 } else {
1230 ret = request_threaded_irq(res->start, NULL,
1231 pm8058_chg_chgstate_handler,
1232 IRQF_TRIGGER_RISING, res->name, NULL);
1233 if (ret < 0) {
1234 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1235 __func__, res->start, ret);
1236 goto err_out;
1237 } else {
1238 pm8058_chg.pmic_chg_irq[CHGSTATE_IRQ] = res->start;
1239 pm8058_chg_disable_irq(CHGSTATE_IRQ);
1240 }
1241 }
1242
1243 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "FASTCHG");
1244 if (res == NULL) {
1245 dev_err(pm8058_chg.dev,
1246 "%s:couldnt find resource FASTCHG\n", __func__);
1247 goto err_out;
1248 } else {
1249 ret = request_threaded_irq(res->start, NULL,
1250 pm8058_chg_fastchg_handler,
1251 IRQF_TRIGGER_RISING, res->name, NULL);
1252 if (ret < 0) {
1253 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1254 __func__, res->start, ret);
1255 goto err_out;
1256 } else {
1257 pm8058_chg.pmic_chg_irq[FASTCHG_IRQ] = res->start;
1258 pm8058_chg_disable_irq(FASTCHG_IRQ);
1259 }
1260 }
1261
1262 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "BATTTEMP");
1263 if (res == NULL) {
1264 dev_err(pm8058_chg.dev,
1265 "%s:couldnt find resource CHG_END\n", __func__);
1266 goto err_out;
1267 } else {
1268 ret = request_threaded_irq(res->start, NULL,
1269 pm8058_chg_batttemp_handler,
1270 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1271 res->name, NULL);
1272 if (ret < 0) {
1273 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1274 __func__, res->start, ret);
1275 goto err_out;
1276 } else {
1277 pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ] = res->start;
1278 pm8058_chg_disable_irq(BATTTEMP_IRQ);
1279 }
1280 }
1281
1282 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1283 "BATT_REPLACE");
1284 if (res == NULL) {
1285 dev_err(pm8058_chg.dev,
1286 "%s:couldnt find resource BATT_REPLACE\n", __func__);
1287 goto err_out;
1288 } else {
1289 ret = request_threaded_irq(res->start, NULL,
1290 pm8058_chg_batt_replace_handler,
1291 IRQF_TRIGGER_RISING, res->name, NULL);
1292 if (ret < 0) {
1293 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1294 __func__, res->start, ret);
1295 goto err_out;
1296 } else {
1297 pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ] = res->start;
1298 pm8058_chg_disable_irq(BATT_REPLACE_IRQ);
1299 }
1300 }
1301
1302 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "BATTCONNECT");
1303 if (res == NULL) {
1304 dev_err(pm8058_chg.dev,
1305 "%s:couldnt find resource BATTCONNECT\n", __func__);
1306 goto err_out;
1307 } else {
1308 ret = request_threaded_irq(res->start, NULL,
1309 pm8058_chg_battconnect_handler,
1310 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1311 res->name, NULL);
1312 if (ret < 0) {
1313 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1314 __func__, res->start, ret);
1315 goto err_out;
1316 } else {
1317 pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ] = res->start;
1318 pm8058_chg_disable_irq(BATTCONNECT_IRQ);
1319 }
1320 }
1321
1322 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "VBATDET");
1323 if (res == NULL) {
1324 dev_err(pm8058_chg.dev,
1325 "%s:couldnt find resource VBATDET\n", __func__);
1326 goto err_out;
1327 } else {
1328 ret = request_threaded_irq(res->start, NULL,
1329 pm8058_chg_vbatdet_handler,
1330 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1331 res->name, NULL);
1332 if (ret < 0) {
1333 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1334 __func__, res->start, ret);
1335 goto err_out;
1336 } else {
1337 pm8058_chg.pmic_chg_irq[VBATDET_IRQ] = res->start;
1338 pm8058_chg_disable_irq(VBATDET_IRQ);
1339 }
1340 }
1341
1342 return 0;
1343
1344err_out:
1345 free_irqs();
1346 return -EINVAL;
1347}
1348
1349static int pm8058_get_charge_batt(void)
1350{
1351 u8 temp;
1352 int rc;
1353
1354 rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
1355 if (rc)
1356 return rc;
1357
1358 temp &= BIT(CHG_CHARGE_BAT);
1359 if (temp)
1360 temp = 1;
1361 return temp;
1362}
1363EXPORT_SYMBOL(pm8058_get_charge_batt);
1364
1365static int pm8058_set_charge_batt(int on)
1366{
1367 u8 temp;
1368 int rc;
1369
1370 rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
1371 if (rc)
1372 return rc;
1373 if (on)
1374 temp |= BIT(CHG_CHARGE_BAT);
1375 else
1376 temp &= ~BIT(CHG_CHARGE_BAT);
1377
1378 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
1379
1380}
1381EXPORT_SYMBOL(pm8058_set_charge_batt);
1382
1383static int get_charge_batt(void *data, u64 * val)
1384{
1385 int ret;
1386
1387 ret = pm8058_get_charge_batt();
1388 if (ret < 0)
1389 return ret;
1390
1391 *val = ret;
1392 return 0;
1393}
1394
1395static int set_charge_batt(void *data, u64 val)
1396{
1397 return pm8058_set_charge_batt(val);
1398}
1399DEFINE_SIMPLE_ATTRIBUTE(fet_fops, get_charge_batt, set_charge_batt, "%llu\n");
1400
1401static void pm8058_chg_determine_initial_state(void)
1402{
1403 if (is_chg_plugged_in()) {
1404 pm8058_chg.present = 1;
1405 msm_charger_notify_event(&usb_hw_chg, CHG_INSERTED_EVENT);
1406 dev_info(pm8058_chg.dev, "%s charger present\n", __func__);
1407 } else {
1408 pm8058_chg.present = 0;
1409 dev_info(pm8058_chg.dev, "%s charger absent\n", __func__);
1410 }
1411 pm8058_chg_enable_irq(CHGVAL_IRQ);
1412}
1413
1414static int pm8058_stop_charging(struct msm_hardware_charger *hw_chg)
1415{
1416 int ret;
1417
1418 dev_info(pm8058_chg.dev, "%s stopping charging\n", __func__);
Abhijeet Dharmapurikar2dae2392011-07-14 18:31:28 -07001419
1420 /* disable the irqs enabled while charging */
1421 pm8058_chg_disable_irq(AUTO_CHGFAIL_IRQ);
1422 pm8058_chg_disable_irq(CHGHOT_IRQ);
1423 pm8058_chg_disable_irq(AUTO_CHGDONE_IRQ);
1424 pm8058_chg_disable_irq(FASTCHG_IRQ);
1425 pm8058_chg_disable_irq(CHG_END_IRQ);
1426 pm8058_chg_disable_irq(VBATDET_IRQ);
1427 pm8058_chg_disable_irq(VBATDET_LOW_IRQ);
1428
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001429 cancel_delayed_work_sync(&pm8058_chg.veoc_begin_work);
1430 cancel_delayed_work_sync(&pm8058_chg.check_vbat_low_work);
1431 cancel_delayed_work_sync(&pm8058_chg.chg_done_check_work);
1432 cancel_delayed_work_sync(&pm8058_chg.charging_check_work);
1433
1434 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[FASTCHG_IRQ]);
1435 if (ret == 1)
1436 pm_chg_suspend(1);
1437 else
1438 dev_err(pm8058_chg.dev,
1439 "%s called when not fast-charging\n", __func__);
1440
1441 pm_chg_failed_clear(1);
1442
1443 pm8058_chg.waiting_for_veoc = 0;
1444 pm8058_chg.waiting_for_topoff = 0;
1445
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001446 if (pm8058_chg.voter)
1447 msm_xo_mode_vote(pm8058_chg.voter, MSM_XO_MODE_OFF);
1448
1449 return 0;
1450}
1451
1452static int get_status(void *data, u64 * val)
1453{
1454 *val = pm8058_chg.current_charger_current;
1455 return 0;
1456}
1457
1458static int set_status(void *data, u64 val)
1459{
1460
1461 pm8058_chg.current_charger_current = val;
1462 if (pm8058_chg.current_charger_current)
1463 pm8058_start_charging(NULL,
1464 AUTO_CHARGING_VMAXSEL,
1465 pm8058_chg.current_charger_current);
1466 else
1467 pm8058_stop_charging(NULL);
1468 return 0;
1469}
1470DEFINE_SIMPLE_ATTRIBUTE(chg_fops, get_status, set_status, "%llu\n");
1471
1472static int set_disable_status_param(const char *val, struct kernel_param *kp)
1473{
1474 int ret;
1475
1476 ret = param_set_int(val, kp);
1477 if (ret)
1478 return ret;
1479
1480 if (pm8058_chg.inited && pm8058_chg.disabled) {
1481 /*
1482 * stop_charging is called during usb suspend
1483 * act as the usb is removed by disabling auto and enum
1484 */
1485 pm_chg_enum_done_enable(0);
1486 pm_chg_auto_disable(1);
1487 pm8058_stop_charging(NULL);
1488 }
1489 return 0;
1490}
1491module_param_call(disabled, set_disable_status_param, param_get_uint,
1492 &(pm8058_chg.disabled), 0644);
1493
1494static int pm8058_charging_switched(struct msm_hardware_charger *hw_chg)
1495{
1496 u8 temp;
1497
1498 temp = 0xA3;
1499 pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
1500 temp = 0x84;
1501 pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
1502 msleep(2);
1503 temp = 0x80;
1504 pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
1505 return 0;
1506}
1507
1508static int get_reg(void *data, u64 * val)
1509{
1510 int i = (int)data;
1511 int ret;
1512 u8 temp;
1513
1514 ret = pm8058_read(pm8058_chg.pm_chip, i, &temp, 1);
1515 if (ret)
1516 return -EAGAIN;
1517 *val = temp;
1518 return 0;
1519}
1520
1521static int set_reg(void *data, u64 val)
1522{
1523 int i = (int)data;
1524 int ret;
1525 u8 temp;
1526
1527 temp = (u8) val;
1528 ret = pm8058_write(pm8058_chg.pm_chip, i, &temp, 1);
1529 mb();
1530 if (ret)
1531 return -EAGAIN;
1532 return 0;
1533}
1534
1535DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "%llu\n");
1536
1537#ifdef CONFIG_DEBUG_FS
1538static void create_debugfs_entries(void)
1539{
1540 pm8058_chg.dent = debugfs_create_dir("pm8058_usb_chg", NULL);
1541
1542 if (IS_ERR(pm8058_chg.dent)) {
1543 pr_err("pmic charger couldnt create debugfs dir\n");
1544 return;
1545 }
1546
1547 debugfs_create_file("CHG_CNTRL", 0644, pm8058_chg.dent,
1548 (void *)PM8058_CHG_CNTRL, &reg_fops);
1549 debugfs_create_file("CHG_CNTRL_2", 0644, pm8058_chg.dent,
1550 (void *)PM8058_CHG_CNTRL_2, &reg_fops);
1551 debugfs_create_file("CHG_VMAX_SEL", 0644, pm8058_chg.dent,
1552 (void *)PM8058_CHG_VMAX_SEL, &reg_fops);
1553 debugfs_create_file("CHG_VBAT_DET", 0644, pm8058_chg.dent,
1554 (void *)PM8058_CHG_VBAT_DET, &reg_fops);
1555 debugfs_create_file("CHG_IMAX", 0644, pm8058_chg.dent,
1556 (void *)PM8058_CHG_IMAX, &reg_fops);
1557 debugfs_create_file("CHG_TRICKLE", 0644, pm8058_chg.dent,
1558 (void *)PM8058_CHG_TRICKLE, &reg_fops);
1559 debugfs_create_file("CHG_ITERM", 0644, pm8058_chg.dent,
1560 (void *)PM8058_CHG_ITERM, &reg_fops);
1561 debugfs_create_file("CHG_TTRKL_MAX", 0644, pm8058_chg.dent,
1562 (void *)PM8058_CHG_TTRKL_MAX, &reg_fops);
1563 debugfs_create_file("CHG_TCHG_MAX", 0644, pm8058_chg.dent,
1564 (void *)PM8058_CHG_TCHG_MAX, &reg_fops);
1565 debugfs_create_file("CHG_TEMP_THRESH", 0644, pm8058_chg.dent,
1566 (void *)PM8058_CHG_TEMP_THRESH, &reg_fops);
1567 debugfs_create_file("CHG_TEMP_REG", 0644, pm8058_chg.dent,
1568 (void *)PM8058_CHG_TEMP_REG, &reg_fops);
1569
1570 debugfs_create_file("FSM_STATE", 0644, pm8058_chg.dent, NULL,
1571 &fsm_fops);
1572
1573 debugfs_create_file("stop", 0644, pm8058_chg.dent, NULL,
1574 &chg_fops);
1575
1576 if (pm8058_chg.pmic_chg_irq[CHGVAL_IRQ])
1577 debugfs_create_file("CHGVAL", 0444, pm8058_chg.dent,
1578 (void *)pm8058_chg.pmic_chg_irq[CHGVAL_IRQ],
1579 &rt_fops);
1580
1581 if (pm8058_chg.pmic_chg_irq[CHGINVAL_IRQ])
1582 debugfs_create_file("CHGINVAL", 0444, pm8058_chg.dent, (void *)
1583 pm8058_chg.pmic_chg_irq[CHGINVAL_IRQ],
1584 &rt_fops);
1585 if (pm8058_chg.pmic_chg_irq[CHGILIM_IRQ])
1586 debugfs_create_file("CHGILIM", 0444, pm8058_chg.dent, (void *)
1587 pm8058_chg.pmic_chg_irq[CHGILIM_IRQ],
1588 &rt_fops);
1589 if (pm8058_chg.pmic_chg_irq[VCP_IRQ])
1590 debugfs_create_file("VCP", 0444, pm8058_chg.dent,
1591 (void *)pm8058_chg.pmic_chg_irq[VCP_IRQ],
1592 &rt_fops);
1593 if (pm8058_chg.pmic_chg_irq[ATC_DONE_IRQ])
1594 debugfs_create_file("ATC_DONE", 0444, pm8058_chg.dent, (void *)
1595 pm8058_chg.pmic_chg_irq[ATC_DONE_IRQ],
1596 &rt_fops);
1597 if (pm8058_chg.pmic_chg_irq[ATCFAIL_IRQ])
1598 debugfs_create_file("ATCFAIL", 0444, pm8058_chg.dent, (void *)
1599 pm8058_chg.pmic_chg_irq[ATCFAIL_IRQ],
1600 &rt_fops);
1601 if (pm8058_chg.pmic_chg_irq[AUTO_CHGDONE_IRQ])
1602 debugfs_create_file("AUTO_CHGDONE", 0444, pm8058_chg.dent,
1603 (void *)
1604 pm8058_chg.pmic_chg_irq[AUTO_CHGDONE_IRQ],
1605 &rt_fops);
1606 if (pm8058_chg.pmic_chg_irq[AUTO_CHGFAIL_IRQ])
1607 debugfs_create_file("AUTO_CHGFAIL", 0444, pm8058_chg.dent,
1608 (void *)
1609 pm8058_chg.pmic_chg_irq[AUTO_CHGFAIL_IRQ],
1610 &rt_fops);
1611 if (pm8058_chg.pmic_chg_irq[CHGSTATE_IRQ])
1612 debugfs_create_file("CHGSTATE", 0444, pm8058_chg.dent, (void *)
1613 pm8058_chg.pmic_chg_irq[CHGSTATE_IRQ],
1614 &rt_fops);
1615 if (pm8058_chg.pmic_chg_irq[FASTCHG_IRQ])
1616 debugfs_create_file("FASTCHG", 0444, pm8058_chg.dent, (void *)
1617 pm8058_chg.pmic_chg_irq[FASTCHG_IRQ],
1618 &rt_fops);
1619 if (pm8058_chg.pmic_chg_irq[CHG_END_IRQ])
1620 debugfs_create_file("CHG_END", 0444, pm8058_chg.dent, (void *)
1621 pm8058_chg.pmic_chg_irq[CHG_END_IRQ],
1622 &rt_fops);
1623 if (pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ])
1624 debugfs_create_file("BATTTEMP", 0444, pm8058_chg.dent, (void *)
1625 pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ],
1626 &rt_fops);
1627 if (pm8058_chg.pmic_chg_irq[CHGHOT_IRQ])
1628 debugfs_create_file("CHGHOT", 0444, pm8058_chg.dent,
1629 (void *)pm8058_chg.pmic_chg_irq[CHGHOT_IRQ],
1630 &rt_fops);
1631 if (pm8058_chg.pmic_chg_irq[CHGTLIMIT_IRQ])
1632 debugfs_create_file("CHGTLIMIT", 0444, pm8058_chg.dent, (void *)
1633 pm8058_chg.pmic_chg_irq[CHGTLIMIT_IRQ],
1634 &rt_fops);
1635 if (pm8058_chg.pmic_chg_irq[CHG_GONE_IRQ])
1636 debugfs_create_file("CHG_GONE", 0444, pm8058_chg.dent, (void *)
1637 pm8058_chg.pmic_chg_irq[CHG_GONE_IRQ],
1638 &rt_fops);
1639 if (pm8058_chg.pmic_chg_irq[VCPMAJOR_IRQ])
1640 debugfs_create_file("VCPMAJOR", 0444, pm8058_chg.dent, (void *)
1641 pm8058_chg.pmic_chg_irq[VCPMAJOR_IRQ],
1642 &rt_fops);
1643 if (pm8058_chg.pmic_chg_irq[BATFET_IRQ])
1644 debugfs_create_file("BATFET", 0444, pm8058_chg.dent,
1645 (void *)pm8058_chg.pmic_chg_irq[BATFET_IRQ],
1646 &rt_fops);
1647 if (pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ])
1648 debugfs_create_file("BATT_REPLACE", 0444, pm8058_chg.dent,
1649 (void *)
1650 pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ],
1651 &rt_fops);
1652 if (pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ])
1653 debugfs_create_file("BATTCONNECT", 0444, pm8058_chg.dent,
1654 (void *)
1655 pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ],
1656 &rt_fops);
1657 if (pm8058_chg.pmic_chg_irq[VBATDET_IRQ])
1658 debugfs_create_file("VBATDET", 0444, pm8058_chg.dent, (void *)
1659 pm8058_chg.pmic_chg_irq[VBATDET_IRQ],
1660 &rt_fops);
1661 if (pm8058_chg.pmic_chg_irq[VBATDET_LOW_IRQ])
1662 debugfs_create_file("VBATDET_LOW", 0444, pm8058_chg.dent,
1663 (void *)
1664 pm8058_chg.pmic_chg_irq[VBATDET_LOW_IRQ],
1665 &rt_fops);
1666 debugfs_create_file("CHARGE_BATT", 0444, pm8058_chg.dent,
1667 NULL,
1668 &fet_fops);
1669}
1670#else
1671static inline void create_debugfs_entries(void)
1672{
1673}
1674#endif
1675
1676static void remove_debugfs_entries(void)
1677{
1678 debugfs_remove_recursive(pm8058_chg.dent);
1679}
1680
1681static struct msm_hardware_charger usb_hw_chg = {
Abhijeet Dharmapurikar0758e1e2011-07-14 18:11:41 -07001682 .type = CHG_TYPE_USB,
1683 .rating = 1,
1684 .name = "pm8058-usb",
1685 .start_charging = pm8058_start_charging,
1686 .stop_charging = pm8058_stop_charging,
1687 .charging_switched = pm8058_charging_switched,
1688 .start_system_current = pm8058_start_system_current,
1689 .stop_system_current = pm8058_stop_system_current,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001690};
1691
1692static int batt_read_adc(int channel, int *mv_reading)
1693{
1694 int ret;
1695 void *h;
1696 struct adc_chan_result adc_chan_result;
1697 struct completion conv_complete_evt;
1698
1699 pr_debug("%s: called for %d\n", __func__, channel);
1700 ret = adc_channel_open(channel, &h);
1701 if (ret) {
1702 pr_err("%s: couldnt open channel %d ret=%d\n",
1703 __func__, channel, ret);
1704 goto out;
1705 }
1706 init_completion(&conv_complete_evt);
1707 ret = adc_channel_request_conv(h, &conv_complete_evt);
1708 if (ret) {
1709 pr_err("%s: couldnt request conv channel %d ret=%d\n",
1710 __func__, channel, ret);
1711 goto out;
1712 }
1713 wait_for_completion(&conv_complete_evt);
1714 ret = adc_channel_read_result(h, &adc_chan_result);
1715 if (ret) {
1716 pr_err("%s: couldnt read result channel %d ret=%d\n",
1717 __func__, channel, ret);
1718 goto out;
1719 }
1720 ret = adc_channel_close(h);
1721 if (ret) {
1722 pr_err("%s: couldnt close channel %d ret=%d\n",
1723 __func__, channel, ret);
1724 }
1725 if (mv_reading)
1726 *mv_reading = adc_chan_result.measurement;
1727
1728 pr_debug("%s: done for %d\n", __func__, channel);
1729 return adc_chan_result.physical;
1730out:
1731 pr_debug("%s: done for %d\n", __func__, channel);
1732 return -EINVAL;
1733
1734}
1735
1736#define BATT_THERM_OPEN_MV 2000
1737static int pm8058_is_battery_present(void)
1738{
1739 int mv_reading;
1740
1741 mv_reading = 0;
1742 batt_read_adc(CHANNEL_ADC_BATT_THERM, &mv_reading);
1743 pr_debug("%s: therm_raw is %d\n", __func__, mv_reading);
1744 if (mv_reading > 0 && mv_reading < BATT_THERM_OPEN_MV)
1745 return 1;
1746
1747 return 0;
1748}
1749
1750static int pm8058_get_battery_temperature(void)
1751{
1752 return batt_read_adc(CHANNEL_ADC_BATT_THERM, NULL);
1753}
1754
1755#define BATT_THERM_OPERATIONAL_MAX_CELCIUS 40
1756#define BATT_THERM_OPERATIONAL_MIN_CELCIUS 0
1757static int pm8058_is_battery_temp_within_range(void)
1758{
1759 int therm_celcius;
1760
1761 therm_celcius = pm8058_get_battery_temperature();
1762 pr_debug("%s: therm_celcius is %d\n", __func__, therm_celcius);
1763 if (therm_celcius > 0
1764 && therm_celcius > BATT_THERM_OPERATIONAL_MIN_CELCIUS
1765 && therm_celcius < BATT_THERM_OPERATIONAL_MAX_CELCIUS)
1766 return 1;
1767
1768 return 0;
1769}
1770
1771#define BATT_ID_MAX_MV 800
1772#define BATT_ID_MIN_MV 600
1773static int pm8058_is_battery_id_valid(void)
1774{
1775 int batt_id_mv;
1776
1777 batt_id_mv = batt_read_adc(CHANNEL_ADC_BATT_ID, NULL);
1778 pr_debug("%s: batt_id_mv is %d\n", __func__, batt_id_mv);
1779
1780 /*
1781 * The readings are not in range
1782 * assume battery is present for now
1783 */
1784 return 1;
1785
1786 if (batt_id_mv > 0
1787 && batt_id_mv > BATT_ID_MIN_MV
1788 && batt_id_mv < BATT_ID_MAX_MV)
1789 return 1;
1790
1791 return 0;
1792}
1793
1794/* returns voltage in mV */
1795static int pm8058_get_battery_mvolts(void)
1796{
1797 int vbatt_mv;
1798
1799 vbatt_mv = batt_read_adc(CHANNEL_ADC_VBATT, NULL);
1800 pr_debug("%s: vbatt_mv is %d\n", __func__, vbatt_mv);
1801 if (vbatt_mv > 0)
1802 return vbatt_mv;
1803 /*
1804 * return 0 to tell the upper layers
1805 * we couldnt read the battery voltage
1806 */
1807 return 0;
1808}
1809
1810static int msm_battery_gauge_alarm_notify(struct notifier_block *nb,
1811 unsigned long status, void *unused)
1812{
1813 int rc;
1814
1815 pr_info("%s: status: %lu\n", __func__, status);
1816
1817 switch (status) {
1818 case 0:
1819 dev_err(pm8058_chg.dev,
1820 "%s: spurious interrupt\n", __func__);
1821 break;
1822 /* expected case - trip of low threshold */
1823 case 1:
1824 rc = pm8058_batt_alarm_state_set(0, 0);
1825 if (rc)
1826 dev_err(pm8058_chg.dev,
1827 "%s: unable to set alarm state\n", __func__);
1828 msm_charger_notify_event(NULL, CHG_BATT_NEEDS_RECHARGING);
1829 break;
1830 case 2:
1831 dev_err(pm8058_chg.dev,
1832 "%s: trip of high threshold\n", __func__);
1833 break;
1834 default:
1835 dev_err(pm8058_chg.dev,
1836 "%s: error received\n", __func__);
1837 };
1838
1839 return 0;
1840}
1841
1842static int pm8058_monitor_for_recharging(void)
1843{
1844 /* enable low comparator */
1845 return pm8058_batt_alarm_state_set(1, 0);
1846}
1847
1848static struct msm_battery_gauge pm8058_batt_gauge = {
1849 .get_battery_mvolts = pm8058_get_battery_mvolts,
1850 .get_battery_temperature = pm8058_get_battery_temperature,
1851 .is_battery_present = pm8058_is_battery_present,
1852 .is_battery_temp_within_range = pm8058_is_battery_temp_within_range,
1853 .is_battery_id_valid = pm8058_is_battery_id_valid,
1854 .monitor_for_recharging = pm8058_monitor_for_recharging,
1855};
1856
1857static int pm8058_usb_voltage_lower_limit(void)
1858{
1859 u8 temp, old;
1860 int ret = 0;
1861
1862 temp = 0x10;
1863 ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
1864 ret |= pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST, &old, 1);
1865 old = old & ~BIT(IGNORE_LL);
1866 temp = 0x90 | (0xF & old);
1867 ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
1868
1869 return ret;
1870}
1871
1872static int __devinit pm8058_charger_probe(struct platform_device *pdev)
1873{
1874 struct pm8058_chip *pm_chip;
Terence Hampson13163082011-08-09 10:17:06 -04001875 struct pmic8058_charger_data *pdata;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001876 int rc = 0;
1877
1878 pm_chip = dev_get_drvdata(pdev->dev.parent);
1879 if (pm_chip == NULL) {
1880 pr_err("%s:no parent data passed in.\n", __func__);
1881 return -EFAULT;
1882 }
1883
1884 pm8058_chg.pm_chip = pm_chip;
1885 pm8058_chg.pdata = pdev->dev.platform_data;
1886 pm8058_chg.dev = &pdev->dev;
Terence Hampson13163082011-08-09 10:17:06 -04001887 pdata = (struct pmic8058_charger_data *) pm8058_chg.pdata;
1888
1889 if (pdata) {
1890 usb_hw_chg.type = pdata->charger_type;
1891 chg_data.charger_type = pdata->charger_type;
1892 chg_data.max_source_current = pdata->max_source_current;
1893 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001894
1895 rc = request_irqs(pdev);
1896 if (rc) {
1897 pr_err("%s: couldnt register interrupts\n", __func__);
1898 goto out;
1899 }
1900
1901 rc = pm8058_usb_voltage_lower_limit();
1902 if (rc) {
1903 pr_err("%s: couldnt set ignore lower limit bit to 0\n",
1904 __func__);
1905 goto free_irq;
1906 }
1907
1908 rc = msm_charger_register(&usb_hw_chg);
1909 if (rc) {
1910 pr_err("%s: msm_charger_register failed ret=%d\n",
1911 __func__, rc);
1912 goto free_irq;
1913 }
1914
1915 pm_chg_batt_temp_disable(0);
1916 msm_battery_gauge_register(&pm8058_batt_gauge);
1917 __dump_chg_regs();
1918
1919 create_debugfs_entries();
1920 INIT_DELAYED_WORK(&pm8058_chg.veoc_begin_work, veoc_begin_work);
1921 INIT_DELAYED_WORK(&pm8058_chg.check_vbat_low_work, vbat_low_work);
1922 INIT_DELAYED_WORK(&pm8058_chg.chg_done_check_work, chg_done_check_work);
1923 INIT_DELAYED_WORK(&pm8058_chg.charging_check_work, charging_check_work);
1924
1925 /* determine what state the charger is in */
1926 pm8058_chg_determine_initial_state();
1927
1928 pm8058_chg_enable_irq(BATTTEMP_IRQ);
1929 pm8058_chg_enable_irq(BATTCONNECT_IRQ);
1930
1931 rc = pm8058_batt_alarm_state_set(0, 0);
1932 if (rc) {
1933 pr_err("%s: unable to set batt alarm state\n", __func__);
1934 goto free_irq;
1935 }
1936
1937 /*
1938 * The batt-alarm driver requires sane values for both min / max,
1939 * regardless of whether they're both activated.
1940 */
1941 rc = pm8058_batt_alarm_threshold_set(resume_mv, 4300);
1942 if (rc) {
1943 pr_err("%s: unable to set batt alarm threshold\n", __func__);
1944 goto free_irq;
1945 }
1946
1947 rc = pm8058_batt_alarm_hold_time_set(PM8058_BATT_ALARM_HOLD_TIME_16_MS);
1948 if (rc) {
1949 pr_err("%s: unable to set batt alarm hold time\n", __func__);
1950 goto free_irq;
1951 }
1952
1953 /* PWM enabled at 2Hz */
1954 rc = pm8058_batt_alarm_pwm_rate_set(1, 7, 4);
1955 if (rc) {
1956 pr_err("%s: unable to set batt alarm pwm rate\n", __func__);
1957 goto free_irq;
1958 }
1959
1960 rc = pm8058_batt_alarm_register_notifier(&alarm_notifier);
1961 if (rc) {
1962 pr_err("%s: unable to register alarm notifier\n", __func__);
1963 goto free_irq;
1964 }
1965
1966 pm8058_chg.inited = 1;
1967
1968 return 0;
1969
1970free_irq:
1971 free_irqs();
1972out:
1973 return rc;
1974}
1975
1976static int __devexit pm8058_charger_remove(struct platform_device *pdev)
1977{
1978 struct pm8058_charger_chip *chip = platform_get_drvdata(pdev);
1979 int rc;
1980
1981 msm_charger_notify_event(&usb_hw_chg, CHG_REMOVED_EVENT);
1982 msm_charger_unregister(&usb_hw_chg);
1983 cancel_delayed_work_sync(&pm8058_chg.veoc_begin_work);
1984 cancel_delayed_work_sync(&pm8058_chg.check_vbat_low_work);
1985 cancel_delayed_work_sync(&pm8058_chg.charging_check_work);
1986 free_irqs();
1987 remove_debugfs_entries();
1988 kfree(chip);
1989
1990 rc = pm8058_batt_alarm_state_set(0, 0);
1991 if (rc)
1992 pr_err("%s: unable to set batt alarm state\n", __func__);
1993
1994 rc |= pm8058_batt_alarm_unregister_notifier(&alarm_notifier);
1995 if (rc)
1996 pr_err("%s: unable to register alarm notifier\n", __func__);
1997 return rc;
1998}
1999
2000static struct platform_driver pm8058_charger_driver = {
2001 .probe = pm8058_charger_probe,
2002 .remove = __devexit_p(pm8058_charger_remove),
2003 .driver = {
2004 .name = "pm8058-charger",
2005 .owner = THIS_MODULE,
2006 },
2007};
2008
2009static int __init pm8058_charger_init(void)
2010{
2011 return platform_driver_register(&pm8058_charger_driver);
2012}
2013
2014static void __exit pm8058_charger_exit(void)
2015{
2016 platform_driver_unregister(&pm8058_charger_driver);
2017}
2018
2019late_initcall(pm8058_charger_init);
2020module_exit(pm8058_charger_exit);
2021
2022MODULE_LICENSE("GPL v2");
2023MODULE_DESCRIPTION("PMIC8058 BATTERY driver");
2024MODULE_VERSION("1.0");
2025MODULE_ALIAS("platform:pm8058_charger");