blob: 1ad7f21322fe4aa309f9bd7519264d37f24992d4 [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
David Keitel27aae422013-03-08 18:23:41 -080086#define PM8921_USB_TRIM_SEL 0x339
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070087
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -070088/* check EOC every 10 seconds */
89#define EOC_CHECK_PERIOD_MS 10000
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -080090/* check for USB unplug every 200 msecs */
91#define UNPLUG_CHECK_WAIT_PERIOD_MS 200
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -070092#define UNPLUG_CHECK_RAMP_MS 25
93#define USB_TRIM_ENTRIES 16
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -070094
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070095enum chg_fsm_state {
96 FSM_STATE_OFF_0 = 0,
97 FSM_STATE_BATFETDET_START_12 = 12,
98 FSM_STATE_BATFETDET_END_16 = 16,
99 FSM_STATE_ON_CHG_HIGHI_1 = 1,
100 FSM_STATE_ATC_2A = 2,
101 FSM_STATE_ATC_2B = 18,
102 FSM_STATE_ON_BAT_3 = 3,
103 FSM_STATE_ATC_FAIL_4 = 4 ,
104 FSM_STATE_DELAY_5 = 5,
105 FSM_STATE_ON_CHG_AND_BAT_6 = 6,
106 FSM_STATE_FAST_CHG_7 = 7,
107 FSM_STATE_TRKL_CHG_8 = 8,
108 FSM_STATE_CHG_FAIL_9 = 9,
109 FSM_STATE_EOC_10 = 10,
110 FSM_STATE_ON_CHG_VREGOK_11 = 11,
111 FSM_STATE_ATC_PAUSE_13 = 13,
112 FSM_STATE_FAST_CHG_PAUSE_14 = 14,
113 FSM_STATE_TRKL_CHG_PAUSE_15 = 15,
114 FSM_STATE_START_BOOT = 20,
115 FSM_STATE_FLCB_VREGOK = 21,
116 FSM_STATE_FLCB = 22,
117};
118
Abhijeet Dharmapurikar236aa5a2011-11-03 12:17:19 -0700119struct fsm_state_to_batt_status {
120 enum chg_fsm_state fsm_state;
121 int batt_state;
122};
123
124static struct fsm_state_to_batt_status map[] = {
125 {FSM_STATE_OFF_0, POWER_SUPPLY_STATUS_UNKNOWN},
126 {FSM_STATE_BATFETDET_START_12, POWER_SUPPLY_STATUS_UNKNOWN},
127 {FSM_STATE_BATFETDET_END_16, POWER_SUPPLY_STATUS_UNKNOWN},
128 /*
129 * for CHG_HIGHI_1 report NOT_CHARGING if battery missing,
130 * too hot/cold, charger too hot
131 */
132 {FSM_STATE_ON_CHG_HIGHI_1, POWER_SUPPLY_STATUS_FULL},
133 {FSM_STATE_ATC_2A, POWER_SUPPLY_STATUS_CHARGING},
134 {FSM_STATE_ATC_2B, POWER_SUPPLY_STATUS_CHARGING},
135 {FSM_STATE_ON_BAT_3, POWER_SUPPLY_STATUS_DISCHARGING},
136 {FSM_STATE_ATC_FAIL_4, POWER_SUPPLY_STATUS_DISCHARGING},
137 {FSM_STATE_DELAY_5, POWER_SUPPLY_STATUS_UNKNOWN },
138 {FSM_STATE_ON_CHG_AND_BAT_6, POWER_SUPPLY_STATUS_CHARGING},
139 {FSM_STATE_FAST_CHG_7, POWER_SUPPLY_STATUS_CHARGING},
140 {FSM_STATE_TRKL_CHG_8, POWER_SUPPLY_STATUS_CHARGING},
141 {FSM_STATE_CHG_FAIL_9, POWER_SUPPLY_STATUS_DISCHARGING},
142 {FSM_STATE_EOC_10, POWER_SUPPLY_STATUS_FULL},
143 {FSM_STATE_ON_CHG_VREGOK_11, POWER_SUPPLY_STATUS_NOT_CHARGING},
144 {FSM_STATE_ATC_PAUSE_13, POWER_SUPPLY_STATUS_NOT_CHARGING},
145 {FSM_STATE_FAST_CHG_PAUSE_14, POWER_SUPPLY_STATUS_NOT_CHARGING},
146 {FSM_STATE_TRKL_CHG_PAUSE_15, POWER_SUPPLY_STATUS_NOT_CHARGING},
147 {FSM_STATE_START_BOOT, POWER_SUPPLY_STATUS_NOT_CHARGING},
148 {FSM_STATE_FLCB_VREGOK, POWER_SUPPLY_STATUS_NOT_CHARGING},
149 {FSM_STATE_FLCB, POWER_SUPPLY_STATUS_NOT_CHARGING},
150};
151
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700152enum chg_regulation_loop {
153 VDD_LOOP = BIT(3),
154 BAT_CURRENT_LOOP = BIT(2),
155 INPUT_CURRENT_LOOP = BIT(1),
156 INPUT_VOLTAGE_LOOP = BIT(0),
157 CHG_ALL_LOOPS = VDD_LOOP | BAT_CURRENT_LOOP
158 | INPUT_CURRENT_LOOP | INPUT_VOLTAGE_LOOP,
159};
160
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700161enum pmic_chg_interrupts {
162 USBIN_VALID_IRQ = 0,
163 USBIN_OV_IRQ,
164 BATT_INSERTED_IRQ,
165 VBATDET_LOW_IRQ,
166 USBIN_UV_IRQ,
167 VBAT_OV_IRQ,
168 CHGWDOG_IRQ,
169 VCP_IRQ,
170 ATCDONE_IRQ,
171 ATCFAIL_IRQ,
172 CHGDONE_IRQ,
173 CHGFAIL_IRQ,
174 CHGSTATE_IRQ,
175 LOOP_CHANGE_IRQ,
176 FASTCHG_IRQ,
177 TRKLCHG_IRQ,
178 BATT_REMOVED_IRQ,
179 BATTTEMP_HOT_IRQ,
180 CHGHOT_IRQ,
181 BATTTEMP_COLD_IRQ,
182 CHG_GONE_IRQ,
183 BAT_TEMP_OK_IRQ,
184 COARSE_DET_LOW_IRQ,
185 VDD_LOOP_IRQ,
186 VREG_OV_IRQ,
187 VBATDET_IRQ,
188 BATFET_IRQ,
189 PSI_IRQ,
190 DCIN_VALID_IRQ,
191 DCIN_OV_IRQ,
192 DCIN_UV_IRQ,
193 PM_CHG_MAX_INTS,
194};
195
196struct bms_notify {
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -0700197 int is_battery_full;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700198 int is_charging;
199 struct work_struct work;
200};
201
202/**
203 * struct pm8921_chg_chip -device information
204 * @dev: device pointer to access the parent
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700205 * @usb_present: present status of usb
206 * @dc_present: present status of dc
207 * @usb_charger_current: usb current to charge the battery with used when
208 * the usb path is enabled or charging is resumed
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209 * @update_time: how frequently the userland needs to be updated
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800210 * @max_voltage_mv: the max volts the batt should be charged up to
211 * @min_voltage_mv: the min battery voltage before turning the FETon
David Keitel0789fc62012-06-07 17:43:27 -0700212 * @uvd_voltage_mv: (PM8917 only) the falling UVD threshold voltage
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700213 * @alarm_low_mv: the battery alarm voltage low
214 * @alarm_high_mv: the battery alarm voltage high
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800215 * @cool_temp_dc: the cool temp threshold in deciCelcius
216 * @warm_temp_dc: the warm temp threshold in deciCelcius
Anirudh Ghayale747b7e2013-04-04 12:18:18 +0530217 * @hysteresis_temp_dc: the hysteresis between temp thresholds in
218 * deciCelcius
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -0700219 * @resume_voltage_delta: the voltage delta from vdd max at which the
220 * battery should resume charging
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221 * @term_current: The charging based term current
222 *
223 */
224struct pm8921_chg_chip {
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700225 struct device *dev;
226 unsigned int usb_present;
227 unsigned int dc_present;
228 unsigned int usb_charger_current;
229 unsigned int max_bat_chg_current;
230 unsigned int pmic_chg_irq[PM_CHG_MAX_INTS];
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700231 unsigned int ttrkl_time;
232 unsigned int update_time;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800233 unsigned int max_voltage_mv;
234 unsigned int min_voltage_mv;
David Keitel0789fc62012-06-07 17:43:27 -0700235 unsigned int uvd_voltage_mv;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700236 unsigned int safe_current_ma;
237 unsigned int alarm_low_mv;
238 unsigned int alarm_high_mv;
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -0800239 int cool_temp_dc;
240 int warm_temp_dc;
Anirudh Ghayale747b7e2013-04-04 12:18:18 +0530241 int hysteresis_temp_dc;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700242 unsigned int temp_check_period;
243 unsigned int cool_bat_chg_current;
244 unsigned int warm_bat_chg_current;
245 unsigned int cool_bat_voltage;
246 unsigned int warm_bat_voltage;
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -0700247 unsigned int is_bat_cool;
248 unsigned int is_bat_warm;
249 unsigned int resume_voltage_delta;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700250 int resume_charge_percent;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700251 unsigned int term_current;
252 unsigned int vbat_channel;
253 unsigned int batt_temp_channel;
254 unsigned int batt_id_channel;
255 struct power_supply usb_psy;
David Keitel6ed71a52012-01-30 12:42:18 -0800256 struct power_supply dc_psy;
David Keitel88e1b572012-01-11 11:57:14 -0800257 struct power_supply *ext_psy;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700258 struct power_supply batt_psy;
259 struct dentry *dent;
260 struct bms_notify bms_notify;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700261 int *usb_trim_table;
Amir Samuelovd31ef502011-10-26 14:41:36 +0200262 bool ext_charging;
263 bool ext_charge_done;
David Keitel38bdd4f2012-04-19 15:39:13 -0700264 bool iusb_fine_res;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700265 DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700266 struct work_struct battery_id_valid_work;
267 int64_t batt_id_min;
268 int64_t batt_id_max;
269 int trkl_voltage;
270 int weak_voltage;
271 int trkl_current;
272 int weak_current;
273 int vin_min;
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -0800274 unsigned int *thermal_mitigation;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700275 int thermal_levels;
276 struct delayed_work update_heartbeat_work;
277 struct delayed_work eoc_work;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -0800278 struct delayed_work unplug_check_work;
David Keitelacf57c82012-03-07 18:48:50 -0800279 struct delayed_work vin_collapse_check_work;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700280 struct delayed_work btc_override_work;
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -0700281 struct wake_lock eoc_wake_lock;
282 enum pm8921_chg_cold_thr cold_thr;
283 enum pm8921_chg_hot_thr hot_thr;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -0800284 int rconn_mohm;
Jay Chokshid674a512012-03-15 14:06:04 -0700285 enum pm8921_chg_led_src_config led_src_config;
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -0700286 bool host_mode;
David Keitelff4f9ce2012-08-24 15:11:23 -0700287 bool has_dc_supply;
David Keitel6ccbf132012-05-30 14:21:24 -0700288 u8 active_path;
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -0700289 int recent_reported_soc;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700290 int battery_less_hardware;
291 int ibatmax_max_adj_ma;
292 int btc_override;
293 int btc_override_cold_decidegc;
294 int btc_override_hot_decidegc;
295 int btc_delay_ms;
296 bool btc_panic_if_cant_stop_chg;
297 int stop_chg_upon_expiry;
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -0800298 bool disable_aicl;
Anirudh Ghayal8ecf5ad2013-02-20 09:48:42 +0530299 int usb_type;
Anirudh Ghayal0da182f2013-02-22 11:17:19 +0530300 bool disable_chg_rmvl_wrkarnd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700301};
302
David Keitelacf57c82012-03-07 18:48:50 -0800303/* user space parameter to limit usb current */
304static unsigned int usb_max_current;
305/*
306 * usb_target_ma is used for wall charger
307 * adaptive input current limiting only. Use
308 * pm_iusbmax_get() to get current maximum usb current setting.
309 */
310static int usb_target_ma;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311static int charging_disabled;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -0700312static int thermal_mitigation;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700313
314static struct pm8921_chg_chip *the_chip;
Anirudh Ghayale747b7e2013-04-04 12:18:18 +0530315static void check_temp_thresholds(struct pm8921_chg_chip *chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700316
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700317#define LPM_ENABLE_BIT BIT(2)
318static int pm8921_chg_set_lpm(struct pm8921_chg_chip *chip, int enable)
319{
320 int rc;
321 u8 reg;
322
323 rc = pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &reg);
324 if (rc) {
325 pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n",
326 CHG_CNTRL, rc);
327 return rc;
328 }
329 reg &= ~LPM_ENABLE_BIT;
330 reg |= (enable ? LPM_ENABLE_BIT : 0);
331
332 rc = pm8xxx_writeb(chip->dev->parent, CHG_CNTRL, reg);
333 if (rc) {
334 pr_err("pm_chg_write failed: addr=%03X, rc=%d\n",
335 CHG_CNTRL, rc);
336 return rc;
337 }
338
339 return rc;
340}
341
342static int pm_chg_write(struct pm8921_chg_chip *chip, u16 addr, u8 reg)
343{
344 int rc;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700345
Abhijeet Dharmapurikar68f44372013-03-01 18:25:05 -0800346 rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
347 if (rc)
348 pr_err("failed: addr=%03X, rc=%d\n", addr, rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700349
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700350 return rc;
351}
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -0700352
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700353static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr,
354 u8 mask, u8 val)
355{
356 int rc;
357 u8 reg;
358
359 rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
360 if (rc) {
361 pr_err("pm8xxx_readb failed: addr=%03X, rc=%d\n", addr, rc);
362 return rc;
363 }
364 reg &= ~mask;
365 reg |= val & mask;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700366 rc = pm_chg_write(chip, addr, reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700368 pr_err("pm_chg_write failed: addr=%03X, rc=%d\n", addr, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369 return rc;
370 }
371 return 0;
372}
373
David Keitelcf867232012-01-27 18:40:12 -0800374static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
375{
376 return pm8xxx_read_irq_stat(chip->dev->parent,
377 chip->pmic_chg_irq[irq_id]);
378}
379
380/* Treat OverVoltage/UnderVoltage as source missing */
381static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
382{
383 return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
384}
385
386/* Treat OverVoltage/UnderVoltage as source missing */
387static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
388{
389 return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
390}
391
Abhijeet Dharmapurikarb2680132012-05-15 16:32:51 -0700392static int is_batfet_closed(struct pm8921_chg_chip *chip)
393{
394 return pm_chg_get_rt_status(chip, BATFET_IRQ);
395}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700396#define CAPTURE_FSM_STATE_CMD 0xC2
397#define READ_BANK_7 0x70
398#define READ_BANK_4 0x40
399static int pm_chg_get_fsm_state(struct pm8921_chg_chip *chip)
400{
401 u8 temp;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800402 int err = 0, ret = 0;
403
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404 temp = CAPTURE_FSM_STATE_CMD;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800405 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700406 if (err) {
407 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800408 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409 }
410
411 temp = READ_BANK_7;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800412 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700413 if (err) {
414 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800415 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700416 }
417
418 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
419 if (err) {
420 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800421 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422 }
423 /* get the lower 4 bits */
424 ret = temp & 0xF;
425
426 temp = READ_BANK_4;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800427 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 if (err) {
429 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800430 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700431 }
432
433 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &temp);
434 if (err) {
435 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800436 goto err_out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437 }
438 /* get the upper 1 bit */
439 ret |= (temp & 0x1) << 4;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800440
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800441err_out:
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800442 if (err)
443 return err;
444
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700445 return ret;
446}
447
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700448#define READ_BANK_6 0x60
449static int pm_chg_get_regulation_loop(struct pm8921_chg_chip *chip)
450{
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800451 u8 temp, data;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800452 int err = 0;
453
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700454 temp = READ_BANK_6;
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800455 err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700456 if (err) {
457 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800458 goto err_out;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700459 }
460
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800461 err = pm8xxx_readb(chip->dev->parent, CHG_TEST, &data);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700462 if (err) {
463 pr_err("pm8xxx_readb fail: addr=%03X, rc=%d\n", CHG_TEST, err);
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800464 goto err_out;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700465 }
466
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800467err_out:
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800468 if (err)
469 return err;
470
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700471 /* return the lower 4 bits */
Abhijeet Dharmapurikar7a679a32013-01-07 18:17:46 -0800472 return data & CHG_ALL_LOOPS;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700473}
474
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475#define CHG_USB_SUSPEND_BIT BIT(2)
476static int pm_chg_usb_suspend_enable(struct pm8921_chg_chip *chip, int enable)
477{
478 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_USB_SUSPEND_BIT,
479 enable ? CHG_USB_SUSPEND_BIT : 0);
480}
481
482#define CHG_EN_BIT BIT(7)
483static int pm_chg_auto_enable(struct pm8921_chg_chip *chip, int enable)
484{
485 return pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_EN_BIT,
486 enable ? CHG_EN_BIT : 0);
487}
488
David Keitel753ec8d2011-11-02 10:56:37 -0700489#define CHG_FAILED_CLEAR BIT(0)
490#define ATC_FAILED_CLEAR BIT(1)
491static int pm_chg_failed_clear(struct pm8921_chg_chip *chip, int clear)
492{
493 int rc;
494
495 rc = pm_chg_masked_write(chip, CHG_CNTRL_3, ATC_FAILED_CLEAR,
496 clear ? ATC_FAILED_CLEAR : 0);
497 rc |= pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_FAILED_CLEAR,
498 clear ? CHG_FAILED_CLEAR : 0);
499 return rc;
500}
501
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700502#define CHG_CHARGE_DIS_BIT BIT(1)
503static int pm_chg_charge_dis(struct pm8921_chg_chip *chip, int disable)
504{
505 return pm_chg_masked_write(chip, CHG_CNTRL, CHG_CHARGE_DIS_BIT,
506 disable ? CHG_CHARGE_DIS_BIT : 0);
507}
508
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -0800509static int pm_is_chg_charge_dis(struct pm8921_chg_chip *chip)
510{
511 u8 temp;
512
513 pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
514 return temp & CHG_CHARGE_DIS_BIT;
515}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516#define PM8921_CHG_V_MIN_MV 3240
517#define PM8921_CHG_V_STEP_MV 20
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800518#define PM8921_CHG_V_STEP_10MV_OFFSET_BIT BIT(7)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700519#define PM8921_CHG_VDDMAX_MAX 4500
520#define PM8921_CHG_VDDMAX_MIN 3400
521#define PM8921_CHG_V_MASK 0x7F
David Keitelcf867232012-01-27 18:40:12 -0800522static int __pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523{
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800524 int remainder;
David Keitelcf867232012-01-27 18:40:12 -0800525 u8 temp = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800527 if (voltage < PM8921_CHG_VDDMAX_MIN
528 || voltage > PM8921_CHG_VDDMAX_MAX) {
529 pr_err("bad mV=%d asked to set\n", voltage);
530 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700531 }
David Keitelcf867232012-01-27 18:40:12 -0800532
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800533 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
534
535 remainder = voltage % 20;
536 if (remainder >= 10) {
537 temp |= PM8921_CHG_V_STEP_10MV_OFFSET_BIT;
538 }
539
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700540 pr_debug("voltage=%d setting %02x\n", voltage, temp);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700541 return pm_chg_write(chip, CHG_VDD_MAX, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700542}
543
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700544static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
545{
546 u8 temp;
547 int rc;
548
549 rc = pm8xxx_readb(chip->dev->parent, CHG_VDD_MAX, &temp);
550 if (rc) {
551 pr_err("rc = %d while reading vdd max\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700552 *voltage = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700553 return rc;
554 }
Abhijeet Dharmapurikar08e7e0a2012-02-22 19:34:20 -0800555 *voltage = (int)(temp & PM8921_CHG_V_MASK) * PM8921_CHG_V_STEP_MV
556 + PM8921_CHG_V_MIN_MV;
557 if (temp & PM8921_CHG_V_STEP_10MV_OFFSET_BIT)
558 *voltage = *voltage + 10;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700559 return 0;
560}
561
David Keitelcf867232012-01-27 18:40:12 -0800562static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
563{
564 int current_mv, ret, steps, i;
565 bool increase;
566
567 ret = 0;
568
569 if (voltage < PM8921_CHG_VDDMAX_MIN
570 || voltage > PM8921_CHG_VDDMAX_MAX) {
571 pr_err("bad mV=%d asked to set\n", voltage);
572 return -EINVAL;
573 }
574
575 ret = pm_chg_vddmax_get(chip, &current_mv);
576 if (ret) {
577 pr_err("Failed to read vddmax rc=%d\n", ret);
578 return -EINVAL;
579 }
580 if (current_mv == voltage)
581 return 0;
582
583 /* Only change in increments when USB is present */
584 if (is_usb_chg_plugged_in(chip)) {
585 if (current_mv < voltage) {
586 steps = (voltage - current_mv) / PM8921_CHG_V_STEP_MV;
587 increase = true;
588 } else {
589 steps = (current_mv - voltage) / PM8921_CHG_V_STEP_MV;
590 increase = false;
591 }
592 for (i = 0; i < steps; i++) {
593 if (increase)
594 current_mv += PM8921_CHG_V_STEP_MV;
595 else
596 current_mv -= PM8921_CHG_V_STEP_MV;
597 ret |= __pm_chg_vddmax_set(chip, current_mv);
598 }
599 }
600 ret |= __pm_chg_vddmax_set(chip, voltage);
601 return ret;
602}
603
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700604#define PM8921_CHG_VDDSAFE_MIN 3400
605#define PM8921_CHG_VDDSAFE_MAX 4500
606static int pm_chg_vddsafe_set(struct pm8921_chg_chip *chip, int voltage)
607{
608 u8 temp;
609
610 if (voltage < PM8921_CHG_VDDSAFE_MIN
611 || voltage > PM8921_CHG_VDDSAFE_MAX) {
612 pr_err("bad mV=%d asked to set\n", voltage);
613 return -EINVAL;
614 }
615 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
616 pr_debug("voltage=%d setting %02x\n", voltage, temp);
617 return pm_chg_masked_write(chip, CHG_VDD_SAFE, PM8921_CHG_V_MASK, temp);
618}
619
620#define PM8921_CHG_VBATDET_MIN 3240
621#define PM8921_CHG_VBATDET_MAX 5780
622static int pm_chg_vbatdet_set(struct pm8921_chg_chip *chip, int voltage)
623{
624 u8 temp;
625
626 if (voltage < PM8921_CHG_VBATDET_MIN
627 || voltage > PM8921_CHG_VBATDET_MAX) {
628 pr_err("bad mV=%d asked to set\n", voltage);
629 return -EINVAL;
630 }
631 temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
632 pr_debug("voltage=%d setting %02x\n", voltage, temp);
633 return pm_chg_masked_write(chip, CHG_VBAT_DET, PM8921_CHG_V_MASK, temp);
634}
635
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -0700636#define PM8921_CHG_VINMIN_MIN_MV 3800
637#define PM8921_CHG_VINMIN_STEP_MV 100
638#define PM8921_CHG_VINMIN_USABLE_MAX 6500
639#define PM8921_CHG_VINMIN_USABLE_MIN 4300
640#define PM8921_CHG_VINMIN_MASK 0x1F
641static int pm_chg_vinmin_set(struct pm8921_chg_chip *chip, int voltage)
642{
643 u8 temp;
644
645 if (voltage < PM8921_CHG_VINMIN_USABLE_MIN
646 || voltage > PM8921_CHG_VINMIN_USABLE_MAX) {
647 pr_err("bad mV=%d asked to set\n", voltage);
648 return -EINVAL;
649 }
650 temp = (voltage - PM8921_CHG_VINMIN_MIN_MV) / PM8921_CHG_VINMIN_STEP_MV;
651 pr_debug("voltage=%d setting %02x\n", voltage, temp);
652 return pm_chg_masked_write(chip, CHG_VIN_MIN, PM8921_CHG_VINMIN_MASK,
653 temp);
654}
655
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -0800656static int pm_chg_vinmin_get(struct pm8921_chg_chip *chip)
657{
658 u8 temp;
659 int rc, voltage_mv;
660
661 rc = pm8xxx_readb(chip->dev->parent, CHG_VIN_MIN, &temp);
662 temp &= PM8921_CHG_VINMIN_MASK;
663
664 voltage_mv = PM8921_CHG_VINMIN_MIN_MV +
665 (int)temp * PM8921_CHG_VINMIN_STEP_MV;
666
667 return voltage_mv;
668}
669
David Keitel0789fc62012-06-07 17:43:27 -0700670#define PM8917_USB_UVD_MIN_MV 3850
671#define PM8917_USB_UVD_MAX_MV 4350
672#define PM8917_USB_UVD_STEP_MV 100
673#define PM8917_USB_UVD_MASK 0x7
674static int pm_chg_uvd_threshold_set(struct pm8921_chg_chip *chip, int thresh_mv)
675{
676 u8 temp;
677
678 if (thresh_mv < PM8917_USB_UVD_MIN_MV
679 || thresh_mv > PM8917_USB_UVD_MAX_MV) {
680 pr_err("bad mV=%d asked to set\n", thresh_mv);
681 return -EINVAL;
682 }
683 temp = (thresh_mv - PM8917_USB_UVD_MIN_MV) / PM8917_USB_UVD_STEP_MV;
684 return pm_chg_masked_write(chip, OVP_USB_UVD,
685 PM8917_USB_UVD_MASK, temp);
686}
687
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688#define PM8921_CHG_IBATMAX_MIN 325
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700689#define PM8921_CHG_IBATMAX_MAX 3025
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690#define PM8921_CHG_I_MIN_MA 225
691#define PM8921_CHG_I_STEP_MA 50
692#define PM8921_CHG_I_MASK 0x3F
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700693static int pm_chg_ibatmax_get(struct pm8921_chg_chip *chip, int *ibat_ma)
694{
695 u8 temp;
696 int rc;
697
698 rc = pm8xxx_readb(chip->dev->parent, CHG_IBAT_MAX, &temp);
699 if (rc) {
700 pr_err("rc = %d while reading ibat max\n", rc);
701 *ibat_ma = 0;
702 return rc;
703 }
704 *ibat_ma = (int)(temp & PM8921_CHG_I_MASK) * PM8921_CHG_I_STEP_MA
705 + PM8921_CHG_I_MIN_MA;
706 return 0;
707}
708
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700709static int pm_chg_ibatmax_set(struct pm8921_chg_chip *chip, int chg_current)
710{
711 u8 temp;
712
713 if (chg_current < PM8921_CHG_IBATMAX_MIN
714 || chg_current > PM8921_CHG_IBATMAX_MAX) {
715 pr_err("bad mA=%d asked to set\n", chg_current);
716 return -EINVAL;
717 }
718 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
719 return pm_chg_masked_write(chip, CHG_IBAT_MAX, PM8921_CHG_I_MASK, temp);
720}
721
722#define PM8921_CHG_IBATSAFE_MIN 225
723#define PM8921_CHG_IBATSAFE_MAX 3375
724static int pm_chg_ibatsafe_set(struct pm8921_chg_chip *chip, int chg_current)
725{
726 u8 temp;
727
728 if (chg_current < PM8921_CHG_IBATSAFE_MIN
729 || chg_current > PM8921_CHG_IBATSAFE_MAX) {
730 pr_err("bad mA=%d asked to set\n", chg_current);
731 return -EINVAL;
732 }
733 temp = (chg_current - PM8921_CHG_I_MIN_MA) / PM8921_CHG_I_STEP_MA;
734 return pm_chg_masked_write(chip, CHG_IBAT_SAFE,
735 PM8921_CHG_I_MASK, temp);
736}
737
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700738#define PM8921_CHG_ITERM_MIN_MA 50
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700739#define PM8921_CHG_ITERM_MAX_MA 200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700740#define PM8921_CHG_ITERM_STEP_MA 10
741#define PM8921_CHG_ITERM_MASK 0xF
742static int pm_chg_iterm_set(struct pm8921_chg_chip *chip, int chg_current)
743{
744 u8 temp;
745
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700746 if (chg_current < PM8921_CHG_ITERM_MIN_MA
747 || chg_current > PM8921_CHG_ITERM_MAX_MA) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700748 pr_err("bad mA=%d asked to set\n", chg_current);
749 return -EINVAL;
750 }
751
752 temp = (chg_current - PM8921_CHG_ITERM_MIN_MA)
753 / PM8921_CHG_ITERM_STEP_MA;
Abhijeet Dharmapurikar71816fd2011-08-12 17:14:10 -0700754 return pm_chg_masked_write(chip, CHG_ITERM, PM8921_CHG_ITERM_MASK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700755 temp);
756}
757
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700758static int pm_chg_iterm_get(struct pm8921_chg_chip *chip, int *chg_current)
759{
760 u8 temp;
761 int rc;
762
763 rc = pm8xxx_readb(chip->dev->parent, CHG_ITERM, &temp);
764 if (rc) {
765 pr_err("err=%d reading CHG_ITEM\n", rc);
Stephen Boyd81982232011-09-26 12:08:38 -0700766 *chg_current = 0;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -0700767 return rc;
768 }
769 temp &= PM8921_CHG_ITERM_MASK;
770 *chg_current = (int)temp * PM8921_CHG_ITERM_STEP_MA
771 + PM8921_CHG_ITERM_MIN_MA;
772 return 0;
773}
774
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800775struct usb_ma_limit_entry {
David Keitel38bdd4f2012-04-19 15:39:13 -0700776 int usb_ma;
777 u8 value;
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800778};
779
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700780/* USB Trim tables */
David Keitel27aae422013-03-08 18:23:41 -0800781static int usb_trim_pm8921_table_1[USB_TRIM_ENTRIES] = {
782 0x0,
783 0x0,
784 -0x5,
785 0x0,
786 -0x7,
787 0x0,
788 -0x9,
789 -0xA,
790 0x0,
791 0x0,
792 -0xE,
793 0x0,
794 -0xF,
795 0x0,
796 -0x10,
797 0x0
798};
799
800static int usb_trim_pm8921_table_2[USB_TRIM_ENTRIES] = {
801 0x0,
802 0x0,
803 -0x2,
804 0x0,
805 -0x4,
806 0x0,
807 -0x4,
808 -0x5,
809 0x0,
810 0x0,
811 -0x6,
812 0x0,
813 -0x6,
814 0x0,
815 -0x6,
816 0x0
817};
818
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700819static int usb_trim_8038_table[USB_TRIM_ENTRIES] = {
820 0x0,
821 0x0,
822 -0x9,
823 0x0,
824 -0xD,
825 0x0,
826 -0x10,
827 -0x11,
828 0x0,
829 0x0,
830 -0x25,
831 0x0,
832 -0x28,
833 0x0,
834 -0x32,
835 0x0
836};
837
838static int usb_trim_8917_table[USB_TRIM_ENTRIES] = {
839 0x0,
840 0x0,
841 0xA,
842 0xC,
843 0x10,
844 0x10,
845 0x13,
846 0x14,
847 0x13,
848 0x3,
849 0x1A,
850 0x1D,
851 0x1D,
852 0x21,
853 0x24,
854 0x26
855};
856
857/* Maximum USB setting table */
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800858static struct usb_ma_limit_entry usb_ma_table[] = {
David Keitel38bdd4f2012-04-19 15:39:13 -0700859 {100, 0x0},
860 {200, 0x1},
861 {500, 0x2},
862 {600, 0x3},
863 {700, 0x4},
864 {800, 0x5},
865 {850, 0x6},
866 {900, 0x8},
867 {950, 0x7},
868 {1000, 0x9},
869 {1100, 0xA},
870 {1200, 0xB},
871 {1300, 0xC},
872 {1400, 0xD},
873 {1500, 0xE},
874 {1600, 0xF},
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -0800875};
876
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700877#define REG_SBI_CONFIG 0x04F
878#define PAGE3_ENABLE_MASK 0x6
879#define USB_OVP_TRIM_MASK 0x3F
880#define USB_OVP_TRIM_PM8917_MASK 0x7F
881#define USB_OVP_TRIM_MIN 0x00
882#define REG_USB_OVP_TRIM_ORIG_LSB 0x10A
883#define REG_USB_OVP_TRIM_ORIG_MSB 0x09C
884#define REG_USB_OVP_TRIM_PM8917 0x2B5
885#define REG_USB_OVP_TRIM_PM8917_BIT BIT(0)
David Keitel27aae422013-03-08 18:23:41 -0800886#define USB_TRIM_MAX_DATA_PM8917 0x3F
887#define USB_TRIM_POLARITY_PM8917_BIT BIT(6)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700888static int pm_chg_usb_trim(struct pm8921_chg_chip *chip, int index)
889{
890 u8 temp, sbi_config, msb, lsb, mask;
891 s8 trim;
892 int rc = 0;
893 static u8 usb_trim_reg_orig = 0xFF;
894
895 /* No trim data for PM8921 */
896 if (!chip->usb_trim_table)
897 return 0;
898
899 if (usb_trim_reg_orig == 0xFF) {
900 rc = pm8xxx_readb(chip->dev->parent,
901 REG_USB_OVP_TRIM_ORIG_MSB, &msb);
902 if (rc) {
903 pr_err("error = %d reading sbi config reg\n", rc);
904 return rc;
905 }
906
907 rc = pm8xxx_readb(chip->dev->parent,
908 REG_USB_OVP_TRIM_ORIG_LSB, &lsb);
909 if (rc) {
910 pr_err("error = %d reading sbi config reg\n", rc);
911 return rc;
912 }
913
914 msb = msb >> 5;
915 lsb = lsb >> 5;
916 usb_trim_reg_orig = msb << 3 | lsb;
917
918 if (pm8xxx_get_version(chip->dev->parent)
919 == PM8XXX_VERSION_8917) {
920 rc = pm8xxx_readb(chip->dev->parent,
921 REG_USB_OVP_TRIM_PM8917, &msb);
922 if (rc) {
923 pr_err("error = %d reading config reg\n", rc);
924 return rc;
925 }
926
927 msb = msb & REG_USB_OVP_TRIM_PM8917_BIT;
928 usb_trim_reg_orig |= msb << 6;
929 }
930 }
931
932 /* use the original trim value */
933 trim = usb_trim_reg_orig;
934
935 trim += chip->usb_trim_table[index];
936 if (trim < 0)
937 trim = 0;
938
939 pr_debug("trim_orig %d write 0x%x index=%d value 0x%x to USB_OVP_TRIM\n",
940 usb_trim_reg_orig, trim, index, chip->usb_trim_table[index]);
941
942 rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, &sbi_config);
943 if (rc) {
944 pr_err("error = %d reading sbi config reg\n", rc);
945 return rc;
946 }
947
948 temp = sbi_config | PAGE3_ENABLE_MASK;
949 rc = pm_chg_write(chip, REG_SBI_CONFIG, temp);
950 if (rc) {
951 pr_err("error = %d writing sbi config reg\n", rc);
952 return rc;
953 }
954
955 mask = USB_OVP_TRIM_MASK;
956
957 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
958 mask = USB_OVP_TRIM_PM8917_MASK;
959
960 rc = pm_chg_masked_write(chip, USB_OVP_TRIM, mask, trim);
961 if (rc) {
962 pr_err("error = %d writing USB_OVP_TRIM\n", rc);
963 return rc;
964 }
965
966 rc = pm_chg_write(chip, REG_SBI_CONFIG, sbi_config);
967 if (rc) {
968 pr_err("error = %d writing sbi config reg\n", rc);
969 return rc;
970 }
971 return rc;
972}
973
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700974#define PM8921_CHG_IUSB_MASK 0x1C
David Keitel38bdd4f2012-04-19 15:39:13 -0700975#define PM8921_CHG_IUSB_SHIFT 2
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700976#define PM8921_CHG_IUSB_MAX 7
977#define PM8921_CHG_IUSB_MIN 0
David Keitel38bdd4f2012-04-19 15:39:13 -0700978#define PM8917_IUSB_FINE_RES BIT(0)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700979static int pm_chg_iusbmax_set(struct pm8921_chg_chip *chip, int index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700980{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700981 u8 temp, fineres, reg_val;
David Keitel38bdd4f2012-04-19 15:39:13 -0700982 int rc;
983
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -0700984 reg_val = usb_ma_table[index].value >> 1;
985 fineres = PM8917_IUSB_FINE_RES & usb_ma_table[index].value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700986
Abhijeet Dharmapurikar485a0532011-08-12 17:18:10 -0700987 if (reg_val < PM8921_CHG_IUSB_MIN || reg_val > PM8921_CHG_IUSB_MAX) {
988 pr_err("bad mA=%d asked to set\n", reg_val);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989 return -EINVAL;
990 }
David Keitel38bdd4f2012-04-19 15:39:13 -0700991 temp = reg_val << PM8921_CHG_IUSB_SHIFT;
992
993 /* IUSB_FINE_RES */
994 if (chip->iusb_fine_res) {
995 /* Clear IUSB_FINE_RES bit to avoid overshoot */
996 rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
997 PM8917_IUSB_FINE_RES, 0);
998
999 rc |= pm_chg_masked_write(chip, PBL_ACCESS2,
1000 PM8921_CHG_IUSB_MASK, temp);
1001
1002 if (rc) {
1003 pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
1004 return rc;
1005 }
1006
1007 if (fineres) {
1008 rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
1009 PM8917_IUSB_FINE_RES, fineres);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001010 if (rc) {
David Keitel38bdd4f2012-04-19 15:39:13 -07001011 pr_err("Failed to write ISUB_FINE_RES rc=%d\n",
1012 rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001013 return rc;
1014 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001015 }
1016 } else {
1017 rc = pm_chg_masked_write(chip, PBL_ACCESS2,
1018 PM8921_CHG_IUSB_MASK, temp);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001019 if (rc) {
David Keitel38bdd4f2012-04-19 15:39:13 -07001020 pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001021 return rc;
1022 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001023 }
1024
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001025 rc = pm_chg_usb_trim(chip, index);
1026 if (rc)
1027 pr_err("unable to set usb trim rc = %d\n", rc);
1028
David Keitel38bdd4f2012-04-19 15:39:13 -07001029 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001030}
1031
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001032static int pm_chg_iusbmax_get(struct pm8921_chg_chip *chip, int *mA)
1033{
David Keitel38bdd4f2012-04-19 15:39:13 -07001034 u8 temp, fineres;
1035 int rc, i;
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001036
David Keitel38bdd4f2012-04-19 15:39:13 -07001037 fineres = 0;
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001038 *mA = 0;
1039 rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS2, &temp);
1040 if (rc) {
1041 pr_err("err=%d reading PBL_ACCESS2\n", rc);
1042 return rc;
1043 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001044
1045 if (chip->iusb_fine_res) {
1046 rc = pm8xxx_readb(chip->dev->parent, IUSB_FINE_RES, &fineres);
1047 if (rc) {
1048 pr_err("err=%d reading IUSB_FINE_RES\n", rc);
1049 return rc;
1050 }
1051 }
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001052 temp &= PM8921_CHG_IUSB_MASK;
David Keitel38bdd4f2012-04-19 15:39:13 -07001053 temp = temp >> PM8921_CHG_IUSB_SHIFT;
1054
1055 temp = (temp << 1) | (fineres & PM8917_IUSB_FINE_RES);
1056 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
1057 if (usb_ma_table[i].value == temp)
1058 break;
1059 }
1060
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001061 if (i < 0) {
1062 pr_err("can't find %d in usb_ma_table. Use min.\n", temp);
1063 i = 0;
1064 }
1065
David Keitel38bdd4f2012-04-19 15:39:13 -07001066 *mA = usb_ma_table[i].usb_ma;
1067
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08001068 return rc;
1069}
1070
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001071#define PM8921_CHG_WD_MASK 0x1F
1072static int pm_chg_disable_wd(struct pm8921_chg_chip *chip)
1073{
1074 /* writing 0 to the wd timer disables it */
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001075 return pm_chg_masked_write(chip, CHG_TWDOG, PM8921_CHG_WD_MASK, 0);
1076}
1077
Abhijeet Dharmapurikarc26cd902011-10-26 18:07:45 -07001078#define PM8921_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001079#define PM8921_CHG_TCHG_MIN 4
1080#define PM8921_CHG_TCHG_MAX 512
1081#define PM8921_CHG_TCHG_STEP 4
1082static int pm_chg_tchg_max_set(struct pm8921_chg_chip *chip, int minutes)
1083{
1084 u8 temp;
1085
1086 if (minutes < PM8921_CHG_TCHG_MIN || minutes > PM8921_CHG_TCHG_MAX) {
1087 pr_err("bad max minutes =%d asked to set\n", minutes);
1088 return -EINVAL;
1089 }
1090
1091 temp = (minutes - 1)/PM8921_CHG_TCHG_STEP;
1092 return pm_chg_masked_write(chip, CHG_TCHG_MAX, PM8921_CHG_TCHG_MASK,
1093 temp);
1094}
1095
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001096#define PM8921_CHG_TTRKL_MASK 0x3F
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001097#define PM8921_CHG_TTRKL_MIN 1
1098#define PM8921_CHG_TTRKL_MAX 64
1099static int pm_chg_ttrkl_max_set(struct pm8921_chg_chip *chip, int minutes)
1100{
1101 u8 temp;
1102
1103 if (minutes < PM8921_CHG_TTRKL_MIN || minutes > PM8921_CHG_TTRKL_MAX) {
1104 pr_err("bad max minutes =%d asked to set\n", minutes);
1105 return -EINVAL;
1106 }
1107
1108 temp = minutes - 1;
1109 return pm_chg_masked_write(chip, CHG_TTRKL_MAX, PM8921_CHG_TTRKL_MASK,
1110 temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001111}
1112
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07001113#define PM8921_CHG_VTRKL_MIN_MV 2050
1114#define PM8921_CHG_VTRKL_MAX_MV 2800
1115#define PM8921_CHG_VTRKL_STEP_MV 50
1116#define PM8921_CHG_VTRKL_SHIFT 4
1117#define PM8921_CHG_VTRKL_MASK 0xF0
1118static int pm_chg_vtrkl_low_set(struct pm8921_chg_chip *chip, int millivolts)
1119{
1120 u8 temp;
1121
1122 if (millivolts < PM8921_CHG_VTRKL_MIN_MV
1123 || millivolts > PM8921_CHG_VTRKL_MAX_MV) {
1124 pr_err("bad voltage = %dmV asked to set\n", millivolts);
1125 return -EINVAL;
1126 }
1127
1128 temp = (millivolts - PM8921_CHG_VTRKL_MIN_MV)/PM8921_CHG_VTRKL_STEP_MV;
1129 temp = temp << PM8921_CHG_VTRKL_SHIFT;
1130 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VTRKL_MASK,
1131 temp);
1132}
1133
1134#define PM8921_CHG_VWEAK_MIN_MV 2100
1135#define PM8921_CHG_VWEAK_MAX_MV 3600
1136#define PM8921_CHG_VWEAK_STEP_MV 100
1137#define PM8921_CHG_VWEAK_MASK 0x0F
1138static int pm_chg_vweak_set(struct pm8921_chg_chip *chip, int millivolts)
1139{
1140 u8 temp;
1141
1142 if (millivolts < PM8921_CHG_VWEAK_MIN_MV
1143 || millivolts > PM8921_CHG_VWEAK_MAX_MV) {
1144 pr_err("bad voltage = %dmV asked to set\n", millivolts);
1145 return -EINVAL;
1146 }
1147
1148 temp = (millivolts - PM8921_CHG_VWEAK_MIN_MV)/PM8921_CHG_VWEAK_STEP_MV;
1149 return pm_chg_masked_write(chip, CHG_VTRICKLE, PM8921_CHG_VWEAK_MASK,
1150 temp);
1151}
1152
1153#define PM8921_CHG_ITRKL_MIN_MA 50
1154#define PM8921_CHG_ITRKL_MAX_MA 200
1155#define PM8921_CHG_ITRKL_MASK 0x0F
1156#define PM8921_CHG_ITRKL_STEP_MA 10
1157static int pm_chg_itrkl_set(struct pm8921_chg_chip *chip, int milliamps)
1158{
1159 u8 temp;
1160
1161 if (milliamps < PM8921_CHG_ITRKL_MIN_MA
1162 || milliamps > PM8921_CHG_ITRKL_MAX_MA) {
1163 pr_err("bad current = %dmA asked to set\n", milliamps);
1164 return -EINVAL;
1165 }
1166
1167 temp = (milliamps - PM8921_CHG_ITRKL_MIN_MA)/PM8921_CHG_ITRKL_STEP_MA;
1168
1169 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_ITRKL_MASK,
1170 temp);
1171}
1172
1173#define PM8921_CHG_IWEAK_MIN_MA 325
1174#define PM8921_CHG_IWEAK_MAX_MA 525
1175#define PM8921_CHG_IWEAK_SHIFT 7
1176#define PM8921_CHG_IWEAK_MASK 0x80
1177static int pm_chg_iweak_set(struct pm8921_chg_chip *chip, int milliamps)
1178{
1179 u8 temp;
1180
1181 if (milliamps < PM8921_CHG_IWEAK_MIN_MA
1182 || milliamps > PM8921_CHG_IWEAK_MAX_MA) {
1183 pr_err("bad current = %dmA asked to set\n", milliamps);
1184 return -EINVAL;
1185 }
1186
1187 if (milliamps < PM8921_CHG_IWEAK_MAX_MA)
1188 temp = 0;
1189 else
1190 temp = 1;
1191
1192 temp = temp << PM8921_CHG_IWEAK_SHIFT;
1193 return pm_chg_masked_write(chip, CHG_ITRICKLE, PM8921_CHG_IWEAK_MASK,
1194 temp);
1195}
1196
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07001197#define PM8921_CHG_BATT_TEMP_THR_COLD BIT(1)
1198#define PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT 1
1199static int pm_chg_batt_cold_temp_config(struct pm8921_chg_chip *chip,
1200 enum pm8921_chg_cold_thr cold_thr)
1201{
1202 u8 temp;
1203
1204 temp = cold_thr << PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT;
1205 temp = temp & PM8921_CHG_BATT_TEMP_THR_COLD;
1206 return pm_chg_masked_write(chip, CHG_CNTRL_2,
1207 PM8921_CHG_BATT_TEMP_THR_COLD,
1208 temp);
1209}
1210
1211#define PM8921_CHG_BATT_TEMP_THR_HOT BIT(0)
1212#define PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT 0
1213static int pm_chg_batt_hot_temp_config(struct pm8921_chg_chip *chip,
1214 enum pm8921_chg_hot_thr hot_thr)
1215{
1216 u8 temp;
1217
1218 temp = hot_thr << PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT;
1219 temp = temp & PM8921_CHG_BATT_TEMP_THR_HOT;
1220 return pm_chg_masked_write(chip, CHG_CNTRL_2,
1221 PM8921_CHG_BATT_TEMP_THR_HOT,
1222 temp);
1223}
1224
Jay Chokshid674a512012-03-15 14:06:04 -07001225#define PM8921_CHG_LED_SRC_CONFIG_SHIFT 4
1226#define PM8921_CHG_LED_SRC_CONFIG_MASK 0x30
1227static int pm_chg_led_src_config(struct pm8921_chg_chip *chip,
1228 enum pm8921_chg_led_src_config led_src_config)
1229{
1230 u8 temp;
1231
1232 if (led_src_config < LED_SRC_GND ||
1233 led_src_config > LED_SRC_BYPASS)
1234 return -EINVAL;
1235
1236 if (led_src_config == LED_SRC_BYPASS)
1237 return 0;
1238
1239 temp = led_src_config << PM8921_CHG_LED_SRC_CONFIG_SHIFT;
1240
1241 return pm_chg_masked_write(chip, CHG_CNTRL_3,
1242 PM8921_CHG_LED_SRC_CONFIG_MASK, temp);
1243}
1244
David Keitel8c5201a2012-02-24 16:08:54 -08001245
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001246static int64_t read_battery_id(struct pm8921_chg_chip *chip)
1247{
1248 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001249 struct pm8xxx_adc_chan_result result;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001250
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001251 rc = pm8xxx_adc_read(chip->batt_id_channel, &result);
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001252 if (rc) {
1253 pr_err("error reading batt id channel = %d, rc = %d\n",
1254 chip->vbat_channel, rc);
1255 return rc;
1256 }
1257 pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
1258 result.measurement);
1259 return result.physical;
1260}
1261
1262static int is_battery_valid(struct pm8921_chg_chip *chip)
1263{
1264 int64_t rc;
1265
1266 if (chip->batt_id_min == 0 && chip->batt_id_max == 0)
1267 return 1;
1268
1269 rc = read_battery_id(chip);
1270 if (rc < 0) {
1271 pr_err("error reading batt id channel = %d, rc = %lld\n",
1272 chip->vbat_channel, rc);
1273 /* assume battery id is valid when adc error happens */
1274 return 1;
1275 }
1276
1277 if (rc < chip->batt_id_min || rc > chip->batt_id_max) {
1278 pr_err("batt_id phy =%lld is not valid\n", rc);
1279 return 0;
1280 }
1281 return 1;
1282}
1283
1284static void check_battery_valid(struct pm8921_chg_chip *chip)
1285{
1286 if (is_battery_valid(chip) == 0) {
1287 pr_err("batt_id not valid, disbling charging\n");
1288 pm_chg_auto_enable(chip, 0);
1289 } else {
1290 pm_chg_auto_enable(chip, !charging_disabled);
1291 }
1292}
1293
1294static void battery_id_valid(struct work_struct *work)
1295{
1296 struct pm8921_chg_chip *chip = container_of(work,
1297 struct pm8921_chg_chip, battery_id_valid_work);
1298
1299 check_battery_valid(chip);
1300}
1301
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001302static void pm8921_chg_enable_irq(struct pm8921_chg_chip *chip, int interrupt)
1303{
1304 if (!__test_and_set_bit(interrupt, chip->enabled_irqs)) {
1305 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
1306 enable_irq(chip->pmic_chg_irq[interrupt]);
1307 }
1308}
1309
1310static void pm8921_chg_disable_irq(struct pm8921_chg_chip *chip, int interrupt)
1311{
1312 if (__test_and_clear_bit(interrupt, chip->enabled_irqs)) {
1313 dev_dbg(chip->dev, "%d\n", chip->pmic_chg_irq[interrupt]);
1314 disable_irq_nosync(chip->pmic_chg_irq[interrupt]);
1315 }
1316}
1317
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08001318static int pm8921_chg_is_enabled(struct pm8921_chg_chip *chip, int interrupt)
1319{
1320 return test_bit(interrupt, chip->enabled_irqs);
1321}
1322
Amir Samuelovd31ef502011-10-26 14:41:36 +02001323static bool is_ext_charging(struct pm8921_chg_chip *chip)
1324{
David Keitel88e1b572012-01-11 11:57:14 -08001325 union power_supply_propval ret = {0,};
Amir Samuelovd31ef502011-10-26 14:41:36 +02001326
David Keitel88e1b572012-01-11 11:57:14 -08001327 if (!chip->ext_psy)
1328 return false;
1329 if (chip->ext_psy->get_property(chip->ext_psy,
1330 POWER_SUPPLY_PROP_CHARGE_TYPE, &ret))
1331 return false;
1332 if (ret.intval > POWER_SUPPLY_CHARGE_TYPE_NONE)
1333 return ret.intval;
Amir Samuelovd31ef502011-10-26 14:41:36 +02001334
1335 return false;
1336}
1337
1338static bool is_ext_trickle_charging(struct pm8921_chg_chip *chip)
1339{
David Keitel88e1b572012-01-11 11:57:14 -08001340 union power_supply_propval ret = {0,};
Amir Samuelovd31ef502011-10-26 14:41:36 +02001341
David Keitel88e1b572012-01-11 11:57:14 -08001342 if (!chip->ext_psy)
1343 return false;
1344 if (chip->ext_psy->get_property(chip->ext_psy,
1345 POWER_SUPPLY_PROP_CHARGE_TYPE, &ret))
1346 return false;
1347 if (ret.intval == POWER_SUPPLY_CHARGE_TYPE_TRICKLE)
Amir Samuelovd31ef502011-10-26 14:41:36 +02001348 return true;
1349
1350 return false;
1351}
1352
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001353static int is_battery_charging(int fsm_state)
1354{
Amir Samuelovd31ef502011-10-26 14:41:36 +02001355 if (is_ext_charging(the_chip))
1356 return 1;
1357
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001358 switch (fsm_state) {
1359 case FSM_STATE_ATC_2A:
1360 case FSM_STATE_ATC_2B:
1361 case FSM_STATE_ON_CHG_AND_BAT_6:
1362 case FSM_STATE_FAST_CHG_7:
1363 case FSM_STATE_TRKL_CHG_8:
1364 return 1;
1365 }
1366 return 0;
1367}
1368
1369static void bms_notify(struct work_struct *work)
1370{
1371 struct bms_notify *n = container_of(work, struct bms_notify, work);
1372
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07001373 if (n->is_charging) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001374 pm8921_bms_charging_began();
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07001375 } else {
1376 pm8921_bms_charging_end(n->is_battery_full);
1377 n->is_battery_full = 0;
1378 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001379}
1380
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07001381static void bms_notify_check(struct pm8921_chg_chip *chip)
1382{
1383 int fsm_state, new_is_charging;
1384
1385 fsm_state = pm_chg_get_fsm_state(chip);
1386 new_is_charging = is_battery_charging(fsm_state);
1387
1388 if (chip->bms_notify.is_charging ^ new_is_charging) {
1389 chip->bms_notify.is_charging = new_is_charging;
1390 schedule_work(&(chip->bms_notify.work));
1391 }
1392}
1393
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001394static enum power_supply_property pm_power_props_usb[] = {
1395 POWER_SUPPLY_PROP_PRESENT,
1396 POWER_SUPPLY_PROP_ONLINE,
1397 POWER_SUPPLY_PROP_CURRENT_MAX,
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001398 POWER_SUPPLY_PROP_SCOPE,
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001399 POWER_SUPPLY_PROP_HEALTH,
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001400};
1401
1402static enum power_supply_property pm_power_props_mains[] = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403 POWER_SUPPLY_PROP_PRESENT,
Willie Ruan9ad6d832011-08-19 11:58:42 -07001404 POWER_SUPPLY_PROP_ONLINE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001405};
1406
1407static char *pm_power_supplied_to[] = {
1408 "battery",
1409};
1410
David Keitel6ed71a52012-01-30 12:42:18 -08001411#define USB_WALL_THRESHOLD_MA 500
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001412static int pm_power_get_property_mains(struct power_supply *psy,
1413 enum power_supply_property psp,
1414 union power_supply_propval *val)
1415{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001416 int type;
1417
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001418 /* Check if called before init */
1419 if (!the_chip)
1420 return -EINVAL;
1421
1422 switch (psp) {
1423 case POWER_SUPPLY_PROP_PRESENT:
1424 case POWER_SUPPLY_PROP_ONLINE:
1425 val->intval = 0;
David Keitelff4f9ce2012-08-24 15:11:23 -07001426
1427 if (the_chip->has_dc_supply) {
1428 val->intval = 1;
1429 return 0;
1430 }
1431
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001432 if (the_chip->dc_present) {
1433 val->intval = 1;
1434 return 0;
1435 }
1436
Anirudh Ghayal8ecf5ad2013-02-20 09:48:42 +05301437 type = the_chip->usb_type;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001438 if (type == POWER_SUPPLY_TYPE_USB_DCP ||
1439 type == POWER_SUPPLY_TYPE_USB_ACA ||
1440 type == POWER_SUPPLY_TYPE_USB_CDP)
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001441 val->intval = is_usb_chg_plugged_in(the_chip);
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001442
1443 break;
1444 default:
1445 return -EINVAL;
1446 }
1447 return 0;
1448}
1449
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001450static int disable_aicl(int disable)
1451{
1452 if (disable != POWER_SUPPLY_HEALTH_UNKNOWN
1453 && disable != POWER_SUPPLY_HEALTH_GOOD) {
1454 pr_err("called with invalid param :%d\n", disable);
1455 return -EINVAL;
1456 }
1457
1458 if (!the_chip) {
1459 pr_err("%s called before init\n", __func__);
1460 return -EINVAL;
1461 }
1462
1463 pr_debug("Disable AICL = %d\n", disable);
1464 the_chip->disable_aicl = disable;
1465 return 0;
1466}
1467
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001468static int switch_usb_to_charge_mode(struct pm8921_chg_chip *chip)
1469{
1470 int rc;
1471
1472 if (!chip->host_mode)
1473 return 0;
1474
1475 /* enable usbin valid comparator and remove force usb ovp fet off */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001476 rc = pm_chg_write(chip, USB_OVP_TEST, 0xB2);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001477 if (rc < 0) {
1478 pr_err("Failed to write 0xB2 to USB_OVP_TEST rc = %d\n", rc);
1479 return rc;
1480 }
1481
1482 chip->host_mode = 0;
1483
1484 return 0;
1485}
1486
1487static int switch_usb_to_host_mode(struct pm8921_chg_chip *chip)
1488{
1489 int rc;
1490
1491 if (chip->host_mode)
1492 return 0;
1493
1494 /* disable usbin valid comparator and force usb ovp fet off */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001495 rc = pm_chg_write(chip, USB_OVP_TEST, 0xB3);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001496 if (rc < 0) {
1497 pr_err("Failed to write 0xB3 to USB_OVP_TEST rc = %d\n", rc);
1498 return rc;
1499 }
1500
1501 chip->host_mode = 1;
1502
1503 return 0;
1504}
1505
1506static int pm_power_set_property_usb(struct power_supply *psy,
1507 enum power_supply_property psp,
1508 const union power_supply_propval *val)
1509{
1510 /* Check if called before init */
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001511 if (!the_chip)
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001512 return -EINVAL;
1513
1514 switch (psp) {
1515 case POWER_SUPPLY_PROP_SCOPE:
1516 if (val->intval == POWER_SUPPLY_SCOPE_SYSTEM)
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001517 return switch_usb_to_host_mode(the_chip);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001518 if (val->intval == POWER_SUPPLY_SCOPE_DEVICE)
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001519 return switch_usb_to_charge_mode(the_chip);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001520 else
1521 return -EINVAL;
1522 break;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001523 case POWER_SUPPLY_PROP_TYPE:
1524 return pm8921_set_usb_power_supply_type(val->intval);
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001525 case POWER_SUPPLY_PROP_HEALTH:
1526 /* UNKNOWN(0) means enable aicl, GOOD(1) means disable aicl */
1527 return disable_aicl(val->intval);
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001528 default:
1529 return -EINVAL;
1530 }
1531 return 0;
1532}
1533
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001534static int usb_property_is_writeable(struct power_supply *psy,
1535 enum power_supply_property psp)
1536{
1537 switch (psp) {
1538 case POWER_SUPPLY_PROP_HEALTH:
1539 return 1;
1540 default:
1541 break;
1542 }
1543
1544 return 0;
1545}
1546
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001547static int pm_power_get_property_usb(struct power_supply *psy,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001548 enum power_supply_property psp,
1549 union power_supply_propval *val)
1550{
David Keitel6ed71a52012-01-30 12:42:18 -08001551 int current_max;
1552
1553 /* Check if called before init */
1554 if (!the_chip)
1555 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001556
1557 switch (psp) {
David Keitel6ed71a52012-01-30 12:42:18 -08001558 case POWER_SUPPLY_PROP_CURRENT_MAX:
Abhijeet Dharmapurikar9da392d2012-02-22 18:59:57 -08001559 if (pm_is_chg_charge_dis(the_chip)) {
1560 val->intval = 0;
1561 } else {
1562 pm_chg_iusbmax_get(the_chip, &current_max);
1563 val->intval = current_max;
1564 }
David Keitel6ed71a52012-01-30 12:42:18 -08001565 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001566 case POWER_SUPPLY_PROP_PRESENT:
Willie Ruan9ad6d832011-08-19 11:58:42 -07001567 case POWER_SUPPLY_PROP_ONLINE:
David Keitel63f71662012-02-08 20:30:00 -08001568 val->intval = 0;
David Keitel63f71662012-02-08 20:30:00 -08001569
Anirudh Ghayal8ecf5ad2013-02-20 09:48:42 +05301570 if (the_chip->usb_type == POWER_SUPPLY_TYPE_USB)
David Keitel86034022012-04-18 12:33:58 -07001571 val->intval = is_usb_chg_plugged_in(the_chip);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001572
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001573 break;
Abhijeet Dharmapurikar5e96aaa2012-06-26 11:21:03 -07001574
1575 case POWER_SUPPLY_PROP_SCOPE:
1576 if (the_chip->host_mode)
1577 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
1578 else
1579 val->intval = POWER_SUPPLY_SCOPE_DEVICE;
1580 break;
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08001581 case POWER_SUPPLY_PROP_HEALTH:
1582 /* UNKNOWN(0) means enable aicl, GOOD(1) means disable aicl */
1583 val->intval = the_chip->disable_aicl;
1584 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001585 default:
1586 return -EINVAL;
1587 }
1588 return 0;
1589}
1590
1591static enum power_supply_property msm_batt_power_props[] = {
1592 POWER_SUPPLY_PROP_STATUS,
1593 POWER_SUPPLY_PROP_CHARGE_TYPE,
1594 POWER_SUPPLY_PROP_HEALTH,
1595 POWER_SUPPLY_PROP_PRESENT,
1596 POWER_SUPPLY_PROP_TECHNOLOGY,
1597 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
1598 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
1599 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1600 POWER_SUPPLY_PROP_CAPACITY,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001601 POWER_SUPPLY_PROP_CURRENT_MAX,
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001602 POWER_SUPPLY_PROP_CURRENT_NOW,
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001603 POWER_SUPPLY_PROP_TEMP,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001604 POWER_SUPPLY_PROP_CHARGE_FULL,
1605 POWER_SUPPLY_PROP_CHARGE_NOW,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001606};
1607
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001608static int get_prop_battery_uvolts(struct pm8921_chg_chip *chip)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001609{
1610 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001611 struct pm8xxx_adc_chan_result result;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001612
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001613 rc = pm8xxx_adc_read(chip->vbat_channel, &result);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001614 if (rc) {
1615 pr_err("error reading adc channel = %d, rc = %d\n",
1616 chip->vbat_channel, rc);
1617 return rc;
1618 }
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07001619 pr_debug("mvolts phy = %lld meas = 0x%llx\n", result.physical,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001620 result.measurement);
1621 return (int)result.physical;
1622}
1623
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301624static int voltage_based_capacity(struct pm8921_chg_chip *chip)
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001625{
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301626 int current_voltage_uv = get_prop_battery_uvolts(chip);
1627 int current_voltage_mv = current_voltage_uv / 1000;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001628 unsigned int low_voltage = chip->min_voltage_mv;
1629 unsigned int high_voltage = chip->max_voltage_mv;
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001630
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301631 if (current_voltage_uv < 0) {
1632 pr_err("Error reading current voltage\n");
1633 return -EIO;
1634 }
1635
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001636 if (current_voltage_mv <= low_voltage)
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001637 return 0;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001638 else if (current_voltage_mv >= high_voltage)
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001639 return 100;
1640 else
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001641 return (current_voltage_mv - low_voltage) * 100
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001642 / (high_voltage - low_voltage);
1643}
1644
David Keitel4f9397b2012-04-16 11:46:16 -07001645static int get_prop_batt_present(struct pm8921_chg_chip *chip)
1646{
1647 return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
1648}
1649
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001650static int get_prop_batt_status(struct pm8921_chg_chip *chip)
1651{
1652 int batt_state = POWER_SUPPLY_STATUS_DISCHARGING;
1653 int fsm_state = pm_chg_get_fsm_state(chip);
1654 int i;
1655
1656 if (chip->ext_psy) {
1657 if (chip->ext_charge_done)
1658 return POWER_SUPPLY_STATUS_FULL;
1659 if (chip->ext_charging)
1660 return POWER_SUPPLY_STATUS_CHARGING;
1661 }
1662
1663 for (i = 0; i < ARRAY_SIZE(map); i++)
1664 if (map[i].fsm_state == fsm_state)
1665 batt_state = map[i].batt_state;
1666
1667 if (fsm_state == FSM_STATE_ON_CHG_HIGHI_1) {
1668 if (!pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ)
1669 || !pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ)
1670 || pm_chg_get_rt_status(chip, CHGHOT_IRQ)
1671 || pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ))
1672
1673 batt_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
1674 }
1675 return batt_state;
1676}
1677
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001678static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
1679{
David Keitel4f9397b2012-04-16 11:46:16 -07001680 int percent_soc;
1681
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001682 if (chip->battery_less_hardware)
1683 return 100;
1684
David Keitel4f9397b2012-04-16 11:46:16 -07001685 if (!get_prop_batt_present(chip))
1686 percent_soc = voltage_based_capacity(chip);
1687 else
1688 percent_soc = pm8921_bms_get_percent_charge();
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001689
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001690 if (percent_soc == -ENXIO)
1691 percent_soc = voltage_based_capacity(chip);
1692
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301693 if (percent_soc < 0) {
1694 pr_err("Unable to read battery voltage\n");
1695 goto fail_voltage;
1696 }
1697
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001698 if (percent_soc <= 10)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001699 pr_warn_ratelimited("low battery charge = %d%%\n",
1700 percent_soc);
1701
1702 if (percent_soc <= chip->resume_charge_percent
1703 && get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL) {
1704 pr_debug("soc fell below %d. charging enabled.\n",
1705 chip->resume_charge_percent);
1706 if (chip->is_bat_warm)
1707 pr_warn_ratelimited("battery is warm = %d, do not resume charging at %d%%.\n",
1708 chip->is_bat_warm,
1709 chip->resume_charge_percent);
1710 else if (chip->is_bat_cool)
1711 pr_warn_ratelimited("battery is cool = %d, do not resume charging at %d%%.\n",
1712 chip->is_bat_cool,
1713 chip->resume_charge_percent);
1714 else
1715 pm_chg_vbatdet_set(the_chip, PM8921_CHG_VBATDET_MAX);
1716 }
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001717
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301718fail_voltage:
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -07001719 chip->recent_reported_soc = percent_soc;
Abhijeet Dharmapurikar5a7df4e2011-07-27 13:16:24 -07001720 return percent_soc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001721}
1722
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301723static int get_prop_batt_current_max(struct pm8921_chg_chip *chip, int *curr)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001724{
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301725 *curr = 0;
1726 *curr = pm8921_bms_get_current_max();
1727 if (*curr == -EINVAL)
1728 return -EINVAL;
1729
1730 return 0;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001731}
1732
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301733static int get_prop_batt_current(struct pm8921_chg_chip *chip, int *curr)
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001734{
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301735 int rc;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001736
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301737 *curr = 0;
1738 rc = pm8921_bms_get_battery_current(curr);
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001739 if (rc == -ENXIO) {
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301740 rc = pm8xxx_ccadc_get_battery_current(curr);
Abhijeet Dharmapurikar4ffea2c2011-11-11 18:25:02 -08001741 }
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301742 if (rc)
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001743 pr_err("unable to get batt current rc = %d\n", rc);
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301744
1745 return rc;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001746}
1747
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001748static int get_prop_batt_fcc(struct pm8921_chg_chip *chip)
1749{
1750 int rc;
1751
1752 rc = pm8921_bms_get_fcc();
1753 if (rc < 0)
1754 pr_err("unable to get batt fcc rc = %d\n", rc);
1755 return rc;
1756}
1757
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301758static int get_prop_batt_charge_now(struct pm8921_chg_chip *chip, int *cc_uah)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001759{
1760 int rc;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001761
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301762 *cc_uah = 0;
1763 rc = pm8921_bms_cc_uah(cc_uah);
1764 if (rc)
1765 pr_err("unable to get batt fcc rc = %d\n", rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001766
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001767 return rc;
1768}
1769
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001770static int get_prop_batt_health(struct pm8921_chg_chip *chip)
1771{
1772 int temp;
1773
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001774 temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
1775 if (temp)
1776 return POWER_SUPPLY_HEALTH_OVERHEAT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001777
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001778 temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
1779 if (temp)
1780 return POWER_SUPPLY_HEALTH_COLD;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001781
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08001782 return POWER_SUPPLY_HEALTH_GOOD;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001783}
1784
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785static int get_prop_charge_type(struct pm8921_chg_chip *chip)
1786{
1787 int temp;
1788
Amir Samuelovd31ef502011-10-26 14:41:36 +02001789 if (!get_prop_batt_present(chip))
1790 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1791
1792 if (is_ext_trickle_charging(chip))
1793 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1794
1795 if (is_ext_charging(chip))
1796 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1797
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001798 temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
1799 if (temp)
1800 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1801
1802 temp = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
1803 if (temp)
1804 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1805
1806 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1807}
1808
Abhijeet Dharmapurikar728bc4d2012-01-03 11:08:33 -08001809#define MAX_TOLERABLE_BATT_TEMP_DDC 680
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301810static int get_prop_batt_temp(struct pm8921_chg_chip *chip, int *temp)
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001811{
1812 int rc;
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001813 struct pm8xxx_adc_chan_result result;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001814
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301815 if (chip->battery_less_hardware) {
1816 *temp = 300;
1817 return 0;
1818 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001819
Siddartha Mohanadossaf91d902011-10-20 10:23:34 -07001820 rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001821 if (rc) {
1822 pr_err("error reading adc channel = %d, rc = %d\n",
1823 chip->vbat_channel, rc);
1824 return rc;
1825 }
1826 pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
1827 result.measurement);
Abhijeet Dharmapurikar728bc4d2012-01-03 11:08:33 -08001828 if (result.physical > MAX_TOLERABLE_BATT_TEMP_DDC)
1829 pr_err("BATT_TEMP= %d > 68degC, device will be shutdown\n",
1830 (int) result.physical);
1831
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301832 *temp = (int)result.physical;
1833
1834 return rc;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001835}
1836
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001837static int pm_batt_power_get_property(struct power_supply *psy,
1838 enum power_supply_property psp,
1839 union power_supply_propval *val)
1840{
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301841 int rc = 0;
1842 int value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001843 struct pm8921_chg_chip *chip = container_of(psy, struct pm8921_chg_chip,
1844 batt_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 switch (psp) {
1846 case POWER_SUPPLY_PROP_STATUS:
1847 val->intval = get_prop_batt_status(chip);
1848 break;
1849 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1850 val->intval = get_prop_charge_type(chip);
1851 break;
1852 case POWER_SUPPLY_PROP_HEALTH:
1853 val->intval = get_prop_batt_health(chip);
1854 break;
1855 case POWER_SUPPLY_PROP_PRESENT:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301856 rc = get_prop_batt_present(chip);
1857 if (rc >= 0) {
1858 val->intval = rc;
1859 rc = 0;
1860 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001861 break;
1862 case POWER_SUPPLY_PROP_TECHNOLOGY:
1863 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1864 break;
1865 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001866 val->intval = chip->max_voltage_mv * 1000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001867 break;
1868 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08001869 val->intval = chip->min_voltage_mv * 1000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001870 break;
1871 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301872 rc = get_prop_battery_uvolts(chip);
1873 if (rc >= 0) {
1874 val->intval = rc;
1875 rc = 0;
1876 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001877 break;
1878 case POWER_SUPPLY_PROP_CAPACITY:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301879 rc = get_prop_batt_capacity(chip);
1880 if (rc >= 0) {
1881 val->intval = rc;
1882 rc = 0;
1883 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001884 break;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001885 case POWER_SUPPLY_PROP_CURRENT_NOW:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301886 rc = get_prop_batt_current(chip, &value);
1887 if (!rc)
1888 val->intval = value;
Abhijeet Dharmapurikare0c3e5f2011-07-11 21:17:23 -07001889 break;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001890 case POWER_SUPPLY_PROP_CURRENT_MAX:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301891 rc = get_prop_batt_current_max(chip, &value);
1892 if (!rc)
1893 val->intval = value;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001894 break;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001895 case POWER_SUPPLY_PROP_TEMP:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301896 rc = get_prop_batt_temp(chip, &value);
1897 if (!rc)
1898 val->intval = value;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07001899 break;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001900 case POWER_SUPPLY_PROP_CHARGE_FULL:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301901 rc = get_prop_batt_fcc(chip);
1902 if (rc >= 0) {
1903 val->intval = rc;
1904 rc = 0;
1905 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001906 break;
1907 case POWER_SUPPLY_PROP_CHARGE_NOW:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301908 rc = get_prop_batt_charge_now(chip, &value);
1909 if (!rc) {
1910 val->intval = value;
1911 rc = 0;
1912 }
Abhijeet Dharmapurikar325bdc92011-09-07 20:45:49 -07001913 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001914 default:
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301915 rc = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001916 }
1917
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05301918 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001919}
1920
1921static void (*notify_vbus_state_func_ptr)(int);
1922static int usb_chg_current;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001923
1924int pm8921_charger_register_vbus_sn(void (*callback)(int))
1925{
1926 pr_debug("%p\n", callback);
1927 notify_vbus_state_func_ptr = callback;
1928 return 0;
1929}
1930EXPORT_SYMBOL_GPL(pm8921_charger_register_vbus_sn);
1931
1932/* this is passed to the hsusb via platform_data msm_otg_pdata */
1933void pm8921_charger_unregister_vbus_sn(void (*callback)(int))
1934{
1935 pr_debug("%p\n", callback);
1936 notify_vbus_state_func_ptr = NULL;
1937}
1938EXPORT_SYMBOL_GPL(pm8921_charger_unregister_vbus_sn);
1939
1940static void notify_usb_of_the_plugin_event(int plugin)
1941{
1942 plugin = !!plugin;
1943 if (notify_vbus_state_func_ptr) {
1944 pr_debug("notifying plugin\n");
1945 (*notify_vbus_state_func_ptr) (plugin);
1946 } else {
1947 pr_debug("unable to notify plugin\n");
1948 }
1949}
1950
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001951static void __pm8921_charger_vbus_draw(unsigned int mA)
1952{
1953 int i, rc;
David Keitel38bdd4f2012-04-19 15:39:13 -07001954 if (!the_chip) {
1955 pr_err("called before init\n");
1956 return;
1957 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001958
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001959 if (usb_max_current && mA > usb_max_current) {
1960 pr_debug("restricting usb current to %d instead of %d\n",
1961 usb_max_current, mA);
1962 mA = usb_max_current;
1963 }
1964
1965 if (mA <= 2) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001966 usb_chg_current = 0;
David Keitelacf57c82012-03-07 18:48:50 -08001967 rc = pm_chg_iusbmax_set(the_chip, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001968 if (rc) {
David Keitelacf57c82012-03-07 18:48:50 -08001969 pr_err("unable to set iusb to %d rc = %d\n", 0, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001970 }
1971 rc = pm_chg_usb_suspend_enable(the_chip, 1);
1972 if (rc)
1973 pr_err("fail to set suspend bit rc=%d\n", rc);
1974 } else {
1975 rc = pm_chg_usb_suspend_enable(the_chip, 0);
1976 if (rc)
1977 pr_err("fail to reset suspend bit rc=%d\n", rc);
1978 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
1979 if (usb_ma_table[i].usb_ma <= mA)
1980 break;
1981 }
David Keitel38bdd4f2012-04-19 15:39:13 -07001982
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001983 if (i < 0) {
1984 pr_err("can't find %dmA in usb_ma_table. Use min.\n",
1985 mA);
1986 i = 0;
1987 }
1988
David Keitel38bdd4f2012-04-19 15:39:13 -07001989 /* Check if IUSB_FINE_RES is available */
David Keitel1454bc82012-10-01 11:12:59 -07001990 while ((usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
David Keitel38bdd4f2012-04-19 15:39:13 -07001991 && !the_chip->iusb_fine_res)
1992 i--;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001993 if (i < 0)
1994 i = 0;
David Keitelacf57c82012-03-07 18:48:50 -08001995 rc = pm_chg_iusbmax_set(the_chip, i);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07001996 if (rc)
David Keitelacf57c82012-03-07 18:48:50 -08001997 pr_err("unable to set iusb to %d rc = %d\n", i, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001998 }
1999}
2000
2001/* USB calls these to tell us how much max usb current the system can draw */
2002void pm8921_charger_vbus_draw(unsigned int mA)
2003{
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002004 int set_usb_now_ma;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002005
2006 pr_debug("Enter charge=%d\n", mA);
David Keitelacf57c82012-03-07 18:48:50 -08002007
David Keitel62c6a4b2012-05-17 12:54:59 -07002008 /*
2009 * Reject VBUS requests if USB connection is the only available
2010 * power source. This makes sure that if booting without
2011 * battery the iusb_max value is not decreased avoiding potential
2012 * brown_outs.
2013 *
2014 * This would also apply when the battery has been
2015 * removed from the running system.
2016 */
Abhijeet Dharmapurikar55cf35b2013-02-20 18:40:59 -08002017 if (mA == 0 && the_chip && !get_prop_batt_present(the_chip)
David Keitel62c6a4b2012-05-17 12:54:59 -07002018 && !is_dc_chg_plugged_in(the_chip)) {
David Keitelff4f9ce2012-08-24 15:11:23 -07002019 if (!the_chip->has_dc_supply) {
Abhijeet Dharmapurikar55cf35b2013-02-20 18:40:59 -08002020 pr_err("rejected: no other power source mA = %d\n", mA);
David Keitelff4f9ce2012-08-24 15:11:23 -07002021 return;
2022 }
David Keitel62c6a4b2012-05-17 12:54:59 -07002023 }
2024
David Keitelacf57c82012-03-07 18:48:50 -08002025 if (usb_max_current && mA > usb_max_current) {
2026 pr_warn("restricting usb current to %d instead of %d\n",
2027 usb_max_current, mA);
2028 mA = usb_max_current;
2029 }
Devin Kim2073afb2012-09-05 13:01:51 -07002030 if (usb_target_ma == 0 && mA > USB_WALL_THRESHOLD_MA)
2031 usb_target_ma = mA;
David Keitelacf57c82012-03-07 18:48:50 -08002032
Anirudh Ghayal0ddca632013-01-23 16:43:31 +05302033 if (usb_target_ma)
2034 usb_target_ma = mA;
2035
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002036
2037 if (mA > USB_WALL_THRESHOLD_MA)
2038 set_usb_now_ma = USB_WALL_THRESHOLD_MA;
2039 else
2040 set_usb_now_ma = mA;
2041
2042 if (the_chip && the_chip->disable_aicl)
2043 set_usb_now_ma = mA;
2044
2045 if (the_chip)
2046 __pm8921_charger_vbus_draw(set_usb_now_ma);
2047 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002048 /*
2049 * called before pmic initialized,
2050 * save this value and use it at probe
2051 */
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002052 usb_chg_current = set_usb_now_ma;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002053}
2054EXPORT_SYMBOL_GPL(pm8921_charger_vbus_draw);
2055
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002056int pm8921_is_usb_chg_plugged_in(void)
2057{
2058 if (!the_chip) {
2059 pr_err("called before init\n");
2060 return -EINVAL;
2061 }
2062 return is_usb_chg_plugged_in(the_chip);
2063}
2064EXPORT_SYMBOL(pm8921_is_usb_chg_plugged_in);
2065
2066int pm8921_is_dc_chg_plugged_in(void)
2067{
2068 if (!the_chip) {
2069 pr_err("called before init\n");
2070 return -EINVAL;
2071 }
2072 return is_dc_chg_plugged_in(the_chip);
2073}
2074EXPORT_SYMBOL(pm8921_is_dc_chg_plugged_in);
2075
2076int pm8921_is_battery_present(void)
2077{
2078 if (!the_chip) {
2079 pr_err("called before init\n");
2080 return -EINVAL;
2081 }
2082 return get_prop_batt_present(the_chip);
2083}
2084EXPORT_SYMBOL(pm8921_is_battery_present);
2085
Abhijeet Dharmapurikarb2680132012-05-15 16:32:51 -07002086int pm8921_is_batfet_closed(void)
2087{
2088 if (!the_chip) {
2089 pr_err("called before init\n");
2090 return -EINVAL;
2091 }
2092 return is_batfet_closed(the_chip);
2093}
2094EXPORT_SYMBOL(pm8921_is_batfet_closed);
David Keitel012deef2011-12-02 11:49:33 -08002095/*
2096 * Disabling the charge current limit causes current
2097 * current limits to have no monitoring. An adequate charger
2098 * capable of supplying high current while sustaining VIN_MIN
2099 * is required if the limiting is disabled.
2100 */
2101int pm8921_disable_input_current_limit(bool disable)
2102{
2103 if (!the_chip) {
2104 pr_err("called before init\n");
2105 return -EINVAL;
2106 }
2107 if (disable) {
2108 pr_warn("Disabling input current limit!\n");
2109
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002110 return pm_chg_write(the_chip, CHG_BUCK_CTRL_TEST3, 0xF2);
David Keitel012deef2011-12-02 11:49:33 -08002111 }
2112 return 0;
2113}
2114EXPORT_SYMBOL(pm8921_disable_input_current_limit);
2115
David Keitel0789fc62012-06-07 17:43:27 -07002116int pm8917_set_under_voltage_detection_threshold(int mv)
2117{
2118 if (!the_chip) {
2119 pr_err("called before init\n");
2120 return -EINVAL;
2121 }
2122 return pm_chg_uvd_threshold_set(the_chip, mv);
2123}
2124EXPORT_SYMBOL(pm8917_set_under_voltage_detection_threshold);
2125
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002126int pm8921_set_max_battery_charge_current(int ma)
2127{
2128 if (!the_chip) {
2129 pr_err("called before init\n");
2130 return -EINVAL;
2131 }
2132 return pm_chg_ibatmax_set(the_chip, ma);
2133}
2134EXPORT_SYMBOL(pm8921_set_max_battery_charge_current);
2135
2136int pm8921_disable_source_current(bool disable)
2137{
2138 if (!the_chip) {
2139 pr_err("called before init\n");
2140 return -EINVAL;
2141 }
2142 if (disable)
2143 pr_warn("current drawn from chg=0, battery provides current\n");
David Keitel0fe15c42012-09-04 09:33:28 -07002144
2145 pm_chg_usb_suspend_enable(the_chip, disable);
2146
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002147 return pm_chg_charge_dis(the_chip, disable);
2148}
2149EXPORT_SYMBOL(pm8921_disable_source_current);
2150
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002151int pm8921_regulate_input_voltage(int voltage)
2152{
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002153 int rc;
2154
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002155 if (!the_chip) {
2156 pr_err("called before init\n");
2157 return -EINVAL;
2158 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002159 rc = pm_chg_vinmin_set(the_chip, voltage);
2160
2161 if (rc == 0)
2162 the_chip->vin_min = voltage;
2163
2164 return rc;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07002165}
2166
Abhijeet Dharmapurikar28669302011-12-21 08:31:28 -08002167#define USB_OV_THRESHOLD_MASK 0x60
2168#define USB_OV_THRESHOLD_SHIFT 5
2169int pm8921_usb_ovp_set_threshold(enum pm8921_usb_ov_threshold ov)
2170{
2171 u8 temp;
2172
2173 if (!the_chip) {
2174 pr_err("called before init\n");
2175 return -EINVAL;
2176 }
2177
2178 if (ov > PM_USB_OV_7V) {
2179 pr_err("limiting to over voltage threshold to 7volts\n");
2180 ov = PM_USB_OV_7V;
2181 }
2182
2183 temp = USB_OV_THRESHOLD_MASK & (ov << USB_OV_THRESHOLD_SHIFT);
2184
2185 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
2186 USB_OV_THRESHOLD_MASK, temp);
2187}
2188EXPORT_SYMBOL(pm8921_usb_ovp_set_threshold);
2189
2190#define USB_DEBOUNCE_TIME_MASK 0x06
2191#define USB_DEBOUNCE_TIME_SHIFT 1
2192int pm8921_usb_ovp_set_hystersis(enum pm8921_usb_debounce_time ms)
2193{
2194 u8 temp;
2195
2196 if (!the_chip) {
2197 pr_err("called before init\n");
2198 return -EINVAL;
2199 }
2200
2201 if (ms > PM_USB_DEBOUNCE_80P5MS) {
2202 pr_err("limiting debounce to 80.5ms\n");
2203 ms = PM_USB_DEBOUNCE_80P5MS;
2204 }
2205
2206 temp = USB_DEBOUNCE_TIME_MASK & (ms << USB_DEBOUNCE_TIME_SHIFT);
2207
2208 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
2209 USB_DEBOUNCE_TIME_MASK, temp);
2210}
2211EXPORT_SYMBOL(pm8921_usb_ovp_set_hystersis);
2212
2213#define USB_OVP_DISABLE_MASK 0x80
2214int pm8921_usb_ovp_disable(int disable)
2215{
2216 u8 temp = 0;
2217
2218 if (!the_chip) {
2219 pr_err("called before init\n");
2220 return -EINVAL;
2221 }
2222
2223 if (disable)
2224 temp = USB_OVP_DISABLE_MASK;
2225
2226 return pm_chg_masked_write(the_chip, USB_OVP_CONTROL,
2227 USB_OVP_DISABLE_MASK, temp);
2228}
2229
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002230bool pm8921_is_battery_charging(int *source)
2231{
2232 int fsm_state, is_charging, dc_present, usb_present;
2233
2234 if (!the_chip) {
2235 pr_err("called before init\n");
2236 return -EINVAL;
2237 }
2238 fsm_state = pm_chg_get_fsm_state(the_chip);
2239 is_charging = is_battery_charging(fsm_state);
2240 if (is_charging == 0) {
2241 *source = PM8921_CHG_SRC_NONE;
2242 return is_charging;
2243 }
2244
2245 if (source == NULL)
2246 return is_charging;
2247
2248 /* the battery is charging, the source is requested, find it */
2249 dc_present = is_dc_chg_plugged_in(the_chip);
2250 usb_present = is_usb_chg_plugged_in(the_chip);
2251
2252 if (dc_present && !usb_present)
2253 *source = PM8921_CHG_SRC_DC;
2254
2255 if (usb_present && !dc_present)
2256 *source = PM8921_CHG_SRC_USB;
2257
2258 if (usb_present && dc_present)
2259 /*
2260 * The system always chooses dc for charging since it has
2261 * higher priority.
2262 */
2263 *source = PM8921_CHG_SRC_DC;
2264
2265 return is_charging;
2266}
2267EXPORT_SYMBOL(pm8921_is_battery_charging);
2268
David Keitel86034022012-04-18 12:33:58 -07002269int pm8921_set_usb_power_supply_type(enum power_supply_type type)
2270{
2271 if (!the_chip) {
2272 pr_err("called before init\n");
2273 return -EINVAL;
2274 }
2275
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002276 if (type < POWER_SUPPLY_TYPE_USB && type > POWER_SUPPLY_TYPE_BATTERY)
David Keitel86034022012-04-18 12:33:58 -07002277 return -EINVAL;
2278
Anirudh Ghayal8ecf5ad2013-02-20 09:48:42 +05302279 the_chip->usb_type = type;
David Keitel86034022012-04-18 12:33:58 -07002280 power_supply_changed(&the_chip->usb_psy);
2281 power_supply_changed(&the_chip->dc_psy);
2282 return 0;
2283}
2284EXPORT_SYMBOL_GPL(pm8921_set_usb_power_supply_type);
2285
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002286int pm8921_batt_temperature(void)
2287{
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05302288 int temp = 0, rc = 0;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002289 if (!the_chip) {
2290 pr_err("called before init\n");
2291 return -EINVAL;
2292 }
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05302293 rc = get_prop_batt_temp(the_chip, &temp);
2294 if (rc) {
2295 pr_err("Unable to read temperature");
2296 return rc;
2297 }
2298 return temp;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07002299}
2300
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002301static void handle_usb_insertion_removal(struct pm8921_chg_chip *chip)
2302{
Abhijeet Dharmapurikar68f44372013-03-01 18:25:05 -08002303 int usb_present;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002304
Abhijeet Dharmapurikare451f342012-02-23 16:39:42 -08002305 pm_chg_failed_clear(chip, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002306 usb_present = is_usb_chg_plugged_in(chip);
2307 if (chip->usb_present ^ usb_present) {
2308 notify_usb_of_the_plugin_event(usb_present);
2309 chip->usb_present = usb_present;
2310 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikar0c4bc152011-10-27 10:22:24 -07002311 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarc9ba2712012-02-23 12:42:24 -08002312 pm8921_bms_calibrate_hkadc();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002313 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002314 if (usb_present) {
2315 schedule_delayed_work(&chip->unplug_check_work,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002316 msecs_to_jiffies(UNPLUG_CHECK_RAMP_MS));
David Keitel8c5201a2012-02-24 16:08:54 -08002317 pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
2318 } else {
David Keitelacf57c82012-03-07 18:48:50 -08002319 /* USB unplugged reset target current */
Devin Kim2073afb2012-09-05 13:01:51 -07002320 usb_target_ma = 0;
David Keitel8c5201a2012-02-24 16:08:54 -08002321 pm8921_chg_disable_irq(chip, CHG_GONE_IRQ);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002322 }
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07002323 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002324}
2325
Amir Samuelovd31ef502011-10-26 14:41:36 +02002326static void handle_stop_ext_chg(struct pm8921_chg_chip *chip)
2327{
David Keitel88e1b572012-01-11 11:57:14 -08002328 if (!chip->ext_psy) {
Amir Samuelovd31ef502011-10-26 14:41:36 +02002329 pr_debug("external charger not registered.\n");
2330 return;
2331 }
2332
2333 if (!chip->ext_charging) {
2334 pr_debug("already not charging.\n");
2335 return;
2336 }
2337
David Keitel88e1b572012-01-11 11:57:14 -08002338 power_supply_set_charge_type(chip->ext_psy,
2339 POWER_SUPPLY_CHARGE_TYPE_NONE);
2340 pm8921_disable_source_current(false); /* release BATFET */
David Keitel63f71662012-02-08 20:30:00 -08002341 power_supply_changed(&chip->dc_psy);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002342 chip->ext_charging = false;
David Keiteld4e59ef2011-11-09 17:38:31 -08002343 chip->ext_charge_done = false;
David Keitel88e1b572012-01-11 11:57:14 -08002344 bms_notify_check(chip);
Amir Samuelov4ffc8ec2012-05-16 09:38:43 +03002345 /* Update battery charging LEDs and user space battery info */
2346 power_supply_changed(&chip->batt_psy);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002347}
2348
2349static void handle_start_ext_chg(struct pm8921_chg_chip *chip)
2350{
2351 int dc_present;
2352 int batt_present;
2353 int batt_temp_ok;
Amir Samuelovd31ef502011-10-26 14:41:36 +02002354 unsigned long delay =
2355 round_jiffies_relative(msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2356
David Keitel88e1b572012-01-11 11:57:14 -08002357 if (!chip->ext_psy) {
Amir Samuelovd31ef502011-10-26 14:41:36 +02002358 pr_debug("external charger not registered.\n");
2359 return;
2360 }
2361
2362 if (chip->ext_charging) {
2363 pr_debug("already charging.\n");
2364 return;
2365 }
2366
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002367 dc_present = is_dc_chg_plugged_in(chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002368 batt_present = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
2369 batt_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002370
2371 if (!dc_present) {
2372 pr_warn("%s. dc not present.\n", __func__);
2373 return;
2374 }
2375 if (!batt_present) {
2376 pr_warn("%s. battery not present.\n", __func__);
2377 return;
2378 }
2379 if (!batt_temp_ok) {
2380 pr_warn("%s. battery temperature not ok.\n", __func__);
2381 return;
2382 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002383
2384 /* Force BATFET=ON */
2385 pm8921_disable_source_current(true);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002386
David Keitel6ccbf132012-05-30 14:21:24 -07002387 schedule_delayed_work(&chip->unplug_check_work,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002388 msecs_to_jiffies(UNPLUG_CHECK_RAMP_MS));
David Keitel6ccbf132012-05-30 14:21:24 -07002389
David Keitel63f71662012-02-08 20:30:00 -08002390 power_supply_set_online(chip->ext_psy, dc_present);
David Keitel88e1b572012-01-11 11:57:14 -08002391 power_supply_set_charge_type(chip->ext_psy,
2392 POWER_SUPPLY_CHARGE_TYPE_FAST);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002393 chip->ext_charging = true;
2394 chip->ext_charge_done = false;
David Keitel88e1b572012-01-11 11:57:14 -08002395 bms_notify_check(chip);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002396 /*
2397 * since we wont get a fastchg irq from external charger
2398 * use eoc worker to detect end of charging
2399 */
Amir Samuelovd31ef502011-10-26 14:41:36 +02002400 schedule_delayed_work(&chip->eoc_work, delay);
2401 wake_lock(&chip->eoc_wake_lock);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002402 if (chip->btc_override)
2403 schedule_delayed_work(&chip->btc_override_work,
2404 round_jiffies_relative(msecs_to_jiffies
2405 (chip->btc_delay_ms)));
Amir Samuelov4ffc8ec2012-05-16 09:38:43 +03002406 /* Update battery charging LEDs and user space battery info */
2407 power_supply_changed(&chip->batt_psy);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002408}
2409
David Keitel6ccbf132012-05-30 14:21:24 -07002410static void turn_off_ovp_fet(struct pm8921_chg_chip *chip, u16 ovptestreg)
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002411{
2412 u8 temp;
2413 int rc;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002414
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002415 rc = pm_chg_write(chip, ovptestreg, 0x30);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002416 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002417 pr_err("Failed to write 0x30 to ovptestreg rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002418 return;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002419 }
David Keitel6ccbf132012-05-30 14:21:24 -07002420 rc = pm8xxx_readb(chip->dev->parent, ovptestreg, &temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002421 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002422 pr_err("Failed to read from ovptestreg rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002423 return;
2424 }
2425 /* set ovp fet disable bit and the write bit */
2426 temp |= 0x81;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002427 rc = pm_chg_write(chip, ovptestreg, temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002428 if (rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002429 pr_err("Failed to write 0x%x ovptestreg rc=%d\n", temp, rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002430 return;
2431 }
2432}
2433
David Keitel6ccbf132012-05-30 14:21:24 -07002434static void turn_on_ovp_fet(struct pm8921_chg_chip *chip, u16 ovptestreg)
David Keitel8c5201a2012-02-24 16:08:54 -08002435{
2436 u8 temp;
2437 int rc;
2438
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002439 rc = pm_chg_write(chip, ovptestreg, 0x30);
David Keitel8c5201a2012-02-24 16:08:54 -08002440 if (rc) {
David Keitel6ccbf132012-05-30 14:21:24 -07002441 pr_err("Failed to write 0x30 to OVP_TEST rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002442 return;
2443 }
David Keitel6ccbf132012-05-30 14:21:24 -07002444 rc = pm8xxx_readb(chip->dev->parent, ovptestreg, &temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002445 if (rc) {
David Keitel6ccbf132012-05-30 14:21:24 -07002446 pr_err("Failed to read from OVP_TEST rc = %d\n", rc);
David Keitel8c5201a2012-02-24 16:08:54 -08002447 return;
2448 }
2449 /* unset ovp fet disable bit and set the write bit */
2450 temp &= 0xFE;
2451 temp |= 0x80;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002452 rc = pm_chg_write(chip, ovptestreg, temp);
David Keitel8c5201a2012-02-24 16:08:54 -08002453 if (rc) {
David Keitel6ccbf132012-05-30 14:21:24 -07002454 pr_err("Failed to write 0x%x to OVP_TEST rc = %d\n",
David Keitel8c5201a2012-02-24 16:08:54 -08002455 temp, rc);
2456 return;
2457 }
2458}
2459
2460static int param_open_ovp_counter = 10;
2461module_param(param_open_ovp_counter, int, 0644);
2462
David Keitel6ccbf132012-05-30 14:21:24 -07002463#define USB_ACTIVE_BIT BIT(5)
2464#define DC_ACTIVE_BIT BIT(6)
2465static int is_active_chg_plugged_in(struct pm8921_chg_chip *chip,
2466 u8 active_chg_mask)
2467{
2468 if (active_chg_mask & USB_ACTIVE_BIT)
2469 return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
2470 else if (active_chg_mask & DC_ACTIVE_BIT)
2471 return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
2472 else
2473 return 0;
2474}
2475
David Keitel8c5201a2012-02-24 16:08:54 -08002476#define WRITE_BANK_4 0xC0
David Keitel6ccbf132012-05-30 14:21:24 -07002477#define OVP_DEBOUNCE_TIME 0x06
David Keitelc3e15bd2012-05-25 17:07:25 -07002478static void unplug_ovp_fet_open(struct pm8921_chg_chip *chip)
David Keitel8c5201a2012-02-24 16:08:54 -08002479{
David Keitel6ccbf132012-05-30 14:21:24 -07002480 int chg_gone = 0, active_chg_plugged_in = 0;
David Keitel8c5201a2012-02-24 16:08:54 -08002481 int count = 0;
David Keitel6ccbf132012-05-30 14:21:24 -07002482 u8 active_mask = 0;
2483 u16 ovpreg, ovptestreg;
2484
2485 if (is_usb_chg_plugged_in(chip) &&
2486 (chip->active_path & USB_ACTIVE_BIT)) {
2487 ovpreg = USB_OVP_CONTROL;
2488 ovptestreg = USB_OVP_TEST;
2489 active_mask = USB_ACTIVE_BIT;
2490 } else if (is_dc_chg_plugged_in(chip) &&
2491 (chip->active_path & DC_ACTIVE_BIT)) {
2492 ovpreg = DC_OVP_CONTROL;
2493 ovptestreg = DC_OVP_TEST;
2494 active_mask = DC_ACTIVE_BIT;
2495 } else {
2496 return;
2497 }
David Keitel8c5201a2012-02-24 16:08:54 -08002498
2499 while (count++ < param_open_ovp_counter) {
David Keitel6ccbf132012-05-30 14:21:24 -07002500 pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x0);
David Keitel8c5201a2012-02-24 16:08:54 -08002501 usleep(10);
David Keitel6ccbf132012-05-30 14:21:24 -07002502 active_chg_plugged_in
2503 = is_active_chg_plugged_in(chip, active_mask);
David Keitel8c5201a2012-02-24 16:08:54 -08002504 chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
David Keitel6ccbf132012-05-30 14:21:24 -07002505 pr_debug("OVP FET count = %d chg_gone=%d, active_valid = %d\n",
2506 count, chg_gone, active_chg_plugged_in);
David Keitel8c5201a2012-02-24 16:08:54 -08002507
2508 /* note usb_chg_plugged_in=0 => chg_gone=1 */
David Keitel6ccbf132012-05-30 14:21:24 -07002509 if (chg_gone == 1 && active_chg_plugged_in == 1) {
David Keitel8c5201a2012-02-24 16:08:54 -08002510 pr_debug("since chg_gone = 1 dis ovp_fet for 20msec\n");
David Keitel6ccbf132012-05-30 14:21:24 -07002511 turn_off_ovp_fet(chip, ovptestreg);
David Keitel8c5201a2012-02-24 16:08:54 -08002512
2513 msleep(20);
2514
David Keitel6ccbf132012-05-30 14:21:24 -07002515 turn_on_ovp_fet(chip, ovptestreg);
David Keitel8c5201a2012-02-24 16:08:54 -08002516 } else {
David Keitel712782e2012-03-29 14:11:47 -07002517 break;
David Keitel8c5201a2012-02-24 16:08:54 -08002518 }
2519 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002520 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
2521 pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x6);
2522 else
2523 pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x2);
2524
David Keitel6ccbf132012-05-30 14:21:24 -07002525 pr_debug("Exit count=%d chg_gone=%d, active_valid=%d\n",
2526 count, chg_gone, active_chg_plugged_in);
David Keitel712782e2012-03-29 14:11:47 -07002527 return;
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002528}
David Keitelacf57c82012-03-07 18:48:50 -08002529
2530static int find_usb_ma_value(int value)
2531{
2532 int i;
2533
2534 for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
2535 if (value >= usb_ma_table[i].usb_ma)
2536 break;
2537 }
2538
2539 return i;
2540}
2541
2542static void decrease_usb_ma_value(int *value)
2543{
2544 int i;
2545
2546 if (value) {
2547 i = find_usb_ma_value(*value);
2548 if (i > 0)
2549 i--;
David Keitelc7bba2f2012-06-15 17:05:52 -07002550 while (!the_chip->iusb_fine_res && i > 0
2551 && (usb_ma_table[i].value & PM8917_IUSB_FINE_RES))
2552 i--;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002553
2554 if (i < 0) {
2555 pr_err("can't find %dmA in usb_ma_table. Use min.\n",
2556 *value);
2557 i = 0;
2558 }
2559
David Keitelacf57c82012-03-07 18:48:50 -08002560 *value = usb_ma_table[i].usb_ma;
2561 }
2562}
2563
2564static void increase_usb_ma_value(int *value)
2565{
2566 int i;
2567
2568 if (value) {
2569 i = find_usb_ma_value(*value);
2570
2571 if (i < (ARRAY_SIZE(usb_ma_table) - 1))
2572 i++;
David Keitel38bdd4f2012-04-19 15:39:13 -07002573 /* Get next correct entry if IUSB_FINE_RES is not available */
2574 while (!the_chip->iusb_fine_res
2575 && (usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
2576 && i < (ARRAY_SIZE(usb_ma_table) - 1))
2577 i++;
2578
David Keitelacf57c82012-03-07 18:48:50 -08002579 *value = usb_ma_table[i].usb_ma;
2580 }
2581}
2582
2583static void vin_collapse_check_worker(struct work_struct *work)
2584{
2585 struct delayed_work *dwork = to_delayed_work(work);
2586 struct pm8921_chg_chip *chip = container_of(dwork,
2587 struct pm8921_chg_chip, vin_collapse_check_work);
2588
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002589 /*
2590 * AICL only for wall-chargers. If the charger appears to be plugged
2591 * back in now, the corresponding unplug must have been because of we
2592 * were trying to draw more current than the charger can support. In
2593 * such a case reset usb current to 500mA and decrease the target.
2594 * The AICL algorithm will step up the current from 500mA to target
2595 */
2596 if (is_usb_chg_plugged_in(chip)
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002597 && usb_target_ma > USB_WALL_THRESHOLD_MA
2598 && !chip->disable_aicl) {
David Keitelacf57c82012-03-07 18:48:50 -08002599 /* decrease usb_target_ma */
2600 decrease_usb_ma_value(&usb_target_ma);
2601 /* reset here, increase in unplug_check_worker */
2602 __pm8921_charger_vbus_draw(USB_WALL_THRESHOLD_MA);
2603 pr_debug("usb_now=%d, usb_target = %d\n",
2604 USB_WALL_THRESHOLD_MA, usb_target_ma);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002605 if (!delayed_work_pending(&chip->unplug_check_work))
2606 schedule_delayed_work(&chip->unplug_check_work,
2607 msecs_to_jiffies
2608 (UNPLUG_CHECK_WAIT_PERIOD_MS));
David Keitelacf57c82012-03-07 18:48:50 -08002609 } else {
2610 handle_usb_insertion_removal(chip);
2611 }
2612}
2613
2614#define VIN_MIN_COLLAPSE_CHECK_MS 50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002615static irqreturn_t usbin_valid_irq_handler(int irq, void *data)
2616{
David Keitelacf57c82012-03-07 18:48:50 -08002617 if (usb_target_ma)
2618 schedule_delayed_work(&the_chip->vin_collapse_check_work,
2619 round_jiffies_relative(msecs_to_jiffies
2620 (VIN_MIN_COLLAPSE_CHECK_MS)));
2621 else
2622 handle_usb_insertion_removal(data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002623 return IRQ_HANDLED;
2624}
2625
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002626static irqreturn_t batt_inserted_irq_handler(int irq, void *data)
2627{
2628 struct pm8921_chg_chip *chip = data;
2629 int status;
2630
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07002631 status = pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
2632 schedule_work(&chip->battery_id_valid_work);
Amir Samuelovd31ef502011-10-26 14:41:36 +02002633 handle_start_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002634 pr_debug("battery present=%d", status);
2635 power_supply_changed(&chip->batt_psy);
2636 return IRQ_HANDLED;
2637}
Amir Samuelovd31ef502011-10-26 14:41:36 +02002638
2639/*
2640 * this interrupt used to restart charging a battery.
2641 *
2642 * Note: When DC-inserted the VBAT can't go low.
2643 * VPH_PWR is provided by the ext-charger.
2644 * After End-Of-Charging from DC, charging can be resumed only
2645 * if DC is removed and then inserted after the battery was in use.
2646 * Therefore the handle_start_ext_chg() is not called.
2647 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002648static irqreturn_t vbatdet_low_irq_handler(int irq, void *data)
2649{
2650 struct pm8921_chg_chip *chip = data;
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002651 int high_transition;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002652
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002653 high_transition = pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ);
Abhijeet Dharmapurikar07e48bf2011-09-26 19:46:40 -07002654
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002655 if (high_transition) {
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002656 /* enable auto charging */
2657 pm_chg_auto_enable(chip, !charging_disabled);
2658 pr_info("batt fell below resume voltage %s\n",
2659 charging_disabled ? "" : "charger enabled");
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002660 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002661 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002662
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002663 power_supply_changed(&chip->batt_psy);
2664 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002665 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002666
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002667 return IRQ_HANDLED;
2668}
2669
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002670static irqreturn_t chgwdog_irq_handler(int irq, void *data)
2671{
2672 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
2673 return IRQ_HANDLED;
2674}
2675
2676static irqreturn_t vcp_irq_handler(int irq, void *data)
2677{
David Keitel8c5201a2012-02-24 16:08:54 -08002678 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002679 return IRQ_HANDLED;
2680}
2681
2682static irqreturn_t atcdone_irq_handler(int irq, void *data)
2683{
2684 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
2685 return IRQ_HANDLED;
2686}
2687
2688static irqreturn_t atcfail_irq_handler(int irq, void *data)
2689{
2690 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
2691 return IRQ_HANDLED;
2692}
2693
2694static irqreturn_t chgdone_irq_handler(int irq, void *data)
2695{
2696 struct pm8921_chg_chip *chip = data;
2697
2698 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02002699
2700 handle_stop_ext_chg(chip);
2701
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002702 power_supply_changed(&chip->batt_psy);
2703 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002704 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002705
Abhijeet Dharmapurikarfad72352011-09-25 23:06:05 -07002706 bms_notify_check(chip);
2707
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002708 return IRQ_HANDLED;
2709}
2710
2711static irqreturn_t chgfail_irq_handler(int irq, void *data)
2712{
2713 struct pm8921_chg_chip *chip = data;
David Keitel753ec8d2011-11-02 10:56:37 -07002714 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002715
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002716 if (!chip->stop_chg_upon_expiry) {
2717 ret = pm_chg_failed_clear(chip, 1);
2718 if (ret)
2719 pr_err("Failed to write CHG_FAILED_CLEAR bit\n");
2720 }
David Keitel753ec8d2011-11-02 10:56:37 -07002721
2722 pr_err("batt_present = %d, batt_temp_ok = %d, state_changed_to=%d\n",
2723 get_prop_batt_present(chip),
2724 pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ),
2725 pm_chg_get_fsm_state(data));
2726
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002727 power_supply_changed(&chip->batt_psy);
2728 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002729 power_supply_changed(&chip->dc_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002730 return IRQ_HANDLED;
2731}
2732
2733static irqreturn_t chgstate_irq_handler(int irq, void *data)
2734{
2735 struct pm8921_chg_chip *chip = data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002736
2737 pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
2738 power_supply_changed(&chip->batt_psy);
2739 power_supply_changed(&chip->usb_psy);
David Keitel63f71662012-02-08 20:30:00 -08002740 power_supply_changed(&chip->dc_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002741
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07002742 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002743
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002744 return IRQ_HANDLED;
2745}
2746
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002747enum {
2748 PON_TIME_25NS = 0x04,
2749 PON_TIME_50NS = 0x08,
2750 PON_TIME_100NS = 0x0C,
2751};
David Keitel8c5201a2012-02-24 16:08:54 -08002752
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002753static void set_min_pon_time(struct pm8921_chg_chip *chip, int pon_time_ns)
David Keitel8c5201a2012-02-24 16:08:54 -08002754{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002755 u8 temp;
2756 int rc;
David Keitel8c5201a2012-02-24 16:08:54 -08002757
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002758 rc = pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0x40);
2759 if (rc) {
2760 pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
2761 return;
2762 }
2763 rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
2764 if (rc) {
2765 pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
2766 return;
2767 }
2768 /* clear the min pon time select bit */
2769 temp &= 0xF3;
2770 /* set the pon time */
2771 temp |= (u8)pon_time_ns;
2772 /* write enable bank 4 */
2773 temp |= 0x80;
2774 rc = pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, temp);
2775 if (rc) {
2776 pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
2777 return;
2778 }
2779}
David Keitel8c5201a2012-02-24 16:08:54 -08002780
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002781static void attempt_reverse_boost_fix(struct pm8921_chg_chip *chip)
2782{
2783 pr_debug("Start\n");
2784 set_min_pon_time(chip, PON_TIME_100NS);
2785 pm_chg_vinmin_set(chip, chip->vin_min + 200);
2786 msleep(250);
2787 pm_chg_vinmin_set(chip, chip->vin_min);
2788 set_min_pon_time(chip, PON_TIME_25NS);
2789 pr_debug("End\n");
David Keitel8c5201a2012-02-24 16:08:54 -08002790}
2791
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002792#define VIN_ACTIVE_BIT BIT(0)
David Keitel6ccbf132012-05-30 14:21:24 -07002793#define UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US 200
2794#define VIN_MIN_INCREASE_MV 100
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002795static void unplug_check_worker(struct work_struct *work)
2796{
2797 struct delayed_work *dwork = to_delayed_work(work);
2798 struct pm8921_chg_chip *chip = container_of(dwork,
2799 struct pm8921_chg_chip, unplug_check_work);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002800 u8 reg_loop = 0, active_path;
David Keitel6ccbf132012-05-30 14:21:24 -07002801 int rc, ibat, active_chg_plugged_in, usb_ma;
David Keitel8c5201a2012-02-24 16:08:54 -08002802 int chg_gone = 0;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002803 bool ramp = false;
David Keitel6ccbf132012-05-30 14:21:24 -07002804
2805 rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS1, &active_path);
2806 if (rc) {
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002807 pr_err("Failed to read PBL_ACCESS1 rc=%d\n", rc);
2808 return;
David Keitel6ccbf132012-05-30 14:21:24 -07002809 }
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002810
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002811 chip->active_path = active_path;
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002812 active_chg_plugged_in = is_active_chg_plugged_in(chip, active_path);
David Keitel6ccbf132012-05-30 14:21:24 -07002813 pr_debug("active_path = 0x%x, active_chg_plugged_in = %d\n",
2814 active_path, active_chg_plugged_in);
2815 if (active_path & USB_ACTIVE_BIT) {
2816 pr_debug("USB charger active\n");
2817
2818 pm_chg_iusbmax_get(chip, &usb_ma);
Devin Kim2073afb2012-09-05 13:01:51 -07002819
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002820 if (usb_ma <= 100) {
2821 pr_debug(
2822 "Unenumerated or suspended usb_ma = %d skip\n",
2823 usb_ma);
2824 goto check_again_later;
David Keitel6ccbf132012-05-30 14:21:24 -07002825 }
2826 } else if (active_path & DC_ACTIVE_BIT) {
2827 pr_debug("DC charger active\n");
2828 } else {
2829 /* No charger active */
2830 if (!(is_usb_chg_plugged_in(chip)
2831 && !(is_dc_chg_plugged_in(chip)))) {
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05302832 get_prop_batt_current(chip, &ibat);
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002833 pr_debug(
David Keitel6ccbf132012-05-30 14:21:24 -07002834 "Stop: chg removed reg_loop = %d, fsm = %d ibat = %d\n",
2835 pm_chg_get_regulation_loop(chip),
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05302836 pm_chg_get_fsm_state(chip), ibat);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002837 return;
2838 } else {
2839 goto check_again_later;
David Keitel6ccbf132012-05-30 14:21:24 -07002840 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002841 }
David Keitel8c5201a2012-02-24 16:08:54 -08002842
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002843 /* AICL only for usb wall charger */
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002844 if ((active_path & USB_ACTIVE_BIT) && usb_target_ma > 0 &&
2845 !chip->disable_aicl) {
David Keitel6ccbf132012-05-30 14:21:24 -07002846 reg_loop = pm_chg_get_regulation_loop(chip);
2847 pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
2848 if ((reg_loop & VIN_ACTIVE_BIT) &&
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002849 (usb_ma > USB_WALL_THRESHOLD_MA)
2850 && !charging_disabled) {
David Keitel6ccbf132012-05-30 14:21:24 -07002851 decrease_usb_ma_value(&usb_ma);
2852 usb_target_ma = usb_ma;
2853 /* end AICL here */
2854 __pm8921_charger_vbus_draw(usb_ma);
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002855 pr_debug("usb_now=%d, usb_target = %d\n",
David Keitel6ccbf132012-05-30 14:21:24 -07002856 usb_ma, usb_target_ma);
2857 }
David Keitelacf57c82012-03-07 18:48:50 -08002858 }
2859
2860 reg_loop = pm_chg_get_regulation_loop(chip);
2861 pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
2862
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05302863 rc = get_prop_batt_current(chip, &ibat);
Anirudh Ghayal0da182f2013-02-22 11:17:19 +05302864 if ((reg_loop & VIN_ACTIVE_BIT) && !chip->disable_chg_rmvl_wrkarnd) {
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05302865 if (ibat > 0 && !rc) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002866 pr_debug("revboost ibat = %d fsm = %d loop = 0x%x\n",
2867 ibat, pm_chg_get_fsm_state(chip), reg_loop);
2868 attempt_reverse_boost_fix(chip);
2869 /* after reverse boost fix check if the active
2870 * charger was detected as removed */
2871 active_chg_plugged_in
2872 = is_active_chg_plugged_in(chip,
2873 active_path);
2874 pr_debug("revboost post: active_chg_plugged_in = %d\n",
2875 active_chg_plugged_in);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002876 }
2877 }
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002878
2879 active_chg_plugged_in = is_active_chg_plugged_in(chip, active_path);
David Keitel6ccbf132012-05-30 14:21:24 -07002880 pr_debug("active_path = 0x%x, active_chg = %d\n",
2881 active_path, active_chg_plugged_in);
David Keitel8c5201a2012-02-24 16:08:54 -08002882 chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
2883
Anirudh Ghayal0da182f2013-02-22 11:17:19 +05302884 if (chg_gone == 1 && active_chg_plugged_in == 1 &&
2885 !chip->disable_chg_rmvl_wrkarnd) {
David Keitel6ccbf132012-05-30 14:21:24 -07002886 pr_debug("chg_gone=%d, active_chg_plugged_in = %d\n",
2887 chg_gone, active_chg_plugged_in);
David Keitelc3e15bd2012-05-25 17:07:25 -07002888 unplug_ovp_fet_open(chip);
David Keitel8c5201a2012-02-24 16:08:54 -08002889 }
2890
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002891 /* AICL only for usb wall charger */
2892 if (!(reg_loop & VIN_ACTIVE_BIT) && (active_path & USB_ACTIVE_BIT)
2893 && usb_target_ma > 0
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08002894 && !charging_disabled
2895 && !chip->disable_aicl) {
David Keitelacf57c82012-03-07 18:48:50 -08002896 /* only increase iusb_max if vin loop not active */
2897 if (usb_ma < usb_target_ma) {
2898 increase_usb_ma_value(&usb_ma);
Anirudh Ghayal0ddca632013-01-23 16:43:31 +05302899 if (usb_ma > usb_target_ma)
2900 usb_ma = usb_target_ma;
David Keitelacf57c82012-03-07 18:48:50 -08002901 __pm8921_charger_vbus_draw(usb_ma);
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08002902 pr_debug("usb_now=%d, usb_target = %d\n",
David Keitelacf57c82012-03-07 18:48:50 -08002903 usb_ma, usb_target_ma);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002904 ramp = true;
Devin Kim2073afb2012-09-05 13:01:51 -07002905 } else {
2906 usb_target_ma = usb_ma;
David Keitelacf57c82012-03-07 18:48:50 -08002907 }
2908 }
Devin Kim2073afb2012-09-05 13:01:51 -07002909check_again_later:
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002910 pr_debug("ramp: %d\n", ramp);
David Keitelacf57c82012-03-07 18:48:50 -08002911 /* schedule to check again later */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002912 if (ramp)
2913 schedule_delayed_work(&chip->unplug_check_work,
2914 msecs_to_jiffies(UNPLUG_CHECK_RAMP_MS));
2915 else
2916 schedule_delayed_work(&chip->unplug_check_work,
2917 msecs_to_jiffies(UNPLUG_CHECK_WAIT_PERIOD_MS));
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002918}
2919
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002920static irqreturn_t loop_change_irq_handler(int irq, void *data)
2921{
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08002922 struct pm8921_chg_chip *chip = data;
2923
2924 pr_debug("fsm_state=%d reg_loop=0x%x\n",
2925 pm_chg_get_fsm_state(data),
2926 pm_chg_get_regulation_loop(data));
David Keitelb57db9e2012-03-28 16:08:43 -07002927 schedule_work(&chip->unplug_check_work.work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002928 return IRQ_HANDLED;
2929}
2930
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002931struct ibatmax_max_adj_entry {
2932 int ibat_max_ma;
2933 int max_adj_ma;
2934};
2935
2936static struct ibatmax_max_adj_entry ibatmax_adj_table[] = {
2937 {975, 300},
2938 {1475, 150},
2939 {1975, 200},
2940 {2475, 250},
2941};
2942
2943static int find_ibat_max_adj_ma(int ibat_target_ma)
2944{
2945 int i = 0;
2946
Abhijeet Dharmapurikare7e27af2013-02-12 14:44:04 -08002947 for (i = ARRAY_SIZE(ibatmax_adj_table); i > 0; i--) {
2948 if (ibat_target_ma >= ibatmax_adj_table[i - 1].ibat_max_ma)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002949 break;
2950 }
2951
Willie Ruaneeee0aa2013-03-04 21:54:10 -08002952 if (i > 0)
2953 i--;
2954
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002955 return ibatmax_adj_table[i].max_adj_ma;
2956}
2957
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002958static irqreturn_t fastchg_irq_handler(int irq, void *data)
2959{
2960 struct pm8921_chg_chip *chip = data;
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002961 int high_transition;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002962
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002963 high_transition = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
2964 if (high_transition && !delayed_work_pending(&chip->eoc_work)) {
2965 wake_lock(&chip->eoc_wake_lock);
2966 schedule_delayed_work(&chip->eoc_work,
2967 round_jiffies_relative(msecs_to_jiffies
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07002968 (EOC_CHECK_PERIOD_MS)));
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002969 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07002970 if (high_transition
2971 && chip->btc_override
2972 && !delayed_work_pending(&chip->btc_override_work)) {
2973 schedule_delayed_work(&chip->btc_override_work,
2974 round_jiffies_relative(msecs_to_jiffies
2975 (chip->btc_delay_ms)));
2976 }
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07002977 power_supply_changed(&chip->batt_psy);
2978 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002979 return IRQ_HANDLED;
2980}
2981
2982static irqreturn_t trklchg_irq_handler(int irq, void *data)
2983{
2984 struct pm8921_chg_chip *chip = data;
2985
2986 power_supply_changed(&chip->batt_psy);
2987 return IRQ_HANDLED;
2988}
2989
2990static irqreturn_t batt_removed_irq_handler(int irq, void *data)
2991{
2992 struct pm8921_chg_chip *chip = data;
2993 int status;
2994
2995 status = pm_chg_get_rt_status(chip, BATT_REMOVED_IRQ);
2996 pr_debug("battery present=%d state=%d", !status,
2997 pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02002998 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002999 power_supply_changed(&chip->batt_psy);
3000 return IRQ_HANDLED;
3001}
3002
3003static irqreturn_t batttemp_hot_irq_handler(int irq, void *data)
3004{
3005 struct pm8921_chg_chip *chip = data;
3006
Amir Samuelovd31ef502011-10-26 14:41:36 +02003007 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003008 power_supply_changed(&chip->batt_psy);
3009 return IRQ_HANDLED;
3010}
3011
3012static irqreturn_t chghot_irq_handler(int irq, void *data)
3013{
3014 struct pm8921_chg_chip *chip = data;
3015
3016 pr_debug("Chg hot fsm_state=%d\n", pm_chg_get_fsm_state(data));
3017 power_supply_changed(&chip->batt_psy);
3018 power_supply_changed(&chip->usb_psy);
David Keitel88e1b572012-01-11 11:57:14 -08003019 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003020 return IRQ_HANDLED;
3021}
3022
3023static irqreturn_t batttemp_cold_irq_handler(int irq, void *data)
3024{
3025 struct pm8921_chg_chip *chip = data;
3026
3027 pr_debug("Batt cold fsm_state=%d\n", pm_chg_get_fsm_state(data));
Amir Samuelovd31ef502011-10-26 14:41:36 +02003028 handle_stop_ext_chg(chip);
3029
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003030 power_supply_changed(&chip->batt_psy);
3031 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003032 return IRQ_HANDLED;
3033}
3034
3035static irqreturn_t chg_gone_irq_handler(int irq, void *data)
3036{
3037 struct pm8921_chg_chip *chip = data;
David Keitelc3e15bd2012-05-25 17:07:25 -07003038 int chg_gone, usb_chg_plugged_in;
David Keitel8c5201a2012-02-24 16:08:54 -08003039
3040 usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
3041 chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
3042
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08003043 pr_debug("chg_gone=%d, usb_valid = %d\n", chg_gone, usb_chg_plugged_in);
3044 pr_debug("Chg gone fsm_state=%d\n", pm_chg_get_fsm_state(data));
David Keitel0873d0f2012-03-29 11:44:49 -07003045
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003046 power_supply_changed(&chip->batt_psy);
3047 power_supply_changed(&chip->usb_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003048 return IRQ_HANDLED;
3049}
David Keitel52fda532011-11-10 10:43:44 -08003050/*
3051 *
3052 * bat_temp_ok_irq_handler - is edge triggered, hence it will
3053 * fire for two cases:
3054 *
3055 * If the interrupt line switches to high temperature is okay
3056 * and thus charging begins.
3057 * If bat_temp_ok is low this means the temperature is now
3058 * too hot or cold, so charging is stopped.
3059 *
3060 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003061static irqreturn_t bat_temp_ok_irq_handler(int irq, void *data)
3062{
David Keitel52fda532011-11-10 10:43:44 -08003063 int bat_temp_ok;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003064 struct pm8921_chg_chip *chip = data;
3065
David Keitel52fda532011-11-10 10:43:44 -08003066 bat_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
3067
3068 pr_debug("batt_temp_ok = %d fsm_state%d\n",
3069 bat_temp_ok, pm_chg_get_fsm_state(data));
3070
3071 if (bat_temp_ok)
3072 handle_start_ext_chg(chip);
3073 else
3074 handle_stop_ext_chg(chip);
Amir Samuelovd31ef502011-10-26 14:41:36 +02003075
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003076 power_supply_changed(&chip->batt_psy);
3077 power_supply_changed(&chip->usb_psy);
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07003078 bms_notify_check(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003079 return IRQ_HANDLED;
3080}
3081
3082static irqreturn_t coarse_det_low_irq_handler(int irq, void *data)
3083{
3084 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3085 return IRQ_HANDLED;
3086}
3087
3088static irqreturn_t vdd_loop_irq_handler(int irq, void *data)
3089{
3090 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3091 return IRQ_HANDLED;
3092}
3093
3094static irqreturn_t vreg_ov_irq_handler(int irq, void *data)
3095{
3096 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3097 return IRQ_HANDLED;
3098}
3099
3100static irqreturn_t vbatdet_irq_handler(int irq, void *data)
3101{
3102 pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
3103 return IRQ_HANDLED;
3104}
3105
3106static irqreturn_t batfet_irq_handler(int irq, void *data)
3107{
3108 struct pm8921_chg_chip *chip = data;
3109
3110 pr_debug("vreg ov\n");
3111 power_supply_changed(&chip->batt_psy);
3112 return IRQ_HANDLED;
3113}
3114
3115static irqreturn_t dcin_valid_irq_handler(int irq, void *data)
3116{
Amir Samuelovd31ef502011-10-26 14:41:36 +02003117 struct pm8921_chg_chip *chip = data;
David Keitel88e1b572012-01-11 11:57:14 -08003118 int dc_present;
Amir Samuelovd31ef502011-10-26 14:41:36 +02003119
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003120 pm_chg_failed_clear(chip, 1);
David Keitel88e1b572012-01-11 11:57:14 -08003121 dc_present = pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003122
3123 if (chip->dc_present ^ dc_present)
3124 pm8921_bms_calibrate_hkadc();
3125
David Keitel88e1b572012-01-11 11:57:14 -08003126 if (dc_present)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003127 pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
David Keitel88e1b572012-01-11 11:57:14 -08003128 else
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003129 pm8921_chg_disable_irq(chip, CHG_GONE_IRQ);
3130
3131 chip->dc_present = dc_present;
3132
3133 if (chip->ext_psy) {
3134 if (dc_present)
3135 handle_start_ext_chg(chip);
3136 else
3137 handle_stop_ext_chg(chip);
3138 } else {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003139 if (dc_present)
3140 schedule_delayed_work(&chip->unplug_check_work,
3141 msecs_to_jiffies(UNPLUG_CHECK_WAIT_PERIOD_MS));
3142 power_supply_changed(&chip->dc_psy);
3143 }
3144
3145 power_supply_changed(&chip->batt_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003146 return IRQ_HANDLED;
3147}
3148
3149static irqreturn_t dcin_ov_irq_handler(int irq, void *data)
3150{
Amir Samuelovd31ef502011-10-26 14:41:36 +02003151 struct pm8921_chg_chip *chip = data;
3152
Amir Samuelovd31ef502011-10-26 14:41:36 +02003153 handle_stop_ext_chg(chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003154 return IRQ_HANDLED;
3155}
3156
3157static irqreturn_t dcin_uv_irq_handler(int irq, void *data)
3158{
Amir Samuelovd31ef502011-10-26 14:41:36 +02003159 struct pm8921_chg_chip *chip = data;
3160
Amir Samuelovd31ef502011-10-26 14:41:36 +02003161 handle_stop_ext_chg(chip);
3162
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003163 return IRQ_HANDLED;
3164}
3165
David Keitel88e1b572012-01-11 11:57:14 -08003166static int __pm_batt_external_power_changed_work(struct device *dev, void *data)
3167{
3168 struct power_supply *psy = &the_chip->batt_psy;
3169 struct power_supply *epsy = dev_get_drvdata(dev);
3170 int i, dcin_irq;
3171
3172 /* Only search for external supply if none is registered */
3173 if (!the_chip->ext_psy) {
3174 dcin_irq = the_chip->pmic_chg_irq[DCIN_VALID_IRQ];
3175 for (i = 0; i < epsy->num_supplicants; i++) {
3176 if (!strncmp(epsy->supplied_to[i], psy->name, 7)) {
3177 if (!strncmp(epsy->name, "dc", 2)) {
3178 the_chip->ext_psy = epsy;
3179 dcin_valid_irq_handler(dcin_irq,
3180 the_chip);
3181 }
3182 }
3183 }
3184 }
3185 return 0;
3186}
3187
3188static void pm_batt_external_power_changed(struct power_supply *psy)
3189{
Anirudh Ghayal34c9b852013-03-21 15:50:34 +05303190 if (!the_chip)
3191 return;
3192
David Keitel88e1b572012-01-11 11:57:14 -08003193 /* Only look for an external supply if it hasn't been registered */
3194 if (!the_chip->ext_psy)
3195 class_for_each_device(power_supply_class, NULL, psy,
3196 __pm_batt_external_power_changed_work);
3197}
3198
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003199/**
3200 * update_heartbeat - internal function to update userspace
3201 * per update_time minutes
3202 *
3203 */
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -07003204#define LOW_SOC_HEARTBEAT_MS 20000
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003205static void update_heartbeat(struct work_struct *work)
3206{
3207 struct delayed_work *dwork = to_delayed_work(work);
3208 struct pm8921_chg_chip *chip = container_of(dwork,
3209 struct pm8921_chg_chip, update_heartbeat_work);
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303210 bool chg_present = chip->usb_present || chip->dc_present;
3211
3212 /* for battery health when charger is not connected */
3213 if (chip->btc_override && !chg_present)
3214 schedule_delayed_work(&chip->btc_override_work,
3215 round_jiffies_relative(msecs_to_jiffies
3216 (chip->btc_delay_ms)));
3217
3218 /*
3219 * check temp thresholds when charger is present and
3220 * and battery is FULL. The temperature here can impact
3221 * the charging restart conditions.
3222 */
3223 if (chip->btc_override && chg_present &&
3224 !wake_lock_active(&chip->eoc_wake_lock))
3225 check_temp_thresholds(chip);
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003226
3227 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarde9c7e72012-07-15 16:29:51 -07003228 if (chip->recent_reported_soc <= 20)
3229 schedule_delayed_work(&chip->update_heartbeat_work,
3230 round_jiffies_relative(msecs_to_jiffies
3231 (LOW_SOC_HEARTBEAT_MS)));
3232 else
3233 schedule_delayed_work(&chip->update_heartbeat_work,
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003234 round_jiffies_relative(msecs_to_jiffies
3235 (chip->update_time)));
3236}
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003237#define VDD_LOOP_ACTIVE_BIT BIT(3)
3238#define VDD_MAX_INCREASE_MV 400
3239static int vdd_max_increase_mv = VDD_MAX_INCREASE_MV;
3240module_param(vdd_max_increase_mv, int, 0644);
3241
3242static int ichg_threshold_ua = -400000;
3243module_param(ichg_threshold_ua, int, 0644);
Abhijeet Dharmapurikardc3323a2012-08-10 15:47:31 -07003244
Abhijeet Dharmapurikarc615f5a2013-03-25 14:35:18 -07003245#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 13
Abhijeet Dharmapurikardc3323a2012-08-10 15:47:31 -07003246#define PM8921_CHG_VDDMAX_RES_MV 10
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003247static void adjust_vdd_max_for_fastchg(struct pm8921_chg_chip *chip,
3248 int vbat_batt_terminal_uv)
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003249{
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003250 int adj_vdd_max_mv, programmed_vdd_max;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003251 int vbat_batt_terminal_mv;
3252 int reg_loop;
3253 int delta_mv = 0;
3254
3255 if (chip->rconn_mohm == 0) {
3256 pr_debug("Exiting as rconn_mohm is 0\n");
3257 return;
3258 }
3259 /* adjust vdd_max only in normal temperature zone */
3260 if (chip->is_bat_cool || chip->is_bat_warm) {
3261 pr_debug("Exiting is_bat_cool = %d is_batt_warm = %d\n",
3262 chip->is_bat_cool, chip->is_bat_warm);
3263 return;
3264 }
3265
3266 reg_loop = pm_chg_get_regulation_loop(chip);
3267 if (!(reg_loop & VDD_LOOP_ACTIVE_BIT)) {
3268 pr_debug("Exiting Vdd loop is not active reg loop=0x%x\n",
3269 reg_loop);
3270 return;
3271 }
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003272 vbat_batt_terminal_mv = vbat_batt_terminal_uv/1000;
3273 pm_chg_vddmax_get(the_chip, &programmed_vdd_max);
3274
3275 delta_mv = chip->max_voltage_mv - vbat_batt_terminal_mv;
3276
Abhijeet Dharmapurikarc615f5a2013-03-25 14:35:18 -07003277 if (delta_mv > 0) /* meaning we want to increase the vddmax */ {
3278 if (delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
3279 pr_debug("vterm = %d is not low enough to inc vdd\n",
3280 vbat_batt_terminal_mv);
3281 return;
3282 }
3283 }
3284
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003285 adj_vdd_max_mv = programmed_vdd_max + delta_mv;
3286 pr_debug("vdd_max needs to be changed by %d mv from %d to %d\n",
3287 delta_mv,
3288 programmed_vdd_max,
3289 adj_vdd_max_mv);
3290
3291 if (adj_vdd_max_mv < chip->max_voltage_mv) {
3292 pr_debug("adj vdd_max lower than default max voltage\n");
3293 return;
3294 }
3295
Abhijeet Dharmapurikarc615f5a2013-03-25 14:35:18 -07003296 adj_vdd_max_mv = (adj_vdd_max_mv / PM8921_CHG_VDDMAX_RES_MV)
3297 * PM8921_CHG_VDDMAX_RES_MV;
Abhijeet Dharmapurikardc3323a2012-08-10 15:47:31 -07003298
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003299 if (adj_vdd_max_mv > (chip->max_voltage_mv + vdd_max_increase_mv))
3300 adj_vdd_max_mv = chip->max_voltage_mv + vdd_max_increase_mv;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003301 pr_debug("adjusting vdd_max_mv to %d to make "
3302 "vbat_batt_termial_uv = %d to %d\n",
3303 adj_vdd_max_mv, vbat_batt_terminal_uv, chip->max_voltage_mv);
3304 pm_chg_vddmax_set(chip, adj_vdd_max_mv);
3305}
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07003306
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003307static void set_appropriate_vbatdet(struct pm8921_chg_chip *chip)
3308{
3309 if (chip->is_bat_cool)
3310 pm_chg_vbatdet_set(the_chip,
3311 the_chip->cool_bat_voltage
3312 - the_chip->resume_voltage_delta);
3313 else if (chip->is_bat_warm)
3314 pm_chg_vbatdet_set(the_chip,
3315 the_chip->warm_bat_voltage
3316 - the_chip->resume_voltage_delta);
3317 else
3318 pm_chg_vbatdet_set(the_chip,
3319 the_chip->max_voltage_mv
3320 - the_chip->resume_voltage_delta);
3321}
3322
3323static void set_appropriate_battery_current(struct pm8921_chg_chip *chip)
3324{
3325 unsigned int chg_current = chip->max_bat_chg_current;
3326
3327 if (chip->is_bat_cool)
3328 chg_current = min(chg_current, chip->cool_bat_chg_current);
3329
3330 if (chip->is_bat_warm)
3331 chg_current = min(chg_current, chip->warm_bat_chg_current);
3332
3333 if (thermal_mitigation != 0 && chip->thermal_mitigation)
3334 chg_current = min(chg_current,
3335 chip->thermal_mitigation[thermal_mitigation]);
3336
3337 pm_chg_ibatmax_set(the_chip, chg_current);
3338}
3339
3340#define TEMP_HYSTERISIS_DECIDEGC 20
3341static void battery_cool(bool enter)
3342{
3343 pr_debug("enter = %d\n", enter);
3344 if (enter == the_chip->is_bat_cool)
3345 return;
3346 the_chip->is_bat_cool = enter;
3347 if (enter)
3348 pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
3349 else
3350 pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
3351 set_appropriate_battery_current(the_chip);
3352 set_appropriate_vbatdet(the_chip);
3353}
3354
3355static void battery_warm(bool enter)
3356{
3357 pr_debug("enter = %d\n", enter);
3358 if (enter == the_chip->is_bat_warm)
3359 return;
3360 the_chip->is_bat_warm = enter;
3361 if (enter)
3362 pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
3363 else
3364 pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
3365
3366 set_appropriate_battery_current(the_chip);
3367 set_appropriate_vbatdet(the_chip);
3368}
3369
3370static void check_temp_thresholds(struct pm8921_chg_chip *chip)
3371{
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05303372 int temp = 0, rc;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003373
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05303374 rc = get_prop_batt_temp(chip, &temp);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003375 pr_debug("temp = %d, warm_thr_temp = %d, cool_thr_temp = %d\n",
3376 temp, chip->warm_temp_dc,
3377 chip->cool_temp_dc);
3378
3379 if (chip->warm_temp_dc != INT_MIN) {
3380 if (chip->is_bat_warm
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303381 && temp < chip->warm_temp_dc - chip->hysteresis_temp_dc)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003382 battery_warm(false);
3383 else if (!chip->is_bat_warm && temp >= chip->warm_temp_dc)
3384 battery_warm(true);
3385 }
3386
3387 if (chip->cool_temp_dc != INT_MIN) {
3388 if (chip->is_bat_cool
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303389 && temp > chip->cool_temp_dc + chip->hysteresis_temp_dc)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003390 battery_cool(false);
3391 else if (!chip->is_bat_cool && temp <= chip->cool_temp_dc)
3392 battery_cool(true);
3393 }
3394}
3395
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003396enum {
3397 CHG_IN_PROGRESS,
3398 CHG_NOT_IN_PROGRESS,
3399 CHG_FINISHED,
3400};
3401
3402#define VBAT_TOLERANCE_MV 70
3403#define CHG_DISABLE_MSLEEP 100
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003404static int is_charging_finished(struct pm8921_chg_chip *chip,
3405 int vbat_batt_terminal_uv, int ichg_meas_ma)
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003406{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003407 int vbat_programmed, iterm_programmed, vbat_intended;
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003408 int regulation_loop, fast_chg, vcp;
3409 int rc;
3410 static int last_vbat_programmed = -EINVAL;
3411
3412 if (!is_ext_charging(chip)) {
3413 /* return if the battery is not being fastcharged */
3414 fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
3415 pr_debug("fast_chg = %d\n", fast_chg);
3416 if (fast_chg == 0)
3417 return CHG_NOT_IN_PROGRESS;
3418
3419 vcp = pm_chg_get_rt_status(chip, VCP_IRQ);
3420 pr_debug("vcp = %d\n", vcp);
3421 if (vcp == 1)
3422 return CHG_IN_PROGRESS;
3423
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003424 /* reset count if battery is hot/cold */
3425 rc = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
3426 pr_debug("batt_temp_ok = %d\n", rc);
3427 if (rc == 0)
3428 return CHG_IN_PROGRESS;
3429
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003430 rc = pm_chg_vddmax_get(chip, &vbat_programmed);
3431 if (rc) {
3432 pr_err("couldnt read vddmax rc = %d\n", rc);
3433 return CHG_IN_PROGRESS;
3434 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003435 pr_debug("vddmax = %d vbat_batt_terminal_uv=%d\n",
3436 vbat_programmed, vbat_batt_terminal_uv);
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003437
3438 if (last_vbat_programmed == -EINVAL)
3439 last_vbat_programmed = vbat_programmed;
3440 if (last_vbat_programmed != vbat_programmed) {
3441 /* vddmax changed, reset and check again */
3442 pr_debug("vddmax = %d last_vdd_max=%d\n",
3443 vbat_programmed, last_vbat_programmed);
3444 last_vbat_programmed = vbat_programmed;
3445 return CHG_IN_PROGRESS;
3446 }
3447
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003448 if (chip->is_bat_cool)
3449 vbat_intended = chip->cool_bat_voltage;
3450 else if (chip->is_bat_warm)
3451 vbat_intended = chip->warm_bat_voltage;
3452 else
3453 vbat_intended = chip->max_voltage_mv;
3454
Abhijeet Dharmapurikarc615f5a2013-03-25 14:35:18 -07003455 if (vbat_batt_terminal_uv / 1000
3456 < vbat_intended - MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
3457 pr_debug("terminal_uv:%d < vbat_intended:%d-hyst:%d\n",
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003458 vbat_batt_terminal_uv,
Abhijeet Dharmapurikarc615f5a2013-03-25 14:35:18 -07003459 vbat_intended,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003460 vbat_intended);
3461 return CHG_IN_PROGRESS;
3462 }
3463
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003464 regulation_loop = pm_chg_get_regulation_loop(chip);
3465 if (regulation_loop < 0) {
3466 pr_err("couldnt read the regulation loop err=%d\n",
3467 regulation_loop);
3468 return CHG_IN_PROGRESS;
3469 }
3470 pr_debug("regulation_loop=%d\n", regulation_loop);
3471
3472 if (regulation_loop != 0 && regulation_loop != VDD_LOOP)
3473 return CHG_IN_PROGRESS;
3474 } /* !is_ext_charging */
3475
3476 /* reset count if battery chg current is more than iterm */
3477 rc = pm_chg_iterm_get(chip, &iterm_programmed);
3478 if (rc) {
3479 pr_err("couldnt read iterm rc = %d\n", rc);
3480 return CHG_IN_PROGRESS;
3481 }
3482
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003483 pr_debug("iterm_programmed = %d ichg_meas_ma=%d\n",
3484 iterm_programmed, ichg_meas_ma);
3485 /*
3486 * ichg_meas_ma < 0 means battery is drawing current
3487 * ichg_meas_ma > 0 means battery is providing current
3488 */
3489 if (ichg_meas_ma > 0)
3490 return CHG_IN_PROGRESS;
3491
3492 if (ichg_meas_ma * -1 > iterm_programmed)
3493 return CHG_IN_PROGRESS;
3494
3495 return CHG_FINISHED;
3496}
3497
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003498#define COMP_OVERRIDE_HOT_BANK 6
3499#define COMP_OVERRIDE_COLD_BANK 7
3500#define COMP_OVERRIDE_BIT BIT(1)
3501static int pm_chg_override_cold(struct pm8921_chg_chip *chip, int flag)
3502{
3503 u8 val;
3504 int rc = 0;
3505
3506 val = 0x80 | COMP_OVERRIDE_COLD_BANK << 2 | COMP_OVERRIDE_BIT;
3507
3508 if (flag)
3509 val |= 0x01;
3510
3511 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3512 if (rc < 0)
3513 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3514
3515 pr_debug("btc cold = %d val = 0x%x\n", flag, val);
3516 return rc;
3517}
3518
3519static int pm_chg_override_hot(struct pm8921_chg_chip *chip, int flag)
3520{
3521 u8 val;
3522 int rc = 0;
3523
3524 val = 0x80 | COMP_OVERRIDE_HOT_BANK << 2 | COMP_OVERRIDE_BIT;
3525
3526 if (flag)
3527 val |= 0x01;
3528
3529 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3530 if (rc < 0)
3531 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3532
3533 pr_debug("btc hot = %d val = 0x%x\n", flag, val);
3534 return rc;
3535}
3536
3537static void __devinit pm8921_chg_btc_override_init(struct pm8921_chg_chip *chip)
3538{
3539 int rc = 0;
3540 u8 reg;
3541 u8 val;
3542
3543 val = COMP_OVERRIDE_HOT_BANK << 2;
3544 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3545 if (rc < 0) {
3546 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3547 goto cold_init;
3548 }
3549 rc = pm8xxx_readb(chip->dev->parent, COMPARATOR_OVERRIDE, &reg);
3550 if (rc < 0) {
3551 pr_err("Could not read bank %d of override rc = %d\n",
3552 COMP_OVERRIDE_HOT_BANK, rc);
3553 goto cold_init;
3554 }
3555 if ((reg & COMP_OVERRIDE_BIT) != COMP_OVERRIDE_BIT) {
3556 /* for now override it as not hot */
3557 rc = pm_chg_override_hot(chip, 0);
3558 if (rc < 0)
3559 pr_err("Could not override hot rc = %d\n", rc);
3560 }
3561
3562cold_init:
3563 val = COMP_OVERRIDE_COLD_BANK << 2;
3564 rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
3565 if (rc < 0) {
3566 pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
3567 return;
3568 }
3569 rc = pm8xxx_readb(chip->dev->parent, COMPARATOR_OVERRIDE, &reg);
3570 if (rc < 0) {
3571 pr_err("Could not read bank %d of override rc = %d\n",
3572 COMP_OVERRIDE_COLD_BANK, rc);
3573 return;
3574 }
3575 if ((reg & COMP_OVERRIDE_BIT) != COMP_OVERRIDE_BIT) {
3576 /* for now override it as not cold */
3577 rc = pm_chg_override_cold(chip, 0);
3578 if (rc < 0)
3579 pr_err("Could not override cold rc = %d\n", rc);
3580 }
3581}
3582
3583static void btc_override_worker(struct work_struct *work)
3584{
3585 int decidegc;
3586 int temp;
3587 int rc = 0;
3588 struct delayed_work *dwork = to_delayed_work(work);
3589 struct pm8921_chg_chip *chip = container_of(dwork,
3590 struct pm8921_chg_chip, btc_override_work);
3591
3592 if (!chip->btc_override) {
3593 pr_err("called when not enabled\n");
3594 return;
3595 }
3596
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05303597 rc = get_prop_batt_temp(chip, &decidegc);
3598 if (rc) {
3599 pr_info("Failed to read temperature\n");
3600 goto fail_btc_temp;
3601 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003602
3603 pr_debug("temp=%d\n", decidegc);
3604
3605 temp = pm_chg_get_rt_status(chip, BATTTEMP_HOT_IRQ);
3606 if (temp) {
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303607 if (decidegc < chip->btc_override_hot_decidegc -
3608 chip->hysteresis_temp_dc)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003609 /* stop forcing batt hot */
3610 rc = pm_chg_override_hot(chip, 0);
3611 if (rc)
3612 pr_err("Couldnt write 0 to hot comp\n");
3613 } else {
3614 if (decidegc >= chip->btc_override_hot_decidegc)
3615 /* start forcing batt hot */
3616 rc = pm_chg_override_hot(chip, 1);
3617 if (rc && chip->btc_panic_if_cant_stop_chg)
3618 panic("Couldnt override comps to stop chg\n");
3619 }
3620
3621 temp = pm_chg_get_rt_status(chip, BATTTEMP_COLD_IRQ);
3622 if (temp) {
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303623 if (decidegc > chip->btc_override_cold_decidegc +
3624 chip->hysteresis_temp_dc)
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003625 /* stop forcing batt cold */
3626 rc = pm_chg_override_cold(chip, 0);
3627 if (rc)
3628 pr_err("Couldnt write 0 to cold comp\n");
3629 } else {
3630 if (decidegc <= chip->btc_override_cold_decidegc)
3631 /* start forcing batt cold */
3632 rc = pm_chg_override_cold(chip, 1);
3633 if (rc && chip->btc_panic_if_cant_stop_chg)
3634 panic("Couldnt override comps to stop chg\n");
3635 }
3636
3637 if ((is_dc_chg_plugged_in(the_chip) || is_usb_chg_plugged_in(the_chip))
3638 && get_prop_batt_status(chip) != POWER_SUPPLY_STATUS_FULL) {
3639 schedule_delayed_work(&chip->btc_override_work,
3640 round_jiffies_relative(msecs_to_jiffies
3641 (chip->btc_delay_ms)));
3642 return;
3643 }
3644
Anirudh Ghayal833f22e2013-03-07 09:09:47 +05303645fail_btc_temp:
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003646 rc = pm_chg_override_hot(chip, 0);
3647 if (rc)
3648 pr_err("Couldnt write 0 to hot comp\n");
3649 rc = pm_chg_override_cold(chip, 0);
3650 if (rc)
3651 pr_err("Couldnt write 0 to cold comp\n");
3652}
3653
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003654/**
Amir Samuelovd31ef502011-10-26 14:41:36 +02003655 * eoc_worker - internal function to check if battery EOC
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003656 * has happened
3657 *
3658 * If all conditions favouring, if the charge current is
3659 * less than the term current for three consecutive times
3660 * an EOC has happened.
3661 * The wakelock is released if there is no need to reshedule
3662 * - this happens when the battery is removed or EOC has
3663 * happened
3664 */
3665#define CONSECUTIVE_COUNT 3
Amir Samuelovd31ef502011-10-26 14:41:36 +02003666static void eoc_worker(struct work_struct *work)
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003667{
3668 struct delayed_work *dwork = to_delayed_work(work);
3669 struct pm8921_chg_chip *chip = container_of(dwork,
3670 struct pm8921_chg_chip, eoc_work);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003671 static int count;
Abhijeet Dharmapurikare451f342012-02-23 16:39:42 -08003672 int end;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003673 int vbat_meas_uv, vbat_meas_mv;
3674 int ichg_meas_ua, ichg_meas_ma;
3675 int vbat_batt_terminal_uv;
Abhijeet Dharmapurikare451f342012-02-23 16:39:42 -08003676
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003677 pm8921_bms_get_simultaneous_battery_voltage_and_current(
3678 &ichg_meas_ua, &vbat_meas_uv);
3679 vbat_meas_mv = vbat_meas_uv / 1000;
3680 /* rconn_mohm is in milliOhms */
3681 ichg_meas_ma = ichg_meas_ua / 1000;
3682 vbat_batt_terminal_uv = vbat_meas_uv
3683 + ichg_meas_ma
3684 * the_chip->rconn_mohm;
3685
3686 end = is_charging_finished(chip, vbat_batt_terminal_uv, ichg_meas_ma);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003687
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303688 if (end == CHG_NOT_IN_PROGRESS && (!chip->btc_override ||
3689 !(chip->usb_present || chip->dc_present))) {
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003690 count = 0;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003691 goto eoc_worker_stop;
Ajay Dudani11aeb7b2012-06-28 19:14:30 -07003692 }
3693
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003694 if (end == CHG_FINISHED) {
3695 count++;
3696 } else {
3697 count = 0;
3698 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003699
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003700 if (count == CONSECUTIVE_COUNT) {
3701 count = 0;
3702 pr_info("End of Charging\n");
3703
3704 pm_chg_auto_enable(chip, 0);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003705
Amir Samuelovd31ef502011-10-26 14:41:36 +02003706 if (is_ext_charging(chip))
3707 chip->ext_charge_done = true;
3708
Abhijeet Dharmapurikareb882f52011-12-22 09:02:34 -08003709 if (chip->is_bat_warm || chip->is_bat_cool)
3710 chip->bms_notify.is_battery_full = 0;
3711 else
3712 chip->bms_notify.is_battery_full = 1;
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003713 /* declare end of charging by invoking chgdone interrupt */
3714 chgdone_irq_handler(chip->pmic_chg_irq[CHGDONE_IRQ], chip);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003715 } else {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003716 check_temp_thresholds(chip);
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303717 if (end != CHG_NOT_IN_PROGRESS)
3718 adjust_vdd_max_for_fastchg(chip, vbat_batt_terminal_uv);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003719 pr_debug("EOC count = %d\n", count);
Abhijeet Dharmapurikar75c03502012-01-09 12:45:57 -08003720 schedule_delayed_work(&chip->eoc_work,
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003721 round_jiffies_relative(msecs_to_jiffies
3722 (EOC_CHECK_PERIOD_MS)));
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08003723 return;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003724 }
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003725
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003726eoc_worker_stop:
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003727 /* set the vbatdet back, in case it was changed to trigger charging */
3728 set_appropriate_vbatdet(chip);
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303729 wake_unlock(&chip->eoc_wake_lock);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07003730}
3731
Abhijeet Dharmapurikar1f52c412011-08-12 17:11:45 -07003732/**
3733 * set_disable_status_param -
3734 *
3735 * Internal function to disable battery charging and also disable drawing
3736 * any current from the source. The device is forced to run on a battery
3737 * after this.
3738 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003739static int set_disable_status_param(const char *val, struct kernel_param *kp)
3740{
3741 int ret;
3742 struct pm8921_chg_chip *chip = the_chip;
3743
3744 ret = param_set_int(val, kp);
3745 if (ret) {
3746 pr_err("error setting value %d\n", ret);
3747 return ret;
3748 }
3749 pr_info("factory set disable param to %d\n", charging_disabled);
3750 if (chip) {
3751 pm_chg_auto_enable(chip, !charging_disabled);
3752 pm_chg_charge_dis(chip, charging_disabled);
3753 }
3754 return 0;
3755}
3756module_param_call(disabled, set_disable_status_param, param_get_uint,
3757 &charging_disabled, 0644);
3758
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08003759static int rconn_mohm;
3760static int set_rconn_mohm(const char *val, struct kernel_param *kp)
3761{
3762 int ret;
3763 struct pm8921_chg_chip *chip = the_chip;
3764
3765 ret = param_set_int(val, kp);
3766 if (ret) {
3767 pr_err("error setting value %d\n", ret);
3768 return ret;
3769 }
3770 if (chip)
3771 chip->rconn_mohm = rconn_mohm;
3772 return 0;
3773}
3774module_param_call(rconn_mohm, set_rconn_mohm, param_get_uint,
3775 &rconn_mohm, 0644);
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07003776/**
3777 * set_thermal_mitigation_level -
3778 *
3779 * Internal function to control battery charging current to reduce
3780 * temperature
3781 */
3782static int set_therm_mitigation_level(const char *val, struct kernel_param *kp)
3783{
3784 int ret;
3785 struct pm8921_chg_chip *chip = the_chip;
3786
3787 ret = param_set_int(val, kp);
3788 if (ret) {
3789 pr_err("error setting value %d\n", ret);
3790 return ret;
3791 }
3792
3793 if (!chip) {
3794 pr_err("called before init\n");
3795 return -EINVAL;
3796 }
3797
3798 if (!chip->thermal_mitigation) {
3799 pr_err("no thermal mitigation\n");
3800 return -EINVAL;
3801 }
3802
3803 if (thermal_mitigation < 0
3804 || thermal_mitigation >= chip->thermal_levels) {
3805 pr_err("out of bound level selected\n");
3806 return -EINVAL;
3807 }
3808
Abhijeet Dharmapurikard585ff22011-11-10 14:27:25 -08003809 set_appropriate_battery_current(chip);
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07003810 return ret;
3811}
3812module_param_call(thermal_mitigation, set_therm_mitigation_level,
3813 param_get_uint,
3814 &thermal_mitigation, 0644);
3815
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08003816static int set_usb_max_current(const char *val, struct kernel_param *kp)
3817{
3818 int ret, mA;
3819 struct pm8921_chg_chip *chip = the_chip;
3820
3821 ret = param_set_int(val, kp);
3822 if (ret) {
3823 pr_err("error setting value %d\n", ret);
3824 return ret;
3825 }
3826 if (chip) {
3827 pr_warn("setting current max to %d\n", usb_max_current);
3828 pm_chg_iusbmax_get(chip, &mA);
3829 if (mA > usb_max_current)
3830 pm8921_charger_vbus_draw(usb_max_current);
3831 return 0;
3832 }
3833 return -EINVAL;
3834}
David Keitelacf57c82012-03-07 18:48:50 -08003835module_param_call(usb_max_current, set_usb_max_current,
3836 param_get_uint, &usb_max_current, 0644);
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08003837
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003838static void free_irqs(struct pm8921_chg_chip *chip)
3839{
3840 int i;
3841
3842 for (i = 0; i < PM_CHG_MAX_INTS; i++)
3843 if (chip->pmic_chg_irq[i]) {
3844 free_irq(chip->pmic_chg_irq[i], chip);
3845 chip->pmic_chg_irq[i] = 0;
3846 }
3847}
3848
David Keitel27aae422013-03-08 18:23:41 -08003849#define PM8921_USB_TRIM_SEL_BIT BIT(6)
David Keitel88e1b572012-01-11 11:57:14 -08003850/* determines the initial present states */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003851static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
3852{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003853 int fsm_state;
Abhijeet Dharmapurikard9ad07e2012-09-17 16:59:36 -07003854 int is_fast_chg;
David Keitel27aae422013-03-08 18:23:41 -08003855 int rc = 0;
3856 u8 trim_sel_reg = 0, regsbi;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003857
3858 chip->dc_present = !!is_dc_chg_plugged_in(chip);
3859 chip->usb_present = !!is_usb_chg_plugged_in(chip);
3860
3861 notify_usb_of_the_plugin_event(chip->usb_present);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003862 if (chip->usb_present || chip->dc_present) {
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003863 schedule_delayed_work(&chip->unplug_check_work,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003864 msecs_to_jiffies(UNPLUG_CHECK_WAIT_PERIOD_MS));
David Keitel8c5201a2012-02-24 16:08:54 -08003865 pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05303866
3867 if (chip->btc_override)
3868 schedule_delayed_work(&chip->btc_override_work,
3869 round_jiffies_relative(msecs_to_jiffies
3870 (chip->btc_delay_ms)));
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08003871 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003872
3873 pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
3874 pm8921_chg_enable_irq(chip, USBIN_VALID_IRQ);
3875 pm8921_chg_enable_irq(chip, BATT_REMOVED_IRQ);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07003876 pm8921_chg_enable_irq(chip, BATT_INSERTED_IRQ);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07003877 pm8921_chg_enable_irq(chip, DCIN_OV_IRQ);
3878 pm8921_chg_enable_irq(chip, DCIN_UV_IRQ);
David Keitel753ec8d2011-11-02 10:56:37 -07003879 pm8921_chg_enable_irq(chip, CHGFAIL_IRQ);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07003880 pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
3881 pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08003882 pm8921_chg_enable_irq(chip, BAT_TEMP_OK_IRQ);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003883
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08003884 if (get_prop_batt_present(the_chip) || is_dc_chg_plugged_in(the_chip))
3885 if (usb_chg_current)
3886 /*
3887 * Reissue a vbus draw call only if a battery
3888 * or DC is present. We don't want to brown out the
3889 * device if usb is its only source
3890 */
3891 __pm8921_charger_vbus_draw(usb_chg_current);
3892 usb_chg_current = 0;
3893
Abhijeet Dharmapurikard9ad07e2012-09-17 16:59:36 -07003894 /*
3895 * The bootloader could have started charging, a fastchg interrupt
3896 * might not happen. Check the real time status and if it is fast
3897 * charging invoke the handler so that the eoc worker could be
3898 * started
3899 */
3900 is_fast_chg = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
3901 if (is_fast_chg)
3902 fastchg_irq_handler(chip->pmic_chg_irq[FASTCHG_IRQ], chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003903
3904 fsm_state = pm_chg_get_fsm_state(chip);
3905 if (is_battery_charging(fsm_state)) {
3906 chip->bms_notify.is_charging = 1;
3907 pm8921_bms_charging_began();
3908 }
3909
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07003910 check_battery_valid(chip);
3911
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003912 pr_debug("usb = %d, dc = %d batt = %d state=%d\n",
3913 chip->usb_present,
3914 chip->dc_present,
3915 get_prop_batt_present(chip),
3916 fsm_state);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003917
3918 /* Determine which USB trim column to use */
David Keitel27aae422013-03-08 18:23:41 -08003919 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003920 chip->usb_trim_table = usb_trim_8917_table;
David Keitel27aae422013-03-08 18:23:41 -08003921 } else if (pm8xxx_get_version(chip->dev->parent) ==
3922 PM8XXX_VERSION_8038) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07003923 chip->usb_trim_table = usb_trim_8038_table;
David Keitel27aae422013-03-08 18:23:41 -08003924 } else if (pm8xxx_get_version(chip->dev->parent) ==
3925 PM8XXX_VERSION_8921) {
3926 rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, &regsbi);
3927 rc |= pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, 0x5E);
3928 rc |= pm8xxx_readb(chip->dev->parent, PM8921_USB_TRIM_SEL,
3929 &trim_sel_reg);
3930 rc |= pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, regsbi);
3931 if (rc)
3932 pr_err("Failed to read trim sel register rc=%d\n", rc);
3933
3934 if (trim_sel_reg & PM8921_USB_TRIM_SEL_BIT)
3935 chip->usb_trim_table = usb_trim_pm8921_table_1;
3936 else
3937 chip->usb_trim_table = usb_trim_pm8921_table_2;
3938 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003939}
3940
3941struct pm_chg_irq_init_data {
3942 unsigned int irq_id;
3943 char *name;
3944 unsigned long flags;
3945 irqreturn_t (*handler)(int, void *);
3946};
3947
3948#define CHG_IRQ(_id, _flags, _handler) \
3949{ \
3950 .irq_id = _id, \
3951 .name = #_id, \
3952 .flags = _flags, \
3953 .handler = _handler, \
3954}
3955struct pm_chg_irq_init_data chg_irq_data[] = {
3956 CHG_IRQ(USBIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3957 usbin_valid_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003958 CHG_IRQ(BATT_INSERTED_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3959 batt_inserted_irq_handler),
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07003960 CHG_IRQ(VBATDET_LOW_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3961 vbatdet_low_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003962 CHG_IRQ(CHGWDOG_IRQ, IRQF_TRIGGER_RISING, chgwdog_irq_handler),
3963 CHG_IRQ(VCP_IRQ, IRQF_TRIGGER_RISING, vcp_irq_handler),
3964 CHG_IRQ(ATCDONE_IRQ, IRQF_TRIGGER_RISING, atcdone_irq_handler),
3965 CHG_IRQ(ATCFAIL_IRQ, IRQF_TRIGGER_RISING, atcfail_irq_handler),
3966 CHG_IRQ(CHGDONE_IRQ, IRQF_TRIGGER_RISING, chgdone_irq_handler),
3967 CHG_IRQ(CHGFAIL_IRQ, IRQF_TRIGGER_RISING, chgfail_irq_handler),
3968 CHG_IRQ(CHGSTATE_IRQ, IRQF_TRIGGER_RISING, chgstate_irq_handler),
3969 CHG_IRQ(LOOP_CHANGE_IRQ, IRQF_TRIGGER_RISING, loop_change_irq_handler),
Abhijeet Dharmapurikar19e38132011-11-03 12:03:36 -07003970 CHG_IRQ(FASTCHG_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3971 fastchg_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003972 CHG_IRQ(TRKLCHG_IRQ, IRQF_TRIGGER_RISING, trklchg_irq_handler),
3973 CHG_IRQ(BATT_REMOVED_IRQ, IRQF_TRIGGER_RISING,
3974 batt_removed_irq_handler),
3975 CHG_IRQ(BATTTEMP_HOT_IRQ, IRQF_TRIGGER_RISING,
3976 batttemp_hot_irq_handler),
3977 CHG_IRQ(CHGHOT_IRQ, IRQF_TRIGGER_RISING, chghot_irq_handler),
3978 CHG_IRQ(BATTTEMP_COLD_IRQ, IRQF_TRIGGER_RISING,
3979 batttemp_cold_irq_handler),
David Keitel8c5201a2012-02-24 16:08:54 -08003980 CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3981 chg_gone_irq_handler),
Abhijeet Dharmapurikarf2471052011-09-25 22:18:36 -07003982 CHG_IRQ(BAT_TEMP_OK_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3983 bat_temp_ok_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003984 CHG_IRQ(COARSE_DET_LOW_IRQ, IRQF_TRIGGER_RISING,
3985 coarse_det_low_irq_handler),
3986 CHG_IRQ(VDD_LOOP_IRQ, IRQF_TRIGGER_RISING, vdd_loop_irq_handler),
3987 CHG_IRQ(VREG_OV_IRQ, IRQF_TRIGGER_RISING, vreg_ov_irq_handler),
3988 CHG_IRQ(VBATDET_IRQ, IRQF_TRIGGER_RISING, vbatdet_irq_handler),
3989 CHG_IRQ(BATFET_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3990 batfet_irq_handler),
3991 CHG_IRQ(DCIN_VALID_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3992 dcin_valid_irq_handler),
3993 CHG_IRQ(DCIN_OV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3994 dcin_ov_irq_handler),
Abhijeet Dharmapurikar956215b2011-10-19 15:30:14 -07003995 CHG_IRQ(DCIN_UV_IRQ, IRQF_TRIGGER_RISING, dcin_uv_irq_handler),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003996};
3997
3998static int __devinit request_irqs(struct pm8921_chg_chip *chip,
3999 struct platform_device *pdev)
4000{
4001 struct resource *res;
4002 int ret, i;
4003
4004 ret = 0;
4005 bitmap_fill(chip->enabled_irqs, PM_CHG_MAX_INTS);
4006
4007 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
4008 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
4009 chg_irq_data[i].name);
4010 if (res == NULL) {
4011 pr_err("couldn't find %s\n", chg_irq_data[i].name);
4012 goto err_out;
4013 }
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004014 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = res->start;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004015 ret = request_irq(res->start, chg_irq_data[i].handler,
4016 chg_irq_data[i].flags,
4017 chg_irq_data[i].name, chip);
4018 if (ret < 0) {
4019 pr_err("couldn't request %d (%s) %d\n", res->start,
4020 chg_irq_data[i].name, ret);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004021 chip->pmic_chg_irq[chg_irq_data[i].irq_id] = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004022 goto err_out;
4023 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004024 pm8921_chg_disable_irq(chip, chg_irq_data[i].irq_id);
4025 }
4026 return 0;
4027
4028err_out:
4029 free_irqs(chip);
4030 return -EINVAL;
4031}
4032
Abhijeet Dharmapurikar68f44372013-03-01 18:25:05 -08004033static void pm8921_chg_force_19p2mhz_clk(struct pm8921_chg_chip *chip)
4034{
4035 int err;
4036 u8 temp;
4037
4038 temp = 0xD1;
4039 err = pm_chg_write(chip, CHG_TEST, temp);
4040 if (err) {
4041 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4042 return;
4043 }
4044
4045 temp = 0xD3;
4046 err = pm_chg_write(chip, CHG_TEST, temp);
4047 if (err) {
4048 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4049 return;
4050 }
4051
4052 temp = 0xD1;
4053 err = pm_chg_write(chip, CHG_TEST, temp);
4054 if (err) {
4055 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4056 return;
4057 }
4058
4059 temp = 0xD5;
4060 err = pm_chg_write(chip, CHG_TEST, temp);
4061 if (err) {
4062 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4063 return;
4064 }
4065
4066 udelay(183);
4067
4068 temp = 0xD1;
4069 err = pm_chg_write(chip, CHG_TEST, temp);
4070 if (err) {
4071 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4072 return;
4073 }
4074
4075 temp = 0xD0;
4076 err = pm_chg_write(chip, CHG_TEST, temp);
4077 if (err) {
4078 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4079 return;
4080 }
4081 udelay(32);
4082
4083 temp = 0xD1;
4084 err = pm_chg_write(chip, CHG_TEST, temp);
4085 if (err) {
4086 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4087 return;
4088 }
4089
4090 temp = 0xD3;
4091 err = pm_chg_write(chip, CHG_TEST, temp);
4092 if (err) {
4093 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4094 return;
4095 }
4096}
4097
4098static void pm8921_chg_set_hw_clk_switching(struct pm8921_chg_chip *chip)
4099{
4100 int err;
4101 u8 temp;
4102
4103 temp = 0xD1;
4104 err = pm_chg_write(chip, CHG_TEST, temp);
4105 if (err) {
4106 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4107 return;
4108 }
4109
4110 temp = 0xD0;
4111 err = pm_chg_write(chip, CHG_TEST, temp);
4112 if (err) {
4113 pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
4114 return;
4115 }
4116}
4117
Abhijeet Dharmapurikared2d87e2012-06-26 20:15:36 -07004118#define VREF_BATT_THERM_FORCE_ON BIT(7)
4119static void detect_battery_removal(struct pm8921_chg_chip *chip)
4120{
4121 u8 temp;
4122
4123 pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
4124 pr_debug("upon restart CHG_CNTRL = 0x%x\n", temp);
4125
4126 if (!(temp & VREF_BATT_THERM_FORCE_ON))
4127 /*
4128 * batt therm force on bit is battery backed and is default 0
4129 * The charger sets this bit at init time. If this bit is found
4130 * 0 that means the battery was removed. Tell the bms about it
4131 */
4132 pm8921_bms_invalidate_shutdown_soc();
4133}
4134
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004135#define ENUM_TIMER_STOP_BIT BIT(1)
4136#define BOOT_DONE_BIT BIT(6)
4137#define CHG_BATFET_ON_BIT BIT(3)
4138#define CHG_VCP_EN BIT(0)
4139#define CHG_BAT_TEMP_DIS_BIT BIT(2)
4140#define SAFE_CURRENT_MA 1500
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004141#define PM_SUB_REV 0x001
4142#define MIN_CHARGE_CURRENT_MA 350
4143#define DEFAULT_SAFETY_MINUTES 500
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004144static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
4145{
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004146 u8 subrev;
4147 int rc, vdd_safe, fcc_uah, safety_time = DEFAULT_SAFETY_MINUTES;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004148
Abhijeet Dharmapurikar68f44372013-03-01 18:25:05 -08004149 /* forcing 19p2mhz before accessing any charger registers */
4150 pm8921_chg_force_19p2mhz_clk(chip);
Abhijeet Dharmapurikarc3695de2012-06-22 14:50:23 -07004151
Abhijeet Dharmapurikared2d87e2012-06-26 20:15:36 -07004152 detect_battery_removal(chip);
4153
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004154 rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004155 BOOT_DONE_BIT, BOOT_DONE_BIT);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004156 if (rc) {
4157 pr_err("Failed to set BOOT_DONE_BIT rc=%d\n", rc);
4158 return rc;
4159 }
4160
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08004161 vdd_safe = chip->max_voltage_mv + VDD_MAX_INCREASE_MV;
4162
4163 if (vdd_safe > PM8921_CHG_VDDSAFE_MAX)
4164 vdd_safe = PM8921_CHG_VDDSAFE_MAX;
4165
4166 rc = pm_chg_vddsafe_set(chip, vdd_safe);
4167
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004168 if (rc) {
4169 pr_err("Failed to set safe voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004170 chip->max_voltage_mv, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004171 return rc;
4172 }
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004173 rc = pm_chg_vbatdet_set(chip,
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004174 chip->max_voltage_mv
4175 - chip->resume_voltage_delta);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004176 if (rc) {
4177 pr_err("Failed to set vbatdet comprator voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004178 chip->max_voltage_mv - chip->resume_voltage_delta, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004179 return rc;
4180 }
4181
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004182 rc = pm_chg_vddmax_set(chip, chip->max_voltage_mv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004183 if (rc) {
4184 pr_err("Failed to set max voltage to %d rc=%d\n",
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004185 chip->max_voltage_mv, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004186 return rc;
4187 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004188
4189 if (chip->safe_current_ma == 0)
4190 chip->safe_current_ma = SAFE_CURRENT_MA;
4191
4192 rc = pm_chg_ibatsafe_set(chip, chip->safe_current_ma);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004193 if (rc) {
4194 pr_err("Failed to set max voltage to %d rc=%d\n",
4195 SAFE_CURRENT_MA, rc);
4196 return rc;
4197 }
4198
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004199 rc = pm_chg_ibatmax_set(chip, chip->max_bat_chg_current);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004200 if (rc) {
4201 pr_err("Failed to set max current to 400 rc=%d\n", rc);
4202 return rc;
4203 }
4204
4205 rc = pm_chg_iterm_set(chip, chip->term_current);
4206 if (rc) {
4207 pr_err("Failed to set term current to %d rc=%d\n",
4208 chip->term_current, rc);
4209 return rc;
4210 }
4211
4212 /* Disable the ENUM TIMER */
4213 rc = pm_chg_masked_write(chip, PBL_ACCESS2, ENUM_TIMER_STOP_BIT,
4214 ENUM_TIMER_STOP_BIT);
4215 if (rc) {
4216 pr_err("Failed to set enum timer stop rc=%d\n", rc);
4217 return rc;
4218 }
4219
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004220 fcc_uah = pm8921_bms_get_fcc();
4221 if (fcc_uah > 0) {
4222 safety_time = div_s64((s64)fcc_uah * 60,
4223 1000 * MIN_CHARGE_CURRENT_MA);
4224 /* add 20 minutes of buffer time */
4225 safety_time += 20;
4226
4227 /* make sure we do not exceed the maximum programmable time */
4228 if (safety_time > PM8921_CHG_TCHG_MAX)
4229 safety_time = PM8921_CHG_TCHG_MAX;
4230 }
4231
4232 rc = pm_chg_tchg_max_set(chip, safety_time);
4233 if (rc) {
4234 pr_err("Failed to set max time to %d minutes rc=%d\n",
4235 safety_time, rc);
4236 return rc;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004237 }
4238
4239 if (chip->ttrkl_time != 0) {
Abhijeet Dharmapurikare45c3d32011-10-19 19:46:48 -07004240 rc = pm_chg_ttrkl_max_set(chip, chip->ttrkl_time);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004241 if (rc) {
4242 pr_err("Failed to set trkl time to %d minutes rc=%d\n",
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004243 chip->ttrkl_time, rc);
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004244 return rc;
4245 }
4246 }
4247
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07004248 if (chip->vin_min != 0) {
4249 rc = pm_chg_vinmin_set(chip, chip->vin_min);
4250 if (rc) {
4251 pr_err("Failed to set vin min to %d mV rc=%d\n",
4252 chip->vin_min, rc);
4253 return rc;
4254 }
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004255 } else {
4256 chip->vin_min = pm_chg_vinmin_get(chip);
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07004257 }
4258
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004259 rc = pm_chg_disable_wd(chip);
4260 if (rc) {
4261 pr_err("Failed to disable wd rc=%d\n", rc);
4262 return rc;
4263 }
4264
4265 rc = pm_chg_masked_write(chip, CHG_CNTRL_2,
4266 CHG_BAT_TEMP_DIS_BIT, 0);
4267 if (rc) {
4268 pr_err("Failed to enable temp control chg rc=%d\n", rc);
4269 return rc;
4270 }
4271 /* switch to a 3.2Mhz for the buck */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004272 if (pm8xxx_get_revision(chip->dev->parent) >= PM8XXX_REVISION_8038_1p0)
4273 rc = pm_chg_write(chip,
4274 CHG_BUCK_CLOCK_CTRL_8038, 0x15);
4275 else
4276 rc = pm_chg_write(chip,
4277 CHG_BUCK_CLOCK_CTRL, 0x15);
4278
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004279 if (rc) {
4280 pr_err("Failed to switch buck clk rc=%d\n", rc);
4281 return rc;
4282 }
4283
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07004284 if (chip->trkl_voltage != 0) {
4285 rc = pm_chg_vtrkl_low_set(chip, chip->trkl_voltage);
4286 if (rc) {
4287 pr_err("Failed to set trkl voltage to %dmv rc=%d\n",
4288 chip->trkl_voltage, rc);
4289 return rc;
4290 }
4291 }
4292
4293 if (chip->weak_voltage != 0) {
4294 rc = pm_chg_vweak_set(chip, chip->weak_voltage);
4295 if (rc) {
4296 pr_err("Failed to set weak voltage to %dmv rc=%d\n",
4297 chip->weak_voltage, rc);
4298 return rc;
4299 }
4300 }
4301
4302 if (chip->trkl_current != 0) {
4303 rc = pm_chg_itrkl_set(chip, chip->trkl_current);
4304 if (rc) {
4305 pr_err("Failed to set trkl current to %dmA rc=%d\n",
4306 chip->trkl_voltage, rc);
4307 return rc;
4308 }
4309 }
4310
4311 if (chip->weak_current != 0) {
4312 rc = pm_chg_iweak_set(chip, chip->weak_current);
4313 if (rc) {
4314 pr_err("Failed to set weak current to %dmA rc=%d\n",
4315 chip->weak_current, rc);
4316 return rc;
4317 }
4318 }
4319
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07004320 rc = pm_chg_batt_cold_temp_config(chip, chip->cold_thr);
4321 if (rc) {
4322 pr_err("Failed to set cold config %d rc=%d\n",
4323 chip->cold_thr, rc);
4324 }
4325
4326 rc = pm_chg_batt_hot_temp_config(chip, chip->hot_thr);
4327 if (rc) {
4328 pr_err("Failed to set hot config %d rc=%d\n",
4329 chip->hot_thr, rc);
4330 }
4331
Jay Chokshid674a512012-03-15 14:06:04 -07004332 rc = pm_chg_led_src_config(chip, chip->led_src_config);
4333 if (rc) {
4334 pr_err("Failed to set charger LED src config %d rc=%d\n",
4335 chip->led_src_config, rc);
4336 }
4337
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004338 /* Workarounds for die 3.0 */
4339 if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0
4340 && pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8921) {
4341 rc = pm8xxx_readb(chip->dev->parent, PM_SUB_REV, &subrev);
4342 if (rc) {
4343 pr_err("read failed: addr=%03X, rc=%d\n",
4344 PM_SUB_REV, rc);
4345 return rc;
4346 }
4347 /* Check if die 3.0.1 is present */
4348 if (subrev & 0x1)
4349 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xA4);
4350 else
4351 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xAC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004352 }
4353
David Keitel0789fc62012-06-07 17:43:27 -07004354 if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004355 /* Set PM8917 USB_OVP debounce time to 15 ms */
4356 rc = pm_chg_masked_write(chip, USB_OVP_CONTROL,
4357 OVP_DEBOUNCE_TIME, 0x6);
4358 if (rc) {
4359 pr_err("Failed to set USB OVP db rc=%d\n", rc);
4360 return rc;
4361 }
4362
4363 /* Enable isub_fine resolution AICL for PM8917 */
David Keitel38bdd4f2012-04-19 15:39:13 -07004364 chip->iusb_fine_res = true;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004365 if (chip->uvd_voltage_mv) {
David Keitel0789fc62012-06-07 17:43:27 -07004366 rc = pm_chg_uvd_threshold_set(chip,
4367 chip->uvd_voltage_mv);
4368 if (rc) {
4369 pr_err("Failed to set UVD threshold %drc=%d\n",
4370 chip->uvd_voltage_mv, rc);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004371 return rc;
4372 }
David Keitel0789fc62012-06-07 17:43:27 -07004373 }
4374 }
David Keitel38bdd4f2012-04-19 15:39:13 -07004375
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004376 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xD9);
David Keitelb51995e2011-11-18 17:03:31 -08004377
David Keitela3c0d822011-11-03 14:18:52 -07004378 /* Disable EOC FSM processing */
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004379 pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0x91);
David Keitela3c0d822011-11-03 14:18:52 -07004380
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004381 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
4382 VREF_BATT_THERM_FORCE_ON);
4383 if (rc)
4384 pr_err("Failed to Force Vref therm rc=%d\n", rc);
4385
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004386 rc = pm_chg_charge_dis(chip, charging_disabled);
4387 if (rc) {
4388 pr_err("Failed to disable CHG_CHARGE_DIS bit rc=%d\n", rc);
4389 return rc;
4390 }
4391
4392 rc = pm_chg_auto_enable(chip, !charging_disabled);
4393 if (rc) {
4394 pr_err("Failed to enable charging rc=%d\n", rc);
4395 return rc;
4396 }
4397
4398 return 0;
4399}
4400
4401static int get_rt_status(void *data, u64 * val)
4402{
4403 int i = (int)data;
4404 int ret;
4405
4406 /* global irq number is passed in via data */
4407 ret = pm_chg_get_rt_status(the_chip, i);
4408 *val = ret;
4409 return 0;
4410}
4411DEFINE_SIMPLE_ATTRIBUTE(rt_fops, get_rt_status, NULL, "%llu\n");
4412
4413static int get_fsm_status(void *data, u64 * val)
4414{
4415 u8 temp;
4416
4417 temp = pm_chg_get_fsm_state(the_chip);
4418 *val = temp;
4419 return 0;
4420}
4421DEFINE_SIMPLE_ATTRIBUTE(fsm_fops, get_fsm_status, NULL, "%llu\n");
4422
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004423static int get_reg_loop(void *data, u64 * val)
4424{
4425 u8 temp;
4426
4427 if (!the_chip) {
4428 pr_err("%s called before init\n", __func__);
4429 return -EINVAL;
4430 }
4431 temp = pm_chg_get_regulation_loop(the_chip);
4432 *val = temp;
4433 return 0;
4434}
4435DEFINE_SIMPLE_ATTRIBUTE(reg_loop_fops, get_reg_loop, NULL, "0x%02llx\n");
4436
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004437static int get_reg(void *data, u64 * val)
4438{
4439 int addr = (int)data;
4440 int ret;
4441 u8 temp;
4442
4443 ret = pm8xxx_readb(the_chip->dev->parent, addr, &temp);
4444 if (ret) {
4445 pr_err("pm8xxx_readb to %x value =%d errored = %d\n",
4446 addr, temp, ret);
4447 return -EAGAIN;
4448 }
4449 *val = temp;
4450 return 0;
4451}
4452
4453static int set_reg(void *data, u64 val)
4454{
4455 int addr = (int)data;
4456 int ret;
4457 u8 temp;
4458
4459 temp = (u8) val;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004460 ret = pm_chg_write(the_chip, addr, temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004461 if (ret) {
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004462 pr_err("pm_chg_write to %x value =%d errored = %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004463 addr, temp, ret);
4464 return -EAGAIN;
4465 }
4466 return 0;
4467}
4468DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
4469
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004470static int reg_loop;
4471#define MAX_REG_LOOP_CHAR 10
4472static int get_reg_loop_param(char *buf, struct kernel_param *kp)
4473{
4474 u8 temp;
4475
4476 if (!the_chip) {
4477 pr_err("called before init\n");
4478 return -EINVAL;
4479 }
4480 temp = pm_chg_get_regulation_loop(the_chip);
4481 return snprintf(buf, MAX_REG_LOOP_CHAR, "%d", temp);
4482}
4483module_param_call(reg_loop, NULL, get_reg_loop_param,
4484 &reg_loop, 0644);
4485
4486static int max_chg_ma;
4487#define MAX_MA_CHAR 10
4488static int get_max_chg_ma_param(char *buf, struct kernel_param *kp)
4489{
4490 if (!the_chip) {
4491 pr_err("called before init\n");
4492 return -EINVAL;
4493 }
4494 return snprintf(buf, MAX_MA_CHAR, "%d", the_chip->max_bat_chg_current);
4495}
4496module_param_call(max_chg_ma, NULL, get_max_chg_ma_param,
4497 &max_chg_ma, 0644);
4498static int ibatmax_ma;
4499static int set_ibat_max(const char *val, struct kernel_param *kp)
4500{
4501 int rc;
4502
4503 if (!the_chip) {
4504 pr_err("called before init\n");
4505 return -EINVAL;
4506 }
4507
4508 rc = param_set_int(val, kp);
4509 if (rc) {
4510 pr_err("error setting value %d\n", rc);
4511 return rc;
4512 }
4513
4514 if (abs(ibatmax_ma - the_chip->max_bat_chg_current)
4515 <= the_chip->ibatmax_max_adj_ma) {
4516 rc = pm_chg_ibatmax_set(the_chip, ibatmax_ma);
4517 if (rc) {
4518 pr_err("Failed to set ibatmax rc = %d\n", rc);
4519 return rc;
4520 }
4521 }
4522
4523 return 0;
4524}
4525static int get_ibat_max(char *buf, struct kernel_param *kp)
4526{
4527 int ibat_ma;
4528 int rc;
4529
4530 if (!the_chip) {
4531 pr_err("called before init\n");
4532 return -EINVAL;
4533 }
4534
4535 rc = pm_chg_ibatmax_get(the_chip, &ibat_ma);
4536 if (rc) {
4537 pr_err("ibatmax_get error = %d\n", rc);
4538 return rc;
4539 }
4540
4541 return snprintf(buf, MAX_MA_CHAR, "%d", ibat_ma);
4542}
4543module_param_call(ibatmax_ma, set_ibat_max, get_ibat_max,
4544 &ibatmax_ma, 0644);
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004545enum {
4546 BAT_WARM_ZONE,
4547 BAT_COOL_ZONE,
4548};
4549static int get_warm_cool(void *data, u64 * val)
4550{
4551 if (!the_chip) {
4552 pr_err("%s called before init\n", __func__);
4553 return -EINVAL;
4554 }
4555 if ((int)data == BAT_WARM_ZONE)
4556 *val = the_chip->is_bat_warm;
4557 if ((int)data == BAT_COOL_ZONE)
4558 *val = the_chip->is_bat_cool;
4559 return 0;
4560}
4561DEFINE_SIMPLE_ATTRIBUTE(warm_cool_fops, get_warm_cool, NULL, "0x%lld\n");
4562
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004563static void create_debugfs_entries(struct pm8921_chg_chip *chip)
4564{
4565 int i;
4566
4567 chip->dent = debugfs_create_dir("pm8921_chg", NULL);
4568
4569 if (IS_ERR(chip->dent)) {
4570 pr_err("pmic charger couldnt create debugfs dir\n");
4571 return;
4572 }
4573
4574 debugfs_create_file("CHG_CNTRL", 0644, chip->dent,
4575 (void *)CHG_CNTRL, &reg_fops);
4576 debugfs_create_file("CHG_CNTRL_2", 0644, chip->dent,
4577 (void *)CHG_CNTRL_2, &reg_fops);
4578 debugfs_create_file("CHG_CNTRL_3", 0644, chip->dent,
4579 (void *)CHG_CNTRL_3, &reg_fops);
4580 debugfs_create_file("PBL_ACCESS1", 0644, chip->dent,
4581 (void *)PBL_ACCESS1, &reg_fops);
4582 debugfs_create_file("PBL_ACCESS2", 0644, chip->dent,
4583 (void *)PBL_ACCESS2, &reg_fops);
4584 debugfs_create_file("SYS_CONFIG_1", 0644, chip->dent,
4585 (void *)SYS_CONFIG_1, &reg_fops);
4586 debugfs_create_file("SYS_CONFIG_2", 0644, chip->dent,
4587 (void *)SYS_CONFIG_2, &reg_fops);
4588 debugfs_create_file("CHG_VDD_MAX", 0644, chip->dent,
4589 (void *)CHG_VDD_MAX, &reg_fops);
4590 debugfs_create_file("CHG_VDD_SAFE", 0644, chip->dent,
4591 (void *)CHG_VDD_SAFE, &reg_fops);
4592 debugfs_create_file("CHG_VBAT_DET", 0644, chip->dent,
4593 (void *)CHG_VBAT_DET, &reg_fops);
4594 debugfs_create_file("CHG_IBAT_MAX", 0644, chip->dent,
4595 (void *)CHG_IBAT_MAX, &reg_fops);
4596 debugfs_create_file("CHG_IBAT_SAFE", 0644, chip->dent,
4597 (void *)CHG_IBAT_SAFE, &reg_fops);
4598 debugfs_create_file("CHG_VIN_MIN", 0644, chip->dent,
4599 (void *)CHG_VIN_MIN, &reg_fops);
4600 debugfs_create_file("CHG_VTRICKLE", 0644, chip->dent,
4601 (void *)CHG_VTRICKLE, &reg_fops);
4602 debugfs_create_file("CHG_ITRICKLE", 0644, chip->dent,
4603 (void *)CHG_ITRICKLE, &reg_fops);
4604 debugfs_create_file("CHG_ITERM", 0644, chip->dent,
4605 (void *)CHG_ITERM, &reg_fops);
4606 debugfs_create_file("CHG_TCHG_MAX", 0644, chip->dent,
4607 (void *)CHG_TCHG_MAX, &reg_fops);
4608 debugfs_create_file("CHG_TWDOG", 0644, chip->dent,
4609 (void *)CHG_TWDOG, &reg_fops);
4610 debugfs_create_file("CHG_TEMP_THRESH", 0644, chip->dent,
4611 (void *)CHG_TEMP_THRESH, &reg_fops);
4612 debugfs_create_file("CHG_COMP_OVR", 0644, chip->dent,
4613 (void *)CHG_COMP_OVR, &reg_fops);
4614 debugfs_create_file("CHG_BUCK_CTRL_TEST1", 0644, chip->dent,
4615 (void *)CHG_BUCK_CTRL_TEST1, &reg_fops);
4616 debugfs_create_file("CHG_BUCK_CTRL_TEST2", 0644, chip->dent,
4617 (void *)CHG_BUCK_CTRL_TEST2, &reg_fops);
4618 debugfs_create_file("CHG_BUCK_CTRL_TEST3", 0644, chip->dent,
4619 (void *)CHG_BUCK_CTRL_TEST3, &reg_fops);
4620 debugfs_create_file("CHG_TEST", 0644, chip->dent,
4621 (void *)CHG_TEST, &reg_fops);
4622
4623 debugfs_create_file("FSM_STATE", 0644, chip->dent, NULL,
4624 &fsm_fops);
4625
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004626 debugfs_create_file("REGULATION_LOOP_CONTROL", 0644, chip->dent, NULL,
4627 &reg_loop_fops);
4628
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004629 debugfs_create_file("BAT_WARM_ZONE", 0644, chip->dent,
4630 (void *)BAT_WARM_ZONE, &warm_cool_fops);
4631 debugfs_create_file("BAT_COOL_ZONE", 0644, chip->dent,
4632 (void *)BAT_COOL_ZONE, &warm_cool_fops);
4633
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004634 for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
4635 if (chip->pmic_chg_irq[chg_irq_data[i].irq_id])
4636 debugfs_create_file(chg_irq_data[i].name, 0444,
4637 chip->dent,
4638 (void *)chg_irq_data[i].irq_id,
4639 &rt_fops);
4640 }
4641}
4642
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004643static int pm8921_charger_suspend_noirq(struct device *dev)
4644{
4645 int rc;
4646 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4647
4648 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON, 0);
4649 if (rc)
4650 pr_err("Failed to Force Vref therm off rc=%d\n", rc);
Abhijeet Dharmapurikar68f44372013-03-01 18:25:05 -08004651
4652 rc = pm8921_chg_set_lpm(chip, 1);
4653 if (rc)
4654 pr_err("Failed to set lpm rc=%d\n", rc);
4655
4656 pm8921_chg_set_hw_clk_switching(chip);
4657
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004658 return 0;
4659}
4660
4661static int pm8921_charger_resume_noirq(struct device *dev)
4662{
4663 int rc;
4664 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4665
Abhijeet Dharmapurikar68f44372013-03-01 18:25:05 -08004666 rc = pm8921_chg_set_lpm(chip, 0);
4667 if (rc)
4668 pr_err("Failed to set lpm rc=%d\n", rc);
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004669
Abhijeet Dharmapurikarc74a7742013-04-10 11:27:51 -07004670 pm8921_chg_force_19p2mhz_clk(chip);
4671
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004672 rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
4673 VREF_BATT_THERM_FORCE_ON);
4674 if (rc)
4675 pr_err("Failed to Force Vref therm on rc=%d\n", rc);
4676 return 0;
4677}
4678
David Keitelf2226022011-12-13 15:55:50 -08004679static int pm8921_charger_resume(struct device *dev)
4680{
David Keitelf2226022011-12-13 15:55:50 -08004681 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4682
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004683 if (pm8921_chg_is_enabled(chip, LOOP_CHANGE_IRQ)) {
4684 disable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
4685 pm8921_chg_disable_irq(chip, LOOP_CHANGE_IRQ);
4686 }
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004687
4688 if (chip->btc_override && (is_dc_chg_plugged_in(the_chip) ||
4689 is_usb_chg_plugged_in(the_chip)))
4690 schedule_delayed_work(&chip->btc_override_work, 0);
4691
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05304692 schedule_delayed_work(&chip->update_heartbeat_work, 0);
4693
David Keitelf2226022011-12-13 15:55:50 -08004694 return 0;
4695}
4696
4697static int pm8921_charger_suspend(struct device *dev)
4698{
David Keitelf2226022011-12-13 15:55:50 -08004699 struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
4700
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05304701 cancel_delayed_work_sync(&chip->update_heartbeat_work);
4702
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004703 if (chip->btc_override)
4704 cancel_delayed_work_sync(&chip->btc_override_work);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004705
4706 if (is_usb_chg_plugged_in(chip)) {
4707 pm8921_chg_enable_irq(chip, LOOP_CHANGE_IRQ);
4708 enable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
4709 }
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004710
David Keitelf2226022011-12-13 15:55:50 -08004711 return 0;
4712}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004713static int __devinit pm8921_charger_probe(struct platform_device *pdev)
4714{
4715 int rc = 0;
4716 struct pm8921_chg_chip *chip;
4717 const struct pm8921_charger_platform_data *pdata
4718 = pdev->dev.platform_data;
4719
4720 if (!pdata) {
4721 pr_err("missing platform data\n");
4722 return -EINVAL;
4723 }
4724
4725 chip = kzalloc(sizeof(struct pm8921_chg_chip),
4726 GFP_KERNEL);
4727 if (!chip) {
4728 pr_err("Cannot allocate pm_chg_chip\n");
4729 return -ENOMEM;
4730 }
4731
4732 chip->dev = &pdev->dev;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004733 chip->ttrkl_time = pdata->ttrkl_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004734 chip->update_time = pdata->update_time;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004735 chip->max_voltage_mv = pdata->max_voltage;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004736 chip->alarm_low_mv = pdata->alarm_low_mv;
4737 chip->alarm_high_mv = pdata->alarm_high_mv;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -08004738 chip->min_voltage_mv = pdata->min_voltage;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004739 chip->safe_current_ma = pdata->safe_current_ma;
David Keitel0789fc62012-06-07 17:43:27 -07004740 chip->uvd_voltage_mv = pdata->uvd_thresh_voltage;
Abhijeet Dharmapurikard55878e2011-10-27 10:22:24 -07004741 chip->resume_voltage_delta = pdata->resume_voltage_delta;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004742 chip->resume_charge_percent = pdata->resume_charge_percent;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004743 chip->term_current = pdata->term_current;
4744 chip->vbat_channel = pdata->charger_cdata.vbat_channel;
Abhijeet Dharmapurikarb24e2c32011-08-17 17:13:09 -07004745 chip->batt_temp_channel = pdata->charger_cdata.batt_temp_channel;
Abhijeet Dharmapurikarbe6bd8c2011-08-19 12:15:06 -07004746 chip->batt_id_channel = pdata->charger_cdata.batt_id_channel;
4747 chip->batt_id_min = pdata->batt_id_min;
4748 chip->batt_id_max = pdata->batt_id_max;
Abhijeet Dharmapurikarbc38f632012-01-10 09:30:11 -08004749 if (pdata->cool_temp != INT_MIN)
4750 chip->cool_temp_dc = pdata->cool_temp * 10;
4751 else
4752 chip->cool_temp_dc = INT_MIN;
4753
4754 if (pdata->warm_temp != INT_MIN)
4755 chip->warm_temp_dc = pdata->warm_temp * 10;
4756 else
4757 chip->warm_temp_dc = INT_MIN;
4758
Anirudh Ghayale747b7e2013-04-04 12:18:18 +05304759 if (pdata->hysteresis_temp)
4760 chip->hysteresis_temp_dc = pdata->hysteresis_temp * 10;
4761 else
4762 chip->hysteresis_temp_dc = TEMP_HYSTERISIS_DECIDEGC;
4763
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004764 chip->temp_check_period = pdata->temp_check_period;
4765 chip->max_bat_chg_current = pdata->max_bat_chg_current;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004766 /* Assign to corresponding module parameter */
4767 usb_max_current = pdata->usb_max_current;
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004768 chip->cool_bat_chg_current = pdata->cool_bat_chg_current;
4769 chip->warm_bat_chg_current = pdata->warm_bat_chg_current;
4770 chip->cool_bat_voltage = pdata->cool_bat_voltage;
4771 chip->warm_bat_voltage = pdata->warm_bat_voltage;
Abhijeet Dharmapurikar26cef9c2011-08-25 19:16:42 -07004772 chip->trkl_voltage = pdata->trkl_voltage;
4773 chip->weak_voltage = pdata->weak_voltage;
4774 chip->trkl_current = pdata->trkl_current;
4775 chip->weak_current = pdata->weak_current;
Abhijeet Dharmapurikar6fe50a82011-08-25 21:33:14 -07004776 chip->vin_min = pdata->vin_min;
Abhijeet Dharmapurikarad742362011-08-29 19:50:02 -07004777 chip->thermal_mitigation = pdata->thermal_mitigation;
4778 chip->thermal_levels = pdata->thermal_levels;
Anirudh Ghayal0da182f2013-02-22 11:17:19 +05304779 chip->disable_chg_rmvl_wrkarnd = pdata->disable_chg_rmvl_wrkarnd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004780
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07004781 chip->cold_thr = pdata->cold_thr;
4782 chip->hot_thr = pdata->hot_thr;
Abhijeet Dharmapurikar40491ce2011-11-07 11:38:54 -08004783 chip->rconn_mohm = pdata->rconn_mohm;
Jay Chokshid674a512012-03-15 14:06:04 -07004784 chip->led_src_config = pdata->led_src_config;
Xiaozhe Shi7c229e52013-01-22 09:46:45 -08004785 chip->has_dc_supply = pdata->has_dc_supply;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004786 chip->battery_less_hardware = pdata->battery_less_hardware;
4787 chip->btc_override = pdata->btc_override;
4788 if (chip->btc_override) {
4789 chip->btc_delay_ms = pdata->btc_delay_ms;
4790 chip->btc_override_cold_decidegc
4791 = pdata->btc_override_cold_degc * 10;
4792 chip->btc_override_hot_decidegc
4793 = pdata->btc_override_hot_degc * 10;
4794 chip->btc_panic_if_cant_stop_chg
4795 = pdata->btc_panic_if_cant_stop_chg;
4796 }
4797
4798 if (chip->battery_less_hardware)
4799 charging_disabled = 1;
4800
4801 chip->ibatmax_max_adj_ma = find_ibat_max_adj_ma(
4802 chip->max_bat_chg_current);
Abhijeet Dharmapurikar0f024232011-10-03 12:00:15 -07004803
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004804 rc = pm8921_chg_hw_init(chip);
4805 if (rc) {
4806 pr_err("couldn't init hardware rc=%d\n", rc);
4807 goto free_chip;
4808 }
4809
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004810 if (chip->btc_override)
4811 pm8921_chg_btc_override_init(chip);
4812
4813 chip->stop_chg_upon_expiry = pdata->stop_chg_upon_expiry;
Anirudh Ghayal8ecf5ad2013-02-20 09:48:42 +05304814 chip->usb_type = POWER_SUPPLY_TYPE_UNKNOWN;
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004815
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08004816 chip->usb_psy.name = "usb";
4817 chip->usb_psy.type = POWER_SUPPLY_TYPE_USB;
4818 chip->usb_psy.supplied_to = pm_power_supplied_to;
4819 chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
4820 chip->usb_psy.properties = pm_power_props_usb;
4821 chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props_usb);
4822 chip->usb_psy.get_property = pm_power_get_property_usb;
4823 chip->usb_psy.set_property = pm_power_set_property_usb;
4824 chip->usb_psy.property_is_writeable = usb_property_is_writeable;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004825
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08004826 chip->dc_psy.name = "pm8921-dc";
4827 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
4828 chip->dc_psy.supplied_to = pm_power_supplied_to;
4829 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
4830 chip->dc_psy.properties = pm_power_props_mains;
4831 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
4832 chip->dc_psy.get_property = pm_power_get_property_mains;
David Keitel6ed71a52012-01-30 12:42:18 -08004833
Abhijeet Dharmapurikard97d54f2013-01-14 20:48:25 -08004834 chip->batt_psy.name = "battery";
4835 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
4836 chip->batt_psy.properties = msm_batt_power_props;
4837 chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props);
4838 chip->batt_psy.get_property = pm_batt_power_get_property;
4839 chip->batt_psy.external_power_changed = pm_batt_external_power_changed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004840 rc = power_supply_register(chip->dev, &chip->usb_psy);
4841 if (rc < 0) {
4842 pr_err("power_supply_register usb failed rc = %d\n", rc);
Abhijeet Dharmapurikar86eea302011-08-15 13:55:18 -07004843 goto free_chip;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004844 }
4845
David Keitel6ed71a52012-01-30 12:42:18 -08004846 rc = power_supply_register(chip->dev, &chip->dc_psy);
4847 if (rc < 0) {
4848 pr_err("power_supply_register usb failed rc = %d\n", rc);
4849 goto unregister_usb;
4850 }
4851
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004852 rc = power_supply_register(chip->dev, &chip->batt_psy);
4853 if (rc < 0) {
4854 pr_err("power_supply_register batt failed rc = %d\n", rc);
David Keitel6ed71a52012-01-30 12:42:18 -08004855 goto unregister_dc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004856 }
4857
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004858 platform_set_drvdata(pdev, chip);
4859 the_chip = chip;
4860
4861 wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
Amir Samuelovd31ef502011-10-26 14:41:36 +02004862 INIT_DELAYED_WORK(&chip->eoc_work, eoc_worker);
David Keitelacf57c82012-03-07 18:48:50 -08004863 INIT_DELAYED_WORK(&chip->vin_collapse_check_work,
4864 vin_collapse_check_worker);
Abhijeet Dharmapurikarc4599552011-12-22 17:27:56 -08004865 INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
Abhijeet Dharmapurikar98738c52011-09-20 17:04:48 -07004866
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004867 INIT_WORK(&chip->bms_notify.work, bms_notify);
4868 INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
4869
4870 INIT_DELAYED_WORK(&chip->update_heartbeat_work, update_heartbeat);
4871 INIT_DELAYED_WORK(&chip->btc_override_work, btc_override_worker);
4872
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004873 rc = request_irqs(chip, pdev);
4874 if (rc) {
4875 pr_err("couldn't register interrupts rc=%d\n", rc);
4876 goto unregister_batt;
4877 }
4878
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07004879 enable_irq_wake(chip->pmic_chg_irq[USBIN_VALID_IRQ]);
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004880 enable_irq_wake(chip->pmic_chg_irq[DCIN_VALID_IRQ]);
David Keitel64dd3f52011-11-10 14:19:38 -08004881 enable_irq_wake(chip->pmic_chg_irq[VBATDET_LOW_IRQ]);
Abhijeet Dharmapurikar28fd0c62012-01-27 13:28:29 -08004882 enable_irq_wake(chip->pmic_chg_irq[FASTCHG_IRQ]);
Abhijeet Dharmapurikare27d8092011-08-12 17:16:29 -07004883
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004884 create_debugfs_entries(chip);
4885
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004886 /* determine what state the charger is in */
4887 determine_initial_state(chip);
4888
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004889 if (chip->update_time)
Abhijeet Dharmapurikar33fe6fb2011-09-14 16:03:11 -07004890 schedule_delayed_work(&chip->update_heartbeat_work,
4891 round_jiffies_relative(msecs_to_jiffies
4892 (chip->update_time)));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004893 return 0;
4894
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004895unregister_batt:
Abhijeet Dharmapurikar999ee572012-08-28 19:33:49 -07004896 wake_lock_destroy(&chip->eoc_wake_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004897 power_supply_unregister(&chip->batt_psy);
David Keitel6ed71a52012-01-30 12:42:18 -08004898unregister_dc:
4899 power_supply_unregister(&chip->dc_psy);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004900unregister_usb:
4901 power_supply_unregister(&chip->usb_psy);
4902free_chip:
4903 kfree(chip);
4904 return rc;
4905}
4906
4907static int __devexit pm8921_charger_remove(struct platform_device *pdev)
4908{
4909 struct pm8921_chg_chip *chip = platform_get_drvdata(pdev);
4910
4911 free_irqs(chip);
4912 platform_set_drvdata(pdev, NULL);
4913 the_chip = NULL;
4914 kfree(chip);
4915 return 0;
4916}
David Keitelf2226022011-12-13 15:55:50 -08004917static const struct dev_pm_ops pm8921_pm_ops = {
4918 .suspend = pm8921_charger_suspend,
Abhijeet Dharmapurikarccac6952012-01-18 16:35:34 -08004919 .suspend_noirq = pm8921_charger_suspend_noirq,
4920 .resume_noirq = pm8921_charger_resume_noirq,
David Keitelf2226022011-12-13 15:55:50 -08004921 .resume = pm8921_charger_resume,
4922};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004923static struct platform_driver pm8921_charger_driver = {
David Keitelf2226022011-12-13 15:55:50 -08004924 .probe = pm8921_charger_probe,
4925 .remove = __devexit_p(pm8921_charger_remove),
4926 .driver = {
4927 .name = PM8921_CHARGER_DEV_NAME,
4928 .owner = THIS_MODULE,
4929 .pm = &pm8921_pm_ops,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004930 },
4931};
4932
4933static int __init pm8921_charger_init(void)
4934{
4935 return platform_driver_register(&pm8921_charger_driver);
4936}
4937
4938static void __exit pm8921_charger_exit(void)
4939{
4940 platform_driver_unregister(&pm8921_charger_driver);
4941}
4942
4943late_initcall(pm8921_charger_init);
4944module_exit(pm8921_charger_exit);
4945
4946MODULE_LICENSE("GPL v2");
4947MODULE_DESCRIPTION("PMIC8921 charger/battery driver");
4948MODULE_VERSION("1.0");
4949MODULE_ALIAS("platform:" PM8921_CHARGER_DEV_NAME);