common/sensor/dev/intel_peci.c (228 lines of code) (raw):

#include <stdio.h> #include <stdlib.h> #include "sensor.h" #include "pal.h" #include <drivers/peci.h> #include "hal_peci.h" #include <string.h> #include "intel_peci.h" #define READ_RETRY 0x03 #define RDPKG_IDX_PKG_TEMP 0x02 #define RDPKG_IDX_DIMM_TEMP 0x0E #define RDPKG_IDX_TJMAX_TEMP 0x10 #define DIMM_TEMP_OFS_0 0x01 #define DIMM_TEMP_OFS_1 0x02 static bool peci_read_retry(uint8_t cmd, uint8_t addr, uint8_t idx, uint16_t param, uint8_t rlen, uint8_t *rbuf) { if (!rbuf) return false; int i; for (i = 0; i < READ_RETRY; i++) { if (!peci_read(cmd, addr, idx, param, rlen, rbuf)) { const uint8_t cc = rbuf[0]; if (cc == PECI_CC_RSP_SUCCESS) break; } /* TODO: read failed, maybe add delay before next read */ } return (i == READ_RETRY) ? false : true; } static bool get_cpu_tjmax(uint8_t addr, int *reading) { if (!reading) return false; const uint16_t param = 0x00; const uint8_t rlen = 0x05; uint8_t rbuf[rlen]; memset(rbuf, 0, sizeof(rbuf)); if (peci_read_retry(PECI_CMD_RD_PKG_CFG0, addr, RDPKG_IDX_TJMAX_TEMP, param, rlen, rbuf) == false) return false; sensor_val *sval = (sensor_val *)reading; sval->integer = rbuf[3]; return true; } static bool get_cpu_margin(uint8_t addr, int *reading) { if (!reading) return false; const uint16_t param = 0xFF; const uint8_t rlen = 0x05; uint8_t rbuf[rlen]; memset(rbuf, 0, sizeof(rbuf)); if (peci_read_retry(PECI_CMD_RD_PKG_CFG0, addr, RDPKG_IDX_PKG_TEMP, param, rlen, rbuf) == false) return false; sensor_val *sval = (sensor_val *)reading; sval->integer = ((int16_t)((rbuf[2] << 8) | rbuf[1]) >> 6) + 1; return true; } static bool get_cpu_pwr(uint8_t sensor_num, int *reading) { if (!reading) return false; int pwr = 0; if (peci_getPwr(sensor_num, &pwr) == false) return false; sensor_val *sval = (sensor_val *)reading; sval->integer = (int16_t)pwr; return true; } static bool get_cpu_temp(uint8_t addr, int *reading) { if (!reading) return false; sensor_val tjmax = { 0 }; if (get_cpu_tjmax(addr, (int *)&tjmax) == false) return false; sensor_val margin = { 0 }; if (get_cpu_margin(addr, (int *)&margin) == false) return false; sensor_val *sval = (sensor_val *)reading; sval->integer = tjmax.integer + margin.integer; return true; } static bool get_dimm_temp(uint8_t addr, uint8_t type, int *reading) { if (!reading) return false; uint8_t temp_ofs = 0xFF; uint16_t param = 0xFF; switch (type) { case PECI_TEMP_CHANNEL0_DIMM0: param = 0x00; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL0_DIMM1: param = 0x00; temp_ofs = DIMM_TEMP_OFS_1; break; case PECI_TEMP_CHANNEL1_DIMM0: param = 0x01; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL1_DIMM1: param = 0x01; temp_ofs = DIMM_TEMP_OFS_1; break; case PECI_TEMP_CHANNEL2_DIMM0: param = 0x02; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL2_DIMM1: param = 0x02; temp_ofs = DIMM_TEMP_OFS_1; break; case PECI_TEMP_CHANNEL3_DIMM0: param = 0x03; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL3_DIMM1: param = 0x03; temp_ofs = DIMM_TEMP_OFS_1; break; case PECI_TEMP_CHANNEL4_DIMM0: param = 0x04; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL4_DIMM1: param = 0x04; temp_ofs = DIMM_TEMP_OFS_1; break; case PECI_TEMP_CHANNEL5_DIMM0: param = 0x05; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL5_DIMM1: param = 0x05; temp_ofs = DIMM_TEMP_OFS_1; break; case PECI_TEMP_CHANNEL6_DIMM0: param = 0x06; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL6_DIMM1: param = 0x06; temp_ofs = DIMM_TEMP_OFS_1; break; case PECI_TEMP_CHANNEL7_DIMM0: param = 0x07; temp_ofs = DIMM_TEMP_OFS_0; break; case PECI_TEMP_CHANNEL7_DIMM1: param = 0x07; temp_ofs = DIMM_TEMP_OFS_1; break; default: break; } if (param == 0xFF || temp_ofs == 0xFF) return false; const uint8_t rlen = 0x05; uint8_t rbuf[rlen]; memset(rbuf, 0, sizeof(rbuf)); if (peci_read_retry(PECI_CMD_RD_PKG_CFG0, addr, RDPKG_IDX_DIMM_TEMP, param, rlen, rbuf) == false) return false; sensor_val *sval = (sensor_val *)reading; sval->integer = rbuf[temp_ofs]; return true; } uint8_t intel_peci_read(uint8_t sensor_num, int *reading) { if (!reading) return SENSOR_UNSPECIFIED_ERROR; bool ret_val = false; sensor_cfg *cfg = &sensor_config[SensorNum_SensorCfg_map[sensor_num]]; const uint8_t read_type = cfg->offset; if (read_type <= PECI_UNKNOWN || read_type >= PECI_MAX) return SENSOR_NOT_FOUND; switch (read_type) { case PECI_TEMP_CHANNEL0_DIMM0: case PECI_TEMP_CHANNEL0_DIMM1: case PECI_TEMP_CHANNEL1_DIMM0: case PECI_TEMP_CHANNEL1_DIMM1: case PECI_TEMP_CHANNEL2_DIMM0: case PECI_TEMP_CHANNEL2_DIMM1: case PECI_TEMP_CHANNEL3_DIMM0: case PECI_TEMP_CHANNEL3_DIMM1: case PECI_TEMP_CHANNEL4_DIMM0: case PECI_TEMP_CHANNEL4_DIMM1: case PECI_TEMP_CHANNEL5_DIMM0: case PECI_TEMP_CHANNEL5_DIMM1: case PECI_TEMP_CHANNEL6_DIMM0: case PECI_TEMP_CHANNEL6_DIMM1: case PECI_TEMP_CHANNEL7_DIMM0: case PECI_TEMP_CHANNEL7_DIMM1: ret_val = get_dimm_temp(cfg->slave_addr, read_type, reading); break; case PECI_TEMP_CPU_MARGIN: ret_val = get_cpu_margin(cfg->slave_addr, reading); break; case PECI_TEMP_CPU_TJMAX: ret_val = get_cpu_tjmax(cfg->slave_addr, reading); break; case PECI_TEMP_CPU: ret_val = get_cpu_temp(cfg->slave_addr, reading); break; case PECI_PWR_CPU: ret_val = get_cpu_pwr(sensor_num, reading); break; default: break; } return ret_val ? SENSOR_READ_SUCCESS : SENSOR_FAIL_TO_ACCESS; } uint8_t intel_peci_init(uint8_t sensor_num) { static bool is_init = false; sensor_config[SensorNum_SensorCfg_map[sensor_num]].read = intel_peci_read; if (!is_init) { int ret; ret = peci_init(); if (ret) return SENSOR_INIT_UNSPECIFIED_ERROR; is_init = true; } return SENSOR_INIT_SUCCESS; }