summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2013-12-12 16:34:22 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-12-13 20:19:05 +0000
commitcddf8a545cd2531ff8cde897a90939cdc8e82e0b (patch)
treeb35789c8655c09fe8637e683addf618cc13c9627
parentd4ce7fd5f4d6eb13623b6d962bec56546a2f3502 (diff)
downloadchrome-ec-cddf8a545cd2531ff8cde897a90939cdc8e82e0b.tar.gz
Implement DPTF thermal thresholds
Any of the EC's temp sensors can have up to two independent thresholds attached to them. When the temperature crosses the threshold (rising or falling), a EC_HOST_EVENT_THERMAL_THRESHOLD event is sent to the AP. It's up to the AP to read the sensor values and figure out why the event was sent. The thresholds are set and enabled with ACPI writes to three registers in the EC interface space: EC_ACPI_MEM_TEMP_ID, EC_ACPI_MEM_TEMP_THRESHOLD, and EC_ACPI_MEM_TEMP_COMMIT. Refer to the comments in ec_commands.h for details on their use. ACPI does not provide any means to read the threshold settings (the AP will just have to remember), but there is an EC console command "dptftemp", that can be used to examine the current settings. BUG=chrome-os-partner:23970 BRANCH=none TEST=manual On the EC console, check the current threshold settings and temperatures: > dptftemp sensor thresh0 thresh1 0 --- --- PECI 1 --- --- ECInternal 2 --- --- I2C-Charger-Die 3 --- --- I2C-Charger-Object 4 --- --- I2C-CPU-Die 5 --- --- I2C-CPU-Object 6 --- --- I2C-Left C-Die 7 --- --- I2C-Left C-Object 8 --- --- I2C-Right C-Die 9 --- --- I2C-Right C-Object 10 --- --- I2C-Right D-Die 11 --- --- I2C-Right D-Object 12 --- --- I2C-Left D-Die 13 --- --- I2C-Left D-Object > > temps PECI : 318 K = 45 C ECInternal : 306 K = 33 C I2C-Charger-Die : 309 K = 36 C I2C-Charger-Object : Not calibrated I2C-CPU-Die : 309 K = 36 C I2C-CPU-Object : Not calibrated I2C-Left C-Die : 306 K = 33 C I2C-Left C-Object : Not calibrated I2C-Right C-Die : 307 K = 34 C I2C-Right C-Object : Not calibrated I2C-Right D-Die : 307 K = 34 C I2C-Right D-Object : Not calibrated I2C-Left D-Die : 306 K = 33 C I2C-Left D-Object : Not calibrated > In this case, the PECI temp is 318 K, so let's set a threshold at 322 K. On the AP: [ "$#" -eq "2" ] || return; iotools io_write8 0x66 0x81 iotools io_write8 0x62 $1 iotools io_write8 0x62 $2 } Back on the EC console, we see that the threshold has been set: [768.176648 DPTF sensor 0, threshold 49 C, index 1, enabled] > dptftemp sensor thresh0 thresh1 0 --- 322 PECI 1 --- --- ECInternal 2 --- --- I2C-Charger-Die ... Now do something on the AP to increase the temperature (webgl aquarium, etc). When the temp goes above 322 K, the EC console reports it and sends a host event, and the "dptftemp" command indicates the over-temp condition: [815.367442 DPTF over threshold [0][1] [815.367878 event set 0x00000100] [815.368069 sci 0x00000100] [815.368619 event clear 0x00000100] > dptftemp sensor thresh0 thresh1 0 --- 322* PECI 1 --- --- ECInternal 2 --- --- I2C-Charger-Die ... Log out and wait for the temp to drop. You'll see that trigger a host event as well: [854.375713 DPTF under threshold [0][1] [854.376147 event set 0x00000100] [[854.376396 event clear 0x00000100] > dptftemp sensor thresh0 thresh1 0 --- 322 PECI 1 --- --- ECInternal 2 --- --- I2C-Charger-Die ... Change-Id: I6bb34c615f37477ccf37163caaa94737baed8dae Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/179962 Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/lm4/lpc.c1
-rw-r--r--common/thermal.c102
-rw-r--r--include/dptf.h6
3 files changed, 106 insertions, 3 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index f8fd54e55f..f77dd363ed 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -9,7 +9,6 @@
#include "clock.h"
#include "common.h"
#include "console.h"
-#include "dptf.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
diff --git a/common/thermal.c b/common/thermal.c
index 873a8a1981..6464ef7161 100644
--- a/common/thermal.c
+++ b/common/thermal.c
@@ -10,6 +10,7 @@
#include "chipset.h"
#include "common.h"
#include "console.h"
+#include "dptf.h"
#include "fan.h"
#include "hooks.h"
#include "host_command.h"
@@ -26,13 +27,77 @@
/*****************************************************************************/
/* 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);
+
+
+
+
+/* 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)) {
+ CPRINTF("[%T DPTF over threshold [%d][%d]\n",
+ sensor_id, i);
+ tripped = 1;
+ }
+ if (cond_went_false(&dptf_threshold[sensor_id][i].over)) {
+ CPRINTF("[%T DPTF under threshold [%d][%d]\n",
+ sensor_id, i);
+ tripped = 1;
+ }
+ }
+
+ return tripped;
+}
+
+
void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable)
{
- /* TODO(crosbug.com/p/23970) */
CPRINTF("[%T DPTF sensor %d, threshold %d C, index %d, %sabled]\n",
sensor_id, K_TO_C(temp), idx, enable ? "en" : "dis");
+
+ if (enable) {
+ dptf_threshold[sensor_id][idx].temp = temp;
+ cond_init(&dptf_threshold[sensor_id][idx].over, 0);
+ } else {
+ dptf_threshold[sensor_id][idx].temp = -1;
+ }
}
+
+
+
+
/*****************************************************************************/
/* EC-specific thermal controls */
@@ -67,6 +132,7 @@ static void thermal_control(void)
int num_valid_limits[EC_TEMP_THRESH_COUNT];
int num_sensors_read;
int fmax;
+ int dptf_tripped;
/* Get ready to count things */
memset(count_over, 0, sizeof(count_over));
@@ -74,6 +140,7 @@ static void thermal_control(void)
memset(num_valid_limits, 0, sizeof(num_valid_limits));
num_sensors_read = 0;
fmax = 0;
+ dptf_tripped = 0;
/* go through all the sensors */
for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
@@ -106,6 +173,9 @@ static void thermal_control(void)
if (f > fmax)
fmax = f;
}
+
+ /* and check the dptf thresholds */
+ dptf_tripped |= dpft_check_temp_threshold(i, t);
}
if (!num_sensors_read) {
@@ -176,6 +246,10 @@ static void thermal_control(void)
for (i = 0; i < CONFIG_FANS; i++)
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 */
@@ -256,6 +330,32 @@ DECLARE_CONSOLE_COMMAND(thermalset, command_thermalset,
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);
+ }
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(dptftemp, command_dptftemp,
+ NULL,
+ "Print DPTF thermal parameters (degrees Kelvin)",
+ NULL);
/*****************************************************************************/
diff --git a/include/dptf.h b/include/dptf.h
index 4213426255..31c9c09bca 100644
--- a/include/dptf.h
+++ b/include/dptf.h
@@ -14,7 +14,11 @@ void dptf_set_fan_duty_target(int pct);
/* 0-100% if in duty mode. -1 if not */
int dptf_get_fan_duty_target(void);
-/* Each temp sensor can have up to two thresholds */
+/* Thermal thresholds may be set for each temp sensor. */
+#define DPTF_THRESHOLDS_PER_SENSOR 2
+#define DPTF_THRESHOLD_HYSTERESIS 2
+
+/* Set/enable the thresholds */
void dptf_set_temp_threshold(int sensor_id, /* zero-based sensor index */
int temp, /* in degrees K */
int idx, /* which threshold (0 or 1) */