summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2013-12-13 12:22:42 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-12-16 22:57:54 +0000
commit700adf4dea7f12fef6e8f12d34005d82ca58a3a2 (patch)
treea168e24f6a2a59e8592ec79e78bfb02d547c1033
parentc450c2b2202cb3d835a0d8d709b5182c96c92c88 (diff)
downloadchrome-ec-700adf4dea7f12fef6e8f12d34005d82ca58a3a2.tar.gz
Let AP read sensor IDs when DPTF thermal thresholds crossed
The spec does not mandate any way to read back the threshold settings themselves, but when a threshold is crossed the AP needs a way to determine which sensor(s) are responsible. Each reading of the EC_ACPI_MEM_TEMP_ID register clears and returns one sensor ID that has crossed one of its thresholds (in either direction) since the last read. A value of 0xFF means "no new thresholds have tripped". Changing or enabling the thresholds for any sensor will clear the unread event count for that sensor. BUG=chrome-os-partner:23970 BRANCH=none TEST=manual On the host, set a couple of thresholds to low values so they trip immediately (I'm testing on Link): # dptf() { [ "$#" -eq "2" ] || return; iotools io_write8 0x66 0x81 iotools io_write8 0x62 $1 iotools io_write8 0x62 $2 } # # dptf 5 0 # dptf 6 10 # dptf 7 3 # dptf 5 2 # dptf 6 10 # dptf 7 2 On the EC console, see that two thresholds have triggered, and that there are two bits set in the AP seen mask: [45.755365 DPTF sensor 0, threshold -63 C, index 1, enabled] [45.768940 DPTF sensor 2, threshold -63 C, index 0, enabled] [46.169490 DPTF over threshold [0][1] [46.169820 DPTF over threshold [2][0] > dptftemp sensor thresh0 thresh1 0 --- 210* I2C-USB C-Die 1 --- --- I2C-USB C-Object 2 210* --- I2C-PCH D-Die 3 --- --- I2C-PCH D-Object 4 --- --- I2C-Hinge C-Die 5 --- --- I2C-Hinge C-Object 6 --- --- I2C-Charger D-Die 7 --- --- I2C-Charger D-Object 8 --- --- ECInternal 9 --- --- PECI AP seen mask: 0x00000005 > Read the EC_ACPI_MEM_TEMP_ID register from the host, to get the two active sensor IDs (0 and 2), then 0xff when those are seen. # iotools io_write8 0x66 0x80; iotools io_write8 0x62 5; iotools io_read8 0x62 0x00 # iotools io_write8 0x66 0x80; iotools io_write8 0x62 5; iotools io_read8 0x62 0x02 # iotools io_write8 0x66 0x80; iotools io_write8 0x62 5; iotools io_read8 0x62 0xff # iotools io_write8 0x66 0x80; iotools io_write8 0x62 5; iotools io_read8 0x62 0xff # Change-Id: I8f047a517357617f18ad59d21fa13409bc81821b Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/180224 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--common/acpi.c5
-rw-r--r--common/thermal.c23
-rw-r--r--include/dptf.h6
-rw-r--r--include/ec_commands.h8
4 files changed, 37 insertions, 5 deletions
diff --git a/common/acpi.c b/common/acpi.c
index 68c281b6e6..69cf3bc837 100644
--- a/common/acpi.c
+++ b/common/acpi.c
@@ -71,6 +71,11 @@ 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
+ case EC_ACPI_MEM_TEMP_ID:
+ result = dptf_query_next_sensor_event();
+ break;
+#endif
default:
CPRINTF("[%T ACPI read 0x%02x (ignored)]\n", acpi_addr);
break;
diff --git a/common/thermal.c b/common/thermal.c
index 6464ef7161..7113564f82 100644
--- a/common/thermal.c
+++ b/common/thermal.c
@@ -7,6 +7,7 @@
* implementation from the original version that shipped on Link.
*/
+#include "atomic.h"
#include "chipset.h"
#include "common.h"
#include "console.h"
@@ -45,8 +46,21 @@ static void dptf_init(void)
}
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)
@@ -68,11 +82,13 @@ static int dpft_check_temp_threshold(int sensor_id, int temp)
if (cond_went_true(&dptf_threshold[sensor_id][i].over)) {
CPRINTF("[%T DPTF over threshold [%d][%d]\n",
sensor_id, i);
+ atomic_or(&dptf_seen, (1 << sensor_id));
tripped = 1;
}
if (cond_went_false(&dptf_threshold[sensor_id][i].over)) {
CPRINTF("[%T DPTF under threshold [%d][%d]\n",
sensor_id, i);
+ atomic_or(&dptf_seen, (1 << sensor_id));
tripped = 1;
}
}
@@ -80,7 +96,6 @@ static int dpft_check_temp_threshold(int sensor_id, int temp)
return tripped;
}
-
void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable)
{
CPRINTF("[%T DPTF sensor %d, threshold %d C, index %d, %sabled]\n",
@@ -89,15 +104,12 @@ void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable)
if (enable) {
dptf_threshold[sensor_id][idx].temp = temp;
cond_init(&dptf_threshold[sensor_id][idx].over, 0);
+ atomic_clear(&dptf_seen, (1 << sensor_id));
} else {
dptf_threshold[sensor_id][idx].temp = -1;
}
}
-
-
-
-
/*****************************************************************************/
/* EC-specific thermal controls */
@@ -350,6 +362,7 @@ static int command_dptftemp(int argc, char **argv)
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,
diff --git a/include/dptf.h b/include/dptf.h
index 31c9c09bca..f611acb361 100644
--- a/include/dptf.h
+++ b/include/dptf.h
@@ -24,4 +24,10 @@ void dptf_set_temp_threshold(int sensor_id, /* zero-based sensor index */
int idx, /* which threshold (0 or 1) */
int enable); /* true = on, false = off */
+/*
+ * Return the ID of a temp sensor that has crossed its threshold since the last
+ time we asked. -1 means none.
+ */
+int dptf_query_next_sensor_event(void);
+
#endif /* __CROS_EC_DPTF_H */
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 7b3fb170d1..f526accd00 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1877,6 +1877,14 @@ struct ec_params_reboot_ec {
* register determines which sensor is affected by the THRESHOLD and COMMIT
* registers. The THRESHOLD register uses the same EC_TEMP_SENSOR_OFFSET scheme
* as the memory-mapped sensors. The COMMIT register applies those settings.
+ *
+ * The spec does not mandate any way to read back the threshold settings
+ * themselves, but when a threshold is crossed the AP needs a way to determine
+ * which sensor(s) are responsible. Each reading of the ID register clears and
+ * returns one sensor ID that has crossed one of its threshold (in either
+ * direction) since the last read. A value of 0xFF means "no new thresholds
+ * have tripped". Setting or enabling the thresholds for a sensor will clear
+ * the unread event count for that sensor.
*/
#define EC_ACPI_MEM_TEMP_ID 0x05
#define EC_ACPI_MEM_TEMP_THRESHOLD 0x06