blob: 5bbbc1bb7fe774b48c5d755273e2e12e32fe0c11 [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>
Subrata Banikaf206282022-12-19 21:56:35 +05308#include <soc/dptf.h>
Sumeet Pawnikare0bff812021-09-23 21:49:29 +05309#include <soc/pci_devs.h>
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060010#include "chip.h"
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -060011#include "dptf.h"
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060012
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060013/* Generic DPTF participants have a PTYP field to distinguish them */
14enum dptf_generic_participant_type {
15 DPTF_GENERIC_PARTICIPANT_TYPE_TSR = 0x3,
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +053016 DPTF_GENERIC_PARTICIPANT_TYPE_FAN = 0x4,
Sumeet Pawnikare0bff812021-09-23 21:49:29 +053017 DPTF_GENERIC_PARTICIPANT_TYPE_TPCH = 0x5,
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060018 DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER = 0xB,
Varshit B Pandya170a76c2022-04-02 15:11:36 +053019 DPTF_GENERIC_PARTICIPANT_TYPE_BATTERY = 0xC,
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +053020 DPTF_GENERIC_PARTICIPANT_TYPE_POWER = 0x11,
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060021};
22
23#define DEFAULT_CHARGER_STR "Battery Charger"
Sumeet Pawnikare0bff812021-09-23 21:49:29 +053024#define DEFAULT_TPCH_STR "Intel PCH FIVR Participant"
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +053025#define DEFAULT_POWER_STR "Power Participant"
Varshit B Pandya170a76c2022-04-02 15:11:36 +053026#define DEFAULT_BATTERY_STR "Battery Participant"
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +053027#define DEFAULT_FAN_STR "Fan Participant"
Sumeet Pawnikare0bff812021-09-23 21:49:29 +053028
29#define PMC_IPC_COMMAND_FIVR_SIZE 0x8
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060030
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060031/*
32 * Helper method to determine if a device is "used" (called out anywhere as a source or a target
33 * of any policies, and therefore should be included in the ACPI tables.
34 */
35static bool is_participant_used(const struct drivers_intel_dptf_config *config,
36 enum dptf_participant participant)
37{
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060038 int i;
39
40 /* Active? */
41 for (i = 0; i < DPTF_MAX_ACTIVE_POLICIES; ++i)
42 if (config->policies.active[i].target == participant)
43 return true;
44
Tim Wawrzynczak7eb11362020-05-29 14:10:53 -060045 /* Passive? */
46 for (i = 0; i < DPTF_MAX_PASSIVE_POLICIES; ++i)
47 if (config->policies.passive[i].source == participant ||
48 config->policies.passive[i].target == participant)
49 return true;
50
Tim Wawrzynczak3a9cde92020-05-29 14:19:15 -060051 /* Critical? */
52 for (i = 0; i < DPTF_MAX_CRITICAL_POLICIES; ++i)
53 if (config->policies.critical[i].source == participant)
54 return true;
55
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060056 /* Check fan as well (its use is implicit in the Active policy) */
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +053057 if ((participant == DPTF_FAN || participant == DPTF_FAN_2) &&
58 config->policies.active[0].target != DPTF_NONE)
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060059 return true;
60
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060061 return false;
62}
63
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +053064/* Return the assigned namestring of the FAN participant */
65static const char *fan_namestring_of(enum dptf_participant participant)
66{
67 switch (participant) {
68 case DPTF_FAN:
69 return "TFN1";
70 case DPTF_FAN_2:
71 return "TFN2";
72 default:
73 return "";
74 }
75}
76
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060077static const char *dptf_acpi_name(const struct device *dev)
78{
79 return "DPTF";
80}
81
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060082static int get_STA_value(const struct drivers_intel_dptf_config *config,
83 enum dptf_participant participant)
84{
85 return is_participant_used(config, participant) ?
86 ACPI_STATUS_DEVICE_ALL_ON :
87 ACPI_STATUS_DEVICE_ALL_OFF;
88}
89
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -060090static void dptf_write_hid(bool is_eisa, const char *hid)
91{
92 if (is_eisa)
93 acpigen_emit_eisaid(hid);
94 else
95 acpigen_write_string(hid);
96}
97
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -060098/* Devices with GENERIC _HID (distinguished by PTYP) */
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060099static void dptf_write_generic_participant(const char *name,
100 enum dptf_generic_participant_type ptype,
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600101 const char *str, int sta_val,
102 const struct dptf_platform_info *platform_info)
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600103{
104 /* Auto-incrementing UID for generic participants */
105 static int generic_uid = 0;
106
107 acpigen_write_device(name);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600108 acpigen_write_name("_HID");
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600109 dptf_write_hid(platform_info->use_eisa_hids, platform_info->generic_hid);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600110
111 acpigen_write_name_integer("_UID", generic_uid++);
112 acpigen_write_STA(sta_val);
113
114 if (str)
Cliff Huang95e4ffe2023-09-07 09:39:37 -0700115 acpigen_write_name_unicode("_STR", str);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600116
117 acpigen_write_name_integer("PTYP", ptype);
118
119 acpigen_pop_len(); /* Device */
120}
121
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600122/* \_SB.PCI0.TCPU */
123static void write_tcpu(const struct device *pci_dev,
124 const struct drivers_intel_dptf_config *config)
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600125{
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600126 /* DPTF CPU device - \_SB.PCI0.TCPU */
127 acpigen_write_scope(TCPU_SCOPE);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600128 acpigen_write_device("TCPU");
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600129 acpigen_write_ADR_pci_device(pci_dev);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600130 acpigen_write_STA(get_STA_value(config, DPTF_CPU));
131 acpigen_pop_len(); /* Device */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600132 acpigen_pop_len(); /* TCPU Scope */
133}
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600134
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530135/* \_SB.DPTF.TFNx */
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600136static void write_fan(const struct drivers_intel_dptf_config *config,
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530137 const struct dptf_platform_info *platform_info,
138 enum dptf_participant participant)
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600139{
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530140 static int fan_uid = 0;
141
142 acpigen_write_device(fan_namestring_of(participant));
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600143 acpigen_write_name("_HID");
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600144 dptf_write_hid(platform_info->use_eisa_hids, platform_info->fan_hid);
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530145 acpigen_write_name_integer("_UID", fan_uid++);
Cliff Huang95e4ffe2023-09-07 09:39:37 -0700146 acpigen_write_name_unicode("_STR", DEFAULT_FAN_STR);
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530147 acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_FAN);
148 acpigen_write_STA(get_STA_value(config, participant));
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600149 acpigen_pop_len(); /* Device */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600150}
151
Sumeet R Pawnikar36571872021-05-11 20:05:20 +0530152/* \_SB.DPTF */
Sumeet Pawnikarf96aa7a2021-07-05 21:09:53 +0530153static void write_imok(void)
154{
155 acpigen_write_method("IMOK", 1);
156 /* Return (Arg0) */
157 acpigen_emit_byte(RETURN_OP);
158 acpigen_emit_byte(ARG0_OP);
159 acpigen_write_method_end();
160}
Sumeet Pawnikard4d6d6c2023-10-12 17:53:37 +0530161
162static void write_dcfg_variable(const struct drivers_intel_dptf_config *config)
163{
164 acpigen_write_name_integer("DCFG", config->dcfg);
165}
166
Sumeet Pawnikarf96aa7a2021-07-05 21:09:53 +0530167/* \_SB.DPTF */
Sumeet R Pawnikar36571872021-05-11 20:05:20 +0530168static void write_oem_variables(const struct drivers_intel_dptf_config *config)
169{
170 int i;
171
172 acpigen_write_name("ODVX");
173 acpigen_write_package(DPTF_OEM_VARIABLE_COUNT);
174 for (i = 0; i < DPTF_OEM_VARIABLE_COUNT; i++)
175 acpigen_write_dword(config->oem_data.oem_variables[i]);
176 acpigen_write_package_end();
177
178 /*
179 * Method (ODUP, 2)
180 * Arg0 = Index of ODVX to update
181 * Arg1 = Value to place in ODVX[Arg0]
182 */
183 acpigen_write_method_serialized("ODUP", 2);
184 /* ODVX[Arg0] = Arg1 */
185 acpigen_write_store();
186 acpigen_emit_byte(ARG1_OP);
187 acpigen_emit_byte(INDEX_OP);
188 acpigen_emit_namestring("ODVX");
189 acpigen_emit_byte(ARG0_OP);
190 acpigen_emit_byte(ZERO_OP); /* Ignore Index() Destination */
191 acpigen_write_method_end();
192
193 /*
194 * Method (ODGT, 1)
195 * Arg0 = Index of ODVX to get
196 */
197 acpigen_write_method_serialized("ODGT", 1);
198 /* Return (ODVX[Arg0]) */
199 acpigen_emit_byte(RETURN_OP);
200 acpigen_emit_byte(DEREF_OP);
201 acpigen_emit_byte(INDEX_OP);
202 acpigen_emit_namestring("ODVX");
203 acpigen_emit_byte(ARG0_OP);
204 acpigen_emit_byte(ZERO_OP); /* Ignore Index() Destination */
205 acpigen_write_method_end();
206
207 /* Method (ODVP) { Return (ODVX) } */
208 acpigen_write_method_serialized("ODVP", 0);
209 acpigen_emit_byte(RETURN_OP);
210 acpigen_emit_namestring("ODVX");
211 acpigen_write_method_end();
212}
213
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600214/* \_SB.DPTF.xxxx */
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600215static void write_generic_devices(const struct drivers_intel_dptf_config *config,
216 const struct dptf_platform_info *platform_info)
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600217{
218 enum dptf_participant participant;
219 char name[ACPI_NAME_BUFFER_SIZE];
220 int i;
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600221
222 dptf_write_generic_participant("TCHG", DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER,
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600223 DEFAULT_CHARGER_STR,
224 get_STA_value(config, DPTF_CHARGER),
225 platform_info);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600226
Tim Wawrzynczak40713aa2021-11-24 09:18:44 -0700227 for (i = 0, participant = DPTF_TEMP_SENSOR_0; i < DPTF_MAX_TSR; ++i, ++participant) {
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600228 snprintf(name, sizeof(name), "TSR%1d", i);
229 dptf_write_generic_participant(name, DPTF_GENERIC_PARTICIPANT_TYPE_TSR,
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600230 NULL, get_STA_value(config, participant),
231 platform_info);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600232 }
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600233}
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600234
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530235static const char *get_pmc_ipcs_method(void)
236{
237 const char *method = acpi_device_path_join(
238 pcidev_path_on_root(PCH_DEVFN_PMC), "IPCS");
239 if (!method) {
240 printk(BIOS_ERR, "%s: Unable to find PMC device IPCS method\n", __func__);
241 return NULL;
242 }
243 return method;
244}
245
246static void write_tpch_write_method(const char *tpch_write_method_name,
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530247 unsigned int ipc_subcmd_ctrl_value)
248{
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530249 /* Get IPCS method from the PMC device */
250 const char *ipcs = get_pmc_ipcs_method();
251 acpigen_write_method_serialized(tpch_write_method_name, 1);
252 acpigen_emit_namestring(ipcs);
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530253 acpigen_write_integer(PMC_IPC_CMD_COMMAND_FIVR);
254 acpigen_write_integer(PMC_IPC_CMD_CMD_ID_FIVR_WRITE);
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530255 acpigen_write_integer(PMC_IPC_COMMAND_FIVR_SIZE);
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530256 acpigen_write_integer(ipc_subcmd_ctrl_value);
257 acpigen_emit_byte(ARG0_OP);
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530258 acpigen_write_zero();
259 acpigen_write_zero();
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530260 /* The reason for returning a value here is a W/A for the ESIF shell */
261 acpigen_emit_byte(RETURN_OP);
Sumeet Pawnikar7c1ce192021-10-07 18:00:57 +0530262 acpigen_write_package(1);
263 acpigen_write_zero();
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530264 acpigen_write_package_end();
265 acpigen_write_method_end();
266}
267
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530268static void write_ppkg_package(const uint8_t i)
269{
270 acpigen_write_store();
271 acpigen_emit_byte(DEREF_OP);
272 acpigen_emit_byte(INDEX_OP);
273 acpigen_emit_byte(ARG0_OP);
274 acpigen_write_integer(i);
275 acpigen_emit_byte(ZERO_OP);
276 acpigen_emit_byte(INDEX_OP);
277 acpigen_emit_namestring("PPKG");
278 acpigen_write_integer(i);
279 acpigen_emit_byte(ZERO_OP);
280}
281
282/*
283 * Truncate Package received from IPC
284 * Arguments:
285 * Arg0: Package returned from the IPCS read call from the Pmc
286 * Return Value:
287 * Return Package with just the Status and ReadBuf0
288 * Status returns 0 for success and 2 for device error
289 */
290static void write_pkgc_method(void)
291{
292 acpigen_write_method_serialized("PKGC", 1);
293 acpigen_write_name("PPKG");
294 acpigen_write_package(2);
295 acpigen_write_zero();
296 acpigen_write_zero();
297 acpigen_write_package_end();
298
299 write_ppkg_package(0);
300 write_ppkg_package(1);
301
302 acpigen_write_return_namestr("PPKG");
303 acpigen_write_method_end();
304}
305
306static void write_tpch_read_method(const char *tpch_read_method_name,
307 unsigned int ipc_subcmd_ctrl_value)
308{
309 /* Get IPCS method from the PMC device */
310 const char *ipcs = get_pmc_ipcs_method();
311 acpigen_write_method_serialized(tpch_read_method_name, 0);
312 acpigen_write_store();
313 acpigen_emit_namestring(ipcs);
314 acpigen_write_integer(PMC_IPC_CMD_COMMAND_FIVR);
315 acpigen_write_integer(PMC_IPC_CMD_CMD_ID_FIVR_READ);
316 acpigen_write_integer(PMC_IPC_COMMAND_FIVR_SIZE);
317 acpigen_write_integer(ipc_subcmd_ctrl_value);
318 acpigen_write_zero();
319 acpigen_write_zero();
320 acpigen_write_zero();
321 acpigen_emit_byte(LOCAL0_OP);
322
323 acpigen_write_store();
324 acpigen_emit_namestring("PKGC");
325 acpigen_emit_byte(LOCAL0_OP);
326 acpigen_emit_byte(LOCAL1_OP);
327
328 acpigen_emit_byte(RETURN_OP);
329 acpigen_emit_byte(LOCAL1_OP);
330 acpigen_write_method_end();
331}
332
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530333static void write_create_tpch(const struct dptf_platform_info *platform_info)
334{
335 acpigen_write_device("TPCH");
336 acpigen_write_name("_HID");
337 dptf_write_hid(platform_info->use_eisa_hids, platform_info->tpch_device_hid);
Cliff Huang95e4ffe2023-09-07 09:39:37 -0700338 acpigen_write_name_unicode("_STR", DEFAULT_TPCH_STR);
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530339 acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_TPCH);
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530340 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
341}
342
343static void write_tpch_methods(const struct dptf_platform_info *platform_info)
344{
345 write_create_tpch(platform_info);
346
Sumeet Pawnikare0bff812021-09-23 21:49:29 +0530347 const struct {
348 enum { READ, WRITE } type;
349 const char *method_name;
350 unsigned int subcommand;
351 } tpch_methods[] = {
352 { .type = WRITE,
353 .method_name =
354 platform_info->tpch_method_names.set_fivr_low_clock_method,
355 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC
356 },
357 { .type = WRITE,
358 .method_name =
359 platform_info->tpch_method_names.set_fivr_high_clock_method,
360 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC
361 },
362 { .type = READ,
363 .method_name =
364 platform_info->tpch_method_names.get_fivr_low_clock_method,
365 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC
366 },
367 { .type = READ,
368 .method_name =
369 platform_info->tpch_method_names.get_fivr_high_clock_method,
370 .subcommand = PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC
371 },
372 { .type = READ,
373 .method_name =
374 platform_info->tpch_method_names.get_fivr_ssc_method,
375 .subcommand = PMC_IPC_SUBCMD_EMI_CTRL0_LOGIC
376 },
377 { .type = READ,
378 .method_name =
379 platform_info->tpch_method_names.get_fivr_switching_fault_status,
380 .subcommand = PMC_IPC_SUBCMD_FFFC_FAULT_STATUS
381 },
382 { .type = READ,
383 .method_name =
384 platform_info->tpch_method_names.get_fivr_switching_freq_mhz,
385 .subcommand = PMC_IPC_SUBCMD_FFFC_RFI_STATUS
386 },
387 };
388
389 write_pkgc_method();
390 for (size_t i = 0; i < ARRAY_SIZE(tpch_methods); i++) {
391 if (tpch_methods[i].type == READ) {
392 write_tpch_read_method(tpch_methods[i].method_name,
393 tpch_methods[i].subcommand);
394 } else if (tpch_methods[i].type == WRITE) {
395 write_tpch_write_method(tpch_methods[i].method_name,
396 tpch_methods[i].subcommand);
397 }
398 }
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530399
400 acpigen_write_device_end(); /* TPCH Device */
401}
402
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530403static void write_create_tpwr(const struct drivers_intel_dptf_config *config,
404 const struct dptf_platform_info *platform_info)
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530405{
406 acpigen_write_device("TPWR");
407 acpigen_write_name("_HID");
408 if (platform_info->tpwr_device_hid != NULL)
409 dptf_write_hid(platform_info->use_eisa_hids, platform_info->tpwr_device_hid);
410 acpigen_write_name_string("_UID", "TPWR");
Cliff Huang95e4ffe2023-09-07 09:39:37 -0700411 acpigen_write_name_unicode("_STR", DEFAULT_POWER_STR);
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530412 acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_POWER);
413 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530414
415 /* PROP method */
416 if(config->prop != 0) {
417 acpigen_write_method_serialized("PROP", 0);
418 acpigen_emit_byte(RETURN_OP);
419 acpigen_write_integer(config->prop);
420 acpigen_pop_len(); /* Method PROP */
421 }
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530422 acpigen_write_device_end(); /* TPWR Power Participant Device */
423}
424
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530425static void write_tpwr_methods(const struct drivers_intel_dptf_config *config,
426 const struct dptf_platform_info *platform_info)
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530427{
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530428 write_create_tpwr(config, platform_info);
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530429}
430
Varshit B Pandya170a76c2022-04-02 15:11:36 +0530431static void write_create_tbat(const struct dptf_platform_info *platform_info)
432{
433 acpigen_write_device("TBAT");
434 acpigen_write_name("_HID");
435 if (platform_info->tbat_device_hid != NULL)
436 dptf_write_hid(platform_info->use_eisa_hids, platform_info->tbat_device_hid);
Varshit B Pandya4060df42022-07-01 17:57:43 +0530437 acpigen_write_name_string("_UID", "1");
Cliff Huang95e4ffe2023-09-07 09:39:37 -0700438 acpigen_write_name_unicode("_STR", DEFAULT_BATTERY_STR);
Varshit B Pandya170a76c2022-04-02 15:11:36 +0530439 acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_BATTERY);
440 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
441 acpigen_write_device_end(); /* TBAT Battery Participant Device */
442}
443
444
445static void write_tbat_methods(const struct dptf_platform_info *platform_info)
446{
447 write_create_tbat(platform_info);
448}
449
450
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530451/* \_SB.DPTF - note: leaves the Scope open for child devices */
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600452static void write_open_dptf_device(const struct device *dev,
453 const struct dptf_platform_info *platform_info)
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600454{
455 acpigen_write_scope("\\_SB");
456 acpigen_write_device(acpi_device_name(dev));
457 acpigen_write_name("_HID");
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600458 dptf_write_hid(platform_info->use_eisa_hids, platform_info->dptf_device_hid);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600459 acpigen_write_name_integer("_UID", 0);
460 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
461}
462
Subrata Banikaf206282022-12-19 21:56:35 +0530463static const struct dptf_platform_info generic_dptf_platform_info = {
464 .use_eisa_hids = CONFIG(DPTF_USE_EISA_HID),
465 /* _HID for the toplevel DPTF device, typically \_SB.DPTF */
466 .dptf_device_hid = DPTF_DPTF_DEVICE,
467 /* _HID for Intel DPTF Generic Device (these require PTYP as well) */
468 .generic_hid = DPTF_GEN_DEVICE,
469 /* _HID for Intel DPTF Fan Device */
470 .fan_hid = DPTF_FAN_DEVICE,
471
472#if CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TPWR)
473 /* _HID for the toplevel TPWR device, typically \_SB.DPTF.TPWR */
474 .tpwr_device_hid = DPTF_TPWR_DEVICE,
475#endif
476
477#if CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TBAT)
478 /* _HID for the toplevel BAT1 device, typically \_SB.DPTF.BAT1 */
479 .tbat_device_hid = DPTF_BAT1_DEVICE,
480#endif
481
482#if CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TPCH)
483 /* _HID for the toplevel TPCH device, typically \_SB.TPCH */
484 .tpch_device_hid = DPTF_TPCH_DEVICE,
485
486 .tpch_method_names = {
487 .set_fivr_low_clock_method = "RFC0",
488 .set_fivr_high_clock_method = "RFC1",
489 .get_fivr_low_clock_method = "GFC0",
490 .get_fivr_high_clock_method = "GFC1",
491 .get_fivr_ssc_method = "GEMI",
492 .get_fivr_switching_fault_status = "GFFS",
493 .get_fivr_switching_freq_mhz = "GFCS",
494 },
495#endif
496};
497
498static const struct dptf_platform_info *get_dptf_platform_info(void)
499{
500 return &generic_dptf_platform_info;
501}
502
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600503/* Add minimal definitions of DPTF devices into the SSDT */
504static void write_device_definitions(const struct device *dev)
505{
Subrata Banikaf206282022-12-19 21:56:35 +0530506 const struct dptf_platform_info *platform_info = get_dptf_platform_info();
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600507 const struct drivers_intel_dptf_config *config;
508 struct device *parent;
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530509 enum dptf_participant p;
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600510
511 /* The CPU device gets an _ADR that matches the ACPI PCI address for 00:04.00 */
Arthur Heymans7fcd4d52023-08-24 15:12:19 +0200512 parent = dev && dev->upstream ? dev->upstream->dev : NULL;
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600513 if (!parent || parent->path.type != DEVICE_PATH_PCI) {
514 printk(BIOS_ERR, "%s: DPTF objects must live under 00:04.0 PCI device\n",
515 __func__);
516 return;
517 }
518
519 config = config_of(dev);
520 write_tcpu(parent, config);
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600521 write_open_dptf_device(dev, platform_info);
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530522
523 if (config->dptf_multifan_support) {
524 for (p = DPTF_FAN; p <= DPTF_FAN_2; ++p)
525 write_fan(config, platform_info, p);
526 } else
527 write_fan(config, platform_info, DPTF_FAN);
528
Sumeet Pawnikard4d6d6c2023-10-12 17:53:37 +0530529 write_dcfg_variable(config);
Sumeet R Pawnikar36571872021-05-11 20:05:20 +0530530 write_oem_variables(config);
Sumeet Pawnikarf96aa7a2021-07-05 21:09:53 +0530531 write_imok();
Tim Wawrzynczak7f7c3882021-04-09 12:15:21 -0600532 write_generic_devices(config, platform_info);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600533
Sumeet Pawnikara91d9312021-08-30 23:19:38 +0530534 if (CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TPCH))
535 write_tpch_methods(platform_info);
536
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530537 if (CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TPWR))
Varshit B Pandya282b3b62022-04-18 14:50:30 +0530538 write_tpwr_methods(config, platform_info);
Varshit B Pandyae7d3a1a2022-03-20 20:39:51 +0530539
Varshit B Pandya170a76c2022-04-02 15:11:36 +0530540 if (CONFIG(DRIVERS_INTEL_DPTF_SUPPORTS_TBAT))
541 write_tbat_methods(platform_info);
542
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600543 acpigen_pop_len(); /* DPTF Device (write_open_dptf_device) */
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600544 acpigen_pop_len(); /* Scope */
545}
546
Martin Roth74f18772023-09-03 21:38:29 -0600547/* Emits policy definitions for each policy type */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600548static void write_policies(const struct drivers_intel_dptf_config *config)
549{
550 dptf_write_enabled_policies(config->policies.active, DPTF_MAX_ACTIVE_POLICIES,
551 config->policies.passive, DPTF_MAX_PASSIVE_POLICIES,
552 config->policies.critical, DPTF_MAX_CRITICAL_POLICIES);
553
554 dptf_write_active_policies(config->policies.active,
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530555 DPTF_MAX_ACTIVE_POLICIES, config->dptf_multifan_support);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600556
557 dptf_write_passive_policies(config->policies.passive,
558 DPTF_MAX_PASSIVE_POLICIES);
559
560 dptf_write_critical_policies(config->policies.critical,
561 DPTF_MAX_CRITICAL_POLICIES);
562}
563
564/* Writes other static tables that are used by DPTF */
565static void write_controls(const struct drivers_intel_dptf_config *config)
566{
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530567 enum dptf_participant p;
568 int fan_num;
569
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600570 dptf_write_charger_perf(config->controls.charger_perf, DPTF_MAX_CHARGER_PERF_STATES);
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530571
572 /* Write TFN perf states based on the number of fans on the platform */
573 if (config->dptf_multifan_support) {
574 for (p = DPTF_FAN, fan_num = 0; p <= DPTF_FAN_2; ++p, ++fan_num)
575 dptf_write_multifan_perf(config->controls.multifan_perf,
576 DPTF_MAX_FAN_PERF_STATES, p, fan_num);
577 } else
578 dptf_write_fan_perf(config->controls.fan_perf, DPTF_MAX_FAN_PERF_STATES,
579 DPTF_FAN);
580
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600581 dptf_write_power_limits(&config->controls.power_limits);
582}
583
584/* Options to control the behavior of devices */
585static void write_options(const struct drivers_intel_dptf_config *config)
586{
587 enum dptf_participant p;
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530588 int i, fan_num;
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600589
Sumeet Pawnikar2f7fa552022-06-08 17:43:36 +0530590 /* Configure Fan options based on the number of fans on the platform */
591 if (config->dptf_multifan_support) {
592 for (p = DPTF_FAN, fan_num = 0; p <= DPTF_FAN_2; ++p, ++fan_num) {
593 dptf_write_scope(p);
594 dptf_write_fan_options(
595 config->options.multifan_options[fan_num].fine_grained_control,
596 config->options.multifan_options[fan_num].step_size,
597 config->options.multifan_options[fan_num].low_speed_notify);
598 acpigen_pop_len(); /* Scope */
599 }
600 } else {
601 dptf_write_scope(DPTF_FAN);
602 dptf_write_fan_options(config->options.fan.fine_grained_control,
603 config->options.fan.step_size,
604 config->options.fan.low_speed_notify);
605 acpigen_pop_len(); /* Scope */
606 }
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600607
608 /* TSR options */
Tim Wawrzynczak40713aa2021-11-24 09:18:44 -0700609 for (p = DPTF_TEMP_SENSOR_0, i = 0; p <= DPTF_TEMP_SENSOR_4; ++p, ++i) {
Tim Wawrzynczakc6a593b2020-07-14 13:19:03 -0600610 if (is_participant_used(config, p) && (config->options.tsr[i].hysteresis ||
611 config->options.tsr[i].desc)) {
612 dptf_write_scope(p);
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600613 dptf_write_tsr_hysteresis(config->options.tsr[i].hysteresis);
614 dptf_write_STR(config->options.tsr[i].desc);
Tim Wawrzynczakc6a593b2020-07-14 13:19:03 -0600615 acpigen_pop_len(); /* Scope */
Tim Wawrzynczak5212ece62020-07-16 11:54:04 -0600616 }
617 }
618}
619
620/* Add custom tables and methods to SSDT */
621static void dptf_fill_ssdt(const struct device *dev)
622{
623 struct drivers_intel_dptf_config *config = config_of(dev);
624
625 write_device_definitions(dev);
626 write_policies(config);
627 write_controls(config);
628 write_options(config);
629
630 printk(BIOS_INFO, DPTF_DEVICE_PATH ": %s at %s\n", dev->chip_ops->name, dev_path(dev));
631}
632
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600633static struct device_operations dptf_ops = {
634 .read_resources = noop_read_resources,
635 .set_resources = noop_set_resources,
636 .acpi_name = dptf_acpi_name,
637 .acpi_fill_ssdt = dptf_fill_ssdt,
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600638};
639
640static void dptf_enable_dev(struct device *dev)
641{
642 dev->ops = &dptf_ops;
643}
644
645struct chip_operations drivers_intel_dptf_ops = {
Nicholas Sudsgaardbfb11be2024-01-30 09:53:46 +0900646 .name = "Intel DPTF",
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600647 .enable_dev = dptf_enable_dev,
648};