1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
5 */
6
7 #include "core.h"
8 #include "acpi.h"
9 #include "debug.h"
10
ath12k_acpi_dsm_get_data(struct ath12k_base * ab,int func)11 static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func)
12 {
13 union acpi_object *obj;
14 acpi_handle root_handle;
15 int ret;
16
17 root_handle = ACPI_HANDLE(ab->dev);
18 if (!root_handle) {
19 ath12k_dbg(ab, ATH12K_DBG_BOOT, "invalid acpi handler\n");
20 return -EOPNOTSUPP;
21 }
22
23 obj = acpi_evaluate_dsm(root_handle, ab->hw_params->acpi_guid, 0, func,
24 NULL);
25
26 if (!obj) {
27 ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_evaluate_dsm() failed\n");
28 return -ENOENT;
29 }
30
31 if (obj->type == ACPI_TYPE_INTEGER) {
32 ab->acpi.func_bit = obj->integer.value;
33 } else if (obj->type == ACPI_TYPE_BUFFER) {
34 switch (func) {
35 case ATH12K_ACPI_DSM_FUNC_TAS_CFG:
36 if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_CFG_SIZE) {
37 ath12k_warn(ab, "invalid ACPI DSM TAS config size: %d\n",
38 obj->buffer.length);
39 ret = -EINVAL;
40 goto out;
41 }
42
43 memcpy(&ab->acpi.tas_cfg, obj->buffer.pointer,
44 obj->buffer.length);
45
46 break;
47 case ATH12K_ACPI_DSM_FUNC_TAS_DATA:
48 if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_DATA_SIZE) {
49 ath12k_warn(ab, "invalid ACPI DSM TAS data size: %d\n",
50 obj->buffer.length);
51 ret = -EINVAL;
52 goto out;
53 }
54
55 memcpy(&ab->acpi.tas_sar_power_table, obj->buffer.pointer,
56 obj->buffer.length);
57
58 break;
59 case ATH12K_ACPI_DSM_FUNC_BIOS_SAR:
60 if (obj->buffer.length != ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE) {
61 ath12k_warn(ab, "invalid ACPI BIOS SAR data size: %d\n",
62 obj->buffer.length);
63 ret = -EINVAL;
64 goto out;
65 }
66
67 memcpy(&ab->acpi.bios_sar_data, obj->buffer.pointer,
68 obj->buffer.length);
69
70 break;
71 case ATH12K_ACPI_DSM_FUNC_GEO_OFFSET:
72 if (obj->buffer.length != ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE) {
73 ath12k_warn(ab, "invalid ACPI GEO OFFSET data size: %d\n",
74 obj->buffer.length);
75 ret = -EINVAL;
76 goto out;
77 }
78
79 memcpy(&ab->acpi.geo_offset_data, obj->buffer.pointer,
80 obj->buffer.length);
81
82 break;
83 case ATH12K_ACPI_DSM_FUNC_INDEX_CCA:
84 if (obj->buffer.length != ATH12K_ACPI_DSM_CCA_DATA_SIZE) {
85 ath12k_warn(ab, "invalid ACPI DSM CCA data size: %d\n",
86 obj->buffer.length);
87 ret = -EINVAL;
88 goto out;
89 }
90
91 memcpy(&ab->acpi.cca_data, obj->buffer.pointer,
92 obj->buffer.length);
93
94 break;
95 case ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE:
96 if (obj->buffer.length != ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE) {
97 ath12k_warn(ab, "invalid ACPI DSM band edge data size: %d\n",
98 obj->buffer.length);
99 ret = -EINVAL;
100 goto out;
101 }
102
103 memcpy(&ab->acpi.band_edge_power, obj->buffer.pointer,
104 obj->buffer.length);
105
106 break;
107 }
108 } else {
109 ath12k_warn(ab, "ACPI DSM method returned an unsupported object type: %d\n",
110 obj->type);
111 ret = -EINVAL;
112 goto out;
113 }
114
115 ret = 0;
116
117 out:
118 ACPI_FREE(obj);
119 return ret;
120 }
121
ath12k_acpi_set_power_limit(struct ath12k_base * ab)122 static int ath12k_acpi_set_power_limit(struct ath12k_base *ab)
123 {
124 const u8 *tas_sar_power_table = ab->acpi.tas_sar_power_table;
125 int ret;
126
127 if (tas_sar_power_table[0] != ATH12K_ACPI_TAS_DATA_VERSION ||
128 tas_sar_power_table[1] != ATH12K_ACPI_TAS_DATA_ENABLE) {
129 ath12k_warn(ab, "latest ACPI TAS data is invalid\n");
130 return -EINVAL;
131 }
132
133 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
134 tas_sar_power_table,
135 ATH12K_ACPI_DSM_TAS_DATA_SIZE);
136 if (ret) {
137 ath12k_warn(ab, "failed to send ACPI TAS data table: %d\n", ret);
138 return ret;
139 }
140
141 return ret;
142 }
143
ath12k_acpi_set_bios_sar_power(struct ath12k_base * ab)144 static int ath12k_acpi_set_bios_sar_power(struct ath12k_base *ab)
145 {
146 int ret;
147
148 if (ab->acpi.bios_sar_data[0] != ATH12K_ACPI_POWER_LIMIT_VERSION ||
149 ab->acpi.bios_sar_data[1] != ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG) {
150 ath12k_warn(ab, "invalid latest ACPI BIOS SAR data\n");
151 return -EINVAL;
152 }
153
154 ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
155 if (ret) {
156 ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
157 return ret;
158 }
159
160 return 0;
161 }
162
ath12k_acpi_dsm_notify(acpi_handle handle,u32 event,void * data)163 static void ath12k_acpi_dsm_notify(acpi_handle handle, u32 event, void *data)
164 {
165 int ret;
166 struct ath12k_base *ab = data;
167
168 if (event == ATH12K_ACPI_NOTIFY_EVENT) {
169 ath12k_warn(ab, "unknown acpi notify %u\n", event);
170 return;
171 }
172
173 if (!ab->acpi.acpi_tas_enable) {
174 ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_tas_enable is false\n");
175 return;
176 }
177
178 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
179 if (ret) {
180 ath12k_warn(ab, "failed to update ACPI TAS data table: %d\n", ret);
181 return;
182 }
183
184 ret = ath12k_acpi_set_power_limit(ab);
185 if (ret) {
186 ath12k_warn(ab, "failed to set ACPI TAS power limit data: %d", ret);
187 return;
188 }
189
190 if (!ab->acpi.acpi_bios_sar_enable)
191 return;
192
193 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
194 if (ret) {
195 ath12k_warn(ab, "failed to update BIOS SAR: %d\n", ret);
196 return;
197 }
198
199 ret = ath12k_acpi_set_bios_sar_power(ab);
200 if (ret) {
201 ath12k_warn(ab, "failed to set BIOS SAR power limit: %d\n", ret);
202 return;
203 }
204 }
205
ath12k_acpi_set_bios_sar_params(struct ath12k_base * ab)206 static int ath12k_acpi_set_bios_sar_params(struct ath12k_base *ab)
207 {
208 int ret;
209
210 ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
211 if (ret) {
212 ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
213 return ret;
214 }
215
216 ret = ath12k_wmi_set_bios_geo_cmd(ab, ab->acpi.geo_offset_data);
217 if (ret) {
218 ath12k_warn(ab, "failed to set ACPI BIOS GEO table: %d\n", ret);
219 return ret;
220 }
221
222 return 0;
223 }
224
ath12k_acpi_set_tas_params(struct ath12k_base * ab)225 static int ath12k_acpi_set_tas_params(struct ath12k_base *ab)
226 {
227 int ret;
228
229 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_CONFIG_TYPE,
230 ab->acpi.tas_cfg,
231 ATH12K_ACPI_DSM_TAS_CFG_SIZE);
232 if (ret) {
233 ath12k_warn(ab, "failed to send ACPI TAS config table parameter: %d\n",
234 ret);
235 return ret;
236 }
237
238 ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
239 ab->acpi.tas_sar_power_table,
240 ATH12K_ACPI_DSM_TAS_DATA_SIZE);
241 if (ret) {
242 ath12k_warn(ab, "failed to send ACPI TAS data table parameter: %d\n",
243 ret);
244 return ret;
245 }
246
247 return 0;
248 }
249
ath12k_acpi_start(struct ath12k_base * ab)250 int ath12k_acpi_start(struct ath12k_base *ab)
251 {
252 acpi_status status;
253 u8 *buf;
254 int ret;
255
256 if (!ab->hw_params->acpi_guid)
257 /* not supported with this hardware */
258 return 0;
259
260 ab->acpi.acpi_tas_enable = false;
261
262 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS);
263 if (ret) {
264 ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to get ACPI DSM data: %d\n", ret);
265 return ret;
266 }
267
268 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG)) {
269 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_CFG);
270 if (ret) {
271 ath12k_warn(ab, "failed to get ACPI TAS config table: %d\n", ret);
272 return ret;
273 }
274 }
275
276 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_DATA)) {
277 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
278 if (ret) {
279 ath12k_warn(ab, "failed to get ACPI TAS data table: %d\n", ret);
280 return ret;
281 }
282
283 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG) &&
284 ab->acpi.tas_sar_power_table[0] == ATH12K_ACPI_TAS_DATA_VERSION &&
285 ab->acpi.tas_sar_power_table[1] == ATH12K_ACPI_TAS_DATA_ENABLE)
286 ab->acpi.acpi_tas_enable = true;
287 }
288
289 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR)) {
290 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
291 if (ret) {
292 ath12k_warn(ab, "failed to get ACPI bios sar data: %d\n", ret);
293 return ret;
294 }
295 }
296
297 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_GEO_OFFSET)) {
298 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_GEO_OFFSET);
299 if (ret) {
300 ath12k_warn(ab, "failed to get ACPI geo offset data: %d\n", ret);
301 return ret;
302 }
303
304 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR) &&
305 ab->acpi.bios_sar_data[0] == ATH12K_ACPI_POWER_LIMIT_VERSION &&
306 ab->acpi.bios_sar_data[1] == ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG &&
307 !ab->acpi.acpi_tas_enable)
308 ab->acpi.acpi_bios_sar_enable = true;
309 }
310
311 if (ab->acpi.acpi_tas_enable) {
312 ret = ath12k_acpi_set_tas_params(ab);
313 if (ret) {
314 ath12k_warn(ab, "failed to send ACPI parameters: %d\n", ret);
315 return ret;
316 }
317 }
318
319 if (ab->acpi.acpi_bios_sar_enable) {
320 ret = ath12k_acpi_set_bios_sar_params(ab);
321 if (ret)
322 return ret;
323 }
324
325 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_CCA)) {
326 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_CCA);
327 if (ret) {
328 ath12k_warn(ab, "failed to get ACPI DSM CCA threshold configuration: %d\n",
329 ret);
330 return ret;
331 }
332
333 if (ab->acpi.cca_data[0] == ATH12K_ACPI_CCA_THR_VERSION &&
334 ab->acpi.cca_data[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET] ==
335 ATH12K_ACPI_CCA_THR_ENABLE_FLAG) {
336 buf = ab->acpi.cca_data + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET;
337 ret = ath12k_wmi_set_bios_cmd(ab,
338 WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE,
339 buf,
340 ATH12K_ACPI_CCA_THR_OFFSET_LEN);
341 if (ret) {
342 ath12k_warn(ab, "failed to set ACPI DSM CCA threshold: %d\n",
343 ret);
344 return ret;
345 }
346 }
347 }
348
349 if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi,
350 ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER)) {
351 ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE);
352 if (ret) {
353 ath12k_warn(ab, "failed to get ACPI DSM band edge channel power: %d\n",
354 ret);
355 return ret;
356 }
357
358 if (ab->acpi.band_edge_power[0] == ATH12K_ACPI_BAND_EDGE_VERSION &&
359 ab->acpi.band_edge_power[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG) {
360 ret = ath12k_wmi_set_bios_cmd(ab,
361 WMI_BIOS_PARAM_TYPE_BANDEDGE,
362 ab->acpi.band_edge_power,
363 sizeof(ab->acpi.band_edge_power));
364 if (ret) {
365 ath12k_warn(ab,
366 "failed to set ACPI DSM band edge channel power: %d\n",
367 ret);
368 return ret;
369 }
370 }
371 }
372
373 status = acpi_install_notify_handler(ACPI_HANDLE(ab->dev),
374 ACPI_DEVICE_NOTIFY,
375 ath12k_acpi_dsm_notify, ab);
376 if (ACPI_FAILURE(status)) {
377 ath12k_warn(ab, "failed to install DSM notify callback: %d\n", status);
378 return -EIO;
379 }
380
381 ab->acpi.started = true;
382
383 return 0;
384 }
385
ath12k_acpi_stop(struct ath12k_base * ab)386 void ath12k_acpi_stop(struct ath12k_base *ab)
387 {
388 if (!ab->acpi.started)
389 return;
390
391 acpi_remove_notify_handler(ACPI_HANDLE(ab->dev),
392 ACPI_DEVICE_NOTIFY,
393 ath12k_acpi_dsm_notify);
394
395 memset(&ab->acpi, 0, sizeof(ab->acpi));
396 }
397