diff options
Diffstat (limited to 'common/peci.c')
-rw-r--r-- | common/peci.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/common/peci.c b/common/peci.c new file mode 100644 index 0000000000..b4422de05e --- /dev/null +++ b/common/peci.c @@ -0,0 +1,165 @@ +/* Copyright 2019 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. + */ + +/* PECI interface for Chrome EC */ + +#include "chipset.h" +#include "console.h" +#include "peci.h" +#include "util.h" + +static int peci_get_cpu_temp(int *cpu_temp) +{ + int rv; + uint8_t r_buf[PECI_GET_TEMP_READ_LENGTH] = {0}; + struct peci_data peci = { + .cmd_code = PECI_CMD_GET_TEMP, + .addr = PECI_TARGET_ADDRESS, + .w_len = PECI_GET_TEMP_WRITE_LENGTH, + .r_len = PECI_GET_TEMP_READ_LENGTH, + .w_buf = NULL, + .r_buf = r_buf, + .timeout_us = PECI_GET_TEMP_TIMEOUT_US, + }; + + rv = peci_transaction(&peci); + if (rv) + return rv; + + /* Get relative raw data of temperature. */ + *cpu_temp = (r_buf[1] << 8) | r_buf[0]; + + /* Convert relative raw data to degrees C. */ + *cpu_temp = ((*cpu_temp ^ 0xFFFF) + 1) >> 6; + + /* + * When the AP transitions into S0, it is possible, depending on the + * timing of the PECI sample, to read an invalid temperature. This is + * very rare, but when it does happen the temperature returned is + * greater than or equal to CONFIG_PECI_TJMAX. + */ + if (*cpu_temp >= CONFIG_PECI_TJMAX) + return EC_ERROR_UNKNOWN; + + /* temperature in K */ + *cpu_temp = CONFIG_PECI_TJMAX - *cpu_temp + 273; + + return EC_SUCCESS; +} + +int peci_temp_sensor_get_val(int idx, int *temp_ptr) +{ + int i, rv; + + if (!chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_STANDBY)) + return EC_ERROR_NOT_POWERED; + + /* + * Retry reading PECI CPU temperature if the first sample is + * invalid or failed to obtain. + */ + for (i = 0; i < 2; i++) { + rv = peci_get_cpu_temp(temp_ptr); + if (!rv) + break; + } + + return rv; +} + +/*****************************************************************************/ +/* Console commands */ +#ifdef CONFIG_CMD_PECI +static int peci_cmd(int argc, char **argv) +{ + uint8_t r_buf[PECI_READ_DATA_FIFO_SIZE] = {0}; + uint8_t w_buf[PECI_WRITE_DATA_FIFO_SIZE] = {0}; + struct peci_data peci = { + .w_buf = w_buf, + .r_buf = r_buf, + }; + + int param; + char *e; + + if ((argc < 6) || (argc > 8)) + return EC_ERROR_PARAM_COUNT; + + peci.addr = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + + peci.w_len = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + peci.r_len = strtoi(argv[3], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + + peci.cmd_code = strtoi(argv[4], &e, 0); + if (*e) + return EC_ERROR_PARAM4; + + peci.timeout_us = strtoi(argv[5], &e, 0); + if (*e) + return EC_ERROR_PARAM5; + + if (argc > 6) { + param = strtoi(argv[6], &e, 0); + if (*e) + return EC_ERROR_PARAM6; + + /* MSB of parameter */ + w_buf[3] = (uint8_t)(param >> 24); + /* LSB of parameter */ + w_buf[2] = (uint8_t)(param >> 16); + /* Index */ + w_buf[1] = (uint8_t)(param >> 8); + /* Host ID[7:1] & Retry[0] */ + w_buf[0] = (uint8_t)(param >> 0); + + if (argc > 7) { + param = strtoi(argv[7], &e, 0); + if (*e) + return EC_ERROR_PARAM7; + + /* Data (1, 2 or 4 bytes) */ + w_buf[7] = (uint8_t)(param >> 24); + w_buf[6] = (uint8_t)(param >> 16); + w_buf[5] = (uint8_t)(param >> 8); + w_buf[4] = (uint8_t)(param >> 0); + } + } else { + peci.w_len = 0x00; + } + + if (peci_transaction(&peci)) { + ccprintf("PECI transaction error\n"); + return EC_ERROR_UNKNOWN; + } + ccprintf("PECI read data: %.*h\n", peci.r_len, r_buf); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(peci, peci_cmd, + "addr wlen rlen cmd timeout(us)", + "PECI command"); + +static int command_peci_temp(int argc, char **argv) +{ + int t; + + if (peci_get_cpu_temp(&t) != EC_SUCCESS) { + ccprintf("PECI get cpu temp error\n"); + return EC_ERROR_UNKNOWN; + } + + ccprintf("CPU temp: %d K, %d C\n", t, K_TO_C(t)); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp, + NULL, + "Print CPU temperature"); +#endif /* CONFIG_CMD_PECI */ |