diff options
-rw-r--r-- | driver/amd_stt.c | 138 | ||||
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | include/config.h | 8 | ||||
-rw-r--r-- | include/driver/amd_stt.h | 27 | ||||
-rw-r--r-- | zephyr/Kconfig | 11 | ||||
-rw-r--r-- | zephyr/shim/include/config_chip.h | 5 |
6 files changed, 190 insertions, 0 deletions
diff --git a/driver/amd_stt.c b/driver/amd_stt.c new file mode 100644 index 0000000000..b8ac8dcfba --- /dev/null +++ b/driver/amd_stt.c @@ -0,0 +1,138 @@ +/* Copyright 2021 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 "amd_stt.h" +#include "common.h" +#include "console.h" +#include "driver/sb_rmi.h" +#include "hooks.h" +#include "math_util.h" +#include "temp_sensor.h" +#include "util.h" + +/* Debug flag can be toggled with console command: stt debug */ +static bool amd_stt_debug; + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) + +static const char * const amd_stt_sensor_name[] = { + [AMD_STT_PCB_SENSOR_APU] = "APU", + [AMD_STT_PCB_SENSOR_REMOTE] = "Ambient", + [AMD_STT_PCB_SENSOR_GPU] = "GPU", +}; + +/** + * Write temperature sensor value to AP via SB-RMI + * + * sensor: + * AMD_STT_PCB_SENSOR_APU + * AMD_STT_PCB_SENSOR_REMOTE + * AMD_STT_PCB_SENSOR_GPU + * + * temp_mk: + * Temperature in degrees milli kelvin + */ +static int write_stt_sensor_val(enum amd_stt_pcb_sensor sensor, int temp_mk) +{ + uint32_t msgIn = 0; + uint32_t msgOut; + int temp_mc; + int temp_c_fp_msb; + int temp_c_fp_lsb; + + temp_mc = MILLI_KELVIN_TO_MILLI_CELSIUS(temp_mk); + + if (amd_stt_debug) + CPRINTS("STT: %s = %d.%d °C", amd_stt_sensor_name[sensor], + temp_mc / 1000, temp_mc % 1000); + + /* Divide by 1000 to get MSB of fixed point temp */ + temp_c_fp_msb = temp_mc / 1000; + /* Modulus 1000 and multiply by 256/1000 to get LSB of fixed point*/ + temp_c_fp_lsb = ((temp_mc % 1000) << 8) / 1000; + + /* + * [15:0]: temperature as signed integer with 8 fractional bits. + * [23:16]: sensor index + * [31:24]: unused + */ + msgIn |= (temp_c_fp_lsb & 0xff); + msgIn |= (temp_c_fp_msb & 0xff) << 8; + msgIn |= (sensor & 0xff) << 16; + return sb_rmi_mailbox_xfer(SB_RMI_WRITE_STT_SENSOR_CMD, msgIn, &msgOut); +} + +static void amd_stt_handler(void) +{ + int rv; + int soc_temp_mk; + int ambient_temp_mk; + + /* + * TODO(b/192391025): Replace with temp_sensor_read_mk(TEMP_SENSOR_SOC) + */ + rv = board_get_soc_temp_mk(&soc_temp_mk); + if (rv) { + CPRINTS("STT: Failed to read SOC temp rv:%d", rv); + return; + } + + rv = write_stt_sensor_val(AMD_STT_PCB_SENSOR_APU, soc_temp_mk); + if (rv) { + CPRINTS("STT: Failed to write SOC temp rv:%d", rv); + return; + } + + /* + * TODO(b/192391025): Replace with + * temp_sensor_read_mk(TEMP_SENSOR_AMBIENT) + */ + rv = board_get_ambient_temp_mk(&ambient_temp_mk); + if (rv) { + CPRINTS("STT: Failed to read AMBIENT temp rv:%d", rv); + return; + } + + rv = write_stt_sensor_val(AMD_STT_PCB_SENSOR_REMOTE, ambient_temp_mk); + if (rv) { + CPRINTS("STT: Failed to write AMBIENT temp rv:%d", rv); + return; + } +} +DECLARE_HOOK(HOOK_SECOND, amd_stt_handler, HOOK_PRIO_TEMP_SENSOR+1); + +static int command_stt(int argc, char **argv) +{ + int sensor_id; + int temp; + + if (argc < 2) + return EC_ERROR_PARAM1; + else if (!strcasecmp(argv[1], "debug")) { + amd_stt_debug = !amd_stt_debug; + return EC_SUCCESS; + } else if (argc != 3) + return EC_ERROR_PARAM2; + else if (!strcasecmp(argv[1], + amd_stt_sensor_name[AMD_STT_PCB_SENSOR_APU])) + sensor_id = AMD_STT_PCB_SENSOR_APU; + else if (!strcasecmp(argv[1], + amd_stt_sensor_name[AMD_STT_PCB_SENSOR_REMOTE])) + sensor_id = AMD_STT_PCB_SENSOR_REMOTE; + else if (!strcasecmp(argv[1], + amd_stt_sensor_name[AMD_STT_PCB_SENSOR_GPU])) + sensor_id = AMD_STT_PCB_SENSOR_GPU; + else + return EC_ERROR_PARAM2; + + temp = atoi(argv[2]); + + return write_stt_sensor_val(sensor_id, temp); +} +DECLARE_CONSOLE_COMMAND(stt, command_stt, + "<apu|ambient|gpu|debug> <temp in mK>", + "Write an STT mK temperature to AP"); diff --git a/driver/build.mk b/driver/build.mk index 0bc42fca47..4ff201c5ce 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -223,3 +223,4 @@ driver-$(CONFIG_MP2964)+=mp2964.o # SOC Interface driver-$(CONFIG_AMD_SB_RMI)+=sb_rmi.o +driver-$(CONFIG_AMD_STT)+=amd_stt.o diff --git a/include/config.h b/include/config.h index a6bd31276d..4e83e96f9c 100644 --- a/include/config.h +++ b/include/config.h @@ -3876,6 +3876,9 @@ */ #undef CONFIG_TEMP_SENSOR_POWER_GPIO +/* AMD STT (Skin Temperature Tracking) */ +#undef CONFIG_AMD_STT + /* Compile common code for throttling the CPU based on the temp sensors */ #undef CONFIG_THROTTLE_AP @@ -6434,4 +6437,9 @@ * !CONFIG_ACCELGYRO_BMI_I2C */ +/* AMD STT requires AMD SB-RMI to be enabled */ +#if defined(CONFIG_AMD_STT) && !defined(CONFIG_AMD_SB_RMI) +#define CONFIG_AMD_SB_RMI +#endif + #endif /* __CROS_EC_CONFIG_H */ diff --git a/include/driver/amd_stt.h b/include/driver/amd_stt.h new file mode 100644 index 0000000000..3d382a6c0a --- /dev/null +++ b/include/driver/amd_stt.h @@ -0,0 +1,27 @@ +/* Copyright 2021 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. + */ + +/* AMD STT (Skin Temperature Tracking) Manager */ + +#ifndef __CROS_EC_AMD_STT_H +#define __CROS_EC_AMD_STT_H + +#define AMD_STT_WRITE_SENSOR_VALUE_CMD 0x3A + +enum amd_stt_pcb_sensor { + AMD_STT_PCB_SENSOR_APU = 0x0, + AMD_STT_PCB_SENSOR_REMOTE = 0x1, + AMD_STT_PCB_SENSOR_GPU = 0x2 +}; + +/** + * Boards must implement these callbacks for SOC and Ambient temperature. + * Temperature must be returned in Milli Kelvin. + * TODO(b/192391025): Replace with direct calls to temp_sensor_read_mk + */ +int board_get_soc_temp_mk(int *temp_mk); +int board_get_ambient_temp_mk(int *temp_mk); + +#endif /* __CROS_EC_AMD_STT_H */ diff --git a/zephyr/Kconfig b/zephyr/Kconfig index b11031b8b4..6253631156 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -802,4 +802,15 @@ config PLATFORM_EC_AMD_SB_RMI tasks such as managing power consumption and power limits of the CPU socket. +config PLATFORM_EC_AMD_STT + bool "Enable driver for AMD STT interface" + depends on PLATFORM_EC_AMD_SB_RMI + help + AMD platforms provide the Skin Temperature Tracking (STT) interface. + Skin temperature management can be used to maximize the system + performance while keeping the skin temperature within its + specification. It makes use of the thermal capacitance of the system + to temporarily boost above the sustainable power limit, while the + chassis skin temperatures are below limits. + endif # PLATFORM_EC diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h index d8bb7c27ac..895e19d568 100644 --- a/zephyr/shim/include/config_chip.h +++ b/zephyr/shim/include/config_chip.h @@ -1760,4 +1760,9 @@ #define CONFIG_AMD_SB_RMI #endif +#undef CONFIG_AMD_STT +#ifdef CONFIG_PLATFORM_EC_AMD_STT +#define CONFIG_AMD_STT +#endif + #endif /* __CROS_EC_CONFIG_CHIP_H */ |