thermal_lib.c 5.0 KB

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