diff options
author | Dawid Niedzwiecki <dawidn@google.com> | 2022-11-10 08:37:19 +0000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-11-14 16:22:41 +0000 |
commit | 5cf490d59c3d0a2ab0ac82b963888de4035a68ef (patch) | |
tree | 0b747f6efe460f26768d13b886ae76aabc206152 | |
parent | 8260703ba889dfde312eaf0eca8f48c9d4273440 (diff) | |
download | chrome-ec-5cf490d59c3d0a2ab0ac82b963888de4035a68ef.tar.gz |
zephyr: tests: add pct2075 emulator
Add PCT2075 temperature sensor emulator. The PCT2075 doesn't support
the OS pin.
The emulator helps with testing code that is touched only by i2c
temperature sensors.
BUG=b:244474857
BRANCH=main
TEST=twister -T zephyr/test/drivers
Signed-off-by: Dawid Niedzwiecki <dn@semihalf.com>
Change-Id: Iaefed4ffd50b17b59da89361abeded28456751ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4020414
Commit-Queue: Keith Short <keithshort@chromium.org>
Tested-by: Dawid Niedzwiecki <dawidn@google.com>
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Reviewed-by: Keith Short <keithshort@chromium.org>
-rw-r--r-- | include/driver/temp_sensor/pct2075.h | 1 | ||||
-rw-r--r-- | zephyr/emul/CMakeLists.txt | 1 | ||||
-rw-r--r-- | zephyr/emul/Kconfig | 7 | ||||
-rw-r--r-- | zephyr/emul/emul_pct2075.c | 107 | ||||
-rw-r--r-- | zephyr/include/emul/emul_pct2075.h | 31 | ||||
-rw-r--r-- | zephyr/shim/src/temp_sensors.c | 2 | ||||
-rw-r--r-- | zephyr/test/drivers/boards/native_posix.overlay | 10 | ||||
-rw-r--r-- | zephyr/test/drivers/default/src/temp_sensor.c | 93 | ||||
-rw-r--r-- | zephyr/test/drivers/default/src/thermistor.c | 32 | ||||
-rw-r--r-- | zephyr/test/drivers/prj.conf | 2 |
10 files changed, 285 insertions, 1 deletions
diff --git a/include/driver/temp_sensor/pct2075.h b/include/driver/temp_sensor/pct2075.h index e79ac0e97a..77fae67712 100644 --- a/include/driver/temp_sensor/pct2075.h +++ b/include/driver/temp_sensor/pct2075.h @@ -21,6 +21,7 @@ #define PCT2075_REG_CONF 0x01 #define PCT2075_REG_THYST 0x02 #define PCT2075_REG_TOS 0x03 +#define PCT2075_REG_TIDLE 0x04 /* * I2C port and address information for all the board PCT2075 sensors should be diff --git a/zephyr/emul/CMakeLists.txt b/zephyr/emul/CMakeLists.txt index 377be11792..3d268dde80 100644 --- a/zephyr/emul/CMakeLists.txt +++ b/zephyr/emul/CMakeLists.txt @@ -26,5 +26,6 @@ zephyr_library_sources_ifdef(CONFIG_EMUL_CROS_FLASH emul_flash.c) zephyr_library_sources_ifdef(CONFIG_EMUL_RTC emul_rtc.c) zephyr_library_sources_ifdef(CONFIG_EMUL_RT9490 emul_rt9490.c) zephyr_library_sources_ifdef(CONFIG_PWM_MOCK pwm_mock.c) +zephyr_library_sources_ifdef(CONFIG_EMUL_PCT2075 emul_pct2075.c) cros_ec_library_include_directories_ifdef(CONFIG_EMUL_CROS_FLASH include) diff --git a/zephyr/emul/Kconfig b/zephyr/emul/Kconfig index e445e30154..94bc4ecc0d 100644 --- a/zephyr/emul/Kconfig +++ b/zephyr/emul/Kconfig @@ -106,6 +106,13 @@ config PWM_MOCK Enable the PWM mock. This driver is a pure mock and does nothing by default. +config EMUL_PCT2075 + bool "PCT2075 emulator" + select EMUL_COMMON_I2C + help + Enable the PCT2075 temperature sensor emulator. It uses emulated I2C bus. + Emulator API is available in zephyr/include/emul/emul_pct2075.h. + rsource "Kconfig.ln9310" rsource "Kconfig.lis2dw12" rsource "Kconfig.i2c_mock" diff --git a/zephyr/emul/emul_pct2075.c b/zephyr/emul/emul_pct2075.c new file mode 100644 index 0000000000..f820fbd30a --- /dev/null +++ b/zephyr/emul/emul_pct2075.c @@ -0,0 +1,107 @@ +/* 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 <zephyr/device.h> + +#include "driver/temp_sensor/pct2075.h" +#include "emul/emul_common_i2c.h" +#include "emul/emul_stub_device.h" +#include "emul/emul_pct2075.h" +#include "util.h" + +/* NOTE: The emulator doesn't support OS pin */ + +#define DT_DRV_COMPAT nxp_pct2075 + +#define PCT2075_TEMP_MAX_MC 127000 +#define PCT2075_TEMP_MIN_MC -55000 +#define PCT2075_RESOLUTION_MC 125 + +static const uint16_t default_values[PCT2075_REG_NUMBER] = { + [PCT2075_REG_TEMP] = 0x00, [PCT2075_REG_CONF] = 0x00, + [PCT2075_REG_THYST] = 0x4b00, [PCT2075_REG_TOS] = 0x5000, + [PCT2075_REG_TIDLE] = 0x00, +}; + +void pct2075_emul_reset_regs(const struct emul *emul) +{ + struct pct2075_data *data = (struct pct2075_data *)emul->data; + + memcpy(data->regs, default_values, PCT2075_REG_NUMBER + 1); +} + +int pct2075_emul_set_temp(const struct emul *emul, int mk) +{ + struct pct2075_data *data = (struct pct2075_data *)emul->data; + int mc = MILLI_KELVIN_TO_MILLI_CELSIUS(mk); + int reg; + + if (!IN_RANGE(mc, PCT2075_TEMP_MIN_MC, PCT2075_TEMP_MAX_MC)) { + return -1; + } + + /* Divide by the sensor resolution to get register value */ + reg = mc / PCT2075_RESOLUTION_MC; + + /* Use 11 most significant bits. */ + data->regs[PCT2075_REG_TEMP] = reg << 5; + + return 0; +} + +int pct2075_emul_read_byte(const struct emul *target, int reg, uint8_t *val, + int bytes) +{ + struct pct2075_data *data = (struct pct2075_data *)target->data; + + if (!IN_RANGE(reg, 0, PCT2075_REG_NUMBER - 1)) { + return -1; + } + + if (bytes == 0) { + *val = data->regs[reg] >> 8; + } else if (bytes == 1) { + *val = data->regs[reg] & 0x00FF; + } else { + /* Support up to 2 bytes read */ + return -1; + } + + return 0; +} + +static int pct2075_emul_init(const struct emul *emul, + const struct device *parent) +{ + struct pct2075_data *data = (struct pct2075_data *)emul->data; + struct i2c_common_emul_data *common_data = &data->common; + + i2c_common_emul_init(common_data); + + pct2075_emul_reset_regs(emul); + + return 0; +} + +#define INIT_PCT2075_EMUL(n) \ + static struct i2c_common_emul_cfg common_cfg_##n; \ + static struct pct2075_data pct2075_data_##n; \ + static struct i2c_common_emul_cfg common_cfg_##n = { \ + .dev_label = DT_NODE_FULL_NAME(DT_DRV_INST(n)), \ + .data = &pct2075_data_##n.common, \ + .addr = DT_INST_REG_ADDR(n) \ + }; \ + static struct pct2075_data pct2075_data_##n = { \ + .common = { \ + .cfg = &common_cfg_##n, \ + .read_byte = pct2075_emul_read_byte, \ + }, \ + }; \ + EMUL_DT_INST_DEFINE(n, pct2075_emul_init, &pct2075_data_##n, \ + &common_cfg_##n, &i2c_common_emul_api) + +DT_INST_FOREACH_STATUS_OKAY(INIT_PCT2075_EMUL) + +DT_INST_FOREACH_STATUS_OKAY(EMUL_STUB_DEVICE); diff --git a/zephyr/include/emul/emul_pct2075.h b/zephyr/include/emul/emul_pct2075.h new file mode 100644 index 0000000000..0c62942a20 --- /dev/null +++ b/zephyr/include/emul/emul_pct2075.h @@ -0,0 +1,31 @@ +/* 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. + */ + +#ifndef EMUL_PCT2075_H +#define EMUL_PCT2075_H + +#include <zephyr/drivers/emul.h> +#include "emul/emul_common_i2c.h" + +#define PCT2075_REG_NUMBER 5 + +struct pct2075_data { + struct i2c_common_emul_data common; + uint16_t regs[PCT2075_REG_NUMBER]; +}; + +/** + * @brief Set the temperature measurement for the sensor. + * + * @param emul Pointer to emulator + * @param mk Temperature to set in mili-kalvin. The temperature + * should me in range of 328150 to 400150, with 150 resolution. + * + * @return 0 on success + * @return negative on error + */ +int pct2075_emul_set_temp(const struct emul *emul, int mk); + +#endif diff --git a/zephyr/shim/src/temp_sensors.c b/zephyr/shim/src/temp_sensors.c index 371d7d7fc9..c8f2047c94 100644 --- a/zephyr/shim/src/temp_sensors.c +++ b/zephyr/shim/src/temp_sensors.c @@ -235,6 +235,8 @@ const struct tmp112_sensor_t tmp112_sensors[TMP112_COUNT] = { const struct temp_sensor_t temp_sensors[] = { DT_FOREACH_CHILD_SEP( TEMP_SENSORS_NODEID, TEMP_SENSOR_ENTRY, (, )) }; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr) { const struct temp_sensor_t *sensor; diff --git a/zephyr/test/drivers/boards/native_posix.overlay b/zephyr/test/drivers/boards/native_posix.overlay index 5489c36d00..e244cb39f1 100644 --- a/zephyr/test/drivers/boards/native_posix.overlay +++ b/zephyr/test/drivers/boards/native_posix.overlay @@ -522,6 +522,11 @@ power-good-pin = <&gpio_ec_pg_pin_temp>; sensor = <&temp_fan>; }; + named_pct2075: soc { + status = "okay"; + power-good-pin = <&gpio_ec_pg_pin_temp>; + sensor = <&pct2075_emul>; + }; }; /* @@ -856,6 +861,11 @@ p1-i2c-addr = <0x9>; gpio-i2c-addr = <0x1a>; }; + + pct2075_emul: pct2075@48 { + compatible = "nxp,pct2075"; + reg = <0x48>; + }; }; clock: clock { diff --git a/zephyr/test/drivers/default/src/temp_sensor.c b/zephyr/test/drivers/default/src/temp_sensor.c index 61441a0229..f387302d73 100644 --- a/zephyr/test/drivers/default/src/temp_sensor.c +++ b/zephyr/test/drivers/default/src/temp_sensor.c @@ -9,13 +9,18 @@ #include <zephyr/drivers/adc/adc_emul.h> #include <zephyr/drivers/gpio.h> #include <zephyr/drivers/gpio/gpio_emul.h> +#include <zephyr/drivers/emul.h> #include <math.h> #include "common.h" +#include "driver/temp_sensor/pct2075.h" +#include "emul/emul_pct2075.h" +#include "math_util.h" #include "temp_sensor.h" #include "temp_sensor/temp_sensor.h" #include "test/drivers/test_state.h" +#include "timer.h" #define GPIO_PG_EC_DSW_PWROK_PATH DT_PATH(named_gpios, pg_ec_dsw_pwrok) #define GPIO_PG_EC_DSW_PWROK_PORT DT_GPIO_PIN(GPIO_PG_EC_DSW_PWROK_PATH, gpios) @@ -110,6 +115,11 @@ ZTEST_USER(temp_sensor, test_temp_sensor_pg_pin) named_temp_pp3300_regulator)), &temp), NULL); + zassert_equal( + EC_ERROR_NOT_POWERED, + temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL(named_pct2075)), + &temp), + NULL); /* power ADC */ zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_EC_PG_PIN_TEMP_PORT, 1), @@ -179,12 +189,92 @@ ZTEST_USER(temp_sensor, test_temp_sensor_read) } } +/** Test if temp_sensor_read() returns temperature on success for PCT2075 */ +ZTEST_USER(temp_sensor, test_temp_sensor_pct2075) +{ + int temp; + const struct emul *dev = EMUL_DT_GET(DT_NODELABEL(pct2075_emul)); + int mk[] = { + MILLI_CELSIUS_TO_MILLI_KELVIN(127000), + MILLI_CELSIUS_TO_MILLI_KELVIN(126850), + MILLI_CELSIUS_TO_MILLI_KELVIN(125), + MILLI_CELSIUS_TO_MILLI_KELVIN(0), + MILLI_CELSIUS_TO_MILLI_KELVIN(-125), + MILLI_CELSIUS_TO_MILLI_KELVIN(-54875), + MILLI_CELSIUS_TO_MILLI_KELVIN(-55000), + }; + + for (int i = 0; i < ARRAY_SIZE(mk); i++) { + pct2075_emul_set_temp(dev, mk[i]); + /* Highly dependent on current implementation. The sensor + * update temperature in the 1 second periodic hook, so + * we need to wait for it. + */ + msleep(1100); + zassert_equal(EC_SUCCESS, + temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL( + named_pct2075)), + &temp)); + zassert_equal(MILLI_KELVIN_TO_KELVIN(mk[i]), temp); + } +} + +/** Test if temperature is not updated on I2C read fail. + * The test highly dependent on current implementation - temp_sensor_read + * doesn't return an error on the i2c read fail, which can/should be changed + * in the future. + */ +ZTEST_USER(temp_sensor, test_temp_sensor_pct2075_fail) +{ + const struct emul *dev = EMUL_DT_GET(DT_NODELABEL(pct2075_emul)); + struct pct2075_data *data = (struct pct2075_data *)dev->data; + int mk1 = 373000, mk2 = 273000; + int temp; + + /* Set initial temperature */ + pct2075_emul_set_temp(dev, mk1); + msleep(1100); + + zassert_equal(EC_SUCCESS, temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL( + named_pct2075)), + &temp)); + /* Make sure the temperature is read correctly */ + zassert_equal(MILLI_KELVIN_TO_KELVIN(mk1), temp); + + /* Set I2C fail on the temperature register */ + i2c_common_emul_set_read_fail_reg(&data->common, PCT2075_REG_TEMP); + pct2075_emul_set_temp(dev, mk2); + /* Wait for potential update */ + msleep(1100); + + /* Make sure the temperature is not changed */ + zassert_equal(EC_SUCCESS, temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL( + named_pct2075)), + &temp)); + zassert_equal(MILLI_KELVIN_TO_KELVIN(mk1), temp); + + /* Restore I2C */ + i2c_common_emul_set_read_fail_reg(&data->common, + I2C_COMMON_EMUL_NO_FAIL_REG); + /* Wait for update */ + msleep(1100); + /* Make sure the temperature is updated */ + zassert_equal(EC_SUCCESS, temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL( + named_pct2075)), + &temp)); + zassert_equal(MILLI_KELVIN_TO_KELVIN(mk2), temp); +} + static void *temp_sensor_setup(void) { const struct device *dev = DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_PG_EC_DSW_PWROK_PATH, gpios)); const struct device *dev_pin = DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_EC_PG_PIN_TEMP_PATH, gpios)); + const struct emul *pct2075_dev = + EMUL_DT_GET(DT_NODELABEL(pct2075_emul)); + struct pct2075_data *pct2075_data = + (struct pct2075_data *)pct2075_dev->data; zassert_not_null(dev, NULL); /* Before tests make sure that power pins are set. */ @@ -193,6 +283,9 @@ static void *temp_sensor_setup(void) zassert_ok(gpio_emul_input_set(dev_pin, GPIO_EC_PG_PIN_TEMP_PORT, 1), NULL); + i2c_common_emul_set_read_fail_reg(&pct2075_data->common, + I2C_COMMON_EMUL_NO_FAIL_REG); + return NULL; } diff --git a/zephyr/test/drivers/default/src/thermistor.c b/zephyr/test/drivers/default/src/thermistor.c index 417b482d99..9e41307618 100644 --- a/zephyr/test/drivers/default/src/thermistor.c +++ b/zephyr/test/drivers/default/src/thermistor.c @@ -58,6 +58,10 @@ ZTEST_USER(thermistor, test_thermistor_power_pin) sensor_idx++) { const struct temp_sensor_t *sensor = &temp_sensors[sensor_idx]; + /* Skip for sensors that are not thermistors */ + if (sensor->zephyr_info->thermistor == NULL) + continue; + zassert_ok(adc_emul_const_value_set(adc_dev, sensor->idx, A_VALID_VOLTAGE), "adc_emul_value_func_set() failed on %s", @@ -72,6 +76,10 @@ ZTEST_USER(thermistor, test_thermistor_power_pin) sensor_idx++) { const struct temp_sensor_t *sensor = &temp_sensors[sensor_idx]; + /* Skip for sensors that are not thermistors */ + if (sensor->zephyr_info->thermistor == NULL) + continue; + zassert_equal(EC_ERROR_NOT_POWERED, sensor->zephyr_info->read(sensor, &temp), "%s failed", sensor->name); @@ -85,6 +93,10 @@ ZTEST_USER(thermistor, test_thermistor_power_pin) sensor_idx++) { const struct temp_sensor_t *sensor = &temp_sensors[sensor_idx]; + /* Skip for sensors that are not thermistors */ + if (sensor->zephyr_info->thermistor == NULL) + continue; + zassert_equal(EC_SUCCESS, sensor->zephyr_info->read(sensor, &temp), "%s failed", sensor->name); @@ -113,6 +125,10 @@ ZTEST_USER(thermistor, test_thermistor_adc_read_error) sensor_idx++) { const struct temp_sensor_t *sensor = &temp_sensors[sensor_idx]; + /* Skip for sensors that are not thermistors */ + if (sensor->zephyr_info->thermistor == NULL) + continue; + zassert_ok(adc_emul_value_func_set(adc_dev, sensor->idx, adc_error_func, NULL), "adc_emul_value_func_set() failed on %s", @@ -123,6 +139,10 @@ ZTEST_USER(thermistor, test_thermistor_adc_read_error) sensor_idx++) { const struct temp_sensor_t *sensor = &temp_sensors[sensor_idx]; + /* Skip for sensors that are not thermistors */ + if (sensor->zephyr_info->thermistor == NULL) + continue; + zassert_equal(EC_ERROR_UNKNOWN, sensor->zephyr_info->read(sensor, &temp), "%s failed", sensor->name); @@ -265,10 +285,16 @@ ZTEST_USER(thermistor, test_thermistors_adc_temperature_conversion) const static int reference_res_arr[] = { DT_FOREACH_STATUS_OKAY( THERMISTOR_COMPAT, GET_THERMISTOR_REF_RES) }; - for (sensor_idx = 0; sensor_idx < NAMED_TEMP_SENSORS_SIZE; sensor_idx++) + for (sensor_idx = 0; sensor_idx < NAMED_TEMP_SENSORS_SIZE; + sensor_idx++) { + /* Skip for sensors that are not thermistors */ + if (temp_sensors[sensor_idx].zephyr_info->thermistor == NULL) + continue; + do_thermistor_test(&temp_sensors[sensor_idx], reference_mv_arr[sensor_idx], reference_res_arr[sensor_idx]); + } } ZTEST_USER(thermistor, test_device_nodes_enabled) @@ -312,6 +338,10 @@ static void thermistor_cleanup(void *state) for (sensor_idx = 0; sensor_idx < NAMED_TEMP_SENSORS_SIZE; sensor_idx++) { + /* Skip for sensors that are not thermistors */ + if (temp_sensors[sensor_idx].zephyr_info->thermistor == NULL) + continue; + /* Setup ADC to return 27*C (300K) which is reasonable value */ adc_emul_const_value_set( adc_dev, temp_sensors[sensor_idx].idx, diff --git a/zephyr/test/drivers/prj.conf b/zephyr/test/drivers/prj.conf index 1e6d57fe45..68a13a1f9d 100644 --- a/zephyr/test/drivers/prj.conf +++ b/zephyr/test/drivers/prj.conf @@ -65,6 +65,7 @@ CONFIG_EMUL_PS8XXX=y CONFIG_EMUL_RTC=y CONFIG_EMUL_TCPCI_PARTNER_DRP=y CONFIG_EMUL_TCPCI_PARTNER_FAULTY_EXT=y +CONFIG_EMUL_PCT2075=y CONFIG_PLATFORM_EC_CHARGE_MANAGER=y CONFIG_PLATFORM_EC_CHARGE_RAMP_SW=y CONFIG_PLATFORM_EC_CHARGESPLASH=y @@ -128,6 +129,7 @@ CONFIG_PLATFORM_EC_USB_PD_CLEAR_HARD_RESET_STATUS=y CONFIG_PLATFORM_EC_CONSOLE_CMD_WAITMS=y CONFIG_PLATFORM_EC_POWER_SLEEP_FAILURE_DETECTION=y CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK=y +CONFIG_PLATFORM_EC_TEMP_SENSOR_PCT2075=y CONFIG_ESPI=y CONFIG_ESPI_EMUL=y |