Skip to content

Commit 7a0e397

Browse files
committed
thermal: ACPI: Add ACPI trip point routines
Add library routines to populate a generic thermal trip point structure with data obtained by evaluating a specific object in the ACPI Namespace. Signed-off-by: Rafael J. Wysocki <[email protected]> Co-developed-by: Daniel Lezcano <[email protected]> Signed-off-by: Daniel Lezcano <[email protected]> Tested-by: Srinivas Pandruvada <[email protected]>
1 parent 40dc192 commit 7a0e397

File tree

4 files changed

+163
-0
lines changed

4 files changed

+163
-0
lines changed

drivers/thermal/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ config THERMAL_OF
7676
Say 'Y' here if you need to build thermal infrastructure
7777
based on device tree.
7878

79+
config THERMAL_ACPI
80+
depends on ACPI
81+
bool
82+
7983
config THERMAL_WRITABLE_TRIPS
8084
bool "Enable writable trip points"
8185
help

drivers/thermal/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o
1313
# interface to/from other layers providing sensors
1414
thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
1515
thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o
16+
thermal_sys-$(CONFIG_THERMAL_ACPI) += thermal_acpi.o
1617

1718
# governors
1819
thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += gov_fair_share.o

drivers/thermal/thermal_acpi.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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+
24+
static int thermal_acpi_trip_init(struct acpi_device *adev,
25+
enum thermal_trip_type type, int id,
26+
struct thermal_trip *trip)
27+
{
28+
unsigned long long temp;
29+
acpi_status status;
30+
char obj_name[5];
31+
32+
switch (type) {
33+
case THERMAL_TRIP_ACTIVE:
34+
if (id < 0 || id > 9)
35+
return -EINVAL;
36+
37+
obj_name[1] = 'A';
38+
obj_name[2] = 'C';
39+
obj_name[3] = '0' + id;
40+
break;
41+
case THERMAL_TRIP_PASSIVE:
42+
obj_name[1] = 'P';
43+
obj_name[2] = 'S';
44+
obj_name[3] = 'V';
45+
break;
46+
case THERMAL_TRIP_HOT:
47+
obj_name[1] = 'H';
48+
obj_name[2] = 'O';
49+
obj_name[3] = 'T';
50+
break;
51+
case THERMAL_TRIP_CRITICAL:
52+
obj_name[1] = 'C';
53+
obj_name[2] = 'R';
54+
obj_name[3] = 'T';
55+
break;
56+
}
57+
58+
obj_name[0] = '_';
59+
obj_name[4] = '\0';
60+
61+
status = acpi_evaluate_integer(adev->handle, obj_name, NULL, &temp);
62+
if (ACPI_FAILURE(status)) {
63+
acpi_handle_debug(adev->handle, "%s evaluation failed\n", obj_name);
64+
return -ENODATA;
65+
}
66+
67+
if (temp < TEMP_MIN_DECIK || temp >= TEMP_MAX_DECIK) {
68+
acpi_handle_debug(adev->handle, "%s result %llu out of range\n",
69+
obj_name, temp);
70+
return -ENODATA;
71+
}
72+
73+
trip->temperature = deci_kelvin_to_millicelsius(temp);
74+
trip->hysteresis = 0;
75+
trip->type = type;
76+
77+
return 0;
78+
}
79+
80+
/**
81+
* thermal_acpi_trip_active - Get the specified active trip point
82+
* @adev: Thermal zone ACPI device object to get the description from.
83+
* @id: Active cooling level (0 - 9).
84+
* @trip: Trip point structure to be populated on success.
85+
*
86+
* Evaluate the _ACx object for the thermal zone represented by @adev to obtain
87+
* the temperature of the active cooling trip point corresponding to the active
88+
* cooling level given by @id and initialize @trip as an active trip point using
89+
* that temperature value.
90+
*
91+
* Return 0 on success or a negative error value on failure.
92+
*/
93+
int thermal_acpi_trip_active(struct acpi_device *adev, int id,
94+
struct thermal_trip *trip)
95+
{
96+
return thermal_acpi_trip_init(adev, THERMAL_TRIP_ACTIVE, id, trip);
97+
}
98+
EXPORT_SYMBOL_GPL(thermal_acpi_trip_active);
99+
100+
/**
101+
* thermal_acpi_trip_passive - Get the passive trip point
102+
* @adev: Thermal zone ACPI device object to get the description from.
103+
* @trip: Trip point structure to be populated on success.
104+
*
105+
* Evaluate the _PSV object for the thermal zone represented by @adev to obtain
106+
* the temperature of the passive cooling trip point and initialize @trip as a
107+
* passive trip point using that temperature value.
108+
*
109+
* Return 0 on success or -ENODATA on failure.
110+
*/
111+
int thermal_acpi_trip_passive(struct acpi_device *adev, struct thermal_trip *trip)
112+
{
113+
return thermal_acpi_trip_init(adev, THERMAL_TRIP_PASSIVE, INT_MAX, trip);
114+
}
115+
EXPORT_SYMBOL_GPL(thermal_acpi_trip_passive);
116+
117+
/**
118+
* thermal_acpi_trip_hot - Get the near critical trip point
119+
* @adev: the ACPI device to get the description from.
120+
* @trip: a &struct thermal_trip to be filled if the function succeed.
121+
*
122+
* Evaluate the _HOT object for the thermal zone represented by @adev to obtain
123+
* the temperature of the trip point at which the system is expected to be put
124+
* into the S4 sleep state and initialize @trip as a hot trip point using that
125+
* temperature value.
126+
*
127+
* Return 0 on success or -ENODATA on failure.
128+
*/
129+
int thermal_acpi_trip_hot(struct acpi_device *adev, struct thermal_trip *trip)
130+
{
131+
return thermal_acpi_trip_init(adev, THERMAL_TRIP_HOT, INT_MAX, trip);
132+
}
133+
EXPORT_SYMBOL_GPL(thermal_acpi_trip_hot);
134+
135+
/**
136+
* thermal_acpi_trip_critical - Get the critical trip point
137+
* @adev: the ACPI device to get the description from.
138+
* @trip: a &struct thermal_trip to be filled if the function succeed.
139+
*
140+
* Evaluate the _CRT object for the thermal zone represented by @adev to obtain
141+
* the temperature of the critical cooling trip point and initialize @trip as a
142+
* critical trip point using that temperature value.
143+
*
144+
* Return 0 on success or -ENODATA on failure.
145+
*/
146+
int thermal_acpi_trip_critical(struct acpi_device *adev, struct thermal_trip *trip)
147+
{
148+
return thermal_acpi_trip_init(adev, THERMAL_TRIP_CRITICAL, INT_MAX, trip);
149+
}
150+
EXPORT_SYMBOL_GPL(thermal_acpi_trip_critical);

include/linux/thermal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,14 @@ int thermal_zone_get_num_trips(struct thermal_zone_device *tz);
346346

347347
int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp);
348348

349+
#ifdef CONFIG_THERMAL_ACPI
350+
int thermal_acpi_trip_active(struct acpi_device *adev, int id,
351+
struct thermal_trip *trip);
352+
int thermal_acpi_trip_passive(struct acpi_device *adev, struct thermal_trip *trip);
353+
int thermal_acpi_trip_hot(struct acpi_device *adev, struct thermal_trip *trip);
354+
int thermal_acpi_trip_critical(struct acpi_device *adev, struct thermal_trip *trip);
355+
#endif
356+
349357
#ifdef CONFIG_THERMAL
350358
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
351359
void *, struct thermal_zone_device_ops *,

0 commit comments

Comments
 (0)