blob: 364c76fb9385239aa85c8ceecefa154eaaebbae0 [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 Keitel33f58952013-05-20 16:17:36 -0700103
David Keitel80668952012-07-27 14:25:49 -0700104#define REG_OFFSET_PERP_SUBTYPE 0x05
David Keitel6dc4ed42013-05-17 11:08:58 -0700105
David Keitelf2170cc2013-02-20 17:49:03 -0800106/* SMBB peripheral subtype values */
David Keitel80668952012-07-27 14:25:49 -0700107#define SMBB_CHGR_SUBTYPE 0x01
108#define SMBB_BUCK_SUBTYPE 0x02
109#define SMBB_BAT_IF_SUBTYPE 0x03
110#define SMBB_USB_CHGPTH_SUBTYPE 0x04
111#define SMBB_DC_CHGPTH_SUBTYPE 0x05
112#define SMBB_BOOST_SUBTYPE 0x06
113#define SMBB_MISC_SUBTYPE 0x07
114
David Keitelf2170cc2013-02-20 17:49:03 -0800115/* SMBB peripheral subtype values */
116#define SMBBP_CHGR_SUBTYPE 0x31
117#define SMBBP_BUCK_SUBTYPE 0x32
118#define SMBBP_BAT_IF_SUBTYPE 0x33
119#define SMBBP_USB_CHGPTH_SUBTYPE 0x34
120#define SMBBP_BOOST_SUBTYPE 0x36
121#define SMBBP_MISC_SUBTYPE 0x37
122
David Keitel46c9f7b2013-04-02 19:54:12 -0700123/* SMBCL peripheral subtype values */
124#define SMBCL_CHGR_SUBTYPE 0x41
125#define SMBCL_BUCK_SUBTYPE 0x42
126#define SMBCL_BAT_IF_SUBTYPE 0x43
127#define SMBCL_USB_CHGPTH_SUBTYPE 0x44
128#define SMBCL_MISC_SUBTYPE 0x47
129
David Keitel80668952012-07-27 14:25:49 -0700130#define QPNP_CHARGER_DEV_NAME "qcom,qpnp-charger"
131
David Keitelb80eda82012-10-15 10:49:11 -0700132/* Status bits and masks */
133#define CHGR_BOOT_DONE BIT(7)
134#define CHGR_CHG_EN BIT(7)
135#define CHGR_ON_BAT_FORCE_BIT BIT(0)
David Keitel5c3a7702012-12-20 11:13:21 -0800136#define USB_VALID_DEB_20MS 0x03
David Keitel9201df32013-01-10 18:38:34 -0800137#define BUCK_VBAT_REG_NODE_SEL_BIT BIT(0)
David Keitel85ae4342013-04-16 11:46:00 -0700138#define VREF_BATT_THERM_FORCE_ON 0xC0
David Keitel796882d2013-05-14 18:01:11 -0700139#define BAT_IF_BPD_CTRL_SEL 0x03
David Keitel85ae4342013-04-16 11:46:00 -0700140#define VREF_BAT_THM_ENABLED_FSM 0x80
David Keitel796882d2013-05-14 18:01:11 -0700141#define REV_BST_DETECTED BIT(0)
142#define BAT_THM_EN BIT(1)
143#define BAT_ID_EN BIT(0)
David Keitel6dc4ed42013-05-17 11:08:58 -0700144#define BOOST_PWR_EN BIT(7)
David Keitelb80eda82012-10-15 10:49:11 -0700145
David Keitel80668952012-07-27 14:25:49 -0700146/* Interrupt definitions */
147/* smbb_chg_interrupts */
148#define CHG_DONE_IRQ BIT(7)
149#define CHG_FAILED_IRQ BIT(6)
150#define FAST_CHG_ON_IRQ BIT(5)
151#define TRKL_CHG_ON_IRQ BIT(4)
152#define STATE_CHANGE_ON_IR BIT(3)
153#define CHGWDDOG_IRQ BIT(2)
154#define VBAT_DET_HI_IRQ BIT(1)
155#define VBAT_DET_LOW_IRQ BIT(0)
156
157/* smbb_buck_interrupts */
158#define VDD_LOOP_IRQ BIT(6)
159#define IBAT_LOOP_IRQ BIT(5)
160#define ICHG_LOOP_IRQ BIT(4)
161#define VCHG_LOOP_IRQ BIT(3)
162#define OVERTEMP_IRQ BIT(2)
163#define VREF_OV_IRQ BIT(1)
164#define VBAT_OV_IRQ BIT(0)
165
166/* smbb_bat_if_interrupts */
167#define PSI_IRQ BIT(4)
168#define VCP_ON_IRQ BIT(3)
169#define BAT_FET_ON_IRQ BIT(2)
170#define BAT_TEMP_OK_IRQ BIT(1)
171#define BATT_PRES_IRQ BIT(0)
172
173/* smbb_usb_interrupts */
174#define CHG_GONE_IRQ BIT(2)
175#define USBIN_VALID_IRQ BIT(1)
176#define COARSE_DET_USB_IRQ BIT(0)
177
178/* smbb_dc_interrupts */
179#define DCIN_VALID_IRQ BIT(1)
180#define COARSE_DET_DC_IRQ BIT(0)
181
182/* smbb_boost_interrupts */
183#define LIMIT_ERROR_IRQ BIT(1)
184#define BOOST_PWR_OK_IRQ BIT(0)
185
186/* smbb_misc_interrupts */
187#define TFTWDOG_IRQ BIT(0)
188
David Keitelfe51cb92013-04-02 19:42:58 -0700189/* SMBB types */
190#define SMBB BIT(1)
191#define SMBBP BIT(2)
192#define SMBCL BIT(3)
193
David Keiteld681cda2012-10-02 15:44:21 -0700194/* Workaround flags */
195#define CHG_FLAGS_VCP_WA BIT(0)
David Keitel33f58952013-05-20 16:17:36 -0700196#define BOOST_FLASH_WA BIT(1)
David Keiteld681cda2012-10-02 15:44:21 -0700197
David Keitel47185a62013-05-15 18:54:10 -0700198struct qpnp_chg_irq {
199 unsigned int irq;
200 unsigned long disabled;
201};
202
David Keitel6dc4ed42013-05-17 11:08:58 -0700203struct qpnp_chg_regulator {
204 struct regulator_desc rdesc;
205 struct regulator_dev *rdev;
206};
207
David Keitel80668952012-07-27 14:25:49 -0700208/**
209 * struct qpnp_chg_chip - device information
210 * @dev: device pointer to access the parent
211 * @spmi: spmi pointer to access spmi information
212 * @chgr_base: charger peripheral base address
213 * @buck_base: buck peripheral base address
214 * @bat_if_base: battery interface peripheral base address
215 * @usb_chgpth_base: USB charge path peripheral base address
216 * @dc_chgpth_base: DC charge path peripheral base address
217 * @boost_base: boost peripheral base address
218 * @misc_base: misc peripheral base address
219 * @freq_base: freq peripheral base address
David Keitel454ee842013-03-08 16:19:11 -0800220 * @bat_is_cool: indicates that battery is cool
221 * @bat_is_warm: indicates that battery is warm
David Keitel80668952012-07-27 14:25:49 -0700222 * @chg_done: indicates that charging is completed
223 * @usb_present: present status of usb
224 * @dc_present: present status of dc
David Keitel42ae0aa2013-03-08 16:20:10 -0800225 * @batt_present: present status of battery
David Keitel3dd5e0f2012-12-12 18:12:36 -0800226 * @use_default_batt_values: flag to report default battery properties
David Keitel89c17752013-06-28 14:52:48 -0700227 * @btc_disabled Flag to disable btc (disables hot and cold irqs)
David Keitel80668952012-07-27 14:25:49 -0700228 * @max_voltage_mv: the max volts the batt should be charged up to
David Keitel5d44fa52012-12-03 16:37:31 -0800229 * @min_voltage_mv: min battery voltage before turning the FET on
David Keitel454ee842013-03-08 16:19:11 -0800230 * @max_bat_chg_current: maximum battery charge current in mA
231 * @warm_bat_chg_ma: warm battery maximum charge current in mA
232 * @cool_bat_chg_ma: cool battery maximum charge current in mA
233 * @warm_bat_mv: warm temperature battery target voltage
234 * @cool_bat_mv: cool temperature battery target voltage
235 * @resume_delta_mv: voltage delta at which battery resumes charging
David Keitel80668952012-07-27 14:25:49 -0700236 * @term_current: the charging based term current
David Keitel5d44fa52012-12-03 16:37:31 -0800237 * @safe_current: battery safety current setting
David Keitel22ed2232013-01-28 11:04:07 -0800238 * @maxinput_usb_ma: Maximum Input current USB
239 * @maxinput_dc_ma: Maximum Input current DC
David Keitel89c17752013-06-28 14:52:48 -0700240 * @hot_batt_p Hot battery threshold setting
241 * @cold_batt_p Cold battery threshold setting
David Keitel0c1a4532013-03-21 16:39:06 -0700242 * @warm_bat_decidegc Warm battery temperature in degree Celsius
243 * @cool_bat_decidegc Cool battery temperature in degree Celsius
David Keitel80668952012-07-27 14:25:49 -0700244 * @revision: PMIC revision
David Keitelfe51cb92013-04-02 19:42:58 -0700245 * @type: SMBB type
246 * @tchg_mins maximum allowed software initiated charge time
David Keitelbe208252013-01-31 14:49:25 -0800247 * @thermal_levels amount of thermal mitigation levels
248 * @thermal_mitigation thermal mitigation level values
249 * @therm_lvl_sel thermal mitigation level selection
David Keitel80668952012-07-27 14:25:49 -0700250 * @dc_psy power supply to export information to userspace
251 * @usb_psy power supply to export information to userspace
252 * @bms_psy power supply to export information to userspace
253 * @batt_psy: power supply to export information to userspace
David Keiteld681cda2012-10-02 15:44:21 -0700254 * @flags: flags to activate specific workarounds
255 * throughout the driver
David Keitel80668952012-07-27 14:25:49 -0700256 *
257 */
258struct qpnp_chg_chip {
259 struct device *dev;
260 struct spmi_device *spmi;
261 u16 chgr_base;
262 u16 buck_base;
263 u16 bat_if_base;
264 u16 usb_chgpth_base;
265 u16 dc_chgpth_base;
266 u16 boost_base;
267 u16 misc_base;
268 u16 freq_base;
David Keitel47185a62013-05-15 18:54:10 -0700269 struct qpnp_chg_irq usbin_valid;
270 struct qpnp_chg_irq dcin_valid;
271 struct qpnp_chg_irq chg_gone;
272 struct qpnp_chg_irq chg_fastchg;
273 struct qpnp_chg_irq chg_trklchg;
274 struct qpnp_chg_irq chg_failed;
275 struct qpnp_chg_irq chg_vbatdet_lo;
276 struct qpnp_chg_irq batt_pres;
David Keitel454ee842013-03-08 16:19:11 -0800277 bool bat_is_cool;
278 bool bat_is_warm;
David Keitel80668952012-07-27 14:25:49 -0700279 bool chg_done;
280 bool usb_present;
281 bool dc_present;
David Keitel42ae0aa2013-03-08 16:20:10 -0800282 bool batt_present;
David Keitel03ee6b52012-10-22 12:25:19 -0700283 bool charging_disabled;
David Keitel89c17752013-06-28 14:52:48 -0700284 bool btc_disabled;
David Keitel3dd5e0f2012-12-12 18:12:36 -0800285 bool use_default_batt_values;
David Keitel8b68d2d2013-05-14 23:36:51 -0700286 bool duty_cycle_100p;
David Keitel796882d2013-05-14 18:01:11 -0700287 unsigned int bpd_detection;
David Keitel80668952012-07-27 14:25:49 -0700288 unsigned int max_bat_chg_current;
David Keitel454ee842013-03-08 16:19:11 -0800289 unsigned int warm_bat_chg_ma;
290 unsigned int cool_bat_chg_ma;
David Keitel80668952012-07-27 14:25:49 -0700291 unsigned int safe_voltage_mv;
292 unsigned int max_voltage_mv;
293 unsigned int min_voltage_mv;
Xiaozhe Shi79a8c492013-05-24 13:09:23 -0700294 int set_vddmax_mv;
295 int delta_vddmax_mv;
David Keitel454ee842013-03-08 16:19:11 -0800296 unsigned int warm_bat_mv;
297 unsigned int cool_bat_mv;
298 unsigned int resume_delta_mv;
David Keitel9fd07382013-05-02 15:37:44 -0700299 int term_current;
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700300 int soc_resume_limit;
301 bool resuming_charging;
David Keitel22ed2232013-01-28 11:04:07 -0800302 unsigned int maxinput_usb_ma;
303 unsigned int maxinput_dc_ma;
David Keitel89c17752013-06-28 14:52:48 -0700304 unsigned int hot_batt_p;
305 unsigned int cold_batt_p;
David Keitel0c1a4532013-03-21 16:39:06 -0700306 unsigned int warm_bat_decidegc;
307 unsigned int cool_bat_decidegc;
David Keitel5d44fa52012-12-03 16:37:31 -0800308 unsigned int safe_current;
David Keitel80668952012-07-27 14:25:49 -0700309 unsigned int revision;
David Keitelfe51cb92013-04-02 19:42:58 -0700310 unsigned int type;
311 unsigned int tchg_mins;
David Keitelbe208252013-01-31 14:49:25 -0800312 unsigned int thermal_levels;
313 unsigned int therm_lvl_sel;
314 unsigned int *thermal_mitigation;
David Keitel80668952012-07-27 14:25:49 -0700315 struct power_supply dc_psy;
316 struct power_supply *usb_psy;
317 struct power_supply *bms_psy;
318 struct power_supply batt_psy;
David Keiteld681cda2012-10-02 15:44:21 -0700319 uint32_t flags;
David Keitel454ee842013-03-08 16:19:11 -0800320 struct qpnp_adc_tm_btm_param adc_param;
David Keitel79f4c932013-04-03 16:08:39 -0700321 struct work_struct adc_measure_work;
David Keitel344c6972013-04-09 19:28:21 -0700322 struct delayed_work arb_stop_work;
David Keitel9fd07382013-05-02 15:37:44 -0700323 struct delayed_work eoc_work;
324 struct wake_lock eoc_wake_lock;
David Keitel6dc4ed42013-05-17 11:08:58 -0700325 struct qpnp_chg_regulator otg_vreg;
326 struct qpnp_chg_regulator boost_vreg;
David Keitel80668952012-07-27 14:25:49 -0700327};
328
David Keitel47185a62013-05-15 18:54:10 -0700329
David Keitel80668952012-07-27 14:25:49 -0700330static struct of_device_id qpnp_charger_match_table[] = {
331 { .compatible = QPNP_CHARGER_DEV_NAME, },
332 {}
333};
334
David Keitel0ef282b2013-05-29 16:04:57 -0700335enum bpd_type {
336 BPD_TYPE_BAT_ID,
337 BPD_TYPE_BAT_THM,
338 BPD_TYPE_BAT_THM_BAT_ID,
339};
David Keitel796882d2013-05-14 18:01:11 -0700340
David Keitel0ef282b2013-05-29 16:04:57 -0700341static const char * const bpd_label[] = {
342 [BPD_TYPE_BAT_ID] = "bpd_id",
343 [BPD_TYPE_BAT_THM] = "bpd_thm",
344 [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
David Keitel796882d2013-05-14 18:01:11 -0700345};
346
David Keitel89c17752013-06-28 14:52:48 -0700347enum btc_type {
348 HOT_THD_25_PCT = 25,
349 HOT_THD_35_PCT = 35,
350 COLD_THD_70_PCT = 70,
351 COLD_THD_80_PCT = 80,
352};
353
354static u8 btc_value[] = {
355 [HOT_THD_25_PCT] = 0x0,
356 [HOT_THD_35_PCT] = BIT(0),
357 [COLD_THD_70_PCT] = 0x0,
358 [COLD_THD_80_PCT] = BIT(1),
359};
360
361 static inline int
David Keitel796882d2013-05-14 18:01:11 -0700362get_bpd(const char *name)
363{
364 int i = 0;
David Keitel0ef282b2013-05-29 16:04:57 -0700365 for (i = 0; i < ARRAY_SIZE(bpd_label); i++) {
366 if (strcmp(bpd_label[i], name) == 0)
David Keitel796882d2013-05-14 18:01:11 -0700367 return i;
368 }
369 return -EINVAL;
370}
371
David Keitel80668952012-07-27 14:25:49 -0700372static int
373qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
374 u16 base, int count)
375{
David Keitel39093572013-06-05 15:32:30 -0700376 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700377 struct spmi_device *spmi = chip->spmi;
378
David Keitel39093572013-06-05 15:32:30 -0700379 if (base == 0) {
380 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
381 base, spmi->sid, rc);
382 return -EINVAL;
383 }
384
385 rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700386 if (rc) {
387 pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
388 spmi->sid, rc);
389 return rc;
390 }
391 return 0;
392}
393
394static int
395qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
396 u16 base, int count)
397{
David Keitel39093572013-06-05 15:32:30 -0700398 int rc = 0;
David Keitel80668952012-07-27 14:25:49 -0700399 struct spmi_device *spmi = chip->spmi;
400
David Keitel39093572013-06-05 15:32:30 -0700401 if (base == 0) {
402 pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
403 base, spmi->sid, rc);
404 return -EINVAL;
405 }
406
407 rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
David Keitel80668952012-07-27 14:25:49 -0700408 if (rc) {
409 pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
410 base, spmi->sid, rc);
411 return rc;
412 }
413
414 return 0;
415}
416
417static int
418qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
419 u8 mask, u8 val, int count)
420{
421 int rc;
422 u8 reg;
423
424 rc = qpnp_chg_read(chip, &reg, base, count);
425 if (rc) {
426 pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
427 return rc;
428 }
429 pr_debug("addr = 0x%x read 0x%x\n", base, reg);
430
431 reg &= ~mask;
432 reg |= val & mask;
433
434 pr_debug("Writing 0x%x\n", reg);
435
436 rc = qpnp_chg_write(chip, &reg, base, count);
437 if (rc) {
438 pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
439 return rc;
440 }
441
442 return 0;
443}
444
David Keitel47185a62013-05-15 18:54:10 -0700445static void
446qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
447{
448 if (__test_and_clear_bit(0, &irq->disabled)) {
449 pr_debug("number = %d\n", irq->irq);
450 enable_irq(irq->irq);
451 }
452}
453
454static void
455qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
456{
457 if (!__test_and_set_bit(0, &irq->disabled)) {
458 pr_debug("number = %d\n", irq->irq);
459 disable_irq_nosync(irq->irq);
460 }
461}
462
David Keitel6f865cd2012-11-30 15:04:32 -0800463#define USB_OTG_EN_BIT BIT(0)
464static int
465qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
466{
467 u8 usb_otg_en;
468 int rc;
469
470 rc = qpnp_chg_read(chip, &usb_otg_en,
471 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
472 1);
473
474 if (rc) {
475 pr_err("spmi read failed: addr=%03X, rc=%d\n",
476 chip->usb_chgpth_base + CHGR_STATUS, rc);
477 return rc;
478 }
479 pr_debug("usb otg en 0x%x\n", usb_otg_en);
480
481 return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
482}
483
David Keitel42ae0aa2013-03-08 16:20:10 -0800484static int
David Keitel6dc4ed42013-05-17 11:08:58 -0700485qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
486{
487 u8 boost_en_ctl;
488 int rc;
489
490 rc = qpnp_chg_read(chip, &boost_en_ctl,
491 chip->boost_base + BOOST_ENABLE_CONTROL, 1);
492 if (rc) {
493 pr_err("spmi read failed: addr=%03X, rc=%d\n",
494 chip->boost_base + BOOST_ENABLE_CONTROL, rc);
495 return rc;
496 }
497
498 pr_debug("boost en 0x%x\n", boost_en_ctl);
499
500 return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
501}
502
503static int
David Keitel42ae0aa2013-03-08 16:20:10 -0800504qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
505{
506 u8 batt_pres_rt_sts;
507 int rc;
508
509 rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
510 INT_RT_STS(chip->bat_if_base), 1);
511 if (rc) {
512 pr_err("spmi read failed: addr=%03X, rc=%d\n",
513 INT_RT_STS(chip->bat_if_base), rc);
514 return rc;
515 }
516
517 return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
518}
519
David Keiteld681cda2012-10-02 15:44:21 -0700520#define USB_VALID_BIT BIT(7)
David Keitel80668952012-07-27 14:25:49 -0700521static int
522qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
523{
524 u8 usbin_valid_rt_sts;
525 int rc;
526
527 rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
David Keiteld681cda2012-10-02 15:44:21 -0700528 chip->usb_chgpth_base + CHGR_STATUS , 1);
David Keitel80668952012-07-27 14:25:49 -0700529
530 if (rc) {
531 pr_err("spmi read failed: addr=%03X, rc=%d\n",
David Keiteld681cda2012-10-02 15:44:21 -0700532 chip->usb_chgpth_base + CHGR_STATUS, rc);
David Keitel80668952012-07-27 14:25:49 -0700533 return rc;
534 }
535 pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
536
David Keiteld681cda2012-10-02 15:44:21 -0700537 return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
David Keitel80668952012-07-27 14:25:49 -0700538}
539
540static int
541qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
542{
543 u8 dcin_valid_rt_sts;
544 int rc;
545
David Keitelf2170cc2013-02-20 17:49:03 -0800546 if (!chip->dc_chgpth_base)
547 return 0;
548
David Keitel80668952012-07-27 14:25:49 -0700549 rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
550 INT_RT_STS(chip->dc_chgpth_base), 1);
551 if (rc) {
552 pr_err("spmi read failed: addr=%03X, rc=%d\n",
553 INT_RT_STS(chip->dc_chgpth_base), rc);
554 return rc;
555 }
556
557 return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
558}
559
David Keitel22ed2232013-01-28 11:04:07 -0800560#define QPNP_CHG_I_MAX_MIN_100 100
561#define QPNP_CHG_I_MAX_MIN_150 150
562#define QPNP_CHG_I_MAX_MIN_MA 200
563#define QPNP_CHG_I_MAX_MAX_MA 2500
564#define QPNP_CHG_I_MAXSTEP_MA 100
565static int
566qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
567{
568 int rc = 0;
569 u8 dc = 0;
570
571 if (mA < QPNP_CHG_I_MAX_MIN_100
572 || mA > QPNP_CHG_I_MAX_MAX_MA) {
573 pr_err("bad mA=%d asked to set\n", mA);
574 return -EINVAL;
575 }
576
577 if (mA == QPNP_CHG_I_MAX_MIN_100) {
578 dc = 0x00;
579 pr_debug("current=%d setting %02x\n", mA, dc);
580 return qpnp_chg_write(chip, &dc,
581 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
582 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
583 dc = 0x01;
584 pr_debug("current=%d setting %02x\n", mA, dc);
585 return qpnp_chg_write(chip, &dc,
586 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
587 }
588
589 dc = mA / QPNP_CHG_I_MAXSTEP_MA;
590
591 pr_debug("current=%d setting 0x%x\n", mA, dc);
592 rc = qpnp_chg_write(chip, &dc,
593 chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
594
595 return rc;
596}
597
David Keitel80668952012-07-27 14:25:49 -0700598static int
599qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
600{
David Keiteld681cda2012-10-02 15:44:21 -0700601 int rc = 0;
602 u8 usb_reg = 0, temp = 8;
David Keitel80668952012-07-27 14:25:49 -0700603
David Keitel22ed2232013-01-28 11:04:07 -0800604 if (mA < QPNP_CHG_I_MAX_MIN_100
605 || mA > QPNP_CHG_I_MAX_MAX_MA) {
David Keitel80668952012-07-27 14:25:49 -0700606 pr_err("bad mA=%d asked to set\n", mA);
607 return -EINVAL;
608 }
609
David Keitel22ed2232013-01-28 11:04:07 -0800610 if (mA == QPNP_CHG_I_MAX_MIN_100) {
611 usb_reg = 0x00;
612 pr_debug("current=%d setting %02x\n", mA, usb_reg);
613 return qpnp_chg_write(chip, &usb_reg,
614 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
615 } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
616 usb_reg = 0x01;
617 pr_debug("current=%d setting %02x\n", mA, usb_reg);
618 return qpnp_chg_write(chip, &usb_reg,
619 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
620 }
621
622 /* Impose input current limit */
623 if (chip->maxinput_usb_ma)
624 mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
625
626 usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
David Keitel80668952012-07-27 14:25:49 -0700627
David Keiteld681cda2012-10-02 15:44:21 -0700628 if (chip->flags & CHG_FLAGS_VCP_WA) {
629 temp = 0xA5;
630 rc = qpnp_chg_write(chip, &temp,
631 chip->buck_base + SEC_ACCESS, 1);
632 rc = qpnp_chg_masked_write(chip,
633 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
634 0x0C, 0x0C, 1);
635 }
636
David Keitel80668952012-07-27 14:25:49 -0700637 pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
David Keiteld681cda2012-10-02 15:44:21 -0700638 rc = qpnp_chg_write(chip, &usb_reg,
David Keitel22ed2232013-01-28 11:04:07 -0800639 chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
David Keiteld681cda2012-10-02 15:44:21 -0700640
641 if (chip->flags & CHG_FLAGS_VCP_WA) {
642 temp = 0xA5;
643 udelay(200);
644 rc = qpnp_chg_write(chip, &temp,
645 chip->buck_base + SEC_ACCESS, 1);
646 rc = qpnp_chg_masked_write(chip,
647 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
648 0x0C, 0x00, 1);
649 }
650
651 return rc;
652}
653
654#define USB_SUSPEND_BIT BIT(0)
655static int
656qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
657{
658 return qpnp_chg_masked_write(chip,
659 chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
660 USB_SUSPEND_BIT,
661 enable ? USB_SUSPEND_BIT : 0, 1);
David Keitel80668952012-07-27 14:25:49 -0700662}
663
David Keitel344c6972013-04-09 19:28:21 -0700664static int
665qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
666{
667 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
668 CHGR_CHG_EN,
669 enable ? CHGR_CHG_EN : 0, 1);
670}
671
672static int
673qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
674{
675 /* Don't run on battery for batteryless hardware */
676 if (chip->use_default_batt_values)
677 return 0;
David Keitel4d66ea02013-04-30 10:57:58 -0700678 /* Don't force on battery if battery is not present */
679 if (!qpnp_chg_is_batt_present(chip))
680 return 0;
David Keitel344c6972013-04-09 19:28:21 -0700681
682 /* This bit forces the charger to run off of the battery rather
683 * than a connected charger */
684 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
685 CHGR_ON_BAT_FORCE_BIT,
686 disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
687}
688
David Keitel8b68d2d2013-05-14 23:36:51 -0700689#define BUCK_DUTY_MASK_100P 0x30
690static int
691qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
692{
693 int rc;
694
695 pr_debug("enable: %d\n", enable);
696
697 rc = qpnp_chg_masked_write(chip,
698 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
699 if (rc) {
700 pr_debug("failed to write sec access rc=%d\n", rc);
701 return rc;
702 }
703
704 rc = qpnp_chg_masked_write(chip,
705 chip->buck_base + BUCK_TEST_SMBC_MODES,
706 BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
707 if (rc) {
708 pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
709 return rc;
710 }
711
712 return rc;
713}
714
David Keitel9fd07382013-05-02 15:37:44 -0700715#define COMPATATOR_OVERRIDE_0 0x80
716static int
717qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
718{
719 int rc;
720
721 pr_debug("toggle: %d\n", enable);
722
723 rc = qpnp_chg_masked_write(chip,
724 chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
725 if (rc) {
726 pr_debug("failed to write sec access rc=%d\n", rc);
727 return rc;
728 }
729
730 rc = qpnp_chg_masked_write(chip,
731 chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_1,
732 0xC0, enable ? 0x00 : COMPATATOR_OVERRIDE_0, 1);
733 if (rc) {
734 pr_debug("failed to toggle chg done override rc=%d\n", rc);
735 return rc;
736 }
737
738 return rc;
739}
740
741#define QPNP_CHG_VBATDET_MIN_MV 3240
742#define QPNP_CHG_VBATDET_MAX_MV 5780
743#define QPNP_CHG_VBATDET_STEP_MV 20
744static int
745qpnp_chg_vbatdet_set(struct qpnp_chg_chip *chip, int vbatdet_mv)
746{
747 u8 temp;
748
749 if (vbatdet_mv < QPNP_CHG_VBATDET_MIN_MV
750 || vbatdet_mv > QPNP_CHG_VBATDET_MAX_MV) {
751 pr_err("bad mV=%d asked to set\n", vbatdet_mv);
752 return -EINVAL;
753 }
754 temp = (vbatdet_mv - QPNP_CHG_VBATDET_MIN_MV)
755 / QPNP_CHG_VBATDET_STEP_MV;
756
757 pr_debug("voltage=%d setting %02x\n", vbatdet_mv, temp);
758 return qpnp_chg_write(chip, &temp,
759 chip->chgr_base + CHGR_VBAT_DET, 1);
760}
761
David Keitel344c6972013-04-09 19:28:21 -0700762static void
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700763qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
764{
765 if (chip->bat_is_cool)
766 qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
767 - chip->resume_delta_mv);
768 else if (chip->bat_is_warm)
769 qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
770 - chip->resume_delta_mv);
771 else if (chip->resuming_charging)
772 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
773 + chip->resume_delta_mv);
774 else
775 qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
776 - chip->resume_delta_mv);
777}
778
779static void
David Keitel344c6972013-04-09 19:28:21 -0700780qpnp_arb_stop_work(struct work_struct *work)
781{
782 struct delayed_work *dwork = to_delayed_work(work);
783 struct qpnp_chg_chip *chip = container_of(dwork,
784 struct qpnp_chg_chip, arb_stop_work);
785
David Keitel9fd07382013-05-02 15:37:44 -0700786 if (!chip->chg_done)
787 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitel344c6972013-04-09 19:28:21 -0700788 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
789}
790
791static void
792qpnp_bat_if_adc_measure_work(struct work_struct *work)
David Keitel79f4c932013-04-03 16:08:39 -0700793{
794 struct qpnp_chg_chip *chip = container_of(work,
795 struct qpnp_chg_chip, adc_measure_work);
796
797 if (qpnp_adc_tm_channel_measure(&chip->adc_param))
798 pr_err("request ADC error\n");
799}
800
David Keitel9fd07382013-05-02 15:37:44 -0700801#define EOC_CHECK_PERIOD_MS 10000
802static irqreturn_t
803qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
804{
805 struct qpnp_chg_chip *chip = _chip;
806 u8 chg_sts = 0;
807 int rc;
808
809 pr_debug("vbatdet-lo triggered\n");
810
811 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
812 if (rc)
813 pr_err("failed to read chg_sts rc=%d\n", rc);
814
815 pr_debug("chg_done chg_sts: 0x%x triggered\n", chg_sts);
816 if (!chip->charging_disabled && (chg_sts & FAST_CHG_ON_IRQ)) {
817 schedule_delayed_work(&chip->eoc_work,
818 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
819 wake_lock(&chip->eoc_wake_lock);
David Keitel47185a62013-05-15 18:54:10 -0700820 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -0700821 } else {
822 qpnp_chg_charge_en(chip, !chip->charging_disabled);
823 }
824
825 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -0700826 if (chip->dc_chgpth_base)
827 power_supply_changed(&chip->dc_psy);
828 if (chip->bat_if_base)
829 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700830 return IRQ_HANDLED;
831}
832
David Keitel344c6972013-04-09 19:28:21 -0700833#define ARB_STOP_WORK_MS 1000
834static irqreturn_t
835qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
836{
837 struct qpnp_chg_chip *chip = _chip;
838
839 pr_debug("chg_gone triggered\n");
840 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
841 qpnp_chg_charge_en(chip, 0);
David Keitel9fd07382013-05-02 15:37:44 -0700842 qpnp_chg_force_run_on_batt(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -0700843 schedule_delayed_work(&chip->arb_stop_work,
844 msecs_to_jiffies(ARB_STOP_WORK_MS));
845 }
846
847 return IRQ_HANDLED;
848}
849
David Keitel80668952012-07-27 14:25:49 -0700850#define ENUM_T_STOP_BIT BIT(0)
851static irqreturn_t
852qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
853{
854 struct qpnp_chg_chip *chip = _chip;
David Keitel6f865cd2012-11-30 15:04:32 -0800855 int usb_present, host_mode;
David Keitel80668952012-07-27 14:25:49 -0700856
857 usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
David Keitel6f865cd2012-11-30 15:04:32 -0800858 host_mode = qpnp_chg_is_otg_en_set(chip);
859 pr_debug("usbin-valid triggered: %d host_mode: %d\n",
860 usb_present, host_mode);
861
862 /* In host mode notifications cmoe from USB supply */
863 if (host_mode)
864 return IRQ_HANDLED;
David Keitel80668952012-07-27 14:25:49 -0700865
866 if (chip->usb_present ^ usb_present) {
867 chip->usb_present = usb_present;
David Keitel9fd07382013-05-02 15:37:44 -0700868 if (!usb_present) {
David Keitel344c6972013-04-09 19:28:21 -0700869 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel9fd07382013-05-02 15:37:44 -0700870 chip->chg_done = false;
871 } else {
872 schedule_delayed_work(&chip->eoc_work,
873 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
874 }
David Keitel344c6972013-04-09 19:28:21 -0700875
David Keitel9fd07382013-05-02 15:37:44 -0700876 power_supply_set_present(chip->usb_psy, chip->usb_present);
David Keitel80668952012-07-27 14:25:49 -0700877 }
878
879 return IRQ_HANDLED;
880}
881
David Keitel7450dcd2013-01-29 18:41:41 -0800882static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -0800883qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
884{
885 struct qpnp_chg_chip *chip = _chip;
886 int batt_present;
887
888 batt_present = qpnp_chg_is_batt_present(chip);
889 pr_debug("batt-pres triggered: %d\n", batt_present);
890
891 if (chip->batt_present ^ batt_present) {
892 chip->batt_present = batt_present;
893 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700894 power_supply_changed(chip->usb_psy);
David Keitel0c1a4532013-03-21 16:39:06 -0700895
896 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
897 && batt_present) {
David Keitel79f4c932013-04-03 16:08:39 -0700898 schedule_work(&chip->adc_measure_work);
David Keitel0c1a4532013-03-21 16:39:06 -0700899 }
David Keitel42ae0aa2013-03-08 16:20:10 -0800900 }
901
902 return IRQ_HANDLED;
903}
904
905static irqreturn_t
David Keitel7450dcd2013-01-29 18:41:41 -0800906qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
907{
908 struct qpnp_chg_chip *chip = _chip;
909 int dc_present;
910
911 dc_present = qpnp_chg_is_dc_chg_plugged_in(chip);
912 pr_debug("dcin-valid triggered: %d\n", dc_present);
913
914 if (chip->dc_present ^ dc_present) {
915 chip->dc_present = dc_present;
David Keitel9fd07382013-05-02 15:37:44 -0700916 if (!dc_present)
917 chip->chg_done = false;
918 else
919 schedule_delayed_work(&chip->eoc_work,
920 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
David Keitel7450dcd2013-01-29 18:41:41 -0800921 power_supply_changed(&chip->dc_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700922 power_supply_changed(&chip->batt_psy);
David Keitel7450dcd2013-01-29 18:41:41 -0800923 }
924
925 return IRQ_HANDLED;
926}
927
David Keitel80668952012-07-27 14:25:49 -0700928#define CHGR_CHG_FAILED_BIT BIT(7)
929static irqreturn_t
930qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
931{
932 struct qpnp_chg_chip *chip = _chip;
David Keitel4429b1f2012-10-18 10:42:50 -0700933 int rc;
David Keitel80668952012-07-27 14:25:49 -0700934
David Keitel9fd07382013-05-02 15:37:44 -0700935 pr_debug("chg_failed triggered\n");
936
David Keitel80668952012-07-27 14:25:49 -0700937 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -0700938 chip->chgr_base + CHGR_CHG_FAILED,
David Keitel80668952012-07-27 14:25:49 -0700939 CHGR_CHG_FAILED_BIT,
940 CHGR_CHG_FAILED_BIT, 1);
941 if (rc)
942 pr_err("Failed to write chg_fail clear bit!\n");
943
David Keiteldbcef092013-05-14 14:48:30 -0700944 if (chip->bat_if_base)
945 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700946 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -0700947 if (chip->dc_chgpth_base)
948 power_supply_changed(&chip->dc_psy);
David Keitel80668952012-07-27 14:25:49 -0700949 return IRQ_HANDLED;
950}
951
952static irqreturn_t
David Keitel42ae0aa2013-03-08 16:20:10 -0800953qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
954{
955 struct qpnp_chg_chip *chip = _chip;
956
957 pr_debug("TRKL IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -0800958
959 chip->chg_done = false;
David Keiteldbcef092013-05-14 14:48:30 -0700960 if (chip->bat_if_base)
961 power_supply_changed(&chip->batt_psy);
David Keitel42ae0aa2013-03-08 16:20:10 -0800962
963 return IRQ_HANDLED;
964}
965
966static irqreturn_t
967qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
968{
969 struct qpnp_chg_chip *chip = _chip;
970
971 pr_debug("FAST_CHG IRQ triggered\n");
David Keitelc9ffe842013-01-25 19:37:51 -0800972 chip->chg_done = false;
David Keiteldbcef092013-05-14 14:48:30 -0700973 if (chip->bat_if_base)
974 power_supply_changed(&chip->batt_psy);
David Keitel9fd07382013-05-02 15:37:44 -0700975 power_supply_changed(chip->usb_psy);
David Keiteldbcef092013-05-14 14:48:30 -0700976 if (chip->dc_chgpth_base)
977 power_supply_changed(&chip->dc_psy);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -0700978 if (chip->resuming_charging) {
979 chip->resuming_charging = false;
980 qpnp_chg_set_appropriate_vbatdet(chip);
981 }
David Keitel47185a62013-05-15 18:54:10 -0700982 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel42ae0aa2013-03-08 16:20:10 -0800983
984 return IRQ_HANDLED;
985}
986
David Keitel03ee6b52012-10-22 12:25:19 -0700987static int
David Keitel432e1232013-06-05 16:10:18 -0700988qpnp_dc_property_is_writeable(struct power_supply *psy,
989 enum power_supply_property psp)
990{
991 switch (psp) {
992 case POWER_SUPPLY_PROP_CURRENT_MAX:
993 return 1;
994 default:
995 break;
996 }
997
998 return 0;
999}
1000
1001static int
David Keitel03ee6b52012-10-22 12:25:19 -07001002qpnp_batt_property_is_writeable(struct power_supply *psy,
1003 enum power_supply_property psp)
1004{
1005 switch (psp) {
1006 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitelbe208252013-01-31 14:49:25 -08001007 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
David Keitel03ee6b52012-10-22 12:25:19 -07001008 return 1;
1009 default:
1010 break;
1011 }
1012
1013 return 0;
1014}
1015
David Keitel6f865cd2012-11-30 15:04:32 -08001016static int
David Keitelbe208252013-01-31 14:49:25 -08001017qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
1018{
1019 int rc;
1020
1021 if (chip->charging_disabled && enable) {
1022 pr_debug("Charging disabled\n");
1023 return 0;
1024 }
1025
1026 rc = qpnp_chg_charge_en(chip, enable);
1027 if (rc) {
1028 pr_err("Failed to control charging %d\n", rc);
1029 return rc;
1030 }
1031
1032 rc = qpnp_chg_force_run_on_batt(chip, !enable);
1033 if (rc)
1034 pr_err("Failed to control charging %d\n", rc);
1035
1036 return rc;
1037}
1038
David Keitel454ee842013-03-08 16:19:11 -08001039static int
1040switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001041{
1042 int rc;
1043
1044 pr_debug("switch to charge mode\n");
1045 if (!qpnp_chg_is_otg_en_set(chip))
1046 return 0;
1047
1048 /* enable usb ovp fet */
1049 rc = qpnp_chg_masked_write(chip,
1050 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1051 USB_OTG_EN_BIT,
1052 0, 1);
1053 if (rc) {
1054 pr_err("Failed to turn on usb ovp rc = %d\n", rc);
1055 return rc;
1056 }
1057
1058 rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
1059 if (rc) {
1060 pr_err("Failed re-enable charging rc = %d\n", rc);
1061 return rc;
1062 }
1063
1064 return 0;
1065}
1066
David Keitel454ee842013-03-08 16:19:11 -08001067static int
1068switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
David Keitel6f865cd2012-11-30 15:04:32 -08001069{
1070 int rc;
1071
1072 pr_debug("switch to host mode\n");
1073 if (qpnp_chg_is_otg_en_set(chip))
1074 return 0;
1075
1076 rc = qpnp_chg_force_run_on_batt(chip, 1);
1077 if (rc) {
1078 pr_err("Failed to disable charging rc = %d\n", rc);
1079 return rc;
1080 }
1081
1082 /* force usb ovp fet off */
1083 rc = qpnp_chg_masked_write(chip,
1084 chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
1085 USB_OTG_EN_BIT,
1086 USB_OTG_EN_BIT, 1);
1087 if (rc) {
1088 pr_err("Failed to turn off usb ovp rc = %d\n", rc);
1089 return rc;
1090 }
1091
1092 return 0;
1093}
1094
David Keitel80668952012-07-27 14:25:49 -07001095static enum power_supply_property pm_power_props_mains[] = {
1096 POWER_SUPPLY_PROP_PRESENT,
1097 POWER_SUPPLY_PROP_ONLINE,
David Keitel432e1232013-06-05 16:10:18 -07001098 POWER_SUPPLY_PROP_CURRENT_MAX,
David Keitel80668952012-07-27 14:25:49 -07001099};
1100
1101static enum power_supply_property msm_batt_power_props[] = {
David Keitelb80eda82012-10-15 10:49:11 -07001102 POWER_SUPPLY_PROP_CHARGING_ENABLED,
David Keitel80668952012-07-27 14:25:49 -07001103 POWER_SUPPLY_PROP_STATUS,
1104 POWER_SUPPLY_PROP_CHARGE_TYPE,
1105 POWER_SUPPLY_PROP_HEALTH,
1106 POWER_SUPPLY_PROP_PRESENT,
1107 POWER_SUPPLY_PROP_TECHNOLOGY,
1108 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
1109 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
1110 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1111 POWER_SUPPLY_PROP_CAPACITY,
1112 POWER_SUPPLY_PROP_CURRENT_NOW,
1113 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301114 POWER_SUPPLY_PROP_CHARGE_FULL,
David Keitel80668952012-07-27 14:25:49 -07001115 POWER_SUPPLY_PROP_TEMP,
David Keitelbe208252013-01-31 14:49:25 -08001116 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301117 POWER_SUPPLY_PROP_CYCLE_COUNT,
David Keitel80668952012-07-27 14:25:49 -07001118};
1119
1120static char *pm_power_supplied_to[] = {
1121 "battery",
1122};
1123
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07001124static char *pm_batt_supplied_to[] = {
1125 "bms",
1126};
1127
David Keitel80668952012-07-27 14:25:49 -07001128#define USB_WALL_THRESHOLD_MA 500
1129static int
1130qpnp_power_get_property_mains(struct power_supply *psy,
1131 enum power_supply_property psp,
1132 union power_supply_propval *val)
1133{
1134 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1135 dc_psy);
1136
1137 switch (psp) {
1138 case POWER_SUPPLY_PROP_PRESENT:
1139 case POWER_SUPPLY_PROP_ONLINE:
1140 val->intval = 0;
David Keitel03ee6b52012-10-22 12:25:19 -07001141 if (chip->charging_disabled)
David Keitel80668952012-07-27 14:25:49 -07001142 return 0;
1143
1144 val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
1145 break;
David Keitel432e1232013-06-05 16:10:18 -07001146 case POWER_SUPPLY_PROP_CURRENT_MAX:
David Keitele2c95302013-07-11 11:15:06 -07001147 val->intval = chip->maxinput_dc_ma * 1000;
David Keitel432e1232013-06-05 16:10:18 -07001148 break;
David Keitel80668952012-07-27 14:25:49 -07001149 default:
1150 return -EINVAL;
1151 }
1152 return 0;
1153}
1154
1155static int
1156get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
1157{
1158 int rc = 0;
1159 struct qpnp_vadc_result results;
1160
David Keitelfe51cb92013-04-02 19:42:58 -07001161 if (chip->revision == 0 && chip->type == SMBB) {
1162 pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
1163 return 0;
1164 } else {
David Keitel80668952012-07-27 14:25:49 -07001165 rc = qpnp_vadc_read(VBAT_SNS, &results);
1166 if (rc) {
1167 pr_err("Unable to read vbat rc=%d\n", rc);
1168 return 0;
1169 }
1170 return results.physical;
David Keitel80668952012-07-27 14:25:49 -07001171 }
1172}
1173
1174#define BATT_PRES_BIT BIT(7)
1175static int
1176get_prop_batt_present(struct qpnp_chg_chip *chip)
1177{
1178 u8 batt_present;
1179 int rc;
1180
1181 rc = qpnp_chg_read(chip, &batt_present,
1182 chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
1183 if (rc) {
1184 pr_err("Couldn't read battery status read failed rc=%d\n", rc);
1185 return 0;
1186 };
1187 return (batt_present & BATT_PRES_BIT) ? 1 : 0;
1188}
1189
1190#define BATT_TEMP_HOT BIT(6)
1191#define BATT_TEMP_OK BIT(7)
1192static int
1193get_prop_batt_health(struct qpnp_chg_chip *chip)
1194{
1195 u8 batt_health;
1196 int rc;
1197
1198 rc = qpnp_chg_read(chip, &batt_health,
David Keiteld681cda2012-10-02 15:44:21 -07001199 chip->bat_if_base + CHGR_STATUS, 1);
David Keitel80668952012-07-27 14:25:49 -07001200 if (rc) {
1201 pr_err("Couldn't read battery health read failed rc=%d\n", rc);
1202 return POWER_SUPPLY_HEALTH_UNKNOWN;
1203 };
1204
1205 if (BATT_TEMP_OK & batt_health)
1206 return POWER_SUPPLY_HEALTH_GOOD;
1207 if (BATT_TEMP_HOT & batt_health)
1208 return POWER_SUPPLY_HEALTH_OVERHEAT;
1209 else
1210 return POWER_SUPPLY_HEALTH_COLD;
1211}
1212
1213static int
1214get_prop_charge_type(struct qpnp_chg_chip *chip)
1215{
1216 int rc;
1217 u8 chgr_sts;
1218
1219 if (!get_prop_batt_present(chip))
1220 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1221
1222 rc = qpnp_chg_read(chip, &chgr_sts,
1223 INT_RT_STS(chip->chgr_base), 1);
1224 if (rc) {
1225 pr_err("failed to read interrupt sts %d\n", rc);
1226 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1227 }
1228
1229 if (chgr_sts & TRKL_CHG_ON_IRQ)
1230 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1231 if (chgr_sts & FAST_CHG_ON_IRQ)
1232 return POWER_SUPPLY_CHARGE_TYPE_FAST;
1233
1234 return POWER_SUPPLY_CHARGE_TYPE_NONE;
1235}
1236
1237static int
1238get_prop_batt_status(struct qpnp_chg_chip *chip)
1239{
1240 int rc;
1241 u8 chgr_sts;
1242
David Keitel9fd07382013-05-02 15:37:44 -07001243 if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
1244 qpnp_chg_is_dc_chg_plugged_in(chip)) && chip->chg_done) {
David Keitelc9ffe842013-01-25 19:37:51 -08001245 return POWER_SUPPLY_STATUS_FULL;
David Keitel9fd07382013-05-02 15:37:44 -07001246 }
David Keitelc9ffe842013-01-25 19:37:51 -08001247
David Keitel9fd07382013-05-02 15:37:44 -07001248 rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
David Keitel80668952012-07-27 14:25:49 -07001249 if (rc) {
1250 pr_err("failed to read interrupt sts %d\n", rc);
David Keitelc9ffe842013-01-25 19:37:51 -08001251 return POWER_SUPPLY_CHARGE_TYPE_NONE;
David Keitel80668952012-07-27 14:25:49 -07001252 }
1253
David Keitel80668952012-07-27 14:25:49 -07001254 if (chgr_sts & TRKL_CHG_ON_IRQ)
1255 return POWER_SUPPLY_STATUS_CHARGING;
1256 if (chgr_sts & FAST_CHG_ON_IRQ)
1257 return POWER_SUPPLY_STATUS_CHARGING;
1258
1259 return POWER_SUPPLY_STATUS_DISCHARGING;
1260}
1261
1262static int
1263get_prop_current_now(struct qpnp_chg_chip *chip)
1264{
1265 union power_supply_propval ret = {0,};
1266
1267 if (chip->bms_psy) {
1268 chip->bms_psy->get_property(chip->bms_psy,
1269 POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
1270 return ret.intval;
1271 } else {
1272 pr_debug("No BMS supply registered return 0\n");
1273 }
1274
1275 return 0;
1276}
1277
1278static int
1279get_prop_full_design(struct qpnp_chg_chip *chip)
1280{
1281 union power_supply_propval ret = {0,};
1282
1283 if (chip->bms_psy) {
1284 chip->bms_psy->get_property(chip->bms_psy,
1285 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
1286 return ret.intval;
1287 } else {
1288 pr_debug("No BMS supply registered return 0\n");
1289 }
1290
1291 return 0;
1292}
1293
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301294static int
1295get_prop_charge_full(struct qpnp_chg_chip *chip)
1296{
1297 union power_supply_propval ret = {0,};
1298
1299 if (chip->bms_psy) {
1300 chip->bms_psy->get_property(chip->bms_psy,
1301 POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
1302 return ret.intval;
1303 } else {
1304 pr_debug("No BMS supply registered return 0\n");
1305 }
1306
1307 return 0;
1308}
1309
David Keitel80668952012-07-27 14:25:49 -07001310#define DEFAULT_CAPACITY 50
1311static int
1312get_prop_capacity(struct qpnp_chg_chip *chip)
1313{
1314 union power_supply_propval ret = {0,};
1315
David Keitel3dd5e0f2012-12-12 18:12:36 -08001316 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
1317 return DEFAULT_CAPACITY;
1318
David Keitel80668952012-07-27 14:25:49 -07001319 if (chip->bms_psy) {
1320 chip->bms_psy->get_property(chip->bms_psy,
1321 POWER_SUPPLY_PROP_CAPACITY, &ret);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07001322 if (get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL
1323 && !chip->resuming_charging
1324 && !chip->charging_disabled
1325 && chip->soc_resume_limit
1326 && ret.intval <= chip->soc_resume_limit) {
1327 pr_debug("resuming charging at %d%% soc\n", ret.intval);
1328 chip->resuming_charging = true;
1329 qpnp_chg_set_appropriate_vbatdet(chip);
1330 qpnp_chg_charge_en(chip, !chip->charging_disabled);
1331 }
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07001332 if (ret.intval == 0) {
David Keiteleeca08f2013-05-17 16:40:46 -07001333 if (!qpnp_chg_is_usb_chg_plugged_in(chip)
1334 && !qpnp_chg_is_usb_chg_plugged_in(chip))
Abhijeet Dharmapurikar53ce35a2013-03-29 16:14:16 -07001335 pr_warn_ratelimited("Battery 0, CHG absent\n");
1336 }
David Keitel80668952012-07-27 14:25:49 -07001337 return ret.intval;
1338 } else {
1339 pr_debug("No BMS supply registered return 50\n");
1340 }
1341
1342 /* return default capacity to avoid userspace
1343 * from shutting down unecessarily */
1344 return DEFAULT_CAPACITY;
1345}
1346
David Keitel3dd5e0f2012-12-12 18:12:36 -08001347#define DEFAULT_TEMP 250
David Keitel80668952012-07-27 14:25:49 -07001348#define MAX_TOLERABLE_BATT_TEMP_DDC 680
1349static int
1350get_prop_batt_temp(struct qpnp_chg_chip *chip)
1351{
1352 int rc = 0;
1353 struct qpnp_vadc_result results;
1354
David Keitel3dd5e0f2012-12-12 18:12:36 -08001355 if (chip->use_default_batt_values || !get_prop_batt_present(chip))
1356 return DEFAULT_TEMP;
1357
David Keitela2dbfc72013-06-07 11:10:14 -07001358 rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &results);
1359 if (rc) {
1360 pr_debug("Unable to read batt temperature rc=%d\n", rc);
1361 return 0;
David Keitel80668952012-07-27 14:25:49 -07001362 }
David Keitela2dbfc72013-06-07 11:10:14 -07001363 pr_debug("get_bat_temp %d %lld\n",
1364 results.adc_code, results.physical);
David Keitel80668952012-07-27 14:25:49 -07001365
David Keitela2dbfc72013-06-07 11:10:14 -07001366 return (int)results.physical;
David Keitel80668952012-07-27 14:25:49 -07001367}
1368
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301369static int get_prop_cycle_count(struct qpnp_chg_chip *chip)
1370{
1371 union power_supply_propval ret = {0,};
1372
1373 if (chip->bms_psy)
1374 chip->bms_psy->get_property(chip->bms_psy,
1375 POWER_SUPPLY_PROP_CYCLE_COUNT, &ret);
1376 return ret.intval;
1377}
1378
David Keitel80668952012-07-27 14:25:49 -07001379static void
1380qpnp_batt_external_power_changed(struct power_supply *psy)
1381{
1382 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1383 batt_psy);
1384 union power_supply_propval ret = {0,};
1385
1386 if (!chip->bms_psy)
1387 chip->bms_psy = power_supply_get_by_name("bms");
1388
1389 chip->usb_psy->get_property(chip->usb_psy,
1390 POWER_SUPPLY_PROP_ONLINE, &ret);
1391
David Keitelc69f2d62013-03-17 14:52:35 -07001392 /* Only honour requests while USB is present */
1393 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07001394 chip->usb_psy->get_property(chip->usb_psy,
1395 POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
David Keitel87473252013-03-21 14:39:45 -07001396 if (ret.intval <= 2 && !chip->use_default_batt_values &&
1397 get_prop_batt_present(chip)) {
David Keitel359ab652013-03-21 17:46:00 -07001398 qpnp_chg_usb_suspend_enable(chip, 1);
David Keitel344c6972013-04-09 19:28:21 -07001399 qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
David Keitelc69f2d62013-03-17 14:52:35 -07001400 } else {
David Keiteld681cda2012-10-02 15:44:21 -07001401 qpnp_chg_usb_suspend_enable(chip, 0);
David Keitel359ab652013-03-21 17:46:00 -07001402 qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
David Keitelc69f2d62013-03-17 14:52:35 -07001403 }
David Keitel80668952012-07-27 14:25:49 -07001404 }
1405
1406 pr_debug("end of power supply changed\n");
1407 power_supply_changed(&chip->batt_psy);
1408}
1409
1410static int
1411qpnp_batt_power_get_property(struct power_supply *psy,
1412 enum power_supply_property psp,
1413 union power_supply_propval *val)
1414{
1415 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
1416 batt_psy);
1417
1418 switch (psp) {
1419 case POWER_SUPPLY_PROP_STATUS:
1420 val->intval = get_prop_batt_status(chip);
1421 break;
1422 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1423 val->intval = get_prop_charge_type(chip);
1424 break;
1425 case POWER_SUPPLY_PROP_HEALTH:
1426 val->intval = get_prop_batt_health(chip);
1427 break;
1428 case POWER_SUPPLY_PROP_PRESENT:
1429 val->intval = get_prop_batt_present(chip);
1430 break;
1431 case POWER_SUPPLY_PROP_TECHNOLOGY:
1432 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1433 break;
1434 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
1435 val->intval = chip->max_voltage_mv * 1000;
1436 break;
1437 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
1438 val->intval = chip->min_voltage_mv * 1000;
1439 break;
1440 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1441 val->intval = get_prop_battery_voltage_now(chip);
1442 break;
1443 case POWER_SUPPLY_PROP_TEMP:
1444 val->intval = get_prop_batt_temp(chip);
1445 break;
1446 case POWER_SUPPLY_PROP_CAPACITY:
1447 val->intval = get_prop_capacity(chip);
1448 break;
1449 case POWER_SUPPLY_PROP_CURRENT_NOW:
1450 val->intval = get_prop_current_now(chip);
1451 break;
1452 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1453 val->intval = get_prop_full_design(chip);
1454 break;
Anirudh Ghayalc9d981a2013-06-24 09:50:33 +05301455 case POWER_SUPPLY_PROP_CHARGE_FULL:
1456 val->intval = get_prop_charge_full(chip);
1457 break;
David Keitelb80eda82012-10-15 10:49:11 -07001458 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
David Keitel03ee6b52012-10-22 12:25:19 -07001459 val->intval = !(chip->charging_disabled);
David Keitelb80eda82012-10-15 10:49:11 -07001460 break;
David Keitelbe208252013-01-31 14:49:25 -08001461 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
1462 val->intval = chip->therm_lvl_sel;
David Keitelb80eda82012-10-15 10:49:11 -07001463 break;
Anirudh Ghayal9dd582d2013-06-07 17:48:58 +05301464 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1465 val->intval = get_prop_cycle_count(chip);
1466 break;
David Keitelb80eda82012-10-15 10:49:11 -07001467 default:
1468 return -EINVAL;
1469 }
1470
David Keitelb80eda82012-10-15 10:49:11 -07001471 return 0;
David Keitel80668952012-07-27 14:25:49 -07001472}
1473
David Keitel89c17752013-06-28 14:52:48 -07001474#define BTC_CONFIG_ENABLED BIT(7)
1475#define BTC_COLD BIT(1)
1476#define BTC_HOT BIT(0)
1477static int
1478qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
1479{
1480 u8 btc_cfg = 0, mask = 0;
1481
1482 /* Do nothing if battery peripheral not present */
1483 if (!chip->bat_if_base)
1484 return 0;
1485
1486 if ((chip->hot_batt_p == HOT_THD_25_PCT)
1487 || (chip->hot_batt_p == HOT_THD_35_PCT)) {
1488 btc_cfg |= btc_value[chip->hot_batt_p];
1489 mask |= BTC_HOT;
1490 }
1491
1492 if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
1493 (chip->cold_batt_p == COLD_THD_80_PCT)) {
1494 btc_cfg |= btc_value[chip->cold_batt_p];
1495 mask |= BTC_COLD;
1496 }
1497
1498 if (chip->btc_disabled)
1499 mask |= BTC_CONFIG_ENABLED;
1500
1501 return qpnp_chg_masked_write(chip,
1502 chip->bat_if_base + BAT_IF_BTC_CTRL,
1503 mask, btc_cfg, 1);
1504}
1505
David Keitelfae11752013-06-28 14:53:19 -07001506#define QPNP_CHG_VINMIN_MIN_MV 4200
David Keitel80668952012-07-27 14:25:49 -07001507#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
1508#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
1509#define QPNP_CHG_VINMIN_MAX_MV 9600
1510#define QPNP_CHG_VINMIN_STEP_MV 50
1511#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
1512#define QPNP_CHG_VINMIN_MASK 0x1F
1513static int
1514qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
1515{
1516 u8 temp;
1517
1518 if (voltage < QPNP_CHG_VINMIN_MIN_MV
1519 || voltage > QPNP_CHG_VINMIN_MAX_MV) {
1520 pr_err("bad mV=%d asked to set\n", voltage);
1521 return -EINVAL;
1522 }
1523 if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
1524 temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
1525 temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
1526 / QPNP_CHG_VINMIN_STEP_HIGH_MV;
1527 } else {
1528 temp = (voltage - QPNP_CHG_VINMIN_MIN_MV)
1529 / QPNP_CHG_VINMIN_STEP_MV;
1530 }
1531
1532 pr_debug("voltage=%d setting %02x\n", voltage, temp);
1533 return qpnp_chg_masked_write(chip,
1534 chip->chgr_base + CHGR_VIN_MIN,
1535 QPNP_CHG_VINMIN_MASK, temp, 1);
1536}
1537
David Keitel5d44fa52012-12-03 16:37:31 -08001538#define QPNP_CHG_IBATSAFE_MIN_MA 100
1539#define QPNP_CHG_IBATSAFE_MAX_MA 3250
1540#define QPNP_CHG_I_STEP_MA 50
1541#define QPNP_CHG_I_MIN_MA 100
1542#define QPNP_CHG_I_MASK 0x3F
1543static int
1544qpnp_chg_ibatsafe_set(struct qpnp_chg_chip *chip, int safe_current)
1545{
1546 u8 temp;
1547
1548 if (safe_current < QPNP_CHG_IBATSAFE_MIN_MA
1549 || safe_current > QPNP_CHG_IBATSAFE_MAX_MA) {
1550 pr_err("bad mA=%d asked to set\n", safe_current);
1551 return -EINVAL;
1552 }
1553
1554 temp = (safe_current - QPNP_CHG_IBATSAFE_MIN_MA)
1555 / QPNP_CHG_I_STEP_MA;
1556 return qpnp_chg_masked_write(chip,
1557 chip->chgr_base + CHGR_IBAT_SAFE,
1558 QPNP_CHG_I_MASK, temp, 1);
1559}
David Keitel80668952012-07-27 14:25:49 -07001560
1561#define QPNP_CHG_ITERM_MIN_MA 100
1562#define QPNP_CHG_ITERM_MAX_MA 250
1563#define QPNP_CHG_ITERM_STEP_MA 50
1564#define QPNP_CHG_ITERM_MASK 0x03
1565static int
1566qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
1567{
1568 u8 temp;
1569
1570 if (term_current < QPNP_CHG_ITERM_MIN_MA
1571 || term_current > QPNP_CHG_ITERM_MAX_MA) {
1572 pr_err("bad mA=%d asked to set\n", term_current);
1573 return -EINVAL;
1574 }
1575
1576 temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
1577 / QPNP_CHG_ITERM_STEP_MA;
1578 return qpnp_chg_masked_write(chip,
1579 chip->chgr_base + CHGR_IBAT_TERM_CHGR,
1580 QPNP_CHG_ITERM_MASK, temp, 1);
1581}
1582
David Keitelff5d0472013-04-04 11:36:06 -07001583#define QPNP_CHG_IBATMAX_MIN 50
David Keitel80668952012-07-27 14:25:49 -07001584#define QPNP_CHG_IBATMAX_MAX 3250
David Keitel80668952012-07-27 14:25:49 -07001585static int
1586qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
1587{
1588 u8 temp;
1589
1590 if (chg_current < QPNP_CHG_IBATMAX_MIN
1591 || chg_current > QPNP_CHG_IBATMAX_MAX) {
1592 pr_err("bad mA=%d asked to set\n", chg_current);
1593 return -EINVAL;
1594 }
David Keitelff5d0472013-04-04 11:36:06 -07001595 temp = chg_current / QPNP_CHG_I_STEP_MA;
David Keitel80668952012-07-27 14:25:49 -07001596 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
1597 QPNP_CHG_I_MASK, temp, 1);
1598}
1599
David Keitela4b7b592013-04-11 18:34:35 -07001600#define QPNP_CHG_TCHG_MASK 0x7F
1601#define QPNP_CHG_TCHG_MIN 4
1602#define QPNP_CHG_TCHG_MAX 512
1603#define QPNP_CHG_TCHG_STEP 4
1604static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
1605{
1606 u8 temp;
1607
1608 if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
1609 pr_err("bad max minutes =%d asked to set\n", minutes);
1610 return -EINVAL;
1611 }
1612
1613 temp = (minutes - 1)/QPNP_CHG_TCHG_STEP;
1614 return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
David Keitela1d16442013-05-09 14:47:37 -07001615 QPNP_CHG_TCHG_MASK, temp, 1);
David Keitela4b7b592013-04-11 18:34:35 -07001616}
David Keitel80668952012-07-27 14:25:49 -07001617
1618#define QPNP_CHG_V_MIN_MV 3240
1619#define QPNP_CHG_V_MAX_MV 4500
1620#define QPNP_CHG_V_STEP_MV 10
1621static int
1622qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
1623{
1624 u8 temp;
1625
1626 if (voltage < QPNP_CHG_V_MIN_MV
1627 || voltage > QPNP_CHG_V_MAX_MV) {
1628 pr_err("bad mV=%d asked to set\n", voltage);
1629 return -EINVAL;
1630 }
1631 temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
1632 pr_debug("voltage=%d setting %02x\n", voltage, temp);
1633 return qpnp_chg_write(chip, &temp,
1634 chip->chgr_base + CHGR_VDD_SAFE, 1);
1635}
1636
1637#define QPNP_CHG_VDDMAX_MIN 3400
1638static int
1639qpnp_chg_vddmax_set(struct qpnp_chg_chip *chip, int voltage)
1640{
1641 u8 temp = 0;
1642
1643 if (voltage < QPNP_CHG_VDDMAX_MIN
1644 || voltage > QPNP_CHG_V_MAX_MV) {
1645 pr_err("bad mV=%d asked to set\n", voltage);
1646 return -EINVAL;
1647 }
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001648 chip->set_vddmax_mv = voltage + chip->delta_vddmax_mv;
David Keitel80668952012-07-27 14:25:49 -07001649
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001650 temp = (chip->set_vddmax_mv - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
David Keitel80668952012-07-27 14:25:49 -07001651
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001652 pr_debug("voltage=%d setting %02x\n", chip->set_vddmax_mv, temp);
David Keitel454ee842013-03-08 16:19:11 -08001653 return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
1654}
1655
David Keitel6dc4ed42013-05-17 11:08:58 -07001656#define BOOST_MIN_UV 4200000
1657#define BOOST_MAX_UV 5500000
1658#define BOOST_STEP_UV 50000
1659#define BOOST_MIN 16
1660#define N_BOOST_V ((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
1661static int
1662qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
1663{
1664 u8 reg = 0;
1665
1666 if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
1667 pr_err("invalid voltage requested %d uV\n", voltage);
1668 return -EINVAL;
1669 }
1670
1671 reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
1672
1673 pr_debug("voltage=%d setting %02x\n", voltage, reg);
1674 return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
1675}
1676
1677static int
1678qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
1679{
1680 int rc;
1681 u8 boost_reg;
1682
1683 rc = qpnp_chg_read(chip, &boost_reg,
1684 chip->boost_base + BOOST_VSET, 1);
1685 if (rc) {
1686 pr_err("failed to read BOOST_VSET rc=%d\n", rc);
1687 return rc;
1688 }
1689
1690 if (boost_reg < BOOST_MIN) {
1691 pr_err("Invalid reading from 0x%x\n", boost_reg);
1692 return -EINVAL;
1693 }
1694
1695 return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
1696}
1697
David Keitel454ee842013-03-08 16:19:11 -08001698/* JEITA compliance logic */
1699static void
1700qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
1701{
1702 if (chip->bat_is_cool)
1703 qpnp_chg_vddmax_set(chip, chip->cool_bat_mv);
1704 else if (chip->bat_is_warm)
1705 qpnp_chg_vddmax_set(chip, chip->warm_bat_mv);
1706 else
1707 qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
1708}
1709
1710static void
David Keitelbe208252013-01-31 14:49:25 -08001711qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
1712{
1713 unsigned int chg_current = chip->max_bat_chg_current;
1714
David Keitel454ee842013-03-08 16:19:11 -08001715 if (chip->bat_is_cool)
1716 chg_current = min(chg_current, chip->cool_bat_chg_ma);
1717
1718 if (chip->bat_is_warm)
1719 chg_current = min(chg_current, chip->warm_bat_chg_ma);
1720
David Keitelbe208252013-01-31 14:49:25 -08001721 if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
1722 chg_current = min(chg_current,
1723 chip->thermal_mitigation[chip->therm_lvl_sel]);
1724
1725 pr_debug("setting %d mA\n", chg_current);
1726 qpnp_chg_ibatmax_set(chip, chg_current);
1727}
1728
1729static void
1730qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
1731{
1732 if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
1733 chip->therm_lvl_sel = lvl_sel;
1734 if (lvl_sel == (chip->thermal_levels - 1)) {
1735 /* disable charging if highest value selected */
1736 qpnp_chg_buck_control(chip, 0);
1737 } else {
1738 qpnp_chg_buck_control(chip, 1);
1739 qpnp_chg_set_appropriate_battery_current(chip);
1740 }
1741 } else {
1742 pr_err("Unsupported level selected %d\n", lvl_sel);
1743 }
1744}
1745
David Keitel6dc4ed42013-05-17 11:08:58 -07001746/* OTG regulator operations */
1747static int
1748qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
1749{
1750 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1751
1752 return switch_usb_to_host_mode(chip);
1753}
1754
1755static int
1756qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
1757{
1758 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1759
1760 return switch_usb_to_charge_mode(chip);
1761}
1762
1763static int
1764qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
1765{
1766 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1767
1768 return qpnp_chg_is_otg_en_set(chip);
1769}
1770
1771static int
1772qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
1773{
1774 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07001775 int rc;
1776
1777 if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
1778 (chip->flags & BOOST_FLASH_WA)) {
1779 qpnp_chg_usb_suspend_enable(chip, 1);
1780
1781 rc = qpnp_chg_masked_write(chip,
1782 chip->usb_chgpth_base + SEC_ACCESS,
1783 0xFF,
1784 0xA5, 1);
1785 if (rc) {
1786 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1787 return rc;
1788 }
1789
1790 rc = qpnp_chg_masked_write(chip,
1791 chip->usb_chgpth_base + COMP_OVR1,
1792 0xFF,
1793 0x2F, 1);
1794 if (rc) {
1795 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1796 return rc;
1797 }
1798 }
David Keitel6dc4ed42013-05-17 11:08:58 -07001799
1800 return qpnp_chg_masked_write(chip,
1801 chip->boost_base + BOOST_ENABLE_CONTROL,
1802 BOOST_PWR_EN,
1803 BOOST_PWR_EN, 1);
1804}
1805
1806/* Boost regulator operations */
David Keitel33f58952013-05-20 16:17:36 -07001807#define ABOVE_VBAT_WEAK BIT(1)
David Keitel6dc4ed42013-05-17 11:08:58 -07001808static int
1809qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
1810{
1811 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
David Keitel33f58952013-05-20 16:17:36 -07001812 int rc;
1813 u8 vbat_sts;
David Keitel6dc4ed42013-05-17 11:08:58 -07001814
David Keitel33f58952013-05-20 16:17:36 -07001815 rc = qpnp_chg_masked_write(chip,
David Keitel6dc4ed42013-05-17 11:08:58 -07001816 chip->boost_base + BOOST_ENABLE_CONTROL,
1817 BOOST_PWR_EN,
1818 0, 1);
David Keitel33f58952013-05-20 16:17:36 -07001819 if (rc) {
1820 pr_err("failed to disable boost rc=%d\n", rc);
1821 return rc;
1822 }
1823
1824 rc = qpnp_chg_read(chip, &vbat_sts,
1825 chip->chgr_base + CHGR_VBAT_STATUS, 1);
1826 if (rc) {
1827 pr_err("failed to read bat sts rc=%d\n", rc);
1828 return rc;
1829 }
1830
1831 if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
1832 rc = qpnp_chg_masked_write(chip,
1833 chip->chgr_base + SEC_ACCESS,
1834 0xFF,
1835 0xA5, 1);
1836 if (rc) {
1837 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1838 return rc;
1839 }
1840
1841 rc = qpnp_chg_masked_write(chip,
1842 chip->chgr_base + COMP_OVR1,
1843 0xFF,
1844 0x20, 1);
1845 if (rc) {
1846 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1847 return rc;
1848 }
1849
1850 usleep(2000);
1851
1852 rc = qpnp_chg_masked_write(chip,
1853 chip->chgr_base + SEC_ACCESS,
1854 0xFF,
1855 0xA5, 1);
1856 if (rc) {
1857 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1858 return rc;
1859 }
1860
1861 rc = qpnp_chg_masked_write(chip,
1862 chip->chgr_base + COMP_OVR1,
1863 0xFF,
1864 0x00, 1);
1865 if (rc) {
1866 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1867 return rc;
1868 }
1869 }
1870
1871 if (qpnp_chg_is_usb_chg_plugged_in(chip)
1872 && (chip->flags & BOOST_FLASH_WA)) {
1873 rc = qpnp_chg_masked_write(chip,
1874 chip->usb_chgpth_base + SEC_ACCESS,
1875 0xFF,
1876 0xA5, 1);
1877 if (rc) {
1878 pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
1879 return rc;
1880 }
1881
1882 rc = qpnp_chg_masked_write(chip,
1883 chip->usb_chgpth_base + COMP_OVR1,
1884 0xFF,
1885 0x00, 1);
1886 if (rc) {
1887 pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
1888 return rc;
1889 }
1890
1891 usleep(1000);
1892
1893 qpnp_chg_usb_suspend_enable(chip, 0);
1894 }
1895
1896 return rc;
David Keitel6dc4ed42013-05-17 11:08:58 -07001897}
1898
1899static int
1900qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
1901{
1902 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1903
1904 return qpnp_chg_is_boost_en_set(chip);
1905}
1906
1907static int
1908qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
1909 int min_uV, int max_uV, unsigned *selector)
1910{
1911 int uV = min_uV;
1912 int rc;
1913 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1914
1915 if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
1916 uV = BOOST_MIN_UV;
1917
1918
1919 if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
1920 pr_err("request %d uV is out of bounds\n", uV);
1921 return -EINVAL;
1922 }
1923
1924 *selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
1925 if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
1926 pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
1927 return -EINVAL;
1928 }
1929
1930 rc = qpnp_boost_vset(chip, uV);
1931
1932 return rc;
1933}
1934
1935static int
1936qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
1937{
1938 struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
1939
1940 return qpnp_boost_vget_uv(chip);
1941}
1942
1943static int
1944qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
1945 unsigned selector)
1946{
1947 if (selector >= N_BOOST_V)
1948 return 0;
1949
1950 return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
1951}
1952
1953static struct regulator_ops qpnp_chg_otg_reg_ops = {
1954 .enable = qpnp_chg_regulator_otg_enable,
1955 .disable = qpnp_chg_regulator_otg_disable,
1956 .is_enabled = qpnp_chg_regulator_otg_is_enabled,
1957};
1958
1959static struct regulator_ops qpnp_chg_boost_reg_ops = {
1960 .enable = qpnp_chg_regulator_boost_enable,
1961 .disable = qpnp_chg_regulator_boost_disable,
1962 .is_enabled = qpnp_chg_regulator_boost_is_enabled,
1963 .set_voltage = qpnp_chg_regulator_boost_set_voltage,
1964 .get_voltage = qpnp_chg_regulator_boost_get_voltage,
1965 .list_voltage = qpnp_chg_regulator_boost_list_voltage,
1966};
1967
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07001968#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 13
1969#define MAX_DELTA_VDD_MAX_MV 30
1970static void
1971qpnp_chg_adjust_vddmax(struct qpnp_chg_chip *chip, int vbat_mv)
1972{
1973 int delta_mv, closest_delta_mv, sign;
1974
1975 delta_mv = chip->max_voltage_mv - vbat_mv;
1976 if (delta_mv > 0 && delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
1977 pr_debug("vbat is not low enough to increase vdd\n");
1978 return;
1979 }
1980
1981 sign = delta_mv > 0 ? 1 : -1;
1982 closest_delta_mv = ((delta_mv + sign * QPNP_CHG_V_STEP_MV / 2)
1983 / QPNP_CHG_V_STEP_MV) * QPNP_CHG_V_STEP_MV;
1984 pr_debug("max_voltage = %d, vbat_mv = %d, delta_mv = %d, closest = %d\n",
1985 chip->max_voltage_mv, vbat_mv,
1986 delta_mv, closest_delta_mv);
1987 chip->delta_vddmax_mv = clamp(chip->delta_vddmax_mv + closest_delta_mv,
1988 -MAX_DELTA_VDD_MAX_MV, MAX_DELTA_VDD_MAX_MV);
1989 pr_debug("using delta_vddmax_mv = %d\n", chip->delta_vddmax_mv);
1990 qpnp_chg_set_appropriate_vddmax(chip);
1991}
1992
David Keitel9fd07382013-05-02 15:37:44 -07001993#define CONSECUTIVE_COUNT 3
1994static void
1995qpnp_eoc_work(struct work_struct *work)
1996{
1997 struct delayed_work *dwork = to_delayed_work(work);
1998 struct qpnp_chg_chip *chip = container_of(dwork,
1999 struct qpnp_chg_chip, eoc_work);
2000 static int count;
2001 int ibat_ma, vbat_mv, rc = 0;
2002 u8 batt_sts = 0, buck_sts = 0, chg_sts = 0;
2003
2004 wake_lock(&chip->eoc_wake_lock);
2005 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2006
2007 rc = qpnp_chg_read(chip, &batt_sts, INT_RT_STS(chip->bat_if_base), 1);
2008 if (rc) {
2009 pr_err("failed to read batt_if rc=%d\n", rc);
2010 return;
2011 }
2012
2013 rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
2014 if (rc) {
2015 pr_err("failed to read buck rc=%d\n", rc);
2016 return;
2017 }
2018
2019 rc = qpnp_chg_read(chip, &chg_sts, INT_RT_STS(chip->chgr_base), 1);
2020 if (rc) {
2021 pr_err("failed to read chg_sts rc=%d\n", rc);
2022 return;
2023 }
2024
2025 pr_debug("chgr: 0x%x, bat_if: 0x%x, buck: 0x%x\n",
2026 chg_sts, batt_sts, buck_sts);
2027
2028 if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
2029 !qpnp_chg_is_dc_chg_plugged_in(chip)) {
2030 pr_debug("no chg connected, stopping\n");
2031 goto stop_eoc;
2032 }
2033
2034 if ((batt_sts & BAT_FET_ON_IRQ) && (chg_sts & FAST_CHG_ON_IRQ
2035 || chg_sts & TRKL_CHG_ON_IRQ)) {
2036 ibat_ma = get_prop_current_now(chip) / 1000;
2037 vbat_mv = get_prop_battery_voltage_now(chip) / 1000;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002038
2039 pr_debug("ibat_ma = %d vbat_mv = %d term_current_ma = %d\n",
2040 ibat_ma, vbat_mv, chip->term_current);
2041
2042 if ((!(chg_sts & VBAT_DET_LOW_IRQ)) && (vbat_mv <
2043 (chip->max_voltage_mv - chip->resume_delta_mv))) {
2044 pr_debug("woke up too early\n");
2045 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
2046 goto stop_eoc;
2047 }
2048
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07002049 if (buck_sts & VDD_LOOP_IRQ)
2050 qpnp_chg_adjust_vddmax(chip, vbat_mv);
2051
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002052 if (!(buck_sts & VDD_LOOP_IRQ)) {
2053 pr_debug("Not in CV\n");
David Keitel9fd07382013-05-02 15:37:44 -07002054 count = 0;
Xiaozhe Shi22af5fe2013-05-29 10:38:30 -07002055 } else if ((ibat_ma * -1) > chip->term_current) {
2056 pr_debug("Not at EOC, battery current too high\n");
2057 count = 0;
2058 } else if (ibat_ma > 0) {
2059 pr_debug("Charging but system demand increased\n");
2060 count = 0;
2061 } else {
David Keitel9fd07382013-05-02 15:37:44 -07002062 if (count == CONSECUTIVE_COUNT) {
2063 pr_info("End of Charging\n");
2064 qpnp_chg_charge_en(chip, 0);
2065 chip->chg_done = true;
2066 power_supply_changed(&chip->batt_psy);
David Keitel47185a62013-05-15 18:54:10 -07002067 qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
David Keitel9fd07382013-05-02 15:37:44 -07002068 goto stop_eoc;
2069 } else {
2070 count += 1;
2071 pr_debug("EOC count = %d\n", count);
2072 }
David Keitel9fd07382013-05-02 15:37:44 -07002073 }
2074 } else {
2075 pr_debug("not charging\n");
2076 goto stop_eoc;
2077 }
2078
2079 schedule_delayed_work(&chip->eoc_work,
2080 msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
2081 return;
2082
2083stop_eoc:
2084 count = 0;
2085 wake_unlock(&chip->eoc_wake_lock);
2086}
2087
David Keitel0c1a4532013-03-21 16:39:06 -07002088#define HYSTERISIS_DECIDEGC 20
David Keitel454ee842013-03-08 16:19:11 -08002089static void
2090qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
2091{
2092 struct qpnp_chg_chip *chip = ctx;
2093 bool bat_warm = 0, bat_cool = 0;
David Keitel1219a802013-03-21 16:37:21 -07002094 int temp;
David Keitel454ee842013-03-08 16:19:11 -08002095
2096 if (state >= ADC_TM_STATE_NUM) {
2097 pr_err("invalid notification %d\n", state);
2098 return;
2099 }
2100
David Keitel1219a802013-03-21 16:37:21 -07002101 temp = get_prop_batt_temp(chip);
David Keitel454ee842013-03-08 16:19:11 -08002102
David Keitel1219a802013-03-21 16:37:21 -07002103 pr_debug("temp = %d state = %s\n", temp,
2104 state == ADC_TM_WARM_STATE ? "warm" : "cool");
2105
2106 if (state == ADC_TM_WARM_STATE) {
2107 if (temp > chip->warm_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002108 /* Normal to warm */
David Keitel454ee842013-03-08 16:19:11 -08002109 bat_warm = true;
2110 bat_cool = false;
2111 chip->adc_param.low_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002112 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002113 chip->adc_param.state_request =
2114 ADC_TM_COOL_THR_ENABLE;
2115 } else if (temp >
2116 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002117 /* Cool to normal */
David Keitel454ee842013-03-08 16:19:11 -08002118 bat_warm = false;
2119 bat_cool = false;
David Keitel1219a802013-03-21 16:37:21 -07002120
2121 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel0c1a4532013-03-21 16:39:06 -07002122 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07002123 chip->adc_param.state_request =
2124 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08002125 }
2126 } else {
David Keitel1219a802013-03-21 16:37:21 -07002127 if (temp < chip->cool_bat_decidegc) {
David Keitel3e37e5a2013-04-18 10:42:30 -07002128 /* Normal to cool */
David Keitel454ee842013-03-08 16:19:11 -08002129 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002130 bat_cool = true;
David Keitel454ee842013-03-08 16:19:11 -08002131 chip->adc_param.high_temp =
David Keitel0c1a4532013-03-21 16:39:06 -07002132 chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
David Keitel1219a802013-03-21 16:37:21 -07002133 chip->adc_param.state_request =
2134 ADC_TM_WARM_THR_ENABLE;
David Keitel3e37e5a2013-04-18 10:42:30 -07002135 } else if (temp <
David Keitel1219a802013-03-21 16:37:21 -07002136 chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
David Keitel3e37e5a2013-04-18 10:42:30 -07002137 /* Warm to normal */
David Keitel454ee842013-03-08 16:19:11 -08002138 bat_warm = false;
David Keitel1219a802013-03-21 16:37:21 -07002139 bat_cool = false;
2140
David Keitel0c1a4532013-03-21 16:39:06 -07002141 chip->adc_param.low_temp = chip->cool_bat_decidegc;
David Keitel1219a802013-03-21 16:37:21 -07002142 chip->adc_param.high_temp = chip->warm_bat_decidegc;
2143 chip->adc_param.state_request =
2144 ADC_TM_HIGH_LOW_THR_ENABLE;
David Keitel454ee842013-03-08 16:19:11 -08002145 }
2146 }
2147
2148 if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
David Keitel1219a802013-03-21 16:37:21 -07002149 chip->bat_is_cool = bat_cool;
2150 chip->bat_is_warm = bat_warm;
2151
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002152 if (bat_cool || bat_warm)
2153 chip->resuming_charging = false;
2154
2155 /**
2156 * set appropriate voltages and currents.
2157 *
2158 * Note that when the battery is hot or cold, the charger
2159 * driver will not resume with SoC. Only vbatdet is used to
2160 * determine resume of charging.
2161 */
David Keitel454ee842013-03-08 16:19:11 -08002162 qpnp_chg_set_appropriate_vddmax(chip);
2163 qpnp_chg_set_appropriate_battery_current(chip);
2164 qpnp_chg_set_appropriate_vbatdet(chip);
David Keitel454ee842013-03-08 16:19:11 -08002165 }
2166
David Keitel1219a802013-03-21 16:37:21 -07002167 if (qpnp_adc_tm_channel_measure(&chip->adc_param))
2168 pr_err("request ADC error\n");
David Keitel454ee842013-03-08 16:19:11 -08002169}
2170
David Keitelbe208252013-01-31 14:49:25 -08002171static int
David Keitel432e1232013-06-05 16:10:18 -07002172qpnp_dc_power_set_property(struct power_supply *psy,
2173 enum power_supply_property psp,
2174 const union power_supply_propval *val)
2175{
2176 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2177 dc_psy);
2178 int rc = 0;
2179
2180 switch (psp) {
2181 case POWER_SUPPLY_PROP_CURRENT_MAX:
2182 if (!val->intval)
2183 break;
2184
2185 rc = qpnp_chg_idcmax_set(chip, val->intval / 1000);
2186 if (rc) {
2187 pr_err("Error setting idcmax property %d\n", rc);
2188 return rc;
2189 }
2190 chip->maxinput_dc_ma = (val->intval / 1000);
2191
2192 break;
2193 default:
2194 return -EINVAL;
2195 }
2196
2197 power_supply_changed(&chip->dc_psy);
2198 return rc;
2199}
2200
2201static int
David Keitelbe208252013-01-31 14:49:25 -08002202qpnp_batt_power_set_property(struct power_supply *psy,
2203 enum power_supply_property psp,
2204 const union power_supply_propval *val)
2205{
2206 struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
2207 batt_psy);
2208
2209 switch (psp) {
2210 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
2211 chip->charging_disabled = !(val->intval);
2212 qpnp_chg_charge_en(chip, !chip->charging_disabled);
2213 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
2214 break;
2215 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
2216 qpnp_batt_system_temp_level_set(chip, val->intval);
2217 break;
2218 default:
2219 return -EINVAL;
2220 }
2221
2222 power_supply_changed(&chip->batt_psy);
2223 return 0;
2224}
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08002225
2226static void
2227qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
David Keiteld681cda2012-10-02 15:44:21 -07002228{
David Keitelfe51cb92013-04-02 19:42:58 -07002229 if (chip->revision > 0 && chip->type == SMBB)
David Keiteld681cda2012-10-02 15:44:21 -07002230 chip->flags |= CHG_FLAGS_VCP_WA;
David Keitel33f58952013-05-20 16:17:36 -07002231 if (chip->type == SMBB)
2232 chip->flags |= BOOST_FLASH_WA;
David Keitel14288042013-06-04 15:16:46 -07002233 if (chip->type == SMBBP)
2234 chip->flags |= BOOST_FLASH_WA;
David Keiteld681cda2012-10-02 15:44:21 -07002235}
2236
David Keitel0f35be42013-04-16 11:10:40 -07002237static int
2238qpnp_chg_request_irqs(struct qpnp_chg_chip *chip)
2239{
2240 int rc = 0;
2241 struct resource *resource;
2242 struct spmi_resource *spmi_resource;
2243 u8 subtype;
2244 struct spmi_device *spmi = chip->spmi;
2245
2246 spmi_for_each_container_dev(spmi_resource, chip->spmi) {
2247 if (!spmi_resource) {
2248 pr_err("qpnp_chg: spmi resource absent\n");
2249 return rc;
2250 }
2251
2252 resource = spmi_get_resource(spmi, spmi_resource,
2253 IORESOURCE_MEM, 0);
2254 if (!(resource && resource->start)) {
2255 pr_err("node %s IO resource absent!\n",
2256 spmi->dev.of_node->full_name);
2257 return rc;
2258 }
2259
2260 rc = qpnp_chg_read(chip, &subtype,
2261 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2262 if (rc) {
2263 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2264 return rc;
2265 }
2266
2267 switch (subtype) {
2268 case SMBB_CHGR_SUBTYPE:
2269 case SMBBP_CHGR_SUBTYPE:
2270 case SMBCL_CHGR_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002271 chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002272 spmi_resource, "fast-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07002273 if (chip->chg_fastchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002274 pr_err("Unable to get fast-chg-on irq\n");
2275 return rc;
2276 }
2277
David Keitel47185a62013-05-15 18:54:10 -07002278 chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002279 spmi_resource, "trkl-chg-on");
David Keitel47185a62013-05-15 18:54:10 -07002280 if (chip->chg_trklchg.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002281 pr_err("Unable to get trkl-chg-on irq\n");
2282 return rc;
2283 }
2284
David Keitel47185a62013-05-15 18:54:10 -07002285 chip->chg_failed.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002286 spmi_resource, "chg-failed");
David Keitel47185a62013-05-15 18:54:10 -07002287 if (chip->chg_failed.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002288 pr_err("Unable to get chg_failed irq\n");
2289 return rc;
2290 }
2291
David Keitel47185a62013-05-15 18:54:10 -07002292 chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
David Keitel9fd07382013-05-02 15:37:44 -07002293 spmi_resource, "vbat-det-lo");
David Keitel47185a62013-05-15 18:54:10 -07002294 if (chip->chg_vbatdet_lo.irq < 0) {
David Keitel9fd07382013-05-02 15:37:44 -07002295 pr_err("Unable to get fast-chg-on irq\n");
2296 return rc;
2297 }
2298
David Keitel47185a62013-05-15 18:54:10 -07002299 rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002300 qpnp_chg_chgr_chg_failed_irq_handler,
David Keitelc9f19172013-04-29 11:01:26 -07002301 IRQF_TRIGGER_RISING, "chg-failed", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002302 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002303 pr_err("Can't request %d chg-failed: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002304 chip->chg_failed.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002305 return rc;
2306 }
2307
David Keitel47185a62013-05-15 18:54:10 -07002308 rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002309 qpnp_chg_chgr_chg_fastchg_irq_handler,
2310 IRQF_TRIGGER_RISING,
2311 "fast-chg-on", chip);
2312 if (rc < 0) {
2313 pr_err("Can't request %d fast-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002314 chip->chg_fastchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002315 return rc;
2316 }
2317
David Keitel47185a62013-05-15 18:54:10 -07002318 rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002319 qpnp_chg_chgr_chg_trklchg_irq_handler,
2320 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002321 "trkl-chg-on", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002322 if (rc < 0) {
2323 pr_err("Can't request %d trkl-chg-on: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002324 chip->chg_trklchg.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002325 return rc;
2326 }
David Keitel9fd07382013-05-02 15:37:44 -07002327
2328 rc |= devm_request_irq(chip->dev,
David Keitel47185a62013-05-15 18:54:10 -07002329 chip->chg_vbatdet_lo.irq,
David Keitel9fd07382013-05-02 15:37:44 -07002330 qpnp_chg_vbatdet_lo_irq_handler,
David Keiteld98e2822013-06-05 11:37:34 -07002331 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitel9fd07382013-05-02 15:37:44 -07002332 "vbat-det-lo", chip);
2333 if (rc < 0) {
2334 pr_err("Can't request %d vbat-det-lo: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002335 chip->chg_vbatdet_lo.irq, rc);
David Keitel9fd07382013-05-02 15:37:44 -07002336 return rc;
2337 }
2338
David Keitel47185a62013-05-15 18:54:10 -07002339 enable_irq_wake(chip->chg_trklchg.irq);
2340 enable_irq_wake(chip->chg_failed.irq);
2341 qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
2342 enable_irq_wake(chip->chg_vbatdet_lo.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002343
2344 break;
2345 case SMBB_BAT_IF_SUBTYPE:
2346 case SMBBP_BAT_IF_SUBTYPE:
2347 case SMBCL_BAT_IF_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002348 chip->batt_pres.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002349 spmi_resource, "batt-pres");
David Keitel47185a62013-05-15 18:54:10 -07002350 if (chip->batt_pres.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002351 pr_err("Unable to get batt-pres irq\n");
2352 return rc;
2353 }
David Keitel47185a62013-05-15 18:54:10 -07002354 rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002355 qpnp_chg_bat_if_batt_pres_irq_handler,
David Keitel69193cc2013-06-24 18:12:22 -07002356 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
2357 | IRQF_SHARED | IRQF_ONESHOT,
David Keitelc9f19172013-04-29 11:01:26 -07002358 "batt-pres", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002359 if (rc < 0) {
2360 pr_err("Can't request %d batt-pres irq: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002361 chip->batt_pres.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002362 return rc;
2363 }
2364
David Keitel47185a62013-05-15 18:54:10 -07002365 enable_irq_wake(chip->batt_pres.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002366 break;
2367 case SMBB_USB_CHGPTH_SUBTYPE:
2368 case SMBBP_USB_CHGPTH_SUBTYPE:
2369 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002370 chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002371 spmi_resource, "usbin-valid");
David Keitel47185a62013-05-15 18:54:10 -07002372 if (chip->usbin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002373 pr_err("Unable to get usbin irq\n");
2374 return rc;
2375 }
David Keitel47185a62013-05-15 18:54:10 -07002376 rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002377 qpnp_chg_usb_usbin_valid_irq_handler,
2378 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002379 "usbin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002380 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002381 pr_err("Can't request %d usbin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002382 chip->usbin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002383 return rc;
2384 }
David Keitel344c6972013-04-09 19:28:21 -07002385
David Keitel47185a62013-05-15 18:54:10 -07002386 chip->chg_gone.irq = spmi_get_irq_byname(spmi,
David Keitel344c6972013-04-09 19:28:21 -07002387 spmi_resource, "chg-gone");
David Keitel47185a62013-05-15 18:54:10 -07002388 if (chip->chg_gone.irq < 0) {
David Keitel344c6972013-04-09 19:28:21 -07002389 pr_err("Unable to get chg-gone irq\n");
2390 return rc;
2391 }
David Keitel47185a62013-05-15 18:54:10 -07002392 rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
David Keitel344c6972013-04-09 19:28:21 -07002393 qpnp_chg_usb_chg_gone_irq_handler,
2394 IRQF_TRIGGER_RISING,
David Keitelc9f19172013-04-29 11:01:26 -07002395 "chg-gone", chip);
David Keitel344c6972013-04-09 19:28:21 -07002396 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002397 pr_err("Can't request %d chg-gone: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002398 chip->chg_gone.irq, rc);
David Keitel344c6972013-04-09 19:28:21 -07002399 return rc;
2400 }
David Keitel47185a62013-05-15 18:54:10 -07002401
2402 enable_irq_wake(chip->usbin_valid.irq);
2403 enable_irq_wake(chip->chg_gone.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002404 break;
2405 case SMBB_DC_CHGPTH_SUBTYPE:
David Keitel47185a62013-05-15 18:54:10 -07002406 chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
David Keitel0f35be42013-04-16 11:10:40 -07002407 spmi_resource, "dcin-valid");
David Keitel47185a62013-05-15 18:54:10 -07002408 if (chip->dcin_valid.irq < 0) {
David Keitel0f35be42013-04-16 11:10:40 -07002409 pr_err("Unable to get dcin irq\n");
2410 return -rc;
2411 }
David Keitel47185a62013-05-15 18:54:10 -07002412 rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
David Keitel0f35be42013-04-16 11:10:40 -07002413 qpnp_chg_dc_dcin_valid_irq_handler,
2414 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
David Keitelc9f19172013-04-29 11:01:26 -07002415 "dcin-valid", chip);
David Keitel0f35be42013-04-16 11:10:40 -07002416 if (rc < 0) {
David Keitelc9f19172013-04-29 11:01:26 -07002417 pr_err("Can't request %d dcin-valid: %d\n",
David Keitel47185a62013-05-15 18:54:10 -07002418 chip->dcin_valid.irq, rc);
David Keitel0f35be42013-04-16 11:10:40 -07002419 return rc;
2420 }
2421
David Keitel47185a62013-05-15 18:54:10 -07002422 enable_irq_wake(chip->dcin_valid.irq);
David Keitel0f35be42013-04-16 11:10:40 -07002423 break;
2424 }
2425 }
2426
2427 return rc;
2428}
2429
Xiaozhe Shica289e02013-06-19 13:24:51 -07002430static int
2431qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
2432{
2433 struct bms_battery_data batt_data;
2434 struct device_node *node;
2435 struct qpnp_vadc_result result;
2436 int rc;
2437
2438 node = of_find_node_by_name(chip->spmi->dev.of_node,
2439 "qcom,battery-data");
2440 if (node) {
2441 memset(&batt_data, 0, sizeof(struct bms_battery_data));
2442 rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
2443 if (rc) {
2444 pr_err("error reading batt id channel = %d, rc = %d\n",
2445 LR_MUX2_BAT_ID, rc);
2446 return rc;
2447 }
2448
2449 rc = of_batterydata_read_data(node,
2450 &batt_data, result.physical);
2451 if (rc) {
2452 pr_err("failed to read battery data: %d\n", rc);
2453 return rc;
2454 }
2455
2456 if (batt_data.max_voltage_uv >= 0)
2457 chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
2458 if (batt_data.iterm_ua >= 0)
2459 chip->term_current = batt_data.iterm_ua / 1000;
2460 }
2461
2462 return 0;
2463}
2464
David Keitel80668952012-07-27 14:25:49 -07002465#define WDOG_EN_BIT BIT(7)
2466static int
2467qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
2468 struct spmi_resource *spmi_resource)
2469{
2470 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07002471 u8 reg = 0;
David Keitel6dc4ed42013-05-17 11:08:58 -07002472 struct regulator_init_data *init_data;
2473 struct regulator_desc *rdesc;
David Keitel80668952012-07-27 14:25:49 -07002474
2475 switch (subtype) {
2476 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002477 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002478 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07002479 rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
2480 if (rc) {
2481 pr_debug("failed setting min_voltage rc=%d\n", rc);
2482 return rc;
2483 }
2484 rc = qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
2485 if (rc) {
2486 pr_debug("failed setting max_voltage rc=%d\n", rc);
2487 return rc;
2488 }
2489 rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
2490 if (rc) {
2491 pr_debug("failed setting safe_voltage rc=%d\n", rc);
2492 return rc;
2493 }
David Keitel454ee842013-03-08 16:19:11 -08002494 rc = qpnp_chg_vbatdet_set(chip,
2495 chip->max_voltage_mv - chip->resume_delta_mv);
David Keitel5d44fa52012-12-03 16:37:31 -08002496 if (rc) {
2497 pr_debug("failed setting resume_voltage rc=%d\n", rc);
2498 return rc;
2499 }
David Keitel80668952012-07-27 14:25:49 -07002500 rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
2501 if (rc) {
2502 pr_debug("failed setting ibatmax rc=%d\n", rc);
2503 return rc;
2504 }
David Keitel365c4c42013-03-08 16:20:40 -08002505 if (chip->term_current) {
2506 rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
2507 if (rc) {
2508 pr_debug("failed setting ibatterm rc=%d\n", rc);
2509 return rc;
2510 }
David Keitel80668952012-07-27 14:25:49 -07002511 }
David Keitel5d44fa52012-12-03 16:37:31 -08002512 rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
2513 if (rc) {
2514 pr_debug("failed setting ibat_Safe rc=%d\n", rc);
2515 return rc;
2516 }
David Keitela4b7b592013-04-11 18:34:35 -07002517 rc = qpnp_chg_tchg_max_set(chip, chip->tchg_mins);
2518 if (rc) {
2519 pr_debug("failed setting tchg_mins rc=%d\n", rc);
2520 return rc;
2521 }
2522
David Keitel80668952012-07-27 14:25:49 -07002523 /* HACK: Disable wdog */
2524 rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
2525 0xFF, 0xA0, 1);
2526
David Keitelb4e43542013-04-09 17:30:41 -07002527 /* HACK: use analog EOC */
David Keitel80668952012-07-27 14:25:49 -07002528 rc = qpnp_chg_masked_write(chip, chip->chgr_base +
2529 CHGR_IBAT_TERM_CHGR,
David Keitel9fd07382013-05-02 15:37:44 -07002530 0xFF, 0x08, 1);
David Keitel80668952012-07-27 14:25:49 -07002531
David Keitel80668952012-07-27 14:25:49 -07002532 break;
2533 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002534 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002535 case SMBCL_BUCK_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07002536 rc = qpnp_chg_toggle_chg_done_logic(chip, 0);
2537 if (rc)
2538 return rc;
2539
David Keitel9201df32013-01-10 18:38:34 -08002540 rc = qpnp_chg_masked_write(chip,
David Keitel5adc7942013-05-21 13:45:17 -07002541 chip->buck_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
David Keitel9201df32013-01-10 18:38:34 -08002542 BUCK_VBAT_REG_NODE_SEL_BIT,
2543 BUCK_VBAT_REG_NODE_SEL_BIT, 1);
2544 if (rc) {
2545 pr_debug("failed to enable IR drop comp rc=%d\n", rc);
2546 return rc;
2547 }
David Keitel80668952012-07-27 14:25:49 -07002548 break;
2549 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002550 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002551 case SMBCL_BAT_IF_SUBTYPE:
David Keitel796882d2013-05-14 18:01:11 -07002552 /* Select battery presence detection */
David Keitel0ef282b2013-05-29 16:04:57 -07002553 switch (chip->bpd_detection) {
2554 case BPD_TYPE_BAT_THM:
2555 reg = BAT_THM_EN;
2556 break;
2557 case BPD_TYPE_BAT_ID:
David Keitel796882d2013-05-14 18:01:11 -07002558 reg = BAT_ID_EN;
David Keitel0ef282b2013-05-29 16:04:57 -07002559 break;
2560 case BPD_TYPE_BAT_THM_BAT_ID:
2561 reg = BAT_THM_EN | BAT_ID_EN;
2562 break;
2563 default:
2564 reg = BAT_THM_EN;
2565 break;
2566 }
David Keitel796882d2013-05-14 18:01:11 -07002567
2568 rc = qpnp_chg_masked_write(chip,
2569 chip->bat_if_base + BAT_IF_BPD_CTRL,
2570 BAT_IF_BPD_CTRL_SEL,
2571 reg, 1);
2572 if (rc) {
2573 pr_debug("failed to chose BPD rc=%d\n", rc);
2574 return rc;
2575 }
David Keitel85ae4342013-04-16 11:46:00 -07002576 /* Force on VREF_BAT_THM */
2577 rc = qpnp_chg_masked_write(chip,
2578 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
2579 VREF_BATT_THERM_FORCE_ON,
2580 VREF_BATT_THERM_FORCE_ON, 1);
2581 if (rc) {
2582 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
2583 return rc;
2584 }
David Keitel80668952012-07-27 14:25:49 -07002585 break;
2586 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002587 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002588 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel9fd07382013-05-02 15:37:44 -07002589 if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
David Keitel80668952012-07-27 14:25:49 -07002590 rc = qpnp_chg_masked_write(chip,
2591 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
2592 ENUM_T_STOP_BIT,
2593 ENUM_T_STOP_BIT, 1);
2594 if (rc) {
2595 pr_err("failed to write enum stop rc=%d\n", rc);
2596 return -ENXIO;
2597 }
2598 }
David Keiteld681cda2012-10-02 15:44:21 -07002599
David Keitel6dc4ed42013-05-17 11:08:58 -07002600 init_data = of_get_regulator_init_data(chip->dev,
2601 spmi_resource->of_node);
2602 if (!init_data) {
2603 pr_err("unable to allocate memory\n");
2604 return -ENOMEM;
2605 }
2606
2607 if (init_data->constraints.name) {
2608 if (of_get_property(chip->dev->of_node,
2609 "otg-parent-supply", NULL))
2610 init_data->supply_regulator = "otg-parent";
2611
2612 rdesc = &(chip->otg_vreg.rdesc);
2613 rdesc->owner = THIS_MODULE;
2614 rdesc->type = REGULATOR_VOLTAGE;
2615 rdesc->ops = &qpnp_chg_otg_reg_ops;
2616 rdesc->name = init_data->constraints.name;
2617
2618 init_data->constraints.valid_ops_mask
2619 |= REGULATOR_CHANGE_STATUS;
2620
2621 chip->otg_vreg.rdev = regulator_register(rdesc,
2622 chip->dev, init_data, chip,
2623 spmi_resource->of_node);
2624 if (IS_ERR(chip->otg_vreg.rdev)) {
2625 rc = PTR_ERR(chip->otg_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07002626 chip->otg_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07002627 if (rc != -EPROBE_DEFER)
2628 pr_err("OTG reg failed, rc=%d\n", rc);
2629 return rc;
2630 }
2631 }
2632
David Keiteld681cda2012-10-02 15:44:21 -07002633 rc = qpnp_chg_masked_write(chip,
David Keitel5c3a7702012-12-20 11:13:21 -08002634 chip->usb_chgpth_base + USB_OVP_CTL,
2635 USB_VALID_DEB_20MS,
2636 USB_VALID_DEB_20MS, 1);
2637
2638 rc = qpnp_chg_masked_write(chip,
David Keiteld681cda2012-10-02 15:44:21 -07002639 chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
2640 ENUM_T_STOP_BIT,
2641 ENUM_T_STOP_BIT, 1);
2642
David Keitel344c6972013-04-09 19:28:21 -07002643 rc = qpnp_chg_masked_write(chip,
2644 chip->usb_chgpth_base + SEC_ACCESS,
2645 0xFF,
2646 0xA5, 1);
2647
2648 rc = qpnp_chg_masked_write(chip,
2649 chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
2650 0xFF,
2651 0x80, 1);
2652
David Keitel80668952012-07-27 14:25:49 -07002653 break;
2654 case SMBB_DC_CHGPTH_SUBTYPE:
2655 break;
2656 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002657 case SMBBP_BOOST_SUBTYPE:
David Keitel6dc4ed42013-05-17 11:08:58 -07002658 init_data = of_get_regulator_init_data(chip->dev,
2659 spmi_resource->of_node);
2660 if (!init_data) {
2661 pr_err("unable to allocate memory\n");
2662 return -ENOMEM;
2663 }
2664
2665 if (init_data->constraints.name) {
2666 if (of_get_property(chip->dev->of_node,
2667 "boost-parent-supply", NULL))
2668 init_data->supply_regulator = "boost-parent";
2669
2670 rdesc = &(chip->boost_vreg.rdesc);
2671 rdesc->owner = THIS_MODULE;
2672 rdesc->type = REGULATOR_VOLTAGE;
2673 rdesc->ops = &qpnp_chg_boost_reg_ops;
2674 rdesc->name = init_data->constraints.name;
2675
2676 init_data->constraints.valid_ops_mask
2677 |= REGULATOR_CHANGE_STATUS
2678 | REGULATOR_CHANGE_VOLTAGE;
2679
2680 chip->boost_vreg.rdev = regulator_register(rdesc,
2681 chip->dev, init_data, chip,
2682 spmi_resource->of_node);
2683 if (IS_ERR(chip->boost_vreg.rdev)) {
2684 rc = PTR_ERR(chip->boost_vreg.rdev);
David Collinscbb12132013-05-28 10:47:28 -07002685 chip->boost_vreg.rdev = NULL;
David Keitel6dc4ed42013-05-17 11:08:58 -07002686 if (rc != -EPROBE_DEFER)
2687 pr_err("boost reg failed, rc=%d\n", rc);
2688 return rc;
2689 }
2690 }
David Keitel80668952012-07-27 14:25:49 -07002691 break;
2692 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002693 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002694 case SMBCL_MISC_SUBTYPE:
David Keitel52d685e2013-05-02 11:59:05 -07002695 if (subtype == SMBB_MISC_SUBTYPE)
2696 chip->type = SMBB;
2697 else if (subtype == SMBBP_MISC_SUBTYPE)
2698 chip->type = SMBBP;
2699 else if (subtype == SMBCL_MISC_SUBTYPE)
2700 chip->type = SMBCL;
2701
David Keitel80668952012-07-27 14:25:49 -07002702 pr_debug("Setting BOOT_DONE\n");
2703 rc = qpnp_chg_masked_write(chip,
2704 chip->misc_base + CHGR_MISC_BOOT_DONE,
2705 CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08002706 rc = qpnp_chg_read(chip, &reg,
2707 chip->misc_base + MISC_REVISION2, 1);
2708 if (rc) {
2709 pr_err("failed to read revision register rc=%d\n", rc);
2710 return rc;
2711 }
David Keitel80668952012-07-27 14:25:49 -07002712
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08002713 chip->revision = reg;
David Keitel80668952012-07-27 14:25:49 -07002714 break;
2715 default:
2716 pr_err("Invalid peripheral subtype\n");
2717 }
2718 return rc;
2719}
2720
David Keitel112ba9c2013-04-12 18:40:43 -07002721#define OF_PROP_READ(chip, prop, qpnp_dt_property, retval, optional) \
2722do { \
2723 if (retval) \
2724 break; \
2725 \
2726 retval = of_property_read_u32(chip->spmi->dev.of_node, \
2727 "qcom," qpnp_dt_property, \
2728 &chip->prop); \
2729 \
2730 if ((retval == -EINVAL) && optional) \
2731 retval = 0; \
2732 else if (retval) \
2733 pr_err("Error reading " #qpnp_dt_property \
2734 " property rc = %d\n", rc); \
2735} while (0)
2736
2737static int
2738qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
2739{
2740 int rc = 0;
David Keitel796882d2013-05-14 18:01:11 -07002741 const char *bpd;
David Keitel112ba9c2013-04-12 18:40:43 -07002742
2743 OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
2744 OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
2745 OF_PROP_READ(chip, safe_voltage_mv, "vddsafe-mv", rc, 0);
2746 OF_PROP_READ(chip, resume_delta_mv, "vbatdet-delta-mv", rc, 0);
2747 OF_PROP_READ(chip, safe_current, "ibatsafe-ma", rc, 0);
2748 OF_PROP_READ(chip, max_bat_chg_current, "ibatmax-ma", rc, 0);
2749 if (rc)
2750 pr_err("failed to read required dt parameters %d\n", rc);
2751
2752 OF_PROP_READ(chip, term_current, "ibatterm-ma", rc, 1);
2753 OF_PROP_READ(chip, maxinput_dc_ma, "maxinput-dc-ma", rc, 1);
2754 OF_PROP_READ(chip, maxinput_usb_ma, "maxinput-usb-ma", rc, 1);
2755 OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
2756 OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
David Keitela4b7b592013-04-11 18:34:35 -07002757 OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
David Keitel89c17752013-06-28 14:52:48 -07002758 OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
2759 OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
Xiaozhe Shi7fc4e3c2013-06-06 13:52:29 -07002760 OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
2761
David Keitel112ba9c2013-04-12 18:40:43 -07002762 if (rc)
2763 return rc;
2764
David Keitel796882d2013-05-14 18:01:11 -07002765 rc = of_property_read_string(chip->spmi->dev.of_node,
2766 "qcom,bpd-detection", &bpd);
2767 if (rc) {
David Keitel0ef282b2013-05-29 16:04:57 -07002768 /* Select BAT_THM as default BPD scheme */
2769 chip->bpd_detection = BPD_TYPE_BAT_THM;
David Keitel796882d2013-05-14 18:01:11 -07002770 } else {
2771 chip->bpd_detection = get_bpd(bpd);
2772 if (chip->bpd_detection < 0) {
2773 pr_err("failed to determine bpd schema %d\n", rc);
2774 return rc;
2775 }
2776 }
2777
David Keitel112ba9c2013-04-12 18:40:43 -07002778 /* Look up JEITA compliance parameters if cool and warm temp provided */
2779 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
2780 rc = qpnp_adc_tm_is_ready();
2781 if (rc) {
2782 pr_err("tm not ready %d\n", rc);
2783 return rc;
2784 }
2785
2786 OF_PROP_READ(chip, warm_bat_chg_ma, "ibatmax-warm-ma", rc, 1);
2787 OF_PROP_READ(chip, cool_bat_chg_ma, "ibatmax-cool-ma", rc, 1);
2788 OF_PROP_READ(chip, warm_bat_mv, "warm-bat-mv", rc, 1);
2789 OF_PROP_READ(chip, cool_bat_mv, "cool-bat-mv", rc, 1);
2790 if (rc)
2791 return rc;
2792 }
2793
David Keitel89c17752013-06-28 14:52:48 -07002794 /* Get the btc-disabled property */
2795 chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
2796 "qcom,btc-disabled");
2797
David Keitel112ba9c2013-04-12 18:40:43 -07002798 /* Get the charging-disabled property */
2799 chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
2800 "qcom,charging-disabled");
2801
David Keitel8b68d2d2013-05-14 23:36:51 -07002802 /* Get the duty-cycle-100p property */
2803 chip->duty_cycle_100p = of_property_read_bool(
2804 chip->spmi->dev.of_node,
2805 "qcom,duty-cycle-100p");
David Keitel8b68d2d2013-05-14 23:36:51 -07002806
David Keitel112ba9c2013-04-12 18:40:43 -07002807 /* Get the fake-batt-values property */
2808 chip->use_default_batt_values =
2809 of_property_read_bool(chip->spmi->dev.of_node,
2810 "qcom,use-default-batt-values");
2811
2812 /* Disable charging when faking battery values */
2813 if (chip->use_default_batt_values)
2814 chip->charging_disabled = true;
2815
2816 of_get_property(chip->spmi->dev.of_node, "qcom,thermal-mitigation",
2817 &(chip->thermal_levels));
2818
2819 if (chip->thermal_levels > sizeof(int)) {
2820 chip->thermal_mitigation = kzalloc(
2821 chip->thermal_levels,
2822 GFP_KERNEL);
2823
2824 if (chip->thermal_mitigation == NULL) {
2825 pr_err("thermal mitigation kzalloc() failed.\n");
2826 return rc;
2827 }
2828
2829 chip->thermal_levels /= sizeof(int);
2830 rc = of_property_read_u32_array(chip->spmi->dev.of_node,
2831 "qcom,thermal-mitigation",
2832 chip->thermal_mitigation, chip->thermal_levels);
2833 if (rc) {
2834 pr_err("qcom,thermal-mitigation missing in dt\n");
2835 return rc;
2836 }
2837 }
2838
2839 return rc;
2840}
2841
David Keitel80668952012-07-27 14:25:49 -07002842static int __devinit
2843qpnp_charger_probe(struct spmi_device *spmi)
2844{
2845 u8 subtype;
2846 struct qpnp_chg_chip *chip;
2847 struct resource *resource;
2848 struct spmi_resource *spmi_resource;
2849 int rc = 0;
2850
2851 chip = kzalloc(sizeof *chip, GFP_KERNEL);
2852 if (chip == NULL) {
2853 pr_err("kzalloc() failed.\n");
2854 return -ENOMEM;
2855 }
2856
David Keitel80668952012-07-27 14:25:49 -07002857 chip->dev = &(spmi->dev);
2858 chip->spmi = spmi;
2859
2860 chip->usb_psy = power_supply_get_by_name("usb");
2861 if (!chip->usb_psy) {
2862 pr_err("usb supply not found deferring probe\n");
2863 rc = -EPROBE_DEFER;
2864 goto fail_chg_enable;
2865 }
2866
David Keitel112ba9c2013-04-12 18:40:43 -07002867 /* Get all device tree properties */
2868 rc = qpnp_charger_read_dt_props(chip);
2869 if (rc)
David Keitel80668952012-07-27 14:25:49 -07002870 goto fail_chg_enable;
David Keitel3dd5e0f2012-12-12 18:12:36 -08002871
Xiaozhe Shica289e02013-06-19 13:24:51 -07002872 /*
2873 * Check if bat_if is set in DT and make sure VADC is present
2874 * Also try loading the battery data profile if bat_if exists
2875 */
David Keiteldd87a172013-05-29 17:05:43 -07002876 spmi_for_each_container_dev(spmi_resource, spmi) {
2877 if (!spmi_resource) {
2878 pr_err("qpnp_chg: spmi resource absent\n");
2879 rc = -ENXIO;
2880 goto fail_chg_enable;
2881 }
2882
2883 resource = spmi_get_resource(spmi, spmi_resource,
2884 IORESOURCE_MEM, 0);
2885 if (!(resource && resource->start)) {
2886 pr_err("node %s IO resource absent!\n",
2887 spmi->dev.of_node->full_name);
2888 rc = -ENXIO;
2889 goto fail_chg_enable;
2890 }
2891
2892 rc = qpnp_chg_read(chip, &subtype,
2893 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2894 if (rc) {
2895 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2896 goto fail_chg_enable;
2897 }
2898
2899 if (subtype == SMBB_BAT_IF_SUBTYPE ||
2900 subtype == SMBBP_BAT_IF_SUBTYPE ||
2901 subtype == SMBCL_BAT_IF_SUBTYPE){
2902 rc = qpnp_vadc_is_ready();
2903 if (rc)
2904 goto fail_chg_enable;
Xiaozhe Shica289e02013-06-19 13:24:51 -07002905
2906 rc = qpnp_chg_load_battery_data(chip);
2907 if (rc)
2908 goto fail_chg_enable;
David Keiteldd87a172013-05-29 17:05:43 -07002909 }
2910 }
2911
David Keitel80668952012-07-27 14:25:49 -07002912 spmi_for_each_container_dev(spmi_resource, spmi) {
2913 if (!spmi_resource) {
2914 pr_err("qpnp_chg: spmi resource absent\n");
2915 rc = -ENXIO;
2916 goto fail_chg_enable;
2917 }
2918
2919 resource = spmi_get_resource(spmi, spmi_resource,
2920 IORESOURCE_MEM, 0);
2921 if (!(resource && resource->start)) {
2922 pr_err("node %s IO resource absent!\n",
2923 spmi->dev.of_node->full_name);
2924 rc = -ENXIO;
2925 goto fail_chg_enable;
2926 }
2927
2928 rc = qpnp_chg_read(chip, &subtype,
2929 resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
2930 if (rc) {
2931 pr_err("Peripheral subtype read failed rc=%d\n", rc);
2932 goto fail_chg_enable;
2933 }
2934
2935 switch (subtype) {
2936 case SMBB_CHGR_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002937 case SMBBP_CHGR_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002938 case SMBCL_CHGR_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07002939 chip->chgr_base = resource->start;
2940 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
2941 if (rc) {
2942 pr_err("Failed to init subtype 0x%x rc=%d\n",
2943 subtype, rc);
2944 goto fail_chg_enable;
2945 }
2946 break;
2947 case SMBB_BUCK_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002948 case SMBBP_BUCK_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002949 case SMBCL_BUCK_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07002950 chip->buck_base = resource->start;
2951 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
2952 if (rc) {
2953 pr_err("Failed to init subtype 0x%x rc=%d\n",
2954 subtype, rc);
2955 goto fail_chg_enable;
2956 }
David Keitel344c6972013-04-09 19:28:21 -07002957
2958 rc = qpnp_chg_masked_write(chip,
2959 chip->buck_base + SEC_ACCESS,
2960 0xFF,
2961 0xA5, 1);
2962
2963 rc = qpnp_chg_masked_write(chip,
2964 chip->buck_base + BUCK_VCHG_OV,
2965 0xff,
2966 0x00, 1);
2967
2968 rc = qpnp_chg_masked_write(chip,
2969 chip->buck_base + SEC_ACCESS,
2970 0xFF,
2971 0xA5, 1);
2972
2973 rc = qpnp_chg_masked_write(chip,
2974 chip->buck_base + BUCK_TEST_SMBC_MODES,
2975 0xFF,
2976 0x80, 1);
2977
David Keiteldbc949b2013-07-11 10:56:03 -07002978 if (chip->duty_cycle_100p) {
2979 rc = qpnp_buck_set_100_duty_cycle_enable(chip,
2980 1);
2981 if (rc) {
2982 pr_err("failed to set duty cycle %d\n",
2983 rc);
2984 goto fail_chg_enable;
2985 }
2986 }
2987
David Keitel80668952012-07-27 14:25:49 -07002988 break;
2989 case SMBB_BAT_IF_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08002990 case SMBBP_BAT_IF_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07002991 case SMBCL_BAT_IF_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07002992 chip->bat_if_base = resource->start;
2993 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
2994 if (rc) {
2995 pr_err("Failed to init subtype 0x%x rc=%d\n",
2996 subtype, rc);
2997 goto fail_chg_enable;
2998 }
2999 break;
3000 case SMBB_USB_CHGPTH_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003001 case SMBBP_USB_CHGPTH_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003002 case SMBCL_USB_CHGPTH_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003003 chip->usb_chgpth_base = resource->start;
3004 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3005 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07003006 if (rc != -EPROBE_DEFER)
3007 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07003008 subtype, rc);
3009 goto fail_chg_enable;
3010 }
3011 break;
3012 case SMBB_DC_CHGPTH_SUBTYPE:
3013 chip->dc_chgpth_base = resource->start;
3014 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3015 if (rc) {
3016 pr_err("Failed to init subtype 0x%x rc=%d\n",
3017 subtype, rc);
3018 goto fail_chg_enable;
3019 }
3020 break;
3021 case SMBB_BOOST_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003022 case SMBBP_BOOST_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003023 chip->boost_base = resource->start;
3024 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3025 if (rc) {
David Keitel6dc4ed42013-05-17 11:08:58 -07003026 if (rc != -EPROBE_DEFER)
3027 pr_err("Failed to init subtype 0x%x rc=%d\n",
David Keitel80668952012-07-27 14:25:49 -07003028 subtype, rc);
3029 goto fail_chg_enable;
3030 }
3031 break;
3032 case SMBB_MISC_SUBTYPE:
David Keitelf2170cc2013-02-20 17:49:03 -08003033 case SMBBP_MISC_SUBTYPE:
David Keitel46c9f7b2013-04-02 19:54:12 -07003034 case SMBCL_MISC_SUBTYPE:
David Keitel80668952012-07-27 14:25:49 -07003035 chip->misc_base = resource->start;
3036 rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
3037 if (rc) {
3038 pr_err("Failed to init subtype=0x%x rc=%d\n",
3039 subtype, rc);
3040 goto fail_chg_enable;
3041 }
3042 break;
3043 default:
3044 pr_err("Invalid peripheral subtype=0x%x\n", subtype);
3045 rc = -EINVAL;
3046 goto fail_chg_enable;
3047 }
3048 }
3049 dev_set_drvdata(&spmi->dev, chip);
3050 device_init_wakeup(&spmi->dev, 1);
3051
David Keitelf2170cc2013-02-20 17:49:03 -08003052 if (chip->bat_if_base) {
David Keitelf2170cc2013-02-20 17:49:03 -08003053 chip->batt_psy.name = "battery";
3054 chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
3055 chip->batt_psy.properties = msm_batt_power_props;
3056 chip->batt_psy.num_properties =
3057 ARRAY_SIZE(msm_batt_power_props);
3058 chip->batt_psy.get_property = qpnp_batt_power_get_property;
3059 chip->batt_psy.set_property = qpnp_batt_power_set_property;
3060 chip->batt_psy.property_is_writeable =
3061 qpnp_batt_property_is_writeable;
3062 chip->batt_psy.external_power_changed =
David Keitel80668952012-07-27 14:25:49 -07003063 qpnp_batt_external_power_changed;
Xiaozhe Shi890fbf42013-05-02 16:42:53 -07003064 chip->batt_psy.supplied_to = pm_batt_supplied_to;
3065 chip->batt_psy.num_supplicants =
3066 ARRAY_SIZE(pm_batt_supplied_to);
David Keitel80668952012-07-27 14:25:49 -07003067
David Keitelf2170cc2013-02-20 17:49:03 -08003068 rc = power_supply_register(chip->dev, &chip->batt_psy);
3069 if (rc < 0) {
3070 pr_err("batt failed to register rc = %d\n", rc);
3071 goto fail_chg_enable;
3072 }
David Keitel79f4c932013-04-03 16:08:39 -07003073 INIT_WORK(&chip->adc_measure_work,
3074 qpnp_bat_if_adc_measure_work);
David Keitelc7093b02013-02-14 12:50:04 -08003075 }
3076
David Keitel9fd07382013-05-02 15:37:44 -07003077 wake_lock_init(&chip->eoc_wake_lock,
3078 WAKE_LOCK_SUSPEND, "qpnp-chg-eoc-lock");
3079 INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
David Keitel5910eea2013-05-02 15:32:25 -07003080 INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
3081
David Keitelf2170cc2013-02-20 17:49:03 -08003082 if (chip->dc_chgpth_base) {
3083 chip->dc_psy.name = "qpnp-dc";
3084 chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
3085 chip->dc_psy.supplied_to = pm_power_supplied_to;
3086 chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
3087 chip->dc_psy.properties = pm_power_props_mains;
3088 chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
3089 chip->dc_psy.get_property = qpnp_power_get_property_mains;
David Keitel432e1232013-06-05 16:10:18 -07003090 chip->dc_psy.set_property = qpnp_dc_power_set_property;
3091 chip->dc_psy.property_is_writeable =
3092 qpnp_dc_property_is_writeable;
David Keitelf2170cc2013-02-20 17:49:03 -08003093
3094 rc = power_supply_register(chip->dev, &chip->dc_psy);
3095 if (rc < 0) {
3096 pr_err("power_supply_register dc failed rc=%d\n", rc);
3097 goto unregister_batt;
3098 }
David Keitel80668952012-07-27 14:25:49 -07003099 }
3100
Sridhar Parasuramae183bd2012-12-21 09:28:46 -08003101 /* Turn on appropriate workaround flags */
3102 qpnp_chg_setup_flags(chip);
3103
David Keitelf2170cc2013-02-20 17:49:03 -08003104 if (chip->maxinput_dc_ma && chip->dc_chgpth_base) {
David Keitel22ed2232013-01-28 11:04:07 -08003105 rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
3106 if (rc) {
3107 pr_err("Error setting idcmax property %d\n", rc);
David Keitelf2170cc2013-02-20 17:49:03 -08003108 goto unregister_batt;
David Keitel22ed2232013-01-28 11:04:07 -08003109 }
3110 }
3111
David Keitel0aea18a2013-06-14 18:57:57 -07003112 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
3113 && chip->bat_if_base) {
David Keitel0c1a4532013-03-21 16:39:06 -07003114 chip->adc_param.low_temp = chip->cool_bat_decidegc;
3115 chip->adc_param.high_temp = chip->warm_bat_decidegc;
David Keitel454ee842013-03-08 16:19:11 -08003116 chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
3117 chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
3118 chip->adc_param.btm_ctx = chip;
3119 chip->adc_param.threshold_notification =
3120 qpnp_chg_adc_notification;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08003121 chip->adc_param.channel = LR_MUX1_BATT_THERM;
David Keitel0c1a4532013-03-21 16:39:06 -07003122
3123 if (get_prop_batt_present(chip)) {
3124 rc = qpnp_adc_tm_channel_measure(&chip->adc_param);
3125 if (rc) {
3126 pr_err("request ADC error %d\n", rc);
3127 goto fail_chg_enable;
3128 }
David Keitel454ee842013-03-08 16:19:11 -08003129 }
3130 }
David Keitel89c17752013-06-28 14:52:48 -07003131 rc = qpnp_chg_bat_if_configure_btc(chip);
3132 if (rc) {
3133 pr_err("failed to configure btc %d\n", rc);
3134 goto unregister_batt;
3135 }
David Keitel454ee842013-03-08 16:19:11 -08003136
David Keitel03ee6b52012-10-22 12:25:19 -07003137 qpnp_chg_charge_en(chip, !chip->charging_disabled);
David Keitelb1ddb742012-11-06 19:05:51 -08003138 qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
Xiaozhe Shi79a8c492013-05-24 13:09:23 -07003139 qpnp_chg_set_appropriate_vddmax(chip);
David Keitelbf359042012-10-19 16:54:58 -07003140
David Keitel0f35be42013-04-16 11:10:40 -07003141 rc = qpnp_chg_request_irqs(chip);
3142 if (rc) {
3143 pr_err("failed to request interrupts %d\n", rc);
3144 goto unregister_batt;
3145 }
3146
David Keitel9fd07382013-05-02 15:37:44 -07003147 qpnp_chg_usb_usbin_valid_irq_handler(USBIN_VALID_IRQ, chip);
David Keiteld2efc392013-06-05 16:27:12 -07003148 qpnp_chg_dc_dcin_valid_irq_handler(DCIN_VALID_IRQ, chip);
David Keitel9fd07382013-05-02 15:37:44 -07003149 power_supply_set_present(chip->usb_psy,
3150 qpnp_chg_is_usb_chg_plugged_in(chip));
3151
David Keitel3c62b472013-05-06 15:38:11 -07003152 /* Set USB psy online to avoid userspace from shutting down if battery
3153 * capacity is at zero and no chargers online. */
3154 if (qpnp_chg_is_usb_chg_plugged_in(chip))
3155 power_supply_set_online(chip->usb_psy, 1);
3156
David Keitel796882d2013-05-14 18:01:11 -07003157 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 -08003158 chip->charging_disabled,
David Keitel796882d2013-05-14 18:01:11 -07003159 chip->bpd_detection,
Abhijeet Dharmapurikar2d996b12013-01-03 17:48:02 -08003160 qpnp_chg_is_usb_chg_plugged_in(chip),
3161 qpnp_chg_is_dc_chg_plugged_in(chip),
3162 get_prop_batt_present(chip),
3163 get_prop_batt_health(chip));
David Keitel80668952012-07-27 14:25:49 -07003164 return 0;
3165
David Keitelc7093b02013-02-14 12:50:04 -08003166unregister_batt:
David Keitelf2170cc2013-02-20 17:49:03 -08003167 if (chip->bat_if_base)
3168 power_supply_unregister(&chip->batt_psy);
David Keitel80668952012-07-27 14:25:49 -07003169fail_chg_enable:
David Collinscbb12132013-05-28 10:47:28 -07003170 regulator_unregister(chip->otg_vreg.rdev);
3171 regulator_unregister(chip->boost_vreg.rdev);
David Keitelbe208252013-01-31 14:49:25 -08003172 kfree(chip->thermal_mitigation);
David Keitel80668952012-07-27 14:25:49 -07003173 kfree(chip);
3174 dev_set_drvdata(&spmi->dev, NULL);
3175 return rc;
3176}
3177
3178static int __devexit
3179qpnp_charger_remove(struct spmi_device *spmi)
3180{
3181 struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
David Keitel0c1a4532013-03-21 16:39:06 -07003182 if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
3183 && chip->batt_present) {
3184 qpnp_adc_tm_disable_chan_meas(&chip->adc_param);
3185 }
David Keitel79f4c932013-04-03 16:08:39 -07003186 cancel_work_sync(&chip->adc_measure_work);
David Keitel9fd07382013-05-02 15:37:44 -07003187 cancel_delayed_work_sync(&chip->eoc_work);
David Keitel79f4c932013-04-03 16:08:39 -07003188
David Collinscbb12132013-05-28 10:47:28 -07003189 regulator_unregister(chip->otg_vreg.rdev);
3190 regulator_unregister(chip->boost_vreg.rdev);
David Keitel6dc4ed42013-05-17 11:08:58 -07003191
David Keitel80668952012-07-27 14:25:49 -07003192 dev_set_drvdata(&spmi->dev, NULL);
3193 kfree(chip);
3194
3195 return 0;
3196}
3197
David Keitel85ae4342013-04-16 11:46:00 -07003198static int qpnp_chg_resume(struct device *dev)
3199{
3200 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
3201 int rc = 0;
3202
David Keitel39093572013-06-05 15:32:30 -07003203 if (chip->bat_if_base) {
3204 rc = qpnp_chg_masked_write(chip,
3205 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
3206 VREF_BATT_THERM_FORCE_ON,
3207 VREF_BATT_THERM_FORCE_ON, 1);
3208 if (rc)
3209 pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
3210 }
David Keitel85ae4342013-04-16 11:46:00 -07003211
3212 return rc;
3213}
3214
3215static int qpnp_chg_suspend(struct device *dev)
3216{
3217 struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
3218 int rc = 0;
3219
David Keitel39093572013-06-05 15:32:30 -07003220 if (chip->bat_if_base) {
3221 rc = qpnp_chg_masked_write(chip,
3222 chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
3223 VREF_BATT_THERM_FORCE_ON,
3224 VREF_BAT_THM_ENABLED_FSM, 1);
3225 if (rc)
3226 pr_debug("failed to set FSM VREF_BAT_THM rc=%d\n", rc);
3227 }
David Keitel85ae4342013-04-16 11:46:00 -07003228
3229 return rc;
3230}
3231
David Keitel723d5012013-05-03 13:17:27 -07003232static const struct dev_pm_ops qpnp_chg_pm_ops = {
David Keitel85ae4342013-04-16 11:46:00 -07003233 .resume = qpnp_chg_resume,
3234 .suspend = qpnp_chg_suspend,
3235};
3236
David Keitel80668952012-07-27 14:25:49 -07003237static struct spmi_driver qpnp_charger_driver = {
3238 .probe = qpnp_charger_probe,
3239 .remove = __devexit_p(qpnp_charger_remove),
3240 .driver = {
David Keitel723d5012013-05-03 13:17:27 -07003241 .name = QPNP_CHARGER_DEV_NAME,
3242 .owner = THIS_MODULE,
3243 .of_match_table = qpnp_charger_match_table,
3244 .pm = &qpnp_chg_pm_ops,
David Keitel80668952012-07-27 14:25:49 -07003245 },
3246};
3247
3248/**
3249 * qpnp_chg_init() - register spmi driver for qpnp-chg
3250 */
3251int __init
3252qpnp_chg_init(void)
3253{
3254 return spmi_driver_register(&qpnp_charger_driver);
3255}
3256module_init(qpnp_chg_init);
3257
3258static void __exit
3259qpnp_chg_exit(void)
3260{
3261 spmi_driver_unregister(&qpnp_charger_driver);
3262}
3263module_exit(qpnp_chg_exit);
3264
3265
3266MODULE_DESCRIPTION("QPNP charger driver");
3267MODULE_LICENSE("GPL v2");
3268MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);