summaryrefslogtreecommitdiff
path: root/zephyr/emul
diff options
context:
space:
mode:
authorAbe Levkoy <alevkoy@chromium.org>2022-04-20 15:50:14 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-21 13:59:54 +0000
commitb8bd278b08f566d1e6347953c42c93f48290511b (patch)
treef82cb5f9572ed6570c9534e334f3b6d6c4d97456 /zephyr/emul
parentbf6f0c21d951f00574d24e34040351e94d4545a0 (diff)
downloadchrome-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.c223
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)