Improvements for determining CPU state using virtual wires
This commit is contained in:
@ -183,6 +183,9 @@ void espi_event(void) {
|
|||||||
VW_SET_DEBUG(VW_SUS_ACK_N, wire);
|
VW_SET_DEBUG(VW_SUS_ACK_N, wire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (value & BIT(7)) {
|
||||||
|
DEBUG("VWIDX47 %X\n", VWIDX47);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect when frequency changes
|
// Detect when frequency changes
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
#ifndef _BOARD_PECI_H
|
#ifndef _BOARD_PECI_H
|
||||||
#define _BOARD_PECI_H
|
#define _BOARD_PECI_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <ec/peci.h>
|
#include <ec/peci.h>
|
||||||
|
|
||||||
extern bool peci_on;
|
extern bool peci_on;
|
||||||
extern int16_t peci_temp;
|
extern int16_t peci_temp;
|
||||||
|
|
||||||
void peci_init(void);
|
void peci_init(void);
|
||||||
|
bool peci_available(void);
|
||||||
int16_t peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data);
|
int16_t peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data);
|
||||||
uint8_t peci_get_fan_duty(void);
|
uint8_t peci_get_fan_duty(void);
|
||||||
|
|
||||||
|
@ -10,10 +10,6 @@
|
|||||||
#include <ec/gpio.h>
|
#include <ec/gpio.h>
|
||||||
#include <ec/pwm.h>
|
#include <ec/pwm.h>
|
||||||
|
|
||||||
#ifndef USE_PECI_OVER_ESPI
|
|
||||||
#define USE_PECI_OVER_ESPI 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fan speed is the lowest requested over HEATUP seconds
|
// Fan speed is the lowest requested over HEATUP seconds
|
||||||
#ifndef BOARD_HEATUP
|
#ifndef BOARD_HEATUP
|
||||||
#define BOARD_HEATUP 4
|
#define BOARD_HEATUP 4
|
||||||
@ -63,10 +59,18 @@ static struct Fan __code FAN = {
|
|||||||
.interpolate = SMOOTH_FANS != 0,
|
.interpolate = SMOOTH_FANS != 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if USE_PECI_OVER_ESPI
|
#if CONFIG_BUS_ESPI
|
||||||
|
|
||||||
void peci_init(void) {}
|
void peci_init(void) {}
|
||||||
|
|
||||||
|
// Returns true if peci is available
|
||||||
|
bool peci_available(void) {
|
||||||
|
// PECI is available if PLTRST_N is high
|
||||||
|
// Do not wake CPU from C10 if HOST_C10 virtual wire is high
|
||||||
|
//TODO: wake CPU every 8 seconds following Intel recommendation?
|
||||||
|
return (vw_get(&VW_PLTRST_N) == VWS_HIGH) && (vw_get(&VW_HOST_C10) != VWS_HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true on success, false on error
|
// Returns true on success, false on error
|
||||||
bool peci_get_temp(int16_t * data) {
|
bool peci_get_temp(int16_t * data) {
|
||||||
//TODO: Wait for completion?
|
//TODO: Wait for completion?
|
||||||
@ -130,15 +134,80 @@ bool peci_get_temp(int16_t * data) {
|
|||||||
// Returns positive completion code on success, negative completion code or
|
// Returns positive completion code on success, negative completion code or
|
||||||
// negative (0x1000 | status register) on PECI hardware error
|
// negative (0x1000 | status register) on PECI hardware error
|
||||||
int16_t peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data) {
|
int16_t peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data) {
|
||||||
//TODO: IMPLEMENT THIS STUB
|
//TODO: Wait for completion?
|
||||||
DEBUG("peci_wr_pkg_config %02X, %04X, %08X\n", index, param, data);
|
// Clear upstream status
|
||||||
index = index;
|
ESUCTRL0 = ESUCTRL0;
|
||||||
param = param;
|
// Clear OOB status
|
||||||
data = data;
|
ESOCTRL0 = ESOCTRL0;
|
||||||
return 0;
|
|
||||||
|
// Set upstream cycle type
|
||||||
|
ESUCTRL1 = ESUCTRL1_OOB;
|
||||||
|
// Set upstream tag / length[11:8]
|
||||||
|
ESUCTRL2 = 0;
|
||||||
|
// Set upstream length [7:0] (size of PECI data plus 3)
|
||||||
|
ESUCTRL3 = 16;
|
||||||
|
|
||||||
|
// Destination address (0x10 is PCH, left shifted by one)
|
||||||
|
UDB[0] = 0x10 << 1;
|
||||||
|
// Command code (0x01 is PECI)
|
||||||
|
UDB[1] = 0x01;
|
||||||
|
// Set byte count
|
||||||
|
UDB[2] = 13;
|
||||||
|
// Set source address (0x0F is EC, left shifted by one, or with 1)
|
||||||
|
UDB[3] = (0x0F << 1) | 1;
|
||||||
|
// PECI target address (0x30 is default)
|
||||||
|
UDB[4] = 0x30;
|
||||||
|
// PECI write length
|
||||||
|
UDB[5] = 10;
|
||||||
|
// PECI read length
|
||||||
|
UDB[6] = 1;
|
||||||
|
// PECI command (0xA5 = WrPkgConfig)
|
||||||
|
UDB[7] = 0xA5;
|
||||||
|
|
||||||
|
// Write host ID
|
||||||
|
UDB[8] = 0;
|
||||||
|
// Write index
|
||||||
|
UDB[9] = index;
|
||||||
|
// Write param
|
||||||
|
UDB[10] = (uint8_t)param;
|
||||||
|
UDB[11] = (uint8_t)(param >> 8);
|
||||||
|
// Write data
|
||||||
|
UDB[12] = (uint8_t)data;
|
||||||
|
UDB[13] = (uint8_t)(data >> 8);
|
||||||
|
UDB[14] = (uint8_t)(data >> 16);
|
||||||
|
UDB[15] = (uint8_t)(data >> 24);
|
||||||
|
|
||||||
|
// Set upstream enable
|
||||||
|
ESUCTRL0 |= ESUCTRL0_ENABLE;
|
||||||
|
// Set upstream go
|
||||||
|
ESUCTRL0 |= ESUCTRL0_GO;
|
||||||
|
|
||||||
|
// Wait until upstream done
|
||||||
|
while (!(ESUCTRL0 & ESUCTRL0_DONE)) {}
|
||||||
|
|
||||||
|
// Wait for response
|
||||||
|
//TODO: do this asynchronously to avoid delays?
|
||||||
|
while (!(ESOCTRL0 & ESOCTRL0_STATUS)) {}
|
||||||
|
|
||||||
|
// Read response length
|
||||||
|
uint8_t len = ESOCTRL4;
|
||||||
|
if (len >= 6) {
|
||||||
|
//TODO: verify packet type, handle PECI status
|
||||||
|
|
||||||
|
// Received enough data for status code
|
||||||
|
int16_t cc = (int16_t)PUTOOBDB[5];
|
||||||
|
if (cc & 0x80) {
|
||||||
|
return -cc;
|
||||||
|
} else {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Did not receive enough data
|
||||||
|
return -0x1000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // USE_PECI_OVER_ESPI
|
#else // CONFIG_BUS_ESPI
|
||||||
|
|
||||||
void peci_init(void) {
|
void peci_init(void) {
|
||||||
// Allow PECI pin to be used
|
// Allow PECI pin to be used
|
||||||
@ -150,6 +219,12 @@ void peci_init(void) {
|
|||||||
PADCTLR = 0x02;
|
PADCTLR = 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if peci is available
|
||||||
|
bool peci_available(void) {
|
||||||
|
// PECI is available if PLTRST# is high
|
||||||
|
return gpio_get(&BUF_PLT_RST_N);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true on success, false on error
|
// Returns true on success, false on error
|
||||||
bool peci_get_temp(int16_t * data) {
|
bool peci_get_temp(int16_t * data) {
|
||||||
// Wait for completion
|
// Wait for completion
|
||||||
@ -236,21 +311,13 @@ int16_t peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_PECI_OVER_ESPI
|
#endif // CONFIG_BUS_ESPI
|
||||||
|
|
||||||
// PECI information can be found here: https://www.intel.com/content/dam/www/public/us/en/documents/design-guides/core-i7-lga-2011-guide.pdf
|
// PECI information can be found here: https://www.intel.com/content/dam/www/public/us/en/documents/design-guides/core-i7-lga-2011-guide.pdf
|
||||||
uint8_t peci_get_fan_duty(void) {
|
uint8_t peci_get_fan_duty(void) {
|
||||||
uint8_t duty;
|
uint8_t duty;
|
||||||
|
|
||||||
#if CONFIG_BUS_ESPI
|
peci_on = peci_available();
|
||||||
// Use PECI if CPU is not in C10 sleep state
|
|
||||||
// HOST_C10 virtual wire is high when CPU is in C10 sleep state
|
|
||||||
peci_on = vw_get(&VW_HOST_C10) == VWS_LOW;
|
|
||||||
#else // CONFIG_BUS_ESPI
|
|
||||||
// Use PECI if in S0 state
|
|
||||||
peci_on = power_state == POWER_STATE_S0;
|
|
||||||
#endif // CONFIG_BUS_ESPI
|
|
||||||
|
|
||||||
if (peci_on) {
|
if (peci_on) {
|
||||||
int16_t peci_offset = 0;
|
int16_t peci_offset = 0;
|
||||||
if (peci_get_temp(&peci_offset)) {
|
if (peci_get_temp(&peci_offset)) {
|
||||||
|
@ -338,13 +338,7 @@ static bool power_peci_limit(bool ac) {
|
|||||||
// Set the power draw limit depending on if on AC or DC power
|
// Set the power draw limit depending on if on AC or DC power
|
||||||
void power_set_limit(void) {
|
void power_set_limit(void) {
|
||||||
static bool last_power_limit_ac = true;
|
static bool last_power_limit_ac = true;
|
||||||
// We don't use power_state because the latency needs to be low
|
if (peci_available()) {
|
||||||
#if CONFIG_BUS_ESPI
|
|
||||||
// HOST_C10 virtual wire is high when CPU is in C10 sleep state
|
|
||||||
if (vw_get(&VW_HOST_C10) == VWS_LOW) {
|
|
||||||
#else // CONFIG_BUS_ESPI
|
|
||||||
if (gpio_get(&BUF_PLT_RST_N)) {
|
|
||||||
#endif // CONFIG_BUS_ESPI
|
|
||||||
bool ac = !gpio_get(&ACIN_N);
|
bool ac = !gpio_get(&ACIN_N);
|
||||||
if (last_power_limit_ac != ac) {
|
if (last_power_limit_ac != ac) {
|
||||||
if (power_peci_limit(ac)) {
|
if (power_peci_limit(ac)) {
|
||||||
|
@ -34,9 +34,6 @@ CFLAGS+=\
|
|||||||
-DCHARGER_CHARGE_VOLTAGE=17600 \
|
-DCHARGER_CHARGE_VOLTAGE=17600 \
|
||||||
-DCHARGER_INPUT_CURRENT=11500
|
-DCHARGER_INPUT_CURRENT=11500
|
||||||
|
|
||||||
# Use PECI over ESPI
|
|
||||||
CFLAGS+=-DUSE_PECI_OVER_ESPI=1
|
|
||||||
|
|
||||||
# Set CPU power limits in watts
|
# Set CPU power limits in watts
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DPOWER_LIMIT_AC=230 \
|
-DPOWER_LIMIT_AC=230 \
|
||||||
|
Reference in New Issue
Block a user