Tim Wawrzynczak has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/41885 )
Change subject: dptf: Add support for generation of Active Policies ......................................................................
dptf: Add support for generation of Active Policies
This change adds support for generating the different pieces of DPTF Active Policies. This includes the Active Relationship Table, in addition to _ACx methods.
BUG=b:143539650 TEST=compiles
Change-Id: Iea0ccbd96f88d0f3a8f2c77a7d0f3a284e5ee463 Signed-off-by: Tim Wawrzynczak twawrzynczak@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, 204 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/85/41885/1
diff --git a/src/acpi/acpigen_dptf.c b/src/acpi/acpigen_dptf.c index d0827b6..dfe5337 100644 --- a/src/acpi/acpigen_dptf.c +++ b/src/acpi/acpigen_dptf.c @@ -13,6 +13,70 @@ #define DPTF_CRITICAL_POLICY_UUID "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" #define DPTF_ACTIVE_POLICY_UUID "3A95C389-E4B8-4629-A526-C52C88626BAE"
+/* Defaults */ +enum { + ART_REVISION = 0, + DEFAULT_WEIGHT = 100, + DPTF_MAX_ART_THRESHOLDS = 10, +}; + +/* Convert degrees C to 1/10 degree Kelvin for ACPI */ +static int to_acpi_temp(int deg_c) +{ + return deg_c * 10 + 2732; +} + +/* Writes out a 0-argument non-Serialized Method that returns an Integer */ +static void write_simple_return_method(const char *name, int value) +{ + acpigen_write_method(name, 0); + acpigen_write_return_integer(value); + acpigen_pop_len(); /* Method */ +} + +/* Return the assigned namestring of any participant */ +static const char *namestring_of(enum dptf_participant participant) +{ + switch (participant) { + case DPTF_CPU: + return "TCPU"; + case DPTF_CHARGER: + return "TCHG"; + case DPTF_FAN: + return "TFN1"; + case DPTF_TSR0: + return "TSR0"; + case DPTF_TSR1: + return "TSR1"; + case DPTF_TSR2: + return "TSR2"; + case DPTF_TSR3: + return "TSR3"; + default: + return ""; + } +} + +/* Helper to get Scope for participants underneath _SB.DPTF */ +static const char *scope_of(enum dptf_participant participant) +{ + static char scope[16]; + + if (participant == DPTF_CPU) + snprintf(scope, sizeof(scope), "\_SB.%s", namestring_of(participant)); + else + snprintf(scope, sizeof(scope), TOPLEVEL_DPTF_SCOPE ".%s", + namestring_of(participant)); + + return scope; +} + +/* Write out scope of a participant */ +void dptf_write_scope(enum dptf_participant participant) +{ + acpigen_write_scope(scope_of(participant)); +} + /* * Almost all Intel boards use a Global NVS field named DPTE. * Writes out a _STA that checks if \DPTE is 1, and returns 0xF if true, 0x0 otherwise. @@ -68,3 +132,98 @@ acpigen_pop_len(); /* Package */ acpigen_pop_len(); /* Scope */ } + +/* + * This table describes active cooling relationships between the system's fan and the + * temperature sensors that it can have an effect on. As ever-increasing temperature thresholds + * are crossed (_AC9.._AC0, low to high), the corresponding fan percentages listed in this table + * are used to increase the speed of the fan in order to speed up cooling. + */ +static void write_active_relationship_table(const struct dptf_active_policy *policies, int max_count) +{ + char *pkg_count; + int i, j; + + /* Nothing to do */ + if (!max_count || policies[0].target == DPTF_NONE) + return; + + acpigen_write_scope(TOPLEVEL_DPTF_SCOPE); + acpigen_write_method("_ART", 0); + + /* Return this package */ + acpigen_emit_byte(RETURN_OP); + + /* Keep track of items added to the package */ + pkg_count = acpigen_write_package(1); /* The '1' here is for the revision */ + acpigen_write_integer(ART_REVISION); + + for (i = 0; i < max_count; ++i) + { + /* + * These have to be filled out from AC0 down to AC9, filling in only as many + * as are used. As soon as one isn't filled in, we're done. + */ + if (policies[i].target == DPTF_NONE) + break; + + (*pkg_count)++; + + /* Source, Target, Percent, Fan % for each of _AC0 ... _AC9 */ + acpigen_write_package(13); + acpigen_emit_namestring(namestring_of(DPTF_FAN)); + acpigen_emit_namestring(namestring_of(policies[i].target)); + acpigen_write_integer(DEFAULT_IF_0(policies[i].weight, DEFAULT_WEIGHT)); + + /* Write out fan %; corresponds with target's _ACx methods */ + for (j = 0; j < DPTF_MAX_ART_THRESHOLDS; ++j) + acpigen_write_integer(policies[i].thresholds[j].fan_pct); + + acpigen_pop_len(); /* inner Package */ + } + + acpigen_pop_len(); /* outer Package */ + acpigen_pop_len(); /* Method _ART */ + acpigen_pop_len(); /* Scope */ +} + +/* + * _AC9 through _AC0 represent temperature thresholds, in increasing order, defined from _AC0 + * down, that, when reached, DPTF will activate TFN1 in order to actively cool the temperature + * sensor(s). As increasing thresholds are reached, the fan is spun faster. + */ +static void write_active_cooling_methods(const struct dptf_active_policy *policies, + int max_count) +{ + char name[5]; + int i, j; + + /* Nothing to do */ + if (!max_count || policies[0].target == DPTF_NONE) + return; + + for (i = 0; i < max_count; ++i) { + if (policies[i].target == DPTF_NONE) + break; + + dptf_write_scope(policies[i].target); + + /* Write out as many of _AC0 through _AC9 that are applicable */ + for (j = 0; j < DPTF_MAX_ACX; ++j) { + if (!policies[i].thresholds[j].temp) + break; + + snprintf(name, sizeof(name), "_AC%1X", j); + write_simple_return_method(name, to_acpi_temp( + policies[i].thresholds[j].temp)); + } + + acpigen_pop_len(); /* Scope */ + } +} + +void dptf_write_active_policies(const struct dptf_active_policy *policies, int max_count) +{ + write_active_relationship_table(policies, max_count); + write_active_cooling_methods(policies, max_count); +} diff --git a/src/drivers/intel/dptf/chip.h b/src/drivers/intel/dptf/chip.h index 9ab7963..bc4235e 100644 --- a/src/drivers/intel/dptf/chip.h +++ b/src/drivers/intel/dptf/chip.h @@ -9,6 +9,7 @@ struct drivers_intel_dptf_config { struct { struct dptf_enabled_policies enabled; + struct dptf_active_policy active[DPTF_MAX_ACTIVE_POLICIES]; } policies; };
diff --git a/src/drivers/intel/dptf/dptf.c b/src/drivers/intel/dptf/dptf.c index e3e4efd..a3764fa 100644 --- a/src/drivers/intel/dptf/dptf.c +++ b/src/drivers/intel/dptf/dptf.c @@ -23,6 +23,17 @@ static bool is_participant_used(const struct drivers_intel_dptf_config *config, enum dptf_participant participant) { + int i; + + /* Active? */ + for (i = 0; i < DPTF_MAX_ACTIVE_POLICIES; ++i) + if (config->policies.active[i].target == participant) + return true; + + /* Check fan as well (it's use is implicit in the Active policy) */ + if (participant == DPTF_FAN && config->policies.enabled.active) + return true; + return false; }
@@ -39,6 +50,10 @@ /* Policies */ dptf_write_enabled_policies(&config->policies.enabled);
+ if (config->policies.enabled.active) + dptf_write_active_policies(config->policies.active, + DPTF_MAX_ACTIVE_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 f717296..24dc279 100644 --- a/src/include/acpi/acpigen_dptf.h +++ b/src/include/acpi/acpigen_dptf.h @@ -22,6 +22,13 @@ DPTF_PARTICIPANT_COUNT, };
+/* DPTF compile-time constants */ +enum { + /* A device can only define _AC0 .. _AC9 (i.e., 10) Active Cooling Methods */ + DPTF_MAX_ACX = 10, + DPTF_MAX_ACTIVE_POLICIES = (DPTF_PARTICIPANT_COUNT-1), +}; + /* Which policies are enabled? */ struct dptf_enabled_policies { bool passive; @@ -29,12 +36,34 @@ bool active; };
+/* Active Policy */ +struct dptf_active_policy { + /* Device capable of being affected by the fan */ + enum dptf_participant target; + /* */ + uint8_t weight; + /* When target reaches temperature 'temp', the source will turn on at 'fan_pct' % */ + struct { + /* (degrees C) */ + uint8_t temp; + /* 0 - 100 */ + uint8_t fan_pct; + } thresholds [DPTF_MAX_ACX]; +}; + /* * This function writes out _SB.DPTF.IDSP, which describes the different DPTF policies that * this implementation is using. */ void dptf_write_enabled_policies(const struct dptf_enabled_policies *policies);
+/* + * 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 + * of full speed. + */ +void dptf_write_active_policies(const struct dptf_active_policy *policies, int max_count); + /* Helper method to open the scope for a given participant. */ void dptf_write_scope(enum dptf_participant participant);