mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal managament updates from Zhang Rui:
"Specifics:
- Abstract the code and introduce helper functions for all int340x
thermal drivers. From: Srinivas Pandruvada.
- Reorganize the ACPI LPAT table support code so that it can be
shared for both ACPI PMIC driver and int340x thermal driver.
- Add support for Braswell in intel_soc_dts thermal driver.
- a couple of small fixes/cleanups for step_wise governor and int340x
thermal driver"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux:
Thermal/int340x_thermal: remove unused uuids.
thermal: step_wise: spelling fixes
thermal: int340x: fix sparse warning
Thermal/int340x: LPAT conversion for temperature
ACPI / PMIC: Use common LPAT table handling functions
ACPI / LPAT: Common table processing functions
thermal: Intel SoC DTS: Add Braswell support
Thermal/int340x/int3402: Provide notification support
Thermal/int340x/processor_thermal: Add thermal zone support
Thermal/int340x/int3403: Use int340x thermal API
Thermal/int340x/int3402: Use int340x thermal API
Thermal/int340x: Add common thermal zone handler
This commit is contained in:
commit
89d3fa45b4
13 changed files with 760 additions and 507 deletions
|
|
@ -1,4 +1,5 @@
|
|||
obj-$(CONFIG_INT340X_THERMAL) += int3400_thermal.o
|
||||
obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal_zone.o
|
||||
obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o
|
||||
obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o
|
||||
obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o
|
||||
|
|
|
|||
|
|
@ -18,19 +18,15 @@
|
|||
|
||||
enum int3400_thermal_uuid {
|
||||
INT3400_THERMAL_PASSIVE_1,
|
||||
INT3400_THERMAL_PASSIVE_2,
|
||||
INT3400_THERMAL_ACTIVE,
|
||||
INT3400_THERMAL_CRITICAL,
|
||||
INT3400_THERMAL_COOLING_MODE,
|
||||
INT3400_THERMAL_MAXIMUM_UUID,
|
||||
};
|
||||
|
||||
static u8 *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
|
||||
"42A441D6-AE6A-462b-A84B-4A8CE79027D3",
|
||||
"9E04115A-AE87-4D1C-9500-0F3E340BFE75",
|
||||
"3A95C389-E4B8-4629-A526-C52C88626BAE",
|
||||
"97C68AE7-15FA-499c-B8C9-5DA81D606E0A",
|
||||
"16CAF1B7-DD38-40ed-B1C1-1B8A1913D531",
|
||||
};
|
||||
|
||||
struct int3400_thermal_priv {
|
||||
|
|
|
|||
|
|
@ -14,152 +14,39 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/thermal.h>
|
||||
#include "int340x_thermal_zone.h"
|
||||
|
||||
#define ACPI_ACTIVE_COOLING_MAX_NR 10
|
||||
|
||||
struct active_trip {
|
||||
unsigned long temp;
|
||||
int id;
|
||||
bool valid;
|
||||
};
|
||||
#define INT3402_PERF_CHANGED_EVENT 0x80
|
||||
#define INT3402_THERMAL_EVENT 0x90
|
||||
|
||||
struct int3402_thermal_data {
|
||||
unsigned long *aux_trips;
|
||||
int aux_trip_nr;
|
||||
unsigned long psv_temp;
|
||||
int psv_trip_id;
|
||||
unsigned long crt_temp;
|
||||
int crt_trip_id;
|
||||
unsigned long hot_temp;
|
||||
int hot_trip_id;
|
||||
struct active_trip act_trips[ACPI_ACTIVE_COOLING_MAX_NR];
|
||||
acpi_handle *handle;
|
||||
struct int34x_thermal_zone *int340x_zone;
|
||||
};
|
||||
|
||||
static int int3402_thermal_get_zone_temp(struct thermal_zone_device *zone,
|
||||
unsigned long *temp)
|
||||
static void int3402_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct int3402_thermal_data *d = zone->devdata;
|
||||
unsigned long long tmp;
|
||||
acpi_status status;
|
||||
struct int3402_thermal_data *priv = data;
|
||||
|
||||
status = acpi_evaluate_integer(d->handle, "_TMP", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
/* _TMP returns the temperature in tenths of degrees Kelvin */
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int3402_thermal_get_trip_temp(struct thermal_zone_device *zone,
|
||||
int trip, unsigned long *temp)
|
||||
{
|
||||
struct int3402_thermal_data *d = zone->devdata;
|
||||
int i;
|
||||
|
||||
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 < ACPI_ACTIVE_COOLING_MAX_NR; i++) {
|
||||
if (d->act_trips[i].valid &&
|
||||
d->act_trips[i].id == trip) {
|
||||
*temp = d->act_trips[i].temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ACPI_ACTIVE_COOLING_MAX_NR)
|
||||
return -EINVAL;
|
||||
switch (event) {
|
||||
case INT3402_PERF_CHANGED_EVENT:
|
||||
break;
|
||||
case INT3402_THERMAL_EVENT:
|
||||
int340x_thermal_zone_device_update(priv->int340x_zone);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int3402_thermal_get_trip_type(struct thermal_zone_device *zone,
|
||||
int trip, enum thermal_trip_type *type)
|
||||
{
|
||||
struct int3402_thermal_data *d = zone->devdata;
|
||||
int i;
|
||||
|
||||
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 < ACPI_ACTIVE_COOLING_MAX_NR; i++) {
|
||||
if (d->act_trips[i].valid &&
|
||||
d->act_trips[i].id == trip) {
|
||||
*type = THERMAL_TRIP_ACTIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ACPI_ACTIVE_COOLING_MAX_NR)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int3402_thermal_set_trip_temp(struct thermal_zone_device *zone, int trip,
|
||||
unsigned long temp)
|
||||
{
|
||||
struct int3402_thermal_data *d = zone->devdata;
|
||||
acpi_status status;
|
||||
char name[10];
|
||||
|
||||
snprintf(name, sizeof(name), "PAT%d", trip);
|
||||
status = acpi_execute_simple_method(d->handle, name,
|
||||
MILLICELSIUS_TO_DECI_KELVIN(temp));
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
d->aux_trips[trip] = temp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_zone_device_ops int3402_thermal_zone_ops = {
|
||||
.get_temp = int3402_thermal_get_zone_temp,
|
||||
.get_trip_temp = int3402_thermal_get_trip_temp,
|
||||
.get_trip_type = int3402_thermal_get_trip_type,
|
||||
.set_trip_temp = int3402_thermal_set_trip_temp,
|
||||
};
|
||||
|
||||
static struct thermal_zone_params int3402_thermal_params = {
|
||||
.governor_name = "user_space",
|
||||
.no_hwmon = true,
|
||||
};
|
||||
|
||||
static int int3402_thermal_get_temp(acpi_handle handle, char *name,
|
||||
unsigned long *temp)
|
||||
{
|
||||
unsigned long long r;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(handle, name, NULL, &r);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int3402_thermal_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
|
||||
struct int3402_thermal_data *d;
|
||||
struct thermal_zone_device *zone;
|
||||
acpi_status status;
|
||||
unsigned long long trip_cnt;
|
||||
int trip_mask = 0, i;
|
||||
int ret;
|
||||
|
||||
if (!acpi_has_method(adev->handle, "_TMP"))
|
||||
return -ENODEV;
|
||||
|
|
@ -168,54 +55,33 @@ static int int3402_thermal_probe(struct platform_device *pdev)
|
|||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt);
|
||||
if (ACPI_FAILURE(status))
|
||||
trip_cnt = 0;
|
||||
else {
|
||||
d->aux_trips = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*d->aux_trips) * trip_cnt, GFP_KERNEL);
|
||||
if (!d->aux_trips)
|
||||
return -ENOMEM;
|
||||
trip_mask = trip_cnt - 1;
|
||||
d->handle = adev->handle;
|
||||
d->aux_trip_nr = trip_cnt;
|
||||
d->int340x_zone = int340x_thermal_zone_add(adev, NULL);
|
||||
if (IS_ERR(d->int340x_zone))
|
||||
return PTR_ERR(d->int340x_zone);
|
||||
|
||||
ret = acpi_install_notify_handler(adev->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
int3402_notify,
|
||||
d);
|
||||
if (ret) {
|
||||
int340x_thermal_zone_remove(d->int340x_zone);
|
||||
return ret;
|
||||
}
|
||||
|
||||
d->crt_trip_id = -1;
|
||||
if (!int3402_thermal_get_temp(adev->handle, "_CRT", &d->crt_temp))
|
||||
d->crt_trip_id = trip_cnt++;
|
||||
d->hot_trip_id = -1;
|
||||
if (!int3402_thermal_get_temp(adev->handle, "_HOT", &d->hot_temp))
|
||||
d->hot_trip_id = trip_cnt++;
|
||||
d->psv_trip_id = -1;
|
||||
if (!int3402_thermal_get_temp(adev->handle, "_PSV", &d->psv_temp))
|
||||
d->psv_trip_id = trip_cnt++;
|
||||
for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) {
|
||||
char name[5] = { '_', 'A', 'C', '0' + i, '\0' };
|
||||
if (int3402_thermal_get_temp(adev->handle, name,
|
||||
&d->act_trips[i].temp))
|
||||
break;
|
||||
d->act_trips[i].id = trip_cnt++;
|
||||
d->act_trips[i].valid = true;
|
||||
}
|
||||
|
||||
zone = thermal_zone_device_register(acpi_device_bid(adev), trip_cnt,
|
||||
trip_mask, d,
|
||||
&int3402_thermal_zone_ops,
|
||||
&int3402_thermal_params,
|
||||
0, 0);
|
||||
if (IS_ERR(zone))
|
||||
return PTR_ERR(zone);
|
||||
platform_set_drvdata(pdev, zone);
|
||||
d->handle = adev->handle;
|
||||
platform_set_drvdata(pdev, d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int3402_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct thermal_zone_device *zone = platform_get_drvdata(pdev);
|
||||
struct int3402_thermal_data *d = platform_get_drvdata(pdev);
|
||||
|
||||
acpi_remove_notify_handler(d->handle,
|
||||
ACPI_DEVICE_NOTIFY, int3402_notify);
|
||||
int340x_thermal_zone_remove(d->int340x_zone);
|
||||
|
||||
thermal_zone_device_unregister(zone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/acpi.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "int340x_thermal_zone.h"
|
||||
|
||||
#define INT3403_TYPE_SENSOR 0x03
|
||||
#define INT3403_TYPE_CHARGER 0x0B
|
||||
|
|
@ -26,18 +27,9 @@
|
|||
#define INT3403_PERF_CHANGED_EVENT 0x80
|
||||
#define INT3403_THERMAL_EVENT 0x90
|
||||
|
||||
#define DECI_KELVIN_TO_MILLI_CELSIUS(t, off) (((t) - (off)) * 100)
|
||||
#define KELVIN_OFFSET 2732
|
||||
#define MILLI_CELSIUS_TO_DECI_KELVIN(t, off) (((t) / 100) + (off))
|
||||
|
||||
/* Preserved structure for future expandbility */
|
||||
struct int3403_sensor {
|
||||
struct thermal_zone_device *tzone;
|
||||
unsigned long *thresholds;
|
||||
unsigned long crit_temp;
|
||||
int crit_trip_id;
|
||||
unsigned long psv_temp;
|
||||
int psv_trip_id;
|
||||
|
||||
struct int34x_thermal_zone *int340x_zone;
|
||||
};
|
||||
|
||||
struct int3403_performance_state {
|
||||
|
|
@ -63,126 +55,6 @@ struct int3403_priv {
|
|||
void *priv;
|
||||
};
|
||||
|
||||
static int sys_get_curr_temp(struct thermal_zone_device *tzone,
|
||||
unsigned long *temp)
|
||||
{
|
||||
struct int3403_priv *priv = tzone->devdata;
|
||||
struct acpi_device *device = priv->adev;
|
||||
unsigned long long tmp;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "_TMP", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
*temp = DECI_KELVIN_TO_MILLI_CELSIUS(tmp, KELVIN_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_get_trip_hyst(struct thermal_zone_device *tzone,
|
||||
int trip, unsigned long *temp)
|
||||
{
|
||||
struct int3403_priv *priv = tzone->devdata;
|
||||
struct acpi_device *device = priv->adev;
|
||||
unsigned long long hyst;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "GTSH", NULL, &hyst);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
* Thermal hysteresis represents a temperature difference.
|
||||
* Kelvin and Celsius have same degree size. So the
|
||||
* conversion here between tenths of degree Kelvin unit
|
||||
* and Milli-Celsius unit is just to multiply 100.
|
||||
*/
|
||||
*temp = hyst * 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_get_trip_temp(struct thermal_zone_device *tzone,
|
||||
int trip, unsigned long *temp)
|
||||
{
|
||||
struct int3403_priv *priv = tzone->devdata;
|
||||
struct int3403_sensor *obj = priv->priv;
|
||||
|
||||
if (priv->type != INT3403_TYPE_SENSOR || !obj)
|
||||
return -EINVAL;
|
||||
|
||||
if (trip == obj->crit_trip_id)
|
||||
*temp = obj->crit_temp;
|
||||
else if (trip == obj->psv_trip_id)
|
||||
*temp = obj->psv_temp;
|
||||
else {
|
||||
/*
|
||||
* get_trip_temp is a mandatory callback but
|
||||
* PATx method doesn't return any value, so return
|
||||
* cached value, which was last set from user space
|
||||
*/
|
||||
*temp = obj->thresholds[trip];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_get_trip_type(struct thermal_zone_device *thermal,
|
||||
int trip, enum thermal_trip_type *type)
|
||||
{
|
||||
struct int3403_priv *priv = thermal->devdata;
|
||||
struct int3403_sensor *obj = priv->priv;
|
||||
|
||||
/* Mandatory callback, may not mean much here */
|
||||
if (trip == obj->crit_trip_id)
|
||||
*type = THERMAL_TRIP_CRITICAL;
|
||||
else
|
||||
*type = THERMAL_TRIP_PASSIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sys_set_trip_temp(struct thermal_zone_device *tzone, int trip,
|
||||
unsigned long temp)
|
||||
{
|
||||
struct int3403_priv *priv = tzone->devdata;
|
||||
struct acpi_device *device = priv->adev;
|
||||
struct int3403_sensor *obj = priv->priv;
|
||||
acpi_status status;
|
||||
char name[10];
|
||||
int ret = 0;
|
||||
|
||||
snprintf(name, sizeof(name), "PAT%d", trip);
|
||||
if (acpi_has_method(device->handle, name)) {
|
||||
status = acpi_execute_simple_method(device->handle, name,
|
||||
MILLI_CELSIUS_TO_DECI_KELVIN(temp,
|
||||
KELVIN_OFFSET));
|
||||
if (ACPI_FAILURE(status))
|
||||
ret = -EIO;
|
||||
else
|
||||
obj->thresholds[trip] = temp;
|
||||
} else {
|
||||
ret = -EIO;
|
||||
dev_err(&device->dev, "sys_set_trip_temp: method not found\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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,
|
||||
.get_trip_hyst = sys_get_trip_hyst,
|
||||
};
|
||||
|
||||
static struct thermal_zone_params int3403_thermal_params = {
|
||||
.governor_name = "user_space",
|
||||
.no_hwmon = true,
|
||||
};
|
||||
|
||||
static void int3403_notify(acpi_handle handle,
|
||||
u32 event, void *data)
|
||||
{
|
||||
|
|
@ -200,7 +72,7 @@ static void int3403_notify(acpi_handle handle,
|
|||
case INT3403_PERF_CHANGED_EVENT:
|
||||
break;
|
||||
case INT3403_THERMAL_EVENT:
|
||||
thermal_zone_device_update(obj->tzone);
|
||||
int340x_thermal_zone_device_update(obj->int340x_zone);
|
||||
break;
|
||||
default:
|
||||
dev_err(&priv->pdev->dev, "Unsupported event [0x%x]\n", event);
|
||||
|
|
@ -208,41 +80,10 @@ static void int3403_notify(acpi_handle handle,
|
|||
}
|
||||
}
|
||||
|
||||
static int sys_get_trip_crt(struct acpi_device *device, unsigned long *temp)
|
||||
{
|
||||
unsigned long long crt;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "_CRT", NULL, &crt);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
*temp = DECI_KELVIN_TO_MILLI_CELSIUS(crt, KELVIN_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_get_trip_psv(struct acpi_device *device, unsigned long *temp)
|
||||
{
|
||||
unsigned long long psv;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(device->handle, "_PSV", NULL, &psv);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
*temp = DECI_KELVIN_TO_MILLI_CELSIUS(psv, KELVIN_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int3403_sensor_add(struct int3403_priv *priv)
|
||||
{
|
||||
int result = 0;
|
||||
acpi_status status;
|
||||
struct int3403_sensor *obj;
|
||||
unsigned long long trip_cnt;
|
||||
int trip_mask = 0;
|
||||
|
||||
obj = devm_kzalloc(&priv->pdev->dev, sizeof(*obj), GFP_KERNEL);
|
||||
if (!obj)
|
||||
|
|
@ -250,39 +91,9 @@ static int int3403_sensor_add(struct int3403_priv *priv)
|
|||
|
||||
priv->priv = obj;
|
||||
|
||||
status = acpi_evaluate_integer(priv->adev->handle, "PATC", NULL,
|
||||
&trip_cnt);
|
||||
if (ACPI_FAILURE(status))
|
||||
trip_cnt = 0;
|
||||
|
||||
if (trip_cnt) {
|
||||
/* We have to cache, thresholds can't be readback */
|
||||
obj->thresholds = devm_kzalloc(&priv->pdev->dev,
|
||||
sizeof(*obj->thresholds) * trip_cnt,
|
||||
GFP_KERNEL);
|
||||
if (!obj->thresholds) {
|
||||
result = -ENOMEM;
|
||||
goto err_free_obj;
|
||||
}
|
||||
trip_mask = BIT(trip_cnt) - 1;
|
||||
}
|
||||
|
||||
obj->psv_trip_id = -1;
|
||||
if (!sys_get_trip_psv(priv->adev, &obj->psv_temp))
|
||||
obj->psv_trip_id = trip_cnt++;
|
||||
|
||||
obj->crit_trip_id = -1;
|
||||
if (!sys_get_trip_crt(priv->adev, &obj->crit_temp))
|
||||
obj->crit_trip_id = trip_cnt++;
|
||||
|
||||
obj->tzone = thermal_zone_device_register(acpi_device_bid(priv->adev),
|
||||
trip_cnt, trip_mask, priv, &tzone_ops,
|
||||
&int3403_thermal_params, 0, 0);
|
||||
if (IS_ERR(obj->tzone)) {
|
||||
result = PTR_ERR(obj->tzone);
|
||||
obj->tzone = NULL;
|
||||
goto err_free_obj;
|
||||
}
|
||||
obj->int340x_zone = int340x_thermal_zone_add(priv->adev, NULL);
|
||||
if (IS_ERR(obj->int340x_zone))
|
||||
return PTR_ERR(obj->int340x_zone);
|
||||
|
||||
result = acpi_install_notify_handler(priv->adev->handle,
|
||||
ACPI_DEVICE_NOTIFY, int3403_notify,
|
||||
|
|
@ -293,7 +104,7 @@ static int int3403_sensor_add(struct int3403_priv *priv)
|
|||
return 0;
|
||||
|
||||
err_free_obj:
|
||||
thermal_zone_device_unregister(obj->tzone);
|
||||
int340x_thermal_zone_remove(obj->int340x_zone);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -303,7 +114,8 @@ static int int3403_sensor_remove(struct int3403_priv *priv)
|
|||
|
||||
acpi_remove_notify_handler(priv->adev->handle,
|
||||
ACPI_DEVICE_NOTIFY, int3403_notify);
|
||||
thermal_zone_device_unregister(obj->tzone);
|
||||
int340x_thermal_zone_remove(obj->int340x_zone);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
276
drivers/thermal/int340x_thermal/int340x_thermal_zone.c
Normal file
276
drivers/thermal/int340x_thermal/int340x_thermal_zone.c
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* int340x_thermal_zone.c
|
||||
* Copyright (c) 2015, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/thermal.h>
|
||||
#include "int340x_thermal_zone.h"
|
||||
|
||||
static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
|
||||
unsigned long *temp)
|
||||
{
|
||||
struct int34x_thermal_zone *d = zone->devdata;
|
||||
unsigned long long tmp;
|
||||
acpi_status status;
|
||||
|
||||
if (d->override_ops && d->override_ops->get_temp)
|
||||
return d->override_ops->get_temp(zone, temp);
|
||||
|
||||
status = acpi_evaluate_integer(d->adev->handle, "_TMP", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
if (d->lpat_table) {
|
||||
int conv_temp;
|
||||
|
||||
conv_temp = acpi_lpat_raw_to_temp(d->lpat_table, (int)tmp);
|
||||
if (conv_temp < 0)
|
||||
return conv_temp;
|
||||
|
||||
*temp = (unsigned long)conv_temp * 10;
|
||||
} else
|
||||
/* _TMP returns the temperature in tenths of degrees Kelvin */
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
|
||||
int trip, unsigned long *temp)
|
||||
{
|
||||
struct int34x_thermal_zone *d = zone->devdata;
|
||||
int i;
|
||||
|
||||
if (d->override_ops && d->override_ops->get_trip_temp)
|
||||
return d->override_ops->get_trip_temp(zone, trip, temp);
|
||||
|
||||
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)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (d->override_ops && d->override_ops->get_trip_type)
|
||||
return d->override_ops->get_trip_type(zone, trip, type);
|
||||
|
||||
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)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
|
||||
int trip, unsigned long temp)
|
||||
{
|
||||
struct int34x_thermal_zone *d = zone->devdata;
|
||||
acpi_status status;
|
||||
char name[10];
|
||||
|
||||
if (d->override_ops && d->override_ops->set_trip_temp)
|
||||
return d->override_ops->set_trip_temp(zone, trip, temp);
|
||||
|
||||
snprintf(name, sizeof(name), "PAT%d", trip);
|
||||
status = acpi_execute_simple_method(d->adev->handle, name,
|
||||
MILLICELSIUS_TO_DECI_KELVIN(temp));
|
||||
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, unsigned long *temp)
|
||||
{
|
||||
struct int34x_thermal_zone *d = zone->devdata;
|
||||
acpi_status status;
|
||||
unsigned long long hyst;
|
||||
|
||||
if (d->override_ops && d->override_ops->get_trip_hyst)
|
||||
return d->override_ops->get_trip_hyst(zone, trip, temp);
|
||||
|
||||
status = acpi_evaluate_integer(d->adev->handle, "GTSH", NULL, &hyst);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
*temp = hyst * 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
static int int340x_thermal_get_trip_config(acpi_handle handle, char *name,
|
||||
unsigned long *temp)
|
||||
{
|
||||
unsigned long long r;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(handle, name, NULL, &r);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_zone_params int340x_thermal_params = {
|
||||
.governor_name = "user_space",
|
||||
.no_hwmon = true,
|
||||
};
|
||||
|
||||
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
|
||||
struct thermal_zone_device_ops *override_ops)
|
||||
{
|
||||
struct int34x_thermal_zone *int34x_thermal_zone;
|
||||
acpi_status status;
|
||||
unsigned long long trip_cnt;
|
||||
int trip_mask = 0, i;
|
||||
int ret;
|
||||
|
||||
int34x_thermal_zone = kzalloc(sizeof(*int34x_thermal_zone),
|
||||
GFP_KERNEL);
|
||||
if (!int34x_thermal_zone)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
int34x_thermal_zone->adev = adev;
|
||||
int34x_thermal_zone->override_ops = override_ops;
|
||||
|
||||
status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt);
|
||||
if (ACPI_FAILURE(status))
|
||||
trip_cnt = 0;
|
||||
else {
|
||||
int34x_thermal_zone->aux_trips = kzalloc(
|
||||
sizeof(*int34x_thermal_zone->aux_trips) *
|
||||
trip_cnt, GFP_KERNEL);
|
||||
if (!int34x_thermal_zone->aux_trips) {
|
||||
ret = -ENOMEM;
|
||||
goto free_mem;
|
||||
}
|
||||
trip_mask = BIT(trip_cnt) - 1;
|
||||
int34x_thermal_zone->aux_trip_nr = trip_cnt;
|
||||
}
|
||||
|
||||
int34x_thermal_zone->crt_trip_id = -1;
|
||||
if (!int340x_thermal_get_trip_config(adev->handle, "_CRT",
|
||||
&int34x_thermal_zone->crt_temp))
|
||||
int34x_thermal_zone->crt_trip_id = trip_cnt++;
|
||||
int34x_thermal_zone->hot_trip_id = -1;
|
||||
if (!int340x_thermal_get_trip_config(adev->handle, "_HOT",
|
||||
&int34x_thermal_zone->hot_temp))
|
||||
int34x_thermal_zone->hot_trip_id = trip_cnt++;
|
||||
int34x_thermal_zone->psv_trip_id = -1;
|
||||
if (!int340x_thermal_get_trip_config(adev->handle, "_PSV",
|
||||
&int34x_thermal_zone->psv_temp))
|
||||
int34x_thermal_zone->psv_trip_id = 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(adev->handle, name,
|
||||
&int34x_thermal_zone->act_trips[i].temp))
|
||||
break;
|
||||
|
||||
int34x_thermal_zone->act_trips[i].id = trip_cnt++;
|
||||
int34x_thermal_zone->act_trips[i].valid = true;
|
||||
}
|
||||
int34x_thermal_zone->lpat_table = acpi_lpat_get_conversion_table(
|
||||
adev->handle);
|
||||
|
||||
int34x_thermal_zone->zone = thermal_zone_device_register(
|
||||
acpi_device_bid(adev),
|
||||
trip_cnt,
|
||||
trip_mask, int34x_thermal_zone,
|
||||
&int340x_thermal_zone_ops,
|
||||
&int340x_thermal_params,
|
||||
0, 0);
|
||||
if (IS_ERR(int34x_thermal_zone->zone)) {
|
||||
ret = PTR_ERR(int34x_thermal_zone->zone);
|
||||
goto free_lpat;
|
||||
}
|
||||
|
||||
return int34x_thermal_zone;
|
||||
|
||||
free_lpat:
|
||||
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
|
||||
free_mem:
|
||||
kfree(int34x_thermal_zone);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(int340x_thermal_zone_add);
|
||||
|
||||
void int340x_thermal_zone_remove(struct int34x_thermal_zone
|
||||
*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);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove);
|
||||
|
||||
MODULE_AUTHOR("Aaron Lu <[email protected]>");
|
||||
MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
|
||||
MODULE_DESCRIPTION("Intel INT340x common thermal zone handler");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
68
drivers/thermal/int340x_thermal/int340x_thermal_zone.h
Normal file
68
drivers/thermal/int340x_thermal/int340x_thermal_zone.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* int340x_thermal_zone.h
|
||||
* Copyright (c) 2015, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INT340X_THERMAL_ZONE_H__
|
||||
#define __INT340X_THERMAL_ZONE_H__
|
||||
|
||||
#include <acpi/acpi_lpat.h>
|
||||
|
||||
#define INT340X_THERMAL_MAX_ACT_TRIP_COUNT 10
|
||||
|
||||
struct active_trip {
|
||||
unsigned long temp;
|
||||
int id;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct int34x_thermal_zone {
|
||||
struct acpi_device *adev;
|
||||
struct active_trip act_trips[INT340X_THERMAL_MAX_ACT_TRIP_COUNT];
|
||||
unsigned long *aux_trips;
|
||||
int aux_trip_nr;
|
||||
unsigned long psv_temp;
|
||||
int psv_trip_id;
|
||||
unsigned long crt_temp;
|
||||
int crt_trip_id;
|
||||
unsigned long hot_temp;
|
||||
int hot_trip_id;
|
||||
struct thermal_zone_device *zone;
|
||||
struct thermal_zone_device_ops *override_ops;
|
||||
void *priv_data;
|
||||
struct acpi_lpat_conversion_table *lpat_table;
|
||||
};
|
||||
|
||||
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *,
|
||||
struct thermal_zone_device_ops *override_ops);
|
||||
void int340x_thermal_zone_remove(struct int34x_thermal_zone *);
|
||||
|
||||
static inline void int340x_thermal_zone_set_priv_data(
|
||||
struct int34x_thermal_zone *tzone, void *priv_data)
|
||||
{
|
||||
tzone->priv_data = priv_data;
|
||||
}
|
||||
|
||||
static inline void *int340x_thermal_zone_get_priv_data(
|
||||
struct int34x_thermal_zone *tzone)
|
||||
{
|
||||
return tzone->priv_data;
|
||||
}
|
||||
|
||||
static inline void int340x_thermal_zone_device_update(
|
||||
struct int34x_thermal_zone *tzone)
|
||||
{
|
||||
thermal_zone_device_update(tzone->zone);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -18,6 +18,8 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/thermal.h>
|
||||
#include "int340x_thermal_zone.h"
|
||||
|
||||
/* Broadwell-U/HSB thermal reporting device */
|
||||
#define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603
|
||||
|
|
@ -39,6 +41,7 @@ struct proc_thermal_device {
|
|||
struct device *dev;
|
||||
struct acpi_device *adev;
|
||||
struct power_config power_limits[2];
|
||||
struct int34x_thermal_zone *int340x_zone;
|
||||
};
|
||||
|
||||
enum proc_thermal_emum_mode_type {
|
||||
|
|
@ -117,6 +120,72 @@ static struct attribute_group power_limit_attribute_group = {
|
|||
.name = "power_limits"
|
||||
};
|
||||
|
||||
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(unsigned long *temp)
|
||||
{
|
||||
int cpu;
|
||||
u32 eax, edx;
|
||||
int err;
|
||||
unsigned long curr_temp_off = 0;
|
||||
|
||||
*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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
|
||||
unsigned long *temp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = read_temp_msr(temp);
|
||||
if (!ret)
|
||||
*temp = (stored_tjmax - *temp) * 1000;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct thermal_zone_device_ops proc_thermal_local_ops = {
|
||||
.get_temp = proc_thermal_get_zone_temp,
|
||||
};
|
||||
|
||||
static int proc_thermal_add(struct device *dev,
|
||||
struct proc_thermal_device **priv)
|
||||
{
|
||||
|
|
@ -126,6 +195,8 @@ static int proc_thermal_add(struct device *dev,
|
|||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *elements, *ppcc;
|
||||
union acpi_object *p;
|
||||
unsigned long long tmp;
|
||||
struct thermal_zone_device_ops *ops = NULL;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
|
|
@ -178,6 +249,24 @@ static int proc_thermal_add(struct device *dev,
|
|||
|
||||
ret = sysfs_create_group(&dev->kobj,
|
||||
&power_limit_attribute_group);
|
||||
if (ret)
|
||||
goto free_buffer;
|
||||
|
||||
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)
|
||||
ops = &proc_thermal_local_ops;
|
||||
}
|
||||
|
||||
proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops);
|
||||
if (IS_ERR(proc_priv->int340x_zone)) {
|
||||
sysfs_remove_group(&proc_priv->dev->kobj,
|
||||
&power_limit_attribute_group);
|
||||
ret = PTR_ERR(proc_priv->int340x_zone);
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
free_buffer:
|
||||
kfree(buf.pointer);
|
||||
|
|
@ -185,8 +274,9 @@ free_buffer:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void proc_thermal_remove(struct proc_thermal_device *proc_priv)
|
||||
static void proc_thermal_remove(struct proc_thermal_device *proc_priv)
|
||||
{
|
||||
int340x_thermal_zone_remove(proc_priv->int340x_zone);
|
||||
sysfs_remove_group(&proc_priv->dev->kobj,
|
||||
&power_limit_attribute_group);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -309,10 +309,13 @@ static int soc_dts_enable(int id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct soc_sensor_entry *alloc_soc_dts(int id, u32 tj_max)
|
||||
static struct soc_sensor_entry *alloc_soc_dts(int id, u32 tj_max,
|
||||
bool notification_support)
|
||||
{
|
||||
struct soc_sensor_entry *aux_entry;
|
||||
char name[10];
|
||||
int trip_count = 0;
|
||||
int trip_mask = 0;
|
||||
int err;
|
||||
|
||||
aux_entry = kzalloc(sizeof(*aux_entry), GFP_KERNEL);
|
||||
|
|
@ -332,11 +335,16 @@ static struct soc_sensor_entry *alloc_soc_dts(int id, u32 tj_max)
|
|||
aux_entry->tj_max = tj_max;
|
||||
aux_entry->temp_mask = 0x00FF << (id * 8);
|
||||
aux_entry->temp_shift = id * 8;
|
||||
if (notification_support) {
|
||||
trip_count = SOC_MAX_DTS_TRIPS;
|
||||
trip_mask = 0x02;
|
||||
}
|
||||
snprintf(name, sizeof(name), "soc_dts%d", id);
|
||||
aux_entry->tzone = thermal_zone_device_register(name,
|
||||
SOC_MAX_DTS_TRIPS,
|
||||
0x02,
|
||||
aux_entry, &tzone_ops, NULL, 0, 0);
|
||||
trip_count,
|
||||
trip_mask,
|
||||
aux_entry, &tzone_ops,
|
||||
NULL, 0, 0);
|
||||
if (IS_ERR(aux_entry->tzone)) {
|
||||
err = PTR_ERR(aux_entry->tzone);
|
||||
goto err_ret;
|
||||
|
|
@ -402,6 +410,7 @@ static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data)
|
|||
|
||||
static const struct x86_cpu_id soc_thermal_ids[] = {
|
||||
{ X86_VENDOR_INTEL, X86_FAMILY_ANY, 0x37, 0, BYT_SOC_DTS_APIC_IRQ},
|
||||
{ X86_VENDOR_INTEL, X86_FAMILY_ANY, 0x4c, 0, 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, soc_thermal_ids);
|
||||
|
|
@ -420,8 +429,11 @@ static int __init intel_soc_thermal_init(void)
|
|||
if (get_tj_max(&tj_max))
|
||||
return -EINVAL;
|
||||
|
||||
soc_dts_thres_irq = (int)match_cpu->driver_data;
|
||||
|
||||
for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
|
||||
soc_dts[i] = alloc_soc_dts(i, tj_max);
|
||||
soc_dts[i] = alloc_soc_dts(i, tj_max,
|
||||
soc_dts_thres_irq ? true : false);
|
||||
if (IS_ERR(soc_dts[i])) {
|
||||
err = PTR_ERR(soc_dts[i]);
|
||||
goto err_free;
|
||||
|
|
@ -430,15 +442,15 @@ static int __init intel_soc_thermal_init(void)
|
|||
|
||||
spin_lock_init(&intr_notify_lock);
|
||||
|
||||
soc_dts_thres_irq = (int)match_cpu->driver_data;
|
||||
|
||||
err = request_threaded_irq(soc_dts_thres_irq, NULL,
|
||||
soc_irq_thread_fn,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"soc_dts", soc_dts);
|
||||
if (err) {
|
||||
pr_err("request_threaded_irq ret %d\n", err);
|
||||
goto err_free;
|
||||
if (soc_dts_thres_irq) {
|
||||
err = request_threaded_irq(soc_dts_thres_irq, NULL,
|
||||
soc_irq_thread_fn,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"soc_dts", soc_dts);
|
||||
if (err) {
|
||||
pr_err("request_threaded_irq ret %d\n", err);
|
||||
goto err_free;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
|
||||
|
|
@ -451,7 +463,8 @@ static int __init intel_soc_thermal_init(void)
|
|||
|
||||
err_trip_temp:
|
||||
i = SOC_MAX_DTS_SENSORS;
|
||||
free_irq(soc_dts_thres_irq, soc_dts);
|
||||
if (soc_dts_thres_irq)
|
||||
free_irq(soc_dts_thres_irq, soc_dts);
|
||||
err_free:
|
||||
while (--i >= 0)
|
||||
free_soc_dts(soc_dts[i]);
|
||||
|
|
@ -466,7 +479,8 @@ static void __exit intel_soc_thermal_exit(void)
|
|||
for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
|
||||
update_trip_temp(soc_dts[i], 0, 0);
|
||||
|
||||
free_irq(soc_dts_thres_irq, soc_dts);
|
||||
if (soc_dts_thres_irq)
|
||||
free_irq(soc_dts_thres_irq, soc_dts);
|
||||
|
||||
for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
|
||||
free_soc_dts(soc_dts[i]);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
* c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing
|
||||
* d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit,
|
||||
* if the cooling state already equals lower limit,
|
||||
* deactive the thermal instance
|
||||
* deactivate the thermal instance
|
||||
*/
|
||||
static unsigned long get_target_state(struct thermal_instance *instance,
|
||||
enum thermal_trend trend, bool throttle)
|
||||
|
|
@ -169,7 +169,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
|
|||
}
|
||||
|
||||
/**
|
||||
* step_wise_throttle - throttles devices asscciated with the given zone
|
||||
* step_wise_throttle - throttles devices associated with the given zone
|
||||
* @tz - thermal_zone_device
|
||||
* @trip - the trip point
|
||||
* @trip_type - type of the trip point
|
||||
|
|
|
|||
Loading…
Reference in a new issue