diff options
author | Abe Levkoy <alevkoy@chromium.org> | 2022-04-20 15:50:14 -0600 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-04-21 13:59:54 +0000 |
commit | b8bd278b08f566d1e6347953c42c93f48290511b (patch) | |
tree | f82cb5f9572ed6570c9534e334f3b6d6c4d97456 /zephyr/emul | |
parent | bf6f0c21d951f00574d24e34040351e94d4545a0 (diff) | |
download | chrome-ec-b8bd278b08f566d1e6347953c42c93f48290511b.tar.gz |
zephyr test: SYV682x emulator: Use common I2C emul
Implement the SYV682x emulator in terms of the common I2C emulator.
Support simulating I2C errors.
BUG=b:190519131
TEST=zmake test test-drivers
BRANCH=none
Signed-off-by: Abe Levkoy <alevkoy@chromium.org>
Change-Id: I7c4bf95efeed1f8d984a8308ca2f147ae771f434
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3330701
Reviewed-by: Sam Hurst <shurst@google.com>
Diffstat (limited to 'zephyr/emul')
-rw-r--r-- | zephyr/emul/emul_syv682x.c | 223 |
1 files changed, 94 insertions, 129 deletions
diff --git a/zephyr/emul/emul_syv682x.c b/zephyr/emul/emul_syv682x.c index 8963a7ced4..1fb79ad60f 100644 --- a/zephyr/emul/emul_syv682x.c +++ b/zephyr/emul/emul_syv682x.c @@ -18,16 +18,15 @@ LOG_MODULE_REGISTER(syv682x); #include <string.h> #include <ztest.h> +#include "emul/emul_common_i2c.h" #include "emul/emul_syv682x.h" #define EMUL_REG_COUNT (SYV682X_CONTROL_4_REG + 1) #define EMUL_REG_IS_VALID(reg) (reg >= 0 && reg < EMUL_REG_COUNT) struct syv682x_emul_data { - /** I2C emulator detail */ - struct i2c_emul emul; - /** Smart battery device being emulated */ - const struct device *i2c; + struct i2c_common_emul_data common; + /** GPIO ports connected to the PPC */ const struct device *frs_en_gpio_port; gpio_pin_t frs_en_gpio_pin; const struct device *alert_gpio_port; @@ -51,14 +50,20 @@ struct syv682x_emul_data { /** Static configuration for the emulator */ struct syv682x_emul_cfg { - /** Label of the I2C bus this emulator connects to */ - const char *i2c_label; - /** Address of smart battery on i2c bus */ - uint16_t addr; - /** Pointer to runtime data */ - struct syv682x_emul_data *data; + const struct i2c_common_emul_cfg common; }; +/* Gets the SYV682x data struct that contains an I2C emulator struct. */ +static struct syv682x_emul_data * +i2c_emul_to_syv682x_emul_data(const struct i2c_emul *emul) +{ + struct i2c_common_emul_data *i2c_common_data = + CONTAINER_OF(emul, struct i2c_common_emul_data, emul); + struct syv682x_emul_data *syv682x_data = + CONTAINER_OF(i2c_common_data, struct syv682x_emul_data, common); + return syv682x_data; +} + /* Asserts or deasserts the interrupt signal to the EC. */ static void syv682x_emul_set_alert(struct syv682x_emul_data *data, bool alert) { @@ -70,12 +75,11 @@ static void syv682x_emul_set_alert(struct syv682x_emul_data *data, bool alert) int syv682x_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val) { - struct syv682x_emul_data *data; + struct syv682x_emul_data *data = i2c_emul_to_syv682x_emul_data(emul); if (!EMUL_REG_IS_VALID(reg)) return -EIO; - data = CONTAINER_OF(emul, struct syv682x_emul_data, emul); data->reg[reg] = val; return 0; @@ -85,8 +89,7 @@ void syv682x_emul_set_condition(struct i2c_emul *emul, uint8_t status, uint8_t control_4) { uint8_t control_4_interrupt = control_4 & SYV682X_CONTROL_4_INT_MASK; - struct syv682x_emul_data *data = - CONTAINER_OF(emul, struct syv682x_emul_data, emul); + struct syv682x_emul_data *data = i2c_emul_to_syv682x_emul_data(emul); int frs_en_gpio = gpio_emul_output_get(data->frs_en_gpio_port, data->frs_en_gpio_pin); @@ -131,8 +134,7 @@ void syv682x_emul_set_condition(struct i2c_emul *emul, uint8_t status, void syv682x_emul_set_busy_reads(struct i2c_emul *emul, int reads) { - struct syv682x_emul_data *data = - CONTAINER_OF(emul, struct syv682x_emul_data, emul); + struct syv682x_emul_data *data = i2c_emul_to_syv682x_emul_data(emul); data->busy_read_count = reads; if (reads) data->reg[SYV682X_CONTROL_3_REG] |= SYV682X_BUSY; @@ -142,129 +144,81 @@ void syv682x_emul_set_busy_reads(struct i2c_emul *emul, int reads) int syv682x_emul_get_reg(struct i2c_emul *emul, int reg, uint8_t *val) { - struct syv682x_emul_data *data; + struct syv682x_emul_data *data = i2c_emul_to_syv682x_emul_data(emul); if (!EMUL_REG_IS_VALID(reg)) return -EIO; - data = CONTAINER_OF(emul, struct syv682x_emul_data, emul); *val = data->reg[reg]; return 0; } -/** - * Emulate an I2C transfer to an SYV682x. This handles simple reads and writes. - * - * @param emul I2C emulation information - * @param msgs List of messages to process. For 'read' messages, this function - * updates the 'buf' member with the data that was read - * @param num_msgs Number of messages to process - * @param addr Address of the I2C target device. - * - * @return 0 on success, -EIO on general input / output error - */ -static int syv682x_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs, - int num_msgs, int addr) +static int syv682x_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, + int bytes) { - const struct syv682x_emul_cfg *cfg; - struct syv682x_emul_data *data; - data = CONTAINER_OF(emul, struct syv682x_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); + struct syv682x_emul_data *data = i2c_emul_to_syv682x_emul_data(emul); - if (num_msgs == 1) { - int reg = msgs[0].buf[0]; - uint8_t val = msgs[0].buf[1]; + zassert_equal(bytes, 1, "Write: bytes == %i at offset 0x%x", bytes, + reg); - if (!((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE - && msgs[0].len == 2)) { - LOG_ERR("Unexpected write msgs"); - return -EIO; - } + switch (reg) { + case SYV682X_CONTROL_1_REG: + /* + * If OVP or TSD is active, the power path stays + * disabled. + */ + if (data->status_cond & + (SYV682X_STATUS_TSD | SYV682X_STATUS_OVP)) + val |= SYV682X_CONTROL_1_PWR_ENB; + break; + case SYV682X_CONTROL_4_REG: + /* Interrupt bits are read-only. */ + val &= ~SYV682X_CONTROL_4_INT_MASK; + break; + default: + break; + } - switch (reg) { - case SYV682X_CONTROL_1_REG: - /* - * If OVP or TSD is active, the power path stays - * disabled. - */ - if (data->status_cond & (SYV682X_STATUS_TSD | - SYV682X_STATUS_OVP)) - val |= SYV682X_CONTROL_1_PWR_ENB; - break; - case SYV682X_CONTROL_4_REG: - /* Interrupt bits are read-only. */ - val &= ~SYV682X_CONTROL_4_INT_MASK; - break; - default: - break; - } + return syv682x_emul_set_reg(emul, reg, val); +} - return syv682x_emul_set_reg(emul, msgs[0].buf[0], val); - } else if (num_msgs == 2) { - int ret; - int reg; - uint8_t *buf; - - 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; - } +static int syv682x_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val, + int bytes) +{ + struct syv682x_emul_data *data = i2c_emul_to_syv682x_emul_data(emul); + int ret = syv682x_emul_get_reg(emul, reg, val); - reg = msgs[0].buf[0]; - buf = &msgs[1].buf[0]; - ret = syv682x_emul_get_reg(emul, reg, buf); + zassert_equal(bytes, 0, "Read: bytes == %i at offset 0x%x", bytes, reg); - switch (reg) { - /* - * STATUS and the interrupt bits of CONTROL_4 are clear-on-read - * (if the underlying condition has cleared). - */ - case SYV682X_STATUS_REG: - syv682x_emul_set_reg(emul, reg, data->status_cond); - break; - case SYV682X_CONTROL_3_REG: - /* Update CONTROL_3[BUSY] based on the busy count. */ - if (data->busy_read_count > 0) { - if (--data->busy_read_count == 0) { - data->reg[SYV682X_CONTROL_3_REG] &= - ~SYV682X_BUSY; - } + switch (reg) { + /* + * STATUS and the interrupt bits of CONTROL_4 are clear-on-read + * (if the underlying condition has cleared). + */ + case SYV682X_STATUS_REG: + syv682x_emul_set_reg(emul, reg, data->status_cond); + break; + case SYV682X_CONTROL_3_REG: + /* Update CONTROL_3[BUSY] based on the busy count. */ + if (data->busy_read_count > 0) { + if (--data->busy_read_count == 0) { + data->reg[SYV682X_CONTROL_3_REG] &= + ~SYV682X_BUSY; } - break; - case SYV682X_CONTROL_4_REG: - syv682x_emul_set_reg(emul, reg, - (*buf & ~SYV682X_CONTROL_4_INT_MASK) | - data->control_4_cond); - break; - default: - break; } - - return ret; - } else { - LOG_ERR("Unexpected num_msgs"); - return -EIO; + break; + case SYV682X_CONTROL_4_REG: + syv682x_emul_set_reg(emul, reg, + (*val & ~SYV682X_CONTROL_4_INT_MASK) | + data->control_4_cond); + break; + default: + break; } -} - -/* Device instantiation */ -static struct i2c_emul_api syv682x_emul_api = { - .transfer = syv682x_emul_transfer, -}; + return ret; +} static void syv682x_emul_reset(struct syv682x_emul_data *data) { @@ -293,19 +247,28 @@ static int syv682x_emul_init(const struct emul *emul, const struct device *parent) { const struct syv682x_emul_cfg *cfg = emul->cfg; - struct syv682x_emul_data *data = cfg->data; + struct syv682x_emul_data *data = emul->data; - data->emul.api = &syv682x_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; data->cfg = cfg; + data->common.emul.api = &i2c_common_emul_api; + data->common.emul.addr = cfg->common.addr; + data->common.emul.parent = emul; + data->common.i2c = parent; + data->common.cfg = &cfg->common; + i2c_common_emul_init(&data->common); + syv682x_emul_reset(data); - return i2c_emul_register(parent, emul->dev_label, &data->emul); + return i2c_emul_register(parent, emul->dev_label, &data->common.emul); } +/* Device instantiation */ #define SYV682X_EMUL(n) \ static struct syv682x_emul_data syv682x_emul_data_##n = { \ + .common = { \ + .write_byte = syv682x_emul_write_byte, \ + .read_byte = syv682x_emul_read_byte, \ + }, \ .frs_en_gpio_port = DEVICE_DT_GET(DT_GPIO_CTLR( \ DT_INST_PROP(n, frs_en_gpio), gpios)), \ .frs_en_gpio_pin = DT_GPIO_PIN( \ @@ -316,17 +279,19 @@ static int syv682x_emul_init(const struct emul *emul, DT_INST_PROP(n, alert_gpio), gpios), \ }; \ static const struct syv682x_emul_cfg syv682x_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .data = &syv682x_emul_data_##n, \ - .addr = DT_INST_REG_ADDR(n), \ + .common = { \ + .i2c_label = DT_INST_BUS_LABEL(n), \ + .dev_label = DT_INST_LABEL(n), \ + .addr = DT_INST_REG_ADDR(n), \ + }, \ }; \ EMUL_DEFINE(syv682x_emul_init, DT_DRV_INST(n), &syv682x_emul_cfg_##n, \ &syv682x_emul_data_##n) DT_INST_FOREACH_STATUS_OKAY(SYV682X_EMUL) -#define SYV682X_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &syv682x_emul_data_##n.emul; +#define SYV682X_EMUL_CASE(n) \ + case DT_INST_DEP_ORD(n): return &syv682x_emul_data_##n.common.emul; struct i2c_emul *syv682x_emul_get(int ord) |