Move power limit functions to common board code

Logic for changing power limit is the same for all boards with GPUs. It
is still called from board_event() instead of in power_event() to
maintain the current behavior of checking every main cycle.

Signed-off-by: Tim Crawford <tcrawford@system76.com>
This commit is contained in:
Tim Crawford 2021-06-10 15:05:15 -06:00 committed by Jeremy Soller
parent 3f446e5c6e
commit a8229d9e62
16 changed files with 52 additions and 318 deletions

View File

@ -7,7 +7,6 @@
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
@ -32,44 +31,8 @@ void board_init(void) {
gpio_set(&SWI_N, true);
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
if (main_cycle == 0) {
// Set keyboard LEDs

View File

@ -30,44 +30,8 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
// Read POST codes
while (P80H81HS & 1) {

View File

@ -7,7 +7,6 @@
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
@ -35,44 +34,8 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
// Read POST codes
while (P80H81HS & 1) {

View File

@ -7,6 +7,5 @@
void board_init(void);
void board_event(void);
void board_on_ac(bool ac);
#endif // _BOARD_BOARD_H

View File

@ -17,6 +17,7 @@ extern enum PowerState power_state;
void power_on_ds5(void);
void power_on_s5(void);
void power_off_s5(void);
void power_set_limit(void);
void power_cpu_reset(void);
void power_event(void);

View File

@ -10,6 +10,7 @@
#include <board/gpio.h>
#include <board/kbled.h>
#include <board/lid.h>
#include <board/peci.h>
#include <board/power.h>
#include <board/pmc.h>
#include <board/pnp.h>
@ -350,6 +351,47 @@ void power_off_s5(void) {
update_power_state();
}
#ifdef HAVE_DGPU
static void power_peci_limit(bool ac) {
uint8_t watts = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
// Set PL4 using PECI
int res = peci_wr_pkg_config(60, 0, ((uint32_t)watts) * 8);
DEBUG("power_peci_limit %d = %d\n", watts, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("power_peci_limit failed: 0x%02X\n", -res);
} else {
ERROR("power_peci_limit unknown response: 0x%02X\n", res);
}
}
}
// Set the power draw limit depending on if on AC or DC power
void power_set_limit(void) {
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
#if EC_ESPI
if (gpio_get(&CPU_C10_GATE_N)) {
#else
if (gpio_get(&BUF_PLT_RST_N)) {
#endif
bool ac = !gpio_get(&ACIN_N);
if (last_power_limit_ac != ac) {
power_peci_limit(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
}
#else
static void power_peci_limit(bool ac) { ac = ac; }
void power_set_limit(void) {}
#endif // HAVE_DGPU
// This function is run when the CPU is reset
void power_cpu_reset(void) {
// LPC was just reset, enable PNP devices
@ -378,7 +420,7 @@ void power_event(void) {
static bool ac_last = true;
bool ac_new = gpio_get(&ACIN_N);
if (ac_new != ac_last) {
board_on_ac(!ac_new);
power_peci_limit(!ac_new);
DEBUG("Power adapter ");
if (ac_new) {

View File

@ -25,6 +25,4 @@ void board_init(void) {
gpio_set(&SWI_N, true);
}
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
void board_event(void) {}

View File

@ -31,8 +31,6 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
void board_event(void) {
espi_event();

View File

@ -25,6 +25,4 @@ void board_init(void) {
gpio_set(&SWI_N, true);
}
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
void board_event(void) {}

View File

@ -6,7 +6,6 @@
#include <board/espi.h>
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
@ -38,48 +37,9 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
#if HAVE_DGPU
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
#else // HAVE_DGPU
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
#endif // HAVE_DGPU
void board_event(void) {
#if HAVE_DGPU
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&CPU_C10_GATE_N)) {
bool ac = !gpio_get(&ACIN_N);
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
#endif // HAVE_DGPU
espi_event();

View File

@ -7,7 +7,6 @@
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
@ -31,44 +30,8 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
// Read POST codes
while (P80H81HS & 1) {

View File

@ -33,8 +33,6 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
void board_event(void) {
espi_event();

View File

@ -25,8 +25,6 @@ void board_init(void) {
gpio_set(&SWI_N, true);
}
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
void board_event(void) {
if (main_cycle == 0) {
if (power_state == POWER_STATE_S0 || power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) {

View File

@ -7,7 +7,6 @@
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
@ -32,42 +31,6 @@ void board_init(void) {
gpio_set(&SWI_N, true);
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
}

View File

@ -7,7 +7,6 @@
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
@ -35,44 +34,8 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
// Read POST codes
while (P80H81HS & 1) {

View File

@ -7,7 +7,6 @@
#include <board/gctrl.h>
#include <board/gpio.h>
#include <board/kbc.h>
#include <board/peci.h>
#include <board/power.h>
#include <common/debug.h>
@ -34,44 +33,8 @@ void board_init(void) {
SPCTRL1 |= 0xC8;
}
// Set PL4 using PECI
static int set_power_limit(uint8_t watts) {
return peci_wr_pkg_config(
60, // index
0, // param
((uint32_t)watts) * 8
);
}
void board_on_ac(bool ac) {
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
// Retry, timeout errors happen occasionally
for (int i = 0; i < 16; i++) {
int res = set_power_limit(power_limit);
DEBUG("set_power_limit %d = %d\n", power_limit, res);
if (res == 0x40) {
break;
} else if (res < 0) {
ERROR("set_power_limit failed: 0x%02X\n", -res);
} else {
ERROR("set_power_limit unknown response: 0x%02X\n", res);
}
}
}
void board_event(void) {
bool ac = !gpio_get(&ACIN_N);
static bool last_power_limit_ac = true;
// We don't use power_state because the latency needs to be low
if (gpio_get(&BUF_PLT_RST_N)) {
if (last_power_limit_ac != ac) {
board_on_ac(ac);
last_power_limit_ac = ac;
}
} else {
last_power_limit_ac = true;
}
power_set_limit();
// Read POST codes
while (P80H81HS & 1) {