]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/power/supply/bq24190_charger.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
[mirror_ubuntu-jammy-kernel.git] / drivers / power / supply / bq24190_charger.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
d7bf353f
MG
2/*
3 * Driver for the TI bq24190 battery charger.
4 *
5 * Author: Mark A. Greer <mgreer@animalcreek.com>
d7bf353f
MG
6 */
7
8#include <linux/module.h>
9#include <linux/interrupt.h>
10#include <linux/delay.h>
11#include <linux/of_irq.h>
12#include <linux/of_device.h>
13#include <linux/pm_runtime.h>
14#include <linux/power_supply.h>
66b6bef2
HG
15#include <linux/power/bq24190_charger.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h>
da26580f 18#include <linux/workqueue.h>
d7bf353f
MG
19#include <linux/gpio.h>
20#include <linux/i2c.h>
161a2135 21#include <linux/extcon-provider.h>
d7bf353f 22
d7bf353f
MG
23#define BQ24190_MANUFACTURER "Texas Instruments"
24
25#define BQ24190_REG_ISC 0x00 /* Input Source Control */
26#define BQ24190_REG_ISC_EN_HIZ_MASK BIT(7)
27#define BQ24190_REG_ISC_EN_HIZ_SHIFT 7
28#define BQ24190_REG_ISC_VINDPM_MASK (BIT(6) | BIT(5) | BIT(4) | \
29 BIT(3))
30#define BQ24190_REG_ISC_VINDPM_SHIFT 3
31#define BQ24190_REG_ISC_IINLIM_MASK (BIT(2) | BIT(1) | BIT(0))
32#define BQ24190_REG_ISC_IINLIM_SHIFT 0
33
34#define BQ24190_REG_POC 0x01 /* Power-On Configuration */
35#define BQ24190_REG_POC_RESET_MASK BIT(7)
36#define BQ24190_REG_POC_RESET_SHIFT 7
37#define BQ24190_REG_POC_WDT_RESET_MASK BIT(6)
38#define BQ24190_REG_POC_WDT_RESET_SHIFT 6
39#define BQ24190_REG_POC_CHG_CONFIG_MASK (BIT(5) | BIT(4))
40#define BQ24190_REG_POC_CHG_CONFIG_SHIFT 4
03add17f
LB
41#define BQ24190_REG_POC_CHG_CONFIG_DISABLE 0x0
42#define BQ24190_REG_POC_CHG_CONFIG_CHARGE 0x1
43#define BQ24190_REG_POC_CHG_CONFIG_OTG 0x2
d7bf353f
MG
44#define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1))
45#define BQ24190_REG_POC_SYS_MIN_SHIFT 1
8412a5be
LB
46#define BQ24190_REG_POC_SYS_MIN_MIN 3000
47#define BQ24190_REG_POC_SYS_MIN_MAX 3700
d7bf353f
MG
48#define BQ24190_REG_POC_BOOST_LIM_MASK BIT(0)
49#define BQ24190_REG_POC_BOOST_LIM_SHIFT 0
50
51#define BQ24190_REG_CCC 0x02 /* Charge Current Control */
52#define BQ24190_REG_CCC_ICHG_MASK (BIT(7) | BIT(6) | BIT(5) | \
53 BIT(4) | BIT(3) | BIT(2))
54#define BQ24190_REG_CCC_ICHG_SHIFT 2
55#define BQ24190_REG_CCC_FORCE_20PCT_MASK BIT(0)
56#define BQ24190_REG_CCC_FORCE_20PCT_SHIFT 0
57
58#define BQ24190_REG_PCTCC 0x03 /* Pre-charge/Termination Current Cntl */
59#define BQ24190_REG_PCTCC_IPRECHG_MASK (BIT(7) | BIT(6) | BIT(5) | \
60 BIT(4))
61#define BQ24190_REG_PCTCC_IPRECHG_SHIFT 4
14e1a131
LB
62#define BQ24190_REG_PCTCC_IPRECHG_MIN 128
63#define BQ24190_REG_PCTCC_IPRECHG_MAX 2048
d7bf353f
MG
64#define BQ24190_REG_PCTCC_ITERM_MASK (BIT(3) | BIT(2) | BIT(1) | \
65 BIT(0))
66#define BQ24190_REG_PCTCC_ITERM_SHIFT 0
14e1a131
LB
67#define BQ24190_REG_PCTCC_ITERM_MIN 128
68#define BQ24190_REG_PCTCC_ITERM_MAX 2048
d7bf353f
MG
69
70#define BQ24190_REG_CVC 0x04 /* Charge Voltage Control */
71#define BQ24190_REG_CVC_VREG_MASK (BIT(7) | BIT(6) | BIT(5) | \
72 BIT(4) | BIT(3) | BIT(2))
73#define BQ24190_REG_CVC_VREG_SHIFT 2
74#define BQ24190_REG_CVC_BATLOWV_MASK BIT(1)
75#define BQ24190_REG_CVC_BATLOWV_SHIFT 1
76#define BQ24190_REG_CVC_VRECHG_MASK BIT(0)
77#define BQ24190_REG_CVC_VRECHG_SHIFT 0
78
79#define BQ24190_REG_CTTC 0x05 /* Charge Term/Timer Control */
80#define BQ24190_REG_CTTC_EN_TERM_MASK BIT(7)
81#define BQ24190_REG_CTTC_EN_TERM_SHIFT 7
82#define BQ24190_REG_CTTC_TERM_STAT_MASK BIT(6)
83#define BQ24190_REG_CTTC_TERM_STAT_SHIFT 6
84#define BQ24190_REG_CTTC_WATCHDOG_MASK (BIT(5) | BIT(4))
85#define BQ24190_REG_CTTC_WATCHDOG_SHIFT 4
86#define BQ24190_REG_CTTC_EN_TIMER_MASK BIT(3)
87#define BQ24190_REG_CTTC_EN_TIMER_SHIFT 3
88#define BQ24190_REG_CTTC_CHG_TIMER_MASK (BIT(2) | BIT(1))
89#define BQ24190_REG_CTTC_CHG_TIMER_SHIFT 1
90#define BQ24190_REG_CTTC_JEITA_ISET_MASK BIT(0)
91#define BQ24190_REG_CTTC_JEITA_ISET_SHIFT 0
92
93#define BQ24190_REG_ICTRC 0x06 /* IR Comp/Thermal Regulation Control */
94#define BQ24190_REG_ICTRC_BAT_COMP_MASK (BIT(7) | BIT(6) | BIT(5))
95#define BQ24190_REG_ICTRC_BAT_COMP_SHIFT 5
96#define BQ24190_REG_ICTRC_VCLAMP_MASK (BIT(4) | BIT(3) | BIT(2))
97#define BQ24190_REG_ICTRC_VCLAMP_SHIFT 2
98#define BQ24190_REG_ICTRC_TREG_MASK (BIT(1) | BIT(0))
99#define BQ24190_REG_ICTRC_TREG_SHIFT 0
100
101#define BQ24190_REG_MOC 0x07 /* Misc. Operation Control */
102#define BQ24190_REG_MOC_DPDM_EN_MASK BIT(7)
103#define BQ24190_REG_MOC_DPDM_EN_SHIFT 7
104#define BQ24190_REG_MOC_TMR2X_EN_MASK BIT(6)
105#define BQ24190_REG_MOC_TMR2X_EN_SHIFT 6
106#define BQ24190_REG_MOC_BATFET_DISABLE_MASK BIT(5)
107#define BQ24190_REG_MOC_BATFET_DISABLE_SHIFT 5
108#define BQ24190_REG_MOC_JEITA_VSET_MASK BIT(4)
109#define BQ24190_REG_MOC_JEITA_VSET_SHIFT 4
110#define BQ24190_REG_MOC_INT_MASK_MASK (BIT(1) | BIT(0))
111#define BQ24190_REG_MOC_INT_MASK_SHIFT 0
112
113#define BQ24190_REG_SS 0x08 /* System Status */
114#define BQ24190_REG_SS_VBUS_STAT_MASK (BIT(7) | BIT(6))
115#define BQ24190_REG_SS_VBUS_STAT_SHIFT 6
116#define BQ24190_REG_SS_CHRG_STAT_MASK (BIT(5) | BIT(4))
117#define BQ24190_REG_SS_CHRG_STAT_SHIFT 4
118#define BQ24190_REG_SS_DPM_STAT_MASK BIT(3)
119#define BQ24190_REG_SS_DPM_STAT_SHIFT 3
120#define BQ24190_REG_SS_PG_STAT_MASK BIT(2)
121#define BQ24190_REG_SS_PG_STAT_SHIFT 2
122#define BQ24190_REG_SS_THERM_STAT_MASK BIT(1)
123#define BQ24190_REG_SS_THERM_STAT_SHIFT 1
124#define BQ24190_REG_SS_VSYS_STAT_MASK BIT(0)
125#define BQ24190_REG_SS_VSYS_STAT_SHIFT 0
126
127#define BQ24190_REG_F 0x09 /* Fault */
128#define BQ24190_REG_F_WATCHDOG_FAULT_MASK BIT(7)
129#define BQ24190_REG_F_WATCHDOG_FAULT_SHIFT 7
130#define BQ24190_REG_F_BOOST_FAULT_MASK BIT(6)
131#define BQ24190_REG_F_BOOST_FAULT_SHIFT 6
132#define BQ24190_REG_F_CHRG_FAULT_MASK (BIT(5) | BIT(4))
133#define BQ24190_REG_F_CHRG_FAULT_SHIFT 4
134#define BQ24190_REG_F_BAT_FAULT_MASK BIT(3)
135#define BQ24190_REG_F_BAT_FAULT_SHIFT 3
136#define BQ24190_REG_F_NTC_FAULT_MASK (BIT(2) | BIT(1) | BIT(0))
137#define BQ24190_REG_F_NTC_FAULT_SHIFT 0
138
139#define BQ24190_REG_VPRS 0x0A /* Vendor/Part/Revision Status */
140#define BQ24190_REG_VPRS_PN_MASK (BIT(5) | BIT(4) | BIT(3))
141#define BQ24190_REG_VPRS_PN_SHIFT 3
142#define BQ24190_REG_VPRS_PN_24190 0x4
d0717d73 143#define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193, 24196 */
d7bf353f
MG
144#define BQ24190_REG_VPRS_PN_24192I 0x3
145#define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2)
146#define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2
147#define BQ24190_REG_VPRS_DEV_REG_MASK (BIT(1) | BIT(0))
148#define BQ24190_REG_VPRS_DEV_REG_SHIFT 0
149
150/*
151 * The FAULT register is latched by the bq24190 (except for NTC_FAULT)
152 * so the first read after a fault returns the latched value and subsequent
153 * reads return the current value. In order to return the fault status
154 * to the user, have the interrupt handler save the reg's value and retrieve
68abfb80 155 * it in the appropriate health/status routine.
d7bf353f
MG
156 */
157struct bq24190_dev_info {
158 struct i2c_client *client;
159 struct device *dev;
161a2135 160 struct extcon_dev *edev;
297d716f
KK
161 struct power_supply *charger;
162 struct power_supply *battery;
18f8e6f6 163 struct delayed_work input_current_limit_work;
d7bf353f 164 char model_name[I2C_NAME_SIZE];
35c3c196
TL
165 bool initialized;
166 bool irq_event;
8412a5be 167 u16 sys_min;
14e1a131
LB
168 u16 iprechg;
169 u16 iterm;
d7bf353f 170 struct mutex f_reg_lock;
d7bf353f
MG
171 u8 f_reg;
172 u8 ss_reg;
173 u8 watchdog;
174};
175
161a2135
BM
176static const unsigned int bq24190_usb_extcon_cable[] = {
177 EXTCON_USB,
178 EXTCON_NONE,
179};
180
d7bf353f
MG
181/*
182 * The tables below provide a 2-way mapping for the value that goes in
183 * the register field and the real-world value that it represents.
184 * The index of the array is the value that goes in the register; the
185 * number at that index in the array is the real-world value that it
186 * represents.
187 */
da26580f
HG
188
189/* REG00[2:0] (IINLIM) in uAh */
03add17f
LB
190static const int bq24190_isc_iinlim_values[] = {
191 100000, 150000, 500000, 900000, 1200000, 1500000, 2000000, 3000000
192};
da26580f 193
d7bf353f
MG
194/* REG02[7:2] (ICHG) in uAh */
195static const int bq24190_ccc_ichg_values[] = {
196 512000, 576000, 640000, 704000, 768000, 832000, 896000, 960000,
197 1024000, 1088000, 1152000, 1216000, 1280000, 1344000, 1408000, 1472000,
198 1536000, 1600000, 1664000, 1728000, 1792000, 1856000, 1920000, 1984000,
199 2048000, 2112000, 2176000, 2240000, 2304000, 2368000, 2432000, 2496000,
200 2560000, 2624000, 2688000, 2752000, 2816000, 2880000, 2944000, 3008000,
201 3072000, 3136000, 3200000, 3264000, 3328000, 3392000, 3456000, 3520000,
202 3584000, 3648000, 3712000, 3776000, 3840000, 3904000, 3968000, 4032000,
203 4096000, 4160000, 4224000, 4288000, 4352000, 4416000, 4480000, 4544000
204};
205
206/* REG04[7:2] (VREG) in uV */
207static const int bq24190_cvc_vreg_values[] = {
208 3504000, 3520000, 3536000, 3552000, 3568000, 3584000, 3600000, 3616000,
209 3632000, 3648000, 3664000, 3680000, 3696000, 3712000, 3728000, 3744000,
210 3760000, 3776000, 3792000, 3808000, 3824000, 3840000, 3856000, 3872000,
211 3888000, 3904000, 3920000, 3936000, 3952000, 3968000, 3984000, 4000000,
212 4016000, 4032000, 4048000, 4064000, 4080000, 4096000, 4112000, 4128000,
213 4144000, 4160000, 4176000, 4192000, 4208000, 4224000, 4240000, 4256000,
214 4272000, 4288000, 4304000, 4320000, 4336000, 4352000, 4368000, 4384000,
215 4400000
216};
217
c56ca24a 218/* REG06[1:0] (TREG) in tenths of degrees Celsius */
d7bf353f
MG
219static const int bq24190_ictrc_treg_values[] = {
220 600, 800, 1000, 1200
221};
222
223/*
224 * Return the index in 'tbl' of greatest value that is less than or equal to
225 * 'val'. The index range returned is 0 to 'tbl_size' - 1. Assumes that
226 * the values in 'tbl' are sorted from smallest to largest and 'tbl_size'
227 * is less than 2^8.
228 */
229static u8 bq24190_find_idx(const int tbl[], int tbl_size, int v)
230{
231 int i;
232
233 for (i = 1; i < tbl_size; i++)
234 if (v < tbl[i])
235 break;
236
237 return i - 1;
238}
239
240/* Basic driver I/O routines */
241
242static int bq24190_read(struct bq24190_dev_info *bdi, u8 reg, u8 *data)
243{
244 int ret;
245
246 ret = i2c_smbus_read_byte_data(bdi->client, reg);
247 if (ret < 0)
248 return ret;
249
250 *data = ret;
251 return 0;
252}
253
254static int bq24190_write(struct bq24190_dev_info *bdi, u8 reg, u8 data)
255{
256 return i2c_smbus_write_byte_data(bdi->client, reg, data);
257}
258
259static int bq24190_read_mask(struct bq24190_dev_info *bdi, u8 reg,
260 u8 mask, u8 shift, u8 *data)
261{
262 u8 v;
263 int ret;
264
265 ret = bq24190_read(bdi, reg, &v);
266 if (ret < 0)
267 return ret;
268
269 v &= mask;
270 v >>= shift;
271 *data = v;
272
273 return 0;
274}
275
276static int bq24190_write_mask(struct bq24190_dev_info *bdi, u8 reg,
277 u8 mask, u8 shift, u8 data)
278{
279 u8 v;
280 int ret;
281
282 ret = bq24190_read(bdi, reg, &v);
283 if (ret < 0)
284 return ret;
285
286 v &= ~mask;
287 v |= ((data << shift) & mask);
288
289 return bq24190_write(bdi, reg, v);
290}
291
292static int bq24190_get_field_val(struct bq24190_dev_info *bdi,
293 u8 reg, u8 mask, u8 shift,
294 const int tbl[], int tbl_size,
295 int *val)
296{
297 u8 v;
298 int ret;
299
300 ret = bq24190_read_mask(bdi, reg, mask, shift, &v);
301 if (ret < 0)
302 return ret;
303
304 v = (v >= tbl_size) ? (tbl_size - 1) : v;
305 *val = tbl[v];
306
307 return 0;
308}
309
310static int bq24190_set_field_val(struct bq24190_dev_info *bdi,
311 u8 reg, u8 mask, u8 shift,
312 const int tbl[], int tbl_size,
313 int val)
314{
315 u8 idx;
316
317 idx = bq24190_find_idx(tbl, tbl_size, val);
318
319 return bq24190_write_mask(bdi, reg, mask, shift, idx);
320}
321
322#ifdef CONFIG_SYSFS
323/*
324 * There are a numerous options that are configurable on the bq24190
325 * that go well beyond what the power_supply properties provide access to.
326 * Provide sysfs access to them so they can be examined and possibly modified
327 * on the fly. They will be provided for the charger power_supply object only
328 * and will be prefixed by 'f_' to make them easier to recognize.
329 */
330
331#define BQ24190_SYSFS_FIELD(_name, r, f, m, store) \
332{ \
333 .attr = __ATTR(f_##_name, m, bq24190_sysfs_show, store), \
334 .reg = BQ24190_REG_##r, \
335 .mask = BQ24190_REG_##r##_##f##_MASK, \
336 .shift = BQ24190_REG_##r##_##f##_SHIFT, \
337}
338
339#define BQ24190_SYSFS_FIELD_RW(_name, r, f) \
340 BQ24190_SYSFS_FIELD(_name, r, f, S_IWUSR | S_IRUGO, \
341 bq24190_sysfs_store)
342
343#define BQ24190_SYSFS_FIELD_RO(_name, r, f) \
344 BQ24190_SYSFS_FIELD(_name, r, f, S_IRUGO, NULL)
345
346static ssize_t bq24190_sysfs_show(struct device *dev,
347 struct device_attribute *attr, char *buf);
348static ssize_t bq24190_sysfs_store(struct device *dev,
349 struct device_attribute *attr, const char *buf, size_t count);
350
351struct bq24190_sysfs_field_info {
352 struct device_attribute attr;
353 u8 reg;
354 u8 mask;
355 u8 shift;
356};
357
d24fed39
AV
358/* On i386 ptrace-abi.h defines SS that breaks the macro calls below. */
359#undef SS
360
d7bf353f
MG
361static struct bq24190_sysfs_field_info bq24190_sysfs_field_tbl[] = {
362 /* sysfs name reg field in reg */
363 BQ24190_SYSFS_FIELD_RW(en_hiz, ISC, EN_HIZ),
364 BQ24190_SYSFS_FIELD_RW(vindpm, ISC, VINDPM),
365 BQ24190_SYSFS_FIELD_RW(iinlim, ISC, IINLIM),
366 BQ24190_SYSFS_FIELD_RW(chg_config, POC, CHG_CONFIG),
367 BQ24190_SYSFS_FIELD_RW(sys_min, POC, SYS_MIN),
368 BQ24190_SYSFS_FIELD_RW(boost_lim, POC, BOOST_LIM),
369 BQ24190_SYSFS_FIELD_RW(ichg, CCC, ICHG),
370 BQ24190_SYSFS_FIELD_RW(force_20_pct, CCC, FORCE_20PCT),
371 BQ24190_SYSFS_FIELD_RW(iprechg, PCTCC, IPRECHG),
372 BQ24190_SYSFS_FIELD_RW(iterm, PCTCC, ITERM),
373 BQ24190_SYSFS_FIELD_RW(vreg, CVC, VREG),
374 BQ24190_SYSFS_FIELD_RW(batlowv, CVC, BATLOWV),
375 BQ24190_SYSFS_FIELD_RW(vrechg, CVC, VRECHG),
376 BQ24190_SYSFS_FIELD_RW(en_term, CTTC, EN_TERM),
377 BQ24190_SYSFS_FIELD_RW(term_stat, CTTC, TERM_STAT),
378 BQ24190_SYSFS_FIELD_RO(watchdog, CTTC, WATCHDOG),
379 BQ24190_SYSFS_FIELD_RW(en_timer, CTTC, EN_TIMER),
380 BQ24190_SYSFS_FIELD_RW(chg_timer, CTTC, CHG_TIMER),
381 BQ24190_SYSFS_FIELD_RW(jeta_iset, CTTC, JEITA_ISET),
382 BQ24190_SYSFS_FIELD_RW(bat_comp, ICTRC, BAT_COMP),
383 BQ24190_SYSFS_FIELD_RW(vclamp, ICTRC, VCLAMP),
384 BQ24190_SYSFS_FIELD_RW(treg, ICTRC, TREG),
385 BQ24190_SYSFS_FIELD_RW(dpdm_en, MOC, DPDM_EN),
386 BQ24190_SYSFS_FIELD_RW(tmr2x_en, MOC, TMR2X_EN),
387 BQ24190_SYSFS_FIELD_RW(batfet_disable, MOC, BATFET_DISABLE),
388 BQ24190_SYSFS_FIELD_RW(jeita_vset, MOC, JEITA_VSET),
389 BQ24190_SYSFS_FIELD_RO(int_mask, MOC, INT_MASK),
390 BQ24190_SYSFS_FIELD_RO(vbus_stat, SS, VBUS_STAT),
391 BQ24190_SYSFS_FIELD_RO(chrg_stat, SS, CHRG_STAT),
392 BQ24190_SYSFS_FIELD_RO(dpm_stat, SS, DPM_STAT),
393 BQ24190_SYSFS_FIELD_RO(pg_stat, SS, PG_STAT),
394 BQ24190_SYSFS_FIELD_RO(therm_stat, SS, THERM_STAT),
395 BQ24190_SYSFS_FIELD_RO(vsys_stat, SS, VSYS_STAT),
396 BQ24190_SYSFS_FIELD_RO(watchdog_fault, F, WATCHDOG_FAULT),
397 BQ24190_SYSFS_FIELD_RO(boost_fault, F, BOOST_FAULT),
398 BQ24190_SYSFS_FIELD_RO(chrg_fault, F, CHRG_FAULT),
399 BQ24190_SYSFS_FIELD_RO(bat_fault, F, BAT_FAULT),
400 BQ24190_SYSFS_FIELD_RO(ntc_fault, F, NTC_FAULT),
401 BQ24190_SYSFS_FIELD_RO(pn, VPRS, PN),
402 BQ24190_SYSFS_FIELD_RO(ts_profile, VPRS, TS_PROFILE),
403 BQ24190_SYSFS_FIELD_RO(dev_reg, VPRS, DEV_REG),
404};
405
406static struct attribute *
407 bq24190_sysfs_attrs[ARRAY_SIZE(bq24190_sysfs_field_tbl) + 1];
408
348a3c07 409ATTRIBUTE_GROUPS(bq24190_sysfs);
d7bf353f
MG
410
411static void bq24190_sysfs_init_attrs(void)
412{
413 int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);
414
415 for (i = 0; i < limit; i++)
416 bq24190_sysfs_attrs[i] = &bq24190_sysfs_field_tbl[i].attr.attr;
417
418 bq24190_sysfs_attrs[limit] = NULL; /* Has additional entry for this */
419}
420
421static struct bq24190_sysfs_field_info *bq24190_sysfs_field_lookup(
422 const char *name)
423{
424 int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);
425
426 for (i = 0; i < limit; i++)
427 if (!strcmp(name, bq24190_sysfs_field_tbl[i].attr.attr.name))
428 break;
429
430 if (i >= limit)
431 return NULL;
432
433 return &bq24190_sysfs_field_tbl[i];
434}
435
436static ssize_t bq24190_sysfs_show(struct device *dev,
437 struct device_attribute *attr, char *buf)
438{
439 struct power_supply *psy = dev_get_drvdata(dev);
297d716f 440 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
d7bf353f 441 struct bq24190_sysfs_field_info *info;
f385e6e2 442 ssize_t count;
d7bf353f
MG
443 int ret;
444 u8 v;
445
446 info = bq24190_sysfs_field_lookup(attr->attr.name);
447 if (!info)
448 return -EINVAL;
449
f385e6e2
TL
450 ret = pm_runtime_get_sync(bdi->dev);
451 if (ret < 0)
452 return ret;
453
d7bf353f
MG
454 ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);
455 if (ret)
f385e6e2
TL
456 count = ret;
457 else
458 count = scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
d7bf353f 459
f385e6e2
TL
460 pm_runtime_mark_last_busy(bdi->dev);
461 pm_runtime_put_autosuspend(bdi->dev);
462
463 return count;
d7bf353f
MG
464}
465
466static ssize_t bq24190_sysfs_store(struct device *dev,
467 struct device_attribute *attr, const char *buf, size_t count)
468{
469 struct power_supply *psy = dev_get_drvdata(dev);
297d716f 470 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
d7bf353f
MG
471 struct bq24190_sysfs_field_info *info;
472 int ret;
473 u8 v;
474
475 info = bq24190_sysfs_field_lookup(attr->attr.name);
476 if (!info)
477 return -EINVAL;
478
479 ret = kstrtou8(buf, 0, &v);
480 if (ret < 0)
481 return ret;
482
f385e6e2
TL
483 ret = pm_runtime_get_sync(bdi->dev);
484 if (ret < 0)
485 return ret;
486
d7bf353f
MG
487 ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);
488 if (ret)
f385e6e2
TL
489 count = ret;
490
491 pm_runtime_mark_last_busy(bdi->dev);
492 pm_runtime_put_autosuspend(bdi->dev);
d7bf353f
MG
493
494 return count;
495}
d7bf353f
MG
496#endif
497
66b6bef2
HG
498#ifdef CONFIG_REGULATOR
499static int bq24190_set_charge_mode(struct regulator_dev *dev, u8 val)
500{
501 struct bq24190_dev_info *bdi = rdev_get_drvdata(dev);
502 int ret;
503
504 ret = pm_runtime_get_sync(bdi->dev);
505 if (ret < 0) {
506 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);
507 pm_runtime_put_noidle(bdi->dev);
508 return ret;
509 }
510
511 ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
512 BQ24190_REG_POC_CHG_CONFIG_MASK,
513 BQ24190_REG_POC_CHG_CONFIG_SHIFT, val);
514
515 pm_runtime_mark_last_busy(bdi->dev);
516 pm_runtime_put_autosuspend(bdi->dev);
517
518 return ret;
519}
520
521static int bq24190_vbus_enable(struct regulator_dev *dev)
522{
523 return bq24190_set_charge_mode(dev, BQ24190_REG_POC_CHG_CONFIG_OTG);
524}
525
526static int bq24190_vbus_disable(struct regulator_dev *dev)
527{
528 return bq24190_set_charge_mode(dev, BQ24190_REG_POC_CHG_CONFIG_CHARGE);
529}
530
531static int bq24190_vbus_is_enabled(struct regulator_dev *dev)
532{
533 struct bq24190_dev_info *bdi = rdev_get_drvdata(dev);
534 int ret;
535 u8 val;
536
537 ret = pm_runtime_get_sync(bdi->dev);
538 if (ret < 0) {
539 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);
540 pm_runtime_put_noidle(bdi->dev);
541 return ret;
542 }
543
544 ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
545 BQ24190_REG_POC_CHG_CONFIG_MASK,
546 BQ24190_REG_POC_CHG_CONFIG_SHIFT, &val);
547
548 pm_runtime_mark_last_busy(bdi->dev);
549 pm_runtime_put_autosuspend(bdi->dev);
550
551 return ret ? ret : val == BQ24190_REG_POC_CHG_CONFIG_OTG;
552}
553
554static const struct regulator_ops bq24190_vbus_ops = {
555 .enable = bq24190_vbus_enable,
556 .disable = bq24190_vbus_disable,
557 .is_enabled = bq24190_vbus_is_enabled,
558};
559
560static const struct regulator_desc bq24190_vbus_desc = {
561 .name = "usb_otg_vbus",
74d09c92 562 .of_match = "usb-otg-vbus",
66b6bef2
HG
563 .type = REGULATOR_VOLTAGE,
564 .owner = THIS_MODULE,
565 .ops = &bq24190_vbus_ops,
566 .fixed_uV = 5000000,
567 .n_voltages = 1,
568};
569
570static const struct regulator_init_data bq24190_vbus_init_data = {
571 .constraints = {
572 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
573 },
574};
575
576static int bq24190_register_vbus_regulator(struct bq24190_dev_info *bdi)
577{
578 struct bq24190_platform_data *pdata = bdi->dev->platform_data;
579 struct regulator_config cfg = { };
580 struct regulator_dev *reg;
581 int ret = 0;
582
583 cfg.dev = bdi->dev;
584 if (pdata && pdata->regulator_init_data)
585 cfg.init_data = pdata->regulator_init_data;
586 else
587 cfg.init_data = &bq24190_vbus_init_data;
588 cfg.driver_data = bdi;
589 reg = devm_regulator_register(bdi->dev, &bq24190_vbus_desc, &cfg);
590 if (IS_ERR(reg)) {
591 ret = PTR_ERR(reg);
592 dev_err(bdi->dev, "Can't register regulator: %d\n", ret);
593 }
594
595 return ret;
596}
597#else
598static int bq24190_register_vbus_regulator(struct bq24190_dev_info *bdi)
599{
600 return 0;
601}
602#endif
603
a4c7590b 604static int bq24190_set_config(struct bq24190_dev_info *bdi)
d7bf353f
MG
605{
606 int ret;
607 u8 v;
608
609 ret = bq24190_read(bdi, BQ24190_REG_CTTC, &v);
610 if (ret < 0)
611 return ret;
612
613 bdi->watchdog = ((v & BQ24190_REG_CTTC_WATCHDOG_MASK) >>
614 BQ24190_REG_CTTC_WATCHDOG_SHIFT);
a4c7590b
LB
615
616 /*
617 * According to the "Host Mode and default Mode" section of the
618 * manual, a write to any register causes the bq24190 to switch
619 * from default mode to host mode. It will switch back to default
620 * mode after a WDT timeout unless the WDT is turned off as well.
621 * So, by simply turning off the WDT, we accomplish both with the
622 * same write.
623 */
d7bf353f
MG
624 v &= ~BQ24190_REG_CTTC_WATCHDOG_MASK;
625
a4c7590b
LB
626 ret = bq24190_write(bdi, BQ24190_REG_CTTC, v);
627 if (ret < 0)
628 return ret;
629
8412a5be
LB
630 if (bdi->sys_min) {
631 v = bdi->sys_min / 100 - 30; // manual section 9.5.1.2, table 9
632 ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
633 BQ24190_REG_POC_SYS_MIN_MASK,
634 BQ24190_REG_POC_SYS_MIN_SHIFT,
635 v);
636 if (ret < 0)
637 return ret;
638 }
639
14e1a131
LB
640 if (bdi->iprechg) {
641 v = bdi->iprechg / 128 - 1; // manual section 9.5.1.4, table 11
642 ret = bq24190_write_mask(bdi, BQ24190_REG_PCTCC,
643 BQ24190_REG_PCTCC_IPRECHG_MASK,
644 BQ24190_REG_PCTCC_IPRECHG_SHIFT,
645 v);
646 if (ret < 0)
647 return ret;
648 }
649
650 if (bdi->iterm) {
651 v = bdi->iterm / 128 - 1; // manual section 9.5.1.4, table 11
652 ret = bq24190_write_mask(bdi, BQ24190_REG_PCTCC,
653 BQ24190_REG_PCTCC_ITERM_MASK,
654 BQ24190_REG_PCTCC_ITERM_SHIFT,
655 v);
656 if (ret < 0)
657 return ret;
658 }
659
a4c7590b 660 return 0;
d7bf353f
MG
661}
662
663static int bq24190_register_reset(struct bq24190_dev_info *bdi)
664{
665 int ret, limit = 100;
666 u8 v;
667
d1600275
HG
668 /*
669 * This prop. can be passed on device instantiation from platform code:
670 * struct property_entry pe[] =
671 * { PROPERTY_ENTRY_BOOL("disable-reset"), ... };
672 * struct i2c_board_info bi =
673 * { .type = "bq24190", .addr = 0x6b, .properties = pe, .irq = irq };
674 * struct i2c_adapter ad = { ... };
675 * i2c_add_adapter(&ad);
676 * i2c_new_device(&ad, &bi);
677 */
6cf62a3b
HG
678 if (device_property_read_bool(bdi->dev, "disable-reset"))
679 return 0;
680
d7bf353f
MG
681 /* Reset the registers */
682 ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
683 BQ24190_REG_POC_RESET_MASK,
684 BQ24190_REG_POC_RESET_SHIFT,
685 0x1);
686 if (ret < 0)
687 return ret;
688
689 /* Reset bit will be cleared by hardware so poll until it is */
690 do {
691 ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
692 BQ24190_REG_POC_RESET_MASK,
693 BQ24190_REG_POC_RESET_SHIFT,
694 &v);
695 if (ret < 0)
696 return ret;
697
61489b0f
LB
698 if (v == 0)
699 return 0;
d7bf353f 700
61489b0f 701 usleep_range(100, 200);
d7bf353f
MG
702 } while (--limit);
703
61489b0f 704 return -EIO;
d7bf353f
MG
705}
706
707/* Charger power supply property routines */
708
709static int bq24190_charger_get_charge_type(struct bq24190_dev_info *bdi,
710 union power_supply_propval *val)
711{
712 u8 v;
713 int type, ret;
714
715 ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
716 BQ24190_REG_POC_CHG_CONFIG_MASK,
717 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
718 &v);
719 if (ret < 0)
720 return ret;
721
722 /* If POC[CHG_CONFIG] (REG01[5:4]) == 0, charge is disabled */
723 if (!v) {
724 type = POWER_SUPPLY_CHARGE_TYPE_NONE;
725 } else {
726 ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
727 BQ24190_REG_CCC_FORCE_20PCT_MASK,
728 BQ24190_REG_CCC_FORCE_20PCT_SHIFT,
729 &v);
730 if (ret < 0)
731 return ret;
732
733 type = (v) ? POWER_SUPPLY_CHARGE_TYPE_TRICKLE :
734 POWER_SUPPLY_CHARGE_TYPE_FAST;
735 }
736
737 val->intval = type;
738
739 return 0;
740}
741
742static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,
743 const union power_supply_propval *val)
744{
745 u8 chg_config, force_20pct, en_term;
746 int ret;
747
748 /*
749 * According to the "Termination when REG02[0] = 1" section of
750 * the bq24190 manual, the trickle charge could be less than the
751 * termination current so it recommends turning off the termination
752 * function.
753 *
754 * Note: AFAICT from the datasheet, the user will have to manually
755 * turn off the charging when in 20% mode. If its not turned off,
756 * there could be battery damage. So, use this mode at your own risk.
757 */
758 switch (val->intval) {
759 case POWER_SUPPLY_CHARGE_TYPE_NONE:
760 chg_config = 0x0;
761 break;
762 case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
763 chg_config = 0x1;
764 force_20pct = 0x1;
765 en_term = 0x0;
766 break;
767 case POWER_SUPPLY_CHARGE_TYPE_FAST:
768 chg_config = 0x1;
769 force_20pct = 0x0;
770 en_term = 0x1;
771 break;
772 default:
773 return -EINVAL;
774 }
775
776 if (chg_config) { /* Enabling the charger */
777 ret = bq24190_write_mask(bdi, BQ24190_REG_CCC,
778 BQ24190_REG_CCC_FORCE_20PCT_MASK,
779 BQ24190_REG_CCC_FORCE_20PCT_SHIFT,
780 force_20pct);
781 if (ret < 0)
782 return ret;
783
784 ret = bq24190_write_mask(bdi, BQ24190_REG_CTTC,
785 BQ24190_REG_CTTC_EN_TERM_MASK,
786 BQ24190_REG_CTTC_EN_TERM_SHIFT,
787 en_term);
788 if (ret < 0)
789 return ret;
790 }
791
792 return bq24190_write_mask(bdi, BQ24190_REG_POC,
793 BQ24190_REG_POC_CHG_CONFIG_MASK,
794 BQ24190_REG_POC_CHG_CONFIG_SHIFT, chg_config);
795}
796
797static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
798 union power_supply_propval *val)
799{
800 u8 v;
68abfb80 801 int health;
d7bf353f
MG
802
803 mutex_lock(&bdi->f_reg_lock);
68abfb80
LB
804 v = bdi->f_reg;
805 mutex_unlock(&bdi->f_reg_lock);
d7bf353f 806
1eb2869b
LB
807 if (v & BQ24190_REG_F_NTC_FAULT_MASK) {
808 switch (v >> BQ24190_REG_F_NTC_FAULT_SHIFT & 0x7) {
809 case 0x1: /* TS1 Cold */
810 case 0x3: /* TS2 Cold */
811 case 0x5: /* Both Cold */
812 health = POWER_SUPPLY_HEALTH_COLD;
d7bf353f 813 break;
1eb2869b
LB
814 case 0x2: /* TS1 Hot */
815 case 0x4: /* TS2 Hot */
816 case 0x6: /* Both Hot */
817 health = POWER_SUPPLY_HEALTH_OVERHEAT;
818 break;
819 default:
820 health = POWER_SUPPLY_HEALTH_UNKNOWN;
821 }
822 } else if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
823 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
824 } else if (v & BQ24190_REG_F_CHRG_FAULT_MASK) {
825 switch (v >> BQ24190_REG_F_CHRG_FAULT_SHIFT & 0x3) {
d7bf353f
MG
826 case 0x1: /* Input Fault (VBUS OVP or VBAT<VBUS<3.8V) */
827 /*
828 * This could be over-voltage or under-voltage
829 * and there's no way to tell which. Instead
830 * of looking foolish and returning 'OVERVOLTAGE'
831 * when its really under-voltage, just return
832 * 'UNSPEC_FAILURE'.
833 */
834 health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
835 break;
836 case 0x2: /* Thermal Shutdown */
837 health = POWER_SUPPLY_HEALTH_OVERHEAT;
838 break;
839 case 0x3: /* Charge Safety Timer Expiration */
840 health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
841 break;
1eb2869b
LB
842 default: /* prevent compiler warning */
843 health = -1;
d7bf353f 844 }
1eb2869b
LB
845 } else if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {
846 /*
847 * This could be over-current or over-voltage but there's
848 * no way to tell which. Return 'OVERVOLTAGE' since there
849 * isn't an 'OVERCURRENT' value defined that we can return
850 * even if it was over-current.
851 */
852 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
853 } else {
854 health = POWER_SUPPLY_HEALTH_GOOD;
d7bf353f
MG
855 }
856
857 val->intval = health;
858
859 return 0;
860}
861
862static int bq24190_charger_get_online(struct bq24190_dev_info *bdi,
863 union power_supply_propval *val)
864{
1eb2869b 865 u8 pg_stat, batfet_disable;
d7bf353f
MG
866 int ret;
867
868 ret = bq24190_read_mask(bdi, BQ24190_REG_SS,
869 BQ24190_REG_SS_PG_STAT_MASK,
1eb2869b 870 BQ24190_REG_SS_PG_STAT_SHIFT, &pg_stat);
d7bf353f
MG
871 if (ret < 0)
872 return ret;
873
1eb2869b
LB
874 ret = bq24190_read_mask(bdi, BQ24190_REG_MOC,
875 BQ24190_REG_MOC_BATFET_DISABLE_MASK,
876 BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, &batfet_disable);
877 if (ret < 0)
878 return ret;
879
880 val->intval = pg_stat && !batfet_disable;
881
d7bf353f
MG
882 return 0;
883}
884
1eb2869b
LB
885static int bq24190_battery_set_online(struct bq24190_dev_info *bdi,
886 const union power_supply_propval *val);
887static int bq24190_battery_get_status(struct bq24190_dev_info *bdi,
888 union power_supply_propval *val);
889static int bq24190_battery_get_temp_alert_max(struct bq24190_dev_info *bdi,
890 union power_supply_propval *val);
891static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,
892 const union power_supply_propval *val);
893
894static int bq24190_charger_set_online(struct bq24190_dev_info *bdi,
895 const union power_supply_propval *val)
896{
897 return bq24190_battery_set_online(bdi, val);
898}
899
900static int bq24190_charger_get_status(struct bq24190_dev_info *bdi,
901 union power_supply_propval *val)
902{
903 return bq24190_battery_get_status(bdi, val);
904}
905
906static int bq24190_charger_get_temp_alert_max(struct bq24190_dev_info *bdi,
907 union power_supply_propval *val)
908{
909 return bq24190_battery_get_temp_alert_max(bdi, val);
910}
911
912static int bq24190_charger_set_temp_alert_max(struct bq24190_dev_info *bdi,
913 const union power_supply_propval *val)
914{
915 return bq24190_battery_set_temp_alert_max(bdi, val);
916}
917
14e1a131
LB
918static int bq24190_charger_get_precharge(struct bq24190_dev_info *bdi,
919 union power_supply_propval *val)
920{
921 u8 v;
922 int ret;
923
924 ret = bq24190_read_mask(bdi, BQ24190_REG_PCTCC,
925 BQ24190_REG_PCTCC_IPRECHG_MASK,
926 BQ24190_REG_PCTCC_IPRECHG_SHIFT, &v);
927 if (ret < 0)
928 return ret;
929
930 val->intval = ++v * 128 * 1000;
931 return 0;
932}
933
934static int bq24190_charger_get_charge_term(struct bq24190_dev_info *bdi,
935 union power_supply_propval *val)
936{
937 u8 v;
938 int ret;
939
940 ret = bq24190_read_mask(bdi, BQ24190_REG_PCTCC,
941 BQ24190_REG_PCTCC_ITERM_MASK,
942 BQ24190_REG_PCTCC_ITERM_SHIFT, &v);
943 if (ret < 0)
944 return ret;
945
946 val->intval = ++v * 128 * 1000;
947 return 0;
948}
949
d7bf353f
MG
950static int bq24190_charger_get_current(struct bq24190_dev_info *bdi,
951 union power_supply_propval *val)
952{
953 u8 v;
954 int curr, ret;
955
956 ret = bq24190_get_field_val(bdi, BQ24190_REG_CCC,
957 BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
958 bq24190_ccc_ichg_values,
959 ARRAY_SIZE(bq24190_ccc_ichg_values), &curr);
960 if (ret < 0)
961 return ret;
962
963 ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
964 BQ24190_REG_CCC_FORCE_20PCT_MASK,
965 BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);
966 if (ret < 0)
967 return ret;
968
969 /* If FORCE_20PCT is enabled, then current is 20% of ICHG value */
970 if (v)
971 curr /= 5;
972
973 val->intval = curr;
974 return 0;
975}
976
977static int bq24190_charger_get_current_max(struct bq24190_dev_info *bdi,
978 union power_supply_propval *val)
979{
980 int idx = ARRAY_SIZE(bq24190_ccc_ichg_values) - 1;
981
982 val->intval = bq24190_ccc_ichg_values[idx];
983 return 0;
984}
985
986static int bq24190_charger_set_current(struct bq24190_dev_info *bdi,
987 const union power_supply_propval *val)
988{
989 u8 v;
990 int ret, curr = val->intval;
991
992 ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
993 BQ24190_REG_CCC_FORCE_20PCT_MASK,
994 BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);
995 if (ret < 0)
996 return ret;
997
998 /* If FORCE_20PCT is enabled, have to multiply value passed in by 5 */
999 if (v)
1000 curr *= 5;
1001
1002 return bq24190_set_field_val(bdi, BQ24190_REG_CCC,
1003 BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
1004 bq24190_ccc_ichg_values,
1005 ARRAY_SIZE(bq24190_ccc_ichg_values), curr);
1006}
1007
1008static int bq24190_charger_get_voltage(struct bq24190_dev_info *bdi,
1009 union power_supply_propval *val)
1010{
1011 int voltage, ret;
1012
1013 ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,
1014 BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
1015 bq24190_cvc_vreg_values,
1016 ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);
1017 if (ret < 0)
1018 return ret;
1019
1020 val->intval = voltage;
1021 return 0;
1022}
1023
1024static int bq24190_charger_get_voltage_max(struct bq24190_dev_info *bdi,
1025 union power_supply_propval *val)
1026{
1027 int idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1;
1028
1029 val->intval = bq24190_cvc_vreg_values[idx];
1030 return 0;
1031}
1032
1033static int bq24190_charger_set_voltage(struct bq24190_dev_info *bdi,
1034 const union power_supply_propval *val)
1035{
1036 return bq24190_set_field_val(bdi, BQ24190_REG_CVC,
1037 BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
1038 bq24190_cvc_vreg_values,
1039 ARRAY_SIZE(bq24190_cvc_vreg_values), val->intval);
1040}
1041
74229f93
HG
1042static int bq24190_charger_get_iinlimit(struct bq24190_dev_info *bdi,
1043 union power_supply_propval *val)
1044{
1045 int iinlimit, ret;
1046
1047 ret = bq24190_get_field_val(bdi, BQ24190_REG_ISC,
1048 BQ24190_REG_ISC_IINLIM_MASK,
1049 BQ24190_REG_ISC_IINLIM_SHIFT,
1050 bq24190_isc_iinlim_values,
1051 ARRAY_SIZE(bq24190_isc_iinlim_values), &iinlimit);
1052 if (ret < 0)
1053 return ret;
1054
1055 val->intval = iinlimit;
1056 return 0;
1057}
1058
1059static int bq24190_charger_set_iinlimit(struct bq24190_dev_info *bdi,
1060 const union power_supply_propval *val)
1061{
1062 return bq24190_set_field_val(bdi, BQ24190_REG_ISC,
1063 BQ24190_REG_ISC_IINLIM_MASK,
1064 BQ24190_REG_ISC_IINLIM_SHIFT,
1065 bq24190_isc_iinlim_values,
1066 ARRAY_SIZE(bq24190_isc_iinlim_values), val->intval);
1067}
1068
d7bf353f
MG
1069static int bq24190_charger_get_property(struct power_supply *psy,
1070 enum power_supply_property psp, union power_supply_propval *val)
1071{
297d716f 1072 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
d7bf353f
MG
1073 int ret;
1074
1075 dev_dbg(bdi->dev, "prop: %d\n", psp);
1076
f385e6e2
TL
1077 ret = pm_runtime_get_sync(bdi->dev);
1078 if (ret < 0)
1079 return ret;
d7bf353f
MG
1080
1081 switch (psp) {
1082 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1083 ret = bq24190_charger_get_charge_type(bdi, val);
1084 break;
1085 case POWER_SUPPLY_PROP_HEALTH:
1086 ret = bq24190_charger_get_health(bdi, val);
1087 break;
1088 case POWER_SUPPLY_PROP_ONLINE:
1089 ret = bq24190_charger_get_online(bdi, val);
1090 break;
1eb2869b
LB
1091 case POWER_SUPPLY_PROP_STATUS:
1092 ret = bq24190_charger_get_status(bdi, val);
1093 break;
1094 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1095 ret = bq24190_charger_get_temp_alert_max(bdi, val);
1096 break;
14e1a131
LB
1097 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
1098 ret = bq24190_charger_get_precharge(bdi, val);
1099 break;
1100 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
1101 ret = bq24190_charger_get_charge_term(bdi, val);
1102 break;
d7bf353f
MG
1103 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
1104 ret = bq24190_charger_get_current(bdi, val);
1105 break;
1106 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1107 ret = bq24190_charger_get_current_max(bdi, val);
1108 break;
1109 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
1110 ret = bq24190_charger_get_voltage(bdi, val);
1111 break;
1112 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
1113 ret = bq24190_charger_get_voltage_max(bdi, val);
1114 break;
74229f93
HG
1115 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
1116 ret = bq24190_charger_get_iinlimit(bdi, val);
1117 break;
d7bf353f
MG
1118 case POWER_SUPPLY_PROP_SCOPE:
1119 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
1120 ret = 0;
1121 break;
1122 case POWER_SUPPLY_PROP_MODEL_NAME:
1123 val->strval = bdi->model_name;
1124 ret = 0;
1125 break;
1126 case POWER_SUPPLY_PROP_MANUFACTURER:
1127 val->strval = BQ24190_MANUFACTURER;
1128 ret = 0;
1129 break;
1130 default:
1131 ret = -ENODATA;
1132 }
1133
f385e6e2
TL
1134 pm_runtime_mark_last_busy(bdi->dev);
1135 pm_runtime_put_autosuspend(bdi->dev);
1136
d7bf353f
MG
1137 return ret;
1138}
1139
1140static int bq24190_charger_set_property(struct power_supply *psy,
1141 enum power_supply_property psp,
1142 const union power_supply_propval *val)
1143{
297d716f 1144 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
d7bf353f
MG
1145 int ret;
1146
1147 dev_dbg(bdi->dev, "prop: %d\n", psp);
1148
f385e6e2
TL
1149 ret = pm_runtime_get_sync(bdi->dev);
1150 if (ret < 0)
1151 return ret;
d7bf353f
MG
1152
1153 switch (psp) {
1eb2869b
LB
1154 case POWER_SUPPLY_PROP_ONLINE:
1155 ret = bq24190_charger_set_online(bdi, val);
1156 break;
1157 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1158 ret = bq24190_charger_set_temp_alert_max(bdi, val);
1159 break;
d7bf353f
MG
1160 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1161 ret = bq24190_charger_set_charge_type(bdi, val);
1162 break;
1163 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
1164 ret = bq24190_charger_set_current(bdi, val);
1165 break;
1166 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
1167 ret = bq24190_charger_set_voltage(bdi, val);
1168 break;
74229f93
HG
1169 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
1170 ret = bq24190_charger_set_iinlimit(bdi, val);
1171 break;
d7bf353f
MG
1172 default:
1173 ret = -EINVAL;
1174 }
1175
f385e6e2
TL
1176 pm_runtime_mark_last_busy(bdi->dev);
1177 pm_runtime_put_autosuspend(bdi->dev);
1178
d7bf353f
MG
1179 return ret;
1180}
1181
1182static int bq24190_charger_property_is_writeable(struct power_supply *psy,
1183 enum power_supply_property psp)
1184{
d7bf353f 1185 switch (psp) {
1eb2869b
LB
1186 case POWER_SUPPLY_PROP_ONLINE:
1187 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
d7bf353f
MG
1188 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1189 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
1190 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
74229f93 1191 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
31381042 1192 return 1;
d7bf353f 1193 default:
31381042 1194 return 0;
d7bf353f 1195 }
d7bf353f
MG
1196}
1197
18f8e6f6
HG
1198static void bq24190_input_current_limit_work(struct work_struct *work)
1199{
1200 struct bq24190_dev_info *bdi =
1201 container_of(work, struct bq24190_dev_info,
1202 input_current_limit_work.work);
1203
1204 power_supply_set_input_current_limit_from_supplier(bdi->charger);
1205}
1206
1207/* Sync the input-current-limit with our parent supply (if we have one) */
1208static void bq24190_charger_external_power_changed(struct power_supply *psy)
1209{
1210 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
1211
1212 /*
1213 * The Power-Good detection may take up to 220ms, sometimes
1214 * the external charger detection is quicker, and the bq24190 will
1215 * reset to iinlim based on its own charger detection (which is not
1216 * hooked up when using external charger detection) resulting in a
1217 * too low default 500mA iinlim. Delay setting the input-current-limit
1218 * for 300ms to avoid this.
1219 */
1220 queue_delayed_work(system_wq, &bdi->input_current_limit_work,
1221 msecs_to_jiffies(300));
1222}
1223
d7bf353f 1224static enum power_supply_property bq24190_charger_properties[] = {
c9f85a90 1225 POWER_SUPPLY_PROP_CHARGE_TYPE,
d7bf353f
MG
1226 POWER_SUPPLY_PROP_HEALTH,
1227 POWER_SUPPLY_PROP_ONLINE,
1eb2869b
LB
1228 POWER_SUPPLY_PROP_STATUS,
1229 POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
14e1a131
LB
1230 POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
1231 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
d7bf353f
MG
1232 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
1233 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
1234 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
1235 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
74229f93 1236 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
d7bf353f
MG
1237 POWER_SUPPLY_PROP_SCOPE,
1238 POWER_SUPPLY_PROP_MODEL_NAME,
1239 POWER_SUPPLY_PROP_MANUFACTURER,
1240};
1241
1242static char *bq24190_charger_supplied_to[] = {
1243 "main-battery",
1244};
1245
297d716f
KK
1246static const struct power_supply_desc bq24190_charger_desc = {
1247 .name = "bq24190-charger",
1248 .type = POWER_SUPPLY_TYPE_USB,
1249 .properties = bq24190_charger_properties,
1250 .num_properties = ARRAY_SIZE(bq24190_charger_properties),
1251 .get_property = bq24190_charger_get_property,
1252 .set_property = bq24190_charger_set_property,
1253 .property_is_writeable = bq24190_charger_property_is_writeable,
18f8e6f6 1254 .external_power_changed = bq24190_charger_external_power_changed,
297d716f 1255};
d7bf353f
MG
1256
1257/* Battery power supply property routines */
1258
1259static int bq24190_battery_get_status(struct bq24190_dev_info *bdi,
1260 union power_supply_propval *val)
1261{
1262 u8 ss_reg, chrg_fault;
1263 int status, ret;
1264
1265 mutex_lock(&bdi->f_reg_lock);
68abfb80
LB
1266 chrg_fault = bdi->f_reg;
1267 mutex_unlock(&bdi->f_reg_lock);
d7bf353f
MG
1268
1269 chrg_fault &= BQ24190_REG_F_CHRG_FAULT_MASK;
1270 chrg_fault >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
1271
1272 ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);
1273 if (ret < 0)
1274 return ret;
1275
1276 /*
1277 * The battery must be discharging when any of these are true:
1278 * - there is no good power source;
1279 * - there is a charge fault.
1280 * Could also be discharging when in "supplement mode" but
1281 * there is no way to tell when its in that mode.
1282 */
1283 if (!(ss_reg & BQ24190_REG_SS_PG_STAT_MASK) || chrg_fault) {
1284 status = POWER_SUPPLY_STATUS_DISCHARGING;
1285 } else {
1286 ss_reg &= BQ24190_REG_SS_CHRG_STAT_MASK;
1287 ss_reg >>= BQ24190_REG_SS_CHRG_STAT_SHIFT;
1288
1289 switch (ss_reg) {
1290 case 0x0: /* Not Charging */
1291 status = POWER_SUPPLY_STATUS_NOT_CHARGING;
1292 break;
1293 case 0x1: /* Pre-charge */
1294 case 0x2: /* Fast Charging */
1295 status = POWER_SUPPLY_STATUS_CHARGING;
1296 break;
1297 case 0x3: /* Charge Termination Done */
1298 status = POWER_SUPPLY_STATUS_FULL;
1299 break;
1300 default:
1301 ret = -EIO;
1302 }
1303 }
1304
1305 if (!ret)
1306 val->intval = status;
1307
1308 return ret;
1309}
1310
1311static int bq24190_battery_get_health(struct bq24190_dev_info *bdi,
1312 union power_supply_propval *val)
1313{
1314 u8 v;
68abfb80 1315 int health;
d7bf353f
MG
1316
1317 mutex_lock(&bdi->f_reg_lock);
68abfb80
LB
1318 v = bdi->f_reg;
1319 mutex_unlock(&bdi->f_reg_lock);
d7bf353f
MG
1320
1321 if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
1322 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1323 } else {
1324 v &= BQ24190_REG_F_NTC_FAULT_MASK;
1325 v >>= BQ24190_REG_F_NTC_FAULT_SHIFT;
1326
1327 switch (v) {
1328 case 0x0: /* Normal */
1329 health = POWER_SUPPLY_HEALTH_GOOD;
1330 break;
1331 case 0x1: /* TS1 Cold */
1332 case 0x3: /* TS2 Cold */
1333 case 0x5: /* Both Cold */
1334 health = POWER_SUPPLY_HEALTH_COLD;
1335 break;
1336 case 0x2: /* TS1 Hot */
1337 case 0x4: /* TS2 Hot */
1338 case 0x6: /* Both Hot */
1339 health = POWER_SUPPLY_HEALTH_OVERHEAT;
1340 break;
1341 default:
1342 health = POWER_SUPPLY_HEALTH_UNKNOWN;
1343 }
1344 }
1345
1346 val->intval = health;
1347 return 0;
1348}
1349
1350static int bq24190_battery_get_online(struct bq24190_dev_info *bdi,
1351 union power_supply_propval *val)
1352{
1353 u8 batfet_disable;
1354 int ret;
1355
1356 ret = bq24190_read_mask(bdi, BQ24190_REG_MOC,
1357 BQ24190_REG_MOC_BATFET_DISABLE_MASK,
1358 BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, &batfet_disable);
1359 if (ret < 0)
1360 return ret;
1361
1362 val->intval = !batfet_disable;
1363 return 0;
1364}
1365
1366static int bq24190_battery_set_online(struct bq24190_dev_info *bdi,
1367 const union power_supply_propval *val)
1368{
1369 return bq24190_write_mask(bdi, BQ24190_REG_MOC,
1370 BQ24190_REG_MOC_BATFET_DISABLE_MASK,
1371 BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, !val->intval);
1372}
1373
1374static int bq24190_battery_get_temp_alert_max(struct bq24190_dev_info *bdi,
1375 union power_supply_propval *val)
1376{
1377 int temp, ret;
1378
1379 ret = bq24190_get_field_val(bdi, BQ24190_REG_ICTRC,
1380 BQ24190_REG_ICTRC_TREG_MASK,
1381 BQ24190_REG_ICTRC_TREG_SHIFT,
1382 bq24190_ictrc_treg_values,
1383 ARRAY_SIZE(bq24190_ictrc_treg_values), &temp);
1384 if (ret < 0)
1385 return ret;
1386
1387 val->intval = temp;
1388 return 0;
1389}
1390
1391static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,
1392 const union power_supply_propval *val)
1393{
1394 return bq24190_set_field_val(bdi, BQ24190_REG_ICTRC,
1395 BQ24190_REG_ICTRC_TREG_MASK,
1396 BQ24190_REG_ICTRC_TREG_SHIFT,
1397 bq24190_ictrc_treg_values,
1398 ARRAY_SIZE(bq24190_ictrc_treg_values), val->intval);
1399}
1400
1401static int bq24190_battery_get_property(struct power_supply *psy,
1402 enum power_supply_property psp, union power_supply_propval *val)
1403{
297d716f 1404 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
d7bf353f
MG
1405 int ret;
1406
1eb2869b 1407 dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");
d7bf353f
MG
1408 dev_dbg(bdi->dev, "prop: %d\n", psp);
1409
f385e6e2
TL
1410 ret = pm_runtime_get_sync(bdi->dev);
1411 if (ret < 0)
1412 return ret;
d7bf353f
MG
1413
1414 switch (psp) {
1415 case POWER_SUPPLY_PROP_STATUS:
1416 ret = bq24190_battery_get_status(bdi, val);
1417 break;
1418 case POWER_SUPPLY_PROP_HEALTH:
1419 ret = bq24190_battery_get_health(bdi, val);
1420 break;
1421 case POWER_SUPPLY_PROP_ONLINE:
1422 ret = bq24190_battery_get_online(bdi, val);
1423 break;
1424 case POWER_SUPPLY_PROP_TECHNOLOGY:
1425 /* Could be Li-on or Li-polymer but no way to tell which */
1426 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
1427 ret = 0;
1428 break;
1429 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1430 ret = bq24190_battery_get_temp_alert_max(bdi, val);
1431 break;
1432 case POWER_SUPPLY_PROP_SCOPE:
1433 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
1434 ret = 0;
1435 break;
1436 default:
1437 ret = -ENODATA;
1438 }
1439
f385e6e2
TL
1440 pm_runtime_mark_last_busy(bdi->dev);
1441 pm_runtime_put_autosuspend(bdi->dev);
1442
d7bf353f
MG
1443 return ret;
1444}
1445
1446static int bq24190_battery_set_property(struct power_supply *psy,
1447 enum power_supply_property psp,
1448 const union power_supply_propval *val)
1449{
297d716f 1450 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
d7bf353f
MG
1451 int ret;
1452
1eb2869b 1453 dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");
d7bf353f
MG
1454 dev_dbg(bdi->dev, "prop: %d\n", psp);
1455
f385e6e2
TL
1456 ret = pm_runtime_get_sync(bdi->dev);
1457 if (ret < 0)
1458 return ret;
d7bf353f
MG
1459
1460 switch (psp) {
1461 case POWER_SUPPLY_PROP_ONLINE:
1462 ret = bq24190_battery_set_online(bdi, val);
1463 break;
1464 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1465 ret = bq24190_battery_set_temp_alert_max(bdi, val);
1466 break;
1467 default:
1468 ret = -EINVAL;
1469 }
1470
f385e6e2
TL
1471 pm_runtime_mark_last_busy(bdi->dev);
1472 pm_runtime_put_autosuspend(bdi->dev);
1473
d7bf353f
MG
1474 return ret;
1475}
1476
1477static int bq24190_battery_property_is_writeable(struct power_supply *psy,
1478 enum power_supply_property psp)
1479{
1480 int ret;
1481
1482 switch (psp) {
1483 case POWER_SUPPLY_PROP_ONLINE:
1484 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1485 ret = 1;
1486 break;
1487 default:
1488 ret = 0;
1489 }
1490
1491 return ret;
1492}
1493
1494static enum power_supply_property bq24190_battery_properties[] = {
1495 POWER_SUPPLY_PROP_STATUS,
1496 POWER_SUPPLY_PROP_HEALTH,
1497 POWER_SUPPLY_PROP_ONLINE,
1498 POWER_SUPPLY_PROP_TECHNOLOGY,
1499 POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
1500 POWER_SUPPLY_PROP_SCOPE,
1501};
1502
297d716f
KK
1503static const struct power_supply_desc bq24190_battery_desc = {
1504 .name = "bq24190-battery",
1505 .type = POWER_SUPPLY_TYPE_BATTERY,
1506 .properties = bq24190_battery_properties,
1507 .num_properties = ARRAY_SIZE(bq24190_battery_properties),
1508 .get_property = bq24190_battery_get_property,
1509 .set_property = bq24190_battery_set_property,
1510 .property_is_writeable = bq24190_battery_property_is_writeable,
1511};
d7bf353f 1512
161a2135
BM
1513static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)
1514{
1515 bool otg_enabled;
1516 int ret;
1517
1518 otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK);
1519 ret = extcon_set_state_sync(bdi->edev, EXTCON_USB, otg_enabled);
1520 if (ret < 0)
1521 dev_err(bdi->dev, "Can't set extcon state to %d: %d\n",
1522 otg_enabled, ret);
1523
1524 return ret;
1525}
1526
35c3c196 1527static void bq24190_check_status(struct bq24190_dev_info *bdi)
d7bf353f 1528{
2d9fee6a
LB
1529 const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK;
1530 const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK
1531 | BQ24190_REG_F_NTC_FAULT_MASK;
1532 bool alert_charger = false, alert_battery = false;
31f50e48 1533 u8 ss_reg = 0, f_reg = 0;
68abfb80 1534 int i, ret;
d7bf353f 1535
d7bf353f
MG
1536 ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);
1537 if (ret < 0) {
1538 dev_err(bdi->dev, "Can't read SS reg: %d\n", ret);
35c3c196 1539 return;
d7bf353f
MG
1540 }
1541
68abfb80
LB
1542 i = 0;
1543 do {
1544 ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);
1545 if (ret < 0) {
1546 dev_err(bdi->dev, "Can't read F reg: %d\n", ret);
35c3c196 1547 return;
68abfb80
LB
1548 }
1549 } while (f_reg && ++i < 2);
d7bf353f 1550
d63d07c6
LB
1551 /* ignore over/under voltage fault after disconnect */
1552 if (f_reg == (1 << BQ24190_REG_F_CHRG_FAULT_SHIFT) &&
1553 !(ss_reg & BQ24190_REG_SS_PG_STAT_MASK))
1554 f_reg = 0;
1555
d7bf353f 1556 if (f_reg != bdi->f_reg) {
d63d07c6 1557 dev_warn(bdi->dev,
68abfb80
LB
1558 "Fault: boost %d, charge %d, battery %d, ntc %d\n",
1559 !!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK),
1560 !!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK),
1561 !!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK),
1562 !!(f_reg & BQ24190_REG_F_NTC_FAULT_MASK));
1563
1564 mutex_lock(&bdi->f_reg_lock);
2d9fee6a
LB
1565 if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f))
1566 alert_battery = true;
1567 if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f))
1568 alert_charger = true;
d7bf353f 1569 bdi->f_reg = f_reg;
68abfb80 1570 mutex_unlock(&bdi->f_reg_lock);
d7bf353f
MG
1571 }
1572
ba52e757
LB
1573 if (ss_reg != bdi->ss_reg) {
1574 /*
1575 * The device is in host mode so when PG_STAT goes from 1->0
1576 * (i.e., power removed) HIZ needs to be disabled.
1577 */
1578 if ((bdi->ss_reg & BQ24190_REG_SS_PG_STAT_MASK) &&
1579 !(ss_reg & BQ24190_REG_SS_PG_STAT_MASK)) {
1580 ret = bq24190_write_mask(bdi, BQ24190_REG_ISC,
1581 BQ24190_REG_ISC_EN_HIZ_MASK,
1582 BQ24190_REG_ISC_EN_HIZ_SHIFT,
1583 0);
1584 if (ret < 0)
1585 dev_err(bdi->dev, "Can't access ISC reg: %d\n",
1586 ret);
1587 }
1588
1589 if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss))
1590 alert_battery = true;
1591 if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss))
1592 alert_charger = true;
1593 bdi->ss_reg = ss_reg;
1594 }
1595
161a2135 1596 if (alert_charger || alert_battery) {
2d9fee6a 1597 power_supply_changed(bdi->charger);
161a2135
BM
1598 bq24190_configure_usb_otg(bdi, ss_reg);
1599 }
1eb2869b 1600 if (alert_battery && bdi->battery)
2d9fee6a 1601 power_supply_changed(bdi->battery);
d7bf353f 1602
d7bf353f 1603 dev_dbg(bdi->dev, "ss_reg: 0x%02x, f_reg: 0x%02x\n", ss_reg, f_reg);
35c3c196
TL
1604}
1605
1606static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
1607{
1608 struct bq24190_dev_info *bdi = data;
e3ebc381 1609 int error;
35c3c196
TL
1610
1611 bdi->irq_event = true;
e3ebc381
LB
1612 error = pm_runtime_get_sync(bdi->dev);
1613 if (error < 0) {
1614 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1615 pm_runtime_put_noidle(bdi->dev);
f385e6e2
TL
1616 return IRQ_NONE;
1617 }
35c3c196 1618 bq24190_check_status(bdi);
f385e6e2
TL
1619 pm_runtime_mark_last_busy(bdi->dev);
1620 pm_runtime_put_autosuspend(bdi->dev);
35c3c196 1621 bdi->irq_event = false;
d7bf353f
MG
1622
1623 return IRQ_HANDLED;
1624}
1625
1626static int bq24190_hw_init(struct bq24190_dev_info *bdi)
1627{
1628 u8 v;
1629 int ret;
1630
d7bf353f
MG
1631 /* First check that the device really is what its supposed to be */
1632 ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,
1633 BQ24190_REG_VPRS_PN_MASK,
1634 BQ24190_REG_VPRS_PN_SHIFT,
1635 &v);
1636 if (ret < 0)
f385e6e2 1637 return ret;
d7bf353f 1638
5ea67bb0
JM
1639 switch (v) {
1640 case BQ24190_REG_VPRS_PN_24190:
1641 case BQ24190_REG_VPRS_PN_24192:
1642 case BQ24190_REG_VPRS_PN_24192I:
1643 break;
1644 default:
99c88eb2 1645 dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
f385e6e2 1646 return -ENODEV;
99c88eb2 1647 }
d7bf353f
MG
1648
1649 ret = bq24190_register_reset(bdi);
1650 if (ret < 0)
f385e6e2 1651 return ret;
d7bf353f 1652
a4c7590b 1653 ret = bq24190_set_config(bdi);
2d9fee6a 1654 if (ret < 0)
f385e6e2 1655 return ret;
2d9fee6a 1656
f385e6e2 1657 return bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
d7bf353f
MG
1658}
1659
a4c7590b
LB
1660static int bq24190_get_config(struct bq24190_dev_info *bdi)
1661{
8412a5be 1662 const char * const s = "ti,system-minimum-microvolt";
14e1a131 1663 struct power_supply_battery_info info = {};
8412a5be
LB
1664 int v;
1665
1666 if (device_property_read_u32(bdi->dev, s, &v) == 0) {
1667 v /= 1000;
1668 if (v >= BQ24190_REG_POC_SYS_MIN_MIN
1669 && v <= BQ24190_REG_POC_SYS_MIN_MAX)
1670 bdi->sys_min = v;
1671 else
1672 dev_warn(bdi->dev, "invalid value for %s: %u\n", s, v);
1673 }
1674
14e1a131
LB
1675 if (bdi->dev->of_node &&
1676 !power_supply_get_battery_info(bdi->charger, &info)) {
1677 v = info.precharge_current_ua / 1000;
1678 if (v >= BQ24190_REG_PCTCC_IPRECHG_MIN
1679 && v <= BQ24190_REG_PCTCC_IPRECHG_MAX)
1680 bdi->iprechg = v;
1681 else
1682 dev_warn(bdi->dev, "invalid value for battery:precharge-current-microamp: %d\n",
1683 v);
1684
1685 v = info.charge_term_current_ua / 1000;
1686 if (v >= BQ24190_REG_PCTCC_ITERM_MIN
1687 && v <= BQ24190_REG_PCTCC_ITERM_MAX)
1688 bdi->iterm = v;
1689 else
1690 dev_warn(bdi->dev, "invalid value for battery:charge-term-current-microamp: %d\n",
1691 v);
1692 }
1693
a4c7590b
LB
1694 return 0;
1695}
1696
d7bf353f
MG
1697static int bq24190_probe(struct i2c_client *client,
1698 const struct i2c_device_id *id)
1699{
1700 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1701 struct device *dev = &client->dev;
297d716f 1702 struct power_supply_config charger_cfg = {}, battery_cfg = {};
d7bf353f
MG
1703 struct bq24190_dev_info *bdi;
1704 int ret;
1705
1706 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
1707 dev_err(dev, "No support for SMBUS_BYTE_DATA\n");
1708 return -ENODEV;
1709 }
1710
1711 bdi = devm_kzalloc(dev, sizeof(*bdi), GFP_KERNEL);
1712 if (!bdi) {
1713 dev_err(dev, "Can't alloc bdi struct\n");
1714 return -ENOMEM;
1715 }
1716
1717 bdi->client = client;
1718 bdi->dev = dev;
d7bf353f
MG
1719 strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
1720 mutex_init(&bdi->f_reg_lock);
2d9fee6a
LB
1721 bdi->f_reg = 0;
1722 bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
18f8e6f6
HG
1723 INIT_DELAYED_WORK(&bdi->input_current_limit_work,
1724 bq24190_input_current_limit_work);
d7bf353f
MG
1725
1726 i2c_set_clientdata(client, bdi);
1727
a4c7590b 1728 if (client->irq <= 0) {
d7bf353f
MG
1729 dev_err(dev, "Can't get irq info\n");
1730 return -EINVAL;
1731 }
1732
161a2135
BM
1733 bdi->edev = devm_extcon_dev_allocate(dev, bq24190_usb_extcon_cable);
1734 if (IS_ERR(bdi->edev))
1735 return PTR_ERR(bdi->edev);
1736
1737 ret = devm_extcon_dev_register(dev, bdi->edev);
1738 if (ret < 0)
1739 return ret;
1740
d7bf353f 1741 pm_runtime_enable(dev);
f385e6e2
TL
1742 pm_runtime_use_autosuspend(dev);
1743 pm_runtime_set_autosuspend_delay(dev, 600);
1744 ret = pm_runtime_get_sync(dev);
e3ebc381
LB
1745 if (ret < 0) {
1746 dev_err(dev, "pm_runtime_get failed: %i\n", ret);
1747 goto out_pmrt;
1748 }
d7bf353f 1749
348a3c07
SR
1750#ifdef CONFIG_SYSFS
1751 bq24190_sysfs_init_attrs();
1752 charger_cfg.attr_grp = bq24190_sysfs_groups;
1753#endif
1754
297d716f 1755 charger_cfg.drv_data = bdi;
14e1a131 1756 charger_cfg.of_node = dev->of_node;
297d716f
KK
1757 charger_cfg.supplied_to = bq24190_charger_supplied_to;
1758 charger_cfg.num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to),
1759 bdi->charger = power_supply_register(dev, &bq24190_charger_desc,
1760 &charger_cfg);
1761 if (IS_ERR(bdi->charger)) {
d7bf353f 1762 dev_err(dev, "Can't register charger\n");
297d716f 1763 ret = PTR_ERR(bdi->charger);
e3ebc381 1764 goto out_pmrt;
d7bf353f
MG
1765 }
1766
1eb2869b
LB
1767 /* the battery class is deprecated and will be removed. */
1768 /* in the interim, this property hides it. */
1769 if (!device_property_read_bool(dev, "omit-battery-class")) {
1770 battery_cfg.drv_data = bdi;
1771 bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
1772 &battery_cfg);
1773 if (IS_ERR(bdi->battery)) {
1774 dev_err(dev, "Can't register battery\n");
1775 ret = PTR_ERR(bdi->battery);
1776 goto out_charger;
1777 }
d7bf353f
MG
1778 }
1779
a4c7590b
LB
1780 ret = bq24190_get_config(bdi);
1781 if (ret < 0) {
1782 dev_err(dev, "Can't get devicetree config\n");
1783 goto out_charger;
1784 }
1785
1786 ret = bq24190_hw_init(bdi);
1787 if (ret < 0) {
1788 dev_err(dev, "Hardware init failed\n");
1789 goto out_charger;
1790 }
1791
161a2135
BM
1792 ret = bq24190_configure_usb_otg(bdi, bdi->ss_reg);
1793 if (ret < 0)
1794 goto out_charger;
1795
35c3c196
TL
1796 bdi->initialized = true;
1797
01c0e0a2 1798 ret = devm_request_threaded_irq(dev, client->irq, NULL,
d62acc5e
LB
1799 bq24190_irq_handler_thread,
1800 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
1801 "bq24190-charger", bdi);
1802 if (ret < 0) {
1803 dev_err(dev, "Can't set up irq handler\n");
348a3c07 1804 goto out_charger;
d7bf353f
MG
1805 }
1806
66b6bef2
HG
1807 ret = bq24190_register_vbus_regulator(bdi);
1808 if (ret < 0)
348a3c07 1809 goto out_charger;
66b6bef2 1810
01c0e0a2 1811 enable_irq_wake(client->irq);
f385e6e2
TL
1812
1813 pm_runtime_mark_last_busy(dev);
1814 pm_runtime_put_autosuspend(dev);
1815
d7bf353f
MG
1816 return 0;
1817
e3ebc381 1818out_charger:
1eb2869b
LB
1819 if (!IS_ERR_OR_NULL(bdi->battery))
1820 power_supply_unregister(bdi->battery);
d62acc5e 1821 power_supply_unregister(bdi->charger);
cb190af2 1822
e3ebc381 1823out_pmrt:
f385e6e2 1824 pm_runtime_put_sync(dev);
f385e6e2 1825 pm_runtime_dont_use_autosuspend(dev);
d62acc5e 1826 pm_runtime_disable(dev);
d7bf353f
MG
1827 return ret;
1828}
1829
1830static int bq24190_remove(struct i2c_client *client)
1831{
1832 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
f385e6e2 1833 int error;
d7bf353f 1834
f385e6e2
TL
1835 error = pm_runtime_get_sync(bdi->dev);
1836 if (error < 0) {
1837 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1838 pm_runtime_put_noidle(bdi->dev);
1839 }
d7bf353f 1840
f385e6e2 1841 bq24190_register_reset(bdi);
1eb2869b
LB
1842 if (bdi->battery)
1843 power_supply_unregister(bdi->battery);
297d716f 1844 power_supply_unregister(bdi->charger);
f385e6e2
TL
1845 if (error >= 0)
1846 pm_runtime_put_sync(bdi->dev);
1847 pm_runtime_dont_use_autosuspend(bdi->dev);
d7bf353f
MG
1848 pm_runtime_disable(bdi->dev);
1849
d7bf353f
MG
1850 return 0;
1851}
1852
b98074e2 1853static __maybe_unused int bq24190_runtime_suspend(struct device *dev)
35c3c196
TL
1854{
1855 struct i2c_client *client = to_i2c_client(dev);
1856 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1857
1858 if (!bdi->initialized)
1859 return 0;
1860
1861 dev_dbg(bdi->dev, "%s\n", __func__);
1862
1863 return 0;
1864}
1865
b98074e2 1866static __maybe_unused int bq24190_runtime_resume(struct device *dev)
35c3c196
TL
1867{
1868 struct i2c_client *client = to_i2c_client(dev);
1869 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1870
1871 if (!bdi->initialized)
1872 return 0;
1873
1874 if (!bdi->irq_event) {
1875 dev_dbg(bdi->dev, "checking events on possible wakeirq\n");
1876 bq24190_check_status(bdi);
1877 }
1878
1879 return 0;
1880}
1881
b98074e2 1882static __maybe_unused int bq24190_pm_suspend(struct device *dev)
d7bf353f
MG
1883{
1884 struct i2c_client *client = to_i2c_client(dev);
1885 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
f385e6e2
TL
1886 int error;
1887
1888 error = pm_runtime_get_sync(bdi->dev);
1889 if (error < 0) {
1890 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1891 pm_runtime_put_noidle(bdi->dev);
1892 }
d7bf353f 1893
d7bf353f 1894 bq24190_register_reset(bdi);
f385e6e2
TL
1895
1896 if (error >= 0) {
1897 pm_runtime_mark_last_busy(bdi->dev);
1898 pm_runtime_put_autosuspend(bdi->dev);
1899 }
d7bf353f
MG
1900
1901 return 0;
1902}
1903
b98074e2 1904static __maybe_unused int bq24190_pm_resume(struct device *dev)
d7bf353f
MG
1905{
1906 struct i2c_client *client = to_i2c_client(dev);
1907 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
f385e6e2 1908 int error;
d7bf353f 1909
2d9fee6a
LB
1910 bdi->f_reg = 0;
1911 bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
d7bf353f 1912
f385e6e2
TL
1913 error = pm_runtime_get_sync(bdi->dev);
1914 if (error < 0) {
1915 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1916 pm_runtime_put_noidle(bdi->dev);
1917 }
1918
d7bf353f 1919 bq24190_register_reset(bdi);
a4c7590b 1920 bq24190_set_config(bdi);
2d9fee6a 1921 bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
f385e6e2
TL
1922
1923 if (error >= 0) {
1924 pm_runtime_mark_last_busy(bdi->dev);
1925 pm_runtime_put_autosuspend(bdi->dev);
1926 }
d7bf353f
MG
1927
1928 /* Things may have changed while suspended so alert upper layer */
297d716f 1929 power_supply_changed(bdi->charger);
1eb2869b
LB
1930 if (bdi->battery)
1931 power_supply_changed(bdi->battery);
d7bf353f
MG
1932
1933 return 0;
1934}
d7bf353f 1935
35c3c196
TL
1936static const struct dev_pm_ops bq24190_pm_ops = {
1937 SET_RUNTIME_PM_OPS(bq24190_runtime_suspend, bq24190_runtime_resume,
1938 NULL)
1939 SET_SYSTEM_SLEEP_PM_OPS(bq24190_pm_suspend, bq24190_pm_resume)
1940};
d7bf353f 1941
d7bf353f 1942static const struct i2c_device_id bq24190_i2c_ids[] = {
99c88eb2 1943 { "bq24190" },
5ea67bb0 1944 { "bq24192" },
99c88eb2 1945 { "bq24192i" },
d0717d73 1946 { "bq24196" },
d7bf353f
MG
1947 { },
1948};
63369b2b 1949MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
d7bf353f
MG
1950
1951#ifdef CONFIG_OF
1952static const struct of_device_id bq24190_of_match[] = {
1953 { .compatible = "ti,bq24190", },
5ea67bb0 1954 { .compatible = "ti,bq24192", },
64b46b7b 1955 { .compatible = "ti,bq24192i", },
d0717d73 1956 { .compatible = "ti,bq24196", },
d7bf353f
MG
1957 { },
1958};
1959MODULE_DEVICE_TABLE(of, bq24190_of_match);
1960#else
1961static const struct of_device_id bq24190_of_match[] = {
1962 { },
1963};
1964#endif
1965
1966static struct i2c_driver bq24190_driver = {
1967 .probe = bq24190_probe,
1968 .remove = bq24190_remove,
1969 .id_table = bq24190_i2c_ids,
1970 .driver = {
1971 .name = "bq24190-charger",
d7bf353f
MG
1972 .pm = &bq24190_pm_ops,
1973 .of_match_table = of_match_ptr(bq24190_of_match),
1974 },
1975};
1976module_i2c_driver(bq24190_driver);
1977
1978MODULE_LICENSE("GPL");
1979MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");
d7bf353f 1980MODULE_DESCRIPTION("TI BQ24190 Charger Driver");