summaryrefslogtreecommitdiff
path: root/common/dptf.c
diff options
context:
space:
mode:
authorRavi Chandra Sadineni <ravisadineni@chromium.org>2016-07-25 18:06:29 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-07-30 01:24:52 -0700
commit78a875eadb1016d757883c7ae5f166201b2ab8de (patch)
treeac77d701e2ce83c09d898932a5915a58b43ce30b /common/dptf.c
parentbcb0de22a429eacb2e3f588cd93294b9bccea2bc (diff)
downloadchrome-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.c188
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);