emul: Simplify emulator bus initialization and API
Allow emulator creators to write an init function that can be used across multiple busses so as to reduce the boilerplate and cognitive load in creating an emulator. Part of this change includes allowing access to the emul struct from a field in a {bus}_struct api (e.g. i2c_struct), which removes the need for sporadic usages of CONTAINER_OF to access the emul struct. Overall, this change simplifies and reduces the amount of boilerplate code to get a device emulator up and running, thus reducing excise work to writing tests. TEST=twister on accel,espi, and eeprom drivers tests Signed-off-by: Aaron Massey <aaronmassey@google.com>
This commit is contained in:
parent
1028459afd
commit
9d7b9dc807
|
@ -109,7 +109,7 @@ static int espi_emul_read_lpc_request(const struct device *dev, enum lpc_periphe
|
|||
#ifdef CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
|
||||
case EACPI_GET_SHARED_MEMORY:
|
||||
__ASSERT_NO_MSG(api->get_acpi_shm);
|
||||
*data = (uint32_t)api->get_acpi_shm(emul);
|
||||
*data = (uint32_t)api->get_acpi_shm(emul->target);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -146,7 +146,7 @@ static int espi_emul_send_vwire(const struct device *dev, enum espi_vwire_signal
|
|||
__ASSERT_NO_MSG(emul->api->set_vw);
|
||||
api = emul->api;
|
||||
|
||||
return api->set_vw(emul, vw, level);
|
||||
return api->set_vw(emul->target, vw, level);
|
||||
}
|
||||
|
||||
static int espi_emul_receive_vwire(const struct device *dev, enum espi_vwire_signal vw,
|
||||
|
@ -170,7 +170,7 @@ static int espi_emul_receive_vwire(const struct device *dev, enum espi_vwire_sig
|
|||
__ASSERT_NO_MSG(emul->api->get_vw);
|
||||
api = emul->api;
|
||||
|
||||
return api->get_vw(emul, vw, level);
|
||||
return api->get_vw(emul->target, vw, level);
|
||||
}
|
||||
|
||||
static int espi_emul_manage_callback(const struct device *dev, struct espi_callback *callback,
|
||||
|
@ -189,11 +189,10 @@ static int espi_emul_manage_callback(const struct device *dev, struct espi_callb
|
|||
static int espi_emul_init(const struct device *dev)
|
||||
{
|
||||
struct espi_emul_data *data = dev->data;
|
||||
const struct emul_list_for_bus *list = dev->config;
|
||||
|
||||
sys_slist_init(&data->emuls);
|
||||
|
||||
return emul_init_for_bus_from_list(dev, list);
|
||||
return emul_init_for_bus(dev);
|
||||
}
|
||||
|
||||
int espi_emul_register(const struct device *dev, const char *name, struct espi_emul *emul)
|
||||
|
|
|
@ -90,7 +90,7 @@ static int i2c_emul_transfer(const struct device *dev, struct i2c_msg *msgs, uin
|
|||
__ASSERT_NO_MSG(emul->api);
|
||||
__ASSERT_NO_MSG(emul->api->transfer);
|
||||
|
||||
ret = api->transfer(emul, msgs, num_msgs, addr);
|
||||
ret = api->transfer(emul->target, msgs, num_msgs, addr);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -106,12 +106,11 @@ static int i2c_emul_transfer(const struct device *dev, struct i2c_msg *msgs, uin
|
|||
static int i2c_emul_init(const struct device *dev)
|
||||
{
|
||||
struct i2c_emul_data *data = dev->data;
|
||||
const struct emul_list_for_bus *list = dev->config;
|
||||
int rc;
|
||||
|
||||
sys_slist_init(&data->emuls);
|
||||
|
||||
rc = emul_init_for_bus_from_list(dev, list);
|
||||
rc = emul_init_for_bus(dev);
|
||||
|
||||
/* Set config to an uninitialized state */
|
||||
data->config = (I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(data->bitrate));
|
||||
|
|
|
@ -78,7 +78,7 @@ static int spi_emul_io(const struct device *dev, const struct spi_config *config
|
|||
__ASSERT_NO_MSG(emul->api);
|
||||
__ASSERT_NO_MSG(emul->api->io);
|
||||
|
||||
return api->io(emul, config, tx_bufs, rx_bufs);
|
||||
return api->io(emul->target, config, tx_bufs, rx_bufs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,11 +89,10 @@ static int spi_emul_io(const struct device *dev, const struct spi_config *config
|
|||
static int spi_emul_init(const struct device *dev)
|
||||
{
|
||||
struct spi_emul_data *data = dev->data;
|
||||
const struct emul_list_for_bus *list = dev->config;
|
||||
|
||||
sys_slist_init(&data->emuls);
|
||||
|
||||
return emul_init_for_bus_from_list(dev, list);
|
||||
return emul_init_for_bus(dev);
|
||||
}
|
||||
|
||||
int spi_emul_register(const struct device *dev, const char *name, struct spi_emul *emul)
|
||||
|
|
|
@ -18,9 +18,23 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct device;
|
||||
struct emul;
|
||||
|
||||
/* #includes required after forward-declaration of struct emul later defined in this header. */
|
||||
#include <zephyr/drivers/espi_emul.h>
|
||||
#include <zephyr/drivers/i2c_emul.h>
|
||||
#include <zephyr/drivers/spi_emul.h>
|
||||
#include <zephyr/device.h>
|
||||
|
||||
/**
|
||||
* The types of supported buses.
|
||||
*/
|
||||
enum emul_bus_type {
|
||||
EMUL_BUS_TYPE_I2C,
|
||||
EMUL_BUS_TYPE_ESPI,
|
||||
EMUL_BUS_TYPE_SPI,
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure uniquely identifying a device to be emulated
|
||||
*
|
||||
|
@ -47,7 +61,10 @@ struct emul_list_for_bus {
|
|||
*/
|
||||
typedef int (*emul_init_t)(const struct emul *emul, const struct device *parent);
|
||||
|
||||
/** An emulator instance */
|
||||
/** An emulator instance - represents the *target* emulated device/peripheral that is
|
||||
* interacted with through an emulated bus. Instances of emulated bus nodes (e.g. i2c_emul)
|
||||
* and emulators (i.e. struct emul) are exactly 1..1
|
||||
*/
|
||||
struct emul {
|
||||
/** function used to initialise the emulator state */
|
||||
emul_init_t init;
|
||||
|
@ -57,6 +74,14 @@ struct emul {
|
|||
const void *cfg;
|
||||
/** Emulator-specific data */
|
||||
void *data;
|
||||
/** The bus type that the emulator is attached to */
|
||||
enum emul_bus_type bus_type;
|
||||
/** Pointer to the emulated bus node */
|
||||
union bus {
|
||||
struct i2c_emul *i2c;
|
||||
struct espi_emul *espi;
|
||||
struct spi_emul *spi;
|
||||
} bus;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -69,6 +94,17 @@ extern const struct emul __emul_list_end[];
|
|||
/* Use the devicetree node identifier as a unique name. */
|
||||
#define EMUL_REG_NAME(node_id) (_CONCAT(__emulreg_, node_id))
|
||||
|
||||
/* Get a unique identifier based on the given _dev_node_id's reg property and
|
||||
* the bus its on. Intended for use in other internal macros when declaring {bus}_emul
|
||||
* structs in peripheral emulators.
|
||||
*/
|
||||
#define Z_EMUL_REG_BUS_IDENTIFIER(_dev_node_id) (_CONCAT(_CONCAT(__emulreg_, _dev_node_id), _bus))
|
||||
|
||||
/* Conditionally places text based on what bus _dev_node_id is on. */
|
||||
#define Z_EMUL_BUS(_dev_node_id, _i2c, _espi, _spi) \
|
||||
COND_CODE_1(DT_ON_BUS(_dev_node_id, i2c), (_i2c), \
|
||||
(COND_CODE_1(DT_ON_BUS(_dev_node_id, espi), (_espi), \
|
||||
(COND_CODE_1(DT_ON_BUS(_dev_node_id, spi), (_spi), (-EINVAL))))))
|
||||
/**
|
||||
* Define a new emulator
|
||||
*
|
||||
|
@ -80,25 +116,34 @@ extern const struct emul __emul_list_end[];
|
|||
* @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
|
||||
* @param bus_api emulator-specific bus api
|
||||
*/
|
||||
#define EMUL_DEFINE(init_ptr, node_id, cfg_ptr, data_ptr) \
|
||||
#define EMUL_DEFINE(init_ptr, node_id, cfg_ptr, data_ptr, bus_api) \
|
||||
static struct Z_EMUL_BUS(node_id, i2c_emul, espi_emul, spi_emul) \
|
||||
Z_EMUL_REG_BUS_IDENTIFIER(node_id) = { \
|
||||
.api = bus_api, \
|
||||
.Z_EMUL_BUS(node_id, addr, chipsel, chipsel) = DT_REG_ADDR(node_id), \
|
||||
}; \
|
||||
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), \
|
||||
.bus_type = Z_EMUL_BUS(node_id, EMUL_BUS_TYPE_I2C, EMUL_BUS_TYPE_ESPI, \
|
||||
EMUL_BUS_TYPE_SPI), \
|
||||
.bus = {.Z_EMUL_BUS(node_id, i2c, espi, spi) = \
|
||||
&(Z_EMUL_REG_BUS_IDENTIFIER(node_id))}, \
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up a list of emulators
|
||||
*
|
||||
* @param dev Device the emulators are attached to (e.g. an I2C controller)
|
||||
* @param list List of devices to set up
|
||||
* @return 0 if OK
|
||||
* @return negative value on error
|
||||
*/
|
||||
int emul_init_for_bus_from_list(const struct device *dev, const struct emul_list_for_bus *list);
|
||||
int emul_init_for_bus(const struct device *dev);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the emul structure for an emulator by name
|
||||
|
|
|
@ -7,17 +7,17 @@
|
|||
#ifndef ZEPHYR_INCLUDE_DRIVERS_ESPI_SPI_EMUL_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_ESPI_SPI_EMUL_H_
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/emul.h>
|
||||
#include <zephyr/drivers/espi.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Public APIs for the eSPI emulation drivers.
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/espi.h>
|
||||
#include <zephyr/drivers/emul.h>
|
||||
|
||||
/**
|
||||
* @brief eSPI Emulation Interface
|
||||
* @defgroup espi_emul_interface eSPI Emulation Interface
|
||||
|
@ -37,39 +37,39 @@ struct espi_emul;
|
|||
* Passes eSPI virtual wires set request (virtual wire packet) to the emulator.
|
||||
* The emulator updates the state (level) of its virtual wire.
|
||||
*
|
||||
* @param emul Emulator instance
|
||||
* @param target The device Emulator instance
|
||||
* @param vw The signal to be set.
|
||||
* @param level The level of signal requested LOW(0) or HIGH(1).
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input / output error.
|
||||
*/
|
||||
typedef int (*emul_espi_api_set_vw)(struct espi_emul *emul, enum espi_vwire_signal vw,
|
||||
typedef int (*emul_espi_api_set_vw)(const struct emul *target, enum espi_vwire_signal vw,
|
||||
uint8_t level);
|
||||
|
||||
/**
|
||||
* Passes eSPI virtual wires get request (virtual wire packet) to the emulator.
|
||||
* The emulator returns the state (level) of its virtual wire.
|
||||
*
|
||||
* @param emul Emulator instance
|
||||
* @param target The device Emulator instance
|
||||
* @param vw The signal to be get.
|
||||
* @param level The level of the signal to be get.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input / output error.
|
||||
*/
|
||||
typedef int (*emul_espi_api_get_vw)(struct espi_emul *emul, enum espi_vwire_signal vw,
|
||||
typedef int (*emul_espi_api_get_vw)(const struct emul *target, enum espi_vwire_signal vw,
|
||||
uint8_t *level);
|
||||
|
||||
#ifdef CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
|
||||
/**
|
||||
* Get the ACPI shared memory address owned by the emulator.
|
||||
*
|
||||
* @param emul Emulator instance.
|
||||
* @param target The device Emulator instance
|
||||
*
|
||||
* @retval The address of the memory.
|
||||
*/
|
||||
typedef uintptr_t (*emul_espi_api_get_acpi_shm)(struct espi_emul *emul);
|
||||
typedef uintptr_t (*emul_espi_api_get_acpi_shm)(const struct emul *target);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ typedef uintptr_t (*emul_espi_api_get_acpi_shm)(struct espi_emul *emul);
|
|||
*
|
||||
* @param dev eSPI emulation controller device
|
||||
* @param chipsel Chip-select value
|
||||
* @return emulator to use
|
||||
* @return espi_emul to use
|
||||
* @return NULL if not found
|
||||
*/
|
||||
typedef struct espi_emul *(*emul_find_emul)(const struct device *dev, unsigned int chipsel);
|
||||
|
@ -109,8 +109,8 @@ struct emul_espi_device_api {
|
|||
/** Node in a linked list of emulators for eSPI devices */
|
||||
struct espi_emul {
|
||||
sys_snode_t node;
|
||||
/** Parent emulator */
|
||||
const struct emul *parent;
|
||||
/** Target emulator - REQUIRED for all emulated bus nodes of any type */
|
||||
const struct emul *target;
|
||||
/** API provided for this device */
|
||||
const struct emul_espi_device_api *api;
|
||||
/** eSPI chip-select of the emulated device */
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
#ifndef ZEPHYR_INCLUDE_DRIVERS_I2C_I2C_EMUL_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_I2C_I2C_EMUL_H_
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/emul.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
/**
|
||||
* @brief I2C Emulation Interface
|
||||
* @defgroup i2c_emul_interface I2C Emulation Interface
|
||||
|
@ -20,10 +24,6 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/emul.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -35,8 +35,8 @@ struct i2c_emul_api;
|
|||
struct i2c_emul {
|
||||
sys_snode_t node;
|
||||
|
||||
/** Parent emulator */
|
||||
const struct emul *parent;
|
||||
/** Target emulator - REQUIRED for all emulated bus nodes of any type */
|
||||
const struct emul *target;
|
||||
|
||||
/* API provided for this device */
|
||||
const struct i2c_emul_api *api;
|
||||
|
@ -49,16 +49,16 @@ struct i2c_emul {
|
|||
* Passes I2C messages to the emulator. The emulator updates the data with what
|
||||
* was read back.
|
||||
*
|
||||
* @param emul Emulator instance
|
||||
* @param target The device Emulator instance.
|
||||
* @param msgs Array of messages to transfer. For 'read' messages, this function
|
||||
* updates the 'buf' member with the data that was read
|
||||
* updates the 'buf' member with the data that was read.
|
||||
* @param num_msgs Number of messages to transfer.
|
||||
* @param addr Address of the I2C target device.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input / output error.
|
||||
*/
|
||||
typedef int (*i2c_emul_transfer_t)(struct i2c_emul *emul, struct i2c_msg *msgs, int num_msgs,
|
||||
typedef int (*i2c_emul_transfer_t)(const struct emul *target, struct i2c_msg *msgs, int num_msgs,
|
||||
int addr);
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,16 +7,17 @@
|
|||
#ifndef ZEPHYR_INCLUDE_DRIVERS_SPI_SPI_EMUL_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_SPI_SPI_EMUL_H_
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/emul.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Public APIs for the SPI emulation drivers.
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/emul.h>
|
||||
|
||||
/**
|
||||
* @brief SPI Emulation Interface
|
||||
* @defgroup spi_emul_interface SPI Emulation Interface
|
||||
|
@ -35,8 +36,8 @@ struct spi_emul_api;
|
|||
struct spi_emul {
|
||||
sys_snode_t node;
|
||||
|
||||
/** Parent emulator */
|
||||
const struct emul *parent;
|
||||
/** Target emulator - REQUIRED for all bus emulators */
|
||||
const struct emul *target;
|
||||
|
||||
/* API provided for this device */
|
||||
const struct spi_emul_api *api;
|
||||
|
@ -49,7 +50,7 @@ struct spi_emul {
|
|||
* Passes SPI messages to the emulator. The emulator updates the data with what
|
||||
* was read back.
|
||||
*
|
||||
* @param emul Emulator instance
|
||||
* @param target The device Emulator instance
|
||||
* @param config Pointer to a valid spi_config structure instance.
|
||||
* Pointer-comparison may be used to detect changes from
|
||||
* previous operations.
|
||||
|
@ -61,7 +62,7 @@ struct spi_emul {
|
|||
* @retval 0 If successful.
|
||||
* @retval -EIO General input / output error.
|
||||
*/
|
||||
typedef int (*spi_emul_io_t)(struct spi_emul *emul, const struct spi_config *config,
|
||||
typedef int (*spi_emul_io_t)(const struct emul *target, const struct spi_config *config,
|
||||
const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs);
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,7 +26,7 @@ const struct emul *emul_get_binding(const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int emul_init_for_bus_from_list(const struct device *dev, const struct emul_list_for_bus *list)
|
||||
int emul_init_for_bus(const struct device *dev)
|
||||
{
|
||||
const struct emul_list_for_bus *cfg = dev->config;
|
||||
|
||||
|
@ -43,10 +43,48 @@ int emul_init_for_bus_from_list(const struct device *dev, const struct emul_list
|
|||
|
||||
__ASSERT(emul, "Cannot find emulator for '%s'", elp->label);
|
||||
|
||||
switch (emul->bus_type) {
|
||||
case EMUL_BUS_TYPE_I2C:
|
||||
emul->bus.i2c->target = emul;
|
||||
break;
|
||||
case EMUL_BUS_TYPE_ESPI:
|
||||
emul->bus.espi->target = emul;
|
||||
break;
|
||||
case EMUL_BUS_TYPE_SPI:
|
||||
emul->bus.spi->target = emul;
|
||||
break;
|
||||
}
|
||||
int rc = emul->init(emul, dev);
|
||||
|
||||
if (rc != 0) {
|
||||
LOG_WRN("Init %s emulator failed: %d\n", elp->label, rc);
|
||||
LOG_WRN("Init %s emulator failed: %d",
|
||||
elp->label, rc);
|
||||
}
|
||||
|
||||
switch (emul->bus_type) {
|
||||
#ifdef CONFIG_I2C_EMUL
|
||||
case EMUL_BUS_TYPE_I2C:
|
||||
rc = i2c_emul_register(dev, emul->dev_label, emul->bus.i2c);
|
||||
break;
|
||||
#endif /* CONFIG_I2C_EMUL */
|
||||
#ifdef CONFIG_ESPI_EMUL
|
||||
case EMUL_BUS_TYPE_ESPI:
|
||||
rc = espi_emul_register(dev, emul->dev_label, emul->bus.espi);
|
||||
break;
|
||||
#endif /* CONFIG_ESPI_EMUL */
|
||||
#ifdef CONFIG_SPI_EMUL
|
||||
case EMUL_BUS_TYPE_SPI:
|
||||
rc = spi_emul_register(dev, emul->dev_label, emul->bus.spi);
|
||||
break;
|
||||
#endif /* CONFIG_SPI_EMUL */
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
LOG_WRN("Found no emulated bus enabled to register emulator %s",
|
||||
elp->label);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
LOG_WRN("Failed to register emulator for %s: %d", elp->label, rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,14 +24,6 @@ LOG_MODULE_REGISTER(bosch_bmi160);
|
|||
|
||||
/** Run-time data used by the emulator */
|
||||
struct bmi160_emul_data {
|
||||
union {
|
||||
/** SPI emulator detail */
|
||||
struct spi_emul emul_spi;
|
||||
/** I2C emulator detail */
|
||||
struct i2c_emul emul_i2c;
|
||||
};
|
||||
/** BMI160 device being emulated */
|
||||
const struct device *dev;
|
||||
uint8_t pmu_status;
|
||||
/** Current register to read (address) */
|
||||
uint32_t cur_reg;
|
||||
|
@ -175,7 +167,7 @@ static int reg_read(const struct emul *emulator, int regn)
|
|||
}
|
||||
|
||||
#if BMI160_BUS_SPI
|
||||
static int bmi160_emul_io_spi(struct spi_emul *emul, const struct spi_config *config,
|
||||
static int bmi160_emul_io_spi(const struct emul *emulator, const struct spi_config *config,
|
||||
const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs)
|
||||
{
|
||||
struct bmi160_emul_data *data;
|
||||
|
@ -183,7 +175,7 @@ static int bmi160_emul_io_spi(struct spi_emul *emul, const struct spi_config *co
|
|||
unsigned int regn, val;
|
||||
int count;
|
||||
|
||||
data = CONTAINER_OF(emul, struct bmi160_emul_data, emul_spi);
|
||||
data = emulator->data;
|
||||
|
||||
__ASSERT_NO_MSG(tx_bufs || rx_bufs);
|
||||
__ASSERT_NO_MSG(!tx_bufs || !rx_bufs || tx_bufs->count == rx_bufs->count);
|
||||
|
@ -205,11 +197,11 @@ static int bmi160_emul_io_spi(struct spi_emul *emul, const struct spi_config *co
|
|||
case 1:
|
||||
if (regn & BMI160_REG_READ) {
|
||||
regn &= BMI160_REG_MASK;
|
||||
val = reg_read(emul->parent, regn);
|
||||
val = reg_read(emulator, regn);
|
||||
*(uint8_t *)rxd->buf = val;
|
||||
} else {
|
||||
val = *(uint8_t *)txd->buf;
|
||||
reg_write(emul->parent, regn, val);
|
||||
reg_write(emulator, regn, val);
|
||||
}
|
||||
break;
|
||||
case BMI160_SAMPLE_SIZE:
|
||||
|
@ -239,13 +231,13 @@ static int bmi160_emul_io_spi(struct spi_emul *emul, const struct spi_config *co
|
|||
#endif
|
||||
|
||||
#if BMI160_BUS_I2C
|
||||
static int bmi160_emul_transfer_i2c(struct i2c_emul *emul, struct i2c_msg *msgs, int num_msgs,
|
||||
static int bmi160_emul_transfer_i2c(const struct emul *emulator, struct i2c_msg *msgs, int num_msgs,
|
||||
int addr)
|
||||
{
|
||||
struct bmi160_emul_data *data;
|
||||
unsigned int val;
|
||||
|
||||
data = CONTAINER_OF(emul, struct bmi160_emul_data, emul_i2c);
|
||||
data = emulator->data;
|
||||
|
||||
__ASSERT_NO_MSG(msgs && num_msgs);
|
||||
|
||||
|
@ -267,7 +259,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(emul->parent, data->cur_reg);
|
||||
val = reg_read(emulator, data->cur_reg);
|
||||
msgs->buf[0] = val;
|
||||
break;
|
||||
case BMI160_SAMPLE_SIZE:
|
||||
|
@ -281,7 +273,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(emul->parent, data->cur_reg, msgs->buf[0]);
|
||||
reg_write(emulator, data->cur_reg, msgs->buf[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -307,79 +299,26 @@ static struct i2c_emul_api bmi160_emul_api_i2c = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static void emul_bosch_bmi160_init(const struct emul *emul, const struct device *parent)
|
||||
static int emul_bosch_bmi160_init(const struct emul *target, const struct device *parent)
|
||||
{
|
||||
const struct bmi160_emul_cfg *cfg = emul->cfg;
|
||||
struct bmi160_emul_data *data = emul->data;
|
||||
const struct bmi160_emul_cfg *cfg = target->cfg;
|
||||
struct bmi160_emul_data *data = target->data;
|
||||
uint8_t *reg = cfg->reg;
|
||||
|
||||
data->dev = parent;
|
||||
data->pmu_status = 0;
|
||||
|
||||
reg[BMI160_REG_CHIPID] = BMI160_CHIP_ID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if BMI160_BUS_SPI
|
||||
/**
|
||||
* Set up a new BMI160 emulator (SPI)
|
||||
*
|
||||
* This should be called for each BMI160 device that needs to be emulated. It
|
||||
* registers it with the SPI emulation controller.
|
||||
*
|
||||
* @param emul Emulation information
|
||||
* @param parent Device to emulate (must use BMI160 driver)
|
||||
* @return 0 indicating success (always)
|
||||
*/
|
||||
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 = 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);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BMI160_BUS_I2C
|
||||
/**
|
||||
* Set up a new BMI160 emulator (I2C)
|
||||
*
|
||||
* This should be called for each BMI160 device that needs to be emulated. It
|
||||
* registers it with the SPI emulation controller.
|
||||
*
|
||||
* @param emul Emulation information
|
||||
* @param parent Device to emulate (must use BMI160 driver)
|
||||
* @return 0 indicating success (always)
|
||||
*/
|
||||
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 = 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);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define BMI160_EMUL_DATA(n) \
|
||||
static uint8_t bmi160_emul_reg_##n[BMI160_REG_COUNT]; \
|
||||
static struct bmi160_emul_data bmi160_emul_data_##n;
|
||||
|
||||
#define BMI160_EMUL_DEFINE(n, type) \
|
||||
EMUL_DEFINE(emul_bosch_bmi160_init_##type, DT_DRV_INST(n), &bmi160_emul_cfg_##n, \
|
||||
&bmi160_emul_data_##n)
|
||||
#define BMI160_EMUL_DEFINE(n, api) \
|
||||
EMUL_DEFINE(emul_bosch_bmi160_init, DT_DRV_INST(n), &bmi160_emul_cfg_##n, \
|
||||
&bmi160_emul_data_##n, &api)
|
||||
|
||||
/* Instantiation macros used when a device is on a SPI bus */
|
||||
#define BMI160_EMUL_SPI(n) \
|
||||
|
@ -389,7 +328,7 @@ static int emul_bosch_bmi160_init_i2c(const struct emul *emul, const struct devi
|
|||
.reg = bmi160_emul_reg_##n, \
|
||||
.chipsel = \
|
||||
DT_INST_REG_ADDR(n) }; \
|
||||
BMI160_EMUL_DEFINE(n, spi)
|
||||
BMI160_EMUL_DEFINE(n, bmi160_emul_api_spi)
|
||||
|
||||
#define BMI160_EMUL_I2C(n) \
|
||||
BMI160_EMUL_DATA(n) \
|
||||
|
@ -397,7 +336,7 @@ static int emul_bosch_bmi160_init_i2c(const struct emul *emul, const struct devi
|
|||
DT_INST_BUS_LABEL(n), \
|
||||
.reg = bmi160_emul_reg_##n, \
|
||||
.addr = DT_INST_REG_ADDR(n) }; \
|
||||
BMI160_EMUL_DEFINE(n, i2c)
|
||||
BMI160_EMUL_DEFINE(n, bmi160_emul_api_i2c)
|
||||
|
||||
/*
|
||||
* Main instantiation macro. Use of COND_CODE_1() selects the right
|
||||
|
|
|
@ -109,7 +109,8 @@ static void emul_host_init_vw_state(struct espi_host_emul_data *data)
|
|||
* @return index in the array
|
||||
* @return -1 if not found
|
||||
*/
|
||||
static int emul_host_find_index(struct espi_host_emul_data *data, enum espi_vwire_signal vw)
|
||||
static int emul_host_find_index(struct espi_host_emul_data *data,
|
||||
enum espi_vwire_signal vw)
|
||||
{
|
||||
int idx;
|
||||
|
||||
|
@ -122,12 +123,12 @@ static int emul_host_find_index(struct espi_host_emul_data *data, enum espi_vwir
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int emul_host_set_vw(struct espi_emul *emul, enum espi_vwire_signal vw, uint8_t level)
|
||||
static int emul_host_set_vw(const struct emul *emulator,
|
||||
enum espi_vwire_signal vw, uint8_t level)
|
||||
{
|
||||
struct espi_host_emul_data *data;
|
||||
struct espi_host_emul_data *data = emulator->data;
|
||||
int idx;
|
||||
|
||||
data = CONTAINER_OF(emul, struct espi_host_emul_data, emul);
|
||||
idx = emul_host_find_index(data, vw);
|
||||
|
||||
if (idx < 0 || data->vw_state[idx].dir != ESPI_SLAVE_TO_MASTER) {
|
||||
|
@ -140,12 +141,12 @@ static int emul_host_set_vw(struct espi_emul *emul, enum espi_vwire_signal vw, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int emul_host_get_vw(struct espi_emul *emul, enum espi_vwire_signal vw, uint8_t *level)
|
||||
static int emul_host_get_vw(const struct emul *emulator,
|
||||
enum espi_vwire_signal vw, uint8_t *level)
|
||||
{
|
||||
struct espi_host_emul_data *data;
|
||||
struct espi_host_emul_data *data = emulator->data;
|
||||
int idx;
|
||||
|
||||
data = CONTAINER_OF(emul, struct espi_host_emul_data, emul);
|
||||
idx = emul_host_find_index(data, vw);
|
||||
|
||||
if (idx < 0 || data->vw_state[idx].dir != ESPI_MASTER_TO_SLAVE) {
|
||||
|
@ -158,7 +159,8 @@ static int emul_host_get_vw(struct espi_emul *emul, enum espi_vwire_signal vw, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
int emul_espi_host_send_vw(const struct device *espi_dev, enum espi_vwire_signal vw, uint8_t level)
|
||||
int emul_espi_host_send_vw(const struct device *espi_dev, enum espi_vwire_signal vw,
|
||||
uint8_t level)
|
||||
{
|
||||
struct espi_emul *emul_espi;
|
||||
struct espi_event evt;
|
||||
|
@ -173,7 +175,7 @@ int emul_espi_host_send_vw(const struct device *espi_dev, enum espi_vwire_signal
|
|||
__ASSERT_NO_MSG(api->find_emul);
|
||||
|
||||
emul_espi = api->find_emul(espi_dev, EMUL_ESPI_HOST_CHIPSEL);
|
||||
data_host = CONTAINER_OF(emul_espi, struct espi_host_emul_data, emul);
|
||||
data_host = espi_dev->data;
|
||||
|
||||
idx = emul_host_find_index(data_host, vw);
|
||||
if (idx < 0 || data_host->vw_state[idx].dir != ESPI_MASTER_TO_SLAVE) {
|
||||
|
@ -212,9 +214,9 @@ int emul_espi_host_port80_write(const struct device *espi_dev, uint32_t data)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
|
||||
static uintptr_t emul_espi_dev_get_acpi_shm(struct espi_emul *emul)
|
||||
static uintptr_t emul_espi_dev_get_acpi_shm(const struct emul *emulator)
|
||||
{
|
||||
struct espi_host_emul_data *data = CONTAINER_OF(emul, struct espi_host_emul_data, emul);
|
||||
struct espi_host_emul_data *data = emulator->data;
|
||||
|
||||
return (uintptr_t)data->shm_acpi_mmap;
|
||||
}
|
||||
|
@ -226,7 +228,7 @@ uintptr_t emul_espi_host_get_acpi_shm(const struct device *espi_dev)
|
|||
|
||||
__ASSERT_NO_MSG(rc == 0);
|
||||
|
||||
return (uintptr_t)shm;
|
||||
return (uintptr_t) shm;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -246,16 +248,11 @@ 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 = emul->data;
|
||||
|
||||
data->emul.api = &ap_emul_api;
|
||||
data->emul.chipsel = cfg->chipsel;
|
||||
data->emul.parent = emul;
|
||||
data->espi = bus;
|
||||
emul_host_init_vw_state(data);
|
||||
|
||||
return espi_emul_register(bus, emul->dev_label, &data->emul);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HOST_EMUL(n) \
|
||||
|
@ -264,6 +261,6 @@ static int emul_host_init(const struct emul *emul, const struct device *bus)
|
|||
.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)
|
||||
&espi_host_emul_data_##n, &ap_emul_api)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(HOST_EMUL)
|
||||
|
|
|
@ -52,7 +52,8 @@ struct at24_emul_cfg {
|
|||
* @retval 0 If successful
|
||||
* @retval -EIO General input / output error
|
||||
*/
|
||||
static int at24_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs, int num_msgs, int addr)
|
||||
static int at24_emul_transfer(const struct emul *emulator, struct i2c_msg *msgs,
|
||||
int num_msgs, int addr)
|
||||
{
|
||||
struct at24_emul_data *data;
|
||||
const struct at24_emul_cfg *cfg;
|
||||
|
@ -60,11 +61,12 @@ static int at24_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs, int n
|
|||
bool too_fast;
|
||||
uint32_t i2c_cfg;
|
||||
|
||||
data = CONTAINER_OF(emul, struct at24_emul_data, emul);
|
||||
cfg = emul->parent->cfg;
|
||||
data = emulator->data;
|
||||
cfg = emulator->cfg;
|
||||
|
||||
if (cfg->addr != addr) {
|
||||
LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr, addr);
|
||||
LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr,
|
||||
addr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -119,7 +121,7 @@ static int at24_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs, int n
|
|||
|
||||
/* Device instantiation */
|
||||
|
||||
static struct i2c_emul_api at24_emul_api = {
|
||||
static struct i2c_emul_api bus_api = {
|
||||
.transfer = at24_emul_transfer,
|
||||
};
|
||||
|
||||
|
@ -129,27 +131,25 @@ static struct i2c_emul_api at24_emul_api = {
|
|||
* This should be called for each AT24 device that needs to be emulated. It
|
||||
* registers it with the I2C emulation controller.
|
||||
*
|
||||
* @param emul Emulation information
|
||||
* @param emulator Emulation information
|
||||
* @param parent Device to emulate (must use AT24 driver)
|
||||
* @return 0 indicating success (always)
|
||||
*/
|
||||
static int emul_atmel_at24_init(const struct emul *emul, const struct device *parent)
|
||||
static int emul_atmel_at24_init(const struct emul *emulator, const struct device *parent)
|
||||
{
|
||||
const struct at24_emul_cfg *cfg = emul->cfg;
|
||||
struct at24_emul_data *data = emul->data;
|
||||
const struct at24_emul_cfg *cfg = emulator->cfg;
|
||||
struct at24_emul_data *data = emulator->data;
|
||||
|
||||
data->emul.api = &at24_emul_api;
|
||||
data->emul.api = &bus_api;
|
||||
data->emul.addr = cfg->addr;
|
||||
data->emul.parent = emul;
|
||||
data->emul.target = emulator;
|
||||
data->i2c = parent;
|
||||
data->cur_reg = 0;
|
||||
|
||||
/* Start with an erased EEPROM, assuming all 0xff */
|
||||
memset(cfg->buf, 0xff, cfg->size);
|
||||
|
||||
int rc = i2c_emul_register(parent, emul->dev_label, &data->emul);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define EEPROM_AT24_EMUL(n) \
|
||||
|
@ -161,6 +161,7 @@ static int emul_atmel_at24_init(const struct emul *emul, const struct device *pa
|
|||
.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)
|
||||
EMUL_DEFINE(&emul_atmel_at24_init, DT_DRV_INST(n), &at24_emul_cfg_##n, \
|
||||
&at24_emul_data_##n, &bus_api)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(EEPROM_AT24_EMUL)
|
||||
|
|
Loading…
Reference in a new issue