OpenCloudOS-Kernel/drivers/thermal/intel/int340x_thermal/int3400_thermal.c

687 lines
16 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0-only
/*
* INT3400 thermal driver
*
* Copyright (C) 2014, Intel Corporation
* Authors: Zhang Rui <rui.zhang@intel.com>
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include "acpi_thermal_rel.h"
#define INT3400_THERMAL_TABLE_CHANGED 0x83
#define INT3400_ODVP_CHANGED 0x88
#define INT3400_KEEP_ALIVE 0xA0
enum int3400_thermal_uuid {
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
INT3400_THERMAL_ACTIVE = 0,
INT3400_THERMAL_PASSIVE_1,
INT3400_THERMAL_CRITICAL,
INT3400_THERMAL_ADAPTIVE_PERFORMANCE,
INT3400_THERMAL_EMERGENCY_CALL_MODE,
INT3400_THERMAL_PASSIVE_2,
INT3400_THERMAL_POWER_BOSS,
INT3400_THERMAL_VIRTUAL_SENSOR,
INT3400_THERMAL_COOLING_MODE,
INT3400_THERMAL_HARDWARE_DUTY_CYCLING,
INT3400_THERMAL_MAXIMUM_UUID,
};
static char *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
"3A95C389-E4B8-4629-A526-C52C88626BAE",
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
"42A441D6-AE6A-462b-A84B-4A8CE79027D3",
"97C68AE7-15FA-499c-B8C9-5DA81D606E0A",
"63BE270F-1C11-48FD-A6F7-3AF253FF3E2D",
"5349962F-71E6-431D-9AE8-0A635B710AEE",
"9E04115A-AE87-4D1C-9500-0F3E340BFE75",
"F5A35014-C209-46A4-993A-EB56DE7530A1",
"6ED722A7-9240-48A5-B479-31EEF723D7CF",
"16CAF1B7-DD38-40ED-B1C1-1B8A1913D531",
"BE84BABF-C4D4-403D-B495-3128FD44dAC1",
};
struct odvp_attr;
struct int3400_thermal_priv {
struct acpi_device *adev;
struct platform_device *pdev;
struct thermal_zone_device *thermal;
int art_count;
struct art *arts;
int trt_count;
struct trt *trts;
u32 uuid_bitmap;
int rel_misc_dev_res;
int current_uuid_index;
char *data_vault;
int odvp_count;
int *odvp;
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
u32 os_uuid_mask;
struct odvp_attr *odvp_attrs;
};
static int evaluate_odvp(struct int3400_thermal_priv *priv);
struct odvp_attr {
int odvp;
struct int3400_thermal_priv *priv;
struct device_attribute attr;
};
static ssize_t data_vault_read(struct file *file, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t off, size_t count)
{
memcpy(buf, attr->private + off, count);
return count;
}
static BIN_ATTR_RO(data_vault, 0);
static struct bin_attribute *data_attributes[] = {
&bin_attr_data_vault,
NULL,
};
static ssize_t imok_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
acpi_status status;
int input, ret;
ret = kstrtouint(buf, 10, &input);
if (ret)
return ret;
status = acpi_execute_simple_method(priv->adev->handle, "IMOK", input);
if (ACPI_FAILURE(status))
return -EIO;
return count;
}
static DEVICE_ATTR_WO(imok);
static struct attribute *imok_attr[] = {
&dev_attr_imok.attr,
NULL
};
static const struct attribute_group imok_attribute_group = {
.attrs = imok_attr,
};
static const struct attribute_group data_attribute_group = {
.bin_attrs = data_attributes,
};
static ssize_t available_uuids_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
int i;
int length = 0;
if (!priv->uuid_bitmap)
return sprintf(buf, "UNKNOWN\n");
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]);
}
return length;
}
static ssize_t current_uuid_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
int i, length = 0;
if (priv->current_uuid_index > 0)
return sprintf(buf, "%s\n",
int3400_thermal_uuids[priv->current_uuid_index]);
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]);
}
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
if (length)
return length;
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
return sprintf(buf, "INVALID\n");
}
static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enable)
{
u32 ret, buf[2];
acpi_status status;
int result = 0;
struct acpi_osc_context context = {
.uuid_str = uuid_str,
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
.rev = 1,
.cap.length = 8,
.cap.pointer = buf,
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
};
buf[OSC_QUERY_DWORD] = 0;
buf[OSC_SUPPORT_DWORD] = *enable;
status = acpi_run_osc(handle, &context);
if (ACPI_SUCCESS(status)) {
ret = *((u32 *)(context.ret.pointer + 4));
if (ret != *enable)
result = -EPERM;
kfree(context.ret.pointer);
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
} else
result = -EPERM;
return result;
}
static int set_os_uuid_mask(struct int3400_thermal_priv *priv, u32 mask)
{
int cap = 0;
/*
* Capability bits:
* Bit 0: set to 1 to indicate DPTF is active
* Bi1 1: set to 1 to active cooling is supported by user space daemon
* Bit 2: set to 1 to passive cooling is supported by user space daemon
* Bit 3: set to 1 to critical trip is handled by user space daemon
*/
if (mask)
cap = (priv->os_uuid_mask << 1) | 0x01;
return int3400_thermal_run_osc(priv->adev->handle,
"b23ba85d-c8b7-3542-88de-8de2ffcfd698",
&cap);
}
static ssize_t current_uuid_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
int ret, i;
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; ++i) {
if (!strncmp(buf, int3400_thermal_uuids[i],
sizeof(int3400_thermal_uuids[i]) - 1)) {
/*
* If we have a list of supported UUIDs, make sure
* this one is supported.
*/
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
if (priv->uuid_bitmap & BIT(i)) {
priv->current_uuid_index = i;
return count;
}
/*
* There is support of only 3 policies via the new
* _OSC to inform OS capability:
* INT3400_THERMAL_ACTIVE
* INT3400_THERMAL_PASSIVE_1
* INT3400_THERMAL_CRITICAL
*/
if (i > INT3400_THERMAL_CRITICAL)
return -EINVAL;
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
priv->os_uuid_mask |= BIT(i);
break;
}
}
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
if (priv->os_uuid_mask) {
ret = set_os_uuid_mask(priv, priv->os_uuid_mask);
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
if (ret)
return ret;
}
return count;
}
static DEVICE_ATTR_RW(current_uuid);
static DEVICE_ATTR_RO(available_uuids);
static struct attribute *uuid_attrs[] = {
&dev_attr_available_uuids.attr,
&dev_attr_current_uuid.attr,
NULL
};
static const struct attribute_group uuid_attribute_group = {
.attrs = uuid_attrs,
.name = "uuids"
};
static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
{
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *obja, *objb;
int i, j;
int result = 0;
acpi_status status;
status = acpi_evaluate_object(priv->adev->handle, "IDSP", NULL, &buf);
if (ACPI_FAILURE(status))
return -ENODEV;
obja = (union acpi_object *)buf.pointer;
if (obja->type != ACPI_TYPE_PACKAGE) {
result = -EINVAL;
goto end;
}
for (i = 0; i < obja->package.count; i++) {
objb = &obja->package.elements[i];
if (objb->type != ACPI_TYPE_BUFFER) {
result = -EINVAL;
goto end;
}
/* UUID must be 16 bytes */
if (objb->buffer.length != 16) {
result = -EINVAL;
goto end;
}
for (j = 0; j < INT3400_THERMAL_MAXIMUM_UUID; j++) {
guid_t guid;
guid_parse(int3400_thermal_uuids[j], &guid);
if (guid_equal((guid_t *)objb->buffer.pointer, &guid)) {
priv->uuid_bitmap |= (1 << j);
break;
}
}
}
end:
kfree(buf.pointer);
return result;
}
static ssize_t odvp_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct odvp_attr *odvp_attr;
odvp_attr = container_of(attr, struct odvp_attr, attr);
return sprintf(buf, "%d\n", odvp_attr->priv->odvp[odvp_attr->odvp]);
}
static void cleanup_odvp(struct int3400_thermal_priv *priv)
{
int i;
if (priv->odvp_attrs) {
for (i = 0; i < priv->odvp_count; i++) {
sysfs_remove_file(&priv->pdev->dev.kobj,
&priv->odvp_attrs[i].attr.attr);
kfree(priv->odvp_attrs[i].attr.attr.name);
}
kfree(priv->odvp_attrs);
}
kfree(priv->odvp);
priv->odvp_count = 0;
}
static int evaluate_odvp(struct int3400_thermal_priv *priv)
{
struct acpi_buffer odvp = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj = NULL;
acpi_status status;
int i, ret;
status = acpi_evaluate_object(priv->adev->handle, "ODVP", NULL, &odvp);
if (ACPI_FAILURE(status)) {
ret = -EINVAL;
goto out_err;
}
obj = odvp.pointer;
if (obj->type != ACPI_TYPE_PACKAGE) {
ret = -EINVAL;
goto out_err;
}
if (priv->odvp == NULL) {
priv->odvp_count = obj->package.count;
priv->odvp = kmalloc_array(priv->odvp_count, sizeof(int),
GFP_KERNEL);
if (!priv->odvp) {
ret = -ENOMEM;
goto out_err;
}
}
if (priv->odvp_attrs == NULL) {
priv->odvp_attrs = kcalloc(priv->odvp_count,
sizeof(struct odvp_attr),
GFP_KERNEL);
if (!priv->odvp_attrs) {
ret = -ENOMEM;
goto out_err;
}
for (i = 0; i < priv->odvp_count; i++) {
struct odvp_attr *odvp = &priv->odvp_attrs[i];
sysfs_attr_init(&odvp->attr.attr);
odvp->priv = priv;
odvp->odvp = i;
odvp->attr.attr.name = kasprintf(GFP_KERNEL,
"odvp%d", i);
if (!odvp->attr.attr.name) {
ret = -ENOMEM;
goto out_err;
}
odvp->attr.attr.mode = 0444;
odvp->attr.show = odvp_show;
odvp->attr.store = NULL;
ret = sysfs_create_file(&priv->pdev->dev.kobj,
&odvp->attr.attr);
if (ret)
goto out_err;
}
}
for (i = 0; i < obj->package.count; i++) {
if (obj->package.elements[i].type == ACPI_TYPE_INTEGER)
priv->odvp[i] = obj->package.elements[i].integer.value;
}
kfree(obj);
return 0;
out_err:
cleanup_odvp(priv);
kfree(obj);
return ret;
}
static void int3400_notify(acpi_handle handle,
u32 event,
void *data)
{
struct int3400_thermal_priv *priv = data;
char *thermal_prop[5];
int therm_event;
if (!priv)
return;
switch (event) {
case INT3400_THERMAL_TABLE_CHANGED:
therm_event = THERMAL_TABLE_CHANGED;
break;
case INT3400_KEEP_ALIVE:
therm_event = THERMAL_EVENT_KEEP_ALIVE;
break;
case INT3400_ODVP_CHANGED:
evaluate_odvp(priv);
therm_event = THERMAL_DEVICE_POWER_CAPABILITY_CHANGED;
break;
default:
/* Ignore unknown notification codes sent to INT3400 device */
return;
}
thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", priv->thermal->type);
thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", priv->thermal->temperature);
thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=");
thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", therm_event);
thermal_prop[4] = NULL;
kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE, thermal_prop);
kfree(thermal_prop[0]);
kfree(thermal_prop[1]);
kfree(thermal_prop[2]);
kfree(thermal_prop[3]);
}
static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,
thermal: consistently use int for temperatures The thermal code uses int, long and unsigned long for temperatures in different places. Using an unsigned type limits the thermal framework to positive temperatures without need. Also several drivers currently will report temperatures near UINT_MAX for temperatures below 0°C. This will probably immediately shut the machine down due to overtemperature if started below 0°C. 'long' is 64bit on several architectures. This is not needed since INT_MAX °mC is above the melting point of all known materials. Consistently use a plain 'int' for temperatures throughout the thermal code and the drivers. This only changes the places in the drivers where the temperature is passed around as pointer, when drivers internally use another type this is not changed. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Jean Delvare <jdelvare@suse.de> Reviewed-by: Lukasz Majewski <l.majewski@samsung.com> Reviewed-by: Darren Hart <dvhart@linux.intel.com> Reviewed-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Peter Feuerer <peter@piie.net> Cc: Punit Agrawal <punit.agrawal@arm.com> Cc: Zhang Rui <rui.zhang@intel.com> Cc: Eduardo Valentin <edubezval@gmail.com> Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Jean Delvare <jdelvare@suse.de> Cc: Peter Feuerer <peter@piie.net> Cc: Heiko Stuebner <heiko@sntech.de> Cc: Lukasz Majewski <l.majewski@samsung.com> Cc: Stephen Warren <swarren@wwwdotorg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: linux-acpi@vger.kernel.org Cc: platform-driver-x86@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-omap@vger.kernel.org Cc: linux-samsung-soc@vger.kernel.org Cc: Guenter Roeck <linux@roeck-us.net> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: Maxime Ripard <maxime.ripard@free-electrons.com> Cc: Darren Hart <dvhart@infradead.org> Cc: lm-sensors@lm-sensors.org Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2015-07-24 14:12:54 +08:00
int *temp)
{
*temp = 20 * 1000; /* faked temp sensor with 20C */
return 0;
}
static int int3400_thermal_change_mode(struct thermal_zone_device *thermal,
enum thermal_device_mode mode)
{
struct int3400_thermal_priv *priv = thermal->devdata;
int result = 0;
if (!priv)
return -EINVAL;
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
if (mode != thermal->mode) {
int enabled;
enabled = mode == THERMAL_DEVICE_ENABLED;
if (priv->os_uuid_mask) {
if (!enabled) {
priv->os_uuid_mask = 0;
result = set_os_uuid_mask(priv, priv->os_uuid_mask);
}
goto eval_odvp;
}
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
if (priv->current_uuid_index < 0 ||
priv->current_uuid_index >= INT3400_THERMAL_MAXIMUM_UUID)
return -EINVAL;
result = int3400_thermal_run_osc(priv->adev->handle,
thermal: int340x: Update OS policy capability handshake Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2022-03-15 06:09:37 +08:00
int3400_thermal_uuids[priv->current_uuid_index],
&enabled);
}
thermal: Use mode helpers in drivers Use thermal_zone_device_{en|dis}able() and thermal_zone_device_is_enabled(). Consequently, all set_mode() implementations in drivers: - can stop modifying tzd's "mode" member, - shall stop taking tzd's lock, as it is taken in the helpers - shall stop calling thermal_zone_device_update() as it is called in the helpers - can assume they are called when the mode truly changes, so checks to verify that can be dropped Not providing set_mode() by a driver no longer prevents the core from being able to set tzd's mode, so the relevant check in mode_store() is removed. Other comments: - acpi/thermal.c: tz->thermal_zone->mode will be updated only after we return from set_mode(), so use function parameter in thermal_set_mode() instead, no need to call acpi_thermal_check() in set_mode() - thermal/imx_thermal.c: regmap writes and mode assignment are done in thermal_zone_device_{en|dis}able() and set_mode() callback - thermal/intel/intel_quark_dts_thermal.c: soc_dts_{en|dis}able() are a part of set_mode() callback, so they don't need to modify tzd->mode, and don't need to fall back to the opposite mode if unsuccessful, as the return value will be propagated to thermal_zone_device_{en|dis}able() and ultimately tzd's member will not be changed in thermal_zone_device_set_mode(). - thermal/of-thermal.c: no need to set zone->mode to DISABLED in of_parse_thermal_zones() as a tzd is kzalloc'ed so mode is DISABLED anyway Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com> [for acerhdf] Acked-by: Peter Kaestle <peter@piie.net> Reviewed-by: Amit Kucheria <amit.kucheria@linaro.org> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20200629122925.21729-8-andrzej.p@collabora.com
2020-06-29 20:29:21 +08:00
eval_odvp:
evaluate_odvp(priv);
return result;
}
static struct thermal_zone_device_ops int3400_thermal_ops = {
.get_temp = int3400_thermal_get_temp,
.change_mode = int3400_thermal_change_mode,
};
static struct thermal_zone_params int3400_thermal_params = {
.governor_name = "user_space",
.no_hwmon = true,
};
static void int3400_setup_gddv(struct int3400_thermal_priv *priv)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
acpi_status status;
status = acpi_evaluate_object(priv->adev->handle, "GDDV", NULL,
&buffer);
if (ACPI_FAILURE(status) || !buffer.length)
return;
obj = buffer.pointer;
if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 1
|| obj->package.elements[0].type != ACPI_TYPE_BUFFER)
goto out_free;
priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer,
obj->package.elements[0].buffer.length,
GFP_KERNEL);
if (ZERO_OR_NULL_PTR(priv->data_vault))
goto out_free;
bin_attr_data_vault.private = priv->data_vault;
bin_attr_data_vault.size = obj->package.elements[0].buffer.length;
out_free:
kfree(buffer.pointer);
}
static int int3400_thermal_probe(struct platform_device *pdev)
{
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
struct int3400_thermal_priv *priv;
int result;
if (!adev)
return -ENODEV;
priv = kzalloc(sizeof(struct int3400_thermal_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->pdev = pdev;
priv->adev = adev;
result = int3400_thermal_get_uuids(priv);
/* Missing IDSP isn't fatal */
if (result && result != -ENODEV)
goto free_priv;
priv->current_uuid_index = -1;
result = acpi_parse_art(priv->adev->handle, &priv->art_count,
&priv->arts, true);
if (result)
dev_dbg(&pdev->dev, "_ART table parsing error\n");
result = acpi_parse_trt(priv->adev->handle, &priv->trt_count,
&priv->trts, true);
if (result)
dev_dbg(&pdev->dev, "_TRT table parsing error\n");
platform_set_drvdata(pdev, priv);
int3400_setup_gddv(priv);
evaluate_odvp(priv);
priv->thermal = thermal_zone_device_register("INT3400 Thermal", 0, 0,
priv, &int3400_thermal_ops,
&int3400_thermal_params, 0, 0);
if (IS_ERR(priv->thermal)) {
result = PTR_ERR(priv->thermal);
goto free_art_trt;
}
priv->rel_misc_dev_res = acpi_thermal_rel_misc_device_add(
priv->adev->handle);
result = sysfs_create_group(&pdev->dev.kobj, &uuid_attribute_group);
if (result)
goto free_rel_misc;
if (acpi_has_method(priv->adev->handle, "IMOK")) {
result = sysfs_create_group(&pdev->dev.kobj, &imok_attribute_group);
if (result)
goto free_imok;
}
if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
result = sysfs_create_group(&pdev->dev.kobj,
&data_attribute_group);
if (result)
goto free_uuid;
}
result = acpi_install_notify_handler(
priv->adev->handle, ACPI_DEVICE_NOTIFY, int3400_notify,
(void *)priv);
if (result)
goto free_sysfs;
return 0;
free_sysfs:
cleanup_odvp(priv);
if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
kfree(priv->data_vault);
}
free_uuid:
sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
free_imok:
sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group);
free_rel_misc:
if (!priv->rel_misc_dev_res)
acpi_thermal_rel_misc_device_remove(priv->adev->handle);
thermal_zone_device_unregister(priv->thermal);
free_art_trt:
kfree(priv->trts);
kfree(priv->arts);
free_priv:
kfree(priv);
return result;
}
static int int3400_thermal_remove(struct platform_device *pdev)
{
struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
acpi_remove_notify_handler(
priv->adev->handle, ACPI_DEVICE_NOTIFY,
int3400_notify);
cleanup_odvp(priv);
if (!priv->rel_misc_dev_res)
acpi_thermal_rel_misc_device_remove(priv->adev->handle);
if (!ZERO_OR_NULL_PTR(priv->data_vault))
sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group);
thermal_zone_device_unregister(priv->thermal);
kfree(priv->data_vault);
kfree(priv->trts);
kfree(priv->arts);
kfree(priv);
return 0;
}
static const struct acpi_device_id int3400_thermal_match[] = {
{"INT3400", 0},
{"INTC1040", 0},
{"INTC1041", 0},
{"INTC1042", 0},
{"INTC10A0", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, int3400_thermal_match);
static struct platform_driver int3400_thermal_driver = {
.probe = int3400_thermal_probe,
.remove = int3400_thermal_remove,
.driver = {
.name = "int3400 thermal",
.acpi_match_table = ACPI_PTR(int3400_thermal_match),
},
};
module_platform_driver(int3400_thermal_driver);
MODULE_DESCRIPTION("INT3400 Thermal driver");
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
MODULE_LICENSE("GPL");