--- a/device-api/include/management-api/device_mgmt_api_rpc_types.h +++ b/device-api/include/management-api/device_mgmt_api_rpc_types.h @@ -1572,8 +1572,10 @@ uint8_t total; /**< total entries available in this group */ uint8_t pad[3]; /**< Padding for alignment */ uint64_t fault_mask; /**< bit (first+i) set if entry i could not be sampled (data zeroed) */ - uint16_t data[PVT_SAMPLES_MAX_WORDS]; /**< count*stride words, entry-major */ -} __attribute__((packed)); + uint16_t data[PVT_SAMPLES_MAX_WORDS]; /**< count*stride words, entry-major; temperatures in C + are int16_t, TS_RAW words are 12-bit sensor codes */ +} __attribute__((aligned(8))); /* not packed: the firmware writes entries through pointers into + data[]; the field offsets are the same */ /*! \struct device_mgmt_pvt_samples_cmd_t \brief Command to request disaggregated PVT samples --- a/device-api/include/management-api/device_mgmt_api_spec.h +++ b/device-api/include/management-api/device_mgmt_api_spec.h @@ -310,8 +310,11 @@ PVT_SAMPLE_GROUP_MEMSHIRE_VM = 3, /**< Mem Shire voltage monitors, 6 words/entry: ms, noc x (cur,hi,lo) (mV) */ PVT_SAMPLE_GROUP_IOSHIRE = 4, /**< IO Shire, 1 entry of 15 words: ts(3), pd(3), vm noc/0p75/mxn (9) */ PVT_SAMPLE_GROUP_PSHIRE_VM = 5, /**< PCIe Shire voltage monitors, 1 entry of 6 words: pshr, noc x (cur,hi,lo) */ - PVT_SAMPLE_GROUP_HILO_RESET = 6, /**< Reset all high/low latches; no data returned */ - PVT_SAMPLE_GROUP_MAX = 7, /**< */ + PVT_SAMPLE_GROUP_HILO_RESET = 6, /**< Reserved, not served: resetting the latches is global state */ + PVT_SAMPLE_GROUP_TS_RAW = 7, /**< All 35 temperature sensors (0-33 Minion Shires, 34 IO Shire), 3 words/entry: + raw 12-bit codes current, high, low. RUN_1 converts them as + T(C) = (57400 + 249400 * code / 4096 - 124700) / 1000, 0.061 C per code */ + PVT_SAMPLE_GROUP_MAX = 8, /**< */ }; typedef uint8_t mdi_hart_selection_flag_e; --- a/device-bootloaders/src/ServiceProcessorBL2/services/thermal_power_monitor.c +++ b/device-bootloaders/src/ServiceProcessorBL2/services/thermal_power_monitor.c @@ -13,6 +13,7 @@ #include "bl2_thermal_power_monitor.h" #include "bl2_pvt_controller.h" +#include #include #include "minion_configuration.h" #include @@ -962,6 +963,9 @@ case PVT_SAMPLE_GROUP_PSHIRE_VM: status = pvt_get_pshire_vm_sample((PShire_VM_sample *)out); break; + case PVT_SAMPLE_GROUP_TS_RAW: + status = pvt_get_ts_raw_sample(idx, (TS_Sample *)out); + break; default: status = -1; break; @@ -969,6 +973,13 @@ return status; } +/* The response stays within the 512 B that PVT_SAMPLES_MAX_WORDS is sized for, and entries are + written through uint16_t pointers into data[]. */ +_Static_assert(sizeof(struct device_mgmt_pvt_samples_rsp_t) <= 512, "PVT samples response over 512 B"); +_Static_assert((offsetof(struct device_mgmt_pvt_samples_rsp_t, samples) + + offsetof(struct pvt_samples_t, data)) % sizeof(uint16_t) == 0, + "PVT samples data[] not 2-byte aligned"); + static void pwr_svc_get_asic_pvt_samples(uint16_t tag, uint64_t req_start_time, void *buffer) { static struct device_mgmt_pvt_samples_rsp_t dm_rsp; /* ~0.5 KB, keep off the task stack */ @@ -980,6 +991,13 @@ uint8_t first = cmd->req.first; uint8_t count = cmd->req.count; + /* The SQ buffer is static: a request shorter than this command would leave group, first and + count holding bytes of an earlier command. Serve it as an invalid group. */ + if (cmd->command_info.cmd_hdr.size < sizeof(struct device_mgmt_pvt_samples_cmd_t)) + { + group = PVT_SAMPLE_GROUP_MAX; + } + memset(&dm_rsp.samples, 0, sizeof(dm_rsp.samples)); switch (group) @@ -990,10 +1008,10 @@ case PVT_SAMPLE_GROUP_MEMSHIRE_VM: stride = 6; total = PVTC_MEM_SHIRE_NUM; break; case PVT_SAMPLE_GROUP_IOSHIRE: stride = 15; total = 1; break; case PVT_SAMPLE_GROUP_PSHIRE_VM: stride = 6; total = 1; break; - case PVT_SAMPLE_GROUP_HILO_RESET: - status = pvt_hilo_reset(); - stride = 0; total = 0; count = 0; - break; + case PVT_SAMPLE_GROUP_TS_RAW: stride = 3; total = PVTC_MINION_SHIRE_NUM + 1; break; + /* PVT_SAMPLE_GROUP_HILO_RESET is not served by this GET: pvt_hilo_reset() clears the TS, PD + and VM latches on all five controllers, which the SP's own reports (minshire_high/low, the + voltage min/max) read too, so one reader's request would wipe every other reader's peaks. */ default: status = THERMAL_PWR_MGMT_PVT_ACCESS_FAILED; count = 0; --- a/device-bootloaders/src/ServiceProcessorBL2/driver/pvt_controller.c +++ b/device-bootloaders/src/ServiceProcessorBL2/driver/pvt_controller.c @@ -664,6 +664,44 @@ return pvt_get_ts_data(pvt_id, ts_id, ts_sample); } +/* Same registers as pvt_get_ts_data, without pvt_ts_conversion: the integer conversion keeps + whole degrees, while the sensor resolves 0.061 C. No log on a fault: a host may poll this. */ +static int pvt_get_ts_raw_data(uint8_t pvt_id, uint8_t ts_id, TS_Sample *ts_sample) +{ + uint32_t sample_data; + uint32_t hilo; + + ts_sample->current = 0; + ts_sample->high = 0; + ts_sample->low = 0; + + sample_data = pReg_Pvtc[pvt_id]->ts.ts_individual[ts_id].sdif_data; + if (TS_PD_INDIVIDUAL_IP_SDIF_DATA_SAMPLE_FAULT_GET(sample_data)) + { + return ERROR_PVT_SAMPLE_FAULT; + } + + ts_sample->current = (int16_t)TS_PD_INDIVIDUAL_IP_SDIF_DATA_SAMPLE_DATA_GET(sample_data); + + hilo = pReg_Pvtc[pvt_id]->ts.ts_individual[ts_id].smpl_hilo; + + ts_sample->high = (int16_t)TS_PD_INDIVIDUAL_IP_SMPL_HILO_SMPL_HI_GET(hilo); + ts_sample->low = (int16_t)TS_PD_INDIVIDUAL_IP_SMPL_HILO_SMPL_LO_GET(hilo); + + return 0; +} + +int pvt_get_ts_raw_sample(uint8_t ts_index, TS_Sample *ts_sample) +{ + if (ts_index > PVTC_IOSHIRE_TS_PD_ID) + { + return ERROR_PVT_MINION_ID_OUT_OF_RANGE; + } + + return pvt_get_ts_raw_data((uint8_t)(ts_index / PVTC_TS_NUM), (uint8_t)(ts_index % PVTC_TS_NUM), + ts_sample); +} + static int pvt_get_pd_data(uint8_t pvt_id, uint8_t pd_id, PD_Sample *pd_sample) { uint32_t sample_data; --- a/device-bootloaders/src/ServiceProcessorBL2/include/bl2_pvt_controller.h +++ b/device-bootloaders/src/ServiceProcessorBL2/include/bl2_pvt_controller.h @@ -542,6 +542,14 @@ */ int pvt_get_ioshire_ts_sample(TS_Sample *ts_sample); +/*! \fn int pvt_get_ts_raw_sample(uint8_t ts_index, TS_Sample *ts_sample) + \brief Reads one temperature sensor's raw 12-bit codes (current, high, low), unconverted + \param ts_index 0-33 Minion Shire, PVTC_IOSHIRE_TS_PD_ID (34) IO Shire + \param ts_sample Raw codes (0-4095); RUN_1: T(C) = (57400 + 249400 * code / 4096 - 124700) / 1000 + \return Status indicating success or negative error +*/ +int pvt_get_ts_raw_sample(uint8_t ts_index, TS_Sample *ts_sample); + /*! \fn int pvt_get_min_shire_pd_sample(PVTC_MINSHIRE_e min_id, PD_Sample *pd_sample) \brief This function gets PD sample for Minion Shire \param min_id Minion Shire ID