162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2023 Linaro Limited 462306a36Sopenharmony_ci * Copyright 2023 Intel Corporation 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Library routines for populating a generic thermal trip point structure 762306a36Sopenharmony_ci * with data obtained by evaluating a specific object in the ACPI Namespace. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/acpi.h> 1062306a36Sopenharmony_ci#include <linux/units.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "thermal_core.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* 1562306a36Sopenharmony_ci * Minimum temperature for full military grade is 218°K (-55°C) and 1662306a36Sopenharmony_ci * max temperature is 448°K (175°C). We can consider those values as 1762306a36Sopenharmony_ci * the boundaries for the [trips] temperature returned by the 1862306a36Sopenharmony_ci * firmware. Any values out of these boundaries may be considered 1962306a36Sopenharmony_ci * bogus and we can assume the firmware has no data to provide. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci#define TEMP_MIN_DECIK 2180 2262306a36Sopenharmony_ci#define TEMP_MAX_DECIK 4480 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic int thermal_acpi_trip_temp(struct acpi_device *adev, char *obj_name, 2562306a36Sopenharmony_ci int *ret_temp) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci unsigned long long temp; 2862306a36Sopenharmony_ci acpi_status status; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci status = acpi_evaluate_integer(adev->handle, obj_name, NULL, &temp); 3162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 3262306a36Sopenharmony_ci acpi_handle_debug(adev->handle, "%s evaluation failed\n", obj_name); 3362306a36Sopenharmony_ci return -ENODATA; 3462306a36Sopenharmony_ci } 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci if (temp >= TEMP_MIN_DECIK && temp <= TEMP_MAX_DECIK) { 3762306a36Sopenharmony_ci *ret_temp = deci_kelvin_to_millicelsius(temp); 3862306a36Sopenharmony_ci } else { 3962306a36Sopenharmony_ci acpi_handle_debug(adev->handle, "%s result %llu out of range\n", 4062306a36Sopenharmony_ci obj_name, temp); 4162306a36Sopenharmony_ci *ret_temp = THERMAL_TEMP_INVALID; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci return 0; 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/** 4862306a36Sopenharmony_ci * thermal_acpi_active_trip_temp - Retrieve active trip point temperature 4962306a36Sopenharmony_ci * @adev: Target thermal zone ACPI device object. 5062306a36Sopenharmony_ci * @id: Active cooling level (0 - 9). 5162306a36Sopenharmony_ci * @ret_temp: Address to store the retrieved temperature value on success. 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * Evaluate the _ACx object for the thermal zone represented by @adev to obtain 5462306a36Sopenharmony_ci * the temperature of the active cooling trip point corresponding to the active 5562306a36Sopenharmony_ci * cooling level given by @id. 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * Return 0 on success or a negative error value on failure. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ciint thermal_acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci char obj_name[] = {'_', 'A', 'C', '0' + id, '\0'}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (id < 0 || id > 9) 6462306a36Sopenharmony_ci return -EINVAL; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return thermal_acpi_trip_temp(adev, obj_name, ret_temp); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(thermal_acpi_active_trip_temp); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/** 7162306a36Sopenharmony_ci * thermal_acpi_passive_trip_temp - Retrieve passive trip point temperature 7262306a36Sopenharmony_ci * @adev: Target thermal zone ACPI device object. 7362306a36Sopenharmony_ci * @ret_temp: Address to store the retrieved temperature value on success. 7462306a36Sopenharmony_ci * 7562306a36Sopenharmony_ci * Evaluate the _PSV object for the thermal zone represented by @adev to obtain 7662306a36Sopenharmony_ci * the temperature of the passive cooling trip point. 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * Return 0 on success or -ENODATA on failure. 7962306a36Sopenharmony_ci */ 8062306a36Sopenharmony_ciint thermal_acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci return thermal_acpi_trip_temp(adev, "_PSV", ret_temp); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(thermal_acpi_passive_trip_temp); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/** 8762306a36Sopenharmony_ci * thermal_acpi_hot_trip_temp - Retrieve hot trip point temperature 8862306a36Sopenharmony_ci * @adev: Target thermal zone ACPI device object. 8962306a36Sopenharmony_ci * @ret_temp: Address to store the retrieved temperature value on success. 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * Evaluate the _HOT object for the thermal zone represented by @adev to obtain 9262306a36Sopenharmony_ci * the temperature of the trip point at which the system is expected to be put 9362306a36Sopenharmony_ci * into the S4 sleep state. 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * Return 0 on success or -ENODATA on failure. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ciint thermal_acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci return thermal_acpi_trip_temp(adev, "_HOT", ret_temp); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(thermal_acpi_hot_trip_temp); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/** 10462306a36Sopenharmony_ci * thermal_acpi_critical_trip_temp - Retrieve critical trip point temperature 10562306a36Sopenharmony_ci * @adev: Target thermal zone ACPI device object. 10662306a36Sopenharmony_ci * @ret_temp: Address to store the retrieved temperature value on success. 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * Evaluate the _CRT object for the thermal zone represented by @adev to obtain 10962306a36Sopenharmony_ci * the temperature of the critical cooling trip point. 11062306a36Sopenharmony_ci * 11162306a36Sopenharmony_ci * Return 0 on success or -ENODATA on failure. 11262306a36Sopenharmony_ci */ 11362306a36Sopenharmony_ciint thermal_acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci return thermal_acpi_trip_temp(adev, "_CRT", ret_temp); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(thermal_acpi_critical_trip_temp); 118