1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2023 Linaro Limited
4 * Copyright 2023 Intel Corporation
5 *
6 * Library routines for populating a generic thermal trip point structure
7 * with data obtained by evaluating a specific object in the ACPI Namespace.
8 */
9#include <linux/acpi.h>
10#include <linux/units.h>
11
12#include "thermal_core.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	2180
22#define TEMP_MAX_DECIK	4480
23
24static int thermal_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 = deci_kelvin_to_millicelsius(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
47/**
48 * thermal_acpi_active_trip_temp - Retrieve active trip point temperature
49 * @adev: Target thermal zone ACPI device object.
50 * @id: Active cooling level (0 - 9).
51 * @ret_temp: Address to store the retrieved temperature value on success.
52 *
53 * Evaluate the _ACx object for the thermal zone represented by @adev to obtain
54 * the temperature of the active cooling trip point corresponding to the active
55 * cooling level given by @id.
56 *
57 * Return 0 on success or a negative error value on failure.
58 */
59int thermal_acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp)
60{
61	char obj_name[] = {'_', 'A', 'C', '0' + id, '\0'};
62
63	if (id < 0 || id > 9)
64		return -EINVAL;
65
66	return thermal_acpi_trip_temp(adev, obj_name, ret_temp);
67}
68EXPORT_SYMBOL_GPL(thermal_acpi_active_trip_temp);
69
70/**
71 * thermal_acpi_passive_trip_temp - Retrieve passive trip point temperature
72 * @adev: Target thermal zone ACPI device object.
73 * @ret_temp: Address to store the retrieved temperature value on success.
74 *
75 * Evaluate the _PSV object for the thermal zone represented by @adev to obtain
76 * the temperature of the passive cooling trip point.
77 *
78 * Return 0 on success or -ENODATA on failure.
79 */
80int thermal_acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp)
81{
82	return thermal_acpi_trip_temp(adev, "_PSV", ret_temp);
83}
84EXPORT_SYMBOL_GPL(thermal_acpi_passive_trip_temp);
85
86/**
87 * thermal_acpi_hot_trip_temp - Retrieve hot trip point temperature
88 * @adev: Target thermal zone ACPI device object.
89 * @ret_temp: Address to store the retrieved temperature value on success.
90 *
91 * Evaluate the _HOT object for the thermal zone represented by @adev to obtain
92 * the temperature of the trip point at which the system is expected to be put
93 * into the S4 sleep state.
94 *
95 * Return 0 on success or -ENODATA on failure.
96 */
97int thermal_acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp)
98{
99	return thermal_acpi_trip_temp(adev, "_HOT", ret_temp);
100}
101EXPORT_SYMBOL_GPL(thermal_acpi_hot_trip_temp);
102
103/**
104 * thermal_acpi_critical_trip_temp - Retrieve critical trip point temperature
105 * @adev: Target thermal zone ACPI device object.
106 * @ret_temp: Address to store the retrieved temperature value on success.
107 *
108 * Evaluate the _CRT object for the thermal zone represented by @adev to obtain
109 * the temperature of the critical cooling trip point.
110 *
111 * Return 0 on success or -ENODATA on failure.
112 */
113int thermal_acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp)
114{
115	return thermal_acpi_trip_temp(adev, "_CRT", ret_temp);
116}
117EXPORT_SYMBOL_GPL(thermal_acpi_critical_trip_temp);
118