summaryrefslogtreecommitdiff
path: root/zephyr/emul
diff options
context:
space:
mode:
authorEdward Hill <ecgh@chromium.org>2021-06-15 01:34:13 -0600
committerCommit Bot <commit-bot@chromium.org>2021-06-30 19:06:56 +0000
commit3c3f146e86216a03c5946ceedf0996e8c647c55c (patch)
treed5a5c34dccf662ae06d5faf563505bb3d9d1344f /zephyr/emul
parent8df0ec85f3fc54f618cab271f58d6a8a3f55cbc7 (diff)
downloadchrome-ec-3c3f146e86216a03c5946ceedf0996e8c647c55c.tar.gz
zephyr: Add pi3usb9201 emulator and test
BUG=b:184852906 BRANCH=none TEST=zmake configure --test zephyr/test/drivers Change-Id: Ie554b6957269c638357d82d6f5dcc2ceda08caab Signed-off-by: Edward Hill <ecgh@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2961272 Commit-Queue: Keith Short <keithshort@chromium.org> Reviewed-by: Keith Short <keithshort@chromium.org>
Diffstat (limited to 'zephyr/emul')
-rw-r--r--zephyr/emul/CMakeLists.txt1
-rw-r--r--zephyr/emul/Kconfig7
-rw-r--r--zephyr/emul/emul_pi3usb9201.c201
3 files changed, 209 insertions, 0 deletions
diff --git a/zephyr/emul/CMakeLists.txt b/zephyr/emul/CMakeLists.txt
index 0a97a35df6..f490dc2b03 100644
--- a/zephyr/emul/CMakeLists.txt
+++ b/zephyr/emul/CMakeLists.txt
@@ -4,3 +4,4 @@
zephyr_library_sources_ifdef(CONFIG_EMUL_SMART_BATTERY emul_smart_battery.c)
zephyr_library_sources_ifdef(CONFIG_EMUL_BMA255 emul_bma255.c)
+zephyr_library_sources_ifdef(CONFIG_EMUL_BC12_DETECT_PI3USB9201 emul_pi3usb9201.c)
diff --git a/zephyr/emul/Kconfig b/zephyr/emul/Kconfig
index bbf492ea8d..c2850e3e2b 100644
--- a/zephyr/emul/Kconfig
+++ b/zephyr/emul/Kconfig
@@ -13,3 +13,10 @@ config EMUL_BMA255
Enable the BMA255 emulator. This driver use emulated I2C bus.
It is used to test bma2x2 driver. Emulators API is available in
zephyr/include/emul/emul_bma255.h
+
+config EMUL_BC12_DETECT_PI3USB9201
+ bool "PI3USB9201 emulator"
+ help
+ Enable the PI3USB9201 emulator. PI3USB9201 is a BC1.2 charger
+ detector/advertiser. The emulator supports reading and writing the
+ 4 I2C registers of the PI3USB9201 using the emulated I2C bus.
diff --git a/zephyr/emul/emul_pi3usb9201.c b/zephyr/emul/emul_pi3usb9201.c
new file mode 100644
index 0000000000..d00ffe24c6
--- /dev/null
+++ b/zephyr/emul/emul_pi3usb9201.c
@@ -0,0 +1,201 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#define DT_DRV_COMPAT zephyr_pi3usb9201_emul
+
+#include <device.h>
+#include <emul.h>
+#include <drivers/i2c.h>
+#include <drivers/i2c_emul.h>
+
+#include "emul/emul_pi3usb9201.h"
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(emul_pi3usb9201, LOG_LEVEL_DBG);
+
+#define EMUL_REG_COUNT (PI3USB9201_REG_HOST_STS + 1)
+#define EMUL_REG_IS_VALID(reg) (reg >= 0 && reg < EMUL_REG_COUNT)
+
+/** Run-time data used by the emulator */
+struct pi3usb9201_emul_data {
+ /** I2C emulator detail */
+ struct i2c_emul emul;
+ /** pi3usb9201 device being emulated */
+ const struct device *i2c;
+ /** Configuration information */
+ const struct pi3usb9201_emul_cfg *cfg;
+ /** Current state of all emulated pi3usb9201 registers */
+ uint8_t reg[EMUL_REG_COUNT];
+};
+
+/** Static configuration for the emulator */
+struct pi3usb9201_emul_cfg {
+ /** Label of the I2C bus this emulator connects to */
+ const char *i2c_label;
+ /** Pointer to run-time data */
+ struct pi3usb9201_emul_data *data;
+ /** Address of pi3usb9201 on i2c bus */
+ uint16_t addr;
+};
+
+int pi3usb9201_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val)
+{
+ struct pi3usb9201_emul_data *data;
+
+ if (!EMUL_REG_IS_VALID(reg))
+ return -EIO;
+
+ data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul);
+ data->reg[reg] = val;
+
+ return 0;
+}
+
+int pi3usb9201_emul_get_reg(struct i2c_emul *emul, int reg, uint8_t *val)
+{
+ struct pi3usb9201_emul_data *data;
+
+ if (!EMUL_REG_IS_VALID(reg))
+ return -EIO;
+
+ data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul);
+ *val = data->reg[reg];
+
+ return 0;
+}
+
+static void pi3usb9201_emul_reset(struct i2c_emul *emul)
+{
+ struct pi3usb9201_emul_data *data;
+
+ data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul);
+
+ data->reg[PI3USB9201_REG_CTRL_1] = 0;
+ data->reg[PI3USB9201_REG_CTRL_2] = 0;
+ data->reg[PI3USB9201_REG_CLIENT_STS] = 0;
+ data->reg[PI3USB9201_REG_HOST_STS] = 0;
+}
+
+/**
+ * Emulate an I2C transfer to a pi3usb9201
+ *
+ * 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 pi3usb9201_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs,
+ int num_msgs, int addr)
+{
+ const struct pi3usb9201_emul_cfg *cfg;
+ struct pi3usb9201_emul_data *data;
+ unsigned int len;
+ int ret, i, reg;
+ bool read;
+
+ data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul);
+ cfg = data->cfg;
+
+ if (cfg->addr != addr) {
+ LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr,
+ addr);
+ return -EIO;
+ }
+
+ i2c_dump_msgs("emul", msgs, num_msgs, addr);
+
+ if (num_msgs == 1) {
+ if (!(((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE)
+ && (msgs[0].len == 2))) {
+ LOG_ERR("Unexpected write msgs");
+ return -EIO;
+ }
+ return pi3usb9201_emul_set_reg(emul, msgs[0].buf[0],
+ msgs[0].buf[1]);
+ } else if (num_msgs == 2) {
+ if (!(((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE)
+ && (msgs[0].len == 1)
+ && ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ)
+ && (msgs[1].len == 1))) {
+ LOG_ERR("Unexpected read msgs");
+ return -EIO;
+ }
+ return pi3usb9201_emul_get_reg(emul, msgs[0].buf[0],
+ &(msgs[1].buf[0]));
+ } else {
+ LOG_ERR("Unexpected num_msgs");
+ return -EIO;
+ }
+
+}
+
+/* Device instantiation */
+
+static struct i2c_emul_api pi3usb9201_emul_api = {
+ .transfer = pi3usb9201_emul_transfer,
+};
+
+/**
+ * @brief Set up a new pi3usb9201 emulator
+ *
+ * This should be called for each pi3usb9201 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 pi3usb9201_emul_init(const struct emul *emul,
+ const struct device *parent)
+{
+ const struct pi3usb9201_emul_cfg *cfg = emul->cfg;
+ struct pi3usb9201_emul_data *data = cfg->data;
+ int ret;
+
+ data->emul.api = &pi3usb9201_emul_api;
+ data->emul.addr = cfg->addr;
+ data->i2c = parent;
+ data->cfg = cfg;
+
+ ret = i2c_emul_register(parent, emul->dev_label, &data->emul);
+
+ pi3usb9201_emul_reset(&data->emul);
+
+ return ret;
+}
+
+#define PI3USB9201_EMUL(n) \
+ static struct pi3usb9201_emul_data \
+ pi3usb9201_emul_data_##n = {}; \
+ \
+ static const struct pi3usb9201_emul_cfg \
+ pi3usb9201_emul_cfg_##n = { \
+ .i2c_label = DT_INST_BUS_LABEL(n), \
+ .data = &pi3usb9201_emul_data_##n, \
+ .addr = DT_INST_REG_ADDR(n), \
+ }; \
+ EMUL_DEFINE(pi3usb9201_emul_init, DT_DRV_INST(n), \
+ &pi3usb9201_emul_cfg_##n)
+
+DT_INST_FOREACH_STATUS_OKAY(PI3USB9201_EMUL)
+
+#define PI3USB9201_EMUL_CASE(n) \
+ case DT_INST_DEP_ORD(n): return &pi3usb9201_emul_data_##n.emul;
+
+struct i2c_emul *pi3usb9201_emul_get(int ord)
+{
+ switch (ord) {
+ DT_INST_FOREACH_STATUS_OKAY(PI3USB9201_EMUL_CASE)
+
+ default:
+ return NULL;
+ }
+}