blob: 0bf8e5aeeda0c296db3ae19f2200e18c6b6a6e6d [file] [log] [blame]
David Keitela8099ff2014-01-06 11:31:40 -08001/* Copyright (c) 2012-2014, 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>
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -070032#include <linux/qpnp-revid.h>
Matt Mowera0f9b392015-10-12 19:37:46 -050033#ifdef CONFIG_ANDROID_INTF_ALARM_DEV
34#include <linux/alarmtimer.h>
35#else
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -070036#include <linux/android_alarm.h>
Matt Mowera0f9b392015-10-12 19:37:46 -050037#endif
Wu Fenglin04ae6de2013-09-09 19:15:06 +080038#include <linux/spinlock.h>
David Keitelcd2e1022014-05-02 17:25:15 -070039#include <linux/gpio.h>
40#include <linux/of_gpio.h>
41#include <linux/qpnp/pin.h>
David Keitel80668952012-07-27 14:25:49 -070042
43/* Interrupt offsets */
44#define INT_RT_STS(base) (base + 0x10)
45#define INT_SET_TYPE(base) (base + 0x11)
46#define INT_POLARITY_HIGH(base) (base + 0x12)
47#define INT_POLARITY_LOW(base) (base + 0x13)
48#define INT_LATCHED_CLR(base) (base + 0x14)
49#define INT_EN_SET(base) (base + 0x15)
50#define INT_EN_CLR(base) (base + 0x16)
51#define INT_LATCHED_STS(base) (base + 0x18)
52#define INT_PENDING_STS(base) (base + 0x19)
53#define INT_MID_SEL(base) (base + 0x1A)
54#define INT_PRIORITY(base) (base + 0x1B)
55
56/* Peripheral register offsets */
57#define CHGR_CHG_OPTION 0x08
58#define CHGR_ATC_STATUS 0x0A
59#define CHGR_VBAT_STATUS 0x0B
60#define CHGR_IBAT_BMS 0x0C
61#define CHGR_IBAT_STS 0x0D
62#define CHGR_VDD_MAX 0x40
63#define CHGR_VDD_SAFE 0x41
64#define CHGR_VDD_MAX_STEP 0x42
65#define CHGR_IBAT_MAX 0x44
66#define CHGR_IBAT_SAFE 0x45
67#define CHGR_VIN_MIN 0x47
68#define CHGR_VIN_MIN_STEP 0x48
69#define CHGR_CHG_CTRL 0x49
70#define CHGR_CHG_FAILED 0x4A
71#define CHGR_ATC_CTRL 0x4B
72#define CHGR_ATC_FAILED 0x4C
73#define CHGR_VBAT_TRKL 0x50
74#define CHGR_VBAT_WEAK 0x52
75#define CHGR_IBAT_ATC_A 0x54
76#define CHGR_IBAT_ATC_B 0x55
77#define CHGR_IBAT_TERM_CHGR 0x5B
78#define CHGR_IBAT_TERM_BMS 0x5C
79#define CHGR_VBAT_DET 0x5D
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -080080#define CHGR_TTRKL_MAX_EN 0x5E
David Keitel80668952012-07-27 14:25:49 -070081#define CHGR_TTRKL_MAX 0x5F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -080082#define CHGR_TCHG_MAX_EN 0x60
David Keitel80668952012-07-27 14:25:49 -070083#define CHGR_TCHG_MAX 0x61
84#define CHGR_CHG_WDOG_TIME 0x62
85#define CHGR_CHG_WDOG_DLY 0x63
86#define CHGR_CHG_WDOG_PET 0x64
87#define CHGR_CHG_WDOG_EN 0x65
David Keitel9201df32013-01-10 18:38:34 -080088#define CHGR_IR_DROP_COMPEN 0x67
wangxlbe091422014-12-31 10:08:48 +080089#ifdef CONFIG_TCMD
90#define CHGR_USB_PRIORITY_SEL 0x40
91#endif
David Keitel22ed2232013-01-28 11:04:07 -080092#define CHGR_I_MAX_REG 0x44
David Keiteld681cda2012-10-02 15:44:21 -070093#define CHGR_USB_USB_SUSP 0x47
David Keitel6f865cd2012-11-30 15:04:32 -080094#define CHGR_USB_USB_OTG_CTL 0x48
David Keitel80668952012-07-27 14:25:49 -070095#define CHGR_USB_ENUM_T_STOP 0x4E
David Keitel2586f0a2013-08-20 10:02:26 -070096#define CHGR_USB_TRIM 0xF1
David Keitel80668952012-07-27 14:25:49 -070097#define CHGR_CHG_TEMP_THRESH 0x66
98#define CHGR_BAT_IF_PRES_STATUS 0x08
David Keiteld681cda2012-10-02 15:44:21 -070099#define CHGR_STATUS 0x09
David Keitel80668952012-07-27 14:25:49 -0700100#define CHGR_BAT_IF_VCP 0x42
101#define CHGR_BAT_IF_BATFET_CTRL1 0x90
David Keitel9eca8ac2013-09-06 14:18:36 -0700102#define CHGR_BAT_IF_BATFET_CTRL4 0x93
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -0700103#define CHGR_BAT_IF_SPARE 0xDF
David Keitel80668952012-07-27 14:25:49 -0700104#define CHGR_MISC_BOOT_DONE 0x42
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700105#define CHGR_BUCK_PSTG_CTRL 0x73
David Keitel9fd07382013-05-02 15:37:44 -0700106#define CHGR_BUCK_COMPARATOR_OVRIDE_1 0xEB
Fenglin Wuc64e9942014-08-22 13:47:34 +0800107#define CHGR_BUCK_COMPARATOR_OVRIDE_2 0xEC
David Keiteld681cda2012-10-02 15:44:21 -0700108#define CHGR_BUCK_COMPARATOR_OVRIDE_3 0xED
David Keitel79e08322014-04-21 14:17:05 -0700109#define CHG_OVR0 0xED
110#define CHG_TRICKLE_CLAMP 0xE3
David Keitel9201df32013-01-10 18:38:34 -0800111#define CHGR_BUCK_BCK_VBAT_REG_MODE 0x74
Sridhar Parasuramae183bd2012-12-21 09:28:46 -0800112#define MISC_REVISION2 0x01
David Keitel5c3a7702012-12-20 11:13:21 -0800113#define USB_OVP_CTL 0x42
David Keitel344c6972013-04-09 19:28:21 -0700114#define USB_CHG_GONE_REV_BST 0xED
115#define BUCK_VCHG_OV 0x77
116#define BUCK_TEST_SMBC_MODES 0xE6
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700117#define BUCK_CTRL_TRIM1 0xF1
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700118#define BUCK_CTRL_TRIM3 0xF3
David Keiteld681cda2012-10-02 15:44:21 -0700119#define SEC_ACCESS 0xD0
David Keitel85ae4342013-04-16 11:46:00 -0700120#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
David Keitel796882d2013-05-14 18:01:11 -0700121#define BAT_IF_BPD_CTRL 0x48
David Keitel6dc4ed42013-05-17 11:08:58 -0700122#define BOOST_VSET 0x41
123#define BOOST_ENABLE_CONTROL 0x46
David Keitel33f58952013-05-20 16:17:36 -0700124#define COMP_OVR1 0xEA
David Keitel89c17752013-06-28 14:52:48 -0700125#define BAT_IF_BTC_CTRL 0x49
David Keitel0b62bdd2013-07-10 17:30:51 -0700126#define USB_OCP_THR 0x52
127#define USB_OCP_CLR 0x53
Zhenhua Huang2a0ee352013-07-23 01:55:43 +0800128#define BAT_IF_TEMP_STATUS 0x09
David Keitel8b9bd312014-01-15 14:44:00 -0800129#define BOOST_ILIM 0x78
David Keitel975b5352014-01-27 14:28:04 -0800130#define USB_SPARE 0xDF
131#define DC_COMP_OVR1 0xE9
David Keitel59fbb762014-02-05 16:46:24 -0800132#define CHGR_COMP_OVR1 0xEE
David Keitel820a90d2014-03-25 18:18:04 -0700133#define USB_CHGPTH_CTL 0x40
David Keitel80668952012-07-27 14:25:49 -0700134#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700135
David Keitelf2170cc2013-02-20 17:49:03 -0800136/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700137#define SMBB_CHGR_SUBTYPE 0x01
138#define SMBB_BUCK_SUBTYPE 0x02
139#define SMBB_BAT_IF_SUBTYPE 0x03
140#define SMBB_USB_CHGPTH_SUBTYPE 0x04
141#define SMBB_DC_CHGPTH_SUBTYPE 0x05
142#define SMBB_BOOST_SUBTYPE 0x06
143#define SMBB_MISC_SUBTYPE 0x07
144
David Keitelf2170cc2013-02-20 17:49:03 -0800145/* SMBB peripheral subtype values */
146#define SMBBP_CHGR_SUBTYPE 0x31
147#define SMBBP_BUCK_SUBTYPE 0x32
148#define SMBBP_BAT_IF_SUBTYPE 0x33
149#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
150#define SMBBP_BOOST_SUBTYPE 0x36
151#define SMBBP_MISC_SUBTYPE 0x37
152
David Keitel46c9f7b2013-04-02 19:54:12 -0700153/* SMBCL peripheral subtype values */
154#define SMBCL_CHGR_SUBTYPE 0x41
155#define SMBCL_BUCK_SUBTYPE 0x42
156#define SMBCL_BAT_IF_SUBTYPE 0x43
157#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
158#define SMBCL_MISC_SUBTYPE 0x47
159
David Keitel80668952012-07-27 14:25:49 -0700160#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
161
David Keitelb80eda82012-10-15 10:49:11 -0700162/* Status bits and masks */
163#define CHGR_BOOT_DONE BIT(7)
164#define CHGR_CHG_EN BIT(7)
165#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800166#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800167#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700168#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700169#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700170#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700171#define REV_BST_DETECTED BIT(0)
172#define BAT_THM_EN BIT(1)
173#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700174#define BOOST_PWR_EN BIT(7)
David Keitel0b62bdd2013-07-10 17:30:51 -0700175#define OCP_CLR_BIT BIT(7)
176#define OCP_THR_MASK 0x03
177#define OCP_THR_900_MA 0x02
178#define OCP_THR_500_MA 0x01
179#define OCP_THR_200_MA 0x00
David Keitel820a90d2014-03-25 18:18:04 -0700180#define DC_HIGHER_PRIORITY BIT(7)
wangxlbe091422014-12-31 10:08:48 +0800181#ifdef CONFIG_TCMD
182#define CHG_PTH_PRIORITY_SEL BIT(7)
183#endif
David Keitel80668952012-07-27 14:25:49 -0700184/* Interrupt definitions */
185/* smbb_chg_interrupts */
186#define CHG_DONE_IRQ BIT(7)
187#define CHG_FAILED_IRQ BIT(6)
188#define FAST_CHG_ON_IRQ BIT(5)
189#define TRKL_CHG_ON_IRQ BIT(4)
190#define STATE_CHANGE_ON_IR BIT(3)
191#define CHGWDDOG_IRQ BIT(2)
192#define VBAT_DET_HI_IRQ BIT(1)
193#define VBAT_DET_LOW_IRQ BIT(0)
194
195/* smbb_buck_interrupts */
196#define VDD_LOOP_IRQ BIT(6)
197#define IBAT_LOOP_IRQ BIT(5)
198#define ICHG_LOOP_IRQ BIT(4)
199#define VCHG_LOOP_IRQ BIT(3)
200#define OVERTEMP_IRQ BIT(2)
201#define VREF_OV_IRQ BIT(1)
202#define VBAT_OV_IRQ BIT(0)
203
204/* smbb_bat_if_interrupts */
205#define PSI_IRQ BIT(4)
206#define VCP_ON_IRQ BIT(3)
207#define BAT_FET_ON_IRQ BIT(2)
208#define BAT_TEMP_OK_IRQ BIT(1)
209#define BATT_PRES_IRQ BIT(0)
210
211/* smbb_usb_interrupts */
212#define CHG_GONE_IRQ BIT(2)
213#define USBIN_VALID_IRQ BIT(1)
214#define COARSE_DET_USB_IRQ BIT(0)
215
216/* smbb_dc_interrupts */
217#define DCIN_VALID_IRQ BIT(1)
218#define COARSE_DET_DC_IRQ BIT(0)
219
220/* smbb_boost_interrupts */
221#define LIMIT_ERROR_IRQ BIT(1)
222#define BOOST_PWR_OK_IRQ BIT(0)
223
224/* smbb_misc_interrupts */
225#define TFTWDOG_IRQ BIT(0)
226
David Keitelfe51cb92013-04-02 19:42:58 -0700227/* SMBB types */
228#define SMBB BIT(1)
229#define SMBBP BIT(2)
230#define SMBCL BIT(3)
231
David Keiteld681cda2012-10-02 15:44:21 -0700232/* Workaround flags */
233#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700234#define BOOST_FLASH_WA BIT(1)
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700235#define POWER_STAGE_WA BIT(2)
David Keiteld681cda2012-10-02 15:44:21 -0700236
David Keitel47185a62013-05-15 18:54:10 -0700237struct qpnp_chg_irq {
David Keitel9879e2a2013-06-28 18:40:22 -0700238 int irq;
David Keitel47185a62013-05-15 18:54:10 -0700239 unsigned long disabled;
David Keitelbf6a1062014-01-23 10:57:36 -0800240 unsigned long wake_enable;
Fenglin Wu67aa2ca2015-01-20 16:40:11 +0800241 bool is_wake;
David Keitel47185a62013-05-15 18:54:10 -0700242};
243
David Keitel6dc4ed42013-05-17 11:08:58 -0700244struct qpnp_chg_regulator {
245 struct regulator_desc rdesc;
246 struct regulator_dev *rdev;
247};
248
David Keitel80668952012-07-27 14:25:49 -0700249/**
250 * struct qpnp_chg_chip - device information
251 * @dev: device pointer to access the parent
252 * @spmi: spmi pointer to access spmi information
253 * @chgr_base: charger peripheral base address
254 * @buck_base: buck peripheral base address
255 * @bat_if_base: battery interface peripheral base address
256 * @usb_chgpth_base: USB charge path peripheral base address
257 * @dc_chgpth_base: DC charge path peripheral base address
258 * @boost_base: boost peripheral base address
259 * @misc_base: misc peripheral base address
260 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800261 * @bat_is_cool: indicates that battery is cool
262 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700263 * @chg_done: indicates that charging is completed
264 * @usb_present: present status of usb
265 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800266 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800267 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700268 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700269 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800270 * @min_voltage_mv: min battery voltage before turning the FET on
Prasad Sodagudic3678012013-09-23 12:01:19 +0530271 * @batt_weak_voltage_mv: Weak battery voltage threshold
David Keitelbdbae452014-01-14 17:19:50 -0800272 * @vbatdet_max_err_mv resume voltage hysterisis
David Keitel454ee842013-03-08 16:19:11 -0800273 * @max_bat_chg_current: maximum battery charge current in mA
274 * @warm_bat_chg_ma: warm battery maximum charge current in mA
275 * @cool_bat_chg_ma: cool battery maximum charge current in mA
276 * @warm_bat_mv: warm temperature battery target voltage
277 * @cool_bat_mv: cool temperature battery target voltage
278 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700279 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800280 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800281 * @maxinput_usb_ma: Maximum Input current USB
282 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700283 * @hot_batt_p Hot battery threshold setting
284 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700285 * @warm_bat_decidegc Warm battery temperature in degree Celsius
286 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700287 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700288 * @type: SMBB type
289 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800290 * @thermal_levels amount of thermal mitigation levels
291 * @thermal_mitigation thermal mitigation level values
292 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700293 * @dc_psy power supply to export information to userspace
294 * @usb_psy power supply to export information to userspace
295 * @bms_psy power supply to export information to userspace
296 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700297 * @flags: flags to activate specific workarounds
298 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700299 *
300 */
301struct qpnp_chg_chip {
302 struct device *dev;
303 struct spmi_device *spmi;
304 u16 chgr_base;
305 u16 buck_base;
306 u16 bat_if_base;
307 u16 usb_chgpth_base;
308 u16 dc_chgpth_base;
309 u16 boost_base;
310 u16 misc_base;
311 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700312 struct qpnp_chg_irq usbin_valid;
David Keitel0b62bdd2013-07-10 17:30:51 -0700313 struct qpnp_chg_irq usb_ocp;
David Keitel47185a62013-05-15 18:54:10 -0700314 struct qpnp_chg_irq dcin_valid;
315 struct qpnp_chg_irq chg_gone;
316 struct qpnp_chg_irq chg_fastchg;
317 struct qpnp_chg_irq chg_trklchg;
318 struct qpnp_chg_irq chg_failed;
319 struct qpnp_chg_irq chg_vbatdet_lo;
320 struct qpnp_chg_irq batt_pres;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700321 struct qpnp_chg_irq batt_temp_ok;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800322 struct qpnp_chg_irq coarse_det_usb;
David Keitel454ee842013-03-08 16:19:11 -0800323 bool bat_is_cool;
324 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700325 bool chg_done;
David Keitel7ac385e2013-08-19 18:02:40 -0700326 bool charger_monitor_checked;
David Keitel80668952012-07-27 14:25:49 -0700327 bool usb_present;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800328 u8 usbin_health;
329 bool usb_coarse_det;
David Keitel80668952012-07-27 14:25:49 -0700330 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800331 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700332 bool charging_disabled;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800333 bool ovp_monitor_enable;
334 bool usb_valid_check_ovp;
David Keitel89c17752013-06-28 14:52:48 -0700335 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800336 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700337 bool duty_cycle_100p;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700338 bool ibat_calibration_enabled;
339 bool aicl_settled;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800340 bool use_external_rsense;
Wu Fenglin64fb1ac2013-11-08 10:20:14 +0800341 bool fastchg_on;
David Keitel975b5352014-01-27 14:28:04 -0800342 bool parallel_ovp_mode;
David Keitel796882d2013-05-14 18:01:11 -0700343 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700344 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800345 unsigned int warm_bat_chg_ma;
346 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700347 unsigned int safe_voltage_mv;
348 unsigned int max_voltage_mv;
349 unsigned int min_voltage_mv;
Prasad Sodagudic3678012013-09-23 12:01:19 +0530350 unsigned int batt_weak_voltage_mv;
David Keitelbdbae452014-01-14 17:19:50 -0800351 unsigned int vbatdet_max_err_mv;
David Keitelfd305ee2013-07-19 20:19:06 -0700352 int prev_usb_max_ma;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700353 int set_vddmax_mv;
354 int delta_vddmax_mv;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700355 u8 trim_center;
David Keitel454ee842013-03-08 16:19:11 -0800356 unsigned int warm_bat_mv;
357 unsigned int cool_bat_mv;
358 unsigned int resume_delta_mv;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700359 int insertion_ocv_uv;
David Keitel9fd07382013-05-02 15:37:44 -0700360 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700361 int soc_resume_limit;
362 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800363 unsigned int maxinput_usb_ma;
364 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700365 unsigned int hot_batt_p;
366 unsigned int cold_batt_p;
David Keitel27a97e62013-06-24 13:57:12 -0700367 int warm_bat_decidegc;
368 int cool_bat_decidegc;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -0800369 int fake_battery_soc;
David Keitel5d44fa52012-12-03 16:37:31 -0800370 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700371 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700372 unsigned int type;
373 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800374 unsigned int thermal_levels;
375 unsigned int therm_lvl_sel;
376 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700377 struct power_supply dc_psy;
378 struct power_supply *usb_psy;
379 struct power_supply *bms_psy;
380 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700381 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800382 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700383 struct work_struct adc_measure_work;
David Keitelecab15a2013-08-06 15:41:39 -0700384 struct work_struct adc_disable_work;
David Keitel344c6972013-04-09 19:28:21 -0700385 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700386 struct delayed_work eoc_work;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800387 struct delayed_work usbin_health_check;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -0700388 struct work_struct soc_check_work;
David Keitel7ac385e2013-08-19 18:02:40 -0700389 struct delayed_work aicl_check_work;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700390 struct work_struct insertion_ocv_work;
David Keitel8b9bd312014-01-15 14:44:00 -0800391 struct work_struct ocp_clear_work;
Chunmei Cai661a7cd2014-08-05 17:31:54 +0800392 struct qpnp_chg_regulator flash_wa_vreg;
David Keitel6dc4ed42013-05-17 11:08:58 -0700393 struct qpnp_chg_regulator otg_vreg;
394 struct qpnp_chg_regulator boost_vreg;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -0700395 struct qpnp_chg_regulator batfet_vreg;
David Keitel6e63bd52013-09-06 18:00:03 -0700396 bool batfet_ext_en;
397 struct work_struct batfet_lcl_work;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700398 struct qpnp_vadc_chip *vadc_dev;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800399 struct qpnp_iadc_chip *iadc_dev;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -0700400 struct qpnp_adc_tm_chip *adc_tm_dev;
David Keitelec3c09802013-06-13 13:05:30 -0700401 struct mutex jeita_configure_lock;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800402 spinlock_t usbin_health_monitor_lock;
David Keitel6e63bd52013-09-06 18:00:03 -0700403 struct mutex batfet_vreg_lock;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700404 struct alarm reduce_power_stage_alarm;
405 struct work_struct reduce_power_stage_work;
406 bool power_stage_workaround_running;
Zhenhua Huangdc335512013-10-30 11:45:15 +0800407 bool power_stage_workaround_enable;
Chunmei Cai661a7cd2014-08-05 17:31:54 +0800408 bool is_flash_wa_reg_enabled;
David Keitelcd2e1022014-05-02 17:25:15 -0700409 bool ext_ovp_ic_gpio_enabled;
410 unsigned int ext_ovp_isns_gpio;
411 unsigned int usb_trim_default;
Chunmei Cai661a7cd2014-08-05 17:31:54 +0800412 u8 chg_temp_thresh_default;
David Keitel80668952012-07-27 14:25:49 -0700413};
414
David Keitel59fbb762014-02-05 16:46:24 -0800415static void
416qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip);
David Keitel47185a62013-05-15 18:54:10 -0700417
David Keitel80668952012-07-27 14:25:49 -0700418static struct of_device_id qpnp_charger_match_table[] = {
419 { .compatible = QPNP_CHARGER_DEV_NAME, },
420 {}
421};
422
David Keitel0ef282b2013-05-29 16:04:57 -0700423enum bpd_type {
424 BPD_TYPE_BAT_ID,
425 BPD_TYPE_BAT_THM,
426 BPD_TYPE_BAT_THM_BAT_ID,
427};
David Keitel796882d2013-05-14 18:01:11 -0700428
David Keitel0ef282b2013-05-29 16:04:57 -0700429static const char * const bpd_label[] = {
430 [BPD_TYPE_BAT_ID] = "bpd_id",
431 [BPD_TYPE_BAT_THM] = "bpd_thm",
432 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700433};
434
David Keitel89c17752013-06-28 14:52:48 -0700435enum btc_type {
436 HOT_THD_25_PCT = 25,
437 HOT_THD_35_PCT = 35,
438 COLD_THD_70_PCT = 70,
439 COLD_THD_80_PCT = 80,
440};
441
442static u8 btc_value[] = {
443 [HOT_THD_25_PCT] = 0x0,
444 [HOT_THD_35_PCT] = BIT(0),
445 [COLD_THD_70_PCT] = 0x0,
446 [COLD_THD_80_PCT] = BIT(1),
447};
448
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800449enum usbin_health {
450 USBIN_UNKNOW,
451 USBIN_OK,
452 USBIN_OVP,
453};
454
David Keitelcd2e1022014-05-02 17:25:15 -0700455static int ext_ovp_isns_present;
456module_param(ext_ovp_isns_present, int, 0444);
457static int ext_ovp_isns_r;
458module_param(ext_ovp_isns_r, int, 0444);
459
460static bool ext_ovp_isns_online;
461static long ext_ovp_isns_ua;
462#define MAX_CURRENT_LENGTH_9A 10
463#define ISNS_CURRENT_RATIO 2500
464static int ext_ovp_isns_read(char *buffer, const struct kernel_param *kp)
465{
466 int rc;
467 struct qpnp_vadc_result results;
468 struct power_supply *batt_psy = power_supply_get_by_name("battery");
469 struct qpnp_chg_chip *chip = container_of(batt_psy,
470 struct qpnp_chg_chip, batt_psy);
471
472 if (!ext_ovp_isns_present)
473 return 0;
474
475 rc = qpnp_vadc_read(chip->vadc_dev, P_MUX7_1_1, &results);
476 if (rc) {
477 pr_err("Unable to read vbat rc=%d\n", rc);
478 return 0;
479 }
480
481 pr_debug("voltage %lld uV, current: %d\n mA", results.physical,
482 ((int) results.physical /
483 (ext_ovp_isns_r / ISNS_CURRENT_RATIO)));
484
485 return snprintf(buffer, MAX_CURRENT_LENGTH_9A, "%d\n",
486 ((int)results.physical /
487 (ext_ovp_isns_r / ISNS_CURRENT_RATIO)));
488}
489
490static int ext_ovp_isns_enable(const char *val, const struct kernel_param *kp)
491{
492 int rc;
493 struct power_supply *batt_psy = power_supply_get_by_name("battery");
494 struct qpnp_chg_chip *chip = container_of(batt_psy,
495 struct qpnp_chg_chip, batt_psy);
496
497 rc = param_set_bool(val, kp);
498 if (rc) {
499 pr_err("Unable to set gpio en: %d\n", rc);
500 return rc;
501 }
502
503 if (*(bool *)kp->arg) {
504 gpio_direction_output(
505 chip->ext_ovp_isns_gpio, 1);
506 chip->ext_ovp_ic_gpio_enabled = 1;
507 pr_debug("enabled GPIO\n");
508 } else {
509 gpio_direction_output(
510 chip->ext_ovp_isns_gpio, 0);
511 chip->ext_ovp_ic_gpio_enabled = 0;
512 pr_debug("disabled GPIO\n");
513 }
514
515 return rc;
516}
517
518static struct kernel_param_ops ext_ovp_isns_ops = {
519 .get = ext_ovp_isns_read,
520};
521module_param_cb(ext_ovp_isns_ua, &ext_ovp_isns_ops, &ext_ovp_isns_ua, 0644);
522
523static struct kernel_param_ops ext_ovp_en_ops = {
524 .set = ext_ovp_isns_enable,
525 .get = param_get_bool,
526};
527module_param_cb(ext_ovp_isns_online, &ext_ovp_en_ops,
528 &ext_ovp_isns_online, 0664);
529
wangxlee3614a2015-02-03 13:13:11 +0800530#ifdef CONFIG_TCMD
531static struct qpnp_chg_chip *the_chip;
532#endif
533
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800534static inline int
David Keitel796882d2013-05-14 18:01:11 -0700535get_bpd(const char *name)
536{
537 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700538 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
539 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700540 return i;
541 }
542 return -EINVAL;
543}
544
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700545static bool
546is_within_range(int value, int left, int right)
547{
548 if (left >= right && left >= value && value >= right)
549 return 1;
550 if (left <= right && left <= value && value <= right)
551 return 1;
552 return 0;
553}
554
David Keitel80668952012-07-27 14:25:49 -0700555static int
556qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
557 u16 base, int count)
558{
David Keitel39093572013-06-05 15:32:30 -0700559 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700560 struct spmi_device *spmi = chip->spmi;
561
David Keitel39093572013-06-05 15:32:30 -0700562 if (base == 0) {
563 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
564 base, spmi->sid, rc);
565 return -EINVAL;
566 }
567
568 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700569 if (rc) {
570 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
571 spmi->sid, rc);
572 return rc;
573 }
574 return 0;
575}
576
577static int
578qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
579 u16 base, int count)
580{
David Keitel39093572013-06-05 15:32:30 -0700581 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700582 struct spmi_device *spmi = chip->spmi;
583
David Keitel39093572013-06-05 15:32:30 -0700584 if (base == 0) {
585 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
586 base, spmi->sid, rc);
587 return -EINVAL;
588 }
589
590 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700591 if (rc) {
592 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
593 base, spmi->sid, rc);
594 return rc;
595 }
596
597 return 0;
598}
599
600static int
601qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
602 u8 mask, u8 val, int count)
603{
604 int rc;
605 u8 reg;
606
607 rc = qpnp_chg_read(chip, &reg, base, count);
608 if (rc) {
609 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
610 return rc;
611 }
612 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
613
614 reg &= ~mask;
615 reg |= val & mask;
616
617 pr_debug("Writing 0x%x\n", reg);
618
619 rc = qpnp_chg_write(chip, &reg, base, count);
620 if (rc) {
621 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
622 return rc;
623 }
624
625 return 0;
626}
627
David Keitel47185a62013-05-15 18:54:10 -0700628static void
629qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
630{
631 if (__test_and_clear_bit(0, &irq->disabled)) {
632 pr_debug("number = %d\n", irq->irq);
633 enable_irq(irq->irq);
634 }
Fenglin Wu67aa2ca2015-01-20 16:40:11 +0800635 if ((irq->is_wake) && (!__test_and_set_bit(0, &irq->wake_enable))) {
636 pr_debug("enable wake, number = %d\n", irq->irq);
637 enable_irq_wake(irq->irq);
638 }
David Keitel47185a62013-05-15 18:54:10 -0700639}
640
641static void
642qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
643{
644 if (!__test_and_set_bit(0, &irq->disabled)) {
645 pr_debug("number = %d\n", irq->irq);
646 disable_irq_nosync(irq->irq);
647 }
Fenglin Wu67aa2ca2015-01-20 16:40:11 +0800648 if ((irq->is_wake) && (__test_and_clear_bit(0, &irq->wake_enable))) {
649 pr_debug("disable wake, number = %d\n", irq->irq);
650 disable_irq_wake(irq->irq);
651 }
David Keitel47185a62013-05-15 18:54:10 -0700652}
653
David Keitelbf6a1062014-01-23 10:57:36 -0800654static void
655qpnp_chg_irq_wake_enable(struct qpnp_chg_irq *irq)
656{
657 if (!__test_and_set_bit(0, &irq->wake_enable)) {
658 pr_debug("number = %d\n", irq->irq);
659 enable_irq_wake(irq->irq);
660 }
Fenglin Wu67aa2ca2015-01-20 16:40:11 +0800661 irq->is_wake = true;
David Keitelbf6a1062014-01-23 10:57:36 -0800662}
663
664static void
665qpnp_chg_irq_wake_disable(struct qpnp_chg_irq *irq)
666{
667 if (__test_and_clear_bit(0, &irq->wake_enable)) {
668 pr_debug("number = %d\n", irq->irq);
669 disable_irq_wake(irq->irq);
670 }
Fenglin Wu67aa2ca2015-01-20 16:40:11 +0800671 irq->is_wake = false;
David Keitelbf6a1062014-01-23 10:57:36 -0800672}
673
David Keitel6f865cd2012-11-30 15:04:32 -0800674#define USB_OTG_EN_BIT BIT(0)
675static int
676qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
677{
678 u8 usb_otg_en;
679 int rc;
680
681 rc = qpnp_chg_read(chip, &usb_otg_en,
682 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
683 1);
684
685 if (rc) {
686 pr_err("spmi read failed: addr=%03X, rc=%d\n",
687 chip->usb_chgpth_base + CHGR_STATUS, rc);
688 return rc;
689 }
690 pr_debug("usb otg en 0x%x\n", usb_otg_en);
691
692 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
693}
694
David Keitel42ae0aa2013-03-08 16:20:10 -0800695static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700696qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
697{
698 u8 boost_en_ctl;
699 int rc;
700
701 rc = qpnp_chg_read(chip, &boost_en_ctl,
702 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
703 if (rc) {
704 pr_err("spmi read failed: addr=%03X, rc=%d\n",
705 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
706 return rc;
707 }
708
709 pr_debug("boost en 0x%x\n", boost_en_ctl);
710
711 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
712}
713
714static int
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700715qpnp_chg_is_batt_temp_ok(struct qpnp_chg_chip *chip)
716{
717 u8 batt_rt_sts;
718 int rc;
719
720 rc = qpnp_chg_read(chip, &batt_rt_sts,
721 INT_RT_STS(chip->bat_if_base), 1);
722 if (rc) {
723 pr_err("spmi read failed: addr=%03X, rc=%d\n",
724 INT_RT_STS(chip->bat_if_base), rc);
725 return rc;
726 }
727
728 return (batt_rt_sts & BAT_TEMP_OK_IRQ) ? 1 : 0;
729}
730
731static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800732qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
733{
734 u8 batt_pres_rt_sts;
735 int rc;
736
737 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
738 INT_RT_STS(chip->bat_if_base), 1);
739 if (rc) {
740 pr_err("spmi read failed: addr=%03X, rc=%d\n",
741 INT_RT_STS(chip->bat_if_base), rc);
742 return rc;
743 }
744
745 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
746}
747
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700748static int
749qpnp_chg_is_batfet_closed(struct qpnp_chg_chip *chip)
750{
751 u8 batfet_closed_rt_sts;
752 int rc;
753
754 rc = qpnp_chg_read(chip, &batfet_closed_rt_sts,
755 INT_RT_STS(chip->bat_if_base), 1);
756 if (rc) {
757 pr_err("spmi read failed: addr=%03X, rc=%d\n",
758 INT_RT_STS(chip->bat_if_base), rc);
759 return rc;
760 }
761
762 return (batfet_closed_rt_sts & BAT_FET_ON_IRQ) ? 1 : 0;
763}
764
David Keitel80668952012-07-27 14:25:49 -0700765static int
766qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
767{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800768 u8 usb_chgpth_rt_sts;
David Keitel80668952012-07-27 14:25:49 -0700769 int rc;
770
Zhenhua Huangf1163872014-03-03 10:51:25 +0800771 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
772 INT_RT_STS(chip->usb_chgpth_base), 1);
David Keitel80668952012-07-27 14:25:49 -0700773
774 if (rc) {
775 pr_err("spmi read failed: addr=%03X, rc=%d\n",
Zhenhua Huangf1163872014-03-03 10:51:25 +0800776 INT_RT_STS(chip->usb_chgpth_base), rc);
David Keitel80668952012-07-27 14:25:49 -0700777 return rc;
778 }
Zhenhua Huangf1163872014-03-03 10:51:25 +0800779 pr_debug("chgr usb sts 0x%x\n", usb_chgpth_rt_sts);
David Keitel80668952012-07-27 14:25:49 -0700780
Zhenhua Huangf1163872014-03-03 10:51:25 +0800781 return (usb_chgpth_rt_sts & USBIN_VALID_IRQ) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700782}
783
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700784static bool
David Keitel820a90d2014-03-25 18:18:04 -0700785qpnp_is_dc_higher_prio(struct qpnp_chg_chip *chip)
786{
787 int rc;
788 u8 usb_ctl;
789
790 if (!chip->type == SMBB)
791 return false;
792
793 rc = qpnp_chg_read(chip, &usb_ctl,
794 chip->usb_chgpth_base + USB_CHGPTH_CTL, 1);
795 if (rc) {
796 pr_err("failed to read usb ctl rc=%d\n", rc);
797 return 0;
798 }
799
800 return !!(usb_ctl & DC_HIGHER_PRIORITY);
801}
802
803static bool
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700804qpnp_chg_is_ibat_loop_active(struct qpnp_chg_chip *chip)
805{
806 int rc;
807 u8 buck_sts;
808
809 rc = qpnp_chg_read(chip, &buck_sts,
810 INT_RT_STS(chip->buck_base), 1);
811 if (rc) {
812 pr_err("failed to read buck RT status rc=%d\n", rc);
813 return 0;
814 }
815
816 return !!(buck_sts & IBAT_LOOP_IRQ);
817}
818
Zhenhua Huangf1163872014-03-03 10:51:25 +0800819#define USB_VALID_MASK 0xC0
820#define USB_VALID_IN_MASK BIT(7)
821#define USB_COARSE_DET 0x10
822#define USB_VALID_OVP_VALUE 0x40
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800823static int
824qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
825{
826 u8 usbin_chg_rt_sts;
827 int rc;
828 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
829 chip->usb_chgpth_base + CHGR_STATUS , 1);
830 if (rc) {
831 pr_err("spmi read failed: addr=%03X, rc=%d\n",
832 chip->usb_chgpth_base + CHGR_STATUS, rc);
833 return rc;
834 }
835 return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
836}
837
838static int
839qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
840{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800841 u8 usbin_chg_rt_sts, usb_chgpth_rt_sts;
842 u8 usbin_health = 0;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800843 int rc;
844
845 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
846 chip->usb_chgpth_base + CHGR_STATUS , 1);
847
848 if (rc) {
849 pr_err("spmi read failed: addr=%03X, rc=%d\n",
850 chip->usb_chgpth_base + CHGR_STATUS, rc);
851 return rc;
852 }
853
Zhenhua Huangf1163872014-03-03 10:51:25 +0800854 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
855 INT_RT_STS(chip->usb_chgpth_base) , 1);
856
857 if (rc) {
858 pr_err("spmi read failed: addr=%03X, rc=%d\n",
859 INT_RT_STS(chip->usb_chgpth_base), rc);
860 return rc;
861 }
862
863 pr_debug("chgr usb sts 0x%x, chgpth rt sts 0x%x\n",
864 usbin_chg_rt_sts, usb_chgpth_rt_sts);
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800865 if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
866 if ((usbin_chg_rt_sts & USB_VALID_MASK)
867 == USB_VALID_OVP_VALUE) {
868 usbin_health = USBIN_OVP;
869 pr_err("Over voltage charger inserted\n");
Zhenhua Huangf1163872014-03-03 10:51:25 +0800870 } else if ((usb_chgpth_rt_sts & USBIN_VALID_IRQ) != 0) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800871 usbin_health = USBIN_OK;
872 pr_debug("Valid charger inserted\n");
873 }
874 } else {
875 usbin_health = USBIN_UNKNOW;
876 pr_debug("Charger plug out\n");
877 }
878
879 return usbin_health;
880}
881
David Keitel80668952012-07-27 14:25:49 -0700882static int
883qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
884{
885 u8 dcin_valid_rt_sts;
886 int rc;
887
David Keitelf2170cc2013-02-20 17:49:03 -0800888 if (!chip->dc_chgpth_base)
889 return 0;
890
David Keitel80668952012-07-27 14:25:49 -0700891 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
892 INT_RT_STS(chip->dc_chgpth_base), 1);
893 if (rc) {
894 pr_err("spmi read failed: addr=%03X, rc=%d\n",
895 INT_RT_STS(chip->dc_chgpth_base), rc);
896 return rc;
897 }
898
899 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
900}
901
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700902static int
903qpnp_chg_is_ichg_loop_active(struct qpnp_chg_chip *chip)
904{
905 u8 buck_sts;
906 int rc;
907
908 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
909
910 if (rc) {
911 pr_err("spmi read failed: addr=%03X, rc=%d\n",
912 INT_RT_STS(chip->buck_base), rc);
913 return rc;
914 }
915 pr_debug("buck usb sts 0x%x\n", buck_sts);
916
917 return (buck_sts & ICHG_LOOP_IRQ) ? 1 : 0;
918}
919
David Keitel22ed2232013-01-28 11:04:07 -0800920#define QPNP_CHG_I_MAX_MIN_100 100
921#define QPNP_CHG_I_MAX_MIN_150 150
922#define QPNP_CHG_I_MAX_MIN_MA 200
923#define QPNP_CHG_I_MAX_MAX_MA 2500
924#define QPNP_CHG_I_MAXSTEP_MA 100
925static int
926qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
927{
928 int rc = 0;
929 u8 dc = 0;
930
931 if (mA < QPNP_CHG_I_MAX_MIN_100
932 || mA > QPNP_CHG_I_MAX_MAX_MA) {
933 pr_err("bad mA=%d asked to set\n", mA);
934 return -EINVAL;
935 }
936
937 if (mA == QPNP_CHG_I_MAX_MIN_100) {
938 dc = 0x00;
939 pr_debug("current=%d setting %02x\n", mA, dc);
940 return qpnp_chg_write(chip, &dc,
941 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
942 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
943 dc = 0x01;
944 pr_debug("current=%d setting %02x\n", mA, dc);
945 return qpnp_chg_write(chip, &dc,
946 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
947 }
948
949 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
950
951 pr_debug("current=%d setting 0x%x\n", mA, dc);
952 rc = qpnp_chg_write(chip, &dc,
953 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
954
955 return rc;
956}
957
David Keitel80668952012-07-27 14:25:49 -0700958static int
David Keitel2586f0a2013-08-20 10:02:26 -0700959qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
960{
961 int rc = 0;
962 u8 trim_reg;
963
964 rc = qpnp_chg_read(chip, &trim_reg,
965 chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
966 if (rc) {
967 pr_err("failed to read USB_TRIM rc=%d\n", rc);
968 return 0;
969 }
970
971 return trim_reg;
972}
973
974static int
975qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
976{
977 int rc = 0;
978
979 rc = qpnp_chg_masked_write(chip,
980 chip->usb_chgpth_base + SEC_ACCESS,
981 0xFF,
982 0xA5, 1);
983 if (rc) {
984 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
985 return rc;
986 }
987
988 rc = qpnp_chg_masked_write(chip,
989 chip->usb_chgpth_base + CHGR_USB_TRIM,
990 0xFF,
991 trim, 1);
992 if (rc) {
993 pr_err("failed to write USB TRIM rc=%d\n", rc);
994 return rc;
995 }
996
997 return rc;
998}
999
David Keitelcd2e1022014-05-02 17:25:15 -07001000#define IOVP_USB_WALL_TRSH_MA 150
David Keitel2586f0a2013-08-20 10:02:26 -07001001static int
David Keitel80668952012-07-27 14:25:49 -07001002qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
1003{
David Keiteld681cda2012-10-02 15:44:21 -07001004 int rc = 0;
1005 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -07001006
David Keitel7b0568482013-12-02 14:47:42 -08001007 if (mA < 0 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -07001008 pr_err("bad mA=%d asked to set\n", mA);
1009 return -EINVAL;
1010 }
1011
David Keitel7b0568482013-12-02 14:47:42 -08001012 if (mA <= QPNP_CHG_I_MAX_MIN_100) {
David Keitel22ed2232013-01-28 11:04:07 -08001013 usb_reg = 0x00;
1014 pr_debug("current=%d setting %02x\n", mA, usb_reg);
1015 return qpnp_chg_write(chip, &usb_reg,
1016 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1017 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
1018 usb_reg = 0x01;
1019 pr_debug("current=%d setting %02x\n", mA, usb_reg);
1020 return qpnp_chg_write(chip, &usb_reg,
1021 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1022 }
1023
1024 /* Impose input current limit */
1025 if (chip->maxinput_usb_ma)
1026 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
1027
1028 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -07001029
David Keiteld681cda2012-10-02 15:44:21 -07001030 if (chip->flags & CHG_FLAGS_VCP_WA) {
1031 temp = 0xA5;
1032 rc = qpnp_chg_write(chip, &temp,
1033 chip->buck_base + SEC_ACCESS, 1);
1034 rc = qpnp_chg_masked_write(chip,
1035 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
1036 0x0C, 0x0C, 1);
1037 }
1038
David Keitel80668952012-07-27 14:25:49 -07001039 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -07001040 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -08001041 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -07001042
1043 if (chip->flags & CHG_FLAGS_VCP_WA) {
1044 temp = 0xA5;
1045 udelay(200);
1046 rc = qpnp_chg_write(chip, &temp,
1047 chip->buck_base + SEC_ACCESS, 1);
1048 rc = qpnp_chg_masked_write(chip,
1049 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
1050 0x0C, 0x00, 1);
1051 }
1052
1053 return rc;
1054}
1055
David Keitel25544a22013-12-06 17:59:24 -08001056#define QPNP_CHG_VINMIN_MIN_MV 4000
David Keitel337bd862013-07-15 21:42:58 -07001057#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
1058#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
1059#define QPNP_CHG_VINMIN_MAX_MV 9600
1060#define QPNP_CHG_VINMIN_STEP_MV 50
1061#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
Prasad Sodagudi95624b62013-09-26 16:40:59 +05301062#define QPNP_CHG_VINMIN_MASK 0x3F
David Keitel25544a22013-12-06 17:59:24 -08001063#define QPNP_CHG_VINMIN_MIN_VAL 0x0C
David Keitel337bd862013-07-15 21:42:58 -07001064static int
1065qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
1066{
1067 u8 temp;
1068
David Keitel25544a22013-12-06 17:59:24 -08001069 if ((voltage < QPNP_CHG_VINMIN_MIN_MV)
1070 || (voltage > QPNP_CHG_VINMIN_MAX_MV)) {
David Keitel337bd862013-07-15 21:42:58 -07001071 pr_err("bad mV=%d asked to set\n", voltage);
1072 return -EINVAL;
1073 }
1074 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
1075 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
David Keitel289fcf82013-10-24 11:33:00 -07001076 temp += (voltage - QPNP_CHG_VINMIN_HIGH_MIN_MV)
David Keitel337bd862013-07-15 21:42:58 -07001077 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
1078 } else {
1079 temp = QPNP_CHG_VINMIN_MIN_VAL;
1080 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
1081 / QPNP_CHG_VINMIN_STEP_MV;
1082 }
1083
1084 pr_debug("voltage=%d setting %02x\n", voltage, temp);
1085 return qpnp_chg_masked_write(chip,
1086 chip->chgr_base + CHGR_VIN_MIN,
1087 QPNP_CHG_VINMIN_MASK, temp, 1);
1088}
1089
1090static int
1091qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
1092{
1093 int rc, vin_min_mv;
1094 u8 vin_min;
1095
1096 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
1097 if (rc) {
1098 pr_err("failed to read VIN_MIN rc=%d\n", rc);
1099 return 0;
1100 }
1101
1102 if (vin_min == 0)
1103 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
David Keitel289fcf82013-10-24 11:33:00 -07001104 else if (vin_min >= QPNP_CHG_VINMIN_HIGH_MIN_VAL)
David Keitel337bd862013-07-15 21:42:58 -07001105 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
1106 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
1107 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
1108 else
1109 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
1110 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
1111 * QPNP_CHG_VINMIN_STEP_MV;
1112 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
1113
1114 return vin_min_mv;
1115}
1116
Prasad Sodagudic3678012013-09-23 12:01:19 +05301117#define QPNP_CHG_VBATWEAK_MIN_MV 2100
1118#define QPNP_CHG_VBATWEAK_MAX_MV 3600
1119#define QPNP_CHG_VBATWEAK_STEP_MV 100
1120static int
1121qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
1122{
1123 u8 temp;
1124
1125 if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
1126 || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
1127 return -EINVAL;
1128
1129 temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
1130 / QPNP_CHG_VBATWEAK_STEP_MV;
1131
1132 pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
1133 return qpnp_chg_write(chip, &temp,
1134 chip->chgr_base + CHGR_VBAT_WEAK, 1);
1135}
1136
David Keitel337bd862013-07-15 21:42:58 -07001137static int
1138qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
1139{
1140 int rc, iusbmax_ma;
1141 u8 iusbmax;
1142
1143 rc = qpnp_chg_read(chip, &iusbmax,
1144 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1145 if (rc) {
1146 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
1147 return 0;
1148 }
1149
1150 if (iusbmax == 0)
1151 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
1152 else if (iusbmax == 0x01)
1153 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
1154 else
1155 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
1156
1157 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
1158
1159 return iusbmax_ma;
1160}
1161
David Keitel975b5352014-01-27 14:28:04 -08001162#define ILIMIT_OVR_0 0x02
1163static int
1164override_dcin_ilimit(struct qpnp_chg_chip *chip, bool override)
1165{
1166 int rc;
1167
1168 pr_debug("override %d\n", override);
1169 rc = qpnp_chg_masked_write(chip,
1170 chip->dc_chgpth_base + SEC_ACCESS,
1171 0xA5,
1172 0xA5, 1);
1173 rc |= qpnp_chg_masked_write(chip,
1174 chip->dc_chgpth_base + DC_COMP_OVR1,
1175 0xFF,
1176 override ? ILIMIT_OVR_0 : 0, 1);
1177 if (rc) {
1178 pr_err("Failed to override dc ilimit rc = %d\n", rc);
1179 return rc;
1180 }
1181
1182 return rc;
1183}
1184
1185#define DUAL_PATH_EN BIT(7)
1186static int
1187switch_parallel_ovp_mode(struct qpnp_chg_chip *chip, bool enable)
1188{
1189 int rc = 0;
1190
1191 if (!chip->usb_chgpth_base || !chip->dc_chgpth_base)
1192 return rc;
1193
1194 pr_debug("enable %d\n", enable);
1195 rc = override_dcin_ilimit(chip, 1);
1196 udelay(10);
1197
1198 /* enable/disable dual path mode */
1199 rc = qpnp_chg_masked_write(chip,
1200 chip->usb_chgpth_base + SEC_ACCESS,
1201 0xA5,
1202 0xA5, 1);
1203 rc |= qpnp_chg_masked_write(chip,
1204 chip->usb_chgpth_base + USB_SPARE,
1205 0xFF,
1206 enable ? DUAL_PATH_EN : 0, 1);
1207 if (rc) {
1208 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1209 return rc;
1210 }
1211
David Keitelbf2edba2014-03-05 10:49:32 -08001212 if (enable)
1213 rc = override_dcin_ilimit(chip, 0);
David Keitel975b5352014-01-27 14:28:04 -08001214 return rc;
1215}
1216
David Keiteld681cda2012-10-02 15:44:21 -07001217#define USB_SUSPEND_BIT BIT(0)
1218static int
1219qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
1220{
David Keitel975b5352014-01-27 14:28:04 -08001221 /* Turn off DC OVP FET when going into USB suspend */
1222 if (chip->parallel_ovp_mode && enable)
1223 switch_parallel_ovp_mode(chip, 0);
1224
David Keiteld681cda2012-10-02 15:44:21 -07001225 return qpnp_chg_masked_write(chip,
1226 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
1227 USB_SUSPEND_BIT,
1228 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -07001229}
1230
David Keitel344c6972013-04-09 19:28:21 -07001231static int
1232qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
1233{
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001234 if (chip->insertion_ocv_uv == 0 && enable) {
1235 pr_debug("Battery not present, skipping\n");
1236 return 0;
1237 }
1238 pr_debug("charging %s\n", enable ? "enabled" : "disabled");
David Keitel344c6972013-04-09 19:28:21 -07001239 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1240 CHGR_CHG_EN,
1241 enable ? CHGR_CHG_EN : 0, 1);
1242}
1243
1244static int
1245qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
1246{
1247 /* Don't run on battery for batteryless hardware */
1248 if (chip->use_default_batt_values)
1249 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -07001250 /* Don't force on battery if battery is not present */
1251 if (!qpnp_chg_is_batt_present(chip))
1252 return 0;
David Keitel344c6972013-04-09 19:28:21 -07001253
1254 /* This bit forces the charger to run off of the battery rather
1255 * than a connected charger */
1256 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1257 CHGR_ON_BAT_FORCE_BIT,
1258 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
1259}
1260
David Keitel8b68d2d2013-05-14 23:36:51 -07001261#define BUCK_DUTY_MASK_100P 0x30
1262static int
1263qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
1264{
1265 int rc;
1266
1267 pr_debug("enable: %d\n", enable);
1268
1269 rc = qpnp_chg_masked_write(chip,
1270 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1271 if (rc) {
1272 pr_debug("failed to write sec access rc=%d\n", rc);
1273 return rc;
1274 }
1275
1276 rc = qpnp_chg_masked_write(chip,
1277 chip->buck_base + BUCK_TEST_SMBC_MODES,
1278 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
1279 if (rc) {
1280 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
1281 return rc;
1282 }
1283
1284 return rc;
1285}
1286
David Keitel9fd07382013-05-02 15:37:44 -07001287#define COMPATATOR_OVERRIDE_0 0x80
1288static int
1289qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
1290{
1291 int rc;
1292
1293 pr_debug("toggle: %d\n", enable);
1294
1295 rc = qpnp_chg_masked_write(chip,
1296 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1297 if (rc) {
1298 pr_debug("failed to write sec access rc=%d\n", rc);
1299 return rc;
1300 }
1301
1302 rc = qpnp_chg_masked_write(chip,
1303 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
1304 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
1305 if (rc) {
1306 pr_debug("failed to toggle chg done override rc=%d\n", rc);
1307 return rc;
1308 }
1309
1310 return rc;
1311}
1312
1313#define QPNP_CHG_VBATDET_MIN_MV 3240
1314#define QPNP_CHG_VBATDET_MAX_MV 5780
1315#define QPNP_CHG_VBATDET_STEP_MV 20
1316static int
1317qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
1318{
1319 u8 temp;
1320
1321 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
1322 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
1323 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
1324 return -EINVAL;
1325 }
1326 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
1327 / QPNP_CHG_VBATDET_STEP_MV;
1328
1329 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
1330 return qpnp_chg_write(chip, &temp,
1331 chip->chgr_base + CHGR_VBAT_DET, 1);
1332}
1333
David Keitel344c6972013-04-09 19:28:21 -07001334static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001335qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
1336{
1337 if (chip->bat_is_cool)
1338 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
1339 - chip->resume_delta_mv);
1340 else if (chip->bat_is_warm)
1341 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
1342 - chip->resume_delta_mv);
1343 else if (chip->resuming_charging)
1344 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1345 + chip->resume_delta_mv);
1346 else
1347 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1348 - chip->resume_delta_mv);
1349}
1350
1351static void
David Keitel344c6972013-04-09 19:28:21 -07001352qpnp_arb_stop_work(struct work_struct *work)
1353{
1354 struct delayed_work *dwork = to_delayed_work(work);
1355 struct qpnp_chg_chip *chip = container_of(dwork,
1356 struct qpnp_chg_chip, arb_stop_work);
1357
David Keitel9fd07382013-05-02 15:37:44 -07001358 if (!chip->chg_done)
1359 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -07001360 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1361}
1362
1363static void
1364qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -07001365{
1366 struct qpnp_chg_chip *chip = container_of(work,
1367 struct qpnp_chg_chip, adc_measure_work);
1368
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07001369 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -07001370 pr_err("request ADC error\n");
1371}
1372
David Keitelecab15a2013-08-06 15:41:39 -07001373static void
1374qpnp_bat_if_adc_disable_work(struct work_struct *work)
1375{
1376 struct qpnp_chg_chip *chip = container_of(work,
1377 struct qpnp_chg_chip, adc_disable_work);
1378
1379 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev, &chip->adc_param);
1380}
1381
David Keitel9fd07382013-05-02 15:37:44 -07001382#define EOC_CHECK_PERIOD_MS 10000
1383static irqreturn_t
1384qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
1385{
1386 struct qpnp_chg_chip *chip = _chip;
1387 u8 chg_sts = 0;
1388 int rc;
1389
1390 pr_debug("vbatdet-lo triggered\n");
1391
1392 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
1393 if (rc)
1394 pr_err("failed to read chg_sts rc=%d\n", rc);
1395
1396 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
1397 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
1398 schedule_delayed_work(&chip->eoc_work,
1399 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001400 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07001401 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001402 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07001403
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001404 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001405 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001406 if (chip->dc_chgpth_base) {
1407 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001408 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001409 }
1410 if (chip->bat_if_base) {
1411 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001412 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001413 }
David Keitel9fd07382013-05-02 15:37:44 -07001414 return IRQ_HANDLED;
1415}
1416
David Keitel344c6972013-04-09 19:28:21 -07001417#define ARB_STOP_WORK_MS 1000
1418static irqreturn_t
1419qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
1420{
1421 struct qpnp_chg_chip *chip = _chip;
David Keitel7e38f512013-11-19 11:15:11 -08001422 u8 usb_sts;
1423 int rc;
1424
1425 rc = qpnp_chg_read(chip, &usb_sts,
1426 INT_RT_STS(chip->usb_chgpth_base), 1);
1427 if (rc)
1428 pr_err("failed to read usb_chgpth_sts rc=%d\n", rc);
David Keitel344c6972013-04-09 19:28:21 -07001429
1430 pr_debug("chg_gone triggered\n");
David Keiteld53183a2014-01-07 17:17:44 -08001431 if ((qpnp_chg_is_usb_chg_plugged_in(chip)
1432 || qpnp_chg_is_dc_chg_plugged_in(chip))
1433 && (usb_sts & CHG_GONE_IRQ)) {
David Keitelcd2e1022014-05-02 17:25:15 -07001434 if (ext_ovp_isns_present) {
1435 pr_debug("EXT OVP IC ISNS disabled due to ARB WA\n");
1436 gpio_direction_output(chip->ext_ovp_isns_gpio, 0);
1437 }
1438
David Keitel344c6972013-04-09 19:28:21 -07001439 qpnp_chg_charge_en(chip, 0);
David Keitelcd2e1022014-05-02 17:25:15 -07001440
David Keitel9fd07382013-05-02 15:37:44 -07001441 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001442 schedule_delayed_work(&chip->arb_stop_work,
1443 msecs_to_jiffies(ARB_STOP_WORK_MS));
1444 }
1445
1446 return IRQ_HANDLED;
1447}
1448
David Keitel0b62bdd2013-07-10 17:30:51 -07001449static irqreturn_t
1450qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
1451{
1452 struct qpnp_chg_chip *chip = _chip;
David Keitel0b62bdd2013-07-10 17:30:51 -07001453
1454 pr_debug("usb-ocp triggered\n");
1455
David Keitel8b9bd312014-01-15 14:44:00 -08001456 schedule_work(&chip->ocp_clear_work);
1457
1458 return IRQ_HANDLED;
1459}
1460
1461#define BOOST_ILIMIT_MIN 0x07
1462#define BOOST_ILIMIT_DEF 0x02
1463#define BOOST_ILIMT_MASK 0xFF
1464static void
1465qpnp_chg_ocp_clear_work(struct work_struct *work)
1466{
1467 int rc;
1468 u8 usb_sts;
1469 struct qpnp_chg_chip *chip = container_of(work,
1470 struct qpnp_chg_chip, ocp_clear_work);
1471
1472 if (chip->type == SMBBP) {
1473 rc = qpnp_chg_masked_write(chip,
1474 chip->boost_base + BOOST_ILIM,
1475 BOOST_ILIMT_MASK,
1476 BOOST_ILIMIT_MIN, 1);
1477 if (rc) {
1478 pr_err("Failed to turn configure ilim rc = %d\n", rc);
1479 return;
1480 }
1481 }
1482
David Keitel0b62bdd2013-07-10 17:30:51 -07001483 rc = qpnp_chg_masked_write(chip,
1484 chip->usb_chgpth_base + USB_OCP_CLR,
1485 OCP_CLR_BIT,
1486 OCP_CLR_BIT, 1);
1487 if (rc)
1488 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1489
1490 /* force usb ovp fet off */
1491 rc = qpnp_chg_masked_write(chip,
1492 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1493 USB_OTG_EN_BIT,
1494 USB_OTG_EN_BIT, 1);
1495 if (rc)
1496 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1497
David Keitel8b9bd312014-01-15 14:44:00 -08001498 if (chip->type == SMBBP) {
1499 /* Wait for OCP circuitry to be powered up */
1500 msleep(100);
1501 rc = qpnp_chg_read(chip, &usb_sts,
1502 INT_RT_STS(chip->usb_chgpth_base), 1);
1503 if (rc) {
1504 pr_err("failed to read interrupt sts %d\n", rc);
1505 return;
1506 }
1507
1508 if (usb_sts & COARSE_DET_USB_IRQ) {
1509 rc = qpnp_chg_masked_write(chip,
1510 chip->boost_base + BOOST_ILIM,
1511 BOOST_ILIMT_MASK,
1512 BOOST_ILIMIT_DEF, 1);
1513 if (rc) {
1514 pr_err("Failed to set ilim rc = %d\n", rc);
1515 return;
1516 }
1517 } else {
1518 pr_warn_ratelimited("USB short to GND detected!\n");
1519 }
1520 }
David Keitel0b62bdd2013-07-10 17:30:51 -07001521}
1522
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001523#define QPNP_CHG_VDDMAX_MIN 3400
1524#define QPNP_CHG_V_MIN_MV 3240
1525#define QPNP_CHG_V_MAX_MV 4500
1526#define QPNP_CHG_V_STEP_MV 10
1527#define QPNP_CHG_BUCK_TRIM1_STEP 10
1528#define QPNP_CHG_BUCK_VDD_TRIM_MASK 0xF0
1529static int
1530qpnp_chg_vddmax_and_trim_set(struct qpnp_chg_chip *chip,
1531 int voltage, int trim_mv)
1532{
1533 int rc, trim_set;
1534 u8 vddmax = 0, trim = 0;
1535
1536 if (voltage < QPNP_CHG_VDDMAX_MIN
1537 || voltage > QPNP_CHG_V_MAX_MV) {
1538 pr_err("bad mV=%d asked to set\n", voltage);
1539 return -EINVAL;
1540 }
1541
1542 vddmax = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1543 rc = qpnp_chg_write(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1544 if (rc) {
1545 pr_err("Failed to write vddmax: %d\n", rc);
1546 return rc;
1547 }
1548
1549 rc = qpnp_chg_masked_write(chip,
1550 chip->buck_base + SEC_ACCESS,
1551 0xFF,
1552 0xA5, 1);
1553 if (rc) {
1554 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1555 return rc;
1556 }
1557 trim_set = clamp((int)chip->trim_center
1558 + (trim_mv / QPNP_CHG_BUCK_TRIM1_STEP),
1559 0, 0xF);
1560 trim = (u8)trim_set << 4;
1561 rc = qpnp_chg_masked_write(chip,
1562 chip->buck_base + BUCK_CTRL_TRIM1,
1563 QPNP_CHG_BUCK_VDD_TRIM_MASK,
1564 trim, 1);
1565 if (rc) {
1566 pr_err("Failed to write buck trim1: %d\n", rc);
1567 return rc;
1568 }
1569 pr_debug("voltage=%d+%d setting vddmax: %02x, trim: %02x\n",
1570 voltage, trim_mv, vddmax, trim);
1571 return 0;
1572}
1573
Xiaozhe Shie8504482013-10-30 18:10:31 -07001574static int
1575qpnp_chg_vddmax_get(struct qpnp_chg_chip *chip)
1576{
1577 int rc;
1578 u8 vddmax = 0;
1579
1580 rc = qpnp_chg_read(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1581 if (rc) {
1582 pr_err("Failed to write vddmax: %d\n", rc);
1583 return rc;
1584 }
1585
1586 return QPNP_CHG_V_MIN_MV + (int)vddmax * QPNP_CHG_V_STEP_MV;
1587}
1588
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001589/* JEITA compliance logic */
1590static void
1591qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1592{
1593 if (chip->bat_is_cool)
1594 qpnp_chg_vddmax_and_trim_set(chip, chip->cool_bat_mv,
1595 chip->delta_vddmax_mv);
1596 else if (chip->bat_is_warm)
1597 qpnp_chg_vddmax_and_trim_set(chip, chip->warm_bat_mv,
1598 chip->delta_vddmax_mv);
1599 else
1600 qpnp_chg_vddmax_and_trim_set(chip, chip->max_voltage_mv,
1601 chip->delta_vddmax_mv);
1602}
1603
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001604static void
1605qpnp_usbin_health_check_work(struct work_struct *work)
1606{
1607 int usbin_health = 0;
1608 u8 psy_health_sts = 0;
1609 struct delayed_work *dwork = to_delayed_work(work);
1610 struct qpnp_chg_chip *chip = container_of(dwork,
1611 struct qpnp_chg_chip, usbin_health_check);
1612
1613 usbin_health = qpnp_chg_check_usbin_health(chip);
1614 spin_lock(&chip->usbin_health_monitor_lock);
1615 if (chip->usbin_health != usbin_health) {
1616 pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
1617 chip->usbin_health, usbin_health);
1618 chip->usbin_health = usbin_health;
1619 if (usbin_health == USBIN_OVP)
1620 psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1621 else if (usbin_health == USBIN_OK)
1622 psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
1623 power_supply_set_health_state(chip->usb_psy, psy_health_sts);
1624 power_supply_changed(chip->usb_psy);
1625 }
1626 /* enable OVP monitor in usb valid after coarse-det complete */
1627 chip->usb_valid_check_ovp = true;
1628 spin_unlock(&chip->usbin_health_monitor_lock);
1629 return;
1630}
1631
1632#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
1633#define USB_DEB_BYPASS 0x0
1634#define USB_DEB_5MS 0x1
1635#define USB_DEB_10MS 0x2
1636#define USB_DEB_20MS 0x3
1637static irqreturn_t
1638qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
1639{
1640 struct qpnp_chg_chip *chip = _chip;
1641 int host_mode, rc = 0;
1642 int debounce[] = {
1643 [USB_DEB_BYPASS] = 0,
1644 [USB_DEB_5MS] = 5,
1645 [USB_DEB_10MS] = 10,
1646 [USB_DEB_20MS] = 20 };
1647 u8 ovp_ctl;
1648 bool usb_coarse_det;
1649
1650 host_mode = qpnp_chg_is_otg_en_set(chip);
1651 usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
1652 pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
1653 usb_coarse_det, host_mode);
1654
1655 if (host_mode)
1656 return IRQ_HANDLED;
1657 /* ignore to monitor OVP in usbin valid irq handler
1658 if the coarse-det fired first, do the OVP state monitor
1659 in the usbin_health_check work, and after the work,
1660 enable monitor OVP in usbin valid irq handler */
1661 chip->usb_valid_check_ovp = false;
1662 if (chip->usb_coarse_det ^ usb_coarse_det) {
1663 chip->usb_coarse_det = usb_coarse_det;
1664 if (usb_coarse_det) {
1665 /* usb coarse-det rising edge, check the usbin_valid
1666 debounce time setting, and start a delay work to
1667 check the OVP status*/
1668 rc = qpnp_chg_read(chip, &ovp_ctl,
1669 chip->usb_chgpth_base + USB_OVP_CTL, 1);
1670
1671 if (rc) {
1672 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1673 chip->usb_chgpth_base + USB_OVP_CTL,
1674 rc);
1675 return rc;
1676 }
1677 ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
1678 schedule_delayed_work(&chip->usbin_health_check,
1679 msecs_to_jiffies(debounce[ovp_ctl]));
1680 } else {
1681 /* usb coarse-det rising edge, set the usb psy health
1682 status to unknown */
1683 pr_debug("usb coarse det clear, set usb health to unknown\n");
1684 chip->usbin_health = USBIN_UNKNOW;
1685 power_supply_set_health_state(chip->usb_psy,
1686 POWER_SUPPLY_HEALTH_UNKNOWN);
1687 power_supply_changed(chip->usb_psy);
1688 }
1689
1690 }
1691 return IRQ_HANDLED;
1692}
1693
David Keitel6e63bd52013-09-06 18:00:03 -07001694#define BATFET_LPM_MASK 0xC0
1695#define BATFET_LPM 0x40
1696#define BATFET_NO_LPM 0x00
1697static int
1698qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
1699{
1700 int rc = 0;
1701
David Keitelcadbc282013-09-26 11:39:14 -07001702 if (chip->charging_disabled || !chip->bat_if_base)
1703 return rc;
1704
David Keitel6e63bd52013-09-06 18:00:03 -07001705 if (chip->type == SMBB)
1706 rc = qpnp_chg_masked_write(chip,
1707 chip->bat_if_base + CHGR_BAT_IF_SPARE,
1708 BATFET_LPM_MASK,
1709 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1710 else
1711 rc = qpnp_chg_masked_write(chip,
1712 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
1713 BATFET_LPM_MASK,
1714 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1715
1716 return rc;
1717}
1718
David Keitel820a90d2014-03-25 18:18:04 -07001719#define USB_WALL_THRESHOLD_MA 500
David Keitel80668952012-07-27 14:25:49 -07001720#define ENUM_T_STOP_BIT BIT(0)
David Keitel820a90d2014-03-25 18:18:04 -07001721#define USB_5V_UV 5000000
1722#define USB_9V_UV 9000000
David Keitel80668952012-07-27 14:25:49 -07001723static irqreturn_t
1724qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1725{
1726 struct qpnp_chg_chip *chip = _chip;
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001727 int usb_present, host_mode, usbin_health;
1728 u8 psy_health_sts;
David Keitel80668952012-07-27 14:25:49 -07001729
1730 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001731 host_mode = qpnp_chg_is_otg_en_set(chip);
1732 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1733 usb_present, host_mode);
1734
1735 /* In host mode notifications cmoe from USB supply */
1736 if (host_mode)
1737 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001738
1739 if (chip->usb_present ^ usb_present) {
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07001740 chip->aicl_settled = false;
David Keitel80668952012-07-27 14:25:49 -07001741 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001742 if (!usb_present) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001743 /* when a valid charger inserted, and increase the
1744 * charger voltage to OVP threshold, then
1745 * usb_in_valid falling edge interrupt triggers.
1746 * So we handle the OVP monitor here, and ignore
1747 * other health state changes */
1748 if (chip->ovp_monitor_enable &&
1749 (chip->usb_valid_check_ovp)) {
1750 usbin_health =
1751 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001752 if ((chip->usbin_health != usbin_health)
1753 && (usbin_health == USBIN_OVP)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001754 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001755 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001756 POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1757 power_supply_set_health_state(
1758 chip->usb_psy,
1759 psy_health_sts);
1760 power_supply_changed(chip->usb_psy);
1761 }
1762 }
Xiaozhe Shi9e887be2014-05-21 15:18:58 -07001763 if (!qpnp_chg_is_dc_chg_plugged_in(chip))
David Keitel6e63bd52013-09-06 18:00:03 -07001764 chip->chg_done = false;
David Keitel820a90d2014-03-25 18:18:04 -07001765
1766 if (!qpnp_is_dc_higher_prio(chip))
1767 qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
1768
David Keitela9185602013-11-12 17:55:48 -08001769 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel7b0568482013-12-02 14:47:42 -08001770 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelcd2e1022014-05-02 17:25:15 -07001771 qpnp_chg_iusb_trim_set(chip, chip->usb_trim_default);
David Keitelfd305ee2013-07-19 20:19:06 -07001772 chip->prev_usb_max_ma = -EINVAL;
David Keitel9fd07382013-05-02 15:37:44 -07001773 } else {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001774 /* when OVP clamped usbin, and then decrease
1775 * the charger voltage to lower than the OVP
1776 * threshold, a usbin_valid rising edge
1777 * interrupt triggered. So we change the usb
1778 * psy health state back to good */
1779 if (chip->ovp_monitor_enable &&
1780 (chip->usb_valid_check_ovp)) {
1781 usbin_health =
1782 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001783 if ((chip->usbin_health != usbin_health)
1784 && (usbin_health == USBIN_OK)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001785 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001786 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001787 POWER_SUPPLY_HEALTH_GOOD;
1788 power_supply_set_health_state(
1789 chip->usb_psy,
1790 psy_health_sts);
1791 power_supply_changed(chip->usb_psy);
1792 }
1793 }
1794
David Keitel9fd07382013-05-02 15:37:44 -07001795 schedule_delayed_work(&chip->eoc_work,
1796 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001797 schedule_work(&chip->soc_check_work);
David Keitel9fd07382013-05-02 15:37:44 -07001798 }
David Keitel344c6972013-04-09 19:28:21 -07001799
David Keitel9fd07382013-05-02 15:37:44 -07001800 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel6e63bd52013-09-06 18:00:03 -07001801 schedule_work(&chip->batfet_lcl_work);
David Keitel80668952012-07-27 14:25:49 -07001802 }
1803
1804 return IRQ_HANDLED;
1805}
1806
Fenglin Wuc64e9942014-08-22 13:47:34 +08001807#define BUCK_VIN_LOOP_CMP_OVRD_MASK 0x30
1808static int
1809qpnp_chg_bypass_vchg_loop_debouncer(struct qpnp_chg_chip *chip, bool bypass)
1810{
1811 int rc;
1812 u8 value = bypass ? 0x10 : 0;
1813
1814 pr_debug("bypass vchg_loop debouncer: %d\n", bypass);
1815
1816 rc = qpnp_chg_masked_write(chip, chip->buck_base + SEC_ACCESS,
1817 0xFF, 0xA5, 1);
1818 if (rc) {
1819 pr_err("failed to write SEC_ACCESS register, rc = %d\n", rc);
1820 return rc;
1821 }
1822
1823 rc = qpnp_chg_masked_write(chip,
1824 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_2,
1825 BUCK_VIN_LOOP_CMP_OVRD_MASK, value, 1);
1826 if (rc)
1827 pr_err("failed to write BUCK_COMP_OVRIDE_2, rc = %d\n", rc);
1828
1829 return rc;
1830}
1831
1832static int
1833qpnp_chg_vchg_loop_debouncer_setting_get(struct qpnp_chg_chip *chip)
1834{
1835 int rc;
1836 u8 value;
1837
1838 rc = qpnp_chg_read(chip, &value,
1839 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_2, 1);
1840 if (rc) {
1841 pr_err("failed to read BUCK_CMP_OVERIDE_2, rc = %d\n", rc);
1842 return 0;
1843 }
1844
1845 return value & BUCK_VIN_LOOP_CMP_OVRD_MASK;
1846}
1847
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001848#define TEST_EN_SMBC_LOOP 0xE5
1849#define IBAT_REGULATION_DISABLE BIT(2)
David Keitel7450dcd2013-01-29 18:41:41 -08001850static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001851qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1852{
1853 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001854 int batt_temp_good, batt_present, rc;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001855
1856 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1857 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1858
Xiaozhe Shi87831862014-01-20 17:44:40 -08001859 batt_present = qpnp_chg_is_batt_present(chip);
1860 if (batt_present) {
1861 rc = qpnp_chg_masked_write(chip,
1862 chip->buck_base + SEC_ACCESS,
1863 0xFF,
1864 0xA5, 1);
1865 if (rc) {
1866 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1867 return rc;
1868 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001869
Xiaozhe Shi87831862014-01-20 17:44:40 -08001870 rc = qpnp_chg_masked_write(chip,
1871 chip->buck_base + TEST_EN_SMBC_LOOP,
1872 IBAT_REGULATION_DISABLE,
1873 batt_temp_good ? 0 : IBAT_REGULATION_DISABLE, 1);
1874 if (rc) {
1875 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1876 return rc;
1877 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001878 }
1879
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001880 pr_debug("psy changed batt_psy\n");
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001881 power_supply_changed(&chip->batt_psy);
1882 return IRQ_HANDLED;
1883}
1884
1885static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001886qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1887{
1888 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001889 int batt_present, batt_temp_good, rc;
David Keitel42ae0aa2013-03-08 16:20:10 -08001890
1891 batt_present = qpnp_chg_is_batt_present(chip);
1892 pr_debug("batt-pres triggered: %d\n", batt_present);
1893
1894 if (chip->batt_present ^ batt_present) {
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001895 if (batt_present) {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001896 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1897 rc = qpnp_chg_masked_write(chip,
1898 chip->buck_base + SEC_ACCESS,
1899 0xFF,
1900 0xA5, 1);
1901 if (rc) {
1902 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1903 return rc;
1904 }
1905
1906 rc = qpnp_chg_masked_write(chip,
1907 chip->buck_base + TEST_EN_SMBC_LOOP,
1908 IBAT_REGULATION_DISABLE,
1909 batt_temp_good
1910 ? 0 : IBAT_REGULATION_DISABLE, 1);
1911 if (rc) {
1912 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1913 return rc;
1914 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001915 schedule_work(&chip->insertion_ocv_work);
1916 } else {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001917 rc = qpnp_chg_masked_write(chip,
1918 chip->buck_base + SEC_ACCESS,
1919 0xFF,
1920 0xA5, 1);
1921 if (rc) {
1922 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1923 return rc;
1924 }
1925
1926 rc = qpnp_chg_masked_write(chip,
1927 chip->buck_base + TEST_EN_SMBC_LOOP,
1928 IBAT_REGULATION_DISABLE,
1929 0, 1);
1930 if (rc) {
1931 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1932 return rc;
1933 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001934 chip->insertion_ocv_uv = 0;
1935 qpnp_chg_charge_en(chip, 0);
1936 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001937 chip->batt_present = batt_present;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001938 pr_debug("psy changed batt_psy\n");
David Keitel42ae0aa2013-03-08 16:20:10 -08001939 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001940 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001941 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001942
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001943 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07001944 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001945 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001946 schedule_work(&chip->adc_measure_work);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001947 } else if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitelec3c09802013-06-13 13:05:30 -07001948 && !batt_present) {
David Keitelecab15a2013-08-06 15:41:39 -07001949 schedule_work(&chip->adc_disable_work);
David Keitelec3c09802013-06-13 13:05:30 -07001950 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001951 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001952 }
1953
1954 return IRQ_HANDLED;
1955}
1956
1957static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001958qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1959{
1960 struct qpnp_chg_chip *chip = _chip;
1961 int dc_present;
1962
1963 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1964 pr_debug("dcin-valid triggered: %d\n", dc_present);
1965
1966 if (chip->dc_present ^ dc_present) {
1967 chip->dc_present = dc_present;
David Keitel6d4b9da2013-09-05 17:38:40 -07001968 if (qpnp_chg_is_otg_en_set(chip))
1969 qpnp_chg_force_run_on_batt(chip, !dc_present ? 1 : 0);
David Keitel86628cc2014-06-09 13:24:00 -07001970 if (!dc_present && (!qpnp_chg_is_usb_chg_plugged_in(chip) ||
1971 qpnp_chg_is_otg_en_set(chip))) {
David Keitel9fd07382013-05-02 15:37:44 -07001972 chip->chg_done = false;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001973 } else {
David Keitel9fd07382013-05-02 15:37:44 -07001974 schedule_delayed_work(&chip->eoc_work,
1975 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001976 schedule_work(&chip->soc_check_work);
1977 }
David Keitel820a90d2014-03-25 18:18:04 -07001978
1979 if (qpnp_is_dc_higher_prio(chip)) {
1980 pr_debug("dc has higher priority\n");
1981 if (dc_present) {
1982 qpnp_chg_iusbmax_set(chip,
1983 QPNP_CHG_I_MAX_MIN_100);
1984 power_supply_set_voltage_limit(chip->usb_psy,
1985 USB_5V_UV);
1986 } else {
1987 chip->aicl_settled = false;
1988 qpnp_chg_iusbmax_set(chip,
1989 USB_WALL_THRESHOLD_MA);
1990 power_supply_set_voltage_limit(chip->usb_psy,
1991 USB_9V_UV);
1992 }
1993 }
1994
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001995 pr_debug("psy changed dc_psy\n");
David Keitel7450dcd2013-01-29 18:41:41 -08001996 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001997 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001998 power_supply_changed(&chip->batt_psy);
David Keitel6e63bd52013-09-06 18:00:03 -07001999 schedule_work(&chip->batfet_lcl_work);
David Keitel7450dcd2013-01-29 18:41:41 -08002000 }
2001
2002 return IRQ_HANDLED;
2003}
2004
David Keitel80668952012-07-27 14:25:49 -07002005#define CHGR_CHG_FAILED_BIT BIT(7)
2006static irqreturn_t
2007qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
2008{
2009 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07002010 int rc;
David Keitel80668952012-07-27 14:25:49 -07002011
David Keitel9fd07382013-05-02 15:37:44 -07002012 pr_debug("chg_failed triggered\n");
2013
David Keitel80668952012-07-27 14:25:49 -07002014 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07002015 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07002016 CHGR_CHG_FAILED_BIT,
2017 CHGR_CHG_FAILED_BIT, 1);
2018 if (rc)
2019 pr_err("Failed to write chg_fail clear bit!\n");
2020
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002021 if (chip->bat_if_base) {
2022 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002023 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002024 }
2025 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07002026 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002027 if (chip->dc_chgpth_base) {
2028 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002029 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002030 }
David Keitel80668952012-07-27 14:25:49 -07002031 return IRQ_HANDLED;
2032}
2033
2034static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08002035qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
2036{
2037 struct qpnp_chg_chip *chip = _chip;
2038
2039 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08002040
2041 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002042 if (chip->bat_if_base) {
2043 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002044 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002045 }
David Keitel42ae0aa2013-03-08 16:20:10 -08002046
2047 return IRQ_HANDLED;
2048}
2049
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002050static int qpnp_chg_is_fastchg_on(struct qpnp_chg_chip *chip)
David Keitel42ae0aa2013-03-08 16:20:10 -08002051{
David Keitel337bd862013-07-15 21:42:58 -07002052 u8 chgr_sts;
2053 int rc;
2054
David Keitelbf6a1062014-01-23 10:57:36 -08002055 qpnp_chg_irq_wake_disable(&chip->chg_fastchg);
2056
David Keitel337bd862013-07-15 21:42:58 -07002057 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002058 if (rc) {
2059 pr_err("failed to read interrupt status %d\n", rc);
2060 return rc;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002061 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002062 pr_debug("chgr_sts 0x%x\n", chgr_sts);
2063 return (chgr_sts & FAST_CHG_ON_IRQ) ? 1 : 0;
2064}
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002065
David Keitel59fbb762014-02-05 16:46:24 -08002066#define VBATDET_BYPASS 0x01
2067static int
2068bypass_vbatdet_comp(struct qpnp_chg_chip *chip, bool bypass)
2069{
2070 int rc;
2071
2072 pr_debug("bypass %d\n", bypass);
2073 rc = qpnp_chg_masked_write(chip,
2074 chip->chgr_base + SEC_ACCESS,
2075 0xA5,
2076 0xA5, 1);
2077 rc |= qpnp_chg_masked_write(chip,
2078 chip->chgr_base + CHGR_COMP_OVR1,
2079 0xFF,
2080 bypass ? VBATDET_BYPASS : 0, 1);
2081 if (rc) {
2082 pr_err("Failed to bypass vbatdet comp rc = %d\n", rc);
2083 return rc;
2084 }
2085
2086 return rc;
2087}
2088
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002089static irqreturn_t
2090qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
2091{
2092 struct qpnp_chg_chip *chip = _chip;
2093 bool fastchg_on = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002094
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002095 fastchg_on = qpnp_chg_is_fastchg_on(chip);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002096
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002097 pr_debug("FAST_CHG IRQ triggered, fastchg_on: %d\n", fastchg_on);
David Keitel337bd862013-07-15 21:42:58 -07002098
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002099 if (chip->fastchg_on ^ fastchg_on) {
2100 chip->fastchg_on = fastchg_on;
2101 if (chip->bat_if_base) {
2102 pr_debug("psy changed batt_psy\n");
2103 power_supply_changed(&chip->batt_psy);
2104 }
2105
2106 pr_debug("psy changed usb_psy\n");
2107 power_supply_changed(chip->usb_psy);
2108
2109 if (chip->dc_chgpth_base) {
2110 pr_debug("psy changed dc_psy\n");
2111 power_supply_changed(&chip->dc_psy);
2112 }
2113
2114 if (fastchg_on) {
2115 chip->chg_done = false;
David Keitel59fbb762014-02-05 16:46:24 -08002116 bypass_vbatdet_comp(chip, 1);
2117 if (chip->bat_is_warm || chip->bat_is_cool) {
2118 qpnp_chg_set_appropriate_vddmax(chip);
2119 qpnp_chg_set_appropriate_battery_current(chip);
2120 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002121
2122 if (chip->resuming_charging) {
2123 chip->resuming_charging = false;
2124 qpnp_chg_set_appropriate_vbatdet(chip);
2125 }
2126
2127 if (!chip->charging_disabled) {
2128 schedule_delayed_work(&chip->eoc_work,
2129 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2130 pm_stay_awake(chip->dev);
2131 }
David Keitel975b5352014-01-27 14:28:04 -08002132 if (chip->parallel_ovp_mode)
2133 switch_parallel_ovp_mode(chip, 1);
David Keitelcd2e1022014-05-02 17:25:15 -07002134
2135 if (ext_ovp_isns_present &&
2136 chip->ext_ovp_ic_gpio_enabled) {
2137 pr_debug("EXT OVP IC ISNS enabled\n");
2138 gpio_direction_output(
2139 chip->ext_ovp_isns_gpio, 1);
2140 }
David Keitel975b5352014-01-27 14:28:04 -08002141 } else {
2142 if (chip->parallel_ovp_mode)
2143 switch_parallel_ovp_mode(chip, 0);
David Keitel59fbb762014-02-05 16:46:24 -08002144 if (!chip->bat_is_warm && !chip->bat_is_cool)
2145 bypass_vbatdet_comp(chip, 0);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002146 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002147 }
2148
David Keitel47185a62013-05-15 18:54:10 -07002149 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -08002150
2151 return IRQ_HANDLED;
2152}
2153
David Keitel03ee6b52012-10-22 12:25:19 -07002154static int
David Keitel432e1232013-06-05 16:10:18 -07002155qpnp_dc_property_is_writeable(struct power_supply *psy,
2156 enum power_supply_property psp)
2157{
2158 switch (psp) {
2159 case POWER_SUPPLY_PROP_CURRENT_MAX:
2160 return 1;
2161 default:
2162 break;
2163 }
2164
2165 return 0;
2166}
2167
2168static int
David Keitel03ee6b52012-10-22 12:25:19 -07002169qpnp_batt_property_is_writeable(struct power_supply *psy,
2170 enum power_supply_property psp)
2171{
2172 switch (psp) {
2173 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08002174 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07002175 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel2586f0a2013-08-20 10:02:26 -07002176 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002177 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
Fenglin Wuc64e9942014-08-22 13:47:34 +08002178 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
David Keitel337bd862013-07-15 21:42:58 -07002179 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07002180 case POWER_SUPPLY_PROP_COOL_TEMP:
2181 case POWER_SUPPLY_PROP_WARM_TEMP:
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002182 case POWER_SUPPLY_PROP_CAPACITY:
David Keitel03ee6b52012-10-22 12:25:19 -07002183 return 1;
2184 default:
2185 break;
2186 }
2187
2188 return 0;
2189}
2190
David Keitel6f865cd2012-11-30 15:04:32 -08002191static int
David Keitelbe208252013-01-31 14:49:25 -08002192qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
2193{
2194 int rc;
2195
2196 if (chip->charging_disabled && enable) {
2197 pr_debug("Charging disabled\n");
2198 return 0;
2199 }
2200
2201 rc = qpnp_chg_charge_en(chip, enable);
2202 if (rc) {
2203 pr_err("Failed to control charging %d\n", rc);
2204 return rc;
2205 }
2206
2207 rc = qpnp_chg_force_run_on_batt(chip, !enable);
2208 if (rc)
2209 pr_err("Failed to control charging %d\n", rc);
2210
2211 return rc;
2212}
2213
David Keitel454ee842013-03-08 16:19:11 -08002214static int
2215switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002216{
2217 int rc;
2218
2219 pr_debug("switch to charge mode\n");
2220 if (!qpnp_chg_is_otg_en_set(chip))
2221 return 0;
2222
David Keitel8b9bd312014-01-15 14:44:00 -08002223 if (chip->type == SMBBP) {
2224 rc = qpnp_chg_masked_write(chip,
2225 chip->boost_base + BOOST_ILIM,
2226 BOOST_ILIMT_MASK,
2227 BOOST_ILIMIT_DEF, 1);
2228 if (rc) {
2229 pr_err("Failed to set ilim rc = %d\n", rc);
2230 return rc;
2231 }
2232 }
2233
David Keitel6f865cd2012-11-30 15:04:32 -08002234 /* enable usb ovp fet */
2235 rc = qpnp_chg_masked_write(chip,
2236 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2237 USB_OTG_EN_BIT,
2238 0, 1);
2239 if (rc) {
2240 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
2241 return rc;
2242 }
2243
2244 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2245 if (rc) {
2246 pr_err("Failed re-enable charging rc = %d\n", rc);
2247 return rc;
2248 }
2249
2250 return 0;
2251}
2252
David Keitel454ee842013-03-08 16:19:11 -08002253static int
2254switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002255{
2256 int rc;
David Keitel8b9bd312014-01-15 14:44:00 -08002257 u8 usb_sts;
David Keitel6f865cd2012-11-30 15:04:32 -08002258
2259 pr_debug("switch to host mode\n");
2260 if (qpnp_chg_is_otg_en_set(chip))
2261 return 0;
2262
David Keitel975b5352014-01-27 14:28:04 -08002263 if (chip->parallel_ovp_mode)
2264 switch_parallel_ovp_mode(chip, 0);
2265
David Keitel8b9bd312014-01-15 14:44:00 -08002266 if (chip->type == SMBBP) {
2267 rc = qpnp_chg_masked_write(chip,
2268 chip->boost_base + BOOST_ILIM,
2269 BOOST_ILIMT_MASK,
2270 BOOST_ILIMIT_MIN, 1);
2271 if (rc) {
2272 pr_err("Failed to turn configure ilim rc = %d\n", rc);
2273 return rc;
2274 }
2275 }
2276
David Keitel6d4b9da2013-09-05 17:38:40 -07002277 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
2278 rc = qpnp_chg_force_run_on_batt(chip, 1);
2279 if (rc) {
2280 pr_err("Failed to disable charging rc = %d\n", rc);
2281 return rc;
2282 }
David Keitel6f865cd2012-11-30 15:04:32 -08002283 }
2284
2285 /* force usb ovp fet off */
2286 rc = qpnp_chg_masked_write(chip,
2287 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2288 USB_OTG_EN_BIT,
2289 USB_OTG_EN_BIT, 1);
2290 if (rc) {
2291 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
2292 return rc;
2293 }
2294
David Keitel8b9bd312014-01-15 14:44:00 -08002295 if (chip->type == SMBBP) {
2296 /* Wait for OCP circuitry to be powered up */
2297 msleep(100);
2298 rc = qpnp_chg_read(chip, &usb_sts,
2299 INT_RT_STS(chip->usb_chgpth_base), 1);
2300 if (rc) {
2301 pr_err("failed to read interrupt sts %d\n", rc);
2302 return rc;
2303 }
2304
2305 if (usb_sts & COARSE_DET_USB_IRQ) {
2306 rc = qpnp_chg_masked_write(chip,
2307 chip->boost_base + BOOST_ILIM,
2308 BOOST_ILIMT_MASK,
2309 BOOST_ILIMIT_DEF, 1);
2310 if (rc) {
2311 pr_err("Failed to set ilim rc = %d\n", rc);
2312 return rc;
2313 }
2314 } else {
2315 pr_warn_ratelimited("USB short to GND detected!\n");
2316 }
2317 }
2318
David Keitel6f865cd2012-11-30 15:04:32 -08002319 return 0;
2320}
2321
David Keitel80668952012-07-27 14:25:49 -07002322static enum power_supply_property pm_power_props_mains[] = {
2323 POWER_SUPPLY_PROP_PRESENT,
2324 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07002325 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07002326};
2327
2328static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07002329 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07002330 POWER_SUPPLY_PROP_STATUS,
2331 POWER_SUPPLY_PROP_CHARGE_TYPE,
2332 POWER_SUPPLY_PROP_HEALTH,
2333 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002334 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07002335 POWER_SUPPLY_PROP_TECHNOLOGY,
2336 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
2337 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
2338 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2339 POWER_SUPPLY_PROP_CAPACITY,
2340 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07002341 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
David Keitel2586f0a2013-08-20 10:02:26 -07002342 POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002343 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
Fenglin Wuc64e9942014-08-22 13:47:34 +08002344 POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS,
David Keitel337bd862013-07-15 21:42:58 -07002345 POWER_SUPPLY_PROP_VOLTAGE_MIN,
2346 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07002347 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302348 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07002349 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07002350 POWER_SUPPLY_PROP_COOL_TEMP,
2351 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08002352 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302353 POWER_SUPPLY_PROP_CYCLE_COUNT,
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002354 POWER_SUPPLY_PROP_VOLTAGE_OCV,
David Keitel80668952012-07-27 14:25:49 -07002355};
2356
2357static char *pm_power_supplied_to[] = {
2358 "battery",
2359};
2360
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07002361static char *pm_batt_supplied_to[] = {
2362 "bms",
2363};
2364
David Keitel337bd862013-07-15 21:42:58 -07002365static int charger_monitor;
2366module_param(charger_monitor, int, 0644);
2367
David Keitel2586f0a2013-08-20 10:02:26 -07002368static int ext_ovp_present;
2369module_param(ext_ovp_present, int, 0444);
2370
David Keitelcd2e1022014-05-02 17:25:15 -07002371#define OVP_USB_WALL_TRSH_MA 200
David Keitel80668952012-07-27 14:25:49 -07002372static int
2373qpnp_power_get_property_mains(struct power_supply *psy,
2374 enum power_supply_property psp,
2375 union power_supply_propval *val)
2376{
2377 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2378 dc_psy);
2379
2380 switch (psp) {
2381 case POWER_SUPPLY_PROP_PRESENT:
2382 case POWER_SUPPLY_PROP_ONLINE:
2383 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07002384 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07002385 return 0;
2386
2387 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
2388 break;
David Keitel432e1232013-06-05 16:10:18 -07002389 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07002390 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07002391 break;
David Keitel80668952012-07-27 14:25:49 -07002392 default:
2393 return -EINVAL;
2394 }
2395 return 0;
2396}
2397
David Keitel7ac385e2013-08-19 18:02:40 -07002398static void
2399qpnp_aicl_check_work(struct work_struct *work)
2400{
2401 struct delayed_work *dwork = to_delayed_work(work);
2402 struct qpnp_chg_chip *chip = container_of(dwork,
2403 struct qpnp_chg_chip, aicl_check_work);
2404 union power_supply_propval ret = {0,};
2405
2406 if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
2407 chip->usb_psy->get_property(chip->usb_psy,
2408 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
2409 if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
2410 pr_debug("no charger_monitor present set iusbmax %d\n",
2411 ret.intval / 1000);
2412 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2413 }
2414 } else {
2415 pr_debug("charger_monitor is present\n");
2416 }
2417 chip->charger_monitor_checked = true;
2418}
2419
David Keitel80668952012-07-27 14:25:49 -07002420static int
2421get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
2422{
2423 int rc = 0;
2424 struct qpnp_vadc_result results;
2425
David Keitelfe51cb92013-04-02 19:42:58 -07002426 if (chip->revision == 0 && chip->type == SMBB) {
2427 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
2428 return 0;
2429 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002430 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07002431 if (rc) {
2432 pr_err("Unable to read vbat rc=%d\n", rc);
2433 return 0;
2434 }
2435 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07002436 }
2437}
2438
2439#define BATT_PRES_BIT BIT(7)
2440static int
2441get_prop_batt_present(struct qpnp_chg_chip *chip)
2442{
2443 u8 batt_present;
2444 int rc;
2445
2446 rc = qpnp_chg_read(chip, &batt_present,
2447 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
2448 if (rc) {
2449 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
2450 return 0;
2451 };
2452 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
2453}
2454
2455#define BATT_TEMP_HOT BIT(6)
2456#define BATT_TEMP_OK BIT(7)
2457static int
2458get_prop_batt_health(struct qpnp_chg_chip *chip)
2459{
2460 u8 batt_health;
2461 int rc;
2462
2463 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07002464 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07002465 if (rc) {
2466 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
2467 return POWER_SUPPLY_HEALTH_UNKNOWN;
2468 };
2469
2470 if (BATT_TEMP_OK & batt_health)
2471 return POWER_SUPPLY_HEALTH_GOOD;
2472 if (BATT_TEMP_HOT & batt_health)
2473 return POWER_SUPPLY_HEALTH_OVERHEAT;
2474 else
2475 return POWER_SUPPLY_HEALTH_COLD;
2476}
2477
2478static int
2479get_prop_charge_type(struct qpnp_chg_chip *chip)
2480{
2481 int rc;
2482 u8 chgr_sts;
2483
2484 if (!get_prop_batt_present(chip))
2485 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2486
2487 rc = qpnp_chg_read(chip, &chgr_sts,
2488 INT_RT_STS(chip->chgr_base), 1);
2489 if (rc) {
2490 pr_err("failed to read interrupt sts %d\n", rc);
2491 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2492 }
2493
2494 if (chgr_sts & TRKL_CHG_ON_IRQ)
2495 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
2496 if (chgr_sts & FAST_CHG_ON_IRQ)
2497 return POWER_SUPPLY_CHARGE_TYPE_FAST;
2498
2499 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2500}
2501
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002502#define DEFAULT_CAPACITY 50
2503static int
2504get_batt_capacity(struct qpnp_chg_chip *chip)
2505{
2506 union power_supply_propval ret = {0,};
2507
2508 if (chip->fake_battery_soc >= 0)
2509 return chip->fake_battery_soc;
2510 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2511 return DEFAULT_CAPACITY;
2512 if (chip->bms_psy) {
2513 chip->bms_psy->get_property(chip->bms_psy,
2514 POWER_SUPPLY_PROP_CAPACITY, &ret);
2515 return ret.intval;
2516 }
2517 return DEFAULT_CAPACITY;
2518}
2519
David Keitel80668952012-07-27 14:25:49 -07002520static int
2521get_prop_batt_status(struct qpnp_chg_chip *chip)
2522{
2523 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002524 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07002525
David Keitel9fd07382013-05-02 15:37:44 -07002526 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07002527 if (rc) {
2528 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08002529 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07002530 }
2531
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002532 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
2533 if (rc) {
2534 pr_err("failed to read bat_if sts %d\n", rc);
2535 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2536 }
2537
David Keitela8099ff2014-01-06 11:31:40 -08002538 if ((chgr_sts & TRKL_CHG_ON_IRQ) && !(bat_if_sts & BAT_FET_ON_IRQ))
David Keitel80668952012-07-27 14:25:49 -07002539 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002540 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07002541 return POWER_SUPPLY_STATUS_CHARGING;
2542
Chunmei Caib3999b22014-07-11 15:38:13 +08002543 /*
2544 * Report full if state of charge is 100 or chg_done is true
2545 * when a charger is connected and boost is disabled
2546 */
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002547 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
Chunmei Caib3999b22014-07-11 15:38:13 +08002548 qpnp_chg_is_dc_chg_plugged_in(chip)) &&
2549 (chip->chg_done || get_batt_capacity(chip) == 100)
2550 && qpnp_chg_is_boost_en_set(chip) == 0) {
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002551 return POWER_SUPPLY_STATUS_FULL;
2552 }
2553
David Keitel80668952012-07-27 14:25:49 -07002554 return POWER_SUPPLY_STATUS_DISCHARGING;
2555}
2556
2557static int
2558get_prop_current_now(struct qpnp_chg_chip *chip)
2559{
2560 union power_supply_propval ret = {0,};
2561
2562 if (chip->bms_psy) {
2563 chip->bms_psy->get_property(chip->bms_psy,
2564 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
2565 return ret.intval;
2566 } else {
2567 pr_debug("No BMS supply registered return 0\n");
2568 }
2569
2570 return 0;
2571}
2572
2573static int
2574get_prop_full_design(struct qpnp_chg_chip *chip)
2575{
2576 union power_supply_propval ret = {0,};
2577
2578 if (chip->bms_psy) {
2579 chip->bms_psy->get_property(chip->bms_psy,
2580 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
2581 return ret.intval;
2582 } else {
2583 pr_debug("No BMS supply registered return 0\n");
2584 }
2585
2586 return 0;
2587}
2588
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302589static int
2590get_prop_charge_full(struct qpnp_chg_chip *chip)
2591{
2592 union power_supply_propval ret = {0,};
2593
2594 if (chip->bms_psy) {
2595 chip->bms_psy->get_property(chip->bms_psy,
2596 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
2597 return ret.intval;
2598 } else {
2599 pr_debug("No BMS supply registered return 0\n");
2600 }
2601
2602 return 0;
2603}
2604
David Keitel80668952012-07-27 14:25:49 -07002605static int
2606get_prop_capacity(struct qpnp_chg_chip *chip)
2607{
2608 union power_supply_propval ret = {0,};
Xiaozhe Shibda84992013-09-05 10:39:11 -07002609 int battery_status, bms_status, soc, charger_in;
David Keitel80668952012-07-27 14:25:49 -07002610
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002611 if (chip->fake_battery_soc >= 0)
2612 return chip->fake_battery_soc;
2613
David Keitel3dd5e0f2012-12-12 18:12:36 -08002614 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2615 return DEFAULT_CAPACITY;
2616
David Keitel80668952012-07-27 14:25:49 -07002617 if (chip->bms_psy) {
2618 chip->bms_psy->get_property(chip->bms_psy,
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002619 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002620 soc = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002621 battery_status = get_prop_batt_status(chip);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002622 chip->bms_psy->get_property(chip->bms_psy,
2623 POWER_SUPPLY_PROP_STATUS, &ret);
2624 bms_status = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002625 charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
2626 qpnp_chg_is_dc_chg_plugged_in(chip);
2627
2628 if (battery_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shibda84992013-09-05 10:39:11 -07002629 && bms_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002630 && charger_in
Xiaozhe Shie8504482013-10-30 18:10:31 -07002631 && !chip->bat_is_cool
2632 && !chip->bat_is_warm
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002633 && !chip->resuming_charging
2634 && !chip->charging_disabled
2635 && chip->soc_resume_limit
Xiaozhe Shibda84992013-09-05 10:39:11 -07002636 && soc <= chip->soc_resume_limit) {
2637 pr_debug("resuming charging at %d%% soc\n", soc);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002638 chip->resuming_charging = true;
David Keitelbf6a1062014-01-23 10:57:36 -08002639 qpnp_chg_irq_wake_enable(&chip->chg_fastchg);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002640 qpnp_chg_set_appropriate_vbatdet(chip);
2641 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2642 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002643 if (soc == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07002644 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
2645 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07002646 pr_warn_ratelimited("Battery 0, CHG absent\n");
2647 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002648 return soc;
David Keitel80668952012-07-27 14:25:49 -07002649 } else {
2650 pr_debug("No BMS supply registered return 50\n");
2651 }
2652
2653 /* return default capacity to avoid userspace
2654 * from shutting down unecessarily */
2655 return DEFAULT_CAPACITY;
2656}
2657
David Keitel3dd5e0f2012-12-12 18:12:36 -08002658#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07002659#define MAX_TOLERABLE_BATT_TEMP_DDC 680
2660static int
2661get_prop_batt_temp(struct qpnp_chg_chip *chip)
2662{
2663 int rc = 0;
2664 struct qpnp_vadc_result results;
2665
David Keitel3dd5e0f2012-12-12 18:12:36 -08002666 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2667 return DEFAULT_TEMP;
2668
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002669 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07002670 if (rc) {
2671 pr_debug("Unable to read batt temperature rc=%d\n", rc);
2672 return 0;
David Keitel80668952012-07-27 14:25:49 -07002673 }
Xiaozhe Shi4c8458a2013-11-26 13:00:56 -08002674 pr_debug("get_bat_temp %d, %lld\n",
David Keitela2dbfc72013-06-07 11:10:14 -07002675 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07002676
David Keitela2dbfc72013-06-07 11:10:14 -07002677 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07002678}
2679
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302680static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
2681{
2682 union power_supply_propval ret = {0,};
2683
2684 if (chip->bms_psy)
2685 chip->bms_psy->get_property(chip->bms_psy,
2686 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
2687 return ret.intval;
2688}
2689
David Keitel337bd862013-07-15 21:42:58 -07002690static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
2691{
2692 u8 buck_sts;
2693 int rc;
2694
2695 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2696
2697 if (rc) {
2698 pr_err("spmi read failed: addr=%03X, rc=%d\n",
2699 INT_RT_STS(chip->buck_base), rc);
2700 return rc;
2701 }
2702 pr_debug("buck usb sts 0x%x\n", buck_sts);
2703
2704 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
2705}
2706
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002707static int get_prop_online(struct qpnp_chg_chip *chip)
2708{
2709 return qpnp_chg_is_batfet_closed(chip);
2710}
2711
David Keitel80668952012-07-27 14:25:49 -07002712static void
2713qpnp_batt_external_power_changed(struct power_supply *psy)
2714{
2715 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2716 batt_psy);
2717 union power_supply_propval ret = {0,};
2718
2719 if (!chip->bms_psy)
2720 chip->bms_psy = power_supply_get_by_name("bms");
2721
2722 chip->usb_psy->get_property(chip->usb_psy,
2723 POWER_SUPPLY_PROP_ONLINE, &ret);
2724
David Keitelc69f2d62013-03-17 14:52:35 -07002725 /* Only honour requests while USB is present */
2726 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002727 chip->usb_psy->get_property(chip->usb_psy,
2728 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07002729
2730 if (chip->prev_usb_max_ma == ret.intval)
2731 goto skip_set_iusb_max;
2732
Zhenhua Huangdd619742013-10-24 10:02:07 +08002733 chip->prev_usb_max_ma = ret.intval;
2734
David Keitel87473252013-03-21 14:39:45 -07002735 if (ret.intval <= 2 && !chip->use_default_batt_values &&
2736 get_prop_batt_present(chip)) {
David Keitela9185602013-11-12 17:55:48 -08002737 if (ret.intval == 2)
2738 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07002739 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07002740 } else {
David Keiteld681cda2012-10-02 15:44:21 -07002741 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel820a90d2014-03-25 18:18:04 -07002742 if (qpnp_is_dc_higher_prio(chip)
2743 && qpnp_chg_is_dc_chg_plugged_in(chip)) {
2744 pr_debug("dc has higher priority\n");
2745 qpnp_chg_iusbmax_set(chip,
2746 QPNP_CHG_I_MAX_MIN_100);
2747 } else if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
David Keitel7ac385e2013-08-19 18:02:40 -07002748 && (charger_monitor ||
2749 !chip->charger_monitor_checked)) {
David Keitel820a90d2014-03-25 18:18:04 -07002750 if (!qpnp_is_dc_higher_prio(chip))
2751 qpnp_chg_idcmax_set(chip,
2752 QPNP_CHG_I_MAX_MIN_100);
David Keitelcd2e1022014-05-02 17:25:15 -07002753 if (unlikely(ext_ovp_present)) {
David Keitel820a90d2014-03-25 18:18:04 -07002754 qpnp_chg_iusbmax_set(chip,
2755 OVP_USB_WALL_TRSH_MA);
David Keitelcd2e1022014-05-02 17:25:15 -07002756 } else if (unlikely(
2757 ext_ovp_isns_present)) {
David Keitel05b34692014-07-22 11:59:59 -07002758 qpnp_chg_iusb_trim_set(chip,
2759 chip->usb_trim_default);
David Keitelcd2e1022014-05-02 17:25:15 -07002760 qpnp_chg_iusbmax_set(chip,
2761 IOVP_USB_WALL_TRSH_MA);
2762 } else {
2763 qpnp_chg_iusbmax_set(chip,
2764 USB_WALL_THRESHOLD_MA);
2765 }
David Keitel337bd862013-07-15 21:42:58 -07002766 } else {
2767 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2768 }
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002769
2770 if ((chip->flags & POWER_STAGE_WA)
2771 && ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
Zhenhua Huangdc335512013-10-30 11:45:15 +08002772 && !chip->power_stage_workaround_running
2773 && chip->power_stage_workaround_enable) {
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002774 chip->power_stage_workaround_running = true;
2775 pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
2776 charger_monitor);
2777 schedule_work(&chip->reduce_power_stage_work);
2778 }
David Keitelc69f2d62013-03-17 14:52:35 -07002779 }
David Keitel80668952012-07-27 14:25:49 -07002780 }
2781
David Keitelfd305ee2013-07-19 20:19:06 -07002782skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07002783 pr_debug("end of power supply changed\n");
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002784 pr_debug("psy changed batt_psy\n");
David Keitel80668952012-07-27 14:25:49 -07002785 power_supply_changed(&chip->batt_psy);
2786}
2787
2788static int
2789qpnp_batt_power_get_property(struct power_supply *psy,
2790 enum power_supply_property psp,
2791 union power_supply_propval *val)
2792{
2793 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2794 batt_psy);
2795
2796 switch (psp) {
2797 case POWER_SUPPLY_PROP_STATUS:
2798 val->intval = get_prop_batt_status(chip);
2799 break;
2800 case POWER_SUPPLY_PROP_CHARGE_TYPE:
2801 val->intval = get_prop_charge_type(chip);
2802 break;
2803 case POWER_SUPPLY_PROP_HEALTH:
2804 val->intval = get_prop_batt_health(chip);
2805 break;
2806 case POWER_SUPPLY_PROP_PRESENT:
2807 val->intval = get_prop_batt_present(chip);
2808 break;
2809 case POWER_SUPPLY_PROP_TECHNOLOGY:
2810 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2811 break;
2812 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2813 val->intval = chip->max_voltage_mv * 1000;
2814 break;
2815 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2816 val->intval = chip->min_voltage_mv * 1000;
2817 break;
2818 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2819 val->intval = get_prop_battery_voltage_now(chip);
2820 break;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002821 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2822 val->intval = chip->insertion_ocv_uv;
2823 break;
David Keitel80668952012-07-27 14:25:49 -07002824 case POWER_SUPPLY_PROP_TEMP:
2825 val->intval = get_prop_batt_temp(chip);
2826 break;
David Keitelec3c09802013-06-13 13:05:30 -07002827 case POWER_SUPPLY_PROP_COOL_TEMP:
2828 val->intval = chip->cool_bat_decidegc;
2829 break;
2830 case POWER_SUPPLY_PROP_WARM_TEMP:
2831 val->intval = chip->warm_bat_decidegc;
2832 break;
David Keitel80668952012-07-27 14:25:49 -07002833 case POWER_SUPPLY_PROP_CAPACITY:
2834 val->intval = get_prop_capacity(chip);
2835 break;
2836 case POWER_SUPPLY_PROP_CURRENT_NOW:
2837 val->intval = get_prop_current_now(chip);
2838 break;
2839 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2840 val->intval = get_prop_full_design(chip);
2841 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302842 case POWER_SUPPLY_PROP_CHARGE_FULL:
2843 val->intval = get_prop_charge_full(chip);
2844 break;
David Keitelb80eda82012-10-15 10:49:11 -07002845 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07002846 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07002847 break;
David Keitelbe208252013-01-31 14:49:25 -08002848 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2849 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07002850 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302851 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2852 val->intval = get_prop_cycle_count(chip);
2853 break;
David Keitel337bd862013-07-15 21:42:58 -07002854 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
2855 val->intval = get_prop_vchg_loop(chip);
2856 break;
2857 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2858 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
2859 break;
David Keitel2586f0a2013-08-20 10:02:26 -07002860 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
2861 val->intval = qpnp_chg_iusb_trim_get(chip);
2862 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002863 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
2864 val->intval = chip->aicl_settled;
2865 break;
David Keitel337bd862013-07-15 21:42:58 -07002866 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2867 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
2868 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002869 case POWER_SUPPLY_PROP_ONLINE:
2870 val->intval = get_prop_online(chip);
2871 break;
Fenglin Wuc64e9942014-08-22 13:47:34 +08002872 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
2873 val->intval = qpnp_chg_vchg_loop_debouncer_setting_get(chip);
2874 break;
2875
David Keitelb80eda82012-10-15 10:49:11 -07002876 default:
2877 return -EINVAL;
2878 }
2879
David Keitelb80eda82012-10-15 10:49:11 -07002880 return 0;
David Keitel80668952012-07-27 14:25:49 -07002881}
2882
David Keitel89c17752013-06-28 14:52:48 -07002883#define BTC_CONFIG_ENABLED BIT(7)
2884#define BTC_COLD BIT(1)
2885#define BTC_HOT BIT(0)
2886static int
2887qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
2888{
2889 u8 btc_cfg = 0, mask = 0;
2890
2891 /* Do nothing if battery peripheral not present */
2892 if (!chip->bat_if_base)
2893 return 0;
2894
2895 if ((chip->hot_batt_p == HOT_THD_25_PCT)
2896 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
2897 btc_cfg |= btc_value[chip->hot_batt_p];
2898 mask |= BTC_HOT;
2899 }
2900
2901 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
2902 (chip->cold_batt_p == COLD_THD_80_PCT)) {
2903 btc_cfg |= btc_value[chip->cold_batt_p];
2904 mask |= BTC_COLD;
2905 }
2906
2907 if (chip->btc_disabled)
2908 mask |= BTC_CONFIG_ENABLED;
2909
2910 return qpnp_chg_masked_write(chip,
2911 chip->bat_if_base + BAT_IF_BTC_CTRL,
2912 mask, btc_cfg, 1);
2913}
2914
David Keitel5d44fa52012-12-03 16:37:31 -08002915#define QPNP_CHG_IBATSAFE_MIN_MA 100
2916#define QPNP_CHG_IBATSAFE_MAX_MA 3250
2917#define QPNP_CHG_I_STEP_MA 50
2918#define QPNP_CHG_I_MIN_MA 100
2919#define QPNP_CHG_I_MASK 0x3F
2920static int
2921qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
2922{
2923 u8 temp;
2924
2925 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
2926 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
2927 pr_err("bad mA=%d asked to set\n", safe_current);
2928 return -EINVAL;
2929 }
2930
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08002931 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08002932 return qpnp_chg_masked_write(chip,
2933 chip->chgr_base + CHGR_IBAT_SAFE,
2934 QPNP_CHG_I_MASK, temp, 1);
2935}
David Keitel80668952012-07-27 14:25:49 -07002936
2937#define QPNP_CHG_ITERM_MIN_MA 100
2938#define QPNP_CHG_ITERM_MAX_MA 250
2939#define QPNP_CHG_ITERM_STEP_MA 50
2940#define QPNP_CHG_ITERM_MASK 0x03
2941static int
2942qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
2943{
2944 u8 temp;
2945
2946 if (term_current < QPNP_CHG_ITERM_MIN_MA
2947 || term_current > QPNP_CHG_ITERM_MAX_MA) {
2948 pr_err("bad mA=%d asked to set\n", term_current);
2949 return -EINVAL;
2950 }
2951
2952 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
2953 / QPNP_CHG_ITERM_STEP_MA;
2954 return qpnp_chg_masked_write(chip,
2955 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
2956 QPNP_CHG_ITERM_MASK, temp, 1);
2957}
2958
David Keitelff5d0472013-04-04 11:36:06 -07002959#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07002960#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07002961static int
2962qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
2963{
2964 u8 temp;
2965
2966 if (chg_current < QPNP_CHG_IBATMAX_MIN
2967 || chg_current > QPNP_CHG_IBATMAX_MAX) {
2968 pr_err("bad mA=%d asked to set\n", chg_current);
2969 return -EINVAL;
2970 }
David Keitelff5d0472013-04-04 11:36:06 -07002971 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07002972 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
2973 QPNP_CHG_I_MASK, temp, 1);
2974}
2975
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002976static int
2977qpnp_chg_ibatmax_get(struct qpnp_chg_chip *chip, int *chg_current)
2978{
2979 int rc;
2980 u8 temp;
2981
2982 *chg_current = 0;
2983 rc = qpnp_chg_read(chip, &temp, chip->chgr_base + CHGR_IBAT_MAX, 1);
2984 if (rc) {
2985 pr_err("failed read ibat_max rc=%d\n", rc);
2986 return rc;
2987 }
2988
2989 *chg_current = ((temp & QPNP_CHG_I_MASK) * QPNP_CHG_I_STEP_MA);
2990
2991 return 0;
2992}
2993
David Keitela4b7b592013-04-11 18:34:35 -07002994#define QPNP_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002995#define QPNP_CHG_TCHG_EN_MASK 0x80
David Keitela4b7b592013-04-11 18:34:35 -07002996#define QPNP_CHG_TCHG_MIN 4
2997#define QPNP_CHG_TCHG_MAX 512
2998#define QPNP_CHG_TCHG_STEP 4
2999static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
3000{
3001 u8 temp;
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08003002 int rc;
David Keitela4b7b592013-04-11 18:34:35 -07003003
3004 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
3005 pr_err("bad max minutes =%d asked to set\n", minutes);
3006 return -EINVAL;
3007 }
3008
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08003009 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
3010 QPNP_CHG_TCHG_EN_MASK, 0, 1);
3011 if (rc) {
3012 pr_err("failed write tchg_max_en rc=%d\n", rc);
3013 return rc;
3014 }
3015
3016 temp = minutes / QPNP_CHG_TCHG_STEP - 1;
3017
3018 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07003019 QPNP_CHG_TCHG_MASK, temp, 1);
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08003020 if (rc) {
3021 pr_err("failed write tchg_max_en rc=%d\n", rc);
3022 return rc;
3023 }
3024
3025 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
3026 QPNP_CHG_TCHG_EN_MASK, QPNP_CHG_TCHG_EN_MASK, 1);
3027 if (rc) {
3028 pr_err("failed write tchg_max_en rc=%d\n", rc);
3029 return rc;
3030 }
3031
3032 return 0;
David Keitela4b7b592013-04-11 18:34:35 -07003033}
David Keitel80668952012-07-27 14:25:49 -07003034
David Keitel59fbb762014-02-05 16:46:24 -08003035static void
3036qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
3037{
3038 unsigned int chg_current = chip->max_bat_chg_current;
3039
3040 if (chip->bat_is_cool)
3041 chg_current = min(chg_current, chip->cool_bat_chg_ma);
3042
3043 if (chip->bat_is_warm)
3044 chg_current = min(chg_current, chip->warm_bat_chg_ma);
3045
3046 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
3047 chg_current = min(chg_current,
3048 chip->thermal_mitigation[chip->therm_lvl_sel]);
3049
3050 pr_debug("setting %d mA\n", chg_current);
3051 qpnp_chg_ibatmax_set(chip, chg_current);
3052}
3053
David Keitel80668952012-07-27 14:25:49 -07003054static int
3055qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
3056{
3057 u8 temp;
3058
3059 if (voltage < QPNP_CHG_V_MIN_MV
3060 || voltage > QPNP_CHG_V_MAX_MV) {
3061 pr_err("bad mV=%d asked to set\n", voltage);
3062 return -EINVAL;
3063 }
3064 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
3065 pr_debug("voltage=%d setting %02x\n", voltage, temp);
3066 return qpnp_chg_write(chip, &temp,
3067 chip->chgr_base + CHGR_VDD_SAFE, 1);
3068}
3069
wangxlee3614a2015-02-03 13:13:11 +08003070#ifdef CONFIG_TCMD
3071int qpnp_disable_source_current(bool disable)
3072{
3073 int ret =-1;
3074 if(!the_chip)
3075 {
3076 pr_err("called before init\n");
3077 return -EINVAL;
3078 }
3079 if(disable)
3080 {
3081 ret = qpnp_chg_charge_en(the_chip, !disable);
3082 if(ret)
3083 {
3084 printk("TCMD : qpnp_chg_charge_en failed. result = %d", ret);
3085 return ret;
3086 }
3087 else
3088 {
3089 ret = qpnp_chg_force_run_on_batt(the_chip, true);
3090 if(ret)
3091 printk("TCMD : pnp_chg_force_run_on_batt failed. result = %d", ret);
3092 }
3093 }
3094 else
3095 {
3096 ret = qpnp_chg_force_run_on_batt(the_chip, false);
3097 if(ret)
3098 {
3099 printk("TCMD : pnp_chg_force_run_on_batt failed. result = %d", ret);
3100 return ret;
3101 }
3102 else
3103 {
3104 ret = qpnp_chg_charge_en(the_chip, !disable);
3105 if(ret)
3106 printk("TCMD : qpnp_chg_charge_en failed. result = %d", ret);
3107 }
3108 }
3109 return ret;
3110}
3111
3112EXPORT_SYMBOL(qpnp_disable_source_current);
3113
3114int qpnp_disable_usb_charging(bool disable)
3115{
3116 int ret =-1;
3117 if (!the_chip)
3118 {
3119 pr_err("called before init\n");
3120 return -EINVAL;
3121 }
3122
3123 ret = qpnp_chg_usb_suspend_enable(the_chip, disable);
3124 if(disable)
3125 {
3126 printk("TCMD : Disable USB charging\n");
3127 ret = qpnp_chg_iusbmax_set(the_chip, QPNP_CHG_I_MAX_MIN_100);
3128 }
3129 else
3130 {
3131 printk("TCMD : Enable USB charging\n");
3132 ret = qpnp_chg_iusbmax_set(the_chip, QPNP_CHG_I_MAX_MAX_MA);
3133 if(ret)
3134 {
3135 printk("TCMD : FAILED to set MAX USB current !\n");
3136 }
3137 else
3138 {
3139 ret = qpnp_disable_source_current(false);
3140 if(ret)
3141 {
3142 printk("TCMD : FAILED to enable source current !\n");
3143 }
3144 }
3145 }
3146 return ret;
3147}
3148
3149EXPORT_SYMBOL(qpnp_disable_usb_charging);
3150
wangxlbe091422014-12-31 10:08:48 +08003151int qpnp_chg_priority(int enable)
3152{
3153 int rc = 0,rc1 = 0;
3154 u8 value;
3155 if (!the_chip)
3156 {
3157 pr_err("the_chip is NULL\n");
3158 return -EINVAL;
3159 }
3160 printk("TCMD : setting %s priority\n", enable ? "DC_IN" : "USB_IN");
3161 /*This bit to change priority of wireless charging path and USB charging path*/
3162 rc = qpnp_chg_masked_write(the_chip,
3163 the_chip->usb_chgpth_base + CHGR_USB_PRIORITY_SEL,
3164 CHG_PTH_PRIORITY_SEL,
3165 enable ? CHG_PTH_PRIORITY_SEL : 0, 1);
3166 if(rc){
3167 printk("TCMD :failed to set %s priority\n", enable ? "DC_IN" : "USB_IN");
3168 }
3169
3170 rc1 = qpnp_chg_read(the_chip, &value, the_chip->usb_chgpth_base + CHGR_USB_PRIORITY_SEL, 1);
3171 if (rc1) {
3172 printk("TCMD :failed to read 0x%02x value: %d\n",the_chip->usb_chgpth_base + CHGR_USB_PRIORITY_SEL,rc1);
3173 return rc1;
3174 }
3175 printk("TCMD :0x%02x value = 0x%02x\n",the_chip->usb_chgpth_base + CHGR_USB_PRIORITY_SEL,value);
3176
3177 return rc;
3178}
3179
3180EXPORT_SYMBOL(qpnp_chg_priority);
3181
wangxlee3614a2015-02-03 13:13:11 +08003182int qpnp_set_max_battery_charge_current(bool enable)
3183{
wangxl07c6bc92014-12-31 10:07:44 +08003184 int ret = -1;
wangxlee3614a2015-02-03 13:13:11 +08003185 unsigned int chg_current = 0;
3186 if (!the_chip)
3187 {
3188 pr_err("called before init\n");
3189 return -EINVAL;
3190 }
3191
wangxl07c6bc92014-12-31 10:07:44 +08003192 chg_current = (enable) ? 850 : the_chip->warm_bat_chg_ma;
wangxlee3614a2015-02-03 13:13:11 +08003193
3194 ret = qpnp_chg_ibatmax_set(the_chip, chg_current);
wangxl07c6bc92014-12-31 10:07:44 +08003195 if(ret < 0) {
3196 return ret;
3197 }
3198 ret = qpnp_chg_iusbmax_set(the_chip, 1500);
wangxlee3614a2015-02-03 13:13:11 +08003199 return ret;
3200}
3201
3202EXPORT_SYMBOL(qpnp_set_max_battery_charge_current);
wangxl07c6bc92014-12-31 10:07:44 +08003203
3204int qpnp_get_usb_max_current(int* usb_max_current){
3205 if (!the_chip)
3206 {
3207 pr_err("called before init\n");
3208 return -EINVAL;
3209 }
3210
3211 *usb_max_current = qpnp_chg_usb_iusbmax_get(the_chip);
3212 return 0;
3213 }
3214
3215EXPORT_SYMBOL(qpnp_get_usb_max_current);
3216
3217int qpnp_get_bat_max_current(int* bat_max_current){
3218 int max_current, rc = -1;
3219 if (!the_chip)
3220 {
3221 pr_err("called before init\n");
3222 return -EINVAL;
3223 }
3224
3225 rc = qpnp_chg_ibatmax_get(the_chip,&max_current);
3226 *bat_max_current = max_current;
3227
3228 return rc;
3229 }
3230
3231EXPORT_SYMBOL(qpnp_get_bat_max_current);
3232
3233int qpnp_set_usb_max_current(int usb_max_current){
3234 int ret = -1;
3235 if (!the_chip)
3236 {
3237 pr_err("called before init\n");
3238 return -EINVAL;
3239 }
3240
3241 ret = qpnp_chg_iusbmax_set(the_chip, usb_max_current);
3242 return ret;
3243 }
3244
3245EXPORT_SYMBOL(qpnp_set_usb_max_current);
3246
3247int qpnp_set_bat_max_current(int bat_max_current){
3248 int rc = -1;
3249 if (!the_chip)
3250 {
3251 pr_err("called before init\n");
3252 return -EINVAL;
3253 }
3254
3255 rc = qpnp_chg_ibatmax_set(the_chip, bat_max_current);
3256
3257 return rc;
3258 }
3259
3260EXPORT_SYMBOL(qpnp_set_bat_max_current);
wangxlee3614a2015-02-03 13:13:11 +08003261#endif
3262
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003263#define IBAT_TRIM_TGT_MA 500
3264#define IBAT_TRIM_OFFSET_MASK 0x7F
3265#define IBAT_TRIM_GOOD_BIT BIT(7)
3266#define IBAT_TRIM_LOW_LIM 20
3267#define IBAT_TRIM_HIGH_LIM 114
3268#define IBAT_TRIM_MEAN 64
3269
3270static void
3271qpnp_chg_trim_ibat(struct qpnp_chg_chip *chip, u8 ibat_trim)
3272{
3273 int ibat_now_ma, ibat_diff_ma, rc;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003274 struct qpnp_iadc_result i_result;
3275 enum qpnp_iadc_channels iadc_channel;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003276
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003277 iadc_channel = chip->use_external_rsense ?
3278 EXTERNAL_RSENSE : INTERNAL_RSENSE;
3279 rc = qpnp_iadc_read(chip->iadc_dev, iadc_channel, &i_result);
3280 if (rc) {
3281 pr_err("Unable to read bat rc=%d\n", rc);
3282 return;
3283 }
3284
3285 ibat_now_ma = i_result.result_ua / 1000;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003286
3287 if (qpnp_chg_is_ibat_loop_active(chip)) {
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003288 ibat_diff_ma = ibat_now_ma - IBAT_TRIM_TGT_MA;
3289
3290 if (abs(ibat_diff_ma) > 50) {
3291 ibat_trim += (ibat_diff_ma / 20);
3292 ibat_trim &= IBAT_TRIM_OFFSET_MASK;
3293 /* reject new ibat_trim if it is outside limits */
3294 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
3295 IBAT_TRIM_HIGH_LIM))
3296 return;
3297 }
Chunmei Cai76705f02014-12-11 09:48:42 +08003298
3299 if (chip->type == SMBBP) {
3300 rc = qpnp_chg_masked_write(chip,
3301 chip->buck_base + SEC_ACCESS,
3302 0xFF, 0xA5, 1);
3303 if (rc) {
3304 pr_err("failed to write SEC_ACCESS: %d\n", rc);
3305 return;
3306 }
3307 }
3308
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003309 ibat_trim |= IBAT_TRIM_GOOD_BIT;
3310 rc = qpnp_chg_write(chip, &ibat_trim,
3311 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3312 if (rc)
3313 pr_err("failed to set IBAT_TRIM rc=%d\n", rc);
3314
3315 pr_debug("ibat_now=%dmA, itgt=%dmA, ibat_diff=%dmA, ibat_trim=%x\n",
3316 ibat_now_ma, IBAT_TRIM_TGT_MA,
3317 ibat_diff_ma, ibat_trim);
3318 } else {
3319 pr_debug("ibat loop not active - cannot calibrate ibat\n");
3320 }
3321}
3322
3323static int
3324qpnp_chg_input_current_settled(struct qpnp_chg_chip *chip)
3325{
3326 int rc, ibat_max_ma;
3327 u8 reg, chgr_sts, ibat_trim, i;
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07003328 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003329
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07003330 if (!usb_present) {
3331 pr_debug("Ignoring AICL settled, since USB is removed\n");
3332 return 0;
3333 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003334 chip->aicl_settled = true;
3335
3336 /*
3337 * Perform the ibat calibration.
3338 * This is for devices which have a IBAT_TRIM error
3339 * which can show IBAT_MAX out of spec.
3340 */
3341 if (!chip->ibat_calibration_enabled)
3342 return 0;
3343
Chunmei Cai76705f02014-12-11 09:48:42 +08003344 if (chip->type != SMBB && chip->type != SMBBP)
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003345 return 0;
3346
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003347 rc = qpnp_chg_read(chip, &reg,
3348 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3349 if (rc) {
3350 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
3351 return rc;
3352 }
3353 if (reg & IBAT_TRIM_GOOD_BIT) {
3354 pr_debug("IBAT_TRIM_GOOD bit already set. Quitting!\n");
3355 return 0;
3356 }
3357 ibat_trim = reg & IBAT_TRIM_OFFSET_MASK;
3358
3359 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
3360 IBAT_TRIM_HIGH_LIM)) {
3361 pr_debug("Improper ibat_trim value=%x setting to value=%x\n",
3362 ibat_trim, IBAT_TRIM_MEAN);
3363 ibat_trim = IBAT_TRIM_MEAN;
Chunmei Cai76705f02014-12-11 09:48:42 +08003364
3365 if (chip->type == SMBBP) {
3366 rc = qpnp_chg_masked_write(chip,
3367 chip->buck_base + SEC_ACCESS,
3368 0xFF, 0xA5, 1);
3369 if (rc) {
3370 pr_err("failed to write SEC_ACCESS: %d\n", rc);
3371 return rc;
3372 }
3373 }
3374
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003375 rc = qpnp_chg_masked_write(chip,
3376 chip->buck_base + BUCK_CTRL_TRIM3,
3377 IBAT_TRIM_OFFSET_MASK, ibat_trim, 1);
3378 if (rc) {
3379 pr_err("failed to set ibat_trim to %x rc=%d\n",
3380 IBAT_TRIM_MEAN, rc);
3381 return rc;
3382 }
3383 }
3384
3385 rc = qpnp_chg_read(chip, &chgr_sts,
3386 INT_RT_STS(chip->chgr_base), 1);
3387 if (rc) {
3388 pr_err("failed to read interrupt sts rc=%d\n", rc);
3389 return rc;
3390 }
3391 if (!(chgr_sts & FAST_CHG_ON_IRQ)) {
3392 pr_debug("Not in fastchg\n");
3393 return rc;
3394 }
3395
3396 /* save the ibat_max to restore it later */
3397 rc = qpnp_chg_ibatmax_get(chip, &ibat_max_ma);
3398 if (rc) {
3399 pr_debug("failed to save ibatmax rc=%d\n", rc);
3400 return rc;
3401 }
3402
3403 rc = qpnp_chg_ibatmax_set(chip, IBAT_TRIM_TGT_MA);
3404 if (rc) {
3405 pr_err("failed to set ibatmax rc=%d\n", rc);
3406 return rc;
3407 }
3408
3409 for (i = 0; i < 3; i++) {
3410 /*
3411 * ibat settling delay - to make sure the BMS controller
3412 * has sufficient time to sample ibat for the configured
3413 * ibat_max
3414 */
3415 msleep(20);
3416 if (qpnp_chg_is_ibat_loop_active(chip))
3417 qpnp_chg_trim_ibat(chip, ibat_trim);
3418 else
3419 pr_debug("ibat loop not active\n");
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003420
3421 /* read the adjusted ibat_trim for further adjustments */
3422 rc = qpnp_chg_read(chip, &ibat_trim,
3423 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3424 if (rc) {
3425 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
3426 break;
3427 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003428 }
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003429
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003430 /* restore IBATMAX */
3431 rc = qpnp_chg_ibatmax_set(chip, ibat_max_ma);
3432 if (rc)
3433 pr_err("failed to restore ibatmax rc=%d\n", rc);
3434
3435 return rc;
3436}
3437
3438
David Keitel6dc4ed42013-05-17 11:08:58 -07003439#define BOOST_MIN_UV 4200000
3440#define BOOST_MAX_UV 5500000
3441#define BOOST_STEP_UV 50000
3442#define BOOST_MIN 16
3443#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
3444static int
3445qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
3446{
3447 u8 reg = 0;
3448
3449 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
3450 pr_err("invalid voltage requested %d uV\n", voltage);
3451 return -EINVAL;
3452 }
3453
3454 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
3455
3456 pr_debug("voltage=%d setting %02x\n", voltage, reg);
3457 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
3458}
3459
3460static int
3461qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
3462{
3463 int rc;
3464 u8 boost_reg;
3465
3466 rc = qpnp_chg_read(chip, &boost_reg,
3467 chip->boost_base + BOOST_VSET, 1);
3468 if (rc) {
3469 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
3470 return rc;
3471 }
3472
3473 if (boost_reg < BOOST_MIN) {
3474 pr_err("Invalid reading from 0x%x\n", boost_reg);
3475 return -EINVAL;
3476 }
3477
3478 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
3479}
3480
David Keitel454ee842013-03-08 16:19:11 -08003481static void
David Keitelbe208252013-01-31 14:49:25 -08003482qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
3483{
3484 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
3485 chip->therm_lvl_sel = lvl_sel;
3486 if (lvl_sel == (chip->thermal_levels - 1)) {
3487 /* disable charging if highest value selected */
3488 qpnp_chg_buck_control(chip, 0);
3489 } else {
3490 qpnp_chg_buck_control(chip, 1);
3491 qpnp_chg_set_appropriate_battery_current(chip);
3492 }
3493 } else {
3494 pr_err("Unsupported level selected %d\n", lvl_sel);
3495 }
3496}
3497
Chunmei Cai661a7cd2014-08-05 17:31:54 +08003498/*
3499 * Increase the SMBB/SMBBP charger overtemp threshold to 150C while firing
3500 * the flash (and/or torch for PM8x26) when the bharger is used as the
3501 * power source.
3502 */
3503static int
3504qpnp_chg_temp_threshold_set(struct qpnp_chg_chip *chip, u8 value)
3505{
3506 int rc;
3507
3508 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
3509 CHGR_CHG_TEMP_THRESH ,
3510 0xFF, value, 1);
3511 if (rc)
3512 pr_err("set CHG_TEMP_THRESH_Flash failed, value = %d, rc = %d\n",
3513 value, rc);
3514
3515 return rc;
3516}
3517
3518#define CHG_TEMP_THRESH_FOR_FLASH 0xFD
3519#define CHG_TEMP_THRESH_DEFAULT 0x94
3520static int
3521qpnp_chg_regulator_flash_wa_enable(struct regulator_dev *rdev)
3522{
3523 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3524 int rc = 0;
3525
3526 if (chip->flags & BOOST_FLASH_WA) {
3527 rc = qpnp_chg_temp_threshold_set(chip,
3528 CHG_TEMP_THRESH_FOR_FLASH);
3529 if (rc) {
3530 pr_err("set chg temp threshold failed rc = %d\n", rc);
3531 return rc;
3532 }
3533 }
3534 chip->is_flash_wa_reg_enabled = true;
3535
3536 return rc;
3537}
3538
3539static int
3540qpnp_chg_regulator_flash_wa_disable(struct regulator_dev *rdev)
3541{
3542 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3543 int rc = 0;
3544
3545 if (chip->flags & BOOST_FLASH_WA) {
3546 rc = qpnp_chg_temp_threshold_set(chip,
3547 chip->chg_temp_thresh_default);
3548 if (rc) {
3549 pr_err("set chg temp threshold failed rc = %d\n", rc);
3550 return rc;
3551 }
3552
3553 }
3554 chip->is_flash_wa_reg_enabled = false;
3555
3556 return rc;
3557}
3558
3559static int
3560qpnp_chg_regulator_flash_wa_is_enabled(struct regulator_dev *rdev)
3561{
3562 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3563
3564 return chip->is_flash_wa_reg_enabled;
3565}
3566
David Keitel6dc4ed42013-05-17 11:08:58 -07003567/* OTG regulator operations */
3568static int
3569qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
3570{
3571 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3572
3573 return switch_usb_to_host_mode(chip);
3574}
3575
3576static int
3577qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
3578{
3579 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3580
3581 return switch_usb_to_charge_mode(chip);
3582}
3583
3584static int
3585qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
3586{
3587 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3588
3589 return qpnp_chg_is_otg_en_set(chip);
3590}
3591
3592static int
3593qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
3594{
3595 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
Chunmei Caib3999b22014-07-11 15:38:13 +08003596 int usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel33f58952013-05-20 16:17:36 -07003597 int rc;
3598
Chunmei Caib3999b22014-07-11 15:38:13 +08003599 if (usb_present && (chip->flags & BOOST_FLASH_WA)) {
David Keitelcd2e1022014-05-02 17:25:15 -07003600
3601 if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
3602 pr_debug("EXT OVP IC ISNS disabled\n");
3603 gpio_direction_output(chip->ext_ovp_isns_gpio, 0);
3604 }
3605
David Keitel33f58952013-05-20 16:17:36 -07003606 qpnp_chg_usb_suspend_enable(chip, 1);
3607
3608 rc = qpnp_chg_masked_write(chip,
3609 chip->usb_chgpth_base + SEC_ACCESS,
3610 0xFF,
3611 0xA5, 1);
3612 if (rc) {
3613 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3614 return rc;
3615 }
Fenglin Wu77188ab2015-04-20 17:54:37 +08003616 if (chip->type != SMBBP) {
3617 rc = qpnp_chg_masked_write(chip,
3618 chip->usb_chgpth_base + COMP_OVR1,
3619 0xFF,
3620 0x2F, 1);
3621 if (rc) {
3622 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3623 return rc;
3624 }
David Keitel33f58952013-05-20 16:17:36 -07003625 }
3626 }
David Keitel6dc4ed42013-05-17 11:08:58 -07003627
Chunmei Caib3999b22014-07-11 15:38:13 +08003628 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003629 chip->boost_base + BOOST_ENABLE_CONTROL,
3630 BOOST_PWR_EN,
3631 BOOST_PWR_EN, 1);
Chunmei Caib3999b22014-07-11 15:38:13 +08003632 if (rc) {
3633 pr_err("failed to enable boost rc = %d\n", rc);
3634 return rc;
3635 }
3636 /*
3637 * update battery status when charger is connected and state is full
3638 */
3639 if (usb_present && (chip->chg_done
3640 || (get_batt_capacity(chip) == 100)
3641 || (get_prop_batt_status(chip) ==
3642 POWER_SUPPLY_STATUS_FULL)))
3643 power_supply_changed(&chip->batt_psy);
3644
3645 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003646}
3647
3648/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07003649#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07003650static int
3651qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
3652{
3653 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07003654 int rc;
3655 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07003656
David Keitel33f58952013-05-20 16:17:36 -07003657 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003658 chip->boost_base + BOOST_ENABLE_CONTROL,
3659 BOOST_PWR_EN,
3660 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07003661 if (rc) {
3662 pr_err("failed to disable boost rc=%d\n", rc);
3663 return rc;
3664 }
3665
3666 rc = qpnp_chg_read(chip, &vbat_sts,
3667 chip->chgr_base + CHGR_VBAT_STATUS, 1);
3668 if (rc) {
3669 pr_err("failed to read bat sts rc=%d\n", rc);
3670 return rc;
3671 }
3672
3673 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
3674 rc = qpnp_chg_masked_write(chip,
3675 chip->chgr_base + SEC_ACCESS,
3676 0xFF,
3677 0xA5, 1);
3678 if (rc) {
3679 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3680 return rc;
3681 }
3682
3683 rc = qpnp_chg_masked_write(chip,
3684 chip->chgr_base + COMP_OVR1,
3685 0xFF,
3686 0x20, 1);
3687 if (rc) {
3688 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3689 return rc;
3690 }
3691
3692 usleep(2000);
3693
3694 rc = qpnp_chg_masked_write(chip,
3695 chip->chgr_base + SEC_ACCESS,
3696 0xFF,
3697 0xA5, 1);
3698 if (rc) {
3699 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3700 return rc;
3701 }
3702
3703 rc = qpnp_chg_masked_write(chip,
3704 chip->chgr_base + COMP_OVR1,
3705 0xFF,
3706 0x00, 1);
3707 if (rc) {
3708 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3709 return rc;
3710 }
3711 }
3712
3713 if (qpnp_chg_is_usb_chg_plugged_in(chip)
3714 && (chip->flags & BOOST_FLASH_WA)) {
3715 rc = qpnp_chg_masked_write(chip,
3716 chip->usb_chgpth_base + SEC_ACCESS,
3717 0xFF,
3718 0xA5, 1);
3719 if (rc) {
3720 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3721 return rc;
3722 }
Fenglin Wu77188ab2015-04-20 17:54:37 +08003723 if (chip->type != SMBBP) {
3724 rc = qpnp_chg_masked_write(chip,
3725 chip->usb_chgpth_base + COMP_OVR1,
3726 0xFF,
3727 0x00, 1);
3728 if (rc) {
3729 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3730 return rc;
3731 }
David Keitel33f58952013-05-20 16:17:36 -07003732 }
David Keitel33f58952013-05-20 16:17:36 -07003733 usleep(1000);
3734
3735 qpnp_chg_usb_suspend_enable(chip, 0);
3736 }
3737
Chunmei Caib3999b22014-07-11 15:38:13 +08003738 /*
3739 * When a charger is connected,if state of charge is not full
3740 * resumeing charging else update battery status
3741 */
3742 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
3743 if (get_batt_capacity(chip) < 100 || !chip->chg_done) {
3744 chip->chg_done = false;
3745 chip->resuming_charging = true;
3746 qpnp_chg_set_appropriate_vbatdet(chip);
3747 } else if (chip->chg_done) {
3748 power_supply_changed(&chip->batt_psy);
3749 }
3750 }
3751
David Keitelcd2e1022014-05-02 17:25:15 -07003752 if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
3753 pr_debug("EXT OVP IC ISNS enable\n");
3754 gpio_direction_output(chip->ext_ovp_isns_gpio, 1);
3755 }
3756
David Keitel33f58952013-05-20 16:17:36 -07003757 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003758}
3759
3760static int
3761qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
3762{
3763 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3764
3765 return qpnp_chg_is_boost_en_set(chip);
3766}
3767
3768static int
3769qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
3770 int min_uV, int max_uV, unsigned *selector)
3771{
3772 int uV = min_uV;
3773 int rc;
3774 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3775
3776 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
3777 uV = BOOST_MIN_UV;
3778
3779
3780 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
3781 pr_err("request %d uV is out of bounds\n", uV);
3782 return -EINVAL;
3783 }
3784
3785 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
3786 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
3787 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
3788 return -EINVAL;
3789 }
3790
3791 rc = qpnp_boost_vset(chip, uV);
3792
3793 return rc;
3794}
3795
3796static int
3797qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
3798{
3799 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3800
3801 return qpnp_boost_vget_uv(chip);
3802}
3803
3804static int
3805qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
3806 unsigned selector)
3807{
3808 if (selector >= N_BOOST_V)
3809 return 0;
3810
3811 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
3812}
3813
Chunmei Cai661a7cd2014-08-05 17:31:54 +08003814static struct regulator_ops qpnp_chg_flash_wa_reg_ops = {
3815 .enable = qpnp_chg_regulator_flash_wa_enable,
3816 .disable = qpnp_chg_regulator_flash_wa_disable,
3817 .is_enabled = qpnp_chg_regulator_flash_wa_is_enabled,
3818};
3819
David Keitel6dc4ed42013-05-17 11:08:58 -07003820static struct regulator_ops qpnp_chg_otg_reg_ops = {
3821 .enable = qpnp_chg_regulator_otg_enable,
3822 .disable = qpnp_chg_regulator_otg_disable,
3823 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
3824};
3825
3826static struct regulator_ops qpnp_chg_boost_reg_ops = {
3827 .enable = qpnp_chg_regulator_boost_enable,
3828 .disable = qpnp_chg_regulator_boost_disable,
3829 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
3830 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
3831 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
3832 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
3833};
3834
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003835static int
David Keitel6e63bd52013-09-06 18:00:03 -07003836qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003837{
David Keitel9eca8ac2013-09-06 14:18:36 -07003838 int rc = 0;
David Keitel6e63bd52013-09-06 18:00:03 -07003839 u8 reg = 0;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003840
David Keitelcadbc282013-09-26 11:39:14 -07003841 if (!chip->bat_if_base)
3842 return rc;
3843
David Keitel9eca8ac2013-09-06 14:18:36 -07003844 if (chip->type == SMBB)
3845 rc = qpnp_chg_read(chip, &reg,
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003846 chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
David Keitel9eca8ac2013-09-06 14:18:36 -07003847 else
3848 rc = qpnp_chg_read(chip, &reg,
3849 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
David Keitel6e63bd52013-09-06 18:00:03 -07003850
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003851 if (rc) {
3852 pr_err("failed to read batt_if rc=%d\n", rc);
3853 return rc;
3854 }
3855
David Keitel6e63bd52013-09-06 18:00:03 -07003856 if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003857 return 1;
3858
3859 return 0;
3860}
3861
David Keitel6e63bd52013-09-06 18:00:03 -07003862static int
3863qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
3864{
3865 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3866 int rc = 0;
3867
3868 mutex_lock(&chip->batfet_vreg_lock);
3869 /* Only enable if not already enabled */
3870 if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
3871 rc = qpnp_chg_regulator_batfet_set(chip, 1);
3872 if (rc)
3873 pr_err("failed to write to batt_if rc=%d\n", rc);
3874 }
3875
3876 chip->batfet_ext_en = true;
3877 mutex_unlock(&chip->batfet_vreg_lock);
3878
3879 return rc;
3880}
3881
3882static int
3883qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
3884{
3885 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3886 int rc = 0;
3887
3888 mutex_lock(&chip->batfet_vreg_lock);
3889 /* Don't allow disable if charger connected */
3890 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3891 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3892 rc = qpnp_chg_regulator_batfet_set(chip, 0);
3893 if (rc)
3894 pr_err("failed to write to batt_if rc=%d\n", rc);
3895 }
3896
3897 chip->batfet_ext_en = false;
3898 mutex_unlock(&chip->batfet_vreg_lock);
3899
3900 return rc;
3901}
3902
3903static int
3904qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
3905{
3906 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3907
3908 return chip->batfet_ext_en;
3909}
3910
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003911static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
3912 .enable = qpnp_chg_regulator_batfet_enable,
3913 .disable = qpnp_chg_regulator_batfet_disable,
3914 .is_enabled = qpnp_chg_regulator_batfet_is_enabled,
3915};
3916
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003917#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 8
3918#define MAX_DELTA_VDD_MAX_MV 80
3919#define VDD_MAX_CENTER_OFFSET 4
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003920static void
3921qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
3922{
3923 int delta_mv, closest_delta_mv, sign;
3924
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003925 delta_mv = chip->max_voltage_mv - VDD_MAX_CENTER_OFFSET - vbat_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003926 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
3927 pr_debug("vbat is not low enough to increase vdd\n");
3928 return;
3929 }
3930
3931 sign = delta_mv > 0 ? 1 : -1;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003932 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_BUCK_TRIM1_STEP / 2)
3933 / QPNP_CHG_BUCK_TRIM1_STEP) * QPNP_CHG_BUCK_TRIM1_STEP;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003934 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
3935 chip->max_voltage_mv, vbat_mv,
3936 delta_mv, closest_delta_mv);
3937 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
3938 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
3939 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
3940 qpnp_chg_set_appropriate_vddmax(chip);
3941}
3942
David Keitel9fd07382013-05-02 15:37:44 -07003943#define CONSECUTIVE_COUNT 3
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003944#define VBATDET_MAX_ERR_MV 50
David Keitel9fd07382013-05-02 15:37:44 -07003945static void
3946qpnp_eoc_work(struct work_struct *work)
3947{
3948 struct delayed_work *dwork = to_delayed_work(work);
3949 struct qpnp_chg_chip *chip = container_of(dwork,
3950 struct qpnp_chg_chip, eoc_work);
3951 static int count;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003952 static int vbat_low_count;
David Keitel9fd07382013-05-02 15:37:44 -07003953 int ibat_ma, vbat_mv, rc = 0;
3954 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003955 bool vbat_lower_than_vbatdet;
David Keitel9fd07382013-05-02 15:37:44 -07003956
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003957 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003958 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3959
3960 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
3961 if (rc) {
3962 pr_err("failed to read batt_if rc=%d\n", rc);
3963 return;
3964 }
3965
3966 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
3967 if (rc) {
3968 pr_err("failed to read buck rc=%d\n", rc);
3969 return;
3970 }
3971
3972 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
3973 if (rc) {
3974 pr_err("failed to read chg_sts rc=%d\n", rc);
3975 return;
3976 }
3977
3978 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
3979 chg_sts, batt_sts, buck_sts);
3980
3981 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3982 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3983 pr_debug("no chg connected, stopping\n");
3984 goto stop_eoc;
3985 }
3986
3987 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
3988 || chg_sts & TRKL_CHG_ON_IRQ)) {
3989 ibat_ma = get_prop_current_now(chip) / 1000;
3990 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003991
3992 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
3993 ibat_ma, vbat_mv, chip->term_current);
3994
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003995 vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
3996 if (vbat_lower_than_vbatdet && vbat_mv <
3997 (chip->max_voltage_mv - chip->resume_delta_mv
David Keitelbdbae452014-01-14 17:19:50 -08003998 - chip->vbatdet_max_err_mv)) {
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003999 vbat_low_count++;
4000 pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
4001 vbat_mv, chip->max_voltage_mv,
4002 chip->resume_delta_mv,
David Keitelbdbae452014-01-14 17:19:50 -08004003 chip->vbatdet_max_err_mv,
4004 vbat_low_count);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004005 if (vbat_low_count >= CONSECUTIVE_COUNT) {
4006 pr_debug("woke up too early stopping\n");
4007 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
4008 goto stop_eoc;
4009 } else {
4010 goto check_again_later;
4011 }
4012 } else {
4013 vbat_low_count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07004014 }
4015
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07004016 if (buck_sts & VDD_LOOP_IRQ)
4017 qpnp_chg_adjust_vddmax(chip, vbat_mv);
4018
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07004019 if (!(buck_sts & VDD_LOOP_IRQ)) {
4020 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07004021 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07004022 } else if ((ibat_ma * -1) > chip->term_current) {
4023 pr_debug("Not at EOC, battery current too high\n");
4024 count = 0;
4025 } else if (ibat_ma > 0) {
4026 pr_debug("Charging but system demand increased\n");
4027 count = 0;
4028 } else {
David Keitel9fd07382013-05-02 15:37:44 -07004029 if (count == CONSECUTIVE_COUNT) {
Xiaozhe Shie8504482013-10-30 18:10:31 -07004030 if (!chip->bat_is_cool && !chip->bat_is_warm) {
4031 pr_info("End of Charging\n");
4032 chip->chg_done = true;
4033 } else {
4034 pr_info("stop charging: battery is %s, vddmax = %d reached\n",
4035 chip->bat_is_cool
4036 ? "cool" : "warm",
4037 qpnp_chg_vddmax_get(chip));
4038 }
David Keitel9fd07382013-05-02 15:37:44 -07004039 qpnp_chg_charge_en(chip, 0);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004040 /* sleep for a second before enabling */
4041 msleep(2000);
4042 qpnp_chg_charge_en(chip,
4043 !chip->charging_disabled);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004044 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07004045 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07004046 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07004047 goto stop_eoc;
4048 } else {
4049 count += 1;
4050 pr_debug("EOC count = %d\n", count);
4051 }
David Keitel9fd07382013-05-02 15:37:44 -07004052 }
4053 } else {
4054 pr_debug("not charging\n");
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004055 goto stop_eoc;
David Keitel9fd07382013-05-02 15:37:44 -07004056 }
4057
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004058check_again_later:
David Keitel9fd07382013-05-02 15:37:44 -07004059 schedule_delayed_work(&chip->eoc_work,
4060 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
4061 return;
4062
4063stop_eoc:
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004064 vbat_low_count = 0;
David Keitel9fd07382013-05-02 15:37:44 -07004065 count = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004066 pm_relax(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07004067}
4068
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004069static void
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004070qpnp_chg_insertion_ocv_work(struct work_struct *work)
4071{
4072 struct qpnp_chg_chip *chip = container_of(work,
4073 struct qpnp_chg_chip, insertion_ocv_work);
4074 u8 bat_if_sts = 0, charge_en = 0;
4075 int rc;
4076
4077 chip->insertion_ocv_uv = get_prop_battery_voltage_now(chip);
4078
4079 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
4080 if (rc)
4081 pr_err("failed to read bat_if sts %d\n", rc);
4082
4083 rc = qpnp_chg_read(chip, &charge_en,
4084 chip->chgr_base + CHGR_CHG_CTRL, 1);
4085 if (rc)
4086 pr_err("failed to read bat_if sts %d\n", rc);
4087
4088 pr_debug("batfet sts = %02x, charge_en = %02x ocv = %d\n",
4089 bat_if_sts, charge_en, chip->insertion_ocv_uv);
4090 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4091 pr_debug("psy changed batt_psy\n");
4092 power_supply_changed(&chip->batt_psy);
4093}
4094
4095static void
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004096qpnp_chg_soc_check_work(struct work_struct *work)
4097{
4098 struct qpnp_chg_chip *chip = container_of(work,
4099 struct qpnp_chg_chip, soc_check_work);
4100
4101 get_prop_capacity(chip);
4102}
4103
David Keitel0c1a4532013-03-21 16:39:06 -07004104#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08004105static void
4106qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
4107{
4108 struct qpnp_chg_chip *chip = ctx;
4109 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07004110 int temp;
David Keitel454ee842013-03-08 16:19:11 -08004111
4112 if (state >= ADC_TM_STATE_NUM) {
4113 pr_err("invalid notification %d\n", state);
4114 return;
4115 }
4116
David Keitel1219a802013-03-21 16:37:21 -07004117 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08004118
David Keitel1219a802013-03-21 16:37:21 -07004119 pr_debug("temp = %d state = %s\n", temp,
4120 state == ADC_TM_WARM_STATE ? "warm" : "cool");
4121
4122 if (state == ADC_TM_WARM_STATE) {
David Keitel410ee0d2014-02-20 16:48:04 -08004123 if (temp >= chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07004124 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08004125 bat_warm = true;
4126 bat_cool = false;
4127 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07004128 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07004129 chip->adc_param.state_request =
4130 ADC_TM_COOL_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08004131 } else if (temp >=
David Keitel1219a802013-03-21 16:37:21 -07004132 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07004133 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08004134 bat_warm = false;
4135 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07004136
4137 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07004138 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07004139 chip->adc_param.state_request =
4140 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08004141 }
4142 } else {
David Keitel410ee0d2014-02-20 16:48:04 -08004143 if (temp <= chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07004144 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08004145 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07004146 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08004147 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07004148 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07004149 chip->adc_param.state_request =
4150 ADC_TM_WARM_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08004151 } else if (temp <=
David Keitel1219a802013-03-21 16:37:21 -07004152 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07004153 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08004154 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07004155 bat_cool = false;
4156
David Keitel0c1a4532013-03-21 16:39:06 -07004157 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07004158 chip->adc_param.high_temp = chip->warm_bat_decidegc;
4159 chip->adc_param.state_request =
4160 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08004161 }
4162 }
4163
4164 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07004165 chip->bat_is_cool = bat_cool;
4166 chip->bat_is_warm = bat_warm;
4167
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004168 /**
4169 * set appropriate voltages and currents.
4170 *
4171 * Note that when the battery is hot or cold, the charger
4172 * driver will not resume with SoC. Only vbatdet is used to
4173 * determine resume of charging.
4174 */
David Keitel59fbb762014-02-05 16:46:24 -08004175 if (bat_cool || bat_warm) {
4176 chip->resuming_charging = false;
4177 qpnp_chg_set_appropriate_vbatdet(chip);
4178
4179 /* To avoid ARB, only vbatdet is configured in
4180 * warm/cold zones. Once vbat < vbatdet the
4181 * appropriate vddmax/ibatmax adjustments will
4182 * be made in the fast charge interrupt. */
4183 bypass_vbatdet_comp(chip, 1);
4184 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4185 qpnp_chg_charge_en(chip, chip->charging_disabled);
4186 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4187 } else {
4188 bypass_vbatdet_comp(chip, 0);
4189 /* restore normal parameters */
4190 qpnp_chg_set_appropriate_vbatdet(chip);
4191 qpnp_chg_set_appropriate_vddmax(chip);
4192 qpnp_chg_set_appropriate_battery_current(chip);
4193 }
David Keitel454ee842013-03-08 16:19:11 -08004194 }
4195
David Keitelec3c09802013-06-13 13:05:30 -07004196 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
4197 chip->bat_is_warm, chip->bat_is_cool,
4198 chip->adc_param.low_temp, chip->adc_param.high_temp);
4199
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004200 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07004201 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07004202}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004203
David Keitelec3c09802013-06-13 13:05:30 -07004204#define MIN_COOL_TEMP -300
4205#define MAX_WARM_TEMP 1000
4206
4207static int
4208qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
4209 enum power_supply_property psp, int temp_degc)
4210{
4211 int rc = 0;
4212
4213 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
4214 pr_err("Bad temperature request %d\n", temp_degc);
4215 return -EINVAL;
4216 }
4217
4218 mutex_lock(&chip->jeita_configure_lock);
4219 switch (psp) {
4220 case POWER_SUPPLY_PROP_COOL_TEMP:
4221 if (temp_degc >=
4222 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
4223 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
4224 temp_degc, chip->warm_bat_decidegc,
4225 HYSTERISIS_DECIDEGC);
4226 rc = -EINVAL;
4227 goto mutex_unlock;
4228 }
4229 if (chip->bat_is_cool)
4230 chip->adc_param.high_temp =
4231 temp_degc + HYSTERISIS_DECIDEGC;
4232 else if (!chip->bat_is_warm)
4233 chip->adc_param.low_temp = temp_degc;
4234
4235 chip->cool_bat_decidegc = temp_degc;
4236 break;
4237 case POWER_SUPPLY_PROP_WARM_TEMP:
4238 if (temp_degc <=
4239 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
4240 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
4241 temp_degc, chip->warm_bat_decidegc,
4242 HYSTERISIS_DECIDEGC);
4243 rc = -EINVAL;
4244 goto mutex_unlock;
4245 }
4246 if (chip->bat_is_warm)
4247 chip->adc_param.low_temp =
4248 temp_degc - HYSTERISIS_DECIDEGC;
4249 else if (!chip->bat_is_cool)
4250 chip->adc_param.high_temp = temp_degc;
4251
4252 chip->warm_bat_decidegc = temp_degc;
4253 break;
4254 default:
4255 rc = -EINVAL;
4256 goto mutex_unlock;
4257 }
4258
4259 schedule_work(&chip->adc_measure_work);
4260
4261mutex_unlock:
4262 mutex_unlock(&chip->jeita_configure_lock);
4263 return rc;
David Keitel454ee842013-03-08 16:19:11 -08004264}
4265
Matt Mowera0f9b392015-10-12 19:37:46 -05004266#ifdef CONFIG_ANDROID_INTF_ALARM_DEV
4267#define POWER_STAGE_REDUCE_CHECK_PERIOD_NS (20LL * NSEC_PER_SEC)
4268#else
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004269#define POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS 20
Matt Mowera0f9b392015-10-12 19:37:46 -05004270#endif
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004271#define POWER_STAGE_REDUCE_MAX_VBAT_UV 3900000
4272#define POWER_STAGE_REDUCE_MIN_VCHG_UV 4800000
4273#define POWER_STAGE_SEL_MASK 0x0F
4274#define POWER_STAGE_REDUCED 0x01
4275#define POWER_STAGE_DEFAULT 0x0F
4276static bool
4277qpnp_chg_is_power_stage_reduced(struct qpnp_chg_chip *chip)
4278{
4279 int rc;
4280 u8 reg;
4281
4282 rc = qpnp_chg_read(chip, &reg,
4283 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
4284 1);
4285 if (rc) {
4286 pr_err("Error %d reading power stage register\n", rc);
4287 return false;
4288 }
4289
4290 if ((reg & POWER_STAGE_SEL_MASK) == POWER_STAGE_DEFAULT)
4291 return false;
4292
4293 return true;
4294}
4295
4296static int
4297qpnp_chg_power_stage_set(struct qpnp_chg_chip *chip, bool reduce)
4298{
4299 int rc;
4300 u8 reg = 0xA5;
4301
4302 rc = qpnp_chg_write(chip, &reg,
4303 chip->buck_base + SEC_ACCESS,
4304 1);
4305 if (rc) {
4306 pr_err("Error %d writing 0xA5 to buck's 0x%x reg\n",
4307 rc, SEC_ACCESS);
4308 return rc;
4309 }
4310
4311 reg = POWER_STAGE_DEFAULT;
4312 if (reduce)
4313 reg = POWER_STAGE_REDUCED;
4314 rc = qpnp_chg_write(chip, &reg,
4315 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
4316 1);
4317
4318 if (rc)
4319 pr_err("Error %d writing 0x%x power stage register\n", rc, reg);
4320 return rc;
4321}
4322
4323static int
4324qpnp_chg_get_vusbin_uv(struct qpnp_chg_chip *chip)
4325{
4326 int rc = 0;
4327 struct qpnp_vadc_result results;
4328
4329 rc = qpnp_vadc_read(chip->vadc_dev, USBIN, &results);
4330 if (rc) {
4331 pr_err("Unable to read vbat rc=%d\n", rc);
4332 return 0;
4333 }
4334 return results.physical;
4335}
4336
4337static
4338int get_vusb_averaged(struct qpnp_chg_chip *chip, int sample_count)
4339{
4340 int vusb_uv = 0;
4341 int i;
4342
4343 /* avoid overflows */
4344 if (sample_count > 256)
4345 sample_count = 256;
4346
4347 for (i = 0; i < sample_count; i++)
4348 vusb_uv += qpnp_chg_get_vusbin_uv(chip);
4349
4350 vusb_uv = vusb_uv / sample_count;
4351 return vusb_uv;
4352}
4353
4354static
4355int get_vbat_averaged(struct qpnp_chg_chip *chip, int sample_count)
4356{
4357 int vbat_uv = 0;
4358 int i;
4359
4360 /* avoid overflows */
4361 if (sample_count > 256)
4362 sample_count = 256;
4363
4364 for (i = 0; i < sample_count; i++)
4365 vbat_uv += get_prop_battery_voltage_now(chip);
4366
4367 vbat_uv = vbat_uv / sample_count;
4368 return vbat_uv;
4369}
4370
4371static void
4372qpnp_chg_reduce_power_stage(struct qpnp_chg_chip *chip)
4373{
Matt Mowera0f9b392015-10-12 19:37:46 -05004374#ifdef CONFIG_ANDROID_INTF_ALARM_DEV
4375 ktime_t kt;
4376#else
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004377 struct timespec ts;
Matt Mowera0f9b392015-10-12 19:37:46 -05004378#endif
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004379 bool power_stage_reduced_in_hw = qpnp_chg_is_power_stage_reduced(chip);
4380 bool reduce_power_stage = false;
4381 int vbat_uv = get_vbat_averaged(chip, 16);
4382 int vusb_uv = get_vusb_averaged(chip, 16);
4383 bool fast_chg =
4384 (get_prop_charge_type(chip) == POWER_SUPPLY_CHARGE_TYPE_FAST);
4385 static int count_restore_power_stage;
4386 static int count_reduce_power_stage;
4387 bool vchg_loop = get_prop_vchg_loop(chip);
4388 bool ichg_loop = qpnp_chg_is_ichg_loop_active(chip);
4389 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
4390 bool usb_ma_above_wall =
4391 (qpnp_chg_usb_iusbmax_get(chip) > USB_WALL_THRESHOLD_MA);
4392
4393 if (fast_chg
4394 && usb_present
4395 && usb_ma_above_wall
4396 && vbat_uv < POWER_STAGE_REDUCE_MAX_VBAT_UV
4397 && vusb_uv > POWER_STAGE_REDUCE_MIN_VCHG_UV)
4398 reduce_power_stage = true;
4399
4400 if ((usb_present && usb_ma_above_wall)
4401 && (vchg_loop || ichg_loop))
4402 reduce_power_stage = true;
4403
4404 if (power_stage_reduced_in_hw && !reduce_power_stage) {
4405 count_restore_power_stage++;
4406 count_reduce_power_stage = 0;
4407 } else if (!power_stage_reduced_in_hw && reduce_power_stage) {
4408 count_reduce_power_stage++;
4409 count_restore_power_stage = 0;
4410 } else if (power_stage_reduced_in_hw == reduce_power_stage) {
4411 count_restore_power_stage = 0;
4412 count_reduce_power_stage = 0;
4413 }
4414
4415 pr_debug("power_stage_hw = %d reduce_power_stage = %d usb_present = %d usb_ma_above_wall = %d vbat_uv(16) = %d vusb_uv(16) = %d fast_chg = %d , ichg = %d, vchg = %d, restore,reduce = %d, %d\n",
4416 power_stage_reduced_in_hw, reduce_power_stage,
4417 usb_present, usb_ma_above_wall,
4418 vbat_uv, vusb_uv, fast_chg,
4419 ichg_loop, vchg_loop,
4420 count_restore_power_stage, count_reduce_power_stage);
4421
4422 if (!power_stage_reduced_in_hw && reduce_power_stage) {
4423 if (count_reduce_power_stage >= 2) {
4424 qpnp_chg_power_stage_set(chip, true);
4425 power_stage_reduced_in_hw = true;
4426 }
4427 }
4428
4429 if (power_stage_reduced_in_hw && !reduce_power_stage) {
4430 if (count_restore_power_stage >= 6
4431 || (!usb_present || !usb_ma_above_wall)) {
4432 qpnp_chg_power_stage_set(chip, false);
4433 power_stage_reduced_in_hw = false;
4434 }
4435 }
4436
4437 if (usb_present && usb_ma_above_wall) {
Matt Mowera0f9b392015-10-12 19:37:46 -05004438#ifdef CONFIG_ANDROID_INTF_ALARM_DEV
4439 kt = ns_to_ktime(POWER_STAGE_REDUCE_CHECK_PERIOD_NS);
4440 alarm_start_relative(&chip->reduce_power_stage_alarm, kt);
4441#else
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004442 getnstimeofday(&ts);
4443 ts.tv_sec += POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS;
4444 alarm_start_range(&chip->reduce_power_stage_alarm,
4445 timespec_to_ktime(ts),
4446 timespec_to_ktime(ts));
Matt Mowera0f9b392015-10-12 19:37:46 -05004447#endif
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004448 } else {
4449 pr_debug("stopping power stage workaround\n");
4450 chip->power_stage_workaround_running = false;
4451 }
4452}
4453
4454static void
David Keitel6e63bd52013-09-06 18:00:03 -07004455qpnp_chg_batfet_lcl_work(struct work_struct *work)
4456{
4457 struct qpnp_chg_chip *chip = container_of(work,
4458 struct qpnp_chg_chip, batfet_lcl_work);
4459
4460 mutex_lock(&chip->batfet_vreg_lock);
4461 if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
4462 qpnp_chg_is_dc_chg_plugged_in(chip)) {
4463 qpnp_chg_regulator_batfet_set(chip, 1);
4464 pr_debug("disabled ULPM\n");
4465 } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
4466 && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
4467 qpnp_chg_regulator_batfet_set(chip, 0);
4468 pr_debug("enabled ULPM\n");
4469 }
4470 mutex_unlock(&chip->batfet_vreg_lock);
4471}
4472
4473static void
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004474qpnp_chg_reduce_power_stage_work(struct work_struct *work)
4475{
4476 struct qpnp_chg_chip *chip = container_of(work,
4477 struct qpnp_chg_chip, reduce_power_stage_work);
4478
4479 qpnp_chg_reduce_power_stage(chip);
4480}
4481
Matt Mowera0f9b392015-10-12 19:37:46 -05004482#ifdef CONFIG_ANDROID_INTF_ALARM_DEV
4483static enum alarmtimer_restart
4484qpnp_chg_reduce_power_stage_callback(struct alarm *alarm, ktime_t now)
4485{
4486 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
4487 reduce_power_stage_alarm);
4488
4489 schedule_work(&chip->reduce_power_stage_work);
4490 return ALARMTIMER_NORESTART;
4491}
4492#else
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004493static void
4494qpnp_chg_reduce_power_stage_callback(struct alarm *alarm)
4495{
4496 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
4497 reduce_power_stage_alarm);
4498
4499 schedule_work(&chip->reduce_power_stage_work);
4500}
Matt Mowera0f9b392015-10-12 19:37:46 -05004501#endif
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004502
David Keitelbe208252013-01-31 14:49:25 -08004503static int
David Keitel432e1232013-06-05 16:10:18 -07004504qpnp_dc_power_set_property(struct power_supply *psy,
4505 enum power_supply_property psp,
4506 const union power_supply_propval *val)
4507{
4508 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
4509 dc_psy);
4510 int rc = 0;
4511
4512 switch (psp) {
4513 case POWER_SUPPLY_PROP_CURRENT_MAX:
4514 if (!val->intval)
4515 break;
4516
4517 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
4518 if (rc) {
4519 pr_err("Error setting idcmax property %d\n", rc);
4520 return rc;
4521 }
4522 chip->maxinput_dc_ma = (val->intval / 1000);
4523
4524 break;
4525 default:
4526 return -EINVAL;
4527 }
4528
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004529 pr_debug("psy changed dc_psy\n");
David Keitel432e1232013-06-05 16:10:18 -07004530 power_supply_changed(&chip->dc_psy);
4531 return rc;
4532}
4533
4534static int
David Keitelbe208252013-01-31 14:49:25 -08004535qpnp_batt_power_set_property(struct power_supply *psy,
4536 enum power_supply_property psp,
4537 const union power_supply_propval *val)
4538{
4539 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
4540 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004541 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08004542
4543 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07004544 case POWER_SUPPLY_PROP_COOL_TEMP:
4545 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
4546 break;
4547 case POWER_SUPPLY_PROP_WARM_TEMP:
4548 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
4549 break;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08004550 case POWER_SUPPLY_PROP_CAPACITY:
4551 chip->fake_battery_soc = val->intval;
4552 power_supply_changed(&chip->batt_psy);
4553 break;
David Keitelbe208252013-01-31 14:49:25 -08004554 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
4555 chip->charging_disabled = !(val->intval);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004556 if (chip->charging_disabled) {
4557 /* disable charging */
4558 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4559 qpnp_chg_force_run_on_batt(chip,
4560 chip->charging_disabled);
4561 } else {
4562 /* enable charging */
4563 qpnp_chg_force_run_on_batt(chip,
4564 chip->charging_disabled);
4565 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4566 }
David Keitelbe208252013-01-31 14:49:25 -08004567 break;
4568 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
4569 qpnp_batt_system_temp_level_set(chip, val->intval);
4570 break;
David Keitel337bd862013-07-15 21:42:58 -07004571 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel820a90d2014-03-25 18:18:04 -07004572 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
4573 !(qpnp_is_dc_higher_prio(chip)
4574 && qpnp_chg_is_dc_chg_plugged_in(chip)))
David Keitel7b0568482013-12-02 14:47:42 -08004575 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
David Keitel337bd862013-07-15 21:42:58 -07004576 break;
David Keitel2586f0a2013-08-20 10:02:26 -07004577 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
4578 qpnp_chg_iusb_trim_set(chip, val->intval);
4579 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004580 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
David Keitel820a90d2014-03-25 18:18:04 -07004581 if (val->intval)
4582 qpnp_chg_input_current_settled(chip);
4583 else
4584 chip->aicl_settled = false;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004585 break;
David Keitel337bd862013-07-15 21:42:58 -07004586 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
4587 qpnp_chg_vinmin_set(chip, val->intval / 1000);
4588 break;
Fenglin Wuc64e9942014-08-22 13:47:34 +08004589 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
4590 rc = qpnp_chg_bypass_vchg_loop_debouncer(chip, !!val->intval);
4591 break;
David Keitelbe208252013-01-31 14:49:25 -08004592 default:
4593 return -EINVAL;
4594 }
4595
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004596 pr_debug("psy changed batt_psy\n");
David Keitelbe208252013-01-31 14:49:25 -08004597 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004598 return rc;
David Keitelbe208252013-01-31 14:49:25 -08004599}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004600
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004601static int
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004602qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07004603{
David Keitelfe51cb92013-04-02 19:42:58 -07004604 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07004605 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07004606 if (chip->type == SMBB)
4607 chip->flags |= BOOST_FLASH_WA;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004608 if (chip->type == SMBBP) {
4609 struct device_node *revid_dev_node;
4610 struct pmic_revid_data *revid_data;
4611
4612 chip->flags |= BOOST_FLASH_WA;
4613
4614 revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
4615 "qcom,pmic-revid", 0);
4616 if (!revid_dev_node) {
4617 pr_err("Missing qcom,pmic-revid property\n");
4618 return -EINVAL;
4619 }
4620 revid_data = get_revid_data(revid_dev_node);
4621 if (IS_ERR(revid_data)) {
4622 pr_err("Couldnt get revid data rc = %ld\n",
4623 PTR_ERR(revid_data));
4624 return PTR_ERR(revid_data);
4625 }
4626
4627 if (revid_data->rev4 < PM8226_V2P1_REV4
4628 || ((revid_data->rev4 == PM8226_V2P1_REV4)
4629 && (revid_data->rev3 <= PM8226_V2P1_REV3))) {
4630 chip->flags |= POWER_STAGE_WA;
4631 }
4632 }
4633 return 0;
David Keiteld681cda2012-10-02 15:44:21 -07004634}
4635
David Keitel0f35be42013-04-16 11:10:40 -07004636static int
4637qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
4638{
4639 int rc = 0;
4640 struct resource *resource;
4641 struct spmi_resource *spmi_resource;
4642 u8 subtype;
4643 struct spmi_device *spmi = chip->spmi;
4644
4645 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
4646 if (!spmi_resource) {
4647 pr_err("qpnp_chg: spmi resource absent\n");
4648 return rc;
4649 }
4650
4651 resource = spmi_get_resource(spmi, spmi_resource,
4652 IORESOURCE_MEM, 0);
4653 if (!(resource && resource->start)) {
4654 pr_err("node %s IO resource absent!\n",
4655 spmi->dev.of_node->full_name);
4656 return rc;
4657 }
4658
4659 rc = qpnp_chg_read(chip, &subtype,
4660 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4661 if (rc) {
4662 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4663 return rc;
4664 }
4665
4666 switch (subtype) {
4667 case SMBB_CHGR_SUBTYPE:
4668 case SMBBP_CHGR_SUBTYPE:
4669 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004670 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004671 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004672 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004673 pr_err("Unable to get fast-chg-on irq\n");
4674 return rc;
4675 }
4676
David Keitel47185a62013-05-15 18:54:10 -07004677 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004678 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004679 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004680 pr_err("Unable to get trkl-chg-on irq\n");
4681 return rc;
4682 }
4683
David Keitel47185a62013-05-15 18:54:10 -07004684 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004685 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07004686 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004687 pr_err("Unable to get chg_failed irq\n");
4688 return rc;
4689 }
4690
David Keitel47185a62013-05-15 18:54:10 -07004691 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07004692 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07004693 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07004694 pr_err("Unable to get fast-chg-on irq\n");
4695 return rc;
4696 }
4697
David Keitel47185a62013-05-15 18:54:10 -07004698 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004699 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07004700 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004701 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004702 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004703 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004704 return rc;
4705 }
4706
David Keitel47185a62013-05-15 18:54:10 -07004707 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004708 qpnp_chg_chgr_chg_fastchg_irq_handler,
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08004709 IRQF_TRIGGER_RISING |
4710 IRQF_TRIGGER_FALLING,
David Keitel0f35be42013-04-16 11:10:40 -07004711 "fast-chg-on", chip);
4712 if (rc < 0) {
4713 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004714 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004715 return rc;
4716 }
4717
David Keitel47185a62013-05-15 18:54:10 -07004718 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004719 qpnp_chg_chgr_chg_trklchg_irq_handler,
4720 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004721 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004722 if (rc < 0) {
4723 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004724 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004725 return rc;
4726 }
David Keitel9fd07382013-05-02 15:37:44 -07004727
4728 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07004729 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07004730 qpnp_chg_vbatdet_lo_irq_handler,
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004731 IRQF_TRIGGER_RISING,
David Keitel9fd07382013-05-02 15:37:44 -07004732 "vbat-det-lo", chip);
4733 if (rc < 0) {
4734 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004735 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07004736 return rc;
4737 }
4738
David Keitelbf6a1062014-01-23 10:57:36 -08004739 qpnp_chg_irq_wake_enable(&chip->chg_trklchg);
4740 qpnp_chg_irq_wake_enable(&chip->chg_failed);
David Keitelbf6a1062014-01-23 10:57:36 -08004741 qpnp_chg_irq_wake_enable(&chip->chg_vbatdet_lo);
Fenglin Wu67aa2ca2015-01-20 16:40:11 +08004742 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel0f35be42013-04-16 11:10:40 -07004743 break;
Fenglin Wu67aa2ca2015-01-20 16:40:11 +08004744
David Keitel0f35be42013-04-16 11:10:40 -07004745 case SMBB_BAT_IF_SUBTYPE:
4746 case SMBBP_BAT_IF_SUBTYPE:
4747 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004748 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004749 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07004750 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004751 pr_err("Unable to get batt-pres irq\n");
4752 return rc;
4753 }
David Keitel47185a62013-05-15 18:54:10 -07004754 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004755 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07004756 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
4757 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07004758 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004759 if (rc < 0) {
4760 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004761 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004762 return rc;
4763 }
4764
David Keitelbf6a1062014-01-23 10:57:36 -08004765 qpnp_chg_irq_wake_enable(&chip->batt_pres);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004766
4767 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
4768 spmi_resource, "bat-temp-ok");
4769 if (chip->batt_temp_ok.irq < 0) {
4770 pr_err("Unable to get bat-temp-ok irq\n");
4771 return rc;
4772 }
4773 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
4774 qpnp_chg_bat_if_batt_temp_irq_handler,
4775 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4776 "bat-temp-ok", chip);
4777 if (rc < 0) {
4778 pr_err("Can't request %d bat-temp-ok irq: %d\n",
4779 chip->batt_temp_ok.irq, rc);
4780 return rc;
4781 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08004782 qpnp_chg_bat_if_batt_temp_irq_handler(0, chip);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004783
David Keitelbf6a1062014-01-23 10:57:36 -08004784 qpnp_chg_irq_wake_enable(&chip->batt_temp_ok);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004785
David Keitel0f35be42013-04-16 11:10:40 -07004786 break;
David Keitel337bd862013-07-15 21:42:58 -07004787 case SMBB_BUCK_SUBTYPE:
4788 case SMBBP_BUCK_SUBTYPE:
4789 case SMBCL_BUCK_SUBTYPE:
David Keitel337bd862013-07-15 21:42:58 -07004790 break;
4791
David Keitel0f35be42013-04-16 11:10:40 -07004792 case SMBB_USB_CHGPTH_SUBTYPE:
4793 case SMBBP_USB_CHGPTH_SUBTYPE:
4794 case SMBCL_USB_CHGPTH_SUBTYPE:
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004795 if (chip->ovp_monitor_enable) {
4796 chip->coarse_det_usb.irq =
4797 spmi_get_irq_byname(spmi,
4798 spmi_resource, "coarse-det-usb");
4799 if (chip->coarse_det_usb.irq < 0) {
4800 pr_err("Can't get coarse-det irq\n");
4801 return rc;
4802 }
4803 rc = devm_request_irq(chip->dev,
4804 chip->coarse_det_usb.irq,
4805 qpnp_chg_coarse_det_usb_irq_handler,
4806 IRQF_TRIGGER_RISING |
4807 IRQF_TRIGGER_FALLING,
4808 "coarse-det-usb", chip);
4809 if (rc < 0) {
4810 pr_err("Can't req %d coarse-det: %d\n",
4811 chip->coarse_det_usb.irq, rc);
4812 return rc;
4813 }
4814 }
4815
David Keitel47185a62013-05-15 18:54:10 -07004816 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004817 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004818 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004819 pr_err("Unable to get usbin irq\n");
4820 return rc;
4821 }
David Keitel47185a62013-05-15 18:54:10 -07004822 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004823 qpnp_chg_usb_usbin_valid_irq_handler,
4824 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004825 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004826 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004827 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004828 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004829 return rc;
4830 }
David Keitel344c6972013-04-09 19:28:21 -07004831
David Keitel47185a62013-05-15 18:54:10 -07004832 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07004833 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07004834 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07004835 pr_err("Unable to get chg-gone irq\n");
4836 return rc;
4837 }
David Keitel47185a62013-05-15 18:54:10 -07004838 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07004839 qpnp_chg_usb_chg_gone_irq_handler,
4840 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07004841 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07004842 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004843 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004844 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07004845 return rc;
4846 }
David Keitel47185a62013-05-15 18:54:10 -07004847
David Keitel0b62bdd2013-07-10 17:30:51 -07004848 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4849 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4850 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
4851 spmi_resource, "usb-ocp");
4852 if (chip->usb_ocp.irq < 0) {
4853 pr_err("Unable to get usbin irq\n");
4854 return rc;
4855 }
4856 rc = devm_request_irq(chip->dev,
4857 chip->usb_ocp.irq,
4858 qpnp_chg_usb_usb_ocp_irq_handler,
4859 IRQF_TRIGGER_RISING, "usb-ocp", chip);
4860 if (rc < 0) {
4861 pr_err("Can't request %d usb-ocp: %d\n",
4862 chip->usb_ocp.irq, rc);
4863 return rc;
4864 }
4865
David Keitelbf6a1062014-01-23 10:57:36 -08004866 qpnp_chg_irq_wake_enable(&chip->usb_ocp);
David Keitel0b62bdd2013-07-10 17:30:51 -07004867 }
4868
David Keitelbf6a1062014-01-23 10:57:36 -08004869 qpnp_chg_irq_wake_enable(&chip->usbin_valid);
4870 qpnp_chg_irq_wake_enable(&chip->chg_gone);
David Keitel0f35be42013-04-16 11:10:40 -07004871 break;
4872 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004873 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004874 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004875 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004876 pr_err("Unable to get dcin irq\n");
4877 return -rc;
4878 }
David Keitel47185a62013-05-15 18:54:10 -07004879 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004880 qpnp_chg_dc_dcin_valid_irq_handler,
4881 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004882 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004883 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004884 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004885 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004886 return rc;
4887 }
4888
David Keitelbf6a1062014-01-23 10:57:36 -08004889 qpnp_chg_irq_wake_enable(&chip->dcin_valid);
David Keitel0f35be42013-04-16 11:10:40 -07004890 break;
4891 }
4892 }
4893
4894 return rc;
4895}
4896
Xiaozhe Shica289e02013-06-19 13:24:51 -07004897static int
4898qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
4899{
4900 struct bms_battery_data batt_data;
4901 struct device_node *node;
4902 struct qpnp_vadc_result result;
4903 int rc;
4904
4905 node = of_find_node_by_name(chip->spmi->dev.of_node,
4906 "qcom,battery-data");
4907 if (node) {
4908 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004909 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07004910 if (rc) {
4911 pr_err("error reading batt id channel = %d, rc = %d\n",
4912 LR_MUX2_BAT_ID, rc);
4913 return rc;
4914 }
4915
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07004916 batt_data.max_voltage_uv = -1;
4917 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07004918 rc = of_batterydata_read_data(node,
4919 &batt_data, result.physical);
4920 if (rc) {
4921 pr_err("failed to read battery data: %d\n", rc);
4922 return rc;
4923 }
4924
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004925 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07004926 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004927 chip->safe_voltage_mv = chip->max_voltage_mv
4928 + MAX_DELTA_VDD_MAX_MV;
4929 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004930 if (batt_data.iterm_ua >= 0)
4931 chip->term_current = batt_data.iterm_ua / 1000;
4932 }
4933
4934 return 0;
4935}
4936
David Keitel80668952012-07-27 14:25:49 -07004937#define WDOG_EN_BIT BIT(7)
4938static int
4939qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
4940 struct spmi_resource *spmi_resource)
4941{
4942 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004943 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07004944 struct regulator_init_data *init_data;
4945 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07004946
4947 switch (subtype) {
4948 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004949 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004950 case SMBCL_CHGR_SUBTYPE:
Prasad Sodagudic3678012013-09-23 12:01:19 +05304951 qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
4952
David Keitel80668952012-07-27 14:25:49 -07004953 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
4954 if (rc) {
4955 pr_debug("failed setting min_voltage rc=%d\n", rc);
4956 return rc;
4957 }
David Keitel80668952012-07-27 14:25:49 -07004958 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
4959 if (rc) {
4960 pr_debug("failed setting safe_voltage rc=%d\n", rc);
4961 return rc;
4962 }
David Keitel454ee842013-03-08 16:19:11 -08004963 rc = qpnp_chg_vbatdet_set(chip,
4964 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08004965 if (rc) {
4966 pr_debug("failed setting resume_voltage rc=%d\n", rc);
4967 return rc;
4968 }
David Keitel80668952012-07-27 14:25:49 -07004969 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
4970 if (rc) {
4971 pr_debug("failed setting ibatmax rc=%d\n", rc);
4972 return rc;
4973 }
David Keitel365c4c42013-03-08 16:20:40 -08004974 if (chip->term_current) {
4975 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
4976 if (rc) {
4977 pr_debug("failed setting ibatterm rc=%d\n", rc);
4978 return rc;
4979 }
David Keitel80668952012-07-27 14:25:49 -07004980 }
David Keitel5d44fa52012-12-03 16:37:31 -08004981 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
4982 if (rc) {
4983 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
4984 return rc;
4985 }
David Keitela4b7b592013-04-11 18:34:35 -07004986 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
4987 if (rc) {
4988 pr_debug("failed setting tchg_mins rc=%d\n", rc);
4989 return rc;
4990 }
4991
David Keitel80668952012-07-27 14:25:49 -07004992 /* HACK: Disable wdog */
4993 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
4994 0xFF, 0xA0, 1);
4995
David Keitelb4e43542013-04-09 17:30:41 -07004996 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07004997 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4998 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07004999 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07005000
David Keitel79e08322014-04-21 14:17:05 -07005001 /* HACK: trkl stuck workaround */
5002
5003 rc = qpnp_chg_masked_write(chip,
5004 chip->chgr_base + SEC_ACCESS,
5005 0xFF,
5006 0xA5, 1);
5007
5008 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
5009 CHG_OVR0,
5010 0xFF, 0x00, 1);
5011
5012 rc = qpnp_chg_masked_write(chip,
5013 chip->chgr_base + SEC_ACCESS,
5014 0xFF,
5015 0xA5, 1);
5016
5017 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
5018 CHG_TRICKLE_CLAMP,
5019 0xFF, 0x00, 1);
Chunmei Cai661a7cd2014-08-05 17:31:54 +08005020
5021 rc = qpnp_chg_read(chip, &chip->chg_temp_thresh_default,
5022 chip->chgr_base + CHGR_CHG_TEMP_THRESH, 1);
5023 if (rc) {
5024 pr_debug("read CHG_TEMP_THRESH failed, rc = %d\n", rc);
5025 chip->chg_temp_thresh_default =
5026 CHG_TEMP_THRESH_DEFAULT;
5027 }
5028
5029 init_data = of_get_regulator_init_data(chip->dev,
5030 spmi_resource->of_node);
5031 if (!init_data) {
5032 pr_err("unable to get regulator init data for flash_wa\n");
5033 return -ENOMEM;
5034 }
5035
5036 if (init_data->constraints.name) {
5037 rdesc = &(chip->flash_wa_vreg.rdesc);
5038 rdesc->owner = THIS_MODULE;
5039 rdesc->type = REGULATOR_VOLTAGE;
5040 rdesc->ops = &qpnp_chg_flash_wa_reg_ops;
5041 rdesc->name = init_data->constraints.name;
5042
5043 init_data->constraints.valid_ops_mask
5044 |= REGULATOR_CHANGE_STATUS;
5045
5046 chip->flash_wa_vreg.rdev =
5047 regulator_register(rdesc, chip->dev, init_data,
5048 chip, spmi_resource->of_node);
5049 if (IS_ERR(chip->flash_wa_vreg.rdev)) {
5050 rc = PTR_ERR(chip->flash_wa_vreg.rdev);
5051 chip->flash_wa_vreg.rdev = NULL;
5052 pr_err("Flash wa failed, rc=%d\n", rc);
5053 return rc;
5054 }
5055 }
David Keitel80668952012-07-27 14:25:49 -07005056 break;
5057 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005058 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005059 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07005060 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
5061 if (rc)
5062 return rc;
5063
David Keitel9201df32013-01-10 18:38:34 -08005064 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07005065 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08005066 BUCK_VBAT_REG_NODE_SEL_BIT,
5067 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
5068 if (rc) {
5069 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
5070 return rc;
5071 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07005072
5073 rc = qpnp_chg_read(chip, &chip->trim_center,
5074 chip->buck_base + BUCK_CTRL_TRIM1, 1);
5075 if (rc) {
5076 pr_debug("failed to read trim center rc=%d\n", rc);
5077 return rc;
5078 }
5079 chip->trim_center >>= 4;
5080 pr_debug("trim center = %02x\n", chip->trim_center);
David Keitel80668952012-07-27 14:25:49 -07005081 break;
5082 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005083 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005084 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07005085 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07005086 switch (chip->bpd_detection) {
5087 case BPD_TYPE_BAT_THM:
5088 reg = BAT_THM_EN;
5089 break;
5090 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07005091 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07005092 break;
5093 case BPD_TYPE_BAT_THM_BAT_ID:
5094 reg = BAT_THM_EN | BAT_ID_EN;
5095 break;
5096 default:
5097 reg = BAT_THM_EN;
5098 break;
5099 }
David Keitel796882d2013-05-14 18:01:11 -07005100
5101 rc = qpnp_chg_masked_write(chip,
5102 chip->bat_if_base + BAT_IF_BPD_CTRL,
5103 BAT_IF_BPD_CTRL_SEL,
5104 reg, 1);
5105 if (rc) {
5106 pr_debug("failed to chose BPD rc=%d\n", rc);
5107 return rc;
5108 }
David Keitel85ae4342013-04-16 11:46:00 -07005109 /* Force on VREF_BAT_THM */
5110 rc = qpnp_chg_masked_write(chip,
5111 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5112 VREF_BATT_THERM_FORCE_ON,
5113 VREF_BATT_THERM_FORCE_ON, 1);
5114 if (rc) {
5115 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
5116 return rc;
5117 }
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07005118
5119 init_data = of_get_regulator_init_data(chip->dev,
5120 spmi_resource->of_node);
5121
5122 if (init_data->constraints.name) {
5123 rdesc = &(chip->batfet_vreg.rdesc);
5124 rdesc->owner = THIS_MODULE;
5125 rdesc->type = REGULATOR_VOLTAGE;
5126 rdesc->ops = &qpnp_chg_batfet_vreg_ops;
5127 rdesc->name = init_data->constraints.name;
5128
5129 init_data->constraints.valid_ops_mask
5130 |= REGULATOR_CHANGE_STATUS;
5131
5132 chip->batfet_vreg.rdev = regulator_register(rdesc,
5133 chip->dev, init_data, chip,
5134 spmi_resource->of_node);
5135 if (IS_ERR(chip->batfet_vreg.rdev)) {
5136 rc = PTR_ERR(chip->batfet_vreg.rdev);
5137 chip->batfet_vreg.rdev = NULL;
5138 if (rc != -EPROBE_DEFER)
5139 pr_err("batfet reg failed, rc=%d\n",
5140 rc);
5141 return rc;
5142 }
5143 }
David Keitel80668952012-07-27 14:25:49 -07005144 break;
5145 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005146 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005147 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07005148 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07005149 rc = qpnp_chg_masked_write(chip,
5150 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
5151 ENUM_T_STOP_BIT,
5152 ENUM_T_STOP_BIT, 1);
5153 if (rc) {
5154 pr_err("failed to write enum stop rc=%d\n", rc);
5155 return -ENXIO;
5156 }
5157 }
David Keiteld681cda2012-10-02 15:44:21 -07005158
David Keitel6dc4ed42013-05-17 11:08:58 -07005159 init_data = of_get_regulator_init_data(chip->dev,
5160 spmi_resource->of_node);
5161 if (!init_data) {
5162 pr_err("unable to allocate memory\n");
5163 return -ENOMEM;
5164 }
5165
5166 if (init_data->constraints.name) {
5167 if (of_get_property(chip->dev->of_node,
5168 "otg-parent-supply", NULL))
5169 init_data->supply_regulator = "otg-parent";
5170
5171 rdesc = &(chip->otg_vreg.rdesc);
5172 rdesc->owner = THIS_MODULE;
5173 rdesc->type = REGULATOR_VOLTAGE;
5174 rdesc->ops = &qpnp_chg_otg_reg_ops;
5175 rdesc->name = init_data->constraints.name;
5176
5177 init_data->constraints.valid_ops_mask
5178 |= REGULATOR_CHANGE_STATUS;
5179
5180 chip->otg_vreg.rdev = regulator_register(rdesc,
5181 chip->dev, init_data, chip,
5182 spmi_resource->of_node);
5183 if (IS_ERR(chip->otg_vreg.rdev)) {
5184 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07005185 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07005186 if (rc != -EPROBE_DEFER)
5187 pr_err("OTG reg failed, rc=%d\n", rc);
5188 return rc;
5189 }
5190 }
5191
David Keiteld681cda2012-10-02 15:44:21 -07005192 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08005193 chip->usb_chgpth_base + USB_OVP_CTL,
5194 USB_VALID_DEB_20MS,
5195 USB_VALID_DEB_20MS, 1);
5196
5197 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07005198 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
5199 ENUM_T_STOP_BIT,
5200 ENUM_T_STOP_BIT, 1);
5201
David Keitel344c6972013-04-09 19:28:21 -07005202 rc = qpnp_chg_masked_write(chip,
5203 chip->usb_chgpth_base + SEC_ACCESS,
5204 0xFF,
5205 0xA5, 1);
5206
5207 rc = qpnp_chg_masked_write(chip,
5208 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
5209 0xFF,
5210 0x80, 1);
5211
David Keitel0b62bdd2013-07-10 17:30:51 -07005212 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
5213 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
5214 rc = qpnp_chg_masked_write(chip,
5215 chip->usb_chgpth_base + USB_OCP_THR,
5216 OCP_THR_MASK,
5217 OCP_THR_900_MA, 1);
5218 if (rc)
5219 pr_err("Failed to configure OCP rc = %d\n", rc);
5220 }
5221
David Keitel80668952012-07-27 14:25:49 -07005222 break;
5223 case SMBB_DC_CHGPTH_SUBTYPE:
5224 break;
5225 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005226 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07005227 init_data = of_get_regulator_init_data(chip->dev,
5228 spmi_resource->of_node);
5229 if (!init_data) {
5230 pr_err("unable to allocate memory\n");
5231 return -ENOMEM;
5232 }
5233
5234 if (init_data->constraints.name) {
5235 if (of_get_property(chip->dev->of_node,
5236 "boost-parent-supply", NULL))
5237 init_data->supply_regulator = "boost-parent";
5238
5239 rdesc = &(chip->boost_vreg.rdesc);
5240 rdesc->owner = THIS_MODULE;
5241 rdesc->type = REGULATOR_VOLTAGE;
5242 rdesc->ops = &qpnp_chg_boost_reg_ops;
5243 rdesc->name = init_data->constraints.name;
5244
5245 init_data->constraints.valid_ops_mask
5246 |= REGULATOR_CHANGE_STATUS
5247 | REGULATOR_CHANGE_VOLTAGE;
5248
5249 chip->boost_vreg.rdev = regulator_register(rdesc,
5250 chip->dev, init_data, chip,
5251 spmi_resource->of_node);
5252 if (IS_ERR(chip->boost_vreg.rdev)) {
5253 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07005254 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07005255 if (rc != -EPROBE_DEFER)
5256 pr_err("boost reg failed, rc=%d\n", rc);
5257 return rc;
5258 }
5259 }
David Keitel80668952012-07-27 14:25:49 -07005260 break;
5261 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005262 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005263 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07005264 if (subtype == SMBB_MISC_SUBTYPE)
5265 chip->type = SMBB;
5266 else if (subtype == SMBBP_MISC_SUBTYPE)
5267 chip->type = SMBBP;
5268 else if (subtype == SMBCL_MISC_SUBTYPE)
5269 chip->type = SMBCL;
5270
David Keitel80668952012-07-27 14:25:49 -07005271 pr_debug("Setting BOOT_DONE\n");
5272 rc = qpnp_chg_masked_write(chip,
5273 chip->misc_base + CHGR_MISC_BOOT_DONE,
5274 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005275 rc = qpnp_chg_read(chip, &reg,
5276 chip->misc_base + MISC_REVISION2, 1);
5277 if (rc) {
5278 pr_err("failed to read revision register rc=%d\n", rc);
5279 return rc;
5280 }
David Keitel80668952012-07-27 14:25:49 -07005281
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005282 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07005283 break;
5284 default:
5285 pr_err("Invalid peripheral subtype\n");
5286 }
5287 return rc;
5288}
5289
David Keitel112ba9c2013-04-12 18:40:43 -07005290#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
5291do { \
5292 if (retval) \
5293 break; \
5294 \
5295 retval = of_property_read_u32(chip->spmi->dev.of_node, \
5296 "qcom," qpnp_dt_property, \
5297 &chip->prop); \
5298 \
5299 if ((retval == -EINVAL) && optional) \
5300 retval = 0; \
5301 else if (retval) \
5302 pr_err("Error reading " #qpnp_dt_property \
5303 " property rc = %d\n", rc); \
5304} while (0)
5305
5306static int
5307qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
5308{
5309 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07005310 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07005311
5312 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
5313 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
5314 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
5315 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
5316 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
5317 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
5318 if (rc)
5319 pr_err("failed to read required dt parameters %d\n", rc);
5320
5321 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
5322 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
5323 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
5324 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
5325 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07005326 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07005327 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
5328 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07005329 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
Prasad Sodagudic3678012013-09-23 12:01:19 +05305330 OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
David Keitelbdbae452014-01-14 17:19:50 -08005331 OF_PROP_READ(chip, vbatdet_max_err_mv, "vbatdet-maxerr-mv", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07005332
David Keitel112ba9c2013-04-12 18:40:43 -07005333 if (rc)
5334 return rc;
5335
David Keitel796882d2013-05-14 18:01:11 -07005336 rc = of_property_read_string(chip->spmi->dev.of_node,
5337 "qcom,bpd-detection", &bpd);
5338 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07005339 /* Select BAT_THM as default BPD scheme */
5340 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005341 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07005342 } else {
5343 chip->bpd_detection = get_bpd(bpd);
5344 if (chip->bpd_detection < 0) {
5345 pr_err("failed to determine bpd schema %d\n", rc);
5346 return rc;
5347 }
5348 }
5349
David Keitelbdbae452014-01-14 17:19:50 -08005350 if (!chip->vbatdet_max_err_mv)
5351 chip->vbatdet_max_err_mv = VBATDET_MAX_ERR_MV;
5352
David Keitel112ba9c2013-04-12 18:40:43 -07005353 /* Look up JEITA compliance parameters if cool and warm temp provided */
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005354 if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005355 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
5356 if (IS_ERR(chip->adc_tm_dev)) {
5357 rc = PTR_ERR(chip->adc_tm_dev);
5358 if (rc != -EPROBE_DEFER)
5359 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07005360 return rc;
5361 }
5362
5363 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
5364 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
5365 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
5366 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
5367 if (rc)
5368 return rc;
5369 }
5370
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08005371 /* Get the use-external-rsense property */
5372 chip->use_external_rsense = of_property_read_bool(
5373 chip->spmi->dev.of_node,
5374 "qcom,use-external-rsense");
5375
David Keitel89c17752013-06-28 14:52:48 -07005376 /* Get the btc-disabled property */
5377 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
5378 "qcom,btc-disabled");
5379
David Keitel2586f0a2013-08-20 10:02:26 -07005380 ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
5381 "qcom,ext-ovp-present");
5382
David Keitelcd2e1022014-05-02 17:25:15 -07005383 /* Check if external IOVP part is configured */
5384 chip->ext_ovp_isns_gpio = of_get_named_gpio(chip->spmi->dev.of_node,
5385 "qcom,ext-ovp-isns-enable-gpio", 0);
5386 if (gpio_is_valid(chip->ext_ovp_isns_gpio)) {
5387 ext_ovp_isns_present = true;
5388 rc = of_property_read_u32(chip->spmi->dev.of_node,
5389 "qcom,ext-ovp-isns-r-ohm", &ext_ovp_isns_r);
5390 if (rc)
5391 return rc;
5392 }
5393
David Keitel112ba9c2013-04-12 18:40:43 -07005394 /* Get the charging-disabled property */
5395 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
5396 "qcom,charging-disabled");
5397
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005398 chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
5399 "qcom,ovp-monitor-en");
5400
David Keitel8b68d2d2013-05-14 23:36:51 -07005401 /* Get the duty-cycle-100p property */
5402 chip->duty_cycle_100p = of_property_read_bool(
5403 chip->spmi->dev.of_node,
5404 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07005405
David Keitel112ba9c2013-04-12 18:40:43 -07005406 /* Get the fake-batt-values property */
5407 chip->use_default_batt_values =
5408 of_property_read_bool(chip->spmi->dev.of_node,
5409 "qcom,use-default-batt-values");
5410
5411 /* Disable charging when faking battery values */
5412 if (chip->use_default_batt_values)
5413 chip->charging_disabled = true;
5414
Zhenhua Huangdc335512013-10-30 11:45:15 +08005415 chip->power_stage_workaround_enable =
5416 of_property_read_bool(chip->spmi->dev.of_node,
5417 "qcom,power-stage-reduced");
5418
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07005419 chip->ibat_calibration_enabled =
5420 of_property_read_bool(chip->spmi->dev.of_node,
5421 "qcom,ibat-calibration-enabled");
David Keitel975b5352014-01-27 14:28:04 -08005422 chip->parallel_ovp_mode =
5423 of_property_read_bool(chip->spmi->dev.of_node,
5424 "qcom,parallel-ovp-mode");
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07005425
David Keitel112ba9c2013-04-12 18:40:43 -07005426 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
5427 &(chip->thermal_levels));
5428
5429 if (chip->thermal_levels > sizeof(int)) {
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305430 chip->thermal_mitigation = devm_kzalloc(chip->dev,
David Keitel112ba9c2013-04-12 18:40:43 -07005431 chip->thermal_levels,
5432 GFP_KERNEL);
5433
5434 if (chip->thermal_mitigation == NULL) {
5435 pr_err("thermal mitigation kzalloc() failed.\n");
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305436 return -ENOMEM;
David Keitel112ba9c2013-04-12 18:40:43 -07005437 }
5438
5439 chip->thermal_levels /= sizeof(int);
5440 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
5441 "qcom,thermal-mitigation",
5442 chip->thermal_mitigation, chip->thermal_levels);
5443 if (rc) {
5444 pr_err("qcom,thermal-mitigation missing in dt\n");
5445 return rc;
5446 }
5447 }
5448
5449 return rc;
5450}
5451
David Keitel80668952012-07-27 14:25:49 -07005452static int __devinit
5453qpnp_charger_probe(struct spmi_device *spmi)
5454{
5455 u8 subtype;
5456 struct qpnp_chg_chip *chip;
5457 struct resource *resource;
5458 struct spmi_resource *spmi_resource;
5459 int rc = 0;
5460
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305461 chip = devm_kzalloc(&spmi->dev,
5462 sizeof(struct qpnp_chg_chip), GFP_KERNEL);
David Keitel80668952012-07-27 14:25:49 -07005463 if (chip == NULL) {
5464 pr_err("kzalloc() failed.\n");
5465 return -ENOMEM;
5466 }
5467
David Keitelfd305ee2013-07-19 20:19:06 -07005468 chip->prev_usb_max_ma = -EINVAL;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08005469 chip->fake_battery_soc = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07005470 chip->dev = &(spmi->dev);
5471 chip->spmi = spmi;
5472
5473 chip->usb_psy = power_supply_get_by_name("usb");
5474 if (!chip->usb_psy) {
5475 pr_err("usb supply not found deferring probe\n");
5476 rc = -EPROBE_DEFER;
5477 goto fail_chg_enable;
5478 }
5479
David Keitelec3c09802013-06-13 13:05:30 -07005480 mutex_init(&chip->jeita_configure_lock);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005481 spin_lock_init(&chip->usbin_health_monitor_lock);
Matt Mowera0f9b392015-10-12 19:37:46 -05005482#ifdef CONFIG_ANDROID_INTF_ALARM_DEV
5483 alarm_init(&chip->reduce_power_stage_alarm, ALARM_REALTIME,
5484 qpnp_chg_reduce_power_stage_callback);
5485#else
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005486 alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
5487 qpnp_chg_reduce_power_stage_callback);
Matt Mowera0f9b392015-10-12 19:37:46 -05005488#endif
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005489 INIT_WORK(&chip->reduce_power_stage_work,
5490 qpnp_chg_reduce_power_stage_work);
David Keitel6e63bd52013-09-06 18:00:03 -07005491 mutex_init(&chip->batfet_vreg_lock);
David Keitel8b9bd312014-01-15 14:44:00 -08005492 INIT_WORK(&chip->ocp_clear_work,
5493 qpnp_chg_ocp_clear_work);
David Keitel6e63bd52013-09-06 18:00:03 -07005494 INIT_WORK(&chip->batfet_lcl_work,
5495 qpnp_chg_batfet_lcl_work);
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005496 INIT_WORK(&chip->insertion_ocv_work,
5497 qpnp_chg_insertion_ocv_work);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005498
David Keitel112ba9c2013-04-12 18:40:43 -07005499 /* Get all device tree properties */
5500 rc = qpnp_charger_read_dt_props(chip);
5501 if (rc)
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305502 return rc;
David Keitel3dd5e0f2012-12-12 18:12:36 -08005503
David Keitelcd2e1022014-05-02 17:25:15 -07005504 if (ext_ovp_isns_present)
5505 chip->ext_ovp_ic_gpio_enabled = 0;
5506
Xiaozhe Shica289e02013-06-19 13:24:51 -07005507 /*
5508 * Check if bat_if is set in DT and make sure VADC is present
5509 * Also try loading the battery data profile if bat_if exists
5510 */
David Keiteldd87a172013-05-29 17:05:43 -07005511 spmi_for_each_container_dev(spmi_resource, spmi) {
5512 if (!spmi_resource) {
5513 pr_err("qpnp_chg: spmi resource absent\n");
5514 rc = -ENXIO;
5515 goto fail_chg_enable;
5516 }
5517
5518 resource = spmi_get_resource(spmi, spmi_resource,
5519 IORESOURCE_MEM, 0);
5520 if (!(resource && resource->start)) {
5521 pr_err("node %s IO resource absent!\n",
5522 spmi->dev.of_node->full_name);
5523 rc = -ENXIO;
5524 goto fail_chg_enable;
5525 }
5526
5527 rc = qpnp_chg_read(chip, &subtype,
5528 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
5529 if (rc) {
5530 pr_err("Peripheral subtype read failed rc=%d\n", rc);
5531 goto fail_chg_enable;
5532 }
5533
5534 if (subtype == SMBB_BAT_IF_SUBTYPE ||
5535 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07005536 subtype == SMBCL_BAT_IF_SUBTYPE) {
5537 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
5538 if (IS_ERR(chip->vadc_dev)) {
5539 rc = PTR_ERR(chip->vadc_dev);
5540 if (rc != -EPROBE_DEFER)
5541 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07005542 goto fail_chg_enable;
David Keitel42648fd2013-08-16 17:45:20 -07005543 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07005544
Chunmei Cai76705f02014-12-11 09:48:42 +08005545 if (subtype == SMBB_BAT_IF_SUBTYPE ||
5546 subtype == SMBBP_BAT_IF_SUBTYPE) {
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08005547 chip->iadc_dev = qpnp_get_iadc(chip->dev,
5548 "chg");
5549 if (IS_ERR(chip->iadc_dev)) {
5550 rc = PTR_ERR(chip->iadc_dev);
5551 if (rc != -EPROBE_DEFER)
5552 pr_err("iadc property missing\n");
5553 goto fail_chg_enable;
5554 }
5555 }
5556
Xiaozhe Shica289e02013-06-19 13:24:51 -07005557 rc = qpnp_chg_load_battery_data(chip);
5558 if (rc)
5559 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07005560 }
5561 }
5562
David Keitel80668952012-07-27 14:25:49 -07005563 spmi_for_each_container_dev(spmi_resource, spmi) {
5564 if (!spmi_resource) {
5565 pr_err("qpnp_chg: spmi resource absent\n");
5566 rc = -ENXIO;
5567 goto fail_chg_enable;
5568 }
5569
5570 resource = spmi_get_resource(spmi, spmi_resource,
5571 IORESOURCE_MEM, 0);
5572 if (!(resource && resource->start)) {
5573 pr_err("node %s IO resource absent!\n",
5574 spmi->dev.of_node->full_name);
5575 rc = -ENXIO;
5576 goto fail_chg_enable;
5577 }
5578
5579 rc = qpnp_chg_read(chip, &subtype,
5580 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
5581 if (rc) {
5582 pr_err("Peripheral subtype read failed rc=%d\n", rc);
5583 goto fail_chg_enable;
5584 }
5585
5586 switch (subtype) {
5587 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005588 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005589 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005590 chip->chgr_base = resource->start;
5591 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5592 if (rc) {
5593 pr_err("Failed to init subtype 0x%x rc=%d\n",
5594 subtype, rc);
5595 goto fail_chg_enable;
5596 }
5597 break;
5598 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005599 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005600 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005601 chip->buck_base = resource->start;
5602 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5603 if (rc) {
5604 pr_err("Failed to init subtype 0x%x rc=%d\n",
5605 subtype, rc);
5606 goto fail_chg_enable;
5607 }
David Keitel344c6972013-04-09 19:28:21 -07005608
5609 rc = qpnp_chg_masked_write(chip,
5610 chip->buck_base + SEC_ACCESS,
5611 0xFF,
5612 0xA5, 1);
5613
5614 rc = qpnp_chg_masked_write(chip,
5615 chip->buck_base + BUCK_VCHG_OV,
5616 0xff,
5617 0x00, 1);
5618
David Keiteldbc949b2013-07-11 10:56:03 -07005619 if (chip->duty_cycle_100p) {
5620 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
5621 1);
5622 if (rc) {
5623 pr_err("failed to set duty cycle %d\n",
5624 rc);
5625 goto fail_chg_enable;
5626 }
5627 }
5628
David Keitel80668952012-07-27 14:25:49 -07005629 break;
5630 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005631 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005632 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005633 chip->bat_if_base = resource->start;
5634 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5635 if (rc) {
5636 pr_err("Failed to init subtype 0x%x rc=%d\n",
5637 subtype, rc);
5638 goto fail_chg_enable;
5639 }
5640 break;
5641 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005642 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005643 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005644 chip->usb_chgpth_base = resource->start;
5645 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5646 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07005647 if (rc != -EPROBE_DEFER)
5648 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07005649 subtype, rc);
5650 goto fail_chg_enable;
5651 }
5652 break;
5653 case SMBB_DC_CHGPTH_SUBTYPE:
5654 chip->dc_chgpth_base = resource->start;
5655 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5656 if (rc) {
5657 pr_err("Failed to init subtype 0x%x rc=%d\n",
5658 subtype, rc);
5659 goto fail_chg_enable;
5660 }
5661 break;
5662 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005663 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005664 chip->boost_base = resource->start;
5665 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5666 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07005667 if (rc != -EPROBE_DEFER)
5668 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07005669 subtype, rc);
5670 goto fail_chg_enable;
5671 }
5672 break;
5673 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005674 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005675 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005676 chip->misc_base = resource->start;
5677 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5678 if (rc) {
5679 pr_err("Failed to init subtype=0x%x rc=%d\n",
5680 subtype, rc);
5681 goto fail_chg_enable;
5682 }
5683 break;
5684 default:
5685 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
5686 rc = -EINVAL;
5687 goto fail_chg_enable;
5688 }
5689 }
5690 dev_set_drvdata(&spmi->dev, chip);
5691 device_init_wakeup(&spmi->dev, 1);
5692
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005693 chip->insertion_ocv_uv = -EINVAL;
5694 chip->batt_present = qpnp_chg_is_batt_present(chip);
David Keitelf2170cc2013-02-20 17:49:03 -08005695 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08005696 chip->batt_psy.name = "battery";
5697 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
5698 chip->batt_psy.properties = msm_batt_power_props;
5699 chip->batt_psy.num_properties =
5700 ARRAY_SIZE(msm_batt_power_props);
5701 chip->batt_psy.get_property = qpnp_batt_power_get_property;
5702 chip->batt_psy.set_property = qpnp_batt_power_set_property;
5703 chip->batt_psy.property_is_writeable =
5704 qpnp_batt_property_is_writeable;
5705 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07005706 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07005707 chip->batt_psy.supplied_to = pm_batt_supplied_to;
5708 chip->batt_psy.num_supplicants =
5709 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07005710
David Keitelf2170cc2013-02-20 17:49:03 -08005711 rc = power_supply_register(chip->dev, &chip->batt_psy);
5712 if (rc < 0) {
5713 pr_err("batt failed to register rc = %d\n", rc);
5714 goto fail_chg_enable;
5715 }
David Keitel79f4c932013-04-03 16:08:39 -07005716 INIT_WORK(&chip->adc_measure_work,
5717 qpnp_bat_if_adc_measure_work);
David Keitelaa375562013-08-08 09:43:28 -07005718 INIT_WORK(&chip->adc_disable_work,
David Keitelecab15a2013-08-06 15:41:39 -07005719 qpnp_bat_if_adc_disable_work);
David Keitelc7093b02013-02-14 12:50:04 -08005720 }
5721
David Keitel9fd07382013-05-02 15:37:44 -07005722 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07005723 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005724 INIT_DELAYED_WORK(&chip->usbin_health_check,
5725 qpnp_usbin_health_check_work);
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07005726 INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
David Keitel7ac385e2013-08-19 18:02:40 -07005727 INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
David Keitel5910eea2013-05-02 15:32:25 -07005728
David Keitelf2170cc2013-02-20 17:49:03 -08005729 if (chip->dc_chgpth_base) {
5730 chip->dc_psy.name = "qpnp-dc";
5731 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
5732 chip->dc_psy.supplied_to = pm_power_supplied_to;
5733 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
5734 chip->dc_psy.properties = pm_power_props_mains;
5735 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
5736 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07005737 chip->dc_psy.set_property = qpnp_dc_power_set_property;
5738 chip->dc_psy.property_is_writeable =
5739 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08005740
5741 rc = power_supply_register(chip->dev, &chip->dc_psy);
5742 if (rc < 0) {
5743 pr_err("power_supply_register dc failed rc=%d\n", rc);
5744 goto unregister_batt;
5745 }
David Keitel80668952012-07-27 14:25:49 -07005746 }
5747
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005748 /* Turn on appropriate workaround flags */
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005749 rc = qpnp_chg_setup_flags(chip);
5750 if (rc < 0) {
5751 pr_err("failed to setup flags rc=%d\n", rc);
5752 goto unregister_dc_psy;
5753 }
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005754
David Keitelf2170cc2013-02-20 17:49:03 -08005755 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08005756 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
5757 if (rc) {
5758 pr_err("Error setting idcmax property %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005759 goto unregister_dc_psy;
David Keitel22ed2232013-01-28 11:04:07 -08005760 }
5761 }
5762
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005763 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0aea18a2013-06-14 18:57:57 -07005764 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07005765 chip->adc_param.low_temp = chip->cool_bat_decidegc;
5766 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08005767 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
5768 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
5769 chip->adc_param.btm_ctx = chip;
5770 chip->adc_param.threshold_notification =
5771 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08005772 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07005773
5774 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005775 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
5776 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005777 if (rc) {
5778 pr_err("request ADC error %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005779 goto unregister_dc_psy;
David Keitel0c1a4532013-03-21 16:39:06 -07005780 }
David Keitel454ee842013-03-08 16:19:11 -08005781 }
5782 }
David Keitel89c17752013-06-28 14:52:48 -07005783 rc = qpnp_chg_bat_if_configure_btc(chip);
5784 if (rc) {
5785 pr_err("failed to configure btc %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005786 goto unregister_dc_psy;
David Keitel89c17752013-06-28 14:52:48 -07005787 }
David Keitel454ee842013-03-08 16:19:11 -08005788
wangxlf0e6b1f2014-12-31 09:51:40 +08005789#ifdef CONFIG_TCMD
5790 the_chip = chip;
5791#endif
5792
David Keitelcd2e1022014-05-02 17:25:15 -07005793 chip->usb_trim_default = qpnp_chg_iusb_trim_get(chip);
David Keitel03ee6b52012-10-22 12:25:19 -07005794 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08005795 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07005796 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07005797
David Keitelbf2edba2014-03-05 10:49:32 -08005798 if (chip->parallel_ovp_mode) {
5799 rc = override_dcin_ilimit(chip, 1);
5800 if (rc) {
5801 pr_err("Override DCIN LLIMIT %d\n", rc);
5802 goto unregister_dc_psy;
5803 }
5804 }
5805
David Keitel0f35be42013-04-16 11:10:40 -07005806 rc = qpnp_chg_request_irqs(chip);
5807 if (rc) {
5808 pr_err("failed to request interrupts %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005809 goto unregister_dc_psy;
David Keitel0f35be42013-04-16 11:10:40 -07005810 }
5811
David Keitel7e38f512013-11-19 11:15:11 -08005812 qpnp_chg_usb_chg_gone_irq_handler(chip->chg_gone.irq, chip);
David Keitelad980fc2013-07-30 18:12:02 -07005813 qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
5814 qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
David Keitel9fd07382013-05-02 15:37:44 -07005815 power_supply_set_present(chip->usb_psy,
5816 qpnp_chg_is_usb_chg_plugged_in(chip));
5817
David Keitel3c62b472013-05-06 15:38:11 -07005818 /* Set USB psy online to avoid userspace from shutting down if battery
5819 * capacity is at zero and no chargers online. */
5820 if (qpnp_chg_is_usb_chg_plugged_in(chip))
5821 power_supply_set_online(chip->usb_psy, 1);
5822
David Keitel7ac385e2013-08-19 18:02:40 -07005823 schedule_delayed_work(&chip->aicl_check_work,
5824 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel796882d2013-05-14 18:01:11 -07005825 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 -08005826 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07005827 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08005828 qpnp_chg_is_usb_chg_plugged_in(chip),
5829 qpnp_chg_is_dc_chg_plugged_in(chip),
5830 get_prop_batt_present(chip),
5831 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07005832 return 0;
5833
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005834unregister_dc_psy:
5835 if (chip->dc_chgpth_base)
5836 power_supply_unregister(&chip->dc_psy);
David Keitelc7093b02013-02-14 12:50:04 -08005837unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08005838 if (chip->bat_if_base)
5839 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07005840fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07005841 regulator_unregister(chip->otg_vreg.rdev);
5842 regulator_unregister(chip->boost_vreg.rdev);
David Keitel80668952012-07-27 14:25:49 -07005843 return rc;
5844}
5845
5846static int __devexit
5847qpnp_charger_remove(struct spmi_device *spmi)
5848{
5849 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005850 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07005851 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005852 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
5853 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005854 }
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305855
5856 cancel_delayed_work_sync(&chip->aicl_check_work);
5857 power_supply_unregister(&chip->dc_psy);
5858 cancel_work_sync(&chip->soc_check_work);
5859 cancel_delayed_work_sync(&chip->usbin_health_check);
5860 cancel_delayed_work_sync(&chip->arb_stop_work);
David Keitel9fd07382013-05-02 15:37:44 -07005861 cancel_delayed_work_sync(&chip->eoc_work);
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305862 cancel_work_sync(&chip->adc_disable_work);
5863 cancel_work_sync(&chip->adc_measure_work);
5864 power_supply_unregister(&chip->batt_psy);
5865 cancel_work_sync(&chip->batfet_lcl_work);
5866 cancel_work_sync(&chip->insertion_ocv_work);
5867 cancel_work_sync(&chip->reduce_power_stage_work);
5868 alarm_cancel(&chip->reduce_power_stage_alarm);
5869
5870 mutex_destroy(&chip->batfet_vreg_lock);
5871 mutex_destroy(&chip->jeita_configure_lock);
David Keitel79f4c932013-04-03 16:08:39 -07005872
David Collinscbb12132013-05-28 10:47:28 -07005873 regulator_unregister(chip->otg_vreg.rdev);
5874 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07005875
David Keitel80668952012-07-27 14:25:49 -07005876 return 0;
5877}
5878
David Keitel85ae4342013-04-16 11:46:00 -07005879static int qpnp_chg_resume(struct device *dev)
5880{
5881 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5882 int rc = 0;
5883
David Keitel39093572013-06-05 15:32:30 -07005884 if (chip->bat_if_base) {
5885 rc = qpnp_chg_masked_write(chip,
5886 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5887 VREF_BATT_THERM_FORCE_ON,
5888 VREF_BATT_THERM_FORCE_ON, 1);
5889 if (rc)
5890 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
5891 }
David Keitel85ae4342013-04-16 11:46:00 -07005892
5893 return rc;
5894}
5895
5896static int qpnp_chg_suspend(struct device *dev)
5897{
5898 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5899 int rc = 0;
5900
c.wangba8a7eb2016-06-29 11:44:31 +08005901 qpnp_chg_regulator_batfet_set(chip, 1);
David Keitel39093572013-06-05 15:32:30 -07005902 if (chip->bat_if_base) {
5903 rc = qpnp_chg_masked_write(chip,
5904 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5905 VREF_BATT_THERM_FORCE_ON,
5906 VREF_BAT_THM_ENABLED_FSM, 1);
5907 if (rc)
5908 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
5909 }
David Keitel85ae4342013-04-16 11:46:00 -07005910
5911 return rc;
5912}
5913
David Keitel723d5012013-05-03 13:17:27 -07005914static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07005915 .resume = qpnp_chg_resume,
5916 .suspend = qpnp_chg_suspend,
5917};
5918
David Keitel80668952012-07-27 14:25:49 -07005919static struct spmi_driver qpnp_charger_driver = {
5920 .probe = qpnp_charger_probe,
5921 .remove = __devexit_p(qpnp_charger_remove),
5922 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07005923 .name = QPNP_CHARGER_DEV_NAME,
5924 .owner = THIS_MODULE,
5925 .of_match_table = qpnp_charger_match_table,
5926 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07005927 },
5928};
5929
5930/**
5931 * qpnp_chg_init() - register spmi driver for qpnp-chg
5932 */
5933int __init
5934qpnp_chg_init(void)
5935{
5936 return spmi_driver_register(&qpnp_charger_driver);
5937}
5938module_init(qpnp_chg_init);
5939
5940static void __exit
5941qpnp_chg_exit(void)
5942{
5943 spmi_driver_unregister(&qpnp_charger_driver);
5944}
5945module_exit(qpnp_chg_exit);
5946
5947
5948MODULE_DESCRIPTION("QPNP charger driver");
5949MODULE_LICENSE("GPL v2");
5950MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);