blob: 56944e61da35614ae40b1e3f57cd6d96b0de1984 [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>
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060012#include <wrdd.h>
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -060013#include "chip.h"
Furquan Shaikh507a98b2020-10-27 15:28:21 -070014#include "wifi_private.h"
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060015
16/* WRDS Spec Revision */
17#define WRDS_REVISION 0x0
18
19/* EWRD Spec Revision */
20#define EWRD_REVISION 0x0
21
22/* WRDS Domain type */
23#define WRDS_DOMAIN_TYPE_WIFI 0x7
24
25/* EWRD Domain type */
26#define EWRD_DOMAIN_TYPE_WIFI 0x7
27
28/* WGDS Domain type */
29#define WGDS_DOMAIN_TYPE_WIFI 0x7
30
31/*
32 * WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
33 * The above representation returns unique and consistent name every time
34 * generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
35 * chosen since it contains the bus address of the device.
36 */
37#define WIFI_ACPI_NAME_MAX_LEN 5
38
Furquan Shaikh5e003392020-10-04 17:34:04 -070039#if CONFIG(HAVE_ACPI_TABLES)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060040__weak
41int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
42{
43 return -1;
44}
45
Furquan Shaikhe31506c2020-10-04 17:48:48 -070046static void emit_sar_acpi_structures(const struct device *dev)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060047{
48 int i, j, package_size;
49 struct wifi_sar_limits sar_limits;
50 struct wifi_sar_delta_table *wgds;
51
Furquan Shaikhe31506c2020-10-04 17:48:48 -070052 /* CBFS SAR and SAR ACPI tables are currently used only by Intel WiFi devices. */
53 if (dev->vendor != PCI_VENDOR_ID_INTEL)
54 return;
55
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -060056 /* Retrieve the sar limits data */
57 if (get_wifi_sar_limits(&sar_limits) < 0) {
58 printk(BIOS_ERR, "Error: failed from getting SAR limits!\n");
59 return;
60 }
61
62 /*
63 * Name ("WRDS", Package () {
64 * Revision,
65 * Package () {
66 * Domain Type, // 0x7:WiFi
67 * WiFi SAR BIOS, // BIOS SAR Enable/disable
68 * SAR Table Set // Set#1 of SAR Table (10 bytes)
69 * }
70 * })
71 */
72 acpigen_write_name("WRDS");
73 acpigen_write_package(2);
74 acpigen_write_dword(WRDS_REVISION);
75 /* Emit 'Domain Type' + 'WiFi SAR BIOS' + 10 bytes for Set#1 */
76 package_size = 1 + 1 + BYTES_PER_SAR_LIMIT;
77 acpigen_write_package(package_size);
78 acpigen_write_dword(WRDS_DOMAIN_TYPE_WIFI);
79 acpigen_write_dword(CONFIG(SAR_ENABLE));
80 for (i = 0; i < BYTES_PER_SAR_LIMIT; i++)
81 acpigen_write_byte(sar_limits.sar_limit[0][i]);
82 acpigen_pop_len();
83 acpigen_pop_len();
84
85 /*
86 * Name ("EWRD", Package () {
87 * Revision,
88 * Package () {
89 * Domain Type, // 0x7:WiFi
90 * Dynamic SAR Enable, // Dynamic SAR Enable/disable
91 * Extended SAR sets, // Number of optional SAR table sets
92 * SAR Table Set, // Set#2 of SAR Table (10 bytes)
93 * SAR Table Set, // Set#3 of SAR Table (10 bytes)
94 * SAR Table Set // Set#4 of SAR Table (10 bytes)
95 * }
96 * })
97 */
98 acpigen_write_name("EWRD");
99 acpigen_write_package(2);
100 acpigen_write_dword(EWRD_REVISION);
101 /*
102 * Emit 'Domain Type' + "Dynamic SAR Enable' + 'Extended SAR sets'
103 * + number of bytes for Set#2 & 3 & 4
104 */
105 package_size = 1 + 1 + 1 + (NUM_SAR_LIMITS - 1) * BYTES_PER_SAR_LIMIT;
106 acpigen_write_package(package_size);
107 acpigen_write_dword(EWRD_DOMAIN_TYPE_WIFI);
108 acpigen_write_dword(CONFIG(DSAR_ENABLE));
109 acpigen_write_dword(CONFIG_DSAR_SET_NUM);
110 for (i = 1; i < NUM_SAR_LIMITS; i++)
111 for (j = 0; j < BYTES_PER_SAR_LIMIT; j++)
112 acpigen_write_byte(sar_limits.sar_limit[i][j]);
113 acpigen_pop_len();
114 acpigen_pop_len();
115
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600116 if (!CONFIG(GEO_SAR_ENABLE))
117 return;
118
119 /*
120 * Name ("WGDS", Package() {
121 * Revision,
122 * Package() {
123 * DomainType, // 0x7:WiFi
124 * WgdsWiFiSarDeltaGroup1PowerMax1, // Group 1 FCC 2400 Max
125 * WgdsWiFiSarDeltaGroup1PowerChainA1, // Group 1 FCC 2400 A Offset
126 * WgdsWiFiSarDeltaGroup1PowerChainB1, // Group 1 FCC 2400 B Offset
127 * WgdsWiFiSarDeltaGroup1PowerMax2, // Group 1 FCC 5200 Max
128 * WgdsWiFiSarDeltaGroup1PowerChainA2, // Group 1 FCC 5200 A Offset
129 * WgdsWiFiSarDeltaGroup1PowerChainB2, // Group 1 FCC 5200 B Offset
130 * WgdsWiFiSarDeltaGroup2PowerMax1, // Group 2 EC Jap 2400 Max
131 * WgdsWiFiSarDeltaGroup2PowerChainA1, // Group 2 EC Jap 2400 A Offset
132 * WgdsWiFiSarDeltaGroup2PowerChainB1, // Group 2 EC Jap 2400 B Offset
133 * WgdsWiFiSarDeltaGroup2PowerMax2, // Group 2 EC Jap 5200 Max
134 * WgdsWiFiSarDeltaGroup2PowerChainA2, // Group 2 EC Jap 5200 A Offset
135 * WgdsWiFiSarDeltaGroup2PowerChainB2, // Group 2 EC Jap 5200 B Offset
136 * WgdsWiFiSarDeltaGroup3PowerMax1, // Group 3 ROW 2400 Max
137 * WgdsWiFiSarDeltaGroup3PowerChainA1, // Group 3 ROW 2400 A Offset
138 * WgdsWiFiSarDeltaGroup3PowerChainB1, // Group 3 ROW 2400 B Offset
139 * WgdsWiFiSarDeltaGroup3PowerMax2, // Group 3 ROW 5200 Max
140 * WgdsWiFiSarDeltaGroup3PowerChainA2, // Group 3 ROW 5200 A Offset
141 * WgdsWiFiSarDeltaGroup3PowerChainB2, // Group 3 ROW 5200 B Offset
142 * }
143 * })
144 */
145
146 wgds = &sar_limits.wgds;
147 acpigen_write_name("WGDS");
148 acpigen_write_package(2);
149 acpigen_write_dword(wgds->version);
150 /* Emit 'Domain Type' +
151 * Group specific delta of power (6 bytes * NUM_WGDS_SAR_GROUPS)
152 */
153 package_size = sizeof(sar_limits.wgds.group) + 1;
154 acpigen_write_package(package_size);
155 acpigen_write_dword(WGDS_DOMAIN_TYPE_WIFI);
156 for (i = 0; i < SAR_NUM_WGDS_GROUPS; i++) {
157 acpigen_write_byte(wgds->group[i].power_max_2400mhz);
158 acpigen_write_byte(wgds->group[i].power_chain_a_2400mhz);
159 acpigen_write_byte(wgds->group[i].power_chain_b_2400mhz);
160 acpigen_write_byte(wgds->group[i].power_max_5200mhz);
161 acpigen_write_byte(wgds->group[i].power_chain_a_5200mhz);
162 acpigen_write_byte(wgds->group[i].power_chain_b_5200mhz);
163 }
164
165 acpigen_pop_len();
166 acpigen_pop_len();
167}
168
Furquan Shaikh44f14502020-10-04 18:05:28 -0700169static void wifi_generic_fill_ssdt(const struct device *dev)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600170{
171 const char *path;
Furquan Shaikh44f14502020-10-04 18:05:28 -0700172 const struct drivers_wifi_generic_config *config = dev->chip_info;
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600173
174 if (!dev->enabled)
175 return;
176
177 path = acpi_device_path(dev->bus->dev);
178 if (!path)
179 return;
180
181 /* Device */
182 acpigen_write_scope(path);
183 acpigen_write_device(acpi_device_name(dev));
Patrick Rudolphc83bab62019-12-13 12:16:06 +0100184 acpi_device_write_uid(dev);
185
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600186 if (dev->chip_ops)
187 acpigen_write_name_string("_DDN", dev->chip_ops->name);
188
189 /* Address */
Furquan Shaikh2b5be882020-10-08 22:37:48 -0700190 acpigen_write_ADR_pci_device(dev);
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600191
192 /* Wake capabilities */
193 if (config)
Furquan Shaikh0af19262020-10-04 12:13:07 -0700194 acpigen_write_PRW(config->wake, ACPI_S3);
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600195
196 /* Fill regulatory domain structure */
197 if (CONFIG(HAVE_REGULATORY_DOMAIN)) {
198 /*
199 * Name ("WRDD", Package () {
200 * WRDD_REVISION, // Revision
201 * Package () {
202 * WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
203 * wifi_regulatory_domain() // Country Identifier
204 * }
205 * })
206 */
207 acpigen_write_name("WRDD");
208 acpigen_write_package(2);
209 acpigen_write_integer(WRDD_REVISION);
210 acpigen_write_package(2);
211 acpigen_write_dword(WRDD_DOMAIN_TYPE_WIFI);
212 acpigen_write_dword(wifi_regulatory_domain());
213 acpigen_pop_len();
214 acpigen_pop_len();
215 }
216
217 /* Fill Wifi sar related ACPI structures */
218 if (CONFIG(USE_SAR))
Furquan Shaikhe31506c2020-10-04 17:48:48 -0700219 emit_sar_acpi_structures(dev);
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600220
221 acpigen_pop_len(); /* Device */
222 acpigen_pop_len(); /* Scope */
223
224 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
225 dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
226}
227
Furquan Shaikh44f14502020-10-04 18:05:28 -0700228static const char *wifi_generic_acpi_name(const struct device *dev)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600229{
230 static char wifi_acpi_name[WIFI_ACPI_NAME_MAX_LEN];
231
Andrew McRae524bcbb2019-09-19 16:55:52 +1000232 /* ACPI 6.3, ASL 20.2.2: (Name Objects Encoding). */
233 snprintf(wifi_acpi_name, sizeof(wifi_acpi_name), "WF%02X",
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600234 (dev_path_encode(dev) & 0xff));
235 return wifi_acpi_name;
236}
Furquan Shaikh5e003392020-10-04 17:34:04 -0700237#endif
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600238
Furquan Shaikh54b27162020-10-03 16:33:07 -0700239static void wifi_pci_dev_init(struct device *dev)
240{
241 if (pci_dev_is_wake_source(dev))
242 elog_add_event_wake(ELOG_WAKE_SOURCE_PME_WIFI, 0);
243}
244
Furquan Shaikh7cb10342020-10-03 14:49:09 -0700245struct device_operations wifi_generic_ops = {
246 .read_resources = pci_dev_read_resources,
247 .set_resources = pci_dev_set_resources,
248 .enable_resources = pci_dev_enable_resources,
Furquan Shaikh54b27162020-10-03 16:33:07 -0700249 .init = wifi_pci_dev_init,
Furquan Shaikh7cb10342020-10-03 14:49:09 -0700250 .ops_pci = &pci_dev_ops_pci,
Furquan Shaikh5e003392020-10-04 17:34:04 -0700251#if CONFIG(HAVE_ACPI_TABLES)
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600252 .acpi_name = wifi_generic_acpi_name,
Furquan Shaikh44f14502020-10-04 18:05:28 -0700253 .acpi_fill_ssdt = wifi_generic_fill_ssdt,
Furquan Shaikh5e003392020-10-04 17:34:04 -0700254#endif
Furquan Shaikha1ddd2a2020-10-04 12:42:09 -0700255#if CONFIG(GENERATE_SMBIOS_TABLES)
256 .get_smbios_data = smbios_write_wifi,
257#endif
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600258};
259
260static void wifi_generic_enable(struct device *dev)
261{
262 struct drivers_wifi_generic_config *config = dev ? dev->chip_info : NULL;
263
264 if (!config)
265 return;
266
267 dev->ops = &wifi_generic_ops;
268}
269
270struct chip_operations drivers_wifi_generic_ops = {
271 CHIP_NAME("WIFI Device")
272 .enable_dev = wifi_generic_enable
273};
Furquan Shaikh8262a2c2020-10-10 19:53:00 -0700274
275static const unsigned short intel_pci_device_ids[] = {
276 PCI_DEVICE_ID_1000_SERIES_WIFI,
277 PCI_DEVICE_ID_6005_SERIES_WIFI,
278 PCI_DEVICE_ID_6005_I_SERIES_WIFI,
279 PCI_DEVICE_ID_1030_SERIES_WIFI,
280 PCI_DEVICE_ID_6030_I_SERIES_WIFI,
281 PCI_DEVICE_ID_6030_SERIES_WIFI,
282 PCI_DEVICE_ID_6150_SERIES_WIFI,
283 PCI_DEVICE_ID_2030_SERIES_WIFI,
284 PCI_DEVICE_ID_2000_SERIES_WIFI,
285 PCI_DEVICE_ID_0135_SERIES_WIFI,
286 PCI_DEVICE_ID_0105_SERIES_WIFI,
287 PCI_DEVICE_ID_6035_SERIES_WIFI,
288 PCI_DEVICE_ID_5300_SERIES_WIFI,
289 PCI_DEVICE_ID_5100_SERIES_WIFI,
290 PCI_DEVICE_ID_6000_SERIES_WIFI,
291 PCI_DEVICE_ID_6000_I_SERIES_WIFI,
292 PCI_DEVICE_ID_5350_SERIES_WIFI,
293 PCI_DEVICE_ID_5150_SERIES_WIFI,
294 /* Wilkins Peak 2 */
295 PCI_DEVICE_ID_WP_7260_SERIES_1_WIFI,
296 PCI_DEVICE_ID_WP_7260_SERIES_2_WIFI,
297 /* Stone Peak 2 */
298 PCI_DEVICE_ID_SP_7265_SERIES_1_WIFI,
299 PCI_DEVICE_ID_SP_7265_SERIES_2_WIFI,
300 /* Stone Field Peak */
301 PCI_DEVICE_ID_SFP_8260_SERIES_1_WIFI,
302 PCI_DEVICE_ID_SFP_8260_SERIES_2_WIFI,
303 /* Windstorm Peak */
304 PCI_DEVICE_ID_WSP_8275_SERIES_1_WIFI,
305 /* Jefferson Peak */
306 PCI_DEVICE_ID_JP_9000_SERIES_1_WIFI,
307 PCI_DEVICE_ID_JP_9000_SERIES_2_WIFI,
308 PCI_DEVICE_ID_JP_9000_SERIES_3_WIFI,
309 /* Thunder Peak 2 */
310 PCI_DEVICE_ID_TP_9260_SERIES_WIFI,
311 /* Harrison Peak */
312 PCI_DEVICE_ID_HrP_9560_SERIES_1_WIFI,
313 PCI_DEVICE_ID_HrP_9560_SERIES_2_WIFI,
314 PCI_DEVICE_ID_HrP_9560_SERIES_3_WIFI,
315 PCI_DEVICE_ID_HrP_9560_SERIES_4_WIFI,
316 PCI_DEVICE_ID_HrP_6SERIES_WIFI,
317 /* Cyclone Peak */
318 PCI_DEVICE_ID_CyP_6SERIES_WIFI,
319 /* Typhoon Peak */
320 PCI_DEVICE_ID_TyP_6SERIES_WIFI,
321 /* Garfield Peak */
322 PCI_DEVICE_ID_GrP_6SERIES_1_WIFI,
323 PCI_DEVICE_ID_GrP_6SERIES_2_WIFI,
324 0
325};
326
327/*
328 * The PCI driver is retained for backward compatibility with boards that never utilized the
329 * chip driver to support Intel WiFi device. For these devices, the PCI driver helps perform the
330 * same operations as above (except exposing the wake property) by utilizing the same
331 * `wifi_generic_ops`.
332 */
333static const struct pci_driver intel_wifi_pci_driver __pci_driver = {
334 .ops = &wifi_generic_ops,
335 .vendor = PCI_VENDOR_ID_INTEL,
336 .devices = intel_pci_device_ids,
337};