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