blob: 00a2f583fe91999abebaa523933dad395e0590f6 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -06002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi_device.h>
4#include <acpi/acpigen.h>
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -06005#include <console/console.h>
6#include <device/device.h>
7#include <device/pci_def.h>
8#include <sar.h>
9#include <string.h>
10#include <wrdd.h>
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -060011#include "chip.h"
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060012
13/* WRDS Spec Revision */
14#define WRDS_REVISION 0x0
15
16/* EWRD Spec Revision */
17#define EWRD_REVISION 0x0
18
19/* WRDS Domain type */
20#define WRDS_DOMAIN_TYPE_WIFI 0x7
21
22/* EWRD Domain type */
23#define EWRD_DOMAIN_TYPE_WIFI 0x7
24
25/* WGDS Domain type */
26#define WGDS_DOMAIN_TYPE_WIFI 0x7
27
28/*
29 * WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
30 * The above representation returns unique and consistent name every time
31 * generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
32 * chosen since it contains the bus address of the device.
33 */
34#define WIFI_ACPI_NAME_MAX_LEN 5
35
36__weak
37int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
38{
39 return -1;
40}
41
42static void emit_sar_acpi_structures(void)
43{
44 int i, j, package_size;
45 struct wifi_sar_limits sar_limits;
46 struct wifi_sar_delta_table *wgds;
47
48 /* Retrieve the sar limits data */
49 if (get_wifi_sar_limits(&sar_limits) < 0) {
50 printk(BIOS_ERR, "Error: failed from getting SAR limits!\n");
51 return;
52 }
53
54 /*
55 * Name ("WRDS", Package () {
56 * Revision,
57 * Package () {
58 * Domain Type, // 0x7:WiFi
59 * WiFi SAR BIOS, // BIOS SAR Enable/disable
60 * SAR Table Set // Set#1 of SAR Table (10 bytes)
61 * }
62 * })
63 */
64 acpigen_write_name("WRDS");
65 acpigen_write_package(2);
66 acpigen_write_dword(WRDS_REVISION);
67 /* Emit 'Domain Type' + 'WiFi SAR BIOS' + 10 bytes for Set#1 */
68 package_size = 1 + 1 + BYTES_PER_SAR_LIMIT;
69 acpigen_write_package(package_size);
70 acpigen_write_dword(WRDS_DOMAIN_TYPE_WIFI);
71 acpigen_write_dword(CONFIG(SAR_ENABLE));
72 for (i = 0; i < BYTES_PER_SAR_LIMIT; i++)
73 acpigen_write_byte(sar_limits.sar_limit[0][i]);
74 acpigen_pop_len();
75 acpigen_pop_len();
76
77 /*
78 * Name ("EWRD", Package () {
79 * Revision,
80 * Package () {
81 * Domain Type, // 0x7:WiFi
82 * Dynamic SAR Enable, // Dynamic SAR Enable/disable
83 * Extended SAR sets, // Number of optional SAR table sets
84 * SAR Table Set, // Set#2 of SAR Table (10 bytes)
85 * SAR Table Set, // Set#3 of SAR Table (10 bytes)
86 * SAR Table Set // Set#4 of SAR Table (10 bytes)
87 * }
88 * })
89 */
90 acpigen_write_name("EWRD");
91 acpigen_write_package(2);
92 acpigen_write_dword(EWRD_REVISION);
93 /*
94 * Emit 'Domain Type' + "Dynamic SAR Enable' + 'Extended SAR sets'
95 * + number of bytes for Set#2 & 3 & 4
96 */
97 package_size = 1 + 1 + 1 + (NUM_SAR_LIMITS - 1) * BYTES_PER_SAR_LIMIT;
98 acpigen_write_package(package_size);
99 acpigen_write_dword(EWRD_DOMAIN_TYPE_WIFI);
100 acpigen_write_dword(CONFIG(DSAR_ENABLE));
101 acpigen_write_dword(CONFIG_DSAR_SET_NUM);
102 for (i = 1; i < NUM_SAR_LIMITS; i++)
103 for (j = 0; j < BYTES_PER_SAR_LIMIT; j++)
104 acpigen_write_byte(sar_limits.sar_limit[i][j]);
105 acpigen_pop_len();
106 acpigen_pop_len();
107
108
109 if (!CONFIG(GEO_SAR_ENABLE))
110 return;
111
112 /*
113 * Name ("WGDS", Package() {
114 * Revision,
115 * Package() {
116 * DomainType, // 0x7:WiFi
117 * WgdsWiFiSarDeltaGroup1PowerMax1, // Group 1 FCC 2400 Max
118 * WgdsWiFiSarDeltaGroup1PowerChainA1, // Group 1 FCC 2400 A Offset
119 * WgdsWiFiSarDeltaGroup1PowerChainB1, // Group 1 FCC 2400 B Offset
120 * WgdsWiFiSarDeltaGroup1PowerMax2, // Group 1 FCC 5200 Max
121 * WgdsWiFiSarDeltaGroup1PowerChainA2, // Group 1 FCC 5200 A Offset
122 * WgdsWiFiSarDeltaGroup1PowerChainB2, // Group 1 FCC 5200 B Offset
123 * WgdsWiFiSarDeltaGroup2PowerMax1, // Group 2 EC Jap 2400 Max
124 * WgdsWiFiSarDeltaGroup2PowerChainA1, // Group 2 EC Jap 2400 A Offset
125 * WgdsWiFiSarDeltaGroup2PowerChainB1, // Group 2 EC Jap 2400 B Offset
126 * WgdsWiFiSarDeltaGroup2PowerMax2, // Group 2 EC Jap 5200 Max
127 * WgdsWiFiSarDeltaGroup2PowerChainA2, // Group 2 EC Jap 5200 A Offset
128 * WgdsWiFiSarDeltaGroup2PowerChainB2, // Group 2 EC Jap 5200 B Offset
129 * WgdsWiFiSarDeltaGroup3PowerMax1, // Group 3 ROW 2400 Max
130 * WgdsWiFiSarDeltaGroup3PowerChainA1, // Group 3 ROW 2400 A Offset
131 * WgdsWiFiSarDeltaGroup3PowerChainB1, // Group 3 ROW 2400 B Offset
132 * WgdsWiFiSarDeltaGroup3PowerMax2, // Group 3 ROW 5200 Max
133 * WgdsWiFiSarDeltaGroup3PowerChainA2, // Group 3 ROW 5200 A Offset
134 * WgdsWiFiSarDeltaGroup3PowerChainB2, // Group 3 ROW 5200 B Offset
135 * }
136 * })
137 */
138
139 wgds = &sar_limits.wgds;
140 acpigen_write_name("WGDS");
141 acpigen_write_package(2);
142 acpigen_write_dword(wgds->version);
143 /* Emit 'Domain Type' +
144 * Group specific delta of power (6 bytes * NUM_WGDS_SAR_GROUPS)
145 */
146 package_size = sizeof(sar_limits.wgds.group) + 1;
147 acpigen_write_package(package_size);
148 acpigen_write_dword(WGDS_DOMAIN_TYPE_WIFI);
149 for (i = 0; i < SAR_NUM_WGDS_GROUPS; i++) {
150 acpigen_write_byte(wgds->group[i].power_max_2400mhz);
151 acpigen_write_byte(wgds->group[i].power_chain_a_2400mhz);
152 acpigen_write_byte(wgds->group[i].power_chain_b_2400mhz);
153 acpigen_write_byte(wgds->group[i].power_max_5200mhz);
154 acpigen_write_byte(wgds->group[i].power_chain_a_5200mhz);
155 acpigen_write_byte(wgds->group[i].power_chain_b_5200mhz);
156 }
157
158 acpigen_pop_len();
159 acpigen_pop_len();
160}
161
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600162void wifi_generic_fill_ssdt(const struct device *dev,
163 const struct drivers_wifi_generic_config *config)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600164{
165 const char *path;
166 u32 address;
167
168 if (!dev->enabled)
169 return;
170
171 path = acpi_device_path(dev->bus->dev);
172 if (!path)
173 return;
174
175 /* Device */
176 acpigen_write_scope(path);
177 acpigen_write_device(acpi_device_name(dev));
Patrick Rudolphc83bab62019-12-13 12:16:06 +0100178 acpi_device_write_uid(dev);
179
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600180 if (dev->chip_ops)
181 acpigen_write_name_string("_DDN", dev->chip_ops->name);
182
183 /* Address */
184 address = PCI_SLOT(dev->path.pci.devfn) & 0xffff;
185 address <<= 16;
186 address |= PCI_FUNC(dev->path.pci.devfn) & 0xffff;
187 acpigen_write_name_dword("_ADR", address);
188
189 /* Wake capabilities */
190 if (config)
191 acpigen_write_PRW(config->wake, config->maxsleep);
192
193 /* Fill regulatory domain structure */
194 if (CONFIG(HAVE_REGULATORY_DOMAIN)) {
195 /*
196 * Name ("WRDD", Package () {
197 * WRDD_REVISION, // Revision
198 * Package () {
199 * WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
200 * wifi_regulatory_domain() // Country Identifier
201 * }
202 * })
203 */
204 acpigen_write_name("WRDD");
205 acpigen_write_package(2);
206 acpigen_write_integer(WRDD_REVISION);
207 acpigen_write_package(2);
208 acpigen_write_dword(WRDD_DOMAIN_TYPE_WIFI);
209 acpigen_write_dword(wifi_regulatory_domain());
210 acpigen_pop_len();
211 acpigen_pop_len();
212 }
213
214 /* Fill Wifi sar related ACPI structures */
215 if (CONFIG(USE_SAR))
216 emit_sar_acpi_structures();
217
218 acpigen_pop_len(); /* Device */
219 acpigen_pop_len(); /* Scope */
220
221 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
222 dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
223}
224
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600225const char *wifi_generic_acpi_name(const struct device *dev)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600226{
227 static char wifi_acpi_name[WIFI_ACPI_NAME_MAX_LEN];
228
Andrew McRae524bcbb2019-09-19 16:55:52 +1000229 /* ACPI 6.3, ASL 20.2.2: (Name Objects Encoding). */
230 snprintf(wifi_acpi_name, sizeof(wifi_acpi_name), "WF%02X",
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600231 (dev_path_encode(dev) & 0xff));
232 return wifi_acpi_name;
233}
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600234
235static void wifi_generic_fill_ssdt_generator(const struct device *dev)
236{
237 wifi_generic_fill_ssdt(dev, dev->chip_info);
238}
239
240static struct device_operations wifi_generic_ops = {
241 .read_resources = noop_read_resources,
242 .set_resources = noop_set_resources,
243 .acpi_name = wifi_generic_acpi_name,
244 .acpi_fill_ssdt = wifi_generic_fill_ssdt_generator,
245};
246
247static void wifi_generic_enable(struct device *dev)
248{
249 struct drivers_wifi_generic_config *config = dev ? dev->chip_info : NULL;
250
251 if (!config)
252 return;
253
254 dev->ops = &wifi_generic_ops;
255}
256
257struct chip_operations drivers_wifi_generic_ops = {
258 CHIP_NAME("WIFI Device")
259 .enable_dev = wifi_generic_enable
260};