diff options
author | Edward Hill <ecgh@chromium.org> | 2021-06-15 01:34:13 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-06-30 19:06:56 +0000 |
commit | 3c3f146e86216a03c5946ceedf0996e8c647c55c (patch) | |
tree | d5a5c34dccf662ae06d5faf563505bb3d9d1344f /zephyr/emul | |
parent | 8df0ec85f3fc54f618cab271f58d6a8a3f55cbc7 (diff) | |
download | chrome-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.txt | 1 | ||||
-rw-r--r-- | zephyr/emul/Kconfig | 7 | ||||
-rw-r--r-- | zephyr/emul/emul_pi3usb9201.c | 201 |
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; + } +} |