blob: d289bfba1cf6020ae033202bfcca2d92a90bdaae [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>
33#include <linux/android_alarm.h>
Wu Fenglin04ae6de2013-09-09 19:15:06 +080034#include <linux/spinlock.h>
David Keitelcd2e1022014-05-02 17:25:15 -070035#include <linux/gpio.h>
36#include <linux/of_gpio.h>
37#include <linux/qpnp/pin.h>
David Keitel80668952012-07-27 14:25:49 -070038
39/* Interrupt offsets */
40#define INT_RT_STS(base) (base + 0x10)
41#define INT_SET_TYPE(base) (base + 0x11)
42#define INT_POLARITY_HIGH(base) (base + 0x12)
43#define INT_POLARITY_LOW(base) (base + 0x13)
44#define INT_LATCHED_CLR(base) (base + 0x14)
45#define INT_EN_SET(base) (base + 0x15)
46#define INT_EN_CLR(base) (base + 0x16)
47#define INT_LATCHED_STS(base) (base + 0x18)
48#define INT_PENDING_STS(base) (base + 0x19)
49#define INT_MID_SEL(base) (base + 0x1A)
50#define INT_PRIORITY(base) (base + 0x1B)
51
52/* Peripheral register offsets */
53#define CHGR_CHG_OPTION 0x08
54#define CHGR_ATC_STATUS 0x0A
55#define CHGR_VBAT_STATUS 0x0B
56#define CHGR_IBAT_BMS 0x0C
57#define CHGR_IBAT_STS 0x0D
58#define CHGR_VDD_MAX 0x40
59#define CHGR_VDD_SAFE 0x41
60#define CHGR_VDD_MAX_STEP 0x42
61#define CHGR_IBAT_MAX 0x44
62#define CHGR_IBAT_SAFE 0x45
63#define CHGR_VIN_MIN 0x47
64#define CHGR_VIN_MIN_STEP 0x48
65#define CHGR_CHG_CTRL 0x49
66#define CHGR_CHG_FAILED 0x4A
67#define CHGR_ATC_CTRL 0x4B
68#define CHGR_ATC_FAILED 0x4C
69#define CHGR_VBAT_TRKL 0x50
70#define CHGR_VBAT_WEAK 0x52
71#define CHGR_IBAT_ATC_A 0x54
72#define CHGR_IBAT_ATC_B 0x55
73#define CHGR_IBAT_TERM_CHGR 0x5B
74#define CHGR_IBAT_TERM_BMS 0x5C
75#define CHGR_VBAT_DET 0x5D
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -080076#define CHGR_TTRKL_MAX_EN 0x5E
David Keitel80668952012-07-27 14:25:49 -070077#define CHGR_TTRKL_MAX 0x5F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -080078#define CHGR_TCHG_MAX_EN 0x60
David Keitel80668952012-07-27 14:25:49 -070079#define CHGR_TCHG_MAX 0x61
80#define CHGR_CHG_WDOG_TIME 0x62
81#define CHGR_CHG_WDOG_DLY 0x63
82#define CHGR_CHG_WDOG_PET 0x64
83#define CHGR_CHG_WDOG_EN 0x65
David Keitel9201df32013-01-10 18:38:34 -080084#define CHGR_IR_DROP_COMPEN 0x67
David Keitel22ed2232013-01-28 11:04:07 -080085#define CHGR_I_MAX_REG 0x44
David Keiteld681cda2012-10-02 15:44:21 -070086#define CHGR_USB_USB_SUSP 0x47
David Keitel6f865cd2012-11-30 15:04:32 -080087#define CHGR_USB_USB_OTG_CTL 0x48
David Keitel80668952012-07-27 14:25:49 -070088#define CHGR_USB_ENUM_T_STOP 0x4E
David Keitel2586f0a2013-08-20 10:02:26 -070089#define CHGR_USB_TRIM 0xF1
David Keitel80668952012-07-27 14:25:49 -070090#define CHGR_CHG_TEMP_THRESH 0x66
91#define CHGR_BAT_IF_PRES_STATUS 0x08
David Keiteld681cda2012-10-02 15:44:21 -070092#define CHGR_STATUS 0x09
David Keitel80668952012-07-27 14:25:49 -070093#define CHGR_BAT_IF_VCP 0x42
94#define CHGR_BAT_IF_BATFET_CTRL1 0x90
David Keitel9eca8ac2013-09-06 14:18:36 -070095#define CHGR_BAT_IF_BATFET_CTRL4 0x93
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -070096#define CHGR_BAT_IF_SPARE 0xDF
David Keitel80668952012-07-27 14:25:49 -070097#define CHGR_MISC_BOOT_DONE 0x42
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -070098#define CHGR_BUCK_PSTG_CTRL 0x73
David Keitel9fd07382013-05-02 15:37:44 -070099#define CHGR_BUCK_COMPARATOR_OVRIDE_1 0xEB
Fenglin Wuc64e9942014-08-22 13:47:34 +0800100#define CHGR_BUCK_COMPARATOR_OVRIDE_2 0xEC
David Keiteld681cda2012-10-02 15:44:21 -0700101#define CHGR_BUCK_COMPARATOR_OVRIDE_3 0xED
David Keitel79e08322014-04-21 14:17:05 -0700102#define CHG_OVR0 0xED
103#define CHG_TRICKLE_CLAMP 0xE3
David Keitel9201df32013-01-10 18:38:34 -0800104#define CHGR_BUCK_BCK_VBAT_REG_MODE 0x74
Sridhar Parasuramae183bd2012-12-21 09:28:46 -0800105#define MISC_REVISION2 0x01
David Keitel5c3a7702012-12-20 11:13:21 -0800106#define USB_OVP_CTL 0x42
David Keitel344c6972013-04-09 19:28:21 -0700107#define USB_CHG_GONE_REV_BST 0xED
108#define BUCK_VCHG_OV 0x77
109#define BUCK_TEST_SMBC_MODES 0xE6
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700110#define BUCK_CTRL_TRIM1 0xF1
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700111#define BUCK_CTRL_TRIM3 0xF3
David Keiteld681cda2012-10-02 15:44:21 -0700112#define SEC_ACCESS 0xD0
David Keitel85ae4342013-04-16 11:46:00 -0700113#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
David Keitel796882d2013-05-14 18:01:11 -0700114#define BAT_IF_BPD_CTRL 0x48
David Keitel6dc4ed42013-05-17 11:08:58 -0700115#define BOOST_VSET 0x41
116#define BOOST_ENABLE_CONTROL 0x46
David Keitel33f58952013-05-20 16:17:36 -0700117#define COMP_OVR1 0xEA
David Keitel89c17752013-06-28 14:52:48 -0700118#define BAT_IF_BTC_CTRL 0x49
David Keitel0b62bdd2013-07-10 17:30:51 -0700119#define USB_OCP_THR 0x52
120#define USB_OCP_CLR 0x53
Zhenhua Huang2a0ee352013-07-23 01:55:43 +0800121#define BAT_IF_TEMP_STATUS 0x09
David Keitel8b9bd312014-01-15 14:44:00 -0800122#define BOOST_ILIM 0x78
David Keitel975b5352014-01-27 14:28:04 -0800123#define USB_SPARE 0xDF
124#define DC_COMP_OVR1 0xE9
David Keitel59fbb762014-02-05 16:46:24 -0800125#define CHGR_COMP_OVR1 0xEE
David Keitel820a90d2014-03-25 18:18:04 -0700126#define USB_CHGPTH_CTL 0x40
David Keitel80668952012-07-27 14:25:49 -0700127#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700128
David Keitelf2170cc2013-02-20 17:49:03 -0800129/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700130#define SMBB_CHGR_SUBTYPE 0x01
131#define SMBB_BUCK_SUBTYPE 0x02
132#define SMBB_BAT_IF_SUBTYPE 0x03
133#define SMBB_USB_CHGPTH_SUBTYPE 0x04
134#define SMBB_DC_CHGPTH_SUBTYPE 0x05
135#define SMBB_BOOST_SUBTYPE 0x06
136#define SMBB_MISC_SUBTYPE 0x07
137
David Keitelf2170cc2013-02-20 17:49:03 -0800138/* SMBB peripheral subtype values */
139#define SMBBP_CHGR_SUBTYPE 0x31
140#define SMBBP_BUCK_SUBTYPE 0x32
141#define SMBBP_BAT_IF_SUBTYPE 0x33
142#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
143#define SMBBP_BOOST_SUBTYPE 0x36
144#define SMBBP_MISC_SUBTYPE 0x37
145
David Keitel46c9f7b2013-04-02 19:54:12 -0700146/* SMBCL peripheral subtype values */
147#define SMBCL_CHGR_SUBTYPE 0x41
148#define SMBCL_BUCK_SUBTYPE 0x42
149#define SMBCL_BAT_IF_SUBTYPE 0x43
150#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
151#define SMBCL_MISC_SUBTYPE 0x47
152
David Keitel80668952012-07-27 14:25:49 -0700153#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
154
David Keitelb80eda82012-10-15 10:49:11 -0700155/* Status bits and masks */
156#define CHGR_BOOT_DONE BIT(7)
157#define CHGR_CHG_EN BIT(7)
158#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800159#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800160#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700161#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700162#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700163#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700164#define REV_BST_DETECTED BIT(0)
165#define BAT_THM_EN BIT(1)
166#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700167#define BOOST_PWR_EN BIT(7)
David Keitel0b62bdd2013-07-10 17:30:51 -0700168#define OCP_CLR_BIT BIT(7)
169#define OCP_THR_MASK 0x03
170#define OCP_THR_900_MA 0x02
171#define OCP_THR_500_MA 0x01
172#define OCP_THR_200_MA 0x00
David Keitel820a90d2014-03-25 18:18:04 -0700173#define DC_HIGHER_PRIORITY BIT(7)
David Keitelb80eda82012-10-15 10:49:11 -0700174
David Keitel80668952012-07-27 14:25:49 -0700175/* Interrupt definitions */
176/* smbb_chg_interrupts */
177#define CHG_DONE_IRQ BIT(7)
178#define CHG_FAILED_IRQ BIT(6)
179#define FAST_CHG_ON_IRQ BIT(5)
180#define TRKL_CHG_ON_IRQ BIT(4)
181#define STATE_CHANGE_ON_IR BIT(3)
182#define CHGWDDOG_IRQ BIT(2)
183#define VBAT_DET_HI_IRQ BIT(1)
184#define VBAT_DET_LOW_IRQ BIT(0)
185
186/* smbb_buck_interrupts */
187#define VDD_LOOP_IRQ BIT(6)
188#define IBAT_LOOP_IRQ BIT(5)
189#define ICHG_LOOP_IRQ BIT(4)
190#define VCHG_LOOP_IRQ BIT(3)
191#define OVERTEMP_IRQ BIT(2)
192#define VREF_OV_IRQ BIT(1)
193#define VBAT_OV_IRQ BIT(0)
194
195/* smbb_bat_if_interrupts */
196#define PSI_IRQ BIT(4)
197#define VCP_ON_IRQ BIT(3)
198#define BAT_FET_ON_IRQ BIT(2)
199#define BAT_TEMP_OK_IRQ BIT(1)
200#define BATT_PRES_IRQ BIT(0)
201
202/* smbb_usb_interrupts */
203#define CHG_GONE_IRQ BIT(2)
204#define USBIN_VALID_IRQ BIT(1)
205#define COARSE_DET_USB_IRQ BIT(0)
206
207/* smbb_dc_interrupts */
208#define DCIN_VALID_IRQ BIT(1)
209#define COARSE_DET_DC_IRQ BIT(0)
210
211/* smbb_boost_interrupts */
212#define LIMIT_ERROR_IRQ BIT(1)
213#define BOOST_PWR_OK_IRQ BIT(0)
214
215/* smbb_misc_interrupts */
216#define TFTWDOG_IRQ BIT(0)
217
David Keitelfe51cb92013-04-02 19:42:58 -0700218/* SMBB types */
219#define SMBB BIT(1)
220#define SMBBP BIT(2)
221#define SMBCL BIT(3)
222
David Keiteld681cda2012-10-02 15:44:21 -0700223/* Workaround flags */
224#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700225#define BOOST_FLASH_WA BIT(1)
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700226#define POWER_STAGE_WA BIT(2)
David Keiteld681cda2012-10-02 15:44:21 -0700227
David Keitel47185a62013-05-15 18:54:10 -0700228struct qpnp_chg_irq {
David Keitel9879e2a2013-06-28 18:40:22 -0700229 int irq;
David Keitel47185a62013-05-15 18:54:10 -0700230 unsigned long disabled;
David Keitelbf6a1062014-01-23 10:57:36 -0800231 unsigned long wake_enable;
David Keitel47185a62013-05-15 18:54:10 -0700232};
233
David Keitel6dc4ed42013-05-17 11:08:58 -0700234struct qpnp_chg_regulator {
235 struct regulator_desc rdesc;
236 struct regulator_dev *rdev;
237};
238
David Keitel80668952012-07-27 14:25:49 -0700239/**
240 * struct qpnp_chg_chip - device information
241 * @dev: device pointer to access the parent
242 * @spmi: spmi pointer to access spmi information
243 * @chgr_base: charger peripheral base address
244 * @buck_base: buck peripheral base address
245 * @bat_if_base: battery interface peripheral base address
246 * @usb_chgpth_base: USB charge path peripheral base address
247 * @dc_chgpth_base: DC charge path peripheral base address
248 * @boost_base: boost peripheral base address
249 * @misc_base: misc peripheral base address
250 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800251 * @bat_is_cool: indicates that battery is cool
252 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700253 * @chg_done: indicates that charging is completed
254 * @usb_present: present status of usb
255 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800256 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800257 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700258 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700259 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800260 * @min_voltage_mv: min battery voltage before turning the FET on
Prasad Sodagudic3678012013-09-23 12:01:19 +0530261 * @batt_weak_voltage_mv: Weak battery voltage threshold
David Keitelbdbae452014-01-14 17:19:50 -0800262 * @vbatdet_max_err_mv resume voltage hysterisis
David Keitel454ee842013-03-08 16:19:11 -0800263 * @max_bat_chg_current: maximum battery charge current in mA
264 * @warm_bat_chg_ma: warm battery maximum charge current in mA
265 * @cool_bat_chg_ma: cool battery maximum charge current in mA
266 * @warm_bat_mv: warm temperature battery target voltage
267 * @cool_bat_mv: cool temperature battery target voltage
268 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700269 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800270 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800271 * @maxinput_usb_ma: Maximum Input current USB
272 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700273 * @hot_batt_p Hot battery threshold setting
274 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700275 * @warm_bat_decidegc Warm battery temperature in degree Celsius
276 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700277 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700278 * @type: SMBB type
279 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800280 * @thermal_levels amount of thermal mitigation levels
281 * @thermal_mitigation thermal mitigation level values
282 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700283 * @dc_psy power supply to export information to userspace
284 * @usb_psy power supply to export information to userspace
285 * @bms_psy power supply to export information to userspace
286 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700287 * @flags: flags to activate specific workarounds
288 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700289 *
290 */
291struct qpnp_chg_chip {
292 struct device *dev;
293 struct spmi_device *spmi;
294 u16 chgr_base;
295 u16 buck_base;
296 u16 bat_if_base;
297 u16 usb_chgpth_base;
298 u16 dc_chgpth_base;
299 u16 boost_base;
300 u16 misc_base;
301 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700302 struct qpnp_chg_irq usbin_valid;
David Keitel0b62bdd2013-07-10 17:30:51 -0700303 struct qpnp_chg_irq usb_ocp;
David Keitel47185a62013-05-15 18:54:10 -0700304 struct qpnp_chg_irq dcin_valid;
305 struct qpnp_chg_irq chg_gone;
306 struct qpnp_chg_irq chg_fastchg;
307 struct qpnp_chg_irq chg_trklchg;
308 struct qpnp_chg_irq chg_failed;
309 struct qpnp_chg_irq chg_vbatdet_lo;
310 struct qpnp_chg_irq batt_pres;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700311 struct qpnp_chg_irq batt_temp_ok;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800312 struct qpnp_chg_irq coarse_det_usb;
David Keitel454ee842013-03-08 16:19:11 -0800313 bool bat_is_cool;
314 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700315 bool chg_done;
David Keitel7ac385e2013-08-19 18:02:40 -0700316 bool charger_monitor_checked;
David Keitel80668952012-07-27 14:25:49 -0700317 bool usb_present;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800318 u8 usbin_health;
319 bool usb_coarse_det;
David Keitel80668952012-07-27 14:25:49 -0700320 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800321 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700322 bool charging_disabled;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800323 bool ovp_monitor_enable;
324 bool usb_valid_check_ovp;
David Keitel89c17752013-06-28 14:52:48 -0700325 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800326 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700327 bool duty_cycle_100p;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700328 bool ibat_calibration_enabled;
329 bool aicl_settled;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800330 bool use_external_rsense;
Wu Fenglin64fb1ac2013-11-08 10:20:14 +0800331 bool fastchg_on;
David Keitel975b5352014-01-27 14:28:04 -0800332 bool parallel_ovp_mode;
David Keitel796882d2013-05-14 18:01:11 -0700333 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700334 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800335 unsigned int warm_bat_chg_ma;
336 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700337 unsigned int safe_voltage_mv;
338 unsigned int max_voltage_mv;
339 unsigned int min_voltage_mv;
Prasad Sodagudic3678012013-09-23 12:01:19 +0530340 unsigned int batt_weak_voltage_mv;
David Keitelbdbae452014-01-14 17:19:50 -0800341 unsigned int vbatdet_max_err_mv;
David Keitelfd305ee2013-07-19 20:19:06 -0700342 int prev_usb_max_ma;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700343 int set_vddmax_mv;
344 int delta_vddmax_mv;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700345 u8 trim_center;
David Keitel454ee842013-03-08 16:19:11 -0800346 unsigned int warm_bat_mv;
347 unsigned int cool_bat_mv;
348 unsigned int resume_delta_mv;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700349 int insertion_ocv_uv;
David Keitel9fd07382013-05-02 15:37:44 -0700350 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700351 int soc_resume_limit;
352 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800353 unsigned int maxinput_usb_ma;
354 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700355 unsigned int hot_batt_p;
356 unsigned int cold_batt_p;
David Keitel27a97e62013-06-24 13:57:12 -0700357 int warm_bat_decidegc;
358 int cool_bat_decidegc;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -0800359 int fake_battery_soc;
David Keitel5d44fa52012-12-03 16:37:31 -0800360 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700361 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700362 unsigned int type;
363 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800364 unsigned int thermal_levels;
365 unsigned int therm_lvl_sel;
366 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700367 struct power_supply dc_psy;
368 struct power_supply *usb_psy;
369 struct power_supply *bms_psy;
370 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700371 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800372 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700373 struct work_struct adc_measure_work;
David Keitelecab15a2013-08-06 15:41:39 -0700374 struct work_struct adc_disable_work;
David Keitel344c6972013-04-09 19:28:21 -0700375 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700376 struct delayed_work eoc_work;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800377 struct delayed_work usbin_health_check;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -0700378 struct work_struct soc_check_work;
David Keitel7ac385e2013-08-19 18:02:40 -0700379 struct delayed_work aicl_check_work;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700380 struct work_struct insertion_ocv_work;
David Keitel8b9bd312014-01-15 14:44:00 -0800381 struct work_struct ocp_clear_work;
Chunmei Cai661a7cd2014-08-05 17:31:54 +0800382 struct qpnp_chg_regulator flash_wa_vreg;
David Keitel6dc4ed42013-05-17 11:08:58 -0700383 struct qpnp_chg_regulator otg_vreg;
384 struct qpnp_chg_regulator boost_vreg;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -0700385 struct qpnp_chg_regulator batfet_vreg;
David Keitel6e63bd52013-09-06 18:00:03 -0700386 bool batfet_ext_en;
387 struct work_struct batfet_lcl_work;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700388 struct qpnp_vadc_chip *vadc_dev;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800389 struct qpnp_iadc_chip *iadc_dev;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -0700390 struct qpnp_adc_tm_chip *adc_tm_dev;
David Keitelec3c09802013-06-13 13:05:30 -0700391 struct mutex jeita_configure_lock;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800392 spinlock_t usbin_health_monitor_lock;
David Keitel6e63bd52013-09-06 18:00:03 -0700393 struct mutex batfet_vreg_lock;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700394 struct alarm reduce_power_stage_alarm;
395 struct work_struct reduce_power_stage_work;
396 bool power_stage_workaround_running;
Zhenhua Huangdc335512013-10-30 11:45:15 +0800397 bool power_stage_workaround_enable;
Chunmei Cai661a7cd2014-08-05 17:31:54 +0800398 bool is_flash_wa_reg_enabled;
David Keitelcd2e1022014-05-02 17:25:15 -0700399 bool ext_ovp_ic_gpio_enabled;
400 unsigned int ext_ovp_isns_gpio;
401 unsigned int usb_trim_default;
Chunmei Cai661a7cd2014-08-05 17:31:54 +0800402 u8 chg_temp_thresh_default;
David Keitel80668952012-07-27 14:25:49 -0700403};
404
David Keitel59fbb762014-02-05 16:46:24 -0800405static void
406qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip);
David Keitel47185a62013-05-15 18:54:10 -0700407
David Keitel80668952012-07-27 14:25:49 -0700408static struct of_device_id qpnp_charger_match_table[] = {
409 { .compatible = QPNP_CHARGER_DEV_NAME, },
410 {}
411};
412
David Keitel0ef282b2013-05-29 16:04:57 -0700413enum bpd_type {
414 BPD_TYPE_BAT_ID,
415 BPD_TYPE_BAT_THM,
416 BPD_TYPE_BAT_THM_BAT_ID,
417};
David Keitel796882d2013-05-14 18:01:11 -0700418
David Keitel0ef282b2013-05-29 16:04:57 -0700419static const char * const bpd_label[] = {
420 [BPD_TYPE_BAT_ID] = "bpd_id",
421 [BPD_TYPE_BAT_THM] = "bpd_thm",
422 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700423};
424
David Keitel89c17752013-06-28 14:52:48 -0700425enum btc_type {
426 HOT_THD_25_PCT = 25,
427 HOT_THD_35_PCT = 35,
428 COLD_THD_70_PCT = 70,
429 COLD_THD_80_PCT = 80,
430};
431
432static u8 btc_value[] = {
433 [HOT_THD_25_PCT] = 0x0,
434 [HOT_THD_35_PCT] = BIT(0),
435 [COLD_THD_70_PCT] = 0x0,
436 [COLD_THD_80_PCT] = BIT(1),
437};
438
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800439enum usbin_health {
440 USBIN_UNKNOW,
441 USBIN_OK,
442 USBIN_OVP,
443};
444
David Keitelcd2e1022014-05-02 17:25:15 -0700445static int ext_ovp_isns_present;
446module_param(ext_ovp_isns_present, int, 0444);
447static int ext_ovp_isns_r;
448module_param(ext_ovp_isns_r, int, 0444);
449
450static bool ext_ovp_isns_online;
451static long ext_ovp_isns_ua;
452#define MAX_CURRENT_LENGTH_9A 10
453#define ISNS_CURRENT_RATIO 2500
454static int ext_ovp_isns_read(char *buffer, const struct kernel_param *kp)
455{
456 int rc;
457 struct qpnp_vadc_result results;
458 struct power_supply *batt_psy = power_supply_get_by_name("battery");
459 struct qpnp_chg_chip *chip = container_of(batt_psy,
460 struct qpnp_chg_chip, batt_psy);
461
462 if (!ext_ovp_isns_present)
463 return 0;
464
465 rc = qpnp_vadc_read(chip->vadc_dev, P_MUX7_1_1, &results);
466 if (rc) {
467 pr_err("Unable to read vbat rc=%d\n", rc);
468 return 0;
469 }
470
471 pr_debug("voltage %lld uV, current: %d\n mA", results.physical,
472 ((int) results.physical /
473 (ext_ovp_isns_r / ISNS_CURRENT_RATIO)));
474
475 return snprintf(buffer, MAX_CURRENT_LENGTH_9A, "%d\n",
476 ((int)results.physical /
477 (ext_ovp_isns_r / ISNS_CURRENT_RATIO)));
478}
479
480static int ext_ovp_isns_enable(const char *val, const struct kernel_param *kp)
481{
482 int rc;
483 struct power_supply *batt_psy = power_supply_get_by_name("battery");
484 struct qpnp_chg_chip *chip = container_of(batt_psy,
485 struct qpnp_chg_chip, batt_psy);
486
487 rc = param_set_bool(val, kp);
488 if (rc) {
489 pr_err("Unable to set gpio en: %d\n", rc);
490 return rc;
491 }
492
493 if (*(bool *)kp->arg) {
494 gpio_direction_output(
495 chip->ext_ovp_isns_gpio, 1);
496 chip->ext_ovp_ic_gpio_enabled = 1;
497 pr_debug("enabled GPIO\n");
498 } else {
499 gpio_direction_output(
500 chip->ext_ovp_isns_gpio, 0);
501 chip->ext_ovp_ic_gpio_enabled = 0;
502 pr_debug("disabled GPIO\n");
503 }
504
505 return rc;
506}
507
508static struct kernel_param_ops ext_ovp_isns_ops = {
509 .get = ext_ovp_isns_read,
510};
511module_param_cb(ext_ovp_isns_ua, &ext_ovp_isns_ops, &ext_ovp_isns_ua, 0644);
512
513static struct kernel_param_ops ext_ovp_en_ops = {
514 .set = ext_ovp_isns_enable,
515 .get = param_get_bool,
516};
517module_param_cb(ext_ovp_isns_online, &ext_ovp_en_ops,
518 &ext_ovp_isns_online, 0664);
519
wangxlee3614a2015-02-03 13:13:11 +0800520#ifdef CONFIG_TCMD
521static struct qpnp_chg_chip *the_chip;
522#endif
523
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800524static inline int
David Keitel796882d2013-05-14 18:01:11 -0700525get_bpd(const char *name)
526{
527 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700528 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
529 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700530 return i;
531 }
532 return -EINVAL;
533}
534
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700535static bool
536is_within_range(int value, int left, int right)
537{
538 if (left >= right && left >= value && value >= right)
539 return 1;
540 if (left <= right && left <= value && value <= right)
541 return 1;
542 return 0;
543}
544
David Keitel80668952012-07-27 14:25:49 -0700545static int
546qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
547 u16 base, int count)
548{
David Keitel39093572013-06-05 15:32:30 -0700549 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700550 struct spmi_device *spmi = chip->spmi;
551
David Keitel39093572013-06-05 15:32:30 -0700552 if (base == 0) {
553 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
554 base, spmi->sid, rc);
555 return -EINVAL;
556 }
557
558 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700559 if (rc) {
560 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
561 spmi->sid, rc);
562 return rc;
563 }
564 return 0;
565}
566
567static int
568qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
569 u16 base, int count)
570{
David Keitel39093572013-06-05 15:32:30 -0700571 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700572 struct spmi_device *spmi = chip->spmi;
573
David Keitel39093572013-06-05 15:32:30 -0700574 if (base == 0) {
575 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
576 base, spmi->sid, rc);
577 return -EINVAL;
578 }
579
580 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700581 if (rc) {
582 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
583 base, spmi->sid, rc);
584 return rc;
585 }
586
587 return 0;
588}
589
590static int
591qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
592 u8 mask, u8 val, int count)
593{
594 int rc;
595 u8 reg;
596
597 rc = qpnp_chg_read(chip, &reg, base, count);
598 if (rc) {
599 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
600 return rc;
601 }
602 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
603
604 reg &= ~mask;
605 reg |= val & mask;
606
607 pr_debug("Writing 0x%x\n", reg);
608
609 rc = qpnp_chg_write(chip, &reg, base, count);
610 if (rc) {
611 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
612 return rc;
613 }
614
615 return 0;
616}
617
David Keitel47185a62013-05-15 18:54:10 -0700618static void
619qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
620{
621 if (__test_and_clear_bit(0, &irq->disabled)) {
622 pr_debug("number = %d\n", irq->irq);
623 enable_irq(irq->irq);
624 }
625}
626
627static void
628qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
629{
630 if (!__test_and_set_bit(0, &irq->disabled)) {
631 pr_debug("number = %d\n", irq->irq);
632 disable_irq_nosync(irq->irq);
633 }
634}
635
David Keitelbf6a1062014-01-23 10:57:36 -0800636static void
637qpnp_chg_irq_wake_enable(struct qpnp_chg_irq *irq)
638{
639 if (!__test_and_set_bit(0, &irq->wake_enable)) {
640 pr_debug("number = %d\n", irq->irq);
641 enable_irq_wake(irq->irq);
642 }
643}
644
645static void
646qpnp_chg_irq_wake_disable(struct qpnp_chg_irq *irq)
647{
648 if (__test_and_clear_bit(0, &irq->wake_enable)) {
649 pr_debug("number = %d\n", irq->irq);
650 disable_irq_wake(irq->irq);
651 }
652}
653
David Keitel6f865cd2012-11-30 15:04:32 -0800654#define USB_OTG_EN_BIT BIT(0)
655static int
656qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
657{
658 u8 usb_otg_en;
659 int rc;
660
661 rc = qpnp_chg_read(chip, &usb_otg_en,
662 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
663 1);
664
665 if (rc) {
666 pr_err("spmi read failed: addr=%03X, rc=%d\n",
667 chip->usb_chgpth_base + CHGR_STATUS, rc);
668 return rc;
669 }
670 pr_debug("usb otg en 0x%x\n", usb_otg_en);
671
672 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
673}
674
David Keitel42ae0aa2013-03-08 16:20:10 -0800675static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700676qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
677{
678 u8 boost_en_ctl;
679 int rc;
680
681 rc = qpnp_chg_read(chip, &boost_en_ctl,
682 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
683 if (rc) {
684 pr_err("spmi read failed: addr=%03X, rc=%d\n",
685 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
686 return rc;
687 }
688
689 pr_debug("boost en 0x%x\n", boost_en_ctl);
690
691 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
692}
693
694static int
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700695qpnp_chg_is_batt_temp_ok(struct qpnp_chg_chip *chip)
696{
697 u8 batt_rt_sts;
698 int rc;
699
700 rc = qpnp_chg_read(chip, &batt_rt_sts,
701 INT_RT_STS(chip->bat_if_base), 1);
702 if (rc) {
703 pr_err("spmi read failed: addr=%03X, rc=%d\n",
704 INT_RT_STS(chip->bat_if_base), rc);
705 return rc;
706 }
707
708 return (batt_rt_sts & BAT_TEMP_OK_IRQ) ? 1 : 0;
709}
710
711static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800712qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
713{
714 u8 batt_pres_rt_sts;
715 int rc;
716
717 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
718 INT_RT_STS(chip->bat_if_base), 1);
719 if (rc) {
720 pr_err("spmi read failed: addr=%03X, rc=%d\n",
721 INT_RT_STS(chip->bat_if_base), rc);
722 return rc;
723 }
724
725 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
726}
727
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700728static int
729qpnp_chg_is_batfet_closed(struct qpnp_chg_chip *chip)
730{
731 u8 batfet_closed_rt_sts;
732 int rc;
733
734 rc = qpnp_chg_read(chip, &batfet_closed_rt_sts,
735 INT_RT_STS(chip->bat_if_base), 1);
736 if (rc) {
737 pr_err("spmi read failed: addr=%03X, rc=%d\n",
738 INT_RT_STS(chip->bat_if_base), rc);
739 return rc;
740 }
741
742 return (batfet_closed_rt_sts & BAT_FET_ON_IRQ) ? 1 : 0;
743}
744
David Keitel80668952012-07-27 14:25:49 -0700745static int
746qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
747{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800748 u8 usb_chgpth_rt_sts;
David Keitel80668952012-07-27 14:25:49 -0700749 int rc;
750
Zhenhua Huangf1163872014-03-03 10:51:25 +0800751 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
752 INT_RT_STS(chip->usb_chgpth_base), 1);
David Keitel80668952012-07-27 14:25:49 -0700753
754 if (rc) {
755 pr_err("spmi read failed: addr=%03X, rc=%d\n",
Zhenhua Huangf1163872014-03-03 10:51:25 +0800756 INT_RT_STS(chip->usb_chgpth_base), rc);
David Keitel80668952012-07-27 14:25:49 -0700757 return rc;
758 }
Zhenhua Huangf1163872014-03-03 10:51:25 +0800759 pr_debug("chgr usb sts 0x%x\n", usb_chgpth_rt_sts);
David Keitel80668952012-07-27 14:25:49 -0700760
Zhenhua Huangf1163872014-03-03 10:51:25 +0800761 return (usb_chgpth_rt_sts & USBIN_VALID_IRQ) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700762}
763
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700764static bool
David Keitel820a90d2014-03-25 18:18:04 -0700765qpnp_is_dc_higher_prio(struct qpnp_chg_chip *chip)
766{
767 int rc;
768 u8 usb_ctl;
769
770 if (!chip->type == SMBB)
771 return false;
772
773 rc = qpnp_chg_read(chip, &usb_ctl,
774 chip->usb_chgpth_base + USB_CHGPTH_CTL, 1);
775 if (rc) {
776 pr_err("failed to read usb ctl rc=%d\n", rc);
777 return 0;
778 }
779
780 return !!(usb_ctl & DC_HIGHER_PRIORITY);
781}
782
783static bool
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700784qpnp_chg_is_ibat_loop_active(struct qpnp_chg_chip *chip)
785{
786 int rc;
787 u8 buck_sts;
788
789 rc = qpnp_chg_read(chip, &buck_sts,
790 INT_RT_STS(chip->buck_base), 1);
791 if (rc) {
792 pr_err("failed to read buck RT status rc=%d\n", rc);
793 return 0;
794 }
795
796 return !!(buck_sts & IBAT_LOOP_IRQ);
797}
798
Zhenhua Huangf1163872014-03-03 10:51:25 +0800799#define USB_VALID_MASK 0xC0
800#define USB_VALID_IN_MASK BIT(7)
801#define USB_COARSE_DET 0x10
802#define USB_VALID_OVP_VALUE 0x40
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800803static int
804qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
805{
806 u8 usbin_chg_rt_sts;
807 int rc;
808 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
809 chip->usb_chgpth_base + CHGR_STATUS , 1);
810 if (rc) {
811 pr_err("spmi read failed: addr=%03X, rc=%d\n",
812 chip->usb_chgpth_base + CHGR_STATUS, rc);
813 return rc;
814 }
815 return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
816}
817
818static int
819qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
820{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800821 u8 usbin_chg_rt_sts, usb_chgpth_rt_sts;
822 u8 usbin_health = 0;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800823 int rc;
824
825 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
826 chip->usb_chgpth_base + CHGR_STATUS , 1);
827
828 if (rc) {
829 pr_err("spmi read failed: addr=%03X, rc=%d\n",
830 chip->usb_chgpth_base + CHGR_STATUS, rc);
831 return rc;
832 }
833
Zhenhua Huangf1163872014-03-03 10:51:25 +0800834 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
835 INT_RT_STS(chip->usb_chgpth_base) , 1);
836
837 if (rc) {
838 pr_err("spmi read failed: addr=%03X, rc=%d\n",
839 INT_RT_STS(chip->usb_chgpth_base), rc);
840 return rc;
841 }
842
843 pr_debug("chgr usb sts 0x%x, chgpth rt sts 0x%x\n",
844 usbin_chg_rt_sts, usb_chgpth_rt_sts);
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800845 if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
846 if ((usbin_chg_rt_sts & USB_VALID_MASK)
847 == USB_VALID_OVP_VALUE) {
848 usbin_health = USBIN_OVP;
849 pr_err("Over voltage charger inserted\n");
Zhenhua Huangf1163872014-03-03 10:51:25 +0800850 } else if ((usb_chgpth_rt_sts & USBIN_VALID_IRQ) != 0) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800851 usbin_health = USBIN_OK;
852 pr_debug("Valid charger inserted\n");
853 }
854 } else {
855 usbin_health = USBIN_UNKNOW;
856 pr_debug("Charger plug out\n");
857 }
858
859 return usbin_health;
860}
861
David Keitel80668952012-07-27 14:25:49 -0700862static int
863qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
864{
865 u8 dcin_valid_rt_sts;
866 int rc;
867
David Keitelf2170cc2013-02-20 17:49:03 -0800868 if (!chip->dc_chgpth_base)
869 return 0;
870
David Keitel80668952012-07-27 14:25:49 -0700871 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
872 INT_RT_STS(chip->dc_chgpth_base), 1);
873 if (rc) {
874 pr_err("spmi read failed: addr=%03X, rc=%d\n",
875 INT_RT_STS(chip->dc_chgpth_base), rc);
876 return rc;
877 }
878
879 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
880}
881
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700882static int
883qpnp_chg_is_ichg_loop_active(struct qpnp_chg_chip *chip)
884{
885 u8 buck_sts;
886 int rc;
887
888 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
889
890 if (rc) {
891 pr_err("spmi read failed: addr=%03X, rc=%d\n",
892 INT_RT_STS(chip->buck_base), rc);
893 return rc;
894 }
895 pr_debug("buck usb sts 0x%x\n", buck_sts);
896
897 return (buck_sts & ICHG_LOOP_IRQ) ? 1 : 0;
898}
899
David Keitel22ed2232013-01-28 11:04:07 -0800900#define QPNP_CHG_I_MAX_MIN_100 100
901#define QPNP_CHG_I_MAX_MIN_150 150
902#define QPNP_CHG_I_MAX_MIN_MA 200
903#define QPNP_CHG_I_MAX_MAX_MA 2500
904#define QPNP_CHG_I_MAXSTEP_MA 100
905static int
906qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
907{
908 int rc = 0;
909 u8 dc = 0;
910
911 if (mA < QPNP_CHG_I_MAX_MIN_100
912 || mA > QPNP_CHG_I_MAX_MAX_MA) {
913 pr_err("bad mA=%d asked to set\n", mA);
914 return -EINVAL;
915 }
916
917 if (mA == QPNP_CHG_I_MAX_MIN_100) {
918 dc = 0x00;
919 pr_debug("current=%d setting %02x\n", mA, dc);
920 return qpnp_chg_write(chip, &dc,
921 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
922 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
923 dc = 0x01;
924 pr_debug("current=%d setting %02x\n", mA, dc);
925 return qpnp_chg_write(chip, &dc,
926 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
927 }
928
929 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
930
931 pr_debug("current=%d setting 0x%x\n", mA, dc);
932 rc = qpnp_chg_write(chip, &dc,
933 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
934
935 return rc;
936}
937
David Keitel80668952012-07-27 14:25:49 -0700938static int
David Keitel2586f0a2013-08-20 10:02:26 -0700939qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
940{
941 int rc = 0;
942 u8 trim_reg;
943
944 rc = qpnp_chg_read(chip, &trim_reg,
945 chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
946 if (rc) {
947 pr_err("failed to read USB_TRIM rc=%d\n", rc);
948 return 0;
949 }
950
951 return trim_reg;
952}
953
954static int
955qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
956{
957 int rc = 0;
958
959 rc = qpnp_chg_masked_write(chip,
960 chip->usb_chgpth_base + SEC_ACCESS,
961 0xFF,
962 0xA5, 1);
963 if (rc) {
964 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
965 return rc;
966 }
967
968 rc = qpnp_chg_masked_write(chip,
969 chip->usb_chgpth_base + CHGR_USB_TRIM,
970 0xFF,
971 trim, 1);
972 if (rc) {
973 pr_err("failed to write USB TRIM rc=%d\n", rc);
974 return rc;
975 }
976
977 return rc;
978}
979
David Keitelcd2e1022014-05-02 17:25:15 -0700980#define IOVP_USB_WALL_TRSH_MA 150
David Keitel2586f0a2013-08-20 10:02:26 -0700981static int
David Keitel80668952012-07-27 14:25:49 -0700982qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
983{
David Keiteld681cda2012-10-02 15:44:21 -0700984 int rc = 0;
985 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700986
David Keitel7b0568482013-12-02 14:47:42 -0800987 if (mA < 0 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700988 pr_err("bad mA=%d asked to set\n", mA);
989 return -EINVAL;
990 }
991
David Keitel7b0568482013-12-02 14:47:42 -0800992 if (mA <= QPNP_CHG_I_MAX_MIN_100) {
David Keitel22ed2232013-01-28 11:04:07 -0800993 usb_reg = 0x00;
994 pr_debug("current=%d setting %02x\n", mA, usb_reg);
995 return qpnp_chg_write(chip, &usb_reg,
996 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
997 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
998 usb_reg = 0x01;
999 pr_debug("current=%d setting %02x\n", mA, usb_reg);
1000 return qpnp_chg_write(chip, &usb_reg,
1001 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1002 }
1003
1004 /* Impose input current limit */
1005 if (chip->maxinput_usb_ma)
1006 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
1007
1008 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -07001009
David Keiteld681cda2012-10-02 15:44:21 -07001010 if (chip->flags & CHG_FLAGS_VCP_WA) {
1011 temp = 0xA5;
1012 rc = qpnp_chg_write(chip, &temp,
1013 chip->buck_base + SEC_ACCESS, 1);
1014 rc = qpnp_chg_masked_write(chip,
1015 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
1016 0x0C, 0x0C, 1);
1017 }
1018
David Keitel80668952012-07-27 14:25:49 -07001019 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -07001020 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -08001021 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -07001022
1023 if (chip->flags & CHG_FLAGS_VCP_WA) {
1024 temp = 0xA5;
1025 udelay(200);
1026 rc = qpnp_chg_write(chip, &temp,
1027 chip->buck_base + SEC_ACCESS, 1);
1028 rc = qpnp_chg_masked_write(chip,
1029 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
1030 0x0C, 0x00, 1);
1031 }
1032
1033 return rc;
1034}
1035
David Keitel25544a22013-12-06 17:59:24 -08001036#define QPNP_CHG_VINMIN_MIN_MV 4000
David Keitel337bd862013-07-15 21:42:58 -07001037#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
1038#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
1039#define QPNP_CHG_VINMIN_MAX_MV 9600
1040#define QPNP_CHG_VINMIN_STEP_MV 50
1041#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
Prasad Sodagudi95624b62013-09-26 16:40:59 +05301042#define QPNP_CHG_VINMIN_MASK 0x3F
David Keitel25544a22013-12-06 17:59:24 -08001043#define QPNP_CHG_VINMIN_MIN_VAL 0x0C
David Keitel337bd862013-07-15 21:42:58 -07001044static int
1045qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
1046{
1047 u8 temp;
1048
David Keitel25544a22013-12-06 17:59:24 -08001049 if ((voltage < QPNP_CHG_VINMIN_MIN_MV)
1050 || (voltage > QPNP_CHG_VINMIN_MAX_MV)) {
David Keitel337bd862013-07-15 21:42:58 -07001051 pr_err("bad mV=%d asked to set\n", voltage);
1052 return -EINVAL;
1053 }
1054 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
1055 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
David Keitel289fcf82013-10-24 11:33:00 -07001056 temp += (voltage - QPNP_CHG_VINMIN_HIGH_MIN_MV)
David Keitel337bd862013-07-15 21:42:58 -07001057 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
1058 } else {
1059 temp = QPNP_CHG_VINMIN_MIN_VAL;
1060 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
1061 / QPNP_CHG_VINMIN_STEP_MV;
1062 }
1063
1064 pr_debug("voltage=%d setting %02x\n", voltage, temp);
1065 return qpnp_chg_masked_write(chip,
1066 chip->chgr_base + CHGR_VIN_MIN,
1067 QPNP_CHG_VINMIN_MASK, temp, 1);
1068}
1069
1070static int
1071qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
1072{
1073 int rc, vin_min_mv;
1074 u8 vin_min;
1075
1076 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
1077 if (rc) {
1078 pr_err("failed to read VIN_MIN rc=%d\n", rc);
1079 return 0;
1080 }
1081
1082 if (vin_min == 0)
1083 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
David Keitel289fcf82013-10-24 11:33:00 -07001084 else if (vin_min >= QPNP_CHG_VINMIN_HIGH_MIN_VAL)
David Keitel337bd862013-07-15 21:42:58 -07001085 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
1086 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
1087 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
1088 else
1089 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
1090 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
1091 * QPNP_CHG_VINMIN_STEP_MV;
1092 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
1093
1094 return vin_min_mv;
1095}
1096
Prasad Sodagudic3678012013-09-23 12:01:19 +05301097#define QPNP_CHG_VBATWEAK_MIN_MV 2100
1098#define QPNP_CHG_VBATWEAK_MAX_MV 3600
1099#define QPNP_CHG_VBATWEAK_STEP_MV 100
1100static int
1101qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
1102{
1103 u8 temp;
1104
1105 if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
1106 || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
1107 return -EINVAL;
1108
1109 temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
1110 / QPNP_CHG_VBATWEAK_STEP_MV;
1111
1112 pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
1113 return qpnp_chg_write(chip, &temp,
1114 chip->chgr_base + CHGR_VBAT_WEAK, 1);
1115}
1116
David Keitel337bd862013-07-15 21:42:58 -07001117static int
1118qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
1119{
1120 int rc, iusbmax_ma;
1121 u8 iusbmax;
1122
1123 rc = qpnp_chg_read(chip, &iusbmax,
1124 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1125 if (rc) {
1126 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
1127 return 0;
1128 }
1129
1130 if (iusbmax == 0)
1131 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
1132 else if (iusbmax == 0x01)
1133 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
1134 else
1135 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
1136
1137 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
1138
1139 return iusbmax_ma;
1140}
1141
David Keitel975b5352014-01-27 14:28:04 -08001142#define ILIMIT_OVR_0 0x02
1143static int
1144override_dcin_ilimit(struct qpnp_chg_chip *chip, bool override)
1145{
1146 int rc;
1147
1148 pr_debug("override %d\n", override);
1149 rc = qpnp_chg_masked_write(chip,
1150 chip->dc_chgpth_base + SEC_ACCESS,
1151 0xA5,
1152 0xA5, 1);
1153 rc |= qpnp_chg_masked_write(chip,
1154 chip->dc_chgpth_base + DC_COMP_OVR1,
1155 0xFF,
1156 override ? ILIMIT_OVR_0 : 0, 1);
1157 if (rc) {
1158 pr_err("Failed to override dc ilimit rc = %d\n", rc);
1159 return rc;
1160 }
1161
1162 return rc;
1163}
1164
1165#define DUAL_PATH_EN BIT(7)
1166static int
1167switch_parallel_ovp_mode(struct qpnp_chg_chip *chip, bool enable)
1168{
1169 int rc = 0;
1170
1171 if (!chip->usb_chgpth_base || !chip->dc_chgpth_base)
1172 return rc;
1173
1174 pr_debug("enable %d\n", enable);
1175 rc = override_dcin_ilimit(chip, 1);
1176 udelay(10);
1177
1178 /* enable/disable dual path mode */
1179 rc = qpnp_chg_masked_write(chip,
1180 chip->usb_chgpth_base + SEC_ACCESS,
1181 0xA5,
1182 0xA5, 1);
1183 rc |= qpnp_chg_masked_write(chip,
1184 chip->usb_chgpth_base + USB_SPARE,
1185 0xFF,
1186 enable ? DUAL_PATH_EN : 0, 1);
1187 if (rc) {
1188 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1189 return rc;
1190 }
1191
David Keitelbf2edba2014-03-05 10:49:32 -08001192 if (enable)
1193 rc = override_dcin_ilimit(chip, 0);
David Keitel975b5352014-01-27 14:28:04 -08001194 return rc;
1195}
1196
David Keiteld681cda2012-10-02 15:44:21 -07001197#define USB_SUSPEND_BIT BIT(0)
1198static int
1199qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
1200{
David Keitel975b5352014-01-27 14:28:04 -08001201 /* Turn off DC OVP FET when going into USB suspend */
1202 if (chip->parallel_ovp_mode && enable)
1203 switch_parallel_ovp_mode(chip, 0);
1204
David Keiteld681cda2012-10-02 15:44:21 -07001205 return qpnp_chg_masked_write(chip,
1206 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
1207 USB_SUSPEND_BIT,
1208 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -07001209}
1210
David Keitel344c6972013-04-09 19:28:21 -07001211static int
1212qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
1213{
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001214 if (chip->insertion_ocv_uv == 0 && enable) {
1215 pr_debug("Battery not present, skipping\n");
1216 return 0;
1217 }
1218 pr_debug("charging %s\n", enable ? "enabled" : "disabled");
David Keitel344c6972013-04-09 19:28:21 -07001219 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1220 CHGR_CHG_EN,
1221 enable ? CHGR_CHG_EN : 0, 1);
1222}
1223
1224static int
1225qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
1226{
1227 /* Don't run on battery for batteryless hardware */
1228 if (chip->use_default_batt_values)
1229 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -07001230 /* Don't force on battery if battery is not present */
1231 if (!qpnp_chg_is_batt_present(chip))
1232 return 0;
David Keitel344c6972013-04-09 19:28:21 -07001233
1234 /* This bit forces the charger to run off of the battery rather
1235 * than a connected charger */
1236 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1237 CHGR_ON_BAT_FORCE_BIT,
1238 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
1239}
1240
David Keitel8b68d2d2013-05-14 23:36:51 -07001241#define BUCK_DUTY_MASK_100P 0x30
1242static int
1243qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
1244{
1245 int rc;
1246
1247 pr_debug("enable: %d\n", enable);
1248
1249 rc = qpnp_chg_masked_write(chip,
1250 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1251 if (rc) {
1252 pr_debug("failed to write sec access rc=%d\n", rc);
1253 return rc;
1254 }
1255
1256 rc = qpnp_chg_masked_write(chip,
1257 chip->buck_base + BUCK_TEST_SMBC_MODES,
1258 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
1259 if (rc) {
1260 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
1261 return rc;
1262 }
1263
1264 return rc;
1265}
1266
David Keitel9fd07382013-05-02 15:37:44 -07001267#define COMPATATOR_OVERRIDE_0 0x80
1268static int
1269qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
1270{
1271 int rc;
1272
1273 pr_debug("toggle: %d\n", enable);
1274
1275 rc = qpnp_chg_masked_write(chip,
1276 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1277 if (rc) {
1278 pr_debug("failed to write sec access rc=%d\n", rc);
1279 return rc;
1280 }
1281
1282 rc = qpnp_chg_masked_write(chip,
1283 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
1284 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
1285 if (rc) {
1286 pr_debug("failed to toggle chg done override rc=%d\n", rc);
1287 return rc;
1288 }
1289
1290 return rc;
1291}
1292
1293#define QPNP_CHG_VBATDET_MIN_MV 3240
1294#define QPNP_CHG_VBATDET_MAX_MV 5780
1295#define QPNP_CHG_VBATDET_STEP_MV 20
1296static int
1297qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
1298{
1299 u8 temp;
1300
1301 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
1302 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
1303 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
1304 return -EINVAL;
1305 }
1306 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
1307 / QPNP_CHG_VBATDET_STEP_MV;
1308
1309 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
1310 return qpnp_chg_write(chip, &temp,
1311 chip->chgr_base + CHGR_VBAT_DET, 1);
1312}
1313
David Keitel344c6972013-04-09 19:28:21 -07001314static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001315qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
1316{
1317 if (chip->bat_is_cool)
1318 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
1319 - chip->resume_delta_mv);
1320 else if (chip->bat_is_warm)
1321 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
1322 - chip->resume_delta_mv);
1323 else if (chip->resuming_charging)
1324 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1325 + chip->resume_delta_mv);
1326 else
1327 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1328 - chip->resume_delta_mv);
1329}
1330
1331static void
David Keitel344c6972013-04-09 19:28:21 -07001332qpnp_arb_stop_work(struct work_struct *work)
1333{
1334 struct delayed_work *dwork = to_delayed_work(work);
1335 struct qpnp_chg_chip *chip = container_of(dwork,
1336 struct qpnp_chg_chip, arb_stop_work);
1337
David Keitel9fd07382013-05-02 15:37:44 -07001338 if (!chip->chg_done)
1339 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -07001340 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1341}
1342
1343static void
1344qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -07001345{
1346 struct qpnp_chg_chip *chip = container_of(work,
1347 struct qpnp_chg_chip, adc_measure_work);
1348
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07001349 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -07001350 pr_err("request ADC error\n");
1351}
1352
David Keitelecab15a2013-08-06 15:41:39 -07001353static void
1354qpnp_bat_if_adc_disable_work(struct work_struct *work)
1355{
1356 struct qpnp_chg_chip *chip = container_of(work,
1357 struct qpnp_chg_chip, adc_disable_work);
1358
1359 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev, &chip->adc_param);
1360}
1361
David Keitel9fd07382013-05-02 15:37:44 -07001362#define EOC_CHECK_PERIOD_MS 10000
1363static irqreturn_t
1364qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
1365{
1366 struct qpnp_chg_chip *chip = _chip;
1367 u8 chg_sts = 0;
1368 int rc;
1369
1370 pr_debug("vbatdet-lo triggered\n");
1371
1372 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
1373 if (rc)
1374 pr_err("failed to read chg_sts rc=%d\n", rc);
1375
1376 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
1377 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
1378 schedule_delayed_work(&chip->eoc_work,
1379 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001380 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07001381 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001382 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07001383
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001384 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001385 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001386 if (chip->dc_chgpth_base) {
1387 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001388 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001389 }
1390 if (chip->bat_if_base) {
1391 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001392 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001393 }
David Keitel9fd07382013-05-02 15:37:44 -07001394 return IRQ_HANDLED;
1395}
1396
David Keitel344c6972013-04-09 19:28:21 -07001397#define ARB_STOP_WORK_MS 1000
1398static irqreturn_t
1399qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
1400{
1401 struct qpnp_chg_chip *chip = _chip;
David Keitel7e38f512013-11-19 11:15:11 -08001402 u8 usb_sts;
1403 int rc;
1404
1405 rc = qpnp_chg_read(chip, &usb_sts,
1406 INT_RT_STS(chip->usb_chgpth_base), 1);
1407 if (rc)
1408 pr_err("failed to read usb_chgpth_sts rc=%d\n", rc);
David Keitel344c6972013-04-09 19:28:21 -07001409
1410 pr_debug("chg_gone triggered\n");
David Keiteld53183a2014-01-07 17:17:44 -08001411 if ((qpnp_chg_is_usb_chg_plugged_in(chip)
1412 || qpnp_chg_is_dc_chg_plugged_in(chip))
1413 && (usb_sts & CHG_GONE_IRQ)) {
David Keitelcd2e1022014-05-02 17:25:15 -07001414 if (ext_ovp_isns_present) {
1415 pr_debug("EXT OVP IC ISNS disabled due to ARB WA\n");
1416 gpio_direction_output(chip->ext_ovp_isns_gpio, 0);
1417 }
1418
David Keitel344c6972013-04-09 19:28:21 -07001419 qpnp_chg_charge_en(chip, 0);
David Keitelcd2e1022014-05-02 17:25:15 -07001420
David Keitel9fd07382013-05-02 15:37:44 -07001421 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001422 schedule_delayed_work(&chip->arb_stop_work,
1423 msecs_to_jiffies(ARB_STOP_WORK_MS));
1424 }
1425
1426 return IRQ_HANDLED;
1427}
1428
David Keitel0b62bdd2013-07-10 17:30:51 -07001429static irqreturn_t
1430qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
1431{
1432 struct qpnp_chg_chip *chip = _chip;
David Keitel0b62bdd2013-07-10 17:30:51 -07001433
1434 pr_debug("usb-ocp triggered\n");
1435
David Keitel8b9bd312014-01-15 14:44:00 -08001436 schedule_work(&chip->ocp_clear_work);
1437
1438 return IRQ_HANDLED;
1439}
1440
1441#define BOOST_ILIMIT_MIN 0x07
1442#define BOOST_ILIMIT_DEF 0x02
1443#define BOOST_ILIMT_MASK 0xFF
1444static void
1445qpnp_chg_ocp_clear_work(struct work_struct *work)
1446{
1447 int rc;
1448 u8 usb_sts;
1449 struct qpnp_chg_chip *chip = container_of(work,
1450 struct qpnp_chg_chip, ocp_clear_work);
1451
1452 if (chip->type == SMBBP) {
1453 rc = qpnp_chg_masked_write(chip,
1454 chip->boost_base + BOOST_ILIM,
1455 BOOST_ILIMT_MASK,
1456 BOOST_ILIMIT_MIN, 1);
1457 if (rc) {
1458 pr_err("Failed to turn configure ilim rc = %d\n", rc);
1459 return;
1460 }
1461 }
1462
David Keitel0b62bdd2013-07-10 17:30:51 -07001463 rc = qpnp_chg_masked_write(chip,
1464 chip->usb_chgpth_base + USB_OCP_CLR,
1465 OCP_CLR_BIT,
1466 OCP_CLR_BIT, 1);
1467 if (rc)
1468 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1469
1470 /* force usb ovp fet off */
1471 rc = qpnp_chg_masked_write(chip,
1472 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1473 USB_OTG_EN_BIT,
1474 USB_OTG_EN_BIT, 1);
1475 if (rc)
1476 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1477
David Keitel8b9bd312014-01-15 14:44:00 -08001478 if (chip->type == SMBBP) {
1479 /* Wait for OCP circuitry to be powered up */
1480 msleep(100);
1481 rc = qpnp_chg_read(chip, &usb_sts,
1482 INT_RT_STS(chip->usb_chgpth_base), 1);
1483 if (rc) {
1484 pr_err("failed to read interrupt sts %d\n", rc);
1485 return;
1486 }
1487
1488 if (usb_sts & COARSE_DET_USB_IRQ) {
1489 rc = qpnp_chg_masked_write(chip,
1490 chip->boost_base + BOOST_ILIM,
1491 BOOST_ILIMT_MASK,
1492 BOOST_ILIMIT_DEF, 1);
1493 if (rc) {
1494 pr_err("Failed to set ilim rc = %d\n", rc);
1495 return;
1496 }
1497 } else {
1498 pr_warn_ratelimited("USB short to GND detected!\n");
1499 }
1500 }
David Keitel0b62bdd2013-07-10 17:30:51 -07001501}
1502
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001503#define QPNP_CHG_VDDMAX_MIN 3400
1504#define QPNP_CHG_V_MIN_MV 3240
1505#define QPNP_CHG_V_MAX_MV 4500
1506#define QPNP_CHG_V_STEP_MV 10
1507#define QPNP_CHG_BUCK_TRIM1_STEP 10
1508#define QPNP_CHG_BUCK_VDD_TRIM_MASK 0xF0
1509static int
1510qpnp_chg_vddmax_and_trim_set(struct qpnp_chg_chip *chip,
1511 int voltage, int trim_mv)
1512{
1513 int rc, trim_set;
1514 u8 vddmax = 0, trim = 0;
1515
1516 if (voltage < QPNP_CHG_VDDMAX_MIN
1517 || voltage > QPNP_CHG_V_MAX_MV) {
1518 pr_err("bad mV=%d asked to set\n", voltage);
1519 return -EINVAL;
1520 }
1521
1522 vddmax = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1523 rc = qpnp_chg_write(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1524 if (rc) {
1525 pr_err("Failed to write vddmax: %d\n", rc);
1526 return rc;
1527 }
1528
1529 rc = qpnp_chg_masked_write(chip,
1530 chip->buck_base + SEC_ACCESS,
1531 0xFF,
1532 0xA5, 1);
1533 if (rc) {
1534 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1535 return rc;
1536 }
1537 trim_set = clamp((int)chip->trim_center
1538 + (trim_mv / QPNP_CHG_BUCK_TRIM1_STEP),
1539 0, 0xF);
1540 trim = (u8)trim_set << 4;
1541 rc = qpnp_chg_masked_write(chip,
1542 chip->buck_base + BUCK_CTRL_TRIM1,
1543 QPNP_CHG_BUCK_VDD_TRIM_MASK,
1544 trim, 1);
1545 if (rc) {
1546 pr_err("Failed to write buck trim1: %d\n", rc);
1547 return rc;
1548 }
1549 pr_debug("voltage=%d+%d setting vddmax: %02x, trim: %02x\n",
1550 voltage, trim_mv, vddmax, trim);
1551 return 0;
1552}
1553
Xiaozhe Shie8504482013-10-30 18:10:31 -07001554static int
1555qpnp_chg_vddmax_get(struct qpnp_chg_chip *chip)
1556{
1557 int rc;
1558 u8 vddmax = 0;
1559
1560 rc = qpnp_chg_read(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1561 if (rc) {
1562 pr_err("Failed to write vddmax: %d\n", rc);
1563 return rc;
1564 }
1565
1566 return QPNP_CHG_V_MIN_MV + (int)vddmax * QPNP_CHG_V_STEP_MV;
1567}
1568
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001569/* JEITA compliance logic */
1570static void
1571qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1572{
1573 if (chip->bat_is_cool)
1574 qpnp_chg_vddmax_and_trim_set(chip, chip->cool_bat_mv,
1575 chip->delta_vddmax_mv);
1576 else if (chip->bat_is_warm)
1577 qpnp_chg_vddmax_and_trim_set(chip, chip->warm_bat_mv,
1578 chip->delta_vddmax_mv);
1579 else
1580 qpnp_chg_vddmax_and_trim_set(chip, chip->max_voltage_mv,
1581 chip->delta_vddmax_mv);
1582}
1583
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001584static void
1585qpnp_usbin_health_check_work(struct work_struct *work)
1586{
1587 int usbin_health = 0;
1588 u8 psy_health_sts = 0;
1589 struct delayed_work *dwork = to_delayed_work(work);
1590 struct qpnp_chg_chip *chip = container_of(dwork,
1591 struct qpnp_chg_chip, usbin_health_check);
1592
1593 usbin_health = qpnp_chg_check_usbin_health(chip);
1594 spin_lock(&chip->usbin_health_monitor_lock);
1595 if (chip->usbin_health != usbin_health) {
1596 pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
1597 chip->usbin_health, usbin_health);
1598 chip->usbin_health = usbin_health;
1599 if (usbin_health == USBIN_OVP)
1600 psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1601 else if (usbin_health == USBIN_OK)
1602 psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
1603 power_supply_set_health_state(chip->usb_psy, psy_health_sts);
1604 power_supply_changed(chip->usb_psy);
1605 }
1606 /* enable OVP monitor in usb valid after coarse-det complete */
1607 chip->usb_valid_check_ovp = true;
1608 spin_unlock(&chip->usbin_health_monitor_lock);
1609 return;
1610}
1611
1612#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
1613#define USB_DEB_BYPASS 0x0
1614#define USB_DEB_5MS 0x1
1615#define USB_DEB_10MS 0x2
1616#define USB_DEB_20MS 0x3
1617static irqreturn_t
1618qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
1619{
1620 struct qpnp_chg_chip *chip = _chip;
1621 int host_mode, rc = 0;
1622 int debounce[] = {
1623 [USB_DEB_BYPASS] = 0,
1624 [USB_DEB_5MS] = 5,
1625 [USB_DEB_10MS] = 10,
1626 [USB_DEB_20MS] = 20 };
1627 u8 ovp_ctl;
1628 bool usb_coarse_det;
1629
1630 host_mode = qpnp_chg_is_otg_en_set(chip);
1631 usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
1632 pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
1633 usb_coarse_det, host_mode);
1634
1635 if (host_mode)
1636 return IRQ_HANDLED;
1637 /* ignore to monitor OVP in usbin valid irq handler
1638 if the coarse-det fired first, do the OVP state monitor
1639 in the usbin_health_check work, and after the work,
1640 enable monitor OVP in usbin valid irq handler */
1641 chip->usb_valid_check_ovp = false;
1642 if (chip->usb_coarse_det ^ usb_coarse_det) {
1643 chip->usb_coarse_det = usb_coarse_det;
1644 if (usb_coarse_det) {
1645 /* usb coarse-det rising edge, check the usbin_valid
1646 debounce time setting, and start a delay work to
1647 check the OVP status*/
1648 rc = qpnp_chg_read(chip, &ovp_ctl,
1649 chip->usb_chgpth_base + USB_OVP_CTL, 1);
1650
1651 if (rc) {
1652 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1653 chip->usb_chgpth_base + USB_OVP_CTL,
1654 rc);
1655 return rc;
1656 }
1657 ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
1658 schedule_delayed_work(&chip->usbin_health_check,
1659 msecs_to_jiffies(debounce[ovp_ctl]));
1660 } else {
1661 /* usb coarse-det rising edge, set the usb psy health
1662 status to unknown */
1663 pr_debug("usb coarse det clear, set usb health to unknown\n");
1664 chip->usbin_health = USBIN_UNKNOW;
1665 power_supply_set_health_state(chip->usb_psy,
1666 POWER_SUPPLY_HEALTH_UNKNOWN);
1667 power_supply_changed(chip->usb_psy);
1668 }
1669
1670 }
1671 return IRQ_HANDLED;
1672}
1673
David Keitel6e63bd52013-09-06 18:00:03 -07001674#define BATFET_LPM_MASK 0xC0
1675#define BATFET_LPM 0x40
1676#define BATFET_NO_LPM 0x00
1677static int
1678qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
1679{
1680 int rc = 0;
1681
David Keitelcadbc282013-09-26 11:39:14 -07001682 if (chip->charging_disabled || !chip->bat_if_base)
1683 return rc;
1684
David Keitel6e63bd52013-09-06 18:00:03 -07001685 if (chip->type == SMBB)
1686 rc = qpnp_chg_masked_write(chip,
1687 chip->bat_if_base + CHGR_BAT_IF_SPARE,
1688 BATFET_LPM_MASK,
1689 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1690 else
1691 rc = qpnp_chg_masked_write(chip,
1692 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
1693 BATFET_LPM_MASK,
1694 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1695
1696 return rc;
1697}
1698
David Keitel820a90d2014-03-25 18:18:04 -07001699#define USB_WALL_THRESHOLD_MA 500
David Keitel80668952012-07-27 14:25:49 -07001700#define ENUM_T_STOP_BIT BIT(0)
David Keitel820a90d2014-03-25 18:18:04 -07001701#define USB_5V_UV 5000000
1702#define USB_9V_UV 9000000
David Keitel80668952012-07-27 14:25:49 -07001703static irqreturn_t
1704qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1705{
1706 struct qpnp_chg_chip *chip = _chip;
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001707 int usb_present, host_mode, usbin_health;
1708 u8 psy_health_sts;
David Keitel80668952012-07-27 14:25:49 -07001709
1710 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001711 host_mode = qpnp_chg_is_otg_en_set(chip);
1712 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1713 usb_present, host_mode);
1714
1715 /* In host mode notifications cmoe from USB supply */
1716 if (host_mode)
1717 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001718
1719 if (chip->usb_present ^ usb_present) {
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07001720 chip->aicl_settled = false;
David Keitel80668952012-07-27 14:25:49 -07001721 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001722 if (!usb_present) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001723 /* when a valid charger inserted, and increase the
1724 * charger voltage to OVP threshold, then
1725 * usb_in_valid falling edge interrupt triggers.
1726 * So we handle the OVP monitor here, and ignore
1727 * other health state changes */
1728 if (chip->ovp_monitor_enable &&
1729 (chip->usb_valid_check_ovp)) {
1730 usbin_health =
1731 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001732 if ((chip->usbin_health != usbin_health)
1733 && (usbin_health == USBIN_OVP)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001734 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001735 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001736 POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1737 power_supply_set_health_state(
1738 chip->usb_psy,
1739 psy_health_sts);
1740 power_supply_changed(chip->usb_psy);
1741 }
1742 }
Xiaozhe Shi9e887be2014-05-21 15:18:58 -07001743 if (!qpnp_chg_is_dc_chg_plugged_in(chip))
David Keitel6e63bd52013-09-06 18:00:03 -07001744 chip->chg_done = false;
David Keitel820a90d2014-03-25 18:18:04 -07001745
1746 if (!qpnp_is_dc_higher_prio(chip))
1747 qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
1748
David Keitela9185602013-11-12 17:55:48 -08001749 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel7b0568482013-12-02 14:47:42 -08001750 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelcd2e1022014-05-02 17:25:15 -07001751 qpnp_chg_iusb_trim_set(chip, chip->usb_trim_default);
David Keitelfd305ee2013-07-19 20:19:06 -07001752 chip->prev_usb_max_ma = -EINVAL;
David Keitel9fd07382013-05-02 15:37:44 -07001753 } else {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001754 /* when OVP clamped usbin, and then decrease
1755 * the charger voltage to lower than the OVP
1756 * threshold, a usbin_valid rising edge
1757 * interrupt triggered. So we change the usb
1758 * psy health state back to good */
1759 if (chip->ovp_monitor_enable &&
1760 (chip->usb_valid_check_ovp)) {
1761 usbin_health =
1762 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001763 if ((chip->usbin_health != usbin_health)
1764 && (usbin_health == USBIN_OK)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001765 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001766 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001767 POWER_SUPPLY_HEALTH_GOOD;
1768 power_supply_set_health_state(
1769 chip->usb_psy,
1770 psy_health_sts);
1771 power_supply_changed(chip->usb_psy);
1772 }
1773 }
1774
David Keitel9fd07382013-05-02 15:37:44 -07001775 schedule_delayed_work(&chip->eoc_work,
1776 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001777 schedule_work(&chip->soc_check_work);
David Keitel9fd07382013-05-02 15:37:44 -07001778 }
David Keitel344c6972013-04-09 19:28:21 -07001779
David Keitel9fd07382013-05-02 15:37:44 -07001780 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel6e63bd52013-09-06 18:00:03 -07001781 schedule_work(&chip->batfet_lcl_work);
David Keitel80668952012-07-27 14:25:49 -07001782 }
1783
1784 return IRQ_HANDLED;
1785}
1786
Fenglin Wuc64e9942014-08-22 13:47:34 +08001787#define BUCK_VIN_LOOP_CMP_OVRD_MASK 0x30
1788static int
1789qpnp_chg_bypass_vchg_loop_debouncer(struct qpnp_chg_chip *chip, bool bypass)
1790{
1791 int rc;
1792 u8 value = bypass ? 0x10 : 0;
1793
1794 pr_debug("bypass vchg_loop debouncer: %d\n", bypass);
1795
1796 rc = qpnp_chg_masked_write(chip, chip->buck_base + SEC_ACCESS,
1797 0xFF, 0xA5, 1);
1798 if (rc) {
1799 pr_err("failed to write SEC_ACCESS register, rc = %d\n", rc);
1800 return rc;
1801 }
1802
1803 rc = qpnp_chg_masked_write(chip,
1804 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_2,
1805 BUCK_VIN_LOOP_CMP_OVRD_MASK, value, 1);
1806 if (rc)
1807 pr_err("failed to write BUCK_COMP_OVRIDE_2, rc = %d\n", rc);
1808
1809 return rc;
1810}
1811
1812static int
1813qpnp_chg_vchg_loop_debouncer_setting_get(struct qpnp_chg_chip *chip)
1814{
1815 int rc;
1816 u8 value;
1817
1818 rc = qpnp_chg_read(chip, &value,
1819 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_2, 1);
1820 if (rc) {
1821 pr_err("failed to read BUCK_CMP_OVERIDE_2, rc = %d\n", rc);
1822 return 0;
1823 }
1824
1825 return value & BUCK_VIN_LOOP_CMP_OVRD_MASK;
1826}
1827
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001828#define TEST_EN_SMBC_LOOP 0xE5
1829#define IBAT_REGULATION_DISABLE BIT(2)
David Keitel7450dcd2013-01-29 18:41:41 -08001830static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001831qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1832{
1833 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001834 int batt_temp_good, batt_present, rc;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001835
1836 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1837 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1838
Xiaozhe Shi87831862014-01-20 17:44:40 -08001839 batt_present = qpnp_chg_is_batt_present(chip);
1840 if (batt_present) {
1841 rc = qpnp_chg_masked_write(chip,
1842 chip->buck_base + SEC_ACCESS,
1843 0xFF,
1844 0xA5, 1);
1845 if (rc) {
1846 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1847 return rc;
1848 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001849
Xiaozhe Shi87831862014-01-20 17:44:40 -08001850 rc = qpnp_chg_masked_write(chip,
1851 chip->buck_base + TEST_EN_SMBC_LOOP,
1852 IBAT_REGULATION_DISABLE,
1853 batt_temp_good ? 0 : IBAT_REGULATION_DISABLE, 1);
1854 if (rc) {
1855 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1856 return rc;
1857 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001858 }
1859
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001860 pr_debug("psy changed batt_psy\n");
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001861 power_supply_changed(&chip->batt_psy);
1862 return IRQ_HANDLED;
1863}
1864
1865static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001866qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1867{
1868 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001869 int batt_present, batt_temp_good, rc;
David Keitel42ae0aa2013-03-08 16:20:10 -08001870
1871 batt_present = qpnp_chg_is_batt_present(chip);
1872 pr_debug("batt-pres triggered: %d\n", batt_present);
1873
1874 if (chip->batt_present ^ batt_present) {
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001875 if (batt_present) {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001876 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1877 rc = qpnp_chg_masked_write(chip,
1878 chip->buck_base + SEC_ACCESS,
1879 0xFF,
1880 0xA5, 1);
1881 if (rc) {
1882 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1883 return rc;
1884 }
1885
1886 rc = qpnp_chg_masked_write(chip,
1887 chip->buck_base + TEST_EN_SMBC_LOOP,
1888 IBAT_REGULATION_DISABLE,
1889 batt_temp_good
1890 ? 0 : IBAT_REGULATION_DISABLE, 1);
1891 if (rc) {
1892 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1893 return rc;
1894 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001895 schedule_work(&chip->insertion_ocv_work);
1896 } else {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001897 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 0, 1);
1910 if (rc) {
1911 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1912 return rc;
1913 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001914 chip->insertion_ocv_uv = 0;
1915 qpnp_chg_charge_en(chip, 0);
1916 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001917 chip->batt_present = batt_present;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001918 pr_debug("psy changed batt_psy\n");
David Keitel42ae0aa2013-03-08 16:20:10 -08001919 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001920 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001921 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001922
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001923 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07001924 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001925 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001926 schedule_work(&chip->adc_measure_work);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001927 } else if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitelec3c09802013-06-13 13:05:30 -07001928 && !batt_present) {
David Keitelecab15a2013-08-06 15:41:39 -07001929 schedule_work(&chip->adc_disable_work);
David Keitelec3c09802013-06-13 13:05:30 -07001930 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001931 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001932 }
1933
1934 return IRQ_HANDLED;
1935}
1936
1937static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001938qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1939{
1940 struct qpnp_chg_chip *chip = _chip;
1941 int dc_present;
1942
1943 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1944 pr_debug("dcin-valid triggered: %d\n", dc_present);
1945
1946 if (chip->dc_present ^ dc_present) {
1947 chip->dc_present = dc_present;
David Keitel6d4b9da2013-09-05 17:38:40 -07001948 if (qpnp_chg_is_otg_en_set(chip))
1949 qpnp_chg_force_run_on_batt(chip, !dc_present ? 1 : 0);
David Keitel86628cc2014-06-09 13:24:00 -07001950 if (!dc_present && (!qpnp_chg_is_usb_chg_plugged_in(chip) ||
1951 qpnp_chg_is_otg_en_set(chip))) {
David Keitel9fd07382013-05-02 15:37:44 -07001952 chip->chg_done = false;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001953 } else {
David Keitel9fd07382013-05-02 15:37:44 -07001954 schedule_delayed_work(&chip->eoc_work,
1955 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001956 schedule_work(&chip->soc_check_work);
1957 }
David Keitel820a90d2014-03-25 18:18:04 -07001958
1959 if (qpnp_is_dc_higher_prio(chip)) {
1960 pr_debug("dc has higher priority\n");
1961 if (dc_present) {
1962 qpnp_chg_iusbmax_set(chip,
1963 QPNP_CHG_I_MAX_MIN_100);
1964 power_supply_set_voltage_limit(chip->usb_psy,
1965 USB_5V_UV);
1966 } else {
1967 chip->aicl_settled = false;
1968 qpnp_chg_iusbmax_set(chip,
1969 USB_WALL_THRESHOLD_MA);
1970 power_supply_set_voltage_limit(chip->usb_psy,
1971 USB_9V_UV);
1972 }
1973 }
1974
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001975 pr_debug("psy changed dc_psy\n");
David Keitel7450dcd2013-01-29 18:41:41 -08001976 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001977 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001978 power_supply_changed(&chip->batt_psy);
David Keitel6e63bd52013-09-06 18:00:03 -07001979 schedule_work(&chip->batfet_lcl_work);
David Keitel7450dcd2013-01-29 18:41:41 -08001980 }
1981
1982 return IRQ_HANDLED;
1983}
1984
David Keitel80668952012-07-27 14:25:49 -07001985#define CHGR_CHG_FAILED_BIT BIT(7)
1986static irqreturn_t
1987qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1988{
1989 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001990 int rc;
David Keitel80668952012-07-27 14:25:49 -07001991
David Keitel9fd07382013-05-02 15:37:44 -07001992 pr_debug("chg_failed triggered\n");
1993
David Keitel80668952012-07-27 14:25:49 -07001994 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001995 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001996 CHGR_CHG_FAILED_BIT,
1997 CHGR_CHG_FAILED_BIT, 1);
1998 if (rc)
1999 pr_err("Failed to write chg_fail clear bit!\n");
2000
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002001 if (chip->bat_if_base) {
2002 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002003 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002004 }
2005 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07002006 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002007 if (chip->dc_chgpth_base) {
2008 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002009 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002010 }
David Keitel80668952012-07-27 14:25:49 -07002011 return IRQ_HANDLED;
2012}
2013
2014static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08002015qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
2016{
2017 struct qpnp_chg_chip *chip = _chip;
2018
2019 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08002020
2021 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002022 if (chip->bat_if_base) {
2023 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002024 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002025 }
David Keitel42ae0aa2013-03-08 16:20:10 -08002026
2027 return IRQ_HANDLED;
2028}
2029
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002030static int qpnp_chg_is_fastchg_on(struct qpnp_chg_chip *chip)
David Keitel42ae0aa2013-03-08 16:20:10 -08002031{
David Keitel337bd862013-07-15 21:42:58 -07002032 u8 chgr_sts;
2033 int rc;
2034
David Keitelbf6a1062014-01-23 10:57:36 -08002035 qpnp_chg_irq_wake_disable(&chip->chg_fastchg);
2036
David Keitel337bd862013-07-15 21:42:58 -07002037 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002038 if (rc) {
2039 pr_err("failed to read interrupt status %d\n", rc);
2040 return rc;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002041 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002042 pr_debug("chgr_sts 0x%x\n", chgr_sts);
2043 return (chgr_sts & FAST_CHG_ON_IRQ) ? 1 : 0;
2044}
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002045
David Keitel59fbb762014-02-05 16:46:24 -08002046#define VBATDET_BYPASS 0x01
2047static int
2048bypass_vbatdet_comp(struct qpnp_chg_chip *chip, bool bypass)
2049{
2050 int rc;
2051
2052 pr_debug("bypass %d\n", bypass);
2053 rc = qpnp_chg_masked_write(chip,
2054 chip->chgr_base + SEC_ACCESS,
2055 0xA5,
2056 0xA5, 1);
2057 rc |= qpnp_chg_masked_write(chip,
2058 chip->chgr_base + CHGR_COMP_OVR1,
2059 0xFF,
2060 bypass ? VBATDET_BYPASS : 0, 1);
2061 if (rc) {
2062 pr_err("Failed to bypass vbatdet comp rc = %d\n", rc);
2063 return rc;
2064 }
2065
2066 return rc;
2067}
2068
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002069static irqreturn_t
2070qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
2071{
2072 struct qpnp_chg_chip *chip = _chip;
2073 bool fastchg_on = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002074
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002075 fastchg_on = qpnp_chg_is_fastchg_on(chip);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002076
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002077 pr_debug("FAST_CHG IRQ triggered, fastchg_on: %d\n", fastchg_on);
David Keitel337bd862013-07-15 21:42:58 -07002078
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002079 if (chip->fastchg_on ^ fastchg_on) {
2080 chip->fastchg_on = fastchg_on;
2081 if (chip->bat_if_base) {
2082 pr_debug("psy changed batt_psy\n");
2083 power_supply_changed(&chip->batt_psy);
2084 }
2085
2086 pr_debug("psy changed usb_psy\n");
2087 power_supply_changed(chip->usb_psy);
2088
2089 if (chip->dc_chgpth_base) {
2090 pr_debug("psy changed dc_psy\n");
2091 power_supply_changed(&chip->dc_psy);
2092 }
2093
2094 if (fastchg_on) {
2095 chip->chg_done = false;
David Keitel59fbb762014-02-05 16:46:24 -08002096 bypass_vbatdet_comp(chip, 1);
2097 if (chip->bat_is_warm || chip->bat_is_cool) {
2098 qpnp_chg_set_appropriate_vddmax(chip);
2099 qpnp_chg_set_appropriate_battery_current(chip);
2100 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002101
2102 if (chip->resuming_charging) {
2103 chip->resuming_charging = false;
2104 qpnp_chg_set_appropriate_vbatdet(chip);
2105 }
2106
2107 if (!chip->charging_disabled) {
2108 schedule_delayed_work(&chip->eoc_work,
2109 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2110 pm_stay_awake(chip->dev);
2111 }
David Keitel975b5352014-01-27 14:28:04 -08002112 if (chip->parallel_ovp_mode)
2113 switch_parallel_ovp_mode(chip, 1);
David Keitelcd2e1022014-05-02 17:25:15 -07002114
2115 if (ext_ovp_isns_present &&
2116 chip->ext_ovp_ic_gpio_enabled) {
2117 pr_debug("EXT OVP IC ISNS enabled\n");
2118 gpio_direction_output(
2119 chip->ext_ovp_isns_gpio, 1);
2120 }
David Keitel975b5352014-01-27 14:28:04 -08002121 } else {
2122 if (chip->parallel_ovp_mode)
2123 switch_parallel_ovp_mode(chip, 0);
David Keitel59fbb762014-02-05 16:46:24 -08002124 if (!chip->bat_is_warm && !chip->bat_is_cool)
2125 bypass_vbatdet_comp(chip, 0);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002126 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002127 }
2128
David Keitel47185a62013-05-15 18:54:10 -07002129 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -08002130
2131 return IRQ_HANDLED;
2132}
2133
David Keitel03ee6b52012-10-22 12:25:19 -07002134static int
David Keitel432e1232013-06-05 16:10:18 -07002135qpnp_dc_property_is_writeable(struct power_supply *psy,
2136 enum power_supply_property psp)
2137{
2138 switch (psp) {
2139 case POWER_SUPPLY_PROP_CURRENT_MAX:
2140 return 1;
2141 default:
2142 break;
2143 }
2144
2145 return 0;
2146}
2147
2148static int
David Keitel03ee6b52012-10-22 12:25:19 -07002149qpnp_batt_property_is_writeable(struct power_supply *psy,
2150 enum power_supply_property psp)
2151{
2152 switch (psp) {
2153 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08002154 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07002155 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel2586f0a2013-08-20 10:02:26 -07002156 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002157 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
Fenglin Wuc64e9942014-08-22 13:47:34 +08002158 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
David Keitel337bd862013-07-15 21:42:58 -07002159 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07002160 case POWER_SUPPLY_PROP_COOL_TEMP:
2161 case POWER_SUPPLY_PROP_WARM_TEMP:
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002162 case POWER_SUPPLY_PROP_CAPACITY:
David Keitel03ee6b52012-10-22 12:25:19 -07002163 return 1;
2164 default:
2165 break;
2166 }
2167
2168 return 0;
2169}
2170
David Keitel6f865cd2012-11-30 15:04:32 -08002171static int
David Keitelbe208252013-01-31 14:49:25 -08002172qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
2173{
2174 int rc;
2175
2176 if (chip->charging_disabled && enable) {
2177 pr_debug("Charging disabled\n");
2178 return 0;
2179 }
2180
2181 rc = qpnp_chg_charge_en(chip, enable);
2182 if (rc) {
2183 pr_err("Failed to control charging %d\n", rc);
2184 return rc;
2185 }
2186
2187 rc = qpnp_chg_force_run_on_batt(chip, !enable);
2188 if (rc)
2189 pr_err("Failed to control charging %d\n", rc);
2190
2191 return rc;
2192}
2193
David Keitel454ee842013-03-08 16:19:11 -08002194static int
2195switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002196{
2197 int rc;
2198
2199 pr_debug("switch to charge mode\n");
2200 if (!qpnp_chg_is_otg_en_set(chip))
2201 return 0;
2202
David Keitel8b9bd312014-01-15 14:44:00 -08002203 if (chip->type == SMBBP) {
2204 rc = qpnp_chg_masked_write(chip,
2205 chip->boost_base + BOOST_ILIM,
2206 BOOST_ILIMT_MASK,
2207 BOOST_ILIMIT_DEF, 1);
2208 if (rc) {
2209 pr_err("Failed to set ilim rc = %d\n", rc);
2210 return rc;
2211 }
2212 }
2213
David Keitel6f865cd2012-11-30 15:04:32 -08002214 /* enable usb ovp fet */
2215 rc = qpnp_chg_masked_write(chip,
2216 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2217 USB_OTG_EN_BIT,
2218 0, 1);
2219 if (rc) {
2220 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
2221 return rc;
2222 }
2223
2224 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2225 if (rc) {
2226 pr_err("Failed re-enable charging rc = %d\n", rc);
2227 return rc;
2228 }
2229
2230 return 0;
2231}
2232
David Keitel454ee842013-03-08 16:19:11 -08002233static int
2234switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002235{
2236 int rc;
David Keitel8b9bd312014-01-15 14:44:00 -08002237 u8 usb_sts;
David Keitel6f865cd2012-11-30 15:04:32 -08002238
2239 pr_debug("switch to host mode\n");
2240 if (qpnp_chg_is_otg_en_set(chip))
2241 return 0;
2242
David Keitel975b5352014-01-27 14:28:04 -08002243 if (chip->parallel_ovp_mode)
2244 switch_parallel_ovp_mode(chip, 0);
2245
David Keitel8b9bd312014-01-15 14:44:00 -08002246 if (chip->type == SMBBP) {
2247 rc = qpnp_chg_masked_write(chip,
2248 chip->boost_base + BOOST_ILIM,
2249 BOOST_ILIMT_MASK,
2250 BOOST_ILIMIT_MIN, 1);
2251 if (rc) {
2252 pr_err("Failed to turn configure ilim rc = %d\n", rc);
2253 return rc;
2254 }
2255 }
2256
David Keitel6d4b9da2013-09-05 17:38:40 -07002257 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
2258 rc = qpnp_chg_force_run_on_batt(chip, 1);
2259 if (rc) {
2260 pr_err("Failed to disable charging rc = %d\n", rc);
2261 return rc;
2262 }
David Keitel6f865cd2012-11-30 15:04:32 -08002263 }
2264
2265 /* force usb ovp fet off */
2266 rc = qpnp_chg_masked_write(chip,
2267 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2268 USB_OTG_EN_BIT,
2269 USB_OTG_EN_BIT, 1);
2270 if (rc) {
2271 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
2272 return rc;
2273 }
2274
David Keitel8b9bd312014-01-15 14:44:00 -08002275 if (chip->type == SMBBP) {
2276 /* Wait for OCP circuitry to be powered up */
2277 msleep(100);
2278 rc = qpnp_chg_read(chip, &usb_sts,
2279 INT_RT_STS(chip->usb_chgpth_base), 1);
2280 if (rc) {
2281 pr_err("failed to read interrupt sts %d\n", rc);
2282 return rc;
2283 }
2284
2285 if (usb_sts & COARSE_DET_USB_IRQ) {
2286 rc = qpnp_chg_masked_write(chip,
2287 chip->boost_base + BOOST_ILIM,
2288 BOOST_ILIMT_MASK,
2289 BOOST_ILIMIT_DEF, 1);
2290 if (rc) {
2291 pr_err("Failed to set ilim rc = %d\n", rc);
2292 return rc;
2293 }
2294 } else {
2295 pr_warn_ratelimited("USB short to GND detected!\n");
2296 }
2297 }
2298
David Keitel6f865cd2012-11-30 15:04:32 -08002299 return 0;
2300}
2301
David Keitel80668952012-07-27 14:25:49 -07002302static enum power_supply_property pm_power_props_mains[] = {
2303 POWER_SUPPLY_PROP_PRESENT,
2304 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07002305 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07002306};
2307
2308static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07002309 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07002310 POWER_SUPPLY_PROP_STATUS,
2311 POWER_SUPPLY_PROP_CHARGE_TYPE,
2312 POWER_SUPPLY_PROP_HEALTH,
2313 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002314 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07002315 POWER_SUPPLY_PROP_TECHNOLOGY,
2316 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
2317 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
2318 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2319 POWER_SUPPLY_PROP_CAPACITY,
2320 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07002321 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
David Keitel2586f0a2013-08-20 10:02:26 -07002322 POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002323 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
Fenglin Wuc64e9942014-08-22 13:47:34 +08002324 POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS,
David Keitel337bd862013-07-15 21:42:58 -07002325 POWER_SUPPLY_PROP_VOLTAGE_MIN,
2326 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07002327 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302328 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07002329 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07002330 POWER_SUPPLY_PROP_COOL_TEMP,
2331 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08002332 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302333 POWER_SUPPLY_PROP_CYCLE_COUNT,
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002334 POWER_SUPPLY_PROP_VOLTAGE_OCV,
David Keitel80668952012-07-27 14:25:49 -07002335};
2336
2337static char *pm_power_supplied_to[] = {
2338 "battery",
2339};
2340
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07002341static char *pm_batt_supplied_to[] = {
2342 "bms",
2343};
2344
David Keitel337bd862013-07-15 21:42:58 -07002345static int charger_monitor;
2346module_param(charger_monitor, int, 0644);
2347
David Keitel2586f0a2013-08-20 10:02:26 -07002348static int ext_ovp_present;
2349module_param(ext_ovp_present, int, 0444);
2350
David Keitelcd2e1022014-05-02 17:25:15 -07002351#define OVP_USB_WALL_TRSH_MA 200
David Keitel80668952012-07-27 14:25:49 -07002352static int
2353qpnp_power_get_property_mains(struct power_supply *psy,
2354 enum power_supply_property psp,
2355 union power_supply_propval *val)
2356{
2357 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2358 dc_psy);
2359
2360 switch (psp) {
2361 case POWER_SUPPLY_PROP_PRESENT:
2362 case POWER_SUPPLY_PROP_ONLINE:
2363 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07002364 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07002365 return 0;
2366
2367 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
2368 break;
David Keitel432e1232013-06-05 16:10:18 -07002369 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07002370 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07002371 break;
David Keitel80668952012-07-27 14:25:49 -07002372 default:
2373 return -EINVAL;
2374 }
2375 return 0;
2376}
2377
David Keitel7ac385e2013-08-19 18:02:40 -07002378static void
2379qpnp_aicl_check_work(struct work_struct *work)
2380{
2381 struct delayed_work *dwork = to_delayed_work(work);
2382 struct qpnp_chg_chip *chip = container_of(dwork,
2383 struct qpnp_chg_chip, aicl_check_work);
2384 union power_supply_propval ret = {0,};
2385
2386 if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
2387 chip->usb_psy->get_property(chip->usb_psy,
2388 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
2389 if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
2390 pr_debug("no charger_monitor present set iusbmax %d\n",
2391 ret.intval / 1000);
2392 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2393 }
2394 } else {
2395 pr_debug("charger_monitor is present\n");
2396 }
2397 chip->charger_monitor_checked = true;
2398}
2399
David Keitel80668952012-07-27 14:25:49 -07002400static int
2401get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
2402{
2403 int rc = 0;
2404 struct qpnp_vadc_result results;
2405
David Keitelfe51cb92013-04-02 19:42:58 -07002406 if (chip->revision == 0 && chip->type == SMBB) {
2407 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
2408 return 0;
2409 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002410 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07002411 if (rc) {
2412 pr_err("Unable to read vbat rc=%d\n", rc);
2413 return 0;
2414 }
2415 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07002416 }
2417}
2418
2419#define BATT_PRES_BIT BIT(7)
2420static int
2421get_prop_batt_present(struct qpnp_chg_chip *chip)
2422{
2423 u8 batt_present;
2424 int rc;
2425
2426 rc = qpnp_chg_read(chip, &batt_present,
2427 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
2428 if (rc) {
2429 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
2430 return 0;
2431 };
2432 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
2433}
2434
2435#define BATT_TEMP_HOT BIT(6)
2436#define BATT_TEMP_OK BIT(7)
2437static int
2438get_prop_batt_health(struct qpnp_chg_chip *chip)
2439{
2440 u8 batt_health;
2441 int rc;
2442
2443 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07002444 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07002445 if (rc) {
2446 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
2447 return POWER_SUPPLY_HEALTH_UNKNOWN;
2448 };
2449
2450 if (BATT_TEMP_OK & batt_health)
2451 return POWER_SUPPLY_HEALTH_GOOD;
2452 if (BATT_TEMP_HOT & batt_health)
2453 return POWER_SUPPLY_HEALTH_OVERHEAT;
2454 else
2455 return POWER_SUPPLY_HEALTH_COLD;
2456}
2457
2458static int
2459get_prop_charge_type(struct qpnp_chg_chip *chip)
2460{
2461 int rc;
2462 u8 chgr_sts;
2463
2464 if (!get_prop_batt_present(chip))
2465 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2466
2467 rc = qpnp_chg_read(chip, &chgr_sts,
2468 INT_RT_STS(chip->chgr_base), 1);
2469 if (rc) {
2470 pr_err("failed to read interrupt sts %d\n", rc);
2471 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2472 }
2473
2474 if (chgr_sts & TRKL_CHG_ON_IRQ)
2475 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
2476 if (chgr_sts & FAST_CHG_ON_IRQ)
2477 return POWER_SUPPLY_CHARGE_TYPE_FAST;
2478
2479 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2480}
2481
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002482#define DEFAULT_CAPACITY 50
2483static int
2484get_batt_capacity(struct qpnp_chg_chip *chip)
2485{
2486 union power_supply_propval ret = {0,};
2487
2488 if (chip->fake_battery_soc >= 0)
2489 return chip->fake_battery_soc;
2490 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2491 return DEFAULT_CAPACITY;
2492 if (chip->bms_psy) {
2493 chip->bms_psy->get_property(chip->bms_psy,
2494 POWER_SUPPLY_PROP_CAPACITY, &ret);
2495 return ret.intval;
2496 }
2497 return DEFAULT_CAPACITY;
2498}
2499
David Keitel80668952012-07-27 14:25:49 -07002500static int
2501get_prop_batt_status(struct qpnp_chg_chip *chip)
2502{
2503 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002504 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07002505
David Keitel9fd07382013-05-02 15:37:44 -07002506 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07002507 if (rc) {
2508 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08002509 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07002510 }
2511
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002512 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
2513 if (rc) {
2514 pr_err("failed to read bat_if sts %d\n", rc);
2515 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2516 }
2517
David Keitela8099ff2014-01-06 11:31:40 -08002518 if ((chgr_sts & TRKL_CHG_ON_IRQ) && !(bat_if_sts & BAT_FET_ON_IRQ))
David Keitel80668952012-07-27 14:25:49 -07002519 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002520 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07002521 return POWER_SUPPLY_STATUS_CHARGING;
2522
Chunmei Caib3999b22014-07-11 15:38:13 +08002523 /*
2524 * Report full if state of charge is 100 or chg_done is true
2525 * when a charger is connected and boost is disabled
2526 */
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002527 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
Chunmei Caib3999b22014-07-11 15:38:13 +08002528 qpnp_chg_is_dc_chg_plugged_in(chip)) &&
2529 (chip->chg_done || get_batt_capacity(chip) == 100)
2530 && qpnp_chg_is_boost_en_set(chip) == 0) {
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002531 return POWER_SUPPLY_STATUS_FULL;
2532 }
2533
David Keitel80668952012-07-27 14:25:49 -07002534 return POWER_SUPPLY_STATUS_DISCHARGING;
2535}
2536
2537static int
2538get_prop_current_now(struct qpnp_chg_chip *chip)
2539{
2540 union power_supply_propval ret = {0,};
2541
2542 if (chip->bms_psy) {
2543 chip->bms_psy->get_property(chip->bms_psy,
2544 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
2545 return ret.intval;
2546 } else {
2547 pr_debug("No BMS supply registered return 0\n");
2548 }
2549
2550 return 0;
2551}
2552
2553static int
2554get_prop_full_design(struct qpnp_chg_chip *chip)
2555{
2556 union power_supply_propval ret = {0,};
2557
2558 if (chip->bms_psy) {
2559 chip->bms_psy->get_property(chip->bms_psy,
2560 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
2561 return ret.intval;
2562 } else {
2563 pr_debug("No BMS supply registered return 0\n");
2564 }
2565
2566 return 0;
2567}
2568
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302569static int
2570get_prop_charge_full(struct qpnp_chg_chip *chip)
2571{
2572 union power_supply_propval ret = {0,};
2573
2574 if (chip->bms_psy) {
2575 chip->bms_psy->get_property(chip->bms_psy,
2576 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
2577 return ret.intval;
2578 } else {
2579 pr_debug("No BMS supply registered return 0\n");
2580 }
2581
2582 return 0;
2583}
2584
David Keitel80668952012-07-27 14:25:49 -07002585static int
2586get_prop_capacity(struct qpnp_chg_chip *chip)
2587{
2588 union power_supply_propval ret = {0,};
Xiaozhe Shibda84992013-09-05 10:39:11 -07002589 int battery_status, bms_status, soc, charger_in;
David Keitel80668952012-07-27 14:25:49 -07002590
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002591 if (chip->fake_battery_soc >= 0)
2592 return chip->fake_battery_soc;
2593
David Keitel3dd5e0f2012-12-12 18:12:36 -08002594 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2595 return DEFAULT_CAPACITY;
2596
David Keitel80668952012-07-27 14:25:49 -07002597 if (chip->bms_psy) {
2598 chip->bms_psy->get_property(chip->bms_psy,
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002599 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002600 soc = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002601 battery_status = get_prop_batt_status(chip);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002602 chip->bms_psy->get_property(chip->bms_psy,
2603 POWER_SUPPLY_PROP_STATUS, &ret);
2604 bms_status = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002605 charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
2606 qpnp_chg_is_dc_chg_plugged_in(chip);
2607
2608 if (battery_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shibda84992013-09-05 10:39:11 -07002609 && bms_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002610 && charger_in
Xiaozhe Shie8504482013-10-30 18:10:31 -07002611 && !chip->bat_is_cool
2612 && !chip->bat_is_warm
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002613 && !chip->resuming_charging
2614 && !chip->charging_disabled
2615 && chip->soc_resume_limit
Xiaozhe Shibda84992013-09-05 10:39:11 -07002616 && soc <= chip->soc_resume_limit) {
2617 pr_debug("resuming charging at %d%% soc\n", soc);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002618 chip->resuming_charging = true;
David Keitelbf6a1062014-01-23 10:57:36 -08002619 qpnp_chg_irq_wake_enable(&chip->chg_fastchg);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002620 qpnp_chg_set_appropriate_vbatdet(chip);
2621 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2622 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002623 if (soc == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07002624 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
2625 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07002626 pr_warn_ratelimited("Battery 0, CHG absent\n");
2627 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002628 return soc;
David Keitel80668952012-07-27 14:25:49 -07002629 } else {
2630 pr_debug("No BMS supply registered return 50\n");
2631 }
2632
2633 /* return default capacity to avoid userspace
2634 * from shutting down unecessarily */
2635 return DEFAULT_CAPACITY;
2636}
2637
David Keitel3dd5e0f2012-12-12 18:12:36 -08002638#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07002639#define MAX_TOLERABLE_BATT_TEMP_DDC 680
2640static int
2641get_prop_batt_temp(struct qpnp_chg_chip *chip)
2642{
2643 int rc = 0;
2644 struct qpnp_vadc_result results;
2645
David Keitel3dd5e0f2012-12-12 18:12:36 -08002646 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2647 return DEFAULT_TEMP;
2648
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002649 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07002650 if (rc) {
2651 pr_debug("Unable to read batt temperature rc=%d\n", rc);
2652 return 0;
David Keitel80668952012-07-27 14:25:49 -07002653 }
Xiaozhe Shi4c8458a2013-11-26 13:00:56 -08002654 pr_debug("get_bat_temp %d, %lld\n",
David Keitela2dbfc72013-06-07 11:10:14 -07002655 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07002656
David Keitela2dbfc72013-06-07 11:10:14 -07002657 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07002658}
2659
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302660static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
2661{
2662 union power_supply_propval ret = {0,};
2663
2664 if (chip->bms_psy)
2665 chip->bms_psy->get_property(chip->bms_psy,
2666 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
2667 return ret.intval;
2668}
2669
David Keitel337bd862013-07-15 21:42:58 -07002670static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
2671{
2672 u8 buck_sts;
2673 int rc;
2674
2675 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2676
2677 if (rc) {
2678 pr_err("spmi read failed: addr=%03X, rc=%d\n",
2679 INT_RT_STS(chip->buck_base), rc);
2680 return rc;
2681 }
2682 pr_debug("buck usb sts 0x%x\n", buck_sts);
2683
2684 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
2685}
2686
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002687static int get_prop_online(struct qpnp_chg_chip *chip)
2688{
2689 return qpnp_chg_is_batfet_closed(chip);
2690}
2691
David Keitel80668952012-07-27 14:25:49 -07002692static void
2693qpnp_batt_external_power_changed(struct power_supply *psy)
2694{
2695 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2696 batt_psy);
2697 union power_supply_propval ret = {0,};
2698
2699 if (!chip->bms_psy)
2700 chip->bms_psy = power_supply_get_by_name("bms");
2701
2702 chip->usb_psy->get_property(chip->usb_psy,
2703 POWER_SUPPLY_PROP_ONLINE, &ret);
2704
David Keitelc69f2d62013-03-17 14:52:35 -07002705 /* Only honour requests while USB is present */
2706 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002707 chip->usb_psy->get_property(chip->usb_psy,
2708 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07002709
2710 if (chip->prev_usb_max_ma == ret.intval)
2711 goto skip_set_iusb_max;
2712
Zhenhua Huangdd619742013-10-24 10:02:07 +08002713 chip->prev_usb_max_ma = ret.intval;
2714
David Keitel87473252013-03-21 14:39:45 -07002715 if (ret.intval <= 2 && !chip->use_default_batt_values &&
2716 get_prop_batt_present(chip)) {
David Keitela9185602013-11-12 17:55:48 -08002717 if (ret.intval == 2)
2718 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07002719 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07002720 } else {
David Keiteld681cda2012-10-02 15:44:21 -07002721 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel820a90d2014-03-25 18:18:04 -07002722 if (qpnp_is_dc_higher_prio(chip)
2723 && qpnp_chg_is_dc_chg_plugged_in(chip)) {
2724 pr_debug("dc has higher priority\n");
2725 qpnp_chg_iusbmax_set(chip,
2726 QPNP_CHG_I_MAX_MIN_100);
2727 } else if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
David Keitel7ac385e2013-08-19 18:02:40 -07002728 && (charger_monitor ||
2729 !chip->charger_monitor_checked)) {
David Keitel820a90d2014-03-25 18:18:04 -07002730 if (!qpnp_is_dc_higher_prio(chip))
2731 qpnp_chg_idcmax_set(chip,
2732 QPNP_CHG_I_MAX_MIN_100);
David Keitelcd2e1022014-05-02 17:25:15 -07002733 if (unlikely(ext_ovp_present)) {
David Keitel820a90d2014-03-25 18:18:04 -07002734 qpnp_chg_iusbmax_set(chip,
2735 OVP_USB_WALL_TRSH_MA);
David Keitelcd2e1022014-05-02 17:25:15 -07002736 } else if (unlikely(
2737 ext_ovp_isns_present)) {
2738 qpnp_chg_iusb_trim_set(chip, 0);
2739 qpnp_chg_iusbmax_set(chip,
2740 IOVP_USB_WALL_TRSH_MA);
2741 } else {
2742 qpnp_chg_iusbmax_set(chip,
2743 USB_WALL_THRESHOLD_MA);
2744 }
David Keitel337bd862013-07-15 21:42:58 -07002745 } else {
2746 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2747 }
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002748
2749 if ((chip->flags & POWER_STAGE_WA)
2750 && ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
Zhenhua Huangdc335512013-10-30 11:45:15 +08002751 && !chip->power_stage_workaround_running
2752 && chip->power_stage_workaround_enable) {
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002753 chip->power_stage_workaround_running = true;
2754 pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
2755 charger_monitor);
2756 schedule_work(&chip->reduce_power_stage_work);
2757 }
David Keitelc69f2d62013-03-17 14:52:35 -07002758 }
David Keitel80668952012-07-27 14:25:49 -07002759 }
2760
David Keitelfd305ee2013-07-19 20:19:06 -07002761skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07002762 pr_debug("end of power supply changed\n");
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002763 pr_debug("psy changed batt_psy\n");
David Keitel80668952012-07-27 14:25:49 -07002764 power_supply_changed(&chip->batt_psy);
2765}
2766
2767static int
2768qpnp_batt_power_get_property(struct power_supply *psy,
2769 enum power_supply_property psp,
2770 union power_supply_propval *val)
2771{
2772 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2773 batt_psy);
2774
2775 switch (psp) {
2776 case POWER_SUPPLY_PROP_STATUS:
2777 val->intval = get_prop_batt_status(chip);
2778 break;
2779 case POWER_SUPPLY_PROP_CHARGE_TYPE:
2780 val->intval = get_prop_charge_type(chip);
2781 break;
2782 case POWER_SUPPLY_PROP_HEALTH:
2783 val->intval = get_prop_batt_health(chip);
2784 break;
2785 case POWER_SUPPLY_PROP_PRESENT:
2786 val->intval = get_prop_batt_present(chip);
2787 break;
2788 case POWER_SUPPLY_PROP_TECHNOLOGY:
2789 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2790 break;
2791 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2792 val->intval = chip->max_voltage_mv * 1000;
2793 break;
2794 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2795 val->intval = chip->min_voltage_mv * 1000;
2796 break;
2797 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2798 val->intval = get_prop_battery_voltage_now(chip);
2799 break;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002800 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2801 val->intval = chip->insertion_ocv_uv;
2802 break;
David Keitel80668952012-07-27 14:25:49 -07002803 case POWER_SUPPLY_PROP_TEMP:
2804 val->intval = get_prop_batt_temp(chip);
2805 break;
David Keitelec3c09802013-06-13 13:05:30 -07002806 case POWER_SUPPLY_PROP_COOL_TEMP:
2807 val->intval = chip->cool_bat_decidegc;
2808 break;
2809 case POWER_SUPPLY_PROP_WARM_TEMP:
2810 val->intval = chip->warm_bat_decidegc;
2811 break;
David Keitel80668952012-07-27 14:25:49 -07002812 case POWER_SUPPLY_PROP_CAPACITY:
2813 val->intval = get_prop_capacity(chip);
2814 break;
2815 case POWER_SUPPLY_PROP_CURRENT_NOW:
2816 val->intval = get_prop_current_now(chip);
2817 break;
2818 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2819 val->intval = get_prop_full_design(chip);
2820 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302821 case POWER_SUPPLY_PROP_CHARGE_FULL:
2822 val->intval = get_prop_charge_full(chip);
2823 break;
David Keitelb80eda82012-10-15 10:49:11 -07002824 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07002825 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07002826 break;
David Keitelbe208252013-01-31 14:49:25 -08002827 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2828 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07002829 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302830 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2831 val->intval = get_prop_cycle_count(chip);
2832 break;
David Keitel337bd862013-07-15 21:42:58 -07002833 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
2834 val->intval = get_prop_vchg_loop(chip);
2835 break;
2836 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2837 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
2838 break;
David Keitel2586f0a2013-08-20 10:02:26 -07002839 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
2840 val->intval = qpnp_chg_iusb_trim_get(chip);
2841 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002842 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
2843 val->intval = chip->aicl_settled;
2844 break;
David Keitel337bd862013-07-15 21:42:58 -07002845 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2846 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
2847 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002848 case POWER_SUPPLY_PROP_ONLINE:
2849 val->intval = get_prop_online(chip);
2850 break;
Fenglin Wuc64e9942014-08-22 13:47:34 +08002851 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
2852 val->intval = qpnp_chg_vchg_loop_debouncer_setting_get(chip);
2853 break;
2854
David Keitelb80eda82012-10-15 10:49:11 -07002855 default:
2856 return -EINVAL;
2857 }
2858
David Keitelb80eda82012-10-15 10:49:11 -07002859 return 0;
David Keitel80668952012-07-27 14:25:49 -07002860}
2861
David Keitel89c17752013-06-28 14:52:48 -07002862#define BTC_CONFIG_ENABLED BIT(7)
2863#define BTC_COLD BIT(1)
2864#define BTC_HOT BIT(0)
2865static int
2866qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
2867{
2868 u8 btc_cfg = 0, mask = 0;
2869
2870 /* Do nothing if battery peripheral not present */
2871 if (!chip->bat_if_base)
2872 return 0;
2873
2874 if ((chip->hot_batt_p == HOT_THD_25_PCT)
2875 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
2876 btc_cfg |= btc_value[chip->hot_batt_p];
2877 mask |= BTC_HOT;
2878 }
2879
2880 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
2881 (chip->cold_batt_p == COLD_THD_80_PCT)) {
2882 btc_cfg |= btc_value[chip->cold_batt_p];
2883 mask |= BTC_COLD;
2884 }
2885
2886 if (chip->btc_disabled)
2887 mask |= BTC_CONFIG_ENABLED;
2888
2889 return qpnp_chg_masked_write(chip,
2890 chip->bat_if_base + BAT_IF_BTC_CTRL,
2891 mask, btc_cfg, 1);
2892}
2893
David Keitel5d44fa52012-12-03 16:37:31 -08002894#define QPNP_CHG_IBATSAFE_MIN_MA 100
2895#define QPNP_CHG_IBATSAFE_MAX_MA 3250
2896#define QPNP_CHG_I_STEP_MA 50
2897#define QPNP_CHG_I_MIN_MA 100
2898#define QPNP_CHG_I_MASK 0x3F
2899static int
2900qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
2901{
2902 u8 temp;
2903
2904 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
2905 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
2906 pr_err("bad mA=%d asked to set\n", safe_current);
2907 return -EINVAL;
2908 }
2909
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08002910 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08002911 return qpnp_chg_masked_write(chip,
2912 chip->chgr_base + CHGR_IBAT_SAFE,
2913 QPNP_CHG_I_MASK, temp, 1);
2914}
David Keitel80668952012-07-27 14:25:49 -07002915
2916#define QPNP_CHG_ITERM_MIN_MA 100
2917#define QPNP_CHG_ITERM_MAX_MA 250
2918#define QPNP_CHG_ITERM_STEP_MA 50
2919#define QPNP_CHG_ITERM_MASK 0x03
2920static int
2921qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
2922{
2923 u8 temp;
2924
2925 if (term_current < QPNP_CHG_ITERM_MIN_MA
2926 || term_current > QPNP_CHG_ITERM_MAX_MA) {
2927 pr_err("bad mA=%d asked to set\n", term_current);
2928 return -EINVAL;
2929 }
2930
2931 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
2932 / QPNP_CHG_ITERM_STEP_MA;
2933 return qpnp_chg_masked_write(chip,
2934 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
2935 QPNP_CHG_ITERM_MASK, temp, 1);
2936}
2937
David Keitelff5d0472013-04-04 11:36:06 -07002938#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07002939#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07002940static int
2941qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
2942{
2943 u8 temp;
2944
2945 if (chg_current < QPNP_CHG_IBATMAX_MIN
2946 || chg_current > QPNP_CHG_IBATMAX_MAX) {
2947 pr_err("bad mA=%d asked to set\n", chg_current);
2948 return -EINVAL;
2949 }
David Keitelff5d0472013-04-04 11:36:06 -07002950 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07002951 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
2952 QPNP_CHG_I_MASK, temp, 1);
2953}
2954
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002955static int
2956qpnp_chg_ibatmax_get(struct qpnp_chg_chip *chip, int *chg_current)
2957{
2958 int rc;
2959 u8 temp;
2960
2961 *chg_current = 0;
2962 rc = qpnp_chg_read(chip, &temp, chip->chgr_base + CHGR_IBAT_MAX, 1);
2963 if (rc) {
2964 pr_err("failed read ibat_max rc=%d\n", rc);
2965 return rc;
2966 }
2967
2968 *chg_current = ((temp & QPNP_CHG_I_MASK) * QPNP_CHG_I_STEP_MA);
2969
2970 return 0;
2971}
2972
David Keitela4b7b592013-04-11 18:34:35 -07002973#define QPNP_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002974#define QPNP_CHG_TCHG_EN_MASK 0x80
David Keitela4b7b592013-04-11 18:34:35 -07002975#define QPNP_CHG_TCHG_MIN 4
2976#define QPNP_CHG_TCHG_MAX 512
2977#define QPNP_CHG_TCHG_STEP 4
2978static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
2979{
2980 u8 temp;
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002981 int rc;
David Keitela4b7b592013-04-11 18:34:35 -07002982
2983 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
2984 pr_err("bad max minutes =%d asked to set\n", minutes);
2985 return -EINVAL;
2986 }
2987
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002988 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
2989 QPNP_CHG_TCHG_EN_MASK, 0, 1);
2990 if (rc) {
2991 pr_err("failed write tchg_max_en rc=%d\n", rc);
2992 return rc;
2993 }
2994
2995 temp = minutes / QPNP_CHG_TCHG_STEP - 1;
2996
2997 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07002998 QPNP_CHG_TCHG_MASK, temp, 1);
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002999 if (rc) {
3000 pr_err("failed write tchg_max_en rc=%d\n", rc);
3001 return rc;
3002 }
3003
3004 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
3005 QPNP_CHG_TCHG_EN_MASK, QPNP_CHG_TCHG_EN_MASK, 1);
3006 if (rc) {
3007 pr_err("failed write tchg_max_en rc=%d\n", rc);
3008 return rc;
3009 }
3010
3011 return 0;
David Keitela4b7b592013-04-11 18:34:35 -07003012}
David Keitel80668952012-07-27 14:25:49 -07003013
David Keitel59fbb762014-02-05 16:46:24 -08003014static void
3015qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
3016{
3017 unsigned int chg_current = chip->max_bat_chg_current;
3018
3019 if (chip->bat_is_cool)
3020 chg_current = min(chg_current, chip->cool_bat_chg_ma);
3021
3022 if (chip->bat_is_warm)
3023 chg_current = min(chg_current, chip->warm_bat_chg_ma);
3024
3025 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
3026 chg_current = min(chg_current,
3027 chip->thermal_mitigation[chip->therm_lvl_sel]);
3028
3029 pr_debug("setting %d mA\n", chg_current);
3030 qpnp_chg_ibatmax_set(chip, chg_current);
3031}
3032
David Keitel80668952012-07-27 14:25:49 -07003033static int
3034qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
3035{
3036 u8 temp;
3037
3038 if (voltage < QPNP_CHG_V_MIN_MV
3039 || voltage > QPNP_CHG_V_MAX_MV) {
3040 pr_err("bad mV=%d asked to set\n", voltage);
3041 return -EINVAL;
3042 }
3043 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
3044 pr_debug("voltage=%d setting %02x\n", voltage, temp);
3045 return qpnp_chg_write(chip, &temp,
3046 chip->chgr_base + CHGR_VDD_SAFE, 1);
3047}
3048
wangxlee3614a2015-02-03 13:13:11 +08003049#ifdef CONFIG_TCMD
3050int qpnp_disable_source_current(bool disable)
3051{
3052 int ret =-1;
3053 if(!the_chip)
3054 {
3055 pr_err("called before init\n");
3056 return -EINVAL;
3057 }
3058 if(disable)
3059 {
3060 ret = qpnp_chg_charge_en(the_chip, !disable);
3061 if(ret)
3062 {
3063 printk("TCMD : qpnp_chg_charge_en failed. result = %d", ret);
3064 return ret;
3065 }
3066 else
3067 {
3068 ret = qpnp_chg_force_run_on_batt(the_chip, true);
3069 if(ret)
3070 printk("TCMD : pnp_chg_force_run_on_batt failed. result = %d", ret);
3071 }
3072 }
3073 else
3074 {
3075 ret = qpnp_chg_force_run_on_batt(the_chip, false);
3076 if(ret)
3077 {
3078 printk("TCMD : pnp_chg_force_run_on_batt failed. result = %d", ret);
3079 return ret;
3080 }
3081 else
3082 {
3083 ret = qpnp_chg_charge_en(the_chip, !disable);
3084 if(ret)
3085 printk("TCMD : qpnp_chg_charge_en failed. result = %d", ret);
3086 }
3087 }
3088 return ret;
3089}
3090
3091EXPORT_SYMBOL(qpnp_disable_source_current);
3092
3093int qpnp_disable_usb_charging(bool disable)
3094{
3095 int ret =-1;
3096 if (!the_chip)
3097 {
3098 pr_err("called before init\n");
3099 return -EINVAL;
3100 }
3101
3102 ret = qpnp_chg_usb_suspend_enable(the_chip, disable);
3103 if(disable)
3104 {
3105 printk("TCMD : Disable USB charging\n");
3106 ret = qpnp_chg_iusbmax_set(the_chip, QPNP_CHG_I_MAX_MIN_100);
3107 }
3108 else
3109 {
3110 printk("TCMD : Enable USB charging\n");
3111 ret = qpnp_chg_iusbmax_set(the_chip, QPNP_CHG_I_MAX_MAX_MA);
3112 if(ret)
3113 {
3114 printk("TCMD : FAILED to set MAX USB current !\n");
3115 }
3116 else
3117 {
3118 ret = qpnp_disable_source_current(false);
3119 if(ret)
3120 {
3121 printk("TCMD : FAILED to enable source current !\n");
3122 }
3123 }
3124 }
3125 return ret;
3126}
3127
3128EXPORT_SYMBOL(qpnp_disable_usb_charging);
3129
3130int qpnp_set_max_battery_charge_current(bool enable)
3131{
wangxl07c6bc92014-12-31 10:07:44 +08003132 int ret = -1;
wangxlee3614a2015-02-03 13:13:11 +08003133 unsigned int chg_current = 0;
3134 if (!the_chip)
3135 {
3136 pr_err("called before init\n");
3137 return -EINVAL;
3138 }
3139
wangxl07c6bc92014-12-31 10:07:44 +08003140 chg_current = (enable) ? 850 : the_chip->warm_bat_chg_ma;
wangxlee3614a2015-02-03 13:13:11 +08003141
3142 ret = qpnp_chg_ibatmax_set(the_chip, chg_current);
wangxl07c6bc92014-12-31 10:07:44 +08003143 if(ret < 0) {
3144 return ret;
3145 }
3146 ret = qpnp_chg_iusbmax_set(the_chip, 1500);
wangxlee3614a2015-02-03 13:13:11 +08003147 return ret;
3148}
3149
3150EXPORT_SYMBOL(qpnp_set_max_battery_charge_current);
wangxl07c6bc92014-12-31 10:07:44 +08003151
3152int qpnp_get_usb_max_current(int* usb_max_current){
3153 if (!the_chip)
3154 {
3155 pr_err("called before init\n");
3156 return -EINVAL;
3157 }
3158
3159 *usb_max_current = qpnp_chg_usb_iusbmax_get(the_chip);
3160 return 0;
3161 }
3162
3163EXPORT_SYMBOL(qpnp_get_usb_max_current);
3164
3165int qpnp_get_bat_max_current(int* bat_max_current){
3166 int max_current, rc = -1;
3167 if (!the_chip)
3168 {
3169 pr_err("called before init\n");
3170 return -EINVAL;
3171 }
3172
3173 rc = qpnp_chg_ibatmax_get(the_chip,&max_current);
3174 *bat_max_current = max_current;
3175
3176 return rc;
3177 }
3178
3179EXPORT_SYMBOL(qpnp_get_bat_max_current);
3180
3181int qpnp_set_usb_max_current(int usb_max_current){
3182 int ret = -1;
3183 if (!the_chip)
3184 {
3185 pr_err("called before init\n");
3186 return -EINVAL;
3187 }
3188
3189 ret = qpnp_chg_iusbmax_set(the_chip, usb_max_current);
3190 return ret;
3191 }
3192
3193EXPORT_SYMBOL(qpnp_set_usb_max_current);
3194
3195int qpnp_set_bat_max_current(int bat_max_current){
3196 int rc = -1;
3197 if (!the_chip)
3198 {
3199 pr_err("called before init\n");
3200 return -EINVAL;
3201 }
3202
3203 rc = qpnp_chg_ibatmax_set(the_chip, bat_max_current);
3204
3205 return rc;
3206 }
3207
3208EXPORT_SYMBOL(qpnp_set_bat_max_current);
wangxlee3614a2015-02-03 13:13:11 +08003209#endif
3210
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003211#define IBAT_TRIM_TGT_MA 500
3212#define IBAT_TRIM_OFFSET_MASK 0x7F
3213#define IBAT_TRIM_GOOD_BIT BIT(7)
3214#define IBAT_TRIM_LOW_LIM 20
3215#define IBAT_TRIM_HIGH_LIM 114
3216#define IBAT_TRIM_MEAN 64
3217
3218static void
3219qpnp_chg_trim_ibat(struct qpnp_chg_chip *chip, u8 ibat_trim)
3220{
3221 int ibat_now_ma, ibat_diff_ma, rc;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003222 struct qpnp_iadc_result i_result;
3223 enum qpnp_iadc_channels iadc_channel;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003224
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003225 iadc_channel = chip->use_external_rsense ?
3226 EXTERNAL_RSENSE : INTERNAL_RSENSE;
3227 rc = qpnp_iadc_read(chip->iadc_dev, iadc_channel, &i_result);
3228 if (rc) {
3229 pr_err("Unable to read bat rc=%d\n", rc);
3230 return;
3231 }
3232
3233 ibat_now_ma = i_result.result_ua / 1000;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003234
3235 if (qpnp_chg_is_ibat_loop_active(chip)) {
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003236 ibat_diff_ma = ibat_now_ma - IBAT_TRIM_TGT_MA;
3237
3238 if (abs(ibat_diff_ma) > 50) {
3239 ibat_trim += (ibat_diff_ma / 20);
3240 ibat_trim &= IBAT_TRIM_OFFSET_MASK;
3241 /* reject new ibat_trim if it is outside limits */
3242 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
3243 IBAT_TRIM_HIGH_LIM))
3244 return;
3245 }
Chunmei Cai76705f02014-12-11 09:48:42 +08003246
3247 if (chip->type == SMBBP) {
3248 rc = qpnp_chg_masked_write(chip,
3249 chip->buck_base + SEC_ACCESS,
3250 0xFF, 0xA5, 1);
3251 if (rc) {
3252 pr_err("failed to write SEC_ACCESS: %d\n", rc);
3253 return;
3254 }
3255 }
3256
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003257 ibat_trim |= IBAT_TRIM_GOOD_BIT;
3258 rc = qpnp_chg_write(chip, &ibat_trim,
3259 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3260 if (rc)
3261 pr_err("failed to set IBAT_TRIM rc=%d\n", rc);
3262
3263 pr_debug("ibat_now=%dmA, itgt=%dmA, ibat_diff=%dmA, ibat_trim=%x\n",
3264 ibat_now_ma, IBAT_TRIM_TGT_MA,
3265 ibat_diff_ma, ibat_trim);
3266 } else {
3267 pr_debug("ibat loop not active - cannot calibrate ibat\n");
3268 }
3269}
3270
3271static int
3272qpnp_chg_input_current_settled(struct qpnp_chg_chip *chip)
3273{
3274 int rc, ibat_max_ma;
3275 u8 reg, chgr_sts, ibat_trim, i;
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07003276 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003277
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07003278 if (!usb_present) {
3279 pr_debug("Ignoring AICL settled, since USB is removed\n");
3280 return 0;
3281 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003282 chip->aicl_settled = true;
3283
3284 /*
3285 * Perform the ibat calibration.
3286 * This is for devices which have a IBAT_TRIM error
3287 * which can show IBAT_MAX out of spec.
3288 */
3289 if (!chip->ibat_calibration_enabled)
3290 return 0;
3291
Chunmei Cai76705f02014-12-11 09:48:42 +08003292 if (chip->type != SMBB && chip->type != SMBBP)
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003293 return 0;
3294
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003295 rc = qpnp_chg_read(chip, &reg,
3296 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3297 if (rc) {
3298 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
3299 return rc;
3300 }
3301 if (reg & IBAT_TRIM_GOOD_BIT) {
3302 pr_debug("IBAT_TRIM_GOOD bit already set. Quitting!\n");
3303 return 0;
3304 }
3305 ibat_trim = reg & IBAT_TRIM_OFFSET_MASK;
3306
3307 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
3308 IBAT_TRIM_HIGH_LIM)) {
3309 pr_debug("Improper ibat_trim value=%x setting to value=%x\n",
3310 ibat_trim, IBAT_TRIM_MEAN);
3311 ibat_trim = IBAT_TRIM_MEAN;
Chunmei Cai76705f02014-12-11 09:48:42 +08003312
3313 if (chip->type == SMBBP) {
3314 rc = qpnp_chg_masked_write(chip,
3315 chip->buck_base + SEC_ACCESS,
3316 0xFF, 0xA5, 1);
3317 if (rc) {
3318 pr_err("failed to write SEC_ACCESS: %d\n", rc);
3319 return rc;
3320 }
3321 }
3322
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003323 rc = qpnp_chg_masked_write(chip,
3324 chip->buck_base + BUCK_CTRL_TRIM3,
3325 IBAT_TRIM_OFFSET_MASK, ibat_trim, 1);
3326 if (rc) {
3327 pr_err("failed to set ibat_trim to %x rc=%d\n",
3328 IBAT_TRIM_MEAN, rc);
3329 return rc;
3330 }
3331 }
3332
3333 rc = qpnp_chg_read(chip, &chgr_sts,
3334 INT_RT_STS(chip->chgr_base), 1);
3335 if (rc) {
3336 pr_err("failed to read interrupt sts rc=%d\n", rc);
3337 return rc;
3338 }
3339 if (!(chgr_sts & FAST_CHG_ON_IRQ)) {
3340 pr_debug("Not in fastchg\n");
3341 return rc;
3342 }
3343
3344 /* save the ibat_max to restore it later */
3345 rc = qpnp_chg_ibatmax_get(chip, &ibat_max_ma);
3346 if (rc) {
3347 pr_debug("failed to save ibatmax rc=%d\n", rc);
3348 return rc;
3349 }
3350
3351 rc = qpnp_chg_ibatmax_set(chip, IBAT_TRIM_TGT_MA);
3352 if (rc) {
3353 pr_err("failed to set ibatmax rc=%d\n", rc);
3354 return rc;
3355 }
3356
3357 for (i = 0; i < 3; i++) {
3358 /*
3359 * ibat settling delay - to make sure the BMS controller
3360 * has sufficient time to sample ibat for the configured
3361 * ibat_max
3362 */
3363 msleep(20);
3364 if (qpnp_chg_is_ibat_loop_active(chip))
3365 qpnp_chg_trim_ibat(chip, ibat_trim);
3366 else
3367 pr_debug("ibat loop not active\n");
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003368
3369 /* read the adjusted ibat_trim for further adjustments */
3370 rc = qpnp_chg_read(chip, &ibat_trim,
3371 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3372 if (rc) {
3373 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
3374 break;
3375 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003376 }
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003377
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003378 /* restore IBATMAX */
3379 rc = qpnp_chg_ibatmax_set(chip, ibat_max_ma);
3380 if (rc)
3381 pr_err("failed to restore ibatmax rc=%d\n", rc);
3382
3383 return rc;
3384}
3385
3386
David Keitel6dc4ed42013-05-17 11:08:58 -07003387#define BOOST_MIN_UV 4200000
3388#define BOOST_MAX_UV 5500000
3389#define BOOST_STEP_UV 50000
3390#define BOOST_MIN 16
3391#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
3392static int
3393qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
3394{
3395 u8 reg = 0;
3396
3397 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
3398 pr_err("invalid voltage requested %d uV\n", voltage);
3399 return -EINVAL;
3400 }
3401
3402 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
3403
3404 pr_debug("voltage=%d setting %02x\n", voltage, reg);
3405 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
3406}
3407
3408static int
3409qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
3410{
3411 int rc;
3412 u8 boost_reg;
3413
3414 rc = qpnp_chg_read(chip, &boost_reg,
3415 chip->boost_base + BOOST_VSET, 1);
3416 if (rc) {
3417 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
3418 return rc;
3419 }
3420
3421 if (boost_reg < BOOST_MIN) {
3422 pr_err("Invalid reading from 0x%x\n", boost_reg);
3423 return -EINVAL;
3424 }
3425
3426 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
3427}
3428
David Keitel454ee842013-03-08 16:19:11 -08003429static void
David Keitelbe208252013-01-31 14:49:25 -08003430qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
3431{
3432 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
3433 chip->therm_lvl_sel = lvl_sel;
3434 if (lvl_sel == (chip->thermal_levels - 1)) {
3435 /* disable charging if highest value selected */
3436 qpnp_chg_buck_control(chip, 0);
3437 } else {
3438 qpnp_chg_buck_control(chip, 1);
3439 qpnp_chg_set_appropriate_battery_current(chip);
3440 }
3441 } else {
3442 pr_err("Unsupported level selected %d\n", lvl_sel);
3443 }
3444}
3445
Chunmei Cai661a7cd2014-08-05 17:31:54 +08003446/*
3447 * Increase the SMBB/SMBBP charger overtemp threshold to 150C while firing
3448 * the flash (and/or torch for PM8x26) when the bharger is used as the
3449 * power source.
3450 */
3451static int
3452qpnp_chg_temp_threshold_set(struct qpnp_chg_chip *chip, u8 value)
3453{
3454 int rc;
3455
3456 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
3457 CHGR_CHG_TEMP_THRESH ,
3458 0xFF, value, 1);
3459 if (rc)
3460 pr_err("set CHG_TEMP_THRESH_Flash failed, value = %d, rc = %d\n",
3461 value, rc);
3462
3463 return rc;
3464}
3465
3466#define CHG_TEMP_THRESH_FOR_FLASH 0xFD
3467#define CHG_TEMP_THRESH_DEFAULT 0x94
3468static int
3469qpnp_chg_regulator_flash_wa_enable(struct regulator_dev *rdev)
3470{
3471 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3472 int rc = 0;
3473
3474 if (chip->flags & BOOST_FLASH_WA) {
3475 rc = qpnp_chg_temp_threshold_set(chip,
3476 CHG_TEMP_THRESH_FOR_FLASH);
3477 if (rc) {
3478 pr_err("set chg temp threshold failed rc = %d\n", rc);
3479 return rc;
3480 }
3481 }
3482 chip->is_flash_wa_reg_enabled = true;
3483
3484 return rc;
3485}
3486
3487static int
3488qpnp_chg_regulator_flash_wa_disable(struct regulator_dev *rdev)
3489{
3490 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3491 int rc = 0;
3492
3493 if (chip->flags & BOOST_FLASH_WA) {
3494 rc = qpnp_chg_temp_threshold_set(chip,
3495 chip->chg_temp_thresh_default);
3496 if (rc) {
3497 pr_err("set chg temp threshold failed rc = %d\n", rc);
3498 return rc;
3499 }
3500
3501 }
3502 chip->is_flash_wa_reg_enabled = false;
3503
3504 return rc;
3505}
3506
3507static int
3508qpnp_chg_regulator_flash_wa_is_enabled(struct regulator_dev *rdev)
3509{
3510 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3511
3512 return chip->is_flash_wa_reg_enabled;
3513}
3514
David Keitel6dc4ed42013-05-17 11:08:58 -07003515/* OTG regulator operations */
3516static int
3517qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
3518{
3519 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3520
3521 return switch_usb_to_host_mode(chip);
3522}
3523
3524static int
3525qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
3526{
3527 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3528
3529 return switch_usb_to_charge_mode(chip);
3530}
3531
3532static int
3533qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
3534{
3535 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3536
3537 return qpnp_chg_is_otg_en_set(chip);
3538}
3539
3540static int
3541qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
3542{
3543 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
Chunmei Caib3999b22014-07-11 15:38:13 +08003544 int usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel33f58952013-05-20 16:17:36 -07003545 int rc;
3546
Chunmei Caib3999b22014-07-11 15:38:13 +08003547 if (usb_present && (chip->flags & BOOST_FLASH_WA)) {
David Keitelcd2e1022014-05-02 17:25:15 -07003548
3549 if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
3550 pr_debug("EXT OVP IC ISNS disabled\n");
3551 gpio_direction_output(chip->ext_ovp_isns_gpio, 0);
3552 }
3553
David Keitel33f58952013-05-20 16:17:36 -07003554 qpnp_chg_usb_suspend_enable(chip, 1);
3555
3556 rc = qpnp_chg_masked_write(chip,
3557 chip->usb_chgpth_base + SEC_ACCESS,
3558 0xFF,
3559 0xA5, 1);
3560 if (rc) {
3561 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3562 return rc;
3563 }
3564
3565 rc = qpnp_chg_masked_write(chip,
3566 chip->usb_chgpth_base + COMP_OVR1,
3567 0xFF,
3568 0x2F, 1);
3569 if (rc) {
3570 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3571 return rc;
3572 }
3573 }
David Keitel6dc4ed42013-05-17 11:08:58 -07003574
Chunmei Caib3999b22014-07-11 15:38:13 +08003575 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003576 chip->boost_base + BOOST_ENABLE_CONTROL,
3577 BOOST_PWR_EN,
3578 BOOST_PWR_EN, 1);
Chunmei Caib3999b22014-07-11 15:38:13 +08003579 if (rc) {
3580 pr_err("failed to enable boost rc = %d\n", rc);
3581 return rc;
3582 }
3583 /*
3584 * update battery status when charger is connected and state is full
3585 */
3586 if (usb_present && (chip->chg_done
3587 || (get_batt_capacity(chip) == 100)
3588 || (get_prop_batt_status(chip) ==
3589 POWER_SUPPLY_STATUS_FULL)))
3590 power_supply_changed(&chip->batt_psy);
3591
3592 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003593}
3594
3595/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07003596#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07003597static int
3598qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
3599{
3600 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07003601 int rc;
3602 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07003603
David Keitel33f58952013-05-20 16:17:36 -07003604 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003605 chip->boost_base + BOOST_ENABLE_CONTROL,
3606 BOOST_PWR_EN,
3607 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07003608 if (rc) {
3609 pr_err("failed to disable boost rc=%d\n", rc);
3610 return rc;
3611 }
3612
3613 rc = qpnp_chg_read(chip, &vbat_sts,
3614 chip->chgr_base + CHGR_VBAT_STATUS, 1);
3615 if (rc) {
3616 pr_err("failed to read bat sts rc=%d\n", rc);
3617 return rc;
3618 }
3619
3620 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
3621 rc = qpnp_chg_masked_write(chip,
3622 chip->chgr_base + SEC_ACCESS,
3623 0xFF,
3624 0xA5, 1);
3625 if (rc) {
3626 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3627 return rc;
3628 }
3629
3630 rc = qpnp_chg_masked_write(chip,
3631 chip->chgr_base + COMP_OVR1,
3632 0xFF,
3633 0x20, 1);
3634 if (rc) {
3635 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3636 return rc;
3637 }
3638
3639 usleep(2000);
3640
3641 rc = qpnp_chg_masked_write(chip,
3642 chip->chgr_base + SEC_ACCESS,
3643 0xFF,
3644 0xA5, 1);
3645 if (rc) {
3646 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3647 return rc;
3648 }
3649
3650 rc = qpnp_chg_masked_write(chip,
3651 chip->chgr_base + COMP_OVR1,
3652 0xFF,
3653 0x00, 1);
3654 if (rc) {
3655 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3656 return rc;
3657 }
3658 }
3659
3660 if (qpnp_chg_is_usb_chg_plugged_in(chip)
3661 && (chip->flags & BOOST_FLASH_WA)) {
3662 rc = qpnp_chg_masked_write(chip,
3663 chip->usb_chgpth_base + SEC_ACCESS,
3664 0xFF,
3665 0xA5, 1);
3666 if (rc) {
3667 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3668 return rc;
3669 }
3670
3671 rc = qpnp_chg_masked_write(chip,
3672 chip->usb_chgpth_base + COMP_OVR1,
3673 0xFF,
3674 0x00, 1);
3675 if (rc) {
3676 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3677 return rc;
3678 }
3679
3680 usleep(1000);
3681
3682 qpnp_chg_usb_suspend_enable(chip, 0);
3683 }
3684
Chunmei Caib3999b22014-07-11 15:38:13 +08003685 /*
3686 * When a charger is connected,if state of charge is not full
3687 * resumeing charging else update battery status
3688 */
3689 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
3690 if (get_batt_capacity(chip) < 100 || !chip->chg_done) {
3691 chip->chg_done = false;
3692 chip->resuming_charging = true;
3693 qpnp_chg_set_appropriate_vbatdet(chip);
3694 } else if (chip->chg_done) {
3695 power_supply_changed(&chip->batt_psy);
3696 }
3697 }
3698
David Keitelcd2e1022014-05-02 17:25:15 -07003699 if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
3700 pr_debug("EXT OVP IC ISNS enable\n");
3701 gpio_direction_output(chip->ext_ovp_isns_gpio, 1);
3702 }
3703
David Keitel33f58952013-05-20 16:17:36 -07003704 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003705}
3706
3707static int
3708qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
3709{
3710 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3711
3712 return qpnp_chg_is_boost_en_set(chip);
3713}
3714
3715static int
3716qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
3717 int min_uV, int max_uV, unsigned *selector)
3718{
3719 int uV = min_uV;
3720 int rc;
3721 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3722
3723 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
3724 uV = BOOST_MIN_UV;
3725
3726
3727 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
3728 pr_err("request %d uV is out of bounds\n", uV);
3729 return -EINVAL;
3730 }
3731
3732 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
3733 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
3734 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
3735 return -EINVAL;
3736 }
3737
3738 rc = qpnp_boost_vset(chip, uV);
3739
3740 return rc;
3741}
3742
3743static int
3744qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
3745{
3746 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3747
3748 return qpnp_boost_vget_uv(chip);
3749}
3750
3751static int
3752qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
3753 unsigned selector)
3754{
3755 if (selector >= N_BOOST_V)
3756 return 0;
3757
3758 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
3759}
3760
Chunmei Cai661a7cd2014-08-05 17:31:54 +08003761static struct regulator_ops qpnp_chg_flash_wa_reg_ops = {
3762 .enable = qpnp_chg_regulator_flash_wa_enable,
3763 .disable = qpnp_chg_regulator_flash_wa_disable,
3764 .is_enabled = qpnp_chg_regulator_flash_wa_is_enabled,
3765};
3766
David Keitel6dc4ed42013-05-17 11:08:58 -07003767static struct regulator_ops qpnp_chg_otg_reg_ops = {
3768 .enable = qpnp_chg_regulator_otg_enable,
3769 .disable = qpnp_chg_regulator_otg_disable,
3770 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
3771};
3772
3773static struct regulator_ops qpnp_chg_boost_reg_ops = {
3774 .enable = qpnp_chg_regulator_boost_enable,
3775 .disable = qpnp_chg_regulator_boost_disable,
3776 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
3777 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
3778 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
3779 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
3780};
3781
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003782static int
David Keitel6e63bd52013-09-06 18:00:03 -07003783qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003784{
David Keitel9eca8ac2013-09-06 14:18:36 -07003785 int rc = 0;
David Keitel6e63bd52013-09-06 18:00:03 -07003786 u8 reg = 0;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003787
David Keitelcadbc282013-09-26 11:39:14 -07003788 if (!chip->bat_if_base)
3789 return rc;
3790
David Keitel9eca8ac2013-09-06 14:18:36 -07003791 if (chip->type == SMBB)
3792 rc = qpnp_chg_read(chip, &reg,
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003793 chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
David Keitel9eca8ac2013-09-06 14:18:36 -07003794 else
3795 rc = qpnp_chg_read(chip, &reg,
3796 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
David Keitel6e63bd52013-09-06 18:00:03 -07003797
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003798 if (rc) {
3799 pr_err("failed to read batt_if rc=%d\n", rc);
3800 return rc;
3801 }
3802
David Keitel6e63bd52013-09-06 18:00:03 -07003803 if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003804 return 1;
3805
3806 return 0;
3807}
3808
David Keitel6e63bd52013-09-06 18:00:03 -07003809static int
3810qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
3811{
3812 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3813 int rc = 0;
3814
3815 mutex_lock(&chip->batfet_vreg_lock);
3816 /* Only enable if not already enabled */
3817 if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
3818 rc = qpnp_chg_regulator_batfet_set(chip, 1);
3819 if (rc)
3820 pr_err("failed to write to batt_if rc=%d\n", rc);
3821 }
3822
3823 chip->batfet_ext_en = true;
3824 mutex_unlock(&chip->batfet_vreg_lock);
3825
3826 return rc;
3827}
3828
3829static int
3830qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
3831{
3832 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3833 int rc = 0;
3834
3835 mutex_lock(&chip->batfet_vreg_lock);
3836 /* Don't allow disable if charger connected */
3837 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3838 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3839 rc = qpnp_chg_regulator_batfet_set(chip, 0);
3840 if (rc)
3841 pr_err("failed to write to batt_if rc=%d\n", rc);
3842 }
3843
3844 chip->batfet_ext_en = false;
3845 mutex_unlock(&chip->batfet_vreg_lock);
3846
3847 return rc;
3848}
3849
3850static int
3851qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
3852{
3853 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3854
3855 return chip->batfet_ext_en;
3856}
3857
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003858static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
3859 .enable = qpnp_chg_regulator_batfet_enable,
3860 .disable = qpnp_chg_regulator_batfet_disable,
3861 .is_enabled = qpnp_chg_regulator_batfet_is_enabled,
3862};
3863
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003864#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 8
3865#define MAX_DELTA_VDD_MAX_MV 80
3866#define VDD_MAX_CENTER_OFFSET 4
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003867static void
3868qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
3869{
3870 int delta_mv, closest_delta_mv, sign;
3871
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003872 delta_mv = chip->max_voltage_mv - VDD_MAX_CENTER_OFFSET - vbat_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003873 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
3874 pr_debug("vbat is not low enough to increase vdd\n");
3875 return;
3876 }
3877
3878 sign = delta_mv > 0 ? 1 : -1;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003879 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_BUCK_TRIM1_STEP / 2)
3880 / QPNP_CHG_BUCK_TRIM1_STEP) * QPNP_CHG_BUCK_TRIM1_STEP;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003881 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
3882 chip->max_voltage_mv, vbat_mv,
3883 delta_mv, closest_delta_mv);
3884 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
3885 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
3886 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
3887 qpnp_chg_set_appropriate_vddmax(chip);
3888}
3889
David Keitel9fd07382013-05-02 15:37:44 -07003890#define CONSECUTIVE_COUNT 3
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003891#define VBATDET_MAX_ERR_MV 50
David Keitel9fd07382013-05-02 15:37:44 -07003892static void
3893qpnp_eoc_work(struct work_struct *work)
3894{
3895 struct delayed_work *dwork = to_delayed_work(work);
3896 struct qpnp_chg_chip *chip = container_of(dwork,
3897 struct qpnp_chg_chip, eoc_work);
3898 static int count;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003899 static int vbat_low_count;
David Keitel9fd07382013-05-02 15:37:44 -07003900 int ibat_ma, vbat_mv, rc = 0;
3901 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003902 bool vbat_lower_than_vbatdet;
David Keitel9fd07382013-05-02 15:37:44 -07003903
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003904 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003905 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3906
3907 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
3908 if (rc) {
3909 pr_err("failed to read batt_if rc=%d\n", rc);
3910 return;
3911 }
3912
3913 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
3914 if (rc) {
3915 pr_err("failed to read buck rc=%d\n", rc);
3916 return;
3917 }
3918
3919 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
3920 if (rc) {
3921 pr_err("failed to read chg_sts rc=%d\n", rc);
3922 return;
3923 }
3924
3925 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
3926 chg_sts, batt_sts, buck_sts);
3927
3928 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3929 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3930 pr_debug("no chg connected, stopping\n");
3931 goto stop_eoc;
3932 }
3933
3934 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
3935 || chg_sts & TRKL_CHG_ON_IRQ)) {
3936 ibat_ma = get_prop_current_now(chip) / 1000;
3937 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003938
3939 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
3940 ibat_ma, vbat_mv, chip->term_current);
3941
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003942 vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
3943 if (vbat_lower_than_vbatdet && vbat_mv <
3944 (chip->max_voltage_mv - chip->resume_delta_mv
David Keitelbdbae452014-01-14 17:19:50 -08003945 - chip->vbatdet_max_err_mv)) {
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003946 vbat_low_count++;
3947 pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
3948 vbat_mv, chip->max_voltage_mv,
3949 chip->resume_delta_mv,
David Keitelbdbae452014-01-14 17:19:50 -08003950 chip->vbatdet_max_err_mv,
3951 vbat_low_count);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003952 if (vbat_low_count >= CONSECUTIVE_COUNT) {
3953 pr_debug("woke up too early stopping\n");
3954 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
3955 goto stop_eoc;
3956 } else {
3957 goto check_again_later;
3958 }
3959 } else {
3960 vbat_low_count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003961 }
3962
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003963 if (buck_sts & VDD_LOOP_IRQ)
3964 qpnp_chg_adjust_vddmax(chip, vbat_mv);
3965
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003966 if (!(buck_sts & VDD_LOOP_IRQ)) {
3967 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07003968 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003969 } else if ((ibat_ma * -1) > chip->term_current) {
3970 pr_debug("Not at EOC, battery current too high\n");
3971 count = 0;
3972 } else if (ibat_ma > 0) {
3973 pr_debug("Charging but system demand increased\n");
3974 count = 0;
3975 } else {
David Keitel9fd07382013-05-02 15:37:44 -07003976 if (count == CONSECUTIVE_COUNT) {
Xiaozhe Shie8504482013-10-30 18:10:31 -07003977 if (!chip->bat_is_cool && !chip->bat_is_warm) {
3978 pr_info("End of Charging\n");
3979 chip->chg_done = true;
3980 } else {
3981 pr_info("stop charging: battery is %s, vddmax = %d reached\n",
3982 chip->bat_is_cool
3983 ? "cool" : "warm",
3984 qpnp_chg_vddmax_get(chip));
3985 }
David Keitel9fd07382013-05-02 15:37:44 -07003986 qpnp_chg_charge_en(chip, 0);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003987 /* sleep for a second before enabling */
3988 msleep(2000);
3989 qpnp_chg_charge_en(chip,
3990 !chip->charging_disabled);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003991 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07003992 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07003993 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07003994 goto stop_eoc;
3995 } else {
3996 count += 1;
3997 pr_debug("EOC count = %d\n", count);
3998 }
David Keitel9fd07382013-05-02 15:37:44 -07003999 }
4000 } else {
4001 pr_debug("not charging\n");
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004002 goto stop_eoc;
David Keitel9fd07382013-05-02 15:37:44 -07004003 }
4004
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004005check_again_later:
David Keitel9fd07382013-05-02 15:37:44 -07004006 schedule_delayed_work(&chip->eoc_work,
4007 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
4008 return;
4009
4010stop_eoc:
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004011 vbat_low_count = 0;
David Keitel9fd07382013-05-02 15:37:44 -07004012 count = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004013 pm_relax(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07004014}
4015
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004016static void
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004017qpnp_chg_insertion_ocv_work(struct work_struct *work)
4018{
4019 struct qpnp_chg_chip *chip = container_of(work,
4020 struct qpnp_chg_chip, insertion_ocv_work);
4021 u8 bat_if_sts = 0, charge_en = 0;
4022 int rc;
4023
4024 chip->insertion_ocv_uv = get_prop_battery_voltage_now(chip);
4025
4026 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
4027 if (rc)
4028 pr_err("failed to read bat_if sts %d\n", rc);
4029
4030 rc = qpnp_chg_read(chip, &charge_en,
4031 chip->chgr_base + CHGR_CHG_CTRL, 1);
4032 if (rc)
4033 pr_err("failed to read bat_if sts %d\n", rc);
4034
4035 pr_debug("batfet sts = %02x, charge_en = %02x ocv = %d\n",
4036 bat_if_sts, charge_en, chip->insertion_ocv_uv);
4037 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4038 pr_debug("psy changed batt_psy\n");
4039 power_supply_changed(&chip->batt_psy);
4040}
4041
4042static void
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004043qpnp_chg_soc_check_work(struct work_struct *work)
4044{
4045 struct qpnp_chg_chip *chip = container_of(work,
4046 struct qpnp_chg_chip, soc_check_work);
4047
4048 get_prop_capacity(chip);
4049}
4050
David Keitel0c1a4532013-03-21 16:39:06 -07004051#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08004052static void
4053qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
4054{
4055 struct qpnp_chg_chip *chip = ctx;
4056 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07004057 int temp;
David Keitel454ee842013-03-08 16:19:11 -08004058
4059 if (state >= ADC_TM_STATE_NUM) {
4060 pr_err("invalid notification %d\n", state);
4061 return;
4062 }
4063
David Keitel1219a802013-03-21 16:37:21 -07004064 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08004065
David Keitel1219a802013-03-21 16:37:21 -07004066 pr_debug("temp = %d state = %s\n", temp,
4067 state == ADC_TM_WARM_STATE ? "warm" : "cool");
4068
4069 if (state == ADC_TM_WARM_STATE) {
David Keitel410ee0d2014-02-20 16:48:04 -08004070 if (temp >= chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07004071 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08004072 bat_warm = true;
4073 bat_cool = false;
4074 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07004075 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07004076 chip->adc_param.state_request =
4077 ADC_TM_COOL_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08004078 } else if (temp >=
David Keitel1219a802013-03-21 16:37:21 -07004079 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07004080 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08004081 bat_warm = false;
4082 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07004083
4084 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07004085 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07004086 chip->adc_param.state_request =
4087 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08004088 }
4089 } else {
David Keitel410ee0d2014-02-20 16:48:04 -08004090 if (temp <= chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07004091 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08004092 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07004093 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08004094 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07004095 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07004096 chip->adc_param.state_request =
4097 ADC_TM_WARM_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08004098 } else if (temp <=
David Keitel1219a802013-03-21 16:37:21 -07004099 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07004100 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08004101 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07004102 bat_cool = false;
4103
David Keitel0c1a4532013-03-21 16:39:06 -07004104 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07004105 chip->adc_param.high_temp = chip->warm_bat_decidegc;
4106 chip->adc_param.state_request =
4107 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08004108 }
4109 }
4110
4111 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07004112 chip->bat_is_cool = bat_cool;
4113 chip->bat_is_warm = bat_warm;
4114
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004115 /**
4116 * set appropriate voltages and currents.
4117 *
4118 * Note that when the battery is hot or cold, the charger
4119 * driver will not resume with SoC. Only vbatdet is used to
4120 * determine resume of charging.
4121 */
David Keitel59fbb762014-02-05 16:46:24 -08004122 if (bat_cool || bat_warm) {
4123 chip->resuming_charging = false;
4124 qpnp_chg_set_appropriate_vbatdet(chip);
4125
4126 /* To avoid ARB, only vbatdet is configured in
4127 * warm/cold zones. Once vbat < vbatdet the
4128 * appropriate vddmax/ibatmax adjustments will
4129 * be made in the fast charge interrupt. */
4130 bypass_vbatdet_comp(chip, 1);
4131 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4132 qpnp_chg_charge_en(chip, chip->charging_disabled);
4133 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4134 } else {
4135 bypass_vbatdet_comp(chip, 0);
4136 /* restore normal parameters */
4137 qpnp_chg_set_appropriate_vbatdet(chip);
4138 qpnp_chg_set_appropriate_vddmax(chip);
4139 qpnp_chg_set_appropriate_battery_current(chip);
4140 }
David Keitel454ee842013-03-08 16:19:11 -08004141 }
4142
David Keitelec3c09802013-06-13 13:05:30 -07004143 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
4144 chip->bat_is_warm, chip->bat_is_cool,
4145 chip->adc_param.low_temp, chip->adc_param.high_temp);
4146
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004147 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07004148 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07004149}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004150
David Keitelec3c09802013-06-13 13:05:30 -07004151#define MIN_COOL_TEMP -300
4152#define MAX_WARM_TEMP 1000
4153
4154static int
4155qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
4156 enum power_supply_property psp, int temp_degc)
4157{
4158 int rc = 0;
4159
4160 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
4161 pr_err("Bad temperature request %d\n", temp_degc);
4162 return -EINVAL;
4163 }
4164
4165 mutex_lock(&chip->jeita_configure_lock);
4166 switch (psp) {
4167 case POWER_SUPPLY_PROP_COOL_TEMP:
4168 if (temp_degc >=
4169 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
4170 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
4171 temp_degc, chip->warm_bat_decidegc,
4172 HYSTERISIS_DECIDEGC);
4173 rc = -EINVAL;
4174 goto mutex_unlock;
4175 }
4176 if (chip->bat_is_cool)
4177 chip->adc_param.high_temp =
4178 temp_degc + HYSTERISIS_DECIDEGC;
4179 else if (!chip->bat_is_warm)
4180 chip->adc_param.low_temp = temp_degc;
4181
4182 chip->cool_bat_decidegc = temp_degc;
4183 break;
4184 case POWER_SUPPLY_PROP_WARM_TEMP:
4185 if (temp_degc <=
4186 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
4187 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
4188 temp_degc, chip->warm_bat_decidegc,
4189 HYSTERISIS_DECIDEGC);
4190 rc = -EINVAL;
4191 goto mutex_unlock;
4192 }
4193 if (chip->bat_is_warm)
4194 chip->adc_param.low_temp =
4195 temp_degc - HYSTERISIS_DECIDEGC;
4196 else if (!chip->bat_is_cool)
4197 chip->adc_param.high_temp = temp_degc;
4198
4199 chip->warm_bat_decidegc = temp_degc;
4200 break;
4201 default:
4202 rc = -EINVAL;
4203 goto mutex_unlock;
4204 }
4205
4206 schedule_work(&chip->adc_measure_work);
4207
4208mutex_unlock:
4209 mutex_unlock(&chip->jeita_configure_lock);
4210 return rc;
David Keitel454ee842013-03-08 16:19:11 -08004211}
4212
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004213#define POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS 20
4214#define POWER_STAGE_REDUCE_MAX_VBAT_UV 3900000
4215#define POWER_STAGE_REDUCE_MIN_VCHG_UV 4800000
4216#define POWER_STAGE_SEL_MASK 0x0F
4217#define POWER_STAGE_REDUCED 0x01
4218#define POWER_STAGE_DEFAULT 0x0F
4219static bool
4220qpnp_chg_is_power_stage_reduced(struct qpnp_chg_chip *chip)
4221{
4222 int rc;
4223 u8 reg;
4224
4225 rc = qpnp_chg_read(chip, &reg,
4226 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
4227 1);
4228 if (rc) {
4229 pr_err("Error %d reading power stage register\n", rc);
4230 return false;
4231 }
4232
4233 if ((reg & POWER_STAGE_SEL_MASK) == POWER_STAGE_DEFAULT)
4234 return false;
4235
4236 return true;
4237}
4238
4239static int
4240qpnp_chg_power_stage_set(struct qpnp_chg_chip *chip, bool reduce)
4241{
4242 int rc;
4243 u8 reg = 0xA5;
4244
4245 rc = qpnp_chg_write(chip, &reg,
4246 chip->buck_base + SEC_ACCESS,
4247 1);
4248 if (rc) {
4249 pr_err("Error %d writing 0xA5 to buck's 0x%x reg\n",
4250 rc, SEC_ACCESS);
4251 return rc;
4252 }
4253
4254 reg = POWER_STAGE_DEFAULT;
4255 if (reduce)
4256 reg = POWER_STAGE_REDUCED;
4257 rc = qpnp_chg_write(chip, &reg,
4258 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
4259 1);
4260
4261 if (rc)
4262 pr_err("Error %d writing 0x%x power stage register\n", rc, reg);
4263 return rc;
4264}
4265
4266static int
4267qpnp_chg_get_vusbin_uv(struct qpnp_chg_chip *chip)
4268{
4269 int rc = 0;
4270 struct qpnp_vadc_result results;
4271
4272 rc = qpnp_vadc_read(chip->vadc_dev, USBIN, &results);
4273 if (rc) {
4274 pr_err("Unable to read vbat rc=%d\n", rc);
4275 return 0;
4276 }
4277 return results.physical;
4278}
4279
4280static
4281int get_vusb_averaged(struct qpnp_chg_chip *chip, int sample_count)
4282{
4283 int vusb_uv = 0;
4284 int i;
4285
4286 /* avoid overflows */
4287 if (sample_count > 256)
4288 sample_count = 256;
4289
4290 for (i = 0; i < sample_count; i++)
4291 vusb_uv += qpnp_chg_get_vusbin_uv(chip);
4292
4293 vusb_uv = vusb_uv / sample_count;
4294 return vusb_uv;
4295}
4296
4297static
4298int get_vbat_averaged(struct qpnp_chg_chip *chip, int sample_count)
4299{
4300 int vbat_uv = 0;
4301 int i;
4302
4303 /* avoid overflows */
4304 if (sample_count > 256)
4305 sample_count = 256;
4306
4307 for (i = 0; i < sample_count; i++)
4308 vbat_uv += get_prop_battery_voltage_now(chip);
4309
4310 vbat_uv = vbat_uv / sample_count;
4311 return vbat_uv;
4312}
4313
4314static void
4315qpnp_chg_reduce_power_stage(struct qpnp_chg_chip *chip)
4316{
4317 struct timespec ts;
4318 bool power_stage_reduced_in_hw = qpnp_chg_is_power_stage_reduced(chip);
4319 bool reduce_power_stage = false;
4320 int vbat_uv = get_vbat_averaged(chip, 16);
4321 int vusb_uv = get_vusb_averaged(chip, 16);
4322 bool fast_chg =
4323 (get_prop_charge_type(chip) == POWER_SUPPLY_CHARGE_TYPE_FAST);
4324 static int count_restore_power_stage;
4325 static int count_reduce_power_stage;
4326 bool vchg_loop = get_prop_vchg_loop(chip);
4327 bool ichg_loop = qpnp_chg_is_ichg_loop_active(chip);
4328 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
4329 bool usb_ma_above_wall =
4330 (qpnp_chg_usb_iusbmax_get(chip) > USB_WALL_THRESHOLD_MA);
4331
4332 if (fast_chg
4333 && usb_present
4334 && usb_ma_above_wall
4335 && vbat_uv < POWER_STAGE_REDUCE_MAX_VBAT_UV
4336 && vusb_uv > POWER_STAGE_REDUCE_MIN_VCHG_UV)
4337 reduce_power_stage = true;
4338
4339 if ((usb_present && usb_ma_above_wall)
4340 && (vchg_loop || ichg_loop))
4341 reduce_power_stage = true;
4342
4343 if (power_stage_reduced_in_hw && !reduce_power_stage) {
4344 count_restore_power_stage++;
4345 count_reduce_power_stage = 0;
4346 } else if (!power_stage_reduced_in_hw && reduce_power_stage) {
4347 count_reduce_power_stage++;
4348 count_restore_power_stage = 0;
4349 } else if (power_stage_reduced_in_hw == reduce_power_stage) {
4350 count_restore_power_stage = 0;
4351 count_reduce_power_stage = 0;
4352 }
4353
4354 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",
4355 power_stage_reduced_in_hw, reduce_power_stage,
4356 usb_present, usb_ma_above_wall,
4357 vbat_uv, vusb_uv, fast_chg,
4358 ichg_loop, vchg_loop,
4359 count_restore_power_stage, count_reduce_power_stage);
4360
4361 if (!power_stage_reduced_in_hw && reduce_power_stage) {
4362 if (count_reduce_power_stage >= 2) {
4363 qpnp_chg_power_stage_set(chip, true);
4364 power_stage_reduced_in_hw = true;
4365 }
4366 }
4367
4368 if (power_stage_reduced_in_hw && !reduce_power_stage) {
4369 if (count_restore_power_stage >= 6
4370 || (!usb_present || !usb_ma_above_wall)) {
4371 qpnp_chg_power_stage_set(chip, false);
4372 power_stage_reduced_in_hw = false;
4373 }
4374 }
4375
4376 if (usb_present && usb_ma_above_wall) {
4377 getnstimeofday(&ts);
4378 ts.tv_sec += POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS;
4379 alarm_start_range(&chip->reduce_power_stage_alarm,
4380 timespec_to_ktime(ts),
4381 timespec_to_ktime(ts));
4382 } else {
4383 pr_debug("stopping power stage workaround\n");
4384 chip->power_stage_workaround_running = false;
4385 }
4386}
4387
4388static void
David Keitel6e63bd52013-09-06 18:00:03 -07004389qpnp_chg_batfet_lcl_work(struct work_struct *work)
4390{
4391 struct qpnp_chg_chip *chip = container_of(work,
4392 struct qpnp_chg_chip, batfet_lcl_work);
4393
4394 mutex_lock(&chip->batfet_vreg_lock);
4395 if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
4396 qpnp_chg_is_dc_chg_plugged_in(chip)) {
4397 qpnp_chg_regulator_batfet_set(chip, 1);
4398 pr_debug("disabled ULPM\n");
4399 } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
4400 && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
4401 qpnp_chg_regulator_batfet_set(chip, 0);
4402 pr_debug("enabled ULPM\n");
4403 }
4404 mutex_unlock(&chip->batfet_vreg_lock);
4405}
4406
4407static void
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004408qpnp_chg_reduce_power_stage_work(struct work_struct *work)
4409{
4410 struct qpnp_chg_chip *chip = container_of(work,
4411 struct qpnp_chg_chip, reduce_power_stage_work);
4412
4413 qpnp_chg_reduce_power_stage(chip);
4414}
4415
4416static void
4417qpnp_chg_reduce_power_stage_callback(struct alarm *alarm)
4418{
4419 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
4420 reduce_power_stage_alarm);
4421
4422 schedule_work(&chip->reduce_power_stage_work);
4423}
4424
David Keitelbe208252013-01-31 14:49:25 -08004425static int
David Keitel432e1232013-06-05 16:10:18 -07004426qpnp_dc_power_set_property(struct power_supply *psy,
4427 enum power_supply_property psp,
4428 const union power_supply_propval *val)
4429{
4430 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
4431 dc_psy);
4432 int rc = 0;
4433
4434 switch (psp) {
4435 case POWER_SUPPLY_PROP_CURRENT_MAX:
4436 if (!val->intval)
4437 break;
4438
4439 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
4440 if (rc) {
4441 pr_err("Error setting idcmax property %d\n", rc);
4442 return rc;
4443 }
4444 chip->maxinput_dc_ma = (val->intval / 1000);
4445
4446 break;
4447 default:
4448 return -EINVAL;
4449 }
4450
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004451 pr_debug("psy changed dc_psy\n");
David Keitel432e1232013-06-05 16:10:18 -07004452 power_supply_changed(&chip->dc_psy);
4453 return rc;
4454}
4455
4456static int
David Keitelbe208252013-01-31 14:49:25 -08004457qpnp_batt_power_set_property(struct power_supply *psy,
4458 enum power_supply_property psp,
4459 const union power_supply_propval *val)
4460{
4461 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
4462 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004463 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08004464
4465 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07004466 case POWER_SUPPLY_PROP_COOL_TEMP:
4467 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
4468 break;
4469 case POWER_SUPPLY_PROP_WARM_TEMP:
4470 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
4471 break;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08004472 case POWER_SUPPLY_PROP_CAPACITY:
4473 chip->fake_battery_soc = val->intval;
4474 power_supply_changed(&chip->batt_psy);
4475 break;
David Keitelbe208252013-01-31 14:49:25 -08004476 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
4477 chip->charging_disabled = !(val->intval);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004478 if (chip->charging_disabled) {
4479 /* disable charging */
4480 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4481 qpnp_chg_force_run_on_batt(chip,
4482 chip->charging_disabled);
4483 } else {
4484 /* enable charging */
4485 qpnp_chg_force_run_on_batt(chip,
4486 chip->charging_disabled);
4487 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4488 }
David Keitelbe208252013-01-31 14:49:25 -08004489 break;
4490 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
4491 qpnp_batt_system_temp_level_set(chip, val->intval);
4492 break;
David Keitel337bd862013-07-15 21:42:58 -07004493 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel820a90d2014-03-25 18:18:04 -07004494 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
4495 !(qpnp_is_dc_higher_prio(chip)
4496 && qpnp_chg_is_dc_chg_plugged_in(chip)))
David Keitel7b0568482013-12-02 14:47:42 -08004497 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
David Keitel337bd862013-07-15 21:42:58 -07004498 break;
David Keitel2586f0a2013-08-20 10:02:26 -07004499 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
4500 qpnp_chg_iusb_trim_set(chip, val->intval);
4501 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004502 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
David Keitel820a90d2014-03-25 18:18:04 -07004503 if (val->intval)
4504 qpnp_chg_input_current_settled(chip);
4505 else
4506 chip->aicl_settled = false;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004507 break;
David Keitel337bd862013-07-15 21:42:58 -07004508 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
4509 qpnp_chg_vinmin_set(chip, val->intval / 1000);
4510 break;
Fenglin Wuc64e9942014-08-22 13:47:34 +08004511 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
4512 rc = qpnp_chg_bypass_vchg_loop_debouncer(chip, !!val->intval);
4513 break;
David Keitelbe208252013-01-31 14:49:25 -08004514 default:
4515 return -EINVAL;
4516 }
4517
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004518 pr_debug("psy changed batt_psy\n");
David Keitelbe208252013-01-31 14:49:25 -08004519 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004520 return rc;
David Keitelbe208252013-01-31 14:49:25 -08004521}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004522
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004523static int
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004524qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07004525{
David Keitelfe51cb92013-04-02 19:42:58 -07004526 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07004527 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07004528 if (chip->type == SMBB)
4529 chip->flags |= BOOST_FLASH_WA;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004530 if (chip->type == SMBBP) {
4531 struct device_node *revid_dev_node;
4532 struct pmic_revid_data *revid_data;
4533
4534 chip->flags |= BOOST_FLASH_WA;
4535
4536 revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
4537 "qcom,pmic-revid", 0);
4538 if (!revid_dev_node) {
4539 pr_err("Missing qcom,pmic-revid property\n");
4540 return -EINVAL;
4541 }
4542 revid_data = get_revid_data(revid_dev_node);
4543 if (IS_ERR(revid_data)) {
4544 pr_err("Couldnt get revid data rc = %ld\n",
4545 PTR_ERR(revid_data));
4546 return PTR_ERR(revid_data);
4547 }
4548
4549 if (revid_data->rev4 < PM8226_V2P1_REV4
4550 || ((revid_data->rev4 == PM8226_V2P1_REV4)
4551 && (revid_data->rev3 <= PM8226_V2P1_REV3))) {
4552 chip->flags |= POWER_STAGE_WA;
4553 }
4554 }
4555 return 0;
David Keiteld681cda2012-10-02 15:44:21 -07004556}
4557
David Keitel0f35be42013-04-16 11:10:40 -07004558static int
4559qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
4560{
4561 int rc = 0;
4562 struct resource *resource;
4563 struct spmi_resource *spmi_resource;
4564 u8 subtype;
4565 struct spmi_device *spmi = chip->spmi;
4566
4567 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
4568 if (!spmi_resource) {
4569 pr_err("qpnp_chg: spmi resource absent\n");
4570 return rc;
4571 }
4572
4573 resource = spmi_get_resource(spmi, spmi_resource,
4574 IORESOURCE_MEM, 0);
4575 if (!(resource && resource->start)) {
4576 pr_err("node %s IO resource absent!\n",
4577 spmi->dev.of_node->full_name);
4578 return rc;
4579 }
4580
4581 rc = qpnp_chg_read(chip, &subtype,
4582 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4583 if (rc) {
4584 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4585 return rc;
4586 }
4587
4588 switch (subtype) {
4589 case SMBB_CHGR_SUBTYPE:
4590 case SMBBP_CHGR_SUBTYPE:
4591 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004592 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004593 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004594 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004595 pr_err("Unable to get fast-chg-on irq\n");
4596 return rc;
4597 }
4598
David Keitel47185a62013-05-15 18:54:10 -07004599 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004600 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004601 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004602 pr_err("Unable to get trkl-chg-on irq\n");
4603 return rc;
4604 }
4605
David Keitel47185a62013-05-15 18:54:10 -07004606 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004607 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07004608 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004609 pr_err("Unable to get chg_failed irq\n");
4610 return rc;
4611 }
4612
David Keitel47185a62013-05-15 18:54:10 -07004613 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07004614 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07004615 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07004616 pr_err("Unable to get fast-chg-on irq\n");
4617 return rc;
4618 }
4619
David Keitel47185a62013-05-15 18:54:10 -07004620 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004621 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07004622 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004623 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004624 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004625 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004626 return rc;
4627 }
4628
David Keitel47185a62013-05-15 18:54:10 -07004629 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004630 qpnp_chg_chgr_chg_fastchg_irq_handler,
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08004631 IRQF_TRIGGER_RISING |
4632 IRQF_TRIGGER_FALLING,
David Keitel0f35be42013-04-16 11:10:40 -07004633 "fast-chg-on", chip);
4634 if (rc < 0) {
4635 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004636 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004637 return rc;
4638 }
4639
David Keitel47185a62013-05-15 18:54:10 -07004640 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004641 qpnp_chg_chgr_chg_trklchg_irq_handler,
4642 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004643 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004644 if (rc < 0) {
4645 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004646 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004647 return rc;
4648 }
David Keitel9fd07382013-05-02 15:37:44 -07004649
4650 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07004651 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07004652 qpnp_chg_vbatdet_lo_irq_handler,
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004653 IRQF_TRIGGER_RISING,
David Keitel9fd07382013-05-02 15:37:44 -07004654 "vbat-det-lo", chip);
4655 if (rc < 0) {
4656 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004657 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07004658 return rc;
4659 }
4660
David Keitelbf6a1062014-01-23 10:57:36 -08004661 qpnp_chg_irq_wake_enable(&chip->chg_trklchg);
4662 qpnp_chg_irq_wake_enable(&chip->chg_failed);
David Keitel47185a62013-05-15 18:54:10 -07004663 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitelbf6a1062014-01-23 10:57:36 -08004664 qpnp_chg_irq_wake_enable(&chip->chg_vbatdet_lo);
David Keitel0f35be42013-04-16 11:10:40 -07004665
4666 break;
4667 case SMBB_BAT_IF_SUBTYPE:
4668 case SMBBP_BAT_IF_SUBTYPE:
4669 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004670 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004671 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07004672 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004673 pr_err("Unable to get batt-pres irq\n");
4674 return rc;
4675 }
David Keitel47185a62013-05-15 18:54:10 -07004676 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004677 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07004678 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
4679 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07004680 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004681 if (rc < 0) {
4682 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004683 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004684 return rc;
4685 }
4686
David Keitelbf6a1062014-01-23 10:57:36 -08004687 qpnp_chg_irq_wake_enable(&chip->batt_pres);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004688
4689 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
4690 spmi_resource, "bat-temp-ok");
4691 if (chip->batt_temp_ok.irq < 0) {
4692 pr_err("Unable to get bat-temp-ok irq\n");
4693 return rc;
4694 }
4695 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
4696 qpnp_chg_bat_if_batt_temp_irq_handler,
4697 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4698 "bat-temp-ok", chip);
4699 if (rc < 0) {
4700 pr_err("Can't request %d bat-temp-ok irq: %d\n",
4701 chip->batt_temp_ok.irq, rc);
4702 return rc;
4703 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08004704 qpnp_chg_bat_if_batt_temp_irq_handler(0, chip);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004705
David Keitelbf6a1062014-01-23 10:57:36 -08004706 qpnp_chg_irq_wake_enable(&chip->batt_temp_ok);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004707
David Keitel0f35be42013-04-16 11:10:40 -07004708 break;
David Keitel337bd862013-07-15 21:42:58 -07004709 case SMBB_BUCK_SUBTYPE:
4710 case SMBBP_BUCK_SUBTYPE:
4711 case SMBCL_BUCK_SUBTYPE:
David Keitel337bd862013-07-15 21:42:58 -07004712 break;
4713
David Keitel0f35be42013-04-16 11:10:40 -07004714 case SMBB_USB_CHGPTH_SUBTYPE:
4715 case SMBBP_USB_CHGPTH_SUBTYPE:
4716 case SMBCL_USB_CHGPTH_SUBTYPE:
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004717 if (chip->ovp_monitor_enable) {
4718 chip->coarse_det_usb.irq =
4719 spmi_get_irq_byname(spmi,
4720 spmi_resource, "coarse-det-usb");
4721 if (chip->coarse_det_usb.irq < 0) {
4722 pr_err("Can't get coarse-det irq\n");
4723 return rc;
4724 }
4725 rc = devm_request_irq(chip->dev,
4726 chip->coarse_det_usb.irq,
4727 qpnp_chg_coarse_det_usb_irq_handler,
4728 IRQF_TRIGGER_RISING |
4729 IRQF_TRIGGER_FALLING,
4730 "coarse-det-usb", chip);
4731 if (rc < 0) {
4732 pr_err("Can't req %d coarse-det: %d\n",
4733 chip->coarse_det_usb.irq, rc);
4734 return rc;
4735 }
4736 }
4737
David Keitel47185a62013-05-15 18:54:10 -07004738 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004739 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004740 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004741 pr_err("Unable to get usbin irq\n");
4742 return rc;
4743 }
David Keitel47185a62013-05-15 18:54:10 -07004744 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004745 qpnp_chg_usb_usbin_valid_irq_handler,
4746 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004747 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004748 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004749 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004750 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004751 return rc;
4752 }
David Keitel344c6972013-04-09 19:28:21 -07004753
David Keitel47185a62013-05-15 18:54:10 -07004754 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07004755 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07004756 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07004757 pr_err("Unable to get chg-gone irq\n");
4758 return rc;
4759 }
David Keitel47185a62013-05-15 18:54:10 -07004760 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07004761 qpnp_chg_usb_chg_gone_irq_handler,
4762 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07004763 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07004764 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004765 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004766 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07004767 return rc;
4768 }
David Keitel47185a62013-05-15 18:54:10 -07004769
David Keitel0b62bdd2013-07-10 17:30:51 -07004770 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4771 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4772 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
4773 spmi_resource, "usb-ocp");
4774 if (chip->usb_ocp.irq < 0) {
4775 pr_err("Unable to get usbin irq\n");
4776 return rc;
4777 }
4778 rc = devm_request_irq(chip->dev,
4779 chip->usb_ocp.irq,
4780 qpnp_chg_usb_usb_ocp_irq_handler,
4781 IRQF_TRIGGER_RISING, "usb-ocp", chip);
4782 if (rc < 0) {
4783 pr_err("Can't request %d usb-ocp: %d\n",
4784 chip->usb_ocp.irq, rc);
4785 return rc;
4786 }
4787
David Keitelbf6a1062014-01-23 10:57:36 -08004788 qpnp_chg_irq_wake_enable(&chip->usb_ocp);
David Keitel0b62bdd2013-07-10 17:30:51 -07004789 }
4790
David Keitelbf6a1062014-01-23 10:57:36 -08004791 qpnp_chg_irq_wake_enable(&chip->usbin_valid);
4792 qpnp_chg_irq_wake_enable(&chip->chg_gone);
David Keitel0f35be42013-04-16 11:10:40 -07004793 break;
4794 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004795 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004796 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004797 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004798 pr_err("Unable to get dcin irq\n");
4799 return -rc;
4800 }
David Keitel47185a62013-05-15 18:54:10 -07004801 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004802 qpnp_chg_dc_dcin_valid_irq_handler,
4803 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004804 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004805 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004806 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004807 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004808 return rc;
4809 }
4810
David Keitelbf6a1062014-01-23 10:57:36 -08004811 qpnp_chg_irq_wake_enable(&chip->dcin_valid);
David Keitel0f35be42013-04-16 11:10:40 -07004812 break;
4813 }
4814 }
4815
4816 return rc;
4817}
4818
Xiaozhe Shica289e02013-06-19 13:24:51 -07004819static int
4820qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
4821{
4822 struct bms_battery_data batt_data;
4823 struct device_node *node;
4824 struct qpnp_vadc_result result;
4825 int rc;
4826
4827 node = of_find_node_by_name(chip->spmi->dev.of_node,
4828 "qcom,battery-data");
4829 if (node) {
4830 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004831 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07004832 if (rc) {
4833 pr_err("error reading batt id channel = %d, rc = %d\n",
4834 LR_MUX2_BAT_ID, rc);
4835 return rc;
4836 }
4837
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07004838 batt_data.max_voltage_uv = -1;
4839 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07004840 rc = of_batterydata_read_data(node,
4841 &batt_data, result.physical);
4842 if (rc) {
4843 pr_err("failed to read battery data: %d\n", rc);
4844 return rc;
4845 }
4846
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004847 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07004848 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004849 chip->safe_voltage_mv = chip->max_voltage_mv
4850 + MAX_DELTA_VDD_MAX_MV;
4851 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004852 if (batt_data.iterm_ua >= 0)
4853 chip->term_current = batt_data.iterm_ua / 1000;
4854 }
4855
4856 return 0;
4857}
4858
David Keitel80668952012-07-27 14:25:49 -07004859#define WDOG_EN_BIT BIT(7)
4860static int
4861qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
4862 struct spmi_resource *spmi_resource)
4863{
4864 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004865 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07004866 struct regulator_init_data *init_data;
4867 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07004868
4869 switch (subtype) {
4870 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004871 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004872 case SMBCL_CHGR_SUBTYPE:
Prasad Sodagudic3678012013-09-23 12:01:19 +05304873 qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
4874
David Keitel80668952012-07-27 14:25:49 -07004875 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
4876 if (rc) {
4877 pr_debug("failed setting min_voltage rc=%d\n", rc);
4878 return rc;
4879 }
David Keitel80668952012-07-27 14:25:49 -07004880 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
4881 if (rc) {
4882 pr_debug("failed setting safe_voltage rc=%d\n", rc);
4883 return rc;
4884 }
David Keitel454ee842013-03-08 16:19:11 -08004885 rc = qpnp_chg_vbatdet_set(chip,
4886 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08004887 if (rc) {
4888 pr_debug("failed setting resume_voltage rc=%d\n", rc);
4889 return rc;
4890 }
David Keitel80668952012-07-27 14:25:49 -07004891 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
4892 if (rc) {
4893 pr_debug("failed setting ibatmax rc=%d\n", rc);
4894 return rc;
4895 }
David Keitel365c4c42013-03-08 16:20:40 -08004896 if (chip->term_current) {
4897 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
4898 if (rc) {
4899 pr_debug("failed setting ibatterm rc=%d\n", rc);
4900 return rc;
4901 }
David Keitel80668952012-07-27 14:25:49 -07004902 }
David Keitel5d44fa52012-12-03 16:37:31 -08004903 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
4904 if (rc) {
4905 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
4906 return rc;
4907 }
David Keitela4b7b592013-04-11 18:34:35 -07004908 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
4909 if (rc) {
4910 pr_debug("failed setting tchg_mins rc=%d\n", rc);
4911 return rc;
4912 }
4913
David Keitel80668952012-07-27 14:25:49 -07004914 /* HACK: Disable wdog */
4915 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
4916 0xFF, 0xA0, 1);
4917
David Keitelb4e43542013-04-09 17:30:41 -07004918 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07004919 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4920 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07004921 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07004922
David Keitel79e08322014-04-21 14:17:05 -07004923 /* HACK: trkl stuck workaround */
4924
4925 rc = qpnp_chg_masked_write(chip,
4926 chip->chgr_base + SEC_ACCESS,
4927 0xFF,
4928 0xA5, 1);
4929
4930 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4931 CHG_OVR0,
4932 0xFF, 0x00, 1);
4933
4934 rc = qpnp_chg_masked_write(chip,
4935 chip->chgr_base + SEC_ACCESS,
4936 0xFF,
4937 0xA5, 1);
4938
4939 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4940 CHG_TRICKLE_CLAMP,
4941 0xFF, 0x00, 1);
Chunmei Cai661a7cd2014-08-05 17:31:54 +08004942
4943 rc = qpnp_chg_read(chip, &chip->chg_temp_thresh_default,
4944 chip->chgr_base + CHGR_CHG_TEMP_THRESH, 1);
4945 if (rc) {
4946 pr_debug("read CHG_TEMP_THRESH failed, rc = %d\n", rc);
4947 chip->chg_temp_thresh_default =
4948 CHG_TEMP_THRESH_DEFAULT;
4949 }
4950
4951 init_data = of_get_regulator_init_data(chip->dev,
4952 spmi_resource->of_node);
4953 if (!init_data) {
4954 pr_err("unable to get regulator init data for flash_wa\n");
4955 return -ENOMEM;
4956 }
4957
4958 if (init_data->constraints.name) {
4959 rdesc = &(chip->flash_wa_vreg.rdesc);
4960 rdesc->owner = THIS_MODULE;
4961 rdesc->type = REGULATOR_VOLTAGE;
4962 rdesc->ops = &qpnp_chg_flash_wa_reg_ops;
4963 rdesc->name = init_data->constraints.name;
4964
4965 init_data->constraints.valid_ops_mask
4966 |= REGULATOR_CHANGE_STATUS;
4967
4968 chip->flash_wa_vreg.rdev =
4969 regulator_register(rdesc, chip->dev, init_data,
4970 chip, spmi_resource->of_node);
4971 if (IS_ERR(chip->flash_wa_vreg.rdev)) {
4972 rc = PTR_ERR(chip->flash_wa_vreg.rdev);
4973 chip->flash_wa_vreg.rdev = NULL;
4974 pr_err("Flash wa failed, rc=%d\n", rc);
4975 return rc;
4976 }
4977 }
David Keitel80668952012-07-27 14:25:49 -07004978 break;
4979 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004980 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004981 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004982 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
4983 if (rc)
4984 return rc;
4985
David Keitel9201df32013-01-10 18:38:34 -08004986 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07004987 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08004988 BUCK_VBAT_REG_NODE_SEL_BIT,
4989 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
4990 if (rc) {
4991 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
4992 return rc;
4993 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07004994
4995 rc = qpnp_chg_read(chip, &chip->trim_center,
4996 chip->buck_base + BUCK_CTRL_TRIM1, 1);
4997 if (rc) {
4998 pr_debug("failed to read trim center rc=%d\n", rc);
4999 return rc;
5000 }
5001 chip->trim_center >>= 4;
5002 pr_debug("trim center = %02x\n", chip->trim_center);
David Keitel80668952012-07-27 14:25:49 -07005003 break;
5004 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005005 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005006 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07005007 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07005008 switch (chip->bpd_detection) {
5009 case BPD_TYPE_BAT_THM:
5010 reg = BAT_THM_EN;
5011 break;
5012 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07005013 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07005014 break;
5015 case BPD_TYPE_BAT_THM_BAT_ID:
5016 reg = BAT_THM_EN | BAT_ID_EN;
5017 break;
5018 default:
5019 reg = BAT_THM_EN;
5020 break;
5021 }
David Keitel796882d2013-05-14 18:01:11 -07005022
5023 rc = qpnp_chg_masked_write(chip,
5024 chip->bat_if_base + BAT_IF_BPD_CTRL,
5025 BAT_IF_BPD_CTRL_SEL,
5026 reg, 1);
5027 if (rc) {
5028 pr_debug("failed to chose BPD rc=%d\n", rc);
5029 return rc;
5030 }
David Keitel85ae4342013-04-16 11:46:00 -07005031 /* Force on VREF_BAT_THM */
5032 rc = qpnp_chg_masked_write(chip,
5033 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5034 VREF_BATT_THERM_FORCE_ON,
5035 VREF_BATT_THERM_FORCE_ON, 1);
5036 if (rc) {
5037 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
5038 return rc;
5039 }
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07005040
5041 init_data = of_get_regulator_init_data(chip->dev,
5042 spmi_resource->of_node);
5043
5044 if (init_data->constraints.name) {
5045 rdesc = &(chip->batfet_vreg.rdesc);
5046 rdesc->owner = THIS_MODULE;
5047 rdesc->type = REGULATOR_VOLTAGE;
5048 rdesc->ops = &qpnp_chg_batfet_vreg_ops;
5049 rdesc->name = init_data->constraints.name;
5050
5051 init_data->constraints.valid_ops_mask
5052 |= REGULATOR_CHANGE_STATUS;
5053
5054 chip->batfet_vreg.rdev = regulator_register(rdesc,
5055 chip->dev, init_data, chip,
5056 spmi_resource->of_node);
5057 if (IS_ERR(chip->batfet_vreg.rdev)) {
5058 rc = PTR_ERR(chip->batfet_vreg.rdev);
5059 chip->batfet_vreg.rdev = NULL;
5060 if (rc != -EPROBE_DEFER)
5061 pr_err("batfet reg failed, rc=%d\n",
5062 rc);
5063 return rc;
5064 }
5065 }
David Keitel80668952012-07-27 14:25:49 -07005066 break;
5067 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005068 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005069 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07005070 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07005071 rc = qpnp_chg_masked_write(chip,
5072 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
5073 ENUM_T_STOP_BIT,
5074 ENUM_T_STOP_BIT, 1);
5075 if (rc) {
5076 pr_err("failed to write enum stop rc=%d\n", rc);
5077 return -ENXIO;
5078 }
5079 }
David Keiteld681cda2012-10-02 15:44:21 -07005080
David Keitel6dc4ed42013-05-17 11:08:58 -07005081 init_data = of_get_regulator_init_data(chip->dev,
5082 spmi_resource->of_node);
5083 if (!init_data) {
5084 pr_err("unable to allocate memory\n");
5085 return -ENOMEM;
5086 }
5087
5088 if (init_data->constraints.name) {
5089 if (of_get_property(chip->dev->of_node,
5090 "otg-parent-supply", NULL))
5091 init_data->supply_regulator = "otg-parent";
5092
5093 rdesc = &(chip->otg_vreg.rdesc);
5094 rdesc->owner = THIS_MODULE;
5095 rdesc->type = REGULATOR_VOLTAGE;
5096 rdesc->ops = &qpnp_chg_otg_reg_ops;
5097 rdesc->name = init_data->constraints.name;
5098
5099 init_data->constraints.valid_ops_mask
5100 |= REGULATOR_CHANGE_STATUS;
5101
5102 chip->otg_vreg.rdev = regulator_register(rdesc,
5103 chip->dev, init_data, chip,
5104 spmi_resource->of_node);
5105 if (IS_ERR(chip->otg_vreg.rdev)) {
5106 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07005107 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07005108 if (rc != -EPROBE_DEFER)
5109 pr_err("OTG reg failed, rc=%d\n", rc);
5110 return rc;
5111 }
5112 }
5113
David Keiteld681cda2012-10-02 15:44:21 -07005114 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08005115 chip->usb_chgpth_base + USB_OVP_CTL,
5116 USB_VALID_DEB_20MS,
5117 USB_VALID_DEB_20MS, 1);
5118
5119 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07005120 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
5121 ENUM_T_STOP_BIT,
5122 ENUM_T_STOP_BIT, 1);
5123
David Keitel344c6972013-04-09 19:28:21 -07005124 rc = qpnp_chg_masked_write(chip,
5125 chip->usb_chgpth_base + SEC_ACCESS,
5126 0xFF,
5127 0xA5, 1);
5128
5129 rc = qpnp_chg_masked_write(chip,
5130 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
5131 0xFF,
5132 0x80, 1);
5133
David Keitel0b62bdd2013-07-10 17:30:51 -07005134 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
5135 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
5136 rc = qpnp_chg_masked_write(chip,
5137 chip->usb_chgpth_base + USB_OCP_THR,
5138 OCP_THR_MASK,
5139 OCP_THR_900_MA, 1);
5140 if (rc)
5141 pr_err("Failed to configure OCP rc = %d\n", rc);
5142 }
5143
David Keitel80668952012-07-27 14:25:49 -07005144 break;
5145 case SMBB_DC_CHGPTH_SUBTYPE:
5146 break;
5147 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005148 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07005149 init_data = of_get_regulator_init_data(chip->dev,
5150 spmi_resource->of_node);
5151 if (!init_data) {
5152 pr_err("unable to allocate memory\n");
5153 return -ENOMEM;
5154 }
5155
5156 if (init_data->constraints.name) {
5157 if (of_get_property(chip->dev->of_node,
5158 "boost-parent-supply", NULL))
5159 init_data->supply_regulator = "boost-parent";
5160
5161 rdesc = &(chip->boost_vreg.rdesc);
5162 rdesc->owner = THIS_MODULE;
5163 rdesc->type = REGULATOR_VOLTAGE;
5164 rdesc->ops = &qpnp_chg_boost_reg_ops;
5165 rdesc->name = init_data->constraints.name;
5166
5167 init_data->constraints.valid_ops_mask
5168 |= REGULATOR_CHANGE_STATUS
5169 | REGULATOR_CHANGE_VOLTAGE;
5170
5171 chip->boost_vreg.rdev = regulator_register(rdesc,
5172 chip->dev, init_data, chip,
5173 spmi_resource->of_node);
5174 if (IS_ERR(chip->boost_vreg.rdev)) {
5175 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07005176 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07005177 if (rc != -EPROBE_DEFER)
5178 pr_err("boost reg failed, rc=%d\n", rc);
5179 return rc;
5180 }
5181 }
David Keitel80668952012-07-27 14:25:49 -07005182 break;
5183 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005184 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005185 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07005186 if (subtype == SMBB_MISC_SUBTYPE)
5187 chip->type = SMBB;
5188 else if (subtype == SMBBP_MISC_SUBTYPE)
5189 chip->type = SMBBP;
5190 else if (subtype == SMBCL_MISC_SUBTYPE)
5191 chip->type = SMBCL;
5192
David Keitel80668952012-07-27 14:25:49 -07005193 pr_debug("Setting BOOT_DONE\n");
5194 rc = qpnp_chg_masked_write(chip,
5195 chip->misc_base + CHGR_MISC_BOOT_DONE,
5196 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005197 rc = qpnp_chg_read(chip, &reg,
5198 chip->misc_base + MISC_REVISION2, 1);
5199 if (rc) {
5200 pr_err("failed to read revision register rc=%d\n", rc);
5201 return rc;
5202 }
David Keitel80668952012-07-27 14:25:49 -07005203
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005204 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07005205 break;
5206 default:
5207 pr_err("Invalid peripheral subtype\n");
5208 }
5209 return rc;
5210}
5211
David Keitel112ba9c2013-04-12 18:40:43 -07005212#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
5213do { \
5214 if (retval) \
5215 break; \
5216 \
5217 retval = of_property_read_u32(chip->spmi->dev.of_node, \
5218 "qcom," qpnp_dt_property, \
5219 &chip->prop); \
5220 \
5221 if ((retval == -EINVAL) && optional) \
5222 retval = 0; \
5223 else if (retval) \
5224 pr_err("Error reading " #qpnp_dt_property \
5225 " property rc = %d\n", rc); \
5226} while (0)
5227
5228static int
5229qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
5230{
5231 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07005232 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07005233
5234 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
5235 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
5236 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
5237 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
5238 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
5239 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
5240 if (rc)
5241 pr_err("failed to read required dt parameters %d\n", rc);
5242
5243 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
5244 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
5245 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
5246 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
5247 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07005248 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07005249 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
5250 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07005251 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
Prasad Sodagudic3678012013-09-23 12:01:19 +05305252 OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
David Keitelbdbae452014-01-14 17:19:50 -08005253 OF_PROP_READ(chip, vbatdet_max_err_mv, "vbatdet-maxerr-mv", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07005254
David Keitel112ba9c2013-04-12 18:40:43 -07005255 if (rc)
5256 return rc;
5257
David Keitel796882d2013-05-14 18:01:11 -07005258 rc = of_property_read_string(chip->spmi->dev.of_node,
5259 "qcom,bpd-detection", &bpd);
5260 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07005261 /* Select BAT_THM as default BPD scheme */
5262 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005263 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07005264 } else {
5265 chip->bpd_detection = get_bpd(bpd);
5266 if (chip->bpd_detection < 0) {
5267 pr_err("failed to determine bpd schema %d\n", rc);
5268 return rc;
5269 }
5270 }
5271
David Keitelbdbae452014-01-14 17:19:50 -08005272 if (!chip->vbatdet_max_err_mv)
5273 chip->vbatdet_max_err_mv = VBATDET_MAX_ERR_MV;
5274
David Keitel112ba9c2013-04-12 18:40:43 -07005275 /* Look up JEITA compliance parameters if cool and warm temp provided */
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005276 if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005277 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
5278 if (IS_ERR(chip->adc_tm_dev)) {
5279 rc = PTR_ERR(chip->adc_tm_dev);
5280 if (rc != -EPROBE_DEFER)
5281 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07005282 return rc;
5283 }
5284
5285 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
5286 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
5287 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
5288 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
5289 if (rc)
5290 return rc;
5291 }
5292
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08005293 /* Get the use-external-rsense property */
5294 chip->use_external_rsense = of_property_read_bool(
5295 chip->spmi->dev.of_node,
5296 "qcom,use-external-rsense");
5297
David Keitel89c17752013-06-28 14:52:48 -07005298 /* Get the btc-disabled property */
5299 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
5300 "qcom,btc-disabled");
5301
David Keitel2586f0a2013-08-20 10:02:26 -07005302 ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
5303 "qcom,ext-ovp-present");
5304
David Keitelcd2e1022014-05-02 17:25:15 -07005305 /* Check if external IOVP part is configured */
5306 chip->ext_ovp_isns_gpio = of_get_named_gpio(chip->spmi->dev.of_node,
5307 "qcom,ext-ovp-isns-enable-gpio", 0);
5308 if (gpio_is_valid(chip->ext_ovp_isns_gpio)) {
5309 ext_ovp_isns_present = true;
5310 rc = of_property_read_u32(chip->spmi->dev.of_node,
5311 "qcom,ext-ovp-isns-r-ohm", &ext_ovp_isns_r);
5312 if (rc)
5313 return rc;
5314 }
5315
David Keitel112ba9c2013-04-12 18:40:43 -07005316 /* Get the charging-disabled property */
5317 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
5318 "qcom,charging-disabled");
5319
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005320 chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
5321 "qcom,ovp-monitor-en");
5322
David Keitel8b68d2d2013-05-14 23:36:51 -07005323 /* Get the duty-cycle-100p property */
5324 chip->duty_cycle_100p = of_property_read_bool(
5325 chip->spmi->dev.of_node,
5326 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07005327
David Keitel112ba9c2013-04-12 18:40:43 -07005328 /* Get the fake-batt-values property */
5329 chip->use_default_batt_values =
5330 of_property_read_bool(chip->spmi->dev.of_node,
5331 "qcom,use-default-batt-values");
5332
5333 /* Disable charging when faking battery values */
5334 if (chip->use_default_batt_values)
5335 chip->charging_disabled = true;
5336
Zhenhua Huangdc335512013-10-30 11:45:15 +08005337 chip->power_stage_workaround_enable =
5338 of_property_read_bool(chip->spmi->dev.of_node,
5339 "qcom,power-stage-reduced");
5340
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07005341 chip->ibat_calibration_enabled =
5342 of_property_read_bool(chip->spmi->dev.of_node,
5343 "qcom,ibat-calibration-enabled");
David Keitel975b5352014-01-27 14:28:04 -08005344 chip->parallel_ovp_mode =
5345 of_property_read_bool(chip->spmi->dev.of_node,
5346 "qcom,parallel-ovp-mode");
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07005347
David Keitel112ba9c2013-04-12 18:40:43 -07005348 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
5349 &(chip->thermal_levels));
5350
5351 if (chip->thermal_levels > sizeof(int)) {
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305352 chip->thermal_mitigation = devm_kzalloc(chip->dev,
David Keitel112ba9c2013-04-12 18:40:43 -07005353 chip->thermal_levels,
5354 GFP_KERNEL);
5355
5356 if (chip->thermal_mitigation == NULL) {
5357 pr_err("thermal mitigation kzalloc() failed.\n");
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305358 return -ENOMEM;
David Keitel112ba9c2013-04-12 18:40:43 -07005359 }
5360
5361 chip->thermal_levels /= sizeof(int);
5362 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
5363 "qcom,thermal-mitigation",
5364 chip->thermal_mitigation, chip->thermal_levels);
5365 if (rc) {
5366 pr_err("qcom,thermal-mitigation missing in dt\n");
5367 return rc;
5368 }
5369 }
5370
5371 return rc;
5372}
5373
David Keitel80668952012-07-27 14:25:49 -07005374static int __devinit
5375qpnp_charger_probe(struct spmi_device *spmi)
5376{
5377 u8 subtype;
5378 struct qpnp_chg_chip *chip;
5379 struct resource *resource;
5380 struct spmi_resource *spmi_resource;
5381 int rc = 0;
5382
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305383 chip = devm_kzalloc(&spmi->dev,
5384 sizeof(struct qpnp_chg_chip), GFP_KERNEL);
David Keitel80668952012-07-27 14:25:49 -07005385 if (chip == NULL) {
5386 pr_err("kzalloc() failed.\n");
5387 return -ENOMEM;
5388 }
5389
David Keitelfd305ee2013-07-19 20:19:06 -07005390 chip->prev_usb_max_ma = -EINVAL;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08005391 chip->fake_battery_soc = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07005392 chip->dev = &(spmi->dev);
5393 chip->spmi = spmi;
5394
5395 chip->usb_psy = power_supply_get_by_name("usb");
5396 if (!chip->usb_psy) {
5397 pr_err("usb supply not found deferring probe\n");
5398 rc = -EPROBE_DEFER;
5399 goto fail_chg_enable;
5400 }
5401
David Keitelec3c09802013-06-13 13:05:30 -07005402 mutex_init(&chip->jeita_configure_lock);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005403 spin_lock_init(&chip->usbin_health_monitor_lock);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005404 alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
5405 qpnp_chg_reduce_power_stage_callback);
5406 INIT_WORK(&chip->reduce_power_stage_work,
5407 qpnp_chg_reduce_power_stage_work);
David Keitel6e63bd52013-09-06 18:00:03 -07005408 mutex_init(&chip->batfet_vreg_lock);
David Keitel8b9bd312014-01-15 14:44:00 -08005409 INIT_WORK(&chip->ocp_clear_work,
5410 qpnp_chg_ocp_clear_work);
David Keitel6e63bd52013-09-06 18:00:03 -07005411 INIT_WORK(&chip->batfet_lcl_work,
5412 qpnp_chg_batfet_lcl_work);
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005413 INIT_WORK(&chip->insertion_ocv_work,
5414 qpnp_chg_insertion_ocv_work);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005415
David Keitel112ba9c2013-04-12 18:40:43 -07005416 /* Get all device tree properties */
5417 rc = qpnp_charger_read_dt_props(chip);
5418 if (rc)
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305419 return rc;
David Keitel3dd5e0f2012-12-12 18:12:36 -08005420
David Keitelcd2e1022014-05-02 17:25:15 -07005421 if (ext_ovp_isns_present)
5422 chip->ext_ovp_ic_gpio_enabled = 0;
5423
Xiaozhe Shica289e02013-06-19 13:24:51 -07005424 /*
5425 * Check if bat_if is set in DT and make sure VADC is present
5426 * Also try loading the battery data profile if bat_if exists
5427 */
David Keiteldd87a172013-05-29 17:05:43 -07005428 spmi_for_each_container_dev(spmi_resource, spmi) {
5429 if (!spmi_resource) {
5430 pr_err("qpnp_chg: spmi resource absent\n");
5431 rc = -ENXIO;
5432 goto fail_chg_enable;
5433 }
5434
5435 resource = spmi_get_resource(spmi, spmi_resource,
5436 IORESOURCE_MEM, 0);
5437 if (!(resource && resource->start)) {
5438 pr_err("node %s IO resource absent!\n",
5439 spmi->dev.of_node->full_name);
5440 rc = -ENXIO;
5441 goto fail_chg_enable;
5442 }
5443
5444 rc = qpnp_chg_read(chip, &subtype,
5445 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
5446 if (rc) {
5447 pr_err("Peripheral subtype read failed rc=%d\n", rc);
5448 goto fail_chg_enable;
5449 }
5450
5451 if (subtype == SMBB_BAT_IF_SUBTYPE ||
5452 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07005453 subtype == SMBCL_BAT_IF_SUBTYPE) {
5454 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
5455 if (IS_ERR(chip->vadc_dev)) {
5456 rc = PTR_ERR(chip->vadc_dev);
5457 if (rc != -EPROBE_DEFER)
5458 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07005459 goto fail_chg_enable;
David Keitel42648fd2013-08-16 17:45:20 -07005460 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07005461
Chunmei Cai76705f02014-12-11 09:48:42 +08005462 if (subtype == SMBB_BAT_IF_SUBTYPE ||
5463 subtype == SMBBP_BAT_IF_SUBTYPE) {
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08005464 chip->iadc_dev = qpnp_get_iadc(chip->dev,
5465 "chg");
5466 if (IS_ERR(chip->iadc_dev)) {
5467 rc = PTR_ERR(chip->iadc_dev);
5468 if (rc != -EPROBE_DEFER)
5469 pr_err("iadc property missing\n");
5470 goto fail_chg_enable;
5471 }
5472 }
5473
Xiaozhe Shica289e02013-06-19 13:24:51 -07005474 rc = qpnp_chg_load_battery_data(chip);
5475 if (rc)
5476 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07005477 }
5478 }
5479
David Keitel80668952012-07-27 14:25:49 -07005480 spmi_for_each_container_dev(spmi_resource, spmi) {
5481 if (!spmi_resource) {
5482 pr_err("qpnp_chg: spmi resource absent\n");
5483 rc = -ENXIO;
5484 goto fail_chg_enable;
5485 }
5486
5487 resource = spmi_get_resource(spmi, spmi_resource,
5488 IORESOURCE_MEM, 0);
5489 if (!(resource && resource->start)) {
5490 pr_err("node %s IO resource absent!\n",
5491 spmi->dev.of_node->full_name);
5492 rc = -ENXIO;
5493 goto fail_chg_enable;
5494 }
5495
5496 rc = qpnp_chg_read(chip, &subtype,
5497 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
5498 if (rc) {
5499 pr_err("Peripheral subtype read failed rc=%d\n", rc);
5500 goto fail_chg_enable;
5501 }
5502
5503 switch (subtype) {
5504 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005505 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005506 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005507 chip->chgr_base = resource->start;
5508 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5509 if (rc) {
5510 pr_err("Failed to init subtype 0x%x rc=%d\n",
5511 subtype, rc);
5512 goto fail_chg_enable;
5513 }
5514 break;
5515 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005516 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005517 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005518 chip->buck_base = resource->start;
5519 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5520 if (rc) {
5521 pr_err("Failed to init subtype 0x%x rc=%d\n",
5522 subtype, rc);
5523 goto fail_chg_enable;
5524 }
David Keitel344c6972013-04-09 19:28:21 -07005525
5526 rc = qpnp_chg_masked_write(chip,
5527 chip->buck_base + SEC_ACCESS,
5528 0xFF,
5529 0xA5, 1);
5530
5531 rc = qpnp_chg_masked_write(chip,
5532 chip->buck_base + BUCK_VCHG_OV,
5533 0xff,
5534 0x00, 1);
5535
David Keiteldbc949b2013-07-11 10:56:03 -07005536 if (chip->duty_cycle_100p) {
5537 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
5538 1);
5539 if (rc) {
5540 pr_err("failed to set duty cycle %d\n",
5541 rc);
5542 goto fail_chg_enable;
5543 }
5544 }
5545
David Keitel80668952012-07-27 14:25:49 -07005546 break;
5547 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005548 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005549 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005550 chip->bat_if_base = resource->start;
5551 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5552 if (rc) {
5553 pr_err("Failed to init subtype 0x%x rc=%d\n",
5554 subtype, rc);
5555 goto fail_chg_enable;
5556 }
5557 break;
5558 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005559 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005560 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005561 chip->usb_chgpth_base = resource->start;
5562 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5563 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07005564 if (rc != -EPROBE_DEFER)
5565 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07005566 subtype, rc);
5567 goto fail_chg_enable;
5568 }
5569 break;
5570 case SMBB_DC_CHGPTH_SUBTYPE:
5571 chip->dc_chgpth_base = resource->start;
5572 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5573 if (rc) {
5574 pr_err("Failed to init subtype 0x%x rc=%d\n",
5575 subtype, rc);
5576 goto fail_chg_enable;
5577 }
5578 break;
5579 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005580 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005581 chip->boost_base = resource->start;
5582 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5583 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07005584 if (rc != -EPROBE_DEFER)
5585 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07005586 subtype, rc);
5587 goto fail_chg_enable;
5588 }
5589 break;
5590 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005591 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005592 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005593 chip->misc_base = resource->start;
5594 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5595 if (rc) {
5596 pr_err("Failed to init subtype=0x%x rc=%d\n",
5597 subtype, rc);
5598 goto fail_chg_enable;
5599 }
5600 break;
5601 default:
5602 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
5603 rc = -EINVAL;
5604 goto fail_chg_enable;
5605 }
5606 }
5607 dev_set_drvdata(&spmi->dev, chip);
5608 device_init_wakeup(&spmi->dev, 1);
5609
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005610 chip->insertion_ocv_uv = -EINVAL;
5611 chip->batt_present = qpnp_chg_is_batt_present(chip);
David Keitelf2170cc2013-02-20 17:49:03 -08005612 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08005613 chip->batt_psy.name = "battery";
5614 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
5615 chip->batt_psy.properties = msm_batt_power_props;
5616 chip->batt_psy.num_properties =
5617 ARRAY_SIZE(msm_batt_power_props);
5618 chip->batt_psy.get_property = qpnp_batt_power_get_property;
5619 chip->batt_psy.set_property = qpnp_batt_power_set_property;
5620 chip->batt_psy.property_is_writeable =
5621 qpnp_batt_property_is_writeable;
5622 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07005623 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07005624 chip->batt_psy.supplied_to = pm_batt_supplied_to;
5625 chip->batt_psy.num_supplicants =
5626 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07005627
David Keitelf2170cc2013-02-20 17:49:03 -08005628 rc = power_supply_register(chip->dev, &chip->batt_psy);
5629 if (rc < 0) {
5630 pr_err("batt failed to register rc = %d\n", rc);
5631 goto fail_chg_enable;
5632 }
David Keitel79f4c932013-04-03 16:08:39 -07005633 INIT_WORK(&chip->adc_measure_work,
5634 qpnp_bat_if_adc_measure_work);
David Keitelaa375562013-08-08 09:43:28 -07005635 INIT_WORK(&chip->adc_disable_work,
David Keitelecab15a2013-08-06 15:41:39 -07005636 qpnp_bat_if_adc_disable_work);
David Keitelc7093b02013-02-14 12:50:04 -08005637 }
5638
David Keitel9fd07382013-05-02 15:37:44 -07005639 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07005640 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005641 INIT_DELAYED_WORK(&chip->usbin_health_check,
5642 qpnp_usbin_health_check_work);
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07005643 INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
David Keitel7ac385e2013-08-19 18:02:40 -07005644 INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
David Keitel5910eea2013-05-02 15:32:25 -07005645
David Keitelf2170cc2013-02-20 17:49:03 -08005646 if (chip->dc_chgpth_base) {
5647 chip->dc_psy.name = "qpnp-dc";
5648 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
5649 chip->dc_psy.supplied_to = pm_power_supplied_to;
5650 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
5651 chip->dc_psy.properties = pm_power_props_mains;
5652 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
5653 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07005654 chip->dc_psy.set_property = qpnp_dc_power_set_property;
5655 chip->dc_psy.property_is_writeable =
5656 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08005657
5658 rc = power_supply_register(chip->dev, &chip->dc_psy);
5659 if (rc < 0) {
5660 pr_err("power_supply_register dc failed rc=%d\n", rc);
5661 goto unregister_batt;
5662 }
David Keitel80668952012-07-27 14:25:49 -07005663 }
5664
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005665 /* Turn on appropriate workaround flags */
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005666 rc = qpnp_chg_setup_flags(chip);
5667 if (rc < 0) {
5668 pr_err("failed to setup flags rc=%d\n", rc);
5669 goto unregister_dc_psy;
5670 }
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005671
David Keitelf2170cc2013-02-20 17:49:03 -08005672 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08005673 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
5674 if (rc) {
5675 pr_err("Error setting idcmax property %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005676 goto unregister_dc_psy;
David Keitel22ed2232013-01-28 11:04:07 -08005677 }
5678 }
5679
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005680 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0aea18a2013-06-14 18:57:57 -07005681 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07005682 chip->adc_param.low_temp = chip->cool_bat_decidegc;
5683 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08005684 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
5685 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
5686 chip->adc_param.btm_ctx = chip;
5687 chip->adc_param.threshold_notification =
5688 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08005689 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07005690
5691 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005692 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
5693 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005694 if (rc) {
5695 pr_err("request ADC error %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005696 goto unregister_dc_psy;
David Keitel0c1a4532013-03-21 16:39:06 -07005697 }
David Keitel454ee842013-03-08 16:19:11 -08005698 }
5699 }
David Keitel89c17752013-06-28 14:52:48 -07005700 rc = qpnp_chg_bat_if_configure_btc(chip);
5701 if (rc) {
5702 pr_err("failed to configure btc %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005703 goto unregister_dc_psy;
David Keitel89c17752013-06-28 14:52:48 -07005704 }
David Keitel454ee842013-03-08 16:19:11 -08005705
wangxlf0e6b1f2014-12-31 09:51:40 +08005706#ifdef CONFIG_TCMD
5707 the_chip = chip;
5708#endif
5709
David Keitelcd2e1022014-05-02 17:25:15 -07005710 chip->usb_trim_default = qpnp_chg_iusb_trim_get(chip);
David Keitel03ee6b52012-10-22 12:25:19 -07005711 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08005712 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07005713 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07005714
David Keitelbf2edba2014-03-05 10:49:32 -08005715 if (chip->parallel_ovp_mode) {
5716 rc = override_dcin_ilimit(chip, 1);
5717 if (rc) {
5718 pr_err("Override DCIN LLIMIT %d\n", rc);
5719 goto unregister_dc_psy;
5720 }
5721 }
5722
David Keitel0f35be42013-04-16 11:10:40 -07005723 rc = qpnp_chg_request_irqs(chip);
5724 if (rc) {
5725 pr_err("failed to request interrupts %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005726 goto unregister_dc_psy;
David Keitel0f35be42013-04-16 11:10:40 -07005727 }
5728
David Keitel7e38f512013-11-19 11:15:11 -08005729 qpnp_chg_usb_chg_gone_irq_handler(chip->chg_gone.irq, chip);
David Keitelad980fc2013-07-30 18:12:02 -07005730 qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
5731 qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
David Keitel9fd07382013-05-02 15:37:44 -07005732 power_supply_set_present(chip->usb_psy,
5733 qpnp_chg_is_usb_chg_plugged_in(chip));
5734
David Keitel3c62b472013-05-06 15:38:11 -07005735 /* Set USB psy online to avoid userspace from shutting down if battery
5736 * capacity is at zero and no chargers online. */
5737 if (qpnp_chg_is_usb_chg_plugged_in(chip))
5738 power_supply_set_online(chip->usb_psy, 1);
5739
David Keitel7ac385e2013-08-19 18:02:40 -07005740 schedule_delayed_work(&chip->aicl_check_work,
5741 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel796882d2013-05-14 18:01:11 -07005742 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 -08005743 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07005744 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08005745 qpnp_chg_is_usb_chg_plugged_in(chip),
5746 qpnp_chg_is_dc_chg_plugged_in(chip),
5747 get_prop_batt_present(chip),
5748 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07005749 return 0;
5750
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005751unregister_dc_psy:
5752 if (chip->dc_chgpth_base)
5753 power_supply_unregister(&chip->dc_psy);
David Keitelc7093b02013-02-14 12:50:04 -08005754unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08005755 if (chip->bat_if_base)
5756 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07005757fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07005758 regulator_unregister(chip->otg_vreg.rdev);
5759 regulator_unregister(chip->boost_vreg.rdev);
David Keitel80668952012-07-27 14:25:49 -07005760 return rc;
5761}
5762
5763static int __devexit
5764qpnp_charger_remove(struct spmi_device *spmi)
5765{
5766 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005767 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07005768 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005769 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
5770 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005771 }
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305772
5773 cancel_delayed_work_sync(&chip->aicl_check_work);
5774 power_supply_unregister(&chip->dc_psy);
5775 cancel_work_sync(&chip->soc_check_work);
5776 cancel_delayed_work_sync(&chip->usbin_health_check);
5777 cancel_delayed_work_sync(&chip->arb_stop_work);
David Keitel9fd07382013-05-02 15:37:44 -07005778 cancel_delayed_work_sync(&chip->eoc_work);
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305779 cancel_work_sync(&chip->adc_disable_work);
5780 cancel_work_sync(&chip->adc_measure_work);
5781 power_supply_unregister(&chip->batt_psy);
5782 cancel_work_sync(&chip->batfet_lcl_work);
5783 cancel_work_sync(&chip->insertion_ocv_work);
5784 cancel_work_sync(&chip->reduce_power_stage_work);
5785 alarm_cancel(&chip->reduce_power_stage_alarm);
5786
5787 mutex_destroy(&chip->batfet_vreg_lock);
5788 mutex_destroy(&chip->jeita_configure_lock);
David Keitel79f4c932013-04-03 16:08:39 -07005789
David Collinscbb12132013-05-28 10:47:28 -07005790 regulator_unregister(chip->otg_vreg.rdev);
5791 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07005792
David Keitel80668952012-07-27 14:25:49 -07005793 return 0;
5794}
5795
David Keitel85ae4342013-04-16 11:46:00 -07005796static int qpnp_chg_resume(struct device *dev)
5797{
5798 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5799 int rc = 0;
5800
David Keitel39093572013-06-05 15:32:30 -07005801 if (chip->bat_if_base) {
5802 rc = qpnp_chg_masked_write(chip,
5803 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5804 VREF_BATT_THERM_FORCE_ON,
5805 VREF_BATT_THERM_FORCE_ON, 1);
5806 if (rc)
5807 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
5808 }
David Keitel85ae4342013-04-16 11:46:00 -07005809
5810 return rc;
5811}
5812
5813static int qpnp_chg_suspend(struct device *dev)
5814{
5815 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5816 int rc = 0;
5817
David Keitel39093572013-06-05 15:32:30 -07005818 if (chip->bat_if_base) {
5819 rc = qpnp_chg_masked_write(chip,
5820 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5821 VREF_BATT_THERM_FORCE_ON,
5822 VREF_BAT_THM_ENABLED_FSM, 1);
5823 if (rc)
5824 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
5825 }
David Keitel85ae4342013-04-16 11:46:00 -07005826
5827 return rc;
5828}
5829
David Keitel723d5012013-05-03 13:17:27 -07005830static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07005831 .resume = qpnp_chg_resume,
5832 .suspend = qpnp_chg_suspend,
5833};
5834
David Keitel80668952012-07-27 14:25:49 -07005835static struct spmi_driver qpnp_charger_driver = {
5836 .probe = qpnp_charger_probe,
5837 .remove = __devexit_p(qpnp_charger_remove),
5838 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07005839 .name = QPNP_CHARGER_DEV_NAME,
5840 .owner = THIS_MODULE,
5841 .of_match_table = qpnp_charger_match_table,
5842 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07005843 },
5844};
5845
5846/**
5847 * qpnp_chg_init() - register spmi driver for qpnp-chg
5848 */
5849int __init
5850qpnp_chg_init(void)
5851{
5852 return spmi_driver_register(&qpnp_charger_driver);
5853}
5854module_init(qpnp_chg_init);
5855
5856static void __exit
5857qpnp_chg_exit(void)
5858{
5859 spmi_driver_unregister(&qpnp_charger_driver);
5860}
5861module_exit(qpnp_chg_exit);
5862
5863
5864MODULE_DESCRIPTION("QPNP charger driver");
5865MODULE_LICENSE("GPL v2");
5866MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);