diff options
author | Madhurima Paruchuri <mparuchuri@google.com> | 2023-03-15 18:54:35 +0000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-04-12 12:23:47 +0000 |
commit | ca4eb6b6aea1c24c01923bb38a67065960d15ad4 (patch) | |
tree | 8c813d15a194ad527b016a21e9e8cd0635e2c1da /zephyr/emul | |
parent | 48cde011ac52a82e5c34d8b50a17c1ae63deaa45 (diff) | |
download | chrome-ec-ca4eb6b6aea1c24c01923bb38a67065960d15ad4.tar.gz |
retimer: Add emulator and unit tests for ANX7452 retimer driver
BUG=b:267589042
BRANCH=none
TEST=./twister -s drivers/drivers.anx7452 -c --coverage
Change-Id: I7b4dcef7e667cd69ecb39f6dda7a6c8570177f40
Signed-off-by: Madhurima Paruchuri <mparuchuri@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4303379
Reviewed-by: Fabio Baltieri <fabiobaltieri@google.com>
Diffstat (limited to 'zephyr/emul')
-rw-r--r-- | zephyr/emul/CMakeLists.txt | 1 | ||||
-rw-r--r-- | zephyr/emul/Kconfig | 11 | ||||
-rw-r--r-- | zephyr/emul/emul_anx7452.c | 262 |
3 files changed, 274 insertions, 0 deletions
diff --git a/zephyr/emul/CMakeLists.txt b/zephyr/emul/CMakeLists.txt index 523e1e98b0..58eef44627 100644 --- a/zephyr/emul/CMakeLists.txt +++ b/zephyr/emul/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory("tcpc") cros_ec_library_include_directories(include) +zephyr_library_sources_ifdef(CONFIG_EMUL_ANX7452 emul_anx7452.c) zephyr_library_sources_ifdef(CONFIG_EMUL_BB_RETIMER emul_bb_retimer.c) zephyr_library_sources_ifdef(CONFIG_EMUL_BC12_DETECT_PI3USB9201 emul_pi3usb9201.c) zephyr_library_sources_ifdef(CONFIG_EMUL_BMA255 emul_bma255.c) diff --git a/zephyr/emul/Kconfig b/zephyr/emul/Kconfig index b160e430b2..ecdbfb426c 100644 --- a/zephyr/emul/Kconfig +++ b/zephyr/emul/Kconfig @@ -190,6 +190,17 @@ config EMUL_PCT2075 Enable the PCT2075 temperature sensor emulator. It uses emulated I2C bus. Emulator API is available in zephyr/include/emul/emul_pct2075.h. +config EMUL_ANX7452 + bool "ANX7452 retimer emulator" + default y + depends on ZTEST && DT_HAS_ANALOGIX_ANX7452_ENABLED + select EMUL_COMMON_I2C + help + Enable the ANX7452(Analogix) retimer emulator. This driver use + emulated I2C bus. It is used to test anx7452 driver. It supports + reads and writes to all emulator registers. Emulators API is + available in zephyr/include/emul/emul_anx7452.h + config EMUL_PS8743 bool "PS8743 emulator" default y diff --git a/zephyr/emul/emul_anx7452.c b/zephyr/emul/emul_anx7452.c new file mode 100644 index 0000000000..f9854d4081 --- /dev/null +++ b/zephyr/emul/emul_anx7452.c @@ -0,0 +1,262 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "driver/retimer/anx7452.h" +#include "emul/emul_anx7452.h" +#include "emul/emul_common_i2c.h" +#include "emul/emul_stub_device.h" + +#include <zephyr/device.h> +#include <zephyr/drivers/emul.h> +#include <zephyr/drivers/i2c.h> +#include <zephyr/drivers/i2c_emul.h> +#include <zephyr/logging/log.h> + +#define DT_DRV_COMPAT analogix_anx7452 + +#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL +LOG_MODULE_REGISTER(emul_anx7452); + +/** Run-time data used by the emulator */ +struct anx7452_emul_data { + /** Common I2C data */ + struct i2c_common_emul_data top_data; + struct i2c_common_emul_data ctltop_data; + + /** Configuration information */ + const struct anx7452_emul_cfg *cfg; + + /** Current state of all emulated ANX7452 retimer registers */ + uint8_t top_reg; + + uint8_t ctltop_cfg0_reg; + + uint8_t ctltop_cfg1_reg; + + uint8_t ctltop_cfg2_reg; +}; + +/** Constant configuration of the emulator */ +struct anx7452_emul_cfg { + const struct i2c_common_emul_cfg top_cfg; + const struct i2c_common_emul_cfg ctltop_cfg; +}; + +/* Workhorse for mapping i2c reg to internal emulator data access */ +static uint8_t *anx7452_emul_get_reg_ptr(struct anx7452_emul_data *data, + int reg) +{ + switch (reg) { + case ANX7452_TOP_STATUS_REG: + return &(data->top_reg); + case ANX7452_CTLTOP_CFG0_REG: + return &(data->ctltop_cfg0_reg); + case ANX7452_CTLTOP_CFG1_REG: + return &(data->ctltop_cfg1_reg); + case ANX7452_CTLTOP_CFG2_REG: + return &(data->ctltop_cfg2_reg); + default: + __ASSERT(false, "Unimplemented Register Access Error on 0x%x", + reg); + /* Statement never reached, required for compiler warnings */ + return NULL; + } +} + +/** Check description in emul_anx7452.h */ +void anx7452_emul_set_reg(const struct emul *emul, int reg, uint8_t val) +{ + struct anx7452_emul_data *data = emul->data; + + uint8_t *reg_to_write = anx7452_emul_get_reg_ptr(data, reg); + *reg_to_write = val; +} + +/** Check description in emul_anx7452.h */ +uint8_t anx7452_emul_get_reg(const struct emul *emul, int reg) +{ + struct anx7452_emul_data *data = emul->data; + uint8_t *reg_to_read = anx7452_emul_get_reg_ptr(data, reg); + + return *reg_to_read; +} + +/** Check description in emul_anx7452.h */ +void anx7452_emul_reset(const struct emul *emul) +{ + struct anx7452_emul_data *data; + + data = emul->data; + + data->top_reg = 0xFF; + + data->ctltop_cfg0_reg = 0x00; + + data->ctltop_cfg1_reg = 0x00; + + data->ctltop_cfg2_reg = 0x00; +} + +static int anx7452_emul_write_byte(const struct emul *emul, int reg, + uint8_t val, int bytes) +{ + struct anx7452_emul_data *data = emul->data; + + uint8_t *reg_to_write = anx7452_emul_get_reg_ptr(data, reg); + *reg_to_write = val; + + return 0; +} + +static int anx7452_emul_read_byte(const struct emul *emul, int reg, + uint8_t *val, int bytes) +{ + struct anx7452_emul_data *data = emul->data; + uint8_t *reg_to_read = anx7452_emul_get_reg_ptr(data, reg); + + *val = *reg_to_read; + + return 0; +} + +/** + * Emulate an I2C transfer for ANX7452 + * + * This handles simple reads and writes + * + * @param emul I2C emulation information + * @param msgs List of messages to process + * @param num_msgs Number of messages to process + * @param addr Address of the I2C target device + * + * @retval 0 If successful + * @retval -EIO General input / output error + */ +static int anx7452_emul_transfer(const struct emul *emul, struct i2c_msg *msgs, + int num_msgs, int addr) +{ + const struct anx7452_emul_cfg *cfg; + struct anx7452_emul_data *data; + struct i2c_common_emul_data *common_data; + + data = emul->data; + cfg = emul->cfg; + + if (addr == cfg->top_cfg.addr) { + const struct i2c_common_emul_cfg *common_cfg = &cfg->top_cfg; + + common_data = &data->top_data; + return i2c_common_emul_transfer_workhorse( + emul, common_data, common_cfg, msgs, num_msgs, addr); + } else if (addr == cfg->ctltop_cfg.addr) { + const struct i2c_common_emul_cfg *common_cfg = &cfg->ctltop_cfg; + + common_data = &data->ctltop_data; + return i2c_common_emul_transfer_workhorse( + emul, common_data, common_cfg, msgs, num_msgs, addr); + } + + LOG_ERR("Cannot map address %02x", addr); + return -EIO; +} + +/* Device instantiation */ + +static struct i2c_emul_api anx7452_emul_api = { + .transfer = anx7452_emul_transfer, +}; + +/* Device instantiation */ + +/** + * @brief Set up a new ANX7452 retimer emulator + * + * This should be called for each ANX7452 retimer 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 anx7452_emul_init(const struct emul *emul, + const struct device *parent) +{ + const struct anx7452_emul_cfg *cfg; + struct anx7452_emul_data *data; + int ret = 0; + + data = emul->data; + cfg = emul->cfg; + + data->top_data.emul.api = &anx7452_emul_api; + data->top_data.emul.addr = cfg->top_cfg.addr; + data->top_data.emul.target = emul; + data->top_data.i2c = parent; + data->top_data.cfg = &cfg->top_cfg; + i2c_common_emul_init(&data->top_data); + + data->ctltop_data.emul.api = &anx7452_emul_api; + data->ctltop_data.emul.addr = cfg->ctltop_cfg.addr; + data->ctltop_data.emul.target = emul; + data->ctltop_data.i2c = parent; + data->ctltop_data.cfg = &cfg->ctltop_cfg; + i2c_common_emul_init(&data->ctltop_data); + + ret |= i2c_emul_register(parent, &data->top_data.emul); + ret |= i2c_emul_register(parent, &data->ctltop_data.emul); + + anx7452_emul_reset(emul); + + return ret; +} + +#define ANX7452_EMUL(n) \ + static struct anx7452_emul_data anx7452_emul_data_##n = { \ + .top_data = { \ + .write_byte = anx7452_emul_write_byte, \ + .read_byte = anx7452_emul_read_byte, \ + }, \ + .ctltop_data = { \ + .write_byte = anx7452_emul_write_byte, \ + .read_byte = anx7452_emul_read_byte, \ + }, \ + }; \ + static const struct anx7452_emul_cfg anx7452_emul_cfg_##n = { \ + .top_cfg = { \ + .dev_label = DT_NODE_FULL_NAME(DT_DRV_INST(n)), \ + .data = &anx7452_emul_data_##n.top_data, \ + .addr = DT_INST_REG_ADDR(n), \ + }, \ + .ctltop_cfg = { \ + .dev_label = DT_NODE_FULL_NAME(DT_DRV_INST(n)), \ + .data = &anx7452_emul_data_##n.ctltop_data, \ + .addr = ANX7452_I2C_ADDR_CTLTOP_FLAGS, \ + }, \ + }; \ + EMUL_DT_INST_DEFINE(n, anx7452_emul_init, &anx7452_emul_data_##n, \ + &anx7452_emul_cfg_##n, &anx7452_emul_api, NULL) + +DT_INST_FOREACH_STATUS_OKAY(ANX7452_EMUL); + +DT_INST_FOREACH_STATUS_OKAY(EMUL_STUB_DEVICE); + +struct i2c_common_emul_data * +emul_anx7452_get_i2c_common_data(const struct emul *emul, + enum anx7452_emul_port port) +{ + struct anx7452_emul_data *data; + + data = emul->data; + + switch (port) { + case TOP_EMUL_PORT: + return &data->top_data; + case CTLTOP_EMUL_PORT: + return &data->ctltop_data; + default: + return NULL; + } +} |