diff options
Diffstat (limited to 'board/crota/fans.c')
-rw-r--r-- | board/crota/fans.c | 185 |
1 files changed, 141 insertions, 44 deletions
diff --git a/board/crota/fans.c b/board/crota/fans.c index 27f5bca929..17e19dc863 100644 --- a/board/crota/fans.c +++ b/board/crota/fans.c @@ -1,4 +1,4 @@ -/* Copyright 2022 The Chromium OS Authors. All rights reserved. +/* 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. */ @@ -12,6 +12,16 @@ #include "fan.h" #include "hooks.h" #include "pwm.h" +#include "timer.h" +#include "thermal.h" +#include "util.h" + +#define SENSOR_SOC_FAN_OFF 30 +#define SENSOR_SOC_FAN_MID 47 +#define SENSOR_SOC_FAN_MAX 53 +#define SENSOR_DDR_FAN_TURN_OFF 37 +#define SENSOR_DDR_FAN_TURN_ON 38 +#define RECORD_TIME (2 * MINUTE) /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { @@ -25,65 +35,152 @@ BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); static const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; -/* - * TOOD(b/181271666): thermistor placement and calibration - * - * Prototype fan spins at about 4200 RPM at 100% PWM, this - * is specific to board ID 2 and might also apears in later - * boards as well. - */ -static const struct fan_rpm fan_rpm_0 = { - .rpm_min = 2200, - .rpm_start = 2200, - .rpm_max = 4200, +static const struct fan_rpm rpm_table[FAN_RPM_TABLE_COUNT] = { + [RPM_TABLE_CPU0] = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 3700, + }, + + [RPM_TABLE_CPU1] = { + .rpm_min = 3700, + .rpm_start = 3700, + .rpm_max = 4000, + }, + + [RPM_TABLE_DDR] = { + .rpm_min = 4000, + .rpm_start = 4000, + .rpm_max = 4200, + }, + + [RPM_TABLE_CHARGER] = { + .rpm_min = 4000, + .rpm_start = 4000, + .rpm_max = 4200, + }, + + [RPM_TABLE_AMBIENT] = { + .rpm_min = 4000, + .rpm_start = 4000, + .rpm_max = 4200, + }, }; -const struct fan_t fans[FAN_CH_COUNT] = { +struct fan_t fans[FAN_CH_COUNT] = { [FAN_CH_0] = { .conf = &fan_conf_0, - .rpm = &fan_rpm_0, + .rpm = &rpm_table[RPM_TABLE_CPU0], }, }; -#ifndef CONFIG_FANS - -/* - * TODO(b/181271666): use static fan speeds until fan and sensors are - * tuned. for now, use: - * - * AP off: 33% - * AP on: 100% - */ - -static void fan_slow(void) +static void fan_get_rpm(int fan) { - const int duty_pct = 33; - - ccprints("%s: speed %d%%", __func__, duty_pct); + static timestamp_t deadline; - pwm_enable(PWM_CH_FAN, 1); - pwm_set_duty(PWM_CH_FAN, duty_pct); + /* Record actual RPM every 2 minutes. */ + if (timestamp_expired(deadline, NULL)) { + ccprints("fan actual rpm: %d", fan_get_rpm_actual(FAN_CH(fan))); + deadline.val += RECORD_TIME; + } } -static void fan_max(void) +static void fan_set_percent(int fan, int pct) { - const int duty_pct = 100; + int new_rpm; - ccprints("%s: speed %d%%", __func__, duty_pct); - - pwm_enable(PWM_CH_FAN, 1); - pwm_set_duty(PWM_CH_FAN, duty_pct); + new_rpm = fan_percent_to_rpm(fan, pct); + fan_set_rpm_target(FAN_CH(fan), new_rpm); + fan_get_rpm(fan); } -DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); -DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); - -#endif /* CONFIG_FANS */ +void board_override_fan_control(int fan, int *tmp) +{ + /* + * Crota's fan speed is control by four sensors. + * + * Sensor charger control the speed when system's temperature + * is too high. + * Other sensors control normal loading's speed. + * + * When sensor charger is triggered, the fan speed is only + * control by sensor charger, avoid heat damage to system. + * When other sensors is triggered, the fan is control + * by other sensors. + * + * Sensor SOC has two slopes for fan speed. + * Sensor DDR also become a fan on/off switch. + */ + static int pct; + int sensor_soc; + int sensor_ddr; + int sensor_charger; + int sensor_ambient; + + /* Decide sensor SOC temperature using which slope. */ + if (tmp[TEMP_SENSOR_1_SOC] > SENSOR_SOC_FAN_MID) { + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_off = + C_TO_K(SENSOR_SOC_FAN_MID); + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_max = + C_TO_K(SENSOR_SOC_FAN_MAX); + } else { + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_off = + C_TO_K(SENSOR_SOC_FAN_OFF); + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_max = + C_TO_K(SENSOR_SOC_FAN_MID); + } + + sensor_soc = thermal_fan_percent( + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_off, + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_max, + C_TO_K(tmp[TEMP_SENSOR_1_SOC])); + sensor_ddr = thermal_fan_percent( + thermal_params[TEMP_SENSOR_2_DDR].temp_fan_off, + thermal_params[TEMP_SENSOR_2_DDR].temp_fan_max, + C_TO_K(tmp[TEMP_SENSOR_2_DDR])); + sensor_charger = thermal_fan_percent( + thermal_params[TEMP_SENSOR_3_CHARGER].temp_fan_off, + thermal_params[TEMP_SENSOR_3_CHARGER].temp_fan_max, + C_TO_K(tmp[TEMP_SENSOR_3_CHARGER])); + sensor_ambient = thermal_fan_percent( + thermal_params[TEMP_SENSOR_4_AMBIENT].temp_fan_off, + thermal_params[TEMP_SENSOR_4_AMBIENT].temp_fan_max, + C_TO_K(tmp[TEMP_SENSOR_4_AMBIENT])); + + /* + * Sensor DDR turn on when temperature > 38, + * turn off when temperature < 37 + */ + if ((tmp[TEMP_SENSOR_2_DDR]) < SENSOR_DDR_FAN_TURN_OFF) { + pct = 0; + } else if ((tmp[TEMP_SENSOR_2_DDR]) > SENSOR_DDR_FAN_TURN_ON) { + /* + * Decide which sensor was triggered and choose table. + * Priority: charger > soc > ddr > ambient + */ + if (sensor_charger) { + fans[fan].rpm = &rpm_table[RPM_TABLE_CHARGER]; + pct = sensor_charger; + } else if (sensor_soc) { + if (tmp[TEMP_SENSOR_1_SOC] > SENSOR_SOC_FAN_MID) + fans[fan].rpm = &rpm_table[RPM_TABLE_CPU1]; + else + fans[fan].rpm = &rpm_table[RPM_TABLE_CPU0]; + pct = sensor_soc; + } else if (sensor_ddr) { + fans[fan].rpm = &rpm_table[RPM_TABLE_DDR]; + pct = sensor_ddr; + } else { + fans[fan].rpm = &rpm_table[RPM_TABLE_AMBIENT]; + pct = sensor_ambient; + } + } + + /* Transfer percent to rpm. */ + fan_set_percent(fan, pct); +} |