1
2
3
4
5
6
7
8
9
10
11#include <linux/module.h>
12#include <linux/interrupt.h>
13#include <linux/delay.h>
14#include <linux/of_irq.h>
15#include <linux/of_device.h>
16#include <linux/pm_runtime.h>
17#include <linux/power_supply.h>
18#include <linux/gpio.h>
19#include <linux/i2c.h>
20
21#include <linux/power/bq24190_charger.h>
22
23
24#define BQ24190_MANUFACTURER "Texas Instruments"
25
26#define BQ24190_REG_ISC 0x00
27#define BQ24190_REG_ISC_EN_HIZ_MASK BIT(7)
28#define BQ24190_REG_ISC_EN_HIZ_SHIFT 7
29#define BQ24190_REG_ISC_VINDPM_MASK (BIT(6) | BIT(5) | BIT(4) | \
30 BIT(3))
31#define BQ24190_REG_ISC_VINDPM_SHIFT 3
32#define BQ24190_REG_ISC_IINLIM_MASK (BIT(2) | BIT(1) | BIT(0))
33#define BQ24190_REG_ISC_IINLIM_SHIFT 0
34
35#define BQ24190_REG_POC 0x01
36#define BQ24190_REG_POC_RESET_MASK BIT(7)
37#define BQ24190_REG_POC_RESET_SHIFT 7
38#define BQ24190_REG_POC_WDT_RESET_MASK BIT(6)
39#define BQ24190_REG_POC_WDT_RESET_SHIFT 6
40#define BQ24190_REG_POC_CHG_CONFIG_MASK (BIT(5) | BIT(4))
41#define BQ24190_REG_POC_CHG_CONFIG_SHIFT 4
42#define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1))
43#define BQ24190_REG_POC_SYS_MIN_SHIFT 1
44#define BQ24190_REG_POC_BOOST_LIM_MASK BIT(0)
45#define BQ24190_REG_POC_BOOST_LIM_SHIFT 0
46
47#define BQ24190_REG_CCC 0x02
48#define BQ24190_REG_CCC_ICHG_MASK (BIT(7) | BIT(6) | BIT(5) | \
49 BIT(4) | BIT(3) | BIT(2))
50#define BQ24190_REG_CCC_ICHG_SHIFT 2
51#define BQ24190_REG_CCC_FORCE_20PCT_MASK BIT(0)
52#define BQ24190_REG_CCC_FORCE_20PCT_SHIFT 0
53
54#define BQ24190_REG_PCTCC 0x03
55#define BQ24190_REG_PCTCC_IPRECHG_MASK (BIT(7) | BIT(6) | BIT(5) | \
56 BIT(4))
57#define BQ24190_REG_PCTCC_IPRECHG_SHIFT 4
58#define BQ24190_REG_PCTCC_ITERM_MASK (BIT(3) | BIT(2) | BIT(1) | \
59 BIT(0))
60#define BQ24190_REG_PCTCC_ITERM_SHIFT 0
61
62#define BQ24190_REG_CVC 0x04
63#define BQ24190_REG_CVC_VREG_MASK (BIT(7) | BIT(6) | BIT(5) | \
64 BIT(4) | BIT(3) | BIT(2))
65#define BQ24190_REG_CVC_VREG_SHIFT 2
66#define BQ24190_REG_CVC_BATLOWV_MASK BIT(1)
67#define BQ24190_REG_CVC_BATLOWV_SHIFT 1
68#define BQ24190_REG_CVC_VRECHG_MASK BIT(0)
69#define BQ24190_REG_CVC_VRECHG_SHIFT 0
70
71#define BQ24190_REG_CTTC 0x05
72#define BQ24190_REG_CTTC_EN_TERM_MASK BIT(7)
73#define BQ24190_REG_CTTC_EN_TERM_SHIFT 7
74#define BQ24190_REG_CTTC_TERM_STAT_MASK BIT(6)
75#define BQ24190_REG_CTTC_TERM_STAT_SHIFT 6
76#define BQ24190_REG_CTTC_WATCHDOG_MASK (BIT(5) | BIT(4))
77#define BQ24190_REG_CTTC_WATCHDOG_SHIFT 4
78#define BQ24190_REG_CTTC_EN_TIMER_MASK BIT(3)
79#define BQ24190_REG_CTTC_EN_TIMER_SHIFT 3
80#define BQ24190_REG_CTTC_CHG_TIMER_MASK (BIT(2) | BIT(1))
81#define BQ24190_REG_CTTC_CHG_TIMER_SHIFT 1
82#define BQ24190_REG_CTTC_JEITA_ISET_MASK BIT(0)
83#define BQ24190_REG_CTTC_JEITA_ISET_SHIFT 0
84
85#define BQ24190_REG_ICTRC 0x06
86#define BQ24190_REG_ICTRC_BAT_COMP_MASK (BIT(7) | BIT(6) | BIT(5))
87#define BQ24190_REG_ICTRC_BAT_COMP_SHIFT 5
88#define BQ24190_REG_ICTRC_VCLAMP_MASK (BIT(4) | BIT(3) | BIT(2))
89#define BQ24190_REG_ICTRC_VCLAMP_SHIFT 2
90#define BQ24190_REG_ICTRC_TREG_MASK (BIT(1) | BIT(0))
91#define BQ24190_REG_ICTRC_TREG_SHIFT 0
92
93#define BQ24190_REG_MOC 0x07
94#define BQ24190_REG_MOC_DPDM_EN_MASK BIT(7)
95#define BQ24190_REG_MOC_DPDM_EN_SHIFT 7
96#define BQ24190_REG_MOC_TMR2X_EN_MASK BIT(6)
97#define BQ24190_REG_MOC_TMR2X_EN_SHIFT 6
98#define BQ24190_REG_MOC_BATFET_DISABLE_MASK BIT(5)
99#define BQ24190_REG_MOC_BATFET_DISABLE_SHIFT 5
100#define BQ24190_REG_MOC_JEITA_VSET_MASK BIT(4)
101#define BQ24190_REG_MOC_JEITA_VSET_SHIFT 4
102#define BQ24190_REG_MOC_INT_MASK_MASK (BIT(1) | BIT(0))
103#define BQ24190_REG_MOC_INT_MASK_SHIFT 0
104
105#define BQ24190_REG_SS 0x08
106#define BQ24190_REG_SS_VBUS_STAT_MASK (BIT(7) | BIT(6))
107#define BQ24190_REG_SS_VBUS_STAT_SHIFT 6
108#define BQ24190_REG_SS_CHRG_STAT_MASK (BIT(5) | BIT(4))
109#define BQ24190_REG_SS_CHRG_STAT_SHIFT 4
110#define BQ24190_REG_SS_DPM_STAT_MASK BIT(3)
111#define BQ24190_REG_SS_DPM_STAT_SHIFT 3
112#define BQ24190_REG_SS_PG_STAT_MASK BIT(2)
113#define BQ24190_REG_SS_PG_STAT_SHIFT 2
114#define BQ24190_REG_SS_THERM_STAT_MASK BIT(1)
115#define BQ24190_REG_SS_THERM_STAT_SHIFT 1
116#define BQ24190_REG_SS_VSYS_STAT_MASK BIT(0)
117#define BQ24190_REG_SS_VSYS_STAT_SHIFT 0
118
119#define BQ24190_REG_F 0x09
120#define BQ24190_REG_F_WATCHDOG_FAULT_MASK BIT(7)
121#define BQ24190_REG_F_WATCHDOG_FAULT_SHIFT 7
122#define BQ24190_REG_F_BOOST_FAULT_MASK BIT(6)
123#define BQ24190_REG_F_BOOST_FAULT_SHIFT 6
124#define BQ24190_REG_F_CHRG_FAULT_MASK (BIT(5) | BIT(4))
125#define BQ24190_REG_F_CHRG_FAULT_SHIFT 4
126#define BQ24190_REG_F_BAT_FAULT_MASK BIT(3)
127#define BQ24190_REG_F_BAT_FAULT_SHIFT 3
128#define BQ24190_REG_F_NTC_FAULT_MASK (BIT(2) | BIT(1) | BIT(0))
129#define BQ24190_REG_F_NTC_FAULT_SHIFT 0
130
131#define BQ24190_REG_VPRS 0x0A
132#define BQ24190_REG_VPRS_PN_MASK (BIT(5) | BIT(4) | BIT(3))
133#define BQ24190_REG_VPRS_PN_SHIFT 3
134#define BQ24190_REG_VPRS_PN_24190 0x4
135#define BQ24190_REG_VPRS_PN_24192 0x5
136#define BQ24190_REG_VPRS_PN_24192I 0x3
137#define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2)
138#define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2
139#define BQ24190_REG_VPRS_DEV_REG_MASK (BIT(1) | BIT(0))
140#define BQ24190_REG_VPRS_DEV_REG_SHIFT 0
141
142
143
144
145
146
147
148
149
150
151
152struct bq24190_dev_info {
153 struct i2c_client *client;
154 struct device *dev;
155 struct power_supply *charger;
156 struct power_supply *battery;
157 char model_name[I2C_NAME_SIZE];
158 kernel_ulong_t model;
159 unsigned int gpio_int;
160 unsigned int irq;
161 struct mutex f_reg_lock;
162 bool first_time;
163 bool charger_health_valid;
164 bool battery_health_valid;
165 bool battery_status_valid;
166 u8 f_reg;
167 u8 ss_reg;
168 u8 watchdog;
169};
170
171
172
173
174
175
176
177
178
179static const int bq24190_ccc_ichg_values[] = {
180 512000, 576000, 640000, 704000, 768000, 832000, 896000, 960000,
181 1024000, 1088000, 1152000, 1216000, 1280000, 1344000, 1408000, 1472000,
182 1536000, 1600000, 1664000, 1728000, 1792000, 1856000, 1920000, 1984000,
183 2048000, 2112000, 2176000, 2240000, 2304000, 2368000, 2432000, 2496000,
184 2560000, 2624000, 2688000, 2752000, 2816000, 2880000, 2944000, 3008000,
185 3072000, 3136000, 3200000, 3264000, 3328000, 3392000, 3456000, 3520000,
186 3584000, 3648000, 3712000, 3776000, 3840000, 3904000, 3968000, 4032000,
187 4096000, 4160000, 4224000, 4288000, 4352000, 4416000, 4480000, 4544000
188};
189
190
191static const int bq24190_cvc_vreg_values[] = {
192 3504000, 3520000, 3536000, 3552000, 3568000, 3584000, 3600000, 3616000,
193 3632000, 3648000, 3664000, 3680000, 3696000, 3712000, 3728000, 3744000,
194 3760000, 3776000, 3792000, 3808000, 3824000, 3840000, 3856000, 3872000,
195 3888000, 3904000, 3920000, 3936000, 3952000, 3968000, 3984000, 4000000,
196 4016000, 4032000, 4048000, 4064000, 4080000, 4096000, 4112000, 4128000,
197 4144000, 4160000, 4176000, 4192000, 4208000, 4224000, 4240000, 4256000,
198 4272000, 4288000, 4304000, 4320000, 4336000, 4352000, 4368000, 4384000,
199 4400000
200};
201
202
203static const int bq24190_ictrc_treg_values[] = {
204 600, 800, 1000, 1200
205};
206
207
208
209
210
211
212
213static u8 bq24190_find_idx(const int tbl[], int tbl_size, int v)
214{
215 int i;
216
217 for (i = 1; i < tbl_size; i++)
218 if (v < tbl[i])
219 break;
220
221 return i - 1;
222}
223
224
225
226static int bq24190_read(struct bq24190_dev_info *bdi, u8 reg, u8 *data)
227{
228 int ret;
229
230 ret = i2c_smbus_read_byte_data(bdi->client, reg);
231 if (ret < 0)
232 return ret;
233
234 *data = ret;
235 return 0;
236}
237
238static int bq24190_write(struct bq24190_dev_info *bdi, u8 reg, u8 data)
239{
240 return i2c_smbus_write_byte_data(bdi->client, reg, data);
241}
242
243static int bq24190_read_mask(struct bq24190_dev_info *bdi, u8 reg,
244 u8 mask, u8 shift, u8 *data)
245{
246 u8 v;
247 int ret;
248
249 ret = bq24190_read(bdi, reg, &v);
250 if (ret < 0)
251 return ret;
252
253 v &= mask;
254 v >>= shift;
255 *data = v;
256
257 return 0;
258}
259
260static int bq24190_write_mask(struct bq24190_dev_info *bdi, u8 reg,
261 u8 mask, u8 shift, u8 data)
262{
263 u8 v;
264 int ret;
265
266 ret = bq24190_read(bdi, reg, &v);
267 if (ret < 0)
268 return ret;
269
270 v &= ~mask;
271 v |= ((data << shift) & mask);
272
273 return bq24190_write(bdi, reg, v);
274}
275
276static int bq24190_get_field_val(struct bq24190_dev_info *bdi,
277 u8 reg, u8 mask, u8 shift,
278 const int tbl[], int tbl_size,
279 int *val)
280{
281 u8 v;
282 int ret;
283
284 ret = bq24190_read_mask(bdi, reg, mask, shift, &v);
285 if (ret < 0)
286 return ret;
287
288 v = (v >= tbl_size) ? (tbl_size - 1) : v;
289 *val = tbl[v];
290
291 return 0;
292}
293
294static int bq24190_set_field_val(struct bq24190_dev_info *bdi,
295 u8 reg, u8 mask, u8 shift,
296 const int tbl[], int tbl_size,
297 int val)
298{
299 u8 idx;
300
301 idx = bq24190_find_idx(tbl, tbl_size, val);
302
303 return bq24190_write_mask(bdi, reg, mask, shift, idx);
304}
305
306#ifdef CONFIG_SYSFS
307
308
309
310
311
312
313
314
315#define BQ24190_SYSFS_FIELD(_name, r, f, m, store) \
316{ \
317 .attr = __ATTR(f_##_name, m, bq24190_sysfs_show, store), \
318 .reg = BQ24190_REG_##r, \
319 .mask = BQ24190_REG_##r##_##f##_MASK, \
320 .shift = BQ24190_REG_##r##_##f##_SHIFT, \
321}
322
323#define BQ24190_SYSFS_FIELD_RW(_name, r, f) \
324 BQ24190_SYSFS_FIELD(_name, r, f, S_IWUSR | S_IRUGO, \
325 bq24190_sysfs_store)
326
327#define BQ24190_SYSFS_FIELD_RO(_name, r, f) \
328 BQ24190_SYSFS_FIELD(_name, r, f, S_IRUGO, NULL)
329
330static ssize_t bq24190_sysfs_show(struct device *dev,
331 struct device_attribute *attr, char *buf);
332static ssize_t bq24190_sysfs_store(struct device *dev,
333 struct device_attribute *attr, const char *buf, size_t count);
334
335struct bq24190_sysfs_field_info {
336 struct device_attribute attr;
337 u8 reg;
338 u8 mask;
339 u8 shift;
340};
341
342
343#undef SS
344
345static struct bq24190_sysfs_field_info bq24190_sysfs_field_tbl[] = {
346
347 BQ24190_SYSFS_FIELD_RW(en_hiz, ISC, EN_HIZ),
348 BQ24190_SYSFS_FIELD_RW(vindpm, ISC, VINDPM),
349 BQ24190_SYSFS_FIELD_RW(iinlim, ISC, IINLIM),
350 BQ24190_SYSFS_FIELD_RW(chg_config, POC, CHG_CONFIG),
351 BQ24190_SYSFS_FIELD_RW(sys_min, POC, SYS_MIN),
352 BQ24190_SYSFS_FIELD_RW(boost_lim, POC, BOOST_LIM),
353 BQ24190_SYSFS_FIELD_RW(ichg, CCC, ICHG),
354 BQ24190_SYSFS_FIELD_RW(force_20_pct, CCC, FORCE_20PCT),
355 BQ24190_SYSFS_FIELD_RW(iprechg, PCTCC, IPRECHG),
356 BQ24190_SYSFS_FIELD_RW(iterm, PCTCC, ITERM),
357 BQ24190_SYSFS_FIELD_RW(vreg, CVC, VREG),
358 BQ24190_SYSFS_FIELD_RW(batlowv, CVC, BATLOWV),
359 BQ24190_SYSFS_FIELD_RW(vrechg, CVC, VRECHG),
360 BQ24190_SYSFS_FIELD_RW(en_term, CTTC, EN_TERM),
361 BQ24190_SYSFS_FIELD_RW(term_stat, CTTC, TERM_STAT),
362 BQ24190_SYSFS_FIELD_RO(watchdog, CTTC, WATCHDOG),
363 BQ24190_SYSFS_FIELD_RW(en_timer, CTTC, EN_TIMER),
364 BQ24190_SYSFS_FIELD_RW(chg_timer, CTTC, CHG_TIMER),
365 BQ24190_SYSFS_FIELD_RW(jeta_iset, CTTC, JEITA_ISET),
366 BQ24190_SYSFS_FIELD_RW(bat_comp, ICTRC, BAT_COMP),
367 BQ24190_SYSFS_FIELD_RW(vclamp, ICTRC, VCLAMP),
368 BQ24190_SYSFS_FIELD_RW(treg, ICTRC, TREG),
369 BQ24190_SYSFS_FIELD_RW(dpdm_en, MOC, DPDM_EN),
370 BQ24190_SYSFS_FIELD_RW(tmr2x_en, MOC, TMR2X_EN),
371 BQ24190_SYSFS_FIELD_RW(batfet_disable, MOC, BATFET_DISABLE),
372 BQ24190_SYSFS_FIELD_RW(jeita_vset, MOC, JEITA_VSET),
373 BQ24190_SYSFS_FIELD_RO(int_mask, MOC, INT_MASK),
374 BQ24190_SYSFS_FIELD_RO(vbus_stat, SS, VBUS_STAT),
375 BQ24190_SYSFS_FIELD_RO(chrg_stat, SS, CHRG_STAT),
376 BQ24190_SYSFS_FIELD_RO(dpm_stat, SS, DPM_STAT),
377 BQ24190_SYSFS_FIELD_RO(pg_stat, SS, PG_STAT),
378 BQ24190_SYSFS_FIELD_RO(therm_stat, SS, THERM_STAT),
379 BQ24190_SYSFS_FIELD_RO(vsys_stat, SS, VSYS_STAT),
380 BQ24190_SYSFS_FIELD_RO(watchdog_fault, F, WATCHDOG_FAULT),
381 BQ24190_SYSFS_FIELD_RO(boost_fault, F, BOOST_FAULT),
382 BQ24190_SYSFS_FIELD_RO(chrg_fault, F, CHRG_FAULT),
383 BQ24190_SYSFS_FIELD_RO(bat_fault, F, BAT_FAULT),
384 BQ24190_SYSFS_FIELD_RO(ntc_fault, F, NTC_FAULT),
385 BQ24190_SYSFS_FIELD_RO(pn, VPRS, PN),
386 BQ24190_SYSFS_FIELD_RO(ts_profile, VPRS, TS_PROFILE),
387 BQ24190_SYSFS_FIELD_RO(dev_reg, VPRS, DEV_REG),
388};
389
390static struct attribute *
391 bq24190_sysfs_attrs[ARRAY_SIZE(bq24190_sysfs_field_tbl) + 1];
392
393static const struct attribute_group bq24190_sysfs_attr_group = {
394 .attrs = bq24190_sysfs_attrs,
395};
396
397static void bq24190_sysfs_init_attrs(void)
398{
399 int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);
400
401 for (i = 0; i < limit; i++)
402 bq24190_sysfs_attrs[i] = &bq24190_sysfs_field_tbl[i].attr.attr;
403
404 bq24190_sysfs_attrs[limit] = NULL;
405}
406
407static struct bq24190_sysfs_field_info *bq24190_sysfs_field_lookup(
408 const char *name)
409{
410 int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);
411
412 for (i = 0; i < limit; i++)
413 if (!strcmp(name, bq24190_sysfs_field_tbl[i].attr.attr.name))
414 break;
415
416 if (i >= limit)
417 return NULL;
418
419 return &bq24190_sysfs_field_tbl[i];
420}
421
422static ssize_t bq24190_sysfs_show(struct device *dev,
423 struct device_attribute *attr, char *buf)
424{
425 struct power_supply *psy = dev_get_drvdata(dev);
426 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
427 struct bq24190_sysfs_field_info *info;
428 int ret;
429 u8 v;
430
431 info = bq24190_sysfs_field_lookup(attr->attr.name);
432 if (!info)
433 return -EINVAL;
434
435 ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);
436 if (ret)
437 return ret;
438
439 return scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
440}
441
442static ssize_t bq24190_sysfs_store(struct device *dev,
443 struct device_attribute *attr, const char *buf, size_t count)
444{
445 struct power_supply *psy = dev_get_drvdata(dev);
446 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
447 struct bq24190_sysfs_field_info *info;
448 int ret;
449 u8 v;
450
451 info = bq24190_sysfs_field_lookup(attr->attr.name);
452 if (!info)
453 return -EINVAL;
454
455 ret = kstrtou8(buf, 0, &v);
456 if (ret < 0)
457 return ret;
458
459 ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);
460 if (ret)
461 return ret;
462
463 return count;
464}
465
466static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
467{
468 bq24190_sysfs_init_attrs();
469
470 return sysfs_create_group(&bdi->charger->dev.kobj,
471 &bq24190_sysfs_attr_group);
472}
473
474static void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi)
475{
476 sysfs_remove_group(&bdi->charger->dev.kobj, &bq24190_sysfs_attr_group);
477}
478#else
479static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
480{
481 return 0;
482}
483
484static inline void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi) {}
485#endif
486
487
488
489
490
491
492
493
494
495static int bq24190_set_mode_host(struct bq24190_dev_info *bdi)
496{
497 int ret;
498 u8 v;
499
500 ret = bq24190_read(bdi, BQ24190_REG_CTTC, &v);
501 if (ret < 0)
502 return ret;
503
504 bdi->watchdog = ((v & BQ24190_REG_CTTC_WATCHDOG_MASK) >>
505 BQ24190_REG_CTTC_WATCHDOG_SHIFT);
506 v &= ~BQ24190_REG_CTTC_WATCHDOG_MASK;
507
508 return bq24190_write(bdi, BQ24190_REG_CTTC, v);
509}
510
511static int bq24190_register_reset(struct bq24190_dev_info *bdi)
512{
513 int ret, limit = 100;
514 u8 v;
515
516
517 ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
518 BQ24190_REG_POC_RESET_MASK,
519 BQ24190_REG_POC_RESET_SHIFT,
520 0x1);
521 if (ret < 0)
522 return ret;
523
524
525 do {
526 ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
527 BQ24190_REG_POC_RESET_MASK,
528 BQ24190_REG_POC_RESET_SHIFT,
529 &v);
530 if (ret < 0)
531 return ret;
532
533 if (!v)
534 break;
535
536 udelay(10);
537 } while (--limit);
538
539 if (!limit)
540 return -EIO;
541
542 return 0;
543}
544
545
546
547static int bq24190_charger_get_charge_type(struct bq24190_dev_info *bdi,
548 union power_supply_propval *val)
549{
550 u8 v;
551 int type, ret;
552
553 ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
554 BQ24190_REG_POC_CHG_CONFIG_MASK,
555 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
556 &v);
557 if (ret < 0)
558 return ret;
559
560
561 if (!v) {
562 type = POWER_SUPPLY_CHARGE_TYPE_NONE;
563 } else {
564 ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
565 BQ24190_REG_CCC_FORCE_20PCT_MASK,
566 BQ24190_REG_CCC_FORCE_20PCT_SHIFT,
567 &v);
568 if (ret < 0)
569 return ret;
570
571 type = (v) ? POWER_SUPPLY_CHARGE_TYPE_TRICKLE :
572 POWER_SUPPLY_CHARGE_TYPE_FAST;
573 }
574
575 val->intval = type;
576
577 return 0;
578}
579
580static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,
581 const union power_supply_propval *val)
582{
583 u8 chg_config, force_20pct, en_term;
584 int ret;
585
586
587
588
589
590
591
592
593
594
595
596 switch (val->intval) {
597 case POWER_SUPPLY_CHARGE_TYPE_NONE:
598 chg_config = 0x0;
599 break;
600 case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
601 chg_config = 0x1;
602 force_20pct = 0x1;
603 en_term = 0x0;
604 break;
605 case POWER_SUPPLY_CHARGE_TYPE_FAST:
606 chg_config = 0x1;
607 force_20pct = 0x0;
608 en_term = 0x1;
609 break;
610 default:
611 return -EINVAL;
612 }
613
614 if (chg_config) {
615 ret = bq24190_write_mask(bdi, BQ24190_REG_CCC,
616 BQ24190_REG_CCC_FORCE_20PCT_MASK,
617 BQ24190_REG_CCC_FORCE_20PCT_SHIFT,
618 force_20pct);
619 if (ret < 0)
620 return ret;
621
622 ret = bq24190_write_mask(bdi, BQ24190_REG_CTTC,
623 BQ24190_REG_CTTC_EN_TERM_MASK,
624 BQ24190_REG_CTTC_EN_TERM_SHIFT,
625 en_term);
626 if (ret < 0)
627 return ret;
628 }
629
630 return bq24190_write_mask(bdi, BQ24190_REG_POC,
631 BQ24190_REG_POC_CHG_CONFIG_MASK,
632 BQ24190_REG_POC_CHG_CONFIG_SHIFT, chg_config);
633}
634
635static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
636 union power_supply_propval *val)
637{
638 u8 v;
639 int health, ret;
640
641 mutex_lock(&bdi->f_reg_lock);
642
643 if (bdi->charger_health_valid) {
644 v = bdi->f_reg;
645 bdi->charger_health_valid = false;
646 mutex_unlock(&bdi->f_reg_lock);
647 } else {
648 mutex_unlock(&bdi->f_reg_lock);
649
650 ret = bq24190_read(bdi, BQ24190_REG_F, &v);
651 if (ret < 0)
652 return ret;
653 }
654
655 if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {
656
657
658
659
660
661
662 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
663 } else {
664 v &= BQ24190_REG_F_CHRG_FAULT_MASK;
665 v >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
666
667 switch (v) {
668 case 0x0:
669 health = POWER_SUPPLY_HEALTH_GOOD;
670 break;
671 case 0x1:
672
673
674
675
676
677
678
679 health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
680 break;
681 case 0x2:
682 health = POWER_SUPPLY_HEALTH_OVERHEAT;
683 break;
684 case 0x3:
685 health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
686 break;
687 default:
688 health = POWER_SUPPLY_HEALTH_UNKNOWN;
689 }
690 }
691
692 val->intval = health;
693
694 return 0;
695}
696
697static int bq24190_charger_get_online(struct bq24190_dev_info *bdi,
698 union power_supply_propval *val)
699{
700 u8 v;
701 int ret;
702
703 ret = bq24190_read_mask(bdi, BQ24190_REG_SS,
704 BQ24190_REG_SS_PG_STAT_MASK,
705 BQ24190_REG_SS_PG_STAT_SHIFT, &v);
706 if (ret < 0)
707 return ret;
708
709 val->intval = v;
710 return 0;
711}
712
713static int bq24190_charger_get_current(struct bq24190_dev_info *bdi,
714 union power_supply_propval *val)
715{
716 u8 v;
717 int curr, ret;
718
719 ret = bq24190_get_field_val(bdi, BQ24190_REG_CCC,
720 BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
721 bq24190_ccc_ichg_values,
722 ARRAY_SIZE(bq24190_ccc_ichg_values), &curr);
723 if (ret < 0)
724 return ret;
725
726 ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
727 BQ24190_REG_CCC_FORCE_20PCT_MASK,
728 BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);
729 if (ret < 0)
730 return ret;
731
732
733 if (v)
734 curr /= 5;
735
736 val->intval = curr;
737 return 0;
738}
739
740static int bq24190_charger_get_current_max(struct bq24190_dev_info *bdi,
741 union power_supply_propval *val)
742{
743 int idx = ARRAY_SIZE(bq24190_ccc_ichg_values) - 1;
744
745 val->intval = bq24190_ccc_ichg_values[idx];
746 return 0;
747}
748
749static int bq24190_charger_set_current(struct bq24190_dev_info *bdi,
750 const union power_supply_propval *val)
751{
752 u8 v;
753 int ret, curr = val->intval;
754
755 ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
756 BQ24190_REG_CCC_FORCE_20PCT_MASK,
757 BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);
758 if (ret < 0)
759 return ret;
760
761
762 if (v)
763 curr *= 5;
764
765 return bq24190_set_field_val(bdi, BQ24190_REG_CCC,
766 BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
767 bq24190_ccc_ichg_values,
768 ARRAY_SIZE(bq24190_ccc_ichg_values), curr);
769}
770
771static int bq24190_charger_get_voltage(struct bq24190_dev_info *bdi,
772 union power_supply_propval *val)
773{
774 int voltage, ret;
775
776 ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,
777 BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
778 bq24190_cvc_vreg_values,
779 ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);
780 if (ret < 0)
781 return ret;
782
783 val->intval = voltage;
784 return 0;
785}
786
787static int bq24190_charger_get_voltage_max(struct bq24190_dev_info *bdi,
788 union power_supply_propval *val)
789{
790 int idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1;
791
792 val->intval = bq24190_cvc_vreg_values[idx];
793 return 0;
794}
795
796static int bq24190_charger_set_voltage(struct bq24190_dev_info *bdi,
797 const union power_supply_propval *val)
798{
799 return bq24190_set_field_val(bdi, BQ24190_REG_CVC,
800 BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
801 bq24190_cvc_vreg_values,
802 ARRAY_SIZE(bq24190_cvc_vreg_values), val->intval);
803}
804
805static int bq24190_charger_get_property(struct power_supply *psy,
806 enum power_supply_property psp, union power_supply_propval *val)
807{
808 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
809 int ret;
810
811 dev_dbg(bdi->dev, "prop: %d\n", psp);
812
813 pm_runtime_get_sync(bdi->dev);
814
815 switch (psp) {
816 case POWER_SUPPLY_PROP_CHARGE_TYPE:
817 ret = bq24190_charger_get_charge_type(bdi, val);
818 break;
819 case POWER_SUPPLY_PROP_HEALTH:
820 ret = bq24190_charger_get_health(bdi, val);
821 break;
822 case POWER_SUPPLY_PROP_ONLINE:
823 ret = bq24190_charger_get_online(bdi, val);
824 break;
825 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
826 ret = bq24190_charger_get_current(bdi, val);
827 break;
828 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
829 ret = bq24190_charger_get_current_max(bdi, val);
830 break;
831 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
832 ret = bq24190_charger_get_voltage(bdi, val);
833 break;
834 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
835 ret = bq24190_charger_get_voltage_max(bdi, val);
836 break;
837 case POWER_SUPPLY_PROP_SCOPE:
838 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
839 ret = 0;
840 break;
841 case POWER_SUPPLY_PROP_MODEL_NAME:
842 val->strval = bdi->model_name;
843 ret = 0;
844 break;
845 case POWER_SUPPLY_PROP_MANUFACTURER:
846 val->strval = BQ24190_MANUFACTURER;
847 ret = 0;
848 break;
849 default:
850 ret = -ENODATA;
851 }
852
853 pm_runtime_put_sync(bdi->dev);
854 return ret;
855}
856
857static int bq24190_charger_set_property(struct power_supply *psy,
858 enum power_supply_property psp,
859 const union power_supply_propval *val)
860{
861 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
862 int ret;
863
864 dev_dbg(bdi->dev, "prop: %d\n", psp);
865
866 pm_runtime_get_sync(bdi->dev);
867
868 switch (psp) {
869 case POWER_SUPPLY_PROP_CHARGE_TYPE:
870 ret = bq24190_charger_set_charge_type(bdi, val);
871 break;
872 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
873 ret = bq24190_charger_set_current(bdi, val);
874 break;
875 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
876 ret = bq24190_charger_set_voltage(bdi, val);
877 break;
878 default:
879 ret = -EINVAL;
880 }
881
882 pm_runtime_put_sync(bdi->dev);
883 return ret;
884}
885
886static int bq24190_charger_property_is_writeable(struct power_supply *psy,
887 enum power_supply_property psp)
888{
889 int ret;
890
891 switch (psp) {
892 case POWER_SUPPLY_PROP_CHARGE_TYPE:
893 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
894 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
895 ret = 1;
896 break;
897 default:
898 ret = 0;
899 }
900
901 return ret;
902}
903
904static enum power_supply_property bq24190_charger_properties[] = {
905 POWER_SUPPLY_PROP_CHARGE_TYPE,
906 POWER_SUPPLY_PROP_HEALTH,
907 POWER_SUPPLY_PROP_ONLINE,
908 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
909 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
910 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
911 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
912 POWER_SUPPLY_PROP_SCOPE,
913 POWER_SUPPLY_PROP_MODEL_NAME,
914 POWER_SUPPLY_PROP_MANUFACTURER,
915};
916
917static char *bq24190_charger_supplied_to[] = {
918 "main-battery",
919};
920
921static const struct power_supply_desc bq24190_charger_desc = {
922 .name = "bq24190-charger",
923 .type = POWER_SUPPLY_TYPE_USB,
924 .properties = bq24190_charger_properties,
925 .num_properties = ARRAY_SIZE(bq24190_charger_properties),
926 .get_property = bq24190_charger_get_property,
927 .set_property = bq24190_charger_set_property,
928 .property_is_writeable = bq24190_charger_property_is_writeable,
929};
930
931
932
933static int bq24190_battery_get_status(struct bq24190_dev_info *bdi,
934 union power_supply_propval *val)
935{
936 u8 ss_reg, chrg_fault;
937 int status, ret;
938
939 mutex_lock(&bdi->f_reg_lock);
940
941 if (bdi->battery_status_valid) {
942 chrg_fault = bdi->f_reg;
943 bdi->battery_status_valid = false;
944 mutex_unlock(&bdi->f_reg_lock);
945 } else {
946 mutex_unlock(&bdi->f_reg_lock);
947
948 ret = bq24190_read(bdi, BQ24190_REG_F, &chrg_fault);
949 if (ret < 0)
950 return ret;
951 }
952
953 chrg_fault &= BQ24190_REG_F_CHRG_FAULT_MASK;
954 chrg_fault >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
955
956 ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);
957 if (ret < 0)
958 return ret;
959
960
961
962
963
964
965
966
967 if (!(ss_reg & BQ24190_REG_SS_PG_STAT_MASK) || chrg_fault) {
968 status = POWER_SUPPLY_STATUS_DISCHARGING;
969 } else {
970 ss_reg &= BQ24190_REG_SS_CHRG_STAT_MASK;
971 ss_reg >>= BQ24190_REG_SS_CHRG_STAT_SHIFT;
972
973 switch (ss_reg) {
974 case 0x0:
975 status = POWER_SUPPLY_STATUS_NOT_CHARGING;
976 break;
977 case 0x1:
978 case 0x2:
979 status = POWER_SUPPLY_STATUS_CHARGING;
980 break;
981 case 0x3:
982 status = POWER_SUPPLY_STATUS_FULL;
983 break;
984 default:
985 ret = -EIO;
986 }
987 }
988
989 if (!ret)
990 val->intval = status;
991
992 return ret;
993}
994
995static int bq24190_battery_get_health(struct bq24190_dev_info *bdi,
996 union power_supply_propval *val)
997{
998 u8 v;
999 int health, ret;
1000
1001 mutex_lock(&bdi->f_reg_lock);
1002
1003 if (bdi->battery_health_valid) {
1004 v = bdi->f_reg;
1005 bdi->battery_health_valid = false;
1006 mutex_unlock(&bdi->f_reg_lock);
1007 } else {
1008 mutex_unlock(&bdi->f_reg_lock);
1009
1010 ret = bq24190_read(bdi, BQ24190_REG_F, &v);
1011 if (ret < 0)
1012 return ret;
1013 }
1014
1015 if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
1016 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1017 } else {
1018 v &= BQ24190_REG_F_NTC_FAULT_MASK;
1019 v >>= BQ24190_REG_F_NTC_FAULT_SHIFT;
1020
1021 switch (v) {
1022 case 0x0:
1023 health = POWER_SUPPLY_HEALTH_GOOD;
1024 break;
1025 case 0x1:
1026 case 0x3:
1027 case 0x5:
1028 health = POWER_SUPPLY_HEALTH_COLD;
1029 break;
1030 case 0x2:
1031 case 0x4:
1032 case 0x6:
1033 health = POWER_SUPPLY_HEALTH_OVERHEAT;
1034 break;
1035 default:
1036 health = POWER_SUPPLY_HEALTH_UNKNOWN;
1037 }
1038 }
1039
1040 val->intval = health;
1041 return 0;
1042}
1043
1044static int bq24190_battery_get_online(struct bq24190_dev_info *bdi,
1045 union power_supply_propval *val)
1046{
1047 u8 batfet_disable;
1048 int ret;
1049
1050 ret = bq24190_read_mask(bdi, BQ24190_REG_MOC,
1051 BQ24190_REG_MOC_BATFET_DISABLE_MASK,
1052 BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, &batfet_disable);
1053 if (ret < 0)
1054 return ret;
1055
1056 val->intval = !batfet_disable;
1057 return 0;
1058}
1059
1060static int bq24190_battery_set_online(struct bq24190_dev_info *bdi,
1061 const union power_supply_propval *val)
1062{
1063 return bq24190_write_mask(bdi, BQ24190_REG_MOC,
1064 BQ24190_REG_MOC_BATFET_DISABLE_MASK,
1065 BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, !val->intval);
1066}
1067
1068static int bq24190_battery_get_temp_alert_max(struct bq24190_dev_info *bdi,
1069 union power_supply_propval *val)
1070{
1071 int temp, ret;
1072
1073 ret = bq24190_get_field_val(bdi, BQ24190_REG_ICTRC,
1074 BQ24190_REG_ICTRC_TREG_MASK,
1075 BQ24190_REG_ICTRC_TREG_SHIFT,
1076 bq24190_ictrc_treg_values,
1077 ARRAY_SIZE(bq24190_ictrc_treg_values), &temp);
1078 if (ret < 0)
1079 return ret;
1080
1081 val->intval = temp;
1082 return 0;
1083}
1084
1085static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,
1086 const union power_supply_propval *val)
1087{
1088 return bq24190_set_field_val(bdi, BQ24190_REG_ICTRC,
1089 BQ24190_REG_ICTRC_TREG_MASK,
1090 BQ24190_REG_ICTRC_TREG_SHIFT,
1091 bq24190_ictrc_treg_values,
1092 ARRAY_SIZE(bq24190_ictrc_treg_values), val->intval);
1093}
1094
1095static int bq24190_battery_get_property(struct power_supply *psy,
1096 enum power_supply_property psp, union power_supply_propval *val)
1097{
1098 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
1099 int ret;
1100
1101 dev_dbg(bdi->dev, "prop: %d\n", psp);
1102
1103 pm_runtime_get_sync(bdi->dev);
1104
1105 switch (psp) {
1106 case POWER_SUPPLY_PROP_STATUS:
1107 ret = bq24190_battery_get_status(bdi, val);
1108 break;
1109 case POWER_SUPPLY_PROP_HEALTH:
1110 ret = bq24190_battery_get_health(bdi, val);
1111 break;
1112 case POWER_SUPPLY_PROP_ONLINE:
1113 ret = bq24190_battery_get_online(bdi, val);
1114 break;
1115 case POWER_SUPPLY_PROP_TECHNOLOGY:
1116
1117 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
1118 ret = 0;
1119 break;
1120 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1121 ret = bq24190_battery_get_temp_alert_max(bdi, val);
1122 break;
1123 case POWER_SUPPLY_PROP_SCOPE:
1124 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
1125 ret = 0;
1126 break;
1127 default:
1128 ret = -ENODATA;
1129 }
1130
1131 pm_runtime_put_sync(bdi->dev);
1132 return ret;
1133}
1134
1135static int bq24190_battery_set_property(struct power_supply *psy,
1136 enum power_supply_property psp,
1137 const union power_supply_propval *val)
1138{
1139 struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
1140 int ret;
1141
1142 dev_dbg(bdi->dev, "prop: %d\n", psp);
1143
1144 pm_runtime_put_sync(bdi->dev);
1145
1146 switch (psp) {
1147 case POWER_SUPPLY_PROP_ONLINE:
1148 ret = bq24190_battery_set_online(bdi, val);
1149 break;
1150 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1151 ret = bq24190_battery_set_temp_alert_max(bdi, val);
1152 break;
1153 default:
1154 ret = -EINVAL;
1155 }
1156
1157 pm_runtime_put_sync(bdi->dev);
1158 return ret;
1159}
1160
1161static int bq24190_battery_property_is_writeable(struct power_supply *psy,
1162 enum power_supply_property psp)
1163{
1164 int ret;
1165
1166 switch (psp) {
1167 case POWER_SUPPLY_PROP_ONLINE:
1168 case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1169 ret = 1;
1170 break;
1171 default:
1172 ret = 0;
1173 }
1174
1175 return ret;
1176}
1177
1178static enum power_supply_property bq24190_battery_properties[] = {
1179 POWER_SUPPLY_PROP_STATUS,
1180 POWER_SUPPLY_PROP_HEALTH,
1181 POWER_SUPPLY_PROP_ONLINE,
1182 POWER_SUPPLY_PROP_TECHNOLOGY,
1183 POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
1184 POWER_SUPPLY_PROP_SCOPE,
1185};
1186
1187static const struct power_supply_desc bq24190_battery_desc = {
1188 .name = "bq24190-battery",
1189 .type = POWER_SUPPLY_TYPE_BATTERY,
1190 .properties = bq24190_battery_properties,
1191 .num_properties = ARRAY_SIZE(bq24190_battery_properties),
1192 .get_property = bq24190_battery_get_property,
1193 .set_property = bq24190_battery_set_property,
1194 .property_is_writeable = bq24190_battery_property_is_writeable,
1195};
1196
1197static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
1198{
1199 struct bq24190_dev_info *bdi = data;
1200 bool alert_userspace = false;
1201 u8 ss_reg = 0, f_reg = 0;
1202 int ret;
1203
1204 pm_runtime_get_sync(bdi->dev);
1205
1206 ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);
1207 if (ret < 0) {
1208 dev_err(bdi->dev, "Can't read SS reg: %d\n", ret);
1209 goto out;
1210 }
1211
1212 if (ss_reg != bdi->ss_reg) {
1213
1214
1215
1216
1217 if ((bdi->ss_reg & BQ24190_REG_SS_PG_STAT_MASK) &&
1218 !(ss_reg & BQ24190_REG_SS_PG_STAT_MASK)) {
1219 ret = bq24190_write_mask(bdi, BQ24190_REG_ISC,
1220 BQ24190_REG_ISC_EN_HIZ_MASK,
1221 BQ24190_REG_ISC_EN_HIZ_SHIFT,
1222 0);
1223 if (ret < 0)
1224 dev_err(bdi->dev, "Can't access ISC reg: %d\n",
1225 ret);
1226 }
1227
1228 bdi->ss_reg = ss_reg;
1229 alert_userspace = true;
1230 }
1231
1232 mutex_lock(&bdi->f_reg_lock);
1233
1234 ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);
1235 if (ret < 0) {
1236 mutex_unlock(&bdi->f_reg_lock);
1237 dev_err(bdi->dev, "Can't read F reg: %d\n", ret);
1238 goto out;
1239 }
1240
1241 if (f_reg != bdi->f_reg) {
1242 bdi->f_reg = f_reg;
1243 bdi->charger_health_valid = true;
1244 bdi->battery_health_valid = true;
1245 bdi->battery_status_valid = true;
1246
1247 alert_userspace = true;
1248 }
1249
1250 mutex_unlock(&bdi->f_reg_lock);
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261 if (alert_userspace) {
1262 if (!bdi->first_time) {
1263 power_supply_changed(bdi->charger);
1264 power_supply_changed(bdi->battery);
1265 } else {
1266 bdi->first_time = false;
1267 }
1268 }
1269
1270out:
1271 pm_runtime_put_sync(bdi->dev);
1272
1273 dev_dbg(bdi->dev, "ss_reg: 0x%02x, f_reg: 0x%02x\n", ss_reg, f_reg);
1274
1275 return IRQ_HANDLED;
1276}
1277
1278static int bq24190_hw_init(struct bq24190_dev_info *bdi)
1279{
1280 u8 v;
1281 int ret;
1282
1283 pm_runtime_get_sync(bdi->dev);
1284
1285
1286 ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,
1287 BQ24190_REG_VPRS_PN_MASK,
1288 BQ24190_REG_VPRS_PN_SHIFT,
1289 &v);
1290 if (ret < 0)
1291 goto out;
1292
1293 if (v != bdi->model) {
1294 ret = -ENODEV;
1295 goto out;
1296 }
1297
1298 ret = bq24190_register_reset(bdi);
1299 if (ret < 0)
1300 goto out;
1301
1302 ret = bq24190_set_mode_host(bdi);
1303out:
1304 pm_runtime_put_sync(bdi->dev);
1305 return ret;
1306}
1307
1308#ifdef CONFIG_OF
1309static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
1310{
1311 bdi->irq = irq_of_parse_and_map(bdi->dev->of_node, 0);
1312 if (bdi->irq <= 0)
1313 return -1;
1314
1315 return 0;
1316}
1317#else
1318static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
1319{
1320 return -1;
1321}
1322#endif
1323
1324static int bq24190_setup_pdata(struct bq24190_dev_info *bdi,
1325 struct bq24190_platform_data *pdata)
1326{
1327 int ret;
1328
1329 if (!gpio_is_valid(pdata->gpio_int))
1330 return -1;
1331
1332 ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
1333 if (ret < 0)
1334 return -1;
1335
1336 ret = gpio_direction_input(pdata->gpio_int);
1337 if (ret < 0)
1338 goto out;
1339
1340 bdi->irq = gpio_to_irq(pdata->gpio_int);
1341 if (!bdi->irq)
1342 goto out;
1343
1344 bdi->gpio_int = pdata->gpio_int;
1345 return 0;
1346
1347out:
1348 gpio_free(pdata->gpio_int);
1349 return -1;
1350}
1351
1352static int bq24190_probe(struct i2c_client *client,
1353 const struct i2c_device_id *id)
1354{
1355 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1356 struct device *dev = &client->dev;
1357 struct bq24190_platform_data *pdata = client->dev.platform_data;
1358 struct power_supply_config charger_cfg = {}, battery_cfg = {};
1359 struct bq24190_dev_info *bdi;
1360 int ret;
1361
1362 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
1363 dev_err(dev, "No support for SMBUS_BYTE_DATA\n");
1364 return -ENODEV;
1365 }
1366
1367 bdi = devm_kzalloc(dev, sizeof(*bdi), GFP_KERNEL);
1368 if (!bdi) {
1369 dev_err(dev, "Can't alloc bdi struct\n");
1370 return -ENOMEM;
1371 }
1372
1373 bdi->client = client;
1374 bdi->dev = dev;
1375 bdi->model = id->driver_data;
1376 strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
1377 mutex_init(&bdi->f_reg_lock);
1378 bdi->first_time = true;
1379 bdi->charger_health_valid = false;
1380 bdi->battery_health_valid = false;
1381 bdi->battery_status_valid = false;
1382
1383 i2c_set_clientdata(client, bdi);
1384
1385 if (dev->of_node)
1386 ret = bq24190_setup_dt(bdi);
1387 else
1388 ret = bq24190_setup_pdata(bdi, pdata);
1389
1390 if (ret) {
1391 dev_err(dev, "Can't get irq info\n");
1392 return -EINVAL;
1393 }
1394
1395 ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
1396 bq24190_irq_handler_thread,
1397 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
1398 "bq24190-charger", bdi);
1399 if (ret < 0) {
1400 dev_err(dev, "Can't set up irq handler\n");
1401 goto out1;
1402 }
1403
1404 pm_runtime_enable(dev);
1405 pm_runtime_resume(dev);
1406
1407 ret = bq24190_hw_init(bdi);
1408 if (ret < 0) {
1409 dev_err(dev, "Hardware init failed\n");
1410 goto out2;
1411 }
1412
1413 charger_cfg.drv_data = bdi;
1414 charger_cfg.supplied_to = bq24190_charger_supplied_to;
1415 charger_cfg.num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to),
1416 bdi->charger = power_supply_register(dev, &bq24190_charger_desc,
1417 &charger_cfg);
1418 if (IS_ERR(bdi->charger)) {
1419 dev_err(dev, "Can't register charger\n");
1420 ret = PTR_ERR(bdi->charger);
1421 goto out2;
1422 }
1423
1424 battery_cfg.drv_data = bdi;
1425 bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
1426 &battery_cfg);
1427 if (IS_ERR(bdi->battery)) {
1428 dev_err(dev, "Can't register battery\n");
1429 ret = PTR_ERR(bdi->battery);
1430 goto out3;
1431 }
1432
1433 ret = bq24190_sysfs_create_group(bdi);
1434 if (ret) {
1435 dev_err(dev, "Can't create sysfs entries\n");
1436 goto out4;
1437 }
1438
1439 return 0;
1440
1441out4:
1442 power_supply_unregister(bdi->battery);
1443out3:
1444 power_supply_unregister(bdi->charger);
1445out2:
1446 pm_runtime_disable(dev);
1447out1:
1448 if (bdi->gpio_int)
1449 gpio_free(bdi->gpio_int);
1450
1451 return ret;
1452}
1453
1454static int bq24190_remove(struct i2c_client *client)
1455{
1456 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1457
1458 pm_runtime_get_sync(bdi->dev);
1459 bq24190_register_reset(bdi);
1460 pm_runtime_put_sync(bdi->dev);
1461
1462 bq24190_sysfs_remove_group(bdi);
1463 power_supply_unregister(bdi->battery);
1464 power_supply_unregister(bdi->charger);
1465 pm_runtime_disable(bdi->dev);
1466
1467 if (bdi->gpio_int)
1468 gpio_free(bdi->gpio_int);
1469
1470 return 0;
1471}
1472
1473#ifdef CONFIG_PM_SLEEP
1474static int bq24190_pm_suspend(struct device *dev)
1475{
1476 struct i2c_client *client = to_i2c_client(dev);
1477 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1478
1479 pm_runtime_get_sync(bdi->dev);
1480 bq24190_register_reset(bdi);
1481 pm_runtime_put_sync(bdi->dev);
1482
1483 return 0;
1484}
1485
1486static int bq24190_pm_resume(struct device *dev)
1487{
1488 struct i2c_client *client = to_i2c_client(dev);
1489 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1490
1491 bdi->charger_health_valid = false;
1492 bdi->battery_health_valid = false;
1493 bdi->battery_status_valid = false;
1494
1495 pm_runtime_get_sync(bdi->dev);
1496 bq24190_register_reset(bdi);
1497 pm_runtime_put_sync(bdi->dev);
1498
1499
1500 power_supply_changed(bdi->charger);
1501 power_supply_changed(bdi->battery);
1502
1503 return 0;
1504}
1505#endif
1506
1507static SIMPLE_DEV_PM_OPS(bq24190_pm_ops, bq24190_pm_suspend, bq24190_pm_resume);
1508
1509
1510
1511
1512
1513
1514static const struct i2c_device_id bq24190_i2c_ids[] = {
1515 { "bq24190", BQ24190_REG_VPRS_PN_24190 },
1516 { },
1517};
1518MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
1519
1520#ifdef CONFIG_OF
1521static const struct of_device_id bq24190_of_match[] = {
1522 { .compatible = "ti,bq24190", },
1523 { },
1524};
1525MODULE_DEVICE_TABLE(of, bq24190_of_match);
1526#else
1527static const struct of_device_id bq24190_of_match[] = {
1528 { },
1529};
1530#endif
1531
1532static struct i2c_driver bq24190_driver = {
1533 .probe = bq24190_probe,
1534 .remove = bq24190_remove,
1535 .id_table = bq24190_i2c_ids,
1536 .driver = {
1537 .name = "bq24190-charger",
1538 .pm = &bq24190_pm_ops,
1539 .of_match_table = of_match_ptr(bq24190_of_match),
1540 },
1541};
1542module_i2c_driver(bq24190_driver);
1543
1544MODULE_LICENSE("GPL");
1545MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");
1546MODULE_DESCRIPTION("TI BQ24190 Charger Driver");
1547