Patrick Georgi has submitted this change. ( https://review.coreboot.org/c/coreboot/+/41886 )
Change subject: dptf: Add support for Passive Policies ......................................................................
dptf: Add support for Passive Policies
This patch adds support for emitting the Thermal Relationship Table, as well as _PSV Methods, which together form the basis for DPTF Passive Policies.
BUG=b:143539650 TEST=compiles
Change-Id: I82e1c9022999b0a2a733aa6cd9c98a850e6f5408 Signed-off-by: Tim Wawrzynczak twawrzynczak@chromium.org Reviewed-on: https://review.coreboot.org/c/coreboot/+/41886 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Duncan Laurie dlaurie@chromium.org --- M src/acpi/acpigen_dptf.c M src/drivers/intel/dptf/chip.h M src/drivers/intel/dptf/dptf.c M src/include/acpi/acpigen_dptf.h 4 files changed, 131 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Duncan Laurie: Looks good to me, approved
diff --git a/src/acpi/acpigen_dptf.c b/src/acpi/acpigen_dptf.c index 74e9191..abd99c1 100644 --- a/src/acpi/acpigen_dptf.c +++ b/src/acpi/acpigen_dptf.c @@ -9,6 +9,7 @@ /* Defaults */ enum { ART_REVISION = 0, + DEFAULT_PRIORITY = 100, DEFAULT_WEIGHT = 100, DPTF_MAX_ART_THRESHOLDS = 10, }; @@ -19,6 +20,12 @@ return deg_c * 10 + 2732; }
+/* Converts ms to 1/10th second for ACPI */ +static int to_acpi_time(int ms) +{ + return ms / 100; +} + /* Writes out a 0-argument non-Serialized Method that returns an Integer */ static void write_simple_return_method(const char *name, int value) { @@ -27,6 +34,13 @@ acpigen_pop_len(); /* Method */ }
+/* Writes out 'count' ZEROs in a row */ +static void write_zeros(int count) +{ + for (; count; --count) + acpigen_write_integer(0); +} + /* Return the assigned namestring of any participant */ static const char *namestring_of(enum dptf_participant participant) { @@ -164,3 +178,87 @@ write_active_relationship_table(policies, max_count); write_active_cooling_methods(policies, max_count); } + +/* + * This writes out the Thermal Relationship Table, which describes the thermal relationships + * between participants in a thermal zone. This information is used to passively cool (i.e., + * throttle) the Source (source of heat), in order to indirectly cool the Target (temperature + * sensor). + */ +static void write_thermal_relationship_table(const struct dptf_passive_policy *policies, + int max_count) +{ + char *pkg_count; + int i; + + /* Nothing to do */ + if (!max_count || policies[0].source == DPTF_NONE) + return; + + acpigen_write_scope(TOPLEVEL_DPTF_SCOPE); + + /* + * A _TRT Revision (TRTR) of 1 means that the 'Priority' field is an arbitrary priority + * value to be used for this specific relationship. The priority value determines the + * order in which various sources are used in a passive thermal action for a given + * target. + */ + acpigen_write_name_integer("TRTR", 1); + + /* Thermal Relationship Table */ + acpigen_write_method("_TRT", 0); + + /* Return this package */ + acpigen_emit_byte(RETURN_OP); + pkg_count = acpigen_write_package(0); + + for (i = 0; i < max_count; ++i) { + /* Stop writing the table once an entry is empty */ + if (policies[i].source == DPTF_NONE) + break; + + /* Keep track of outer package item count */ + (*pkg_count)++; + + acpigen_write_package(8); + + /* Source, Target, Priority, Sampling Period */ + acpigen_emit_namestring(namestring_of(policies[i].source)); + acpigen_emit_namestring(namestring_of(policies[i].target)); + acpigen_write_integer(DEFAULT_IF_0(policies[i].priority, DEFAULT_PRIORITY)); + acpigen_write_integer(to_acpi_time(policies[i].period)); + + /* Reserved */ + write_zeros(4); + + acpigen_pop_len(); /* Package */ + } + + acpigen_pop_len(); /* Package */ + acpigen_pop_len(); /* Method */ + acpigen_pop_len(); /* Scope */ +} + +/* + * When a temperature sensor measures above its the temperature returned in its _PSV Method, + * DPTF will begin throttling Sources in order to indirectly cool the sensor. + */ +static void write_all_PSV(const struct dptf_passive_policy *policies, int max_count) +{ + int i; + + for (i = 0; i < max_count; ++i) { + if (policies[i].source == DPTF_NONE) + break; + + dptf_write_scope(policies[i].target); + write_simple_return_method("_PSV", to_acpi_temp(policies[i].temp)); + acpigen_pop_len(); /* Scope */ + } +} + +void dptf_write_passive_policies(const struct dptf_passive_policy *policies, int max_count) +{ + write_thermal_relationship_table(policies, max_count); + write_all_PSV(policies, max_count); +} diff --git a/src/drivers/intel/dptf/chip.h b/src/drivers/intel/dptf/chip.h index 730d23e..0cd2ad2 100644 --- a/src/drivers/intel/dptf/chip.h +++ b/src/drivers/intel/dptf/chip.h @@ -8,6 +8,7 @@ struct drivers_intel_dptf_config { struct { struct dptf_active_policy active[DPTF_MAX_ACTIVE_POLICIES]; + struct dptf_passive_policy passive[DPTF_MAX_PASSIVE_POLICIES]; } policies; };
diff --git a/src/drivers/intel/dptf/dptf.c b/src/drivers/intel/dptf/dptf.c index 20f8d9b..74f4812 100644 --- a/src/drivers/intel/dptf/dptf.c +++ b/src/drivers/intel/dptf/dptf.c @@ -35,6 +35,12 @@ if (config->policies.active[i].target == participant) return true;
+ /* Passive? */ + for (i = 0; i < DPTF_MAX_PASSIVE_POLICIES; ++i) + if (config->policies.passive[i].source == participant || + config->policies.passive[i].target == participant) + return true; + /* Check fan as well (its use is implicit in the Active policy) */ if (participant == DPTF_FAN && config->policies.active[0].target != DPTF_NONE) return true; @@ -55,6 +61,9 @@ dptf_write_active_policies(config->policies.active, DPTF_MAX_ACTIVE_POLICIES);
+ dptf_write_passive_policies(config->policies.passive, + DPTF_MAX_PASSIVE_POLICIES); + 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 a082b62..214578a 100644 --- a/src/include/acpi/acpigen_dptf.h +++ b/src/include/acpi/acpigen_dptf.h @@ -27,6 +27,7 @@ /* A device can only define _AC0 .. _AC9 i.e. between 0 and 10 Active Cooling Methods */ DPTF_MAX_ACX = 10, DPTF_MAX_ACTIVE_POLICIES = (DPTF_PARTICIPANT_COUNT-1), + DPTF_MAX_PASSIVE_POLICIES = (DPTF_PARTICIPANT_COUNT-1), };
/* Active Policy */ @@ -44,6 +45,20 @@ } thresholds[DPTF_MAX_ACX]; };
+/* Passive Policy */ +struct dptf_passive_policy { + /* The device that can be throttled */ + enum dptf_participant source; + /* The device that controls the throttling */ + enum dptf_participant target; + /* How often to check the temperature for required throttling (ms) */ + uint16_t period; + /* The trip point for turning on throttling (degrees C) */ + uint8_t temp; + /* Relative priority between Policies */ + uint8_t priority; +}; + /* * 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 @@ -51,6 +66,14 @@ */ void dptf_write_active_policies(const struct dptf_active_policy *policies, int max_count);
+/* + * This function uses the definition of the passive policies to write out _PSV Methods on all + * participants that define it. It also writes out the Thermal Relationship Table + * (_SB.DPTF._TRT), which describes various passive (i.e., throttling) policies that can be + * applies when temperature sensors reach the _PSV threshold. + */ +void dptf_write_passive_policies(const struct dptf_passive_policy *policies, int max_count); + /* Helper method to open the scope for a given participant. */ void dptf_write_scope(enum dptf_participant participant);