zephyr/drivers/fuel_gauge/max17048/emul_max17048.c
Michał Barnaś 4aac1756a9 i2c: use device instead of name for i2c dump messages
This commit changes the parameter of i2c_dump_msgs function from
string name to pointer to the device structure.
It allows for comparison of device pointers and allow to use
the printed device name in i2c shell commands.

Signed-off-by: Michał Barnaś <mb@semihalf.com>
2023-09-06 17:54:53 +02:00

157 lines
3.5 KiB
C

/*
* Copyright 2023, Alvaro Garcia <maxpowel@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Emulator for max17048 fuel gauge
*/
#define DT_DRV_COMPAT maxim_max17048
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(maxim_max17048);
#include <zephyr/device.h>
#include <zephyr/drivers/emul.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/i2c_emul.h>
#include <zephyr/sys/byteorder.h>
#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)