blob: ba061d0e8e8bb902741bd44cfed61f2b21ea0f9c [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>
Furquan Shaikh7cb10342020-10-03 14:49:09 -07007#include <device/pci.h>
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -06008#include <device/pci_def.h>
Furquan Shaikha1ddd2a2020-10-04 12:42:09 -07009#include <device/pci_ids.h>
Furquan Shaikh54b27162020-10-03 16:33:07 -070010#include <elog.h>
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060011#include <sar.h>
Furquan Shaikha1ddd2a2020-10-04 12:42:09 -070012#include <smbios.h>
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060013#include <string.h>
14#include <wrdd.h>
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -060015#include "chip.h"
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060016
17/* WRDS Spec Revision */
18#define WRDS_REVISION 0x0
19
20/* EWRD Spec Revision */
21#define EWRD_REVISION 0x0
22
23/* WRDS Domain type */
24#define WRDS_DOMAIN_TYPE_WIFI 0x7
25
26/* EWRD Domain type */
27#define EWRD_DOMAIN_TYPE_WIFI 0x7
28
29/* WGDS Domain type */
30#define WGDS_DOMAIN_TYPE_WIFI 0x7
31
32/*
33 * WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
34 * The above representation returns unique and consistent name every time
35 * generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
36 * chosen since it contains the bus address of the device.
37 */
38#define WIFI_ACPI_NAME_MAX_LEN 5
39
Furquan Shaikh5e003392020-10-04 17:34:04 -070040#if CONFIG(HAVE_ACPI_TABLES)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060041__weak
42int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
43{
44 return -1;
45}
46
47static void emit_sar_acpi_structures(void)
48{
49 int i, j, package_size;
50 struct wifi_sar_limits sar_limits;
51 struct wifi_sar_delta_table *wgds;
52
53 /* Retrieve the sar limits data */
54 if (get_wifi_sar_limits(&sar_limits) < 0) {
55 printk(BIOS_ERR, "Error: failed from getting SAR limits!\n");
56 return;
57 }
58
59 /*
60 * Name ("WRDS", Package () {
61 * Revision,
62 * Package () {
63 * Domain Type, // 0x7:WiFi
64 * WiFi SAR BIOS, // BIOS SAR Enable/disable
65 * SAR Table Set // Set#1 of SAR Table (10 bytes)
66 * }
67 * })
68 */
69 acpigen_write_name("WRDS");
70 acpigen_write_package(2);
71 acpigen_write_dword(WRDS_REVISION);
72 /* Emit 'Domain Type' + 'WiFi SAR BIOS' + 10 bytes for Set#1 */
73 package_size = 1 + 1 + BYTES_PER_SAR_LIMIT;
74 acpigen_write_package(package_size);
75 acpigen_write_dword(WRDS_DOMAIN_TYPE_WIFI);
76 acpigen_write_dword(CONFIG(SAR_ENABLE));
77 for (i = 0; i < BYTES_PER_SAR_LIMIT; i++)
78 acpigen_write_byte(sar_limits.sar_limit[0][i]);
79 acpigen_pop_len();
80 acpigen_pop_len();
81
82 /*
83 * Name ("EWRD", Package () {
84 * Revision,
85 * Package () {
86 * Domain Type, // 0x7:WiFi
87 * Dynamic SAR Enable, // Dynamic SAR Enable/disable
88 * Extended SAR sets, // Number of optional SAR table sets
89 * SAR Table Set, // Set#2 of SAR Table (10 bytes)
90 * SAR Table Set, // Set#3 of SAR Table (10 bytes)
91 * SAR Table Set // Set#4 of SAR Table (10 bytes)
92 * }
93 * })
94 */
95 acpigen_write_name("EWRD");
96 acpigen_write_package(2);
97 acpigen_write_dword(EWRD_REVISION);
98 /*
99 * Emit 'Domain Type' + "Dynamic SAR Enable' + 'Extended SAR sets'
100 * + number of bytes for Set#2 & 3 & 4
101 */
102 package_size = 1 + 1 + 1 + (NUM_SAR_LIMITS - 1) * BYTES_PER_SAR_LIMIT;
103 acpigen_write_package(package_size);
104 acpigen_write_dword(EWRD_DOMAIN_TYPE_WIFI);
105 acpigen_write_dword(CONFIG(DSAR_ENABLE));
106 acpigen_write_dword(CONFIG_DSAR_SET_NUM);
107 for (i = 1; i < NUM_SAR_LIMITS; i++)
108 for (j = 0; j < BYTES_PER_SAR_LIMIT; j++)
109 acpigen_write_byte(sar_limits.sar_limit[i][j]);
110 acpigen_pop_len();
111 acpigen_pop_len();
112
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600113 if (!CONFIG(GEO_SAR_ENABLE))
114 return;
115
116 /*
117 * Name ("WGDS", Package() {
118 * Revision,
119 * Package() {
120 * DomainType, // 0x7:WiFi
121 * WgdsWiFiSarDeltaGroup1PowerMax1, // Group 1 FCC 2400 Max
122 * WgdsWiFiSarDeltaGroup1PowerChainA1, // Group 1 FCC 2400 A Offset
123 * WgdsWiFiSarDeltaGroup1PowerChainB1, // Group 1 FCC 2400 B Offset
124 * WgdsWiFiSarDeltaGroup1PowerMax2, // Group 1 FCC 5200 Max
125 * WgdsWiFiSarDeltaGroup1PowerChainA2, // Group 1 FCC 5200 A Offset
126 * WgdsWiFiSarDeltaGroup1PowerChainB2, // Group 1 FCC 5200 B Offset
127 * WgdsWiFiSarDeltaGroup2PowerMax1, // Group 2 EC Jap 2400 Max
128 * WgdsWiFiSarDeltaGroup2PowerChainA1, // Group 2 EC Jap 2400 A Offset
129 * WgdsWiFiSarDeltaGroup2PowerChainB1, // Group 2 EC Jap 2400 B Offset
130 * WgdsWiFiSarDeltaGroup2PowerMax2, // Group 2 EC Jap 5200 Max
131 * WgdsWiFiSarDeltaGroup2PowerChainA2, // Group 2 EC Jap 5200 A Offset
132 * WgdsWiFiSarDeltaGroup2PowerChainB2, // Group 2 EC Jap 5200 B Offset
133 * WgdsWiFiSarDeltaGroup3PowerMax1, // Group 3 ROW 2400 Max
134 * WgdsWiFiSarDeltaGroup3PowerChainA1, // Group 3 ROW 2400 A Offset
135 * WgdsWiFiSarDeltaGroup3PowerChainB1, // Group 3 ROW 2400 B Offset
136 * WgdsWiFiSarDeltaGroup3PowerMax2, // Group 3 ROW 5200 Max
137 * WgdsWiFiSarDeltaGroup3PowerChainA2, // Group 3 ROW 5200 A Offset
138 * WgdsWiFiSarDeltaGroup3PowerChainB2, // Group 3 ROW 5200 B Offset
139 * }
140 * })
141 */
142
143 wgds = &sar_limits.wgds;
144 acpigen_write_name("WGDS");
145 acpigen_write_package(2);
146 acpigen_write_dword(wgds->version);
147 /* Emit 'Domain Type' +
148 * Group specific delta of power (6 bytes * NUM_WGDS_SAR_GROUPS)
149 */
150 package_size = sizeof(sar_limits.wgds.group) + 1;
151 acpigen_write_package(package_size);
152 acpigen_write_dword(WGDS_DOMAIN_TYPE_WIFI);
153 for (i = 0; i < SAR_NUM_WGDS_GROUPS; i++) {
154 acpigen_write_byte(wgds->group[i].power_max_2400mhz);
155 acpigen_write_byte(wgds->group[i].power_chain_a_2400mhz);
156 acpigen_write_byte(wgds->group[i].power_chain_b_2400mhz);
157 acpigen_write_byte(wgds->group[i].power_max_5200mhz);
158 acpigen_write_byte(wgds->group[i].power_chain_a_5200mhz);
159 acpigen_write_byte(wgds->group[i].power_chain_b_5200mhz);
160 }
161
162 acpigen_pop_len();
163 acpigen_pop_len();
164}
165
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600166void wifi_generic_fill_ssdt(const struct device *dev,
167 const struct drivers_wifi_generic_config *config)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600168{
169 const char *path;
170 u32 address;
171
172 if (!dev->enabled)
173 return;
174
175 path = acpi_device_path(dev->bus->dev);
176 if (!path)
177 return;
178
179 /* Device */
180 acpigen_write_scope(path);
181 acpigen_write_device(acpi_device_name(dev));
Patrick Rudolphc83bab62019-12-13 12:16:06 +0100182 acpi_device_write_uid(dev);
183
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600184 if (dev->chip_ops)
185 acpigen_write_name_string("_DDN", dev->chip_ops->name);
186
187 /* Address */
188 address = PCI_SLOT(dev->path.pci.devfn) & 0xffff;
189 address <<= 16;
190 address |= PCI_FUNC(dev->path.pci.devfn) & 0xffff;
191 acpigen_write_name_dword("_ADR", address);
192
193 /* Wake capabilities */
194 if (config)
Furquan Shaikh0af19262020-10-04 12:13:07 -0700195 acpigen_write_PRW(config->wake, ACPI_S3);
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600196
197 /* Fill regulatory domain structure */
198 if (CONFIG(HAVE_REGULATORY_DOMAIN)) {
199 /*
200 * Name ("WRDD", Package () {
201 * WRDD_REVISION, // Revision
202 * Package () {
203 * WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
204 * wifi_regulatory_domain() // Country Identifier
205 * }
206 * })
207 */
208 acpigen_write_name("WRDD");
209 acpigen_write_package(2);
210 acpigen_write_integer(WRDD_REVISION);
211 acpigen_write_package(2);
212 acpigen_write_dword(WRDD_DOMAIN_TYPE_WIFI);
213 acpigen_write_dword(wifi_regulatory_domain());
214 acpigen_pop_len();
215 acpigen_pop_len();
216 }
217
218 /* Fill Wifi sar related ACPI structures */
219 if (CONFIG(USE_SAR))
220 emit_sar_acpi_structures();
221
222 acpigen_pop_len(); /* Device */
223 acpigen_pop_len(); /* Scope */
224
225 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
226 dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
227}
228
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600229const char *wifi_generic_acpi_name(const struct device *dev)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600230{
231 static char wifi_acpi_name[WIFI_ACPI_NAME_MAX_LEN];
232
Andrew McRae524bcbb2019-09-19 16:55:52 +1000233 /* ACPI 6.3, ASL 20.2.2: (Name Objects Encoding). */
234 snprintf(wifi_acpi_name, sizeof(wifi_acpi_name), "WF%02X",
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600235 (dev_path_encode(dev) & 0xff));
236 return wifi_acpi_name;
237}
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600238
239static void wifi_generic_fill_ssdt_generator(const struct device *dev)
240{
241 wifi_generic_fill_ssdt(dev, dev->chip_info);
242}
Furquan Shaikh5e003392020-10-04 17:34:04 -0700243#endif
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600244
Furquan Shaikh54b27162020-10-03 16:33:07 -0700245static void wifi_pci_dev_init(struct device *dev)
246{
247 if (pci_dev_is_wake_source(dev))
248 elog_add_event_wake(ELOG_WAKE_SOURCE_PME_WIFI, 0);
249}
250
Furquan Shaikha1ddd2a2020-10-04 12:42:09 -0700251#if CONFIG(GENERATE_SMBIOS_TABLES)
252static int smbios_write_intel_wifi(struct device *dev, int *handle, unsigned long *current)
253{
254 struct smbios_type_intel_wifi {
255 u8 type;
256 u8 length;
257 u16 handle;
258 u8 str;
259 u8 eos[2];
260 } __packed;
261
262 struct smbios_type_intel_wifi *t = (struct smbios_type_intel_wifi *)*current;
263 int len = sizeof(struct smbios_type_intel_wifi);
264
265 memset(t, 0, sizeof(struct smbios_type_intel_wifi));
266 t->type = 0x85;
267 t->length = len - 2;
268 t->handle = *handle;
269 /* Intel wifi driver expects this string to be in the table 0x85. */
270 t->str = smbios_add_string(t->eos, "KHOIHGIUCCHHII");
271
272 len = t->length + smbios_string_table_len(t->eos);
273 *current += len;
274 *handle += 1;
275 return len;
276}
277
278static int smbios_write_wifi(struct device *dev, int *handle, unsigned long *current)
279{
280 if (dev->vendor == PCI_VENDOR_ID_INTEL)
281 return smbios_write_intel_wifi(dev, handle, current);
282
283 return 0;
284}
285#endif
286
Furquan Shaikh7cb10342020-10-03 14:49:09 -0700287struct device_operations wifi_generic_ops = {
288 .read_resources = pci_dev_read_resources,
289 .set_resources = pci_dev_set_resources,
290 .enable_resources = pci_dev_enable_resources,
Furquan Shaikh54b27162020-10-03 16:33:07 -0700291 .init = wifi_pci_dev_init,
Furquan Shaikh7cb10342020-10-03 14:49:09 -0700292 .ops_pci = &pci_dev_ops_pci,
Furquan Shaikh5e003392020-10-04 17:34:04 -0700293#if CONFIG(HAVE_ACPI_TABLES)
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600294 .acpi_name = wifi_generic_acpi_name,
295 .acpi_fill_ssdt = wifi_generic_fill_ssdt_generator,
Furquan Shaikh5e003392020-10-04 17:34:04 -0700296#endif
Furquan Shaikha1ddd2a2020-10-04 12:42:09 -0700297#if CONFIG(GENERATE_SMBIOS_TABLES)
298 .get_smbios_data = smbios_write_wifi,
299#endif
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600300};
301
302static void wifi_generic_enable(struct device *dev)
303{
304 struct drivers_wifi_generic_config *config = dev ? dev->chip_info : NULL;
305
306 if (!config)
307 return;
308
309 dev->ops = &wifi_generic_ops;
310}
311
312struct chip_operations drivers_wifi_generic_ops = {
313 CHIP_NAME("WIFI Device")
314 .enable_dev = wifi_generic_enable
315};
Furquan Shaikh8262a2c2020-10-10 19:53:00 -0700316
317static const unsigned short intel_pci_device_ids[] = {
318 PCI_DEVICE_ID_1000_SERIES_WIFI,
319 PCI_DEVICE_ID_6005_SERIES_WIFI,
320 PCI_DEVICE_ID_6005_I_SERIES_WIFI,
321 PCI_DEVICE_ID_1030_SERIES_WIFI,
322 PCI_DEVICE_ID_6030_I_SERIES_WIFI,
323 PCI_DEVICE_ID_6030_SERIES_WIFI,
324 PCI_DEVICE_ID_6150_SERIES_WIFI,
325 PCI_DEVICE_ID_2030_SERIES_WIFI,
326 PCI_DEVICE_ID_2000_SERIES_WIFI,
327 PCI_DEVICE_ID_0135_SERIES_WIFI,
328 PCI_DEVICE_ID_0105_SERIES_WIFI,
329 PCI_DEVICE_ID_6035_SERIES_WIFI,
330 PCI_DEVICE_ID_5300_SERIES_WIFI,
331 PCI_DEVICE_ID_5100_SERIES_WIFI,
332 PCI_DEVICE_ID_6000_SERIES_WIFI,
333 PCI_DEVICE_ID_6000_I_SERIES_WIFI,
334 PCI_DEVICE_ID_5350_SERIES_WIFI,
335 PCI_DEVICE_ID_5150_SERIES_WIFI,
336 /* Wilkins Peak 2 */
337 PCI_DEVICE_ID_WP_7260_SERIES_1_WIFI,
338 PCI_DEVICE_ID_WP_7260_SERIES_2_WIFI,
339 /* Stone Peak 2 */
340 PCI_DEVICE_ID_SP_7265_SERIES_1_WIFI,
341 PCI_DEVICE_ID_SP_7265_SERIES_2_WIFI,
342 /* Stone Field Peak */
343 PCI_DEVICE_ID_SFP_8260_SERIES_1_WIFI,
344 PCI_DEVICE_ID_SFP_8260_SERIES_2_WIFI,
345 /* Windstorm Peak */
346 PCI_DEVICE_ID_WSP_8275_SERIES_1_WIFI,
347 /* Jefferson Peak */
348 PCI_DEVICE_ID_JP_9000_SERIES_1_WIFI,
349 PCI_DEVICE_ID_JP_9000_SERIES_2_WIFI,
350 PCI_DEVICE_ID_JP_9000_SERIES_3_WIFI,
351 /* Thunder Peak 2 */
352 PCI_DEVICE_ID_TP_9260_SERIES_WIFI,
353 /* Harrison Peak */
354 PCI_DEVICE_ID_HrP_9560_SERIES_1_WIFI,
355 PCI_DEVICE_ID_HrP_9560_SERIES_2_WIFI,
356 PCI_DEVICE_ID_HrP_9560_SERIES_3_WIFI,
357 PCI_DEVICE_ID_HrP_9560_SERIES_4_WIFI,
358 PCI_DEVICE_ID_HrP_6SERIES_WIFI,
359 /* Cyclone Peak */
360 PCI_DEVICE_ID_CyP_6SERIES_WIFI,
361 /* Typhoon Peak */
362 PCI_DEVICE_ID_TyP_6SERIES_WIFI,
363 /* Garfield Peak */
364 PCI_DEVICE_ID_GrP_6SERIES_1_WIFI,
365 PCI_DEVICE_ID_GrP_6SERIES_2_WIFI,
366 0
367};
368
369/*
370 * The PCI driver is retained for backward compatibility with boards that never utilized the
371 * chip driver to support Intel WiFi device. For these devices, the PCI driver helps perform the
372 * same operations as above (except exposing the wake property) by utilizing the same
373 * `wifi_generic_ops`.
374 */
375static const struct pci_driver intel_wifi_pci_driver __pci_driver = {
376 .ops = &wifi_generic_ops,
377 .vendor = PCI_VENDOR_ID_INTEL,
378 .devices = intel_pci_device_ids,
379};