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>
This commit is contained in:
parent
c41f7f15c1
commit
7eb1136c27
|
@ -9,6 +9,7 @@
|
|||
/* Defaults */
|
||||
enum {
|
||||
ART_REVISION = 0,
|
||||
DEFAULT_PRIORITY = 100,
|
||||
DEFAULT_WEIGHT = 100,
|
||||
DPTF_MAX_ART_THRESHOLDS = 10,
|
||||
};
|
||||
|
@ -19,6 +20,12 @@ static int to_acpi_temp(int deg_c)
|
|||
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 @@ static void write_simple_return_method(const char *name, int value)
|
|||
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 @@ void dptf_write_active_policies(const struct dptf_active_policy *policies, int m
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -35,6 +35,12 @@ static bool is_participant_used(const struct drivers_intel_dptf_config *config,
|
|||
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 @@ static void dptf_fill_ssdt(const struct device *dev)
|
|||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ enum {
|
|||
/* 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 @@ struct dptf_active_policy {
|
|||
} 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 @@ struct dptf_active_policy {
|
|||
*/
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue