blob: 74f481294d1b0682f31dd696b7e4686f3118d865 [file] [log] [blame]
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -06001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpigen.h>
4#include <console/console.h>
5#include <device/device.h>
6#include "chip.h"
7
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -06008/* Generic DPTF participants have a PTYP field to distinguish them */
9enum dptf_generic_participant_type {
10 DPTF_GENERIC_PARTICIPANT_TYPE_TSR = 0x3,
11 DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER = 0xB,
12};
13
14#define DEFAULT_CHARGER_STR "Battery Charger"
15
16#define DPTF_DEVICE_HID_EISAID "INT3400"
17#define GENERIC_HID_EISAID "INT3403"
18#define FAN_HID_EISAID "INT3404"
19
20#define DPTF_DEVICE_HID "INTC1040"
21#define GENERIC_HID "INTC1043"
22#define FAN_HID "INTC1044"
23
24/*
25 * Helper method to determine if a device is "used" (called out anywhere as a source or a target
26 * of any policies, and therefore should be included in the ACPI tables.
27 */
28static bool is_participant_used(const struct drivers_intel_dptf_config *config,
29 enum dptf_participant participant)
30{
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060031 int i;
32
33 /* Active? */
34 for (i = 0; i < DPTF_MAX_ACTIVE_POLICIES; ++i)
35 if (config->policies.active[i].target == participant)
36 return true;
37
Tim Wawrzynczak7eb11362020-05-29 14:10:53 -060038 /* Passive? */
39 for (i = 0; i < DPTF_MAX_PASSIVE_POLICIES; ++i)
40 if (config->policies.passive[i].source == participant ||
41 config->policies.passive[i].target == participant)
42 return true;
43
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060044 /* Check fan as well (its use is implicit in the Active policy) */
45 if (participant == DPTF_FAN && config->policies.active[0].target != DPTF_NONE)
46 return true;
47
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060048 return false;
49}
50
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060051static const char *dptf_acpi_name(const struct device *dev)
52{
53 return "DPTF";
54}
55
56/* Add custom tables and methods to SSDT */
57static void dptf_fill_ssdt(const struct device *dev)
58{
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060059 struct drivers_intel_dptf_config *config = config_of(dev);
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060060
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060061 dptf_write_active_policies(config->policies.active,
62 DPTF_MAX_ACTIVE_POLICIES);
63
Tim Wawrzynczak7eb11362020-05-29 14:10:53 -060064 dptf_write_passive_policies(config->policies.passive,
65 DPTF_MAX_PASSIVE_POLICIES);
66
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060067 printk(BIOS_INFO, "\\_SB.DPTF: %s at %s\n", dev->chip_ops->name, dev_path(dev));
68}
69
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060070static int get_STA_value(const struct drivers_intel_dptf_config *config,
71 enum dptf_participant participant)
72{
73 return is_participant_used(config, participant) ?
74 ACPI_STATUS_DEVICE_ALL_ON :
75 ACPI_STATUS_DEVICE_ALL_OFF;
76}
77
78static void dptf_write_generic_participant(const char *name,
79 enum dptf_generic_participant_type ptype,
80 const char *str, int sta_val)
81{
82 /* Auto-incrementing UID for generic participants */
83 static int generic_uid = 0;
84
85 acpigen_write_device(name);
86
87 if (CONFIG(DPTF_USE_EISA_HID)) {
88 acpigen_write_name("_HID");
89 acpigen_emit_eisaid(GENERIC_HID_EISAID);
90 } else {
91 acpigen_write_name_string("_HID", GENERIC_HID);
92 }
93
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 Wawrzynczak103bd5e2020-05-29 13:11:00 -0600105/* Add static definitions of DPTF devices into the DSDT */
106static void dptf_inject_dsdt(const struct device *dev)
107{
108 const struct drivers_intel_dptf_config *config;
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600109 enum dptf_participant participant;
110 struct device *parent;
111 char name[5];
112 int i;
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600113
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600114 /* The CPU device gets an _ADR that matches the ACPI PCI address for 00:04.00 */
115 parent = dev && dev->bus ? dev->bus->dev : NULL;
116 if (!parent || parent->path.type != DEVICE_PATH_PCI) {
117 printk(BIOS_ERR, "%s: DPTF objects must live under 00:04.0 PCI device\n",
118 __func__);
119 return;
120 }
121
122 config = config_of(dev);
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600123 acpigen_write_scope("\\_SB");
124
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600125 /* DPTF CPU device - \_SB.TCPU */
126 acpigen_write_device("TCPU");
127 acpigen_write_ADR_pci_device(parent);
128 acpigen_write_STA(get_STA_value(config, DPTF_CPU));
129 acpigen_pop_len(); /* Device */
130
131 /* Toplevel DPTF device - \_SB.DPTF*/
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600132 acpigen_write_device(acpi_device_name(dev));
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600133 if (CONFIG(DPTF_USE_EISA_HID)) {
134 acpigen_write_name("_HID");
135 acpigen_emit_eisaid(DPTF_DEVICE_HID_EISAID);
136 } else {
137 acpigen_write_name_string("_HID", DPTF_DEVICE_HID);
138 }
139
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600140 acpigen_write_name_integer("_UID", 0);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600141 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
142
143 /*
144 * The following devices live underneath \_SB.DPTF:
145 * - Fan, \_SB.DPTF.TFN1
146 * - Charger, \_SB.DPTF.TCHG
147 * - Temperature Sensors, \_SB.DPTF.TSRn
148 */
149
150 acpigen_write_device("TFN1");
151 if (CONFIG(DPTF_USE_EISA_HID)) {
152 acpigen_write_name("_HID");
153 acpigen_emit_eisaid(FAN_HID_EISAID);
154 } else {
155 acpigen_write_name_string("_HID", FAN_HID);
156 }
157
158 acpigen_write_name_integer("_UID", 0);
159 acpigen_write_STA(get_STA_value(config, DPTF_FAN));
160 acpigen_pop_len(); /* Device */
161
162 dptf_write_generic_participant("TCHG", DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER,
163 DEFAULT_CHARGER_STR, get_STA_value(config,
164 DPTF_CHARGER));
165
166 for (i = 0, participant = DPTF_TEMP_SENSOR_0; i < 4; ++i, ++participant) {
167 snprintf(name, sizeof(name), "TSR%1d", i);
168 dptf_write_generic_participant(name, DPTF_GENERIC_PARTICIPANT_TYPE_TSR,
169 NULL, get_STA_value(config, participant));
170 }
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600171
172 acpigen_pop_len(); /* DPTF Device */
173 acpigen_pop_len(); /* Scope */
174}
175
176static struct device_operations dptf_ops = {
177 .read_resources = noop_read_resources,
178 .set_resources = noop_set_resources,
179 .acpi_name = dptf_acpi_name,
180 .acpi_fill_ssdt = dptf_fill_ssdt,
181 .acpi_inject_dsdt = dptf_inject_dsdt,
182};
183
184static void dptf_enable_dev(struct device *dev)
185{
186 dev->ops = &dptf_ops;
187}
188
189struct chip_operations drivers_intel_dptf_ops = {
190 CHIP_NAME("Intel DPTF")
191 .enable_dev = dptf_enable_dev,
192};