/* * Copyright 2023, Alvaro Garcia * * SPDX-License-Identifier: Apache-2.0 * * Emulator for max17048 fuel gauge */ #define DT_DRV_COMPAT maxim_max17048 #include LOG_MODULE_REGISTER(maxim_max17048); #include #include #include #include #include #include "max17048.h" static int crate_value = 0x4000; void emul_max17048_set_crate_status(int value) { crate_value = value; } /** Static configuration for the emulator */ struct max17048_emul_cfg { /** I2C address of emulator */ uint16_t addr; }; static int emul_max17048_reg_write(const struct emul *target, int reg, int val) { return -EIO; } static int emul_max17048_reg_read(const struct emul *target, int reg, int *val) { switch (reg) { case REGISTER_VERSION: *val = 0x1000; break; case REGISTER_CRATE: *val = crate_value; break; case REGISTER_SOC: *val = 0x3525; break; case REGISTER_VCELL: *val = 0x4387; break; default: LOG_ERR("Unknown register 0x%x read", reg); return -EIO; } LOG_INF("read 0x%x = 0x%x", reg, *val); return 0; } static int max17048_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, int num_msgs, int addr) { /* Largely copied from emul_bmi160.c */ unsigned int val; int reg; int rc; __ASSERT_NO_MSG(msgs && num_msgs); i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); switch (num_msgs) { case 2: if (msgs->flags & I2C_MSG_READ) { LOG_ERR("Unexpected read"); return -EIO; } if (msgs->len != 1) { LOG_ERR("Unexpected msg0 length %d", msgs->len); return -EIO; } reg = msgs->buf[0]; /* Now process the 'read' part of the message */ msgs++; if (msgs->flags & I2C_MSG_READ) { switch (msgs->len - 1) { case 1: rc = emul_max17048_reg_read(target, reg, &val); if (rc) { /* Return before writing bad value to message buffer */ return rc; } /* SBS uses SMBus, which sends data in little-endian format. */ sys_put_le16(val, msgs->buf); break; default: LOG_ERR("Unexpected msg1 length %d", msgs->len); return -EIO; } } else { /* We write a word (2 bytes by the SBS spec) */ if (msgs->len != 2) { LOG_ERR("Unexpected msg1 length %d", msgs->len); } uint16_t value = sys_get_le16(msgs->buf); rc = emul_max17048_reg_write(target, reg, value); } break; default: LOG_ERR("Invalid number of messages: %d", num_msgs); return -EIO; } return rc; } static const struct i2c_emul_api max17048_emul_api_i2c = { .transfer = max17048_emul_transfer_i2c, }; /** * Set up a new emulator (I2C) * * @param emul Emulation information * @param parent Device to emulate * @return 0 indicating success (always) */ static int emul_max17048_init(const struct emul *target, const struct device *parent) { ARG_UNUSED(target); ARG_UNUSED(parent); return 0; } /* * Main instantiation macro. */ #define MAX17048_EMUL(n) \ static const struct max17048_emul_cfg max17048_emul_cfg_##n = { \ .addr = DT_INST_REG_ADDR(n), \ }; \ EMUL_DT_INST_DEFINE(n, emul_max17048_init, NULL, \ &max17048_emul_cfg_##n, &max17048_emul_api_i2c, NULL) DT_INST_FOREACH_STATUS_OKAY(MAX17048_EMUL)