blob: 450451082f157592f6e7a5139b5f581d6d674289 [file] [log] [blame]
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -06001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpigen.h>
Tim Wawrzynczakd40a4c22021-02-25 13:14:49 -07004#include <acpi/acpigen_pci.h>
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -06005#include <console/console.h>
6#include <device/device.h>
Sumeet Pawnikara91d9312021-08-30 23:19:38 +05307#include <intelblocks/pmc_ipc.h>
Sumeet Pawnikare0bff812021-09-23 21:49:29 +05308#include <soc/pci_devs.h>
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -06009#include "chip.h"
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -060010#include "dptf.h"
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060011
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060012/* Generic DPTF participants have a PTYP field to distinguish them */
13enum dptf_generic_participant_type {
14 DPTF_GENERIC_PARTICIPANT_TYPE_TSR = 0x3,
Sumeet Pawnikare0bff812021-09-23 21:49:29 +053015 DPTF_GENERIC_PARTICIPANT_TYPE_TPCH = 0x5,
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060016 DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER = 0xB,
Varshit B Pandya170a76c2022-04-02 15:11:36 +053017 DPTF_GENERIC_PARTICIPANT_TYPE_BATTERY = 0xC,
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +053018 DPTF_GENERIC_PARTICIPANT_TYPE_POWER = 0x11,
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060019};
20
21#define DEFAULT_CHARGER_STR "Battery Charger"
Sumeet Pawnikare0bff812021-09-23 21:49:29 +053022#define DEFAULT_TPCH_STR "Intel PCH FIVR Participant"
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +053023#define DEFAULT_POWER_STR "Power Participant"
Varshit B Pandya170a76c2022-04-02 15:11:36 +053024#define DEFAULT_BATTERY_STR "Battery Participant"
Sumeet Pawnikare0bff812021-09-23 21:49:29 +053025
26#define PMC_IPC_COMMAND_FIVR_SIZE 0x8
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060027
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060028/*
29 * Helper method to determine if a device is "used" (called out anywhere as a source or a target
30 * of any policies, and therefore should be included in the ACPI tables.
31 */
32static bool is_participant_used(const struct drivers_intel_dptf_config *config,
33 enum dptf_participant participant)
34{
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060035 int i;
36
37 /* Active? */
38 for (i = 0; i < DPTF_MAX_ACTIVE_POLICIES; ++i)
39 if (config->policies.active[i].target == participant)
40 return true;
41
Tim Wawrzynczak7eb11362020-05-29 14:10:53 -060042 /* Passive? */
43 for (i = 0; i < DPTF_MAX_PASSIVE_POLICIES; ++i)
44 if (config->policies.passive[i].source == participant ||
45 config->policies.passive[i].target == participant)
46 return true;
47
Tim Wawrzynczak3a9cde92020-05-29 14:19:15 -060048 /* Critical? */
49 for (i = 0; i < DPTF_MAX_CRITICAL_POLICIES; ++i)
50 if (config->policies.critical[i].source == participant)
51 return true;
52
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060053 /* Check fan as well (its use is implicit in the Active policy) */
54 if (participant == DPTF_FAN && config->policies.active[0].target != DPTF_NONE)
55 return true;
56
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060057 return false;
58}
59
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060060static const char *dptf_acpi_name(const struct device *dev)
61{
62 return "DPTF";
63}
64
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060065static int get_STA_value(const struct drivers_intel_dptf_config *config,
66 enum dptf_participant participant)
67{
68 return is_participant_used(config, participant) ?
69 ACPI_STATUS_DEVICE_ALL_ON :
70 ACPI_STATUS_DEVICE_ALL_OFF;
71}
72
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -060073static void dptf_write_hid(bool is_eisa, const char *hid)
74{
75 if (is_eisa)
76 acpigen_emit_eisaid(hid);
77 else
78 acpigen_write_string(hid);
79}
80
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -060081/* Devices with GENERIC _HID (distinguished by PTYP) */
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060082static void dptf_write_generic_participant(const char *name,
83 enum dptf_generic_participant_type ptype,
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -060084 const char *str, int sta_val,
85 const struct dptf_platform_info *platform_info)
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060086{
87 /* Auto-incrementing UID for generic participants */
88 static int generic_uid = 0;
89
90 acpigen_write_device(name);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -060091 acpigen_write_name("_HID");
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -060092 dptf_write_hid(platform_info->use_eisa_hids, platform_info->generic_hid);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060093
94 acpigen_write_name_integer("_UID", generic_uid++);
95 acpigen_write_STA(sta_val);
96
97 if (str)
98 acpigen_write_name_string("_STR", str);
99
100 acpigen_write_name_integer("PTYP", ptype);
101
102 acpigen_pop_len(); /* Device */
103}
104
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600105/* \_SB.PCI0.TCPU */
106static void write_tcpu(const struct device *pci_dev,
107 const struct drivers_intel_dptf_config *config)
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600108{
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600109 /* DPTF CPU device - \_SB.PCI0.TCPU */
110 acpigen_write_scope(TCPU_SCOPE);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600111 acpigen_write_device("TCPU");
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600112 acpigen_write_ADR_pci_device(pci_dev);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600113 acpigen_write_STA(get_STA_value(config, DPTF_CPU));
114 acpigen_pop_len(); /* Device */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600115 acpigen_pop_len(); /* TCPU Scope */
116}
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600117
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600118/* \_SB.DPTF.TFN1 */
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600119static void write_fan(const struct drivers_intel_dptf_config *config,
120 const struct dptf_platform_info *platform_info)
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600121{
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600122 acpigen_write_device("TFN1");
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600123 acpigen_write_name("_HID");
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600124 dptf_write_hid(platform_info->use_eisa_hids, platform_info->fan_hid);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600125 acpigen_write_name_integer("_UID", 0);
126 acpigen_write_STA(get_STA_value(config, DPTF_FAN));
127 acpigen_pop_len(); /* Device */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600128}
129
Sumeet R Pawnikar36571872021-05-11 20:05:20 +0530130/* \_SB.DPTF */
Sumeet Pawnikarf96aa7a2021-07-05 21:09:53 +0530131static void write_imok(void)
132{
133 acpigen_write_method("IMOK", 1);
134 /* Return (Arg0) */
135 acpigen_emit_byte(RETURN_OP);
136 acpigen_emit_byte(ARG0_OP);
137 acpigen_write_method_end();
138}
139/* \_SB.DPTF */
Sumeet R Pawnikar36571872021-05-11 20:05:20 +0530140static void write_oem_variables(const struct drivers_intel_dptf_config *config)
141{
142 int i;
143
144 acpigen_write_name("ODVX");
145 acpigen_write_package(DPTF_OEM_VARIABLE_COUNT);
146 for (i = 0; i < DPTF_OEM_VARIABLE_COUNT; i++)
147 acpigen_write_dword(config->oem_data.oem_variables[i]);
148 acpigen_write_package_end();
149
150 /*
151 * Method (ODUP, 2)
152 * Arg0 = Index of ODVX to update
153 * Arg1 = Value to place in ODVX[Arg0]
154 */
155 acpigen_write_method_serialized("ODUP", 2);
156 /* ODVX[Arg0] = Arg1 */
157 acpigen_write_store();
158 acpigen_emit_byte(ARG1_OP);
159 acpigen_emit_byte(INDEX_OP);
160 acpigen_emit_namestring("ODVX");
161 acpigen_emit_byte(ARG0_OP);
162 acpigen_emit_byte(ZERO_OP); /* Ignore Index() Destination */
163 acpigen_write_method_end();
164
165 /*
166 * Method (ODGT, 1)
167 * Arg0 = Index of ODVX to get
168 */
169 acpigen_write_method_serialized("ODGT", 1);
170 /* Return (ODVX[Arg0]) */
171 acpigen_emit_byte(RETURN_OP);
172 acpigen_emit_byte(DEREF_OP);
173 acpigen_emit_byte(INDEX_OP);
174 acpigen_emit_namestring("ODVX");
175 acpigen_emit_byte(ARG0_OP);
176 acpigen_emit_byte(ZERO_OP); /* Ignore Index() Destination */
177 acpigen_write_method_end();
178
179 /* Method (ODVP) { Return (ODVX) } */
180 acpigen_write_method_serialized("ODVP", 0);
181 acpigen_emit_byte(RETURN_OP);
182 acpigen_emit_namestring("ODVX");
183 acpigen_write_method_end();
184}
185
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600186/* \_SB.DPTF.xxxx */
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600187static void write_generic_devices(const struct drivers_intel_dptf_config *config,
188 const struct dptf_platform_info *platform_info)
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600189{
190 enum dptf_participant participant;
191 char name[ACPI_NAME_BUFFER_SIZE];
192 int i;
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600193
194 dptf_write_generic_participant("TCHG", DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER,
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600195 DEFAULT_CHARGER_STR,
196 get_STA_value(config, DPTF_CHARGER),
197 platform_info);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600198
Tim Wawrzynczak40713aa2021-11-24 09:18:44 -0700199 for (i = 0, participant = DPTF_TEMP_SENSOR_0; i < DPTF_MAX_TSR; ++i, ++participant) {
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600200 snprintf(name, sizeof(name), "TSR%1d", i);
201 dptf_write_generic_participant(name, DPTF_GENERIC_PARTICIPANT_TYPE_TSR,
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600202 NULL, get_STA_value(config, participant),
203 platform_info);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600204 }
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600205}
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600206
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530207static const char *get_pmc_ipcs_method(void)
208{
209 const char *method = acpi_device_path_join(
210 pcidev_path_on_root(PCH_DEVFN_PMC), "IPCS");
211 if (!method) {
212 printk(BIOS_ERR, "%s: Unable to find PMC device IPCS method\n", __func__);
213 return NULL;
214 }
215 return method;
216}
217
218static void write_tpch_write_method(const char *tpch_write_method_name,
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530219 unsigned int ipc_subcmd_ctrl_value)
220{
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530221 /* Get IPCS method from the PMC device */
222 const char *ipcs = get_pmc_ipcs_method();
223 acpigen_write_method_serialized(tpch_write_method_name, 1);
224 acpigen_emit_namestring(ipcs);
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530225 acpigen_write_integer(PMC_IPC_CMD_COMMAND_FIVR);
226 acpigen_write_integer(PMC_IPC_CMD_CMD_ID_FIVR_WRITE);
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530227 acpigen_write_integer(PMC_IPC_COMMAND_FIVR_SIZE);
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530228 acpigen_write_integer(ipc_subcmd_ctrl_value);
229 acpigen_emit_byte(ARG0_OP);
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530230 acpigen_write_zero();
231 acpigen_write_zero();
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530232 /* The reason for returning a value here is a W/A for the ESIF shell */
233 acpigen_emit_byte(RETURN_OP);
Sumeet Pawnikar7c1ce192021-10-07 18:00:57 +0530234 acpigen_write_package(1);
235 acpigen_write_zero();
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530236 acpigen_write_package_end();
237 acpigen_write_method_end();
238}
239
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530240static void write_ppkg_package(const uint8_t i)
241{
242 acpigen_write_store();
243 acpigen_emit_byte(DEREF_OP);
244 acpigen_emit_byte(INDEX_OP);
245 acpigen_emit_byte(ARG0_OP);
246 acpigen_write_integer(i);
247 acpigen_emit_byte(ZERO_OP);
248 acpigen_emit_byte(INDEX_OP);
249 acpigen_emit_namestring("PPKG");
250 acpigen_write_integer(i);
251 acpigen_emit_byte(ZERO_OP);
252}
253
254/*
255 * Truncate Package received from IPC
256 * Arguments:
257 * Arg0: Package returned from the IPCS read call from the Pmc
258 * Return Value:
259 * Return Package with just the Status and ReadBuf0
260 * Status returns 0 for success and 2 for device error
261 */
262static void write_pkgc_method(void)
263{
264 acpigen_write_method_serialized("PKGC", 1);
265 acpigen_write_name("PPKG");
266 acpigen_write_package(2);
267 acpigen_write_zero();
268 acpigen_write_zero();
269 acpigen_write_package_end();
270
271 write_ppkg_package(0);
272 write_ppkg_package(1);
273
274 acpigen_write_return_namestr("PPKG");
275 acpigen_write_method_end();
276}
277
278static void write_tpch_read_method(const char *tpch_read_method_name,
279 unsigned int ipc_subcmd_ctrl_value)
280{
281 /* Get IPCS method from the PMC device */
282 const char *ipcs = get_pmc_ipcs_method();
283 acpigen_write_method_serialized(tpch_read_method_name, 0);
284 acpigen_write_store();
285 acpigen_emit_namestring(ipcs);
286 acpigen_write_integer(PMC_IPC_CMD_COMMAND_FIVR);
287 acpigen_write_integer(PMC_IPC_CMD_CMD_ID_FIVR_READ);
288 acpigen_write_integer(PMC_IPC_COMMAND_FIVR_SIZE);
289 acpigen_write_integer(ipc_subcmd_ctrl_value);
290 acpigen_write_zero();
291 acpigen_write_zero();
292 acpigen_write_zero();
293 acpigen_emit_byte(LOCAL0_OP);
294
295 acpigen_write_store();
296 acpigen_emit_namestring("PKGC");
297 acpigen_emit_byte(LOCAL0_OP);
298 acpigen_emit_byte(LOCAL1_OP);
299
300 acpigen_emit_byte(RETURN_OP);
301 acpigen_emit_byte(LOCAL1_OP);
302 acpigen_write_method_end();
303}
304
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530305static void write_create_tpch(const struct dptf_platform_info *platform_info)
306{
307 acpigen_write_device("TPCH");
308 acpigen_write_name("_HID");
309 dptf_write_hid(platform_info->use_eisa_hids, platform_info->tpch_device_hid);
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530310 acpigen_write_name_string("_STR", DEFAULT_TPCH_STR);
311 acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_TPCH);
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530312 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
313}
314
315static void write_tpch_methods(const struct dptf_platform_info *platform_info)
316{
317 write_create_tpch(platform_info);
318
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530319 const struct {
320 enum { READ, WRITE } type;
321 const char *method_name;
322 unsigned int subcommand;
323 } tpch_methods[] = {
324 { .type = WRITE,
325 .method_name =
326 platform_info->tpch_method_names.set_fivr_low_clock_method,
327 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC
328 },
329 { .type = WRITE,
330 .method_name =
331 platform_info->tpch_method_names.set_fivr_high_clock_method,
332 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC
333 },
334 { .type = READ,
335 .method_name =
336 platform_info->tpch_method_names.get_fivr_low_clock_method,
337 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC
338 },
339 { .type = READ,
340 .method_name =
341 platform_info->tpch_method_names.get_fivr_high_clock_method,
342 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC
343 },
344 { .type = READ,
345 .method_name =
346 platform_info->tpch_method_names.get_fivr_ssc_method,
347 .subcommand = PMC_IPC_SUBCMD_EMI_CTRL0_LOGIC
348 },
349 { .type = READ,
350 .method_name =
351 platform_info->tpch_method_names.get_fivr_switching_fault_status,
352 .subcommand = PMC_IPC_SUBCMD_FFFC_FAULT_STATUS
353 },
354 { .type = READ,
355 .method_name =
356 platform_info->tpch_method_names.get_fivr_switching_freq_mhz,
357 .subcommand = PMC_IPC_SUBCMD_FFFC_RFI_STATUS
358 },
359 };
360
361 write_pkgc_method();
362 for (size_t i = 0; i < ARRAY_SIZE(tpch_methods); i++) {
363 if (tpch_methods[i].type == READ) {
364 write_tpch_read_method(tpch_methods[i].method_name,
365 tpch_methods[i].subcommand);
366 } else if (tpch_methods[i].type == WRITE) {
367 write_tpch_write_method(tpch_methods[i].method_name,
368 tpch_methods[i].subcommand);
369 }
370 }
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530371
372 acpigen_write_device_end(); /* TPCH Device */
373}
374
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530375static void write_create_tpwr(const struct drivers_intel_dptf_config *config,
376 const struct dptf_platform_info *platform_info)
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530377{
378 acpigen_write_device("TPWR");
379 acpigen_write_name("_HID");
380 if (platform_info->tpwr_device_hid != NULL)
381 dptf_write_hid(platform_info->use_eisa_hids, platform_info->tpwr_device_hid);
382 acpigen_write_name_string("_UID", "TPWR");
383 acpigen_write_name_string("_STR", DEFAULT_POWER_STR);
384 acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_POWER);
385 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530386
387 /* PROP method */
388 if(config->prop != 0) {
389 acpigen_write_method_serialized("PROP", 0);
390 acpigen_emit_byte(RETURN_OP);
391 acpigen_write_integer(config->prop);
392 acpigen_pop_len(); /* Method PROP */
393 }
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530394 acpigen_write_device_end(); /* TPWR Power Participant Device */
395}
396
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530397static void write_tpwr_methods(const struct drivers_intel_dptf_config *config,
398 const struct dptf_platform_info *platform_info)
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530399{
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530400 write_create_tpwr(config, platform_info);
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530401}
402
Varshit B Pandya170a76c2022-04-02 15:11:36 +0530403static void write_create_tbat(const struct dptf_platform_info *platform_info)
404{
405 acpigen_write_device("TBAT");
406 acpigen_write_name("_HID");
407 if (platform_info->tbat_device_hid != NULL)
408 dptf_write_hid(platform_info->use_eisa_hids, platform_info->tbat_device_hid);
Varshit B Pandya4060df42022-07-01 17:57:43 +0530409 acpigen_write_name_string("_UID", "1");
Varshit B Pandya170a76c2022-04-02 15:11:36 +0530410 acpigen_write_name_string("_STR", DEFAULT_BATTERY_STR);
411 acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_BATTERY);
412 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
413 acpigen_write_device_end(); /* TBAT Battery Participant Device */
414}
415
416
417static void write_tbat_methods(const struct dptf_platform_info *platform_info)
418{
419 write_create_tbat(platform_info);
420}
421
422
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530423/* \_SB.DPTF - note: leaves the Scope open for child devices */
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600424static void write_open_dptf_device(const struct device *dev,
425 const struct dptf_platform_info *platform_info)
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600426{
427 acpigen_write_scope("\\_SB");
428 acpigen_write_device(acpi_device_name(dev));
429 acpigen_write_name("_HID");
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600430 dptf_write_hid(platform_info->use_eisa_hids, platform_info->dptf_device_hid);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600431 acpigen_write_name_integer("_UID", 0);
432 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
433}
434
435/* Add minimal definitions of DPTF devices into the SSDT */
436static void write_device_definitions(const struct device *dev)
437{
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600438 const struct dptf_platform_info *platform_info = get_dptf_platform_info();
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600439 const struct drivers_intel_dptf_config *config;
440 struct device *parent;
441
442 /* The CPU device gets an _ADR that matches the ACPI PCI address for 00:04.00 */
443 parent = dev && dev->bus ? dev->bus->dev : NULL;
444 if (!parent || parent->path.type != DEVICE_PATH_PCI) {
445 printk(BIOS_ERR, "%s: DPTF objects must live under 00:04.0 PCI device\n",
446 __func__);
447 return;
448 }
449
450 config = config_of(dev);
451 write_tcpu(parent, config);
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600452 write_open_dptf_device(dev, platform_info);
453 write_fan(config, platform_info);
Sumeet R Pawnikar36571872021-05-11 20:05:20 +0530454 write_oem_variables(config);
Sumeet Pawnikarf96aa7a2021-07-05 21:09:53 +0530455 write_imok();
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600456 write_generic_devices(config, platform_info);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600457
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530458 if (CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TPCH))
459 write_tpch_methods(platform_info);
460
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530461 if (CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TPWR))
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530462 write_tpwr_methods(config, platform_info);
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530463
Varshit B Pandya170a76c2022-04-02 15:11:36 +0530464 if (CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TBAT))
465 write_tbat_methods(platform_info);
466
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600467 acpigen_pop_len(); /* DPTF Device (write_open_dptf_device) */
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600468 acpigen_pop_len(); /* Scope */
469}
470
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600471/* Emites policy definitions for each policy type */
472static void write_policies(const struct drivers_intel_dptf_config *config)
473{
474 dptf_write_enabled_policies(config->policies.active, DPTF_MAX_ACTIVE_POLICIES,
475 config->policies.passive, DPTF_MAX_PASSIVE_POLICIES,
476 config->policies.critical, DPTF_MAX_CRITICAL_POLICIES);
477
478 dptf_write_active_policies(config->policies.active,
479 DPTF_MAX_ACTIVE_POLICIES);
480
481 dptf_write_passive_policies(config->policies.passive,
482 DPTF_MAX_PASSIVE_POLICIES);
483
484 dptf_write_critical_policies(config->policies.critical,
485 DPTF_MAX_CRITICAL_POLICIES);
486}
487
488/* Writes other static tables that are used by DPTF */
489static void write_controls(const struct drivers_intel_dptf_config *config)
490{
491 dptf_write_charger_perf(config->controls.charger_perf, DPTF_MAX_CHARGER_PERF_STATES);
492 dptf_write_fan_perf(config->controls.fan_perf, DPTF_MAX_FAN_PERF_STATES);
493 dptf_write_power_limits(&config->controls.power_limits);
494}
495
496/* Options to control the behavior of devices */
497static void write_options(const struct drivers_intel_dptf_config *config)
498{
499 enum dptf_participant p;
500 int i;
501
502 /* Fan options */
Tim Wawrzynczak3a658ad2020-07-24 18:58:24 -0600503 dptf_write_scope(DPTF_FAN);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600504 dptf_write_fan_options(config->options.fan.fine_grained_control,
505 config->options.fan.step_size,
506 config->options.fan.low_speed_notify);
Tim Wawrzynczak3a658ad2020-07-24 18:58:24 -0600507 acpigen_pop_len(); /* Scope */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600508
509 /* TSR options */
Tim Wawrzynczak40713aa2021-11-24 09:18:44 -0700510 for (p = DPTF_TEMP_SENSOR_0, i = 0; p <= DPTF_TEMP_SENSOR_4; ++p, ++i) {
Tim Wawrzynczakc6a593b2020-07-14 13:19:03 -0600511 if (is_participant_used(config, p) && (config->options.tsr[i].hysteresis ||
512 config->options.tsr[i].desc)) {
513 dptf_write_scope(p);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600514 dptf_write_tsr_hysteresis(config->options.tsr[i].hysteresis);
515 dptf_write_STR(config->options.tsr[i].desc);
Tim Wawrzynczakc6a593b2020-07-14 13:19:03 -0600516 acpigen_pop_len(); /* Scope */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600517 }
518 }
519}
520
521/* Add custom tables and methods to SSDT */
522static void dptf_fill_ssdt(const struct device *dev)
523{
524 struct drivers_intel_dptf_config *config = config_of(dev);
525
526 write_device_definitions(dev);
527 write_policies(config);
528 write_controls(config);
529 write_options(config);
530
531 printk(BIOS_INFO, DPTF_DEVICE_PATH ": %s at %s\n", dev->chip_ops->name, dev_path(dev));
532}
533
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600534static struct device_operations dptf_ops = {
535 .read_resources = noop_read_resources,
536 .set_resources = noop_set_resources,
537 .acpi_name = dptf_acpi_name,
538 .acpi_fill_ssdt = dptf_fill_ssdt,
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600539};
540
541static void dptf_enable_dev(struct device *dev)
542{
543 dev->ops = &dptf_ops;
544}
545
546struct chip_operations drivers_intel_dptf_ops = {
547 CHIP_NAME("Intel DPTF")
548 .enable_dev = dptf_enable_dev,
549};