blob: 51ec91c2611da1ff65792fe51b54f018dbb58df2 [file] [log] [blame]
Abhijeet Dharmapurikar728bc4d2012-01-03 11:08:33 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
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 Mohanadossaf91d902011-10-20 10:23:34 -070021#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -080022#include <linux/mfd/pm8xxx/ccadc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#include <linux/mfd/pm8xxx/core.h>
24#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025#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
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -080083/* check for USB unplug every 200 msecs */
84#define UNPLUG_CHECK_WAIT_PERIOD_MS 200
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -070085
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070086enum chg_fsm_state {
87 FSM_STATE_OFF_0 = 0,
88 FSM_STATE_BATFETDET_START_12 = 12,
89 FSM_STATE_BATFETDET_END_16 = 16,
90 FSM_STATE_ON_CHG_HIGHI_1 = 1,
91 FSM_STATE_ATC_2A = 2,
92 FSM_STATE_ATC_2B = 18,
93 FSM_STATE_ON_BAT_3 = 3,
94 FSM_STATE_ATC_FAIL_4 = 4 ,
95 FSM_STATE_DELAY_5 = 5,
96 FSM_STATE_ON_CHG_AND_BAT_6 = 6,
97 FSM_STATE_FAST_CHG_7 = 7,
98 FSM_STATE_TRKL_CHG_8 = 8,
99 FSM_STATE_CHG_FAIL_9 = 9,
100 FSM_STATE_EOC_10 = 10,
101 FSM_STATE_ON_CHG_VREGOK_11 = 11,
102 FSM_STATE_ATC_PAUSE_13 = 13,
103 FSM_STATE_FAST_CHG_PAUSE_14 = 14,
104 FSM_STATE_TRKL_CHG_PAUSE_15 = 15,
105 FSM_STATE_START_BOOT = 20,
106 FSM_STATE_FLCB_VREGOK = 21,
107 FSM_STATE_FLCB = 22,
108};
109
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -0700110struct fsm_state_to_batt_status {
111 enum chg_fsm_state fsm_state;
112 int batt_state;
113};
114
115static struct fsm_state_to_batt_status map[] = {
116 {FSM_STATE_OFF_0, POWER_SUPPLY_STATUS_UNKNOWN},
117 {FSM_STATE_BATFETDET_START_12, POWER_SUPPLY_STATUS_UNKNOWN},
118 {FSM_STATE_BATFETDET_END_16, POWER_SUPPLY_STATUS_UNKNOWN},
119 /*
120 * for CHG_HIGHI_1 report NOT_CHARGING if battery missing,
121 * too hot/cold, charger too hot
122 */
123 {FSM_STATE_ON_CHG_HIGHI_1, POWER_SUPPLY_STATUS_FULL},
124 {FSM_STATE_ATC_2A, POWER_SUPPLY_STATUS_CHARGING},
125 {FSM_STATE_ATC_2B, POWER_SUPPLY_STATUS_CHARGING},
126 {FSM_STATE_ON_BAT_3, POWER_SUPPLY_STATUS_DISCHARGING},
127 {FSM_STATE_ATC_FAIL_4, POWER_SUPPLY_STATUS_DISCHARGING},
128 {FSM_STATE_DELAY_5, POWER_SUPPLY_STATUS_UNKNOWN },
129 {FSM_STATE_ON_CHG_AND_BAT_6, POWER_SUPPLY_STATUS_CHARGING},
130 {FSM_STATE_FAST_CHG_7, POWER_SUPPLY_STATUS_CHARGING},
131 {FSM_STATE_TRKL_CHG_8, POWER_SUPPLY_STATUS_CHARGING},
132 {FSM_STATE_CHG_FAIL_9, POWER_SUPPLY_STATUS_DISCHARGING},
133 {FSM_STATE_EOC_10, POWER_SUPPLY_STATUS_FULL},
134 {FSM_STATE_ON_CHG_VREGOK_11, POWER_SUPPLY_STATUS_NOT_CHARGING},
135 {FSM_STATE_ATC_PAUSE_13, POWER_SUPPLY_STATUS_NOT_CHARGING},
136 {FSM_STATE_FAST_CHG_PAUSE_14, POWER_SUPPLY_STATUS_NOT_CHARGING},
137 {FSM_STATE_TRKL_CHG_PAUSE_15, POWER_SUPPLY_STATUS_NOT_CHARGING},
138 {FSM_STATE_START_BOOT, POWER_SUPPLY_STATUS_NOT_CHARGING},
139 {FSM_STATE_FLCB_VREGOK, POWER_SUPPLY_STATUS_NOT_CHARGING},
140 {FSM_STATE_FLCB, POWER_SUPPLY_STATUS_NOT_CHARGING},
141};
142
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700143enum chg_regulation_loop {
144 VDD_LOOP = BIT(3),
145 BAT_CURRENT_LOOP = BIT(2),
146 INPUT_CURRENT_LOOP = BIT(1),
147 INPUT_VOLTAGE_LOOP = BIT(0),
148 CHG_ALL_LOOPS = VDD_LOOP | BAT_CURRENT_LOOP
149 | INPUT_CURRENT_LOOP | INPUT_VOLTAGE_LOOP,
150};
151
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700152enum pmic_chg_interrupts {
153 USBIN_VALID_IRQ = 0,
154 USBIN_OV_IRQ,
155 BATT_INSERTED_IRQ,
156 VBATDET_LOW_IRQ,
157 USBIN_UV_IRQ,
158 VBAT_OV_IRQ,
159 CHGWDOG_IRQ,
160 VCP_IRQ,
161 ATCDONE_IRQ,
162 ATCFAIL_IRQ,
163 CHGDONE_IRQ,
164 CHGFAIL_IRQ,
165 CHGSTATE_IRQ,
166 LOOP_CHANGE_IRQ,
167 FASTCHG_IRQ,
168 TRKLCHG_IRQ,
169 BATT_REMOVED_IRQ,
170 BATTTEMP_HOT_IRQ,
171 CHGHOT_IRQ,
172 BATTTEMP_COLD_IRQ,
173 CHG_GONE_IRQ,
174 BAT_TEMP_OK_IRQ,
175 COARSE_DET_LOW_IRQ,
176 VDD_LOOP_IRQ,
177 VREG_OV_IRQ,
178 VBATDET_IRQ,
179 BATFET_IRQ,
180 PSI_IRQ,
181 DCIN_VALID_IRQ,
182 DCIN_OV_IRQ,
183 DCIN_UV_IRQ,
184 PM_CHG_MAX_INTS,
185};
186
187struct bms_notify {
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700188 int is_battery_full;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189 int is_charging;
190 struct work_struct work;
191};
192
193/**
194 * struct pm8921_chg_chip -device information
195 * @dev: device pointer to access the parent
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700196 * @usb_present: present status of usb
197 * @dc_present: present status of dc
198 * @usb_charger_current: usb current to charge the battery with used when
199 * the usb path is enabled or charging is resumed
200 * @safety_time: max time for which charging will happen
201 * @update_time: how frequently the userland needs to be updated
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800202 * @max_voltage_mv: the max volts the batt should be charged up to
203 * @min_voltage_mv: the min battery voltage before turning the FETon
204 * @cool_temp_dc: the cool temp threshold in deciCelcius
205 * @warm_temp_dc: the warm temp threshold in deciCelcius
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -0700206 * @resume_voltage_delta: the voltage delta from vdd max at which the
207 * battery should resume charging
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208 * @term_current: The charging based term current
209 *
210 */
211struct pm8921_chg_chip {
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700212 struct device *dev;
213 unsigned int usb_present;
214 unsigned int dc_present;
215 unsigned int usb_charger_current;
216 unsigned int max_bat_chg_current;
217 unsigned int pmic_chg_irq[PM_CHG_MAX_INTS];
218 unsigned int safety_time;
219 unsigned int ttrkl_time;
220 unsigned int update_time;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800221 unsigned int max_voltage_mv;
222 unsigned int min_voltage_mv;
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -0800223 int cool_temp_dc;
224 int warm_temp_dc;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700225 unsigned int temp_check_period;
226 unsigned int cool_bat_chg_current;
227 unsigned int warm_bat_chg_current;
228 unsigned int cool_bat_voltage;
229 unsigned int warm_bat_voltage;
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -0700230 unsigned int is_bat_cool;
231 unsigned int is_bat_warm;
232 unsigned int resume_voltage_delta;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700233 unsigned int term_current;
234 unsigned int vbat_channel;
235 unsigned int batt_temp_channel;
236 unsigned int batt_id_channel;
237 struct power_supply usb_psy;
David Keitel88e1b572012-01-11 11:57:14 -0800238 struct power_supply *ext_psy;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700239 struct power_supply batt_psy;
240 struct dentry *dent;
241 struct bms_notify bms_notify;
David Keitelf2226022011-12-13 15:55:50 -0800242 bool keep_btm_on_suspend;
Amir Samuelovd31ef502011-10-26 14:41:36 +0200243 bool ext_charging;
244 bool ext_charge_done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700245 DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700246 struct work_struct battery_id_valid_work;
247 int64_t batt_id_min;
248 int64_t batt_id_max;
249 int trkl_voltage;
250 int weak_voltage;
251 int trkl_current;
252 int weak_current;
253 int vin_min;
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -0800254 unsigned int *thermal_mitigation;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700255 int thermal_levels;
256 struct delayed_work update_heartbeat_work;
257 struct delayed_work eoc_work;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -0800258 struct delayed_work unplug_wrkarnd_restore_work;
259 struct delayed_work unplug_check_work;
260 struct wake_lock unplug_wrkarnd_restore_wake_lock;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700261 struct wake_lock eoc_wake_lock;
262 enum pm8921_chg_cold_thr cold_thr;
263 enum pm8921_chg_hot_thr hot_thr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700264};
265
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800266static int usb_max_current;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267static int charging_disabled;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -0700268static int thermal_mitigation;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700269
270static struct pm8921_chg_chip *the_chip;
271
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -0700272static struct pm8xxx_adc_arb_btm_param btm_config;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -0700273
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr,
275 u8 mask, u8 val)
276{
277 int rc;
278 u8 reg;
279
280 rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
281 if (rc) {
282 pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n", addr, rc);
283 return rc;
284 }
285 reg &= ~mask;
286 reg |= val & mask;
287 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
288 if (rc) {
289 pr_err("pm8xxx_writeb failed: addr=%03X, rc=%d\n", addr, rc);
290 return rc;
291 }
292 return 0;
293}
294
295#define CAPTURE_FSM_STATE_CMD 0xC2
296#define READ_BANK_7 0x70
297#define READ_BANK_4 0x40
298static int pm_chg_get_fsm_state(struct pm8921_chg_chip *chip)
299{
300 u8 temp;
301 int err, ret = 0;
302
303 temp = CAPTURE_FSM_STATE_CMD;
304 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
305 if (err) {
306 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
307 return err;
308 }
309
310 temp = READ_BANK_7;
311 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
312 if (err) {
313 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
314 return err;
315 }
316
317 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
318 if (err) {
319 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
320 return err;
321 }
322 /* get the lower 4 bits */
323 ret = temp & 0xF;
324
325 temp = READ_BANK_4;
326 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
327 if (err) {
328 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
329 return err;
330 }
331
332 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
333 if (err) {
334 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
335 return err;
336 }
337 /* get the upper 1 bit */
338 ret |= (temp & 0x1) << 4;
339 return ret;
340}
341
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700342#define READ_BANK_6 0x60
343static int pm_chg_get_regulation_loop(struct pm8921_chg_chip *chip)
344{
345 u8 temp;
346 int err;
347
348 temp = READ_BANK_6;
349 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
350 if (err) {
351 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
352 return err;
353 }
354
355 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
356 if (err) {
357 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
358 return err;
359 }
360
361 /* return the lower 4 bits */
362 return temp & CHG_ALL_LOOPS;
363}
364
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365#define CHG_USB_SUSPEND_BIT BIT(2)
366static int pm_chg_usb_suspend_enable(struct pm8921_chg_chip *chip, int enable)
367{
368 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_USB_SUSPEND_BIT,
369 enable ? CHG_USB_SUSPEND_BIT : 0);
370}
371
372#define CHG_EN_BIT BIT(7)
373static int pm_chg_auto_enable(struct pm8921_chg_chip *chip, int enable)
374{
375 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_EN_BIT,
376 enable ? CHG_EN_BIT : 0);
377}
378
David Keitel753ec8d2011-11-02 10:56:37 -0700379#define CHG_FAILED_CLEAR BIT(0)
380#define ATC_FAILED_CLEAR BIT(1)
381static int pm_chg_failed_clear(struct pm8921_chg_chip *chip, int clear)
382{
383 int rc;
384
385 rc = pm_chg_masked_write(chip, CHG_CNTRL_3, ATC_FAILED_CLEAR,
386 clear ? ATC_FAILED_CLEAR : 0);
387 rc |= pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_FAILED_CLEAR,
388 clear ? CHG_FAILED_CLEAR : 0);
389 return rc;
390}
391
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700392#define CHG_CHARGE_DIS_BIT BIT(1)
393static int pm_chg_charge_dis(struct pm8921_chg_chip *chip, int disable)
394{
395 return pm_chg_masked_write(chip, CHG_CNTRL, CHG_CHARGE_DIS_BIT,
396 disable ? CHG_CHARGE_DIS_BIT : 0);
397}
398
Abhijeet Dharmapurikarbe054882012-01-03 20:27:07 -0800399static bool pm_is_chg_charge_dis_bit_set(struct pm8921_chg_chip *chip)
400{
401 u8 temp = 0;
402
403 pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
404 return !!(temp & CHG_CHARGE_DIS_BIT);
405}
406
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407#define PM8921_CHG_V_MIN_MV 3240
408#define PM8921_CHG_V_STEP_MV 20
409#define PM8921_CHG_VDDMAX_MAX 4500
410#define PM8921_CHG_VDDMAX_MIN 3400
411#define PM8921_CHG_V_MASK 0x7F
412static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
413{
414 u8 temp;
415
416 if (voltage < PM8921_CHG_VDDMAX_MIN
417 || voltage > PM8921_CHG_VDDMAX_MAX) {
418 pr_err("bad mV=%d asked to set\n", voltage);
419 return -EINVAL;
420 }
421 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
422 pr_debug("voltage=%d setting %02x\n", voltage, temp);
423 return pm_chg_masked_write(chip, CHG_VDD_MAX, PM8921_CHG_V_MASK, temp);
424}
425
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700426static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
427{
428 u8 temp;
429 int rc;
430
431 rc = pm8xxx_readb(chip->dev->parent, CHG_VDD_MAX, &temp);
432 if (rc) {
433 pr_err("rc = %d while reading vdd max\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700434 *voltage = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700435 return rc;
436 }
437 temp &= PM8921_CHG_V_MASK;
438 *voltage = (int)temp * PM8921_CHG_V_STEP_MV + PM8921_CHG_V_MIN_MV;
439 return 0;
440}
441
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700442#define PM8921_CHG_VDDSAFE_MIN 3400
443#define PM8921_CHG_VDDSAFE_MAX 4500
444static int pm_chg_vddsafe_set(struct pm8921_chg_chip *chip, int voltage)
445{
446 u8 temp;
447
448 if (voltage < PM8921_CHG_VDDSAFE_MIN
449 || voltage > PM8921_CHG_VDDSAFE_MAX) {
450 pr_err("bad mV=%d asked to set\n", voltage);
451 return -EINVAL;
452 }
453 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
454 pr_debug("voltage=%d setting %02x\n", voltage, temp);
455 return pm_chg_masked_write(chip, CHG_VDD_SAFE, PM8921_CHG_V_MASK, temp);
456}
457
458#define PM8921_CHG_VBATDET_MIN 3240
459#define PM8921_CHG_VBATDET_MAX 5780
460static int pm_chg_vbatdet_set(struct pm8921_chg_chip *chip, int voltage)
461{
462 u8 temp;
463
464 if (voltage < PM8921_CHG_VBATDET_MIN
465 || voltage > PM8921_CHG_VBATDET_MAX) {
466 pr_err("bad mV=%d asked to set\n", voltage);
467 return -EINVAL;
468 }
469 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
470 pr_debug("voltage=%d setting %02x\n", voltage, temp);
471 return pm_chg_masked_write(chip, CHG_VBAT_DET, PM8921_CHG_V_MASK, temp);
472}
473
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -0700474#define PM8921_CHG_VINMIN_MIN_MV 3800
475#define PM8921_CHG_VINMIN_STEP_MV 100
476#define PM8921_CHG_VINMIN_USABLE_MAX 6500
477#define PM8921_CHG_VINMIN_USABLE_MIN 4300
478#define PM8921_CHG_VINMIN_MASK 0x1F
479static int pm_chg_vinmin_set(struct pm8921_chg_chip *chip, int voltage)
480{
481 u8 temp;
482
483 if (voltage < PM8921_CHG_VINMIN_USABLE_MIN
484 || voltage > PM8921_CHG_VINMIN_USABLE_MAX) {
485 pr_err("bad mV=%d asked to set\n", voltage);
486 return -EINVAL;
487 }
488 temp = (voltage - PM8921_CHG_VINMIN_MIN_MV) / PM8921_CHG_VINMIN_STEP_MV;
489 pr_debug("voltage=%d setting %02x\n", voltage, temp);
490 return pm_chg_masked_write(chip, CHG_VIN_MIN, PM8921_CHG_VINMIN_MASK,
491 temp);
492}
493
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -0800494static int pm_chg_vinmin_get(struct pm8921_chg_chip *chip)
495{
496 u8 temp;
497 int rc, voltage_mv;
498
499 rc = pm8xxx_readb(chip->dev->parent, CHG_VIN_MIN, &temp);
500 temp &= PM8921_CHG_VINMIN_MASK;
501
502 voltage_mv = PM8921_CHG_VINMIN_MIN_MV +
503 (int)temp * PM8921_CHG_VINMIN_STEP_MV;
504
505 return voltage_mv;
506}
507
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700508#define PM8921_CHG_IBATMAX_MIN 325
509#define PM8921_CHG_IBATMAX_MAX 2000
510#define PM8921_CHG_I_MIN_MA 225
511#define PM8921_CHG_I_STEP_MA 50
512#define PM8921_CHG_I_MASK 0x3F
513static int pm_chg_ibatmax_set(struct pm8921_chg_chip *chip, int chg_current)
514{
515 u8 temp;
516
517 if (chg_current < PM8921_CHG_IBATMAX_MIN
518 || chg_current > PM8921_CHG_IBATMAX_MAX) {
519 pr_err("bad mA=%d asked to set\n", chg_current);
520 return -EINVAL;
521 }
522 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
523 return pm_chg_masked_write(chip, CHG_IBAT_MAX, PM8921_CHG_I_MASK, temp);
524}
525
526#define PM8921_CHG_IBATSAFE_MIN 225
527#define PM8921_CHG_IBATSAFE_MAX 3375
528static int pm_chg_ibatsafe_set(struct pm8921_chg_chip *chip, int chg_current)
529{
530 u8 temp;
531
532 if (chg_current < PM8921_CHG_IBATSAFE_MIN
533 || chg_current > PM8921_CHG_IBATSAFE_MAX) {
534 pr_err("bad mA=%d asked to set\n", chg_current);
535 return -EINVAL;
536 }
537 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
538 return pm_chg_masked_write(chip, CHG_IBAT_SAFE,
539 PM8921_CHG_I_MASK, temp);
540}
541
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700542#define PM8921_CHG_ITERM_MIN_MA 50
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700543#define PM8921_CHG_ITERM_MAX_MA 200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700544#define PM8921_CHG_ITERM_STEP_MA 10
545#define PM8921_CHG_ITERM_MASK 0xF
546static int pm_chg_iterm_set(struct pm8921_chg_chip *chip, int chg_current)
547{
548 u8 temp;
549
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700550 if (chg_current < PM8921_CHG_ITERM_MIN_MA
551 || chg_current > PM8921_CHG_ITERM_MAX_MA) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552 pr_err("bad mA=%d asked to set\n", chg_current);
553 return -EINVAL;
554 }
555
556 temp = (chg_current - PM8921_CHG_ITERM_MIN_MA)
557 / PM8921_CHG_ITERM_STEP_MA;
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700558 return pm_chg_masked_write(chip, CHG_ITERM, PM8921_CHG_ITERM_MASK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559 temp);
560}
561
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700562static int pm_chg_iterm_get(struct pm8921_chg_chip *chip, int *chg_current)
563{
564 u8 temp;
565 int rc;
566
567 rc = pm8xxx_readb(chip->dev->parent, CHG_ITERM, &temp);
568 if (rc) {
569 pr_err("err=%d reading CHG_ITEM\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700570 *chg_current = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700571 return rc;
572 }
573 temp &= PM8921_CHG_ITERM_MASK;
574 *chg_current = (int)temp * PM8921_CHG_ITERM_STEP_MA
575 + PM8921_CHG_ITERM_MIN_MA;
576 return 0;
577}
578
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800579struct usb_ma_limit_entry {
580 int usb_ma;
581 u8 chg_iusb_value;
582};
583
584static struct usb_ma_limit_entry usb_ma_table[] = {
585 {100, 0},
586 {500, 1},
587 {700, 2},
588 {850, 3},
589 {900, 4},
590 {1100, 5},
591 {1300, 6},
592 {1500, 7},
593};
594
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700595#define PM8921_CHG_IUSB_MASK 0x1C
596#define PM8921_CHG_IUSB_MAX 7
597#define PM8921_CHG_IUSB_MIN 0
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700598static int pm_chg_iusbmax_set(struct pm8921_chg_chip *chip, int reg_val)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599{
600 u8 temp;
601
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700602 if (reg_val < PM8921_CHG_IUSB_MIN || reg_val > PM8921_CHG_IUSB_MAX) {
603 pr_err("bad mA=%d asked to set\n", reg_val);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700604 return -EINVAL;
605 }
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700606 temp = reg_val << 2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607 return pm_chg_masked_write(chip, PBL_ACCESS2, PM8921_CHG_IUSB_MASK,
608 temp);
609}
610
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800611static int pm_chg_iusbmax_get(struct pm8921_chg_chip *chip, int *mA)
612{
613 u8 temp;
614 int i, rc;
615
616 *mA = 0;
617 rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS2, &temp);
618 if (rc) {
619 pr_err("err=%d reading PBL_ACCESS2\n", rc);
620 return rc;
621 }
622 temp &= PM8921_CHG_IUSB_MASK;
623 temp = temp >> 2;
624 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
625 if (usb_ma_table[i].chg_iusb_value == temp)
626 *mA = usb_ma_table[i].usb_ma;
627 }
628 return rc;
629}
630
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700631#define PM8921_CHG_WD_MASK 0x1F
632static int pm_chg_disable_wd(struct pm8921_chg_chip *chip)
633{
634 /* writing 0 to the wd timer disables it */
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700635 return pm_chg_masked_write(chip, CHG_TWDOG, PM8921_CHG_WD_MASK, 0);
636}
637
Abhijeet Dharmapurikarc26cd902011-10-26 18:07:45 -0700638#define PM8921_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700639#define PM8921_CHG_TCHG_MIN 4
640#define PM8921_CHG_TCHG_MAX 512
641#define PM8921_CHG_TCHG_STEP 4
642static int pm_chg_tchg_max_set(struct pm8921_chg_chip *chip, int minutes)
643{
644 u8 temp;
645
646 if (minutes < PM8921_CHG_TCHG_MIN || minutes > PM8921_CHG_TCHG_MAX) {
647 pr_err("bad max minutes =%d asked to set\n", minutes);
648 return -EINVAL;
649 }
650
651 temp = (minutes - 1)/PM8921_CHG_TCHG_STEP;
652 return pm_chg_masked_write(chip, CHG_TCHG_MAX, PM8921_CHG_TCHG_MASK,
653 temp);
654}
655
656#define PM8921_CHG_TTRKL_MASK 0x1F
657#define PM8921_CHG_TTRKL_MIN 1
658#define PM8921_CHG_TTRKL_MAX 64
659static int pm_chg_ttrkl_max_set(struct pm8921_chg_chip *chip, int minutes)
660{
661 u8 temp;
662
663 if (minutes < PM8921_CHG_TTRKL_MIN || minutes > PM8921_CHG_TTRKL_MAX) {
664 pr_err("bad max minutes =%d asked to set\n", minutes);
665 return -EINVAL;
666 }
667
668 temp = minutes - 1;
669 return pm_chg_masked_write(chip, CHG_TTRKL_MAX, PM8921_CHG_TTRKL_MASK,
670 temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700671}
672
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -0700673#define PM8921_CHG_VTRKL_MIN_MV 2050
674#define PM8921_CHG_VTRKL_MAX_MV 2800
675#define PM8921_CHG_VTRKL_STEP_MV 50
676#define PM8921_CHG_VTRKL_SHIFT 4
677#define PM8921_CHG_VTRKL_MASK 0xF0
678static int pm_chg_vtrkl_low_set(struct pm8921_chg_chip *chip, int millivolts)
679{
680 u8 temp;
681
682 if (millivolts < PM8921_CHG_VTRKL_MIN_MV
683 || millivolts > PM8921_CHG_VTRKL_MAX_MV) {
684 pr_err("bad voltage = %dmV asked to set\n", millivolts);
685 return -EINVAL;
686 }
687
688 temp = (millivolts - PM8921_CHG_VTRKL_MIN_MV)/PM8921_CHG_VTRKL_STEP_MV;
689 temp = temp << PM8921_CHG_VTRKL_SHIFT;
690 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VTRKL_MASK,
691 temp);
692}
693
694#define PM8921_CHG_VWEAK_MIN_MV 2100
695#define PM8921_CHG_VWEAK_MAX_MV 3600
696#define PM8921_CHG_VWEAK_STEP_MV 100
697#define PM8921_CHG_VWEAK_MASK 0x0F
698static int pm_chg_vweak_set(struct pm8921_chg_chip *chip, int millivolts)
699{
700 u8 temp;
701
702 if (millivolts < PM8921_CHG_VWEAK_MIN_MV
703 || millivolts > PM8921_CHG_VWEAK_MAX_MV) {
704 pr_err("bad voltage = %dmV asked to set\n", millivolts);
705 return -EINVAL;
706 }
707
708 temp = (millivolts - PM8921_CHG_VWEAK_MIN_MV)/PM8921_CHG_VWEAK_STEP_MV;
709 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VWEAK_MASK,
710 temp);
711}
712
713#define PM8921_CHG_ITRKL_MIN_MA 50
714#define PM8921_CHG_ITRKL_MAX_MA 200
715#define PM8921_CHG_ITRKL_MASK 0x0F
716#define PM8921_CHG_ITRKL_STEP_MA 10
717static int pm_chg_itrkl_set(struct pm8921_chg_chip *chip, int milliamps)
718{
719 u8 temp;
720
721 if (milliamps < PM8921_CHG_ITRKL_MIN_MA
722 || milliamps > PM8921_CHG_ITRKL_MAX_MA) {
723 pr_err("bad current = %dmA asked to set\n", milliamps);
724 return -EINVAL;
725 }
726
727 temp = (milliamps - PM8921_CHG_ITRKL_MIN_MA)/PM8921_CHG_ITRKL_STEP_MA;
728
729 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_ITRKL_MASK,
730 temp);
731}
732
733#define PM8921_CHG_IWEAK_MIN_MA 325
734#define PM8921_CHG_IWEAK_MAX_MA 525
735#define PM8921_CHG_IWEAK_SHIFT 7
736#define PM8921_CHG_IWEAK_MASK 0x80
737static int pm_chg_iweak_set(struct pm8921_chg_chip *chip, int milliamps)
738{
739 u8 temp;
740
741 if (milliamps < PM8921_CHG_IWEAK_MIN_MA
742 || milliamps > PM8921_CHG_IWEAK_MAX_MA) {
743 pr_err("bad current = %dmA asked to set\n", milliamps);
744 return -EINVAL;
745 }
746
747 if (milliamps < PM8921_CHG_IWEAK_MAX_MA)
748 temp = 0;
749 else
750 temp = 1;
751
752 temp = temp << PM8921_CHG_IWEAK_SHIFT;
753 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_IWEAK_MASK,
754 temp);
755}
756
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700757#define PM8921_CHG_BATT_TEMP_THR_COLD BIT(1)
758#define PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT 1
759static int pm_chg_batt_cold_temp_config(struct pm8921_chg_chip *chip,
760 enum pm8921_chg_cold_thr cold_thr)
761{
762 u8 temp;
763
764 temp = cold_thr << PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT;
765 temp = temp & PM8921_CHG_BATT_TEMP_THR_COLD;
766 return pm_chg_masked_write(chip, CHG_CNTRL_2,
767 PM8921_CHG_BATT_TEMP_THR_COLD,
768 temp);
769}
770
771#define PM8921_CHG_BATT_TEMP_THR_HOT BIT(0)
772#define PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT 0
773static int pm_chg_batt_hot_temp_config(struct pm8921_chg_chip *chip,
774 enum pm8921_chg_hot_thr hot_thr)
775{
776 u8 temp;
777
778 temp = hot_thr << PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT;
779 temp = temp & PM8921_CHG_BATT_TEMP_THR_HOT;
780 return pm_chg_masked_write(chip, CHG_CNTRL_2,
781 PM8921_CHG_BATT_TEMP_THR_HOT,
782 temp);
783}
784
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -0700785static int64_t read_battery_id(struct pm8921_chg_chip *chip)
786{
787 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -0700788 struct pm8xxx_adc_chan_result result;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -0700789
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -0700790 rc = pm8xxx_adc_read(chip->batt_id_channel, &result);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -0700791 if (rc) {
792 pr_err("error reading batt id channel = %d, rc = %d\n",
793 chip->vbat_channel, rc);
794 return rc;
795 }
796 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
797 result.measurement);
798 return result.physical;
799}
800
801static int is_battery_valid(struct pm8921_chg_chip *chip)
802{
803 int64_t rc;
804
805 if (chip->batt_id_min == 0 && chip->batt_id_max == 0)
806 return 1;
807
808 rc = read_battery_id(chip);
809 if (rc < 0) {
810 pr_err("error reading batt id channel = %d, rc = %lld\n",
811 chip->vbat_channel, rc);
812 /* assume battery id is valid when adc error happens */
813 return 1;
814 }
815
816 if (rc < chip->batt_id_min || rc > chip->batt_id_max) {
817 pr_err("batt_id phy =%lld is not valid\n", rc);
818 return 0;
819 }
820 return 1;
821}
822
823static void check_battery_valid(struct pm8921_chg_chip *chip)
824{
825 if (is_battery_valid(chip) == 0) {
826 pr_err("batt_id not valid, disbling charging\n");
827 pm_chg_auto_enable(chip, 0);
828 } else {
829 pm_chg_auto_enable(chip, !charging_disabled);
830 }
831}
832
833static void battery_id_valid(struct work_struct *work)
834{
835 struct pm8921_chg_chip *chip = container_of(work,
836 struct pm8921_chg_chip, battery_id_valid_work);
837
838 check_battery_valid(chip);
839}
840
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841static void pm8921_chg_enable_irq(struct pm8921_chg_chip *chip, int interrupt)
842{
843 if (!__test_and_set_bit(interrupt, chip->enabled_irqs)) {
844 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
845 enable_irq(chip->pmic_chg_irq[interrupt]);
846 }
847}
848
849static void pm8921_chg_disable_irq(struct pm8921_chg_chip *chip, int interrupt)
850{
851 if (__test_and_clear_bit(interrupt, chip->enabled_irqs)) {
852 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
853 disable_irq_nosync(chip->pmic_chg_irq[interrupt]);
854 }
855}
856
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -0800857static int pm8921_chg_is_enabled(struct pm8921_chg_chip *chip, int interrupt)
858{
859 return test_bit(interrupt, chip->enabled_irqs);
860}
861
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700862static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
863{
864 return pm8xxx_read_irq_stat(chip->dev->parent,
865 chip->pmic_chg_irq[irq_id]);
866}
867
868/* Treat OverVoltage/UnderVoltage as source missing */
869static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
870{
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -0700871 return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872}
873
874/* Treat OverVoltage/UnderVoltage as source missing */
875static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
876{
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -0700877 return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700878}
879
Amir Samuelovd31ef502011-10-26 14:41:36 +0200880static bool is_ext_charging(struct pm8921_chg_chip *chip)
881{
David Keitel88e1b572012-01-11 11:57:14 -0800882 union power_supply_propval ret = {0,};
Amir Samuelovd31ef502011-10-26 14:41:36 +0200883
David Keitel88e1b572012-01-11 11:57:14 -0800884 if (!chip->ext_psy)
885 return false;
886 if (chip->ext_psy->get_property(chip->ext_psy,
887 POWER_SUPPLY_PROP_CHARGE_TYPE, &ret))
888 return false;
889 if (ret.intval > POWER_SUPPLY_CHARGE_TYPE_NONE)
890 return ret.intval;
Amir Samuelovd31ef502011-10-26 14:41:36 +0200891
892 return false;
893}
894
895static bool is_ext_trickle_charging(struct pm8921_chg_chip *chip)
896{
David Keitel88e1b572012-01-11 11:57:14 -0800897 union power_supply_propval ret = {0,};
Amir Samuelovd31ef502011-10-26 14:41:36 +0200898
David Keitel88e1b572012-01-11 11:57:14 -0800899 if (!chip->ext_psy)
900 return false;
901 if (chip->ext_psy->get_property(chip->ext_psy,
902 POWER_SUPPLY_PROP_CHARGE_TYPE, &ret))
903 return false;
904 if (ret.intval == POWER_SUPPLY_CHARGE_TYPE_TRICKLE)
Amir Samuelovd31ef502011-10-26 14:41:36 +0200905 return true;
906
907 return false;
908}
909
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700910static int is_battery_charging(int fsm_state)
911{
Amir Samuelovd31ef502011-10-26 14:41:36 +0200912 if (is_ext_charging(the_chip))
913 return 1;
914
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915 switch (fsm_state) {
916 case FSM_STATE_ATC_2A:
917 case FSM_STATE_ATC_2B:
918 case FSM_STATE_ON_CHG_AND_BAT_6:
919 case FSM_STATE_FAST_CHG_7:
920 case FSM_STATE_TRKL_CHG_8:
921 return 1;
922 }
923 return 0;
924}
925
926static void bms_notify(struct work_struct *work)
927{
928 struct bms_notify *n = container_of(work, struct bms_notify, work);
929
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700930 if (n->is_charging) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700931 pm8921_bms_charging_began();
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700932 } else {
933 pm8921_bms_charging_end(n->is_battery_full);
934 n->is_battery_full = 0;
935 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700936}
937
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -0700938static void bms_notify_check(struct pm8921_chg_chip *chip)
939{
940 int fsm_state, new_is_charging;
941
942 fsm_state = pm_chg_get_fsm_state(chip);
943 new_is_charging = is_battery_charging(fsm_state);
944
945 if (chip->bms_notify.is_charging ^ new_is_charging) {
946 chip->bms_notify.is_charging = new_is_charging;
947 schedule_work(&(chip->bms_notify.work));
948 }
949}
950
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700951static enum power_supply_property pm_power_props[] = {
952 POWER_SUPPLY_PROP_PRESENT,
Willie Ruan9ad6d832011-08-19 11:58:42 -0700953 POWER_SUPPLY_PROP_ONLINE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700954};
955
956static char *pm_power_supplied_to[] = {
957 "battery",
958};
959
960static int pm_power_get_property(struct power_supply *psy,
961 enum power_supply_property psp,
962 union power_supply_propval *val)
963{
964 struct pm8921_chg_chip *chip;
965
966 switch (psp) {
967 case POWER_SUPPLY_PROP_PRESENT:
Willie Ruan9ad6d832011-08-19 11:58:42 -0700968 case POWER_SUPPLY_PROP_ONLINE:
David Keitel6df9cea2011-12-21 12:36:45 -0800969 if (psy->type == POWER_SUPPLY_TYPE_USB ||
970 psy->type == POWER_SUPPLY_TYPE_USB_DCP ||
971 psy->type == POWER_SUPPLY_TYPE_USB_CDP ||
972 psy->type == POWER_SUPPLY_TYPE_USB_ACA) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700973 chip = container_of(psy, struct pm8921_chg_chip,
974 usb_psy);
Abhijeet Dharmapurikarbe054882012-01-03 20:27:07 -0800975 if (pm_is_chg_charge_dis_bit_set(chip))
976 val->intval = 0;
977 else
978 val->intval = is_usb_chg_plugged_in(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700979 }
980 break;
981 default:
982 return -EINVAL;
983 }
984 return 0;
985}
986
987static enum power_supply_property msm_batt_power_props[] = {
988 POWER_SUPPLY_PROP_STATUS,
989 POWER_SUPPLY_PROP_CHARGE_TYPE,
990 POWER_SUPPLY_PROP_HEALTH,
991 POWER_SUPPLY_PROP_PRESENT,
992 POWER_SUPPLY_PROP_TECHNOLOGY,
993 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
994 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
995 POWER_SUPPLY_PROP_VOLTAGE_NOW,
996 POWER_SUPPLY_PROP_CAPACITY,
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -0700997 POWER_SUPPLY_PROP_CURRENT_NOW,
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -0700998 POWER_SUPPLY_PROP_TEMP,
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -0700999 POWER_SUPPLY_PROP_ENERGY_FULL,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001000};
1001
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001002static int get_prop_battery_uvolts(struct pm8921_chg_chip *chip)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001003{
1004 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001005 struct pm8xxx_adc_chan_result result;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001007 rc = pm8xxx_adc_read(chip->vbat_channel, &result);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001008 if (rc) {
1009 pr_err("error reading adc channel = %d, rc = %d\n",
1010 chip->vbat_channel, rc);
1011 return rc;
1012 }
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001013 pr_debug("mvolts phy = %lld meas = 0x%llx\n", result.physical,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001014 result.measurement);
1015 return (int)result.physical;
1016}
1017
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001018static unsigned int voltage_based_capacity(struct pm8921_chg_chip *chip)
1019{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001020 unsigned int current_voltage_uv = get_prop_battery_uvolts(chip);
1021 unsigned int current_voltage_mv = current_voltage_uv / 1000;
1022 unsigned int low_voltage = chip->min_voltage_mv;
1023 unsigned int high_voltage = chip->max_voltage_mv;
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001024
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001025 if (current_voltage_mv <= low_voltage)
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001026 return 0;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001027 else if (current_voltage_mv >= high_voltage)
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001028 return 100;
1029 else
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001030 return (current_voltage_mv - low_voltage) * 100
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001031 / (high_voltage - low_voltage);
1032}
1033
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001034static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
1035{
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001036 int percent_soc = pm8921_bms_get_percent_charge();
1037
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001038 if (percent_soc == -ENXIO)
1039 percent_soc = voltage_based_capacity(chip);
1040
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001041 if (percent_soc <= 10)
1042 pr_warn("low battery charge = %d%%\n", percent_soc);
1043
1044 return percent_soc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001045}
1046
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001047static int get_prop_batt_current(struct pm8921_chg_chip *chip)
1048{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001049 int result_ua, rc;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001050
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001051 rc = pm8921_bms_get_battery_current(&result_ua);
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001052 if (rc == -ENXIO) {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001053 rc = pm8xxx_ccadc_get_battery_current(&result_ua);
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001054 }
1055
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001056 if (rc) {
1057 pr_err("unable to get batt current rc = %d\n", rc);
1058 return rc;
1059 } else {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001060 return result_ua;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001061 }
1062}
1063
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001064static int get_prop_batt_fcc(struct pm8921_chg_chip *chip)
1065{
1066 int rc;
1067
1068 rc = pm8921_bms_get_fcc();
1069 if (rc < 0)
1070 pr_err("unable to get batt fcc rc = %d\n", rc);
1071 return rc;
1072}
1073
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074static int get_prop_batt_health(struct pm8921_chg_chip *chip)
1075{
1076 int temp;
1077
1078 temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
1079 if (temp)
1080 return POWER_SUPPLY_HEALTH_OVERHEAT;
1081
1082 temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
1083 if (temp)
1084 return POWER_SUPPLY_HEALTH_COLD;
1085
1086 return POWER_SUPPLY_HEALTH_GOOD;
1087}
1088
1089static int get_prop_batt_present(struct pm8921_chg_chip *chip)
1090{
1091 return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1092}
1093
1094static int get_prop_charge_type(struct pm8921_chg_chip *chip)
1095{
1096 int temp;
1097
Amir Samuelovd31ef502011-10-26 14:41:36 +02001098 if (!get_prop_batt_present(chip))
1099 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1100
1101 if (is_ext_trickle_charging(chip))
1102 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1103
1104 if (is_ext_charging(chip))
1105 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1106
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001107 temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
1108 if (temp)
1109 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1110
1111 temp = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
1112 if (temp)
1113 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1114
1115 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1116}
1117
1118static int get_prop_batt_status(struct pm8921_chg_chip *chip)
1119{
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -07001120 int batt_state = POWER_SUPPLY_STATUS_DISCHARGING;
1121 int fsm_state = pm_chg_get_fsm_state(chip);
1122 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001123
David Keitel88e1b572012-01-11 11:57:14 -08001124 if (chip->ext_psy) {
David Keiteld4e59ef2011-11-09 17:38:31 -08001125 if (chip->ext_charge_done)
1126 return POWER_SUPPLY_STATUS_FULL;
1127 if (chip->ext_charging)
1128 return POWER_SUPPLY_STATUS_CHARGING;
1129 }
1130
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -07001131 for (i = 0; i < ARRAY_SIZE(map); i++)
1132 if (map[i].fsm_state == fsm_state)
1133 batt_state = map[i].batt_state;
Amir Samuelovd31ef502011-10-26 14:41:36 +02001134
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -07001135 if (fsm_state == FSM_STATE_ON_CHG_HIGHI_1) {
1136 if (!pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ)
1137 || !pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ)
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08001138 || pm_chg_get_rt_status(chip, CHGHOT_IRQ)
1139 || pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ))
Amir Samuelovd31ef502011-10-26 14:41:36 +02001140
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -07001141 batt_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
Amir Samuelovd31ef502011-10-26 14:41:36 +02001142 }
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -07001143 return batt_state;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001144}
1145
Abhijeet Dharmapurikar728bc4d2012-01-03 11:08:33 -08001146#define MAX_TOLERABLE_BATT_TEMP_DDC 680
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001147static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
1148{
1149 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001150 struct pm8xxx_adc_chan_result result;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001151
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001152 rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001153 if (rc) {
1154 pr_err("error reading adc channel = %d, rc = %d\n",
1155 chip->vbat_channel, rc);
1156 return rc;
1157 }
1158 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1159 result.measurement);
Abhijeet Dharmapurikar728bc4d2012-01-03 11:08:33 -08001160 if (result.physical > MAX_TOLERABLE_BATT_TEMP_DDC)
1161 pr_err("BATT_TEMP= %d > 68degC, device will be shutdown\n",
1162 (int) result.physical);
1163
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001164 return (int)result.physical;
1165}
1166
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001167static int pm_batt_power_get_property(struct power_supply *psy,
1168 enum power_supply_property psp,
1169 union power_supply_propval *val)
1170{
1171 struct pm8921_chg_chip *chip = container_of(psy, struct pm8921_chg_chip,
1172 batt_psy);
1173
1174 switch (psp) {
1175 case POWER_SUPPLY_PROP_STATUS:
1176 val->intval = get_prop_batt_status(chip);
1177 break;
1178 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1179 val->intval = get_prop_charge_type(chip);
1180 break;
1181 case POWER_SUPPLY_PROP_HEALTH:
1182 val->intval = get_prop_batt_health(chip);
1183 break;
1184 case POWER_SUPPLY_PROP_PRESENT:
1185 val->intval = get_prop_batt_present(chip);
1186 break;
1187 case POWER_SUPPLY_PROP_TECHNOLOGY:
1188 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1189 break;
1190 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001191 val->intval = chip->max_voltage_mv * 1000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001192 break;
1193 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001194 val->intval = chip->min_voltage_mv * 1000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001195 break;
1196 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001197 val->intval = get_prop_battery_uvolts(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001198 break;
1199 case POWER_SUPPLY_PROP_CAPACITY:
1200 val->intval = get_prop_batt_capacity(chip);
1201 break;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001202 case POWER_SUPPLY_PROP_CURRENT_NOW:
1203 val->intval = get_prop_batt_current(chip);
1204 break;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001205 case POWER_SUPPLY_PROP_TEMP:
1206 val->intval = get_prop_batt_temp(chip);
1207 break;
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001208 case POWER_SUPPLY_PROP_ENERGY_FULL:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001209 val->intval = get_prop_batt_fcc(chip) * 1000;
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001210 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001211 default:
1212 return -EINVAL;
1213 }
1214
1215 return 0;
1216}
1217
1218static void (*notify_vbus_state_func_ptr)(int);
1219static int usb_chg_current;
1220static DEFINE_SPINLOCK(vbus_lock);
1221
1222int pm8921_charger_register_vbus_sn(void (*callback)(int))
1223{
1224 pr_debug("%p\n", callback);
1225 notify_vbus_state_func_ptr = callback;
1226 return 0;
1227}
1228EXPORT_SYMBOL_GPL(pm8921_charger_register_vbus_sn);
1229
1230/* this is passed to the hsusb via platform_data msm_otg_pdata */
1231void pm8921_charger_unregister_vbus_sn(void (*callback)(int))
1232{
1233 pr_debug("%p\n", callback);
1234 notify_vbus_state_func_ptr = NULL;
1235}
1236EXPORT_SYMBOL_GPL(pm8921_charger_unregister_vbus_sn);
1237
1238static void notify_usb_of_the_plugin_event(int plugin)
1239{
1240 plugin = !!plugin;
1241 if (notify_vbus_state_func_ptr) {
1242 pr_debug("notifying plugin\n");
1243 (*notify_vbus_state_func_ptr) (plugin);
1244 } else {
1245 pr_debug("unable to notify plugin\n");
1246 }
1247}
1248
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001249/* assumes vbus_lock is held */
1250static void __pm8921_charger_vbus_draw(unsigned int mA)
1251{
1252 int i, rc;
1253
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001254 if (usb_max_current && mA > usb_max_current) {
1255 pr_warn("restricting usb current to %d instead of %d\n",
1256 usb_max_current, mA);
1257 mA = usb_max_current;
1258 }
1259
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260 if (mA > 0 && mA <= 2) {
1261 usb_chg_current = 0;
1262 rc = pm_chg_iusbmax_set(the_chip,
1263 usb_ma_table[0].chg_iusb_value);
1264 if (rc) {
1265 pr_err("unable to set iusb to %d rc = %d\n",
1266 usb_ma_table[0].chg_iusb_value, rc);
1267 }
1268 rc = pm_chg_usb_suspend_enable(the_chip, 1);
1269 if (rc)
1270 pr_err("fail to set suspend bit rc=%d\n", rc);
1271 } else {
1272 rc = pm_chg_usb_suspend_enable(the_chip, 0);
1273 if (rc)
1274 pr_err("fail to reset suspend bit rc=%d\n", rc);
1275 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
1276 if (usb_ma_table[i].usb_ma <= mA)
1277 break;
1278 }
1279 if (i < 0)
1280 i = 0;
1281 rc = pm_chg_iusbmax_set(the_chip,
1282 usb_ma_table[i].chg_iusb_value);
1283 if (rc) {
1284 pr_err("unable to set iusb to %d rc = %d\n",
1285 usb_ma_table[i].chg_iusb_value, rc);
1286 }
1287 }
1288}
1289
1290/* USB calls these to tell us how much max usb current the system can draw */
1291void pm8921_charger_vbus_draw(unsigned int mA)
1292{
1293 unsigned long flags;
1294
1295 pr_debug("Enter charge=%d\n", mA);
1296 spin_lock_irqsave(&vbus_lock, flags);
1297 if (the_chip) {
1298 __pm8921_charger_vbus_draw(mA);
1299 } else {
1300 /*
1301 * called before pmic initialized,
1302 * save this value and use it at probe
1303 */
1304 usb_chg_current = mA;
1305 }
1306 spin_unlock_irqrestore(&vbus_lock, flags);
1307}
1308EXPORT_SYMBOL_GPL(pm8921_charger_vbus_draw);
1309
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07001310int pm8921_charger_enable(bool enable)
1311{
1312 int rc;
1313
1314 if (!the_chip) {
1315 pr_err("called before init\n");
1316 return -EINVAL;
1317 }
1318 enable = !!enable;
1319 rc = pm_chg_auto_enable(the_chip, enable);
1320 if (rc)
1321 pr_err("Failed rc=%d\n", rc);
1322 return rc;
1323}
1324EXPORT_SYMBOL(pm8921_charger_enable);
1325
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001326int pm8921_is_usb_chg_plugged_in(void)
1327{
1328 if (!the_chip) {
1329 pr_err("called before init\n");
1330 return -EINVAL;
1331 }
1332 return is_usb_chg_plugged_in(the_chip);
1333}
1334EXPORT_SYMBOL(pm8921_is_usb_chg_plugged_in);
1335
1336int pm8921_is_dc_chg_plugged_in(void)
1337{
1338 if (!the_chip) {
1339 pr_err("called before init\n");
1340 return -EINVAL;
1341 }
1342 return is_dc_chg_plugged_in(the_chip);
1343}
1344EXPORT_SYMBOL(pm8921_is_dc_chg_plugged_in);
1345
1346int pm8921_is_battery_present(void)
1347{
1348 if (!the_chip) {
1349 pr_err("called before init\n");
1350 return -EINVAL;
1351 }
1352 return get_prop_batt_present(the_chip);
1353}
1354EXPORT_SYMBOL(pm8921_is_battery_present);
1355
David Keitel012deef2011-12-02 11:49:33 -08001356/*
1357 * Disabling the charge current limit causes current
1358 * current limits to have no monitoring. An adequate charger
1359 * capable of supplying high current while sustaining VIN_MIN
1360 * is required if the limiting is disabled.
1361 */
1362int pm8921_disable_input_current_limit(bool disable)
1363{
1364 if (!the_chip) {
1365 pr_err("called before init\n");
1366 return -EINVAL;
1367 }
1368 if (disable) {
1369 pr_warn("Disabling input current limit!\n");
1370
1371 return pm8xxx_writeb(the_chip->dev->parent,
1372 CHG_BUCK_CTRL_TEST3, 0xF2);
1373 }
1374 return 0;
1375}
1376EXPORT_SYMBOL(pm8921_disable_input_current_limit);
1377
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001378int pm8921_set_max_battery_charge_current(int ma)
1379{
1380 if (!the_chip) {
1381 pr_err("called before init\n");
1382 return -EINVAL;
1383 }
1384 return pm_chg_ibatmax_set(the_chip, ma);
1385}
1386EXPORT_SYMBOL(pm8921_set_max_battery_charge_current);
1387
1388int pm8921_disable_source_current(bool disable)
1389{
1390 if (!the_chip) {
1391 pr_err("called before init\n");
1392 return -EINVAL;
1393 }
1394 if (disable)
1395 pr_warn("current drawn from chg=0, battery provides current\n");
1396 return pm_chg_charge_dis(the_chip, disable);
1397}
1398EXPORT_SYMBOL(pm8921_disable_source_current);
1399
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07001400int pm8921_regulate_input_voltage(int voltage)
1401{
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001402 int rc;
1403
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07001404 if (!the_chip) {
1405 pr_err("called before init\n");
1406 return -EINVAL;
1407 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001408 rc = pm_chg_vinmin_set(the_chip, voltage);
1409
1410 if (rc == 0)
1411 the_chip->vin_min = voltage;
1412
1413 return rc;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07001414}
1415
Abhijeet Dharmapurikar28669302011-12-21 08:31:28 -08001416#define USB_OV_THRESHOLD_MASK 0x60
1417#define USB_OV_THRESHOLD_SHIFT 5
1418int pm8921_usb_ovp_set_threshold(enum pm8921_usb_ov_threshold ov)
1419{
1420 u8 temp;
1421
1422 if (!the_chip) {
1423 pr_err("called before init\n");
1424 return -EINVAL;
1425 }
1426
1427 if (ov > PM_USB_OV_7V) {
1428 pr_err("limiting to over voltage threshold to 7volts\n");
1429 ov = PM_USB_OV_7V;
1430 }
1431
1432 temp = USB_OV_THRESHOLD_MASK & (ov << USB_OV_THRESHOLD_SHIFT);
1433
1434 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
1435 USB_OV_THRESHOLD_MASK, temp);
1436}
1437EXPORT_SYMBOL(pm8921_usb_ovp_set_threshold);
1438
1439#define USB_DEBOUNCE_TIME_MASK 0x06
1440#define USB_DEBOUNCE_TIME_SHIFT 1
1441int pm8921_usb_ovp_set_hystersis(enum pm8921_usb_debounce_time ms)
1442{
1443 u8 temp;
1444
1445 if (!the_chip) {
1446 pr_err("called before init\n");
1447 return -EINVAL;
1448 }
1449
1450 if (ms > PM_USB_DEBOUNCE_80P5MS) {
1451 pr_err("limiting debounce to 80.5ms\n");
1452 ms = PM_USB_DEBOUNCE_80P5MS;
1453 }
1454
1455 temp = USB_DEBOUNCE_TIME_MASK & (ms << USB_DEBOUNCE_TIME_SHIFT);
1456
1457 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
1458 USB_DEBOUNCE_TIME_MASK, temp);
1459}
1460EXPORT_SYMBOL(pm8921_usb_ovp_set_hystersis);
1461
1462#define USB_OVP_DISABLE_MASK 0x80
1463int pm8921_usb_ovp_disable(int disable)
1464{
1465 u8 temp = 0;
1466
1467 if (!the_chip) {
1468 pr_err("called before init\n");
1469 return -EINVAL;
1470 }
1471
1472 if (disable)
1473 temp = USB_OVP_DISABLE_MASK;
1474
1475 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
1476 USB_OVP_DISABLE_MASK, temp);
1477}
1478
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001479bool pm8921_is_battery_charging(int *source)
1480{
1481 int fsm_state, is_charging, dc_present, usb_present;
1482
1483 if (!the_chip) {
1484 pr_err("called before init\n");
1485 return -EINVAL;
1486 }
1487 fsm_state = pm_chg_get_fsm_state(the_chip);
1488 is_charging = is_battery_charging(fsm_state);
1489 if (is_charging == 0) {
1490 *source = PM8921_CHG_SRC_NONE;
1491 return is_charging;
1492 }
1493
1494 if (source == NULL)
1495 return is_charging;
1496
1497 /* the battery is charging, the source is requested, find it */
1498 dc_present = is_dc_chg_plugged_in(the_chip);
1499 usb_present = is_usb_chg_plugged_in(the_chip);
1500
1501 if (dc_present && !usb_present)
1502 *source = PM8921_CHG_SRC_DC;
1503
1504 if (usb_present && !dc_present)
1505 *source = PM8921_CHG_SRC_USB;
1506
1507 if (usb_present && dc_present)
1508 /*
1509 * The system always chooses dc for charging since it has
1510 * higher priority.
1511 */
1512 *source = PM8921_CHG_SRC_DC;
1513
1514 return is_charging;
1515}
1516EXPORT_SYMBOL(pm8921_is_battery_charging);
1517
David Keitel6df9cea2011-12-21 12:36:45 -08001518int pm8921_set_usb_power_supply_type(enum power_supply_type type)
1519{
1520 if (!the_chip) {
1521 pr_err("called before init\n");
1522 return -EINVAL;
1523 }
1524
1525 if (type < POWER_SUPPLY_TYPE_USB)
1526 return -EINVAL;
1527
1528 the_chip->usb_psy.type = type;
1529 power_supply_changed(&the_chip->usb_psy);
1530 return 0;
1531}
1532EXPORT_SYMBOL_GPL(pm8921_set_usb_power_supply_type);
1533
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001534int pm8921_batt_temperature(void)
1535{
1536 if (!the_chip) {
1537 pr_err("called before init\n");
1538 return -EINVAL;
1539 }
1540 return get_prop_batt_temp(the_chip);
1541}
1542
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001543static void handle_usb_insertion_removal(struct pm8921_chg_chip *chip)
1544{
1545 int usb_present;
1546
1547 usb_present = is_usb_chg_plugged_in(chip);
1548 if (chip->usb_present ^ usb_present) {
1549 notify_usb_of_the_plugin_event(usb_present);
1550 chip->usb_present = usb_present;
1551 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikar0c4bc152011-10-27 10:22:24 -07001552 power_supply_changed(&chip->batt_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001553 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001554 if (usb_present) {
1555 schedule_delayed_work(&chip->unplug_check_work,
1556 round_jiffies_relative(msecs_to_jiffies
1557 (UNPLUG_CHECK_WAIT_PERIOD_MS)));
1558 }
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001559 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001560}
1561
Amir Samuelovd31ef502011-10-26 14:41:36 +02001562static void handle_stop_ext_chg(struct pm8921_chg_chip *chip)
1563{
David Keitel88e1b572012-01-11 11:57:14 -08001564 if (!chip->ext_psy) {
Amir Samuelovd31ef502011-10-26 14:41:36 +02001565 pr_debug("external charger not registered.\n");
1566 return;
1567 }
1568
1569 if (!chip->ext_charging) {
1570 pr_debug("already not charging.\n");
1571 return;
1572 }
1573
David Keitel88e1b572012-01-11 11:57:14 -08001574 power_supply_set_charge_type(chip->ext_psy,
1575 POWER_SUPPLY_CHARGE_TYPE_NONE);
1576 pm8921_disable_source_current(false); /* release BATFET */
Amir Samuelovd31ef502011-10-26 14:41:36 +02001577 chip->ext_charging = false;
David Keiteld4e59ef2011-11-09 17:38:31 -08001578 chip->ext_charge_done = false;
David Keitel88e1b572012-01-11 11:57:14 -08001579 bms_notify_check(chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001580}
1581
1582static void handle_start_ext_chg(struct pm8921_chg_chip *chip)
1583{
1584 int dc_present;
1585 int batt_present;
1586 int batt_temp_ok;
1587 int vbat_ov;
Amir Samuelovd31ef502011-10-26 14:41:36 +02001588 unsigned long delay =
1589 round_jiffies_relative(msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
1590
David Keitel88e1b572012-01-11 11:57:14 -08001591 if (!chip->ext_psy) {
Amir Samuelovd31ef502011-10-26 14:41:36 +02001592 pr_debug("external charger not registered.\n");
1593 return;
1594 }
1595
1596 if (chip->ext_charging) {
1597 pr_debug("already charging.\n");
1598 return;
1599 }
1600
David Keitel88e1b572012-01-11 11:57:14 -08001601 dc_present = is_dc_chg_plugged_in(the_chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001602 batt_present = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1603 batt_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001604
1605 if (!dc_present) {
1606 pr_warn("%s. dc not present.\n", __func__);
1607 return;
1608 }
1609 if (!batt_present) {
1610 pr_warn("%s. battery not present.\n", __func__);
1611 return;
1612 }
1613 if (!batt_temp_ok) {
1614 pr_warn("%s. battery temperature not ok.\n", __func__);
1615 return;
1616 }
David Keitel88e1b572012-01-11 11:57:14 -08001617 pm8921_disable_source_current(true); /* Force BATFET=ON */
1618 vbat_ov = pm_chg_get_rt_status(chip, VBAT_OV_IRQ);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001619 if (vbat_ov) {
1620 pr_warn("%s. battery over voltage.\n", __func__);
1621 return;
1622 }
Amir Samuelovd31ef502011-10-26 14:41:36 +02001623
David Keitel88e1b572012-01-11 11:57:14 -08001624 power_supply_set_charge_type(chip->ext_psy,
1625 POWER_SUPPLY_CHARGE_TYPE_FAST);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001626 chip->ext_charging = true;
1627 chip->ext_charge_done = false;
David Keitel88e1b572012-01-11 11:57:14 -08001628 bms_notify_check(chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001629 /* Start BMS */
1630 schedule_delayed_work(&chip->eoc_work, delay);
1631 wake_lock(&chip->eoc_wake_lock);
1632}
1633
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001634#define WRITE_BANK_4 0xC0
1635static void unplug_wrkarnd_restore_worker(struct work_struct *work)
1636{
1637 u8 temp;
1638 int rc;
1639 struct delayed_work *dwork = to_delayed_work(work);
1640 struct pm8921_chg_chip *chip = container_of(dwork,
1641 struct pm8921_chg_chip,
1642 unplug_wrkarnd_restore_work);
1643
1644 pr_debug("restoring vin_min to %d mV\n", chip->vin_min);
1645 rc = pm_chg_vinmin_set(the_chip, chip->vin_min);
1646
1647 temp = WRITE_BANK_4 | 0xA;
1648 rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
1649 if (rc) {
1650 pr_err("Error %d writing %d to addr %d\n", rc,
1651 temp, CHG_BUCK_CTRL_TEST3);
1652 }
1653 wake_unlock(&chip->unplug_wrkarnd_restore_wake_lock);
1654}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001655static irqreturn_t usbin_valid_irq_handler(int irq, void *data)
1656{
1657 handle_usb_insertion_removal(data);
1658 return IRQ_HANDLED;
1659}
1660
1661static irqreturn_t usbin_ov_irq_handler(int irq, void *data)
1662{
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -07001663 pr_err("USB OverVoltage\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001664 return IRQ_HANDLED;
1665}
1666
1667static irqreturn_t batt_inserted_irq_handler(int irq, void *data)
1668{
1669 struct pm8921_chg_chip *chip = data;
1670 int status;
1671
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001672 status = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1673 schedule_work(&chip->battery_id_valid_work);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001674 handle_start_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001675 pr_debug("battery present=%d", status);
1676 power_supply_changed(&chip->batt_psy);
1677 return IRQ_HANDLED;
1678}
Amir Samuelovd31ef502011-10-26 14:41:36 +02001679
1680/*
1681 * this interrupt used to restart charging a battery.
1682 *
1683 * Note: When DC-inserted the VBAT can't go low.
1684 * VPH_PWR is provided by the ext-charger.
1685 * After End-Of-Charging from DC, charging can be resumed only
1686 * if DC is removed and then inserted after the battery was in use.
1687 * Therefore the handle_start_ext_chg() is not called.
1688 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001689static irqreturn_t vbatdet_low_irq_handler(int irq, void *data)
1690{
1691 struct pm8921_chg_chip *chip = data;
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07001692 int high_transition;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001693
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07001694 high_transition = pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07001695
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07001696 if (high_transition) {
1697 /* enable auto charging */
1698 pm_chg_auto_enable(chip, !charging_disabled);
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08001699 pr_info("batt fell below resume voltage %s\n",
1700 charging_disabled ? "" : "charger enabled");
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07001701 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001702 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001703
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001704 power_supply_changed(&chip->batt_psy);
1705 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001706
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001707 return IRQ_HANDLED;
1708}
1709
1710static irqreturn_t usbin_uv_irq_handler(int irq, void *data)
1711{
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -07001712 pr_err("USB UnderVoltage\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001713 return IRQ_HANDLED;
1714}
1715
1716static irqreturn_t vbat_ov_irq_handler(int irq, void *data)
1717{
1718 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1719 return IRQ_HANDLED;
1720}
1721
1722static irqreturn_t chgwdog_irq_handler(int irq, void *data)
1723{
1724 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1725 return IRQ_HANDLED;
1726}
1727
1728static irqreturn_t vcp_irq_handler(int irq, void *data)
1729{
1730 pr_warning("VCP triggered BATDET forced on\n");
1731 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1732 return IRQ_HANDLED;
1733}
1734
1735static irqreturn_t atcdone_irq_handler(int irq, void *data)
1736{
1737 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1738 return IRQ_HANDLED;
1739}
1740
1741static irqreturn_t atcfail_irq_handler(int irq, void *data)
1742{
1743 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1744 return IRQ_HANDLED;
1745}
1746
1747static irqreturn_t chgdone_irq_handler(int irq, void *data)
1748{
1749 struct pm8921_chg_chip *chip = data;
1750
1751 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02001752
1753 handle_stop_ext_chg(chip);
1754
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001755 power_supply_changed(&chip->batt_psy);
1756 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001757
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07001758 bms_notify_check(chip);
1759
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001760 return IRQ_HANDLED;
1761}
1762
1763static irqreturn_t chgfail_irq_handler(int irq, void *data)
1764{
1765 struct pm8921_chg_chip *chip = data;
David Keitel753ec8d2011-11-02 10:56:37 -07001766 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001767
David Keitel753ec8d2011-11-02 10:56:37 -07001768 ret = pm_chg_failed_clear(chip, 1);
1769 if (ret)
1770 pr_err("Failed to write CHG_FAILED_CLEAR bit\n");
1771
1772 pr_err("batt_present = %d, batt_temp_ok = %d, state_changed_to=%d\n",
1773 get_prop_batt_present(chip),
1774 pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ),
1775 pm_chg_get_fsm_state(data));
1776
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001777 power_supply_changed(&chip->batt_psy);
1778 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001779 return IRQ_HANDLED;
1780}
1781
1782static irqreturn_t chgstate_irq_handler(int irq, void *data)
1783{
1784 struct pm8921_chg_chip *chip = data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785
1786 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
1787 power_supply_changed(&chip->batt_psy);
1788 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001789
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001790 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001791
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001792 return IRQ_HANDLED;
1793}
1794
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001795#define VIN_ACTIVE_BIT BIT(0)
1796#define UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US 200
1797#define VIN_MIN_INCREASE_MV 100
1798static void unplug_check_worker(struct work_struct *work)
1799{
1800 struct delayed_work *dwork = to_delayed_work(work);
1801 struct pm8921_chg_chip *chip = container_of(dwork,
1802 struct pm8921_chg_chip, unplug_check_work);
1803 u8 reg_loop;
1804 int ibat, usb_chg_plugged_in;
1805
1806 usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
1807 if (!usb_chg_plugged_in) {
1808 pr_debug("Stopping Unplug Check Worker since USB is removed"
1809 "reg_loop = %d, fsm = %d ibat = %d\n",
1810 pm_chg_get_regulation_loop(chip),
1811 pm_chg_get_fsm_state(chip),
1812 get_prop_batt_current(chip)
1813 );
1814 return;
1815 }
1816 reg_loop = pm_chg_get_regulation_loop(chip);
1817 pr_debug("reg_loop=0x%x\n", reg_loop);
1818
1819 if (reg_loop & VIN_ACTIVE_BIT) {
1820 ibat = get_prop_batt_current(chip);
1821
1822 pr_debug("ibat = %d fsm = %d reg_loop = 0x%x\n",
1823 ibat, pm_chg_get_fsm_state(chip), reg_loop);
1824 if (ibat > 0) {
1825 int err;
1826 u8 temp;
1827
1828 temp = WRITE_BANK_4 | 0xE;
1829 err = pm8xxx_writeb(chip->dev->parent,
1830 CHG_BUCK_CTRL_TEST3, temp);
1831 if (err) {
1832 pr_err("Error %d writing %d to addr %d\n", err,
1833 temp, CHG_BUCK_CTRL_TEST3);
1834 }
1835
1836 pm_chg_vinmin_set(chip,
1837 chip->vin_min + VIN_MIN_INCREASE_MV);
1838
1839 wake_lock(&chip->unplug_wrkarnd_restore_wake_lock);
1840 schedule_delayed_work(
1841 &chip->unplug_wrkarnd_restore_work,
1842 round_jiffies_relative(usecs_to_jiffies
1843 (UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US)));
1844 }
1845 }
1846
1847 schedule_delayed_work(&chip->unplug_check_work,
1848 round_jiffies_relative(msecs_to_jiffies
1849 (UNPLUG_CHECK_WAIT_PERIOD_MS)));
1850}
1851
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001852static irqreturn_t loop_change_irq_handler(int irq, void *data)
1853{
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001854 struct pm8921_chg_chip *chip = data;
1855
1856 pr_debug("fsm_state=%d reg_loop=0x%x\n",
1857 pm_chg_get_fsm_state(data),
1858 pm_chg_get_regulation_loop(data));
1859 unplug_check_worker(&(chip->unplug_check_work.work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001860 return IRQ_HANDLED;
1861}
1862
1863static irqreturn_t fastchg_irq_handler(int irq, void *data)
1864{
1865 struct pm8921_chg_chip *chip = data;
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07001866 int high_transition;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001867
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07001868 high_transition = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
1869 if (high_transition && !delayed_work_pending(&chip->eoc_work)) {
1870 wake_lock(&chip->eoc_wake_lock);
1871 schedule_delayed_work(&chip->eoc_work,
1872 round_jiffies_relative(msecs_to_jiffies
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07001873 (EOC_CHECK_PERIOD_MS)));
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07001874 }
1875 power_supply_changed(&chip->batt_psy);
1876 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001877 return IRQ_HANDLED;
1878}
1879
1880static irqreturn_t trklchg_irq_handler(int irq, void *data)
1881{
1882 struct pm8921_chg_chip *chip = data;
1883
1884 power_supply_changed(&chip->batt_psy);
1885 return IRQ_HANDLED;
1886}
1887
1888static irqreturn_t batt_removed_irq_handler(int irq, void *data)
1889{
1890 struct pm8921_chg_chip *chip = data;
1891 int status;
1892
1893 status = pm_chg_get_rt_status(chip, BATT_REMOVED_IRQ);
1894 pr_debug("battery present=%d state=%d", !status,
1895 pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02001896 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001897 power_supply_changed(&chip->batt_psy);
1898 return IRQ_HANDLED;
1899}
1900
1901static irqreturn_t batttemp_hot_irq_handler(int irq, void *data)
1902{
1903 struct pm8921_chg_chip *chip = data;
1904
Amir Samuelovd31ef502011-10-26 14:41:36 +02001905 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001906 power_supply_changed(&chip->batt_psy);
1907 return IRQ_HANDLED;
1908}
1909
1910static irqreturn_t chghot_irq_handler(int irq, void *data)
1911{
1912 struct pm8921_chg_chip *chip = data;
1913
1914 pr_debug("Chg hot fsm_state=%d\n", pm_chg_get_fsm_state(data));
1915 power_supply_changed(&chip->batt_psy);
1916 power_supply_changed(&chip->usb_psy);
David Keitel88e1b572012-01-11 11:57:14 -08001917 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001918 return IRQ_HANDLED;
1919}
1920
1921static irqreturn_t batttemp_cold_irq_handler(int irq, void *data)
1922{
1923 struct pm8921_chg_chip *chip = data;
1924
1925 pr_debug("Batt cold fsm_state=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02001926 handle_stop_ext_chg(chip);
1927
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001928 power_supply_changed(&chip->batt_psy);
1929 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001930 return IRQ_HANDLED;
1931}
1932
1933static irqreturn_t chg_gone_irq_handler(int irq, void *data)
1934{
1935 struct pm8921_chg_chip *chip = data;
1936
1937 pr_debug("Chg gone fsm_state=%d\n", pm_chg_get_fsm_state(data));
1938 power_supply_changed(&chip->batt_psy);
1939 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001940 return IRQ_HANDLED;
1941}
David Keitel52fda532011-11-10 10:43:44 -08001942/*
1943 *
1944 * bat_temp_ok_irq_handler - is edge triggered, hence it will
1945 * fire for two cases:
1946 *
1947 * If the interrupt line switches to high temperature is okay
1948 * and thus charging begins.
1949 * If bat_temp_ok is low this means the temperature is now
1950 * too hot or cold, so charging is stopped.
1951 *
1952 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001953static irqreturn_t bat_temp_ok_irq_handler(int irq, void *data)
1954{
David Keitel52fda532011-11-10 10:43:44 -08001955 int bat_temp_ok;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001956 struct pm8921_chg_chip *chip = data;
1957
David Keitel52fda532011-11-10 10:43:44 -08001958 bat_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
1959
1960 pr_debug("batt_temp_ok = %d fsm_state%d\n",
1961 bat_temp_ok, pm_chg_get_fsm_state(data));
1962
1963 if (bat_temp_ok)
1964 handle_start_ext_chg(chip);
1965 else
1966 handle_stop_ext_chg(chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02001967
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001968 power_supply_changed(&chip->batt_psy);
1969 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001970 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001971 return IRQ_HANDLED;
1972}
1973
1974static irqreturn_t coarse_det_low_irq_handler(int irq, void *data)
1975{
1976 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1977 return IRQ_HANDLED;
1978}
1979
1980static irqreturn_t vdd_loop_irq_handler(int irq, void *data)
1981{
1982 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1983 return IRQ_HANDLED;
1984}
1985
1986static irqreturn_t vreg_ov_irq_handler(int irq, void *data)
1987{
1988 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1989 return IRQ_HANDLED;
1990}
1991
1992static irqreturn_t vbatdet_irq_handler(int irq, void *data)
1993{
1994 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
1995 return IRQ_HANDLED;
1996}
1997
1998static irqreturn_t batfet_irq_handler(int irq, void *data)
1999{
2000 struct pm8921_chg_chip *chip = data;
2001
2002 pr_debug("vreg ov\n");
2003 power_supply_changed(&chip->batt_psy);
2004 return IRQ_HANDLED;
2005}
2006
2007static irqreturn_t dcin_valid_irq_handler(int irq, void *data)
2008{
Amir Samuelovd31ef502011-10-26 14:41:36 +02002009 struct pm8921_chg_chip *chip = data;
David Keitel88e1b572012-01-11 11:57:14 -08002010 int dc_present;
Amir Samuelovd31ef502011-10-26 14:41:36 +02002011
David Keitel88e1b572012-01-11 11:57:14 -08002012 dc_present = pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
2013 if (chip->ext_psy)
2014 power_supply_set_online(chip->ext_psy, dc_present);
2015 chip->dc_present = dc_present;
2016 if (dc_present)
2017 handle_start_ext_chg(chip);
2018 else
2019 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002020 return IRQ_HANDLED;
2021}
2022
2023static irqreturn_t dcin_ov_irq_handler(int irq, void *data)
2024{
Amir Samuelovd31ef502011-10-26 14:41:36 +02002025 struct pm8921_chg_chip *chip = data;
2026
Amir Samuelovd31ef502011-10-26 14:41:36 +02002027 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002028 return IRQ_HANDLED;
2029}
2030
2031static irqreturn_t dcin_uv_irq_handler(int irq, void *data)
2032{
Amir Samuelovd31ef502011-10-26 14:41:36 +02002033 struct pm8921_chg_chip *chip = data;
2034
Amir Samuelovd31ef502011-10-26 14:41:36 +02002035 handle_stop_ext_chg(chip);
2036
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002037 return IRQ_HANDLED;
2038}
2039
David Keitel88e1b572012-01-11 11:57:14 -08002040static int __pm_batt_external_power_changed_work(struct device *dev, void *data)
2041{
2042 struct power_supply *psy = &the_chip->batt_psy;
2043 struct power_supply *epsy = dev_get_drvdata(dev);
2044 int i, dcin_irq;
2045
2046 /* Only search for external supply if none is registered */
2047 if (!the_chip->ext_psy) {
2048 dcin_irq = the_chip->pmic_chg_irq[DCIN_VALID_IRQ];
2049 for (i = 0; i < epsy->num_supplicants; i++) {
2050 if (!strncmp(epsy->supplied_to[i], psy->name, 7)) {
2051 if (!strncmp(epsy->name, "dc", 2)) {
2052 the_chip->ext_psy = epsy;
2053 dcin_valid_irq_handler(dcin_irq,
2054 the_chip);
2055 }
2056 }
2057 }
2058 }
2059 return 0;
2060}
2061
2062static void pm_batt_external_power_changed(struct power_supply *psy)
2063{
2064 /* Only look for an external supply if it hasn't been registered */
2065 if (!the_chip->ext_psy)
2066 class_for_each_device(power_supply_class, NULL, psy,
2067 __pm_batt_external_power_changed_work);
2068}
2069
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07002070/**
2071 * update_heartbeat - internal function to update userspace
2072 * per update_time minutes
2073 *
2074 */
2075static void update_heartbeat(struct work_struct *work)
2076{
2077 struct delayed_work *dwork = to_delayed_work(work);
2078 struct pm8921_chg_chip *chip = container_of(dwork,
2079 struct pm8921_chg_chip, update_heartbeat_work);
2080
2081 power_supply_changed(&chip->batt_psy);
2082 schedule_delayed_work(&chip->update_heartbeat_work,
2083 round_jiffies_relative(msecs_to_jiffies
2084 (chip->update_time)));
2085}
2086
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08002087enum {
2088 CHG_IN_PROGRESS,
2089 CHG_NOT_IN_PROGRESS,
2090 CHG_FINISHED,
2091};
2092
2093#define VBAT_TOLERANCE_MV 70
2094#define CHG_DISABLE_MSLEEP 100
2095static int is_charging_finished(struct pm8921_chg_chip *chip)
2096{
2097 int vbat_meas_uv, vbat_meas_mv, vbat_programmed, vbatdet_low;
2098 int ichg_meas_ma, iterm_programmed;
2099 int regulation_loop, fast_chg, vcp;
2100 int rc;
2101 static int last_vbat_programmed = -EINVAL;
2102
2103 if (!is_ext_charging(chip)) {
2104 /* return if the battery is not being fastcharged */
2105 fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
2106 pr_debug("fast_chg = %d\n", fast_chg);
2107 if (fast_chg == 0)
2108 return CHG_NOT_IN_PROGRESS;
2109
2110 vcp = pm_chg_get_rt_status(chip, VCP_IRQ);
2111 pr_debug("vcp = %d\n", vcp);
2112 if (vcp == 1)
2113 return CHG_IN_PROGRESS;
2114
2115 vbatdet_low = pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ);
2116 pr_debug("vbatdet_low = %d\n", vbatdet_low);
2117 if (vbatdet_low == 1)
2118 return CHG_IN_PROGRESS;
2119
2120 /* reset count if battery is hot/cold */
2121 rc = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
2122 pr_debug("batt_temp_ok = %d\n", rc);
2123 if (rc == 0)
2124 return CHG_IN_PROGRESS;
2125
2126 /* reset count if battery voltage is less than vddmax */
2127 vbat_meas_uv = get_prop_battery_uvolts(chip);
2128 if (vbat_meas_uv < 0)
2129 return CHG_IN_PROGRESS;
2130 vbat_meas_mv = vbat_meas_uv / 1000;
2131
2132 rc = pm_chg_vddmax_get(chip, &vbat_programmed);
2133 if (rc) {
2134 pr_err("couldnt read vddmax rc = %d\n", rc);
2135 return CHG_IN_PROGRESS;
2136 }
2137 pr_debug("vddmax = %d vbat_meas_mv=%d\n",
2138 vbat_programmed, vbat_meas_mv);
2139 if (vbat_meas_mv < vbat_programmed - VBAT_TOLERANCE_MV)
2140 return CHG_IN_PROGRESS;
2141
2142 if (last_vbat_programmed == -EINVAL)
2143 last_vbat_programmed = vbat_programmed;
2144 if (last_vbat_programmed != vbat_programmed) {
2145 /* vddmax changed, reset and check again */
2146 pr_debug("vddmax = %d last_vdd_max=%d\n",
2147 vbat_programmed, last_vbat_programmed);
2148 last_vbat_programmed = vbat_programmed;
2149 return CHG_IN_PROGRESS;
2150 }
2151
2152 /*
2153 * TODO if charging from an external charger
2154 * check SOC instead of regulation loop
2155 */
2156 regulation_loop = pm_chg_get_regulation_loop(chip);
2157 if (regulation_loop < 0) {
2158 pr_err("couldnt read the regulation loop err=%d\n",
2159 regulation_loop);
2160 return CHG_IN_PROGRESS;
2161 }
2162 pr_debug("regulation_loop=%d\n", regulation_loop);
2163
2164 if (regulation_loop != 0 && regulation_loop != VDD_LOOP)
2165 return CHG_IN_PROGRESS;
2166 } /* !is_ext_charging */
2167
2168 /* reset count if battery chg current is more than iterm */
2169 rc = pm_chg_iterm_get(chip, &iterm_programmed);
2170 if (rc) {
2171 pr_err("couldnt read iterm rc = %d\n", rc);
2172 return CHG_IN_PROGRESS;
2173 }
2174
2175 ichg_meas_ma = (get_prop_batt_current(chip)) / 1000;
2176 pr_debug("iterm_programmed = %d ichg_meas_ma=%d\n",
2177 iterm_programmed, ichg_meas_ma);
2178 /*
2179 * ichg_meas_ma < 0 means battery is drawing current
2180 * ichg_meas_ma > 0 means battery is providing current
2181 */
2182 if (ichg_meas_ma > 0)
2183 return CHG_IN_PROGRESS;
2184
2185 if (ichg_meas_ma * -1 > iterm_programmed)
2186 return CHG_IN_PROGRESS;
2187
2188 return CHG_FINISHED;
2189}
2190
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002191/**
Amir Samuelovd31ef502011-10-26 14:41:36 +02002192 * eoc_worker - internal function to check if battery EOC
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002193 * has happened
2194 *
2195 * If all conditions favouring, if the charge current is
2196 * less than the term current for three consecutive times
2197 * an EOC has happened.
2198 * The wakelock is released if there is no need to reshedule
2199 * - this happens when the battery is removed or EOC has
2200 * happened
2201 */
2202#define CONSECUTIVE_COUNT 3
Amir Samuelovd31ef502011-10-26 14:41:36 +02002203static void eoc_worker(struct work_struct *work)
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002204{
2205 struct delayed_work *dwork = to_delayed_work(work);
2206 struct pm8921_chg_chip *chip = container_of(dwork,
2207 struct pm8921_chg_chip, eoc_work);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002208 static int count;
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08002209 int end = is_charging_finished(chip);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002210
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08002211 if (end == CHG_NOT_IN_PROGRESS) {
Amir Samuelovd31ef502011-10-26 14:41:36 +02002212 /* enable fastchg irq */
Amir Samuelovd31ef502011-10-26 14:41:36 +02002213 count = 0;
2214 wake_unlock(&chip->eoc_wake_lock);
2215 return;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002216 }
2217
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08002218 if (end == CHG_FINISHED) {
2219 count++;
2220 } else {
2221 count = 0;
2222 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002223
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002224 if (count == CONSECUTIVE_COUNT) {
2225 count = 0;
2226 pr_info("End of Charging\n");
2227
2228 pm_chg_auto_enable(chip, 0);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002229
Amir Samuelovd31ef502011-10-26 14:41:36 +02002230 if (is_ext_charging(chip))
2231 chip->ext_charge_done = true;
2232
Abhijeet Dharmapurikareb882f52011-12-22 09:02:34 -08002233 if (chip->is_bat_warm || chip->is_bat_cool)
2234 chip->bms_notify.is_battery_full = 0;
2235 else
2236 chip->bms_notify.is_battery_full = 1;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002237 /* declare end of charging by invoking chgdone interrupt */
2238 chgdone_irq_handler(chip->pmic_chg_irq[CHGDONE_IRQ], chip);
2239 wake_unlock(&chip->eoc_wake_lock);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002240 } else {
2241 pr_debug("EOC count = %d\n", count);
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08002242 schedule_delayed_work(&chip->eoc_work,
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002243 round_jiffies_relative(msecs_to_jiffies
2244 (EOC_CHECK_PERIOD_MS)));
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08002245 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002246}
2247
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002248static void btm_configure_work(struct work_struct *work)
2249{
2250 int rc;
2251
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07002252 rc = pm8xxx_adc_btm_configure(&btm_config);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002253 if (rc)
2254 pr_err("failed to configure btm rc=%d", rc);
2255}
2256
2257DECLARE_WORK(btm_config_work, btm_configure_work);
2258
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002259static void set_appropriate_battery_current(struct pm8921_chg_chip *chip)
2260{
2261 unsigned int chg_current = chip->max_bat_chg_current;
2262
2263 if (chip->is_bat_cool)
2264 chg_current = min(chg_current, chip->cool_bat_chg_current);
2265
2266 if (chip->is_bat_warm)
2267 chg_current = min(chg_current, chip->warm_bat_chg_current);
2268
David Keitelfdef3a42011-12-14 19:02:54 -08002269 if (thermal_mitigation != 0 && chip->thermal_mitigation)
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002270 chg_current = min(chg_current,
2271 chip->thermal_mitigation[thermal_mitigation]);
2272
2273 pm_chg_ibatmax_set(the_chip, chg_current);
2274}
2275
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002276#define TEMP_HYSTERISIS_DEGC 2
2277static void battery_cool(bool enter)
2278{
2279 pr_debug("enter = %d\n", enter);
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002280 if (enter == the_chip->is_bat_cool)
2281 return;
2282 the_chip->is_bat_cool = enter;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002283 if (enter) {
2284 btm_config.low_thr_temp =
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002285 the_chip->cool_temp_dc + TEMP_HYSTERISIS_DEGC;
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002286 set_appropriate_battery_current(the_chip);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002287 pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07002288 pm_chg_vbatdet_set(the_chip,
2289 the_chip->cool_bat_voltage
2290 - the_chip->resume_voltage_delta);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002291 } else {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002292 btm_config.low_thr_temp = the_chip->cool_temp_dc;
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002293 set_appropriate_battery_current(the_chip);
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002294 pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07002295 pm_chg_vbatdet_set(the_chip,
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002296 the_chip->max_voltage_mv
2297 - the_chip->resume_voltage_delta);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002298 }
2299 schedule_work(&btm_config_work);
2300}
2301
2302static void battery_warm(bool enter)
2303{
2304 pr_debug("enter = %d\n", enter);
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002305 if (enter == the_chip->is_bat_warm)
2306 return;
2307 the_chip->is_bat_warm = enter;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002308 if (enter) {
2309 btm_config.high_thr_temp =
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002310 the_chip->warm_temp_dc - TEMP_HYSTERISIS_DEGC;
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002311 set_appropriate_battery_current(the_chip);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002312 pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07002313 pm_chg_vbatdet_set(the_chip,
2314 the_chip->warm_bat_voltage
2315 - the_chip->resume_voltage_delta);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002316 } else {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002317 btm_config.high_thr_temp = the_chip->warm_temp_dc;
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002318 set_appropriate_battery_current(the_chip);
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002319 pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07002320 pm_chg_vbatdet_set(the_chip,
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002321 the_chip->max_voltage_mv
2322 - the_chip->resume_voltage_delta);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002323 }
2324 schedule_work(&btm_config_work);
2325}
2326
2327static int configure_btm(struct pm8921_chg_chip *chip)
2328{
2329 int rc;
2330
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08002331 if (chip->warm_temp_dc != INT_MIN)
2332 btm_config.btm_warm_fn = battery_warm;
2333 else
2334 btm_config.btm_warm_fn = NULL;
2335
2336 if (chip->cool_temp_dc != INT_MIN)
2337 btm_config.btm_cool_fn = battery_cool;
2338 else
2339 btm_config.btm_cool_fn = NULL;
2340
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002341 btm_config.low_thr_temp = chip->cool_temp_dc;
2342 btm_config.high_thr_temp = chip->warm_temp_dc;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002343 btm_config.interval = chip->temp_check_period;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07002344 rc = pm8xxx_adc_btm_configure(&btm_config);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002345 if (rc)
2346 pr_err("failed to configure btm rc = %d\n", rc);
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07002347 rc = pm8xxx_adc_btm_start();
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002348 if (rc)
2349 pr_err("failed to start btm rc = %d\n", rc);
2350
2351 return rc;
2352}
2353
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07002354/**
2355 * set_disable_status_param -
2356 *
2357 * Internal function to disable battery charging and also disable drawing
2358 * any current from the source. The device is forced to run on a battery
2359 * after this.
2360 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002361static int set_disable_status_param(const char *val, struct kernel_param *kp)
2362{
2363 int ret;
2364 struct pm8921_chg_chip *chip = the_chip;
2365
2366 ret = param_set_int(val, kp);
2367 if (ret) {
2368 pr_err("error setting value %d\n", ret);
2369 return ret;
2370 }
2371 pr_info("factory set disable param to %d\n", charging_disabled);
2372 if (chip) {
2373 pm_chg_auto_enable(chip, !charging_disabled);
2374 pm_chg_charge_dis(chip, charging_disabled);
2375 }
2376 return 0;
2377}
2378module_param_call(disabled, set_disable_status_param, param_get_uint,
2379 &charging_disabled, 0644);
2380
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07002381/**
2382 * set_thermal_mitigation_level -
2383 *
2384 * Internal function to control battery charging current to reduce
2385 * temperature
2386 */
2387static int set_therm_mitigation_level(const char *val, struct kernel_param *kp)
2388{
2389 int ret;
2390 struct pm8921_chg_chip *chip = the_chip;
2391
2392 ret = param_set_int(val, kp);
2393 if (ret) {
2394 pr_err("error setting value %d\n", ret);
2395 return ret;
2396 }
2397
2398 if (!chip) {
2399 pr_err("called before init\n");
2400 return -EINVAL;
2401 }
2402
2403 if (!chip->thermal_mitigation) {
2404 pr_err("no thermal mitigation\n");
2405 return -EINVAL;
2406 }
2407
2408 if (thermal_mitigation < 0
2409 || thermal_mitigation >= chip->thermal_levels) {
2410 pr_err("out of bound level selected\n");
2411 return -EINVAL;
2412 }
2413
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08002414 set_appropriate_battery_current(chip);
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07002415 return ret;
2416}
2417module_param_call(thermal_mitigation, set_therm_mitigation_level,
2418 param_get_uint,
2419 &thermal_mitigation, 0644);
2420
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08002421static int set_usb_max_current(const char *val, struct kernel_param *kp)
2422{
2423 int ret, mA;
2424 struct pm8921_chg_chip *chip = the_chip;
2425
2426 ret = param_set_int(val, kp);
2427 if (ret) {
2428 pr_err("error setting value %d\n", ret);
2429 return ret;
2430 }
2431 if (chip) {
2432 pr_warn("setting current max to %d\n", usb_max_current);
2433 pm_chg_iusbmax_get(chip, &mA);
2434 if (mA > usb_max_current)
2435 pm8921_charger_vbus_draw(usb_max_current);
2436 return 0;
2437 }
2438 return -EINVAL;
2439}
2440module_param_call(usb_max_current, set_usb_max_current, param_get_uint,
2441 &usb_max_current, 0644);
2442
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002443static void free_irqs(struct pm8921_chg_chip *chip)
2444{
2445 int i;
2446
2447 for (i = 0; i < PM_CHG_MAX_INTS; i++)
2448 if (chip->pmic_chg_irq[i]) {
2449 free_irq(chip->pmic_chg_irq[i], chip);
2450 chip->pmic_chg_irq[i] = 0;
2451 }
2452}
2453
David Keitel88e1b572012-01-11 11:57:14 -08002454/* determines the initial present states */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002455static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
2456{
2457 unsigned long flags;
2458 int fsm_state;
2459
2460 chip->dc_present = !!is_dc_chg_plugged_in(chip);
2461 chip->usb_present = !!is_usb_chg_plugged_in(chip);
2462
2463 notify_usb_of_the_plugin_event(chip->usb_present);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002464 if (chip->usb_present) {
2465 schedule_delayed_work(&chip->unplug_check_work,
2466 round_jiffies_relative(msecs_to_jiffies
2467 (UNPLUG_CHECK_WAIT_PERIOD_MS)));
2468 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002469
2470 pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
2471 pm8921_chg_enable_irq(chip, USBIN_VALID_IRQ);
2472 pm8921_chg_enable_irq(chip, BATT_REMOVED_IRQ);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002473 pm8921_chg_enable_irq(chip, BATT_INSERTED_IRQ);
2474 pm8921_chg_enable_irq(chip, USBIN_OV_IRQ);
2475 pm8921_chg_enable_irq(chip, USBIN_UV_IRQ);
2476 pm8921_chg_enable_irq(chip, DCIN_OV_IRQ);
2477 pm8921_chg_enable_irq(chip, DCIN_UV_IRQ);
David Keitel753ec8d2011-11-02 10:56:37 -07002478 pm8921_chg_enable_irq(chip, CHGFAIL_IRQ);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002479 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
2480 pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
David Keitel52fda532011-11-10 10:43:44 -08002481 pm8921_chg_enable_irq(chip, BAT_TEMP_OK_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002482
2483 spin_lock_irqsave(&vbus_lock, flags);
2484 if (usb_chg_current) {
2485 /* reissue a vbus draw call */
2486 __pm8921_charger_vbus_draw(usb_chg_current);
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002487 fastchg_irq_handler(chip->pmic_chg_irq[FASTCHG_IRQ], chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002488 }
2489 spin_unlock_irqrestore(&vbus_lock, flags);
2490
2491 fsm_state = pm_chg_get_fsm_state(chip);
2492 if (is_battery_charging(fsm_state)) {
2493 chip->bms_notify.is_charging = 1;
2494 pm8921_bms_charging_began();
2495 }
2496
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002497 check_battery_valid(chip);
2498
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002499 pr_debug("usb = %d, dc = %d batt = %d state=%d\n",
2500 chip->usb_present,
2501 chip->dc_present,
2502 get_prop_batt_present(chip),
2503 fsm_state);
2504}
2505
2506struct pm_chg_irq_init_data {
2507 unsigned int irq_id;
2508 char *name;
2509 unsigned long flags;
2510 irqreturn_t (*handler)(int, void *);
2511};
2512
2513#define CHG_IRQ(_id, _flags, _handler) \
2514{ \
2515 .irq_id = _id, \
2516 .name = #_id, \
2517 .flags = _flags, \
2518 .handler = _handler, \
2519}
2520struct pm_chg_irq_init_data chg_irq_data[] = {
2521 CHG_IRQ(USBIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2522 usbin_valid_irq_handler),
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -07002523 CHG_IRQ(USBIN_OV_IRQ, IRQF_TRIGGER_RISING, usbin_ov_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002524 CHG_IRQ(BATT_INSERTED_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2525 batt_inserted_irq_handler),
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002526 CHG_IRQ(VBATDET_LOW_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2527 vbatdet_low_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002528 CHG_IRQ(USBIN_UV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2529 usbin_uv_irq_handler),
2530 CHG_IRQ(VBAT_OV_IRQ, IRQF_TRIGGER_RISING, vbat_ov_irq_handler),
2531 CHG_IRQ(CHGWDOG_IRQ, IRQF_TRIGGER_RISING, chgwdog_irq_handler),
2532 CHG_IRQ(VCP_IRQ, IRQF_TRIGGER_RISING, vcp_irq_handler),
2533 CHG_IRQ(ATCDONE_IRQ, IRQF_TRIGGER_RISING, atcdone_irq_handler),
2534 CHG_IRQ(ATCFAIL_IRQ, IRQF_TRIGGER_RISING, atcfail_irq_handler),
2535 CHG_IRQ(CHGDONE_IRQ, IRQF_TRIGGER_RISING, chgdone_irq_handler),
2536 CHG_IRQ(CHGFAIL_IRQ, IRQF_TRIGGER_RISING, chgfail_irq_handler),
2537 CHG_IRQ(CHGSTATE_IRQ, IRQF_TRIGGER_RISING, chgstate_irq_handler),
2538 CHG_IRQ(LOOP_CHANGE_IRQ, IRQF_TRIGGER_RISING, loop_change_irq_handler),
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002539 CHG_IRQ(FASTCHG_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2540 fastchg_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002541 CHG_IRQ(TRKLCHG_IRQ, IRQF_TRIGGER_RISING, trklchg_irq_handler),
2542 CHG_IRQ(BATT_REMOVED_IRQ, IRQF_TRIGGER_RISING,
2543 batt_removed_irq_handler),
2544 CHG_IRQ(BATTTEMP_HOT_IRQ, IRQF_TRIGGER_RISING,
2545 batttemp_hot_irq_handler),
2546 CHG_IRQ(CHGHOT_IRQ, IRQF_TRIGGER_RISING, chghot_irq_handler),
2547 CHG_IRQ(BATTTEMP_COLD_IRQ, IRQF_TRIGGER_RISING,
2548 batttemp_cold_irq_handler),
2549 CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING, chg_gone_irq_handler),
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07002550 CHG_IRQ(BAT_TEMP_OK_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2551 bat_temp_ok_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002552 CHG_IRQ(COARSE_DET_LOW_IRQ, IRQF_TRIGGER_RISING,
2553 coarse_det_low_irq_handler),
2554 CHG_IRQ(VDD_LOOP_IRQ, IRQF_TRIGGER_RISING, vdd_loop_irq_handler),
2555 CHG_IRQ(VREG_OV_IRQ, IRQF_TRIGGER_RISING, vreg_ov_irq_handler),
2556 CHG_IRQ(VBATDET_IRQ, IRQF_TRIGGER_RISING, vbatdet_irq_handler),
2557 CHG_IRQ(BATFET_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2558 batfet_irq_handler),
2559 CHG_IRQ(DCIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2560 dcin_valid_irq_handler),
2561 CHG_IRQ(DCIN_OV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2562 dcin_ov_irq_handler),
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -07002563 CHG_IRQ(DCIN_UV_IRQ, IRQF_TRIGGER_RISING, dcin_uv_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002564};
2565
2566static int __devinit request_irqs(struct pm8921_chg_chip *chip,
2567 struct platform_device *pdev)
2568{
2569 struct resource *res;
2570 int ret, i;
2571
2572 ret = 0;
2573 bitmap_fill(chip->enabled_irqs, PM_CHG_MAX_INTS);
2574
2575 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
2576 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
2577 chg_irq_data[i].name);
2578 if (res == NULL) {
2579 pr_err("couldn't find %s\n", chg_irq_data[i].name);
2580 goto err_out;
2581 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002582 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = res->start;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002583 ret = request_irq(res->start, chg_irq_data[i].handler,
2584 chg_irq_data[i].flags,
2585 chg_irq_data[i].name, chip);
2586 if (ret < 0) {
2587 pr_err("couldn't request %d (%s) %d\n", res->start,
2588 chg_irq_data[i].name, ret);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002589 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002590 goto err_out;
2591 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002592 pm8921_chg_disable_irq(chip, chg_irq_data[i].irq_id);
2593 }
2594 return 0;
2595
2596err_out:
2597 free_irqs(chip);
2598 return -EINVAL;
2599}
2600
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08002601static void pm8921_chg_force_19p2mhz_clk(struct pm8921_chg_chip *chip)
2602{
2603 int err;
2604 u8 temp;
2605
2606 temp = 0xD1;
2607 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2608 if (err) {
2609 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2610 return;
2611 }
2612
2613 temp = 0xD3;
2614 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2615 if (err) {
2616 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2617 return;
2618 }
2619
2620 temp = 0xD1;
2621 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2622 if (err) {
2623 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2624 return;
2625 }
2626
2627 temp = 0xD5;
2628 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2629 if (err) {
2630 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2631 return;
2632 }
2633
2634 udelay(183);
2635
2636 temp = 0xD1;
2637 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2638 if (err) {
2639 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2640 return;
2641 }
2642
2643 temp = 0xD0;
2644 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2645 if (err) {
2646 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2647 return;
2648 }
2649 udelay(32);
2650
2651 temp = 0xD1;
2652 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2653 if (err) {
2654 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2655 return;
2656 }
2657
2658 temp = 0xD3;
2659 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2660 if (err) {
2661 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2662 return;
2663 }
2664}
2665
2666static void pm8921_chg_set_hw_clk_switching(struct pm8921_chg_chip *chip)
2667{
2668 int err;
2669 u8 temp;
2670
2671 temp = 0xD1;
2672 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2673 if (err) {
2674 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2675 return;
2676 }
2677
2678 temp = 0xD0;
2679 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2680 if (err) {
2681 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
2682 return;
2683 }
2684}
2685
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002686#define ENUM_TIMER_STOP_BIT BIT(1)
2687#define BOOT_DONE_BIT BIT(6)
2688#define CHG_BATFET_ON_BIT BIT(3)
2689#define CHG_VCP_EN BIT(0)
2690#define CHG_BAT_TEMP_DIS_BIT BIT(2)
2691#define SAFE_CURRENT_MA 1500
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08002692#define VREF_BATT_THERM_FORCE_ON BIT(7)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002693static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
2694{
2695 int rc;
2696
2697 rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
2698 BOOT_DONE_BIT, BOOT_DONE_BIT);
2699 if (rc) {
2700 pr_err("Failed to set BOOT_DONE_BIT rc=%d\n", rc);
2701 return rc;
2702 }
2703
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002704 rc = pm_chg_vddsafe_set(chip, chip->max_voltage_mv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002705 if (rc) {
2706 pr_err("Failed to set safe voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002707 chip->max_voltage_mv, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002708 return rc;
2709 }
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07002710 rc = pm_chg_vbatdet_set(chip,
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002711 chip->max_voltage_mv
2712 - chip->resume_voltage_delta);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002713 if (rc) {
2714 pr_err("Failed to set vbatdet comprator voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002715 chip->max_voltage_mv - chip->resume_voltage_delta, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002716 return rc;
2717 }
2718
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002719 rc = pm_chg_vddmax_set(chip, chip->max_voltage_mv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002720 if (rc) {
2721 pr_err("Failed to set max voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08002722 chip->max_voltage_mv, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002723 return rc;
2724 }
2725 rc = pm_chg_ibatsafe_set(chip, SAFE_CURRENT_MA);
2726 if (rc) {
2727 pr_err("Failed to set max voltage to %d rc=%d\n",
2728 SAFE_CURRENT_MA, rc);
2729 return rc;
2730 }
2731
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07002732 rc = pm_chg_ibatmax_set(chip, chip->max_bat_chg_current);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002733 if (rc) {
2734 pr_err("Failed to set max current to 400 rc=%d\n", rc);
2735 return rc;
2736 }
2737
2738 rc = pm_chg_iterm_set(chip, chip->term_current);
2739 if (rc) {
2740 pr_err("Failed to set term current to %d rc=%d\n",
2741 chip->term_current, rc);
2742 return rc;
2743 }
2744
2745 /* Disable the ENUM TIMER */
2746 rc = pm_chg_masked_write(chip, PBL_ACCESS2, ENUM_TIMER_STOP_BIT,
2747 ENUM_TIMER_STOP_BIT);
2748 if (rc) {
2749 pr_err("Failed to set enum timer stop rc=%d\n", rc);
2750 return rc;
2751 }
2752
2753 /* init with the lowest USB current */
2754 rc = pm_chg_iusbmax_set(chip, usb_ma_table[0].chg_iusb_value);
2755 if (rc) {
2756 pr_err("Failed to set usb max to %d rc=%d\n",
2757 usb_ma_table[0].chg_iusb_value, rc);
2758 return rc;
2759 }
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002760
2761 if (chip->safety_time != 0) {
2762 rc = pm_chg_tchg_max_set(chip, chip->safety_time);
2763 if (rc) {
2764 pr_err("Failed to set max time to %d minutes rc=%d\n",
2765 chip->safety_time, rc);
2766 return rc;
2767 }
2768 }
2769
2770 if (chip->ttrkl_time != 0) {
Abhijeet Dharmapurikare45c3d32011-10-19 19:46:48 -07002771 rc = pm_chg_ttrkl_max_set(chip, chip->ttrkl_time);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002772 if (rc) {
2773 pr_err("Failed to set trkl time to %d minutes rc=%d\n",
2774 chip->safety_time, rc);
2775 return rc;
2776 }
2777 }
2778
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002779 if (chip->vin_min != 0) {
2780 rc = pm_chg_vinmin_set(chip, chip->vin_min);
2781 if (rc) {
2782 pr_err("Failed to set vin min to %d mV rc=%d\n",
2783 chip->vin_min, rc);
2784 return rc;
2785 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002786 } else {
2787 chip->vin_min = pm_chg_vinmin_get(chip);
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002788 }
2789
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002790 rc = pm_chg_disable_wd(chip);
2791 if (rc) {
2792 pr_err("Failed to disable wd rc=%d\n", rc);
2793 return rc;
2794 }
2795
2796 rc = pm_chg_masked_write(chip, CHG_CNTRL_2,
2797 CHG_BAT_TEMP_DIS_BIT, 0);
2798 if (rc) {
2799 pr_err("Failed to enable temp control chg rc=%d\n", rc);
2800 return rc;
2801 }
2802 /* switch to a 3.2Mhz for the buck */
2803 rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CLOCK_CTRL, 0x15);
2804 if (rc) {
2805 pr_err("Failed to switch buck clk rc=%d\n", rc);
2806 return rc;
2807 }
2808
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07002809 if (chip->trkl_voltage != 0) {
2810 rc = pm_chg_vtrkl_low_set(chip, chip->trkl_voltage);
2811 if (rc) {
2812 pr_err("Failed to set trkl voltage to %dmv rc=%d\n",
2813 chip->trkl_voltage, rc);
2814 return rc;
2815 }
2816 }
2817
2818 if (chip->weak_voltage != 0) {
2819 rc = pm_chg_vweak_set(chip, chip->weak_voltage);
2820 if (rc) {
2821 pr_err("Failed to set weak voltage to %dmv rc=%d\n",
2822 chip->weak_voltage, rc);
2823 return rc;
2824 }
2825 }
2826
2827 if (chip->trkl_current != 0) {
2828 rc = pm_chg_itrkl_set(chip, chip->trkl_current);
2829 if (rc) {
2830 pr_err("Failed to set trkl current to %dmA rc=%d\n",
2831 chip->trkl_voltage, rc);
2832 return rc;
2833 }
2834 }
2835
2836 if (chip->weak_current != 0) {
2837 rc = pm_chg_iweak_set(chip, chip->weak_current);
2838 if (rc) {
2839 pr_err("Failed to set weak current to %dmA rc=%d\n",
2840 chip->weak_current, rc);
2841 return rc;
2842 }
2843 }
2844
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07002845 rc = pm_chg_batt_cold_temp_config(chip, chip->cold_thr);
2846 if (rc) {
2847 pr_err("Failed to set cold config %d rc=%d\n",
2848 chip->cold_thr, rc);
2849 }
2850
2851 rc = pm_chg_batt_hot_temp_config(chip, chip->hot_thr);
2852 if (rc) {
2853 pr_err("Failed to set hot config %d rc=%d\n",
2854 chip->hot_thr, rc);
2855 }
2856
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002857 /* Workarounds for die 1.1 and 1.0 */
2858 if (pm8xxx_get_revision(chip->dev->parent) < PM8XXX_REVISION_8921_2p0) {
2859 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST2, 0xF1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002860 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xCE);
2861 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD8);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002862
2863 /* software workaround for correct battery_id detection */
2864 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_0, 0xFF);
2865 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_1, 0xFF);
2866 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_2, 0xFF);
2867 pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_3, 0xFF);
2868 pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0D);
2869 udelay(100);
2870 pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0C);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002871 }
2872
David Keitelb51995e2011-11-18 17:03:31 -08002873 /* Workarounds for die 3.0 */
2874 if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0)
2875 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xAC);
2876
2877 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD9);
2878
David Keitela3c0d822011-11-03 14:18:52 -07002879 /* Disable EOC FSM processing */
2880 pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x91);
2881
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08002882 pm8921_chg_force_19p2mhz_clk(chip);
2883
2884 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
2885 VREF_BATT_THERM_FORCE_ON);
2886 if (rc)
2887 pr_err("Failed to Force Vref therm rc=%d\n", rc);
2888
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002889 rc = pm_chg_charge_dis(chip, charging_disabled);
2890 if (rc) {
2891 pr_err("Failed to disable CHG_CHARGE_DIS bit rc=%d\n", rc);
2892 return rc;
2893 }
2894
2895 rc = pm_chg_auto_enable(chip, !charging_disabled);
2896 if (rc) {
2897 pr_err("Failed to enable charging rc=%d\n", rc);
2898 return rc;
2899 }
2900
2901 return 0;
2902}
2903
2904static int get_rt_status(void *data, u64 * val)
2905{
2906 int i = (int)data;
2907 int ret;
2908
2909 /* global irq number is passed in via data */
2910 ret = pm_chg_get_rt_status(the_chip, i);
2911 *val = ret;
2912 return 0;
2913}
2914DEFINE_SIMPLE_ATTRIBUTE(rt_fops, get_rt_status, NULL, "%llu\n");
2915
2916static int get_fsm_status(void *data, u64 * val)
2917{
2918 u8 temp;
2919
2920 temp = pm_chg_get_fsm_state(the_chip);
2921 *val = temp;
2922 return 0;
2923}
2924DEFINE_SIMPLE_ATTRIBUTE(fsm_fops, get_fsm_status, NULL, "%llu\n");
2925
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002926static int get_reg_loop(void *data, u64 * val)
2927{
2928 u8 temp;
2929
2930 if (!the_chip) {
2931 pr_err("%s called before init\n", __func__);
2932 return -EINVAL;
2933 }
2934 temp = pm_chg_get_regulation_loop(the_chip);
2935 *val = temp;
2936 return 0;
2937}
2938DEFINE_SIMPLE_ATTRIBUTE(reg_loop_fops, get_reg_loop, NULL, "0x%02llx\n");
2939
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002940static int get_reg(void *data, u64 * val)
2941{
2942 int addr = (int)data;
2943 int ret;
2944 u8 temp;
2945
2946 ret = pm8xxx_readb(the_chip->dev->parent, addr, &temp);
2947 if (ret) {
2948 pr_err("pm8xxx_readb to %x value =%d errored = %d\n",
2949 addr, temp, ret);
2950 return -EAGAIN;
2951 }
2952 *val = temp;
2953 return 0;
2954}
2955
2956static int set_reg(void *data, u64 val)
2957{
2958 int addr = (int)data;
2959 int ret;
2960 u8 temp;
2961
2962 temp = (u8) val;
2963 ret = pm8xxx_writeb(the_chip->dev->parent, addr, temp);
2964 if (ret) {
2965 pr_err("pm8xxx_writeb to %x value =%d errored = %d\n",
2966 addr, temp, ret);
2967 return -EAGAIN;
2968 }
2969 return 0;
2970}
2971DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
2972
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07002973enum {
2974 BAT_WARM_ZONE,
2975 BAT_COOL_ZONE,
2976};
2977static int get_warm_cool(void *data, u64 * val)
2978{
2979 if (!the_chip) {
2980 pr_err("%s called before init\n", __func__);
2981 return -EINVAL;
2982 }
2983 if ((int)data == BAT_WARM_ZONE)
2984 *val = the_chip->is_bat_warm;
2985 if ((int)data == BAT_COOL_ZONE)
2986 *val = the_chip->is_bat_cool;
2987 return 0;
2988}
2989DEFINE_SIMPLE_ATTRIBUTE(warm_cool_fops, get_warm_cool, NULL, "0x%lld\n");
2990
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002991static void create_debugfs_entries(struct pm8921_chg_chip *chip)
2992{
2993 int i;
2994
2995 chip->dent = debugfs_create_dir("pm8921_chg", NULL);
2996
2997 if (IS_ERR(chip->dent)) {
2998 pr_err("pmic charger couldnt create debugfs dir\n");
2999 return;
3000 }
3001
3002 debugfs_create_file("CHG_CNTRL", 0644, chip->dent,
3003 (void *)CHG_CNTRL, &reg_fops);
3004 debugfs_create_file("CHG_CNTRL_2", 0644, chip->dent,
3005 (void *)CHG_CNTRL_2, &reg_fops);
3006 debugfs_create_file("CHG_CNTRL_3", 0644, chip->dent,
3007 (void *)CHG_CNTRL_3, &reg_fops);
3008 debugfs_create_file("PBL_ACCESS1", 0644, chip->dent,
3009 (void *)PBL_ACCESS1, &reg_fops);
3010 debugfs_create_file("PBL_ACCESS2", 0644, chip->dent,
3011 (void *)PBL_ACCESS2, &reg_fops);
3012 debugfs_create_file("SYS_CONFIG_1", 0644, chip->dent,
3013 (void *)SYS_CONFIG_1, &reg_fops);
3014 debugfs_create_file("SYS_CONFIG_2", 0644, chip->dent,
3015 (void *)SYS_CONFIG_2, &reg_fops);
3016 debugfs_create_file("CHG_VDD_MAX", 0644, chip->dent,
3017 (void *)CHG_VDD_MAX, &reg_fops);
3018 debugfs_create_file("CHG_VDD_SAFE", 0644, chip->dent,
3019 (void *)CHG_VDD_SAFE, &reg_fops);
3020 debugfs_create_file("CHG_VBAT_DET", 0644, chip->dent,
3021 (void *)CHG_VBAT_DET, &reg_fops);
3022 debugfs_create_file("CHG_IBAT_MAX", 0644, chip->dent,
3023 (void *)CHG_IBAT_MAX, &reg_fops);
3024 debugfs_create_file("CHG_IBAT_SAFE", 0644, chip->dent,
3025 (void *)CHG_IBAT_SAFE, &reg_fops);
3026 debugfs_create_file("CHG_VIN_MIN", 0644, chip->dent,
3027 (void *)CHG_VIN_MIN, &reg_fops);
3028 debugfs_create_file("CHG_VTRICKLE", 0644, chip->dent,
3029 (void *)CHG_VTRICKLE, &reg_fops);
3030 debugfs_create_file("CHG_ITRICKLE", 0644, chip->dent,
3031 (void *)CHG_ITRICKLE, &reg_fops);
3032 debugfs_create_file("CHG_ITERM", 0644, chip->dent,
3033 (void *)CHG_ITERM, &reg_fops);
3034 debugfs_create_file("CHG_TCHG_MAX", 0644, chip->dent,
3035 (void *)CHG_TCHG_MAX, &reg_fops);
3036 debugfs_create_file("CHG_TWDOG", 0644, chip->dent,
3037 (void *)CHG_TWDOG, &reg_fops);
3038 debugfs_create_file("CHG_TEMP_THRESH", 0644, chip->dent,
3039 (void *)CHG_TEMP_THRESH, &reg_fops);
3040 debugfs_create_file("CHG_COMP_OVR", 0644, chip->dent,
3041 (void *)CHG_COMP_OVR, &reg_fops);
3042 debugfs_create_file("CHG_BUCK_CTRL_TEST1", 0644, chip->dent,
3043 (void *)CHG_BUCK_CTRL_TEST1, &reg_fops);
3044 debugfs_create_file("CHG_BUCK_CTRL_TEST2", 0644, chip->dent,
3045 (void *)CHG_BUCK_CTRL_TEST2, &reg_fops);
3046 debugfs_create_file("CHG_BUCK_CTRL_TEST3", 0644, chip->dent,
3047 (void *)CHG_BUCK_CTRL_TEST3, &reg_fops);
3048 debugfs_create_file("CHG_TEST", 0644, chip->dent,
3049 (void *)CHG_TEST, &reg_fops);
3050
3051 debugfs_create_file("FSM_STATE", 0644, chip->dent, NULL,
3052 &fsm_fops);
3053
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003054 debugfs_create_file("REGULATION_LOOP_CONTROL", 0644, chip->dent, NULL,
3055 &reg_loop_fops);
3056
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07003057 debugfs_create_file("BAT_WARM_ZONE", 0644, chip->dent,
3058 (void *)BAT_WARM_ZONE, &warm_cool_fops);
3059 debugfs_create_file("BAT_COOL_ZONE", 0644, chip->dent,
3060 (void *)BAT_COOL_ZONE, &warm_cool_fops);
3061
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003062 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
3063 if (chip->pmic_chg_irq[chg_irq_data[i].irq_id])
3064 debugfs_create_file(chg_irq_data[i].name, 0444,
3065 chip->dent,
3066 (void *)chg_irq_data[i].irq_id,
3067 &rt_fops);
3068 }
3069}
3070
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08003071static int pm8921_charger_suspend_noirq(struct device *dev)
3072{
3073 int rc;
3074 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
3075
3076 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON, 0);
3077 if (rc)
3078 pr_err("Failed to Force Vref therm off rc=%d\n", rc);
3079 pm8921_chg_set_hw_clk_switching(chip);
3080 return 0;
3081}
3082
3083static int pm8921_charger_resume_noirq(struct device *dev)
3084{
3085 int rc;
3086 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
3087
3088 pm8921_chg_force_19p2mhz_clk(chip);
3089
3090 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
3091 VREF_BATT_THERM_FORCE_ON);
3092 if (rc)
3093 pr_err("Failed to Force Vref therm on rc=%d\n", rc);
3094 return 0;
3095}
3096
David Keitelf2226022011-12-13 15:55:50 -08003097static int pm8921_charger_resume(struct device *dev)
3098{
3099 int rc;
3100 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
3101
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08003102 if (!(chip->cool_temp_dc == INT_MIN && chip->warm_temp_dc == INT_MIN)
David Keitelf2226022011-12-13 15:55:50 -08003103 && !(chip->keep_btm_on_suspend)) {
3104 rc = pm8xxx_adc_btm_configure(&btm_config);
3105 if (rc)
3106 pr_err("couldn't reconfigure btm rc=%d\n", rc);
3107
3108 rc = pm8xxx_adc_btm_start();
3109 if (rc)
3110 pr_err("couldn't restart btm rc=%d\n", rc);
3111 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003112 if (pm8921_chg_is_enabled(chip, LOOP_CHANGE_IRQ)) {
3113 disable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
3114 pm8921_chg_disable_irq(chip, LOOP_CHANGE_IRQ);
3115 }
David Keitelf2226022011-12-13 15:55:50 -08003116 return 0;
3117}
3118
3119static int pm8921_charger_suspend(struct device *dev)
3120{
3121 int rc;
3122 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
3123
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08003124 if (!(chip->cool_temp_dc == INT_MIN && chip->warm_temp_dc == INT_MIN)
David Keitelf2226022011-12-13 15:55:50 -08003125 && !(chip->keep_btm_on_suspend)) {
3126 rc = pm8xxx_adc_btm_end();
3127 if (rc)
3128 pr_err("Failed to disable BTM on suspend rc=%d\n", rc);
3129 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003130
3131 if (is_usb_chg_plugged_in(chip)) {
3132 pm8921_chg_enable_irq(chip, LOOP_CHANGE_IRQ);
3133 enable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
3134 }
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08003135
David Keitelf2226022011-12-13 15:55:50 -08003136 return 0;
3137}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003138static int __devinit pm8921_charger_probe(struct platform_device *pdev)
3139{
3140 int rc = 0;
3141 struct pm8921_chg_chip *chip;
3142 const struct pm8921_charger_platform_data *pdata
3143 = pdev->dev.platform_data;
3144
3145 if (!pdata) {
3146 pr_err("missing platform data\n");
3147 return -EINVAL;
3148 }
3149
3150 chip = kzalloc(sizeof(struct pm8921_chg_chip),
3151 GFP_KERNEL);
3152 if (!chip) {
3153 pr_err("Cannot allocate pm_chg_chip\n");
3154 return -ENOMEM;
3155 }
3156
3157 chip->dev = &pdev->dev;
3158 chip->safety_time = pdata->safety_time;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07003159 chip->ttrkl_time = pdata->ttrkl_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003160 chip->update_time = pdata->update_time;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08003161 chip->max_voltage_mv = pdata->max_voltage;
3162 chip->min_voltage_mv = pdata->min_voltage;
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07003163 chip->resume_voltage_delta = pdata->resume_voltage_delta;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003164 chip->term_current = pdata->term_current;
3165 chip->vbat_channel = pdata->charger_cdata.vbat_channel;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07003166 chip->batt_temp_channel = pdata->charger_cdata.batt_temp_channel;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07003167 chip->batt_id_channel = pdata->charger_cdata.batt_id_channel;
3168 chip->batt_id_min = pdata->batt_id_min;
3169 chip->batt_id_max = pdata->batt_id_max;
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08003170 if (pdata->cool_temp != INT_MIN)
3171 chip->cool_temp_dc = pdata->cool_temp * 10;
3172 else
3173 chip->cool_temp_dc = INT_MIN;
3174
3175 if (pdata->warm_temp != INT_MIN)
3176 chip->warm_temp_dc = pdata->warm_temp * 10;
3177 else
3178 chip->warm_temp_dc = INT_MIN;
3179
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003180 chip->temp_check_period = pdata->temp_check_period;
3181 chip->max_bat_chg_current = pdata->max_bat_chg_current;
3182 chip->cool_bat_chg_current = pdata->cool_bat_chg_current;
3183 chip->warm_bat_chg_current = pdata->warm_bat_chg_current;
3184 chip->cool_bat_voltage = pdata->cool_bat_voltage;
3185 chip->warm_bat_voltage = pdata->warm_bat_voltage;
David Keitelf2226022011-12-13 15:55:50 -08003186 chip->keep_btm_on_suspend = pdata->keep_btm_on_suspend;
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07003187 chip->trkl_voltage = pdata->trkl_voltage;
3188 chip->weak_voltage = pdata->weak_voltage;
3189 chip->trkl_current = pdata->trkl_current;
3190 chip->weak_current = pdata->weak_current;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07003191 chip->vin_min = pdata->vin_min;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07003192 chip->thermal_mitigation = pdata->thermal_mitigation;
3193 chip->thermal_levels = pdata->thermal_levels;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003194
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07003195 chip->cold_thr = pdata->cold_thr;
3196 chip->hot_thr = pdata->hot_thr;
3197
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003198 rc = pm8921_chg_hw_init(chip);
3199 if (rc) {
3200 pr_err("couldn't init hardware rc=%d\n", rc);
3201 goto free_chip;
3202 }
3203
3204 chip->usb_psy.name = "usb",
3205 chip->usb_psy.type = POWER_SUPPLY_TYPE_USB,
3206 chip->usb_psy.supplied_to = pm_power_supplied_to,
3207 chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
3208 chip->usb_psy.properties = pm_power_props,
3209 chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props),
3210 chip->usb_psy.get_property = pm_power_get_property,
3211
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003212 chip->batt_psy.name = "battery",
3213 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY,
3214 chip->batt_psy.properties = msm_batt_power_props,
3215 chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props),
3216 chip->batt_psy.get_property = pm_batt_power_get_property,
David Keitel88e1b572012-01-11 11:57:14 -08003217 chip->batt_psy.external_power_changed = pm_batt_external_power_changed,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003218 rc = power_supply_register(chip->dev, &chip->usb_psy);
3219 if (rc < 0) {
3220 pr_err("power_supply_register usb failed rc = %d\n", rc);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003221 goto free_chip;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003222 }
3223
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003224 rc = power_supply_register(chip->dev, &chip->batt_psy);
3225 if (rc < 0) {
3226 pr_err("power_supply_register batt failed rc = %d\n", rc);
David Keitel88e1b572012-01-11 11:57:14 -08003227 goto unregister_usb;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003228 }
3229
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003230 platform_set_drvdata(pdev, chip);
3231 the_chip = chip;
3232
3233 wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003234 wake_lock_init(&chip->unplug_wrkarnd_restore_wake_lock,
3235 WAKE_LOCK_SUSPEND, "pm8921_unplug_wrkarnd");
Amir Samuelovd31ef502011-10-26 14:41:36 +02003236 INIT_DELAYED_WORK(&chip->eoc_work, eoc_worker);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003237 INIT_DELAYED_WORK(&chip->unplug_wrkarnd_restore_work,
3238 unplug_wrkarnd_restore_worker);
3239 INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003240
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003241 rc = request_irqs(chip, pdev);
3242 if (rc) {
3243 pr_err("couldn't register interrupts rc=%d\n", rc);
3244 goto unregister_batt;
3245 }
3246
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07003247 enable_irq_wake(chip->pmic_chg_irq[USBIN_VALID_IRQ]);
3248 enable_irq_wake(chip->pmic_chg_irq[USBIN_OV_IRQ]);
3249 enable_irq_wake(chip->pmic_chg_irq[USBIN_UV_IRQ]);
David Keitel64dd3f52011-11-10 14:19:38 -08003250 enable_irq_wake(chip->pmic_chg_irq[BAT_TEMP_OK_IRQ]);
3251 enable_irq_wake(chip->pmic_chg_irq[VBATDET_LOW_IRQ]);
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08003252 enable_irq_wake(chip->pmic_chg_irq[FASTCHG_IRQ]);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003253 /*
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08003254 * if both the cool_temp_dc and warm_temp_dc are invalid device doesnt
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003255 * care for jeita compliance
3256 */
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08003257 if (!(chip->cool_temp_dc == INT_MIN && chip->warm_temp_dc == INT_MIN)) {
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003258 rc = configure_btm(chip);
3259 if (rc) {
3260 pr_err("couldn't register with btm rc=%d\n", rc);
3261 goto free_irq;
3262 }
3263 }
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07003264
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003265 create_debugfs_entries(chip);
3266
3267 INIT_WORK(&chip->bms_notify.work, bms_notify);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07003268 INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003269
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003270 /* determine what state the charger is in */
3271 determine_initial_state(chip);
3272
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003273 if (chip->update_time) {
3274 INIT_DELAYED_WORK(&chip->update_heartbeat_work,
3275 update_heartbeat);
3276 schedule_delayed_work(&chip->update_heartbeat_work,
3277 round_jiffies_relative(msecs_to_jiffies
3278 (chip->update_time)));
3279 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003280 return 0;
3281
3282free_irq:
3283 free_irqs(chip);
3284unregister_batt:
3285 power_supply_unregister(&chip->batt_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003286unregister_usb:
3287 power_supply_unregister(&chip->usb_psy);
3288free_chip:
3289 kfree(chip);
3290 return rc;
3291}
3292
3293static int __devexit pm8921_charger_remove(struct platform_device *pdev)
3294{
3295 struct pm8921_chg_chip *chip = platform_get_drvdata(pdev);
3296
3297 free_irqs(chip);
3298 platform_set_drvdata(pdev, NULL);
3299 the_chip = NULL;
3300 kfree(chip);
3301 return 0;
3302}
David Keitelf2226022011-12-13 15:55:50 -08003303static const struct dev_pm_ops pm8921_pm_ops = {
3304 .suspend = pm8921_charger_suspend,
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08003305 .suspend_noirq = pm8921_charger_suspend_noirq,
3306 .resume_noirq = pm8921_charger_resume_noirq,
David Keitelf2226022011-12-13 15:55:50 -08003307 .resume = pm8921_charger_resume,
3308};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003309static struct platform_driver pm8921_charger_driver = {
David Keitelf2226022011-12-13 15:55:50 -08003310 .probe = pm8921_charger_probe,
3311 .remove = __devexit_p(pm8921_charger_remove),
3312 .driver = {
3313 .name = PM8921_CHARGER_DEV_NAME,
3314 .owner = THIS_MODULE,
3315 .pm = &pm8921_pm_ops,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003316 },
3317};
3318
3319static int __init pm8921_charger_init(void)
3320{
3321 return platform_driver_register(&pm8921_charger_driver);
3322}
3323
3324static void __exit pm8921_charger_exit(void)
3325{
3326 platform_driver_unregister(&pm8921_charger_driver);
3327}
3328
3329late_initcall(pm8921_charger_init);
3330module_exit(pm8921_charger_exit);
3331
3332MODULE_LICENSE("GPL v2");
3333MODULE_DESCRIPTION("PMIC8921 charger/battery driver");
3334MODULE_VERSION("1.0");
3335MODULE_ALIAS("platform:" PM8921_CHARGER_DEV_NAME);