brintos

brintos / linux-shallow public Read only

0
0
Text · 10.2 KiB · 0555d35 Raw
397 lines · c
1// SPDX-License-Identifier: BSD-3-Clause-Clear2/*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 11static 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 117out:118	ACPI_FREE(obj);119	return ret;120}121 122static 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 144static 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 163static 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 206static 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 225static 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 250int 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 386void 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