2023-01-23 21:38:31 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2023 Linaro Limited
* Copyright 2023 Intel Corporation
*
2023-10-17 23:06:52 +03:00
* Library routines for retrieving trip point temperature values from the
* platform firmware via ACPI .
2023-01-23 21:38:31 +03:00
*/
# include <linux/acpi.h>
# include <linux/units.h>
2023-10-13 18:14:05 +03:00
# include <linux/thermal.h>
2023-11-23 09:59:57 +03:00
# include "internal.h"
2023-01-23 21:38:31 +03:00
/*
* Minimum temperature for full military grade is 218 ° K ( - 55 ° C ) and
* max temperature is 448 ° K ( 175 ° C ) . We can consider those values as
* the boundaries for the [ trips ] temperature returned by the
* firmware . Any values out of these boundaries may be considered
* bogus and we can assume the firmware has no data to provide .
*/
2023-10-17 23:06:52 +03:00
# define TEMP_MIN_DECIK 2180ULL
# define TEMP_MAX_DECIK 4480ULL
2023-01-23 21:38:31 +03:00
2023-10-17 23:06:52 +03:00
static int acpi_trip_temp ( struct acpi_device * adev , char * obj_name ,
int * ret_temp )
2023-01-23 21:38:31 +03:00
{
unsigned long long temp ;
acpi_status status ;
status = acpi_evaluate_integer ( adev - > handle , obj_name , NULL , & temp ) ;
if ( ACPI_FAILURE ( status ) ) {
acpi_handle_debug ( adev - > handle , " %s evaluation failed \n " , obj_name ) ;
return - ENODATA ;
}
2023-01-26 15:53:49 +03:00
if ( temp > = TEMP_MIN_DECIK & & temp < = TEMP_MAX_DECIK ) {
2023-10-17 23:06:52 +03:00
* ret_temp = temp ;
2023-01-26 15:53:49 +03:00
} else {
2023-01-23 21:38:31 +03:00
acpi_handle_debug ( adev - > handle , " %s result %llu out of range \n " ,
obj_name , temp ) ;
2023-01-27 21:17:03 +03:00
* ret_temp = THERMAL_TEMP_INVALID ;
2023-01-23 21:38:31 +03:00
}
return 0 ;
}
2023-10-17 23:06:52 +03:00
int acpi_active_trip_temp ( struct acpi_device * adev , int id , int * ret_temp )
{
char obj_name [ ] = { ' _ ' , ' A ' , ' C ' , ' 0 ' + id , ' \0 ' } ;
if ( id < 0 | | id > 9 )
return - EINVAL ;
return acpi_trip_temp ( adev , obj_name , ret_temp ) ;
}
2023-10-17 23:12:33 +03:00
EXPORT_SYMBOL_NS_GPL ( acpi_active_trip_temp , ACPI_THERMAL ) ;
2023-10-17 23:06:52 +03:00
int acpi_passive_trip_temp ( struct acpi_device * adev , int * ret_temp )
{
return acpi_trip_temp ( adev , " _PSV " , ret_temp ) ;
}
2023-10-17 23:12:33 +03:00
EXPORT_SYMBOL_NS_GPL ( acpi_passive_trip_temp , ACPI_THERMAL ) ;
2023-10-17 23:06:52 +03:00
int acpi_hot_trip_temp ( struct acpi_device * adev , int * ret_temp )
{
return acpi_trip_temp ( adev , " _HOT " , ret_temp ) ;
}
2023-10-17 23:12:33 +03:00
EXPORT_SYMBOL_NS_GPL ( acpi_hot_trip_temp , ACPI_THERMAL ) ;
2023-10-17 23:06:52 +03:00
int acpi_critical_trip_temp ( struct acpi_device * adev , int * ret_temp )
{
return acpi_trip_temp ( adev , " _CRT " , ret_temp ) ;
}
2023-10-17 23:12:33 +03:00
EXPORT_SYMBOL_NS_GPL ( acpi_critical_trip_temp , ACPI_THERMAL ) ;
2023-10-17 23:06:52 +03:00
static int thermal_temp ( int error , int temp_decik , int * ret_temp )
{
if ( error )
return error ;
if ( temp_decik = = THERMAL_TEMP_INVALID )
* ret_temp = THERMAL_TEMP_INVALID ;
else
* ret_temp = deci_kelvin_to_millicelsius ( temp_decik ) ;
return 0 ;
}
2023-01-23 21:38:31 +03:00
/**
2023-01-27 21:17:03 +03:00
* thermal_acpi_active_trip_temp - Retrieve active trip point temperature
* @ adev : Target thermal zone ACPI device object .
2023-01-23 21:38:31 +03:00
* @ id : Active cooling level ( 0 - 9 ) .
2023-01-27 21:17:03 +03:00
* @ ret_temp : Address to store the retrieved temperature value on success .
2023-01-23 21:38:31 +03:00
*
* Evaluate the _ACx object for the thermal zone represented by @ adev to obtain
* the temperature of the active cooling trip point corresponding to the active
2023-01-27 21:17:03 +03:00
* cooling level given by @ id .
2023-01-23 21:38:31 +03:00
*
* Return 0 on success or a negative error value on failure .
*/
2023-01-27 21:17:03 +03:00
int thermal_acpi_active_trip_temp ( struct acpi_device * adev , int id , int * ret_temp )
2023-01-23 21:38:31 +03:00
{
2024-02-22 13:57:23 +03:00
int temp_decik = 0 ;
2023-10-17 23:06:52 +03:00
int ret = acpi_active_trip_temp ( adev , id , & temp_decik ) ;
2023-01-27 21:17:03 +03:00
2023-10-17 23:06:52 +03:00
return thermal_temp ( ret , temp_decik , ret_temp ) ;
2023-01-23 21:38:31 +03:00
}
2023-01-27 21:17:03 +03:00
EXPORT_SYMBOL_GPL ( thermal_acpi_active_trip_temp ) ;
2023-01-23 21:38:31 +03:00
/**
2023-01-27 21:17:03 +03:00
* thermal_acpi_passive_trip_temp - Retrieve passive trip point temperature
* @ adev : Target thermal zone ACPI device object .
* @ ret_temp : Address to store the retrieved temperature value on success .
2023-01-23 21:38:31 +03:00
*
* Evaluate the _PSV object for the thermal zone represented by @ adev to obtain
2023-01-27 21:17:03 +03:00
* the temperature of the passive cooling trip point .
2023-01-23 21:38:31 +03:00
*
* Return 0 on success or - ENODATA on failure .
*/
2023-01-27 21:17:03 +03:00
int thermal_acpi_passive_trip_temp ( struct acpi_device * adev , int * ret_temp )
2023-01-23 21:38:31 +03:00
{
2024-02-22 13:57:23 +03:00
int temp_decik = 0 ;
2023-10-17 23:06:52 +03:00
int ret = acpi_passive_trip_temp ( adev , & temp_decik ) ;
return thermal_temp ( ret , temp_decik , ret_temp ) ;
2023-01-23 21:38:31 +03:00
}
2023-01-27 21:17:03 +03:00
EXPORT_SYMBOL_GPL ( thermal_acpi_passive_trip_temp ) ;
2023-01-23 21:38:31 +03:00
/**
2023-01-27 21:17:03 +03:00
* thermal_acpi_hot_trip_temp - Retrieve hot trip point temperature
* @ adev : Target thermal zone ACPI device object .
* @ ret_temp : Address to store the retrieved temperature value on success .
2023-01-23 21:38:31 +03:00
*
* Evaluate the _HOT object for the thermal zone represented by @ adev to obtain
* the temperature of the trip point at which the system is expected to be put
2023-01-27 21:17:03 +03:00
* into the S4 sleep state .
2023-01-23 21:38:31 +03:00
*
* Return 0 on success or - ENODATA on failure .
*/
2023-01-27 21:17:03 +03:00
int thermal_acpi_hot_trip_temp ( struct acpi_device * adev , int * ret_temp )
2023-01-23 21:38:31 +03:00
{
2024-02-22 13:57:23 +03:00
int temp_decik = 0 ;
2023-10-17 23:06:52 +03:00
int ret = acpi_hot_trip_temp ( adev , & temp_decik ) ;
return thermal_temp ( ret , temp_decik , ret_temp ) ;
2023-01-23 21:38:31 +03:00
}
2023-01-27 21:17:03 +03:00
EXPORT_SYMBOL_GPL ( thermal_acpi_hot_trip_temp ) ;
2023-01-23 21:38:31 +03:00
/**
2023-01-27 21:17:03 +03:00
* thermal_acpi_critical_trip_temp - Retrieve critical trip point temperature
* @ adev : Target thermal zone ACPI device object .
* @ ret_temp : Address to store the retrieved temperature value on success .
2023-01-23 21:38:31 +03:00
*
* Evaluate the _CRT object for the thermal zone represented by @ adev to obtain
2023-01-27 21:17:03 +03:00
* the temperature of the critical cooling trip point .
2023-01-23 21:38:31 +03:00
*
* Return 0 on success or - ENODATA on failure .
*/
2023-01-27 21:17:03 +03:00
int thermal_acpi_critical_trip_temp ( struct acpi_device * adev , int * ret_temp )
2023-01-23 21:38:31 +03:00
{
2024-02-22 13:57:23 +03:00
int temp_decik = 0 ;
2023-10-17 23:06:52 +03:00
int ret = acpi_critical_trip_temp ( adev , & temp_decik ) ;
return thermal_temp ( ret , temp_decik , ret_temp ) ;
2023-01-23 21:38:31 +03:00
}
2023-01-27 21:17:03 +03:00
EXPORT_SYMBOL_GPL ( thermal_acpi_critical_trip_temp ) ;