1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ROHM BD99954 charger driver |
4 | * |
5 | * Copyright (C) 2020 Rohm Semiconductors |
6 | * Originally written by: |
7 | * Mikko Mutanen <mikko.mutanen@fi.rohmeurope.com> |
8 | * Markus Laine <markus.laine@fi.rohmeurope.com> |
9 | * Bugs added by: |
10 | * Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> |
11 | */ |
12 | |
13 | /* |
14 | * The battery charging profile of BD99954. |
15 | * |
16 | * Curve (1) represents charging current. |
17 | * Curve (2) represents battery voltage. |
18 | * |
19 | * The BD99954 data sheet divides charging to three phases. |
20 | * a) Trickle-charge with constant current (8). |
21 | * b) pre-charge with constant current (6) |
22 | * c) fast-charge, first with constant current (5) phase. After |
23 | * the battery voltage has reached target level (4) we have constant |
24 | * voltage phase until charging current has dropped to termination |
25 | * level (7) |
26 | * |
27 | * V ^ ^ I |
28 | * . . |
29 | * . . |
30 | *(4)` `.` ` ` ` ` ` ` ` ` ` ` ` ` ` ----------------------------. |
31 | * . :/ . |
32 | * . o----+/:/ ` ` ` ` ` ` ` ` ` ` ` ` `.` ` (5) |
33 | * . + :: + . |
34 | * . + /- -- . |
35 | * . +`/- + . |
36 | * . o/- -: . |
37 | * . .s. +` . |
38 | * . .--+ `/ . |
39 | * . ..`` + .: . |
40 | * . -` + -- . |
41 | * . (2) ...`` + :- . |
42 | * . ...`` + -: . |
43 | *(3)` `.`."" ` ` ` `+-------- ` ` ` ` ` ` `.:` ` ` ` ` ` ` ` ` .` ` (6) |
44 | * . + `:. . |
45 | * . + -: . |
46 | * . + -:. . |
47 | * . + .--. . |
48 | * . (1) + `.+` ` ` `.` ` (7) |
49 | * -..............` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` + ` ` ` .` ` (8) |
50 | * . + - |
51 | * -------------------------------------------------+++++++++--> |
52 | * | trickle | pre | fast | |
53 | * |
54 | * Details of DT properties for different limits can be found from BD99954 |
55 | * device tree binding documentation. |
56 | */ |
57 | |
58 | #include <linux/delay.h> |
59 | #include <linux/gpio/consumer.h> |
60 | #include <linux/interrupt.h> |
61 | #include <linux/i2c.h> |
62 | #include <linux/kernel.h> |
63 | #include <linux/linear_range.h> |
64 | #include <linux/module.h> |
65 | #include <linux/mod_devicetable.h> |
66 | #include <linux/power_supply.h> |
67 | #include <linux/property.h> |
68 | #include <linux/regmap.h> |
69 | #include <linux/types.h> |
70 | |
71 | #include "bd99954-charger.h" |
72 | |
73 | struct battery_data { |
74 | u16 precharge_current; /* Trickle-charge Current */ |
75 | u16 fc_reg_voltage; /* Fast Charging Regulation Voltage */ |
76 | u16 voltage_min; |
77 | u16 voltage_max; |
78 | }; |
79 | |
80 | /* Initial field values, converted to initial register values */ |
81 | struct bd9995x_init_data { |
82 | u16 vsysreg_set; /* VSYS Regulation Setting */ |
83 | u16 ibus_lim_set; /* VBUS input current limitation */ |
84 | u16 icc_lim_set; /* VCC/VACP Input Current Limit Setting */ |
85 | u16 itrich_set; /* Trickle-charge Current Setting */ |
86 | u16 iprech_set; /* Pre-Charge Current Setting */ |
87 | u16 ichg_set; /* Fast-Charge constant current */ |
88 | u16 vfastchg_reg_set1; /* Fast Charging Regulation Voltage */ |
89 | u16 vprechg_th_set; /* Pre-charge Voltage Threshold Setting */ |
90 | u16 vrechg_set; /* Re-charge Battery Voltage Setting */ |
91 | u16 vbatovp_set; /* Battery Over Voltage Threshold Setting */ |
92 | u16 iterm_set; /* Charging termination current */ |
93 | }; |
94 | |
95 | struct bd9995x_state { |
96 | u8 online; |
97 | u16 chgstm_status; |
98 | u16 vbat_vsys_status; |
99 | u16 vbus_vcc_status; |
100 | }; |
101 | |
102 | struct bd9995x_device { |
103 | struct i2c_client *client; |
104 | struct device *dev; |
105 | struct power_supply *charger; |
106 | |
107 | struct regmap *rmap; |
108 | struct regmap_field *rmap_fields[F_MAX_FIELDS]; |
109 | |
110 | int chip_id; |
111 | int chip_rev; |
112 | struct bd9995x_init_data init_data; |
113 | struct bd9995x_state state; |
114 | |
115 | struct mutex lock; /* Protect state data */ |
116 | }; |
117 | |
118 | static const struct regmap_range bd9995x_readonly_reg_ranges[] = { |
119 | regmap_reg_range(CHGSTM_STATUS, SEL_ILIM_VAL), |
120 | regmap_reg_range(IOUT_DACIN_VAL, IOUT_DACIN_VAL), |
121 | regmap_reg_range(VCC_UCD_STATUS, VCC_IDD_STATUS), |
122 | regmap_reg_range(VBUS_UCD_STATUS, VBUS_IDD_STATUS), |
123 | regmap_reg_range(CHIP_ID, CHIP_REV), |
124 | regmap_reg_range(SYSTEM_STATUS, SYSTEM_STATUS), |
125 | regmap_reg_range(IBATP_VAL, VBAT_AVE_VAL), |
126 | regmap_reg_range(VTH_VAL, EXTIADP_AVE_VAL), |
127 | }; |
128 | |
129 | static const struct regmap_access_table bd9995x_writeable_regs = { |
130 | .no_ranges = bd9995x_readonly_reg_ranges, |
131 | .n_no_ranges = ARRAY_SIZE(bd9995x_readonly_reg_ranges), |
132 | }; |
133 | |
134 | static const struct regmap_range bd9995x_volatile_reg_ranges[] = { |
135 | regmap_reg_range(CHGSTM_STATUS, WDT_STATUS), |
136 | regmap_reg_range(VCC_UCD_STATUS, VCC_IDD_STATUS), |
137 | regmap_reg_range(VBUS_UCD_STATUS, VBUS_IDD_STATUS), |
138 | regmap_reg_range(INT0_STATUS, INT7_STATUS), |
139 | regmap_reg_range(SYSTEM_STATUS, SYSTEM_CTRL_SET), |
140 | regmap_reg_range(IBATP_VAL, EXTIADP_AVE_VAL), /* Measurement regs */ |
141 | }; |
142 | |
143 | static const struct regmap_access_table bd9995x_volatile_regs = { |
144 | .yes_ranges = bd9995x_volatile_reg_ranges, |
145 | .n_yes_ranges = ARRAY_SIZE(bd9995x_volatile_reg_ranges), |
146 | }; |
147 | |
148 | static const struct regmap_range_cfg regmap_range_cfg[] = { |
149 | { |
150 | .selector_reg = MAP_SET, |
151 | .selector_mask = 0xFFFF, |
152 | .selector_shift = 0, |
153 | .window_start = 0, |
154 | .window_len = 0x100, |
155 | .range_min = 0 * 0x100, |
156 | .range_max = 3 * 0x100, |
157 | }, |
158 | }; |
159 | |
160 | static const struct regmap_config bd9995x_regmap_config = { |
161 | .reg_bits = 8, |
162 | .val_bits = 16, |
163 | .reg_stride = 1, |
164 | |
165 | .max_register = 3 * 0x100, |
166 | .cache_type = REGCACHE_RBTREE, |
167 | |
168 | .ranges = regmap_range_cfg, |
169 | .num_ranges = ARRAY_SIZE(regmap_range_cfg), |
170 | .val_format_endian = REGMAP_ENDIAN_LITTLE, |
171 | .wr_table = &bd9995x_writeable_regs, |
172 | .volatile_table = &bd9995x_volatile_regs, |
173 | }; |
174 | |
175 | enum bd9995x_chrg_fault { |
176 | CHRG_FAULT_NORMAL, |
177 | CHRG_FAULT_INPUT, |
178 | CHRG_FAULT_THERMAL_SHUTDOWN, |
179 | CHRG_FAULT_TIMER_EXPIRED, |
180 | }; |
181 | |
182 | static int bd9995x_get_prop_batt_health(struct bd9995x_device *bd) |
183 | { |
184 | int ret, tmp; |
185 | |
186 | ret = regmap_field_read(field: bd->rmap_fields[F_BATTEMP], val: &tmp); |
187 | if (ret) |
188 | return POWER_SUPPLY_HEALTH_UNKNOWN; |
189 | |
190 | /* TODO: Check these against datasheet page 34 */ |
191 | |
192 | switch (tmp) { |
193 | case ROOM: |
194 | return POWER_SUPPLY_HEALTH_GOOD; |
195 | case HOT1: |
196 | case HOT2: |
197 | case HOT3: |
198 | return POWER_SUPPLY_HEALTH_OVERHEAT; |
199 | case COLD1: |
200 | case COLD2: |
201 | return POWER_SUPPLY_HEALTH_COLD; |
202 | case TEMP_DIS: |
203 | case BATT_OPEN: |
204 | default: |
205 | return POWER_SUPPLY_HEALTH_UNKNOWN; |
206 | } |
207 | } |
208 | |
209 | static int bd9995x_get_prop_charge_type(struct bd9995x_device *bd) |
210 | { |
211 | int ret, tmp; |
212 | |
213 | ret = regmap_field_read(field: bd->rmap_fields[F_CHGSTM_STATE], val: &tmp); |
214 | if (ret) |
215 | return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; |
216 | |
217 | switch (tmp) { |
218 | case CHGSTM_TRICKLE_CHARGE: |
219 | case CHGSTM_PRE_CHARGE: |
220 | return POWER_SUPPLY_CHARGE_TYPE_TRICKLE; |
221 | case CHGSTM_FAST_CHARGE: |
222 | return POWER_SUPPLY_CHARGE_TYPE_FAST; |
223 | case CHGSTM_TOP_OFF: |
224 | case CHGSTM_DONE: |
225 | case CHGSTM_SUSPEND: |
226 | return POWER_SUPPLY_CHARGE_TYPE_NONE; |
227 | default: /* Rest of the states are error related, no charging */ |
228 | return POWER_SUPPLY_CHARGE_TYPE_NONE; |
229 | } |
230 | } |
231 | |
232 | static bool bd9995x_get_prop_batt_present(struct bd9995x_device *bd) |
233 | { |
234 | int ret, tmp; |
235 | |
236 | ret = regmap_field_read(field: bd->rmap_fields[F_BATTEMP], val: &tmp); |
237 | if (ret) |
238 | return false; |
239 | |
240 | return tmp != BATT_OPEN; |
241 | } |
242 | |
243 | static int bd9995x_get_prop_batt_voltage(struct bd9995x_device *bd) |
244 | { |
245 | int ret, tmp; |
246 | |
247 | ret = regmap_field_read(field: bd->rmap_fields[F_VBAT_VAL], val: &tmp); |
248 | if (ret) |
249 | return 0; |
250 | |
251 | tmp = min(tmp, 19200); |
252 | |
253 | return tmp * 1000; |
254 | } |
255 | |
256 | static int bd9995x_get_prop_batt_current(struct bd9995x_device *bd) |
257 | { |
258 | int ret, tmp; |
259 | |
260 | ret = regmap_field_read(field: bd->rmap_fields[F_IBATP_VAL], val: &tmp); |
261 | if (ret) |
262 | return 0; |
263 | |
264 | return tmp * 1000; |
265 | } |
266 | |
267 | #define DEFAULT_BATTERY_TEMPERATURE 250 |
268 | |
269 | static int bd9995x_get_prop_batt_temp(struct bd9995x_device *bd) |
270 | { |
271 | int ret, tmp; |
272 | |
273 | ret = regmap_field_read(field: bd->rmap_fields[F_THERM_VAL], val: &tmp); |
274 | if (ret) |
275 | return DEFAULT_BATTERY_TEMPERATURE; |
276 | |
277 | return (200 - tmp) * 10; |
278 | } |
279 | |
280 | static int bd9995x_power_supply_get_property(struct power_supply *psy, |
281 | enum power_supply_property psp, |
282 | union power_supply_propval *val) |
283 | { |
284 | int ret, tmp; |
285 | struct bd9995x_device *bd = power_supply_get_drvdata(psy); |
286 | struct bd9995x_state state; |
287 | |
288 | mutex_lock(&bd->lock); |
289 | state = bd->state; |
290 | mutex_unlock(lock: &bd->lock); |
291 | |
292 | switch (psp) { |
293 | case POWER_SUPPLY_PROP_STATUS: |
294 | switch (state.chgstm_status) { |
295 | case CHGSTM_TRICKLE_CHARGE: |
296 | case CHGSTM_PRE_CHARGE: |
297 | case CHGSTM_FAST_CHARGE: |
298 | case CHGSTM_TOP_OFF: |
299 | val->intval = POWER_SUPPLY_STATUS_CHARGING; |
300 | break; |
301 | |
302 | case CHGSTM_DONE: |
303 | val->intval = POWER_SUPPLY_STATUS_FULL; |
304 | break; |
305 | |
306 | case CHGSTM_SUSPEND: |
307 | case CHGSTM_TEMPERATURE_ERROR_1: |
308 | case CHGSTM_TEMPERATURE_ERROR_2: |
309 | case CHGSTM_TEMPERATURE_ERROR_3: |
310 | case CHGSTM_TEMPERATURE_ERROR_4: |
311 | case CHGSTM_TEMPERATURE_ERROR_5: |
312 | case CHGSTM_TEMPERATURE_ERROR_6: |
313 | case CHGSTM_TEMPERATURE_ERROR_7: |
314 | case CHGSTM_THERMAL_SHUT_DOWN_1: |
315 | case CHGSTM_THERMAL_SHUT_DOWN_2: |
316 | case CHGSTM_THERMAL_SHUT_DOWN_3: |
317 | case CHGSTM_THERMAL_SHUT_DOWN_4: |
318 | case CHGSTM_THERMAL_SHUT_DOWN_5: |
319 | case CHGSTM_THERMAL_SHUT_DOWN_6: |
320 | case CHGSTM_THERMAL_SHUT_DOWN_7: |
321 | case CHGSTM_BATTERY_ERROR: |
322 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; |
323 | break; |
324 | |
325 | default: |
326 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; |
327 | break; |
328 | } |
329 | break; |
330 | |
331 | case POWER_SUPPLY_PROP_MANUFACTURER: |
332 | val->strval = BD9995X_MANUFACTURER; |
333 | break; |
334 | |
335 | case POWER_SUPPLY_PROP_ONLINE: |
336 | val->intval = state.online; |
337 | break; |
338 | |
339 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: |
340 | ret = regmap_field_read(field: bd->rmap_fields[F_IBATP_VAL], val: &tmp); |
341 | if (ret) |
342 | return ret; |
343 | val->intval = tmp * 1000; |
344 | break; |
345 | |
346 | case POWER_SUPPLY_PROP_CHARGE_AVG: |
347 | ret = regmap_field_read(field: bd->rmap_fields[F_IBATP_AVE_VAL], val: &tmp); |
348 | if (ret) |
349 | return ret; |
350 | val->intval = tmp * 1000; |
351 | break; |
352 | |
353 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: |
354 | /* |
355 | * Currently the DT uses this property to give the |
356 | * target current for fast-charging constant current phase. |
357 | * I think it is correct in a sense. |
358 | * |
359 | * Yet, this prop we read and return here is the programmed |
360 | * safety limit for combined input currents. This feels |
361 | * also correct in a sense. |
362 | * |
363 | * However, this results a mismatch to DT value and value |
364 | * read from sysfs. |
365 | */ |
366 | ret = regmap_field_read(field: bd->rmap_fields[F_SEL_ILIM_VAL], val: &tmp); |
367 | if (ret) |
368 | return ret; |
369 | val->intval = tmp * 1000; |
370 | break; |
371 | |
372 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: |
373 | if (!state.online) { |
374 | val->intval = 0; |
375 | break; |
376 | } |
377 | |
378 | ret = regmap_field_read(field: bd->rmap_fields[F_VFASTCHG_REG_SET1], |
379 | val: &tmp); |
380 | if (ret) |
381 | return ret; |
382 | |
383 | /* |
384 | * The actual range : 2560 to 19200 mV. No matter what the |
385 | * register says |
386 | */ |
387 | val->intval = clamp_val(tmp << 4, 2560, 19200); |
388 | val->intval *= 1000; |
389 | break; |
390 | |
391 | case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: |
392 | ret = regmap_field_read(field: bd->rmap_fields[F_ITERM_SET], val: &tmp); |
393 | if (ret) |
394 | return ret; |
395 | /* Start step is 64 mA */ |
396 | val->intval = tmp << 6; |
397 | /* Maximum is 1024 mA - no matter what register says */ |
398 | val->intval = min(val->intval, 1024); |
399 | val->intval *= 1000; |
400 | break; |
401 | |
402 | /* Battery properties which we access through charger */ |
403 | case POWER_SUPPLY_PROP_PRESENT: |
404 | val->intval = bd9995x_get_prop_batt_present(bd); |
405 | break; |
406 | |
407 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
408 | val->intval = bd9995x_get_prop_batt_voltage(bd); |
409 | break; |
410 | |
411 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
412 | val->intval = bd9995x_get_prop_batt_current(bd); |
413 | break; |
414 | |
415 | case POWER_SUPPLY_PROP_CHARGE_TYPE: |
416 | val->intval = bd9995x_get_prop_charge_type(bd); |
417 | break; |
418 | |
419 | case POWER_SUPPLY_PROP_HEALTH: |
420 | val->intval = bd9995x_get_prop_batt_health(bd); |
421 | break; |
422 | |
423 | case POWER_SUPPLY_PROP_TEMP: |
424 | val->intval = bd9995x_get_prop_batt_temp(bd); |
425 | break; |
426 | |
427 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
428 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; |
429 | break; |
430 | |
431 | case POWER_SUPPLY_PROP_MODEL_NAME: |
432 | val->strval = "bd99954" ; |
433 | break; |
434 | |
435 | default: |
436 | return -EINVAL; |
437 | |
438 | } |
439 | |
440 | return 0; |
441 | } |
442 | |
443 | static int bd9995x_get_chip_state(struct bd9995x_device *bd, |
444 | struct bd9995x_state *state) |
445 | { |
446 | int i, ret, tmp; |
447 | struct { |
448 | struct regmap_field *id; |
449 | u16 *data; |
450 | } state_fields[] = { |
451 | { |
452 | bd->rmap_fields[F_CHGSTM_STATE], &state->chgstm_status, |
453 | }, { |
454 | bd->rmap_fields[F_VBAT_VSYS_STATUS], |
455 | &state->vbat_vsys_status, |
456 | }, { |
457 | bd->rmap_fields[F_VBUS_VCC_STATUS], |
458 | &state->vbus_vcc_status, |
459 | }, |
460 | }; |
461 | |
462 | |
463 | for (i = 0; i < ARRAY_SIZE(state_fields); i++) { |
464 | ret = regmap_field_read(field: state_fields[i].id, val: &tmp); |
465 | if (ret) |
466 | return ret; |
467 | |
468 | *state_fields[i].data = tmp; |
469 | } |
470 | |
471 | if (state->vbus_vcc_status & STATUS_VCC_DET || |
472 | state->vbus_vcc_status & STATUS_VBUS_DET) |
473 | state->online = 1; |
474 | else |
475 | state->online = 0; |
476 | |
477 | return 0; |
478 | } |
479 | |
480 | static irqreturn_t bd9995x_irq_handler_thread(int irq, void *private) |
481 | { |
482 | struct bd9995x_device *bd = private; |
483 | int ret, status, mask, i; |
484 | unsigned long tmp; |
485 | struct bd9995x_state state; |
486 | |
487 | /* |
488 | * The bd9995x does not seem to generate big amount of interrupts. |
489 | * The logic regarding which interrupts can cause relevant |
490 | * status changes seem to be pretty complex. |
491 | * |
492 | * So lets implement really simple and hopefully bullet-proof handler: |
493 | * It does not really matter which IRQ we handle, we just go and |
494 | * re-read all interesting statuses + give the framework a nudge. |
495 | * |
496 | * Other option would be building a _complex_ and error prone logic |
497 | * trying to decide what could have been changed (resulting this IRQ |
498 | * we are now handling). During the normal operation the BD99954 does |
499 | * not seem to be generating much of interrupts so benefit from such |
500 | * logic would probably be minimal. |
501 | */ |
502 | |
503 | ret = regmap_read(map: bd->rmap, INT0_STATUS, val: &status); |
504 | if (ret) { |
505 | dev_err(bd->dev, "Failed to read IRQ status\n" ); |
506 | return IRQ_NONE; |
507 | } |
508 | |
509 | ret = regmap_field_read(field: bd->rmap_fields[F_INT0_SET], val: &mask); |
510 | if (ret) { |
511 | dev_err(bd->dev, "Failed to read IRQ mask\n" ); |
512 | return IRQ_NONE; |
513 | } |
514 | |
515 | /* Handle only IRQs that are not masked */ |
516 | status &= mask; |
517 | tmp = status; |
518 | |
519 | /* Lowest bit does not represent any sub-registers */ |
520 | tmp >>= 1; |
521 | |
522 | /* |
523 | * Mask and ack IRQs we will handle (+ the idiot bit) |
524 | */ |
525 | ret = regmap_field_write(field: bd->rmap_fields[F_INT0_SET], val: 0); |
526 | if (ret) { |
527 | dev_err(bd->dev, "Failed to mask F_INT0\n" ); |
528 | return IRQ_NONE; |
529 | } |
530 | |
531 | ret = regmap_write(map: bd->rmap, INT0_STATUS, val: status); |
532 | if (ret) { |
533 | dev_err(bd->dev, "Failed to ack F_INT0\n" ); |
534 | goto err_umask; |
535 | } |
536 | |
537 | for_each_set_bit(i, &tmp, 7) { |
538 | int sub_status, sub_mask; |
539 | static const int sub_status_reg[] = { |
540 | INT1_STATUS, INT2_STATUS, INT3_STATUS, INT4_STATUS, |
541 | INT5_STATUS, INT6_STATUS, INT7_STATUS, |
542 | }; |
543 | struct regmap_field *sub_mask_f[] = { |
544 | bd->rmap_fields[F_INT1_SET], |
545 | bd->rmap_fields[F_INT2_SET], |
546 | bd->rmap_fields[F_INT3_SET], |
547 | bd->rmap_fields[F_INT4_SET], |
548 | bd->rmap_fields[F_INT5_SET], |
549 | bd->rmap_fields[F_INT6_SET], |
550 | bd->rmap_fields[F_INT7_SET], |
551 | }; |
552 | |
553 | /* Clear sub IRQs */ |
554 | ret = regmap_read(map: bd->rmap, reg: sub_status_reg[i], val: &sub_status); |
555 | if (ret) { |
556 | dev_err(bd->dev, "Failed to read IRQ sub-status\n" ); |
557 | goto err_umask; |
558 | } |
559 | |
560 | ret = regmap_field_read(field: sub_mask_f[i], val: &sub_mask); |
561 | if (ret) { |
562 | dev_err(bd->dev, "Failed to read IRQ sub-mask\n" ); |
563 | goto err_umask; |
564 | } |
565 | |
566 | /* Ack active sub-statuses */ |
567 | sub_status &= sub_mask; |
568 | |
569 | ret = regmap_write(map: bd->rmap, reg: sub_status_reg[i], val: sub_status); |
570 | if (ret) { |
571 | dev_err(bd->dev, "Failed to ack sub-IRQ\n" ); |
572 | goto err_umask; |
573 | } |
574 | } |
575 | |
576 | ret = regmap_field_write(field: bd->rmap_fields[F_INT0_SET], val: mask); |
577 | if (ret) |
578 | /* May as well retry once */ |
579 | goto err_umask; |
580 | |
581 | /* Read whole chip state */ |
582 | ret = bd9995x_get_chip_state(bd, state: &state); |
583 | if (ret < 0) { |
584 | dev_err(bd->dev, "Failed to read chip state\n" ); |
585 | } else { |
586 | mutex_lock(&bd->lock); |
587 | bd->state = state; |
588 | mutex_unlock(lock: &bd->lock); |
589 | |
590 | power_supply_changed(psy: bd->charger); |
591 | } |
592 | |
593 | return IRQ_HANDLED; |
594 | |
595 | err_umask: |
596 | ret = regmap_field_write(field: bd->rmap_fields[F_INT0_SET], val: mask); |
597 | if (ret) |
598 | dev_err(bd->dev, |
599 | "Failed to un-mask F_INT0 - IRQ permanently disabled\n" ); |
600 | |
601 | return IRQ_NONE; |
602 | } |
603 | |
604 | static int __bd9995x_chip_reset(struct bd9995x_device *bd) |
605 | { |
606 | int ret, state; |
607 | int rst_check_counter = 10; |
608 | u16 tmp = ALLRST | OTPLD; |
609 | |
610 | ret = regmap_raw_write(map: bd->rmap, SYSTEM_CTRL_SET, val: &tmp, val_len: 2); |
611 | if (ret < 0) |
612 | return ret; |
613 | |
614 | do { |
615 | ret = regmap_field_read(field: bd->rmap_fields[F_OTPLD_STATE], val: &state); |
616 | if (ret) |
617 | return ret; |
618 | |
619 | msleep(msecs: 10); |
620 | } while (state == 0 && --rst_check_counter); |
621 | |
622 | if (!rst_check_counter) { |
623 | dev_err(bd->dev, "chip reset not completed\n" ); |
624 | return -ETIMEDOUT; |
625 | } |
626 | |
627 | tmp = 0; |
628 | ret = regmap_raw_write(map: bd->rmap, SYSTEM_CTRL_SET, val: &tmp, val_len: 2); |
629 | |
630 | return ret; |
631 | } |
632 | |
633 | static int bd9995x_hw_init(struct bd9995x_device *bd) |
634 | { |
635 | int ret; |
636 | int i; |
637 | struct bd9995x_state state; |
638 | struct bd9995x_init_data *id = &bd->init_data; |
639 | |
640 | const struct { |
641 | enum bd9995x_fields id; |
642 | u16 value; |
643 | } init_data[] = { |
644 | /* Enable the charging trigger after SDP charger attached */ |
645 | {F_SDP_CHG_TRIG_EN, 1}, |
646 | /* Enable charging trigger after SDP charger attached */ |
647 | {F_SDP_CHG_TRIG, 1}, |
648 | /* Disable charging trigger by BC1.2 detection */ |
649 | {F_VBUS_BC_DISEN, 1}, |
650 | /* Disable charging trigger by BC1.2 detection */ |
651 | {F_VCC_BC_DISEN, 1}, |
652 | /* Disable automatic limitation of the input current */ |
653 | {F_ILIM_AUTO_DISEN, 1}, |
654 | /* Select current limitation when SDP charger attached*/ |
655 | {F_SDP_500_SEL, 1}, |
656 | /* Select current limitation when DCP charger attached */ |
657 | {F_DCP_2500_SEL, 1}, |
658 | {F_VSYSREG_SET, id->vsysreg_set}, |
659 | /* Activate USB charging and DC/DC converter */ |
660 | {F_USB_SUS, 0}, |
661 | /* DCDC clock: 1200 kHz*/ |
662 | {F_DCDC_CLK_SEL, 3}, |
663 | /* Enable charging */ |
664 | {F_CHG_EN, 1}, |
665 | /* Disable Input current Limit setting voltage measurement */ |
666 | {F_EXTIADPEN, 0}, |
667 | /* Disable input current limiting */ |
668 | {F_VSYS_PRIORITY, 1}, |
669 | {F_IBUS_LIM_SET, id->ibus_lim_set}, |
670 | {F_ICC_LIM_SET, id->icc_lim_set}, |
671 | /* Charge Termination Current Setting to 0*/ |
672 | {F_ITERM_SET, id->iterm_set}, |
673 | /* Trickle-charge Current Setting */ |
674 | {F_ITRICH_SET, id->itrich_set}, |
675 | /* Pre-charge Current setting */ |
676 | {F_IPRECH_SET, id->iprech_set}, |
677 | /* Fast Charge Current for constant current phase */ |
678 | {F_ICHG_SET, id->ichg_set}, |
679 | /* Fast Charge Voltage Regulation Setting */ |
680 | {F_VFASTCHG_REG_SET1, id->vfastchg_reg_set1}, |
681 | /* Set Pre-charge Voltage Threshold for trickle charging. */ |
682 | {F_VPRECHG_TH_SET, id->vprechg_th_set}, |
683 | {F_VRECHG_SET, id->vrechg_set}, |
684 | {F_VBATOVP_SET, id->vbatovp_set}, |
685 | /* Reverse buck boost voltage Setting */ |
686 | {F_VRBOOST_SET, 0}, |
687 | /* Disable fast-charging watchdog */ |
688 | {F_WDT_FST, 0}, |
689 | /* Disable pre-charging watchdog */ |
690 | {F_WDT_PRE, 0}, |
691 | /* Power save off */ |
692 | {F_POWER_SAVE_MODE, 0}, |
693 | {F_INT1_SET, INT1_ALL}, |
694 | {F_INT2_SET, INT2_ALL}, |
695 | {F_INT3_SET, INT3_ALL}, |
696 | {F_INT4_SET, INT4_ALL}, |
697 | {F_INT5_SET, INT5_ALL}, |
698 | {F_INT6_SET, INT6_ALL}, |
699 | {F_INT7_SET, INT7_ALL}, |
700 | }; |
701 | |
702 | /* |
703 | * Currently we initialize charger to a known state at startup. |
704 | * If we want to allow for example the boot code to initialize |
705 | * charger we should get rid of this. |
706 | */ |
707 | ret = __bd9995x_chip_reset(bd); |
708 | if (ret < 0) |
709 | return ret; |
710 | |
711 | /* Initialize currents/voltages and other parameters */ |
712 | for (i = 0; i < ARRAY_SIZE(init_data); i++) { |
713 | ret = regmap_field_write(field: bd->rmap_fields[init_data[i].id], |
714 | val: init_data[i].value); |
715 | if (ret) { |
716 | dev_err(bd->dev, "failed to initialize charger (%d)\n" , |
717 | ret); |
718 | return ret; |
719 | } |
720 | } |
721 | |
722 | ret = bd9995x_get_chip_state(bd, state: &state); |
723 | if (ret < 0) |
724 | return ret; |
725 | |
726 | mutex_lock(&bd->lock); |
727 | bd->state = state; |
728 | mutex_unlock(lock: &bd->lock); |
729 | |
730 | return 0; |
731 | } |
732 | |
733 | static enum power_supply_property bd9995x_power_supply_props[] = { |
734 | POWER_SUPPLY_PROP_MANUFACTURER, |
735 | POWER_SUPPLY_PROP_STATUS, |
736 | POWER_SUPPLY_PROP_ONLINE, |
737 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, |
738 | POWER_SUPPLY_PROP_CHARGE_AVG, |
739 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, |
740 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, |
741 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, |
742 | /* Battery props we access through charger */ |
743 | POWER_SUPPLY_PROP_PRESENT, |
744 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
745 | POWER_SUPPLY_PROP_CURRENT_NOW, |
746 | POWER_SUPPLY_PROP_CHARGE_TYPE, |
747 | POWER_SUPPLY_PROP_HEALTH, |
748 | POWER_SUPPLY_PROP_TEMP, |
749 | POWER_SUPPLY_PROP_TECHNOLOGY, |
750 | POWER_SUPPLY_PROP_MODEL_NAME, |
751 | }; |
752 | |
753 | static const struct power_supply_desc bd9995x_power_supply_desc = { |
754 | .name = "bd9995x-charger" , |
755 | .type = POWER_SUPPLY_TYPE_USB, |
756 | .properties = bd9995x_power_supply_props, |
757 | .num_properties = ARRAY_SIZE(bd9995x_power_supply_props), |
758 | .get_property = bd9995x_power_supply_get_property, |
759 | }; |
760 | |
761 | /* |
762 | * Limit configurations for vbus-input-current and vcc-vacp-input-current |
763 | * Minimum limit is 0 uA. Max is 511 * 32000 uA = 16352000 uA. This is |
764 | * configured by writing a register so that each increment in register |
765 | * value equals to 32000 uA limit increment. |
766 | * |
767 | * Eg, value 0x0 is limit 0, value 0x1 is limit 32000, ... |
768 | * Describe the setting in linear_range table. |
769 | */ |
770 | static const struct linear_range input_current_limit_ranges[] = { |
771 | LINEAR_RANGE(0, 0x0, 0x1ff, 32000), |
772 | }; |
773 | |
774 | /* Possible trickle, pre-charging and termination current values */ |
775 | static const struct linear_range charging_current_ranges[] = { |
776 | LINEAR_RANGE(0, 0x0, 0x10, 64000), |
777 | LINEAR_RANGE(1024000, 0x11, 0x1f, 0), |
778 | }; |
779 | |
780 | /* |
781 | * Fast charging voltage regulation, starting re-charging limit |
782 | * and battery over voltage protection have same possible values |
783 | */ |
784 | static const struct linear_range charge_voltage_regulation_ranges[] = { |
785 | LINEAR_RANGE(2560000, 0, 0xA0, 0), |
786 | LINEAR_RANGE(2560000, 0xA0, 0x4B0, 16000), |
787 | LINEAR_RANGE(19200000, 0x4B0, 0x7FF, 0), |
788 | }; |
789 | |
790 | /* Possible VSYS voltage regulation values */ |
791 | static const struct linear_range vsys_voltage_regulation_ranges[] = { |
792 | LINEAR_RANGE(2560000, 0, 0x28, 0), |
793 | LINEAR_RANGE(2560000, 0x28, 0x12C, 64000), |
794 | LINEAR_RANGE(19200000, 0x12C, 0x1FF, 0), |
795 | }; |
796 | |
797 | /* Possible settings for switching from trickle to pre-charging limits */ |
798 | static const struct linear_range trickle_to_pre_threshold_ranges[] = { |
799 | LINEAR_RANGE(2048000, 0, 0x20, 0), |
800 | LINEAR_RANGE(2048000, 0x20, 0x12C, 64000), |
801 | LINEAR_RANGE(19200000, 0x12C, 0x1FF, 0), |
802 | }; |
803 | |
804 | /* Possible current values for fast-charging constant current phase */ |
805 | static const struct linear_range fast_charge_current_ranges[] = { |
806 | LINEAR_RANGE(0, 0, 0xFF, 64000), |
807 | }; |
808 | |
809 | struct battery_init { |
810 | const char *name; |
811 | int *info_data; |
812 | const struct linear_range *range; |
813 | int ranges; |
814 | u16 *data; |
815 | }; |
816 | |
817 | struct dt_init { |
818 | char *prop; |
819 | const struct linear_range *range; |
820 | int ranges; |
821 | u16 *data; |
822 | }; |
823 | |
824 | static int bd9995x_fw_probe(struct bd9995x_device *bd) |
825 | { |
826 | int ret; |
827 | struct power_supply_battery_info *info; |
828 | u32 property; |
829 | int i; |
830 | int regval; |
831 | bool found; |
832 | struct bd9995x_init_data *init = &bd->init_data; |
833 | struct battery_init battery_inits[] = { |
834 | { |
835 | .name = "trickle-charging current" , |
836 | .range = &charging_current_ranges[0], |
837 | .ranges = 2, |
838 | .data = &init->itrich_set, |
839 | }, { |
840 | .name = "pre-charging current" , |
841 | .range = &charging_current_ranges[0], |
842 | .ranges = 2, |
843 | .data = &init->iprech_set, |
844 | }, { |
845 | .name = "pre-to-trickle charge voltage threshold" , |
846 | .range = &trickle_to_pre_threshold_ranges[0], |
847 | .ranges = 2, |
848 | .data = &init->vprechg_th_set, |
849 | }, { |
850 | .name = "charging termination current" , |
851 | .range = &charging_current_ranges[0], |
852 | .ranges = 2, |
853 | .data = &init->iterm_set, |
854 | }, { |
855 | .name = "charging re-start voltage" , |
856 | .range = &charge_voltage_regulation_ranges[0], |
857 | .ranges = 2, |
858 | .data = &init->vrechg_set, |
859 | }, { |
860 | .name = "battery overvoltage limit" , |
861 | .range = &charge_voltage_regulation_ranges[0], |
862 | .ranges = 2, |
863 | .data = &init->vbatovp_set, |
864 | }, { |
865 | .name = "fast-charging max current" , |
866 | .range = &fast_charge_current_ranges[0], |
867 | .ranges = 1, |
868 | .data = &init->ichg_set, |
869 | }, { |
870 | .name = "fast-charging voltage" , |
871 | .range = &charge_voltage_regulation_ranges[0], |
872 | .ranges = 2, |
873 | .data = &init->vfastchg_reg_set1, |
874 | }, |
875 | }; |
876 | struct dt_init props[] = { |
877 | { |
878 | .prop = "rohm,vsys-regulation-microvolt" , |
879 | .range = &vsys_voltage_regulation_ranges[0], |
880 | .ranges = 2, |
881 | .data = &init->vsysreg_set, |
882 | }, { |
883 | .prop = "rohm,vbus-input-current-limit-microamp" , |
884 | .range = &input_current_limit_ranges[0], |
885 | .ranges = 1, |
886 | .data = &init->ibus_lim_set, |
887 | }, { |
888 | .prop = "rohm,vcc-input-current-limit-microamp" , |
889 | .range = &input_current_limit_ranges[0], |
890 | .ranges = 1, |
891 | .data = &init->icc_lim_set, |
892 | }, |
893 | }; |
894 | |
895 | /* |
896 | * The power_supply_get_battery_info() does not support getting values |
897 | * from ACPI. Let's fix it if ACPI is required here. |
898 | */ |
899 | ret = power_supply_get_battery_info(psy: bd->charger, info_out: &info); |
900 | if (ret < 0) |
901 | return ret; |
902 | |
903 | /* Put pointers to the generic battery info */ |
904 | battery_inits[0].info_data = &info->tricklecharge_current_ua; |
905 | battery_inits[1].info_data = &info->precharge_current_ua; |
906 | battery_inits[2].info_data = &info->precharge_voltage_max_uv; |
907 | battery_inits[3].info_data = &info->charge_term_current_ua; |
908 | battery_inits[4].info_data = &info->charge_restart_voltage_uv; |
909 | battery_inits[5].info_data = &info->overvoltage_limit_uv; |
910 | battery_inits[6].info_data = &info->constant_charge_current_max_ua; |
911 | battery_inits[7].info_data = &info->constant_charge_voltage_max_uv; |
912 | |
913 | for (i = 0; i < ARRAY_SIZE(battery_inits); i++) { |
914 | int val = *battery_inits[i].info_data; |
915 | const struct linear_range *range = battery_inits[i].range; |
916 | int ranges = battery_inits[i].ranges; |
917 | |
918 | if (val == -EINVAL) |
919 | continue; |
920 | |
921 | ret = linear_range_get_selector_low_array(r: range, ranges, val, |
922 | selector: ®val, found: &found); |
923 | if (ret) { |
924 | dev_err(bd->dev, "Unsupported value for %s\n" , |
925 | battery_inits[i].name); |
926 | |
927 | power_supply_put_battery_info(psy: bd->charger, info); |
928 | return -EINVAL; |
929 | } |
930 | if (!found) { |
931 | dev_warn(bd->dev, |
932 | "Unsupported value for %s - using smaller\n" , |
933 | battery_inits[i].name); |
934 | } |
935 | *(battery_inits[i].data) = regval; |
936 | } |
937 | |
938 | power_supply_put_battery_info(psy: bd->charger, info); |
939 | |
940 | for (i = 0; i < ARRAY_SIZE(props); i++) { |
941 | ret = device_property_read_u32(dev: bd->dev, propname: props[i].prop, |
942 | val: &property); |
943 | if (ret < 0) { |
944 | dev_err(bd->dev, "failed to read %s" , props[i].prop); |
945 | |
946 | return ret; |
947 | } |
948 | |
949 | ret = linear_range_get_selector_low_array(r: props[i].range, |
950 | ranges: props[i].ranges, |
951 | val: property, selector: ®val, |
952 | found: &found); |
953 | if (ret) { |
954 | dev_err(bd->dev, "Unsupported value for '%s'\n" , |
955 | props[i].prop); |
956 | |
957 | return -EINVAL; |
958 | } |
959 | |
960 | if (!found) { |
961 | dev_warn(bd->dev, |
962 | "Unsupported value for '%s' - using smaller\n" , |
963 | props[i].prop); |
964 | } |
965 | |
966 | *(props[i].data) = regval; |
967 | } |
968 | |
969 | return 0; |
970 | } |
971 | |
972 | static void bd9995x_chip_reset(void *bd) |
973 | { |
974 | __bd9995x_chip_reset(bd); |
975 | } |
976 | |
977 | static int bd9995x_probe(struct i2c_client *client) |
978 | { |
979 | struct device *dev = &client->dev; |
980 | struct bd9995x_device *bd; |
981 | struct power_supply_config psy_cfg = {}; |
982 | int ret; |
983 | int i; |
984 | |
985 | bd = devm_kzalloc(dev, size: sizeof(*bd), GFP_KERNEL); |
986 | if (!bd) |
987 | return -ENOMEM; |
988 | |
989 | bd->client = client; |
990 | bd->dev = dev; |
991 | psy_cfg.drv_data = bd; |
992 | psy_cfg.of_node = dev->of_node; |
993 | |
994 | mutex_init(&bd->lock); |
995 | |
996 | bd->rmap = devm_regmap_init_i2c(client, &bd9995x_regmap_config); |
997 | if (IS_ERR(ptr: bd->rmap)) { |
998 | dev_err(dev, "Failed to setup register access via i2c\n" ); |
999 | return PTR_ERR(ptr: bd->rmap); |
1000 | } |
1001 | |
1002 | for (i = 0; i < ARRAY_SIZE(bd9995x_reg_fields); i++) { |
1003 | const struct reg_field *reg_fields = bd9995x_reg_fields; |
1004 | |
1005 | bd->rmap_fields[i] = devm_regmap_field_alloc(dev, regmap: bd->rmap, |
1006 | reg_field: reg_fields[i]); |
1007 | if (IS_ERR(ptr: bd->rmap_fields[i])) { |
1008 | dev_err(dev, "cannot allocate regmap field\n" ); |
1009 | return PTR_ERR(ptr: bd->rmap_fields[i]); |
1010 | } |
1011 | } |
1012 | |
1013 | i2c_set_clientdata(client, data: bd); |
1014 | |
1015 | ret = regmap_field_read(field: bd->rmap_fields[F_CHIP_ID], val: &bd->chip_id); |
1016 | if (ret) { |
1017 | dev_err(dev, "Cannot read chip ID.\n" ); |
1018 | return ret; |
1019 | } |
1020 | |
1021 | if (bd->chip_id != BD99954_ID) { |
1022 | dev_err(dev, "Chip with ID=0x%x, not supported!\n" , |
1023 | bd->chip_id); |
1024 | return -ENODEV; |
1025 | } |
1026 | |
1027 | ret = regmap_field_read(field: bd->rmap_fields[F_CHIP_REV], val: &bd->chip_rev); |
1028 | if (ret) { |
1029 | dev_err(dev, "Cannot read revision.\n" ); |
1030 | return ret; |
1031 | } |
1032 | |
1033 | dev_info(bd->dev, "Found BD99954 chip rev %d\n" , bd->chip_rev); |
1034 | |
1035 | /* |
1036 | * We need to init the psy before we can call |
1037 | * power_supply_get_battery_info() for it |
1038 | */ |
1039 | bd->charger = devm_power_supply_register(parent: bd->dev, |
1040 | desc: &bd9995x_power_supply_desc, |
1041 | cfg: &psy_cfg); |
1042 | if (IS_ERR(ptr: bd->charger)) { |
1043 | dev_err(dev, "Failed to register power supply\n" ); |
1044 | return PTR_ERR(ptr: bd->charger); |
1045 | } |
1046 | |
1047 | ret = bd9995x_fw_probe(bd); |
1048 | if (ret < 0) { |
1049 | dev_err(dev, "Cannot read device properties.\n" ); |
1050 | return ret; |
1051 | } |
1052 | |
1053 | ret = bd9995x_hw_init(bd); |
1054 | if (ret < 0) { |
1055 | dev_err(dev, "Cannot initialize the chip.\n" ); |
1056 | return ret; |
1057 | } |
1058 | |
1059 | ret = devm_add_action_or_reset(dev, bd9995x_chip_reset, bd); |
1060 | if (ret) |
1061 | return ret; |
1062 | |
1063 | return devm_request_threaded_irq(dev, irq: client->irq, NULL, |
1064 | thread_fn: bd9995x_irq_handler_thread, |
1065 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
1066 | BD9995X_IRQ_PIN, dev_id: bd); |
1067 | } |
1068 | |
1069 | static const struct of_device_id bd9995x_of_match[] = { |
1070 | { .compatible = "rohm,bd99954" , }, |
1071 | { } |
1072 | }; |
1073 | MODULE_DEVICE_TABLE(of, bd9995x_of_match); |
1074 | |
1075 | static struct i2c_driver bd9995x_driver = { |
1076 | .driver = { |
1077 | .name = "bd9995x-charger" , |
1078 | .of_match_table = bd9995x_of_match, |
1079 | }, |
1080 | .probe = bd9995x_probe, |
1081 | }; |
1082 | module_i2c_driver(bd9995x_driver); |
1083 | |
1084 | MODULE_AUTHOR("Laine Markus <markus.laine@fi.rohmeurope.com>" ); |
1085 | MODULE_DESCRIPTION("ROHM BD99954 charger driver" ); |
1086 | MODULE_LICENSE("GPL" ); |
1087 | |