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 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 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 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 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 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 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 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 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