Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Feb 10-13, 2025
Register
Loading...
Note: File does not exist in v4.10.11.
  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);