mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-02 13:14:51 +00:00
separate dptf logic from existing thermal logic.
Signed-off-by: Ravi Chandra Sadineni <ravisadineni@chromium.org> BRANCH=none BUG=chromium:631848 TEST=make buildall -j Change-Id: I718a29b067d37af477306f9bebfcb8e71d84d4ee Reviewed-on: https://chromium-review.googlesource.com/363008 Commit-Ready: David Hendricks <dhendrix@chromium.org> Tested-by: David Hendricks <dhendrix@chromium.org> Reviewed-by: David Hendricks <dhendrix@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Duncan Laurie <dlaurie@google.com>
This commit is contained in:
committed by
chrome-bot
parent
bcb0de22a4
commit
78a875eadb
@@ -29,7 +29,7 @@ static int __bss_slow acpi_data_count;
|
||||
/* Test byte in ACPI memory space */
|
||||
static uint8_t __bss_slow acpi_mem_test;
|
||||
|
||||
#ifdef CONFIG_TEMP_SENSOR
|
||||
#ifdef CONFIG_DPTF
|
||||
static int __bss_slow dptf_temp_sensor_id; /* last sensor ID written */
|
||||
static int __bss_slow dptf_temp_threshold; /* last threshold written */
|
||||
#endif
|
||||
@@ -153,7 +153,7 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
|
||||
result = dptf_get_fan_duty_target();
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_TEMP_SENSOR
|
||||
#ifdef CONFIG_DPTF
|
||||
case EC_ACPI_MEM_TEMP_ID:
|
||||
result = dptf_query_next_sensor_event();
|
||||
break;
|
||||
@@ -198,7 +198,7 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
|
||||
dptf_set_fan_duty_target(data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_TEMP_SENSOR
|
||||
#ifdef CONFIG_DPTF
|
||||
case EC_ACPI_MEM_TEMP_ID:
|
||||
dptf_temp_sensor_id = data;
|
||||
break;
|
||||
|
||||
@@ -40,6 +40,7 @@ common-$(CONFIG_COMMON_RUNTIME)+=hooks.o main.o system.o shared_mem.o
|
||||
common-$(CONFIG_COMMON_TIMER)+=timer.o
|
||||
common-$(CONFIG_CRC8)+= crc8.o
|
||||
common-$(CONFIG_DEVICE_STATE)+=device_state.o
|
||||
common-$(CONFIG_DPTF)+=dptf.o
|
||||
common-$(CONFIG_EXTENSION_COMMAND)+=extension.o
|
||||
common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o
|
||||
common-$(CONFIG_FANS)+=fan.o pwm.o
|
||||
|
||||
188
common/dptf.c
Normal file
188
common/dptf.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#include "atomic.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "dptf.h"
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
#include "temp_sensor.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Console output macros */
|
||||
#define CPUTS(outstr) cputs(CC_DPTF, outstr)
|
||||
#define CPRINTS(format, args...) cprints(CC_DPTF, format, ## args)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* DPTF temperature thresholds */
|
||||
|
||||
static struct {
|
||||
int temp; /* degrees K, negative for disabled */
|
||||
cond_t over; /* watch for crossings */
|
||||
} dptf_threshold[TEMP_SENSOR_COUNT][DPTF_THRESHOLDS_PER_SENSOR];
|
||||
|
||||
static void dptf_init(void)
|
||||
{
|
||||
int id, t;
|
||||
|
||||
for (id = 0; id < TEMP_SENSOR_COUNT; id++)
|
||||
for (t = 0; t < DPTF_THRESHOLDS_PER_SENSOR; t++) {
|
||||
dptf_threshold[id][t].temp = -1;
|
||||
cond_init(&dptf_threshold[id][t].over, 0);
|
||||
}
|
||||
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, dptf_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
/* Keep track of which triggered sensor thresholds the AP has seen */
|
||||
static uint32_t dptf_seen;
|
||||
|
||||
int dptf_query_next_sensor_event(void)
|
||||
{
|
||||
int id;
|
||||
|
||||
for (id = 0; id < TEMP_SENSOR_COUNT; id++)
|
||||
if (dptf_seen & (1 << id)) { /* atomic? */
|
||||
atomic_clear(&dptf_seen, (1 << id));
|
||||
return id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return true if any threshold transition occurs. */
|
||||
static int dpft_check_temp_threshold(int sensor_id, int temp)
|
||||
{
|
||||
int tripped = 0;
|
||||
int max, i;
|
||||
|
||||
for (i = 0; i < DPTF_THRESHOLDS_PER_SENSOR; i++) {
|
||||
|
||||
max = dptf_threshold[sensor_id][i].temp;
|
||||
if (max < 0) /* disabled? */
|
||||
continue;
|
||||
|
||||
if (temp >= max)
|
||||
cond_set_true(&dptf_threshold[sensor_id][i].over);
|
||||
else if (temp <= max - DPTF_THRESHOLD_HYSTERESIS)
|
||||
cond_set_false(&dptf_threshold[sensor_id][i].over);
|
||||
|
||||
if (cond_went_true(&dptf_threshold[sensor_id][i].over)) {
|
||||
CPRINTS("DPTF over threshold [%d][%d",
|
||||
sensor_id, i);
|
||||
atomic_or(&dptf_seen, (1 << sensor_id));
|
||||
tripped = 1;
|
||||
}
|
||||
if (cond_went_false(&dptf_threshold[sensor_id][i].over)) {
|
||||
CPRINTS("DPTF under threshold [%d][%d",
|
||||
sensor_id, i);
|
||||
atomic_or(&dptf_seen, (1 << sensor_id));
|
||||
tripped = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return tripped;
|
||||
}
|
||||
|
||||
void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable)
|
||||
{
|
||||
CPRINTS("DPTF sensor %d, threshold %d C, index %d, %sabled",
|
||||
sensor_id, K_TO_C(temp), idx, enable ? "en" : "dis");
|
||||
|
||||
if (enable) {
|
||||
/* Don't update threshold condition if already enabled */
|
||||
if (dptf_threshold[sensor_id][idx].temp == -1)
|
||||
cond_init(&dptf_threshold[sensor_id][idx].over, 0);
|
||||
dptf_threshold[sensor_id][idx].temp = temp;
|
||||
atomic_clear(&dptf_seen, (1 << sensor_id));
|
||||
} else {
|
||||
dptf_threshold[sensor_id][idx].temp = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* EC-specific thermal controls */
|
||||
|
||||
test_mockable_static void smi_sensor_failure_warning(void)
|
||||
{
|
||||
CPRINTS("can't read any temp sensors!");
|
||||
host_set_single_event(EC_HOST_EVENT_THERMAL);
|
||||
}
|
||||
|
||||
static void thermal_control_dptf(void)
|
||||
{
|
||||
int i, t, rv;
|
||||
int dptf_tripped;
|
||||
int num_sensors_read;
|
||||
|
||||
dptf_tripped = 0;
|
||||
num_sensors_read = 0;
|
||||
|
||||
/* go through all the sensors */
|
||||
for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
|
||||
rv = temp_sensor_read(i, &t);
|
||||
if (rv != EC_SUCCESS)
|
||||
continue;
|
||||
else
|
||||
num_sensors_read++;
|
||||
/* and check the dptf thresholds */
|
||||
dptf_tripped |= dpft_check_temp_threshold(i, t);
|
||||
}
|
||||
|
||||
if (!num_sensors_read) {
|
||||
/*
|
||||
* Trigger a SMI event if we can't read any sensors.
|
||||
*
|
||||
* In theory we could do something more elaborate like forcing
|
||||
* the system to shut down if no sensors are available after
|
||||
* several retries. This is a very unlikely scenario -
|
||||
* particularly on LM4-based boards, since the LM4 has its own
|
||||
* internal temp sensor. It's most likely to occur during
|
||||
* bringup of a new board, where we haven't debugged the I2C
|
||||
* bus to the sensors; forcing a shutdown in that case would
|
||||
* merely hamper board bringup.
|
||||
*/
|
||||
smi_sensor_failure_warning();
|
||||
}
|
||||
|
||||
/* Don't forget to signal any DPTF thresholds */
|
||||
if (dptf_tripped)
|
||||
host_set_single_event(EC_HOST_EVENT_THERMAL_THRESHOLD);
|
||||
}
|
||||
|
||||
/* Wait until after the sensors have been read */
|
||||
DECLARE_HOOK(HOOK_SECOND, thermal_control_dptf, HOOK_PRIO_TEMP_SENSOR_DONE);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Console commands */
|
||||
|
||||
static int command_dptftemp(int argc, char **argv)
|
||||
{
|
||||
int id, t;
|
||||
int temp, trig;
|
||||
|
||||
ccprintf("sensor thresh0 thresh1\n");
|
||||
for (id = 0; id < TEMP_SENSOR_COUNT; id++) {
|
||||
ccprintf(" %2d", id);
|
||||
for (t = 0; t < DPTF_THRESHOLDS_PER_SENSOR; t++) {
|
||||
temp = dptf_threshold[id][t].temp;
|
||||
trig = cond_is_true(&dptf_threshold[id][t].over);
|
||||
if (temp < 0)
|
||||
ccprintf(" --- ");
|
||||
else
|
||||
ccprintf(" %3d%c", temp,
|
||||
trig ? '*' : ' ');
|
||||
}
|
||||
ccprintf(" %s\n", temp_sensors[id].name);
|
||||
}
|
||||
|
||||
ccprintf("AP seen mask: 0x%08x\n", dptf_seen);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(dptftemp, command_dptftemp,
|
||||
NULL,
|
||||
"Print DPTF thermal parameters (degrees Kelvin)",
|
||||
NULL);
|
||||
@@ -111,6 +111,7 @@ static int command_temps(int argc, char **argv)
|
||||
switch (rv) {
|
||||
case EC_SUCCESS:
|
||||
ccprintf("%d K = %d C", t, K_TO_C(t));
|
||||
#ifdef CONFIG_THROTTLE_AP
|
||||
if (thermal_params[i].temp_fan_off &&
|
||||
thermal_params[i].temp_fan_max)
|
||||
ccprintf(" %d%%",
|
||||
@@ -118,6 +119,7 @@ static int command_temps(int argc, char **argv)
|
||||
thermal_params[i].temp_fan_off,
|
||||
thermal_params[i].temp_fan_max,
|
||||
t));
|
||||
#endif
|
||||
ccprintf("\n");
|
||||
break;
|
||||
case EC_ERROR_NOT_POWERED:
|
||||
|
||||
129
common/thermal.c
129
common/thermal.c
@@ -7,11 +7,9 @@
|
||||
* implementation from the original version that shipped on Link.
|
||||
*/
|
||||
|
||||
#include "atomic.h"
|
||||
#include "chipset.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "dptf.h"
|
||||
#include "fan.h"
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
@@ -25,93 +23,6 @@
|
||||
#define CPUTS(outstr) cputs(CC_THERMAL, outstr)
|
||||
#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* DPTF temperature thresholds */
|
||||
|
||||
static struct {
|
||||
int temp; /* degrees K, negative for disabled */
|
||||
cond_t over; /* watch for crossings */
|
||||
} dptf_threshold[TEMP_SENSOR_COUNT][DPTF_THRESHOLDS_PER_SENSOR];
|
||||
|
||||
static void dptf_init(void)
|
||||
{
|
||||
int id, t;
|
||||
|
||||
for (id = 0; id < TEMP_SENSOR_COUNT; id++)
|
||||
for (t = 0; t < DPTF_THRESHOLDS_PER_SENSOR; t++) {
|
||||
dptf_threshold[id][t].temp = -1;
|
||||
cond_init(&dptf_threshold[id][t].over, 0);
|
||||
}
|
||||
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, dptf_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
/* Keep track of which triggered sensor thresholds the AP has seen */
|
||||
static uint32_t dptf_seen;
|
||||
|
||||
int dptf_query_next_sensor_event(void)
|
||||
{
|
||||
int id;
|
||||
|
||||
for (id = 0; id < TEMP_SENSOR_COUNT; id++)
|
||||
if (dptf_seen & (1 << id)) { /* atomic? */
|
||||
atomic_clear(&dptf_seen, (1 << id));
|
||||
return id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return true if any threshold transition occurs. */
|
||||
static int dpft_check_temp_threshold(int sensor_id, int temp)
|
||||
{
|
||||
int tripped = 0;
|
||||
int max, i;
|
||||
|
||||
for (i = 0; i < DPTF_THRESHOLDS_PER_SENSOR; i++) {
|
||||
|
||||
max = dptf_threshold[sensor_id][i].temp;
|
||||
if (max < 0) /* disabled? */
|
||||
continue;
|
||||
|
||||
if (temp >= max)
|
||||
cond_set_true(&dptf_threshold[sensor_id][i].over);
|
||||
else if (temp <= max - DPTF_THRESHOLD_HYSTERESIS)
|
||||
cond_set_false(&dptf_threshold[sensor_id][i].over);
|
||||
|
||||
if (cond_went_true(&dptf_threshold[sensor_id][i].over)) {
|
||||
CPRINTS("DPTF over threshold [%d][%d",
|
||||
sensor_id, i);
|
||||
atomic_or(&dptf_seen, (1 << sensor_id));
|
||||
tripped = 1;
|
||||
}
|
||||
if (cond_went_false(&dptf_threshold[sensor_id][i].over)) {
|
||||
CPRINTS("DPTF under threshold [%d][%d",
|
||||
sensor_id, i);
|
||||
atomic_or(&dptf_seen, (1 << sensor_id));
|
||||
tripped = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return tripped;
|
||||
}
|
||||
|
||||
void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable)
|
||||
{
|
||||
CPRINTS("DPTF sensor %d, threshold %d C, index %d, %sabled",
|
||||
sensor_id, K_TO_C(temp), idx, enable ? "en" : "dis");
|
||||
|
||||
if (enable) {
|
||||
/* Don't update threshold condition if already enabled */
|
||||
if (dptf_threshold[sensor_id][idx].temp == -1)
|
||||
cond_init(&dptf_threshold[sensor_id][idx].over, 0);
|
||||
dptf_threshold[sensor_id][idx].temp = temp;
|
||||
atomic_clear(&dptf_seen, (1 << sensor_id));
|
||||
} else {
|
||||
dptf_threshold[sensor_id][idx].temp = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* EC-specific thermal controls */
|
||||
|
||||
@@ -146,7 +57,6 @@ static void thermal_control(void)
|
||||
int num_valid_limits[EC_TEMP_THRESH_COUNT];
|
||||
int num_sensors_read;
|
||||
int fmax;
|
||||
int dptf_tripped;
|
||||
int temp_fan_configured;
|
||||
|
||||
/* Get ready to count things */
|
||||
@@ -155,7 +65,6 @@ static void thermal_control(void)
|
||||
memset(num_valid_limits, 0, sizeof(num_valid_limits));
|
||||
num_sensors_read = 0;
|
||||
fmax = 0;
|
||||
dptf_tripped = 0;
|
||||
temp_fan_configured = 0;
|
||||
|
||||
/* go through all the sensors */
|
||||
@@ -191,9 +100,6 @@ static void thermal_control(void)
|
||||
|
||||
temp_fan_configured = 1;
|
||||
}
|
||||
|
||||
/* and check the dptf thresholds */
|
||||
dptf_tripped |= dpft_check_temp_threshold(i, t);
|
||||
}
|
||||
|
||||
if (!num_sensors_read) {
|
||||
@@ -266,10 +172,6 @@ static void thermal_control(void)
|
||||
fan_set_percent_needed(i, fmax);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Don't forget to signal any DPTF thresholds */
|
||||
if (dptf_tripped)
|
||||
host_set_single_event(EC_HOST_EVENT_THERMAL_THRESHOLD);
|
||||
}
|
||||
|
||||
/* Wait until after the sensors have been read */
|
||||
@@ -349,36 +251,6 @@ DECLARE_CONSOLE_COMMAND(thermalset, command_thermalset,
|
||||
" Use -1 to skip.",
|
||||
NULL);
|
||||
|
||||
|
||||
static int command_dptftemp(int argc, char **argv)
|
||||
{
|
||||
int id, t;
|
||||
int temp, trig;
|
||||
|
||||
ccprintf("sensor thresh0 thresh1\n");
|
||||
for (id = 0; id < TEMP_SENSOR_COUNT; id++) {
|
||||
ccprintf(" %2d", id);
|
||||
for (t = 0; t < DPTF_THRESHOLDS_PER_SENSOR; t++) {
|
||||
temp = dptf_threshold[id][t].temp;
|
||||
trig = cond_is_true(&dptf_threshold[id][t].over);
|
||||
if (temp < 0)
|
||||
ccprintf(" --- ");
|
||||
else
|
||||
ccprintf(" %3d%c", temp,
|
||||
trig ? '*' : ' ');
|
||||
}
|
||||
ccprintf(" %s\n", temp_sensors[id].name);
|
||||
}
|
||||
|
||||
ccprintf("AP seen mask: 0x%08x\n", dptf_seen);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(dptftemp, command_dptftemp,
|
||||
NULL,
|
||||
"Print DPTF thermal parameters (degrees Kelvin)",
|
||||
NULL);
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Host commands. We'll reuse the host command number, but this is version 1,
|
||||
* not version 0. Different structs, different meanings.
|
||||
@@ -414,4 +286,3 @@ static int thermal_command_get_threshold(struct host_cmd_handler_args *args)
|
||||
DECLARE_HOST_COMMAND(EC_CMD_THERMAL_GET_THRESHOLD,
|
||||
thermal_command_get_threshold,
|
||||
EC_VER_MASK(1));
|
||||
|
||||
|
||||
@@ -1768,6 +1768,13 @@
|
||||
|
||||
/* Compile common code for throttling the CPU based on the temp sensors */
|
||||
#undef CONFIG_THROTTLE_AP
|
||||
/*
|
||||
* If defined, dptf is enabled to manage thermals.
|
||||
*
|
||||
* NOTE: This doesn't mean that thermal control is completely taken care by
|
||||
* DPTF. We have some hybrid solutions where the EC still manages the fans.
|
||||
*/
|
||||
#undef CONFIG_DPTF
|
||||
|
||||
/*****************************************************************************/
|
||||
/* TPM-like configuration */
|
||||
@@ -2245,6 +2252,16 @@
|
||||
#define CONFIG_TEMP_SENSOR
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* DPTF must have temperature sensor enabled to get the readings for
|
||||
* generating DPTF thresholds events.
|
||||
*/
|
||||
#if defined(CONFIG_DPTF) && !defined(CONFIG_TEMP_SENSOR)
|
||||
#define CONFIG_TEMP_SENSOR
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* The Matrix Keyboard Protocol depends on MKBP events. */
|
||||
#ifdef CONFIG_KEYBOARD_PROTOCOL_MKBP
|
||||
|
||||
@@ -60,6 +60,9 @@ CONSOLE_CHANNEL(CC_SWITCH, "switch")
|
||||
#endif
|
||||
CONSOLE_CHANNEL(CC_SYSTEM, "system")
|
||||
CONSOLE_CHANNEL(CC_TASK, "task")
|
||||
#ifdef CONFIG_DPTF
|
||||
CONSOLE_CHANNEL(CC_DPTF, "dptf")
|
||||
#endif
|
||||
CONSOLE_CHANNEL(CC_THERMAL, "thermal")
|
||||
CONSOLE_CHANNEL(CC_TPM, "tpm")
|
||||
CONSOLE_CHANNEL(CC_USB, "usb")
|
||||
|
||||
Reference in New Issue
Block a user