blob: a65ac5bfea262b9b845b24054e4cc97bd0de6e86 [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
David Keiteld681cda2012-10-02 15:44:21 -0700104#define SEC_ACCESS 0xD0
David Keitel85ae4342013-04-16 11:46:00 -0700105#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
David Keitel796882d2013-05-14 18:01:11 -0700106#define BAT_IF_BPD_CTRL 0x48
David Keitel6dc4ed42013-05-17 11:08:58 -0700107#define BOOST_VSET 0x41
108#define BOOST_ENABLE_CONTROL 0x46
David Keitel33f58952013-05-20 16:17:36 -0700109#define COMP_OVR1 0xEA
David Keitel89c17752013-06-28 14:52:48 -0700110#define BAT_IF_BTC_CTRL 0x49
David Keitel0b62bdd2013-07-10 17:30:51 -0700111#define USB_OCP_THR 0x52
112#define USB_OCP_CLR 0x53
Zhenhua Huang2a0ee352013-07-23 01:55:43 +0800113#define BAT_IF_TEMP_STATUS 0x09
David Keitel33f58952013-05-20 16:17:36 -0700114
David Keitel80668952012-07-27 14:25:49 -0700115#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700116
David Keitelf2170cc2013-02-20 17:49:03 -0800117/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700118#define SMBB_CHGR_SUBTYPE 0x01
119#define SMBB_BUCK_SUBTYPE 0x02
120#define SMBB_BAT_IF_SUBTYPE 0x03
121#define SMBB_USB_CHGPTH_SUBTYPE 0x04
122#define SMBB_DC_CHGPTH_SUBTYPE 0x05
123#define SMBB_BOOST_SUBTYPE 0x06
124#define SMBB_MISC_SUBTYPE 0x07
125
David Keitelf2170cc2013-02-20 17:49:03 -0800126/* SMBB peripheral subtype values */
127#define SMBBP_CHGR_SUBTYPE 0x31
128#define SMBBP_BUCK_SUBTYPE 0x32
129#define SMBBP_BAT_IF_SUBTYPE 0x33
130#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
131#define SMBBP_BOOST_SUBTYPE 0x36
132#define SMBBP_MISC_SUBTYPE 0x37
133
David Keitel46c9f7b2013-04-02 19:54:12 -0700134/* SMBCL peripheral subtype values */
135#define SMBCL_CHGR_SUBTYPE 0x41
136#define SMBCL_BUCK_SUBTYPE 0x42
137#define SMBCL_BAT_IF_SUBTYPE 0x43
138#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
139#define SMBCL_MISC_SUBTYPE 0x47
140
David Keitel80668952012-07-27 14:25:49 -0700141#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
142
David Keitelb80eda82012-10-15 10:49:11 -0700143/* Status bits and masks */
144#define CHGR_BOOT_DONE BIT(7)
145#define CHGR_CHG_EN BIT(7)
146#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800147#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800148#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700149#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700150#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700151#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700152#define REV_BST_DETECTED BIT(0)
153#define BAT_THM_EN BIT(1)
154#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700155#define BOOST_PWR_EN BIT(7)
David Keitel0b62bdd2013-07-10 17:30:51 -0700156#define OCP_CLR_BIT BIT(7)
157#define OCP_THR_MASK 0x03
158#define OCP_THR_900_MA 0x02
159#define OCP_THR_500_MA 0x01
160#define OCP_THR_200_MA 0x00
David Keitelb80eda82012-10-15 10:49:11 -0700161
David Keitel80668952012-07-27 14:25:49 -0700162/* Interrupt definitions */
163/* smbb_chg_interrupts */
164#define CHG_DONE_IRQ BIT(7)
165#define CHG_FAILED_IRQ BIT(6)
166#define FAST_CHG_ON_IRQ BIT(5)
167#define TRKL_CHG_ON_IRQ BIT(4)
168#define STATE_CHANGE_ON_IR BIT(3)
169#define CHGWDDOG_IRQ BIT(2)
170#define VBAT_DET_HI_IRQ BIT(1)
171#define VBAT_DET_LOW_IRQ BIT(0)
172
173/* smbb_buck_interrupts */
174#define VDD_LOOP_IRQ BIT(6)
175#define IBAT_LOOP_IRQ BIT(5)
176#define ICHG_LOOP_IRQ BIT(4)
177#define VCHG_LOOP_IRQ BIT(3)
178#define OVERTEMP_IRQ BIT(2)
179#define VREF_OV_IRQ BIT(1)
180#define VBAT_OV_IRQ BIT(0)
181
182/* smbb_bat_if_interrupts */
183#define PSI_IRQ BIT(4)
184#define VCP_ON_IRQ BIT(3)
185#define BAT_FET_ON_IRQ BIT(2)
186#define BAT_TEMP_OK_IRQ BIT(1)
187#define BATT_PRES_IRQ BIT(0)
188
189/* smbb_usb_interrupts */
190#define CHG_GONE_IRQ BIT(2)
191#define USBIN_VALID_IRQ BIT(1)
192#define COARSE_DET_USB_IRQ BIT(0)
193
194/* smbb_dc_interrupts */
195#define DCIN_VALID_IRQ BIT(1)
196#define COARSE_DET_DC_IRQ BIT(0)
197
198/* smbb_boost_interrupts */
199#define LIMIT_ERROR_IRQ BIT(1)
200#define BOOST_PWR_OK_IRQ BIT(0)
201
202/* smbb_misc_interrupts */
203#define TFTWDOG_IRQ BIT(0)
204
David Keitelfe51cb92013-04-02 19:42:58 -0700205/* SMBB types */
206#define SMBB BIT(1)
207#define SMBBP BIT(2)
208#define SMBCL BIT(3)
209
David Keiteld681cda2012-10-02 15:44:21 -0700210/* Workaround flags */
211#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700212#define BOOST_FLASH_WA BIT(1)
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700213#define POWER_STAGE_WA BIT(2)
David Keiteld681cda2012-10-02 15:44:21 -0700214
David Keitel47185a62013-05-15 18:54:10 -0700215struct qpnp_chg_irq {
David Keitel9879e2a2013-06-28 18:40:22 -0700216 int irq;
David Keitel47185a62013-05-15 18:54:10 -0700217 unsigned long disabled;
218};
219
David Keitel6dc4ed42013-05-17 11:08:58 -0700220struct qpnp_chg_regulator {
221 struct regulator_desc rdesc;
222 struct regulator_dev *rdev;
223};
224
David Keitel80668952012-07-27 14:25:49 -0700225/**
226 * struct qpnp_chg_chip - device information
227 * @dev: device pointer to access the parent
228 * @spmi: spmi pointer to access spmi information
229 * @chgr_base: charger peripheral base address
230 * @buck_base: buck peripheral base address
231 * @bat_if_base: battery interface peripheral base address
232 * @usb_chgpth_base: USB charge path peripheral base address
233 * @dc_chgpth_base: DC charge path peripheral base address
234 * @boost_base: boost peripheral base address
235 * @misc_base: misc peripheral base address
236 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800237 * @bat_is_cool: indicates that battery is cool
238 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700239 * @chg_done: indicates that charging is completed
240 * @usb_present: present status of usb
241 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800242 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800243 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700244 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700245 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800246 * @min_voltage_mv: min battery voltage before turning the FET on
Prasad Sodagudic3678012013-09-23 12:01:19 +0530247 * @batt_weak_voltage_mv: Weak battery voltage threshold
David Keitel454ee842013-03-08 16:19:11 -0800248 * @max_bat_chg_current: maximum battery charge current in mA
249 * @warm_bat_chg_ma: warm battery maximum charge current in mA
250 * @cool_bat_chg_ma: cool battery maximum charge current in mA
251 * @warm_bat_mv: warm temperature battery target voltage
252 * @cool_bat_mv: cool temperature battery target voltage
253 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700254 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800255 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800256 * @maxinput_usb_ma: Maximum Input current USB
257 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700258 * @hot_batt_p Hot battery threshold setting
259 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700260 * @warm_bat_decidegc Warm battery temperature in degree Celsius
261 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700262 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700263 * @type: SMBB type
264 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800265 * @thermal_levels amount of thermal mitigation levels
266 * @thermal_mitigation thermal mitigation level values
267 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700268 * @dc_psy power supply to export information to userspace
269 * @usb_psy power supply to export information to userspace
270 * @bms_psy power supply to export information to userspace
271 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700272 * @flags: flags to activate specific workarounds
273 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700274 *
275 */
276struct qpnp_chg_chip {
277 struct device *dev;
278 struct spmi_device *spmi;
279 u16 chgr_base;
280 u16 buck_base;
281 u16 bat_if_base;
282 u16 usb_chgpth_base;
283 u16 dc_chgpth_base;
284 u16 boost_base;
285 u16 misc_base;
286 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700287 struct qpnp_chg_irq usbin_valid;
David Keitel0b62bdd2013-07-10 17:30:51 -0700288 struct qpnp_chg_irq usb_ocp;
David Keitel47185a62013-05-15 18:54:10 -0700289 struct qpnp_chg_irq dcin_valid;
290 struct qpnp_chg_irq chg_gone;
291 struct qpnp_chg_irq chg_fastchg;
292 struct qpnp_chg_irq chg_trklchg;
293 struct qpnp_chg_irq chg_failed;
294 struct qpnp_chg_irq chg_vbatdet_lo;
295 struct qpnp_chg_irq batt_pres;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700296 struct qpnp_chg_irq batt_temp_ok;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800297 struct qpnp_chg_irq coarse_det_usb;
David Keitel454ee842013-03-08 16:19:11 -0800298 bool bat_is_cool;
299 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700300 bool chg_done;
David Keitel7ac385e2013-08-19 18:02:40 -0700301 bool charger_monitor_checked;
David Keitel80668952012-07-27 14:25:49 -0700302 bool usb_present;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800303 u8 usbin_health;
304 bool usb_coarse_det;
David Keitel80668952012-07-27 14:25:49 -0700305 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800306 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700307 bool charging_disabled;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800308 bool ovp_monitor_enable;
309 bool usb_valid_check_ovp;
David Keitel89c17752013-06-28 14:52:48 -0700310 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800311 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700312 bool duty_cycle_100p;
David Keitel796882d2013-05-14 18:01:11 -0700313 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700314 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800315 unsigned int warm_bat_chg_ma;
316 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700317 unsigned int safe_voltage_mv;
318 unsigned int max_voltage_mv;
319 unsigned int min_voltage_mv;
Prasad Sodagudic3678012013-09-23 12:01:19 +0530320 unsigned int batt_weak_voltage_mv;
David Keitelfd305ee2013-07-19 20:19:06 -0700321 int prev_usb_max_ma;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700322 int set_vddmax_mv;
323 int delta_vddmax_mv;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -0700324 u8 trim_center;
David Keitel454ee842013-03-08 16:19:11 -0800325 unsigned int warm_bat_mv;
326 unsigned int cool_bat_mv;
327 unsigned int resume_delta_mv;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700328 int insertion_ocv_uv;
David Keitel9fd07382013-05-02 15:37:44 -0700329 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700330 int soc_resume_limit;
331 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800332 unsigned int maxinput_usb_ma;
333 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700334 unsigned int hot_batt_p;
335 unsigned int cold_batt_p;
David Keitel27a97e62013-06-24 13:57:12 -0700336 int warm_bat_decidegc;
337 int cool_bat_decidegc;
David Keitel5d44fa52012-12-03 16:37:31 -0800338 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700339 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700340 unsigned int type;
341 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800342 unsigned int thermal_levels;
343 unsigned int therm_lvl_sel;
344 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700345 struct power_supply dc_psy;
346 struct power_supply *usb_psy;
347 struct power_supply *bms_psy;
348 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700349 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800350 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700351 struct work_struct adc_measure_work;
David Keitelecab15a2013-08-06 15:41:39 -0700352 struct work_struct adc_disable_work;
David Keitel344c6972013-04-09 19:28:21 -0700353 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700354 struct delayed_work eoc_work;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800355 struct delayed_work usbin_health_check;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -0700356 struct work_struct soc_check_work;
David Keitel7ac385e2013-08-19 18:02:40 -0700357 struct delayed_work aicl_check_work;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700358 struct work_struct insertion_ocv_work;
David Keitel6dc4ed42013-05-17 11:08:58 -0700359 struct qpnp_chg_regulator otg_vreg;
360 struct qpnp_chg_regulator boost_vreg;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -0700361 struct qpnp_chg_regulator batfet_vreg;
David Keitel6e63bd52013-09-06 18:00:03 -0700362 bool batfet_ext_en;
363 struct work_struct batfet_lcl_work;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700364 struct qpnp_vadc_chip *vadc_dev;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -0700365 struct qpnp_adc_tm_chip *adc_tm_dev;
David Keitelec3c09802013-06-13 13:05:30 -0700366 struct mutex jeita_configure_lock;
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800367 spinlock_t usbin_health_monitor_lock;
David Keitel6e63bd52013-09-06 18:00:03 -0700368 struct mutex batfet_vreg_lock;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700369 struct alarm reduce_power_stage_alarm;
370 struct work_struct reduce_power_stage_work;
371 bool power_stage_workaround_running;
David Keitel80668952012-07-27 14:25:49 -0700372};
373
David Keitel47185a62013-05-15 18:54:10 -0700374
David Keitel80668952012-07-27 14:25:49 -0700375static struct of_device_id qpnp_charger_match_table[] = {
376 { .compatible = QPNP_CHARGER_DEV_NAME, },
377 {}
378};
379
David Keitel0ef282b2013-05-29 16:04:57 -0700380enum bpd_type {
381 BPD_TYPE_BAT_ID,
382 BPD_TYPE_BAT_THM,
383 BPD_TYPE_BAT_THM_BAT_ID,
384};
David Keitel796882d2013-05-14 18:01:11 -0700385
David Keitel0ef282b2013-05-29 16:04:57 -0700386static const char * const bpd_label[] = {
387 [BPD_TYPE_BAT_ID] = "bpd_id",
388 [BPD_TYPE_BAT_THM] = "bpd_thm",
389 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700390};
391
David Keitel89c17752013-06-28 14:52:48 -0700392enum btc_type {
393 HOT_THD_25_PCT = 25,
394 HOT_THD_35_PCT = 35,
395 COLD_THD_70_PCT = 70,
396 COLD_THD_80_PCT = 80,
397};
398
399static u8 btc_value[] = {
400 [HOT_THD_25_PCT] = 0x0,
401 [HOT_THD_35_PCT] = BIT(0),
402 [COLD_THD_70_PCT] = 0x0,
403 [COLD_THD_80_PCT] = BIT(1),
404};
405
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800406enum usbin_health {
407 USBIN_UNKNOW,
408 USBIN_OK,
409 USBIN_OVP,
410};
411
412static inline int
David Keitel796882d2013-05-14 18:01:11 -0700413get_bpd(const char *name)
414{
415 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700416 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
417 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700418 return i;
419 }
420 return -EINVAL;
421}
422
David Keitel80668952012-07-27 14:25:49 -0700423static int
424qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
425 u16 base, int count)
426{
David Keitel39093572013-06-05 15:32:30 -0700427 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700428 struct spmi_device *spmi = chip->spmi;
429
David Keitel39093572013-06-05 15:32:30 -0700430 if (base == 0) {
431 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
432 base, spmi->sid, rc);
433 return -EINVAL;
434 }
435
436 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700437 if (rc) {
438 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
439 spmi->sid, rc);
440 return rc;
441 }
442 return 0;
443}
444
445static int
446qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
447 u16 base, int count)
448{
David Keitel39093572013-06-05 15:32:30 -0700449 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700450 struct spmi_device *spmi = chip->spmi;
451
David Keitel39093572013-06-05 15:32:30 -0700452 if (base == 0) {
453 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
454 base, spmi->sid, rc);
455 return -EINVAL;
456 }
457
458 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700459 if (rc) {
460 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
461 base, spmi->sid, rc);
462 return rc;
463 }
464
465 return 0;
466}
467
468static int
469qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
470 u8 mask, u8 val, int count)
471{
472 int rc;
473 u8 reg;
474
475 rc = qpnp_chg_read(chip, &reg, base, count);
476 if (rc) {
477 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
478 return rc;
479 }
480 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
481
482 reg &= ~mask;
483 reg |= val & mask;
484
485 pr_debug("Writing 0x%x\n", reg);
486
487 rc = qpnp_chg_write(chip, &reg, base, count);
488 if (rc) {
489 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
490 return rc;
491 }
492
493 return 0;
494}
495
David Keitel47185a62013-05-15 18:54:10 -0700496static void
497qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
498{
499 if (__test_and_clear_bit(0, &irq->disabled)) {
500 pr_debug("number = %d\n", irq->irq);
501 enable_irq(irq->irq);
502 }
503}
504
505static void
506qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
507{
508 if (!__test_and_set_bit(0, &irq->disabled)) {
509 pr_debug("number = %d\n", irq->irq);
510 disable_irq_nosync(irq->irq);
511 }
512}
513
David Keitel6f865cd2012-11-30 15:04:32 -0800514#define USB_OTG_EN_BIT BIT(0)
515static int
516qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
517{
518 u8 usb_otg_en;
519 int rc;
520
521 rc = qpnp_chg_read(chip, &usb_otg_en,
522 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
523 1);
524
525 if (rc) {
526 pr_err("spmi read failed: addr=%03X, rc=%d\n",
527 chip->usb_chgpth_base + CHGR_STATUS, rc);
528 return rc;
529 }
530 pr_debug("usb otg en 0x%x\n", usb_otg_en);
531
532 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
533}
534
David Keitel42ae0aa2013-03-08 16:20:10 -0800535static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700536qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
537{
538 u8 boost_en_ctl;
539 int rc;
540
541 rc = qpnp_chg_read(chip, &boost_en_ctl,
542 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
543 if (rc) {
544 pr_err("spmi read failed: addr=%03X, rc=%d\n",
545 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
546 return rc;
547 }
548
549 pr_debug("boost en 0x%x\n", boost_en_ctl);
550
551 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
552}
553
554static int
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700555qpnp_chg_is_batt_temp_ok(struct qpnp_chg_chip *chip)
556{
557 u8 batt_rt_sts;
558 int rc;
559
560 rc = qpnp_chg_read(chip, &batt_rt_sts,
561 INT_RT_STS(chip->bat_if_base), 1);
562 if (rc) {
563 pr_err("spmi read failed: addr=%03X, rc=%d\n",
564 INT_RT_STS(chip->bat_if_base), rc);
565 return rc;
566 }
567
568 return (batt_rt_sts & BAT_TEMP_OK_IRQ) ? 1 : 0;
569}
570
571static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800572qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
573{
574 u8 batt_pres_rt_sts;
575 int rc;
576
577 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
578 INT_RT_STS(chip->bat_if_base), 1);
579 if (rc) {
580 pr_err("spmi read failed: addr=%03X, rc=%d\n",
581 INT_RT_STS(chip->bat_if_base), rc);
582 return rc;
583 }
584
585 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
586}
587
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700588static int
589qpnp_chg_is_batfet_closed(struct qpnp_chg_chip *chip)
590{
591 u8 batfet_closed_rt_sts;
592 int rc;
593
594 rc = qpnp_chg_read(chip, &batfet_closed_rt_sts,
595 INT_RT_STS(chip->bat_if_base), 1);
596 if (rc) {
597 pr_err("spmi read failed: addr=%03X, rc=%d\n",
598 INT_RT_STS(chip->bat_if_base), rc);
599 return rc;
600 }
601
602 return (batfet_closed_rt_sts & BAT_FET_ON_IRQ) ? 1 : 0;
603}
604
David Keiteld681cda2012-10-02 15:44:21 -0700605#define USB_VALID_BIT BIT(7)
David Keitel80668952012-07-27 14:25:49 -0700606static int
607qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
608{
609 u8 usbin_valid_rt_sts;
610 int rc;
611
612 rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
David Keiteld681cda2012-10-02 15:44:21 -0700613 chip->usb_chgpth_base + CHGR_STATUS , 1);
David Keitel80668952012-07-27 14:25:49 -0700614
615 if (rc) {
616 pr_err("spmi read failed: addr=%03X, rc=%d\n",
David Keiteld681cda2012-10-02 15:44:21 -0700617 chip->usb_chgpth_base + CHGR_STATUS, rc);
David Keitel80668952012-07-27 14:25:49 -0700618 return rc;
619 }
620 pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
621
David Keiteld681cda2012-10-02 15:44:21 -0700622 return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700623}
624
Wu Fenglin04ae6de2013-09-09 19:15:06 +0800625#define USB_VALID_MASK 0xC0
626#define USB_COARSE_DET 0x10
627#define USB_VALID_UVP_VALUE 0x00
628#define USB_VALID_OVP_VALUE 0x40
629static int
630qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
631{
632 u8 usbin_chg_rt_sts;
633 int rc;
634 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
635 chip->usb_chgpth_base + CHGR_STATUS , 1);
636 if (rc) {
637 pr_err("spmi read failed: addr=%03X, rc=%d\n",
638 chip->usb_chgpth_base + CHGR_STATUS, rc);
639 return rc;
640 }
641 return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
642}
643
644static int
645qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
646{
647 u8 usbin_chg_rt_sts, usbin_health = 0;
648 int rc;
649
650 rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
651 chip->usb_chgpth_base + CHGR_STATUS , 1);
652
653 if (rc) {
654 pr_err("spmi read failed: addr=%03X, rc=%d\n",
655 chip->usb_chgpth_base + CHGR_STATUS, rc);
656 return rc;
657 }
658
659 pr_debug("chgr usb sts 0x%x\n", usbin_chg_rt_sts);
660 if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
661 if ((usbin_chg_rt_sts & USB_VALID_MASK)
662 == USB_VALID_OVP_VALUE) {
663 usbin_health = USBIN_OVP;
664 pr_err("Over voltage charger inserted\n");
665 } else if ((usbin_chg_rt_sts & USB_VALID_BIT) != 0) {
666 usbin_health = USBIN_OK;
667 pr_debug("Valid charger inserted\n");
668 }
669 } else {
670 usbin_health = USBIN_UNKNOW;
671 pr_debug("Charger plug out\n");
672 }
673
674 return usbin_health;
675}
676
David Keitel80668952012-07-27 14:25:49 -0700677static int
678qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
679{
680 u8 dcin_valid_rt_sts;
681 int rc;
682
David Keitelf2170cc2013-02-20 17:49:03 -0800683 if (!chip->dc_chgpth_base)
684 return 0;
685
David Keitel80668952012-07-27 14:25:49 -0700686 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
687 INT_RT_STS(chip->dc_chgpth_base), 1);
688 if (rc) {
689 pr_err("spmi read failed: addr=%03X, rc=%d\n",
690 INT_RT_STS(chip->dc_chgpth_base), rc);
691 return rc;
692 }
693
694 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
695}
696
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -0700697static int
698qpnp_chg_is_ichg_loop_active(struct qpnp_chg_chip *chip)
699{
700 u8 buck_sts;
701 int rc;
702
703 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
704
705 if (rc) {
706 pr_err("spmi read failed: addr=%03X, rc=%d\n",
707 INT_RT_STS(chip->buck_base), rc);
708 return rc;
709 }
710 pr_debug("buck usb sts 0x%x\n", buck_sts);
711
712 return (buck_sts & ICHG_LOOP_IRQ) ? 1 : 0;
713}
714
David Keitel22ed2232013-01-28 11:04:07 -0800715#define QPNP_CHG_I_MAX_MIN_100 100
716#define QPNP_CHG_I_MAX_MIN_150 150
717#define QPNP_CHG_I_MAX_MIN_MA 200
718#define QPNP_CHG_I_MAX_MAX_MA 2500
719#define QPNP_CHG_I_MAXSTEP_MA 100
720static int
721qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
722{
723 int rc = 0;
724 u8 dc = 0;
725
726 if (mA < QPNP_CHG_I_MAX_MIN_100
727 || mA > QPNP_CHG_I_MAX_MAX_MA) {
728 pr_err("bad mA=%d asked to set\n", mA);
729 return -EINVAL;
730 }
731
732 if (mA == QPNP_CHG_I_MAX_MIN_100) {
733 dc = 0x00;
734 pr_debug("current=%d setting %02x\n", mA, dc);
735 return qpnp_chg_write(chip, &dc,
736 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
737 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
738 dc = 0x01;
739 pr_debug("current=%d setting %02x\n", mA, dc);
740 return qpnp_chg_write(chip, &dc,
741 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
742 }
743
744 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
745
746 pr_debug("current=%d setting 0x%x\n", mA, dc);
747 rc = qpnp_chg_write(chip, &dc,
748 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
749
750 return rc;
751}
752
David Keitel80668952012-07-27 14:25:49 -0700753static int
David Keitel2586f0a2013-08-20 10:02:26 -0700754qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
755{
756 int rc = 0;
757 u8 trim_reg;
758
759 rc = qpnp_chg_read(chip, &trim_reg,
760 chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
761 if (rc) {
762 pr_err("failed to read USB_TRIM rc=%d\n", rc);
763 return 0;
764 }
765
766 return trim_reg;
767}
768
769static int
770qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
771{
772 int rc = 0;
773
774 rc = qpnp_chg_masked_write(chip,
775 chip->usb_chgpth_base + SEC_ACCESS,
776 0xFF,
777 0xA5, 1);
778 if (rc) {
779 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
780 return rc;
781 }
782
783 rc = qpnp_chg_masked_write(chip,
784 chip->usb_chgpth_base + CHGR_USB_TRIM,
785 0xFF,
786 trim, 1);
787 if (rc) {
788 pr_err("failed to write USB TRIM rc=%d\n", rc);
789 return rc;
790 }
791
792 return rc;
793}
794
795static int
David Keitel80668952012-07-27 14:25:49 -0700796qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
797{
David Keiteld681cda2012-10-02 15:44:21 -0700798 int rc = 0;
799 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700800
David Keitel22ed2232013-01-28 11:04:07 -0800801 if (mA < QPNP_CHG_I_MAX_MIN_100
802 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700803 pr_err("bad mA=%d asked to set\n", mA);
804 return -EINVAL;
805 }
806
David Keitel22ed2232013-01-28 11:04:07 -0800807 if (mA == QPNP_CHG_I_MAX_MIN_100) {
808 usb_reg = 0x00;
809 pr_debug("current=%d setting %02x\n", mA, usb_reg);
810 return qpnp_chg_write(chip, &usb_reg,
811 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
812 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
813 usb_reg = 0x01;
814 pr_debug("current=%d setting %02x\n", mA, usb_reg);
815 return qpnp_chg_write(chip, &usb_reg,
816 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
817 }
818
819 /* Impose input current limit */
820 if (chip->maxinput_usb_ma)
821 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
822
823 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -0700824
David Keiteld681cda2012-10-02 15:44:21 -0700825 if (chip->flags & CHG_FLAGS_VCP_WA) {
826 temp = 0xA5;
827 rc = qpnp_chg_write(chip, &temp,
828 chip->buck_base + SEC_ACCESS, 1);
829 rc = qpnp_chg_masked_write(chip,
830 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
831 0x0C, 0x0C, 1);
832 }
833
David Keitel80668952012-07-27 14:25:49 -0700834 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -0700835 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -0800836 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -0700837
838 if (chip->flags & CHG_FLAGS_VCP_WA) {
839 temp = 0xA5;
840 udelay(200);
841 rc = qpnp_chg_write(chip, &temp,
842 chip->buck_base + SEC_ACCESS, 1);
843 rc = qpnp_chg_masked_write(chip,
844 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
845 0x0C, 0x00, 1);
846 }
847
848 return rc;
849}
850
David Keitel337bd862013-07-15 21:42:58 -0700851#define QPNP_CHG_VINMIN_MIN_MV 4200
852#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
853#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
854#define QPNP_CHG_VINMIN_MAX_MV 9600
855#define QPNP_CHG_VINMIN_STEP_MV 50
856#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
Prasad Sodagudi95624b62013-09-26 16:40:59 +0530857#define QPNP_CHG_VINMIN_MASK 0x3F
David Keitel337bd862013-07-15 21:42:58 -0700858#define QPNP_CHG_VINMIN_MIN_VAL 0x10
859static int
860qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
861{
862 u8 temp;
863
864 if (voltage < QPNP_CHG_VINMIN_MIN_MV
865 || voltage > QPNP_CHG_VINMIN_MAX_MV) {
866 pr_err("bad mV=%d asked to set\n", voltage);
867 return -EINVAL;
868 }
869 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
870 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
David Keitel289fcf82013-10-24 11:33:00 -0700871 temp += (voltage - QPNP_CHG_VINMIN_HIGH_MIN_MV)
David Keitel337bd862013-07-15 21:42:58 -0700872 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
873 } else {
874 temp = QPNP_CHG_VINMIN_MIN_VAL;
875 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
876 / QPNP_CHG_VINMIN_STEP_MV;
877 }
878
879 pr_debug("voltage=%d setting %02x\n", voltage, temp);
880 return qpnp_chg_masked_write(chip,
881 chip->chgr_base + CHGR_VIN_MIN,
882 QPNP_CHG_VINMIN_MASK, temp, 1);
883}
884
885static int
886qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
887{
888 int rc, vin_min_mv;
889 u8 vin_min;
890
891 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
892 if (rc) {
893 pr_err("failed to read VIN_MIN rc=%d\n", rc);
894 return 0;
895 }
896
897 if (vin_min == 0)
898 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
David Keitel289fcf82013-10-24 11:33:00 -0700899 else if (vin_min >= QPNP_CHG_VINMIN_HIGH_MIN_VAL)
David Keitel337bd862013-07-15 21:42:58 -0700900 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
901 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
902 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
903 else
904 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
905 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
906 * QPNP_CHG_VINMIN_STEP_MV;
907 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
908
909 return vin_min_mv;
910}
911
Prasad Sodagudic3678012013-09-23 12:01:19 +0530912#define QPNP_CHG_VBATWEAK_MIN_MV 2100
913#define QPNP_CHG_VBATWEAK_MAX_MV 3600
914#define QPNP_CHG_VBATWEAK_STEP_MV 100
915static int
916qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
917{
918 u8 temp;
919
920 if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
921 || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
922 return -EINVAL;
923
924 temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
925 / QPNP_CHG_VBATWEAK_STEP_MV;
926
927 pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
928 return qpnp_chg_write(chip, &temp,
929 chip->chgr_base + CHGR_VBAT_WEAK, 1);
930}
931
David Keitel337bd862013-07-15 21:42:58 -0700932static int
933qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
934{
935 int rc, iusbmax_ma;
936 u8 iusbmax;
937
938 rc = qpnp_chg_read(chip, &iusbmax,
939 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
940 if (rc) {
941 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
942 return 0;
943 }
944
945 if (iusbmax == 0)
946 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
947 else if (iusbmax == 0x01)
948 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
949 else
950 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
951
952 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
953
954 return iusbmax_ma;
955}
956
David Keiteld681cda2012-10-02 15:44:21 -0700957#define USB_SUSPEND_BIT BIT(0)
958static int
959qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
960{
961 return qpnp_chg_masked_write(chip,
962 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
963 USB_SUSPEND_BIT,
964 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -0700965}
966
David Keitel344c6972013-04-09 19:28:21 -0700967static int
968qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
969{
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -0700970 if (chip->insertion_ocv_uv == 0 && enable) {
971 pr_debug("Battery not present, skipping\n");
972 return 0;
973 }
974 pr_debug("charging %s\n", enable ? "enabled" : "disabled");
David Keitel344c6972013-04-09 19:28:21 -0700975 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
976 CHGR_CHG_EN,
977 enable ? CHGR_CHG_EN : 0, 1);
978}
979
980static int
981qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
982{
983 /* Don't run on battery for batteryless hardware */
984 if (chip->use_default_batt_values)
985 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -0700986 /* Don't force on battery if battery is not present */
987 if (!qpnp_chg_is_batt_present(chip))
988 return 0;
David Keitel344c6972013-04-09 19:28:21 -0700989
990 /* This bit forces the charger to run off of the battery rather
991 * than a connected charger */
992 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
993 CHGR_ON_BAT_FORCE_BIT,
994 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
995}
996
David Keitel8b68d2d2013-05-14 23:36:51 -0700997#define BUCK_DUTY_MASK_100P 0x30
998static int
999qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
1000{
1001 int rc;
1002
1003 pr_debug("enable: %d\n", enable);
1004
1005 rc = qpnp_chg_masked_write(chip,
1006 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1007 if (rc) {
1008 pr_debug("failed to write sec access rc=%d\n", rc);
1009 return rc;
1010 }
1011
1012 rc = qpnp_chg_masked_write(chip,
1013 chip->buck_base + BUCK_TEST_SMBC_MODES,
1014 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
1015 if (rc) {
1016 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
1017 return rc;
1018 }
1019
1020 return rc;
1021}
1022
David Keitel9fd07382013-05-02 15:37:44 -07001023#define COMPATATOR_OVERRIDE_0 0x80
1024static int
1025qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
1026{
1027 int rc;
1028
1029 pr_debug("toggle: %d\n", enable);
1030
1031 rc = qpnp_chg_masked_write(chip,
1032 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
1033 if (rc) {
1034 pr_debug("failed to write sec access rc=%d\n", rc);
1035 return rc;
1036 }
1037
1038 rc = qpnp_chg_masked_write(chip,
1039 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
1040 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
1041 if (rc) {
1042 pr_debug("failed to toggle chg done override rc=%d\n", rc);
1043 return rc;
1044 }
1045
1046 return rc;
1047}
1048
1049#define QPNP_CHG_VBATDET_MIN_MV 3240
1050#define QPNP_CHG_VBATDET_MAX_MV 5780
1051#define QPNP_CHG_VBATDET_STEP_MV 20
1052static int
1053qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
1054{
1055 u8 temp;
1056
1057 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
1058 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
1059 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
1060 return -EINVAL;
1061 }
1062 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
1063 / QPNP_CHG_VBATDET_STEP_MV;
1064
1065 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
1066 return qpnp_chg_write(chip, &temp,
1067 chip->chgr_base + CHGR_VBAT_DET, 1);
1068}
1069
David Keitel344c6972013-04-09 19:28:21 -07001070static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001071qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
1072{
1073 if (chip->bat_is_cool)
1074 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
1075 - chip->resume_delta_mv);
1076 else if (chip->bat_is_warm)
1077 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
1078 - chip->resume_delta_mv);
1079 else if (chip->resuming_charging)
1080 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1081 + chip->resume_delta_mv);
1082 else
1083 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
1084 - chip->resume_delta_mv);
1085}
1086
1087static void
David Keitel344c6972013-04-09 19:28:21 -07001088qpnp_arb_stop_work(struct work_struct *work)
1089{
1090 struct delayed_work *dwork = to_delayed_work(work);
1091 struct qpnp_chg_chip *chip = container_of(dwork,
1092 struct qpnp_chg_chip, arb_stop_work);
1093
David Keitel9fd07382013-05-02 15:37:44 -07001094 if (!chip->chg_done)
1095 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -07001096 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1097}
1098
1099static void
1100qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -07001101{
1102 struct qpnp_chg_chip *chip = container_of(work,
1103 struct qpnp_chg_chip, adc_measure_work);
1104
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07001105 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -07001106 pr_err("request ADC error\n");
1107}
1108
David Keitelecab15a2013-08-06 15:41:39 -07001109static void
1110qpnp_bat_if_adc_disable_work(struct work_struct *work)
1111{
1112 struct qpnp_chg_chip *chip = container_of(work,
1113 struct qpnp_chg_chip, adc_disable_work);
1114
1115 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev, &chip->adc_param);
1116}
1117
David Keitel9fd07382013-05-02 15:37:44 -07001118#define EOC_CHECK_PERIOD_MS 10000
1119static irqreturn_t
1120qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
1121{
1122 struct qpnp_chg_chip *chip = _chip;
1123 u8 chg_sts = 0;
1124 int rc;
1125
1126 pr_debug("vbatdet-lo triggered\n");
1127
1128 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
1129 if (rc)
1130 pr_err("failed to read chg_sts rc=%d\n", rc);
1131
1132 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
1133 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
1134 schedule_delayed_work(&chip->eoc_work,
1135 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001136 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07001137 }
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001138 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07001139
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001140 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001141 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001142 if (chip->dc_chgpth_base) {
1143 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001144 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001145 }
1146 if (chip->bat_if_base) {
1147 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001148 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001149 }
David Keitel9fd07382013-05-02 15:37:44 -07001150 return IRQ_HANDLED;
1151}
1152
David Keitel344c6972013-04-09 19:28:21 -07001153#define ARB_STOP_WORK_MS 1000
1154static irqreturn_t
1155qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
1156{
1157 struct qpnp_chg_chip *chip = _chip;
1158
1159 pr_debug("chg_gone triggered\n");
1160 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
1161 qpnp_chg_charge_en(chip, 0);
David Keitel9fd07382013-05-02 15:37:44 -07001162 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001163 schedule_delayed_work(&chip->arb_stop_work,
1164 msecs_to_jiffies(ARB_STOP_WORK_MS));
1165 }
1166
1167 return IRQ_HANDLED;
1168}
1169
David Keitel0b62bdd2013-07-10 17:30:51 -07001170static irqreturn_t
1171qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
1172{
1173 struct qpnp_chg_chip *chip = _chip;
1174 int rc;
1175
1176 pr_debug("usb-ocp triggered\n");
1177
1178 rc = qpnp_chg_masked_write(chip,
1179 chip->usb_chgpth_base + USB_OCP_CLR,
1180 OCP_CLR_BIT,
1181 OCP_CLR_BIT, 1);
1182 if (rc)
1183 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1184
1185 /* force usb ovp fet off */
1186 rc = qpnp_chg_masked_write(chip,
1187 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1188 USB_OTG_EN_BIT,
1189 USB_OTG_EN_BIT, 1);
1190 if (rc)
1191 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1192
1193 return IRQ_HANDLED;
1194}
1195
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001196#define QPNP_CHG_VDDMAX_MIN 3400
1197#define QPNP_CHG_V_MIN_MV 3240
1198#define QPNP_CHG_V_MAX_MV 4500
1199#define QPNP_CHG_V_STEP_MV 10
1200#define QPNP_CHG_BUCK_TRIM1_STEP 10
1201#define QPNP_CHG_BUCK_VDD_TRIM_MASK 0xF0
1202static int
1203qpnp_chg_vddmax_and_trim_set(struct qpnp_chg_chip *chip,
1204 int voltage, int trim_mv)
1205{
1206 int rc, trim_set;
1207 u8 vddmax = 0, trim = 0;
1208
1209 if (voltage < QPNP_CHG_VDDMAX_MIN
1210 || voltage > QPNP_CHG_V_MAX_MV) {
1211 pr_err("bad mV=%d asked to set\n", voltage);
1212 return -EINVAL;
1213 }
1214
1215 vddmax = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1216 rc = qpnp_chg_write(chip, &vddmax, chip->chgr_base + CHGR_VDD_MAX, 1);
1217 if (rc) {
1218 pr_err("Failed to write vddmax: %d\n", rc);
1219 return rc;
1220 }
1221
1222 rc = qpnp_chg_masked_write(chip,
1223 chip->buck_base + SEC_ACCESS,
1224 0xFF,
1225 0xA5, 1);
1226 if (rc) {
1227 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1228 return rc;
1229 }
1230 trim_set = clamp((int)chip->trim_center
1231 + (trim_mv / QPNP_CHG_BUCK_TRIM1_STEP),
1232 0, 0xF);
1233 trim = (u8)trim_set << 4;
1234 rc = qpnp_chg_masked_write(chip,
1235 chip->buck_base + BUCK_CTRL_TRIM1,
1236 QPNP_CHG_BUCK_VDD_TRIM_MASK,
1237 trim, 1);
1238 if (rc) {
1239 pr_err("Failed to write buck trim1: %d\n", rc);
1240 return rc;
1241 }
1242 pr_debug("voltage=%d+%d setting vddmax: %02x, trim: %02x\n",
1243 voltage, trim_mv, vddmax, trim);
1244 return 0;
1245}
1246
1247/* JEITA compliance logic */
1248static void
1249qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1250{
1251 if (chip->bat_is_cool)
1252 qpnp_chg_vddmax_and_trim_set(chip, chip->cool_bat_mv,
1253 chip->delta_vddmax_mv);
1254 else if (chip->bat_is_warm)
1255 qpnp_chg_vddmax_and_trim_set(chip, chip->warm_bat_mv,
1256 chip->delta_vddmax_mv);
1257 else
1258 qpnp_chg_vddmax_and_trim_set(chip, chip->max_voltage_mv,
1259 chip->delta_vddmax_mv);
1260}
1261
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001262static void
1263qpnp_usbin_health_check_work(struct work_struct *work)
1264{
1265 int usbin_health = 0;
1266 u8 psy_health_sts = 0;
1267 struct delayed_work *dwork = to_delayed_work(work);
1268 struct qpnp_chg_chip *chip = container_of(dwork,
1269 struct qpnp_chg_chip, usbin_health_check);
1270
1271 usbin_health = qpnp_chg_check_usbin_health(chip);
1272 spin_lock(&chip->usbin_health_monitor_lock);
1273 if (chip->usbin_health != usbin_health) {
1274 pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
1275 chip->usbin_health, usbin_health);
1276 chip->usbin_health = usbin_health;
1277 if (usbin_health == USBIN_OVP)
1278 psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1279 else if (usbin_health == USBIN_OK)
1280 psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
1281 power_supply_set_health_state(chip->usb_psy, psy_health_sts);
1282 power_supply_changed(chip->usb_psy);
1283 }
1284 /* enable OVP monitor in usb valid after coarse-det complete */
1285 chip->usb_valid_check_ovp = true;
1286 spin_unlock(&chip->usbin_health_monitor_lock);
1287 return;
1288}
1289
1290#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
1291#define USB_DEB_BYPASS 0x0
1292#define USB_DEB_5MS 0x1
1293#define USB_DEB_10MS 0x2
1294#define USB_DEB_20MS 0x3
1295static irqreturn_t
1296qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
1297{
1298 struct qpnp_chg_chip *chip = _chip;
1299 int host_mode, rc = 0;
1300 int debounce[] = {
1301 [USB_DEB_BYPASS] = 0,
1302 [USB_DEB_5MS] = 5,
1303 [USB_DEB_10MS] = 10,
1304 [USB_DEB_20MS] = 20 };
1305 u8 ovp_ctl;
1306 bool usb_coarse_det;
1307
1308 host_mode = qpnp_chg_is_otg_en_set(chip);
1309 usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
1310 pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
1311 usb_coarse_det, host_mode);
1312
1313 if (host_mode)
1314 return IRQ_HANDLED;
1315 /* ignore to monitor OVP in usbin valid irq handler
1316 if the coarse-det fired first, do the OVP state monitor
1317 in the usbin_health_check work, and after the work,
1318 enable monitor OVP in usbin valid irq handler */
1319 chip->usb_valid_check_ovp = false;
1320 if (chip->usb_coarse_det ^ usb_coarse_det) {
1321 chip->usb_coarse_det = usb_coarse_det;
1322 if (usb_coarse_det) {
1323 /* usb coarse-det rising edge, check the usbin_valid
1324 debounce time setting, and start a delay work to
1325 check the OVP status*/
1326 rc = qpnp_chg_read(chip, &ovp_ctl,
1327 chip->usb_chgpth_base + USB_OVP_CTL, 1);
1328
1329 if (rc) {
1330 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1331 chip->usb_chgpth_base + USB_OVP_CTL,
1332 rc);
1333 return rc;
1334 }
1335 ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
1336 schedule_delayed_work(&chip->usbin_health_check,
1337 msecs_to_jiffies(debounce[ovp_ctl]));
1338 } else {
1339 /* usb coarse-det rising edge, set the usb psy health
1340 status to unknown */
1341 pr_debug("usb coarse det clear, set usb health to unknown\n");
1342 chip->usbin_health = USBIN_UNKNOW;
1343 power_supply_set_health_state(chip->usb_psy,
1344 POWER_SUPPLY_HEALTH_UNKNOWN);
1345 power_supply_changed(chip->usb_psy);
1346 }
1347
1348 }
1349 return IRQ_HANDLED;
1350}
1351
David Keitel6e63bd52013-09-06 18:00:03 -07001352#define BATFET_LPM_MASK 0xC0
1353#define BATFET_LPM 0x40
1354#define BATFET_NO_LPM 0x00
1355static int
1356qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
1357{
1358 int rc = 0;
1359
David Keitelcadbc282013-09-26 11:39:14 -07001360 if (chip->charging_disabled || !chip->bat_if_base)
1361 return rc;
1362
David Keitel6e63bd52013-09-06 18:00:03 -07001363 if (chip->type == SMBB)
1364 rc = qpnp_chg_masked_write(chip,
1365 chip->bat_if_base + CHGR_BAT_IF_SPARE,
1366 BATFET_LPM_MASK,
1367 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1368 else
1369 rc = qpnp_chg_masked_write(chip,
1370 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
1371 BATFET_LPM_MASK,
1372 enable ? BATFET_NO_LPM : BATFET_LPM, 1);
1373
1374 return rc;
1375}
1376
David Keitel80668952012-07-27 14:25:49 -07001377#define ENUM_T_STOP_BIT BIT(0)
1378static irqreturn_t
1379qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1380{
1381 struct qpnp_chg_chip *chip = _chip;
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001382 int usb_present, host_mode, usbin_health;
1383 u8 psy_health_sts;
David Keitel80668952012-07-27 14:25:49 -07001384
1385 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001386 host_mode = qpnp_chg_is_otg_en_set(chip);
1387 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1388 usb_present, host_mode);
1389
1390 /* In host mode notifications cmoe from USB supply */
1391 if (host_mode)
1392 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001393
1394 if (chip->usb_present ^ usb_present) {
1395 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001396 if (!usb_present) {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001397 /* when a valid charger inserted, and increase the
1398 * charger voltage to OVP threshold, then
1399 * usb_in_valid falling edge interrupt triggers.
1400 * So we handle the OVP monitor here, and ignore
1401 * other health state changes */
1402 if (chip->ovp_monitor_enable &&
1403 (chip->usb_valid_check_ovp)) {
1404 usbin_health =
1405 qpnp_chg_check_usbin_health(chip);
1406 if (chip->usbin_health != usbin_health) {
1407 chip->usbin_health = usbin_health;
1408 if (usbin_health == USBIN_OVP)
1409 psy_health_sts =
1410 POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1411 power_supply_set_health_state(
1412 chip->usb_psy,
1413 psy_health_sts);
1414 power_supply_changed(chip->usb_psy);
1415 }
1416 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001417 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1418 chip->delta_vddmax_mv = 0;
1419 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel6e63bd52013-09-06 18:00:03 -07001420 chip->chg_done = false;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001421 }
David Keitel344c6972013-04-09 19:28:21 -07001422 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitelfd305ee2013-07-19 20:19:06 -07001423 chip->prev_usb_max_ma = -EINVAL;
David Keitel9fd07382013-05-02 15:37:44 -07001424 } else {
Wu Fenglin04ae6de2013-09-09 19:15:06 +08001425 /* when OVP clamped usbin, and then decrease
1426 * the charger voltage to lower than the OVP
1427 * threshold, a usbin_valid rising edge
1428 * interrupt triggered. So we change the usb
1429 * psy health state back to good */
1430 if (chip->ovp_monitor_enable &&
1431 (chip->usb_valid_check_ovp)) {
1432 usbin_health =
1433 qpnp_chg_check_usbin_health(chip);
1434 if (chip->usbin_health != usbin_health) {
1435 chip->usbin_health = usbin_health;
1436 if (usbin_health == USBIN_OK)
1437 psy_health_sts =
1438 POWER_SUPPLY_HEALTH_GOOD;
1439 power_supply_set_health_state(
1440 chip->usb_psy,
1441 psy_health_sts);
1442 power_supply_changed(chip->usb_psy);
1443 }
1444 }
1445
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001446 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1447 chip->delta_vddmax_mv = 0;
1448 qpnp_chg_set_appropriate_vddmax(chip);
1449 }
David Keitel9fd07382013-05-02 15:37:44 -07001450 schedule_delayed_work(&chip->eoc_work,
1451 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001452 schedule_work(&chip->soc_check_work);
David Keitel9fd07382013-05-02 15:37:44 -07001453 }
David Keitel344c6972013-04-09 19:28:21 -07001454
David Keitel9fd07382013-05-02 15:37:44 -07001455 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel6e63bd52013-09-06 18:00:03 -07001456 schedule_work(&chip->batfet_lcl_work);
David Keitel80668952012-07-27 14:25:49 -07001457 }
1458
1459 return IRQ_HANDLED;
1460}
1461
David Keitel7450dcd2013-01-29 18:41:41 -08001462static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001463qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1464{
1465 struct qpnp_chg_chip *chip = _chip;
1466 int batt_temp_good;
1467
1468 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1469 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1470
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001471 pr_debug("psy changed batt_psy\n");
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001472 power_supply_changed(&chip->batt_psy);
1473 return IRQ_HANDLED;
1474}
1475
1476static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001477qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1478{
1479 struct qpnp_chg_chip *chip = _chip;
1480 int batt_present;
1481
1482 batt_present = qpnp_chg_is_batt_present(chip);
1483 pr_debug("batt-pres triggered: %d\n", batt_present);
1484
1485 if (chip->batt_present ^ batt_present) {
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001486 if (batt_present) {
1487 schedule_work(&chip->insertion_ocv_work);
1488 } else {
1489 chip->insertion_ocv_uv = 0;
1490 qpnp_chg_charge_en(chip, 0);
1491 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001492 chip->batt_present = batt_present;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001493 pr_debug("psy changed batt_psy\n");
David Keitel42ae0aa2013-03-08 16:20:10 -08001494 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001495 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001496 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001497
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001498 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07001499 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001500 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001501 schedule_work(&chip->adc_measure_work);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08001502 } else if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitelec3c09802013-06-13 13:05:30 -07001503 && !batt_present) {
David Keitelecab15a2013-08-06 15:41:39 -07001504 schedule_work(&chip->adc_disable_work);
David Keitelec3c09802013-06-13 13:05:30 -07001505 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001506 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001507 }
1508
1509 return IRQ_HANDLED;
1510}
1511
1512static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001513qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1514{
1515 struct qpnp_chg_chip *chip = _chip;
1516 int dc_present;
1517
1518 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1519 pr_debug("dcin-valid triggered: %d\n", dc_present);
1520
1521 if (chip->dc_present ^ dc_present) {
1522 chip->dc_present = dc_present;
David Keitel6d4b9da2013-09-05 17:38:40 -07001523 if (qpnp_chg_is_otg_en_set(chip))
1524 qpnp_chg_force_run_on_batt(chip, !dc_present ? 1 : 0);
David Keitel278f2c72013-08-13 18:00:45 -07001525 if (!dc_present && !qpnp_chg_is_usb_chg_plugged_in(chip)) {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001526 chip->delta_vddmax_mv = 0;
1527 qpnp_chg_set_appropriate_vddmax(chip);
David Keitel9fd07382013-05-02 15:37:44 -07001528 chip->chg_done = false;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001529 } else {
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07001530 if (!qpnp_chg_is_usb_chg_plugged_in(chip)) {
1531 chip->delta_vddmax_mv = 0;
1532 qpnp_chg_set_appropriate_vddmax(chip);
1533 }
David Keitel9fd07382013-05-02 15:37:44 -07001534 schedule_delayed_work(&chip->eoc_work,
1535 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07001536 schedule_work(&chip->soc_check_work);
1537 }
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001538 pr_debug("psy changed dc_psy\n");
David Keitel7450dcd2013-01-29 18:41:41 -08001539 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001540 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001541 power_supply_changed(&chip->batt_psy);
David Keitel6e63bd52013-09-06 18:00:03 -07001542 schedule_work(&chip->batfet_lcl_work);
David Keitel7450dcd2013-01-29 18:41:41 -08001543 }
1544
1545 return IRQ_HANDLED;
1546}
1547
David Keitel80668952012-07-27 14:25:49 -07001548#define CHGR_CHG_FAILED_BIT BIT(7)
1549static irqreturn_t
1550qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1551{
1552 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001553 int rc;
David Keitel80668952012-07-27 14:25:49 -07001554
David Keitel9fd07382013-05-02 15:37:44 -07001555 pr_debug("chg_failed triggered\n");
1556
David Keitel80668952012-07-27 14:25:49 -07001557 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001558 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001559 CHGR_CHG_FAILED_BIT,
1560 CHGR_CHG_FAILED_BIT, 1);
1561 if (rc)
1562 pr_err("Failed to write chg_fail clear bit!\n");
1563
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001564 if (chip->bat_if_base) {
1565 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001566 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001567 }
1568 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001569 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001570 if (chip->dc_chgpth_base) {
1571 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001572 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001573 }
David Keitel80668952012-07-27 14:25:49 -07001574 return IRQ_HANDLED;
1575}
1576
1577static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001578qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
1579{
1580 struct qpnp_chg_chip *chip = _chip;
1581
1582 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001583
1584 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001585 if (chip->bat_if_base) {
1586 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001587 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001588 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001589
1590 return IRQ_HANDLED;
1591}
1592
1593static irqreturn_t
1594qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
1595{
1596 struct qpnp_chg_chip *chip = _chip;
David Keitel337bd862013-07-15 21:42:58 -07001597 u8 chgr_sts;
1598 int rc;
1599
1600 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
1601 if (rc)
1602 pr_err("failed to read interrupt sts %d\n", rc);
David Keitel42ae0aa2013-03-08 16:20:10 -08001603
1604 pr_debug("FAST_CHG IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001605 chip->chg_done = false;
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001606 if (chip->bat_if_base) {
1607 pr_debug("psy changed batt_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001608 power_supply_changed(&chip->batt_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001609 }
1610
1611 pr_debug("psy changed usb_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07001612 power_supply_changed(chip->usb_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001613
1614 if (chip->dc_chgpth_base) {
1615 pr_debug("psy changed dc_psy\n");
David Keiteldbcef092013-05-14 14:48:30 -07001616 power_supply_changed(&chip->dc_psy);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07001617 }
1618
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001619 if (chip->resuming_charging) {
1620 chip->resuming_charging = false;
1621 qpnp_chg_set_appropriate_vbatdet(chip);
1622 }
David Keitel337bd862013-07-15 21:42:58 -07001623
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07001624 if (!chip->charging_disabled) {
1625 schedule_delayed_work(&chip->eoc_work,
1626 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
1627 pm_stay_awake(chip->dev);
1628 }
1629
David Keitel47185a62013-05-15 18:54:10 -07001630 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -08001631
1632 return IRQ_HANDLED;
1633}
1634
David Keitel03ee6b52012-10-22 12:25:19 -07001635static int
David Keitel432e1232013-06-05 16:10:18 -07001636qpnp_dc_property_is_writeable(struct power_supply *psy,
1637 enum power_supply_property psp)
1638{
1639 switch (psp) {
1640 case POWER_SUPPLY_PROP_CURRENT_MAX:
1641 return 1;
1642 default:
1643 break;
1644 }
1645
1646 return 0;
1647}
1648
1649static int
David Keitel03ee6b52012-10-22 12:25:19 -07001650qpnp_batt_property_is_writeable(struct power_supply *psy,
1651 enum power_supply_property psp)
1652{
1653 switch (psp) {
1654 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08001655 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07001656 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
David Keitel2586f0a2013-08-20 10:02:26 -07001657 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
David Keitel337bd862013-07-15 21:42:58 -07001658 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07001659 case POWER_SUPPLY_PROP_COOL_TEMP:
1660 case POWER_SUPPLY_PROP_WARM_TEMP:
David Keitel03ee6b52012-10-22 12:25:19 -07001661 return 1;
1662 default:
1663 break;
1664 }
1665
1666 return 0;
1667}
1668
David Keitel6f865cd2012-11-30 15:04:32 -08001669static int
David Keitelbe208252013-01-31 14:49:25 -08001670qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
1671{
1672 int rc;
1673
1674 if (chip->charging_disabled && enable) {
1675 pr_debug("Charging disabled\n");
1676 return 0;
1677 }
1678
1679 rc = qpnp_chg_charge_en(chip, enable);
1680 if (rc) {
1681 pr_err("Failed to control charging %d\n", rc);
1682 return rc;
1683 }
1684
1685 rc = qpnp_chg_force_run_on_batt(chip, !enable);
1686 if (rc)
1687 pr_err("Failed to control charging %d\n", rc);
1688
1689 return rc;
1690}
1691
David Keitel454ee842013-03-08 16:19:11 -08001692static int
1693switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001694{
1695 int rc;
1696
1697 pr_debug("switch to charge mode\n");
1698 if (!qpnp_chg_is_otg_en_set(chip))
1699 return 0;
1700
1701 /* enable usb ovp fet */
1702 rc = qpnp_chg_masked_write(chip,
1703 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1704 USB_OTG_EN_BIT,
1705 0, 1);
1706 if (rc) {
1707 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1708 return rc;
1709 }
1710
1711 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1712 if (rc) {
1713 pr_err("Failed re-enable charging rc = %d\n", rc);
1714 return rc;
1715 }
1716
1717 return 0;
1718}
1719
David Keitel454ee842013-03-08 16:19:11 -08001720static int
1721switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001722{
1723 int rc;
1724
1725 pr_debug("switch to host mode\n");
1726 if (qpnp_chg_is_otg_en_set(chip))
1727 return 0;
1728
David Keitel6d4b9da2013-09-05 17:38:40 -07001729 if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
1730 rc = qpnp_chg_force_run_on_batt(chip, 1);
1731 if (rc) {
1732 pr_err("Failed to disable charging rc = %d\n", rc);
1733 return rc;
1734 }
David Keitel6f865cd2012-11-30 15:04:32 -08001735 }
1736
1737 /* force usb ovp fet off */
1738 rc = qpnp_chg_masked_write(chip,
1739 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1740 USB_OTG_EN_BIT,
1741 USB_OTG_EN_BIT, 1);
1742 if (rc) {
1743 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1744 return rc;
1745 }
1746
1747 return 0;
1748}
1749
David Keitel80668952012-07-27 14:25:49 -07001750static enum power_supply_property pm_power_props_mains[] = {
1751 POWER_SUPPLY_PROP_PRESENT,
1752 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07001753 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07001754};
1755
1756static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07001757 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07001758 POWER_SUPPLY_PROP_STATUS,
1759 POWER_SUPPLY_PROP_CHARGE_TYPE,
1760 POWER_SUPPLY_PROP_HEALTH,
1761 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001762 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07001763 POWER_SUPPLY_PROP_TECHNOLOGY,
1764 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
1765 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
1766 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1767 POWER_SUPPLY_PROP_CAPACITY,
1768 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07001769 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
David Keitel2586f0a2013-08-20 10:02:26 -07001770 POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
David Keitel337bd862013-07-15 21:42:58 -07001771 POWER_SUPPLY_PROP_VOLTAGE_MIN,
1772 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07001773 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301774 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07001775 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07001776 POWER_SUPPLY_PROP_COOL_TEMP,
1777 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08001778 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301779 POWER_SUPPLY_PROP_CYCLE_COUNT,
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07001780 POWER_SUPPLY_PROP_VOLTAGE_OCV,
David Keitel80668952012-07-27 14:25:49 -07001781};
1782
1783static char *pm_power_supplied_to[] = {
1784 "battery",
1785};
1786
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07001787static char *pm_batt_supplied_to[] = {
1788 "bms",
1789};
1790
David Keitel337bd862013-07-15 21:42:58 -07001791static int charger_monitor;
1792module_param(charger_monitor, int, 0644);
1793
David Keitel2586f0a2013-08-20 10:02:26 -07001794static int ext_ovp_present;
1795module_param(ext_ovp_present, int, 0444);
1796
David Keitel80668952012-07-27 14:25:49 -07001797#define USB_WALL_THRESHOLD_MA 500
David Keitel2586f0a2013-08-20 10:02:26 -07001798#define OVP_USB_WALL_THRESHOLD_MA 200
David Keitel80668952012-07-27 14:25:49 -07001799static int
1800qpnp_power_get_property_mains(struct power_supply *psy,
1801 enum power_supply_property psp,
1802 union power_supply_propval *val)
1803{
1804 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1805 dc_psy);
1806
1807 switch (psp) {
1808 case POWER_SUPPLY_PROP_PRESENT:
1809 case POWER_SUPPLY_PROP_ONLINE:
1810 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07001811 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07001812 return 0;
1813
1814 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
1815 break;
David Keitel432e1232013-06-05 16:10:18 -07001816 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07001817 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07001818 break;
David Keitel80668952012-07-27 14:25:49 -07001819 default:
1820 return -EINVAL;
1821 }
1822 return 0;
1823}
1824
David Keitel7ac385e2013-08-19 18:02:40 -07001825static void
1826qpnp_aicl_check_work(struct work_struct *work)
1827{
1828 struct delayed_work *dwork = to_delayed_work(work);
1829 struct qpnp_chg_chip *chip = container_of(dwork,
1830 struct qpnp_chg_chip, aicl_check_work);
1831 union power_supply_propval ret = {0,};
1832
1833 if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
1834 chip->usb_psy->get_property(chip->usb_psy,
1835 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
1836 if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
1837 pr_debug("no charger_monitor present set iusbmax %d\n",
1838 ret.intval / 1000);
1839 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
1840 }
1841 } else {
1842 pr_debug("charger_monitor is present\n");
1843 }
1844 chip->charger_monitor_checked = true;
1845}
1846
David Keitel80668952012-07-27 14:25:49 -07001847static int
1848get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
1849{
1850 int rc = 0;
1851 struct qpnp_vadc_result results;
1852
David Keitelfe51cb92013-04-02 19:42:58 -07001853 if (chip->revision == 0 && chip->type == SMBB) {
1854 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
1855 return 0;
1856 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001857 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07001858 if (rc) {
1859 pr_err("Unable to read vbat rc=%d\n", rc);
1860 return 0;
1861 }
1862 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07001863 }
1864}
1865
1866#define BATT_PRES_BIT BIT(7)
1867static int
1868get_prop_batt_present(struct qpnp_chg_chip *chip)
1869{
1870 u8 batt_present;
1871 int rc;
1872
1873 rc = qpnp_chg_read(chip, &batt_present,
1874 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
1875 if (rc) {
1876 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
1877 return 0;
1878 };
1879 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
1880}
1881
1882#define BATT_TEMP_HOT BIT(6)
1883#define BATT_TEMP_OK BIT(7)
1884static int
1885get_prop_batt_health(struct qpnp_chg_chip *chip)
1886{
1887 u8 batt_health;
1888 int rc;
1889
1890 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07001891 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07001892 if (rc) {
1893 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
1894 return POWER_SUPPLY_HEALTH_UNKNOWN;
1895 };
1896
1897 if (BATT_TEMP_OK & batt_health)
1898 return POWER_SUPPLY_HEALTH_GOOD;
1899 if (BATT_TEMP_HOT & batt_health)
1900 return POWER_SUPPLY_HEALTH_OVERHEAT;
1901 else
1902 return POWER_SUPPLY_HEALTH_COLD;
1903}
1904
1905static int
1906get_prop_charge_type(struct qpnp_chg_chip *chip)
1907{
1908 int rc;
1909 u8 chgr_sts;
1910
1911 if (!get_prop_batt_present(chip))
1912 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1913
1914 rc = qpnp_chg_read(chip, &chgr_sts,
1915 INT_RT_STS(chip->chgr_base), 1);
1916 if (rc) {
1917 pr_err("failed to read interrupt sts %d\n", rc);
1918 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1919 }
1920
1921 if (chgr_sts & TRKL_CHG_ON_IRQ)
1922 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1923 if (chgr_sts & FAST_CHG_ON_IRQ)
1924 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1925
1926 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1927}
1928
1929static int
1930get_prop_batt_status(struct qpnp_chg_chip *chip)
1931{
1932 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001933 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07001934
David Keitel9fd07382013-05-02 15:37:44 -07001935 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
1936 qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
David Keitelc9ffe842013-01-25 19:37:51 -08001937 return POWER_SUPPLY_STATUS_FULL;
David Keitel9fd07382013-05-02 15:37:44 -07001938 }
David Keitelc9ffe842013-01-25 19:37:51 -08001939
David Keitel9fd07382013-05-02 15:37:44 -07001940 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07001941 if (rc) {
1942 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08001943 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07001944 }
1945
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001946 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
1947 if (rc) {
1948 pr_err("failed to read bat_if sts %d\n", rc);
1949 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1950 }
1951
1952 if (chgr_sts & TRKL_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07001953 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001954 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07001955 return POWER_SUPPLY_STATUS_CHARGING;
1956
1957 return POWER_SUPPLY_STATUS_DISCHARGING;
1958}
1959
1960static int
1961get_prop_current_now(struct qpnp_chg_chip *chip)
1962{
1963 union power_supply_propval ret = {0,};
1964
1965 if (chip->bms_psy) {
1966 chip->bms_psy->get_property(chip->bms_psy,
1967 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
1968 return ret.intval;
1969 } else {
1970 pr_debug("No BMS supply registered return 0\n");
1971 }
1972
1973 return 0;
1974}
1975
1976static int
1977get_prop_full_design(struct qpnp_chg_chip *chip)
1978{
1979 union power_supply_propval ret = {0,};
1980
1981 if (chip->bms_psy) {
1982 chip->bms_psy->get_property(chip->bms_psy,
1983 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
1984 return ret.intval;
1985 } else {
1986 pr_debug("No BMS supply registered return 0\n");
1987 }
1988
1989 return 0;
1990}
1991
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301992static int
1993get_prop_charge_full(struct qpnp_chg_chip *chip)
1994{
1995 union power_supply_propval ret = {0,};
1996
1997 if (chip->bms_psy) {
1998 chip->bms_psy->get_property(chip->bms_psy,
1999 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
2000 return ret.intval;
2001 } else {
2002 pr_debug("No BMS supply registered return 0\n");
2003 }
2004
2005 return 0;
2006}
2007
David Keitel80668952012-07-27 14:25:49 -07002008#define DEFAULT_CAPACITY 50
2009static int
2010get_prop_capacity(struct qpnp_chg_chip *chip)
2011{
2012 union power_supply_propval ret = {0,};
Xiaozhe Shibda84992013-09-05 10:39:11 -07002013 int battery_status, bms_status, soc, charger_in;
David Keitel80668952012-07-27 14:25:49 -07002014
David Keitel3dd5e0f2012-12-12 18:12:36 -08002015 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2016 return DEFAULT_CAPACITY;
2017
David Keitel80668952012-07-27 14:25:49 -07002018 if (chip->bms_psy) {
2019 chip->bms_psy->get_property(chip->bms_psy,
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002020 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002021 soc = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002022 battery_status = get_prop_batt_status(chip);
Xiaozhe Shibda84992013-09-05 10:39:11 -07002023 chip->bms_psy->get_property(chip->bms_psy,
2024 POWER_SUPPLY_PROP_STATUS, &ret);
2025 bms_status = ret.intval;
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002026 charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
2027 qpnp_chg_is_dc_chg_plugged_in(chip);
2028
2029 if (battery_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shibda84992013-09-05 10:39:11 -07002030 && bms_status != POWER_SUPPLY_STATUS_CHARGING
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002031 && charger_in
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002032 && !chip->resuming_charging
2033 && !chip->charging_disabled
2034 && chip->soc_resume_limit
Xiaozhe Shibda84992013-09-05 10:39:11 -07002035 && soc <= chip->soc_resume_limit) {
2036 pr_debug("resuming charging at %d%% soc\n", soc);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002037 chip->resuming_charging = true;
2038 qpnp_chg_set_appropriate_vbatdet(chip);
2039 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2040 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002041 if (soc == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07002042 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
2043 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07002044 pr_warn_ratelimited("Battery 0, CHG absent\n");
2045 }
Xiaozhe Shibda84992013-09-05 10:39:11 -07002046 return soc;
David Keitel80668952012-07-27 14:25:49 -07002047 } else {
2048 pr_debug("No BMS supply registered return 50\n");
2049 }
2050
2051 /* return default capacity to avoid userspace
2052 * from shutting down unecessarily */
2053 return DEFAULT_CAPACITY;
2054}
2055
David Keitel3dd5e0f2012-12-12 18:12:36 -08002056#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07002057#define MAX_TOLERABLE_BATT_TEMP_DDC 680
2058static int
2059get_prop_batt_temp(struct qpnp_chg_chip *chip)
2060{
2061 int rc = 0;
2062 struct qpnp_vadc_result results;
2063
David Keitel3dd5e0f2012-12-12 18:12:36 -08002064 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
2065 return DEFAULT_TEMP;
2066
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002067 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07002068 if (rc) {
2069 pr_debug("Unable to read batt temperature rc=%d\n", rc);
2070 return 0;
David Keitel80668952012-07-27 14:25:49 -07002071 }
David Keitela2dbfc72013-06-07 11:10:14 -07002072 pr_debug("get_bat_temp %d %lld\n",
2073 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07002074
David Keitela2dbfc72013-06-07 11:10:14 -07002075 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07002076}
2077
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302078static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
2079{
2080 union power_supply_propval ret = {0,};
2081
2082 if (chip->bms_psy)
2083 chip->bms_psy->get_property(chip->bms_psy,
2084 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
2085 return ret.intval;
2086}
2087
David Keitel337bd862013-07-15 21:42:58 -07002088static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
2089{
2090 u8 buck_sts;
2091 int rc;
2092
2093 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2094
2095 if (rc) {
2096 pr_err("spmi read failed: addr=%03X, rc=%d\n",
2097 INT_RT_STS(chip->buck_base), rc);
2098 return rc;
2099 }
2100 pr_debug("buck usb sts 0x%x\n", buck_sts);
2101
2102 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
2103}
2104
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002105static int get_prop_online(struct qpnp_chg_chip *chip)
2106{
2107 return qpnp_chg_is_batfet_closed(chip);
2108}
2109
David Keitel80668952012-07-27 14:25:49 -07002110static void
2111qpnp_batt_external_power_changed(struct power_supply *psy)
2112{
2113 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2114 batt_psy);
2115 union power_supply_propval ret = {0,};
2116
2117 if (!chip->bms_psy)
2118 chip->bms_psy = power_supply_get_by_name("bms");
2119
2120 chip->usb_psy->get_property(chip->usb_psy,
2121 POWER_SUPPLY_PROP_ONLINE, &ret);
2122
David Keitelc69f2d62013-03-17 14:52:35 -07002123 /* Only honour requests while USB is present */
2124 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002125 chip->usb_psy->get_property(chip->usb_psy,
2126 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07002127
2128 if (chip->prev_usb_max_ma == ret.intval)
2129 goto skip_set_iusb_max;
2130
Zhenhua Huangdd619742013-10-24 10:02:07 +08002131 chip->prev_usb_max_ma = ret.intval;
2132
David Keitel87473252013-03-21 14:39:45 -07002133 if (ret.intval <= 2 && !chip->use_default_batt_values &&
2134 get_prop_batt_present(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07002135 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07002136 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07002137 } else {
David Keiteld681cda2012-10-02 15:44:21 -07002138 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel337bd862013-07-15 21:42:58 -07002139 if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
David Keitel7ac385e2013-08-19 18:02:40 -07002140 && (charger_monitor ||
2141 !chip->charger_monitor_checked)) {
David Keitel2586f0a2013-08-20 10:02:26 -07002142 if (!ext_ovp_present)
2143 qpnp_chg_iusbmax_set(chip,
David Keitel337bd862013-07-15 21:42:58 -07002144 USB_WALL_THRESHOLD_MA);
David Keitel2586f0a2013-08-20 10:02:26 -07002145 else
2146 qpnp_chg_iusbmax_set(chip,
2147 OVP_USB_WALL_THRESHOLD_MA);
David Keitel337bd862013-07-15 21:42:58 -07002148 } else {
2149 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
2150 }
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07002151
2152 if ((chip->flags & POWER_STAGE_WA)
2153 && ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
2154 && !chip->power_stage_workaround_running) {
2155 chip->power_stage_workaround_running = true;
2156 pr_debug("usb wall chg inserted starting power stage workaround charger_monitor = %d\n",
2157 charger_monitor);
2158 schedule_work(&chip->reduce_power_stage_work);
2159 }
David Keitelc69f2d62013-03-17 14:52:35 -07002160 }
David Keitel80668952012-07-27 14:25:49 -07002161 }
2162
David Keitelfd305ee2013-07-19 20:19:06 -07002163skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07002164 pr_debug("end of power supply changed\n");
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002165 pr_debug("psy changed batt_psy\n");
David Keitel80668952012-07-27 14:25:49 -07002166 power_supply_changed(&chip->batt_psy);
2167}
2168
2169static int
2170qpnp_batt_power_get_property(struct power_supply *psy,
2171 enum power_supply_property psp,
2172 union power_supply_propval *val)
2173{
2174 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2175 batt_psy);
2176
2177 switch (psp) {
2178 case POWER_SUPPLY_PROP_STATUS:
2179 val->intval = get_prop_batt_status(chip);
2180 break;
2181 case POWER_SUPPLY_PROP_CHARGE_TYPE:
2182 val->intval = get_prop_charge_type(chip);
2183 break;
2184 case POWER_SUPPLY_PROP_HEALTH:
2185 val->intval = get_prop_batt_health(chip);
2186 break;
2187 case POWER_SUPPLY_PROP_PRESENT:
2188 val->intval = get_prop_batt_present(chip);
2189 break;
2190 case POWER_SUPPLY_PROP_TECHNOLOGY:
2191 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
2192 break;
2193 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
2194 val->intval = chip->max_voltage_mv * 1000;
2195 break;
2196 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
2197 val->intval = chip->min_voltage_mv * 1000;
2198 break;
2199 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2200 val->intval = get_prop_battery_voltage_now(chip);
2201 break;
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002202 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
2203 val->intval = chip->insertion_ocv_uv;
2204 break;
David Keitel80668952012-07-27 14:25:49 -07002205 case POWER_SUPPLY_PROP_TEMP:
2206 val->intval = get_prop_batt_temp(chip);
2207 break;
David Keitelec3c09802013-06-13 13:05:30 -07002208 case POWER_SUPPLY_PROP_COOL_TEMP:
2209 val->intval = chip->cool_bat_decidegc;
2210 break;
2211 case POWER_SUPPLY_PROP_WARM_TEMP:
2212 val->intval = chip->warm_bat_decidegc;
2213 break;
David Keitel80668952012-07-27 14:25:49 -07002214 case POWER_SUPPLY_PROP_CAPACITY:
2215 val->intval = get_prop_capacity(chip);
2216 break;
2217 case POWER_SUPPLY_PROP_CURRENT_NOW:
2218 val->intval = get_prop_current_now(chip);
2219 break;
2220 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
2221 val->intval = get_prop_full_design(chip);
2222 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05302223 case POWER_SUPPLY_PROP_CHARGE_FULL:
2224 val->intval = get_prop_charge_full(chip);
2225 break;
David Keitelb80eda82012-10-15 10:49:11 -07002226 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07002227 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07002228 break;
David Keitelbe208252013-01-31 14:49:25 -08002229 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2230 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07002231 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05302232 case POWER_SUPPLY_PROP_CYCLE_COUNT:
2233 val->intval = get_prop_cycle_count(chip);
2234 break;
David Keitel337bd862013-07-15 21:42:58 -07002235 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
2236 val->intval = get_prop_vchg_loop(chip);
2237 break;
2238 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2239 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
2240 break;
David Keitel2586f0a2013-08-20 10:02:26 -07002241 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
2242 val->intval = qpnp_chg_iusb_trim_get(chip);
2243 break;
David Keitel337bd862013-07-15 21:42:58 -07002244 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2245 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
2246 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002247 case POWER_SUPPLY_PROP_ONLINE:
2248 val->intval = get_prop_online(chip);
2249 break;
David Keitelb80eda82012-10-15 10:49:11 -07002250 default:
2251 return -EINVAL;
2252 }
2253
David Keitelb80eda82012-10-15 10:49:11 -07002254 return 0;
David Keitel80668952012-07-27 14:25:49 -07002255}
2256
David Keitel89c17752013-06-28 14:52:48 -07002257#define BTC_CONFIG_ENABLED BIT(7)
2258#define BTC_COLD BIT(1)
2259#define BTC_HOT BIT(0)
2260static int
2261qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
2262{
2263 u8 btc_cfg = 0, mask = 0;
2264
2265 /* Do nothing if battery peripheral not present */
2266 if (!chip->bat_if_base)
2267 return 0;
2268
2269 if ((chip->hot_batt_p == HOT_THD_25_PCT)
2270 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
2271 btc_cfg |= btc_value[chip->hot_batt_p];
2272 mask |= BTC_HOT;
2273 }
2274
2275 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
2276 (chip->cold_batt_p == COLD_THD_80_PCT)) {
2277 btc_cfg |= btc_value[chip->cold_batt_p];
2278 mask |= BTC_COLD;
2279 }
2280
2281 if (chip->btc_disabled)
2282 mask |= BTC_CONFIG_ENABLED;
2283
2284 return qpnp_chg_masked_write(chip,
2285 chip->bat_if_base + BAT_IF_BTC_CTRL,
2286 mask, btc_cfg, 1);
2287}
2288
David Keitel5d44fa52012-12-03 16:37:31 -08002289#define QPNP_CHG_IBATSAFE_MIN_MA 100
2290#define QPNP_CHG_IBATSAFE_MAX_MA 3250
2291#define QPNP_CHG_I_STEP_MA 50
2292#define QPNP_CHG_I_MIN_MA 100
2293#define QPNP_CHG_I_MASK 0x3F
2294static int
2295qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
2296{
2297 u8 temp;
2298
2299 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
2300 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
2301 pr_err("bad mA=%d asked to set\n", safe_current);
2302 return -EINVAL;
2303 }
2304
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08002305 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08002306 return qpnp_chg_masked_write(chip,
2307 chip->chgr_base + CHGR_IBAT_SAFE,
2308 QPNP_CHG_I_MASK, temp, 1);
2309}
David Keitel80668952012-07-27 14:25:49 -07002310
2311#define QPNP_CHG_ITERM_MIN_MA 100
2312#define QPNP_CHG_ITERM_MAX_MA 250
2313#define QPNP_CHG_ITERM_STEP_MA 50
2314#define QPNP_CHG_ITERM_MASK 0x03
2315static int
2316qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
2317{
2318 u8 temp;
2319
2320 if (term_current < QPNP_CHG_ITERM_MIN_MA
2321 || term_current > QPNP_CHG_ITERM_MAX_MA) {
2322 pr_err("bad mA=%d asked to set\n", term_current);
2323 return -EINVAL;
2324 }
2325
2326 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
2327 / QPNP_CHG_ITERM_STEP_MA;
2328 return qpnp_chg_masked_write(chip,
2329 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
2330 QPNP_CHG_ITERM_MASK, temp, 1);
2331}
2332
David Keitelff5d0472013-04-04 11:36:06 -07002333#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07002334#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07002335static int
2336qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
2337{
2338 u8 temp;
2339
2340 if (chg_current < QPNP_CHG_IBATMAX_MIN
2341 || chg_current > QPNP_CHG_IBATMAX_MAX) {
2342 pr_err("bad mA=%d asked to set\n", chg_current);
2343 return -EINVAL;
2344 }
David Keitelff5d0472013-04-04 11:36:06 -07002345 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07002346 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
2347 QPNP_CHG_I_MASK, temp, 1);
2348}
2349
David Keitela4b7b592013-04-11 18:34:35 -07002350#define QPNP_CHG_TCHG_MASK 0x7F
2351#define QPNP_CHG_TCHG_MIN 4
2352#define QPNP_CHG_TCHG_MAX 512
2353#define QPNP_CHG_TCHG_STEP 4
2354static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
2355{
2356 u8 temp;
2357
2358 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
2359 pr_err("bad max minutes =%d asked to set\n", minutes);
2360 return -EINVAL;
2361 }
2362
2363 temp = (minutes - 1)/QPNP_CHG_TCHG_STEP;
2364 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07002365 QPNP_CHG_TCHG_MASK, temp, 1);
David Keitela4b7b592013-04-11 18:34:35 -07002366}
David Keitel80668952012-07-27 14:25:49 -07002367
David Keitel80668952012-07-27 14:25:49 -07002368static int
2369qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
2370{
2371 u8 temp;
2372
2373 if (voltage < QPNP_CHG_V_MIN_MV
2374 || voltage > QPNP_CHG_V_MAX_MV) {
2375 pr_err("bad mV=%d asked to set\n", voltage);
2376 return -EINVAL;
2377 }
2378 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
2379 pr_debug("voltage=%d setting %02x\n", voltage, temp);
2380 return qpnp_chg_write(chip, &temp,
2381 chip->chgr_base + CHGR_VDD_SAFE, 1);
2382}
2383
David Keitel6dc4ed42013-05-17 11:08:58 -07002384#define BOOST_MIN_UV 4200000
2385#define BOOST_MAX_UV 5500000
2386#define BOOST_STEP_UV 50000
2387#define BOOST_MIN 16
2388#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
2389static int
2390qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
2391{
2392 u8 reg = 0;
2393
2394 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
2395 pr_err("invalid voltage requested %d uV\n", voltage);
2396 return -EINVAL;
2397 }
2398
2399 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
2400
2401 pr_debug("voltage=%d setting %02x\n", voltage, reg);
2402 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
2403}
2404
2405static int
2406qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
2407{
2408 int rc;
2409 u8 boost_reg;
2410
2411 rc = qpnp_chg_read(chip, &boost_reg,
2412 chip->boost_base + BOOST_VSET, 1);
2413 if (rc) {
2414 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
2415 return rc;
2416 }
2417
2418 if (boost_reg < BOOST_MIN) {
2419 pr_err("Invalid reading from 0x%x\n", boost_reg);
2420 return -EINVAL;
2421 }
2422
2423 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
2424}
2425
David Keitel454ee842013-03-08 16:19:11 -08002426static void
David Keitelbe208252013-01-31 14:49:25 -08002427qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
2428{
2429 unsigned int chg_current = chip->max_bat_chg_current;
2430
David Keitel454ee842013-03-08 16:19:11 -08002431 if (chip->bat_is_cool)
2432 chg_current = min(chg_current, chip->cool_bat_chg_ma);
2433
2434 if (chip->bat_is_warm)
2435 chg_current = min(chg_current, chip->warm_bat_chg_ma);
2436
David Keitelbe208252013-01-31 14:49:25 -08002437 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
2438 chg_current = min(chg_current,
2439 chip->thermal_mitigation[chip->therm_lvl_sel]);
2440
2441 pr_debug("setting %d mA\n", chg_current);
2442 qpnp_chg_ibatmax_set(chip, chg_current);
2443}
2444
2445static void
2446qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
2447{
2448 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
2449 chip->therm_lvl_sel = lvl_sel;
2450 if (lvl_sel == (chip->thermal_levels - 1)) {
2451 /* disable charging if highest value selected */
2452 qpnp_chg_buck_control(chip, 0);
2453 } else {
2454 qpnp_chg_buck_control(chip, 1);
2455 qpnp_chg_set_appropriate_battery_current(chip);
2456 }
2457 } else {
2458 pr_err("Unsupported level selected %d\n", lvl_sel);
2459 }
2460}
2461
David Keitel6dc4ed42013-05-17 11:08:58 -07002462/* OTG regulator operations */
2463static int
2464qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
2465{
2466 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2467
2468 return switch_usb_to_host_mode(chip);
2469}
2470
2471static int
2472qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
2473{
2474 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2475
2476 return switch_usb_to_charge_mode(chip);
2477}
2478
2479static int
2480qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
2481{
2482 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2483
2484 return qpnp_chg_is_otg_en_set(chip);
2485}
2486
2487static int
2488qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
2489{
2490 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07002491 int rc;
2492
2493 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
2494 (chip->flags & BOOST_FLASH_WA)) {
2495 qpnp_chg_usb_suspend_enable(chip, 1);
2496
2497 rc = qpnp_chg_masked_write(chip,
2498 chip->usb_chgpth_base + SEC_ACCESS,
2499 0xFF,
2500 0xA5, 1);
2501 if (rc) {
2502 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2503 return rc;
2504 }
2505
2506 rc = qpnp_chg_masked_write(chip,
2507 chip->usb_chgpth_base + COMP_OVR1,
2508 0xFF,
2509 0x2F, 1);
2510 if (rc) {
2511 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2512 return rc;
2513 }
2514 }
David Keitel6dc4ed42013-05-17 11:08:58 -07002515
2516 return qpnp_chg_masked_write(chip,
2517 chip->boost_base + BOOST_ENABLE_CONTROL,
2518 BOOST_PWR_EN,
2519 BOOST_PWR_EN, 1);
2520}
2521
2522/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07002523#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07002524static int
2525qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
2526{
2527 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07002528 int rc;
2529 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07002530
David Keitel33f58952013-05-20 16:17:36 -07002531 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07002532 chip->boost_base + BOOST_ENABLE_CONTROL,
2533 BOOST_PWR_EN,
2534 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07002535 if (rc) {
2536 pr_err("failed to disable boost rc=%d\n", rc);
2537 return rc;
2538 }
2539
2540 rc = qpnp_chg_read(chip, &vbat_sts,
2541 chip->chgr_base + CHGR_VBAT_STATUS, 1);
2542 if (rc) {
2543 pr_err("failed to read bat sts rc=%d\n", rc);
2544 return rc;
2545 }
2546
2547 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
2548 rc = qpnp_chg_masked_write(chip,
2549 chip->chgr_base + SEC_ACCESS,
2550 0xFF,
2551 0xA5, 1);
2552 if (rc) {
2553 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2554 return rc;
2555 }
2556
2557 rc = qpnp_chg_masked_write(chip,
2558 chip->chgr_base + COMP_OVR1,
2559 0xFF,
2560 0x20, 1);
2561 if (rc) {
2562 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2563 return rc;
2564 }
2565
2566 usleep(2000);
2567
2568 rc = qpnp_chg_masked_write(chip,
2569 chip->chgr_base + SEC_ACCESS,
2570 0xFF,
2571 0xA5, 1);
2572 if (rc) {
2573 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2574 return rc;
2575 }
2576
2577 rc = qpnp_chg_masked_write(chip,
2578 chip->chgr_base + COMP_OVR1,
2579 0xFF,
2580 0x00, 1);
2581 if (rc) {
2582 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2583 return rc;
2584 }
2585 }
2586
2587 if (qpnp_chg_is_usb_chg_plugged_in(chip)
2588 && (chip->flags & BOOST_FLASH_WA)) {
2589 rc = qpnp_chg_masked_write(chip,
2590 chip->usb_chgpth_base + SEC_ACCESS,
2591 0xFF,
2592 0xA5, 1);
2593 if (rc) {
2594 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2595 return rc;
2596 }
2597
2598 rc = qpnp_chg_masked_write(chip,
2599 chip->usb_chgpth_base + COMP_OVR1,
2600 0xFF,
2601 0x00, 1);
2602 if (rc) {
2603 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2604 return rc;
2605 }
2606
2607 usleep(1000);
2608
2609 qpnp_chg_usb_suspend_enable(chip, 0);
2610 }
2611
2612 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07002613}
2614
2615static int
2616qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
2617{
2618 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2619
2620 return qpnp_chg_is_boost_en_set(chip);
2621}
2622
2623static int
2624qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
2625 int min_uV, int max_uV, unsigned *selector)
2626{
2627 int uV = min_uV;
2628 int rc;
2629 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2630
2631 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
2632 uV = BOOST_MIN_UV;
2633
2634
2635 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
2636 pr_err("request %d uV is out of bounds\n", uV);
2637 return -EINVAL;
2638 }
2639
2640 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
2641 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
2642 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
2643 return -EINVAL;
2644 }
2645
2646 rc = qpnp_boost_vset(chip, uV);
2647
2648 return rc;
2649}
2650
2651static int
2652qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
2653{
2654 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2655
2656 return qpnp_boost_vget_uv(chip);
2657}
2658
2659static int
2660qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
2661 unsigned selector)
2662{
2663 if (selector >= N_BOOST_V)
2664 return 0;
2665
2666 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
2667}
2668
2669static struct regulator_ops qpnp_chg_otg_reg_ops = {
2670 .enable = qpnp_chg_regulator_otg_enable,
2671 .disable = qpnp_chg_regulator_otg_disable,
2672 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
2673};
2674
2675static struct regulator_ops qpnp_chg_boost_reg_ops = {
2676 .enable = qpnp_chg_regulator_boost_enable,
2677 .disable = qpnp_chg_regulator_boost_disable,
2678 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
2679 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
2680 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
2681 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
2682};
2683
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002684static int
David Keitel6e63bd52013-09-06 18:00:03 -07002685qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002686{
David Keitel9eca8ac2013-09-06 14:18:36 -07002687 int rc = 0;
David Keitel6e63bd52013-09-06 18:00:03 -07002688 u8 reg = 0;
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002689
David Keitelcadbc282013-09-26 11:39:14 -07002690 if (!chip->bat_if_base)
2691 return rc;
2692
David Keitel9eca8ac2013-09-06 14:18:36 -07002693 if (chip->type == SMBB)
2694 rc = qpnp_chg_read(chip, &reg,
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002695 chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
David Keitel9eca8ac2013-09-06 14:18:36 -07002696 else
2697 rc = qpnp_chg_read(chip, &reg,
2698 chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
David Keitel6e63bd52013-09-06 18:00:03 -07002699
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002700 if (rc) {
2701 pr_err("failed to read batt_if rc=%d\n", rc);
2702 return rc;
2703 }
2704
David Keitel6e63bd52013-09-06 18:00:03 -07002705 if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002706 return 1;
2707
2708 return 0;
2709}
2710
David Keitel6e63bd52013-09-06 18:00:03 -07002711static int
2712qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
2713{
2714 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2715 int rc = 0;
2716
2717 mutex_lock(&chip->batfet_vreg_lock);
2718 /* Only enable if not already enabled */
2719 if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
2720 rc = qpnp_chg_regulator_batfet_set(chip, 1);
2721 if (rc)
2722 pr_err("failed to write to batt_if rc=%d\n", rc);
2723 }
2724
2725 chip->batfet_ext_en = true;
2726 mutex_unlock(&chip->batfet_vreg_lock);
2727
2728 return rc;
2729}
2730
2731static int
2732qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
2733{
2734 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2735 int rc = 0;
2736
2737 mutex_lock(&chip->batfet_vreg_lock);
2738 /* Don't allow disable if charger connected */
2739 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
2740 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
2741 rc = qpnp_chg_regulator_batfet_set(chip, 0);
2742 if (rc)
2743 pr_err("failed to write to batt_if rc=%d\n", rc);
2744 }
2745
2746 chip->batfet_ext_en = false;
2747 mutex_unlock(&chip->batfet_vreg_lock);
2748
2749 return rc;
2750}
2751
2752static int
2753qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
2754{
2755 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2756
2757 return chip->batfet_ext_en;
2758}
2759
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07002760static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
2761 .enable = qpnp_chg_regulator_batfet_enable,
2762 .disable = qpnp_chg_regulator_batfet_disable,
2763 .is_enabled = qpnp_chg_regulator_batfet_is_enabled,
2764};
2765
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07002766#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 8
2767#define MAX_DELTA_VDD_MAX_MV 80
2768#define VDD_MAX_CENTER_OFFSET 4
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002769static void
2770qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
2771{
2772 int delta_mv, closest_delta_mv, sign;
2773
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07002774 delta_mv = chip->max_voltage_mv - VDD_MAX_CENTER_OFFSET - vbat_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002775 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
2776 pr_debug("vbat is not low enough to increase vdd\n");
2777 return;
2778 }
2779
2780 sign = delta_mv > 0 ? 1 : -1;
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07002781 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_BUCK_TRIM1_STEP / 2)
2782 / QPNP_CHG_BUCK_TRIM1_STEP) * QPNP_CHG_BUCK_TRIM1_STEP;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002783 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
2784 chip->max_voltage_mv, vbat_mv,
2785 delta_mv, closest_delta_mv);
2786 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
2787 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
2788 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
2789 qpnp_chg_set_appropriate_vddmax(chip);
2790}
2791
David Keitel9fd07382013-05-02 15:37:44 -07002792#define CONSECUTIVE_COUNT 3
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002793#define VBATDET_MAX_ERR_MV 50
David Keitel9fd07382013-05-02 15:37:44 -07002794static void
2795qpnp_eoc_work(struct work_struct *work)
2796{
2797 struct delayed_work *dwork = to_delayed_work(work);
2798 struct qpnp_chg_chip *chip = container_of(dwork,
2799 struct qpnp_chg_chip, eoc_work);
2800 static int count;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002801 static int vbat_low_count;
David Keitel9fd07382013-05-02 15:37:44 -07002802 int ibat_ma, vbat_mv, rc = 0;
2803 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002804 bool vbat_lower_than_vbatdet;
David Keitel9fd07382013-05-02 15:37:44 -07002805
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002806 pm_stay_awake(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07002807 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2808
2809 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
2810 if (rc) {
2811 pr_err("failed to read batt_if rc=%d\n", rc);
2812 return;
2813 }
2814
2815 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2816 if (rc) {
2817 pr_err("failed to read buck rc=%d\n", rc);
2818 return;
2819 }
2820
2821 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
2822 if (rc) {
2823 pr_err("failed to read chg_sts rc=%d\n", rc);
2824 return;
2825 }
2826
2827 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
2828 chg_sts, batt_sts, buck_sts);
2829
2830 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
2831 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
2832 pr_debug("no chg connected, stopping\n");
2833 goto stop_eoc;
2834 }
2835
2836 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
2837 || chg_sts & TRKL_CHG_ON_IRQ)) {
2838 ibat_ma = get_prop_current_now(chip) / 1000;
2839 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002840
2841 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
2842 ibat_ma, vbat_mv, chip->term_current);
2843
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002844 vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
2845 if (vbat_lower_than_vbatdet && vbat_mv <
2846 (chip->max_voltage_mv - chip->resume_delta_mv
2847 - VBATDET_MAX_ERR_MV)) {
2848 vbat_low_count++;
2849 pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
2850 vbat_mv, chip->max_voltage_mv,
2851 chip->resume_delta_mv,
2852 VBATDET_MAX_ERR_MV, vbat_low_count);
2853 if (vbat_low_count >= CONSECUTIVE_COUNT) {
2854 pr_debug("woke up too early stopping\n");
2855 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
2856 goto stop_eoc;
2857 } else {
2858 goto check_again_later;
2859 }
2860 } else {
2861 vbat_low_count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002862 }
2863
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002864 if (buck_sts & VDD_LOOP_IRQ)
2865 qpnp_chg_adjust_vddmax(chip, vbat_mv);
2866
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002867 if (!(buck_sts & VDD_LOOP_IRQ)) {
2868 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07002869 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002870 } else if ((ibat_ma * -1) > chip->term_current) {
2871 pr_debug("Not at EOC, battery current too high\n");
2872 count = 0;
2873 } else if (ibat_ma > 0) {
2874 pr_debug("Charging but system demand increased\n");
2875 count = 0;
2876 } else {
David Keitel9fd07382013-05-02 15:37:44 -07002877 if (count == CONSECUTIVE_COUNT) {
2878 pr_info("End of Charging\n");
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07002879 chip->delta_vddmax_mv = 0;
2880 qpnp_chg_set_appropriate_vddmax(chip);
Xiaozhe Shi30e94802013-08-19 16:40:53 -07002881 chip->chg_done = true;
David Keitel9fd07382013-05-02 15:37:44 -07002882 qpnp_chg_charge_en(chip, 0);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002883 /* sleep for a second before enabling */
2884 msleep(2000);
2885 qpnp_chg_charge_en(chip,
2886 !chip->charging_disabled);
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07002887 pr_debug("psy changed batt_psy\n");
David Keitel9fd07382013-05-02 15:37:44 -07002888 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07002889 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07002890 goto stop_eoc;
2891 } else {
2892 count += 1;
2893 pr_debug("EOC count = %d\n", count);
2894 }
David Keitel9fd07382013-05-02 15:37:44 -07002895 }
2896 } else {
2897 pr_debug("not charging\n");
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002898 goto stop_eoc;
David Keitel9fd07382013-05-02 15:37:44 -07002899 }
2900
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002901check_again_later:
David Keitel9fd07382013-05-02 15:37:44 -07002902 schedule_delayed_work(&chip->eoc_work,
2903 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2904 return;
2905
2906stop_eoc:
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002907 vbat_low_count = 0;
David Keitel9fd07382013-05-02 15:37:44 -07002908 count = 0;
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07002909 pm_relax(chip->dev);
David Keitel9fd07382013-05-02 15:37:44 -07002910}
2911
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002912static void
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07002913qpnp_chg_insertion_ocv_work(struct work_struct *work)
2914{
2915 struct qpnp_chg_chip *chip = container_of(work,
2916 struct qpnp_chg_chip, insertion_ocv_work);
2917 u8 bat_if_sts = 0, charge_en = 0;
2918 int rc;
2919
2920 chip->insertion_ocv_uv = get_prop_battery_voltage_now(chip);
2921
2922 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
2923 if (rc)
2924 pr_err("failed to read bat_if sts %d\n", rc);
2925
2926 rc = qpnp_chg_read(chip, &charge_en,
2927 chip->chgr_base + CHGR_CHG_CTRL, 1);
2928 if (rc)
2929 pr_err("failed to read bat_if sts %d\n", rc);
2930
2931 pr_debug("batfet sts = %02x, charge_en = %02x ocv = %d\n",
2932 bat_if_sts, charge_en, chip->insertion_ocv_uv);
2933 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2934 pr_debug("psy changed batt_psy\n");
2935 power_supply_changed(&chip->batt_psy);
2936}
2937
2938static void
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07002939qpnp_chg_soc_check_work(struct work_struct *work)
2940{
2941 struct qpnp_chg_chip *chip = container_of(work,
2942 struct qpnp_chg_chip, soc_check_work);
2943
2944 get_prop_capacity(chip);
2945}
2946
David Keitel0c1a4532013-03-21 16:39:06 -07002947#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08002948static void
2949qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
2950{
2951 struct qpnp_chg_chip *chip = ctx;
2952 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07002953 int temp;
David Keitel454ee842013-03-08 16:19:11 -08002954
2955 if (state >= ADC_TM_STATE_NUM) {
2956 pr_err("invalid notification %d\n", state);
2957 return;
2958 }
2959
David Keitel1219a802013-03-21 16:37:21 -07002960 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08002961
David Keitel1219a802013-03-21 16:37:21 -07002962 pr_debug("temp = %d state = %s\n", temp,
2963 state == ADC_TM_WARM_STATE ? "warm" : "cool");
2964
2965 if (state == ADC_TM_WARM_STATE) {
2966 if (temp > chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002967 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08002968 bat_warm = true;
2969 bat_cool = false;
2970 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002971 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002972 chip->adc_param.state_request =
2973 ADC_TM_COOL_THR_ENABLE;
2974 } else if (temp >
2975 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002976 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08002977 bat_warm = false;
2978 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07002979
2980 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07002981 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07002982 chip->adc_param.state_request =
2983 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08002984 }
2985 } else {
David Keitel1219a802013-03-21 16:37:21 -07002986 if (temp < chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002987 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08002988 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002989 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08002990 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002991 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002992 chip->adc_param.state_request =
2993 ADC_TM_WARM_THR_ENABLE;
David Keitel3e37e5a2013-04-18 10:42:30 -07002994 } else if (temp <
David Keitel1219a802013-03-21 16:37:21 -07002995 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002996 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08002997 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002998 bat_cool = false;
2999
David Keitel0c1a4532013-03-21 16:39:06 -07003000 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07003001 chip->adc_param.high_temp = chip->warm_bat_decidegc;
3002 chip->adc_param.state_request =
3003 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08003004 }
3005 }
3006
3007 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07003008 chip->bat_is_cool = bat_cool;
3009 chip->bat_is_warm = bat_warm;
3010
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07003011 if (bat_cool || bat_warm)
3012 chip->resuming_charging = false;
3013
3014 /**
3015 * set appropriate voltages and currents.
3016 *
3017 * Note that when the battery is hot or cold, the charger
3018 * driver will not resume with SoC. Only vbatdet is used to
3019 * determine resume of charging.
3020 */
David Keitel454ee842013-03-08 16:19:11 -08003021 qpnp_chg_set_appropriate_vddmax(chip);
3022 qpnp_chg_set_appropriate_battery_current(chip);
3023 qpnp_chg_set_appropriate_vbatdet(chip);
David Keitel454ee842013-03-08 16:19:11 -08003024 }
3025
David Keitelec3c09802013-06-13 13:05:30 -07003026 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
3027 chip->bat_is_warm, chip->bat_is_cool,
3028 chip->adc_param.low_temp, chip->adc_param.high_temp);
3029
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003030 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07003031 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07003032}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07003033
David Keitelec3c09802013-06-13 13:05:30 -07003034#define MIN_COOL_TEMP -300
3035#define MAX_WARM_TEMP 1000
3036
3037static int
3038qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
3039 enum power_supply_property psp, int temp_degc)
3040{
3041 int rc = 0;
3042
3043 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
3044 pr_err("Bad temperature request %d\n", temp_degc);
3045 return -EINVAL;
3046 }
3047
3048 mutex_lock(&chip->jeita_configure_lock);
3049 switch (psp) {
3050 case POWER_SUPPLY_PROP_COOL_TEMP:
3051 if (temp_degc >=
3052 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
3053 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
3054 temp_degc, chip->warm_bat_decidegc,
3055 HYSTERISIS_DECIDEGC);
3056 rc = -EINVAL;
3057 goto mutex_unlock;
3058 }
3059 if (chip->bat_is_cool)
3060 chip->adc_param.high_temp =
3061 temp_degc + HYSTERISIS_DECIDEGC;
3062 else if (!chip->bat_is_warm)
3063 chip->adc_param.low_temp = temp_degc;
3064
3065 chip->cool_bat_decidegc = temp_degc;
3066 break;
3067 case POWER_SUPPLY_PROP_WARM_TEMP:
3068 if (temp_degc <=
3069 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
3070 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
3071 temp_degc, chip->warm_bat_decidegc,
3072 HYSTERISIS_DECIDEGC);
3073 rc = -EINVAL;
3074 goto mutex_unlock;
3075 }
3076 if (chip->bat_is_warm)
3077 chip->adc_param.low_temp =
3078 temp_degc - HYSTERISIS_DECIDEGC;
3079 else if (!chip->bat_is_cool)
3080 chip->adc_param.high_temp = temp_degc;
3081
3082 chip->warm_bat_decidegc = temp_degc;
3083 break;
3084 default:
3085 rc = -EINVAL;
3086 goto mutex_unlock;
3087 }
3088
3089 schedule_work(&chip->adc_measure_work);
3090
3091mutex_unlock:
3092 mutex_unlock(&chip->jeita_configure_lock);
3093 return rc;
David Keitel454ee842013-03-08 16:19:11 -08003094}
3095
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003096#define POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS 20
3097#define POWER_STAGE_REDUCE_MAX_VBAT_UV 3900000
3098#define POWER_STAGE_REDUCE_MIN_VCHG_UV 4800000
3099#define POWER_STAGE_SEL_MASK 0x0F
3100#define POWER_STAGE_REDUCED 0x01
3101#define POWER_STAGE_DEFAULT 0x0F
3102static bool
3103qpnp_chg_is_power_stage_reduced(struct qpnp_chg_chip *chip)
3104{
3105 int rc;
3106 u8 reg;
3107
3108 rc = qpnp_chg_read(chip, &reg,
3109 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3110 1);
3111 if (rc) {
3112 pr_err("Error %d reading power stage register\n", rc);
3113 return false;
3114 }
3115
3116 if ((reg & POWER_STAGE_SEL_MASK) == POWER_STAGE_DEFAULT)
3117 return false;
3118
3119 return true;
3120}
3121
3122static int
3123qpnp_chg_power_stage_set(struct qpnp_chg_chip *chip, bool reduce)
3124{
3125 int rc;
3126 u8 reg = 0xA5;
3127
3128 rc = qpnp_chg_write(chip, &reg,
3129 chip->buck_base + SEC_ACCESS,
3130 1);
3131 if (rc) {
3132 pr_err("Error %d writing 0xA5 to buck's 0x%x reg\n",
3133 rc, SEC_ACCESS);
3134 return rc;
3135 }
3136
3137 reg = POWER_STAGE_DEFAULT;
3138 if (reduce)
3139 reg = POWER_STAGE_REDUCED;
3140 rc = qpnp_chg_write(chip, &reg,
3141 chip->buck_base + CHGR_BUCK_PSTG_CTRL,
3142 1);
3143
3144 if (rc)
3145 pr_err("Error %d writing 0x%x power stage register\n", rc, reg);
3146 return rc;
3147}
3148
3149static int
3150qpnp_chg_get_vusbin_uv(struct qpnp_chg_chip *chip)
3151{
3152 int rc = 0;
3153 struct qpnp_vadc_result results;
3154
3155 rc = qpnp_vadc_read(chip->vadc_dev, USBIN, &results);
3156 if (rc) {
3157 pr_err("Unable to read vbat rc=%d\n", rc);
3158 return 0;
3159 }
3160 return results.physical;
3161}
3162
3163static
3164int get_vusb_averaged(struct qpnp_chg_chip *chip, int sample_count)
3165{
3166 int vusb_uv = 0;
3167 int i;
3168
3169 /* avoid overflows */
3170 if (sample_count > 256)
3171 sample_count = 256;
3172
3173 for (i = 0; i < sample_count; i++)
3174 vusb_uv += qpnp_chg_get_vusbin_uv(chip);
3175
3176 vusb_uv = vusb_uv / sample_count;
3177 return vusb_uv;
3178}
3179
3180static
3181int get_vbat_averaged(struct qpnp_chg_chip *chip, int sample_count)
3182{
3183 int vbat_uv = 0;
3184 int i;
3185
3186 /* avoid overflows */
3187 if (sample_count > 256)
3188 sample_count = 256;
3189
3190 for (i = 0; i < sample_count; i++)
3191 vbat_uv += get_prop_battery_voltage_now(chip);
3192
3193 vbat_uv = vbat_uv / sample_count;
3194 return vbat_uv;
3195}
3196
3197static void
3198qpnp_chg_reduce_power_stage(struct qpnp_chg_chip *chip)
3199{
3200 struct timespec ts;
3201 bool power_stage_reduced_in_hw = qpnp_chg_is_power_stage_reduced(chip);
3202 bool reduce_power_stage = false;
3203 int vbat_uv = get_vbat_averaged(chip, 16);
3204 int vusb_uv = get_vusb_averaged(chip, 16);
3205 bool fast_chg =
3206 (get_prop_charge_type(chip) == POWER_SUPPLY_CHARGE_TYPE_FAST);
3207 static int count_restore_power_stage;
3208 static int count_reduce_power_stage;
3209 bool vchg_loop = get_prop_vchg_loop(chip);
3210 bool ichg_loop = qpnp_chg_is_ichg_loop_active(chip);
3211 bool usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
3212 bool usb_ma_above_wall =
3213 (qpnp_chg_usb_iusbmax_get(chip) > USB_WALL_THRESHOLD_MA);
3214
3215 if (fast_chg
3216 && usb_present
3217 && usb_ma_above_wall
3218 && vbat_uv < POWER_STAGE_REDUCE_MAX_VBAT_UV
3219 && vusb_uv > POWER_STAGE_REDUCE_MIN_VCHG_UV)
3220 reduce_power_stage = true;
3221
3222 if ((usb_present && usb_ma_above_wall)
3223 && (vchg_loop || ichg_loop))
3224 reduce_power_stage = true;
3225
3226 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3227 count_restore_power_stage++;
3228 count_reduce_power_stage = 0;
3229 } else if (!power_stage_reduced_in_hw && reduce_power_stage) {
3230 count_reduce_power_stage++;
3231 count_restore_power_stage = 0;
3232 } else if (power_stage_reduced_in_hw == reduce_power_stage) {
3233 count_restore_power_stage = 0;
3234 count_reduce_power_stage = 0;
3235 }
3236
3237 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",
3238 power_stage_reduced_in_hw, reduce_power_stage,
3239 usb_present, usb_ma_above_wall,
3240 vbat_uv, vusb_uv, fast_chg,
3241 ichg_loop, vchg_loop,
3242 count_restore_power_stage, count_reduce_power_stage);
3243
3244 if (!power_stage_reduced_in_hw && reduce_power_stage) {
3245 if (count_reduce_power_stage >= 2) {
3246 qpnp_chg_power_stage_set(chip, true);
3247 power_stage_reduced_in_hw = true;
3248 }
3249 }
3250
3251 if (power_stage_reduced_in_hw && !reduce_power_stage) {
3252 if (count_restore_power_stage >= 6
3253 || (!usb_present || !usb_ma_above_wall)) {
3254 qpnp_chg_power_stage_set(chip, false);
3255 power_stage_reduced_in_hw = false;
3256 }
3257 }
3258
3259 if (usb_present && usb_ma_above_wall) {
3260 getnstimeofday(&ts);
3261 ts.tv_sec += POWER_STAGE_REDUCE_CHECK_PERIOD_SECONDS;
3262 alarm_start_range(&chip->reduce_power_stage_alarm,
3263 timespec_to_ktime(ts),
3264 timespec_to_ktime(ts));
3265 } else {
3266 pr_debug("stopping power stage workaround\n");
3267 chip->power_stage_workaround_running = false;
3268 }
3269}
3270
3271static void
David Keitel6e63bd52013-09-06 18:00:03 -07003272qpnp_chg_batfet_lcl_work(struct work_struct *work)
3273{
3274 struct qpnp_chg_chip *chip = container_of(work,
3275 struct qpnp_chg_chip, batfet_lcl_work);
3276
3277 mutex_lock(&chip->batfet_vreg_lock);
3278 if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
3279 qpnp_chg_is_dc_chg_plugged_in(chip)) {
3280 qpnp_chg_regulator_batfet_set(chip, 1);
3281 pr_debug("disabled ULPM\n");
3282 } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
3283 && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
3284 qpnp_chg_regulator_batfet_set(chip, 0);
3285 pr_debug("enabled ULPM\n");
3286 }
3287 mutex_unlock(&chip->batfet_vreg_lock);
3288}
3289
3290static void
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003291qpnp_chg_reduce_power_stage_work(struct work_struct *work)
3292{
3293 struct qpnp_chg_chip *chip = container_of(work,
3294 struct qpnp_chg_chip, reduce_power_stage_work);
3295
3296 qpnp_chg_reduce_power_stage(chip);
3297}
3298
3299static void
3300qpnp_chg_reduce_power_stage_callback(struct alarm *alarm)
3301{
3302 struct qpnp_chg_chip *chip = container_of(alarm, struct qpnp_chg_chip,
3303 reduce_power_stage_alarm);
3304
3305 schedule_work(&chip->reduce_power_stage_work);
3306}
3307
David Keitelbe208252013-01-31 14:49:25 -08003308static int
David Keitel432e1232013-06-05 16:10:18 -07003309qpnp_dc_power_set_property(struct power_supply *psy,
3310 enum power_supply_property psp,
3311 const union power_supply_propval *val)
3312{
3313 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3314 dc_psy);
3315 int rc = 0;
3316
3317 switch (psp) {
3318 case POWER_SUPPLY_PROP_CURRENT_MAX:
3319 if (!val->intval)
3320 break;
3321
3322 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
3323 if (rc) {
3324 pr_err("Error setting idcmax property %d\n", rc);
3325 return rc;
3326 }
3327 chip->maxinput_dc_ma = (val->intval / 1000);
3328
3329 break;
3330 default:
3331 return -EINVAL;
3332 }
3333
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003334 pr_debug("psy changed dc_psy\n");
David Keitel432e1232013-06-05 16:10:18 -07003335 power_supply_changed(&chip->dc_psy);
3336 return rc;
3337}
3338
3339static int
David Keitelbe208252013-01-31 14:49:25 -08003340qpnp_batt_power_set_property(struct power_supply *psy,
3341 enum power_supply_property psp,
3342 const union power_supply_propval *val)
3343{
3344 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
3345 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07003346 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08003347
3348 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07003349 case POWER_SUPPLY_PROP_COOL_TEMP:
3350 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3351 break;
3352 case POWER_SUPPLY_PROP_WARM_TEMP:
3353 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
3354 break;
David Keitelbe208252013-01-31 14:49:25 -08003355 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
3356 chip->charging_disabled = !(val->intval);
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003357 if (chip->charging_disabled) {
3358 /* disable charging */
3359 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3360 qpnp_chg_force_run_on_batt(chip,
3361 chip->charging_disabled);
3362 } else {
3363 /* enable charging */
3364 qpnp_chg_force_run_on_batt(chip,
3365 chip->charging_disabled);
3366 qpnp_chg_charge_en(chip, !chip->charging_disabled);
3367 }
David Keitelbe208252013-01-31 14:49:25 -08003368 break;
3369 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
3370 qpnp_batt_system_temp_level_set(chip, val->intval);
3371 break;
David Keitel337bd862013-07-15 21:42:58 -07003372 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
3373 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
3374 break;
David Keitel2586f0a2013-08-20 10:02:26 -07003375 case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
3376 qpnp_chg_iusb_trim_set(chip, val->intval);
3377 break;
David Keitel337bd862013-07-15 21:42:58 -07003378 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
3379 qpnp_chg_vinmin_set(chip, val->intval / 1000);
3380 break;
David Keitelbe208252013-01-31 14:49:25 -08003381 default:
3382 return -EINVAL;
3383 }
3384
Abhijeet Dharmapurikarba936ec2013-08-12 13:45:50 -07003385 pr_debug("psy changed batt_psy\n");
David Keitelbe208252013-01-31 14:49:25 -08003386 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07003387 return rc;
David Keitelbe208252013-01-31 14:49:25 -08003388}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003389
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003390static int
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003391qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07003392{
David Keitelfe51cb92013-04-02 19:42:58 -07003393 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07003394 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07003395 if (chip->type == SMBB)
3396 chip->flags |= BOOST_FLASH_WA;
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07003397 if (chip->type == SMBBP) {
3398 struct device_node *revid_dev_node;
3399 struct pmic_revid_data *revid_data;
3400
3401 chip->flags |= BOOST_FLASH_WA;
3402
3403 revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
3404 "qcom,pmic-revid", 0);
3405 if (!revid_dev_node) {
3406 pr_err("Missing qcom,pmic-revid property\n");
3407 return -EINVAL;
3408 }
3409 revid_data = get_revid_data(revid_dev_node);
3410 if (IS_ERR(revid_data)) {
3411 pr_err("Couldnt get revid data rc = %ld\n",
3412 PTR_ERR(revid_data));
3413 return PTR_ERR(revid_data);
3414 }
3415
3416 if (revid_data->rev4 < PM8226_V2P1_REV4
3417 || ((revid_data->rev4 == PM8226_V2P1_REV4)
3418 && (revid_data->rev3 <= PM8226_V2P1_REV3))) {
3419 chip->flags |= POWER_STAGE_WA;
3420 }
3421 }
3422 return 0;
David Keiteld681cda2012-10-02 15:44:21 -07003423}
3424
David Keitel0f35be42013-04-16 11:10:40 -07003425static int
3426qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
3427{
3428 int rc = 0;
3429 struct resource *resource;
3430 struct spmi_resource *spmi_resource;
3431 u8 subtype;
3432 struct spmi_device *spmi = chip->spmi;
3433
3434 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
3435 if (!spmi_resource) {
3436 pr_err("qpnp_chg: spmi resource absent\n");
3437 return rc;
3438 }
3439
3440 resource = spmi_get_resource(spmi, spmi_resource,
3441 IORESOURCE_MEM, 0);
3442 if (!(resource && resource->start)) {
3443 pr_err("node %s IO resource absent!\n",
3444 spmi->dev.of_node->full_name);
3445 return rc;
3446 }
3447
3448 rc = qpnp_chg_read(chip, &subtype,
3449 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
3450 if (rc) {
3451 pr_err("Peripheral subtype read failed rc=%d\n", rc);
3452 return rc;
3453 }
3454
3455 switch (subtype) {
3456 case SMBB_CHGR_SUBTYPE:
3457 case SMBBP_CHGR_SUBTYPE:
3458 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07003459 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003460 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07003461 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003462 pr_err("Unable to get fast-chg-on irq\n");
3463 return rc;
3464 }
3465
David Keitel47185a62013-05-15 18:54:10 -07003466 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003467 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07003468 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003469 pr_err("Unable to get trkl-chg-on irq\n");
3470 return rc;
3471 }
3472
David Keitel47185a62013-05-15 18:54:10 -07003473 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003474 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07003475 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003476 pr_err("Unable to get chg_failed irq\n");
3477 return rc;
3478 }
3479
David Keitel47185a62013-05-15 18:54:10 -07003480 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07003481 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07003482 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07003483 pr_err("Unable to get fast-chg-on irq\n");
3484 return rc;
3485 }
3486
David Keitel47185a62013-05-15 18:54:10 -07003487 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003488 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07003489 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003490 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003491 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003492 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003493 return rc;
3494 }
3495
David Keitel47185a62013-05-15 18:54:10 -07003496 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003497 qpnp_chg_chgr_chg_fastchg_irq_handler,
3498 IRQF_TRIGGER_RISING,
3499 "fast-chg-on", chip);
3500 if (rc < 0) {
3501 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003502 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003503 return rc;
3504 }
3505
David Keitel47185a62013-05-15 18:54:10 -07003506 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003507 qpnp_chg_chgr_chg_trklchg_irq_handler,
3508 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07003509 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003510 if (rc < 0) {
3511 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003512 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003513 return rc;
3514 }
David Keitel9fd07382013-05-02 15:37:44 -07003515
3516 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07003517 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07003518 qpnp_chg_vbatdet_lo_irq_handler,
Abhijeet Dharmapurikar8a68b172013-08-12 13:55:58 -07003519 IRQF_TRIGGER_RISING,
David Keitel9fd07382013-05-02 15:37:44 -07003520 "vbat-det-lo", chip);
3521 if (rc < 0) {
3522 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003523 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07003524 return rc;
3525 }
3526
David Keitel47185a62013-05-15 18:54:10 -07003527 enable_irq_wake(chip->chg_trklchg.irq);
3528 enable_irq_wake(chip->chg_failed.irq);
3529 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
3530 enable_irq_wake(chip->chg_vbatdet_lo.irq);
David Keitel0f35be42013-04-16 11:10:40 -07003531
3532 break;
3533 case SMBB_BAT_IF_SUBTYPE:
3534 case SMBBP_BAT_IF_SUBTYPE:
3535 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07003536 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003537 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07003538 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003539 pr_err("Unable to get batt-pres irq\n");
3540 return rc;
3541 }
David Keitel47185a62013-05-15 18:54:10 -07003542 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003543 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07003544 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
3545 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07003546 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003547 if (rc < 0) {
3548 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003549 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003550 return rc;
3551 }
3552
David Keitel47185a62013-05-15 18:54:10 -07003553 enable_irq_wake(chip->batt_pres.irq);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07003554
3555 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
3556 spmi_resource, "bat-temp-ok");
3557 if (chip->batt_temp_ok.irq < 0) {
3558 pr_err("Unable to get bat-temp-ok irq\n");
3559 return rc;
3560 }
3561 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
3562 qpnp_chg_bat_if_batt_temp_irq_handler,
3563 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
3564 "bat-temp-ok", chip);
3565 if (rc < 0) {
3566 pr_err("Can't request %d bat-temp-ok irq: %d\n",
3567 chip->batt_temp_ok.irq, rc);
3568 return rc;
3569 }
3570
3571 enable_irq_wake(chip->batt_temp_ok.irq);
3572
David Keitel0f35be42013-04-16 11:10:40 -07003573 break;
David Keitel337bd862013-07-15 21:42:58 -07003574 case SMBB_BUCK_SUBTYPE:
3575 case SMBBP_BUCK_SUBTYPE:
3576 case SMBCL_BUCK_SUBTYPE:
David Keitel337bd862013-07-15 21:42:58 -07003577 break;
3578
David Keitel0f35be42013-04-16 11:10:40 -07003579 case SMBB_USB_CHGPTH_SUBTYPE:
3580 case SMBBP_USB_CHGPTH_SUBTYPE:
3581 case SMBCL_USB_CHGPTH_SUBTYPE:
Wu Fenglin04ae6de2013-09-09 19:15:06 +08003582 if (chip->ovp_monitor_enable) {
3583 chip->coarse_det_usb.irq =
3584 spmi_get_irq_byname(spmi,
3585 spmi_resource, "coarse-det-usb");
3586 if (chip->coarse_det_usb.irq < 0) {
3587 pr_err("Can't get coarse-det irq\n");
3588 return rc;
3589 }
3590 rc = devm_request_irq(chip->dev,
3591 chip->coarse_det_usb.irq,
3592 qpnp_chg_coarse_det_usb_irq_handler,
3593 IRQF_TRIGGER_RISING |
3594 IRQF_TRIGGER_FALLING,
3595 "coarse-det-usb", chip);
3596 if (rc < 0) {
3597 pr_err("Can't req %d coarse-det: %d\n",
3598 chip->coarse_det_usb.irq, rc);
3599 return rc;
3600 }
3601 }
3602
David Keitel47185a62013-05-15 18:54:10 -07003603 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003604 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07003605 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003606 pr_err("Unable to get usbin irq\n");
3607 return rc;
3608 }
David Keitel47185a62013-05-15 18:54:10 -07003609 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003610 qpnp_chg_usb_usbin_valid_irq_handler,
3611 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07003612 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003613 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003614 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003615 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003616 return rc;
3617 }
David Keitel344c6972013-04-09 19:28:21 -07003618
David Keitel47185a62013-05-15 18:54:10 -07003619 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07003620 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07003621 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07003622 pr_err("Unable to get chg-gone irq\n");
3623 return rc;
3624 }
David Keitel47185a62013-05-15 18:54:10 -07003625 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07003626 qpnp_chg_usb_chg_gone_irq_handler,
3627 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07003628 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07003629 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003630 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003631 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07003632 return rc;
3633 }
David Keitel47185a62013-05-15 18:54:10 -07003634
David Keitel0b62bdd2013-07-10 17:30:51 -07003635 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
3636 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
3637 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
3638 spmi_resource, "usb-ocp");
3639 if (chip->usb_ocp.irq < 0) {
3640 pr_err("Unable to get usbin irq\n");
3641 return rc;
3642 }
3643 rc = devm_request_irq(chip->dev,
3644 chip->usb_ocp.irq,
3645 qpnp_chg_usb_usb_ocp_irq_handler,
3646 IRQF_TRIGGER_RISING, "usb-ocp", chip);
3647 if (rc < 0) {
3648 pr_err("Can't request %d usb-ocp: %d\n",
3649 chip->usb_ocp.irq, rc);
3650 return rc;
3651 }
3652
3653 enable_irq_wake(chip->usb_ocp.irq);
3654 }
3655
David Keitel47185a62013-05-15 18:54:10 -07003656 enable_irq_wake(chip->usbin_valid.irq);
3657 enable_irq_wake(chip->chg_gone.irq);
David Keitel0f35be42013-04-16 11:10:40 -07003658 break;
3659 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07003660 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07003661 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07003662 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07003663 pr_err("Unable to get dcin irq\n");
3664 return -rc;
3665 }
David Keitel47185a62013-05-15 18:54:10 -07003666 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07003667 qpnp_chg_dc_dcin_valid_irq_handler,
3668 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07003669 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07003670 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07003671 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07003672 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07003673 return rc;
3674 }
3675
David Keitel47185a62013-05-15 18:54:10 -07003676 enable_irq_wake(chip->dcin_valid.irq);
David Keitel0f35be42013-04-16 11:10:40 -07003677 break;
3678 }
3679 }
3680
3681 return rc;
3682}
3683
Xiaozhe Shica289e02013-06-19 13:24:51 -07003684static int
3685qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
3686{
3687 struct bms_battery_data batt_data;
3688 struct device_node *node;
3689 struct qpnp_vadc_result result;
3690 int rc;
3691
3692 node = of_find_node_by_name(chip->spmi->dev.of_node,
3693 "qcom,battery-data");
3694 if (node) {
3695 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07003696 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07003697 if (rc) {
3698 pr_err("error reading batt id channel = %d, rc = %d\n",
3699 LR_MUX2_BAT_ID, rc);
3700 return rc;
3701 }
3702
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07003703 batt_data.max_voltage_uv = -1;
3704 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07003705 rc = of_batterydata_read_data(node,
3706 &batt_data, result.physical);
3707 if (rc) {
3708 pr_err("failed to read battery data: %d\n", rc);
3709 return rc;
3710 }
3711
Xiaozhe Shi34e568232013-07-24 12:47:34 -07003712 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07003713 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07003714 chip->safe_voltage_mv = chip->max_voltage_mv
3715 + MAX_DELTA_VDD_MAX_MV;
3716 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07003717 if (batt_data.iterm_ua >= 0)
3718 chip->term_current = batt_data.iterm_ua / 1000;
3719 }
3720
3721 return 0;
3722}
3723
David Keitel80668952012-07-27 14:25:49 -07003724#define WDOG_EN_BIT BIT(7)
3725static int
3726qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
3727 struct spmi_resource *spmi_resource)
3728{
3729 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07003730 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07003731 struct regulator_init_data *init_data;
3732 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07003733
3734 switch (subtype) {
3735 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003736 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003737 case SMBCL_CHGR_SUBTYPE:
Prasad Sodagudic3678012013-09-23 12:01:19 +05303738 qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
3739
David Keitel80668952012-07-27 14:25:49 -07003740 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
3741 if (rc) {
3742 pr_debug("failed setting min_voltage rc=%d\n", rc);
3743 return rc;
3744 }
David Keitel80668952012-07-27 14:25:49 -07003745 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
3746 if (rc) {
3747 pr_debug("failed setting safe_voltage rc=%d\n", rc);
3748 return rc;
3749 }
David Keitel454ee842013-03-08 16:19:11 -08003750 rc = qpnp_chg_vbatdet_set(chip,
3751 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08003752 if (rc) {
3753 pr_debug("failed setting resume_voltage rc=%d\n", rc);
3754 return rc;
3755 }
David Keitel80668952012-07-27 14:25:49 -07003756 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
3757 if (rc) {
3758 pr_debug("failed setting ibatmax rc=%d\n", rc);
3759 return rc;
3760 }
David Keitel365c4c42013-03-08 16:20:40 -08003761 if (chip->term_current) {
3762 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
3763 if (rc) {
3764 pr_debug("failed setting ibatterm rc=%d\n", rc);
3765 return rc;
3766 }
David Keitel80668952012-07-27 14:25:49 -07003767 }
David Keitel5d44fa52012-12-03 16:37:31 -08003768 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
3769 if (rc) {
3770 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
3771 return rc;
3772 }
David Keitela4b7b592013-04-11 18:34:35 -07003773 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
3774 if (rc) {
3775 pr_debug("failed setting tchg_mins rc=%d\n", rc);
3776 return rc;
3777 }
3778
David Keitel80668952012-07-27 14:25:49 -07003779 /* HACK: Disable wdog */
3780 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
3781 0xFF, 0xA0, 1);
3782
David Keitelb4e43542013-04-09 17:30:41 -07003783 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07003784 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
3785 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07003786 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07003787
David Keitel80668952012-07-27 14:25:49 -07003788 break;
3789 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003790 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003791 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07003792 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
3793 if (rc)
3794 return rc;
3795
David Keitel9201df32013-01-10 18:38:34 -08003796 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07003797 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08003798 BUCK_VBAT_REG_NODE_SEL_BIT,
3799 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
3800 if (rc) {
3801 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
3802 return rc;
3803 }
Xiaozhe Shi20b7abf2013-08-15 13:36:55 -07003804
3805 rc = qpnp_chg_read(chip, &chip->trim_center,
3806 chip->buck_base + BUCK_CTRL_TRIM1, 1);
3807 if (rc) {
3808 pr_debug("failed to read trim center rc=%d\n", rc);
3809 return rc;
3810 }
3811 chip->trim_center >>= 4;
3812 pr_debug("trim center = %02x\n", chip->trim_center);
David Keitel80668952012-07-27 14:25:49 -07003813 break;
3814 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003815 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003816 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07003817 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07003818 switch (chip->bpd_detection) {
3819 case BPD_TYPE_BAT_THM:
3820 reg = BAT_THM_EN;
3821 break;
3822 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07003823 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07003824 break;
3825 case BPD_TYPE_BAT_THM_BAT_ID:
3826 reg = BAT_THM_EN | BAT_ID_EN;
3827 break;
3828 default:
3829 reg = BAT_THM_EN;
3830 break;
3831 }
David Keitel796882d2013-05-14 18:01:11 -07003832
3833 rc = qpnp_chg_masked_write(chip,
3834 chip->bat_if_base + BAT_IF_BPD_CTRL,
3835 BAT_IF_BPD_CTRL_SEL,
3836 reg, 1);
3837 if (rc) {
3838 pr_debug("failed to chose BPD rc=%d\n", rc);
3839 return rc;
3840 }
David Keitel85ae4342013-04-16 11:46:00 -07003841 /* Force on VREF_BAT_THM */
3842 rc = qpnp_chg_masked_write(chip,
3843 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
3844 VREF_BATT_THERM_FORCE_ON,
3845 VREF_BATT_THERM_FORCE_ON, 1);
3846 if (rc) {
3847 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
3848 return rc;
3849 }
Abhijeet Dharmapurikare17309f12013-08-05 12:50:21 -07003850
3851 init_data = of_get_regulator_init_data(chip->dev,
3852 spmi_resource->of_node);
3853
3854 if (init_data->constraints.name) {
3855 rdesc = &(chip->batfet_vreg.rdesc);
3856 rdesc->owner = THIS_MODULE;
3857 rdesc->type = REGULATOR_VOLTAGE;
3858 rdesc->ops = &qpnp_chg_batfet_vreg_ops;
3859 rdesc->name = init_data->constraints.name;
3860
3861 init_data->constraints.valid_ops_mask
3862 |= REGULATOR_CHANGE_STATUS;
3863
3864 chip->batfet_vreg.rdev = regulator_register(rdesc,
3865 chip->dev, init_data, chip,
3866 spmi_resource->of_node);
3867 if (IS_ERR(chip->batfet_vreg.rdev)) {
3868 rc = PTR_ERR(chip->batfet_vreg.rdev);
3869 chip->batfet_vreg.rdev = NULL;
3870 if (rc != -EPROBE_DEFER)
3871 pr_err("batfet reg failed, rc=%d\n",
3872 rc);
3873 return rc;
3874 }
3875 }
David Keitel80668952012-07-27 14:25:49 -07003876 break;
3877 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003878 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003879 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07003880 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07003881 rc = qpnp_chg_masked_write(chip,
3882 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
3883 ENUM_T_STOP_BIT,
3884 ENUM_T_STOP_BIT, 1);
3885 if (rc) {
3886 pr_err("failed to write enum stop rc=%d\n", rc);
3887 return -ENXIO;
3888 }
3889 }
David Keiteld681cda2012-10-02 15:44:21 -07003890
David Keitel6dc4ed42013-05-17 11:08:58 -07003891 init_data = of_get_regulator_init_data(chip->dev,
3892 spmi_resource->of_node);
3893 if (!init_data) {
3894 pr_err("unable to allocate memory\n");
3895 return -ENOMEM;
3896 }
3897
3898 if (init_data->constraints.name) {
3899 if (of_get_property(chip->dev->of_node,
3900 "otg-parent-supply", NULL))
3901 init_data->supply_regulator = "otg-parent";
3902
3903 rdesc = &(chip->otg_vreg.rdesc);
3904 rdesc->owner = THIS_MODULE;
3905 rdesc->type = REGULATOR_VOLTAGE;
3906 rdesc->ops = &qpnp_chg_otg_reg_ops;
3907 rdesc->name = init_data->constraints.name;
3908
3909 init_data->constraints.valid_ops_mask
3910 |= REGULATOR_CHANGE_STATUS;
3911
3912 chip->otg_vreg.rdev = regulator_register(rdesc,
3913 chip->dev, init_data, chip,
3914 spmi_resource->of_node);
3915 if (IS_ERR(chip->otg_vreg.rdev)) {
3916 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07003917 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07003918 if (rc != -EPROBE_DEFER)
3919 pr_err("OTG reg failed, rc=%d\n", rc);
3920 return rc;
3921 }
3922 }
3923
David Keiteld681cda2012-10-02 15:44:21 -07003924 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08003925 chip->usb_chgpth_base + USB_OVP_CTL,
3926 USB_VALID_DEB_20MS,
3927 USB_VALID_DEB_20MS, 1);
3928
3929 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07003930 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
3931 ENUM_T_STOP_BIT,
3932 ENUM_T_STOP_BIT, 1);
3933
David Keitel344c6972013-04-09 19:28:21 -07003934 rc = qpnp_chg_masked_write(chip,
3935 chip->usb_chgpth_base + SEC_ACCESS,
3936 0xFF,
3937 0xA5, 1);
3938
3939 rc = qpnp_chg_masked_write(chip,
3940 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
3941 0xFF,
3942 0x80, 1);
3943
David Keitel0b62bdd2013-07-10 17:30:51 -07003944 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
3945 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
3946 rc = qpnp_chg_masked_write(chip,
3947 chip->usb_chgpth_base + USB_OCP_THR,
3948 OCP_THR_MASK,
3949 OCP_THR_900_MA, 1);
3950 if (rc)
3951 pr_err("Failed to configure OCP rc = %d\n", rc);
3952 }
3953
David Keitel80668952012-07-27 14:25:49 -07003954 break;
3955 case SMBB_DC_CHGPTH_SUBTYPE:
3956 break;
3957 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003958 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07003959 init_data = of_get_regulator_init_data(chip->dev,
3960 spmi_resource->of_node);
3961 if (!init_data) {
3962 pr_err("unable to allocate memory\n");
3963 return -ENOMEM;
3964 }
3965
3966 if (init_data->constraints.name) {
3967 if (of_get_property(chip->dev->of_node,
3968 "boost-parent-supply", NULL))
3969 init_data->supply_regulator = "boost-parent";
3970
3971 rdesc = &(chip->boost_vreg.rdesc);
3972 rdesc->owner = THIS_MODULE;
3973 rdesc->type = REGULATOR_VOLTAGE;
3974 rdesc->ops = &qpnp_chg_boost_reg_ops;
3975 rdesc->name = init_data->constraints.name;
3976
3977 init_data->constraints.valid_ops_mask
3978 |= REGULATOR_CHANGE_STATUS
3979 | REGULATOR_CHANGE_VOLTAGE;
3980
3981 chip->boost_vreg.rdev = regulator_register(rdesc,
3982 chip->dev, init_data, chip,
3983 spmi_resource->of_node);
3984 if (IS_ERR(chip->boost_vreg.rdev)) {
3985 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07003986 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07003987 if (rc != -EPROBE_DEFER)
3988 pr_err("boost reg failed, rc=%d\n", rc);
3989 return rc;
3990 }
3991 }
David Keitel80668952012-07-27 14:25:49 -07003992 break;
3993 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003994 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003995 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07003996 if (subtype == SMBB_MISC_SUBTYPE)
3997 chip->type = SMBB;
3998 else if (subtype == SMBBP_MISC_SUBTYPE)
3999 chip->type = SMBBP;
4000 else if (subtype == SMBCL_MISC_SUBTYPE)
4001 chip->type = SMBCL;
4002
David Keitel80668952012-07-27 14:25:49 -07004003 pr_debug("Setting BOOT_DONE\n");
4004 rc = qpnp_chg_masked_write(chip,
4005 chip->misc_base + CHGR_MISC_BOOT_DONE,
4006 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004007 rc = qpnp_chg_read(chip, &reg,
4008 chip->misc_base + MISC_REVISION2, 1);
4009 if (rc) {
4010 pr_err("failed to read revision register rc=%d\n", rc);
4011 return rc;
4012 }
David Keitel80668952012-07-27 14:25:49 -07004013
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004014 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07004015 break;
4016 default:
4017 pr_err("Invalid peripheral subtype\n");
4018 }
4019 return rc;
4020}
4021
David Keitel112ba9c2013-04-12 18:40:43 -07004022#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
4023do { \
4024 if (retval) \
4025 break; \
4026 \
4027 retval = of_property_read_u32(chip->spmi->dev.of_node, \
4028 "qcom," qpnp_dt_property, \
4029 &chip->prop); \
4030 \
4031 if ((retval == -EINVAL) && optional) \
4032 retval = 0; \
4033 else if (retval) \
4034 pr_err("Error reading " #qpnp_dt_property \
4035 " property rc = %d\n", rc); \
4036} while (0)
4037
4038static int
4039qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
4040{
4041 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004042 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07004043
4044 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
4045 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
4046 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
4047 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
4048 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
4049 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
4050 if (rc)
4051 pr_err("failed to read required dt parameters %d\n", rc);
4052
4053 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
4054 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
4055 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
4056 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
4057 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07004058 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07004059 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
4060 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004061 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
Prasad Sodagudic3678012013-09-23 12:01:19 +05304062 OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07004063
David Keitel112ba9c2013-04-12 18:40:43 -07004064 if (rc)
4065 return rc;
4066
David Keitel796882d2013-05-14 18:01:11 -07004067 rc = of_property_read_string(chip->spmi->dev.of_node,
4068 "qcom,bpd-detection", &bpd);
4069 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07004070 /* Select BAT_THM as default BPD scheme */
4071 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004072 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07004073 } else {
4074 chip->bpd_detection = get_bpd(bpd);
4075 if (chip->bpd_detection < 0) {
4076 pr_err("failed to determine bpd schema %d\n", rc);
4077 return rc;
4078 }
4079 }
4080
David Keitel112ba9c2013-04-12 18:40:43 -07004081 /* Look up JEITA compliance parameters if cool and warm temp provided */
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004082 if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004083 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
4084 if (IS_ERR(chip->adc_tm_dev)) {
4085 rc = PTR_ERR(chip->adc_tm_dev);
4086 if (rc != -EPROBE_DEFER)
4087 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07004088 return rc;
4089 }
4090
4091 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
4092 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
4093 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
4094 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
4095 if (rc)
4096 return rc;
4097 }
4098
David Keitel89c17752013-06-28 14:52:48 -07004099 /* Get the btc-disabled property */
4100 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4101 "qcom,btc-disabled");
4102
David Keitel2586f0a2013-08-20 10:02:26 -07004103 ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
4104 "qcom,ext-ovp-present");
4105
David Keitel112ba9c2013-04-12 18:40:43 -07004106 /* Get the charging-disabled property */
4107 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
4108 "qcom,charging-disabled");
4109
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004110 chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
4111 "qcom,ovp-monitor-en");
4112
David Keitel8b68d2d2013-05-14 23:36:51 -07004113 /* Get the duty-cycle-100p property */
4114 chip->duty_cycle_100p = of_property_read_bool(
4115 chip->spmi->dev.of_node,
4116 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07004117
David Keitel112ba9c2013-04-12 18:40:43 -07004118 /* Get the fake-batt-values property */
4119 chip->use_default_batt_values =
4120 of_property_read_bool(chip->spmi->dev.of_node,
4121 "qcom,use-default-batt-values");
4122
4123 /* Disable charging when faking battery values */
4124 if (chip->use_default_batt_values)
4125 chip->charging_disabled = true;
4126
4127 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
4128 &(chip->thermal_levels));
4129
4130 if (chip->thermal_levels > sizeof(int)) {
4131 chip->thermal_mitigation = kzalloc(
4132 chip->thermal_levels,
4133 GFP_KERNEL);
4134
4135 if (chip->thermal_mitigation == NULL) {
4136 pr_err("thermal mitigation kzalloc() failed.\n");
4137 return rc;
4138 }
4139
4140 chip->thermal_levels /= sizeof(int);
4141 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
4142 "qcom,thermal-mitigation",
4143 chip->thermal_mitigation, chip->thermal_levels);
4144 if (rc) {
4145 pr_err("qcom,thermal-mitigation missing in dt\n");
4146 return rc;
4147 }
4148 }
4149
4150 return rc;
4151}
4152
David Keitel80668952012-07-27 14:25:49 -07004153static int __devinit
4154qpnp_charger_probe(struct spmi_device *spmi)
4155{
4156 u8 subtype;
4157 struct qpnp_chg_chip *chip;
4158 struct resource *resource;
4159 struct spmi_resource *spmi_resource;
4160 int rc = 0;
4161
4162 chip = kzalloc(sizeof *chip, GFP_KERNEL);
4163 if (chip == NULL) {
4164 pr_err("kzalloc() failed.\n");
4165 return -ENOMEM;
4166 }
4167
David Keitelfd305ee2013-07-19 20:19:06 -07004168 chip->prev_usb_max_ma = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07004169 chip->dev = &(spmi->dev);
4170 chip->spmi = spmi;
4171
4172 chip->usb_psy = power_supply_get_by_name("usb");
4173 if (!chip->usb_psy) {
4174 pr_err("usb supply not found deferring probe\n");
4175 rc = -EPROBE_DEFER;
4176 goto fail_chg_enable;
4177 }
4178
David Keitelec3c09802013-06-13 13:05:30 -07004179 mutex_init(&chip->jeita_configure_lock);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004180 spin_lock_init(&chip->usbin_health_monitor_lock);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004181 alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
4182 qpnp_chg_reduce_power_stage_callback);
4183 INIT_WORK(&chip->reduce_power_stage_work,
4184 qpnp_chg_reduce_power_stage_work);
David Keitel6e63bd52013-09-06 18:00:03 -07004185 mutex_init(&chip->batfet_vreg_lock);
4186 INIT_WORK(&chip->batfet_lcl_work,
4187 qpnp_chg_batfet_lcl_work);
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004188 INIT_WORK(&chip->insertion_ocv_work,
4189 qpnp_chg_insertion_ocv_work);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004190
David Keitel112ba9c2013-04-12 18:40:43 -07004191 /* Get all device tree properties */
4192 rc = qpnp_charger_read_dt_props(chip);
4193 if (rc)
David Keitel80668952012-07-27 14:25:49 -07004194 goto fail_chg_enable;
David Keitel3dd5e0f2012-12-12 18:12:36 -08004195
Xiaozhe Shica289e02013-06-19 13:24:51 -07004196 /*
4197 * Check if bat_if is set in DT and make sure VADC is present
4198 * Also try loading the battery data profile if bat_if exists
4199 */
David Keiteldd87a172013-05-29 17:05:43 -07004200 spmi_for_each_container_dev(spmi_resource, spmi) {
4201 if (!spmi_resource) {
4202 pr_err("qpnp_chg: spmi resource absent\n");
4203 rc = -ENXIO;
4204 goto fail_chg_enable;
4205 }
4206
4207 resource = spmi_get_resource(spmi, spmi_resource,
4208 IORESOURCE_MEM, 0);
4209 if (!(resource && resource->start)) {
4210 pr_err("node %s IO resource absent!\n",
4211 spmi->dev.of_node->full_name);
4212 rc = -ENXIO;
4213 goto fail_chg_enable;
4214 }
4215
4216 rc = qpnp_chg_read(chip, &subtype,
4217 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4218 if (rc) {
4219 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4220 goto fail_chg_enable;
4221 }
4222
4223 if (subtype == SMBB_BAT_IF_SUBTYPE ||
4224 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07004225 subtype == SMBCL_BAT_IF_SUBTYPE) {
4226 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
4227 if (IS_ERR(chip->vadc_dev)) {
4228 rc = PTR_ERR(chip->vadc_dev);
4229 if (rc != -EPROBE_DEFER)
4230 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07004231 goto fail_chg_enable;
David Keitel42648fd2013-08-16 17:45:20 -07004232 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07004233
4234 rc = qpnp_chg_load_battery_data(chip);
4235 if (rc)
4236 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07004237 }
4238 }
4239
David Keitel80668952012-07-27 14:25:49 -07004240 spmi_for_each_container_dev(spmi_resource, spmi) {
4241 if (!spmi_resource) {
4242 pr_err("qpnp_chg: spmi resource absent\n");
4243 rc = -ENXIO;
4244 goto fail_chg_enable;
4245 }
4246
4247 resource = spmi_get_resource(spmi, spmi_resource,
4248 IORESOURCE_MEM, 0);
4249 if (!(resource && resource->start)) {
4250 pr_err("node %s IO resource absent!\n",
4251 spmi->dev.of_node->full_name);
4252 rc = -ENXIO;
4253 goto fail_chg_enable;
4254 }
4255
4256 rc = qpnp_chg_read(chip, &subtype,
4257 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
4258 if (rc) {
4259 pr_err("Peripheral subtype read failed rc=%d\n", rc);
4260 goto fail_chg_enable;
4261 }
4262
4263 switch (subtype) {
4264 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004265 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004266 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004267 chip->chgr_base = resource->start;
4268 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4269 if (rc) {
4270 pr_err("Failed to init subtype 0x%x rc=%d\n",
4271 subtype, rc);
4272 goto fail_chg_enable;
4273 }
4274 break;
4275 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004276 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004277 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004278 chip->buck_base = resource->start;
4279 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4280 if (rc) {
4281 pr_err("Failed to init subtype 0x%x rc=%d\n",
4282 subtype, rc);
4283 goto fail_chg_enable;
4284 }
David Keitel344c6972013-04-09 19:28:21 -07004285
4286 rc = qpnp_chg_masked_write(chip,
4287 chip->buck_base + SEC_ACCESS,
4288 0xFF,
4289 0xA5, 1);
4290
4291 rc = qpnp_chg_masked_write(chip,
4292 chip->buck_base + BUCK_VCHG_OV,
4293 0xff,
4294 0x00, 1);
4295
David Keiteldbc949b2013-07-11 10:56:03 -07004296 if (chip->duty_cycle_100p) {
4297 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
4298 1);
4299 if (rc) {
4300 pr_err("failed to set duty cycle %d\n",
4301 rc);
4302 goto fail_chg_enable;
4303 }
4304 }
4305
David Keitel80668952012-07-27 14:25:49 -07004306 break;
4307 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004308 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004309 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004310 chip->bat_if_base = resource->start;
4311 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4312 if (rc) {
4313 pr_err("Failed to init subtype 0x%x rc=%d\n",
4314 subtype, rc);
4315 goto fail_chg_enable;
4316 }
4317 break;
4318 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004319 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004320 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004321 chip->usb_chgpth_base = resource->start;
4322 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4323 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07004324 if (rc != -EPROBE_DEFER)
4325 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07004326 subtype, rc);
4327 goto fail_chg_enable;
4328 }
4329 break;
4330 case SMBB_DC_CHGPTH_SUBTYPE:
4331 chip->dc_chgpth_base = resource->start;
4332 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4333 if (rc) {
4334 pr_err("Failed to init subtype 0x%x rc=%d\n",
4335 subtype, rc);
4336 goto fail_chg_enable;
4337 }
4338 break;
4339 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004340 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004341 chip->boost_base = resource->start;
4342 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4343 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07004344 if (rc != -EPROBE_DEFER)
4345 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07004346 subtype, rc);
4347 goto fail_chg_enable;
4348 }
4349 break;
4350 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08004351 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07004352 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07004353 chip->misc_base = resource->start;
4354 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
4355 if (rc) {
4356 pr_err("Failed to init subtype=0x%x rc=%d\n",
4357 subtype, rc);
4358 goto fail_chg_enable;
4359 }
4360 break;
4361 default:
4362 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
4363 rc = -EINVAL;
4364 goto fail_chg_enable;
4365 }
4366 }
4367 dev_set_drvdata(&spmi->dev, chip);
4368 device_init_wakeup(&spmi->dev, 1);
4369
Xiaozhe Shibc4f9ee2013-08-29 17:03:44 -07004370 chip->insertion_ocv_uv = -EINVAL;
4371 chip->batt_present = qpnp_chg_is_batt_present(chip);
David Keitelf2170cc2013-02-20 17:49:03 -08004372 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08004373 chip->batt_psy.name = "battery";
4374 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
4375 chip->batt_psy.properties = msm_batt_power_props;
4376 chip->batt_psy.num_properties =
4377 ARRAY_SIZE(msm_batt_power_props);
4378 chip->batt_psy.get_property = qpnp_batt_power_get_property;
4379 chip->batt_psy.set_property = qpnp_batt_power_set_property;
4380 chip->batt_psy.property_is_writeable =
4381 qpnp_batt_property_is_writeable;
4382 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07004383 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07004384 chip->batt_psy.supplied_to = pm_batt_supplied_to;
4385 chip->batt_psy.num_supplicants =
4386 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07004387
David Keitelf2170cc2013-02-20 17:49:03 -08004388 rc = power_supply_register(chip->dev, &chip->batt_psy);
4389 if (rc < 0) {
4390 pr_err("batt failed to register rc = %d\n", rc);
4391 goto fail_chg_enable;
4392 }
David Keitel79f4c932013-04-03 16:08:39 -07004393 INIT_WORK(&chip->adc_measure_work,
4394 qpnp_bat_if_adc_measure_work);
David Keitelaa375562013-08-08 09:43:28 -07004395 INIT_WORK(&chip->adc_disable_work,
David Keitelecab15a2013-08-06 15:41:39 -07004396 qpnp_bat_if_adc_disable_work);
David Keitelc7093b02013-02-14 12:50:04 -08004397 }
4398
David Keitel9fd07382013-05-02 15:37:44 -07004399 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07004400 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
Wu Fenglin04ae6de2013-09-09 19:15:06 +08004401 INIT_DELAYED_WORK(&chip->usbin_health_check,
4402 qpnp_usbin_health_check_work);
Xiaozhe Shi8fbbadc2013-07-31 10:59:09 -07004403 INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
David Keitel7ac385e2013-08-19 18:02:40 -07004404 INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
David Keitel5910eea2013-05-02 15:32:25 -07004405
David Keitelf2170cc2013-02-20 17:49:03 -08004406 if (chip->dc_chgpth_base) {
4407 chip->dc_psy.name = "qpnp-dc";
4408 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
4409 chip->dc_psy.supplied_to = pm_power_supplied_to;
4410 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
4411 chip->dc_psy.properties = pm_power_props_mains;
4412 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
4413 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07004414 chip->dc_psy.set_property = qpnp_dc_power_set_property;
4415 chip->dc_psy.property_is_writeable =
4416 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08004417
4418 rc = power_supply_register(chip->dev, &chip->dc_psy);
4419 if (rc < 0) {
4420 pr_err("power_supply_register dc failed rc=%d\n", rc);
4421 goto unregister_batt;
4422 }
David Keitel80668952012-07-27 14:25:49 -07004423 }
4424
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004425 /* Turn on appropriate workaround flags */
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004426 rc = qpnp_chg_setup_flags(chip);
4427 if (rc < 0) {
4428 pr_err("failed to setup flags rc=%d\n", rc);
4429 goto unregister_dc_psy;
4430 }
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08004431
David Keitelf2170cc2013-02-20 17:49:03 -08004432 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08004433 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
4434 if (rc) {
4435 pr_err("Error setting idcmax property %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004436 goto unregister_dc_psy;
David Keitel22ed2232013-01-28 11:04:07 -08004437 }
4438 }
4439
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004440 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0aea18a2013-06-14 18:57:57 -07004441 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07004442 chip->adc_param.low_temp = chip->cool_bat_decidegc;
4443 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08004444 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
4445 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
4446 chip->adc_param.btm_ctx = chip;
4447 chip->adc_param.threshold_notification =
4448 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08004449 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07004450
4451 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004452 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
4453 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07004454 if (rc) {
4455 pr_err("request ADC error %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004456 goto unregister_dc_psy;
David Keitel0c1a4532013-03-21 16:39:06 -07004457 }
David Keitel454ee842013-03-08 16:19:11 -08004458 }
4459 }
David Keitel89c17752013-06-28 14:52:48 -07004460 rc = qpnp_chg_bat_if_configure_btc(chip);
4461 if (rc) {
4462 pr_err("failed to configure btc %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004463 goto unregister_dc_psy;
David Keitel89c17752013-06-28 14:52:48 -07004464 }
David Keitel454ee842013-03-08 16:19:11 -08004465
David Keitel03ee6b52012-10-22 12:25:19 -07004466 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08004467 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07004468 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07004469
David Keitel0f35be42013-04-16 11:10:40 -07004470 rc = qpnp_chg_request_irqs(chip);
4471 if (rc) {
4472 pr_err("failed to request interrupts %d\n", rc);
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004473 goto unregister_dc_psy;
David Keitel0f35be42013-04-16 11:10:40 -07004474 }
4475
David Keitelad980fc2013-07-30 18:12:02 -07004476 qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
4477 qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
David Keitel9fd07382013-05-02 15:37:44 -07004478 power_supply_set_present(chip->usb_psy,
4479 qpnp_chg_is_usb_chg_plugged_in(chip));
4480
David Keitel3c62b472013-05-06 15:38:11 -07004481 /* Set USB psy online to avoid userspace from shutting down if battery
4482 * capacity is at zero and no chargers online. */
4483 if (qpnp_chg_is_usb_chg_plugged_in(chip))
4484 power_supply_set_online(chip->usb_psy, 1);
4485
David Keitel7ac385e2013-08-19 18:02:40 -07004486 schedule_delayed_work(&chip->aicl_check_work,
4487 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel796882d2013-05-14 18:01:11 -07004488 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 -08004489 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07004490 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08004491 qpnp_chg_is_usb_chg_plugged_in(chip),
4492 qpnp_chg_is_dc_chg_plugged_in(chip),
4493 get_prop_batt_present(chip),
4494 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07004495 return 0;
4496
Abhijeet Dharmapurikare7497002013-07-29 11:25:37 -07004497unregister_dc_psy:
4498 if (chip->dc_chgpth_base)
4499 power_supply_unregister(&chip->dc_psy);
David Keitelc7093b02013-02-14 12:50:04 -08004500unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08004501 if (chip->bat_if_base)
4502 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07004503fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07004504 regulator_unregister(chip->otg_vreg.rdev);
4505 regulator_unregister(chip->boost_vreg.rdev);
David Keitelbe208252013-01-31 14:49:25 -08004506 kfree(chip->thermal_mitigation);
David Keitel80668952012-07-27 14:25:49 -07004507 kfree(chip);
4508 dev_set_drvdata(&spmi->dev, NULL);
4509 return rc;
4510}
4511
4512static int __devexit
4513qpnp_charger_remove(struct spmi_device *spmi)
4514{
4515 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
Zhenhua Huang4c593ec2013-08-13 17:22:58 +08004516 if ((chip->cool_bat_decidegc || chip->warm_bat_decidegc)
David Keitel0c1a4532013-03-21 16:39:06 -07004517 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07004518 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
4519 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07004520 }
David Keitel79f4c932013-04-03 16:08:39 -07004521 cancel_work_sync(&chip->adc_measure_work);
David Keitel9fd07382013-05-02 15:37:44 -07004522 cancel_delayed_work_sync(&chip->eoc_work);
David Keitel79f4c932013-04-03 16:08:39 -07004523
David Collinscbb12132013-05-28 10:47:28 -07004524 regulator_unregister(chip->otg_vreg.rdev);
4525 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07004526
David Keitel80668952012-07-27 14:25:49 -07004527 dev_set_drvdata(&spmi->dev, NULL);
4528 kfree(chip);
4529
4530 return 0;
4531}
4532
David Keitel85ae4342013-04-16 11:46:00 -07004533static int qpnp_chg_resume(struct device *dev)
4534{
4535 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
4536 int rc = 0;
4537
David Keitel39093572013-06-05 15:32:30 -07004538 if (chip->bat_if_base) {
4539 rc = qpnp_chg_masked_write(chip,
4540 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4541 VREF_BATT_THERM_FORCE_ON,
4542 VREF_BATT_THERM_FORCE_ON, 1);
4543 if (rc)
4544 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
4545 }
David Keitel85ae4342013-04-16 11:46:00 -07004546
4547 return rc;
4548}
4549
4550static int qpnp_chg_suspend(struct device *dev)
4551{
4552 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
4553 int rc = 0;
4554
David Keitel39093572013-06-05 15:32:30 -07004555 if (chip->bat_if_base) {
4556 rc = qpnp_chg_masked_write(chip,
4557 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
4558 VREF_BATT_THERM_FORCE_ON,
4559 VREF_BAT_THM_ENABLED_FSM, 1);
4560 if (rc)
4561 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
4562 }
David Keitel85ae4342013-04-16 11:46:00 -07004563
4564 return rc;
4565}
4566
David Keitel723d5012013-05-03 13:17:27 -07004567static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07004568 .resume = qpnp_chg_resume,
4569 .suspend = qpnp_chg_suspend,
4570};
4571
David Keitel80668952012-07-27 14:25:49 -07004572static struct spmi_driver qpnp_charger_driver = {
4573 .probe = qpnp_charger_probe,
4574 .remove = __devexit_p(qpnp_charger_remove),
4575 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07004576 .name = QPNP_CHARGER_DEV_NAME,
4577 .owner = THIS_MODULE,
4578 .of_match_table = qpnp_charger_match_table,
4579 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07004580 },
4581};
4582
4583/**
4584 * qpnp_chg_init() - register spmi driver for qpnp-chg
4585 */
4586int __init
4587qpnp_chg_init(void)
4588{
4589 return spmi_driver_register(&qpnp_charger_driver);
4590}
4591module_init(qpnp_chg_init);
4592
4593static void __exit
4594qpnp_chg_exit(void)
4595{
4596 spmi_driver_unregister(&qpnp_charger_driver);
4597}
4598module_exit(qpnp_chg_exit);
4599
4600
4601MODULE_DESCRIPTION("QPNP charger driver");
4602MODULE_LICENSE("GPL v2");
4603MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);