1 /*
2 * Copyright (c) 2020 Linumiz
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Relevant documents:
7 * - BQ27441
8 * Datasheet: https://www.ti.com/lit/gpn/bq27441-g1
9 * Technical reference manual: https://www.ti.com/lit/pdf/sluuac9
10 * - BQ27421
11 * Datasheet: https://www.ti.com/lit/gpn/bq27421-g1
12 * Technical reference manual: https://www.ti.com/lit/pdf/sluuac5
13 * - BQ27427
14 * Datasheet: https://www.ti.com/lit/gpn/bq27427
15 * Technical reference manual: https://www.ti.com/lit/pdf/sluucd5
16 */
17
18 #define DT_DRV_COMPAT ti_bq274xx
19
20 #include <zephyr/drivers/i2c.h>
21 #include <zephyr/init.h>
22 #include <zephyr/drivers/sensor.h>
23 #include <zephyr/pm/device.h>
24 #include <zephyr/sys/__assert.h>
25 #include <string.h>
26 #include <zephyr/sys/byteorder.h>
27 #include <zephyr/drivers/gpio.h>
28 #include <zephyr/logging/log.h>
29
30 #include "bq274xx.h"
31
32 LOG_MODULE_REGISTER(bq274xx, CONFIG_SENSOR_LOG_LEVEL);
33
34 /* subclass 64 & 82 needs 5ms delay */
35 #define BQ274XX_SUBCLASS_DELAY K_MSEC(5)
36
37 /* Time to wait for CFGUP bit to be set, up to 1 second according to the
38 * technical reference manual, keep some headroom like the Linux driver.
39 */
40 #define BQ274XX_CFGUP_DELAY K_MSEC(25)
41 #define BQ274XX_CFGUP_MAX_TRIES 100
42
43 /* Time to set pin in order to exit shutdown mode */
44 #define PIN_DELAY_TIME K_MSEC(1)
45
46 /* Delay from power up or shutdown exit to chip entering active state, this is
47 * defined as 250ms typical in the datasheet (Power-up communication delay).
48 */
49 #define POWER_UP_DELAY_MS 300
50
51 /* Data memory size */
52 #define BQ27XXX_DM_SZ 32
53
54 /* Config update mode flag */
55 #define BQ27XXX_FLAG_CFGUP BIT(4)
56
57 /* BQ27427 CC Gain */
58 #define BQ27427_CC_GAIN BQ274XX_EXT_BLKDAT(5)
59 #define BQ27427_CC_GAIN_SIGN_BIT BIT(7)
60
61 /* Subclasses */
62 #define BQ274XX_SUBCLASS_82 82
63 #define BQ274XX_SUBCLASS_105 105
64
65 /* For temperature conversion */
66 #define KELVIN_OFFSET 273.15
67
68 static const struct bq274xx_regs bq27421_regs = {
69 .dm_design_capacity = 10,
70 .dm_design_energy = 12,
71 .dm_terminate_voltage = 16,
72 .dm_taper_rate = 27,
73 };
74
75 static const struct bq274xx_regs bq27427_regs = {
76 .dm_design_capacity = 6,
77 .dm_design_energy = 8,
78 .dm_terminate_voltage = 10,
79 .dm_taper_rate = 21,
80 };
81
bq274xx_cmd_reg_read(const struct device * dev,uint8_t reg_addr,int16_t * val)82 static int bq274xx_cmd_reg_read(const struct device *dev, uint8_t reg_addr,
83 int16_t *val)
84 {
85 const struct bq274xx_config *config = dev->config;
86 uint8_t i2c_data[2];
87 int ret;
88
89 ret = i2c_burst_read_dt(&config->i2c, reg_addr, i2c_data, sizeof(i2c_data));
90 if (ret < 0) {
91 LOG_ERR("Unable to read register");
92 return -EIO;
93 }
94
95 *val = sys_get_le16(i2c_data);
96
97 return 0;
98 }
99
bq274xx_ctrl_reg_write(const struct device * dev,uint16_t subcommand)100 static int bq274xx_ctrl_reg_write(const struct device *dev, uint16_t subcommand)
101 {
102 const struct bq274xx_config *config = dev->config;
103 int ret;
104
105 uint8_t tx_buf[3];
106
107 tx_buf[0] = BQ274XX_CMD_CONTROL;
108 sys_put_le16(subcommand, &tx_buf[1]);
109
110 ret = i2c_write_dt(&config->i2c, tx_buf, sizeof(tx_buf));
111 if (ret < 0) {
112 LOG_ERR("Failed to write into control register");
113 return -EIO;
114 }
115
116 return 0;
117 }
118
bq274xx_get_device_type(const struct device * dev,uint16_t * val)119 static int bq274xx_get_device_type(const struct device *dev, uint16_t *val)
120 {
121 int ret;
122
123 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_DEVICE_TYPE);
124 if (ret < 0) {
125 LOG_ERR("Unable to write control register");
126 return -EIO;
127 }
128
129 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_CONTROL, val);
130 if (ret < 0) {
131 LOG_ERR("Unable to read register");
132 return -EIO;
133 }
134
135 return 0;
136 }
137
bq274xx_read_block(const struct device * dev,uint8_t subclass,uint8_t * block,uint8_t num_bytes)138 static int bq274xx_read_block(const struct device *dev,
139 uint8_t subclass,
140 uint8_t *block, uint8_t num_bytes)
141 {
142 const struct bq274xx_config *const config = dev->config;
143 int ret;
144
145 ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_CLASS, subclass);
146 if (ret < 0) {
147 LOG_ERR("Failed to update state subclass");
148 return -EIO;
149 }
150
151 /* DataBlock(), 0 for the first 32 bytes. */
152 ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_BLOCK, 0x00);
153 if (ret < 0) {
154 LOG_ERR("Failed to update block offset");
155 return -EIO;
156 }
157
158 k_sleep(BQ274XX_SUBCLASS_DELAY);
159
160 ret = i2c_burst_read_dt(&config->i2c, BQ274XX_EXT_BLKDAT_START, block, num_bytes);
161 if (ret < 0) {
162 LOG_ERR("Unable to read block data");
163 return -EIO;
164 }
165
166 return 0;
167 }
168
bq274xx_write_block(const struct device * dev,uint8_t * block,uint8_t num_bytes)169 static int bq274xx_write_block(const struct device *dev,
170 uint8_t *block, uint8_t num_bytes)
171 {
172 const struct bq274xx_config *const config = dev->config;
173 uint8_t checksum = 0;
174 int ret;
175 uint8_t buf[1 + BQ27XXX_DM_SZ];
176
177 __ASSERT_NO_MSG(num_bytes <= BQ27XXX_DM_SZ);
178
179 buf[0] = BQ274XX_EXT_BLKDAT_START;
180 memcpy(&buf[1], block, num_bytes);
181
182 ret = i2c_write_dt(&config->i2c, buf, 1 + num_bytes);
183 if (ret < 0) {
184 LOG_ERR("Unable to write block data");
185 return -EIO;
186 }
187
188 for (uint8_t i = 0; i < num_bytes; i++) {
189 checksum += block[i];
190 }
191 checksum = 0xff - checksum;
192
193 ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_CHECKSUM, checksum);
194 if (ret < 0) {
195 LOG_ERR("Failed to update block checksum");
196 return -EIO;
197 }
198
199 k_sleep(BQ274XX_SUBCLASS_DELAY);
200
201 return 0;
202 }
203
bq274xx_update_block(uint8_t * block,uint8_t offset,uint16_t val,bool * block_modified)204 static void bq274xx_update_block(uint8_t *block,
205 uint8_t offset, uint16_t val,
206 bool *block_modified)
207 {
208 uint16_t old_val;
209
210 old_val = sys_get_be16(&block[offset]);
211
212 LOG_DBG("update block: off=%d old=%d new=%d\n", offset, old_val, val);
213
214 if (val == old_val) {
215 return;
216 }
217
218 sys_put_be16(val, &block[offset]);
219
220 *block_modified = true;
221 }
222
bq274xx_mode_cfgupdate(const struct device * dev,bool enabled)223 static int bq274xx_mode_cfgupdate(const struct device *dev, bool enabled)
224 {
225 uint16_t flags;
226 uint8_t try;
227 int ret;
228 uint16_t val = enabled ? BQ274XX_CTRL_SET_CFGUPDATE : BQ274XX_CTRL_SOFT_RESET;
229 bool enabled_flag;
230
231 ret = bq274xx_ctrl_reg_write(dev, val);
232 if (ret < 0) {
233 LOG_ERR("Unable to set device mode to %02x", val);
234 return -EIO;
235 }
236
237 for (try = 0; try < BQ274XX_CFGUP_MAX_TRIES; try++) {
238 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_FLAGS, &flags);
239 if (ret < 0) {
240 LOG_ERR("Unable to read flags");
241 return -EIO;
242 }
243
244 enabled_flag = !!(flags & BQ27XXX_FLAG_CFGUP);
245 if (enabled_flag == enabled) {
246 LOG_DBG("CFGUP ready, try %u", try);
247 break;
248 }
249
250 k_sleep(BQ274XX_CFGUP_DELAY);
251 }
252
253 if (try >= BQ274XX_CFGUP_MAX_TRIES) {
254 LOG_ERR("Config mode change timeout");
255 return -EIO;
256 }
257
258 return 0;
259 }
260
261 /*
262 * BQ27427 needs the CC Gain polarity swapped from the ROM value.
263 * The details are currently only documented in the TI E2E support forum:
264 * https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1215460/bq27427evm-misbehaving-stateofcharge
265 */
bq27427_ccgain_quirk(const struct device * dev)266 static int bq27427_ccgain_quirk(const struct device *dev)
267 {
268 const struct bq274xx_config *const config = dev->config;
269 int ret;
270 uint8_t val, checksum;
271
272 ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_CLASS,
273 BQ274XX_SUBCLASS_105);
274 if (ret < 0) {
275 LOG_ERR("Failed to update state subclass");
276 return -EIO;
277 }
278
279 ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_BLOCK, 0x00);
280 if (ret < 0) {
281 LOG_ERR("Failed to update block offset");
282 return -EIO;
283 }
284
285 k_sleep(BQ274XX_SUBCLASS_DELAY);
286
287 ret = i2c_reg_read_byte_dt(&config->i2c, BQ27427_CC_GAIN, &val);
288 if (ret < 0) {
289 LOG_ERR("Failed to read ccgain");
290 return -EIO;
291 }
292
293 if (!(val & BQ27427_CC_GAIN_SIGN_BIT)) {
294 LOG_DBG("bq27427 quirk already applied");
295 return 0;
296 }
297
298 ret = i2c_reg_read_byte_dt(&config->i2c, BQ274XX_EXT_CHECKSUM, &checksum);
299 if (ret < 0) {
300 LOG_ERR("Failed to read block checksum");
301 return -EIO;
302 }
303
304 /* Flip the sign bit on both value and checksum. */
305 val ^= BQ27427_CC_GAIN_SIGN_BIT;
306 checksum ^= BQ27427_CC_GAIN_SIGN_BIT;
307
308 LOG_DBG("bq27427: val=%02x checksum=%02x", val, checksum);
309
310 ret = i2c_reg_write_byte_dt(&config->i2c, BQ27427_CC_GAIN, val);
311 if (ret < 0) {
312 LOG_ERR("Failed to update ccgain");
313 return -EIO;
314 }
315
316 ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_CHECKSUM, checksum);
317 if (ret < 0) {
318 LOG_ERR("Failed to update block checksum");
319 return -EIO;
320 }
321
322 k_sleep(BQ274XX_SUBCLASS_DELAY);
323
324 return 0;
325 }
326
bq274xx_ensure_chemistry(const struct device * dev)327 static int bq274xx_ensure_chemistry(const struct device *dev)
328 {
329 struct bq274xx_data *data = dev->data;
330 const struct bq274xx_config *const config = dev->config;
331 uint16_t chem_id = config->chemistry_id;
332
333 if (chem_id == 0) {
334 /* No chemistry ID set, rely on the default of the device.*/
335 return 0;
336 }
337 int ret;
338 uint16_t val;
339
340 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_CHEM_ID);
341 if (ret < 0) {
342 LOG_ERR("Unable to write control register");
343 return -EIO;
344 }
345
346 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_CONTROL, &val);
347 if (ret < 0) {
348 LOG_ERR("Unable to read register");
349 return -EIO;
350 }
351
352 LOG_DBG("Chem ID: %04x", val);
353
354 if (val != chem_id) {
355 /* Only the bq27427 has a configurable Chemistry ID. On bq27421, it depends on the
356 * variant of the chip, so just error out if the chemistry ID is wrong.
357 */
358 if (data->regs != &bq27427_regs) {
359 LOG_ERR("Unable to confirm chemistry ID 0x%04x. Device reported 0x%04x",
360 chem_id, val);
361 return -EIO;
362 }
363
364 uint16_t cmd;
365
366 switch (val) {
367 case BQ27427_CHEM_ID_A:
368 cmd = BQ27427_CTRL_CHEM_A;
369 break;
370 case BQ27427_CHEM_ID_B:
371 cmd = BQ27427_CTRL_CHEM_B;
372 break;
373 case BQ27427_CHEM_ID_C:
374 cmd = BQ27427_CTRL_CHEM_C;
375 break;
376 default:
377 LOG_ERR("Unsupported chemistry ID 0x%04x", val);
378 return -EINVAL;
379 }
380
381 ret = bq274xx_ctrl_reg_write(dev, cmd);
382 if (ret < 0) {
383 LOG_ERR("Unable to configure chemistry");
384 return -EIO;
385 }
386 }
387 return 0;
388 }
389
bq274xx_gauge_configure(const struct device * dev)390 static int bq274xx_gauge_configure(const struct device *dev)
391 {
392 const struct bq274xx_config *const config = dev->config;
393 struct bq274xx_data *data = dev->data;
394 const struct bq274xx_regs *regs;
395 int ret;
396 uint16_t designenergy_mwh, taperrate;
397 uint8_t block[BQ27XXX_DM_SZ];
398 bool block_modified = false;
399 uint16_t id;
400
401 if (data->regs == NULL) {
402 k_sleep(K_TIMEOUT_ABS_MS(POWER_UP_DELAY_MS));
403
404 ret = bq274xx_get_device_type(dev, &id);
405 if (ret < 0) {
406 LOG_ERR("Unable to get device ID");
407 return -EIO;
408 }
409
410 if (id == BQ27421_DEVICE_ID) {
411 data->regs = &bq27421_regs;
412 } else if (id == BQ27427_DEVICE_ID) {
413 data->regs = &bq27427_regs;
414 } else {
415 LOG_ERR("Unsupported device ID: 0x%04x", id);
416 return -ENOTSUP;
417 }
418 }
419 regs = data->regs;
420
421 designenergy_mwh = (uint32_t)config->design_capacity * 37 / 10; /* x3.7 */
422 taperrate = config->design_capacity * 10 / config->taper_current;
423
424 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_A);
425 if (ret < 0) {
426 LOG_ERR("Unable to unseal the battery");
427 return -EIO;
428 }
429
430 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_B);
431 if (ret < 0) {
432 LOG_ERR("Unable to unseal the battery");
433 return -EIO;
434 }
435
436 ret = bq274xx_mode_cfgupdate(dev, true);
437 if (ret < 0) {
438 return ret;
439 }
440
441 ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_CONTROL, 0x00);
442 if (ret < 0) {
443 LOG_ERR("Failed to enable block data memory");
444 return -EIO;
445 }
446
447 ret = bq274xx_read_block(dev, BQ274XX_SUBCLASS_82, block, sizeof(block));
448 if (ret < 0) {
449 return ret;
450 }
451
452 bq274xx_update_block(block,
453 regs->dm_design_capacity, config->design_capacity,
454 &block_modified);
455 bq274xx_update_block(block,
456 regs->dm_design_energy, designenergy_mwh,
457 &block_modified);
458 bq274xx_update_block(block,
459 regs->dm_terminate_voltage, config->terminate_voltage,
460 &block_modified);
461 bq274xx_update_block(block,
462 regs->dm_taper_rate, taperrate,
463 &block_modified);
464
465 if (block_modified) {
466 LOG_INF("bq274xx: updating fuel gauge parameters");
467
468 ret = bq274xx_write_block(dev, block, sizeof(block));
469 if (ret < 0) {
470 return ret;
471 }
472
473 if (data->regs == &bq27427_regs) {
474 ret = bq27427_ccgain_quirk(dev);
475 if (ret < 0) {
476 return ret;
477 }
478 }
479
480 ret = bq274xx_ensure_chemistry(dev);
481 if (ret < 0) {
482 return ret;
483 }
484
485 ret = bq274xx_mode_cfgupdate(dev, false);
486 if (ret < 0) {
487 return ret;
488 }
489 }
490
491 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SEALED);
492 if (ret < 0) {
493 LOG_ERR("Failed to seal the gauge");
494 return -EIO;
495 }
496
497 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_BAT_INSERT);
498 if (ret < 0) {
499 LOG_ERR("Unable to configure BAT Detect");
500 return -EIO;
501 }
502
503 data->configured = true;
504
505 return 0;
506 }
507
bq274xx_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)508 static int bq274xx_channel_get(const struct device *dev, enum sensor_channel chan,
509 struct sensor_value *val)
510 {
511 struct bq274xx_data *data = dev->data;
512 int32_t int_temp;
513
514 switch (chan) {
515 case SENSOR_CHAN_GAUGE_VOLTAGE:
516 val->val1 = ((data->voltage / 1000));
517 val->val2 = ((data->voltage % 1000) * 1000U);
518 break;
519
520 case SENSOR_CHAN_GAUGE_AVG_CURRENT:
521 val->val1 = ((data->avg_current / 1000));
522 val->val2 = ((data->avg_current % 1000) * 1000U);
523 break;
524
525 case SENSOR_CHAN_GAUGE_STDBY_CURRENT:
526 val->val1 = ((data->stdby_current / 1000));
527 val->val2 = ((data->stdby_current % 1000) * 1000U);
528 break;
529
530 case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT:
531 val->val1 = ((data->max_load_current / 1000));
532 val->val2 = ((data->max_load_current % 1000) * 1000U);
533 break;
534
535 case SENSOR_CHAN_GAUGE_TEMP:
536 /* Convert units from 0.1K to 0.01K */
537 int_temp = data->internal_temperature * 10;
538 /* Convert to 0.01C */
539 int_temp -= (int32_t)(100.0 * KELVIN_OFFSET);
540 val->val1 = int_temp / 100;
541 val->val2 = (int_temp % 100) * 10000;
542 break;
543
544 case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE:
545 val->val1 = data->state_of_charge;
546 val->val2 = 0;
547 break;
548
549 case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH:
550 val->val1 = data->state_of_health;
551 val->val2 = 0;
552 break;
553
554 case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY:
555 val->val1 = data->full_charge_capacity;
556 val->val2 = 0;
557 break;
558
559 case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY:
560 val->val1 = data->remaining_charge_capacity;
561 val->val2 = 0;
562 break;
563
564 case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY:
565 val->val1 = data->nom_avail_capacity;
566 val->val2 = 0;
567 break;
568
569 case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY:
570 val->val1 = data->full_avail_capacity;
571 val->val2 = 0;
572 break;
573
574 case SENSOR_CHAN_GAUGE_AVG_POWER:
575 val->val1 = data->avg_power;
576 val->val2 = 0;
577 break;
578
579 default:
580 return -ENOTSUP;
581 }
582
583 return 0;
584 }
585
bq274xx_sample_fetch(const struct device * dev,enum sensor_channel chan)586 static int bq274xx_sample_fetch(const struct device *dev, enum sensor_channel chan)
587 {
588 struct bq274xx_data *data = dev->data;
589 int ret = -ENOTSUP;
590
591 if (!data->configured) {
592 ret = bq274xx_gauge_configure(dev);
593 if (ret < 0) {
594 return ret;
595 }
596 }
597
598 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_VOLTAGE) {
599 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_VOLTAGE,
600 &data->voltage);
601 if (ret < 0) {
602 LOG_ERR("Failed to read voltage");
603 return -EIO;
604 }
605 }
606
607 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_AVG_CURRENT) {
608 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_AVG_CURRENT,
609 &data->avg_current);
610 if (ret < 0) {
611 LOG_ERR("Failed to read average current ");
612 return -EIO;
613 }
614 }
615
616 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_TEMP) {
617 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_INT_TEMP,
618 &data->internal_temperature);
619 if (ret < 0) {
620 LOG_ERR("Failed to read internal temperature");
621 return -EIO;
622 }
623 }
624
625 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_STDBY_CURRENT) {
626 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_STDBY_CURRENT,
627 &data->stdby_current);
628 if (ret < 0) {
629 LOG_ERR("Failed to read standby current");
630 return -EIO;
631 }
632 }
633
634 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT) {
635 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_MAX_CURRENT,
636 &data->max_load_current);
637 if (ret < 0) {
638 LOG_ERR("Failed to read maximum current");
639 return -EIO;
640 }
641 }
642
643 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_STATE_OF_CHARGE) {
644 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_SOC,
645 &data->state_of_charge);
646 if (ret < 0) {
647 LOG_ERR("Failed to read state of charge");
648 return -EIO;
649 }
650 }
651
652 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY) {
653 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_FULL_CAPACITY,
654 &data->full_charge_capacity);
655 if (ret < 0) {
656 LOG_ERR("Failed to read full charge capacity");
657 return -EIO;
658 }
659 }
660
661 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY) {
662 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_REM_CAPACITY,
663 &data->remaining_charge_capacity);
664 if (ret < 0) {
665 LOG_ERR("Failed to read remaining charge capacity");
666 return -EIO;
667 }
668 }
669
670 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY) {
671 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_NOM_CAPACITY,
672 &data->nom_avail_capacity);
673 if (ret < 0) {
674 LOG_ERR("Failed to read nominal available capacity");
675 return -EIO;
676 }
677 }
678
679 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY) {
680 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_AVAIL_CAPACITY,
681 &data->full_avail_capacity);
682 if (ret < 0) {
683 LOG_ERR("Failed to read full available capacity");
684 return -EIO;
685 }
686 }
687
688 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_AVG_POWER) {
689 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_AVG_POWER,
690 &data->avg_power);
691 if (ret < 0) {
692 LOG_ERR("Failed to read battery average power");
693 return -EIO;
694 }
695 }
696
697 if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_STATE_OF_HEALTH) {
698 ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_SOH,
699 &data->state_of_health);
700
701 data->state_of_health = (data->state_of_health) & 0x00FF;
702
703 if (ret < 0) {
704 LOG_ERR("Failed to read state of health");
705 return -EIO;
706 }
707 }
708
709 return ret;
710 }
711
712 /**
713 * @brief initialise the fuel gauge
714 *
715 * @return 0 for success
716 */
bq274xx_gauge_init(const struct device * dev)717 static int bq274xx_gauge_init(const struct device *dev)
718 {
719 const struct bq274xx_config *const config = dev->config;
720 int ret = 0;
721
722 if (!device_is_ready(config->i2c.bus)) {
723 LOG_ERR("I2C bus device not ready");
724 return -ENODEV;
725 }
726
727 #if defined(CONFIG_BQ274XX_PM) || defined(CONFIG_BQ274XX_TRIGGER)
728 if (!gpio_is_ready_dt(&config->int_gpios)) {
729 LOG_ERR("GPIO device pointer is not ready to be used");
730 return -ENODEV;
731 }
732 #endif
733
734 #ifdef CONFIG_BQ274XX_TRIGGER
735 ret = bq274xx_trigger_mode_init(dev);
736 if (ret < 0) {
737 LOG_ERR("Unable set up trigger mode.");
738 return ret;
739 }
740 #endif
741
742 if (!config->lazy_loading) {
743 ret = bq274xx_gauge_configure(dev);
744 }
745
746 return ret;
747 }
748
749 #ifdef CONFIG_BQ274XX_PM
bq274xx_enter_shutdown_mode(const struct device * dev)750 static int bq274xx_enter_shutdown_mode(const struct device *dev)
751 {
752 int ret;
753
754 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_A);
755 if (ret < 0) {
756 LOG_ERR("Unable to unseal the battery");
757 return ret;
758 }
759
760 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_B);
761 if (ret < 0) {
762 LOG_ERR("Unable to unseal the battery");
763 return ret;
764 }
765
766 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SHUTDOWN_ENABLE);
767 if (ret < 0) {
768 LOG_ERR("Unable to enable shutdown mode");
769 return ret;
770 }
771
772 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SHUTDOWN);
773 if (ret < 0) {
774 LOG_ERR("Unable to enter shutdown mode");
775 return ret;
776 }
777
778 ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SEALED);
779 if (ret < 0) {
780 LOG_ERR("Failed to seal the gauge");
781 return ret;
782 }
783
784 return 0;
785 }
786
bq274xx_exit_shutdown_mode(const struct device * dev)787 static int bq274xx_exit_shutdown_mode(const struct device *dev)
788 {
789 const struct bq274xx_config *const config = dev->config;
790 int ret;
791
792 ret = gpio_pin_configure_dt(&config->int_gpios, GPIO_OUTPUT | GPIO_OPEN_DRAIN);
793 if (ret < 0) {
794 LOG_ERR("Unable to configure interrupt pin to output and open drain");
795 return ret;
796 }
797
798 ret = gpio_pin_set_dt(&config->int_gpios, 0);
799 if (ret < 0) {
800 LOG_ERR("Unable to set interrupt pin to low");
801 return ret;
802 }
803
804 k_sleep(PIN_DELAY_TIME);
805
806 ret = gpio_pin_configure_dt(&config->int_gpios, GPIO_INPUT);
807 if (ret < 0) {
808 LOG_ERR("Unable to configure interrupt pin to input");
809 return ret;
810 }
811
812 if (!config->lazy_loading) {
813 k_sleep(K_MSEC(POWER_UP_DELAY_MS));
814
815 ret = bq274xx_gauge_configure(dev);
816 if (ret < 0) {
817 LOG_ERR("Unable to configure bq274xx gauge");
818 return ret;
819 }
820 }
821
822 return 0;
823 }
824
bq274xx_pm_action(const struct device * dev,enum pm_device_action action)825 static int bq274xx_pm_action(const struct device *dev,
826 enum pm_device_action action)
827 {
828 int ret;
829
830 switch (action) {
831 case PM_DEVICE_ACTION_TURN_OFF:
832 ret = bq274xx_enter_shutdown_mode(dev);
833 break;
834 case PM_DEVICE_ACTION_RESUME:
835 ret = bq274xx_exit_shutdown_mode(dev);
836 break;
837 default:
838 ret = -ENOTSUP;
839 break;
840 }
841
842 return ret;
843 }
844 #endif /* CONFIG_BQ274XX_PM */
845
846 static DEVICE_API(sensor, bq274xx_battery_driver_api) = {
847 .sample_fetch = bq274xx_sample_fetch,
848 .channel_get = bq274xx_channel_get,
849 #ifdef CONFIG_BQ274XX_TRIGGER
850 .trigger_set = bq274xx_trigger_set,
851 #endif
852 };
853
854 #if defined(CONFIG_BQ274XX_PM) || defined(CONFIG_BQ274XX_TRIGGER)
855 #define BQ274XX_INT_CFG(index) \
856 .int_gpios = GPIO_DT_SPEC_INST_GET(index, int_gpios),
857 #define PM_BQ274XX_DT_INST_DEFINE(index, bq274xx_pm_action) \
858 PM_DEVICE_DT_INST_DEFINE(index, bq274xx_pm_action)
859 #define PM_BQ274XX_DT_INST_GET(index) PM_DEVICE_DT_INST_GET(index)
860 #else
861 #define BQ274XX_INT_CFG(index)
862 #define PM_BQ274XX_DT_INST_DEFINE(index, bq274xx_pm_action)
863 #define PM_BQ274XX_DT_INST_GET(index) NULL
864 #endif
865
866 #define BQ274XX_INIT(index) \
867 static struct bq274xx_data bq274xx_driver_##index; \
868 \
869 static const struct bq274xx_config bq274xx_config_##index = { \
870 .i2c = I2C_DT_SPEC_INST_GET(index), \
871 BQ274XX_INT_CFG(index) \
872 .design_voltage = DT_INST_PROP(index, design_voltage), \
873 .design_capacity = DT_INST_PROP(index, design_capacity), \
874 .taper_current = DT_INST_PROP(index, taper_current), \
875 .terminate_voltage = DT_INST_PROP(index, terminate_voltage), \
876 .chemistry_id = DT_INST_PROP_OR(index, chemistry_id, 0), \
877 .lazy_loading = DT_INST_PROP(index, zephyr_lazy_load), \
878 }; \
879 \
880 PM_BQ274XX_DT_INST_DEFINE(index, bq274xx_pm_action); \
881 \
882 SENSOR_DEVICE_DT_INST_DEFINE(index, &bq274xx_gauge_init, \
883 PM_BQ274XX_DT_INST_GET(index), \
884 &bq274xx_driver_##index, \
885 &bq274xx_config_##index, POST_KERNEL, \
886 CONFIG_SENSOR_INIT_PRIORITY, \
887 &bq274xx_battery_driver_api);
888
889 DT_INST_FOREACH_STATUS_OKAY(BQ274XX_INIT)
890