drivers/uart: Replace 'unsigned long int' by 'unsigned long'
[coreboot2.git] / src / ec / google / chromeec / ec_dptf_helpers.c
blob3034010e3681504f5094f3d6c769707ccf526dd1
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpigen.h>
4 #include <acpi/acpigen_dptf.h>
5 #include <ec/google/common/dptf.h>
6 #include <drivers/intel/dptf/chip.h>
7 #include <stdio.h>
9 #include "chip.h"
11 * The Chrome EC is typically in charge of many system functions, including battery charging and
12 * fan PWM control. This places it in the middle of a DPTF implementation and therefore, many of
13 * the "helper" ACPI Methods themselves call EC Methods. Because of that, the responsibility for
14 * producing the corresponding AML lies here.
17 /* DPTF Event types */
18 enum {
19 TRIP_POINTS_CHANGED_EVENT = 0x81,
20 THERMAL_EVENT = 0x90,
23 /* EC constants */
24 enum {
25 EC_FAN_DUTY_AUTO = 0xFF,
28 /* Return the fan number as a string for the FAN participant */
29 static const char *fan_num_namestring_of(enum dptf_participant participant)
31 switch (participant) {
32 case DPTF_FAN:
33 return "FAN0";
34 case DPTF_FAN_2:
35 return "FAN1";
36 default:
37 return "";
41 static void write_charger_PPPC(const struct device *ec)
43 acpigen_write_method_serialized("PPPC", 0);
46 * Convert size of PPSS table to index
48 * Store (SizeOf (PPSS), Local0)
49 * Decrement (Local0)
51 acpigen_write_store();
52 acpigen_emit_byte(SIZEOF_OP);
53 acpigen_emit_namestring("PPSS");
54 acpigen_emit_byte(LOCAL0_OP);
55 acpigen_emit_byte(DECREMENT_OP);
56 acpigen_emit_byte(LOCAL0_OP);
59 * Check if charging is disabled (AC removed)
61 * If (\_SB.PCI0.LPCB.EC0.ACEX () = Zero) {
62 * Return (Local0)
63 * }
65 acpigen_write_if();
66 acpigen_emit_byte(LEQUAL_OP);
67 acpigen_emit_namestring(acpi_device_path_join(ec, "ACEX"));
68 acpigen_emit_byte(ZERO_OP);
69 acpigen_write_return_op(LOCAL0_OP);
70 acpigen_pop_len(); /* If */
72 /* Return highest power state (index 0) */
73 acpigen_write_return_op(ZERO_OP);
75 acpigen_pop_len(); /* Method */
78 static void write_charger_SPPC(const struct device *ec)
81 * SPPC - Set charger current limit
82 * Method(SPPC, 1) {
83 * Store (DeRefOf (Index (DeRefOf (Index
84 * (PPSS, ToInteger (Arg0))), 4)), Local0)
85 * \_SB.PCI0.LPCB.EC0.CHGS (Local0)
86 * }
89 acpigen_write_method_serialized("SPPC", 1);
91 /* Retrieve Control (index 4) for specified PPSS level */
92 acpigen_emit_byte(STORE_OP);
93 acpigen_emit_byte(DEREF_OP);
94 acpigen_emit_byte(INDEX_OP);
95 acpigen_emit_byte(DEREF_OP);
96 acpigen_emit_byte(INDEX_OP);
97 acpigen_emit_namestring("PPSS");
98 acpigen_write_to_integer(ARG0_OP, ZERO_OP);
99 acpigen_emit_byte(ZERO_OP); /* 3rd arg to Index */
100 acpigen_write_integer(4); /* Index */
101 acpigen_emit_byte(ZERO_OP); /* 3rd arg to Index */
102 acpigen_emit_byte(LOCAL0_OP);
104 /* Pass Control value to EC to limit charging */
105 acpigen_emit_namestring(acpi_device_path_join(ec, "CHGS"));
106 acpigen_emit_byte(LOCAL0_OP);
107 acpigen_pop_len(); /* Method */
110 static void write_fan_fst(const struct device *ec, int participant)
112 /* TFST is a package that is used to store data from FAND */
113 acpigen_write_name("TFST");
114 acpigen_write_package(3);
115 acpigen_write_integer(0); /* Revision */
116 acpigen_write_integer(0); /* Control */
117 acpigen_write_integer(0); /* Speed */
118 acpigen_pop_len(); /* Package */
120 /* _FST */
121 acpigen_write_method_serialized("_FST", 0);
122 acpigen_write_store();
123 acpigen_emit_namestring(acpi_device_path_join(ec, "FAND"));
124 acpigen_emit_byte(INDEX_OP);
125 acpigen_emit_namestring("TFST");
126 acpigen_write_integer(1);
127 acpigen_emit_byte(ZERO_OP); /* 3rd arg to Index */
128 acpigen_write_store();
129 acpigen_emit_namestring(acpi_device_path_join(ec, fan_num_namestring_of(participant)));
130 acpigen_emit_byte(INDEX_OP);
131 acpigen_emit_namestring("TFST");
132 acpigen_write_integer(2);
133 acpigen_emit_byte(ZERO_OP);
134 acpigen_emit_byte(RETURN_OP);
135 acpigen_emit_namestring("TFST");
136 acpigen_pop_len(); /* Method _FST */
139 static void write_fan_fsl(const struct device *ec)
141 /* _FSL */
142 acpigen_write_method_serialized("_FSL", 1);
143 acpigen_write_store();
144 acpigen_emit_byte(ARG0_OP);
145 acpigen_emit_namestring(acpi_device_path_join(ec, "FAND"));
146 acpigen_pop_len(); /* Method _FSL */
150 * Emit code to execute if the policy is enabled after this function is called, and also
151 * remember to manually add a acpigen_pop_len() afterwards!
153 static void write_is_policy_enabled(bool enabled)
156 * Local0 = SizeOf (IDSP)
157 * Local1 = 0
158 * Local2 = 0
160 * While (Local1 < Local0) {
161 * If (IDSP[Local1] == Arg0 && Arg1 == enabled) {
162 * Local2 = 1
164 * Local1++
167 * If (Local2 == 1) {
168 * ..........
171 /* Local0 = SizeOf (IDSP) */
172 acpigen_write_store();
173 acpigen_emit_byte(SIZEOF_OP);
174 acpigen_emit_namestring("IDSP");
175 acpigen_emit_byte(LOCAL0_OP);
177 /* Local1 = 0 (index variable) */
178 acpigen_write_store();
179 acpigen_write_zero();
180 acpigen_emit_byte(LOCAL1_OP);
182 /* Local2 = 0 (out variable, 1=found, 0=not found) */
183 acpigen_write_store();
184 acpigen_write_zero();
185 acpigen_emit_byte(LOCAL2_OP);
188 * While (Local1 < Local0) {
190 acpigen_emit_byte(WHILE_OP);
191 acpigen_write_len_f();
192 acpigen_emit_byte(LLESS_OP);
193 acpigen_emit_byte(LOCAL1_OP);
194 acpigen_emit_byte(LOCAL0_OP);
196 /* If (IDSP[Local1] == Arg0 && Arg1 == 1) { */
197 acpigen_write_if();
198 acpigen_emit_byte(LAND_OP);
199 acpigen_emit_byte(LEQUAL_OP);
200 acpigen_emit_byte(DEREF_OP);
201 acpigen_emit_byte(INDEX_OP);
202 acpigen_emit_namestring("IDSP");
203 acpigen_emit_byte(LOCAL1_OP);
204 acpigen_emit_byte(ZERO_OP); /* 3rd arg of index - unused */
205 acpigen_emit_byte(ARG0_OP); /* end lequal */
206 acpigen_emit_byte(LEQUAL_OP);
207 acpigen_emit_byte(ARG1_OP);
208 acpigen_write_integer(enabled ? 1 : 0);
210 /* { Local2 = 1 } */
211 acpigen_write_store();
212 acpigen_write_one();
213 acpigen_emit_byte(LOCAL2_OP);
214 acpigen_pop_len(); /* If */
217 * Local1++
218 * } # End of While
220 acpigen_emit_byte(INCREMENT_OP);
221 acpigen_emit_byte(LOCAL1_OP);
222 acpigen_pop_len(); /* While */
225 * If (Local2 == 1)
227 acpigen_write_if();
228 acpigen_emit_byte(LEQUAL_OP);
229 acpigen_emit_byte(LOCAL2_OP);
230 acpigen_write_one();
232 /* caller must insert acpigen_pop_len() ! */
235 static void write_dptf_OSC(const struct device *ec)
237 char name[16];
238 int i;
241 * Arg0: Buffer containing UUID
242 * Arg1: "Integer containing Revision ID of buffer format", but Linux passes whether
243 * it is enabling (1) or disabling (0) the policy in Arg1.
244 * Arg2: Integer containing count of entries in Arg3
245 * Arg3: Buffer containing list of DWORD capabilities
246 * Return: Buffer containing list of DWORD capabilities
248 acpigen_write_method_serialized("_OSC", 4);
251 * If the Passive Policy is enabled:
252 * 1) Disable temperature sensor trip points in the EC (replaces TINI)
253 * 2) Disable the charge limit in the EC (replaces TCHG.INIT)
255 write_is_policy_enabled(true);
256 for (i = 0; i < DPTF_MAX_TSR; ++i) {
257 snprintf(name, sizeof(name), "^TSR%1d.PATD", i);
258 acpigen_emit_namestring(name);
261 acpigen_emit_namestring(acpi_device_path_join(ec, "CHGD"));
262 acpigen_pop_len(); /* If (from write_is_policy_enabled) */
264 /* If the Active Policy is disabled, disable DPTF fan control in the EC */
265 write_is_policy_enabled(false);
266 acpigen_write_store();
267 acpigen_write_integer(EC_FAN_DUTY_AUTO);
268 acpigen_emit_namestring(acpi_device_path_join(ec, "FAND"));
269 acpigen_pop_len(); /* If (from write_is_policy_enabled) */
271 acpigen_write_return_op(ARG3_OP);
272 acpigen_pop_len(); /* Method _OSC */
275 static void write_dppm_methods(const struct device *ec)
277 enum dptf_participant p;
278 char name[16];
279 int i;
281 acpigen_write_scope("\\_SB.DPTF");
282 write_dptf_OSC(ec);
284 /* TEVT */
285 if (CONFIG(EC_SUPPORTS_DPTF_TEVT)) {
286 acpigen_write_method("TEVT", 1);
288 /* Local0 = ToInteger(Arg0) */
289 acpigen_write_to_integer(ARG0_OP, LOCAL0_OP);
290 for (p = DPTF_TEMP_SENSOR_0, i = 0; p <= DPTF_TEMP_SENSOR_4; ++p, ++i) {
291 snprintf(name, sizeof(name), "^TSR%1d", i);
292 acpigen_write_if_lequal_op_int(LOCAL0_OP, i);
293 acpigen_notify(name, THERMAL_EVENT);
294 acpigen_pop_len(); /* If */
297 acpigen_pop_len(); /* Method */
300 /* TPET */
301 acpigen_write_method("TPET", 0);
302 for (p = DPTF_TEMP_SENSOR_0, i = 0; p <= DPTF_TEMP_SENSOR_4; ++p, ++i) {
303 snprintf(name, sizeof(name), "^TSR%1d", i);
304 acpigen_notify(name, TRIP_POINTS_CHANGED_EVENT);
307 acpigen_pop_len(); /* Method */
308 acpigen_pop_len(); /* Scope */
311 static void write_charger_methods(const struct device *ec)
313 dptf_write_scope(DPTF_CHARGER);
314 write_charger_PPPC(ec);
315 write_charger_SPPC(ec);
316 acpigen_pop_len(); /* Scope */
319 static void write_fan_methods(const struct device *ec, int participant)
321 dptf_write_scope(participant);
322 write_fan_fsl(ec);
323 write_fan_fst(ec, participant);
324 acpigen_pop_len(); /* Scope */
327 static void write_thermal_methods(const struct device *ec, enum dptf_participant participant,
328 int tsr_index)
330 dptf_write_scope(participant);
333 * GTSH - Amount of hysteresis inherent in temperature reading (2 degrees, in units of
334 * 1/10th degree K)
336 acpigen_write_name_integer("GTSH", 20);
338 /* _TMP - read temperature from EC */
339 acpigen_write_method_serialized("_TMP", 0);
340 acpigen_emit_byte(RETURN_OP);
341 acpigen_emit_namestring(acpi_device_path_join(ec, "TSRD"));
342 acpigen_write_integer(tsr_index);
343 acpigen_pop_len(); /* Method _TMP */
345 /* PATC - Aux trip point count */
346 acpigen_write_name_integer("PATC", 2);
348 /* PAT0 - Set Aux trip point 0 */
349 acpigen_write_method_serialized("PAT0", 1);
350 acpigen_emit_namestring(acpi_device_path_join(ec, "PAT0"));
351 acpigen_write_integer(tsr_index);
352 acpigen_emit_byte(ARG0_OP);
353 acpigen_pop_len(); /* Method PAT0 */
355 /* PAT1 - Set Aux trip point 1 */
356 acpigen_write_method_serialized("PAT1", 1);
357 acpigen_emit_namestring(acpi_device_path_join(ec, "PAT1"));
358 acpigen_write_integer(tsr_index);
359 acpigen_emit_byte(ARG0_OP);
360 acpigen_pop_len(); /* Method PAT0 */
362 /* PATD - Disable Aux trip point */
363 acpigen_write_method_serialized("PATD", 0);
364 acpigen_emit_namestring(acpi_device_path_join(ec, "PATD"));
365 acpigen_write_integer(tsr_index);
366 acpigen_pop_len(); /* Method PAT0 */
368 acpigen_pop_len(); /* Scope */
371 void ec_fill_dptf_helpers(const struct device *ec, const struct device *fan_dev)
373 enum dptf_participant p;
374 int i;
375 struct ec_google_chromeec_config *config = fan_dev->chip_info;
377 write_dppm_methods(ec);
378 write_charger_methods(ec);
380 if (config->ec_multifan_support) {
381 for (p = DPTF_FAN; p <= DPTF_FAN_2; ++p)
382 write_fan_methods(ec, p);
383 } else
384 write_fan_methods(ec, DPTF_FAN);
386 for (p = DPTF_TEMP_SENSOR_0, i = 0; p <= DPTF_TEMP_SENSOR_4; ++p, ++i)
387 write_thermal_methods(ec, p, i);