Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #ifndef ACPI_ACPIGEN_DPTF_H |
| 4 | #define ACPI_ACPIGEN_DPTF_H |
| 5 | |
| 6 | #include <device/device.h> |
| 7 | #include <stdbool.h> |
Elyes HAOUAS | 5817c56 | 2020-07-12 09:03:22 +0200 | [diff] [blame] | 8 | #include <stdint.h> |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 9 | |
| 10 | /* A common idiom is to use a default value if none is provided (i.e., == 0) */ |
| 11 | #define DEFAULT_IF_0(thing, default_) ((thing) ? (thing) : (default_)) |
| 12 | |
Tim Wawrzynczak | 5212ece6 | 2020-07-16 11:54:04 -0600 | [diff] [blame] | 13 | /* Hardcoded paths */ |
| 14 | #define DPTF_DEVICE_PATH "\\_SB.DPTF" |
| 15 | #define TCPU_SCOPE "\\_SB.PCI0" |
| 16 | |
Sumeet Pawnikar | 2f7fa55 | 2022-06-08 17:43:36 +0530 | [diff] [blame] | 17 | #define DPTF_MAX_FAN_PARTICIPANTS 2 |
| 18 | |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 19 | /* List of available participants (i.e., they can participate in policies) */ |
| 20 | enum dptf_participant { |
| 21 | DPTF_NONE, |
| 22 | DPTF_CPU, |
| 23 | DPTF_CHARGER, |
| 24 | DPTF_FAN, |
Sumeet Pawnikar | 2f7fa55 | 2022-06-08 17:43:36 +0530 | [diff] [blame] | 25 | DPTF_FAN_2, |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 26 | DPTF_TEMP_SENSOR_0, |
| 27 | DPTF_TEMP_SENSOR_1, |
| 28 | DPTF_TEMP_SENSOR_2, |
| 29 | DPTF_TEMP_SENSOR_3, |
Tim Wawrzynczak | 40713aa | 2021-11-24 09:18:44 -0700 | [diff] [blame] | 30 | DPTF_TEMP_SENSOR_4, |
Sumeet Pawnikar | e2e0a6b | 2021-09-24 18:39:50 +0530 | [diff] [blame] | 31 | DPTF_TPCH, |
Varshit B Pandya | e7d3a1a | 2022-03-20 20:39:51 +0530 | [diff] [blame] | 32 | DPTF_POWER, |
Varshit B Pandya | 170a76c | 2022-04-02 15:11:36 +0530 | [diff] [blame] | 33 | DPTF_BATTERY, |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 34 | DPTF_PARTICIPANT_COUNT, |
| 35 | }; |
| 36 | |
| 37 | /* DPTF compile-time constants */ |
| 38 | enum { |
| 39 | /* A device can only define _AC0 .. _AC9 i.e. between 0 and 10 Active Cooling Methods */ |
| 40 | DPTF_MAX_ACX = 10, |
| 41 | DPTF_MAX_ACTIVE_POLICIES = (DPTF_PARTICIPANT_COUNT-1), |
Tim Wawrzynczak | 7eb1136 | 2020-05-29 14:10:53 -0600 | [diff] [blame] | 42 | DPTF_MAX_PASSIVE_POLICIES = (DPTF_PARTICIPANT_COUNT-1), |
Tim Wawrzynczak | 3a9cde9 | 2020-05-29 14:19:15 -0600 | [diff] [blame] | 43 | DPTF_MAX_CRITICAL_POLICIES = (DPTF_PARTICIPANT_COUNT-1), |
Tim Wawrzynczak | 46f6fcf | 2020-05-29 14:29:53 -0600 | [diff] [blame] | 44 | |
| 45 | /* Maximum found by automatic inspection (awk) */ |
| 46 | DPTF_MAX_CHARGER_PERF_STATES = 10, |
Dtrain Hsu | 384dfac | 2022-09-07 10:35:06 +0800 | [diff] [blame] | 47 | DPTF_MAX_FAN_PERF_STATES = 20, |
Tim Wawrzynczak | 2ad8ffe | 2020-05-29 14:39:02 -0600 | [diff] [blame] | 48 | |
| 49 | /* From ACPI spec 6.3 */ |
| 50 | DPTF_FIELD_UNUSED = 0xFFFFFFFFull, |
Tim Wawrzynczak | e4d8ebc | 2020-05-29 14:58:16 -0600 | [diff] [blame] | 51 | |
| 52 | /* Max supported by DPTF */ |
Tim Wawrzynczak | 40713aa | 2021-11-24 09:18:44 -0700 | [diff] [blame] | 53 | DPTF_MAX_TSR = 5, |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 54 | }; |
| 55 | |
| 56 | /* Active Policy */ |
| 57 | struct dptf_active_policy { |
Sumeet Pawnikar | 2f7fa55 | 2022-06-08 17:43:36 +0530 | [diff] [blame] | 58 | /* The device that can be throttled */ |
| 59 | enum dptf_participant source; |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 60 | /* Device capable of being affected by the fan */ |
| 61 | enum dptf_participant target; |
| 62 | /* Source's contribution to the Target's cooling capability as a percentage */ |
| 63 | uint8_t weight; |
| 64 | /* When target reaches temperature 'temp', the source will turn on at 'fan_pct' % */ |
| 65 | struct { |
| 66 | /* (degrees C) */ |
| 67 | uint8_t temp; |
| 68 | /* 0 - 100 */ |
| 69 | uint8_t fan_pct; |
| 70 | } thresholds[DPTF_MAX_ACX]; |
| 71 | }; |
| 72 | |
Tim Wawrzynczak | 7eb1136 | 2020-05-29 14:10:53 -0600 | [diff] [blame] | 73 | /* Passive Policy */ |
| 74 | struct dptf_passive_policy { |
| 75 | /* The device that can be throttled */ |
| 76 | enum dptf_participant source; |
| 77 | /* The device that controls the throttling */ |
| 78 | enum dptf_participant target; |
| 79 | /* How often to check the temperature for required throttling (ms) */ |
| 80 | uint16_t period; |
| 81 | /* The trip point for turning on throttling (degrees C) */ |
| 82 | uint8_t temp; |
| 83 | /* Relative priority between Policies */ |
| 84 | uint8_t priority; |
| 85 | }; |
| 86 | |
Tim Wawrzynczak | 3a9cde9 | 2020-05-29 14:19:15 -0600 | [diff] [blame] | 87 | /* Critical Policy type: graceful S4 transition or graceful shutdown */ |
| 88 | enum dptf_critical_policy_type { |
| 89 | DPTF_CRITICAL_S4, |
| 90 | DPTF_CRITICAL_SHUTDOWN, |
| 91 | }; |
| 92 | |
| 93 | /* Critical Policy */ |
| 94 | struct dptf_critical_policy { |
| 95 | /* The device that can trigger a critical event */ |
| 96 | enum dptf_participant source; |
| 97 | /* What type of critical policy */ |
| 98 | enum dptf_critical_policy_type type; |
| 99 | /* Temperature to activate policy, degrees C */ |
| 100 | uint8_t temp; |
| 101 | }; |
| 102 | |
Tim Wawrzynczak | 46f6fcf | 2020-05-29 14:29:53 -0600 | [diff] [blame] | 103 | /* Different levels of charging capability, chosen by passive policies */ |
| 104 | struct dptf_charger_perf { |
| 105 | /* Control value */ |
| 106 | uint8_t control; |
| 107 | /* Charging performance, in mA */ |
| 108 | uint16_t raw_perf; |
| 109 | }; |
| 110 | |
Tim Wawrzynczak | 2ad8ffe | 2020-05-29 14:39:02 -0600 | [diff] [blame] | 111 | /* Different levels of fan activity, chosen by active policies */ |
| 112 | struct dptf_fan_perf { |
| 113 | /* Fan percentage level */ |
| 114 | uint8_t percent; |
| 115 | /* Fan speed, in RPM */ |
| 116 | uint16_t speed; |
| 117 | /* Noise level, in 0.1 dBs */ |
| 118 | uint16_t noise_level; |
| 119 | /* Power in mA */ |
| 120 | uint16_t power; |
| 121 | }; |
| 122 | |
Sumeet Pawnikar | 2f7fa55 | 2022-06-08 17:43:36 +0530 | [diff] [blame] | 123 | /* Different levels of fan activity, chosen by active policies */ |
| 124 | struct dptf_multifan_perf { |
| 125 | /* Fan percentage level */ |
| 126 | uint8_t percent; |
| 127 | /* Fan speed, in RPM */ |
| 128 | uint16_t speed; |
| 129 | /* Noise level, in 0.1 dBs */ |
| 130 | uint16_t noise_level; |
| 131 | /* Power in mA */ |
| 132 | uint16_t power; |
| 133 | }; |
| 134 | |
Tim Wawrzynczak | bb5c255 | 2020-05-29 14:46:19 -0600 | [diff] [blame] | 135 | /* Running Average Power Limits (RAPL) */ |
| 136 | struct dptf_power_limit_config { |
| 137 | /* Minimum level of power limit, in mW */ |
| 138 | uint32_t min_power; |
| 139 | /* Maximum level of power limit, in mW */ |
| 140 | uint32_t max_power; |
| 141 | /* Minimum time window running average is over, in seconds */ |
| 142 | uint32_t time_window_min; |
| 143 | /* Maximum time window running average is over, in seconds */ |
| 144 | uint32_t time_window_max; |
| 145 | /* Granularity of the power limit setting (between min and max), in mW */ |
| 146 | uint16_t granularity; |
| 147 | }; |
| 148 | |
| 149 | /* Only PL1 and PL2 are controllable via DPTF */ |
| 150 | struct dptf_power_limits { |
| 151 | struct dptf_power_limit_config pl1; |
| 152 | struct dptf_power_limit_config pl2; |
| 153 | }; |
| 154 | |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 155 | /* |
Tim Wawrzynczak | 03465f4 | 2020-06-03 16:27:30 -0600 | [diff] [blame] | 156 | * This function writes out \_SB.DPTF.IDSP, which describes the different DPTF policies that |
| 157 | * this implementation is using. |
| 158 | */ |
| 159 | void dptf_write_enabled_policies(const struct dptf_active_policy *active_policies, |
| 160 | int active_count, |
| 161 | const struct dptf_passive_policy *passive_policies, |
| 162 | int passive_count, |
| 163 | const struct dptf_critical_policy *critical_policies, |
| 164 | int critical_count); |
| 165 | |
| 166 | /* |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 167 | * This function provides tables of temperature and corresponding fan or percent. When the |
| 168 | * temperature thresholds are met (_AC0 - _AC9), the fan is driven to corresponding percentage |
| 169 | * of full speed. |
| 170 | */ |
Sumeet Pawnikar | 2f7fa55 | 2022-06-08 17:43:36 +0530 | [diff] [blame] | 171 | void dptf_write_active_policies(const struct dptf_active_policy *policies, int max_count, |
| 172 | bool dptf_multifan_support); |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 173 | |
Tim Wawrzynczak | 7eb1136 | 2020-05-29 14:10:53 -0600 | [diff] [blame] | 174 | /* |
| 175 | * This function uses the definition of the passive policies to write out _PSV Methods on all |
| 176 | * participants that define it. It also writes out the Thermal Relationship Table |
| 177 | * (\_SB.DPTF._TRT), which describes various passive (i.e., throttling) policies that can be |
| 178 | * applies when temperature sensors reach the _PSV threshold. |
| 179 | */ |
| 180 | void dptf_write_passive_policies(const struct dptf_passive_policy *policies, int max_count); |
| 181 | |
Tim Wawrzynczak | 3a9cde9 | 2020-05-29 14:19:15 -0600 | [diff] [blame] | 182 | /* |
| 183 | * Critical policies are temperature thresholds that, when reached, will cause the system to |
| 184 | * take some emergency action in order to eliminate excess temperatures from damaging the |
| 185 | * system. The emergency actions are a graceful suspend or a graceful shutdown. |
| 186 | */ |
| 187 | void dptf_write_critical_policies(const struct dptf_critical_policy *policies, int max_count); |
| 188 | |
Tim Wawrzynczak | 46f6fcf | 2020-05-29 14:29:53 -0600 | [diff] [blame] | 189 | /* |
| 190 | * These are various performance levels for battery charging. They can be used in conjunction |
| 191 | * with passive policies to lower the charging rate when the _PSV threshold is met. |
| 192 | */ |
| 193 | void dptf_write_charger_perf(const struct dptf_charger_perf *perf, int max_count); |
| 194 | |
Tim Wawrzynczak | 2ad8ffe | 2020-05-29 14:39:02 -0600 | [diff] [blame] | 195 | /* |
| 196 | * This function writes an ACPI table describing various performance levels possible for active |
| 197 | * policies. They indicate, for a given fan percentage level: |
| 198 | * 1) What the corresponding speed is (in RPM) |
| 199 | * 2) The expected noise level (in tenths of decibels AKA centibels, or DPTF_FIELD_UNUSED) |
| 200 | * 3) The power consumption (in mW, or DPTF_FIELD_UNUSED to indicate this field is unused). |
| 201 | * 4) The corresponding active cooling trip point (from _ART) (typically left as |
| 202 | * DPTF_FIELD_UNUSED). |
| 203 | */ |
Sumeet Pawnikar | 2f7fa55 | 2022-06-08 17:43:36 +0530 | [diff] [blame] | 204 | void dptf_write_fan_perf(const struct dptf_fan_perf *perf, int max_count, |
| 205 | enum dptf_participant participant); |
| 206 | |
| 207 | void dptf_write_multifan_perf( |
| 208 | const struct dptf_multifan_perf |
| 209 | states[DPTF_MAX_FAN_PARTICIPANTS][DPTF_MAX_FAN_PERF_STATES], |
| 210 | int max_count, enum dptf_participant participant, int fan_num); |
| 211 | |
| 212 | int dptf_write_fan_perf_fps(uint8_t percent, uint16_t power, uint16_t speed, |
| 213 | uint16_t noise_level); |
Tim Wawrzynczak | 2ad8ffe | 2020-05-29 14:39:02 -0600 | [diff] [blame] | 214 | |
Tim Wawrzynczak | bb5c255 | 2020-05-29 14:46:19 -0600 | [diff] [blame] | 215 | /* |
| 216 | * This function writes out a PPCC table, which indicates power ranges that different Intel |
| 217 | * Running Average Power Limits (RAPLs) can take, as well as the time period they average over |
| 218 | * and the minimum adjustment amount. |
| 219 | */ |
| 220 | void dptf_write_power_limits(const struct dptf_power_limits *limits); |
| 221 | |
Tim Wawrzynczak | e4d8ebc | 2020-05-29 14:58:16 -0600 | [diff] [blame] | 222 | /* Set the _STR Name */ |
| 223 | void dptf_write_STR(const char *str); |
| 224 | |
| 225 | /* Set options in the _FIF table */ |
| 226 | void dptf_write_fan_options(bool fine_grained, int step_size, bool low_speed_notify); |
| 227 | |
| 228 | /* |
| 229 | * Sets the amount of inherent hysteresis in temperature sensor readings (either from hardware |
| 230 | * circuitry or possibly from the EC's firmware implementation. |
| 231 | */ |
| 232 | void dptf_write_tsr_hysteresis(uint8_t hysteresis); |
| 233 | |
Tim Wawrzynczak | c41f7f1 | 2020-05-29 13:56:37 -0600 | [diff] [blame] | 234 | /* Helper method to open the scope for a given participant. */ |
| 235 | void dptf_write_scope(enum dptf_participant participant); |
| 236 | |
| 237 | /* |
| 238 | * Write out a _STA that will check the value of the DPTE field in GNVS, and return 0xF if DPTE |
| 239 | * is 1, otherwise it will return 0. |
| 240 | */ |
| 241 | void dptf_write_STA(void); |
| 242 | |
| 243 | #endif /* ACPI_ACPIGEN_DPTF_H */ |