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>
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
38 int get_wifi_sar_limits(struct wifi_sar_limits
*sar_limits
)
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");
56 * Name ("WRDS", 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)
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
]);
79 * Name ("EWRD", 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)
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
]);
110 if (!CONFIG(GEO_SAR_ENABLE
))
114 * Name ("WGDS", 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
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
);
163 void generic_wifi_fill_ssdt(const struct device
*dev
,
164 const struct generic_wifi_config
*config
)
172 path
= acpi_device_path(dev
->bus
->dev
);
177 acpigen_write_scope(path
);
178 acpigen_write_device(acpi_device_name(dev
));
179 acpi_device_write_uid(dev
);
182 acpigen_write_name_string("_DDN", dev
->chip_ops
->name
);
185 address
= PCI_SLOT(dev
->path
.pci
.devfn
) & 0xffff;
187 address
|= PCI_FUNC(dev
->path
.pci
.devfn
) & 0xffff;
188 acpigen_write_name_dword("_ADR", address
);
190 /* Wake capabilities */
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
200 * WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
201 * wifi_regulatory_domain() // Country Identifier
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());
215 /* Fill Wifi sar related ACPI structures */
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
;