blob: ba1a5681af3160f18585990a39263a80fc763e71 [file] [log] [blame]
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001/* Copyright (c) 2011-2013, The Linux Foundation. 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>
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -070024#include <linux/regulator/consumer.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026#include <linux/delay.h>
27#include <linux/bitops.h>
28#include <linux/workqueue.h>
29#include <linux/debugfs.h>
30#include <linux/slab.h>
Ajay Dudani11aeb7b2012-06-28 19:14:30 -070031#include <linux/mfd/pm8xxx/batt-alarm.h>
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -070032#include <linux/ratelimit.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070033
34#include <mach/msm_xo.h>
35#include <mach/msm_hsusb.h>
36
37#define CHG_BUCK_CLOCK_CTRL 0x14
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -070038#define CHG_BUCK_CLOCK_CTRL_8038 0xD
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070039
40#define PBL_ACCESS1 0x04
41#define PBL_ACCESS2 0x05
42#define SYS_CONFIG_1 0x06
43#define SYS_CONFIG_2 0x07
44#define CHG_CNTRL 0x204
45#define CHG_IBAT_MAX 0x205
46#define CHG_TEST 0x206
47#define CHG_BUCK_CTRL_TEST1 0x207
48#define CHG_BUCK_CTRL_TEST2 0x208
49#define CHG_BUCK_CTRL_TEST3 0x209
50#define COMPARATOR_OVERRIDE 0x20A
51#define PSI_TXRX_SAMPLE_DATA_0 0x20B
52#define PSI_TXRX_SAMPLE_DATA_1 0x20C
53#define PSI_TXRX_SAMPLE_DATA_2 0x20D
54#define PSI_TXRX_SAMPLE_DATA_3 0x20E
55#define PSI_CONFIG_STATUS 0x20F
56#define CHG_IBAT_SAFE 0x210
57#define CHG_ITRICKLE 0x211
58#define CHG_CNTRL_2 0x212
59#define CHG_VBAT_DET 0x213
60#define CHG_VTRICKLE 0x214
61#define CHG_ITERM 0x215
62#define CHG_CNTRL_3 0x216
63#define CHG_VIN_MIN 0x217
64#define CHG_TWDOG 0x218
65#define CHG_TTRKL_MAX 0x219
66#define CHG_TEMP_THRESH 0x21A
67#define CHG_TCHG_MAX 0x21B
68#define USB_OVP_CONTROL 0x21C
69#define DC_OVP_CONTROL 0x21D
70#define USB_OVP_TEST 0x21E
71#define DC_OVP_TEST 0x21F
72#define CHG_VDD_MAX 0x220
73#define CHG_VDD_SAFE 0x221
74#define CHG_VBAT_BOOT_THRESH 0x222
75#define USB_OVP_TRIM 0x355
76#define BUCK_CONTROL_TRIM1 0x356
77#define BUCK_CONTROL_TRIM2 0x357
78#define BUCK_CONTROL_TRIM3 0x358
79#define BUCK_CONTROL_TRIM4 0x359
80#define CHG_DEFAULTS_TRIM 0x35A
81#define CHG_ITRIM 0x35B
82#define CHG_TTRIM 0x35C
83#define CHG_COMP_OVR 0x20A
David Keitel38bdd4f2012-04-19 15:39:13 -070084#define IUSB_FINE_RES 0x2B6
David Keitel0789fc62012-06-07 17:43:27 -070085#define OVP_USB_UVD 0x2B7
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070086
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -070087/* check EOC every 10 seconds */
88#define EOC_CHECK_PERIOD_MS 10000
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -080089/* check for USB unplug every 200 msecs */
90#define UNPLUG_CHECK_WAIT_PERIOD_MS 200
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -070091#define UNPLUG_CHECK_RAMP_MS 25
92#define USB_TRIM_ENTRIES 16
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -070093
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070094enum chg_fsm_state {
95 FSM_STATE_OFF_0 = 0,
96 FSM_STATE_BATFETDET_START_12 = 12,
97 FSM_STATE_BATFETDET_END_16 = 16,
98 FSM_STATE_ON_CHG_HIGHI_1 = 1,
99 FSM_STATE_ATC_2A = 2,
100 FSM_STATE_ATC_2B = 18,
101 FSM_STATE_ON_BAT_3 = 3,
102 FSM_STATE_ATC_FAIL_4 = 4 ,
103 FSM_STATE_DELAY_5 = 5,
104 FSM_STATE_ON_CHG_AND_BAT_6 = 6,
105 FSM_STATE_FAST_CHG_7 = 7,
106 FSM_STATE_TRKL_CHG_8 = 8,
107 FSM_STATE_CHG_FAIL_9 = 9,
108 FSM_STATE_EOC_10 = 10,
109 FSM_STATE_ON_CHG_VREGOK_11 = 11,
110 FSM_STATE_ATC_PAUSE_13 = 13,
111 FSM_STATE_FAST_CHG_PAUSE_14 = 14,
112 FSM_STATE_TRKL_CHG_PAUSE_15 = 15,
113 FSM_STATE_START_BOOT = 20,
114 FSM_STATE_FLCB_VREGOK = 21,
115 FSM_STATE_FLCB = 22,
116};
117
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -0700118struct fsm_state_to_batt_status {
119 enum chg_fsm_state fsm_state;
120 int batt_state;
121};
122
123static struct fsm_state_to_batt_status map[] = {
124 {FSM_STATE_OFF_0, POWER_SUPPLY_STATUS_UNKNOWN},
125 {FSM_STATE_BATFETDET_START_12, POWER_SUPPLY_STATUS_UNKNOWN},
126 {FSM_STATE_BATFETDET_END_16, POWER_SUPPLY_STATUS_UNKNOWN},
127 /*
128 * for CHG_HIGHI_1 report NOT_CHARGING if battery missing,
129 * too hot/cold, charger too hot
130 */
131 {FSM_STATE_ON_CHG_HIGHI_1, POWER_SUPPLY_STATUS_FULL},
132 {FSM_STATE_ATC_2A, POWER_SUPPLY_STATUS_CHARGING},
133 {FSM_STATE_ATC_2B, POWER_SUPPLY_STATUS_CHARGING},
134 {FSM_STATE_ON_BAT_3, POWER_SUPPLY_STATUS_DISCHARGING},
135 {FSM_STATE_ATC_FAIL_4, POWER_SUPPLY_STATUS_DISCHARGING},
136 {FSM_STATE_DELAY_5, POWER_SUPPLY_STATUS_UNKNOWN },
137 {FSM_STATE_ON_CHG_AND_BAT_6, POWER_SUPPLY_STATUS_CHARGING},
138 {FSM_STATE_FAST_CHG_7, POWER_SUPPLY_STATUS_CHARGING},
139 {FSM_STATE_TRKL_CHG_8, POWER_SUPPLY_STATUS_CHARGING},
140 {FSM_STATE_CHG_FAIL_9, POWER_SUPPLY_STATUS_DISCHARGING},
141 {FSM_STATE_EOC_10, POWER_SUPPLY_STATUS_FULL},
142 {FSM_STATE_ON_CHG_VREGOK_11, POWER_SUPPLY_STATUS_NOT_CHARGING},
143 {FSM_STATE_ATC_PAUSE_13, POWER_SUPPLY_STATUS_NOT_CHARGING},
144 {FSM_STATE_FAST_CHG_PAUSE_14, POWER_SUPPLY_STATUS_NOT_CHARGING},
145 {FSM_STATE_TRKL_CHG_PAUSE_15, POWER_SUPPLY_STATUS_NOT_CHARGING},
146 {FSM_STATE_START_BOOT, POWER_SUPPLY_STATUS_NOT_CHARGING},
147 {FSM_STATE_FLCB_VREGOK, POWER_SUPPLY_STATUS_NOT_CHARGING},
148 {FSM_STATE_FLCB, POWER_SUPPLY_STATUS_NOT_CHARGING},
149};
150
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700151enum chg_regulation_loop {
152 VDD_LOOP = BIT(3),
153 BAT_CURRENT_LOOP = BIT(2),
154 INPUT_CURRENT_LOOP = BIT(1),
155 INPUT_VOLTAGE_LOOP = BIT(0),
156 CHG_ALL_LOOPS = VDD_LOOP | BAT_CURRENT_LOOP
157 | INPUT_CURRENT_LOOP | INPUT_VOLTAGE_LOOP,
158};
159
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160enum pmic_chg_interrupts {
161 USBIN_VALID_IRQ = 0,
162 USBIN_OV_IRQ,
163 BATT_INSERTED_IRQ,
164 VBATDET_LOW_IRQ,
165 USBIN_UV_IRQ,
166 VBAT_OV_IRQ,
167 CHGWDOG_IRQ,
168 VCP_IRQ,
169 ATCDONE_IRQ,
170 ATCFAIL_IRQ,
171 CHGDONE_IRQ,
172 CHGFAIL_IRQ,
173 CHGSTATE_IRQ,
174 LOOP_CHANGE_IRQ,
175 FASTCHG_IRQ,
176 TRKLCHG_IRQ,
177 BATT_REMOVED_IRQ,
178 BATTTEMP_HOT_IRQ,
179 CHGHOT_IRQ,
180 BATTTEMP_COLD_IRQ,
181 CHG_GONE_IRQ,
182 BAT_TEMP_OK_IRQ,
183 COARSE_DET_LOW_IRQ,
184 VDD_LOOP_IRQ,
185 VREG_OV_IRQ,
186 VBATDET_IRQ,
187 BATFET_IRQ,
188 PSI_IRQ,
189 DCIN_VALID_IRQ,
190 DCIN_OV_IRQ,
191 DCIN_UV_IRQ,
192 PM_CHG_MAX_INTS,
193};
194
195struct bms_notify {
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700196 int is_battery_full;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700197 int is_charging;
198 struct work_struct work;
199};
200
201/**
202 * struct pm8921_chg_chip -device information
203 * @dev: device pointer to access the parent
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 * @usb_present: present status of usb
205 * @dc_present: present status of dc
206 * @usb_charger_current: usb current to charge the battery with used when
207 * the usb path is enabled or charging is resumed
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208 * @update_time: how frequently the userland needs to be updated
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800209 * @max_voltage_mv: the max volts the batt should be charged up to
210 * @min_voltage_mv: the min battery voltage before turning the FETon
David Keitel0789fc62012-06-07 17:43:27 -0700211 * @uvd_voltage_mv: (PM8917 only) the falling UVD threshold voltage
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700212 * @alarm_low_mv: the battery alarm voltage low
213 * @alarm_high_mv: the battery alarm voltage high
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800214 * @cool_temp_dc: the cool temp threshold in deciCelcius
215 * @warm_temp_dc: the warm temp threshold in deciCelcius
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -0700216 * @resume_voltage_delta: the voltage delta from vdd max at which the
217 * battery should resume charging
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218 * @term_current: The charging based term current
219 *
220 */
221struct pm8921_chg_chip {
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700222 struct device *dev;
223 unsigned int usb_present;
224 unsigned int dc_present;
225 unsigned int usb_charger_current;
226 unsigned int max_bat_chg_current;
227 unsigned int pmic_chg_irq[PM_CHG_MAX_INTS];
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700228 unsigned int ttrkl_time;
229 unsigned int update_time;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800230 unsigned int max_voltage_mv;
231 unsigned int min_voltage_mv;
David Keitel0789fc62012-06-07 17:43:27 -0700232 unsigned int uvd_voltage_mv;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700233 unsigned int safe_current_ma;
234 unsigned int alarm_low_mv;
235 unsigned int alarm_high_mv;
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -0800236 int cool_temp_dc;
237 int warm_temp_dc;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700238 unsigned int temp_check_period;
239 unsigned int cool_bat_chg_current;
240 unsigned int warm_bat_chg_current;
241 unsigned int cool_bat_voltage;
242 unsigned int warm_bat_voltage;
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -0700243 unsigned int is_bat_cool;
244 unsigned int is_bat_warm;
245 unsigned int resume_voltage_delta;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700246 int resume_charge_percent;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700247 unsigned int term_current;
248 unsigned int vbat_channel;
249 unsigned int batt_temp_channel;
250 unsigned int batt_id_channel;
251 struct power_supply usb_psy;
David Keitel6ed71a52012-01-30 12:42:18 -0800252 struct power_supply dc_psy;
David Keitel88e1b572012-01-11 11:57:14 -0800253 struct power_supply *ext_psy;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700254 struct power_supply batt_psy;
255 struct dentry *dent;
256 struct bms_notify bms_notify;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700257 int *usb_trim_table;
258 struct regulator *vreg_xoadc;
Amir Samuelovd31ef502011-10-26 14:41:36 +0200259 bool ext_charging;
260 bool ext_charge_done;
David Keitel38bdd4f2012-04-19 15:39:13 -0700261 bool iusb_fine_res;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700262 bool final_kickstart;
263 bool lockup_lpm_wrkarnd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700264 DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700265 struct work_struct battery_id_valid_work;
266 int64_t batt_id_min;
267 int64_t batt_id_max;
268 int trkl_voltage;
269 int weak_voltage;
270 int trkl_current;
271 int weak_current;
272 int vin_min;
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -0800273 unsigned int *thermal_mitigation;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700274 int thermal_levels;
275 struct delayed_work update_heartbeat_work;
276 struct delayed_work eoc_work;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -0800277 struct delayed_work unplug_check_work;
David Keitelacf57c82012-03-07 18:48:50 -0800278 struct delayed_work vin_collapse_check_work;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700279 struct delayed_work btc_override_work;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700280 struct wake_lock eoc_wake_lock;
281 enum pm8921_chg_cold_thr cold_thr;
282 enum pm8921_chg_hot_thr hot_thr;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -0800283 int rconn_mohm;
Jay Chokshid674a512012-03-15 14:06:04 -0700284 enum pm8921_chg_led_src_config led_src_config;
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -0700285 bool host_mode;
David Keitelff4f9ce2012-08-24 15:11:23 -0700286 bool has_dc_supply;
David Keitel6ccbf132012-05-30 14:21:24 -0700287 u8 active_path;
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -0700288 int recent_reported_soc;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700289 int battery_less_hardware;
290 int ibatmax_max_adj_ma;
291 int btc_override;
292 int btc_override_cold_decidegc;
293 int btc_override_hot_decidegc;
294 int btc_delay_ms;
295 bool btc_panic_if_cant_stop_chg;
296 int stop_chg_upon_expiry;
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -0800297 bool disable_aicl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298};
299
David Keitelacf57c82012-03-07 18:48:50 -0800300/* user space parameter to limit usb current */
301static unsigned int usb_max_current;
302/*
303 * usb_target_ma is used for wall charger
304 * adaptive input current limiting only. Use
305 * pm_iusbmax_get() to get current maximum usb current setting.
306 */
307static int usb_target_ma;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308static int charging_disabled;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -0700309static int thermal_mitigation;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700310
311static struct pm8921_chg_chip *the_chip;
312
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700313static DEFINE_SPINLOCK(lpm_lock);
314#define LPM_ENABLE_BIT BIT(2)
315static int pm8921_chg_set_lpm(struct pm8921_chg_chip *chip, int enable)
316{
317 int rc;
318 u8 reg;
319
320 rc = pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &reg);
321 if (rc) {
322 pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n",
323 CHG_CNTRL, rc);
324 return rc;
325 }
326 reg &= ~LPM_ENABLE_BIT;
327 reg |= (enable ? LPM_ENABLE_BIT : 0);
328
329 rc = pm8xxx_writeb(chip->dev->parent, CHG_CNTRL, reg);
330 if (rc) {
331 pr_err("pm_chg_write failed: addr=%03X, rc=%d\n",
332 CHG_CNTRL, rc);
333 return rc;
334 }
335
336 return rc;
337}
338
339static int pm_chg_write(struct pm8921_chg_chip *chip, u16 addr, u8 reg)
340{
341 int rc;
342 unsigned long flags = 0;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800343 u8 temp;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700344
345 /* Disable LPM */
346 if (chip->lockup_lpm_wrkarnd) {
347 spin_lock_irqsave(&lpm_lock, flags);
348
349 /*
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800350 * This delay is to prevent exit out of 32khz mode within
351 * 200uS. It could be that chg was removed just few uS before
352 * this gets called.
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700353 */
354 udelay(200);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800355 /* no clks */
356 temp = 0xD1;
357 rc = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
358 if (rc) {
359 pr_err("Error %d writing %d to CHG_TEST\n", rc, temp);
360 goto release_lpm_lock;
361 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700362
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800363 /* force 19.2Mhz before reading */
364 temp = 0xD3;
365 rc = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
366 if (rc) {
367 pr_err("Error %d writing %d to CHG_TEST\n", rc, temp);
368 goto release_lpm_lock;
369 }
370
371 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
372 if (rc) {
373 pr_err("failed: addr=%03X, rc=%d\n", addr, rc);
374 goto release_lpm_lock;
375 }
376
377 /* no clks */
378 temp = 0xD1;
379 rc = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
380 if (rc) {
381 pr_err("Error %d writing %d to CHG_TEST\n", rc, temp);
382 goto release_lpm_lock;
383 }
384
385 /* switch to hw clk selection */
386 temp = 0xD0;
387 rc = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
388 if (rc) {
389 pr_err("Error %d writing %d to CHG_TEST\n", rc, temp);
390 goto release_lpm_lock;
391 }
392
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700393 udelay(200);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700394
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800395release_lpm_lock:
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700396 spin_unlock_irqrestore(&lpm_lock, flags);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800397 } else {
398 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
399 if (rc)
400 pr_err("failed: addr=%03X, rc=%d\n", addr, rc);
401 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700402 return rc;
403}
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -0700404
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr,
406 u8 mask, u8 val)
407{
408 int rc;
409 u8 reg;
410
411 rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
412 if (rc) {
413 pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n", addr, rc);
414 return rc;
415 }
416 reg &= ~mask;
417 reg |= val & mask;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700418 rc = pm_chg_write(chip, addr, reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700419 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700420 pr_err("pm_chg_write failed: addr=%03X, rc=%d\n", addr, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700421 return rc;
422 }
423 return 0;
424}
425
David Keitelcf867232012-01-27 18:40:12 -0800426static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
427{
428 return pm8xxx_read_irq_stat(chip->dev->parent,
429 chip->pmic_chg_irq[irq_id]);
430}
431
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700432static int is_chg_on_bat(struct pm8921_chg_chip *chip)
433{
434 return !(pm_chg_get_rt_status(chip, DCIN_VALID_IRQ)
435 || pm_chg_get_rt_status(chip, USBIN_VALID_IRQ));
436}
437
438static void pm8921_chg_bypass_bat_gone_debounce(struct pm8921_chg_chip *chip,
439 int bypass)
440{
441 int rc;
442
443 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, bypass ? 0x89 : 0x88);
444 if (rc) {
445 pr_err("Failed to set bypass bit to %d rc=%d\n", bypass, rc);
446 }
447}
448
David Keitelcf867232012-01-27 18:40:12 -0800449/* Treat OverVoltage/UnderVoltage as source missing */
450static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
451{
452 return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
453}
454
455/* Treat OverVoltage/UnderVoltage as source missing */
456static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
457{
458 return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
459}
460
Abhijeet Dharmapurikarb2680132012-05-15 16:32:51 -0700461static int is_batfet_closed(struct pm8921_chg_chip *chip)
462{
463 return pm_chg_get_rt_status(chip, BATFET_IRQ);
464}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700465#define CAPTURE_FSM_STATE_CMD 0xC2
466#define READ_BANK_7 0x70
467#define READ_BANK_4 0x40
468static int pm_chg_get_fsm_state(struct pm8921_chg_chip *chip)
469{
470 u8 temp;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800471 unsigned long flags = 0;
472 int err = 0, ret = 0;
473
474 if (chip->lockup_lpm_wrkarnd) {
475 spin_lock_irqsave(&lpm_lock, flags);
476
477 /*
478 * This delay is to prevent exit out of 32khz mode within
479 * 200uS. It could be that chg was removed just few uS before
480 * this gets called.
481 */
482 udelay(200);
483 /* no clks */
484 temp = 0xD1;
485 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
486 if (err) {
487 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
488 goto err_out;
489 }
490
491 /* force 19.2Mhz before reading */
492 temp = 0xD3;
493 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
494 if (err) {
495 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
496 goto err_out;
497 }
498 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700499
500 temp = CAPTURE_FSM_STATE_CMD;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800501 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700502 if (err) {
503 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800504 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700505 }
506
507 temp = READ_BANK_7;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800508 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509 if (err) {
510 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800511 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700512 }
513
514 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
515 if (err) {
516 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800517 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518 }
519 /* get the lower 4 bits */
520 ret = temp & 0xF;
521
522 temp = READ_BANK_4;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800523 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700524 if (err) {
525 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800526 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700527 }
528
529 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
530 if (err) {
531 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800532 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700533 }
534 /* get the upper 1 bit */
535 ret |= (temp & 0x1) << 4;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800536
537 if (chip->lockup_lpm_wrkarnd) {
538 /* no clks */
539 temp = 0xD1;
540 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
541 if (err) {
542 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
543 goto err_out;
544 }
545
546 /* switch to hw clk selection */
547 temp = 0xD0;
548 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
549 if (err) {
550 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
551 goto err_out;
552 }
553
554 udelay(200);
555 }
556
557err_out:
558 if (chip->lockup_lpm_wrkarnd)
559 spin_unlock_irqrestore(&lpm_lock, flags);
560 if (err)
561 return err;
562
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 return ret;
564}
565
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700566#define READ_BANK_6 0x60
567static int pm_chg_get_regulation_loop(struct pm8921_chg_chip *chip)
568{
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800569 u8 temp, data;
570 unsigned long flags = 0;
571 int err = 0;
572
573 if (chip->lockup_lpm_wrkarnd) {
574 spin_lock_irqsave(&lpm_lock, flags);
575
576 /*
577 * This delay is to prevent exit out of 32khz mode within
578 * 200uS. It could be that chg was removed just few uS before
579 * this gets called.
580 */
581 udelay(200);
582 /* no clks */
583 temp = 0xD1;
584 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
585 if (err) {
586 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
587 goto err_out;
588 }
589
590 /* force 19.2Mhz before reading */
591 temp = 0xD3;
592 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
593 if (err) {
594 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
595 goto err_out;
596 }
597 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700598
599 temp = READ_BANK_6;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800600 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700601 if (err) {
602 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800603 goto err_out;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700604 }
605
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800606 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &data);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700607 if (err) {
608 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800609 goto err_out;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700610 }
611
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800612 if (chip->lockup_lpm_wrkarnd) {
613 /* no clks */
614 temp = 0xD1;
615 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
616 if (err) {
617 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
618 goto err_out;
619 }
620
621 /* switch to hw clk selection */
622 temp = 0xD0;
623 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
624 if (err) {
625 pr_err("Error %d writing %d to CHG_TEST\n", err, temp);
626 goto err_out;
627 }
628
629 udelay(200);
630 }
631
632err_out:
633 if (chip->lockup_lpm_wrkarnd)
634 spin_unlock_irqrestore(&lpm_lock, flags);
635 if (err)
636 return err;
637
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700638 /* return the lower 4 bits */
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800639 return data & CHG_ALL_LOOPS;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700640}
641
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642#define CHG_USB_SUSPEND_BIT BIT(2)
643static int pm_chg_usb_suspend_enable(struct pm8921_chg_chip *chip, int enable)
644{
645 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_USB_SUSPEND_BIT,
646 enable ? CHG_USB_SUSPEND_BIT : 0);
647}
648
649#define CHG_EN_BIT BIT(7)
650static int pm_chg_auto_enable(struct pm8921_chg_chip *chip, int enable)
651{
652 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_EN_BIT,
653 enable ? CHG_EN_BIT : 0);
654}
655
David Keitel753ec8d2011-11-02 10:56:37 -0700656#define CHG_FAILED_CLEAR BIT(0)
657#define ATC_FAILED_CLEAR BIT(1)
658static int pm_chg_failed_clear(struct pm8921_chg_chip *chip, int clear)
659{
660 int rc;
661
662 rc = pm_chg_masked_write(chip, CHG_CNTRL_3, ATC_FAILED_CLEAR,
663 clear ? ATC_FAILED_CLEAR : 0);
664 rc |= pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_FAILED_CLEAR,
665 clear ? CHG_FAILED_CLEAR : 0);
666 return rc;
667}
668
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700669#define CHG_CHARGE_DIS_BIT BIT(1)
670static int pm_chg_charge_dis(struct pm8921_chg_chip *chip, int disable)
671{
672 return pm_chg_masked_write(chip, CHG_CNTRL, CHG_CHARGE_DIS_BIT,
673 disable ? CHG_CHARGE_DIS_BIT : 0);
674}
675
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -0800676static int pm_is_chg_charge_dis(struct pm8921_chg_chip *chip)
677{
678 u8 temp;
679
680 pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
681 return temp & CHG_CHARGE_DIS_BIT;
682}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683#define PM8921_CHG_V_MIN_MV 3240
684#define PM8921_CHG_V_STEP_MV 20
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800685#define PM8921_CHG_V_STEP_10MV_OFFSET_BIT BIT(7)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700686#define PM8921_CHG_VDDMAX_MAX 4500
687#define PM8921_CHG_VDDMAX_MIN 3400
688#define PM8921_CHG_V_MASK 0x7F
David Keitelcf867232012-01-27 18:40:12 -0800689static int __pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690{
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800691 int remainder;
David Keitelcf867232012-01-27 18:40:12 -0800692 u8 temp = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800694 if (voltage < PM8921_CHG_VDDMAX_MIN
695 || voltage > PM8921_CHG_VDDMAX_MAX) {
696 pr_err("bad mV=%d asked to set\n", voltage);
697 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700698 }
David Keitelcf867232012-01-27 18:40:12 -0800699
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800700 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
701
702 remainder = voltage % 20;
703 if (remainder >= 10) {
704 temp |= PM8921_CHG_V_STEP_10MV_OFFSET_BIT;
705 }
706
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 pr_debug("voltage=%d setting %02x\n", voltage, temp);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700708 return pm_chg_write(chip, CHG_VDD_MAX, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700709}
710
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700711static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
712{
713 u8 temp;
714 int rc;
715
716 rc = pm8xxx_readb(chip->dev->parent, CHG_VDD_MAX, &temp);
717 if (rc) {
718 pr_err("rc = %d while reading vdd max\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700719 *voltage = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700720 return rc;
721 }
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800722 *voltage = (int)(temp & PM8921_CHG_V_MASK) * PM8921_CHG_V_STEP_MV
723 + PM8921_CHG_V_MIN_MV;
724 if (temp & PM8921_CHG_V_STEP_10MV_OFFSET_BIT)
725 *voltage = *voltage + 10;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700726 return 0;
727}
728
David Keitelcf867232012-01-27 18:40:12 -0800729static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
730{
731 int current_mv, ret, steps, i;
732 bool increase;
733
734 ret = 0;
735
736 if (voltage < PM8921_CHG_VDDMAX_MIN
737 || voltage > PM8921_CHG_VDDMAX_MAX) {
738 pr_err("bad mV=%d asked to set\n", voltage);
739 return -EINVAL;
740 }
741
742 ret = pm_chg_vddmax_get(chip, &current_mv);
743 if (ret) {
744 pr_err("Failed to read vddmax rc=%d\n", ret);
745 return -EINVAL;
746 }
747 if (current_mv == voltage)
748 return 0;
749
750 /* Only change in increments when USB is present */
751 if (is_usb_chg_plugged_in(chip)) {
752 if (current_mv < voltage) {
753 steps = (voltage - current_mv) / PM8921_CHG_V_STEP_MV;
754 increase = true;
755 } else {
756 steps = (current_mv - voltage) / PM8921_CHG_V_STEP_MV;
757 increase = false;
758 }
759 for (i = 0; i < steps; i++) {
760 if (increase)
761 current_mv += PM8921_CHG_V_STEP_MV;
762 else
763 current_mv -= PM8921_CHG_V_STEP_MV;
764 ret |= __pm_chg_vddmax_set(chip, current_mv);
765 }
766 }
767 ret |= __pm_chg_vddmax_set(chip, voltage);
768 return ret;
769}
770
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700771#define PM8921_CHG_VDDSAFE_MIN 3400
772#define PM8921_CHG_VDDSAFE_MAX 4500
773static int pm_chg_vddsafe_set(struct pm8921_chg_chip *chip, int voltage)
774{
775 u8 temp;
776
777 if (voltage < PM8921_CHG_VDDSAFE_MIN
778 || voltage > PM8921_CHG_VDDSAFE_MAX) {
779 pr_err("bad mV=%d asked to set\n", voltage);
780 return -EINVAL;
781 }
782 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
783 pr_debug("voltage=%d setting %02x\n", voltage, temp);
784 return pm_chg_masked_write(chip, CHG_VDD_SAFE, PM8921_CHG_V_MASK, temp);
785}
786
787#define PM8921_CHG_VBATDET_MIN 3240
788#define PM8921_CHG_VBATDET_MAX 5780
789static int pm_chg_vbatdet_set(struct pm8921_chg_chip *chip, int voltage)
790{
791 u8 temp;
792
793 if (voltage < PM8921_CHG_VBATDET_MIN
794 || voltage > PM8921_CHG_VBATDET_MAX) {
795 pr_err("bad mV=%d asked to set\n", voltage);
796 return -EINVAL;
797 }
798 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
799 pr_debug("voltage=%d setting %02x\n", voltage, temp);
800 return pm_chg_masked_write(chip, CHG_VBAT_DET, PM8921_CHG_V_MASK, temp);
801}
802
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -0700803#define PM8921_CHG_VINMIN_MIN_MV 3800
804#define PM8921_CHG_VINMIN_STEP_MV 100
805#define PM8921_CHG_VINMIN_USABLE_MAX 6500
806#define PM8921_CHG_VINMIN_USABLE_MIN 4300
807#define PM8921_CHG_VINMIN_MASK 0x1F
808static int pm_chg_vinmin_set(struct pm8921_chg_chip *chip, int voltage)
809{
810 u8 temp;
811
812 if (voltage < PM8921_CHG_VINMIN_USABLE_MIN
813 || voltage > PM8921_CHG_VINMIN_USABLE_MAX) {
814 pr_err("bad mV=%d asked to set\n", voltage);
815 return -EINVAL;
816 }
817 temp = (voltage - PM8921_CHG_VINMIN_MIN_MV) / PM8921_CHG_VINMIN_STEP_MV;
818 pr_debug("voltage=%d setting %02x\n", voltage, temp);
819 return pm_chg_masked_write(chip, CHG_VIN_MIN, PM8921_CHG_VINMIN_MASK,
820 temp);
821}
822
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -0800823static int pm_chg_vinmin_get(struct pm8921_chg_chip *chip)
824{
825 u8 temp;
826 int rc, voltage_mv;
827
828 rc = pm8xxx_readb(chip->dev->parent, CHG_VIN_MIN, &temp);
829 temp &= PM8921_CHG_VINMIN_MASK;
830
831 voltage_mv = PM8921_CHG_VINMIN_MIN_MV +
832 (int)temp * PM8921_CHG_VINMIN_STEP_MV;
833
834 return voltage_mv;
835}
836
David Keitel0789fc62012-06-07 17:43:27 -0700837#define PM8917_USB_UVD_MIN_MV 3850
838#define PM8917_USB_UVD_MAX_MV 4350
839#define PM8917_USB_UVD_STEP_MV 100
840#define PM8917_USB_UVD_MASK 0x7
841static int pm_chg_uvd_threshold_set(struct pm8921_chg_chip *chip, int thresh_mv)
842{
843 u8 temp;
844
845 if (thresh_mv < PM8917_USB_UVD_MIN_MV
846 || thresh_mv > PM8917_USB_UVD_MAX_MV) {
847 pr_err("bad mV=%d asked to set\n", thresh_mv);
848 return -EINVAL;
849 }
850 temp = (thresh_mv - PM8917_USB_UVD_MIN_MV) / PM8917_USB_UVD_STEP_MV;
851 return pm_chg_masked_write(chip, OVP_USB_UVD,
852 PM8917_USB_UVD_MASK, temp);
853}
854
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700855#define PM8921_CHG_IBATMAX_MIN 325
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700856#define PM8921_CHG_IBATMAX_MAX 3025
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700857#define PM8921_CHG_I_MIN_MA 225
858#define PM8921_CHG_I_STEP_MA 50
859#define PM8921_CHG_I_MASK 0x3F
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700860static int pm_chg_ibatmax_get(struct pm8921_chg_chip *chip, int *ibat_ma)
861{
862 u8 temp;
863 int rc;
864
865 rc = pm8xxx_readb(chip->dev->parent, CHG_IBAT_MAX, &temp);
866 if (rc) {
867 pr_err("rc = %d while reading ibat max\n", rc);
868 *ibat_ma = 0;
869 return rc;
870 }
871 *ibat_ma = (int)(temp & PM8921_CHG_I_MASK) * PM8921_CHG_I_STEP_MA
872 + PM8921_CHG_I_MIN_MA;
873 return 0;
874}
875
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700876static int pm_chg_ibatmax_set(struct pm8921_chg_chip *chip, int chg_current)
877{
878 u8 temp;
879
880 if (chg_current < PM8921_CHG_IBATMAX_MIN
881 || chg_current > PM8921_CHG_IBATMAX_MAX) {
882 pr_err("bad mA=%d asked to set\n", chg_current);
883 return -EINVAL;
884 }
885 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
886 return pm_chg_masked_write(chip, CHG_IBAT_MAX, PM8921_CHG_I_MASK, temp);
887}
888
889#define PM8921_CHG_IBATSAFE_MIN 225
890#define PM8921_CHG_IBATSAFE_MAX 3375
891static int pm_chg_ibatsafe_set(struct pm8921_chg_chip *chip, int chg_current)
892{
893 u8 temp;
894
895 if (chg_current < PM8921_CHG_IBATSAFE_MIN
896 || chg_current > PM8921_CHG_IBATSAFE_MAX) {
897 pr_err("bad mA=%d asked to set\n", chg_current);
898 return -EINVAL;
899 }
900 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
901 return pm_chg_masked_write(chip, CHG_IBAT_SAFE,
902 PM8921_CHG_I_MASK, temp);
903}
904
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905#define PM8921_CHG_ITERM_MIN_MA 50
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700906#define PM8921_CHG_ITERM_MAX_MA 200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700907#define PM8921_CHG_ITERM_STEP_MA 10
908#define PM8921_CHG_ITERM_MASK 0xF
909static int pm_chg_iterm_set(struct pm8921_chg_chip *chip, int chg_current)
910{
911 u8 temp;
912
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700913 if (chg_current < PM8921_CHG_ITERM_MIN_MA
914 || chg_current > PM8921_CHG_ITERM_MAX_MA) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915 pr_err("bad mA=%d asked to set\n", chg_current);
916 return -EINVAL;
917 }
918
919 temp = (chg_current - PM8921_CHG_ITERM_MIN_MA)
920 / PM8921_CHG_ITERM_STEP_MA;
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700921 return pm_chg_masked_write(chip, CHG_ITERM, PM8921_CHG_ITERM_MASK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700922 temp);
923}
924
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700925static int pm_chg_iterm_get(struct pm8921_chg_chip *chip, int *chg_current)
926{
927 u8 temp;
928 int rc;
929
930 rc = pm8xxx_readb(chip->dev->parent, CHG_ITERM, &temp);
931 if (rc) {
932 pr_err("err=%d reading CHG_ITEM\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700933 *chg_current = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700934 return rc;
935 }
936 temp &= PM8921_CHG_ITERM_MASK;
937 *chg_current = (int)temp * PM8921_CHG_ITERM_STEP_MA
938 + PM8921_CHG_ITERM_MIN_MA;
939 return 0;
940}
941
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800942struct usb_ma_limit_entry {
David Keitel38bdd4f2012-04-19 15:39:13 -0700943 int usb_ma;
944 u8 value;
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800945};
946
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700947/* USB Trim tables */
948static int usb_trim_8038_table[USB_TRIM_ENTRIES] = {
949 0x0,
950 0x0,
951 -0x9,
952 0x0,
953 -0xD,
954 0x0,
955 -0x10,
956 -0x11,
957 0x0,
958 0x0,
959 -0x25,
960 0x0,
961 -0x28,
962 0x0,
963 -0x32,
964 0x0
965};
966
967static int usb_trim_8917_table[USB_TRIM_ENTRIES] = {
968 0x0,
969 0x0,
970 0xA,
971 0xC,
972 0x10,
973 0x10,
974 0x13,
975 0x14,
976 0x13,
977 0x3,
978 0x1A,
979 0x1D,
980 0x1D,
981 0x21,
982 0x24,
983 0x26
984};
985
986/* Maximum USB setting table */
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800987static struct usb_ma_limit_entry usb_ma_table[] = {
David Keitel38bdd4f2012-04-19 15:39:13 -0700988 {100, 0x0},
989 {200, 0x1},
990 {500, 0x2},
991 {600, 0x3},
992 {700, 0x4},
993 {800, 0x5},
994 {850, 0x6},
995 {900, 0x8},
996 {950, 0x7},
997 {1000, 0x9},
998 {1100, 0xA},
999 {1200, 0xB},
1000 {1300, 0xC},
1001 {1400, 0xD},
1002 {1500, 0xE},
1003 {1600, 0xF},
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001004};
1005
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001006#define REG_SBI_CONFIG 0x04F
1007#define PAGE3_ENABLE_MASK 0x6
1008#define USB_OVP_TRIM_MASK 0x3F
1009#define USB_OVP_TRIM_PM8917_MASK 0x7F
1010#define USB_OVP_TRIM_MIN 0x00
1011#define REG_USB_OVP_TRIM_ORIG_LSB 0x10A
1012#define REG_USB_OVP_TRIM_ORIG_MSB 0x09C
1013#define REG_USB_OVP_TRIM_PM8917 0x2B5
1014#define REG_USB_OVP_TRIM_PM8917_BIT BIT(0)
1015static int pm_chg_usb_trim(struct pm8921_chg_chip *chip, int index)
1016{
1017 u8 temp, sbi_config, msb, lsb, mask;
1018 s8 trim;
1019 int rc = 0;
1020 static u8 usb_trim_reg_orig = 0xFF;
1021
1022 /* No trim data for PM8921 */
1023 if (!chip->usb_trim_table)
1024 return 0;
1025
1026 if (usb_trim_reg_orig == 0xFF) {
1027 rc = pm8xxx_readb(chip->dev->parent,
1028 REG_USB_OVP_TRIM_ORIG_MSB, &msb);
1029 if (rc) {
1030 pr_err("error = %d reading sbi config reg\n", rc);
1031 return rc;
1032 }
1033
1034 rc = pm8xxx_readb(chip->dev->parent,
1035 REG_USB_OVP_TRIM_ORIG_LSB, &lsb);
1036 if (rc) {
1037 pr_err("error = %d reading sbi config reg\n", rc);
1038 return rc;
1039 }
1040
1041 msb = msb >> 5;
1042 lsb = lsb >> 5;
1043 usb_trim_reg_orig = msb << 3 | lsb;
1044
1045 if (pm8xxx_get_version(chip->dev->parent)
1046 == PM8XXX_VERSION_8917) {
1047 rc = pm8xxx_readb(chip->dev->parent,
1048 REG_USB_OVP_TRIM_PM8917, &msb);
1049 if (rc) {
1050 pr_err("error = %d reading config reg\n", rc);
1051 return rc;
1052 }
1053
1054 msb = msb & REG_USB_OVP_TRIM_PM8917_BIT;
1055 usb_trim_reg_orig |= msb << 6;
1056 }
1057 }
1058
1059 /* use the original trim value */
1060 trim = usb_trim_reg_orig;
1061
1062 trim += chip->usb_trim_table[index];
1063 if (trim < 0)
1064 trim = 0;
1065
1066 pr_debug("trim_orig %d write 0x%x index=%d value 0x%x to USB_OVP_TRIM\n",
1067 usb_trim_reg_orig, trim, index, chip->usb_trim_table[index]);
1068
1069 rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, &sbi_config);
1070 if (rc) {
1071 pr_err("error = %d reading sbi config reg\n", rc);
1072 return rc;
1073 }
1074
1075 temp = sbi_config | PAGE3_ENABLE_MASK;
1076 rc = pm_chg_write(chip, REG_SBI_CONFIG, temp);
1077 if (rc) {
1078 pr_err("error = %d writing sbi config reg\n", rc);
1079 return rc;
1080 }
1081
1082 mask = USB_OVP_TRIM_MASK;
1083
1084 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
1085 mask = USB_OVP_TRIM_PM8917_MASK;
1086
1087 rc = pm_chg_masked_write(chip, USB_OVP_TRIM, mask, trim);
1088 if (rc) {
1089 pr_err("error = %d writing USB_OVP_TRIM\n", rc);
1090 return rc;
1091 }
1092
1093 rc = pm_chg_write(chip, REG_SBI_CONFIG, sbi_config);
1094 if (rc) {
1095 pr_err("error = %d writing sbi config reg\n", rc);
1096 return rc;
1097 }
1098 return rc;
1099}
1100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001101#define PM8921_CHG_IUSB_MASK 0x1C
David Keitel38bdd4f2012-04-19 15:39:13 -07001102#define PM8921_CHG_IUSB_SHIFT 2
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001103#define PM8921_CHG_IUSB_MAX 7
1104#define PM8921_CHG_IUSB_MIN 0
David Keitel38bdd4f2012-04-19 15:39:13 -07001105#define PM8917_IUSB_FINE_RES BIT(0)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001106static int pm_chg_iusbmax_set(struct pm8921_chg_chip *chip, int index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001107{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001108 u8 temp, fineres, reg_val;
David Keitel38bdd4f2012-04-19 15:39:13 -07001109 int rc;
1110
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001111 reg_val = usb_ma_table[index].value >> 1;
1112 fineres = PM8917_IUSB_FINE_RES & usb_ma_table[index].value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001113
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -07001114 if (reg_val < PM8921_CHG_IUSB_MIN || reg_val > PM8921_CHG_IUSB_MAX) {
1115 pr_err("bad mA=%d asked to set\n", reg_val);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001116 return -EINVAL;
1117 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001118 temp = reg_val << PM8921_CHG_IUSB_SHIFT;
1119
1120 /* IUSB_FINE_RES */
1121 if (chip->iusb_fine_res) {
1122 /* Clear IUSB_FINE_RES bit to avoid overshoot */
1123 rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
1124 PM8917_IUSB_FINE_RES, 0);
1125
1126 rc |= pm_chg_masked_write(chip, PBL_ACCESS2,
1127 PM8921_CHG_IUSB_MASK, temp);
1128
1129 if (rc) {
1130 pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
1131 return rc;
1132 }
1133
1134 if (fineres) {
1135 rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
1136 PM8917_IUSB_FINE_RES, fineres);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001137 if (rc) {
David Keitel38bdd4f2012-04-19 15:39:13 -07001138 pr_err("Failed to write ISUB_FINE_RES rc=%d\n",
1139 rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001140 return rc;
1141 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001142 }
1143 } else {
1144 rc = pm_chg_masked_write(chip, PBL_ACCESS2,
1145 PM8921_CHG_IUSB_MASK, temp);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001146 if (rc) {
David Keitel38bdd4f2012-04-19 15:39:13 -07001147 pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001148 return rc;
1149 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001150 }
1151
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001152 rc = pm_chg_usb_trim(chip, index);
1153 if (rc)
1154 pr_err("unable to set usb trim rc = %d\n", rc);
1155
David Keitel38bdd4f2012-04-19 15:39:13 -07001156 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001157}
1158
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001159static int pm_chg_iusbmax_get(struct pm8921_chg_chip *chip, int *mA)
1160{
David Keitel38bdd4f2012-04-19 15:39:13 -07001161 u8 temp, fineres;
1162 int rc, i;
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001163
David Keitel38bdd4f2012-04-19 15:39:13 -07001164 fineres = 0;
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001165 *mA = 0;
1166 rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS2, &temp);
1167 if (rc) {
1168 pr_err("err=%d reading PBL_ACCESS2\n", rc);
1169 return rc;
1170 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001171
1172 if (chip->iusb_fine_res) {
1173 rc = pm8xxx_readb(chip->dev->parent, IUSB_FINE_RES, &fineres);
1174 if (rc) {
1175 pr_err("err=%d reading IUSB_FINE_RES\n", rc);
1176 return rc;
1177 }
1178 }
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001179 temp &= PM8921_CHG_IUSB_MASK;
David Keitel38bdd4f2012-04-19 15:39:13 -07001180 temp = temp >> PM8921_CHG_IUSB_SHIFT;
1181
1182 temp = (temp << 1) | (fineres & PM8917_IUSB_FINE_RES);
1183 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
1184 if (usb_ma_table[i].value == temp)
1185 break;
1186 }
1187
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001188 if (i < 0) {
1189 pr_err("can't find %d in usb_ma_table. Use min.\n", temp);
1190 i = 0;
1191 }
1192
David Keitel38bdd4f2012-04-19 15:39:13 -07001193 *mA = usb_ma_table[i].usb_ma;
1194
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001195 return rc;
1196}
1197
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001198#define PM8921_CHG_WD_MASK 0x1F
1199static int pm_chg_disable_wd(struct pm8921_chg_chip *chip)
1200{
1201 /* writing 0 to the wd timer disables it */
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001202 return pm_chg_masked_write(chip, CHG_TWDOG, PM8921_CHG_WD_MASK, 0);
1203}
1204
Abhijeet Dharmapurikarc26cd902011-10-26 18:07:45 -07001205#define PM8921_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001206#define PM8921_CHG_TCHG_MIN 4
1207#define PM8921_CHG_TCHG_MAX 512
1208#define PM8921_CHG_TCHG_STEP 4
1209static int pm_chg_tchg_max_set(struct pm8921_chg_chip *chip, int minutes)
1210{
1211 u8 temp;
1212
1213 if (minutes < PM8921_CHG_TCHG_MIN || minutes > PM8921_CHG_TCHG_MAX) {
1214 pr_err("bad max minutes =%d asked to set\n", minutes);
1215 return -EINVAL;
1216 }
1217
1218 temp = (minutes - 1)/PM8921_CHG_TCHG_STEP;
1219 return pm_chg_masked_write(chip, CHG_TCHG_MAX, PM8921_CHG_TCHG_MASK,
1220 temp);
1221}
1222
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001223#define PM8921_CHG_TTRKL_MASK 0x3F
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001224#define PM8921_CHG_TTRKL_MIN 1
1225#define PM8921_CHG_TTRKL_MAX 64
1226static int pm_chg_ttrkl_max_set(struct pm8921_chg_chip *chip, int minutes)
1227{
1228 u8 temp;
1229
1230 if (minutes < PM8921_CHG_TTRKL_MIN || minutes > PM8921_CHG_TTRKL_MAX) {
1231 pr_err("bad max minutes =%d asked to set\n", minutes);
1232 return -EINVAL;
1233 }
1234
1235 temp = minutes - 1;
1236 return pm_chg_masked_write(chip, CHG_TTRKL_MAX, PM8921_CHG_TTRKL_MASK,
1237 temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001238}
1239
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07001240#define PM8921_CHG_VTRKL_MIN_MV 2050
1241#define PM8921_CHG_VTRKL_MAX_MV 2800
1242#define PM8921_CHG_VTRKL_STEP_MV 50
1243#define PM8921_CHG_VTRKL_SHIFT 4
1244#define PM8921_CHG_VTRKL_MASK 0xF0
1245static int pm_chg_vtrkl_low_set(struct pm8921_chg_chip *chip, int millivolts)
1246{
1247 u8 temp;
1248
1249 if (millivolts < PM8921_CHG_VTRKL_MIN_MV
1250 || millivolts > PM8921_CHG_VTRKL_MAX_MV) {
1251 pr_err("bad voltage = %dmV asked to set\n", millivolts);
1252 return -EINVAL;
1253 }
1254
1255 temp = (millivolts - PM8921_CHG_VTRKL_MIN_MV)/PM8921_CHG_VTRKL_STEP_MV;
1256 temp = temp << PM8921_CHG_VTRKL_SHIFT;
1257 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VTRKL_MASK,
1258 temp);
1259}
1260
1261#define PM8921_CHG_VWEAK_MIN_MV 2100
1262#define PM8921_CHG_VWEAK_MAX_MV 3600
1263#define PM8921_CHG_VWEAK_STEP_MV 100
1264#define PM8921_CHG_VWEAK_MASK 0x0F
1265static int pm_chg_vweak_set(struct pm8921_chg_chip *chip, int millivolts)
1266{
1267 u8 temp;
1268
1269 if (millivolts < PM8921_CHG_VWEAK_MIN_MV
1270 || millivolts > PM8921_CHG_VWEAK_MAX_MV) {
1271 pr_err("bad voltage = %dmV asked to set\n", millivolts);
1272 return -EINVAL;
1273 }
1274
1275 temp = (millivolts - PM8921_CHG_VWEAK_MIN_MV)/PM8921_CHG_VWEAK_STEP_MV;
1276 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VWEAK_MASK,
1277 temp);
1278}
1279
1280#define PM8921_CHG_ITRKL_MIN_MA 50
1281#define PM8921_CHG_ITRKL_MAX_MA 200
1282#define PM8921_CHG_ITRKL_MASK 0x0F
1283#define PM8921_CHG_ITRKL_STEP_MA 10
1284static int pm_chg_itrkl_set(struct pm8921_chg_chip *chip, int milliamps)
1285{
1286 u8 temp;
1287
1288 if (milliamps < PM8921_CHG_ITRKL_MIN_MA
1289 || milliamps > PM8921_CHG_ITRKL_MAX_MA) {
1290 pr_err("bad current = %dmA asked to set\n", milliamps);
1291 return -EINVAL;
1292 }
1293
1294 temp = (milliamps - PM8921_CHG_ITRKL_MIN_MA)/PM8921_CHG_ITRKL_STEP_MA;
1295
1296 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_ITRKL_MASK,
1297 temp);
1298}
1299
1300#define PM8921_CHG_IWEAK_MIN_MA 325
1301#define PM8921_CHG_IWEAK_MAX_MA 525
1302#define PM8921_CHG_IWEAK_SHIFT 7
1303#define PM8921_CHG_IWEAK_MASK 0x80
1304static int pm_chg_iweak_set(struct pm8921_chg_chip *chip, int milliamps)
1305{
1306 u8 temp;
1307
1308 if (milliamps < PM8921_CHG_IWEAK_MIN_MA
1309 || milliamps > PM8921_CHG_IWEAK_MAX_MA) {
1310 pr_err("bad current = %dmA asked to set\n", milliamps);
1311 return -EINVAL;
1312 }
1313
1314 if (milliamps < PM8921_CHG_IWEAK_MAX_MA)
1315 temp = 0;
1316 else
1317 temp = 1;
1318
1319 temp = temp << PM8921_CHG_IWEAK_SHIFT;
1320 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_IWEAK_MASK,
1321 temp);
1322}
1323
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07001324#define PM8921_CHG_BATT_TEMP_THR_COLD BIT(1)
1325#define PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT 1
1326static int pm_chg_batt_cold_temp_config(struct pm8921_chg_chip *chip,
1327 enum pm8921_chg_cold_thr cold_thr)
1328{
1329 u8 temp;
1330
1331 temp = cold_thr << PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT;
1332 temp = temp & PM8921_CHG_BATT_TEMP_THR_COLD;
1333 return pm_chg_masked_write(chip, CHG_CNTRL_2,
1334 PM8921_CHG_BATT_TEMP_THR_COLD,
1335 temp);
1336}
1337
1338#define PM8921_CHG_BATT_TEMP_THR_HOT BIT(0)
1339#define PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT 0
1340static int pm_chg_batt_hot_temp_config(struct pm8921_chg_chip *chip,
1341 enum pm8921_chg_hot_thr hot_thr)
1342{
1343 u8 temp;
1344
1345 temp = hot_thr << PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT;
1346 temp = temp & PM8921_CHG_BATT_TEMP_THR_HOT;
1347 return pm_chg_masked_write(chip, CHG_CNTRL_2,
1348 PM8921_CHG_BATT_TEMP_THR_HOT,
1349 temp);
1350}
1351
Jay Chokshid674a512012-03-15 14:06:04 -07001352#define PM8921_CHG_LED_SRC_CONFIG_SHIFT 4
1353#define PM8921_CHG_LED_SRC_CONFIG_MASK 0x30
1354static int pm_chg_led_src_config(struct pm8921_chg_chip *chip,
1355 enum pm8921_chg_led_src_config led_src_config)
1356{
1357 u8 temp;
1358
1359 if (led_src_config < LED_SRC_GND ||
1360 led_src_config > LED_SRC_BYPASS)
1361 return -EINVAL;
1362
1363 if (led_src_config == LED_SRC_BYPASS)
1364 return 0;
1365
1366 temp = led_src_config << PM8921_CHG_LED_SRC_CONFIG_SHIFT;
1367
1368 return pm_chg_masked_write(chip, CHG_CNTRL_3,
1369 PM8921_CHG_LED_SRC_CONFIG_MASK, temp);
1370}
1371
David Keitel8c5201a2012-02-24 16:08:54 -08001372
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001373static int64_t read_battery_id(struct pm8921_chg_chip *chip)
1374{
1375 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001376 struct pm8xxx_adc_chan_result result;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001377
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001378 rc = pm8xxx_adc_read(chip->batt_id_channel, &result);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001379 if (rc) {
1380 pr_err("error reading batt id channel = %d, rc = %d\n",
1381 chip->vbat_channel, rc);
1382 return rc;
1383 }
1384 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
1385 result.measurement);
1386 return result.physical;
1387}
1388
1389static int is_battery_valid(struct pm8921_chg_chip *chip)
1390{
1391 int64_t rc;
1392
1393 if (chip->batt_id_min == 0 && chip->batt_id_max == 0)
1394 return 1;
1395
1396 rc = read_battery_id(chip);
1397 if (rc < 0) {
1398 pr_err("error reading batt id channel = %d, rc = %lld\n",
1399 chip->vbat_channel, rc);
1400 /* assume battery id is valid when adc error happens */
1401 return 1;
1402 }
1403
1404 if (rc < chip->batt_id_min || rc > chip->batt_id_max) {
1405 pr_err("batt_id phy =%lld is not valid\n", rc);
1406 return 0;
1407 }
1408 return 1;
1409}
1410
1411static void check_battery_valid(struct pm8921_chg_chip *chip)
1412{
1413 if (is_battery_valid(chip) == 0) {
1414 pr_err("batt_id not valid, disbling charging\n");
1415 pm_chg_auto_enable(chip, 0);
1416 } else {
1417 pm_chg_auto_enable(chip, !charging_disabled);
1418 }
1419}
1420
1421static void battery_id_valid(struct work_struct *work)
1422{
1423 struct pm8921_chg_chip *chip = container_of(work,
1424 struct pm8921_chg_chip, battery_id_valid_work);
1425
1426 check_battery_valid(chip);
1427}
1428
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001429static void pm8921_chg_enable_irq(struct pm8921_chg_chip *chip, int interrupt)
1430{
1431 if (!__test_and_set_bit(interrupt, chip->enabled_irqs)) {
1432 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
1433 enable_irq(chip->pmic_chg_irq[interrupt]);
1434 }
1435}
1436
1437static void pm8921_chg_disable_irq(struct pm8921_chg_chip *chip, int interrupt)
1438{
1439 if (__test_and_clear_bit(interrupt, chip->enabled_irqs)) {
1440 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
1441 disable_irq_nosync(chip->pmic_chg_irq[interrupt]);
1442 }
1443}
1444
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001445static int pm8921_chg_is_enabled(struct pm8921_chg_chip *chip, int interrupt)
1446{
1447 return test_bit(interrupt, chip->enabled_irqs);
1448}
1449
Amir Samuelovd31ef502011-10-26 14:41:36 +02001450static bool is_ext_charging(struct pm8921_chg_chip *chip)
1451{
David Keitel88e1b572012-01-11 11:57:14 -08001452 union power_supply_propval ret = {0,};
Amir Samuelovd31ef502011-10-26 14:41:36 +02001453
David Keitel88e1b572012-01-11 11:57:14 -08001454 if (!chip->ext_psy)
1455 return false;
1456 if (chip->ext_psy->get_property(chip->ext_psy,
1457 POWER_SUPPLY_PROP_CHARGE_TYPE, &ret))
1458 return false;
1459 if (ret.intval > POWER_SUPPLY_CHARGE_TYPE_NONE)
1460 return ret.intval;
Amir Samuelovd31ef502011-10-26 14:41:36 +02001461
1462 return false;
1463}
1464
1465static bool is_ext_trickle_charging(struct pm8921_chg_chip *chip)
1466{
David Keitel88e1b572012-01-11 11:57:14 -08001467 union power_supply_propval ret = {0,};
Amir Samuelovd31ef502011-10-26 14:41:36 +02001468
David Keitel88e1b572012-01-11 11:57:14 -08001469 if (!chip->ext_psy)
1470 return false;
1471 if (chip->ext_psy->get_property(chip->ext_psy,
1472 POWER_SUPPLY_PROP_CHARGE_TYPE, &ret))
1473 return false;
1474 if (ret.intval == POWER_SUPPLY_CHARGE_TYPE_TRICKLE)
Amir Samuelovd31ef502011-10-26 14:41:36 +02001475 return true;
1476
1477 return false;
1478}
1479
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001480static int is_battery_charging(int fsm_state)
1481{
Amir Samuelovd31ef502011-10-26 14:41:36 +02001482 if (is_ext_charging(the_chip))
1483 return 1;
1484
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001485 switch (fsm_state) {
1486 case FSM_STATE_ATC_2A:
1487 case FSM_STATE_ATC_2B:
1488 case FSM_STATE_ON_CHG_AND_BAT_6:
1489 case FSM_STATE_FAST_CHG_7:
1490 case FSM_STATE_TRKL_CHG_8:
1491 return 1;
1492 }
1493 return 0;
1494}
1495
1496static void bms_notify(struct work_struct *work)
1497{
1498 struct bms_notify *n = container_of(work, struct bms_notify, work);
1499
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07001500 if (n->is_charging) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001501 pm8921_bms_charging_began();
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07001502 } else {
1503 pm8921_bms_charging_end(n->is_battery_full);
1504 n->is_battery_full = 0;
1505 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001506}
1507
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001508static void bms_notify_check(struct pm8921_chg_chip *chip)
1509{
1510 int fsm_state, new_is_charging;
1511
1512 fsm_state = pm_chg_get_fsm_state(chip);
1513 new_is_charging = is_battery_charging(fsm_state);
1514
1515 if (chip->bms_notify.is_charging ^ new_is_charging) {
1516 chip->bms_notify.is_charging = new_is_charging;
1517 schedule_work(&(chip->bms_notify.work));
1518 }
1519}
1520
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001521static enum power_supply_property pm_power_props_usb[] = {
1522 POWER_SUPPLY_PROP_PRESENT,
1523 POWER_SUPPLY_PROP_ONLINE,
1524 POWER_SUPPLY_PROP_CURRENT_MAX,
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001525 POWER_SUPPLY_PROP_SCOPE,
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001526 POWER_SUPPLY_PROP_HEALTH,
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001527};
1528
1529static enum power_supply_property pm_power_props_mains[] = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001530 POWER_SUPPLY_PROP_PRESENT,
Willie Ruan9ad6d832011-08-19 11:58:42 -07001531 POWER_SUPPLY_PROP_ONLINE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001532};
1533
1534static char *pm_power_supplied_to[] = {
1535 "battery",
1536};
1537
David Keitel6ed71a52012-01-30 12:42:18 -08001538#define USB_WALL_THRESHOLD_MA 500
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001539static int pm_power_get_property_mains(struct power_supply *psy,
1540 enum power_supply_property psp,
1541 union power_supply_propval *val)
1542{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001543 int type;
1544
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001545 /* Check if called before init */
1546 if (!the_chip)
1547 return -EINVAL;
1548
1549 switch (psp) {
1550 case POWER_SUPPLY_PROP_PRESENT:
1551 case POWER_SUPPLY_PROP_ONLINE:
1552 val->intval = 0;
David Keitelff4f9ce2012-08-24 15:11:23 -07001553
1554 if (the_chip->has_dc_supply) {
1555 val->intval = 1;
1556 return 0;
1557 }
1558
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001559 if (the_chip->dc_present) {
1560 val->intval = 1;
1561 return 0;
1562 }
1563
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001564 type = the_chip->usb_psy.type;
1565 if (type == POWER_SUPPLY_TYPE_USB_DCP ||
1566 type == POWER_SUPPLY_TYPE_USB_ACA ||
1567 type == POWER_SUPPLY_TYPE_USB_CDP)
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001568 val->intval = is_usb_chg_plugged_in(the_chip);
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001569
1570 break;
1571 default:
1572 return -EINVAL;
1573 }
1574 return 0;
1575}
1576
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001577static int disable_aicl(int disable)
1578{
1579 if (disable != POWER_SUPPLY_HEALTH_UNKNOWN
1580 && disable != POWER_SUPPLY_HEALTH_GOOD) {
1581 pr_err("called with invalid param :%d\n", disable);
1582 return -EINVAL;
1583 }
1584
1585 if (!the_chip) {
1586 pr_err("%s called before init\n", __func__);
1587 return -EINVAL;
1588 }
1589
1590 pr_debug("Disable AICL = %d\n", disable);
1591 the_chip->disable_aicl = disable;
1592 return 0;
1593}
1594
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001595static int switch_usb_to_charge_mode(struct pm8921_chg_chip *chip)
1596{
1597 int rc;
1598
1599 if (!chip->host_mode)
1600 return 0;
1601
1602 /* enable usbin valid comparator and remove force usb ovp fet off */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001603 rc = pm_chg_write(chip, USB_OVP_TEST, 0xB2);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001604 if (rc < 0) {
1605 pr_err("Failed to write 0xB2 to USB_OVP_TEST rc = %d\n", rc);
1606 return rc;
1607 }
1608
1609 chip->host_mode = 0;
1610
1611 return 0;
1612}
1613
1614static int switch_usb_to_host_mode(struct pm8921_chg_chip *chip)
1615{
1616 int rc;
1617
1618 if (chip->host_mode)
1619 return 0;
1620
1621 /* disable usbin valid comparator and force usb ovp fet off */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001622 rc = pm_chg_write(chip, USB_OVP_TEST, 0xB3);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001623 if (rc < 0) {
1624 pr_err("Failed to write 0xB3 to USB_OVP_TEST rc = %d\n", rc);
1625 return rc;
1626 }
1627
1628 chip->host_mode = 1;
1629
1630 return 0;
1631}
1632
1633static int pm_power_set_property_usb(struct power_supply *psy,
1634 enum power_supply_property psp,
1635 const union power_supply_propval *val)
1636{
1637 /* Check if called before init */
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001638 if (!the_chip)
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001639 return -EINVAL;
1640
1641 switch (psp) {
1642 case POWER_SUPPLY_PROP_SCOPE:
1643 if (val->intval == POWER_SUPPLY_SCOPE_SYSTEM)
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001644 return switch_usb_to_host_mode(the_chip);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001645 if (val->intval == POWER_SUPPLY_SCOPE_DEVICE)
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001646 return switch_usb_to_charge_mode(the_chip);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001647 else
1648 return -EINVAL;
1649 break;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001650 case POWER_SUPPLY_PROP_TYPE:
1651 return pm8921_set_usb_power_supply_type(val->intval);
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001652 case POWER_SUPPLY_PROP_HEALTH:
1653 /* UNKNOWN(0) means enable aicl, GOOD(1) means disable aicl */
1654 return disable_aicl(val->intval);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001655 default:
1656 return -EINVAL;
1657 }
1658 return 0;
1659}
1660
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001661static int usb_property_is_writeable(struct power_supply *psy,
1662 enum power_supply_property psp)
1663{
1664 switch (psp) {
1665 case POWER_SUPPLY_PROP_HEALTH:
1666 return 1;
1667 default:
1668 break;
1669 }
1670
1671 return 0;
1672}
1673
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001674static int pm_power_get_property_usb(struct power_supply *psy,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001675 enum power_supply_property psp,
1676 union power_supply_propval *val)
1677{
David Keitel6ed71a52012-01-30 12:42:18 -08001678 int current_max;
1679
1680 /* Check if called before init */
1681 if (!the_chip)
1682 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001683
1684 switch (psp) {
David Keitel6ed71a52012-01-30 12:42:18 -08001685 case POWER_SUPPLY_PROP_CURRENT_MAX:
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001686 if (pm_is_chg_charge_dis(the_chip)) {
1687 val->intval = 0;
1688 } else {
1689 pm_chg_iusbmax_get(the_chip, &current_max);
1690 val->intval = current_max;
1691 }
David Keitel6ed71a52012-01-30 12:42:18 -08001692 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001693 case POWER_SUPPLY_PROP_PRESENT:
Willie Ruan9ad6d832011-08-19 11:58:42 -07001694 case POWER_SUPPLY_PROP_ONLINE:
David Keitel63f71662012-02-08 20:30:00 -08001695 val->intval = 0;
David Keitel63f71662012-02-08 20:30:00 -08001696
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001697 if (the_chip->usb_psy.type == POWER_SUPPLY_TYPE_USB)
David Keitel86034022012-04-18 12:33:58 -07001698 val->intval = is_usb_chg_plugged_in(the_chip);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001699
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001700 break;
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001701
1702 case POWER_SUPPLY_PROP_SCOPE:
1703 if (the_chip->host_mode)
1704 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
1705 else
1706 val->intval = POWER_SUPPLY_SCOPE_DEVICE;
1707 break;
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001708 case POWER_SUPPLY_PROP_HEALTH:
1709 /* UNKNOWN(0) means enable aicl, GOOD(1) means disable aicl */
1710 val->intval = the_chip->disable_aicl;
1711 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001712 default:
1713 return -EINVAL;
1714 }
1715 return 0;
1716}
1717
1718static enum power_supply_property msm_batt_power_props[] = {
1719 POWER_SUPPLY_PROP_STATUS,
1720 POWER_SUPPLY_PROP_CHARGE_TYPE,
1721 POWER_SUPPLY_PROP_HEALTH,
1722 POWER_SUPPLY_PROP_PRESENT,
1723 POWER_SUPPLY_PROP_TECHNOLOGY,
1724 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
1725 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
1726 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1727 POWER_SUPPLY_PROP_CAPACITY,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001728 POWER_SUPPLY_PROP_CURRENT_MAX,
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001729 POWER_SUPPLY_PROP_CURRENT_NOW,
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001730 POWER_SUPPLY_PROP_TEMP,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001731 POWER_SUPPLY_PROP_CHARGE_FULL,
1732 POWER_SUPPLY_PROP_CHARGE_NOW,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001733};
1734
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001735static int get_prop_battery_uvolts(struct pm8921_chg_chip *chip)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001736{
1737 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001738 struct pm8xxx_adc_chan_result result;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001739
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001740 rc = pm8xxx_adc_read(chip->vbat_channel, &result);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001741 if (rc) {
1742 pr_err("error reading adc channel = %d, rc = %d\n",
1743 chip->vbat_channel, rc);
1744 return rc;
1745 }
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001746 pr_debug("mvolts phy = %lld meas = 0x%llx\n", result.physical,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001747 result.measurement);
1748 return (int)result.physical;
1749}
1750
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001751static unsigned int voltage_based_capacity(struct pm8921_chg_chip *chip)
1752{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001753 unsigned int current_voltage_uv = get_prop_battery_uvolts(chip);
1754 unsigned int current_voltage_mv = current_voltage_uv / 1000;
1755 unsigned int low_voltage = chip->min_voltage_mv;
1756 unsigned int high_voltage = chip->max_voltage_mv;
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001757
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001758 if (current_voltage_mv <= low_voltage)
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001759 return 0;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001760 else if (current_voltage_mv >= high_voltage)
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001761 return 100;
1762 else
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001763 return (current_voltage_mv - low_voltage) * 100
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001764 / (high_voltage - low_voltage);
1765}
1766
David Keitel4f9397b2012-04-16 11:46:16 -07001767static int get_prop_batt_present(struct pm8921_chg_chip *chip)
1768{
1769 return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1770}
1771
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001772static int get_prop_batt_status(struct pm8921_chg_chip *chip)
1773{
1774 int batt_state = POWER_SUPPLY_STATUS_DISCHARGING;
1775 int fsm_state = pm_chg_get_fsm_state(chip);
1776 int i;
1777
1778 if (chip->ext_psy) {
1779 if (chip->ext_charge_done)
1780 return POWER_SUPPLY_STATUS_FULL;
1781 if (chip->ext_charging)
1782 return POWER_SUPPLY_STATUS_CHARGING;
1783 }
1784
1785 for (i = 0; i < ARRAY_SIZE(map); i++)
1786 if (map[i].fsm_state == fsm_state)
1787 batt_state = map[i].batt_state;
1788
1789 if (fsm_state == FSM_STATE_ON_CHG_HIGHI_1) {
1790 if (!pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ)
1791 || !pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ)
1792 || pm_chg_get_rt_status(chip, CHGHOT_IRQ)
1793 || pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ))
1794
1795 batt_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
1796 }
1797 return batt_state;
1798}
1799
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001800static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
1801{
David Keitel4f9397b2012-04-16 11:46:16 -07001802 int percent_soc;
1803
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001804 if (chip->battery_less_hardware)
1805 return 100;
1806
David Keitel4f9397b2012-04-16 11:46:16 -07001807 if (!get_prop_batt_present(chip))
1808 percent_soc = voltage_based_capacity(chip);
1809 else
1810 percent_soc = pm8921_bms_get_percent_charge();
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001811
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001812 if (percent_soc == -ENXIO)
1813 percent_soc = voltage_based_capacity(chip);
1814
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001815 if (percent_soc <= 10)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001816 pr_warn_ratelimited("low battery charge = %d%%\n",
1817 percent_soc);
1818
1819 if (percent_soc <= chip->resume_charge_percent
1820 && get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL) {
1821 pr_debug("soc fell below %d. charging enabled.\n",
1822 chip->resume_charge_percent);
1823 if (chip->is_bat_warm)
1824 pr_warn_ratelimited("battery is warm = %d, do not resume charging at %d%%.\n",
1825 chip->is_bat_warm,
1826 chip->resume_charge_percent);
1827 else if (chip->is_bat_cool)
1828 pr_warn_ratelimited("battery is cool = %d, do not resume charging at %d%%.\n",
1829 chip->is_bat_cool,
1830 chip->resume_charge_percent);
1831 else
1832 pm_chg_vbatdet_set(the_chip, PM8921_CHG_VBATDET_MAX);
1833 }
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001834
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -07001835 chip->recent_reported_soc = percent_soc;
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001836 return percent_soc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001837}
1838
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001839static int get_prop_batt_current_max(struct pm8921_chg_chip *chip)
1840{
1841 return pm8921_bms_get_current_max();
1842}
1843
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001844static int get_prop_batt_current(struct pm8921_chg_chip *chip)
1845{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001846 int result_ua, rc;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001847
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001848 rc = pm8921_bms_get_battery_current(&result_ua);
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001849 if (rc == -ENXIO) {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001850 rc = pm8xxx_ccadc_get_battery_current(&result_ua);
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001851 }
1852
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001853 if (rc) {
1854 pr_err("unable to get batt current rc = %d\n", rc);
1855 return rc;
1856 } else {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001857 return result_ua;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001858 }
1859}
1860
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001861static int get_prop_batt_fcc(struct pm8921_chg_chip *chip)
1862{
1863 int rc;
1864
1865 rc = pm8921_bms_get_fcc();
1866 if (rc < 0)
1867 pr_err("unable to get batt fcc rc = %d\n", rc);
1868 return rc;
1869}
1870
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001871static int get_prop_batt_charge_now(struct pm8921_chg_chip *chip)
1872{
1873 int rc;
1874 int cc_uah;
1875
1876 rc = pm8921_bms_cc_uah(&cc_uah);
1877
1878 if (rc == 0)
1879 return cc_uah;
1880
1881 pr_err("unable to get batt fcc rc = %d\n", rc);
1882 return rc;
1883}
1884
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001885static int get_prop_batt_health(struct pm8921_chg_chip *chip)
1886{
1887 int temp;
1888
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001889 temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
1890 if (temp)
1891 return POWER_SUPPLY_HEALTH_OVERHEAT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001892
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001893 temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
1894 if (temp)
1895 return POWER_SUPPLY_HEALTH_COLD;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001896
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001897 return POWER_SUPPLY_HEALTH_GOOD;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001898}
1899
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001900static int get_prop_charge_type(struct pm8921_chg_chip *chip)
1901{
1902 int temp;
1903
Amir Samuelovd31ef502011-10-26 14:41:36 +02001904 if (!get_prop_batt_present(chip))
1905 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1906
1907 if (is_ext_trickle_charging(chip))
1908 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1909
1910 if (is_ext_charging(chip))
1911 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1912
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001913 temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
1914 if (temp)
1915 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1916
1917 temp = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
1918 if (temp)
1919 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1920
1921 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1922}
1923
Abhijeet Dharmapurikar728bc4d2012-01-03 11:08:33 -08001924#define MAX_TOLERABLE_BATT_TEMP_DDC 680
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001925static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
1926{
1927 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001928 struct pm8xxx_adc_chan_result result;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001929
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001930 if (chip->battery_less_hardware)
1931 return 300;
1932
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001933 rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001934 if (rc) {
1935 pr_err("error reading adc channel = %d, rc = %d\n",
1936 chip->vbat_channel, rc);
1937 return rc;
1938 }
1939 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1940 result.measurement);
Abhijeet Dharmapurikar728bc4d2012-01-03 11:08:33 -08001941 if (result.physical > MAX_TOLERABLE_BATT_TEMP_DDC)
1942 pr_err("BATT_TEMP= %d > 68degC, device will be shutdown\n",
1943 (int) result.physical);
1944
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001945 return (int)result.physical;
1946}
1947
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001948static int pm_batt_power_get_property(struct power_supply *psy,
1949 enum power_supply_property psp,
1950 union power_supply_propval *val)
1951{
1952 struct pm8921_chg_chip *chip = container_of(psy, struct pm8921_chg_chip,
1953 batt_psy);
1954
1955 switch (psp) {
1956 case POWER_SUPPLY_PROP_STATUS:
1957 val->intval = get_prop_batt_status(chip);
1958 break;
1959 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1960 val->intval = get_prop_charge_type(chip);
1961 break;
1962 case POWER_SUPPLY_PROP_HEALTH:
1963 val->intval = get_prop_batt_health(chip);
1964 break;
1965 case POWER_SUPPLY_PROP_PRESENT:
1966 val->intval = get_prop_batt_present(chip);
1967 break;
1968 case POWER_SUPPLY_PROP_TECHNOLOGY:
1969 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1970 break;
1971 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001972 val->intval = chip->max_voltage_mv * 1000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001973 break;
1974 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001975 val->intval = chip->min_voltage_mv * 1000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001976 break;
1977 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001978 val->intval = get_prop_battery_uvolts(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001979 break;
1980 case POWER_SUPPLY_PROP_CAPACITY:
1981 val->intval = get_prop_batt_capacity(chip);
1982 break;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001983 case POWER_SUPPLY_PROP_CURRENT_NOW:
1984 val->intval = get_prop_batt_current(chip);
1985 break;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001986 case POWER_SUPPLY_PROP_CURRENT_MAX:
1987 val->intval = get_prop_batt_current_max(chip);
1988 break;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001989 case POWER_SUPPLY_PROP_TEMP:
1990 val->intval = get_prop_batt_temp(chip);
1991 break;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001992 case POWER_SUPPLY_PROP_CHARGE_FULL:
1993 val->intval = get_prop_batt_fcc(chip);
1994 break;
1995 case POWER_SUPPLY_PROP_CHARGE_NOW:
1996 val->intval = get_prop_batt_charge_now(chip);
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001997 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001998 default:
1999 return -EINVAL;
2000 }
2001
2002 return 0;
2003}
2004
2005static void (*notify_vbus_state_func_ptr)(int);
2006static int usb_chg_current;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002007
2008int pm8921_charger_register_vbus_sn(void (*callback)(int))
2009{
2010 pr_debug("%p\n", callback);
2011 notify_vbus_state_func_ptr = callback;
2012 return 0;
2013}
2014EXPORT_SYMBOL_GPL(pm8921_charger_register_vbus_sn);
2015
2016/* this is passed to the hsusb via platform_data msm_otg_pdata */
2017void pm8921_charger_unregister_vbus_sn(void (*callback)(int))
2018{
2019 pr_debug("%p\n", callback);
2020 notify_vbus_state_func_ptr = NULL;
2021}
2022EXPORT_SYMBOL_GPL(pm8921_charger_unregister_vbus_sn);
2023
2024static void notify_usb_of_the_plugin_event(int plugin)
2025{
2026 plugin = !!plugin;
2027 if (notify_vbus_state_func_ptr) {
2028 pr_debug("notifying plugin\n");
2029 (*notify_vbus_state_func_ptr) (plugin);
2030 } else {
2031 pr_debug("unable to notify plugin\n");
2032 }
2033}
2034
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002035static void __pm8921_charger_vbus_draw(unsigned int mA)
2036{
2037 int i, rc;
David Keitel38bdd4f2012-04-19 15:39:13 -07002038 if (!the_chip) {
2039 pr_err("called before init\n");
2040 return;
2041 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002042
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002043 if (usb_max_current && mA > usb_max_current) {
2044 pr_debug("restricting usb current to %d instead of %d\n",
2045 usb_max_current, mA);
2046 mA = usb_max_current;
2047 }
2048
2049 if (mA <= 2) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002050 usb_chg_current = 0;
David Keitelacf57c82012-03-07 18:48:50 -08002051 rc = pm_chg_iusbmax_set(the_chip, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002052 if (rc) {
David Keitelacf57c82012-03-07 18:48:50 -08002053 pr_err("unable to set iusb to %d rc = %d\n", 0, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002054 }
2055 rc = pm_chg_usb_suspend_enable(the_chip, 1);
2056 if (rc)
2057 pr_err("fail to set suspend bit rc=%d\n", rc);
2058 } else {
2059 rc = pm_chg_usb_suspend_enable(the_chip, 0);
2060 if (rc)
2061 pr_err("fail to reset suspend bit rc=%d\n", rc);
2062 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
2063 if (usb_ma_table[i].usb_ma <= mA)
2064 break;
2065 }
David Keitel38bdd4f2012-04-19 15:39:13 -07002066
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002067 if (i < 0) {
2068 pr_err("can't find %dmA in usb_ma_table. Use min.\n",
2069 mA);
2070 i = 0;
2071 }
2072
David Keitel38bdd4f2012-04-19 15:39:13 -07002073 /* Check if IUSB_FINE_RES is available */
David Keitel1454bc82012-10-01 11:12:59 -07002074 while ((usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
David Keitel38bdd4f2012-04-19 15:39:13 -07002075 && !the_chip->iusb_fine_res)
2076 i--;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002077 if (i < 0)
2078 i = 0;
David Keitelacf57c82012-03-07 18:48:50 -08002079 rc = pm_chg_iusbmax_set(the_chip, i);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002080 if (rc)
David Keitelacf57c82012-03-07 18:48:50 -08002081 pr_err("unable to set iusb to %d rc = %d\n", i, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002082 }
2083}
2084
2085/* USB calls these to tell us how much max usb current the system can draw */
2086void pm8921_charger_vbus_draw(unsigned int mA)
2087{
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002088 int set_usb_now_ma;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002089
2090 pr_debug("Enter charge=%d\n", mA);
David Keitelacf57c82012-03-07 18:48:50 -08002091
David Keitel62c6a4b2012-05-17 12:54:59 -07002092 /*
2093 * Reject VBUS requests if USB connection is the only available
2094 * power source. This makes sure that if booting without
2095 * battery the iusb_max value is not decreased avoiding potential
2096 * brown_outs.
2097 *
2098 * This would also apply when the battery has been
2099 * removed from the running system.
2100 */
Abhijeet Dharmapurikar55cf35b2013-02-20 18:40:59 -08002101 if (mA == 0 && the_chip && !get_prop_batt_present(the_chip)
David Keitel62c6a4b2012-05-17 12:54:59 -07002102 && !is_dc_chg_plugged_in(the_chip)) {
David Keitelff4f9ce2012-08-24 15:11:23 -07002103 if (!the_chip->has_dc_supply) {
Abhijeet Dharmapurikar55cf35b2013-02-20 18:40:59 -08002104 pr_err("rejected: no other power source mA = %d\n", mA);
David Keitelff4f9ce2012-08-24 15:11:23 -07002105 return;
2106 }
David Keitel62c6a4b2012-05-17 12:54:59 -07002107 }
2108
David Keitelacf57c82012-03-07 18:48:50 -08002109 if (usb_max_current && mA > usb_max_current) {
2110 pr_warn("restricting usb current to %d instead of %d\n",
2111 usb_max_current, mA);
2112 mA = usb_max_current;
2113 }
Devin Kim2073afb2012-09-05 13:01:51 -07002114 if (usb_target_ma == 0 && mA > USB_WALL_THRESHOLD_MA)
2115 usb_target_ma = mA;
David Keitelacf57c82012-03-07 18:48:50 -08002116
Anirudh Ghayal0ddca632013-01-23 16:43:31 +05302117 if (usb_target_ma)
2118 usb_target_ma = mA;
2119
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002120
2121 if (mA > USB_WALL_THRESHOLD_MA)
2122 set_usb_now_ma = USB_WALL_THRESHOLD_MA;
2123 else
2124 set_usb_now_ma = mA;
2125
2126 if (the_chip && the_chip->disable_aicl)
2127 set_usb_now_ma = mA;
2128
2129 if (the_chip)
2130 __pm8921_charger_vbus_draw(set_usb_now_ma);
2131 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002132 /*
2133 * called before pmic initialized,
2134 * save this value and use it at probe
2135 */
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002136 usb_chg_current = set_usb_now_ma;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002137}
2138EXPORT_SYMBOL_GPL(pm8921_charger_vbus_draw);
2139
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002140int pm8921_is_usb_chg_plugged_in(void)
2141{
2142 if (!the_chip) {
2143 pr_err("called before init\n");
2144 return -EINVAL;
2145 }
2146 return is_usb_chg_plugged_in(the_chip);
2147}
2148EXPORT_SYMBOL(pm8921_is_usb_chg_plugged_in);
2149
2150int pm8921_is_dc_chg_plugged_in(void)
2151{
2152 if (!the_chip) {
2153 pr_err("called before init\n");
2154 return -EINVAL;
2155 }
2156 return is_dc_chg_plugged_in(the_chip);
2157}
2158EXPORT_SYMBOL(pm8921_is_dc_chg_plugged_in);
2159
2160int pm8921_is_battery_present(void)
2161{
2162 if (!the_chip) {
2163 pr_err("called before init\n");
2164 return -EINVAL;
2165 }
2166 return get_prop_batt_present(the_chip);
2167}
2168EXPORT_SYMBOL(pm8921_is_battery_present);
2169
Abhijeet Dharmapurikarb2680132012-05-15 16:32:51 -07002170int pm8921_is_batfet_closed(void)
2171{
2172 if (!the_chip) {
2173 pr_err("called before init\n");
2174 return -EINVAL;
2175 }
2176 return is_batfet_closed(the_chip);
2177}
2178EXPORT_SYMBOL(pm8921_is_batfet_closed);
David Keitel012deef2011-12-02 11:49:33 -08002179/*
2180 * Disabling the charge current limit causes current
2181 * current limits to have no monitoring. An adequate charger
2182 * capable of supplying high current while sustaining VIN_MIN
2183 * is required if the limiting is disabled.
2184 */
2185int pm8921_disable_input_current_limit(bool disable)
2186{
2187 if (!the_chip) {
2188 pr_err("called before init\n");
2189 return -EINVAL;
2190 }
2191 if (disable) {
2192 pr_warn("Disabling input current limit!\n");
2193
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002194 return pm_chg_write(the_chip, CHG_BUCK_CTRL_TEST3, 0xF2);
David Keitel012deef2011-12-02 11:49:33 -08002195 }
2196 return 0;
2197}
2198EXPORT_SYMBOL(pm8921_disable_input_current_limit);
2199
David Keitel0789fc62012-06-07 17:43:27 -07002200int pm8917_set_under_voltage_detection_threshold(int mv)
2201{
2202 if (!the_chip) {
2203 pr_err("called before init\n");
2204 return -EINVAL;
2205 }
2206 return pm_chg_uvd_threshold_set(the_chip, mv);
2207}
2208EXPORT_SYMBOL(pm8917_set_under_voltage_detection_threshold);
2209
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002210int pm8921_set_max_battery_charge_current(int ma)
2211{
2212 if (!the_chip) {
2213 pr_err("called before init\n");
2214 return -EINVAL;
2215 }
2216 return pm_chg_ibatmax_set(the_chip, ma);
2217}
2218EXPORT_SYMBOL(pm8921_set_max_battery_charge_current);
2219
2220int pm8921_disable_source_current(bool disable)
2221{
2222 if (!the_chip) {
2223 pr_err("called before init\n");
2224 return -EINVAL;
2225 }
2226 if (disable)
2227 pr_warn("current drawn from chg=0, battery provides current\n");
David Keitel0fe15c42012-09-04 09:33:28 -07002228
2229 pm_chg_usb_suspend_enable(the_chip, disable);
2230
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002231 return pm_chg_charge_dis(the_chip, disable);
2232}
2233EXPORT_SYMBOL(pm8921_disable_source_current);
2234
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002235int pm8921_regulate_input_voltage(int voltage)
2236{
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002237 int rc;
2238
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002239 if (!the_chip) {
2240 pr_err("called before init\n");
2241 return -EINVAL;
2242 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002243 rc = pm_chg_vinmin_set(the_chip, voltage);
2244
2245 if (rc == 0)
2246 the_chip->vin_min = voltage;
2247
2248 return rc;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002249}
2250
Abhijeet Dharmapurikar28669302011-12-21 08:31:28 -08002251#define USB_OV_THRESHOLD_MASK 0x60
2252#define USB_OV_THRESHOLD_SHIFT 5
2253int pm8921_usb_ovp_set_threshold(enum pm8921_usb_ov_threshold ov)
2254{
2255 u8 temp;
2256
2257 if (!the_chip) {
2258 pr_err("called before init\n");
2259 return -EINVAL;
2260 }
2261
2262 if (ov > PM_USB_OV_7V) {
2263 pr_err("limiting to over voltage threshold to 7volts\n");
2264 ov = PM_USB_OV_7V;
2265 }
2266
2267 temp = USB_OV_THRESHOLD_MASK & (ov << USB_OV_THRESHOLD_SHIFT);
2268
2269 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
2270 USB_OV_THRESHOLD_MASK, temp);
2271}
2272EXPORT_SYMBOL(pm8921_usb_ovp_set_threshold);
2273
2274#define USB_DEBOUNCE_TIME_MASK 0x06
2275#define USB_DEBOUNCE_TIME_SHIFT 1
2276int pm8921_usb_ovp_set_hystersis(enum pm8921_usb_debounce_time ms)
2277{
2278 u8 temp;
2279
2280 if (!the_chip) {
2281 pr_err("called before init\n");
2282 return -EINVAL;
2283 }
2284
2285 if (ms > PM_USB_DEBOUNCE_80P5MS) {
2286 pr_err("limiting debounce to 80.5ms\n");
2287 ms = PM_USB_DEBOUNCE_80P5MS;
2288 }
2289
2290 temp = USB_DEBOUNCE_TIME_MASK & (ms << USB_DEBOUNCE_TIME_SHIFT);
2291
2292 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
2293 USB_DEBOUNCE_TIME_MASK, temp);
2294}
2295EXPORT_SYMBOL(pm8921_usb_ovp_set_hystersis);
2296
2297#define USB_OVP_DISABLE_MASK 0x80
2298int pm8921_usb_ovp_disable(int disable)
2299{
2300 u8 temp = 0;
2301
2302 if (!the_chip) {
2303 pr_err("called before init\n");
2304 return -EINVAL;
2305 }
2306
2307 if (disable)
2308 temp = USB_OVP_DISABLE_MASK;
2309
2310 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
2311 USB_OVP_DISABLE_MASK, temp);
2312}
2313
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002314bool pm8921_is_battery_charging(int *source)
2315{
2316 int fsm_state, is_charging, dc_present, usb_present;
2317
2318 if (!the_chip) {
2319 pr_err("called before init\n");
2320 return -EINVAL;
2321 }
2322 fsm_state = pm_chg_get_fsm_state(the_chip);
2323 is_charging = is_battery_charging(fsm_state);
2324 if (is_charging == 0) {
2325 *source = PM8921_CHG_SRC_NONE;
2326 return is_charging;
2327 }
2328
2329 if (source == NULL)
2330 return is_charging;
2331
2332 /* the battery is charging, the source is requested, find it */
2333 dc_present = is_dc_chg_plugged_in(the_chip);
2334 usb_present = is_usb_chg_plugged_in(the_chip);
2335
2336 if (dc_present && !usb_present)
2337 *source = PM8921_CHG_SRC_DC;
2338
2339 if (usb_present && !dc_present)
2340 *source = PM8921_CHG_SRC_USB;
2341
2342 if (usb_present && dc_present)
2343 /*
2344 * The system always chooses dc for charging since it has
2345 * higher priority.
2346 */
2347 *source = PM8921_CHG_SRC_DC;
2348
2349 return is_charging;
2350}
2351EXPORT_SYMBOL(pm8921_is_battery_charging);
2352
David Keitel86034022012-04-18 12:33:58 -07002353int pm8921_set_usb_power_supply_type(enum power_supply_type type)
2354{
2355 if (!the_chip) {
2356 pr_err("called before init\n");
2357 return -EINVAL;
2358 }
2359
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002360 if (type < POWER_SUPPLY_TYPE_USB && type > POWER_SUPPLY_TYPE_BATTERY)
David Keitel86034022012-04-18 12:33:58 -07002361 return -EINVAL;
2362
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002363 the_chip->usb_psy.type = type;
David Keitel86034022012-04-18 12:33:58 -07002364 power_supply_changed(&the_chip->usb_psy);
2365 power_supply_changed(&the_chip->dc_psy);
2366 return 0;
2367}
2368EXPORT_SYMBOL_GPL(pm8921_set_usb_power_supply_type);
2369
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002370int pm8921_batt_temperature(void)
2371{
2372 if (!the_chip) {
2373 pr_err("called before init\n");
2374 return -EINVAL;
2375 }
2376 return get_prop_batt_temp(the_chip);
2377}
2378
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002379static int __pm8921_apply_19p2mhz_kickstart(struct pm8921_chg_chip *chip)
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002380{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002381 int err;
2382 u8 temp;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002383
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002384
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002385 temp = 0xD1;
2386 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2387 if (err) {
2388 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002389 return err;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002390 }
2391
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002392 temp = 0xD3;
2393 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2394 if (err) {
2395 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002396 return err;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002397 }
2398
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002399 temp = 0xD1;
2400 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2401 if (err) {
2402 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002403 return err;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002404 }
2405
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002406 temp = 0xD5;
2407 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2408 if (err) {
2409 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002410 return err;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002411 }
2412
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002413 /* Wait a few clock cycles before re-enabling hw clock switching */
2414 udelay(183);
2415
2416 temp = 0xD1;
2417 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2418 if (err) {
2419 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002420 return err;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002421 }
2422
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002423 temp = 0xD0;
2424 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
2425 if (err) {
2426 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002427 return err;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002428 }
2429
2430 /* Wait for few clock cycles before re-enabling LPM */
2431 udelay(32);
2432
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08002433 return 0;
2434}
2435
2436static int pm8921_apply_19p2mhz_kickstart(struct pm8921_chg_chip *chip)
2437{
2438 int err;
2439 unsigned long flags = 0;
2440
2441 spin_lock_irqsave(&lpm_lock, flags);
2442 err = pm8921_chg_set_lpm(chip, 0);
2443 if (err) {
2444 pr_err("Error settig LPM rc=%d\n", err);
2445 goto kick_err;
2446 }
2447
2448 __pm8921_apply_19p2mhz_kickstart(chip);
2449
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002450kick_err:
2451 err = pm8921_chg_set_lpm(chip, 1);
2452 if (err)
2453 pr_err("Error settig LPM rc=%d\n", err);
2454
2455 spin_unlock_irqrestore(&lpm_lock, flags);
2456
2457 return err;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07002458}
2459
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002460static void handle_usb_insertion_removal(struct pm8921_chg_chip *chip)
2461{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002462 int usb_present, rc = 0;
2463
2464 if (chip->lockup_lpm_wrkarnd) {
2465 rc = pm8921_apply_19p2mhz_kickstart(chip);
2466 if (rc)
2467 pr_err("Failed to apply kickstart rc=%d\n", rc);
2468 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002469
Abhijeet Dharmapurikare451f342012-02-23 16:39:42 -08002470 pm_chg_failed_clear(chip, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002471 usb_present = is_usb_chg_plugged_in(chip);
2472 if (chip->usb_present ^ usb_present) {
2473 notify_usb_of_the_plugin_event(usb_present);
2474 chip->usb_present = usb_present;
2475 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikar0c4bc152011-10-27 10:22:24 -07002476 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarc9ba2712012-02-23 12:42:24 -08002477 pm8921_bms_calibrate_hkadc();
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002478
2479 /* Enable/disable bypass if charger is on battery */
2480 if (chip->lockup_lpm_wrkarnd)
2481 pm8921_chg_bypass_bat_gone_debounce(chip,
2482 is_chg_on_bat(chip));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002483 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002484 if (usb_present) {
2485 schedule_delayed_work(&chip->unplug_check_work,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002486 msecs_to_jiffies(UNPLUG_CHECK_RAMP_MS));
David Keitel8c5201a2012-02-24 16:08:54 -08002487 pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
2488 } else {
David Keitelacf57c82012-03-07 18:48:50 -08002489 /* USB unplugged reset target current */
Devin Kim2073afb2012-09-05 13:01:51 -07002490 usb_target_ma = 0;
David Keitel8c5201a2012-02-24 16:08:54 -08002491 pm8921_chg_disable_irq(chip, CHG_GONE_IRQ);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002492 }
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07002493 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002494}
2495
Amir Samuelovd31ef502011-10-26 14:41:36 +02002496static void handle_stop_ext_chg(struct pm8921_chg_chip *chip)
2497{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002498 if (chip->lockup_lpm_wrkarnd)
2499 /* Enable bypass if charger is on battery */
2500 pm8921_chg_bypass_bat_gone_debounce(chip, is_chg_on_bat(chip));
2501
David Keitel88e1b572012-01-11 11:57:14 -08002502 if (!chip->ext_psy) {
Amir Samuelovd31ef502011-10-26 14:41:36 +02002503 pr_debug("external charger not registered.\n");
2504 return;
2505 }
2506
2507 if (!chip->ext_charging) {
2508 pr_debug("already not charging.\n");
2509 return;
2510 }
2511
David Keitel88e1b572012-01-11 11:57:14 -08002512 power_supply_set_charge_type(chip->ext_psy,
2513 POWER_SUPPLY_CHARGE_TYPE_NONE);
2514 pm8921_disable_source_current(false); /* release BATFET */
David Keitel63f71662012-02-08 20:30:00 -08002515 power_supply_changed(&chip->dc_psy);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002516 chip->ext_charging = false;
David Keiteld4e59ef2011-11-09 17:38:31 -08002517 chip->ext_charge_done = false;
David Keitel88e1b572012-01-11 11:57:14 -08002518 bms_notify_check(chip);
Amir Samuelov4ffc8ec2012-05-16 09:38:43 +03002519 /* Update battery charging LEDs and user space battery info */
2520 power_supply_changed(&chip->batt_psy);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002521}
2522
2523static void handle_start_ext_chg(struct pm8921_chg_chip *chip)
2524{
2525 int dc_present;
2526 int batt_present;
2527 int batt_temp_ok;
Amir Samuelovd31ef502011-10-26 14:41:36 +02002528 unsigned long delay =
2529 round_jiffies_relative(msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2530
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002531 /* Disable bypass if charger connected and not running on bat */
2532 if (chip->lockup_lpm_wrkarnd)
2533 pm8921_chg_bypass_bat_gone_debounce(chip, is_chg_on_bat(chip));
2534
David Keitel88e1b572012-01-11 11:57:14 -08002535 if (!chip->ext_psy) {
Amir Samuelovd31ef502011-10-26 14:41:36 +02002536 pr_debug("external charger not registered.\n");
2537 return;
2538 }
2539
2540 if (chip->ext_charging) {
2541 pr_debug("already charging.\n");
2542 return;
2543 }
2544
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002545 dc_present = is_dc_chg_plugged_in(chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002546 batt_present = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
2547 batt_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002548
2549 if (!dc_present) {
2550 pr_warn("%s. dc not present.\n", __func__);
2551 return;
2552 }
2553 if (!batt_present) {
2554 pr_warn("%s. battery not present.\n", __func__);
2555 return;
2556 }
2557 if (!batt_temp_ok) {
2558 pr_warn("%s. battery temperature not ok.\n", __func__);
2559 return;
2560 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002561
2562 /* Force BATFET=ON */
2563 pm8921_disable_source_current(true);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002564
David Keitel6ccbf132012-05-30 14:21:24 -07002565 schedule_delayed_work(&chip->unplug_check_work,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002566 msecs_to_jiffies(UNPLUG_CHECK_RAMP_MS));
David Keitel6ccbf132012-05-30 14:21:24 -07002567
David Keitel63f71662012-02-08 20:30:00 -08002568 power_supply_set_online(chip->ext_psy, dc_present);
David Keitel88e1b572012-01-11 11:57:14 -08002569 power_supply_set_charge_type(chip->ext_psy,
2570 POWER_SUPPLY_CHARGE_TYPE_FAST);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002571 chip->ext_charging = true;
2572 chip->ext_charge_done = false;
David Keitel88e1b572012-01-11 11:57:14 -08002573 bms_notify_check(chip);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002574 /*
2575 * since we wont get a fastchg irq from external charger
2576 * use eoc worker to detect end of charging
2577 */
Amir Samuelovd31ef502011-10-26 14:41:36 +02002578 schedule_delayed_work(&chip->eoc_work, delay);
2579 wake_lock(&chip->eoc_wake_lock);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002580 if (chip->btc_override)
2581 schedule_delayed_work(&chip->btc_override_work,
2582 round_jiffies_relative(msecs_to_jiffies
2583 (chip->btc_delay_ms)));
Amir Samuelov4ffc8ec2012-05-16 09:38:43 +03002584 /* Update battery charging LEDs and user space battery info */
2585 power_supply_changed(&chip->batt_psy);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002586}
2587
David Keitel6ccbf132012-05-30 14:21:24 -07002588static void turn_off_ovp_fet(struct pm8921_chg_chip *chip, u16 ovptestreg)
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002589{
2590 u8 temp;
2591 int rc;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002592
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002593 rc = pm_chg_write(chip, ovptestreg, 0x30);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002594 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002595 pr_err("Failed to write 0x30 to ovptestreg rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002596 return;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002597 }
David Keitel6ccbf132012-05-30 14:21:24 -07002598 rc = pm8xxx_readb(chip->dev->parent, ovptestreg, &temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002599 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002600 pr_err("Failed to read from ovptestreg rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002601 return;
2602 }
2603 /* set ovp fet disable bit and the write bit */
2604 temp |= 0x81;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002605 rc = pm_chg_write(chip, ovptestreg, temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002606 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002607 pr_err("Failed to write 0x%x ovptestreg rc=%d\n", temp, rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002608 return;
2609 }
2610}
2611
David Keitel6ccbf132012-05-30 14:21:24 -07002612static void turn_on_ovp_fet(struct pm8921_chg_chip *chip, u16 ovptestreg)
David Keitel8c5201a2012-02-24 16:08:54 -08002613{
2614 u8 temp;
2615 int rc;
2616
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002617 rc = pm_chg_write(chip, ovptestreg, 0x30);
David Keitel8c5201a2012-02-24 16:08:54 -08002618 if (rc) {
David Keitel6ccbf132012-05-30 14:21:24 -07002619 pr_err("Failed to write 0x30 to OVP_TEST rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002620 return;
2621 }
David Keitel6ccbf132012-05-30 14:21:24 -07002622 rc = pm8xxx_readb(chip->dev->parent, ovptestreg, &temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002623 if (rc) {
David Keitel6ccbf132012-05-30 14:21:24 -07002624 pr_err("Failed to read from OVP_TEST rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002625 return;
2626 }
2627 /* unset ovp fet disable bit and set the write bit */
2628 temp &= 0xFE;
2629 temp |= 0x80;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002630 rc = pm_chg_write(chip, ovptestreg, temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002631 if (rc) {
David Keitel6ccbf132012-05-30 14:21:24 -07002632 pr_err("Failed to write 0x%x to OVP_TEST rc = %d\n",
David Keitel8c5201a2012-02-24 16:08:54 -08002633 temp, rc);
2634 return;
2635 }
2636}
2637
2638static int param_open_ovp_counter = 10;
2639module_param(param_open_ovp_counter, int, 0644);
2640
David Keitel6ccbf132012-05-30 14:21:24 -07002641#define USB_ACTIVE_BIT BIT(5)
2642#define DC_ACTIVE_BIT BIT(6)
2643static int is_active_chg_plugged_in(struct pm8921_chg_chip *chip,
2644 u8 active_chg_mask)
2645{
2646 if (active_chg_mask & USB_ACTIVE_BIT)
2647 return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
2648 else if (active_chg_mask & DC_ACTIVE_BIT)
2649 return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
2650 else
2651 return 0;
2652}
2653
David Keitel8c5201a2012-02-24 16:08:54 -08002654#define WRITE_BANK_4 0xC0
David Keitel6ccbf132012-05-30 14:21:24 -07002655#define OVP_DEBOUNCE_TIME 0x06
David Keitelc3e15bd2012-05-25 17:07:25 -07002656static void unplug_ovp_fet_open(struct pm8921_chg_chip *chip)
David Keitel8c5201a2012-02-24 16:08:54 -08002657{
David Keitel6ccbf132012-05-30 14:21:24 -07002658 int chg_gone = 0, active_chg_plugged_in = 0;
David Keitel8c5201a2012-02-24 16:08:54 -08002659 int count = 0;
David Keitel6ccbf132012-05-30 14:21:24 -07002660 u8 active_mask = 0;
2661 u16 ovpreg, ovptestreg;
2662
2663 if (is_usb_chg_plugged_in(chip) &&
2664 (chip->active_path & USB_ACTIVE_BIT)) {
2665 ovpreg = USB_OVP_CONTROL;
2666 ovptestreg = USB_OVP_TEST;
2667 active_mask = USB_ACTIVE_BIT;
2668 } else if (is_dc_chg_plugged_in(chip) &&
2669 (chip->active_path & DC_ACTIVE_BIT)) {
2670 ovpreg = DC_OVP_CONTROL;
2671 ovptestreg = DC_OVP_TEST;
2672 active_mask = DC_ACTIVE_BIT;
2673 } else {
2674 return;
2675 }
David Keitel8c5201a2012-02-24 16:08:54 -08002676
2677 while (count++ < param_open_ovp_counter) {
David Keitel6ccbf132012-05-30 14:21:24 -07002678 pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x0);
David Keitel8c5201a2012-02-24 16:08:54 -08002679 usleep(10);
David Keitel6ccbf132012-05-30 14:21:24 -07002680 active_chg_plugged_in
2681 = is_active_chg_plugged_in(chip, active_mask);
David Keitel8c5201a2012-02-24 16:08:54 -08002682 chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
David Keitel6ccbf132012-05-30 14:21:24 -07002683 pr_debug("OVP FET count = %d chg_gone=%d, active_valid = %d\n",
2684 count, chg_gone, active_chg_plugged_in);
David Keitel8c5201a2012-02-24 16:08:54 -08002685
2686 /* note usb_chg_plugged_in=0 => chg_gone=1 */
David Keitel6ccbf132012-05-30 14:21:24 -07002687 if (chg_gone == 1 && active_chg_plugged_in == 1) {
David Keitel8c5201a2012-02-24 16:08:54 -08002688 pr_debug("since chg_gone = 1 dis ovp_fet for 20msec\n");
David Keitel6ccbf132012-05-30 14:21:24 -07002689 turn_off_ovp_fet(chip, ovptestreg);
David Keitel8c5201a2012-02-24 16:08:54 -08002690
2691 msleep(20);
2692
David Keitel6ccbf132012-05-30 14:21:24 -07002693 turn_on_ovp_fet(chip, ovptestreg);
David Keitel8c5201a2012-02-24 16:08:54 -08002694 } else {
David Keitel712782e2012-03-29 14:11:47 -07002695 break;
David Keitel8c5201a2012-02-24 16:08:54 -08002696 }
2697 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002698 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
2699 pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x6);
2700 else
2701 pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x2);
2702
David Keitel6ccbf132012-05-30 14:21:24 -07002703 pr_debug("Exit count=%d chg_gone=%d, active_valid=%d\n",
2704 count, chg_gone, active_chg_plugged_in);
David Keitel712782e2012-03-29 14:11:47 -07002705 return;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002706}
David Keitelacf57c82012-03-07 18:48:50 -08002707
2708static int find_usb_ma_value(int value)
2709{
2710 int i;
2711
2712 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
2713 if (value >= usb_ma_table[i].usb_ma)
2714 break;
2715 }
2716
2717 return i;
2718}
2719
2720static void decrease_usb_ma_value(int *value)
2721{
2722 int i;
2723
2724 if (value) {
2725 i = find_usb_ma_value(*value);
2726 if (i > 0)
2727 i--;
David Keitelc7bba2f2012-06-15 17:05:52 -07002728 while (!the_chip->iusb_fine_res && i > 0
2729 && (usb_ma_table[i].value & PM8917_IUSB_FINE_RES))
2730 i--;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002731
2732 if (i < 0) {
2733 pr_err("can't find %dmA in usb_ma_table. Use min.\n",
2734 *value);
2735 i = 0;
2736 }
2737
David Keitelacf57c82012-03-07 18:48:50 -08002738 *value = usb_ma_table[i].usb_ma;
2739 }
2740}
2741
2742static void increase_usb_ma_value(int *value)
2743{
2744 int i;
2745
2746 if (value) {
2747 i = find_usb_ma_value(*value);
2748
2749 if (i < (ARRAY_SIZE(usb_ma_table) - 1))
2750 i++;
David Keitel38bdd4f2012-04-19 15:39:13 -07002751 /* Get next correct entry if IUSB_FINE_RES is not available */
2752 while (!the_chip->iusb_fine_res
2753 && (usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
2754 && i < (ARRAY_SIZE(usb_ma_table) - 1))
2755 i++;
2756
David Keitelacf57c82012-03-07 18:48:50 -08002757 *value = usb_ma_table[i].usb_ma;
2758 }
2759}
2760
2761static void vin_collapse_check_worker(struct work_struct *work)
2762{
2763 struct delayed_work *dwork = to_delayed_work(work);
2764 struct pm8921_chg_chip *chip = container_of(dwork,
2765 struct pm8921_chg_chip, vin_collapse_check_work);
2766
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002767 /*
2768 * AICL only for wall-chargers. If the charger appears to be plugged
2769 * back in now, the corresponding unplug must have been because of we
2770 * were trying to draw more current than the charger can support. In
2771 * such a case reset usb current to 500mA and decrease the target.
2772 * The AICL algorithm will step up the current from 500mA to target
2773 */
2774 if (is_usb_chg_plugged_in(chip)
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002775 && usb_target_ma > USB_WALL_THRESHOLD_MA
2776 && !chip->disable_aicl) {
David Keitelacf57c82012-03-07 18:48:50 -08002777 /* decrease usb_target_ma */
2778 decrease_usb_ma_value(&usb_target_ma);
2779 /* reset here, increase in unplug_check_worker */
2780 __pm8921_charger_vbus_draw(USB_WALL_THRESHOLD_MA);
2781 pr_debug("usb_now=%d, usb_target = %d\n",
2782 USB_WALL_THRESHOLD_MA, usb_target_ma);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002783 if (!delayed_work_pending(&chip->unplug_check_work))
2784 schedule_delayed_work(&chip->unplug_check_work,
2785 msecs_to_jiffies
2786 (UNPLUG_CHECK_WAIT_PERIOD_MS));
David Keitelacf57c82012-03-07 18:48:50 -08002787 } else {
2788 handle_usb_insertion_removal(chip);
2789 }
2790}
2791
2792#define VIN_MIN_COLLAPSE_CHECK_MS 50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002793static irqreturn_t usbin_valid_irq_handler(int irq, void *data)
2794{
David Keitelacf57c82012-03-07 18:48:50 -08002795 if (usb_target_ma)
2796 schedule_delayed_work(&the_chip->vin_collapse_check_work,
2797 round_jiffies_relative(msecs_to_jiffies
2798 (VIN_MIN_COLLAPSE_CHECK_MS)));
2799 else
2800 handle_usb_insertion_removal(data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002801 return IRQ_HANDLED;
2802}
2803
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002804static irqreturn_t batt_inserted_irq_handler(int irq, void *data)
2805{
2806 struct pm8921_chg_chip *chip = data;
2807 int status;
2808
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002809 status = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
2810 schedule_work(&chip->battery_id_valid_work);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002811 handle_start_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002812 pr_debug("battery present=%d", status);
2813 power_supply_changed(&chip->batt_psy);
2814 return IRQ_HANDLED;
2815}
Amir Samuelovd31ef502011-10-26 14:41:36 +02002816
2817/*
2818 * this interrupt used to restart charging a battery.
2819 *
2820 * Note: When DC-inserted the VBAT can't go low.
2821 * VPH_PWR is provided by the ext-charger.
2822 * After End-Of-Charging from DC, charging can be resumed only
2823 * if DC is removed and then inserted after the battery was in use.
2824 * Therefore the handle_start_ext_chg() is not called.
2825 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002826static irqreturn_t vbatdet_low_irq_handler(int irq, void *data)
2827{
2828 struct pm8921_chg_chip *chip = data;
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002829 int high_transition;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002830
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002831 high_transition = pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07002832
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002833 if (high_transition) {
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002834 /* enable auto charging */
2835 pm_chg_auto_enable(chip, !charging_disabled);
2836 pr_info("batt fell below resume voltage %s\n",
2837 charging_disabled ? "" : "charger enabled");
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002838 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002839 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002840
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002841 power_supply_changed(&chip->batt_psy);
2842 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002843 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002844
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002845 return IRQ_HANDLED;
2846}
2847
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002848static irqreturn_t chgwdog_irq_handler(int irq, void *data)
2849{
2850 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
2851 return IRQ_HANDLED;
2852}
2853
2854static irqreturn_t vcp_irq_handler(int irq, void *data)
2855{
David Keitel8c5201a2012-02-24 16:08:54 -08002856 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002857 return IRQ_HANDLED;
2858}
2859
2860static irqreturn_t atcdone_irq_handler(int irq, void *data)
2861{
2862 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
2863 return IRQ_HANDLED;
2864}
2865
2866static irqreturn_t atcfail_irq_handler(int irq, void *data)
2867{
2868 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
2869 return IRQ_HANDLED;
2870}
2871
2872static irqreturn_t chgdone_irq_handler(int irq, void *data)
2873{
2874 struct pm8921_chg_chip *chip = data;
2875
2876 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02002877
2878 handle_stop_ext_chg(chip);
2879
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002880 power_supply_changed(&chip->batt_psy);
2881 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002882 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002883
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07002884 bms_notify_check(chip);
2885
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002886 return IRQ_HANDLED;
2887}
2888
2889static irqreturn_t chgfail_irq_handler(int irq, void *data)
2890{
2891 struct pm8921_chg_chip *chip = data;
David Keitel753ec8d2011-11-02 10:56:37 -07002892 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002893
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002894 if (!chip->stop_chg_upon_expiry) {
2895 ret = pm_chg_failed_clear(chip, 1);
2896 if (ret)
2897 pr_err("Failed to write CHG_FAILED_CLEAR bit\n");
2898 }
David Keitel753ec8d2011-11-02 10:56:37 -07002899
2900 pr_err("batt_present = %d, batt_temp_ok = %d, state_changed_to=%d\n",
2901 get_prop_batt_present(chip),
2902 pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ),
2903 pm_chg_get_fsm_state(data));
2904
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002905 power_supply_changed(&chip->batt_psy);
2906 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002907 power_supply_changed(&chip->dc_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002908 return IRQ_HANDLED;
2909}
2910
2911static irqreturn_t chgstate_irq_handler(int irq, void *data)
2912{
2913 struct pm8921_chg_chip *chip = data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002914
2915 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
2916 power_supply_changed(&chip->batt_psy);
2917 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002918 power_supply_changed(&chip->dc_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002919
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07002920 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002921
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002922 return IRQ_HANDLED;
2923}
2924
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002925enum {
2926 PON_TIME_25NS = 0x04,
2927 PON_TIME_50NS = 0x08,
2928 PON_TIME_100NS = 0x0C,
2929};
David Keitel8c5201a2012-02-24 16:08:54 -08002930
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002931static void set_min_pon_time(struct pm8921_chg_chip *chip, int pon_time_ns)
David Keitel8c5201a2012-02-24 16:08:54 -08002932{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002933 u8 temp;
2934 int rc;
David Keitel8c5201a2012-02-24 16:08:54 -08002935
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002936 rc = pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0x40);
2937 if (rc) {
2938 pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
2939 return;
2940 }
2941 rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
2942 if (rc) {
2943 pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
2944 return;
2945 }
2946 /* clear the min pon time select bit */
2947 temp &= 0xF3;
2948 /* set the pon time */
2949 temp |= (u8)pon_time_ns;
2950 /* write enable bank 4 */
2951 temp |= 0x80;
2952 rc = pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, temp);
2953 if (rc) {
2954 pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
2955 return;
2956 }
2957}
David Keitel8c5201a2012-02-24 16:08:54 -08002958
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002959static void attempt_reverse_boost_fix(struct pm8921_chg_chip *chip)
2960{
2961 pr_debug("Start\n");
2962 set_min_pon_time(chip, PON_TIME_100NS);
2963 pm_chg_vinmin_set(chip, chip->vin_min + 200);
2964 msleep(250);
2965 pm_chg_vinmin_set(chip, chip->vin_min);
2966 set_min_pon_time(chip, PON_TIME_25NS);
2967 pr_debug("End\n");
David Keitel8c5201a2012-02-24 16:08:54 -08002968}
2969
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002970#define VIN_ACTIVE_BIT BIT(0)
David Keitel6ccbf132012-05-30 14:21:24 -07002971#define UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US 200
2972#define VIN_MIN_INCREASE_MV 100
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002973static void unplug_check_worker(struct work_struct *work)
2974{
2975 struct delayed_work *dwork = to_delayed_work(work);
2976 struct pm8921_chg_chip *chip = container_of(dwork,
2977 struct pm8921_chg_chip, unplug_check_work);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002978 u8 reg_loop = 0, active_path;
David Keitel6ccbf132012-05-30 14:21:24 -07002979 int rc, ibat, active_chg_plugged_in, usb_ma;
David Keitel8c5201a2012-02-24 16:08:54 -08002980 int chg_gone = 0;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002981 bool ramp = false;
David Keitel6ccbf132012-05-30 14:21:24 -07002982
2983 rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS1, &active_path);
2984 if (rc) {
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002985 pr_err("Failed to read PBL_ACCESS1 rc=%d\n", rc);
2986 return;
David Keitel6ccbf132012-05-30 14:21:24 -07002987 }
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002988
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002989 chip->active_path = active_path;
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002990 active_chg_plugged_in = is_active_chg_plugged_in(chip, active_path);
David Keitel6ccbf132012-05-30 14:21:24 -07002991 pr_debug("active_path = 0x%x, active_chg_plugged_in = %d\n",
2992 active_path, active_chg_plugged_in);
2993 if (active_path & USB_ACTIVE_BIT) {
2994 pr_debug("USB charger active\n");
2995
2996 pm_chg_iusbmax_get(chip, &usb_ma);
Devin Kim2073afb2012-09-05 13:01:51 -07002997
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002998 if (usb_ma <= 100) {
2999 pr_debug(
3000 "Unenumerated or suspended usb_ma = %d skip\n",
3001 usb_ma);
3002 goto check_again_later;
David Keitel6ccbf132012-05-30 14:21:24 -07003003 }
3004 } else if (active_path & DC_ACTIVE_BIT) {
3005 pr_debug("DC charger active\n");
3006 } else {
3007 /* No charger active */
3008 if (!(is_usb_chg_plugged_in(chip)
3009 && !(is_dc_chg_plugged_in(chip)))) {
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08003010 pr_debug(
David Keitel6ccbf132012-05-30 14:21:24 -07003011 "Stop: chg removed reg_loop = %d, fsm = %d ibat = %d\n",
3012 pm_chg_get_regulation_loop(chip),
3013 pm_chg_get_fsm_state(chip),
3014 get_prop_batt_current(chip)
3015 );
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003016 if (chip->lockup_lpm_wrkarnd) {
3017 rc = pm8921_apply_19p2mhz_kickstart(chip);
3018 if (rc)
3019 pr_err("Failed kickstart rc=%d\n", rc);
3020
3021 /*
3022 * Make sure kickstart happens at least 200 ms
3023 * after charger has been removed.
3024 */
3025 if (chip->final_kickstart) {
3026 chip->final_kickstart = false;
3027 goto check_again_later;
3028 }
3029 }
3030 return;
3031 } else {
3032 goto check_again_later;
David Keitel6ccbf132012-05-30 14:21:24 -07003033 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003034 }
David Keitel8c5201a2012-02-24 16:08:54 -08003035
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003036 chip->final_kickstart = true;
3037
3038 /* AICL only for usb wall charger */
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08003039 if ((active_path & USB_ACTIVE_BIT) && usb_target_ma > 0 &&
3040 !chip->disable_aicl) {
David Keitel6ccbf132012-05-30 14:21:24 -07003041 reg_loop = pm_chg_get_regulation_loop(chip);
3042 pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
3043 if ((reg_loop & VIN_ACTIVE_BIT) &&
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003044 (usb_ma > USB_WALL_THRESHOLD_MA)
3045 && !charging_disabled) {
David Keitel6ccbf132012-05-30 14:21:24 -07003046 decrease_usb_ma_value(&usb_ma);
3047 usb_target_ma = usb_ma;
3048 /* end AICL here */
3049 __pm8921_charger_vbus_draw(usb_ma);
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08003050 pr_debug("usb_now=%d, usb_target = %d\n",
David Keitel6ccbf132012-05-30 14:21:24 -07003051 usb_ma, usb_target_ma);
3052 }
David Keitelacf57c82012-03-07 18:48:50 -08003053 }
3054
3055 reg_loop = pm_chg_get_regulation_loop(chip);
3056 pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
3057
David Keitel6ccbf132012-05-30 14:21:24 -07003058 ibat = get_prop_batt_current(chip);
David Keitelacf57c82012-03-07 18:48:50 -08003059 if (reg_loop & VIN_ACTIVE_BIT) {
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003060 if (ibat > 0) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003061 pr_debug("revboost ibat = %d fsm = %d loop = 0x%x\n",
3062 ibat, pm_chg_get_fsm_state(chip), reg_loop);
3063 attempt_reverse_boost_fix(chip);
3064 /* after reverse boost fix check if the active
3065 * charger was detected as removed */
3066 active_chg_plugged_in
3067 = is_active_chg_plugged_in(chip,
3068 active_path);
3069 pr_debug("revboost post: active_chg_plugged_in = %d\n",
3070 active_chg_plugged_in);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003071 }
3072 }
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08003073
3074 active_chg_plugged_in = is_active_chg_plugged_in(chip, active_path);
David Keitel6ccbf132012-05-30 14:21:24 -07003075 pr_debug("active_path = 0x%x, active_chg = %d\n",
3076 active_path, active_chg_plugged_in);
David Keitel8c5201a2012-02-24 16:08:54 -08003077 chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
3078
David Keitel6ccbf132012-05-30 14:21:24 -07003079 if (chg_gone == 1 && active_chg_plugged_in == 1) {
3080 pr_debug("chg_gone=%d, active_chg_plugged_in = %d\n",
3081 chg_gone, active_chg_plugged_in);
David Keitelc3e15bd2012-05-25 17:07:25 -07003082 unplug_ovp_fet_open(chip);
David Keitel8c5201a2012-02-24 16:08:54 -08003083 }
3084
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003085 /* AICL only for usb wall charger */
3086 if (!(reg_loop & VIN_ACTIVE_BIT) && (active_path & USB_ACTIVE_BIT)
3087 && usb_target_ma > 0
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08003088 && !charging_disabled
3089 && !chip->disable_aicl) {
David Keitelacf57c82012-03-07 18:48:50 -08003090 /* only increase iusb_max if vin loop not active */
3091 if (usb_ma < usb_target_ma) {
3092 increase_usb_ma_value(&usb_ma);
Anirudh Ghayal0ddca632013-01-23 16:43:31 +05303093 if (usb_ma > usb_target_ma)
3094 usb_ma = usb_target_ma;
David Keitelacf57c82012-03-07 18:48:50 -08003095 __pm8921_charger_vbus_draw(usb_ma);
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08003096 pr_debug("usb_now=%d, usb_target = %d\n",
David Keitelacf57c82012-03-07 18:48:50 -08003097 usb_ma, usb_target_ma);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003098 ramp = true;
Devin Kim2073afb2012-09-05 13:01:51 -07003099 } else {
3100 usb_target_ma = usb_ma;
David Keitelacf57c82012-03-07 18:48:50 -08003101 }
3102 }
Devin Kim2073afb2012-09-05 13:01:51 -07003103check_again_later:
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003104 pr_debug("ramp: %d\n", ramp);
David Keitelacf57c82012-03-07 18:48:50 -08003105 /* schedule to check again later */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003106 if (ramp)
3107 schedule_delayed_work(&chip->unplug_check_work,
3108 msecs_to_jiffies(UNPLUG_CHECK_RAMP_MS));
3109 else
3110 schedule_delayed_work(&chip->unplug_check_work,
3111 msecs_to_jiffies(UNPLUG_CHECK_WAIT_PERIOD_MS));
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003112}
3113
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003114static irqreturn_t loop_change_irq_handler(int irq, void *data)
3115{
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003116 struct pm8921_chg_chip *chip = data;
3117
3118 pr_debug("fsm_state=%d reg_loop=0x%x\n",
3119 pm_chg_get_fsm_state(data),
3120 pm_chg_get_regulation_loop(data));
David Keitelb57db9e2012-03-28 16:08:43 -07003121 schedule_work(&chip->unplug_check_work.work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003122 return IRQ_HANDLED;
3123}
3124
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003125struct ibatmax_max_adj_entry {
3126 int ibat_max_ma;
3127 int max_adj_ma;
3128};
3129
3130static struct ibatmax_max_adj_entry ibatmax_adj_table[] = {
3131 {975, 300},
3132 {1475, 150},
3133 {1975, 200},
3134 {2475, 250},
3135};
3136
3137static int find_ibat_max_adj_ma(int ibat_target_ma)
3138{
3139 int i = 0;
3140
Abhijeet Dharmapurikare7e27af2013-02-12 14:44:04 -08003141 for (i = ARRAY_SIZE(ibatmax_adj_table); i > 0; i--) {
3142 if (ibat_target_ma >= ibatmax_adj_table[i - 1].ibat_max_ma)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003143 break;
3144 }
3145
3146 return ibatmax_adj_table[i].max_adj_ma;
3147}
3148
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003149static irqreturn_t fastchg_irq_handler(int irq, void *data)
3150{
3151 struct pm8921_chg_chip *chip = data;
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07003152 int high_transition;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003153
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07003154 high_transition = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
3155 if (high_transition && !delayed_work_pending(&chip->eoc_work)) {
3156 wake_lock(&chip->eoc_wake_lock);
3157 schedule_delayed_work(&chip->eoc_work,
3158 round_jiffies_relative(msecs_to_jiffies
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003159 (EOC_CHECK_PERIOD_MS)));
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07003160 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003161 if (high_transition
3162 && chip->btc_override
3163 && !delayed_work_pending(&chip->btc_override_work)) {
3164 schedule_delayed_work(&chip->btc_override_work,
3165 round_jiffies_relative(msecs_to_jiffies
3166 (chip->btc_delay_ms)));
3167 }
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07003168 power_supply_changed(&chip->batt_psy);
3169 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003170 return IRQ_HANDLED;
3171}
3172
3173static irqreturn_t trklchg_irq_handler(int irq, void *data)
3174{
3175 struct pm8921_chg_chip *chip = data;
3176
3177 power_supply_changed(&chip->batt_psy);
3178 return IRQ_HANDLED;
3179}
3180
3181static irqreturn_t batt_removed_irq_handler(int irq, void *data)
3182{
3183 struct pm8921_chg_chip *chip = data;
3184 int status;
3185
3186 status = pm_chg_get_rt_status(chip, BATT_REMOVED_IRQ);
3187 pr_debug("battery present=%d state=%d", !status,
3188 pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02003189 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003190 power_supply_changed(&chip->batt_psy);
3191 return IRQ_HANDLED;
3192}
3193
3194static irqreturn_t batttemp_hot_irq_handler(int irq, void *data)
3195{
3196 struct pm8921_chg_chip *chip = data;
3197
Amir Samuelovd31ef502011-10-26 14:41:36 +02003198 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003199 power_supply_changed(&chip->batt_psy);
3200 return IRQ_HANDLED;
3201}
3202
3203static irqreturn_t chghot_irq_handler(int irq, void *data)
3204{
3205 struct pm8921_chg_chip *chip = data;
3206
3207 pr_debug("Chg hot fsm_state=%d\n", pm_chg_get_fsm_state(data));
3208 power_supply_changed(&chip->batt_psy);
3209 power_supply_changed(&chip->usb_psy);
David Keitel88e1b572012-01-11 11:57:14 -08003210 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003211 return IRQ_HANDLED;
3212}
3213
3214static irqreturn_t batttemp_cold_irq_handler(int irq, void *data)
3215{
3216 struct pm8921_chg_chip *chip = data;
3217
3218 pr_debug("Batt cold fsm_state=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02003219 handle_stop_ext_chg(chip);
3220
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003221 power_supply_changed(&chip->batt_psy);
3222 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003223 return IRQ_HANDLED;
3224}
3225
3226static irqreturn_t chg_gone_irq_handler(int irq, void *data)
3227{
3228 struct pm8921_chg_chip *chip = data;
David Keitelc3e15bd2012-05-25 17:07:25 -07003229 int chg_gone, usb_chg_plugged_in;
David Keitel8c5201a2012-02-24 16:08:54 -08003230
3231 usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
3232 chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
3233
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08003234 pr_debug("chg_gone=%d, usb_valid = %d\n", chg_gone, usb_chg_plugged_in);
3235 pr_debug("Chg gone fsm_state=%d\n", pm_chg_get_fsm_state(data));
David Keitel0873d0f2012-03-29 11:44:49 -07003236
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003237 power_supply_changed(&chip->batt_psy);
3238 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003239 return IRQ_HANDLED;
3240}
David Keitel52fda532011-11-10 10:43:44 -08003241/*
3242 *
3243 * bat_temp_ok_irq_handler - is edge triggered, hence it will
3244 * fire for two cases:
3245 *
3246 * If the interrupt line switches to high temperature is okay
3247 * and thus charging begins.
3248 * If bat_temp_ok is low this means the temperature is now
3249 * too hot or cold, so charging is stopped.
3250 *
3251 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003252static irqreturn_t bat_temp_ok_irq_handler(int irq, void *data)
3253{
David Keitel52fda532011-11-10 10:43:44 -08003254 int bat_temp_ok;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003255 struct pm8921_chg_chip *chip = data;
3256
David Keitel52fda532011-11-10 10:43:44 -08003257 bat_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
3258
3259 pr_debug("batt_temp_ok = %d fsm_state%d\n",
3260 bat_temp_ok, pm_chg_get_fsm_state(data));
3261
3262 if (bat_temp_ok)
3263 handle_start_ext_chg(chip);
3264 else
3265 handle_stop_ext_chg(chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02003266
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003267 power_supply_changed(&chip->batt_psy);
3268 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07003269 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003270 return IRQ_HANDLED;
3271}
3272
3273static irqreturn_t coarse_det_low_irq_handler(int irq, void *data)
3274{
3275 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3276 return IRQ_HANDLED;
3277}
3278
3279static irqreturn_t vdd_loop_irq_handler(int irq, void *data)
3280{
3281 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3282 return IRQ_HANDLED;
3283}
3284
3285static irqreturn_t vreg_ov_irq_handler(int irq, void *data)
3286{
3287 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3288 return IRQ_HANDLED;
3289}
3290
3291static irqreturn_t vbatdet_irq_handler(int irq, void *data)
3292{
3293 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3294 return IRQ_HANDLED;
3295}
3296
3297static irqreturn_t batfet_irq_handler(int irq, void *data)
3298{
3299 struct pm8921_chg_chip *chip = data;
3300
3301 pr_debug("vreg ov\n");
3302 power_supply_changed(&chip->batt_psy);
3303 return IRQ_HANDLED;
3304}
3305
3306static irqreturn_t dcin_valid_irq_handler(int irq, void *data)
3307{
Amir Samuelovd31ef502011-10-26 14:41:36 +02003308 struct pm8921_chg_chip *chip = data;
David Keitel88e1b572012-01-11 11:57:14 -08003309 int dc_present;
Amir Samuelovd31ef502011-10-26 14:41:36 +02003310
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003311 pm_chg_failed_clear(chip, 1);
David Keitel88e1b572012-01-11 11:57:14 -08003312 dc_present = pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003313
3314 if (chip->dc_present ^ dc_present)
3315 pm8921_bms_calibrate_hkadc();
3316
David Keitel88e1b572012-01-11 11:57:14 -08003317 if (dc_present)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003318 pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
David Keitel88e1b572012-01-11 11:57:14 -08003319 else
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003320 pm8921_chg_disable_irq(chip, CHG_GONE_IRQ);
3321
3322 chip->dc_present = dc_present;
3323
3324 if (chip->ext_psy) {
3325 if (dc_present)
3326 handle_start_ext_chg(chip);
3327 else
3328 handle_stop_ext_chg(chip);
3329 } else {
3330 if (chip->lockup_lpm_wrkarnd)
3331 /* if no external supply call bypass debounce here */
3332 pm8921_chg_bypass_bat_gone_debounce(chip,
3333 is_chg_on_bat(chip));
3334
3335 if (dc_present)
3336 schedule_delayed_work(&chip->unplug_check_work,
3337 msecs_to_jiffies(UNPLUG_CHECK_WAIT_PERIOD_MS));
3338 power_supply_changed(&chip->dc_psy);
3339 }
3340
3341 power_supply_changed(&chip->batt_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003342 return IRQ_HANDLED;
3343}
3344
3345static irqreturn_t dcin_ov_irq_handler(int irq, void *data)
3346{
Amir Samuelovd31ef502011-10-26 14:41:36 +02003347 struct pm8921_chg_chip *chip = data;
3348
Amir Samuelovd31ef502011-10-26 14:41:36 +02003349 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003350 return IRQ_HANDLED;
3351}
3352
3353static irqreturn_t dcin_uv_irq_handler(int irq, void *data)
3354{
Amir Samuelovd31ef502011-10-26 14:41:36 +02003355 struct pm8921_chg_chip *chip = data;
3356
Amir Samuelovd31ef502011-10-26 14:41:36 +02003357 handle_stop_ext_chg(chip);
3358
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003359 return IRQ_HANDLED;
3360}
3361
David Keitel88e1b572012-01-11 11:57:14 -08003362static int __pm_batt_external_power_changed_work(struct device *dev, void *data)
3363{
3364 struct power_supply *psy = &the_chip->batt_psy;
3365 struct power_supply *epsy = dev_get_drvdata(dev);
3366 int i, dcin_irq;
3367
3368 /* Only search for external supply if none is registered */
3369 if (!the_chip->ext_psy) {
3370 dcin_irq = the_chip->pmic_chg_irq[DCIN_VALID_IRQ];
3371 for (i = 0; i < epsy->num_supplicants; i++) {
3372 if (!strncmp(epsy->supplied_to[i], psy->name, 7)) {
3373 if (!strncmp(epsy->name, "dc", 2)) {
3374 the_chip->ext_psy = epsy;
3375 dcin_valid_irq_handler(dcin_irq,
3376 the_chip);
3377 }
3378 }
3379 }
3380 }
3381 return 0;
3382}
3383
3384static void pm_batt_external_power_changed(struct power_supply *psy)
3385{
3386 /* Only look for an external supply if it hasn't been registered */
3387 if (!the_chip->ext_psy)
3388 class_for_each_device(power_supply_class, NULL, psy,
3389 __pm_batt_external_power_changed_work);
3390}
3391
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003392/**
3393 * update_heartbeat - internal function to update userspace
3394 * per update_time minutes
3395 *
3396 */
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -07003397#define LOW_SOC_HEARTBEAT_MS 20000
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003398static void update_heartbeat(struct work_struct *work)
3399{
3400 struct delayed_work *dwork = to_delayed_work(work);
3401 struct pm8921_chg_chip *chip = container_of(dwork,
3402 struct pm8921_chg_chip, update_heartbeat_work);
3403
3404 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -07003405 if (chip->recent_reported_soc <= 20)
3406 schedule_delayed_work(&chip->update_heartbeat_work,
3407 round_jiffies_relative(msecs_to_jiffies
3408 (LOW_SOC_HEARTBEAT_MS)));
3409 else
3410 schedule_delayed_work(&chip->update_heartbeat_work,
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003411 round_jiffies_relative(msecs_to_jiffies
3412 (chip->update_time)));
3413}
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003414#define VDD_LOOP_ACTIVE_BIT BIT(3)
3415#define VDD_MAX_INCREASE_MV 400
3416static int vdd_max_increase_mv = VDD_MAX_INCREASE_MV;
3417module_param(vdd_max_increase_mv, int, 0644);
3418
3419static int ichg_threshold_ua = -400000;
3420module_param(ichg_threshold_ua, int, 0644);
Abhijeet Dharmapurikardc3323a2012-08-10 15:47:31 -07003421
3422#define PM8921_CHG_VDDMAX_RES_MV 10
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003423static void adjust_vdd_max_for_fastchg(struct pm8921_chg_chip *chip,
3424 int vbat_batt_terminal_uv)
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003425{
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003426 int adj_vdd_max_mv, programmed_vdd_max;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003427 int vbat_batt_terminal_mv;
3428 int reg_loop;
3429 int delta_mv = 0;
3430
3431 if (chip->rconn_mohm == 0) {
3432 pr_debug("Exiting as rconn_mohm is 0\n");
3433 return;
3434 }
3435 /* adjust vdd_max only in normal temperature zone */
3436 if (chip->is_bat_cool || chip->is_bat_warm) {
3437 pr_debug("Exiting is_bat_cool = %d is_batt_warm = %d\n",
3438 chip->is_bat_cool, chip->is_bat_warm);
3439 return;
3440 }
3441
3442 reg_loop = pm_chg_get_regulation_loop(chip);
3443 if (!(reg_loop & VDD_LOOP_ACTIVE_BIT)) {
3444 pr_debug("Exiting Vdd loop is not active reg loop=0x%x\n",
3445 reg_loop);
3446 return;
3447 }
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003448 vbat_batt_terminal_mv = vbat_batt_terminal_uv/1000;
3449 pm_chg_vddmax_get(the_chip, &programmed_vdd_max);
3450
3451 delta_mv = chip->max_voltage_mv - vbat_batt_terminal_mv;
3452
3453 adj_vdd_max_mv = programmed_vdd_max + delta_mv;
3454 pr_debug("vdd_max needs to be changed by %d mv from %d to %d\n",
3455 delta_mv,
3456 programmed_vdd_max,
3457 adj_vdd_max_mv);
3458
3459 if (adj_vdd_max_mv < chip->max_voltage_mv) {
3460 pr_debug("adj vdd_max lower than default max voltage\n");
3461 return;
3462 }
3463
Abhijeet Dharmapurikardc3323a2012-08-10 15:47:31 -07003464 adj_vdd_max_mv = DIV_ROUND_UP(adj_vdd_max_mv, PM8921_CHG_VDDMAX_RES_MV)
3465 * PM8921_CHG_VDDMAX_RES_MV;
3466
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003467 if (adj_vdd_max_mv > (chip->max_voltage_mv + vdd_max_increase_mv))
3468 adj_vdd_max_mv = chip->max_voltage_mv + vdd_max_increase_mv;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003469 pr_debug("adjusting vdd_max_mv to %d to make "
3470 "vbat_batt_termial_uv = %d to %d\n",
3471 adj_vdd_max_mv, vbat_batt_terminal_uv, chip->max_voltage_mv);
3472 pm_chg_vddmax_set(chip, adj_vdd_max_mv);
3473}
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003474
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003475static void set_appropriate_vbatdet(struct pm8921_chg_chip *chip)
3476{
3477 if (chip->is_bat_cool)
3478 pm_chg_vbatdet_set(the_chip,
3479 the_chip->cool_bat_voltage
3480 - the_chip->resume_voltage_delta);
3481 else if (chip->is_bat_warm)
3482 pm_chg_vbatdet_set(the_chip,
3483 the_chip->warm_bat_voltage
3484 - the_chip->resume_voltage_delta);
3485 else
3486 pm_chg_vbatdet_set(the_chip,
3487 the_chip->max_voltage_mv
3488 - the_chip->resume_voltage_delta);
3489}
3490
3491static void set_appropriate_battery_current(struct pm8921_chg_chip *chip)
3492{
3493 unsigned int chg_current = chip->max_bat_chg_current;
3494
3495 if (chip->is_bat_cool)
3496 chg_current = min(chg_current, chip->cool_bat_chg_current);
3497
3498 if (chip->is_bat_warm)
3499 chg_current = min(chg_current, chip->warm_bat_chg_current);
3500
3501 if (thermal_mitigation != 0 && chip->thermal_mitigation)
3502 chg_current = min(chg_current,
3503 chip->thermal_mitigation[thermal_mitigation]);
3504
3505 pm_chg_ibatmax_set(the_chip, chg_current);
3506}
3507
3508#define TEMP_HYSTERISIS_DECIDEGC 20
3509static void battery_cool(bool enter)
3510{
3511 pr_debug("enter = %d\n", enter);
3512 if (enter == the_chip->is_bat_cool)
3513 return;
3514 the_chip->is_bat_cool = enter;
3515 if (enter)
3516 pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
3517 else
3518 pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
3519 set_appropriate_battery_current(the_chip);
3520 set_appropriate_vbatdet(the_chip);
3521}
3522
3523static void battery_warm(bool enter)
3524{
3525 pr_debug("enter = %d\n", enter);
3526 if (enter == the_chip->is_bat_warm)
3527 return;
3528 the_chip->is_bat_warm = enter;
3529 if (enter)
3530 pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
3531 else
3532 pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
3533
3534 set_appropriate_battery_current(the_chip);
3535 set_appropriate_vbatdet(the_chip);
3536}
3537
3538static void check_temp_thresholds(struct pm8921_chg_chip *chip)
3539{
3540 int temp = 0;
3541
3542 temp = get_prop_batt_temp(chip);
3543 pr_debug("temp = %d, warm_thr_temp = %d, cool_thr_temp = %d\n",
3544 temp, chip->warm_temp_dc,
3545 chip->cool_temp_dc);
3546
3547 if (chip->warm_temp_dc != INT_MIN) {
3548 if (chip->is_bat_warm
3549 && temp < chip->warm_temp_dc - TEMP_HYSTERISIS_DECIDEGC)
3550 battery_warm(false);
3551 else if (!chip->is_bat_warm && temp >= chip->warm_temp_dc)
3552 battery_warm(true);
3553 }
3554
3555 if (chip->cool_temp_dc != INT_MIN) {
3556 if (chip->is_bat_cool
3557 && temp > chip->cool_temp_dc + TEMP_HYSTERISIS_DECIDEGC)
3558 battery_cool(false);
3559 else if (!chip->is_bat_cool && temp <= chip->cool_temp_dc)
3560 battery_cool(true);
3561 }
3562}
3563
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003564enum {
3565 CHG_IN_PROGRESS,
3566 CHG_NOT_IN_PROGRESS,
3567 CHG_FINISHED,
3568};
3569
3570#define VBAT_TOLERANCE_MV 70
3571#define CHG_DISABLE_MSLEEP 100
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003572static int is_charging_finished(struct pm8921_chg_chip *chip,
3573 int vbat_batt_terminal_uv, int ichg_meas_ma)
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003574{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003575 int vbat_programmed, iterm_programmed, vbat_intended;
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003576 int regulation_loop, fast_chg, vcp;
3577 int rc;
3578 static int last_vbat_programmed = -EINVAL;
3579
3580 if (!is_ext_charging(chip)) {
3581 /* return if the battery is not being fastcharged */
3582 fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
3583 pr_debug("fast_chg = %d\n", fast_chg);
3584 if (fast_chg == 0)
3585 return CHG_NOT_IN_PROGRESS;
3586
3587 vcp = pm_chg_get_rt_status(chip, VCP_IRQ);
3588 pr_debug("vcp = %d\n", vcp);
3589 if (vcp == 1)
3590 return CHG_IN_PROGRESS;
3591
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003592 /* reset count if battery is hot/cold */
3593 rc = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
3594 pr_debug("batt_temp_ok = %d\n", rc);
3595 if (rc == 0)
3596 return CHG_IN_PROGRESS;
3597
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003598 rc = pm_chg_vddmax_get(chip, &vbat_programmed);
3599 if (rc) {
3600 pr_err("couldnt read vddmax rc = %d\n", rc);
3601 return CHG_IN_PROGRESS;
3602 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003603 pr_debug("vddmax = %d vbat_batt_terminal_uv=%d\n",
3604 vbat_programmed, vbat_batt_terminal_uv);
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003605
3606 if (last_vbat_programmed == -EINVAL)
3607 last_vbat_programmed = vbat_programmed;
3608 if (last_vbat_programmed != vbat_programmed) {
3609 /* vddmax changed, reset and check again */
3610 pr_debug("vddmax = %d last_vdd_max=%d\n",
3611 vbat_programmed, last_vbat_programmed);
3612 last_vbat_programmed = vbat_programmed;
3613 return CHG_IN_PROGRESS;
3614 }
3615
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003616 if (chip->is_bat_cool)
3617 vbat_intended = chip->cool_bat_voltage;
3618 else if (chip->is_bat_warm)
3619 vbat_intended = chip->warm_bat_voltage;
3620 else
3621 vbat_intended = chip->max_voltage_mv;
3622
3623 if (vbat_batt_terminal_uv / 1000 < vbat_intended) {
3624 pr_debug("terminal_uv:%d < vbat_intended:%d.\n",
3625 vbat_batt_terminal_uv,
3626 vbat_intended);
3627 return CHG_IN_PROGRESS;
3628 }
3629
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003630 regulation_loop = pm_chg_get_regulation_loop(chip);
3631 if (regulation_loop < 0) {
3632 pr_err("couldnt read the regulation loop err=%d\n",
3633 regulation_loop);
3634 return CHG_IN_PROGRESS;
3635 }
3636 pr_debug("regulation_loop=%d\n", regulation_loop);
3637
3638 if (regulation_loop != 0 && regulation_loop != VDD_LOOP)
3639 return CHG_IN_PROGRESS;
3640 } /* !is_ext_charging */
3641
3642 /* reset count if battery chg current is more than iterm */
3643 rc = pm_chg_iterm_get(chip, &iterm_programmed);
3644 if (rc) {
3645 pr_err("couldnt read iterm rc = %d\n", rc);
3646 return CHG_IN_PROGRESS;
3647 }
3648
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003649 pr_debug("iterm_programmed = %d ichg_meas_ma=%d\n",
3650 iterm_programmed, ichg_meas_ma);
3651 /*
3652 * ichg_meas_ma < 0 means battery is drawing current
3653 * ichg_meas_ma > 0 means battery is providing current
3654 */
3655 if (ichg_meas_ma > 0)
3656 return CHG_IN_PROGRESS;
3657
3658 if (ichg_meas_ma * -1 > iterm_programmed)
3659 return CHG_IN_PROGRESS;
3660
3661 return CHG_FINISHED;
3662}
3663
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003664#define COMP_OVERRIDE_HOT_BANK 6
3665#define COMP_OVERRIDE_COLD_BANK 7
3666#define COMP_OVERRIDE_BIT BIT(1)
3667static int pm_chg_override_cold(struct pm8921_chg_chip *chip, int flag)
3668{
3669 u8 val;
3670 int rc = 0;
3671
3672 val = 0x80 | COMP_OVERRIDE_COLD_BANK << 2 | COMP_OVERRIDE_BIT;
3673
3674 if (flag)
3675 val |= 0x01;
3676
3677 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3678 if (rc < 0)
3679 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3680
3681 pr_debug("btc cold = %d val = 0x%x\n", flag, val);
3682 return rc;
3683}
3684
3685static int pm_chg_override_hot(struct pm8921_chg_chip *chip, int flag)
3686{
3687 u8 val;
3688 int rc = 0;
3689
3690 val = 0x80 | COMP_OVERRIDE_HOT_BANK << 2 | COMP_OVERRIDE_BIT;
3691
3692 if (flag)
3693 val |= 0x01;
3694
3695 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3696 if (rc < 0)
3697 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3698
3699 pr_debug("btc hot = %d val = 0x%x\n", flag, val);
3700 return rc;
3701}
3702
3703static void __devinit pm8921_chg_btc_override_init(struct pm8921_chg_chip *chip)
3704{
3705 int rc = 0;
3706 u8 reg;
3707 u8 val;
3708
3709 val = COMP_OVERRIDE_HOT_BANK << 2;
3710 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3711 if (rc < 0) {
3712 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3713 goto cold_init;
3714 }
3715 rc = pm8xxx_readb(chip->dev->parent, COMPARATOR_OVERRIDE, &reg);
3716 if (rc < 0) {
3717 pr_err("Could not read bank %d of override rc = %d\n",
3718 COMP_OVERRIDE_HOT_BANK, rc);
3719 goto cold_init;
3720 }
3721 if ((reg & COMP_OVERRIDE_BIT) != COMP_OVERRIDE_BIT) {
3722 /* for now override it as not hot */
3723 rc = pm_chg_override_hot(chip, 0);
3724 if (rc < 0)
3725 pr_err("Could not override hot rc = %d\n", rc);
3726 }
3727
3728cold_init:
3729 val = COMP_OVERRIDE_COLD_BANK << 2;
3730 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3731 if (rc < 0) {
3732 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3733 return;
3734 }
3735 rc = pm8xxx_readb(chip->dev->parent, COMPARATOR_OVERRIDE, &reg);
3736 if (rc < 0) {
3737 pr_err("Could not read bank %d of override rc = %d\n",
3738 COMP_OVERRIDE_COLD_BANK, rc);
3739 return;
3740 }
3741 if ((reg & COMP_OVERRIDE_BIT) != COMP_OVERRIDE_BIT) {
3742 /* for now override it as not cold */
3743 rc = pm_chg_override_cold(chip, 0);
3744 if (rc < 0)
3745 pr_err("Could not override cold rc = %d\n", rc);
3746 }
3747}
3748
3749static void btc_override_worker(struct work_struct *work)
3750{
3751 int decidegc;
3752 int temp;
3753 int rc = 0;
3754 struct delayed_work *dwork = to_delayed_work(work);
3755 struct pm8921_chg_chip *chip = container_of(dwork,
3756 struct pm8921_chg_chip, btc_override_work);
3757
3758 if (!chip->btc_override) {
3759 pr_err("called when not enabled\n");
3760 return;
3761 }
3762
3763 decidegc = get_prop_batt_temp(chip);
3764
3765 pr_debug("temp=%d\n", decidegc);
3766
3767 temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
3768 if (temp) {
3769 if (decidegc < chip->btc_override_hot_decidegc)
3770 /* stop forcing batt hot */
3771 rc = pm_chg_override_hot(chip, 0);
3772 if (rc)
3773 pr_err("Couldnt write 0 to hot comp\n");
3774 } else {
3775 if (decidegc >= chip->btc_override_hot_decidegc)
3776 /* start forcing batt hot */
3777 rc = pm_chg_override_hot(chip, 1);
3778 if (rc && chip->btc_panic_if_cant_stop_chg)
3779 panic("Couldnt override comps to stop chg\n");
3780 }
3781
3782 temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
3783 if (temp) {
3784 if (decidegc > chip->btc_override_cold_decidegc)
3785 /* stop forcing batt cold */
3786 rc = pm_chg_override_cold(chip, 0);
3787 if (rc)
3788 pr_err("Couldnt write 0 to cold comp\n");
3789 } else {
3790 if (decidegc <= chip->btc_override_cold_decidegc)
3791 /* start forcing batt cold */
3792 rc = pm_chg_override_cold(chip, 1);
3793 if (rc && chip->btc_panic_if_cant_stop_chg)
3794 panic("Couldnt override comps to stop chg\n");
3795 }
3796
3797 if ((is_dc_chg_plugged_in(the_chip) || is_usb_chg_plugged_in(the_chip))
3798 && get_prop_batt_status(chip) != POWER_SUPPLY_STATUS_FULL) {
3799 schedule_delayed_work(&chip->btc_override_work,
3800 round_jiffies_relative(msecs_to_jiffies
3801 (chip->btc_delay_ms)));
3802 return;
3803 }
3804
3805 rc = pm_chg_override_hot(chip, 0);
3806 if (rc)
3807 pr_err("Couldnt write 0 to hot comp\n");
3808 rc = pm_chg_override_cold(chip, 0);
3809 if (rc)
3810 pr_err("Couldnt write 0 to cold comp\n");
3811}
3812
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003813/**
Amir Samuelovd31ef502011-10-26 14:41:36 +02003814 * eoc_worker - internal function to check if battery EOC
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003815 * has happened
3816 *
3817 * If all conditions favouring, if the charge current is
3818 * less than the term current for three consecutive times
3819 * an EOC has happened.
3820 * The wakelock is released if there is no need to reshedule
3821 * - this happens when the battery is removed or EOC has
3822 * happened
3823 */
3824#define CONSECUTIVE_COUNT 3
Amir Samuelovd31ef502011-10-26 14:41:36 +02003825static void eoc_worker(struct work_struct *work)
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003826{
3827 struct delayed_work *dwork = to_delayed_work(work);
3828 struct pm8921_chg_chip *chip = container_of(dwork,
3829 struct pm8921_chg_chip, eoc_work);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003830 static int count;
Abhijeet Dharmapurikare451f342012-02-23 16:39:42 -08003831 int end;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003832 int vbat_meas_uv, vbat_meas_mv;
3833 int ichg_meas_ua, ichg_meas_ma;
3834 int vbat_batt_terminal_uv;
Abhijeet Dharmapurikare451f342012-02-23 16:39:42 -08003835
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003836 pm8921_bms_get_simultaneous_battery_voltage_and_current(
3837 &ichg_meas_ua, &vbat_meas_uv);
3838 vbat_meas_mv = vbat_meas_uv / 1000;
3839 /* rconn_mohm is in milliOhms */
3840 ichg_meas_ma = ichg_meas_ua / 1000;
3841 vbat_batt_terminal_uv = vbat_meas_uv
3842 + ichg_meas_ma
3843 * the_chip->rconn_mohm;
3844
3845 end = is_charging_finished(chip, vbat_batt_terminal_uv, ichg_meas_ma);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003846
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003847 if (end == CHG_NOT_IN_PROGRESS) {
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003848 count = 0;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003849 goto eoc_worker_stop;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07003850 }
3851
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003852 if (end == CHG_FINISHED) {
3853 count++;
3854 } else {
3855 count = 0;
3856 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003857
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003858 if (count == CONSECUTIVE_COUNT) {
3859 count = 0;
3860 pr_info("End of Charging\n");
3861
3862 pm_chg_auto_enable(chip, 0);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003863
Amir Samuelovd31ef502011-10-26 14:41:36 +02003864 if (is_ext_charging(chip))
3865 chip->ext_charge_done = true;
3866
Abhijeet Dharmapurikareb882f52011-12-22 09:02:34 -08003867 if (chip->is_bat_warm || chip->is_bat_cool)
3868 chip->bms_notify.is_battery_full = 0;
3869 else
3870 chip->bms_notify.is_battery_full = 1;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003871 /* declare end of charging by invoking chgdone interrupt */
3872 chgdone_irq_handler(chip->pmic_chg_irq[CHGDONE_IRQ], chip);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003873 } else {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003874 check_temp_thresholds(chip);
3875 adjust_vdd_max_for_fastchg(chip, vbat_batt_terminal_uv);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003876 pr_debug("EOC count = %d\n", count);
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003877 schedule_delayed_work(&chip->eoc_work,
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003878 round_jiffies_relative(msecs_to_jiffies
3879 (EOC_CHECK_PERIOD_MS)));
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08003880 return;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003881 }
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003882
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003883eoc_worker_stop:
3884 wake_unlock(&chip->eoc_wake_lock);
3885 /* set the vbatdet back, in case it was changed to trigger charging */
3886 set_appropriate_vbatdet(chip);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003887}
3888
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07003889/**
3890 * set_disable_status_param -
3891 *
3892 * Internal function to disable battery charging and also disable drawing
3893 * any current from the source. The device is forced to run on a battery
3894 * after this.
3895 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003896static int set_disable_status_param(const char *val, struct kernel_param *kp)
3897{
3898 int ret;
3899 struct pm8921_chg_chip *chip = the_chip;
3900
3901 ret = param_set_int(val, kp);
3902 if (ret) {
3903 pr_err("error setting value %d\n", ret);
3904 return ret;
3905 }
3906 pr_info("factory set disable param to %d\n", charging_disabled);
3907 if (chip) {
3908 pm_chg_auto_enable(chip, !charging_disabled);
3909 pm_chg_charge_dis(chip, charging_disabled);
3910 }
3911 return 0;
3912}
3913module_param_call(disabled, set_disable_status_param, param_get_uint,
3914 &charging_disabled, 0644);
3915
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003916static int rconn_mohm;
3917static int set_rconn_mohm(const char *val, struct kernel_param *kp)
3918{
3919 int ret;
3920 struct pm8921_chg_chip *chip = the_chip;
3921
3922 ret = param_set_int(val, kp);
3923 if (ret) {
3924 pr_err("error setting value %d\n", ret);
3925 return ret;
3926 }
3927 if (chip)
3928 chip->rconn_mohm = rconn_mohm;
3929 return 0;
3930}
3931module_param_call(rconn_mohm, set_rconn_mohm, param_get_uint,
3932 &rconn_mohm, 0644);
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07003933/**
3934 * set_thermal_mitigation_level -
3935 *
3936 * Internal function to control battery charging current to reduce
3937 * temperature
3938 */
3939static int set_therm_mitigation_level(const char *val, struct kernel_param *kp)
3940{
3941 int ret;
3942 struct pm8921_chg_chip *chip = the_chip;
3943
3944 ret = param_set_int(val, kp);
3945 if (ret) {
3946 pr_err("error setting value %d\n", ret);
3947 return ret;
3948 }
3949
3950 if (!chip) {
3951 pr_err("called before init\n");
3952 return -EINVAL;
3953 }
3954
3955 if (!chip->thermal_mitigation) {
3956 pr_err("no thermal mitigation\n");
3957 return -EINVAL;
3958 }
3959
3960 if (thermal_mitigation < 0
3961 || thermal_mitigation >= chip->thermal_levels) {
3962 pr_err("out of bound level selected\n");
3963 return -EINVAL;
3964 }
3965
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08003966 set_appropriate_battery_current(chip);
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07003967 return ret;
3968}
3969module_param_call(thermal_mitigation, set_therm_mitigation_level,
3970 param_get_uint,
3971 &thermal_mitigation, 0644);
3972
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08003973static int set_usb_max_current(const char *val, struct kernel_param *kp)
3974{
3975 int ret, mA;
3976 struct pm8921_chg_chip *chip = the_chip;
3977
3978 ret = param_set_int(val, kp);
3979 if (ret) {
3980 pr_err("error setting value %d\n", ret);
3981 return ret;
3982 }
3983 if (chip) {
3984 pr_warn("setting current max to %d\n", usb_max_current);
3985 pm_chg_iusbmax_get(chip, &mA);
3986 if (mA > usb_max_current)
3987 pm8921_charger_vbus_draw(usb_max_current);
3988 return 0;
3989 }
3990 return -EINVAL;
3991}
David Keitelacf57c82012-03-07 18:48:50 -08003992module_param_call(usb_max_current, set_usb_max_current,
3993 param_get_uint, &usb_max_current, 0644);
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08003994
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003995static void free_irqs(struct pm8921_chg_chip *chip)
3996{
3997 int i;
3998
3999 for (i = 0; i < PM_CHG_MAX_INTS; i++)
4000 if (chip->pmic_chg_irq[i]) {
4001 free_irq(chip->pmic_chg_irq[i], chip);
4002 chip->pmic_chg_irq[i] = 0;
4003 }
4004}
4005
David Keitel88e1b572012-01-11 11:57:14 -08004006/* determines the initial present states */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004007static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
4008{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004009 int fsm_state;
Abhijeet Dharmapurikard9ad07e2012-09-17 16:59:36 -07004010 int is_fast_chg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004011
4012 chip->dc_present = !!is_dc_chg_plugged_in(chip);
4013 chip->usb_present = !!is_usb_chg_plugged_in(chip);
4014
4015 notify_usb_of_the_plugin_event(chip->usb_present);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004016 if (chip->usb_present || chip->dc_present) {
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004017 schedule_delayed_work(&chip->unplug_check_work,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004018 msecs_to_jiffies(UNPLUG_CHECK_WAIT_PERIOD_MS));
David Keitel8c5201a2012-02-24 16:08:54 -08004019 pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004020 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004021
4022 pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
4023 pm8921_chg_enable_irq(chip, USBIN_VALID_IRQ);
4024 pm8921_chg_enable_irq(chip, BATT_REMOVED_IRQ);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004025 pm8921_chg_enable_irq(chip, BATT_INSERTED_IRQ);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004026 pm8921_chg_enable_irq(chip, DCIN_OV_IRQ);
4027 pm8921_chg_enable_irq(chip, DCIN_UV_IRQ);
David Keitel753ec8d2011-11-02 10:56:37 -07004028 pm8921_chg_enable_irq(chip, CHGFAIL_IRQ);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004029 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
4030 pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08004031 pm8921_chg_enable_irq(chip, BAT_TEMP_OK_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004032
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08004033 if (get_prop_batt_present(the_chip) || is_dc_chg_plugged_in(the_chip))
4034 if (usb_chg_current)
4035 /*
4036 * Reissue a vbus draw call only if a battery
4037 * or DC is present. We don't want to brown out the
4038 * device if usb is its only source
4039 */
4040 __pm8921_charger_vbus_draw(usb_chg_current);
4041 usb_chg_current = 0;
4042
Abhijeet Dharmapurikard9ad07e2012-09-17 16:59:36 -07004043 /*
4044 * The bootloader could have started charging, a fastchg interrupt
4045 * might not happen. Check the real time status and if it is fast
4046 * charging invoke the handler so that the eoc worker could be
4047 * started
4048 */
4049 is_fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
4050 if (is_fast_chg)
4051 fastchg_irq_handler(chip->pmic_chg_irq[FASTCHG_IRQ], chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004052
4053 fsm_state = pm_chg_get_fsm_state(chip);
4054 if (is_battery_charging(fsm_state)) {
4055 chip->bms_notify.is_charging = 1;
4056 pm8921_bms_charging_began();
4057 }
4058
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07004059 check_battery_valid(chip);
4060
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004061 pr_debug("usb = %d, dc = %d batt = %d state=%d\n",
4062 chip->usb_present,
4063 chip->dc_present,
4064 get_prop_batt_present(chip),
4065 fsm_state);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004066
4067 /* Determine which USB trim column to use */
4068 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
4069 chip->usb_trim_table = usb_trim_8917_table;
4070 else if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8038)
4071 chip->usb_trim_table = usb_trim_8038_table;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004072}
4073
4074struct pm_chg_irq_init_data {
4075 unsigned int irq_id;
4076 char *name;
4077 unsigned long flags;
4078 irqreturn_t (*handler)(int, void *);
4079};
4080
4081#define CHG_IRQ(_id, _flags, _handler) \
4082{ \
4083 .irq_id = _id, \
4084 .name = #_id, \
4085 .flags = _flags, \
4086 .handler = _handler, \
4087}
4088struct pm_chg_irq_init_data chg_irq_data[] = {
4089 CHG_IRQ(USBIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4090 usbin_valid_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004091 CHG_IRQ(BATT_INSERTED_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4092 batt_inserted_irq_handler),
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07004093 CHG_IRQ(VBATDET_LOW_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4094 vbatdet_low_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004095 CHG_IRQ(CHGWDOG_IRQ, IRQF_TRIGGER_RISING, chgwdog_irq_handler),
4096 CHG_IRQ(VCP_IRQ, IRQF_TRIGGER_RISING, vcp_irq_handler),
4097 CHG_IRQ(ATCDONE_IRQ, IRQF_TRIGGER_RISING, atcdone_irq_handler),
4098 CHG_IRQ(ATCFAIL_IRQ, IRQF_TRIGGER_RISING, atcfail_irq_handler),
4099 CHG_IRQ(CHGDONE_IRQ, IRQF_TRIGGER_RISING, chgdone_irq_handler),
4100 CHG_IRQ(CHGFAIL_IRQ, IRQF_TRIGGER_RISING, chgfail_irq_handler),
4101 CHG_IRQ(CHGSTATE_IRQ, IRQF_TRIGGER_RISING, chgstate_irq_handler),
4102 CHG_IRQ(LOOP_CHANGE_IRQ, IRQF_TRIGGER_RISING, loop_change_irq_handler),
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07004103 CHG_IRQ(FASTCHG_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4104 fastchg_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004105 CHG_IRQ(TRKLCHG_IRQ, IRQF_TRIGGER_RISING, trklchg_irq_handler),
4106 CHG_IRQ(BATT_REMOVED_IRQ, IRQF_TRIGGER_RISING,
4107 batt_removed_irq_handler),
4108 CHG_IRQ(BATTTEMP_HOT_IRQ, IRQF_TRIGGER_RISING,
4109 batttemp_hot_irq_handler),
4110 CHG_IRQ(CHGHOT_IRQ, IRQF_TRIGGER_RISING, chghot_irq_handler),
4111 CHG_IRQ(BATTTEMP_COLD_IRQ, IRQF_TRIGGER_RISING,
4112 batttemp_cold_irq_handler),
David Keitel8c5201a2012-02-24 16:08:54 -08004113 CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4114 chg_gone_irq_handler),
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07004115 CHG_IRQ(BAT_TEMP_OK_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4116 bat_temp_ok_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004117 CHG_IRQ(COARSE_DET_LOW_IRQ, IRQF_TRIGGER_RISING,
4118 coarse_det_low_irq_handler),
4119 CHG_IRQ(VDD_LOOP_IRQ, IRQF_TRIGGER_RISING, vdd_loop_irq_handler),
4120 CHG_IRQ(VREG_OV_IRQ, IRQF_TRIGGER_RISING, vreg_ov_irq_handler),
4121 CHG_IRQ(VBATDET_IRQ, IRQF_TRIGGER_RISING, vbatdet_irq_handler),
4122 CHG_IRQ(BATFET_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4123 batfet_irq_handler),
4124 CHG_IRQ(DCIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4125 dcin_valid_irq_handler),
4126 CHG_IRQ(DCIN_OV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4127 dcin_ov_irq_handler),
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -07004128 CHG_IRQ(DCIN_UV_IRQ, IRQF_TRIGGER_RISING, dcin_uv_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004129};
4130
4131static int __devinit request_irqs(struct pm8921_chg_chip *chip,
4132 struct platform_device *pdev)
4133{
4134 struct resource *res;
4135 int ret, i;
4136
4137 ret = 0;
4138 bitmap_fill(chip->enabled_irqs, PM_CHG_MAX_INTS);
4139
4140 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
4141 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
4142 chg_irq_data[i].name);
4143 if (res == NULL) {
4144 pr_err("couldn't find %s\n", chg_irq_data[i].name);
4145 goto err_out;
4146 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004147 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = res->start;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004148 ret = request_irq(res->start, chg_irq_data[i].handler,
4149 chg_irq_data[i].flags,
4150 chg_irq_data[i].name, chip);
4151 if (ret < 0) {
4152 pr_err("couldn't request %d (%s) %d\n", res->start,
4153 chg_irq_data[i].name, ret);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004154 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004155 goto err_out;
4156 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004157 pm8921_chg_disable_irq(chip, chg_irq_data[i].irq_id);
4158 }
4159 return 0;
4160
4161err_out:
4162 free_irqs(chip);
4163 return -EINVAL;
4164}
4165
Abhijeet Dharmapurikared2d87e2012-06-26 20:15:36 -07004166#define VREF_BATT_THERM_FORCE_ON BIT(7)
4167static void detect_battery_removal(struct pm8921_chg_chip *chip)
4168{
4169 u8 temp;
4170
4171 pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
4172 pr_debug("upon restart CHG_CNTRL = 0x%x\n", temp);
4173
4174 if (!(temp & VREF_BATT_THERM_FORCE_ON))
4175 /*
4176 * batt therm force on bit is battery backed and is default 0
4177 * The charger sets this bit at init time. If this bit is found
4178 * 0 that means the battery was removed. Tell the bms about it
4179 */
4180 pm8921_bms_invalidate_shutdown_soc();
4181}
4182
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004183#define ENUM_TIMER_STOP_BIT BIT(1)
4184#define BOOT_DONE_BIT BIT(6)
4185#define CHG_BATFET_ON_BIT BIT(3)
4186#define CHG_VCP_EN BIT(0)
4187#define CHG_BAT_TEMP_DIS_BIT BIT(2)
4188#define SAFE_CURRENT_MA 1500
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004189#define PM_SUB_REV 0x001
4190#define MIN_CHARGE_CURRENT_MA 350
4191#define DEFAULT_SAFETY_MINUTES 500
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004192static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
4193{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004194 u8 subrev;
4195 int rc, vdd_safe, fcc_uah, safety_time = DEFAULT_SAFETY_MINUTES;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004196
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004197 spin_lock_init(&lpm_lock);
Abhijeet Dharmapurikarf5abc1c2013-01-30 21:51:37 -08004198
4199 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8921) {
4200 rc = __pm8921_apply_19p2mhz_kickstart(chip);
4201 if (rc) {
4202 pr_err("Failed to apply kickstart rc=%d\n", rc);
4203 return rc;
4204 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004205 }
Abhijeet Dharmapurikarc3695de2012-06-22 14:50:23 -07004206
Abhijeet Dharmapurikared2d87e2012-06-26 20:15:36 -07004207 detect_battery_removal(chip);
4208
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004209 rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004210 BOOT_DONE_BIT, BOOT_DONE_BIT);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004211 if (rc) {
4212 pr_err("Failed to set BOOT_DONE_BIT rc=%d\n", rc);
4213 return rc;
4214 }
4215
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08004216 vdd_safe = chip->max_voltage_mv + VDD_MAX_INCREASE_MV;
4217
4218 if (vdd_safe > PM8921_CHG_VDDSAFE_MAX)
4219 vdd_safe = PM8921_CHG_VDDSAFE_MAX;
4220
4221 rc = pm_chg_vddsafe_set(chip, vdd_safe);
4222
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004223 if (rc) {
4224 pr_err("Failed to set safe voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004225 chip->max_voltage_mv, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004226 return rc;
4227 }
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004228 rc = pm_chg_vbatdet_set(chip,
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004229 chip->max_voltage_mv
4230 - chip->resume_voltage_delta);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004231 if (rc) {
4232 pr_err("Failed to set vbatdet comprator voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004233 chip->max_voltage_mv - chip->resume_voltage_delta, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004234 return rc;
4235 }
4236
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004237 rc = pm_chg_vddmax_set(chip, chip->max_voltage_mv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004238 if (rc) {
4239 pr_err("Failed to set max voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004240 chip->max_voltage_mv, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004241 return rc;
4242 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004243
4244 if (chip->safe_current_ma == 0)
4245 chip->safe_current_ma = SAFE_CURRENT_MA;
4246
4247 rc = pm_chg_ibatsafe_set(chip, chip->safe_current_ma);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004248 if (rc) {
4249 pr_err("Failed to set max voltage to %d rc=%d\n",
4250 SAFE_CURRENT_MA, rc);
4251 return rc;
4252 }
4253
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004254 rc = pm_chg_ibatmax_set(chip, chip->max_bat_chg_current);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004255 if (rc) {
4256 pr_err("Failed to set max current to 400 rc=%d\n", rc);
4257 return rc;
4258 }
4259
4260 rc = pm_chg_iterm_set(chip, chip->term_current);
4261 if (rc) {
4262 pr_err("Failed to set term current to %d rc=%d\n",
4263 chip->term_current, rc);
4264 return rc;
4265 }
4266
4267 /* Disable the ENUM TIMER */
4268 rc = pm_chg_masked_write(chip, PBL_ACCESS2, ENUM_TIMER_STOP_BIT,
4269 ENUM_TIMER_STOP_BIT);
4270 if (rc) {
4271 pr_err("Failed to set enum timer stop rc=%d\n", rc);
4272 return rc;
4273 }
4274
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004275 fcc_uah = pm8921_bms_get_fcc();
4276 if (fcc_uah > 0) {
4277 safety_time = div_s64((s64)fcc_uah * 60,
4278 1000 * MIN_CHARGE_CURRENT_MA);
4279 /* add 20 minutes of buffer time */
4280 safety_time += 20;
4281
4282 /* make sure we do not exceed the maximum programmable time */
4283 if (safety_time > PM8921_CHG_TCHG_MAX)
4284 safety_time = PM8921_CHG_TCHG_MAX;
4285 }
4286
4287 rc = pm_chg_tchg_max_set(chip, safety_time);
4288 if (rc) {
4289 pr_err("Failed to set max time to %d minutes rc=%d\n",
4290 safety_time, rc);
4291 return rc;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004292 }
4293
4294 if (chip->ttrkl_time != 0) {
Abhijeet Dharmapurikare45c3d32011-10-19 19:46:48 -07004295 rc = pm_chg_ttrkl_max_set(chip, chip->ttrkl_time);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004296 if (rc) {
4297 pr_err("Failed to set trkl time to %d minutes rc=%d\n",
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004298 chip->ttrkl_time, rc);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004299 return rc;
4300 }
4301 }
4302
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07004303 if (chip->vin_min != 0) {
4304 rc = pm_chg_vinmin_set(chip, chip->vin_min);
4305 if (rc) {
4306 pr_err("Failed to set vin min to %d mV rc=%d\n",
4307 chip->vin_min, rc);
4308 return rc;
4309 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004310 } else {
4311 chip->vin_min = pm_chg_vinmin_get(chip);
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07004312 }
4313
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004314 rc = pm_chg_disable_wd(chip);
4315 if (rc) {
4316 pr_err("Failed to disable wd rc=%d\n", rc);
4317 return rc;
4318 }
4319
4320 rc = pm_chg_masked_write(chip, CHG_CNTRL_2,
4321 CHG_BAT_TEMP_DIS_BIT, 0);
4322 if (rc) {
4323 pr_err("Failed to enable temp control chg rc=%d\n", rc);
4324 return rc;
4325 }
4326 /* switch to a 3.2Mhz for the buck */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004327 if (pm8xxx_get_revision(chip->dev->parent) >= PM8XXX_REVISION_8038_1p0)
4328 rc = pm_chg_write(chip,
4329 CHG_BUCK_CLOCK_CTRL_8038, 0x15);
4330 else
4331 rc = pm_chg_write(chip,
4332 CHG_BUCK_CLOCK_CTRL, 0x15);
4333
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004334 if (rc) {
4335 pr_err("Failed to switch buck clk rc=%d\n", rc);
4336 return rc;
4337 }
4338
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07004339 if (chip->trkl_voltage != 0) {
4340 rc = pm_chg_vtrkl_low_set(chip, chip->trkl_voltage);
4341 if (rc) {
4342 pr_err("Failed to set trkl voltage to %dmv rc=%d\n",
4343 chip->trkl_voltage, rc);
4344 return rc;
4345 }
4346 }
4347
4348 if (chip->weak_voltage != 0) {
4349 rc = pm_chg_vweak_set(chip, chip->weak_voltage);
4350 if (rc) {
4351 pr_err("Failed to set weak voltage to %dmv rc=%d\n",
4352 chip->weak_voltage, rc);
4353 return rc;
4354 }
4355 }
4356
4357 if (chip->trkl_current != 0) {
4358 rc = pm_chg_itrkl_set(chip, chip->trkl_current);
4359 if (rc) {
4360 pr_err("Failed to set trkl current to %dmA rc=%d\n",
4361 chip->trkl_voltage, rc);
4362 return rc;
4363 }
4364 }
4365
4366 if (chip->weak_current != 0) {
4367 rc = pm_chg_iweak_set(chip, chip->weak_current);
4368 if (rc) {
4369 pr_err("Failed to set weak current to %dmA rc=%d\n",
4370 chip->weak_current, rc);
4371 return rc;
4372 }
4373 }
4374
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07004375 rc = pm_chg_batt_cold_temp_config(chip, chip->cold_thr);
4376 if (rc) {
4377 pr_err("Failed to set cold config %d rc=%d\n",
4378 chip->cold_thr, rc);
4379 }
4380
4381 rc = pm_chg_batt_hot_temp_config(chip, chip->hot_thr);
4382 if (rc) {
4383 pr_err("Failed to set hot config %d rc=%d\n",
4384 chip->hot_thr, rc);
4385 }
4386
Jay Chokshid674a512012-03-15 14:06:04 -07004387 rc = pm_chg_led_src_config(chip, chip->led_src_config);
4388 if (rc) {
4389 pr_err("Failed to set charger LED src config %d rc=%d\n",
4390 chip->led_src_config, rc);
4391 }
4392
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004393 /* Workarounds for die 3.0 */
4394 if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0
4395 && pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8921) {
4396 rc = pm8xxx_readb(chip->dev->parent, PM_SUB_REV, &subrev);
4397 if (rc) {
4398 pr_err("read failed: addr=%03X, rc=%d\n",
4399 PM_SUB_REV, rc);
4400 return rc;
4401 }
4402 /* Check if die 3.0.1 is present */
4403 if (subrev & 0x1)
4404 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xA4);
4405 else
4406 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xAC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004407 }
4408
David Keitel0789fc62012-06-07 17:43:27 -07004409 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004410 /* Set PM8917 USB_OVP debounce time to 15 ms */
4411 rc = pm_chg_masked_write(chip, USB_OVP_CONTROL,
4412 OVP_DEBOUNCE_TIME, 0x6);
4413 if (rc) {
4414 pr_err("Failed to set USB OVP db rc=%d\n", rc);
4415 return rc;
4416 }
4417
4418 /* Enable isub_fine resolution AICL for PM8917 */
David Keitel38bdd4f2012-04-19 15:39:13 -07004419 chip->iusb_fine_res = true;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004420 if (chip->uvd_voltage_mv) {
David Keitel0789fc62012-06-07 17:43:27 -07004421 rc = pm_chg_uvd_threshold_set(chip,
4422 chip->uvd_voltage_mv);
4423 if (rc) {
4424 pr_err("Failed to set UVD threshold %drc=%d\n",
4425 chip->uvd_voltage_mv, rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004426 return rc;
4427 }
David Keitel0789fc62012-06-07 17:43:27 -07004428 }
4429 }
David Keitel38bdd4f2012-04-19 15:39:13 -07004430
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004431 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xD9);
David Keitelb51995e2011-11-18 17:03:31 -08004432
David Keitela3c0d822011-11-03 14:18:52 -07004433 /* Disable EOC FSM processing */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004434 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0x91);
David Keitela3c0d822011-11-03 14:18:52 -07004435
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004436 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
4437 VREF_BATT_THERM_FORCE_ON);
4438 if (rc)
4439 pr_err("Failed to Force Vref therm rc=%d\n", rc);
4440
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004441 rc = pm_chg_charge_dis(chip, charging_disabled);
4442 if (rc) {
4443 pr_err("Failed to disable CHG_CHARGE_DIS bit rc=%d\n", rc);
4444 return rc;
4445 }
4446
4447 rc = pm_chg_auto_enable(chip, !charging_disabled);
4448 if (rc) {
4449 pr_err("Failed to enable charging rc=%d\n", rc);
4450 return rc;
4451 }
4452
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004453 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8921) {
4454 /* Clear kickstart */
4455 rc = pm8xxx_writeb(chip->dev->parent, CHG_TEST, 0xD0);
4456 if (rc) {
4457 pr_err("Failed to clear kickstart rc=%d\n", rc);
4458 return rc;
4459 }
4460
4461 /* From here the lpm_workaround will be active */
4462 chip->lockup_lpm_wrkarnd = true;
4463
4464 /* Enable LPM */
4465 pm8921_chg_set_lpm(chip, 1);
4466 }
4467
4468 if (chip->lockup_lpm_wrkarnd) {
4469 chip->vreg_xoadc = regulator_get(chip->dev, "vreg_xoadc");
4470 if (IS_ERR(chip->vreg_xoadc))
4471 return -ENODEV;
4472
4473 rc = regulator_set_optimum_mode(chip->vreg_xoadc, 10000);
4474 if (rc < 0) {
4475 pr_err("Failed to set configure HPM rc=%d\n", rc);
4476 return rc;
4477 }
4478
4479 rc = regulator_set_voltage(chip->vreg_xoadc, 1800000, 1800000);
4480 if (rc) {
4481 pr_err("Failed to set L14 voltage rc=%d\n", rc);
4482 return rc;
4483 }
4484
4485 rc = regulator_enable(chip->vreg_xoadc);
4486 if (rc) {
4487 pr_err("Failed to enable L14 rc=%d\n", rc);
4488 return rc;
4489 }
4490 }
4491
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004492 return 0;
4493}
4494
4495static int get_rt_status(void *data, u64 * val)
4496{
4497 int i = (int)data;
4498 int ret;
4499
4500 /* global irq number is passed in via data */
4501 ret = pm_chg_get_rt_status(the_chip, i);
4502 *val = ret;
4503 return 0;
4504}
4505DEFINE_SIMPLE_ATTRIBUTE(rt_fops, get_rt_status, NULL, "%llu\n");
4506
4507static int get_fsm_status(void *data, u64 * val)
4508{
4509 u8 temp;
4510
4511 temp = pm_chg_get_fsm_state(the_chip);
4512 *val = temp;
4513 return 0;
4514}
4515DEFINE_SIMPLE_ATTRIBUTE(fsm_fops, get_fsm_status, NULL, "%llu\n");
4516
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004517static int get_reg_loop(void *data, u64 * val)
4518{
4519 u8 temp;
4520
4521 if (!the_chip) {
4522 pr_err("%s called before init\n", __func__);
4523 return -EINVAL;
4524 }
4525 temp = pm_chg_get_regulation_loop(the_chip);
4526 *val = temp;
4527 return 0;
4528}
4529DEFINE_SIMPLE_ATTRIBUTE(reg_loop_fops, get_reg_loop, NULL, "0x%02llx\n");
4530
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004531static int get_reg(void *data, u64 * val)
4532{
4533 int addr = (int)data;
4534 int ret;
4535 u8 temp;
4536
4537 ret = pm8xxx_readb(the_chip->dev->parent, addr, &temp);
4538 if (ret) {
4539 pr_err("pm8xxx_readb to %x value =%d errored = %d\n",
4540 addr, temp, ret);
4541 return -EAGAIN;
4542 }
4543 *val = temp;
4544 return 0;
4545}
4546
4547static int set_reg(void *data, u64 val)
4548{
4549 int addr = (int)data;
4550 int ret;
4551 u8 temp;
4552
4553 temp = (u8) val;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004554 ret = pm_chg_write(the_chip, addr, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004555 if (ret) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004556 pr_err("pm_chg_write to %x value =%d errored = %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004557 addr, temp, ret);
4558 return -EAGAIN;
4559 }
4560 return 0;
4561}
4562DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
4563
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004564static int reg_loop;
4565#define MAX_REG_LOOP_CHAR 10
4566static int get_reg_loop_param(char *buf, struct kernel_param *kp)
4567{
4568 u8 temp;
4569
4570 if (!the_chip) {
4571 pr_err("called before init\n");
4572 return -EINVAL;
4573 }
4574 temp = pm_chg_get_regulation_loop(the_chip);
4575 return snprintf(buf, MAX_REG_LOOP_CHAR, "%d", temp);
4576}
4577module_param_call(reg_loop, NULL, get_reg_loop_param,
4578 &reg_loop, 0644);
4579
4580static int max_chg_ma;
4581#define MAX_MA_CHAR 10
4582static int get_max_chg_ma_param(char *buf, struct kernel_param *kp)
4583{
4584 if (!the_chip) {
4585 pr_err("called before init\n");
4586 return -EINVAL;
4587 }
4588 return snprintf(buf, MAX_MA_CHAR, "%d", the_chip->max_bat_chg_current);
4589}
4590module_param_call(max_chg_ma, NULL, get_max_chg_ma_param,
4591 &max_chg_ma, 0644);
4592static int ibatmax_ma;
4593static int set_ibat_max(const char *val, struct kernel_param *kp)
4594{
4595 int rc;
4596
4597 if (!the_chip) {
4598 pr_err("called before init\n");
4599 return -EINVAL;
4600 }
4601
4602 rc = param_set_int(val, kp);
4603 if (rc) {
4604 pr_err("error setting value %d\n", rc);
4605 return rc;
4606 }
4607
4608 if (abs(ibatmax_ma - the_chip->max_bat_chg_current)
4609 <= the_chip->ibatmax_max_adj_ma) {
4610 rc = pm_chg_ibatmax_set(the_chip, ibatmax_ma);
4611 if (rc) {
4612 pr_err("Failed to set ibatmax rc = %d\n", rc);
4613 return rc;
4614 }
4615 }
4616
4617 return 0;
4618}
4619static int get_ibat_max(char *buf, struct kernel_param *kp)
4620{
4621 int ibat_ma;
4622 int rc;
4623
4624 if (!the_chip) {
4625 pr_err("called before init\n");
4626 return -EINVAL;
4627 }
4628
4629 rc = pm_chg_ibatmax_get(the_chip, &ibat_ma);
4630 if (rc) {
4631 pr_err("ibatmax_get error = %d\n", rc);
4632 return rc;
4633 }
4634
4635 return snprintf(buf, MAX_MA_CHAR, "%d", ibat_ma);
4636}
4637module_param_call(ibatmax_ma, set_ibat_max, get_ibat_max,
4638 &ibatmax_ma, 0644);
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004639enum {
4640 BAT_WARM_ZONE,
4641 BAT_COOL_ZONE,
4642};
4643static int get_warm_cool(void *data, u64 * val)
4644{
4645 if (!the_chip) {
4646 pr_err("%s called before init\n", __func__);
4647 return -EINVAL;
4648 }
4649 if ((int)data == BAT_WARM_ZONE)
4650 *val = the_chip->is_bat_warm;
4651 if ((int)data == BAT_COOL_ZONE)
4652 *val = the_chip->is_bat_cool;
4653 return 0;
4654}
4655DEFINE_SIMPLE_ATTRIBUTE(warm_cool_fops, get_warm_cool, NULL, "0x%lld\n");
4656
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004657static void create_debugfs_entries(struct pm8921_chg_chip *chip)
4658{
4659 int i;
4660
4661 chip->dent = debugfs_create_dir("pm8921_chg", NULL);
4662
4663 if (IS_ERR(chip->dent)) {
4664 pr_err("pmic charger couldnt create debugfs dir\n");
4665 return;
4666 }
4667
4668 debugfs_create_file("CHG_CNTRL", 0644, chip->dent,
4669 (void *)CHG_CNTRL, &reg_fops);
4670 debugfs_create_file("CHG_CNTRL_2", 0644, chip->dent,
4671 (void *)CHG_CNTRL_2, &reg_fops);
4672 debugfs_create_file("CHG_CNTRL_3", 0644, chip->dent,
4673 (void *)CHG_CNTRL_3, &reg_fops);
4674 debugfs_create_file("PBL_ACCESS1", 0644, chip->dent,
4675 (void *)PBL_ACCESS1, &reg_fops);
4676 debugfs_create_file("PBL_ACCESS2", 0644, chip->dent,
4677 (void *)PBL_ACCESS2, &reg_fops);
4678 debugfs_create_file("SYS_CONFIG_1", 0644, chip->dent,
4679 (void *)SYS_CONFIG_1, &reg_fops);
4680 debugfs_create_file("SYS_CONFIG_2", 0644, chip->dent,
4681 (void *)SYS_CONFIG_2, &reg_fops);
4682 debugfs_create_file("CHG_VDD_MAX", 0644, chip->dent,
4683 (void *)CHG_VDD_MAX, &reg_fops);
4684 debugfs_create_file("CHG_VDD_SAFE", 0644, chip->dent,
4685 (void *)CHG_VDD_SAFE, &reg_fops);
4686 debugfs_create_file("CHG_VBAT_DET", 0644, chip->dent,
4687 (void *)CHG_VBAT_DET, &reg_fops);
4688 debugfs_create_file("CHG_IBAT_MAX", 0644, chip->dent,
4689 (void *)CHG_IBAT_MAX, &reg_fops);
4690 debugfs_create_file("CHG_IBAT_SAFE", 0644, chip->dent,
4691 (void *)CHG_IBAT_SAFE, &reg_fops);
4692 debugfs_create_file("CHG_VIN_MIN", 0644, chip->dent,
4693 (void *)CHG_VIN_MIN, &reg_fops);
4694 debugfs_create_file("CHG_VTRICKLE", 0644, chip->dent,
4695 (void *)CHG_VTRICKLE, &reg_fops);
4696 debugfs_create_file("CHG_ITRICKLE", 0644, chip->dent,
4697 (void *)CHG_ITRICKLE, &reg_fops);
4698 debugfs_create_file("CHG_ITERM", 0644, chip->dent,
4699 (void *)CHG_ITERM, &reg_fops);
4700 debugfs_create_file("CHG_TCHG_MAX", 0644, chip->dent,
4701 (void *)CHG_TCHG_MAX, &reg_fops);
4702 debugfs_create_file("CHG_TWDOG", 0644, chip->dent,
4703 (void *)CHG_TWDOG, &reg_fops);
4704 debugfs_create_file("CHG_TEMP_THRESH", 0644, chip->dent,
4705 (void *)CHG_TEMP_THRESH, &reg_fops);
4706 debugfs_create_file("CHG_COMP_OVR", 0644, chip->dent,
4707 (void *)CHG_COMP_OVR, &reg_fops);
4708 debugfs_create_file("CHG_BUCK_CTRL_TEST1", 0644, chip->dent,
4709 (void *)CHG_BUCK_CTRL_TEST1, &reg_fops);
4710 debugfs_create_file("CHG_BUCK_CTRL_TEST2", 0644, chip->dent,
4711 (void *)CHG_BUCK_CTRL_TEST2, &reg_fops);
4712 debugfs_create_file("CHG_BUCK_CTRL_TEST3", 0644, chip->dent,
4713 (void *)CHG_BUCK_CTRL_TEST3, &reg_fops);
4714 debugfs_create_file("CHG_TEST", 0644, chip->dent,
4715 (void *)CHG_TEST, &reg_fops);
4716
4717 debugfs_create_file("FSM_STATE", 0644, chip->dent, NULL,
4718 &fsm_fops);
4719
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004720 debugfs_create_file("REGULATION_LOOP_CONTROL", 0644, chip->dent, NULL,
4721 &reg_loop_fops);
4722
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004723 debugfs_create_file("BAT_WARM_ZONE", 0644, chip->dent,
4724 (void *)BAT_WARM_ZONE, &warm_cool_fops);
4725 debugfs_create_file("BAT_COOL_ZONE", 0644, chip->dent,
4726 (void *)BAT_COOL_ZONE, &warm_cool_fops);
4727
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004728 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
4729 if (chip->pmic_chg_irq[chg_irq_data[i].irq_id])
4730 debugfs_create_file(chg_irq_data[i].name, 0444,
4731 chip->dent,
4732 (void *)chg_irq_data[i].irq_id,
4733 &rt_fops);
4734 }
4735}
4736
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004737static int pm8921_charger_suspend_noirq(struct device *dev)
4738{
4739 int rc;
4740 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4741
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004742 if (chip->lockup_lpm_wrkarnd) {
4743 rc = regulator_disable(chip->vreg_xoadc);
4744 if (rc)
4745 pr_err("Failed to disable L14 rc=%d\n", rc);
4746
4747 rc = pm8921_apply_19p2mhz_kickstart(chip);
4748 if (rc)
4749 pr_err("Failed to apply kickstart rc=%d\n", rc);
4750 }
4751
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004752 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON, 0);
4753 if (rc)
4754 pr_err("Failed to Force Vref therm off rc=%d\n", rc);
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004755 return 0;
4756}
4757
4758static int pm8921_charger_resume_noirq(struct device *dev)
4759{
4760 int rc;
4761 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4762
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004763 if (chip->lockup_lpm_wrkarnd) {
4764 rc = regulator_enable(chip->vreg_xoadc);
4765 if (rc)
4766 pr_err("Failed to enable L14 rc=%d\n", rc);
4767
4768 rc = pm8921_apply_19p2mhz_kickstart(chip);
4769 if (rc)
4770 pr_err("Failed to apply kickstart rc=%d\n", rc);
4771 }
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004772
4773 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
4774 VREF_BATT_THERM_FORCE_ON);
4775 if (rc)
4776 pr_err("Failed to Force Vref therm on rc=%d\n", rc);
4777 return 0;
4778}
4779
David Keitelf2226022011-12-13 15:55:50 -08004780static int pm8921_charger_resume(struct device *dev)
4781{
David Keitelf2226022011-12-13 15:55:50 -08004782 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4783
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004784 if (pm8921_chg_is_enabled(chip, LOOP_CHANGE_IRQ)) {
4785 disable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
4786 pm8921_chg_disable_irq(chip, LOOP_CHANGE_IRQ);
4787 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004788
4789 if (chip->btc_override && (is_dc_chg_plugged_in(the_chip) ||
4790 is_usb_chg_plugged_in(the_chip)))
4791 schedule_delayed_work(&chip->btc_override_work, 0);
4792
David Keitelf2226022011-12-13 15:55:50 -08004793 return 0;
4794}
4795
4796static int pm8921_charger_suspend(struct device *dev)
4797{
David Keitelf2226022011-12-13 15:55:50 -08004798 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4799
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004800 if (chip->btc_override)
4801 cancel_delayed_work_sync(&chip->btc_override_work);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004802
4803 if (is_usb_chg_plugged_in(chip)) {
4804 pm8921_chg_enable_irq(chip, LOOP_CHANGE_IRQ);
4805 enable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
4806 }
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004807
David Keitelf2226022011-12-13 15:55:50 -08004808 return 0;
4809}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004810static int __devinit pm8921_charger_probe(struct platform_device *pdev)
4811{
4812 int rc = 0;
4813 struct pm8921_chg_chip *chip;
4814 const struct pm8921_charger_platform_data *pdata
4815 = pdev->dev.platform_data;
4816
4817 if (!pdata) {
4818 pr_err("missing platform data\n");
4819 return -EINVAL;
4820 }
4821
4822 chip = kzalloc(sizeof(struct pm8921_chg_chip),
4823 GFP_KERNEL);
4824 if (!chip) {
4825 pr_err("Cannot allocate pm_chg_chip\n");
4826 return -ENOMEM;
4827 }
4828
4829 chip->dev = &pdev->dev;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004830 chip->ttrkl_time = pdata->ttrkl_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004831 chip->update_time = pdata->update_time;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004832 chip->max_voltage_mv = pdata->max_voltage;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004833 chip->alarm_low_mv = pdata->alarm_low_mv;
4834 chip->alarm_high_mv = pdata->alarm_high_mv;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004835 chip->min_voltage_mv = pdata->min_voltage;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004836 chip->safe_current_ma = pdata->safe_current_ma;
David Keitel0789fc62012-06-07 17:43:27 -07004837 chip->uvd_voltage_mv = pdata->uvd_thresh_voltage;
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004838 chip->resume_voltage_delta = pdata->resume_voltage_delta;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004839 chip->resume_charge_percent = pdata->resume_charge_percent;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004840 chip->term_current = pdata->term_current;
4841 chip->vbat_channel = pdata->charger_cdata.vbat_channel;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004842 chip->batt_temp_channel = pdata->charger_cdata.batt_temp_channel;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07004843 chip->batt_id_channel = pdata->charger_cdata.batt_id_channel;
4844 chip->batt_id_min = pdata->batt_id_min;
4845 chip->batt_id_max = pdata->batt_id_max;
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08004846 if (pdata->cool_temp != INT_MIN)
4847 chip->cool_temp_dc = pdata->cool_temp * 10;
4848 else
4849 chip->cool_temp_dc = INT_MIN;
4850
4851 if (pdata->warm_temp != INT_MIN)
4852 chip->warm_temp_dc = pdata->warm_temp * 10;
4853 else
4854 chip->warm_temp_dc = INT_MIN;
4855
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004856 chip->temp_check_period = pdata->temp_check_period;
4857 chip->max_bat_chg_current = pdata->max_bat_chg_current;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004858 /* Assign to corresponding module parameter */
4859 usb_max_current = pdata->usb_max_current;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004860 chip->cool_bat_chg_current = pdata->cool_bat_chg_current;
4861 chip->warm_bat_chg_current = pdata->warm_bat_chg_current;
4862 chip->cool_bat_voltage = pdata->cool_bat_voltage;
4863 chip->warm_bat_voltage = pdata->warm_bat_voltage;
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07004864 chip->trkl_voltage = pdata->trkl_voltage;
4865 chip->weak_voltage = pdata->weak_voltage;
4866 chip->trkl_current = pdata->trkl_current;
4867 chip->weak_current = pdata->weak_current;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07004868 chip->vin_min = pdata->vin_min;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07004869 chip->thermal_mitigation = pdata->thermal_mitigation;
4870 chip->thermal_levels = pdata->thermal_levels;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004871
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07004872 chip->cold_thr = pdata->cold_thr;
4873 chip->hot_thr = pdata->hot_thr;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08004874 chip->rconn_mohm = pdata->rconn_mohm;
Jay Chokshid674a512012-03-15 14:06:04 -07004875 chip->led_src_config = pdata->led_src_config;
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08004876 chip->has_dc_supply = pdata->has_dc_supply;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004877 chip->battery_less_hardware = pdata->battery_less_hardware;
4878 chip->btc_override = pdata->btc_override;
4879 if (chip->btc_override) {
4880 chip->btc_delay_ms = pdata->btc_delay_ms;
4881 chip->btc_override_cold_decidegc
4882 = pdata->btc_override_cold_degc * 10;
4883 chip->btc_override_hot_decidegc
4884 = pdata->btc_override_hot_degc * 10;
4885 chip->btc_panic_if_cant_stop_chg
4886 = pdata->btc_panic_if_cant_stop_chg;
4887 }
4888
4889 if (chip->battery_less_hardware)
4890 charging_disabled = 1;
4891
4892 chip->ibatmax_max_adj_ma = find_ibat_max_adj_ma(
4893 chip->max_bat_chg_current);
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07004894
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004895 rc = pm8921_chg_hw_init(chip);
4896 if (rc) {
4897 pr_err("couldn't init hardware rc=%d\n", rc);
4898 goto free_chip;
4899 }
4900
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004901 if (chip->btc_override)
4902 pm8921_chg_btc_override_init(chip);
4903
4904 chip->stop_chg_upon_expiry = pdata->stop_chg_upon_expiry;
4905
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08004906 chip->usb_psy.name = "usb";
4907 chip->usb_psy.type = POWER_SUPPLY_TYPE_USB;
4908 chip->usb_psy.supplied_to = pm_power_supplied_to;
4909 chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
4910 chip->usb_psy.properties = pm_power_props_usb;
4911 chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props_usb);
4912 chip->usb_psy.get_property = pm_power_get_property_usb;
4913 chip->usb_psy.set_property = pm_power_set_property_usb;
4914 chip->usb_psy.property_is_writeable = usb_property_is_writeable;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004915
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08004916 chip->dc_psy.name = "pm8921-dc";
4917 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
4918 chip->dc_psy.supplied_to = pm_power_supplied_to;
4919 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
4920 chip->dc_psy.properties = pm_power_props_mains;
4921 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
4922 chip->dc_psy.get_property = pm_power_get_property_mains;
David Keitel6ed71a52012-01-30 12:42:18 -08004923
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08004924 chip->batt_psy.name = "battery";
4925 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
4926 chip->batt_psy.properties = msm_batt_power_props;
4927 chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props);
4928 chip->batt_psy.get_property = pm_batt_power_get_property;
4929 chip->batt_psy.external_power_changed = pm_batt_external_power_changed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004930 rc = power_supply_register(chip->dev, &chip->usb_psy);
4931 if (rc < 0) {
4932 pr_err("power_supply_register usb failed rc = %d\n", rc);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004933 goto free_chip;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004934 }
4935
David Keitel6ed71a52012-01-30 12:42:18 -08004936 rc = power_supply_register(chip->dev, &chip->dc_psy);
4937 if (rc < 0) {
4938 pr_err("power_supply_register usb failed rc = %d\n", rc);
4939 goto unregister_usb;
4940 }
4941
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004942 rc = power_supply_register(chip->dev, &chip->batt_psy);
4943 if (rc < 0) {
4944 pr_err("power_supply_register batt failed rc = %d\n", rc);
David Keitel6ed71a52012-01-30 12:42:18 -08004945 goto unregister_dc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004946 }
4947
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004948 platform_set_drvdata(pdev, chip);
4949 the_chip = chip;
4950
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004951 /* set initial state of the USB charger type to UNKNOWN */
4952 power_supply_set_supply_type(&chip->usb_psy, POWER_SUPPLY_TYPE_UNKNOWN);
4953
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004954 wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
Amir Samuelovd31ef502011-10-26 14:41:36 +02004955 INIT_DELAYED_WORK(&chip->eoc_work, eoc_worker);
David Keitelacf57c82012-03-07 18:48:50 -08004956 INIT_DELAYED_WORK(&chip->vin_collapse_check_work,
4957 vin_collapse_check_worker);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004958 INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004959
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004960 INIT_WORK(&chip->bms_notify.work, bms_notify);
4961 INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
4962
4963 INIT_DELAYED_WORK(&chip->update_heartbeat_work, update_heartbeat);
4964 INIT_DELAYED_WORK(&chip->btc_override_work, btc_override_worker);
4965
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004966 rc = request_irqs(chip, pdev);
4967 if (rc) {
4968 pr_err("couldn't register interrupts rc=%d\n", rc);
4969 goto unregister_batt;
4970 }
4971
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07004972 enable_irq_wake(chip->pmic_chg_irq[USBIN_VALID_IRQ]);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004973 enable_irq_wake(chip->pmic_chg_irq[DCIN_VALID_IRQ]);
David Keitel64dd3f52011-11-10 14:19:38 -08004974 enable_irq_wake(chip->pmic_chg_irq[VBATDET_LOW_IRQ]);
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08004975 enable_irq_wake(chip->pmic_chg_irq[FASTCHG_IRQ]);
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07004976
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004977 create_debugfs_entries(chip);
4978
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004979 /* determine what state the charger is in */
4980 determine_initial_state(chip);
4981
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004982 if (chip->update_time)
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07004983 schedule_delayed_work(&chip->update_heartbeat_work,
4984 round_jiffies_relative(msecs_to_jiffies
4985 (chip->update_time)));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004986 return 0;
4987
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004988unregister_batt:
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004989 wake_lock_destroy(&chip->eoc_wake_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004990 power_supply_unregister(&chip->batt_psy);
David Keitel6ed71a52012-01-30 12:42:18 -08004991unregister_dc:
4992 power_supply_unregister(&chip->dc_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004993unregister_usb:
4994 power_supply_unregister(&chip->usb_psy);
4995free_chip:
4996 kfree(chip);
4997 return rc;
4998}
4999
5000static int __devexit pm8921_charger_remove(struct platform_device *pdev)
5001{
5002 struct pm8921_chg_chip *chip = platform_get_drvdata(pdev);
5003
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07005004 regulator_put(chip->vreg_xoadc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005005 free_irqs(chip);
5006 platform_set_drvdata(pdev, NULL);
5007 the_chip = NULL;
5008 kfree(chip);
5009 return 0;
5010}
David Keitelf2226022011-12-13 15:55:50 -08005011static const struct dev_pm_ops pm8921_pm_ops = {
5012 .suspend = pm8921_charger_suspend,
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08005013 .suspend_noirq = pm8921_charger_suspend_noirq,
5014 .resume_noirq = pm8921_charger_resume_noirq,
David Keitelf2226022011-12-13 15:55:50 -08005015 .resume = pm8921_charger_resume,
5016};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005017static struct platform_driver pm8921_charger_driver = {
David Keitelf2226022011-12-13 15:55:50 -08005018 .probe = pm8921_charger_probe,
5019 .remove = __devexit_p(pm8921_charger_remove),
5020 .driver = {
5021 .name = PM8921_CHARGER_DEV_NAME,
5022 .owner = THIS_MODULE,
5023 .pm = &pm8921_pm_ops,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005024 },
5025};
5026
5027static int __init pm8921_charger_init(void)
5028{
5029 return platform_driver_register(&pm8921_charger_driver);
5030}
5031
5032static void __exit pm8921_charger_exit(void)
5033{
5034 platform_driver_unregister(&pm8921_charger_driver);
5035}
5036
5037late_initcall(pm8921_charger_init);
5038module_exit(pm8921_charger_exit);
5039
5040MODULE_LICENSE("GPL v2");
5041MODULE_DESCRIPTION("PMIC8921 charger/battery driver");
5042MODULE_VERSION("1.0");
5043MODULE_ALIAS("platform:" PM8921_CHARGER_DEV_NAME);