summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDawid Niedzwiecki <dawidn@google.com>2022-11-10 08:37:19 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-11-14 16:22:41 +0000
commit5cf490d59c3d0a2ab0ac82b963888de4035a68ef (patch)
tree0b747f6efe460f26768d13b886ae76aabc206152
parent8260703ba889dfde312eaf0eca8f48c9d4273440 (diff)
downloadchrome-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.h1
-rw-r--r--zephyr/emul/CMakeLists.txt1
-rw-r--r--zephyr/emul/Kconfig7
-rw-r--r--zephyr/emul/emul_pct2075.c107
-rw-r--r--zephyr/include/emul/emul_pct2075.h31
-rw-r--r--zephyr/shim/src/temp_sensors.c2
-rw-r--r--zephyr/test/drivers/boards/native_posix.overlay10
-rw-r--r--zephyr/test/drivers/default/src/temp_sensor.c93
-rw-r--r--zephyr/test/drivers/default/src/thermistor.c32
-rw-r--r--zephyr/test/drivers/prj.conf2
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