common/util/hal_peci.c (198 lines of code) (raw):

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <drivers/peci.h> #include "hal_peci.h" const struct device *dev; int peci_init() { dev = device_get_binding("PECI"); int ret; uint32_t bitrate = 1000; if (!dev) { printf("peci device not found"); return false; } ret = peci_config(dev, bitrate); if (ret) { printf("set bitrate %dKbps failed %d\n", bitrate, ret); return ret; } ret = peci_enable(dev); if (ret) { printf("peci enable failed %d\n", ret); return ret; } return ret; } int peci_ping(uint8_t address) { struct peci_msg pkgcfg; int ret; pkgcfg.addr = address; pkgcfg.cmd_code = PECI_CMD_PING; pkgcfg.tx_buffer.buf = NULL; pkgcfg.tx_buffer.len = 0x0; pkgcfg.rx_buffer.len = 0x0; ret = peci_transfer(dev, &pkgcfg); if (ret) { printf("ping failed %d\n", ret); free(pkgcfg.tx_buffer.buf); return ret; } free(pkgcfg.tx_buffer.buf); return ret; } int peci_read(uint8_t cmd, uint8_t address, uint8_t u8Index, uint16_t u16Param, uint8_t u8ReadLen, uint8_t *readBuf) { struct peci_msg rdpkgcfg; int ret; rdpkgcfg.cmd_code = cmd; rdpkgcfg.addr = address; rdpkgcfg.tx_buffer.len = 0x05; rdpkgcfg.rx_buffer.len = u8ReadLen; rdpkgcfg.tx_buffer.buf = malloc(rdpkgcfg.tx_buffer.len * sizeof(uint8_t)); rdpkgcfg.rx_buffer.buf = readBuf; rdpkgcfg.tx_buffer.buf[0] = 0x00; rdpkgcfg.tx_buffer.buf[1] = u8Index; rdpkgcfg.tx_buffer.buf[2] = u16Param & 0xff; rdpkgcfg.tx_buffer.buf[3] = u16Param >> 8; ret = peci_transfer(dev, &rdpkgcfg); if (DEBUG_PECI) { uint8_t index; for (index = 0; index < 5; index++) printf("%02x ", readBuf[index]); printf("\n"); } if (ret) { printf("peci read failed %d\n", ret); free(rdpkgcfg.tx_buffer.buf); return ret; } free(rdpkgcfg.tx_buffer.buf); return ret; } int peci_write(uint8_t cmd, uint8_t address, uint8_t u8ReadLen, uint8_t *readBuf, uint8_t u8WriteLen, uint8_t *writeBuf) { struct peci_msg wrpkgcfg; int ret; wrpkgcfg.addr = address; wrpkgcfg.cmd_code = cmd; wrpkgcfg.tx_buffer.len = u8WriteLen; wrpkgcfg.rx_buffer.len = u8ReadLen; wrpkgcfg.rx_buffer.buf = readBuf; wrpkgcfg.tx_buffer.buf = writeBuf; ret = peci_transfer(dev, &wrpkgcfg); if (ret) { printk("peci write failed %d\n", ret); return ret; } return ret; } bool peci_retry_read(uint8_t cmd, uint8_t address, uint8_t u8Index, uint16_t u16Param, uint8_t u8ReadLen, uint8_t *readBuf) { uint8_t i, ret, retry = 5; if (readBuf == NULL) return false; for (i = 0; i < retry; ++i) { k_msleep(10); memcpy(&readBuf[0], 0, u8ReadLen * sizeof(uint8_t)); ret = peci_read(cmd, address, u8Index, u16Param, u8ReadLen, readBuf); if (!ret) { if (readBuf[0] == PECI_CC_RSP_SUCCESS) { return true; } } } return false; } bool peci_getPwr(uint8_t sensor_num, int *reading) { uint8_t rdpkgcfgCmd = PECI_RD_PKG_CFG0_CMD; uint8_t PECIaddr = 0x30; uint8_t readlen = 0x05; uint8_t *readbuf = (uint8_t*)malloc(2 * readlen * sizeof(uint8_t)); uint8_t u8index[2] = { 0x03, 0x1F }; uint16_t u16Param[2] = { 0x00FF, 0x0000 }; uint8_t ret, complete_code; bool is_retry_success = false; uint32_t pkg_energy, run_time, diff_energy, diff_time; static uint32_t last_pkg_energy = 0, last_run_time = 0; peci_read(rdpkgcfgCmd, PECIaddr, u8index[0], u16Param[0], readlen, readbuf); complete_code = readbuf[0]; if (complete_code == PECI_CC_RSP_TIMEOUT || complete_code == PECI_CC_OUT_OF_RESOURCES_TIMEOUT) { is_retry_success = peci_retry_read(rdpkgcfgCmd, PECIaddr, u8index[0], u16Param[0], readlen, readbuf); if (!is_retry_success) { printf("PECI sensor [%x] response timeout. Reach Max retry.\n", sensor_num); free(readbuf); return false; } } ret = peci_read(rdpkgcfgCmd, PECIaddr, u8index[1], u16Param[1], readlen, &readbuf[5]); complete_code = readbuf[5]; if (complete_code == PECI_CC_RSP_TIMEOUT || complete_code == PECI_CC_OUT_OF_RESOURCES_TIMEOUT) { is_retry_success = peci_retry_read(rdpkgcfgCmd, PECIaddr, u8index[1], u16Param[1], readlen, &readbuf[5]); if (!is_retry_success) { printf("PECI sensor [%x] response timeout. Reach Max retry.\n", sensor_num); free(readbuf); return false; } } if (ret) { free(readbuf); return false; } if (readbuf[0] != PECI_CC_RSP_SUCCESS || readbuf[5] != PECI_CC_RSP_SUCCESS) { if (readbuf[0] == PECI_CC_ILLEGAL_REQUEST || readbuf[5] == PECI_CC_ILLEGAL_REQUEST) { printf("Unknown request\n"); } else { printf("PECI control hardware, firmware or associated logic error\n"); } free(readbuf); return false; } pkg_energy = readbuf[4]; pkg_energy = (pkg_energy << 8) | readbuf[3]; pkg_energy = (pkg_energy << 8) | readbuf[2]; pkg_energy = (pkg_energy << 8) | readbuf[1]; run_time = readbuf[9]; run_time = (run_time << 8) | readbuf[8]; run_time = (run_time << 8) | readbuf[7]; run_time = (run_time << 8) | readbuf[6]; if (last_pkg_energy == 0 && last_run_time == 0) { // first read, need second data to calculate last_pkg_energy = pkg_energy; last_run_time = run_time; free(readbuf); return false; } if (pkg_energy >= last_pkg_energy) { diff_energy = pkg_energy - last_pkg_energy; } else { diff_energy = pkg_energy + (0xffffffff - last_pkg_energy + 1); } last_pkg_energy = pkg_energy; if (run_time >= last_run_time) { diff_time = run_time - last_run_time; } else { diff_time = run_time + (0xffffffff - last_run_time + 1); } last_run_time = run_time; if (diff_time == 0) { free(readbuf); return false; } else { free(readbuf); *reading = ((float)diff_energy / (float)diff_time * 0.06103515625); // energy / unit time return true; } }