diff options
author | Abe Levkoy <alevkoy@chromium.org> | 2021-09-01 12:15:29 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-09-15 22:42:36 +0000 |
commit | f47bf498f741c04bdfdd6b961f4e579f34279096 (patch) | |
tree | ef18a5d94244b37c6f7316fe495e5b79e45a326e | |
parent | d7884389d0c8d4c29719cf75a1efc3ca3fc02bf7 (diff) | |
download | chrome-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.c | 43 | ||||
-rw-r--r-- | zephyr/include/emul/emul_syv682x.h | 10 | ||||
-rw-r--r-- | zephyr/test/drivers/CMakeLists.txt | 2 | ||||
-rw-r--r-- | zephyr/test/drivers/src/ppc.c | 45 |
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, ®), "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, ®), "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) |