diff options
author | Ravi Chandra Sadineni <ravisadineni@chromium.org> | 2016-07-25 18:06:29 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-07-30 01:24:52 -0700 |
commit | 78a875eadb1016d757883c7ae5f166201b2ab8de (patch) | |
tree | ac77d701e2ce83c09d898932a5915a58b43ce30b /common/dptf.c | |
parent | bcb0de22a429eacb2e3f588cd93294b9bccea2bc (diff) | |
download | chrome-ec-78a875eadb1016d757883c7ae5f166201b2ab8de.tar.gz |
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>
Diffstat (limited to 'common/dptf.c')
-rw-r--r-- | common/dptf.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/common/dptf.c b/common/dptf.c new file mode 100644 index 0000000000..638427c3b3 --- /dev/null +++ b/common/dptf.c @@ -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); |