summaryrefslogtreecommitdiff
path: root/zephyr/emul/emul_smart_battery.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /zephyr/emul/emul_smart_battery.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-14496.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'zephyr/emul/emul_smart_battery.c')
-rw-r--r--zephyr/emul/emul_smart_battery.c893
1 files changed, 0 insertions, 893 deletions
diff --git a/zephyr/emul/emul_smart_battery.c b/zephyr/emul/emul_smart_battery.c
deleted file mode 100644
index 4b1d87336e..0000000000
--- a/zephyr/emul/emul_smart_battery.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/* Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#define DT_DRV_COMPAT zephyr_smart_battery
-
-#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
-#include <logging/log.h>
-LOG_MODULE_REGISTER(smart_battery);
-
-#include <device.h>
-#include <emul.h>
-#include <drivers/i2c.h>
-#include <drivers/i2c_emul.h>
-
-#include "emul/emul_common_i2c.h"
-#include "emul/emul_smart_battery.h"
-
-#include "crc8.h"
-#include "battery_smart.h"
-
-#define SBAT_DATA_FROM_I2C_EMUL(_emul) \
- CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \
- struct sbat_emul_data, common)
-
-/** Run-time data used by the emulator */
-struct sbat_emul_data {
- /** Common I2C data */
- struct i2c_common_emul_data common;
-
- /** Data required to simulate battery */
- struct sbat_emul_bat_data bat;
- /** Command that should be handled next */
- int cur_cmd;
- /** Message buffer which is used to handle smb transactions */
- uint8_t msg_buf[MSG_BUF_LEN];
- /** Total bytes that were generated in response to smb read operation */
- int num_to_read;
-};
-
-/** Check description in emul_smart_battery.h */
-struct sbat_emul_bat_data *sbat_emul_get_bat_data(struct i2c_emul *emul)
-{
- struct sbat_emul_data *data;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
-
- return &data->bat;
-}
-
-/** Check description in emul_smart_battery.h */
-uint16_t sbat_emul_date_to_word(unsigned int day, unsigned int month,
- unsigned int year)
-{
- year -= MANUFACTURE_DATE_YEAR_OFFSET;
- year <<= MANUFACTURE_DATE_YEAR_SHIFT;
- year &= MANUFACTURE_DATE_YEAR_MASK;
- month <<= MANUFACTURE_DATE_MONTH_SHIFT;
- month &= MANUFACTURE_DATE_MONTH_MASK;
- day <<= MANUFACTURE_DATE_DAY_SHIFT;
- day &= MANUFACTURE_DATE_DAY_MASK;
-
- return day | month | year;
-}
-
-/**
- * @brief Compute CRC from the beginning of the message
- *
- * @param addr Smart battery address on SMBus
- * @param read If message for which CRC is computed is read. For read message
- * byte command and repeated address is added to CRC
- * @param cmd Command used in read message
- *
- * @return pec CRC from first bytes of message
- */
-static uint8_t sbat_emul_pec_head(uint8_t addr, int read, uint8_t cmd)
-{
- uint8_t pec;
-
- addr <<= 1;
-
- pec = cros_crc8(&addr, 1);
- if (!read) {
- return pec;
- }
-
- pec = cros_crc8_arg(&cmd, 1, pec);
- addr |= I2C_MSG_READ;
- pec = cros_crc8_arg(&addr, 1, pec);
-
- return pec;
-}
-
-/**
- * @brief Convert from 10mW power units to mA current under given mV voltage
- *
- * @param mw Power in 10mW units
- * @param mv Voltage in mV units
- *
- * @return Current in mA units
- */
-static uint16_t sbat_emul_10mw_to_ma(int mw, int mv)
-{
- /* Smart battery use 10mW units, convert to mW */
- mw *= 10;
- /* Multiple by 1000 to get mA instead of A */
- return 1000 * mw/mv;
-}
-
-/**
- * @brief Convert from mA current to 10mW power under given mV voltage
- *
- * @param ma Current in mA units
- * @param mv Voltage in mV units
- *
- * @return Power in 10mW units
- */
-static uint16_t sbat_emul_ma_to_10mw(int ma, int mv)
-{
- int mw;
- /* Divide by 1000 to get mW instead of uW */
- mw = ma * mv / 1000;
- /* Smart battery use 10mW units, convert to 10mW */
- return mw / 10;
-}
-
-/**
- * @brief Get time in minutes how long it will take to get given amount of
- * charge at given current flow
- *
- * @param bat Pointer to battery data to set error code in case of
- * over/under flow in time calculation
- * @param rate Rate of current in mAh
- * @param cap Required amount of charge in mA
- * @param time Pointer to memory where calculated time will be stored
- *
- * @return 0 on success
- * @return -EINVAL when over or under flow occurred
- */
-static int sbat_emul_get_time_to_complete(struct sbat_emul_bat_data *bat,
- int rate, int cap, uint16_t *ret_time)
-{
- int time;
-
- /* At negative rate process never ends, return maximum value */
- if (rate <= 0) {
- *ret_time = UINT16_MAX;
-
- return 0;
- }
- /* Convert capacity from mAh to mAmin */
- time = cap * 60 / rate;
- /* Check overflow */
- if (time >= UINT16_MAX) {
- *ret_time = UINT16_MAX;
- bat->error_code = STATUS_CODE_OVERUNDERFLOW;
-
- return -EINVAL;
- }
- /* Check underflow */
- if (time < 0) {
- *ret_time = 0;
- bat->error_code = STATUS_CODE_OVERUNDERFLOW;
-
- return -EINVAL;
- }
-
- *ret_time = time;
-
- return 0;
-}
-
-/**
- * @brief Get time in minutes how long it will take to charge battery
- *
- * @param bat Pointer to battery data
- * @param rate Rate of charging current in mAh
- * @param time Pointer to memory where calculated time will be stored
- *
- * @return 0 on success
- * @return -EINVAL when over or under flow occurred
- */
-static int sbat_emul_time_to_full(struct sbat_emul_bat_data *bat, int rate,
- uint16_t *time)
-{
- int cap;
-
- cap = bat->full_cap - bat->cap;
- return sbat_emul_get_time_to_complete(bat, rate, cap, time);
-}
-
-/**
- * @brief Get time in minutes how long it will take to discharge battery. Note,
- * that rate should be negative to indicate discharging.
- *
- * @param bat Pointer to battery data
- * @param rate Rate of charging current in mAh
- * @param time Pointer to memory where calculated time will be stored
- *
- * @return 0 on success
- * @return -EINVAL when over or under flow occurred
- */
-static int sbat_emul_time_to_empty(struct sbat_emul_bat_data *bat, int rate,
- uint16_t *time)
-{
- int cap;
-
- /* Reverse to have discharging rate instead of charging rate */
- rate = -rate;
- cap = bat->cap;
- return sbat_emul_get_time_to_complete(bat, rate, cap, time);
-}
-
-/**
- * @brief Check if battery can supply for 10 seconds additional power/current
- * set in at_rate register.
- *
- * @param bat Pointer to battery data
- * @param rate Rate of charging current in mAh
- * @param ok Pointer to memory where 0 is written if battery is able to supply
- * additional power/curent or 1 is written if battery is unable
- * to do so.
- *
- * @return 0 on success
- */
-static int sbat_emul_read_at_rate_ok(struct sbat_emul_bat_data *bat,
- uint16_t *ok)
-{
- int rem_time_s;
- int rate;
-
- rate = bat->at_rate;
- if (bat->mode & MODE_CAPACITY) {
- rate = sbat_emul_10mw_to_ma(rate, bat->design_mv);
- }
-
- /* Add current battery usage */
- rate += bat->cur;
- if (rate >= 0) {
- /* Battery will be charged */
- *ok = 1;
-
- return 0;
- }
- /* Reverse to have discharging rate instead of charging rate */
- rate = -rate;
-
- rem_time_s = bat->cap * 3600 / rate;
- if (rem_time_s > 10) {
- /*
- * Battery can support 10 seconds of additional at_rate
- * current/power
- */
- *ok = 1;
- } else {
- *ok = 0;
- }
-
- return 0;
-}
-
-/**
- * @brief Get battery status. This function use emulated status register and
- * set or clear some of the flags based on other properties of emulated
- * smart battery. Discharge bit, capacity alarm, time alarm, fully
- * discharged bit and error code are controlled by battery properties.
- * Terminate charge/discharge/overcharge alarms are set only if they are
- * set in emulated status register and battery is charging/discharging,
- * so they are partialy controlled by emulated status register.
- * Other bits are controlled by emulated status register
- *
- * @param emul Pointer to smart battery emulator
- *
- * @return value which equals to computed status register
- */
-static uint16_t sbat_emul_read_status(struct i2c_emul *emul)
-{
- uint16_t status, cap, rem_time, charge_percent;
- struct sbat_emul_bat_data *bat;
- struct sbat_emul_data *data;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
- bat = &data->bat;
-
- status = bat->status;
-
- /*
- * Over charged and terminate charger alarm cannot appear when battery
- * is not charged
- */
- if (bat->cur <= 0) {
- status &= ~(STATUS_TERMINATE_CHARGE_ALARM |
- STATUS_OVERCHARGED_ALARM);
- status |= STATUS_DISCHARGING;
- }
- /* Terminate discharge alarm cannot appear when battery is charged */
- if (bat->cur >= 0) {
- status &= ~(STATUS_TERMINATE_DISCHARGE_ALARM |
- STATUS_DISCHARGING);
- }
-
- sbat_emul_get_word_val(emul, SB_REMAINING_CAPACITY, &cap);
- if (bat->cap_alarm && cap < bat->cap_alarm) {
- status |= STATUS_REMAINING_CAPACITY_ALARM;
- } else {
- status &= ~STATUS_REMAINING_CAPACITY_ALARM;
- }
-
- sbat_emul_get_word_val(emul, SB_AVERAGE_TIME_TO_EMPTY, &rem_time);
- if (bat->time_alarm && rem_time < bat->time_alarm) {
- status |= STATUS_REMAINING_TIME_ALARM;
- } else {
- status &= ~STATUS_REMAINING_TIME_ALARM;
- }
-
- /* Unset fully discharged bit when charge is grater than 20% */
- sbat_emul_get_word_val(emul, SB_RELATIVE_STATE_OF_CHARGE,
- &charge_percent);
- if (charge_percent > 20) {
- status &= ~STATUS_FULLY_DISCHARGED;
- } else {
- status |= STATUS_FULLY_DISCHARGED;
- }
-
- status |= bat->error_code & STATUS_ERR_CODE_MASK;
-
- return status;
-}
-
-/** Check description in emul_smart_battery.h */
-int sbat_emul_get_word_val(struct i2c_emul *emul, int cmd, uint16_t *val)
-{
- struct sbat_emul_bat_data *bat;
- struct sbat_emul_data *data;
- int mode_mw;
- int rate;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
- bat = &data->bat;
- mode_mw = bat->mode & MODE_CAPACITY;
-
- switch (cmd) {
- case SB_MANUFACTURER_ACCESS:
- *val = bat->mf_access;
- return 0;
- case SB_REMAINING_CAPACITY_ALARM:
- *val = bat->cap_alarm;
- return 0;
- case SB_REMAINING_TIME_ALARM:
- *val = bat->time_alarm;
- return 0;
- case SB_BATTERY_MODE:
- *val = bat->mode;
- return 0;
- case SB_AT_RATE:
- *val = bat->at_rate;
- return 0;
- case SB_AT_RATE_TIME_TO_FULL:
- /* Support for reporting time to full in mW mode is optional */
- if (mode_mw && !bat->at_rate_full_mw_support) {
- bat->error_code = STATUS_CODE_OVERUNDERFLOW;
- *val = UINT16_MAX;
-
- return -EINVAL;
- }
-
- rate = bat->at_rate;
- if (mode_mw) {
- rate = sbat_emul_10mw_to_ma(rate, bat->design_mv);
- }
- return sbat_emul_time_to_full(bat, rate, val);
-
- case SB_AT_RATE_TIME_TO_EMPTY:
- rate = bat->at_rate;
- if (mode_mw) {
- rate = sbat_emul_10mw_to_ma(rate, bat->design_mv);
- }
- return sbat_emul_time_to_empty(bat, rate, val);
-
- case SB_AT_RATE_OK:
- return sbat_emul_read_at_rate_ok(bat, val);
- case SB_TEMPERATURE:
- *val = bat->temp;
- return 0;
- case SB_VOLTAGE:
- *val = bat->volt;
- return 0;
- case SB_CURRENT:
- *val = bat->cur;
- return 0;
- case SB_AVERAGE_CURRENT:
- *val = bat->avg_cur;
- return 0;
- case SB_MAX_ERROR:
- *val = bat->max_error;
- return 0;
- case SB_RELATIVE_STATE_OF_CHARGE:
- /* Percent of charge according to full capacity */
- *val = 100 * bat->cap / bat->full_cap;
- return 0;
- case SB_ABSOLUTE_STATE_OF_CHARGE:
- /* Percent of charge according to design capacity */
- *val = 100 * bat->cap / bat->design_cap;
- return 0;
- case SB_REMAINING_CAPACITY:
- if (mode_mw) {
- *val = sbat_emul_ma_to_10mw(bat->cap, bat->design_mv);
- } else {
- *val = bat->cap;
- }
- return 0;
- case SB_FULL_CHARGE_CAPACITY:
- if (mode_mw) {
- *val = sbat_emul_ma_to_10mw(bat->full_cap,
- bat->design_mv);
- } else {
- *val = bat->full_cap;
- }
- return 0;
- case SB_RUN_TIME_TO_EMPTY:
- rate = bat->cur;
- return sbat_emul_time_to_empty(bat, rate, val);
- case SB_AVERAGE_TIME_TO_EMPTY:
- rate = bat->avg_cur;
- return sbat_emul_time_to_empty(bat, rate, val);
- case SB_AVERAGE_TIME_TO_FULL:
- rate = bat->avg_cur;
- return sbat_emul_time_to_full(bat, rate, val);
- case SB_CHARGING_CURRENT:
- *val = bat->desired_charg_cur;
- return 0;
- case SB_CHARGING_VOLTAGE:
- *val = bat->desired_charg_volt;
- return 0;
- case SB_BATTERY_STATUS:
- *val = sbat_emul_read_status(emul);
- return 0;
- case SB_CYCLE_COUNT:
- *val = bat->cycle_count;
- return 0;
- case SB_DESIGN_CAPACITY:
- if (mode_mw) {
- *val = sbat_emul_ma_to_10mw(bat->design_cap,
- bat->design_mv);
- } else {
- *val = bat->design_cap;
- }
- return 0;
- case SB_DESIGN_VOLTAGE:
- *val = bat->design_mv;
- return 0;
- case SB_SPECIFICATION_INFO:
- *val = bat->spec_info;
- return 0;
- case SB_MANUFACTURE_DATE:
- *val = bat->mf_date;
- return 0;
- case SB_SERIAL_NUMBER:
- *val = bat->sn;
- return 0;
- default:
- /* Unknown command or return value is not word */
- return 1;
- }
-}
-
-/** Check description in emul_smart_battery.h */
-int sbat_emul_get_block_data(struct i2c_emul *emul, int cmd, uint8_t **blk,
- int *len)
-{
- struct sbat_emul_bat_data *bat;
- struct sbat_emul_data *data;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
- bat = &data->bat;
-
- switch (cmd) {
- case SB_MANUFACTURER_NAME:
- *blk = bat->mf_name;
- *len = bat->mf_name_len;
- return 0;
- case SB_DEVICE_NAME:
- *blk = bat->dev_name;
- *len = bat->dev_name_len;
- return 0;
- case SB_DEVICE_CHEMISTRY:
- *blk = bat->dev_chem;
- *len = bat->dev_chem_len;
- return 0;
- case SB_MANUFACTURER_DATA:
- *blk = bat->mf_data;
- *len = bat->mf_data_len;
- return 0;
- default:
- /* Unknown command or return value is not word */
- return 1;
- }
-}
-
-/**
- * @brief Append PEC to read command response if battery support it
- *
- * @param data Pointer to smart battery emulator data
- * @param cmd Command for which PEC is calculated
- */
-static void sbat_emul_append_pec(struct sbat_emul_data *data, int cmd)
-{
- uint8_t pec;
-
- if (BATTERY_SPEC_VERSION(data->bat.spec_info) ==
- BATTERY_SPEC_VER_1_1_WITH_PEC) {
- pec = sbat_emul_pec_head(data->common.cfg->addr, 1, cmd);
- pec = cros_crc8_arg(data->msg_buf, data->num_to_read, pec);
- data->msg_buf[data->num_to_read] = pec;
- data->num_to_read++;
- }
-}
-
-/** Check description in emul_smart_battery.h */
-void sbat_emul_set_response(struct i2c_emul *emul, int cmd, uint8_t *buf,
- int len, bool fail)
-{
- struct sbat_emul_data *data;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
-
- if (fail) {
- data->bat.error_code = STATUS_CODE_UNKNOWN_ERROR;
- data->num_to_read = 0;
- return;
- }
-
- data->num_to_read = MIN(len, MSG_BUF_LEN - 1);
- memcpy(data->msg_buf, buf, data->num_to_read);
- data->bat.error_code = STATUS_CODE_OK;
- sbat_emul_append_pec(data, cmd);
-}
-
-/**
- * @brief Function which handles read messages. It expects that data->cur_cmd
- * is set to command number which should be handled. It guarantee that
- * data->num_to_read is set to number of bytes in data->msg_buf on
- * successful handling read request. On error, data->num_to_read is
- * always set to 0.
- *
- * @param emul Pointer to smart battery emulator
- * @param reg Command selected by last write message. If data->cur_cmd is
- * different than SBAT_EMUL_NO_CMD, then reg should equal to
- * data->cur_cmd
- *
- * @return 0 on success
- * @return -EIO on error
- */
-static int sbat_emul_handle_read_msg(struct i2c_emul *emul, int reg)
-{
- struct sbat_emul_data *data;
- uint16_t word;
- uint8_t *blk;
- int ret, len;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
-
- if (data->cur_cmd == SBAT_EMUL_NO_CMD) {
- /* Unexpected read message without preceding command select */
- data->bat.error_code = STATUS_CODE_UNKNOWN_ERROR;
- return -EIO;
- }
- data->cur_cmd = SBAT_EMUL_NO_CMD;
- data->num_to_read = 0;
-
- /* Handle commands which return word */
- ret = sbat_emul_get_word_val(emul, reg, &word);
- if (ret < 0) {
- return -EIO;
- }
- if (ret == 0) {
- data->num_to_read = 2;
- data->msg_buf[0] = word & 0xff;
- data->msg_buf[1] = (word >> 8) & 0xff;
- data->bat.error_code = STATUS_CODE_OK;
- sbat_emul_append_pec(data, reg);
-
- return 0;
- }
-
- /* Handle commands which return block */
- ret = sbat_emul_get_block_data(emul, reg, &blk, &len);
- if (ret != 0) {
- if (ret == 1) {
- data->bat.error_code = STATUS_CODE_UNSUPPORTED;
- LOG_ERR("Unknown read command (0x%x)", reg);
- }
-
- return -EIO;
- }
-
- data->num_to_read = len + 1;
- data->msg_buf[0] = len;
- memcpy(&data->msg_buf[1], blk, len);
- data->bat.error_code = STATUS_CODE_OK;
- sbat_emul_append_pec(data, reg);
-
- return 0;
-}
-
-/**
- * @brief Function which finalize write messages.
- *
- * @param emul Pointer to smart battery emulator
- * @param reg First byte of write message, usually selected command
- * @param bytes Number of bytes received in data->msg_buf
- *
- * @return 0 on success
- * @return -EIO on error
- */
-static int sbat_emul_finalize_write_msg(struct i2c_emul *emul, int reg,
- int bytes)
-{
- struct sbat_emul_bat_data *bat;
- struct sbat_emul_data *data;
- uint16_t word;
- uint8_t pec;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
- bat = &data->bat;
-
- /*
- * Fail if:
- * - there are no bytes to handle
- * - there are too many bytes
- * - there is command byte and only one data byte
- */
- if (bytes <= 0 || bytes > 4 || bytes == 2) {
- data->bat.error_code = STATUS_CODE_BADSIZE;
- LOG_ERR("wrong write message size (%d)", bytes);
-
- return -EIO;
- }
-
- /* There is only command for read */
- if (bytes == 1) {
- data->cur_cmd = reg;
- return 0;
- }
-
- /* Handle PEC */
- data->msg_buf[0] = reg;
- if (bytes == 4) {
- if (BATTERY_SPEC_VERSION(data->bat.spec_info) !=
- BATTERY_SPEC_VER_1_1_WITH_PEC) {
- data->bat.error_code = STATUS_CODE_BADSIZE;
- LOG_ERR("Unexpected PEC; No support in this version");
-
- return -EIO;
- }
- pec = sbat_emul_pec_head(data->common.cfg->addr, 0, 0);
- pec = cros_crc8_arg(data->msg_buf, 3, pec);
- if (pec != data->msg_buf[3]) {
- data->bat.error_code = STATUS_CODE_UNKNOWN_ERROR;
- LOG_ERR("Wrong PEC 0x%x != 0x%x",
- pec, data->msg_buf[3]);
-
- return -EIO;
- }
- }
-
- word = ((int)data->msg_buf[2] << 8) | data->msg_buf[1];
-
- switch (data->msg_buf[0]) {
- case SB_MANUFACTURER_ACCESS:
- bat->mf_access = word;
- break;
- case SB_REMAINING_CAPACITY_ALARM:
- bat->cap_alarm = word;
- break;
- case SB_REMAINING_TIME_ALARM:
- bat->time_alarm = word;
- break;
- case SB_BATTERY_MODE:
- /* Allow to set only upper byte */
- bat->mode &= 0xff;
- bat->mode |= word & 0xff00;
- break;
- case SB_AT_RATE:
- bat->at_rate = word;
- break;
- default:
- data->bat.error_code = STATUS_CODE_ACCESS_DENIED;
- LOG_ERR("Unknown write command (0x%x)", data->msg_buf[0]);
-
- return -EIO;
- }
-
- data->bat.error_code = STATUS_CODE_OK;
-
- return 0;
-}
-
-/**
- * @brief Function called for each byte of write message which is saved in
- * data->msg_buf
- *
- * @param emul Pointer to smart battery emulator
- * @param reg First byte of write message, usually selected command
- * @param val Received byte of write message
- * @param bytes Number of bytes already received
- *
- * @return 0 on success
- */
-static int sbat_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val,
- int bytes)
-{
- struct sbat_emul_data *data;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
-
- if (bytes < MSG_BUF_LEN) {
- data->msg_buf[bytes] = val;
- }
-
- return 0;
-}
-
-/**
- * @brief Function called for each byte of read message. Byte from data->msg_buf
- * is copied to read message response.
- *
- * @param emul Pointer to smart battery emulator
- * @param reg First byte of last write message, usually selected command
- * @param val Pointer where byte to read should be stored
- * @param bytes Number of bytes already readed
- *
- * @return 0 on success
- */
-static int sbat_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val,
- int bytes)
-{
- struct sbat_emul_data *data;
-
- data = SBAT_DATA_FROM_I2C_EMUL(emul);
-
- if (bytes < data->num_to_read) {
- *val = data->msg_buf[bytes];
- }
-
- return 0;
-}
-
-/**
- * @brief Get currently accessed register, which always equals to selected
- * command.
- *
- * @param emul Pointer to smart battery emulator
- * @param reg First byte of last write message, usually selected command
- * @param bytes Number of bytes already handled from current message
- * @param read If currently handled is read message
- *
- * @return Currently accessed register
- */
-static int sbat_emul_access_reg(struct i2c_emul *emul, int reg, int bytes,
- bool read)
-{
- return reg;
-}
-
-/* Device instantiation */
-
-static struct i2c_emul_api sbat_emul_api = {
- .transfer = i2c_common_emul_transfer,
-};
-
-/**
- * @brief Set up a new Smart Battery emulator
- *
- * This should be called for each Smart Battery device that needs to be
- * emulated. It registers it with the I2C emulation controller.
- *
- * @param emul Emulation information
- * @param parent Device to emulate
- *
- * @return 0 indicating success (always)
- */
-static int sbat_emul_init(const struct emul *emul,
- const struct device *parent)
-{
- const struct i2c_common_emul_cfg *cfg = emul->cfg;
- struct i2c_common_emul_data *data = cfg->data;
- int ret;
-
- data->emul.api = &sbat_emul_api;
- data->emul.addr = cfg->addr;
- data->i2c = parent;
- data->cfg = cfg;
- i2c_common_emul_init(data);
-
- ret = i2c_emul_register(parent, emul->dev_label, &data->emul);
-
- return ret;
-}
-
-#define SMART_BATTERY_EMUL(n) \
- static struct sbat_emul_data sbat_emul_data_##n = { \
- .bat = { \
- .mf_access = DT_INST_PROP(n, mf_access), \
- .at_rate_full_mw_support = DT_INST_PROP(n, \
- at_rate_full_mw_support), \
- .spec_info = ((DT_STRING_TOKEN(DT_DRV_INST(n), \
- version) << \
- BATTERY_SPEC_VERSION_SHIFT) & \
- BATTERY_SPEC_VERSION_MASK) | \
- ((DT_INST_PROP(n, vscale) << \
- BATTERY_SPEC_VSCALE_SHIFT) & \
- BATTERY_SPEC_VSCALE_MASK) | \
- ((DT_INST_PROP(n, ipscale) << \
- BATTERY_SPEC_IPSCALE_SHIFT) & \
- BATTERY_SPEC_IPSCALE_MASK) | \
- BATTERY_SPEC_REVISION_1, \
- .mode = (DT_INST_PROP(n, \
- int_charge_controller) * \
- MODE_INTERNAL_CHARGE_CONTROLLER) | \
- (DT_INST_PROP(n, primary_battery) * \
- MODE_PRIMARY_BATTERY_SUPPORT), \
- .design_mv = DT_INST_PROP(n, design_mv), \
- .design_cap = DT_INST_PROP(n, design_cap), \
- .temp = DT_INST_PROP(n, temperature), \
- .volt = DT_INST_PROP(n, volt), \
- .cur = DT_INST_PROP(n, cur), \
- .avg_cur = DT_INST_PROP(n, avg_cur), \
- .max_error = DT_INST_PROP(n, max_error), \
- .cap = DT_INST_PROP(n, cap), \
- .full_cap = DT_INST_PROP(n, full_cap), \
- .desired_charg_cur = DT_INST_PROP(n, \
- desired_charg_cur), \
- .desired_charg_volt = DT_INST_PROP(n, \
- desired_charg_volt), \
- .cycle_count = DT_INST_PROP(n, cycle_count), \
- .sn = DT_INST_PROP(n, serial_number), \
- .mf_name = DT_INST_PROP(n, mf_name), \
- .mf_name_len = sizeof( \
- DT_INST_PROP(n, mf_name)) - 1, \
- .mf_data = DT_INST_PROP(n, mf_data), \
- .mf_data_len = sizeof( \
- DT_INST_PROP(n, mf_data)) - 1, \
- .dev_name = DT_INST_PROP(n, dev_name), \
- .dev_name_len = sizeof( \
- DT_INST_PROP(n, dev_name)) - 1, \
- .dev_chem = DT_INST_PROP(n, dev_chem), \
- .dev_chem_len = sizeof( \
- DT_INST_PROP(n, dev_chem)) - 1, \
- .mf_date = 0, \
- .cap_alarm = 0, \
- .time_alarm = 0, \
- .at_rate = 0, \
- .status = STATUS_INITIALIZED, \
- .error_code = STATUS_CODE_OK, \
- }, \
- .cur_cmd = SBAT_EMUL_NO_CMD, \
- .common = { \
- .start_write = NULL, \
- .write_byte = sbat_emul_write_byte, \
- .finish_write = sbat_emul_finalize_write_msg, \
- .start_read = sbat_emul_handle_read_msg, \
- .read_byte = sbat_emul_read_byte, \
- .finish_read = NULL, \
- .access_reg = sbat_emul_access_reg, \
- }, \
- }; \
- \
- static const struct i2c_common_emul_cfg sbat_emul_cfg_##n = { \
- .i2c_label = DT_INST_BUS_LABEL(n), \
- .dev_label = DT_INST_LABEL(n), \
- .data = &sbat_emul_data_##n.common, \
- .addr = DT_INST_REG_ADDR(n), \
- }; \
- EMUL_DEFINE(sbat_emul_init, DT_DRV_INST(n), &sbat_emul_cfg_##n, \
- &sbat_emul_data_##n)
-
-DT_INST_FOREACH_STATUS_OKAY(SMART_BATTERY_EMUL)
-
-#define SMART_BATTERY_EMUL_CASE(n) \
- case DT_INST_DEP_ORD(n): return &sbat_emul_data_##n.common.emul;
-
-/** Check description in emul_smart_battery.h */
-struct i2c_emul *sbat_emul_get_ptr(int ord)
-{
- switch (ord) {
- DT_INST_FOREACH_STATUS_OKAY(SMART_BATTERY_EMUL_CASE)
-
- default:
- return NULL;
- }
-}