blob: aa16edd3e4b064ee8b32607c0ace8a31e8ed39c5 [file] [log] [blame]
Xiaozhe Shid5d21412013-02-06 17:14:41 -08001/* Copyright (c) 2012-2013, 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
73#define CHGR_TTRKL_MAX 0x5F
74#define CHGR_TTRKL_MAX_EN 0x60
75#define CHGR_TCHG_MAX 0x61
76#define CHGR_CHG_WDOG_TIME 0x62
77#define CHGR_CHG_WDOG_DLY 0x63
78#define CHGR_CHG_WDOG_PET 0x64
79#define CHGR_CHG_WDOG_EN 0x65
David Keitel9201df32013-01-10 18:38:34 -080080#define CHGR_IR_DROP_COMPEN 0x67
David Keitel22ed2232013-01-28 11:04:07 -080081#define CHGR_I_MAX_REG 0x44
David Keiteld681cda2012-10-02 15:44:21 -070082#define CHGR_USB_USB_SUSP 0x47
David Keitel6f865cd2012-11-30 15:04:32 -080083#define CHGR_USB_USB_OTG_CTL 0x48
David Keitel80668952012-07-27 14:25:49 -070084#define CHGR_USB_ENUM_T_STOP 0x4E
David Keitel2586f0a2013-08-20 10:02:26 -070085#define CHGR_USB_TRIM 0xF1
David Keitel80668952012-07-27 14:25:49 -070086#define CHGR_CHG_TEMP_THRESH 0x66
87#define CHGR_BAT_IF_PRES_STATUS 0x08
David Keiteld681cda2012-10-02 15:44:21 -070088#define CHGR_STATUS 0x09
David Keitel80668952012-07-27 14:25:49 -070089#define CHGR_BAT_IF_VCP 0x42
90#define CHGR_BAT_IF_BATFET_CTRL1 0x90
David Keitel9eca8ac2013-09-06 14:18:36 -070091#define CHGR_BAT_IF_BATFET_CTRL4 0x93
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -070092#define CHGR_BAT_IF_SPARE 0xDF
David Keitel80668952012-07-27 14:25:49 -070093#define CHGR_MISC_BOOT_DONE 0x42
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -070094#define CHGR_BUCK_PSTG_CTRL 0x73
David Keitel9fd07382013-05-02 15:37:44 -070095#define CHGR_BUCK_COMPARATOR_OVRIDE_1 0xEB
David Keiteld681cda2012-10-02 15:44:21 -070096#define CHGR_BUCK_COMPARATOR_OVRIDE_3 0xED
David Keitel9201df32013-01-10 18:38:34 -080097#define CHGR_BUCK_BCK_VBAT_REG_MODE 0x74
Sridhar Parasuramae183bd2012-12-21 09:28:46 -080098#define MISC_REVISION2 0x01
David Keitel5c3a7702012-12-20 11:13:21 -080099#define USB_OVP_CTL 0x42
David Keitel344c6972013-04-09 19:28:21 -0700100#define USB_CHG_GONE_REV_BST 0xED
101#define BUCK_VCHG_OV 0x77
102#define BUCK_TEST_SMBC_MODES 0xE6
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700103#define BUCK_CTRL_TRIM1 0xF1
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700104#define BUCK_CTRL_TRIM3 0xF3
David Keiteld681cda2012-10-02 15:44:21 -0700105#define SEC_ACCESS 0xD0
David Keitel85ae4342013-04-16 11:46:00 -0700106#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
David Keitel796882d2013-05-14 18:01:11 -0700107#define BAT_IF_BPD_CTRL 0x48
David Keitel6dc4ed42013-05-17 11:08:58 -0700108#define BOOST_VSET 0x41
109#define BOOST_ENABLE_CONTROL 0x46
David Keitel33f58952013-05-20 16:17:36 -0700110#define COMP_OVR1 0xEA
David Keitel89c17752013-06-28 14:52:48 -0700111#define BAT_IF_BTC_CTRL 0x49
David Keitel0b62bdd2013-07-10 17:30:51 -0700112#define USB_OCP_THR 0x52
113#define USB_OCP_CLR 0x53
Zhenhua Huang2a0ee352013-07-23 01:55:43 +0800114#define BAT_IF_TEMP_STATUS 0x09
David Keitel33f58952013-05-20 16:17:36 -0700115
David Keitel80668952012-07-27 14:25:49 -0700116#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700117
David Keitelf2170cc2013-02-20 17:49:03 -0800118/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700119#define SMBB_CHGR_SUBTYPE 0x01
120#define SMBB_BUCK_SUBTYPE 0x02
121#define SMBB_BAT_IF_SUBTYPE 0x03
122#define SMBB_USB_CHGPTH_SUBTYPE 0x04
123#define SMBB_DC_CHGPTH_SUBTYPE 0x05
124#define SMBB_BOOST_SUBTYPE 0x06
125#define SMBB_MISC_SUBTYPE 0x07
126
David Keitelf2170cc2013-02-20 17:49:03 -0800127/* SMBB peripheral subtype values */
128#define SMBBP_CHGR_SUBTYPE 0x31
129#define SMBBP_BUCK_SUBTYPE 0x32
130#define SMBBP_BAT_IF_SUBTYPE 0x33
131#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
132#define SMBBP_BOOST_SUBTYPE 0x36
133#define SMBBP_MISC_SUBTYPE 0x37
134
David Keitel46c9f7b2013-04-02 19:54:12 -0700135/* SMBCL peripheral subtype values */
136#define SMBCL_CHGR_SUBTYPE 0x41
137#define SMBCL_BUCK_SUBTYPE 0x42
138#define SMBCL_BAT_IF_SUBTYPE 0x43
139#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
140#define SMBCL_MISC_SUBTYPE 0x47
141
David Keitel80668952012-07-27 14:25:49 -0700142#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
143
David Keitelb80eda82012-10-15 10:49:11 -0700144/* Status bits and masks */
145#define CHGR_BOOT_DONE BIT(7)
146#define CHGR_CHG_EN BIT(7)
147#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800148#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800149#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700150#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700151#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700152#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700153#define REV_BST_DETECTED BIT(0)
154#define BAT_THM_EN BIT(1)
155#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700156#define BOOST_PWR_EN BIT(7)
David Keitel0b62bdd2013-07-10 17:30:51 -0700157#define OCP_CLR_BIT BIT(7)
158#define OCP_THR_MASK 0x03
159#define OCP_THR_900_MA 0x02
160#define OCP_THR_500_MA 0x01
161#define OCP_THR_200_MA 0x00
David Keitelb80eda82012-10-15 10:49:11 -0700162
David Keitel80668952012-07-27 14:25:49 -0700163/* Interrupt definitions */
164/* smbb_chg_interrupts */
165#define CHG_DONE_IRQ BIT(7)
166#define CHG_FAILED_IRQ BIT(6)
167#define FAST_CHG_ON_IRQ BIT(5)
168#define TRKL_CHG_ON_IRQ BIT(4)
169#define STATE_CHANGE_ON_IR BIT(3)
170#define CHGWDDOG_IRQ BIT(2)
171#define VBAT_DET_HI_IRQ BIT(1)
172#define VBAT_DET_LOW_IRQ BIT(0)
173
174/* smbb_buck_interrupts */
175#define VDD_LOOP_IRQ BIT(6)
176#define IBAT_LOOP_IRQ BIT(5)
177#define ICHG_LOOP_IRQ BIT(4)
178#define VCHG_LOOP_IRQ BIT(3)
179#define OVERTEMP_IRQ BIT(2)
180#define VREF_OV_IRQ BIT(1)
181#define VBAT_OV_IRQ BIT(0)
182
183/* smbb_bat_if_interrupts */
184#define PSI_IRQ BIT(4)
185#define VCP_ON_IRQ BIT(3)
186#define BAT_FET_ON_IRQ BIT(2)
187#define BAT_TEMP_OK_IRQ BIT(1)
188#define BATT_PRES_IRQ BIT(0)
189
190/* smbb_usb_interrupts */
191#define CHG_GONE_IRQ BIT(2)
192#define USBIN_VALID_IRQ BIT(1)
193#define COARSE_DET_USB_IRQ BIT(0)
194
195/* smbb_dc_interrupts */
196#define DCIN_VALID_IRQ BIT(1)
197#define COARSE_DET_DC_IRQ BIT(0)
198
199/* smbb_boost_interrupts */
200#define LIMIT_ERROR_IRQ BIT(1)
201#define BOOST_PWR_OK_IRQ BIT(0)
202
203/* smbb_misc_interrupts */
204#define TFTWDOG_IRQ BIT(0)
205
David Keitelfe51cb92013-04-02 19:42:58 -0700206/* SMBB types */
207#define SMBB BIT(1)
208#define SMBBP BIT(2)
209#define SMBCL BIT(3)
210
David Keiteld681cda2012-10-02 15:44:21 -0700211/* Workaround flags */
212#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700213#define BOOST_FLASH_WA BIT(1)
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700214#define POWER_STAGE_WA BIT(2)
David Keiteld681cda2012-10-02 15:44:21 -0700215
David Keitel47185a62013-05-15 18:54:10 -0700216struct qpnp_chg_irq {
David Keitel9879e2a2013-06-28 18:40:22 -0700217 int irq;
David Keitel47185a62013-05-15 18:54:10 -0700218 unsigned long disabled;
219};
220
David Keitel6dc4ed42013-05-17 11:08:58 -0700221struct qpnp_chg_regulator {
222 struct regulator_desc rdesc;
223 struct regulator_dev *rdev;
224};
225
David Keitel80668952012-07-27 14:25:49 -0700226/**
227 * struct qpnp_chg_chip - device information
228 * @dev: device pointer to access the parent
229 * @spmi: spmi pointer to access spmi information
230 * @chgr_base: charger peripheral base address
231 * @buck_base: buck peripheral base address
232 * @bat_if_base: battery interface peripheral base address
233 * @usb_chgpth_base: USB charge path peripheral base address
234 * @dc_chgpth_base: DC charge path peripheral base address
235 * @boost_base: boost peripheral base address
236 * @misc_base: misc peripheral base address
237 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800238 * @bat_is_cool: indicates that battery is cool
239 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700240 * @chg_done: indicates that charging is completed
241 * @usb_present: present status of usb
242 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800243 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800244 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700245 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700246 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800247 * @min_voltage_mv: min battery voltage before turning the FET on
Prasad Sodagudic3678012013-09-23 12:01:19 +0530248 * @batt_weak_voltage_mv: Weak battery voltage threshold
David Keitel454ee842013-03-08 16:19:11 -0800249 * @max_bat_chg_current: maximum battery charge current in mA
250 * @warm_bat_chg_ma: warm battery maximum charge current in mA
251 * @cool_bat_chg_ma: cool battery maximum charge current in mA
252 * @warm_bat_mv: warm temperature battery target voltage
253 * @cool_bat_mv: cool temperature battery target voltage
254 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700255 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800256 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800257 * @maxinput_usb_ma: Maximum Input current USB
258 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700259 * @hot_batt_p Hot battery threshold setting
260 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700261 * @warm_bat_decidegc Warm battery temperature in degree Celsius
262 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700263 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700264 * @type: SMBB type
265 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800266 * @thermal_levels amount of thermal mitigation levels
267 * @thermal_mitigation thermal mitigation level values
268 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700269 * @dc_psy power supply to export information to userspace
270 * @usb_psy power supply to export information to userspace
271 * @bms_psy power supply to export information to userspace
272 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700273 * @flags: flags to activate specific workarounds
274 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700275 *
276 */
277struct qpnp_chg_chip {
278 struct device *dev;
279 struct spmi_device *spmi;
280 u16 chgr_base;
281 u16 buck_base;
282 u16 bat_if_base;
283 u16 usb_chgpth_base;
284 u16 dc_chgpth_base;
285 u16 boost_base;
286 u16 misc_base;
287 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700288 struct qpnp_chg_irq usbin_valid;
David Keitel0b62bdd2013-07-10 17:30:51 -0700289 struct qpnp_chg_irq usb_ocp;
David Keitel47185a62013-05-15 18:54:10 -0700290 struct qpnp_chg_irq dcin_valid;
291 struct qpnp_chg_irq chg_gone;
292 struct qpnp_chg_irq chg_fastchg;
293 struct qpnp_chg_irq chg_trklchg;
294 struct qpnp_chg_irq chg_failed;
295 struct qpnp_chg_irq chg_vbatdet_lo;
296 struct qpnp_chg_irq batt_pres;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700297 struct qpnp_chg_irq batt_temp_ok;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800298 struct qpnp_chg_irq coarse_det_usb;
David Keitel454ee842013-03-08 16:19:11 -0800299 bool bat_is_cool;
300 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700301 bool chg_done;
David Keitel7ac385e2013-08-19 18:02:40 -0700302 bool charger_monitor_checked;
David Keitel80668952012-07-27 14:25:49 -0700303 bool usb_present;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800304 u8 usbin_health;
305 bool usb_coarse_det;
David Keitel80668952012-07-27 14:25:49 -0700306 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800307 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700308 bool charging_disabled;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800309 bool ovp_monitor_enable;
310 bool usb_valid_check_ovp;
David Keitel89c17752013-06-28 14:52:48 -0700311 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800312 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700313 bool duty_cycle_100p;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700314 bool ibat_calibration_enabled;
315 bool aicl_settled;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800316 bool use_external_rsense;
David Keitel796882d2013-05-14 18:01:11 -0700317 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700318 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800319 unsigned int warm_bat_chg_ma;
320 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700321 unsigned int safe_voltage_mv;
322 unsigned int max_voltage_mv;
323 unsigned int min_voltage_mv;
Prasad Sodagudic3678012013-09-23 12:01:19 +0530324 unsigned int batt_weak_voltage_mv;
David Keitelfd305ee2013-07-19 20:19:06 -0700325 int prev_usb_max_ma;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700326 int set_vddmax_mv;
327 int delta_vddmax_mv;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700328 u8 trim_center;
David Keitel454ee842013-03-08 16:19:11 -0800329 unsigned int warm_bat_mv;
330 unsigned int cool_bat_mv;
331 unsigned int resume_delta_mv;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700332 int insertion_ocv_uv;
David Keitel9fd07382013-05-02 15:37:44 -0700333 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700334 int soc_resume_limit;
335 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800336 unsigned int maxinput_usb_ma;
337 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700338 unsigned int hot_batt_p;
339 unsigned int cold_batt_p;
David Keitel27a97e62013-06-24 13:57:12 -0700340 int warm_bat_decidegc;
341 int cool_bat_decidegc;
David Keitel5d44fa52012-12-03 16:37:31 -0800342 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700343 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700344 unsigned int type;
345 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800346 unsigned int thermal_levels;
347 unsigned int therm_lvl_sel;
348 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700349 struct power_supply dc_psy;
350 struct power_supply *usb_psy;
351 struct power_supply *bms_psy;
352 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700353 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800354 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700355 struct work_struct adc_measure_work;
David Keitelecab15a2013-08-06 15:41:39 -0700356 struct work_struct adc_disable_work;
David Keitel344c6972013-04-09 19:28:21 -0700357 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700358 struct delayed_work eoc_work;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800359 struct delayed_work usbin_health_check;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -0700360 struct work_struct soc_check_work;
David Keitel7ac385e2013-08-19 18:02:40 -0700361 struct delayed_work aicl_check_work;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700362 struct work_struct insertion_ocv_work;
David Keitel6dc4ed42013-05-17 11:08:58 -0700363 struct qpnp_chg_regulator otg_vreg;
364 struct qpnp_chg_regulator boost_vreg;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -0700365 struct qpnp_chg_regulator batfet_vreg;
David Keitel6e63bd52013-09-06 18:00:03 -0700366 bool batfet_ext_en;
367 struct work_struct batfet_lcl_work;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700368 struct qpnp_vadc_chip *vadc_dev;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -0800369 struct qpnp_iadc_chip *iadc_dev;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -0700370 struct qpnp_adc_tm_chip *adc_tm_dev;
David Keitelec3c09802013-06-13 13:05:30 -0700371 struct mutex jeita_configure_lock;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800372 spinlock_t usbin_health_monitor_lock;
David Keitel6e63bd52013-09-06 18:00:03 -0700373 struct mutex batfet_vreg_lock;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700374 struct alarm reduce_power_stage_alarm;
375 struct work_struct reduce_power_stage_work;
376 bool power_stage_workaround_running;
Zhenhua Huangdc335512013-10-30 11:45:15 +0800377 bool power_stage_workaround_enable;
David Keitel80668952012-07-27 14:25:49 -0700378};
379
David Keitel47185a62013-05-15 18:54:10 -0700380
David Keitel80668952012-07-27 14:25:49 -0700381static struct of_device_id qpnp_charger_match_table[] = {
382 { .compatible = QPNP_CHARGER_DEV_NAME, },
383 {}
384};
385
David Keitel0ef282b2013-05-29 16:04:57 -0700386enum bpd_type {
387 BPD_TYPE_BAT_ID,
388 BPD_TYPE_BAT_THM,
389 BPD_TYPE_BAT_THM_BAT_ID,
390};
David Keitel796882d2013-05-14 18:01:11 -0700391
David Keitel0ef282b2013-05-29 16:04:57 -0700392static const char * const bpd_label[] = {
393 [BPD_TYPE_BAT_ID] = "bpd_id",
394 [BPD_TYPE_BAT_THM] = "bpd_thm",
395 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700396};
397
David Keitel89c17752013-06-28 14:52:48 -0700398enum btc_type {
399 HOT_THD_25_PCT = 25,
400 HOT_THD_35_PCT = 35,
401 COLD_THD_70_PCT = 70,
402 COLD_THD_80_PCT = 80,
403};
404
405static u8 btc_value[] = {
406 [HOT_THD_25_PCT] = 0x0,
407 [HOT_THD_35_PCT] = BIT(0),
408 [COLD_THD_70_PCT] = 0x0,
409 [COLD_THD_80_PCT] = BIT(1),
410};
411
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800412enum usbin_health {
413 USBIN_UNKNOW,
414 USBIN_OK,
415 USBIN_OVP,
416};
417
418static inline int
David Keitel796882d2013-05-14 18:01:11 -0700419get_bpd(const char *name)
420{
421 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700422 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
423 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700424 return i;
425 }
426 return -EINVAL;
427}
428
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700429static bool
430is_within_range(int value, int left, int right)
431{
432 if (left >= right && left >= value && value >= right)
433 return 1;
434 if (left <= right && left <= value && value <= right)
435 return 1;
436 return 0;
437}
438
David Keitel80668952012-07-27 14:25:49 -0700439static int
440qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
441 u16 base, int count)
442{
David Keitel39093572013-06-05 15:32:30 -0700443 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700444 struct spmi_device *spmi = chip->spmi;
445
David Keitel39093572013-06-05 15:32:30 -0700446 if (base == 0) {
447 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
448 base, spmi->sid, rc);
449 return -EINVAL;
450 }
451
452 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700453 if (rc) {
454 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
455 spmi->sid, rc);
456 return rc;
457 }
458 return 0;
459}
460
461static int
462qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
463 u16 base, int count)
464{
David Keitel39093572013-06-05 15:32:30 -0700465 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700466 struct spmi_device *spmi = chip->spmi;
467
David Keitel39093572013-06-05 15:32:30 -0700468 if (base == 0) {
469 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
470 base, spmi->sid, rc);
471 return -EINVAL;
472 }
473
474 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700475 if (rc) {
476 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
477 base, spmi->sid, rc);
478 return rc;
479 }
480
481 return 0;
482}
483
484static int
485qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
486 u8 mask, u8 val, int count)
487{
488 int rc;
489 u8 reg;
490
491 rc = qpnp_chg_read(chip, &reg, base, count);
492 if (rc) {
493 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
494 return rc;
495 }
496 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
497
498 reg &= ~mask;
499 reg |= val & mask;
500
501 pr_debug("Writing 0x%x\n", reg);
502
503 rc = qpnp_chg_write(chip, &reg, base, count);
504 if (rc) {
505 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
506 return rc;
507 }
508
509 return 0;
510}
511
David Keitel47185a62013-05-15 18:54:10 -0700512static void
513qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
514{
515 if (__test_and_clear_bit(0, &irq->disabled)) {
516 pr_debug("number = %d\n", irq->irq);
517 enable_irq(irq->irq);
518 }
519}
520
521static void
522qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
523{
524 if (!__test_and_set_bit(0, &irq->disabled)) {
525 pr_debug("number = %d\n", irq->irq);
526 disable_irq_nosync(irq->irq);
527 }
528}
529
David Keitel6f865cd2012-11-30 15:04:32 -0800530#define USB_OTG_EN_BIT BIT(0)
531static int
532qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
533{
534 u8 usb_otg_en;
535 int rc;
536
537 rc = qpnp_chg_read(chip, &usb_otg_en,
538 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
539 1);
540
541 if (rc) {
542 pr_err("spmi read failed: addr=%03X, rc=%d\n",
543 chip->usb_chgpth_base + CHGR_STATUS, rc);
544 return rc;
545 }
546 pr_debug("usb otg en 0x%x\n", usb_otg_en);
547
548 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
549}
550
David Keitel42ae0aa2013-03-08 16:20:10 -0800551static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700552qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
553{
554 u8 boost_en_ctl;
555 int rc;
556
557 rc = qpnp_chg_read(chip, &boost_en_ctl,
558 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
559 if (rc) {
560 pr_err("spmi read failed: addr=%03X, rc=%d\n",
561 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
562 return rc;
563 }
564
565 pr_debug("boost en 0x%x\n", boost_en_ctl);
566
567 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
568}
569
570static int
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700571qpnp_chg_is_batt_temp_ok(struct qpnp_chg_chip *chip)
572{
573 u8 batt_rt_sts;
574 int rc;
575
576 rc = qpnp_chg_read(chip, &batt_rt_sts,
577 INT_RT_STS(chip->bat_if_base), 1);
578 if (rc) {
579 pr_err("spmi read failed: addr=%03X, rc=%d\n",
580 INT_RT_STS(chip->bat_if_base), rc);
581 return rc;
582 }
583
584 return (batt_rt_sts & BAT_TEMP_OK_IRQ) ? 1 : 0;
585}
586
587static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800588qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
589{
590 u8 batt_pres_rt_sts;
591 int rc;
592
593 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
594 INT_RT_STS(chip->bat_if_base), 1);
595 if (rc) {
596 pr_err("spmi read failed: addr=%03X, rc=%d\n",
597 INT_RT_STS(chip->bat_if_base), rc);
598 return rc;
599 }
600
601 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
602}
603
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700604static int
605qpnp_chg_is_batfet_closed(struct qpnp_chg_chip *chip)
606{
607 u8 batfet_closed_rt_sts;
608 int rc;
609
610 rc = qpnp_chg_read(chip, &batfet_closed_rt_sts,
611 INT_RT_STS(chip->bat_if_base), 1);
612 if (rc) {
613 pr_err("spmi read failed: addr=%03X, rc=%d\n",
614 INT_RT_STS(chip->bat_if_base), rc);
615 return rc;
616 }
617
618 return (batfet_closed_rt_sts & BAT_FET_ON_IRQ) ? 1 : 0;
619}
620
David Keiteld681cda2012-10-02 15:44:21 -0700621#define USB_VALID_BIT BIT(7)
David Keitel80668952012-07-27 14:25:49 -0700622static int
623qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
624{
625 u8 usbin_valid_rt_sts;
626 int rc;
627
628 rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
David Keiteld681cda2012-10-02 15:44:21 -0700629 chip->usb_chgpth_base + CHGR_STATUS , 1);
David Keitel80668952012-07-27 14:25:49 -0700630
631 if (rc) {
632 pr_err("spmi read failed: addr=%03X, rc=%d\n",
David Keiteld681cda2012-10-02 15:44:21 -0700633 chip->usb_chgpth_base + CHGR_STATUS, rc);
David Keitel80668952012-07-27 14:25:49 -0700634 return rc;
635 }
636 pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
637
David Keiteld681cda2012-10-02 15:44:21 -0700638 return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700639}
640
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -0700641static bool
642qpnp_chg_is_ibat_loop_active(struct qpnp_chg_chip *chip)
643{
644 int rc;
645 u8 buck_sts;
646
647 rc = qpnp_chg_read(chip, &buck_sts,
648 INT_RT_STS(chip->buck_base), 1);
649 if (rc) {
650 pr_err("failed to read buck RT status rc=%d\n", rc);
651 return 0;
652 }
653
654 return !!(buck_sts & IBAT_LOOP_IRQ);
655}
656
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800657#define USB_VALID_MASK 0xC0
658#define USB_COARSE_DET 0x10
659#define USB_VALID_UVP_VALUE 0x00
660#define USB_VALID_OVP_VALUE 0x40
661static int
662qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
663{
664 u8 usbin_chg_rt_sts;
665 int rc;
666 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
667 chip->usb_chgpth_base + CHGR_STATUS , 1);
668 if (rc) {
669 pr_err("spmi read failed: addr=%03X, rc=%d\n",
670 chip->usb_chgpth_base + CHGR_STATUS, rc);
671 return rc;
672 }
673 return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
674}
675
676static int
677qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
678{
679 u8 usbin_chg_rt_sts, usbin_health = 0;
680 int rc;
681
682 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
683 chip->usb_chgpth_base + CHGR_STATUS , 1);
684
685 if (rc) {
686 pr_err("spmi read failed: addr=%03X, rc=%d\n",
687 chip->usb_chgpth_base + CHGR_STATUS, rc);
688 return rc;
689 }
690
691 pr_debug("chgr usb sts 0x%x\n", usbin_chg_rt_sts);
692 if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
693 if ((usbin_chg_rt_sts & USB_VALID_MASK)
694 == USB_VALID_OVP_VALUE) {
695 usbin_health = USBIN_OVP;
696 pr_err("Over voltage charger inserted\n");
697 } else if ((usbin_chg_rt_sts & USB_VALID_BIT) != 0) {
698 usbin_health = USBIN_OK;
699 pr_debug("Valid charger inserted\n");
700 }
701 } else {
702 usbin_health = USBIN_UNKNOW;
703 pr_debug("Charger plug out\n");
704 }
705
706 return usbin_health;
707}
708
David Keitel80668952012-07-27 14:25:49 -0700709static int
710qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
711{
712 u8 dcin_valid_rt_sts;
713 int rc;
714
David Keitelf2170cc2013-02-20 17:49:03 -0800715 if (!chip->dc_chgpth_base)
716 return 0;
717
David Keitel80668952012-07-27 14:25:49 -0700718 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
719 INT_RT_STS(chip->dc_chgpth_base), 1);
720 if (rc) {
721 pr_err("spmi read failed: addr=%03X, rc=%d\n",
722 INT_RT_STS(chip->dc_chgpth_base), rc);
723 return rc;
724 }
725
726 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
727}
728
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700729static int
730qpnp_chg_is_ichg_loop_active(struct qpnp_chg_chip *chip)
731{
732 u8 buck_sts;
733 int rc;
734
735 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
736
737 if (rc) {
738 pr_err("spmi read failed: addr=%03X, rc=%d\n",
739 INT_RT_STS(chip->buck_base), rc);
740 return rc;
741 }
742 pr_debug("buck usb sts 0x%x\n", buck_sts);
743
744 return (buck_sts & ICHG_LOOP_IRQ) ? 1 : 0;
745}
746
David Keitel22ed2232013-01-28 11:04:07 -0800747#define QPNP_CHG_I_MAX_MIN_100 100
748#define QPNP_CHG_I_MAX_MIN_150 150
749#define QPNP_CHG_I_MAX_MIN_MA 200
750#define QPNP_CHG_I_MAX_MAX_MA 2500
751#define QPNP_CHG_I_MAXSTEP_MA 100
752static int
753qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
754{
755 int rc = 0;
756 u8 dc = 0;
757
758 if (mA < QPNP_CHG_I_MAX_MIN_100
759 || mA > QPNP_CHG_I_MAX_MAX_MA) {
760 pr_err("bad mA=%d asked to set\n", mA);
761 return -EINVAL;
762 }
763
764 if (mA == QPNP_CHG_I_MAX_MIN_100) {
765 dc = 0x00;
766 pr_debug("current=%d setting %02x\n", mA, dc);
767 return qpnp_chg_write(chip, &dc,
768 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
769 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
770 dc = 0x01;
771 pr_debug("current=%d setting %02x\n", mA, dc);
772 return qpnp_chg_write(chip, &dc,
773 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
774 }
775
776 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
777
778 pr_debug("current=%d setting 0x%x\n", mA, dc);
779 rc = qpnp_chg_write(chip, &dc,
780 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
781
782 return rc;
783}
784
David Keitel80668952012-07-27 14:25:49 -0700785static int
David Keitel2586f0a2013-08-20 10:02:26 -0700786qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
787{
788 int rc = 0;
789 u8 trim_reg;
790
791 rc = qpnp_chg_read(chip, &trim_reg,
792 chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
793 if (rc) {
794 pr_err("failed to read USB_TRIM rc=%d\n", rc);
795 return 0;
796 }
797
798 return trim_reg;
799}
800
801static int
802qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
803{
804 int rc = 0;
805
806 rc = qpnp_chg_masked_write(chip,
807 chip->usb_chgpth_base + SEC_ACCESS,
808 0xFF,
809 0xA5, 1);
810 if (rc) {
811 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
812 return rc;
813 }
814
815 rc = qpnp_chg_masked_write(chip,
816 chip->usb_chgpth_base + CHGR_USB_TRIM,
817 0xFF,
818 trim, 1);
819 if (rc) {
820 pr_err("failed to write USB TRIM rc=%d\n", rc);
821 return rc;
822 }
823
824 return rc;
825}
826
827static int
David Keitel80668952012-07-27 14:25:49 -0700828qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
829{
David Keiteld681cda2012-10-02 15:44:21 -0700830 int rc = 0;
831 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700832
David Keitel22ed2232013-01-28 11:04:07 -0800833 if (mA < QPNP_CHG_I_MAX_MIN_100
834 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700835 pr_err("bad mA=%d asked to set\n", mA);
836 return -EINVAL;
837 }
838
David Keitel22ed2232013-01-28 11:04:07 -0800839 if (mA == QPNP_CHG_I_MAX_MIN_100) {
840 usb_reg = 0x00;
841 pr_debug("current=%d setting %02x\n", mA, usb_reg);
842 return qpnp_chg_write(chip, &usb_reg,
843 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
844 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
845 usb_reg = 0x01;
846 pr_debug("current=%d setting %02x\n", mA, usb_reg);
847 return qpnp_chg_write(chip, &usb_reg,
848 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
849 }
850
851 /* Impose input current limit */
852 if (chip->maxinput_usb_ma)
853 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
854
855 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -0700856
David Keiteld681cda2012-10-02 15:44:21 -0700857 if (chip->flags & CHG_FLAGS_VCP_WA) {
858 temp = 0xA5;
859 rc = qpnp_chg_write(chip, &temp,
860 chip->buck_base + SEC_ACCESS, 1);
861 rc = qpnp_chg_masked_write(chip,
862 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
863 0x0C, 0x0C, 1);
864 }
865
David Keitel80668952012-07-27 14:25:49 -0700866 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -0700867 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -0800868 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -0700869
870 if (chip->flags & CHG_FLAGS_VCP_WA) {
871 temp = 0xA5;
872 udelay(200);
873 rc = qpnp_chg_write(chip, &temp,
874 chip->buck_base + SEC_ACCESS, 1);
875 rc = qpnp_chg_masked_write(chip,
876 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
877 0x0C, 0x00, 1);
878 }
879
880 return rc;
881}
882
David Keitel337bd862013-07-15 21:42:58 -0700883#define QPNP_CHG_VINMIN_MIN_MV 4200
884#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
885#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
886#define QPNP_CHG_VINMIN_MAX_MV 9600
887#define QPNP_CHG_VINMIN_STEP_MV 50
888#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
Prasad Sodagudi95624b62013-09-26 16:40:59 +0530889#define QPNP_CHG_VINMIN_MASK 0x3F
David Keitel337bd862013-07-15 21:42:58 -0700890#define QPNP_CHG_VINMIN_MIN_VAL 0x10
891static int
892qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
893{
894 u8 temp;
895
896 if (voltage < QPNP_CHG_VINMIN_MIN_MV
897 || voltage > QPNP_CHG_VINMIN_MAX_MV) {
898 pr_err("bad mV=%d asked to set\n", voltage);
899 return -EINVAL;
900 }
901 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
902 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
David Keitel289fcf82013-10-24 11:33:00 -0700903 temp += (voltage - QPNP_CHG_VINMIN_HIGH_MIN_MV)
David Keitel337bd862013-07-15 21:42:58 -0700904 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
905 } else {
906 temp = QPNP_CHG_VINMIN_MIN_VAL;
907 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
908 / QPNP_CHG_VINMIN_STEP_MV;
909 }
910
911 pr_debug("voltage=%d setting %02x\n", voltage, temp);
912 return qpnp_chg_masked_write(chip,
913 chip->chgr_base + CHGR_VIN_MIN,
914 QPNP_CHG_VINMIN_MASK, temp, 1);
915}
916
917static int
918qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
919{
920 int rc, vin_min_mv;
921 u8 vin_min;
922
923 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
924 if (rc) {
925 pr_err("failed to read VIN_MIN rc=%d\n", rc);
926 return 0;
927 }
928
929 if (vin_min == 0)
930 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
David Keitel289fcf82013-10-24 11:33:00 -0700931 else if (vin_min >= QPNP_CHG_VINMIN_HIGH_MIN_VAL)
David Keitel337bd862013-07-15 21:42:58 -0700932 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
933 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
934 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
935 else
936 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
937 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
938 * QPNP_CHG_VINMIN_STEP_MV;
939 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
940
941 return vin_min_mv;
942}
943
Prasad Sodagudic3678012013-09-23 12:01:19 +0530944#define QPNP_CHG_VBATWEAK_MIN_MV 2100
945#define QPNP_CHG_VBATWEAK_MAX_MV 3600
946#define QPNP_CHG_VBATWEAK_STEP_MV 100
947static int
948qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
949{
950 u8 temp;
951
952 if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
953 || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
954 return -EINVAL;
955
956 temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
957 / QPNP_CHG_VBATWEAK_STEP_MV;
958
959 pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
960 return qpnp_chg_write(chip, &temp,
961 chip->chgr_base + CHGR_VBAT_WEAK, 1);
962}
963
David Keitel337bd862013-07-15 21:42:58 -0700964static int
965qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
966{
967 int rc, iusbmax_ma;
968 u8 iusbmax;
969
970 rc = qpnp_chg_read(chip, &iusbmax,
971 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
972 if (rc) {
973 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
974 return 0;
975 }
976
977 if (iusbmax == 0)
978 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
979 else if (iusbmax == 0x01)
980 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
981 else
982 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
983
984 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
985
986 return iusbmax_ma;
987}
988
David Keiteld681cda2012-10-02 15:44:21 -0700989#define USB_SUSPEND_BIT BIT(0)
990static int
991qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
992{
993 return qpnp_chg_masked_write(chip,
994 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
995 USB_SUSPEND_BIT,
996 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -0700997}
998
David Keitel344c6972013-04-09 19:28:21 -0700999static int
1000qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
1001{
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001002 if (chip->insertion_ocv_uv == 0 && enable) {
1003 pr_debug("Battery not present, skipping\n");
1004 return 0;
1005 }
1006 pr_debug("charging %s\n", enable ? "enabled" : "disabled");
David Keitel344c6972013-04-09 19:28:21 -07001007 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1008 CHGR_CHG_EN,
1009 enable ? CHGR_CHG_EN : 0, 1);
1010}
1011
1012static int
1013qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
1014{
1015 /* Don't run on battery for batteryless hardware */
1016 if (chip->use_default_batt_values)
1017 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -07001018 /* Don't force on battery if battery is not present */
1019 if (!qpnp_chg_is_batt_present(chip))
1020 return 0;
David Keitel344c6972013-04-09 19:28:21 -07001021
1022 /* This bit forces the charger to run off of the battery rather
1023 * than a connected charger */
1024 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
1025 CHGR_ON_BAT_FORCE_BIT,
1026 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
1027}
1028
David Keitel8b68d2d2013-05-14 23:36:51 -07001029#define BUCK_DUTY_MASK_100P 0x30
1030static int
1031qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
1032{
1033 int rc;
1034
1035 pr_debug("enable: %d\n", enable);
1036
1037 rc = qpnp_chg_masked_write(chip,
1038 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1039 if (rc) {
1040 pr_debug("failed to write sec access rc=%d\n", rc);
1041 return rc;
1042 }
1043
1044 rc = qpnp_chg_masked_write(chip,
1045 chip->buck_base + BUCK_TEST_SMBC_MODES,
1046 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
1047 if (rc) {
1048 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
1049 return rc;
1050 }
1051
1052 return rc;
1053}
1054
David Keitel9fd07382013-05-02 15:37:44 -07001055#define COMPATATOR_OVERRIDE_0 0x80
1056static int
1057qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
1058{
1059 int rc;
1060
1061 pr_debug("toggle: %d\n", enable);
1062
1063 rc = qpnp_chg_masked_write(chip,
1064 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1065 if (rc) {
1066 pr_debug("failed to write sec access rc=%d\n", rc);
1067 return rc;
1068 }
1069
1070 rc = qpnp_chg_masked_write(chip,
1071 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
1072 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
1073 if (rc) {
1074 pr_debug("failed to toggle chg done override rc=%d\n", rc);
1075 return rc;
1076 }
1077
1078 return rc;
1079}
1080
1081#define QPNP_CHG_VBATDET_MIN_MV 3240
1082#define QPNP_CHG_VBATDET_MAX_MV 5780
1083#define QPNP_CHG_VBATDET_STEP_MV 20
1084static int
1085qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
1086{
1087 u8 temp;
1088
1089 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
1090 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
1091 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
1092 return -EINVAL;
1093 }
1094 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
1095 / QPNP_CHG_VBATDET_STEP_MV;
1096
1097 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
1098 return qpnp_chg_write(chip, &temp,
1099 chip->chgr_base + CHGR_VBAT_DET, 1);
1100}
1101
David Keitel344c6972013-04-09 19:28:21 -07001102static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001103qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
1104{
1105 if (chip->bat_is_cool)
1106 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
1107 - chip->resume_delta_mv);
1108 else if (chip->bat_is_warm)
1109 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
1110 - chip->resume_delta_mv);
1111 else if (chip->resuming_charging)
1112 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1113 + chip->resume_delta_mv);
1114 else
1115 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1116 - chip->resume_delta_mv);
1117}
1118
1119static void
David Keitel344c6972013-04-09 19:28:21 -07001120qpnp_arb_stop_work(struct work_struct *work)
1121{
1122 struct delayed_work *dwork = to_delayed_work(work);
1123 struct qpnp_chg_chip *chip = container_of(dwork,
1124 struct qpnp_chg_chip, arb_stop_work);
1125
David Keitel9fd07382013-05-02 15:37:44 -07001126 if (!chip->chg_done)
1127 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -07001128 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1129}
1130
1131static void
1132qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -07001133{
1134 struct qpnp_chg_chip *chip = container_of(work,
1135 struct qpnp_chg_chip, adc_measure_work);
1136
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07001137 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -07001138 pr_err("request ADC error\n");
1139}
1140
David Keitelecab15a2013-08-06 15:41:39 -07001141static void
1142qpnp_bat_if_adc_disable_work(struct work_struct *work)
1143{
1144 struct qpnp_chg_chip *chip = container_of(work,
1145 struct qpnp_chg_chip, adc_disable_work);
1146
1147 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev, &chip->adc_param);
1148}
1149
David Keitel9fd07382013-05-02 15:37:44 -07001150#define EOC_CHECK_PERIOD_MS 10000
1151static irqreturn_t
1152qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
1153{
1154 struct qpnp_chg_chip *chip = _chip;
1155 u8 chg_sts = 0;
1156 int rc;
1157
1158 pr_debug("vbatdet-lo triggered\n");
1159
1160 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
1161 if (rc)
1162 pr_err("failed to read chg_sts rc=%d\n", rc);
1163
1164 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
1165 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
1166 schedule_delayed_work(&chip->eoc_work,
1167 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001168 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07001169 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001170 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07001171
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001172 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001173 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001174 if (chip->dc_chgpth_base) {
1175 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001176 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001177 }
1178 if (chip->bat_if_base) {
1179 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001180 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001181 }
David Keitel9fd07382013-05-02 15:37:44 -07001182 return IRQ_HANDLED;
1183}
1184
David Keitel344c6972013-04-09 19:28:21 -07001185#define ARB_STOP_WORK_MS 1000
1186static irqreturn_t
1187qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
1188{
1189 struct qpnp_chg_chip *chip = _chip;
1190
1191 pr_debug("chg_gone triggered\n");
1192 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
1193 qpnp_chg_charge_en(chip, 0);
David Keitel9fd07382013-05-02 15:37:44 -07001194 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001195 schedule_delayed_work(&chip->arb_stop_work,
1196 msecs_to_jiffies(ARB_STOP_WORK_MS));
1197 }
1198
1199 return IRQ_HANDLED;
1200}
1201
David Keitel0b62bdd2013-07-10 17:30:51 -07001202static irqreturn_t
1203qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
1204{
1205 struct qpnp_chg_chip *chip = _chip;
1206 int rc;
1207
1208 pr_debug("usb-ocp triggered\n");
1209
1210 rc = qpnp_chg_masked_write(chip,
1211 chip->usb_chgpth_base + USB_OCP_CLR,
1212 OCP_CLR_BIT,
1213 OCP_CLR_BIT, 1);
1214 if (rc)
1215 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1216
1217 /* force usb ovp fet off */
1218 rc = qpnp_chg_masked_write(chip,
1219 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1220 USB_OTG_EN_BIT,
1221 USB_OTG_EN_BIT, 1);
1222 if (rc)
1223 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1224
1225 return IRQ_HANDLED;
1226}
1227
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001228#define QPNP_CHG_VDDMAX_MIN 3400
1229#define QPNP_CHG_V_MIN_MV 3240
1230#define QPNP_CHG_V_MAX_MV 4500
1231#define QPNP_CHG_V_STEP_MV 10
1232#define QPNP_CHG_BUCK_TRIM1_STEP 10
1233#define QPNP_CHG_BUCK_VDD_TRIM_MASK 0xF0
1234static int
1235qpnp_chg_vddmax_and_trim_set(struct qpnp_chg_chip *chip,
1236 int voltage, int trim_mv)
1237{
1238 int rc, trim_set;
1239 u8 vddmax = 0, trim = 0;
1240
1241 if (voltage < QPNP_CHG_VDDMAX_MIN
1242 || voltage > QPNP_CHG_V_MAX_MV) {
1243 pr_err("bad mV=%d asked to set\n", voltage);
1244 return -EINVAL;
1245 }
1246
1247 vddmax = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1248 rc = qpnp_chg_write(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1249 if (rc) {
1250 pr_err("Failed to write vddmax: %d\n", rc);
1251 return rc;
1252 }
1253
1254 rc = qpnp_chg_masked_write(chip,
1255 chip->buck_base + SEC_ACCESS,
1256 0xFF,
1257 0xA5, 1);
1258 if (rc) {
1259 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1260 return rc;
1261 }
1262 trim_set = clamp((int)chip->trim_center
1263 + (trim_mv / QPNP_CHG_BUCK_TRIM1_STEP),
1264 0, 0xF);
1265 trim = (u8)trim_set << 4;
1266 rc = qpnp_chg_masked_write(chip,
1267 chip->buck_base + BUCK_CTRL_TRIM1,
1268 QPNP_CHG_BUCK_VDD_TRIM_MASK,
1269 trim, 1);
1270 if (rc) {
1271 pr_err("Failed to write buck trim1: %d\n", rc);
1272 return rc;
1273 }
1274 pr_debug("voltage=%d+%d setting vddmax: %02x, trim: %02x\n",
1275 voltage, trim_mv, vddmax, trim);
1276 return 0;
1277}
1278
1279/* JEITA compliance logic */
1280static void
1281qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1282{
1283 if (chip->bat_is_cool)
1284 qpnp_chg_vddmax_and_trim_set(chip, chip->cool_bat_mv,
1285 chip->delta_vddmax_mv);
1286 else if (chip->bat_is_warm)
1287 qpnp_chg_vddmax_and_trim_set(chip, chip->warm_bat_mv,
1288 chip->delta_vddmax_mv);
1289 else
1290 qpnp_chg_vddmax_and_trim_set(chip, chip->max_voltage_mv,
1291 chip->delta_vddmax_mv);
1292}
1293
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001294static void
1295qpnp_usbin_health_check_work(struct work_struct *work)
1296{
1297 int usbin_health = 0;
1298 u8 psy_health_sts = 0;
1299 struct delayed_work *dwork = to_delayed_work(work);
1300 struct qpnp_chg_chip *chip = container_of(dwork,
1301 struct qpnp_chg_chip, usbin_health_check);
1302
1303 usbin_health = qpnp_chg_check_usbin_health(chip);
1304 spin_lock(&chip->usbin_health_monitor_lock);
1305 if (chip->usbin_health != usbin_health) {
1306 pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
1307 chip->usbin_health, usbin_health);
1308 chip->usbin_health = usbin_health;
1309 if (usbin_health == USBIN_OVP)
1310 psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1311 else if (usbin_health == USBIN_OK)
1312 psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
1313 power_supply_set_health_state(chip->usb_psy, psy_health_sts);
1314 power_supply_changed(chip->usb_psy);
1315 }
1316 /* enable OVP monitor in usb valid after coarse-det complete */
1317 chip->usb_valid_check_ovp = true;
1318 spin_unlock(&chip->usbin_health_monitor_lock);
1319 return;
1320}
1321
1322#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
1323#define USB_DEB_BYPASS 0x0
1324#define USB_DEB_5MS 0x1
1325#define USB_DEB_10MS 0x2
1326#define USB_DEB_20MS 0x3
1327static irqreturn_t
1328qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
1329{
1330 struct qpnp_chg_chip *chip = _chip;
1331 int host_mode, rc = 0;
1332 int debounce[] = {
1333 [USB_DEB_BYPASS] = 0,
1334 [USB_DEB_5MS] = 5,
1335 [USB_DEB_10MS] = 10,
1336 [USB_DEB_20MS] = 20 };
1337 u8 ovp_ctl;
1338 bool usb_coarse_det;
1339
1340 host_mode = qpnp_chg_is_otg_en_set(chip);
1341 usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
1342 pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
1343 usb_coarse_det, host_mode);
1344
1345 if (host_mode)
1346 return IRQ_HANDLED;
1347 /* ignore to monitor OVP in usbin valid irq handler
1348 if the coarse-det fired first, do the OVP state monitor
1349 in the usbin_health_check work, and after the work,
1350 enable monitor OVP in usbin valid irq handler */
1351 chip->usb_valid_check_ovp = false;
1352 if (chip->usb_coarse_det ^ usb_coarse_det) {
1353 chip->usb_coarse_det = usb_coarse_det;
1354 if (usb_coarse_det) {
1355 /* usb coarse-det rising edge, check the usbin_valid
1356 debounce time setting, and start a delay work to
1357 check the OVP status*/
1358 rc = qpnp_chg_read(chip, &ovp_ctl,
1359 chip->usb_chgpth_base + USB_OVP_CTL, 1);
1360
1361 if (rc) {
1362 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1363 chip->usb_chgpth_base + USB_OVP_CTL,
1364 rc);
1365 return rc;
1366 }
1367 ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
1368 schedule_delayed_work(&chip->usbin_health_check,
1369 msecs_to_jiffies(debounce[ovp_ctl]));
1370 } else {
1371 /* usb coarse-det rising edge, set the usb psy health
1372 status to unknown */
1373 pr_debug("usb coarse det clear, set usb health to unknown\n");
1374 chip->usbin_health = USBIN_UNKNOW;
1375 power_supply_set_health_state(chip->usb_psy,
1376 POWER_SUPPLY_HEALTH_UNKNOWN);
1377 power_supply_changed(chip->usb_psy);
1378 }
1379
1380 }
1381 return IRQ_HANDLED;
1382}
1383
David Keitel6e63bd52013-09-06 18:00:03 -07001384#define BATFET_LPM_MASK 0xC0
1385#define BATFET_LPM 0x40
1386#define BATFET_NO_LPM 0x00
1387static int
1388qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
1389{
1390 int rc = 0;
1391
David Keitelcadbc282013-09-26 11:39:14 -07001392 if (chip->charging_disabled || !chip->bat_if_base)
1393 return rc;
1394
David Keitel6e63bd52013-09-06 18:00:03 -07001395 if (chip->type == SMBB)
1396 rc = qpnp_chg_masked_write(chip,
1397 chip->bat_if_base + CHGR_BAT_IF_SPARE,
1398 BATFET_LPM_MASK,
1399 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1400 else
1401 rc = qpnp_chg_masked_write(chip,
1402 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
1403 BATFET_LPM_MASK,
1404 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1405
1406 return rc;
1407}
1408
David Keitel80668952012-07-27 14:25:49 -07001409#define ENUM_T_STOP_BIT BIT(0)
1410static irqreturn_t
1411qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1412{
1413 struct qpnp_chg_chip *chip = _chip;
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001414 int usb_present, host_mode, usbin_health;
1415 u8 psy_health_sts;
David Keitel80668952012-07-27 14:25:49 -07001416
1417 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001418 host_mode = qpnp_chg_is_otg_en_set(chip);
1419 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1420 usb_present, host_mode);
1421
1422 /* In host mode notifications cmoe from USB supply */
1423 if (host_mode)
1424 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001425
1426 if (chip->usb_present ^ usb_present) {
1427 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001428 if (!usb_present) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001429 /* when a valid charger inserted, and increase the
1430 * charger voltage to OVP threshold, then
1431 * usb_in_valid falling edge interrupt triggers.
1432 * So we handle the OVP monitor here, and ignore
1433 * other health state changes */
1434 if (chip->ovp_monitor_enable &&
1435 (chip->usb_valid_check_ovp)) {
1436 usbin_health =
1437 qpnp_chg_check_usbin_health(chip);
1438 if (chip->usbin_health != usbin_health) {
1439 chip->usbin_health = usbin_health;
1440 if (usbin_health == USBIN_OVP)
1441 psy_health_sts =
1442 POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1443 power_supply_set_health_state(
1444 chip->usb_psy,
1445 psy_health_sts);
1446 power_supply_changed(chip->usb_psy);
1447 }
1448 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001449 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1450 chip->delta_vddmax_mv = 0;
1451 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel6e63bd52013-09-06 18:00:03 -07001452 chip->chg_done = false;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001453 }
David Keitela9185602013-11-12 17:55:48 -08001454 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitelfd305ee2013-07-19 20:19:06 -07001455 chip->prev_usb_max_ma = -EINVAL;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07001456 chip->aicl_settled = false;
David Keitel9fd07382013-05-02 15:37:44 -07001457 } else {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001458 /* when OVP clamped usbin, and then decrease
1459 * the charger voltage to lower than the OVP
1460 * threshold, a usbin_valid rising edge
1461 * interrupt triggered. So we change the usb
1462 * psy health state back to good */
1463 if (chip->ovp_monitor_enable &&
1464 (chip->usb_valid_check_ovp)) {
1465 usbin_health =
1466 qpnp_chg_check_usbin_health(chip);
1467 if (chip->usbin_health != usbin_health) {
1468 chip->usbin_health = usbin_health;
1469 if (usbin_health == USBIN_OK)
1470 psy_health_sts =
1471 POWER_SUPPLY_HEALTH_GOOD;
1472 power_supply_set_health_state(
1473 chip->usb_psy,
1474 psy_health_sts);
1475 power_supply_changed(chip->usb_psy);
1476 }
1477 }
1478
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001479 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1480 chip->delta_vddmax_mv = 0;
1481 qpnp_chg_set_appropriate_vddmax(chip);
1482 }
David Keitel9fd07382013-05-02 15:37:44 -07001483 schedule_delayed_work(&chip->eoc_work,
1484 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001485 schedule_work(&chip->soc_check_work);
David Keitel9fd07382013-05-02 15:37:44 -07001486 }
David Keitel344c6972013-04-09 19:28:21 -07001487
David Keitel9fd07382013-05-02 15:37:44 -07001488 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel6e63bd52013-09-06 18:00:03 -07001489 schedule_work(&chip->batfet_lcl_work);
David Keitel80668952012-07-27 14:25:49 -07001490 }
1491
1492 return IRQ_HANDLED;
1493}
1494
David Keitel7450dcd2013-01-29 18:41:41 -08001495static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001496qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1497{
1498 struct qpnp_chg_chip *chip = _chip;
1499 int batt_temp_good;
1500
1501 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1502 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1503
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001504 pr_debug("psy changed batt_psy\n");
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001505 power_supply_changed(&chip->batt_psy);
1506 return IRQ_HANDLED;
1507}
1508
1509static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001510qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1511{
1512 struct qpnp_chg_chip *chip = _chip;
1513 int batt_present;
1514
1515 batt_present = qpnp_chg_is_batt_present(chip);
1516 pr_debug("batt-pres triggered: %d\n", batt_present);
1517
1518 if (chip->batt_present ^ batt_present) {
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001519 if (batt_present) {
1520 schedule_work(&chip->insertion_ocv_work);
1521 } else {
1522 chip->insertion_ocv_uv = 0;
1523 qpnp_chg_charge_en(chip, 0);
1524 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001525 chip->batt_present = batt_present;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001526 pr_debug("psy changed batt_psy\n");
David Keitel42ae0aa2013-03-08 16:20:10 -08001527 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001528 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001529 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001530
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001531 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07001532 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001533 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001534 schedule_work(&chip->adc_measure_work);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001535 } else if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitelec3c09802013-06-13 13:05:30 -07001536 && !batt_present) {
David Keitelecab15a2013-08-06 15:41:39 -07001537 schedule_work(&chip->adc_disable_work);
David Keitelec3c09802013-06-13 13:05:30 -07001538 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001539 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001540 }
1541
1542 return IRQ_HANDLED;
1543}
1544
1545static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001546qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1547{
1548 struct qpnp_chg_chip *chip = _chip;
1549 int dc_present;
1550
1551 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1552 pr_debug("dcin-valid triggered: %d\n", dc_present);
1553
1554 if (chip->dc_present ^ dc_present) {
1555 chip->dc_present = dc_present;
David Keitel6d4b9da2013-09-05 17:38:40 -07001556 if (qpnp_chg_is_otg_en_set(chip))
1557 qpnp_chg_force_run_on_batt(chip, !dc_present ? 1 : 0);
David Keitel278f2c72013-08-13 18:00:45 -07001558 if (!dc_present && !qpnp_chg_is_usb_chg_plugged_in(chip)) {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001559 chip->delta_vddmax_mv = 0;
1560 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel9fd07382013-05-02 15:37:44 -07001561 chip->chg_done = false;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001562 } else {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001563 if (!qpnp_chg_is_usb_chg_plugged_in(chip)) {
1564 chip->delta_vddmax_mv = 0;
1565 qpnp_chg_set_appropriate_vddmax(chip);
1566 }
David Keitel9fd07382013-05-02 15:37:44 -07001567 schedule_delayed_work(&chip->eoc_work,
1568 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001569 schedule_work(&chip->soc_check_work);
1570 }
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001571 pr_debug("psy changed dc_psy\n");
David Keitel7450dcd2013-01-29 18:41:41 -08001572 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001573 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001574 power_supply_changed(&chip->batt_psy);
David Keitel6e63bd52013-09-06 18:00:03 -07001575 schedule_work(&chip->batfet_lcl_work);
David Keitel7450dcd2013-01-29 18:41:41 -08001576 }
1577
1578 return IRQ_HANDLED;
1579}
1580
David Keitel80668952012-07-27 14:25:49 -07001581#define CHGR_CHG_FAILED_BIT BIT(7)
1582static irqreturn_t
1583qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1584{
1585 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001586 int rc;
David Keitel80668952012-07-27 14:25:49 -07001587
David Keitel9fd07382013-05-02 15:37:44 -07001588 pr_debug("chg_failed triggered\n");
1589
David Keitel80668952012-07-27 14:25:49 -07001590 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001591 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001592 CHGR_CHG_FAILED_BIT,
1593 CHGR_CHG_FAILED_BIT, 1);
1594 if (rc)
1595 pr_err("Failed to write chg_fail clear bit!\n");
1596
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001597 if (chip->bat_if_base) {
1598 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001599 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001600 }
1601 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001602 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001603 if (chip->dc_chgpth_base) {
1604 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001605 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001606 }
David Keitel80668952012-07-27 14:25:49 -07001607 return IRQ_HANDLED;
1608}
1609
1610static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001611qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
1612{
1613 struct qpnp_chg_chip *chip = _chip;
1614
1615 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001616
1617 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001618 if (chip->bat_if_base) {
1619 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001620 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001621 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001622
1623 return IRQ_HANDLED;
1624}
1625
1626static irqreturn_t
1627qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
1628{
1629 struct qpnp_chg_chip *chip = _chip;
David Keitel337bd862013-07-15 21:42:58 -07001630 u8 chgr_sts;
1631 int rc;
1632
1633 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
1634 if (rc)
1635 pr_err("failed to read interrupt sts %d\n", rc);
David Keitel42ae0aa2013-03-08 16:20:10 -08001636
1637 pr_debug("FAST_CHG IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001638 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001639 if (chip->bat_if_base) {
1640 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001641 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001642 }
1643
1644 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001645 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001646
1647 if (chip->dc_chgpth_base) {
1648 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001649 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001650 }
1651
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001652 if (chip->resuming_charging) {
1653 chip->resuming_charging = false;
1654 qpnp_chg_set_appropriate_vbatdet(chip);
1655 }
David Keitel337bd862013-07-15 21:42:58 -07001656
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001657 if (!chip->charging_disabled) {
1658 schedule_delayed_work(&chip->eoc_work,
1659 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
1660 pm_stay_awake(chip->dev);
1661 }
1662
David Keitel47185a62013-05-15 18:54:10 -07001663 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -08001664
1665 return IRQ_HANDLED;
1666}
1667
David Keitel03ee6b52012-10-22 12:25:19 -07001668static int
David Keitel432e1232013-06-05 16:10:18 -07001669qpnp_dc_property_is_writeable(struct power_supply *psy,
1670 enum power_supply_property psp)
1671{
1672 switch (psp) {
1673 case POWER_SUPPLY_PROP_CURRENT_MAX:
1674 return 1;
1675 default:
1676 break;
1677 }
1678
1679 return 0;
1680}
1681
1682static int
David Keitel03ee6b52012-10-22 12:25:19 -07001683qpnp_batt_property_is_writeable(struct power_supply *psy,
1684 enum power_supply_property psp)
1685{
1686 switch (psp) {
1687 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08001688 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07001689 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel2586f0a2013-08-20 10:02:26 -07001690 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07001691 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
David Keitel337bd862013-07-15 21:42:58 -07001692 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07001693 case POWER_SUPPLY_PROP_COOL_TEMP:
1694 case POWER_SUPPLY_PROP_WARM_TEMP:
David Keitel03ee6b52012-10-22 12:25:19 -07001695 return 1;
1696 default:
1697 break;
1698 }
1699
1700 return 0;
1701}
1702
David Keitel6f865cd2012-11-30 15:04:32 -08001703static int
David Keitelbe208252013-01-31 14:49:25 -08001704qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
1705{
1706 int rc;
1707
1708 if (chip->charging_disabled && enable) {
1709 pr_debug("Charging disabled\n");
1710 return 0;
1711 }
1712
1713 rc = qpnp_chg_charge_en(chip, enable);
1714 if (rc) {
1715 pr_err("Failed to control charging %d\n", rc);
1716 return rc;
1717 }
1718
1719 rc = qpnp_chg_force_run_on_batt(chip, !enable);
1720 if (rc)
1721 pr_err("Failed to control charging %d\n", rc);
1722
1723 return rc;
1724}
1725
David Keitel454ee842013-03-08 16:19:11 -08001726static int
1727switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001728{
1729 int rc;
1730
1731 pr_debug("switch to charge mode\n");
1732 if (!qpnp_chg_is_otg_en_set(chip))
1733 return 0;
1734
1735 /* enable usb ovp fet */
1736 rc = qpnp_chg_masked_write(chip,
1737 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1738 USB_OTG_EN_BIT,
1739 0, 1);
1740 if (rc) {
1741 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1742 return rc;
1743 }
1744
1745 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1746 if (rc) {
1747 pr_err("Failed re-enable charging rc = %d\n", rc);
1748 return rc;
1749 }
1750
1751 return 0;
1752}
1753
David Keitel454ee842013-03-08 16:19:11 -08001754static int
1755switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001756{
1757 int rc;
1758
1759 pr_debug("switch to host mode\n");
1760 if (qpnp_chg_is_otg_en_set(chip))
1761 return 0;
1762
David Keitel6d4b9da2013-09-05 17:38:40 -07001763 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1764 rc = qpnp_chg_force_run_on_batt(chip, 1);
1765 if (rc) {
1766 pr_err("Failed to disable charging rc = %d\n", rc);
1767 return rc;
1768 }
David Keitel6f865cd2012-11-30 15:04:32 -08001769 }
1770
1771 /* force usb ovp fet off */
1772 rc = qpnp_chg_masked_write(chip,
1773 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1774 USB_OTG_EN_BIT,
1775 USB_OTG_EN_BIT, 1);
1776 if (rc) {
1777 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1778 return rc;
1779 }
1780
1781 return 0;
1782}
1783
David Keitel80668952012-07-27 14:25:49 -07001784static enum power_supply_property pm_power_props_mains[] = {
1785 POWER_SUPPLY_PROP_PRESENT,
1786 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07001787 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07001788};
1789
1790static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07001791 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07001792 POWER_SUPPLY_PROP_STATUS,
1793 POWER_SUPPLY_PROP_CHARGE_TYPE,
1794 POWER_SUPPLY_PROP_HEALTH,
1795 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001796 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07001797 POWER_SUPPLY_PROP_TECHNOLOGY,
1798 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
1799 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
1800 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1801 POWER_SUPPLY_PROP_CAPACITY,
1802 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07001803 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
David Keitel2586f0a2013-08-20 10:02:26 -07001804 POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07001805 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
David Keitel337bd862013-07-15 21:42:58 -07001806 POWER_SUPPLY_PROP_VOLTAGE_MIN,
1807 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07001808 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301809 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07001810 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07001811 POWER_SUPPLY_PROP_COOL_TEMP,
1812 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08001813 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301814 POWER_SUPPLY_PROP_CYCLE_COUNT,
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001815 POWER_SUPPLY_PROP_VOLTAGE_OCV,
David Keitel80668952012-07-27 14:25:49 -07001816};
1817
1818static char *pm_power_supplied_to[] = {
1819 "battery",
1820};
1821
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07001822static char *pm_batt_supplied_to[] = {
1823 "bms",
1824};
1825
David Keitel337bd862013-07-15 21:42:58 -07001826static int charger_monitor;
1827module_param(charger_monitor, int, 0644);
1828
David Keitel2586f0a2013-08-20 10:02:26 -07001829static int ext_ovp_present;
1830module_param(ext_ovp_present, int, 0444);
1831
David Keitel80668952012-07-27 14:25:49 -07001832#define USB_WALL_THRESHOLD_MA 500
David Keitel2586f0a2013-08-20 10:02:26 -07001833#define OVP_USB_WALL_THRESHOLD_MA 200
David Keitel80668952012-07-27 14:25:49 -07001834static int
1835qpnp_power_get_property_mains(struct power_supply *psy,
1836 enum power_supply_property psp,
1837 union power_supply_propval *val)
1838{
1839 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1840 dc_psy);
1841
1842 switch (psp) {
1843 case POWER_SUPPLY_PROP_PRESENT:
1844 case POWER_SUPPLY_PROP_ONLINE:
1845 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07001846 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07001847 return 0;
1848
1849 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
1850 break;
David Keitel432e1232013-06-05 16:10:18 -07001851 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07001852 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07001853 break;
David Keitel80668952012-07-27 14:25:49 -07001854 default:
1855 return -EINVAL;
1856 }
1857 return 0;
1858}
1859
David Keitel7ac385e2013-08-19 18:02:40 -07001860static void
1861qpnp_aicl_check_work(struct work_struct *work)
1862{
1863 struct delayed_work *dwork = to_delayed_work(work);
1864 struct qpnp_chg_chip *chip = container_of(dwork,
1865 struct qpnp_chg_chip, aicl_check_work);
1866 union power_supply_propval ret = {0,};
1867
1868 if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
1869 chip->usb_psy->get_property(chip->usb_psy,
1870 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
1871 if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
1872 pr_debug("no charger_monitor present set iusbmax %d\n",
1873 ret.intval / 1000);
1874 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
1875 }
1876 } else {
1877 pr_debug("charger_monitor is present\n");
1878 }
1879 chip->charger_monitor_checked = true;
1880}
1881
David Keitel80668952012-07-27 14:25:49 -07001882static int
1883get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
1884{
1885 int rc = 0;
1886 struct qpnp_vadc_result results;
1887
David Keitelfe51cb92013-04-02 19:42:58 -07001888 if (chip->revision == 0 && chip->type == SMBB) {
1889 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
1890 return 0;
1891 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001892 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07001893 if (rc) {
1894 pr_err("Unable to read vbat rc=%d\n", rc);
1895 return 0;
1896 }
1897 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07001898 }
1899}
1900
1901#define BATT_PRES_BIT BIT(7)
1902static int
1903get_prop_batt_present(struct qpnp_chg_chip *chip)
1904{
1905 u8 batt_present;
1906 int rc;
1907
1908 rc = qpnp_chg_read(chip, &batt_present,
1909 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
1910 if (rc) {
1911 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
1912 return 0;
1913 };
1914 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
1915}
1916
1917#define BATT_TEMP_HOT BIT(6)
1918#define BATT_TEMP_OK BIT(7)
1919static int
1920get_prop_batt_health(struct qpnp_chg_chip *chip)
1921{
1922 u8 batt_health;
1923 int rc;
1924
1925 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07001926 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07001927 if (rc) {
1928 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
1929 return POWER_SUPPLY_HEALTH_UNKNOWN;
1930 };
1931
1932 if (BATT_TEMP_OK & batt_health)
1933 return POWER_SUPPLY_HEALTH_GOOD;
1934 if (BATT_TEMP_HOT & batt_health)
1935 return POWER_SUPPLY_HEALTH_OVERHEAT;
1936 else
1937 return POWER_SUPPLY_HEALTH_COLD;
1938}
1939
1940static int
1941get_prop_charge_type(struct qpnp_chg_chip *chip)
1942{
1943 int rc;
1944 u8 chgr_sts;
1945
1946 if (!get_prop_batt_present(chip))
1947 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1948
1949 rc = qpnp_chg_read(chip, &chgr_sts,
1950 INT_RT_STS(chip->chgr_base), 1);
1951 if (rc) {
1952 pr_err("failed to read interrupt sts %d\n", rc);
1953 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1954 }
1955
1956 if (chgr_sts & TRKL_CHG_ON_IRQ)
1957 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1958 if (chgr_sts & FAST_CHG_ON_IRQ)
1959 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1960
1961 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1962}
1963
1964static int
1965get_prop_batt_status(struct qpnp_chg_chip *chip)
1966{
1967 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001968 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07001969
David Keitel9fd07382013-05-02 15:37:44 -07001970 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
1971 qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
David Keitelc9ffe842013-01-25 19:37:51 -08001972 return POWER_SUPPLY_STATUS_FULL;
David Keitel9fd07382013-05-02 15:37:44 -07001973 }
David Keitelc9ffe842013-01-25 19:37:51 -08001974
David Keitel9fd07382013-05-02 15:37:44 -07001975 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07001976 if (rc) {
1977 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08001978 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07001979 }
1980
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001981 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
1982 if (rc) {
1983 pr_err("failed to read bat_if sts %d\n", rc);
1984 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1985 }
1986
1987 if (chgr_sts & TRKL_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07001988 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001989 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07001990 return POWER_SUPPLY_STATUS_CHARGING;
1991
1992 return POWER_SUPPLY_STATUS_DISCHARGING;
1993}
1994
1995static int
1996get_prop_current_now(struct qpnp_chg_chip *chip)
1997{
1998 union power_supply_propval ret = {0,};
1999
2000 if (chip->bms_psy) {
2001 chip->bms_psy->get_property(chip->bms_psy,
2002 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
2003 return ret.intval;
2004 } else {
2005 pr_debug("No BMS supply registered return 0\n");
2006 }
2007
2008 return 0;
2009}
2010
2011static int
2012get_prop_full_design(struct qpnp_chg_chip *chip)
2013{
2014 union power_supply_propval ret = {0,};
2015
2016 if (chip->bms_psy) {
2017 chip->bms_psy->get_property(chip->bms_psy,
2018 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
2019 return ret.intval;
2020 } else {
2021 pr_debug("No BMS supply registered return 0\n");
2022 }
2023
2024 return 0;
2025}
2026
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302027static int
2028get_prop_charge_full(struct qpnp_chg_chip *chip)
2029{
2030 union power_supply_propval ret = {0,};
2031
2032 if (chip->bms_psy) {
2033 chip->bms_psy->get_property(chip->bms_psy,
2034 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
2035 return ret.intval;
2036 } else {
2037 pr_debug("No BMS supply registered return 0\n");
2038 }
2039
2040 return 0;
2041}
2042
David Keitel80668952012-07-27 14:25:49 -07002043#define DEFAULT_CAPACITY 50
2044static int
2045get_prop_capacity(struct qpnp_chg_chip *chip)
2046{
2047 union power_supply_propval ret = {0,};
Xiaozhe Shibda84992013-09-05 10:39:11 -07002048 int battery_status, bms_status, soc, charger_in;
David Keitel80668952012-07-27 14:25:49 -07002049
David Keitel3dd5e0f2012-12-12 18:12:36 -08002050 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2051 return DEFAULT_CAPACITY;
2052
David Keitel80668952012-07-27 14:25:49 -07002053 if (chip->bms_psy) {
2054 chip->bms_psy->get_property(chip->bms_psy,
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002055 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002056 soc = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002057 battery_status = get_prop_batt_status(chip);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002058 chip->bms_psy->get_property(chip->bms_psy,
2059 POWER_SUPPLY_PROP_STATUS, &ret);
2060 bms_status = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002061 charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
2062 qpnp_chg_is_dc_chg_plugged_in(chip);
2063
2064 if (battery_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shibda84992013-09-05 10:39:11 -07002065 && bms_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002066 && charger_in
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002067 && !chip->resuming_charging
2068 && !chip->charging_disabled
2069 && chip->soc_resume_limit
Xiaozhe Shibda84992013-09-05 10:39:11 -07002070 && soc <= chip->soc_resume_limit) {
2071 pr_debug("resuming charging at %d%% soc\n", soc);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002072 chip->resuming_charging = true;
2073 qpnp_chg_set_appropriate_vbatdet(chip);
2074 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2075 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002076 if (soc == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07002077 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
2078 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07002079 pr_warn_ratelimited("Battery 0, CHG absent\n");
2080 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002081 return soc;
David Keitel80668952012-07-27 14:25:49 -07002082 } else {
2083 pr_debug("No BMS supply registered return 50\n");
2084 }
2085
2086 /* return default capacity to avoid userspace
2087 * from shutting down unecessarily */
2088 return DEFAULT_CAPACITY;
2089}
2090
David Keitel3dd5e0f2012-12-12 18:12:36 -08002091#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07002092#define MAX_TOLERABLE_BATT_TEMP_DDC 680
2093static int
2094get_prop_batt_temp(struct qpnp_chg_chip *chip)
2095{
2096 int rc = 0;
2097 struct qpnp_vadc_result results;
2098
David Keitel3dd5e0f2012-12-12 18:12:36 -08002099 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2100 return DEFAULT_TEMP;
2101
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002102 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07002103 if (rc) {
2104 pr_debug("Unable to read batt temperature rc=%d\n", rc);
2105 return 0;
David Keitel80668952012-07-27 14:25:49 -07002106 }
David Keitela2dbfc72013-06-07 11:10:14 -07002107 pr_debug("get_bat_temp %d %lld\n",
2108 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07002109
David Keitela2dbfc72013-06-07 11:10:14 -07002110 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07002111}
2112
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302113static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
2114{
2115 union power_supply_propval ret = {0,};
2116
2117 if (chip->bms_psy)
2118 chip->bms_psy->get_property(chip->bms_psy,
2119 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
2120 return ret.intval;
2121}
2122
David Keitel337bd862013-07-15 21:42:58 -07002123static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
2124{
2125 u8 buck_sts;
2126 int rc;
2127
2128 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2129
2130 if (rc) {
2131 pr_err("spmi read failed: addr=%03X, rc=%d\n",
2132 INT_RT_STS(chip->buck_base), rc);
2133 return rc;
2134 }
2135 pr_debug("buck usb sts 0x%x\n", buck_sts);
2136
2137 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
2138}
2139
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002140static int get_prop_online(struct qpnp_chg_chip *chip)
2141{
2142 return qpnp_chg_is_batfet_closed(chip);
2143}
2144
David Keitel80668952012-07-27 14:25:49 -07002145static void
2146qpnp_batt_external_power_changed(struct power_supply *psy)
2147{
2148 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2149 batt_psy);
2150 union power_supply_propval ret = {0,};
2151
2152 if (!chip->bms_psy)
2153 chip->bms_psy = power_supply_get_by_name("bms");
2154
2155 chip->usb_psy->get_property(chip->usb_psy,
2156 POWER_SUPPLY_PROP_ONLINE, &ret);
2157
David Keitelc69f2d62013-03-17 14:52:35 -07002158 /* Only honour requests while USB is present */
2159 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002160 chip->usb_psy->get_property(chip->usb_psy,
2161 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07002162
2163 if (chip->prev_usb_max_ma == ret.intval)
2164 goto skip_set_iusb_max;
2165
Zhenhua Huangdd619742013-10-24 10:02:07 +08002166 chip->prev_usb_max_ma = ret.intval;
2167
David Keitel87473252013-03-21 14:39:45 -07002168 if (ret.intval <= 2 && !chip->use_default_batt_values &&
2169 get_prop_batt_present(chip)) {
David Keitela9185602013-11-12 17:55:48 -08002170 if (ret.intval == 2)
2171 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07002172 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07002173 } else {
David Keiteld681cda2012-10-02 15:44:21 -07002174 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel337bd862013-07-15 21:42:58 -07002175 if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
David Keitel7ac385e2013-08-19 18:02:40 -07002176 && (charger_monitor ||
2177 !chip->charger_monitor_checked)) {
David Keitel2586f0a2013-08-20 10:02:26 -07002178 if (!ext_ovp_present)
2179 qpnp_chg_iusbmax_set(chip,
David Keitel337bd862013-07-15 21:42:58 -07002180 USB_WALL_THRESHOLD_MA);
David Keitel2586f0a2013-08-20 10:02:26 -07002181 else
2182 qpnp_chg_iusbmax_set(chip,
2183 OVP_USB_WALL_THRESHOLD_MA);
David Keitel337bd862013-07-15 21:42:58 -07002184 } else {
2185 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2186 }
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002187
2188 if ((chip->flags & POWER_STAGE_WA)
2189 && ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
Zhenhua Huangdc335512013-10-30 11:45:15 +08002190 && !chip->power_stage_workaround_running
2191 && chip->power_stage_workaround_enable) {
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002192 chip->power_stage_workaround_running = true;
2193 pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
2194 charger_monitor);
2195 schedule_work(&chip->reduce_power_stage_work);
2196 }
David Keitelc69f2d62013-03-17 14:52:35 -07002197 }
David Keitel80668952012-07-27 14:25:49 -07002198 }
2199
David Keitelfd305ee2013-07-19 20:19:06 -07002200skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07002201 pr_debug("end of power supply changed\n");
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002202 pr_debug("psy changed batt_psy\n");
David Keitel80668952012-07-27 14:25:49 -07002203 power_supply_changed(&chip->batt_psy);
2204}
2205
2206static int
2207qpnp_batt_power_get_property(struct power_supply *psy,
2208 enum power_supply_property psp,
2209 union power_supply_propval *val)
2210{
2211 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2212 batt_psy);
2213
2214 switch (psp) {
2215 case POWER_SUPPLY_PROP_STATUS:
2216 val->intval = get_prop_batt_status(chip);
2217 break;
2218 case POWER_SUPPLY_PROP_CHARGE_TYPE:
2219 val->intval = get_prop_charge_type(chip);
2220 break;
2221 case POWER_SUPPLY_PROP_HEALTH:
2222 val->intval = get_prop_batt_health(chip);
2223 break;
2224 case POWER_SUPPLY_PROP_PRESENT:
2225 val->intval = get_prop_batt_present(chip);
2226 break;
2227 case POWER_SUPPLY_PROP_TECHNOLOGY:
2228 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2229 break;
2230 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2231 val->intval = chip->max_voltage_mv * 1000;
2232 break;
2233 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2234 val->intval = chip->min_voltage_mv * 1000;
2235 break;
2236 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2237 val->intval = get_prop_battery_voltage_now(chip);
2238 break;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002239 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2240 val->intval = chip->insertion_ocv_uv;
2241 break;
David Keitel80668952012-07-27 14:25:49 -07002242 case POWER_SUPPLY_PROP_TEMP:
2243 val->intval = get_prop_batt_temp(chip);
2244 break;
David Keitelec3c09802013-06-13 13:05:30 -07002245 case POWER_SUPPLY_PROP_COOL_TEMP:
2246 val->intval = chip->cool_bat_decidegc;
2247 break;
2248 case POWER_SUPPLY_PROP_WARM_TEMP:
2249 val->intval = chip->warm_bat_decidegc;
2250 break;
David Keitel80668952012-07-27 14:25:49 -07002251 case POWER_SUPPLY_PROP_CAPACITY:
2252 val->intval = get_prop_capacity(chip);
2253 break;
2254 case POWER_SUPPLY_PROP_CURRENT_NOW:
2255 val->intval = get_prop_current_now(chip);
2256 break;
2257 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2258 val->intval = get_prop_full_design(chip);
2259 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302260 case POWER_SUPPLY_PROP_CHARGE_FULL:
2261 val->intval = get_prop_charge_full(chip);
2262 break;
David Keitelb80eda82012-10-15 10:49:11 -07002263 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07002264 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07002265 break;
David Keitelbe208252013-01-31 14:49:25 -08002266 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2267 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07002268 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302269 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2270 val->intval = get_prop_cycle_count(chip);
2271 break;
David Keitel337bd862013-07-15 21:42:58 -07002272 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
2273 val->intval = get_prop_vchg_loop(chip);
2274 break;
2275 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2276 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
2277 break;
David Keitel2586f0a2013-08-20 10:02:26 -07002278 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
2279 val->intval = qpnp_chg_iusb_trim_get(chip);
2280 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002281 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
2282 val->intval = chip->aicl_settled;
2283 break;
David Keitel337bd862013-07-15 21:42:58 -07002284 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2285 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
2286 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002287 case POWER_SUPPLY_PROP_ONLINE:
2288 val->intval = get_prop_online(chip);
2289 break;
David Keitelb80eda82012-10-15 10:49:11 -07002290 default:
2291 return -EINVAL;
2292 }
2293
David Keitelb80eda82012-10-15 10:49:11 -07002294 return 0;
David Keitel80668952012-07-27 14:25:49 -07002295}
2296
David Keitel89c17752013-06-28 14:52:48 -07002297#define BTC_CONFIG_ENABLED BIT(7)
2298#define BTC_COLD BIT(1)
2299#define BTC_HOT BIT(0)
2300static int
2301qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
2302{
2303 u8 btc_cfg = 0, mask = 0;
2304
2305 /* Do nothing if battery peripheral not present */
2306 if (!chip->bat_if_base)
2307 return 0;
2308
2309 if ((chip->hot_batt_p == HOT_THD_25_PCT)
2310 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
2311 btc_cfg |= btc_value[chip->hot_batt_p];
2312 mask |= BTC_HOT;
2313 }
2314
2315 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
2316 (chip->cold_batt_p == COLD_THD_80_PCT)) {
2317 btc_cfg |= btc_value[chip->cold_batt_p];
2318 mask |= BTC_COLD;
2319 }
2320
2321 if (chip->btc_disabled)
2322 mask |= BTC_CONFIG_ENABLED;
2323
2324 return qpnp_chg_masked_write(chip,
2325 chip->bat_if_base + BAT_IF_BTC_CTRL,
2326 mask, btc_cfg, 1);
2327}
2328
David Keitel5d44fa52012-12-03 16:37:31 -08002329#define QPNP_CHG_IBATSAFE_MIN_MA 100
2330#define QPNP_CHG_IBATSAFE_MAX_MA 3250
2331#define QPNP_CHG_I_STEP_MA 50
2332#define QPNP_CHG_I_MIN_MA 100
2333#define QPNP_CHG_I_MASK 0x3F
2334static int
2335qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
2336{
2337 u8 temp;
2338
2339 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
2340 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
2341 pr_err("bad mA=%d asked to set\n", safe_current);
2342 return -EINVAL;
2343 }
2344
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08002345 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08002346 return qpnp_chg_masked_write(chip,
2347 chip->chgr_base + CHGR_IBAT_SAFE,
2348 QPNP_CHG_I_MASK, temp, 1);
2349}
David Keitel80668952012-07-27 14:25:49 -07002350
2351#define QPNP_CHG_ITERM_MIN_MA 100
2352#define QPNP_CHG_ITERM_MAX_MA 250
2353#define QPNP_CHG_ITERM_STEP_MA 50
2354#define QPNP_CHG_ITERM_MASK 0x03
2355static int
2356qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
2357{
2358 u8 temp;
2359
2360 if (term_current < QPNP_CHG_ITERM_MIN_MA
2361 || term_current > QPNP_CHG_ITERM_MAX_MA) {
2362 pr_err("bad mA=%d asked to set\n", term_current);
2363 return -EINVAL;
2364 }
2365
2366 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
2367 / QPNP_CHG_ITERM_STEP_MA;
2368 return qpnp_chg_masked_write(chip,
2369 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
2370 QPNP_CHG_ITERM_MASK, temp, 1);
2371}
2372
David Keitelff5d0472013-04-04 11:36:06 -07002373#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07002374#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07002375static int
2376qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
2377{
2378 u8 temp;
2379
2380 if (chg_current < QPNP_CHG_IBATMAX_MIN
2381 || chg_current > QPNP_CHG_IBATMAX_MAX) {
2382 pr_err("bad mA=%d asked to set\n", chg_current);
2383 return -EINVAL;
2384 }
David Keitelff5d0472013-04-04 11:36:06 -07002385 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07002386 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
2387 QPNP_CHG_I_MASK, temp, 1);
2388}
2389
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002390static int
2391qpnp_chg_ibatmax_get(struct qpnp_chg_chip *chip, int *chg_current)
2392{
2393 int rc;
2394 u8 temp;
2395
2396 *chg_current = 0;
2397 rc = qpnp_chg_read(chip, &temp, chip->chgr_base + CHGR_IBAT_MAX, 1);
2398 if (rc) {
2399 pr_err("failed read ibat_max rc=%d\n", rc);
2400 return rc;
2401 }
2402
2403 *chg_current = ((temp & QPNP_CHG_I_MASK) * QPNP_CHG_I_STEP_MA);
2404
2405 return 0;
2406}
2407
David Keitela4b7b592013-04-11 18:34:35 -07002408#define QPNP_CHG_TCHG_MASK 0x7F
2409#define QPNP_CHG_TCHG_MIN 4
2410#define QPNP_CHG_TCHG_MAX 512
2411#define QPNP_CHG_TCHG_STEP 4
2412static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
2413{
2414 u8 temp;
2415
2416 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
2417 pr_err("bad max minutes =%d asked to set\n", minutes);
2418 return -EINVAL;
2419 }
2420
2421 temp = (minutes - 1)/QPNP_CHG_TCHG_STEP;
2422 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07002423 QPNP_CHG_TCHG_MASK, temp, 1);
David Keitela4b7b592013-04-11 18:34:35 -07002424}
David Keitel80668952012-07-27 14:25:49 -07002425
David Keitel80668952012-07-27 14:25:49 -07002426static int
2427qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
2428{
2429 u8 temp;
2430
2431 if (voltage < QPNP_CHG_V_MIN_MV
2432 || voltage > QPNP_CHG_V_MAX_MV) {
2433 pr_err("bad mV=%d asked to set\n", voltage);
2434 return -EINVAL;
2435 }
2436 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
2437 pr_debug("voltage=%d setting %02x\n", voltage, temp);
2438 return qpnp_chg_write(chip, &temp,
2439 chip->chgr_base + CHGR_VDD_SAFE, 1);
2440}
2441
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002442#define IBAT_TRIM_TGT_MA 500
2443#define IBAT_TRIM_OFFSET_MASK 0x7F
2444#define IBAT_TRIM_GOOD_BIT BIT(7)
2445#define IBAT_TRIM_LOW_LIM 20
2446#define IBAT_TRIM_HIGH_LIM 114
2447#define IBAT_TRIM_MEAN 64
2448
2449static void
2450qpnp_chg_trim_ibat(struct qpnp_chg_chip *chip, u8 ibat_trim)
2451{
2452 int ibat_now_ma, ibat_diff_ma, rc;
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002453 struct qpnp_iadc_result i_result;
2454 enum qpnp_iadc_channels iadc_channel;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002455
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002456 iadc_channel = chip->use_external_rsense ?
2457 EXTERNAL_RSENSE : INTERNAL_RSENSE;
2458 rc = qpnp_iadc_read(chip->iadc_dev, iadc_channel, &i_result);
2459 if (rc) {
2460 pr_err("Unable to read bat rc=%d\n", rc);
2461 return;
2462 }
2463
2464 ibat_now_ma = i_result.result_ua / 1000;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002465
2466 if (qpnp_chg_is_ibat_loop_active(chip)) {
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002467 ibat_diff_ma = ibat_now_ma - IBAT_TRIM_TGT_MA;
2468
2469 if (abs(ibat_diff_ma) > 50) {
2470 ibat_trim += (ibat_diff_ma / 20);
2471 ibat_trim &= IBAT_TRIM_OFFSET_MASK;
2472 /* reject new ibat_trim if it is outside limits */
2473 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
2474 IBAT_TRIM_HIGH_LIM))
2475 return;
2476 }
2477 ibat_trim |= IBAT_TRIM_GOOD_BIT;
2478 rc = qpnp_chg_write(chip, &ibat_trim,
2479 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2480 if (rc)
2481 pr_err("failed to set IBAT_TRIM rc=%d\n", rc);
2482
2483 pr_debug("ibat_now=%dmA, itgt=%dmA, ibat_diff=%dmA, ibat_trim=%x\n",
2484 ibat_now_ma, IBAT_TRIM_TGT_MA,
2485 ibat_diff_ma, ibat_trim);
2486 } else {
2487 pr_debug("ibat loop not active - cannot calibrate ibat\n");
2488 }
2489}
2490
2491static int
2492qpnp_chg_input_current_settled(struct qpnp_chg_chip *chip)
2493{
2494 int rc, ibat_max_ma;
2495 u8 reg, chgr_sts, ibat_trim, i;
2496
2497 chip->aicl_settled = true;
2498
2499 /*
2500 * Perform the ibat calibration.
2501 * This is for devices which have a IBAT_TRIM error
2502 * which can show IBAT_MAX out of spec.
2503 */
2504 if (!chip->ibat_calibration_enabled)
2505 return 0;
2506
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002507 if (chip->type != SMBB)
2508 return 0;
2509
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002510 rc = qpnp_chg_read(chip, &reg,
2511 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2512 if (rc) {
2513 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
2514 return rc;
2515 }
2516 if (reg & IBAT_TRIM_GOOD_BIT) {
2517 pr_debug("IBAT_TRIM_GOOD bit already set. Quitting!\n");
2518 return 0;
2519 }
2520 ibat_trim = reg & IBAT_TRIM_OFFSET_MASK;
2521
2522 if (!is_within_range(ibat_trim, IBAT_TRIM_LOW_LIM,
2523 IBAT_TRIM_HIGH_LIM)) {
2524 pr_debug("Improper ibat_trim value=%x setting to value=%x\n",
2525 ibat_trim, IBAT_TRIM_MEAN);
2526 ibat_trim = IBAT_TRIM_MEAN;
2527 rc = qpnp_chg_masked_write(chip,
2528 chip->buck_base + BUCK_CTRL_TRIM3,
2529 IBAT_TRIM_OFFSET_MASK, ibat_trim, 1);
2530 if (rc) {
2531 pr_err("failed to set ibat_trim to %x rc=%d\n",
2532 IBAT_TRIM_MEAN, rc);
2533 return rc;
2534 }
2535 }
2536
2537 rc = qpnp_chg_read(chip, &chgr_sts,
2538 INT_RT_STS(chip->chgr_base), 1);
2539 if (rc) {
2540 pr_err("failed to read interrupt sts rc=%d\n", rc);
2541 return rc;
2542 }
2543 if (!(chgr_sts & FAST_CHG_ON_IRQ)) {
2544 pr_debug("Not in fastchg\n");
2545 return rc;
2546 }
2547
2548 /* save the ibat_max to restore it later */
2549 rc = qpnp_chg_ibatmax_get(chip, &ibat_max_ma);
2550 if (rc) {
2551 pr_debug("failed to save ibatmax rc=%d\n", rc);
2552 return rc;
2553 }
2554
2555 rc = qpnp_chg_ibatmax_set(chip, IBAT_TRIM_TGT_MA);
2556 if (rc) {
2557 pr_err("failed to set ibatmax rc=%d\n", rc);
2558 return rc;
2559 }
2560
2561 for (i = 0; i < 3; i++) {
2562 /*
2563 * ibat settling delay - to make sure the BMS controller
2564 * has sufficient time to sample ibat for the configured
2565 * ibat_max
2566 */
2567 msleep(20);
2568 if (qpnp_chg_is_ibat_loop_active(chip))
2569 qpnp_chg_trim_ibat(chip, ibat_trim);
2570 else
2571 pr_debug("ibat loop not active\n");
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002572
2573 /* read the adjusted ibat_trim for further adjustments */
2574 rc = qpnp_chg_read(chip, &ibat_trim,
2575 chip->buck_base + BUCK_CTRL_TRIM3, 1);
2576 if (rc) {
2577 pr_err("failed to read BUCK_CTRL_TRIM3 rc=%d\n", rc);
2578 break;
2579 }
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002580 }
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08002581
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07002582 /* restore IBATMAX */
2583 rc = qpnp_chg_ibatmax_set(chip, ibat_max_ma);
2584 if (rc)
2585 pr_err("failed to restore ibatmax rc=%d\n", rc);
2586
2587 return rc;
2588}
2589
2590
David Keitel6dc4ed42013-05-17 11:08:58 -07002591#define BOOST_MIN_UV 4200000
2592#define BOOST_MAX_UV 5500000
2593#define BOOST_STEP_UV 50000
2594#define BOOST_MIN 16
2595#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
2596static int
2597qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
2598{
2599 u8 reg = 0;
2600
2601 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
2602 pr_err("invalid voltage requested %d uV\n", voltage);
2603 return -EINVAL;
2604 }
2605
2606 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
2607
2608 pr_debug("voltage=%d setting %02x\n", voltage, reg);
2609 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
2610}
2611
2612static int
2613qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
2614{
2615 int rc;
2616 u8 boost_reg;
2617
2618 rc = qpnp_chg_read(chip, &boost_reg,
2619 chip->boost_base + BOOST_VSET, 1);
2620 if (rc) {
2621 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
2622 return rc;
2623 }
2624
2625 if (boost_reg < BOOST_MIN) {
2626 pr_err("Invalid reading from 0x%x\n", boost_reg);
2627 return -EINVAL;
2628 }
2629
2630 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
2631}
2632
David Keitel454ee842013-03-08 16:19:11 -08002633static void
David Keitelbe208252013-01-31 14:49:25 -08002634qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
2635{
2636 unsigned int chg_current = chip->max_bat_chg_current;
2637
David Keitel454ee842013-03-08 16:19:11 -08002638 if (chip->bat_is_cool)
2639 chg_current = min(chg_current, chip->cool_bat_chg_ma);
2640
2641 if (chip->bat_is_warm)
2642 chg_current = min(chg_current, chip->warm_bat_chg_ma);
2643
David Keitelbe208252013-01-31 14:49:25 -08002644 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
2645 chg_current = min(chg_current,
2646 chip->thermal_mitigation[chip->therm_lvl_sel]);
2647
2648 pr_debug("setting %d mA\n", chg_current);
2649 qpnp_chg_ibatmax_set(chip, chg_current);
2650}
2651
2652static void
2653qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
2654{
2655 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
2656 chip->therm_lvl_sel = lvl_sel;
2657 if (lvl_sel == (chip->thermal_levels - 1)) {
2658 /* disable charging if highest value selected */
2659 qpnp_chg_buck_control(chip, 0);
2660 } else {
2661 qpnp_chg_buck_control(chip, 1);
2662 qpnp_chg_set_appropriate_battery_current(chip);
2663 }
2664 } else {
2665 pr_err("Unsupported level selected %d\n", lvl_sel);
2666 }
2667}
2668
David Keitel6dc4ed42013-05-17 11:08:58 -07002669/* OTG regulator operations */
2670static int
2671qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
2672{
2673 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2674
2675 return switch_usb_to_host_mode(chip);
2676}
2677
2678static int
2679qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
2680{
2681 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2682
2683 return switch_usb_to_charge_mode(chip);
2684}
2685
2686static int
2687qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
2688{
2689 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2690
2691 return qpnp_chg_is_otg_en_set(chip);
2692}
2693
2694static int
2695qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
2696{
2697 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07002698 int rc;
2699
2700 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
2701 (chip->flags & BOOST_FLASH_WA)) {
2702 qpnp_chg_usb_suspend_enable(chip, 1);
2703
2704 rc = qpnp_chg_masked_write(chip,
2705 chip->usb_chgpth_base + SEC_ACCESS,
2706 0xFF,
2707 0xA5, 1);
2708 if (rc) {
2709 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2710 return rc;
2711 }
2712
2713 rc = qpnp_chg_masked_write(chip,
2714 chip->usb_chgpth_base + COMP_OVR1,
2715 0xFF,
2716 0x2F, 1);
2717 if (rc) {
2718 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2719 return rc;
2720 }
2721 }
David Keitel6dc4ed42013-05-17 11:08:58 -07002722
2723 return qpnp_chg_masked_write(chip,
2724 chip->boost_base + BOOST_ENABLE_CONTROL,
2725 BOOST_PWR_EN,
2726 BOOST_PWR_EN, 1);
2727}
2728
2729/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07002730#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07002731static int
2732qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
2733{
2734 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07002735 int rc;
2736 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07002737
David Keitel33f58952013-05-20 16:17:36 -07002738 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07002739 chip->boost_base + BOOST_ENABLE_CONTROL,
2740 BOOST_PWR_EN,
2741 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07002742 if (rc) {
2743 pr_err("failed to disable boost rc=%d\n", rc);
2744 return rc;
2745 }
2746
2747 rc = qpnp_chg_read(chip, &vbat_sts,
2748 chip->chgr_base + CHGR_VBAT_STATUS, 1);
2749 if (rc) {
2750 pr_err("failed to read bat sts rc=%d\n", rc);
2751 return rc;
2752 }
2753
2754 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
2755 rc = qpnp_chg_masked_write(chip,
2756 chip->chgr_base + SEC_ACCESS,
2757 0xFF,
2758 0xA5, 1);
2759 if (rc) {
2760 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2761 return rc;
2762 }
2763
2764 rc = qpnp_chg_masked_write(chip,
2765 chip->chgr_base + COMP_OVR1,
2766 0xFF,
2767 0x20, 1);
2768 if (rc) {
2769 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2770 return rc;
2771 }
2772
2773 usleep(2000);
2774
2775 rc = qpnp_chg_masked_write(chip,
2776 chip->chgr_base + SEC_ACCESS,
2777 0xFF,
2778 0xA5, 1);
2779 if (rc) {
2780 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2781 return rc;
2782 }
2783
2784 rc = qpnp_chg_masked_write(chip,
2785 chip->chgr_base + COMP_OVR1,
2786 0xFF,
2787 0x00, 1);
2788 if (rc) {
2789 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2790 return rc;
2791 }
2792 }
2793
2794 if (qpnp_chg_is_usb_chg_plugged_in(chip)
2795 && (chip->flags & BOOST_FLASH_WA)) {
2796 rc = qpnp_chg_masked_write(chip,
2797 chip->usb_chgpth_base + SEC_ACCESS,
2798 0xFF,
2799 0xA5, 1);
2800 if (rc) {
2801 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2802 return rc;
2803 }
2804
2805 rc = qpnp_chg_masked_write(chip,
2806 chip->usb_chgpth_base + COMP_OVR1,
2807 0xFF,
2808 0x00, 1);
2809 if (rc) {
2810 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2811 return rc;
2812 }
2813
2814 usleep(1000);
2815
2816 qpnp_chg_usb_suspend_enable(chip, 0);
2817 }
2818
2819 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07002820}
2821
2822static int
2823qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
2824{
2825 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2826
2827 return qpnp_chg_is_boost_en_set(chip);
2828}
2829
2830static int
2831qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
2832 int min_uV, int max_uV, unsigned *selector)
2833{
2834 int uV = min_uV;
2835 int rc;
2836 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2837
2838 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
2839 uV = BOOST_MIN_UV;
2840
2841
2842 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
2843 pr_err("request %d uV is out of bounds\n", uV);
2844 return -EINVAL;
2845 }
2846
2847 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
2848 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
2849 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
2850 return -EINVAL;
2851 }
2852
2853 rc = qpnp_boost_vset(chip, uV);
2854
2855 return rc;
2856}
2857
2858static int
2859qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
2860{
2861 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2862
2863 return qpnp_boost_vget_uv(chip);
2864}
2865
2866static int
2867qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
2868 unsigned selector)
2869{
2870 if (selector >= N_BOOST_V)
2871 return 0;
2872
2873 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
2874}
2875
2876static struct regulator_ops qpnp_chg_otg_reg_ops = {
2877 .enable = qpnp_chg_regulator_otg_enable,
2878 .disable = qpnp_chg_regulator_otg_disable,
2879 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
2880};
2881
2882static struct regulator_ops qpnp_chg_boost_reg_ops = {
2883 .enable = qpnp_chg_regulator_boost_enable,
2884 .disable = qpnp_chg_regulator_boost_disable,
2885 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
2886 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
2887 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
2888 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
2889};
2890
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002891static int
David Keitel6e63bd52013-09-06 18:00:03 -07002892qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002893{
David Keitel9eca8ac2013-09-06 14:18:36 -07002894 int rc = 0;
David Keitel6e63bd52013-09-06 18:00:03 -07002895 u8 reg = 0;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002896
David Keitelcadbc282013-09-26 11:39:14 -07002897 if (!chip->bat_if_base)
2898 return rc;
2899
David Keitel9eca8ac2013-09-06 14:18:36 -07002900 if (chip->type == SMBB)
2901 rc = qpnp_chg_read(chip, &reg,
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002902 chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
David Keitel9eca8ac2013-09-06 14:18:36 -07002903 else
2904 rc = qpnp_chg_read(chip, &reg,
2905 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
David Keitel6e63bd52013-09-06 18:00:03 -07002906
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002907 if (rc) {
2908 pr_err("failed to read batt_if rc=%d\n", rc);
2909 return rc;
2910 }
2911
David Keitel6e63bd52013-09-06 18:00:03 -07002912 if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002913 return 1;
2914
2915 return 0;
2916}
2917
David Keitel6e63bd52013-09-06 18:00:03 -07002918static int
2919qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
2920{
2921 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2922 int rc = 0;
2923
2924 mutex_lock(&chip->batfet_vreg_lock);
2925 /* Only enable if not already enabled */
2926 if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
2927 rc = qpnp_chg_regulator_batfet_set(chip, 1);
2928 if (rc)
2929 pr_err("failed to write to batt_if rc=%d\n", rc);
2930 }
2931
2932 chip->batfet_ext_en = true;
2933 mutex_unlock(&chip->batfet_vreg_lock);
2934
2935 return rc;
2936}
2937
2938static int
2939qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
2940{
2941 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2942 int rc = 0;
2943
2944 mutex_lock(&chip->batfet_vreg_lock);
2945 /* Don't allow disable if charger connected */
2946 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
2947 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
2948 rc = qpnp_chg_regulator_batfet_set(chip, 0);
2949 if (rc)
2950 pr_err("failed to write to batt_if rc=%d\n", rc);
2951 }
2952
2953 chip->batfet_ext_en = false;
2954 mutex_unlock(&chip->batfet_vreg_lock);
2955
2956 return rc;
2957}
2958
2959static int
2960qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
2961{
2962 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2963
2964 return chip->batfet_ext_en;
2965}
2966
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002967static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
2968 .enable = qpnp_chg_regulator_batfet_enable,
2969 .disable = qpnp_chg_regulator_batfet_disable,
2970 .is_enabled = qpnp_chg_regulator_batfet_is_enabled,
2971};
2972
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07002973#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 8
2974#define MAX_DELTA_VDD_MAX_MV 80
2975#define VDD_MAX_CENTER_OFFSET 4
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002976static void
2977qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
2978{
2979 int delta_mv, closest_delta_mv, sign;
2980
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07002981 delta_mv = chip->max_voltage_mv - VDD_MAX_CENTER_OFFSET - vbat_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002982 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
2983 pr_debug("vbat is not low enough to increase vdd\n");
2984 return;
2985 }
2986
2987 sign = delta_mv > 0 ? 1 : -1;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07002988 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_BUCK_TRIM1_STEP / 2)
2989 / QPNP_CHG_BUCK_TRIM1_STEP) * QPNP_CHG_BUCK_TRIM1_STEP;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002990 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
2991 chip->max_voltage_mv, vbat_mv,
2992 delta_mv, closest_delta_mv);
2993 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
2994 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
2995 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
2996 qpnp_chg_set_appropriate_vddmax(chip);
2997}
2998
David Keitel9fd07382013-05-02 15:37:44 -07002999#define CONSECUTIVE_COUNT 3
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003000#define VBATDET_MAX_ERR_MV 50
David Keitel9fd07382013-05-02 15:37:44 -07003001static void
3002qpnp_eoc_work(struct work_struct *work)
3003{
3004 struct delayed_work *dwork = to_delayed_work(work);
3005 struct qpnp_chg_chip *chip = container_of(dwork,
3006 struct qpnp_chg_chip, eoc_work);
3007 static int count;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003008 static int vbat_low_count;
David Keitel9fd07382013-05-02 15:37:44 -07003009 int ibat_ma, vbat_mv, rc = 0;
3010 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003011 bool vbat_lower_than_vbatdet;
David Keitel9fd07382013-05-02 15:37:44 -07003012
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003013 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003014 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3015
3016 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
3017 if (rc) {
3018 pr_err("failed to read batt_if rc=%d\n", rc);
3019 return;
3020 }
3021
3022 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
3023 if (rc) {
3024 pr_err("failed to read buck rc=%d\n", rc);
3025 return;
3026 }
3027
3028 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
3029 if (rc) {
3030 pr_err("failed to read chg_sts rc=%d\n", rc);
3031 return;
3032 }
3033
3034 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
3035 chg_sts, batt_sts, buck_sts);
3036
3037 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
3038 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3039 pr_debug("no chg connected, stopping\n");
3040 goto stop_eoc;
3041 }
3042
3043 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
3044 || chg_sts & TRKL_CHG_ON_IRQ)) {
3045 ibat_ma = get_prop_current_now(chip) / 1000;
3046 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003047
3048 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
3049 ibat_ma, vbat_mv, chip->term_current);
3050
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003051 vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
3052 if (vbat_lower_than_vbatdet && vbat_mv <
3053 (chip->max_voltage_mv - chip->resume_delta_mv
3054 - VBATDET_MAX_ERR_MV)) {
3055 vbat_low_count++;
3056 pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
3057 vbat_mv, chip->max_voltage_mv,
3058 chip->resume_delta_mv,
3059 VBATDET_MAX_ERR_MV, vbat_low_count);
3060 if (vbat_low_count >= CONSECUTIVE_COUNT) {
3061 pr_debug("woke up too early stopping\n");
3062 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
3063 goto stop_eoc;
3064 } else {
3065 goto check_again_later;
3066 }
3067 } else {
3068 vbat_low_count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003069 }
3070
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003071 if (buck_sts & VDD_LOOP_IRQ)
3072 qpnp_chg_adjust_vddmax(chip, vbat_mv);
3073
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003074 if (!(buck_sts & VDD_LOOP_IRQ)) {
3075 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07003076 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07003077 } else if ((ibat_ma * -1) > chip->term_current) {
3078 pr_debug("Not at EOC, battery current too high\n");
3079 count = 0;
3080 } else if (ibat_ma > 0) {
3081 pr_debug("Charging but system demand increased\n");
3082 count = 0;
3083 } else {
David Keitel9fd07382013-05-02 15:37:44 -07003084 if (count == CONSECUTIVE_COUNT) {
3085 pr_info("End of Charging\n");
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003086 chip->delta_vddmax_mv = 0;
3087 qpnp_chg_set_appropriate_vddmax(chip);
Xiaozhe Shi30e94802013-08-19 16:40:53 -07003088 chip->chg_done = true;
David Keitel9fd07382013-05-02 15:37:44 -07003089 qpnp_chg_charge_en(chip, 0);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003090 /* sleep for a second before enabling */
3091 msleep(2000);
3092 qpnp_chg_charge_en(chip,
3093 !chip->charging_disabled);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003094 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07003095 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07003096 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07003097 goto stop_eoc;
3098 } else {
3099 count += 1;
3100 pr_debug("EOC count = %d\n", count);
3101 }
David Keitel9fd07382013-05-02 15:37:44 -07003102 }
3103 } else {
3104 pr_debug("not charging\n");
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003105 goto stop_eoc;
David Keitel9fd07382013-05-02 15:37:44 -07003106 }
3107
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003108check_again_later:
David Keitel9fd07382013-05-02 15:37:44 -07003109 schedule_delayed_work(&chip->eoc_work,
3110 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
3111 return;
3112
3113stop_eoc:
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003114 vbat_low_count = 0;
David Keitel9fd07382013-05-02 15:37:44 -07003115 count = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003116 pm_relax(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07003117}
3118
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003119static void
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07003120qpnp_chg_insertion_ocv_work(struct work_struct *work)
3121{
3122 struct qpnp_chg_chip *chip = container_of(work,
3123 struct qpnp_chg_chip, insertion_ocv_work);
3124 u8 bat_if_sts = 0, charge_en = 0;
3125 int rc;
3126
3127 chip->insertion_ocv_uv = get_prop_battery_voltage_now(chip);
3128
3129 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
3130 if (rc)
3131 pr_err("failed to read bat_if sts %d\n", rc);
3132
3133 rc = qpnp_chg_read(chip, &charge_en,
3134 chip->chgr_base + CHGR_CHG_CTRL, 1);
3135 if (rc)
3136 pr_err("failed to read bat_if sts %d\n", rc);
3137
3138 pr_debug("batfet sts = %02x, charge_en = %02x ocv = %d\n",
3139 bat_if_sts, charge_en, chip->insertion_ocv_uv);
3140 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3141 pr_debug("psy changed batt_psy\n");
3142 power_supply_changed(&chip->batt_psy);
3143}
3144
3145static void
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07003146qpnp_chg_soc_check_work(struct work_struct *work)
3147{
3148 struct qpnp_chg_chip *chip = container_of(work,
3149 struct qpnp_chg_chip, soc_check_work);
3150
3151 get_prop_capacity(chip);
3152}
3153
David Keitel0c1a4532013-03-21 16:39:06 -07003154#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08003155static void
3156qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
3157{
3158 struct qpnp_chg_chip *chip = ctx;
3159 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07003160 int temp;
David Keitel454ee842013-03-08 16:19:11 -08003161
3162 if (state >= ADC_TM_STATE_NUM) {
3163 pr_err("invalid notification %d\n", state);
3164 return;
3165 }
3166
David Keitel1219a802013-03-21 16:37:21 -07003167 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08003168
David Keitel1219a802013-03-21 16:37:21 -07003169 pr_debug("temp = %d state = %s\n", temp,
3170 state == ADC_TM_WARM_STATE ? "warm" : "cool");
3171
3172 if (state == ADC_TM_WARM_STATE) {
3173 if (temp > chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003174 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08003175 bat_warm = true;
3176 bat_cool = false;
3177 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003178 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003179 chip->adc_param.state_request =
3180 ADC_TM_COOL_THR_ENABLE;
3181 } else if (temp >
3182 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003183 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08003184 bat_warm = false;
3185 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07003186
3187 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07003188 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003189 chip->adc_param.state_request =
3190 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003191 }
3192 } else {
David Keitel1219a802013-03-21 16:37:21 -07003193 if (temp < chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07003194 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08003195 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003196 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08003197 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07003198 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07003199 chip->adc_param.state_request =
3200 ADC_TM_WARM_THR_ENABLE;
David Keitel3e37e5a2013-04-18 10:42:30 -07003201 } else if (temp <
David Keitel1219a802013-03-21 16:37:21 -07003202 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07003203 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08003204 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07003205 bat_cool = false;
3206
David Keitel0c1a4532013-03-21 16:39:06 -07003207 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003208 chip->adc_param.high_temp = chip->warm_bat_decidegc;
3209 chip->adc_param.state_request =
3210 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003211 }
3212 }
3213
3214 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07003215 chip->bat_is_cool = bat_cool;
3216 chip->bat_is_warm = bat_warm;
3217
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07003218 if (bat_cool || bat_warm)
3219 chip->resuming_charging = false;
3220
3221 /**
3222 * set appropriate voltages and currents.
3223 *
3224 * Note that when the battery is hot or cold, the charger
3225 * driver will not resume with SoC. Only vbatdet is used to
3226 * determine resume of charging.
3227 */
David Keitel454ee842013-03-08 16:19:11 -08003228 qpnp_chg_set_appropriate_vddmax(chip);
3229 qpnp_chg_set_appropriate_battery_current(chip);
3230 qpnp_chg_set_appropriate_vbatdet(chip);
David Keitel454ee842013-03-08 16:19:11 -08003231 }
3232
David Keitelec3c09802013-06-13 13:05:30 -07003233 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
3234 chip->bat_is_warm, chip->bat_is_cool,
3235 chip->adc_param.low_temp, chip->adc_param.high_temp);
3236
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003237 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07003238 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07003239}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07003240
David Keitelec3c09802013-06-13 13:05:30 -07003241#define MIN_COOL_TEMP -300
3242#define MAX_WARM_TEMP 1000
3243
3244static int
3245qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
3246 enum power_supply_property psp, int temp_degc)
3247{
3248 int rc = 0;
3249
3250 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
3251 pr_err("Bad temperature request %d\n", temp_degc);
3252 return -EINVAL;
3253 }
3254
3255 mutex_lock(&chip->jeita_configure_lock);
3256 switch (psp) {
3257 case POWER_SUPPLY_PROP_COOL_TEMP:
3258 if (temp_degc >=
3259 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
3260 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
3261 temp_degc, chip->warm_bat_decidegc,
3262 HYSTERISIS_DECIDEGC);
3263 rc = -EINVAL;
3264 goto mutex_unlock;
3265 }
3266 if (chip->bat_is_cool)
3267 chip->adc_param.high_temp =
3268 temp_degc + HYSTERISIS_DECIDEGC;
3269 else if (!chip->bat_is_warm)
3270 chip->adc_param.low_temp = temp_degc;
3271
3272 chip->cool_bat_decidegc = temp_degc;
3273 break;
3274 case POWER_SUPPLY_PROP_WARM_TEMP:
3275 if (temp_degc <=
3276 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
3277 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
3278 temp_degc, chip->warm_bat_decidegc,
3279 HYSTERISIS_DECIDEGC);
3280 rc = -EINVAL;
3281 goto mutex_unlock;
3282 }
3283 if (chip->bat_is_warm)
3284 chip->adc_param.low_temp =
3285 temp_degc - HYSTERISIS_DECIDEGC;
3286 else if (!chip->bat_is_cool)
3287 chip->adc_param.high_temp = temp_degc;
3288
3289 chip->warm_bat_decidegc = temp_degc;
3290 break;
3291 default:
3292 rc = -EINVAL;
3293 goto mutex_unlock;
3294 }
3295
3296 schedule_work(&chip->adc_measure_work);
3297
3298mutex_unlock:
3299 mutex_unlock(&chip->jeita_configure_lock);
3300 return rc;
David Keitel454ee842013-03-08 16:19:11 -08003301}
3302
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003303#define POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS 20
3304#define POWER_STAGE_REDUCE_MAX_VBAT_UV 3900000
3305#define POWER_STAGE_REDUCE_MIN_VCHG_UV 4800000
3306#define POWER_STAGE_SEL_MASK 0x0F
3307#define POWER_STAGE_REDUCED 0x01
3308#define POWER_STAGE_DEFAULT 0x0F
3309static bool
3310qpnp_chg_is_power_stage_reduced(struct qpnp_chg_chip *chip)
3311{
3312 int rc;
3313 u8 reg;
3314
3315 rc = qpnp_chg_read(chip, &reg,
3316 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3317 1);
3318 if (rc) {
3319 pr_err("Error %d reading power stage register\n", rc);
3320 return false;
3321 }
3322
3323 if ((reg & POWER_STAGE_SEL_MASK) == POWER_STAGE_DEFAULT)
3324 return false;
3325
3326 return true;
3327}
3328
3329static int
3330qpnp_chg_power_stage_set(struct qpnp_chg_chip *chip, bool reduce)
3331{
3332 int rc;
3333 u8 reg = 0xA5;
3334
3335 rc = qpnp_chg_write(chip, &reg,
3336 chip->buck_base + SEC_ACCESS,
3337 1);
3338 if (rc) {
3339 pr_err("Error %d writing 0xA5 to buck's 0x%x reg\n",
3340 rc, SEC_ACCESS);
3341 return rc;
3342 }
3343
3344 reg = POWER_STAGE_DEFAULT;
3345 if (reduce)
3346 reg = POWER_STAGE_REDUCED;
3347 rc = qpnp_chg_write(chip, &reg,
3348 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3349 1);
3350
3351 if (rc)
3352 pr_err("Error %d writing 0x%x power stage register\n", rc, reg);
3353 return rc;
3354}
3355
3356static int
3357qpnp_chg_get_vusbin_uv(struct qpnp_chg_chip *chip)
3358{
3359 int rc = 0;
3360 struct qpnp_vadc_result results;
3361
3362 rc = qpnp_vadc_read(chip->vadc_dev, USBIN, &results);
3363 if (rc) {
3364 pr_err("Unable to read vbat rc=%d\n", rc);
3365 return 0;
3366 }
3367 return results.physical;
3368}
3369
3370static
3371int get_vusb_averaged(struct qpnp_chg_chip *chip, int sample_count)
3372{
3373 int vusb_uv = 0;
3374 int i;
3375
3376 /* avoid overflows */
3377 if (sample_count > 256)
3378 sample_count = 256;
3379
3380 for (i = 0; i < sample_count; i++)
3381 vusb_uv += qpnp_chg_get_vusbin_uv(chip);
3382
3383 vusb_uv = vusb_uv / sample_count;
3384 return vusb_uv;
3385}
3386
3387static
3388int get_vbat_averaged(struct qpnp_chg_chip *chip, int sample_count)
3389{
3390 int vbat_uv = 0;
3391 int i;
3392
3393 /* avoid overflows */
3394 if (sample_count > 256)
3395 sample_count = 256;
3396
3397 for (i = 0; i < sample_count; i++)
3398 vbat_uv += get_prop_battery_voltage_now(chip);
3399
3400 vbat_uv = vbat_uv / sample_count;
3401 return vbat_uv;
3402}
3403
3404static void
3405qpnp_chg_reduce_power_stage(struct qpnp_chg_chip *chip)
3406{
3407 struct timespec ts;
3408 bool power_stage_reduced_in_hw = qpnp_chg_is_power_stage_reduced(chip);
3409 bool reduce_power_stage = false;
3410 int vbat_uv = get_vbat_averaged(chip, 16);
3411 int vusb_uv = get_vusb_averaged(chip, 16);
3412 bool fast_chg =
3413 (get_prop_charge_type(chip) == POWER_SUPPLY_CHARGE_TYPE_FAST);
3414 static int count_restore_power_stage;
3415 static int count_reduce_power_stage;
3416 bool vchg_loop = get_prop_vchg_loop(chip);
3417 bool ichg_loop = qpnp_chg_is_ichg_loop_active(chip);
3418 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
3419 bool usb_ma_above_wall =
3420 (qpnp_chg_usb_iusbmax_get(chip) > USB_WALL_THRESHOLD_MA);
3421
3422 if (fast_chg
3423 && usb_present
3424 && usb_ma_above_wall
3425 && vbat_uv < POWER_STAGE_REDUCE_MAX_VBAT_UV
3426 && vusb_uv > POWER_STAGE_REDUCE_MIN_VCHG_UV)
3427 reduce_power_stage = true;
3428
3429 if ((usb_present && usb_ma_above_wall)
3430 && (vchg_loop || ichg_loop))
3431 reduce_power_stage = true;
3432
3433 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3434 count_restore_power_stage++;
3435 count_reduce_power_stage = 0;
3436 } else if (!power_stage_reduced_in_hw && reduce_power_stage) {
3437 count_reduce_power_stage++;
3438 count_restore_power_stage = 0;
3439 } else if (power_stage_reduced_in_hw == reduce_power_stage) {
3440 count_restore_power_stage = 0;
3441 count_reduce_power_stage = 0;
3442 }
3443
3444 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",
3445 power_stage_reduced_in_hw, reduce_power_stage,
3446 usb_present, usb_ma_above_wall,
3447 vbat_uv, vusb_uv, fast_chg,
3448 ichg_loop, vchg_loop,
3449 count_restore_power_stage, count_reduce_power_stage);
3450
3451 if (!power_stage_reduced_in_hw && reduce_power_stage) {
3452 if (count_reduce_power_stage >= 2) {
3453 qpnp_chg_power_stage_set(chip, true);
3454 power_stage_reduced_in_hw = true;
3455 }
3456 }
3457
3458 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3459 if (count_restore_power_stage >= 6
3460 || (!usb_present || !usb_ma_above_wall)) {
3461 qpnp_chg_power_stage_set(chip, false);
3462 power_stage_reduced_in_hw = false;
3463 }
3464 }
3465
3466 if (usb_present && usb_ma_above_wall) {
3467 getnstimeofday(&ts);
3468 ts.tv_sec += POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS;
3469 alarm_start_range(&chip->reduce_power_stage_alarm,
3470 timespec_to_ktime(ts),
3471 timespec_to_ktime(ts));
3472 } else {
3473 pr_debug("stopping power stage workaround\n");
3474 chip->power_stage_workaround_running = false;
3475 }
3476}
3477
3478static void
David Keitel6e63bd52013-09-06 18:00:03 -07003479qpnp_chg_batfet_lcl_work(struct work_struct *work)
3480{
3481 struct qpnp_chg_chip *chip = container_of(work,
3482 struct qpnp_chg_chip, batfet_lcl_work);
3483
3484 mutex_lock(&chip->batfet_vreg_lock);
3485 if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
3486 qpnp_chg_is_dc_chg_plugged_in(chip)) {
3487 qpnp_chg_regulator_batfet_set(chip, 1);
3488 pr_debug("disabled ULPM\n");
3489 } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
3490 && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3491 qpnp_chg_regulator_batfet_set(chip, 0);
3492 pr_debug("enabled ULPM\n");
3493 }
3494 mutex_unlock(&chip->batfet_vreg_lock);
3495}
3496
3497static void
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003498qpnp_chg_reduce_power_stage_work(struct work_struct *work)
3499{
3500 struct qpnp_chg_chip *chip = container_of(work,
3501 struct qpnp_chg_chip, reduce_power_stage_work);
3502
3503 qpnp_chg_reduce_power_stage(chip);
3504}
3505
3506static void
3507qpnp_chg_reduce_power_stage_callback(struct alarm *alarm)
3508{
3509 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
3510 reduce_power_stage_alarm);
3511
3512 schedule_work(&chip->reduce_power_stage_work);
3513}
3514
David Keitelbe208252013-01-31 14:49:25 -08003515static int
David Keitel432e1232013-06-05 16:10:18 -07003516qpnp_dc_power_set_property(struct power_supply *psy,
3517 enum power_supply_property psp,
3518 const union power_supply_propval *val)
3519{
3520 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3521 dc_psy);
3522 int rc = 0;
3523
3524 switch (psp) {
3525 case POWER_SUPPLY_PROP_CURRENT_MAX:
3526 if (!val->intval)
3527 break;
3528
3529 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
3530 if (rc) {
3531 pr_err("Error setting idcmax property %d\n", rc);
3532 return rc;
3533 }
3534 chip->maxinput_dc_ma = (val->intval / 1000);
3535
3536 break;
3537 default:
3538 return -EINVAL;
3539 }
3540
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003541 pr_debug("psy changed dc_psy\n");
David Keitel432e1232013-06-05 16:10:18 -07003542 power_supply_changed(&chip->dc_psy);
3543 return rc;
3544}
3545
3546static int
David Keitelbe208252013-01-31 14:49:25 -08003547qpnp_batt_power_set_property(struct power_supply *psy,
3548 enum power_supply_property psp,
3549 const union power_supply_propval *val)
3550{
3551 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3552 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07003553 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08003554
3555 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07003556 case POWER_SUPPLY_PROP_COOL_TEMP:
3557 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3558 break;
3559 case POWER_SUPPLY_PROP_WARM_TEMP:
3560 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3561 break;
David Keitelbe208252013-01-31 14:49:25 -08003562 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
3563 chip->charging_disabled = !(val->intval);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003564 if (chip->charging_disabled) {
3565 /* disable charging */
3566 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3567 qpnp_chg_force_run_on_batt(chip,
3568 chip->charging_disabled);
3569 } else {
3570 /* enable charging */
3571 qpnp_chg_force_run_on_batt(chip,
3572 chip->charging_disabled);
3573 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3574 }
David Keitelbe208252013-01-31 14:49:25 -08003575 break;
3576 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
3577 qpnp_batt_system_temp_level_set(chip, val->intval);
3578 break;
David Keitel337bd862013-07-15 21:42:58 -07003579 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
3580 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
3581 break;
David Keitel2586f0a2013-08-20 10:02:26 -07003582 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
3583 qpnp_chg_iusb_trim_set(chip, val->intval);
3584 break;
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07003585 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
3586 qpnp_chg_input_current_settled(chip);
3587 break;
David Keitel337bd862013-07-15 21:42:58 -07003588 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
3589 qpnp_chg_vinmin_set(chip, val->intval / 1000);
3590 break;
David Keitelbe208252013-01-31 14:49:25 -08003591 default:
3592 return -EINVAL;
3593 }
3594
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003595 pr_debug("psy changed batt_psy\n");
David Keitelbe208252013-01-31 14:49:25 -08003596 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07003597 return rc;
David Keitelbe208252013-01-31 14:49:25 -08003598}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003599
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003600static int
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003601qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07003602{
David Keitelfe51cb92013-04-02 19:42:58 -07003603 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07003604 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07003605 if (chip->type == SMBB)
3606 chip->flags |= BOOST_FLASH_WA;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003607 if (chip->type == SMBBP) {
3608 struct device_node *revid_dev_node;
3609 struct pmic_revid_data *revid_data;
3610
3611 chip->flags |= BOOST_FLASH_WA;
3612
3613 revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
3614 "qcom,pmic-revid", 0);
3615 if (!revid_dev_node) {
3616 pr_err("Missing qcom,pmic-revid property\n");
3617 return -EINVAL;
3618 }
3619 revid_data = get_revid_data(revid_dev_node);
3620 if (IS_ERR(revid_data)) {
3621 pr_err("Couldnt get revid data rc = %ld\n",
3622 PTR_ERR(revid_data));
3623 return PTR_ERR(revid_data);
3624 }
3625
3626 if (revid_data->rev4 < PM8226_V2P1_REV4
3627 || ((revid_data->rev4 == PM8226_V2P1_REV4)
3628 && (revid_data->rev3 <= PM8226_V2P1_REV3))) {
3629 chip->flags |= POWER_STAGE_WA;
3630 }
3631 }
3632 return 0;
David Keiteld681cda2012-10-02 15:44:21 -07003633}
3634
David Keitel0f35be42013-04-16 11:10:40 -07003635static int
3636qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
3637{
3638 int rc = 0;
3639 struct resource *resource;
3640 struct spmi_resource *spmi_resource;
3641 u8 subtype;
3642 struct spmi_device *spmi = chip->spmi;
3643
3644 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
3645 if (!spmi_resource) {
3646 pr_err("qpnp_chg: spmi resource absent\n");
3647 return rc;
3648 }
3649
3650 resource = spmi_get_resource(spmi, spmi_resource,
3651 IORESOURCE_MEM, 0);
3652 if (!(resource && resource->start)) {
3653 pr_err("node %s IO resource absent!\n",
3654 spmi->dev.of_node->full_name);
3655 return rc;
3656 }
3657
3658 rc = qpnp_chg_read(chip, &subtype,
3659 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
3660 if (rc) {
3661 pr_err("Peripheral subtype read failed rc=%d\n", rc);
3662 return rc;
3663 }
3664
3665 switch (subtype) {
3666 case SMBB_CHGR_SUBTYPE:
3667 case SMBBP_CHGR_SUBTYPE:
3668 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07003669 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003670 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07003671 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003672 pr_err("Unable to get fast-chg-on irq\n");
3673 return rc;
3674 }
3675
David Keitel47185a62013-05-15 18:54:10 -07003676 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003677 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07003678 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003679 pr_err("Unable to get trkl-chg-on irq\n");
3680 return rc;
3681 }
3682
David Keitel47185a62013-05-15 18:54:10 -07003683 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003684 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07003685 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003686 pr_err("Unable to get chg_failed irq\n");
3687 return rc;
3688 }
3689
David Keitel47185a62013-05-15 18:54:10 -07003690 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07003691 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07003692 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07003693 pr_err("Unable to get fast-chg-on irq\n");
3694 return rc;
3695 }
3696
David Keitel47185a62013-05-15 18:54:10 -07003697 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003698 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07003699 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003700 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003701 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003702 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003703 return rc;
3704 }
3705
David Keitel47185a62013-05-15 18:54:10 -07003706 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003707 qpnp_chg_chgr_chg_fastchg_irq_handler,
3708 IRQF_TRIGGER_RISING,
3709 "fast-chg-on", chip);
3710 if (rc < 0) {
3711 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003712 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003713 return rc;
3714 }
3715
David Keitel47185a62013-05-15 18:54:10 -07003716 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003717 qpnp_chg_chgr_chg_trklchg_irq_handler,
3718 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07003719 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003720 if (rc < 0) {
3721 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003722 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003723 return rc;
3724 }
David Keitel9fd07382013-05-02 15:37:44 -07003725
3726 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07003727 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07003728 qpnp_chg_vbatdet_lo_irq_handler,
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003729 IRQF_TRIGGER_RISING,
David Keitel9fd07382013-05-02 15:37:44 -07003730 "vbat-det-lo", chip);
3731 if (rc < 0) {
3732 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003733 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07003734 return rc;
3735 }
3736
David Keitel47185a62013-05-15 18:54:10 -07003737 enable_irq_wake(chip->chg_trklchg.irq);
3738 enable_irq_wake(chip->chg_failed.irq);
3739 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
3740 enable_irq_wake(chip->chg_vbatdet_lo.irq);
David Keitel0f35be42013-04-16 11:10:40 -07003741
3742 break;
3743 case SMBB_BAT_IF_SUBTYPE:
3744 case SMBBP_BAT_IF_SUBTYPE:
3745 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07003746 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003747 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07003748 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003749 pr_err("Unable to get batt-pres irq\n");
3750 return rc;
3751 }
David Keitel47185a62013-05-15 18:54:10 -07003752 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003753 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07003754 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
3755 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07003756 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003757 if (rc < 0) {
3758 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003759 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003760 return rc;
3761 }
3762
David Keitel47185a62013-05-15 18:54:10 -07003763 enable_irq_wake(chip->batt_pres.irq);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07003764
3765 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
3766 spmi_resource, "bat-temp-ok");
3767 if (chip->batt_temp_ok.irq < 0) {
3768 pr_err("Unable to get bat-temp-ok irq\n");
3769 return rc;
3770 }
3771 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
3772 qpnp_chg_bat_if_batt_temp_irq_handler,
3773 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3774 "bat-temp-ok", chip);
3775 if (rc < 0) {
3776 pr_err("Can't request %d bat-temp-ok irq: %d\n",
3777 chip->batt_temp_ok.irq, rc);
3778 return rc;
3779 }
3780
3781 enable_irq_wake(chip->batt_temp_ok.irq);
3782
David Keitel0f35be42013-04-16 11:10:40 -07003783 break;
David Keitel337bd862013-07-15 21:42:58 -07003784 case SMBB_BUCK_SUBTYPE:
3785 case SMBBP_BUCK_SUBTYPE:
3786 case SMBCL_BUCK_SUBTYPE:
David Keitel337bd862013-07-15 21:42:58 -07003787 break;
3788
David Keitel0f35be42013-04-16 11:10:40 -07003789 case SMBB_USB_CHGPTH_SUBTYPE:
3790 case SMBBP_USB_CHGPTH_SUBTYPE:
3791 case SMBCL_USB_CHGPTH_SUBTYPE:
Wu Fenglin04ae6de2013-09-09 19:15:06 +08003792 if (chip->ovp_monitor_enable) {
3793 chip->coarse_det_usb.irq =
3794 spmi_get_irq_byname(spmi,
3795 spmi_resource, "coarse-det-usb");
3796 if (chip->coarse_det_usb.irq < 0) {
3797 pr_err("Can't get coarse-det irq\n");
3798 return rc;
3799 }
3800 rc = devm_request_irq(chip->dev,
3801 chip->coarse_det_usb.irq,
3802 qpnp_chg_coarse_det_usb_irq_handler,
3803 IRQF_TRIGGER_RISING |
3804 IRQF_TRIGGER_FALLING,
3805 "coarse-det-usb", chip);
3806 if (rc < 0) {
3807 pr_err("Can't req %d coarse-det: %d\n",
3808 chip->coarse_det_usb.irq, rc);
3809 return rc;
3810 }
3811 }
3812
David Keitel47185a62013-05-15 18:54:10 -07003813 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003814 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07003815 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003816 pr_err("Unable to get usbin irq\n");
3817 return rc;
3818 }
David Keitel47185a62013-05-15 18:54:10 -07003819 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003820 qpnp_chg_usb_usbin_valid_irq_handler,
3821 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07003822 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003823 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003824 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003825 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003826 return rc;
3827 }
David Keitel344c6972013-04-09 19:28:21 -07003828
David Keitel47185a62013-05-15 18:54:10 -07003829 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07003830 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07003831 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07003832 pr_err("Unable to get chg-gone irq\n");
3833 return rc;
3834 }
David Keitel47185a62013-05-15 18:54:10 -07003835 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07003836 qpnp_chg_usb_chg_gone_irq_handler,
3837 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07003838 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07003839 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003840 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003841 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07003842 return rc;
3843 }
David Keitel47185a62013-05-15 18:54:10 -07003844
David Keitel0b62bdd2013-07-10 17:30:51 -07003845 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
3846 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
3847 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
3848 spmi_resource, "usb-ocp");
3849 if (chip->usb_ocp.irq < 0) {
3850 pr_err("Unable to get usbin irq\n");
3851 return rc;
3852 }
3853 rc = devm_request_irq(chip->dev,
3854 chip->usb_ocp.irq,
3855 qpnp_chg_usb_usb_ocp_irq_handler,
3856 IRQF_TRIGGER_RISING, "usb-ocp", chip);
3857 if (rc < 0) {
3858 pr_err("Can't request %d usb-ocp: %d\n",
3859 chip->usb_ocp.irq, rc);
3860 return rc;
3861 }
3862
3863 enable_irq_wake(chip->usb_ocp.irq);
3864 }
3865
David Keitel47185a62013-05-15 18:54:10 -07003866 enable_irq_wake(chip->usbin_valid.irq);
3867 enable_irq_wake(chip->chg_gone.irq);
David Keitel0f35be42013-04-16 11:10:40 -07003868 break;
3869 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07003870 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003871 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07003872 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003873 pr_err("Unable to get dcin irq\n");
3874 return -rc;
3875 }
David Keitel47185a62013-05-15 18:54:10 -07003876 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003877 qpnp_chg_dc_dcin_valid_irq_handler,
3878 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07003879 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003880 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003881 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003882 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003883 return rc;
3884 }
3885
David Keitel47185a62013-05-15 18:54:10 -07003886 enable_irq_wake(chip->dcin_valid.irq);
David Keitel0f35be42013-04-16 11:10:40 -07003887 break;
3888 }
3889 }
3890
3891 return rc;
3892}
3893
Xiaozhe Shica289e02013-06-19 13:24:51 -07003894static int
3895qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
3896{
3897 struct bms_battery_data batt_data;
3898 struct device_node *node;
3899 struct qpnp_vadc_result result;
3900 int rc;
3901
3902 node = of_find_node_by_name(chip->spmi->dev.of_node,
3903 "qcom,battery-data");
3904 if (node) {
3905 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07003906 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07003907 if (rc) {
3908 pr_err("error reading batt id channel = %d, rc = %d\n",
3909 LR_MUX2_BAT_ID, rc);
3910 return rc;
3911 }
3912
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07003913 batt_data.max_voltage_uv = -1;
3914 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07003915 rc = of_batterydata_read_data(node,
3916 &batt_data, result.physical);
3917 if (rc) {
3918 pr_err("failed to read battery data: %d\n", rc);
3919 return rc;
3920 }
3921
Xiaozhe Shi34e568232013-07-24 12:47:34 -07003922 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07003923 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07003924 chip->safe_voltage_mv = chip->max_voltage_mv
3925 + MAX_DELTA_VDD_MAX_MV;
3926 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07003927 if (batt_data.iterm_ua >= 0)
3928 chip->term_current = batt_data.iterm_ua / 1000;
3929 }
3930
3931 return 0;
3932}
3933
David Keitel80668952012-07-27 14:25:49 -07003934#define WDOG_EN_BIT BIT(7)
3935static int
3936qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
3937 struct spmi_resource *spmi_resource)
3938{
3939 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07003940 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07003941 struct regulator_init_data *init_data;
3942 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07003943
3944 switch (subtype) {
3945 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003946 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003947 case SMBCL_CHGR_SUBTYPE:
Prasad Sodagudic3678012013-09-23 12:01:19 +05303948 qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
3949
David Keitel80668952012-07-27 14:25:49 -07003950 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
3951 if (rc) {
3952 pr_debug("failed setting min_voltage rc=%d\n", rc);
3953 return rc;
3954 }
David Keitel80668952012-07-27 14:25:49 -07003955 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
3956 if (rc) {
3957 pr_debug("failed setting safe_voltage rc=%d\n", rc);
3958 return rc;
3959 }
David Keitel454ee842013-03-08 16:19:11 -08003960 rc = qpnp_chg_vbatdet_set(chip,
3961 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08003962 if (rc) {
3963 pr_debug("failed setting resume_voltage rc=%d\n", rc);
3964 return rc;
3965 }
David Keitel80668952012-07-27 14:25:49 -07003966 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
3967 if (rc) {
3968 pr_debug("failed setting ibatmax rc=%d\n", rc);
3969 return rc;
3970 }
David Keitel365c4c42013-03-08 16:20:40 -08003971 if (chip->term_current) {
3972 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
3973 if (rc) {
3974 pr_debug("failed setting ibatterm rc=%d\n", rc);
3975 return rc;
3976 }
David Keitel80668952012-07-27 14:25:49 -07003977 }
David Keitel5d44fa52012-12-03 16:37:31 -08003978 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
3979 if (rc) {
3980 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
3981 return rc;
3982 }
David Keitela4b7b592013-04-11 18:34:35 -07003983 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
3984 if (rc) {
3985 pr_debug("failed setting tchg_mins rc=%d\n", rc);
3986 return rc;
3987 }
3988
David Keitel80668952012-07-27 14:25:49 -07003989 /* HACK: Disable wdog */
3990 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
3991 0xFF, 0xA0, 1);
3992
David Keitelb4e43542013-04-09 17:30:41 -07003993 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07003994 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
3995 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07003996 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07003997
David Keitel80668952012-07-27 14:25:49 -07003998 break;
3999 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004000 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004001 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004002 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
4003 if (rc)
4004 return rc;
4005
David Keitel9201df32013-01-10 18:38:34 -08004006 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07004007 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08004008 BUCK_VBAT_REG_NODE_SEL_BIT,
4009 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
4010 if (rc) {
4011 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
4012 return rc;
4013 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07004014
4015 rc = qpnp_chg_read(chip, &chip->trim_center,
4016 chip->buck_base + BUCK_CTRL_TRIM1, 1);
4017 if (rc) {
4018 pr_debug("failed to read trim center rc=%d\n", rc);
4019 return rc;
4020 }
4021 chip->trim_center >>= 4;
4022 pr_debug("trim center = %02x\n", chip->trim_center);
David Keitel80668952012-07-27 14:25:49 -07004023 break;
4024 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004025 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004026 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07004027 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07004028 switch (chip->bpd_detection) {
4029 case BPD_TYPE_BAT_THM:
4030 reg = BAT_THM_EN;
4031 break;
4032 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07004033 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07004034 break;
4035 case BPD_TYPE_BAT_THM_BAT_ID:
4036 reg = BAT_THM_EN | BAT_ID_EN;
4037 break;
4038 default:
4039 reg = BAT_THM_EN;
4040 break;
4041 }
David Keitel796882d2013-05-14 18:01:11 -07004042
4043 rc = qpnp_chg_masked_write(chip,
4044 chip->bat_if_base + BAT_IF_BPD_CTRL,
4045 BAT_IF_BPD_CTRL_SEL,
4046 reg, 1);
4047 if (rc) {
4048 pr_debug("failed to chose BPD rc=%d\n", rc);
4049 return rc;
4050 }
David Keitel85ae4342013-04-16 11:46:00 -07004051 /* Force on VREF_BAT_THM */
4052 rc = qpnp_chg_masked_write(chip,
4053 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4054 VREF_BATT_THERM_FORCE_ON,
4055 VREF_BATT_THERM_FORCE_ON, 1);
4056 if (rc) {
4057 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
4058 return rc;
4059 }
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07004060
4061 init_data = of_get_regulator_init_data(chip->dev,
4062 spmi_resource->of_node);
4063
4064 if (init_data->constraints.name) {
4065 rdesc = &(chip->batfet_vreg.rdesc);
4066 rdesc->owner = THIS_MODULE;
4067 rdesc->type = REGULATOR_VOLTAGE;
4068 rdesc->ops = &qpnp_chg_batfet_vreg_ops;
4069 rdesc->name = init_data->constraints.name;
4070
4071 init_data->constraints.valid_ops_mask
4072 |= REGULATOR_CHANGE_STATUS;
4073
4074 chip->batfet_vreg.rdev = regulator_register(rdesc,
4075 chip->dev, init_data, chip,
4076 spmi_resource->of_node);
4077 if (IS_ERR(chip->batfet_vreg.rdev)) {
4078 rc = PTR_ERR(chip->batfet_vreg.rdev);
4079 chip->batfet_vreg.rdev = NULL;
4080 if (rc != -EPROBE_DEFER)
4081 pr_err("batfet reg failed, rc=%d\n",
4082 rc);
4083 return rc;
4084 }
4085 }
David Keitel80668952012-07-27 14:25:49 -07004086 break;
4087 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004088 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004089 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07004090 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07004091 rc = qpnp_chg_masked_write(chip,
4092 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4093 ENUM_T_STOP_BIT,
4094 ENUM_T_STOP_BIT, 1);
4095 if (rc) {
4096 pr_err("failed to write enum stop rc=%d\n", rc);
4097 return -ENXIO;
4098 }
4099 }
David Keiteld681cda2012-10-02 15:44:21 -07004100
David Keitel6dc4ed42013-05-17 11:08:58 -07004101 init_data = of_get_regulator_init_data(chip->dev,
4102 spmi_resource->of_node);
4103 if (!init_data) {
4104 pr_err("unable to allocate memory\n");
4105 return -ENOMEM;
4106 }
4107
4108 if (init_data->constraints.name) {
4109 if (of_get_property(chip->dev->of_node,
4110 "otg-parent-supply", NULL))
4111 init_data->supply_regulator = "otg-parent";
4112
4113 rdesc = &(chip->otg_vreg.rdesc);
4114 rdesc->owner = THIS_MODULE;
4115 rdesc->type = REGULATOR_VOLTAGE;
4116 rdesc->ops = &qpnp_chg_otg_reg_ops;
4117 rdesc->name = init_data->constraints.name;
4118
4119 init_data->constraints.valid_ops_mask
4120 |= REGULATOR_CHANGE_STATUS;
4121
4122 chip->otg_vreg.rdev = regulator_register(rdesc,
4123 chip->dev, init_data, chip,
4124 spmi_resource->of_node);
4125 if (IS_ERR(chip->otg_vreg.rdev)) {
4126 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004127 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004128 if (rc != -EPROBE_DEFER)
4129 pr_err("OTG reg failed, rc=%d\n", rc);
4130 return rc;
4131 }
4132 }
4133
David Keiteld681cda2012-10-02 15:44:21 -07004134 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08004135 chip->usb_chgpth_base + USB_OVP_CTL,
4136 USB_VALID_DEB_20MS,
4137 USB_VALID_DEB_20MS, 1);
4138
4139 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07004140 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
4141 ENUM_T_STOP_BIT,
4142 ENUM_T_STOP_BIT, 1);
4143
David Keitel344c6972013-04-09 19:28:21 -07004144 rc = qpnp_chg_masked_write(chip,
4145 chip->usb_chgpth_base + SEC_ACCESS,
4146 0xFF,
4147 0xA5, 1);
4148
4149 rc = qpnp_chg_masked_write(chip,
4150 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
4151 0xFF,
4152 0x80, 1);
4153
David Keitel0b62bdd2013-07-10 17:30:51 -07004154 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
4155 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
4156 rc = qpnp_chg_masked_write(chip,
4157 chip->usb_chgpth_base + USB_OCP_THR,
4158 OCP_THR_MASK,
4159 OCP_THR_900_MA, 1);
4160 if (rc)
4161 pr_err("Failed to configure OCP rc = %d\n", rc);
4162 }
4163
David Keitel80668952012-07-27 14:25:49 -07004164 break;
4165 case SMBB_DC_CHGPTH_SUBTYPE:
4166 break;
4167 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004168 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07004169 init_data = of_get_regulator_init_data(chip->dev,
4170 spmi_resource->of_node);
4171 if (!init_data) {
4172 pr_err("unable to allocate memory\n");
4173 return -ENOMEM;
4174 }
4175
4176 if (init_data->constraints.name) {
4177 if (of_get_property(chip->dev->of_node,
4178 "boost-parent-supply", NULL))
4179 init_data->supply_regulator = "boost-parent";
4180
4181 rdesc = &(chip->boost_vreg.rdesc);
4182 rdesc->owner = THIS_MODULE;
4183 rdesc->type = REGULATOR_VOLTAGE;
4184 rdesc->ops = &qpnp_chg_boost_reg_ops;
4185 rdesc->name = init_data->constraints.name;
4186
4187 init_data->constraints.valid_ops_mask
4188 |= REGULATOR_CHANGE_STATUS
4189 | REGULATOR_CHANGE_VOLTAGE;
4190
4191 chip->boost_vreg.rdev = regulator_register(rdesc,
4192 chip->dev, init_data, chip,
4193 spmi_resource->of_node);
4194 if (IS_ERR(chip->boost_vreg.rdev)) {
4195 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07004196 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07004197 if (rc != -EPROBE_DEFER)
4198 pr_err("boost reg failed, rc=%d\n", rc);
4199 return rc;
4200 }
4201 }
David Keitel80668952012-07-27 14:25:49 -07004202 break;
4203 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004204 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004205 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07004206 if (subtype == SMBB_MISC_SUBTYPE)
4207 chip->type = SMBB;
4208 else if (subtype == SMBBP_MISC_SUBTYPE)
4209 chip->type = SMBBP;
4210 else if (subtype == SMBCL_MISC_SUBTYPE)
4211 chip->type = SMBCL;
4212
David Keitel80668952012-07-27 14:25:49 -07004213 pr_debug("Setting BOOT_DONE\n");
4214 rc = qpnp_chg_masked_write(chip,
4215 chip->misc_base + CHGR_MISC_BOOT_DONE,
4216 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004217 rc = qpnp_chg_read(chip, &reg,
4218 chip->misc_base + MISC_REVISION2, 1);
4219 if (rc) {
4220 pr_err("failed to read revision register rc=%d\n", rc);
4221 return rc;
4222 }
David Keitel80668952012-07-27 14:25:49 -07004223
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004224 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07004225 break;
4226 default:
4227 pr_err("Invalid peripheral subtype\n");
4228 }
4229 return rc;
4230}
4231
David Keitel112ba9c2013-04-12 18:40:43 -07004232#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
4233do { \
4234 if (retval) \
4235 break; \
4236 \
4237 retval = of_property_read_u32(chip->spmi->dev.of_node, \
4238 "qcom," qpnp_dt_property, \
4239 &chip->prop); \
4240 \
4241 if ((retval == -EINVAL) && optional) \
4242 retval = 0; \
4243 else if (retval) \
4244 pr_err("Error reading " #qpnp_dt_property \
4245 " property rc = %d\n", rc); \
4246} while (0)
4247
4248static int
4249qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
4250{
4251 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004252 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07004253
4254 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
4255 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
4256 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
4257 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
4258 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
4259 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
4260 if (rc)
4261 pr_err("failed to read required dt parameters %d\n", rc);
4262
4263 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
4264 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
4265 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
4266 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
4267 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07004268 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07004269 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
4270 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004271 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
Prasad Sodagudic3678012013-09-23 12:01:19 +05304272 OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004273
David Keitel112ba9c2013-04-12 18:40:43 -07004274 if (rc)
4275 return rc;
4276
David Keitel796882d2013-05-14 18:01:11 -07004277 rc = of_property_read_string(chip->spmi->dev.of_node,
4278 "qcom,bpd-detection", &bpd);
4279 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07004280 /* Select BAT_THM as default BPD scheme */
4281 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004282 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004283 } else {
4284 chip->bpd_detection = get_bpd(bpd);
4285 if (chip->bpd_detection < 0) {
4286 pr_err("failed to determine bpd schema %d\n", rc);
4287 return rc;
4288 }
4289 }
4290
David Keitel112ba9c2013-04-12 18:40:43 -07004291 /* Look up JEITA compliance parameters if cool and warm temp provided */
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004292 if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004293 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
4294 if (IS_ERR(chip->adc_tm_dev)) {
4295 rc = PTR_ERR(chip->adc_tm_dev);
4296 if (rc != -EPROBE_DEFER)
4297 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07004298 return rc;
4299 }
4300
4301 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
4302 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
4303 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
4304 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
4305 if (rc)
4306 return rc;
4307 }
4308
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08004309 /* Get the use-external-rsense property */
4310 chip->use_external_rsense = of_property_read_bool(
4311 chip->spmi->dev.of_node,
4312 "qcom,use-external-rsense");
4313
David Keitel89c17752013-06-28 14:52:48 -07004314 /* Get the btc-disabled property */
4315 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4316 "qcom,btc-disabled");
4317
David Keitel2586f0a2013-08-20 10:02:26 -07004318 ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
4319 "qcom,ext-ovp-present");
4320
David Keitel112ba9c2013-04-12 18:40:43 -07004321 /* Get the charging-disabled property */
4322 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4323 "qcom,charging-disabled");
4324
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004325 chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
4326 "qcom,ovp-monitor-en");
4327
David Keitel8b68d2d2013-05-14 23:36:51 -07004328 /* Get the duty-cycle-100p property */
4329 chip->duty_cycle_100p = of_property_read_bool(
4330 chip->spmi->dev.of_node,
4331 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07004332
David Keitel112ba9c2013-04-12 18:40:43 -07004333 /* Get the fake-batt-values property */
4334 chip->use_default_batt_values =
4335 of_property_read_bool(chip->spmi->dev.of_node,
4336 "qcom,use-default-batt-values");
4337
4338 /* Disable charging when faking battery values */
4339 if (chip->use_default_batt_values)
4340 chip->charging_disabled = true;
4341
Zhenhua Huangdc335512013-10-30 11:45:15 +08004342 chip->power_stage_workaround_enable =
4343 of_property_read_bool(chip->spmi->dev.of_node,
4344 "qcom,power-stage-reduced");
4345
Anirudh Ghayal42fc8a12013-10-21 17:42:54 -07004346 chip->ibat_calibration_enabled =
4347 of_property_read_bool(chip->spmi->dev.of_node,
4348 "qcom,ibat-calibration-enabled");
4349
David Keitel112ba9c2013-04-12 18:40:43 -07004350 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
4351 &(chip->thermal_levels));
4352
4353 if (chip->thermal_levels > sizeof(int)) {
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304354 chip->thermal_mitigation = devm_kzalloc(chip->dev,
David Keitel112ba9c2013-04-12 18:40:43 -07004355 chip->thermal_levels,
4356 GFP_KERNEL);
4357
4358 if (chip->thermal_mitigation == NULL) {
4359 pr_err("thermal mitigation kzalloc() failed.\n");
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304360 return -ENOMEM;
David Keitel112ba9c2013-04-12 18:40:43 -07004361 }
4362
4363 chip->thermal_levels /= sizeof(int);
4364 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
4365 "qcom,thermal-mitigation",
4366 chip->thermal_mitigation, chip->thermal_levels);
4367 if (rc) {
4368 pr_err("qcom,thermal-mitigation missing in dt\n");
4369 return rc;
4370 }
4371 }
4372
4373 return rc;
4374}
4375
David Keitel80668952012-07-27 14:25:49 -07004376static int __devinit
4377qpnp_charger_probe(struct spmi_device *spmi)
4378{
4379 u8 subtype;
4380 struct qpnp_chg_chip *chip;
4381 struct resource *resource;
4382 struct spmi_resource *spmi_resource;
4383 int rc = 0;
4384
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304385 chip = devm_kzalloc(&spmi->dev,
4386 sizeof(struct qpnp_chg_chip), GFP_KERNEL);
David Keitel80668952012-07-27 14:25:49 -07004387 if (chip == NULL) {
4388 pr_err("kzalloc() failed.\n");
4389 return -ENOMEM;
4390 }
4391
David Keitelfd305ee2013-07-19 20:19:06 -07004392 chip->prev_usb_max_ma = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07004393 chip->dev = &(spmi->dev);
4394 chip->spmi = spmi;
4395
4396 chip->usb_psy = power_supply_get_by_name("usb");
4397 if (!chip->usb_psy) {
4398 pr_err("usb supply not found deferring probe\n");
4399 rc = -EPROBE_DEFER;
4400 goto fail_chg_enable;
4401 }
4402
David Keitelec3c09802013-06-13 13:05:30 -07004403 mutex_init(&chip->jeita_configure_lock);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004404 spin_lock_init(&chip->usbin_health_monitor_lock);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004405 alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
4406 qpnp_chg_reduce_power_stage_callback);
4407 INIT_WORK(&chip->reduce_power_stage_work,
4408 qpnp_chg_reduce_power_stage_work);
David Keitel6e63bd52013-09-06 18:00:03 -07004409 mutex_init(&chip->batfet_vreg_lock);
4410 INIT_WORK(&chip->batfet_lcl_work,
4411 qpnp_chg_batfet_lcl_work);
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004412 INIT_WORK(&chip->insertion_ocv_work,
4413 qpnp_chg_insertion_ocv_work);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004414
David Keitel112ba9c2013-04-12 18:40:43 -07004415 /* Get all device tree properties */
4416 rc = qpnp_charger_read_dt_props(chip);
4417 if (rc)
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304418 return rc;
David Keitel3dd5e0f2012-12-12 18:12:36 -08004419
Xiaozhe Shica289e02013-06-19 13:24:51 -07004420 /*
4421 * Check if bat_if is set in DT and make sure VADC is present
4422 * Also try loading the battery data profile if bat_if exists
4423 */
David Keiteldd87a172013-05-29 17:05:43 -07004424 spmi_for_each_container_dev(spmi_resource, spmi) {
4425 if (!spmi_resource) {
4426 pr_err("qpnp_chg: spmi resource absent\n");
4427 rc = -ENXIO;
4428 goto fail_chg_enable;
4429 }
4430
4431 resource = spmi_get_resource(spmi, spmi_resource,
4432 IORESOURCE_MEM, 0);
4433 if (!(resource && resource->start)) {
4434 pr_err("node %s IO resource absent!\n",
4435 spmi->dev.of_node->full_name);
4436 rc = -ENXIO;
4437 goto fail_chg_enable;
4438 }
4439
4440 rc = qpnp_chg_read(chip, &subtype,
4441 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4442 if (rc) {
4443 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4444 goto fail_chg_enable;
4445 }
4446
4447 if (subtype == SMBB_BAT_IF_SUBTYPE ||
4448 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004449 subtype == SMBCL_BAT_IF_SUBTYPE) {
4450 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
4451 if (IS_ERR(chip->vadc_dev)) {
4452 rc = PTR_ERR(chip->vadc_dev);
4453 if (rc != -EPROBE_DEFER)
4454 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07004455 goto fail_chg_enable;
David Keitel42648fd2013-08-16 17:45:20 -07004456 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004457
Abhijeet Dharmapurikar2d81b262013-11-14 19:15:05 -08004458 if (subtype == SMBB_BAT_IF_SUBTYPE) {
4459 chip->iadc_dev = qpnp_get_iadc(chip->dev,
4460 "chg");
4461 if (IS_ERR(chip->iadc_dev)) {
4462 rc = PTR_ERR(chip->iadc_dev);
4463 if (rc != -EPROBE_DEFER)
4464 pr_err("iadc property missing\n");
4465 goto fail_chg_enable;
4466 }
4467 }
4468
Xiaozhe Shica289e02013-06-19 13:24:51 -07004469 rc = qpnp_chg_load_battery_data(chip);
4470 if (rc)
4471 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07004472 }
4473 }
4474
David Keitel80668952012-07-27 14:25:49 -07004475 spmi_for_each_container_dev(spmi_resource, spmi) {
4476 if (!spmi_resource) {
4477 pr_err("qpnp_chg: spmi resource absent\n");
4478 rc = -ENXIO;
4479 goto fail_chg_enable;
4480 }
4481
4482 resource = spmi_get_resource(spmi, spmi_resource,
4483 IORESOURCE_MEM, 0);
4484 if (!(resource && resource->start)) {
4485 pr_err("node %s IO resource absent!\n",
4486 spmi->dev.of_node->full_name);
4487 rc = -ENXIO;
4488 goto fail_chg_enable;
4489 }
4490
4491 rc = qpnp_chg_read(chip, &subtype,
4492 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4493 if (rc) {
4494 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4495 goto fail_chg_enable;
4496 }
4497
4498 switch (subtype) {
4499 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004500 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004501 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004502 chip->chgr_base = resource->start;
4503 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4504 if (rc) {
4505 pr_err("Failed to init subtype 0x%x rc=%d\n",
4506 subtype, rc);
4507 goto fail_chg_enable;
4508 }
4509 break;
4510 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004511 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004512 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004513 chip->buck_base = resource->start;
4514 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4515 if (rc) {
4516 pr_err("Failed to init subtype 0x%x rc=%d\n",
4517 subtype, rc);
4518 goto fail_chg_enable;
4519 }
David Keitel344c6972013-04-09 19:28:21 -07004520
4521 rc = qpnp_chg_masked_write(chip,
4522 chip->buck_base + SEC_ACCESS,
4523 0xFF,
4524 0xA5, 1);
4525
4526 rc = qpnp_chg_masked_write(chip,
4527 chip->buck_base + BUCK_VCHG_OV,
4528 0xff,
4529 0x00, 1);
4530
David Keiteldbc949b2013-07-11 10:56:03 -07004531 if (chip->duty_cycle_100p) {
4532 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
4533 1);
4534 if (rc) {
4535 pr_err("failed to set duty cycle %d\n",
4536 rc);
4537 goto fail_chg_enable;
4538 }
4539 }
4540
David Keitel80668952012-07-27 14:25:49 -07004541 break;
4542 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004543 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004544 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004545 chip->bat_if_base = resource->start;
4546 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4547 if (rc) {
4548 pr_err("Failed to init subtype 0x%x rc=%d\n",
4549 subtype, rc);
4550 goto fail_chg_enable;
4551 }
4552 break;
4553 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004554 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004555 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004556 chip->usb_chgpth_base = resource->start;
4557 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4558 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07004559 if (rc != -EPROBE_DEFER)
4560 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07004561 subtype, rc);
4562 goto fail_chg_enable;
4563 }
4564 break;
4565 case SMBB_DC_CHGPTH_SUBTYPE:
4566 chip->dc_chgpth_base = resource->start;
4567 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4568 if (rc) {
4569 pr_err("Failed to init subtype 0x%x rc=%d\n",
4570 subtype, rc);
4571 goto fail_chg_enable;
4572 }
4573 break;
4574 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004575 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004576 chip->boost_base = resource->start;
4577 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4578 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07004579 if (rc != -EPROBE_DEFER)
4580 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07004581 subtype, rc);
4582 goto fail_chg_enable;
4583 }
4584 break;
4585 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004586 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004587 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004588 chip->misc_base = resource->start;
4589 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4590 if (rc) {
4591 pr_err("Failed to init subtype=0x%x rc=%d\n",
4592 subtype, rc);
4593 goto fail_chg_enable;
4594 }
4595 break;
4596 default:
4597 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
4598 rc = -EINVAL;
4599 goto fail_chg_enable;
4600 }
4601 }
4602 dev_set_drvdata(&spmi->dev, chip);
4603 device_init_wakeup(&spmi->dev, 1);
4604
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004605 chip->insertion_ocv_uv = -EINVAL;
4606 chip->batt_present = qpnp_chg_is_batt_present(chip);
David Keitelf2170cc2013-02-20 17:49:03 -08004607 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08004608 chip->batt_psy.name = "battery";
4609 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
4610 chip->batt_psy.properties = msm_batt_power_props;
4611 chip->batt_psy.num_properties =
4612 ARRAY_SIZE(msm_batt_power_props);
4613 chip->batt_psy.get_property = qpnp_batt_power_get_property;
4614 chip->batt_psy.set_property = qpnp_batt_power_set_property;
4615 chip->batt_psy.property_is_writeable =
4616 qpnp_batt_property_is_writeable;
4617 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07004618 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07004619 chip->batt_psy.supplied_to = pm_batt_supplied_to;
4620 chip->batt_psy.num_supplicants =
4621 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07004622
David Keitelf2170cc2013-02-20 17:49:03 -08004623 rc = power_supply_register(chip->dev, &chip->batt_psy);
4624 if (rc < 0) {
4625 pr_err("batt failed to register rc = %d\n", rc);
4626 goto fail_chg_enable;
4627 }
David Keitel79f4c932013-04-03 16:08:39 -07004628 INIT_WORK(&chip->adc_measure_work,
4629 qpnp_bat_if_adc_measure_work);
David Keitelaa375562013-08-08 09:43:28 -07004630 INIT_WORK(&chip->adc_disable_work,
David Keitelecab15a2013-08-06 15:41:39 -07004631 qpnp_bat_if_adc_disable_work);
David Keitelc7093b02013-02-14 12:50:04 -08004632 }
4633
David Keitel9fd07382013-05-02 15:37:44 -07004634 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07004635 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004636 INIT_DELAYED_WORK(&chip->usbin_health_check,
4637 qpnp_usbin_health_check_work);
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004638 INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
David Keitel7ac385e2013-08-19 18:02:40 -07004639 INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
David Keitel5910eea2013-05-02 15:32:25 -07004640
David Keitelf2170cc2013-02-20 17:49:03 -08004641 if (chip->dc_chgpth_base) {
4642 chip->dc_psy.name = "qpnp-dc";
4643 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
4644 chip->dc_psy.supplied_to = pm_power_supplied_to;
4645 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
4646 chip->dc_psy.properties = pm_power_props_mains;
4647 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
4648 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07004649 chip->dc_psy.set_property = qpnp_dc_power_set_property;
4650 chip->dc_psy.property_is_writeable =
4651 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08004652
4653 rc = power_supply_register(chip->dev, &chip->dc_psy);
4654 if (rc < 0) {
4655 pr_err("power_supply_register dc failed rc=%d\n", rc);
4656 goto unregister_batt;
4657 }
David Keitel80668952012-07-27 14:25:49 -07004658 }
4659
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004660 /* Turn on appropriate workaround flags */
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004661 rc = qpnp_chg_setup_flags(chip);
4662 if (rc < 0) {
4663 pr_err("failed to setup flags rc=%d\n", rc);
4664 goto unregister_dc_psy;
4665 }
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004666
David Keitelf2170cc2013-02-20 17:49:03 -08004667 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08004668 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
4669 if (rc) {
4670 pr_err("Error setting idcmax property %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004671 goto unregister_dc_psy;
David Keitel22ed2232013-01-28 11:04:07 -08004672 }
4673 }
4674
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004675 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0aea18a2013-06-14 18:57:57 -07004676 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07004677 chip->adc_param.low_temp = chip->cool_bat_decidegc;
4678 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08004679 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
4680 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
4681 chip->adc_param.btm_ctx = chip;
4682 chip->adc_param.threshold_notification =
4683 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08004684 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07004685
4686 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004687 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
4688 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07004689 if (rc) {
4690 pr_err("request ADC error %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004691 goto unregister_dc_psy;
David Keitel0c1a4532013-03-21 16:39:06 -07004692 }
David Keitel454ee842013-03-08 16:19:11 -08004693 }
4694 }
David Keitel89c17752013-06-28 14:52:48 -07004695 rc = qpnp_chg_bat_if_configure_btc(chip);
4696 if (rc) {
4697 pr_err("failed to configure btc %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004698 goto unregister_dc_psy;
David Keitel89c17752013-06-28 14:52:48 -07004699 }
David Keitel454ee842013-03-08 16:19:11 -08004700
David Keitel03ee6b52012-10-22 12:25:19 -07004701 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08004702 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07004703 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07004704
David Keitel0f35be42013-04-16 11:10:40 -07004705 rc = qpnp_chg_request_irqs(chip);
4706 if (rc) {
4707 pr_err("failed to request interrupts %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004708 goto unregister_dc_psy;
David Keitel0f35be42013-04-16 11:10:40 -07004709 }
4710
David Keitelad980fc2013-07-30 18:12:02 -07004711 qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
4712 qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
David Keitel9fd07382013-05-02 15:37:44 -07004713 power_supply_set_present(chip->usb_psy,
4714 qpnp_chg_is_usb_chg_plugged_in(chip));
4715
David Keitel3c62b472013-05-06 15:38:11 -07004716 /* Set USB psy online to avoid userspace from shutting down if battery
4717 * capacity is at zero and no chargers online. */
4718 if (qpnp_chg_is_usb_chg_plugged_in(chip))
4719 power_supply_set_online(chip->usb_psy, 1);
4720
David Keitel7ac385e2013-08-19 18:02:40 -07004721 schedule_delayed_work(&chip->aicl_check_work,
4722 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel796882d2013-05-14 18:01:11 -07004723 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 -08004724 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07004725 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08004726 qpnp_chg_is_usb_chg_plugged_in(chip),
4727 qpnp_chg_is_dc_chg_plugged_in(chip),
4728 get_prop_batt_present(chip),
4729 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07004730 return 0;
4731
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004732unregister_dc_psy:
4733 if (chip->dc_chgpth_base)
4734 power_supply_unregister(&chip->dc_psy);
David Keitelc7093b02013-02-14 12:50:04 -08004735unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08004736 if (chip->bat_if_base)
4737 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07004738fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07004739 regulator_unregister(chip->otg_vreg.rdev);
4740 regulator_unregister(chip->boost_vreg.rdev);
David Keitel80668952012-07-27 14:25:49 -07004741 return rc;
4742}
4743
4744static int __devexit
4745qpnp_charger_remove(struct spmi_device *spmi)
4746{
4747 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004748 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07004749 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004750 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
4751 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07004752 }
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304753
4754 cancel_delayed_work_sync(&chip->aicl_check_work);
4755 power_supply_unregister(&chip->dc_psy);
4756 cancel_work_sync(&chip->soc_check_work);
4757 cancel_delayed_work_sync(&chip->usbin_health_check);
4758 cancel_delayed_work_sync(&chip->arb_stop_work);
David Keitel9fd07382013-05-02 15:37:44 -07004759 cancel_delayed_work_sync(&chip->eoc_work);
Prasad Sodagudidb7bf152013-10-25 16:05:16 +05304760 cancel_work_sync(&chip->adc_disable_work);
4761 cancel_work_sync(&chip->adc_measure_work);
4762 power_supply_unregister(&chip->batt_psy);
4763 cancel_work_sync(&chip->batfet_lcl_work);
4764 cancel_work_sync(&chip->insertion_ocv_work);
4765 cancel_work_sync(&chip->reduce_power_stage_work);
4766 alarm_cancel(&chip->reduce_power_stage_alarm);
4767
4768 mutex_destroy(&chip->batfet_vreg_lock);
4769 mutex_destroy(&chip->jeita_configure_lock);
David Keitel79f4c932013-04-03 16:08:39 -07004770
David Collinscbb12132013-05-28 10:47:28 -07004771 regulator_unregister(chip->otg_vreg.rdev);
4772 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07004773
David Keitel80668952012-07-27 14:25:49 -07004774 return 0;
4775}
4776
David Keitel85ae4342013-04-16 11:46:00 -07004777static int qpnp_chg_resume(struct device *dev)
4778{
4779 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
4780 int rc = 0;
4781
David Keitel39093572013-06-05 15:32:30 -07004782 if (chip->bat_if_base) {
4783 rc = qpnp_chg_masked_write(chip,
4784 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4785 VREF_BATT_THERM_FORCE_ON,
4786 VREF_BATT_THERM_FORCE_ON, 1);
4787 if (rc)
4788 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
4789 }
David Keitel85ae4342013-04-16 11:46:00 -07004790
4791 return rc;
4792}
4793
4794static int qpnp_chg_suspend(struct device *dev)
4795{
4796 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
4797 int rc = 0;
4798
David Keitel39093572013-06-05 15:32:30 -07004799 if (chip->bat_if_base) {
4800 rc = qpnp_chg_masked_write(chip,
4801 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4802 VREF_BATT_THERM_FORCE_ON,
4803 VREF_BAT_THM_ENABLED_FSM, 1);
4804 if (rc)
4805 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
4806 }
David Keitel85ae4342013-04-16 11:46:00 -07004807
4808 return rc;
4809}
4810
David Keitel723d5012013-05-03 13:17:27 -07004811static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07004812 .resume = qpnp_chg_resume,
4813 .suspend = qpnp_chg_suspend,
4814};
4815
David Keitel80668952012-07-27 14:25:49 -07004816static struct spmi_driver qpnp_charger_driver = {
4817 .probe = qpnp_charger_probe,
4818 .remove = __devexit_p(qpnp_charger_remove),
4819 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07004820 .name = QPNP_CHARGER_DEV_NAME,
4821 .owner = THIS_MODULE,
4822 .of_match_table = qpnp_charger_match_table,
4823 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07004824 },
4825};
4826
4827/**
4828 * qpnp_chg_init() - register spmi driver for qpnp-chg
4829 */
4830int __init
4831qpnp_chg_init(void)
4832{
4833 return spmi_driver_register(&qpnp_charger_driver);
4834}
4835module_init(qpnp_chg_init);
4836
4837static void __exit
4838qpnp_chg_exit(void)
4839{
4840 spmi_driver_unregister(&qpnp_charger_driver);
4841}
4842module_exit(qpnp_chg_exit);
4843
4844
4845MODULE_DESCRIPTION("QPNP charger driver");
4846MODULE_LICENSE("GPL v2");
4847MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);