mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
Merge branch 'thermal-intel'
Merge changes affecting thermal control on Intel platforms for 6.3-rc1: - Consolidate code accessing the Intel TCC (Thermal Control Circuitry) MSRs by introducing library functions for that and making the TCC-related code in thermal drivers use them (Zhang Rui). - Enhance the x86_pkg_temp_thermal driver to support dynamic tjmax changes (Zhang Rui). - Address an "unsigned expression compared with zero" warning in the intel_soc_dts_iosf thermal driver (Yang Li). - Update comments regarding two functions in the Intel Menlow thermal driver (Deming Wang). - Use sysfs_emit_at() instead of scnprintf() in the int340x thermal driver (ye xingchen). - Make the intel_pch thermal driver support the Wellsburg PCH (Tim Zimmermann). - Add trip point initialization helper functions for ACPI-defined trip points and modify two thermal drivers to use them (Rafael Wysocki, Daniel Lezcano). - Modify the intel_pch and processor_thermal_device_pci thermal drivers use generic trip point tables instead of thermal zone trip point callbacks (Daniel Lezcano). - Add production mode attribute sysfs attribute to the int340x thermal driver (Srinivas Pandruvada). - Rework dynamic trip point updates handling and locking in the int340x thermal driver (Rafael Wysocki). - Make the int340x thermal driver use a generic trip points table instead of thermal zone trip point callbacks (Rafael Wysocki, Daniel Lezcano). * thermal-intel: thermal: intel: int340x: Use generic trip points table thermal: intel: int340x: Use zone lock for synchronization thermal: intel: int340x: Rework updating trip points thermal: ACPI: Initialize trips if temperature is out of range thermal: intel: processor_thermal_device_pci: Use generic trip point thermal: intel: int340x: Add production mode attribute thermal: intel: intel_pch: Use generic trip points thermal: ACPI: Add ACPI trip point routines thermal: intel: intel_pch: Add support for Wellsburg PCH thermal: int340x_thermal: Use sysfs_emit_at() instead of scnprintf() thermal: intel: menlow: Update function descriptions thermal: intel: Fix unsigned comparison with less than zero thermal/x86_pkg_temp_thermal: Add support for handling dynamic tjmax thermal/x86_pkg_temp_thermal: Use Intel TCC library thermal/intel/intel_tcc_cooling: Use Intel TCC library thermal/intel/intel_soc_dts_iosf: Use Intel TCC library thermal/int340x/processor_thermal: Use Intel TCC library thermal/intel: Introduce Intel TCC library
This commit is contained in:
commit
f364beb5b6
@ -84,6 +84,9 @@ DPTF ACPI Drivers interface
|
||||
https:/github.com/intel/thermal_daemon for decoding
|
||||
thermal table.
|
||||
|
||||
``production_mode`` (RO)
|
||||
When different from zero, manufacturer locked thermal configuration
|
||||
from further changes.
|
||||
|
||||
ACPI Thermal Relationship table interface
|
||||
------------------------------------------
|
||||
|
@ -76,6 +76,10 @@ config THERMAL_OF
|
||||
Say 'Y' here if you need to build thermal infrastructure
|
||||
based on device tree.
|
||||
|
||||
config THERMAL_ACPI
|
||||
depends on ACPI
|
||||
bool
|
||||
|
||||
config THERMAL_WRITABLE_TRIPS
|
||||
bool "Enable writable trip points"
|
||||
help
|
||||
|
@ -13,6 +13,7 @@ thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o
|
||||
# interface to/from other layers providing sensors
|
||||
thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
|
||||
thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o
|
||||
thermal_sys-$(CONFIG_THERMAL_ACPI) += thermal_acpi.o
|
||||
|
||||
# governors
|
||||
thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += gov_fair_share.o
|
||||
|
@ -12,11 +12,16 @@ config X86_THERMAL_VECTOR
|
||||
def_bool y
|
||||
depends on X86 && CPU_SUP_INTEL && X86_LOCAL_APIC
|
||||
|
||||
config INTEL_TCC
|
||||
bool
|
||||
depends on X86
|
||||
|
||||
config X86_PKG_TEMP_THERMAL
|
||||
tristate "X86 package temperature thermal driver"
|
||||
depends on X86_THERMAL_VECTOR
|
||||
select THERMAL_GOV_USER_SPACE
|
||||
select THERMAL_WRITABLE_TRIPS
|
||||
select INTEL_TCC
|
||||
default m
|
||||
help
|
||||
Enable this to register CPU digital sensor for package temperature as
|
||||
@ -28,6 +33,7 @@ config INTEL_SOC_DTS_IOSF_CORE
|
||||
tristate
|
||||
depends on X86 && PCI
|
||||
select IOSF_MBI
|
||||
select INTEL_TCC
|
||||
help
|
||||
This is becoming a common feature for Intel SoCs to expose the additional
|
||||
digital temperature sensors (DTSs) using side band interface (IOSF). This
|
||||
@ -75,6 +81,7 @@ config INTEL_BXT_PMIC_THERMAL
|
||||
config INTEL_PCH_THERMAL
|
||||
tristate "Intel PCH Thermal Reporting Driver"
|
||||
depends on X86 && PCI
|
||||
select THERMAL_ACPI if ACPI
|
||||
help
|
||||
Enable this to support thermal reporting on certain intel PCHs.
|
||||
Thermal reporting device will provide temperature reading,
|
||||
@ -83,6 +90,7 @@ config INTEL_PCH_THERMAL
|
||||
config INTEL_TCC_COOLING
|
||||
tristate "Intel TCC offset cooling Driver"
|
||||
depends on X86
|
||||
select INTEL_TCC
|
||||
help
|
||||
Enable this to support system cooling by adjusting the effective TCC
|
||||
activation temperature via the TCC Offset register, which is widely
|
||||
|
@ -2,6 +2,7 @@
|
||||
#
|
||||
# Makefile for various Intel thermal drivers.
|
||||
|
||||
obj-$(CONFIG_INTEL_TCC) += intel_tcc.o
|
||||
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
|
||||
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
|
||||
obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
|
||||
|
@ -9,7 +9,9 @@ config INT340X_THERMAL
|
||||
select THERMAL_GOV_USER_SPACE
|
||||
select ACPI_THERMAL_REL
|
||||
select ACPI_FAN
|
||||
select THERMAL_ACPI
|
||||
select INTEL_SOC_DTS_IOSF_CORE
|
||||
select INTEL_TCC
|
||||
select PROC_THERMAL_MMIO_RAPL if POWERCAP
|
||||
help
|
||||
Newer laptops and tablets that use ACPI may have thermal sensors and
|
||||
|
@ -60,6 +60,7 @@ struct int3400_thermal_priv {
|
||||
int odvp_count;
|
||||
int *odvp;
|
||||
u32 os_uuid_mask;
|
||||
int production_mode;
|
||||
struct odvp_attr *odvp_attrs;
|
||||
};
|
||||
|
||||
@ -130,10 +131,7 @@ static ssize_t available_uuids_show(struct device *dev,
|
||||
|
||||
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
|
||||
if (priv->uuid_bitmap & (1 << i))
|
||||
length += scnprintf(&buf[length],
|
||||
PAGE_SIZE - length,
|
||||
"%s\n",
|
||||
int3400_thermal_uuids[i]);
|
||||
length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
|
||||
}
|
||||
|
||||
return length;
|
||||
@ -151,10 +149,7 @@ static ssize_t current_uuid_show(struct device *dev,
|
||||
|
||||
for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) {
|
||||
if (priv->os_uuid_mask & BIT(i))
|
||||
length += scnprintf(&buf[length],
|
||||
PAGE_SIZE - length,
|
||||
"%s\n",
|
||||
int3400_thermal_uuids[i]);
|
||||
length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
|
||||
}
|
||||
|
||||
if (length)
|
||||
@ -315,6 +310,44 @@ static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t production_mode_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", priv->production_mode);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(production_mode);
|
||||
|
||||
static int production_mode_init(struct int3400_thermal_priv *priv)
|
||||
{
|
||||
unsigned long long mode;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
|
||||
priv->production_mode = -1;
|
||||
|
||||
status = acpi_evaluate_integer(priv->adev->handle, "DCFG", NULL, &mode);
|
||||
/* If the method is not present, this is not an error */
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
|
||||
ret = sysfs_create_file(&priv->pdev->dev.kobj, &dev_attr_production_mode.attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->production_mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void production_mode_exit(struct int3400_thermal_priv *priv)
|
||||
{
|
||||
if (priv->production_mode >= 0)
|
||||
sysfs_remove_file(&priv->pdev->dev.kobj, &dev_attr_production_mode.attr);
|
||||
}
|
||||
|
||||
static ssize_t odvp_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
@ -610,8 +643,15 @@ static int int3400_thermal_probe(struct platform_device *pdev)
|
||||
if (result)
|
||||
goto free_sysfs;
|
||||
|
||||
result = production_mode_init(priv);
|
||||
if (result)
|
||||
goto free_notify;
|
||||
|
||||
return 0;
|
||||
|
||||
free_notify:
|
||||
acpi_remove_notify_handler(priv->adev->handle, ACPI_DEVICE_NOTIFY,
|
||||
int3400_notify);
|
||||
free_sysfs:
|
||||
cleanup_odvp(priv);
|
||||
if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
|
||||
@ -638,6 +678,8 @@ static int int3400_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
production_mode_exit(priv);
|
||||
|
||||
acpi_remove_notify_handler(
|
||||
priv->adev->handle, ACPI_DEVICE_NOTIFY,
|
||||
int3400_notify);
|
||||
|
@ -69,7 +69,7 @@ static void int3403_notify(acpi_handle handle,
|
||||
THERMAL_TRIP_VIOLATED);
|
||||
break;
|
||||
case INT3403_PERF_TRIP_POINT_CHANGED:
|
||||
int340x_thermal_read_trips(obj->int340x_zone);
|
||||
int340x_thermal_update_trips(obj->int340x_zone);
|
||||
int340x_thermal_zone_device_update(obj->int340x_zone,
|
||||
THERMAL_TRIP_CHANGED);
|
||||
break;
|
||||
|
@ -37,73 +37,6 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
|
||||
int trip, int *temp)
|
||||
{
|
||||
struct int34x_thermal_zone *d = zone->devdata;
|
||||
int i, ret = 0;
|
||||
|
||||
mutex_lock(&d->trip_mutex);
|
||||
|
||||
if (trip < d->aux_trip_nr)
|
||||
*temp = d->aux_trips[trip];
|
||||
else if (trip == d->crt_trip_id)
|
||||
*temp = d->crt_temp;
|
||||
else if (trip == d->psv_trip_id)
|
||||
*temp = d->psv_temp;
|
||||
else if (trip == d->hot_trip_id)
|
||||
*temp = d->hot_temp;
|
||||
else {
|
||||
for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
|
||||
if (d->act_trips[i].valid &&
|
||||
d->act_trips[i].id == trip) {
|
||||
*temp = d->act_trips[i].temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->trip_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
|
||||
int trip,
|
||||
enum thermal_trip_type *type)
|
||||
{
|
||||
struct int34x_thermal_zone *d = zone->devdata;
|
||||
int i, ret = 0;
|
||||
|
||||
mutex_lock(&d->trip_mutex);
|
||||
|
||||
if (trip < d->aux_trip_nr)
|
||||
*type = THERMAL_TRIP_PASSIVE;
|
||||
else if (trip == d->crt_trip_id)
|
||||
*type = THERMAL_TRIP_CRITICAL;
|
||||
else if (trip == d->hot_trip_id)
|
||||
*type = THERMAL_TRIP_HOT;
|
||||
else if (trip == d->psv_trip_id)
|
||||
*type = THERMAL_TRIP_PASSIVE;
|
||||
else {
|
||||
for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
|
||||
if (d->act_trips[i].valid &&
|
||||
d->act_trips[i].id == trip) {
|
||||
*type = THERMAL_TRIP_ACTIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->trip_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
|
||||
int trip, int temp)
|
||||
{
|
||||
@ -117,25 +50,6 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
d->aux_trips[trip] = temp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
|
||||
int trip, int *temp)
|
||||
{
|
||||
struct int34x_thermal_zone *d = zone->devdata;
|
||||
acpi_status status;
|
||||
unsigned long long hyst;
|
||||
|
||||
status = acpi_evaluate_integer(d->adev->handle, "GTSH", NULL, &hyst);
|
||||
if (ACPI_FAILURE(status))
|
||||
*temp = 0;
|
||||
else
|
||||
*temp = hyst * 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -146,67 +60,39 @@ static void int340x_thermal_critical(struct thermal_zone_device *zone)
|
||||
|
||||
static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
|
||||
.get_temp = int340x_thermal_get_zone_temp,
|
||||
.get_trip_temp = int340x_thermal_get_trip_temp,
|
||||
.get_trip_type = int340x_thermal_get_trip_type,
|
||||
.set_trip_temp = int340x_thermal_set_trip_temp,
|
||||
.get_trip_hyst = int340x_thermal_get_trip_hyst,
|
||||
.critical = int340x_thermal_critical,
|
||||
};
|
||||
|
||||
static int int340x_thermal_get_trip_config(acpi_handle handle, char *name,
|
||||
int *temp)
|
||||
static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
|
||||
struct thermal_trip *zone_trips,
|
||||
int trip_cnt)
|
||||
{
|
||||
unsigned long long r;
|
||||
acpi_status status;
|
||||
int i, ret;
|
||||
|
||||
status = acpi_evaluate_integer(handle, name, NULL, &r);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
ret = thermal_acpi_trip_critical(zone_adev, &zone_trips[trip_cnt]);
|
||||
if (!ret)
|
||||
trip_cnt++;
|
||||
|
||||
*temp = deci_kelvin_to_millicelsius(r);
|
||||
ret = thermal_acpi_trip_hot(zone_adev, &zone_trips[trip_cnt]);
|
||||
if (!ret)
|
||||
trip_cnt++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone)
|
||||
{
|
||||
int trip_cnt = int34x_zone->aux_trip_nr;
|
||||
int i;
|
||||
|
||||
mutex_lock(&int34x_zone->trip_mutex);
|
||||
|
||||
int34x_zone->crt_trip_id = -1;
|
||||
if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_CRT",
|
||||
&int34x_zone->crt_temp))
|
||||
int34x_zone->crt_trip_id = trip_cnt++;
|
||||
|
||||
int34x_zone->hot_trip_id = -1;
|
||||
if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_HOT",
|
||||
&int34x_zone->hot_temp))
|
||||
int34x_zone->hot_trip_id = trip_cnt++;
|
||||
|
||||
int34x_zone->psv_trip_id = -1;
|
||||
if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_PSV",
|
||||
&int34x_zone->psv_temp))
|
||||
int34x_zone->psv_trip_id = trip_cnt++;
|
||||
ret = thermal_acpi_trip_passive(zone_adev, &zone_trips[trip_cnt]);
|
||||
if (!ret)
|
||||
trip_cnt++;
|
||||
|
||||
for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
|
||||
char name[5] = { '_', 'A', 'C', '0' + i, '\0' };
|
||||
|
||||
if (int340x_thermal_get_trip_config(int34x_zone->adev->handle,
|
||||
name,
|
||||
&int34x_zone->act_trips[i].temp))
|
||||
ret = thermal_acpi_trip_active(zone_adev, i, &zone_trips[trip_cnt]);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
int34x_zone->act_trips[i].id = trip_cnt++;
|
||||
int34x_zone->act_trips[i].valid = true;
|
||||
trip_cnt++;
|
||||
}
|
||||
|
||||
mutex_unlock(&int34x_zone->trip_mutex);
|
||||
|
||||
return trip_cnt;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(int340x_thermal_read_trips);
|
||||
|
||||
static struct thermal_zone_params int340x_thermal_params = {
|
||||
.governor_name = "user_space",
|
||||
@ -217,18 +103,18 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
|
||||
int (*get_temp) (struct thermal_zone_device *, int *))
|
||||
{
|
||||
struct int34x_thermal_zone *int34x_thermal_zone;
|
||||
acpi_status status;
|
||||
unsigned long long trip_cnt;
|
||||
struct thermal_trip *zone_trips;
|
||||
unsigned long long trip_cnt = 0;
|
||||
unsigned long long hyst;
|
||||
int trip_mask = 0;
|
||||
int ret;
|
||||
acpi_status status;
|
||||
int i, ret;
|
||||
|
||||
int34x_thermal_zone = kzalloc(sizeof(*int34x_thermal_zone),
|
||||
GFP_KERNEL);
|
||||
if (!int34x_thermal_zone)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mutex_init(&int34x_thermal_zone->trip_mutex);
|
||||
|
||||
int34x_thermal_zone->adev = adev;
|
||||
|
||||
int34x_thermal_zone->ops = kmemdup(&int340x_thermal_zone_ops,
|
||||
@ -242,33 +128,42 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
|
||||
int34x_thermal_zone->ops->get_temp = get_temp;
|
||||
|
||||
status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt);
|
||||
if (ACPI_FAILURE(status))
|
||||
trip_cnt = 0;
|
||||
else {
|
||||
int i;
|
||||
|
||||
int34x_thermal_zone->aux_trips =
|
||||
kcalloc(trip_cnt,
|
||||
sizeof(*int34x_thermal_zone->aux_trips),
|
||||
GFP_KERNEL);
|
||||
if (!int34x_thermal_zone->aux_trips) {
|
||||
ret = -ENOMEM;
|
||||
goto err_trip_alloc;
|
||||
}
|
||||
trip_mask = BIT(trip_cnt) - 1;
|
||||
if (!ACPI_FAILURE(status)) {
|
||||
int34x_thermal_zone->aux_trip_nr = trip_cnt;
|
||||
for (i = 0; i < trip_cnt; ++i)
|
||||
int34x_thermal_zone->aux_trips[i] = THERMAL_TEMP_INVALID;
|
||||
trip_mask = BIT(trip_cnt) - 1;
|
||||
}
|
||||
|
||||
trip_cnt = int340x_thermal_read_trips(int34x_thermal_zone);
|
||||
zone_trips = kzalloc(sizeof(*zone_trips) * (trip_cnt + INT340X_THERMAL_MAX_TRIP_COUNT),
|
||||
GFP_KERNEL);
|
||||
if (!zone_trips) {
|
||||
ret = -ENOMEM;
|
||||
goto err_trips_alloc;
|
||||
}
|
||||
|
||||
for (i = 0; i < trip_cnt; i++) {
|
||||
zone_trips[i].type = THERMAL_TRIP_PASSIVE;
|
||||
zone_trips[i].temperature = THERMAL_TEMP_INVALID;
|
||||
}
|
||||
|
||||
trip_cnt = int340x_thermal_read_trips(adev, zone_trips, trip_cnt);
|
||||
|
||||
status = acpi_evaluate_integer(adev->handle, "GTSH", NULL, &hyst);
|
||||
if (ACPI_SUCCESS(status))
|
||||
hyst *= 100;
|
||||
else
|
||||
hyst = 0;
|
||||
|
||||
for (i = 0; i < trip_cnt; ++i)
|
||||
zone_trips[i].hysteresis = hyst;
|
||||
|
||||
int34x_thermal_zone->trips = zone_trips;
|
||||
|
||||
int34x_thermal_zone->lpat_table = acpi_lpat_get_conversion_table(
|
||||
adev->handle);
|
||||
|
||||
int34x_thermal_zone->zone = thermal_zone_device_register(
|
||||
int34x_thermal_zone->zone = thermal_zone_device_register_with_trips(
|
||||
acpi_device_bid(adev),
|
||||
trip_cnt,
|
||||
zone_trips, trip_cnt,
|
||||
trip_mask, int34x_thermal_zone,
|
||||
int34x_thermal_zone->ops,
|
||||
&int340x_thermal_params,
|
||||
@ -286,12 +181,11 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
|
||||
err_enable:
|
||||
thermal_zone_device_unregister(int34x_thermal_zone->zone);
|
||||
err_thermal_zone:
|
||||
kfree(int34x_thermal_zone->trips);
|
||||
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
|
||||
kfree(int34x_thermal_zone->aux_trips);
|
||||
err_trip_alloc:
|
||||
err_trips_alloc:
|
||||
kfree(int34x_thermal_zone->ops);
|
||||
err_ops_alloc:
|
||||
mutex_destroy(&int34x_thermal_zone->trip_mutex);
|
||||
kfree(int34x_thermal_zone);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
@ -302,13 +196,55 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone
|
||||
{
|
||||
thermal_zone_device_unregister(int34x_thermal_zone->zone);
|
||||
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
|
||||
kfree(int34x_thermal_zone->aux_trips);
|
||||
kfree(int34x_thermal_zone->trips);
|
||||
kfree(int34x_thermal_zone->ops);
|
||||
mutex_destroy(&int34x_thermal_zone->trip_mutex);
|
||||
kfree(int34x_thermal_zone);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove);
|
||||
|
||||
void int340x_thermal_update_trips(struct int34x_thermal_zone *int34x_zone)
|
||||
{
|
||||
struct acpi_device *zone_adev = int34x_zone->adev;
|
||||
struct thermal_trip *zone_trips = int34x_zone->trips;
|
||||
int trip_cnt = int34x_zone->zone->num_trips;
|
||||
int act_trip_nr = 0;
|
||||
int i;
|
||||
|
||||
mutex_lock(&int34x_zone->zone->lock);
|
||||
|
||||
for (i = int34x_zone->aux_trip_nr; i < trip_cnt; i++) {
|
||||
struct thermal_trip trip;
|
||||
int err;
|
||||
|
||||
switch (zone_trips[i].type) {
|
||||
case THERMAL_TRIP_CRITICAL:
|
||||
err = thermal_acpi_trip_critical(zone_adev, &trip);
|
||||
break;
|
||||
case THERMAL_TRIP_HOT:
|
||||
err = thermal_acpi_trip_hot(zone_adev, &trip);
|
||||
break;
|
||||
case THERMAL_TRIP_PASSIVE:
|
||||
err = thermal_acpi_trip_passive(zone_adev, &trip);
|
||||
break;
|
||||
case THERMAL_TRIP_ACTIVE:
|
||||
err = thermal_acpi_trip_active(zone_adev, act_trip_nr++,
|
||||
&trip);
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
}
|
||||
if (err) {
|
||||
zone_trips[i].temperature = THERMAL_TEMP_INVALID;
|
||||
continue;
|
||||
}
|
||||
|
||||
zone_trips[i].temperature = trip.temperature;
|
||||
}
|
||||
|
||||
mutex_unlock(&int34x_zone->zone->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(int340x_thermal_update_trips);
|
||||
|
||||
MODULE_AUTHOR("Aaron Lu <aaron.lu@intel.com>");
|
||||
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
|
||||
MODULE_DESCRIPTION("Intel INT340x common thermal zone handler");
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <acpi/acpi_lpat.h>
|
||||
|
||||
#define INT340X_THERMAL_MAX_ACT_TRIP_COUNT 10
|
||||
#define INT340X_THERMAL_MAX_TRIP_COUNT INT340X_THERMAL_MAX_ACT_TRIP_COUNT + 3
|
||||
|
||||
struct active_trip {
|
||||
int temp;
|
||||
@ -19,26 +20,18 @@ struct active_trip {
|
||||
|
||||
struct int34x_thermal_zone {
|
||||
struct acpi_device *adev;
|
||||
struct active_trip act_trips[INT340X_THERMAL_MAX_ACT_TRIP_COUNT];
|
||||
unsigned long *aux_trips;
|
||||
struct thermal_trip *trips;
|
||||
int aux_trip_nr;
|
||||
int psv_temp;
|
||||
int psv_trip_id;
|
||||
int crt_temp;
|
||||
int crt_trip_id;
|
||||
int hot_temp;
|
||||
int hot_trip_id;
|
||||
struct thermal_zone_device *zone;
|
||||
struct thermal_zone_device_ops *ops;
|
||||
void *priv_data;
|
||||
struct acpi_lpat_conversion_table *lpat_table;
|
||||
struct mutex trip_mutex;
|
||||
};
|
||||
|
||||
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *,
|
||||
int (*get_temp) (struct thermal_zone_device *, int *));
|
||||
void int340x_thermal_zone_remove(struct int34x_thermal_zone *);
|
||||
int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone);
|
||||
void int340x_thermal_update_trips(struct int34x_thermal_zone *int34x_zone);
|
||||
|
||||
static inline void int340x_thermal_zone_set_priv_data(
|
||||
struct int34x_thermal_zone *tzone, void *priv_data)
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2014, Intel Corporation.
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/intel_tcc.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
@ -68,54 +69,17 @@ static const struct attribute_group power_limit_attribute_group = {
|
||||
.name = "power_limits"
|
||||
};
|
||||
|
||||
static int tcc_get_offset(void)
|
||||
{
|
||||
u64 val;
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return (val >> 24) & 0x3f;
|
||||
}
|
||||
|
||||
static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int tcc;
|
||||
int offset;
|
||||
|
||||
tcc = tcc_get_offset();
|
||||
if (tcc < 0)
|
||||
return tcc;
|
||||
offset = intel_tcc_get_offset(-1);
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
|
||||
return sprintf(buf, "%d\n", tcc);
|
||||
}
|
||||
|
||||
static int tcc_offset_update(unsigned int tcc)
|
||||
{
|
||||
u64 val;
|
||||
int err;
|
||||
|
||||
if (tcc > 63)
|
||||
return -EINVAL;
|
||||
|
||||
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val & BIT(31))
|
||||
return -EPERM;
|
||||
|
||||
val &= ~GENMASK_ULL(29, 24);
|
||||
val |= (tcc & 0x3f) << 24;
|
||||
|
||||
err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
return sprintf(buf, "%d\n", offset);
|
||||
}
|
||||
|
||||
static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
|
||||
@ -136,7 +100,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
|
||||
if (kstrtouint(buf, 0, &tcc))
|
||||
return -EINVAL;
|
||||
|
||||
err = tcc_offset_update(tcc);
|
||||
err = intel_tcc_set_offset(-1, tcc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -145,66 +109,25 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
|
||||
|
||||
static DEVICE_ATTR_RW(tcc_offset_degree_celsius);
|
||||
|
||||
static int stored_tjmax; /* since it is fixed, we can have local storage */
|
||||
|
||||
static int get_tjmax(void)
|
||||
{
|
||||
u32 eax, edx;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = (eax >> 16) & 0xff;
|
||||
if (val)
|
||||
return val;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int read_temp_msr(int *temp)
|
||||
static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
|
||||
int *temp)
|
||||
{
|
||||
int cpu;
|
||||
u32 eax, edx;
|
||||
int err;
|
||||
unsigned long curr_temp_off = 0;
|
||||
int curr_temp;
|
||||
|
||||
*temp = 0;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_THERM_STATUS, &eax,
|
||||
&edx);
|
||||
if (err)
|
||||
goto err_ret;
|
||||
else {
|
||||
if (eax & 0x80000000) {
|
||||
curr_temp_off = (eax >> 16) & 0x7f;
|
||||
if (!*temp || curr_temp_off < *temp)
|
||||
*temp = curr_temp_off;
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
goto err_ret;
|
||||
}
|
||||
}
|
||||
curr_temp = intel_tcc_get_temp(cpu, false);
|
||||
if (curr_temp < 0)
|
||||
return curr_temp;
|
||||
if (!*temp || curr_temp > *temp)
|
||||
*temp = curr_temp;
|
||||
}
|
||||
|
||||
*temp *= 1000;
|
||||
|
||||
return 0;
|
||||
err_ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
|
||||
int *temp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = read_temp_msr(temp);
|
||||
if (!ret)
|
||||
*temp = (stored_tjmax - *temp) * 1000;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int proc_thermal_read_ppcc(struct proc_thermal_device *proc_priv)
|
||||
@ -298,8 +221,7 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
|
||||
status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
/* there is no _TMP method, add local method */
|
||||
stored_tjmax = get_tjmax();
|
||||
if (stored_tjmax > 0)
|
||||
if (intel_tcc_get_tjmax(-1) > 0)
|
||||
get_temp = proc_thermal_get_zone_temp;
|
||||
}
|
||||
|
||||
@ -352,7 +274,7 @@ static int tcc_offset_save = -1;
|
||||
|
||||
int proc_thermal_suspend(struct device *dev)
|
||||
{
|
||||
tcc_offset_save = tcc_get_offset();
|
||||
tcc_offset_save = intel_tcc_get_offset(-1);
|
||||
if (tcc_offset_save < 0)
|
||||
dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save);
|
||||
|
||||
@ -369,7 +291,7 @@ int proc_thermal_resume(struct device *dev)
|
||||
|
||||
/* Do not update if saving failed */
|
||||
if (tcc_offset_save >= 0)
|
||||
tcc_offset_update(tcc_offset_save);
|
||||
intel_tcc_set_offset(-1, tcc_offset_save);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -456,6 +378,7 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);
|
||||
|
||||
MODULE_IMPORT_NS(INTEL_TCC);
|
||||
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
|
||||
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -144,34 +144,6 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_get_trip_temp(struct thermal_zone_device *tzd,
|
||||
int trip, int *temp)
|
||||
{
|
||||
struct proc_thermal_pci *pci_info = tzd->devdata;
|
||||
u32 _temp;
|
||||
|
||||
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &_temp);
|
||||
if (!_temp) {
|
||||
*temp = THERMAL_TEMP_INVALID;
|
||||
} else {
|
||||
int tjmax;
|
||||
|
||||
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
|
||||
_temp = tjmax - _temp;
|
||||
*temp = (unsigned long)_temp * 1000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_get_trip_type(struct thermal_zone_device *tzd, int trip,
|
||||
enum thermal_trip_type *type)
|
||||
{
|
||||
*type = THERMAL_TRIP_PASSIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
|
||||
{
|
||||
struct proc_thermal_pci *pci_info = tzd->devdata;
|
||||
@ -200,10 +172,26 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_trip_temp(struct proc_thermal_pci *pci_info)
|
||||
{
|
||||
int temp, tjmax;
|
||||
|
||||
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp);
|
||||
if (!temp)
|
||||
return THERMAL_TEMP_INVALID;
|
||||
|
||||
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
|
||||
temp = (tjmax - temp) * 1000;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static struct thermal_trip psv_trip = {
|
||||
.type = THERMAL_TRIP_PASSIVE,
|
||||
};
|
||||
|
||||
static struct thermal_zone_device_ops tzone_ops = {
|
||||
.get_temp = sys_get_curr_temp,
|
||||
.get_trip_temp = sys_get_trip_temp,
|
||||
.get_trip_type = sys_get_trip_type,
|
||||
.set_trip_temp = sys_set_trip_temp,
|
||||
};
|
||||
|
||||
@ -251,7 +239,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
|
||||
if (ret)
|
||||
goto err_ret_thermal;
|
||||
|
||||
pci_info->tzone = thermal_zone_device_register("TCPU_PCI", 1, 1, pci_info,
|
||||
psv_trip.temperature = get_trip_temp(pci_info);
|
||||
|
||||
pci_info->tzone = thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip,
|
||||
1, 1, pci_info,
|
||||
&tzone_ops,
|
||||
&tzone_params, 0, 0);
|
||||
if (IS_ERR(pci_info->tzone)) {
|
||||
|
@ -232,9 +232,9 @@ static DEFINE_MUTEX(intel_menlow_attr_lock);
|
||||
|
||||
/*
|
||||
* sensor_get_auxtrip - get the current auxtrip value from sensor
|
||||
* @name: Thermalzone name
|
||||
* @auxtype : AUX0/AUX1
|
||||
* @buf: syfs buffer
|
||||
* @handle: Object handle
|
||||
* @index : GET_AUX1/GET_AUX0
|
||||
* @value : The address will be fill by the value
|
||||
*/
|
||||
static int sensor_get_auxtrip(acpi_handle handle, int index,
|
||||
unsigned long long *value)
|
||||
@ -254,9 +254,9 @@ static int sensor_get_auxtrip(acpi_handle handle, int index,
|
||||
|
||||
/*
|
||||
* sensor_set_auxtrip - set the new auxtrip value to sensor
|
||||
* @name: Thermalzone name
|
||||
* @auxtype : AUX0/AUX1
|
||||
* @buf: syfs buffer
|
||||
* @handle: Object handle
|
||||
* @index : GET_AUX1/GET_AUX0
|
||||
* @value : The value will be set
|
||||
*/
|
||||
static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */
|
||||
#define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */
|
||||
#define PCH_THERMAL_DID_LWB 0xA1B1 /* Lewisburg PCH */
|
||||
#define PCH_THERMAL_DID_WBG 0x8D24 /* Wellsburg PCH */
|
||||
|
||||
/* Wildcat Point-LP PCH Thermal registers */
|
||||
#define WPT_TEMP 0x0000 /* Temperature */
|
||||
@ -65,6 +66,8 @@
|
||||
#define WPT_TEMP_OFFSET (PCH_TEMP_OFFSET * MILLIDEGREE_PER_DEGREE)
|
||||
#define GET_PCH_TEMP(x) (((x) / 2) + PCH_TEMP_OFFSET)
|
||||
|
||||
#define PCH_MAX_TRIPS 3 /* critical, hot, passive */
|
||||
|
||||
/* Amount of time for each cooling delay, 100ms by default for now */
|
||||
static unsigned int delay_timeout = 100;
|
||||
module_param(delay_timeout, int, 0644);
|
||||
@ -82,12 +85,7 @@ struct pch_thermal_device {
|
||||
const struct pch_dev_ops *ops;
|
||||
struct pci_dev *pdev;
|
||||
struct thermal_zone_device *tzd;
|
||||
int crt_trip_id;
|
||||
unsigned long crt_temp;
|
||||
int hot_trip_id;
|
||||
unsigned long hot_temp;
|
||||
int psv_trip_id;
|
||||
unsigned long psv_temp;
|
||||
struct thermal_trip trips[PCH_MAX_TRIPS];
|
||||
bool bios_enabled;
|
||||
};
|
||||
|
||||
@ -102,33 +100,22 @@ static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
|
||||
int *nr_trips)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
|
||||
ptd->psv_trip_id = -1;
|
||||
int ret;
|
||||
|
||||
adev = ACPI_COMPANION(&ptd->pdev->dev);
|
||||
if (adev) {
|
||||
unsigned long long r;
|
||||
acpi_status status;
|
||||
if (!adev)
|
||||
return;
|
||||
|
||||
status = acpi_evaluate_integer(adev->handle, "_PSV", NULL,
|
||||
&r);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
unsigned long trip_temp;
|
||||
ret = thermal_acpi_trip_passive(adev, &ptd->trips[*nr_trips]);
|
||||
if (ret || ptd->trips[*nr_trips].temperature <= 0)
|
||||
return;
|
||||
|
||||
trip_temp = deci_kelvin_to_millicelsius(r);
|
||||
if (trip_temp) {
|
||||
ptd->psv_temp = trip_temp;
|
||||
ptd->psv_trip_id = *nr_trips;
|
||||
++(*nr_trips);
|
||||
}
|
||||
}
|
||||
}
|
||||
++(*nr_trips);
|
||||
}
|
||||
#else
|
||||
static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
|
||||
int *nr_trips)
|
||||
{
|
||||
ptd->psv_trip_id = -1;
|
||||
|
||||
}
|
||||
#endif
|
||||
@ -163,21 +150,19 @@ static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips)
|
||||
}
|
||||
|
||||
read_trips:
|
||||
ptd->crt_trip_id = -1;
|
||||
trip_temp = readw(ptd->hw_base + WPT_CTT);
|
||||
trip_temp &= 0x1FF;
|
||||
if (trip_temp) {
|
||||
ptd->crt_temp = GET_WPT_TEMP(trip_temp);
|
||||
ptd->crt_trip_id = 0;
|
||||
ptd->trips[*nr_trips].temperature = GET_WPT_TEMP(trip_temp);
|
||||
ptd->trips[*nr_trips].type = THERMAL_TRIP_CRITICAL;
|
||||
++(*nr_trips);
|
||||
}
|
||||
|
||||
ptd->hot_trip_id = -1;
|
||||
trip_temp = readw(ptd->hw_base + WPT_PHL);
|
||||
trip_temp &= 0x1FF;
|
||||
if (trip_temp) {
|
||||
ptd->hot_temp = GET_WPT_TEMP(trip_temp);
|
||||
ptd->hot_trip_id = *nr_trips;
|
||||
ptd->trips[*nr_trips].temperature = GET_WPT_TEMP(trip_temp);
|
||||
ptd->trips[*nr_trips].type = THERMAL_TRIP_HOT;
|
||||
++(*nr_trips);
|
||||
}
|
||||
|
||||
@ -298,39 +283,6 @@ static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp)
|
||||
return ptd->ops->get_temp(ptd, temp);
|
||||
}
|
||||
|
||||
static int pch_get_trip_type(struct thermal_zone_device *tzd, int trip,
|
||||
enum thermal_trip_type *type)
|
||||
{
|
||||
struct pch_thermal_device *ptd = tzd->devdata;
|
||||
|
||||
if (ptd->crt_trip_id == trip)
|
||||
*type = THERMAL_TRIP_CRITICAL;
|
||||
else if (ptd->hot_trip_id == trip)
|
||||
*type = THERMAL_TRIP_HOT;
|
||||
else if (ptd->psv_trip_id == trip)
|
||||
*type = THERMAL_TRIP_PASSIVE;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pch_get_trip_temp(struct thermal_zone_device *tzd, int trip, int *temp)
|
||||
{
|
||||
struct pch_thermal_device *ptd = tzd->devdata;
|
||||
|
||||
if (ptd->crt_trip_id == trip)
|
||||
*temp = ptd->crt_temp;
|
||||
else if (ptd->hot_trip_id == trip)
|
||||
*temp = ptd->hot_temp;
|
||||
else if (ptd->psv_trip_id == trip)
|
||||
*temp = ptd->psv_temp;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pch_critical(struct thermal_zone_device *tzd)
|
||||
{
|
||||
dev_dbg(&tzd->device, "%s: critical temperature reached\n", tzd->type);
|
||||
@ -338,8 +290,6 @@ static void pch_critical(struct thermal_zone_device *tzd)
|
||||
|
||||
static struct thermal_zone_device_ops tzd_ops = {
|
||||
.get_temp = pch_thermal_get_temp,
|
||||
.get_trip_type = pch_get_trip_type,
|
||||
.get_trip_temp = pch_get_trip_temp,
|
||||
.critical = pch_critical,
|
||||
};
|
||||
|
||||
@ -350,6 +300,7 @@ enum board_ids {
|
||||
board_cnl,
|
||||
board_cml,
|
||||
board_lwb,
|
||||
board_wbg,
|
||||
};
|
||||
|
||||
static const struct board_info {
|
||||
@ -380,6 +331,10 @@ static const struct board_info {
|
||||
.name = "pch_lewisburg",
|
||||
.ops = &pch_dev_ops_wpt,
|
||||
},
|
||||
[board_wbg] = {
|
||||
.name = "pch_wellsburg",
|
||||
.ops = &pch_dev_ops_wpt,
|
||||
},
|
||||
};
|
||||
|
||||
static int intel_pch_thermal_probe(struct pci_dev *pdev,
|
||||
@ -423,8 +378,9 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto error_cleanup;
|
||||
|
||||
ptd->tzd = thermal_zone_device_register(bi->name, nr_trips, 0, ptd,
|
||||
&tzd_ops, NULL, 0, 0);
|
||||
ptd->tzd = thermal_zone_device_register_with_trips(bi->name, ptd->trips,
|
||||
nr_trips, 0, ptd,
|
||||
&tzd_ops, NULL, 0, 0);
|
||||
if (IS_ERR(ptd->tzd)) {
|
||||
dev_err(&pdev->dev, "Failed to register thermal zone %s\n",
|
||||
bi->name);
|
||||
@ -495,6 +451,8 @@ static const struct pci_device_id intel_pch_thermal_id[] = {
|
||||
.driver_data = board_cml, },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_LWB),
|
||||
.driver_data = board_lwb, },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WBG),
|
||||
.driver_data = board_wbg, },
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/intel_tcc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -45,32 +46,6 @@
|
||||
/* DTS0 and DTS 1 */
|
||||
#define SOC_MAX_DTS_SENSORS 2
|
||||
|
||||
static int get_tj_max(u32 *tj_max)
|
||||
{
|
||||
u32 eax, edx;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
|
||||
if (err)
|
||||
goto err_ret;
|
||||
else {
|
||||
val = (eax >> 16) & 0xff;
|
||||
if (val)
|
||||
*tj_max = val * 1000;
|
||||
else {
|
||||
err = -EINVAL;
|
||||
goto err_ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_ret:
|
||||
*tj_max = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
|
||||
int *temp)
|
||||
{
|
||||
@ -405,7 +380,7 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
|
||||
{
|
||||
struct intel_soc_dts_sensors *sensors;
|
||||
bool notification;
|
||||
u32 tj_max;
|
||||
int tj_max;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@ -415,8 +390,9 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
|
||||
if (!trip_count || read_only_trip_count > trip_count)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (get_tj_max(&tj_max))
|
||||
return ERR_PTR(-EINVAL);
|
||||
tj_max = intel_tcc_get_tjmax(-1);
|
||||
if (tj_max < 0)
|
||||
return ERR_PTR(tj_max);
|
||||
|
||||
sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
|
||||
if (!sensors)
|
||||
@ -475,4 +451,5 @@ void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
|
||||
|
||||
MODULE_IMPORT_NS(INTEL_TCC);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
139
drivers/thermal/intel/intel_tcc.c
Normal file
139
drivers/thermal/intel/intel_tcc.c
Normal file
@ -0,0 +1,139 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* intel_tcc.c - Library for Intel TCC (thermal control circuitry) MSR access
|
||||
* Copyright (c) 2022, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/intel_tcc.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
/**
|
||||
* intel_tcc_get_tjmax() - returns the default TCC activation Temperature
|
||||
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
||||
*
|
||||
* Get the TjMax value, which is the default thermal throttling or TCC
|
||||
* activation temperature in degrees C.
|
||||
*
|
||||
* Return: Tjmax value in degrees C on success, negative error code otherwise.
|
||||
*/
|
||||
int intel_tcc_get_tjmax(int cpu)
|
||||
{
|
||||
u32 low, high;
|
||||
int val, err;
|
||||
|
||||
if (cpu < 0)
|
||||
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
||||
else
|
||||
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = (low >> 16) & 0xff;
|
||||
|
||||
return val ? val : -ENODATA;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, INTEL_TCC);
|
||||
|
||||
/**
|
||||
* intel_tcc_get_offset() - returns the TCC Offset value to Tjmax
|
||||
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
||||
*
|
||||
* Get the TCC offset value to Tjmax. The effective thermal throttling or TCC
|
||||
* activation temperature equals "Tjmax" - "TCC Offset", in degrees C.
|
||||
*
|
||||
* Return: Tcc offset value in degrees C on success, negative error code otherwise.
|
||||
*/
|
||||
int intel_tcc_get_offset(int cpu)
|
||||
{
|
||||
u32 low, high;
|
||||
int err;
|
||||
|
||||
if (cpu < 0)
|
||||
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
||||
else
|
||||
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return (low >> 24) & 0x3f;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
|
||||
|
||||
/**
|
||||
* intel_tcc_set_offset() - set the TCC offset value to Tjmax
|
||||
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
||||
* @offset: TCC offset value in degree C
|
||||
*
|
||||
* Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC
|
||||
* activation temperature equals "Tjmax" - "TCC Offset", in degree C.
|
||||
*
|
||||
* Return: On success returns 0, negative error code otherwise.
|
||||
*/
|
||||
|
||||
int intel_tcc_set_offset(int cpu, int offset)
|
||||
{
|
||||
u32 low, high;
|
||||
int err;
|
||||
|
||||
if (offset < 0 || offset > 0x3f)
|
||||
return -EINVAL;
|
||||
|
||||
if (cpu < 0)
|
||||
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
||||
else
|
||||
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* MSR Locked */
|
||||
if (low & BIT(31))
|
||||
return -EPERM;
|
||||
|
||||
low &= ~(0x3f << 24);
|
||||
low |= offset << 24;
|
||||
|
||||
if (cpu < 0)
|
||||
return wrmsr_safe(MSR_IA32_TEMPERATURE_TARGET, low, high);
|
||||
else
|
||||
return wrmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, low, high);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
|
||||
|
||||
/**
|
||||
* intel_tcc_get_temp() - returns the current temperature
|
||||
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
||||
* @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
|
||||
*
|
||||
* Get the current temperature returned by the CPU core/package level
|
||||
* thermal sensor, in degrees C.
|
||||
*
|
||||
* Return: Temperature in degrees C on success, negative error code otherwise.
|
||||
*/
|
||||
int intel_tcc_get_temp(int cpu, bool pkg)
|
||||
{
|
||||
u32 low, high;
|
||||
u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
|
||||
int tjmax, temp, err;
|
||||
|
||||
tjmax = intel_tcc_get_tjmax(cpu);
|
||||
if (tjmax < 0)
|
||||
return tjmax;
|
||||
|
||||
if (cpu < 0)
|
||||
err = rdmsr_safe(msr, &low, &high);
|
||||
else
|
||||
err = rdmsr_safe_on_cpu(cpu, msr, &low, &high);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Temperature is beyond the valid thermal sensor range */
|
||||
if (!(low & BIT(31)))
|
||||
return -ENODATA;
|
||||
|
||||
temp = tjmax - ((low >> 16) & 0x7f);
|
||||
|
||||
/* Do not allow negative CPU temperature */
|
||||
return temp >= 0 ? temp : -ENODATA;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);
|
@ -7,12 +7,11 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/intel_tcc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#define TCC_SHIFT 24
|
||||
#define TCC_MASK (0x3fULL<<24)
|
||||
#define TCC_PROGRAMMABLE BIT(30)
|
||||
#define TCC_LOCKED BIT(31)
|
||||
|
||||
@ -21,47 +20,26 @@ static struct thermal_cooling_device *tcc_cdev;
|
||||
static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
*state)
|
||||
{
|
||||
*state = TCC_MASK >> TCC_SHIFT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcc_offset_update(int tcc)
|
||||
{
|
||||
u64 val;
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val &= ~TCC_MASK;
|
||||
val |= tcc << TCC_SHIFT;
|
||||
|
||||
err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*state = 0x3f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
*state)
|
||||
{
|
||||
u64 val;
|
||||
int err;
|
||||
int offset = intel_tcc_get_offset(-1);
|
||||
|
||||
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
||||
if (err)
|
||||
return err;
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
|
||||
*state = (val & TCC_MASK) >> TCC_SHIFT;
|
||||
*state = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
||||
state)
|
||||
{
|
||||
return tcc_offset_update(state);
|
||||
return intel_tcc_set_offset(-1, (int)state);
|
||||
}
|
||||
|
||||
static const struct thermal_cooling_device_ops tcc_cooling_ops = {
|
||||
@ -140,6 +118,7 @@ static void __exit tcc_cooling_exit(void)
|
||||
|
||||
module_exit(tcc_cooling_exit)
|
||||
|
||||
MODULE_IMPORT_NS(INTEL_TCC);
|
||||
MODULE_DESCRIPTION("TCC offset cooling device Driver");
|
||||
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/intel_tcc.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/device.h>
|
||||
@ -48,7 +49,6 @@ MODULE_PARM_DESC(notify_delay_ms,
|
||||
struct zone_device {
|
||||
int cpu;
|
||||
bool work_scheduled;
|
||||
u32 tj_max;
|
||||
u32 msr_pkg_therm_low;
|
||||
u32 msr_pkg_therm_high;
|
||||
struct delayed_work work;
|
||||
@ -105,38 +105,18 @@ static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* tj-max is interesting because threshold is set relative to this
|
||||
* temperature.
|
||||
*/
|
||||
static int get_tj_max(int cpu, u32 *tj_max)
|
||||
{
|
||||
u32 eax, edx, val;
|
||||
int err;
|
||||
|
||||
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = (eax >> 16) & 0xff;
|
||||
*tj_max = val * 1000;
|
||||
|
||||
return val ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
|
||||
{
|
||||
struct zone_device *zonedev = tzd->devdata;
|
||||
u32 eax, edx;
|
||||
int val;
|
||||
|
||||
rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_STATUS,
|
||||
&eax, &edx);
|
||||
if (eax & 0x80000000) {
|
||||
*temp = zonedev->tj_max - ((eax >> 16) & 0x7f) * 1000;
|
||||
pr_debug("sys_get_curr_temp %d\n", *temp);
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
val = intel_tcc_get_temp(zonedev->cpu, true);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
*temp = val * 1000;
|
||||
pr_debug("sys_get_curr_temp %d\n", *temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -144,9 +124,14 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
|
||||
{
|
||||
struct zone_device *zonedev = tzd->devdata;
|
||||
u32 l, h, mask, shift, intr;
|
||||
int ret;
|
||||
int tj_max, ret;
|
||||
|
||||
if (trip >= MAX_NUMBER_OF_TRIPS || temp >= zonedev->tj_max)
|
||||
tj_max = intel_tcc_get_tjmax(zonedev->cpu);
|
||||
if (tj_max < 0)
|
||||
return tj_max;
|
||||
tj_max *= 1000;
|
||||
|
||||
if (trip >= MAX_NUMBER_OF_TRIPS || temp >= tj_max)
|
||||
return -EINVAL;
|
||||
|
||||
ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
@ -171,7 +156,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
|
||||
if (!temp) {
|
||||
l &= ~intr;
|
||||
} else {
|
||||
l |= (zonedev->tj_max - temp)/1000 << shift;
|
||||
l |= (tj_max - temp)/1000 << shift;
|
||||
l |= intr;
|
||||
}
|
||||
|
||||
@ -326,9 +311,10 @@ static struct thermal_trip *pkg_temp_thermal_trips_init(int cpu, int tj_max, int
|
||||
static int pkg_temp_thermal_device_add(unsigned int cpu)
|
||||
{
|
||||
int id = topology_logical_die_id(cpu);
|
||||
u32 tj_max, eax, ebx, ecx, edx;
|
||||
u32 eax, ebx, ecx, edx;
|
||||
struct zone_device *zonedev;
|
||||
int thres_count, err;
|
||||
int tj_max;
|
||||
|
||||
if (id >= max_id)
|
||||
return -ENOMEM;
|
||||
@ -340,9 +326,9 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
|
||||
|
||||
thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS);
|
||||
|
||||
err = get_tj_max(cpu, &tj_max);
|
||||
if (err)
|
||||
return err;
|
||||
tj_max = intel_tcc_get_tjmax(cpu);
|
||||
if (tj_max < 0)
|
||||
return tj_max;
|
||||
|
||||
zonedev = kzalloc(sizeof(*zonedev), GFP_KERNEL);
|
||||
if (!zonedev)
|
||||
@ -356,7 +342,6 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
|
||||
|
||||
INIT_DELAYED_WORK(&zonedev->work, pkg_temp_thermal_threshold_work_fn);
|
||||
zonedev->cpu = cpu;
|
||||
zonedev->tj_max = tj_max;
|
||||
zonedev->tzone = thermal_zone_device_register_with_trips("x86_pkg_temp",
|
||||
zonedev->trips, thres_count,
|
||||
(thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01,
|
||||
@ -545,6 +530,7 @@ static void __exit pkg_temp_thermal_exit(void)
|
||||
}
|
||||
module_exit(pkg_temp_thermal_exit)
|
||||
|
||||
MODULE_IMPORT_NS(INTEL_TCC);
|
||||
MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
|
||||
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
151
drivers/thermal/thermal_acpi.c
Normal file
151
drivers/thermal/thermal_acpi.c
Normal file
@ -0,0 +1,151 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2023 Linaro Limited
|
||||
* Copyright 2023 Intel Corporation
|
||||
*
|
||||
* Library routines for populating a generic thermal trip point structure
|
||||
* with data obtained by evaluating a specific object in the ACPI Namespace.
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "thermal_core.h"
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define TEMP_MIN_DECIK 2180
|
||||
#define TEMP_MAX_DECIK 4480
|
||||
|
||||
static int thermal_acpi_trip_init(struct acpi_device *adev,
|
||||
enum thermal_trip_type type, int id,
|
||||
struct thermal_trip *trip)
|
||||
{
|
||||
unsigned long long temp;
|
||||
acpi_status status;
|
||||
char obj_name[5];
|
||||
|
||||
switch (type) {
|
||||
case THERMAL_TRIP_ACTIVE:
|
||||
if (id < 0 || id > 9)
|
||||
return -EINVAL;
|
||||
|
||||
obj_name[1] = 'A';
|
||||
obj_name[2] = 'C';
|
||||
obj_name[3] = '0' + id;
|
||||
break;
|
||||
case THERMAL_TRIP_PASSIVE:
|
||||
obj_name[1] = 'P';
|
||||
obj_name[2] = 'S';
|
||||
obj_name[3] = 'V';
|
||||
break;
|
||||
case THERMAL_TRIP_HOT:
|
||||
obj_name[1] = 'H';
|
||||
obj_name[2] = 'O';
|
||||
obj_name[3] = 'T';
|
||||
break;
|
||||
case THERMAL_TRIP_CRITICAL:
|
||||
obj_name[1] = 'C';
|
||||
obj_name[2] = 'R';
|
||||
obj_name[3] = 'T';
|
||||
break;
|
||||
}
|
||||
|
||||
obj_name[0] = '_';
|
||||
obj_name[4] = '\0';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (temp >= TEMP_MIN_DECIK && temp <= TEMP_MAX_DECIK) {
|
||||
trip->temperature = deci_kelvin_to_millicelsius(temp);
|
||||
} else {
|
||||
acpi_handle_debug(adev->handle, "%s result %llu out of range\n",
|
||||
obj_name, temp);
|
||||
trip->temperature = THERMAL_TEMP_INVALID;
|
||||
}
|
||||
|
||||
trip->hysteresis = 0;
|
||||
trip->type = type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* thermal_acpi_trip_active - Get the specified active trip point
|
||||
* @adev: Thermal zone ACPI device object to get the description from.
|
||||
* @id: Active cooling level (0 - 9).
|
||||
* @trip: Trip point structure to be populated on success.
|
||||
*
|
||||
* 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
|
||||
* cooling level given by @id and initialize @trip as an active trip point using
|
||||
* that temperature value.
|
||||
*
|
||||
* Return 0 on success or a negative error value on failure.
|
||||
*/
|
||||
int thermal_acpi_trip_active(struct acpi_device *adev, int id,
|
||||
struct thermal_trip *trip)
|
||||
{
|
||||
return thermal_acpi_trip_init(adev, THERMAL_TRIP_ACTIVE, id, trip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(thermal_acpi_trip_active);
|
||||
|
||||
/**
|
||||
* thermal_acpi_trip_passive - Get the passive trip point
|
||||
* @adev: Thermal zone ACPI device object to get the description from.
|
||||
* @trip: Trip point structure to be populated on success.
|
||||
*
|
||||
* Evaluate the _PSV object for the thermal zone represented by @adev to obtain
|
||||
* the temperature of the passive cooling trip point and initialize @trip as a
|
||||
* passive trip point using that temperature value.
|
||||
*
|
||||
* Return 0 on success or -ENODATA on failure.
|
||||
*/
|
||||
int thermal_acpi_trip_passive(struct acpi_device *adev, struct thermal_trip *trip)
|
||||
{
|
||||
return thermal_acpi_trip_init(adev, THERMAL_TRIP_PASSIVE, INT_MAX, trip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(thermal_acpi_trip_passive);
|
||||
|
||||
/**
|
||||
* thermal_acpi_trip_hot - Get the near critical trip point
|
||||
* @adev: the ACPI device to get the description from.
|
||||
* @trip: a &struct thermal_trip to be filled if the function succeed.
|
||||
*
|
||||
* 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
|
||||
* into the S4 sleep state and initialize @trip as a hot trip point using that
|
||||
* temperature value.
|
||||
*
|
||||
* Return 0 on success or -ENODATA on failure.
|
||||
*/
|
||||
int thermal_acpi_trip_hot(struct acpi_device *adev, struct thermal_trip *trip)
|
||||
{
|
||||
return thermal_acpi_trip_init(adev, THERMAL_TRIP_HOT, INT_MAX, trip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(thermal_acpi_trip_hot);
|
||||
|
||||
/**
|
||||
* thermal_acpi_trip_critical - Get the critical trip point
|
||||
* @adev: the ACPI device to get the description from.
|
||||
* @trip: a &struct thermal_trip to be filled if the function succeed.
|
||||
*
|
||||
* Evaluate the _CRT object for the thermal zone represented by @adev to obtain
|
||||
* the temperature of the critical cooling trip point and initialize @trip as a
|
||||
* critical trip point using that temperature value.
|
||||
*
|
||||
* Return 0 on success or -ENODATA on failure.
|
||||
*/
|
||||
int thermal_acpi_trip_critical(struct acpi_device *adev, struct thermal_trip *trip)
|
||||
{
|
||||
return thermal_acpi_trip_init(adev, THERMAL_TRIP_CRITICAL, INT_MAX, trip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(thermal_acpi_trip_critical);
|
18
include/linux/intel_tcc.h
Normal file
18
include/linux/intel_tcc.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* header for Intel TCC (thermal control circuitry) library
|
||||
*
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_TCC_H__
|
||||
#define __INTEL_TCC_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
int intel_tcc_get_tjmax(int cpu);
|
||||
int intel_tcc_get_offset(int cpu);
|
||||
int intel_tcc_set_offset(int cpu, int offset);
|
||||
int intel_tcc_get_temp(int cpu, bool pkg);
|
||||
|
||||
#endif /* __INTEL_TCC_H__ */
|
@ -346,6 +346,14 @@ int thermal_zone_get_num_trips(struct thermal_zone_device *tz);
|
||||
|
||||
int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp);
|
||||
|
||||
#ifdef CONFIG_THERMAL_ACPI
|
||||
int thermal_acpi_trip_active(struct acpi_device *adev, int id,
|
||||
struct thermal_trip *trip);
|
||||
int thermal_acpi_trip_passive(struct acpi_device *adev, struct thermal_trip *trip);
|
||||
int thermal_acpi_trip_hot(struct acpi_device *adev, struct thermal_trip *trip);
|
||||
int thermal_acpi_trip_critical(struct acpi_device *adev, struct thermal_trip *trip);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_THERMAL
|
||||
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
|
||||
void *, struct thermal_zone_device_ops *,
|
||||
|
Loading…
Reference in New Issue
Block a user