|
| 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); |
0 commit comments