blob: 087020224e0d14ec95bf2c0eb68d1a486f7045cc [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 Keiteld681cda2012-10-02 15:44:21 -0700653#define USB_VALID_BIT BIT(7)
David Keitel80668952012-07-27 14:25:49 -0700654static int
655qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
656{
657 u8 usbin_valid_rt_sts;
658 int rc;
659
660 rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
David Keiteld681cda2012-10-02 15:44:21 -0700661 chip->usb_chgpth_base + CHGR_STATUS , 1);
David Keitel80668952012-07-27 14:25:49 -0700662
663 if (rc) {
664 pr_err("spmi read failed: addr=%03X, rc=%d\n",
David Keiteld681cda2012-10-02 15:44:21 -0700665 chip->usb_chgpth_base + CHGR_STATUS, rc);
David Keitel80668952012-07-27 14:25:49 -0700666 return rc;
667 }
668 pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
669
David Keiteld681cda2012-10-02 15:44:21 -0700670 return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700671}
672
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700673static bool
674qpnp_chg_is_ibat_loop_active(struct qpnp_chg_chip *chip)
675{
676 int rc;
677 u8 buck_sts;
678
679 rc = qpnp_chg_read(chip, &buck_sts,
680 INT_RT_STS(chip->buck_base), 1);
681 if (rc) {
682 pr_err("failed to read buck RT status rc=%d\n", rc);
683 return 0;
684 }
685
686 return !!(buck_sts & IBAT_LOOP_IRQ);
687}
688
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800689#define USB_VALID_MASK 0xC0
690#define USB_COARSE_DET 0x10
691#define USB_VALID_UVP_VALUE 0x00
692#define USB_VALID_OVP_VALUE 0x40
693static int
694qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
695{
696 u8 usbin_chg_rt_sts;
697 int rc;
698 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
699 chip->usb_chgpth_base + CHGR_STATUS , 1);
700 if (rc) {
701 pr_err("spmi read failed: addr=%03X, rc=%d\n",
702 chip->usb_chgpth_base + CHGR_STATUS, rc);
703 return rc;
704 }
705 return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
706}
707
708static int
709qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
710{
711 u8 usbin_chg_rt_sts, usbin_health = 0;
712 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
723 pr_debug("chgr usb sts 0x%x\n", usbin_chg_rt_sts);
724 if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
725 if ((usbin_chg_rt_sts & USB_VALID_MASK)
726 == USB_VALID_OVP_VALUE) {
727 usbin_health = USBIN_OVP;
728 pr_err("Over voltage charger inserted\n");
729 } else if ((usbin_chg_rt_sts & USB_VALID_BIT) != 0) {
730 usbin_health = USBIN_OK;
731 pr_debug("Valid charger inserted\n");
732 }
733 } else {
734 usbin_health = USBIN_UNKNOW;
735 pr_debug("Charger plug out\n");
736 }
737
738 return usbin_health;
739}
740
David Keitel80668952012-07-27 14:25:49 -0700741static int
742qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
743{
744 u8 dcin_valid_rt_sts;
745 int rc;
746
David Keitelf2170cc2013-02-20 17:49:03 -0800747 if (!chip->dc_chgpth_base)
748 return 0;
749
David Keitel80668952012-07-27 14:25:49 -0700750 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
751 INT_RT_STS(chip->dc_chgpth_base), 1);
752 if (rc) {
753 pr_err("spmi read failed: addr=%03X, rc=%d\n",
754 INT_RT_STS(chip->dc_chgpth_base), rc);
755 return rc;
756 }
757
758 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
759}
760
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700761static int
762qpnp_chg_is_ichg_loop_active(struct qpnp_chg_chip *chip)
763{
764 u8 buck_sts;
765 int rc;
766
767 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
768
769 if (rc) {
770 pr_err("spmi read failed: addr=%03X, rc=%d\n",
771 INT_RT_STS(chip->buck_base), rc);
772 return rc;
773 }
774 pr_debug("buck usb sts 0x%x\n", buck_sts);
775
776 return (buck_sts & ICHG_LOOP_IRQ) ? 1 : 0;
777}
778
David Keitel22ed2232013-01-28 11:04:07 -0800779#define QPNP_CHG_I_MAX_MIN_100 100
780#define QPNP_CHG_I_MAX_MIN_150 150
781#define QPNP_CHG_I_MAX_MIN_MA 200
782#define QPNP_CHG_I_MAX_MAX_MA 2500
783#define QPNP_CHG_I_MAXSTEP_MA 100
784static int
785qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
786{
787 int rc = 0;
788 u8 dc = 0;
789
790 if (mA < QPNP_CHG_I_MAX_MIN_100
791 || mA > QPNP_CHG_I_MAX_MAX_MA) {
792 pr_err("bad mA=%d asked to set\n", mA);
793 return -EINVAL;
794 }
795
796 if (mA == QPNP_CHG_I_MAX_MIN_100) {
797 dc = 0x00;
798 pr_debug("current=%d setting %02x\n", mA, dc);
799 return qpnp_chg_write(chip, &dc,
800 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
801 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
802 dc = 0x01;
803 pr_debug("current=%d setting %02x\n", mA, dc);
804 return qpnp_chg_write(chip, &dc,
805 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
806 }
807
808 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
809
810 pr_debug("current=%d setting 0x%x\n", mA, dc);
811 rc = qpnp_chg_write(chip, &dc,
812 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
813
814 return rc;
815}
816
David Keitel80668952012-07-27 14:25:49 -0700817static int
David Keitel2586f0a2013-08-20 10:02:26 -0700818qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
819{
820 int rc = 0;
821 u8 trim_reg;
822
823 rc = qpnp_chg_read(chip, &trim_reg,
824 chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
825 if (rc) {
826 pr_err("failed to read USB_TRIM rc=%d\n", rc);
827 return 0;
828 }
829
830 return trim_reg;
831}
832
833static int
834qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
835{
836 int rc = 0;
837
838 rc = qpnp_chg_masked_write(chip,
839 chip->usb_chgpth_base + SEC_ACCESS,
840 0xFF,
841 0xA5, 1);
842 if (rc) {
843 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
844 return rc;
845 }
846
847 rc = qpnp_chg_masked_write(chip,
848 chip->usb_chgpth_base + CHGR_USB_TRIM,
849 0xFF,
850 trim, 1);
851 if (rc) {
852 pr_err("failed to write USB TRIM rc=%d\n", rc);
853 return rc;
854 }
855
856 return rc;
857}
858
859static int
David Keitel80668952012-07-27 14:25:49 -0700860qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
861{
David Keiteld681cda2012-10-02 15:44:21 -0700862 int rc = 0;
863 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700864
David Keitel7b0568482013-12-02 14:47:42 -0800865 if (mA < 0 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700866 pr_err("bad mA=%d asked to set\n", mA);
867 return -EINVAL;
868 }
869
David Keitel7b0568482013-12-02 14:47:42 -0800870 if (mA <= QPNP_CHG_I_MAX_MIN_100) {
David Keitel22ed2232013-01-28 11:04:07 -0800871 usb_reg = 0x00;
872 pr_debug("current=%d setting %02x\n", mA, usb_reg);
873 return qpnp_chg_write(chip, &usb_reg,
874 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
875 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
876 usb_reg = 0x01;
877 pr_debug("current=%d setting %02x\n", mA, usb_reg);
878 return qpnp_chg_write(chip, &usb_reg,
879 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
880 }
881
882 /* Impose input current limit */
883 if (chip->maxinput_usb_ma)
884 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
885
886 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -0700887
David Keiteld681cda2012-10-02 15:44:21 -0700888 if (chip->flags & CHG_FLAGS_VCP_WA) {
889 temp = 0xA5;
890 rc = qpnp_chg_write(chip, &temp,
891 chip->buck_base + SEC_ACCESS, 1);
892 rc = qpnp_chg_masked_write(chip,
893 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
894 0x0C, 0x0C, 1);
895 }
896
David Keitel80668952012-07-27 14:25:49 -0700897 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -0700898 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -0800899 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -0700900
901 if (chip->flags & CHG_FLAGS_VCP_WA) {
902 temp = 0xA5;
903 udelay(200);
904 rc = qpnp_chg_write(chip, &temp,
905 chip->buck_base + SEC_ACCESS, 1);
906 rc = qpnp_chg_masked_write(chip,
907 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
908 0x0C, 0x00, 1);
909 }
910
911 return rc;
912}
913
David Keitel25544a22013-12-06 17:59:24 -0800914#define QPNP_CHG_VINMIN_MIN_MV 4000
David Keitel337bd862013-07-15 21:42:58 -0700915#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
916#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
917#define QPNP_CHG_VINMIN_MAX_MV 9600
918#define QPNP_CHG_VINMIN_STEP_MV 50
919#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
Prasad Sodagudi95624b62013-09-26 16:40:59 +0530920#define QPNP_CHG_VINMIN_MASK 0x3F
David Keitel25544a22013-12-06 17:59:24 -0800921#define QPNP_CHG_VINMIN_MIN_VAL 0x0C
David Keitel337bd862013-07-15 21:42:58 -0700922static int
923qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
924{
925 u8 temp;
926
David Keitel25544a22013-12-06 17:59:24 -0800927 if ((voltage < QPNP_CHG_VINMIN_MIN_MV)
928 || (voltage > QPNP_CHG_VINMIN_MAX_MV)) {
David Keitel337bd862013-07-15 21:42:58 -0700929 pr_err("bad mV=%d asked to set\n", voltage);
930 return -EINVAL;
931 }
932 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
933 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
David Keitel289fcf82013-10-24 11:33:00 -0700934 temp += (voltage - QPNP_CHG_VINMIN_HIGH_MIN_MV)
David Keitel337bd862013-07-15 21:42:58 -0700935 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
936 } else {
937 temp = QPNP_CHG_VINMIN_MIN_VAL;
938 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
939 / QPNP_CHG_VINMIN_STEP_MV;
940 }
941
942 pr_debug("voltage=%d setting %02x\n", voltage, temp);
943 return qpnp_chg_masked_write(chip,
944 chip->chgr_base + CHGR_VIN_MIN,
945 QPNP_CHG_VINMIN_MASK, temp, 1);
946}
947
948static int
949qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
950{
951 int rc, vin_min_mv;
952 u8 vin_min;
953
954 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
955 if (rc) {
956 pr_err("failed to read VIN_MIN rc=%d\n", rc);
957 return 0;
958 }
959
960 if (vin_min == 0)
961 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
David Keitel289fcf82013-10-24 11:33:00 -0700962 else if (vin_min >= QPNP_CHG_VINMIN_HIGH_MIN_VAL)
David Keitel337bd862013-07-15 21:42:58 -0700963 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
964 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
965 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
966 else
967 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
968 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
969 * QPNP_CHG_VINMIN_STEP_MV;
970 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
971
972 return vin_min_mv;
973}
974
Prasad Sodagudic3678012013-09-23 12:01:19 +0530975#define QPNP_CHG_VBATWEAK_MIN_MV 2100
976#define QPNP_CHG_VBATWEAK_MAX_MV 3600
977#define QPNP_CHG_VBATWEAK_STEP_MV 100
978static int
979qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
980{
981 u8 temp;
982
983 if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
984 || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
985 return -EINVAL;
986
987 temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
988 / QPNP_CHG_VBATWEAK_STEP_MV;
989
990 pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
991 return qpnp_chg_write(chip, &temp,
992 chip->chgr_base + CHGR_VBAT_WEAK, 1);
993}
994
David Keitel337bd862013-07-15 21:42:58 -0700995static int
996qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
997{
998 int rc, iusbmax_ma;
999 u8 iusbmax;
1000
1001 rc = qpnp_chg_read(chip, &iusbmax,
1002 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
1003 if (rc) {
1004 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
1005 return 0;
1006 }
1007
1008 if (iusbmax == 0)
1009 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
1010 else if (iusbmax == 0x01)
1011 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
1012 else
1013 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
1014
1015 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
1016
1017 return iusbmax_ma;
1018}
1019
David Keitel975b5352014-01-27 14:28:04 -08001020#define ILIMIT_OVR_0 0x02
1021static int
1022override_dcin_ilimit(struct qpnp_chg_chip *chip, bool override)
1023{
1024 int rc;
1025
1026 pr_debug("override %d\n", override);
1027 rc = qpnp_chg_masked_write(chip,
1028 chip->dc_chgpth_base + SEC_ACCESS,
1029 0xA5,
1030 0xA5, 1);
1031 rc |= qpnp_chg_masked_write(chip,
1032 chip->dc_chgpth_base + DC_COMP_OVR1,
1033 0xFF,
1034 override ? ILIMIT_OVR_0 : 0, 1);
1035 if (rc) {
1036 pr_err("Failed to override dc ilimit rc = %d\n", rc);
1037 return rc;
1038 }
1039
1040 return rc;
1041}
1042
1043#define DUAL_PATH_EN BIT(7)
1044static int
1045switch_parallel_ovp_mode(struct qpnp_chg_chip *chip, bool enable)
1046{
1047 int rc = 0;
1048
1049 if (!chip->usb_chgpth_base || !chip->dc_chgpth_base)
1050 return rc;
1051
1052 pr_debug("enable %d\n", enable);
1053 rc = override_dcin_ilimit(chip, 1);
1054 udelay(10);
1055
1056 /* enable/disable dual path mode */
1057 rc = qpnp_chg_masked_write(chip,
1058 chip->usb_chgpth_base + SEC_ACCESS,
1059 0xA5,
1060 0xA5, 1);
1061 rc |= qpnp_chg_masked_write(chip,
1062 chip->usb_chgpth_base + USB_SPARE,
1063 0xFF,
1064 enable ? DUAL_PATH_EN : 0, 1);
1065 if (rc) {
1066 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1067 return rc;
1068 }
1069
1070 rc = override_dcin_ilimit(chip, 0);
1071 return rc;
1072}
1073
David Keiteld681cda2012-10-02 15:44:21 -07001074#define USB_SUSPEND_BIT BIT(0)
1075static int
1076qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
1077{
David Keitel975b5352014-01-27 14:28:04 -08001078 /* Turn off DC OVP FET when going into USB suspend */
1079 if (chip->parallel_ovp_mode && enable)
1080 switch_parallel_ovp_mode(chip, 0);
1081
David Keiteld681cda2012-10-02 15:44:21 -07001082 return qpnp_chg_masked_write(chip,
1083 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
1084 USB_SUSPEND_BIT,
1085 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -07001086}
1087
David Keitel344c6972013-04-09 19:28:21 -07001088static int
1089qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
1090{
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001091 if (chip->insertion_ocv_uv == 0 && enable) {
1092 pr_debug("Battery not present, skipping\n");
1093 return 0;
1094 }
1095 pr_debug("charging %s\n", enable ? "enabled" : "disabled");
David Keitel344c6972013-04-09 19:28:21 -07001096 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1097 CHGR_CHG_EN,
1098 enable ? CHGR_CHG_EN : 0, 1);
1099}
1100
1101static int
1102qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
1103{
1104 /* Don't run on battery for batteryless hardware */
1105 if (chip->use_default_batt_values)
1106 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -07001107 /* Don't force on battery if battery is not present */
1108 if (!qpnp_chg_is_batt_present(chip))
1109 return 0;
David Keitel344c6972013-04-09 19:28:21 -07001110
1111 /* This bit forces the charger to run off of the battery rather
1112 * than a connected charger */
1113 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1114 CHGR_ON_BAT_FORCE_BIT,
1115 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
1116}
1117
David Keitel8b68d2d2013-05-14 23:36:51 -07001118#define BUCK_DUTY_MASK_100P 0x30
1119static int
1120qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
1121{
1122 int rc;
1123
1124 pr_debug("enable: %d\n", enable);
1125
1126 rc = qpnp_chg_masked_write(chip,
1127 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1128 if (rc) {
1129 pr_debug("failed to write sec access rc=%d\n", rc);
1130 return rc;
1131 }
1132
1133 rc = qpnp_chg_masked_write(chip,
1134 chip->buck_base + BUCK_TEST_SMBC_MODES,
1135 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
1136 if (rc) {
1137 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
1138 return rc;
1139 }
1140
1141 return rc;
1142}
1143
David Keitel9fd07382013-05-02 15:37:44 -07001144#define COMPATATOR_OVERRIDE_0 0x80
1145static int
1146qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
1147{
1148 int rc;
1149
1150 pr_debug("toggle: %d\n", enable);
1151
1152 rc = qpnp_chg_masked_write(chip,
1153 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1154 if (rc) {
1155 pr_debug("failed to write sec access rc=%d\n", rc);
1156 return rc;
1157 }
1158
1159 rc = qpnp_chg_masked_write(chip,
1160 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
1161 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
1162 if (rc) {
1163 pr_debug("failed to toggle chg done override rc=%d\n", rc);
1164 return rc;
1165 }
1166
1167 return rc;
1168}
1169
1170#define QPNP_CHG_VBATDET_MIN_MV 3240
1171#define QPNP_CHG_VBATDET_MAX_MV 5780
1172#define QPNP_CHG_VBATDET_STEP_MV 20
1173static int
1174qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
1175{
1176 u8 temp;
1177
1178 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
1179 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
1180 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
1181 return -EINVAL;
1182 }
1183 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
1184 / QPNP_CHG_VBATDET_STEP_MV;
1185
1186 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
1187 return qpnp_chg_write(chip, &temp,
1188 chip->chgr_base + CHGR_VBAT_DET, 1);
1189}
1190
David Keitel344c6972013-04-09 19:28:21 -07001191static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001192qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
1193{
1194 if (chip->bat_is_cool)
1195 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
1196 - chip->resume_delta_mv);
1197 else if (chip->bat_is_warm)
1198 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
1199 - chip->resume_delta_mv);
1200 else if (chip->resuming_charging)
1201 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1202 + chip->resume_delta_mv);
1203 else
1204 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1205 - chip->resume_delta_mv);
1206}
1207
1208static void
David Keitel344c6972013-04-09 19:28:21 -07001209qpnp_arb_stop_work(struct work_struct *work)
1210{
1211 struct delayed_work *dwork = to_delayed_work(work);
1212 struct qpnp_chg_chip *chip = container_of(dwork,
1213 struct qpnp_chg_chip, arb_stop_work);
1214
David Keitel9fd07382013-05-02 15:37:44 -07001215 if (!chip->chg_done)
1216 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -07001217 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1218}
1219
1220static void
1221qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -07001222{
1223 struct qpnp_chg_chip *chip = container_of(work,
1224 struct qpnp_chg_chip, adc_measure_work);
1225
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07001226 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -07001227 pr_err("request ADC error\n");
1228}
1229
David Keitelecab15a2013-08-06 15:41:39 -07001230static void
1231qpnp_bat_if_adc_disable_work(struct work_struct *work)
1232{
1233 struct qpnp_chg_chip *chip = container_of(work,
1234 struct qpnp_chg_chip, adc_disable_work);
1235
1236 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev, &chip->adc_param);
1237}
1238
David Keitel9fd07382013-05-02 15:37:44 -07001239#define EOC_CHECK_PERIOD_MS 10000
1240static irqreturn_t
1241qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
1242{
1243 struct qpnp_chg_chip *chip = _chip;
1244 u8 chg_sts = 0;
1245 int rc;
1246
1247 pr_debug("vbatdet-lo triggered\n");
1248
1249 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
1250 if (rc)
1251 pr_err("failed to read chg_sts rc=%d\n", rc);
1252
1253 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
1254 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
1255 schedule_delayed_work(&chip->eoc_work,
1256 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001257 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07001258 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001259 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07001260
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001261 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001262 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001263 if (chip->dc_chgpth_base) {
1264 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001265 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001266 }
1267 if (chip->bat_if_base) {
1268 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001269 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001270 }
David Keitel9fd07382013-05-02 15:37:44 -07001271 return IRQ_HANDLED;
1272}
1273
David Keitel344c6972013-04-09 19:28:21 -07001274#define ARB_STOP_WORK_MS 1000
1275static irqreturn_t
1276qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
1277{
1278 struct qpnp_chg_chip *chip = _chip;
David Keitel7e38f512013-11-19 11:15:11 -08001279 u8 usb_sts;
1280 int rc;
1281
1282 rc = qpnp_chg_read(chip, &usb_sts,
1283 INT_RT_STS(chip->usb_chgpth_base), 1);
1284 if (rc)
1285 pr_err("failed to read usb_chgpth_sts rc=%d\n", rc);
David Keitel344c6972013-04-09 19:28:21 -07001286
1287 pr_debug("chg_gone triggered\n");
David Keiteld53183a2014-01-07 17:17:44 -08001288 if ((qpnp_chg_is_usb_chg_plugged_in(chip)
1289 || qpnp_chg_is_dc_chg_plugged_in(chip))
1290 && (usb_sts & CHG_GONE_IRQ)) {
David Keitel344c6972013-04-09 19:28:21 -07001291 qpnp_chg_charge_en(chip, 0);
David Keitel9fd07382013-05-02 15:37:44 -07001292 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001293 schedule_delayed_work(&chip->arb_stop_work,
1294 msecs_to_jiffies(ARB_STOP_WORK_MS));
1295 }
1296
1297 return IRQ_HANDLED;
1298}
1299
David Keitel0b62bdd2013-07-10 17:30:51 -07001300static irqreturn_t
1301qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
1302{
1303 struct qpnp_chg_chip *chip = _chip;
David Keitel0b62bdd2013-07-10 17:30:51 -07001304
1305 pr_debug("usb-ocp triggered\n");
1306
David Keitel8b9bd312014-01-15 14:44:00 -08001307 schedule_work(&chip->ocp_clear_work);
1308
1309 return IRQ_HANDLED;
1310}
1311
1312#define BOOST_ILIMIT_MIN 0x07
1313#define BOOST_ILIMIT_DEF 0x02
1314#define BOOST_ILIMT_MASK 0xFF
1315static void
1316qpnp_chg_ocp_clear_work(struct work_struct *work)
1317{
1318 int rc;
1319 u8 usb_sts;
1320 struct qpnp_chg_chip *chip = container_of(work,
1321 struct qpnp_chg_chip, ocp_clear_work);
1322
1323 if (chip->type == SMBBP) {
1324 rc = qpnp_chg_masked_write(chip,
1325 chip->boost_base + BOOST_ILIM,
1326 BOOST_ILIMT_MASK,
1327 BOOST_ILIMIT_MIN, 1);
1328 if (rc) {
1329 pr_err("Failed to turn configure ilim rc = %d\n", rc);
1330 return;
1331 }
1332 }
1333
David Keitel0b62bdd2013-07-10 17:30:51 -07001334 rc = qpnp_chg_masked_write(chip,
1335 chip->usb_chgpth_base + USB_OCP_CLR,
1336 OCP_CLR_BIT,
1337 OCP_CLR_BIT, 1);
1338 if (rc)
1339 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1340
1341 /* force usb ovp fet off */
1342 rc = qpnp_chg_masked_write(chip,
1343 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1344 USB_OTG_EN_BIT,
1345 USB_OTG_EN_BIT, 1);
1346 if (rc)
1347 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1348
David Keitel8b9bd312014-01-15 14:44:00 -08001349 if (chip->type == SMBBP) {
1350 /* Wait for OCP circuitry to be powered up */
1351 msleep(100);
1352 rc = qpnp_chg_read(chip, &usb_sts,
1353 INT_RT_STS(chip->usb_chgpth_base), 1);
1354 if (rc) {
1355 pr_err("failed to read interrupt sts %d\n", rc);
1356 return;
1357 }
1358
1359 if (usb_sts & COARSE_DET_USB_IRQ) {
1360 rc = qpnp_chg_masked_write(chip,
1361 chip->boost_base + BOOST_ILIM,
1362 BOOST_ILIMT_MASK,
1363 BOOST_ILIMIT_DEF, 1);
1364 if (rc) {
1365 pr_err("Failed to set ilim rc = %d\n", rc);
1366 return;
1367 }
1368 } else {
1369 pr_warn_ratelimited("USB short to GND detected!\n");
1370 }
1371 }
David Keitel0b62bdd2013-07-10 17:30:51 -07001372}
1373
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001374#define QPNP_CHG_VDDMAX_MIN 3400
1375#define QPNP_CHG_V_MIN_MV 3240
1376#define QPNP_CHG_V_MAX_MV 4500
1377#define QPNP_CHG_V_STEP_MV 10
1378#define QPNP_CHG_BUCK_TRIM1_STEP 10
1379#define QPNP_CHG_BUCK_VDD_TRIM_MASK 0xF0
1380static int
1381qpnp_chg_vddmax_and_trim_set(struct qpnp_chg_chip *chip,
1382 int voltage, int trim_mv)
1383{
1384 int rc, trim_set;
1385 u8 vddmax = 0, trim = 0;
1386
1387 if (voltage < QPNP_CHG_VDDMAX_MIN
1388 || voltage > QPNP_CHG_V_MAX_MV) {
1389 pr_err("bad mV=%d asked to set\n", voltage);
1390 return -EINVAL;
1391 }
1392
1393 vddmax = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1394 rc = qpnp_chg_write(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1395 if (rc) {
1396 pr_err("Failed to write vddmax: %d\n", rc);
1397 return rc;
1398 }
1399
1400 rc = qpnp_chg_masked_write(chip,
1401 chip->buck_base + SEC_ACCESS,
1402 0xFF,
1403 0xA5, 1);
1404 if (rc) {
1405 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1406 return rc;
1407 }
1408 trim_set = clamp((int)chip->trim_center
1409 + (trim_mv / QPNP_CHG_BUCK_TRIM1_STEP),
1410 0, 0xF);
1411 trim = (u8)trim_set << 4;
1412 rc = qpnp_chg_masked_write(chip,
1413 chip->buck_base + BUCK_CTRL_TRIM1,
1414 QPNP_CHG_BUCK_VDD_TRIM_MASK,
1415 trim, 1);
1416 if (rc) {
1417 pr_err("Failed to write buck trim1: %d\n", rc);
1418 return rc;
1419 }
1420 pr_debug("voltage=%d+%d setting vddmax: %02x, trim: %02x\n",
1421 voltage, trim_mv, vddmax, trim);
1422 return 0;
1423}
1424
Xiaozhe Shie8504482013-10-30 18:10:31 -07001425static int
1426qpnp_chg_vddmax_get(struct qpnp_chg_chip *chip)
1427{
1428 int rc;
1429 u8 vddmax = 0;
1430
1431 rc = qpnp_chg_read(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1432 if (rc) {
1433 pr_err("Failed to write vddmax: %d\n", rc);
1434 return rc;
1435 }
1436
1437 return QPNP_CHG_V_MIN_MV + (int)vddmax * QPNP_CHG_V_STEP_MV;
1438}
1439
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001440/* JEITA compliance logic */
1441static void
1442qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1443{
1444 if (chip->bat_is_cool)
1445 qpnp_chg_vddmax_and_trim_set(chip, chip->cool_bat_mv,
1446 chip->delta_vddmax_mv);
1447 else if (chip->bat_is_warm)
1448 qpnp_chg_vddmax_and_trim_set(chip, chip->warm_bat_mv,
1449 chip->delta_vddmax_mv);
1450 else
1451 qpnp_chg_vddmax_and_trim_set(chip, chip->max_voltage_mv,
1452 chip->delta_vddmax_mv);
1453}
1454
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001455static void
1456qpnp_usbin_health_check_work(struct work_struct *work)
1457{
1458 int usbin_health = 0;
1459 u8 psy_health_sts = 0;
1460 struct delayed_work *dwork = to_delayed_work(work);
1461 struct qpnp_chg_chip *chip = container_of(dwork,
1462 struct qpnp_chg_chip, usbin_health_check);
1463
1464 usbin_health = qpnp_chg_check_usbin_health(chip);
1465 spin_lock(&chip->usbin_health_monitor_lock);
1466 if (chip->usbin_health != usbin_health) {
1467 pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
1468 chip->usbin_health, usbin_health);
1469 chip->usbin_health = usbin_health;
1470 if (usbin_health == USBIN_OVP)
1471 psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1472 else if (usbin_health == USBIN_OK)
1473 psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
1474 power_supply_set_health_state(chip->usb_psy, psy_health_sts);
1475 power_supply_changed(chip->usb_psy);
1476 }
1477 /* enable OVP monitor in usb valid after coarse-det complete */
1478 chip->usb_valid_check_ovp = true;
1479 spin_unlock(&chip->usbin_health_monitor_lock);
1480 return;
1481}
1482
1483#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
1484#define USB_DEB_BYPASS 0x0
1485#define USB_DEB_5MS 0x1
1486#define USB_DEB_10MS 0x2
1487#define USB_DEB_20MS 0x3
1488static irqreturn_t
1489qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
1490{
1491 struct qpnp_chg_chip *chip = _chip;
1492 int host_mode, rc = 0;
1493 int debounce[] = {
1494 [USB_DEB_BYPASS] = 0,
1495 [USB_DEB_5MS] = 5,
1496 [USB_DEB_10MS] = 10,
1497 [USB_DEB_20MS] = 20 };
1498 u8 ovp_ctl;
1499 bool usb_coarse_det;
1500
1501 host_mode = qpnp_chg_is_otg_en_set(chip);
1502 usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
1503 pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
1504 usb_coarse_det, host_mode);
1505
1506 if (host_mode)
1507 return IRQ_HANDLED;
1508 /* ignore to monitor OVP in usbin valid irq handler
1509 if the coarse-det fired first, do the OVP state monitor
1510 in the usbin_health_check work, and after the work,
1511 enable monitor OVP in usbin valid irq handler */
1512 chip->usb_valid_check_ovp = false;
1513 if (chip->usb_coarse_det ^ usb_coarse_det) {
1514 chip->usb_coarse_det = usb_coarse_det;
1515 if (usb_coarse_det) {
1516 /* usb coarse-det rising edge, check the usbin_valid
1517 debounce time setting, and start a delay work to
1518 check the OVP status*/
1519 rc = qpnp_chg_read(chip, &ovp_ctl,
1520 chip->usb_chgpth_base + USB_OVP_CTL, 1);
1521
1522 if (rc) {
1523 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1524 chip->usb_chgpth_base + USB_OVP_CTL,
1525 rc);
1526 return rc;
1527 }
1528 ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
1529 schedule_delayed_work(&chip->usbin_health_check,
1530 msecs_to_jiffies(debounce[ovp_ctl]));
1531 } else {
1532 /* usb coarse-det rising edge, set the usb psy health
1533 status to unknown */
1534 pr_debug("usb coarse det clear, set usb health to unknown\n");
1535 chip->usbin_health = USBIN_UNKNOW;
1536 power_supply_set_health_state(chip->usb_psy,
1537 POWER_SUPPLY_HEALTH_UNKNOWN);
1538 power_supply_changed(chip->usb_psy);
1539 }
1540
1541 }
1542 return IRQ_HANDLED;
1543}
1544
David Keitel6e63bd52013-09-06 18:00:03 -07001545#define BATFET_LPM_MASK 0xC0
1546#define BATFET_LPM 0x40
1547#define BATFET_NO_LPM 0x00
1548static int
1549qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
1550{
1551 int rc = 0;
1552
David Keitelcadbc282013-09-26 11:39:14 -07001553 if (chip->charging_disabled || !chip->bat_if_base)
1554 return rc;
1555
David Keitel6e63bd52013-09-06 18:00:03 -07001556 if (chip->type == SMBB)
1557 rc = qpnp_chg_masked_write(chip,
1558 chip->bat_if_base + CHGR_BAT_IF_SPARE,
1559 BATFET_LPM_MASK,
1560 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1561 else
1562 rc = qpnp_chg_masked_write(chip,
1563 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
1564 BATFET_LPM_MASK,
1565 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1566
1567 return rc;
1568}
1569
David Keitel80668952012-07-27 14:25:49 -07001570#define ENUM_T_STOP_BIT BIT(0)
1571static irqreturn_t
1572qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1573{
1574 struct qpnp_chg_chip *chip = _chip;
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001575 int usb_present, host_mode, usbin_health;
1576 u8 psy_health_sts;
David Keitel80668952012-07-27 14:25:49 -07001577
1578 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001579 host_mode = qpnp_chg_is_otg_en_set(chip);
1580 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1581 usb_present, host_mode);
1582
1583 /* In host mode notifications cmoe from USB supply */
1584 if (host_mode)
1585 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001586
1587 if (chip->usb_present ^ usb_present) {
1588 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001589 if (!usb_present) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001590 /* when a valid charger inserted, and increase the
1591 * charger voltage to OVP threshold, then
1592 * usb_in_valid falling edge interrupt triggers.
1593 * So we handle the OVP monitor here, and ignore
1594 * other health state changes */
1595 if (chip->ovp_monitor_enable &&
1596 (chip->usb_valid_check_ovp)) {
1597 usbin_health =
1598 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001599 if ((chip->usbin_health != usbin_health)
1600 && (usbin_health == USBIN_OVP)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001601 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001602 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001603 POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1604 power_supply_set_health_state(
1605 chip->usb_psy,
1606 psy_health_sts);
1607 power_supply_changed(chip->usb_psy);
1608 }
1609 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001610 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1611 chip->delta_vddmax_mv = 0;
1612 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel6e63bd52013-09-06 18:00:03 -07001613 chip->chg_done = false;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001614 }
David Keitela9185602013-11-12 17:55:48 -08001615 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel7b0568482013-12-02 14:47:42 -08001616 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelfd305ee2013-07-19 20:19:06 -07001617 chip->prev_usb_max_ma = -EINVAL;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07001618 chip->aicl_settled = false;
David Keitel9fd07382013-05-02 15:37:44 -07001619 } else {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001620 /* when OVP clamped usbin, and then decrease
1621 * the charger voltage to lower than the OVP
1622 * threshold, a usbin_valid rising edge
1623 * interrupt triggered. So we change the usb
1624 * psy health state back to good */
1625 if (chip->ovp_monitor_enable &&
1626 (chip->usb_valid_check_ovp)) {
1627 usbin_health =
1628 qpnp_chg_check_usbin_health(chip);
Wu Fenglin15c907c2013-10-18 18:08:33 +08001629 if ((chip->usbin_health != usbin_health)
1630 && (usbin_health == USBIN_OK)) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001631 chip->usbin_health = usbin_health;
Wu Fenglin15c907c2013-10-18 18:08:33 +08001632 psy_health_sts =
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001633 POWER_SUPPLY_HEALTH_GOOD;
1634 power_supply_set_health_state(
1635 chip->usb_psy,
1636 psy_health_sts);
1637 power_supply_changed(chip->usb_psy);
1638 }
1639 }
1640
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001641 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1642 chip->delta_vddmax_mv = 0;
1643 qpnp_chg_set_appropriate_vddmax(chip);
1644 }
David Keitel9fd07382013-05-02 15:37:44 -07001645 schedule_delayed_work(&chip->eoc_work,
1646 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001647 schedule_work(&chip->soc_check_work);
David Keitel9fd07382013-05-02 15:37:44 -07001648 }
David Keitel344c6972013-04-09 19:28:21 -07001649
David Keitel9fd07382013-05-02 15:37:44 -07001650 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel6e63bd52013-09-06 18:00:03 -07001651 schedule_work(&chip->batfet_lcl_work);
David Keitel80668952012-07-27 14:25:49 -07001652 }
1653
1654 return IRQ_HANDLED;
1655}
1656
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001657#define TEST_EN_SMBC_LOOP 0xE5
1658#define IBAT_REGULATION_DISABLE BIT(2)
David Keitel7450dcd2013-01-29 18:41:41 -08001659static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001660qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1661{
1662 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001663 int batt_temp_good, batt_present, rc;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001664
1665 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1666 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1667
Xiaozhe Shi87831862014-01-20 17:44:40 -08001668 batt_present = qpnp_chg_is_batt_present(chip);
1669 if (batt_present) {
1670 rc = qpnp_chg_masked_write(chip,
1671 chip->buck_base + SEC_ACCESS,
1672 0xFF,
1673 0xA5, 1);
1674 if (rc) {
1675 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1676 return rc;
1677 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001678
Xiaozhe Shi87831862014-01-20 17:44:40 -08001679 rc = qpnp_chg_masked_write(chip,
1680 chip->buck_base + TEST_EN_SMBC_LOOP,
1681 IBAT_REGULATION_DISABLE,
1682 batt_temp_good ? 0 : IBAT_REGULATION_DISABLE, 1);
1683 if (rc) {
1684 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1685 return rc;
1686 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08001687 }
1688
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001689 pr_debug("psy changed batt_psy\n");
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001690 power_supply_changed(&chip->batt_psy);
1691 return IRQ_HANDLED;
1692}
1693
1694static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001695qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1696{
1697 struct qpnp_chg_chip *chip = _chip;
Xiaozhe Shi87831862014-01-20 17:44:40 -08001698 int batt_present, batt_temp_good, rc;
David Keitel42ae0aa2013-03-08 16:20:10 -08001699
1700 batt_present = qpnp_chg_is_batt_present(chip);
1701 pr_debug("batt-pres triggered: %d\n", batt_present);
1702
1703 if (chip->batt_present ^ batt_present) {
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001704 if (batt_present) {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001705 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1706 rc = qpnp_chg_masked_write(chip,
1707 chip->buck_base + SEC_ACCESS,
1708 0xFF,
1709 0xA5, 1);
1710 if (rc) {
1711 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1712 return rc;
1713 }
1714
1715 rc = qpnp_chg_masked_write(chip,
1716 chip->buck_base + TEST_EN_SMBC_LOOP,
1717 IBAT_REGULATION_DISABLE,
1718 batt_temp_good
1719 ? 0 : IBAT_REGULATION_DISABLE, 1);
1720 if (rc) {
1721 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1722 return rc;
1723 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001724 schedule_work(&chip->insertion_ocv_work);
1725 } else {
Xiaozhe Shi87831862014-01-20 17:44:40 -08001726 rc = qpnp_chg_masked_write(chip,
1727 chip->buck_base + SEC_ACCESS,
1728 0xFF,
1729 0xA5, 1);
1730 if (rc) {
1731 pr_err("failed to write SEC_ACCESS: %d\n", rc);
1732 return rc;
1733 }
1734
1735 rc = qpnp_chg_masked_write(chip,
1736 chip->buck_base + TEST_EN_SMBC_LOOP,
1737 IBAT_REGULATION_DISABLE,
1738 0, 1);
1739 if (rc) {
1740 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1741 return rc;
1742 }
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001743 chip->insertion_ocv_uv = 0;
1744 qpnp_chg_charge_en(chip, 0);
1745 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001746 chip->batt_present = batt_present;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001747 pr_debug("psy changed batt_psy\n");
David Keitel42ae0aa2013-03-08 16:20:10 -08001748 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001749 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001750 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001751
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001752 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07001753 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001754 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001755 schedule_work(&chip->adc_measure_work);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001756 } else if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitelec3c09802013-06-13 13:05:30 -07001757 && !batt_present) {
David Keitelecab15a2013-08-06 15:41:39 -07001758 schedule_work(&chip->adc_disable_work);
David Keitelec3c09802013-06-13 13:05:30 -07001759 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001760 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001761 }
1762
1763 return IRQ_HANDLED;
1764}
1765
1766static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001767qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1768{
1769 struct qpnp_chg_chip *chip = _chip;
1770 int dc_present;
1771
1772 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1773 pr_debug("dcin-valid triggered: %d\n", dc_present);
1774
1775 if (chip->dc_present ^ dc_present) {
1776 chip->dc_present = dc_present;
David Keitel6d4b9da2013-09-05 17:38:40 -07001777 if (qpnp_chg_is_otg_en_set(chip))
1778 qpnp_chg_force_run_on_batt(chip, !dc_present ? 1 : 0);
David Keitel278f2c72013-08-13 18:00:45 -07001779 if (!dc_present && !qpnp_chg_is_usb_chg_plugged_in(chip)) {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001780 chip->delta_vddmax_mv = 0;
1781 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel9fd07382013-05-02 15:37:44 -07001782 chip->chg_done = false;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001783 } else {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001784 if (!qpnp_chg_is_usb_chg_plugged_in(chip)) {
1785 chip->delta_vddmax_mv = 0;
1786 qpnp_chg_set_appropriate_vddmax(chip);
1787 }
David Keitel9fd07382013-05-02 15:37:44 -07001788 schedule_delayed_work(&chip->eoc_work,
1789 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001790 schedule_work(&chip->soc_check_work);
1791 }
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001792 pr_debug("psy changed dc_psy\n");
David Keitel7450dcd2013-01-29 18:41:41 -08001793 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001794 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001795 power_supply_changed(&chip->batt_psy);
David Keitel6e63bd52013-09-06 18:00:03 -07001796 schedule_work(&chip->batfet_lcl_work);
David Keitel7450dcd2013-01-29 18:41:41 -08001797 }
1798
1799 return IRQ_HANDLED;
1800}
1801
David Keitel80668952012-07-27 14:25:49 -07001802#define CHGR_CHG_FAILED_BIT BIT(7)
1803static irqreturn_t
1804qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1805{
1806 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001807 int rc;
David Keitel80668952012-07-27 14:25:49 -07001808
David Keitel9fd07382013-05-02 15:37:44 -07001809 pr_debug("chg_failed triggered\n");
1810
David Keitel80668952012-07-27 14:25:49 -07001811 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001812 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001813 CHGR_CHG_FAILED_BIT,
1814 CHGR_CHG_FAILED_BIT, 1);
1815 if (rc)
1816 pr_err("Failed to write chg_fail clear bit!\n");
1817
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001818 if (chip->bat_if_base) {
1819 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001820 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001821 }
1822 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001823 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001824 if (chip->dc_chgpth_base) {
1825 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001826 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001827 }
David Keitel80668952012-07-27 14:25:49 -07001828 return IRQ_HANDLED;
1829}
1830
1831static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001832qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
1833{
1834 struct qpnp_chg_chip *chip = _chip;
1835
1836 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001837
1838 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001839 if (chip->bat_if_base) {
1840 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001841 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001842 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001843
1844 return IRQ_HANDLED;
1845}
1846
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001847static int qpnp_chg_is_fastchg_on(struct qpnp_chg_chip *chip)
David Keitel42ae0aa2013-03-08 16:20:10 -08001848{
David Keitel337bd862013-07-15 21:42:58 -07001849 u8 chgr_sts;
1850 int rc;
1851
David Keitelbf6a1062014-01-23 10:57:36 -08001852 qpnp_chg_irq_wake_disable(&chip->chg_fastchg);
1853
David Keitel337bd862013-07-15 21:42:58 -07001854 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001855 if (rc) {
1856 pr_err("failed to read interrupt status %d\n", rc);
1857 return rc;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001858 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001859 pr_debug("chgr_sts 0x%x\n", chgr_sts);
1860 return (chgr_sts & FAST_CHG_ON_IRQ) ? 1 : 0;
1861}
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001862
David Keitel59fbb762014-02-05 16:46:24 -08001863#define VBATDET_BYPASS 0x01
1864static int
1865bypass_vbatdet_comp(struct qpnp_chg_chip *chip, bool bypass)
1866{
1867 int rc;
1868
1869 pr_debug("bypass %d\n", bypass);
1870 rc = qpnp_chg_masked_write(chip,
1871 chip->chgr_base + SEC_ACCESS,
1872 0xA5,
1873 0xA5, 1);
1874 rc |= qpnp_chg_masked_write(chip,
1875 chip->chgr_base + CHGR_COMP_OVR1,
1876 0xFF,
1877 bypass ? VBATDET_BYPASS : 0, 1);
1878 if (rc) {
1879 pr_err("Failed to bypass vbatdet comp rc = %d\n", rc);
1880 return rc;
1881 }
1882
1883 return rc;
1884}
1885
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001886static irqreturn_t
1887qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
1888{
1889 struct qpnp_chg_chip *chip = _chip;
1890 bool fastchg_on = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001891
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001892 fastchg_on = qpnp_chg_is_fastchg_on(chip);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001893
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001894 pr_debug("FAST_CHG IRQ triggered, fastchg_on: %d\n", fastchg_on);
David Keitel337bd862013-07-15 21:42:58 -07001895
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001896 if (chip->fastchg_on ^ fastchg_on) {
1897 chip->fastchg_on = fastchg_on;
1898 if (chip->bat_if_base) {
1899 pr_debug("psy changed batt_psy\n");
1900 power_supply_changed(&chip->batt_psy);
1901 }
1902
1903 pr_debug("psy changed usb_psy\n");
1904 power_supply_changed(chip->usb_psy);
1905
1906 if (chip->dc_chgpth_base) {
1907 pr_debug("psy changed dc_psy\n");
1908 power_supply_changed(&chip->dc_psy);
1909 }
1910
1911 if (fastchg_on) {
1912 chip->chg_done = false;
David Keitel59fbb762014-02-05 16:46:24 -08001913 bypass_vbatdet_comp(chip, 1);
1914 if (chip->bat_is_warm || chip->bat_is_cool) {
1915 qpnp_chg_set_appropriate_vddmax(chip);
1916 qpnp_chg_set_appropriate_battery_current(chip);
1917 }
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001918
1919 if (chip->resuming_charging) {
1920 chip->resuming_charging = false;
1921 qpnp_chg_set_appropriate_vbatdet(chip);
1922 }
1923
1924 if (!chip->charging_disabled) {
1925 schedule_delayed_work(&chip->eoc_work,
1926 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
1927 pm_stay_awake(chip->dev);
1928 }
David Keitel975b5352014-01-27 14:28:04 -08001929 if (chip->parallel_ovp_mode)
1930 switch_parallel_ovp_mode(chip, 1);
1931 } else {
1932 if (chip->parallel_ovp_mode)
1933 switch_parallel_ovp_mode(chip, 0);
David Keitel59fbb762014-02-05 16:46:24 -08001934 if (!chip->bat_is_warm && !chip->bat_is_cool)
1935 bypass_vbatdet_comp(chip, 0);
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08001936 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001937 }
1938
David Keitel47185a62013-05-15 18:54:10 -07001939 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -08001940
1941 return IRQ_HANDLED;
1942}
1943
David Keitel03ee6b52012-10-22 12:25:19 -07001944static int
David Keitel432e1232013-06-05 16:10:18 -07001945qpnp_dc_property_is_writeable(struct power_supply *psy,
1946 enum power_supply_property psp)
1947{
1948 switch (psp) {
1949 case POWER_SUPPLY_PROP_CURRENT_MAX:
1950 return 1;
1951 default:
1952 break;
1953 }
1954
1955 return 0;
1956}
1957
1958static int
David Keitel03ee6b52012-10-22 12:25:19 -07001959qpnp_batt_property_is_writeable(struct power_supply *psy,
1960 enum power_supply_property psp)
1961{
1962 switch (psp) {
1963 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08001964 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07001965 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel2586f0a2013-08-20 10:02:26 -07001966 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07001967 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
David Keitel337bd862013-07-15 21:42:58 -07001968 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07001969 case POWER_SUPPLY_PROP_COOL_TEMP:
1970 case POWER_SUPPLY_PROP_WARM_TEMP:
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08001971 case POWER_SUPPLY_PROP_CAPACITY:
David Keitel03ee6b52012-10-22 12:25:19 -07001972 return 1;
1973 default:
1974 break;
1975 }
1976
1977 return 0;
1978}
1979
David Keitel6f865cd2012-11-30 15:04:32 -08001980static int
David Keitelbe208252013-01-31 14:49:25 -08001981qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
1982{
1983 int rc;
1984
1985 if (chip->charging_disabled && enable) {
1986 pr_debug("Charging disabled\n");
1987 return 0;
1988 }
1989
1990 rc = qpnp_chg_charge_en(chip, enable);
1991 if (rc) {
1992 pr_err("Failed to control charging %d\n", rc);
1993 return rc;
1994 }
1995
1996 rc = qpnp_chg_force_run_on_batt(chip, !enable);
1997 if (rc)
1998 pr_err("Failed to control charging %d\n", rc);
1999
2000 return rc;
2001}
2002
David Keitel454ee842013-03-08 16:19:11 -08002003static int
2004switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002005{
2006 int rc;
2007
2008 pr_debug("switch to charge mode\n");
2009 if (!qpnp_chg_is_otg_en_set(chip))
2010 return 0;
2011
David Keitel8b9bd312014-01-15 14:44:00 -08002012 if (chip->type == SMBBP) {
2013 rc = qpnp_chg_masked_write(chip,
2014 chip->boost_base + BOOST_ILIM,
2015 BOOST_ILIMT_MASK,
2016 BOOST_ILIMIT_DEF, 1);
2017 if (rc) {
2018 pr_err("Failed to set ilim rc = %d\n", rc);
2019 return rc;
2020 }
2021 }
2022
David Keitel6f865cd2012-11-30 15:04:32 -08002023 /* enable usb ovp fet */
2024 rc = qpnp_chg_masked_write(chip,
2025 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2026 USB_OTG_EN_BIT,
2027 0, 1);
2028 if (rc) {
2029 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
2030 return rc;
2031 }
2032
2033 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2034 if (rc) {
2035 pr_err("Failed re-enable charging rc = %d\n", rc);
2036 return rc;
2037 }
2038
2039 return 0;
2040}
2041
David Keitel454ee842013-03-08 16:19:11 -08002042static int
2043switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08002044{
2045 int rc;
David Keitel8b9bd312014-01-15 14:44:00 -08002046 u8 usb_sts;
David Keitel6f865cd2012-11-30 15:04:32 -08002047
2048 pr_debug("switch to host mode\n");
2049 if (qpnp_chg_is_otg_en_set(chip))
2050 return 0;
2051
David Keitel975b5352014-01-27 14:28:04 -08002052 if (chip->parallel_ovp_mode)
2053 switch_parallel_ovp_mode(chip, 0);
2054
David Keitel8b9bd312014-01-15 14:44:00 -08002055 if (chip->type == SMBBP) {
2056 rc = qpnp_chg_masked_write(chip,
2057 chip->boost_base + BOOST_ILIM,
2058 BOOST_ILIMT_MASK,
2059 BOOST_ILIMIT_MIN, 1);
2060 if (rc) {
2061 pr_err("Failed to turn configure ilim rc = %d\n", rc);
2062 return rc;
2063 }
2064 }
2065
David Keitel6d4b9da2013-09-05 17:38:40 -07002066 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
2067 rc = qpnp_chg_force_run_on_batt(chip, 1);
2068 if (rc) {
2069 pr_err("Failed to disable charging rc = %d\n", rc);
2070 return rc;
2071 }
David Keitel6f865cd2012-11-30 15:04:32 -08002072 }
2073
2074 /* force usb ovp fet off */
2075 rc = qpnp_chg_masked_write(chip,
2076 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
2077 USB_OTG_EN_BIT,
2078 USB_OTG_EN_BIT, 1);
2079 if (rc) {
2080 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
2081 return rc;
2082 }
2083
David Keitel8b9bd312014-01-15 14:44:00 -08002084 if (chip->type == SMBBP) {
2085 /* Wait for OCP circuitry to be powered up */
2086 msleep(100);
2087 rc = qpnp_chg_read(chip, &usb_sts,
2088 INT_RT_STS(chip->usb_chgpth_base), 1);
2089 if (rc) {
2090 pr_err("failed to read interrupt sts %d\n", rc);
2091 return rc;
2092 }
2093
2094 if (usb_sts & COARSE_DET_USB_IRQ) {
2095 rc = qpnp_chg_masked_write(chip,
2096 chip->boost_base + BOOST_ILIM,
2097 BOOST_ILIMT_MASK,
2098 BOOST_ILIMIT_DEF, 1);
2099 if (rc) {
2100 pr_err("Failed to set ilim rc = %d\n", rc);
2101 return rc;
2102 }
2103 } else {
2104 pr_warn_ratelimited("USB short to GND detected!\n");
2105 }
2106 }
2107
David Keitel6f865cd2012-11-30 15:04:32 -08002108 return 0;
2109}
2110
David Keitel80668952012-07-27 14:25:49 -07002111static enum power_supply_property pm_power_props_mains[] = {
2112 POWER_SUPPLY_PROP_PRESENT,
2113 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07002114 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07002115};
2116
2117static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07002118 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07002119 POWER_SUPPLY_PROP_STATUS,
2120 POWER_SUPPLY_PROP_CHARGE_TYPE,
2121 POWER_SUPPLY_PROP_HEALTH,
2122 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002123 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07002124 POWER_SUPPLY_PROP_TECHNOLOGY,
2125 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
2126 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
2127 POWER_SUPPLY_PROP_VOLTAGE_NOW,
2128 POWER_SUPPLY_PROP_CAPACITY,
2129 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07002130 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
David Keitel2586f0a2013-08-20 10:02:26 -07002131 POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002132 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
David Keitel337bd862013-07-15 21:42:58 -07002133 POWER_SUPPLY_PROP_VOLTAGE_MIN,
2134 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07002135 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302136 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07002137 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07002138 POWER_SUPPLY_PROP_COOL_TEMP,
2139 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08002140 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302141 POWER_SUPPLY_PROP_CYCLE_COUNT,
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002142 POWER_SUPPLY_PROP_VOLTAGE_OCV,
David Keitel80668952012-07-27 14:25:49 -07002143};
2144
2145static char *pm_power_supplied_to[] = {
2146 "battery",
2147};
2148
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07002149static char *pm_batt_supplied_to[] = {
2150 "bms",
2151};
2152
David Keitel337bd862013-07-15 21:42:58 -07002153static int charger_monitor;
2154module_param(charger_monitor, int, 0644);
2155
David Keitel2586f0a2013-08-20 10:02:26 -07002156static int ext_ovp_present;
2157module_param(ext_ovp_present, int, 0444);
2158
David Keitel80668952012-07-27 14:25:49 -07002159#define USB_WALL_THRESHOLD_MA 500
David Keitel2586f0a2013-08-20 10:02:26 -07002160#define OVP_USB_WALL_THRESHOLD_MA 200
David Keitel80668952012-07-27 14:25:49 -07002161static int
2162qpnp_power_get_property_mains(struct power_supply *psy,
2163 enum power_supply_property psp,
2164 union power_supply_propval *val)
2165{
2166 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2167 dc_psy);
2168
2169 switch (psp) {
2170 case POWER_SUPPLY_PROP_PRESENT:
2171 case POWER_SUPPLY_PROP_ONLINE:
2172 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07002173 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07002174 return 0;
2175
2176 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
2177 break;
David Keitel432e1232013-06-05 16:10:18 -07002178 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07002179 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07002180 break;
David Keitel80668952012-07-27 14:25:49 -07002181 default:
2182 return -EINVAL;
2183 }
2184 return 0;
2185}
2186
David Keitel7ac385e2013-08-19 18:02:40 -07002187static void
2188qpnp_aicl_check_work(struct work_struct *work)
2189{
2190 struct delayed_work *dwork = to_delayed_work(work);
2191 struct qpnp_chg_chip *chip = container_of(dwork,
2192 struct qpnp_chg_chip, aicl_check_work);
2193 union power_supply_propval ret = {0,};
2194
2195 if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
2196 chip->usb_psy->get_property(chip->usb_psy,
2197 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
2198 if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
2199 pr_debug("no charger_monitor present set iusbmax %d\n",
2200 ret.intval / 1000);
2201 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2202 }
2203 } else {
2204 pr_debug("charger_monitor is present\n");
2205 }
2206 chip->charger_monitor_checked = true;
2207}
2208
David Keitel80668952012-07-27 14:25:49 -07002209static int
2210get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
2211{
2212 int rc = 0;
2213 struct qpnp_vadc_result results;
2214
David Keitelfe51cb92013-04-02 19:42:58 -07002215 if (chip->revision == 0 && chip->type == SMBB) {
2216 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
2217 return 0;
2218 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002219 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07002220 if (rc) {
2221 pr_err("Unable to read vbat rc=%d\n", rc);
2222 return 0;
2223 }
2224 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07002225 }
2226}
2227
2228#define BATT_PRES_BIT BIT(7)
2229static int
2230get_prop_batt_present(struct qpnp_chg_chip *chip)
2231{
2232 u8 batt_present;
2233 int rc;
2234
2235 rc = qpnp_chg_read(chip, &batt_present,
2236 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
2237 if (rc) {
2238 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
2239 return 0;
2240 };
2241 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
2242}
2243
2244#define BATT_TEMP_HOT BIT(6)
2245#define BATT_TEMP_OK BIT(7)
2246static int
2247get_prop_batt_health(struct qpnp_chg_chip *chip)
2248{
2249 u8 batt_health;
2250 int rc;
2251
2252 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07002253 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07002254 if (rc) {
2255 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
2256 return POWER_SUPPLY_HEALTH_UNKNOWN;
2257 };
2258
2259 if (BATT_TEMP_OK & batt_health)
2260 return POWER_SUPPLY_HEALTH_GOOD;
2261 if (BATT_TEMP_HOT & batt_health)
2262 return POWER_SUPPLY_HEALTH_OVERHEAT;
2263 else
2264 return POWER_SUPPLY_HEALTH_COLD;
2265}
2266
2267static int
2268get_prop_charge_type(struct qpnp_chg_chip *chip)
2269{
2270 int rc;
2271 u8 chgr_sts;
2272
2273 if (!get_prop_batt_present(chip))
2274 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2275
2276 rc = qpnp_chg_read(chip, &chgr_sts,
2277 INT_RT_STS(chip->chgr_base), 1);
2278 if (rc) {
2279 pr_err("failed to read interrupt sts %d\n", rc);
2280 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2281 }
2282
2283 if (chgr_sts & TRKL_CHG_ON_IRQ)
2284 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
2285 if (chgr_sts & FAST_CHG_ON_IRQ)
2286 return POWER_SUPPLY_CHARGE_TYPE_FAST;
2287
2288 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2289}
2290
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002291#define DEFAULT_CAPACITY 50
2292static int
2293get_batt_capacity(struct qpnp_chg_chip *chip)
2294{
2295 union power_supply_propval ret = {0,};
2296
2297 if (chip->fake_battery_soc >= 0)
2298 return chip->fake_battery_soc;
2299 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2300 return DEFAULT_CAPACITY;
2301 if (chip->bms_psy) {
2302 chip->bms_psy->get_property(chip->bms_psy,
2303 POWER_SUPPLY_PROP_CAPACITY, &ret);
2304 return ret.intval;
2305 }
2306 return DEFAULT_CAPACITY;
2307}
2308
David Keitel80668952012-07-27 14:25:49 -07002309static int
2310get_prop_batt_status(struct qpnp_chg_chip *chip)
2311{
2312 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002313 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07002314
David Keitel9fd07382013-05-02 15:37:44 -07002315 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
2316 qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
David Keitelc9ffe842013-01-25 19:37:51 -08002317 return POWER_SUPPLY_STATUS_FULL;
David Keitel9fd07382013-05-02 15:37:44 -07002318 }
David Keitelc9ffe842013-01-25 19:37:51 -08002319
David Keitel9fd07382013-05-02 15:37:44 -07002320 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07002321 if (rc) {
2322 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08002323 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07002324 }
2325
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002326 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
2327 if (rc) {
2328 pr_err("failed to read bat_if sts %d\n", rc);
2329 return POWER_SUPPLY_CHARGE_TYPE_NONE;
2330 }
2331
David Keitela8099ff2014-01-06 11:31:40 -08002332 if ((chgr_sts & TRKL_CHG_ON_IRQ) && !(bat_if_sts & BAT_FET_ON_IRQ))
David Keitel80668952012-07-27 14:25:49 -07002333 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08002334 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07002335 return POWER_SUPPLY_STATUS_CHARGING;
2336
Xiaozhe Shi72a72f22013-12-26 13:54:29 -08002337 /* report full if state of charge is 100 and a charger is connected */
2338 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
2339 qpnp_chg_is_dc_chg_plugged_in(chip))
2340 && get_batt_capacity(chip) == 100) {
2341 return POWER_SUPPLY_STATUS_FULL;
2342 }
2343
David Keitel80668952012-07-27 14:25:49 -07002344 return POWER_SUPPLY_STATUS_DISCHARGING;
2345}
2346
2347static int
2348get_prop_current_now(struct qpnp_chg_chip *chip)
2349{
2350 union power_supply_propval ret = {0,};
2351
2352 if (chip->bms_psy) {
2353 chip->bms_psy->get_property(chip->bms_psy,
2354 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
2355 return ret.intval;
2356 } else {
2357 pr_debug("No BMS supply registered return 0\n");
2358 }
2359
2360 return 0;
2361}
2362
2363static int
2364get_prop_full_design(struct qpnp_chg_chip *chip)
2365{
2366 union power_supply_propval ret = {0,};
2367
2368 if (chip->bms_psy) {
2369 chip->bms_psy->get_property(chip->bms_psy,
2370 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
2371 return ret.intval;
2372 } else {
2373 pr_debug("No BMS supply registered return 0\n");
2374 }
2375
2376 return 0;
2377}
2378
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302379static int
2380get_prop_charge_full(struct qpnp_chg_chip *chip)
2381{
2382 union power_supply_propval ret = {0,};
2383
2384 if (chip->bms_psy) {
2385 chip->bms_psy->get_property(chip->bms_psy,
2386 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
2387 return ret.intval;
2388 } else {
2389 pr_debug("No BMS supply registered return 0\n");
2390 }
2391
2392 return 0;
2393}
2394
David Keitel80668952012-07-27 14:25:49 -07002395static int
2396get_prop_capacity(struct qpnp_chg_chip *chip)
2397{
2398 union power_supply_propval ret = {0,};
Xiaozhe Shibda84992013-09-05 10:39:11 -07002399 int battery_status, bms_status, soc, charger_in;
David Keitel80668952012-07-27 14:25:49 -07002400
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08002401 if (chip->fake_battery_soc >= 0)
2402 return chip->fake_battery_soc;
2403
David Keitel3dd5e0f2012-12-12 18:12:36 -08002404 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2405 return DEFAULT_CAPACITY;
2406
David Keitel80668952012-07-27 14:25:49 -07002407 if (chip->bms_psy) {
2408 chip->bms_psy->get_property(chip->bms_psy,
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002409 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002410 soc = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002411 battery_status = get_prop_batt_status(chip);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002412 chip->bms_psy->get_property(chip->bms_psy,
2413 POWER_SUPPLY_PROP_STATUS, &ret);
2414 bms_status = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002415 charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
2416 qpnp_chg_is_dc_chg_plugged_in(chip);
2417
2418 if (battery_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shibda84992013-09-05 10:39:11 -07002419 && bms_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002420 && charger_in
Xiaozhe Shie8504482013-10-30 18:10:31 -07002421 && !chip->bat_is_cool
2422 && !chip->bat_is_warm
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002423 && !chip->resuming_charging
2424 && !chip->charging_disabled
2425 && chip->soc_resume_limit
Xiaozhe Shibda84992013-09-05 10:39:11 -07002426 && soc <= chip->soc_resume_limit) {
2427 pr_debug("resuming charging at %d%% soc\n", soc);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002428 chip->resuming_charging = true;
David Keitelbf6a1062014-01-23 10:57:36 -08002429 qpnp_chg_irq_wake_enable(&chip->chg_fastchg);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002430 qpnp_chg_set_appropriate_vbatdet(chip);
2431 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2432 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002433 if (soc == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07002434 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
2435 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07002436 pr_warn_ratelimited("Battery 0, CHG absent\n");
2437 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002438 return soc;
David Keitel80668952012-07-27 14:25:49 -07002439 } else {
2440 pr_debug("No BMS supply registered return 50\n");
2441 }
2442
2443 /* return default capacity to avoid userspace
2444 * from shutting down unecessarily */
2445 return DEFAULT_CAPACITY;
2446}
2447
David Keitel3dd5e0f2012-12-12 18:12:36 -08002448#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07002449#define MAX_TOLERABLE_BATT_TEMP_DDC 680
2450static int
2451get_prop_batt_temp(struct qpnp_chg_chip *chip)
2452{
2453 int rc = 0;
2454 struct qpnp_vadc_result results;
2455
David Keitel3dd5e0f2012-12-12 18:12:36 -08002456 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2457 return DEFAULT_TEMP;
2458
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002459 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07002460 if (rc) {
2461 pr_debug("Unable to read batt temperature rc=%d\n", rc);
2462 return 0;
David Keitel80668952012-07-27 14:25:49 -07002463 }
Xiaozhe Shi4c8458a2013-11-26 13:00:56 -08002464 pr_debug("get_bat_temp %d, %lld\n",
David Keitela2dbfc72013-06-07 11:10:14 -07002465 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07002466
David Keitela2dbfc72013-06-07 11:10:14 -07002467 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07002468}
2469
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302470static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
2471{
2472 union power_supply_propval ret = {0,};
2473
2474 if (chip->bms_psy)
2475 chip->bms_psy->get_property(chip->bms_psy,
2476 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
2477 return ret.intval;
2478}
2479
David Keitel337bd862013-07-15 21:42:58 -07002480static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
2481{
2482 u8 buck_sts;
2483 int rc;
2484
2485 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2486
2487 if (rc) {
2488 pr_err("spmi read failed: addr=%03X, rc=%d\n",
2489 INT_RT_STS(chip->buck_base), rc);
2490 return rc;
2491 }
2492 pr_debug("buck usb sts 0x%x\n", buck_sts);
2493
2494 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
2495}
2496
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002497static int get_prop_online(struct qpnp_chg_chip *chip)
2498{
2499 return qpnp_chg_is_batfet_closed(chip);
2500}
2501
David Keitel80668952012-07-27 14:25:49 -07002502static void
2503qpnp_batt_external_power_changed(struct power_supply *psy)
2504{
2505 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2506 batt_psy);
2507 union power_supply_propval ret = {0,};
2508
2509 if (!chip->bms_psy)
2510 chip->bms_psy = power_supply_get_by_name("bms");
2511
2512 chip->usb_psy->get_property(chip->usb_psy,
2513 POWER_SUPPLY_PROP_ONLINE, &ret);
2514
David Keitelc69f2d62013-03-17 14:52:35 -07002515 /* Only honour requests while USB is present */
2516 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002517 chip->usb_psy->get_property(chip->usb_psy,
2518 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07002519
2520 if (chip->prev_usb_max_ma == ret.intval)
2521 goto skip_set_iusb_max;
2522
Zhenhua Huangdd619742013-10-24 10:02:07 +08002523 chip->prev_usb_max_ma = ret.intval;
2524
David Keitel87473252013-03-21 14:39:45 -07002525 if (ret.intval <= 2 && !chip->use_default_batt_values &&
2526 get_prop_batt_present(chip)) {
David Keitela9185602013-11-12 17:55:48 -08002527 if (ret.intval == 2)
2528 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07002529 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07002530 } else {
David Keiteld681cda2012-10-02 15:44:21 -07002531 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel337bd862013-07-15 21:42:58 -07002532 if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
David Keitel7ac385e2013-08-19 18:02:40 -07002533 && (charger_monitor ||
2534 !chip->charger_monitor_checked)) {
David Keitel2586f0a2013-08-20 10:02:26 -07002535 if (!ext_ovp_present)
2536 qpnp_chg_iusbmax_set(chip,
David Keitel337bd862013-07-15 21:42:58 -07002537 USB_WALL_THRESHOLD_MA);
David Keitel2586f0a2013-08-20 10:02:26 -07002538 else
2539 qpnp_chg_iusbmax_set(chip,
2540 OVP_USB_WALL_THRESHOLD_MA);
David Keitel337bd862013-07-15 21:42:58 -07002541 } else {
2542 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2543 }
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002544
2545 if ((chip->flags & POWER_STAGE_WA)
2546 && ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
Zhenhua Huangdc335512013-10-30 11:45:15 +08002547 && !chip->power_stage_workaround_running
2548 && chip->power_stage_workaround_enable) {
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002549 chip->power_stage_workaround_running = true;
2550 pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
2551 charger_monitor);
2552 schedule_work(&chip->reduce_power_stage_work);
2553 }
David Keitelc69f2d62013-03-17 14:52:35 -07002554 }
David Keitel80668952012-07-27 14:25:49 -07002555 }
2556
David Keitelfd305ee2013-07-19 20:19:06 -07002557skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07002558 pr_debug("end of power supply changed\n");
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002559 pr_debug("psy changed batt_psy\n");
David Keitel80668952012-07-27 14:25:49 -07002560 power_supply_changed(&chip->batt_psy);
2561}
2562
2563static int
2564qpnp_batt_power_get_property(struct power_supply *psy,
2565 enum power_supply_property psp,
2566 union power_supply_propval *val)
2567{
2568 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2569 batt_psy);
2570
2571 switch (psp) {
2572 case POWER_SUPPLY_PROP_STATUS:
2573 val->intval = get_prop_batt_status(chip);
2574 break;
2575 case POWER_SUPPLY_PROP_CHARGE_TYPE:
2576 val->intval = get_prop_charge_type(chip);
2577 break;
2578 case POWER_SUPPLY_PROP_HEALTH:
2579 val->intval = get_prop_batt_health(chip);
2580 break;
2581 case POWER_SUPPLY_PROP_PRESENT:
2582 val->intval = get_prop_batt_present(chip);
2583 break;
2584 case POWER_SUPPLY_PROP_TECHNOLOGY:
2585 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2586 break;
2587 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2588 val->intval = chip->max_voltage_mv * 1000;
2589 break;
2590 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2591 val->intval = chip->min_voltage_mv * 1000;
2592 break;
2593 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2594 val->intval = get_prop_battery_voltage_now(chip);
2595 break;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002596 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2597 val->intval = chip->insertion_ocv_uv;
2598 break;
David Keitel80668952012-07-27 14:25:49 -07002599 case POWER_SUPPLY_PROP_TEMP:
2600 val->intval = get_prop_batt_temp(chip);
2601 break;
David Keitelec3c09802013-06-13 13:05:30 -07002602 case POWER_SUPPLY_PROP_COOL_TEMP:
2603 val->intval = chip->cool_bat_decidegc;
2604 break;
2605 case POWER_SUPPLY_PROP_WARM_TEMP:
2606 val->intval = chip->warm_bat_decidegc;
2607 break;
David Keitel80668952012-07-27 14:25:49 -07002608 case POWER_SUPPLY_PROP_CAPACITY:
2609 val->intval = get_prop_capacity(chip);
2610 break;
2611 case POWER_SUPPLY_PROP_CURRENT_NOW:
2612 val->intval = get_prop_current_now(chip);
2613 break;
2614 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2615 val->intval = get_prop_full_design(chip);
2616 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302617 case POWER_SUPPLY_PROP_CHARGE_FULL:
2618 val->intval = get_prop_charge_full(chip);
2619 break;
David Keitelb80eda82012-10-15 10:49:11 -07002620 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07002621 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07002622 break;
David Keitelbe208252013-01-31 14:49:25 -08002623 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2624 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07002625 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302626 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2627 val->intval = get_prop_cycle_count(chip);
2628 break;
David Keitel337bd862013-07-15 21:42:58 -07002629 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
2630 val->intval = get_prop_vchg_loop(chip);
2631 break;
2632 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2633 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
2634 break;
David Keitel2586f0a2013-08-20 10:02:26 -07002635 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
2636 val->intval = qpnp_chg_iusb_trim_get(chip);
2637 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002638 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
2639 val->intval = chip->aicl_settled;
2640 break;
David Keitel337bd862013-07-15 21:42:58 -07002641 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2642 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
2643 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002644 case POWER_SUPPLY_PROP_ONLINE:
2645 val->intval = get_prop_online(chip);
2646 break;
David Keitelb80eda82012-10-15 10:49:11 -07002647 default:
2648 return -EINVAL;
2649 }
2650
David Keitelb80eda82012-10-15 10:49:11 -07002651 return 0;
David Keitel80668952012-07-27 14:25:49 -07002652}
2653
David Keitel89c17752013-06-28 14:52:48 -07002654#define BTC_CONFIG_ENABLED BIT(7)
2655#define BTC_COLD BIT(1)
2656#define BTC_HOT BIT(0)
2657static int
2658qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
2659{
2660 u8 btc_cfg = 0, mask = 0;
2661
2662 /* Do nothing if battery peripheral not present */
2663 if (!chip->bat_if_base)
2664 return 0;
2665
2666 if ((chip->hot_batt_p == HOT_THD_25_PCT)
2667 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
2668 btc_cfg |= btc_value[chip->hot_batt_p];
2669 mask |= BTC_HOT;
2670 }
2671
2672 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
2673 (chip->cold_batt_p == COLD_THD_80_PCT)) {
2674 btc_cfg |= btc_value[chip->cold_batt_p];
2675 mask |= BTC_COLD;
2676 }
2677
2678 if (chip->btc_disabled)
2679 mask |= BTC_CONFIG_ENABLED;
2680
2681 return qpnp_chg_masked_write(chip,
2682 chip->bat_if_base + BAT_IF_BTC_CTRL,
2683 mask, btc_cfg, 1);
2684}
2685
David Keitel5d44fa52012-12-03 16:37:31 -08002686#define QPNP_CHG_IBATSAFE_MIN_MA 100
2687#define QPNP_CHG_IBATSAFE_MAX_MA 3250
2688#define QPNP_CHG_I_STEP_MA 50
2689#define QPNP_CHG_I_MIN_MA 100
2690#define QPNP_CHG_I_MASK 0x3F
2691static int
2692qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
2693{
2694 u8 temp;
2695
2696 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
2697 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
2698 pr_err("bad mA=%d asked to set\n", safe_current);
2699 return -EINVAL;
2700 }
2701
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08002702 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08002703 return qpnp_chg_masked_write(chip,
2704 chip->chgr_base + CHGR_IBAT_SAFE,
2705 QPNP_CHG_I_MASK, temp, 1);
2706}
David Keitel80668952012-07-27 14:25:49 -07002707
2708#define QPNP_CHG_ITERM_MIN_MA 100
2709#define QPNP_CHG_ITERM_MAX_MA 250
2710#define QPNP_CHG_ITERM_STEP_MA 50
2711#define QPNP_CHG_ITERM_MASK 0x03
2712static int
2713qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
2714{
2715 u8 temp;
2716
2717 if (term_current < QPNP_CHG_ITERM_MIN_MA
2718 || term_current > QPNP_CHG_ITERM_MAX_MA) {
2719 pr_err("bad mA=%d asked to set\n", term_current);
2720 return -EINVAL;
2721 }
2722
2723 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
2724 / QPNP_CHG_ITERM_STEP_MA;
2725 return qpnp_chg_masked_write(chip,
2726 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
2727 QPNP_CHG_ITERM_MASK, temp, 1);
2728}
2729
David Keitelff5d0472013-04-04 11:36:06 -07002730#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07002731#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07002732static int
2733qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
2734{
2735 u8 temp;
2736
2737 if (chg_current < QPNP_CHG_IBATMAX_MIN
2738 || chg_current > QPNP_CHG_IBATMAX_MAX) {
2739 pr_err("bad mA=%d asked to set\n", chg_current);
2740 return -EINVAL;
2741 }
David Keitelff5d0472013-04-04 11:36:06 -07002742 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07002743 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
2744 QPNP_CHG_I_MASK, temp, 1);
2745}
2746
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002747static int
2748qpnp_chg_ibatmax_get(struct qpnp_chg_chip *chip, int *chg_current)
2749{
2750 int rc;
2751 u8 temp;
2752
2753 *chg_current = 0;
2754 rc = qpnp_chg_read(chip, &temp, chip->chgr_base + CHGR_IBAT_MAX, 1);
2755 if (rc) {
2756 pr_err("failed read ibat_max rc=%d\n", rc);
2757 return rc;
2758 }
2759
2760 *chg_current = ((temp & QPNP_CHG_I_MASK) * QPNP_CHG_I_STEP_MA);
2761
2762 return 0;
2763}
2764
David Keitela4b7b592013-04-11 18:34:35 -07002765#define QPNP_CHG_TCHG_MASK 0x7F
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002766#define QPNP_CHG_TCHG_EN_MASK 0x80
David Keitela4b7b592013-04-11 18:34:35 -07002767#define QPNP_CHG_TCHG_MIN 4
2768#define QPNP_CHG_TCHG_MAX 512
2769#define QPNP_CHG_TCHG_STEP 4
2770static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
2771{
2772 u8 temp;
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002773 int rc;
David Keitela4b7b592013-04-11 18:34:35 -07002774
2775 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
2776 pr_err("bad max minutes =%d asked to set\n", minutes);
2777 return -EINVAL;
2778 }
2779
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002780 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
2781 QPNP_CHG_TCHG_EN_MASK, 0, 1);
2782 if (rc) {
2783 pr_err("failed write tchg_max_en rc=%d\n", rc);
2784 return rc;
2785 }
2786
2787 temp = minutes / QPNP_CHG_TCHG_STEP - 1;
2788
2789 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07002790 QPNP_CHG_TCHG_MASK, temp, 1);
Abhijeet Dharmapurikar11e61562013-11-19 12:01:29 -08002791 if (rc) {
2792 pr_err("failed write tchg_max_en rc=%d\n", rc);
2793 return rc;
2794 }
2795
2796 rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
2797 QPNP_CHG_TCHG_EN_MASK, QPNP_CHG_TCHG_EN_MASK, 1);
2798 if (rc) {
2799 pr_err("failed write tchg_max_en rc=%d\n", rc);
2800 return rc;
2801 }
2802
2803 return 0;
David Keitela4b7b592013-04-11 18:34:35 -07002804}
David Keitel80668952012-07-27 14:25:49 -07002805
David Keitel59fbb762014-02-05 16:46:24 -08002806static void
2807qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
2808{
2809 unsigned int chg_current = chip->max_bat_chg_current;
2810
2811 if (chip->bat_is_cool)
2812 chg_current = min(chg_current, chip->cool_bat_chg_ma);
2813
2814 if (chip->bat_is_warm)
2815 chg_current = min(chg_current, chip->warm_bat_chg_ma);
2816
2817 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
2818 chg_current = min(chg_current,
2819 chip->thermal_mitigation[chip->therm_lvl_sel]);
2820
2821 pr_debug("setting %d mA\n", chg_current);
2822 qpnp_chg_ibatmax_set(chip, chg_current);
2823}
2824
David Keitel80668952012-07-27 14:25:49 -07002825static int
2826qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
2827{
2828 u8 temp;
2829
2830 if (voltage < QPNP_CHG_V_MIN_MV
2831 || voltage > QPNP_CHG_V_MAX_MV) {
2832 pr_err("bad mV=%d asked to set\n", voltage);
2833 return -EINVAL;
2834 }
2835 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
2836 pr_debug("voltage=%d setting %02x\n", voltage, temp);
2837 return qpnp_chg_write(chip, &temp,
2838 chip->chgr_base + CHGR_VDD_SAFE, 1);
2839}
2840
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002841#define IBAT_TRIM_TGT_MA 500
2842#define IBAT_TRIM_OFFSET_MASK 0x7F
2843#define IBAT_TRIM_GOOD_BIT BIT(7)
2844#define IBAT_TRIM_LOW_LIM 20
2845#define IBAT_TRIM_HIGH_LIM 114
2846#define IBAT_TRIM_MEAN 64
2847
2848static void
2849qpnp_chg_trim_ibat(struct qpnp_chg_chip *chip, u8 ibat_trim)
2850{
2851 int ibat_now_ma, ibat_diff_ma, rc;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002852 struct qpnp_iadc_result i_result;
2853 enum qpnp_iadc_channels iadc_channel;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002854
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002855 iadc_channel = chip->use_external_rsense ?
2856 EXTERNAL_RSENSE : INTERNAL_RSENSE;
2857 rc = qpnp_iadc_read(chip->iadc_dev, iadc_channel, &i_result);
2858 if (rc) {
2859 pr_err("Unable to read bat rc=%d\n", rc);
2860 return;
2861 }
2862
2863 ibat_now_ma = i_result.result_ua / 1000;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002864
2865 if (qpnp_chg_is_ibat_loop_active(chip)) {
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002866 ibat_diff_ma = ibat_now_ma - IBAT_TRIM_TGT_MA;
2867
2868 if (abs(ibat_diff_ma) > 50) {
2869 ibat_trim += (ibat_diff_ma / 20);
2870 ibat_trim &= IBAT_TRIM_OFFSET_MASK;
2871 /* reject new ibat_trim if it is outside limits */
2872 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
2873 IBAT_TRIM_HIGH_LIM))
2874 return;
2875 }
2876 ibat_trim |= IBAT_TRIM_GOOD_BIT;
2877 rc = qpnp_chg_write(chip, &ibat_trim,
2878 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2879 if (rc)
2880 pr_err("failed to set IBAT_TRIM rc=%d\n", rc);
2881
2882 pr_debug("ibat_now=%dmA, itgt=%dmA, ibat_diff=%dmA, ibat_trim=%x\n",
2883 ibat_now_ma, IBAT_TRIM_TGT_MA,
2884 ibat_diff_ma, ibat_trim);
2885 } else {
2886 pr_debug("ibat loop not active - cannot calibrate ibat\n");
2887 }
2888}
2889
2890static int
2891qpnp_chg_input_current_settled(struct qpnp_chg_chip *chip)
2892{
2893 int rc, ibat_max_ma;
2894 u8 reg, chgr_sts, ibat_trim, i;
2895
2896 chip->aicl_settled = true;
2897
2898 /*
2899 * Perform the ibat calibration.
2900 * This is for devices which have a IBAT_TRIM error
2901 * which can show IBAT_MAX out of spec.
2902 */
2903 if (!chip->ibat_calibration_enabled)
2904 return 0;
2905
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002906 if (chip->type != SMBB)
2907 return 0;
2908
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002909 rc = qpnp_chg_read(chip, &reg,
2910 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2911 if (rc) {
2912 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
2913 return rc;
2914 }
2915 if (reg & IBAT_TRIM_GOOD_BIT) {
2916 pr_debug("IBAT_TRIM_GOOD bit already set. Quitting!\n");
2917 return 0;
2918 }
2919 ibat_trim = reg & IBAT_TRIM_OFFSET_MASK;
2920
2921 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
2922 IBAT_TRIM_HIGH_LIM)) {
2923 pr_debug("Improper ibat_trim value=%x setting to value=%x\n",
2924 ibat_trim, IBAT_TRIM_MEAN);
2925 ibat_trim = IBAT_TRIM_MEAN;
2926 rc = qpnp_chg_masked_write(chip,
2927 chip->buck_base + BUCK_CTRL_TRIM3,
2928 IBAT_TRIM_OFFSET_MASK, ibat_trim, 1);
2929 if (rc) {
2930 pr_err("failed to set ibat_trim to %x rc=%d\n",
2931 IBAT_TRIM_MEAN, rc);
2932 return rc;
2933 }
2934 }
2935
2936 rc = qpnp_chg_read(chip, &chgr_sts,
2937 INT_RT_STS(chip->chgr_base), 1);
2938 if (rc) {
2939 pr_err("failed to read interrupt sts rc=%d\n", rc);
2940 return rc;
2941 }
2942 if (!(chgr_sts & FAST_CHG_ON_IRQ)) {
2943 pr_debug("Not in fastchg\n");
2944 return rc;
2945 }
2946
2947 /* save the ibat_max to restore it later */
2948 rc = qpnp_chg_ibatmax_get(chip, &ibat_max_ma);
2949 if (rc) {
2950 pr_debug("failed to save ibatmax rc=%d\n", rc);
2951 return rc;
2952 }
2953
2954 rc = qpnp_chg_ibatmax_set(chip, IBAT_TRIM_TGT_MA);
2955 if (rc) {
2956 pr_err("failed to set ibatmax rc=%d\n", rc);
2957 return rc;
2958 }
2959
2960 for (i = 0; i < 3; i++) {
2961 /*
2962 * ibat settling delay - to make sure the BMS controller
2963 * has sufficient time to sample ibat for the configured
2964 * ibat_max
2965 */
2966 msleep(20);
2967 if (qpnp_chg_is_ibat_loop_active(chip))
2968 qpnp_chg_trim_ibat(chip, ibat_trim);
2969 else
2970 pr_debug("ibat loop not active\n");
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002971
2972 /* read the adjusted ibat_trim for further adjustments */
2973 rc = qpnp_chg_read(chip, &ibat_trim,
2974 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2975 if (rc) {
2976 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
2977 break;
2978 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002979 }
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002980
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002981 /* restore IBATMAX */
2982 rc = qpnp_chg_ibatmax_set(chip, ibat_max_ma);
2983 if (rc)
2984 pr_err("failed to restore ibatmax rc=%d\n", rc);
2985
2986 return rc;
2987}
2988
2989
David Keitel6dc4ed42013-05-17 11:08:58 -07002990#define BOOST_MIN_UV 4200000
2991#define BOOST_MAX_UV 5500000
2992#define BOOST_STEP_UV 50000
2993#define BOOST_MIN 16
2994#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
2995static int
2996qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
2997{
2998 u8 reg = 0;
2999
3000 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
3001 pr_err("invalid voltage requested %d uV\n", voltage);
3002 return -EINVAL;
3003 }
3004
3005 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
3006
3007 pr_debug("voltage=%d setting %02x\n", voltage, reg);
3008 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
3009}
3010
3011static int
3012qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
3013{
3014 int rc;
3015 u8 boost_reg;
3016
3017 rc = qpnp_chg_read(chip, &boost_reg,
3018 chip->boost_base + BOOST_VSET, 1);
3019 if (rc) {
3020 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
3021 return rc;
3022 }
3023
3024 if (boost_reg < BOOST_MIN) {
3025 pr_err("Invalid reading from 0x%x\n", boost_reg);
3026 return -EINVAL;
3027 }
3028
3029 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
3030}
3031
David Keitel454ee842013-03-08 16:19:11 -08003032static void
David Keitelbe208252013-01-31 14:49:25 -08003033qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
3034{
3035 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
3036 chip->therm_lvl_sel = lvl_sel;
3037 if (lvl_sel == (chip->thermal_levels - 1)) {
3038 /* disable charging if highest value selected */
3039 qpnp_chg_buck_control(chip, 0);
3040 } else {
3041 qpnp_chg_buck_control(chip, 1);
3042 qpnp_chg_set_appropriate_battery_current(chip);
3043 }
3044 } else {
3045 pr_err("Unsupported level selected %d\n", lvl_sel);
3046 }
3047}
3048
David Keitel6dc4ed42013-05-17 11:08:58 -07003049/* OTG regulator operations */
3050static int
3051qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
3052{
3053 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3054
3055 return switch_usb_to_host_mode(chip);
3056}
3057
3058static int
3059qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
3060{
3061 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3062
3063 return switch_usb_to_charge_mode(chip);
3064}
3065
3066static int
3067qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
3068{
3069 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3070
3071 return qpnp_chg_is_otg_en_set(chip);
3072}
3073
3074static int
3075qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
3076{
3077 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07003078 int rc;
3079
3080 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
3081 (chip->flags & BOOST_FLASH_WA)) {
3082 qpnp_chg_usb_suspend_enable(chip, 1);
3083
3084 rc = qpnp_chg_masked_write(chip,
3085 chip->usb_chgpth_base + SEC_ACCESS,
3086 0xFF,
3087 0xA5, 1);
3088 if (rc) {
3089 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3090 return rc;
3091 }
3092
3093 rc = qpnp_chg_masked_write(chip,
3094 chip->usb_chgpth_base + COMP_OVR1,
3095 0xFF,
3096 0x2F, 1);
3097 if (rc) {
3098 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3099 return rc;
3100 }
3101 }
David Keitel6dc4ed42013-05-17 11:08:58 -07003102
3103 return qpnp_chg_masked_write(chip,
3104 chip->boost_base + BOOST_ENABLE_CONTROL,
3105 BOOST_PWR_EN,
3106 BOOST_PWR_EN, 1);
3107}
3108
3109/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07003110#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07003111static int
3112qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
3113{
3114 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07003115 int rc;
3116 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07003117
David Keitel33f58952013-05-20 16:17:36 -07003118 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07003119 chip->boost_base + BOOST_ENABLE_CONTROL,
3120 BOOST_PWR_EN,
3121 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07003122 if (rc) {
3123 pr_err("failed to disable boost rc=%d\n", rc);
3124 return rc;
3125 }
3126
3127 rc = qpnp_chg_read(chip, &vbat_sts,
3128 chip->chgr_base + CHGR_VBAT_STATUS, 1);
3129 if (rc) {
3130 pr_err("failed to read bat sts rc=%d\n", rc);
3131 return rc;
3132 }
3133
3134 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
3135 rc = qpnp_chg_masked_write(chip,
3136 chip->chgr_base + SEC_ACCESS,
3137 0xFF,
3138 0xA5, 1);
3139 if (rc) {
3140 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3141 return rc;
3142 }
3143
3144 rc = qpnp_chg_masked_write(chip,
3145 chip->chgr_base + COMP_OVR1,
3146 0xFF,
3147 0x20, 1);
3148 if (rc) {
3149 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3150 return rc;
3151 }
3152
3153 usleep(2000);
3154
3155 rc = qpnp_chg_masked_write(chip,
3156 chip->chgr_base + SEC_ACCESS,
3157 0xFF,
3158 0xA5, 1);
3159 if (rc) {
3160 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3161 return rc;
3162 }
3163
3164 rc = qpnp_chg_masked_write(chip,
3165 chip->chgr_base + COMP_OVR1,
3166 0xFF,
3167 0x00, 1);
3168 if (rc) {
3169 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3170 return rc;
3171 }
3172 }
3173
3174 if (qpnp_chg_is_usb_chg_plugged_in(chip)
3175 && (chip->flags & BOOST_FLASH_WA)) {
3176 rc = qpnp_chg_masked_write(chip,
3177 chip->usb_chgpth_base + SEC_ACCESS,
3178 0xFF,
3179 0xA5, 1);
3180 if (rc) {
3181 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
3182 return rc;
3183 }
3184
3185 rc = qpnp_chg_masked_write(chip,
3186 chip->usb_chgpth_base + COMP_OVR1,
3187 0xFF,
3188 0x00, 1);
3189 if (rc) {
3190 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
3191 return rc;
3192 }
3193
3194 usleep(1000);
3195
3196 qpnp_chg_usb_suspend_enable(chip, 0);
3197 }
3198
3199 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07003200}
3201
3202static int
3203qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
3204{
3205 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3206
3207 return qpnp_chg_is_boost_en_set(chip);
3208}
3209
3210static int
3211qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
3212 int min_uV, int max_uV, unsigned *selector)
3213{
3214 int uV = min_uV;
3215 int rc;
3216 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3217
3218 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
3219 uV = BOOST_MIN_UV;
3220
3221
3222 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
3223 pr_err("request %d uV is out of bounds\n", uV);
3224 return -EINVAL;
3225 }
3226
3227 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
3228 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
3229 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
3230 return -EINVAL;
3231 }
3232
3233 rc = qpnp_boost_vset(chip, uV);
3234
3235 return rc;
3236}
3237
3238static int
3239qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
3240{
3241 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3242
3243 return qpnp_boost_vget_uv(chip);
3244}
3245
3246static int
3247qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
3248 unsigned selector)
3249{
3250 if (selector >= N_BOOST_V)
3251 return 0;
3252
3253 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
3254}
3255
3256static struct regulator_ops qpnp_chg_otg_reg_ops = {
3257 .enable = qpnp_chg_regulator_otg_enable,
3258 .disable = qpnp_chg_regulator_otg_disable,
3259 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
3260};
3261
3262static struct regulator_ops qpnp_chg_boost_reg_ops = {
3263 .enable = qpnp_chg_regulator_boost_enable,
3264 .disable = qpnp_chg_regulator_boost_disable,
3265 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
3266 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
3267 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
3268 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
3269};
3270
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003271static int
David Keitel6e63bd52013-09-06 18:00:03 -07003272qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003273{
David Keitel9eca8ac2013-09-06 14:18:36 -07003274 int rc = 0;
David Keitel6e63bd52013-09-06 18:00:03 -07003275 u8 reg = 0;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003276
David Keitelcadbc282013-09-26 11:39:14 -07003277 if (!chip->bat_if_base)
3278 return rc;
3279
David Keitel9eca8ac2013-09-06 14:18:36 -07003280 if (chip->type == SMBB)
3281 rc = qpnp_chg_read(chip, &reg,
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003282 chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
David Keitel9eca8ac2013-09-06 14:18:36 -07003283 else
3284 rc = qpnp_chg_read(chip, &reg,
3285 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
David Keitel6e63bd52013-09-06 18:00:03 -07003286
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003287 if (rc) {
3288 pr_err("failed to read batt_if rc=%d\n", rc);
3289 return rc;
3290 }
3291
David Keitel6e63bd52013-09-06 18:00:03 -07003292 if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003293 return 1;
3294
3295 return 0;
3296}
3297
David Keitel6e63bd52013-09-06 18:00:03 -07003298static int
3299qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
3300{
3301 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3302 int rc = 0;
3303
3304 mutex_lock(&chip->batfet_vreg_lock);
3305 /* Only enable if not already enabled */
3306 if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
3307 rc = qpnp_chg_regulator_batfet_set(chip, 1);
3308 if (rc)
3309 pr_err("failed to write to batt_if rc=%d\n", rc);
3310 }
3311
3312 chip->batfet_ext_en = true;
3313 mutex_unlock(&chip->batfet_vreg_lock);
3314
3315 return rc;
3316}
3317
3318static int
3319qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
3320{
3321 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3322 int rc = 0;
3323
3324 mutex_lock(&chip->batfet_vreg_lock);
3325 /* Don't allow disable if charger connected */
3326 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3327 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3328 rc = qpnp_chg_regulator_batfet_set(chip, 0);
3329 if (rc)
3330 pr_err("failed to write to batt_if rc=%d\n", rc);
3331 }
3332
3333 chip->batfet_ext_en = false;
3334 mutex_unlock(&chip->batfet_vreg_lock);
3335
3336 return rc;
3337}
3338
3339static int
3340qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
3341{
3342 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
3343
3344 return chip->batfet_ext_en;
3345}
3346
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003347static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
3348 .enable = qpnp_chg_regulator_batfet_enable,
3349 .disable = qpnp_chg_regulator_batfet_disable,
3350 .is_enabled = qpnp_chg_regulator_batfet_is_enabled,
3351};
3352
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003353#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 8
3354#define MAX_DELTA_VDD_MAX_MV 80
3355#define VDD_MAX_CENTER_OFFSET 4
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003356static void
3357qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
3358{
3359 int delta_mv, closest_delta_mv, sign;
3360
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003361 delta_mv = chip->max_voltage_mv - VDD_MAX_CENTER_OFFSET - vbat_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003362 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
3363 pr_debug("vbat is not low enough to increase vdd\n");
3364 return;
3365 }
3366
3367 sign = delta_mv > 0 ? 1 : -1;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003368 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_BUCK_TRIM1_STEP / 2)
3369 / QPNP_CHG_BUCK_TRIM1_STEP) * QPNP_CHG_BUCK_TRIM1_STEP;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003370 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
3371 chip->max_voltage_mv, vbat_mv,
3372 delta_mv, closest_delta_mv);
3373 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
3374 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
3375 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
3376 qpnp_chg_set_appropriate_vddmax(chip);
3377}
3378
David Keitel9fd07382013-05-02 15:37:44 -07003379#define CONSECUTIVE_COUNT 3
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003380#define VBATDET_MAX_ERR_MV 50
David Keitel9fd07382013-05-02 15:37:44 -07003381static void
3382qpnp_eoc_work(struct work_struct *work)
3383{
3384 struct delayed_work *dwork = to_delayed_work(work);
3385 struct qpnp_chg_chip *chip = container_of(dwork,
3386 struct qpnp_chg_chip, eoc_work);
3387 static int count;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003388 static int vbat_low_count;
David Keitel9fd07382013-05-02 15:37:44 -07003389 int ibat_ma, vbat_mv, rc = 0;
3390 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003391 bool vbat_lower_than_vbatdet;
David Keitel9fd07382013-05-02 15:37:44 -07003392
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003393 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003394 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3395
3396 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
3397 if (rc) {
3398 pr_err("failed to read batt_if rc=%d\n", rc);
3399 return;
3400 }
3401
3402 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
3403 if (rc) {
3404 pr_err("failed to read buck rc=%d\n", rc);
3405 return;
3406 }
3407
3408 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
3409 if (rc) {
3410 pr_err("failed to read chg_sts rc=%d\n", rc);
3411 return;
3412 }
3413
3414 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
3415 chg_sts, batt_sts, buck_sts);
3416
3417 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3418 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3419 pr_debug("no chg connected, stopping\n");
3420 goto stop_eoc;
3421 }
3422
3423 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
3424 || chg_sts & TRKL_CHG_ON_IRQ)) {
3425 ibat_ma = get_prop_current_now(chip) / 1000;
3426 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003427
3428 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
3429 ibat_ma, vbat_mv, chip->term_current);
3430
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003431 vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
3432 if (vbat_lower_than_vbatdet && vbat_mv <
3433 (chip->max_voltage_mv - chip->resume_delta_mv
David Keitelbdbae452014-01-14 17:19:50 -08003434 - chip->vbatdet_max_err_mv)) {
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003435 vbat_low_count++;
3436 pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
3437 vbat_mv, chip->max_voltage_mv,
3438 chip->resume_delta_mv,
David Keitelbdbae452014-01-14 17:19:50 -08003439 chip->vbatdet_max_err_mv,
3440 vbat_low_count);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003441 if (vbat_low_count >= CONSECUTIVE_COUNT) {
3442 pr_debug("woke up too early stopping\n");
3443 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
3444 goto stop_eoc;
3445 } else {
3446 goto check_again_later;
3447 }
3448 } else {
3449 vbat_low_count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003450 }
3451
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003452 if (buck_sts & VDD_LOOP_IRQ)
3453 qpnp_chg_adjust_vddmax(chip, vbat_mv);
3454
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003455 if (!(buck_sts & VDD_LOOP_IRQ)) {
3456 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07003457 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003458 } else if ((ibat_ma * -1) > chip->term_current) {
3459 pr_debug("Not at EOC, battery current too high\n");
3460 count = 0;
3461 } else if (ibat_ma > 0) {
3462 pr_debug("Charging but system demand increased\n");
3463 count = 0;
3464 } else {
David Keitel9fd07382013-05-02 15:37:44 -07003465 if (count == CONSECUTIVE_COUNT) {
Xiaozhe Shie8504482013-10-30 18:10:31 -07003466 if (!chip->bat_is_cool && !chip->bat_is_warm) {
3467 pr_info("End of Charging\n");
3468 chip->chg_done = true;
3469 } else {
3470 pr_info("stop charging: battery is %s, vddmax = %d reached\n",
3471 chip->bat_is_cool
3472 ? "cool" : "warm",
3473 qpnp_chg_vddmax_get(chip));
3474 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003475 chip->delta_vddmax_mv = 0;
3476 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel9fd07382013-05-02 15:37:44 -07003477 qpnp_chg_charge_en(chip, 0);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003478 /* sleep for a second before enabling */
3479 msleep(2000);
3480 qpnp_chg_charge_en(chip,
3481 !chip->charging_disabled);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003482 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07003483 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07003484 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07003485 goto stop_eoc;
3486 } else {
3487 count += 1;
3488 pr_debug("EOC count = %d\n", count);
3489 }
David Keitel9fd07382013-05-02 15:37:44 -07003490 }
3491 } else {
3492 pr_debug("not charging\n");
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003493 goto stop_eoc;
David Keitel9fd07382013-05-02 15:37:44 -07003494 }
3495
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003496check_again_later:
David Keitel9fd07382013-05-02 15:37:44 -07003497 schedule_delayed_work(&chip->eoc_work,
3498 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
3499 return;
3500
3501stop_eoc:
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003502 vbat_low_count = 0;
David Keitel9fd07382013-05-02 15:37:44 -07003503 count = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003504 pm_relax(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003505}
3506
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003507static void
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07003508qpnp_chg_insertion_ocv_work(struct work_struct *work)
3509{
3510 struct qpnp_chg_chip *chip = container_of(work,
3511 struct qpnp_chg_chip, insertion_ocv_work);
3512 u8 bat_if_sts = 0, charge_en = 0;
3513 int rc;
3514
3515 chip->insertion_ocv_uv = get_prop_battery_voltage_now(chip);
3516
3517 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
3518 if (rc)
3519 pr_err("failed to read bat_if sts %d\n", rc);
3520
3521 rc = qpnp_chg_read(chip, &charge_en,
3522 chip->chgr_base + CHGR_CHG_CTRL, 1);
3523 if (rc)
3524 pr_err("failed to read bat_if sts %d\n", rc);
3525
3526 pr_debug("batfet sts = %02x, charge_en = %02x ocv = %d\n",
3527 bat_if_sts, charge_en, chip->insertion_ocv_uv);
3528 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3529 pr_debug("psy changed batt_psy\n");
3530 power_supply_changed(&chip->batt_psy);
3531}
3532
3533static void
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003534qpnp_chg_soc_check_work(struct work_struct *work)
3535{
3536 struct qpnp_chg_chip *chip = container_of(work,
3537 struct qpnp_chg_chip, soc_check_work);
3538
3539 get_prop_capacity(chip);
3540}
3541
David Keitel0c1a4532013-03-21 16:39:06 -07003542#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08003543static void
3544qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
3545{
3546 struct qpnp_chg_chip *chip = ctx;
3547 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07003548 int temp;
David Keitel454ee842013-03-08 16:19:11 -08003549
3550 if (state >= ADC_TM_STATE_NUM) {
3551 pr_err("invalid notification %d\n", state);
3552 return;
3553 }
3554
David Keitel1219a802013-03-21 16:37:21 -07003555 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08003556
David Keitel1219a802013-03-21 16:37:21 -07003557 pr_debug("temp = %d state = %s\n", temp,
3558 state == ADC_TM_WARM_STATE ? "warm" : "cool");
3559
3560 if (state == ADC_TM_WARM_STATE) {
David Keitel410ee0d2014-02-20 16:48:04 -08003561 if (temp >= chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003562 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08003563 bat_warm = true;
3564 bat_cool = false;
3565 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003566 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003567 chip->adc_param.state_request =
3568 ADC_TM_COOL_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08003569 } else if (temp >=
David Keitel1219a802013-03-21 16:37:21 -07003570 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003571 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08003572 bat_warm = false;
3573 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07003574
3575 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07003576 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003577 chip->adc_param.state_request =
3578 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003579 }
3580 } else {
David Keitel410ee0d2014-02-20 16:48:04 -08003581 if (temp <= chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003582 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08003583 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003584 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08003585 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003586 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003587 chip->adc_param.state_request =
3588 ADC_TM_WARM_THR_ENABLE;
David Keitel410ee0d2014-02-20 16:48:04 -08003589 } else if (temp <=
David Keitel1219a802013-03-21 16:37:21 -07003590 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003591 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08003592 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003593 bat_cool = false;
3594
David Keitel0c1a4532013-03-21 16:39:06 -07003595 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003596 chip->adc_param.high_temp = chip->warm_bat_decidegc;
3597 chip->adc_param.state_request =
3598 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003599 }
3600 }
3601
3602 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07003603 chip->bat_is_cool = bat_cool;
3604 chip->bat_is_warm = bat_warm;
3605
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07003606 /**
3607 * set appropriate voltages and currents.
3608 *
3609 * Note that when the battery is hot or cold, the charger
3610 * driver will not resume with SoC. Only vbatdet is used to
3611 * determine resume of charging.
3612 */
David Keitel59fbb762014-02-05 16:46:24 -08003613 if (bat_cool || bat_warm) {
3614 chip->resuming_charging = false;
3615 qpnp_chg_set_appropriate_vbatdet(chip);
3616
3617 /* To avoid ARB, only vbatdet is configured in
3618 * warm/cold zones. Once vbat < vbatdet the
3619 * appropriate vddmax/ibatmax adjustments will
3620 * be made in the fast charge interrupt. */
3621 bypass_vbatdet_comp(chip, 1);
3622 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3623 qpnp_chg_charge_en(chip, chip->charging_disabled);
3624 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3625 } else {
3626 bypass_vbatdet_comp(chip, 0);
3627 /* restore normal parameters */
3628 qpnp_chg_set_appropriate_vbatdet(chip);
3629 qpnp_chg_set_appropriate_vddmax(chip);
3630 qpnp_chg_set_appropriate_battery_current(chip);
3631 }
David Keitel454ee842013-03-08 16:19:11 -08003632 }
3633
David Keitelec3c09802013-06-13 13:05:30 -07003634 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
3635 chip->bat_is_warm, chip->bat_is_cool,
3636 chip->adc_param.low_temp, chip->adc_param.high_temp);
3637
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003638 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07003639 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07003640}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07003641
David Keitelec3c09802013-06-13 13:05:30 -07003642#define MIN_COOL_TEMP -300
3643#define MAX_WARM_TEMP 1000
3644
3645static int
3646qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
3647 enum power_supply_property psp, int temp_degc)
3648{
3649 int rc = 0;
3650
3651 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
3652 pr_err("Bad temperature request %d\n", temp_degc);
3653 return -EINVAL;
3654 }
3655
3656 mutex_lock(&chip->jeita_configure_lock);
3657 switch (psp) {
3658 case POWER_SUPPLY_PROP_COOL_TEMP:
3659 if (temp_degc >=
3660 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
3661 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
3662 temp_degc, chip->warm_bat_decidegc,
3663 HYSTERISIS_DECIDEGC);
3664 rc = -EINVAL;
3665 goto mutex_unlock;
3666 }
3667 if (chip->bat_is_cool)
3668 chip->adc_param.high_temp =
3669 temp_degc + HYSTERISIS_DECIDEGC;
3670 else if (!chip->bat_is_warm)
3671 chip->adc_param.low_temp = temp_degc;
3672
3673 chip->cool_bat_decidegc = temp_degc;
3674 break;
3675 case POWER_SUPPLY_PROP_WARM_TEMP:
3676 if (temp_degc <=
3677 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
3678 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
3679 temp_degc, chip->warm_bat_decidegc,
3680 HYSTERISIS_DECIDEGC);
3681 rc = -EINVAL;
3682 goto mutex_unlock;
3683 }
3684 if (chip->bat_is_warm)
3685 chip->adc_param.low_temp =
3686 temp_degc - HYSTERISIS_DECIDEGC;
3687 else if (!chip->bat_is_cool)
3688 chip->adc_param.high_temp = temp_degc;
3689
3690 chip->warm_bat_decidegc = temp_degc;
3691 break;
3692 default:
3693 rc = -EINVAL;
3694 goto mutex_unlock;
3695 }
3696
3697 schedule_work(&chip->adc_measure_work);
3698
3699mutex_unlock:
3700 mutex_unlock(&chip->jeita_configure_lock);
3701 return rc;
David Keitel454ee842013-03-08 16:19:11 -08003702}
3703
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003704#define POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS 20
3705#define POWER_STAGE_REDUCE_MAX_VBAT_UV 3900000
3706#define POWER_STAGE_REDUCE_MIN_VCHG_UV 4800000
3707#define POWER_STAGE_SEL_MASK 0x0F
3708#define POWER_STAGE_REDUCED 0x01
3709#define POWER_STAGE_DEFAULT 0x0F
3710static bool
3711qpnp_chg_is_power_stage_reduced(struct qpnp_chg_chip *chip)
3712{
3713 int rc;
3714 u8 reg;
3715
3716 rc = qpnp_chg_read(chip, &reg,
3717 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3718 1);
3719 if (rc) {
3720 pr_err("Error %d reading power stage register\n", rc);
3721 return false;
3722 }
3723
3724 if ((reg & POWER_STAGE_SEL_MASK) == POWER_STAGE_DEFAULT)
3725 return false;
3726
3727 return true;
3728}
3729
3730static int
3731qpnp_chg_power_stage_set(struct qpnp_chg_chip *chip, bool reduce)
3732{
3733 int rc;
3734 u8 reg = 0xA5;
3735
3736 rc = qpnp_chg_write(chip, &reg,
3737 chip->buck_base + SEC_ACCESS,
3738 1);
3739 if (rc) {
3740 pr_err("Error %d writing 0xA5 to buck's 0x%x reg\n",
3741 rc, SEC_ACCESS);
3742 return rc;
3743 }
3744
3745 reg = POWER_STAGE_DEFAULT;
3746 if (reduce)
3747 reg = POWER_STAGE_REDUCED;
3748 rc = qpnp_chg_write(chip, &reg,
3749 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3750 1);
3751
3752 if (rc)
3753 pr_err("Error %d writing 0x%x power stage register\n", rc, reg);
3754 return rc;
3755}
3756
3757static int
3758qpnp_chg_get_vusbin_uv(struct qpnp_chg_chip *chip)
3759{
3760 int rc = 0;
3761 struct qpnp_vadc_result results;
3762
3763 rc = qpnp_vadc_read(chip->vadc_dev, USBIN, &results);
3764 if (rc) {
3765 pr_err("Unable to read vbat rc=%d\n", rc);
3766 return 0;
3767 }
3768 return results.physical;
3769}
3770
3771static
3772int get_vusb_averaged(struct qpnp_chg_chip *chip, int sample_count)
3773{
3774 int vusb_uv = 0;
3775 int i;
3776
3777 /* avoid overflows */
3778 if (sample_count > 256)
3779 sample_count = 256;
3780
3781 for (i = 0; i < sample_count; i++)
3782 vusb_uv += qpnp_chg_get_vusbin_uv(chip);
3783
3784 vusb_uv = vusb_uv / sample_count;
3785 return vusb_uv;
3786}
3787
3788static
3789int get_vbat_averaged(struct qpnp_chg_chip *chip, int sample_count)
3790{
3791 int vbat_uv = 0;
3792 int i;
3793
3794 /* avoid overflows */
3795 if (sample_count > 256)
3796 sample_count = 256;
3797
3798 for (i = 0; i < sample_count; i++)
3799 vbat_uv += get_prop_battery_voltage_now(chip);
3800
3801 vbat_uv = vbat_uv / sample_count;
3802 return vbat_uv;
3803}
3804
3805static void
3806qpnp_chg_reduce_power_stage(struct qpnp_chg_chip *chip)
3807{
3808 struct timespec ts;
3809 bool power_stage_reduced_in_hw = qpnp_chg_is_power_stage_reduced(chip);
3810 bool reduce_power_stage = false;
3811 int vbat_uv = get_vbat_averaged(chip, 16);
3812 int vusb_uv = get_vusb_averaged(chip, 16);
3813 bool fast_chg =
3814 (get_prop_charge_type(chip) == POWER_SUPPLY_CHARGE_TYPE_FAST);
3815 static int count_restore_power_stage;
3816 static int count_reduce_power_stage;
3817 bool vchg_loop = get_prop_vchg_loop(chip);
3818 bool ichg_loop = qpnp_chg_is_ichg_loop_active(chip);
3819 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
3820 bool usb_ma_above_wall =
3821 (qpnp_chg_usb_iusbmax_get(chip) > USB_WALL_THRESHOLD_MA);
3822
3823 if (fast_chg
3824 && usb_present
3825 && usb_ma_above_wall
3826 && vbat_uv < POWER_STAGE_REDUCE_MAX_VBAT_UV
3827 && vusb_uv > POWER_STAGE_REDUCE_MIN_VCHG_UV)
3828 reduce_power_stage = true;
3829
3830 if ((usb_present && usb_ma_above_wall)
3831 && (vchg_loop || ichg_loop))
3832 reduce_power_stage = true;
3833
3834 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3835 count_restore_power_stage++;
3836 count_reduce_power_stage = 0;
3837 } else if (!power_stage_reduced_in_hw && reduce_power_stage) {
3838 count_reduce_power_stage++;
3839 count_restore_power_stage = 0;
3840 } else if (power_stage_reduced_in_hw == reduce_power_stage) {
3841 count_restore_power_stage = 0;
3842 count_reduce_power_stage = 0;
3843 }
3844
3845 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",
3846 power_stage_reduced_in_hw, reduce_power_stage,
3847 usb_present, usb_ma_above_wall,
3848 vbat_uv, vusb_uv, fast_chg,
3849 ichg_loop, vchg_loop,
3850 count_restore_power_stage, count_reduce_power_stage);
3851
3852 if (!power_stage_reduced_in_hw && reduce_power_stage) {
3853 if (count_reduce_power_stage >= 2) {
3854 qpnp_chg_power_stage_set(chip, true);
3855 power_stage_reduced_in_hw = true;
3856 }
3857 }
3858
3859 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3860 if (count_restore_power_stage >= 6
3861 || (!usb_present || !usb_ma_above_wall)) {
3862 qpnp_chg_power_stage_set(chip, false);
3863 power_stage_reduced_in_hw = false;
3864 }
3865 }
3866
3867 if (usb_present && usb_ma_above_wall) {
3868 getnstimeofday(&ts);
3869 ts.tv_sec += POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS;
3870 alarm_start_range(&chip->reduce_power_stage_alarm,
3871 timespec_to_ktime(ts),
3872 timespec_to_ktime(ts));
3873 } else {
3874 pr_debug("stopping power stage workaround\n");
3875 chip->power_stage_workaround_running = false;
3876 }
3877}
3878
3879static void
David Keitel6e63bd52013-09-06 18:00:03 -07003880qpnp_chg_batfet_lcl_work(struct work_struct *work)
3881{
3882 struct qpnp_chg_chip *chip = container_of(work,
3883 struct qpnp_chg_chip, batfet_lcl_work);
3884
3885 mutex_lock(&chip->batfet_vreg_lock);
3886 if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
3887 qpnp_chg_is_dc_chg_plugged_in(chip)) {
3888 qpnp_chg_regulator_batfet_set(chip, 1);
3889 pr_debug("disabled ULPM\n");
3890 } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
3891 && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3892 qpnp_chg_regulator_batfet_set(chip, 0);
3893 pr_debug("enabled ULPM\n");
3894 }
3895 mutex_unlock(&chip->batfet_vreg_lock);
3896}
3897
3898static void
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003899qpnp_chg_reduce_power_stage_work(struct work_struct *work)
3900{
3901 struct qpnp_chg_chip *chip = container_of(work,
3902 struct qpnp_chg_chip, reduce_power_stage_work);
3903
3904 qpnp_chg_reduce_power_stage(chip);
3905}
3906
3907static void
3908qpnp_chg_reduce_power_stage_callback(struct alarm *alarm)
3909{
3910 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
3911 reduce_power_stage_alarm);
3912
3913 schedule_work(&chip->reduce_power_stage_work);
3914}
3915
David Keitelbe208252013-01-31 14:49:25 -08003916static int
David Keitel432e1232013-06-05 16:10:18 -07003917qpnp_dc_power_set_property(struct power_supply *psy,
3918 enum power_supply_property psp,
3919 const union power_supply_propval *val)
3920{
3921 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3922 dc_psy);
3923 int rc = 0;
3924
3925 switch (psp) {
3926 case POWER_SUPPLY_PROP_CURRENT_MAX:
3927 if (!val->intval)
3928 break;
3929
3930 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
3931 if (rc) {
3932 pr_err("Error setting idcmax property %d\n", rc);
3933 return rc;
3934 }
3935 chip->maxinput_dc_ma = (val->intval / 1000);
3936
3937 break;
3938 default:
3939 return -EINVAL;
3940 }
3941
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003942 pr_debug("psy changed dc_psy\n");
David Keitel432e1232013-06-05 16:10:18 -07003943 power_supply_changed(&chip->dc_psy);
3944 return rc;
3945}
3946
3947static int
David Keitelbe208252013-01-31 14:49:25 -08003948qpnp_batt_power_set_property(struct power_supply *psy,
3949 enum power_supply_property psp,
3950 const union power_supply_propval *val)
3951{
3952 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3953 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07003954 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08003955
3956 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07003957 case POWER_SUPPLY_PROP_COOL_TEMP:
3958 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3959 break;
3960 case POWER_SUPPLY_PROP_WARM_TEMP:
3961 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3962 break;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08003963 case POWER_SUPPLY_PROP_CAPACITY:
3964 chip->fake_battery_soc = val->intval;
3965 power_supply_changed(&chip->batt_psy);
3966 break;
David Keitelbe208252013-01-31 14:49:25 -08003967 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
3968 chip->charging_disabled = !(val->intval);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003969 if (chip->charging_disabled) {
3970 /* disable charging */
3971 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3972 qpnp_chg_force_run_on_batt(chip,
3973 chip->charging_disabled);
3974 } else {
3975 /* enable charging */
3976 qpnp_chg_force_run_on_batt(chip,
3977 chip->charging_disabled);
3978 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3979 }
David Keitelbe208252013-01-31 14:49:25 -08003980 break;
3981 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
3982 qpnp_batt_system_temp_level_set(chip, val->intval);
3983 break;
David Keitel337bd862013-07-15 21:42:58 -07003984 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel7b0568482013-12-02 14:47:42 -08003985 if (qpnp_chg_is_usb_chg_plugged_in(chip))
3986 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
David Keitel337bd862013-07-15 21:42:58 -07003987 break;
David Keitel2586f0a2013-08-20 10:02:26 -07003988 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
3989 qpnp_chg_iusb_trim_set(chip, val->intval);
3990 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003991 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
3992 qpnp_chg_input_current_settled(chip);
3993 break;
David Keitel337bd862013-07-15 21:42:58 -07003994 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
3995 qpnp_chg_vinmin_set(chip, val->intval / 1000);
3996 break;
David Keitelbe208252013-01-31 14:49:25 -08003997 default:
3998 return -EINVAL;
3999 }
4000
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07004001 pr_debug("psy changed batt_psy\n");
David Keitelbe208252013-01-31 14:49:25 -08004002 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07004003 return rc;
David Keitelbe208252013-01-31 14:49:25 -08004004}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004005
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004006static int
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004007qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07004008{
David Keitelfe51cb92013-04-02 19:42:58 -07004009 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07004010 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07004011 if (chip->type == SMBB)
4012 chip->flags |= BOOST_FLASH_WA;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004013 if (chip->type == SMBBP) {
4014 struct device_node *revid_dev_node;
4015 struct pmic_revid_data *revid_data;
4016
4017 chip->flags |= BOOST_FLASH_WA;
4018
4019 revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
4020 "qcom,pmic-revid", 0);
4021 if (!revid_dev_node) {
4022 pr_err("Missing qcom,pmic-revid property\n");
4023 return -EINVAL;
4024 }
4025 revid_data = get_revid_data(revid_dev_node);
4026 if (IS_ERR(revid_data)) {
4027 pr_err("Couldnt get revid data rc = %ld\n",
4028 PTR_ERR(revid_data));
4029 return PTR_ERR(revid_data);
4030 }
4031
4032 if (revid_data->rev4 < PM8226_V2P1_REV4
4033 || ((revid_data->rev4 == PM8226_V2P1_REV4)
4034 && (revid_data->rev3 <= PM8226_V2P1_REV3))) {
4035 chip->flags |= POWER_STAGE_WA;
4036 }
4037 }
4038 return 0;
David Keiteld681cda2012-10-02 15:44:21 -07004039}
4040
David Keitel0f35be42013-04-16 11:10:40 -07004041static int
4042qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
4043{
4044 int rc = 0;
4045 struct resource *resource;
4046 struct spmi_resource *spmi_resource;
4047 u8 subtype;
4048 struct spmi_device *spmi = chip->spmi;
4049
4050 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
4051 if (!spmi_resource) {
4052 pr_err("qpnp_chg: spmi resource absent\n");
4053 return rc;
4054 }
4055
4056 resource = spmi_get_resource(spmi, spmi_resource,
4057 IORESOURCE_MEM, 0);
4058 if (!(resource && resource->start)) {
4059 pr_err("node %s IO resource absent!\n",
4060 spmi->dev.of_node->full_name);
4061 return rc;
4062 }
4063
4064 rc = qpnp_chg_read(chip, &subtype,
4065 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4066 if (rc) {
4067 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4068 return rc;
4069 }
4070
4071 switch (subtype) {
4072 case SMBB_CHGR_SUBTYPE:
4073 case SMBBP_CHGR_SUBTYPE:
4074 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004075 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004076 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004077 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004078 pr_err("Unable to get fast-chg-on irq\n");
4079 return rc;
4080 }
4081
David Keitel47185a62013-05-15 18:54:10 -07004082 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004083 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07004084 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004085 pr_err("Unable to get trkl-chg-on irq\n");
4086 return rc;
4087 }
4088
David Keitel47185a62013-05-15 18:54:10 -07004089 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004090 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07004091 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004092 pr_err("Unable to get chg_failed irq\n");
4093 return rc;
4094 }
4095
David Keitel47185a62013-05-15 18:54:10 -07004096 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07004097 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07004098 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07004099 pr_err("Unable to get fast-chg-on irq\n");
4100 return rc;
4101 }
4102
David Keitel47185a62013-05-15 18:54:10 -07004103 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004104 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07004105 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004106 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004107 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004108 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004109 return rc;
4110 }
4111
David Keitel47185a62013-05-15 18:54:10 -07004112 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004113 qpnp_chg_chgr_chg_fastchg_irq_handler,
Wu Fenglin64fb1ac2013-11-08 10:20:14 +08004114 IRQF_TRIGGER_RISING |
4115 IRQF_TRIGGER_FALLING,
David Keitel0f35be42013-04-16 11:10:40 -07004116 "fast-chg-on", chip);
4117 if (rc < 0) {
4118 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004119 chip->chg_fastchg.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_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004124 qpnp_chg_chgr_chg_trklchg_irq_handler,
4125 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004126 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004127 if (rc < 0) {
4128 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004129 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004130 return rc;
4131 }
David Keitel9fd07382013-05-02 15:37:44 -07004132
4133 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07004134 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07004135 qpnp_chg_vbatdet_lo_irq_handler,
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07004136 IRQF_TRIGGER_RISING,
David Keitel9fd07382013-05-02 15:37:44 -07004137 "vbat-det-lo", chip);
4138 if (rc < 0) {
4139 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004140 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07004141 return rc;
4142 }
4143
David Keitelbf6a1062014-01-23 10:57:36 -08004144 qpnp_chg_irq_wake_enable(&chip->chg_trklchg);
4145 qpnp_chg_irq_wake_enable(&chip->chg_failed);
David Keitel47185a62013-05-15 18:54:10 -07004146 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitelbf6a1062014-01-23 10:57:36 -08004147 qpnp_chg_irq_wake_enable(&chip->chg_vbatdet_lo);
David Keitel0f35be42013-04-16 11:10:40 -07004148
4149 break;
4150 case SMBB_BAT_IF_SUBTYPE:
4151 case SMBBP_BAT_IF_SUBTYPE:
4152 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004153 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004154 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07004155 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004156 pr_err("Unable to get batt-pres irq\n");
4157 return rc;
4158 }
David Keitel47185a62013-05-15 18:54:10 -07004159 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004160 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07004161 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
4162 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07004163 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004164 if (rc < 0) {
4165 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004166 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004167 return rc;
4168 }
4169
David Keitelbf6a1062014-01-23 10:57:36 -08004170 qpnp_chg_irq_wake_enable(&chip->batt_pres);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004171
4172 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
4173 spmi_resource, "bat-temp-ok");
4174 if (chip->batt_temp_ok.irq < 0) {
4175 pr_err("Unable to get bat-temp-ok irq\n");
4176 return rc;
4177 }
4178 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
4179 qpnp_chg_bat_if_batt_temp_irq_handler,
4180 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
4181 "bat-temp-ok", chip);
4182 if (rc < 0) {
4183 pr_err("Can't request %d bat-temp-ok irq: %d\n",
4184 chip->batt_temp_ok.irq, rc);
4185 return rc;
4186 }
Xiaozhe Shi6c726652014-01-03 15:45:14 -08004187 qpnp_chg_bat_if_batt_temp_irq_handler(0, chip);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004188
David Keitelbf6a1062014-01-23 10:57:36 -08004189 qpnp_chg_irq_wake_enable(&chip->batt_temp_ok);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07004190
David Keitel0f35be42013-04-16 11:10:40 -07004191 break;
David Keitel337bd862013-07-15 21:42:58 -07004192 case SMBB_BUCK_SUBTYPE:
4193 case SMBBP_BUCK_SUBTYPE:
4194 case SMBCL_BUCK_SUBTYPE:
David Keitel337bd862013-07-15 21:42:58 -07004195 break;
4196
David Keitel0f35be42013-04-16 11:10:40 -07004197 case SMBB_USB_CHGPTH_SUBTYPE:
4198 case SMBBP_USB_CHGPTH_SUBTYPE:
4199 case SMBCL_USB_CHGPTH_SUBTYPE:
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004200 if (chip->ovp_monitor_enable) {
4201 chip->coarse_det_usb.irq =
4202 spmi_get_irq_byname(spmi,
4203 spmi_resource, "coarse-det-usb");
4204 if (chip->coarse_det_usb.irq < 0) {
4205 pr_err("Can't get coarse-det irq\n");
4206 return rc;
4207 }
4208 rc = devm_request_irq(chip->dev,
4209 chip->coarse_det_usb.irq,
4210 qpnp_chg_coarse_det_usb_irq_handler,
4211 IRQF_TRIGGER_RISING |
4212 IRQF_TRIGGER_FALLING,
4213 "coarse-det-usb", chip);
4214 if (rc < 0) {
4215 pr_err("Can't req %d coarse-det: %d\n",
4216 chip->coarse_det_usb.irq, rc);
4217 return rc;
4218 }
4219 }
4220
David Keitel47185a62013-05-15 18:54:10 -07004221 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004222 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004223 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004224 pr_err("Unable to get usbin irq\n");
4225 return rc;
4226 }
David Keitel47185a62013-05-15 18:54:10 -07004227 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004228 qpnp_chg_usb_usbin_valid_irq_handler,
4229 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004230 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004231 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004232 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004233 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004234 return rc;
4235 }
David Keitel344c6972013-04-09 19:28:21 -07004236
David Keitel47185a62013-05-15 18:54:10 -07004237 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07004238 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07004239 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07004240 pr_err("Unable to get chg-gone irq\n");
4241 return rc;
4242 }
David Keitel47185a62013-05-15 18:54:10 -07004243 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07004244 qpnp_chg_usb_chg_gone_irq_handler,
4245 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07004246 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07004247 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004248 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004249 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07004250 return rc;
4251 }
David Keitel47185a62013-05-15 18:54:10 -07004252
David Keitel0b62bdd2013-07-10 17:30:51 -07004253 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4254 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4255 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
4256 spmi_resource, "usb-ocp");
4257 if (chip->usb_ocp.irq < 0) {
4258 pr_err("Unable to get usbin irq\n");
4259 return rc;
4260 }
4261 rc = devm_request_irq(chip->dev,
4262 chip->usb_ocp.irq,
4263 qpnp_chg_usb_usb_ocp_irq_handler,
4264 IRQF_TRIGGER_RISING, "usb-ocp", chip);
4265 if (rc < 0) {
4266 pr_err("Can't request %d usb-ocp: %d\n",
4267 chip->usb_ocp.irq, rc);
4268 return rc;
4269 }
4270
David Keitelbf6a1062014-01-23 10:57:36 -08004271 qpnp_chg_irq_wake_enable(&chip->usb_ocp);
David Keitel0b62bdd2013-07-10 17:30:51 -07004272 }
4273
David Keitelbf6a1062014-01-23 10:57:36 -08004274 qpnp_chg_irq_wake_enable(&chip->usbin_valid);
4275 qpnp_chg_irq_wake_enable(&chip->chg_gone);
David Keitel0f35be42013-04-16 11:10:40 -07004276 break;
4277 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07004278 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07004279 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07004280 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07004281 pr_err("Unable to get dcin irq\n");
4282 return -rc;
4283 }
David Keitel47185a62013-05-15 18:54:10 -07004284 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07004285 qpnp_chg_dc_dcin_valid_irq_handler,
4286 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07004287 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07004288 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07004289 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07004290 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07004291 return rc;
4292 }
4293
David Keitelbf6a1062014-01-23 10:57:36 -08004294 qpnp_chg_irq_wake_enable(&chip->dcin_valid);
David Keitel0f35be42013-04-16 11:10:40 -07004295 break;
4296 }
4297 }
4298
4299 return rc;
4300}
4301
Xiaozhe Shica289e02013-06-19 13:24:51 -07004302static int
4303qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
4304{
4305 struct bms_battery_data batt_data;
4306 struct device_node *node;
4307 struct qpnp_vadc_result result;
4308 int rc;
4309
4310 node = of_find_node_by_name(chip->spmi->dev.of_node,
4311 "qcom,battery-data");
4312 if (node) {
4313 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004314 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07004315 if (rc) {
4316 pr_err("error reading batt id channel = %d, rc = %d\n",
4317 LR_MUX2_BAT_ID, rc);
4318 return rc;
4319 }
4320
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07004321 batt_data.max_voltage_uv = -1;
4322 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07004323 rc = of_batterydata_read_data(node,
4324 &batt_data, result.physical);
4325 if (rc) {
4326 pr_err("failed to read battery data: %d\n", rc);
4327 return rc;
4328 }
4329
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004330 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07004331 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07004332 chip->safe_voltage_mv = chip->max_voltage_mv
4333 + MAX_DELTA_VDD_MAX_MV;
4334 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004335 if (batt_data.iterm_ua >= 0)
4336 chip->term_current = batt_data.iterm_ua / 1000;
4337 }
4338
4339 return 0;
4340}
4341
David Keitel80668952012-07-27 14:25:49 -07004342#define WDOG_EN_BIT BIT(7)
4343static int
4344qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
4345 struct spmi_resource *spmi_resource)
4346{
4347 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004348 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07004349 struct regulator_init_data *init_data;
4350 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07004351
4352 switch (subtype) {
4353 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004354 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004355 case SMBCL_CHGR_SUBTYPE:
Prasad Sodagudic3678012013-09-23 12:01:19 +05304356 qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
4357
David Keitel80668952012-07-27 14:25:49 -07004358 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
4359 if (rc) {
4360 pr_debug("failed setting min_voltage rc=%d\n", rc);
4361 return rc;
4362 }
David Keitel80668952012-07-27 14:25:49 -07004363 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
4364 if (rc) {
4365 pr_debug("failed setting safe_voltage rc=%d\n", rc);
4366 return rc;
4367 }
David Keitel454ee842013-03-08 16:19:11 -08004368 rc = qpnp_chg_vbatdet_set(chip,
4369 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08004370 if (rc) {
4371 pr_debug("failed setting resume_voltage rc=%d\n", rc);
4372 return rc;
4373 }
David Keitel80668952012-07-27 14:25:49 -07004374 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
4375 if (rc) {
4376 pr_debug("failed setting ibatmax rc=%d\n", rc);
4377 return rc;
4378 }
David Keitel365c4c42013-03-08 16:20:40 -08004379 if (chip->term_current) {
4380 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
4381 if (rc) {
4382 pr_debug("failed setting ibatterm rc=%d\n", rc);
4383 return rc;
4384 }
David Keitel80668952012-07-27 14:25:49 -07004385 }
David Keitel5d44fa52012-12-03 16:37:31 -08004386 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
4387 if (rc) {
4388 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
4389 return rc;
4390 }
David Keitela4b7b592013-04-11 18:34:35 -07004391 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
4392 if (rc) {
4393 pr_debug("failed setting tchg_mins rc=%d\n", rc);
4394 return rc;
4395 }
4396
David Keitel80668952012-07-27 14:25:49 -07004397 /* HACK: Disable wdog */
4398 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
4399 0xFF, 0xA0, 1);
4400
David Keitelb4e43542013-04-09 17:30:41 -07004401 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07004402 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
4403 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07004404 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07004405
David Keitel80668952012-07-27 14:25:49 -07004406 break;
4407 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004408 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004409 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004410 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
4411 if (rc)
4412 return rc;
4413
David Keitel9201df32013-01-10 18:38:34 -08004414 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07004415 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08004416 BUCK_VBAT_REG_NODE_SEL_BIT,
4417 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
4418 if (rc) {
4419 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
4420 return rc;
4421 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07004422
4423 rc = qpnp_chg_read(chip, &chip->trim_center,
4424 chip->buck_base + BUCK_CTRL_TRIM1, 1);
4425 if (rc) {
4426 pr_debug("failed to read trim center rc=%d\n", rc);
4427 return rc;
4428 }
4429 chip->trim_center >>= 4;
4430 pr_debug("trim center = %02x\n", chip->trim_center);
David Keitel80668952012-07-27 14:25:49 -07004431 break;
4432 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004433 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004434 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07004435 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07004436 switch (chip->bpd_detection) {
4437 case BPD_TYPE_BAT_THM:
4438 reg = BAT_THM_EN;
4439 break;
4440 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07004441 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07004442 break;
4443 case BPD_TYPE_BAT_THM_BAT_ID:
4444 reg = BAT_THM_EN | BAT_ID_EN;
4445 break;
4446 default:
4447 reg = BAT_THM_EN;
4448 break;
4449 }
David Keitel796882d2013-05-14 18:01:11 -07004450
4451 rc = qpnp_chg_masked_write(chip,
4452 chip->bat_if_base + BAT_IF_BPD_CTRL,
4453 BAT_IF_BPD_CTRL_SEL,
4454 reg, 1);
4455 if (rc) {
4456 pr_debug("failed to chose BPD rc=%d\n", rc);
4457 return rc;
4458 }
David Keitel85ae4342013-04-16 11:46:00 -07004459 /* Force on VREF_BAT_THM */
4460 rc = qpnp_chg_masked_write(chip,
4461 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4462 VREF_BATT_THERM_FORCE_ON,
4463 VREF_BATT_THERM_FORCE_ON, 1);
4464 if (rc) {
4465 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
4466 return rc;
4467 }
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07004468
4469 init_data = of_get_regulator_init_data(chip->dev,
4470 spmi_resource->of_node);
4471
4472 if (init_data->constraints.name) {
4473 rdesc = &(chip->batfet_vreg.rdesc);
4474 rdesc->owner = THIS_MODULE;
4475 rdesc->type = REGULATOR_VOLTAGE;
4476 rdesc->ops = &qpnp_chg_batfet_vreg_ops;
4477 rdesc->name = init_data->constraints.name;
4478
4479 init_data->constraints.valid_ops_mask
4480 |= REGULATOR_CHANGE_STATUS;
4481
4482 chip->batfet_vreg.rdev = regulator_register(rdesc,
4483 chip->dev, init_data, chip,
4484 spmi_resource->of_node);
4485 if (IS_ERR(chip->batfet_vreg.rdev)) {
4486 rc = PTR_ERR(chip->batfet_vreg.rdev);
4487 chip->batfet_vreg.rdev = NULL;
4488 if (rc != -EPROBE_DEFER)
4489 pr_err("batfet reg failed, rc=%d\n",
4490 rc);
4491 return rc;
4492 }
4493 }
David Keitel80668952012-07-27 14:25:49 -07004494 break;
4495 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004496 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004497 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004498 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07004499 rc = qpnp_chg_masked_write(chip,
4500 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4501 ENUM_T_STOP_BIT,
4502 ENUM_T_STOP_BIT, 1);
4503 if (rc) {
4504 pr_err("failed to write enum stop rc=%d\n", rc);
4505 return -ENXIO;
4506 }
4507 }
David Keiteld681cda2012-10-02 15:44:21 -07004508
David Keitel6dc4ed42013-05-17 11:08:58 -07004509 init_data = of_get_regulator_init_data(chip->dev,
4510 spmi_resource->of_node);
4511 if (!init_data) {
4512 pr_err("unable to allocate memory\n");
4513 return -ENOMEM;
4514 }
4515
4516 if (init_data->constraints.name) {
4517 if (of_get_property(chip->dev->of_node,
4518 "otg-parent-supply", NULL))
4519 init_data->supply_regulator = "otg-parent";
4520
4521 rdesc = &(chip->otg_vreg.rdesc);
4522 rdesc->owner = THIS_MODULE;
4523 rdesc->type = REGULATOR_VOLTAGE;
4524 rdesc->ops = &qpnp_chg_otg_reg_ops;
4525 rdesc->name = init_data->constraints.name;
4526
4527 init_data->constraints.valid_ops_mask
4528 |= REGULATOR_CHANGE_STATUS;
4529
4530 chip->otg_vreg.rdev = regulator_register(rdesc,
4531 chip->dev, init_data, chip,
4532 spmi_resource->of_node);
4533 if (IS_ERR(chip->otg_vreg.rdev)) {
4534 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004535 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004536 if (rc != -EPROBE_DEFER)
4537 pr_err("OTG reg failed, rc=%d\n", rc);
4538 return rc;
4539 }
4540 }
4541
David Keiteld681cda2012-10-02 15:44:21 -07004542 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08004543 chip->usb_chgpth_base + USB_OVP_CTL,
4544 USB_VALID_DEB_20MS,
4545 USB_VALID_DEB_20MS, 1);
4546
4547 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07004548 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4549 ENUM_T_STOP_BIT,
4550 ENUM_T_STOP_BIT, 1);
4551
David Keitel344c6972013-04-09 19:28:21 -07004552 rc = qpnp_chg_masked_write(chip,
4553 chip->usb_chgpth_base + SEC_ACCESS,
4554 0xFF,
4555 0xA5, 1);
4556
4557 rc = qpnp_chg_masked_write(chip,
4558 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
4559 0xFF,
4560 0x80, 1);
4561
David Keitel0b62bdd2013-07-10 17:30:51 -07004562 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4563 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4564 rc = qpnp_chg_masked_write(chip,
4565 chip->usb_chgpth_base + USB_OCP_THR,
4566 OCP_THR_MASK,
4567 OCP_THR_900_MA, 1);
4568 if (rc)
4569 pr_err("Failed to configure OCP rc = %d\n", rc);
4570 }
4571
David Keitel80668952012-07-27 14:25:49 -07004572 break;
4573 case SMBB_DC_CHGPTH_SUBTYPE:
4574 break;
4575 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004576 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07004577 init_data = of_get_regulator_init_data(chip->dev,
4578 spmi_resource->of_node);
4579 if (!init_data) {
4580 pr_err("unable to allocate memory\n");
4581 return -ENOMEM;
4582 }
4583
4584 if (init_data->constraints.name) {
4585 if (of_get_property(chip->dev->of_node,
4586 "boost-parent-supply", NULL))
4587 init_data->supply_regulator = "boost-parent";
4588
4589 rdesc = &(chip->boost_vreg.rdesc);
4590 rdesc->owner = THIS_MODULE;
4591 rdesc->type = REGULATOR_VOLTAGE;
4592 rdesc->ops = &qpnp_chg_boost_reg_ops;
4593 rdesc->name = init_data->constraints.name;
4594
4595 init_data->constraints.valid_ops_mask
4596 |= REGULATOR_CHANGE_STATUS
4597 | REGULATOR_CHANGE_VOLTAGE;
4598
4599 chip->boost_vreg.rdev = regulator_register(rdesc,
4600 chip->dev, init_data, chip,
4601 spmi_resource->of_node);
4602 if (IS_ERR(chip->boost_vreg.rdev)) {
4603 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004604 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004605 if (rc != -EPROBE_DEFER)
4606 pr_err("boost reg failed, rc=%d\n", rc);
4607 return rc;
4608 }
4609 }
David Keitel80668952012-07-27 14:25:49 -07004610 break;
4611 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004612 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004613 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07004614 if (subtype == SMBB_MISC_SUBTYPE)
4615 chip->type = SMBB;
4616 else if (subtype == SMBBP_MISC_SUBTYPE)
4617 chip->type = SMBBP;
4618 else if (subtype == SMBCL_MISC_SUBTYPE)
4619 chip->type = SMBCL;
4620
David Keitel80668952012-07-27 14:25:49 -07004621 pr_debug("Setting BOOT_DONE\n");
4622 rc = qpnp_chg_masked_write(chip,
4623 chip->misc_base + CHGR_MISC_BOOT_DONE,
4624 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004625 rc = qpnp_chg_read(chip, &reg,
4626 chip->misc_base + MISC_REVISION2, 1);
4627 if (rc) {
4628 pr_err("failed to read revision register rc=%d\n", rc);
4629 return rc;
4630 }
David Keitel80668952012-07-27 14:25:49 -07004631
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004632 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07004633 break;
4634 default:
4635 pr_err("Invalid peripheral subtype\n");
4636 }
4637 return rc;
4638}
4639
David Keitel112ba9c2013-04-12 18:40:43 -07004640#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
4641do { \
4642 if (retval) \
4643 break; \
4644 \
4645 retval = of_property_read_u32(chip->spmi->dev.of_node, \
4646 "qcom," qpnp_dt_property, \
4647 &chip->prop); \
4648 \
4649 if ((retval == -EINVAL) && optional) \
4650 retval = 0; \
4651 else if (retval) \
4652 pr_err("Error reading " #qpnp_dt_property \
4653 " property rc = %d\n", rc); \
4654} while (0)
4655
4656static int
4657qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
4658{
4659 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004660 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07004661
4662 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
4663 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
4664 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
4665 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
4666 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
4667 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
4668 if (rc)
4669 pr_err("failed to read required dt parameters %d\n", rc);
4670
4671 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
4672 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
4673 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
4674 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
4675 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07004676 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07004677 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
4678 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004679 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
Prasad Sodagudic3678012013-09-23 12:01:19 +05304680 OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
David Keitelbdbae452014-01-14 17:19:50 -08004681 OF_PROP_READ(chip, vbatdet_max_err_mv, "vbatdet-maxerr-mv", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004682
David Keitel112ba9c2013-04-12 18:40:43 -07004683 if (rc)
4684 return rc;
4685
David Keitel796882d2013-05-14 18:01:11 -07004686 rc = of_property_read_string(chip->spmi->dev.of_node,
4687 "qcom,bpd-detection", &bpd);
4688 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07004689 /* Select BAT_THM as default BPD scheme */
4690 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004691 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004692 } else {
4693 chip->bpd_detection = get_bpd(bpd);
4694 if (chip->bpd_detection < 0) {
4695 pr_err("failed to determine bpd schema %d\n", rc);
4696 return rc;
4697 }
4698 }
4699
David Keitelbdbae452014-01-14 17:19:50 -08004700 if (!chip->vbatdet_max_err_mv)
4701 chip->vbatdet_max_err_mv = VBATDET_MAX_ERR_MV;
4702
David Keitel112ba9c2013-04-12 18:40:43 -07004703 /* Look up JEITA compliance parameters if cool and warm temp provided */
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004704 if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004705 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
4706 if (IS_ERR(chip->adc_tm_dev)) {
4707 rc = PTR_ERR(chip->adc_tm_dev);
4708 if (rc != -EPROBE_DEFER)
4709 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07004710 return rc;
4711 }
4712
4713 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
4714 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
4715 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
4716 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
4717 if (rc)
4718 return rc;
4719 }
4720
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08004721 /* Get the use-external-rsense property */
4722 chip->use_external_rsense = of_property_read_bool(
4723 chip->spmi->dev.of_node,
4724 "qcom,use-external-rsense");
4725
David Keitel89c17752013-06-28 14:52:48 -07004726 /* Get the btc-disabled property */
4727 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4728 "qcom,btc-disabled");
4729
David Keitel2586f0a2013-08-20 10:02:26 -07004730 ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
4731 "qcom,ext-ovp-present");
4732
David Keitel112ba9c2013-04-12 18:40:43 -07004733 /* Get the charging-disabled property */
4734 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4735 "qcom,charging-disabled");
4736
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004737 chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
4738 "qcom,ovp-monitor-en");
4739
David Keitel8b68d2d2013-05-14 23:36:51 -07004740 /* Get the duty-cycle-100p property */
4741 chip->duty_cycle_100p = of_property_read_bool(
4742 chip->spmi->dev.of_node,
4743 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07004744
David Keitel112ba9c2013-04-12 18:40:43 -07004745 /* Get the fake-batt-values property */
4746 chip->use_default_batt_values =
4747 of_property_read_bool(chip->spmi->dev.of_node,
4748 "qcom,use-default-batt-values");
4749
4750 /* Disable charging when faking battery values */
4751 if (chip->use_default_batt_values)
4752 chip->charging_disabled = true;
4753
Zhenhua Huangdc335512013-10-30 11:45:15 +08004754 chip->power_stage_workaround_enable =
4755 of_property_read_bool(chip->spmi->dev.of_node,
4756 "qcom,power-stage-reduced");
4757
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004758 chip->ibat_calibration_enabled =
4759 of_property_read_bool(chip->spmi->dev.of_node,
4760 "qcom,ibat-calibration-enabled");
David Keitel975b5352014-01-27 14:28:04 -08004761 chip->parallel_ovp_mode =
4762 of_property_read_bool(chip->spmi->dev.of_node,
4763 "qcom,parallel-ovp-mode");
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004764
David Keitel112ba9c2013-04-12 18:40:43 -07004765 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
4766 &(chip->thermal_levels));
4767
4768 if (chip->thermal_levels > sizeof(int)) {
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304769 chip->thermal_mitigation = devm_kzalloc(chip->dev,
David Keitel112ba9c2013-04-12 18:40:43 -07004770 chip->thermal_levels,
4771 GFP_KERNEL);
4772
4773 if (chip->thermal_mitigation == NULL) {
4774 pr_err("thermal mitigation kzalloc() failed.\n");
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304775 return -ENOMEM;
David Keitel112ba9c2013-04-12 18:40:43 -07004776 }
4777
4778 chip->thermal_levels /= sizeof(int);
4779 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
4780 "qcom,thermal-mitigation",
4781 chip->thermal_mitigation, chip->thermal_levels);
4782 if (rc) {
4783 pr_err("qcom,thermal-mitigation missing in dt\n");
4784 return rc;
4785 }
4786 }
4787
4788 return rc;
4789}
4790
David Keitel80668952012-07-27 14:25:49 -07004791static int __devinit
4792qpnp_charger_probe(struct spmi_device *spmi)
4793{
4794 u8 subtype;
4795 struct qpnp_chg_chip *chip;
4796 struct resource *resource;
4797 struct spmi_resource *spmi_resource;
4798 int rc = 0;
4799
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304800 chip = devm_kzalloc(&spmi->dev,
4801 sizeof(struct qpnp_chg_chip), GFP_KERNEL);
David Keitel80668952012-07-27 14:25:49 -07004802 if (chip == NULL) {
4803 pr_err("kzalloc() failed.\n");
4804 return -ENOMEM;
4805 }
4806
David Keitelfd305ee2013-07-19 20:19:06 -07004807 chip->prev_usb_max_ma = -EINVAL;
Xiaozhe Shi78797cf2013-11-12 13:18:42 -08004808 chip->fake_battery_soc = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07004809 chip->dev = &(spmi->dev);
4810 chip->spmi = spmi;
4811
4812 chip->usb_psy = power_supply_get_by_name("usb");
4813 if (!chip->usb_psy) {
4814 pr_err("usb supply not found deferring probe\n");
4815 rc = -EPROBE_DEFER;
4816 goto fail_chg_enable;
4817 }
4818
David Keitelec3c09802013-06-13 13:05:30 -07004819 mutex_init(&chip->jeita_configure_lock);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004820 spin_lock_init(&chip->usbin_health_monitor_lock);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004821 alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
4822 qpnp_chg_reduce_power_stage_callback);
4823 INIT_WORK(&chip->reduce_power_stage_work,
4824 qpnp_chg_reduce_power_stage_work);
David Keitel6e63bd52013-09-06 18:00:03 -07004825 mutex_init(&chip->batfet_vreg_lock);
David Keitel8b9bd312014-01-15 14:44:00 -08004826 INIT_WORK(&chip->ocp_clear_work,
4827 qpnp_chg_ocp_clear_work);
David Keitel6e63bd52013-09-06 18:00:03 -07004828 INIT_WORK(&chip->batfet_lcl_work,
4829 qpnp_chg_batfet_lcl_work);
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004830 INIT_WORK(&chip->insertion_ocv_work,
4831 qpnp_chg_insertion_ocv_work);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004832
David Keitel112ba9c2013-04-12 18:40:43 -07004833 /* Get all device tree properties */
4834 rc = qpnp_charger_read_dt_props(chip);
4835 if (rc)
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304836 return rc;
David Keitel3dd5e0f2012-12-12 18:12:36 -08004837
Xiaozhe Shica289e02013-06-19 13:24:51 -07004838 /*
4839 * Check if bat_if is set in DT and make sure VADC is present
4840 * Also try loading the battery data profile if bat_if exists
4841 */
David Keiteldd87a172013-05-29 17:05:43 -07004842 spmi_for_each_container_dev(spmi_resource, spmi) {
4843 if (!spmi_resource) {
4844 pr_err("qpnp_chg: spmi resource absent\n");
4845 rc = -ENXIO;
4846 goto fail_chg_enable;
4847 }
4848
4849 resource = spmi_get_resource(spmi, spmi_resource,
4850 IORESOURCE_MEM, 0);
4851 if (!(resource && resource->start)) {
4852 pr_err("node %s IO resource absent!\n",
4853 spmi->dev.of_node->full_name);
4854 rc = -ENXIO;
4855 goto fail_chg_enable;
4856 }
4857
4858 rc = qpnp_chg_read(chip, &subtype,
4859 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4860 if (rc) {
4861 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4862 goto fail_chg_enable;
4863 }
4864
4865 if (subtype == SMBB_BAT_IF_SUBTYPE ||
4866 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004867 subtype == SMBCL_BAT_IF_SUBTYPE) {
4868 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
4869 if (IS_ERR(chip->vadc_dev)) {
4870 rc = PTR_ERR(chip->vadc_dev);
4871 if (rc != -EPROBE_DEFER)
4872 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07004873 goto fail_chg_enable;
David Keitel42648fd2013-08-16 17:45:20 -07004874 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004875
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08004876 if (subtype == SMBB_BAT_IF_SUBTYPE) {
4877 chip->iadc_dev = qpnp_get_iadc(chip->dev,
4878 "chg");
4879 if (IS_ERR(chip->iadc_dev)) {
4880 rc = PTR_ERR(chip->iadc_dev);
4881 if (rc != -EPROBE_DEFER)
4882 pr_err("iadc property missing\n");
4883 goto fail_chg_enable;
4884 }
4885 }
4886
Xiaozhe Shica289e02013-06-19 13:24:51 -07004887 rc = qpnp_chg_load_battery_data(chip);
4888 if (rc)
4889 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07004890 }
4891 }
4892
David Keitel80668952012-07-27 14:25:49 -07004893 spmi_for_each_container_dev(spmi_resource, spmi) {
4894 if (!spmi_resource) {
4895 pr_err("qpnp_chg: spmi resource absent\n");
4896 rc = -ENXIO;
4897 goto fail_chg_enable;
4898 }
4899
4900 resource = spmi_get_resource(spmi, spmi_resource,
4901 IORESOURCE_MEM, 0);
4902 if (!(resource && resource->start)) {
4903 pr_err("node %s IO resource absent!\n",
4904 spmi->dev.of_node->full_name);
4905 rc = -ENXIO;
4906 goto fail_chg_enable;
4907 }
4908
4909 rc = qpnp_chg_read(chip, &subtype,
4910 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4911 if (rc) {
4912 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4913 goto fail_chg_enable;
4914 }
4915
4916 switch (subtype) {
4917 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004918 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004919 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004920 chip->chgr_base = resource->start;
4921 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4922 if (rc) {
4923 pr_err("Failed to init subtype 0x%x rc=%d\n",
4924 subtype, rc);
4925 goto fail_chg_enable;
4926 }
4927 break;
4928 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004929 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004930 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004931 chip->buck_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 }
David Keitel344c6972013-04-09 19:28:21 -07004938
4939 rc = qpnp_chg_masked_write(chip,
4940 chip->buck_base + SEC_ACCESS,
4941 0xFF,
4942 0xA5, 1);
4943
4944 rc = qpnp_chg_masked_write(chip,
4945 chip->buck_base + BUCK_VCHG_OV,
4946 0xff,
4947 0x00, 1);
4948
David Keiteldbc949b2013-07-11 10:56:03 -07004949 if (chip->duty_cycle_100p) {
4950 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
4951 1);
4952 if (rc) {
4953 pr_err("failed to set duty cycle %d\n",
4954 rc);
4955 goto fail_chg_enable;
4956 }
4957 }
4958
David Keitel80668952012-07-27 14:25:49 -07004959 break;
4960 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004961 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004962 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004963 chip->bat_if_base = resource->start;
4964 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4965 if (rc) {
4966 pr_err("Failed to init subtype 0x%x rc=%d\n",
4967 subtype, rc);
4968 goto fail_chg_enable;
4969 }
4970 break;
4971 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004972 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004973 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004974 chip->usb_chgpth_base = resource->start;
4975 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4976 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07004977 if (rc != -EPROBE_DEFER)
4978 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07004979 subtype, rc);
4980 goto fail_chg_enable;
4981 }
4982 break;
4983 case SMBB_DC_CHGPTH_SUBTYPE:
4984 chip->dc_chgpth_base = resource->start;
4985 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4986 if (rc) {
4987 pr_err("Failed to init subtype 0x%x rc=%d\n",
4988 subtype, rc);
4989 goto fail_chg_enable;
4990 }
4991 break;
4992 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004993 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004994 chip->boost_base = resource->start;
4995 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4996 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07004997 if (rc != -EPROBE_DEFER)
4998 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07004999 subtype, rc);
5000 goto fail_chg_enable;
5001 }
5002 break;
5003 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08005004 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07005005 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07005006 chip->misc_base = resource->start;
5007 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
5008 if (rc) {
5009 pr_err("Failed to init subtype=0x%x rc=%d\n",
5010 subtype, rc);
5011 goto fail_chg_enable;
5012 }
5013 break;
5014 default:
5015 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
5016 rc = -EINVAL;
5017 goto fail_chg_enable;
5018 }
5019 }
5020 dev_set_drvdata(&spmi->dev, chip);
5021 device_init_wakeup(&spmi->dev, 1);
5022
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07005023 chip->insertion_ocv_uv = -EINVAL;
5024 chip->batt_present = qpnp_chg_is_batt_present(chip);
David Keitelf2170cc2013-02-20 17:49:03 -08005025 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08005026 chip->batt_psy.name = "battery";
5027 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
5028 chip->batt_psy.properties = msm_batt_power_props;
5029 chip->batt_psy.num_properties =
5030 ARRAY_SIZE(msm_batt_power_props);
5031 chip->batt_psy.get_property = qpnp_batt_power_get_property;
5032 chip->batt_psy.set_property = qpnp_batt_power_set_property;
5033 chip->batt_psy.property_is_writeable =
5034 qpnp_batt_property_is_writeable;
5035 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07005036 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07005037 chip->batt_psy.supplied_to = pm_batt_supplied_to;
5038 chip->batt_psy.num_supplicants =
5039 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07005040
David Keitelf2170cc2013-02-20 17:49:03 -08005041 rc = power_supply_register(chip->dev, &chip->batt_psy);
5042 if (rc < 0) {
5043 pr_err("batt failed to register rc = %d\n", rc);
5044 goto fail_chg_enable;
5045 }
David Keitel79f4c932013-04-03 16:08:39 -07005046 INIT_WORK(&chip->adc_measure_work,
5047 qpnp_bat_if_adc_measure_work);
David Keitelaa375562013-08-08 09:43:28 -07005048 INIT_WORK(&chip->adc_disable_work,
David Keitelecab15a2013-08-06 15:41:39 -07005049 qpnp_bat_if_adc_disable_work);
David Keitelc7093b02013-02-14 12:50:04 -08005050 }
5051
David Keitel9fd07382013-05-02 15:37:44 -07005052 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07005053 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08005054 INIT_DELAYED_WORK(&chip->usbin_health_check,
5055 qpnp_usbin_health_check_work);
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07005056 INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
David Keitel7ac385e2013-08-19 18:02:40 -07005057 INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
David Keitel5910eea2013-05-02 15:32:25 -07005058
David Keitelf2170cc2013-02-20 17:49:03 -08005059 if (chip->dc_chgpth_base) {
5060 chip->dc_psy.name = "qpnp-dc";
5061 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
5062 chip->dc_psy.supplied_to = pm_power_supplied_to;
5063 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
5064 chip->dc_psy.properties = pm_power_props_mains;
5065 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
5066 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07005067 chip->dc_psy.set_property = qpnp_dc_power_set_property;
5068 chip->dc_psy.property_is_writeable =
5069 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08005070
5071 rc = power_supply_register(chip->dev, &chip->dc_psy);
5072 if (rc < 0) {
5073 pr_err("power_supply_register dc failed rc=%d\n", rc);
5074 goto unregister_batt;
5075 }
David Keitel80668952012-07-27 14:25:49 -07005076 }
5077
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005078 /* Turn on appropriate workaround flags */
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005079 rc = qpnp_chg_setup_flags(chip);
5080 if (rc < 0) {
5081 pr_err("failed to setup flags rc=%d\n", rc);
5082 goto unregister_dc_psy;
5083 }
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08005084
David Keitelf2170cc2013-02-20 17:49:03 -08005085 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08005086 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
5087 if (rc) {
5088 pr_err("Error setting idcmax property %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005089 goto unregister_dc_psy;
David Keitel22ed2232013-01-28 11:04:07 -08005090 }
5091 }
5092
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005093 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0aea18a2013-06-14 18:57:57 -07005094 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07005095 chip->adc_param.low_temp = chip->cool_bat_decidegc;
5096 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08005097 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
5098 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
5099 chip->adc_param.btm_ctx = chip;
5100 chip->adc_param.threshold_notification =
5101 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08005102 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07005103
5104 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005105 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
5106 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005107 if (rc) {
5108 pr_err("request ADC error %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005109 goto unregister_dc_psy;
David Keitel0c1a4532013-03-21 16:39:06 -07005110 }
David Keitel454ee842013-03-08 16:19:11 -08005111 }
5112 }
David Keitel89c17752013-06-28 14:52:48 -07005113 rc = qpnp_chg_bat_if_configure_btc(chip);
5114 if (rc) {
5115 pr_err("failed to configure btc %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005116 goto unregister_dc_psy;
David Keitel89c17752013-06-28 14:52:48 -07005117 }
David Keitel454ee842013-03-08 16:19:11 -08005118
David Keitel03ee6b52012-10-22 12:25:19 -07005119 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08005120 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07005121 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07005122
David Keitel0f35be42013-04-16 11:10:40 -07005123 rc = qpnp_chg_request_irqs(chip);
5124 if (rc) {
5125 pr_err("failed to request interrupts %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005126 goto unregister_dc_psy;
David Keitel0f35be42013-04-16 11:10:40 -07005127 }
5128
David Keitel7e38f512013-11-19 11:15:11 -08005129 qpnp_chg_usb_chg_gone_irq_handler(chip->chg_gone.irq, chip);
David Keitelad980fc2013-07-30 18:12:02 -07005130 qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
5131 qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
David Keitel9fd07382013-05-02 15:37:44 -07005132 power_supply_set_present(chip->usb_psy,
5133 qpnp_chg_is_usb_chg_plugged_in(chip));
5134
David Keitel3c62b472013-05-06 15:38:11 -07005135 /* Set USB psy online to avoid userspace from shutting down if battery
5136 * capacity is at zero and no chargers online. */
5137 if (qpnp_chg_is_usb_chg_plugged_in(chip))
5138 power_supply_set_online(chip->usb_psy, 1);
5139
David Keitel7ac385e2013-08-19 18:02:40 -07005140 schedule_delayed_work(&chip->aicl_check_work,
5141 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel796882d2013-05-14 18:01:11 -07005142 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 -08005143 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07005144 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08005145 qpnp_chg_is_usb_chg_plugged_in(chip),
5146 qpnp_chg_is_dc_chg_plugged_in(chip),
5147 get_prop_batt_present(chip),
5148 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07005149 return 0;
5150
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07005151unregister_dc_psy:
5152 if (chip->dc_chgpth_base)
5153 power_supply_unregister(&chip->dc_psy);
David Keitelc7093b02013-02-14 12:50:04 -08005154unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08005155 if (chip->bat_if_base)
5156 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07005157fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07005158 regulator_unregister(chip->otg_vreg.rdev);
5159 regulator_unregister(chip->boost_vreg.rdev);
David Keitel80668952012-07-27 14:25:49 -07005160 return rc;
5161}
5162
5163static int __devexit
5164qpnp_charger_remove(struct spmi_device *spmi)
5165{
5166 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08005167 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07005168 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07005169 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
5170 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07005171 }
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305172
5173 cancel_delayed_work_sync(&chip->aicl_check_work);
5174 power_supply_unregister(&chip->dc_psy);
5175 cancel_work_sync(&chip->soc_check_work);
5176 cancel_delayed_work_sync(&chip->usbin_health_check);
5177 cancel_delayed_work_sync(&chip->arb_stop_work);
David Keitel9fd07382013-05-02 15:37:44 -07005178 cancel_delayed_work_sync(&chip->eoc_work);
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05305179 cancel_work_sync(&chip->adc_disable_work);
5180 cancel_work_sync(&chip->adc_measure_work);
5181 power_supply_unregister(&chip->batt_psy);
5182 cancel_work_sync(&chip->batfet_lcl_work);
5183 cancel_work_sync(&chip->insertion_ocv_work);
5184 cancel_work_sync(&chip->reduce_power_stage_work);
5185 alarm_cancel(&chip->reduce_power_stage_alarm);
5186
5187 mutex_destroy(&chip->batfet_vreg_lock);
5188 mutex_destroy(&chip->jeita_configure_lock);
David Keitel79f4c932013-04-03 16:08:39 -07005189
David Collinscbb12132013-05-28 10:47:28 -07005190 regulator_unregister(chip->otg_vreg.rdev);
5191 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07005192
David Keitel80668952012-07-27 14:25:49 -07005193 return 0;
5194}
5195
David Keitel85ae4342013-04-16 11:46:00 -07005196static int qpnp_chg_resume(struct device *dev)
5197{
5198 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5199 int rc = 0;
5200
David Keitel39093572013-06-05 15:32:30 -07005201 if (chip->bat_if_base) {
5202 rc = qpnp_chg_masked_write(chip,
5203 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5204 VREF_BATT_THERM_FORCE_ON,
5205 VREF_BATT_THERM_FORCE_ON, 1);
5206 if (rc)
5207 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
5208 }
David Keitel85ae4342013-04-16 11:46:00 -07005209
5210 return rc;
5211}
5212
5213static int qpnp_chg_suspend(struct device *dev)
5214{
5215 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
5216 int rc = 0;
5217
David Keitel39093572013-06-05 15:32:30 -07005218 if (chip->bat_if_base) {
5219 rc = qpnp_chg_masked_write(chip,
5220 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
5221 VREF_BATT_THERM_FORCE_ON,
5222 VREF_BAT_THM_ENABLED_FSM, 1);
5223 if (rc)
5224 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
5225 }
David Keitel85ae4342013-04-16 11:46:00 -07005226
5227 return rc;
5228}
5229
David Keitel723d5012013-05-03 13:17:27 -07005230static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07005231 .resume = qpnp_chg_resume,
5232 .suspend = qpnp_chg_suspend,
5233};
5234
David Keitel80668952012-07-27 14:25:49 -07005235static struct spmi_driver qpnp_charger_driver = {
5236 .probe = qpnp_charger_probe,
5237 .remove = __devexit_p(qpnp_charger_remove),
5238 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07005239 .name = QPNP_CHARGER_DEV_NAME,
5240 .owner = THIS_MODULE,
5241 .of_match_table = qpnp_charger_match_table,
5242 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07005243 },
5244};
5245
5246/**
5247 * qpnp_chg_init() - register spmi driver for qpnp-chg
5248 */
5249int __init
5250qpnp_chg_init(void)
5251{
5252 return spmi_driver_register(&qpnp_charger_driver);
5253}
5254module_init(qpnp_chg_init);
5255
5256static void __exit
5257qpnp_chg_exit(void)
5258{
5259 spmi_driver_unregister(&qpnp_charger_driver);
5260}
5261module_exit(qpnp_chg_exit);
5262
5263
5264MODULE_DESCRIPTION("QPNP charger driver");
5265MODULE_LICENSE("GPL v2");
5266MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);