mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-03 13:39:53 +00:00
Add thermal engine test
BUG=chrome-os-partner:19236 TEST=Pass the test. BRANCH=None Change-Id: I1c96437e1fb3492faa5352383f852dc1d2718ace Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/51248 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
@@ -6,9 +6,22 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "gpio.h"
|
||||
#include "temp_sensor.h"
|
||||
|
||||
const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
{"EC_INT", 0, 0, 0, 0},
|
||||
{"LID_OPEN", 0, 0, 0, 0},
|
||||
{"POWER_BUTTON_L", 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static int dummy_temp_get_val(int idx, int *temp_ptr)
|
||||
{
|
||||
*temp_ptr = 0;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = {
|
||||
{"CPU", TEMP_SENSOR_TYPE_CPU, dummy_temp_get_val, 0, 3},
|
||||
{"Board", TEMP_SENSOR_TYPE_BOARD, dummy_temp_get_val, 0, 3},
|
||||
{"Case", TEMP_SENSOR_TYPE_CASE, dummy_temp_get_val, 0, 0},
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define CONFIG_KEYBOARD_PROTOCOL_MKBP
|
||||
#define CONFIG_LID_SWITCH
|
||||
#define CONFIG_POWER_BUTTON
|
||||
#define CONFIG_TEMP_SENSOR
|
||||
|
||||
enum gpio_signal {
|
||||
GPIO_EC_INT,
|
||||
@@ -22,4 +23,12 @@ enum gpio_signal {
|
||||
GPIO_COUNT
|
||||
};
|
||||
|
||||
enum temp_sensor_id {
|
||||
TEMP_SENSOR_CPU = 0,
|
||||
TEMP_SENSOR_BOARD,
|
||||
TEMP_SENSOR_CASE,
|
||||
|
||||
TEMP_SENSOR_COUNT
|
||||
};
|
||||
|
||||
#endif /* __BOARD_H */
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/* Default temperature to report in mapped memory */
|
||||
#define MAPPED_TEMP_DEFAULT (296 - EC_TEMP_SENSOR_OFFSET)
|
||||
|
||||
int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr)
|
||||
test_mockable int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr)
|
||||
{
|
||||
const struct temp_sensor_t *sensor;
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
* temp_sensor_type. Threshold values for overheated action first (warning,
|
||||
* prochot, power-down), followed by fan speed stepping thresholds.
|
||||
*/
|
||||
static struct thermal_config_t thermal_config[TEMP_SENSOR_TYPE_COUNT] = {
|
||||
test_export_static struct thermal_config_t
|
||||
thermal_config[TEMP_SENSOR_TYPE_COUNT] = {
|
||||
/* TEMP_SENSOR_TYPE_CPU */
|
||||
{THERMAL_CONFIG_WARNING_ON_FAIL,
|
||||
{373, 378, 383, 327, 335, 343, 351, 359} } ,
|
||||
@@ -38,8 +39,8 @@ static struct thermal_config_t thermal_config[TEMP_SENSOR_TYPE_COUNT] = {
|
||||
};
|
||||
|
||||
/* Fan speed settings. Real max RPM is about 9300. */
|
||||
static const int fan_speed[THERMAL_FAN_STEPS + 1] = {0, 3000, 4575, 6150,
|
||||
7725, -1};
|
||||
test_export_static const int fan_speed[THERMAL_FAN_STEPS + 1] =
|
||||
{0, 3000, 4575, 6150, 7725, -1};
|
||||
|
||||
/* Number of consecutive overheated events for each temperature sensor. */
|
||||
static int8_t ot_count[TEMP_SENSOR_COUNT][THRESHOLD_COUNT + THERMAL_FAN_STEPS];
|
||||
@@ -159,7 +160,9 @@ static inline void update_and_check_stat(int temp,
|
||||
const int16_t threshold = config->thresholds[threshold_id];
|
||||
const int delay = temp_sensors[sensor_id].action_delay_sec;
|
||||
|
||||
if (threshold > 0 && temp >= threshold) {
|
||||
if (threshold <= 0) {
|
||||
ot_count[sensor_id][threshold_id] = 0;
|
||||
} else if (temp >= threshold) {
|
||||
++ot_count[sensor_id][threshold_id];
|
||||
if (ot_count[sensor_id][threshold_id] >= delay) {
|
||||
ot_count[sensor_id][threshold_id] = delay;
|
||||
@@ -174,8 +177,6 @@ static inline void update_and_check_stat(int temp,
|
||||
* threshold causing overheated actions to trigger repeatedly.
|
||||
*/
|
||||
overheated[threshold_id] = 1;
|
||||
} else {
|
||||
ot_count[sensor_id][threshold_id] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,9 +77,11 @@ enum ec_error_list {
|
||||
#ifdef TEST_BUILD
|
||||
#define test_mockable __attribute__((weak))
|
||||
#define test_mockable_static __attribute__((weak))
|
||||
#define test_export_static
|
||||
#else
|
||||
#define test_mockable
|
||||
#define test_mockable_static static
|
||||
#define test_export_static static
|
||||
#endif
|
||||
|
||||
#endif /* __CROS_EC_COMMON_H */
|
||||
|
||||
@@ -10,7 +10,7 @@ test-list-y=pingpong timer_calib timer_dos timer_jump mutex utils
|
||||
#disable: powerdemo
|
||||
|
||||
# TODO(victoryang): Fix these tests:
|
||||
# thermal scancode typematic charging
|
||||
# scancode typematic charging
|
||||
|
||||
test-list-$(BOARD_bds)+=
|
||||
test-list-$(BOARD_daisy)+=kb_scan flash stress
|
||||
@@ -26,6 +26,7 @@ test-list-$(BOARD_slippy)=
|
||||
|
||||
# Emulator tests
|
||||
test-list-host=mutex pingpong utils kb_scan kb_mkbp lid_sw power_button hooks
|
||||
test-list-host+=thermal
|
||||
|
||||
flash-y=flash.o
|
||||
hooks-y=hooks.o
|
||||
@@ -37,6 +38,8 @@ pingpong-y=pingpong.o
|
||||
power_button-y=power_button.o
|
||||
powerdemo-y=powerdemo.o
|
||||
stress-y=stress.o
|
||||
thermal-y=thermal.o
|
||||
thermal-scale=200
|
||||
timer_calib-y=timer_calib.o
|
||||
timer_dos-y=timer_dos.o
|
||||
utils-y=utils.o
|
||||
|
||||
236
test/thermal.c
Normal file
236
test/thermal.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/* Copyright (c) 2013 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.
|
||||
*
|
||||
* Test thermal engine.
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
#include "temp_sensor.h"
|
||||
#include "test_util.h"
|
||||
#include "thermal.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
static int mock_temp[TEMP_SENSOR_COUNT];
|
||||
static int fan_rpm;
|
||||
static int cpu_throttled;
|
||||
static int cpu_down;
|
||||
|
||||
extern struct thermal_config_t thermal_config[TEMP_SENSOR_TYPE_COUNT];
|
||||
extern const int fan_speed[THERMAL_FAN_STEPS + 1];
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Mock functions */
|
||||
|
||||
int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr)
|
||||
{
|
||||
if (mock_temp[id] >= 0) {
|
||||
*temp_ptr = mock_temp[id];
|
||||
return EC_SUCCESS;
|
||||
} else {
|
||||
return -mock_temp[id];
|
||||
}
|
||||
}
|
||||
|
||||
void pwm_set_fan_rpm_mode(int rpm_mode)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
void pwm_set_fan_target_rpm(int rpm)
|
||||
{
|
||||
fan_rpm = rpm;
|
||||
}
|
||||
|
||||
void chipset_force_shutdown(void)
|
||||
{
|
||||
cpu_down = 1;
|
||||
}
|
||||
|
||||
void chipset_throttle_cpu(int throttled)
|
||||
{
|
||||
cpu_throttled = throttled;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Test utilities */
|
||||
|
||||
/* Test shorthands */
|
||||
#define T_CPU TEMP_SENSOR_CPU
|
||||
#define T_BOARD TEMP_SENSOR_BOARD
|
||||
#define T_CASE TEMP_SENSOR_CASE
|
||||
#define THRESHOLD(x, y) (thermal_config[x].thresholds[y])
|
||||
#define FAN_THRESHOLD(x, y) THRESHOLD(x, THRESHOLD_COUNT + (y))
|
||||
|
||||
static void reset_mock_temp(void)
|
||||
{
|
||||
int i;
|
||||
enum temp_sensor_type type;
|
||||
for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
|
||||
type = temp_sensors[i].type;
|
||||
mock_temp[i] = FAN_THRESHOLD(type, 0) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int wait_fan_rpm(int rpm, int timeout_secs)
|
||||
{
|
||||
do {
|
||||
if (fan_rpm == rpm)
|
||||
return 1;
|
||||
usleep(SECOND);
|
||||
} while (timeout_secs--);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_value(int *v, int target, int timeout_secs)
|
||||
{
|
||||
do {
|
||||
if (*v == target)
|
||||
return 1;
|
||||
usleep(SECOND);
|
||||
} while (timeout_secs--);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_set(int *v, int timeout_secs)
|
||||
{
|
||||
return wait_value(v, 1, timeout_secs);
|
||||
}
|
||||
|
||||
static int wait_clear(int *v, int timeout_secs)
|
||||
{
|
||||
return wait_value(v, 0, timeout_secs);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Tests */
|
||||
|
||||
static int test_init_val(void)
|
||||
{
|
||||
/* Initial mock temperature values are all zero. */
|
||||
TEST_ASSERT(cpu_throttled == 0);
|
||||
TEST_ASSERT(cpu_down == 0);
|
||||
TEST_ASSERT(!(host_get_events() &
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD)));
|
||||
TEST_ASSERT(!(host_get_events() &
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN)));
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_cpu_fan(void)
|
||||
{
|
||||
reset_mock_temp();
|
||||
|
||||
/*
|
||||
* Increase CPU temperature to first fan step and check if
|
||||
* the fan comes up.
|
||||
*/
|
||||
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 0);
|
||||
TEST_ASSERT(wait_fan_rpm(fan_speed[1], 11));
|
||||
|
||||
/* Increase CPU temperature to second fan step */
|
||||
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 1);
|
||||
TEST_ASSERT(wait_fan_rpm(fan_speed[2], 11));
|
||||
|
||||
/* Test threshold hysteresis */
|
||||
mock_temp[T_CPU]--;
|
||||
usleep(15 * SECOND);
|
||||
TEST_ASSERT(fan_rpm == fan_speed[2]);
|
||||
|
||||
/* Test action delay */
|
||||
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 4);
|
||||
usleep((temp_sensors[T_CPU].action_delay_sec - 1) * SECOND);
|
||||
TEST_ASSERT(fan_rpm == fan_speed[2]);
|
||||
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 0);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_safety(void)
|
||||
{
|
||||
reset_mock_temp();
|
||||
|
||||
/* Trigger CPU throttling */
|
||||
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_WARNING);
|
||||
TEST_ASSERT(wait_set(&cpu_throttled, 11));
|
||||
TEST_ASSERT(host_get_events() &
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD));
|
||||
|
||||
/* Lower temperature. CPU not throttled anymore. */
|
||||
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_WARNING) - 5;
|
||||
TEST_ASSERT(wait_clear(&cpu_throttled, 2));
|
||||
|
||||
/* Thermal shutdown */
|
||||
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_CPU_DOWN);
|
||||
TEST_ASSERT(wait_set(&cpu_down, 11));
|
||||
TEST_ASSERT(host_get_events() &
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN));
|
||||
|
||||
mock_temp[T_CPU] = 0;
|
||||
usleep(SECOND);
|
||||
cpu_down = 0;
|
||||
|
||||
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_POWER_DOWN);
|
||||
TEST_ASSERT(wait_set(&cpu_down, 11));
|
||||
TEST_ASSERT(host_get_events() &
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN));
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_sensor_failure(void)
|
||||
{
|
||||
reset_mock_temp();
|
||||
|
||||
/* Failure due to sensor not powered should be ignored */
|
||||
mock_temp[T_CPU] = -EC_ERROR_NOT_POWERED;
|
||||
usleep(2 * SECOND);
|
||||
TEST_ASSERT(!(host_get_events() &
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL)));
|
||||
|
||||
/* Other failure should be pumped up to host */
|
||||
mock_temp[T_CPU] = -EC_ERROR_UNKNOWN;
|
||||
usleep(2 * SECOND);
|
||||
TEST_ASSERT(host_get_events() &
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL));
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int check_assumption(void)
|
||||
{
|
||||
TEST_ASSERT((int)TEMP_SENSOR_CPU == (int)TEMP_SENSOR_TYPE_CPU);
|
||||
TEST_ASSERT((int)TEMP_SENSOR_BOARD == (int)TEMP_SENSOR_TYPE_BOARD);
|
||||
TEST_ASSERT((int)TEMP_SENSOR_CASE == (int)TEMP_SENSOR_TYPE_CASE);
|
||||
|
||||
TEST_ASSERT(temp_sensors[T_CPU].action_delay_sec != 0);
|
||||
|
||||
TEST_ASSERT(thermal_config[T_CPU].config_flags &
|
||||
THERMAL_CONFIG_WARNING_ON_FAIL);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void run_test(void)
|
||||
{
|
||||
test_reset();
|
||||
|
||||
/* Test assumptions */
|
||||
RUN_TEST(check_assumption);
|
||||
|
||||
RUN_TEST(test_init_val);
|
||||
RUN_TEST(test_cpu_fan);
|
||||
/* No tests for board and case temp sensors as they are ignored. */
|
||||
RUN_TEST(test_safety);
|
||||
RUN_TEST(test_sensor_failure);
|
||||
|
||||
test_print_result();
|
||||
}
|
||||
@@ -14,4 +14,5 @@
|
||||
* 'd' in an opaque parameter passed to the routine at startup
|
||||
* 's' is the stack size in bytes; must be a multiple of 8
|
||||
*/
|
||||
#define CONFIG_TEST_TASK_LIST /* No test task */
|
||||
#define CONFIG_TEST_TASK_LIST \
|
||||
TASK_TEST(THERMAL, thermal_task, NULL, TASK_STACK_SIZE)
|
||||
|
||||
Reference in New Issue
Block a user