blob: dd53da3b664a19464353d20617573848f7211562 [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
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600108 if (!CONFIG(GEO_SAR_ENABLE))
109 return;
110
111 /*
112 * Name ("WGDS", Package() {
113 * Revision,
114 * Package() {
115 * DomainType, // 0x7:WiFi
116 * WgdsWiFiSarDeltaGroup1PowerMax1, // Group 1 FCC 2400 Max
117 * WgdsWiFiSarDeltaGroup1PowerChainA1, // Group 1 FCC 2400 A Offset
118 * WgdsWiFiSarDeltaGroup1PowerChainB1, // Group 1 FCC 2400 B Offset
119 * WgdsWiFiSarDeltaGroup1PowerMax2, // Group 1 FCC 5200 Max
120 * WgdsWiFiSarDeltaGroup1PowerChainA2, // Group 1 FCC 5200 A Offset
121 * WgdsWiFiSarDeltaGroup1PowerChainB2, // Group 1 FCC 5200 B Offset
122 * WgdsWiFiSarDeltaGroup2PowerMax1, // Group 2 EC Jap 2400 Max
123 * WgdsWiFiSarDeltaGroup2PowerChainA1, // Group 2 EC Jap 2400 A Offset
124 * WgdsWiFiSarDeltaGroup2PowerChainB1, // Group 2 EC Jap 2400 B Offset
125 * WgdsWiFiSarDeltaGroup2PowerMax2, // Group 2 EC Jap 5200 Max
126 * WgdsWiFiSarDeltaGroup2PowerChainA2, // Group 2 EC Jap 5200 A Offset
127 * WgdsWiFiSarDeltaGroup2PowerChainB2, // Group 2 EC Jap 5200 B Offset
128 * WgdsWiFiSarDeltaGroup3PowerMax1, // Group 3 ROW 2400 Max
129 * WgdsWiFiSarDeltaGroup3PowerChainA1, // Group 3 ROW 2400 A Offset
130 * WgdsWiFiSarDeltaGroup3PowerChainB1, // Group 3 ROW 2400 B Offset
131 * WgdsWiFiSarDeltaGroup3PowerMax2, // Group 3 ROW 5200 Max
132 * WgdsWiFiSarDeltaGroup3PowerChainA2, // Group 3 ROW 5200 A Offset
133 * WgdsWiFiSarDeltaGroup3PowerChainB2, // Group 3 ROW 5200 B Offset
134 * }
135 * })
136 */
137
138 wgds = &sar_limits.wgds;
139 acpigen_write_name("WGDS");
140 acpigen_write_package(2);
141 acpigen_write_dword(wgds->version);
142 /* Emit 'Domain Type' +
143 * Group specific delta of power (6 bytes * NUM_WGDS_SAR_GROUPS)
144 */
145 package_size = sizeof(sar_limits.wgds.group) + 1;
146 acpigen_write_package(package_size);
147 acpigen_write_dword(WGDS_DOMAIN_TYPE_WIFI);
148 for (i = 0; i < SAR_NUM_WGDS_GROUPS; i++) {
149 acpigen_write_byte(wgds->group[i].power_max_2400mhz);
150 acpigen_write_byte(wgds->group[i].power_chain_a_2400mhz);
151 acpigen_write_byte(wgds->group[i].power_chain_b_2400mhz);
152 acpigen_write_byte(wgds->group[i].power_max_5200mhz);
153 acpigen_write_byte(wgds->group[i].power_chain_a_5200mhz);
154 acpigen_write_byte(wgds->group[i].power_chain_b_5200mhz);
155 }
156
157 acpigen_pop_len();
158 acpigen_pop_len();
159}
160
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600161void wifi_generic_fill_ssdt(const struct device *dev,
162 const struct drivers_wifi_generic_config *config)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600163{
164 const char *path;
165 u32 address;
166
167 if (!dev->enabled)
168 return;
169
170 path = acpi_device_path(dev->bus->dev);
171 if (!path)
172 return;
173
174 /* Device */
175 acpigen_write_scope(path);
176 acpigen_write_device(acpi_device_name(dev));
Patrick Rudolphc83bab62019-12-13 12:16:06 +0100177 acpi_device_write_uid(dev);
178
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600179 if (dev->chip_ops)
180 acpigen_write_name_string("_DDN", dev->chip_ops->name);
181
182 /* Address */
183 address = PCI_SLOT(dev->path.pci.devfn) & 0xffff;
184 address <<= 16;
185 address |= PCI_FUNC(dev->path.pci.devfn) & 0xffff;
186 acpigen_write_name_dword("_ADR", address);
187
188 /* Wake capabilities */
189 if (config)
190 acpigen_write_PRW(config->wake, config->maxsleep);
191
192 /* Fill regulatory domain structure */
193 if (CONFIG(HAVE_REGULATORY_DOMAIN)) {
194 /*
195 * Name ("WRDD", Package () {
196 * WRDD_REVISION, // Revision
197 * Package () {
198 * WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
199 * wifi_regulatory_domain() // Country Identifier
200 * }
201 * })
202 */
203 acpigen_write_name("WRDD");
204 acpigen_write_package(2);
205 acpigen_write_integer(WRDD_REVISION);
206 acpigen_write_package(2);
207 acpigen_write_dword(WRDD_DOMAIN_TYPE_WIFI);
208 acpigen_write_dword(wifi_regulatory_domain());
209 acpigen_pop_len();
210 acpigen_pop_len();
211 }
212
213 /* Fill Wifi sar related ACPI structures */
214 if (CONFIG(USE_SAR))
215 emit_sar_acpi_structures();
216
217 acpigen_pop_len(); /* Device */
218 acpigen_pop_len(); /* Scope */
219
220 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
221 dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
222}
223
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600224const char *wifi_generic_acpi_name(const struct device *dev)
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600225{
226 static char wifi_acpi_name[WIFI_ACPI_NAME_MAX_LEN];
227
Andrew McRae524bcbb2019-09-19 16:55:52 +1000228 /* ACPI 6.3, ASL 20.2.2: (Name Objects Encoding). */
229 snprintf(wifi_acpi_name, sizeof(wifi_acpi_name), "WF%02X",
Karthikeyan Ramasubramanianfd5d7882019-05-29 15:09:42 -0600230 (dev_path_encode(dev) & 0xff));
231 return wifi_acpi_name;
232}
Karthikeyan Ramasubramanianafeb7b32020-07-23 00:25:25 -0600233
234static void wifi_generic_fill_ssdt_generator(const struct device *dev)
235{
236 wifi_generic_fill_ssdt(dev, dev->chip_info);
237}
238
239static struct device_operations wifi_generic_ops = {
240 .read_resources = noop_read_resources,
241 .set_resources = noop_set_resources,
242 .acpi_name = wifi_generic_acpi_name,
243 .acpi_fill_ssdt = wifi_generic_fill_ssdt_generator,
244};
245
246static void wifi_generic_enable(struct device *dev)
247{
248 struct drivers_wifi_generic_config *config = dev ? dev->chip_info : NULL;
249
250 if (!config)
251 return;
252
253 dev->ops = &wifi_generic_ops;
254}
255
256struct chip_operations drivers_wifi_generic_ops = {
257 CHIP_NAME("WIFI Device")
258 .enable_dev = wifi_generic_enable
259};