From 457ac8c4c99c114e697a1faf3c52cff2abc9d744 Mon Sep 17 00:00:00 2001 From: Tristan Honscheid Date: Thu, 22 Sep 2022 16:27:56 -0600 Subject: zephyr: tests: I2C controller i2c_read32 and i2c_write32 Add tests for the functions `i2c_read32()` and `i2c_write32()` in `common/i2c_controller.c`. Also add a very basic I2C emulator for testing raw reads and writes. BRANCH=None BUG=b:248311206 TEST=./twister Signed-off-by: Tristan Honscheid Change-Id: Id41cbb853e76c456c0fb141bdb97c939687507f6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3916557 Code-Coverage: Zoss Reviewed-by: Aaron Massey --- zephyr/test/drivers/CMakeLists.txt | 1 + zephyr/test/drivers/Kconfig | 3 + zephyr/test/drivers/i2c_controller/CMakeLists.txt | 10 ++ zephyr/test/drivers/i2c_controller/i2c.dts | 13 +++ .../i2c_controller/include/basic_i2c_device_emul.h | 24 +++++ .../i2c_controller/src/basic_i2c_device_emul.c | 89 ++++++++++++++++ .../drivers/i2c_controller/src/i2c_controller.c | 114 +++++++++++++++++++++ zephyr/test/drivers/testcase.yaml | 4 + 8 files changed, 258 insertions(+) create mode 100644 zephyr/test/drivers/i2c_controller/CMakeLists.txt create mode 100644 zephyr/test/drivers/i2c_controller/i2c.dts create mode 100644 zephyr/test/drivers/i2c_controller/include/basic_i2c_device_emul.h create mode 100644 zephyr/test/drivers/i2c_controller/src/basic_i2c_device_emul.c create mode 100644 zephyr/test/drivers/i2c_controller/src/i2c_controller.c diff --git a/zephyr/test/drivers/CMakeLists.txt b/zephyr/test/drivers/CMakeLists.txt index 92b690a40a..41fe7ca7f7 100644 --- a/zephyr/test/drivers/CMakeLists.txt +++ b/zephyr/test/drivers/CMakeLists.txt @@ -48,6 +48,7 @@ add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_DEFAULT default) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_AP_MUX_CONTROL ap_mux_control) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_CHARGESPLASH chargesplash) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_ISL923X isl923x) +add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_I2C_CONTROLLER i2c_controller) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_KEYBOARD_SCAN keyboard_scan) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_LED_DRIVER led_driver) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_MKBP mkbp) diff --git a/zephyr/test/drivers/Kconfig b/zephyr/test/drivers/Kconfig index bcaec2a8f2..900900dc56 100644 --- a/zephyr/test/drivers/Kconfig +++ b/zephyr/test/drivers/Kconfig @@ -17,6 +17,9 @@ config LINK_TEST_SUITE_HOST_COMMANDS config LINK_TEST_SUITE_ISL923X bool "Link and test the isl923x tests" +config LINK_TEST_SUITE_I2C_CONTROLLER + bool "Link and test the i2c_controller tests" + config LINK_TEST_SUITE_KEYBOARD_SCAN bool "Link and test the keyboard_scan tests" diff --git a/zephyr/test/drivers/i2c_controller/CMakeLists.txt b/zephyr/test/drivers/i2c_controller/CMakeLists.txt new file mode 100644 index 0000000000..995146f493 --- /dev/null +++ b/zephyr/test/drivers/i2c_controller/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +zephyr_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") + +target_sources(app PRIVATE + src/basic_i2c_device_emul.c + src/i2c_controller.c +) diff --git a/zephyr/test/drivers/i2c_controller/i2c.dts b/zephyr/test/drivers/i2c_controller/i2c.dts new file mode 100644 index 0000000000..e36a6484c8 --- /dev/null +++ b/zephyr/test/drivers/i2c_controller/i2c.dts @@ -0,0 +1,13 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +&i2c0 { + /* Add a test I2C define */ + basic_i2c_device: basic_i2c_device@ec { + compatible = "basic-i2c-device"; + status = "okay"; + reg = <0xec>; + }; +}; diff --git a/zephyr/test/drivers/i2c_controller/include/basic_i2c_device_emul.h b/zephyr/test/drivers/i2c_controller/include/basic_i2c_device_emul.h new file mode 100644 index 0000000000..8d54e9a335 --- /dev/null +++ b/zephyr/test/drivers/i2c_controller/include/basic_i2c_device_emul.h @@ -0,0 +1,24 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include + +#include "emul/emul_common_i2c.h" + +/** + * @brief Emulator state struct + * + */ +struct basic_i2c_device_data { + struct i2c_common_emul_data common; + uint8_t regs[256]; +}; + +/** + * @brief Resets the internal register store to default + * + * @param emul Pointer to the emulator object + */ +void basic_i2c_device_reset(const struct emul *emul); diff --git a/zephyr/test/drivers/i2c_controller/src/basic_i2c_device_emul.c b/zephyr/test/drivers/i2c_controller/src/basic_i2c_device_emul.c new file mode 100644 index 0000000000..b05fef6836 --- /dev/null +++ b/zephyr/test/drivers/i2c_controller/src/basic_i2c_device_emul.c @@ -0,0 +1,89 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include + +#include "basic_i2c_device_emul.h" +#include "emul/emul_common_i2c.h" +#include "emul/emul_stub_device.h" + +#define DT_DRV_COMPAT basic_i2c_device + +void basic_i2c_device_reset(const struct emul *emul) +{ + struct basic_i2c_device_data *data = + (struct basic_i2c_device_data *)emul->data; + + memset(data->regs, 0, sizeof(data->regs)); +} + +static int basic_i2c_device_write(const struct emul *emul, int reg, uint8_t val, + int bytes, void *unused_data) +{ + struct basic_i2c_device_data *data = + (struct basic_i2c_device_data *)emul->data; + + uint8_t *regs = data->regs; + int pos = reg + bytes - 1; + + if (!IN_RANGE(pos, 0, sizeof(data->regs) - 1)) { + return -1; + } + regs[pos] = val; + + return 0; +} + +static int basic_i2c_device_read(const struct emul *emul, int reg, uint8_t *val, + int bytes, void *unused_data) +{ + struct basic_i2c_device_data *data = + (struct basic_i2c_device_data *)emul->data; + + uint8_t *regs = data->regs; + int pos = reg + bytes; + + if (!IN_RANGE(pos, 0, sizeof(data->regs) - 1)) { + return -1; + } + *val = regs[pos]; + + return 0; +} + +static int basic_i2c_device_init(const struct emul *emul, + const struct device *parent) +{ + struct basic_i2c_device_data *data = + (struct basic_i2c_device_data *)emul->data; + struct i2c_common_emul_data *common_data = &data->common; + + i2c_common_emul_init(common_data); + i2c_common_emul_set_read_func(common_data, basic_i2c_device_read, NULL); + i2c_common_emul_set_write_func(common_data, basic_i2c_device_write, + NULL); + + basic_i2c_device_reset(emul); + + return 0; +} + +#define INIT_BASIC_I2C_DEVICE_EMUL(n) \ + static struct i2c_common_emul_cfg common_cfg_##n; \ + static struct basic_i2c_device_data basic_i2c_device_data_##n; \ + static struct i2c_common_emul_cfg common_cfg_##n = { \ + .dev_label = DT_NODE_FULL_NAME(DT_DRV_INST(n)), \ + .data = &basic_i2c_device_data_##n.common, \ + .addr = DT_INST_REG_ADDR(n) \ + }; \ + static struct basic_i2c_device_data basic_i2c_device_data_##n = { \ + .common = { .cfg = &common_cfg_##n } \ + }; \ + EMUL_DT_INST_DEFINE(n, basic_i2c_device_init, \ + &basic_i2c_device_data_##n, &common_cfg_##n, \ + &i2c_common_emul_api) + +DT_INST_FOREACH_STATUS_OKAY(INIT_BASIC_I2C_DEVICE_EMUL); + +DT_INST_FOREACH_STATUS_OKAY(EMUL_STUB_DEVICE); diff --git a/zephyr/test/drivers/i2c_controller/src/i2c_controller.c b/zephyr/test/drivers/i2c_controller/src/i2c_controller.c new file mode 100644 index 0000000000..cb48a84d38 --- /dev/null +++ b/zephyr/test/drivers/i2c_controller/src/i2c_controller.c @@ -0,0 +1,114 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include +#include +#include +#include + +#include "basic_i2c_device_emul.h" +#include "i2c.h" +#include "test/drivers/test_state.h" + +struct i2c_controller_fixture { + int port; + int addr; + const struct emul *emul; + struct basic_i2c_device_data *emul_data; +}; + +ZTEST_F(i2c_controller, write_read32_le) +{ + uint32_t expected = 0xAABBCCDD; + uint32_t actual; + + zassert_ok(i2c_write32(fixture->port, fixture->addr, 0, expected)); + + /* Get the first four bytes of the register space as a uint32_t */ + actual = *((uint32_t *)&fixture->emul_data->regs[0]); + + zassert_equal(expected, actual, "got %08x, expected %08x", actual, + expected); + + /* Now read back through I2C API */ + zassert_ok(i2c_read32(fixture->port, fixture->addr, 0, &actual)); + + zassert_equal(expected, actual, "got %08x, expected %08x", actual, + expected); +} + +ZTEST_F(i2c_controller, write_read32_be) +{ + uint32_t expected = 0xAABBCCDD; + uint32_t actual; + + zassert_ok(i2c_write32(fixture->port, + fixture->addr | I2C_FLAG_BIG_ENDIAN, 0, + expected)); + + /* Get the first four bytes of the register space as a uint32_t */ + actual = __bswap_32(*((uint32_t *)&fixture->emul_data->regs[0])); + + zassert_equal(expected, actual, "got %08x, expected %08x", actual, + expected); + + /* Now read back through I2C API */ + zassert_ok(i2c_read32(fixture->port, + fixture->addr | I2C_FLAG_BIG_ENDIAN, 0, &actual)); + + zassert_equal(expected, actual, "got %08x, expected %08x", actual, + expected); +} + +ZTEST_F(i2c_controller, read32_fail) +{ + int ret; + uint32_t data; + + /* Fail by reading from wrong address */ + ret = i2c_read32(fixture->port, fixture->addr + 1, 0, &data); + + zassert_equal(EC_ERROR_INVAL, ret, "Got %d", ret); +} + +ZTEST_F(i2c_controller, write32_fail) +{ + int ret; + + /* Fail by writing to wrong address */ + ret = i2c_write32(fixture->port, fixture->addr + 1, 0, 0x00000000); + + zassert_equal(EC_ERROR_INVAL, ret, "Got %d", ret); +} + +static void *setup(void) +{ + static struct i2c_controller_fixture fixture; + const struct emul *emul = EMUL_DT_GET(DT_NODELABEL(basic_i2c_device)); + struct basic_i2c_device_data *emul_data = + (struct basic_i2c_device_data *)emul->data; + + fixture.port = I2C_PORT_BY_DEV(DT_NODELABEL(basic_i2c_device)); + fixture.addr = emul_data->common.cfg->addr; + fixture.emul = emul; + fixture.emul_data = emul_data; + + return &fixture; +} + +static void reset(void *data) +{ + struct i2c_controller_fixture *f = + (struct i2c_controller_fixture *)data; + + basic_i2c_device_reset(f->emul); + + i2c_common_emul_set_read_fail_reg(&f->emul_data->common, + I2C_COMMON_EMUL_NO_FAIL_REG); + i2c_common_emul_set_write_fail_reg(&f->emul_data->common, + I2C_COMMON_EMUL_NO_FAIL_REG); +} + +ZTEST_SUITE(i2c_controller, drivers_predicate_post_main, setup, reset, reset, + NULL); diff --git a/zephyr/test/drivers/testcase.yaml b/zephyr/test/drivers/testcase.yaml index 329eb445dd..352025f89b 100644 --- a/zephyr/test/drivers/testcase.yaml +++ b/zephyr/test/drivers/testcase.yaml @@ -47,6 +47,10 @@ tests: extra_configs: - CONFIG_LINK_TEST_SUITE_ISL923X=y - CONFIG_POWER_SEQUENCE_MOCK=y + drivers.i2c_controller: + extra_args: DTC_OVERLAY_FILE="./boards/native_posix.overlay;i2c_controller/i2c.dts" + extra_configs: + - CONFIG_LINK_TEST_SUITE_I2C_CONTROLLER=y drivers.keyboard_scan: extra_configs: - CONFIG_LINK_TEST_SUITE_KEYBOARD_SCAN=y -- cgit v1.2.1