From 78f5a2e13645460cd313d6487903e709f0d1143e Mon Sep 17 00:00:00 2001 From: Yuval Peress Date: Sun, 17 Oct 2021 23:04:15 -0600 Subject: zephyr: ppc: sn5s330: Add test for func_set1 retry loop Add a basic test that ensures that the func_set1 register write is attempted at least one more time on an initial failure. BRANCH=none BUG=b:203364783 TEST=zmake configure --test zephyr/test/drivers Signed-off-by: Yuval Peress Change-Id: Ib06794de0af29fb44e4cb550c7b1ef3c2667af0e Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3229005 Commit-Queue: Jeremy Bettis Reviewed-by: Jeremy Bettis --- zephyr/dts/bindings/emul/cros,sn5s330.yaml | 12 +++ zephyr/emul/CMakeLists.txt | 1 + zephyr/emul/Kconfig | 1 + zephyr/emul/Kconfig.sn5s330 | 22 +++++ zephyr/emul/emul_sn5s330.c | 128 +++++++++++++++++++++++++++++ zephyr/include/emul/emul_sn5s330.h | 30 +++++++ zephyr/test/drivers/overlay.dts | 6 ++ zephyr/test/drivers/src/main.c | 2 + zephyr/test/drivers/src/ppc_sn5s330.c | 60 ++++++++++++++ 9 files changed, 262 insertions(+) create mode 100644 zephyr/dts/bindings/emul/cros,sn5s330.yaml create mode 100644 zephyr/emul/Kconfig.sn5s330 create mode 100644 zephyr/emul/emul_sn5s330.c create mode 100644 zephyr/include/emul/emul_sn5s330.h create mode 100644 zephyr/test/drivers/src/ppc_sn5s330.c diff --git a/zephyr/dts/bindings/emul/cros,sn5s330.yaml b/zephyr/dts/bindings/emul/cros,sn5s330.yaml new file mode 100644 index 0000000000..b7964b777b --- /dev/null +++ b/zephyr/dts/bindings/emul/cros,sn5s330.yaml @@ -0,0 +1,12 @@ +# Copyright 2021 The chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +description: sn5s330 emulator + +compatible: "cros,sn5s330" + +include: base.yaml +properties: + reg: + required: true diff --git a/zephyr/emul/CMakeLists.txt b/zephyr/emul/CMakeLists.txt index 19dcc84d30..ce3ad191eb 100644 --- a/zephyr/emul/CMakeLists.txt +++ b/zephyr/emul/CMakeLists.txt @@ -18,3 +18,4 @@ zephyr_library_sources_ifdef(CONFIG_I2C_MOCK i2c_mock.c) zephyr_library_sources_ifdef(CONFIG_EMUL_ISL923X emul_isl923x.c) zephyr_library_sources_ifdef(CONFIG_EMUL_CLOCK_CONTROL emul_clock_control.c) zephyr_library_sources_ifdef(CONFIG_EMUL_TCPCI emul_tcpci.c) +zephyr_library_sources_ifdef(CONFIG_EMUL_SN5S330 emul_sn5s330.c) diff --git a/zephyr/emul/Kconfig b/zephyr/emul/Kconfig index 9a0b434bc9..a6b39405c6 100644 --- a/zephyr/emul/Kconfig +++ b/zephyr/emul/Kconfig @@ -73,3 +73,4 @@ rsource "Kconfig.i2c_mock" rsource "Kconfig.isl923x" rsource "Kconfig.clock_control" rsource "Kconfig.tcpci" +rsource "Kconfig.sn5s330" diff --git a/zephyr/emul/Kconfig.sn5s330 b/zephyr/emul/Kconfig.sn5s330 new file mode 100644 index 0000000000..aba3bb9028 --- /dev/null +++ b/zephyr/emul/Kconfig.sn5s330 @@ -0,0 +1,22 @@ +# Copyright 2021 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +DT_COMPAT_SN5S330_EMUL := cros,sn5s330-emul + +menuconfig EMUL_SN5S330 + bool "sn5s330 emulator" + default $(dt_compat_enabled,$(DT_COMPAT_SN5S330_EMUL)) + depends on I2C_EMUL + help + Enable the sn5s330 emulator. This driver uses the emulated I2C bus. It + is used to test the sn5s330 driver. Emulator API is available in + zephyr/include/emul/emul_sn5s330.h + +if EMUL_SN5S330 + +module = SN5S330_EMUL +module-str = sn5s330_emul +source "subsys/logging/Kconfig.template.log_config" + +endif # EMUL_SN5S330 diff --git a/zephyr/emul/emul_sn5s330.c b/zephyr/emul/emul_sn5s330.c new file mode 100644 index 0000000000..44334ec71b --- /dev/null +++ b/zephyr/emul/emul_sn5s330.c @@ -0,0 +1,128 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define DT_DRV_COMPAT cros_sn5s330_emul + +#include +#include +#include +#include +#include +#include + +#include "driver/ppc/sn5s330.h" +#include "driver/ppc/sn5s330_public.h" +#include "emul/emul_common_i2c.h" +#include "emul/emul_sn5s330.h" +#include "i2c.h" + +#include +LOG_MODULE_REGISTER(sn5s330_emul, CONFIG_SN5S330_EMUL_LOG_LEVEL); + +#define SN5S330_DATA_FROM_I2C_EMUL(_emul) \ + CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ + struct sn5s330_emul_data, common) + +struct sn5s330_emul_data { + /** Common I2C data */ + struct i2c_common_emul_data common; + /** Emulated FUNC_SET1 register */ + uint8_t func_set1_reg; +}; + +struct sn5s330_emul_cfg { + /** Common I2C config */ + const struct i2c_common_emul_cfg common; +}; + +struct i2c_emul *sn5s330_emul_to_i2c_emul(const struct emul *emul) +{ + struct sn5s330_emul_data *data = emul->data; + + return &(data->common.emul); +} + +int sn5s330_emul_peek_reg(const struct emul *emul, uint32_t reg, uint32_t *val) +{ + struct sn5s330_emul_data *data = SN5S330_DATA_FROM_I2C_EMUL(emul); + + switch (reg) { + case SN5S330_FUNC_SET1: + *val = data->func_set1_reg; + break; + default: + return -EINVAL; + } + return 0; +} + +static int sn5s330_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val, + int bytes) +{ + struct sn5s330_emul_data *data = SN5S330_DATA_FROM_I2C_EMUL(emul); + + switch (reg) { + case SN5S330_FUNC_SET1: + __ASSERT_NO_MSG(bytes == 0); + *val = data->func_set1_reg; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int sn5s330_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, + int bytes) +{ + struct sn5s330_emul_data *data = SN5S330_DATA_FROM_I2C_EMUL(emul); + + switch (reg) { + case SN5S330_FUNC_SET1: + __ASSERT_NO_MSG(bytes == 1); + data->func_set1_reg = val; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int emul_sn5s330_init(const struct emul *emul, + const struct device *parent) +{ + const struct sn5s330_emul_cfg *cfg = emul->cfg; + struct sn5s330_emul_data *data = emul->data; + + 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); + + return i2c_emul_register(parent, emul->dev_label, &data->common.emul); +} + +#define INIT_SN5S330(n) \ + static struct sn5s330_emul_data sn5s330_emul_data_##n = { \ + .common = { \ + .write_byte = sn5s330_emul_write_byte, \ + .read_byte = sn5s330_emul_read_byte, \ + }, \ + }; \ + static struct sn5s330_emul_cfg sn5s330_emul_cfg_##n = { \ + .common = { \ + .i2c_label = DT_INST_BUS_LABEL(n), \ + .dev_label = DT_INST_LABEL(n), \ + .addr = DT_INST_REG_ADDR(n), \ + }, \ + }; \ + EMUL_DEFINE(emul_sn5s330_init, DT_DRV_INST(n), &sn5s330_emul_cfg_##n, \ + &sn5s330_emul_data_##n) + +DT_INST_FOREACH_STATUS_OKAY(INIT_SN5S330) diff --git a/zephyr/include/emul/emul_sn5s330.h b/zephyr/include/emul/emul_sn5s330.h new file mode 100644 index 0000000000..ad6d0f04c1 --- /dev/null +++ b/zephyr/include/emul/emul_sn5s330.h @@ -0,0 +1,30 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef ZEPHYR_INCLUDE_EMUL_EMUL_SN5S330_H_ +#define ZEPHYR_INCLUDE_EMUL_EMUL_SN5S330_H_ + +#include +#include + +/** + * @brief The i2c emulator pointer from the top level emul. + * + * @param emul The emulator to query + * @return Pointer to the i2c emulator struct + */ +struct i2c_emul *sn5s330_emul_to_i2c_emul(const struct emul *emul); + +/** + * @brief Get the register value without incurring any side-effects + * + * @param emul The emulator to query + * @param reg The register to read + * @param val Pointer to write the register value to + * @return 0 on success + */ +int sn5s330_emul_peek_reg(const struct emul *emul, uint32_t reg, uint32_t *val); + +#endif /* ZEPHYR_INCLUDE_EMUL_EMUL_SN5S330_H_ */ diff --git a/zephyr/test/drivers/overlay.dts b/zephyr/test/drivers/overlay.dts index d49973180d..96fc7de31a 100644 --- a/zephyr/test/drivers/overlay.dts +++ b/zephyr/test/drivers/overlay.dts @@ -520,6 +520,12 @@ label = "PI3USB9201_EMUL"; }; + sn5s330_emul: sn5s330@40 { + compatible = "cros,sn5s330-emul"; + reg = <0x40>; + label = "SN5S330_EMUL"; + }; + syv682x_emul: syv682x@41 { compatible = "zephyr,syv682x-emul"; reg = <0x41>; diff --git a/zephyr/test/drivers/src/main.c b/zephyr/test/drivers/src/main.c index 64e49b7006..ee82140ca6 100644 --- a/zephyr/test/drivers/src/main.c +++ b/zephyr/test/drivers/src/main.c @@ -26,6 +26,7 @@ extern void test_suite_stm_mems_common(void); extern void test_suite_isl923x(void); extern void test_suite_usb_mux(void); extern void test_suite_ppc_syv682c(void); +extern void test_suite_ppc_sn5s330(void); extern void test_suite_cros_cbi(void); extern void test_suite_tcpci(void); @@ -54,6 +55,7 @@ void test_main(void) test_suite_stm_mems_common(); test_suite_isl923x(); test_suite_usb_mux(); + test_suite_ppc_sn5s330(); test_suite_ppc_syv682c(); test_suite_cros_cbi(); test_suite_tcpci(); diff --git a/zephyr/test/drivers/src/ppc_sn5s330.c b/zephyr/test/drivers/src/ppc_sn5s330.c new file mode 100644 index 0000000000..f38376072a --- /dev/null +++ b/zephyr/test/drivers/src/ppc_sn5s330.c @@ -0,0 +1,60 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * 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 "driver/ppc/sn5s330.h" +#include "driver/ppc/sn5s330_public.h" +#include "emul/emul_common_i2c.h" +#include "emul/emul_sn5s330.h" +#include "usbc_ppc.h" + +/** This must match the index of the sn5s330 in ppc_chips[] */ +#define SN5S330_PORT 0 +#define EMUL emul_get_binding(DT_LABEL(DT_NODELABEL(sn5s330_emul))) + +static int fail_until_write_func(struct i2c_emul *emul, int reg, uint8_t val, + int bytes, void *data) +{ + uint32_t *count = data; + + if (*count != 0) { + *count -= 1; + return -EIO; + } + return 0; +} + +static void test_fail_once_func_set1(void) +{ + const struct emul *emul = EMUL; + struct i2c_emul *i2c_emul = sn5s330_emul_to_i2c_emul(emul); + uint32_t count = 1; + uint32_t func_set1_value; + + i2c_common_emul_set_write_func(i2c_emul, fail_until_write_func, &count); + /* + * Call the init and ignore the return value, we're just checking that + * setting FUNC_SET1 retries at least once. + */ + sn5s330_drv.init(SN5S330_PORT); + zassert_equal(count, 0, NULL); + zassert_ok(sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET1, + &func_set1_value), + NULL); + zassert_true((func_set1_value & SN5S330_ILIM_1_62) != 0, NULL); + i2c_common_emul_set_write_func(i2c_emul, NULL, NULL); +} + +void test_suite_ppc_sn5s330(void) +{ + ztest_test_suite( + ppc_sn5s330, + ztest_unit_test(test_fail_once_func_set1)); + ztest_run_test_suite(ppc_sn5s330); +} -- cgit v1.2.1