dptf: Add support for Running Average Power Limits

This change adds support for emitting the PPCC table, which describes
the ranges available as knobs for DPTF to tune. It can support min/max
power, min/max time window for averaging, and the minimum adjustment size
(granularity or step size) of each power limit. The current implementation
only supports PL1 and PL2.

BUG=b:143539650
TEST=compiles

Change-Id: I67e80d661ea5bb79980ef285eca40c9a4b0f1849
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41890
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
This commit is contained in:
Tim Wawrzynczak 2020-05-29 14:46:19 -06:00 committed by Patrick Georgi
parent 2ad8ffed6f
commit bb5c255907
4 changed files with 75 additions and 0 deletions

View File

@ -15,6 +15,9 @@ enum {
DEFAULT_TRIP_POINT = 0xFFFFFFFFull,
DEFAULT_WEIGHT = 100,
DPTF_MAX_ART_THRESHOLDS = 10,
PPCC_REVISION = 2,
RAPL_PL1_INDEX = 0,
RAPL_PL2_INDEX = 1,
};
/* Convert degrees C to 1/10 degree Kelvin for ACPI */
@ -358,3 +361,46 @@ void dptf_write_fan_perf(const struct dptf_fan_perf *states, int max_count)
acpigen_pop_len(); /* Package */
acpigen_pop_len(); /* Scope */
}
void dptf_write_power_limits(const struct dptf_power_limits *limits)
{
char *pkg_count;
/* Nothing to do */
if (!limits->pl1.min_power && !limits->pl2.min_power)
return;
dptf_write_scope(DPTF_CPU);
acpigen_write_method("PPCC", 0);
pkg_count = acpigen_write_package(1); /* 1 for the Revision */
acpigen_write_integer(PPCC_REVISION); /* revision */
if (limits->pl1.min_power) {
(*pkg_count)++;
acpigen_write_package(6);
acpigen_write_integer(RAPL_PL1_INDEX);
acpigen_write_integer(limits->pl1.min_power);
acpigen_write_integer(limits->pl1.max_power);
acpigen_write_integer(limits->pl1.time_window_min);
acpigen_write_integer(limits->pl1.time_window_max);
acpigen_write_integer(limits->pl1.granularity);
acpigen_pop_len(); /* inner Package */
}
if (limits->pl2.min_power) {
(*pkg_count)++;
acpigen_write_package(6);
acpigen_write_integer(RAPL_PL2_INDEX);
acpigen_write_integer(limits->pl2.min_power);
acpigen_write_integer(limits->pl2.max_power);
acpigen_write_integer(limits->pl2.time_window_min);
acpigen_write_integer(limits->pl2.time_window_max);
acpigen_write_integer(limits->pl2.granularity);
acpigen_pop_len(); /* inner Package */
}
acpigen_pop_len(); /* outer Package */
acpigen_pop_len(); /* Method */
acpigen_pop_len(); /* Scope */
}

View File

@ -15,6 +15,7 @@ struct drivers_intel_dptf_config {
struct {
struct dptf_charger_perf charger_perf[DPTF_MAX_CHARGER_PERF_STATES];
struct dptf_fan_perf fan_perf[DPTF_MAX_FAN_PERF_STATES];
struct dptf_power_limits power_limits;
} controls;
};

View File

@ -75,6 +75,7 @@ static void dptf_fill_ssdt(const struct device *dev)
/* Controls */
dptf_write_charger_perf(config->controls.charger_perf, DPTF_MAX_CHARGER_PERF_STATES);
dptf_write_fan_perf(config->controls.fan_perf, DPTF_MAX_FAN_PERF_STATES);
dptf_write_power_limits(&config->controls.power_limits);
printk(BIOS_INFO, "\\_SB.DPTF: %s at %s\n", dev->chip_ops->name, dev_path(dev));
}

View File

@ -103,6 +103,26 @@ struct dptf_fan_perf {
uint16_t power;
};
/* Running Average Power Limits (RAPL) */
struct dptf_power_limit_config {
/* Minimum level of power limit, in mW */
uint32_t min_power;
/* Maximum level of power limit, in mW */
uint32_t max_power;
/* Minimum time window running average is over, in seconds */
uint32_t time_window_min;
/* Maximum time window running average is over, in seconds */
uint32_t time_window_max;
/* Granularity of the power limit setting (between min and max), in mW */
uint16_t granularity;
};
/* Only PL1 and PL2 are controllable via DPTF */
struct dptf_power_limits {
struct dptf_power_limit_config pl1;
struct dptf_power_limit_config pl2;
};
/*
* This function provides tables of temperature and corresponding fan or percent. When the
* temperature thresholds are met (_AC0 - _AC9), the fan is driven to corresponding percentage
@ -142,6 +162,13 @@ void dptf_write_charger_perf(const struct dptf_charger_perf *perf, int max_count
*/
void dptf_write_fan_perf(const struct dptf_fan_perf *perf, int max_count);
/*
* This function writes out a PPCC table, which indicates power ranges that different Intel
* Running Average Power Limits (RAPLs) can take, as well as the time period they average over
* and the minimum adjustment amount.
*/
void dptf_write_power_limits(const struct dptf_power_limits *limits);
/* Helper method to open the scope for a given participant. */
void dptf_write_scope(enum dptf_participant participant);