at master 5.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright 2023 Linaro Limited 4 * Copyright 2023 Intel Corporation 5 * 6 * Library routines for retrieving trip point temperature values from the 7 * platform firmware via ACPI. 8 */ 9#include <linux/acpi.h> 10#include <linux/units.h> 11#include <linux/thermal.h> 12#include "internal.h" 13 14/* 15 * Minimum temperature for full military grade is 218°K (-55°C) and 16 * max temperature is 448°K (175°C). We can consider those values as 17 * the boundaries for the [trips] temperature returned by the 18 * firmware. Any values out of these boundaries may be considered 19 * bogus and we can assume the firmware has no data to provide. 20 */ 21#define TEMP_MIN_DECIK 2180ULL 22#define TEMP_MAX_DECIK 4480ULL 23 24static int acpi_trip_temp(struct acpi_device *adev, char *obj_name, 25 int *ret_temp) 26{ 27 unsigned long long temp; 28 acpi_status status; 29 30 status = acpi_evaluate_integer(adev->handle, obj_name, NULL, &temp); 31 if (ACPI_FAILURE(status)) { 32 acpi_handle_debug(adev->handle, "%s evaluation failed\n", obj_name); 33 return -ENODATA; 34 } 35 36 if (temp >= TEMP_MIN_DECIK && temp <= TEMP_MAX_DECIK) { 37 *ret_temp = temp; 38 } else { 39 acpi_handle_debug(adev->handle, "%s result %llu out of range\n", 40 obj_name, temp); 41 *ret_temp = THERMAL_TEMP_INVALID; 42 } 43 44 return 0; 45} 46 47int acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp) 48{ 49 char obj_name[] = {'_', 'A', 'C', '0' + id, '\0'}; 50 51 if (id < 0 || id > 9) 52 return -EINVAL; 53 54 return acpi_trip_temp(adev, obj_name, ret_temp); 55} 56EXPORT_SYMBOL_NS_GPL(acpi_active_trip_temp, "ACPI_THERMAL"); 57 58int acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp) 59{ 60 return acpi_trip_temp(adev, "_PSV", ret_temp); 61} 62EXPORT_SYMBOL_NS_GPL(acpi_passive_trip_temp, "ACPI_THERMAL"); 63 64int acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp) 65{ 66 return acpi_trip_temp(adev, "_HOT", ret_temp); 67} 68EXPORT_SYMBOL_NS_GPL(acpi_hot_trip_temp, "ACPI_THERMAL"); 69 70int acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp) 71{ 72 return acpi_trip_temp(adev, "_CRT", ret_temp); 73} 74EXPORT_SYMBOL_NS_GPL(acpi_critical_trip_temp, "ACPI_THERMAL"); 75 76static int thermal_temp(int error, int temp_decik, int *ret_temp) 77{ 78 if (error) 79 return error; 80 81 if (temp_decik == THERMAL_TEMP_INVALID) 82 *ret_temp = THERMAL_TEMP_INVALID; 83 else 84 *ret_temp = deci_kelvin_to_millicelsius(temp_decik); 85 86 return 0; 87} 88 89/** 90 * thermal_acpi_active_trip_temp - Retrieve active trip point temperature 91 * @adev: Target thermal zone ACPI device object. 92 * @id: Active cooling level (0 - 9). 93 * @ret_temp: Address to store the retrieved temperature value on success. 94 * 95 * Evaluate the _ACx object for the thermal zone represented by @adev to obtain 96 * the temperature of the active cooling trip point corresponding to the active 97 * cooling level given by @id. 98 * 99 * Return 0 on success or a negative error value on failure. 100 */ 101int thermal_acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp) 102{ 103 int temp_decik = 0; 104 int ret = acpi_active_trip_temp(adev, id, &temp_decik); 105 106 return thermal_temp(ret, temp_decik, ret_temp); 107} 108EXPORT_SYMBOL_GPL(thermal_acpi_active_trip_temp); 109 110/** 111 * thermal_acpi_passive_trip_temp - Retrieve passive trip point temperature 112 * @adev: Target thermal zone ACPI device object. 113 * @ret_temp: Address to store the retrieved temperature value on success. 114 * 115 * Evaluate the _PSV object for the thermal zone represented by @adev to obtain 116 * the temperature of the passive cooling trip point. 117 * 118 * Return 0 on success or -ENODATA on failure. 119 */ 120int thermal_acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp) 121{ 122 int temp_decik = 0; 123 int ret = acpi_passive_trip_temp(adev, &temp_decik); 124 125 return thermal_temp(ret, temp_decik, ret_temp); 126} 127EXPORT_SYMBOL_GPL(thermal_acpi_passive_trip_temp); 128 129/** 130 * thermal_acpi_hot_trip_temp - Retrieve hot trip point temperature 131 * @adev: Target thermal zone ACPI device object. 132 * @ret_temp: Address to store the retrieved temperature value on success. 133 * 134 * Evaluate the _HOT object for the thermal zone represented by @adev to obtain 135 * the temperature of the trip point at which the system is expected to be put 136 * into the S4 sleep state. 137 * 138 * Return 0 on success or -ENODATA on failure. 139 */ 140int thermal_acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp) 141{ 142 int temp_decik = 0; 143 int ret = acpi_hot_trip_temp(adev, &temp_decik); 144 145 return thermal_temp(ret, temp_decik, ret_temp); 146} 147EXPORT_SYMBOL_GPL(thermal_acpi_hot_trip_temp); 148 149/** 150 * thermal_acpi_critical_trip_temp - Retrieve critical trip point temperature 151 * @adev: Target thermal zone ACPI device object. 152 * @ret_temp: Address to store the retrieved temperature value on success. 153 * 154 * Evaluate the _CRT object for the thermal zone represented by @adev to obtain 155 * the temperature of the critical cooling trip point. 156 * 157 * Return 0 on success or -ENODATA on failure. 158 */ 159int thermal_acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp) 160{ 161 int temp_decik = 0; 162 int ret = acpi_critical_trip_temp(adev, &temp_decik); 163 164 return thermal_temp(ret, temp_decik, ret_temp); 165} 166EXPORT_SYMBOL_GPL(thermal_acpi_critical_trip_temp);