blob: 88e00ba21982dcabaa9f00885df930fd91592ba0 [file] [log] [blame]
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
David Keitel80668952012-07-27 14:25:49 -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/slab.h>
17#include <linux/err.h>
18#include <linux/spmi.h>
19#include <linux/of.h>
20#include <linux/of_device.h>
21#include <linux/radix-tree.h>
22#include <linux/interrupt.h>
David Keiteld681cda2012-10-02 15:44:21 -070023#include <linux/delay.h>
David Keitel80668952012-07-27 14:25:49 -070024#include <linux/qpnp/qpnp-adc.h>
25#include <linux/power_supply.h>
26#include <linux/bitops.h>
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -070027#include <linux/ratelimit.h>
David Keitel6dc4ed42013-05-17 11:08:58 -070028#include <linux/regulator/driver.h>
29#include <linux/regulator/of_regulator.h>
30#include <linux/regulator/machine.h>
Xiaozhe Shica289e02013-06-19 13:24:51 -070031#include <linux/of_batterydata.h>
David Keitel80668952012-07-27 14:25:49 -070032
33/* Interrupt offsets */
34#define INT_RT_STS(base) (base + 0x10)
35#define INT_SET_TYPE(base) (base + 0x11)
36#define INT_POLARITY_HIGH(base) (base + 0x12)
37#define INT_POLARITY_LOW(base) (base + 0x13)
38#define INT_LATCHED_CLR(base) (base + 0x14)
39#define INT_EN_SET(base) (base + 0x15)
40#define INT_EN_CLR(base) (base + 0x16)
41#define INT_LATCHED_STS(base) (base + 0x18)
42#define INT_PENDING_STS(base) (base + 0x19)
43#define INT_MID_SEL(base) (base + 0x1A)
44#define INT_PRIORITY(base) (base + 0x1B)
45
46/* Peripheral register offsets */
47#define CHGR_CHG_OPTION 0x08
48#define CHGR_ATC_STATUS 0x0A
49#define CHGR_VBAT_STATUS 0x0B
50#define CHGR_IBAT_BMS 0x0C
51#define CHGR_IBAT_STS 0x0D
52#define CHGR_VDD_MAX 0x40
53#define CHGR_VDD_SAFE 0x41
54#define CHGR_VDD_MAX_STEP 0x42
55#define CHGR_IBAT_MAX 0x44
56#define CHGR_IBAT_SAFE 0x45
57#define CHGR_VIN_MIN 0x47
58#define CHGR_VIN_MIN_STEP 0x48
59#define CHGR_CHG_CTRL 0x49
60#define CHGR_CHG_FAILED 0x4A
61#define CHGR_ATC_CTRL 0x4B
62#define CHGR_ATC_FAILED 0x4C
63#define CHGR_VBAT_TRKL 0x50
64#define CHGR_VBAT_WEAK 0x52
65#define CHGR_IBAT_ATC_A 0x54
66#define CHGR_IBAT_ATC_B 0x55
67#define CHGR_IBAT_TERM_CHGR 0x5B
68#define CHGR_IBAT_TERM_BMS 0x5C
69#define CHGR_VBAT_DET 0x5D
70#define CHGR_TTRKL_MAX 0x5F
71#define CHGR_TTRKL_MAX_EN 0x60
72#define CHGR_TCHG_MAX 0x61
73#define CHGR_CHG_WDOG_TIME 0x62
74#define CHGR_CHG_WDOG_DLY 0x63
75#define CHGR_CHG_WDOG_PET 0x64
76#define CHGR_CHG_WDOG_EN 0x65
David Keitel9201df32013-01-10 18:38:34 -080077#define CHGR_IR_DROP_COMPEN 0x67
David Keitel22ed2232013-01-28 11:04:07 -080078#define CHGR_I_MAX_REG 0x44
David Keiteld681cda2012-10-02 15:44:21 -070079#define CHGR_USB_USB_SUSP 0x47
David Keitel6f865cd2012-11-30 15:04:32 -080080#define CHGR_USB_USB_OTG_CTL 0x48
David Keitel80668952012-07-27 14:25:49 -070081#define CHGR_USB_ENUM_T_STOP 0x4E
82#define CHGR_CHG_TEMP_THRESH 0x66
83#define CHGR_BAT_IF_PRES_STATUS 0x08
David Keiteld681cda2012-10-02 15:44:21 -070084#define CHGR_STATUS 0x09
David Keitel80668952012-07-27 14:25:49 -070085#define CHGR_BAT_IF_VCP 0x42
86#define CHGR_BAT_IF_BATFET_CTRL1 0x90
87#define CHGR_MISC_BOOT_DONE 0x42
David Keitel9fd07382013-05-02 15:37:44 -070088#define CHGR_BUCK_COMPARATOR_OVRIDE_1 0xEB
David Keiteld681cda2012-10-02 15:44:21 -070089#define CHGR_BUCK_COMPARATOR_OVRIDE_3 0xED
David Keitel9201df32013-01-10 18:38:34 -080090#define CHGR_BUCK_BCK_VBAT_REG_MODE 0x74
Sridhar Parasuramae183bd2012-12-21 09:28:46 -080091#define MISC_REVISION2 0x01
David Keitel5c3a7702012-12-20 11:13:21 -080092#define USB_OVP_CTL 0x42
David Keitel344c6972013-04-09 19:28:21 -070093#define USB_CHG_GONE_REV_BST 0xED
94#define BUCK_VCHG_OV 0x77
95#define BUCK_TEST_SMBC_MODES 0xE6
David Keiteld681cda2012-10-02 15:44:21 -070096#define SEC_ACCESS 0xD0
David Keitel85ae4342013-04-16 11:46:00 -070097#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
David Keitel796882d2013-05-14 18:01:11 -070098#define BAT_IF_BPD_CTRL 0x48
David Keitel6dc4ed42013-05-17 11:08:58 -070099#define BOOST_VSET 0x41
100#define BOOST_ENABLE_CONTROL 0x46
David Keitel33f58952013-05-20 16:17:36 -0700101#define COMP_OVR1 0xEA
David Keitel89c17752013-06-28 14:52:48 -0700102#define BAT_IF_BTC_CTRL 0x49
David Keitel33f58952013-05-20 16:17:36 -0700103
David Keitel80668952012-07-27 14:25:49 -0700104#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700105
David Keitelf2170cc2013-02-20 17:49:03 -0800106/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700107#define SMBB_CHGR_SUBTYPE 0x01
108#define SMBB_BUCK_SUBTYPE 0x02
109#define SMBB_BAT_IF_SUBTYPE 0x03
110#define SMBB_USB_CHGPTH_SUBTYPE 0x04
111#define SMBB_DC_CHGPTH_SUBTYPE 0x05
112#define SMBB_BOOST_SUBTYPE 0x06
113#define SMBB_MISC_SUBTYPE 0x07
114
David Keitelf2170cc2013-02-20 17:49:03 -0800115/* SMBB peripheral subtype values */
116#define SMBBP_CHGR_SUBTYPE 0x31
117#define SMBBP_BUCK_SUBTYPE 0x32
118#define SMBBP_BAT_IF_SUBTYPE 0x33
119#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
120#define SMBBP_BOOST_SUBTYPE 0x36
121#define SMBBP_MISC_SUBTYPE 0x37
122
David Keitel46c9f7b2013-04-02 19:54:12 -0700123/* SMBCL peripheral subtype values */
124#define SMBCL_CHGR_SUBTYPE 0x41
125#define SMBCL_BUCK_SUBTYPE 0x42
126#define SMBCL_BAT_IF_SUBTYPE 0x43
127#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
128#define SMBCL_MISC_SUBTYPE 0x47
129
David Keitel80668952012-07-27 14:25:49 -0700130#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
131
David Keitelb80eda82012-10-15 10:49:11 -0700132/* Status bits and masks */
133#define CHGR_BOOT_DONE BIT(7)
134#define CHGR_CHG_EN BIT(7)
135#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800136#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800137#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700138#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700139#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700140#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700141#define REV_BST_DETECTED BIT(0)
142#define BAT_THM_EN BIT(1)
143#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700144#define BOOST_PWR_EN BIT(7)
David Keitelb80eda82012-10-15 10:49:11 -0700145
David Keitel80668952012-07-27 14:25:49 -0700146/* Interrupt definitions */
147/* smbb_chg_interrupts */
148#define CHG_DONE_IRQ BIT(7)
149#define CHG_FAILED_IRQ BIT(6)
150#define FAST_CHG_ON_IRQ BIT(5)
151#define TRKL_CHG_ON_IRQ BIT(4)
152#define STATE_CHANGE_ON_IR BIT(3)
153#define CHGWDDOG_IRQ BIT(2)
154#define VBAT_DET_HI_IRQ BIT(1)
155#define VBAT_DET_LOW_IRQ BIT(0)
156
157/* smbb_buck_interrupts */
158#define VDD_LOOP_IRQ BIT(6)
159#define IBAT_LOOP_IRQ BIT(5)
160#define ICHG_LOOP_IRQ BIT(4)
161#define VCHG_LOOP_IRQ BIT(3)
162#define OVERTEMP_IRQ BIT(2)
163#define VREF_OV_IRQ BIT(1)
164#define VBAT_OV_IRQ BIT(0)
165
166/* smbb_bat_if_interrupts */
167#define PSI_IRQ BIT(4)
168#define VCP_ON_IRQ BIT(3)
169#define BAT_FET_ON_IRQ BIT(2)
170#define BAT_TEMP_OK_IRQ BIT(1)
171#define BATT_PRES_IRQ BIT(0)
172
173/* smbb_usb_interrupts */
174#define CHG_GONE_IRQ BIT(2)
175#define USBIN_VALID_IRQ BIT(1)
176#define COARSE_DET_USB_IRQ BIT(0)
177
178/* smbb_dc_interrupts */
179#define DCIN_VALID_IRQ BIT(1)
180#define COARSE_DET_DC_IRQ BIT(0)
181
182/* smbb_boost_interrupts */
183#define LIMIT_ERROR_IRQ BIT(1)
184#define BOOST_PWR_OK_IRQ BIT(0)
185
186/* smbb_misc_interrupts */
187#define TFTWDOG_IRQ BIT(0)
188
David Keitelfe51cb92013-04-02 19:42:58 -0700189/* SMBB types */
190#define SMBB BIT(1)
191#define SMBBP BIT(2)
192#define SMBCL BIT(3)
193
David Keiteld681cda2012-10-02 15:44:21 -0700194/* Workaround flags */
195#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700196#define BOOST_FLASH_WA BIT(1)
David Keiteld681cda2012-10-02 15:44:21 -0700197
David Keitel47185a62013-05-15 18:54:10 -0700198struct qpnp_chg_irq {
199 unsigned int irq;
200 unsigned long disabled;
201};
202
David Keitel6dc4ed42013-05-17 11:08:58 -0700203struct qpnp_chg_regulator {
204 struct regulator_desc rdesc;
205 struct regulator_dev *rdev;
206};
207
David Keitel80668952012-07-27 14:25:49 -0700208/**
209 * struct qpnp_chg_chip - device information
210 * @dev: device pointer to access the parent
211 * @spmi: spmi pointer to access spmi information
212 * @chgr_base: charger peripheral base address
213 * @buck_base: buck peripheral base address
214 * @bat_if_base: battery interface peripheral base address
215 * @usb_chgpth_base: USB charge path peripheral base address
216 * @dc_chgpth_base: DC charge path peripheral base address
217 * @boost_base: boost peripheral base address
218 * @misc_base: misc peripheral base address
219 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800220 * @bat_is_cool: indicates that battery is cool
221 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700222 * @chg_done: indicates that charging is completed
223 * @usb_present: present status of usb
224 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800225 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800226 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700227 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700228 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800229 * @min_voltage_mv: min battery voltage before turning the FET on
David Keitel454ee842013-03-08 16:19:11 -0800230 * @max_bat_chg_current: maximum battery charge current in mA
231 * @warm_bat_chg_ma: warm battery maximum charge current in mA
232 * @cool_bat_chg_ma: cool battery maximum charge current in mA
233 * @warm_bat_mv: warm temperature battery target voltage
234 * @cool_bat_mv: cool temperature battery target voltage
235 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700236 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800237 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800238 * @maxinput_usb_ma: Maximum Input current USB
239 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700240 * @hot_batt_p Hot battery threshold setting
241 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700242 * @warm_bat_decidegc Warm battery temperature in degree Celsius
243 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700244 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700245 * @type: SMBB type
246 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800247 * @thermal_levels amount of thermal mitigation levels
248 * @thermal_mitigation thermal mitigation level values
249 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700250 * @dc_psy power supply to export information to userspace
251 * @usb_psy power supply to export information to userspace
252 * @bms_psy power supply to export information to userspace
253 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700254 * @flags: flags to activate specific workarounds
255 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700256 *
257 */
258struct qpnp_chg_chip {
259 struct device *dev;
260 struct spmi_device *spmi;
261 u16 chgr_base;
262 u16 buck_base;
263 u16 bat_if_base;
264 u16 usb_chgpth_base;
265 u16 dc_chgpth_base;
266 u16 boost_base;
267 u16 misc_base;
268 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700269 struct qpnp_chg_irq usbin_valid;
270 struct qpnp_chg_irq dcin_valid;
271 struct qpnp_chg_irq chg_gone;
272 struct qpnp_chg_irq chg_fastchg;
273 struct qpnp_chg_irq chg_trklchg;
274 struct qpnp_chg_irq chg_failed;
275 struct qpnp_chg_irq chg_vbatdet_lo;
276 struct qpnp_chg_irq batt_pres;
David Keitel337bd862013-07-15 21:42:58 -0700277 struct qpnp_chg_irq vchg_loop;
David Keitel454ee842013-03-08 16:19:11 -0800278 bool bat_is_cool;
279 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700280 bool chg_done;
281 bool usb_present;
282 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800283 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700284 bool charging_disabled;
David Keitel89c17752013-06-28 14:52:48 -0700285 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800286 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700287 bool duty_cycle_100p;
David Keitel796882d2013-05-14 18:01:11 -0700288 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700289 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800290 unsigned int warm_bat_chg_ma;
291 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700292 unsigned int safe_voltage_mv;
293 unsigned int max_voltage_mv;
294 unsigned int min_voltage_mv;
David Keitelfd305ee2013-07-19 20:19:06 -0700295 int prev_usb_max_ma;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700296 int set_vddmax_mv;
297 int delta_vddmax_mv;
David Keitel454ee842013-03-08 16:19:11 -0800298 unsigned int warm_bat_mv;
299 unsigned int cool_bat_mv;
300 unsigned int resume_delta_mv;
David Keitel9fd07382013-05-02 15:37:44 -0700301 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700302 int soc_resume_limit;
303 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800304 unsigned int maxinput_usb_ma;
305 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700306 unsigned int hot_batt_p;
307 unsigned int cold_batt_p;
David Keitel0c1a4532013-03-21 16:39:06 -0700308 unsigned int warm_bat_decidegc;
309 unsigned int cool_bat_decidegc;
David Keitel5d44fa52012-12-03 16:37:31 -0800310 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700311 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700312 unsigned int type;
313 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800314 unsigned int thermal_levels;
315 unsigned int therm_lvl_sel;
316 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700317 struct power_supply dc_psy;
318 struct power_supply *usb_psy;
319 struct power_supply *bms_psy;
320 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700321 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800322 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700323 struct work_struct adc_measure_work;
David Keitel344c6972013-04-09 19:28:21 -0700324 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700325 struct delayed_work eoc_work;
326 struct wake_lock eoc_wake_lock;
David Keitel6dc4ed42013-05-17 11:08:58 -0700327 struct qpnp_chg_regulator otg_vreg;
328 struct qpnp_chg_regulator boost_vreg;
David Keitel80668952012-07-27 14:25:49 -0700329};
330
David Keitel47185a62013-05-15 18:54:10 -0700331
David Keitel80668952012-07-27 14:25:49 -0700332static struct of_device_id qpnp_charger_match_table[] = {
333 { .compatible = QPNP_CHARGER_DEV_NAME, },
334 {}
335};
336
David Keitel0ef282b2013-05-29 16:04:57 -0700337enum bpd_type {
338 BPD_TYPE_BAT_ID,
339 BPD_TYPE_BAT_THM,
340 BPD_TYPE_BAT_THM_BAT_ID,
341};
David Keitel796882d2013-05-14 18:01:11 -0700342
David Keitel0ef282b2013-05-29 16:04:57 -0700343static const char * const bpd_label[] = {
344 [BPD_TYPE_BAT_ID] = "bpd_id",
345 [BPD_TYPE_BAT_THM] = "bpd_thm",
346 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700347};
348
David Keitel89c17752013-06-28 14:52:48 -0700349enum btc_type {
350 HOT_THD_25_PCT = 25,
351 HOT_THD_35_PCT = 35,
352 COLD_THD_70_PCT = 70,
353 COLD_THD_80_PCT = 80,
354};
355
356static u8 btc_value[] = {
357 [HOT_THD_25_PCT] = 0x0,
358 [HOT_THD_35_PCT] = BIT(0),
359 [COLD_THD_70_PCT] = 0x0,
360 [COLD_THD_80_PCT] = BIT(1),
361};
362
363 static inline int
David Keitel796882d2013-05-14 18:01:11 -0700364get_bpd(const char *name)
365{
366 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700367 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
368 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700369 return i;
370 }
371 return -EINVAL;
372}
373
David Keitel80668952012-07-27 14:25:49 -0700374static int
375qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
376 u16 base, int count)
377{
David Keitel39093572013-06-05 15:32:30 -0700378 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700379 struct spmi_device *spmi = chip->spmi;
380
David Keitel39093572013-06-05 15:32:30 -0700381 if (base == 0) {
382 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
383 base, spmi->sid, rc);
384 return -EINVAL;
385 }
386
387 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700388 if (rc) {
389 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
390 spmi->sid, rc);
391 return rc;
392 }
393 return 0;
394}
395
396static int
397qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
398 u16 base, int count)
399{
David Keitel39093572013-06-05 15:32:30 -0700400 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700401 struct spmi_device *spmi = chip->spmi;
402
David Keitel39093572013-06-05 15:32:30 -0700403 if (base == 0) {
404 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
405 base, spmi->sid, rc);
406 return -EINVAL;
407 }
408
409 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700410 if (rc) {
411 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
412 base, spmi->sid, rc);
413 return rc;
414 }
415
416 return 0;
417}
418
419static int
420qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
421 u8 mask, u8 val, int count)
422{
423 int rc;
424 u8 reg;
425
426 rc = qpnp_chg_read(chip, &reg, base, count);
427 if (rc) {
428 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
429 return rc;
430 }
431 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
432
433 reg &= ~mask;
434 reg |= val & mask;
435
436 pr_debug("Writing 0x%x\n", reg);
437
438 rc = qpnp_chg_write(chip, &reg, base, count);
439 if (rc) {
440 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
441 return rc;
442 }
443
444 return 0;
445}
446
David Keitel47185a62013-05-15 18:54:10 -0700447static void
448qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
449{
450 if (__test_and_clear_bit(0, &irq->disabled)) {
451 pr_debug("number = %d\n", irq->irq);
452 enable_irq(irq->irq);
453 }
454}
455
456static void
457qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
458{
459 if (!__test_and_set_bit(0, &irq->disabled)) {
460 pr_debug("number = %d\n", irq->irq);
461 disable_irq_nosync(irq->irq);
462 }
463}
464
David Keitel6f865cd2012-11-30 15:04:32 -0800465#define USB_OTG_EN_BIT BIT(0)
466static int
467qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
468{
469 u8 usb_otg_en;
470 int rc;
471
472 rc = qpnp_chg_read(chip, &usb_otg_en,
473 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
474 1);
475
476 if (rc) {
477 pr_err("spmi read failed: addr=%03X, rc=%d\n",
478 chip->usb_chgpth_base + CHGR_STATUS, rc);
479 return rc;
480 }
481 pr_debug("usb otg en 0x%x\n", usb_otg_en);
482
483 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
484}
485
David Keitel42ae0aa2013-03-08 16:20:10 -0800486static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700487qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
488{
489 u8 boost_en_ctl;
490 int rc;
491
492 rc = qpnp_chg_read(chip, &boost_en_ctl,
493 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
494 if (rc) {
495 pr_err("spmi read failed: addr=%03X, rc=%d\n",
496 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
497 return rc;
498 }
499
500 pr_debug("boost en 0x%x\n", boost_en_ctl);
501
502 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
503}
504
505static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800506qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
507{
508 u8 batt_pres_rt_sts;
509 int rc;
510
511 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
512 INT_RT_STS(chip->bat_if_base), 1);
513 if (rc) {
514 pr_err("spmi read failed: addr=%03X, rc=%d\n",
515 INT_RT_STS(chip->bat_if_base), rc);
516 return rc;
517 }
518
519 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
520}
521
David Keiteld681cda2012-10-02 15:44:21 -0700522#define USB_VALID_BIT BIT(7)
David Keitel80668952012-07-27 14:25:49 -0700523static int
524qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
525{
526 u8 usbin_valid_rt_sts;
527 int rc;
528
529 rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
David Keiteld681cda2012-10-02 15:44:21 -0700530 chip->usb_chgpth_base + CHGR_STATUS , 1);
David Keitel80668952012-07-27 14:25:49 -0700531
532 if (rc) {
533 pr_err("spmi read failed: addr=%03X, rc=%d\n",
David Keiteld681cda2012-10-02 15:44:21 -0700534 chip->usb_chgpth_base + CHGR_STATUS, rc);
David Keitel80668952012-07-27 14:25:49 -0700535 return rc;
536 }
537 pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
538
David Keiteld681cda2012-10-02 15:44:21 -0700539 return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700540}
541
542static int
543qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
544{
545 u8 dcin_valid_rt_sts;
546 int rc;
547
David Keitelf2170cc2013-02-20 17:49:03 -0800548 if (!chip->dc_chgpth_base)
549 return 0;
550
David Keitel80668952012-07-27 14:25:49 -0700551 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
552 INT_RT_STS(chip->dc_chgpth_base), 1);
553 if (rc) {
554 pr_err("spmi read failed: addr=%03X, rc=%d\n",
555 INT_RT_STS(chip->dc_chgpth_base), rc);
556 return rc;
557 }
558
559 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
560}
561
David Keitel22ed2232013-01-28 11:04:07 -0800562#define QPNP_CHG_I_MAX_MIN_100 100
563#define QPNP_CHG_I_MAX_MIN_150 150
564#define QPNP_CHG_I_MAX_MIN_MA 200
565#define QPNP_CHG_I_MAX_MAX_MA 2500
566#define QPNP_CHG_I_MAXSTEP_MA 100
567static int
568qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
569{
570 int rc = 0;
571 u8 dc = 0;
572
573 if (mA < QPNP_CHG_I_MAX_MIN_100
574 || mA > QPNP_CHG_I_MAX_MAX_MA) {
575 pr_err("bad mA=%d asked to set\n", mA);
576 return -EINVAL;
577 }
578
579 if (mA == QPNP_CHG_I_MAX_MIN_100) {
580 dc = 0x00;
581 pr_debug("current=%d setting %02x\n", mA, dc);
582 return qpnp_chg_write(chip, &dc,
583 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
584 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
585 dc = 0x01;
586 pr_debug("current=%d setting %02x\n", mA, dc);
587 return qpnp_chg_write(chip, &dc,
588 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
589 }
590
591 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
592
593 pr_debug("current=%d setting 0x%x\n", mA, dc);
594 rc = qpnp_chg_write(chip, &dc,
595 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
596
597 return rc;
598}
599
David Keitel80668952012-07-27 14:25:49 -0700600static int
601qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
602{
David Keiteld681cda2012-10-02 15:44:21 -0700603 int rc = 0;
604 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700605
David Keitel22ed2232013-01-28 11:04:07 -0800606 if (mA < QPNP_CHG_I_MAX_MIN_100
607 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700608 pr_err("bad mA=%d asked to set\n", mA);
609 return -EINVAL;
610 }
611
David Keitel22ed2232013-01-28 11:04:07 -0800612 if (mA == QPNP_CHG_I_MAX_MIN_100) {
613 usb_reg = 0x00;
614 pr_debug("current=%d setting %02x\n", mA, usb_reg);
615 return qpnp_chg_write(chip, &usb_reg,
616 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
617 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
618 usb_reg = 0x01;
619 pr_debug("current=%d setting %02x\n", mA, usb_reg);
620 return qpnp_chg_write(chip, &usb_reg,
621 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
622 }
623
624 /* Impose input current limit */
625 if (chip->maxinput_usb_ma)
626 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
627
628 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -0700629
David Keiteld681cda2012-10-02 15:44:21 -0700630 if (chip->flags & CHG_FLAGS_VCP_WA) {
631 temp = 0xA5;
632 rc = qpnp_chg_write(chip, &temp,
633 chip->buck_base + SEC_ACCESS, 1);
634 rc = qpnp_chg_masked_write(chip,
635 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
636 0x0C, 0x0C, 1);
637 }
638
David Keitel80668952012-07-27 14:25:49 -0700639 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -0700640 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -0800641 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -0700642
643 if (chip->flags & CHG_FLAGS_VCP_WA) {
644 temp = 0xA5;
645 udelay(200);
646 rc = qpnp_chg_write(chip, &temp,
647 chip->buck_base + SEC_ACCESS, 1);
648 rc = qpnp_chg_masked_write(chip,
649 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
650 0x0C, 0x00, 1);
651 }
652
653 return rc;
654}
655
David Keitel337bd862013-07-15 21:42:58 -0700656#define QPNP_CHG_VINMIN_MIN_MV 4200
657#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
658#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
659#define QPNP_CHG_VINMIN_MAX_MV 9600
660#define QPNP_CHG_VINMIN_STEP_MV 50
661#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
662#define QPNP_CHG_VINMIN_MASK 0x1F
663#define QPNP_CHG_VINMIN_MIN_VAL 0x10
664static int
665qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
666{
667 u8 temp;
668
669 if (voltage < QPNP_CHG_VINMIN_MIN_MV
670 || voltage > QPNP_CHG_VINMIN_MAX_MV) {
671 pr_err("bad mV=%d asked to set\n", voltage);
672 return -EINVAL;
673 }
674 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
675 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
676 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
677 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
678 } else {
679 temp = QPNP_CHG_VINMIN_MIN_VAL;
680 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
681 / QPNP_CHG_VINMIN_STEP_MV;
682 }
683
684 pr_debug("voltage=%d setting %02x\n", voltage, temp);
685 return qpnp_chg_masked_write(chip,
686 chip->chgr_base + CHGR_VIN_MIN,
687 QPNP_CHG_VINMIN_MASK, temp, 1);
688}
689
690static int
691qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
692{
693 int rc, vin_min_mv;
694 u8 vin_min;
695
696 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
697 if (rc) {
698 pr_err("failed to read VIN_MIN rc=%d\n", rc);
699 return 0;
700 }
701
702 if (vin_min == 0)
703 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
704 else if (vin_min > QPNP_CHG_VINMIN_HIGH_MIN_VAL)
705 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
706 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
707 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
708 else
709 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
710 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
711 * QPNP_CHG_VINMIN_STEP_MV;
712 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
713
714 return vin_min_mv;
715}
716
717static int
718qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
719{
720 int rc, iusbmax_ma;
721 u8 iusbmax;
722
723 rc = qpnp_chg_read(chip, &iusbmax,
724 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
725 if (rc) {
726 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
727 return 0;
728 }
729
730 if (iusbmax == 0)
731 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
732 else if (iusbmax == 0x01)
733 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
734 else
735 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
736
737 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
738
739 return iusbmax_ma;
740}
741
David Keiteld681cda2012-10-02 15:44:21 -0700742#define USB_SUSPEND_BIT BIT(0)
743static int
744qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
745{
746 return qpnp_chg_masked_write(chip,
747 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
748 USB_SUSPEND_BIT,
749 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -0700750}
751
David Keitel344c6972013-04-09 19:28:21 -0700752static int
753qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
754{
755 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
756 CHGR_CHG_EN,
757 enable ? CHGR_CHG_EN : 0, 1);
758}
759
760static int
761qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
762{
763 /* Don't run on battery for batteryless hardware */
764 if (chip->use_default_batt_values)
765 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -0700766 /* Don't force on battery if battery is not present */
767 if (!qpnp_chg_is_batt_present(chip))
768 return 0;
David Keitel344c6972013-04-09 19:28:21 -0700769
770 /* This bit forces the charger to run off of the battery rather
771 * than a connected charger */
772 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
773 CHGR_ON_BAT_FORCE_BIT,
774 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
775}
776
David Keitel8b68d2d2013-05-14 23:36:51 -0700777#define BUCK_DUTY_MASK_100P 0x30
778static int
779qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
780{
781 int rc;
782
783 pr_debug("enable: %d\n", enable);
784
785 rc = qpnp_chg_masked_write(chip,
786 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
787 if (rc) {
788 pr_debug("failed to write sec access rc=%d\n", rc);
789 return rc;
790 }
791
792 rc = qpnp_chg_masked_write(chip,
793 chip->buck_base + BUCK_TEST_SMBC_MODES,
794 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
795 if (rc) {
796 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
797 return rc;
798 }
799
800 return rc;
801}
802
David Keitel9fd07382013-05-02 15:37:44 -0700803#define COMPATATOR_OVERRIDE_0 0x80
804static int
805qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
806{
807 int rc;
808
809 pr_debug("toggle: %d\n", enable);
810
811 rc = qpnp_chg_masked_write(chip,
812 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
813 if (rc) {
814 pr_debug("failed to write sec access rc=%d\n", rc);
815 return rc;
816 }
817
818 rc = qpnp_chg_masked_write(chip,
819 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
820 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
821 if (rc) {
822 pr_debug("failed to toggle chg done override rc=%d\n", rc);
823 return rc;
824 }
825
826 return rc;
827}
828
829#define QPNP_CHG_VBATDET_MIN_MV 3240
830#define QPNP_CHG_VBATDET_MAX_MV 5780
831#define QPNP_CHG_VBATDET_STEP_MV 20
832static int
833qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
834{
835 u8 temp;
836
837 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
838 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
839 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
840 return -EINVAL;
841 }
842 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
843 / QPNP_CHG_VBATDET_STEP_MV;
844
845 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
846 return qpnp_chg_write(chip, &temp,
847 chip->chgr_base + CHGR_VBAT_DET, 1);
848}
849
David Keitel344c6972013-04-09 19:28:21 -0700850static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700851qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
852{
853 if (chip->bat_is_cool)
854 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
855 - chip->resume_delta_mv);
856 else if (chip->bat_is_warm)
857 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
858 - chip->resume_delta_mv);
859 else if (chip->resuming_charging)
860 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
861 + chip->resume_delta_mv);
862 else
863 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
864 - chip->resume_delta_mv);
865}
866
867static void
David Keitel344c6972013-04-09 19:28:21 -0700868qpnp_arb_stop_work(struct work_struct *work)
869{
870 struct delayed_work *dwork = to_delayed_work(work);
871 struct qpnp_chg_chip *chip = container_of(dwork,
872 struct qpnp_chg_chip, arb_stop_work);
873
David Keitel9fd07382013-05-02 15:37:44 -0700874 if (!chip->chg_done)
875 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -0700876 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
877}
878
879static void
880qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -0700881{
882 struct qpnp_chg_chip *chip = container_of(work,
883 struct qpnp_chg_chip, adc_measure_work);
884
885 if (qpnp_adc_tm_channel_measure(&chip->adc_param))
886 pr_err("request ADC error\n");
887}
888
David Keitel337bd862013-07-15 21:42:58 -0700889static irqreturn_t
890qpnp_chg_buck_vchg_loop_irq_handler(int irq, void *_chip)
891{
892 struct qpnp_chg_chip *chip = _chip;
893
894 if (chip->bat_if_base)
895 power_supply_changed(&chip->batt_psy);
896
897 return IRQ_HANDLED;
898}
899
David Keitel9fd07382013-05-02 15:37:44 -0700900#define EOC_CHECK_PERIOD_MS 10000
901static irqreturn_t
902qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
903{
904 struct qpnp_chg_chip *chip = _chip;
905 u8 chg_sts = 0;
906 int rc;
907
908 pr_debug("vbatdet-lo triggered\n");
909
910 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
911 if (rc)
912 pr_err("failed to read chg_sts rc=%d\n", rc);
913
914 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
915 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
916 schedule_delayed_work(&chip->eoc_work,
917 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
918 wake_lock(&chip->eoc_wake_lock);
David Keitel47185a62013-05-15 18:54:10 -0700919 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -0700920 } else {
921 qpnp_chg_charge_en(chip, !chip->charging_disabled);
922 }
923
924 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -0700925 if (chip->dc_chgpth_base)
926 power_supply_changed(&chip->dc_psy);
927 if (chip->bat_if_base)
928 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700929 return IRQ_HANDLED;
930}
931
David Keitel344c6972013-04-09 19:28:21 -0700932#define ARB_STOP_WORK_MS 1000
933static irqreturn_t
934qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
935{
936 struct qpnp_chg_chip *chip = _chip;
937
938 pr_debug("chg_gone triggered\n");
939 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
940 qpnp_chg_charge_en(chip, 0);
David Keitel9fd07382013-05-02 15:37:44 -0700941 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -0700942 schedule_delayed_work(&chip->arb_stop_work,
943 msecs_to_jiffies(ARB_STOP_WORK_MS));
944 }
945
946 return IRQ_HANDLED;
947}
948
David Keitel80668952012-07-27 14:25:49 -0700949#define ENUM_T_STOP_BIT BIT(0)
950static irqreturn_t
951qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
952{
953 struct qpnp_chg_chip *chip = _chip;
David Keitel6f865cd2012-11-30 15:04:32 -0800954 int usb_present, host_mode;
David Keitel80668952012-07-27 14:25:49 -0700955
956 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -0800957 host_mode = qpnp_chg_is_otg_en_set(chip);
958 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
959 usb_present, host_mode);
960
961 /* In host mode notifications cmoe from USB supply */
962 if (host_mode)
963 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -0700964
965 if (chip->usb_present ^ usb_present) {
966 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -0700967 if (!usb_present) {
David Keitel344c6972013-04-09 19:28:21 -0700968 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel9fd07382013-05-02 15:37:44 -0700969 chip->chg_done = false;
David Keitelfd305ee2013-07-19 20:19:06 -0700970 chip->prev_usb_max_ma = -EINVAL;
David Keitel9fd07382013-05-02 15:37:44 -0700971 } else {
972 schedule_delayed_work(&chip->eoc_work,
973 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
974 }
David Keitel344c6972013-04-09 19:28:21 -0700975
David Keitel9fd07382013-05-02 15:37:44 -0700976 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel80668952012-07-27 14:25:49 -0700977 }
978
979 return IRQ_HANDLED;
980}
981
David Keitel7450dcd2013-01-29 18:41:41 -0800982static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -0800983qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
984{
985 struct qpnp_chg_chip *chip = _chip;
986 int batt_present;
987
988 batt_present = qpnp_chg_is_batt_present(chip);
989 pr_debug("batt-pres triggered: %d\n", batt_present);
990
991 if (chip->batt_present ^ batt_present) {
992 chip->batt_present = batt_present;
993 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700994 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -0700995
996 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
997 && batt_present) {
David Keitel79f4c932013-04-03 16:08:39 -0700998 schedule_work(&chip->adc_measure_work);
David Keitel0c1a4532013-03-21 16:39:06 -0700999 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001000 }
1001
1002 return IRQ_HANDLED;
1003}
1004
1005static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001006qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1007{
1008 struct qpnp_chg_chip *chip = _chip;
1009 int dc_present;
1010
1011 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1012 pr_debug("dcin-valid triggered: %d\n", dc_present);
1013
1014 if (chip->dc_present ^ dc_present) {
1015 chip->dc_present = dc_present;
David Keitel9fd07382013-05-02 15:37:44 -07001016 if (!dc_present)
1017 chip->chg_done = false;
1018 else
1019 schedule_delayed_work(&chip->eoc_work,
1020 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel7450dcd2013-01-29 18:41:41 -08001021 power_supply_changed(&chip->dc_psy);
David Keitel9fd07382013-05-02 15:37:44 -07001022 power_supply_changed(&chip->batt_psy);
David Keitel7450dcd2013-01-29 18:41:41 -08001023 }
1024
1025 return IRQ_HANDLED;
1026}
1027
David Keitel80668952012-07-27 14:25:49 -07001028#define CHGR_CHG_FAILED_BIT BIT(7)
1029static irqreturn_t
1030qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1031{
1032 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001033 int rc;
David Keitel80668952012-07-27 14:25:49 -07001034
David Keitel9fd07382013-05-02 15:37:44 -07001035 pr_debug("chg_failed triggered\n");
1036
David Keitel80668952012-07-27 14:25:49 -07001037 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001038 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001039 CHGR_CHG_FAILED_BIT,
1040 CHGR_CHG_FAILED_BIT, 1);
1041 if (rc)
1042 pr_err("Failed to write chg_fail clear bit!\n");
1043
David Keiteldbcef092013-05-14 14:48:30 -07001044 if (chip->bat_if_base)
1045 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -07001046 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -07001047 if (chip->dc_chgpth_base)
1048 power_supply_changed(&chip->dc_psy);
David Keitel80668952012-07-27 14:25:49 -07001049 return IRQ_HANDLED;
1050}
1051
1052static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001053qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
1054{
1055 struct qpnp_chg_chip *chip = _chip;
1056
1057 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001058
1059 chip->chg_done = false;
David Keiteldbcef092013-05-14 14:48:30 -07001060 if (chip->bat_if_base)
1061 power_supply_changed(&chip->batt_psy);
David Keitel42ae0aa2013-03-08 16:20:10 -08001062
1063 return IRQ_HANDLED;
1064}
1065
1066static irqreturn_t
1067qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
1068{
1069 struct qpnp_chg_chip *chip = _chip;
David Keitel337bd862013-07-15 21:42:58 -07001070 u8 chgr_sts;
1071 int rc;
1072
1073 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
1074 if (rc)
1075 pr_err("failed to read interrupt sts %d\n", rc);
David Keitel42ae0aa2013-03-08 16:20:10 -08001076
1077 pr_debug("FAST_CHG IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001078 chip->chg_done = false;
David Keiteldbcef092013-05-14 14:48:30 -07001079 if (chip->bat_if_base)
1080 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -07001081 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -07001082 if (chip->dc_chgpth_base)
1083 power_supply_changed(&chip->dc_psy);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001084 if (chip->resuming_charging) {
1085 chip->resuming_charging = false;
1086 qpnp_chg_set_appropriate_vbatdet(chip);
1087 }
David Keitel337bd862013-07-15 21:42:58 -07001088
David Keitel47185a62013-05-15 18:54:10 -07001089 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel337bd862013-07-15 21:42:58 -07001090 if (chgr_sts & FAST_CHG_ON_IRQ)
1091 qpnp_chg_enable_irq(&chip->vchg_loop);
1092 else
1093 qpnp_chg_disable_irq(&chip->vchg_loop);
David Keitel42ae0aa2013-03-08 16:20:10 -08001094
1095 return IRQ_HANDLED;
1096}
1097
David Keitel03ee6b52012-10-22 12:25:19 -07001098static int
David Keitel432e1232013-06-05 16:10:18 -07001099qpnp_dc_property_is_writeable(struct power_supply *psy,
1100 enum power_supply_property psp)
1101{
1102 switch (psp) {
1103 case POWER_SUPPLY_PROP_CURRENT_MAX:
1104 return 1;
1105 default:
1106 break;
1107 }
1108
1109 return 0;
1110}
1111
1112static int
David Keitel03ee6b52012-10-22 12:25:19 -07001113qpnp_batt_property_is_writeable(struct power_supply *psy,
1114 enum power_supply_property psp)
1115{
1116 switch (psp) {
1117 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08001118 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07001119 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
1120 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitel03ee6b52012-10-22 12:25:19 -07001121 return 1;
1122 default:
1123 break;
1124 }
1125
1126 return 0;
1127}
1128
David Keitel6f865cd2012-11-30 15:04:32 -08001129static int
David Keitelbe208252013-01-31 14:49:25 -08001130qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
1131{
1132 int rc;
1133
1134 if (chip->charging_disabled && enable) {
1135 pr_debug("Charging disabled\n");
1136 return 0;
1137 }
1138
1139 rc = qpnp_chg_charge_en(chip, enable);
1140 if (rc) {
1141 pr_err("Failed to control charging %d\n", rc);
1142 return rc;
1143 }
1144
1145 rc = qpnp_chg_force_run_on_batt(chip, !enable);
1146 if (rc)
1147 pr_err("Failed to control charging %d\n", rc);
1148
1149 return rc;
1150}
1151
David Keitel454ee842013-03-08 16:19:11 -08001152static int
1153switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001154{
1155 int rc;
1156
1157 pr_debug("switch to charge mode\n");
1158 if (!qpnp_chg_is_otg_en_set(chip))
1159 return 0;
1160
1161 /* enable usb ovp fet */
1162 rc = qpnp_chg_masked_write(chip,
1163 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1164 USB_OTG_EN_BIT,
1165 0, 1);
1166 if (rc) {
1167 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1168 return rc;
1169 }
1170
1171 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1172 if (rc) {
1173 pr_err("Failed re-enable charging rc = %d\n", rc);
1174 return rc;
1175 }
1176
1177 return 0;
1178}
1179
David Keitel454ee842013-03-08 16:19:11 -08001180static int
1181switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001182{
1183 int rc;
1184
1185 pr_debug("switch to host mode\n");
1186 if (qpnp_chg_is_otg_en_set(chip))
1187 return 0;
1188
1189 rc = qpnp_chg_force_run_on_batt(chip, 1);
1190 if (rc) {
1191 pr_err("Failed to disable charging rc = %d\n", rc);
1192 return rc;
1193 }
1194
1195 /* force usb ovp fet off */
1196 rc = qpnp_chg_masked_write(chip,
1197 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1198 USB_OTG_EN_BIT,
1199 USB_OTG_EN_BIT, 1);
1200 if (rc) {
1201 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1202 return rc;
1203 }
1204
1205 return 0;
1206}
1207
David Keitel80668952012-07-27 14:25:49 -07001208static enum power_supply_property pm_power_props_mains[] = {
1209 POWER_SUPPLY_PROP_PRESENT,
1210 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07001211 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07001212};
1213
1214static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07001215 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07001216 POWER_SUPPLY_PROP_STATUS,
1217 POWER_SUPPLY_PROP_CHARGE_TYPE,
1218 POWER_SUPPLY_PROP_HEALTH,
1219 POWER_SUPPLY_PROP_PRESENT,
1220 POWER_SUPPLY_PROP_TECHNOLOGY,
1221 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
1222 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
1223 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1224 POWER_SUPPLY_PROP_CAPACITY,
1225 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07001226 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
1227 POWER_SUPPLY_PROP_VOLTAGE_MIN,
1228 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07001229 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301230 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07001231 POWER_SUPPLY_PROP_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08001232 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301233 POWER_SUPPLY_PROP_CYCLE_COUNT,
David Keitel80668952012-07-27 14:25:49 -07001234};
1235
1236static char *pm_power_supplied_to[] = {
1237 "battery",
1238};
1239
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07001240static char *pm_batt_supplied_to[] = {
1241 "bms",
1242};
1243
David Keitel337bd862013-07-15 21:42:58 -07001244static int charger_monitor;
1245module_param(charger_monitor, int, 0644);
1246
David Keitel80668952012-07-27 14:25:49 -07001247#define USB_WALL_THRESHOLD_MA 500
1248static int
1249qpnp_power_get_property_mains(struct power_supply *psy,
1250 enum power_supply_property psp,
1251 union power_supply_propval *val)
1252{
1253 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1254 dc_psy);
1255
1256 switch (psp) {
1257 case POWER_SUPPLY_PROP_PRESENT:
1258 case POWER_SUPPLY_PROP_ONLINE:
1259 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07001260 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07001261 return 0;
1262
1263 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
1264 break;
David Keitel432e1232013-06-05 16:10:18 -07001265 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07001266 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07001267 break;
David Keitel80668952012-07-27 14:25:49 -07001268 default:
1269 return -EINVAL;
1270 }
1271 return 0;
1272}
1273
1274static int
1275get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
1276{
1277 int rc = 0;
1278 struct qpnp_vadc_result results;
1279
David Keitelfe51cb92013-04-02 19:42:58 -07001280 if (chip->revision == 0 && chip->type == SMBB) {
1281 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
1282 return 0;
1283 } else {
David Keitel80668952012-07-27 14:25:49 -07001284 rc = qpnp_vadc_read(VBAT_SNS, &results);
1285 if (rc) {
1286 pr_err("Unable to read vbat rc=%d\n", rc);
1287 return 0;
1288 }
1289 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07001290 }
1291}
1292
1293#define BATT_PRES_BIT BIT(7)
1294static int
1295get_prop_batt_present(struct qpnp_chg_chip *chip)
1296{
1297 u8 batt_present;
1298 int rc;
1299
1300 rc = qpnp_chg_read(chip, &batt_present,
1301 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
1302 if (rc) {
1303 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
1304 return 0;
1305 };
1306 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
1307}
1308
1309#define BATT_TEMP_HOT BIT(6)
1310#define BATT_TEMP_OK BIT(7)
1311static int
1312get_prop_batt_health(struct qpnp_chg_chip *chip)
1313{
1314 u8 batt_health;
1315 int rc;
1316
1317 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07001318 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07001319 if (rc) {
1320 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
1321 return POWER_SUPPLY_HEALTH_UNKNOWN;
1322 };
1323
1324 if (BATT_TEMP_OK & batt_health)
1325 return POWER_SUPPLY_HEALTH_GOOD;
1326 if (BATT_TEMP_HOT & batt_health)
1327 return POWER_SUPPLY_HEALTH_OVERHEAT;
1328 else
1329 return POWER_SUPPLY_HEALTH_COLD;
1330}
1331
1332static int
1333get_prop_charge_type(struct qpnp_chg_chip *chip)
1334{
1335 int rc;
1336 u8 chgr_sts;
1337
1338 if (!get_prop_batt_present(chip))
1339 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1340
1341 rc = qpnp_chg_read(chip, &chgr_sts,
1342 INT_RT_STS(chip->chgr_base), 1);
1343 if (rc) {
1344 pr_err("failed to read interrupt sts %d\n", rc);
1345 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1346 }
1347
1348 if (chgr_sts & TRKL_CHG_ON_IRQ)
1349 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1350 if (chgr_sts & FAST_CHG_ON_IRQ)
1351 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1352
1353 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1354}
1355
1356static int
1357get_prop_batt_status(struct qpnp_chg_chip *chip)
1358{
1359 int rc;
1360 u8 chgr_sts;
1361
David Keitel9fd07382013-05-02 15:37:44 -07001362 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
1363 qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
David Keitelc9ffe842013-01-25 19:37:51 -08001364 return POWER_SUPPLY_STATUS_FULL;
David Keitel9fd07382013-05-02 15:37:44 -07001365 }
David Keitelc9ffe842013-01-25 19:37:51 -08001366
David Keitel9fd07382013-05-02 15:37:44 -07001367 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07001368 if (rc) {
1369 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08001370 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07001371 }
1372
David Keitel80668952012-07-27 14:25:49 -07001373 if (chgr_sts & TRKL_CHG_ON_IRQ)
1374 return POWER_SUPPLY_STATUS_CHARGING;
1375 if (chgr_sts & FAST_CHG_ON_IRQ)
1376 return POWER_SUPPLY_STATUS_CHARGING;
1377
1378 return POWER_SUPPLY_STATUS_DISCHARGING;
1379}
1380
1381static int
1382get_prop_current_now(struct qpnp_chg_chip *chip)
1383{
1384 union power_supply_propval ret = {0,};
1385
1386 if (chip->bms_psy) {
1387 chip->bms_psy->get_property(chip->bms_psy,
1388 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
1389 return ret.intval;
1390 } else {
1391 pr_debug("No BMS supply registered return 0\n");
1392 }
1393
1394 return 0;
1395}
1396
1397static int
1398get_prop_full_design(struct qpnp_chg_chip *chip)
1399{
1400 union power_supply_propval ret = {0,};
1401
1402 if (chip->bms_psy) {
1403 chip->bms_psy->get_property(chip->bms_psy,
1404 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
1405 return ret.intval;
1406 } else {
1407 pr_debug("No BMS supply registered return 0\n");
1408 }
1409
1410 return 0;
1411}
1412
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301413static int
1414get_prop_charge_full(struct qpnp_chg_chip *chip)
1415{
1416 union power_supply_propval ret = {0,};
1417
1418 if (chip->bms_psy) {
1419 chip->bms_psy->get_property(chip->bms_psy,
1420 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
1421 return ret.intval;
1422 } else {
1423 pr_debug("No BMS supply registered return 0\n");
1424 }
1425
1426 return 0;
1427}
1428
David Keitel80668952012-07-27 14:25:49 -07001429#define DEFAULT_CAPACITY 50
1430static int
1431get_prop_capacity(struct qpnp_chg_chip *chip)
1432{
1433 union power_supply_propval ret = {0,};
1434
David Keitel3dd5e0f2012-12-12 18:12:36 -08001435 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
1436 return DEFAULT_CAPACITY;
1437
David Keitel80668952012-07-27 14:25:49 -07001438 if (chip->bms_psy) {
1439 chip->bms_psy->get_property(chip->bms_psy,
1440 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001441 if (get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL
1442 && !chip->resuming_charging
1443 && !chip->charging_disabled
1444 && chip->soc_resume_limit
1445 && ret.intval <= chip->soc_resume_limit) {
1446 pr_debug("resuming charging at %d%% soc\n", ret.intval);
1447 chip->resuming_charging = true;
1448 qpnp_chg_set_appropriate_vbatdet(chip);
1449 qpnp_chg_charge_en(chip, !chip->charging_disabled);
1450 }
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07001451 if (ret.intval == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07001452 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
1453 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07001454 pr_warn_ratelimited("Battery 0, CHG absent\n");
1455 }
David Keitel80668952012-07-27 14:25:49 -07001456 return ret.intval;
1457 } else {
1458 pr_debug("No BMS supply registered return 50\n");
1459 }
1460
1461 /* return default capacity to avoid userspace
1462 * from shutting down unecessarily */
1463 return DEFAULT_CAPACITY;
1464}
1465
David Keitel3dd5e0f2012-12-12 18:12:36 -08001466#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07001467#define MAX_TOLERABLE_BATT_TEMP_DDC 680
1468static int
1469get_prop_batt_temp(struct qpnp_chg_chip *chip)
1470{
1471 int rc = 0;
1472 struct qpnp_vadc_result results;
1473
David Keitel3dd5e0f2012-12-12 18:12:36 -08001474 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
1475 return DEFAULT_TEMP;
1476
David Keitela2dbfc72013-06-07 11:10:14 -07001477 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &results);
1478 if (rc) {
1479 pr_debug("Unable to read batt temperature rc=%d\n", rc);
1480 return 0;
David Keitel80668952012-07-27 14:25:49 -07001481 }
David Keitela2dbfc72013-06-07 11:10:14 -07001482 pr_debug("get_bat_temp %d %lld\n",
1483 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07001484
David Keitela2dbfc72013-06-07 11:10:14 -07001485 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07001486}
1487
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301488static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
1489{
1490 union power_supply_propval ret = {0,};
1491
1492 if (chip->bms_psy)
1493 chip->bms_psy->get_property(chip->bms_psy,
1494 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
1495 return ret.intval;
1496}
1497
David Keitel337bd862013-07-15 21:42:58 -07001498static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
1499{
1500 u8 buck_sts;
1501 int rc;
1502
1503 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
1504
1505 if (rc) {
1506 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1507 INT_RT_STS(chip->buck_base), rc);
1508 return rc;
1509 }
1510 pr_debug("buck usb sts 0x%x\n", buck_sts);
1511
1512 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
1513}
1514
David Keitel80668952012-07-27 14:25:49 -07001515static void
1516qpnp_batt_external_power_changed(struct power_supply *psy)
1517{
1518 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1519 batt_psy);
1520 union power_supply_propval ret = {0,};
1521
1522 if (!chip->bms_psy)
1523 chip->bms_psy = power_supply_get_by_name("bms");
1524
1525 chip->usb_psy->get_property(chip->usb_psy,
1526 POWER_SUPPLY_PROP_ONLINE, &ret);
1527
David Keitelc69f2d62013-03-17 14:52:35 -07001528 /* Only honour requests while USB is present */
1529 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07001530 chip->usb_psy->get_property(chip->usb_psy,
1531 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07001532
1533 if (chip->prev_usb_max_ma == ret.intval)
1534 goto skip_set_iusb_max;
1535
David Keitel87473252013-03-21 14:39:45 -07001536 if (ret.intval <= 2 && !chip->use_default_batt_values &&
1537 get_prop_batt_present(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07001538 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001539 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07001540 } else {
David Keiteld681cda2012-10-02 15:44:21 -07001541 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel337bd862013-07-15 21:42:58 -07001542 if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
1543 && (charger_monitor)) {
1544 qpnp_chg_iusbmax_set(chip,
1545 USB_WALL_THRESHOLD_MA);
1546 } else {
1547 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
1548 }
David Keitelc69f2d62013-03-17 14:52:35 -07001549 }
David Keitelfd305ee2013-07-19 20:19:06 -07001550 chip->prev_usb_max_ma = ret.intval;
David Keitel80668952012-07-27 14:25:49 -07001551 }
1552
David Keitelfd305ee2013-07-19 20:19:06 -07001553skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07001554 pr_debug("end of power supply changed\n");
1555 power_supply_changed(&chip->batt_psy);
1556}
1557
1558static int
1559qpnp_batt_power_get_property(struct power_supply *psy,
1560 enum power_supply_property psp,
1561 union power_supply_propval *val)
1562{
1563 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1564 batt_psy);
1565
1566 switch (psp) {
1567 case POWER_SUPPLY_PROP_STATUS:
1568 val->intval = get_prop_batt_status(chip);
1569 break;
1570 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1571 val->intval = get_prop_charge_type(chip);
1572 break;
1573 case POWER_SUPPLY_PROP_HEALTH:
1574 val->intval = get_prop_batt_health(chip);
1575 break;
1576 case POWER_SUPPLY_PROP_PRESENT:
1577 val->intval = get_prop_batt_present(chip);
1578 break;
1579 case POWER_SUPPLY_PROP_TECHNOLOGY:
1580 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1581 break;
1582 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1583 val->intval = chip->max_voltage_mv * 1000;
1584 break;
1585 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
1586 val->intval = chip->min_voltage_mv * 1000;
1587 break;
1588 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1589 val->intval = get_prop_battery_voltage_now(chip);
1590 break;
1591 case POWER_SUPPLY_PROP_TEMP:
1592 val->intval = get_prop_batt_temp(chip);
1593 break;
1594 case POWER_SUPPLY_PROP_CAPACITY:
1595 val->intval = get_prop_capacity(chip);
1596 break;
1597 case POWER_SUPPLY_PROP_CURRENT_NOW:
1598 val->intval = get_prop_current_now(chip);
1599 break;
1600 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1601 val->intval = get_prop_full_design(chip);
1602 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301603 case POWER_SUPPLY_PROP_CHARGE_FULL:
1604 val->intval = get_prop_charge_full(chip);
1605 break;
David Keitelb80eda82012-10-15 10:49:11 -07001606 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07001607 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07001608 break;
David Keitelbe208252013-01-31 14:49:25 -08001609 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
1610 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07001611 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301612 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1613 val->intval = get_prop_cycle_count(chip);
1614 break;
David Keitel337bd862013-07-15 21:42:58 -07001615 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
1616 val->intval = get_prop_vchg_loop(chip);
1617 break;
1618 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
1619 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
1620 break;
1621 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
1622 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
1623 break;
David Keitelb80eda82012-10-15 10:49:11 -07001624 default:
1625 return -EINVAL;
1626 }
1627
David Keitelb80eda82012-10-15 10:49:11 -07001628 return 0;
David Keitel80668952012-07-27 14:25:49 -07001629}
1630
David Keitel89c17752013-06-28 14:52:48 -07001631#define BTC_CONFIG_ENABLED BIT(7)
1632#define BTC_COLD BIT(1)
1633#define BTC_HOT BIT(0)
1634static int
1635qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
1636{
1637 u8 btc_cfg = 0, mask = 0;
1638
1639 /* Do nothing if battery peripheral not present */
1640 if (!chip->bat_if_base)
1641 return 0;
1642
1643 if ((chip->hot_batt_p == HOT_THD_25_PCT)
1644 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
1645 btc_cfg |= btc_value[chip->hot_batt_p];
1646 mask |= BTC_HOT;
1647 }
1648
1649 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
1650 (chip->cold_batt_p == COLD_THD_80_PCT)) {
1651 btc_cfg |= btc_value[chip->cold_batt_p];
1652 mask |= BTC_COLD;
1653 }
1654
1655 if (chip->btc_disabled)
1656 mask |= BTC_CONFIG_ENABLED;
1657
1658 return qpnp_chg_masked_write(chip,
1659 chip->bat_if_base + BAT_IF_BTC_CTRL,
1660 mask, btc_cfg, 1);
1661}
1662
David Keitel5d44fa52012-12-03 16:37:31 -08001663#define QPNP_CHG_IBATSAFE_MIN_MA 100
1664#define QPNP_CHG_IBATSAFE_MAX_MA 3250
1665#define QPNP_CHG_I_STEP_MA 50
1666#define QPNP_CHG_I_MIN_MA 100
1667#define QPNP_CHG_I_MASK 0x3F
1668static int
1669qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
1670{
1671 u8 temp;
1672
1673 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
1674 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
1675 pr_err("bad mA=%d asked to set\n", safe_current);
1676 return -EINVAL;
1677 }
1678
1679 temp = (safe_current - QPNP_CHG_IBATSAFE_MIN_MA)
1680 / QPNP_CHG_I_STEP_MA;
1681 return qpnp_chg_masked_write(chip,
1682 chip->chgr_base + CHGR_IBAT_SAFE,
1683 QPNP_CHG_I_MASK, temp, 1);
1684}
David Keitel80668952012-07-27 14:25:49 -07001685
1686#define QPNP_CHG_ITERM_MIN_MA 100
1687#define QPNP_CHG_ITERM_MAX_MA 250
1688#define QPNP_CHG_ITERM_STEP_MA 50
1689#define QPNP_CHG_ITERM_MASK 0x03
1690static int
1691qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
1692{
1693 u8 temp;
1694
1695 if (term_current < QPNP_CHG_ITERM_MIN_MA
1696 || term_current > QPNP_CHG_ITERM_MAX_MA) {
1697 pr_err("bad mA=%d asked to set\n", term_current);
1698 return -EINVAL;
1699 }
1700
1701 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
1702 / QPNP_CHG_ITERM_STEP_MA;
1703 return qpnp_chg_masked_write(chip,
1704 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
1705 QPNP_CHG_ITERM_MASK, temp, 1);
1706}
1707
David Keitelff5d0472013-04-04 11:36:06 -07001708#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07001709#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07001710static int
1711qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
1712{
1713 u8 temp;
1714
1715 if (chg_current < QPNP_CHG_IBATMAX_MIN
1716 || chg_current > QPNP_CHG_IBATMAX_MAX) {
1717 pr_err("bad mA=%d asked to set\n", chg_current);
1718 return -EINVAL;
1719 }
David Keitelff5d0472013-04-04 11:36:06 -07001720 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07001721 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
1722 QPNP_CHG_I_MASK, temp, 1);
1723}
1724
David Keitela4b7b592013-04-11 18:34:35 -07001725#define QPNP_CHG_TCHG_MASK 0x7F
1726#define QPNP_CHG_TCHG_MIN 4
1727#define QPNP_CHG_TCHG_MAX 512
1728#define QPNP_CHG_TCHG_STEP 4
1729static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
1730{
1731 u8 temp;
1732
1733 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
1734 pr_err("bad max minutes =%d asked to set\n", minutes);
1735 return -EINVAL;
1736 }
1737
1738 temp = (minutes - 1)/QPNP_CHG_TCHG_STEP;
1739 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07001740 QPNP_CHG_TCHG_MASK, temp, 1);
David Keitela4b7b592013-04-11 18:34:35 -07001741}
David Keitel80668952012-07-27 14:25:49 -07001742
1743#define QPNP_CHG_V_MIN_MV 3240
1744#define QPNP_CHG_V_MAX_MV 4500
1745#define QPNP_CHG_V_STEP_MV 10
1746static int
1747qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
1748{
1749 u8 temp;
1750
1751 if (voltage < QPNP_CHG_V_MIN_MV
1752 || voltage > QPNP_CHG_V_MAX_MV) {
1753 pr_err("bad mV=%d asked to set\n", voltage);
1754 return -EINVAL;
1755 }
1756 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1757 pr_debug("voltage=%d setting %02x\n", voltage, temp);
1758 return qpnp_chg_write(chip, &temp,
1759 chip->chgr_base + CHGR_VDD_SAFE, 1);
1760}
1761
1762#define QPNP_CHG_VDDMAX_MIN 3400
1763static int
1764qpnp_chg_vddmax_set(struct qpnp_chg_chip *chip, int voltage)
1765{
1766 u8 temp = 0;
1767
1768 if (voltage < QPNP_CHG_VDDMAX_MIN
1769 || voltage > QPNP_CHG_V_MAX_MV) {
1770 pr_err("bad mV=%d asked to set\n", voltage);
1771 return -EINVAL;
1772 }
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001773 chip->set_vddmax_mv = voltage + chip->delta_vddmax_mv;
David Keitel80668952012-07-27 14:25:49 -07001774
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001775 temp = (chip->set_vddmax_mv - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
David Keitel80668952012-07-27 14:25:49 -07001776
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001777 pr_debug("voltage=%d setting %02x\n", chip->set_vddmax_mv, temp);
David Keitel454ee842013-03-08 16:19:11 -08001778 return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
1779}
1780
David Keitel6dc4ed42013-05-17 11:08:58 -07001781#define BOOST_MIN_UV 4200000
1782#define BOOST_MAX_UV 5500000
1783#define BOOST_STEP_UV 50000
1784#define BOOST_MIN 16
1785#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
1786static int
1787qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
1788{
1789 u8 reg = 0;
1790
1791 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
1792 pr_err("invalid voltage requested %d uV\n", voltage);
1793 return -EINVAL;
1794 }
1795
1796 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
1797
1798 pr_debug("voltage=%d setting %02x\n", voltage, reg);
1799 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
1800}
1801
1802static int
1803qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
1804{
1805 int rc;
1806 u8 boost_reg;
1807
1808 rc = qpnp_chg_read(chip, &boost_reg,
1809 chip->boost_base + BOOST_VSET, 1);
1810 if (rc) {
1811 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
1812 return rc;
1813 }
1814
1815 if (boost_reg < BOOST_MIN) {
1816 pr_err("Invalid reading from 0x%x\n", boost_reg);
1817 return -EINVAL;
1818 }
1819
1820 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
1821}
1822
David Keitel454ee842013-03-08 16:19:11 -08001823/* JEITA compliance logic */
1824static void
1825qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1826{
1827 if (chip->bat_is_cool)
1828 qpnp_chg_vddmax_set(chip, chip->cool_bat_mv);
1829 else if (chip->bat_is_warm)
1830 qpnp_chg_vddmax_set(chip, chip->warm_bat_mv);
1831 else
1832 qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
1833}
1834
1835static void
David Keitelbe208252013-01-31 14:49:25 -08001836qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
1837{
1838 unsigned int chg_current = chip->max_bat_chg_current;
1839
David Keitel454ee842013-03-08 16:19:11 -08001840 if (chip->bat_is_cool)
1841 chg_current = min(chg_current, chip->cool_bat_chg_ma);
1842
1843 if (chip->bat_is_warm)
1844 chg_current = min(chg_current, chip->warm_bat_chg_ma);
1845
David Keitelbe208252013-01-31 14:49:25 -08001846 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
1847 chg_current = min(chg_current,
1848 chip->thermal_mitigation[chip->therm_lvl_sel]);
1849
1850 pr_debug("setting %d mA\n", chg_current);
1851 qpnp_chg_ibatmax_set(chip, chg_current);
1852}
1853
1854static void
1855qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
1856{
1857 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
1858 chip->therm_lvl_sel = lvl_sel;
1859 if (lvl_sel == (chip->thermal_levels - 1)) {
1860 /* disable charging if highest value selected */
1861 qpnp_chg_buck_control(chip, 0);
1862 } else {
1863 qpnp_chg_buck_control(chip, 1);
1864 qpnp_chg_set_appropriate_battery_current(chip);
1865 }
1866 } else {
1867 pr_err("Unsupported level selected %d\n", lvl_sel);
1868 }
1869}
1870
David Keitel6dc4ed42013-05-17 11:08:58 -07001871/* OTG regulator operations */
1872static int
1873qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
1874{
1875 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1876
1877 return switch_usb_to_host_mode(chip);
1878}
1879
1880static int
1881qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
1882{
1883 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1884
1885 return switch_usb_to_charge_mode(chip);
1886}
1887
1888static int
1889qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
1890{
1891 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1892
1893 return qpnp_chg_is_otg_en_set(chip);
1894}
1895
1896static int
1897qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
1898{
1899 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07001900 int rc;
1901
1902 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
1903 (chip->flags & BOOST_FLASH_WA)) {
1904 qpnp_chg_usb_suspend_enable(chip, 1);
1905
1906 rc = qpnp_chg_masked_write(chip,
1907 chip->usb_chgpth_base + SEC_ACCESS,
1908 0xFF,
1909 0xA5, 1);
1910 if (rc) {
1911 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1912 return rc;
1913 }
1914
1915 rc = qpnp_chg_masked_write(chip,
1916 chip->usb_chgpth_base + COMP_OVR1,
1917 0xFF,
1918 0x2F, 1);
1919 if (rc) {
1920 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1921 return rc;
1922 }
1923 }
David Keitel6dc4ed42013-05-17 11:08:58 -07001924
1925 return qpnp_chg_masked_write(chip,
1926 chip->boost_base + BOOST_ENABLE_CONTROL,
1927 BOOST_PWR_EN,
1928 BOOST_PWR_EN, 1);
1929}
1930
1931/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07001932#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07001933static int
1934qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
1935{
1936 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07001937 int rc;
1938 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07001939
David Keitel33f58952013-05-20 16:17:36 -07001940 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07001941 chip->boost_base + BOOST_ENABLE_CONTROL,
1942 BOOST_PWR_EN,
1943 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07001944 if (rc) {
1945 pr_err("failed to disable boost rc=%d\n", rc);
1946 return rc;
1947 }
1948
1949 rc = qpnp_chg_read(chip, &vbat_sts,
1950 chip->chgr_base + CHGR_VBAT_STATUS, 1);
1951 if (rc) {
1952 pr_err("failed to read bat sts rc=%d\n", rc);
1953 return rc;
1954 }
1955
1956 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
1957 rc = qpnp_chg_masked_write(chip,
1958 chip->chgr_base + SEC_ACCESS,
1959 0xFF,
1960 0xA5, 1);
1961 if (rc) {
1962 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1963 return rc;
1964 }
1965
1966 rc = qpnp_chg_masked_write(chip,
1967 chip->chgr_base + COMP_OVR1,
1968 0xFF,
1969 0x20, 1);
1970 if (rc) {
1971 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1972 return rc;
1973 }
1974
1975 usleep(2000);
1976
1977 rc = qpnp_chg_masked_write(chip,
1978 chip->chgr_base + SEC_ACCESS,
1979 0xFF,
1980 0xA5, 1);
1981 if (rc) {
1982 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1983 return rc;
1984 }
1985
1986 rc = qpnp_chg_masked_write(chip,
1987 chip->chgr_base + COMP_OVR1,
1988 0xFF,
1989 0x00, 1);
1990 if (rc) {
1991 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1992 return rc;
1993 }
1994 }
1995
1996 if (qpnp_chg_is_usb_chg_plugged_in(chip)
1997 && (chip->flags & BOOST_FLASH_WA)) {
1998 rc = qpnp_chg_masked_write(chip,
1999 chip->usb_chgpth_base + SEC_ACCESS,
2000 0xFF,
2001 0xA5, 1);
2002 if (rc) {
2003 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2004 return rc;
2005 }
2006
2007 rc = qpnp_chg_masked_write(chip,
2008 chip->usb_chgpth_base + COMP_OVR1,
2009 0xFF,
2010 0x00, 1);
2011 if (rc) {
2012 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2013 return rc;
2014 }
2015
2016 usleep(1000);
2017
2018 qpnp_chg_usb_suspend_enable(chip, 0);
2019 }
2020
2021 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07002022}
2023
2024static int
2025qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
2026{
2027 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2028
2029 return qpnp_chg_is_boost_en_set(chip);
2030}
2031
2032static int
2033qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
2034 int min_uV, int max_uV, unsigned *selector)
2035{
2036 int uV = min_uV;
2037 int rc;
2038 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2039
2040 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
2041 uV = BOOST_MIN_UV;
2042
2043
2044 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
2045 pr_err("request %d uV is out of bounds\n", uV);
2046 return -EINVAL;
2047 }
2048
2049 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
2050 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
2051 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
2052 return -EINVAL;
2053 }
2054
2055 rc = qpnp_boost_vset(chip, uV);
2056
2057 return rc;
2058}
2059
2060static int
2061qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
2062{
2063 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2064
2065 return qpnp_boost_vget_uv(chip);
2066}
2067
2068static int
2069qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
2070 unsigned selector)
2071{
2072 if (selector >= N_BOOST_V)
2073 return 0;
2074
2075 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
2076}
2077
2078static struct regulator_ops qpnp_chg_otg_reg_ops = {
2079 .enable = qpnp_chg_regulator_otg_enable,
2080 .disable = qpnp_chg_regulator_otg_disable,
2081 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
2082};
2083
2084static struct regulator_ops qpnp_chg_boost_reg_ops = {
2085 .enable = qpnp_chg_regulator_boost_enable,
2086 .disable = qpnp_chg_regulator_boost_disable,
2087 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
2088 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
2089 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
2090 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
2091};
2092
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002093#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 13
2094#define MAX_DELTA_VDD_MAX_MV 30
2095static void
2096qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
2097{
2098 int delta_mv, closest_delta_mv, sign;
2099
2100 delta_mv = chip->max_voltage_mv - vbat_mv;
2101 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
2102 pr_debug("vbat is not low enough to increase vdd\n");
2103 return;
2104 }
2105
2106 sign = delta_mv > 0 ? 1 : -1;
2107 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_V_STEP_MV / 2)
2108 / QPNP_CHG_V_STEP_MV) * QPNP_CHG_V_STEP_MV;
2109 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
2110 chip->max_voltage_mv, vbat_mv,
2111 delta_mv, closest_delta_mv);
2112 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
2113 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
2114 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
2115 qpnp_chg_set_appropriate_vddmax(chip);
2116}
2117
David Keitel9fd07382013-05-02 15:37:44 -07002118#define CONSECUTIVE_COUNT 3
2119static void
2120qpnp_eoc_work(struct work_struct *work)
2121{
2122 struct delayed_work *dwork = to_delayed_work(work);
2123 struct qpnp_chg_chip *chip = container_of(dwork,
2124 struct qpnp_chg_chip, eoc_work);
2125 static int count;
2126 int ibat_ma, vbat_mv, rc = 0;
2127 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
2128
2129 wake_lock(&chip->eoc_wake_lock);
2130 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2131
2132 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
2133 if (rc) {
2134 pr_err("failed to read batt_if rc=%d\n", rc);
2135 return;
2136 }
2137
2138 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2139 if (rc) {
2140 pr_err("failed to read buck rc=%d\n", rc);
2141 return;
2142 }
2143
2144 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
2145 if (rc) {
2146 pr_err("failed to read chg_sts rc=%d\n", rc);
2147 return;
2148 }
2149
2150 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
2151 chg_sts, batt_sts, buck_sts);
2152
2153 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
2154 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
2155 pr_debug("no chg connected, stopping\n");
2156 goto stop_eoc;
2157 }
2158
2159 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
2160 || chg_sts & TRKL_CHG_ON_IRQ)) {
2161 ibat_ma = get_prop_current_now(chip) / 1000;
2162 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002163
2164 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
2165 ibat_ma, vbat_mv, chip->term_current);
2166
2167 if ((!(chg_sts & VBAT_DET_LOW_IRQ)) && (vbat_mv <
2168 (chip->max_voltage_mv - chip->resume_delta_mv))) {
2169 pr_debug("woke up too early\n");
2170 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
2171 goto stop_eoc;
2172 }
2173
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002174 if (buck_sts & VDD_LOOP_IRQ)
2175 qpnp_chg_adjust_vddmax(chip, vbat_mv);
2176
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002177 if (!(buck_sts & VDD_LOOP_IRQ)) {
2178 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07002179 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002180 } else if ((ibat_ma * -1) > chip->term_current) {
2181 pr_debug("Not at EOC, battery current too high\n");
2182 count = 0;
2183 } else if (ibat_ma > 0) {
2184 pr_debug("Charging but system demand increased\n");
2185 count = 0;
2186 } else {
David Keitel9fd07382013-05-02 15:37:44 -07002187 if (count == CONSECUTIVE_COUNT) {
2188 pr_info("End of Charging\n");
2189 qpnp_chg_charge_en(chip, 0);
2190 chip->chg_done = true;
2191 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07002192 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07002193 goto stop_eoc;
2194 } else {
2195 count += 1;
2196 pr_debug("EOC count = %d\n", count);
2197 }
David Keitel9fd07382013-05-02 15:37:44 -07002198 }
2199 } else {
2200 pr_debug("not charging\n");
2201 goto stop_eoc;
2202 }
2203
2204 schedule_delayed_work(&chip->eoc_work,
2205 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2206 return;
2207
2208stop_eoc:
2209 count = 0;
2210 wake_unlock(&chip->eoc_wake_lock);
2211}
2212
David Keitel0c1a4532013-03-21 16:39:06 -07002213#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08002214static void
2215qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
2216{
2217 struct qpnp_chg_chip *chip = ctx;
2218 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07002219 int temp;
David Keitel454ee842013-03-08 16:19:11 -08002220
2221 if (state >= ADC_TM_STATE_NUM) {
2222 pr_err("invalid notification %d\n", state);
2223 return;
2224 }
2225
David Keitel1219a802013-03-21 16:37:21 -07002226 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08002227
David Keitel1219a802013-03-21 16:37:21 -07002228 pr_debug("temp = %d state = %s\n", temp,
2229 state == ADC_TM_WARM_STATE ? "warm" : "cool");
2230
2231 if (state == ADC_TM_WARM_STATE) {
2232 if (temp > chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002233 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08002234 bat_warm = true;
2235 bat_cool = false;
2236 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002237 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002238 chip->adc_param.state_request =
2239 ADC_TM_COOL_THR_ENABLE;
2240 } else if (temp >
2241 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002242 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08002243 bat_warm = false;
2244 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07002245
2246 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07002247 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07002248 chip->adc_param.state_request =
2249 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08002250 }
2251 } else {
David Keitel1219a802013-03-21 16:37:21 -07002252 if (temp < chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002253 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08002254 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002255 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08002256 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002257 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002258 chip->adc_param.state_request =
2259 ADC_TM_WARM_THR_ENABLE;
David Keitel3e37e5a2013-04-18 10:42:30 -07002260 } else if (temp <
David Keitel1219a802013-03-21 16:37:21 -07002261 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002262 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08002263 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002264 bat_cool = false;
2265
David Keitel0c1a4532013-03-21 16:39:06 -07002266 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07002267 chip->adc_param.high_temp = chip->warm_bat_decidegc;
2268 chip->adc_param.state_request =
2269 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08002270 }
2271 }
2272
2273 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07002274 chip->bat_is_cool = bat_cool;
2275 chip->bat_is_warm = bat_warm;
2276
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002277 if (bat_cool || bat_warm)
2278 chip->resuming_charging = false;
2279
2280 /**
2281 * set appropriate voltages and currents.
2282 *
2283 * Note that when the battery is hot or cold, the charger
2284 * driver will not resume with SoC. Only vbatdet is used to
2285 * determine resume of charging.
2286 */
David Keitel454ee842013-03-08 16:19:11 -08002287 qpnp_chg_set_appropriate_vddmax(chip);
2288 qpnp_chg_set_appropriate_battery_current(chip);
2289 qpnp_chg_set_appropriate_vbatdet(chip);
David Keitel454ee842013-03-08 16:19:11 -08002290 }
2291
David Keitel1219a802013-03-21 16:37:21 -07002292 if (qpnp_adc_tm_channel_measure(&chip->adc_param))
2293 pr_err("request ADC error\n");
David Keitel454ee842013-03-08 16:19:11 -08002294}
2295
David Keitelbe208252013-01-31 14:49:25 -08002296static int
David Keitel432e1232013-06-05 16:10:18 -07002297qpnp_dc_power_set_property(struct power_supply *psy,
2298 enum power_supply_property psp,
2299 const union power_supply_propval *val)
2300{
2301 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2302 dc_psy);
2303 int rc = 0;
2304
2305 switch (psp) {
2306 case POWER_SUPPLY_PROP_CURRENT_MAX:
2307 if (!val->intval)
2308 break;
2309
2310 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
2311 if (rc) {
2312 pr_err("Error setting idcmax property %d\n", rc);
2313 return rc;
2314 }
2315 chip->maxinput_dc_ma = (val->intval / 1000);
2316
2317 break;
2318 default:
2319 return -EINVAL;
2320 }
2321
2322 power_supply_changed(&chip->dc_psy);
2323 return rc;
2324}
2325
2326static int
David Keitelbe208252013-01-31 14:49:25 -08002327qpnp_batt_power_set_property(struct power_supply *psy,
2328 enum power_supply_property psp,
2329 const union power_supply_propval *val)
2330{
2331 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2332 batt_psy);
2333
2334 switch (psp) {
2335 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
2336 chip->charging_disabled = !(val->intval);
2337 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2338 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2339 break;
2340 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2341 qpnp_batt_system_temp_level_set(chip, val->intval);
2342 break;
David Keitel337bd862013-07-15 21:42:58 -07002343 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2344 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
2345 break;
2346 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2347 qpnp_chg_vinmin_set(chip, val->intval / 1000);
2348 break;
David Keitelbe208252013-01-31 14:49:25 -08002349 default:
2350 return -EINVAL;
2351 }
2352
2353 power_supply_changed(&chip->batt_psy);
2354 return 0;
2355}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08002356
2357static void
2358qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07002359{
David Keitelfe51cb92013-04-02 19:42:58 -07002360 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07002361 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07002362 if (chip->type == SMBB)
2363 chip->flags |= BOOST_FLASH_WA;
David Keitel14288042013-06-04 15:16:46 -07002364 if (chip->type == SMBBP)
2365 chip->flags |= BOOST_FLASH_WA;
David Keiteld681cda2012-10-02 15:44:21 -07002366}
2367
David Keitel0f35be42013-04-16 11:10:40 -07002368static int
2369qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
2370{
2371 int rc = 0;
2372 struct resource *resource;
2373 struct spmi_resource *spmi_resource;
2374 u8 subtype;
2375 struct spmi_device *spmi = chip->spmi;
2376
2377 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
2378 if (!spmi_resource) {
2379 pr_err("qpnp_chg: spmi resource absent\n");
2380 return rc;
2381 }
2382
2383 resource = spmi_get_resource(spmi, spmi_resource,
2384 IORESOURCE_MEM, 0);
2385 if (!(resource && resource->start)) {
2386 pr_err("node %s IO resource absent!\n",
2387 spmi->dev.of_node->full_name);
2388 return rc;
2389 }
2390
2391 rc = qpnp_chg_read(chip, &subtype,
2392 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2393 if (rc) {
2394 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2395 return rc;
2396 }
2397
2398 switch (subtype) {
2399 case SMBB_CHGR_SUBTYPE:
2400 case SMBBP_CHGR_SUBTYPE:
2401 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002402 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002403 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07002404 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002405 pr_err("Unable to get fast-chg-on irq\n");
2406 return rc;
2407 }
2408
David Keitel47185a62013-05-15 18:54:10 -07002409 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002410 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07002411 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002412 pr_err("Unable to get trkl-chg-on irq\n");
2413 return rc;
2414 }
2415
David Keitel47185a62013-05-15 18:54:10 -07002416 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002417 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07002418 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002419 pr_err("Unable to get chg_failed irq\n");
2420 return rc;
2421 }
2422
David Keitel47185a62013-05-15 18:54:10 -07002423 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07002424 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07002425 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07002426 pr_err("Unable to get fast-chg-on irq\n");
2427 return rc;
2428 }
2429
David Keitel47185a62013-05-15 18:54:10 -07002430 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002431 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07002432 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002433 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002434 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002435 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002436 return rc;
2437 }
2438
David Keitel47185a62013-05-15 18:54:10 -07002439 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002440 qpnp_chg_chgr_chg_fastchg_irq_handler,
2441 IRQF_TRIGGER_RISING,
2442 "fast-chg-on", chip);
2443 if (rc < 0) {
2444 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002445 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002446 return rc;
2447 }
2448
David Keitel47185a62013-05-15 18:54:10 -07002449 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002450 qpnp_chg_chgr_chg_trklchg_irq_handler,
2451 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002452 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002453 if (rc < 0) {
2454 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002455 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002456 return rc;
2457 }
David Keitel9fd07382013-05-02 15:37:44 -07002458
2459 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07002460 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07002461 qpnp_chg_vbatdet_lo_irq_handler,
David Keiteld98e2822013-06-05 11:37:34 -07002462 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitel9fd07382013-05-02 15:37:44 -07002463 "vbat-det-lo", chip);
2464 if (rc < 0) {
2465 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002466 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07002467 return rc;
2468 }
2469
David Keitel47185a62013-05-15 18:54:10 -07002470 enable_irq_wake(chip->chg_trklchg.irq);
2471 enable_irq_wake(chip->chg_failed.irq);
2472 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
2473 enable_irq_wake(chip->chg_vbatdet_lo.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002474
2475 break;
2476 case SMBB_BAT_IF_SUBTYPE:
2477 case SMBBP_BAT_IF_SUBTYPE:
2478 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002479 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002480 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07002481 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002482 pr_err("Unable to get batt-pres irq\n");
2483 return rc;
2484 }
David Keitel47185a62013-05-15 18:54:10 -07002485 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002486 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07002487 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
2488 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07002489 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002490 if (rc < 0) {
2491 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002492 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002493 return rc;
2494 }
2495
David Keitel47185a62013-05-15 18:54:10 -07002496 enable_irq_wake(chip->batt_pres.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002497 break;
David Keitel337bd862013-07-15 21:42:58 -07002498 case SMBB_BUCK_SUBTYPE:
2499 case SMBBP_BUCK_SUBTYPE:
2500 case SMBCL_BUCK_SUBTYPE:
2501 chip->vchg_loop.irq = spmi_get_irq_byname(spmi,
2502 spmi_resource, "vchg-loop");
2503 if (chip->vchg_loop.irq < 0) {
2504 pr_err("Unable to get vchg-loop irq\n");
2505 return rc;
2506 }
2507 rc = devm_request_irq(chip->dev, chip->vchg_loop.irq,
2508 qpnp_chg_buck_vchg_loop_irq_handler,
2509 IRQF_TRIGGER_RISING,
2510 "vchg-loop", chip);
2511 if (rc < 0) {
2512 pr_err("Can't request %d vchg-loop irq: %d\n",
2513 chip->vchg_loop.irq, rc);
2514 return rc;
2515 }
2516
2517 enable_irq_wake(chip->vchg_loop.irq);
2518 qpnp_chg_disable_irq(&chip->vchg_loop);
2519 break;
2520
David Keitel0f35be42013-04-16 11:10:40 -07002521 case SMBB_USB_CHGPTH_SUBTYPE:
2522 case SMBBP_USB_CHGPTH_SUBTYPE:
2523 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002524 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002525 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07002526 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002527 pr_err("Unable to get usbin irq\n");
2528 return rc;
2529 }
David Keitel47185a62013-05-15 18:54:10 -07002530 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002531 qpnp_chg_usb_usbin_valid_irq_handler,
2532 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002533 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002534 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002535 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002536 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002537 return rc;
2538 }
David Keitel344c6972013-04-09 19:28:21 -07002539
David Keitel47185a62013-05-15 18:54:10 -07002540 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07002541 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07002542 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07002543 pr_err("Unable to get chg-gone irq\n");
2544 return rc;
2545 }
David Keitel47185a62013-05-15 18:54:10 -07002546 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07002547 qpnp_chg_usb_chg_gone_irq_handler,
2548 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07002549 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07002550 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002551 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002552 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07002553 return rc;
2554 }
David Keitel47185a62013-05-15 18:54:10 -07002555
2556 enable_irq_wake(chip->usbin_valid.irq);
2557 enable_irq_wake(chip->chg_gone.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002558 break;
2559 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002560 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002561 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07002562 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002563 pr_err("Unable to get dcin irq\n");
2564 return -rc;
2565 }
David Keitel47185a62013-05-15 18:54:10 -07002566 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002567 qpnp_chg_dc_dcin_valid_irq_handler,
2568 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002569 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002570 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002571 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002572 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002573 return rc;
2574 }
2575
David Keitel47185a62013-05-15 18:54:10 -07002576 enable_irq_wake(chip->dcin_valid.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002577 break;
2578 }
2579 }
2580
2581 return rc;
2582}
2583
Xiaozhe Shica289e02013-06-19 13:24:51 -07002584static int
2585qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
2586{
2587 struct bms_battery_data batt_data;
2588 struct device_node *node;
2589 struct qpnp_vadc_result result;
2590 int rc;
2591
2592 node = of_find_node_by_name(chip->spmi->dev.of_node,
2593 "qcom,battery-data");
2594 if (node) {
2595 memset(&batt_data, 0, sizeof(struct bms_battery_data));
2596 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2597 if (rc) {
2598 pr_err("error reading batt id channel = %d, rc = %d\n",
2599 LR_MUX2_BAT_ID, rc);
2600 return rc;
2601 }
2602
2603 rc = of_batterydata_read_data(node,
2604 &batt_data, result.physical);
2605 if (rc) {
2606 pr_err("failed to read battery data: %d\n", rc);
2607 return rc;
2608 }
2609
2610 if (batt_data.max_voltage_uv >= 0)
2611 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
2612 if (batt_data.iterm_ua >= 0)
2613 chip->term_current = batt_data.iterm_ua / 1000;
2614 }
2615
2616 return 0;
2617}
2618
David Keitel80668952012-07-27 14:25:49 -07002619#define WDOG_EN_BIT BIT(7)
2620static int
2621qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
2622 struct spmi_resource *spmi_resource)
2623{
2624 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07002625 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07002626 struct regulator_init_data *init_data;
2627 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07002628
2629 switch (subtype) {
2630 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002631 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002632 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07002633 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
2634 if (rc) {
2635 pr_debug("failed setting min_voltage rc=%d\n", rc);
2636 return rc;
2637 }
2638 rc = qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
2639 if (rc) {
2640 pr_debug("failed setting max_voltage rc=%d\n", rc);
2641 return rc;
2642 }
2643 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
2644 if (rc) {
2645 pr_debug("failed setting safe_voltage rc=%d\n", rc);
2646 return rc;
2647 }
David Keitel454ee842013-03-08 16:19:11 -08002648 rc = qpnp_chg_vbatdet_set(chip,
2649 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08002650 if (rc) {
2651 pr_debug("failed setting resume_voltage rc=%d\n", rc);
2652 return rc;
2653 }
David Keitel80668952012-07-27 14:25:49 -07002654 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
2655 if (rc) {
2656 pr_debug("failed setting ibatmax rc=%d\n", rc);
2657 return rc;
2658 }
David Keitel365c4c42013-03-08 16:20:40 -08002659 if (chip->term_current) {
2660 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
2661 if (rc) {
2662 pr_debug("failed setting ibatterm rc=%d\n", rc);
2663 return rc;
2664 }
David Keitel80668952012-07-27 14:25:49 -07002665 }
David Keitel5d44fa52012-12-03 16:37:31 -08002666 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
2667 if (rc) {
2668 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
2669 return rc;
2670 }
David Keitela4b7b592013-04-11 18:34:35 -07002671 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
2672 if (rc) {
2673 pr_debug("failed setting tchg_mins rc=%d\n", rc);
2674 return rc;
2675 }
2676
David Keitel80668952012-07-27 14:25:49 -07002677 /* HACK: Disable wdog */
2678 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
2679 0xFF, 0xA0, 1);
2680
David Keitelb4e43542013-04-09 17:30:41 -07002681 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07002682 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
2683 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07002684 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07002685
David Keitel80668952012-07-27 14:25:49 -07002686 break;
2687 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002688 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002689 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07002690 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
2691 if (rc)
2692 return rc;
2693
David Keitel9201df32013-01-10 18:38:34 -08002694 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07002695 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08002696 BUCK_VBAT_REG_NODE_SEL_BIT,
2697 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
2698 if (rc) {
2699 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
2700 return rc;
2701 }
David Keitel80668952012-07-27 14:25:49 -07002702 break;
2703 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002704 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002705 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07002706 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07002707 switch (chip->bpd_detection) {
2708 case BPD_TYPE_BAT_THM:
2709 reg = BAT_THM_EN;
2710 break;
2711 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07002712 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07002713 break;
2714 case BPD_TYPE_BAT_THM_BAT_ID:
2715 reg = BAT_THM_EN | BAT_ID_EN;
2716 break;
2717 default:
2718 reg = BAT_THM_EN;
2719 break;
2720 }
David Keitel796882d2013-05-14 18:01:11 -07002721
2722 rc = qpnp_chg_masked_write(chip,
2723 chip->bat_if_base + BAT_IF_BPD_CTRL,
2724 BAT_IF_BPD_CTRL_SEL,
2725 reg, 1);
2726 if (rc) {
2727 pr_debug("failed to chose BPD rc=%d\n", rc);
2728 return rc;
2729 }
David Keitel85ae4342013-04-16 11:46:00 -07002730 /* Force on VREF_BAT_THM */
2731 rc = qpnp_chg_masked_write(chip,
2732 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
2733 VREF_BATT_THERM_FORCE_ON,
2734 VREF_BATT_THERM_FORCE_ON, 1);
2735 if (rc) {
2736 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
2737 return rc;
2738 }
David Keitel80668952012-07-27 14:25:49 -07002739 break;
2740 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002741 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002742 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07002743 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07002744 rc = qpnp_chg_masked_write(chip,
2745 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
2746 ENUM_T_STOP_BIT,
2747 ENUM_T_STOP_BIT, 1);
2748 if (rc) {
2749 pr_err("failed to write enum stop rc=%d\n", rc);
2750 return -ENXIO;
2751 }
2752 }
David Keiteld681cda2012-10-02 15:44:21 -07002753
David Keitel6dc4ed42013-05-17 11:08:58 -07002754 init_data = of_get_regulator_init_data(chip->dev,
2755 spmi_resource->of_node);
2756 if (!init_data) {
2757 pr_err("unable to allocate memory\n");
2758 return -ENOMEM;
2759 }
2760
2761 if (init_data->constraints.name) {
2762 if (of_get_property(chip->dev->of_node,
2763 "otg-parent-supply", NULL))
2764 init_data->supply_regulator = "otg-parent";
2765
2766 rdesc = &(chip->otg_vreg.rdesc);
2767 rdesc->owner = THIS_MODULE;
2768 rdesc->type = REGULATOR_VOLTAGE;
2769 rdesc->ops = &qpnp_chg_otg_reg_ops;
2770 rdesc->name = init_data->constraints.name;
2771
2772 init_data->constraints.valid_ops_mask
2773 |= REGULATOR_CHANGE_STATUS;
2774
2775 chip->otg_vreg.rdev = regulator_register(rdesc,
2776 chip->dev, init_data, chip,
2777 spmi_resource->of_node);
2778 if (IS_ERR(chip->otg_vreg.rdev)) {
2779 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07002780 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07002781 if (rc != -EPROBE_DEFER)
2782 pr_err("OTG reg failed, rc=%d\n", rc);
2783 return rc;
2784 }
2785 }
2786
David Keiteld681cda2012-10-02 15:44:21 -07002787 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08002788 chip->usb_chgpth_base + USB_OVP_CTL,
2789 USB_VALID_DEB_20MS,
2790 USB_VALID_DEB_20MS, 1);
2791
2792 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07002793 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
2794 ENUM_T_STOP_BIT,
2795 ENUM_T_STOP_BIT, 1);
2796
David Keitel344c6972013-04-09 19:28:21 -07002797 rc = qpnp_chg_masked_write(chip,
2798 chip->usb_chgpth_base + SEC_ACCESS,
2799 0xFF,
2800 0xA5, 1);
2801
2802 rc = qpnp_chg_masked_write(chip,
2803 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
2804 0xFF,
2805 0x80, 1);
2806
David Keitel80668952012-07-27 14:25:49 -07002807 break;
2808 case SMBB_DC_CHGPTH_SUBTYPE:
2809 break;
2810 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002811 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07002812 init_data = of_get_regulator_init_data(chip->dev,
2813 spmi_resource->of_node);
2814 if (!init_data) {
2815 pr_err("unable to allocate memory\n");
2816 return -ENOMEM;
2817 }
2818
2819 if (init_data->constraints.name) {
2820 if (of_get_property(chip->dev->of_node,
2821 "boost-parent-supply", NULL))
2822 init_data->supply_regulator = "boost-parent";
2823
2824 rdesc = &(chip->boost_vreg.rdesc);
2825 rdesc->owner = THIS_MODULE;
2826 rdesc->type = REGULATOR_VOLTAGE;
2827 rdesc->ops = &qpnp_chg_boost_reg_ops;
2828 rdesc->name = init_data->constraints.name;
2829
2830 init_data->constraints.valid_ops_mask
2831 |= REGULATOR_CHANGE_STATUS
2832 | REGULATOR_CHANGE_VOLTAGE;
2833
2834 chip->boost_vreg.rdev = regulator_register(rdesc,
2835 chip->dev, init_data, chip,
2836 spmi_resource->of_node);
2837 if (IS_ERR(chip->boost_vreg.rdev)) {
2838 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07002839 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07002840 if (rc != -EPROBE_DEFER)
2841 pr_err("boost reg failed, rc=%d\n", rc);
2842 return rc;
2843 }
2844 }
David Keitel80668952012-07-27 14:25:49 -07002845 break;
2846 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002847 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002848 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07002849 if (subtype == SMBB_MISC_SUBTYPE)
2850 chip->type = SMBB;
2851 else if (subtype == SMBBP_MISC_SUBTYPE)
2852 chip->type = SMBBP;
2853 else if (subtype == SMBCL_MISC_SUBTYPE)
2854 chip->type = SMBCL;
2855
David Keitel80668952012-07-27 14:25:49 -07002856 pr_debug("Setting BOOT_DONE\n");
2857 rc = qpnp_chg_masked_write(chip,
2858 chip->misc_base + CHGR_MISC_BOOT_DONE,
2859 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08002860 rc = qpnp_chg_read(chip, &reg,
2861 chip->misc_base + MISC_REVISION2, 1);
2862 if (rc) {
2863 pr_err("failed to read revision register rc=%d\n", rc);
2864 return rc;
2865 }
David Keitel80668952012-07-27 14:25:49 -07002866
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08002867 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07002868 break;
2869 default:
2870 pr_err("Invalid peripheral subtype\n");
2871 }
2872 return rc;
2873}
2874
David Keitel112ba9c2013-04-12 18:40:43 -07002875#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
2876do { \
2877 if (retval) \
2878 break; \
2879 \
2880 retval = of_property_read_u32(chip->spmi->dev.of_node, \
2881 "qcom," qpnp_dt_property, \
2882 &chip->prop); \
2883 \
2884 if ((retval == -EINVAL) && optional) \
2885 retval = 0; \
2886 else if (retval) \
2887 pr_err("Error reading " #qpnp_dt_property \
2888 " property rc = %d\n", rc); \
2889} while (0)
2890
2891static int
2892qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
2893{
2894 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07002895 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07002896
2897 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
2898 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
2899 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
2900 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
2901 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
2902 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
2903 if (rc)
2904 pr_err("failed to read required dt parameters %d\n", rc);
2905
2906 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
2907 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
2908 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
2909 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
2910 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07002911 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07002912 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
2913 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002914 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
2915
David Keitel112ba9c2013-04-12 18:40:43 -07002916 if (rc)
2917 return rc;
2918
David Keitel796882d2013-05-14 18:01:11 -07002919 rc = of_property_read_string(chip->spmi->dev.of_node,
2920 "qcom,bpd-detection", &bpd);
2921 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07002922 /* Select BAT_THM as default BPD scheme */
2923 chip->bpd_detection = BPD_TYPE_BAT_THM;
David Keitel796882d2013-05-14 18:01:11 -07002924 } else {
2925 chip->bpd_detection = get_bpd(bpd);
2926 if (chip->bpd_detection < 0) {
2927 pr_err("failed to determine bpd schema %d\n", rc);
2928 return rc;
2929 }
2930 }
2931
David Keitel112ba9c2013-04-12 18:40:43 -07002932 /* Look up JEITA compliance parameters if cool and warm temp provided */
2933 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
2934 rc = qpnp_adc_tm_is_ready();
2935 if (rc) {
2936 pr_err("tm not ready %d\n", rc);
2937 return rc;
2938 }
2939
2940 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
2941 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
2942 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
2943 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
2944 if (rc)
2945 return rc;
2946 }
2947
David Keitel89c17752013-06-28 14:52:48 -07002948 /* Get the btc-disabled property */
2949 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
2950 "qcom,btc-disabled");
2951
David Keitel112ba9c2013-04-12 18:40:43 -07002952 /* Get the charging-disabled property */
2953 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
2954 "qcom,charging-disabled");
2955
David Keitel8b68d2d2013-05-14 23:36:51 -07002956 /* Get the duty-cycle-100p property */
2957 chip->duty_cycle_100p = of_property_read_bool(
2958 chip->spmi->dev.of_node,
2959 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07002960
David Keitel112ba9c2013-04-12 18:40:43 -07002961 /* Get the fake-batt-values property */
2962 chip->use_default_batt_values =
2963 of_property_read_bool(chip->spmi->dev.of_node,
2964 "qcom,use-default-batt-values");
2965
2966 /* Disable charging when faking battery values */
2967 if (chip->use_default_batt_values)
2968 chip->charging_disabled = true;
2969
2970 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
2971 &(chip->thermal_levels));
2972
2973 if (chip->thermal_levels > sizeof(int)) {
2974 chip->thermal_mitigation = kzalloc(
2975 chip->thermal_levels,
2976 GFP_KERNEL);
2977
2978 if (chip->thermal_mitigation == NULL) {
2979 pr_err("thermal mitigation kzalloc() failed.\n");
2980 return rc;
2981 }
2982
2983 chip->thermal_levels /= sizeof(int);
2984 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
2985 "qcom,thermal-mitigation",
2986 chip->thermal_mitigation, chip->thermal_levels);
2987 if (rc) {
2988 pr_err("qcom,thermal-mitigation missing in dt\n");
2989 return rc;
2990 }
2991 }
2992
2993 return rc;
2994}
2995
David Keitel80668952012-07-27 14:25:49 -07002996static int __devinit
2997qpnp_charger_probe(struct spmi_device *spmi)
2998{
2999 u8 subtype;
3000 struct qpnp_chg_chip *chip;
3001 struct resource *resource;
3002 struct spmi_resource *spmi_resource;
3003 int rc = 0;
3004
3005 chip = kzalloc(sizeof *chip, GFP_KERNEL);
3006 if (chip == NULL) {
3007 pr_err("kzalloc() failed.\n");
3008 return -ENOMEM;
3009 }
3010
David Keitelfd305ee2013-07-19 20:19:06 -07003011 chip->prev_usb_max_ma = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07003012 chip->dev = &(spmi->dev);
3013 chip->spmi = spmi;
3014
3015 chip->usb_psy = power_supply_get_by_name("usb");
3016 if (!chip->usb_psy) {
3017 pr_err("usb supply not found deferring probe\n");
3018 rc = -EPROBE_DEFER;
3019 goto fail_chg_enable;
3020 }
3021
David Keitel112ba9c2013-04-12 18:40:43 -07003022 /* Get all device tree properties */
3023 rc = qpnp_charger_read_dt_props(chip);
3024 if (rc)
David Keitel80668952012-07-27 14:25:49 -07003025 goto fail_chg_enable;
David Keitel3dd5e0f2012-12-12 18:12:36 -08003026
Xiaozhe Shica289e02013-06-19 13:24:51 -07003027 /*
3028 * Check if bat_if is set in DT and make sure VADC is present
3029 * Also try loading the battery data profile if bat_if exists
3030 */
David Keiteldd87a172013-05-29 17:05:43 -07003031 spmi_for_each_container_dev(spmi_resource, spmi) {
3032 if (!spmi_resource) {
3033 pr_err("qpnp_chg: spmi resource absent\n");
3034 rc = -ENXIO;
3035 goto fail_chg_enable;
3036 }
3037
3038 resource = spmi_get_resource(spmi, spmi_resource,
3039 IORESOURCE_MEM, 0);
3040 if (!(resource && resource->start)) {
3041 pr_err("node %s IO resource absent!\n",
3042 spmi->dev.of_node->full_name);
3043 rc = -ENXIO;
3044 goto fail_chg_enable;
3045 }
3046
3047 rc = qpnp_chg_read(chip, &subtype,
3048 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
3049 if (rc) {
3050 pr_err("Peripheral subtype read failed rc=%d\n", rc);
3051 goto fail_chg_enable;
3052 }
3053
3054 if (subtype == SMBB_BAT_IF_SUBTYPE ||
3055 subtype == SMBBP_BAT_IF_SUBTYPE ||
3056 subtype == SMBCL_BAT_IF_SUBTYPE){
3057 rc = qpnp_vadc_is_ready();
3058 if (rc)
3059 goto fail_chg_enable;
Xiaozhe Shica289e02013-06-19 13:24:51 -07003060
3061 rc = qpnp_chg_load_battery_data(chip);
3062 if (rc)
3063 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07003064 }
3065 }
3066
David Keitel80668952012-07-27 14:25:49 -07003067 spmi_for_each_container_dev(spmi_resource, spmi) {
3068 if (!spmi_resource) {
3069 pr_err("qpnp_chg: spmi resource absent\n");
3070 rc = -ENXIO;
3071 goto fail_chg_enable;
3072 }
3073
3074 resource = spmi_get_resource(spmi, spmi_resource,
3075 IORESOURCE_MEM, 0);
3076 if (!(resource && resource->start)) {
3077 pr_err("node %s IO resource absent!\n",
3078 spmi->dev.of_node->full_name);
3079 rc = -ENXIO;
3080 goto fail_chg_enable;
3081 }
3082
3083 rc = qpnp_chg_read(chip, &subtype,
3084 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
3085 if (rc) {
3086 pr_err("Peripheral subtype read failed rc=%d\n", rc);
3087 goto fail_chg_enable;
3088 }
3089
3090 switch (subtype) {
3091 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003092 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003093 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003094 chip->chgr_base = resource->start;
3095 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3096 if (rc) {
3097 pr_err("Failed to init subtype 0x%x rc=%d\n",
3098 subtype, rc);
3099 goto fail_chg_enable;
3100 }
3101 break;
3102 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003103 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003104 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003105 chip->buck_base = resource->start;
3106 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3107 if (rc) {
3108 pr_err("Failed to init subtype 0x%x rc=%d\n",
3109 subtype, rc);
3110 goto fail_chg_enable;
3111 }
David Keitel344c6972013-04-09 19:28:21 -07003112
3113 rc = qpnp_chg_masked_write(chip,
3114 chip->buck_base + SEC_ACCESS,
3115 0xFF,
3116 0xA5, 1);
3117
3118 rc = qpnp_chg_masked_write(chip,
3119 chip->buck_base + BUCK_VCHG_OV,
3120 0xff,
3121 0x00, 1);
3122
3123 rc = qpnp_chg_masked_write(chip,
3124 chip->buck_base + SEC_ACCESS,
3125 0xFF,
3126 0xA5, 1);
3127
3128 rc = qpnp_chg_masked_write(chip,
3129 chip->buck_base + BUCK_TEST_SMBC_MODES,
3130 0xFF,
3131 0x80, 1);
3132
David Keiteldbc949b2013-07-11 10:56:03 -07003133 if (chip->duty_cycle_100p) {
3134 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
3135 1);
3136 if (rc) {
3137 pr_err("failed to set duty cycle %d\n",
3138 rc);
3139 goto fail_chg_enable;
3140 }
3141 }
3142
David Keitel80668952012-07-27 14:25:49 -07003143 break;
3144 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003145 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003146 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003147 chip->bat_if_base = resource->start;
3148 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3149 if (rc) {
3150 pr_err("Failed to init subtype 0x%x rc=%d\n",
3151 subtype, rc);
3152 goto fail_chg_enable;
3153 }
3154 break;
3155 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003156 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003157 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003158 chip->usb_chgpth_base = resource->start;
3159 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3160 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07003161 if (rc != -EPROBE_DEFER)
3162 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07003163 subtype, rc);
3164 goto fail_chg_enable;
3165 }
3166 break;
3167 case SMBB_DC_CHGPTH_SUBTYPE:
3168 chip->dc_chgpth_base = resource->start;
3169 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3170 if (rc) {
3171 pr_err("Failed to init subtype 0x%x rc=%d\n",
3172 subtype, rc);
3173 goto fail_chg_enable;
3174 }
3175 break;
3176 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003177 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003178 chip->boost_base = resource->start;
3179 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3180 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07003181 if (rc != -EPROBE_DEFER)
3182 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07003183 subtype, rc);
3184 goto fail_chg_enable;
3185 }
3186 break;
3187 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003188 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003189 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003190 chip->misc_base = resource->start;
3191 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3192 if (rc) {
3193 pr_err("Failed to init subtype=0x%x rc=%d\n",
3194 subtype, rc);
3195 goto fail_chg_enable;
3196 }
3197 break;
3198 default:
3199 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
3200 rc = -EINVAL;
3201 goto fail_chg_enable;
3202 }
3203 }
3204 dev_set_drvdata(&spmi->dev, chip);
3205 device_init_wakeup(&spmi->dev, 1);
3206
David Keitelf2170cc2013-02-20 17:49:03 -08003207 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08003208 chip->batt_psy.name = "battery";
3209 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
3210 chip->batt_psy.properties = msm_batt_power_props;
3211 chip->batt_psy.num_properties =
3212 ARRAY_SIZE(msm_batt_power_props);
3213 chip->batt_psy.get_property = qpnp_batt_power_get_property;
3214 chip->batt_psy.set_property = qpnp_batt_power_set_property;
3215 chip->batt_psy.property_is_writeable =
3216 qpnp_batt_property_is_writeable;
3217 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07003218 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07003219 chip->batt_psy.supplied_to = pm_batt_supplied_to;
3220 chip->batt_psy.num_supplicants =
3221 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07003222
David Keitelf2170cc2013-02-20 17:49:03 -08003223 rc = power_supply_register(chip->dev, &chip->batt_psy);
3224 if (rc < 0) {
3225 pr_err("batt failed to register rc = %d\n", rc);
3226 goto fail_chg_enable;
3227 }
David Keitel79f4c932013-04-03 16:08:39 -07003228 INIT_WORK(&chip->adc_measure_work,
3229 qpnp_bat_if_adc_measure_work);
David Keitelc7093b02013-02-14 12:50:04 -08003230 }
3231
David Keitel9fd07382013-05-02 15:37:44 -07003232 wake_lock_init(&chip->eoc_wake_lock,
3233 WAKE_LOCK_SUSPEND, "qpnp-chg-eoc-lock");
3234 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07003235 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
3236
David Keitelf2170cc2013-02-20 17:49:03 -08003237 if (chip->dc_chgpth_base) {
3238 chip->dc_psy.name = "qpnp-dc";
3239 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
3240 chip->dc_psy.supplied_to = pm_power_supplied_to;
3241 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
3242 chip->dc_psy.properties = pm_power_props_mains;
3243 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
3244 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07003245 chip->dc_psy.set_property = qpnp_dc_power_set_property;
3246 chip->dc_psy.property_is_writeable =
3247 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08003248
3249 rc = power_supply_register(chip->dev, &chip->dc_psy);
3250 if (rc < 0) {
3251 pr_err("power_supply_register dc failed rc=%d\n", rc);
3252 goto unregister_batt;
3253 }
David Keitel80668952012-07-27 14:25:49 -07003254 }
3255
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003256 /* Turn on appropriate workaround flags */
3257 qpnp_chg_setup_flags(chip);
3258
David Keitelf2170cc2013-02-20 17:49:03 -08003259 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08003260 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
3261 if (rc) {
3262 pr_err("Error setting idcmax property %d\n", rc);
David Keitelf2170cc2013-02-20 17:49:03 -08003263 goto unregister_batt;
David Keitel22ed2232013-01-28 11:04:07 -08003264 }
3265 }
3266
David Keitel0aea18a2013-06-14 18:57:57 -07003267 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
3268 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07003269 chip->adc_param.low_temp = chip->cool_bat_decidegc;
3270 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08003271 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
3272 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
3273 chip->adc_param.btm_ctx = chip;
3274 chip->adc_param.threshold_notification =
3275 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08003276 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07003277
3278 if (get_prop_batt_present(chip)) {
3279 rc = qpnp_adc_tm_channel_measure(&chip->adc_param);
3280 if (rc) {
3281 pr_err("request ADC error %d\n", rc);
3282 goto fail_chg_enable;
3283 }
David Keitel454ee842013-03-08 16:19:11 -08003284 }
3285 }
David Keitel89c17752013-06-28 14:52:48 -07003286 rc = qpnp_chg_bat_if_configure_btc(chip);
3287 if (rc) {
3288 pr_err("failed to configure btc %d\n", rc);
3289 goto unregister_batt;
3290 }
David Keitel454ee842013-03-08 16:19:11 -08003291
David Keitel03ee6b52012-10-22 12:25:19 -07003292 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08003293 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003294 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07003295
David Keitel0f35be42013-04-16 11:10:40 -07003296 rc = qpnp_chg_request_irqs(chip);
3297 if (rc) {
3298 pr_err("failed to request interrupts %d\n", rc);
3299 goto unregister_batt;
3300 }
3301
David Keitel9fd07382013-05-02 15:37:44 -07003302 qpnp_chg_usb_usbin_valid_irq_handler(USBIN_VALID_IRQ, chip);
David Keiteld2efc392013-06-05 16:27:12 -07003303 qpnp_chg_dc_dcin_valid_irq_handler(DCIN_VALID_IRQ, chip);
David Keitel9fd07382013-05-02 15:37:44 -07003304 power_supply_set_present(chip->usb_psy,
3305 qpnp_chg_is_usb_chg_plugged_in(chip));
3306
David Keitel3c62b472013-05-06 15:38:11 -07003307 /* Set USB psy online to avoid userspace from shutting down if battery
3308 * capacity is at zero and no chargers online. */
3309 if (qpnp_chg_is_usb_chg_plugged_in(chip))
3310 power_supply_set_online(chip->usb_psy, 1);
3311
David Keitel796882d2013-05-14 18:01:11 -07003312 pr_info("success chg_dis = %d, bpd = %d, usb = %d, dc = %d b_health = %d batt_present = %d\n",
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08003313 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07003314 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08003315 qpnp_chg_is_usb_chg_plugged_in(chip),
3316 qpnp_chg_is_dc_chg_plugged_in(chip),
3317 get_prop_batt_present(chip),
3318 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07003319 return 0;
3320
David Keitelc7093b02013-02-14 12:50:04 -08003321unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08003322 if (chip->bat_if_base)
3323 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07003324fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07003325 regulator_unregister(chip->otg_vreg.rdev);
3326 regulator_unregister(chip->boost_vreg.rdev);
David Keitelbe208252013-01-31 14:49:25 -08003327 kfree(chip->thermal_mitigation);
David Keitel80668952012-07-27 14:25:49 -07003328 kfree(chip);
3329 dev_set_drvdata(&spmi->dev, NULL);
3330 return rc;
3331}
3332
3333static int __devexit
3334qpnp_charger_remove(struct spmi_device *spmi)
3335{
3336 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
David Keitel0c1a4532013-03-21 16:39:06 -07003337 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
3338 && chip->batt_present) {
3339 qpnp_adc_tm_disable_chan_meas(&chip->adc_param);
3340 }
David Keitel79f4c932013-04-03 16:08:39 -07003341 cancel_work_sync(&chip->adc_measure_work);
David Keitel9fd07382013-05-02 15:37:44 -07003342 cancel_delayed_work_sync(&chip->eoc_work);
David Keitel79f4c932013-04-03 16:08:39 -07003343
David Collinscbb12132013-05-28 10:47:28 -07003344 regulator_unregister(chip->otg_vreg.rdev);
3345 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07003346
David Keitel80668952012-07-27 14:25:49 -07003347 dev_set_drvdata(&spmi->dev, NULL);
3348 kfree(chip);
3349
3350 return 0;
3351}
3352
David Keitel85ae4342013-04-16 11:46:00 -07003353static int qpnp_chg_resume(struct device *dev)
3354{
3355 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
3356 int rc = 0;
3357
David Keitel39093572013-06-05 15:32:30 -07003358 if (chip->bat_if_base) {
3359 rc = qpnp_chg_masked_write(chip,
3360 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
3361 VREF_BATT_THERM_FORCE_ON,
3362 VREF_BATT_THERM_FORCE_ON, 1);
3363 if (rc)
3364 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
3365 }
David Keitel85ae4342013-04-16 11:46:00 -07003366
3367 return rc;
3368}
3369
3370static int qpnp_chg_suspend(struct device *dev)
3371{
3372 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
3373 int rc = 0;
3374
David Keitel39093572013-06-05 15:32:30 -07003375 if (chip->bat_if_base) {
3376 rc = qpnp_chg_masked_write(chip,
3377 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
3378 VREF_BATT_THERM_FORCE_ON,
3379 VREF_BAT_THM_ENABLED_FSM, 1);
3380 if (rc)
3381 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
3382 }
David Keitel85ae4342013-04-16 11:46:00 -07003383
3384 return rc;
3385}
3386
David Keitel337bd862013-07-15 21:42:58 -07003387static int
3388qpnp_chg_ops_set(const char *val, const struct kernel_param *kp)
3389{
3390 return -EINVAL;
3391}
3392
3393#define MAX_LEN_VADC 10
3394static int
3395qpnp_chg_usb_in_get(char *val, const struct kernel_param *kp)
3396{
3397 int rc;
3398 struct qpnp_vadc_result results;
3399
3400 rc = qpnp_vadc_is_ready();
3401 if (rc)
3402 return rc;
3403
3404 rc = qpnp_vadc_read(USBIN, &results);
3405 if (rc) {
3406 pr_err("Unable to read vchg rc=%d\n", rc);
3407 return 0;
3408 }
3409 rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
3410
3411 return rc;
3412}
3413
3414static int
3415qpnp_chg_vchg_get(char *val, const struct kernel_param *kp)
3416{
3417 int rc;
3418 struct qpnp_vadc_result results;
3419
3420 rc = qpnp_vadc_is_ready();
3421 if (rc)
3422 return rc;
3423
3424 rc = qpnp_vadc_read(VCHG_SNS, &results);
3425 if (rc) {
3426 pr_err("Unable to read vchg rc=%d\n", rc);
3427 return 0;
3428 }
3429 rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
3430
3431 return rc;
3432}
3433
3434static struct kernel_param_ops usb_in_uv_param_ops = {
3435 .set = qpnp_chg_ops_set,
3436 .get = qpnp_chg_usb_in_get,
3437};
3438
3439static struct kernel_param_ops vchg_uv_param_ops = {
3440 .set = qpnp_chg_ops_set,
3441 .get = qpnp_chg_vchg_get,
3442};
3443
3444module_param_cb(usb_in_uv, &usb_in_uv_param_ops, NULL, 0644);
3445module_param_cb(vchg_uv, &vchg_uv_param_ops, NULL, 0644);
3446
David Keitel723d5012013-05-03 13:17:27 -07003447static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07003448 .resume = qpnp_chg_resume,
3449 .suspend = qpnp_chg_suspend,
3450};
3451
David Keitel80668952012-07-27 14:25:49 -07003452static struct spmi_driver qpnp_charger_driver = {
3453 .probe = qpnp_charger_probe,
3454 .remove = __devexit_p(qpnp_charger_remove),
3455 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07003456 .name = QPNP_CHARGER_DEV_NAME,
3457 .owner = THIS_MODULE,
3458 .of_match_table = qpnp_charger_match_table,
3459 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07003460 },
3461};
3462
3463/**
3464 * qpnp_chg_init() - register spmi driver for qpnp-chg
3465 */
3466int __init
3467qpnp_chg_init(void)
3468{
3469 return spmi_driver_register(&qpnp_charger_driver);
3470}
3471module_init(qpnp_chg_init);
3472
3473static void __exit
3474qpnp_chg_exit(void)
3475{
3476 spmi_driver_unregister(&qpnp_charger_driver);
3477}
3478module_exit(qpnp_chg_exit);
3479
3480
3481MODULE_DESCRIPTION("QPNP charger driver");
3482MODULE_LICENSE("GPL v2");
3483MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);