blob: 1deb76595d860402b7e651457622d8219e71daba [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>
David Keitel80668952012-07-27 14:25:49 -070032
33/* Interrupt offsets */
34#define INT_RT_STS(base) (base + 0x10)
35#define INT_SET_TYPE(base) (base + 0x11)
36#define INT_POLARITY_HIGH(base) (base + 0x12)
37#define INT_POLARITY_LOW(base) (base + 0x13)
38#define INT_LATCHED_CLR(base) (base + 0x14)
39#define INT_EN_SET(base) (base + 0x15)
40#define INT_EN_CLR(base) (base + 0x16)
41#define INT_LATCHED_STS(base) (base + 0x18)
42#define INT_PENDING_STS(base) (base + 0x19)
43#define INT_MID_SEL(base) (base + 0x1A)
44#define INT_PRIORITY(base) (base + 0x1B)
45
46/* Peripheral register offsets */
47#define CHGR_CHG_OPTION 0x08
48#define CHGR_ATC_STATUS 0x0A
49#define CHGR_VBAT_STATUS 0x0B
50#define CHGR_IBAT_BMS 0x0C
51#define CHGR_IBAT_STS 0x0D
52#define CHGR_VDD_MAX 0x40
53#define CHGR_VDD_SAFE 0x41
54#define CHGR_VDD_MAX_STEP 0x42
55#define CHGR_IBAT_MAX 0x44
56#define CHGR_IBAT_SAFE 0x45
57#define CHGR_VIN_MIN 0x47
58#define CHGR_VIN_MIN_STEP 0x48
59#define CHGR_CHG_CTRL 0x49
60#define CHGR_CHG_FAILED 0x4A
61#define CHGR_ATC_CTRL 0x4B
62#define CHGR_ATC_FAILED 0x4C
63#define CHGR_VBAT_TRKL 0x50
64#define CHGR_VBAT_WEAK 0x52
65#define CHGR_IBAT_ATC_A 0x54
66#define CHGR_IBAT_ATC_B 0x55
67#define CHGR_IBAT_TERM_CHGR 0x5B
68#define CHGR_IBAT_TERM_BMS 0x5C
69#define CHGR_VBAT_DET 0x5D
70#define CHGR_TTRKL_MAX 0x5F
71#define CHGR_TTRKL_MAX_EN 0x60
72#define CHGR_TCHG_MAX 0x61
73#define CHGR_CHG_WDOG_TIME 0x62
74#define CHGR_CHG_WDOG_DLY 0x63
75#define CHGR_CHG_WDOG_PET 0x64
76#define CHGR_CHG_WDOG_EN 0x65
David Keitel9201df32013-01-10 18:38:34 -080077#define CHGR_IR_DROP_COMPEN 0x67
David Keitel22ed2232013-01-28 11:04:07 -080078#define CHGR_I_MAX_REG 0x44
David Keiteld681cda2012-10-02 15:44:21 -070079#define CHGR_USB_USB_SUSP 0x47
David Keitel6f865cd2012-11-30 15:04:32 -080080#define CHGR_USB_USB_OTG_CTL 0x48
David Keitel80668952012-07-27 14:25:49 -070081#define CHGR_USB_ENUM_T_STOP 0x4E
82#define CHGR_CHG_TEMP_THRESH 0x66
83#define CHGR_BAT_IF_PRES_STATUS 0x08
David Keiteld681cda2012-10-02 15:44:21 -070084#define CHGR_STATUS 0x09
David Keitel80668952012-07-27 14:25:49 -070085#define CHGR_BAT_IF_VCP 0x42
86#define CHGR_BAT_IF_BATFET_CTRL1 0x90
87#define CHGR_MISC_BOOT_DONE 0x42
David Keitel9fd07382013-05-02 15:37:44 -070088#define CHGR_BUCK_COMPARATOR_OVRIDE_1 0xEB
David Keiteld681cda2012-10-02 15:44:21 -070089#define CHGR_BUCK_COMPARATOR_OVRIDE_3 0xED
David Keitel9201df32013-01-10 18:38:34 -080090#define CHGR_BUCK_BCK_VBAT_REG_MODE 0x74
Sridhar Parasuramae183bd2012-12-21 09:28:46 -080091#define MISC_REVISION2 0x01
David Keitel5c3a7702012-12-20 11:13:21 -080092#define USB_OVP_CTL 0x42
David Keitel344c6972013-04-09 19:28:21 -070093#define USB_CHG_GONE_REV_BST 0xED
94#define BUCK_VCHG_OV 0x77
95#define BUCK_TEST_SMBC_MODES 0xE6
David Keiteld681cda2012-10-02 15:44:21 -070096#define SEC_ACCESS 0xD0
David Keitel85ae4342013-04-16 11:46:00 -070097#define BAT_IF_VREF_BAT_THM_CTRL 0x4A
David Keitel796882d2013-05-14 18:01:11 -070098#define BAT_IF_BPD_CTRL 0x48
David Keitel6dc4ed42013-05-17 11:08:58 -070099#define BOOST_VSET 0x41
100#define BOOST_ENABLE_CONTROL 0x46
David Keitel33f58952013-05-20 16:17:36 -0700101#define COMP_OVR1 0xEA
David Keitel89c17752013-06-28 14:52:48 -0700102#define BAT_IF_BTC_CTRL 0x49
David Keitel0b62bdd2013-07-10 17:30:51 -0700103#define USB_OCP_THR 0x52
104#define USB_OCP_CLR 0x53
Zhenhua Huang2a0ee352013-07-23 01:55:43 +0800105#define BAT_IF_TEMP_STATUS 0x09
David Keitel33f58952013-05-20 16:17:36 -0700106
David Keitel80668952012-07-27 14:25:49 -0700107#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700108
David Keitelf2170cc2013-02-20 17:49:03 -0800109/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700110#define SMBB_CHGR_SUBTYPE 0x01
111#define SMBB_BUCK_SUBTYPE 0x02
112#define SMBB_BAT_IF_SUBTYPE 0x03
113#define SMBB_USB_CHGPTH_SUBTYPE 0x04
114#define SMBB_DC_CHGPTH_SUBTYPE 0x05
115#define SMBB_BOOST_SUBTYPE 0x06
116#define SMBB_MISC_SUBTYPE 0x07
117
David Keitelf2170cc2013-02-20 17:49:03 -0800118/* SMBB peripheral subtype values */
119#define SMBBP_CHGR_SUBTYPE 0x31
120#define SMBBP_BUCK_SUBTYPE 0x32
121#define SMBBP_BAT_IF_SUBTYPE 0x33
122#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
123#define SMBBP_BOOST_SUBTYPE 0x36
124#define SMBBP_MISC_SUBTYPE 0x37
125
David Keitel46c9f7b2013-04-02 19:54:12 -0700126/* SMBCL peripheral subtype values */
127#define SMBCL_CHGR_SUBTYPE 0x41
128#define SMBCL_BUCK_SUBTYPE 0x42
129#define SMBCL_BAT_IF_SUBTYPE 0x43
130#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
131#define SMBCL_MISC_SUBTYPE 0x47
132
David Keitel80668952012-07-27 14:25:49 -0700133#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
134
David Keitelb80eda82012-10-15 10:49:11 -0700135/* Status bits and masks */
136#define CHGR_BOOT_DONE BIT(7)
137#define CHGR_CHG_EN BIT(7)
138#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800139#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800140#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700141#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700142#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700143#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700144#define REV_BST_DETECTED BIT(0)
145#define BAT_THM_EN BIT(1)
146#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700147#define BOOST_PWR_EN BIT(7)
David Keitel0b62bdd2013-07-10 17:30:51 -0700148#define OCP_CLR_BIT BIT(7)
149#define OCP_THR_MASK 0x03
150#define OCP_THR_900_MA 0x02
151#define OCP_THR_500_MA 0x01
152#define OCP_THR_200_MA 0x00
David Keitelb80eda82012-10-15 10:49:11 -0700153
David Keitel80668952012-07-27 14:25:49 -0700154/* Interrupt definitions */
155/* smbb_chg_interrupts */
156#define CHG_DONE_IRQ BIT(7)
157#define CHG_FAILED_IRQ BIT(6)
158#define FAST_CHG_ON_IRQ BIT(5)
159#define TRKL_CHG_ON_IRQ BIT(4)
160#define STATE_CHANGE_ON_IR BIT(3)
161#define CHGWDDOG_IRQ BIT(2)
162#define VBAT_DET_HI_IRQ BIT(1)
163#define VBAT_DET_LOW_IRQ BIT(0)
164
165/* smbb_buck_interrupts */
166#define VDD_LOOP_IRQ BIT(6)
167#define IBAT_LOOP_IRQ BIT(5)
168#define ICHG_LOOP_IRQ BIT(4)
169#define VCHG_LOOP_IRQ BIT(3)
170#define OVERTEMP_IRQ BIT(2)
171#define VREF_OV_IRQ BIT(1)
172#define VBAT_OV_IRQ BIT(0)
173
174/* smbb_bat_if_interrupts */
175#define PSI_IRQ BIT(4)
176#define VCP_ON_IRQ BIT(3)
177#define BAT_FET_ON_IRQ BIT(2)
178#define BAT_TEMP_OK_IRQ BIT(1)
179#define BATT_PRES_IRQ BIT(0)
180
181/* smbb_usb_interrupts */
182#define CHG_GONE_IRQ BIT(2)
183#define USBIN_VALID_IRQ BIT(1)
184#define COARSE_DET_USB_IRQ BIT(0)
185
186/* smbb_dc_interrupts */
187#define DCIN_VALID_IRQ BIT(1)
188#define COARSE_DET_DC_IRQ BIT(0)
189
190/* smbb_boost_interrupts */
191#define LIMIT_ERROR_IRQ BIT(1)
192#define BOOST_PWR_OK_IRQ BIT(0)
193
194/* smbb_misc_interrupts */
195#define TFTWDOG_IRQ BIT(0)
196
David Keitelfe51cb92013-04-02 19:42:58 -0700197/* SMBB types */
198#define SMBB BIT(1)
199#define SMBBP BIT(2)
200#define SMBCL BIT(3)
201
David Keiteld681cda2012-10-02 15:44:21 -0700202/* Workaround flags */
203#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700204#define BOOST_FLASH_WA BIT(1)
David Keiteld681cda2012-10-02 15:44:21 -0700205
David Keitel47185a62013-05-15 18:54:10 -0700206struct qpnp_chg_irq {
207 unsigned int irq;
208 unsigned long disabled;
209};
210
David Keitel6dc4ed42013-05-17 11:08:58 -0700211struct qpnp_chg_regulator {
212 struct regulator_desc rdesc;
213 struct regulator_dev *rdev;
214};
215
David Keitel80668952012-07-27 14:25:49 -0700216/**
217 * struct qpnp_chg_chip - device information
218 * @dev: device pointer to access the parent
219 * @spmi: spmi pointer to access spmi information
220 * @chgr_base: charger peripheral base address
221 * @buck_base: buck peripheral base address
222 * @bat_if_base: battery interface peripheral base address
223 * @usb_chgpth_base: USB charge path peripheral base address
224 * @dc_chgpth_base: DC charge path peripheral base address
225 * @boost_base: boost peripheral base address
226 * @misc_base: misc peripheral base address
227 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800228 * @bat_is_cool: indicates that battery is cool
229 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700230 * @chg_done: indicates that charging is completed
231 * @usb_present: present status of usb
232 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800233 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800234 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700235 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700236 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800237 * @min_voltage_mv: min battery voltage before turning the FET on
David Keitel454ee842013-03-08 16:19:11 -0800238 * @max_bat_chg_current: maximum battery charge current in mA
239 * @warm_bat_chg_ma: warm battery maximum charge current in mA
240 * @cool_bat_chg_ma: cool battery maximum charge current in mA
241 * @warm_bat_mv: warm temperature battery target voltage
242 * @cool_bat_mv: cool temperature battery target voltage
243 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700244 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800245 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800246 * @maxinput_usb_ma: Maximum Input current USB
247 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700248 * @hot_batt_p Hot battery threshold setting
249 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700250 * @warm_bat_decidegc Warm battery temperature in degree Celsius
251 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700252 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700253 * @type: SMBB type
254 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800255 * @thermal_levels amount of thermal mitigation levels
256 * @thermal_mitigation thermal mitigation level values
257 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700258 * @dc_psy power supply to export information to userspace
259 * @usb_psy power supply to export information to userspace
260 * @bms_psy power supply to export information to userspace
261 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700262 * @flags: flags to activate specific workarounds
263 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700264 *
265 */
266struct qpnp_chg_chip {
267 struct device *dev;
268 struct spmi_device *spmi;
269 u16 chgr_base;
270 u16 buck_base;
271 u16 bat_if_base;
272 u16 usb_chgpth_base;
273 u16 dc_chgpth_base;
274 u16 boost_base;
275 u16 misc_base;
276 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700277 struct qpnp_chg_irq usbin_valid;
David Keitel0b62bdd2013-07-10 17:30:51 -0700278 struct qpnp_chg_irq usb_ocp;
David Keitel47185a62013-05-15 18:54:10 -0700279 struct qpnp_chg_irq dcin_valid;
280 struct qpnp_chg_irq chg_gone;
281 struct qpnp_chg_irq chg_fastchg;
282 struct qpnp_chg_irq chg_trklchg;
283 struct qpnp_chg_irq chg_failed;
284 struct qpnp_chg_irq chg_vbatdet_lo;
285 struct qpnp_chg_irq batt_pres;
David Keitel337bd862013-07-15 21:42:58 -0700286 struct qpnp_chg_irq vchg_loop;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700287 struct qpnp_chg_irq batt_temp_ok;
David Keitel454ee842013-03-08 16:19:11 -0800288 bool bat_is_cool;
289 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700290 bool chg_done;
291 bool usb_present;
292 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800293 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700294 bool charging_disabled;
David Keitel89c17752013-06-28 14:52:48 -0700295 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800296 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700297 bool duty_cycle_100p;
David Keitel796882d2013-05-14 18:01:11 -0700298 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700299 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800300 unsigned int warm_bat_chg_ma;
301 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700302 unsigned int safe_voltage_mv;
303 unsigned int max_voltage_mv;
304 unsigned int min_voltage_mv;
David Keitelfd305ee2013-07-19 20:19:06 -0700305 int prev_usb_max_ma;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700306 int set_vddmax_mv;
307 int delta_vddmax_mv;
David Keitel454ee842013-03-08 16:19:11 -0800308 unsigned int warm_bat_mv;
309 unsigned int cool_bat_mv;
310 unsigned int resume_delta_mv;
David Keitel9fd07382013-05-02 15:37:44 -0700311 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700312 int soc_resume_limit;
313 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800314 unsigned int maxinput_usb_ma;
315 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700316 unsigned int hot_batt_p;
317 unsigned int cold_batt_p;
David Keitel27a97e62013-06-24 13:57:12 -0700318 int warm_bat_decidegc;
319 int cool_bat_decidegc;
David Keitel5d44fa52012-12-03 16:37:31 -0800320 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700321 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700322 unsigned int type;
323 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800324 unsigned int thermal_levels;
325 unsigned int therm_lvl_sel;
326 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700327 struct power_supply dc_psy;
328 struct power_supply *usb_psy;
329 struct power_supply *bms_psy;
330 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700331 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800332 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700333 struct work_struct adc_measure_work;
David Keitel344c6972013-04-09 19:28:21 -0700334 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700335 struct delayed_work eoc_work;
336 struct wake_lock eoc_wake_lock;
David Keitel6dc4ed42013-05-17 11:08:58 -0700337 struct qpnp_chg_regulator otg_vreg;
338 struct qpnp_chg_regulator boost_vreg;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700339 struct qpnp_vadc_chip *vadc_dev;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -0700340 struct qpnp_adc_tm_chip *adc_tm_dev;
David Keitelec3c09802013-06-13 13:05:30 -0700341 struct mutex jeita_configure_lock;
David Keitel80668952012-07-27 14:25:49 -0700342};
343
David Keitel47185a62013-05-15 18:54:10 -0700344
David Keitel80668952012-07-27 14:25:49 -0700345static struct of_device_id qpnp_charger_match_table[] = {
346 { .compatible = QPNP_CHARGER_DEV_NAME, },
347 {}
348};
349
David Keitel0ef282b2013-05-29 16:04:57 -0700350enum bpd_type {
351 BPD_TYPE_BAT_ID,
352 BPD_TYPE_BAT_THM,
353 BPD_TYPE_BAT_THM_BAT_ID,
354};
David Keitel796882d2013-05-14 18:01:11 -0700355
David Keitel0ef282b2013-05-29 16:04:57 -0700356static const char * const bpd_label[] = {
357 [BPD_TYPE_BAT_ID] = "bpd_id",
358 [BPD_TYPE_BAT_THM] = "bpd_thm",
359 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700360};
361
David Keitel89c17752013-06-28 14:52:48 -0700362enum btc_type {
363 HOT_THD_25_PCT = 25,
364 HOT_THD_35_PCT = 35,
365 COLD_THD_70_PCT = 70,
366 COLD_THD_80_PCT = 80,
367};
368
369static u8 btc_value[] = {
370 [HOT_THD_25_PCT] = 0x0,
371 [HOT_THD_35_PCT] = BIT(0),
372 [COLD_THD_70_PCT] = 0x0,
373 [COLD_THD_80_PCT] = BIT(1),
374};
375
376 static inline int
David Keitel796882d2013-05-14 18:01:11 -0700377get_bpd(const char *name)
378{
379 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700380 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
381 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700382 return i;
383 }
384 return -EINVAL;
385}
386
David Keitel80668952012-07-27 14:25:49 -0700387static int
388qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
389 u16 base, int count)
390{
David Keitel39093572013-06-05 15:32:30 -0700391 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700392 struct spmi_device *spmi = chip->spmi;
393
David Keitel39093572013-06-05 15:32:30 -0700394 if (base == 0) {
395 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
396 base, spmi->sid, rc);
397 return -EINVAL;
398 }
399
400 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700401 if (rc) {
402 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
403 spmi->sid, rc);
404 return rc;
405 }
406 return 0;
407}
408
409static int
410qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
411 u16 base, int count)
412{
David Keitel39093572013-06-05 15:32:30 -0700413 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700414 struct spmi_device *spmi = chip->spmi;
415
David Keitel39093572013-06-05 15:32:30 -0700416 if (base == 0) {
417 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
418 base, spmi->sid, rc);
419 return -EINVAL;
420 }
421
422 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700423 if (rc) {
424 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
425 base, spmi->sid, rc);
426 return rc;
427 }
428
429 return 0;
430}
431
432static int
433qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
434 u8 mask, u8 val, int count)
435{
436 int rc;
437 u8 reg;
438
439 rc = qpnp_chg_read(chip, &reg, base, count);
440 if (rc) {
441 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
442 return rc;
443 }
444 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
445
446 reg &= ~mask;
447 reg |= val & mask;
448
449 pr_debug("Writing 0x%x\n", reg);
450
451 rc = qpnp_chg_write(chip, &reg, base, count);
452 if (rc) {
453 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
454 return rc;
455 }
456
457 return 0;
458}
459
David Keitel47185a62013-05-15 18:54:10 -0700460static void
461qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
462{
463 if (__test_and_clear_bit(0, &irq->disabled)) {
464 pr_debug("number = %d\n", irq->irq);
465 enable_irq(irq->irq);
466 }
467}
468
469static void
470qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
471{
472 if (!__test_and_set_bit(0, &irq->disabled)) {
473 pr_debug("number = %d\n", irq->irq);
474 disable_irq_nosync(irq->irq);
475 }
476}
477
David Keitel6f865cd2012-11-30 15:04:32 -0800478#define USB_OTG_EN_BIT BIT(0)
479static int
480qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
481{
482 u8 usb_otg_en;
483 int rc;
484
485 rc = qpnp_chg_read(chip, &usb_otg_en,
486 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
487 1);
488
489 if (rc) {
490 pr_err("spmi read failed: addr=%03X, rc=%d\n",
491 chip->usb_chgpth_base + CHGR_STATUS, rc);
492 return rc;
493 }
494 pr_debug("usb otg en 0x%x\n", usb_otg_en);
495
496 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
497}
498
David Keitel42ae0aa2013-03-08 16:20:10 -0800499static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700500qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
501{
502 u8 boost_en_ctl;
503 int rc;
504
505 rc = qpnp_chg_read(chip, &boost_en_ctl,
506 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
507 if (rc) {
508 pr_err("spmi read failed: addr=%03X, rc=%d\n",
509 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
510 return rc;
511 }
512
513 pr_debug("boost en 0x%x\n", boost_en_ctl);
514
515 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
516}
517
518static int
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700519qpnp_chg_is_batt_temp_ok(struct qpnp_chg_chip *chip)
520{
521 u8 batt_rt_sts;
522 int rc;
523
524 rc = qpnp_chg_read(chip, &batt_rt_sts,
525 INT_RT_STS(chip->bat_if_base), 1);
526 if (rc) {
527 pr_err("spmi read failed: addr=%03X, rc=%d\n",
528 INT_RT_STS(chip->bat_if_base), rc);
529 return rc;
530 }
531
532 return (batt_rt_sts & BAT_TEMP_OK_IRQ) ? 1 : 0;
533}
534
535static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800536qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
537{
538 u8 batt_pres_rt_sts;
539 int rc;
540
541 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
542 INT_RT_STS(chip->bat_if_base), 1);
543 if (rc) {
544 pr_err("spmi read failed: addr=%03X, rc=%d\n",
545 INT_RT_STS(chip->bat_if_base), rc);
546 return rc;
547 }
548
549 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
550}
551
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -0700552static int
553qpnp_chg_is_batfet_closed(struct qpnp_chg_chip *chip)
554{
555 u8 batfet_closed_rt_sts;
556 int rc;
557
558 rc = qpnp_chg_read(chip, &batfet_closed_rt_sts,
559 INT_RT_STS(chip->bat_if_base), 1);
560 if (rc) {
561 pr_err("spmi read failed: addr=%03X, rc=%d\n",
562 INT_RT_STS(chip->bat_if_base), rc);
563 return rc;
564 }
565
566 return (batfet_closed_rt_sts & BAT_FET_ON_IRQ) ? 1 : 0;
567}
568
David Keiteld681cda2012-10-02 15:44:21 -0700569#define USB_VALID_BIT BIT(7)
David Keitel80668952012-07-27 14:25:49 -0700570static int
571qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
572{
573 u8 usbin_valid_rt_sts;
574 int rc;
575
576 rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
David Keiteld681cda2012-10-02 15:44:21 -0700577 chip->usb_chgpth_base + CHGR_STATUS , 1);
David Keitel80668952012-07-27 14:25:49 -0700578
579 if (rc) {
580 pr_err("spmi read failed: addr=%03X, rc=%d\n",
David Keiteld681cda2012-10-02 15:44:21 -0700581 chip->usb_chgpth_base + CHGR_STATUS, rc);
David Keitel80668952012-07-27 14:25:49 -0700582 return rc;
583 }
584 pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
585
David Keiteld681cda2012-10-02 15:44:21 -0700586 return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700587}
588
589static int
590qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
591{
592 u8 dcin_valid_rt_sts;
593 int rc;
594
David Keitelf2170cc2013-02-20 17:49:03 -0800595 if (!chip->dc_chgpth_base)
596 return 0;
597
David Keitel80668952012-07-27 14:25:49 -0700598 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
599 INT_RT_STS(chip->dc_chgpth_base), 1);
600 if (rc) {
601 pr_err("spmi read failed: addr=%03X, rc=%d\n",
602 INT_RT_STS(chip->dc_chgpth_base), rc);
603 return rc;
604 }
605
606 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
607}
608
David Keitel22ed2232013-01-28 11:04:07 -0800609#define QPNP_CHG_I_MAX_MIN_100 100
610#define QPNP_CHG_I_MAX_MIN_150 150
611#define QPNP_CHG_I_MAX_MIN_MA 200
612#define QPNP_CHG_I_MAX_MAX_MA 2500
613#define QPNP_CHG_I_MAXSTEP_MA 100
614static int
615qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
616{
617 int rc = 0;
618 u8 dc = 0;
619
620 if (mA < QPNP_CHG_I_MAX_MIN_100
621 || mA > QPNP_CHG_I_MAX_MAX_MA) {
622 pr_err("bad mA=%d asked to set\n", mA);
623 return -EINVAL;
624 }
625
626 if (mA == QPNP_CHG_I_MAX_MIN_100) {
627 dc = 0x00;
628 pr_debug("current=%d setting %02x\n", mA, dc);
629 return qpnp_chg_write(chip, &dc,
630 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
631 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
632 dc = 0x01;
633 pr_debug("current=%d setting %02x\n", mA, dc);
634 return qpnp_chg_write(chip, &dc,
635 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
636 }
637
638 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
639
640 pr_debug("current=%d setting 0x%x\n", mA, dc);
641 rc = qpnp_chg_write(chip, &dc,
642 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
643
644 return rc;
645}
646
David Keitel80668952012-07-27 14:25:49 -0700647static int
648qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
649{
David Keiteld681cda2012-10-02 15:44:21 -0700650 int rc = 0;
651 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700652
David Keitel22ed2232013-01-28 11:04:07 -0800653 if (mA < QPNP_CHG_I_MAX_MIN_100
654 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700655 pr_err("bad mA=%d asked to set\n", mA);
656 return -EINVAL;
657 }
658
David Keitel22ed2232013-01-28 11:04:07 -0800659 if (mA == QPNP_CHG_I_MAX_MIN_100) {
660 usb_reg = 0x00;
661 pr_debug("current=%d setting %02x\n", mA, usb_reg);
662 return qpnp_chg_write(chip, &usb_reg,
663 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
664 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
665 usb_reg = 0x01;
666 pr_debug("current=%d setting %02x\n", mA, usb_reg);
667 return qpnp_chg_write(chip, &usb_reg,
668 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
669 }
670
671 /* Impose input current limit */
672 if (chip->maxinput_usb_ma)
673 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
674
675 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -0700676
David Keiteld681cda2012-10-02 15:44:21 -0700677 if (chip->flags & CHG_FLAGS_VCP_WA) {
678 temp = 0xA5;
679 rc = qpnp_chg_write(chip, &temp,
680 chip->buck_base + SEC_ACCESS, 1);
681 rc = qpnp_chg_masked_write(chip,
682 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
683 0x0C, 0x0C, 1);
684 }
685
David Keitel80668952012-07-27 14:25:49 -0700686 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -0700687 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -0800688 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -0700689
690 if (chip->flags & CHG_FLAGS_VCP_WA) {
691 temp = 0xA5;
692 udelay(200);
693 rc = qpnp_chg_write(chip, &temp,
694 chip->buck_base + SEC_ACCESS, 1);
695 rc = qpnp_chg_masked_write(chip,
696 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
697 0x0C, 0x00, 1);
698 }
699
700 return rc;
701}
702
David Keitel337bd862013-07-15 21:42:58 -0700703#define QPNP_CHG_VINMIN_MIN_MV 4200
704#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
705#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
706#define QPNP_CHG_VINMIN_MAX_MV 9600
707#define QPNP_CHG_VINMIN_STEP_MV 50
708#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
709#define QPNP_CHG_VINMIN_MASK 0x1F
710#define QPNP_CHG_VINMIN_MIN_VAL 0x10
711static int
712qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
713{
714 u8 temp;
715
716 if (voltage < QPNP_CHG_VINMIN_MIN_MV
717 || voltage > QPNP_CHG_VINMIN_MAX_MV) {
718 pr_err("bad mV=%d asked to set\n", voltage);
719 return -EINVAL;
720 }
721 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
722 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
723 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
724 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
725 } else {
726 temp = QPNP_CHG_VINMIN_MIN_VAL;
727 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
728 / QPNP_CHG_VINMIN_STEP_MV;
729 }
730
731 pr_debug("voltage=%d setting %02x\n", voltage, temp);
732 return qpnp_chg_masked_write(chip,
733 chip->chgr_base + CHGR_VIN_MIN,
734 QPNP_CHG_VINMIN_MASK, temp, 1);
735}
736
737static int
738qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
739{
740 int rc, vin_min_mv;
741 u8 vin_min;
742
743 rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
744 if (rc) {
745 pr_err("failed to read VIN_MIN rc=%d\n", rc);
746 return 0;
747 }
748
749 if (vin_min == 0)
750 vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
751 else if (vin_min > QPNP_CHG_VINMIN_HIGH_MIN_VAL)
752 vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
753 (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
754 * QPNP_CHG_VINMIN_STEP_HIGH_MV;
755 else
756 vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
757 (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
758 * QPNP_CHG_VINMIN_STEP_MV;
759 pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
760
761 return vin_min_mv;
762}
763
764static int
765qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
766{
767 int rc, iusbmax_ma;
768 u8 iusbmax;
769
770 rc = qpnp_chg_read(chip, &iusbmax,
771 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
772 if (rc) {
773 pr_err("failed to read IUSB_MAX rc=%d\n", rc);
774 return 0;
775 }
776
777 if (iusbmax == 0)
778 iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
779 else if (iusbmax == 0x01)
780 iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
781 else
782 iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
783
784 pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
785
786 return iusbmax_ma;
787}
788
David Keiteld681cda2012-10-02 15:44:21 -0700789#define USB_SUSPEND_BIT BIT(0)
790static int
791qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
792{
793 return qpnp_chg_masked_write(chip,
794 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
795 USB_SUSPEND_BIT,
796 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -0700797}
798
David Keitel344c6972013-04-09 19:28:21 -0700799static int
800qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
801{
802 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
803 CHGR_CHG_EN,
804 enable ? CHGR_CHG_EN : 0, 1);
805}
806
807static int
808qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
809{
810 /* Don't run on battery for batteryless hardware */
811 if (chip->use_default_batt_values)
812 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -0700813 /* Don't force on battery if battery is not present */
814 if (!qpnp_chg_is_batt_present(chip))
815 return 0;
David Keitel344c6972013-04-09 19:28:21 -0700816
817 /* This bit forces the charger to run off of the battery rather
818 * than a connected charger */
819 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
820 CHGR_ON_BAT_FORCE_BIT,
821 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
822}
823
David Keitel8b68d2d2013-05-14 23:36:51 -0700824#define BUCK_DUTY_MASK_100P 0x30
825static int
826qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
827{
828 int rc;
829
830 pr_debug("enable: %d\n", enable);
831
832 rc = qpnp_chg_masked_write(chip,
833 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
834 if (rc) {
835 pr_debug("failed to write sec access rc=%d\n", rc);
836 return rc;
837 }
838
839 rc = qpnp_chg_masked_write(chip,
840 chip->buck_base + BUCK_TEST_SMBC_MODES,
841 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
842 if (rc) {
843 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
844 return rc;
845 }
846
847 return rc;
848}
849
David Keitel9fd07382013-05-02 15:37:44 -0700850#define COMPATATOR_OVERRIDE_0 0x80
851static int
852qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
853{
854 int rc;
855
856 pr_debug("toggle: %d\n", enable);
857
858 rc = qpnp_chg_masked_write(chip,
859 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
860 if (rc) {
861 pr_debug("failed to write sec access rc=%d\n", rc);
862 return rc;
863 }
864
865 rc = qpnp_chg_masked_write(chip,
866 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
867 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
868 if (rc) {
869 pr_debug("failed to toggle chg done override rc=%d\n", rc);
870 return rc;
871 }
872
873 return rc;
874}
875
876#define QPNP_CHG_VBATDET_MIN_MV 3240
877#define QPNP_CHG_VBATDET_MAX_MV 5780
878#define QPNP_CHG_VBATDET_STEP_MV 20
879static int
880qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
881{
882 u8 temp;
883
884 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
885 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
886 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
887 return -EINVAL;
888 }
889 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
890 / QPNP_CHG_VBATDET_STEP_MV;
891
892 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
893 return qpnp_chg_write(chip, &temp,
894 chip->chgr_base + CHGR_VBAT_DET, 1);
895}
896
David Keitel344c6972013-04-09 19:28:21 -0700897static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700898qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
899{
900 if (chip->bat_is_cool)
901 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
902 - chip->resume_delta_mv);
903 else if (chip->bat_is_warm)
904 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
905 - chip->resume_delta_mv);
906 else if (chip->resuming_charging)
907 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
908 + chip->resume_delta_mv);
909 else
910 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
911 - chip->resume_delta_mv);
912}
913
914static void
David Keitel344c6972013-04-09 19:28:21 -0700915qpnp_arb_stop_work(struct work_struct *work)
916{
917 struct delayed_work *dwork = to_delayed_work(work);
918 struct qpnp_chg_chip *chip = container_of(dwork,
919 struct qpnp_chg_chip, arb_stop_work);
920
David Keitel9fd07382013-05-02 15:37:44 -0700921 if (!chip->chg_done)
922 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -0700923 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
924}
925
926static void
927qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -0700928{
929 struct qpnp_chg_chip *chip = container_of(work,
930 struct qpnp_chg_chip, adc_measure_work);
931
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -0700932 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel79f4c932013-04-03 16:08:39 -0700933 pr_err("request ADC error\n");
934}
935
David Keitel337bd862013-07-15 21:42:58 -0700936static irqreturn_t
937qpnp_chg_buck_vchg_loop_irq_handler(int irq, void *_chip)
938{
939 struct qpnp_chg_chip *chip = _chip;
940
941 if (chip->bat_if_base)
942 power_supply_changed(&chip->batt_psy);
943
944 return IRQ_HANDLED;
945}
946
David Keitel9fd07382013-05-02 15:37:44 -0700947#define EOC_CHECK_PERIOD_MS 10000
948static irqreturn_t
949qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
950{
951 struct qpnp_chg_chip *chip = _chip;
952 u8 chg_sts = 0;
953 int rc;
954
955 pr_debug("vbatdet-lo triggered\n");
956
957 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
958 if (rc)
959 pr_err("failed to read chg_sts rc=%d\n", rc);
960
961 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
962 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
963 schedule_delayed_work(&chip->eoc_work,
964 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
965 wake_lock(&chip->eoc_wake_lock);
David Keitel47185a62013-05-15 18:54:10 -0700966 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -0700967 } else {
968 qpnp_chg_charge_en(chip, !chip->charging_disabled);
969 }
970
971 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -0700972 if (chip->dc_chgpth_base)
973 power_supply_changed(&chip->dc_psy);
974 if (chip->bat_if_base)
975 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700976 return IRQ_HANDLED;
977}
978
David Keitel344c6972013-04-09 19:28:21 -0700979#define ARB_STOP_WORK_MS 1000
980static irqreturn_t
981qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
982{
983 struct qpnp_chg_chip *chip = _chip;
984
985 pr_debug("chg_gone triggered\n");
986 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
987 qpnp_chg_charge_en(chip, 0);
David Keitel9fd07382013-05-02 15:37:44 -0700988 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -0700989 schedule_delayed_work(&chip->arb_stop_work,
990 msecs_to_jiffies(ARB_STOP_WORK_MS));
991 }
992
993 return IRQ_HANDLED;
994}
995
David Keitel0b62bdd2013-07-10 17:30:51 -0700996static irqreturn_t
997qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
998{
999 struct qpnp_chg_chip *chip = _chip;
1000 int rc;
1001
1002 pr_debug("usb-ocp triggered\n");
1003
1004 rc = qpnp_chg_masked_write(chip,
1005 chip->usb_chgpth_base + USB_OCP_CLR,
1006 OCP_CLR_BIT,
1007 OCP_CLR_BIT, 1);
1008 if (rc)
1009 pr_err("Failed to clear OCP bit rc = %d\n", rc);
1010
1011 /* force usb ovp fet off */
1012 rc = qpnp_chg_masked_write(chip,
1013 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1014 USB_OTG_EN_BIT,
1015 USB_OTG_EN_BIT, 1);
1016 if (rc)
1017 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1018
1019 return IRQ_HANDLED;
1020}
1021
David Keitel80668952012-07-27 14:25:49 -07001022#define ENUM_T_STOP_BIT BIT(0)
1023static irqreturn_t
1024qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
1025{
1026 struct qpnp_chg_chip *chip = _chip;
David Keitel6f865cd2012-11-30 15:04:32 -08001027 int usb_present, host_mode;
David Keitel80668952012-07-27 14:25:49 -07001028
1029 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -08001030 host_mode = qpnp_chg_is_otg_en_set(chip);
1031 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
1032 usb_present, host_mode);
1033
1034 /* In host mode notifications cmoe from USB supply */
1035 if (host_mode)
1036 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -07001037
1038 if (chip->usb_present ^ usb_present) {
1039 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -07001040 if (!usb_present) {
David Keitel344c6972013-04-09 19:28:21 -07001041 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel9fd07382013-05-02 15:37:44 -07001042 chip->chg_done = false;
David Keitelfd305ee2013-07-19 20:19:06 -07001043 chip->prev_usb_max_ma = -EINVAL;
David Keitel9fd07382013-05-02 15:37:44 -07001044 } else {
1045 schedule_delayed_work(&chip->eoc_work,
1046 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
1047 }
David Keitel344c6972013-04-09 19:28:21 -07001048
David Keitel9fd07382013-05-02 15:37:44 -07001049 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel80668952012-07-27 14:25:49 -07001050 }
1051
1052 return IRQ_HANDLED;
1053}
1054
David Keitel7450dcd2013-01-29 18:41:41 -08001055static irqreturn_t
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001056qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
1057{
1058 struct qpnp_chg_chip *chip = _chip;
1059 int batt_temp_good;
1060
1061 batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
1062 pr_debug("batt-temp triggered: %d\n", batt_temp_good);
1063
1064 power_supply_changed(&chip->batt_psy);
1065 return IRQ_HANDLED;
1066}
1067
1068static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001069qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
1070{
1071 struct qpnp_chg_chip *chip = _chip;
1072 int batt_present;
1073
1074 batt_present = qpnp_chg_is_batt_present(chip);
1075 pr_debug("batt-pres triggered: %d\n", batt_present);
1076
1077 if (chip->batt_present ^ batt_present) {
1078 chip->batt_present = batt_present;
1079 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -07001080 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -07001081
1082 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
1083 && batt_present) {
David Keitelec3c09802013-06-13 13:05:30 -07001084 pr_debug("enabling vadc notifications\n");
David Keitel79f4c932013-04-03 16:08:39 -07001085 schedule_work(&chip->adc_measure_work);
David Keitelec3c09802013-06-13 13:05:30 -07001086 } else if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
1087 && !batt_present) {
1088 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
1089 &chip->adc_param);
1090 pr_debug("disabling vadc notifications\n");
David Keitel0c1a4532013-03-21 16:39:06 -07001091 }
David Keitel42ae0aa2013-03-08 16:20:10 -08001092 }
1093
1094 return IRQ_HANDLED;
1095}
1096
1097static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -08001098qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
1099{
1100 struct qpnp_chg_chip *chip = _chip;
1101 int dc_present;
1102
1103 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
1104 pr_debug("dcin-valid triggered: %d\n", dc_present);
1105
1106 if (chip->dc_present ^ dc_present) {
1107 chip->dc_present = dc_present;
David Keitel9fd07382013-05-02 15:37:44 -07001108 if (!dc_present)
1109 chip->chg_done = false;
1110 else
1111 schedule_delayed_work(&chip->eoc_work,
1112 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel7450dcd2013-01-29 18:41:41 -08001113 power_supply_changed(&chip->dc_psy);
David Keitel9fd07382013-05-02 15:37:44 -07001114 power_supply_changed(&chip->batt_psy);
David Keitel7450dcd2013-01-29 18:41:41 -08001115 }
1116
1117 return IRQ_HANDLED;
1118}
1119
David Keitel80668952012-07-27 14:25:49 -07001120#define CHGR_CHG_FAILED_BIT BIT(7)
1121static irqreturn_t
1122qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
1123{
1124 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -07001125 int rc;
David Keitel80668952012-07-27 14:25:49 -07001126
David Keitel9fd07382013-05-02 15:37:44 -07001127 pr_debug("chg_failed triggered\n");
1128
David Keitel80668952012-07-27 14:25:49 -07001129 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07001130 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -07001131 CHGR_CHG_FAILED_BIT,
1132 CHGR_CHG_FAILED_BIT, 1);
1133 if (rc)
1134 pr_err("Failed to write chg_fail clear bit!\n");
1135
David Keiteldbcef092013-05-14 14:48:30 -07001136 if (chip->bat_if_base)
1137 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -07001138 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -07001139 if (chip->dc_chgpth_base)
1140 power_supply_changed(&chip->dc_psy);
David Keitel80668952012-07-27 14:25:49 -07001141 return IRQ_HANDLED;
1142}
1143
1144static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -08001145qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
1146{
1147 struct qpnp_chg_chip *chip = _chip;
1148
1149 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001150
1151 chip->chg_done = false;
David Keiteldbcef092013-05-14 14:48:30 -07001152 if (chip->bat_if_base)
1153 power_supply_changed(&chip->batt_psy);
David Keitel42ae0aa2013-03-08 16:20:10 -08001154
1155 return IRQ_HANDLED;
1156}
1157
1158static irqreturn_t
1159qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
1160{
1161 struct qpnp_chg_chip *chip = _chip;
David Keitel337bd862013-07-15 21:42:58 -07001162 u8 chgr_sts;
1163 int rc;
1164
1165 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
1166 if (rc)
1167 pr_err("failed to read interrupt sts %d\n", rc);
David Keitel42ae0aa2013-03-08 16:20:10 -08001168
1169 pr_debug("FAST_CHG IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -08001170 chip->chg_done = false;
David Keiteldbcef092013-05-14 14:48:30 -07001171 if (chip->bat_if_base)
1172 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -07001173 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -07001174 if (chip->dc_chgpth_base)
1175 power_supply_changed(&chip->dc_psy);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001176 if (chip->resuming_charging) {
1177 chip->resuming_charging = false;
1178 qpnp_chg_set_appropriate_vbatdet(chip);
1179 }
David Keitel337bd862013-07-15 21:42:58 -07001180
David Keitel47185a62013-05-15 18:54:10 -07001181 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel337bd862013-07-15 21:42:58 -07001182 if (chgr_sts & FAST_CHG_ON_IRQ)
1183 qpnp_chg_enable_irq(&chip->vchg_loop);
1184 else
1185 qpnp_chg_disable_irq(&chip->vchg_loop);
David Keitel42ae0aa2013-03-08 16:20:10 -08001186
1187 return IRQ_HANDLED;
1188}
1189
David Keitel03ee6b52012-10-22 12:25:19 -07001190static int
David Keitel432e1232013-06-05 16:10:18 -07001191qpnp_dc_property_is_writeable(struct power_supply *psy,
1192 enum power_supply_property psp)
1193{
1194 switch (psp) {
1195 case POWER_SUPPLY_PROP_CURRENT_MAX:
1196 return 1;
1197 default:
1198 break;
1199 }
1200
1201 return 0;
1202}
1203
1204static int
David Keitel03ee6b52012-10-22 12:25:19 -07001205qpnp_batt_property_is_writeable(struct power_supply *psy,
1206 enum power_supply_property psp)
1207{
1208 switch (psp) {
1209 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08001210 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel337bd862013-07-15 21:42:58 -07001211 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
1212 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
David Keitelec3c09802013-06-13 13:05:30 -07001213 case POWER_SUPPLY_PROP_COOL_TEMP:
1214 case POWER_SUPPLY_PROP_WARM_TEMP:
David Keitel03ee6b52012-10-22 12:25:19 -07001215 return 1;
1216 default:
1217 break;
1218 }
1219
1220 return 0;
1221}
1222
David Keitel6f865cd2012-11-30 15:04:32 -08001223static int
David Keitelbe208252013-01-31 14:49:25 -08001224qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
1225{
1226 int rc;
1227
1228 if (chip->charging_disabled && enable) {
1229 pr_debug("Charging disabled\n");
1230 return 0;
1231 }
1232
1233 rc = qpnp_chg_charge_en(chip, enable);
1234 if (rc) {
1235 pr_err("Failed to control charging %d\n", rc);
1236 return rc;
1237 }
1238
1239 rc = qpnp_chg_force_run_on_batt(chip, !enable);
1240 if (rc)
1241 pr_err("Failed to control charging %d\n", rc);
1242
1243 return rc;
1244}
1245
David Keitel454ee842013-03-08 16:19:11 -08001246static int
1247switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001248{
1249 int rc;
1250
1251 pr_debug("switch to charge mode\n");
1252 if (!qpnp_chg_is_otg_en_set(chip))
1253 return 0;
1254
1255 /* enable usb ovp fet */
1256 rc = qpnp_chg_masked_write(chip,
1257 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1258 USB_OTG_EN_BIT,
1259 0, 1);
1260 if (rc) {
1261 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1262 return rc;
1263 }
1264
1265 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1266 if (rc) {
1267 pr_err("Failed re-enable charging rc = %d\n", rc);
1268 return rc;
1269 }
1270
1271 return 0;
1272}
1273
David Keitel454ee842013-03-08 16:19:11 -08001274static int
1275switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001276{
1277 int rc;
1278
1279 pr_debug("switch to host mode\n");
1280 if (qpnp_chg_is_otg_en_set(chip))
1281 return 0;
1282
1283 rc = qpnp_chg_force_run_on_batt(chip, 1);
1284 if (rc) {
1285 pr_err("Failed to disable charging rc = %d\n", rc);
1286 return rc;
1287 }
1288
1289 /* force usb ovp fet off */
1290 rc = qpnp_chg_masked_write(chip,
1291 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1292 USB_OTG_EN_BIT,
1293 USB_OTG_EN_BIT, 1);
1294 if (rc) {
1295 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1296 return rc;
1297 }
1298
1299 return 0;
1300}
1301
David Keitel80668952012-07-27 14:25:49 -07001302static enum power_supply_property pm_power_props_mains[] = {
1303 POWER_SUPPLY_PROP_PRESENT,
1304 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07001305 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07001306};
1307
1308static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07001309 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07001310 POWER_SUPPLY_PROP_STATUS,
1311 POWER_SUPPLY_PROP_CHARGE_TYPE,
1312 POWER_SUPPLY_PROP_HEALTH,
1313 POWER_SUPPLY_PROP_PRESENT,
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001314 POWER_SUPPLY_PROP_ONLINE,
David Keitel80668952012-07-27 14:25:49 -07001315 POWER_SUPPLY_PROP_TECHNOLOGY,
1316 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
1317 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
1318 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1319 POWER_SUPPLY_PROP_CAPACITY,
1320 POWER_SUPPLY_PROP_CURRENT_NOW,
David Keitel337bd862013-07-15 21:42:58 -07001321 POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
1322 POWER_SUPPLY_PROP_VOLTAGE_MIN,
1323 POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
David Keitel80668952012-07-27 14:25:49 -07001324 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301325 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07001326 POWER_SUPPLY_PROP_TEMP,
David Keitelec3c09802013-06-13 13:05:30 -07001327 POWER_SUPPLY_PROP_COOL_TEMP,
1328 POWER_SUPPLY_PROP_WARM_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08001329 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301330 POWER_SUPPLY_PROP_CYCLE_COUNT,
David Keitel80668952012-07-27 14:25:49 -07001331};
1332
1333static char *pm_power_supplied_to[] = {
1334 "battery",
1335};
1336
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07001337static char *pm_batt_supplied_to[] = {
1338 "bms",
1339};
1340
David Keitel337bd862013-07-15 21:42:58 -07001341static int charger_monitor;
1342module_param(charger_monitor, int, 0644);
1343
David Keitel80668952012-07-27 14:25:49 -07001344#define USB_WALL_THRESHOLD_MA 500
1345static int
1346qpnp_power_get_property_mains(struct power_supply *psy,
1347 enum power_supply_property psp,
1348 union power_supply_propval *val)
1349{
1350 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1351 dc_psy);
1352
1353 switch (psp) {
1354 case POWER_SUPPLY_PROP_PRESENT:
1355 case POWER_SUPPLY_PROP_ONLINE:
1356 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07001357 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07001358 return 0;
1359
1360 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
1361 break;
David Keitel432e1232013-06-05 16:10:18 -07001362 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07001363 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07001364 break;
David Keitel80668952012-07-27 14:25:49 -07001365 default:
1366 return -EINVAL;
1367 }
1368 return 0;
1369}
1370
1371static int
1372get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
1373{
1374 int rc = 0;
1375 struct qpnp_vadc_result results;
1376
David Keitelfe51cb92013-04-02 19:42:58 -07001377 if (chip->revision == 0 && chip->type == SMBB) {
1378 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
1379 return 0;
1380 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001381 rc = qpnp_vadc_read(chip->vadc_dev, VBAT_SNS, &results);
David Keitel80668952012-07-27 14:25:49 -07001382 if (rc) {
1383 pr_err("Unable to read vbat rc=%d\n", rc);
1384 return 0;
1385 }
1386 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07001387 }
1388}
1389
1390#define BATT_PRES_BIT BIT(7)
1391static int
1392get_prop_batt_present(struct qpnp_chg_chip *chip)
1393{
1394 u8 batt_present;
1395 int rc;
1396
1397 rc = qpnp_chg_read(chip, &batt_present,
1398 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
1399 if (rc) {
1400 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
1401 return 0;
1402 };
1403 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
1404}
1405
1406#define BATT_TEMP_HOT BIT(6)
1407#define BATT_TEMP_OK BIT(7)
1408static int
1409get_prop_batt_health(struct qpnp_chg_chip *chip)
1410{
1411 u8 batt_health;
1412 int rc;
1413
1414 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07001415 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07001416 if (rc) {
1417 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
1418 return POWER_SUPPLY_HEALTH_UNKNOWN;
1419 };
1420
1421 if (BATT_TEMP_OK & batt_health)
1422 return POWER_SUPPLY_HEALTH_GOOD;
1423 if (BATT_TEMP_HOT & batt_health)
1424 return POWER_SUPPLY_HEALTH_OVERHEAT;
1425 else
1426 return POWER_SUPPLY_HEALTH_COLD;
1427}
1428
1429static int
1430get_prop_charge_type(struct qpnp_chg_chip *chip)
1431{
1432 int rc;
1433 u8 chgr_sts;
1434
1435 if (!get_prop_batt_present(chip))
1436 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1437
1438 rc = qpnp_chg_read(chip, &chgr_sts,
1439 INT_RT_STS(chip->chgr_base), 1);
1440 if (rc) {
1441 pr_err("failed to read interrupt sts %d\n", rc);
1442 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1443 }
1444
1445 if (chgr_sts & TRKL_CHG_ON_IRQ)
1446 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1447 if (chgr_sts & FAST_CHG_ON_IRQ)
1448 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1449
1450 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1451}
1452
1453static int
1454get_prop_batt_status(struct qpnp_chg_chip *chip)
1455{
1456 int rc;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001457 u8 chgr_sts, bat_if_sts;
David Keitel80668952012-07-27 14:25:49 -07001458
David Keitel9fd07382013-05-02 15:37:44 -07001459 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
1460 qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
David Keitelc9ffe842013-01-25 19:37:51 -08001461 return POWER_SUPPLY_STATUS_FULL;
David Keitel9fd07382013-05-02 15:37:44 -07001462 }
David Keitelc9ffe842013-01-25 19:37:51 -08001463
David Keitel9fd07382013-05-02 15:37:44 -07001464 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07001465 if (rc) {
1466 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08001467 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07001468 }
1469
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001470 rc = qpnp_chg_read(chip, &bat_if_sts, INT_RT_STS(chip->bat_if_base), 1);
1471 if (rc) {
1472 pr_err("failed to read bat_if sts %d\n", rc);
1473 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1474 }
1475
1476 if (chgr_sts & TRKL_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07001477 return POWER_SUPPLY_STATUS_CHARGING;
Zhenhua Huang2a0ee352013-07-23 01:55:43 +08001478 if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
David Keitel80668952012-07-27 14:25:49 -07001479 return POWER_SUPPLY_STATUS_CHARGING;
1480
1481 return POWER_SUPPLY_STATUS_DISCHARGING;
1482}
1483
1484static int
1485get_prop_current_now(struct qpnp_chg_chip *chip)
1486{
1487 union power_supply_propval ret = {0,};
1488
1489 if (chip->bms_psy) {
1490 chip->bms_psy->get_property(chip->bms_psy,
1491 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
1492 return ret.intval;
1493 } else {
1494 pr_debug("No BMS supply registered return 0\n");
1495 }
1496
1497 return 0;
1498}
1499
1500static int
1501get_prop_full_design(struct qpnp_chg_chip *chip)
1502{
1503 union power_supply_propval ret = {0,};
1504
1505 if (chip->bms_psy) {
1506 chip->bms_psy->get_property(chip->bms_psy,
1507 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
1508 return ret.intval;
1509 } else {
1510 pr_debug("No BMS supply registered return 0\n");
1511 }
1512
1513 return 0;
1514}
1515
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301516static int
1517get_prop_charge_full(struct qpnp_chg_chip *chip)
1518{
1519 union power_supply_propval ret = {0,};
1520
1521 if (chip->bms_psy) {
1522 chip->bms_psy->get_property(chip->bms_psy,
1523 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
1524 return ret.intval;
1525 } else {
1526 pr_debug("No BMS supply registered return 0\n");
1527 }
1528
1529 return 0;
1530}
1531
David Keitel80668952012-07-27 14:25:49 -07001532#define DEFAULT_CAPACITY 50
1533static int
1534get_prop_capacity(struct qpnp_chg_chip *chip)
1535{
1536 union power_supply_propval ret = {0,};
1537
David Keitel3dd5e0f2012-12-12 18:12:36 -08001538 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
1539 return DEFAULT_CAPACITY;
1540
David Keitel80668952012-07-27 14:25:49 -07001541 if (chip->bms_psy) {
1542 chip->bms_psy->get_property(chip->bms_psy,
1543 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001544 if (get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL
1545 && !chip->resuming_charging
1546 && !chip->charging_disabled
1547 && chip->soc_resume_limit
1548 && ret.intval <= chip->soc_resume_limit) {
1549 pr_debug("resuming charging at %d%% soc\n", ret.intval);
1550 chip->resuming_charging = true;
1551 qpnp_chg_set_appropriate_vbatdet(chip);
1552 qpnp_chg_charge_en(chip, !chip->charging_disabled);
1553 }
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07001554 if (ret.intval == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07001555 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
1556 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07001557 pr_warn_ratelimited("Battery 0, CHG absent\n");
1558 }
David Keitel80668952012-07-27 14:25:49 -07001559 return ret.intval;
1560 } else {
1561 pr_debug("No BMS supply registered return 50\n");
1562 }
1563
1564 /* return default capacity to avoid userspace
1565 * from shutting down unecessarily */
1566 return DEFAULT_CAPACITY;
1567}
1568
David Keitel3dd5e0f2012-12-12 18:12:36 -08001569#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07001570#define MAX_TOLERABLE_BATT_TEMP_DDC 680
1571static int
1572get_prop_batt_temp(struct qpnp_chg_chip *chip)
1573{
1574 int rc = 0;
1575 struct qpnp_vadc_result results;
1576
David Keitel3dd5e0f2012-12-12 18:12:36 -08001577 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
1578 return DEFAULT_TEMP;
1579
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001580 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM, &results);
David Keitela2dbfc72013-06-07 11:10:14 -07001581 if (rc) {
1582 pr_debug("Unable to read batt temperature rc=%d\n", rc);
1583 return 0;
David Keitel80668952012-07-27 14:25:49 -07001584 }
David Keitela2dbfc72013-06-07 11:10:14 -07001585 pr_debug("get_bat_temp %d %lld\n",
1586 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07001587
David Keitela2dbfc72013-06-07 11:10:14 -07001588 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07001589}
1590
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301591static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
1592{
1593 union power_supply_propval ret = {0,};
1594
1595 if (chip->bms_psy)
1596 chip->bms_psy->get_property(chip->bms_psy,
1597 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
1598 return ret.intval;
1599}
1600
David Keitel337bd862013-07-15 21:42:58 -07001601static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
1602{
1603 u8 buck_sts;
1604 int rc;
1605
1606 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
1607
1608 if (rc) {
1609 pr_err("spmi read failed: addr=%03X, rc=%d\n",
1610 INT_RT_STS(chip->buck_base), rc);
1611 return rc;
1612 }
1613 pr_debug("buck usb sts 0x%x\n", buck_sts);
1614
1615 return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
1616}
1617
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001618static int get_prop_online(struct qpnp_chg_chip *chip)
1619{
1620 return qpnp_chg_is_batfet_closed(chip);
1621}
1622
David Keitel80668952012-07-27 14:25:49 -07001623static void
1624qpnp_batt_external_power_changed(struct power_supply *psy)
1625{
1626 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1627 batt_psy);
1628 union power_supply_propval ret = {0,};
1629
1630 if (!chip->bms_psy)
1631 chip->bms_psy = power_supply_get_by_name("bms");
1632
1633 chip->usb_psy->get_property(chip->usb_psy,
1634 POWER_SUPPLY_PROP_ONLINE, &ret);
1635
David Keitelc69f2d62013-03-17 14:52:35 -07001636 /* Only honour requests while USB is present */
1637 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07001638 chip->usb_psy->get_property(chip->usb_psy,
1639 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitelfd305ee2013-07-19 20:19:06 -07001640
1641 if (chip->prev_usb_max_ma == ret.intval)
1642 goto skip_set_iusb_max;
1643
David Keitel87473252013-03-21 14:39:45 -07001644 if (ret.intval <= 2 && !chip->use_default_batt_values &&
1645 get_prop_batt_present(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07001646 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001647 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07001648 } else {
David Keiteld681cda2012-10-02 15:44:21 -07001649 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel337bd862013-07-15 21:42:58 -07001650 if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
1651 && (charger_monitor)) {
1652 qpnp_chg_iusbmax_set(chip,
1653 USB_WALL_THRESHOLD_MA);
1654 } else {
1655 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
1656 }
David Keitelc69f2d62013-03-17 14:52:35 -07001657 }
David Keitelfd305ee2013-07-19 20:19:06 -07001658 chip->prev_usb_max_ma = ret.intval;
David Keitel80668952012-07-27 14:25:49 -07001659 }
1660
David Keitelfd305ee2013-07-19 20:19:06 -07001661skip_set_iusb_max:
David Keitel80668952012-07-27 14:25:49 -07001662 pr_debug("end of power supply changed\n");
1663 power_supply_changed(&chip->batt_psy);
1664}
1665
1666static int
1667qpnp_batt_power_get_property(struct power_supply *psy,
1668 enum power_supply_property psp,
1669 union power_supply_propval *val)
1670{
1671 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1672 batt_psy);
1673
1674 switch (psp) {
1675 case POWER_SUPPLY_PROP_STATUS:
1676 val->intval = get_prop_batt_status(chip);
1677 break;
1678 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1679 val->intval = get_prop_charge_type(chip);
1680 break;
1681 case POWER_SUPPLY_PROP_HEALTH:
1682 val->intval = get_prop_batt_health(chip);
1683 break;
1684 case POWER_SUPPLY_PROP_PRESENT:
1685 val->intval = get_prop_batt_present(chip);
1686 break;
1687 case POWER_SUPPLY_PROP_TECHNOLOGY:
1688 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1689 break;
1690 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1691 val->intval = chip->max_voltage_mv * 1000;
1692 break;
1693 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
1694 val->intval = chip->min_voltage_mv * 1000;
1695 break;
1696 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1697 val->intval = get_prop_battery_voltage_now(chip);
1698 break;
1699 case POWER_SUPPLY_PROP_TEMP:
1700 val->intval = get_prop_batt_temp(chip);
1701 break;
David Keitelec3c09802013-06-13 13:05:30 -07001702 case POWER_SUPPLY_PROP_COOL_TEMP:
1703 val->intval = chip->cool_bat_decidegc;
1704 break;
1705 case POWER_SUPPLY_PROP_WARM_TEMP:
1706 val->intval = chip->warm_bat_decidegc;
1707 break;
David Keitel80668952012-07-27 14:25:49 -07001708 case POWER_SUPPLY_PROP_CAPACITY:
1709 val->intval = get_prop_capacity(chip);
1710 break;
1711 case POWER_SUPPLY_PROP_CURRENT_NOW:
1712 val->intval = get_prop_current_now(chip);
1713 break;
1714 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1715 val->intval = get_prop_full_design(chip);
1716 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301717 case POWER_SUPPLY_PROP_CHARGE_FULL:
1718 val->intval = get_prop_charge_full(chip);
1719 break;
David Keitelb80eda82012-10-15 10:49:11 -07001720 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07001721 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07001722 break;
David Keitelbe208252013-01-31 14:49:25 -08001723 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
1724 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07001725 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301726 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1727 val->intval = get_prop_cycle_count(chip);
1728 break;
David Keitel337bd862013-07-15 21:42:58 -07001729 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
1730 val->intval = get_prop_vchg_loop(chip);
1731 break;
1732 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
1733 val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
1734 break;
1735 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
1736 val->intval = qpnp_chg_vinmin_get(chip) * 1000;
1737 break;
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07001738 case POWER_SUPPLY_PROP_ONLINE:
1739 val->intval = get_prop_online(chip);
1740 break;
David Keitelb80eda82012-10-15 10:49:11 -07001741 default:
1742 return -EINVAL;
1743 }
1744
David Keitelb80eda82012-10-15 10:49:11 -07001745 return 0;
David Keitel80668952012-07-27 14:25:49 -07001746}
1747
David Keitel89c17752013-06-28 14:52:48 -07001748#define BTC_CONFIG_ENABLED BIT(7)
1749#define BTC_COLD BIT(1)
1750#define BTC_HOT BIT(0)
1751static int
1752qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
1753{
1754 u8 btc_cfg = 0, mask = 0;
1755
1756 /* Do nothing if battery peripheral not present */
1757 if (!chip->bat_if_base)
1758 return 0;
1759
1760 if ((chip->hot_batt_p == HOT_THD_25_PCT)
1761 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
1762 btc_cfg |= btc_value[chip->hot_batt_p];
1763 mask |= BTC_HOT;
1764 }
1765
1766 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
1767 (chip->cold_batt_p == COLD_THD_80_PCT)) {
1768 btc_cfg |= btc_value[chip->cold_batt_p];
1769 mask |= BTC_COLD;
1770 }
1771
1772 if (chip->btc_disabled)
1773 mask |= BTC_CONFIG_ENABLED;
1774
1775 return qpnp_chg_masked_write(chip,
1776 chip->bat_if_base + BAT_IF_BTC_CTRL,
1777 mask, btc_cfg, 1);
1778}
1779
David Keitel5d44fa52012-12-03 16:37:31 -08001780#define QPNP_CHG_IBATSAFE_MIN_MA 100
1781#define QPNP_CHG_IBATSAFE_MAX_MA 3250
1782#define QPNP_CHG_I_STEP_MA 50
1783#define QPNP_CHG_I_MIN_MA 100
1784#define QPNP_CHG_I_MASK 0x3F
1785static int
1786qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
1787{
1788 u8 temp;
1789
1790 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
1791 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
1792 pr_err("bad mA=%d asked to set\n", safe_current);
1793 return -EINVAL;
1794 }
1795
Zhenhua Huanga2964fb2013-07-23 09:06:20 +08001796 temp = safe_current / QPNP_CHG_I_STEP_MA;
David Keitel5d44fa52012-12-03 16:37:31 -08001797 return qpnp_chg_masked_write(chip,
1798 chip->chgr_base + CHGR_IBAT_SAFE,
1799 QPNP_CHG_I_MASK, temp, 1);
1800}
David Keitel80668952012-07-27 14:25:49 -07001801
1802#define QPNP_CHG_ITERM_MIN_MA 100
1803#define QPNP_CHG_ITERM_MAX_MA 250
1804#define QPNP_CHG_ITERM_STEP_MA 50
1805#define QPNP_CHG_ITERM_MASK 0x03
1806static int
1807qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
1808{
1809 u8 temp;
1810
1811 if (term_current < QPNP_CHG_ITERM_MIN_MA
1812 || term_current > QPNP_CHG_ITERM_MAX_MA) {
1813 pr_err("bad mA=%d asked to set\n", term_current);
1814 return -EINVAL;
1815 }
1816
1817 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
1818 / QPNP_CHG_ITERM_STEP_MA;
1819 return qpnp_chg_masked_write(chip,
1820 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
1821 QPNP_CHG_ITERM_MASK, temp, 1);
1822}
1823
David Keitelff5d0472013-04-04 11:36:06 -07001824#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07001825#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07001826static int
1827qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
1828{
1829 u8 temp;
1830
1831 if (chg_current < QPNP_CHG_IBATMAX_MIN
1832 || chg_current > QPNP_CHG_IBATMAX_MAX) {
1833 pr_err("bad mA=%d asked to set\n", chg_current);
1834 return -EINVAL;
1835 }
David Keitelff5d0472013-04-04 11:36:06 -07001836 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07001837 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
1838 QPNP_CHG_I_MASK, temp, 1);
1839}
1840
David Keitela4b7b592013-04-11 18:34:35 -07001841#define QPNP_CHG_TCHG_MASK 0x7F
1842#define QPNP_CHG_TCHG_MIN 4
1843#define QPNP_CHG_TCHG_MAX 512
1844#define QPNP_CHG_TCHG_STEP 4
1845static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
1846{
1847 u8 temp;
1848
1849 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
1850 pr_err("bad max minutes =%d asked to set\n", minutes);
1851 return -EINVAL;
1852 }
1853
1854 temp = (minutes - 1)/QPNP_CHG_TCHG_STEP;
1855 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07001856 QPNP_CHG_TCHG_MASK, temp, 1);
David Keitela4b7b592013-04-11 18:34:35 -07001857}
David Keitel80668952012-07-27 14:25:49 -07001858
1859#define QPNP_CHG_V_MIN_MV 3240
1860#define QPNP_CHG_V_MAX_MV 4500
1861#define QPNP_CHG_V_STEP_MV 10
1862static int
1863qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
1864{
1865 u8 temp;
1866
1867 if (voltage < QPNP_CHG_V_MIN_MV
1868 || voltage > QPNP_CHG_V_MAX_MV) {
1869 pr_err("bad mV=%d asked to set\n", voltage);
1870 return -EINVAL;
1871 }
1872 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1873 pr_debug("voltage=%d setting %02x\n", voltage, temp);
1874 return qpnp_chg_write(chip, &temp,
1875 chip->chgr_base + CHGR_VDD_SAFE, 1);
1876}
1877
1878#define QPNP_CHG_VDDMAX_MIN 3400
1879static int
1880qpnp_chg_vddmax_set(struct qpnp_chg_chip *chip, int voltage)
1881{
1882 u8 temp = 0;
1883
1884 if (voltage < QPNP_CHG_VDDMAX_MIN
1885 || voltage > QPNP_CHG_V_MAX_MV) {
1886 pr_err("bad mV=%d asked to set\n", voltage);
1887 return -EINVAL;
1888 }
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001889 chip->set_vddmax_mv = voltage + chip->delta_vddmax_mv;
David Keitel80668952012-07-27 14:25:49 -07001890
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001891 temp = (chip->set_vddmax_mv - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
David Keitel80668952012-07-27 14:25:49 -07001892
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001893 pr_debug("voltage=%d setting %02x\n", chip->set_vddmax_mv, temp);
David Keitel454ee842013-03-08 16:19:11 -08001894 return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
1895}
1896
David Keitel6dc4ed42013-05-17 11:08:58 -07001897#define BOOST_MIN_UV 4200000
1898#define BOOST_MAX_UV 5500000
1899#define BOOST_STEP_UV 50000
1900#define BOOST_MIN 16
1901#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
1902static int
1903qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
1904{
1905 u8 reg = 0;
1906
1907 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
1908 pr_err("invalid voltage requested %d uV\n", voltage);
1909 return -EINVAL;
1910 }
1911
1912 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
1913
1914 pr_debug("voltage=%d setting %02x\n", voltage, reg);
1915 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
1916}
1917
1918static int
1919qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
1920{
1921 int rc;
1922 u8 boost_reg;
1923
1924 rc = qpnp_chg_read(chip, &boost_reg,
1925 chip->boost_base + BOOST_VSET, 1);
1926 if (rc) {
1927 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
1928 return rc;
1929 }
1930
1931 if (boost_reg < BOOST_MIN) {
1932 pr_err("Invalid reading from 0x%x\n", boost_reg);
1933 return -EINVAL;
1934 }
1935
1936 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
1937}
1938
David Keitel454ee842013-03-08 16:19:11 -08001939/* JEITA compliance logic */
1940static void
1941qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1942{
1943 if (chip->bat_is_cool)
1944 qpnp_chg_vddmax_set(chip, chip->cool_bat_mv);
1945 else if (chip->bat_is_warm)
1946 qpnp_chg_vddmax_set(chip, chip->warm_bat_mv);
1947 else
1948 qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
1949}
1950
1951static void
David Keitelbe208252013-01-31 14:49:25 -08001952qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
1953{
1954 unsigned int chg_current = chip->max_bat_chg_current;
1955
David Keitel454ee842013-03-08 16:19:11 -08001956 if (chip->bat_is_cool)
1957 chg_current = min(chg_current, chip->cool_bat_chg_ma);
1958
1959 if (chip->bat_is_warm)
1960 chg_current = min(chg_current, chip->warm_bat_chg_ma);
1961
David Keitelbe208252013-01-31 14:49:25 -08001962 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
1963 chg_current = min(chg_current,
1964 chip->thermal_mitigation[chip->therm_lvl_sel]);
1965
1966 pr_debug("setting %d mA\n", chg_current);
1967 qpnp_chg_ibatmax_set(chip, chg_current);
1968}
1969
1970static void
1971qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
1972{
1973 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
1974 chip->therm_lvl_sel = lvl_sel;
1975 if (lvl_sel == (chip->thermal_levels - 1)) {
1976 /* disable charging if highest value selected */
1977 qpnp_chg_buck_control(chip, 0);
1978 } else {
1979 qpnp_chg_buck_control(chip, 1);
1980 qpnp_chg_set_appropriate_battery_current(chip);
1981 }
1982 } else {
1983 pr_err("Unsupported level selected %d\n", lvl_sel);
1984 }
1985}
1986
David Keitel6dc4ed42013-05-17 11:08:58 -07001987/* OTG regulator operations */
1988static int
1989qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
1990{
1991 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1992
1993 return switch_usb_to_host_mode(chip);
1994}
1995
1996static int
1997qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
1998{
1999 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2000
2001 return switch_usb_to_charge_mode(chip);
2002}
2003
2004static int
2005qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
2006{
2007 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2008
2009 return qpnp_chg_is_otg_en_set(chip);
2010}
2011
2012static int
2013qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
2014{
2015 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07002016 int rc;
2017
2018 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
2019 (chip->flags & BOOST_FLASH_WA)) {
2020 qpnp_chg_usb_suspend_enable(chip, 1);
2021
2022 rc = qpnp_chg_masked_write(chip,
2023 chip->usb_chgpth_base + SEC_ACCESS,
2024 0xFF,
2025 0xA5, 1);
2026 if (rc) {
2027 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2028 return rc;
2029 }
2030
2031 rc = qpnp_chg_masked_write(chip,
2032 chip->usb_chgpth_base + COMP_OVR1,
2033 0xFF,
2034 0x2F, 1);
2035 if (rc) {
2036 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2037 return rc;
2038 }
2039 }
David Keitel6dc4ed42013-05-17 11:08:58 -07002040
2041 return qpnp_chg_masked_write(chip,
2042 chip->boost_base + BOOST_ENABLE_CONTROL,
2043 BOOST_PWR_EN,
2044 BOOST_PWR_EN, 1);
2045}
2046
2047/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07002048#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07002049static int
2050qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
2051{
2052 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07002053 int rc;
2054 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07002055
David Keitel33f58952013-05-20 16:17:36 -07002056 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07002057 chip->boost_base + BOOST_ENABLE_CONTROL,
2058 BOOST_PWR_EN,
2059 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07002060 if (rc) {
2061 pr_err("failed to disable boost rc=%d\n", rc);
2062 return rc;
2063 }
2064
2065 rc = qpnp_chg_read(chip, &vbat_sts,
2066 chip->chgr_base + CHGR_VBAT_STATUS, 1);
2067 if (rc) {
2068 pr_err("failed to read bat sts rc=%d\n", rc);
2069 return rc;
2070 }
2071
2072 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
2073 rc = qpnp_chg_masked_write(chip,
2074 chip->chgr_base + SEC_ACCESS,
2075 0xFF,
2076 0xA5, 1);
2077 if (rc) {
2078 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2079 return rc;
2080 }
2081
2082 rc = qpnp_chg_masked_write(chip,
2083 chip->chgr_base + COMP_OVR1,
2084 0xFF,
2085 0x20, 1);
2086 if (rc) {
2087 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2088 return rc;
2089 }
2090
2091 usleep(2000);
2092
2093 rc = qpnp_chg_masked_write(chip,
2094 chip->chgr_base + SEC_ACCESS,
2095 0xFF,
2096 0xA5, 1);
2097 if (rc) {
2098 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2099 return rc;
2100 }
2101
2102 rc = qpnp_chg_masked_write(chip,
2103 chip->chgr_base + COMP_OVR1,
2104 0xFF,
2105 0x00, 1);
2106 if (rc) {
2107 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2108 return rc;
2109 }
2110 }
2111
2112 if (qpnp_chg_is_usb_chg_plugged_in(chip)
2113 && (chip->flags & BOOST_FLASH_WA)) {
2114 rc = qpnp_chg_masked_write(chip,
2115 chip->usb_chgpth_base + SEC_ACCESS,
2116 0xFF,
2117 0xA5, 1);
2118 if (rc) {
2119 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
2120 return rc;
2121 }
2122
2123 rc = qpnp_chg_masked_write(chip,
2124 chip->usb_chgpth_base + COMP_OVR1,
2125 0xFF,
2126 0x00, 1);
2127 if (rc) {
2128 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
2129 return rc;
2130 }
2131
2132 usleep(1000);
2133
2134 qpnp_chg_usb_suspend_enable(chip, 0);
2135 }
2136
2137 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07002138}
2139
2140static int
2141qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
2142{
2143 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2144
2145 return qpnp_chg_is_boost_en_set(chip);
2146}
2147
2148static int
2149qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
2150 int min_uV, int max_uV, unsigned *selector)
2151{
2152 int uV = min_uV;
2153 int rc;
2154 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2155
2156 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
2157 uV = BOOST_MIN_UV;
2158
2159
2160 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
2161 pr_err("request %d uV is out of bounds\n", uV);
2162 return -EINVAL;
2163 }
2164
2165 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
2166 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
2167 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
2168 return -EINVAL;
2169 }
2170
2171 rc = qpnp_boost_vset(chip, uV);
2172
2173 return rc;
2174}
2175
2176static int
2177qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
2178{
2179 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
2180
2181 return qpnp_boost_vget_uv(chip);
2182}
2183
2184static int
2185qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
2186 unsigned selector)
2187{
2188 if (selector >= N_BOOST_V)
2189 return 0;
2190
2191 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
2192}
2193
2194static struct regulator_ops qpnp_chg_otg_reg_ops = {
2195 .enable = qpnp_chg_regulator_otg_enable,
2196 .disable = qpnp_chg_regulator_otg_disable,
2197 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
2198};
2199
2200static struct regulator_ops qpnp_chg_boost_reg_ops = {
2201 .enable = qpnp_chg_regulator_boost_enable,
2202 .disable = qpnp_chg_regulator_boost_disable,
2203 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
2204 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
2205 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
2206 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
2207};
2208
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002209#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 13
2210#define MAX_DELTA_VDD_MAX_MV 30
2211static void
2212qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
2213{
2214 int delta_mv, closest_delta_mv, sign;
2215
2216 delta_mv = chip->max_voltage_mv - vbat_mv;
2217 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
2218 pr_debug("vbat is not low enough to increase vdd\n");
2219 return;
2220 }
2221
2222 sign = delta_mv > 0 ? 1 : -1;
2223 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_V_STEP_MV / 2)
2224 / QPNP_CHG_V_STEP_MV) * QPNP_CHG_V_STEP_MV;
2225 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
2226 chip->max_voltage_mv, vbat_mv,
2227 delta_mv, closest_delta_mv);
2228 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
2229 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
2230 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
2231 qpnp_chg_set_appropriate_vddmax(chip);
2232}
2233
David Keitel9fd07382013-05-02 15:37:44 -07002234#define CONSECUTIVE_COUNT 3
2235static void
2236qpnp_eoc_work(struct work_struct *work)
2237{
2238 struct delayed_work *dwork = to_delayed_work(work);
2239 struct qpnp_chg_chip *chip = container_of(dwork,
2240 struct qpnp_chg_chip, eoc_work);
2241 static int count;
2242 int ibat_ma, vbat_mv, rc = 0;
2243 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
2244
2245 wake_lock(&chip->eoc_wake_lock);
2246 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2247
2248 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
2249 if (rc) {
2250 pr_err("failed to read batt_if rc=%d\n", rc);
2251 return;
2252 }
2253
2254 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2255 if (rc) {
2256 pr_err("failed to read buck rc=%d\n", rc);
2257 return;
2258 }
2259
2260 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
2261 if (rc) {
2262 pr_err("failed to read chg_sts rc=%d\n", rc);
2263 return;
2264 }
2265
2266 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
2267 chg_sts, batt_sts, buck_sts);
2268
2269 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
2270 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
2271 pr_debug("no chg connected, stopping\n");
2272 goto stop_eoc;
2273 }
2274
2275 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
2276 || chg_sts & TRKL_CHG_ON_IRQ)) {
2277 ibat_ma = get_prop_current_now(chip) / 1000;
2278 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002279
2280 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
2281 ibat_ma, vbat_mv, chip->term_current);
2282
2283 if ((!(chg_sts & VBAT_DET_LOW_IRQ)) && (vbat_mv <
2284 (chip->max_voltage_mv - chip->resume_delta_mv))) {
2285 pr_debug("woke up too early\n");
2286 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
2287 goto stop_eoc;
2288 }
2289
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002290 if (buck_sts & VDD_LOOP_IRQ)
2291 qpnp_chg_adjust_vddmax(chip, vbat_mv);
2292
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002293 if (!(buck_sts & VDD_LOOP_IRQ)) {
2294 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07002295 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002296 } else if ((ibat_ma * -1) > chip->term_current) {
2297 pr_debug("Not at EOC, battery current too high\n");
2298 count = 0;
2299 } else if (ibat_ma > 0) {
2300 pr_debug("Charging but system demand increased\n");
2301 count = 0;
2302 } else {
David Keitel9fd07382013-05-02 15:37:44 -07002303 if (count == CONSECUTIVE_COUNT) {
2304 pr_info("End of Charging\n");
2305 qpnp_chg_charge_en(chip, 0);
2306 chip->chg_done = true;
2307 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07002308 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07002309 goto stop_eoc;
2310 } else {
2311 count += 1;
2312 pr_debug("EOC count = %d\n", count);
2313 }
David Keitel9fd07382013-05-02 15:37:44 -07002314 }
2315 } else {
2316 pr_debug("not charging\n");
2317 goto stop_eoc;
2318 }
2319
2320 schedule_delayed_work(&chip->eoc_work,
2321 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2322 return;
2323
2324stop_eoc:
2325 count = 0;
2326 wake_unlock(&chip->eoc_wake_lock);
2327}
2328
David Keitel0c1a4532013-03-21 16:39:06 -07002329#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08002330static void
2331qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
2332{
2333 struct qpnp_chg_chip *chip = ctx;
2334 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07002335 int temp;
David Keitel454ee842013-03-08 16:19:11 -08002336
2337 if (state >= ADC_TM_STATE_NUM) {
2338 pr_err("invalid notification %d\n", state);
2339 return;
2340 }
2341
David Keitel1219a802013-03-21 16:37:21 -07002342 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08002343
David Keitel1219a802013-03-21 16:37:21 -07002344 pr_debug("temp = %d state = %s\n", temp,
2345 state == ADC_TM_WARM_STATE ? "warm" : "cool");
2346
2347 if (state == ADC_TM_WARM_STATE) {
2348 if (temp > chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002349 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08002350 bat_warm = true;
2351 bat_cool = false;
2352 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002353 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002354 chip->adc_param.state_request =
2355 ADC_TM_COOL_THR_ENABLE;
2356 } else if (temp >
2357 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002358 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08002359 bat_warm = false;
2360 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07002361
2362 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07002363 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07002364 chip->adc_param.state_request =
2365 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08002366 }
2367 } else {
David Keitel1219a802013-03-21 16:37:21 -07002368 if (temp < chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002369 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08002370 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002371 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08002372 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002373 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002374 chip->adc_param.state_request =
2375 ADC_TM_WARM_THR_ENABLE;
David Keitel3e37e5a2013-04-18 10:42:30 -07002376 } else if (temp <
David Keitel1219a802013-03-21 16:37:21 -07002377 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002378 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08002379 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002380 bat_cool = false;
2381
David Keitel0c1a4532013-03-21 16:39:06 -07002382 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07002383 chip->adc_param.high_temp = chip->warm_bat_decidegc;
2384 chip->adc_param.state_request =
2385 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08002386 }
2387 }
2388
2389 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07002390 chip->bat_is_cool = bat_cool;
2391 chip->bat_is_warm = bat_warm;
2392
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002393 if (bat_cool || bat_warm)
2394 chip->resuming_charging = false;
2395
2396 /**
2397 * set appropriate voltages and currents.
2398 *
2399 * Note that when the battery is hot or cold, the charger
2400 * driver will not resume with SoC. Only vbatdet is used to
2401 * determine resume of charging.
2402 */
David Keitel454ee842013-03-08 16:19:11 -08002403 qpnp_chg_set_appropriate_vddmax(chip);
2404 qpnp_chg_set_appropriate_battery_current(chip);
2405 qpnp_chg_set_appropriate_vbatdet(chip);
David Keitel454ee842013-03-08 16:19:11 -08002406 }
2407
David Keitelec3c09802013-06-13 13:05:30 -07002408 pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
2409 chip->bat_is_warm, chip->bat_is_cool,
2410 chip->adc_param.low_temp, chip->adc_param.high_temp);
2411
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07002412 if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
David Keitel1219a802013-03-21 16:37:21 -07002413 pr_err("request ADC error\n");
David Keitelec3c09802013-06-13 13:05:30 -07002414}
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002415
David Keitelec3c09802013-06-13 13:05:30 -07002416#define MIN_COOL_TEMP -300
2417#define MAX_WARM_TEMP 1000
2418
2419static int
2420qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
2421 enum power_supply_property psp, int temp_degc)
2422{
2423 int rc = 0;
2424
2425 if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
2426 pr_err("Bad temperature request %d\n", temp_degc);
2427 return -EINVAL;
2428 }
2429
2430 mutex_lock(&chip->jeita_configure_lock);
2431 switch (psp) {
2432 case POWER_SUPPLY_PROP_COOL_TEMP:
2433 if (temp_degc >=
2434 (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
2435 pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
2436 temp_degc, chip->warm_bat_decidegc,
2437 HYSTERISIS_DECIDEGC);
2438 rc = -EINVAL;
2439 goto mutex_unlock;
2440 }
2441 if (chip->bat_is_cool)
2442 chip->adc_param.high_temp =
2443 temp_degc + HYSTERISIS_DECIDEGC;
2444 else if (!chip->bat_is_warm)
2445 chip->adc_param.low_temp = temp_degc;
2446
2447 chip->cool_bat_decidegc = temp_degc;
2448 break;
2449 case POWER_SUPPLY_PROP_WARM_TEMP:
2450 if (temp_degc <=
2451 (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
2452 pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
2453 temp_degc, chip->warm_bat_decidegc,
2454 HYSTERISIS_DECIDEGC);
2455 rc = -EINVAL;
2456 goto mutex_unlock;
2457 }
2458 if (chip->bat_is_warm)
2459 chip->adc_param.low_temp =
2460 temp_degc - HYSTERISIS_DECIDEGC;
2461 else if (!chip->bat_is_cool)
2462 chip->adc_param.high_temp = temp_degc;
2463
2464 chip->warm_bat_decidegc = temp_degc;
2465 break;
2466 default:
2467 rc = -EINVAL;
2468 goto mutex_unlock;
2469 }
2470
2471 schedule_work(&chip->adc_measure_work);
2472
2473mutex_unlock:
2474 mutex_unlock(&chip->jeita_configure_lock);
2475 return rc;
David Keitel454ee842013-03-08 16:19:11 -08002476}
2477
David Keitelbe208252013-01-31 14:49:25 -08002478static int
David Keitel432e1232013-06-05 16:10:18 -07002479qpnp_dc_power_set_property(struct power_supply *psy,
2480 enum power_supply_property psp,
2481 const union power_supply_propval *val)
2482{
2483 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2484 dc_psy);
2485 int rc = 0;
2486
2487 switch (psp) {
2488 case POWER_SUPPLY_PROP_CURRENT_MAX:
2489 if (!val->intval)
2490 break;
2491
2492 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
2493 if (rc) {
2494 pr_err("Error setting idcmax property %d\n", rc);
2495 return rc;
2496 }
2497 chip->maxinput_dc_ma = (val->intval / 1000);
2498
2499 break;
2500 default:
2501 return -EINVAL;
2502 }
2503
2504 power_supply_changed(&chip->dc_psy);
2505 return rc;
2506}
2507
2508static int
David Keitelbe208252013-01-31 14:49:25 -08002509qpnp_batt_power_set_property(struct power_supply *psy,
2510 enum power_supply_property psp,
2511 const union power_supply_propval *val)
2512{
2513 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2514 batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07002515 int rc = 0;
David Keitelbe208252013-01-31 14:49:25 -08002516
2517 switch (psp) {
David Keitelec3c09802013-06-13 13:05:30 -07002518 case POWER_SUPPLY_PROP_COOL_TEMP:
2519 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
2520 break;
2521 case POWER_SUPPLY_PROP_WARM_TEMP:
2522 rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
2523 break;
David Keitelbe208252013-01-31 14:49:25 -08002524 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
2525 chip->charging_disabled = !(val->intval);
2526 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2527 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2528 break;
2529 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2530 qpnp_batt_system_temp_level_set(chip, val->intval);
2531 break;
David Keitel337bd862013-07-15 21:42:58 -07002532 case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
2533 qpnp_chg_iusbmax_set(chip, val->intval / 1000);
2534 break;
2535 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
2536 qpnp_chg_vinmin_set(chip, val->intval / 1000);
2537 break;
David Keitelbe208252013-01-31 14:49:25 -08002538 default:
2539 return -EINVAL;
2540 }
2541
2542 power_supply_changed(&chip->batt_psy);
David Keitelec3c09802013-06-13 13:05:30 -07002543 return rc;
David Keitelbe208252013-01-31 14:49:25 -08002544}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08002545
2546static void
2547qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07002548{
David Keitelfe51cb92013-04-02 19:42:58 -07002549 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07002550 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07002551 if (chip->type == SMBB)
2552 chip->flags |= BOOST_FLASH_WA;
David Keitel14288042013-06-04 15:16:46 -07002553 if (chip->type == SMBBP)
2554 chip->flags |= BOOST_FLASH_WA;
David Keiteld681cda2012-10-02 15:44:21 -07002555}
2556
David Keitel0f35be42013-04-16 11:10:40 -07002557static int
2558qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
2559{
2560 int rc = 0;
2561 struct resource *resource;
2562 struct spmi_resource *spmi_resource;
2563 u8 subtype;
2564 struct spmi_device *spmi = chip->spmi;
2565
2566 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
2567 if (!spmi_resource) {
2568 pr_err("qpnp_chg: spmi resource absent\n");
2569 return rc;
2570 }
2571
2572 resource = spmi_get_resource(spmi, spmi_resource,
2573 IORESOURCE_MEM, 0);
2574 if (!(resource && resource->start)) {
2575 pr_err("node %s IO resource absent!\n",
2576 spmi->dev.of_node->full_name);
2577 return rc;
2578 }
2579
2580 rc = qpnp_chg_read(chip, &subtype,
2581 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2582 if (rc) {
2583 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2584 return rc;
2585 }
2586
2587 switch (subtype) {
2588 case SMBB_CHGR_SUBTYPE:
2589 case SMBBP_CHGR_SUBTYPE:
2590 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002591 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002592 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07002593 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002594 pr_err("Unable to get fast-chg-on irq\n");
2595 return rc;
2596 }
2597
David Keitel47185a62013-05-15 18:54:10 -07002598 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002599 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07002600 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002601 pr_err("Unable to get trkl-chg-on irq\n");
2602 return rc;
2603 }
2604
David Keitel47185a62013-05-15 18:54:10 -07002605 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002606 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07002607 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002608 pr_err("Unable to get chg_failed irq\n");
2609 return rc;
2610 }
2611
David Keitel47185a62013-05-15 18:54:10 -07002612 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07002613 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07002614 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07002615 pr_err("Unable to get fast-chg-on irq\n");
2616 return rc;
2617 }
2618
David Keitel47185a62013-05-15 18:54:10 -07002619 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002620 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07002621 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002622 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002623 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002624 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002625 return rc;
2626 }
2627
David Keitel47185a62013-05-15 18:54:10 -07002628 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002629 qpnp_chg_chgr_chg_fastchg_irq_handler,
2630 IRQF_TRIGGER_RISING,
2631 "fast-chg-on", chip);
2632 if (rc < 0) {
2633 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002634 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002635 return rc;
2636 }
2637
David Keitel47185a62013-05-15 18:54:10 -07002638 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002639 qpnp_chg_chgr_chg_trklchg_irq_handler,
2640 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002641 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002642 if (rc < 0) {
2643 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002644 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002645 return rc;
2646 }
David Keitel9fd07382013-05-02 15:37:44 -07002647
2648 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07002649 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07002650 qpnp_chg_vbatdet_lo_irq_handler,
David Keiteld98e2822013-06-05 11:37:34 -07002651 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitel9fd07382013-05-02 15:37:44 -07002652 "vbat-det-lo", chip);
2653 if (rc < 0) {
2654 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002655 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07002656 return rc;
2657 }
2658
David Keitel47185a62013-05-15 18:54:10 -07002659 enable_irq_wake(chip->chg_trklchg.irq);
2660 enable_irq_wake(chip->chg_failed.irq);
2661 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
2662 enable_irq_wake(chip->chg_vbatdet_lo.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002663
2664 break;
2665 case SMBB_BAT_IF_SUBTYPE:
2666 case SMBBP_BAT_IF_SUBTYPE:
2667 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002668 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002669 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07002670 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002671 pr_err("Unable to get batt-pres irq\n");
2672 return rc;
2673 }
David Keitel47185a62013-05-15 18:54:10 -07002674 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002675 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07002676 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
2677 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07002678 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002679 if (rc < 0) {
2680 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002681 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002682 return rc;
2683 }
2684
David Keitel47185a62013-05-15 18:54:10 -07002685 enable_irq_wake(chip->batt_pres.irq);
Abhijeet Dharmapurikar84b13dd2013-07-08 18:43:56 -07002686
2687 chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
2688 spmi_resource, "bat-temp-ok");
2689 if (chip->batt_temp_ok.irq < 0) {
2690 pr_err("Unable to get bat-temp-ok irq\n");
2691 return rc;
2692 }
2693 rc = devm_request_irq(chip->dev, chip->batt_temp_ok.irq,
2694 qpnp_chg_bat_if_batt_temp_irq_handler,
2695 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
2696 "bat-temp-ok", chip);
2697 if (rc < 0) {
2698 pr_err("Can't request %d bat-temp-ok irq: %d\n",
2699 chip->batt_temp_ok.irq, rc);
2700 return rc;
2701 }
2702
2703 enable_irq_wake(chip->batt_temp_ok.irq);
2704
David Keitel0f35be42013-04-16 11:10:40 -07002705 break;
David Keitel337bd862013-07-15 21:42:58 -07002706 case SMBB_BUCK_SUBTYPE:
2707 case SMBBP_BUCK_SUBTYPE:
2708 case SMBCL_BUCK_SUBTYPE:
2709 chip->vchg_loop.irq = spmi_get_irq_byname(spmi,
2710 spmi_resource, "vchg-loop");
2711 if (chip->vchg_loop.irq < 0) {
2712 pr_err("Unable to get vchg-loop irq\n");
2713 return rc;
2714 }
2715 rc = devm_request_irq(chip->dev, chip->vchg_loop.irq,
2716 qpnp_chg_buck_vchg_loop_irq_handler,
2717 IRQF_TRIGGER_RISING,
2718 "vchg-loop", chip);
2719 if (rc < 0) {
2720 pr_err("Can't request %d vchg-loop irq: %d\n",
2721 chip->vchg_loop.irq, rc);
2722 return rc;
2723 }
2724
2725 enable_irq_wake(chip->vchg_loop.irq);
2726 qpnp_chg_disable_irq(&chip->vchg_loop);
2727 break;
2728
David Keitel0f35be42013-04-16 11:10:40 -07002729 case SMBB_USB_CHGPTH_SUBTYPE:
2730 case SMBBP_USB_CHGPTH_SUBTYPE:
2731 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002732 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002733 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07002734 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002735 pr_err("Unable to get usbin irq\n");
2736 return rc;
2737 }
David Keitel47185a62013-05-15 18:54:10 -07002738 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002739 qpnp_chg_usb_usbin_valid_irq_handler,
2740 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002741 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002742 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002743 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002744 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002745 return rc;
2746 }
David Keitel344c6972013-04-09 19:28:21 -07002747
David Keitel47185a62013-05-15 18:54:10 -07002748 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07002749 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07002750 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07002751 pr_err("Unable to get chg-gone irq\n");
2752 return rc;
2753 }
David Keitel47185a62013-05-15 18:54:10 -07002754 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07002755 qpnp_chg_usb_chg_gone_irq_handler,
2756 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07002757 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07002758 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002759 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002760 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07002761 return rc;
2762 }
David Keitel47185a62013-05-15 18:54:10 -07002763
David Keitel0b62bdd2013-07-10 17:30:51 -07002764 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
2765 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
2766 chip->usb_ocp.irq = spmi_get_irq_byname(spmi,
2767 spmi_resource, "usb-ocp");
2768 if (chip->usb_ocp.irq < 0) {
2769 pr_err("Unable to get usbin irq\n");
2770 return rc;
2771 }
2772 rc = devm_request_irq(chip->dev,
2773 chip->usb_ocp.irq,
2774 qpnp_chg_usb_usb_ocp_irq_handler,
2775 IRQF_TRIGGER_RISING, "usb-ocp", chip);
2776 if (rc < 0) {
2777 pr_err("Can't request %d usb-ocp: %d\n",
2778 chip->usb_ocp.irq, rc);
2779 return rc;
2780 }
2781
2782 enable_irq_wake(chip->usb_ocp.irq);
2783 }
2784
David Keitel47185a62013-05-15 18:54:10 -07002785 enable_irq_wake(chip->usbin_valid.irq);
2786 enable_irq_wake(chip->chg_gone.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002787 break;
2788 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002789 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002790 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07002791 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002792 pr_err("Unable to get dcin irq\n");
2793 return -rc;
2794 }
David Keitel47185a62013-05-15 18:54:10 -07002795 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002796 qpnp_chg_dc_dcin_valid_irq_handler,
2797 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002798 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002799 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002800 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002801 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002802 return rc;
2803 }
2804
David Keitel47185a62013-05-15 18:54:10 -07002805 enable_irq_wake(chip->dcin_valid.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002806 break;
2807 }
2808 }
2809
2810 return rc;
2811}
2812
Xiaozhe Shica289e02013-06-19 13:24:51 -07002813static int
2814qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
2815{
2816 struct bms_battery_data batt_data;
2817 struct device_node *node;
2818 struct qpnp_vadc_result result;
2819 int rc;
2820
2821 node = of_find_node_by_name(chip->spmi->dev.of_node,
2822 "qcom,battery-data");
2823 if (node) {
2824 memset(&batt_data, 0, sizeof(struct bms_battery_data));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07002825 rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &result);
Xiaozhe Shica289e02013-06-19 13:24:51 -07002826 if (rc) {
2827 pr_err("error reading batt id channel = %d, rc = %d\n",
2828 LR_MUX2_BAT_ID, rc);
2829 return rc;
2830 }
2831
Xiaozhe Shi23174ea2013-07-30 17:51:09 -07002832 batt_data.max_voltage_uv = -1;
2833 batt_data.iterm_ua = -1;
Xiaozhe Shica289e02013-06-19 13:24:51 -07002834 rc = of_batterydata_read_data(node,
2835 &batt_data, result.physical);
2836 if (rc) {
2837 pr_err("failed to read battery data: %d\n", rc);
2838 return rc;
2839 }
2840
Xiaozhe Shi34e568232013-07-24 12:47:34 -07002841 if (batt_data.max_voltage_uv >= 0) {
Xiaozhe Shica289e02013-06-19 13:24:51 -07002842 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
Xiaozhe Shi34e568232013-07-24 12:47:34 -07002843 chip->safe_voltage_mv = chip->max_voltage_mv
2844 + MAX_DELTA_VDD_MAX_MV;
2845 }
Xiaozhe Shica289e02013-06-19 13:24:51 -07002846 if (batt_data.iterm_ua >= 0)
2847 chip->term_current = batt_data.iterm_ua / 1000;
2848 }
2849
2850 return 0;
2851}
2852
David Keitel80668952012-07-27 14:25:49 -07002853#define WDOG_EN_BIT BIT(7)
2854static int
2855qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
2856 struct spmi_resource *spmi_resource)
2857{
2858 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07002859 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07002860 struct regulator_init_data *init_data;
2861 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07002862
2863 switch (subtype) {
2864 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002865 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002866 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07002867 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
2868 if (rc) {
2869 pr_debug("failed setting min_voltage rc=%d\n", rc);
2870 return rc;
2871 }
2872 rc = qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
2873 if (rc) {
2874 pr_debug("failed setting max_voltage rc=%d\n", rc);
2875 return rc;
2876 }
2877 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
2878 if (rc) {
2879 pr_debug("failed setting safe_voltage rc=%d\n", rc);
2880 return rc;
2881 }
David Keitel454ee842013-03-08 16:19:11 -08002882 rc = qpnp_chg_vbatdet_set(chip,
2883 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08002884 if (rc) {
2885 pr_debug("failed setting resume_voltage rc=%d\n", rc);
2886 return rc;
2887 }
David Keitel80668952012-07-27 14:25:49 -07002888 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
2889 if (rc) {
2890 pr_debug("failed setting ibatmax rc=%d\n", rc);
2891 return rc;
2892 }
David Keitel365c4c42013-03-08 16:20:40 -08002893 if (chip->term_current) {
2894 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
2895 if (rc) {
2896 pr_debug("failed setting ibatterm rc=%d\n", rc);
2897 return rc;
2898 }
David Keitel80668952012-07-27 14:25:49 -07002899 }
David Keitel5d44fa52012-12-03 16:37:31 -08002900 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
2901 if (rc) {
2902 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
2903 return rc;
2904 }
David Keitela4b7b592013-04-11 18:34:35 -07002905 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
2906 if (rc) {
2907 pr_debug("failed setting tchg_mins rc=%d\n", rc);
2908 return rc;
2909 }
2910
David Keitel80668952012-07-27 14:25:49 -07002911 /* HACK: Disable wdog */
2912 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
2913 0xFF, 0xA0, 1);
2914
David Keitelb4e43542013-04-09 17:30:41 -07002915 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07002916 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
2917 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07002918 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07002919
David Keitel80668952012-07-27 14:25:49 -07002920 break;
2921 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002922 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002923 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07002924 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
2925 if (rc)
2926 return rc;
2927
David Keitel9201df32013-01-10 18:38:34 -08002928 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07002929 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08002930 BUCK_VBAT_REG_NODE_SEL_BIT,
2931 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
2932 if (rc) {
2933 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
2934 return rc;
2935 }
David Keitel80668952012-07-27 14:25:49 -07002936 break;
2937 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002938 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002939 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07002940 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07002941 switch (chip->bpd_detection) {
2942 case BPD_TYPE_BAT_THM:
2943 reg = BAT_THM_EN;
2944 break;
2945 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07002946 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07002947 break;
2948 case BPD_TYPE_BAT_THM_BAT_ID:
2949 reg = BAT_THM_EN | BAT_ID_EN;
2950 break;
2951 default:
2952 reg = BAT_THM_EN;
2953 break;
2954 }
David Keitel796882d2013-05-14 18:01:11 -07002955
2956 rc = qpnp_chg_masked_write(chip,
2957 chip->bat_if_base + BAT_IF_BPD_CTRL,
2958 BAT_IF_BPD_CTRL_SEL,
2959 reg, 1);
2960 if (rc) {
2961 pr_debug("failed to chose BPD rc=%d\n", rc);
2962 return rc;
2963 }
David Keitel85ae4342013-04-16 11:46:00 -07002964 /* Force on VREF_BAT_THM */
2965 rc = qpnp_chg_masked_write(chip,
2966 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
2967 VREF_BATT_THERM_FORCE_ON,
2968 VREF_BATT_THERM_FORCE_ON, 1);
2969 if (rc) {
2970 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
2971 return rc;
2972 }
David Keitel80668952012-07-27 14:25:49 -07002973 break;
2974 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002975 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002976 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07002977 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07002978 rc = qpnp_chg_masked_write(chip,
2979 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
2980 ENUM_T_STOP_BIT,
2981 ENUM_T_STOP_BIT, 1);
2982 if (rc) {
2983 pr_err("failed to write enum stop rc=%d\n", rc);
2984 return -ENXIO;
2985 }
2986 }
David Keiteld681cda2012-10-02 15:44:21 -07002987
David Keitel6dc4ed42013-05-17 11:08:58 -07002988 init_data = of_get_regulator_init_data(chip->dev,
2989 spmi_resource->of_node);
2990 if (!init_data) {
2991 pr_err("unable to allocate memory\n");
2992 return -ENOMEM;
2993 }
2994
2995 if (init_data->constraints.name) {
2996 if (of_get_property(chip->dev->of_node,
2997 "otg-parent-supply", NULL))
2998 init_data->supply_regulator = "otg-parent";
2999
3000 rdesc = &(chip->otg_vreg.rdesc);
3001 rdesc->owner = THIS_MODULE;
3002 rdesc->type = REGULATOR_VOLTAGE;
3003 rdesc->ops = &qpnp_chg_otg_reg_ops;
3004 rdesc->name = init_data->constraints.name;
3005
3006 init_data->constraints.valid_ops_mask
3007 |= REGULATOR_CHANGE_STATUS;
3008
3009 chip->otg_vreg.rdev = regulator_register(rdesc,
3010 chip->dev, init_data, chip,
3011 spmi_resource->of_node);
3012 if (IS_ERR(chip->otg_vreg.rdev)) {
3013 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07003014 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07003015 if (rc != -EPROBE_DEFER)
3016 pr_err("OTG reg failed, rc=%d\n", rc);
3017 return rc;
3018 }
3019 }
3020
David Keiteld681cda2012-10-02 15:44:21 -07003021 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08003022 chip->usb_chgpth_base + USB_OVP_CTL,
3023 USB_VALID_DEB_20MS,
3024 USB_VALID_DEB_20MS, 1);
3025
3026 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07003027 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
3028 ENUM_T_STOP_BIT,
3029 ENUM_T_STOP_BIT, 1);
3030
David Keitel344c6972013-04-09 19:28:21 -07003031 rc = qpnp_chg_masked_write(chip,
3032 chip->usb_chgpth_base + SEC_ACCESS,
3033 0xFF,
3034 0xA5, 1);
3035
3036 rc = qpnp_chg_masked_write(chip,
3037 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
3038 0xFF,
3039 0x80, 1);
3040
David Keitel0b62bdd2013-07-10 17:30:51 -07003041 if ((subtype == SMBBP_USB_CHGPTH_SUBTYPE) ||
3042 (subtype == SMBCL_USB_CHGPTH_SUBTYPE)) {
3043 rc = qpnp_chg_masked_write(chip,
3044 chip->usb_chgpth_base + USB_OCP_THR,
3045 OCP_THR_MASK,
3046 OCP_THR_900_MA, 1);
3047 if (rc)
3048 pr_err("Failed to configure OCP rc = %d\n", rc);
3049 }
3050
David Keitel80668952012-07-27 14:25:49 -07003051 break;
3052 case SMBB_DC_CHGPTH_SUBTYPE:
3053 break;
3054 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003055 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07003056 init_data = of_get_regulator_init_data(chip->dev,
3057 spmi_resource->of_node);
3058 if (!init_data) {
3059 pr_err("unable to allocate memory\n");
3060 return -ENOMEM;
3061 }
3062
3063 if (init_data->constraints.name) {
3064 if (of_get_property(chip->dev->of_node,
3065 "boost-parent-supply", NULL))
3066 init_data->supply_regulator = "boost-parent";
3067
3068 rdesc = &(chip->boost_vreg.rdesc);
3069 rdesc->owner = THIS_MODULE;
3070 rdesc->type = REGULATOR_VOLTAGE;
3071 rdesc->ops = &qpnp_chg_boost_reg_ops;
3072 rdesc->name = init_data->constraints.name;
3073
3074 init_data->constraints.valid_ops_mask
3075 |= REGULATOR_CHANGE_STATUS
3076 | REGULATOR_CHANGE_VOLTAGE;
3077
3078 chip->boost_vreg.rdev = regulator_register(rdesc,
3079 chip->dev, init_data, chip,
3080 spmi_resource->of_node);
3081 if (IS_ERR(chip->boost_vreg.rdev)) {
3082 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07003083 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07003084 if (rc != -EPROBE_DEFER)
3085 pr_err("boost reg failed, rc=%d\n", rc);
3086 return rc;
3087 }
3088 }
David Keitel80668952012-07-27 14:25:49 -07003089 break;
3090 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003091 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003092 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07003093 if (subtype == SMBB_MISC_SUBTYPE)
3094 chip->type = SMBB;
3095 else if (subtype == SMBBP_MISC_SUBTYPE)
3096 chip->type = SMBBP;
3097 else if (subtype == SMBCL_MISC_SUBTYPE)
3098 chip->type = SMBCL;
3099
David Keitel80668952012-07-27 14:25:49 -07003100 pr_debug("Setting BOOT_DONE\n");
3101 rc = qpnp_chg_masked_write(chip,
3102 chip->misc_base + CHGR_MISC_BOOT_DONE,
3103 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003104 rc = qpnp_chg_read(chip, &reg,
3105 chip->misc_base + MISC_REVISION2, 1);
3106 if (rc) {
3107 pr_err("failed to read revision register rc=%d\n", rc);
3108 return rc;
3109 }
David Keitel80668952012-07-27 14:25:49 -07003110
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003111 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07003112 break;
3113 default:
3114 pr_err("Invalid peripheral subtype\n");
3115 }
3116 return rc;
3117}
3118
David Keitel112ba9c2013-04-12 18:40:43 -07003119#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
3120do { \
3121 if (retval) \
3122 break; \
3123 \
3124 retval = of_property_read_u32(chip->spmi->dev.of_node, \
3125 "qcom," qpnp_dt_property, \
3126 &chip->prop); \
3127 \
3128 if ((retval == -EINVAL) && optional) \
3129 retval = 0; \
3130 else if (retval) \
3131 pr_err("Error reading " #qpnp_dt_property \
3132 " property rc = %d\n", rc); \
3133} while (0)
3134
3135static int
3136qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
3137{
3138 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07003139 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07003140
3141 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
3142 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
3143 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
3144 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
3145 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
3146 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
3147 if (rc)
3148 pr_err("failed to read required dt parameters %d\n", rc);
3149
3150 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
3151 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
3152 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
3153 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
3154 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07003155 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07003156 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
3157 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07003158 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
3159
David Keitel112ba9c2013-04-12 18:40:43 -07003160 if (rc)
3161 return rc;
3162
David Keitel796882d2013-05-14 18:01:11 -07003163 rc = of_property_read_string(chip->spmi->dev.of_node,
3164 "qcom,bpd-detection", &bpd);
3165 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07003166 /* Select BAT_THM as default BPD scheme */
3167 chip->bpd_detection = BPD_TYPE_BAT_THM;
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003168 rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07003169 } else {
3170 chip->bpd_detection = get_bpd(bpd);
3171 if (chip->bpd_detection < 0) {
3172 pr_err("failed to determine bpd schema %d\n", rc);
3173 return rc;
3174 }
3175 }
3176
David Keitel112ba9c2013-04-12 18:40:43 -07003177 /* Look up JEITA compliance parameters if cool and warm temp provided */
3178 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003179 chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
3180 if (IS_ERR(chip->adc_tm_dev)) {
3181 rc = PTR_ERR(chip->adc_tm_dev);
3182 if (rc != -EPROBE_DEFER)
3183 pr_err("adc-tm not ready, defer probe\n");
David Keitel112ba9c2013-04-12 18:40:43 -07003184 return rc;
3185 }
3186
3187 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
3188 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
3189 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
3190 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
3191 if (rc)
3192 return rc;
3193 }
3194
David Keitel89c17752013-06-28 14:52:48 -07003195 /* Get the btc-disabled property */
3196 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
3197 "qcom,btc-disabled");
3198
David Keitel112ba9c2013-04-12 18:40:43 -07003199 /* Get the charging-disabled property */
3200 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
3201 "qcom,charging-disabled");
3202
David Keitel8b68d2d2013-05-14 23:36:51 -07003203 /* Get the duty-cycle-100p property */
3204 chip->duty_cycle_100p = of_property_read_bool(
3205 chip->spmi->dev.of_node,
3206 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07003207
David Keitel112ba9c2013-04-12 18:40:43 -07003208 /* Get the fake-batt-values property */
3209 chip->use_default_batt_values =
3210 of_property_read_bool(chip->spmi->dev.of_node,
3211 "qcom,use-default-batt-values");
3212
3213 /* Disable charging when faking battery values */
3214 if (chip->use_default_batt_values)
3215 chip->charging_disabled = true;
3216
3217 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
3218 &(chip->thermal_levels));
3219
3220 if (chip->thermal_levels > sizeof(int)) {
3221 chip->thermal_mitigation = kzalloc(
3222 chip->thermal_levels,
3223 GFP_KERNEL);
3224
3225 if (chip->thermal_mitigation == NULL) {
3226 pr_err("thermal mitigation kzalloc() failed.\n");
3227 return rc;
3228 }
3229
3230 chip->thermal_levels /= sizeof(int);
3231 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
3232 "qcom,thermal-mitigation",
3233 chip->thermal_mitigation, chip->thermal_levels);
3234 if (rc) {
3235 pr_err("qcom,thermal-mitigation missing in dt\n");
3236 return rc;
3237 }
3238 }
3239
3240 return rc;
3241}
3242
David Keitel80668952012-07-27 14:25:49 -07003243static int __devinit
3244qpnp_charger_probe(struct spmi_device *spmi)
3245{
3246 u8 subtype;
3247 struct qpnp_chg_chip *chip;
3248 struct resource *resource;
3249 struct spmi_resource *spmi_resource;
3250 int rc = 0;
3251
3252 chip = kzalloc(sizeof *chip, GFP_KERNEL);
3253 if (chip == NULL) {
3254 pr_err("kzalloc() failed.\n");
3255 return -ENOMEM;
3256 }
3257
David Keitelfd305ee2013-07-19 20:19:06 -07003258 chip->prev_usb_max_ma = -EINVAL;
David Keitel80668952012-07-27 14:25:49 -07003259 chip->dev = &(spmi->dev);
3260 chip->spmi = spmi;
3261
3262 chip->usb_psy = power_supply_get_by_name("usb");
3263 if (!chip->usb_psy) {
3264 pr_err("usb supply not found deferring probe\n");
3265 rc = -EPROBE_DEFER;
3266 goto fail_chg_enable;
3267 }
3268
David Keitelec3c09802013-06-13 13:05:30 -07003269 mutex_init(&chip->jeita_configure_lock);
David Keitel112ba9c2013-04-12 18:40:43 -07003270 /* Get all device tree properties */
3271 rc = qpnp_charger_read_dt_props(chip);
3272 if (rc)
David Keitel80668952012-07-27 14:25:49 -07003273 goto fail_chg_enable;
David Keitel3dd5e0f2012-12-12 18:12:36 -08003274
Xiaozhe Shica289e02013-06-19 13:24:51 -07003275 /*
3276 * Check if bat_if is set in DT and make sure VADC is present
3277 * Also try loading the battery data profile if bat_if exists
3278 */
David Keiteldd87a172013-05-29 17:05:43 -07003279 spmi_for_each_container_dev(spmi_resource, spmi) {
3280 if (!spmi_resource) {
3281 pr_err("qpnp_chg: spmi resource absent\n");
3282 rc = -ENXIO;
3283 goto fail_chg_enable;
3284 }
3285
3286 resource = spmi_get_resource(spmi, spmi_resource,
3287 IORESOURCE_MEM, 0);
3288 if (!(resource && resource->start)) {
3289 pr_err("node %s IO resource absent!\n",
3290 spmi->dev.of_node->full_name);
3291 rc = -ENXIO;
3292 goto fail_chg_enable;
3293 }
3294
3295 rc = qpnp_chg_read(chip, &subtype,
3296 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
3297 if (rc) {
3298 pr_err("Peripheral subtype read failed rc=%d\n", rc);
3299 goto fail_chg_enable;
3300 }
3301
3302 if (subtype == SMBB_BAT_IF_SUBTYPE ||
3303 subtype == SMBBP_BAT_IF_SUBTYPE ||
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07003304 subtype == SMBCL_BAT_IF_SUBTYPE) {
3305 chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg");
3306 if (IS_ERR(chip->vadc_dev)) {
3307 rc = PTR_ERR(chip->vadc_dev);
3308 if (rc != -EPROBE_DEFER)
3309 pr_err("vadc property missing\n");
David Keiteldd87a172013-05-29 17:05:43 -07003310 goto fail_chg_enable;
Xiaozhe Shica289e02013-06-19 13:24:51 -07003311
3312 rc = qpnp_chg_load_battery_data(chip);
3313 if (rc)
3314 goto fail_chg_enable;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07003315 }
David Keiteldd87a172013-05-29 17:05:43 -07003316 }
3317 }
3318
David Keitel80668952012-07-27 14:25:49 -07003319 spmi_for_each_container_dev(spmi_resource, spmi) {
3320 if (!spmi_resource) {
3321 pr_err("qpnp_chg: spmi resource absent\n");
3322 rc = -ENXIO;
3323 goto fail_chg_enable;
3324 }
3325
3326 resource = spmi_get_resource(spmi, spmi_resource,
3327 IORESOURCE_MEM, 0);
3328 if (!(resource && resource->start)) {
3329 pr_err("node %s IO resource absent!\n",
3330 spmi->dev.of_node->full_name);
3331 rc = -ENXIO;
3332 goto fail_chg_enable;
3333 }
3334
3335 rc = qpnp_chg_read(chip, &subtype,
3336 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
3337 if (rc) {
3338 pr_err("Peripheral subtype read failed rc=%d\n", rc);
3339 goto fail_chg_enable;
3340 }
3341
3342 switch (subtype) {
3343 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003344 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003345 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003346 chip->chgr_base = resource->start;
3347 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3348 if (rc) {
3349 pr_err("Failed to init subtype 0x%x rc=%d\n",
3350 subtype, rc);
3351 goto fail_chg_enable;
3352 }
3353 break;
3354 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003355 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003356 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003357 chip->buck_base = resource->start;
3358 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3359 if (rc) {
3360 pr_err("Failed to init subtype 0x%x rc=%d\n",
3361 subtype, rc);
3362 goto fail_chg_enable;
3363 }
David Keitel344c6972013-04-09 19:28:21 -07003364
3365 rc = qpnp_chg_masked_write(chip,
3366 chip->buck_base + SEC_ACCESS,
3367 0xFF,
3368 0xA5, 1);
3369
3370 rc = qpnp_chg_masked_write(chip,
3371 chip->buck_base + BUCK_VCHG_OV,
3372 0xff,
3373 0x00, 1);
3374
3375 rc = qpnp_chg_masked_write(chip,
3376 chip->buck_base + SEC_ACCESS,
3377 0xFF,
3378 0xA5, 1);
3379
3380 rc = qpnp_chg_masked_write(chip,
3381 chip->buck_base + BUCK_TEST_SMBC_MODES,
3382 0xFF,
3383 0x80, 1);
3384
David Keiteldbc949b2013-07-11 10:56:03 -07003385 if (chip->duty_cycle_100p) {
3386 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
3387 1);
3388 if (rc) {
3389 pr_err("failed to set duty cycle %d\n",
3390 rc);
3391 goto fail_chg_enable;
3392 }
3393 }
3394
David Keitel80668952012-07-27 14:25:49 -07003395 break;
3396 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003397 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003398 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003399 chip->bat_if_base = resource->start;
3400 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3401 if (rc) {
3402 pr_err("Failed to init subtype 0x%x rc=%d\n",
3403 subtype, rc);
3404 goto fail_chg_enable;
3405 }
3406 break;
3407 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003408 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003409 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003410 chip->usb_chgpth_base = resource->start;
3411 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3412 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07003413 if (rc != -EPROBE_DEFER)
3414 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07003415 subtype, rc);
3416 goto fail_chg_enable;
3417 }
3418 break;
3419 case SMBB_DC_CHGPTH_SUBTYPE:
3420 chip->dc_chgpth_base = resource->start;
3421 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3422 if (rc) {
3423 pr_err("Failed to init subtype 0x%x rc=%d\n",
3424 subtype, rc);
3425 goto fail_chg_enable;
3426 }
3427 break;
3428 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003429 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003430 chip->boost_base = resource->start;
3431 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3432 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07003433 if (rc != -EPROBE_DEFER)
3434 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07003435 subtype, rc);
3436 goto fail_chg_enable;
3437 }
3438 break;
3439 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003440 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003441 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003442 chip->misc_base = resource->start;
3443 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3444 if (rc) {
3445 pr_err("Failed to init subtype=0x%x rc=%d\n",
3446 subtype, rc);
3447 goto fail_chg_enable;
3448 }
3449 break;
3450 default:
3451 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
3452 rc = -EINVAL;
3453 goto fail_chg_enable;
3454 }
3455 }
3456 dev_set_drvdata(&spmi->dev, chip);
3457 device_init_wakeup(&spmi->dev, 1);
3458
David Keitelf2170cc2013-02-20 17:49:03 -08003459 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08003460 chip->batt_psy.name = "battery";
3461 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
3462 chip->batt_psy.properties = msm_batt_power_props;
3463 chip->batt_psy.num_properties =
3464 ARRAY_SIZE(msm_batt_power_props);
3465 chip->batt_psy.get_property = qpnp_batt_power_get_property;
3466 chip->batt_psy.set_property = qpnp_batt_power_set_property;
3467 chip->batt_psy.property_is_writeable =
3468 qpnp_batt_property_is_writeable;
3469 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07003470 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07003471 chip->batt_psy.supplied_to = pm_batt_supplied_to;
3472 chip->batt_psy.num_supplicants =
3473 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07003474
David Keitelf2170cc2013-02-20 17:49:03 -08003475 rc = power_supply_register(chip->dev, &chip->batt_psy);
3476 if (rc < 0) {
3477 pr_err("batt failed to register rc = %d\n", rc);
3478 goto fail_chg_enable;
3479 }
David Keitel79f4c932013-04-03 16:08:39 -07003480 INIT_WORK(&chip->adc_measure_work,
3481 qpnp_bat_if_adc_measure_work);
David Keitelc7093b02013-02-14 12:50:04 -08003482 }
3483
David Keitel9fd07382013-05-02 15:37:44 -07003484 wake_lock_init(&chip->eoc_wake_lock,
3485 WAKE_LOCK_SUSPEND, "qpnp-chg-eoc-lock");
3486 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07003487 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
3488
David Keitelf2170cc2013-02-20 17:49:03 -08003489 if (chip->dc_chgpth_base) {
3490 chip->dc_psy.name = "qpnp-dc";
3491 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
3492 chip->dc_psy.supplied_to = pm_power_supplied_to;
3493 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
3494 chip->dc_psy.properties = pm_power_props_mains;
3495 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
3496 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07003497 chip->dc_psy.set_property = qpnp_dc_power_set_property;
3498 chip->dc_psy.property_is_writeable =
3499 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08003500
3501 rc = power_supply_register(chip->dev, &chip->dc_psy);
3502 if (rc < 0) {
3503 pr_err("power_supply_register dc failed rc=%d\n", rc);
3504 goto unregister_batt;
3505 }
David Keitel80668952012-07-27 14:25:49 -07003506 }
3507
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003508 /* Turn on appropriate workaround flags */
3509 qpnp_chg_setup_flags(chip);
3510
David Keitelf2170cc2013-02-20 17:49:03 -08003511 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08003512 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
3513 if (rc) {
3514 pr_err("Error setting idcmax property %d\n", rc);
David Keitelf2170cc2013-02-20 17:49:03 -08003515 goto unregister_batt;
David Keitel22ed2232013-01-28 11:04:07 -08003516 }
3517 }
3518
David Keitel0aea18a2013-06-14 18:57:57 -07003519 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
3520 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07003521 chip->adc_param.low_temp = chip->cool_bat_decidegc;
3522 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08003523 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
3524 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
3525 chip->adc_param.btm_ctx = chip;
3526 chip->adc_param.threshold_notification =
3527 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08003528 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07003529
3530 if (get_prop_batt_present(chip)) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003531 rc = qpnp_adc_tm_channel_measure(chip->adc_tm_dev,
3532 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07003533 if (rc) {
3534 pr_err("request ADC error %d\n", rc);
3535 goto fail_chg_enable;
3536 }
David Keitel454ee842013-03-08 16:19:11 -08003537 }
3538 }
David Keitel89c17752013-06-28 14:52:48 -07003539 rc = qpnp_chg_bat_if_configure_btc(chip);
3540 if (rc) {
3541 pr_err("failed to configure btc %d\n", rc);
3542 goto unregister_batt;
3543 }
David Keitel454ee842013-03-08 16:19:11 -08003544
David Keitel03ee6b52012-10-22 12:25:19 -07003545 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08003546 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003547 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07003548
David Keitel0f35be42013-04-16 11:10:40 -07003549 rc = qpnp_chg_request_irqs(chip);
3550 if (rc) {
3551 pr_err("failed to request interrupts %d\n", rc);
3552 goto unregister_batt;
3553 }
3554
David Keitel9fd07382013-05-02 15:37:44 -07003555 qpnp_chg_usb_usbin_valid_irq_handler(USBIN_VALID_IRQ, chip);
David Keiteld2efc392013-06-05 16:27:12 -07003556 qpnp_chg_dc_dcin_valid_irq_handler(DCIN_VALID_IRQ, chip);
David Keitel9fd07382013-05-02 15:37:44 -07003557 power_supply_set_present(chip->usb_psy,
3558 qpnp_chg_is_usb_chg_plugged_in(chip));
3559
David Keitel3c62b472013-05-06 15:38:11 -07003560 /* Set USB psy online to avoid userspace from shutting down if battery
3561 * capacity is at zero and no chargers online. */
3562 if (qpnp_chg_is_usb_chg_plugged_in(chip))
3563 power_supply_set_online(chip->usb_psy, 1);
3564
David Keitel796882d2013-05-14 18:01:11 -07003565 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 -08003566 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07003567 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08003568 qpnp_chg_is_usb_chg_plugged_in(chip),
3569 qpnp_chg_is_dc_chg_plugged_in(chip),
3570 get_prop_batt_present(chip),
3571 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07003572 return 0;
3573
David Keitelc7093b02013-02-14 12:50:04 -08003574unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08003575 if (chip->bat_if_base)
3576 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07003577fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07003578 regulator_unregister(chip->otg_vreg.rdev);
3579 regulator_unregister(chip->boost_vreg.rdev);
David Keitelbe208252013-01-31 14:49:25 -08003580 kfree(chip->thermal_mitigation);
David Keitel80668952012-07-27 14:25:49 -07003581 kfree(chip);
3582 dev_set_drvdata(&spmi->dev, NULL);
3583 return rc;
3584}
3585
3586static int __devexit
3587qpnp_charger_remove(struct spmi_device *spmi)
3588{
3589 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
David Keitel0c1a4532013-03-21 16:39:06 -07003590 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
3591 && chip->batt_present) {
Siddartha Mohanadoss88a3fde2013-06-24 16:18:52 -07003592 qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
3593 &chip->adc_param);
David Keitel0c1a4532013-03-21 16:39:06 -07003594 }
David Keitel79f4c932013-04-03 16:08:39 -07003595 cancel_work_sync(&chip->adc_measure_work);
David Keitel9fd07382013-05-02 15:37:44 -07003596 cancel_delayed_work_sync(&chip->eoc_work);
David Keitel79f4c932013-04-03 16:08:39 -07003597
David Collinscbb12132013-05-28 10:47:28 -07003598 regulator_unregister(chip->otg_vreg.rdev);
3599 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07003600
David Keitel80668952012-07-27 14:25:49 -07003601 dev_set_drvdata(&spmi->dev, NULL);
3602 kfree(chip);
3603
3604 return 0;
3605}
3606
David Keitel85ae4342013-04-16 11:46:00 -07003607static int qpnp_chg_resume(struct device *dev)
3608{
3609 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
3610 int rc = 0;
3611
David Keitel39093572013-06-05 15:32:30 -07003612 if (chip->bat_if_base) {
3613 rc = qpnp_chg_masked_write(chip,
3614 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
3615 VREF_BATT_THERM_FORCE_ON,
3616 VREF_BATT_THERM_FORCE_ON, 1);
3617 if (rc)
3618 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
3619 }
David Keitel85ae4342013-04-16 11:46:00 -07003620
3621 return rc;
3622}
3623
3624static int qpnp_chg_suspend(struct device *dev)
3625{
3626 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
3627 int rc = 0;
3628
David Keitel39093572013-06-05 15:32:30 -07003629 if (chip->bat_if_base) {
3630 rc = qpnp_chg_masked_write(chip,
3631 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
3632 VREF_BATT_THERM_FORCE_ON,
3633 VREF_BAT_THM_ENABLED_FSM, 1);
3634 if (rc)
3635 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
3636 }
David Keitel85ae4342013-04-16 11:46:00 -07003637
3638 return rc;
3639}
3640
David Keitel723d5012013-05-03 13:17:27 -07003641static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07003642 .resume = qpnp_chg_resume,
3643 .suspend = qpnp_chg_suspend,
3644};
3645
David Keitel80668952012-07-27 14:25:49 -07003646static struct spmi_driver qpnp_charger_driver = {
3647 .probe = qpnp_charger_probe,
3648 .remove = __devexit_p(qpnp_charger_remove),
3649 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07003650 .name = QPNP_CHARGER_DEV_NAME,
3651 .owner = THIS_MODULE,
3652 .of_match_table = qpnp_charger_match_table,
3653 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07003654 },
3655};
3656
3657/**
3658 * qpnp_chg_init() - register spmi driver for qpnp-chg
3659 */
3660int __init
3661qpnp_chg_init(void)
3662{
3663 return spmi_driver_register(&qpnp_charger_driver);
3664}
3665module_init(qpnp_chg_init);
3666
3667static void __exit
3668qpnp_chg_exit(void)
3669{
3670 spmi_driver_unregister(&qpnp_charger_driver);
3671}
3672module_exit(qpnp_chg_exit);
3673
3674
3675MODULE_DESCRIPTION("QPNP charger driver");
3676MODULE_LICENSE("GPL v2");
3677MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);