blob: 20f8d9b4ae1dda9f303785f2a107ed6b02906b58 [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
38 /* Check fan as well (its use is implicit in the Active policy) */
39 if (participant == DPTF_FAN && config->policies.active[0].target != DPTF_NONE)
40 return true;
41
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060042 return false;
43}
44
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060045static const char *dptf_acpi_name(const struct device *dev)
46{
47 return "DPTF";
48}
49
50/* Add custom tables and methods to SSDT */
51static void dptf_fill_ssdt(const struct device *dev)
52{
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060053 struct drivers_intel_dptf_config *config = config_of(dev);
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060054
Tim Wawrzynczakc41f7f12020-05-29 13:56:37 -060055 dptf_write_active_policies(config->policies.active,
56 DPTF_MAX_ACTIVE_POLICIES);
57
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060058 printk(BIOS_INFO, "\\_SB.DPTF: %s at %s\n", dev->chip_ops->name, dev_path(dev));
59}
60
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -060061static int get_STA_value(const struct drivers_intel_dptf_config *config,
62 enum dptf_participant participant)
63{
64 return is_participant_used(config, participant) ?
65 ACPI_STATUS_DEVICE_ALL_ON :
66 ACPI_STATUS_DEVICE_ALL_OFF;
67}
68
69static void dptf_write_generic_participant(const char *name,
70 enum dptf_generic_participant_type ptype,
71 const char *str, int sta_val)
72{
73 /* Auto-incrementing UID for generic participants */
74 static int generic_uid = 0;
75
76 acpigen_write_device(name);
77
78 if (CONFIG(DPTF_USE_EISA_HID)) {
79 acpigen_write_name("_HID");
80 acpigen_emit_eisaid(GENERIC_HID_EISAID);
81 } else {
82 acpigen_write_name_string("_HID", GENERIC_HID);
83 }
84
85 acpigen_write_name_integer("_UID", generic_uid++);
86 acpigen_write_STA(sta_val);
87
88 if (str)
89 acpigen_write_name_string("_STR", str);
90
91 acpigen_write_name_integer("PTYP", ptype);
92
93 acpigen_pop_len(); /* Device */
94}
95
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -060096/* Add static definitions of DPTF devices into the DSDT */
97static void dptf_inject_dsdt(const struct device *dev)
98{
99 const struct drivers_intel_dptf_config *config;
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600100 enum dptf_participant participant;
101 struct device *parent;
102 char name[5];
103 int i;
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600104
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600105 /* The CPU device gets an _ADR that matches the ACPI PCI address for 00:04.00 */
106 parent = dev && dev->bus ? dev->bus->dev : NULL;
107 if (!parent || parent->path.type != DEVICE_PATH_PCI) {
108 printk(BIOS_ERR, "%s: DPTF objects must live under 00:04.0 PCI device\n",
109 __func__);
110 return;
111 }
112
113 config = config_of(dev);
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600114 acpigen_write_scope("\\_SB");
115
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600116 /* DPTF CPU device - \_SB.TCPU */
117 acpigen_write_device("TCPU");
118 acpigen_write_ADR_pci_device(parent);
119 acpigen_write_STA(get_STA_value(config, DPTF_CPU));
120 acpigen_pop_len(); /* Device */
121
122 /* Toplevel DPTF device - \_SB.DPTF*/
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600123 acpigen_write_device(acpi_device_name(dev));
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600124 if (CONFIG(DPTF_USE_EISA_HID)) {
125 acpigen_write_name("_HID");
126 acpigen_emit_eisaid(DPTF_DEVICE_HID_EISAID);
127 } else {
128 acpigen_write_name_string("_HID", DPTF_DEVICE_HID);
129 }
130
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600131 acpigen_write_name_integer("_UID", 0);
Tim Wawrzynczakff2f6b22020-05-29 13:24:03 -0600132 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
133
134 /*
135 * The following devices live underneath \_SB.DPTF:
136 * - Fan, \_SB.DPTF.TFN1
137 * - Charger, \_SB.DPTF.TCHG
138 * - Temperature Sensors, \_SB.DPTF.TSRn
139 */
140
141 acpigen_write_device("TFN1");
142 if (CONFIG(DPTF_USE_EISA_HID)) {
143 acpigen_write_name("_HID");
144 acpigen_emit_eisaid(FAN_HID_EISAID);
145 } else {
146 acpigen_write_name_string("_HID", FAN_HID);
147 }
148
149 acpigen_write_name_integer("_UID", 0);
150 acpigen_write_STA(get_STA_value(config, DPTF_FAN));
151 acpigen_pop_len(); /* Device */
152
153 dptf_write_generic_participant("TCHG", DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER,
154 DEFAULT_CHARGER_STR, get_STA_value(config,
155 DPTF_CHARGER));
156
157 for (i = 0, participant = DPTF_TEMP_SENSOR_0; i < 4; ++i, ++participant) {
158 snprintf(name, sizeof(name), "TSR%1d", i);
159 dptf_write_generic_participant(name, DPTF_GENERIC_PARTICIPANT_TYPE_TSR,
160 NULL, get_STA_value(config, participant));
161 }
Tim Wawrzynczak103bd5e2020-05-29 13:11:00 -0600162
163 acpigen_pop_len(); /* DPTF Device */
164 acpigen_pop_len(); /* Scope */
165}
166
167static struct device_operations dptf_ops = {
168 .read_resources = noop_read_resources,
169 .set_resources = noop_set_resources,
170 .acpi_name = dptf_acpi_name,
171 .acpi_fill_ssdt = dptf_fill_ssdt,
172 .acpi_inject_dsdt = dptf_inject_dsdt,
173};
174
175static void dptf_enable_dev(struct device *dev)
176{
177 dev->ops = &dptf_ops;
178}
179
180struct chip_operations drivers_intel_dptf_ops = {
181 CHIP_NAME("Intel DPTF")
182 .enable_dev = dptf_enable_dev,
183};