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