blob: 38bd66641eec3fe89dbf8887b7be196d9d2adc65 [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
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800520static inline int
David Keitel796882d2013-05-14 18:01:11 -0700521get_bpd(const char *name)
522{
523 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700524 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
525 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700526 return i;
527 }
528 return -EINVAL;
529}
530
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700531static bool
532is_within_range(int value, int left, int right)
533{
534 if (left >= right && left >= value && value >= right)
535 return 1;
536 if (left <= right && left <= value && value <= right)
537 return 1;
538 return 0;
539}
540
David Keitel80668952012-07-27 14:25:49 -0700541static int
542qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
543 u16 base, int count)
544{
David Keitel39093572013-06-05 15:32:30 -0700545 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700546 struct spmi_device *spmi = chip->spmi;
547
David Keitel39093572013-06-05 15:32:30 -0700548 if (base == 0) {
549 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
550 base, spmi->sid, rc);
551 return -EINVAL;
552 }
553
554 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700555 if (rc) {
556 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
557 spmi->sid, rc);
558 return rc;
559 }
560 return 0;
561}
562
563static int
564qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
565 u16 base, int count)
566{
David Keitel39093572013-06-05 15:32:30 -0700567 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700568 struct spmi_device *spmi = chip->spmi;
569
David Keitel39093572013-06-05 15:32:30 -0700570 if (base == 0) {
571 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
572 base, spmi->sid, rc);
573 return -EINVAL;
574 }
575
576 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700577 if (rc) {
578 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
579 base, spmi->sid, rc);
580 return rc;
581 }
582
583 return 0;
584}
585
586static int
587qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
588 u8 mask, u8 val, int count)
589{
590 int rc;
591 u8 reg;
592
593 rc = qpnp_chg_read(chip, &reg, base, count);
594 if (rc) {
595 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
596 return rc;
597 }
598 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
599
600 reg &= ~mask;
601 reg |= val & mask;
602
603 pr_debug("Writing 0x%x\n", reg);
604
605 rc = qpnp_chg_write(chip, &reg, base, count);
606 if (rc) {
607 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
608 return rc;
609 }
610
611 return 0;
612}
613
David Keitel47185a62013-05-15 18:54:10 -0700614static void
615qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
616{
617 if (__test_and_clear_bit(0, &irq->disabled)) {
618 pr_debug("number = %d\n", irq->irq);
619 enable_irq(irq->irq);
620 }
621}
622
623static void
624qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
625{
626 if (!__test_and_set_bit(0, &irq->disabled)) {
627 pr_debug("number = %d\n", irq->irq);
628 disable_irq_nosync(irq->irq);
629 }
630}
631
David Keitelbf6a1062014-01-23 10:57:36 -0800632static void
633qpnp_chg_irq_wake_enable(struct qpnp_chg_irq *irq)
634{
635 if (!__test_and_set_bit(0, &irq->wake_enable)) {
636 pr_debug("number = %d\n", irq->irq);
637 enable_irq_wake(irq->irq);
638 }
639}
640
641static void
642qpnp_chg_irq_wake_disable(struct qpnp_chg_irq *irq)
643{
644 if (__test_and_clear_bit(0, &irq->wake_enable)) {
645 pr_debug("number = %d\n", irq->irq);
646 disable_irq_wake(irq->irq);
647 }
648}
649
David Keitel6f865cd2012-11-30 15:04:32 -0800650#define USB_OTG_EN_BIT BIT(0)
651static int
652qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
653{
654 u8 usb_otg_en;
655 int rc;
656
657 rc = qpnp_chg_read(chip, &usb_otg_en,
658 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
659 1);
660
661 if (rc) {
662 pr_err("spmi read failed: addr=%03X, rc=%d\n",
663 chip->usb_chgpth_base + CHGR_STATUS, rc);
664 return rc;
665 }
666 pr_debug("usb otg en 0x%x\n", usb_otg_en);
667
668 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
669}
670
David Keitel42ae0aa2013-03-08 16:20:10 -0800671static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700672qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
673{
674 u8 boost_en_ctl;
675 int rc;
676
677 rc = qpnp_chg_read(chip, &boost_en_ctl,
678 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
679 if (rc) {
680 pr_err("spmi read failed: addr=%03X, rc=%d\n",
681 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
682 return rc;
683 }
684
685 pr_debug("boost en 0x%x\n", boost_en_ctl);
686
687 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
688}
689
690static int
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700691qpnp_chg_is_batt_temp_ok(struct qpnp_chg_chip *chip)
692{
693 u8 batt_rt_sts;
694 int rc;
695
696 rc = qpnp_chg_read(chip, &batt_rt_sts,
697 INT_RT_STS(chip->bat_if_base), 1);
698 if (rc) {
699 pr_err("spmi read failed: addr=%03X, rc=%d\n",
700 INT_RT_STS(chip->bat_if_base), rc);
701 return rc;
702 }
703
704 return (batt_rt_sts & BAT_TEMP_OK_IRQ) ? 1 : 0;
705}
706
707static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800708qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
709{
710 u8 batt_pres_rt_sts;
711 int rc;
712
713 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
714 INT_RT_STS(chip->bat_if_base), 1);
715 if (rc) {
716 pr_err("spmi read failed: addr=%03X, rc=%d\n",
717 INT_RT_STS(chip->bat_if_base), rc);
718 return rc;
719 }
720
721 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
722}
723
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700724static int
725qpnp_chg_is_batfet_closed(struct qpnp_chg_chip *chip)
726{
727 u8 batfet_closed_rt_sts;
728 int rc;
729
730 rc = qpnp_chg_read(chip, &batfet_closed_rt_sts,
731 INT_RT_STS(chip->bat_if_base), 1);
732 if (rc) {
733 pr_err("spmi read failed: addr=%03X, rc=%d\n",
734 INT_RT_STS(chip->bat_if_base), rc);
735 return rc;
736 }
737
738 return (batfet_closed_rt_sts & BAT_FET_ON_IRQ) ? 1 : 0;
739}
740
David Keitel80668952012-07-27 14:25:49 -0700741static int
742qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
743{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800744 u8 usb_chgpth_rt_sts;
David Keitel80668952012-07-27 14:25:49 -0700745 int rc;
746
Zhenhua Huangf1163872014-03-03 10:51:25 +0800747 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
748 INT_RT_STS(chip->usb_chgpth_base), 1);
David Keitel80668952012-07-27 14:25:49 -0700749
750 if (rc) {
751 pr_err("spmi read failed: addr=%03X, rc=%d\n",
Zhenhua Huangf1163872014-03-03 10:51:25 +0800752 INT_RT_STS(chip->usb_chgpth_base), rc);
David Keitel80668952012-07-27 14:25:49 -0700753 return rc;
754 }
Zhenhua Huangf1163872014-03-03 10:51:25 +0800755 pr_debug("chgr usb sts 0x%x\n", usb_chgpth_rt_sts);
David Keitel80668952012-07-27 14:25:49 -0700756
Zhenhua Huangf1163872014-03-03 10:51:25 +0800757 return (usb_chgpth_rt_sts & USBIN_VALID_IRQ) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700758}
759
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700760static bool
David Keitel820a90d2014-03-25 18:18:04 -0700761qpnp_is_dc_higher_prio(struct qpnp_chg_chip *chip)
762{
763 int rc;
764 u8 usb_ctl;
765
766 if (!chip->type == SMBB)
767 return false;
768
769 rc = qpnp_chg_read(chip, &usb_ctl,
770 chip->usb_chgpth_base + USB_CHGPTH_CTL, 1);
771 if (rc) {
772 pr_err("failed to read usb ctl rc=%d\n", rc);
773 return 0;
774 }
775
776 return !!(usb_ctl & DC_HIGHER_PRIORITY);
777}
778
779static bool
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700780qpnp_chg_is_ibat_loop_active(struct qpnp_chg_chip *chip)
781{
782 int rc;
783 u8 buck_sts;
784
785 rc = qpnp_chg_read(chip, &buck_sts,
786 INT_RT_STS(chip->buck_base), 1);
787 if (rc) {
788 pr_err("failed to read buck RT status rc=%d\n", rc);
789 return 0;
790 }
791
792 return !!(buck_sts & IBAT_LOOP_IRQ);
793}
794
Zhenhua Huangf1163872014-03-03 10:51:25 +0800795#define USB_VALID_MASK 0xC0
796#define USB_VALID_IN_MASK BIT(7)
797#define USB_COARSE_DET 0x10
798#define USB_VALID_OVP_VALUE 0x40
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800799static int
800qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
801{
802 u8 usbin_chg_rt_sts;
803 int rc;
804 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
805 chip->usb_chgpth_base + CHGR_STATUS , 1);
806 if (rc) {
807 pr_err("spmi read failed: addr=%03X, rc=%d\n",
808 chip->usb_chgpth_base + CHGR_STATUS, rc);
809 return rc;
810 }
811 return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
812}
813
814static int
815qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
816{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800817 u8 usbin_chg_rt_sts, usb_chgpth_rt_sts;
818 u8 usbin_health = 0;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800819 int rc;
820
821 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
822 chip->usb_chgpth_base + CHGR_STATUS , 1);
823
824 if (rc) {
825 pr_err("spmi read failed: addr=%03X, rc=%d\n",
826 chip->usb_chgpth_base + CHGR_STATUS, rc);
827 return rc;
828 }
829
Zhenhua Huangf1163872014-03-03 10:51:25 +0800830 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
831 INT_RT_STS(chip->usb_chgpth_base) , 1);
832
833 if (rc) {
834 pr_err("spmi read failed: addr=%03X, rc=%d\n",
835 INT_RT_STS(chip->usb_chgpth_base), rc);
836 return rc;
837 }
838
839 pr_debug("chgr usb sts 0x%x, chgpth rt sts 0x%x\n",
840 usbin_chg_rt_sts, usb_chgpth_rt_sts);
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800841 if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
842 if ((usbin_chg_rt_sts & USB_VALID_MASK)
843 == USB_VALID_OVP_VALUE) {
844 usbin_health = USBIN_OVP;
845 pr_err("Over voltage charger inserted\n");
Zhenhua Huangf1163872014-03-03 10:51:25 +0800846 } else if ((usb_chgpth_rt_sts & USBIN_VALID_IRQ) != 0) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800847 usbin_health = USBIN_OK;
848 pr_debug("Valid charger inserted\n");
849 }
850 } else {
851 usbin_health = USBIN_UNKNOW;
852 pr_debug("Charger plug out\n");
853 }
854
855 return usbin_health;
856}
857
David Keitel80668952012-07-27 14:25:49 -0700858static int
859qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
860{
861 u8 dcin_valid_rt_sts;
862 int rc;
863
David Keitelf2170cc2013-02-20 17:49:03 -0800864 if (!chip->dc_chgpth_base)
865 return 0;
866
David Keitel80668952012-07-27 14:25:49 -0700867 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
868 INT_RT_STS(chip->dc_chgpth_base), 1);
869 if (rc) {
870 pr_err("spmi read failed: addr=%03X, rc=%d\n",
871 INT_RT_STS(chip->dc_chgpth_base), rc);
872 return rc;
873 }
874
875 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
876}
877
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700878static int
879qpnp_chg_is_ichg_loop_active(struct qpnp_chg_chip *chip)
880{
881 u8 buck_sts;
882 int rc;
883
884 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
885
886 if (rc) {
887 pr_err("spmi read failed: addr=%03X, rc=%d\n",
888 INT_RT_STS(chip->buck_base), rc);
889 return rc;
890 }
891 pr_debug("buck usb sts 0x%x\n", buck_sts);
892
893 return (buck_sts & ICHG_LOOP_IRQ) ? 1 : 0;
894}
895
David Keitel22ed2232013-01-28 11:04:07 -0800896#define QPNP_CHG_I_MAX_MIN_100 100
897#define QPNP_CHG_I_MAX_MIN_150 150
898#define QPNP_CHG_I_MAX_MIN_MA 200
899#define QPNP_CHG_I_MAX_MAX_MA 2500
900#define QPNP_CHG_I_MAXSTEP_MA 100
901static int
902qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
903{
904 int rc = 0;
905 u8 dc = 0;
906
907 if (mA < QPNP_CHG_I_MAX_MIN_100
908 || mA > QPNP_CHG_I_MAX_MAX_MA) {
909 pr_err("bad mA=%d asked to set\n", mA);
910 return -EINVAL;
911 }
912
913 if (mA == QPNP_CHG_I_MAX_MIN_100) {
914 dc = 0x00;
915 pr_debug("current=%d setting %02x\n", mA, dc);
916 return qpnp_chg_write(chip, &dc,
917 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
918 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
919 dc = 0x01;
920 pr_debug("current=%d setting %02x\n", mA, dc);
921 return qpnp_chg_write(chip, &dc,
922 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
923 }
924
925 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
926
927 pr_debug("current=%d setting 0x%x\n", mA, dc);
928 rc = qpnp_chg_write(chip, &dc,
929 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
930
931 return rc;
932}
933
David Keitel80668952012-07-27 14:25:49 -0700934static int
David Keitel2586f0a2013-08-20 10:02:26 -0700935qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
936{
937 int rc = 0;
938 u8 trim_reg;
939
940 rc = qpnp_chg_read(chip, &trim_reg,
941 chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
942 if (rc) {
943 pr_err("failed to read USB_TRIM rc=%d\n", rc);
944 return 0;
945 }
946
947 return trim_reg;
948}
949
950static int
951qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
952{
953 int rc = 0;
954
955 rc = qpnp_chg_masked_write(chip,
956 chip->usb_chgpth_base + SEC_ACCESS,
957 0xFF,
958 0xA5, 1);
959 if (rc) {
960 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
961 return rc;
962 }
963
964 rc = qpnp_chg_masked_write(chip,
965 chip->usb_chgpth_base + CHGR_USB_TRIM,
966 0xFF,
967 trim, 1);
968 if (rc) {
969 pr_err("failed to write USB TRIM rc=%d\n", rc);
970 return rc;
971 }
972
973 return rc;
974}
975
David Keitelcd2e1022014-05-02 17:25:15 -0700976#define IOVP_USB_WALL_TRSH_MA 150
David Keitel2586f0a2013-08-20 10:02:26 -0700977static int
David Keitel80668952012-07-27 14:25:49 -0700978qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
979{
David Keiteld681cda2012-10-02 15:44:21 -0700980 int rc = 0;
981 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700982
David Keitel7b0568482013-12-02 14:47:42 -0800983 if (mA < 0 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700984 pr_err("bad mA=%d asked to set\n", mA);
985 return -EINVAL;
986 }
987
David Keitel7b0568482013-12-02 14:47:42 -0800988 if (mA <= QPNP_CHG_I_MAX_MIN_100) {
David Keitel22ed2232013-01-28 11:04:07 -0800989 usb_reg = 0x00;
990 pr_debug("current=%d setting %02x\n", mA, usb_reg);
991 return qpnp_chg_write(chip, &usb_reg,
992 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
993 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
994 usb_reg = 0x01;
995 pr_debug("current=%d setting %02x\n", mA, usb_reg);
996 return qpnp_chg_write(chip, &usb_reg,
997 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
998 }
999
1000 /* Impose input current limit */
1001 if (chip->maxinput_usb_ma)
1002 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
1003
1004 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -07001005
David Keiteld681cda2012-10-02 15:44:21 -07001006 if (chip->flags & CHG_FLAGS_VCP_WA) {
1007 temp = 0xA5;
1008 rc = qpnp_chg_write(chip, &temp,
1009 chip->buck_base + SEC_ACCESS, 1);
1010 rc = qpnp_chg_masked_write(chip,
1011 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
1012 0x0C, 0x0C, 1);
1013 }
1014
David Keitel80668952012-07-27 14:25:49 -07001015 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -07001016 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -08001017 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -07001018
1019 if (chip->flags & CHG_FLAGS_VCP_WA) {
1020 temp = 0xA5;
1021 udelay(200);
1022 rc = qpnp_chg_write(chip, &temp,
1023 chip->buck_base + SEC_ACCESS, 1);
1024 rc = qpnp_chg_masked_write(chip,
1025 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
1026 0x0C, 0x00, 1);
1027 }
1028
1029 return rc;
1030}
1031
David Keitel25544a22013-12-06 17:59:24 -08001032#define QPNP_CHG_VINMIN_MIN_MV 4000
David Keitel337bd862013-07-15 21:42:58 -07001033#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
1034#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
1035#define QPNP_CHG_VINMIN_MAX_MV 9600
1036#define QPNP_CHG_VINMIN_STEP_MV 50
1037#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
Prasad Sodagudi95624b62013-09-26 16:40:59 +05301038#define QPNP_CHG_VINMIN_MASK 0x3F
David Keitel25544a22013-12-06 17:59:24 -08001039#define QPNP_CHG_VINMIN_MIN_VAL 0x0C
David Keitel337bd862013-07-15 21:42:58 -07001040static int
1041qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
1042{
1043 u8 temp;
1044
David Keitel25544a22013-12-06 17:59:24 -08001045 if ((voltage < QPNP_CHG_VINMIN_MIN_MV)
1046 || (voltage > QPNP_CHG_VINMIN_MAX_MV)) {
David Keitel337bd862013-07-15 21:42:58 -07001047 pr_err("bad mV=%d asked to set\n", voltage);
1048 return -EINVAL;
1049 }
1050 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
1051 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
David Keitel289fcf82013-10-24 11:33:00 -07001052 temp += (voltage - QPNP_CHG_VINMIN_HIGH_MIN_MV)
David Keitel337bd862013-07-15 21:42:58 -07001053 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
1054 } else {
1055 temp = QPNP_CHG_VINMIN_MIN_VAL;
1056 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
1057 / QPNP_CHG_VINMIN_STEP_MV;
1058 }
1059
1060 pr_debug("voltage=%d setting %02x\n", voltage, temp);
1061 return qpnp_chg_masked_write(chip,
1062 chip->chgr_base + CHGR_VIN_MIN,
1063 QPNP_CHG_VINMIN_MASK, temp, 1);
1064}
1065
1066static int
1067qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
1068{
1069 int rc, vin_min_mv;
1070 u8 vin_min;
1071
1072 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
1073 if (rc) {
1074 pr_err("failed to read VIN_MIN rc=%d\n", rc);
1075 return 0;
1076 }
1077
1078 if (vin_min == 0)
1079 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
David Keitel289fcf82013-10-24 11:33:00 -07001080 else if (vin_min >= QPNP_CHG_VINMIN_HIGH_MIN_VAL)
David Keitel337bd862013-07-15 21:42:58 -07001081 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
1082 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
1083 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
1084 else
1085 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
1086 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
1087 * QPNP_CHG_VINMIN_STEP_MV;
1088 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
1089
1090 return vin_min_mv;
1091}
1092
Prasad Sodagudic3678012013-09-23 12:01:19 +05301093#define QPNP_CHG_VBATWEAK_MIN_MV 2100
1094#define QPNP_CHG_VBATWEAK_MAX_MV 3600
1095#define QPNP_CHG_VBATWEAK_STEP_MV 100
1096static int
1097qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
1098{
1099 u8 temp;
1100
1101 if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
1102 || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
1103 return -EINVAL;
1104
1105 temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
1106 / QPNP_CHG_VBATWEAK_STEP_MV;
1107
1108 pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
1109 return qpnp_chg_write(chip, &temp,
1110 chip->chgr_base + CHGR_VBAT_WEAK, 1);
1111}
1112
David Keitel337bd862013-07-15 21:42:58 -07001113static int
1114qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
1115{
1116 int rc, iusbmax_ma;
1117 u8 iusbmax;
1118
1119 rc = qpnp_chg_read(chip, &iusbmax,
1120 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1121 if (rc) {
1122 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
1123 return 0;
1124 }
1125
1126 if (iusbmax == 0)
1127 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
1128 else if (iusbmax == 0x01)
1129 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
1130 else
1131 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
1132
1133 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
1134
1135 return iusbmax_ma;
1136}
1137
David Keitel975b5352014-01-27 14:28:04 -08001138#define ILIMIT_OVR_0 0x02
1139static int
1140override_dcin_ilimit(struct qpnp_chg_chip *chip, bool override)
1141{
1142 int rc;
1143
1144 pr_debug("override %d\n", override);
1145 rc = qpnp_chg_masked_write(chip,
1146 chip->dc_chgpth_base + SEC_ACCESS,
1147 0xA5,
1148 0xA5, 1);
1149 rc |= qpnp_chg_masked_write(chip,
1150 chip->dc_chgpth_base + DC_COMP_OVR1,
1151 0xFF,
1152 override ? ILIMIT_OVR_0 : 0, 1);
1153 if (rc) {
1154 pr_err("Failed to override dc ilimit rc = %d\n", rc);
1155 return rc;
1156 }
1157
1158 return rc;
1159}
1160
1161#define DUAL_PATH_EN BIT(7)
1162static int
1163switch_parallel_ovp_mode(struct qpnp_chg_chip *chip, bool enable)
1164{
1165 int rc = 0;
1166
1167 if (!chip->usb_chgpth_base || !chip->dc_chgpth_base)
1168 return rc;
1169
1170 pr_debug("enable %d\n", enable);
1171 rc = override_dcin_ilimit(chip, 1);
1172 udelay(10);
1173
1174 /* enable/disable dual path mode */
1175 rc = qpnp_chg_masked_write(chip,
1176 chip->usb_chgpth_base + SEC_ACCESS,
1177 0xA5,
1178 0xA5, 1);
1179 rc |= qpnp_chg_masked_write(chip,
1180 chip->usb_chgpth_base + USB_SPARE,
1181 0xFF,
1182 enable ? DUAL_PATH_EN : 0, 1);
1183 if (rc) {
1184 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1185 return rc;
1186 }
1187
David Keitelbf2edba2014-03-05 10:49:32 -08001188 if (enable)
1189 rc = override_dcin_ilimit(chip, 0);
David Keitel975b5352014-01-27 14:28:04 -08001190 return rc;
1191}
1192
David Keiteld681cda2012-10-02 15:44:21 -07001193#define USB_SUSPEND_BIT BIT(0)
1194static int
1195qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
1196{
David Keitel975b5352014-01-27 14:28:04 -08001197 /* Turn off DC OVP FET when going into USB suspend */
1198 if (chip->parallel_ovp_mode && enable)
1199 switch_parallel_ovp_mode(chip, 0);
1200
David Keiteld681cda2012-10-02 15:44:21 -07001201 return qpnp_chg_masked_write(chip,
1202 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
1203 USB_SUSPEND_BIT,
1204 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -07001205}
1206
David Keitel344c6972013-04-09 19:28:21 -07001207static int
1208qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
1209{
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001210 if (chip->insertion_ocv_uv == 0 && enable) {
1211 pr_debug("Battery not present, skipping\n");
1212 return 0;
1213 }
1214 pr_debug("charging %s\n", enable ? "enabled" : "disabled");
David Keitel344c6972013-04-09 19:28:21 -07001215 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1216 CHGR_CHG_EN,
1217 enable ? CHGR_CHG_EN : 0, 1);
1218}
1219
1220static int
1221qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
1222{
1223 /* Don't run on battery for batteryless hardware */
1224 if (chip->use_default_batt_values)
1225 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -07001226 /* Don't force on battery if battery is not present */
1227 if (!qpnp_chg_is_batt_present(chip))
1228 return 0;
David Keitel344c6972013-04-09 19:28:21 -07001229
1230 /* This bit forces the charger to run off of the battery rather
1231 * than a connected charger */
1232 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1233 CHGR_ON_BAT_FORCE_BIT,
1234 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
1235}
1236
David Keitel8b68d2d2013-05-14 23:36:51 -07001237#define BUCK_DUTY_MASK_100P 0x30
1238static int
1239qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
1240{
1241 int rc;
1242
1243 pr_debug("enable: %d\n", enable);
1244
1245 rc = qpnp_chg_masked_write(chip,
1246 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1247 if (rc) {
1248 pr_debug("failed to write sec access rc=%d\n", rc);
1249 return rc;
1250 }
1251
1252 rc = qpnp_chg_masked_write(chip,
1253 chip->buck_base + BUCK_TEST_SMBC_MODES,
1254 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
1255 if (rc) {
1256 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
1257 return rc;
1258 }
1259
1260 return rc;
1261}
1262
David Keitel9fd07382013-05-02 15:37:44 -07001263#define COMPATATOR_OVERRIDE_0 0x80
1264static int
1265qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
1266{
1267 int rc;
1268
1269 pr_debug("toggle: %d\n", enable);
1270
1271 rc = qpnp_chg_masked_write(chip,
1272 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1273 if (rc) {
1274 pr_debug("failed to write sec access rc=%d\n", rc);
1275 return rc;
1276 }
1277
1278 rc = qpnp_chg_masked_write(chip,
1279 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
1280 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
1281 if (rc) {
1282 pr_debug("failed to toggle chg done override rc=%d\n", rc);
1283 return rc;
1284 }
1285
1286 return rc;
1287}
1288
1289#define QPNP_CHG_VBATDET_MIN_MV 3240
1290#define QPNP_CHG_VBATDET_MAX_MV 5780
1291#define QPNP_CHG_VBATDET_STEP_MV 20
1292static int
1293qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
1294{
1295 u8 temp;
1296
1297 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
1298 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
1299 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
1300 return -EINVAL;
1301 }
1302 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
1303 / QPNP_CHG_VBATDET_STEP_MV;
1304
1305 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
1306 return qpnp_chg_write(chip, &temp,
1307 chip->chgr_base + CHGR_VBAT_DET, 1);
1308}
1309
David Keitel344c6972013-04-09 19:28:21 -07001310static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001311qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
1312{
1313 if (chip->bat_is_cool)
1314 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
1315 - chip->resume_delta_mv);
1316 else if (chip->bat_is_warm)
1317 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
1318 - chip->resume_delta_mv);
1319 else if (chip->resuming_charging)
1320 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1321 + chip->resume_delta_mv);
1322 else
1323 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1324 - chip->resume_delta_mv);
1325}
1326
1327static void
David Keitel344c6972013-04-09 19:28:21 -07001328qpnp_arb_stop_work(struct work_struct *work)
1329{
1330 struct delayed_work *dwork = to_delayed_work(work);
1331 struct qpnp_chg_chip *chip = container_of(dwork,
1332 struct qpnp_chg_chip, arb_stop_work);
1333
David Keitel9fd07382013-05-02 15:37:44 -07001334 if (!chip->chg_done)
1335 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -07001336 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1337}
1338
1339static void
1340qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -07001341{
1342 struct qpnp_chg_chip *chip = container_of(work,
1343 struct qpnp_chg_chip, adc_measure_work);
1344
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07001345 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -07001346 pr_err("request ADC error\n");
1347}
1348
David Keitelecab15a2013-08-06 15:41:39 -07001349static void
1350qpnp_bat_if_adc_disable_work(struct work_struct *work)
1351{
1352 struct qpnp_chg_chip *chip = container_of(work,
1353 struct qpnp_chg_chip, adc_disable_work);
1354
1355 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev, &chip->adc_param);
1356}
1357
David Keitel9fd07382013-05-02 15:37:44 -07001358#define EOC_CHECK_PERIOD_MS 10000
1359static irqreturn_t
1360qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
1361{
1362 struct qpnp_chg_chip *chip = _chip;
1363 u8 chg_sts = 0;
1364 int rc;
1365
1366 pr_debug("vbatdet-lo triggered\n");
1367
1368 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
1369 if (rc)
1370 pr_err("failed to read chg_sts rc=%d\n", rc);
1371
1372 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
1373 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
1374 schedule_delayed_work(&chip->eoc_work,
1375 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001376 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07001377 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001378 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07001379
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001380 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001381 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001382 if (chip->dc_chgpth_base) {
1383 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001384 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001385 }
1386 if (chip->bat_if_base) {
1387 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001388 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001389 }
David Keitel9fd07382013-05-02 15:37:44 -07001390 return IRQ_HANDLED;
1391}
1392
David Keitel344c6972013-04-09 19:28:21 -07001393#define ARB_STOP_WORK_MS 1000
1394static irqreturn_t
1395qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
1396{
1397 struct qpnp_chg_chip *chip = _chip;
David Keitel7e38f512013-11-19 11:15:11 -08001398 u8 usb_sts;
1399 int rc;
1400
1401 rc = qpnp_chg_read(chip, &usb_sts,
1402 INT_RT_STS(chip->usb_chgpth_base), 1);
1403 if (rc)
1404 pr_err("failed to read usb_chgpth_sts rc=%d\n", rc);
David Keitel344c6972013-04-09 19:28:21 -07001405
1406 pr_debug("chg_gone triggered\n");
David Keiteld53183a2014-01-07 17:17:44 -08001407 if ((qpnp_chg_is_usb_chg_plugged_in(chip)
1408 || qpnp_chg_is_dc_chg_plugged_in(chip))
1409 && (usb_sts & CHG_GONE_IRQ)) {
David Keitelcd2e1022014-05-02 17:25:15 -07001410 if (ext_ovp_isns_present) {
1411 pr_debug("EXT OVP IC ISNS disabled due to ARB WA\n");
1412 gpio_direction_output(chip->ext_ovp_isns_gpio, 0);
1413 }
1414
David Keitel344c6972013-04-09 19:28:21 -07001415 qpnp_chg_charge_en(chip, 0);
David Keitelcd2e1022014-05-02 17:25:15 -07001416
David Keitel9fd07382013-05-02 15:37:44 -07001417 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001418 schedule_delayed_work(&chip->arb_stop_work,
1419 msecs_to_jiffies(ARB_STOP_WORK_MS));
1420 }
1421
1422 return IRQ_HANDLED;
1423}
1424
David Keitel0b62bdd2013-07-10 17:30:51 -07001425static irqreturn_t
1426qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
1427{
1428 struct qpnp_chg_chip *chip = _chip;
David Keitel0b62bdd2013-07-10 17:30:51 -07001429
1430 pr_debug("usb-ocp triggered\n");
1431
David Keitel8b9bd312014-01-15 14:44:00 -08001432 schedule_work(&chip->ocp_clear_work);
1433
1434 return IRQ_HANDLED;
1435}
1436
1437#define BOOST_ILIMIT_MIN 0x07
1438#define BOOST_ILIMIT_DEF 0x02
1439#define BOOST_ILIMT_MASK 0xFF
1440static void
1441qpnp_chg_ocp_clear_work(struct work_struct *work)
1442{
1443 int rc;
1444 u8 usb_sts;
1445 struct qpnp_chg_chip *chip = container_of(work,
1446 struct qpnp_chg_chip, ocp_clear_work);
1447
1448 if (chip->type == SMBBP) {
1449 rc = qpnp_chg_masked_write(chip,
1450 chip->boost_base + BOOST_ILIM,
1451 BOOST_ILIMT_MASK,
1452 BOOST_ILIMIT_MIN, 1);
1453 if (rc) {
1454 pr_err("Failed to turn configure ilim rc = %d\n", rc);
1455 return;
1456 }
1457 }
1458
David Keitel0b62bdd2013-07-10 17:30:51 -07001459 rc = qpnp_chg_masked_write(chip,
1460 chip->usb_chgpth_base + USB_OCP_CLR,
1461 OCP_CLR_BIT,
1462 OCP_CLR_BIT, 1);
1463 if (rc)
1464 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1465
1466 /* force usb ovp fet off */
1467 rc = qpnp_chg_masked_write(chip,
1468 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1469 USB_OTG_EN_BIT,
1470 USB_OTG_EN_BIT, 1);
1471 if (rc)
1472 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1473
David Keitel8b9bd312014-01-15 14:44:00 -08001474 if (chip->type == SMBBP) {
1475 /* Wait for OCP circuitry to be powered up */
1476 msleep(100);
1477 rc = qpnp_chg_read(chip, &usb_sts,
1478 INT_RT_STS(chip->usb_chgpth_base), 1);
1479 if (rc) {
1480 pr_err("failed to read interrupt sts %d\n", rc);
1481 return;
1482 }
1483
1484 if (usb_sts & COARSE_DET_USB_IRQ) {
1485 rc = qpnp_chg_masked_write(chip,
1486 chip->boost_base + BOOST_ILIM,
1487 BOOST_ILIMT_MASK,
1488 BOOST_ILIMIT_DEF, 1);
1489 if (rc) {
1490 pr_err("Failed to set ilim rc = %d\n", rc);
1491 return;
1492 }
1493 } else {
1494 pr_warn_ratelimited("USB short to GND detected!\n");
1495 }
1496 }
David Keitel0b62bdd2013-07-10 17:30:51 -07001497}
1498
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001499#define QPNP_CHG_VDDMAX_MIN 3400
1500#define QPNP_CHG_V_MIN_MV 3240
1501#define QPNP_CHG_V_MAX_MV 4500
1502#define QPNP_CHG_V_STEP_MV 10
1503#define QPNP_CHG_BUCK_TRIM1_STEP 10
1504#define QPNP_CHG_BUCK_VDD_TRIM_MASK 0xF0
1505static int
1506qpnp_chg_vddmax_and_trim_set(struct qpnp_chg_chip *chip,
1507 int voltage, int trim_mv)
1508{
1509 int rc, trim_set;
1510 u8 vddmax = 0, trim = 0;
1511
1512 if (voltage < QPNP_CHG_VDDMAX_MIN
1513 || voltage > QPNP_CHG_V_MAX_MV) {
1514 pr_err("bad mV=%d asked to set\n", voltage);
1515 return -EINVAL;
1516 }
1517
1518 vddmax = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1519 rc = qpnp_chg_write(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1520 if (rc) {
1521 pr_err("Failed to write vddmax: %d\n", rc);
1522 return rc;
1523 }
1524
1525 rc = qpnp_chg_masked_write(chip,
1526 chip->buck_base + SEC_ACCESS,
1527 0xFF,
1528 0xA5, 1);
1529 if (rc) {
1530 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1531 return rc;
1532 }
1533 trim_set = clamp((int)chip->trim_center
1534 + (trim_mv / QPNP_CHG_BUCK_TRIM1_STEP),
1535 0, 0xF);
1536 trim = (u8)trim_set << 4;
1537 rc = qpnp_chg_masked_write(chip,
1538 chip->buck_base + BUCK_CTRL_TRIM1,
1539 QPNP_CHG_BUCK_VDD_TRIM_MASK,
1540 trim, 1);
1541 if (rc) {
1542 pr_err("Failed to write buck trim1: %d\n", rc);
1543 return rc;
1544 }
1545 pr_debug("voltage=%d+%d setting vddmax: %02x, trim: %02x\n",
1546 voltage, trim_mv, vddmax, trim);
1547 return 0;
1548}
1549
Xiaozhe Shie8504482013-10-30 18:10:31 -07001550static int
1551qpnp_chg_vddmax_get(struct qpnp_chg_chip *chip)
1552{
1553 int rc;
1554 u8 vddmax = 0;
1555
1556 rc = qpnp_chg_read(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1557 if (rc) {
1558 pr_err("Failed to write vddmax: %d\n", rc);
1559 return rc;
1560 }
1561
1562 return QPNP_CHG_V_MIN_MV + (int)vddmax * QPNP_CHG_V_STEP_MV;
1563}
1564
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001565/* JEITA compliance logic */
1566static void
1567qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1568{
1569 if (chip->bat_is_cool)
1570 qpnp_chg_vddmax_and_trim_set(chip, chip->cool_bat_mv,
1571 chip->delta_vddmax_mv);
1572 else if (chip->bat_is_warm)
1573 qpnp_chg_vddmax_and_trim_set(chip, chip->warm_bat_mv,
1574 chip->delta_vddmax_mv);
1575 else
1576 qpnp_chg_vddmax_and_trim_set(chip, chip->max_voltage_mv,
1577 chip->delta_vddmax_mv);
1578}
1579
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001580static void
1581qpnp_usbin_health_check_work(struct work_struct *work)
1582{
1583 int usbin_health = 0;
1584 u8 psy_health_sts = 0;
1585 struct delayed_work *dwork = to_delayed_work(work);
1586 struct qpnp_chg_chip *chip = container_of(dwork,
1587 struct qpnp_chg_chip, usbin_health_check);
1588
1589 usbin_health = qpnp_chg_check_usbin_health(chip);
1590 spin_lock(&chip->usbin_health_monitor_lock);
1591 if (chip->usbin_health != usbin_health) {
1592 pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
1593 chip->usbin_health, usbin_health);
1594 chip->usbin_health = usbin_health;
1595 if (usbin_health == USBIN_OVP)
1596 psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1597 else if (usbin_health == USBIN_OK)
1598 psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
1599 power_supply_set_health_state(chip->usb_psy, psy_health_sts);
1600 power_supply_changed(chip->usb_psy);
1601 }
1602 /* enable OVP monitor in usb valid after coarse-det complete */
1603 chip->usb_valid_check_ovp = true;
1604 spin_unlock(&chip->usbin_health_monitor_lock);
1605 return;
1606}
1607
1608#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
1609#define USB_DEB_BYPASS 0x0
1610#define USB_DEB_5MS 0x1
1611#define USB_DEB_10MS 0x2
1612#define USB_DEB_20MS 0x3
1613static irqreturn_t
1614qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
1615{
1616 struct qpnp_chg_chip *chip = _chip;
1617 int host_mode, rc = 0;
1618 int debounce[] = {
1619 [USB_DEB_BYPASS] = 0,
1620 [USB_DEB_5MS] = 5,
1621 [USB_DEB_10MS] = 10,
1622 [USB_DEB_20MS] = 20 };
1623 u8 ovp_ctl;
1624 bool usb_coarse_det;
1625
1626 host_mode = qpnp_chg_is_otg_en_set(chip);
1627 usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
1628 pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
1629 usb_coarse_det, host_mode);
1630
1631 if (host_mode)
1632 return IRQ_HANDLED;
1633 /* ignore to monitor OVP in usbin valid irq handler
1634 if the coarse-det fired first, do the OVP state monitor
1635 in the usbin_health_check work, and after the work,
1636 enable monitor OVP in usbin valid irq handler */
1637 chip->usb_valid_check_ovp = false;
1638 if (chip->usb_coarse_det ^ usb_coarse_det) {
1639 chip->usb_coarse_det = usb_coarse_det;
1640 if (usb_coarse_det) {
1641 /* usb coarse-det rising edge, check the usbin_valid
1642 debounce time setting, and start a delay work to
1643 check the OVP status*/
1644 rc = qpnp_chg_read(chip, &ovp_ctl,
1645 chip->usb_chgpth_base + USB_OVP_CTL, 1);
1646
1647 if (rc) {
1648 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1649 chip->usb_chgpth_base + USB_OVP_CTL,
1650 rc);
1651 return rc;
1652 }
1653 ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
1654 schedule_delayed_work(&chip->usbin_health_check,
1655 msecs_to_jiffies(debounce[ovp_ctl]));
1656 } else {
1657 /* usb coarse-det rising edge, set the usb psy health
1658 status to unknown */
1659 pr_debug("usb coarse det clear, set usb health to unknown\n");
1660 chip->usbin_health = USBIN_UNKNOW;
1661 power_supply_set_health_state(chip->usb_psy,
1662 POWER_SUPPLY_HEALTH_UNKNOWN);
1663 power_supply_changed(chip->usb_psy);
1664 }
1665
1666 }
1667 return IRQ_HANDLED;
1668}
1669
David Keitel6e63bd52013-09-06 18:00:03 -07001670#define BATFET_LPM_MASK 0xC0
1671#define BATFET_LPM 0x40
1672#define BATFET_NO_LPM 0x00
1673static int
1674qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
1675{
1676 int rc = 0;
1677
David Keitelcadbc282013-09-26 11:39:14 -07001678 if (chip->charging_disabled || !chip->bat_if_base)
1679 return rc;
1680
David Keitel6e63bd52013-09-06 18:00:03 -07001681 if (chip->type == SMBB)
1682 rc = qpnp_chg_masked_write(chip,
1683 chip->bat_if_base + CHGR_BAT_IF_SPARE,
1684 BATFET_LPM_MASK,
1685 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1686 else
1687 rc = qpnp_chg_masked_write(chip,
1688 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
1689 BATFET_LPM_MASK,
1690 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1691
1692 return rc;
1693}
1694
David Keitel820a90d2014-03-25 18:18:04 -07001695#define USB_WALL_THRESHOLD_MA 500
David Keitel80668952012-07-27 14:25:49 -07001696#define ENUM_T_STOP_BIT BIT(0)
David Keitel820a90d2014-03-25 18:18:04 -07001697#define USB_5V_UV 5000000
1698#define USB_9V_UV 9000000
David Keitel80668952012-07-27 14:25:49 -07001699static irqreturn_t
1700qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1701{
1702 struct qpnp_chg_chip *chip = _chip;
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001703 int usb_present, host_mode, usbin_health;
1704 u8 psy_health_sts;
David Keitel80668952012-07-27 14:25:49 -07001705
1706 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001707 host_mode = qpnp_chg_is_otg_en_set(chip);
1708 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1709 usb_present, host_mode);
1710
1711 /* In host mode notifications cmoe from USB supply */
1712 if (host_mode)
1713 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001714
1715 if (chip->usb_present ^ usb_present) {
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07001716 chip->aicl_settled = false;
David Keitel80668952012-07-27 14:25:49 -07001717 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001718 if (!usb_present) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001719 /* when a valid charger inserted, and increase the
1720 * charger voltage to OVP threshold, then
1721 * usb_in_valid falling edge interrupt triggers.
1722 * So we handle the OVP monitor here, and ignore
1723 * other health state changes */
1724 if (chip->ovp_monitor_enable &&
1725 (chip->usb_valid_check_ovp)) {
1726 usbin_health =
1727 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001728 if ((chip->usbin_health != usbin_health)
1729 && (usbin_health == USBIN_OVP)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001730 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001731 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001732 POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1733 power_supply_set_health_state(
1734 chip->usb_psy,
1735 psy_health_sts);
1736 power_supply_changed(chip->usb_psy);
1737 }
1738 }
Xiaozhe Shi9e887be2014-05-21 15:18:58 -07001739 if (!qpnp_chg_is_dc_chg_plugged_in(chip))
David Keitel6e63bd52013-09-06 18:00:03 -07001740 chip->chg_done = false;
David Keitel820a90d2014-03-25 18:18:04 -07001741
1742 if (!qpnp_is_dc_higher_prio(chip))
1743 qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
1744
David Keitela9185602013-11-12 17:55:48 -08001745 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel7b0568482013-12-02 14:47:42 -08001746 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelcd2e1022014-05-02 17:25:15 -07001747 qpnp_chg_iusb_trim_set(chip, chip->usb_trim_default);
David Keitelfd305ee2013-07-19 20:19:06 -07001748 chip->prev_usb_max_ma = -EINVAL;
David Keitel9fd07382013-05-02 15:37:44 -07001749 } else {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001750 /* when OVP clamped usbin, and then decrease
1751 * the charger voltage to lower than the OVP
1752 * threshold, a usbin_valid rising edge
1753 * interrupt triggered. So we change the usb
1754 * psy health state back to good */
1755 if (chip->ovp_monitor_enable &&
1756 (chip->usb_valid_check_ovp)) {
1757 usbin_health =
1758 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001759 if ((chip->usbin_health != usbin_health)
1760 && (usbin_health == USBIN_OK)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001761 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001762 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001763 POWER_SUPPLY_HEALTH_GOOD;
1764 power_supply_set_health_state(
1765 chip->usb_psy,
1766 psy_health_sts);
1767 power_supply_changed(chip->usb_psy);
1768 }
1769 }
1770
David Keitel9fd07382013-05-02 15:37:44 -07001771 schedule_delayed_work(&chip->eoc_work,
1772 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001773 schedule_work(&chip->soc_check_work);
David Keitel9fd07382013-05-02 15:37:44 -07001774 }
David Keitel344c6972013-04-09 19:28:21 -07001775
David Keitel9fd07382013-05-02 15:37:44 -07001776 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel6e63bd52013-09-06 18:00:03 -07001777 schedule_work(&chip->batfet_lcl_work);
David Keitel80668952012-07-27 14:25:49 -07001778 }
1779
1780 return IRQ_HANDLED;
1781}
1782
Fenglin Wuc64e9942014-08-22 13:47:34 +08001783#define BUCK_VIN_LOOP_CMP_OVRD_MASK 0x30
1784static int
1785qpnp_chg_bypass_vchg_loop_debouncer(struct qpnp_chg_chip *chip, bool bypass)
1786{
1787 int rc;
1788 u8 value = bypass ? 0x10 : 0;
1789
1790 pr_debug("bypass vchg_loop debouncer: %d\n", bypass);
1791
1792 rc = qpnp_chg_masked_write(chip, chip->buck_base + SEC_ACCESS,
1793 0xFF, 0xA5, 1);
1794 if (rc) {
1795 pr_err("failed to write SEC_ACCESS register, rc = %d\n", rc);
1796 return rc;
1797 }
1798
1799 rc = qpnp_chg_masked_write(chip,
1800 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_2,
1801 BUCK_VIN_LOOP_CMP_OVRD_MASK, value, 1);
1802 if (rc)
1803 pr_err("failed to write BUCK_COMP_OVRIDE_2, rc = %d\n", rc);
1804
1805 return rc;
1806}
1807
1808static int
1809qpnp_chg_vchg_loop_debouncer_setting_get(struct qpnp_chg_chip *chip)
1810{
1811 int rc;
1812 u8 value;
1813
1814 rc = qpnp_chg_read(chip, &value,
1815 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_2, 1);
1816 if (rc) {
1817 pr_err("failed to read BUCK_CMP_OVERIDE_2, rc = %d\n", rc);
1818 return 0;
1819 }
1820
1821 return value & BUCK_VIN_LOOP_CMP_OVRD_MASK;
1822}
1823
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001824#define TEST_EN_SMBC_LOOP 0xE5
1825#define IBAT_REGULATION_DISABLE BIT(2)
David Keitel7450dcd2013-01-29 18:41:41 -08001826static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001827qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1828{
1829 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001830 int batt_temp_good, batt_present, rc;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001831
1832 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1833 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1834
Xiaozhe Shi87831862014-01-20 17:44:40 -08001835 batt_present = qpnp_chg_is_batt_present(chip);
1836 if (batt_present) {
1837 rc = qpnp_chg_masked_write(chip,
1838 chip->buck_base + SEC_ACCESS,
1839 0xFF,
1840 0xA5, 1);
1841 if (rc) {
1842 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1843 return rc;
1844 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001845
Xiaozhe Shi87831862014-01-20 17:44:40 -08001846 rc = qpnp_chg_masked_write(chip,
1847 chip->buck_base + TEST_EN_SMBC_LOOP,
1848 IBAT_REGULATION_DISABLE,
1849 batt_temp_good ? 0 : IBAT_REGULATION_DISABLE, 1);
1850 if (rc) {
1851 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1852 return rc;
1853 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001854 }
1855
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001856 pr_debug("psy changed batt_psy\n");
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001857 power_supply_changed(&chip->batt_psy);
1858 return IRQ_HANDLED;
1859}
1860
1861static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001862qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1863{
1864 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001865 int batt_present, batt_temp_good, rc;
David Keitel42ae0aa2013-03-08 16:20:10 -08001866
1867 batt_present = qpnp_chg_is_batt_present(chip);
1868 pr_debug("batt-pres triggered: %d\n", batt_present);
1869
1870 if (chip->batt_present ^ batt_present) {
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001871 if (batt_present) {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001872 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1873 rc = qpnp_chg_masked_write(chip,
1874 chip->buck_base + SEC_ACCESS,
1875 0xFF,
1876 0xA5, 1);
1877 if (rc) {
1878 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1879 return rc;
1880 }
1881
1882 rc = qpnp_chg_masked_write(chip,
1883 chip->buck_base + TEST_EN_SMBC_LOOP,
1884 IBAT_REGULATION_DISABLE,
1885 batt_temp_good
1886 ? 0 : IBAT_REGULATION_DISABLE, 1);
1887 if (rc) {
1888 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1889 return rc;
1890 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001891 schedule_work(&chip->insertion_ocv_work);
1892 } else {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001893 rc = qpnp_chg_masked_write(chip,
1894 chip->buck_base + SEC_ACCESS,
1895 0xFF,
1896 0xA5, 1);
1897 if (rc) {
1898 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1899 return rc;
1900 }
1901
1902 rc = qpnp_chg_masked_write(chip,
1903 chip->buck_base + TEST_EN_SMBC_LOOP,
1904 IBAT_REGULATION_DISABLE,
1905 0, 1);
1906 if (rc) {
1907 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1908 return rc;
1909 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001910 chip->insertion_ocv_uv = 0;
1911 qpnp_chg_charge_en(chip, 0);
1912 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001913 chip->batt_present = batt_present;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001914 pr_debug("psy changed batt_psy\n");
David Keitel42ae0aa2013-03-08 16:20:10 -08001915 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001916 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001917 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001918
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001919 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07001920 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001921 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001922 schedule_work(&chip->adc_measure_work);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001923 } else if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitelec3c09802013-06-13 13:05:30 -07001924 && !batt_present) {
David Keitelecab15a2013-08-06 15:41:39 -07001925 schedule_work(&chip->adc_disable_work);
David Keitelec3c09802013-06-13 13:05:30 -07001926 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001927 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001928 }
1929
1930 return IRQ_HANDLED;
1931}
1932
1933static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001934qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1935{
1936 struct qpnp_chg_chip *chip = _chip;
1937 int dc_present;
1938
1939 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1940 pr_debug("dcin-valid triggered: %d\n", dc_present);
1941
1942 if (chip->dc_present ^ dc_present) {
1943 chip->dc_present = dc_present;
David Keitel6d4b9da2013-09-05 17:38:40 -07001944 if (qpnp_chg_is_otg_en_set(chip))
1945 qpnp_chg_force_run_on_batt(chip, !dc_present ? 1 : 0);
David Keitel86628cc2014-06-09 13:24:00 -07001946 if (!dc_present && (!qpnp_chg_is_usb_chg_plugged_in(chip) ||
1947 qpnp_chg_is_otg_en_set(chip))) {
David Keitel9fd07382013-05-02 15:37:44 -07001948 chip->chg_done = false;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001949 } else {
David Keitel9fd07382013-05-02 15:37:44 -07001950 schedule_delayed_work(&chip->eoc_work,
1951 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001952 schedule_work(&chip->soc_check_work);
1953 }
David Keitel820a90d2014-03-25 18:18:04 -07001954
1955 if (qpnp_is_dc_higher_prio(chip)) {
1956 pr_debug("dc has higher priority\n");
1957 if (dc_present) {
1958 qpnp_chg_iusbmax_set(chip,
1959 QPNP_CHG_I_MAX_MIN_100);
1960 power_supply_set_voltage_limit(chip->usb_psy,
1961 USB_5V_UV);
1962 } else {
1963 chip->aicl_settled = false;
1964 qpnp_chg_iusbmax_set(chip,
1965 USB_WALL_THRESHOLD_MA);
1966 power_supply_set_voltage_limit(chip->usb_psy,
1967 USB_9V_UV);
1968 }
1969 }
1970
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001971 pr_debug("psy changed dc_psy\n");
David Keitel7450dcd2013-01-29 18:41:41 -08001972 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001973 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001974 power_supply_changed(&chip->batt_psy);
David Keitel6e63bd52013-09-06 18:00:03 -07001975 schedule_work(&chip->batfet_lcl_work);
David Keitel7450dcd2013-01-29 18:41:41 -08001976 }
1977
1978 return IRQ_HANDLED;
1979}
1980
David Keitel80668952012-07-27 14:25:49 -07001981#define CHGR_CHG_FAILED_BIT BIT(7)
1982static irqreturn_t
1983qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1984{
1985 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001986 int rc;
David Keitel80668952012-07-27 14:25:49 -07001987
David Keitel9fd07382013-05-02 15:37:44 -07001988 pr_debug("chg_failed triggered\n");
1989
David Keitel80668952012-07-27 14:25:49 -07001990 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001991 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001992 CHGR_CHG_FAILED_BIT,
1993 CHGR_CHG_FAILED_BIT, 1);
1994 if (rc)
1995 pr_err("Failed to write chg_fail clear bit!\n");
1996
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001997 if (chip->bat_if_base) {
1998 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001999 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002000 }
2001 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07002002 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002003 if (chip->dc_chgpth_base) {
2004 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002005 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002006 }
David Keitel80668952012-07-27 14:25:49 -07002007 return IRQ_HANDLED;
2008}
2009
2010static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08002011qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
2012{
2013 struct qpnp_chg_chip *chip = _chip;
2014
2015 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08002016
2017 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002018 if (chip->bat_if_base) {
2019 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07002020 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002021 }
David Keitel42ae0aa2013-03-08 16:20:10 -08002022
2023 return IRQ_HANDLED;
2024}
2025
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002026static int qpnp_chg_is_fastchg_on(struct qpnp_chg_chip *chip)
David Keitel42ae0aa2013-03-08 16:20:10 -08002027{
David Keitel337bd862013-07-15 21:42:58 -07002028 u8 chgr_sts;
2029 int rc;
2030
David Keitelbf6a1062014-01-23 10:57:36 -08002031 qpnp_chg_irq_wake_disable(&chip->chg_fastchg);
2032
David Keitel337bd862013-07-15 21:42:58 -07002033 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002034 if (rc) {
2035 pr_err("failed to read interrupt status %d\n", rc);
2036 return rc;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002037 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002038 pr_debug("chgr_sts 0x%x\n", chgr_sts);
2039 return (chgr_sts & FAST_CHG_ON_IRQ) ? 1 : 0;
2040}
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002041
David Keitel59fbb762014-02-05 16:46:24 -08002042#define VBATDET_BYPASS 0x01
2043static int
2044bypass_vbatdet_comp(struct qpnp_chg_chip *chip, bool bypass)
2045{
2046 int rc;
2047
2048 pr_debug("bypass %d\n", bypass);
2049 rc = qpnp_chg_masked_write(chip,
2050 chip->chgr_base + SEC_ACCESS,
2051 0xA5,
2052 0xA5, 1);
2053 rc |= qpnp_chg_masked_write(chip,
2054 chip->chgr_base + CHGR_COMP_OVR1,
2055 0xFF,
2056 bypass ? VBATDET_BYPASS : 0, 1);
2057 if (rc) {
2058 pr_err("Failed to bypass vbatdet comp rc = %d\n", rc);
2059 return rc;
2060 }
2061
2062 return rc;
2063}
2064
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002065static irqreturn_t
2066qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
2067{
2068 struct qpnp_chg_chip *chip = _chip;
2069 bool fastchg_on = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002070
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002071 fastchg_on = qpnp_chg_is_fastchg_on(chip);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002072
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002073 pr_debug("FAST_CHG IRQ triggered, fastchg_on: %d\n", fastchg_on);
David Keitel337bd862013-07-15 21:42:58 -07002074
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002075 if (chip->fastchg_on ^ fastchg_on) {
2076 chip->fastchg_on = fastchg_on;
2077 if (chip->bat_if_base) {
2078 pr_debug("psy changed batt_psy\n");
2079 power_supply_changed(&chip->batt_psy);
2080 }
2081
2082 pr_debug("psy changed usb_psy\n");
2083 power_supply_changed(chip->usb_psy);
2084
2085 if (chip->dc_chgpth_base) {
2086 pr_debug("psy changed dc_psy\n");
2087 power_supply_changed(&chip->dc_psy);
2088 }
2089
2090 if (fastchg_on) {
2091 chip->chg_done = false;
David Keitel59fbb762014-02-05 16:46:24 -08002092 bypass_vbatdet_comp(chip, 1);
2093 if (chip->bat_is_warm || chip->bat_is_cool) {
2094 qpnp_chg_set_appropriate_vddmax(chip);
2095 qpnp_chg_set_appropriate_battery_current(chip);
2096 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002097
2098 if (chip->resuming_charging) {
2099 chip->resuming_charging = false;
2100 qpnp_chg_set_appropriate_vbatdet(chip);
2101 }
2102
2103 if (!chip->charging_disabled) {
2104 schedule_delayed_work(&chip->eoc_work,
2105 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2106 pm_stay_awake(chip->dev);
2107 }
David Keitel975b5352014-01-27 14:28:04 -08002108 if (chip->parallel_ovp_mode)
2109 switch_parallel_ovp_mode(chip, 1);
David Keitelcd2e1022014-05-02 17:25:15 -07002110
2111 if (ext_ovp_isns_present &&
2112 chip->ext_ovp_ic_gpio_enabled) {
2113 pr_debug("EXT OVP IC ISNS enabled\n");
2114 gpio_direction_output(
2115 chip->ext_ovp_isns_gpio, 1);
2116 }
David Keitel975b5352014-01-27 14:28:04 -08002117 } else {
2118 if (chip->parallel_ovp_mode)
2119 switch_parallel_ovp_mode(chip, 0);
David Keitel59fbb762014-02-05 16:46:24 -08002120 if (!chip->bat_is_warm && !chip->bat_is_cool)
2121 bypass_vbatdet_comp(chip, 0);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08002122 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002123 }
2124
David Keitel47185a62013-05-15 18:54:10 -07002125 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -08002126
2127 return IRQ_HANDLED;
2128}
2129
David Keitel03ee6b52012-10-22 12:25:19 -07002130static int
David Keitel432e1232013-06-05 16:10:18 -07002131qpnp_dc_property_is_writeable(struct power_supply *psy,
2132 enum power_supply_property psp)
2133{
2134 switch (psp) {
2135 case POWER_SUPPLY_PROP_CURRENT_MAX:
2136 return 1;
2137 default:
2138 break;
2139 }
2140
2141 return 0;
2142}
2143
2144static int
David Keitel03ee6b52012-10-22 12:25:19 -07002145qpnp_batt_property_is_writeable(struct power_supply *psy,
2146 enum power_supply_property psp)
2147{
2148 switch (psp) {
2149 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08002150 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07002151 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel2586f0a2013-08-20 10:02:26 -07002152 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002153 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
Fenglin Wuc64e9942014-08-22 13:47:34 +08002154 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
David Keitel337bd862013-07-15 21:42:58 -07002155 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07002156 case POWER_SUPPLY_PROP_COOL_TEMP:
2157 case POWER_SUPPLY_PROP_WARM_TEMP:
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002158 case POWER_SUPPLY_PROP_CAPACITY:
David Keitel03ee6b52012-10-22 12:25:19 -07002159 return 1;
2160 default:
2161 break;
2162 }
2163
2164 return 0;
2165}
2166
David Keitel6f865cd2012-11-30 15:04:32 -08002167static int
David Keitelbe208252013-01-31 14:49:25 -08002168qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
2169{
2170 int rc;
2171
2172 if (chip->charging_disabled && enable) {
2173 pr_debug("Charging disabled\n");
2174 return 0;
2175 }
2176
2177 rc = qpnp_chg_charge_en(chip, enable);
2178 if (rc) {
2179 pr_err("Failed to control charging %d\n", rc);
2180 return rc;
2181 }
2182
2183 rc = qpnp_chg_force_run_on_batt(chip, !enable);
2184 if (rc)
2185 pr_err("Failed to control charging %d\n", rc);
2186
2187 return rc;
2188}
2189
David Keitel454ee842013-03-08 16:19:11 -08002190static int
2191switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002192{
2193 int rc;
2194
2195 pr_debug("switch to charge mode\n");
2196 if (!qpnp_chg_is_otg_en_set(chip))
2197 return 0;
2198
David Keitel8b9bd312014-01-15 14:44:00 -08002199 if (chip->type == SMBBP) {
2200 rc = qpnp_chg_masked_write(chip,
2201 chip->boost_base + BOOST_ILIM,
2202 BOOST_ILIMT_MASK,
2203 BOOST_ILIMIT_DEF, 1);
2204 if (rc) {
2205 pr_err("Failed to set ilim rc = %d\n", rc);
2206 return rc;
2207 }
2208 }
2209
David Keitel6f865cd2012-11-30 15:04:32 -08002210 /* enable usb ovp fet */
2211 rc = qpnp_chg_masked_write(chip,
2212 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2213 USB_OTG_EN_BIT,
2214 0, 1);
2215 if (rc) {
2216 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
2217 return rc;
2218 }
2219
2220 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2221 if (rc) {
2222 pr_err("Failed re-enable charging rc = %d\n", rc);
2223 return rc;
2224 }
2225
2226 return 0;
2227}
2228
David Keitel454ee842013-03-08 16:19:11 -08002229static int
2230switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002231{
2232 int rc;
David Keitel8b9bd312014-01-15 14:44:00 -08002233 u8 usb_sts;
David Keitel6f865cd2012-11-30 15:04:32 -08002234
2235 pr_debug("switch to host mode\n");
2236 if (qpnp_chg_is_otg_en_set(chip))
2237 return 0;
2238
David Keitel975b5352014-01-27 14:28:04 -08002239 if (chip->parallel_ovp_mode)
2240 switch_parallel_ovp_mode(chip, 0);
2241
David Keitel8b9bd312014-01-15 14:44:00 -08002242 if (chip->type == SMBBP) {
2243 rc = qpnp_chg_masked_write(chip,
2244 chip->boost_base + BOOST_ILIM,
2245 BOOST_ILIMT_MASK,
2246 BOOST_ILIMIT_MIN, 1);
2247 if (rc) {
2248 pr_err("Failed to turn configure ilim rc = %d\n", rc);
2249 return rc;
2250 }
2251 }
2252
David Keitel6d4b9da2013-09-05 17:38:40 -07002253 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
2254 rc = qpnp_chg_force_run_on_batt(chip, 1);
2255 if (rc) {
2256 pr_err("Failed to disable charging rc = %d\n", rc);
2257 return rc;
2258 }
David Keitel6f865cd2012-11-30 15:04:32 -08002259 }
2260
2261 /* force usb ovp fet off */
2262 rc = qpnp_chg_masked_write(chip,
2263 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2264 USB_OTG_EN_BIT,
2265 USB_OTG_EN_BIT, 1);
2266 if (rc) {
2267 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
2268 return rc;
2269 }
2270
David Keitel8b9bd312014-01-15 14:44:00 -08002271 if (chip->type == SMBBP) {
2272 /* Wait for OCP circuitry to be powered up */
2273 msleep(100);
2274 rc = qpnp_chg_read(chip, &usb_sts,
2275 INT_RT_STS(chip->usb_chgpth_base), 1);
2276 if (rc) {
2277 pr_err("failed to read interrupt sts %d\n", rc);
2278 return rc;
2279 }
2280
2281 if (usb_sts & COARSE_DET_USB_IRQ) {
2282 rc = qpnp_chg_masked_write(chip,
2283 chip->boost_base + BOOST_ILIM,
2284 BOOST_ILIMT_MASK,
2285 BOOST_ILIMIT_DEF, 1);
2286 if (rc) {
2287 pr_err("Failed to set ilim rc = %d\n", rc);
2288 return rc;
2289 }
2290 } else {
2291 pr_warn_ratelimited("USB short to GND detected!\n");
2292 }
2293 }
2294
David Keitel6f865cd2012-11-30 15:04:32 -08002295 return 0;
2296}
2297
David Keitel80668952012-07-27 14:25:49 -07002298static enum power_supply_property pm_power_props_mains[] = {
2299 POWER_SUPPLY_PROP_PRESENT,
2300 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07002301 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07002302};
2303
2304static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07002305 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07002306 POWER_SUPPLY_PROP_STATUS,
2307 POWER_SUPPLY_PROP_CHARGE_TYPE,
2308 POWER_SUPPLY_PROP_HEALTH,
2309 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002310 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07002311 POWER_SUPPLY_PROP_TECHNOLOGY,
2312 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
2313 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
2314 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2315 POWER_SUPPLY_PROP_CAPACITY,
2316 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07002317 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
David Keitel2586f0a2013-08-20 10:02:26 -07002318 POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002319 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
Fenglin Wuc64e9942014-08-22 13:47:34 +08002320 POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS,
David Keitel337bd862013-07-15 21:42:58 -07002321 POWER_SUPPLY_PROP_VOLTAGE_MIN,
2322 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07002323 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302324 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07002325 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07002326 POWER_SUPPLY_PROP_COOL_TEMP,
2327 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08002328 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302329 POWER_SUPPLY_PROP_CYCLE_COUNT,
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002330 POWER_SUPPLY_PROP_VOLTAGE_OCV,
David Keitel80668952012-07-27 14:25:49 -07002331};
2332
2333static char *pm_power_supplied_to[] = {
2334 "battery",
2335};
2336
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07002337static char *pm_batt_supplied_to[] = {
2338 "bms",
2339};
2340
David Keitel337bd862013-07-15 21:42:58 -07002341static int charger_monitor;
2342module_param(charger_monitor, int, 0644);
2343
David Keitel2586f0a2013-08-20 10:02:26 -07002344static int ext_ovp_present;
2345module_param(ext_ovp_present, int, 0444);
2346
David Keitelcd2e1022014-05-02 17:25:15 -07002347#define OVP_USB_WALL_TRSH_MA 200
David Keitel80668952012-07-27 14:25:49 -07002348static int
2349qpnp_power_get_property_mains(struct power_supply *psy,
2350 enum power_supply_property psp,
2351 union power_supply_propval *val)
2352{
2353 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2354 dc_psy);
2355
2356 switch (psp) {
2357 case POWER_SUPPLY_PROP_PRESENT:
2358 case POWER_SUPPLY_PROP_ONLINE:
2359 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07002360 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07002361 return 0;
2362
2363 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
2364 break;
David Keitel432e1232013-06-05 16:10:18 -07002365 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07002366 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07002367 break;
David Keitel80668952012-07-27 14:25:49 -07002368 default:
2369 return -EINVAL;
2370 }
2371 return 0;
2372}
2373
David Keitel7ac385e2013-08-19 18:02:40 -07002374static void
2375qpnp_aicl_check_work(struct work_struct *work)
2376{
2377 struct delayed_work *dwork = to_delayed_work(work);
2378 struct qpnp_chg_chip *chip = container_of(dwork,
2379 struct qpnp_chg_chip, aicl_check_work);
2380 union power_supply_propval ret = {0,};
2381
2382 if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
2383 chip->usb_psy->get_property(chip->usb_psy,
2384 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
2385 if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
2386 pr_debug("no charger_monitor present set iusbmax %d\n",
2387 ret.intval / 1000);
2388 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2389 }
2390 } else {
2391 pr_debug("charger_monitor is present\n");
2392 }
2393 chip->charger_monitor_checked = true;
2394}
2395
David Keitel80668952012-07-27 14:25:49 -07002396static int
2397get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
2398{
2399 int rc = 0;
2400 struct qpnp_vadc_result results;
2401
David Keitelfe51cb92013-04-02 19:42:58 -07002402 if (chip->revision == 0 && chip->type == SMBB) {
2403 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
2404 return 0;
2405 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002406 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07002407 if (rc) {
2408 pr_err("Unable to read vbat rc=%d\n", rc);
2409 return 0;
2410 }
2411 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07002412 }
2413}
2414
2415#define BATT_PRES_BIT BIT(7)
2416static int
2417get_prop_batt_present(struct qpnp_chg_chip *chip)
2418{
2419 u8 batt_present;
2420 int rc;
2421
2422 rc = qpnp_chg_read(chip, &batt_present,
2423 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
2424 if (rc) {
2425 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
2426 return 0;
2427 };
2428 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
2429}
2430
2431#define BATT_TEMP_HOT BIT(6)
2432#define BATT_TEMP_OK BIT(7)
2433static int
2434get_prop_batt_health(struct qpnp_chg_chip *chip)
2435{
2436 u8 batt_health;
2437 int rc;
2438
2439 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07002440 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07002441 if (rc) {
2442 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
2443 return POWER_SUPPLY_HEALTH_UNKNOWN;
2444 };
2445
2446 if (BATT_TEMP_OK & batt_health)
2447 return POWER_SUPPLY_HEALTH_GOOD;
2448 if (BATT_TEMP_HOT & batt_health)
2449 return POWER_SUPPLY_HEALTH_OVERHEAT;
2450 else
2451 return POWER_SUPPLY_HEALTH_COLD;
2452}
2453
2454static int
2455get_prop_charge_type(struct qpnp_chg_chip *chip)
2456{
2457 int rc;
2458 u8 chgr_sts;
2459
2460 if (!get_prop_batt_present(chip))
2461 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2462
2463 rc = qpnp_chg_read(chip, &chgr_sts,
2464 INT_RT_STS(chip->chgr_base), 1);
2465 if (rc) {
2466 pr_err("failed to read interrupt sts %d\n", rc);
2467 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2468 }
2469
2470 if (chgr_sts & TRKL_CHG_ON_IRQ)
2471 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
2472 if (chgr_sts & FAST_CHG_ON_IRQ)
2473 return POWER_SUPPLY_CHARGE_TYPE_FAST;
2474
2475 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2476}
2477
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002478#define DEFAULT_CAPACITY 50
2479static int
2480get_batt_capacity(struct qpnp_chg_chip *chip)
2481{
2482 union power_supply_propval ret = {0,};
2483
2484 if (chip->fake_battery_soc >= 0)
2485 return chip->fake_battery_soc;
2486 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2487 return DEFAULT_CAPACITY;
2488 if (chip->bms_psy) {
2489 chip->bms_psy->get_property(chip->bms_psy,
2490 POWER_SUPPLY_PROP_CAPACITY, &ret);
2491 return ret.intval;
2492 }
2493 return DEFAULT_CAPACITY;
2494}
2495
David Keitel80668952012-07-27 14:25:49 -07002496static int
2497get_prop_batt_status(struct qpnp_chg_chip *chip)
2498{
2499 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002500 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07002501
David Keitel9fd07382013-05-02 15:37:44 -07002502 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07002503 if (rc) {
2504 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08002505 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07002506 }
2507
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002508 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
2509 if (rc) {
2510 pr_err("failed to read bat_if sts %d\n", rc);
2511 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2512 }
2513
David Keitela8099ff2014-01-06 11:31:40 -08002514 if ((chgr_sts & TRKL_CHG_ON_IRQ) && !(bat_if_sts & BAT_FET_ON_IRQ))
David Keitel80668952012-07-27 14:25:49 -07002515 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002516 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07002517 return POWER_SUPPLY_STATUS_CHARGING;
2518
Chunmei Caib3999b22014-07-11 15:38:13 +08002519 /*
2520 * Report full if state of charge is 100 or chg_done is true
2521 * when a charger is connected and boost is disabled
2522 */
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002523 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
Chunmei Caib3999b22014-07-11 15:38:13 +08002524 qpnp_chg_is_dc_chg_plugged_in(chip)) &&
2525 (chip->chg_done || get_batt_capacity(chip) == 100)
2526 && qpnp_chg_is_boost_en_set(chip) == 0) {
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002527 return POWER_SUPPLY_STATUS_FULL;
2528 }
2529
David Keitel80668952012-07-27 14:25:49 -07002530 return POWER_SUPPLY_STATUS_DISCHARGING;
2531}
2532
2533static int
2534get_prop_current_now(struct qpnp_chg_chip *chip)
2535{
2536 union power_supply_propval ret = {0,};
2537
2538 if (chip->bms_psy) {
2539 chip->bms_psy->get_property(chip->bms_psy,
2540 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
2541 return ret.intval;
2542 } else {
2543 pr_debug("No BMS supply registered return 0\n");
2544 }
2545
2546 return 0;
2547}
2548
2549static int
2550get_prop_full_design(struct qpnp_chg_chip *chip)
2551{
2552 union power_supply_propval ret = {0,};
2553
2554 if (chip->bms_psy) {
2555 chip->bms_psy->get_property(chip->bms_psy,
2556 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
2557 return ret.intval;
2558 } else {
2559 pr_debug("No BMS supply registered return 0\n");
2560 }
2561
2562 return 0;
2563}
2564
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302565static int
2566get_prop_charge_full(struct qpnp_chg_chip *chip)
2567{
2568 union power_supply_propval ret = {0,};
2569
2570 if (chip->bms_psy) {
2571 chip->bms_psy->get_property(chip->bms_psy,
2572 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
2573 return ret.intval;
2574 } else {
2575 pr_debug("No BMS supply registered return 0\n");
2576 }
2577
2578 return 0;
2579}
2580
David Keitel80668952012-07-27 14:25:49 -07002581static int
2582get_prop_capacity(struct qpnp_chg_chip *chip)
2583{
2584 union power_supply_propval ret = {0,};
Xiaozhe Shibda84992013-09-05 10:39:11 -07002585 int battery_status, bms_status, soc, charger_in;
David Keitel80668952012-07-27 14:25:49 -07002586
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002587 if (chip->fake_battery_soc >= 0)
2588 return chip->fake_battery_soc;
2589
David Keitel3dd5e0f2012-12-12 18:12:36 -08002590 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2591 return DEFAULT_CAPACITY;
2592
David Keitel80668952012-07-27 14:25:49 -07002593 if (chip->bms_psy) {
2594 chip->bms_psy->get_property(chip->bms_psy,
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002595 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002596 soc = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002597 battery_status = get_prop_batt_status(chip);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002598 chip->bms_psy->get_property(chip->bms_psy,
2599 POWER_SUPPLY_PROP_STATUS, &ret);
2600 bms_status = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002601 charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
2602 qpnp_chg_is_dc_chg_plugged_in(chip);
2603
2604 if (battery_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shibda84992013-09-05 10:39:11 -07002605 && bms_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002606 && charger_in
Xiaozhe Shie8504482013-10-30 18:10:31 -07002607 && !chip->bat_is_cool
2608 && !chip->bat_is_warm
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002609 && !chip->resuming_charging
2610 && !chip->charging_disabled
2611 && chip->soc_resume_limit
Xiaozhe Shibda84992013-09-05 10:39:11 -07002612 && soc <= chip->soc_resume_limit) {
2613 pr_debug("resuming charging at %d%% soc\n", soc);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002614 chip->resuming_charging = true;
David Keitelbf6a1062014-01-23 10:57:36 -08002615 qpnp_chg_irq_wake_enable(&chip->chg_fastchg);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002616 qpnp_chg_set_appropriate_vbatdet(chip);
2617 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2618 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002619 if (soc == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07002620 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
2621 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07002622 pr_warn_ratelimited("Battery 0, CHG absent\n");
2623 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002624 return soc;
David Keitel80668952012-07-27 14:25:49 -07002625 } else {
2626 pr_debug("No BMS supply registered return 50\n");
2627 }
2628
2629 /* return default capacity to avoid userspace
2630 * from shutting down unecessarily */
2631 return DEFAULT_CAPACITY;
2632}
2633
David Keitel3dd5e0f2012-12-12 18:12:36 -08002634#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07002635#define MAX_TOLERABLE_BATT_TEMP_DDC 680
2636static int
2637get_prop_batt_temp(struct qpnp_chg_chip *chip)
2638{
2639 int rc = 0;
2640 struct qpnp_vadc_result results;
2641
David Keitel3dd5e0f2012-12-12 18:12:36 -08002642 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2643 return DEFAULT_TEMP;
2644
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002645 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07002646 if (rc) {
2647 pr_debug("Unable to read batt temperature rc=%d\n", rc);
2648 return 0;
David Keitel80668952012-07-27 14:25:49 -07002649 }
Xiaozhe Shi4c8458a2013-11-26 13:00:56 -08002650 pr_debug("get_bat_temp %d, %lld\n",
David Keitela2dbfc72013-06-07 11:10:14 -07002651 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07002652
David Keitela2dbfc72013-06-07 11:10:14 -07002653 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07002654}
2655
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302656static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
2657{
2658 union power_supply_propval ret = {0,};
2659
2660 if (chip->bms_psy)
2661 chip->bms_psy->get_property(chip->bms_psy,
2662 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
2663 return ret.intval;
2664}
2665
David Keitel337bd862013-07-15 21:42:58 -07002666static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
2667{
2668 u8 buck_sts;
2669 int rc;
2670
2671 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2672
2673 if (rc) {
2674 pr_err("spmi read failed: addr=%03X, rc=%d\n",
2675 INT_RT_STS(chip->buck_base), rc);
2676 return rc;
2677 }
2678 pr_debug("buck usb sts 0x%x\n", buck_sts);
2679
2680 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
2681}
2682
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002683static int get_prop_online(struct qpnp_chg_chip *chip)
2684{
2685 return qpnp_chg_is_batfet_closed(chip);
2686}
2687
David Keitel80668952012-07-27 14:25:49 -07002688static void
2689qpnp_batt_external_power_changed(struct power_supply *psy)
2690{
2691 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2692 batt_psy);
2693 union power_supply_propval ret = {0,};
2694
2695 if (!chip->bms_psy)
2696 chip->bms_psy = power_supply_get_by_name("bms");
2697
2698 chip->usb_psy->get_property(chip->usb_psy,
2699 POWER_SUPPLY_PROP_ONLINE, &ret);
2700
David Keitelc69f2d62013-03-17 14:52:35 -07002701 /* Only honour requests while USB is present */
2702 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002703 chip->usb_psy->get_property(chip->usb_psy,
2704 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07002705
2706 if (chip->prev_usb_max_ma == ret.intval)
2707 goto skip_set_iusb_max;
2708
Zhenhua Huangdd619742013-10-24 10:02:07 +08002709 chip->prev_usb_max_ma = ret.intval;
2710
David Keitel87473252013-03-21 14:39:45 -07002711 if (ret.intval <= 2 && !chip->use_default_batt_values &&
2712 get_prop_batt_present(chip)) {
David Keitela9185602013-11-12 17:55:48 -08002713 if (ret.intval == 2)
2714 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07002715 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07002716 } else {
David Keiteld681cda2012-10-02 15:44:21 -07002717 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel820a90d2014-03-25 18:18:04 -07002718 if (qpnp_is_dc_higher_prio(chip)
2719 && qpnp_chg_is_dc_chg_plugged_in(chip)) {
2720 pr_debug("dc has higher priority\n");
2721 qpnp_chg_iusbmax_set(chip,
2722 QPNP_CHG_I_MAX_MIN_100);
2723 } else if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
David Keitel7ac385e2013-08-19 18:02:40 -07002724 && (charger_monitor ||
2725 !chip->charger_monitor_checked)) {
David Keitel820a90d2014-03-25 18:18:04 -07002726 if (!qpnp_is_dc_higher_prio(chip))
2727 qpnp_chg_idcmax_set(chip,
2728 QPNP_CHG_I_MAX_MIN_100);
David Keitelcd2e1022014-05-02 17:25:15 -07002729 if (unlikely(ext_ovp_present)) {
David Keitel820a90d2014-03-25 18:18:04 -07002730 qpnp_chg_iusbmax_set(chip,
2731 OVP_USB_WALL_TRSH_MA);
David Keitelcd2e1022014-05-02 17:25:15 -07002732 } else if (unlikely(
2733 ext_ovp_isns_present)) {
2734 qpnp_chg_iusb_trim_set(chip, 0);
2735 qpnp_chg_iusbmax_set(chip,
2736 IOVP_USB_WALL_TRSH_MA);
2737 } else {
2738 qpnp_chg_iusbmax_set(chip,
2739 USB_WALL_THRESHOLD_MA);
2740 }
David Keitel337bd862013-07-15 21:42:58 -07002741 } else {
2742 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2743 }
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002744
2745 if ((chip->flags & POWER_STAGE_WA)
2746 && ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
Zhenhua Huangdc335512013-10-30 11:45:15 +08002747 && !chip->power_stage_workaround_running
2748 && chip->power_stage_workaround_enable) {
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002749 chip->power_stage_workaround_running = true;
2750 pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
2751 charger_monitor);
2752 schedule_work(&chip->reduce_power_stage_work);
2753 }
David Keitelc69f2d62013-03-17 14:52:35 -07002754 }
David Keitel80668952012-07-27 14:25:49 -07002755 }
2756
David Keitelfd305ee2013-07-19 20:19:06 -07002757skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07002758 pr_debug("end of power supply changed\n");
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002759 pr_debug("psy changed batt_psy\n");
David Keitel80668952012-07-27 14:25:49 -07002760 power_supply_changed(&chip->batt_psy);
2761}
2762
2763static int
2764qpnp_batt_power_get_property(struct power_supply *psy,
2765 enum power_supply_property psp,
2766 union power_supply_propval *val)
2767{
2768 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2769 batt_psy);
2770
2771 switch (psp) {
2772 case POWER_SUPPLY_PROP_STATUS:
2773 val->intval = get_prop_batt_status(chip);
2774 break;
2775 case POWER_SUPPLY_PROP_CHARGE_TYPE:
2776 val->intval = get_prop_charge_type(chip);
2777 break;
2778 case POWER_SUPPLY_PROP_HEALTH:
2779 val->intval = get_prop_batt_health(chip);
2780 break;
2781 case POWER_SUPPLY_PROP_PRESENT:
2782 val->intval = get_prop_batt_present(chip);
2783 break;
2784 case POWER_SUPPLY_PROP_TECHNOLOGY:
2785 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2786 break;
2787 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2788 val->intval = chip->max_voltage_mv * 1000;
2789 break;
2790 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2791 val->intval = chip->min_voltage_mv * 1000;
2792 break;
2793 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2794 val->intval = get_prop_battery_voltage_now(chip);
2795 break;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002796 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2797 val->intval = chip->insertion_ocv_uv;
2798 break;
David Keitel80668952012-07-27 14:25:49 -07002799 case POWER_SUPPLY_PROP_TEMP:
2800 val->intval = get_prop_batt_temp(chip);
2801 break;
David Keitelec3c09802013-06-13 13:05:30 -07002802 case POWER_SUPPLY_PROP_COOL_TEMP:
2803 val->intval = chip->cool_bat_decidegc;
2804 break;
2805 case POWER_SUPPLY_PROP_WARM_TEMP:
2806 val->intval = chip->warm_bat_decidegc;
2807 break;
David Keitel80668952012-07-27 14:25:49 -07002808 case POWER_SUPPLY_PROP_CAPACITY:
2809 val->intval = get_prop_capacity(chip);
2810 break;
2811 case POWER_SUPPLY_PROP_CURRENT_NOW:
2812 val->intval = get_prop_current_now(chip);
2813 break;
2814 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2815 val->intval = get_prop_full_design(chip);
2816 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302817 case POWER_SUPPLY_PROP_CHARGE_FULL:
2818 val->intval = get_prop_charge_full(chip);
2819 break;
David Keitelb80eda82012-10-15 10:49:11 -07002820 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07002821 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07002822 break;
David Keitelbe208252013-01-31 14:49:25 -08002823 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2824 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07002825 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302826 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2827 val->intval = get_prop_cycle_count(chip);
2828 break;
David Keitel337bd862013-07-15 21:42:58 -07002829 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
2830 val->intval = get_prop_vchg_loop(chip);
2831 break;
2832 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2833 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
2834 break;
David Keitel2586f0a2013-08-20 10:02:26 -07002835 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
2836 val->intval = qpnp_chg_iusb_trim_get(chip);
2837 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002838 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
2839 val->intval = chip->aicl_settled;
2840 break;
David Keitel337bd862013-07-15 21:42:58 -07002841 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2842 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
2843 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002844 case POWER_SUPPLY_PROP_ONLINE:
2845 val->intval = get_prop_online(chip);
2846 break;
Fenglin Wuc64e9942014-08-22 13:47:34 +08002847 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
2848 val->intval = qpnp_chg_vchg_loop_debouncer_setting_get(chip);
2849 break;
2850
David Keitelb80eda82012-10-15 10:49:11 -07002851 default:
2852 return -EINVAL;
2853 }
2854
David Keitelb80eda82012-10-15 10:49:11 -07002855 return 0;
David Keitel80668952012-07-27 14:25:49 -07002856}
2857
David Keitel89c17752013-06-28 14:52:48 -07002858#define BTC_CONFIG_ENABLED BIT(7)
2859#define BTC_COLD BIT(1)
2860#define BTC_HOT BIT(0)
2861static int
2862qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
2863{
2864 u8 btc_cfg = 0, mask = 0;
2865
2866 /* Do nothing if battery peripheral not present */
2867 if (!chip->bat_if_base)
2868 return 0;
2869
2870 if ((chip->hot_batt_p == HOT_THD_25_PCT)
2871 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
2872 btc_cfg |= btc_value[chip->hot_batt_p];
2873 mask |= BTC_HOT;
2874 }
2875
2876 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
2877 (chip->cold_batt_p == COLD_THD_80_PCT)) {
2878 btc_cfg |= btc_value[chip->cold_batt_p];
2879 mask |= BTC_COLD;
2880 }
2881
2882 if (chip->btc_disabled)
2883 mask |= BTC_CONFIG_ENABLED;
2884
2885 return qpnp_chg_masked_write(chip,
2886 chip->bat_if_base + BAT_IF_BTC_CTRL,
2887 mask, btc_cfg, 1);
2888}
2889
David Keitel5d44fa52012-12-03 16:37:31 -08002890#define QPNP_CHG_IBATSAFE_MIN_MA 100
2891#define QPNP_CHG_IBATSAFE_MAX_MA 3250
2892#define QPNP_CHG_I_STEP_MA 50
2893#define QPNP_CHG_I_MIN_MA 100
2894#define QPNP_CHG_I_MASK 0x3F
2895static int
2896qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
2897{
2898 u8 temp;
2899
2900 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
2901 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
2902 pr_err("bad mA=%d asked to set\n", safe_current);
2903 return -EINVAL;
2904 }
2905
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08002906 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08002907 return qpnp_chg_masked_write(chip,
2908 chip->chgr_base + CHGR_IBAT_SAFE,
2909 QPNP_CHG_I_MASK, temp, 1);
2910}
David Keitel80668952012-07-27 14:25:49 -07002911
2912#define QPNP_CHG_ITERM_MIN_MA 100
2913#define QPNP_CHG_ITERM_MAX_MA 250
2914#define QPNP_CHG_ITERM_STEP_MA 50
2915#define QPNP_CHG_ITERM_MASK 0x03
2916static int
2917qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
2918{
2919 u8 temp;
2920
2921 if (term_current < QPNP_CHG_ITERM_MIN_MA
2922 || term_current > QPNP_CHG_ITERM_MAX_MA) {
2923 pr_err("bad mA=%d asked to set\n", term_current);
2924 return -EINVAL;
2925 }
2926
2927 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
2928 / QPNP_CHG_ITERM_STEP_MA;
2929 return qpnp_chg_masked_write(chip,
2930 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
2931 QPNP_CHG_ITERM_MASK, temp, 1);
2932}
2933
David Keitelff5d0472013-04-04 11:36:06 -07002934#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07002935#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07002936static int
2937qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
2938{
2939 u8 temp;
2940
2941 if (chg_current < QPNP_CHG_IBATMAX_MIN
2942 || chg_current > QPNP_CHG_IBATMAX_MAX) {
2943 pr_err("bad mA=%d asked to set\n", chg_current);
2944 return -EINVAL;
2945 }
David Keitelff5d0472013-04-04 11:36:06 -07002946 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07002947 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
2948 QPNP_CHG_I_MASK, temp, 1);
2949}
2950
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002951static int
2952qpnp_chg_ibatmax_get(struct qpnp_chg_chip *chip, int *chg_current)
2953{
2954 int rc;
2955 u8 temp;
2956
2957 *chg_current = 0;
2958 rc = qpnp_chg_read(chip, &temp, chip->chgr_base + CHGR_IBAT_MAX, 1);
2959 if (rc) {
2960 pr_err("failed read ibat_max rc=%d\n", rc);
2961 return rc;
2962 }
2963
2964 *chg_current = ((temp & QPNP_CHG_I_MASK) * QPNP_CHG_I_STEP_MA);
2965
2966 return 0;
2967}
2968
David Keitela4b7b592013-04-11 18:34:35 -07002969#define QPNP_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002970#define QPNP_CHG_TCHG_EN_MASK 0x80
David Keitela4b7b592013-04-11 18:34:35 -07002971#define QPNP_CHG_TCHG_MIN 4
2972#define QPNP_CHG_TCHG_MAX 512
2973#define QPNP_CHG_TCHG_STEP 4
2974static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
2975{
2976 u8 temp;
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002977 int rc;
David Keitela4b7b592013-04-11 18:34:35 -07002978
2979 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
2980 pr_err("bad max minutes =%d asked to set\n", minutes);
2981 return -EINVAL;
2982 }
2983
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002984 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
2985 QPNP_CHG_TCHG_EN_MASK, 0, 1);
2986 if (rc) {
2987 pr_err("failed write tchg_max_en rc=%d\n", rc);
2988 return rc;
2989 }
2990
2991 temp = minutes / QPNP_CHG_TCHG_STEP - 1;
2992
2993 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07002994 QPNP_CHG_TCHG_MASK, temp, 1);
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002995 if (rc) {
2996 pr_err("failed write tchg_max_en rc=%d\n", rc);
2997 return rc;
2998 }
2999
3000 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
3001 QPNP_CHG_TCHG_EN_MASK, QPNP_CHG_TCHG_EN_MASK, 1);
3002 if (rc) {
3003 pr_err("failed write tchg_max_en rc=%d\n", rc);
3004 return rc;
3005 }
3006
3007 return 0;
David Keitela4b7b592013-04-11 18:34:35 -07003008}
David Keitel80668952012-07-27 14:25:49 -07003009
David Keitel59fbb762014-02-05 16:46:24 -08003010static void
3011qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
3012{
3013 unsigned int chg_current = chip->max_bat_chg_current;
3014
3015 if (chip->bat_is_cool)
3016 chg_current = min(chg_current, chip->cool_bat_chg_ma);
3017
3018 if (chip->bat_is_warm)
3019 chg_current = min(chg_current, chip->warm_bat_chg_ma);
3020
3021 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
3022 chg_current = min(chg_current,
3023 chip->thermal_mitigation[chip->therm_lvl_sel]);
3024
3025 pr_debug("setting %d mA\n", chg_current);
3026 qpnp_chg_ibatmax_set(chip, chg_current);
3027}
3028
David Keitel80668952012-07-27 14:25:49 -07003029static int
3030qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
3031{
3032 u8 temp;
3033
3034 if (voltage < QPNP_CHG_V_MIN_MV
3035 || voltage > QPNP_CHG_V_MAX_MV) {
3036 pr_err("bad mV=%d asked to set\n", voltage);
3037 return -EINVAL;
3038 }
3039 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
3040 pr_debug("voltage=%d setting %02x\n", voltage, temp);
3041 return qpnp_chg_write(chip, &temp,
3042 chip->chgr_base + CHGR_VDD_SAFE, 1);
3043}
3044
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003045#define IBAT_TRIM_TGT_MA 500
3046#define IBAT_TRIM_OFFSET_MASK 0x7F
3047#define IBAT_TRIM_GOOD_BIT BIT(7)
3048#define IBAT_TRIM_LOW_LIM 20
3049#define IBAT_TRIM_HIGH_LIM 114
3050#define IBAT_TRIM_MEAN 64
3051
3052static void
3053qpnp_chg_trim_ibat(struct qpnp_chg_chip *chip, u8 ibat_trim)
3054{
3055 int ibat_now_ma, ibat_diff_ma, rc;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003056 struct qpnp_iadc_result i_result;
3057 enum qpnp_iadc_channels iadc_channel;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003058
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003059 iadc_channel = chip->use_external_rsense ?
3060 EXTERNAL_RSENSE : INTERNAL_RSENSE;
3061 rc = qpnp_iadc_read(chip->iadc_dev, iadc_channel, &i_result);
3062 if (rc) {
3063 pr_err("Unable to read bat rc=%d\n", rc);
3064 return;
3065 }
3066
3067 ibat_now_ma = i_result.result_ua / 1000;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003068
3069 if (qpnp_chg_is_ibat_loop_active(chip)) {
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003070 ibat_diff_ma = ibat_now_ma - IBAT_TRIM_TGT_MA;
3071
3072 if (abs(ibat_diff_ma) > 50) {
3073 ibat_trim += (ibat_diff_ma / 20);
3074 ibat_trim &= IBAT_TRIM_OFFSET_MASK;
3075 /* reject new ibat_trim if it is outside limits */
3076 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
3077 IBAT_TRIM_HIGH_LIM))
3078 return;
3079 }
3080 ibat_trim |= IBAT_TRIM_GOOD_BIT;
3081 rc = qpnp_chg_write(chip, &ibat_trim,
3082 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3083 if (rc)
3084 pr_err("failed to set IBAT_TRIM rc=%d\n", rc);
3085
3086 pr_debug("ibat_now=%dmA, itgt=%dmA, ibat_diff=%dmA, ibat_trim=%x\n",
3087 ibat_now_ma, IBAT_TRIM_TGT_MA,
3088 ibat_diff_ma, ibat_trim);
3089 } else {
3090 pr_debug("ibat loop not active - cannot calibrate ibat\n");
3091 }
3092}
3093
3094static int
3095qpnp_chg_input_current_settled(struct qpnp_chg_chip *chip)
3096{
3097 int rc, ibat_max_ma;
3098 u8 reg, chgr_sts, ibat_trim, i;
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07003099 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003100
Abhijeet Dharmapurikar02e59562014-08-12 19:31:31 -07003101 if (!usb_present) {
3102 pr_debug("Ignoring AICL settled, since USB is removed\n");
3103 return 0;
3104 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003105 chip->aicl_settled = true;
3106
3107 /*
3108 * Perform the ibat calibration.
3109 * This is for devices which have a IBAT_TRIM error
3110 * which can show IBAT_MAX out of spec.
3111 */
3112 if (!chip->ibat_calibration_enabled)
3113 return 0;
3114
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003115 if (chip->type != SMBB)
3116 return 0;
3117
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003118 rc = qpnp_chg_read(chip, &reg,
3119 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3120 if (rc) {
3121 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
3122 return rc;
3123 }
3124 if (reg & IBAT_TRIM_GOOD_BIT) {
3125 pr_debug("IBAT_TRIM_GOOD bit already set. Quitting!\n");
3126 return 0;
3127 }
3128 ibat_trim = reg & IBAT_TRIM_OFFSET_MASK;
3129
3130 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
3131 IBAT_TRIM_HIGH_LIM)) {
3132 pr_debug("Improper ibat_trim value=%x setting to value=%x\n",
3133 ibat_trim, IBAT_TRIM_MEAN);
3134 ibat_trim = IBAT_TRIM_MEAN;
3135 rc = qpnp_chg_masked_write(chip,
3136 chip->buck_base + BUCK_CTRL_TRIM3,
3137 IBAT_TRIM_OFFSET_MASK, ibat_trim, 1);
3138 if (rc) {
3139 pr_err("failed to set ibat_trim to %x rc=%d\n",
3140 IBAT_TRIM_MEAN, rc);
3141 return rc;
3142 }
3143 }
3144
3145 rc = qpnp_chg_read(chip, &chgr_sts,
3146 INT_RT_STS(chip->chgr_base), 1);
3147 if (rc) {
3148 pr_err("failed to read interrupt sts rc=%d\n", rc);
3149 return rc;
3150 }
3151 if (!(chgr_sts & FAST_CHG_ON_IRQ)) {
3152 pr_debug("Not in fastchg\n");
3153 return rc;
3154 }
3155
3156 /* save the ibat_max to restore it later */
3157 rc = qpnp_chg_ibatmax_get(chip, &ibat_max_ma);
3158 if (rc) {
3159 pr_debug("failed to save ibatmax rc=%d\n", rc);
3160 return rc;
3161 }
3162
3163 rc = qpnp_chg_ibatmax_set(chip, IBAT_TRIM_TGT_MA);
3164 if (rc) {
3165 pr_err("failed to set ibatmax rc=%d\n", rc);
3166 return rc;
3167 }
3168
3169 for (i = 0; i < 3; i++) {
3170 /*
3171 * ibat settling delay - to make sure the BMS controller
3172 * has sufficient time to sample ibat for the configured
3173 * ibat_max
3174 */
3175 msleep(20);
3176 if (qpnp_chg_is_ibat_loop_active(chip))
3177 qpnp_chg_trim_ibat(chip, ibat_trim);
3178 else
3179 pr_debug("ibat loop not active\n");
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003180
3181 /* read the adjusted ibat_trim for further adjustments */
3182 rc = qpnp_chg_read(chip, &ibat_trim,
3183 chip->buck_base + BUCK_CTRL_TRIM3, 1);
3184 if (rc) {
3185 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
3186 break;
3187 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003188 }
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08003189
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003190 /* restore IBATMAX */
3191 rc = qpnp_chg_ibatmax_set(chip, ibat_max_ma);
3192 if (rc)
3193 pr_err("failed to restore ibatmax rc=%d\n", rc);
3194
3195 return rc;
3196}
3197
3198
David Keitel6dc4ed42013-05-17 11:08:58 -07003199#define BOOST_MIN_UV 4200000
3200#define BOOST_MAX_UV 5500000
3201#define BOOST_STEP_UV 50000
3202#define BOOST_MIN 16
3203#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
3204static int
3205qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
3206{
3207 u8 reg = 0;
3208
3209 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
3210 pr_err("invalid voltage requested %d uV\n", voltage);
3211 return -EINVAL;
3212 }
3213
3214 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
3215
3216 pr_debug("voltage=%d setting %02x\n", voltage, reg);
3217 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
3218}
3219
3220static int
3221qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
3222{
3223 int rc;
3224 u8 boost_reg;
3225
3226 rc = qpnp_chg_read(chip, &boost_reg,
3227 chip->boost_base + BOOST_VSET, 1);
3228 if (rc) {
3229 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
3230 return rc;
3231 }
3232
3233 if (boost_reg < BOOST_MIN) {
3234 pr_err("Invalid reading from 0x%x\n", boost_reg);
3235 return -EINVAL;
3236 }
3237
3238 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
3239}
3240
David Keitel454ee842013-03-08 16:19:11 -08003241static void
David Keitelbe208252013-01-31 14:49:25 -08003242qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
3243{
3244 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
3245 chip->therm_lvl_sel = lvl_sel;
3246 if (lvl_sel == (chip->thermal_levels - 1)) {
3247 /* disable charging if highest value selected */
3248 qpnp_chg_buck_control(chip, 0);
3249 } else {
3250 qpnp_chg_buck_control(chip, 1);
3251 qpnp_chg_set_appropriate_battery_current(chip);
3252 }
3253 } else {
3254 pr_err("Unsupported level selected %d\n", lvl_sel);
3255 }
3256}
3257
Chunmei Cai661a7cd2014-08-05 17:31:54 +08003258/*
3259 * Increase the SMBB/SMBBP charger overtemp threshold to 150C while firing
3260 * the flash (and/or torch for PM8x26) when the bharger is used as the
3261 * power source.
3262 */
3263static int
3264qpnp_chg_temp_threshold_set(struct qpnp_chg_chip *chip, u8 value)
3265{
3266 int rc;
3267
3268 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
3269 CHGR_CHG_TEMP_THRESH ,
3270 0xFF, value, 1);
3271 if (rc)
3272 pr_err("set CHG_TEMP_THRESH_Flash failed, value = %d, rc = %d\n",
3273 value, rc);
3274
3275 return rc;
3276}
3277
3278#define CHG_TEMP_THRESH_FOR_FLASH 0xFD
3279#define CHG_TEMP_THRESH_DEFAULT 0x94
3280static int
3281qpnp_chg_regulator_flash_wa_enable(struct regulator_dev *rdev)
3282{
3283 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3284 int rc = 0;
3285
3286 if (chip->flags & BOOST_FLASH_WA) {
3287 rc = qpnp_chg_temp_threshold_set(chip,
3288 CHG_TEMP_THRESH_FOR_FLASH);
3289 if (rc) {
3290 pr_err("set chg temp threshold failed rc = %d\n", rc);
3291 return rc;
3292 }
3293 }
3294 chip->is_flash_wa_reg_enabled = true;
3295
3296 return rc;
3297}
3298
3299static int
3300qpnp_chg_regulator_flash_wa_disable(struct regulator_dev *rdev)
3301{
3302 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3303 int rc = 0;
3304
3305 if (chip->flags & BOOST_FLASH_WA) {
3306 rc = qpnp_chg_temp_threshold_set(chip,
3307 chip->chg_temp_thresh_default);
3308 if (rc) {
3309 pr_err("set chg temp threshold failed rc = %d\n", rc);
3310 return rc;
3311 }
3312
3313 }
3314 chip->is_flash_wa_reg_enabled = false;
3315
3316 return rc;
3317}
3318
3319static int
3320qpnp_chg_regulator_flash_wa_is_enabled(struct regulator_dev *rdev)
3321{
3322 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3323
3324 return chip->is_flash_wa_reg_enabled;
3325}
3326
David Keitel6dc4ed42013-05-17 11:08:58 -07003327/* OTG regulator operations */
3328static int
3329qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
3330{
3331 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3332
3333 return switch_usb_to_host_mode(chip);
3334}
3335
3336static int
3337qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
3338{
3339 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3340
3341 return switch_usb_to_charge_mode(chip);
3342}
3343
3344static int
3345qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
3346{
3347 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3348
3349 return qpnp_chg_is_otg_en_set(chip);
3350}
3351
3352static int
3353qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
3354{
3355 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
Chunmei Caib3999b22014-07-11 15:38:13 +08003356 int usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel33f58952013-05-20 16:17:36 -07003357 int rc;
3358
Chunmei Caib3999b22014-07-11 15:38:13 +08003359 if (usb_present && (chip->flags & BOOST_FLASH_WA)) {
David Keitelcd2e1022014-05-02 17:25:15 -07003360
3361 if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
3362 pr_debug("EXT OVP IC ISNS disabled\n");
3363 gpio_direction_output(chip->ext_ovp_isns_gpio, 0);
3364 }
3365
David Keitel33f58952013-05-20 16:17:36 -07003366 qpnp_chg_usb_suspend_enable(chip, 1);
3367
3368 rc = qpnp_chg_masked_write(chip,
3369 chip->usb_chgpth_base + SEC_ACCESS,
3370 0xFF,
3371 0xA5, 1);
3372 if (rc) {
3373 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3374 return rc;
3375 }
3376
3377 rc = qpnp_chg_masked_write(chip,
3378 chip->usb_chgpth_base + COMP_OVR1,
3379 0xFF,
3380 0x2F, 1);
3381 if (rc) {
3382 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3383 return rc;
3384 }
3385 }
David Keitel6dc4ed42013-05-17 11:08:58 -07003386
Chunmei Caib3999b22014-07-11 15:38:13 +08003387 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003388 chip->boost_base + BOOST_ENABLE_CONTROL,
3389 BOOST_PWR_EN,
3390 BOOST_PWR_EN, 1);
Chunmei Caib3999b22014-07-11 15:38:13 +08003391 if (rc) {
3392 pr_err("failed to enable boost rc = %d\n", rc);
3393 return rc;
3394 }
3395 /*
3396 * update battery status when charger is connected and state is full
3397 */
3398 if (usb_present && (chip->chg_done
3399 || (get_batt_capacity(chip) == 100)
3400 || (get_prop_batt_status(chip) ==
3401 POWER_SUPPLY_STATUS_FULL)))
3402 power_supply_changed(&chip->batt_psy);
3403
3404 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003405}
3406
3407/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07003408#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07003409static int
3410qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
3411{
3412 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07003413 int rc;
3414 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07003415
David Keitel33f58952013-05-20 16:17:36 -07003416 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003417 chip->boost_base + BOOST_ENABLE_CONTROL,
3418 BOOST_PWR_EN,
3419 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07003420 if (rc) {
3421 pr_err("failed to disable boost rc=%d\n", rc);
3422 return rc;
3423 }
3424
3425 rc = qpnp_chg_read(chip, &vbat_sts,
3426 chip->chgr_base + CHGR_VBAT_STATUS, 1);
3427 if (rc) {
3428 pr_err("failed to read bat sts rc=%d\n", rc);
3429 return rc;
3430 }
3431
3432 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
3433 rc = qpnp_chg_masked_write(chip,
3434 chip->chgr_base + SEC_ACCESS,
3435 0xFF,
3436 0xA5, 1);
3437 if (rc) {
3438 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3439 return rc;
3440 }
3441
3442 rc = qpnp_chg_masked_write(chip,
3443 chip->chgr_base + COMP_OVR1,
3444 0xFF,
3445 0x20, 1);
3446 if (rc) {
3447 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3448 return rc;
3449 }
3450
3451 usleep(2000);
3452
3453 rc = qpnp_chg_masked_write(chip,
3454 chip->chgr_base + SEC_ACCESS,
3455 0xFF,
3456 0xA5, 1);
3457 if (rc) {
3458 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3459 return rc;
3460 }
3461
3462 rc = qpnp_chg_masked_write(chip,
3463 chip->chgr_base + COMP_OVR1,
3464 0xFF,
3465 0x00, 1);
3466 if (rc) {
3467 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3468 return rc;
3469 }
3470 }
3471
3472 if (qpnp_chg_is_usb_chg_plugged_in(chip)
3473 && (chip->flags & BOOST_FLASH_WA)) {
3474 rc = qpnp_chg_masked_write(chip,
3475 chip->usb_chgpth_base + SEC_ACCESS,
3476 0xFF,
3477 0xA5, 1);
3478 if (rc) {
3479 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3480 return rc;
3481 }
3482
3483 rc = qpnp_chg_masked_write(chip,
3484 chip->usb_chgpth_base + COMP_OVR1,
3485 0xFF,
3486 0x00, 1);
3487 if (rc) {
3488 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3489 return rc;
3490 }
3491
3492 usleep(1000);
3493
3494 qpnp_chg_usb_suspend_enable(chip, 0);
3495 }
3496
Chunmei Caib3999b22014-07-11 15:38:13 +08003497 /*
3498 * When a charger is connected,if state of charge is not full
3499 * resumeing charging else update battery status
3500 */
3501 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
3502 if (get_batt_capacity(chip) < 100 || !chip->chg_done) {
3503 chip->chg_done = false;
3504 chip->resuming_charging = true;
3505 qpnp_chg_set_appropriate_vbatdet(chip);
3506 } else if (chip->chg_done) {
3507 power_supply_changed(&chip->batt_psy);
3508 }
3509 }
3510
David Keitelcd2e1022014-05-02 17:25:15 -07003511 if (ext_ovp_isns_present && chip->ext_ovp_ic_gpio_enabled) {
3512 pr_debug("EXT OVP IC ISNS enable\n");
3513 gpio_direction_output(chip->ext_ovp_isns_gpio, 1);
3514 }
3515
David Keitel33f58952013-05-20 16:17:36 -07003516 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003517}
3518
3519static int
3520qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
3521{
3522 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3523
3524 return qpnp_chg_is_boost_en_set(chip);
3525}
3526
3527static int
3528qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
3529 int min_uV, int max_uV, unsigned *selector)
3530{
3531 int uV = min_uV;
3532 int rc;
3533 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3534
3535 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
3536 uV = BOOST_MIN_UV;
3537
3538
3539 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
3540 pr_err("request %d uV is out of bounds\n", uV);
3541 return -EINVAL;
3542 }
3543
3544 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
3545 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
3546 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
3547 return -EINVAL;
3548 }
3549
3550 rc = qpnp_boost_vset(chip, uV);
3551
3552 return rc;
3553}
3554
3555static int
3556qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
3557{
3558 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3559
3560 return qpnp_boost_vget_uv(chip);
3561}
3562
3563static int
3564qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
3565 unsigned selector)
3566{
3567 if (selector >= N_BOOST_V)
3568 return 0;
3569
3570 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
3571}
3572
Chunmei Cai661a7cd2014-08-05 17:31:54 +08003573static struct regulator_ops qpnp_chg_flash_wa_reg_ops = {
3574 .enable = qpnp_chg_regulator_flash_wa_enable,
3575 .disable = qpnp_chg_regulator_flash_wa_disable,
3576 .is_enabled = qpnp_chg_regulator_flash_wa_is_enabled,
3577};
3578
David Keitel6dc4ed42013-05-17 11:08:58 -07003579static struct regulator_ops qpnp_chg_otg_reg_ops = {
3580 .enable = qpnp_chg_regulator_otg_enable,
3581 .disable = qpnp_chg_regulator_otg_disable,
3582 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
3583};
3584
3585static struct regulator_ops qpnp_chg_boost_reg_ops = {
3586 .enable = qpnp_chg_regulator_boost_enable,
3587 .disable = qpnp_chg_regulator_boost_disable,
3588 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
3589 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
3590 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
3591 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
3592};
3593
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003594static int
David Keitel6e63bd52013-09-06 18:00:03 -07003595qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003596{
David Keitel9eca8ac2013-09-06 14:18:36 -07003597 int rc = 0;
David Keitel6e63bd52013-09-06 18:00:03 -07003598 u8 reg = 0;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003599
David Keitelcadbc282013-09-26 11:39:14 -07003600 if (!chip->bat_if_base)
3601 return rc;
3602
David Keitel9eca8ac2013-09-06 14:18:36 -07003603 if (chip->type == SMBB)
3604 rc = qpnp_chg_read(chip, &reg,
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003605 chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
David Keitel9eca8ac2013-09-06 14:18:36 -07003606 else
3607 rc = qpnp_chg_read(chip, &reg,
3608 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
David Keitel6e63bd52013-09-06 18:00:03 -07003609
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003610 if (rc) {
3611 pr_err("failed to read batt_if rc=%d\n", rc);
3612 return rc;
3613 }
3614
David Keitel6e63bd52013-09-06 18:00:03 -07003615 if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003616 return 1;
3617
3618 return 0;
3619}
3620
David Keitel6e63bd52013-09-06 18:00:03 -07003621static int
3622qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
3623{
3624 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3625 int rc = 0;
3626
3627 mutex_lock(&chip->batfet_vreg_lock);
3628 /* Only enable if not already enabled */
3629 if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
3630 rc = qpnp_chg_regulator_batfet_set(chip, 1);
3631 if (rc)
3632 pr_err("failed to write to batt_if rc=%d\n", rc);
3633 }
3634
3635 chip->batfet_ext_en = true;
3636 mutex_unlock(&chip->batfet_vreg_lock);
3637
3638 return rc;
3639}
3640
3641static int
3642qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
3643{
3644 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3645 int rc = 0;
3646
3647 mutex_lock(&chip->batfet_vreg_lock);
3648 /* Don't allow disable if charger connected */
3649 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3650 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3651 rc = qpnp_chg_regulator_batfet_set(chip, 0);
3652 if (rc)
3653 pr_err("failed to write to batt_if rc=%d\n", rc);
3654 }
3655
3656 chip->batfet_ext_en = false;
3657 mutex_unlock(&chip->batfet_vreg_lock);
3658
3659 return rc;
3660}
3661
3662static int
3663qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
3664{
3665 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3666
3667 return chip->batfet_ext_en;
3668}
3669
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003670static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
3671 .enable = qpnp_chg_regulator_batfet_enable,
3672 .disable = qpnp_chg_regulator_batfet_disable,
3673 .is_enabled = qpnp_chg_regulator_batfet_is_enabled,
3674};
3675
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003676#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 8
3677#define MAX_DELTA_VDD_MAX_MV 80
3678#define VDD_MAX_CENTER_OFFSET 4
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003679static void
3680qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
3681{
3682 int delta_mv, closest_delta_mv, sign;
3683
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003684 delta_mv = chip->max_voltage_mv - VDD_MAX_CENTER_OFFSET - vbat_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003685 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
3686 pr_debug("vbat is not low enough to increase vdd\n");
3687 return;
3688 }
3689
3690 sign = delta_mv > 0 ? 1 : -1;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003691 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_BUCK_TRIM1_STEP / 2)
3692 / QPNP_CHG_BUCK_TRIM1_STEP) * QPNP_CHG_BUCK_TRIM1_STEP;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003693 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
3694 chip->max_voltage_mv, vbat_mv,
3695 delta_mv, closest_delta_mv);
3696 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
3697 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
3698 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
3699 qpnp_chg_set_appropriate_vddmax(chip);
3700}
3701
David Keitel9fd07382013-05-02 15:37:44 -07003702#define CONSECUTIVE_COUNT 3
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003703#define VBATDET_MAX_ERR_MV 50
David Keitel9fd07382013-05-02 15:37:44 -07003704static void
3705qpnp_eoc_work(struct work_struct *work)
3706{
3707 struct delayed_work *dwork = to_delayed_work(work);
3708 struct qpnp_chg_chip *chip = container_of(dwork,
3709 struct qpnp_chg_chip, eoc_work);
3710 static int count;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003711 static int vbat_low_count;
David Keitel9fd07382013-05-02 15:37:44 -07003712 int ibat_ma, vbat_mv, rc = 0;
3713 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003714 bool vbat_lower_than_vbatdet;
David Keitel9fd07382013-05-02 15:37:44 -07003715
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003716 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003717 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3718
3719 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
3720 if (rc) {
3721 pr_err("failed to read batt_if rc=%d\n", rc);
3722 return;
3723 }
3724
3725 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
3726 if (rc) {
3727 pr_err("failed to read buck rc=%d\n", rc);
3728 return;
3729 }
3730
3731 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
3732 if (rc) {
3733 pr_err("failed to read chg_sts rc=%d\n", rc);
3734 return;
3735 }
3736
3737 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
3738 chg_sts, batt_sts, buck_sts);
3739
3740 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3741 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3742 pr_debug("no chg connected, stopping\n");
3743 goto stop_eoc;
3744 }
3745
3746 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
3747 || chg_sts & TRKL_CHG_ON_IRQ)) {
3748 ibat_ma = get_prop_current_now(chip) / 1000;
3749 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003750
3751 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
3752 ibat_ma, vbat_mv, chip->term_current);
3753
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003754 vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
3755 if (vbat_lower_than_vbatdet && vbat_mv <
3756 (chip->max_voltage_mv - chip->resume_delta_mv
David Keitelbdbae452014-01-14 17:19:50 -08003757 - chip->vbatdet_max_err_mv)) {
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003758 vbat_low_count++;
3759 pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
3760 vbat_mv, chip->max_voltage_mv,
3761 chip->resume_delta_mv,
David Keitelbdbae452014-01-14 17:19:50 -08003762 chip->vbatdet_max_err_mv,
3763 vbat_low_count);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003764 if (vbat_low_count >= CONSECUTIVE_COUNT) {
3765 pr_debug("woke up too early stopping\n");
3766 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
3767 goto stop_eoc;
3768 } else {
3769 goto check_again_later;
3770 }
3771 } else {
3772 vbat_low_count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003773 }
3774
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003775 if (buck_sts & VDD_LOOP_IRQ)
3776 qpnp_chg_adjust_vddmax(chip, vbat_mv);
3777
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003778 if (!(buck_sts & VDD_LOOP_IRQ)) {
3779 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07003780 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003781 } else if ((ibat_ma * -1) > chip->term_current) {
3782 pr_debug("Not at EOC, battery current too high\n");
3783 count = 0;
3784 } else if (ibat_ma > 0) {
3785 pr_debug("Charging but system demand increased\n");
3786 count = 0;
3787 } else {
David Keitel9fd07382013-05-02 15:37:44 -07003788 if (count == CONSECUTIVE_COUNT) {
Xiaozhe Shie8504482013-10-30 18:10:31 -07003789 if (!chip->bat_is_cool && !chip->bat_is_warm) {
3790 pr_info("End of Charging\n");
3791 chip->chg_done = true;
3792 } else {
3793 pr_info("stop charging: battery is %s, vddmax = %d reached\n",
3794 chip->bat_is_cool
3795 ? "cool" : "warm",
3796 qpnp_chg_vddmax_get(chip));
3797 }
David Keitel9fd07382013-05-02 15:37:44 -07003798 qpnp_chg_charge_en(chip, 0);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003799 /* sleep for a second before enabling */
3800 msleep(2000);
3801 qpnp_chg_charge_en(chip,
3802 !chip->charging_disabled);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003803 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07003804 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07003805 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07003806 goto stop_eoc;
3807 } else {
3808 count += 1;
3809 pr_debug("EOC count = %d\n", count);
3810 }
David Keitel9fd07382013-05-02 15:37:44 -07003811 }
3812 } else {
3813 pr_debug("not charging\n");
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003814 goto stop_eoc;
David Keitel9fd07382013-05-02 15:37:44 -07003815 }
3816
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003817check_again_later:
David Keitel9fd07382013-05-02 15:37:44 -07003818 schedule_delayed_work(&chip->eoc_work,
3819 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
3820 return;
3821
3822stop_eoc:
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003823 vbat_low_count = 0;
David Keitel9fd07382013-05-02 15:37:44 -07003824 count = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003825 pm_relax(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003826}
3827
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003828static void
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07003829qpnp_chg_insertion_ocv_work(struct work_struct *work)
3830{
3831 struct qpnp_chg_chip *chip = container_of(work,
3832 struct qpnp_chg_chip, insertion_ocv_work);
3833 u8 bat_if_sts = 0, charge_en = 0;
3834 int rc;
3835
3836 chip->insertion_ocv_uv = get_prop_battery_voltage_now(chip);
3837
3838 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
3839 if (rc)
3840 pr_err("failed to read bat_if sts %d\n", rc);
3841
3842 rc = qpnp_chg_read(chip, &charge_en,
3843 chip->chgr_base + CHGR_CHG_CTRL, 1);
3844 if (rc)
3845 pr_err("failed to read bat_if sts %d\n", rc);
3846
3847 pr_debug("batfet sts = %02x, charge_en = %02x ocv = %d\n",
3848 bat_if_sts, charge_en, chip->insertion_ocv_uv);
3849 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3850 pr_debug("psy changed batt_psy\n");
3851 power_supply_changed(&chip->batt_psy);
3852}
3853
3854static void
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003855qpnp_chg_soc_check_work(struct work_struct *work)
3856{
3857 struct qpnp_chg_chip *chip = container_of(work,
3858 struct qpnp_chg_chip, soc_check_work);
3859
3860 get_prop_capacity(chip);
3861}
3862
David Keitel0c1a4532013-03-21 16:39:06 -07003863#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08003864static void
3865qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
3866{
3867 struct qpnp_chg_chip *chip = ctx;
3868 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07003869 int temp;
David Keitel454ee842013-03-08 16:19:11 -08003870
3871 if (state >= ADC_TM_STATE_NUM) {
3872 pr_err("invalid notification %d\n", state);
3873 return;
3874 }
3875
David Keitel1219a802013-03-21 16:37:21 -07003876 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08003877
David Keitel1219a802013-03-21 16:37:21 -07003878 pr_debug("temp = %d state = %s\n", temp,
3879 state == ADC_TM_WARM_STATE ? "warm" : "cool");
3880
3881 if (state == ADC_TM_WARM_STATE) {
David Keitel410ee0d2014-02-20 16:48:04 -08003882 if (temp >= chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003883 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08003884 bat_warm = true;
3885 bat_cool = false;
3886 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003887 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003888 chip->adc_param.state_request =
3889 ADC_TM_COOL_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08003890 } else if (temp >=
David Keitel1219a802013-03-21 16:37:21 -07003891 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003892 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08003893 bat_warm = false;
3894 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07003895
3896 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07003897 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003898 chip->adc_param.state_request =
3899 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003900 }
3901 } else {
David Keitel410ee0d2014-02-20 16:48:04 -08003902 if (temp <= chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003903 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08003904 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003905 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08003906 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003907 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003908 chip->adc_param.state_request =
3909 ADC_TM_WARM_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08003910 } else if (temp <=
David Keitel1219a802013-03-21 16:37:21 -07003911 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003912 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08003913 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003914 bat_cool = false;
3915
David Keitel0c1a4532013-03-21 16:39:06 -07003916 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003917 chip->adc_param.high_temp = chip->warm_bat_decidegc;
3918 chip->adc_param.state_request =
3919 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003920 }
3921 }
3922
3923 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07003924 chip->bat_is_cool = bat_cool;
3925 chip->bat_is_warm = bat_warm;
3926
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07003927 /**
3928 * set appropriate voltages and currents.
3929 *
3930 * Note that when the battery is hot or cold, the charger
3931 * driver will not resume with SoC. Only vbatdet is used to
3932 * determine resume of charging.
3933 */
David Keitel59fbb762014-02-05 16:46:24 -08003934 if (bat_cool || bat_warm) {
3935 chip->resuming_charging = false;
3936 qpnp_chg_set_appropriate_vbatdet(chip);
3937
3938 /* To avoid ARB, only vbatdet is configured in
3939 * warm/cold zones. Once vbat < vbatdet the
3940 * appropriate vddmax/ibatmax adjustments will
3941 * be made in the fast charge interrupt. */
3942 bypass_vbatdet_comp(chip, 1);
3943 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3944 qpnp_chg_charge_en(chip, chip->charging_disabled);
3945 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3946 } else {
3947 bypass_vbatdet_comp(chip, 0);
3948 /* restore normal parameters */
3949 qpnp_chg_set_appropriate_vbatdet(chip);
3950 qpnp_chg_set_appropriate_vddmax(chip);
3951 qpnp_chg_set_appropriate_battery_current(chip);
3952 }
David Keitel454ee842013-03-08 16:19:11 -08003953 }
3954
David Keitelec3c09802013-06-13 13:05:30 -07003955 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
3956 chip->bat_is_warm, chip->bat_is_cool,
3957 chip->adc_param.low_temp, chip->adc_param.high_temp);
3958
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003959 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07003960 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07003961}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07003962
David Keitelec3c09802013-06-13 13:05:30 -07003963#define MIN_COOL_TEMP -300
3964#define MAX_WARM_TEMP 1000
3965
3966static int
3967qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
3968 enum power_supply_property psp, int temp_degc)
3969{
3970 int rc = 0;
3971
3972 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
3973 pr_err("Bad temperature request %d\n", temp_degc);
3974 return -EINVAL;
3975 }
3976
3977 mutex_lock(&chip->jeita_configure_lock);
3978 switch (psp) {
3979 case POWER_SUPPLY_PROP_COOL_TEMP:
3980 if (temp_degc >=
3981 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
3982 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
3983 temp_degc, chip->warm_bat_decidegc,
3984 HYSTERISIS_DECIDEGC);
3985 rc = -EINVAL;
3986 goto mutex_unlock;
3987 }
3988 if (chip->bat_is_cool)
3989 chip->adc_param.high_temp =
3990 temp_degc + HYSTERISIS_DECIDEGC;
3991 else if (!chip->bat_is_warm)
3992 chip->adc_param.low_temp = temp_degc;
3993
3994 chip->cool_bat_decidegc = temp_degc;
3995 break;
3996 case POWER_SUPPLY_PROP_WARM_TEMP:
3997 if (temp_degc <=
3998 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
3999 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
4000 temp_degc, chip->warm_bat_decidegc,
4001 HYSTERISIS_DECIDEGC);
4002 rc = -EINVAL;
4003 goto mutex_unlock;
4004 }
4005 if (chip->bat_is_warm)
4006 chip->adc_param.low_temp =
4007 temp_degc - HYSTERISIS_DECIDEGC;
4008 else if (!chip->bat_is_cool)
4009 chip->adc_param.high_temp = temp_degc;
4010
4011 chip->warm_bat_decidegc = temp_degc;
4012 break;
4013 default:
4014 rc = -EINVAL;
4015 goto mutex_unlock;
4016 }
4017
4018 schedule_work(&chip->adc_measure_work);
4019
4020mutex_unlock:
4021 mutex_unlock(&chip->jeita_configure_lock);
4022 return rc;
David Keitel454ee842013-03-08 16:19:11 -08004023}
4024
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004025#define POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS 20
4026#define POWER_STAGE_REDUCE_MAX_VBAT_UV 3900000
4027#define POWER_STAGE_REDUCE_MIN_VCHG_UV 4800000
4028#define POWER_STAGE_SEL_MASK 0x0F
4029#define POWER_STAGE_REDUCED 0x01
4030#define POWER_STAGE_DEFAULT 0x0F
4031static bool
4032qpnp_chg_is_power_stage_reduced(struct qpnp_chg_chip *chip)
4033{
4034 int rc;
4035 u8 reg;
4036
4037 rc = qpnp_chg_read(chip, &reg,
4038 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
4039 1);
4040 if (rc) {
4041 pr_err("Error %d reading power stage register\n", rc);
4042 return false;
4043 }
4044
4045 if ((reg & POWER_STAGE_SEL_MASK) == POWER_STAGE_DEFAULT)
4046 return false;
4047
4048 return true;
4049}
4050
4051static int
4052qpnp_chg_power_stage_set(struct qpnp_chg_chip *chip, bool reduce)
4053{
4054 int rc;
4055 u8 reg = 0xA5;
4056
4057 rc = qpnp_chg_write(chip, &reg,
4058 chip->buck_base + SEC_ACCESS,
4059 1);
4060 if (rc) {
4061 pr_err("Error %d writing 0xA5 to buck's 0x%x reg\n",
4062 rc, SEC_ACCESS);
4063 return rc;
4064 }
4065
4066 reg = POWER_STAGE_DEFAULT;
4067 if (reduce)
4068 reg = POWER_STAGE_REDUCED;
4069 rc = qpnp_chg_write(chip, &reg,
4070 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
4071 1);
4072
4073 if (rc)
4074 pr_err("Error %d writing 0x%x power stage register\n", rc, reg);
4075 return rc;
4076}
4077
4078static int
4079qpnp_chg_get_vusbin_uv(struct qpnp_chg_chip *chip)
4080{
4081 int rc = 0;
4082 struct qpnp_vadc_result results;
4083
4084 rc = qpnp_vadc_read(chip->vadc_dev, USBIN, &results);
4085 if (rc) {
4086 pr_err("Unable to read vbat rc=%d\n", rc);
4087 return 0;
4088 }
4089 return results.physical;
4090}
4091
4092static
4093int get_vusb_averaged(struct qpnp_chg_chip *chip, int sample_count)
4094{
4095 int vusb_uv = 0;
4096 int i;
4097
4098 /* avoid overflows */
4099 if (sample_count > 256)
4100 sample_count = 256;
4101
4102 for (i = 0; i < sample_count; i++)
4103 vusb_uv += qpnp_chg_get_vusbin_uv(chip);
4104
4105 vusb_uv = vusb_uv / sample_count;
4106 return vusb_uv;
4107}
4108
4109static
4110int get_vbat_averaged(struct qpnp_chg_chip *chip, int sample_count)
4111{
4112 int vbat_uv = 0;
4113 int i;
4114
4115 /* avoid overflows */
4116 if (sample_count > 256)
4117 sample_count = 256;
4118
4119 for (i = 0; i < sample_count; i++)
4120 vbat_uv += get_prop_battery_voltage_now(chip);
4121
4122 vbat_uv = vbat_uv / sample_count;
4123 return vbat_uv;
4124}
4125
4126static void
4127qpnp_chg_reduce_power_stage(struct qpnp_chg_chip *chip)
4128{
4129 struct timespec ts;
4130 bool power_stage_reduced_in_hw = qpnp_chg_is_power_stage_reduced(chip);
4131 bool reduce_power_stage = false;
4132 int vbat_uv = get_vbat_averaged(chip, 16);
4133 int vusb_uv = get_vusb_averaged(chip, 16);
4134 bool fast_chg =
4135 (get_prop_charge_type(chip) == POWER_SUPPLY_CHARGE_TYPE_FAST);
4136 static int count_restore_power_stage;
4137 static int count_reduce_power_stage;
4138 bool vchg_loop = get_prop_vchg_loop(chip);
4139 bool ichg_loop = qpnp_chg_is_ichg_loop_active(chip);
4140 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
4141 bool usb_ma_above_wall =
4142 (qpnp_chg_usb_iusbmax_get(chip) > USB_WALL_THRESHOLD_MA);
4143
4144 if (fast_chg
4145 && usb_present
4146 && usb_ma_above_wall
4147 && vbat_uv < POWER_STAGE_REDUCE_MAX_VBAT_UV
4148 && vusb_uv > POWER_STAGE_REDUCE_MIN_VCHG_UV)
4149 reduce_power_stage = true;
4150
4151 if ((usb_present && usb_ma_above_wall)
4152 && (vchg_loop || ichg_loop))
4153 reduce_power_stage = true;
4154
4155 if (power_stage_reduced_in_hw && !reduce_power_stage) {
4156 count_restore_power_stage++;
4157 count_reduce_power_stage = 0;
4158 } else if (!power_stage_reduced_in_hw && reduce_power_stage) {
4159 count_reduce_power_stage++;
4160 count_restore_power_stage = 0;
4161 } else if (power_stage_reduced_in_hw == reduce_power_stage) {
4162 count_restore_power_stage = 0;
4163 count_reduce_power_stage = 0;
4164 }
4165
4166 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",
4167 power_stage_reduced_in_hw, reduce_power_stage,
4168 usb_present, usb_ma_above_wall,
4169 vbat_uv, vusb_uv, fast_chg,
4170 ichg_loop, vchg_loop,
4171 count_restore_power_stage, count_reduce_power_stage);
4172
4173 if (!power_stage_reduced_in_hw && reduce_power_stage) {
4174 if (count_reduce_power_stage >= 2) {
4175 qpnp_chg_power_stage_set(chip, true);
4176 power_stage_reduced_in_hw = true;
4177 }
4178 }
4179
4180 if (power_stage_reduced_in_hw && !reduce_power_stage) {
4181 if (count_restore_power_stage >= 6
4182 || (!usb_present || !usb_ma_above_wall)) {
4183 qpnp_chg_power_stage_set(chip, false);
4184 power_stage_reduced_in_hw = false;
4185 }
4186 }
4187
4188 if (usb_present && usb_ma_above_wall) {
4189 getnstimeofday(&ts);
4190 ts.tv_sec += POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS;
4191 alarm_start_range(&chip->reduce_power_stage_alarm,
4192 timespec_to_ktime(ts),
4193 timespec_to_ktime(ts));
4194 } else {
4195 pr_debug("stopping power stage workaround\n");
4196 chip->power_stage_workaround_running = false;
4197 }
4198}
4199
4200static void
David Keitel6e63bd52013-09-06 18:00:03 -07004201qpnp_chg_batfet_lcl_work(struct work_struct *work)
4202{
4203 struct qpnp_chg_chip *chip = container_of(work,
4204 struct qpnp_chg_chip, batfet_lcl_work);
4205
4206 mutex_lock(&chip->batfet_vreg_lock);
4207 if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
4208 qpnp_chg_is_dc_chg_plugged_in(chip)) {
4209 qpnp_chg_regulator_batfet_set(chip, 1);
4210 pr_debug("disabled ULPM\n");
4211 } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
4212 && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
4213 qpnp_chg_regulator_batfet_set(chip, 0);
4214 pr_debug("enabled ULPM\n");
4215 }
4216 mutex_unlock(&chip->batfet_vreg_lock);
4217}
4218
4219static void
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004220qpnp_chg_reduce_power_stage_work(struct work_struct *work)
4221{
4222 struct qpnp_chg_chip *chip = container_of(work,
4223 struct qpnp_chg_chip, reduce_power_stage_work);
4224
4225 qpnp_chg_reduce_power_stage(chip);
4226}
4227
4228static void
4229qpnp_chg_reduce_power_stage_callback(struct alarm *alarm)
4230{
4231 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
4232 reduce_power_stage_alarm);
4233
4234 schedule_work(&chip->reduce_power_stage_work);
4235}
4236
David Keitelbe208252013-01-31 14:49:25 -08004237static int
David Keitel432e1232013-06-05 16:10:18 -07004238qpnp_dc_power_set_property(struct power_supply *psy,
4239 enum power_supply_property psp,
4240 const union power_supply_propval *val)
4241{
4242 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
4243 dc_psy);
4244 int rc = 0;
4245
4246 switch (psp) {
4247 case POWER_SUPPLY_PROP_CURRENT_MAX:
4248 if (!val->intval)
4249 break;
4250
4251 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
4252 if (rc) {
4253 pr_err("Error setting idcmax property %d\n", rc);
4254 return rc;
4255 }
4256 chip->maxinput_dc_ma = (val->intval / 1000);
4257
4258 break;
4259 default:
4260 return -EINVAL;
4261 }
4262
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004263 pr_debug("psy changed dc_psy\n");
David Keitel432e1232013-06-05 16:10:18 -07004264 power_supply_changed(&chip->dc_psy);
4265 return rc;
4266}
4267
4268static int
David Keitelbe208252013-01-31 14:49:25 -08004269qpnp_batt_power_set_property(struct power_supply *psy,
4270 enum power_supply_property psp,
4271 const union power_supply_propval *val)
4272{
4273 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
4274 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004275 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08004276
4277 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07004278 case POWER_SUPPLY_PROP_COOL_TEMP:
4279 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
4280 break;
4281 case POWER_SUPPLY_PROP_WARM_TEMP:
4282 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
4283 break;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08004284 case POWER_SUPPLY_PROP_CAPACITY:
4285 chip->fake_battery_soc = val->intval;
4286 power_supply_changed(&chip->batt_psy);
4287 break;
David Keitelbe208252013-01-31 14:49:25 -08004288 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
4289 chip->charging_disabled = !(val->intval);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004290 if (chip->charging_disabled) {
4291 /* disable charging */
4292 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4293 qpnp_chg_force_run_on_batt(chip,
4294 chip->charging_disabled);
4295 } else {
4296 /* enable charging */
4297 qpnp_chg_force_run_on_batt(chip,
4298 chip->charging_disabled);
4299 qpnp_chg_charge_en(chip, !chip->charging_disabled);
4300 }
David Keitelbe208252013-01-31 14:49:25 -08004301 break;
4302 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
4303 qpnp_batt_system_temp_level_set(chip, val->intval);
4304 break;
David Keitel337bd862013-07-15 21:42:58 -07004305 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel820a90d2014-03-25 18:18:04 -07004306 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
4307 !(qpnp_is_dc_higher_prio(chip)
4308 && qpnp_chg_is_dc_chg_plugged_in(chip)))
David Keitel7b0568482013-12-02 14:47:42 -08004309 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
David Keitel337bd862013-07-15 21:42:58 -07004310 break;
David Keitel2586f0a2013-08-20 10:02:26 -07004311 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
4312 qpnp_chg_iusb_trim_set(chip, val->intval);
4313 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004314 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
David Keitel820a90d2014-03-25 18:18:04 -07004315 if (val->intval)
4316 qpnp_chg_input_current_settled(chip);
4317 else
4318 chip->aicl_settled = false;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004319 break;
David Keitel337bd862013-07-15 21:42:58 -07004320 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
4321 qpnp_chg_vinmin_set(chip, val->intval / 1000);
4322 break;
Fenglin Wuc64e9942014-08-22 13:47:34 +08004323 case POWER_SUPPLY_PROP_VCHG_LOOP_DBC_BYPASS:
4324 rc = qpnp_chg_bypass_vchg_loop_debouncer(chip, !!val->intval);
4325 break;
David Keitelbe208252013-01-31 14:49:25 -08004326 default:
4327 return -EINVAL;
4328 }
4329
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004330 pr_debug("psy changed batt_psy\n");
David Keitelbe208252013-01-31 14:49:25 -08004331 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004332 return rc;
David Keitelbe208252013-01-31 14:49:25 -08004333}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004334
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004335static int
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004336qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07004337{
David Keitelfe51cb92013-04-02 19:42:58 -07004338 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07004339 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07004340 if (chip->type == SMBB)
4341 chip->flags |= BOOST_FLASH_WA;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004342 if (chip->type == SMBBP) {
4343 struct device_node *revid_dev_node;
4344 struct pmic_revid_data *revid_data;
4345
4346 chip->flags |= BOOST_FLASH_WA;
4347
4348 revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
4349 "qcom,pmic-revid", 0);
4350 if (!revid_dev_node) {
4351 pr_err("Missing qcom,pmic-revid property\n");
4352 return -EINVAL;
4353 }
4354 revid_data = get_revid_data(revid_dev_node);
4355 if (IS_ERR(revid_data)) {
4356 pr_err("Couldnt get revid data rc = %ld\n",
4357 PTR_ERR(revid_data));
4358 return PTR_ERR(revid_data);
4359 }
4360
4361 if (revid_data->rev4 < PM8226_V2P1_REV4
4362 || ((revid_data->rev4 == PM8226_V2P1_REV4)
4363 && (revid_data->rev3 <= PM8226_V2P1_REV3))) {
4364 chip->flags |= POWER_STAGE_WA;
4365 }
4366 }
4367 return 0;
David Keiteld681cda2012-10-02 15:44:21 -07004368}
4369
David Keitel0f35be42013-04-16 11:10:40 -07004370static int
4371qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
4372{
4373 int rc = 0;
4374 struct resource *resource;
4375 struct spmi_resource *spmi_resource;
4376 u8 subtype;
4377 struct spmi_device *spmi = chip->spmi;
4378
4379 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
4380 if (!spmi_resource) {
4381 pr_err("qpnp_chg: spmi resource absent\n");
4382 return rc;
4383 }
4384
4385 resource = spmi_get_resource(spmi, spmi_resource,
4386 IORESOURCE_MEM, 0);
4387 if (!(resource && resource->start)) {
4388 pr_err("node %s IO resource absent!\n",
4389 spmi->dev.of_node->full_name);
4390 return rc;
4391 }
4392
4393 rc = qpnp_chg_read(chip, &subtype,
4394 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4395 if (rc) {
4396 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4397 return rc;
4398 }
4399
4400 switch (subtype) {
4401 case SMBB_CHGR_SUBTYPE:
4402 case SMBBP_CHGR_SUBTYPE:
4403 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004404 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004405 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004406 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004407 pr_err("Unable to get fast-chg-on irq\n");
4408 return rc;
4409 }
4410
David Keitel47185a62013-05-15 18:54:10 -07004411 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004412 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004413 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004414 pr_err("Unable to get trkl-chg-on irq\n");
4415 return rc;
4416 }
4417
David Keitel47185a62013-05-15 18:54:10 -07004418 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004419 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07004420 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004421 pr_err("Unable to get chg_failed irq\n");
4422 return rc;
4423 }
4424
David Keitel47185a62013-05-15 18:54:10 -07004425 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07004426 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07004427 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07004428 pr_err("Unable to get fast-chg-on irq\n");
4429 return rc;
4430 }
4431
David Keitel47185a62013-05-15 18:54:10 -07004432 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004433 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07004434 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004435 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004436 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004437 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004438 return rc;
4439 }
4440
David Keitel47185a62013-05-15 18:54:10 -07004441 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004442 qpnp_chg_chgr_chg_fastchg_irq_handler,
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08004443 IRQF_TRIGGER_RISING |
4444 IRQF_TRIGGER_FALLING,
David Keitel0f35be42013-04-16 11:10:40 -07004445 "fast-chg-on", chip);
4446 if (rc < 0) {
4447 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004448 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004449 return rc;
4450 }
4451
David Keitel47185a62013-05-15 18:54:10 -07004452 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004453 qpnp_chg_chgr_chg_trklchg_irq_handler,
4454 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004455 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004456 if (rc < 0) {
4457 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004458 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004459 return rc;
4460 }
David Keitel9fd07382013-05-02 15:37:44 -07004461
4462 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07004463 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07004464 qpnp_chg_vbatdet_lo_irq_handler,
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004465 IRQF_TRIGGER_RISING,
David Keitel9fd07382013-05-02 15:37:44 -07004466 "vbat-det-lo", chip);
4467 if (rc < 0) {
4468 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004469 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07004470 return rc;
4471 }
4472
David Keitelbf6a1062014-01-23 10:57:36 -08004473 qpnp_chg_irq_wake_enable(&chip->chg_trklchg);
4474 qpnp_chg_irq_wake_enable(&chip->chg_failed);
David Keitel47185a62013-05-15 18:54:10 -07004475 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitelbf6a1062014-01-23 10:57:36 -08004476 qpnp_chg_irq_wake_enable(&chip->chg_vbatdet_lo);
David Keitel0f35be42013-04-16 11:10:40 -07004477
4478 break;
4479 case SMBB_BAT_IF_SUBTYPE:
4480 case SMBBP_BAT_IF_SUBTYPE:
4481 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004482 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004483 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07004484 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004485 pr_err("Unable to get batt-pres irq\n");
4486 return rc;
4487 }
David Keitel47185a62013-05-15 18:54:10 -07004488 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004489 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07004490 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
4491 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07004492 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004493 if (rc < 0) {
4494 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004495 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004496 return rc;
4497 }
4498
David Keitelbf6a1062014-01-23 10:57:36 -08004499 qpnp_chg_irq_wake_enable(&chip->batt_pres);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004500
4501 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
4502 spmi_resource, "bat-temp-ok");
4503 if (chip->batt_temp_ok.irq < 0) {
4504 pr_err("Unable to get bat-temp-ok irq\n");
4505 return rc;
4506 }
4507 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
4508 qpnp_chg_bat_if_batt_temp_irq_handler,
4509 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4510 "bat-temp-ok", chip);
4511 if (rc < 0) {
4512 pr_err("Can't request %d bat-temp-ok irq: %d\n",
4513 chip->batt_temp_ok.irq, rc);
4514 return rc;
4515 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08004516 qpnp_chg_bat_if_batt_temp_irq_handler(0, chip);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004517
David Keitelbf6a1062014-01-23 10:57:36 -08004518 qpnp_chg_irq_wake_enable(&chip->batt_temp_ok);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004519
David Keitel0f35be42013-04-16 11:10:40 -07004520 break;
David Keitel337bd862013-07-15 21:42:58 -07004521 case SMBB_BUCK_SUBTYPE:
4522 case SMBBP_BUCK_SUBTYPE:
4523 case SMBCL_BUCK_SUBTYPE:
David Keitel337bd862013-07-15 21:42:58 -07004524 break;
4525
David Keitel0f35be42013-04-16 11:10:40 -07004526 case SMBB_USB_CHGPTH_SUBTYPE:
4527 case SMBBP_USB_CHGPTH_SUBTYPE:
4528 case SMBCL_USB_CHGPTH_SUBTYPE:
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004529 if (chip->ovp_monitor_enable) {
4530 chip->coarse_det_usb.irq =
4531 spmi_get_irq_byname(spmi,
4532 spmi_resource, "coarse-det-usb");
4533 if (chip->coarse_det_usb.irq < 0) {
4534 pr_err("Can't get coarse-det irq\n");
4535 return rc;
4536 }
4537 rc = devm_request_irq(chip->dev,
4538 chip->coarse_det_usb.irq,
4539 qpnp_chg_coarse_det_usb_irq_handler,
4540 IRQF_TRIGGER_RISING |
4541 IRQF_TRIGGER_FALLING,
4542 "coarse-det-usb", chip);
4543 if (rc < 0) {
4544 pr_err("Can't req %d coarse-det: %d\n",
4545 chip->coarse_det_usb.irq, rc);
4546 return rc;
4547 }
4548 }
4549
David Keitel47185a62013-05-15 18:54:10 -07004550 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004551 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004552 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004553 pr_err("Unable to get usbin irq\n");
4554 return rc;
4555 }
David Keitel47185a62013-05-15 18:54:10 -07004556 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004557 qpnp_chg_usb_usbin_valid_irq_handler,
4558 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004559 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004560 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004561 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004562 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004563 return rc;
4564 }
David Keitel344c6972013-04-09 19:28:21 -07004565
David Keitel47185a62013-05-15 18:54:10 -07004566 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07004567 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07004568 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07004569 pr_err("Unable to get chg-gone irq\n");
4570 return rc;
4571 }
David Keitel47185a62013-05-15 18:54:10 -07004572 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07004573 qpnp_chg_usb_chg_gone_irq_handler,
4574 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07004575 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07004576 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004577 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004578 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07004579 return rc;
4580 }
David Keitel47185a62013-05-15 18:54:10 -07004581
David Keitel0b62bdd2013-07-10 17:30:51 -07004582 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4583 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4584 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
4585 spmi_resource, "usb-ocp");
4586 if (chip->usb_ocp.irq < 0) {
4587 pr_err("Unable to get usbin irq\n");
4588 return rc;
4589 }
4590 rc = devm_request_irq(chip->dev,
4591 chip->usb_ocp.irq,
4592 qpnp_chg_usb_usb_ocp_irq_handler,
4593 IRQF_TRIGGER_RISING, "usb-ocp", chip);
4594 if (rc < 0) {
4595 pr_err("Can't request %d usb-ocp: %d\n",
4596 chip->usb_ocp.irq, rc);
4597 return rc;
4598 }
4599
David Keitelbf6a1062014-01-23 10:57:36 -08004600 qpnp_chg_irq_wake_enable(&chip->usb_ocp);
David Keitel0b62bdd2013-07-10 17:30:51 -07004601 }
4602
David Keitelbf6a1062014-01-23 10:57:36 -08004603 qpnp_chg_irq_wake_enable(&chip->usbin_valid);
4604 qpnp_chg_irq_wake_enable(&chip->chg_gone);
David Keitel0f35be42013-04-16 11:10:40 -07004605 break;
4606 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004607 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004608 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004609 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004610 pr_err("Unable to get dcin irq\n");
4611 return -rc;
4612 }
David Keitel47185a62013-05-15 18:54:10 -07004613 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004614 qpnp_chg_dc_dcin_valid_irq_handler,
4615 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004616 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004617 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004618 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004619 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004620 return rc;
4621 }
4622
David Keitelbf6a1062014-01-23 10:57:36 -08004623 qpnp_chg_irq_wake_enable(&chip->dcin_valid);
David Keitel0f35be42013-04-16 11:10:40 -07004624 break;
4625 }
4626 }
4627
4628 return rc;
4629}
4630
Xiaozhe Shica289e02013-06-19 13:24:51 -07004631static int
4632qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
4633{
4634 struct bms_battery_data batt_data;
4635 struct device_node *node;
4636 struct qpnp_vadc_result result;
4637 int rc;
4638
4639 node = of_find_node_by_name(chip->spmi->dev.of_node,
4640 "qcom,battery-data");
4641 if (node) {
4642 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004643 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07004644 if (rc) {
4645 pr_err("error reading batt id channel = %d, rc = %d\n",
4646 LR_MUX2_BAT_ID, rc);
4647 return rc;
4648 }
4649
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07004650 batt_data.max_voltage_uv = -1;
4651 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07004652 rc = of_batterydata_read_data(node,
4653 &batt_data, result.physical);
4654 if (rc) {
4655 pr_err("failed to read battery data: %d\n", rc);
4656 return rc;
4657 }
4658
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004659 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07004660 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004661 chip->safe_voltage_mv = chip->max_voltage_mv
4662 + MAX_DELTA_VDD_MAX_MV;
4663 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004664 if (batt_data.iterm_ua >= 0)
4665 chip->term_current = batt_data.iterm_ua / 1000;
4666 }
4667
4668 return 0;
4669}
4670
David Keitel80668952012-07-27 14:25:49 -07004671#define WDOG_EN_BIT BIT(7)
4672static int
4673qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
4674 struct spmi_resource *spmi_resource)
4675{
4676 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004677 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07004678 struct regulator_init_data *init_data;
4679 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07004680
4681 switch (subtype) {
4682 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004683 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004684 case SMBCL_CHGR_SUBTYPE:
Prasad Sodagudic3678012013-09-23 12:01:19 +05304685 qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
4686
David Keitel80668952012-07-27 14:25:49 -07004687 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
4688 if (rc) {
4689 pr_debug("failed setting min_voltage rc=%d\n", rc);
4690 return rc;
4691 }
David Keitel80668952012-07-27 14:25:49 -07004692 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
4693 if (rc) {
4694 pr_debug("failed setting safe_voltage rc=%d\n", rc);
4695 return rc;
4696 }
David Keitel454ee842013-03-08 16:19:11 -08004697 rc = qpnp_chg_vbatdet_set(chip,
4698 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08004699 if (rc) {
4700 pr_debug("failed setting resume_voltage rc=%d\n", rc);
4701 return rc;
4702 }
David Keitel80668952012-07-27 14:25:49 -07004703 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
4704 if (rc) {
4705 pr_debug("failed setting ibatmax rc=%d\n", rc);
4706 return rc;
4707 }
David Keitel365c4c42013-03-08 16:20:40 -08004708 if (chip->term_current) {
4709 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
4710 if (rc) {
4711 pr_debug("failed setting ibatterm rc=%d\n", rc);
4712 return rc;
4713 }
David Keitel80668952012-07-27 14:25:49 -07004714 }
David Keitel5d44fa52012-12-03 16:37:31 -08004715 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
4716 if (rc) {
4717 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
4718 return rc;
4719 }
David Keitela4b7b592013-04-11 18:34:35 -07004720 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
4721 if (rc) {
4722 pr_debug("failed setting tchg_mins rc=%d\n", rc);
4723 return rc;
4724 }
4725
David Keitel80668952012-07-27 14:25:49 -07004726 /* HACK: Disable wdog */
4727 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
4728 0xFF, 0xA0, 1);
4729
David Keitelb4e43542013-04-09 17:30:41 -07004730 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07004731 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4732 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07004733 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07004734
David Keitel79e08322014-04-21 14:17:05 -07004735 /* HACK: trkl stuck workaround */
4736
4737 rc = qpnp_chg_masked_write(chip,
4738 chip->chgr_base + SEC_ACCESS,
4739 0xFF,
4740 0xA5, 1);
4741
4742 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4743 CHG_OVR0,
4744 0xFF, 0x00, 1);
4745
4746 rc = qpnp_chg_masked_write(chip,
4747 chip->chgr_base + SEC_ACCESS,
4748 0xFF,
4749 0xA5, 1);
4750
4751 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4752 CHG_TRICKLE_CLAMP,
4753 0xFF, 0x00, 1);
Chunmei Cai661a7cd2014-08-05 17:31:54 +08004754
4755 rc = qpnp_chg_read(chip, &chip->chg_temp_thresh_default,
4756 chip->chgr_base + CHGR_CHG_TEMP_THRESH, 1);
4757 if (rc) {
4758 pr_debug("read CHG_TEMP_THRESH failed, rc = %d\n", rc);
4759 chip->chg_temp_thresh_default =
4760 CHG_TEMP_THRESH_DEFAULT;
4761 }
4762
4763 init_data = of_get_regulator_init_data(chip->dev,
4764 spmi_resource->of_node);
4765 if (!init_data) {
4766 pr_err("unable to get regulator init data for flash_wa\n");
4767 return -ENOMEM;
4768 }
4769
4770 if (init_data->constraints.name) {
4771 rdesc = &(chip->flash_wa_vreg.rdesc);
4772 rdesc->owner = THIS_MODULE;
4773 rdesc->type = REGULATOR_VOLTAGE;
4774 rdesc->ops = &qpnp_chg_flash_wa_reg_ops;
4775 rdesc->name = init_data->constraints.name;
4776
4777 init_data->constraints.valid_ops_mask
4778 |= REGULATOR_CHANGE_STATUS;
4779
4780 chip->flash_wa_vreg.rdev =
4781 regulator_register(rdesc, chip->dev, init_data,
4782 chip, spmi_resource->of_node);
4783 if (IS_ERR(chip->flash_wa_vreg.rdev)) {
4784 rc = PTR_ERR(chip->flash_wa_vreg.rdev);
4785 chip->flash_wa_vreg.rdev = NULL;
4786 pr_err("Flash wa failed, rc=%d\n", rc);
4787 return rc;
4788 }
4789 }
David Keitel80668952012-07-27 14:25:49 -07004790 break;
4791 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004792 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004793 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004794 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
4795 if (rc)
4796 return rc;
4797
David Keitel9201df32013-01-10 18:38:34 -08004798 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07004799 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08004800 BUCK_VBAT_REG_NODE_SEL_BIT,
4801 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
4802 if (rc) {
4803 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
4804 return rc;
4805 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07004806
4807 rc = qpnp_chg_read(chip, &chip->trim_center,
4808 chip->buck_base + BUCK_CTRL_TRIM1, 1);
4809 if (rc) {
4810 pr_debug("failed to read trim center rc=%d\n", rc);
4811 return rc;
4812 }
4813 chip->trim_center >>= 4;
4814 pr_debug("trim center = %02x\n", chip->trim_center);
David Keitel80668952012-07-27 14:25:49 -07004815 break;
4816 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004817 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004818 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07004819 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07004820 switch (chip->bpd_detection) {
4821 case BPD_TYPE_BAT_THM:
4822 reg = BAT_THM_EN;
4823 break;
4824 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07004825 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07004826 break;
4827 case BPD_TYPE_BAT_THM_BAT_ID:
4828 reg = BAT_THM_EN | BAT_ID_EN;
4829 break;
4830 default:
4831 reg = BAT_THM_EN;
4832 break;
4833 }
David Keitel796882d2013-05-14 18:01:11 -07004834
4835 rc = qpnp_chg_masked_write(chip,
4836 chip->bat_if_base + BAT_IF_BPD_CTRL,
4837 BAT_IF_BPD_CTRL_SEL,
4838 reg, 1);
4839 if (rc) {
4840 pr_debug("failed to chose BPD rc=%d\n", rc);
4841 return rc;
4842 }
David Keitel85ae4342013-04-16 11:46:00 -07004843 /* Force on VREF_BAT_THM */
4844 rc = qpnp_chg_masked_write(chip,
4845 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4846 VREF_BATT_THERM_FORCE_ON,
4847 VREF_BATT_THERM_FORCE_ON, 1);
4848 if (rc) {
4849 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
4850 return rc;
4851 }
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07004852
4853 init_data = of_get_regulator_init_data(chip->dev,
4854 spmi_resource->of_node);
4855
4856 if (init_data->constraints.name) {
4857 rdesc = &(chip->batfet_vreg.rdesc);
4858 rdesc->owner = THIS_MODULE;
4859 rdesc->type = REGULATOR_VOLTAGE;
4860 rdesc->ops = &qpnp_chg_batfet_vreg_ops;
4861 rdesc->name = init_data->constraints.name;
4862
4863 init_data->constraints.valid_ops_mask
4864 |= REGULATOR_CHANGE_STATUS;
4865
4866 chip->batfet_vreg.rdev = regulator_register(rdesc,
4867 chip->dev, init_data, chip,
4868 spmi_resource->of_node);
4869 if (IS_ERR(chip->batfet_vreg.rdev)) {
4870 rc = PTR_ERR(chip->batfet_vreg.rdev);
4871 chip->batfet_vreg.rdev = NULL;
4872 if (rc != -EPROBE_DEFER)
4873 pr_err("batfet reg failed, rc=%d\n",
4874 rc);
4875 return rc;
4876 }
4877 }
David Keitel80668952012-07-27 14:25:49 -07004878 break;
4879 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004880 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004881 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004882 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07004883 rc = qpnp_chg_masked_write(chip,
4884 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4885 ENUM_T_STOP_BIT,
4886 ENUM_T_STOP_BIT, 1);
4887 if (rc) {
4888 pr_err("failed to write enum stop rc=%d\n", rc);
4889 return -ENXIO;
4890 }
4891 }
David Keiteld681cda2012-10-02 15:44:21 -07004892
David Keitel6dc4ed42013-05-17 11:08:58 -07004893 init_data = of_get_regulator_init_data(chip->dev,
4894 spmi_resource->of_node);
4895 if (!init_data) {
4896 pr_err("unable to allocate memory\n");
4897 return -ENOMEM;
4898 }
4899
4900 if (init_data->constraints.name) {
4901 if (of_get_property(chip->dev->of_node,
4902 "otg-parent-supply", NULL))
4903 init_data->supply_regulator = "otg-parent";
4904
4905 rdesc = &(chip->otg_vreg.rdesc);
4906 rdesc->owner = THIS_MODULE;
4907 rdesc->type = REGULATOR_VOLTAGE;
4908 rdesc->ops = &qpnp_chg_otg_reg_ops;
4909 rdesc->name = init_data->constraints.name;
4910
4911 init_data->constraints.valid_ops_mask
4912 |= REGULATOR_CHANGE_STATUS;
4913
4914 chip->otg_vreg.rdev = regulator_register(rdesc,
4915 chip->dev, init_data, chip,
4916 spmi_resource->of_node);
4917 if (IS_ERR(chip->otg_vreg.rdev)) {
4918 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004919 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004920 if (rc != -EPROBE_DEFER)
4921 pr_err("OTG reg failed, rc=%d\n", rc);
4922 return rc;
4923 }
4924 }
4925
David Keiteld681cda2012-10-02 15:44:21 -07004926 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08004927 chip->usb_chgpth_base + USB_OVP_CTL,
4928 USB_VALID_DEB_20MS,
4929 USB_VALID_DEB_20MS, 1);
4930
4931 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07004932 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4933 ENUM_T_STOP_BIT,
4934 ENUM_T_STOP_BIT, 1);
4935
David Keitel344c6972013-04-09 19:28:21 -07004936 rc = qpnp_chg_masked_write(chip,
4937 chip->usb_chgpth_base + SEC_ACCESS,
4938 0xFF,
4939 0xA5, 1);
4940
4941 rc = qpnp_chg_masked_write(chip,
4942 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
4943 0xFF,
4944 0x80, 1);
4945
David Keitel0b62bdd2013-07-10 17:30:51 -07004946 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4947 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4948 rc = qpnp_chg_masked_write(chip,
4949 chip->usb_chgpth_base + USB_OCP_THR,
4950 OCP_THR_MASK,
4951 OCP_THR_900_MA, 1);
4952 if (rc)
4953 pr_err("Failed to configure OCP rc = %d\n", rc);
4954 }
4955
David Keitel80668952012-07-27 14:25:49 -07004956 break;
4957 case SMBB_DC_CHGPTH_SUBTYPE:
4958 break;
4959 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004960 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07004961 init_data = of_get_regulator_init_data(chip->dev,
4962 spmi_resource->of_node);
4963 if (!init_data) {
4964 pr_err("unable to allocate memory\n");
4965 return -ENOMEM;
4966 }
4967
4968 if (init_data->constraints.name) {
4969 if (of_get_property(chip->dev->of_node,
4970 "boost-parent-supply", NULL))
4971 init_data->supply_regulator = "boost-parent";
4972
4973 rdesc = &(chip->boost_vreg.rdesc);
4974 rdesc->owner = THIS_MODULE;
4975 rdesc->type = REGULATOR_VOLTAGE;
4976 rdesc->ops = &qpnp_chg_boost_reg_ops;
4977 rdesc->name = init_data->constraints.name;
4978
4979 init_data->constraints.valid_ops_mask
4980 |= REGULATOR_CHANGE_STATUS
4981 | REGULATOR_CHANGE_VOLTAGE;
4982
4983 chip->boost_vreg.rdev = regulator_register(rdesc,
4984 chip->dev, init_data, chip,
4985 spmi_resource->of_node);
4986 if (IS_ERR(chip->boost_vreg.rdev)) {
4987 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004988 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004989 if (rc != -EPROBE_DEFER)
4990 pr_err("boost reg failed, rc=%d\n", rc);
4991 return rc;
4992 }
4993 }
David Keitel80668952012-07-27 14:25:49 -07004994 break;
4995 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004996 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004997 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07004998 if (subtype == SMBB_MISC_SUBTYPE)
4999 chip->type = SMBB;
5000 else if (subtype == SMBBP_MISC_SUBTYPE)
5001 chip->type = SMBBP;
5002 else if (subtype == SMBCL_MISC_SUBTYPE)
5003 chip->type = SMBCL;
5004
David Keitel80668952012-07-27 14:25:49 -07005005 pr_debug("Setting BOOT_DONE\n");
5006 rc = qpnp_chg_masked_write(chip,
5007 chip->misc_base + CHGR_MISC_BOOT_DONE,
5008 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005009 rc = qpnp_chg_read(chip, &reg,
5010 chip->misc_base + MISC_REVISION2, 1);
5011 if (rc) {
5012 pr_err("failed to read revision register rc=%d\n", rc);
5013 return rc;
5014 }
David Keitel80668952012-07-27 14:25:49 -07005015
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005016 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07005017 break;
5018 default:
5019 pr_err("Invalid peripheral subtype\n");
5020 }
5021 return rc;
5022}
5023
David Keitel112ba9c2013-04-12 18:40:43 -07005024#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
5025do { \
5026 if (retval) \
5027 break; \
5028 \
5029 retval = of_property_read_u32(chip->spmi->dev.of_node, \
5030 "qcom," qpnp_dt_property, \
5031 &chip->prop); \
5032 \
5033 if ((retval == -EINVAL) && optional) \
5034 retval = 0; \
5035 else if (retval) \
5036 pr_err("Error reading " #qpnp_dt_property \
5037 " property rc = %d\n", rc); \
5038} while (0)
5039
5040static int
5041qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
5042{
5043 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07005044 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07005045
5046 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
5047 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
5048 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
5049 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
5050 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
5051 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
5052 if (rc)
5053 pr_err("failed to read required dt parameters %d\n", rc);
5054
5055 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
5056 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
5057 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
5058 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
5059 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07005060 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07005061 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
5062 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07005063 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
Prasad Sodagudic3678012013-09-23 12:01:19 +05305064 OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
David Keitelbdbae452014-01-14 17:19:50 -08005065 OF_PROP_READ(chip, vbatdet_max_err_mv, "vbatdet-maxerr-mv", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07005066
David Keitel112ba9c2013-04-12 18:40:43 -07005067 if (rc)
5068 return rc;
5069
David Keitel796882d2013-05-14 18:01:11 -07005070 rc = of_property_read_string(chip->spmi->dev.of_node,
5071 "qcom,bpd-detection", &bpd);
5072 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07005073 /* Select BAT_THM as default BPD scheme */
5074 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005075 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07005076 } else {
5077 chip->bpd_detection = get_bpd(bpd);
5078 if (chip->bpd_detection < 0) {
5079 pr_err("failed to determine bpd schema %d\n", rc);
5080 return rc;
5081 }
5082 }
5083
David Keitelbdbae452014-01-14 17:19:50 -08005084 if (!chip->vbatdet_max_err_mv)
5085 chip->vbatdet_max_err_mv = VBATDET_MAX_ERR_MV;
5086
David Keitel112ba9c2013-04-12 18:40:43 -07005087 /* Look up JEITA compliance parameters if cool and warm temp provided */
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005088 if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005089 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
5090 if (IS_ERR(chip->adc_tm_dev)) {
5091 rc = PTR_ERR(chip->adc_tm_dev);
5092 if (rc != -EPROBE_DEFER)
5093 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07005094 return rc;
5095 }
5096
5097 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
5098 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
5099 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
5100 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
5101 if (rc)
5102 return rc;
5103 }
5104
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08005105 /* Get the use-external-rsense property */
5106 chip->use_external_rsense = of_property_read_bool(
5107 chip->spmi->dev.of_node,
5108 "qcom,use-external-rsense");
5109
David Keitel89c17752013-06-28 14:52:48 -07005110 /* Get the btc-disabled property */
5111 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
5112 "qcom,btc-disabled");
5113
David Keitel2586f0a2013-08-20 10:02:26 -07005114 ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
5115 "qcom,ext-ovp-present");
5116
David Keitelcd2e1022014-05-02 17:25:15 -07005117 /* Check if external IOVP part is configured */
5118 chip->ext_ovp_isns_gpio = of_get_named_gpio(chip->spmi->dev.of_node,
5119 "qcom,ext-ovp-isns-enable-gpio", 0);
5120 if (gpio_is_valid(chip->ext_ovp_isns_gpio)) {
5121 ext_ovp_isns_present = true;
5122 rc = of_property_read_u32(chip->spmi->dev.of_node,
5123 "qcom,ext-ovp-isns-r-ohm", &ext_ovp_isns_r);
5124 if (rc)
5125 return rc;
5126 }
5127
David Keitel112ba9c2013-04-12 18:40:43 -07005128 /* Get the charging-disabled property */
5129 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
5130 "qcom,charging-disabled");
5131
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005132 chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
5133 "qcom,ovp-monitor-en");
5134
David Keitel8b68d2d2013-05-14 23:36:51 -07005135 /* Get the duty-cycle-100p property */
5136 chip->duty_cycle_100p = of_property_read_bool(
5137 chip->spmi->dev.of_node,
5138 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07005139
David Keitel112ba9c2013-04-12 18:40:43 -07005140 /* Get the fake-batt-values property */
5141 chip->use_default_batt_values =
5142 of_property_read_bool(chip->spmi->dev.of_node,
5143 "qcom,use-default-batt-values");
5144
5145 /* Disable charging when faking battery values */
5146 if (chip->use_default_batt_values)
5147 chip->charging_disabled = true;
5148
Zhenhua Huangdc335512013-10-30 11:45:15 +08005149 chip->power_stage_workaround_enable =
5150 of_property_read_bool(chip->spmi->dev.of_node,
5151 "qcom,power-stage-reduced");
5152
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07005153 chip->ibat_calibration_enabled =
5154 of_property_read_bool(chip->spmi->dev.of_node,
5155 "qcom,ibat-calibration-enabled");
David Keitel975b5352014-01-27 14:28:04 -08005156 chip->parallel_ovp_mode =
5157 of_property_read_bool(chip->spmi->dev.of_node,
5158 "qcom,parallel-ovp-mode");
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07005159
David Keitel112ba9c2013-04-12 18:40:43 -07005160 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
5161 &(chip->thermal_levels));
5162
5163 if (chip->thermal_levels > sizeof(int)) {
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305164 chip->thermal_mitigation = devm_kzalloc(chip->dev,
David Keitel112ba9c2013-04-12 18:40:43 -07005165 chip->thermal_levels,
5166 GFP_KERNEL);
5167
5168 if (chip->thermal_mitigation == NULL) {
5169 pr_err("thermal mitigation kzalloc() failed.\n");
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305170 return -ENOMEM;
David Keitel112ba9c2013-04-12 18:40:43 -07005171 }
5172
5173 chip->thermal_levels /= sizeof(int);
5174 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
5175 "qcom,thermal-mitigation",
5176 chip->thermal_mitigation, chip->thermal_levels);
5177 if (rc) {
5178 pr_err("qcom,thermal-mitigation missing in dt\n");
5179 return rc;
5180 }
5181 }
5182
5183 return rc;
5184}
5185
David Keitel80668952012-07-27 14:25:49 -07005186static int __devinit
5187qpnp_charger_probe(struct spmi_device *spmi)
5188{
5189 u8 subtype;
5190 struct qpnp_chg_chip *chip;
5191 struct resource *resource;
5192 struct spmi_resource *spmi_resource;
5193 int rc = 0;
5194
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305195 chip = devm_kzalloc(&spmi->dev,
5196 sizeof(struct qpnp_chg_chip), GFP_KERNEL);
David Keitel80668952012-07-27 14:25:49 -07005197 if (chip == NULL) {
5198 pr_err("kzalloc() failed.\n");
5199 return -ENOMEM;
5200 }
5201
David Keitelfd305ee2013-07-19 20:19:06 -07005202 chip->prev_usb_max_ma = -EINVAL;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08005203 chip->fake_battery_soc = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07005204 chip->dev = &(spmi->dev);
5205 chip->spmi = spmi;
5206
5207 chip->usb_psy = power_supply_get_by_name("usb");
5208 if (!chip->usb_psy) {
5209 pr_err("usb supply not found deferring probe\n");
5210 rc = -EPROBE_DEFER;
5211 goto fail_chg_enable;
5212 }
5213
David Keitelec3c09802013-06-13 13:05:30 -07005214 mutex_init(&chip->jeita_configure_lock);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005215 spin_lock_init(&chip->usbin_health_monitor_lock);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005216 alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
5217 qpnp_chg_reduce_power_stage_callback);
5218 INIT_WORK(&chip->reduce_power_stage_work,
5219 qpnp_chg_reduce_power_stage_work);
David Keitel6e63bd52013-09-06 18:00:03 -07005220 mutex_init(&chip->batfet_vreg_lock);
David Keitel8b9bd312014-01-15 14:44:00 -08005221 INIT_WORK(&chip->ocp_clear_work,
5222 qpnp_chg_ocp_clear_work);
David Keitel6e63bd52013-09-06 18:00:03 -07005223 INIT_WORK(&chip->batfet_lcl_work,
5224 qpnp_chg_batfet_lcl_work);
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005225 INIT_WORK(&chip->insertion_ocv_work,
5226 qpnp_chg_insertion_ocv_work);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005227
David Keitel112ba9c2013-04-12 18:40:43 -07005228 /* Get all device tree properties */
5229 rc = qpnp_charger_read_dt_props(chip);
5230 if (rc)
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305231 return rc;
David Keitel3dd5e0f2012-12-12 18:12:36 -08005232
David Keitelcd2e1022014-05-02 17:25:15 -07005233 if (ext_ovp_isns_present)
5234 chip->ext_ovp_ic_gpio_enabled = 0;
5235
Xiaozhe Shica289e02013-06-19 13:24:51 -07005236 /*
5237 * Check if bat_if is set in DT and make sure VADC is present
5238 * Also try loading the battery data profile if bat_if exists
5239 */
David Keiteldd87a172013-05-29 17:05:43 -07005240 spmi_for_each_container_dev(spmi_resource, spmi) {
5241 if (!spmi_resource) {
5242 pr_err("qpnp_chg: spmi resource absent\n");
5243 rc = -ENXIO;
5244 goto fail_chg_enable;
5245 }
5246
5247 resource = spmi_get_resource(spmi, spmi_resource,
5248 IORESOURCE_MEM, 0);
5249 if (!(resource && resource->start)) {
5250 pr_err("node %s IO resource absent!\n",
5251 spmi->dev.of_node->full_name);
5252 rc = -ENXIO;
5253 goto fail_chg_enable;
5254 }
5255
5256 rc = qpnp_chg_read(chip, &subtype,
5257 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
5258 if (rc) {
5259 pr_err("Peripheral subtype read failed rc=%d\n", rc);
5260 goto fail_chg_enable;
5261 }
5262
5263 if (subtype == SMBB_BAT_IF_SUBTYPE ||
5264 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07005265 subtype == SMBCL_BAT_IF_SUBTYPE) {
5266 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
5267 if (IS_ERR(chip->vadc_dev)) {
5268 rc = PTR_ERR(chip->vadc_dev);
5269 if (rc != -EPROBE_DEFER)
5270 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07005271 goto fail_chg_enable;
David Keitel42648fd2013-08-16 17:45:20 -07005272 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07005273
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08005274 if (subtype == SMBB_BAT_IF_SUBTYPE) {
5275 chip->iadc_dev = qpnp_get_iadc(chip->dev,
5276 "chg");
5277 if (IS_ERR(chip->iadc_dev)) {
5278 rc = PTR_ERR(chip->iadc_dev);
5279 if (rc != -EPROBE_DEFER)
5280 pr_err("iadc property missing\n");
5281 goto fail_chg_enable;
5282 }
5283 }
5284
Xiaozhe Shica289e02013-06-19 13:24:51 -07005285 rc = qpnp_chg_load_battery_data(chip);
5286 if (rc)
5287 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07005288 }
5289 }
5290
David Keitel80668952012-07-27 14:25:49 -07005291 spmi_for_each_container_dev(spmi_resource, spmi) {
5292 if (!spmi_resource) {
5293 pr_err("qpnp_chg: spmi resource absent\n");
5294 rc = -ENXIO;
5295 goto fail_chg_enable;
5296 }
5297
5298 resource = spmi_get_resource(spmi, spmi_resource,
5299 IORESOURCE_MEM, 0);
5300 if (!(resource && resource->start)) {
5301 pr_err("node %s IO resource absent!\n",
5302 spmi->dev.of_node->full_name);
5303 rc = -ENXIO;
5304 goto fail_chg_enable;
5305 }
5306
5307 rc = qpnp_chg_read(chip, &subtype,
5308 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
5309 if (rc) {
5310 pr_err("Peripheral subtype read failed rc=%d\n", rc);
5311 goto fail_chg_enable;
5312 }
5313
5314 switch (subtype) {
5315 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005316 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005317 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005318 chip->chgr_base = resource->start;
5319 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5320 if (rc) {
5321 pr_err("Failed to init subtype 0x%x rc=%d\n",
5322 subtype, rc);
5323 goto fail_chg_enable;
5324 }
5325 break;
5326 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005327 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005328 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005329 chip->buck_base = resource->start;
5330 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5331 if (rc) {
5332 pr_err("Failed to init subtype 0x%x rc=%d\n",
5333 subtype, rc);
5334 goto fail_chg_enable;
5335 }
David Keitel344c6972013-04-09 19:28:21 -07005336
5337 rc = qpnp_chg_masked_write(chip,
5338 chip->buck_base + SEC_ACCESS,
5339 0xFF,
5340 0xA5, 1);
5341
5342 rc = qpnp_chg_masked_write(chip,
5343 chip->buck_base + BUCK_VCHG_OV,
5344 0xff,
5345 0x00, 1);
5346
David Keiteldbc949b2013-07-11 10:56:03 -07005347 if (chip->duty_cycle_100p) {
5348 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
5349 1);
5350 if (rc) {
5351 pr_err("failed to set duty cycle %d\n",
5352 rc);
5353 goto fail_chg_enable;
5354 }
5355 }
5356
David Keitel80668952012-07-27 14:25:49 -07005357 break;
5358 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005359 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005360 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005361 chip->bat_if_base = resource->start;
5362 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5363 if (rc) {
5364 pr_err("Failed to init subtype 0x%x rc=%d\n",
5365 subtype, rc);
5366 goto fail_chg_enable;
5367 }
5368 break;
5369 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005370 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005371 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005372 chip->usb_chgpth_base = resource->start;
5373 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5374 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07005375 if (rc != -EPROBE_DEFER)
5376 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07005377 subtype, rc);
5378 goto fail_chg_enable;
5379 }
5380 break;
5381 case SMBB_DC_CHGPTH_SUBTYPE:
5382 chip->dc_chgpth_base = resource->start;
5383 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5384 if (rc) {
5385 pr_err("Failed to init subtype 0x%x rc=%d\n",
5386 subtype, rc);
5387 goto fail_chg_enable;
5388 }
5389 break;
5390 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005391 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005392 chip->boost_base = resource->start;
5393 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5394 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07005395 if (rc != -EPROBE_DEFER)
5396 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07005397 subtype, rc);
5398 goto fail_chg_enable;
5399 }
5400 break;
5401 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005402 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005403 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005404 chip->misc_base = resource->start;
5405 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5406 if (rc) {
5407 pr_err("Failed to init subtype=0x%x rc=%d\n",
5408 subtype, rc);
5409 goto fail_chg_enable;
5410 }
5411 break;
5412 default:
5413 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
5414 rc = -EINVAL;
5415 goto fail_chg_enable;
5416 }
5417 }
5418 dev_set_drvdata(&spmi->dev, chip);
5419 device_init_wakeup(&spmi->dev, 1);
5420
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005421 chip->insertion_ocv_uv = -EINVAL;
5422 chip->batt_present = qpnp_chg_is_batt_present(chip);
David Keitelf2170cc2013-02-20 17:49:03 -08005423 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08005424 chip->batt_psy.name = "battery";
5425 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
5426 chip->batt_psy.properties = msm_batt_power_props;
5427 chip->batt_psy.num_properties =
5428 ARRAY_SIZE(msm_batt_power_props);
5429 chip->batt_psy.get_property = qpnp_batt_power_get_property;
5430 chip->batt_psy.set_property = qpnp_batt_power_set_property;
5431 chip->batt_psy.property_is_writeable =
5432 qpnp_batt_property_is_writeable;
5433 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07005434 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07005435 chip->batt_psy.supplied_to = pm_batt_supplied_to;
5436 chip->batt_psy.num_supplicants =
5437 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07005438
David Keitelf2170cc2013-02-20 17:49:03 -08005439 rc = power_supply_register(chip->dev, &chip->batt_psy);
5440 if (rc < 0) {
5441 pr_err("batt failed to register rc = %d\n", rc);
5442 goto fail_chg_enable;
5443 }
David Keitel79f4c932013-04-03 16:08:39 -07005444 INIT_WORK(&chip->adc_measure_work,
5445 qpnp_bat_if_adc_measure_work);
David Keitelaa375562013-08-08 09:43:28 -07005446 INIT_WORK(&chip->adc_disable_work,
David Keitelecab15a2013-08-06 15:41:39 -07005447 qpnp_bat_if_adc_disable_work);
David Keitelc7093b02013-02-14 12:50:04 -08005448 }
5449
David Keitel9fd07382013-05-02 15:37:44 -07005450 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07005451 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005452 INIT_DELAYED_WORK(&chip->usbin_health_check,
5453 qpnp_usbin_health_check_work);
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07005454 INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
David Keitel7ac385e2013-08-19 18:02:40 -07005455 INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
David Keitel5910eea2013-05-02 15:32:25 -07005456
David Keitelf2170cc2013-02-20 17:49:03 -08005457 if (chip->dc_chgpth_base) {
5458 chip->dc_psy.name = "qpnp-dc";
5459 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
5460 chip->dc_psy.supplied_to = pm_power_supplied_to;
5461 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
5462 chip->dc_psy.properties = pm_power_props_mains;
5463 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
5464 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07005465 chip->dc_psy.set_property = qpnp_dc_power_set_property;
5466 chip->dc_psy.property_is_writeable =
5467 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08005468
5469 rc = power_supply_register(chip->dev, &chip->dc_psy);
5470 if (rc < 0) {
5471 pr_err("power_supply_register dc failed rc=%d\n", rc);
5472 goto unregister_batt;
5473 }
David Keitel80668952012-07-27 14:25:49 -07005474 }
5475
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005476 /* Turn on appropriate workaround flags */
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005477 rc = qpnp_chg_setup_flags(chip);
5478 if (rc < 0) {
5479 pr_err("failed to setup flags rc=%d\n", rc);
5480 goto unregister_dc_psy;
5481 }
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005482
David Keitelf2170cc2013-02-20 17:49:03 -08005483 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08005484 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
5485 if (rc) {
5486 pr_err("Error setting idcmax property %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005487 goto unregister_dc_psy;
David Keitel22ed2232013-01-28 11:04:07 -08005488 }
5489 }
5490
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005491 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0aea18a2013-06-14 18:57:57 -07005492 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07005493 chip->adc_param.low_temp = chip->cool_bat_decidegc;
5494 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08005495 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
5496 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
5497 chip->adc_param.btm_ctx = chip;
5498 chip->adc_param.threshold_notification =
5499 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08005500 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07005501
5502 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005503 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
5504 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005505 if (rc) {
5506 pr_err("request ADC error %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005507 goto unregister_dc_psy;
David Keitel0c1a4532013-03-21 16:39:06 -07005508 }
David Keitel454ee842013-03-08 16:19:11 -08005509 }
5510 }
David Keitel89c17752013-06-28 14:52:48 -07005511 rc = qpnp_chg_bat_if_configure_btc(chip);
5512 if (rc) {
5513 pr_err("failed to configure btc %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005514 goto unregister_dc_psy;
David Keitel89c17752013-06-28 14:52:48 -07005515 }
David Keitel454ee842013-03-08 16:19:11 -08005516
David Keitelcd2e1022014-05-02 17:25:15 -07005517 chip->usb_trim_default = qpnp_chg_iusb_trim_get(chip);
David Keitel03ee6b52012-10-22 12:25:19 -07005518 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08005519 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07005520 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07005521
David Keitelbf2edba2014-03-05 10:49:32 -08005522 if (chip->parallel_ovp_mode) {
5523 rc = override_dcin_ilimit(chip, 1);
5524 if (rc) {
5525 pr_err("Override DCIN LLIMIT %d\n", rc);
5526 goto unregister_dc_psy;
5527 }
5528 }
5529
David Keitel0f35be42013-04-16 11:10:40 -07005530 rc = qpnp_chg_request_irqs(chip);
5531 if (rc) {
5532 pr_err("failed to request interrupts %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005533 goto unregister_dc_psy;
David Keitel0f35be42013-04-16 11:10:40 -07005534 }
5535
David Keitel7e38f512013-11-19 11:15:11 -08005536 qpnp_chg_usb_chg_gone_irq_handler(chip->chg_gone.irq, chip);
David Keitelad980fc2013-07-30 18:12:02 -07005537 qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
5538 qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
David Keitel9fd07382013-05-02 15:37:44 -07005539 power_supply_set_present(chip->usb_psy,
5540 qpnp_chg_is_usb_chg_plugged_in(chip));
5541
David Keitel3c62b472013-05-06 15:38:11 -07005542 /* Set USB psy online to avoid userspace from shutting down if battery
5543 * capacity is at zero and no chargers online. */
5544 if (qpnp_chg_is_usb_chg_plugged_in(chip))
5545 power_supply_set_online(chip->usb_psy, 1);
5546
David Keitel7ac385e2013-08-19 18:02:40 -07005547 schedule_delayed_work(&chip->aicl_check_work,
5548 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel796882d2013-05-14 18:01:11 -07005549 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 -08005550 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07005551 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08005552 qpnp_chg_is_usb_chg_plugged_in(chip),
5553 qpnp_chg_is_dc_chg_plugged_in(chip),
5554 get_prop_batt_present(chip),
5555 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07005556 return 0;
5557
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005558unregister_dc_psy:
5559 if (chip->dc_chgpth_base)
5560 power_supply_unregister(&chip->dc_psy);
David Keitelc7093b02013-02-14 12:50:04 -08005561unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08005562 if (chip->bat_if_base)
5563 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07005564fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07005565 regulator_unregister(chip->otg_vreg.rdev);
5566 regulator_unregister(chip->boost_vreg.rdev);
David Keitel80668952012-07-27 14:25:49 -07005567 return rc;
5568}
5569
5570static int __devexit
5571qpnp_charger_remove(struct spmi_device *spmi)
5572{
5573 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005574 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07005575 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005576 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
5577 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005578 }
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305579
5580 cancel_delayed_work_sync(&chip->aicl_check_work);
5581 power_supply_unregister(&chip->dc_psy);
5582 cancel_work_sync(&chip->soc_check_work);
5583 cancel_delayed_work_sync(&chip->usbin_health_check);
5584 cancel_delayed_work_sync(&chip->arb_stop_work);
David Keitel9fd07382013-05-02 15:37:44 -07005585 cancel_delayed_work_sync(&chip->eoc_work);
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305586 cancel_work_sync(&chip->adc_disable_work);
5587 cancel_work_sync(&chip->adc_measure_work);
5588 power_supply_unregister(&chip->batt_psy);
5589 cancel_work_sync(&chip->batfet_lcl_work);
5590 cancel_work_sync(&chip->insertion_ocv_work);
5591 cancel_work_sync(&chip->reduce_power_stage_work);
5592 alarm_cancel(&chip->reduce_power_stage_alarm);
5593
5594 mutex_destroy(&chip->batfet_vreg_lock);
5595 mutex_destroy(&chip->jeita_configure_lock);
David Keitel79f4c932013-04-03 16:08:39 -07005596
David Collinscbb12132013-05-28 10:47:28 -07005597 regulator_unregister(chip->otg_vreg.rdev);
5598 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07005599
David Keitel80668952012-07-27 14:25:49 -07005600 return 0;
5601}
5602
David Keitel85ae4342013-04-16 11:46:00 -07005603static int qpnp_chg_resume(struct device *dev)
5604{
5605 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5606 int rc = 0;
5607
David Keitel39093572013-06-05 15:32:30 -07005608 if (chip->bat_if_base) {
5609 rc = qpnp_chg_masked_write(chip,
5610 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5611 VREF_BATT_THERM_FORCE_ON,
5612 VREF_BATT_THERM_FORCE_ON, 1);
5613 if (rc)
5614 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
5615 }
David Keitel85ae4342013-04-16 11:46:00 -07005616
5617 return rc;
5618}
5619
5620static int qpnp_chg_suspend(struct device *dev)
5621{
5622 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5623 int rc = 0;
5624
David Keitel39093572013-06-05 15:32:30 -07005625 if (chip->bat_if_base) {
5626 rc = qpnp_chg_masked_write(chip,
5627 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5628 VREF_BATT_THERM_FORCE_ON,
5629 VREF_BAT_THM_ENABLED_FSM, 1);
5630 if (rc)
5631 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
5632 }
David Keitel85ae4342013-04-16 11:46:00 -07005633
5634 return rc;
5635}
5636
David Keitel723d5012013-05-03 13:17:27 -07005637static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07005638 .resume = qpnp_chg_resume,
5639 .suspend = qpnp_chg_suspend,
5640};
5641
David Keitel80668952012-07-27 14:25:49 -07005642static struct spmi_driver qpnp_charger_driver = {
5643 .probe = qpnp_charger_probe,
5644 .remove = __devexit_p(qpnp_charger_remove),
5645 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07005646 .name = QPNP_CHARGER_DEV_NAME,
5647 .owner = THIS_MODULE,
5648 .of_match_table = qpnp_charger_match_table,
5649 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07005650 },
5651};
5652
5653/**
5654 * qpnp_chg_init() - register spmi driver for qpnp-chg
5655 */
5656int __init
5657qpnp_chg_init(void)
5658{
5659 return spmi_driver_register(&qpnp_charger_driver);
5660}
5661module_init(qpnp_chg_init);
5662
5663static void __exit
5664qpnp_chg_exit(void)
5665{
5666 spmi_driver_unregister(&qpnp_charger_driver);
5667}
5668module_exit(qpnp_chg_exit);
5669
5670
5671MODULE_DESCRIPTION("QPNP charger driver");
5672MODULE_LICENSE("GPL v2");
5673MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);