You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
634 lines
18 KiB
634 lines
18 KiB
/* |
|
* Copyright (c) 2025 Philipp Steiner <philipp.steiner1987@gmail.com> |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
* |
|
* Zephyr driver for LC709203F Battery Monitor |
|
* |
|
* This driver implements the sensor API for the LC709203F battery monitor, |
|
* providing battery voltage, state-of-charge (SOC), and temperature measurements. |
|
* |
|
* Note: |
|
* - The LC709203F is assumed to be connected via I2C. |
|
* - The register addresses and conversion factors used here are based on |
|
* common LC709203F implementations. Consult your datasheet and adjust as needed. |
|
* - To use this driver, create a matching device tree node (with a "compatible" |
|
* string, I2C bus, and register address) so that the DT_INST_* macros can pick it up. |
|
* - The LC chip works best when queried every few seconds at the fastest. Don't disconnect the LiPo |
|
* battery, it is used to power the LC chip! |
|
*/ |
|
|
|
#define DT_DRV_COMPAT onnn_lc709203f |
|
|
|
#include "lc709203f.h" |
|
|
|
#include <zephyr/drivers/fuel_gauge.h> |
|
#include <zephyr/kernel.h> |
|
#include <zephyr/init.h> |
|
#include <zephyr/drivers/gpio.h> |
|
#include <zephyr/pm/device.h> |
|
#include <zephyr/sys/byteorder.h> |
|
#include <zephyr/sys/crc.h> |
|
#include <zephyr/sys/__assert.h> |
|
#include <zephyr/logging/log.h> |
|
|
|
LOG_MODULE_REGISTER(lc709203f); |
|
|
|
/* Battery temperature source */ |
|
enum lc709203f_temp_mode { |
|
LC709203F_TEMPERATURE_I2C = 0x0000, |
|
LC709203F_TEMPERATURE_THERMISTOR = 0x0001, |
|
}; |
|
|
|
/* Chip power state */ |
|
enum lc709203f_power_mode { |
|
LC709203F_POWER_MODE_OPERATIONAL = 0x0001, |
|
LC709203F_POWER_MODE_SLEEP = 0x0002, |
|
}; |
|
|
|
/* Current Direction Auto/Charge/Discharge mode */ |
|
enum lc709203f_current_direction { |
|
LC709203F_DIRECTION_AUTO = 0x0000, |
|
LC709203F_DIRECTION_CHARGE = 0x0001, |
|
LC709203F_DIRECTION_DISCHARGE = 0xFFFF, |
|
}; |
|
|
|
/* Selects a battery profile */ |
|
enum lc709203f_battery_profile { |
|
LC709203F_BATTERY_PROFILE_0 = 0x0000, |
|
LC709203F_BATTERY_PROFILE_1 = 0x0001, |
|
}; |
|
|
|
/* Approx battery pack size. Pick the closest of the following values for your battery size. */ |
|
enum lc709203f_battery_apa { |
|
LC709203F_APA_100MAH = 0x08, |
|
LC709203F_APA_200MAH = 0x0B, |
|
LC709203F_APA_500MAH = 0x10, |
|
LC709203F_APA_1000MAH = 0x19, |
|
LC709203F_APA_2000MAH = 0x2D, |
|
LC709203F_APA_3000MAH = 0x36, |
|
}; |
|
|
|
struct lc709203f_config { |
|
struct i2c_dt_spec i2c; |
|
bool initial_rsoc; |
|
char *battery_apa; |
|
enum lc709203f_battery_profile battery_profile; |
|
bool thermistor; |
|
int thermistor_b_value; |
|
int thermistor_apt; |
|
enum lc709203f_temp_mode thermistor_mode; |
|
}; |
|
|
|
#define LC709203F_INIT_RSOC_VAL 0xAA55 /* RSOC initialization value */ |
|
#define LC709203F_CRC_POLYNOMIAL 0x07 /* Polynomial to calculate CRC-8-ATM */ |
|
|
|
static int lc709203f_read_word(const struct device *dev, uint8_t reg, uint16_t *value); |
|
static int lc709203f_write_word(const struct device *dev, uint8_t reg, uint16_t value); |
|
|
|
static int lc709203f_get_alarm_low_rsoc(const struct device *dev, uint8_t *rsoc); |
|
static int lc709203f_get_alarm_low_voltage(const struct device *dev, uint16_t *voltage); |
|
static int lc709203f_get_apa(const struct device *dev, enum lc709203f_battery_apa *apa); |
|
static int lc709203f_get_cell_temperature(const struct device *dev, uint16_t *temperature); |
|
static int lc709203f_get_cell_voltage(const struct device *dev, uint16_t *voltage); |
|
static int lc709203f_get_current_direction(const struct device *dev, |
|
enum lc709203f_current_direction *direction); |
|
static int lc709203f_get_power_mode(const struct device *dev, enum lc709203f_power_mode *mode); |
|
static int lc709203f_get_rsoc(const struct device *dev, uint8_t *rsoc); |
|
|
|
static int lc709203f_set_initial_rsoc(const struct device *dev); |
|
static int lc709203f_set_alarm_low_rsoc(const struct device *dev, uint8_t rsoc); |
|
static int lc709203f_set_alarm_low_voltage(const struct device *dev, uint16_t voltage); |
|
static int lc709203f_set_apa(const struct device *dev, enum lc709203f_battery_apa apa); |
|
static int lc709203f_set_apt(const struct device *dev, uint16_t apt); |
|
static int lc709203f_set_battery_profile(const struct device *dev, |
|
enum lc709203f_battery_profile profile); |
|
static int lc709203f_set_current_direction(const struct device *dev, |
|
enum lc709203f_current_direction direction); |
|
static int lc709203f_set_power_mode(const struct device *dev, enum lc709203f_power_mode mode); |
|
static int lc709203f_set_temp_mode(const struct device *dev, enum lc709203f_temp_mode mode); |
|
static int lc709203f_set_thermistor_b(const struct device *dev, uint16_t value); |
|
|
|
/* |
|
* Read a 16-bit register value (with CRC check). |
|
* |
|
* The LC709203F expects the following transaction: |
|
* Write: [reg] |
|
* Read: [LSB, MSB, CRC] |
|
* |
|
* The CRC is computed over: |
|
* [I2C_addr (write), reg, I2C_addr (read), LSB, MSB] |
|
*/ |
|
static int lc709203f_read_word(const struct device *dev, uint8_t reg, uint16_t *value) |
|
{ |
|
const struct lc709203f_config *config = dev->config; |
|
uint8_t buf[3]; |
|
int ret; |
|
|
|
ret = i2c_write_read_dt(&config->i2c, ®, sizeof(reg), buf, sizeof(buf)); |
|
if (ret) { |
|
LOG_ERR("i2c_write_read failed (reg 0x%02x): %d", reg, ret); |
|
return ret; |
|
} |
|
|
|
uint8_t crc_buf[5]; |
|
|
|
/* Build buffer for CRC calculation */ |
|
crc_buf[0] = config->i2c.addr << 1; |
|
crc_buf[1] = reg; |
|
crc_buf[2] = (config->i2c.addr << 1) | 0x01; |
|
crc_buf[3] = buf[0]; /* LSB */ |
|
crc_buf[4] = buf[1]; /* MSB */ |
|
|
|
uint8_t crc = crc8(crc_buf, sizeof(crc_buf), LC709203F_CRC_POLYNOMIAL, 0, false); |
|
|
|
if (crc != buf[2]) { |
|
LOG_ERR("CRC mismatch on reg 0x%02x", reg); |
|
return -EIO; |
|
} |
|
|
|
if (value) { |
|
*value = sys_get_le16(buf); /* LSB, MSB */ |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/* |
|
* Write a 16-bit word to a register (with CRC appended). |
|
* |
|
* The transaction is: |
|
* Write: [reg, LSB, MSB, CRC] |
|
* |
|
* The CRC is computed over: |
|
* [I2C_addr (write), reg, LSB, MSB] |
|
*/ |
|
static int lc709203f_write_word(const struct device *dev, uint8_t reg, uint16_t value) |
|
{ |
|
const struct lc709203f_config *config = dev->config; |
|
uint8_t crc_buf[4]; |
|
uint8_t write_buf[4]; |
|
|
|
crc_buf[0] = config->i2c.addr << 1; |
|
crc_buf[1] = reg; |
|
sys_put_le16(value, &crc_buf[2]); /* LSB, MSB */ |
|
|
|
write_buf[0] = reg; |
|
sys_put_le16(value, &write_buf[1]); /* LSB, MSB */ |
|
write_buf[3] = crc8(crc_buf, sizeof(crc_buf), LC709203F_CRC_POLYNOMIAL, 0, false); |
|
|
|
return i2c_write_dt(&config->i2c, write_buf, sizeof(write_buf)); |
|
} |
|
|
|
static int lc709203f_get_alarm_low_rsoc(const struct device *dev, uint8_t *rsoc) |
|
{ |
|
uint16_t tmp; |
|
int ret; |
|
|
|
if (!dev || !rsoc) { |
|
return -EINVAL; |
|
} |
|
|
|
ret = lc709203f_read_word(dev, LC709203F_REG_ALARM_LOW_RSOC, &tmp); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
*rsoc = (uint8_t)tmp; |
|
return 0; |
|
} |
|
|
|
static int lc709203f_get_alarm_low_voltage(const struct device *dev, uint16_t *voltage) |
|
{ |
|
if (!dev || !voltage) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_read_word(dev, LC709203F_REG_ALARM_LOW_VOLTAGE, voltage); |
|
} |
|
|
|
static int lc709203f_get_apa(const struct device *dev, enum lc709203f_battery_apa *apa) |
|
{ |
|
uint16_t tmp; |
|
int ret; |
|
|
|
if (!dev || !apa) { |
|
return -EINVAL; |
|
} |
|
|
|
ret = lc709203f_read_word(dev, LC709203F_REG_APA, &tmp); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
*apa = (enum lc709203f_battery_apa)tmp; |
|
return 0; |
|
} |
|
|
|
static int lc709203f_get_cell_temperature(const struct device *dev, uint16_t *temperature) |
|
{ |
|
if (!dev || !temperature) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_read_word(dev, LC709203F_REG_CELL_TEMPERATURE, temperature); |
|
} |
|
|
|
static int lc709203f_get_cell_voltage(const struct device *dev, uint16_t *voltage) |
|
{ |
|
if (!dev || !voltage) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_read_word(dev, LC709203F_REG_CELL_VOLTAGE, voltage); |
|
} |
|
|
|
static int lc709203f_get_current_direction(const struct device *dev, |
|
enum lc709203f_current_direction *direction) |
|
{ |
|
uint16_t tmp; |
|
int ret; |
|
|
|
if (!dev || !direction) { |
|
return -EINVAL; |
|
} |
|
|
|
ret = lc709203f_read_word(dev, LC709203F_REG_CURRENT_DIRECTION, &tmp); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
*direction = (enum lc709203f_current_direction)tmp; |
|
return 0; |
|
} |
|
|
|
static int lc709203f_get_power_mode(const struct device *dev, enum lc709203f_power_mode *mode) |
|
{ |
|
uint16_t tmp; |
|
int ret; |
|
|
|
if (!dev || !mode) { |
|
return -EINVAL; |
|
} |
|
|
|
ret = lc709203f_read_word(dev, LC709203F_REG_IC_POWER_MODE, &tmp); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
*mode = (enum lc709203f_power_mode)tmp; |
|
return 0; |
|
} |
|
|
|
static int lc709203f_get_rsoc(const struct device *dev, uint8_t *rsoc) |
|
{ |
|
uint16_t tmp; |
|
int ret; |
|
|
|
if (!dev || !rsoc) { |
|
return -EINVAL; |
|
} |
|
|
|
ret = lc709203f_read_word(dev, LC709203F_REG_RSOC, &tmp); |
|
if (ret) { |
|
return ret; |
|
} |
|
|
|
*rsoc = (uint8_t)tmp; |
|
return 0; |
|
} |
|
|
|
static int lc709203f_set_initial_rsoc(const struct device *dev) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_INITIAL_RSOC, LC709203F_INIT_RSOC_VAL); |
|
} |
|
|
|
static int lc709203f_set_alarm_low_rsoc(const struct device *dev, uint8_t rsoc) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
if (rsoc > 100) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_ALARM_LOW_RSOC, rsoc); |
|
} |
|
|
|
static int lc709203f_set_alarm_low_voltage(const struct device *dev, uint16_t voltage) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_ALARM_LOW_VOLTAGE, voltage); |
|
} |
|
|
|
static int lc709203f_set_apa(const struct device *dev, enum lc709203f_battery_apa apa) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_APA, (uint16_t)apa); |
|
} |
|
|
|
static int lc709203f_set_apt(const struct device *dev, uint16_t apt) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_APT, apt); |
|
} |
|
|
|
static int lc709203f_set_battery_profile(const struct device *dev, |
|
enum lc709203f_battery_profile profile) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_BAT_PROFILE, (uint16_t)profile); |
|
} |
|
|
|
static int lc709203f_set_current_direction(const struct device *dev, |
|
enum lc709203f_current_direction direction) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_CURRENT_DIRECTION, (uint16_t)direction); |
|
} |
|
|
|
static int lc709203f_set_power_mode(const struct device *dev, enum lc709203f_power_mode mode) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_IC_POWER_MODE, (uint16_t)mode); |
|
} |
|
|
|
static int lc709203f_set_temp_mode(const struct device *dev, enum lc709203f_temp_mode mode) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_STATUS_BIT, (uint16_t)mode); |
|
} |
|
|
|
static int lc709203f_set_thermistor_b(const struct device *dev, uint16_t value) |
|
{ |
|
if (!dev) { |
|
return -EINVAL; |
|
} |
|
return lc709203f_write_word(dev, LC709203F_REG_THERMISTOR_B, value); |
|
} |
|
|
|
enum lc709203f_battery_apa lc709203f_string_to_apa(const char *apa_string) |
|
{ |
|
static const char *const apas[] = {"100mAh", "200mAh", "500mAh", |
|
"1000mAh", "2000mAh", "3000mAh"}; |
|
|
|
static const enum lc709203f_battery_apa apa_values[] = { |
|
LC709203F_APA_100MAH, LC709203F_APA_200MAH, LC709203F_APA_500MAH, |
|
LC709203F_APA_1000MAH, LC709203F_APA_2000MAH, LC709203F_APA_3000MAH}; |
|
|
|
/* Check if the string is NULL or empty */ |
|
for (size_t i = 0; i < ARRAY_SIZE(apas); i++) { |
|
if (strncmp(apa_string, apas[i], strlen(apas[i])) == 0) { |
|
return apa_values[i]; |
|
} |
|
} |
|
LOG_ERR("Invalid apa_string: %s, returning default: %d", apa_string, LC709203F_APA_100MAH); |
|
return LC709203F_APA_100MAH; |
|
} |
|
|
|
enum lc709203f_power_mode lc709203f_num_to_power_mode(uint16_t num) |
|
{ |
|
switch (num) { |
|
case 1: |
|
return LC709203F_POWER_MODE_OPERATIONAL; |
|
case 2: |
|
return LC709203F_POWER_MODE_SLEEP; |
|
default: |
|
LOG_ERR("Invalid power mode: %d", num); |
|
return LC709203F_POWER_MODE_OPERATIONAL; |
|
} |
|
} |
|
|
|
enum lc709203f_current_direction lc709203f_num_to_current_direction(uint16_t num) |
|
{ |
|
switch (num) { |
|
case 0: |
|
return LC709203F_DIRECTION_AUTO; |
|
case 1: |
|
return LC709203F_DIRECTION_CHARGE; |
|
case 0xFFFF: |
|
return LC709203F_DIRECTION_DISCHARGE; |
|
default: |
|
LOG_ERR("Invalid current direction: %d", num); |
|
return LC709203F_DIRECTION_AUTO; |
|
} |
|
} |
|
|
|
/* |
|
* Device initialization function. |
|
*/ |
|
static int lc709203f_init(const struct device *dev) |
|
{ |
|
const struct lc709203f_config *config = dev->config; |
|
int ret = 0; |
|
|
|
if (!device_is_ready(config->i2c.bus)) { |
|
LOG_ERR("I2C bus not ready"); |
|
return -ENODEV; |
|
} |
|
|
|
enum lc709203f_power_mode mode = LC709203F_POWER_MODE_OPERATIONAL; |
|
|
|
LOG_DBG("Get power mode"); |
|
ret = lc709203f_get_power_mode(dev, &mode); |
|
if (ret) { |
|
LOG_ERR("Failed to get power mode: %d", ret); |
|
} |
|
|
|
LOG_DBG("Power mode: %d", mode); |
|
if (mode == LC709203F_POWER_MODE_SLEEP) { |
|
LOG_DBG("Set Power mode"); |
|
ret = lc709203f_set_power_mode(dev, LC709203F_POWER_MODE_OPERATIONAL); |
|
|
|
if (ret) { |
|
LOG_ERR("Failed to set power mode: %d", ret); |
|
} |
|
} |
|
|
|
LOG_DBG("Set battery pack: %s", config->battery_apa); |
|
ret = lc709203f_set_apa(dev, lc709203f_string_to_apa(config->battery_apa)); |
|
|
|
if (ret) { |
|
LOG_ERR("Failed to set battery pack: %d", ret); |
|
} |
|
|
|
LOG_DBG("Set battery profile: %d", config->battery_profile); |
|
ret = lc709203f_set_battery_profile(dev, config->battery_profile); |
|
|
|
if (ret) { |
|
LOG_ERR("Failed to set battery profile: %d", ret); |
|
} |
|
|
|
if (config->thermistor) { |
|
LOG_DBG("Set temperature mode: %d", config->thermistor_mode); |
|
lc709203f_set_temp_mode(dev, config->thermistor_mode); |
|
if (ret) { |
|
LOG_ERR("Failed to set temperature mode: %d", ret); |
|
} |
|
|
|
LOG_DBG("Set thermistor B value: %d", config->thermistor_b_value); |
|
ret = lc709203f_set_thermistor_b(dev, config->thermistor_b_value); |
|
|
|
if (ret) { |
|
LOG_ERR("Failed to set thermistor B value: %d", ret); |
|
} |
|
|
|
LOG_DBG("Set thermistor APT: %d", config->thermistor_apt); |
|
ret = lc709203f_set_apt(dev, config->thermistor_apt); |
|
|
|
if (ret) { |
|
LOG_ERR("Failed to set thermistor APT: %d", ret); |
|
} |
|
} |
|
|
|
if (config->initial_rsoc) { |
|
LOG_DBG("lc709203f_set_initial_rsoc"); |
|
ret = lc709203f_set_initial_rsoc(dev); |
|
|
|
if (ret) { |
|
LOG_ERR("Quickstart failed: %d", ret); |
|
return ret; |
|
} |
|
} |
|
|
|
LOG_DBG("initialized"); |
|
return 0; |
|
} |
|
|
|
static int lc709203f_get_prop(const struct device *dev, fuel_gauge_prop_t prop, |
|
union fuel_gauge_prop_val *val) |
|
{ |
|
int rc = 0; |
|
uint16_t tmp_val = 0; |
|
const struct lc709203f_config *config = dev->config; |
|
|
|
switch (prop) { |
|
case FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE: |
|
rc = lc709203f_get_rsoc(dev, &val->relative_state_of_charge); |
|
break; |
|
case FUEL_GAUGE_TEMPERATURE: |
|
if (!config->thermistor) { |
|
LOG_ERR("Thermistor not enabled"); |
|
return -ENOTSUP; |
|
} |
|
rc = lc709203f_get_cell_temperature(dev, &val->temperature); |
|
break; |
|
case FUEL_GAUGE_VOLTAGE: |
|
rc = lc709203f_get_cell_voltage(dev, &tmp_val); |
|
val->voltage = tmp_val * 1000; |
|
break; |
|
case FUEL_GAUGE_SBS_MODE: |
|
rc = lc709203f_get_power_mode(dev, (enum lc709203f_power_mode *)&val->sbs_mode); |
|
break; |
|
case FUEL_GAUGE_DESIGN_CAPACITY: { |
|
enum lc709203f_battery_apa apa = LC709203F_APA_100MAH; |
|
|
|
rc = lc709203f_get_apa(dev, &apa); |
|
|
|
switch (apa) { |
|
case LC709203F_APA_100MAH: |
|
val->design_cap = 100; |
|
break; |
|
case LC709203F_APA_200MAH: |
|
val->design_cap = 200; |
|
break; |
|
case LC709203F_APA_500MAH: |
|
val->design_cap = 500; |
|
break; |
|
case LC709203F_APA_1000MAH: |
|
val->design_cap = 1000; |
|
break; |
|
case LC709203F_APA_2000MAH: |
|
val->design_cap = 2000; |
|
break; |
|
case LC709203F_APA_3000MAH: |
|
val->design_cap = 3000; |
|
break; |
|
default: |
|
LOG_ERR("Invalid battery capacity: %d", apa); |
|
return -EINVAL; |
|
} |
|
break; |
|
} |
|
case FUEL_GAUGE_CURRENT_DIRECTION: |
|
rc = lc709203f_get_current_direction( |
|
dev, (enum lc709203f_current_direction *)&val->current_direction); |
|
break; |
|
case FUEL_GAUGE_STATE_OF_CHARGE_ALARM: |
|
rc = lc709203f_get_alarm_low_rsoc(dev, &val->state_of_charge_alarm); |
|
break; |
|
case FUEL_GAUGE_LOW_VOLTAGE_ALARM: |
|
rc = lc709203f_get_alarm_low_voltage(dev, &tmp_val); |
|
val->low_voltage_alarm = tmp_val * 1000; |
|
break; |
|
default: |
|
rc = -ENOTSUP; |
|
break; |
|
} |
|
|
|
return rc; |
|
} |
|
|
|
static int lc709203f_set_prop(const struct device *dev, fuel_gauge_prop_t prop, |
|
union fuel_gauge_prop_val val) |
|
{ |
|
int rc = 0; |
|
|
|
switch (prop) { |
|
case FUEL_GAUGE_SBS_MODE: |
|
rc = lc709203f_set_power_mode(dev, lc709203f_num_to_power_mode(val.sbs_mode)); |
|
break; |
|
case FUEL_GAUGE_CURRENT_DIRECTION: |
|
rc = lc709203f_set_current_direction( |
|
dev, lc709203f_num_to_current_direction(val.current_direction)); |
|
break; |
|
case FUEL_GAUGE_STATE_OF_CHARGE_ALARM: |
|
rc = lc709203f_set_alarm_low_rsoc(dev, val.state_of_charge_alarm); |
|
break; |
|
case FUEL_GAUGE_LOW_VOLTAGE_ALARM: |
|
rc = lc709203f_set_alarm_low_voltage(dev, val.low_voltage_alarm / 1000); |
|
break; |
|
default: |
|
rc = -ENOTSUP; |
|
break; |
|
} |
|
|
|
return rc; |
|
} |
|
|
|
static DEVICE_API(fuel_gauge, lc709203f_driver_api) = { |
|
.get_property = &lc709203f_get_prop, |
|
.set_property = &lc709203f_set_prop, |
|
}; |
|
|
|
#define LC709203F_INIT(inst) \ |
|
\ |
|
static const struct lc709203f_config lc709203f_config_##inst = { \ |
|
.i2c = I2C_DT_SPEC_INST_GET(inst), \ |
|
.initial_rsoc = DT_INST_PROP(inst, initial_rsoc), \ |
|
.battery_apa = DT_INST_PROP(inst, apa), \ |
|
.battery_profile = DT_INST_PROP(inst, battery_profile), \ |
|
.thermistor = DT_INST_PROP(inst, thermistor), \ |
|
.thermistor_b_value = DT_INST_PROP(inst, thermistor_b_value), \ |
|
.thermistor_apt = DT_INST_PROP(inst, apt), \ |
|
.thermistor_mode = DT_INST_PROP(inst, thermistor_mode), \ |
|
}; \ |
|
\ |
|
DEVICE_DT_INST_DEFINE(inst, &lc709203f_init, NULL, NULL, &lc709203f_config_##inst, \ |
|
POST_KERNEL, CONFIG_FUEL_GAUGE_INIT_PRIORITY, \ |
|
&lc709203f_driver_api); |
|
|
|
DT_INST_FOREACH_STATUS_OKAY(LC709203F_INIT)
|
|
|