aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/acpi/acpigen_dptf.c46
-rw-r--r--src/drivers/intel/dptf/chip.h1
-rw-r--r--src/drivers/intel/dptf/dptf.c1
-rw-r--r--src/include/acpi/acpigen_dptf.h27
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);