blob: 82582c410ba65dd0881a1073fdf77dc5a0b67105 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/platform_device.h>
18#include <linux/errno.h>
19#include <linux/mfd/pm8xxx/pm8921-charger.h>
20#include <linux/mfd/pm8xxx/pm8921-bms.h>
Siddartha Mohanadoss77d106e2011-09-20 16:25:59 -070021#include <linux/mfd/pm8xxx/pm8921-adc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070022#include <linux/mfd/pm8xxx/core.h>
23#include <linux/interrupt.h>
24#include <linux/power_supply.h>
25#include <linux/delay.h>
26#include <linux/bitops.h>
27#include <linux/workqueue.h>
28#include <linux/debugfs.h>
29#include <linux/slab.h>
30
31#include <mach/msm_xo.h>
32#include <mach/msm_hsusb.h>
33
34#define CHG_BUCK_CLOCK_CTRL 0x14
35
36#define PBL_ACCESS1 0x04
37#define PBL_ACCESS2 0x05
38#define SYS_CONFIG_1 0x06
39#define SYS_CONFIG_2 0x07
40#define CHG_CNTRL 0x204
41#define CHG_IBAT_MAX 0x205
42#define CHG_TEST 0x206
43#define CHG_BUCK_CTRL_TEST1 0x207
44#define CHG_BUCK_CTRL_TEST2 0x208
45#define CHG_BUCK_CTRL_TEST3 0x209
46#define COMPARATOR_OVERRIDE 0x20A
47#define PSI_TXRX_SAMPLE_DATA_0 0x20B
48#define PSI_TXRX_SAMPLE_DATA_1 0x20C
49#define PSI_TXRX_SAMPLE_DATA_2 0x20D
50#define PSI_TXRX_SAMPLE_DATA_3 0x20E
51#define PSI_CONFIG_STATUS 0x20F
52#define CHG_IBAT_SAFE 0x210
53#define CHG_ITRICKLE 0x211
54#define CHG_CNTRL_2 0x212
55#define CHG_VBAT_DET 0x213
56#define CHG_VTRICKLE 0x214
57#define CHG_ITERM 0x215
58#define CHG_CNTRL_3 0x216
59#define CHG_VIN_MIN 0x217
60#define CHG_TWDOG 0x218
61#define CHG_TTRKL_MAX 0x219
62#define CHG_TEMP_THRESH 0x21A
63#define CHG_TCHG_MAX 0x21B
64#define USB_OVP_CONTROL 0x21C
65#define DC_OVP_CONTROL 0x21D
66#define USB_OVP_TEST 0x21E
67#define DC_OVP_TEST 0x21F
68#define CHG_VDD_MAX 0x220
69#define CHG_VDD_SAFE 0x221
70#define CHG_VBAT_BOOT_THRESH 0x222
71#define USB_OVP_TRIM 0x355
72#define BUCK_CONTROL_TRIM1 0x356
73#define BUCK_CONTROL_TRIM2 0x357
74#define BUCK_CONTROL_TRIM3 0x358
75#define BUCK_CONTROL_TRIM4 0x359
76#define CHG_DEFAULTS_TRIM 0x35A
77#define CHG_ITRIM 0x35B
78#define CHG_TTRIM 0x35C
79#define CHG_COMP_OVR 0x20A
80
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -070081/* check EOC every 10 seconds */
82#define EOC_CHECK_PERIOD_MS 10000
83
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084enum chg_fsm_state {
85 FSM_STATE_OFF_0 = 0,
86 FSM_STATE_BATFETDET_START_12 = 12,
87 FSM_STATE_BATFETDET_END_16 = 16,
88 FSM_STATE_ON_CHG_HIGHI_1 = 1,
89 FSM_STATE_ATC_2A = 2,
90 FSM_STATE_ATC_2B = 18,
91 FSM_STATE_ON_BAT_3 = 3,
92 FSM_STATE_ATC_FAIL_4 = 4 ,
93 FSM_STATE_DELAY_5 = 5,
94 FSM_STATE_ON_CHG_AND_BAT_6 = 6,
95 FSM_STATE_FAST_CHG_7 = 7,
96 FSM_STATE_TRKL_CHG_8 = 8,
97 FSM_STATE_CHG_FAIL_9 = 9,
98 FSM_STATE_EOC_10 = 10,
99 FSM_STATE_ON_CHG_VREGOK_11 = 11,
100 FSM_STATE_ATC_PAUSE_13 = 13,
101 FSM_STATE_FAST_CHG_PAUSE_14 = 14,
102 FSM_STATE_TRKL_CHG_PAUSE_15 = 15,
103 FSM_STATE_START_BOOT = 20,
104 FSM_STATE_FLCB_VREGOK = 21,
105 FSM_STATE_FLCB = 22,
106};
107
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700108enum chg_regulation_loop {
109 VDD_LOOP = BIT(3),
110 BAT_CURRENT_LOOP = BIT(2),
111 INPUT_CURRENT_LOOP = BIT(1),
112 INPUT_VOLTAGE_LOOP = BIT(0),
113 CHG_ALL_LOOPS = VDD_LOOP | BAT_CURRENT_LOOP
114 | INPUT_CURRENT_LOOP | INPUT_VOLTAGE_LOOP,
115};
116
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117enum pmic_chg_interrupts {
118 USBIN_VALID_IRQ = 0,
119 USBIN_OV_IRQ,
120 BATT_INSERTED_IRQ,
121 VBATDET_LOW_IRQ,
122 USBIN_UV_IRQ,
123 VBAT_OV_IRQ,
124 CHGWDOG_IRQ,
125 VCP_IRQ,
126 ATCDONE_IRQ,
127 ATCFAIL_IRQ,
128 CHGDONE_IRQ,
129 CHGFAIL_IRQ,
130 CHGSTATE_IRQ,
131 LOOP_CHANGE_IRQ,
132 FASTCHG_IRQ,
133 TRKLCHG_IRQ,
134 BATT_REMOVED_IRQ,
135 BATTTEMP_HOT_IRQ,
136 CHGHOT_IRQ,
137 BATTTEMP_COLD_IRQ,
138 CHG_GONE_IRQ,
139 BAT_TEMP_OK_IRQ,
140 COARSE_DET_LOW_IRQ,
141 VDD_LOOP_IRQ,
142 VREG_OV_IRQ,
143 VBATDET_IRQ,
144 BATFET_IRQ,
145 PSI_IRQ,
146 DCIN_VALID_IRQ,
147 DCIN_OV_IRQ,
148 DCIN_UV_IRQ,
149 PM_CHG_MAX_INTS,
150};
151
152struct bms_notify {
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700153 int is_battery_full;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154 int is_charging;
155 struct work_struct work;
156};
157
158/**
159 * struct pm8921_chg_chip -device information
160 * @dev: device pointer to access the parent
161 * @is_usb_path_used: indicates whether USB charging is used at all
162 * @is_usb_path_used: indicates whether DC charging is used at all
163 * @usb_present: present status of usb
164 * @dc_present: present status of dc
165 * @usb_charger_current: usb current to charge the battery with used when
166 * the usb path is enabled or charging is resumed
167 * @safety_time: max time for which charging will happen
168 * @update_time: how frequently the userland needs to be updated
169 * @max_voltage: the max volts the batt should be charged up to
170 * @min_voltage: the min battery voltage before turning the FETon
171 * @resume_voltage: the voltage at which the battery should resume
172 * charging
173 * @term_current: The charging based term current
174 *
175 */
176struct pm8921_chg_chip {
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700177 struct device *dev;
178 unsigned int usb_present;
179 unsigned int dc_present;
180 unsigned int usb_charger_current;
181 unsigned int max_bat_chg_current;
182 unsigned int pmic_chg_irq[PM_CHG_MAX_INTS];
183 unsigned int safety_time;
184 unsigned int ttrkl_time;
185 unsigned int update_time;
186 unsigned int max_voltage;
187 unsigned int min_voltage;
188 unsigned int cool_temp;
189 unsigned int warm_temp;
190 unsigned int temp_check_period;
191 unsigned int cool_bat_chg_current;
192 unsigned int warm_bat_chg_current;
193 unsigned int cool_bat_voltage;
194 unsigned int warm_bat_voltage;
195 unsigned int resume_voltage;
196 unsigned int term_current;
197 unsigned int vbat_channel;
198 unsigned int batt_temp_channel;
199 unsigned int batt_id_channel;
200 struct power_supply usb_psy;
201 struct power_supply dc_psy;
202 struct power_supply batt_psy;
203 struct dentry *dent;
204 struct bms_notify bms_notify;
Amir Samuelovd31ef502011-10-26 14:41:36 +0200205 struct ext_chg_pm8921 *ext;
206 bool ext_charging;
207 bool ext_charge_done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208 DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700209 struct work_struct battery_id_valid_work;
210 int64_t batt_id_min;
211 int64_t batt_id_max;
212 int trkl_voltage;
213 int weak_voltage;
214 int trkl_current;
215 int weak_current;
216 int vin_min;
217 int *thermal_mitigation;
218 int thermal_levels;
219 struct delayed_work update_heartbeat_work;
220 struct delayed_work eoc_work;
221 struct wake_lock eoc_wake_lock;
222 enum pm8921_chg_cold_thr cold_thr;
223 enum pm8921_chg_hot_thr hot_thr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224};
225
226static int charging_disabled;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -0700227static int thermal_mitigation;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700228
229static struct pm8921_chg_chip *the_chip;
230
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -0700231static struct pm8921_adc_arb_btm_param btm_config;
232
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700233static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr,
234 u8 mask, u8 val)
235{
236 int rc;
237 u8 reg;
238
239 rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
240 if (rc) {
241 pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n", addr, rc);
242 return rc;
243 }
244 reg &= ~mask;
245 reg |= val & mask;
246 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
247 if (rc) {
248 pr_err("pm8xxx_writeb failed: addr=%03X, rc=%d\n", addr, rc);
249 return rc;
250 }
251 return 0;
252}
253
254#define CAPTURE_FSM_STATE_CMD 0xC2
255#define READ_BANK_7 0x70
256#define READ_BANK_4 0x40
257static int pm_chg_get_fsm_state(struct pm8921_chg_chip *chip)
258{
259 u8 temp;
260 int err, ret = 0;
261
262 temp = CAPTURE_FSM_STATE_CMD;
263 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
264 if (err) {
265 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
266 return err;
267 }
268
269 temp = READ_BANK_7;
270 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
271 if (err) {
272 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
273 return err;
274 }
275
276 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
277 if (err) {
278 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
279 return err;
280 }
281 /* get the lower 4 bits */
282 ret = temp & 0xF;
283
284 temp = READ_BANK_4;
285 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
286 if (err) {
287 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
288 return err;
289 }
290
291 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
292 if (err) {
293 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
294 return err;
295 }
296 /* get the upper 1 bit */
297 ret |= (temp & 0x1) << 4;
298 return ret;
299}
300
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700301#define READ_BANK_6 0x60
302static int pm_chg_get_regulation_loop(struct pm8921_chg_chip *chip)
303{
304 u8 temp;
305 int err;
306
307 temp = READ_BANK_6;
308 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
309 if (err) {
310 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
311 return err;
312 }
313
314 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
315 if (err) {
316 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
317 return err;
318 }
319
320 /* return the lower 4 bits */
321 return temp & CHG_ALL_LOOPS;
322}
323
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700324#define CHG_USB_SUSPEND_BIT BIT(2)
325static int pm_chg_usb_suspend_enable(struct pm8921_chg_chip *chip, int enable)
326{
327 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_USB_SUSPEND_BIT,
328 enable ? CHG_USB_SUSPEND_BIT : 0);
329}
330
331#define CHG_EN_BIT BIT(7)
332static int pm_chg_auto_enable(struct pm8921_chg_chip *chip, int enable)
333{
334 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_EN_BIT,
335 enable ? CHG_EN_BIT : 0);
336}
337
338#define CHG_CHARGE_DIS_BIT BIT(1)
339static int pm_chg_charge_dis(struct pm8921_chg_chip *chip, int disable)
340{
341 return pm_chg_masked_write(chip, CHG_CNTRL, CHG_CHARGE_DIS_BIT,
342 disable ? CHG_CHARGE_DIS_BIT : 0);
343}
344
345#define PM8921_CHG_V_MIN_MV 3240
346#define PM8921_CHG_V_STEP_MV 20
347#define PM8921_CHG_VDDMAX_MAX 4500
348#define PM8921_CHG_VDDMAX_MIN 3400
349#define PM8921_CHG_V_MASK 0x7F
350static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
351{
352 u8 temp;
353
354 if (voltage < PM8921_CHG_VDDMAX_MIN
355 || voltage > PM8921_CHG_VDDMAX_MAX) {
356 pr_err("bad mV=%d asked to set\n", voltage);
357 return -EINVAL;
358 }
359 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
360 pr_debug("voltage=%d setting %02x\n", voltage, temp);
361 return pm_chg_masked_write(chip, CHG_VDD_MAX, PM8921_CHG_V_MASK, temp);
362}
363
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700364static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
365{
366 u8 temp;
367 int rc;
368
369 rc = pm8xxx_readb(chip->dev->parent, CHG_VDD_MAX, &temp);
370 if (rc) {
371 pr_err("rc = %d while reading vdd max\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700372 *voltage = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700373 return rc;
374 }
375 temp &= PM8921_CHG_V_MASK;
376 *voltage = (int)temp * PM8921_CHG_V_STEP_MV + PM8921_CHG_V_MIN_MV;
377 return 0;
378}
379
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380#define PM8921_CHG_VDDSAFE_MIN 3400
381#define PM8921_CHG_VDDSAFE_MAX 4500
382static int pm_chg_vddsafe_set(struct pm8921_chg_chip *chip, int voltage)
383{
384 u8 temp;
385
386 if (voltage < PM8921_CHG_VDDSAFE_MIN
387 || voltage > PM8921_CHG_VDDSAFE_MAX) {
388 pr_err("bad mV=%d asked to set\n", voltage);
389 return -EINVAL;
390 }
391 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
392 pr_debug("voltage=%d setting %02x\n", voltage, temp);
393 return pm_chg_masked_write(chip, CHG_VDD_SAFE, PM8921_CHG_V_MASK, temp);
394}
395
396#define PM8921_CHG_VBATDET_MIN 3240
397#define PM8921_CHG_VBATDET_MAX 5780
398static int pm_chg_vbatdet_set(struct pm8921_chg_chip *chip, int voltage)
399{
400 u8 temp;
401
402 if (voltage < PM8921_CHG_VBATDET_MIN
403 || voltage > PM8921_CHG_VBATDET_MAX) {
404 pr_err("bad mV=%d asked to set\n", voltage);
405 return -EINVAL;
406 }
407 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
408 pr_debug("voltage=%d setting %02x\n", voltage, temp);
409 return pm_chg_masked_write(chip, CHG_VBAT_DET, PM8921_CHG_V_MASK, temp);
410}
411
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -0700412#define PM8921_CHG_VINMIN_MIN_MV 3800
413#define PM8921_CHG_VINMIN_STEP_MV 100
414#define PM8921_CHG_VINMIN_USABLE_MAX 6500
415#define PM8921_CHG_VINMIN_USABLE_MIN 4300
416#define PM8921_CHG_VINMIN_MASK 0x1F
417static int pm_chg_vinmin_set(struct pm8921_chg_chip *chip, int voltage)
418{
419 u8 temp;
420
421 if (voltage < PM8921_CHG_VINMIN_USABLE_MIN
422 || voltage > PM8921_CHG_VINMIN_USABLE_MAX) {
423 pr_err("bad mV=%d asked to set\n", voltage);
424 return -EINVAL;
425 }
426 temp = (voltage - PM8921_CHG_VINMIN_MIN_MV) / PM8921_CHG_VINMIN_STEP_MV;
427 pr_debug("voltage=%d setting %02x\n", voltage, temp);
428 return pm_chg_masked_write(chip, CHG_VIN_MIN, PM8921_CHG_VINMIN_MASK,
429 temp);
430}
431
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432#define PM8921_CHG_IBATMAX_MIN 325
433#define PM8921_CHG_IBATMAX_MAX 2000
434#define PM8921_CHG_I_MIN_MA 225
435#define PM8921_CHG_I_STEP_MA 50
436#define PM8921_CHG_I_MASK 0x3F
437static int pm_chg_ibatmax_set(struct pm8921_chg_chip *chip, int chg_current)
438{
439 u8 temp;
440
441 if (chg_current < PM8921_CHG_IBATMAX_MIN
442 || chg_current > PM8921_CHG_IBATMAX_MAX) {
443 pr_err("bad mA=%d asked to set\n", chg_current);
444 return -EINVAL;
445 }
446 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
447 return pm_chg_masked_write(chip, CHG_IBAT_MAX, PM8921_CHG_I_MASK, temp);
448}
449
450#define PM8921_CHG_IBATSAFE_MIN 225
451#define PM8921_CHG_IBATSAFE_MAX 3375
452static int pm_chg_ibatsafe_set(struct pm8921_chg_chip *chip, int chg_current)
453{
454 u8 temp;
455
456 if (chg_current < PM8921_CHG_IBATSAFE_MIN
457 || chg_current > PM8921_CHG_IBATSAFE_MAX) {
458 pr_err("bad mA=%d asked to set\n", chg_current);
459 return -EINVAL;
460 }
461 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
462 return pm_chg_masked_write(chip, CHG_IBAT_SAFE,
463 PM8921_CHG_I_MASK, temp);
464}
465
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700466#define PM8921_CHG_ITERM_MIN_MA 50
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700467#define PM8921_CHG_ITERM_MAX_MA 200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468#define PM8921_CHG_ITERM_STEP_MA 10
469#define PM8921_CHG_ITERM_MASK 0xF
470static int pm_chg_iterm_set(struct pm8921_chg_chip *chip, int chg_current)
471{
472 u8 temp;
473
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700474 if (chg_current < PM8921_CHG_ITERM_MIN_MA
475 || chg_current > PM8921_CHG_ITERM_MAX_MA) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700476 pr_err("bad mA=%d asked to set\n", chg_current);
477 return -EINVAL;
478 }
479
480 temp = (chg_current - PM8921_CHG_ITERM_MIN_MA)
481 / PM8921_CHG_ITERM_STEP_MA;
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700482 return pm_chg_masked_write(chip, CHG_ITERM, PM8921_CHG_ITERM_MASK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700483 temp);
484}
485
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700486static int pm_chg_iterm_get(struct pm8921_chg_chip *chip, int *chg_current)
487{
488 u8 temp;
489 int rc;
490
491 rc = pm8xxx_readb(chip->dev->parent, CHG_ITERM, &temp);
492 if (rc) {
493 pr_err("err=%d reading CHG_ITEM\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700494 *chg_current = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700495 return rc;
496 }
497 temp &= PM8921_CHG_ITERM_MASK;
498 *chg_current = (int)temp * PM8921_CHG_ITERM_STEP_MA
499 + PM8921_CHG_ITERM_MIN_MA;
500 return 0;
501}
502
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700503#define PM8921_CHG_IUSB_MASK 0x1C
504#define PM8921_CHG_IUSB_MAX 7
505#define PM8921_CHG_IUSB_MIN 0
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700506static int pm_chg_iusbmax_set(struct pm8921_chg_chip *chip, int reg_val)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700507{
508 u8 temp;
509
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700510 if (reg_val < PM8921_CHG_IUSB_MIN || reg_val > PM8921_CHG_IUSB_MAX) {
511 pr_err("bad mA=%d asked to set\n", reg_val);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700512 return -EINVAL;
513 }
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700514 temp = reg_val << 2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700515 return pm_chg_masked_write(chip, PBL_ACCESS2, PM8921_CHG_IUSB_MASK,
516 temp);
517}
518
519#define PM8921_CHG_WD_MASK 0x1F
520static int pm_chg_disable_wd(struct pm8921_chg_chip *chip)
521{
522 /* writing 0 to the wd timer disables it */
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700523 return pm_chg_masked_write(chip, CHG_TWDOG, PM8921_CHG_WD_MASK, 0);
524}
525
526#define PM8921_CHG_TCHG_MASK 0x3F
527#define PM8921_CHG_TCHG_MIN 4
528#define PM8921_CHG_TCHG_MAX 512
529#define PM8921_CHG_TCHG_STEP 4
530static int pm_chg_tchg_max_set(struct pm8921_chg_chip *chip, int minutes)
531{
532 u8 temp;
533
534 if (minutes < PM8921_CHG_TCHG_MIN || minutes > PM8921_CHG_TCHG_MAX) {
535 pr_err("bad max minutes =%d asked to set\n", minutes);
536 return -EINVAL;
537 }
538
539 temp = (minutes - 1)/PM8921_CHG_TCHG_STEP;
540 return pm_chg_masked_write(chip, CHG_TCHG_MAX, PM8921_CHG_TCHG_MASK,
541 temp);
542}
543
544#define PM8921_CHG_TTRKL_MASK 0x1F
545#define PM8921_CHG_TTRKL_MIN 1
546#define PM8921_CHG_TTRKL_MAX 64
547static int pm_chg_ttrkl_max_set(struct pm8921_chg_chip *chip, int minutes)
548{
549 u8 temp;
550
551 if (minutes < PM8921_CHG_TTRKL_MIN || minutes > PM8921_CHG_TTRKL_MAX) {
552 pr_err("bad max minutes =%d asked to set\n", minutes);
553 return -EINVAL;
554 }
555
556 temp = minutes - 1;
557 return pm_chg_masked_write(chip, CHG_TTRKL_MAX, PM8921_CHG_TTRKL_MASK,
558 temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559}
560
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -0700561#define PM8921_CHG_VTRKL_MIN_MV 2050
562#define PM8921_CHG_VTRKL_MAX_MV 2800
563#define PM8921_CHG_VTRKL_STEP_MV 50
564#define PM8921_CHG_VTRKL_SHIFT 4
565#define PM8921_CHG_VTRKL_MASK 0xF0
566static int pm_chg_vtrkl_low_set(struct pm8921_chg_chip *chip, int millivolts)
567{
568 u8 temp;
569
570 if (millivolts < PM8921_CHG_VTRKL_MIN_MV
571 || millivolts > PM8921_CHG_VTRKL_MAX_MV) {
572 pr_err("bad voltage = %dmV asked to set\n", millivolts);
573 return -EINVAL;
574 }
575
576 temp = (millivolts - PM8921_CHG_VTRKL_MIN_MV)/PM8921_CHG_VTRKL_STEP_MV;
577 temp = temp << PM8921_CHG_VTRKL_SHIFT;
578 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VTRKL_MASK,
579 temp);
580}
581
582#define PM8921_CHG_VWEAK_MIN_MV 2100
583#define PM8921_CHG_VWEAK_MAX_MV 3600
584#define PM8921_CHG_VWEAK_STEP_MV 100
585#define PM8921_CHG_VWEAK_MASK 0x0F
586static int pm_chg_vweak_set(struct pm8921_chg_chip *chip, int millivolts)
587{
588 u8 temp;
589
590 if (millivolts < PM8921_CHG_VWEAK_MIN_MV
591 || millivolts > PM8921_CHG_VWEAK_MAX_MV) {
592 pr_err("bad voltage = %dmV asked to set\n", millivolts);
593 return -EINVAL;
594 }
595
596 temp = (millivolts - PM8921_CHG_VWEAK_MIN_MV)/PM8921_CHG_VWEAK_STEP_MV;
597 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VWEAK_MASK,
598 temp);
599}
600
601#define PM8921_CHG_ITRKL_MIN_MA 50
602#define PM8921_CHG_ITRKL_MAX_MA 200
603#define PM8921_CHG_ITRKL_MASK 0x0F
604#define PM8921_CHG_ITRKL_STEP_MA 10
605static int pm_chg_itrkl_set(struct pm8921_chg_chip *chip, int milliamps)
606{
607 u8 temp;
608
609 if (milliamps < PM8921_CHG_ITRKL_MIN_MA
610 || milliamps > PM8921_CHG_ITRKL_MAX_MA) {
611 pr_err("bad current = %dmA asked to set\n", milliamps);
612 return -EINVAL;
613 }
614
615 temp = (milliamps - PM8921_CHG_ITRKL_MIN_MA)/PM8921_CHG_ITRKL_STEP_MA;
616
617 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_ITRKL_MASK,
618 temp);
619}
620
621#define PM8921_CHG_IWEAK_MIN_MA 325
622#define PM8921_CHG_IWEAK_MAX_MA 525
623#define PM8921_CHG_IWEAK_SHIFT 7
624#define PM8921_CHG_IWEAK_MASK 0x80
625static int pm_chg_iweak_set(struct pm8921_chg_chip *chip, int milliamps)
626{
627 u8 temp;
628
629 if (milliamps < PM8921_CHG_IWEAK_MIN_MA
630 || milliamps > PM8921_CHG_IWEAK_MAX_MA) {
631 pr_err("bad current = %dmA asked to set\n", milliamps);
632 return -EINVAL;
633 }
634
635 if (milliamps < PM8921_CHG_IWEAK_MAX_MA)
636 temp = 0;
637 else
638 temp = 1;
639
640 temp = temp << PM8921_CHG_IWEAK_SHIFT;
641 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_IWEAK_MASK,
642 temp);
643}
644
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700645#define PM8921_CHG_BATT_TEMP_THR_COLD BIT(1)
646#define PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT 1
647static int pm_chg_batt_cold_temp_config(struct pm8921_chg_chip *chip,
648 enum pm8921_chg_cold_thr cold_thr)
649{
650 u8 temp;
651
652 temp = cold_thr << PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT;
653 temp = temp & PM8921_CHG_BATT_TEMP_THR_COLD;
654 return pm_chg_masked_write(chip, CHG_CNTRL_2,
655 PM8921_CHG_BATT_TEMP_THR_COLD,
656 temp);
657}
658
659#define PM8921_CHG_BATT_TEMP_THR_HOT BIT(0)
660#define PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT 0
661static int pm_chg_batt_hot_temp_config(struct pm8921_chg_chip *chip,
662 enum pm8921_chg_hot_thr hot_thr)
663{
664 u8 temp;
665
666 temp = hot_thr << PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT;
667 temp = temp & PM8921_CHG_BATT_TEMP_THR_HOT;
668 return pm_chg_masked_write(chip, CHG_CNTRL_2,
669 PM8921_CHG_BATT_TEMP_THR_HOT,
670 temp);
671}
672
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -0700673static int64_t read_battery_id(struct pm8921_chg_chip *chip)
674{
675 int rc;
676 struct pm8921_adc_chan_result result;
677
678 rc = pm8921_adc_read(chip->batt_id_channel, &result);
679 if (rc) {
680 pr_err("error reading batt id channel = %d, rc = %d\n",
681 chip->vbat_channel, rc);
682 return rc;
683 }
684 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
685 result.measurement);
686 return result.physical;
687}
688
689static int is_battery_valid(struct pm8921_chg_chip *chip)
690{
691 int64_t rc;
692
693 if (chip->batt_id_min == 0 && chip->batt_id_max == 0)
694 return 1;
695
696 rc = read_battery_id(chip);
697 if (rc < 0) {
698 pr_err("error reading batt id channel = %d, rc = %lld\n",
699 chip->vbat_channel, rc);
700 /* assume battery id is valid when adc error happens */
701 return 1;
702 }
703
704 if (rc < chip->batt_id_min || rc > chip->batt_id_max) {
705 pr_err("batt_id phy =%lld is not valid\n", rc);
706 return 0;
707 }
708 return 1;
709}
710
711static void check_battery_valid(struct pm8921_chg_chip *chip)
712{
713 if (is_battery_valid(chip) == 0) {
714 pr_err("batt_id not valid, disbling charging\n");
715 pm_chg_auto_enable(chip, 0);
716 } else {
717 pm_chg_auto_enable(chip, !charging_disabled);
718 }
719}
720
721static void battery_id_valid(struct work_struct *work)
722{
723 struct pm8921_chg_chip *chip = container_of(work,
724 struct pm8921_chg_chip, battery_id_valid_work);
725
726 check_battery_valid(chip);
727}
728
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729static void pm8921_chg_enable_irq(struct pm8921_chg_chip *chip, int interrupt)
730{
731 if (!__test_and_set_bit(interrupt, chip->enabled_irqs)) {
732 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
733 enable_irq(chip->pmic_chg_irq[interrupt]);
734 }
735}
736
737static void pm8921_chg_disable_irq(struct pm8921_chg_chip *chip, int interrupt)
738{
739 if (__test_and_clear_bit(interrupt, chip->enabled_irqs)) {
740 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
741 disable_irq_nosync(chip->pmic_chg_irq[interrupt]);
742 }
743}
744
745static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
746{
747 return pm8xxx_read_irq_stat(chip->dev->parent,
748 chip->pmic_chg_irq[irq_id]);
749}
750
751/* Treat OverVoltage/UnderVoltage as source missing */
752static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
753{
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -0700754 return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700755}
756
757/* Treat OverVoltage/UnderVoltage as source missing */
758static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
759{
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -0700760 return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700761}
762
Amir Samuelovd31ef502011-10-26 14:41:36 +0200763static bool is_ext_charging(struct pm8921_chg_chip *chip)
764{
765 if (chip->ext == NULL)
766 return false;
767
768 if (chip->ext_charging)
769 return true;
770
771 return false;
772}
773
774static bool is_ext_trickle_charging(struct pm8921_chg_chip *chip)
775{
776 if (chip->ext == NULL)
777 return false;
778
779 if (chip->ext->is_trickle(chip->ext->ctx))
780 return true;
781
782 return false;
783}
784
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700785static int is_battery_charging(int fsm_state)
786{
Amir Samuelovd31ef502011-10-26 14:41:36 +0200787 if (is_ext_charging(the_chip))
788 return 1;
789
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790 switch (fsm_state) {
791 case FSM_STATE_ATC_2A:
792 case FSM_STATE_ATC_2B:
793 case FSM_STATE_ON_CHG_AND_BAT_6:
794 case FSM_STATE_FAST_CHG_7:
795 case FSM_STATE_TRKL_CHG_8:
796 return 1;
797 }
798 return 0;
799}
800
801static void bms_notify(struct work_struct *work)
802{
803 struct bms_notify *n = container_of(work, struct bms_notify, work);
804
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700805 if (n->is_charging) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700806 pm8921_bms_charging_began();
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700807 } else {
808 pm8921_bms_charging_end(n->is_battery_full);
809 n->is_battery_full = 0;
810 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811}
812
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -0700813static void bms_notify_check(struct pm8921_chg_chip *chip)
814{
815 int fsm_state, new_is_charging;
816
817 fsm_state = pm_chg_get_fsm_state(chip);
818 new_is_charging = is_battery_charging(fsm_state);
819
820 if (chip->bms_notify.is_charging ^ new_is_charging) {
821 chip->bms_notify.is_charging = new_is_charging;
822 schedule_work(&(chip->bms_notify.work));
823 }
824}
825
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700826static enum power_supply_property pm_power_props[] = {
827 POWER_SUPPLY_PROP_PRESENT,
Willie Ruan9ad6d832011-08-19 11:58:42 -0700828 POWER_SUPPLY_PROP_ONLINE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700829};
830
831static char *pm_power_supplied_to[] = {
832 "battery",
833};
834
835static int pm_power_get_property(struct power_supply *psy,
836 enum power_supply_property psp,
837 union power_supply_propval *val)
838{
839 struct pm8921_chg_chip *chip;
840
841 switch (psp) {
842 case POWER_SUPPLY_PROP_PRESENT:
Willie Ruan9ad6d832011-08-19 11:58:42 -0700843 case POWER_SUPPLY_PROP_ONLINE:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700844 if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
845 chip = container_of(psy, struct pm8921_chg_chip,
846 dc_psy);
847 val->intval = is_dc_chg_plugged_in(chip);
848 }
849 if (psy->type == POWER_SUPPLY_TYPE_USB) {
850 chip = container_of(psy, struct pm8921_chg_chip,
851 usb_psy);
852 val->intval = is_usb_chg_plugged_in(chip);
853 }
854 break;
855 default:
856 return -EINVAL;
857 }
858 return 0;
859}
860
861static enum power_supply_property msm_batt_power_props[] = {
862 POWER_SUPPLY_PROP_STATUS,
863 POWER_SUPPLY_PROP_CHARGE_TYPE,
864 POWER_SUPPLY_PROP_HEALTH,
865 POWER_SUPPLY_PROP_PRESENT,
866 POWER_SUPPLY_PROP_TECHNOLOGY,
867 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
868 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
869 POWER_SUPPLY_PROP_VOLTAGE_NOW,
870 POWER_SUPPLY_PROP_CAPACITY,
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -0700871 POWER_SUPPLY_PROP_CURRENT_NOW,
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700872 POWER_SUPPLY_PROP_TEMP,
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -0700873 POWER_SUPPLY_PROP_ENERGY_FULL,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700874};
875
876static int get_prop_battery_mvolts(struct pm8921_chg_chip *chip)
877{
878 int rc;
879 struct pm8921_adc_chan_result result;
880
881 rc = pm8921_adc_read(chip->vbat_channel, &result);
882 if (rc) {
883 pr_err("error reading adc channel = %d, rc = %d\n",
884 chip->vbat_channel, rc);
885 return rc;
886 }
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -0700887 pr_debug("mvolts phy = %lld meas = 0x%llx\n", result.physical,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700888 result.measurement);
889 return (int)result.physical;
890}
891
892static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
893{
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -0700894 int percent_soc = pm8921_bms_get_percent_charge();
895
896 if (percent_soc <= 10)
897 pr_warn("low battery charge = %d%%\n", percent_soc);
898
899 return percent_soc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900}
901
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -0700902static int get_prop_batt_current(struct pm8921_chg_chip *chip)
903{
904 int result_ma, rc;
905
906 rc = pm8921_bms_get_battery_current(&result_ma);
907 if (rc) {
908 pr_err("unable to get batt current rc = %d\n", rc);
909 return rc;
910 } else {
911 return result_ma;
912 }
913}
914
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -0700915static int get_prop_batt_fcc(struct pm8921_chg_chip *chip)
916{
917 int rc;
918
919 rc = pm8921_bms_get_fcc();
920 if (rc < 0)
921 pr_err("unable to get batt fcc rc = %d\n", rc);
922 return rc;
923}
924
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700925static int get_prop_batt_health(struct pm8921_chg_chip *chip)
926{
927 int temp;
928
929 temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
930 if (temp)
931 return POWER_SUPPLY_HEALTH_OVERHEAT;
932
933 temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
934 if (temp)
935 return POWER_SUPPLY_HEALTH_COLD;
936
937 return POWER_SUPPLY_HEALTH_GOOD;
938}
939
940static int get_prop_batt_present(struct pm8921_chg_chip *chip)
941{
942 return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
943}
944
945static int get_prop_charge_type(struct pm8921_chg_chip *chip)
946{
947 int temp;
948
Amir Samuelovd31ef502011-10-26 14:41:36 +0200949 if (!get_prop_batt_present(chip))
950 return POWER_SUPPLY_CHARGE_TYPE_NONE;
951
952 if (is_ext_trickle_charging(chip))
953 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
954
955 if (is_ext_charging(chip))
956 return POWER_SUPPLY_CHARGE_TYPE_FAST;
957
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700958 temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
959 if (temp)
960 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
961
962 temp = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
963 if (temp)
964 return POWER_SUPPLY_CHARGE_TYPE_FAST;
965
966 return POWER_SUPPLY_CHARGE_TYPE_NONE;
967}
968
969static int get_prop_batt_status(struct pm8921_chg_chip *chip)
970{
971 int temp = 0;
972
Amir Samuelovd31ef502011-10-26 14:41:36 +0200973 if (!get_prop_batt_present(chip))
974 return POWER_SUPPLY_STATUS_UNKNOWN;
975
976 if (chip->ext) {
977 if (chip->ext_charge_done)
978 return POWER_SUPPLY_STATUS_FULL;
979
980 if (chip->ext_charging)
981 return POWER_SUPPLY_STATUS_CHARGING;
982 }
983
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700984 /* TODO reading the FSM state is more reliable */
985 temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
986
987 temp |= pm_chg_get_rt_status(chip, FASTCHG_IRQ);
988 if (temp)
989 return POWER_SUPPLY_STATUS_CHARGING;
990 /*
991 * The battery is not charging
992 * check the FET - if on battery is discharging
993 * - if off battery is isolated(full) and the system
994 * is being driven from a charger
995 */
996 temp = pm_chg_get_rt_status(chip, BATFET_IRQ);
997 if (temp)
998 return POWER_SUPPLY_STATUS_DISCHARGING;
999
1000 return POWER_SUPPLY_STATUS_FULL;
1001}
1002
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001003static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
1004{
1005 int rc;
1006 struct pm8921_adc_chan_result result;
1007
1008 rc = pm8921_adc_read(chip->batt_temp_channel, &result);
1009 if (rc) {
1010 pr_err("error reading adc channel = %d, rc = %d\n",
1011 chip->vbat_channel, rc);
1012 return rc;
1013 }
1014 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1015 result.measurement);
1016 return (int)result.physical;
1017}
1018
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001019static int pm_batt_power_get_property(struct power_supply *psy,
1020 enum power_supply_property psp,
1021 union power_supply_propval *val)
1022{
1023 struct pm8921_chg_chip *chip = container_of(psy, struct pm8921_chg_chip,
1024 batt_psy);
1025
1026 switch (psp) {
1027 case POWER_SUPPLY_PROP_STATUS:
1028 val->intval = get_prop_batt_status(chip);
1029 break;
1030 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1031 val->intval = get_prop_charge_type(chip);
1032 break;
1033 case POWER_SUPPLY_PROP_HEALTH:
1034 val->intval = get_prop_batt_health(chip);
1035 break;
1036 case POWER_SUPPLY_PROP_PRESENT:
1037 val->intval = get_prop_batt_present(chip);
1038 break;
1039 case POWER_SUPPLY_PROP_TECHNOLOGY:
1040 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1041 break;
1042 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1043 val->intval = chip->max_voltage;
1044 break;
1045 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
1046 val->intval = chip->min_voltage;
1047 break;
1048 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1049 val->intval = get_prop_battery_mvolts(chip);
1050 break;
1051 case POWER_SUPPLY_PROP_CAPACITY:
1052 val->intval = get_prop_batt_capacity(chip);
1053 break;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001054 case POWER_SUPPLY_PROP_CURRENT_NOW:
1055 val->intval = get_prop_batt_current(chip);
1056 break;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001057 case POWER_SUPPLY_PROP_TEMP:
1058 val->intval = get_prop_batt_temp(chip);
1059 break;
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001060 case POWER_SUPPLY_PROP_ENERGY_FULL:
1061 val->intval = get_prop_batt_fcc(chip);
1062 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001063 default:
1064 return -EINVAL;
1065 }
1066
1067 return 0;
1068}
1069
1070static void (*notify_vbus_state_func_ptr)(int);
1071static int usb_chg_current;
1072static DEFINE_SPINLOCK(vbus_lock);
1073
1074int pm8921_charger_register_vbus_sn(void (*callback)(int))
1075{
1076 pr_debug("%p\n", callback);
1077 notify_vbus_state_func_ptr = callback;
1078 return 0;
1079}
1080EXPORT_SYMBOL_GPL(pm8921_charger_register_vbus_sn);
1081
1082/* this is passed to the hsusb via platform_data msm_otg_pdata */
1083void pm8921_charger_unregister_vbus_sn(void (*callback)(int))
1084{
1085 pr_debug("%p\n", callback);
1086 notify_vbus_state_func_ptr = NULL;
1087}
1088EXPORT_SYMBOL_GPL(pm8921_charger_unregister_vbus_sn);
1089
1090static void notify_usb_of_the_plugin_event(int plugin)
1091{
1092 plugin = !!plugin;
1093 if (notify_vbus_state_func_ptr) {
1094 pr_debug("notifying plugin\n");
1095 (*notify_vbus_state_func_ptr) (plugin);
1096 } else {
1097 pr_debug("unable to notify plugin\n");
1098 }
1099}
1100
1101struct usb_ma_limit_entry {
1102 int usb_ma;
1103 u8 chg_iusb_value;
1104};
1105
1106static struct usb_ma_limit_entry usb_ma_table[] = {
1107 {100, 0},
1108 {500, 1},
1109 {700, 2},
1110 {850, 3},
1111 {900, 4},
1112 {1100, 5},
1113 {1300, 6},
1114 {1500, 7},
1115};
1116
1117/* assumes vbus_lock is held */
1118static void __pm8921_charger_vbus_draw(unsigned int mA)
1119{
1120 int i, rc;
1121
1122 if (mA > 0 && mA <= 2) {
1123 usb_chg_current = 0;
1124 rc = pm_chg_iusbmax_set(the_chip,
1125 usb_ma_table[0].chg_iusb_value);
1126 if (rc) {
1127 pr_err("unable to set iusb to %d rc = %d\n",
1128 usb_ma_table[0].chg_iusb_value, rc);
1129 }
1130 rc = pm_chg_usb_suspend_enable(the_chip, 1);
1131 if (rc)
1132 pr_err("fail to set suspend bit rc=%d\n", rc);
1133 } else {
1134 rc = pm_chg_usb_suspend_enable(the_chip, 0);
1135 if (rc)
1136 pr_err("fail to reset suspend bit rc=%d\n", rc);
1137 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
1138 if (usb_ma_table[i].usb_ma <= mA)
1139 break;
1140 }
1141 if (i < 0)
1142 i = 0;
1143 rc = pm_chg_iusbmax_set(the_chip,
1144 usb_ma_table[i].chg_iusb_value);
1145 if (rc) {
1146 pr_err("unable to set iusb to %d rc = %d\n",
1147 usb_ma_table[i].chg_iusb_value, rc);
1148 }
1149 }
1150}
1151
1152/* USB calls these to tell us how much max usb current the system can draw */
1153void pm8921_charger_vbus_draw(unsigned int mA)
1154{
1155 unsigned long flags;
1156
1157 pr_debug("Enter charge=%d\n", mA);
1158 spin_lock_irqsave(&vbus_lock, flags);
1159 if (the_chip) {
1160 __pm8921_charger_vbus_draw(mA);
1161 } else {
1162 /*
1163 * called before pmic initialized,
1164 * save this value and use it at probe
1165 */
1166 usb_chg_current = mA;
1167 }
1168 spin_unlock_irqrestore(&vbus_lock, flags);
1169}
1170EXPORT_SYMBOL_GPL(pm8921_charger_vbus_draw);
1171
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07001172int pm8921_charger_enable(bool enable)
1173{
1174 int rc;
1175
1176 if (!the_chip) {
1177 pr_err("called before init\n");
1178 return -EINVAL;
1179 }
1180 enable = !!enable;
1181 rc = pm_chg_auto_enable(the_chip, enable);
1182 if (rc)
1183 pr_err("Failed rc=%d\n", rc);
1184 return rc;
1185}
1186EXPORT_SYMBOL(pm8921_charger_enable);
1187
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001188int pm8921_is_usb_chg_plugged_in(void)
1189{
1190 if (!the_chip) {
1191 pr_err("called before init\n");
1192 return -EINVAL;
1193 }
1194 return is_usb_chg_plugged_in(the_chip);
1195}
1196EXPORT_SYMBOL(pm8921_is_usb_chg_plugged_in);
1197
1198int pm8921_is_dc_chg_plugged_in(void)
1199{
1200 if (!the_chip) {
1201 pr_err("called before init\n");
1202 return -EINVAL;
1203 }
1204 return is_dc_chg_plugged_in(the_chip);
1205}
1206EXPORT_SYMBOL(pm8921_is_dc_chg_plugged_in);
1207
1208int pm8921_is_battery_present(void)
1209{
1210 if (!the_chip) {
1211 pr_err("called before init\n");
1212 return -EINVAL;
1213 }
1214 return get_prop_batt_present(the_chip);
1215}
1216EXPORT_SYMBOL(pm8921_is_battery_present);
1217
1218int pm8921_set_max_battery_charge_current(int ma)
1219{
1220 if (!the_chip) {
1221 pr_err("called before init\n");
1222 return -EINVAL;
1223 }
1224 return pm_chg_ibatmax_set(the_chip, ma);
1225}
1226EXPORT_SYMBOL(pm8921_set_max_battery_charge_current);
1227
1228int pm8921_disable_source_current(bool disable)
1229{
1230 if (!the_chip) {
1231 pr_err("called before init\n");
1232 return -EINVAL;
1233 }
1234 if (disable)
1235 pr_warn("current drawn from chg=0, battery provides current\n");
1236 return pm_chg_charge_dis(the_chip, disable);
1237}
1238EXPORT_SYMBOL(pm8921_disable_source_current);
1239
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07001240int pm8921_regulate_input_voltage(int voltage)
1241{
1242 if (!the_chip) {
1243 pr_err("called before init\n");
1244 return -EINVAL;
1245 }
1246 return pm_chg_vinmin_set(the_chip, voltage);
1247}
1248
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001249bool pm8921_is_battery_charging(int *source)
1250{
1251 int fsm_state, is_charging, dc_present, usb_present;
1252
1253 if (!the_chip) {
1254 pr_err("called before init\n");
1255 return -EINVAL;
1256 }
1257 fsm_state = pm_chg_get_fsm_state(the_chip);
1258 is_charging = is_battery_charging(fsm_state);
1259 if (is_charging == 0) {
1260 *source = PM8921_CHG_SRC_NONE;
1261 return is_charging;
1262 }
1263
1264 if (source == NULL)
1265 return is_charging;
1266
1267 /* the battery is charging, the source is requested, find it */
1268 dc_present = is_dc_chg_plugged_in(the_chip);
1269 usb_present = is_usb_chg_plugged_in(the_chip);
1270
1271 if (dc_present && !usb_present)
1272 *source = PM8921_CHG_SRC_DC;
1273
1274 if (usb_present && !dc_present)
1275 *source = PM8921_CHG_SRC_USB;
1276
1277 if (usb_present && dc_present)
1278 /*
1279 * The system always chooses dc for charging since it has
1280 * higher priority.
1281 */
1282 *source = PM8921_CHG_SRC_DC;
1283
1284 return is_charging;
1285}
1286EXPORT_SYMBOL(pm8921_is_battery_charging);
1287
1288int pm8921_batt_temperature(void)
1289{
1290 if (!the_chip) {
1291 pr_err("called before init\n");
1292 return -EINVAL;
1293 }
1294 return get_prop_batt_temp(the_chip);
1295}
1296
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001297static void handle_usb_insertion_removal(struct pm8921_chg_chip *chip)
1298{
1299 int usb_present;
1300
1301 usb_present = is_usb_chg_plugged_in(chip);
1302 if (chip->usb_present ^ usb_present) {
1303 notify_usb_of_the_plugin_event(usb_present);
1304 chip->usb_present = usb_present;
1305 power_supply_changed(&chip->usb_psy);
1306 }
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001307 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001308}
1309
Amir Samuelovd31ef502011-10-26 14:41:36 +02001310static void handle_stop_ext_chg(struct pm8921_chg_chip *chip)
1311{
1312 if (chip->ext == NULL) {
1313 pr_debug("external charger not registered.\n");
1314 return;
1315 }
1316
1317 if (!chip->ext_charging) {
1318 pr_debug("already not charging.\n");
1319 return;
1320 }
1321
1322 chip->ext->stop_charging(chip->ext->ctx);
1323 chip->ext_charging = false;
1324}
1325
1326static void handle_start_ext_chg(struct pm8921_chg_chip *chip)
1327{
1328 int dc_present;
1329 int batt_present;
1330 int batt_temp_ok;
1331 int vbat_ov;
1332 int batfet;
1333 unsigned long delay =
1334 round_jiffies_relative(msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
1335
1336 if (chip->ext == NULL) {
1337 pr_debug("external charger not registered.\n");
1338 return;
1339 }
1340
1341 if (chip->ext_charging) {
1342 pr_debug("already charging.\n");
1343 return;
1344 }
1345
1346 dc_present = is_dc_chg_plugged_in(chip);
1347 batt_present = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1348 batt_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
1349 vbat_ov = pm_chg_get_rt_status(chip, VBAT_OV_IRQ);
1350 batfet = pm_chg_get_rt_status(chip, BATFET_IRQ);
1351
1352 if (!dc_present) {
1353 pr_warn("%s. dc not present.\n", __func__);
1354 return;
1355 }
1356 if (!batt_present) {
1357 pr_warn("%s. battery not present.\n", __func__);
1358 return;
1359 }
1360 if (!batt_temp_ok) {
1361 pr_warn("%s. battery temperature not ok.\n", __func__);
1362 return;
1363 }
1364 if (vbat_ov) {
1365 pr_warn("%s. battery over voltage.\n", __func__);
1366 return;
1367 }
1368 if (!batfet) {
1369 pr_warn("%s. battery FET not closed.\n", __func__);
1370 return;
1371 }
1372
1373 chip->ext->start_charging(chip->ext->ctx);
1374 chip->ext_charging = true;
1375 chip->ext_charge_done = false;
1376 /* Start BMS */
1377 schedule_delayed_work(&chip->eoc_work, delay);
1378 wake_lock(&chip->eoc_wake_lock);
1379}
1380
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001381static void handle_dc_removal_insertion(struct pm8921_chg_chip *chip)
1382{
1383 int dc_present;
1384
1385 dc_present = is_dc_chg_plugged_in(chip);
1386 if (chip->dc_present ^ dc_present) {
1387 chip->dc_present = dc_present;
1388 power_supply_changed(&chip->dc_psy);
1389 }
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001390 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001391}
1392
1393static irqreturn_t usbin_valid_irq_handler(int irq, void *data)
1394{
1395 handle_usb_insertion_removal(data);
1396 return IRQ_HANDLED;
1397}
1398
1399static irqreturn_t usbin_ov_irq_handler(int irq, void *data)
1400{
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -07001401 pr_err("USB OverVoltage\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001402 return IRQ_HANDLED;
1403}
1404
1405static irqreturn_t batt_inserted_irq_handler(int irq, void *data)
1406{
1407 struct pm8921_chg_chip *chip = data;
1408 int status;
1409
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001410 status = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1411 schedule_work(&chip->battery_id_valid_work);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001412 handle_start_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001413 pr_debug("battery present=%d", status);
1414 power_supply_changed(&chip->batt_psy);
1415 return IRQ_HANDLED;
1416}
Amir Samuelovd31ef502011-10-26 14:41:36 +02001417
1418/*
1419 * this interrupt used to restart charging a battery.
1420 *
1421 * Note: When DC-inserted the VBAT can't go low.
1422 * VPH_PWR is provided by the ext-charger.
1423 * After End-Of-Charging from DC, charging can be resumed only
1424 * if DC is removed and then inserted after the battery was in use.
1425 * Therefore the handle_start_ext_chg() is not called.
1426 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001427static irqreturn_t vbatdet_low_irq_handler(int irq, void *data)
1428{
1429 struct pm8921_chg_chip *chip = data;
1430
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001431 pm8921_chg_disable_irq(chip, VBATDET_LOW_IRQ);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07001432
1433 /* enable auto charging */
1434 pm_chg_auto_enable(chip, !charging_disabled);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001435 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001436
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001437 power_supply_changed(&chip->batt_psy);
1438 power_supply_changed(&chip->usb_psy);
1439 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001440
1441 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001442 return IRQ_HANDLED;
1443}
1444
1445static irqreturn_t usbin_uv_irq_handler(int irq, void *data)
1446{
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -07001447 pr_err("USB UnderVoltage\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001448 return IRQ_HANDLED;
1449}
1450
1451static irqreturn_t vbat_ov_irq_handler(int irq, void *data)
1452{
1453 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1454 return IRQ_HANDLED;
1455}
1456
1457static irqreturn_t chgwdog_irq_handler(int irq, void *data)
1458{
1459 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1460 return IRQ_HANDLED;
1461}
1462
1463static irqreturn_t vcp_irq_handler(int irq, void *data)
1464{
1465 pr_warning("VCP triggered BATDET forced on\n");
1466 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1467 return IRQ_HANDLED;
1468}
1469
1470static irqreturn_t atcdone_irq_handler(int irq, void *data)
1471{
1472 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1473 return IRQ_HANDLED;
1474}
1475
1476static irqreturn_t atcfail_irq_handler(int irq, void *data)
1477{
1478 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1479 return IRQ_HANDLED;
1480}
1481
1482static irqreturn_t chgdone_irq_handler(int irq, void *data)
1483{
1484 struct pm8921_chg_chip *chip = data;
1485
1486 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02001487
1488 handle_stop_ext_chg(chip);
1489
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001490 power_supply_changed(&chip->batt_psy);
1491 power_supply_changed(&chip->usb_psy);
1492 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001493
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07001494 chip->bms_notify.is_battery_full = 1;
1495 bms_notify_check(chip);
1496
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001497 /*
1498 * since charging is now done, start monitoring for
1499 * battery voltage below resume voltage
1500 */
1501 pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
1502
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001503 return IRQ_HANDLED;
1504}
1505
1506static irqreturn_t chgfail_irq_handler(int irq, void *data)
1507{
1508 struct pm8921_chg_chip *chip = data;
1509
1510 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1511 power_supply_changed(&chip->batt_psy);
1512 power_supply_changed(&chip->usb_psy);
1513 power_supply_changed(&chip->dc_psy);
1514 return IRQ_HANDLED;
1515}
1516
1517static irqreturn_t chgstate_irq_handler(int irq, void *data)
1518{
1519 struct pm8921_chg_chip *chip = data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001520
1521 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1522 power_supply_changed(&chip->batt_psy);
1523 power_supply_changed(&chip->usb_psy);
1524 power_supply_changed(&chip->dc_psy);
1525
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001526 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001527
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001528 return IRQ_HANDLED;
1529}
1530
1531static irqreturn_t loop_change_irq_handler(int irq, void *data)
1532{
1533 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1534 return IRQ_HANDLED;
1535}
1536
1537static irqreturn_t fastchg_irq_handler(int irq, void *data)
1538{
1539 struct pm8921_chg_chip *chip = data;
1540
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001541 /* disable this irq now, reenable it when resuming charging */
1542 pm8921_chg_disable_irq(chip, FASTCHG_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001543 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001544 wake_lock(&chip->eoc_wake_lock);
1545 schedule_delayed_work(&chip->eoc_work,
1546 round_jiffies_relative(msecs_to_jiffies
1547 (EOC_CHECK_PERIOD_MS)));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001548 return IRQ_HANDLED;
1549}
1550
1551static irqreturn_t trklchg_irq_handler(int irq, void *data)
1552{
1553 struct pm8921_chg_chip *chip = data;
1554
1555 power_supply_changed(&chip->batt_psy);
1556 return IRQ_HANDLED;
1557}
1558
1559static irqreturn_t batt_removed_irq_handler(int irq, void *data)
1560{
1561 struct pm8921_chg_chip *chip = data;
1562 int status;
1563
1564 status = pm_chg_get_rt_status(chip, BATT_REMOVED_IRQ);
1565 pr_debug("battery present=%d state=%d", !status,
1566 pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02001567 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001568 power_supply_changed(&chip->batt_psy);
1569 return IRQ_HANDLED;
1570}
1571
1572static irqreturn_t batttemp_hot_irq_handler(int irq, void *data)
1573{
1574 struct pm8921_chg_chip *chip = data;
1575
Amir Samuelovd31ef502011-10-26 14:41:36 +02001576 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001577 power_supply_changed(&chip->batt_psy);
1578 return IRQ_HANDLED;
1579}
1580
1581static irqreturn_t chghot_irq_handler(int irq, void *data)
1582{
1583 struct pm8921_chg_chip *chip = data;
1584
1585 pr_debug("Chg hot fsm_state=%d\n", pm_chg_get_fsm_state(data));
1586 power_supply_changed(&chip->batt_psy);
1587 power_supply_changed(&chip->usb_psy);
1588 power_supply_changed(&chip->dc_psy);
1589 return IRQ_HANDLED;
1590}
1591
1592static irqreturn_t batttemp_cold_irq_handler(int irq, void *data)
1593{
1594 struct pm8921_chg_chip *chip = data;
1595
1596 pr_debug("Batt cold fsm_state=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02001597 handle_stop_ext_chg(chip);
1598
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001599 power_supply_changed(&chip->batt_psy);
1600 power_supply_changed(&chip->usb_psy);
1601 power_supply_changed(&chip->dc_psy);
1602 return IRQ_HANDLED;
1603}
1604
1605static irqreturn_t chg_gone_irq_handler(int irq, void *data)
1606{
1607 struct pm8921_chg_chip *chip = data;
1608
1609 pr_debug("Chg gone fsm_state=%d\n", pm_chg_get_fsm_state(data));
1610 power_supply_changed(&chip->batt_psy);
1611 power_supply_changed(&chip->usb_psy);
1612 power_supply_changed(&chip->dc_psy);
1613 return IRQ_HANDLED;
1614}
1615
1616static irqreturn_t bat_temp_ok_irq_handler(int irq, void *data)
1617{
1618 struct pm8921_chg_chip *chip = data;
1619
1620 pr_debug("batt temp ok fsm_state=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02001621 handle_start_ext_chg(chip);
1622
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001623 power_supply_changed(&chip->batt_psy);
1624 power_supply_changed(&chip->usb_psy);
1625 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001626 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001627 return IRQ_HANDLED;
1628}
1629
1630static irqreturn_t coarse_det_low_irq_handler(int irq, void *data)
1631{
1632 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1633 return IRQ_HANDLED;
1634}
1635
1636static irqreturn_t vdd_loop_irq_handler(int irq, void *data)
1637{
1638 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1639 return IRQ_HANDLED;
1640}
1641
1642static irqreturn_t vreg_ov_irq_handler(int irq, void *data)
1643{
1644 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1645 return IRQ_HANDLED;
1646}
1647
1648static irqreturn_t vbatdet_irq_handler(int irq, void *data)
1649{
1650 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1651 return IRQ_HANDLED;
1652}
1653
1654static irqreturn_t batfet_irq_handler(int irq, void *data)
1655{
1656 struct pm8921_chg_chip *chip = data;
1657
1658 pr_debug("vreg ov\n");
1659 power_supply_changed(&chip->batt_psy);
1660 return IRQ_HANDLED;
1661}
1662
1663static irqreturn_t dcin_valid_irq_handler(int irq, void *data)
1664{
Amir Samuelovd31ef502011-10-26 14:41:36 +02001665 struct pm8921_chg_chip *chip = data;
1666
1667 pm8921_disable_source_current(true); /* Force BATFET=ON */
1668
1669 handle_dc_removal_insertion(chip);
1670 handle_start_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001671 return IRQ_HANDLED;
1672}
1673
1674static irqreturn_t dcin_ov_irq_handler(int irq, void *data)
1675{
Amir Samuelovd31ef502011-10-26 14:41:36 +02001676 struct pm8921_chg_chip *chip = data;
1677
1678 pm8921_disable_source_current(false); /* release BATFET */
1679
1680 handle_dc_removal_insertion(chip);
1681 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001682 return IRQ_HANDLED;
1683}
1684
1685static irqreturn_t dcin_uv_irq_handler(int irq, void *data)
1686{
Amir Samuelovd31ef502011-10-26 14:41:36 +02001687 struct pm8921_chg_chip *chip = data;
1688
1689 pm8921_disable_source_current(false); /* release BATFET */
1690 handle_stop_ext_chg(chip);
1691
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001692 return IRQ_HANDLED;
1693}
1694
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07001695/**
1696 * update_heartbeat - internal function to update userspace
1697 * per update_time minutes
1698 *
1699 */
1700static void update_heartbeat(struct work_struct *work)
1701{
1702 struct delayed_work *dwork = to_delayed_work(work);
1703 struct pm8921_chg_chip *chip = container_of(dwork,
1704 struct pm8921_chg_chip, update_heartbeat_work);
1705
1706 power_supply_changed(&chip->batt_psy);
1707 schedule_delayed_work(&chip->update_heartbeat_work,
1708 round_jiffies_relative(msecs_to_jiffies
1709 (chip->update_time)));
1710}
1711
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001712/**
Amir Samuelovd31ef502011-10-26 14:41:36 +02001713 * eoc_worker - internal function to check if battery EOC
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001714 * has happened
1715 *
1716 * If all conditions favouring, if the charge current is
1717 * less than the term current for three consecutive times
1718 * an EOC has happened.
1719 * The wakelock is released if there is no need to reshedule
1720 * - this happens when the battery is removed or EOC has
1721 * happened
1722 */
1723#define CONSECUTIVE_COUNT 3
1724#define VBAT_TOLERANCE_MV 70
1725#define CHG_DISABLE_MSLEEP 100
Amir Samuelovd31ef502011-10-26 14:41:36 +02001726static void eoc_worker(struct work_struct *work)
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001727{
1728 struct delayed_work *dwork = to_delayed_work(work);
1729 struct pm8921_chg_chip *chip = container_of(dwork,
1730 struct pm8921_chg_chip, eoc_work);
1731 int vbat_meas, vbat_programmed;
1732 int ichg_meas, iterm_programmed;
1733 int regulation_loop, fast_chg, vcp;
1734 int rc;
1735 static int count;
1736
Amir Samuelovd31ef502011-10-26 14:41:36 +02001737 if (!is_ext_charging(chip)) {
1738 /* return if the battery is not being fastcharged */
1739 fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
1740 pr_debug("fast_chg = %d\n", fast_chg);
1741 if (fast_chg == 0) {
1742 /* enable fastchg irq */
1743 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
1744 count = 0;
1745 wake_unlock(&chip->eoc_wake_lock);
1746 return;
1747 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001748
Amir Samuelovd31ef502011-10-26 14:41:36 +02001749 vcp = pm_chg_get_rt_status(chip, VCP_IRQ);
1750 pr_debug("vcp = %d\n", vcp);
1751 if (vcp == 1)
1752 goto reset_and_reschedule;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001753
Amir Samuelovd31ef502011-10-26 14:41:36 +02001754 /* reset count if battery is hot/cold */
1755 rc = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
1756 pr_debug("batt_temp_ok = %d\n", rc);
1757 if (rc == 0)
1758 goto reset_and_reschedule;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001759
Amir Samuelovd31ef502011-10-26 14:41:36 +02001760 /* reset count if battery voltage is less than vddmax */
1761 vbat_meas = get_prop_battery_mvolts(chip);
1762 if (vbat_meas < 0)
1763 goto reset_and_reschedule;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001764
Amir Samuelovd31ef502011-10-26 14:41:36 +02001765 rc = pm_chg_vddmax_get(chip, &vbat_programmed);
1766 if (rc) {
1767 pr_err("couldnt read vddmax rc = %d\n", rc);
1768 goto reset_and_reschedule;
1769 }
1770 pr_debug("vddmax = %d vbat_meas=%d\n",
1771 vbat_programmed, vbat_meas);
1772 if (vbat_meas < vbat_programmed - VBAT_TOLERANCE_MV)
1773 goto reset_and_reschedule;
1774 } /* !is_ext_charging */
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001775
1776 /* reset count if battery chg current is more than iterm */
1777 rc = pm_chg_iterm_get(chip, &iterm_programmed);
1778 if (rc) {
1779 pr_err("couldnt read iterm rc = %d\n", rc);
1780 goto reset_and_reschedule;
1781 }
1782
1783 ichg_meas = get_prop_batt_current(chip);
1784 pr_debug("iterm_programmed = %d ichg_meas=%d\n",
1785 iterm_programmed, ichg_meas);
1786 /*
1787 * ichg_meas < 0 means battery is drawing current
1788 * ichg_meas > 0 means battery is providing current
1789 */
1790 if (ichg_meas > 0)
1791 goto reset_and_reschedule;
1792
1793 if (ichg_meas * -1 > iterm_programmed)
1794 goto reset_and_reschedule;
1795
Amir Samuelovd31ef502011-10-26 14:41:36 +02001796 if (!is_ext_charging(chip)) {
1797 /*
1798 * TODO if charging from an external charger
1799 * check SOC instead of regulation loop
1800 */
1801 regulation_loop = pm_chg_get_regulation_loop(chip);
1802 if (regulation_loop < 0) {
1803 pr_err("couldnt read the regulation loop err=%d\n",
1804 regulation_loop);
1805 goto reset_and_reschedule;
1806 }
1807 pr_debug("regulation_loop=%d\n", regulation_loop);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07001808
Amir Samuelovd31ef502011-10-26 14:41:36 +02001809 if (regulation_loop != 0 && regulation_loop != VDD_LOOP)
1810 goto reset_and_reschedule;
1811 } /* !is_ext_charging */
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001812
1813 count++;
1814 if (count == CONSECUTIVE_COUNT) {
1815 count = 0;
1816 pr_info("End of Charging\n");
1817
1818 pm_chg_auto_enable(chip, 0);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001819
Amir Samuelovd31ef502011-10-26 14:41:36 +02001820 if (is_ext_charging(chip))
1821 chip->ext_charge_done = true;
1822
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001823 /* declare end of charging by invoking chgdone interrupt */
1824 chgdone_irq_handler(chip->pmic_chg_irq[CHGDONE_IRQ], chip);
1825 wake_unlock(&chip->eoc_wake_lock);
1826 return;
1827 } else {
1828 pr_debug("EOC count = %d\n", count);
1829 goto reschedule;
1830 }
1831
1832reset_and_reschedule:
1833 count = 0;
1834reschedule:
1835 schedule_delayed_work(&chip->eoc_work,
1836 round_jiffies_relative(msecs_to_jiffies
1837 (EOC_CHECK_PERIOD_MS)));
1838}
1839
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07001840static void btm_configure_work(struct work_struct *work)
1841{
1842 int rc;
1843
1844 rc = pm8921_adc_btm_configure(&btm_config);
1845 if (rc)
1846 pr_err("failed to configure btm rc=%d", rc);
1847}
1848
1849DECLARE_WORK(btm_config_work, btm_configure_work);
1850
1851#define TEMP_HYSTERISIS_DEGC 2
1852static void battery_cool(bool enter)
1853{
1854 pr_debug("enter = %d\n", enter);
1855 if (enter) {
1856 btm_config.low_thr_temp =
1857 the_chip->cool_temp + TEMP_HYSTERISIS_DEGC;
1858 pm_chg_ibatmax_set(the_chip, the_chip->cool_bat_chg_current);
1859 pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
1860 } else {
1861 btm_config.low_thr_temp = the_chip->cool_temp;
1862 pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
1863 pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
1864 }
1865 schedule_work(&btm_config_work);
1866}
1867
1868static void battery_warm(bool enter)
1869{
1870 pr_debug("enter = %d\n", enter);
1871 if (enter) {
1872 btm_config.high_thr_temp =
1873 the_chip->warm_temp - TEMP_HYSTERISIS_DEGC;
1874 pm_chg_ibatmax_set(the_chip, the_chip->warm_bat_chg_current);
1875 pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
1876 } else {
1877 btm_config.high_thr_temp = the_chip->warm_temp;
1878 pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
1879 pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
1880 }
1881 schedule_work(&btm_config_work);
1882}
1883
1884static int configure_btm(struct pm8921_chg_chip *chip)
1885{
1886 int rc;
1887
1888 btm_config.btm_warm_fn = battery_warm;
1889 btm_config.btm_cool_fn = battery_cool;
1890 btm_config.low_thr_temp = chip->cool_temp;
1891 btm_config.high_thr_temp = chip->warm_temp;
1892 btm_config.interval = chip->temp_check_period;
1893 rc = pm8921_adc_btm_configure(&btm_config);
1894 if (rc)
1895 pr_err("failed to configure btm rc = %d\n", rc);
1896 rc = pm8921_adc_btm_start();
1897 if (rc)
1898 pr_err("failed to start btm rc = %d\n", rc);
1899
1900 return rc;
1901}
1902
Amir Samuelovd31ef502011-10-26 14:41:36 +02001903int register_external_dc_charger(struct ext_chg_pm8921 *ext)
1904{
1905 if (the_chip == NULL) {
1906 pr_err("called too early\n");
1907 return -EINVAL;
1908 }
1909 /* TODO check function pointers */
1910 the_chip->ext = ext;
1911 the_chip->ext_charging = false;
1912
1913 if (is_dc_chg_plugged_in(the_chip))
1914 pm8921_disable_source_current(true); /* Force BATFET=ON */
1915
1916 handle_start_ext_chg(the_chip);
1917
1918 return 0;
1919}
1920EXPORT_SYMBOL(register_external_dc_charger);
1921
1922void unregister_external_dc_charger(struct ext_chg_pm8921 *ext)
1923{
1924 if (the_chip == NULL) {
1925 pr_err("called too early\n");
1926 return;
1927 }
1928 handle_stop_ext_chg(the_chip);
1929 the_chip->ext = NULL;
1930}
1931EXPORT_SYMBOL(unregister_external_dc_charger);
1932
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07001933/**
1934 * set_disable_status_param -
1935 *
1936 * Internal function to disable battery charging and also disable drawing
1937 * any current from the source. The device is forced to run on a battery
1938 * after this.
1939 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001940static int set_disable_status_param(const char *val, struct kernel_param *kp)
1941{
1942 int ret;
1943 struct pm8921_chg_chip *chip = the_chip;
1944
1945 ret = param_set_int(val, kp);
1946 if (ret) {
1947 pr_err("error setting value %d\n", ret);
1948 return ret;
1949 }
1950 pr_info("factory set disable param to %d\n", charging_disabled);
1951 if (chip) {
1952 pm_chg_auto_enable(chip, !charging_disabled);
1953 pm_chg_charge_dis(chip, charging_disabled);
1954 }
1955 return 0;
1956}
1957module_param_call(disabled, set_disable_status_param, param_get_uint,
1958 &charging_disabled, 0644);
1959
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07001960/**
1961 * set_thermal_mitigation_level -
1962 *
1963 * Internal function to control battery charging current to reduce
1964 * temperature
1965 */
1966static int set_therm_mitigation_level(const char *val, struct kernel_param *kp)
1967{
1968 int ret;
1969 struct pm8921_chg_chip *chip = the_chip;
1970
1971 ret = param_set_int(val, kp);
1972 if (ret) {
1973 pr_err("error setting value %d\n", ret);
1974 return ret;
1975 }
1976
1977 if (!chip) {
1978 pr_err("called before init\n");
1979 return -EINVAL;
1980 }
1981
1982 if (!chip->thermal_mitigation) {
1983 pr_err("no thermal mitigation\n");
1984 return -EINVAL;
1985 }
1986
1987 if (thermal_mitigation < 0
1988 || thermal_mitigation >= chip->thermal_levels) {
1989 pr_err("out of bound level selected\n");
1990 return -EINVAL;
1991 }
1992
1993 ret = pm_chg_ibatmax_set(chip,
1994 chip->thermal_mitigation[thermal_mitigation]);
1995 return ret;
1996}
1997module_param_call(thermal_mitigation, set_therm_mitigation_level,
1998 param_get_uint,
1999 &thermal_mitigation, 0644);
2000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002001static void free_irqs(struct pm8921_chg_chip *chip)
2002{
2003 int i;
2004
2005 for (i = 0; i < PM_CHG_MAX_INTS; i++)
2006 if (chip->pmic_chg_irq[i]) {
2007 free_irq(chip->pmic_chg_irq[i], chip);
2008 chip->pmic_chg_irq[i] = 0;
2009 }
2010}
2011
2012/* determines the initial present states and notifies msm_charger */
2013static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
2014{
2015 unsigned long flags;
2016 int fsm_state;
2017
2018 chip->dc_present = !!is_dc_chg_plugged_in(chip);
2019 chip->usb_present = !!is_usb_chg_plugged_in(chip);
2020
2021 notify_usb_of_the_plugin_event(chip->usb_present);
2022
2023 pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
2024 pm8921_chg_enable_irq(chip, USBIN_VALID_IRQ);
2025 pm8921_chg_enable_irq(chip, BATT_REMOVED_IRQ);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002026 pm8921_chg_enable_irq(chip, BATT_INSERTED_IRQ);
2027 pm8921_chg_enable_irq(chip, USBIN_OV_IRQ);
2028 pm8921_chg_enable_irq(chip, USBIN_UV_IRQ);
2029 pm8921_chg_enable_irq(chip, DCIN_OV_IRQ);
2030 pm8921_chg_enable_irq(chip, DCIN_UV_IRQ);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002031 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
2032 pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002033
2034 spin_lock_irqsave(&vbus_lock, flags);
2035 if (usb_chg_current) {
2036 /* reissue a vbus draw call */
2037 __pm8921_charger_vbus_draw(usb_chg_current);
2038 }
2039 spin_unlock_irqrestore(&vbus_lock, flags);
2040
2041 fsm_state = pm_chg_get_fsm_state(chip);
2042 if (is_battery_charging(fsm_state)) {
2043 chip->bms_notify.is_charging = 1;
2044 pm8921_bms_charging_began();
2045 }
2046
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002047 check_battery_valid(chip);
2048
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002049 pr_debug("usb = %d, dc = %d batt = %d state=%d\n",
2050 chip->usb_present,
2051 chip->dc_present,
2052 get_prop_batt_present(chip),
2053 fsm_state);
2054}
2055
2056struct pm_chg_irq_init_data {
2057 unsigned int irq_id;
2058 char *name;
2059 unsigned long flags;
2060 irqreturn_t (*handler)(int, void *);
2061};
2062
2063#define CHG_IRQ(_id, _flags, _handler) \
2064{ \
2065 .irq_id = _id, \
2066 .name = #_id, \
2067 .flags = _flags, \
2068 .handler = _handler, \
2069}
2070struct pm_chg_irq_init_data chg_irq_data[] = {
2071 CHG_IRQ(USBIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2072 usbin_valid_irq_handler),
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -07002073 CHG_IRQ(USBIN_OV_IRQ, IRQF_TRIGGER_RISING, usbin_ov_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002074 CHG_IRQ(BATT_INSERTED_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2075 batt_inserted_irq_handler),
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002076 CHG_IRQ(VBATDET_LOW_IRQ, IRQF_TRIGGER_HIGH, vbatdet_low_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002077 CHG_IRQ(USBIN_UV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2078 usbin_uv_irq_handler),
2079 CHG_IRQ(VBAT_OV_IRQ, IRQF_TRIGGER_RISING, vbat_ov_irq_handler),
2080 CHG_IRQ(CHGWDOG_IRQ, IRQF_TRIGGER_RISING, chgwdog_irq_handler),
2081 CHG_IRQ(VCP_IRQ, IRQF_TRIGGER_RISING, vcp_irq_handler),
2082 CHG_IRQ(ATCDONE_IRQ, IRQF_TRIGGER_RISING, atcdone_irq_handler),
2083 CHG_IRQ(ATCFAIL_IRQ, IRQF_TRIGGER_RISING, atcfail_irq_handler),
2084 CHG_IRQ(CHGDONE_IRQ, IRQF_TRIGGER_RISING, chgdone_irq_handler),
2085 CHG_IRQ(CHGFAIL_IRQ, IRQF_TRIGGER_RISING, chgfail_irq_handler),
2086 CHG_IRQ(CHGSTATE_IRQ, IRQF_TRIGGER_RISING, chgstate_irq_handler),
2087 CHG_IRQ(LOOP_CHANGE_IRQ, IRQF_TRIGGER_RISING, loop_change_irq_handler),
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002088 CHG_IRQ(FASTCHG_IRQ, IRQF_TRIGGER_HIGH, fastchg_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002089 CHG_IRQ(TRKLCHG_IRQ, IRQF_TRIGGER_RISING, trklchg_irq_handler),
2090 CHG_IRQ(BATT_REMOVED_IRQ, IRQF_TRIGGER_RISING,
2091 batt_removed_irq_handler),
2092 CHG_IRQ(BATTTEMP_HOT_IRQ, IRQF_TRIGGER_RISING,
2093 batttemp_hot_irq_handler),
2094 CHG_IRQ(CHGHOT_IRQ, IRQF_TRIGGER_RISING, chghot_irq_handler),
2095 CHG_IRQ(BATTTEMP_COLD_IRQ, IRQF_TRIGGER_RISING,
2096 batttemp_cold_irq_handler),
2097 CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING, chg_gone_irq_handler),
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07002098 CHG_IRQ(BAT_TEMP_OK_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2099 bat_temp_ok_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002100 CHG_IRQ(COARSE_DET_LOW_IRQ, IRQF_TRIGGER_RISING,
2101 coarse_det_low_irq_handler),
2102 CHG_IRQ(VDD_LOOP_IRQ, IRQF_TRIGGER_RISING, vdd_loop_irq_handler),
2103 CHG_IRQ(VREG_OV_IRQ, IRQF_TRIGGER_RISING, vreg_ov_irq_handler),
2104 CHG_IRQ(VBATDET_IRQ, IRQF_TRIGGER_RISING, vbatdet_irq_handler),
2105 CHG_IRQ(BATFET_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2106 batfet_irq_handler),
2107 CHG_IRQ(DCIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2108 dcin_valid_irq_handler),
2109 CHG_IRQ(DCIN_OV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2110 dcin_ov_irq_handler),
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -07002111 CHG_IRQ(DCIN_UV_IRQ, IRQF_TRIGGER_RISING, dcin_uv_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002112};
2113
2114static int __devinit request_irqs(struct pm8921_chg_chip *chip,
2115 struct platform_device *pdev)
2116{
2117 struct resource *res;
2118 int ret, i;
2119
2120 ret = 0;
2121 bitmap_fill(chip->enabled_irqs, PM_CHG_MAX_INTS);
2122
2123 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
2124 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
2125 chg_irq_data[i].name);
2126 if (res == NULL) {
2127 pr_err("couldn't find %s\n", chg_irq_data[i].name);
2128 goto err_out;
2129 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002130 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = res->start;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002131 ret = request_irq(res->start, chg_irq_data[i].handler,
2132 chg_irq_data[i].flags,
2133 chg_irq_data[i].name, chip);
2134 if (ret < 0) {
2135 pr_err("couldn't request %d (%s) %d\n", res->start,
2136 chg_irq_data[i].name, ret);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002137 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002138 goto err_out;
2139 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002140 pm8921_chg_disable_irq(chip, chg_irq_data[i].irq_id);
2141 }
2142 return 0;
2143
2144err_out:
2145 free_irqs(chip);
2146 return -EINVAL;
2147}
2148
2149#define ENUM_TIMER_STOP_BIT BIT(1)
2150#define BOOT_DONE_BIT BIT(6)
2151#define CHG_BATFET_ON_BIT BIT(3)
2152#define CHG_VCP_EN BIT(0)
2153#define CHG_BAT_TEMP_DIS_BIT BIT(2)
2154#define SAFE_CURRENT_MA 1500
2155static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
2156{
2157 int rc;
2158
2159 rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
2160 BOOT_DONE_BIT, BOOT_DONE_BIT);
2161 if (rc) {
2162 pr_err("Failed to set BOOT_DONE_BIT rc=%d\n", rc);
2163 return rc;
2164 }
2165
2166 rc = pm_chg_vddsafe_set(chip, chip->max_voltage);
2167 if (rc) {
2168 pr_err("Failed to set safe voltage to %d rc=%d\n",
2169 chip->max_voltage, rc);
2170 return rc;
2171 }
2172 rc = pm_chg_vbatdet_set(chip, chip->resume_voltage);
2173 if (rc) {
2174 pr_err("Failed to set vbatdet comprator voltage to %d rc=%d\n",
2175 chip->resume_voltage, rc);
2176 return rc;
2177 }
2178
2179 rc = pm_chg_vddmax_set(chip, chip->max_voltage);
2180 if (rc) {
2181 pr_err("Failed to set max voltage to %d rc=%d\n",
2182 chip->max_voltage, rc);
2183 return rc;
2184 }
2185 rc = pm_chg_ibatsafe_set(chip, SAFE_CURRENT_MA);
2186 if (rc) {
2187 pr_err("Failed to set max voltage to %d rc=%d\n",
2188 SAFE_CURRENT_MA, rc);
2189 return rc;
2190 }
2191
2192 /* TODO needs to be changed as per the temeperature of the battery */
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002193 rc = pm_chg_ibatmax_set(chip, chip->max_bat_chg_current);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002194 if (rc) {
2195 pr_err("Failed to set max current to 400 rc=%d\n", rc);
2196 return rc;
2197 }
2198
2199 rc = pm_chg_iterm_set(chip, chip->term_current);
2200 if (rc) {
2201 pr_err("Failed to set term current to %d rc=%d\n",
2202 chip->term_current, rc);
2203 return rc;
2204 }
2205
2206 /* Disable the ENUM TIMER */
2207 rc = pm_chg_masked_write(chip, PBL_ACCESS2, ENUM_TIMER_STOP_BIT,
2208 ENUM_TIMER_STOP_BIT);
2209 if (rc) {
2210 pr_err("Failed to set enum timer stop rc=%d\n", rc);
2211 return rc;
2212 }
2213
2214 /* init with the lowest USB current */
2215 rc = pm_chg_iusbmax_set(chip, usb_ma_table[0].chg_iusb_value);
2216 if (rc) {
2217 pr_err("Failed to set usb max to %d rc=%d\n",
2218 usb_ma_table[0].chg_iusb_value, rc);
2219 return rc;
2220 }
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002221
2222 if (chip->safety_time != 0) {
2223 rc = pm_chg_tchg_max_set(chip, chip->safety_time);
2224 if (rc) {
2225 pr_err("Failed to set max time to %d minutes rc=%d\n",
2226 chip->safety_time, rc);
2227 return rc;
2228 }
2229 }
2230
2231 if (chip->ttrkl_time != 0) {
2232 rc = pm_chg_ttrkl_max_set(chip, chip->safety_time);
2233 if (rc) {
2234 pr_err("Failed to set trkl time to %d minutes rc=%d\n",
2235 chip->safety_time, rc);
2236 return rc;
2237 }
2238 }
2239
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002240 if (chip->vin_min != 0) {
2241 rc = pm_chg_vinmin_set(chip, chip->vin_min);
2242 if (rc) {
2243 pr_err("Failed to set vin min to %d mV rc=%d\n",
2244 chip->vin_min, rc);
2245 return rc;
2246 }
2247 }
2248
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002249 rc = pm_chg_disable_wd(chip);
2250 if (rc) {
2251 pr_err("Failed to disable wd rc=%d\n", rc);
2252 return rc;
2253 }
2254
2255 rc = pm_chg_masked_write(chip, CHG_CNTRL_2,
2256 CHG_BAT_TEMP_DIS_BIT, 0);
2257 if (rc) {
2258 pr_err("Failed to enable temp control chg rc=%d\n", rc);
2259 return rc;
2260 }
2261 /* switch to a 3.2Mhz for the buck */
2262 rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CLOCK_CTRL, 0x15);
2263 if (rc) {
2264 pr_err("Failed to switch buck clk rc=%d\n", rc);
2265 return rc;
2266 }
2267
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07002268 if (chip->trkl_voltage != 0) {
2269 rc = pm_chg_vtrkl_low_set(chip, chip->trkl_voltage);
2270 if (rc) {
2271 pr_err("Failed to set trkl voltage to %dmv rc=%d\n",
2272 chip->trkl_voltage, rc);
2273 return rc;
2274 }
2275 }
2276
2277 if (chip->weak_voltage != 0) {
2278 rc = pm_chg_vweak_set(chip, chip->weak_voltage);
2279 if (rc) {
2280 pr_err("Failed to set weak voltage to %dmv rc=%d\n",
2281 chip->weak_voltage, rc);
2282 return rc;
2283 }
2284 }
2285
2286 if (chip->trkl_current != 0) {
2287 rc = pm_chg_itrkl_set(chip, chip->trkl_current);
2288 if (rc) {
2289 pr_err("Failed to set trkl current to %dmA rc=%d\n",
2290 chip->trkl_voltage, rc);
2291 return rc;
2292 }
2293 }
2294
2295 if (chip->weak_current != 0) {
2296 rc = pm_chg_iweak_set(chip, chip->weak_current);
2297 if (rc) {
2298 pr_err("Failed to set weak current to %dmA rc=%d\n",
2299 chip->weak_current, rc);
2300 return rc;
2301 }
2302 }
2303
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07002304 rc = pm_chg_batt_cold_temp_config(chip, chip->cold_thr);
2305 if (rc) {
2306 pr_err("Failed to set cold config %d rc=%d\n",
2307 chip->cold_thr, rc);
2308 }
2309
2310 rc = pm_chg_batt_hot_temp_config(chip, chip->hot_thr);
2311 if (rc) {
2312 pr_err("Failed to set hot config %d rc=%d\n",
2313 chip->hot_thr, rc);
2314 }
2315
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002316 /* Workarounds for die 1.1 and 1.0 */
2317 if (pm8xxx_get_revision(chip->dev->parent) < PM8XXX_REVISION_8921_2p0) {
2318 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST2, 0xF1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002319 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xCE);
2320 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD8);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002321
2322 /* software workaround for correct battery_id detection */
2323 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_0, 0xFF);
2324 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_1, 0xFF);
2325 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_2, 0xFF);
2326 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_3, 0xFF);
2327 pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0D);
2328 udelay(100);
2329 pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0C);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002330 }
2331
2332 rc = pm_chg_charge_dis(chip, charging_disabled);
2333 if (rc) {
2334 pr_err("Failed to disable CHG_CHARGE_DIS bit rc=%d\n", rc);
2335 return rc;
2336 }
2337
2338 rc = pm_chg_auto_enable(chip, !charging_disabled);
2339 if (rc) {
2340 pr_err("Failed to enable charging rc=%d\n", rc);
2341 return rc;
2342 }
2343
2344 return 0;
2345}
2346
2347static int get_rt_status(void *data, u64 * val)
2348{
2349 int i = (int)data;
2350 int ret;
2351
2352 /* global irq number is passed in via data */
2353 ret = pm_chg_get_rt_status(the_chip, i);
2354 *val = ret;
2355 return 0;
2356}
2357DEFINE_SIMPLE_ATTRIBUTE(rt_fops, get_rt_status, NULL, "%llu\n");
2358
2359static int get_fsm_status(void *data, u64 * val)
2360{
2361 u8 temp;
2362
2363 temp = pm_chg_get_fsm_state(the_chip);
2364 *val = temp;
2365 return 0;
2366}
2367DEFINE_SIMPLE_ATTRIBUTE(fsm_fops, get_fsm_status, NULL, "%llu\n");
2368
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002369static int get_reg_loop(void *data, u64 * val)
2370{
2371 u8 temp;
2372
2373 if (!the_chip) {
2374 pr_err("%s called before init\n", __func__);
2375 return -EINVAL;
2376 }
2377 temp = pm_chg_get_regulation_loop(the_chip);
2378 *val = temp;
2379 return 0;
2380}
2381DEFINE_SIMPLE_ATTRIBUTE(reg_loop_fops, get_reg_loop, NULL, "0x%02llx\n");
2382
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002383static int get_reg(void *data, u64 * val)
2384{
2385 int addr = (int)data;
2386 int ret;
2387 u8 temp;
2388
2389 ret = pm8xxx_readb(the_chip->dev->parent, addr, &temp);
2390 if (ret) {
2391 pr_err("pm8xxx_readb to %x value =%d errored = %d\n",
2392 addr, temp, ret);
2393 return -EAGAIN;
2394 }
2395 *val = temp;
2396 return 0;
2397}
2398
2399static int set_reg(void *data, u64 val)
2400{
2401 int addr = (int)data;
2402 int ret;
2403 u8 temp;
2404
2405 temp = (u8) val;
2406 ret = pm8xxx_writeb(the_chip->dev->parent, addr, temp);
2407 if (ret) {
2408 pr_err("pm8xxx_writeb to %x value =%d errored = %d\n",
2409 addr, temp, ret);
2410 return -EAGAIN;
2411 }
2412 return 0;
2413}
2414DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
2415
2416static void create_debugfs_entries(struct pm8921_chg_chip *chip)
2417{
2418 int i;
2419
2420 chip->dent = debugfs_create_dir("pm8921_chg", NULL);
2421
2422 if (IS_ERR(chip->dent)) {
2423 pr_err("pmic charger couldnt create debugfs dir\n");
2424 return;
2425 }
2426
2427 debugfs_create_file("CHG_CNTRL", 0644, chip->dent,
2428 (void *)CHG_CNTRL, &reg_fops);
2429 debugfs_create_file("CHG_CNTRL_2", 0644, chip->dent,
2430 (void *)CHG_CNTRL_2, &reg_fops);
2431 debugfs_create_file("CHG_CNTRL_3", 0644, chip->dent,
2432 (void *)CHG_CNTRL_3, &reg_fops);
2433 debugfs_create_file("PBL_ACCESS1", 0644, chip->dent,
2434 (void *)PBL_ACCESS1, &reg_fops);
2435 debugfs_create_file("PBL_ACCESS2", 0644, chip->dent,
2436 (void *)PBL_ACCESS2, &reg_fops);
2437 debugfs_create_file("SYS_CONFIG_1", 0644, chip->dent,
2438 (void *)SYS_CONFIG_1, &reg_fops);
2439 debugfs_create_file("SYS_CONFIG_2", 0644, chip->dent,
2440 (void *)SYS_CONFIG_2, &reg_fops);
2441 debugfs_create_file("CHG_VDD_MAX", 0644, chip->dent,
2442 (void *)CHG_VDD_MAX, &reg_fops);
2443 debugfs_create_file("CHG_VDD_SAFE", 0644, chip->dent,
2444 (void *)CHG_VDD_SAFE, &reg_fops);
2445 debugfs_create_file("CHG_VBAT_DET", 0644, chip->dent,
2446 (void *)CHG_VBAT_DET, &reg_fops);
2447 debugfs_create_file("CHG_IBAT_MAX", 0644, chip->dent,
2448 (void *)CHG_IBAT_MAX, &reg_fops);
2449 debugfs_create_file("CHG_IBAT_SAFE", 0644, chip->dent,
2450 (void *)CHG_IBAT_SAFE, &reg_fops);
2451 debugfs_create_file("CHG_VIN_MIN", 0644, chip->dent,
2452 (void *)CHG_VIN_MIN, &reg_fops);
2453 debugfs_create_file("CHG_VTRICKLE", 0644, chip->dent,
2454 (void *)CHG_VTRICKLE, &reg_fops);
2455 debugfs_create_file("CHG_ITRICKLE", 0644, chip->dent,
2456 (void *)CHG_ITRICKLE, &reg_fops);
2457 debugfs_create_file("CHG_ITERM", 0644, chip->dent,
2458 (void *)CHG_ITERM, &reg_fops);
2459 debugfs_create_file("CHG_TCHG_MAX", 0644, chip->dent,
2460 (void *)CHG_TCHG_MAX, &reg_fops);
2461 debugfs_create_file("CHG_TWDOG", 0644, chip->dent,
2462 (void *)CHG_TWDOG, &reg_fops);
2463 debugfs_create_file("CHG_TEMP_THRESH", 0644, chip->dent,
2464 (void *)CHG_TEMP_THRESH, &reg_fops);
2465 debugfs_create_file("CHG_COMP_OVR", 0644, chip->dent,
2466 (void *)CHG_COMP_OVR, &reg_fops);
2467 debugfs_create_file("CHG_BUCK_CTRL_TEST1", 0644, chip->dent,
2468 (void *)CHG_BUCK_CTRL_TEST1, &reg_fops);
2469 debugfs_create_file("CHG_BUCK_CTRL_TEST2", 0644, chip->dent,
2470 (void *)CHG_BUCK_CTRL_TEST2, &reg_fops);
2471 debugfs_create_file("CHG_BUCK_CTRL_TEST3", 0644, chip->dent,
2472 (void *)CHG_BUCK_CTRL_TEST3, &reg_fops);
2473 debugfs_create_file("CHG_TEST", 0644, chip->dent,
2474 (void *)CHG_TEST, &reg_fops);
2475
2476 debugfs_create_file("FSM_STATE", 0644, chip->dent, NULL,
2477 &fsm_fops);
2478
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002479 debugfs_create_file("REGULATION_LOOP_CONTROL", 0644, chip->dent, NULL,
2480 &reg_loop_fops);
2481
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002482 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
2483 if (chip->pmic_chg_irq[chg_irq_data[i].irq_id])
2484 debugfs_create_file(chg_irq_data[i].name, 0444,
2485 chip->dent,
2486 (void *)chg_irq_data[i].irq_id,
2487 &rt_fops);
2488 }
2489}
2490
2491static int __devinit pm8921_charger_probe(struct platform_device *pdev)
2492{
2493 int rc = 0;
2494 struct pm8921_chg_chip *chip;
2495 const struct pm8921_charger_platform_data *pdata
2496 = pdev->dev.platform_data;
2497
2498 if (!pdata) {
2499 pr_err("missing platform data\n");
2500 return -EINVAL;
2501 }
2502
2503 chip = kzalloc(sizeof(struct pm8921_chg_chip),
2504 GFP_KERNEL);
2505 if (!chip) {
2506 pr_err("Cannot allocate pm_chg_chip\n");
2507 return -ENOMEM;
2508 }
2509
2510 chip->dev = &pdev->dev;
2511 chip->safety_time = pdata->safety_time;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002512 chip->ttrkl_time = pdata->ttrkl_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002513 chip->update_time = pdata->update_time;
2514 chip->max_voltage = pdata->max_voltage;
2515 chip->min_voltage = pdata->min_voltage;
2516 chip->resume_voltage = pdata->resume_voltage;
2517 chip->term_current = pdata->term_current;
2518 chip->vbat_channel = pdata->charger_cdata.vbat_channel;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002519 chip->batt_temp_channel = pdata->charger_cdata.batt_temp_channel;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002520 chip->batt_id_channel = pdata->charger_cdata.batt_id_channel;
2521 chip->batt_id_min = pdata->batt_id_min;
2522 chip->batt_id_max = pdata->batt_id_max;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002523 chip->cool_temp = pdata->cool_temp;
2524 chip->warm_temp = pdata->warm_temp;
2525 chip->temp_check_period = pdata->temp_check_period;
2526 chip->max_bat_chg_current = pdata->max_bat_chg_current;
2527 chip->cool_bat_chg_current = pdata->cool_bat_chg_current;
2528 chip->warm_bat_chg_current = pdata->warm_bat_chg_current;
2529 chip->cool_bat_voltage = pdata->cool_bat_voltage;
2530 chip->warm_bat_voltage = pdata->warm_bat_voltage;
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07002531 chip->trkl_voltage = pdata->trkl_voltage;
2532 chip->weak_voltage = pdata->weak_voltage;
2533 chip->trkl_current = pdata->trkl_current;
2534 chip->weak_current = pdata->weak_current;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002535 chip->vin_min = pdata->vin_min;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07002536 chip->thermal_mitigation = pdata->thermal_mitigation;
2537 chip->thermal_levels = pdata->thermal_levels;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002538
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07002539 chip->cold_thr = pdata->cold_thr;
2540 chip->hot_thr = pdata->hot_thr;
2541
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002542 rc = pm8921_chg_hw_init(chip);
2543 if (rc) {
2544 pr_err("couldn't init hardware rc=%d\n", rc);
2545 goto free_chip;
2546 }
2547
2548 chip->usb_psy.name = "usb",
2549 chip->usb_psy.type = POWER_SUPPLY_TYPE_USB,
2550 chip->usb_psy.supplied_to = pm_power_supplied_to,
2551 chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
2552 chip->usb_psy.properties = pm_power_props,
2553 chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props),
2554 chip->usb_psy.get_property = pm_power_get_property,
2555
2556 chip->dc_psy.name = "ac",
2557 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS,
2558 chip->dc_psy.supplied_to = pm_power_supplied_to,
2559 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
2560 chip->dc_psy.properties = pm_power_props,
2561 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props),
2562 chip->dc_psy.get_property = pm_power_get_property,
2563
2564 chip->batt_psy.name = "battery",
2565 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY,
2566 chip->batt_psy.properties = msm_batt_power_props,
2567 chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props),
2568 chip->batt_psy.get_property = pm_batt_power_get_property,
2569
2570 rc = power_supply_register(chip->dev, &chip->usb_psy);
2571 if (rc < 0) {
2572 pr_err("power_supply_register usb failed rc = %d\n", rc);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002573 goto free_chip;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002574 }
2575
2576 rc = power_supply_register(chip->dev, &chip->dc_psy);
2577 if (rc < 0) {
2578 pr_err("power_supply_register dc failed rc = %d\n", rc);
2579 goto unregister_usb;
2580 }
2581
2582 rc = power_supply_register(chip->dev, &chip->batt_psy);
2583 if (rc < 0) {
2584 pr_err("power_supply_register batt failed rc = %d\n", rc);
2585 goto unregister_dc;
2586 }
2587
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002588 platform_set_drvdata(pdev, chip);
2589 the_chip = chip;
2590
2591 wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
Amir Samuelovd31ef502011-10-26 14:41:36 +02002592 INIT_DELAYED_WORK(&chip->eoc_work, eoc_worker);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002593
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002594 rc = request_irqs(chip, pdev);
2595 if (rc) {
2596 pr_err("couldn't register interrupts rc=%d\n", rc);
2597 goto unregister_batt;
2598 }
2599
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07002600 enable_irq_wake(chip->pmic_chg_irq[USBIN_VALID_IRQ]);
2601 enable_irq_wake(chip->pmic_chg_irq[USBIN_OV_IRQ]);
2602 enable_irq_wake(chip->pmic_chg_irq[USBIN_UV_IRQ]);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002603 /*
2604 * if both the cool_temp and warm_temp are zero the device doesnt
2605 * care for jeita compliance
2606 */
2607 if (!(chip->cool_temp == 0 && chip->warm_temp == 0)) {
2608 rc = configure_btm(chip);
2609 if (rc) {
2610 pr_err("couldn't register with btm rc=%d\n", rc);
2611 goto free_irq;
2612 }
2613 }
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07002614
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002615 create_debugfs_entries(chip);
2616
2617 INIT_WORK(&chip->bms_notify.work, bms_notify);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002618 INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002619
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002620 /* determine what state the charger is in */
2621 determine_initial_state(chip);
2622
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07002623 if (chip->update_time) {
2624 INIT_DELAYED_WORK(&chip->update_heartbeat_work,
2625 update_heartbeat);
2626 schedule_delayed_work(&chip->update_heartbeat_work,
2627 round_jiffies_relative(msecs_to_jiffies
2628 (chip->update_time)));
2629 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002630 return 0;
2631
2632free_irq:
2633 free_irqs(chip);
2634unregister_batt:
2635 power_supply_unregister(&chip->batt_psy);
2636unregister_dc:
2637 power_supply_unregister(&chip->dc_psy);
2638unregister_usb:
2639 power_supply_unregister(&chip->usb_psy);
2640free_chip:
2641 kfree(chip);
2642 return rc;
2643}
2644
2645static int __devexit pm8921_charger_remove(struct platform_device *pdev)
2646{
2647 struct pm8921_chg_chip *chip = platform_get_drvdata(pdev);
2648
2649 free_irqs(chip);
2650 platform_set_drvdata(pdev, NULL);
2651 the_chip = NULL;
2652 kfree(chip);
2653 return 0;
2654}
2655
2656static struct platform_driver pm8921_charger_driver = {
2657 .probe = pm8921_charger_probe,
2658 .remove = __devexit_p(pm8921_charger_remove),
2659 .driver = {
2660 .name = PM8921_CHARGER_DEV_NAME,
2661 .owner = THIS_MODULE,
2662 },
2663};
2664
2665static int __init pm8921_charger_init(void)
2666{
2667 return platform_driver_register(&pm8921_charger_driver);
2668}
2669
2670static void __exit pm8921_charger_exit(void)
2671{
2672 platform_driver_unregister(&pm8921_charger_driver);
2673}
2674
2675late_initcall(pm8921_charger_init);
2676module_exit(pm8921_charger_exit);
2677
2678MODULE_LICENSE("GPL v2");
2679MODULE_DESCRIPTION("PMIC8921 charger/battery driver");
2680MODULE_VERSION("1.0");
2681MODULE_ALIAS("platform:" PM8921_CHARGER_DEV_NAME);