blob: d66317e23e7688e474a5b36a17e2025581d009ef [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;
206
207
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;
763 pm8058_chg.current_charger_current = chg_current;
764 pm8058_chg_enable_irq(FASTCHG_IRQ);
765
766 ret = pm_chg_vmaxsel_set(chg_voltage);
767 if (ret)
768 goto out;
769
770 /* set vbat to CC to CV threshold */
771 ret = pm_chg_vbatdet_set(AUTO_CHARGING_VBATDET);
772 if (ret)
773 goto out;
774
775 pm8058_chg.vbatdet = AUTO_CHARGING_VBATDET;
776 /*
777 * get the state of vbat and if it is higher than
778 * AUTO_CHARGING_VBATDET we start the veoc start timer
779 * else wait for the voltage to go to AUTO_CHARGING_VBATDET
780 * and then start the 90 min timer
781 */
782 vbat_higher_than_vbatdet =
783 pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VBATDET_IRQ]);
784 if (vbat_higher_than_vbatdet) {
785 /*
786 * we are in constant voltage phase of charging
787 * IEOC should happen withing 90 mins of this instant
788 * else we enable VEOC
789 */
790 dev_info(pm8058_chg.dev, "%s begin veoc timer\n", __func__);
791 schedule_delayed_work(&pm8058_chg.veoc_begin_work,
792 round_jiffies_relative(msecs_to_jiffies
793 (AUTO_CHARGING_VEOC_BEGIN_TIME_MS)));
794 } else
795 pm8058_chg_enable_irq(VBATDET_IRQ);
796
797 ret = __pm8058_start_charging(chg_current, AUTO_CHARGING_IEOC_ITERM,
798 AUTO_CHARGING_FAST_TIME_MAX_MINUTES);
799 pm8058_chg.current_charger_current = chg_current;
800
801 /*
802 * We want to check the FSM state to verify we're charging. We must
803 * wait before doing this to allow the VBATDET to settle. The worst
804 * case for this is two seconds. The batt alarm does not have this
805 * delay.
806 */
807 schedule_delayed_work(&pm8058_chg.charging_check_work,
808 round_jiffies_relative(msecs_to_jiffies
809 (AUTO_CHARGING_VBATDET_DEBOUNCE_TIME_MS)));
810
811out:
812 return ret;
813}
814
815static void veoc_begin_work(struct work_struct *work)
816{
817 /* we have been doing CV for 90mins with no signs of IEOC
818 * start checking for VEOC in addition with 16min charges*/
819 dev_info(pm8058_chg.dev, "%s begin veoc detection\n", __func__);
820 pm8058_chg.waiting_for_veoc = 1;
821 /*
822 * disable VBATDET irq we dont need it unless we are at the end of
823 * charge cycle
824 */
825 pm8058_chg_disable_irq(VBATDET_IRQ);
826 __pm8058_start_charging(pm8058_chg.current_charger_current,
827 AUTO_CHARGING_VEOC_ITERM,
828 AUTO_CHARGING_VEOC_TCHG);
829}
830
831static void vbat_low_work(struct work_struct *work)
832{
833 /*
834 * It has been one minute and the battery still holds voltage
835 * start the final topoff - charging is almost done
836 */
837 dev_info(pm8058_chg.dev, "%s vbatt maintains for a minute"
838 "starting topoff\n", __func__);
839 pm8058_chg.waiting_for_veoc = 0;
840 pm8058_chg.waiting_for_topoff = 1;
841 pm8058_chg_disable_irq(VBATDET_LOW_IRQ);
842 pm8058_chg_disable_irq(VBATDET_IRQ);
843 __pm8058_start_charging(pm8058_chg.current_charger_current,
844 AUTO_CHARGING_VEOC_ITERM,
845 AUTO_CHARGING_VEOC_TCHG_FINAL_CYCLE);
846}
847
848
849static irqreturn_t pm8058_chg_chgval_handler(int irq, void *dev_id)
850{
851 u8 old, temp;
852 int ret;
853
854 if (is_chg_plugged_in()) { /* this debounces it */
855 if (!pm8058_chg.present) {
856 msm_charger_notify_event(&usb_hw_chg,
857 CHG_INSERTED_EVENT);
858 pm8058_chg.present = 1;
859 }
860 } else {
861 if (pm8058_chg.present) {
862 ret = pm8058_read(pm8058_chg.pm_chip,
863 PM8058_OVP_TEST_REG,
864 &old, 1);
865 temp = old | BIT(FORCE_OVP_OFF);
866 ret = pm8058_write(pm8058_chg.pm_chip,
867 PM8058_OVP_TEST_REG,
868 &temp, 1);
869 temp = 0xFC;
870 ret = pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST,
871 &temp, 1);
872 /* 10 ms sleep is for the VCHG to discharge */
873 msleep(10);
874 temp = 0xF0;
875 ret = pm8058_write(pm8058_chg.pm_chip,
876 PM8058_CHG_TEST,
877 &temp, 1);
878 ret = pm8058_write(pm8058_chg.pm_chip,
879 PM8058_OVP_TEST_REG,
880 &old, 1);
881
882 pm_chg_enum_done_enable(0);
883 pm_chg_auto_disable(1);
884 msm_charger_notify_event(&usb_hw_chg,
885 CHG_REMOVED_EVENT);
886 pm8058_chg.present = 0;
887 }
888 }
889
890 return IRQ_HANDLED;
891}
892
893static irqreturn_t pm8058_chg_chginval_handler(int irq, void *dev_id)
894{
895 u8 old, temp;
896 int ret;
897
898 if (pm8058_chg.present) {
899 pm8058_chg_disable_irq(CHGINVAL_IRQ);
900
901 pm_chg_enum_done_enable(0);
902 pm_chg_auto_disable(1);
903 ret = pm8058_read(pm8058_chg.pm_chip,
904 PM8058_OVP_TEST_REG, &old, 1);
905 temp = old | BIT(FORCE_OVP_OFF);
906 ret = pm8058_write(pm8058_chg.pm_chip,
907 PM8058_OVP_TEST_REG, &temp, 1);
908 temp = 0xFC;
909 ret = pm8058_write(pm8058_chg.pm_chip,
910 PM8058_CHG_TEST, &temp, 1);
911 /* 10 ms sleep is for the VCHG to discharge */
912 msleep(10);
913 temp = 0xF0;
914 ret = pm8058_write(pm8058_chg.pm_chip,
915 PM8058_CHG_TEST, &temp, 1);
916 ret = pm8058_write(pm8058_chg.pm_chip,
917 PM8058_OVP_TEST_REG, &old, 1);
918
919 if (!is_chg_plugged_in()) {
920 msm_charger_notify_event(&usb_hw_chg,
921 CHG_REMOVED_EVENT);
922 pm8058_chg.present = 0;
923 } else {
924 /* was a fake */
925 pm8058_chg_enable_irq(CHGINVAL_IRQ);
926 }
927 }
928
929 return IRQ_HANDLED;
930}
931
932static irqreturn_t pm8058_chg_auto_chgdone_handler(int irq, void *dev_id)
933{
934 dev_info(pm8058_chg.dev, "%s waiting a sec to confirm\n",
935 __func__);
Abhijeet Dharmapurikar2dae2392011-07-14 18:31:28 -0700936 pm8058_chg_disable_irq(AUTO_CHGDONE_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700937 pm8058_chg_disable_irq(VBATDET_IRQ);
938 if (!delayed_work_pending(&pm8058_chg.chg_done_check_work)) {
939 schedule_delayed_work(&pm8058_chg.chg_done_check_work,
940 round_jiffies_relative(msecs_to_jiffies
941 (AUTO_CHARGING_DONE_CHECK_TIME_MS)));
942 }
943 return IRQ_HANDLED;
944}
945
946/* can only happen with the pmic charger when it has been charing
947 * for either 16 mins wating for VEOC or 32 mins for topoff
948 * without a IEOC indication */
949static irqreturn_t pm8058_chg_auto_chgfail_handler(int irq, void *dev_id)
950{
951 pm8058_chg_disable_irq(AUTO_CHGFAIL_IRQ);
952
953 if (pm8058_chg.waiting_for_topoff == 1) {
954 dev_info(pm8058_chg.dev, "%s topoff done, charging done\n",
955 __func__);
956 pm8058_chg.waiting_for_topoff = 0;
957 /* notify we are done charging */
958 msm_charger_notify_event(&usb_hw_chg, CHG_DONE_EVENT);
959 } else {
960 /* start one minute timer and monitor VBATDET_LOW */
961 dev_info(pm8058_chg.dev, "%s monitoring vbat_low for a"
962 "minute\n", __func__);
963 schedule_delayed_work(&pm8058_chg.check_vbat_low_work,
964 round_jiffies_relative(msecs_to_jiffies
965 (AUTO_CHARGING_VEOC_VBAT_LOW_CHECK_TIME_MS)));
966
967 /* note we are waiting on veoc */
968 pm8058_chg.waiting_for_veoc = 1;
969
970 pm_chg_vbatdet_set(AUTO_CHARGING_VEOC_VBATDET);
971 pm8058_chg.vbatdet = AUTO_CHARGING_VEOC_VBATDET;
972 pm8058_chg_enable_irq(VBATDET_LOW_IRQ);
973 }
974 return IRQ_HANDLED;
975}
976
977static irqreturn_t pm8058_chg_chgstate_handler(int irq, void *dev_id)
978{
979 u8 temp;
980
981 temp = 0x00;
982 if (!pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1)) {
983 pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
984 dev_dbg(pm8058_chg.dev, "%s state=%d\n", __func__, temp);
985 }
986 return IRQ_HANDLED;
987}
988
989static irqreturn_t pm8058_chg_fastchg_handler(int irq, void *dev_id)
990{
991 pm8058_chg_disable_irq(FASTCHG_IRQ);
992
993 /* we have begun the fast charging state */
994 dev_info(pm8058_chg.dev, "%s begin fast charging"
995 , __func__);
996 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_BEGIN_FAST_CHARGING);
997 return IRQ_HANDLED;
998}
999
1000static irqreturn_t pm8058_chg_batttemp_handler(int irq, void *dev_id)
1001{
1002 int ret;
1003
1004 /* we could get temperature
1005 * interrupt when the battery is plugged out
1006 */
1007 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ]);
1008 if (ret) {
1009 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_REMOVED);
1010 } else {
1011 /* read status to determine we are inrange or outofrange */
1012 ret =
1013 pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ]);
1014 if (ret)
1015 msm_charger_notify_event(&usb_hw_chg,
1016 CHG_BATT_TEMP_OUTOFRANGE);
1017 else
1018 msm_charger_notify_event(&usb_hw_chg,
1019 CHG_BATT_TEMP_INRANGE);
1020 }
1021
1022 return IRQ_HANDLED;
1023}
1024
1025static irqreturn_t pm8058_chg_vbatdet_handler(int irq, void *dev_id)
1026{
1027 int ret;
1028
1029 /* settling time */
1030 msleep(20);
1031 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[VBATDET_IRQ]);
1032
1033 if (ret) {
1034 if (pm8058_chg.vbatdet == AUTO_CHARGING_VBATDET
1035 && !delayed_work_pending(&pm8058_chg.veoc_begin_work)) {
1036 /*
1037 * we are in constant voltage phase of charging
1038 * IEOC should happen withing 90 mins of this instant
1039 * else we enable VEOC
1040 */
1041 dev_info(pm8058_chg.dev, "%s entered constant voltage"
1042 "begin veoc timer\n", __func__);
1043 schedule_delayed_work(&pm8058_chg.veoc_begin_work,
1044 round_jiffies_relative
1045 (msecs_to_jiffies
1046 (AUTO_CHARGING_VEOC_BEGIN_TIME_MS)));
1047 }
1048 } else {
1049 if (pm8058_chg.vbatdet == AUTO_CHARGING_VEOC_VBATDET) {
1050 cancel_delayed_work_sync(
1051 &pm8058_chg.check_vbat_low_work);
1052
1053 if (pm8058_chg.waiting_for_topoff
1054 || pm8058_chg.waiting_for_veoc) {
1055 /*
1056 * the battery dropped its voltage below 4100
1057 * around a minute charge the battery for 16
1058 * mins and check vbat again for a minute
1059 */
1060 dev_info(pm8058_chg.dev, "%s batt dropped vlt"
1061 "within a minute\n", __func__);
1062 pm8058_chg.waiting_for_topoff = 0;
1063 pm8058_chg.waiting_for_veoc = 1;
1064 pm8058_chg_disable_irq(VBATDET_IRQ);
1065 __pm8058_start_charging(pm8058_chg.
1066 current_charger_current,
1067 AUTO_CHARGING_VEOC_ITERM,
1068 AUTO_CHARGING_VEOC_TCHG);
1069 }
1070 }
1071 }
1072 return IRQ_HANDLED;
1073}
1074
1075static irqreturn_t pm8058_chg_batt_replace_handler(int irq, void *dev_id)
1076{
1077 int ret;
1078
1079 pm8058_chg_disable_irq(BATT_REPLACE_IRQ);
1080 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ]);
1081 if (ret) {
1082 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_INSERTED);
1083 /*
1084 * battery is present enable batt removal
1085 * and batt temperatture interrupt
1086 */
1087 pm8058_chg_enable_irq(BATTCONNECT_IRQ);
1088 }
1089 return IRQ_HANDLED;
1090}
1091
1092static irqreturn_t pm8058_chg_battconnect_handler(int irq, void *dev_id)
1093{
1094 int ret;
1095
1096 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ]);
1097 if (ret) {
1098 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_REMOVED);
1099 } else {
1100 msm_charger_notify_event(&usb_hw_chg, CHG_BATT_INSERTED);
1101 pm8058_chg_enable_irq(BATTTEMP_IRQ);
1102 }
1103
1104 return IRQ_HANDLED;
1105}
1106
1107static int get_rt_status(void *data, u64 * val)
1108{
1109 int i = (int)data;
1110 int ret;
1111
1112 ret = pm_chg_get_rt_status(i);
1113 *val = ret;
1114 return 0;
1115}
1116
1117DEFINE_SIMPLE_ATTRIBUTE(rt_fops, get_rt_status, NULL, "%llu\n");
1118DEFINE_SIMPLE_ATTRIBUTE(fsm_fops, get_fsm_status, NULL, "%llu\n");
1119
1120static void free_irqs(void)
1121{
1122 int i;
1123
1124 for (i = 0; i < PMIC_CHG_MAX_INTS; i++)
1125 if (pm8058_chg.pmic_chg_irq[i]) {
1126 free_irq(pm8058_chg.pmic_chg_irq[i], NULL);
1127 pm8058_chg.pmic_chg_irq[i] = 0;
1128 }
1129}
1130
1131static int __devinit request_irqs(struct platform_device *pdev)
1132{
1133 struct resource *res;
1134 int ret;
1135
1136 ret = 0;
1137 bitmap_fill(pm8058_chg.enabled_irqs, PMIC_CHG_MAX_INTS);
1138
1139 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "CHGVAL");
1140 if (res == NULL) {
1141 dev_err(pm8058_chg.dev,
1142 "%s:couldnt find resource CHGVAL\n", __func__);
1143 goto err_out;
1144 } else {
1145 ret = request_threaded_irq(res->start, NULL,
1146 pm8058_chg_chgval_handler,
1147 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1148 res->name, NULL);
1149 if (ret < 0) {
1150 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1151 __func__, res->start, ret);
1152 goto err_out;
1153 } else {
1154 pm8058_chg.pmic_chg_irq[CHGVAL_IRQ] = res->start;
1155 pm8058_chg_disable_irq(CHGVAL_IRQ);
1156 enable_irq_wake(pm8058_chg.pmic_chg_irq[CHGVAL_IRQ]);
1157 }
1158 }
1159
1160 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "CHGINVAL");
1161 if (res == NULL) {
1162 dev_err(pm8058_chg.dev,
1163 "%s:couldnt find resource CHGINVAL\n", __func__);
1164 goto err_out;
1165 } else {
1166 ret = request_threaded_irq(res->start, NULL,
1167 pm8058_chg_chginval_handler,
1168 IRQF_TRIGGER_RISING, res->name, NULL);
1169 if (ret < 0) {
1170 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1171 __func__, res->start, ret);
1172 goto err_out;
1173 } else {
1174 pm8058_chg.pmic_chg_irq[CHGINVAL_IRQ] = res->start;
1175 pm8058_chg_disable_irq(CHGINVAL_IRQ);
1176 }
1177 }
1178
1179 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1180 "AUTO_CHGDONE");
1181 if (res == NULL) {
1182 dev_err(pm8058_chg.dev,
1183 "%s:couldnt find resource AUTO_CHGDONE\n", __func__);
1184 goto err_out;
1185 } else {
1186 ret = request_threaded_irq(res->start, NULL,
1187 pm8058_chg_auto_chgdone_handler,
Abhijeet Dharmapurikar2dae2392011-07-14 18:31:28 -07001188 IRQF_TRIGGER_RISING,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001189 res->name, NULL);
1190 if (ret < 0) {
1191 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1192 __func__, res->start, ret);
1193 goto err_out;
1194 } else {
1195 pm8058_chg.pmic_chg_irq[AUTO_CHGDONE_IRQ] = res->start;
1196 pm8058_chg_disable_irq(AUTO_CHGDONE_IRQ);
1197 }
1198 }
1199
1200 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1201 "AUTO_CHGFAIL");
1202 if (res == NULL) {
1203 dev_err(pm8058_chg.dev,
1204 "%s:couldnt find resource AUTO_CHGFAIL\n", __func__);
1205 goto err_out;
1206 } else {
1207 ret = request_threaded_irq(res->start, NULL,
1208 pm8058_chg_auto_chgfail_handler,
1209 IRQF_TRIGGER_RISING, res->name, NULL);
1210 if (ret < 0) {
1211 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1212 __func__, res->start, ret);
1213 goto err_out;
1214 } else {
1215 pm8058_chg.pmic_chg_irq[AUTO_CHGFAIL_IRQ] = res->start;
1216 pm8058_chg_disable_irq(AUTO_CHGFAIL_IRQ);
1217 }
1218 }
1219
1220 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "CHGSTATE");
1221 if (res == NULL) {
1222 dev_err(pm8058_chg.dev,
1223 "%s:couldnt find resource CHGSTATE\n", __func__);
1224 goto err_out;
1225 } else {
1226 ret = request_threaded_irq(res->start, NULL,
1227 pm8058_chg_chgstate_handler,
1228 IRQF_TRIGGER_RISING, res->name, NULL);
1229 if (ret < 0) {
1230 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1231 __func__, res->start, ret);
1232 goto err_out;
1233 } else {
1234 pm8058_chg.pmic_chg_irq[CHGSTATE_IRQ] = res->start;
1235 pm8058_chg_disable_irq(CHGSTATE_IRQ);
1236 }
1237 }
1238
1239 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "FASTCHG");
1240 if (res == NULL) {
1241 dev_err(pm8058_chg.dev,
1242 "%s:couldnt find resource FASTCHG\n", __func__);
1243 goto err_out;
1244 } else {
1245 ret = request_threaded_irq(res->start, NULL,
1246 pm8058_chg_fastchg_handler,
1247 IRQF_TRIGGER_RISING, res->name, NULL);
1248 if (ret < 0) {
1249 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1250 __func__, res->start, ret);
1251 goto err_out;
1252 } else {
1253 pm8058_chg.pmic_chg_irq[FASTCHG_IRQ] = res->start;
1254 pm8058_chg_disable_irq(FASTCHG_IRQ);
1255 }
1256 }
1257
1258 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "BATTTEMP");
1259 if (res == NULL) {
1260 dev_err(pm8058_chg.dev,
1261 "%s:couldnt find resource CHG_END\n", __func__);
1262 goto err_out;
1263 } else {
1264 ret = request_threaded_irq(res->start, NULL,
1265 pm8058_chg_batttemp_handler,
1266 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1267 res->name, NULL);
1268 if (ret < 0) {
1269 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1270 __func__, res->start, ret);
1271 goto err_out;
1272 } else {
1273 pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ] = res->start;
1274 pm8058_chg_disable_irq(BATTTEMP_IRQ);
1275 }
1276 }
1277
1278 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1279 "BATT_REPLACE");
1280 if (res == NULL) {
1281 dev_err(pm8058_chg.dev,
1282 "%s:couldnt find resource BATT_REPLACE\n", __func__);
1283 goto err_out;
1284 } else {
1285 ret = request_threaded_irq(res->start, NULL,
1286 pm8058_chg_batt_replace_handler,
1287 IRQF_TRIGGER_RISING, res->name, NULL);
1288 if (ret < 0) {
1289 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1290 __func__, res->start, ret);
1291 goto err_out;
1292 } else {
1293 pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ] = res->start;
1294 pm8058_chg_disable_irq(BATT_REPLACE_IRQ);
1295 }
1296 }
1297
1298 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "BATTCONNECT");
1299 if (res == NULL) {
1300 dev_err(pm8058_chg.dev,
1301 "%s:couldnt find resource BATTCONNECT\n", __func__);
1302 goto err_out;
1303 } else {
1304 ret = request_threaded_irq(res->start, NULL,
1305 pm8058_chg_battconnect_handler,
1306 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1307 res->name, NULL);
1308 if (ret < 0) {
1309 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1310 __func__, res->start, ret);
1311 goto err_out;
1312 } else {
1313 pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ] = res->start;
1314 pm8058_chg_disable_irq(BATTCONNECT_IRQ);
1315 }
1316 }
1317
1318 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "VBATDET");
1319 if (res == NULL) {
1320 dev_err(pm8058_chg.dev,
1321 "%s:couldnt find resource VBATDET\n", __func__);
1322 goto err_out;
1323 } else {
1324 ret = request_threaded_irq(res->start, NULL,
1325 pm8058_chg_vbatdet_handler,
1326 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1327 res->name, NULL);
1328 if (ret < 0) {
1329 dev_err(pm8058_chg.dev, "%s:couldnt request %d %d\n",
1330 __func__, res->start, ret);
1331 goto err_out;
1332 } else {
1333 pm8058_chg.pmic_chg_irq[VBATDET_IRQ] = res->start;
1334 pm8058_chg_disable_irq(VBATDET_IRQ);
1335 }
1336 }
1337
1338 return 0;
1339
1340err_out:
1341 free_irqs();
1342 return -EINVAL;
1343}
1344
1345static int pm8058_get_charge_batt(void)
1346{
1347 u8 temp;
1348 int rc;
1349
1350 rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
1351 if (rc)
1352 return rc;
1353
1354 temp &= BIT(CHG_CHARGE_BAT);
1355 if (temp)
1356 temp = 1;
1357 return temp;
1358}
1359EXPORT_SYMBOL(pm8058_get_charge_batt);
1360
1361static int pm8058_set_charge_batt(int on)
1362{
1363 u8 temp;
1364 int rc;
1365
1366 rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
1367 if (rc)
1368 return rc;
1369 if (on)
1370 temp |= BIT(CHG_CHARGE_BAT);
1371 else
1372 temp &= ~BIT(CHG_CHARGE_BAT);
1373
1374 return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
1375
1376}
1377EXPORT_SYMBOL(pm8058_set_charge_batt);
1378
1379static int get_charge_batt(void *data, u64 * val)
1380{
1381 int ret;
1382
1383 ret = pm8058_get_charge_batt();
1384 if (ret < 0)
1385 return ret;
1386
1387 *val = ret;
1388 return 0;
1389}
1390
1391static int set_charge_batt(void *data, u64 val)
1392{
1393 return pm8058_set_charge_batt(val);
1394}
1395DEFINE_SIMPLE_ATTRIBUTE(fet_fops, get_charge_batt, set_charge_batt, "%llu\n");
1396
1397static void pm8058_chg_determine_initial_state(void)
1398{
1399 if (is_chg_plugged_in()) {
1400 pm8058_chg.present = 1;
1401 msm_charger_notify_event(&usb_hw_chg, CHG_INSERTED_EVENT);
1402 dev_info(pm8058_chg.dev, "%s charger present\n", __func__);
1403 } else {
1404 pm8058_chg.present = 0;
1405 dev_info(pm8058_chg.dev, "%s charger absent\n", __func__);
1406 }
1407 pm8058_chg_enable_irq(CHGVAL_IRQ);
1408}
1409
1410static int pm8058_stop_charging(struct msm_hardware_charger *hw_chg)
1411{
1412 int ret;
1413
1414 dev_info(pm8058_chg.dev, "%s stopping charging\n", __func__);
Abhijeet Dharmapurikar2dae2392011-07-14 18:31:28 -07001415
1416 /* disable the irqs enabled while charging */
1417 pm8058_chg_disable_irq(AUTO_CHGFAIL_IRQ);
1418 pm8058_chg_disable_irq(CHGHOT_IRQ);
1419 pm8058_chg_disable_irq(AUTO_CHGDONE_IRQ);
1420 pm8058_chg_disable_irq(FASTCHG_IRQ);
1421 pm8058_chg_disable_irq(CHG_END_IRQ);
1422 pm8058_chg_disable_irq(VBATDET_IRQ);
1423 pm8058_chg_disable_irq(VBATDET_LOW_IRQ);
1424
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001425 cancel_delayed_work_sync(&pm8058_chg.veoc_begin_work);
1426 cancel_delayed_work_sync(&pm8058_chg.check_vbat_low_work);
1427 cancel_delayed_work_sync(&pm8058_chg.chg_done_check_work);
1428 cancel_delayed_work_sync(&pm8058_chg.charging_check_work);
1429
1430 ret = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[FASTCHG_IRQ]);
1431 if (ret == 1)
1432 pm_chg_suspend(1);
1433 else
1434 dev_err(pm8058_chg.dev,
1435 "%s called when not fast-charging\n", __func__);
1436
1437 pm_chg_failed_clear(1);
1438
1439 pm8058_chg.waiting_for_veoc = 0;
1440 pm8058_chg.waiting_for_topoff = 0;
1441
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001442 if (pm8058_chg.voter)
1443 msm_xo_mode_vote(pm8058_chg.voter, MSM_XO_MODE_OFF);
1444
1445 return 0;
1446}
1447
1448static int get_status(void *data, u64 * val)
1449{
1450 *val = pm8058_chg.current_charger_current;
1451 return 0;
1452}
1453
1454static int set_status(void *data, u64 val)
1455{
1456
1457 pm8058_chg.current_charger_current = val;
1458 if (pm8058_chg.current_charger_current)
1459 pm8058_start_charging(NULL,
1460 AUTO_CHARGING_VMAXSEL,
1461 pm8058_chg.current_charger_current);
1462 else
1463 pm8058_stop_charging(NULL);
1464 return 0;
1465}
1466DEFINE_SIMPLE_ATTRIBUTE(chg_fops, get_status, set_status, "%llu\n");
1467
1468static int set_disable_status_param(const char *val, struct kernel_param *kp)
1469{
1470 int ret;
1471
1472 ret = param_set_int(val, kp);
1473 if (ret)
1474 return ret;
1475
1476 if (pm8058_chg.inited && pm8058_chg.disabled) {
1477 /*
1478 * stop_charging is called during usb suspend
1479 * act as the usb is removed by disabling auto and enum
1480 */
1481 pm_chg_enum_done_enable(0);
1482 pm_chg_auto_disable(1);
1483 pm8058_stop_charging(NULL);
1484 }
1485 return 0;
1486}
1487module_param_call(disabled, set_disable_status_param, param_get_uint,
1488 &(pm8058_chg.disabled), 0644);
1489
1490static int pm8058_charging_switched(struct msm_hardware_charger *hw_chg)
1491{
1492 u8 temp;
1493
1494 temp = 0xA3;
1495 pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
1496 temp = 0x84;
1497 pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
1498 msleep(2);
1499 temp = 0x80;
1500 pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
1501 return 0;
1502}
1503
1504static int get_reg(void *data, u64 * val)
1505{
1506 int i = (int)data;
1507 int ret;
1508 u8 temp;
1509
1510 ret = pm8058_read(pm8058_chg.pm_chip, i, &temp, 1);
1511 if (ret)
1512 return -EAGAIN;
1513 *val = temp;
1514 return 0;
1515}
1516
1517static int set_reg(void *data, u64 val)
1518{
1519 int i = (int)data;
1520 int ret;
1521 u8 temp;
1522
1523 temp = (u8) val;
1524 ret = pm8058_write(pm8058_chg.pm_chip, i, &temp, 1);
1525 mb();
1526 if (ret)
1527 return -EAGAIN;
1528 return 0;
1529}
1530
1531DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "%llu\n");
1532
1533#ifdef CONFIG_DEBUG_FS
1534static void create_debugfs_entries(void)
1535{
1536 pm8058_chg.dent = debugfs_create_dir("pm8058_usb_chg", NULL);
1537
1538 if (IS_ERR(pm8058_chg.dent)) {
1539 pr_err("pmic charger couldnt create debugfs dir\n");
1540 return;
1541 }
1542
1543 debugfs_create_file("CHG_CNTRL", 0644, pm8058_chg.dent,
1544 (void *)PM8058_CHG_CNTRL, &reg_fops);
1545 debugfs_create_file("CHG_CNTRL_2", 0644, pm8058_chg.dent,
1546 (void *)PM8058_CHG_CNTRL_2, &reg_fops);
1547 debugfs_create_file("CHG_VMAX_SEL", 0644, pm8058_chg.dent,
1548 (void *)PM8058_CHG_VMAX_SEL, &reg_fops);
1549 debugfs_create_file("CHG_VBAT_DET", 0644, pm8058_chg.dent,
1550 (void *)PM8058_CHG_VBAT_DET, &reg_fops);
1551 debugfs_create_file("CHG_IMAX", 0644, pm8058_chg.dent,
1552 (void *)PM8058_CHG_IMAX, &reg_fops);
1553 debugfs_create_file("CHG_TRICKLE", 0644, pm8058_chg.dent,
1554 (void *)PM8058_CHG_TRICKLE, &reg_fops);
1555 debugfs_create_file("CHG_ITERM", 0644, pm8058_chg.dent,
1556 (void *)PM8058_CHG_ITERM, &reg_fops);
1557 debugfs_create_file("CHG_TTRKL_MAX", 0644, pm8058_chg.dent,
1558 (void *)PM8058_CHG_TTRKL_MAX, &reg_fops);
1559 debugfs_create_file("CHG_TCHG_MAX", 0644, pm8058_chg.dent,
1560 (void *)PM8058_CHG_TCHG_MAX, &reg_fops);
1561 debugfs_create_file("CHG_TEMP_THRESH", 0644, pm8058_chg.dent,
1562 (void *)PM8058_CHG_TEMP_THRESH, &reg_fops);
1563 debugfs_create_file("CHG_TEMP_REG", 0644, pm8058_chg.dent,
1564 (void *)PM8058_CHG_TEMP_REG, &reg_fops);
1565
1566 debugfs_create_file("FSM_STATE", 0644, pm8058_chg.dent, NULL,
1567 &fsm_fops);
1568
1569 debugfs_create_file("stop", 0644, pm8058_chg.dent, NULL,
1570 &chg_fops);
1571
1572 if (pm8058_chg.pmic_chg_irq[CHGVAL_IRQ])
1573 debugfs_create_file("CHGVAL", 0444, pm8058_chg.dent,
1574 (void *)pm8058_chg.pmic_chg_irq[CHGVAL_IRQ],
1575 &rt_fops);
1576
1577 if (pm8058_chg.pmic_chg_irq[CHGINVAL_IRQ])
1578 debugfs_create_file("CHGINVAL", 0444, pm8058_chg.dent, (void *)
1579 pm8058_chg.pmic_chg_irq[CHGINVAL_IRQ],
1580 &rt_fops);
1581 if (pm8058_chg.pmic_chg_irq[CHGILIM_IRQ])
1582 debugfs_create_file("CHGILIM", 0444, pm8058_chg.dent, (void *)
1583 pm8058_chg.pmic_chg_irq[CHGILIM_IRQ],
1584 &rt_fops);
1585 if (pm8058_chg.pmic_chg_irq[VCP_IRQ])
1586 debugfs_create_file("VCP", 0444, pm8058_chg.dent,
1587 (void *)pm8058_chg.pmic_chg_irq[VCP_IRQ],
1588 &rt_fops);
1589 if (pm8058_chg.pmic_chg_irq[ATC_DONE_IRQ])
1590 debugfs_create_file("ATC_DONE", 0444, pm8058_chg.dent, (void *)
1591 pm8058_chg.pmic_chg_irq[ATC_DONE_IRQ],
1592 &rt_fops);
1593 if (pm8058_chg.pmic_chg_irq[ATCFAIL_IRQ])
1594 debugfs_create_file("ATCFAIL", 0444, pm8058_chg.dent, (void *)
1595 pm8058_chg.pmic_chg_irq[ATCFAIL_IRQ],
1596 &rt_fops);
1597 if (pm8058_chg.pmic_chg_irq[AUTO_CHGDONE_IRQ])
1598 debugfs_create_file("AUTO_CHGDONE", 0444, pm8058_chg.dent,
1599 (void *)
1600 pm8058_chg.pmic_chg_irq[AUTO_CHGDONE_IRQ],
1601 &rt_fops);
1602 if (pm8058_chg.pmic_chg_irq[AUTO_CHGFAIL_IRQ])
1603 debugfs_create_file("AUTO_CHGFAIL", 0444, pm8058_chg.dent,
1604 (void *)
1605 pm8058_chg.pmic_chg_irq[AUTO_CHGFAIL_IRQ],
1606 &rt_fops);
1607 if (pm8058_chg.pmic_chg_irq[CHGSTATE_IRQ])
1608 debugfs_create_file("CHGSTATE", 0444, pm8058_chg.dent, (void *)
1609 pm8058_chg.pmic_chg_irq[CHGSTATE_IRQ],
1610 &rt_fops);
1611 if (pm8058_chg.pmic_chg_irq[FASTCHG_IRQ])
1612 debugfs_create_file("FASTCHG", 0444, pm8058_chg.dent, (void *)
1613 pm8058_chg.pmic_chg_irq[FASTCHG_IRQ],
1614 &rt_fops);
1615 if (pm8058_chg.pmic_chg_irq[CHG_END_IRQ])
1616 debugfs_create_file("CHG_END", 0444, pm8058_chg.dent, (void *)
1617 pm8058_chg.pmic_chg_irq[CHG_END_IRQ],
1618 &rt_fops);
1619 if (pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ])
1620 debugfs_create_file("BATTTEMP", 0444, pm8058_chg.dent, (void *)
1621 pm8058_chg.pmic_chg_irq[BATTTEMP_IRQ],
1622 &rt_fops);
1623 if (pm8058_chg.pmic_chg_irq[CHGHOT_IRQ])
1624 debugfs_create_file("CHGHOT", 0444, pm8058_chg.dent,
1625 (void *)pm8058_chg.pmic_chg_irq[CHGHOT_IRQ],
1626 &rt_fops);
1627 if (pm8058_chg.pmic_chg_irq[CHGTLIMIT_IRQ])
1628 debugfs_create_file("CHGTLIMIT", 0444, pm8058_chg.dent, (void *)
1629 pm8058_chg.pmic_chg_irq[CHGTLIMIT_IRQ],
1630 &rt_fops);
1631 if (pm8058_chg.pmic_chg_irq[CHG_GONE_IRQ])
1632 debugfs_create_file("CHG_GONE", 0444, pm8058_chg.dent, (void *)
1633 pm8058_chg.pmic_chg_irq[CHG_GONE_IRQ],
1634 &rt_fops);
1635 if (pm8058_chg.pmic_chg_irq[VCPMAJOR_IRQ])
1636 debugfs_create_file("VCPMAJOR", 0444, pm8058_chg.dent, (void *)
1637 pm8058_chg.pmic_chg_irq[VCPMAJOR_IRQ],
1638 &rt_fops);
1639 if (pm8058_chg.pmic_chg_irq[BATFET_IRQ])
1640 debugfs_create_file("BATFET", 0444, pm8058_chg.dent,
1641 (void *)pm8058_chg.pmic_chg_irq[BATFET_IRQ],
1642 &rt_fops);
1643 if (pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ])
1644 debugfs_create_file("BATT_REPLACE", 0444, pm8058_chg.dent,
1645 (void *)
1646 pm8058_chg.pmic_chg_irq[BATT_REPLACE_IRQ],
1647 &rt_fops);
1648 if (pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ])
1649 debugfs_create_file("BATTCONNECT", 0444, pm8058_chg.dent,
1650 (void *)
1651 pm8058_chg.pmic_chg_irq[BATTCONNECT_IRQ],
1652 &rt_fops);
1653 if (pm8058_chg.pmic_chg_irq[VBATDET_IRQ])
1654 debugfs_create_file("VBATDET", 0444, pm8058_chg.dent, (void *)
1655 pm8058_chg.pmic_chg_irq[VBATDET_IRQ],
1656 &rt_fops);
1657 if (pm8058_chg.pmic_chg_irq[VBATDET_LOW_IRQ])
1658 debugfs_create_file("VBATDET_LOW", 0444, pm8058_chg.dent,
1659 (void *)
1660 pm8058_chg.pmic_chg_irq[VBATDET_LOW_IRQ],
1661 &rt_fops);
1662 debugfs_create_file("CHARGE_BATT", 0444, pm8058_chg.dent,
1663 NULL,
1664 &fet_fops);
1665}
1666#else
1667static inline void create_debugfs_entries(void)
1668{
1669}
1670#endif
1671
1672static void remove_debugfs_entries(void)
1673{
1674 debugfs_remove_recursive(pm8058_chg.dent);
1675}
1676
1677static struct msm_hardware_charger usb_hw_chg = {
Abhijeet Dharmapurikar0758e1e2011-07-14 18:11:41 -07001678 .type = CHG_TYPE_USB,
1679 .rating = 1,
1680 .name = "pm8058-usb",
1681 .start_charging = pm8058_start_charging,
1682 .stop_charging = pm8058_stop_charging,
1683 .charging_switched = pm8058_charging_switched,
1684 .start_system_current = pm8058_start_system_current,
1685 .stop_system_current = pm8058_stop_system_current,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001686};
1687
1688static int batt_read_adc(int channel, int *mv_reading)
1689{
1690 int ret;
1691 void *h;
1692 struct adc_chan_result adc_chan_result;
1693 struct completion conv_complete_evt;
1694
1695 pr_debug("%s: called for %d\n", __func__, channel);
1696 ret = adc_channel_open(channel, &h);
1697 if (ret) {
1698 pr_err("%s: couldnt open channel %d ret=%d\n",
1699 __func__, channel, ret);
1700 goto out;
1701 }
1702 init_completion(&conv_complete_evt);
1703 ret = adc_channel_request_conv(h, &conv_complete_evt);
1704 if (ret) {
1705 pr_err("%s: couldnt request conv channel %d ret=%d\n",
1706 __func__, channel, ret);
1707 goto out;
1708 }
1709 wait_for_completion(&conv_complete_evt);
1710 ret = adc_channel_read_result(h, &adc_chan_result);
1711 if (ret) {
1712 pr_err("%s: couldnt read result channel %d ret=%d\n",
1713 __func__, channel, ret);
1714 goto out;
1715 }
1716 ret = adc_channel_close(h);
1717 if (ret) {
1718 pr_err("%s: couldnt close channel %d ret=%d\n",
1719 __func__, channel, ret);
1720 }
1721 if (mv_reading)
1722 *mv_reading = adc_chan_result.measurement;
1723
1724 pr_debug("%s: done for %d\n", __func__, channel);
1725 return adc_chan_result.physical;
1726out:
1727 pr_debug("%s: done for %d\n", __func__, channel);
1728 return -EINVAL;
1729
1730}
1731
1732#define BATT_THERM_OPEN_MV 2000
1733static int pm8058_is_battery_present(void)
1734{
1735 int mv_reading;
1736
1737 mv_reading = 0;
1738 batt_read_adc(CHANNEL_ADC_BATT_THERM, &mv_reading);
1739 pr_debug("%s: therm_raw is %d\n", __func__, mv_reading);
1740 if (mv_reading > 0 && mv_reading < BATT_THERM_OPEN_MV)
1741 return 1;
1742
1743 return 0;
1744}
1745
1746static int pm8058_get_battery_temperature(void)
1747{
1748 return batt_read_adc(CHANNEL_ADC_BATT_THERM, NULL);
1749}
1750
1751#define BATT_THERM_OPERATIONAL_MAX_CELCIUS 40
1752#define BATT_THERM_OPERATIONAL_MIN_CELCIUS 0
1753static int pm8058_is_battery_temp_within_range(void)
1754{
1755 int therm_celcius;
1756
1757 therm_celcius = pm8058_get_battery_temperature();
1758 pr_debug("%s: therm_celcius is %d\n", __func__, therm_celcius);
1759 if (therm_celcius > 0
1760 && therm_celcius > BATT_THERM_OPERATIONAL_MIN_CELCIUS
1761 && therm_celcius < BATT_THERM_OPERATIONAL_MAX_CELCIUS)
1762 return 1;
1763
1764 return 0;
1765}
1766
1767#define BATT_ID_MAX_MV 800
1768#define BATT_ID_MIN_MV 600
1769static int pm8058_is_battery_id_valid(void)
1770{
1771 int batt_id_mv;
1772
1773 batt_id_mv = batt_read_adc(CHANNEL_ADC_BATT_ID, NULL);
1774 pr_debug("%s: batt_id_mv is %d\n", __func__, batt_id_mv);
1775
1776 /*
1777 * The readings are not in range
1778 * assume battery is present for now
1779 */
1780 return 1;
1781
1782 if (batt_id_mv > 0
1783 && batt_id_mv > BATT_ID_MIN_MV
1784 && batt_id_mv < BATT_ID_MAX_MV)
1785 return 1;
1786
1787 return 0;
1788}
1789
1790/* returns voltage in mV */
1791static int pm8058_get_battery_mvolts(void)
1792{
1793 int vbatt_mv;
1794
1795 vbatt_mv = batt_read_adc(CHANNEL_ADC_VBATT, NULL);
1796 pr_debug("%s: vbatt_mv is %d\n", __func__, vbatt_mv);
1797 if (vbatt_mv > 0)
1798 return vbatt_mv;
1799 /*
1800 * return 0 to tell the upper layers
1801 * we couldnt read the battery voltage
1802 */
1803 return 0;
1804}
1805
1806static int msm_battery_gauge_alarm_notify(struct notifier_block *nb,
1807 unsigned long status, void *unused)
1808{
1809 int rc;
1810
1811 pr_info("%s: status: %lu\n", __func__, status);
1812
1813 switch (status) {
1814 case 0:
1815 dev_err(pm8058_chg.dev,
1816 "%s: spurious interrupt\n", __func__);
1817 break;
1818 /* expected case - trip of low threshold */
1819 case 1:
1820 rc = pm8058_batt_alarm_state_set(0, 0);
1821 if (rc)
1822 dev_err(pm8058_chg.dev,
1823 "%s: unable to set alarm state\n", __func__);
1824 msm_charger_notify_event(NULL, CHG_BATT_NEEDS_RECHARGING);
1825 break;
1826 case 2:
1827 dev_err(pm8058_chg.dev,
1828 "%s: trip of high threshold\n", __func__);
1829 break;
1830 default:
1831 dev_err(pm8058_chg.dev,
1832 "%s: error received\n", __func__);
1833 };
1834
1835 return 0;
1836}
1837
1838static int pm8058_monitor_for_recharging(void)
1839{
1840 /* enable low comparator */
1841 return pm8058_batt_alarm_state_set(1, 0);
1842}
1843
1844static struct msm_battery_gauge pm8058_batt_gauge = {
1845 .get_battery_mvolts = pm8058_get_battery_mvolts,
1846 .get_battery_temperature = pm8058_get_battery_temperature,
1847 .is_battery_present = pm8058_is_battery_present,
1848 .is_battery_temp_within_range = pm8058_is_battery_temp_within_range,
1849 .is_battery_id_valid = pm8058_is_battery_id_valid,
1850 .monitor_for_recharging = pm8058_monitor_for_recharging,
1851};
1852
1853static int pm8058_usb_voltage_lower_limit(void)
1854{
1855 u8 temp, old;
1856 int ret = 0;
1857
1858 temp = 0x10;
1859 ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
1860 ret |= pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST, &old, 1);
1861 old = old & ~BIT(IGNORE_LL);
1862 temp = 0x90 | (0xF & old);
1863 ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
1864
1865 return ret;
1866}
1867
1868static int __devinit pm8058_charger_probe(struct platform_device *pdev)
1869{
1870 struct pm8058_chip *pm_chip;
1871 int rc = 0;
1872
1873 pm_chip = dev_get_drvdata(pdev->dev.parent);
1874 if (pm_chip == NULL) {
1875 pr_err("%s:no parent data passed in.\n", __func__);
1876 return -EFAULT;
1877 }
1878
1879 pm8058_chg.pm_chip = pm_chip;
1880 pm8058_chg.pdata = pdev->dev.platform_data;
1881 pm8058_chg.dev = &pdev->dev;
1882
1883 rc = request_irqs(pdev);
1884 if (rc) {
1885 pr_err("%s: couldnt register interrupts\n", __func__);
1886 goto out;
1887 }
1888
1889 rc = pm8058_usb_voltage_lower_limit();
1890 if (rc) {
1891 pr_err("%s: couldnt set ignore lower limit bit to 0\n",
1892 __func__);
1893 goto free_irq;
1894 }
1895
1896 rc = msm_charger_register(&usb_hw_chg);
1897 if (rc) {
1898 pr_err("%s: msm_charger_register failed ret=%d\n",
1899 __func__, rc);
1900 goto free_irq;
1901 }
1902
1903 pm_chg_batt_temp_disable(0);
1904 msm_battery_gauge_register(&pm8058_batt_gauge);
1905 __dump_chg_regs();
1906
1907 create_debugfs_entries();
1908 INIT_DELAYED_WORK(&pm8058_chg.veoc_begin_work, veoc_begin_work);
1909 INIT_DELAYED_WORK(&pm8058_chg.check_vbat_low_work, vbat_low_work);
1910 INIT_DELAYED_WORK(&pm8058_chg.chg_done_check_work, chg_done_check_work);
1911 INIT_DELAYED_WORK(&pm8058_chg.charging_check_work, charging_check_work);
1912
1913 /* determine what state the charger is in */
1914 pm8058_chg_determine_initial_state();
1915
1916 pm8058_chg_enable_irq(BATTTEMP_IRQ);
1917 pm8058_chg_enable_irq(BATTCONNECT_IRQ);
1918
1919 rc = pm8058_batt_alarm_state_set(0, 0);
1920 if (rc) {
1921 pr_err("%s: unable to set batt alarm state\n", __func__);
1922 goto free_irq;
1923 }
1924
1925 /*
1926 * The batt-alarm driver requires sane values for both min / max,
1927 * regardless of whether they're both activated.
1928 */
1929 rc = pm8058_batt_alarm_threshold_set(resume_mv, 4300);
1930 if (rc) {
1931 pr_err("%s: unable to set batt alarm threshold\n", __func__);
1932 goto free_irq;
1933 }
1934
1935 rc = pm8058_batt_alarm_hold_time_set(PM8058_BATT_ALARM_HOLD_TIME_16_MS);
1936 if (rc) {
1937 pr_err("%s: unable to set batt alarm hold time\n", __func__);
1938 goto free_irq;
1939 }
1940
1941 /* PWM enabled at 2Hz */
1942 rc = pm8058_batt_alarm_pwm_rate_set(1, 7, 4);
1943 if (rc) {
1944 pr_err("%s: unable to set batt alarm pwm rate\n", __func__);
1945 goto free_irq;
1946 }
1947
1948 rc = pm8058_batt_alarm_register_notifier(&alarm_notifier);
1949 if (rc) {
1950 pr_err("%s: unable to register alarm notifier\n", __func__);
1951 goto free_irq;
1952 }
1953
1954 pm8058_chg.inited = 1;
1955
1956 return 0;
1957
1958free_irq:
1959 free_irqs();
1960out:
1961 return rc;
1962}
1963
1964static int __devexit pm8058_charger_remove(struct platform_device *pdev)
1965{
1966 struct pm8058_charger_chip *chip = platform_get_drvdata(pdev);
1967 int rc;
1968
1969 msm_charger_notify_event(&usb_hw_chg, CHG_REMOVED_EVENT);
1970 msm_charger_unregister(&usb_hw_chg);
1971 cancel_delayed_work_sync(&pm8058_chg.veoc_begin_work);
1972 cancel_delayed_work_sync(&pm8058_chg.check_vbat_low_work);
1973 cancel_delayed_work_sync(&pm8058_chg.charging_check_work);
1974 free_irqs();
1975 remove_debugfs_entries();
1976 kfree(chip);
1977
1978 rc = pm8058_batt_alarm_state_set(0, 0);
1979 if (rc)
1980 pr_err("%s: unable to set batt alarm state\n", __func__);
1981
1982 rc |= pm8058_batt_alarm_unregister_notifier(&alarm_notifier);
1983 if (rc)
1984 pr_err("%s: unable to register alarm notifier\n", __func__);
1985 return rc;
1986}
1987
1988static struct platform_driver pm8058_charger_driver = {
1989 .probe = pm8058_charger_probe,
1990 .remove = __devexit_p(pm8058_charger_remove),
1991 .driver = {
1992 .name = "pm8058-charger",
1993 .owner = THIS_MODULE,
1994 },
1995};
1996
1997static int __init pm8058_charger_init(void)
1998{
1999 return platform_driver_register(&pm8058_charger_driver);
2000}
2001
2002static void __exit pm8058_charger_exit(void)
2003{
2004 platform_driver_unregister(&pm8058_charger_driver);
2005}
2006
2007late_initcall(pm8058_charger_init);
2008module_exit(pm8058_charger_exit);
2009
2010MODULE_LICENSE("GPL v2");
2011MODULE_DESCRIPTION("PMIC8058 BATTERY driver");
2012MODULE_VERSION("1.0");
2013MODULE_ALIAS("platform:pm8058_charger");