From 94ef5f3ab3dd20ee5558df5607997985b7e2f45c Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Thu, 5 Apr 2012 11:30:16 +0800 Subject: [PATCH] Increase fan speed control to 5 steps. Factor out fan speed control for easier adjusting fan speed stepping. Also increase number of fan speed steps from 2 to 5. Signed-off-by: Vic Yang BUG=chrome-os-partner:8466 TEST=Manual test. Change-Id: I0ff601c0a4f2ed2a4867bdc6e550eb2827404754 --- common/thermal.c | 110 +++++++++++++++++++++++++++++++++++----------- include/thermal.h | 12 ++--- 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/common/thermal.c b/common/thermal.c index d7fbcc76f8..f2e53c55b5 100644 --- a/common/thermal.c +++ b/common/thermal.c @@ -25,31 +25,42 @@ extern const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT]; /* Temperature threshold configuration. Must be in the same order as in - * enum temp_sensor_type. */ + * enum temp_sensor_type. Threshold values for overheated action first. + * Followed by fan speed stepping thresholds. */ struct thermal_config_t thermal_config[TEMP_SENSOR_TYPE_COUNT] = { /* TEMP_SENSOR_TYPE_CPU */ - {THERMAL_CONFIG_WARNING_ON_FAIL, {328, 338, 343, 348, 353}}, + {THERMAL_CONFIG_WARNING_ON_FAIL, + {343, 348, 353, 318, 323, 328, 333, 338}}, /* TEMP_SENSOR_TYPE_BOARD */ {THERMAL_CONFIG_NO_FLAG, {THERMAL_THRESHOLD_DISABLE_ALL}}, /* TEMP_SENSOR_TYPE_CASE */ - {THERMAL_CONFIG_NO_FLAG, {THERMAL_THRESHOLD_DISABLE, - THERMAL_THRESHOLD_DISABLE, 343, THERMAL_THRESHOLD_DISABLE, 358}}, + {THERMAL_CONFIG_NO_FLAG, {343, THERMAL_THRESHOLD_DISABLE, 358, + THERMAL_THRESHOLD_DISABLE_ALL}}, }; +/* Fan speed settings. */ +/* TODO: Currently temperature polling task sometimes hangs. So we should not + * turn off fan according to temperature readings. Modify this to turn off fan + * when we have reliable temperature readings. See crosbug.com/p/8479 + */ +const int fan_speed[THERMAL_FAN_STEPS + 1] = {4000, 5000, 6000, 7000, 8000, -1}; + /* Number of consecutive overheated events for each temperature sensor. */ -static int8_t ot_count[TEMP_SENSOR_COUNT][THRESHOLD_COUNT]; +static int8_t ot_count[TEMP_SENSOR_COUNT][THRESHOLD_COUNT + THERMAL_FAN_STEPS]; /* Flag that indicate if each threshold is reached. * Note that higher threshold reached does not necessarily mean lower thresholds * are reached (since we can disable any threshold.) */ -static int8_t overheated[THRESHOLD_COUNT]; +static int8_t overheated[THRESHOLD_COUNT + THERMAL_FAN_STEPS]; +static int8_t *fan_threshold_reached = overheated + THRESHOLD_COUNT; static int fan_ctrl_on = 1; int thermal_set_threshold(enum temp_sensor_type type, int threshold_id, int value) { - if (threshold_id < 0 || threshold_id >= THRESHOLD_COUNT) + if (threshold_id < 0 || + threshold_id >= THRESHOLD_COUNT + THERMAL_FAN_STEPS) return EC_ERROR_INVAL; if (value < 0) return EC_ERROR_INVAL; @@ -62,7 +73,8 @@ int thermal_set_threshold(enum temp_sensor_type type, int threshold_id, int valu int thermal_get_threshold(enum temp_sensor_type type, int threshold_id) { - if (threshold_id < 0 || threshold_id >= THRESHOLD_COUNT) + if (threshold_id < 0 || + threshold_id >= THRESHOLD_COUNT + THERMAL_FAN_STEPS) return EC_ERROR_INVAL; return thermal_config[type].thresholds[threshold_id]; @@ -106,18 +118,11 @@ static void overheated_action(void) } if (fan_ctrl_on) { - if (overheated[THRESHOLD_FAN_HI]) - pwm_set_fan_target_rpm(-1); /* Max RPM. */ - else if (overheated[THRESHOLD_FAN_LO]) - pwm_set_fan_target_rpm(6000); - else - /* TODO: Currently temperature polling task sometimes - * hangs. So we should not turn off fan according to - * temperature readings. Modify this to turn off fan - * when we have reliable temperature readings. - * See crosbug.com/p/8479 - */ - pwm_set_fan_target_rpm(4000); + int i; + for (i = THERMAL_FAN_STEPS - 1; i >= 0; --i) + if (fan_threshold_reached[i]) + break; + pwm_set_fan_target_rpm(fan_speed[i + 1]); } } @@ -158,7 +163,7 @@ static void thermal_process(void) int i, j; int cur_temp; - for (i = 0; i < THRESHOLD_COUNT; ++i) + for (i = 0; i < THRESHOLD_COUNT + THERMAL_FAN_STEPS; ++i) overheated[i] = 0; for (i = 0; i < TEMP_SENSOR_COUNT; ++i) { @@ -176,7 +181,7 @@ static void thermal_process(void) smi_sensor_failure_warning(); continue; } - for (j = 0; j < THRESHOLD_COUNT; ++j) + for (j = 0; j < THRESHOLD_COUNT + THERMAL_FAN_STEPS; ++j) update_and_check_stat(cur_temp, i, j); } @@ -200,10 +205,6 @@ static void print_thermal_config(enum temp_sensor_type type) { const struct thermal_config_t *config = thermal_config + type; uart_printf("Sensor Type %d:\n", type); - uart_printf("\tFan Low: %d K \n", - config->thresholds[THRESHOLD_FAN_LO]); - uart_printf("\tFan High: %d K \n", - config->thresholds[THRESHOLD_FAN_HI]); uart_printf("\tWarning: %d K \n", config->thresholds[THRESHOLD_WARNING]); uart_printf("\tCPU Down: %d K \n", @@ -213,6 +214,20 @@ static void print_thermal_config(enum temp_sensor_type type) } +static void print_fan_stepping(enum temp_sensor_type type) +{ + const struct thermal_config_t *config = thermal_config + type; + int i; + + uart_printf("Sensor Type %d:\n", type); + uart_printf("\tLowest speed: %d RPM\n", fan_speed[0]); + for (i = 0; i < THERMAL_FAN_STEPS; ++i) + uart_printf("\t%3d K: %d RPM\n", + config->thresholds[THRESHOLD_COUNT + i], + fan_speed[i+1]); +} + + static int command_thermal_config(int argc, char **argv) { char *e; @@ -256,6 +271,49 @@ static int command_thermal_config(int argc, char **argv) DECLARE_CONSOLE_COMMAND(thermal, command_thermal_config); +static int command_fan_config(int argc, char **argv) +{ + char *e; + int sensor_type, stepping_id, value; + + if (argc != 2 && argc != 4) { + uart_puts("Usage: thermalfan [ ]\n"); + return EC_ERROR_UNKNOWN; + } + + sensor_type = strtoi(argv[1], &e, 0); + if ((e && *e) || sensor_type < 0 || + sensor_type >= TEMP_SENSOR_TYPE_COUNT) { + uart_puts("Bad sensor type ID.\n"); + return EC_ERROR_UNKNOWN; + } + + if (argc == 2) { + print_fan_stepping(sensor_type); + return EC_SUCCESS; + } + + stepping_id = strtoi(argv[2], &e, 0); + if ((e && *e) || stepping_id < 0 || stepping_id >= THERMAL_FAN_STEPS) { + uart_puts("Bad stepping ID.\n"); + return EC_ERROR_UNKNOWN; + } + + value = strtoi(argv[3], &e, 0); + if ((e && *e) || value < 0) { + uart_puts("Bad threshold value.\n"); + return EC_ERROR_UNKNOWN; + } + + thermal_config[sensor_type].thresholds[THRESHOLD_COUNT + stepping_id] = value; + uart_printf("Setting fan step %d of sensor type %d to %d K\n", + stepping_id, sensor_type, value); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(thermalfan, command_fan_config); + + static int command_thermal_auto_fan_ctrl(int argc, char **argv) { return thermal_toggle_auto_fan_ctrl(1); diff --git a/include/thermal.h b/include/thermal.h index ab606baaa8..6259504c01 100644 --- a/include/thermal.h +++ b/include/thermal.h @@ -14,6 +14,10 @@ #define THERMAL_CONFIG_NO_FLAG 0x0 #define THERMAL_CONFIG_WARNING_ON_FAIL 0x1 +/* Number of steps for fan speed control. Speed of each step defined + * in thermal.c */ +#define THERMAL_FAN_STEPS 5 + /* Set a threshold temperature to this value to disable the threshold limit. */ #define THERMAL_THRESHOLD_DISABLE 0 @@ -24,12 +28,8 @@ #define THERMAL_THRESHOLD_DISABLE_ALL 0 enum thermal_threshold { - /* Low fan speed */ - THRESHOLD_FAN_LO = 0, - /* High fan speed */ - THRESHOLD_FAN_HI, /* Issue overheating warning */ - THRESHOLD_WARNING, + THRESHOLD_WARNING = 0, /* Shut down CPU */ THRESHOLD_CPU_DOWN, /* Shut down everything we can */ @@ -43,7 +43,7 @@ struct thermal_config_t { /* Configuration flags. */ int8_t config_flags; /* Threshold temperatures. */ - int16_t thresholds[THRESHOLD_COUNT]; + int16_t thresholds[THRESHOLD_COUNT + THERMAL_FAN_STEPS]; }; /* Set the threshold temperature value. Return -1 on error. */