treewide: replace GPLv2 long form headers with SPDX header
[coreboot.git] / src / drivers / wifi / generic.c
blobd3b0a529bca125d4649484b0b4be38743e7d6cf1
1 /* This file is part of the coreboot project. */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <acpi/acpi_device.h>
5 #include <acpi/acpigen.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci_def.h>
9 #include <sar.h>
10 #include <string.h>
11 #include <wrdd.h>
12 #include "generic_wifi.h"
14 /* WRDS Spec Revision */
15 #define WRDS_REVISION 0x0
17 /* EWRD Spec Revision */
18 #define EWRD_REVISION 0x0
20 /* WRDS Domain type */
21 #define WRDS_DOMAIN_TYPE_WIFI 0x7
23 /* EWRD Domain type */
24 #define EWRD_DOMAIN_TYPE_WIFI 0x7
26 /* WGDS Domain type */
27 #define WGDS_DOMAIN_TYPE_WIFI 0x7
30 * WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
31 * The above representation returns unique and consistent name every time
32 * generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
33 * chosen since it contains the bus address of the device.
35 #define WIFI_ACPI_NAME_MAX_LEN 5
37 __weak
38 int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
40 return -1;
43 static void emit_sar_acpi_structures(void)
45 int i, j, package_size;
46 struct wifi_sar_limits sar_limits;
47 struct wifi_sar_delta_table *wgds;
49 /* Retrieve the sar limits data */
50 if (get_wifi_sar_limits(&sar_limits) < 0) {
51 printk(BIOS_ERR, "Error: failed from getting SAR limits!\n");
52 return;
56 * Name ("WRDS", Package () {
57 * Revision,
58 * Package () {
59 * Domain Type, // 0x7:WiFi
60 * WiFi SAR BIOS, // BIOS SAR Enable/disable
61 * SAR Table Set // Set#1 of SAR Table (10 bytes)
62 * }
63 * })
65 acpigen_write_name("WRDS");
66 acpigen_write_package(2);
67 acpigen_write_dword(WRDS_REVISION);
68 /* Emit 'Domain Type' + 'WiFi SAR BIOS' + 10 bytes for Set#1 */
69 package_size = 1 + 1 + BYTES_PER_SAR_LIMIT;
70 acpigen_write_package(package_size);
71 acpigen_write_dword(WRDS_DOMAIN_TYPE_WIFI);
72 acpigen_write_dword(CONFIG(SAR_ENABLE));
73 for (i = 0; i < BYTES_PER_SAR_LIMIT; i++)
74 acpigen_write_byte(sar_limits.sar_limit[0][i]);
75 acpigen_pop_len();
76 acpigen_pop_len();
79 * Name ("EWRD", Package () {
80 * Revision,
81 * Package () {
82 * Domain Type, // 0x7:WiFi
83 * Dynamic SAR Enable, // Dynamic SAR Enable/disable
84 * Extended SAR sets, // Number of optional SAR table sets
85 * SAR Table Set, // Set#2 of SAR Table (10 bytes)
86 * SAR Table Set, // Set#3 of SAR Table (10 bytes)
87 * SAR Table Set // Set#4 of SAR Table (10 bytes)
88 * }
89 * })
91 acpigen_write_name("EWRD");
92 acpigen_write_package(2);
93 acpigen_write_dword(EWRD_REVISION);
95 * Emit 'Domain Type' + "Dynamic SAR Enable' + 'Extended SAR sets'
96 * + number of bytes for Set#2 & 3 & 4
98 package_size = 1 + 1 + 1 + (NUM_SAR_LIMITS - 1) * BYTES_PER_SAR_LIMIT;
99 acpigen_write_package(package_size);
100 acpigen_write_dword(EWRD_DOMAIN_TYPE_WIFI);
101 acpigen_write_dword(CONFIG(DSAR_ENABLE));
102 acpigen_write_dword(CONFIG_DSAR_SET_NUM);
103 for (i = 1; i < NUM_SAR_LIMITS; i++)
104 for (j = 0; j < BYTES_PER_SAR_LIMIT; j++)
105 acpigen_write_byte(sar_limits.sar_limit[i][j]);
106 acpigen_pop_len();
107 acpigen_pop_len();
110 if (!CONFIG(GEO_SAR_ENABLE))
111 return;
114 * Name ("WGDS", Package() {
115 * Revision,
116 * Package() {
117 * DomainType, // 0x7:WiFi
118 * WgdsWiFiSarDeltaGroup1PowerMax1, // Group 1 FCC 2400 Max
119 * WgdsWiFiSarDeltaGroup1PowerChainA1, // Group 1 FCC 2400 A Offset
120 * WgdsWiFiSarDeltaGroup1PowerChainB1, // Group 1 FCC 2400 B Offset
121 * WgdsWiFiSarDeltaGroup1PowerMax2, // Group 1 FCC 5200 Max
122 * WgdsWiFiSarDeltaGroup1PowerChainA2, // Group 1 FCC 5200 A Offset
123 * WgdsWiFiSarDeltaGroup1PowerChainB2, // Group 1 FCC 5200 B Offset
124 * WgdsWiFiSarDeltaGroup2PowerMax1, // Group 2 EC Jap 2400 Max
125 * WgdsWiFiSarDeltaGroup2PowerChainA1, // Group 2 EC Jap 2400 A Offset
126 * WgdsWiFiSarDeltaGroup2PowerChainB1, // Group 2 EC Jap 2400 B Offset
127 * WgdsWiFiSarDeltaGroup2PowerMax2, // Group 2 EC Jap 5200 Max
128 * WgdsWiFiSarDeltaGroup2PowerChainA2, // Group 2 EC Jap 5200 A Offset
129 * WgdsWiFiSarDeltaGroup2PowerChainB2, // Group 2 EC Jap 5200 B Offset
130 * WgdsWiFiSarDeltaGroup3PowerMax1, // Group 3 ROW 2400 Max
131 * WgdsWiFiSarDeltaGroup3PowerChainA1, // Group 3 ROW 2400 A Offset
132 * WgdsWiFiSarDeltaGroup3PowerChainB1, // Group 3 ROW 2400 B Offset
133 * WgdsWiFiSarDeltaGroup3PowerMax2, // Group 3 ROW 5200 Max
134 * WgdsWiFiSarDeltaGroup3PowerChainA2, // Group 3 ROW 5200 A Offset
135 * WgdsWiFiSarDeltaGroup3PowerChainB2, // Group 3 ROW 5200 B Offset
137 * })
140 wgds = &sar_limits.wgds;
141 acpigen_write_name("WGDS");
142 acpigen_write_package(2);
143 acpigen_write_dword(wgds->version);
144 /* Emit 'Domain Type' +
145 * Group specific delta of power (6 bytes * NUM_WGDS_SAR_GROUPS)
147 package_size = sizeof(sar_limits.wgds.group) + 1;
148 acpigen_write_package(package_size);
149 acpigen_write_dword(WGDS_DOMAIN_TYPE_WIFI);
150 for (i = 0; i < SAR_NUM_WGDS_GROUPS; i++) {
151 acpigen_write_byte(wgds->group[i].power_max_2400mhz);
152 acpigen_write_byte(wgds->group[i].power_chain_a_2400mhz);
153 acpigen_write_byte(wgds->group[i].power_chain_b_2400mhz);
154 acpigen_write_byte(wgds->group[i].power_max_5200mhz);
155 acpigen_write_byte(wgds->group[i].power_chain_a_5200mhz);
156 acpigen_write_byte(wgds->group[i].power_chain_b_5200mhz);
159 acpigen_pop_len();
160 acpigen_pop_len();
163 void generic_wifi_fill_ssdt(const struct device *dev,
164 const struct generic_wifi_config *config)
166 const char *path;
167 u32 address;
169 if (!dev->enabled)
170 return;
172 path = acpi_device_path(dev->bus->dev);
173 if (!path)
174 return;
176 /* Device */
177 acpigen_write_scope(path);
178 acpigen_write_device(acpi_device_name(dev));
179 acpi_device_write_uid(dev);
181 if (dev->chip_ops)
182 acpigen_write_name_string("_DDN", dev->chip_ops->name);
184 /* Address */
185 address = PCI_SLOT(dev->path.pci.devfn) & 0xffff;
186 address <<= 16;
187 address |= PCI_FUNC(dev->path.pci.devfn) & 0xffff;
188 acpigen_write_name_dword("_ADR", address);
190 /* Wake capabilities */
191 if (config)
192 acpigen_write_PRW(config->wake, config->maxsleep);
194 /* Fill regulatory domain structure */
195 if (CONFIG(HAVE_REGULATORY_DOMAIN)) {
197 * Name ("WRDD", Package () {
198 * WRDD_REVISION, // Revision
199 * Package () {
200 * WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
201 * wifi_regulatory_domain() // Country Identifier
203 * })
205 acpigen_write_name("WRDD");
206 acpigen_write_package(2);
207 acpigen_write_integer(WRDD_REVISION);
208 acpigen_write_package(2);
209 acpigen_write_dword(WRDD_DOMAIN_TYPE_WIFI);
210 acpigen_write_dword(wifi_regulatory_domain());
211 acpigen_pop_len();
212 acpigen_pop_len();
215 /* Fill Wifi sar related ACPI structures */
216 if (CONFIG(USE_SAR))
217 emit_sar_acpi_structures();
219 acpigen_pop_len(); /* Device */
220 acpigen_pop_len(); /* Scope */
222 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
223 dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
226 const char *generic_wifi_acpi_name(const struct device *dev)
228 static char wifi_acpi_name[WIFI_ACPI_NAME_MAX_LEN];
230 /* ACPI 6.3, ASL 20.2.2: (Name Objects Encoding). */
231 snprintf(wifi_acpi_name, sizeof(wifi_acpi_name), "WF%02X",
232 (dev_path_encode(dev) & 0xff));
233 return wifi_acpi_name;