blob: 63017248a84b44465e1599be58446937b7741ba9 [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 Keitel80668952012-07-27 14:25:49 -070035
36/* Interrupt offsets */
37#define INT_RT_STS(base) (base + 0x10)
38#define INT_SET_TYPE(base) (base + 0x11)
39#define INT_POLARITY_HIGH(base) (base + 0x12)
40#define INT_POLARITY_LOW(base) (base + 0x13)
41#define INT_LATCHED_CLR(base) (base + 0x14)
42#define INT_EN_SET(base) (base + 0x15)
43#define INT_EN_CLR(base) (base + 0x16)
44#define INT_LATCHED_STS(base) (base + 0x18)
45#define INT_PENDING_STS(base) (base + 0x19)
46#define INT_MID_SEL(base) (base + 0x1A)
47#define INT_PRIORITY(base) (base + 0x1B)
48
49/* Peripheral register offsets */
50#define CHGR_CHG_OPTION 0x08
51#define CHGR_ATC_STATUS 0x0A
52#define CHGR_VBAT_STATUS 0x0B
53#define CHGR_IBAT_BMS 0x0C
54#define CHGR_IBAT_STS 0x0D
55#define CHGR_VDD_MAX 0x40
56#define CHGR_VDD_SAFE 0x41
57#define CHGR_VDD_MAX_STEP 0x42
58#define CHGR_IBAT_MAX 0x44
59#define CHGR_IBAT_SAFE 0x45
60#define CHGR_VIN_MIN 0x47
61#define CHGR_VIN_MIN_STEP 0x48
62#define CHGR_CHG_CTRL 0x49
63#define CHGR_CHG_FAILED 0x4A
64#define CHGR_ATC_CTRL 0x4B
65#define CHGR_ATC_FAILED 0x4C
66#define CHGR_VBAT_TRKL 0x50
67#define CHGR_VBAT_WEAK 0x52
68#define CHGR_IBAT_ATC_A 0x54
69#define CHGR_IBAT_ATC_B 0x55
70#define CHGR_IBAT_TERM_CHGR 0x5B
71#define CHGR_IBAT_TERM_BMS 0x5C
72#define CHGR_VBAT_DET 0x5D
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -080073#define CHGR_TTRKL_MAX_EN 0x5E
David Keitel80668952012-07-27 14:25:49 -070074#define CHGR_TTRKL_MAX 0x5F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -080075#define CHGR_TCHG_MAX_EN 0x60
David Keitel80668952012-07-27 14:25:49 -070076#define CHGR_TCHG_MAX 0x61
77#define CHGR_CHG_WDOG_TIME 0x62
78#define CHGR_CHG_WDOG_DLY 0x63
79#define CHGR_CHG_WDOG_PET 0x64
80#define CHGR_CHG_WDOG_EN 0x65
David Keitel9201df32013-01-10 18:38:34 -080081#define CHGR_IR_DROP_COMPEN 0x67
David Keitel22ed2232013-01-28 11:04:07 -080082#define CHGR_I_MAX_REG 0x44
David Keiteld681cda2012-10-02 15:44:21 -070083#define CHGR_USB_USB_SUSP 0x47
David Keitel6f865cd2012-11-30 15:04:32 -080084#define CHGR_USB_USB_OTG_CTL 0x48
David Keitel80668952012-07-27 14:25:49 -070085#define CHGR_USB_ENUM_T_STOP 0x4E
David Keitel2586f0a2013-08-20 10:02:26 -070086#define CHGR_USB_TRIM 0xF1
David Keitel80668952012-07-27 14:25:49 -070087#define CHGR_CHG_TEMP_THRESH 0x66
88#define CHGR_BAT_IF_PRES_STATUS 0x08
David Keiteld681cda2012-10-02 15:44:21 -070089#define CHGR_STATUS 0x09
David Keitel80668952012-07-27 14:25:49 -070090#define CHGR_BAT_IF_VCP 0x42
91#define CHGR_BAT_IF_BATFET_CTRL1 0x90
David Keitel9eca8ac2013-09-06 14:18:36 -070092#define CHGR_BAT_IF_BATFET_CTRL4 0x93
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -070093#define CHGR_BAT_IF_SPARE 0xDF
David Keitel80668952012-07-27 14:25:49 -070094#define CHGR_MISC_BOOT_DONE 0x42
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -070095#define CHGR_BUCK_PSTG_CTRL 0x73
David Keitel9fd07382013-05-02 15:37:44 -070096#define CHGR_BUCK_COMPARATOR_OVRIDE_1 0xEB
David Keiteld681cda2012-10-02 15:44:21 -070097#define CHGR_BUCK_COMPARATOR_OVRIDE_3 0xED
David Keitel9201df32013-01-10 18:38:34 -080098#define CHGR_BUCK_BCK_VBAT_REG_MODE 0x74
Sridhar Parasuramae183bd2012-12-21 09:28:46 -080099#define MISC_REVISION2 0x01
David Keitel5c3a7702012-12-20 11:13:21 -0800100#define USB_OVP_CTL 0x42
David Keitel344c6972013-04-09 19:28:21 -0700101#define USB_CHG_GONE_REV_BST 0xED
102#define BUCK_VCHG_OV 0x77
103#define BUCK_TEST_SMBC_MODES 0xE6
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700104#define BUCK_CTRL_TRIM1 0xF1
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700105#define BUCK_CTRL_TRIM3 0xF3
David Keiteld681cda2012-10-02 15:44:21 -0700106#define SEC_ACCESS 0xD0
David Keitel85ae4342013-04-16 11:46:00 -0700107#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
David Keitel796882d2013-05-14 18:01:11 -0700108#define BAT_IF_BPD_CTRL 0x48
David Keitel6dc4ed42013-05-17 11:08:58 -0700109#define BOOST_VSET 0x41
110#define BOOST_ENABLE_CONTROL 0x46
David Keitel33f58952013-05-20 16:17:36 -0700111#define COMP_OVR1 0xEA
David Keitel89c17752013-06-28 14:52:48 -0700112#define BAT_IF_BTC_CTRL 0x49
David Keitel0b62bdd2013-07-10 17:30:51 -0700113#define USB_OCP_THR 0x52
114#define USB_OCP_CLR 0x53
Zhenhua Huang2a0ee352013-07-23 01:55:43 +0800115#define BAT_IF_TEMP_STATUS 0x09
David Keitel8b9bd312014-01-15 14:44:00 -0800116#define BOOST_ILIM 0x78
David Keitel975b5352014-01-27 14:28:04 -0800117#define USB_SPARE 0xDF
118#define DC_COMP_OVR1 0xE9
David Keitel59fbb762014-02-05 16:46:24 -0800119#define CHGR_COMP_OVR1 0xEE
David Keitel33f58952013-05-20 16:17:36 -0700120
David Keitel80668952012-07-27 14:25:49 -0700121#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700122
David Keitelf2170cc2013-02-20 17:49:03 -0800123/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700124#define SMBB_CHGR_SUBTYPE 0x01
125#define SMBB_BUCK_SUBTYPE 0x02
126#define SMBB_BAT_IF_SUBTYPE 0x03
127#define SMBB_USB_CHGPTH_SUBTYPE 0x04
128#define SMBB_DC_CHGPTH_SUBTYPE 0x05
129#define SMBB_BOOST_SUBTYPE 0x06
130#define SMBB_MISC_SUBTYPE 0x07
131
David Keitelf2170cc2013-02-20 17:49:03 -0800132/* SMBB peripheral subtype values */
133#define SMBBP_CHGR_SUBTYPE 0x31
134#define SMBBP_BUCK_SUBTYPE 0x32
135#define SMBBP_BAT_IF_SUBTYPE 0x33
136#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
137#define SMBBP_BOOST_SUBTYPE 0x36
138#define SMBBP_MISC_SUBTYPE 0x37
139
David Keitel46c9f7b2013-04-02 19:54:12 -0700140/* SMBCL peripheral subtype values */
141#define SMBCL_CHGR_SUBTYPE 0x41
142#define SMBCL_BUCK_SUBTYPE 0x42
143#define SMBCL_BAT_IF_SUBTYPE 0x43
144#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
145#define SMBCL_MISC_SUBTYPE 0x47
146
David Keitel80668952012-07-27 14:25:49 -0700147#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
148
David Keitelb80eda82012-10-15 10:49:11 -0700149/* Status bits and masks */
150#define CHGR_BOOT_DONE BIT(7)
151#define CHGR_CHG_EN BIT(7)
152#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800153#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800154#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700155#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700156#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700157#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700158#define REV_BST_DETECTED BIT(0)
159#define BAT_THM_EN BIT(1)
160#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700161#define BOOST_PWR_EN BIT(7)
David Keitel0b62bdd2013-07-10 17:30:51 -0700162#define OCP_CLR_BIT BIT(7)
163#define OCP_THR_MASK 0x03
164#define OCP_THR_900_MA 0x02
165#define OCP_THR_500_MA 0x01
166#define OCP_THR_200_MA 0x00
David Keitelb80eda82012-10-15 10:49:11 -0700167
David Keitel80668952012-07-27 14:25:49 -0700168/* Interrupt definitions */
169/* smbb_chg_interrupts */
170#define CHG_DONE_IRQ BIT(7)
171#define CHG_FAILED_IRQ BIT(6)
172#define FAST_CHG_ON_IRQ BIT(5)
173#define TRKL_CHG_ON_IRQ BIT(4)
174#define STATE_CHANGE_ON_IR BIT(3)
175#define CHGWDDOG_IRQ BIT(2)
176#define VBAT_DET_HI_IRQ BIT(1)
177#define VBAT_DET_LOW_IRQ BIT(0)
178
179/* smbb_buck_interrupts */
180#define VDD_LOOP_IRQ BIT(6)
181#define IBAT_LOOP_IRQ BIT(5)
182#define ICHG_LOOP_IRQ BIT(4)
183#define VCHG_LOOP_IRQ BIT(3)
184#define OVERTEMP_IRQ BIT(2)
185#define VREF_OV_IRQ BIT(1)
186#define VBAT_OV_IRQ BIT(0)
187
188/* smbb_bat_if_interrupts */
189#define PSI_IRQ BIT(4)
190#define VCP_ON_IRQ BIT(3)
191#define BAT_FET_ON_IRQ BIT(2)
192#define BAT_TEMP_OK_IRQ BIT(1)
193#define BATT_PRES_IRQ BIT(0)
194
195/* smbb_usb_interrupts */
196#define CHG_GONE_IRQ BIT(2)
197#define USBIN_VALID_IRQ BIT(1)
198#define COARSE_DET_USB_IRQ BIT(0)
199
200/* smbb_dc_interrupts */
201#define DCIN_VALID_IRQ BIT(1)
202#define COARSE_DET_DC_IRQ BIT(0)
203
204/* smbb_boost_interrupts */
205#define LIMIT_ERROR_IRQ BIT(1)
206#define BOOST_PWR_OK_IRQ BIT(0)
207
208/* smbb_misc_interrupts */
209#define TFTWDOG_IRQ BIT(0)
210
David Keitelfe51cb92013-04-02 19:42:58 -0700211/* SMBB types */
212#define SMBB BIT(1)
213#define SMBBP BIT(2)
214#define SMBCL BIT(3)
215
David Keiteld681cda2012-10-02 15:44:21 -0700216/* Workaround flags */
217#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700218#define BOOST_FLASH_WA BIT(1)
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700219#define POWER_STAGE_WA BIT(2)
David Keiteld681cda2012-10-02 15:44:21 -0700220
David Keitel47185a62013-05-15 18:54:10 -0700221struct qpnp_chg_irq {
David Keitel9879e2a2013-06-28 18:40:22 -0700222 int irq;
David Keitel47185a62013-05-15 18:54:10 -0700223 unsigned long disabled;
David Keitelbf6a1062014-01-23 10:57:36 -0800224 unsigned long wake_enable;
David Keitel47185a62013-05-15 18:54:10 -0700225};
226
David Keitel6dc4ed42013-05-17 11:08:58 -0700227struct qpnp_chg_regulator {
228 struct regulator_desc rdesc;
229 struct regulator_dev *rdev;
230};
231
David Keitel80668952012-07-27 14:25:49 -0700232/**
233 * struct qpnp_chg_chip - device information
234 * @dev: device pointer to access the parent
235 * @spmi: spmi pointer to access spmi information
236 * @chgr_base: charger peripheral base address
237 * @buck_base: buck peripheral base address
238 * @bat_if_base: battery interface peripheral base address
239 * @usb_chgpth_base: USB charge path peripheral base address
240 * @dc_chgpth_base: DC charge path peripheral base address
241 * @boost_base: boost peripheral base address
242 * @misc_base: misc peripheral base address
243 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800244 * @bat_is_cool: indicates that battery is cool
245 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700246 * @chg_done: indicates that charging is completed
247 * @usb_present: present status of usb
248 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800249 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800250 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700251 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700252 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800253 * @min_voltage_mv: min battery voltage before turning the FET on
Prasad Sodagudic3678012013-09-23 12:01:19 +0530254 * @batt_weak_voltage_mv: Weak battery voltage threshold
David Keitelbdbae452014-01-14 17:19:50 -0800255 * @vbatdet_max_err_mv resume voltage hysterisis
David Keitel454ee842013-03-08 16:19:11 -0800256 * @max_bat_chg_current: maximum battery charge current in mA
257 * @warm_bat_chg_ma: warm battery maximum charge current in mA
258 * @cool_bat_chg_ma: cool battery maximum charge current in mA
259 * @warm_bat_mv: warm temperature battery target voltage
260 * @cool_bat_mv: cool temperature battery target voltage
261 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700262 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800263 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800264 * @maxinput_usb_ma: Maximum Input current USB
265 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700266 * @hot_batt_p Hot battery threshold setting
267 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700268 * @warm_bat_decidegc Warm battery temperature in degree Celsius
269 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700270 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700271 * @type: SMBB type
272 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800273 * @thermal_levels amount of thermal mitigation levels
274 * @thermal_mitigation thermal mitigation level values
275 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700276 * @dc_psy power supply to export information to userspace
277 * @usb_psy power supply to export information to userspace
278 * @bms_psy power supply to export information to userspace
279 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700280 * @flags: flags to activate specific workarounds
281 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700282 *
283 */
284struct qpnp_chg_chip {
285 struct device *dev;
286 struct spmi_device *spmi;
287 u16 chgr_base;
288 u16 buck_base;
289 u16 bat_if_base;
290 u16 usb_chgpth_base;
291 u16 dc_chgpth_base;
292 u16 boost_base;
293 u16 misc_base;
294 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700295 struct qpnp_chg_irq usbin_valid;
David Keitel0b62bdd2013-07-10 17:30:51 -0700296 struct qpnp_chg_irq usb_ocp;
David Keitel47185a62013-05-15 18:54:10 -0700297 struct qpnp_chg_irq dcin_valid;
298 struct qpnp_chg_irq chg_gone;
299 struct qpnp_chg_irq chg_fastchg;
300 struct qpnp_chg_irq chg_trklchg;
301 struct qpnp_chg_irq chg_failed;
302 struct qpnp_chg_irq chg_vbatdet_lo;
303 struct qpnp_chg_irq batt_pres;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700304 struct qpnp_chg_irq batt_temp_ok;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800305 struct qpnp_chg_irq coarse_det_usb;
David Keitel454ee842013-03-08 16:19:11 -0800306 bool bat_is_cool;
307 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700308 bool chg_done;
David Keitel7ac385e2013-08-19 18:02:40 -0700309 bool charger_monitor_checked;
David Keitel80668952012-07-27 14:25:49 -0700310 bool usb_present;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800311 u8 usbin_health;
312 bool usb_coarse_det;
David Keitel80668952012-07-27 14:25:49 -0700313 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800314 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700315 bool charging_disabled;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800316 bool ovp_monitor_enable;
317 bool usb_valid_check_ovp;
David Keitel89c17752013-06-28 14:52:48 -0700318 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800319 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700320 bool duty_cycle_100p;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700321 bool ibat_calibration_enabled;
322 bool aicl_settled;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800323 bool use_external_rsense;
Wu Fenglin64fb1ac2013-11-08 10:20:14 +0800324 bool fastchg_on;
David Keitel975b5352014-01-27 14:28:04 -0800325 bool parallel_ovp_mode;
David Keitel796882d2013-05-14 18:01:11 -0700326 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700327 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800328 unsigned int warm_bat_chg_ma;
329 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700330 unsigned int safe_voltage_mv;
331 unsigned int max_voltage_mv;
332 unsigned int min_voltage_mv;
Prasad Sodagudic3678012013-09-23 12:01:19 +0530333 unsigned int batt_weak_voltage_mv;
David Keitelbdbae452014-01-14 17:19:50 -0800334 unsigned int vbatdet_max_err_mv;
David Keitelfd305ee2013-07-19 20:19:06 -0700335 int prev_usb_max_ma;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700336 int set_vddmax_mv;
337 int delta_vddmax_mv;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700338 u8 trim_center;
David Keitel454ee842013-03-08 16:19:11 -0800339 unsigned int warm_bat_mv;
340 unsigned int cool_bat_mv;
341 unsigned int resume_delta_mv;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700342 int insertion_ocv_uv;
David Keitel9fd07382013-05-02 15:37:44 -0700343 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700344 int soc_resume_limit;
345 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800346 unsigned int maxinput_usb_ma;
347 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700348 unsigned int hot_batt_p;
349 unsigned int cold_batt_p;
David Keitel27a97e62013-06-24 13:57:12 -0700350 int warm_bat_decidegc;
351 int cool_bat_decidegc;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -0800352 int fake_battery_soc;
David Keitel5d44fa52012-12-03 16:37:31 -0800353 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700354 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700355 unsigned int type;
356 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800357 unsigned int thermal_levels;
358 unsigned int therm_lvl_sel;
359 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700360 struct power_supply dc_psy;
361 struct power_supply *usb_psy;
362 struct power_supply *bms_psy;
363 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700364 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800365 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700366 struct work_struct adc_measure_work;
David Keitelecab15a2013-08-06 15:41:39 -0700367 struct work_struct adc_disable_work;
David Keitel344c6972013-04-09 19:28:21 -0700368 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700369 struct delayed_work eoc_work;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800370 struct delayed_work usbin_health_check;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -0700371 struct work_struct soc_check_work;
David Keitel7ac385e2013-08-19 18:02:40 -0700372 struct delayed_work aicl_check_work;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700373 struct work_struct insertion_ocv_work;
David Keitel8b9bd312014-01-15 14:44:00 -0800374 struct work_struct ocp_clear_work;
David Keitel6dc4ed42013-05-17 11:08:58 -0700375 struct qpnp_chg_regulator otg_vreg;
376 struct qpnp_chg_regulator boost_vreg;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -0700377 struct qpnp_chg_regulator batfet_vreg;
David Keitel6e63bd52013-09-06 18:00:03 -0700378 bool batfet_ext_en;
379 struct work_struct batfet_lcl_work;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700380 struct qpnp_vadc_chip *vadc_dev;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800381 struct qpnp_iadc_chip *iadc_dev;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -0700382 struct qpnp_adc_tm_chip *adc_tm_dev;
David Keitelec3c09802013-06-13 13:05:30 -0700383 struct mutex jeita_configure_lock;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800384 spinlock_t usbin_health_monitor_lock;
David Keitel6e63bd52013-09-06 18:00:03 -0700385 struct mutex batfet_vreg_lock;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700386 struct alarm reduce_power_stage_alarm;
387 struct work_struct reduce_power_stage_work;
388 bool power_stage_workaround_running;
Zhenhua Huangdc335512013-10-30 11:45:15 +0800389 bool power_stage_workaround_enable;
David Keitel80668952012-07-27 14:25:49 -0700390};
391
David Keitel59fbb762014-02-05 16:46:24 -0800392static void
393qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip);
David Keitel47185a62013-05-15 18:54:10 -0700394
David Keitel80668952012-07-27 14:25:49 -0700395static struct of_device_id qpnp_charger_match_table[] = {
396 { .compatible = QPNP_CHARGER_DEV_NAME, },
397 {}
398};
399
David Keitel0ef282b2013-05-29 16:04:57 -0700400enum bpd_type {
401 BPD_TYPE_BAT_ID,
402 BPD_TYPE_BAT_THM,
403 BPD_TYPE_BAT_THM_BAT_ID,
404};
David Keitel796882d2013-05-14 18:01:11 -0700405
David Keitel0ef282b2013-05-29 16:04:57 -0700406static const char * const bpd_label[] = {
407 [BPD_TYPE_BAT_ID] = "bpd_id",
408 [BPD_TYPE_BAT_THM] = "bpd_thm",
409 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700410};
411
David Keitel89c17752013-06-28 14:52:48 -0700412enum btc_type {
413 HOT_THD_25_PCT = 25,
414 HOT_THD_35_PCT = 35,
415 COLD_THD_70_PCT = 70,
416 COLD_THD_80_PCT = 80,
417};
418
419static u8 btc_value[] = {
420 [HOT_THD_25_PCT] = 0x0,
421 [HOT_THD_35_PCT] = BIT(0),
422 [COLD_THD_70_PCT] = 0x0,
423 [COLD_THD_80_PCT] = BIT(1),
424};
425
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800426enum usbin_health {
427 USBIN_UNKNOW,
428 USBIN_OK,
429 USBIN_OVP,
430};
431
432static inline int
David Keitel796882d2013-05-14 18:01:11 -0700433get_bpd(const char *name)
434{
435 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700436 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
437 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700438 return i;
439 }
440 return -EINVAL;
441}
442
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700443static bool
444is_within_range(int value, int left, int right)
445{
446 if (left >= right && left >= value && value >= right)
447 return 1;
448 if (left <= right && left <= value && value <= right)
449 return 1;
450 return 0;
451}
452
David Keitel80668952012-07-27 14:25:49 -0700453static int
454qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
455 u16 base, int count)
456{
David Keitel39093572013-06-05 15:32:30 -0700457 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700458 struct spmi_device *spmi = chip->spmi;
459
David Keitel39093572013-06-05 15:32:30 -0700460 if (base == 0) {
461 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
462 base, spmi->sid, rc);
463 return -EINVAL;
464 }
465
466 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700467 if (rc) {
468 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
469 spmi->sid, rc);
470 return rc;
471 }
472 return 0;
473}
474
475static int
476qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
477 u16 base, int count)
478{
David Keitel39093572013-06-05 15:32:30 -0700479 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700480 struct spmi_device *spmi = chip->spmi;
481
David Keitel39093572013-06-05 15:32:30 -0700482 if (base == 0) {
483 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
484 base, spmi->sid, rc);
485 return -EINVAL;
486 }
487
488 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700489 if (rc) {
490 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
491 base, spmi->sid, rc);
492 return rc;
493 }
494
495 return 0;
496}
497
498static int
499qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
500 u8 mask, u8 val, int count)
501{
502 int rc;
503 u8 reg;
504
505 rc = qpnp_chg_read(chip, &reg, base, count);
506 if (rc) {
507 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
508 return rc;
509 }
510 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
511
512 reg &= ~mask;
513 reg |= val & mask;
514
515 pr_debug("Writing 0x%x\n", reg);
516
517 rc = qpnp_chg_write(chip, &reg, base, count);
518 if (rc) {
519 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
520 return rc;
521 }
522
523 return 0;
524}
525
David Keitel47185a62013-05-15 18:54:10 -0700526static void
527qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
528{
529 if (__test_and_clear_bit(0, &irq->disabled)) {
530 pr_debug("number = %d\n", irq->irq);
531 enable_irq(irq->irq);
532 }
533}
534
535static void
536qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
537{
538 if (!__test_and_set_bit(0, &irq->disabled)) {
539 pr_debug("number = %d\n", irq->irq);
540 disable_irq_nosync(irq->irq);
541 }
542}
543
David Keitelbf6a1062014-01-23 10:57:36 -0800544static void
545qpnp_chg_irq_wake_enable(struct qpnp_chg_irq *irq)
546{
547 if (!__test_and_set_bit(0, &irq->wake_enable)) {
548 pr_debug("number = %d\n", irq->irq);
549 enable_irq_wake(irq->irq);
550 }
551}
552
553static void
554qpnp_chg_irq_wake_disable(struct qpnp_chg_irq *irq)
555{
556 if (__test_and_clear_bit(0, &irq->wake_enable)) {
557 pr_debug("number = %d\n", irq->irq);
558 disable_irq_wake(irq->irq);
559 }
560}
561
David Keitel6f865cd2012-11-30 15:04:32 -0800562#define USB_OTG_EN_BIT BIT(0)
563static int
564qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
565{
566 u8 usb_otg_en;
567 int rc;
568
569 rc = qpnp_chg_read(chip, &usb_otg_en,
570 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
571 1);
572
573 if (rc) {
574 pr_err("spmi read failed: addr=%03X, rc=%d\n",
575 chip->usb_chgpth_base + CHGR_STATUS, rc);
576 return rc;
577 }
578 pr_debug("usb otg en 0x%x\n", usb_otg_en);
579
580 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
581}
582
David Keitel42ae0aa2013-03-08 16:20:10 -0800583static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700584qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
585{
586 u8 boost_en_ctl;
587 int rc;
588
589 rc = qpnp_chg_read(chip, &boost_en_ctl,
590 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
591 if (rc) {
592 pr_err("spmi read failed: addr=%03X, rc=%d\n",
593 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
594 return rc;
595 }
596
597 pr_debug("boost en 0x%x\n", boost_en_ctl);
598
599 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
600}
601
602static int
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700603qpnp_chg_is_batt_temp_ok(struct qpnp_chg_chip *chip)
604{
605 u8 batt_rt_sts;
606 int rc;
607
608 rc = qpnp_chg_read(chip, &batt_rt_sts,
609 INT_RT_STS(chip->bat_if_base), 1);
610 if (rc) {
611 pr_err("spmi read failed: addr=%03X, rc=%d\n",
612 INT_RT_STS(chip->bat_if_base), rc);
613 return rc;
614 }
615
616 return (batt_rt_sts & BAT_TEMP_OK_IRQ) ? 1 : 0;
617}
618
619static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800620qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
621{
622 u8 batt_pres_rt_sts;
623 int rc;
624
625 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
626 INT_RT_STS(chip->bat_if_base), 1);
627 if (rc) {
628 pr_err("spmi read failed: addr=%03X, rc=%d\n",
629 INT_RT_STS(chip->bat_if_base), rc);
630 return rc;
631 }
632
633 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
634}
635
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700636static int
637qpnp_chg_is_batfet_closed(struct qpnp_chg_chip *chip)
638{
639 u8 batfet_closed_rt_sts;
640 int rc;
641
642 rc = qpnp_chg_read(chip, &batfet_closed_rt_sts,
643 INT_RT_STS(chip->bat_if_base), 1);
644 if (rc) {
645 pr_err("spmi read failed: addr=%03X, rc=%d\n",
646 INT_RT_STS(chip->bat_if_base), rc);
647 return rc;
648 }
649
650 return (batfet_closed_rt_sts & BAT_FET_ON_IRQ) ? 1 : 0;
651}
652
David Keitel80668952012-07-27 14:25:49 -0700653static int
654qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
655{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800656 u8 usb_chgpth_rt_sts;
David Keitel80668952012-07-27 14:25:49 -0700657 int rc;
658
Zhenhua Huangf1163872014-03-03 10:51:25 +0800659 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
660 INT_RT_STS(chip->usb_chgpth_base), 1);
David Keitel80668952012-07-27 14:25:49 -0700661
662 if (rc) {
663 pr_err("spmi read failed: addr=%03X, rc=%d\n",
Zhenhua Huangf1163872014-03-03 10:51:25 +0800664 INT_RT_STS(chip->usb_chgpth_base), rc);
David Keitel80668952012-07-27 14:25:49 -0700665 return rc;
666 }
Zhenhua Huangf1163872014-03-03 10:51:25 +0800667 pr_debug("chgr usb sts 0x%x\n", usb_chgpth_rt_sts);
David Keitel80668952012-07-27 14:25:49 -0700668
Zhenhua Huangf1163872014-03-03 10:51:25 +0800669 return (usb_chgpth_rt_sts & USBIN_VALID_IRQ) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700670}
671
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700672static bool
673qpnp_chg_is_ibat_loop_active(struct qpnp_chg_chip *chip)
674{
675 int rc;
676 u8 buck_sts;
677
678 rc = qpnp_chg_read(chip, &buck_sts,
679 INT_RT_STS(chip->buck_base), 1);
680 if (rc) {
681 pr_err("failed to read buck RT status rc=%d\n", rc);
682 return 0;
683 }
684
685 return !!(buck_sts & IBAT_LOOP_IRQ);
686}
687
Zhenhua Huangf1163872014-03-03 10:51:25 +0800688#define USB_VALID_MASK 0xC0
689#define USB_VALID_IN_MASK BIT(7)
690#define USB_COARSE_DET 0x10
691#define USB_VALID_OVP_VALUE 0x40
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800692static int
693qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
694{
695 u8 usbin_chg_rt_sts;
696 int rc;
697 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
698 chip->usb_chgpth_base + CHGR_STATUS , 1);
699 if (rc) {
700 pr_err("spmi read failed: addr=%03X, rc=%d\n",
701 chip->usb_chgpth_base + CHGR_STATUS, rc);
702 return rc;
703 }
704 return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
705}
706
707static int
708qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
709{
Zhenhua Huangf1163872014-03-03 10:51:25 +0800710 u8 usbin_chg_rt_sts, usb_chgpth_rt_sts;
711 u8 usbin_health = 0;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800712 int rc;
713
714 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
715 chip->usb_chgpth_base + CHGR_STATUS , 1);
716
717 if (rc) {
718 pr_err("spmi read failed: addr=%03X, rc=%d\n",
719 chip->usb_chgpth_base + CHGR_STATUS, rc);
720 return rc;
721 }
722
Zhenhua Huangf1163872014-03-03 10:51:25 +0800723 rc = qpnp_chg_read(chip, &usb_chgpth_rt_sts,
724 INT_RT_STS(chip->usb_chgpth_base) , 1);
725
726 if (rc) {
727 pr_err("spmi read failed: addr=%03X, rc=%d\n",
728 INT_RT_STS(chip->usb_chgpth_base), rc);
729 return rc;
730 }
731
732 pr_debug("chgr usb sts 0x%x, chgpth rt sts 0x%x\n",
733 usbin_chg_rt_sts, usb_chgpth_rt_sts);
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800734 if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
735 if ((usbin_chg_rt_sts & USB_VALID_MASK)
736 == USB_VALID_OVP_VALUE) {
737 usbin_health = USBIN_OVP;
738 pr_err("Over voltage charger inserted\n");
Zhenhua Huangf1163872014-03-03 10:51:25 +0800739 } else if ((usb_chgpth_rt_sts & USBIN_VALID_IRQ) != 0) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800740 usbin_health = USBIN_OK;
741 pr_debug("Valid charger inserted\n");
742 }
743 } else {
744 usbin_health = USBIN_UNKNOW;
745 pr_debug("Charger plug out\n");
746 }
747
748 return usbin_health;
749}
750
David Keitel80668952012-07-27 14:25:49 -0700751static int
752qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
753{
754 u8 dcin_valid_rt_sts;
755 int rc;
756
David Keitelf2170cc2013-02-20 17:49:03 -0800757 if (!chip->dc_chgpth_base)
758 return 0;
759
David Keitel80668952012-07-27 14:25:49 -0700760 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
761 INT_RT_STS(chip->dc_chgpth_base), 1);
762 if (rc) {
763 pr_err("spmi read failed: addr=%03X, rc=%d\n",
764 INT_RT_STS(chip->dc_chgpth_base), rc);
765 return rc;
766 }
767
768 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
769}
770
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700771static int
772qpnp_chg_is_ichg_loop_active(struct qpnp_chg_chip *chip)
773{
774 u8 buck_sts;
775 int rc;
776
777 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
778
779 if (rc) {
780 pr_err("spmi read failed: addr=%03X, rc=%d\n",
781 INT_RT_STS(chip->buck_base), rc);
782 return rc;
783 }
784 pr_debug("buck usb sts 0x%x\n", buck_sts);
785
786 return (buck_sts & ICHG_LOOP_IRQ) ? 1 : 0;
787}
788
David Keitel22ed2232013-01-28 11:04:07 -0800789#define QPNP_CHG_I_MAX_MIN_100 100
790#define QPNP_CHG_I_MAX_MIN_150 150
791#define QPNP_CHG_I_MAX_MIN_MA 200
792#define QPNP_CHG_I_MAX_MAX_MA 2500
793#define QPNP_CHG_I_MAXSTEP_MA 100
794static int
795qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
796{
797 int rc = 0;
798 u8 dc = 0;
799
800 if (mA < QPNP_CHG_I_MAX_MIN_100
801 || mA > QPNP_CHG_I_MAX_MAX_MA) {
802 pr_err("bad mA=%d asked to set\n", mA);
803 return -EINVAL;
804 }
805
806 if (mA == QPNP_CHG_I_MAX_MIN_100) {
807 dc = 0x00;
808 pr_debug("current=%d setting %02x\n", mA, dc);
809 return qpnp_chg_write(chip, &dc,
810 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
811 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
812 dc = 0x01;
813 pr_debug("current=%d setting %02x\n", mA, dc);
814 return qpnp_chg_write(chip, &dc,
815 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
816 }
817
818 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
819
820 pr_debug("current=%d setting 0x%x\n", mA, dc);
821 rc = qpnp_chg_write(chip, &dc,
822 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
823
824 return rc;
825}
826
David Keitel80668952012-07-27 14:25:49 -0700827static int
David Keitel2586f0a2013-08-20 10:02:26 -0700828qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
829{
830 int rc = 0;
831 u8 trim_reg;
832
833 rc = qpnp_chg_read(chip, &trim_reg,
834 chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
835 if (rc) {
836 pr_err("failed to read USB_TRIM rc=%d\n", rc);
837 return 0;
838 }
839
840 return trim_reg;
841}
842
843static int
844qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
845{
846 int rc = 0;
847
848 rc = qpnp_chg_masked_write(chip,
849 chip->usb_chgpth_base + SEC_ACCESS,
850 0xFF,
851 0xA5, 1);
852 if (rc) {
853 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
854 return rc;
855 }
856
857 rc = qpnp_chg_masked_write(chip,
858 chip->usb_chgpth_base + CHGR_USB_TRIM,
859 0xFF,
860 trim, 1);
861 if (rc) {
862 pr_err("failed to write USB TRIM rc=%d\n", rc);
863 return rc;
864 }
865
866 return rc;
867}
868
869static int
David Keitel80668952012-07-27 14:25:49 -0700870qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
871{
David Keiteld681cda2012-10-02 15:44:21 -0700872 int rc = 0;
873 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700874
David Keitel7b0568482013-12-02 14:47:42 -0800875 if (mA < 0 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700876 pr_err("bad mA=%d asked to set\n", mA);
877 return -EINVAL;
878 }
879
David Keitel7b0568482013-12-02 14:47:42 -0800880 if (mA <= QPNP_CHG_I_MAX_MIN_100) {
David Keitel22ed2232013-01-28 11:04:07 -0800881 usb_reg = 0x00;
882 pr_debug("current=%d setting %02x\n", mA, usb_reg);
883 return qpnp_chg_write(chip, &usb_reg,
884 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
885 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
886 usb_reg = 0x01;
887 pr_debug("current=%d setting %02x\n", mA, usb_reg);
888 return qpnp_chg_write(chip, &usb_reg,
889 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
890 }
891
892 /* Impose input current limit */
893 if (chip->maxinput_usb_ma)
894 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
895
896 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -0700897
David Keiteld681cda2012-10-02 15:44:21 -0700898 if (chip->flags & CHG_FLAGS_VCP_WA) {
899 temp = 0xA5;
900 rc = qpnp_chg_write(chip, &temp,
901 chip->buck_base + SEC_ACCESS, 1);
902 rc = qpnp_chg_masked_write(chip,
903 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
904 0x0C, 0x0C, 1);
905 }
906
David Keitel80668952012-07-27 14:25:49 -0700907 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -0700908 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -0800909 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -0700910
911 if (chip->flags & CHG_FLAGS_VCP_WA) {
912 temp = 0xA5;
913 udelay(200);
914 rc = qpnp_chg_write(chip, &temp,
915 chip->buck_base + SEC_ACCESS, 1);
916 rc = qpnp_chg_masked_write(chip,
917 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
918 0x0C, 0x00, 1);
919 }
920
921 return rc;
922}
923
David Keitel25544a22013-12-06 17:59:24 -0800924#define QPNP_CHG_VINMIN_MIN_MV 4000
David Keitel337bd862013-07-15 21:42:58 -0700925#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
926#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
927#define QPNP_CHG_VINMIN_MAX_MV 9600
928#define QPNP_CHG_VINMIN_STEP_MV 50
929#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
Prasad Sodagudi95624b62013-09-26 16:40:59 +0530930#define QPNP_CHG_VINMIN_MASK 0x3F
David Keitel25544a22013-12-06 17:59:24 -0800931#define QPNP_CHG_VINMIN_MIN_VAL 0x0C
David Keitel337bd862013-07-15 21:42:58 -0700932static int
933qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
934{
935 u8 temp;
936
David Keitel25544a22013-12-06 17:59:24 -0800937 if ((voltage < QPNP_CHG_VINMIN_MIN_MV)
938 || (voltage > QPNP_CHG_VINMIN_MAX_MV)) {
David Keitel337bd862013-07-15 21:42:58 -0700939 pr_err("bad mV=%d asked to set\n", voltage);
940 return -EINVAL;
941 }
942 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
943 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
David Keitel289fcf82013-10-24 11:33:00 -0700944 temp += (voltage - QPNP_CHG_VINMIN_HIGH_MIN_MV)
David Keitel337bd862013-07-15 21:42:58 -0700945 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
946 } else {
947 temp = QPNP_CHG_VINMIN_MIN_VAL;
948 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
949 / QPNP_CHG_VINMIN_STEP_MV;
950 }
951
952 pr_debug("voltage=%d setting %02x\n", voltage, temp);
953 return qpnp_chg_masked_write(chip,
954 chip->chgr_base + CHGR_VIN_MIN,
955 QPNP_CHG_VINMIN_MASK, temp, 1);
956}
957
958static int
959qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
960{
961 int rc, vin_min_mv;
962 u8 vin_min;
963
964 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
965 if (rc) {
966 pr_err("failed to read VIN_MIN rc=%d\n", rc);
967 return 0;
968 }
969
970 if (vin_min == 0)
971 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
David Keitel289fcf82013-10-24 11:33:00 -0700972 else if (vin_min >= QPNP_CHG_VINMIN_HIGH_MIN_VAL)
David Keitel337bd862013-07-15 21:42:58 -0700973 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
974 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
975 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
976 else
977 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
978 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
979 * QPNP_CHG_VINMIN_STEP_MV;
980 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
981
982 return vin_min_mv;
983}
984
Prasad Sodagudic3678012013-09-23 12:01:19 +0530985#define QPNP_CHG_VBATWEAK_MIN_MV 2100
986#define QPNP_CHG_VBATWEAK_MAX_MV 3600
987#define QPNP_CHG_VBATWEAK_STEP_MV 100
988static int
989qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
990{
991 u8 temp;
992
993 if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
994 || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
995 return -EINVAL;
996
997 temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
998 / QPNP_CHG_VBATWEAK_STEP_MV;
999
1000 pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
1001 return qpnp_chg_write(chip, &temp,
1002 chip->chgr_base + CHGR_VBAT_WEAK, 1);
1003}
1004
David Keitel337bd862013-07-15 21:42:58 -07001005static int
1006qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
1007{
1008 int rc, iusbmax_ma;
1009 u8 iusbmax;
1010
1011 rc = qpnp_chg_read(chip, &iusbmax,
1012 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1013 if (rc) {
1014 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
1015 return 0;
1016 }
1017
1018 if (iusbmax == 0)
1019 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
1020 else if (iusbmax == 0x01)
1021 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
1022 else
1023 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
1024
1025 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
1026
1027 return iusbmax_ma;
1028}
1029
David Keitel975b5352014-01-27 14:28:04 -08001030#define ILIMIT_OVR_0 0x02
1031static int
1032override_dcin_ilimit(struct qpnp_chg_chip *chip, bool override)
1033{
1034 int rc;
1035
1036 pr_debug("override %d\n", override);
1037 rc = qpnp_chg_masked_write(chip,
1038 chip->dc_chgpth_base + SEC_ACCESS,
1039 0xA5,
1040 0xA5, 1);
1041 rc |= qpnp_chg_masked_write(chip,
1042 chip->dc_chgpth_base + DC_COMP_OVR1,
1043 0xFF,
1044 override ? ILIMIT_OVR_0 : 0, 1);
1045 if (rc) {
1046 pr_err("Failed to override dc ilimit rc = %d\n", rc);
1047 return rc;
1048 }
1049
1050 return rc;
1051}
1052
1053#define DUAL_PATH_EN BIT(7)
1054static int
1055switch_parallel_ovp_mode(struct qpnp_chg_chip *chip, bool enable)
1056{
1057 int rc = 0;
1058
1059 if (!chip->usb_chgpth_base || !chip->dc_chgpth_base)
1060 return rc;
1061
1062 pr_debug("enable %d\n", enable);
1063 rc = override_dcin_ilimit(chip, 1);
1064 udelay(10);
1065
1066 /* enable/disable dual path mode */
1067 rc = qpnp_chg_masked_write(chip,
1068 chip->usb_chgpth_base + SEC_ACCESS,
1069 0xA5,
1070 0xA5, 1);
1071 rc |= qpnp_chg_masked_write(chip,
1072 chip->usb_chgpth_base + USB_SPARE,
1073 0xFF,
1074 enable ? DUAL_PATH_EN : 0, 1);
1075 if (rc) {
1076 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1077 return rc;
1078 }
1079
David Keitelbf2edba2014-03-05 10:49:32 -08001080 if (enable)
1081 rc = override_dcin_ilimit(chip, 0);
David Keitel975b5352014-01-27 14:28:04 -08001082 return rc;
1083}
1084
David Keiteld681cda2012-10-02 15:44:21 -07001085#define USB_SUSPEND_BIT BIT(0)
1086static int
1087qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
1088{
David Keitel975b5352014-01-27 14:28:04 -08001089 /* Turn off DC OVP FET when going into USB suspend */
1090 if (chip->parallel_ovp_mode && enable)
1091 switch_parallel_ovp_mode(chip, 0);
1092
David Keiteld681cda2012-10-02 15:44:21 -07001093 return qpnp_chg_masked_write(chip,
1094 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
1095 USB_SUSPEND_BIT,
1096 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -07001097}
1098
David Keitel344c6972013-04-09 19:28:21 -07001099static int
1100qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
1101{
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001102 if (chip->insertion_ocv_uv == 0 && enable) {
1103 pr_debug("Battery not present, skipping\n");
1104 return 0;
1105 }
1106 pr_debug("charging %s\n", enable ? "enabled" : "disabled");
David Keitel344c6972013-04-09 19:28:21 -07001107 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1108 CHGR_CHG_EN,
1109 enable ? CHGR_CHG_EN : 0, 1);
1110}
1111
1112static int
1113qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
1114{
1115 /* Don't run on battery for batteryless hardware */
1116 if (chip->use_default_batt_values)
1117 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -07001118 /* Don't force on battery if battery is not present */
1119 if (!qpnp_chg_is_batt_present(chip))
1120 return 0;
David Keitel344c6972013-04-09 19:28:21 -07001121
1122 /* This bit forces the charger to run off of the battery rather
1123 * than a connected charger */
1124 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1125 CHGR_ON_BAT_FORCE_BIT,
1126 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
1127}
1128
David Keitel8b68d2d2013-05-14 23:36:51 -07001129#define BUCK_DUTY_MASK_100P 0x30
1130static int
1131qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
1132{
1133 int rc;
1134
1135 pr_debug("enable: %d\n", enable);
1136
1137 rc = qpnp_chg_masked_write(chip,
1138 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1139 if (rc) {
1140 pr_debug("failed to write sec access rc=%d\n", rc);
1141 return rc;
1142 }
1143
1144 rc = qpnp_chg_masked_write(chip,
1145 chip->buck_base + BUCK_TEST_SMBC_MODES,
1146 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
1147 if (rc) {
1148 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
1149 return rc;
1150 }
1151
1152 return rc;
1153}
1154
David Keitel9fd07382013-05-02 15:37:44 -07001155#define COMPATATOR_OVERRIDE_0 0x80
1156static int
1157qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
1158{
1159 int rc;
1160
1161 pr_debug("toggle: %d\n", enable);
1162
1163 rc = qpnp_chg_masked_write(chip,
1164 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1165 if (rc) {
1166 pr_debug("failed to write sec access rc=%d\n", rc);
1167 return rc;
1168 }
1169
1170 rc = qpnp_chg_masked_write(chip,
1171 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
1172 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
1173 if (rc) {
1174 pr_debug("failed to toggle chg done override rc=%d\n", rc);
1175 return rc;
1176 }
1177
1178 return rc;
1179}
1180
1181#define QPNP_CHG_VBATDET_MIN_MV 3240
1182#define QPNP_CHG_VBATDET_MAX_MV 5780
1183#define QPNP_CHG_VBATDET_STEP_MV 20
1184static int
1185qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
1186{
1187 u8 temp;
1188
1189 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
1190 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
1191 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
1192 return -EINVAL;
1193 }
1194 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
1195 / QPNP_CHG_VBATDET_STEP_MV;
1196
1197 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
1198 return qpnp_chg_write(chip, &temp,
1199 chip->chgr_base + CHGR_VBAT_DET, 1);
1200}
1201
David Keitel344c6972013-04-09 19:28:21 -07001202static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001203qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
1204{
1205 if (chip->bat_is_cool)
1206 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
1207 - chip->resume_delta_mv);
1208 else if (chip->bat_is_warm)
1209 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
1210 - chip->resume_delta_mv);
1211 else if (chip->resuming_charging)
1212 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1213 + chip->resume_delta_mv);
1214 else
1215 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1216 - chip->resume_delta_mv);
1217}
1218
1219static void
David Keitel344c6972013-04-09 19:28:21 -07001220qpnp_arb_stop_work(struct work_struct *work)
1221{
1222 struct delayed_work *dwork = to_delayed_work(work);
1223 struct qpnp_chg_chip *chip = container_of(dwork,
1224 struct qpnp_chg_chip, arb_stop_work);
1225
David Keitel9fd07382013-05-02 15:37:44 -07001226 if (!chip->chg_done)
1227 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -07001228 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1229}
1230
1231static void
1232qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -07001233{
1234 struct qpnp_chg_chip *chip = container_of(work,
1235 struct qpnp_chg_chip, adc_measure_work);
1236
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07001237 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -07001238 pr_err("request ADC error\n");
1239}
1240
David Keitelecab15a2013-08-06 15:41:39 -07001241static void
1242qpnp_bat_if_adc_disable_work(struct work_struct *work)
1243{
1244 struct qpnp_chg_chip *chip = container_of(work,
1245 struct qpnp_chg_chip, adc_disable_work);
1246
1247 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev, &chip->adc_param);
1248}
1249
David Keitel9fd07382013-05-02 15:37:44 -07001250#define EOC_CHECK_PERIOD_MS 10000
1251static irqreturn_t
1252qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
1253{
1254 struct qpnp_chg_chip *chip = _chip;
1255 u8 chg_sts = 0;
1256 int rc;
1257
1258 pr_debug("vbatdet-lo triggered\n");
1259
1260 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
1261 if (rc)
1262 pr_err("failed to read chg_sts rc=%d\n", rc);
1263
1264 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
1265 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
1266 schedule_delayed_work(&chip->eoc_work,
1267 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001268 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07001269 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001270 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07001271
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001272 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001273 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001274 if (chip->dc_chgpth_base) {
1275 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001276 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001277 }
1278 if (chip->bat_if_base) {
1279 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001280 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001281 }
David Keitel9fd07382013-05-02 15:37:44 -07001282 return IRQ_HANDLED;
1283}
1284
David Keitel344c6972013-04-09 19:28:21 -07001285#define ARB_STOP_WORK_MS 1000
1286static irqreturn_t
1287qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
1288{
1289 struct qpnp_chg_chip *chip = _chip;
David Keitel7e38f512013-11-19 11:15:11 -08001290 u8 usb_sts;
1291 int rc;
1292
1293 rc = qpnp_chg_read(chip, &usb_sts,
1294 INT_RT_STS(chip->usb_chgpth_base), 1);
1295 if (rc)
1296 pr_err("failed to read usb_chgpth_sts rc=%d\n", rc);
David Keitel344c6972013-04-09 19:28:21 -07001297
1298 pr_debug("chg_gone triggered\n");
David Keiteld53183a2014-01-07 17:17:44 -08001299 if ((qpnp_chg_is_usb_chg_plugged_in(chip)
1300 || qpnp_chg_is_dc_chg_plugged_in(chip))
1301 && (usb_sts & CHG_GONE_IRQ)) {
David Keitel344c6972013-04-09 19:28:21 -07001302 qpnp_chg_charge_en(chip, 0);
David Keitel9fd07382013-05-02 15:37:44 -07001303 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001304 schedule_delayed_work(&chip->arb_stop_work,
1305 msecs_to_jiffies(ARB_STOP_WORK_MS));
1306 }
1307
1308 return IRQ_HANDLED;
1309}
1310
David Keitel0b62bdd2013-07-10 17:30:51 -07001311static irqreturn_t
1312qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
1313{
1314 struct qpnp_chg_chip *chip = _chip;
David Keitel0b62bdd2013-07-10 17:30:51 -07001315
1316 pr_debug("usb-ocp triggered\n");
1317
David Keitel8b9bd312014-01-15 14:44:00 -08001318 schedule_work(&chip->ocp_clear_work);
1319
1320 return IRQ_HANDLED;
1321}
1322
1323#define BOOST_ILIMIT_MIN 0x07
1324#define BOOST_ILIMIT_DEF 0x02
1325#define BOOST_ILIMT_MASK 0xFF
1326static void
1327qpnp_chg_ocp_clear_work(struct work_struct *work)
1328{
1329 int rc;
1330 u8 usb_sts;
1331 struct qpnp_chg_chip *chip = container_of(work,
1332 struct qpnp_chg_chip, ocp_clear_work);
1333
1334 if (chip->type == SMBBP) {
1335 rc = qpnp_chg_masked_write(chip,
1336 chip->boost_base + BOOST_ILIM,
1337 BOOST_ILIMT_MASK,
1338 BOOST_ILIMIT_MIN, 1);
1339 if (rc) {
1340 pr_err("Failed to turn configure ilim rc = %d\n", rc);
1341 return;
1342 }
1343 }
1344
David Keitel0b62bdd2013-07-10 17:30:51 -07001345 rc = qpnp_chg_masked_write(chip,
1346 chip->usb_chgpth_base + USB_OCP_CLR,
1347 OCP_CLR_BIT,
1348 OCP_CLR_BIT, 1);
1349 if (rc)
1350 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1351
1352 /* force usb ovp fet off */
1353 rc = qpnp_chg_masked_write(chip,
1354 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1355 USB_OTG_EN_BIT,
1356 USB_OTG_EN_BIT, 1);
1357 if (rc)
1358 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1359
David Keitel8b9bd312014-01-15 14:44:00 -08001360 if (chip->type == SMBBP) {
1361 /* Wait for OCP circuitry to be powered up */
1362 msleep(100);
1363 rc = qpnp_chg_read(chip, &usb_sts,
1364 INT_RT_STS(chip->usb_chgpth_base), 1);
1365 if (rc) {
1366 pr_err("failed to read interrupt sts %d\n", rc);
1367 return;
1368 }
1369
1370 if (usb_sts & COARSE_DET_USB_IRQ) {
1371 rc = qpnp_chg_masked_write(chip,
1372 chip->boost_base + BOOST_ILIM,
1373 BOOST_ILIMT_MASK,
1374 BOOST_ILIMIT_DEF, 1);
1375 if (rc) {
1376 pr_err("Failed to set ilim rc = %d\n", rc);
1377 return;
1378 }
1379 } else {
1380 pr_warn_ratelimited("USB short to GND detected!\n");
1381 }
1382 }
David Keitel0b62bdd2013-07-10 17:30:51 -07001383}
1384
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001385#define QPNP_CHG_VDDMAX_MIN 3400
1386#define QPNP_CHG_V_MIN_MV 3240
1387#define QPNP_CHG_V_MAX_MV 4500
1388#define QPNP_CHG_V_STEP_MV 10
1389#define QPNP_CHG_BUCK_TRIM1_STEP 10
1390#define QPNP_CHG_BUCK_VDD_TRIM_MASK 0xF0
1391static int
1392qpnp_chg_vddmax_and_trim_set(struct qpnp_chg_chip *chip,
1393 int voltage, int trim_mv)
1394{
1395 int rc, trim_set;
1396 u8 vddmax = 0, trim = 0;
1397
1398 if (voltage < QPNP_CHG_VDDMAX_MIN
1399 || voltage > QPNP_CHG_V_MAX_MV) {
1400 pr_err("bad mV=%d asked to set\n", voltage);
1401 return -EINVAL;
1402 }
1403
1404 vddmax = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1405 rc = qpnp_chg_write(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1406 if (rc) {
1407 pr_err("Failed to write vddmax: %d\n", rc);
1408 return rc;
1409 }
1410
1411 rc = qpnp_chg_masked_write(chip,
1412 chip->buck_base + SEC_ACCESS,
1413 0xFF,
1414 0xA5, 1);
1415 if (rc) {
1416 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1417 return rc;
1418 }
1419 trim_set = clamp((int)chip->trim_center
1420 + (trim_mv / QPNP_CHG_BUCK_TRIM1_STEP),
1421 0, 0xF);
1422 trim = (u8)trim_set << 4;
1423 rc = qpnp_chg_masked_write(chip,
1424 chip->buck_base + BUCK_CTRL_TRIM1,
1425 QPNP_CHG_BUCK_VDD_TRIM_MASK,
1426 trim, 1);
1427 if (rc) {
1428 pr_err("Failed to write buck trim1: %d\n", rc);
1429 return rc;
1430 }
1431 pr_debug("voltage=%d+%d setting vddmax: %02x, trim: %02x\n",
1432 voltage, trim_mv, vddmax, trim);
1433 return 0;
1434}
1435
Xiaozhe Shie8504482013-10-30 18:10:31 -07001436static int
1437qpnp_chg_vddmax_get(struct qpnp_chg_chip *chip)
1438{
1439 int rc;
1440 u8 vddmax = 0;
1441
1442 rc = qpnp_chg_read(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1443 if (rc) {
1444 pr_err("Failed to write vddmax: %d\n", rc);
1445 return rc;
1446 }
1447
1448 return QPNP_CHG_V_MIN_MV + (int)vddmax * QPNP_CHG_V_STEP_MV;
1449}
1450
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001451/* JEITA compliance logic */
1452static void
1453qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1454{
1455 if (chip->bat_is_cool)
1456 qpnp_chg_vddmax_and_trim_set(chip, chip->cool_bat_mv,
1457 chip->delta_vddmax_mv);
1458 else if (chip->bat_is_warm)
1459 qpnp_chg_vddmax_and_trim_set(chip, chip->warm_bat_mv,
1460 chip->delta_vddmax_mv);
1461 else
1462 qpnp_chg_vddmax_and_trim_set(chip, chip->max_voltage_mv,
1463 chip->delta_vddmax_mv);
1464}
1465
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001466static void
1467qpnp_usbin_health_check_work(struct work_struct *work)
1468{
1469 int usbin_health = 0;
1470 u8 psy_health_sts = 0;
1471 struct delayed_work *dwork = to_delayed_work(work);
1472 struct qpnp_chg_chip *chip = container_of(dwork,
1473 struct qpnp_chg_chip, usbin_health_check);
1474
1475 usbin_health = qpnp_chg_check_usbin_health(chip);
1476 spin_lock(&chip->usbin_health_monitor_lock);
1477 if (chip->usbin_health != usbin_health) {
1478 pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
1479 chip->usbin_health, usbin_health);
1480 chip->usbin_health = usbin_health;
1481 if (usbin_health == USBIN_OVP)
1482 psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1483 else if (usbin_health == USBIN_OK)
1484 psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
1485 power_supply_set_health_state(chip->usb_psy, psy_health_sts);
1486 power_supply_changed(chip->usb_psy);
1487 }
1488 /* enable OVP monitor in usb valid after coarse-det complete */
1489 chip->usb_valid_check_ovp = true;
1490 spin_unlock(&chip->usbin_health_monitor_lock);
1491 return;
1492}
1493
1494#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
1495#define USB_DEB_BYPASS 0x0
1496#define USB_DEB_5MS 0x1
1497#define USB_DEB_10MS 0x2
1498#define USB_DEB_20MS 0x3
1499static irqreturn_t
1500qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
1501{
1502 struct qpnp_chg_chip *chip = _chip;
1503 int host_mode, rc = 0;
1504 int debounce[] = {
1505 [USB_DEB_BYPASS] = 0,
1506 [USB_DEB_5MS] = 5,
1507 [USB_DEB_10MS] = 10,
1508 [USB_DEB_20MS] = 20 };
1509 u8 ovp_ctl;
1510 bool usb_coarse_det;
1511
1512 host_mode = qpnp_chg_is_otg_en_set(chip);
1513 usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
1514 pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
1515 usb_coarse_det, host_mode);
1516
1517 if (host_mode)
1518 return IRQ_HANDLED;
1519 /* ignore to monitor OVP in usbin valid irq handler
1520 if the coarse-det fired first, do the OVP state monitor
1521 in the usbin_health_check work, and after the work,
1522 enable monitor OVP in usbin valid irq handler */
1523 chip->usb_valid_check_ovp = false;
1524 if (chip->usb_coarse_det ^ usb_coarse_det) {
1525 chip->usb_coarse_det = usb_coarse_det;
1526 if (usb_coarse_det) {
1527 /* usb coarse-det rising edge, check the usbin_valid
1528 debounce time setting, and start a delay work to
1529 check the OVP status*/
1530 rc = qpnp_chg_read(chip, &ovp_ctl,
1531 chip->usb_chgpth_base + USB_OVP_CTL, 1);
1532
1533 if (rc) {
1534 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1535 chip->usb_chgpth_base + USB_OVP_CTL,
1536 rc);
1537 return rc;
1538 }
1539 ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
1540 schedule_delayed_work(&chip->usbin_health_check,
1541 msecs_to_jiffies(debounce[ovp_ctl]));
1542 } else {
1543 /* usb coarse-det rising edge, set the usb psy health
1544 status to unknown */
1545 pr_debug("usb coarse det clear, set usb health to unknown\n");
1546 chip->usbin_health = USBIN_UNKNOW;
1547 power_supply_set_health_state(chip->usb_psy,
1548 POWER_SUPPLY_HEALTH_UNKNOWN);
1549 power_supply_changed(chip->usb_psy);
1550 }
1551
1552 }
1553 return IRQ_HANDLED;
1554}
1555
David Keitel6e63bd52013-09-06 18:00:03 -07001556#define BATFET_LPM_MASK 0xC0
1557#define BATFET_LPM 0x40
1558#define BATFET_NO_LPM 0x00
1559static int
1560qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
1561{
1562 int rc = 0;
1563
David Keitelcadbc282013-09-26 11:39:14 -07001564 if (chip->charging_disabled || !chip->bat_if_base)
1565 return rc;
1566
David Keitel6e63bd52013-09-06 18:00:03 -07001567 if (chip->type == SMBB)
1568 rc = qpnp_chg_masked_write(chip,
1569 chip->bat_if_base + CHGR_BAT_IF_SPARE,
1570 BATFET_LPM_MASK,
1571 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1572 else
1573 rc = qpnp_chg_masked_write(chip,
1574 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
1575 BATFET_LPM_MASK,
1576 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1577
1578 return rc;
1579}
1580
David Keitel80668952012-07-27 14:25:49 -07001581#define ENUM_T_STOP_BIT BIT(0)
1582static irqreturn_t
1583qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1584{
1585 struct qpnp_chg_chip *chip = _chip;
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001586 int usb_present, host_mode, usbin_health;
1587 u8 psy_health_sts;
David Keitel80668952012-07-27 14:25:49 -07001588
1589 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001590 host_mode = qpnp_chg_is_otg_en_set(chip);
1591 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1592 usb_present, host_mode);
1593
1594 /* In host mode notifications cmoe from USB supply */
1595 if (host_mode)
1596 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001597
1598 if (chip->usb_present ^ usb_present) {
1599 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001600 if (!usb_present) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001601 /* when a valid charger inserted, and increase the
1602 * charger voltage to OVP threshold, then
1603 * usb_in_valid falling edge interrupt triggers.
1604 * So we handle the OVP monitor here, and ignore
1605 * other health state changes */
1606 if (chip->ovp_monitor_enable &&
1607 (chip->usb_valid_check_ovp)) {
1608 usbin_health =
1609 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001610 if ((chip->usbin_health != usbin_health)
1611 && (usbin_health == USBIN_OVP)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001612 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001613 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001614 POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1615 power_supply_set_health_state(
1616 chip->usb_psy,
1617 psy_health_sts);
1618 power_supply_changed(chip->usb_psy);
1619 }
1620 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001621 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1622 chip->delta_vddmax_mv = 0;
1623 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel6e63bd52013-09-06 18:00:03 -07001624 chip->chg_done = false;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001625 }
David Keitela9185602013-11-12 17:55:48 -08001626 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel7b0568482013-12-02 14:47:42 -08001627 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelfd305ee2013-07-19 20:19:06 -07001628 chip->prev_usb_max_ma = -EINVAL;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07001629 chip->aicl_settled = false;
David Keitel9fd07382013-05-02 15:37:44 -07001630 } else {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001631 /* when OVP clamped usbin, and then decrease
1632 * the charger voltage to lower than the OVP
1633 * threshold, a usbin_valid rising edge
1634 * interrupt triggered. So we change the usb
1635 * psy health state back to good */
1636 if (chip->ovp_monitor_enable &&
1637 (chip->usb_valid_check_ovp)) {
1638 usbin_health =
1639 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001640 if ((chip->usbin_health != usbin_health)
1641 && (usbin_health == USBIN_OK)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001642 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001643 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001644 POWER_SUPPLY_HEALTH_GOOD;
1645 power_supply_set_health_state(
1646 chip->usb_psy,
1647 psy_health_sts);
1648 power_supply_changed(chip->usb_psy);
1649 }
1650 }
1651
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001652 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1653 chip->delta_vddmax_mv = 0;
1654 qpnp_chg_set_appropriate_vddmax(chip);
1655 }
David Keitel9fd07382013-05-02 15:37:44 -07001656 schedule_delayed_work(&chip->eoc_work,
1657 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001658 schedule_work(&chip->soc_check_work);
David Keitel9fd07382013-05-02 15:37:44 -07001659 }
David Keitel344c6972013-04-09 19:28:21 -07001660
David Keitel9fd07382013-05-02 15:37:44 -07001661 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel6e63bd52013-09-06 18:00:03 -07001662 schedule_work(&chip->batfet_lcl_work);
David Keitel80668952012-07-27 14:25:49 -07001663 }
1664
1665 return IRQ_HANDLED;
1666}
1667
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001668#define TEST_EN_SMBC_LOOP 0xE5
1669#define IBAT_REGULATION_DISABLE BIT(2)
David Keitel7450dcd2013-01-29 18:41:41 -08001670static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001671qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1672{
1673 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001674 int batt_temp_good, batt_present, rc;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001675
1676 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1677 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1678
Xiaozhe Shi87831862014-01-20 17:44:40 -08001679 batt_present = qpnp_chg_is_batt_present(chip);
1680 if (batt_present) {
1681 rc = qpnp_chg_masked_write(chip,
1682 chip->buck_base + SEC_ACCESS,
1683 0xFF,
1684 0xA5, 1);
1685 if (rc) {
1686 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1687 return rc;
1688 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001689
Xiaozhe Shi87831862014-01-20 17:44:40 -08001690 rc = qpnp_chg_masked_write(chip,
1691 chip->buck_base + TEST_EN_SMBC_LOOP,
1692 IBAT_REGULATION_DISABLE,
1693 batt_temp_good ? 0 : IBAT_REGULATION_DISABLE, 1);
1694 if (rc) {
1695 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1696 return rc;
1697 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001698 }
1699
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001700 pr_debug("psy changed batt_psy\n");
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001701 power_supply_changed(&chip->batt_psy);
1702 return IRQ_HANDLED;
1703}
1704
1705static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001706qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1707{
1708 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001709 int batt_present, batt_temp_good, rc;
David Keitel42ae0aa2013-03-08 16:20:10 -08001710
1711 batt_present = qpnp_chg_is_batt_present(chip);
1712 pr_debug("batt-pres triggered: %d\n", batt_present);
1713
1714 if (chip->batt_present ^ batt_present) {
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001715 if (batt_present) {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001716 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1717 rc = qpnp_chg_masked_write(chip,
1718 chip->buck_base + SEC_ACCESS,
1719 0xFF,
1720 0xA5, 1);
1721 if (rc) {
1722 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1723 return rc;
1724 }
1725
1726 rc = qpnp_chg_masked_write(chip,
1727 chip->buck_base + TEST_EN_SMBC_LOOP,
1728 IBAT_REGULATION_DISABLE,
1729 batt_temp_good
1730 ? 0 : IBAT_REGULATION_DISABLE, 1);
1731 if (rc) {
1732 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1733 return rc;
1734 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001735 schedule_work(&chip->insertion_ocv_work);
1736 } else {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001737 rc = qpnp_chg_masked_write(chip,
1738 chip->buck_base + SEC_ACCESS,
1739 0xFF,
1740 0xA5, 1);
1741 if (rc) {
1742 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1743 return rc;
1744 }
1745
1746 rc = qpnp_chg_masked_write(chip,
1747 chip->buck_base + TEST_EN_SMBC_LOOP,
1748 IBAT_REGULATION_DISABLE,
1749 0, 1);
1750 if (rc) {
1751 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1752 return rc;
1753 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001754 chip->insertion_ocv_uv = 0;
1755 qpnp_chg_charge_en(chip, 0);
1756 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001757 chip->batt_present = batt_present;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001758 pr_debug("psy changed batt_psy\n");
David Keitel42ae0aa2013-03-08 16:20:10 -08001759 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001760 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001761 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001762
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001763 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07001764 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001765 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001766 schedule_work(&chip->adc_measure_work);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001767 } else if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitelec3c09802013-06-13 13:05:30 -07001768 && !batt_present) {
David Keitelecab15a2013-08-06 15:41:39 -07001769 schedule_work(&chip->adc_disable_work);
David Keitelec3c09802013-06-13 13:05:30 -07001770 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001771 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001772 }
1773
1774 return IRQ_HANDLED;
1775}
1776
1777static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001778qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1779{
1780 struct qpnp_chg_chip *chip = _chip;
1781 int dc_present;
1782
1783 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1784 pr_debug("dcin-valid triggered: %d\n", dc_present);
1785
1786 if (chip->dc_present ^ dc_present) {
1787 chip->dc_present = dc_present;
David Keitel6d4b9da2013-09-05 17:38:40 -07001788 if (qpnp_chg_is_otg_en_set(chip))
1789 qpnp_chg_force_run_on_batt(chip, !dc_present ? 1 : 0);
David Keitel278f2c72013-08-13 18:00:45 -07001790 if (!dc_present && !qpnp_chg_is_usb_chg_plugged_in(chip)) {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001791 chip->delta_vddmax_mv = 0;
1792 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel9fd07382013-05-02 15:37:44 -07001793 chip->chg_done = false;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001794 } else {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001795 if (!qpnp_chg_is_usb_chg_plugged_in(chip)) {
1796 chip->delta_vddmax_mv = 0;
1797 qpnp_chg_set_appropriate_vddmax(chip);
1798 }
David Keitel9fd07382013-05-02 15:37:44 -07001799 schedule_delayed_work(&chip->eoc_work,
1800 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001801 schedule_work(&chip->soc_check_work);
1802 }
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001803 pr_debug("psy changed dc_psy\n");
David Keitel7450dcd2013-01-29 18:41:41 -08001804 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001805 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001806 power_supply_changed(&chip->batt_psy);
David Keitel6e63bd52013-09-06 18:00:03 -07001807 schedule_work(&chip->batfet_lcl_work);
David Keitel7450dcd2013-01-29 18:41:41 -08001808 }
1809
1810 return IRQ_HANDLED;
1811}
1812
David Keitel80668952012-07-27 14:25:49 -07001813#define CHGR_CHG_FAILED_BIT BIT(7)
1814static irqreturn_t
1815qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1816{
1817 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001818 int rc;
David Keitel80668952012-07-27 14:25:49 -07001819
David Keitel9fd07382013-05-02 15:37:44 -07001820 pr_debug("chg_failed triggered\n");
1821
David Keitel80668952012-07-27 14:25:49 -07001822 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001823 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001824 CHGR_CHG_FAILED_BIT,
1825 CHGR_CHG_FAILED_BIT, 1);
1826 if (rc)
1827 pr_err("Failed to write chg_fail clear bit!\n");
1828
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001829 if (chip->bat_if_base) {
1830 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001831 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001832 }
1833 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001834 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001835 if (chip->dc_chgpth_base) {
1836 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001837 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001838 }
David Keitel80668952012-07-27 14:25:49 -07001839 return IRQ_HANDLED;
1840}
1841
1842static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001843qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
1844{
1845 struct qpnp_chg_chip *chip = _chip;
1846
1847 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001848
1849 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001850 if (chip->bat_if_base) {
1851 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001852 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001853 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001854
1855 return IRQ_HANDLED;
1856}
1857
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001858static int qpnp_chg_is_fastchg_on(struct qpnp_chg_chip *chip)
David Keitel42ae0aa2013-03-08 16:20:10 -08001859{
David Keitel337bd862013-07-15 21:42:58 -07001860 u8 chgr_sts;
1861 int rc;
1862
David Keitelbf6a1062014-01-23 10:57:36 -08001863 qpnp_chg_irq_wake_disable(&chip->chg_fastchg);
1864
David Keitel337bd862013-07-15 21:42:58 -07001865 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001866 if (rc) {
1867 pr_err("failed to read interrupt status %d\n", rc);
1868 return rc;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001869 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001870 pr_debug("chgr_sts 0x%x\n", chgr_sts);
1871 return (chgr_sts & FAST_CHG_ON_IRQ) ? 1 : 0;
1872}
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001873
David Keitel59fbb762014-02-05 16:46:24 -08001874#define VBATDET_BYPASS 0x01
1875static int
1876bypass_vbatdet_comp(struct qpnp_chg_chip *chip, bool bypass)
1877{
1878 int rc;
1879
1880 pr_debug("bypass %d\n", bypass);
1881 rc = qpnp_chg_masked_write(chip,
1882 chip->chgr_base + SEC_ACCESS,
1883 0xA5,
1884 0xA5, 1);
1885 rc |= qpnp_chg_masked_write(chip,
1886 chip->chgr_base + CHGR_COMP_OVR1,
1887 0xFF,
1888 bypass ? VBATDET_BYPASS : 0, 1);
1889 if (rc) {
1890 pr_err("Failed to bypass vbatdet comp rc = %d\n", rc);
1891 return rc;
1892 }
1893
1894 return rc;
1895}
1896
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001897static irqreturn_t
1898qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
1899{
1900 struct qpnp_chg_chip *chip = _chip;
1901 bool fastchg_on = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001902
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001903 fastchg_on = qpnp_chg_is_fastchg_on(chip);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001904
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001905 pr_debug("FAST_CHG IRQ triggered, fastchg_on: %d\n", fastchg_on);
David Keitel337bd862013-07-15 21:42:58 -07001906
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001907 if (chip->fastchg_on ^ fastchg_on) {
1908 chip->fastchg_on = fastchg_on;
1909 if (chip->bat_if_base) {
1910 pr_debug("psy changed batt_psy\n");
1911 power_supply_changed(&chip->batt_psy);
1912 }
1913
1914 pr_debug("psy changed usb_psy\n");
1915 power_supply_changed(chip->usb_psy);
1916
1917 if (chip->dc_chgpth_base) {
1918 pr_debug("psy changed dc_psy\n");
1919 power_supply_changed(&chip->dc_psy);
1920 }
1921
1922 if (fastchg_on) {
1923 chip->chg_done = false;
David Keitel59fbb762014-02-05 16:46:24 -08001924 bypass_vbatdet_comp(chip, 1);
1925 if (chip->bat_is_warm || chip->bat_is_cool) {
1926 qpnp_chg_set_appropriate_vddmax(chip);
1927 qpnp_chg_set_appropriate_battery_current(chip);
1928 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001929
1930 if (chip->resuming_charging) {
1931 chip->resuming_charging = false;
1932 qpnp_chg_set_appropriate_vbatdet(chip);
1933 }
1934
1935 if (!chip->charging_disabled) {
1936 schedule_delayed_work(&chip->eoc_work,
1937 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
1938 pm_stay_awake(chip->dev);
1939 }
David Keitel975b5352014-01-27 14:28:04 -08001940 if (chip->parallel_ovp_mode)
1941 switch_parallel_ovp_mode(chip, 1);
1942 } else {
1943 if (chip->parallel_ovp_mode)
1944 switch_parallel_ovp_mode(chip, 0);
David Keitel59fbb762014-02-05 16:46:24 -08001945 if (!chip->bat_is_warm && !chip->bat_is_cool)
1946 bypass_vbatdet_comp(chip, 0);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001947 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001948 }
1949
David Keitel47185a62013-05-15 18:54:10 -07001950 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -08001951
1952 return IRQ_HANDLED;
1953}
1954
David Keitel03ee6b52012-10-22 12:25:19 -07001955static int
David Keitel432e1232013-06-05 16:10:18 -07001956qpnp_dc_property_is_writeable(struct power_supply *psy,
1957 enum power_supply_property psp)
1958{
1959 switch (psp) {
1960 case POWER_SUPPLY_PROP_CURRENT_MAX:
1961 return 1;
1962 default:
1963 break;
1964 }
1965
1966 return 0;
1967}
1968
1969static int
David Keitel03ee6b52012-10-22 12:25:19 -07001970qpnp_batt_property_is_writeable(struct power_supply *psy,
1971 enum power_supply_property psp)
1972{
1973 switch (psp) {
1974 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08001975 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07001976 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel2586f0a2013-08-20 10:02:26 -07001977 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07001978 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
David Keitel337bd862013-07-15 21:42:58 -07001979 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07001980 case POWER_SUPPLY_PROP_COOL_TEMP:
1981 case POWER_SUPPLY_PROP_WARM_TEMP:
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08001982 case POWER_SUPPLY_PROP_CAPACITY:
David Keitel03ee6b52012-10-22 12:25:19 -07001983 return 1;
1984 default:
1985 break;
1986 }
1987
1988 return 0;
1989}
1990
David Keitel6f865cd2012-11-30 15:04:32 -08001991static int
David Keitelbe208252013-01-31 14:49:25 -08001992qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
1993{
1994 int rc;
1995
1996 if (chip->charging_disabled && enable) {
1997 pr_debug("Charging disabled\n");
1998 return 0;
1999 }
2000
2001 rc = qpnp_chg_charge_en(chip, enable);
2002 if (rc) {
2003 pr_err("Failed to control charging %d\n", rc);
2004 return rc;
2005 }
2006
2007 rc = qpnp_chg_force_run_on_batt(chip, !enable);
2008 if (rc)
2009 pr_err("Failed to control charging %d\n", rc);
2010
2011 return rc;
2012}
2013
David Keitel454ee842013-03-08 16:19:11 -08002014static int
2015switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002016{
2017 int rc;
2018
2019 pr_debug("switch to charge mode\n");
2020 if (!qpnp_chg_is_otg_en_set(chip))
2021 return 0;
2022
David Keitel8b9bd312014-01-15 14:44:00 -08002023 if (chip->type == SMBBP) {
2024 rc = qpnp_chg_masked_write(chip,
2025 chip->boost_base + BOOST_ILIM,
2026 BOOST_ILIMT_MASK,
2027 BOOST_ILIMIT_DEF, 1);
2028 if (rc) {
2029 pr_err("Failed to set ilim rc = %d\n", rc);
2030 return rc;
2031 }
2032 }
2033
David Keitel6f865cd2012-11-30 15:04:32 -08002034 /* enable usb ovp fet */
2035 rc = qpnp_chg_masked_write(chip,
2036 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2037 USB_OTG_EN_BIT,
2038 0, 1);
2039 if (rc) {
2040 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
2041 return rc;
2042 }
2043
2044 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2045 if (rc) {
2046 pr_err("Failed re-enable charging rc = %d\n", rc);
2047 return rc;
2048 }
2049
2050 return 0;
2051}
2052
David Keitel454ee842013-03-08 16:19:11 -08002053static int
2054switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002055{
2056 int rc;
David Keitel8b9bd312014-01-15 14:44:00 -08002057 u8 usb_sts;
David Keitel6f865cd2012-11-30 15:04:32 -08002058
2059 pr_debug("switch to host mode\n");
2060 if (qpnp_chg_is_otg_en_set(chip))
2061 return 0;
2062
David Keitel975b5352014-01-27 14:28:04 -08002063 if (chip->parallel_ovp_mode)
2064 switch_parallel_ovp_mode(chip, 0);
2065
David Keitel8b9bd312014-01-15 14:44:00 -08002066 if (chip->type == SMBBP) {
2067 rc = qpnp_chg_masked_write(chip,
2068 chip->boost_base + BOOST_ILIM,
2069 BOOST_ILIMT_MASK,
2070 BOOST_ILIMIT_MIN, 1);
2071 if (rc) {
2072 pr_err("Failed to turn configure ilim rc = %d\n", rc);
2073 return rc;
2074 }
2075 }
2076
David Keitel6d4b9da2013-09-05 17:38:40 -07002077 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
2078 rc = qpnp_chg_force_run_on_batt(chip, 1);
2079 if (rc) {
2080 pr_err("Failed to disable charging rc = %d\n", rc);
2081 return rc;
2082 }
David Keitel6f865cd2012-11-30 15:04:32 -08002083 }
2084
2085 /* force usb ovp fet off */
2086 rc = qpnp_chg_masked_write(chip,
2087 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2088 USB_OTG_EN_BIT,
2089 USB_OTG_EN_BIT, 1);
2090 if (rc) {
2091 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
2092 return rc;
2093 }
2094
David Keitel8b9bd312014-01-15 14:44:00 -08002095 if (chip->type == SMBBP) {
2096 /* Wait for OCP circuitry to be powered up */
2097 msleep(100);
2098 rc = qpnp_chg_read(chip, &usb_sts,
2099 INT_RT_STS(chip->usb_chgpth_base), 1);
2100 if (rc) {
2101 pr_err("failed to read interrupt sts %d\n", rc);
2102 return rc;
2103 }
2104
2105 if (usb_sts & COARSE_DET_USB_IRQ) {
2106 rc = qpnp_chg_masked_write(chip,
2107 chip->boost_base + BOOST_ILIM,
2108 BOOST_ILIMT_MASK,
2109 BOOST_ILIMIT_DEF, 1);
2110 if (rc) {
2111 pr_err("Failed to set ilim rc = %d\n", rc);
2112 return rc;
2113 }
2114 } else {
2115 pr_warn_ratelimited("USB short to GND detected!\n");
2116 }
2117 }
2118
David Keitel6f865cd2012-11-30 15:04:32 -08002119 return 0;
2120}
2121
David Keitel80668952012-07-27 14:25:49 -07002122static enum power_supply_property pm_power_props_mains[] = {
2123 POWER_SUPPLY_PROP_PRESENT,
2124 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07002125 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07002126};
2127
2128static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07002129 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07002130 POWER_SUPPLY_PROP_STATUS,
2131 POWER_SUPPLY_PROP_CHARGE_TYPE,
2132 POWER_SUPPLY_PROP_HEALTH,
2133 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002134 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07002135 POWER_SUPPLY_PROP_TECHNOLOGY,
2136 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
2137 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
2138 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2139 POWER_SUPPLY_PROP_CAPACITY,
2140 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07002141 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
David Keitel2586f0a2013-08-20 10:02:26 -07002142 POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002143 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
David Keitel337bd862013-07-15 21:42:58 -07002144 POWER_SUPPLY_PROP_VOLTAGE_MIN,
2145 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07002146 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302147 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07002148 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07002149 POWER_SUPPLY_PROP_COOL_TEMP,
2150 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08002151 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302152 POWER_SUPPLY_PROP_CYCLE_COUNT,
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002153 POWER_SUPPLY_PROP_VOLTAGE_OCV,
David Keitel80668952012-07-27 14:25:49 -07002154};
2155
2156static char *pm_power_supplied_to[] = {
2157 "battery",
2158};
2159
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07002160static char *pm_batt_supplied_to[] = {
2161 "bms",
2162};
2163
David Keitel337bd862013-07-15 21:42:58 -07002164static int charger_monitor;
2165module_param(charger_monitor, int, 0644);
2166
David Keitel2586f0a2013-08-20 10:02:26 -07002167static int ext_ovp_present;
2168module_param(ext_ovp_present, int, 0444);
2169
David Keitel80668952012-07-27 14:25:49 -07002170#define USB_WALL_THRESHOLD_MA 500
David Keitel2586f0a2013-08-20 10:02:26 -07002171#define OVP_USB_WALL_THRESHOLD_MA 200
David Keitel80668952012-07-27 14:25:49 -07002172static int
2173qpnp_power_get_property_mains(struct power_supply *psy,
2174 enum power_supply_property psp,
2175 union power_supply_propval *val)
2176{
2177 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2178 dc_psy);
2179
2180 switch (psp) {
2181 case POWER_SUPPLY_PROP_PRESENT:
2182 case POWER_SUPPLY_PROP_ONLINE:
2183 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07002184 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07002185 return 0;
2186
2187 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
2188 break;
David Keitel432e1232013-06-05 16:10:18 -07002189 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07002190 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07002191 break;
David Keitel80668952012-07-27 14:25:49 -07002192 default:
2193 return -EINVAL;
2194 }
2195 return 0;
2196}
2197
David Keitel7ac385e2013-08-19 18:02:40 -07002198static void
2199qpnp_aicl_check_work(struct work_struct *work)
2200{
2201 struct delayed_work *dwork = to_delayed_work(work);
2202 struct qpnp_chg_chip *chip = container_of(dwork,
2203 struct qpnp_chg_chip, aicl_check_work);
2204 union power_supply_propval ret = {0,};
2205
2206 if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
2207 chip->usb_psy->get_property(chip->usb_psy,
2208 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
2209 if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
2210 pr_debug("no charger_monitor present set iusbmax %d\n",
2211 ret.intval / 1000);
2212 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2213 }
2214 } else {
2215 pr_debug("charger_monitor is present\n");
2216 }
2217 chip->charger_monitor_checked = true;
2218}
2219
David Keitel80668952012-07-27 14:25:49 -07002220static int
2221get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
2222{
2223 int rc = 0;
2224 struct qpnp_vadc_result results;
2225
David Keitelfe51cb92013-04-02 19:42:58 -07002226 if (chip->revision == 0 && chip->type == SMBB) {
2227 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
2228 return 0;
2229 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002230 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07002231 if (rc) {
2232 pr_err("Unable to read vbat rc=%d\n", rc);
2233 return 0;
2234 }
2235 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07002236 }
2237}
2238
2239#define BATT_PRES_BIT BIT(7)
2240static int
2241get_prop_batt_present(struct qpnp_chg_chip *chip)
2242{
2243 u8 batt_present;
2244 int rc;
2245
2246 rc = qpnp_chg_read(chip, &batt_present,
2247 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
2248 if (rc) {
2249 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
2250 return 0;
2251 };
2252 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
2253}
2254
2255#define BATT_TEMP_HOT BIT(6)
2256#define BATT_TEMP_OK BIT(7)
2257static int
2258get_prop_batt_health(struct qpnp_chg_chip *chip)
2259{
2260 u8 batt_health;
2261 int rc;
2262
2263 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07002264 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07002265 if (rc) {
2266 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
2267 return POWER_SUPPLY_HEALTH_UNKNOWN;
2268 };
2269
2270 if (BATT_TEMP_OK & batt_health)
2271 return POWER_SUPPLY_HEALTH_GOOD;
2272 if (BATT_TEMP_HOT & batt_health)
2273 return POWER_SUPPLY_HEALTH_OVERHEAT;
2274 else
2275 return POWER_SUPPLY_HEALTH_COLD;
2276}
2277
2278static int
2279get_prop_charge_type(struct qpnp_chg_chip *chip)
2280{
2281 int rc;
2282 u8 chgr_sts;
2283
2284 if (!get_prop_batt_present(chip))
2285 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2286
2287 rc = qpnp_chg_read(chip, &chgr_sts,
2288 INT_RT_STS(chip->chgr_base), 1);
2289 if (rc) {
2290 pr_err("failed to read interrupt sts %d\n", rc);
2291 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2292 }
2293
2294 if (chgr_sts & TRKL_CHG_ON_IRQ)
2295 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
2296 if (chgr_sts & FAST_CHG_ON_IRQ)
2297 return POWER_SUPPLY_CHARGE_TYPE_FAST;
2298
2299 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2300}
2301
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002302#define DEFAULT_CAPACITY 50
2303static int
2304get_batt_capacity(struct qpnp_chg_chip *chip)
2305{
2306 union power_supply_propval ret = {0,};
2307
2308 if (chip->fake_battery_soc >= 0)
2309 return chip->fake_battery_soc;
2310 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2311 return DEFAULT_CAPACITY;
2312 if (chip->bms_psy) {
2313 chip->bms_psy->get_property(chip->bms_psy,
2314 POWER_SUPPLY_PROP_CAPACITY, &ret);
2315 return ret.intval;
2316 }
2317 return DEFAULT_CAPACITY;
2318}
2319
David Keitel80668952012-07-27 14:25:49 -07002320static int
2321get_prop_batt_status(struct qpnp_chg_chip *chip)
2322{
2323 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002324 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07002325
David Keitel9fd07382013-05-02 15:37:44 -07002326 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
2327 qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
David Keitelc9ffe842013-01-25 19:37:51 -08002328 return POWER_SUPPLY_STATUS_FULL;
David Keitel9fd07382013-05-02 15:37:44 -07002329 }
David Keitelc9ffe842013-01-25 19:37:51 -08002330
David Keitel9fd07382013-05-02 15:37:44 -07002331 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07002332 if (rc) {
2333 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08002334 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07002335 }
2336
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002337 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
2338 if (rc) {
2339 pr_err("failed to read bat_if sts %d\n", rc);
2340 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2341 }
2342
David Keitela8099ff2014-01-06 11:31:40 -08002343 if ((chgr_sts & TRKL_CHG_ON_IRQ) && !(bat_if_sts & BAT_FET_ON_IRQ))
David Keitel80668952012-07-27 14:25:49 -07002344 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002345 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07002346 return POWER_SUPPLY_STATUS_CHARGING;
2347
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002348 /* report full if state of charge is 100 and a charger is connected */
2349 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
2350 qpnp_chg_is_dc_chg_plugged_in(chip))
2351 && get_batt_capacity(chip) == 100) {
2352 return POWER_SUPPLY_STATUS_FULL;
2353 }
2354
David Keitel80668952012-07-27 14:25:49 -07002355 return POWER_SUPPLY_STATUS_DISCHARGING;
2356}
2357
2358static int
2359get_prop_current_now(struct qpnp_chg_chip *chip)
2360{
2361 union power_supply_propval ret = {0,};
2362
2363 if (chip->bms_psy) {
2364 chip->bms_psy->get_property(chip->bms_psy,
2365 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
2366 return ret.intval;
2367 } else {
2368 pr_debug("No BMS supply registered return 0\n");
2369 }
2370
2371 return 0;
2372}
2373
2374static int
2375get_prop_full_design(struct qpnp_chg_chip *chip)
2376{
2377 union power_supply_propval ret = {0,};
2378
2379 if (chip->bms_psy) {
2380 chip->bms_psy->get_property(chip->bms_psy,
2381 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
2382 return ret.intval;
2383 } else {
2384 pr_debug("No BMS supply registered return 0\n");
2385 }
2386
2387 return 0;
2388}
2389
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302390static int
2391get_prop_charge_full(struct qpnp_chg_chip *chip)
2392{
2393 union power_supply_propval ret = {0,};
2394
2395 if (chip->bms_psy) {
2396 chip->bms_psy->get_property(chip->bms_psy,
2397 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
2398 return ret.intval;
2399 } else {
2400 pr_debug("No BMS supply registered return 0\n");
2401 }
2402
2403 return 0;
2404}
2405
David Keitel80668952012-07-27 14:25:49 -07002406static int
2407get_prop_capacity(struct qpnp_chg_chip *chip)
2408{
2409 union power_supply_propval ret = {0,};
Xiaozhe Shibda84992013-09-05 10:39:11 -07002410 int battery_status, bms_status, soc, charger_in;
David Keitel80668952012-07-27 14:25:49 -07002411
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002412 if (chip->fake_battery_soc >= 0)
2413 return chip->fake_battery_soc;
2414
David Keitel3dd5e0f2012-12-12 18:12:36 -08002415 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2416 return DEFAULT_CAPACITY;
2417
David Keitel80668952012-07-27 14:25:49 -07002418 if (chip->bms_psy) {
2419 chip->bms_psy->get_property(chip->bms_psy,
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002420 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002421 soc = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002422 battery_status = get_prop_batt_status(chip);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002423 chip->bms_psy->get_property(chip->bms_psy,
2424 POWER_SUPPLY_PROP_STATUS, &ret);
2425 bms_status = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002426 charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
2427 qpnp_chg_is_dc_chg_plugged_in(chip);
2428
2429 if (battery_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shibda84992013-09-05 10:39:11 -07002430 && bms_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002431 && charger_in
Xiaozhe Shie8504482013-10-30 18:10:31 -07002432 && !chip->bat_is_cool
2433 && !chip->bat_is_warm
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002434 && !chip->resuming_charging
2435 && !chip->charging_disabled
2436 && chip->soc_resume_limit
Xiaozhe Shibda84992013-09-05 10:39:11 -07002437 && soc <= chip->soc_resume_limit) {
2438 pr_debug("resuming charging at %d%% soc\n", soc);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002439 chip->resuming_charging = true;
David Keitelbf6a1062014-01-23 10:57:36 -08002440 qpnp_chg_irq_wake_enable(&chip->chg_fastchg);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002441 qpnp_chg_set_appropriate_vbatdet(chip);
2442 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2443 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002444 if (soc == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07002445 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
2446 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07002447 pr_warn_ratelimited("Battery 0, CHG absent\n");
2448 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002449 return soc;
David Keitel80668952012-07-27 14:25:49 -07002450 } else {
2451 pr_debug("No BMS supply registered return 50\n");
2452 }
2453
2454 /* return default capacity to avoid userspace
2455 * from shutting down unecessarily */
2456 return DEFAULT_CAPACITY;
2457}
2458
David Keitel3dd5e0f2012-12-12 18:12:36 -08002459#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07002460#define MAX_TOLERABLE_BATT_TEMP_DDC 680
2461static int
2462get_prop_batt_temp(struct qpnp_chg_chip *chip)
2463{
2464 int rc = 0;
2465 struct qpnp_vadc_result results;
2466
David Keitel3dd5e0f2012-12-12 18:12:36 -08002467 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2468 return DEFAULT_TEMP;
2469
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002470 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07002471 if (rc) {
2472 pr_debug("Unable to read batt temperature rc=%d\n", rc);
2473 return 0;
David Keitel80668952012-07-27 14:25:49 -07002474 }
Xiaozhe Shi4c8458a2013-11-26 13:00:56 -08002475 pr_debug("get_bat_temp %d, %lld\n",
David Keitela2dbfc72013-06-07 11:10:14 -07002476 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07002477
David Keitela2dbfc72013-06-07 11:10:14 -07002478 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07002479}
2480
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302481static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
2482{
2483 union power_supply_propval ret = {0,};
2484
2485 if (chip->bms_psy)
2486 chip->bms_psy->get_property(chip->bms_psy,
2487 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
2488 return ret.intval;
2489}
2490
David Keitel337bd862013-07-15 21:42:58 -07002491static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
2492{
2493 u8 buck_sts;
2494 int rc;
2495
2496 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2497
2498 if (rc) {
2499 pr_err("spmi read failed: addr=%03X, rc=%d\n",
2500 INT_RT_STS(chip->buck_base), rc);
2501 return rc;
2502 }
2503 pr_debug("buck usb sts 0x%x\n", buck_sts);
2504
2505 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
2506}
2507
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002508static int get_prop_online(struct qpnp_chg_chip *chip)
2509{
2510 return qpnp_chg_is_batfet_closed(chip);
2511}
2512
David Keitel80668952012-07-27 14:25:49 -07002513static void
2514qpnp_batt_external_power_changed(struct power_supply *psy)
2515{
2516 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2517 batt_psy);
2518 union power_supply_propval ret = {0,};
2519
2520 if (!chip->bms_psy)
2521 chip->bms_psy = power_supply_get_by_name("bms");
2522
2523 chip->usb_psy->get_property(chip->usb_psy,
2524 POWER_SUPPLY_PROP_ONLINE, &ret);
2525
David Keitelc69f2d62013-03-17 14:52:35 -07002526 /* Only honour requests while USB is present */
2527 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002528 chip->usb_psy->get_property(chip->usb_psy,
2529 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07002530
2531 if (chip->prev_usb_max_ma == ret.intval)
2532 goto skip_set_iusb_max;
2533
Zhenhua Huangdd619742013-10-24 10:02:07 +08002534 chip->prev_usb_max_ma = ret.intval;
2535
David Keitel87473252013-03-21 14:39:45 -07002536 if (ret.intval <= 2 && !chip->use_default_batt_values &&
2537 get_prop_batt_present(chip)) {
David Keitela9185602013-11-12 17:55:48 -08002538 if (ret.intval == 2)
2539 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07002540 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07002541 } else {
David Keiteld681cda2012-10-02 15:44:21 -07002542 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel337bd862013-07-15 21:42:58 -07002543 if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
David Keitel7ac385e2013-08-19 18:02:40 -07002544 && (charger_monitor ||
2545 !chip->charger_monitor_checked)) {
David Keitel2586f0a2013-08-20 10:02:26 -07002546 if (!ext_ovp_present)
2547 qpnp_chg_iusbmax_set(chip,
David Keitel337bd862013-07-15 21:42:58 -07002548 USB_WALL_THRESHOLD_MA);
David Keitel2586f0a2013-08-20 10:02:26 -07002549 else
2550 qpnp_chg_iusbmax_set(chip,
2551 OVP_USB_WALL_THRESHOLD_MA);
David Keitel337bd862013-07-15 21:42:58 -07002552 } else {
2553 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2554 }
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002555
2556 if ((chip->flags & POWER_STAGE_WA)
2557 && ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
Zhenhua Huangdc335512013-10-30 11:45:15 +08002558 && !chip->power_stage_workaround_running
2559 && chip->power_stage_workaround_enable) {
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002560 chip->power_stage_workaround_running = true;
2561 pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
2562 charger_monitor);
2563 schedule_work(&chip->reduce_power_stage_work);
2564 }
David Keitelc69f2d62013-03-17 14:52:35 -07002565 }
David Keitel80668952012-07-27 14:25:49 -07002566 }
2567
David Keitelfd305ee2013-07-19 20:19:06 -07002568skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07002569 pr_debug("end of power supply changed\n");
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002570 pr_debug("psy changed batt_psy\n");
David Keitel80668952012-07-27 14:25:49 -07002571 power_supply_changed(&chip->batt_psy);
2572}
2573
2574static int
2575qpnp_batt_power_get_property(struct power_supply *psy,
2576 enum power_supply_property psp,
2577 union power_supply_propval *val)
2578{
2579 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2580 batt_psy);
2581
2582 switch (psp) {
2583 case POWER_SUPPLY_PROP_STATUS:
2584 val->intval = get_prop_batt_status(chip);
2585 break;
2586 case POWER_SUPPLY_PROP_CHARGE_TYPE:
2587 val->intval = get_prop_charge_type(chip);
2588 break;
2589 case POWER_SUPPLY_PROP_HEALTH:
2590 val->intval = get_prop_batt_health(chip);
2591 break;
2592 case POWER_SUPPLY_PROP_PRESENT:
2593 val->intval = get_prop_batt_present(chip);
2594 break;
2595 case POWER_SUPPLY_PROP_TECHNOLOGY:
2596 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2597 break;
2598 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2599 val->intval = chip->max_voltage_mv * 1000;
2600 break;
2601 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2602 val->intval = chip->min_voltage_mv * 1000;
2603 break;
2604 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2605 val->intval = get_prop_battery_voltage_now(chip);
2606 break;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002607 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2608 val->intval = chip->insertion_ocv_uv;
2609 break;
David Keitel80668952012-07-27 14:25:49 -07002610 case POWER_SUPPLY_PROP_TEMP:
2611 val->intval = get_prop_batt_temp(chip);
2612 break;
David Keitelec3c09802013-06-13 13:05:30 -07002613 case POWER_SUPPLY_PROP_COOL_TEMP:
2614 val->intval = chip->cool_bat_decidegc;
2615 break;
2616 case POWER_SUPPLY_PROP_WARM_TEMP:
2617 val->intval = chip->warm_bat_decidegc;
2618 break;
David Keitel80668952012-07-27 14:25:49 -07002619 case POWER_SUPPLY_PROP_CAPACITY:
2620 val->intval = get_prop_capacity(chip);
2621 break;
2622 case POWER_SUPPLY_PROP_CURRENT_NOW:
2623 val->intval = get_prop_current_now(chip);
2624 break;
2625 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2626 val->intval = get_prop_full_design(chip);
2627 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302628 case POWER_SUPPLY_PROP_CHARGE_FULL:
2629 val->intval = get_prop_charge_full(chip);
2630 break;
David Keitelb80eda82012-10-15 10:49:11 -07002631 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07002632 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07002633 break;
David Keitelbe208252013-01-31 14:49:25 -08002634 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2635 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07002636 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302637 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2638 val->intval = get_prop_cycle_count(chip);
2639 break;
David Keitel337bd862013-07-15 21:42:58 -07002640 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
2641 val->intval = get_prop_vchg_loop(chip);
2642 break;
2643 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2644 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
2645 break;
David Keitel2586f0a2013-08-20 10:02:26 -07002646 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
2647 val->intval = qpnp_chg_iusb_trim_get(chip);
2648 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002649 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
2650 val->intval = chip->aicl_settled;
2651 break;
David Keitel337bd862013-07-15 21:42:58 -07002652 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2653 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
2654 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002655 case POWER_SUPPLY_PROP_ONLINE:
2656 val->intval = get_prop_online(chip);
2657 break;
David Keitelb80eda82012-10-15 10:49:11 -07002658 default:
2659 return -EINVAL;
2660 }
2661
David Keitelb80eda82012-10-15 10:49:11 -07002662 return 0;
David Keitel80668952012-07-27 14:25:49 -07002663}
2664
David Keitel89c17752013-06-28 14:52:48 -07002665#define BTC_CONFIG_ENABLED BIT(7)
2666#define BTC_COLD BIT(1)
2667#define BTC_HOT BIT(0)
2668static int
2669qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
2670{
2671 u8 btc_cfg = 0, mask = 0;
2672
2673 /* Do nothing if battery peripheral not present */
2674 if (!chip->bat_if_base)
2675 return 0;
2676
2677 if ((chip->hot_batt_p == HOT_THD_25_PCT)
2678 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
2679 btc_cfg |= btc_value[chip->hot_batt_p];
2680 mask |= BTC_HOT;
2681 }
2682
2683 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
2684 (chip->cold_batt_p == COLD_THD_80_PCT)) {
2685 btc_cfg |= btc_value[chip->cold_batt_p];
2686 mask |= BTC_COLD;
2687 }
2688
2689 if (chip->btc_disabled)
2690 mask |= BTC_CONFIG_ENABLED;
2691
2692 return qpnp_chg_masked_write(chip,
2693 chip->bat_if_base + BAT_IF_BTC_CTRL,
2694 mask, btc_cfg, 1);
2695}
2696
David Keitel5d44fa52012-12-03 16:37:31 -08002697#define QPNP_CHG_IBATSAFE_MIN_MA 100
2698#define QPNP_CHG_IBATSAFE_MAX_MA 3250
2699#define QPNP_CHG_I_STEP_MA 50
2700#define QPNP_CHG_I_MIN_MA 100
2701#define QPNP_CHG_I_MASK 0x3F
2702static int
2703qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
2704{
2705 u8 temp;
2706
2707 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
2708 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
2709 pr_err("bad mA=%d asked to set\n", safe_current);
2710 return -EINVAL;
2711 }
2712
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08002713 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08002714 return qpnp_chg_masked_write(chip,
2715 chip->chgr_base + CHGR_IBAT_SAFE,
2716 QPNP_CHG_I_MASK, temp, 1);
2717}
David Keitel80668952012-07-27 14:25:49 -07002718
2719#define QPNP_CHG_ITERM_MIN_MA 100
2720#define QPNP_CHG_ITERM_MAX_MA 250
2721#define QPNP_CHG_ITERM_STEP_MA 50
2722#define QPNP_CHG_ITERM_MASK 0x03
2723static int
2724qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
2725{
2726 u8 temp;
2727
2728 if (term_current < QPNP_CHG_ITERM_MIN_MA
2729 || term_current > QPNP_CHG_ITERM_MAX_MA) {
2730 pr_err("bad mA=%d asked to set\n", term_current);
2731 return -EINVAL;
2732 }
2733
2734 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
2735 / QPNP_CHG_ITERM_STEP_MA;
2736 return qpnp_chg_masked_write(chip,
2737 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
2738 QPNP_CHG_ITERM_MASK, temp, 1);
2739}
2740
David Keitelff5d0472013-04-04 11:36:06 -07002741#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07002742#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07002743static int
2744qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
2745{
2746 u8 temp;
2747
2748 if (chg_current < QPNP_CHG_IBATMAX_MIN
2749 || chg_current > QPNP_CHG_IBATMAX_MAX) {
2750 pr_err("bad mA=%d asked to set\n", chg_current);
2751 return -EINVAL;
2752 }
David Keitelff5d0472013-04-04 11:36:06 -07002753 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07002754 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
2755 QPNP_CHG_I_MASK, temp, 1);
2756}
2757
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002758static int
2759qpnp_chg_ibatmax_get(struct qpnp_chg_chip *chip, int *chg_current)
2760{
2761 int rc;
2762 u8 temp;
2763
2764 *chg_current = 0;
2765 rc = qpnp_chg_read(chip, &temp, chip->chgr_base + CHGR_IBAT_MAX, 1);
2766 if (rc) {
2767 pr_err("failed read ibat_max rc=%d\n", rc);
2768 return rc;
2769 }
2770
2771 *chg_current = ((temp & QPNP_CHG_I_MASK) * QPNP_CHG_I_STEP_MA);
2772
2773 return 0;
2774}
2775
David Keitela4b7b592013-04-11 18:34:35 -07002776#define QPNP_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002777#define QPNP_CHG_TCHG_EN_MASK 0x80
David Keitela4b7b592013-04-11 18:34:35 -07002778#define QPNP_CHG_TCHG_MIN 4
2779#define QPNP_CHG_TCHG_MAX 512
2780#define QPNP_CHG_TCHG_STEP 4
2781static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
2782{
2783 u8 temp;
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002784 int rc;
David Keitela4b7b592013-04-11 18:34:35 -07002785
2786 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
2787 pr_err("bad max minutes =%d asked to set\n", minutes);
2788 return -EINVAL;
2789 }
2790
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002791 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
2792 QPNP_CHG_TCHG_EN_MASK, 0, 1);
2793 if (rc) {
2794 pr_err("failed write tchg_max_en rc=%d\n", rc);
2795 return rc;
2796 }
2797
2798 temp = minutes / QPNP_CHG_TCHG_STEP - 1;
2799
2800 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07002801 QPNP_CHG_TCHG_MASK, temp, 1);
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002802 if (rc) {
2803 pr_err("failed write tchg_max_en rc=%d\n", rc);
2804 return rc;
2805 }
2806
2807 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
2808 QPNP_CHG_TCHG_EN_MASK, QPNP_CHG_TCHG_EN_MASK, 1);
2809 if (rc) {
2810 pr_err("failed write tchg_max_en rc=%d\n", rc);
2811 return rc;
2812 }
2813
2814 return 0;
David Keitela4b7b592013-04-11 18:34:35 -07002815}
David Keitel80668952012-07-27 14:25:49 -07002816
David Keitel59fbb762014-02-05 16:46:24 -08002817static void
2818qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
2819{
2820 unsigned int chg_current = chip->max_bat_chg_current;
2821
2822 if (chip->bat_is_cool)
2823 chg_current = min(chg_current, chip->cool_bat_chg_ma);
2824
2825 if (chip->bat_is_warm)
2826 chg_current = min(chg_current, chip->warm_bat_chg_ma);
2827
2828 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
2829 chg_current = min(chg_current,
2830 chip->thermal_mitigation[chip->therm_lvl_sel]);
2831
2832 pr_debug("setting %d mA\n", chg_current);
2833 qpnp_chg_ibatmax_set(chip, chg_current);
2834}
2835
David Keitel80668952012-07-27 14:25:49 -07002836static int
2837qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
2838{
2839 u8 temp;
2840
2841 if (voltage < QPNP_CHG_V_MIN_MV
2842 || voltage > QPNP_CHG_V_MAX_MV) {
2843 pr_err("bad mV=%d asked to set\n", voltage);
2844 return -EINVAL;
2845 }
2846 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
2847 pr_debug("voltage=%d setting %02x\n", voltage, temp);
2848 return qpnp_chg_write(chip, &temp,
2849 chip->chgr_base + CHGR_VDD_SAFE, 1);
2850}
2851
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002852#define IBAT_TRIM_TGT_MA 500
2853#define IBAT_TRIM_OFFSET_MASK 0x7F
2854#define IBAT_TRIM_GOOD_BIT BIT(7)
2855#define IBAT_TRIM_LOW_LIM 20
2856#define IBAT_TRIM_HIGH_LIM 114
2857#define IBAT_TRIM_MEAN 64
2858
2859static void
2860qpnp_chg_trim_ibat(struct qpnp_chg_chip *chip, u8 ibat_trim)
2861{
2862 int ibat_now_ma, ibat_diff_ma, rc;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002863 struct qpnp_iadc_result i_result;
2864 enum qpnp_iadc_channels iadc_channel;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002865
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002866 iadc_channel = chip->use_external_rsense ?
2867 EXTERNAL_RSENSE : INTERNAL_RSENSE;
2868 rc = qpnp_iadc_read(chip->iadc_dev, iadc_channel, &i_result);
2869 if (rc) {
2870 pr_err("Unable to read bat rc=%d\n", rc);
2871 return;
2872 }
2873
2874 ibat_now_ma = i_result.result_ua / 1000;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002875
2876 if (qpnp_chg_is_ibat_loop_active(chip)) {
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002877 ibat_diff_ma = ibat_now_ma - IBAT_TRIM_TGT_MA;
2878
2879 if (abs(ibat_diff_ma) > 50) {
2880 ibat_trim += (ibat_diff_ma / 20);
2881 ibat_trim &= IBAT_TRIM_OFFSET_MASK;
2882 /* reject new ibat_trim if it is outside limits */
2883 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
2884 IBAT_TRIM_HIGH_LIM))
2885 return;
2886 }
2887 ibat_trim |= IBAT_TRIM_GOOD_BIT;
2888 rc = qpnp_chg_write(chip, &ibat_trim,
2889 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2890 if (rc)
2891 pr_err("failed to set IBAT_TRIM rc=%d\n", rc);
2892
2893 pr_debug("ibat_now=%dmA, itgt=%dmA, ibat_diff=%dmA, ibat_trim=%x\n",
2894 ibat_now_ma, IBAT_TRIM_TGT_MA,
2895 ibat_diff_ma, ibat_trim);
2896 } else {
2897 pr_debug("ibat loop not active - cannot calibrate ibat\n");
2898 }
2899}
2900
2901static int
2902qpnp_chg_input_current_settled(struct qpnp_chg_chip *chip)
2903{
2904 int rc, ibat_max_ma;
2905 u8 reg, chgr_sts, ibat_trim, i;
2906
2907 chip->aicl_settled = true;
2908
2909 /*
2910 * Perform the ibat calibration.
2911 * This is for devices which have a IBAT_TRIM error
2912 * which can show IBAT_MAX out of spec.
2913 */
2914 if (!chip->ibat_calibration_enabled)
2915 return 0;
2916
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002917 if (chip->type != SMBB)
2918 return 0;
2919
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002920 rc = qpnp_chg_read(chip, &reg,
2921 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2922 if (rc) {
2923 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
2924 return rc;
2925 }
2926 if (reg & IBAT_TRIM_GOOD_BIT) {
2927 pr_debug("IBAT_TRIM_GOOD bit already set. Quitting!\n");
2928 return 0;
2929 }
2930 ibat_trim = reg & IBAT_TRIM_OFFSET_MASK;
2931
2932 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
2933 IBAT_TRIM_HIGH_LIM)) {
2934 pr_debug("Improper ibat_trim value=%x setting to value=%x\n",
2935 ibat_trim, IBAT_TRIM_MEAN);
2936 ibat_trim = IBAT_TRIM_MEAN;
2937 rc = qpnp_chg_masked_write(chip,
2938 chip->buck_base + BUCK_CTRL_TRIM3,
2939 IBAT_TRIM_OFFSET_MASK, ibat_trim, 1);
2940 if (rc) {
2941 pr_err("failed to set ibat_trim to %x rc=%d\n",
2942 IBAT_TRIM_MEAN, rc);
2943 return rc;
2944 }
2945 }
2946
2947 rc = qpnp_chg_read(chip, &chgr_sts,
2948 INT_RT_STS(chip->chgr_base), 1);
2949 if (rc) {
2950 pr_err("failed to read interrupt sts rc=%d\n", rc);
2951 return rc;
2952 }
2953 if (!(chgr_sts & FAST_CHG_ON_IRQ)) {
2954 pr_debug("Not in fastchg\n");
2955 return rc;
2956 }
2957
2958 /* save the ibat_max to restore it later */
2959 rc = qpnp_chg_ibatmax_get(chip, &ibat_max_ma);
2960 if (rc) {
2961 pr_debug("failed to save ibatmax rc=%d\n", rc);
2962 return rc;
2963 }
2964
2965 rc = qpnp_chg_ibatmax_set(chip, IBAT_TRIM_TGT_MA);
2966 if (rc) {
2967 pr_err("failed to set ibatmax rc=%d\n", rc);
2968 return rc;
2969 }
2970
2971 for (i = 0; i < 3; i++) {
2972 /*
2973 * ibat settling delay - to make sure the BMS controller
2974 * has sufficient time to sample ibat for the configured
2975 * ibat_max
2976 */
2977 msleep(20);
2978 if (qpnp_chg_is_ibat_loop_active(chip))
2979 qpnp_chg_trim_ibat(chip, ibat_trim);
2980 else
2981 pr_debug("ibat loop not active\n");
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002982
2983 /* read the adjusted ibat_trim for further adjustments */
2984 rc = qpnp_chg_read(chip, &ibat_trim,
2985 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2986 if (rc) {
2987 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
2988 break;
2989 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002990 }
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002991
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002992 /* restore IBATMAX */
2993 rc = qpnp_chg_ibatmax_set(chip, ibat_max_ma);
2994 if (rc)
2995 pr_err("failed to restore ibatmax rc=%d\n", rc);
2996
2997 return rc;
2998}
2999
3000
David Keitel6dc4ed42013-05-17 11:08:58 -07003001#define BOOST_MIN_UV 4200000
3002#define BOOST_MAX_UV 5500000
3003#define BOOST_STEP_UV 50000
3004#define BOOST_MIN 16
3005#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
3006static int
3007qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
3008{
3009 u8 reg = 0;
3010
3011 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
3012 pr_err("invalid voltage requested %d uV\n", voltage);
3013 return -EINVAL;
3014 }
3015
3016 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
3017
3018 pr_debug("voltage=%d setting %02x\n", voltage, reg);
3019 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
3020}
3021
3022static int
3023qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
3024{
3025 int rc;
3026 u8 boost_reg;
3027
3028 rc = qpnp_chg_read(chip, &boost_reg,
3029 chip->boost_base + BOOST_VSET, 1);
3030 if (rc) {
3031 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
3032 return rc;
3033 }
3034
3035 if (boost_reg < BOOST_MIN) {
3036 pr_err("Invalid reading from 0x%x\n", boost_reg);
3037 return -EINVAL;
3038 }
3039
3040 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
3041}
3042
David Keitel454ee842013-03-08 16:19:11 -08003043static void
David Keitelbe208252013-01-31 14:49:25 -08003044qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
3045{
3046 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
3047 chip->therm_lvl_sel = lvl_sel;
3048 if (lvl_sel == (chip->thermal_levels - 1)) {
3049 /* disable charging if highest value selected */
3050 qpnp_chg_buck_control(chip, 0);
3051 } else {
3052 qpnp_chg_buck_control(chip, 1);
3053 qpnp_chg_set_appropriate_battery_current(chip);
3054 }
3055 } else {
3056 pr_err("Unsupported level selected %d\n", lvl_sel);
3057 }
3058}
3059
David Keitel6dc4ed42013-05-17 11:08:58 -07003060/* OTG regulator operations */
3061static int
3062qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
3063{
3064 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3065
3066 return switch_usb_to_host_mode(chip);
3067}
3068
3069static int
3070qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
3071{
3072 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3073
3074 return switch_usb_to_charge_mode(chip);
3075}
3076
3077static int
3078qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
3079{
3080 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3081
3082 return qpnp_chg_is_otg_en_set(chip);
3083}
3084
3085static int
3086qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
3087{
3088 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07003089 int rc;
3090
3091 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
3092 (chip->flags & BOOST_FLASH_WA)) {
3093 qpnp_chg_usb_suspend_enable(chip, 1);
3094
3095 rc = qpnp_chg_masked_write(chip,
3096 chip->usb_chgpth_base + SEC_ACCESS,
3097 0xFF,
3098 0xA5, 1);
3099 if (rc) {
3100 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3101 return rc;
3102 }
3103
3104 rc = qpnp_chg_masked_write(chip,
3105 chip->usb_chgpth_base + COMP_OVR1,
3106 0xFF,
3107 0x2F, 1);
3108 if (rc) {
3109 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3110 return rc;
3111 }
3112 }
David Keitel6dc4ed42013-05-17 11:08:58 -07003113
3114 return qpnp_chg_masked_write(chip,
3115 chip->boost_base + BOOST_ENABLE_CONTROL,
3116 BOOST_PWR_EN,
3117 BOOST_PWR_EN, 1);
3118}
3119
3120/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07003121#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07003122static int
3123qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
3124{
3125 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07003126 int rc;
3127 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07003128
David Keitel33f58952013-05-20 16:17:36 -07003129 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003130 chip->boost_base + BOOST_ENABLE_CONTROL,
3131 BOOST_PWR_EN,
3132 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07003133 if (rc) {
3134 pr_err("failed to disable boost rc=%d\n", rc);
3135 return rc;
3136 }
3137
3138 rc = qpnp_chg_read(chip, &vbat_sts,
3139 chip->chgr_base + CHGR_VBAT_STATUS, 1);
3140 if (rc) {
3141 pr_err("failed to read bat sts rc=%d\n", rc);
3142 return rc;
3143 }
3144
3145 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
3146 rc = qpnp_chg_masked_write(chip,
3147 chip->chgr_base + SEC_ACCESS,
3148 0xFF,
3149 0xA5, 1);
3150 if (rc) {
3151 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3152 return rc;
3153 }
3154
3155 rc = qpnp_chg_masked_write(chip,
3156 chip->chgr_base + COMP_OVR1,
3157 0xFF,
3158 0x20, 1);
3159 if (rc) {
3160 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3161 return rc;
3162 }
3163
3164 usleep(2000);
3165
3166 rc = qpnp_chg_masked_write(chip,
3167 chip->chgr_base + SEC_ACCESS,
3168 0xFF,
3169 0xA5, 1);
3170 if (rc) {
3171 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3172 return rc;
3173 }
3174
3175 rc = qpnp_chg_masked_write(chip,
3176 chip->chgr_base + COMP_OVR1,
3177 0xFF,
3178 0x00, 1);
3179 if (rc) {
3180 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3181 return rc;
3182 }
3183 }
3184
3185 if (qpnp_chg_is_usb_chg_plugged_in(chip)
3186 && (chip->flags & BOOST_FLASH_WA)) {
3187 rc = qpnp_chg_masked_write(chip,
3188 chip->usb_chgpth_base + SEC_ACCESS,
3189 0xFF,
3190 0xA5, 1);
3191 if (rc) {
3192 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3193 return rc;
3194 }
3195
3196 rc = qpnp_chg_masked_write(chip,
3197 chip->usb_chgpth_base + COMP_OVR1,
3198 0xFF,
3199 0x00, 1);
3200 if (rc) {
3201 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3202 return rc;
3203 }
3204
3205 usleep(1000);
3206
3207 qpnp_chg_usb_suspend_enable(chip, 0);
3208 }
3209
3210 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003211}
3212
3213static int
3214qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
3215{
3216 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3217
3218 return qpnp_chg_is_boost_en_set(chip);
3219}
3220
3221static int
3222qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
3223 int min_uV, int max_uV, unsigned *selector)
3224{
3225 int uV = min_uV;
3226 int rc;
3227 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3228
3229 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
3230 uV = BOOST_MIN_UV;
3231
3232
3233 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
3234 pr_err("request %d uV is out of bounds\n", uV);
3235 return -EINVAL;
3236 }
3237
3238 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
3239 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
3240 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
3241 return -EINVAL;
3242 }
3243
3244 rc = qpnp_boost_vset(chip, uV);
3245
3246 return rc;
3247}
3248
3249static int
3250qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
3251{
3252 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3253
3254 return qpnp_boost_vget_uv(chip);
3255}
3256
3257static int
3258qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
3259 unsigned selector)
3260{
3261 if (selector >= N_BOOST_V)
3262 return 0;
3263
3264 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
3265}
3266
3267static struct regulator_ops qpnp_chg_otg_reg_ops = {
3268 .enable = qpnp_chg_regulator_otg_enable,
3269 .disable = qpnp_chg_regulator_otg_disable,
3270 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
3271};
3272
3273static struct regulator_ops qpnp_chg_boost_reg_ops = {
3274 .enable = qpnp_chg_regulator_boost_enable,
3275 .disable = qpnp_chg_regulator_boost_disable,
3276 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
3277 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
3278 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
3279 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
3280};
3281
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003282static int
David Keitel6e63bd52013-09-06 18:00:03 -07003283qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003284{
David Keitel9eca8ac2013-09-06 14:18:36 -07003285 int rc = 0;
David Keitel6e63bd52013-09-06 18:00:03 -07003286 u8 reg = 0;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003287
David Keitelcadbc282013-09-26 11:39:14 -07003288 if (!chip->bat_if_base)
3289 return rc;
3290
David Keitel9eca8ac2013-09-06 14:18:36 -07003291 if (chip->type == SMBB)
3292 rc = qpnp_chg_read(chip, &reg,
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003293 chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
David Keitel9eca8ac2013-09-06 14:18:36 -07003294 else
3295 rc = qpnp_chg_read(chip, &reg,
3296 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
David Keitel6e63bd52013-09-06 18:00:03 -07003297
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003298 if (rc) {
3299 pr_err("failed to read batt_if rc=%d\n", rc);
3300 return rc;
3301 }
3302
David Keitel6e63bd52013-09-06 18:00:03 -07003303 if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003304 return 1;
3305
3306 return 0;
3307}
3308
David Keitel6e63bd52013-09-06 18:00:03 -07003309static int
3310qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
3311{
3312 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3313 int rc = 0;
3314
3315 mutex_lock(&chip->batfet_vreg_lock);
3316 /* Only enable if not already enabled */
3317 if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
3318 rc = qpnp_chg_regulator_batfet_set(chip, 1);
3319 if (rc)
3320 pr_err("failed to write to batt_if rc=%d\n", rc);
3321 }
3322
3323 chip->batfet_ext_en = true;
3324 mutex_unlock(&chip->batfet_vreg_lock);
3325
3326 return rc;
3327}
3328
3329static int
3330qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
3331{
3332 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3333 int rc = 0;
3334
3335 mutex_lock(&chip->batfet_vreg_lock);
3336 /* Don't allow disable if charger connected */
3337 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3338 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3339 rc = qpnp_chg_regulator_batfet_set(chip, 0);
3340 if (rc)
3341 pr_err("failed to write to batt_if rc=%d\n", rc);
3342 }
3343
3344 chip->batfet_ext_en = false;
3345 mutex_unlock(&chip->batfet_vreg_lock);
3346
3347 return rc;
3348}
3349
3350static int
3351qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
3352{
3353 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3354
3355 return chip->batfet_ext_en;
3356}
3357
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003358static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
3359 .enable = qpnp_chg_regulator_batfet_enable,
3360 .disable = qpnp_chg_regulator_batfet_disable,
3361 .is_enabled = qpnp_chg_regulator_batfet_is_enabled,
3362};
3363
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003364#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 8
3365#define MAX_DELTA_VDD_MAX_MV 80
3366#define VDD_MAX_CENTER_OFFSET 4
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003367static void
3368qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
3369{
3370 int delta_mv, closest_delta_mv, sign;
3371
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003372 delta_mv = chip->max_voltage_mv - VDD_MAX_CENTER_OFFSET - vbat_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003373 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
3374 pr_debug("vbat is not low enough to increase vdd\n");
3375 return;
3376 }
3377
3378 sign = delta_mv > 0 ? 1 : -1;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003379 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_BUCK_TRIM1_STEP / 2)
3380 / QPNP_CHG_BUCK_TRIM1_STEP) * QPNP_CHG_BUCK_TRIM1_STEP;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003381 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
3382 chip->max_voltage_mv, vbat_mv,
3383 delta_mv, closest_delta_mv);
3384 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
3385 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
3386 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
3387 qpnp_chg_set_appropriate_vddmax(chip);
3388}
3389
David Keitel9fd07382013-05-02 15:37:44 -07003390#define CONSECUTIVE_COUNT 3
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003391#define VBATDET_MAX_ERR_MV 50
David Keitel9fd07382013-05-02 15:37:44 -07003392static void
3393qpnp_eoc_work(struct work_struct *work)
3394{
3395 struct delayed_work *dwork = to_delayed_work(work);
3396 struct qpnp_chg_chip *chip = container_of(dwork,
3397 struct qpnp_chg_chip, eoc_work);
3398 static int count;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003399 static int vbat_low_count;
David Keitel9fd07382013-05-02 15:37:44 -07003400 int ibat_ma, vbat_mv, rc = 0;
3401 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003402 bool vbat_lower_than_vbatdet;
David Keitel9fd07382013-05-02 15:37:44 -07003403
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003404 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003405 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3406
3407 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
3408 if (rc) {
3409 pr_err("failed to read batt_if rc=%d\n", rc);
3410 return;
3411 }
3412
3413 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
3414 if (rc) {
3415 pr_err("failed to read buck rc=%d\n", rc);
3416 return;
3417 }
3418
3419 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
3420 if (rc) {
3421 pr_err("failed to read chg_sts rc=%d\n", rc);
3422 return;
3423 }
3424
3425 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
3426 chg_sts, batt_sts, buck_sts);
3427
3428 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3429 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3430 pr_debug("no chg connected, stopping\n");
3431 goto stop_eoc;
3432 }
3433
3434 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
3435 || chg_sts & TRKL_CHG_ON_IRQ)) {
3436 ibat_ma = get_prop_current_now(chip) / 1000;
3437 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003438
3439 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
3440 ibat_ma, vbat_mv, chip->term_current);
3441
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003442 vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
3443 if (vbat_lower_than_vbatdet && vbat_mv <
3444 (chip->max_voltage_mv - chip->resume_delta_mv
David Keitelbdbae452014-01-14 17:19:50 -08003445 - chip->vbatdet_max_err_mv)) {
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003446 vbat_low_count++;
3447 pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
3448 vbat_mv, chip->max_voltage_mv,
3449 chip->resume_delta_mv,
David Keitelbdbae452014-01-14 17:19:50 -08003450 chip->vbatdet_max_err_mv,
3451 vbat_low_count);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003452 if (vbat_low_count >= CONSECUTIVE_COUNT) {
3453 pr_debug("woke up too early stopping\n");
3454 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
3455 goto stop_eoc;
3456 } else {
3457 goto check_again_later;
3458 }
3459 } else {
3460 vbat_low_count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003461 }
3462
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003463 if (buck_sts & VDD_LOOP_IRQ)
3464 qpnp_chg_adjust_vddmax(chip, vbat_mv);
3465
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003466 if (!(buck_sts & VDD_LOOP_IRQ)) {
3467 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07003468 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003469 } else if ((ibat_ma * -1) > chip->term_current) {
3470 pr_debug("Not at EOC, battery current too high\n");
3471 count = 0;
3472 } else if (ibat_ma > 0) {
3473 pr_debug("Charging but system demand increased\n");
3474 count = 0;
3475 } else {
David Keitel9fd07382013-05-02 15:37:44 -07003476 if (count == CONSECUTIVE_COUNT) {
Xiaozhe Shie8504482013-10-30 18:10:31 -07003477 if (!chip->bat_is_cool && !chip->bat_is_warm) {
3478 pr_info("End of Charging\n");
3479 chip->chg_done = true;
3480 } else {
3481 pr_info("stop charging: battery is %s, vddmax = %d reached\n",
3482 chip->bat_is_cool
3483 ? "cool" : "warm",
3484 qpnp_chg_vddmax_get(chip));
3485 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003486 chip->delta_vddmax_mv = 0;
3487 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel9fd07382013-05-02 15:37:44 -07003488 qpnp_chg_charge_en(chip, 0);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003489 /* sleep for a second before enabling */
3490 msleep(2000);
3491 qpnp_chg_charge_en(chip,
3492 !chip->charging_disabled);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003493 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07003494 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07003495 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07003496 goto stop_eoc;
3497 } else {
3498 count += 1;
3499 pr_debug("EOC count = %d\n", count);
3500 }
David Keitel9fd07382013-05-02 15:37:44 -07003501 }
3502 } else {
3503 pr_debug("not charging\n");
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003504 goto stop_eoc;
David Keitel9fd07382013-05-02 15:37:44 -07003505 }
3506
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003507check_again_later:
David Keitel9fd07382013-05-02 15:37:44 -07003508 schedule_delayed_work(&chip->eoc_work,
3509 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
3510 return;
3511
3512stop_eoc:
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003513 vbat_low_count = 0;
David Keitel9fd07382013-05-02 15:37:44 -07003514 count = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003515 pm_relax(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003516}
3517
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003518static void
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07003519qpnp_chg_insertion_ocv_work(struct work_struct *work)
3520{
3521 struct qpnp_chg_chip *chip = container_of(work,
3522 struct qpnp_chg_chip, insertion_ocv_work);
3523 u8 bat_if_sts = 0, charge_en = 0;
3524 int rc;
3525
3526 chip->insertion_ocv_uv = get_prop_battery_voltage_now(chip);
3527
3528 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
3529 if (rc)
3530 pr_err("failed to read bat_if sts %d\n", rc);
3531
3532 rc = qpnp_chg_read(chip, &charge_en,
3533 chip->chgr_base + CHGR_CHG_CTRL, 1);
3534 if (rc)
3535 pr_err("failed to read bat_if sts %d\n", rc);
3536
3537 pr_debug("batfet sts = %02x, charge_en = %02x ocv = %d\n",
3538 bat_if_sts, charge_en, chip->insertion_ocv_uv);
3539 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3540 pr_debug("psy changed batt_psy\n");
3541 power_supply_changed(&chip->batt_psy);
3542}
3543
3544static void
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003545qpnp_chg_soc_check_work(struct work_struct *work)
3546{
3547 struct qpnp_chg_chip *chip = container_of(work,
3548 struct qpnp_chg_chip, soc_check_work);
3549
3550 get_prop_capacity(chip);
3551}
3552
David Keitel0c1a4532013-03-21 16:39:06 -07003553#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08003554static void
3555qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
3556{
3557 struct qpnp_chg_chip *chip = ctx;
3558 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07003559 int temp;
David Keitel454ee842013-03-08 16:19:11 -08003560
3561 if (state >= ADC_TM_STATE_NUM) {
3562 pr_err("invalid notification %d\n", state);
3563 return;
3564 }
3565
David Keitel1219a802013-03-21 16:37:21 -07003566 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08003567
David Keitel1219a802013-03-21 16:37:21 -07003568 pr_debug("temp = %d state = %s\n", temp,
3569 state == ADC_TM_WARM_STATE ? "warm" : "cool");
3570
3571 if (state == ADC_TM_WARM_STATE) {
David Keitel410ee0d2014-02-20 16:48:04 -08003572 if (temp >= chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003573 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08003574 bat_warm = true;
3575 bat_cool = false;
3576 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003577 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003578 chip->adc_param.state_request =
3579 ADC_TM_COOL_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08003580 } else if (temp >=
David Keitel1219a802013-03-21 16:37:21 -07003581 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003582 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08003583 bat_warm = false;
3584 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07003585
3586 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07003587 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003588 chip->adc_param.state_request =
3589 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003590 }
3591 } else {
David Keitel410ee0d2014-02-20 16:48:04 -08003592 if (temp <= chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003593 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08003594 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003595 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08003596 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003597 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003598 chip->adc_param.state_request =
3599 ADC_TM_WARM_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08003600 } else if (temp <=
David Keitel1219a802013-03-21 16:37:21 -07003601 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003602 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08003603 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003604 bat_cool = false;
3605
David Keitel0c1a4532013-03-21 16:39:06 -07003606 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003607 chip->adc_param.high_temp = chip->warm_bat_decidegc;
3608 chip->adc_param.state_request =
3609 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003610 }
3611 }
3612
3613 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07003614 chip->bat_is_cool = bat_cool;
3615 chip->bat_is_warm = bat_warm;
3616
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07003617 /**
3618 * set appropriate voltages and currents.
3619 *
3620 * Note that when the battery is hot or cold, the charger
3621 * driver will not resume with SoC. Only vbatdet is used to
3622 * determine resume of charging.
3623 */
David Keitel59fbb762014-02-05 16:46:24 -08003624 if (bat_cool || bat_warm) {
3625 chip->resuming_charging = false;
3626 qpnp_chg_set_appropriate_vbatdet(chip);
3627
3628 /* To avoid ARB, only vbatdet is configured in
3629 * warm/cold zones. Once vbat < vbatdet the
3630 * appropriate vddmax/ibatmax adjustments will
3631 * be made in the fast charge interrupt. */
3632 bypass_vbatdet_comp(chip, 1);
3633 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3634 qpnp_chg_charge_en(chip, chip->charging_disabled);
3635 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3636 } else {
3637 bypass_vbatdet_comp(chip, 0);
3638 /* restore normal parameters */
3639 qpnp_chg_set_appropriate_vbatdet(chip);
3640 qpnp_chg_set_appropriate_vddmax(chip);
3641 qpnp_chg_set_appropriate_battery_current(chip);
3642 }
David Keitel454ee842013-03-08 16:19:11 -08003643 }
3644
David Keitelec3c09802013-06-13 13:05:30 -07003645 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
3646 chip->bat_is_warm, chip->bat_is_cool,
3647 chip->adc_param.low_temp, chip->adc_param.high_temp);
3648
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003649 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07003650 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07003651}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07003652
David Keitelec3c09802013-06-13 13:05:30 -07003653#define MIN_COOL_TEMP -300
3654#define MAX_WARM_TEMP 1000
3655
3656static int
3657qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
3658 enum power_supply_property psp, int temp_degc)
3659{
3660 int rc = 0;
3661
3662 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
3663 pr_err("Bad temperature request %d\n", temp_degc);
3664 return -EINVAL;
3665 }
3666
3667 mutex_lock(&chip->jeita_configure_lock);
3668 switch (psp) {
3669 case POWER_SUPPLY_PROP_COOL_TEMP:
3670 if (temp_degc >=
3671 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
3672 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
3673 temp_degc, chip->warm_bat_decidegc,
3674 HYSTERISIS_DECIDEGC);
3675 rc = -EINVAL;
3676 goto mutex_unlock;
3677 }
3678 if (chip->bat_is_cool)
3679 chip->adc_param.high_temp =
3680 temp_degc + HYSTERISIS_DECIDEGC;
3681 else if (!chip->bat_is_warm)
3682 chip->adc_param.low_temp = temp_degc;
3683
3684 chip->cool_bat_decidegc = temp_degc;
3685 break;
3686 case POWER_SUPPLY_PROP_WARM_TEMP:
3687 if (temp_degc <=
3688 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
3689 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
3690 temp_degc, chip->warm_bat_decidegc,
3691 HYSTERISIS_DECIDEGC);
3692 rc = -EINVAL;
3693 goto mutex_unlock;
3694 }
3695 if (chip->bat_is_warm)
3696 chip->adc_param.low_temp =
3697 temp_degc - HYSTERISIS_DECIDEGC;
3698 else if (!chip->bat_is_cool)
3699 chip->adc_param.high_temp = temp_degc;
3700
3701 chip->warm_bat_decidegc = temp_degc;
3702 break;
3703 default:
3704 rc = -EINVAL;
3705 goto mutex_unlock;
3706 }
3707
3708 schedule_work(&chip->adc_measure_work);
3709
3710mutex_unlock:
3711 mutex_unlock(&chip->jeita_configure_lock);
3712 return rc;
David Keitel454ee842013-03-08 16:19:11 -08003713}
3714
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003715#define POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS 20
3716#define POWER_STAGE_REDUCE_MAX_VBAT_UV 3900000
3717#define POWER_STAGE_REDUCE_MIN_VCHG_UV 4800000
3718#define POWER_STAGE_SEL_MASK 0x0F
3719#define POWER_STAGE_REDUCED 0x01
3720#define POWER_STAGE_DEFAULT 0x0F
3721static bool
3722qpnp_chg_is_power_stage_reduced(struct qpnp_chg_chip *chip)
3723{
3724 int rc;
3725 u8 reg;
3726
3727 rc = qpnp_chg_read(chip, &reg,
3728 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3729 1);
3730 if (rc) {
3731 pr_err("Error %d reading power stage register\n", rc);
3732 return false;
3733 }
3734
3735 if ((reg & POWER_STAGE_SEL_MASK) == POWER_STAGE_DEFAULT)
3736 return false;
3737
3738 return true;
3739}
3740
3741static int
3742qpnp_chg_power_stage_set(struct qpnp_chg_chip *chip, bool reduce)
3743{
3744 int rc;
3745 u8 reg = 0xA5;
3746
3747 rc = qpnp_chg_write(chip, &reg,
3748 chip->buck_base + SEC_ACCESS,
3749 1);
3750 if (rc) {
3751 pr_err("Error %d writing 0xA5 to buck's 0x%x reg\n",
3752 rc, SEC_ACCESS);
3753 return rc;
3754 }
3755
3756 reg = POWER_STAGE_DEFAULT;
3757 if (reduce)
3758 reg = POWER_STAGE_REDUCED;
3759 rc = qpnp_chg_write(chip, &reg,
3760 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3761 1);
3762
3763 if (rc)
3764 pr_err("Error %d writing 0x%x power stage register\n", rc, reg);
3765 return rc;
3766}
3767
3768static int
3769qpnp_chg_get_vusbin_uv(struct qpnp_chg_chip *chip)
3770{
3771 int rc = 0;
3772 struct qpnp_vadc_result results;
3773
3774 rc = qpnp_vadc_read(chip->vadc_dev, USBIN, &results);
3775 if (rc) {
3776 pr_err("Unable to read vbat rc=%d\n", rc);
3777 return 0;
3778 }
3779 return results.physical;
3780}
3781
3782static
3783int get_vusb_averaged(struct qpnp_chg_chip *chip, int sample_count)
3784{
3785 int vusb_uv = 0;
3786 int i;
3787
3788 /* avoid overflows */
3789 if (sample_count > 256)
3790 sample_count = 256;
3791
3792 for (i = 0; i < sample_count; i++)
3793 vusb_uv += qpnp_chg_get_vusbin_uv(chip);
3794
3795 vusb_uv = vusb_uv / sample_count;
3796 return vusb_uv;
3797}
3798
3799static
3800int get_vbat_averaged(struct qpnp_chg_chip *chip, int sample_count)
3801{
3802 int vbat_uv = 0;
3803 int i;
3804
3805 /* avoid overflows */
3806 if (sample_count > 256)
3807 sample_count = 256;
3808
3809 for (i = 0; i < sample_count; i++)
3810 vbat_uv += get_prop_battery_voltage_now(chip);
3811
3812 vbat_uv = vbat_uv / sample_count;
3813 return vbat_uv;
3814}
3815
3816static void
3817qpnp_chg_reduce_power_stage(struct qpnp_chg_chip *chip)
3818{
3819 struct timespec ts;
3820 bool power_stage_reduced_in_hw = qpnp_chg_is_power_stage_reduced(chip);
3821 bool reduce_power_stage = false;
3822 int vbat_uv = get_vbat_averaged(chip, 16);
3823 int vusb_uv = get_vusb_averaged(chip, 16);
3824 bool fast_chg =
3825 (get_prop_charge_type(chip) == POWER_SUPPLY_CHARGE_TYPE_FAST);
3826 static int count_restore_power_stage;
3827 static int count_reduce_power_stage;
3828 bool vchg_loop = get_prop_vchg_loop(chip);
3829 bool ichg_loop = qpnp_chg_is_ichg_loop_active(chip);
3830 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
3831 bool usb_ma_above_wall =
3832 (qpnp_chg_usb_iusbmax_get(chip) > USB_WALL_THRESHOLD_MA);
3833
3834 if (fast_chg
3835 && usb_present
3836 && usb_ma_above_wall
3837 && vbat_uv < POWER_STAGE_REDUCE_MAX_VBAT_UV
3838 && vusb_uv > POWER_STAGE_REDUCE_MIN_VCHG_UV)
3839 reduce_power_stage = true;
3840
3841 if ((usb_present && usb_ma_above_wall)
3842 && (vchg_loop || ichg_loop))
3843 reduce_power_stage = true;
3844
3845 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3846 count_restore_power_stage++;
3847 count_reduce_power_stage = 0;
3848 } else if (!power_stage_reduced_in_hw && reduce_power_stage) {
3849 count_reduce_power_stage++;
3850 count_restore_power_stage = 0;
3851 } else if (power_stage_reduced_in_hw == reduce_power_stage) {
3852 count_restore_power_stage = 0;
3853 count_reduce_power_stage = 0;
3854 }
3855
3856 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",
3857 power_stage_reduced_in_hw, reduce_power_stage,
3858 usb_present, usb_ma_above_wall,
3859 vbat_uv, vusb_uv, fast_chg,
3860 ichg_loop, vchg_loop,
3861 count_restore_power_stage, count_reduce_power_stage);
3862
3863 if (!power_stage_reduced_in_hw && reduce_power_stage) {
3864 if (count_reduce_power_stage >= 2) {
3865 qpnp_chg_power_stage_set(chip, true);
3866 power_stage_reduced_in_hw = true;
3867 }
3868 }
3869
3870 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3871 if (count_restore_power_stage >= 6
3872 || (!usb_present || !usb_ma_above_wall)) {
3873 qpnp_chg_power_stage_set(chip, false);
3874 power_stage_reduced_in_hw = false;
3875 }
3876 }
3877
3878 if (usb_present && usb_ma_above_wall) {
3879 getnstimeofday(&ts);
3880 ts.tv_sec += POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS;
3881 alarm_start_range(&chip->reduce_power_stage_alarm,
3882 timespec_to_ktime(ts),
3883 timespec_to_ktime(ts));
3884 } else {
3885 pr_debug("stopping power stage workaround\n");
3886 chip->power_stage_workaround_running = false;
3887 }
3888}
3889
3890static void
David Keitel6e63bd52013-09-06 18:00:03 -07003891qpnp_chg_batfet_lcl_work(struct work_struct *work)
3892{
3893 struct qpnp_chg_chip *chip = container_of(work,
3894 struct qpnp_chg_chip, batfet_lcl_work);
3895
3896 mutex_lock(&chip->batfet_vreg_lock);
3897 if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
3898 qpnp_chg_is_dc_chg_plugged_in(chip)) {
3899 qpnp_chg_regulator_batfet_set(chip, 1);
3900 pr_debug("disabled ULPM\n");
3901 } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
3902 && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3903 qpnp_chg_regulator_batfet_set(chip, 0);
3904 pr_debug("enabled ULPM\n");
3905 }
3906 mutex_unlock(&chip->batfet_vreg_lock);
3907}
3908
3909static void
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003910qpnp_chg_reduce_power_stage_work(struct work_struct *work)
3911{
3912 struct qpnp_chg_chip *chip = container_of(work,
3913 struct qpnp_chg_chip, reduce_power_stage_work);
3914
3915 qpnp_chg_reduce_power_stage(chip);
3916}
3917
3918static void
3919qpnp_chg_reduce_power_stage_callback(struct alarm *alarm)
3920{
3921 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
3922 reduce_power_stage_alarm);
3923
3924 schedule_work(&chip->reduce_power_stage_work);
3925}
3926
David Keitelbe208252013-01-31 14:49:25 -08003927static int
David Keitel432e1232013-06-05 16:10:18 -07003928qpnp_dc_power_set_property(struct power_supply *psy,
3929 enum power_supply_property psp,
3930 const union power_supply_propval *val)
3931{
3932 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3933 dc_psy);
3934 int rc = 0;
3935
3936 switch (psp) {
3937 case POWER_SUPPLY_PROP_CURRENT_MAX:
3938 if (!val->intval)
3939 break;
3940
3941 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
3942 if (rc) {
3943 pr_err("Error setting idcmax property %d\n", rc);
3944 return rc;
3945 }
3946 chip->maxinput_dc_ma = (val->intval / 1000);
3947
3948 break;
3949 default:
3950 return -EINVAL;
3951 }
3952
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003953 pr_debug("psy changed dc_psy\n");
David Keitel432e1232013-06-05 16:10:18 -07003954 power_supply_changed(&chip->dc_psy);
3955 return rc;
3956}
3957
3958static int
David Keitelbe208252013-01-31 14:49:25 -08003959qpnp_batt_power_set_property(struct power_supply *psy,
3960 enum power_supply_property psp,
3961 const union power_supply_propval *val)
3962{
3963 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3964 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07003965 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08003966
3967 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07003968 case POWER_SUPPLY_PROP_COOL_TEMP:
3969 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3970 break;
3971 case POWER_SUPPLY_PROP_WARM_TEMP:
3972 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3973 break;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08003974 case POWER_SUPPLY_PROP_CAPACITY:
3975 chip->fake_battery_soc = val->intval;
3976 power_supply_changed(&chip->batt_psy);
3977 break;
David Keitelbe208252013-01-31 14:49:25 -08003978 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
3979 chip->charging_disabled = !(val->intval);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003980 if (chip->charging_disabled) {
3981 /* disable charging */
3982 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3983 qpnp_chg_force_run_on_batt(chip,
3984 chip->charging_disabled);
3985 } else {
3986 /* enable charging */
3987 qpnp_chg_force_run_on_batt(chip,
3988 chip->charging_disabled);
3989 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3990 }
David Keitelbe208252013-01-31 14:49:25 -08003991 break;
3992 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
3993 qpnp_batt_system_temp_level_set(chip, val->intval);
3994 break;
David Keitel337bd862013-07-15 21:42:58 -07003995 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel7b0568482013-12-02 14:47:42 -08003996 if (qpnp_chg_is_usb_chg_plugged_in(chip))
3997 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
David Keitel337bd862013-07-15 21:42:58 -07003998 break;
David Keitel2586f0a2013-08-20 10:02:26 -07003999 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
4000 qpnp_chg_iusb_trim_set(chip, val->intval);
4001 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004002 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
4003 qpnp_chg_input_current_settled(chip);
4004 break;
David Keitel337bd862013-07-15 21:42:58 -07004005 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
4006 qpnp_chg_vinmin_set(chip, val->intval / 1000);
4007 break;
David Keitelbe208252013-01-31 14:49:25 -08004008 default:
4009 return -EINVAL;
4010 }
4011
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004012 pr_debug("psy changed batt_psy\n");
David Keitelbe208252013-01-31 14:49:25 -08004013 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004014 return rc;
David Keitelbe208252013-01-31 14:49:25 -08004015}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004016
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004017static int
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004018qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07004019{
David Keitelfe51cb92013-04-02 19:42:58 -07004020 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07004021 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07004022 if (chip->type == SMBB)
4023 chip->flags |= BOOST_FLASH_WA;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004024 if (chip->type == SMBBP) {
4025 struct device_node *revid_dev_node;
4026 struct pmic_revid_data *revid_data;
4027
4028 chip->flags |= BOOST_FLASH_WA;
4029
4030 revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
4031 "qcom,pmic-revid", 0);
4032 if (!revid_dev_node) {
4033 pr_err("Missing qcom,pmic-revid property\n");
4034 return -EINVAL;
4035 }
4036 revid_data = get_revid_data(revid_dev_node);
4037 if (IS_ERR(revid_data)) {
4038 pr_err("Couldnt get revid data rc = %ld\n",
4039 PTR_ERR(revid_data));
4040 return PTR_ERR(revid_data);
4041 }
4042
4043 if (revid_data->rev4 < PM8226_V2P1_REV4
4044 || ((revid_data->rev4 == PM8226_V2P1_REV4)
4045 && (revid_data->rev3 <= PM8226_V2P1_REV3))) {
4046 chip->flags |= POWER_STAGE_WA;
4047 }
4048 }
4049 return 0;
David Keiteld681cda2012-10-02 15:44:21 -07004050}
4051
David Keitel0f35be42013-04-16 11:10:40 -07004052static int
4053qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
4054{
4055 int rc = 0;
4056 struct resource *resource;
4057 struct spmi_resource *spmi_resource;
4058 u8 subtype;
4059 struct spmi_device *spmi = chip->spmi;
4060
4061 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
4062 if (!spmi_resource) {
4063 pr_err("qpnp_chg: spmi resource absent\n");
4064 return rc;
4065 }
4066
4067 resource = spmi_get_resource(spmi, spmi_resource,
4068 IORESOURCE_MEM, 0);
4069 if (!(resource && resource->start)) {
4070 pr_err("node %s IO resource absent!\n",
4071 spmi->dev.of_node->full_name);
4072 return rc;
4073 }
4074
4075 rc = qpnp_chg_read(chip, &subtype,
4076 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4077 if (rc) {
4078 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4079 return rc;
4080 }
4081
4082 switch (subtype) {
4083 case SMBB_CHGR_SUBTYPE:
4084 case SMBBP_CHGR_SUBTYPE:
4085 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004086 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004087 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004088 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004089 pr_err("Unable to get fast-chg-on irq\n");
4090 return rc;
4091 }
4092
David Keitel47185a62013-05-15 18:54:10 -07004093 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004094 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004095 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004096 pr_err("Unable to get trkl-chg-on irq\n");
4097 return rc;
4098 }
4099
David Keitel47185a62013-05-15 18:54:10 -07004100 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004101 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07004102 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004103 pr_err("Unable to get chg_failed irq\n");
4104 return rc;
4105 }
4106
David Keitel47185a62013-05-15 18:54:10 -07004107 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07004108 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07004109 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07004110 pr_err("Unable to get fast-chg-on irq\n");
4111 return rc;
4112 }
4113
David Keitel47185a62013-05-15 18:54:10 -07004114 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004115 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07004116 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004117 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004118 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004119 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004120 return rc;
4121 }
4122
David Keitel47185a62013-05-15 18:54:10 -07004123 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004124 qpnp_chg_chgr_chg_fastchg_irq_handler,
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08004125 IRQF_TRIGGER_RISING |
4126 IRQF_TRIGGER_FALLING,
David Keitel0f35be42013-04-16 11:10:40 -07004127 "fast-chg-on", chip);
4128 if (rc < 0) {
4129 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004130 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004131 return rc;
4132 }
4133
David Keitel47185a62013-05-15 18:54:10 -07004134 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004135 qpnp_chg_chgr_chg_trklchg_irq_handler,
4136 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004137 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004138 if (rc < 0) {
4139 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004140 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004141 return rc;
4142 }
David Keitel9fd07382013-05-02 15:37:44 -07004143
4144 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07004145 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07004146 qpnp_chg_vbatdet_lo_irq_handler,
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004147 IRQF_TRIGGER_RISING,
David Keitel9fd07382013-05-02 15:37:44 -07004148 "vbat-det-lo", chip);
4149 if (rc < 0) {
4150 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004151 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07004152 return rc;
4153 }
4154
David Keitelbf6a1062014-01-23 10:57:36 -08004155 qpnp_chg_irq_wake_enable(&chip->chg_trklchg);
4156 qpnp_chg_irq_wake_enable(&chip->chg_failed);
David Keitel47185a62013-05-15 18:54:10 -07004157 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitelbf6a1062014-01-23 10:57:36 -08004158 qpnp_chg_irq_wake_enable(&chip->chg_vbatdet_lo);
David Keitel0f35be42013-04-16 11:10:40 -07004159
4160 break;
4161 case SMBB_BAT_IF_SUBTYPE:
4162 case SMBBP_BAT_IF_SUBTYPE:
4163 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004164 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004165 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07004166 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004167 pr_err("Unable to get batt-pres irq\n");
4168 return rc;
4169 }
David Keitel47185a62013-05-15 18:54:10 -07004170 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004171 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07004172 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
4173 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07004174 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004175 if (rc < 0) {
4176 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004177 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004178 return rc;
4179 }
4180
David Keitelbf6a1062014-01-23 10:57:36 -08004181 qpnp_chg_irq_wake_enable(&chip->batt_pres);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004182
4183 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
4184 spmi_resource, "bat-temp-ok");
4185 if (chip->batt_temp_ok.irq < 0) {
4186 pr_err("Unable to get bat-temp-ok irq\n");
4187 return rc;
4188 }
4189 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
4190 qpnp_chg_bat_if_batt_temp_irq_handler,
4191 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4192 "bat-temp-ok", chip);
4193 if (rc < 0) {
4194 pr_err("Can't request %d bat-temp-ok irq: %d\n",
4195 chip->batt_temp_ok.irq, rc);
4196 return rc;
4197 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08004198 qpnp_chg_bat_if_batt_temp_irq_handler(0, chip);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004199
David Keitelbf6a1062014-01-23 10:57:36 -08004200 qpnp_chg_irq_wake_enable(&chip->batt_temp_ok);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004201
David Keitel0f35be42013-04-16 11:10:40 -07004202 break;
David Keitel337bd862013-07-15 21:42:58 -07004203 case SMBB_BUCK_SUBTYPE:
4204 case SMBBP_BUCK_SUBTYPE:
4205 case SMBCL_BUCK_SUBTYPE:
David Keitel337bd862013-07-15 21:42:58 -07004206 break;
4207
David Keitel0f35be42013-04-16 11:10:40 -07004208 case SMBB_USB_CHGPTH_SUBTYPE:
4209 case SMBBP_USB_CHGPTH_SUBTYPE:
4210 case SMBCL_USB_CHGPTH_SUBTYPE:
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004211 if (chip->ovp_monitor_enable) {
4212 chip->coarse_det_usb.irq =
4213 spmi_get_irq_byname(spmi,
4214 spmi_resource, "coarse-det-usb");
4215 if (chip->coarse_det_usb.irq < 0) {
4216 pr_err("Can't get coarse-det irq\n");
4217 return rc;
4218 }
4219 rc = devm_request_irq(chip->dev,
4220 chip->coarse_det_usb.irq,
4221 qpnp_chg_coarse_det_usb_irq_handler,
4222 IRQF_TRIGGER_RISING |
4223 IRQF_TRIGGER_FALLING,
4224 "coarse-det-usb", chip);
4225 if (rc < 0) {
4226 pr_err("Can't req %d coarse-det: %d\n",
4227 chip->coarse_det_usb.irq, rc);
4228 return rc;
4229 }
4230 }
4231
David Keitel47185a62013-05-15 18:54:10 -07004232 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004233 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004234 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004235 pr_err("Unable to get usbin irq\n");
4236 return rc;
4237 }
David Keitel47185a62013-05-15 18:54:10 -07004238 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004239 qpnp_chg_usb_usbin_valid_irq_handler,
4240 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004241 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004242 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004243 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004244 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004245 return rc;
4246 }
David Keitel344c6972013-04-09 19:28:21 -07004247
David Keitel47185a62013-05-15 18:54:10 -07004248 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07004249 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07004250 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07004251 pr_err("Unable to get chg-gone irq\n");
4252 return rc;
4253 }
David Keitel47185a62013-05-15 18:54:10 -07004254 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07004255 qpnp_chg_usb_chg_gone_irq_handler,
4256 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07004257 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07004258 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004259 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004260 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07004261 return rc;
4262 }
David Keitel47185a62013-05-15 18:54:10 -07004263
David Keitel0b62bdd2013-07-10 17:30:51 -07004264 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4265 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4266 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
4267 spmi_resource, "usb-ocp");
4268 if (chip->usb_ocp.irq < 0) {
4269 pr_err("Unable to get usbin irq\n");
4270 return rc;
4271 }
4272 rc = devm_request_irq(chip->dev,
4273 chip->usb_ocp.irq,
4274 qpnp_chg_usb_usb_ocp_irq_handler,
4275 IRQF_TRIGGER_RISING, "usb-ocp", chip);
4276 if (rc < 0) {
4277 pr_err("Can't request %d usb-ocp: %d\n",
4278 chip->usb_ocp.irq, rc);
4279 return rc;
4280 }
4281
David Keitelbf6a1062014-01-23 10:57:36 -08004282 qpnp_chg_irq_wake_enable(&chip->usb_ocp);
David Keitel0b62bdd2013-07-10 17:30:51 -07004283 }
4284
David Keitelbf6a1062014-01-23 10:57:36 -08004285 qpnp_chg_irq_wake_enable(&chip->usbin_valid);
4286 qpnp_chg_irq_wake_enable(&chip->chg_gone);
David Keitel0f35be42013-04-16 11:10:40 -07004287 break;
4288 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004289 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004290 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004291 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004292 pr_err("Unable to get dcin irq\n");
4293 return -rc;
4294 }
David Keitel47185a62013-05-15 18:54:10 -07004295 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004296 qpnp_chg_dc_dcin_valid_irq_handler,
4297 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004298 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004299 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004300 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004301 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004302 return rc;
4303 }
4304
David Keitelbf6a1062014-01-23 10:57:36 -08004305 qpnp_chg_irq_wake_enable(&chip->dcin_valid);
David Keitel0f35be42013-04-16 11:10:40 -07004306 break;
4307 }
4308 }
4309
4310 return rc;
4311}
4312
Xiaozhe Shica289e02013-06-19 13:24:51 -07004313static int
4314qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
4315{
4316 struct bms_battery_data batt_data;
4317 struct device_node *node;
4318 struct qpnp_vadc_result result;
4319 int rc;
4320
4321 node = of_find_node_by_name(chip->spmi->dev.of_node,
4322 "qcom,battery-data");
4323 if (node) {
4324 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004325 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07004326 if (rc) {
4327 pr_err("error reading batt id channel = %d, rc = %d\n",
4328 LR_MUX2_BAT_ID, rc);
4329 return rc;
4330 }
4331
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07004332 batt_data.max_voltage_uv = -1;
4333 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07004334 rc = of_batterydata_read_data(node,
4335 &batt_data, result.physical);
4336 if (rc) {
4337 pr_err("failed to read battery data: %d\n", rc);
4338 return rc;
4339 }
4340
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004341 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07004342 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004343 chip->safe_voltage_mv = chip->max_voltage_mv
4344 + MAX_DELTA_VDD_MAX_MV;
4345 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004346 if (batt_data.iterm_ua >= 0)
4347 chip->term_current = batt_data.iterm_ua / 1000;
4348 }
4349
4350 return 0;
4351}
4352
David Keitel80668952012-07-27 14:25:49 -07004353#define WDOG_EN_BIT BIT(7)
4354static int
4355qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
4356 struct spmi_resource *spmi_resource)
4357{
4358 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004359 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07004360 struct regulator_init_data *init_data;
4361 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07004362
4363 switch (subtype) {
4364 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004365 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004366 case SMBCL_CHGR_SUBTYPE:
Prasad Sodagudic3678012013-09-23 12:01:19 +05304367 qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
4368
David Keitel80668952012-07-27 14:25:49 -07004369 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
4370 if (rc) {
4371 pr_debug("failed setting min_voltage rc=%d\n", rc);
4372 return rc;
4373 }
David Keitel80668952012-07-27 14:25:49 -07004374 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
4375 if (rc) {
4376 pr_debug("failed setting safe_voltage rc=%d\n", rc);
4377 return rc;
4378 }
David Keitel454ee842013-03-08 16:19:11 -08004379 rc = qpnp_chg_vbatdet_set(chip,
4380 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08004381 if (rc) {
4382 pr_debug("failed setting resume_voltage rc=%d\n", rc);
4383 return rc;
4384 }
David Keitel80668952012-07-27 14:25:49 -07004385 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
4386 if (rc) {
4387 pr_debug("failed setting ibatmax rc=%d\n", rc);
4388 return rc;
4389 }
David Keitel365c4c42013-03-08 16:20:40 -08004390 if (chip->term_current) {
4391 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
4392 if (rc) {
4393 pr_debug("failed setting ibatterm rc=%d\n", rc);
4394 return rc;
4395 }
David Keitel80668952012-07-27 14:25:49 -07004396 }
David Keitel5d44fa52012-12-03 16:37:31 -08004397 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
4398 if (rc) {
4399 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
4400 return rc;
4401 }
David Keitela4b7b592013-04-11 18:34:35 -07004402 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
4403 if (rc) {
4404 pr_debug("failed setting tchg_mins rc=%d\n", rc);
4405 return rc;
4406 }
4407
David Keitel80668952012-07-27 14:25:49 -07004408 /* HACK: Disable wdog */
4409 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
4410 0xFF, 0xA0, 1);
4411
David Keitelb4e43542013-04-09 17:30:41 -07004412 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07004413 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4414 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07004415 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07004416
David Keitel80668952012-07-27 14:25:49 -07004417 break;
4418 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004419 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004420 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004421 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
4422 if (rc)
4423 return rc;
4424
David Keitel9201df32013-01-10 18:38:34 -08004425 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07004426 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08004427 BUCK_VBAT_REG_NODE_SEL_BIT,
4428 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
4429 if (rc) {
4430 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
4431 return rc;
4432 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07004433
4434 rc = qpnp_chg_read(chip, &chip->trim_center,
4435 chip->buck_base + BUCK_CTRL_TRIM1, 1);
4436 if (rc) {
4437 pr_debug("failed to read trim center rc=%d\n", rc);
4438 return rc;
4439 }
4440 chip->trim_center >>= 4;
4441 pr_debug("trim center = %02x\n", chip->trim_center);
David Keitel80668952012-07-27 14:25:49 -07004442 break;
4443 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004444 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004445 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07004446 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07004447 switch (chip->bpd_detection) {
4448 case BPD_TYPE_BAT_THM:
4449 reg = BAT_THM_EN;
4450 break;
4451 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07004452 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07004453 break;
4454 case BPD_TYPE_BAT_THM_BAT_ID:
4455 reg = BAT_THM_EN | BAT_ID_EN;
4456 break;
4457 default:
4458 reg = BAT_THM_EN;
4459 break;
4460 }
David Keitel796882d2013-05-14 18:01:11 -07004461
4462 rc = qpnp_chg_masked_write(chip,
4463 chip->bat_if_base + BAT_IF_BPD_CTRL,
4464 BAT_IF_BPD_CTRL_SEL,
4465 reg, 1);
4466 if (rc) {
4467 pr_debug("failed to chose BPD rc=%d\n", rc);
4468 return rc;
4469 }
David Keitel85ae4342013-04-16 11:46:00 -07004470 /* Force on VREF_BAT_THM */
4471 rc = qpnp_chg_masked_write(chip,
4472 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4473 VREF_BATT_THERM_FORCE_ON,
4474 VREF_BATT_THERM_FORCE_ON, 1);
4475 if (rc) {
4476 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
4477 return rc;
4478 }
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07004479
4480 init_data = of_get_regulator_init_data(chip->dev,
4481 spmi_resource->of_node);
4482
4483 if (init_data->constraints.name) {
4484 rdesc = &(chip->batfet_vreg.rdesc);
4485 rdesc->owner = THIS_MODULE;
4486 rdesc->type = REGULATOR_VOLTAGE;
4487 rdesc->ops = &qpnp_chg_batfet_vreg_ops;
4488 rdesc->name = init_data->constraints.name;
4489
4490 init_data->constraints.valid_ops_mask
4491 |= REGULATOR_CHANGE_STATUS;
4492
4493 chip->batfet_vreg.rdev = regulator_register(rdesc,
4494 chip->dev, init_data, chip,
4495 spmi_resource->of_node);
4496 if (IS_ERR(chip->batfet_vreg.rdev)) {
4497 rc = PTR_ERR(chip->batfet_vreg.rdev);
4498 chip->batfet_vreg.rdev = NULL;
4499 if (rc != -EPROBE_DEFER)
4500 pr_err("batfet reg failed, rc=%d\n",
4501 rc);
4502 return rc;
4503 }
4504 }
David Keitel80668952012-07-27 14:25:49 -07004505 break;
4506 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004507 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004508 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004509 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07004510 rc = qpnp_chg_masked_write(chip,
4511 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4512 ENUM_T_STOP_BIT,
4513 ENUM_T_STOP_BIT, 1);
4514 if (rc) {
4515 pr_err("failed to write enum stop rc=%d\n", rc);
4516 return -ENXIO;
4517 }
4518 }
David Keiteld681cda2012-10-02 15:44:21 -07004519
David Keitel6dc4ed42013-05-17 11:08:58 -07004520 init_data = of_get_regulator_init_data(chip->dev,
4521 spmi_resource->of_node);
4522 if (!init_data) {
4523 pr_err("unable to allocate memory\n");
4524 return -ENOMEM;
4525 }
4526
4527 if (init_data->constraints.name) {
4528 if (of_get_property(chip->dev->of_node,
4529 "otg-parent-supply", NULL))
4530 init_data->supply_regulator = "otg-parent";
4531
4532 rdesc = &(chip->otg_vreg.rdesc);
4533 rdesc->owner = THIS_MODULE;
4534 rdesc->type = REGULATOR_VOLTAGE;
4535 rdesc->ops = &qpnp_chg_otg_reg_ops;
4536 rdesc->name = init_data->constraints.name;
4537
4538 init_data->constraints.valid_ops_mask
4539 |= REGULATOR_CHANGE_STATUS;
4540
4541 chip->otg_vreg.rdev = regulator_register(rdesc,
4542 chip->dev, init_data, chip,
4543 spmi_resource->of_node);
4544 if (IS_ERR(chip->otg_vreg.rdev)) {
4545 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004546 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004547 if (rc != -EPROBE_DEFER)
4548 pr_err("OTG reg failed, rc=%d\n", rc);
4549 return rc;
4550 }
4551 }
4552
David Keiteld681cda2012-10-02 15:44:21 -07004553 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08004554 chip->usb_chgpth_base + USB_OVP_CTL,
4555 USB_VALID_DEB_20MS,
4556 USB_VALID_DEB_20MS, 1);
4557
4558 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07004559 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4560 ENUM_T_STOP_BIT,
4561 ENUM_T_STOP_BIT, 1);
4562
David Keitel344c6972013-04-09 19:28:21 -07004563 rc = qpnp_chg_masked_write(chip,
4564 chip->usb_chgpth_base + SEC_ACCESS,
4565 0xFF,
4566 0xA5, 1);
4567
4568 rc = qpnp_chg_masked_write(chip,
4569 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
4570 0xFF,
4571 0x80, 1);
4572
David Keitel0b62bdd2013-07-10 17:30:51 -07004573 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4574 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4575 rc = qpnp_chg_masked_write(chip,
4576 chip->usb_chgpth_base + USB_OCP_THR,
4577 OCP_THR_MASK,
4578 OCP_THR_900_MA, 1);
4579 if (rc)
4580 pr_err("Failed to configure OCP rc = %d\n", rc);
4581 }
4582
David Keitel80668952012-07-27 14:25:49 -07004583 break;
4584 case SMBB_DC_CHGPTH_SUBTYPE:
4585 break;
4586 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004587 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07004588 init_data = of_get_regulator_init_data(chip->dev,
4589 spmi_resource->of_node);
4590 if (!init_data) {
4591 pr_err("unable to allocate memory\n");
4592 return -ENOMEM;
4593 }
4594
4595 if (init_data->constraints.name) {
4596 if (of_get_property(chip->dev->of_node,
4597 "boost-parent-supply", NULL))
4598 init_data->supply_regulator = "boost-parent";
4599
4600 rdesc = &(chip->boost_vreg.rdesc);
4601 rdesc->owner = THIS_MODULE;
4602 rdesc->type = REGULATOR_VOLTAGE;
4603 rdesc->ops = &qpnp_chg_boost_reg_ops;
4604 rdesc->name = init_data->constraints.name;
4605
4606 init_data->constraints.valid_ops_mask
4607 |= REGULATOR_CHANGE_STATUS
4608 | REGULATOR_CHANGE_VOLTAGE;
4609
4610 chip->boost_vreg.rdev = regulator_register(rdesc,
4611 chip->dev, init_data, chip,
4612 spmi_resource->of_node);
4613 if (IS_ERR(chip->boost_vreg.rdev)) {
4614 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004615 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004616 if (rc != -EPROBE_DEFER)
4617 pr_err("boost reg failed, rc=%d\n", rc);
4618 return rc;
4619 }
4620 }
David Keitel80668952012-07-27 14:25:49 -07004621 break;
4622 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004623 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004624 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07004625 if (subtype == SMBB_MISC_SUBTYPE)
4626 chip->type = SMBB;
4627 else if (subtype == SMBBP_MISC_SUBTYPE)
4628 chip->type = SMBBP;
4629 else if (subtype == SMBCL_MISC_SUBTYPE)
4630 chip->type = SMBCL;
4631
David Keitel80668952012-07-27 14:25:49 -07004632 pr_debug("Setting BOOT_DONE\n");
4633 rc = qpnp_chg_masked_write(chip,
4634 chip->misc_base + CHGR_MISC_BOOT_DONE,
4635 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004636 rc = qpnp_chg_read(chip, &reg,
4637 chip->misc_base + MISC_REVISION2, 1);
4638 if (rc) {
4639 pr_err("failed to read revision register rc=%d\n", rc);
4640 return rc;
4641 }
David Keitel80668952012-07-27 14:25:49 -07004642
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004643 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07004644 break;
4645 default:
4646 pr_err("Invalid peripheral subtype\n");
4647 }
4648 return rc;
4649}
4650
David Keitel112ba9c2013-04-12 18:40:43 -07004651#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
4652do { \
4653 if (retval) \
4654 break; \
4655 \
4656 retval = of_property_read_u32(chip->spmi->dev.of_node, \
4657 "qcom," qpnp_dt_property, \
4658 &chip->prop); \
4659 \
4660 if ((retval == -EINVAL) && optional) \
4661 retval = 0; \
4662 else if (retval) \
4663 pr_err("Error reading " #qpnp_dt_property \
4664 " property rc = %d\n", rc); \
4665} while (0)
4666
4667static int
4668qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
4669{
4670 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004671 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07004672
4673 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
4674 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
4675 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
4676 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
4677 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
4678 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
4679 if (rc)
4680 pr_err("failed to read required dt parameters %d\n", rc);
4681
4682 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
4683 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
4684 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
4685 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
4686 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07004687 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07004688 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
4689 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004690 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
Prasad Sodagudic3678012013-09-23 12:01:19 +05304691 OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
David Keitelbdbae452014-01-14 17:19:50 -08004692 OF_PROP_READ(chip, vbatdet_max_err_mv, "vbatdet-maxerr-mv", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004693
David Keitel112ba9c2013-04-12 18:40:43 -07004694 if (rc)
4695 return rc;
4696
David Keitel796882d2013-05-14 18:01:11 -07004697 rc = of_property_read_string(chip->spmi->dev.of_node,
4698 "qcom,bpd-detection", &bpd);
4699 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07004700 /* Select BAT_THM as default BPD scheme */
4701 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004702 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004703 } else {
4704 chip->bpd_detection = get_bpd(bpd);
4705 if (chip->bpd_detection < 0) {
4706 pr_err("failed to determine bpd schema %d\n", rc);
4707 return rc;
4708 }
4709 }
4710
David Keitelbdbae452014-01-14 17:19:50 -08004711 if (!chip->vbatdet_max_err_mv)
4712 chip->vbatdet_max_err_mv = VBATDET_MAX_ERR_MV;
4713
David Keitel112ba9c2013-04-12 18:40:43 -07004714 /* Look up JEITA compliance parameters if cool and warm temp provided */
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004715 if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004716 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
4717 if (IS_ERR(chip->adc_tm_dev)) {
4718 rc = PTR_ERR(chip->adc_tm_dev);
4719 if (rc != -EPROBE_DEFER)
4720 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07004721 return rc;
4722 }
4723
4724 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
4725 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
4726 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
4727 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
4728 if (rc)
4729 return rc;
4730 }
4731
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08004732 /* Get the use-external-rsense property */
4733 chip->use_external_rsense = of_property_read_bool(
4734 chip->spmi->dev.of_node,
4735 "qcom,use-external-rsense");
4736
David Keitel89c17752013-06-28 14:52:48 -07004737 /* Get the btc-disabled property */
4738 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4739 "qcom,btc-disabled");
4740
David Keitel2586f0a2013-08-20 10:02:26 -07004741 ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
4742 "qcom,ext-ovp-present");
4743
David Keitel112ba9c2013-04-12 18:40:43 -07004744 /* Get the charging-disabled property */
4745 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4746 "qcom,charging-disabled");
4747
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004748 chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
4749 "qcom,ovp-monitor-en");
4750
David Keitel8b68d2d2013-05-14 23:36:51 -07004751 /* Get the duty-cycle-100p property */
4752 chip->duty_cycle_100p = of_property_read_bool(
4753 chip->spmi->dev.of_node,
4754 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07004755
David Keitel112ba9c2013-04-12 18:40:43 -07004756 /* Get the fake-batt-values property */
4757 chip->use_default_batt_values =
4758 of_property_read_bool(chip->spmi->dev.of_node,
4759 "qcom,use-default-batt-values");
4760
4761 /* Disable charging when faking battery values */
4762 if (chip->use_default_batt_values)
4763 chip->charging_disabled = true;
4764
Zhenhua Huangdc335512013-10-30 11:45:15 +08004765 chip->power_stage_workaround_enable =
4766 of_property_read_bool(chip->spmi->dev.of_node,
4767 "qcom,power-stage-reduced");
4768
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004769 chip->ibat_calibration_enabled =
4770 of_property_read_bool(chip->spmi->dev.of_node,
4771 "qcom,ibat-calibration-enabled");
David Keitel975b5352014-01-27 14:28:04 -08004772 chip->parallel_ovp_mode =
4773 of_property_read_bool(chip->spmi->dev.of_node,
4774 "qcom,parallel-ovp-mode");
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004775
David Keitel112ba9c2013-04-12 18:40:43 -07004776 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
4777 &(chip->thermal_levels));
4778
4779 if (chip->thermal_levels > sizeof(int)) {
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304780 chip->thermal_mitigation = devm_kzalloc(chip->dev,
David Keitel112ba9c2013-04-12 18:40:43 -07004781 chip->thermal_levels,
4782 GFP_KERNEL);
4783
4784 if (chip->thermal_mitigation == NULL) {
4785 pr_err("thermal mitigation kzalloc() failed.\n");
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304786 return -ENOMEM;
David Keitel112ba9c2013-04-12 18:40:43 -07004787 }
4788
4789 chip->thermal_levels /= sizeof(int);
4790 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
4791 "qcom,thermal-mitigation",
4792 chip->thermal_mitigation, chip->thermal_levels);
4793 if (rc) {
4794 pr_err("qcom,thermal-mitigation missing in dt\n");
4795 return rc;
4796 }
4797 }
4798
4799 return rc;
4800}
4801
David Keitel80668952012-07-27 14:25:49 -07004802static int __devinit
4803qpnp_charger_probe(struct spmi_device *spmi)
4804{
4805 u8 subtype;
4806 struct qpnp_chg_chip *chip;
4807 struct resource *resource;
4808 struct spmi_resource *spmi_resource;
4809 int rc = 0;
4810
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304811 chip = devm_kzalloc(&spmi->dev,
4812 sizeof(struct qpnp_chg_chip), GFP_KERNEL);
David Keitel80668952012-07-27 14:25:49 -07004813 if (chip == NULL) {
4814 pr_err("kzalloc() failed.\n");
4815 return -ENOMEM;
4816 }
4817
David Keitelfd305ee2013-07-19 20:19:06 -07004818 chip->prev_usb_max_ma = -EINVAL;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08004819 chip->fake_battery_soc = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07004820 chip->dev = &(spmi->dev);
4821 chip->spmi = spmi;
4822
4823 chip->usb_psy = power_supply_get_by_name("usb");
4824 if (!chip->usb_psy) {
4825 pr_err("usb supply not found deferring probe\n");
4826 rc = -EPROBE_DEFER;
4827 goto fail_chg_enable;
4828 }
4829
David Keitelec3c09802013-06-13 13:05:30 -07004830 mutex_init(&chip->jeita_configure_lock);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004831 spin_lock_init(&chip->usbin_health_monitor_lock);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004832 alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
4833 qpnp_chg_reduce_power_stage_callback);
4834 INIT_WORK(&chip->reduce_power_stage_work,
4835 qpnp_chg_reduce_power_stage_work);
David Keitel6e63bd52013-09-06 18:00:03 -07004836 mutex_init(&chip->batfet_vreg_lock);
David Keitel8b9bd312014-01-15 14:44:00 -08004837 INIT_WORK(&chip->ocp_clear_work,
4838 qpnp_chg_ocp_clear_work);
David Keitel6e63bd52013-09-06 18:00:03 -07004839 INIT_WORK(&chip->batfet_lcl_work,
4840 qpnp_chg_batfet_lcl_work);
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004841 INIT_WORK(&chip->insertion_ocv_work,
4842 qpnp_chg_insertion_ocv_work);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004843
David Keitel112ba9c2013-04-12 18:40:43 -07004844 /* Get all device tree properties */
4845 rc = qpnp_charger_read_dt_props(chip);
4846 if (rc)
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304847 return rc;
David Keitel3dd5e0f2012-12-12 18:12:36 -08004848
Xiaozhe Shica289e02013-06-19 13:24:51 -07004849 /*
4850 * Check if bat_if is set in DT and make sure VADC is present
4851 * Also try loading the battery data profile if bat_if exists
4852 */
David Keiteldd87a172013-05-29 17:05:43 -07004853 spmi_for_each_container_dev(spmi_resource, spmi) {
4854 if (!spmi_resource) {
4855 pr_err("qpnp_chg: spmi resource absent\n");
4856 rc = -ENXIO;
4857 goto fail_chg_enable;
4858 }
4859
4860 resource = spmi_get_resource(spmi, spmi_resource,
4861 IORESOURCE_MEM, 0);
4862 if (!(resource && resource->start)) {
4863 pr_err("node %s IO resource absent!\n",
4864 spmi->dev.of_node->full_name);
4865 rc = -ENXIO;
4866 goto fail_chg_enable;
4867 }
4868
4869 rc = qpnp_chg_read(chip, &subtype,
4870 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4871 if (rc) {
4872 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4873 goto fail_chg_enable;
4874 }
4875
4876 if (subtype == SMBB_BAT_IF_SUBTYPE ||
4877 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004878 subtype == SMBCL_BAT_IF_SUBTYPE) {
4879 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
4880 if (IS_ERR(chip->vadc_dev)) {
4881 rc = PTR_ERR(chip->vadc_dev);
4882 if (rc != -EPROBE_DEFER)
4883 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07004884 goto fail_chg_enable;
David Keitel42648fd2013-08-16 17:45:20 -07004885 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004886
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08004887 if (subtype == SMBB_BAT_IF_SUBTYPE) {
4888 chip->iadc_dev = qpnp_get_iadc(chip->dev,
4889 "chg");
4890 if (IS_ERR(chip->iadc_dev)) {
4891 rc = PTR_ERR(chip->iadc_dev);
4892 if (rc != -EPROBE_DEFER)
4893 pr_err("iadc property missing\n");
4894 goto fail_chg_enable;
4895 }
4896 }
4897
Xiaozhe Shica289e02013-06-19 13:24:51 -07004898 rc = qpnp_chg_load_battery_data(chip);
4899 if (rc)
4900 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07004901 }
4902 }
4903
David Keitel80668952012-07-27 14:25:49 -07004904 spmi_for_each_container_dev(spmi_resource, spmi) {
4905 if (!spmi_resource) {
4906 pr_err("qpnp_chg: spmi resource absent\n");
4907 rc = -ENXIO;
4908 goto fail_chg_enable;
4909 }
4910
4911 resource = spmi_get_resource(spmi, spmi_resource,
4912 IORESOURCE_MEM, 0);
4913 if (!(resource && resource->start)) {
4914 pr_err("node %s IO resource absent!\n",
4915 spmi->dev.of_node->full_name);
4916 rc = -ENXIO;
4917 goto fail_chg_enable;
4918 }
4919
4920 rc = qpnp_chg_read(chip, &subtype,
4921 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4922 if (rc) {
4923 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4924 goto fail_chg_enable;
4925 }
4926
4927 switch (subtype) {
4928 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004929 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004930 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004931 chip->chgr_base = resource->start;
4932 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4933 if (rc) {
4934 pr_err("Failed to init subtype 0x%x rc=%d\n",
4935 subtype, rc);
4936 goto fail_chg_enable;
4937 }
4938 break;
4939 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004940 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004941 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004942 chip->buck_base = resource->start;
4943 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4944 if (rc) {
4945 pr_err("Failed to init subtype 0x%x rc=%d\n",
4946 subtype, rc);
4947 goto fail_chg_enable;
4948 }
David Keitel344c6972013-04-09 19:28:21 -07004949
4950 rc = qpnp_chg_masked_write(chip,
4951 chip->buck_base + SEC_ACCESS,
4952 0xFF,
4953 0xA5, 1);
4954
4955 rc = qpnp_chg_masked_write(chip,
4956 chip->buck_base + BUCK_VCHG_OV,
4957 0xff,
4958 0x00, 1);
4959
David Keiteldbc949b2013-07-11 10:56:03 -07004960 if (chip->duty_cycle_100p) {
4961 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
4962 1);
4963 if (rc) {
4964 pr_err("failed to set duty cycle %d\n",
4965 rc);
4966 goto fail_chg_enable;
4967 }
4968 }
4969
David Keitel80668952012-07-27 14:25:49 -07004970 break;
4971 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004972 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004973 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004974 chip->bat_if_base = resource->start;
4975 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4976 if (rc) {
4977 pr_err("Failed to init subtype 0x%x rc=%d\n",
4978 subtype, rc);
4979 goto fail_chg_enable;
4980 }
4981 break;
4982 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004983 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004984 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004985 chip->usb_chgpth_base = resource->start;
4986 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4987 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07004988 if (rc != -EPROBE_DEFER)
4989 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07004990 subtype, rc);
4991 goto fail_chg_enable;
4992 }
4993 break;
4994 case SMBB_DC_CHGPTH_SUBTYPE:
4995 chip->dc_chgpth_base = resource->start;
4996 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4997 if (rc) {
4998 pr_err("Failed to init subtype 0x%x rc=%d\n",
4999 subtype, rc);
5000 goto fail_chg_enable;
5001 }
5002 break;
5003 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005004 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005005 chip->boost_base = resource->start;
5006 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5007 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07005008 if (rc != -EPROBE_DEFER)
5009 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07005010 subtype, rc);
5011 goto fail_chg_enable;
5012 }
5013 break;
5014 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005015 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005016 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005017 chip->misc_base = resource->start;
5018 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5019 if (rc) {
5020 pr_err("Failed to init subtype=0x%x rc=%d\n",
5021 subtype, rc);
5022 goto fail_chg_enable;
5023 }
5024 break;
5025 default:
5026 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
5027 rc = -EINVAL;
5028 goto fail_chg_enable;
5029 }
5030 }
5031 dev_set_drvdata(&spmi->dev, chip);
5032 device_init_wakeup(&spmi->dev, 1);
5033
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005034 chip->insertion_ocv_uv = -EINVAL;
5035 chip->batt_present = qpnp_chg_is_batt_present(chip);
David Keitelf2170cc2013-02-20 17:49:03 -08005036 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08005037 chip->batt_psy.name = "battery";
5038 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
5039 chip->batt_psy.properties = msm_batt_power_props;
5040 chip->batt_psy.num_properties =
5041 ARRAY_SIZE(msm_batt_power_props);
5042 chip->batt_psy.get_property = qpnp_batt_power_get_property;
5043 chip->batt_psy.set_property = qpnp_batt_power_set_property;
5044 chip->batt_psy.property_is_writeable =
5045 qpnp_batt_property_is_writeable;
5046 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07005047 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07005048 chip->batt_psy.supplied_to = pm_batt_supplied_to;
5049 chip->batt_psy.num_supplicants =
5050 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07005051
David Keitelf2170cc2013-02-20 17:49:03 -08005052 rc = power_supply_register(chip->dev, &chip->batt_psy);
5053 if (rc < 0) {
5054 pr_err("batt failed to register rc = %d\n", rc);
5055 goto fail_chg_enable;
5056 }
David Keitel79f4c932013-04-03 16:08:39 -07005057 INIT_WORK(&chip->adc_measure_work,
5058 qpnp_bat_if_adc_measure_work);
David Keitelaa375562013-08-08 09:43:28 -07005059 INIT_WORK(&chip->adc_disable_work,
David Keitelecab15a2013-08-06 15:41:39 -07005060 qpnp_bat_if_adc_disable_work);
David Keitelc7093b02013-02-14 12:50:04 -08005061 }
5062
David Keitel9fd07382013-05-02 15:37:44 -07005063 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07005064 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005065 INIT_DELAYED_WORK(&chip->usbin_health_check,
5066 qpnp_usbin_health_check_work);
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07005067 INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
David Keitel7ac385e2013-08-19 18:02:40 -07005068 INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
David Keitel5910eea2013-05-02 15:32:25 -07005069
David Keitelf2170cc2013-02-20 17:49:03 -08005070 if (chip->dc_chgpth_base) {
5071 chip->dc_psy.name = "qpnp-dc";
5072 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
5073 chip->dc_psy.supplied_to = pm_power_supplied_to;
5074 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
5075 chip->dc_psy.properties = pm_power_props_mains;
5076 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
5077 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07005078 chip->dc_psy.set_property = qpnp_dc_power_set_property;
5079 chip->dc_psy.property_is_writeable =
5080 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08005081
5082 rc = power_supply_register(chip->dev, &chip->dc_psy);
5083 if (rc < 0) {
5084 pr_err("power_supply_register dc failed rc=%d\n", rc);
5085 goto unregister_batt;
5086 }
David Keitel80668952012-07-27 14:25:49 -07005087 }
5088
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005089 /* Turn on appropriate workaround flags */
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005090 rc = qpnp_chg_setup_flags(chip);
5091 if (rc < 0) {
5092 pr_err("failed to setup flags rc=%d\n", rc);
5093 goto unregister_dc_psy;
5094 }
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005095
David Keitelf2170cc2013-02-20 17:49:03 -08005096 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08005097 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
5098 if (rc) {
5099 pr_err("Error setting idcmax property %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005100 goto unregister_dc_psy;
David Keitel22ed2232013-01-28 11:04:07 -08005101 }
5102 }
5103
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005104 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0aea18a2013-06-14 18:57:57 -07005105 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07005106 chip->adc_param.low_temp = chip->cool_bat_decidegc;
5107 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08005108 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
5109 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
5110 chip->adc_param.btm_ctx = chip;
5111 chip->adc_param.threshold_notification =
5112 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08005113 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07005114
5115 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005116 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
5117 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005118 if (rc) {
5119 pr_err("request ADC error %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005120 goto unregister_dc_psy;
David Keitel0c1a4532013-03-21 16:39:06 -07005121 }
David Keitel454ee842013-03-08 16:19:11 -08005122 }
5123 }
David Keitel89c17752013-06-28 14:52:48 -07005124 rc = qpnp_chg_bat_if_configure_btc(chip);
5125 if (rc) {
5126 pr_err("failed to configure btc %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005127 goto unregister_dc_psy;
David Keitel89c17752013-06-28 14:52:48 -07005128 }
David Keitel454ee842013-03-08 16:19:11 -08005129
David Keitel03ee6b52012-10-22 12:25:19 -07005130 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08005131 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07005132 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07005133
David Keitelbf2edba2014-03-05 10:49:32 -08005134 if (chip->parallel_ovp_mode) {
5135 rc = override_dcin_ilimit(chip, 1);
5136 if (rc) {
5137 pr_err("Override DCIN LLIMIT %d\n", rc);
5138 goto unregister_dc_psy;
5139 }
5140 }
5141
David Keitel0f35be42013-04-16 11:10:40 -07005142 rc = qpnp_chg_request_irqs(chip);
5143 if (rc) {
5144 pr_err("failed to request interrupts %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005145 goto unregister_dc_psy;
David Keitel0f35be42013-04-16 11:10:40 -07005146 }
5147
David Keitel7e38f512013-11-19 11:15:11 -08005148 qpnp_chg_usb_chg_gone_irq_handler(chip->chg_gone.irq, chip);
David Keitelad980fc2013-07-30 18:12:02 -07005149 qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
5150 qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
David Keitel9fd07382013-05-02 15:37:44 -07005151 power_supply_set_present(chip->usb_psy,
5152 qpnp_chg_is_usb_chg_plugged_in(chip));
5153
David Keitel3c62b472013-05-06 15:38:11 -07005154 /* Set USB psy online to avoid userspace from shutting down if battery
5155 * capacity is at zero and no chargers online. */
5156 if (qpnp_chg_is_usb_chg_plugged_in(chip))
5157 power_supply_set_online(chip->usb_psy, 1);
5158
David Keitel7ac385e2013-08-19 18:02:40 -07005159 schedule_delayed_work(&chip->aicl_check_work,
5160 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel796882d2013-05-14 18:01:11 -07005161 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 -08005162 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07005163 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08005164 qpnp_chg_is_usb_chg_plugged_in(chip),
5165 qpnp_chg_is_dc_chg_plugged_in(chip),
5166 get_prop_batt_present(chip),
5167 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07005168 return 0;
5169
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005170unregister_dc_psy:
5171 if (chip->dc_chgpth_base)
5172 power_supply_unregister(&chip->dc_psy);
David Keitelc7093b02013-02-14 12:50:04 -08005173unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08005174 if (chip->bat_if_base)
5175 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07005176fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07005177 regulator_unregister(chip->otg_vreg.rdev);
5178 regulator_unregister(chip->boost_vreg.rdev);
David Keitel80668952012-07-27 14:25:49 -07005179 return rc;
5180}
5181
5182static int __devexit
5183qpnp_charger_remove(struct spmi_device *spmi)
5184{
5185 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005186 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07005187 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005188 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
5189 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005190 }
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305191
5192 cancel_delayed_work_sync(&chip->aicl_check_work);
5193 power_supply_unregister(&chip->dc_psy);
5194 cancel_work_sync(&chip->soc_check_work);
5195 cancel_delayed_work_sync(&chip->usbin_health_check);
5196 cancel_delayed_work_sync(&chip->arb_stop_work);
David Keitel9fd07382013-05-02 15:37:44 -07005197 cancel_delayed_work_sync(&chip->eoc_work);
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305198 cancel_work_sync(&chip->adc_disable_work);
5199 cancel_work_sync(&chip->adc_measure_work);
5200 power_supply_unregister(&chip->batt_psy);
5201 cancel_work_sync(&chip->batfet_lcl_work);
5202 cancel_work_sync(&chip->insertion_ocv_work);
5203 cancel_work_sync(&chip->reduce_power_stage_work);
5204 alarm_cancel(&chip->reduce_power_stage_alarm);
5205
5206 mutex_destroy(&chip->batfet_vreg_lock);
5207 mutex_destroy(&chip->jeita_configure_lock);
David Keitel79f4c932013-04-03 16:08:39 -07005208
David Collinscbb12132013-05-28 10:47:28 -07005209 regulator_unregister(chip->otg_vreg.rdev);
5210 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07005211
David Keitel80668952012-07-27 14:25:49 -07005212 return 0;
5213}
5214
David Keitel85ae4342013-04-16 11:46:00 -07005215static int qpnp_chg_resume(struct device *dev)
5216{
5217 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5218 int rc = 0;
5219
David Keitel39093572013-06-05 15:32:30 -07005220 if (chip->bat_if_base) {
5221 rc = qpnp_chg_masked_write(chip,
5222 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5223 VREF_BATT_THERM_FORCE_ON,
5224 VREF_BATT_THERM_FORCE_ON, 1);
5225 if (rc)
5226 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
5227 }
David Keitel85ae4342013-04-16 11:46:00 -07005228
5229 return rc;
5230}
5231
5232static int qpnp_chg_suspend(struct device *dev)
5233{
5234 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5235 int rc = 0;
5236
David Keitel39093572013-06-05 15:32:30 -07005237 if (chip->bat_if_base) {
5238 rc = qpnp_chg_masked_write(chip,
5239 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5240 VREF_BATT_THERM_FORCE_ON,
5241 VREF_BAT_THM_ENABLED_FSM, 1);
5242 if (rc)
5243 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
5244 }
David Keitel85ae4342013-04-16 11:46:00 -07005245
5246 return rc;
5247}
5248
David Keitel723d5012013-05-03 13:17:27 -07005249static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07005250 .resume = qpnp_chg_resume,
5251 .suspend = qpnp_chg_suspend,
5252};
5253
David Keitel80668952012-07-27 14:25:49 -07005254static struct spmi_driver qpnp_charger_driver = {
5255 .probe = qpnp_charger_probe,
5256 .remove = __devexit_p(qpnp_charger_remove),
5257 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07005258 .name = QPNP_CHARGER_DEV_NAME,
5259 .owner = THIS_MODULE,
5260 .of_match_table = qpnp_charger_match_table,
5261 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07005262 },
5263};
5264
5265/**
5266 * qpnp_chg_init() - register spmi driver for qpnp-chg
5267 */
5268int __init
5269qpnp_chg_init(void)
5270{
5271 return spmi_driver_register(&qpnp_charger_driver);
5272}
5273module_init(qpnp_chg_init);
5274
5275static void __exit
5276qpnp_chg_exit(void)
5277{
5278 spmi_driver_unregister(&qpnp_charger_driver);
5279}
5280module_exit(qpnp_chg_exit);
5281
5282
5283MODULE_DESCRIPTION("QPNP charger driver");
5284MODULE_LICENSE("GPL v2");
5285MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);