summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbe Levkoy <alevkoy@chromium.org>2021-09-01 12:15:29 -0600
committerCommit Bot <commit-bot@chromium.org>2021-09-15 22:42:36 +0000
commitf47bf498f741c04bdfdd6b961f4e579f34279096 (patch)
treeef18a5d94244b37c6f7316fe495e5b79e45a326e
parentd7884389d0c8d4c29719cf75a1efc3ca3fc02bf7 (diff)
downloadchrome-ec-f47bf498f741c04bdfdd6b961f4e579f34279096.tar.gz
zephyr: Test SYV682 5V_OC interrupt handling
Simulate a 5V OC condition and verify that the driver turns VBUS off. Support status interrupt conditions and clear-on-read registers in SYV682x emulator. Increase line coverage of syv682x.c from 37.9% to 52.8%. BUG=b:190519131 TEST=zmake -l DEBUG configure --test zephyr/test/drivers BRANCH=none Signed-off-by: Abe Levkoy <alevkoy@chromium.org> Change-Id: I9c5b419057cf4ccb1531527a71760533240d1f47 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3059218 Reviewed-by: Jeremy Bettis <jbettis@chromium.org>
-rw-r--r--zephyr/emul/emul_syv682x.c43
-rw-r--r--zephyr/include/emul/emul_syv682x.h10
-rw-r--r--zephyr/test/drivers/CMakeLists.txt2
-rw-r--r--zephyr/test/drivers/src/ppc.c45
4 files changed, 92 insertions, 8 deletions
diff --git a/zephyr/emul/emul_syv682x.c b/zephyr/emul/emul_syv682x.c
index dff9df651c..3d76d10492 100644
--- a/zephyr/emul/emul_syv682x.c
+++ b/zephyr/emul/emul_syv682x.c
@@ -12,6 +12,7 @@
#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(syv682x);
+#include <stdint.h>
#include <string.h>
#include "emul/emul_syv682x.h"
@@ -28,6 +29,12 @@ struct syv682x_emul_data {
const struct syv682x_emul_cfg *cfg;
/** Current state of all emulated SYV682x registers */
uint8_t reg[EMUL_REG_COUNT];
+ /**
+ * Current state of conditions affecting interrupt bits, as distinct
+ * from the current values of those bits stored in reg.
+ */
+ uint8_t status_cond;
+ uint8_t control_4_cond;
};
/** Static configuration for the emulator */
@@ -53,6 +60,15 @@ int syv682x_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val)
return 0;
}
+void syv682x_emul_set_status(struct i2c_emul *emul, uint8_t val)
+{
+ struct syv682x_emul_data *data;
+
+ data = CONTAINER_OF(emul, struct syv682x_emul_data, emul);
+ data->status_cond = val;
+ data->reg[SYV682X_STATUS_REG] |= val;
+}
+
int syv682x_emul_get_reg(struct i2c_emul *emul, int reg, uint8_t *val)
{
struct syv682x_emul_data *data;
@@ -102,6 +118,10 @@ static int syv682x_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs,
return syv682x_emul_set_reg(emul, msgs[0].buf[0],
msgs[0].buf[1]);
} 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) ==
@@ -110,8 +130,27 @@ static int syv682x_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs,
LOG_ERR("Unexpected read msgs");
return -EIO;
}
- return syv682x_emul_get_reg(emul, msgs[0].buf[0],
- &msgs[1].buf[0]);
+
+ reg = msgs[0].buf[0];
+ buf = &msgs[1].buf[0];
+ ret = syv682x_emul_get_reg(emul, reg, buf);
+
+ switch (reg) {
+ /*
+ * These registers 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_4_REG:
+ syv682x_emul_set_reg(emul, reg, data->control_4_cond);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
} else {
LOG_ERR("Unexpected num_msgs");
return -EIO;
diff --git a/zephyr/include/emul/emul_syv682x.h b/zephyr/include/emul/emul_syv682x.h
index 9fec144aa0..aa0d8840f7 100644
--- a/zephyr/include/emul/emul_syv682x.h
+++ b/zephyr/include/emul/emul_syv682x.h
@@ -12,6 +12,7 @@
#define __EMUL_SYV682X_H
#include <drivers/i2c_emul.h>
+#include <stdint.h>
/* Register info copied from syv682.h */
@@ -109,6 +110,15 @@
struct i2c_emul *syv682x_emul_get(int ord);
/**
+ * @brief Set the underlying interrupt conditions affecting the status register
+ *
+ * @param emul SYV682x emulator
+ * @param val A status register value corresponding to the underlying
+ * conditions
+ */
+void syv682x_emul_set_status(struct i2c_emul *emul, uint8_t val);
+
+/**
* @brief Set value of a register of SYV682x
*
* @param emul SYV682x emulator
diff --git a/zephyr/test/drivers/CMakeLists.txt b/zephyr/test/drivers/CMakeLists.txt
index 20d9a53cec..c90b334e60 100644
--- a/zephyr/test/drivers/CMakeLists.txt
+++ b/zephyr/test/drivers/CMakeLists.txt
@@ -7,7 +7,9 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(drivers)
# Include the local test directory for shimmed_test_tasks.h
+zephyr_include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
zephyr_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
+zephyr_include_directories("${PLATFORM_EC}/driver/ppc/")
FILE(GLOB test_sources src/*.c)
target_sources(app PRIVATE ${test_sources})
diff --git a/zephyr/test/drivers/src/ppc.c b/zephyr/test/drivers/src/ppc.c
index d4d067ad27..dced25c227 100644
--- a/zephyr/test/drivers/src/ppc.c
+++ b/zephyr/test/drivers/src/ppc.c
@@ -10,37 +10,70 @@
#include "emul/emul_syv682x.h"
#include "stubs.h"
+#include "syv682x.h"
+#include "timer.h"
#include "usbc_ppc.h"
#define SYV682X_ORD DT_DEP_ORD(DT_NODELABEL(syv682x_emul))
+static const int syv682x_port = 1;
+
static void test_ppc_syv682x_vbus_enable(void)
{
struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
- const int port = 1;
uint8_t reg;
- zassert_ok(ppc_init(port), "PPC init failed");
-
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
"Reading CONTROL_1 failed");
zassert_equal(reg & SYV682X_CONTROL_1_PWR_ENB,
SYV682X_CONTROL_1_PWR_ENB, "VBUS sourcing disabled");
- zassert_false(ppc_is_sourcing_vbus(port),
+ zassert_false(ppc_is_sourcing_vbus(syv682x_port),
"PPC sourcing VBUS at beginning of test");
- zassert_ok(ppc_vbus_source_enable(port, true), "VBUS enable failed");
+ zassert_ok(ppc_vbus_source_enable(syv682x_port, true),
+ "VBUS enable failed");
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
"Reading CONTROL_1 failed");
zassert_equal(reg & SYV682X_CONTROL_1_PWR_ENB, 0,
"VBUS sourcing disabled");
- zassert_true(ppc_is_sourcing_vbus(port),
+ zassert_true(ppc_is_sourcing_vbus(syv682x_port),
"PPC is not sourcing VBUS after VBUS enabled");
}
+static void test_ppc_syv682x_interrupt(void)
+{
+ struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
+
+ syv682x_emul_set_status(emul, SYV682X_STATUS_OC_5V);
+ syv682x_interrupt(syv682x_port);
+
+ /* An OC event less than 100 ms should not cause VBUS to turn off. */
+ msleep(50);
+ syv682x_interrupt(syv682x_port);
+ zassert_true(ppc_is_sourcing_vbus(syv682x_port),
+ "PPC is not sourcing VBUS after 50 ms OC");
+ /* But one greater than 100 ms should. */
+ msleep(60);
+ syv682x_interrupt(syv682x_port);
+ zassert_false(ppc_is_sourcing_vbus(syv682x_port),
+ "PPC is sourcing VBUS after 100 ms OC");
+
+ syv682x_emul_set_status(emul, 0x0);
+ /*
+ * TODO(b/190519131): Organize the tests to be more hermetic and avoid
+ * the following issue: The driver triggers overcurrent protection. If
+ * overcurrent protection is triggered 3 times, the TC won't turn the
+ * port back on without a detach. This could frustrate efforts to test
+ * the TC.
+ */
+}
+
static void test_ppc_syv682x(void)
{
+ zassert_ok(ppc_init(syv682x_port), "PPC init failed");
+
test_ppc_syv682x_vbus_enable();
+ test_ppc_syv682x_interrupt();
}
void test_suite_ppc(void)