diff options
-rw-r--r-- | src/acpi/acpigen_dptf.c | 46 | ||||
-rw-r--r-- | src/drivers/intel/dptf/chip.h | 1 | ||||
-rw-r--r-- | src/drivers/intel/dptf/dptf.c | 1 | ||||
-rw-r--r-- | src/include/acpi/acpigen_dptf.h | 27 |
4 files changed, 75 insertions, 0 deletions
diff --git a/src/acpi/acpigen_dptf.c b/src/acpi/acpigen_dptf.c index 6caf8bfcaf..9be3f5be8f 100644 --- a/src/acpi/acpigen_dptf.c +++ b/src/acpi/acpigen_dptf.c @@ -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 */ +} diff --git a/src/drivers/intel/dptf/chip.h b/src/drivers/intel/dptf/chip.h index cc4ae47caf..0d2c25cf61 100644 --- a/src/drivers/intel/dptf/chip.h +++ b/src/drivers/intel/dptf/chip.h @@ -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; }; diff --git a/src/drivers/intel/dptf/dptf.c b/src/drivers/intel/dptf/dptf.c index bfc04200e0..15a7d1297b 100644 --- a/src/drivers/intel/dptf/dptf.c +++ b/src/drivers/intel/dptf/dptf.c @@ -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)); } diff --git a/src/include/acpi/acpigen_dptf.h b/src/include/acpi/acpigen_dptf.h index 3452f79578..474f72cd71 100644 --- a/src/include/acpi/acpigen_dptf.h +++ b/src/include/acpi/acpigen_dptf.h @@ -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); |