summaryrefslogtreecommitdiff
path: root/zephyr/emul
diff options
context:
space:
mode:
authorMadhurima Paruchuri <mparuchuri@google.com>2023-03-15 18:54:35 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-04-12 12:23:47 +0000
commitca4eb6b6aea1c24c01923bb38a67065960d15ad4 (patch)
tree8c813d15a194ad527b016a21e9e8cd0635e2c1da /zephyr/emul
parent48cde011ac52a82e5c34d8b50a17c1ae63deaa45 (diff)
downloadchrome-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.txt1
-rw-r--r--zephyr/emul/Kconfig11
-rw-r--r--zephyr/emul/emul_anx7452.c262
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;
+ }
+}