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

source code of linux/drivers/power/supply/bq24190_charger.c