emul: Add data and parent pointers to emulators
Emulators are difficult to work with, they generally require maintaining some state in a mutable data struct. Since the emulator struct doesn't support a data field like devices do, the pattern seems to be to add it to the configuration. This makes following the logic of where things are difficult. 1. Add a `struct emul *parent` structure to the espi/i2c/spi emulator structs to make it easier when casting up. 2. Add a `void *data` field to `struct emul` to hold the data for emulators. Signed-off-by: Yuval Peress <peress@chromium.org>
This commit is contained in:
parent
512dab526c
commit
2629fc566d
|
@ -56,6 +56,8 @@ struct emul {
|
|||
const char *dev_label;
|
||||
/** Emulator-specific configuration data */
|
||||
const void *cfg;
|
||||
/** Emulator-specific data */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -78,13 +80,15 @@ extern const struct emul __emul_list_end[];
|
|||
* typedef)
|
||||
* @param node_id Node ID of the driver to emulate (e.g. DT_DRV_INST(n))
|
||||
* @param cfg_ptr emulator-specific configuration data
|
||||
* @param data_ptr emulator-specific data
|
||||
*/
|
||||
#define EMUL_DEFINE(init_ptr, node_id, cfg_ptr) \
|
||||
static struct emul EMUL_REG_NAME(node_id) \
|
||||
__attribute__((__section__(".emulators"))) __used = { \
|
||||
.init = (init_ptr), \
|
||||
.dev_label = DT_LABEL(node_id), \
|
||||
.cfg = (cfg_ptr), \
|
||||
#define EMUL_DEFINE(init_ptr, node_id, cfg_ptr, data_ptr) \
|
||||
static struct emul EMUL_REG_NAME(node_id) __attribute__((__section__(".emulators"))) \
|
||||
__used = { \
|
||||
.init = (init_ptr), \
|
||||
.dev_label = DT_LABEL(node_id), \
|
||||
.cfg = (cfg_ptr), \
|
||||
.data = (data_ptr), \
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <zephyr/types.h>
|
||||
#include <device.h>
|
||||
#include <drivers/emul.h>
|
||||
|
||||
/**
|
||||
* @brief eSPI Emulation Interface
|
||||
|
@ -111,9 +112,11 @@ struct emul_espi_device_api {
|
|||
/** Node in a linked list of emulators for eSPI devices */
|
||||
struct espi_emul {
|
||||
sys_snode_t node;
|
||||
/* API provided for this device */
|
||||
/** Parent emulator */
|
||||
const struct emul *parent;
|
||||
/** API provided for this device */
|
||||
const struct emul_espi_device_api *api;
|
||||
/* eSPI chip-select of the emulated device */
|
||||
/** eSPI chip-select of the emulated device */
|
||||
uint16_t chipsel;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <zephyr/types.h>
|
||||
#include <device.h>
|
||||
#include <drivers/emul.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -34,6 +35,9 @@ struct i2c_emul_api;
|
|||
struct i2c_emul {
|
||||
sys_snode_t node;
|
||||
|
||||
/** Parent emulator */
|
||||
const struct emul *parent;
|
||||
|
||||
/* API provided for this device */
|
||||
const struct i2c_emul_api *api;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <zephyr/types.h>
|
||||
#include <device.h>
|
||||
#include <drivers/emul.h>
|
||||
|
||||
/**
|
||||
* @brief SPI Emulation Interface
|
||||
|
@ -34,6 +35,9 @@ struct spi_emul_api;
|
|||
struct spi_emul {
|
||||
sys_snode_t node;
|
||||
|
||||
/** Parent emulator */
|
||||
const struct emul *parent;
|
||||
|
||||
/* API provided for this device */
|
||||
const struct spi_emul_api *api;
|
||||
|
||||
|
|
|
@ -32,8 +32,6 @@ struct bmi160_emul_data {
|
|||
};
|
||||
/** BMI160 device being emulated */
|
||||
const struct device *dev;
|
||||
/** Configuration information */
|
||||
const struct bmi160_emul_cfg *cfg;
|
||||
uint8_t pmu_status;
|
||||
/** Current register to read (address) */
|
||||
uint32_t cur_reg;
|
||||
|
@ -43,8 +41,6 @@ struct bmi160_emul_data {
|
|||
struct bmi160_emul_cfg {
|
||||
/** Label of the SPI bus this emulator connects to */
|
||||
const char *bus_label;
|
||||
/** Pointer to run-time data */
|
||||
struct bmi160_emul_data *data;
|
||||
/** Chip registers */
|
||||
uint8_t *reg;
|
||||
union {
|
||||
|
@ -77,9 +73,10 @@ static void sample_read(struct bmi160_emul_data *data, union bmi160_sample *buf)
|
|||
memcpy(buf->raw, raw_data, ARRAY_SIZE(raw_data));
|
||||
}
|
||||
|
||||
static void reg_write(const struct bmi160_emul_cfg *cfg, int regn, int val)
|
||||
static void reg_write(const struct emul *emulator, int regn, int val)
|
||||
{
|
||||
struct bmi160_emul_data *data = cfg->data;
|
||||
struct bmi160_emul_data *data = emulator->data;
|
||||
const struct bmi160_emul_cfg *cfg = emulator->cfg;
|
||||
|
||||
LOG_INF("write %x = %x", regn, val);
|
||||
cfg->reg[regn] = val;
|
||||
|
@ -136,9 +133,10 @@ static void reg_write(const struct bmi160_emul_cfg *cfg, int regn, int val)
|
|||
}
|
||||
}
|
||||
|
||||
static int reg_read(const struct bmi160_emul_cfg *cfg, int regn)
|
||||
static int reg_read(const struct emul *emulator, int regn)
|
||||
{
|
||||
struct bmi160_emul_data *data = cfg->data;
|
||||
struct bmi160_emul_data *data = emulator->data;
|
||||
const struct bmi160_emul_cfg *cfg = emulator->cfg;
|
||||
int val;
|
||||
|
||||
LOG_INF("read %x =", regn);
|
||||
|
@ -185,13 +183,11 @@ static int bmi160_emul_io_spi(struct spi_emul *emul,
|
|||
const struct spi_buf_set *rx_bufs)
|
||||
{
|
||||
struct bmi160_emul_data *data;
|
||||
const struct bmi160_emul_cfg *cfg;
|
||||
const struct spi_buf *tx, *txd, *rxd;
|
||||
unsigned int regn, val;
|
||||
int count;
|
||||
|
||||
data = CONTAINER_OF(emul, struct bmi160_emul_data, emul_spi);
|
||||
cfg = data->cfg;
|
||||
|
||||
__ASSERT_NO_MSG(tx_bufs || rx_bufs);
|
||||
__ASSERT_NO_MSG(!tx_bufs || !rx_bufs ||
|
||||
|
@ -214,11 +210,11 @@ static int bmi160_emul_io_spi(struct spi_emul *emul,
|
|||
case 1:
|
||||
if (regn & BMI160_REG_READ) {
|
||||
regn &= BMI160_REG_MASK;
|
||||
val = reg_read(cfg, regn);
|
||||
val = reg_read(emul->parent, regn);
|
||||
*(uint8_t *)rxd->buf = val;
|
||||
} else {
|
||||
val = *(uint8_t *)txd->buf;
|
||||
reg_write(cfg, regn, val);
|
||||
reg_write(emul->parent, regn, val);
|
||||
}
|
||||
break;
|
||||
case BMI160_SAMPLE_SIZE:
|
||||
|
@ -252,11 +248,9 @@ static int bmi160_emul_transfer_i2c(struct i2c_emul *emul, struct i2c_msg *msgs,
|
|||
int num_msgs, int addr)
|
||||
{
|
||||
struct bmi160_emul_data *data;
|
||||
const struct bmi160_emul_cfg *cfg;
|
||||
unsigned int val;
|
||||
|
||||
data = CONTAINER_OF(emul, struct bmi160_emul_data, emul_i2c);
|
||||
cfg = data->cfg;
|
||||
|
||||
__ASSERT_NO_MSG(msgs && num_msgs);
|
||||
|
||||
|
@ -278,7 +272,7 @@ static int bmi160_emul_transfer_i2c(struct i2c_emul *emul, struct i2c_msg *msgs,
|
|||
if (msgs->flags & I2C_MSG_READ) {
|
||||
switch (msgs->len) {
|
||||
case 1:
|
||||
val = reg_read(cfg, data->cur_reg);
|
||||
val = reg_read(emul->parent, data->cur_reg);
|
||||
msgs->buf[0] = val;
|
||||
break;
|
||||
case BMI160_SAMPLE_SIZE:
|
||||
|
@ -292,7 +286,7 @@ static int bmi160_emul_transfer_i2c(struct i2c_emul *emul, struct i2c_msg *msgs,
|
|||
if (msgs->len != 1) {
|
||||
LOG_ERR("Unexpected msg1 length %d", msgs->len);
|
||||
}
|
||||
reg_write(cfg, data->cur_reg, msgs->buf[0]);
|
||||
reg_write(emul->parent, data->cur_reg, msgs->buf[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -322,11 +316,10 @@ static void emul_bosch_bmi160_init(const struct emul *emul,
|
|||
const struct device *parent)
|
||||
{
|
||||
const struct bmi160_emul_cfg *cfg = emul->cfg;
|
||||
struct bmi160_emul_data *data = cfg->data;
|
||||
struct bmi160_emul_data *data = emul->data;
|
||||
uint8_t *reg = cfg->reg;
|
||||
|
||||
data->dev = parent;
|
||||
data->cfg = cfg;
|
||||
data->pmu_status = 0;
|
||||
|
||||
reg[BMI160_REG_CHIPID] = BMI160_CHIP_ID;
|
||||
|
@ -347,11 +340,12 @@ static int emul_bosch_bmi160_init_spi(const struct emul *emul,
|
|||
const struct device *parent)
|
||||
{
|
||||
const struct bmi160_emul_cfg *cfg = emul->cfg;
|
||||
struct bmi160_emul_data *data = cfg->data;
|
||||
struct bmi160_emul_data *data = emul->data;
|
||||
|
||||
emul_bosch_bmi160_init(emul, parent);
|
||||
data->emul_spi.api = &bmi160_emul_api_spi;
|
||||
data->emul_spi.chipsel = cfg->chipsel;
|
||||
data->emul_spi.parent = emul;
|
||||
|
||||
int rc = spi_emul_register(parent, emul->dev_label, &data->emul_spi);
|
||||
|
||||
|
@ -374,11 +368,12 @@ static int emul_bosch_bmi160_init_i2c(const struct emul *emul,
|
|||
const struct device *parent)
|
||||
{
|
||||
const struct bmi160_emul_cfg *cfg = emul->cfg;
|
||||
struct bmi160_emul_data *data = cfg->data;
|
||||
struct bmi160_emul_data *data = emul->data;
|
||||
|
||||
emul_bosch_bmi160_init(emul, parent);
|
||||
data->emul_i2c.api = &bmi160_emul_api_i2c;
|
||||
data->emul_i2c.addr = cfg->addr;
|
||||
data->emul_i2c.parent = emul;
|
||||
|
||||
int rc = i2c_emul_register(parent, emul->dev_label, &data->emul_i2c);
|
||||
|
||||
|
@ -392,14 +387,13 @@ static int emul_bosch_bmi160_init_i2c(const struct emul *emul,
|
|||
|
||||
#define BMI160_EMUL_DEFINE(n, type) \
|
||||
EMUL_DEFINE(emul_bosch_bmi160_init_##type, DT_DRV_INST(n), \
|
||||
&bmi160_emul_cfg_##n)
|
||||
&bmi160_emul_cfg_##n, &bmi160_emul_data_##n)
|
||||
|
||||
/* Instantiation macros used when a device is on a SPI bus */
|
||||
#define BMI160_EMUL_SPI(n) \
|
||||
BMI160_EMUL_DATA(n) \
|
||||
static const struct bmi160_emul_cfg bmi160_emul_cfg_##n = { \
|
||||
.bus_label = DT_INST_BUS_LABEL(n), \
|
||||
.data = &bmi160_emul_data_##n, \
|
||||
.reg = bmi160_emul_reg_##n, \
|
||||
.chipsel = DT_INST_REG_ADDR(n) \
|
||||
}; \
|
||||
|
@ -409,7 +403,6 @@ static int emul_bosch_bmi160_init_i2c(const struct emul *emul,
|
|||
BMI160_EMUL_DATA(n) \
|
||||
static const struct bmi160_emul_cfg bmi160_emul_cfg_##n = { \
|
||||
.bus_label = DT_INST_BUS_LABEL(n), \
|
||||
.data = &bmi160_emul_data_##n, \
|
||||
.reg = bmi160_emul_reg_##n, \
|
||||
.addr = DT_INST_REG_ADDR(n) \
|
||||
}; \
|
||||
|
|
|
@ -68,8 +68,6 @@ struct espi_host_emul_data {
|
|||
struct espi_emul emul;
|
||||
/** eSPI controller device */
|
||||
const struct device *espi;
|
||||
/** Configuration information */
|
||||
const struct espi_host_emul_cfg *cfg;
|
||||
/** Virtual Wires states, for one slave only.
|
||||
* With multi-slaves config, the states should be saved per slave */
|
||||
struct vw_data vw_state[NUMBER_OF_VWIRES];
|
||||
|
@ -85,8 +83,6 @@ struct espi_host_emul_cfg {
|
|||
const char *espi_label;
|
||||
/** Label of the emulated AP*/
|
||||
const char *label;
|
||||
/** Pointer to run-time data */
|
||||
struct espi_host_emul_data *data;
|
||||
/* eSPI chip-select of the emulated device */
|
||||
uint16_t chipsel;
|
||||
};
|
||||
|
@ -258,24 +254,24 @@ static struct emul_espi_device_api ap_emul_api = {
|
|||
static int emul_host_init(const struct emul *emul, const struct device *bus)
|
||||
{
|
||||
const struct espi_host_emul_cfg *cfg = emul->cfg;
|
||||
struct espi_host_emul_data *data = cfg->data;
|
||||
struct espi_host_emul_data *data = emul->data;
|
||||
|
||||
data->emul.api = &ap_emul_api;
|
||||
data->emul.chipsel = cfg->chipsel;
|
||||
data->emul.parent = emul;
|
||||
data->espi = bus;
|
||||
data->cfg = cfg;
|
||||
emul_host_init_vw_state(data);
|
||||
|
||||
return espi_emul_register(bus, emul->dev_label, &data->emul);
|
||||
}
|
||||
|
||||
#define HOST_EMUL(n) \
|
||||
static struct espi_host_emul_data espi_host_emul_data_##n; \
|
||||
static const struct espi_host_emul_cfg espi_host_emul_cfg_##n = { \
|
||||
.espi_label = DT_INST_BUS_LABEL(n), \
|
||||
.data = &espi_host_emul_data_##n, \
|
||||
.chipsel = DT_INST_REG_ADDR(n), \
|
||||
}; \
|
||||
EMUL_DEFINE(emul_host_init, DT_DRV_INST(n), &espi_host_emul_cfg_##n)
|
||||
#define HOST_EMUL(n) \
|
||||
static struct espi_host_emul_data espi_host_emul_data_##n; \
|
||||
static const struct espi_host_emul_cfg espi_host_emul_cfg_##n = { \
|
||||
.espi_label = DT_INST_BUS_LABEL(n), \
|
||||
.chipsel = DT_INST_REG_ADDR(n), \
|
||||
}; \
|
||||
EMUL_DEFINE(emul_host_init, DT_DRV_INST(n), &espi_host_emul_cfg_##n, \
|
||||
&espi_host_emul_data_##n)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(HOST_EMUL)
|
||||
|
|
|
@ -22,8 +22,6 @@ struct at24_emul_data {
|
|||
struct i2c_emul emul;
|
||||
/** AT24 device being emulated */
|
||||
const struct device *i2c;
|
||||
/** Configuration information */
|
||||
const struct at24_emul_cfg *cfg;
|
||||
/** Current register to read (address) */
|
||||
uint32_t cur_reg;
|
||||
};
|
||||
|
@ -32,8 +30,6 @@ struct at24_emul_data {
|
|||
struct at24_emul_cfg {
|
||||
/** Label of the I2C bus this emulator connects to */
|
||||
const char *i2c_label;
|
||||
/** Pointer to run-time data */
|
||||
struct at24_emul_data *data;
|
||||
/** EEPROM data contents */
|
||||
uint8_t *buf;
|
||||
/** Size of EEPROM in bytes */
|
||||
|
@ -67,7 +63,7 @@ static int at24_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs,
|
|||
bool too_fast;
|
||||
|
||||
data = CONTAINER_OF(emul, struct at24_emul_data, emul);
|
||||
cfg = data->cfg;
|
||||
cfg = emul->parent->cfg;
|
||||
|
||||
if (cfg->addr != addr) {
|
||||
LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr,
|
||||
|
@ -141,12 +137,12 @@ static int emul_atmel_at24_init(const struct emul *emul,
|
|||
const struct device *parent)
|
||||
{
|
||||
const struct at24_emul_cfg *cfg = emul->cfg;
|
||||
struct at24_emul_data *data = cfg->data;
|
||||
struct at24_emul_data *data = emul->data;
|
||||
|
||||
data->emul.api = &at24_emul_api;
|
||||
data->emul.addr = cfg->addr;
|
||||
data->emul.parent = emul;
|
||||
data->i2c = parent;
|
||||
data->cfg = cfg;
|
||||
data->cur_reg = 0;
|
||||
|
||||
/* Start with an erased EEPROM, assuming all 0xff */
|
||||
|
@ -157,17 +153,16 @@ static int emul_atmel_at24_init(const struct emul *emul,
|
|||
return rc;
|
||||
}
|
||||
|
||||
#define EEPROM_AT24_EMUL(n) \
|
||||
static uint8_t at24_emul_buf_##n[DT_INST_PROP(n, size)]; \
|
||||
static struct at24_emul_data at24_emul_data_##n; \
|
||||
static const struct at24_emul_cfg at24_emul_cfg_##n = { \
|
||||
.i2c_label = DT_INST_BUS_LABEL(n), \
|
||||
.data = &at24_emul_data_##n, \
|
||||
.buf = at24_emul_buf_##n, \
|
||||
.size = DT_INST_PROP(n, size), \
|
||||
.addr = DT_INST_REG_ADDR(n), \
|
||||
.addr_width = 8, \
|
||||
}; \
|
||||
EMUL_DEFINE(emul_atmel_at24_init, DT_DRV_INST(n), &at24_emul_cfg_##n)
|
||||
#define EEPROM_AT24_EMUL(n) \
|
||||
static uint8_t at24_emul_buf_##n[DT_INST_PROP(n, size)]; \
|
||||
static struct at24_emul_data at24_emul_data_##n; \
|
||||
static const struct at24_emul_cfg at24_emul_cfg_##n = { \
|
||||
.i2c_label = DT_INST_BUS_LABEL(n), \
|
||||
.buf = at24_emul_buf_##n, \
|
||||
.size = DT_INST_PROP(n, size), \
|
||||
.addr = DT_INST_REG_ADDR(n), \
|
||||
.addr_width = 8, \
|
||||
}; \
|
||||
EMUL_DEFINE(emul_atmel_at24_init, DT_DRV_INST(n), &at24_emul_cfg_##n, &at24_emul_data_##n)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(EEPROM_AT24_EMUL)
|
||||
|
|
Loading…
Reference in a new issue