Set power limits on AC plug event
This commit is contained in:
committed by
Jeremy Soller
parent
5a8653ef08
commit
90bdcb3818
45
power.sh
45
power.sh
@ -2,13 +2,10 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
./ectool.sh info
|
has_ec=0
|
||||||
sudo modprobe msr
|
if ./ectool.sh info 2> /dev/null
|
||||||
|
|
||||||
header=1
|
|
||||||
if [ -e power.csv ]
|
|
||||||
then
|
then
|
||||||
header=0
|
has_ec=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
has_dgpu=0
|
has_dgpu=0
|
||||||
@ -17,6 +14,14 @@ then
|
|||||||
has_dgpu=1
|
has_dgpu=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sudo modprobe msr
|
||||||
|
|
||||||
|
header=1
|
||||||
|
if [ -e power.csv ]
|
||||||
|
then
|
||||||
|
header=0
|
||||||
|
fi
|
||||||
|
|
||||||
while true
|
while true
|
||||||
do
|
do
|
||||||
if [ "${header}" == "1" ]
|
if [ "${header}" == "1" ]
|
||||||
@ -29,12 +34,18 @@ do
|
|||||||
F="${F}\tCPU C"
|
F="${F}\tCPU C"
|
||||||
F="${F}\tCPU TCC"
|
F="${F}\tCPU TCC"
|
||||||
F="${F}\tCPU TJM"
|
F="${F}\tCPU TJM"
|
||||||
F="${F}\tCPU FAN"
|
if [ "${has_ec}" == "1" ]
|
||||||
|
then
|
||||||
|
F="${F}\tCPU FAN"
|
||||||
|
fi
|
||||||
if [ "${has_dgpu}" == "1" ]
|
if [ "${has_dgpu}" == "1" ]
|
||||||
then
|
then
|
||||||
F="${F}\tGPU W"
|
F="${F}\tGPU W"
|
||||||
F="${F}\tGPU C"
|
F="${F}\tGPU C"
|
||||||
F="${F}\tGPU FAN"
|
if [ "${has_ec}" == "1" ]
|
||||||
|
then
|
||||||
|
F="${F}\tGPU FAN"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
F="$(date "+%T")"
|
F="$(date "+%T")"
|
||||||
@ -71,9 +82,12 @@ do
|
|||||||
F="${F}\t$(printf "%d" "${TCC}")"
|
F="${F}\t$(printf "%d" "${TCC}")"
|
||||||
F="${F}\t$(printf "%d" "${TJMAX}")"
|
F="${F}\t$(printf "%d" "${TJMAX}")"
|
||||||
|
|
||||||
D="$(sudo tool/target/release/system76_ectool fan 0)"
|
if [ "${has_ec}" == "1" ]
|
||||||
P="$(echo "(${D} * 100)/255" | bc -lq)"
|
then
|
||||||
F="${F}\t$(printf "%.0f" "${P}")"
|
D="$(sudo tool/target/release/system76_ectool fan 0)"
|
||||||
|
P="$(echo "(${D} * 100)/255" | bc -lq)"
|
||||||
|
F="${F}\t$(printf "%.0f" "${P}")"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "${has_dgpu}" == "1" ]
|
if [ "${has_dgpu}" == "1" ]
|
||||||
then
|
then
|
||||||
@ -83,9 +97,12 @@ do
|
|||||||
DGPU_T="$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader)"
|
DGPU_T="$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader)"
|
||||||
F="${F}\t${DGPU_T}"
|
F="${F}\t${DGPU_T}"
|
||||||
|
|
||||||
D="$(sudo tool/target/release/system76_ectool fan 1)"
|
if [ "${has_ec}" == "1" ]
|
||||||
P="$(echo "(${D} * 100)/255" | bc -lq)"
|
then
|
||||||
F="${F}\t$(printf "%.0f" "${P}")"
|
D="$(sudo tool/target/release/system76_ectool fan 1)"
|
||||||
|
P="$(echo "(${D} * 100)/255" | bc -lq)"
|
||||||
|
F="${F}\t$(printf "%.0f" "${P}")"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <board/dgpu.h>
|
#include <board/dgpu.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbc.h>
|
#include <board/kbc.h>
|
||||||
|
#include <board/peci.h>
|
||||||
#include <board/power.h>
|
#include <board/power.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
|
||||||
@ -25,10 +26,36 @@ void board_init(void) {
|
|||||||
dgpu_init();
|
dgpu_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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_event(void) {
|
void board_event(void) {
|
||||||
|
bool acin = !gpio_get(&ACIN_N);
|
||||||
|
gpio_set(&AC_PRESENT, acin);
|
||||||
|
|
||||||
|
static uint8_t last_power_limit = 0;
|
||||||
|
if (power_state == POWER_STATE_S0) {
|
||||||
|
uint8_t power_limit = acin ? POWER_LIMIT_AC : POWER_LIMIT_DC;
|
||||||
|
if (power_limit != last_power_limit) {
|
||||||
|
int res = set_power_limit(power_limit);
|
||||||
|
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
||||||
|
if (res >= 0) {
|
||||||
|
last_power_limit = power_limit;
|
||||||
|
} else {
|
||||||
|
ERROR("set_power_limit failed: %X\n", -res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
last_power_limit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (main_cycle == 0) {
|
if (main_cycle == 0) {
|
||||||
bool acin = !gpio_get(&ACIN_N);
|
|
||||||
gpio_set(&AC_PRESENT, acin);
|
|
||||||
if (acin) {
|
if (acin) {
|
||||||
// Discharging (no AC adapter)
|
// Discharging (no AC adapter)
|
||||||
gpio_set(&LED_BAT_CHG, false);
|
gpio_set(&LED_BAT_CHG, false);
|
||||||
|
@ -31,6 +31,11 @@ CFLAGS+=\
|
|||||||
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
||||||
-DCHARGER_INPUT_CURRENT=11800
|
-DCHARGER_INPUT_CURRENT=11800
|
||||||
|
|
||||||
|
# Set CPU power limits in watts
|
||||||
|
CFLAGS+=\
|
||||||
|
-DPOWER_LIMIT_AC=180 \
|
||||||
|
-DPOWER_LIMIT_DC=28
|
||||||
|
|
||||||
# Enable debug logging over keyboard parallel port
|
# Enable debug logging over keyboard parallel port
|
||||||
#CFLAGS+=-DPARPORT_DEBUG
|
#CFLAGS+=-DPARPORT_DEBUG
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ void dgpu_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dgpu_event(void) {
|
void dgpu_event(void) {
|
||||||
if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN)) {
|
if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) {
|
||||||
// Use I2CS if in S0 state
|
// Use I2CS if in S0 state
|
||||||
int8_t rlts;
|
int8_t rlts;
|
||||||
int res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1);
|
int res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1);
|
||||||
|
@ -11,6 +11,7 @@ struct Gpio __code DD_ON = GPIO(E, 4);
|
|||||||
struct Gpio __code DGPU_PWR_EN = GPIO(H, 4);
|
struct Gpio __code DGPU_PWR_EN = GPIO(H, 4);
|
||||||
struct Gpio __code EC_EN = GPIO(B, 6); // renamed to SUSBC_EN
|
struct Gpio __code EC_EN = GPIO(B, 6); // renamed to SUSBC_EN
|
||||||
struct Gpio __code EC_RSMRST_N = GPIO(E, 5);
|
struct Gpio __code EC_RSMRST_N = GPIO(E, 5);
|
||||||
|
struct Gpio __code GC6_FB_EN = GPIO(H, 3);
|
||||||
struct Gpio __code LED_ACIN = GPIO(C, 7);
|
struct Gpio __code LED_ACIN = GPIO(C, 7);
|
||||||
struct Gpio __code LED_AIRPLANE_N = GPIO(H, 7);
|
struct Gpio __code LED_AIRPLANE_N = GPIO(H, 7);
|
||||||
struct Gpio __code LED_CAP_N = GPIO(J, 2);
|
struct Gpio __code LED_CAP_N = GPIO(J, 2);
|
||||||
|
@ -22,6 +22,7 @@ extern struct Gpio __code DD_ON;
|
|||||||
extern struct Gpio __code DGPU_PWR_EN;
|
extern struct Gpio __code DGPU_PWR_EN;
|
||||||
extern struct Gpio __code EC_EN; // renamed to SUSBC_EN
|
extern struct Gpio __code EC_EN; // renamed to SUSBC_EN
|
||||||
extern struct Gpio __code EC_RSMRST_N;
|
extern struct Gpio __code EC_RSMRST_N;
|
||||||
|
extern struct Gpio __code GC6_FB_EN;
|
||||||
extern struct Gpio __code LED_ACIN;
|
extern struct Gpio __code LED_ACIN;
|
||||||
extern struct Gpio __code LED_AIRPLANE_N;
|
extern struct Gpio __code LED_AIRPLANE_N;
|
||||||
extern struct Gpio __code LED_CAP_N;
|
extern struct Gpio __code LED_CAP_N;
|
||||||
|
@ -10,6 +10,7 @@ extern uint8_t peci_tcontrol;
|
|||||||
extern uint8_t peci_tjmax;
|
extern uint8_t peci_tjmax;
|
||||||
|
|
||||||
void peci_init(void);
|
void peci_init(void);
|
||||||
|
int peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data);
|
||||||
void peci_event(void);
|
void peci_event(void);
|
||||||
|
|
||||||
#endif // _BOARD_PECI_H
|
#endif // _BOARD_PECI_H
|
||||||
|
@ -123,6 +123,57 @@ void peci_init(void) {
|
|||||||
PADCTLR = 0x02;
|
PADCTLR = 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns positive completion code on success, negative completion code or
|
||||||
|
// negative (0x1000 | status register) on PECI hardware error
|
||||||
|
int peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data) {
|
||||||
|
// Wait for completion
|
||||||
|
while (HOSTAR & 1) {}
|
||||||
|
// Clear status
|
||||||
|
HOSTAR = HOSTAR;
|
||||||
|
|
||||||
|
// Enable PECI, clearing data fifo's, enable AW_FCS
|
||||||
|
HOCTLR = (1 << 5) | (1 << 3) | (1 << 1);
|
||||||
|
// Set address to default
|
||||||
|
HOTRADDR = 0x30;
|
||||||
|
// Set write length
|
||||||
|
HOWRLR = 10;
|
||||||
|
// Set read length
|
||||||
|
HORDLR = 1;
|
||||||
|
// Set command
|
||||||
|
HOCMDR = 0xA5;
|
||||||
|
|
||||||
|
// Write host ID
|
||||||
|
HOWRDR = 0;
|
||||||
|
// Write index
|
||||||
|
HOWRDR = index;
|
||||||
|
// Write param
|
||||||
|
HOWRDR = (uint8_t)param;
|
||||||
|
HOWRDR = (uint8_t)(param >> 8);
|
||||||
|
// Write data
|
||||||
|
HOWRDR = (uint8_t)data;
|
||||||
|
HOWRDR = (uint8_t)(data >> 8);
|
||||||
|
HOWRDR = (uint8_t)(data >> 16);
|
||||||
|
HOWRDR = (uint8_t)(data >> 24);
|
||||||
|
|
||||||
|
// Start transaction
|
||||||
|
HOCTLR |= 1;
|
||||||
|
|
||||||
|
// Wait for completion
|
||||||
|
while (HOSTAR & 1) {}
|
||||||
|
|
||||||
|
int status = (int)HOSTAR;
|
||||||
|
if (status & (1 << 1)) {
|
||||||
|
int cc = (int)HORDDR;
|
||||||
|
if (cc & 0x80) {
|
||||||
|
return -cc;
|
||||||
|
} else {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -(0x1000 | status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
void peci_event(void) {
|
void peci_event(void) {
|
||||||
if (power_state == POWER_STATE_S0) {
|
if (power_state == POWER_STATE_S0) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <board/dgpu.h>
|
#include <board/dgpu.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbc.h>
|
#include <board/kbc.h>
|
||||||
|
#include <board/peci.h>
|
||||||
#include <board/power.h>
|
#include <board/power.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
|
||||||
@ -26,10 +27,36 @@ void board_init(void) {
|
|||||||
dgpu_init();
|
dgpu_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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_event(void) {
|
void board_event(void) {
|
||||||
|
bool acin = !gpio_get(&ACIN_N);
|
||||||
|
gpio_set(&AC_PRESENT, acin);
|
||||||
|
|
||||||
|
static uint8_t last_power_limit = 0;
|
||||||
|
if (power_state == POWER_STATE_S0) {
|
||||||
|
uint8_t power_limit = acin ? POWER_LIMIT_AC : POWER_LIMIT_DC;
|
||||||
|
if (power_limit != last_power_limit) {
|
||||||
|
int res = set_power_limit(power_limit);
|
||||||
|
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
||||||
|
if (res >= 0) {
|
||||||
|
last_power_limit = power_limit;
|
||||||
|
} else {
|
||||||
|
ERROR("set_power_limit failed: %X\n", -res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
last_power_limit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (main_cycle == 0) {
|
if (main_cycle == 0) {
|
||||||
bool acin = !gpio_get(&ACIN_N);
|
|
||||||
gpio_set(&AC_PRESENT, acin);
|
|
||||||
if (acin) {
|
if (acin) {
|
||||||
// Discharging (no AC adapter)
|
// Discharging (no AC adapter)
|
||||||
gpio_set(&LED_BAT_CHG, false);
|
gpio_set(&LED_BAT_CHG, false);
|
||||||
|
@ -31,6 +31,11 @@ CFLAGS+=\
|
|||||||
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
||||||
-DCHARGER_INPUT_CURRENT=9230
|
-DCHARGER_INPUT_CURRENT=9230
|
||||||
|
|
||||||
|
# Set CPU power limits in watts
|
||||||
|
CFLAGS+=\
|
||||||
|
-DPOWER_LIMIT_AC=180 \
|
||||||
|
-DPOWER_LIMIT_DC=28
|
||||||
|
|
||||||
# Enable debug logging over keyboard parallel port
|
# Enable debug logging over keyboard parallel port
|
||||||
#CFLAGS+=-DPARPORT_DEBUG
|
#CFLAGS+=-DPARPORT_DEBUG
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ void dgpu_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dgpu_event(void) {
|
void dgpu_event(void) {
|
||||||
if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN)) {
|
if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) {
|
||||||
// Use I2CS if in S0 state
|
// Use I2CS if in S0 state
|
||||||
int8_t rlts;
|
int8_t rlts;
|
||||||
int res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1);
|
int res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1);
|
||||||
|
@ -11,6 +11,7 @@ struct Gpio __code CCD_EN = GPIO(D, 1);
|
|||||||
struct Gpio __code DD_ON = GPIO(E, 4);
|
struct Gpio __code DD_ON = GPIO(E, 4);
|
||||||
struct Gpio __code DGPU_PWR_EN = GPIO(J, 2);
|
struct Gpio __code DGPU_PWR_EN = GPIO(J, 2);
|
||||||
struct Gpio __code EC_RSMRST_N = GPIO(E, 5);
|
struct Gpio __code EC_RSMRST_N = GPIO(E, 5);
|
||||||
|
struct Gpio __code GC6_FB_EN = GPIO(J, 3);
|
||||||
struct Gpio __code LED_ACIN = GPIO(C, 7);
|
struct Gpio __code LED_ACIN = GPIO(C, 7);
|
||||||
struct Gpio __code LED_AIRPLANE_N = GPIO(H, 7);
|
struct Gpio __code LED_AIRPLANE_N = GPIO(H, 7);
|
||||||
struct Gpio __code LED_BAT_CHG = GPIO(H, 5);
|
struct Gpio __code LED_BAT_CHG = GPIO(H, 5);
|
||||||
|
@ -23,6 +23,7 @@ extern struct Gpio __code DD_ON;
|
|||||||
extern struct Gpio __code DGPU_PWR_EN;
|
extern struct Gpio __code DGPU_PWR_EN;
|
||||||
#define HAVE_EC_EN 0
|
#define HAVE_EC_EN 0
|
||||||
extern struct Gpio __code EC_RSMRST_N;
|
extern struct Gpio __code EC_RSMRST_N;
|
||||||
|
extern struct Gpio __code GC6_FB_EN;
|
||||||
extern struct Gpio __code LED_ACIN;
|
extern struct Gpio __code LED_ACIN;
|
||||||
extern struct Gpio __code LED_AIRPLANE_N;
|
extern struct Gpio __code LED_AIRPLANE_N;
|
||||||
extern struct Gpio __code LED_BAT_CHG;
|
extern struct Gpio __code LED_BAT_CHG;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <board/dgpu.h>
|
#include <board/dgpu.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbc.h>
|
#include <board/kbc.h>
|
||||||
|
#include <board/peci.h>
|
||||||
#include <board/power.h>
|
#include <board/power.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
|
||||||
@ -28,10 +29,36 @@ void board_init(void) {
|
|||||||
dgpu_init();
|
dgpu_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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_event(void) {
|
void board_event(void) {
|
||||||
|
bool acin = !gpio_get(&ACIN_N);
|
||||||
|
gpio_set(&AC_PRESENT, acin);
|
||||||
|
|
||||||
|
static uint8_t last_power_limit = 0;
|
||||||
|
if (power_state == POWER_STATE_S0) {
|
||||||
|
uint8_t power_limit = acin ? POWER_LIMIT_AC : POWER_LIMIT_DC;
|
||||||
|
if (power_limit != last_power_limit) {
|
||||||
|
int res = set_power_limit(power_limit);
|
||||||
|
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
||||||
|
if (res >= 0) {
|
||||||
|
last_power_limit = power_limit;
|
||||||
|
} else {
|
||||||
|
ERROR("set_power_limit failed: %X\n", -res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
last_power_limit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (main_cycle == 0) {
|
if (main_cycle == 0) {
|
||||||
bool acin = !gpio_get(&ACIN_N);
|
|
||||||
gpio_set(&AC_PRESENT, acin);
|
|
||||||
if (acin) {
|
if (acin) {
|
||||||
// Discharging (no AC adapter)
|
// Discharging (no AC adapter)
|
||||||
gpio_set(&LED_BAT_CHG, false);
|
gpio_set(&LED_BAT_CHG, false);
|
||||||
|
@ -31,6 +31,11 @@ CFLAGS+=\
|
|||||||
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
||||||
-DCHARGER_INPUT_CURRENT=13050
|
-DCHARGER_INPUT_CURRENT=13050
|
||||||
|
|
||||||
|
# Set CPU power limits in watts
|
||||||
|
CFLAGS+=\
|
||||||
|
-DPOWER_LIMIT_AC=180 \
|
||||||
|
-DPOWER_LIMIT_DC=28
|
||||||
|
|
||||||
# Enable debug logging over keyboard parallel port
|
# Enable debug logging over keyboard parallel port
|
||||||
#CFLAGS+=-DPARPORT_DEBUG
|
#CFLAGS+=-DPARPORT_DEBUG
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user