Commit a5c926ac authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge back Intel thermal control changes for 6.3.

parents acd7e9ee e90eb1df
...@@ -84,6 +84,9 @@ DPTF ACPI Drivers interface ...@@ -84,6 +84,9 @@ DPTF ACPI Drivers interface
https:/github.com/intel/thermal_daemon for decoding https:/github.com/intel/thermal_daemon for decoding
thermal table. thermal table.
``production_mode`` (RO)
When different from zero, manufacturer locked thermal configuration
from further changes.
ACPI Thermal Relationship table interface ACPI Thermal Relationship table interface
------------------------------------------ ------------------------------------------
......
...@@ -1079,8 +1079,6 @@ struct mbox_list { ...@@ -1079,8 +1079,6 @@ struct mbox_list {
#if IS_ENABLED(CONFIG_THERMAL) #if IS_ENABLED(CONFIG_THERMAL)
struct ch_thermal { struct ch_thermal {
struct thermal_zone_device *tzdev; struct thermal_zone_device *tzdev;
int trip_temp;
int trip_type;
}; };
#endif #endif
......
...@@ -29,36 +29,12 @@ static int cxgb4_thermal_get_temp(struct thermal_zone_device *tzdev, ...@@ -29,36 +29,12 @@ static int cxgb4_thermal_get_temp(struct thermal_zone_device *tzdev,
return 0; return 0;
} }
static int cxgb4_thermal_get_trip_type(struct thermal_zone_device *tzdev,
int trip, enum thermal_trip_type *type)
{
struct adapter *adap = tzdev->devdata;
if (!adap->ch_thermal.trip_temp)
return -EINVAL;
*type = adap->ch_thermal.trip_type;
return 0;
}
static int cxgb4_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
int trip, int *temp)
{
struct adapter *adap = tzdev->devdata;
if (!adap->ch_thermal.trip_temp)
return -EINVAL;
*temp = adap->ch_thermal.trip_temp;
return 0;
}
static struct thermal_zone_device_ops cxgb4_thermal_ops = { static struct thermal_zone_device_ops cxgb4_thermal_ops = {
.get_temp = cxgb4_thermal_get_temp, .get_temp = cxgb4_thermal_get_temp,
.get_trip_type = cxgb4_thermal_get_trip_type,
.get_trip_temp = cxgb4_thermal_get_trip_temp,
}; };
static struct thermal_trip trip = { .type = THERMAL_TRIP_CRITICAL } ;
int cxgb4_thermal_init(struct adapter *adap) int cxgb4_thermal_init(struct adapter *adap)
{ {
struct ch_thermal *ch_thermal = &adap->ch_thermal; struct ch_thermal *ch_thermal = &adap->ch_thermal;
...@@ -79,15 +55,14 @@ int cxgb4_thermal_init(struct adapter *adap) ...@@ -79,15 +55,14 @@ int cxgb4_thermal_init(struct adapter *adap)
if (ret < 0) { if (ret < 0) {
num_trip = 0; /* could not get trip temperature */ num_trip = 0; /* could not get trip temperature */
} else { } else {
ch_thermal->trip_temp = val * 1000; trip.temperature = val * 1000;
ch_thermal->trip_type = THERMAL_TRIP_CRITICAL;
} }
snprintf(ch_tz_name, sizeof(ch_tz_name), "cxgb4_%s", adap->name); snprintf(ch_tz_name, sizeof(ch_tz_name), "cxgb4_%s", adap->name);
ch_thermal->tzdev = thermal_zone_device_register(ch_tz_name, num_trip, ch_thermal->tzdev = thermal_zone_device_register_with_trips(ch_tz_name, &trip, num_trip,
0, adap, 0, adap,
&cxgb4_thermal_ops, &cxgb4_thermal_ops,
NULL, 0, 0); NULL, 0, 0);
if (IS_ERR(ch_thermal->tzdev)) { if (IS_ERR(ch_thermal->tzdev)) {
ret = PTR_ERR(ch_thermal->tzdev); ret = PTR_ERR(ch_thermal->tzdev);
dev_err(adap->pdev_dev, "Failed to register thermal zone\n"); dev_err(adap->pdev_dev, "Failed to register thermal zone\n");
......
...@@ -501,7 +501,7 @@ struct iwl_mvm_tt_mgmt { ...@@ -501,7 +501,7 @@ struct iwl_mvm_tt_mgmt {
* @tzone: thermal zone device data * @tzone: thermal zone device data
*/ */
struct iwl_mvm_thermal_device { struct iwl_mvm_thermal_device {
s16 temp_trips[IWL_MAX_DTS_TRIPS]; struct thermal_trip trips[IWL_MAX_DTS_TRIPS];
u8 fw_trips_index[IWL_MAX_DTS_TRIPS]; u8 fw_trips_index[IWL_MAX_DTS_TRIPS];
struct thermal_zone_device *tzone; struct thermal_zone_device *tzone;
}; };
......
...@@ -573,11 +573,11 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm) ...@@ -573,11 +573,11 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
* and uncompressed, the FW should get it compressed and sorted * and uncompressed, the FW should get it compressed and sorted
*/ */
/* compress temp_trips to cmd array, remove uninitialized values*/ /* compress trips to cmd array, remove uninitialized values*/
for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) { for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
if (mvm->tz_device.temp_trips[i] != S16_MIN) { if (mvm->tz_device.trips[i].temperature != INT_MIN) {
cmd.thresholds[idx++] = cmd.thresholds[idx++] =
cpu_to_le16(mvm->tz_device.temp_trips[i]); cpu_to_le16((s16)(mvm->tz_device.trips[i].temperature / 1000));
} }
} }
cmd.num_temps = cpu_to_le32(idx); cmd.num_temps = cpu_to_le32(idx);
...@@ -593,8 +593,8 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm) ...@@ -593,8 +593,8 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
*/ */
for (i = 0; i < idx; i++) { for (i = 0; i < idx; i++) {
for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) { for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) {
if (le16_to_cpu(cmd.thresholds[i]) == if ((int)(le16_to_cpu(cmd.thresholds[i]) * 1000) ==
mvm->tz_device.temp_trips[j]) mvm->tz_device.trips[j].temperature)
mvm->tz_device.fw_trips_index[i] = j; mvm->tz_device.fw_trips_index[i] = j;
} }
} }
...@@ -638,37 +638,12 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device, ...@@ -638,37 +638,12 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
return ret; return ret;
} }
static int iwl_mvm_tzone_get_trip_temp(struct thermal_zone_device *device,
int trip, int *temp)
{
struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS)
return -EINVAL;
*temp = mvm->tz_device.temp_trips[trip] * 1000;
return 0;
}
static int iwl_mvm_tzone_get_trip_type(struct thermal_zone_device *device,
int trip, enum thermal_trip_type *type)
{
if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS)
return -EINVAL;
*type = THERMAL_TRIP_PASSIVE;
return 0;
}
static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
int trip, int temp) int trip, int temp)
{ {
struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata; struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
struct iwl_mvm_thermal_device *tzone; struct iwl_mvm_thermal_device *tzone;
int i, ret; int ret;
s16 temperature;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
...@@ -678,40 +653,17 @@ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, ...@@ -678,40 +653,17 @@ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
goto out; goto out;
} }
if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) {
ret = -EINVAL;
goto out;
}
if ((temp / 1000) > S16_MAX) { if ((temp / 1000) > S16_MAX) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
temperature = (s16)(temp / 1000);
tzone = &mvm->tz_device; tzone = &mvm->tz_device;
if (!tzone) { if (!tzone) {
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
/* no updates*/
if (tzone->temp_trips[trip] == temperature) {
ret = 0;
goto out;
}
/* already existing temperature */
for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
if (tzone->temp_trips[i] == temperature) {
ret = -EINVAL;
goto out;
}
}
tzone->temp_trips[trip] = temperature;
ret = iwl_mvm_send_temp_report_ths_cmd(mvm); ret = iwl_mvm_send_temp_report_ths_cmd(mvm);
out: out:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
...@@ -720,8 +672,6 @@ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, ...@@ -720,8 +672,6 @@ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
static struct thermal_zone_device_ops tzone_ops = { static struct thermal_zone_device_ops tzone_ops = {
.get_temp = iwl_mvm_tzone_get_temp, .get_temp = iwl_mvm_tzone_get_temp,
.get_trip_temp = iwl_mvm_tzone_get_trip_temp,
.get_trip_type = iwl_mvm_tzone_get_trip_type,
.set_trip_temp = iwl_mvm_tzone_set_trip_temp, .set_trip_temp = iwl_mvm_tzone_set_trip_temp,
}; };
...@@ -743,7 +693,8 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) ...@@ -743,7 +693,8 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF); sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF);
mvm->tz_device.tzone = thermal_zone_device_register(name, mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name,
mvm->tz_device.trips,
IWL_MAX_DTS_TRIPS, IWL_MAX_DTS_TRIPS,
IWL_WRITABLE_TRIPS_MSK, IWL_WRITABLE_TRIPS_MSK,
mvm, &tzone_ops, mvm, &tzone_ops,
...@@ -766,8 +717,10 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) ...@@ -766,8 +717,10 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
/* 0 is a valid temperature, /* 0 is a valid temperature,
* so initialize the array with S16_MIN which invalid temperature * so initialize the array with S16_MIN which invalid temperature
*/ */
for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) {
mvm->tz_device.temp_trips[i] = S16_MIN; mvm->tz_device.trips[i].temperature = INT_MIN;
mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE;
}
} }
static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev, static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
* measured by the on-die thermal monitor are within 0 <= Tj <= 90. So, * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So,
* assume 89°C is critical temperature. * assume 89°C is critical temperature.
*/ */
#define ACERHDF_DEFAULT_TEMP_FANON 60000
#define ACERHDF_DEFAULT_TEMP_FANOFF 53000
#define ACERHDF_TEMP_CRIT 89000 #define ACERHDF_TEMP_CRIT 89000
#define ACERHDF_FAN_OFF 0 #define ACERHDF_FAN_OFF 0
#define ACERHDF_FAN_AUTO 1 #define ACERHDF_FAN_AUTO 1
...@@ -70,8 +72,8 @@ static int kernelmode; ...@@ -70,8 +72,8 @@ static int kernelmode;
#endif #endif
static unsigned int interval = 10; static unsigned int interval = 10;
static unsigned int fanon = 60000; static unsigned int fanon = ACERHDF_DEFAULT_TEMP_FANON;
static unsigned int fanoff = 53000; static unsigned int fanoff = ACERHDF_DEFAULT_TEMP_FANOFF;
static unsigned int verbose; static unsigned int verbose;
static unsigned int list_supported; static unsigned int list_supported;
static unsigned int fanstate = ACERHDF_FAN_AUTO; static unsigned int fanstate = ACERHDF_FAN_AUTO;
...@@ -137,6 +139,15 @@ struct ctrl_settings { ...@@ -137,6 +139,15 @@ struct ctrl_settings {
int mcmd_enable; int mcmd_enable;
}; };
static struct thermal_trip trips[] = {
[0] = { .temperature = ACERHDF_DEFAULT_TEMP_FANON,
.hysteresis = ACERHDF_DEFAULT_TEMP_FANON - ACERHDF_DEFAULT_TEMP_FANOFF,
.type = THERMAL_TRIP_ACTIVE },
[1] = { .temperature = ACERHDF_TEMP_CRIT,
.type = THERMAL_TRIP_CRITICAL }
};
static struct ctrl_settings ctrl_cfg __read_mostly; static struct ctrl_settings ctrl_cfg __read_mostly;
/* Register addresses and values for different BIOS versions */ /* Register addresses and values for different BIOS versions */
...@@ -326,6 +337,15 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal) ...@@ -326,6 +337,15 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal)
fanon = ACERHDF_MAX_FANON; fanon = ACERHDF_MAX_FANON;
} }
if (fanon < fanoff) {
pr_err("fanoff temperature (%d) is above fanon temperature (%d), clamping to %d\n",
fanoff, fanon, fanon);
fanoff = fanon;
};
trips[0].temperature = fanon;
trips[0].hysteresis = fanon - fanoff;
if (kernelmode && prev_interval != interval) { if (kernelmode && prev_interval != interval) {
if (interval > ACERHDF_MAX_INTERVAL) { if (interval > ACERHDF_MAX_INTERVAL) {
pr_err("interval too high, set to %d\n", pr_err("interval too high, set to %d\n",
...@@ -424,43 +444,6 @@ static int acerhdf_change_mode(struct thermal_zone_device *thermal, ...@@ -424,43 +444,6 @@ static int acerhdf_change_mode(struct thermal_zone_device *thermal,
return 0; return 0;
} }
static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip,
enum thermal_trip_type *type)
{
if (trip == 0)
*type = THERMAL_TRIP_ACTIVE;
else if (trip == 1)
*type = THERMAL_TRIP_CRITICAL;
else
return -EINVAL;
return 0;
}
static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
int *temp)
{
if (trip != 0)
return -EINVAL;
*temp = fanon - fanoff;
return 0;
}
static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
int *temp)
{
if (trip == 0)
*temp = fanon;
else if (trip == 1)
*temp = ACERHDF_TEMP_CRIT;
else
return -EINVAL;
return 0;
}
static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal, static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
int *temperature) int *temperature)
{ {
...@@ -474,13 +457,9 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = { ...@@ -474,13 +457,9 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = {
.unbind = acerhdf_unbind, .unbind = acerhdf_unbind,
.get_temp = acerhdf_get_ec_temp, .get_temp = acerhdf_get_ec_temp,
.change_mode = acerhdf_change_mode, .change_mode = acerhdf_change_mode,
.get_trip_type = acerhdf_get_trip_type,
.get_trip_hyst = acerhdf_get_trip_hyst,
.get_trip_temp = acerhdf_get_trip_temp,
.get_crit_temp = acerhdf_get_crit_temp, .get_crit_temp = acerhdf_get_crit_temp,
}; };
/* /*
* cooling device callback functions * cooling device callback functions
* get maximal fan cooling state * get maximal fan cooling state
...@@ -710,10 +689,10 @@ static int __init acerhdf_register_thermal(void) ...@@ -710,10 +689,10 @@ static int __init acerhdf_register_thermal(void)
if (IS_ERR(cl_dev)) if (IS_ERR(cl_dev))
return -EINVAL; return -EINVAL;
thz_dev = thermal_zone_device_register("acerhdf", 2, 0, NULL, thz_dev = thermal_zone_device_register_with_trips("acerhdf", trips, ARRAY_SIZE(trips),
&acerhdf_dev_ops, 0, NULL, &acerhdf_dev_ops,
&acerhdf_zone_params, 0, &acerhdf_zone_params, 0,
(kernelmode) ? interval*1000 : 0); (kernelmode) ? interval*1000 : 0);
if (IS_ERR(thz_dev)) if (IS_ERR(thz_dev))
return -EINVAL; return -EINVAL;
......
...@@ -76,6 +76,10 @@ config THERMAL_OF ...@@ -76,6 +76,10 @@ config THERMAL_OF
Say 'Y' here if you need to build thermal infrastructure Say 'Y' here if you need to build thermal infrastructure
based on device tree. based on device tree.
config THERMAL_ACPI
depends on ACPI
bool
config THERMAL_WRITABLE_TRIPS config THERMAL_WRITABLE_TRIPS
bool "Enable writable trip points" bool "Enable writable trip points"
help help
......
...@@ -13,6 +13,7 @@ thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o ...@@ -13,6 +13,7 @@ thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o
# interface to/from other layers providing sensors # interface to/from other layers providing sensors
thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o
thermal_sys-$(CONFIG_THERMAL_ACPI) += thermal_acpi.o
# governors # governors
thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += gov_fair_share.o thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += gov_fair_share.o
......
...@@ -761,8 +761,7 @@ static void armada_set_sane_name(struct platform_device *pdev, ...@@ -761,8 +761,7 @@ static void armada_set_sane_name(struct platform_device *pdev,
} }
/* Save the name locally */ /* Save the name locally */
strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1); strscpy(priv->zone_name, name, THERMAL_NAME_LENGTH);
priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0';
/* Then check there are no '-' or hwmon core will complain */ /* Then check there are no '-' or hwmon core will complain */
do { do {
...@@ -785,33 +784,34 @@ static int armada_configure_overheat_int(struct armada_thermal_priv *priv, ...@@ -785,33 +784,34 @@ static int armada_configure_overheat_int(struct armada_thermal_priv *priv,
int sensor_id) int sensor_id)
{ {
/* Retrieve the critical trip point to enable the overheat interrupt */ /* Retrieve the critical trip point to enable the overheat interrupt */
const struct thermal_trip *trips = of_thermal_get_trip_points(tz); struct thermal_trip trip;
int ret; int ret;
int i; int i;
if (!trips) for (i = 0; i < thermal_zone_get_num_trips(tz); i++) {
return -EINVAL;
for (i = 0; i < of_thermal_get_ntrips(tz); i++) ret = thermal_zone_get_trip(tz, i, &trip);
if (trips[i].type == THERMAL_TRIP_CRITICAL) if (ret)
break; return ret;
if (i == of_thermal_get_ntrips(tz)) if (trip.type != THERMAL_TRIP_CRITICAL)
return -EINVAL; continue;
ret = armada_select_channel(priv, sensor_id); ret = armada_select_channel(priv, sensor_id);
if (ret) if (ret)
return ret; return ret;
armada_set_overheat_thresholds(priv, armada_set_overheat_thresholds(priv, trip.temperature,
trips[i].temperature, trip.hysteresis);
trips[i].hysteresis); priv->overheat_sensor = tz;
priv->overheat_sensor = tz; priv->interrupt_source = sensor_id;
priv->interrupt_source = sensor_id;
armada_enable_overheat_interrupt(priv); armada_enable_overheat_interrupt(priv);
return 0; return 0;
}
return -EINVAL;
} }
static int armada_thermal_probe(struct platform_device *pdev) static int armada_thermal_probe(struct platform_device *pdev)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/thermal.h> #include <linux/thermal.h>
#include "../thermal_core.h"
#include "../thermal_hwmon.h" #include "../thermal_hwmon.h"
#define BCM2835_TS_TSENSCTL 0x00 #define BCM2835_TS_TSENSCTL 0x00
...@@ -224,7 +225,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) ...@@ -224,7 +225,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
*/ */
val = readl(data->regs + BCM2835_TS_TSENSCTL); val = readl(data->regs + BCM2835_TS_TSENSCTL);
if (!(val & BCM2835_TS_TSENSCTL_RSTB)) { if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
int trip_temp, offset, slope; struct thermal_trip trip;
int offset, slope;
slope = thermal_zone_get_slope(tz); slope = thermal_zone_get_slope(tz);
offset = thermal_zone_get_offset(tz); offset = thermal_zone_get_offset(tz);
...@@ -232,7 +234,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) ...@@ -232,7 +234,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
* For now we deal only with critical, otherwise * For now we deal only with critical, otherwise
* would need to iterate * would need to iterate
*/ */
err = tz->ops->get_trip_temp(tz, 0, &trip_temp); err = thermal_zone_get_trip(tz, 0, &trip);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Not able to read trip_temp: %d\n", "Not able to read trip_temp: %d\n",
...@@ -249,7 +251,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) ...@@ -249,7 +251,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT); val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
/* trip_adc value from info */ /* trip_adc value from info */
val |= bcm2835_thermal_temp2adc(trip_temp, val |= bcm2835_thermal_temp2adc(trip.temperature,
offset, offset,
slope) slope)
<< BCM2835_TS_TSENSCTL_THOLD_SHIFT; << BCM2835_TS_TSENSCTL_THOLD_SHIFT;
......
...@@ -120,44 +120,6 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) ...@@ -120,44 +120,6 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,
int trip,
enum thermal_trip_type *type)
{
struct da9062_thermal *thermal = z->devdata;
switch (trip) {
case 0:
*type = THERMAL_TRIP_HOT;
break;
default:
dev_err(thermal->dev,
"Driver does not support more than 1 trip-wire\n");
return -EINVAL;
}
return 0;
}
static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z,
int trip,
int *temp)
{
struct da9062_thermal *thermal = z->devdata;
switch (trip) {
case 0:
*temp = DA9062_MILLI_CELSIUS(125);
break;
default:
dev_err(thermal->dev,
"Driver does not support more than 1 trip-wire\n");
return -EINVAL;
}
return 0;
}
static int da9062_thermal_get_temp(struct thermal_zone_device *z, static int da9062_thermal_get_temp(struct thermal_zone_device *z,
int *temp) int *temp)
{ {
...@@ -172,8 +134,10 @@ static int da9062_thermal_get_temp(struct thermal_zone_device *z, ...@@ -172,8 +134,10 @@ static int da9062_thermal_get_temp(struct thermal_zone_device *z,
static struct thermal_zone_device_ops da9062_thermal_ops = { static struct thermal_zone_device_ops da9062_thermal_ops = {
.get_temp = da9062_thermal_get_temp, .get_temp = da9062_thermal_get_temp,
.get_trip_type = da9062_thermal_get_trip_type, };
.get_trip_temp = da9062_thermal_get_trip_temp,
static struct thermal_trip trips[] = {
{ .temperature = DA9062_MILLI_CELSIUS(125), .type = THERMAL_TRIP_HOT },
}; };
static const struct da9062_thermal_config da9062_config = { static const struct da9062_thermal_config da9062_config = {
...@@ -228,10 +192,10 @@ static int da9062_thermal_probe(struct platform_device *pdev) ...@@ -228,10 +192,10 @@ static int da9062_thermal_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on); INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
mutex_init(&thermal->lock); mutex_init(&thermal->lock);
thermal->zone = thermal_zone_device_register(thermal->config->name, thermal->zone = thermal_zone_device_register_with_trips(thermal->config->name,
1, 0, thermal, trips, ARRAY_SIZE(trips), 0, thermal,
&da9062_thermal_ops, NULL, pp_tmp, &da9062_thermal_ops, NULL, pp_tmp,
0); 0);
if (IS_ERR(thermal->zone)) { if (IS_ERR(thermal->zone)) {
dev_err(&pdev->dev, "Cannot register thermal zone device\n"); dev_err(&pdev->dev, "Cannot register thermal zone device\n");
ret = PTR_ERR(thermal->zone); ret = PTR_ERR(thermal->zone);
......
...@@ -13,26 +13,28 @@ ...@@ -13,26 +13,28 @@
#include "thermal_core.h" #include "thermal_core.h"
static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id)
{ {
int trip_temp, trip_hyst; struct thermal_trip trip;
struct thermal_instance *instance; struct thermal_instance *instance;
int ret;
tz->ops->get_trip_temp(tz, trip, &trip_temp); ret = __thermal_zone_get_trip(tz, trip_id, &trip);
if (ret) {
pr_warn_once("Failed to retrieve trip point %d\n", trip_id);
return ret;
}
if (!tz->ops->get_trip_hyst) { if (!trip.hysteresis)
pr_warn_once("Undefined get_trip_hyst for thermal zone %s - " dev_info_once(&tz->device,
"running with default hysteresis zero\n", tz->type); "Zero hysteresis value for thermal zone %s\n", tz->type);
trip_hyst = 0;
} else
tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
trip, trip_temp, tz->temperature, trip_id, trip.temperature, tz->temperature,
trip_hyst); trip.hysteresis);
list_for_each_entry(instance, &tz->thermal_instances, tz_node) { list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (instance->trip != trip) if (instance->trip != trip_id)
continue; continue;
/* in case fan is in initial state, switch the fan off */ /* in case fan is in initial state, switch the fan off */
...@@ -50,10 +52,10 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) ...@@ -50,10 +52,10 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
* enable fan when temperature exceeds trip_temp and disable * enable fan when temperature exceeds trip_temp and disable
* the fan in case it falls below trip_temp minus hysteresis * the fan in case it falls below trip_temp minus hysteresis
*/ */
if (instance->target == 0 && tz->temperature >= trip_temp) if (instance->target == 0 && tz->temperature >= trip.temperature)
instance->target = 1; instance->target = 1;
else if (instance->target == 1 && else if (instance->target == 1 &&
tz->temperature <= trip_temp - trip_hyst) tz->temperature <= trip.temperature - trip.hysteresis)
instance->target = 0; instance->target = 0;
dev_dbg(&instance->cdev->device, "target=%d\n", dev_dbg(&instance->cdev->device, "target=%d\n",
...@@ -63,6 +65,8 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) ...@@ -63,6 +65,8 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
instance->cdev->updated = false; /* cdev needs update */ instance->cdev->updated = false; /* cdev needs update */
mutex_unlock(&instance->cdev->lock); mutex_unlock(&instance->cdev->lock);
} }
return 0;
} }
/** /**
...@@ -95,10 +99,13 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) ...@@ -95,10 +99,13 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
static int bang_bang_control(struct thermal_zone_device *tz, int trip) static int bang_bang_control(struct thermal_zone_device *tz, int trip)
{ {
struct thermal_instance *instance; struct thermal_instance *instance;
int ret;
lockdep_assert_held(&tz->lock); lockdep_assert_held(&tz->lock);
thermal_zone_trip_update(tz, trip); ret = thermal_zone_trip_update(tz, trip);
if (ret)
return ret;
list_for_each_entry(instance, &tz->thermal_instances, tz_node) list_for_each_entry(instance, &tz->thermal_instances, tz_node)
thermal_cdev_update(instance->cdev); thermal_cdev_update(instance->cdev);
......
...@@ -21,16 +21,12 @@ ...@@ -21,16 +21,12 @@
*/ */
static int get_trip_level(struct thermal_zone_device *tz) static int get_trip_level(struct thermal_zone_device *tz)
{ {
int count = 0; struct thermal_trip trip;
int trip_temp; int count;
enum thermal_trip_type trip_type;
if (tz->num_trips == 0 || !tz->ops->get_trip_temp)
return 0;
for (count = 0; count < tz->num_trips; count++) { for (count = 0; count < tz->num_trips; count++) {
tz->ops->get_trip_temp(tz, count, &trip_temp); __thermal_zone_get_trip(tz, count, &trip);
if (tz->temperature < trip_temp) if (tz->temperature < trip.temperature)
break; break;
} }
...@@ -38,10 +34,8 @@ static int get_trip_level(struct thermal_zone_device *tz) ...@@ -38,10 +34,8 @@ static int get_trip_level(struct thermal_zone_device *tz)
* count > 0 only if temperature is greater than first trip * count > 0 only if temperature is greater than first trip
* point, in which case, trip_point = count - 1 * point, in which case, trip_point = count - 1
*/ */
if (count > 0) { if (count > 0)
tz->ops->get_trip_type(tz, count - 1, &trip_type); trace_thermal_zone_trip(tz, count - 1, trip.type);
trace_thermal_zone_trip(tz, count - 1, trip_type);
}
return count; return count;
} }
......
...@@ -124,16 +124,15 @@ static void estimate_pid_constants(struct thermal_zone_device *tz, ...@@ -124,16 +124,15 @@ static void estimate_pid_constants(struct thermal_zone_device *tz,
u32 sustainable_power, int trip_switch_on, u32 sustainable_power, int trip_switch_on,
int control_temp) int control_temp)
{ {
struct thermal_trip trip;
u32 temperature_threshold = control_temp;
int ret; int ret;
int switch_on_temp;
u32 temperature_threshold;
s32 k_i; s32 k_i;
ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp); ret = __thermal_zone_get_trip(tz, trip_switch_on, &trip);
if (ret) if (!ret)
switch_on_temp = 0; temperature_threshold -= trip.temperature;
temperature_threshold = control_temp - switch_on_temp;
/* /*
* estimate_pid_constants() tries to find appropriate default * estimate_pid_constants() tries to find appropriate default
* values for thermal zones that don't provide them. If a * values for thermal zones that don't provide them. If a
...@@ -519,10 +518,10 @@ static void get_governor_trips(struct thermal_zone_device *tz, ...@@ -519,10 +518,10 @@ static void get_governor_trips(struct thermal_zone_device *tz,
last_passive = INVALID_TRIP; last_passive = INVALID_TRIP;
for (i = 0; i < tz->num_trips; i++) { for (i = 0; i < tz->num_trips; i++) {
enum thermal_trip_type type; struct thermal_trip trip;
int ret; int ret;
ret = tz->ops->get_trip_type(tz, i, &type); ret = __thermal_zone_get_trip(tz, i, &trip);
if (ret) { if (ret) {
dev_warn(&tz->device, dev_warn(&tz->device,
"Failed to get trip point %d type: %d\n", i, "Failed to get trip point %d type: %d\n", i,
...@@ -530,14 +529,14 @@ static void get_governor_trips(struct thermal_zone_device *tz, ...@@ -530,14 +529,14 @@ static void get_governor_trips(struct thermal_zone_device *tz,
continue; continue;
} }
if (type == THERMAL_TRIP_PASSIVE) { if (trip.type == THERMAL_TRIP_PASSIVE) {
if (!found_first_passive) { if (!found_first_passive) {
params->trip_switch_on = i; params->trip_switch_on = i;
found_first_passive = true; found_first_passive = true;
} else { } else {
last_passive = i; last_passive = i;
} }
} else if (type == THERMAL_TRIP_ACTIVE) { } else if (trip.type == THERMAL_TRIP_ACTIVE) {
last_active = i; last_active = i;
} else { } else {
break; break;
...@@ -632,7 +631,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz) ...@@ -632,7 +631,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
{ {
int ret; int ret;
struct power_allocator_params *params; struct power_allocator_params *params;
int control_temp; struct thermal_trip trip;
ret = check_power_actors(tz); ret = check_power_actors(tz);
if (ret) if (ret)
...@@ -658,13 +657,12 @@ static int power_allocator_bind(struct thermal_zone_device *tz) ...@@ -658,13 +657,12 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
get_governor_trips(tz, params); get_governor_trips(tz, params);
if (tz->num_trips > 0) { if (tz->num_trips > 0) {
ret = tz->ops->get_trip_temp(tz, ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature,
params->trip_max_desired_temperature, &trip);
&control_temp);
if (!ret) if (!ret)
estimate_pid_constants(tz, tz->tzp->sustainable_power, estimate_pid_constants(tz, tz->tzp->sustainable_power,
params->trip_switch_on, params->trip_switch_on,
control_temp); trip.temperature);
} }
reset_pid_controller(params); reset_pid_controller(params);
...@@ -694,11 +692,11 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) ...@@ -694,11 +692,11 @@ static void power_allocator_unbind(struct thermal_zone_device *tz)
tz->governor_data = NULL; tz->governor_data = NULL;
} }
static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_id)
{ {
int ret;
int switch_on_temp, control_temp;
struct power_allocator_params *params = tz->governor_data; struct power_allocator_params *params = tz->governor_data;
struct thermal_trip trip;
int ret;
bool update; bool update;
lockdep_assert_held(&tz->lock); lockdep_assert_held(&tz->lock);
...@@ -707,13 +705,12 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) ...@@ -707,13 +705,12 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
* We get called for every trip point but we only need to do * We get called for every trip point but we only need to do
* our calculations once * our calculations once
*/ */
if (trip != params->trip_max_desired_temperature) if (trip_id != params->trip_max_desired_temperature)
return 0; return 0;
ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, ret = __thermal_zone_get_trip(tz, params->trip_switch_on, &trip);
&switch_on_temp); if (!ret && (tz->temperature < trip.temperature)) {
if (!ret && (tz->temperature < switch_on_temp)) { update = (tz->last_temperature >= trip.temperature);
update = (tz->last_temperature >= switch_on_temp);
tz->passive = 0; tz->passive = 0;
reset_pid_controller(params); reset_pid_controller(params);
allow_maximum_power(tz, update); allow_maximum_power(tz, update);
...@@ -722,16 +719,14 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) ...@@ -722,16 +719,14 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
tz->passive = 1; tz->passive = 1;
ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature, ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, &trip);
&control_temp);
if (ret) { if (ret) {
dev_warn(&tz->device, dev_warn(&tz->device, "Failed to get the maximum desired temperature: %d\n",
"Failed to get the maximum desired temperature: %d\n",
ret); ret);
return ret; return ret;
} }
return allocate_power(tz, control_temp); return allocate_power(tz, trip.temperature);
} }
static struct thermal_governor thermal_gov_power_allocator = { static struct thermal_governor thermal_gov_power_allocator = {
......
...@@ -95,30 +95,28 @@ static void update_passive_instance(struct thermal_zone_device *tz, ...@@ -95,30 +95,28 @@ static void update_passive_instance(struct thermal_zone_device *tz,
tz->passive += value; tz->passive += value;
} }
static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id)
{ {
int trip_temp;
enum thermal_trip_type trip_type;
enum thermal_trend trend; enum thermal_trend trend;
struct thermal_instance *instance; struct thermal_instance *instance;
struct thermal_trip trip;
bool throttle = false; bool throttle = false;
int old_target; int old_target;
tz->ops->get_trip_temp(tz, trip, &trip_temp); __thermal_zone_get_trip(tz, trip_id, &trip);
tz->ops->get_trip_type(tz, trip, &trip_type);
trend = get_tz_trend(tz, trip); trend = get_tz_trend(tz, trip_id);
if (tz->temperature >= trip_temp) { if (tz->temperature >= trip.temperature) {
throttle = true; throttle = true;
trace_thermal_zone_trip(tz, trip, trip_type); trace_thermal_zone_trip(tz, trip_id, trip.type);
} }
dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
trip, trip_type, trip_temp, trend, throttle); trip_id, trip.type, trip.temperature, trend, throttle);
list_for_each_entry(instance, &tz->thermal_instances, tz_node) { list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (instance->trip != trip) if (instance->trip != trip_id)
continue; continue;
old_target = instance->target; old_target = instance->target;
...@@ -132,11 +130,11 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) ...@@ -132,11 +130,11 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
/* Activate a passive thermal instance */ /* Activate a passive thermal instance */
if (old_target == THERMAL_NO_TARGET && if (old_target == THERMAL_NO_TARGET &&
instance->target != THERMAL_NO_TARGET) instance->target != THERMAL_NO_TARGET)
update_passive_instance(tz, trip_type, 1); update_passive_instance(tz, trip.type, 1);
/* Deactivate a passive thermal instance */ /* Deactivate a passive thermal instance */
else if (old_target != THERMAL_NO_TARGET && else if (old_target != THERMAL_NO_TARGET &&
instance->target == THERMAL_NO_TARGET) instance->target == THERMAL_NO_TARGET)
update_passive_instance(tz, trip_type, -1); update_passive_instance(tz, trip.type, -1);
instance->initialized = true; instance->initialized = true;
mutex_lock(&instance->cdev->lock); mutex_lock(&instance->cdev->lock);
......
...@@ -482,7 +482,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, ...@@ -482,7 +482,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
struct hisi_thermal_sensor *sensor) struct hisi_thermal_sensor *sensor)
{ {
int ret, i; int ret, i;
const struct thermal_trip *trip; struct thermal_trip trip;
sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, sensor->tzd = devm_thermal_of_zone_register(&pdev->dev,
sensor->id, sensor, sensor->id, sensor,
...@@ -495,11 +495,12 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, ...@@ -495,11 +495,12 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
return ret; return ret;
} }
trip = of_thermal_get_trip_points(sensor->tzd); for (i = 0; i < thermal_zone_get_num_trips(sensor->tzd); i++) {
for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { thermal_zone_get_trip(sensor->tzd, i, &trip);
if (trip[i].type == THERMAL_TRIP_PASSIVE) {
sensor->thres_temp = trip[i].temperature; if (trip.type == THERMAL_TRIP_PASSIVE) {
sensor->thres_temp = trip.temperature;
break; break;
} }
} }
......
...@@ -76,7 +76,6 @@ ...@@ -76,7 +76,6 @@
enum imx_thermal_trip { enum imx_thermal_trip {
IMX_TRIP_PASSIVE, IMX_TRIP_PASSIVE,
IMX_TRIP_CRITICAL, IMX_TRIP_CRITICAL,
IMX_TRIP_NUM,
}; };
#define IMX_POLLING_DELAY 2000 /* millisecond */ #define IMX_POLLING_DELAY 2000 /* millisecond */
...@@ -115,6 +114,11 @@ struct thermal_soc_data { ...@@ -115,6 +114,11 @@ struct thermal_soc_data {
u32 low_alarm_shift; u32 low_alarm_shift;
}; };
static struct thermal_trip trips[] = {
[IMX_TRIP_PASSIVE] = { .type = THERMAL_TRIP_PASSIVE },
[IMX_TRIP_CRITICAL] = { .type = THERMAL_TRIP_CRITICAL },
};
static struct thermal_soc_data thermal_imx6q_data = { static struct thermal_soc_data thermal_imx6q_data = {
.version = TEMPMON_IMX6Q, .version = TEMPMON_IMX6Q,
...@@ -201,8 +205,6 @@ struct imx_thermal_data { ...@@ -201,8 +205,6 @@ struct imx_thermal_data {
struct thermal_cooling_device *cdev; struct thermal_cooling_device *cdev;
struct regmap *tempmon; struct regmap *tempmon;
u32 c1, c2; /* See formula in imx_init_calib() */ u32 c1, c2; /* See formula in imx_init_calib() */
int temp_passive;
int temp_critical;
int temp_max; int temp_max;
int alarm_temp; int alarm_temp;
int last_temp; int last_temp;
...@@ -279,12 +281,12 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) ...@@ -279,12 +281,12 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
/* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
if (data->socdata->version == TEMPMON_IMX6Q) { if (data->socdata->version == TEMPMON_IMX6Q) {
if (data->alarm_temp == data->temp_passive && if (data->alarm_temp == trips[IMX_TRIP_PASSIVE].temperature &&
*temp >= data->temp_passive) *temp >= trips[IMX_TRIP_PASSIVE].temperature)
imx_set_alarm_temp(data, data->temp_critical); imx_set_alarm_temp(data, trips[IMX_TRIP_CRITICAL].temperature);
if (data->alarm_temp == data->temp_critical && if (data->alarm_temp == trips[IMX_TRIP_CRITICAL].temperature &&
*temp < data->temp_passive) { *temp < trips[IMX_TRIP_PASSIVE].temperature) {
imx_set_alarm_temp(data, data->temp_passive); imx_set_alarm_temp(data, trips[IMX_TRIP_PASSIVE].temperature);
dev_dbg(&tz->device, "thermal alarm off: T < %d\n", dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
data->alarm_temp / 1000); data->alarm_temp / 1000);
} }
...@@ -330,29 +332,10 @@ static int imx_change_mode(struct thermal_zone_device *tz, ...@@ -330,29 +332,10 @@ static int imx_change_mode(struct thermal_zone_device *tz,
return 0; return 0;
} }
static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
enum thermal_trip_type *type)
{
*type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE :
THERMAL_TRIP_CRITICAL;
return 0;
}
static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp) static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
{ {
struct imx_thermal_data *data = tz->devdata; *temp = trips[IMX_TRIP_CRITICAL].temperature;
*temp = data->temp_critical;
return 0;
}
static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
int *temp)
{
struct imx_thermal_data *data = tz->devdata;
*temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
data->temp_critical;
return 0; return 0;
} }
...@@ -371,10 +354,10 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip, ...@@ -371,10 +354,10 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
return -EPERM; return -EPERM;
/* do not allow passive to be set higher than critical */ /* do not allow passive to be set higher than critical */
if (temp < 0 || temp > data->temp_critical) if (temp < 0 || temp > trips[IMX_TRIP_CRITICAL].temperature)
return -EINVAL; return -EINVAL;
data->temp_passive = temp; trips[IMX_TRIP_PASSIVE].temperature = temp;
imx_set_alarm_temp(data, temp); imx_set_alarm_temp(data, temp);
...@@ -423,8 +406,6 @@ static struct thermal_zone_device_ops imx_tz_ops = { ...@@ -423,8 +406,6 @@ static struct thermal_zone_device_ops imx_tz_ops = {
.unbind = imx_unbind, .unbind = imx_unbind,
.get_temp = imx_get_temp, .get_temp = imx_get_temp,
.change_mode = imx_change_mode, .change_mode = imx_change_mode,
.get_trip_type = imx_get_trip_type,
.get_trip_temp = imx_get_trip_temp,
.get_crit_temp = imx_get_crit_temp, .get_crit_temp = imx_get_crit_temp,
.set_trip_temp = imx_set_trip_temp, .set_trip_temp = imx_set_trip_temp,
}; };
...@@ -507,8 +488,8 @@ static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0) ...@@ -507,8 +488,8 @@ static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0)
* Set the critical trip point at 5 °C under max * Set the critical trip point at 5 °C under max
* Set the passive trip point at 10 °C under max (changeable via sysfs) * Set the passive trip point at 10 °C under max (changeable via sysfs)
*/ */
data->temp_critical = data->temp_max - (1000 * 5); trips[IMX_TRIP_PASSIVE].temperature = data->temp_max - (1000 * 10);
data->temp_passive = data->temp_max - (1000 * 10); trips[IMX_TRIP_CRITICAL].temperature = data->temp_max - (1000 * 5);
} }
static int imx_init_from_tempmon_data(struct platform_device *pdev) static int imx_init_from_tempmon_data(struct platform_device *pdev)
...@@ -743,12 +724,13 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -743,12 +724,13 @@ static int imx_thermal_probe(struct platform_device *pdev)
goto legacy_cleanup; goto legacy_cleanup;
} }
data->tz = thermal_zone_device_register("imx_thermal_zone", data->tz = thermal_zone_device_register_with_trips("imx_thermal_zone",
IMX_TRIP_NUM, trips,
BIT(IMX_TRIP_PASSIVE), data, ARRAY_SIZE(trips),
&imx_tz_ops, NULL, BIT(IMX_TRIP_PASSIVE), data,
IMX_PASSIVE_DELAY, &imx_tz_ops, NULL,
IMX_POLLING_DELAY); IMX_PASSIVE_DELAY,
IMX_POLLING_DELAY);
if (IS_ERR(data->tz)) { if (IS_ERR(data->tz)) {
ret = PTR_ERR(data->tz); ret = PTR_ERR(data->tz);
dev_err(&pdev->dev, dev_err(&pdev->dev,
...@@ -758,8 +740,8 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -758,8 +740,8 @@ static int imx_thermal_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC" dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
" critical:%dC passive:%dC\n", data->temp_grade, " critical:%dC passive:%dC\n", data->temp_grade,
data->temp_max / 1000, data->temp_critical / 1000, data->temp_max / 1000, trips[IMX_TRIP_CRITICAL].temperature / 1000,
data->temp_passive / 1000); trips[IMX_TRIP_PASSIVE].temperature / 1000);
/* Enable measurements at ~ 10 Hz */ /* Enable measurements at ~ 10 Hz */
regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR, regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
...@@ -767,10 +749,10 @@ static int imx_thermal_probe(struct platform_device *pdev) ...@@ -767,10 +749,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET, regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
measure_freq << data->socdata->measure_freq_shift); measure_freq << data->socdata->measure_freq_shift);
imx_set_alarm_temp(data, data->temp_passive); imx_set_alarm_temp(data, trips[IMX_TRIP_PASSIVE].temperature);
if (data->socdata->version == TEMPMON_IMX6SX) if (data->socdata->version == TEMPMON_IMX6SX)
imx_set_panic_temp(data, data->temp_critical); imx_set_panic_temp(data, trips[IMX_TRIP_CRITICAL].temperature);
regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
data->socdata->power_down_mask); data->socdata->power_down_mask);
......
...@@ -12,11 +12,16 @@ config X86_THERMAL_VECTOR ...@@ -12,11 +12,16 @@ config X86_THERMAL_VECTOR
def_bool y def_bool y
depends on X86 && CPU_SUP_INTEL && X86_LOCAL_APIC depends on X86 && CPU_SUP_INTEL && X86_LOCAL_APIC
config INTEL_TCC
bool
depends on X86
config X86_PKG_TEMP_THERMAL config X86_PKG_TEMP_THERMAL
tristate "X86 package temperature thermal driver" tristate "X86 package temperature thermal driver"
depends on X86_THERMAL_VECTOR depends on X86_THERMAL_VECTOR
select THERMAL_GOV_USER_SPACE select THERMAL_GOV_USER_SPACE
select THERMAL_WRITABLE_TRIPS select THERMAL_WRITABLE_TRIPS
select INTEL_TCC
default m default m
help help
Enable this to register CPU digital sensor for package temperature as Enable this to register CPU digital sensor for package temperature as
...@@ -28,6 +33,7 @@ config INTEL_SOC_DTS_IOSF_CORE ...@@ -28,6 +33,7 @@ config INTEL_SOC_DTS_IOSF_CORE
tristate tristate
depends on X86 && PCI depends on X86 && PCI
select IOSF_MBI select IOSF_MBI
select INTEL_TCC
help help
This is becoming a common feature for Intel SoCs to expose the additional This is becoming a common feature for Intel SoCs to expose the additional
digital temperature sensors (DTSs) using side band interface (IOSF). This digital temperature sensors (DTSs) using side band interface (IOSF). This
...@@ -75,6 +81,7 @@ config INTEL_BXT_PMIC_THERMAL ...@@ -75,6 +81,7 @@ config INTEL_BXT_PMIC_THERMAL
config INTEL_PCH_THERMAL config INTEL_PCH_THERMAL
tristate "Intel PCH Thermal Reporting Driver" tristate "Intel PCH Thermal Reporting Driver"
depends on X86 && PCI depends on X86 && PCI
select THERMAL_ACPI if ACPI
help help
Enable this to support thermal reporting on certain intel PCHs. Enable this to support thermal reporting on certain intel PCHs.
Thermal reporting device will provide temperature reading, Thermal reporting device will provide temperature reading,
...@@ -83,6 +90,7 @@ config INTEL_PCH_THERMAL ...@@ -83,6 +90,7 @@ config INTEL_PCH_THERMAL
config INTEL_TCC_COOLING config INTEL_TCC_COOLING
tristate "Intel TCC offset cooling Driver" tristate "Intel TCC offset cooling Driver"
depends on X86 depends on X86
select INTEL_TCC
help help
Enable this to support system cooling by adjusting the effective TCC Enable this to support system cooling by adjusting the effective TCC
activation temperature via the TCC Offset register, which is widely activation temperature via the TCC Offset register, which is widely
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# #
# Makefile for various Intel thermal drivers. # Makefile for various Intel thermal drivers.
obj-$(CONFIG_INTEL_TCC) += intel_tcc.o
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
......
...@@ -10,6 +10,7 @@ config INT340X_THERMAL ...@@ -10,6 +10,7 @@ config INT340X_THERMAL
select ACPI_THERMAL_REL select ACPI_THERMAL_REL
select ACPI_FAN select ACPI_FAN
select INTEL_SOC_DTS_IOSF_CORE select INTEL_SOC_DTS_IOSF_CORE
select INTEL_TCC
select PROC_THERMAL_MMIO_RAPL if POWERCAP select PROC_THERMAL_MMIO_RAPL if POWERCAP
help help
Newer laptops and tablets that use ACPI may have thermal sensors and Newer laptops and tablets that use ACPI may have thermal sensors and
......
...@@ -60,6 +60,7 @@ struct int3400_thermal_priv { ...@@ -60,6 +60,7 @@ struct int3400_thermal_priv {
int odvp_count; int odvp_count;
int *odvp; int *odvp;
u32 os_uuid_mask; u32 os_uuid_mask;
int production_mode;
struct odvp_attr *odvp_attrs; struct odvp_attr *odvp_attrs;
}; };
...@@ -130,10 +131,7 @@ static ssize_t available_uuids_show(struct device *dev, ...@@ -130,10 +131,7 @@ static ssize_t available_uuids_show(struct device *dev,
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) { for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
if (priv->uuid_bitmap & (1 << i)) if (priv->uuid_bitmap & (1 << i))
length += scnprintf(&buf[length], length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
PAGE_SIZE - length,
"%s\n",
int3400_thermal_uuids[i]);
} }
return length; return length;
...@@ -151,10 +149,7 @@ static ssize_t current_uuid_show(struct device *dev, ...@@ -151,10 +149,7 @@ static ssize_t current_uuid_show(struct device *dev,
for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) { for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) {
if (priv->os_uuid_mask & BIT(i)) if (priv->os_uuid_mask & BIT(i))
length += scnprintf(&buf[length], length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
PAGE_SIZE - length,
"%s\n",
int3400_thermal_uuids[i]);
} }
if (length) if (length)
...@@ -315,6 +310,44 @@ static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv) ...@@ -315,6 +310,44 @@ static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
return result; return result;
} }
static ssize_t production_mode_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
return sysfs_emit(buf, "%d\n", priv->production_mode);
}
static DEVICE_ATTR_RO(production_mode);
static int production_mode_init(struct int3400_thermal_priv *priv)
{
unsigned long long mode;
acpi_status status;
int ret;
priv->production_mode = -1;
status = acpi_evaluate_integer(priv->adev->handle, "DCFG", NULL, &mode);
/* If the method is not present, this is not an error */
if (ACPI_FAILURE(status))
return 0;
ret = sysfs_create_file(&priv->pdev->dev.kobj, &dev_attr_production_mode.attr);
if (ret)
return ret;
priv->production_mode = mode;
return 0;
}
static void production_mode_exit(struct int3400_thermal_priv *priv)
{
if (priv->production_mode >= 0)
sysfs_remove_file(&priv->pdev->dev.kobj, &dev_attr_production_mode.attr);
}
static ssize_t odvp_show(struct device *dev, struct device_attribute *attr, static ssize_t odvp_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
...@@ -610,8 +643,15 @@ static int int3400_thermal_probe(struct platform_device *pdev) ...@@ -610,8 +643,15 @@ static int int3400_thermal_probe(struct platform_device *pdev)
if (result) if (result)
goto free_sysfs; goto free_sysfs;
result = production_mode_init(priv);
if (result)
goto free_notify;
return 0; return 0;
free_notify:
acpi_remove_notify_handler(priv->adev->handle, ACPI_DEVICE_NOTIFY,
int3400_notify);
free_sysfs: free_sysfs:
cleanup_odvp(priv); cleanup_odvp(priv);
if (!ZERO_OR_NULL_PTR(priv->data_vault)) { if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
...@@ -638,6 +678,8 @@ static int int3400_thermal_remove(struct platform_device *pdev) ...@@ -638,6 +678,8 @@ static int int3400_thermal_remove(struct platform_device *pdev)
{ {
struct int3400_thermal_priv *priv = platform_get_drvdata(pdev); struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
production_mode_exit(priv);
acpi_remove_notify_handler( acpi_remove_notify_handler(
priv->adev->handle, ACPI_DEVICE_NOTIFY, priv->adev->handle, ACPI_DEVICE_NOTIFY,
int3400_notify); int3400_notify);
......
...@@ -18,9 +18,6 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone, ...@@ -18,9 +18,6 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
unsigned long long tmp; unsigned long long tmp;
acpi_status status; 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); status = acpi_evaluate_integer(d->adev->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -EIO; return -EIO;
...@@ -46,9 +43,6 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone, ...@@ -46,9 +43,6 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
struct int34x_thermal_zone *d = zone->devdata; struct int34x_thermal_zone *d = zone->devdata;
int i, ret = 0; int i, ret = 0;
if (d->override_ops && d->override_ops->get_trip_temp)
return d->override_ops->get_trip_temp(zone, trip, temp);
mutex_lock(&d->trip_mutex); mutex_lock(&d->trip_mutex);
if (trip < d->aux_trip_nr) if (trip < d->aux_trip_nr)
...@@ -83,9 +77,6 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone, ...@@ -83,9 +77,6 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
struct int34x_thermal_zone *d = zone->devdata; struct int34x_thermal_zone *d = zone->devdata;
int i, ret = 0; int i, ret = 0;
if (d->override_ops && d->override_ops->get_trip_type)
return d->override_ops->get_trip_type(zone, trip, type);
mutex_lock(&d->trip_mutex); mutex_lock(&d->trip_mutex);
if (trip < d->aux_trip_nr) if (trip < d->aux_trip_nr)
...@@ -120,9 +111,6 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone, ...@@ -120,9 +111,6 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
acpi_status status; acpi_status status;
char name[10]; 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); snprintf(name, sizeof(name), "PAT%d", trip);
status = acpi_execute_simple_method(d->adev->handle, name, status = acpi_execute_simple_method(d->adev->handle, name,
millicelsius_to_deci_kelvin(temp)); millicelsius_to_deci_kelvin(temp));
...@@ -142,9 +130,6 @@ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone, ...@@ -142,9 +130,6 @@ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
acpi_status status; acpi_status status;
unsigned long long hyst; 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); status = acpi_evaluate_integer(d->adev->handle, "GTSH", NULL, &hyst);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
*temp = 0; *temp = 0;
...@@ -229,7 +214,7 @@ static struct thermal_zone_params int340x_thermal_params = { ...@@ -229,7 +214,7 @@ static struct thermal_zone_params int340x_thermal_params = {
}; };
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
struct thermal_zone_device_ops *override_ops) int (*get_temp) (struct thermal_zone_device *, int *))
{ {
struct int34x_thermal_zone *int34x_thermal_zone; struct int34x_thermal_zone *int34x_thermal_zone;
acpi_status status; acpi_status status;
...@@ -245,7 +230,16 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, ...@@ -245,7 +230,16 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
mutex_init(&int34x_thermal_zone->trip_mutex); mutex_init(&int34x_thermal_zone->trip_mutex);
int34x_thermal_zone->adev = adev; int34x_thermal_zone->adev = adev;
int34x_thermal_zone->override_ops = override_ops;
int34x_thermal_zone->ops = kmemdup(&int340x_thermal_zone_ops,
sizeof(int340x_thermal_zone_ops), GFP_KERNEL);
if (!int34x_thermal_zone->ops) {
ret = -ENOMEM;
goto err_ops_alloc;
}
if (get_temp)
int34x_thermal_zone->ops->get_temp = get_temp;
status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt); status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
...@@ -276,7 +270,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, ...@@ -276,7 +270,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
acpi_device_bid(adev), acpi_device_bid(adev),
trip_cnt, trip_cnt,
trip_mask, int34x_thermal_zone, trip_mask, int34x_thermal_zone,
&int340x_thermal_zone_ops, int34x_thermal_zone->ops,
&int340x_thermal_params, &int340x_thermal_params,
0, 0); 0, 0);
if (IS_ERR(int34x_thermal_zone->zone)) { if (IS_ERR(int34x_thermal_zone->zone)) {
...@@ -295,6 +289,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, ...@@ -295,6 +289,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
kfree(int34x_thermal_zone->aux_trips); kfree(int34x_thermal_zone->aux_trips);
err_trip_alloc: err_trip_alloc:
kfree(int34x_thermal_zone->ops);
err_ops_alloc:
mutex_destroy(&int34x_thermal_zone->trip_mutex); mutex_destroy(&int34x_thermal_zone->trip_mutex);
kfree(int34x_thermal_zone); kfree(int34x_thermal_zone);
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -307,6 +303,7 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone ...@@ -307,6 +303,7 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone
thermal_zone_device_unregister(int34x_thermal_zone->zone); thermal_zone_device_unregister(int34x_thermal_zone->zone);
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
kfree(int34x_thermal_zone->aux_trips); kfree(int34x_thermal_zone->aux_trips);
kfree(int34x_thermal_zone->ops);
mutex_destroy(&int34x_thermal_zone->trip_mutex); mutex_destroy(&int34x_thermal_zone->trip_mutex);
kfree(int34x_thermal_zone); kfree(int34x_thermal_zone);
} }
......
...@@ -29,14 +29,14 @@ struct int34x_thermal_zone { ...@@ -29,14 +29,14 @@ struct int34x_thermal_zone {
int hot_temp; int hot_temp;
int hot_trip_id; int hot_trip_id;
struct thermal_zone_device *zone; struct thermal_zone_device *zone;
struct thermal_zone_device_ops *override_ops; struct thermal_zone_device_ops *ops;
void *priv_data; void *priv_data;
struct acpi_lpat_conversion_table *lpat_table; struct acpi_lpat_conversion_table *lpat_table;
struct mutex trip_mutex; struct mutex trip_mutex;
}; };
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *, struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *,
struct thermal_zone_device_ops *override_ops); int (*get_temp) (struct thermal_zone_device *, int *));
void int340x_thermal_zone_remove(struct int34x_thermal_zone *); void int340x_thermal_zone_remove(struct int34x_thermal_zone *);
int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone); int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright (c) 2014, Intel Corporation. * Copyright (c) 2014, Intel Corporation.
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/intel_tcc.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -68,54 +69,17 @@ static const struct attribute_group power_limit_attribute_group = { ...@@ -68,54 +69,17 @@ static const struct attribute_group power_limit_attribute_group = {
.name = "power_limits" .name = "power_limits"
}; };
static int tcc_get_offset(void)
{
u64 val;
int err;
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
if (err)
return err;
return (val >> 24) & 0x3f;
}
static ssize_t tcc_offset_degree_celsius_show(struct device *dev, static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
int tcc; int offset;
tcc = tcc_get_offset();
if (tcc < 0)
return tcc;
return sprintf(buf, "%d\n", tcc);
}
static int tcc_offset_update(unsigned int tcc)
{
u64 val;
int err;
if (tcc > 63) offset = intel_tcc_get_offset(-1);
return -EINVAL; if (offset < 0)
return offset;
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
if (err)
return err;
if (val & BIT(31)) return sprintf(buf, "%d\n", offset);
return -EPERM;
val &= ~GENMASK_ULL(29, 24);
val |= (tcc & 0x3f) << 24;
err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
if (err)
return err;
return 0;
} }
static ssize_t tcc_offset_degree_celsius_store(struct device *dev, static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
...@@ -136,7 +100,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev, ...@@ -136,7 +100,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
if (kstrtouint(buf, 0, &tcc)) if (kstrtouint(buf, 0, &tcc))
return -EINVAL; return -EINVAL;
err = tcc_offset_update(tcc); err = intel_tcc_set_offset(-1, tcc);
if (err) if (err)
return err; return err;
...@@ -145,72 +109,27 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev, ...@@ -145,72 +109,27 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
static DEVICE_ATTR_RW(tcc_offset_degree_celsius); static DEVICE_ATTR_RW(tcc_offset_degree_celsius);
static int stored_tjmax; /* since it is fixed, we can have local storage */ static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
int *temp)
static int get_tjmax(void)
{
u32 eax, edx;
u32 val;
int err;
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err)
return err;
val = (eax >> 16) & 0xff;
if (val)
return val;
return -EINVAL;
}
static int read_temp_msr(int *temp)
{ {
int cpu; int cpu;
u32 eax, edx; int curr_temp;
int err;
unsigned long curr_temp_off = 0;
*temp = 0; *temp = 0;
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_THERM_STATUS, &eax, curr_temp = intel_tcc_get_temp(cpu, false);
&edx); if (curr_temp < 0)
if (err) return curr_temp;
goto err_ret; if (!*temp || curr_temp > *temp)
else { *temp = curr_temp;
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; *temp *= 1000;
err_ret:
return err;
}
static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone, return 0;
int *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_read_ppcc(struct proc_thermal_device *proc_priv) static int proc_thermal_read_ppcc(struct proc_thermal_device *proc_priv)
{ {
int i; int i;
...@@ -285,7 +204,7 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv) ...@@ -285,7 +204,7 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
struct acpi_device *adev; struct acpi_device *adev;
acpi_status status; acpi_status status;
unsigned long long tmp; unsigned long long tmp;
struct thermal_zone_device_ops *ops = NULL; int (*get_temp) (struct thermal_zone_device *, int *) = NULL;
int ret; int ret;
adev = ACPI_COMPANION(dev); adev = ACPI_COMPANION(dev);
...@@ -302,12 +221,11 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv) ...@@ -302,12 +221,11 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp); status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
/* there is no _TMP method, add local method */ /* there is no _TMP method, add local method */
stored_tjmax = get_tjmax(); if (intel_tcc_get_tjmax(-1) > 0)
if (stored_tjmax > 0) get_temp = proc_thermal_get_zone_temp;
ops = &proc_thermal_local_ops;
} }
proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops); proc_priv->int340x_zone = int340x_thermal_zone_add(adev, get_temp);
if (IS_ERR(proc_priv->int340x_zone)) { if (IS_ERR(proc_priv->int340x_zone)) {
return PTR_ERR(proc_priv->int340x_zone); return PTR_ERR(proc_priv->int340x_zone);
} else } else
...@@ -356,7 +274,7 @@ static int tcc_offset_save = -1; ...@@ -356,7 +274,7 @@ static int tcc_offset_save = -1;
int proc_thermal_suspend(struct device *dev) int proc_thermal_suspend(struct device *dev)
{ {
tcc_offset_save = tcc_get_offset(); tcc_offset_save = intel_tcc_get_offset(-1);
if (tcc_offset_save < 0) if (tcc_offset_save < 0)
dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save); dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save);
...@@ -373,7 +291,7 @@ int proc_thermal_resume(struct device *dev) ...@@ -373,7 +291,7 @@ int proc_thermal_resume(struct device *dev)
/* Do not update if saving failed */ /* Do not update if saving failed */
if (tcc_offset_save >= 0) if (tcc_offset_save >= 0)
tcc_offset_update(tcc_offset_save); intel_tcc_set_offset(-1, tcc_offset_save);
return 0; return 0;
} }
...@@ -460,6 +378,7 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * ...@@ -460,6 +378,7 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
} }
EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);
MODULE_IMPORT_NS(INTEL_TCC);
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -144,34 +144,6 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) ...@@ -144,34 +144,6 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
return 0; return 0;
} }
static int sys_get_trip_temp(struct thermal_zone_device *tzd,
int trip, int *temp)
{
struct proc_thermal_pci *pci_info = tzd->devdata;
u32 _temp;
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &_temp);
if (!_temp) {
*temp = THERMAL_TEMP_INVALID;
} else {
int tjmax;
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
_temp = tjmax - _temp;
*temp = (unsigned long)_temp * 1000;
}
return 0;
}
static int sys_get_trip_type(struct thermal_zone_device *tzd, int trip,
enum thermal_trip_type *type)
{
*type = THERMAL_TRIP_PASSIVE;
return 0;
}
static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
{ {
struct proc_thermal_pci *pci_info = tzd->devdata; struct proc_thermal_pci *pci_info = tzd->devdata;
...@@ -200,10 +172,26 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp ...@@ -200,10 +172,26 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp
return 0; return 0;
} }
static int get_trip_temp(struct proc_thermal_pci *pci_info)
{
int temp, tjmax;
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp);
if (!temp)
return THERMAL_TEMP_INVALID;
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
temp = (tjmax - temp) * 1000;
return temp;
}
static struct thermal_trip psv_trip = {
.type = THERMAL_TRIP_PASSIVE,
};
static struct thermal_zone_device_ops tzone_ops = { static struct thermal_zone_device_ops tzone_ops = {
.get_temp = sys_get_curr_temp, .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, .set_trip_temp = sys_set_trip_temp,
}; };
...@@ -251,7 +239,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ ...@@ -251,7 +239,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
if (ret) if (ret)
goto err_ret_thermal; goto err_ret_thermal;
pci_info->tzone = thermal_zone_device_register("TCPU_PCI", 1, 1, pci_info, psv_trip.temperature = get_trip_temp(pci_info);
pci_info->tzone = thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip,
1, 1, pci_info,
&tzone_ops, &tzone_ops,
&tzone_params, 0, 0); &tzone_params, 0, 0);
if (IS_ERR(pci_info->tzone)) { if (IS_ERR(pci_info->tzone)) {
......
...@@ -232,9 +232,9 @@ static DEFINE_MUTEX(intel_menlow_attr_lock); ...@@ -232,9 +232,9 @@ static DEFINE_MUTEX(intel_menlow_attr_lock);
/* /*
* sensor_get_auxtrip - get the current auxtrip value from sensor * sensor_get_auxtrip - get the current auxtrip value from sensor
* @name: Thermalzone name * @handle: Object handle
* @auxtype : AUX0/AUX1 * @index : GET_AUX1/GET_AUX0
* @buf: syfs buffer * @value : The address will be fill by the value
*/ */
static int sensor_get_auxtrip(acpi_handle handle, int index, static int sensor_get_auxtrip(acpi_handle handle, int index,
unsigned long long *value) unsigned long long *value)
...@@ -254,9 +254,9 @@ static int sensor_get_auxtrip(acpi_handle handle, int index, ...@@ -254,9 +254,9 @@ static int sensor_get_auxtrip(acpi_handle handle, int index,
/* /*
* sensor_set_auxtrip - set the new auxtrip value to sensor * sensor_set_auxtrip - set the new auxtrip value to sensor
* @name: Thermalzone name * @handle: Object handle
* @auxtype : AUX0/AUX1 * @index : GET_AUX1/GET_AUX0
* @buf: syfs buffer * @value : The value will be set
*/ */
static int sensor_set_auxtrip(acpi_handle handle, int index, int value) static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
{ {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */ #define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */
#define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */ #define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */
#define PCH_THERMAL_DID_LWB 0xA1B1 /* Lewisburg PCH */ #define PCH_THERMAL_DID_LWB 0xA1B1 /* Lewisburg PCH */
#define PCH_THERMAL_DID_WBG 0x8D24 /* Wellsburg PCH */
/* Wildcat Point-LP PCH Thermal registers */ /* Wildcat Point-LP PCH Thermal registers */
#define WPT_TEMP 0x0000 /* Temperature */ #define WPT_TEMP 0x0000 /* Temperature */
...@@ -65,6 +66,8 @@ ...@@ -65,6 +66,8 @@
#define WPT_TEMP_OFFSET (PCH_TEMP_OFFSET * MILLIDEGREE_PER_DEGREE) #define WPT_TEMP_OFFSET (PCH_TEMP_OFFSET * MILLIDEGREE_PER_DEGREE)
#define GET_PCH_TEMP(x) (((x) / 2) + PCH_TEMP_OFFSET) #define GET_PCH_TEMP(x) (((x) / 2) + PCH_TEMP_OFFSET)
#define PCH_MAX_TRIPS 3 /* critical, hot, passive */
/* Amount of time for each cooling delay, 100ms by default for now */ /* Amount of time for each cooling delay, 100ms by default for now */
static unsigned int delay_timeout = 100; static unsigned int delay_timeout = 100;
module_param(delay_timeout, int, 0644); module_param(delay_timeout, int, 0644);
...@@ -82,12 +85,7 @@ struct pch_thermal_device { ...@@ -82,12 +85,7 @@ struct pch_thermal_device {
const struct pch_dev_ops *ops; const struct pch_dev_ops *ops;
struct pci_dev *pdev; struct pci_dev *pdev;
struct thermal_zone_device *tzd; struct thermal_zone_device *tzd;
int crt_trip_id; struct thermal_trip trips[PCH_MAX_TRIPS];
unsigned long crt_temp;
int hot_trip_id;
unsigned long hot_temp;
int psv_trip_id;
unsigned long psv_temp;
bool bios_enabled; bool bios_enabled;
}; };
...@@ -102,33 +100,22 @@ static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, ...@@ -102,33 +100,22 @@ static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
int *nr_trips) int *nr_trips)
{ {
struct acpi_device *adev; struct acpi_device *adev;
int ret;
ptd->psv_trip_id = -1;
adev = ACPI_COMPANION(&ptd->pdev->dev); adev = ACPI_COMPANION(&ptd->pdev->dev);
if (adev) { if (!adev)
unsigned long long r; return;
acpi_status status;
ret = thermal_acpi_trip_passive(adev, &ptd->trips[*nr_trips]);
status = acpi_evaluate_integer(adev->handle, "_PSV", NULL, if (ret)
&r); return;
if (ACPI_SUCCESS(status)) {
unsigned long trip_temp; ++(*nr_trips);
trip_temp = deci_kelvin_to_millicelsius(r);
if (trip_temp) {
ptd->psv_temp = trip_temp;
ptd->psv_trip_id = *nr_trips;
++(*nr_trips);
}
}
}
} }
#else #else
static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
int *nr_trips) int *nr_trips)
{ {
ptd->psv_trip_id = -1;
} }
#endif #endif
...@@ -163,21 +150,19 @@ static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips) ...@@ -163,21 +150,19 @@ static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips)
} }
read_trips: read_trips:
ptd->crt_trip_id = -1;
trip_temp = readw(ptd->hw_base + WPT_CTT); trip_temp = readw(ptd->hw_base + WPT_CTT);
trip_temp &= 0x1FF; trip_temp &= 0x1FF;
if (trip_temp) { if (trip_temp) {
ptd->crt_temp = GET_WPT_TEMP(trip_temp); ptd->trips[*nr_trips].temperature = GET_WPT_TEMP(trip_temp);
ptd->crt_trip_id = 0; ptd->trips[*nr_trips].type = THERMAL_TRIP_CRITICAL;
++(*nr_trips); ++(*nr_trips);
} }
ptd->hot_trip_id = -1;
trip_temp = readw(ptd->hw_base + WPT_PHL); trip_temp = readw(ptd->hw_base + WPT_PHL);
trip_temp &= 0x1FF; trip_temp &= 0x1FF;
if (trip_temp) { if (trip_temp) {
ptd->hot_temp = GET_WPT_TEMP(trip_temp); ptd->trips[*nr_trips].temperature = GET_WPT_TEMP(trip_temp);
ptd->hot_trip_id = *nr_trips; ptd->trips[*nr_trips].type = THERMAL_TRIP_HOT;
++(*nr_trips); ++(*nr_trips);
} }
...@@ -298,39 +283,6 @@ static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp) ...@@ -298,39 +283,6 @@ static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp)
return ptd->ops->get_temp(ptd, temp); return ptd->ops->get_temp(ptd, temp);
} }
static int pch_get_trip_type(struct thermal_zone_device *tzd, int trip,
enum thermal_trip_type *type)
{
struct pch_thermal_device *ptd = tzd->devdata;
if (ptd->crt_trip_id == trip)
*type = THERMAL_TRIP_CRITICAL;
else if (ptd->hot_trip_id == trip)
*type = THERMAL_TRIP_HOT;
else if (ptd->psv_trip_id == trip)
*type = THERMAL_TRIP_PASSIVE;
else
return -EINVAL;
return 0;
}
static int pch_get_trip_temp(struct thermal_zone_device *tzd, int trip, int *temp)
{
struct pch_thermal_device *ptd = tzd->devdata;
if (ptd->crt_trip_id == trip)
*temp = ptd->crt_temp;
else if (ptd->hot_trip_id == trip)
*temp = ptd->hot_temp;
else if (ptd->psv_trip_id == trip)
*temp = ptd->psv_temp;
else
return -EINVAL;
return 0;
}
static void pch_critical(struct thermal_zone_device *tzd) static void pch_critical(struct thermal_zone_device *tzd)
{ {
dev_dbg(&tzd->device, "%s: critical temperature reached\n", tzd->type); dev_dbg(&tzd->device, "%s: critical temperature reached\n", tzd->type);
...@@ -338,8 +290,6 @@ static void pch_critical(struct thermal_zone_device *tzd) ...@@ -338,8 +290,6 @@ static void pch_critical(struct thermal_zone_device *tzd)
static struct thermal_zone_device_ops tzd_ops = { static struct thermal_zone_device_ops tzd_ops = {
.get_temp = pch_thermal_get_temp, .get_temp = pch_thermal_get_temp,
.get_trip_type = pch_get_trip_type,
.get_trip_temp = pch_get_trip_temp,
.critical = pch_critical, .critical = pch_critical,
}; };
...@@ -350,6 +300,7 @@ enum board_ids { ...@@ -350,6 +300,7 @@ enum board_ids {
board_cnl, board_cnl,
board_cml, board_cml,
board_lwb, board_lwb,
board_wbg,
}; };
static const struct board_info { static const struct board_info {
...@@ -380,6 +331,10 @@ static const struct board_info { ...@@ -380,6 +331,10 @@ static const struct board_info {
.name = "pch_lewisburg", .name = "pch_lewisburg",
.ops = &pch_dev_ops_wpt, .ops = &pch_dev_ops_wpt,
}, },
[board_wbg] = {
.name = "pch_wellsburg",
.ops = &pch_dev_ops_wpt,
},
}; };
static int intel_pch_thermal_probe(struct pci_dev *pdev, static int intel_pch_thermal_probe(struct pci_dev *pdev,
...@@ -423,8 +378,9 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev, ...@@ -423,8 +378,9 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev,
if (err) if (err)
goto error_cleanup; goto error_cleanup;
ptd->tzd = thermal_zone_device_register(bi->name, nr_trips, 0, ptd, ptd->tzd = thermal_zone_device_register_with_trips(bi->name, ptd->trips,
&tzd_ops, NULL, 0, 0); nr_trips, 0, ptd,
&tzd_ops, NULL, 0, 0);
if (IS_ERR(ptd->tzd)) { if (IS_ERR(ptd->tzd)) {
dev_err(&pdev->dev, "Failed to register thermal zone %s\n", dev_err(&pdev->dev, "Failed to register thermal zone %s\n",
bi->name); bi->name);
...@@ -495,6 +451,8 @@ static const struct pci_device_id intel_pch_thermal_id[] = { ...@@ -495,6 +451,8 @@ static const struct pci_device_id intel_pch_thermal_id[] = {
.driver_data = board_cml, }, .driver_data = board_cml, },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_LWB), { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_LWB),
.driver_data = board_lwb, }, .driver_data = board_lwb, },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WBG),
.driver_data = board_wbg, },
{ 0, }, { 0, },
}; };
MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/intel_tcc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -45,32 +46,6 @@ ...@@ -45,32 +46,6 @@
/* DTS0 and DTS 1 */ /* DTS0 and DTS 1 */
#define SOC_MAX_DTS_SENSORS 2 #define SOC_MAX_DTS_SENSORS 2
static int get_tj_max(u32 *tj_max)
{
u32 eax, edx;
u32 val;
int err;
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err)
goto err_ret;
else {
val = (eax >> 16) & 0xff;
if (val)
*tj_max = val * 1000;
else {
err = -EINVAL;
goto err_ret;
}
}
return 0;
err_ret:
*tj_max = 0;
return err;
}
static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip, static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
int *temp) int *temp)
{ {
...@@ -405,7 +380,7 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( ...@@ -405,7 +380,7 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
{ {
struct intel_soc_dts_sensors *sensors; struct intel_soc_dts_sensors *sensors;
bool notification; bool notification;
u32 tj_max; int tj_max;
int ret; int ret;
int i; int i;
...@@ -415,8 +390,9 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( ...@@ -415,8 +390,9 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
if (!trip_count || read_only_trip_count > trip_count) if (!trip_count || read_only_trip_count > trip_count)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (get_tj_max(&tj_max)) tj_max = intel_tcc_get_tjmax(-1);
return ERR_PTR(-EINVAL); if (tj_max < 0)
return ERR_PTR(tj_max);
sensors = kzalloc(sizeof(*sensors), GFP_KERNEL); sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
if (!sensors) if (!sensors)
...@@ -475,4 +451,5 @@ void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors) ...@@ -475,4 +451,5 @@ void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
} }
EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit); EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
MODULE_IMPORT_NS(INTEL_TCC);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0-only
/*
* intel_tcc.c - Library for Intel TCC (thermal control circuitry) MSR access
* Copyright (c) 2022, Intel Corporation.
*/
#include <linux/errno.h>
#include <linux/intel_tcc.h>
#include <asm/msr.h>
/**
* intel_tcc_get_tjmax() - returns the default TCC activation Temperature
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
*
* Get the TjMax value, which is the default thermal throttling or TCC
* activation temperature in degrees C.
*
* Return: Tjmax value in degrees C on success, negative error code otherwise.
*/
int intel_tcc_get_tjmax(int cpu)
{
u32 low, high;
int val, err;
if (cpu < 0)
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
else
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
if (err)
return err;
val = (low >> 16) & 0xff;
return val ? val : -ENODATA;
}
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, INTEL_TCC);
/**
* intel_tcc_get_offset() - returns the TCC Offset value to Tjmax
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
*
* Get the TCC offset value to Tjmax. The effective thermal throttling or TCC
* activation temperature equals "Tjmax" - "TCC Offset", in degrees C.
*
* Return: Tcc offset value in degrees C on success, negative error code otherwise.
*/
int intel_tcc_get_offset(int cpu)
{
u32 low, high;
int err;
if (cpu < 0)
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
else
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
if (err)
return err;
return (low >> 24) & 0x3f;
}
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
/**
* intel_tcc_set_offset() - set the TCC offset value to Tjmax
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
* @offset: TCC offset value in degree C
*
* Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC
* activation temperature equals "Tjmax" - "TCC Offset", in degree C.
*
* Return: On success returns 0, negative error code otherwise.
*/
int intel_tcc_set_offset(int cpu, int offset)
{
u32 low, high;
int err;
if (offset < 0 || offset > 0x3f)
return -EINVAL;
if (cpu < 0)
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
else
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
if (err)
return err;
/* MSR Locked */
if (low & BIT(31))
return -EPERM;
low &= ~(0x3f << 24);
low |= offset << 24;
if (cpu < 0)
return wrmsr_safe(MSR_IA32_TEMPERATURE_TARGET, low, high);
else
return wrmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, low, high);
}
EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
/**
* intel_tcc_get_temp() - returns the current temperature
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
* @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
*
* Get the current temperature returned by the CPU core/package level
* thermal sensor, in degrees C.
*
* Return: Temperature in degrees C on success, negative error code otherwise.
*/
int intel_tcc_get_temp(int cpu, bool pkg)
{
u32 low, high;
u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
int tjmax, temp, err;
tjmax = intel_tcc_get_tjmax(cpu);
if (tjmax < 0)
return tjmax;
if (cpu < 0)
err = rdmsr_safe(msr, &low, &high);
else
err = rdmsr_safe_on_cpu(cpu, msr, &low, &high);
if (err)
return err;
/* Temperature is beyond the valid thermal sensor range */
if (!(low & BIT(31)))
return -ENODATA;
temp = tjmax - ((low >> 16) & 0x7f);
/* Do not allow negative CPU temperature */
return temp >= 0 ? temp : -ENODATA;
}
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);
...@@ -7,12 +7,11 @@ ...@@ -7,12 +7,11 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/device.h> #include <linux/device.h>
#include <linux/intel_tcc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/thermal.h> #include <linux/thermal.h>
#include <asm/cpu_device_id.h> #include <asm/cpu_device_id.h>
#define TCC_SHIFT 24
#define TCC_MASK (0x3fULL<<24)
#define TCC_PROGRAMMABLE BIT(30) #define TCC_PROGRAMMABLE BIT(30)
#define TCC_LOCKED BIT(31) #define TCC_LOCKED BIT(31)
...@@ -21,47 +20,26 @@ static struct thermal_cooling_device *tcc_cdev; ...@@ -21,47 +20,26 @@ static struct thermal_cooling_device *tcc_cdev;
static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
*state) *state)
{ {
*state = TCC_MASK >> TCC_SHIFT; *state = 0x3f;
return 0;
}
static int tcc_offset_update(int tcc)
{
u64 val;
int err;
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
if (err)
return err;
val &= ~TCC_MASK;
val |= tcc << TCC_SHIFT;
err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
if (err)
return err;
return 0; return 0;
} }
static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
*state) *state)
{ {
u64 val; int offset = intel_tcc_get_offset(-1);
int err;
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); if (offset < 0)
if (err) return offset;
return err;
*state = (val & TCC_MASK) >> TCC_SHIFT; *state = offset;
return 0; return 0;
} }
static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long
state) state)
{ {
return tcc_offset_update(state); return intel_tcc_set_offset(-1, (int)state);
} }
static const struct thermal_cooling_device_ops tcc_cooling_ops = { static const struct thermal_cooling_device_ops tcc_cooling_ops = {
...@@ -140,6 +118,7 @@ static void __exit tcc_cooling_exit(void) ...@@ -140,6 +118,7 @@ static void __exit tcc_cooling_exit(void)
module_exit(tcc_cooling_exit) module_exit(tcc_cooling_exit)
MODULE_IMPORT_NS(INTEL_TCC);
MODULE_DESCRIPTION("TCC offset cooling device Driver"); MODULE_DESCRIPTION("TCC offset cooling device Driver");
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>"); MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/intel_tcc.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -48,11 +49,11 @@ MODULE_PARM_DESC(notify_delay_ms, ...@@ -48,11 +49,11 @@ MODULE_PARM_DESC(notify_delay_ms,
struct zone_device { struct zone_device {
int cpu; int cpu;
bool work_scheduled; bool work_scheduled;
u32 tj_max;
u32 msr_pkg_therm_low; u32 msr_pkg_therm_low;
u32 msr_pkg_therm_high; u32 msr_pkg_therm_high;
struct delayed_work work; struct delayed_work work;
struct thermal_zone_device *tzone; struct thermal_zone_device *tzone;
struct thermal_trip *trips;
struct cpumask cpumask; struct cpumask cpumask;
}; };
...@@ -104,71 +105,17 @@ static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu) ...@@ -104,71 +105,17 @@ static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu)
return NULL; return NULL;
} }
/*
* tj-max is interesting because threshold is set relative to this
* temperature.
*/
static int get_tj_max(int cpu, u32 *tj_max)
{
u32 eax, edx, val;
int err;
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err)
return err;
val = (eax >> 16) & 0xff;
*tj_max = val * 1000;
return val ? 0 : -EINVAL;
}
static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
{ {
struct zone_device *zonedev = tzd->devdata; struct zone_device *zonedev = tzd->devdata;
u32 eax, edx; int val;
rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_STATUS,
&eax, &edx);
if (eax & 0x80000000) {
*temp = zonedev->tj_max - ((eax >> 16) & 0x7f) * 1000;
pr_debug("sys_get_curr_temp %d\n", *temp);
return 0;
}
return -EINVAL;
}
static int sys_get_trip_temp(struct thermal_zone_device *tzd,
int trip, int *temp)
{
struct zone_device *zonedev = tzd->devdata;
unsigned long thres_reg_value;
u32 mask, shift, eax, edx;
int ret;
if (trip >= MAX_NUMBER_OF_TRIPS)
return -EINVAL;
if (trip) {
mask = THERM_MASK_THRESHOLD1;
shift = THERM_SHIFT_THRESHOLD1;
} else {
mask = THERM_MASK_THRESHOLD0;
shift = THERM_SHIFT_THRESHOLD0;
}
ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
&eax, &edx);
if (ret < 0)
return ret;
thres_reg_value = (eax & mask) >> shift; val = intel_tcc_get_temp(zonedev->cpu, true);
if (thres_reg_value) if (val < 0)
*temp = zonedev->tj_max - thres_reg_value * 1000; return val;
else
*temp = THERMAL_TEMP_INVALID;
pr_debug("sys_get_trip_temp %d\n", *temp);
*temp = val * 1000;
pr_debug("sys_get_curr_temp %d\n", *temp);
return 0; return 0;
} }
...@@ -177,9 +124,14 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) ...@@ -177,9 +124,14 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
{ {
struct zone_device *zonedev = tzd->devdata; struct zone_device *zonedev = tzd->devdata;
u32 l, h, mask, shift, intr; u32 l, h, mask, shift, intr;
int ret; int tj_max, ret;
tj_max = intel_tcc_get_tjmax(zonedev->cpu);
if (tj_max < 0)
return tj_max;
tj_max *= 1000;
if (trip >= MAX_NUMBER_OF_TRIPS || temp >= zonedev->tj_max) if (trip >= MAX_NUMBER_OF_TRIPS || temp >= tj_max)
return -EINVAL; return -EINVAL;
ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
...@@ -204,7 +156,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) ...@@ -204,7 +156,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
if (!temp) { if (!temp) {
l &= ~intr; l &= ~intr;
} else { } else {
l |= (zonedev->tj_max - temp)/1000 << shift; l |= (tj_max - temp)/1000 << shift;
l |= intr; l |= intr;
} }
...@@ -212,18 +164,9 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) ...@@ -212,18 +164,9 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
l, h); l, h);
} }
static int sys_get_trip_type(struct thermal_zone_device *thermal, int trip,
enum thermal_trip_type *type)
{
*type = THERMAL_TRIP_PASSIVE;
return 0;
}
/* Thermal zone callback registry */ /* Thermal zone callback registry */
static struct thermal_zone_device_ops tzone_ops = { static struct thermal_zone_device_ops tzone_ops = {
.get_temp = sys_get_curr_temp, .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, .set_trip_temp = sys_set_trip_temp,
}; };
...@@ -323,12 +266,55 @@ static int pkg_thermal_notify(u64 msr_val) ...@@ -323,12 +266,55 @@ static int pkg_thermal_notify(u64 msr_val)
return 0; return 0;
} }
static struct thermal_trip *pkg_temp_thermal_trips_init(int cpu, int tj_max, int num_trips)
{
struct thermal_trip *trips;
unsigned long thres_reg_value;
u32 mask, shift, eax, edx;
int ret, i;
trips = kzalloc(sizeof(*trips) * num_trips, GFP_KERNEL);
if (!trips)
return ERR_PTR(-ENOMEM);
for (i = 0; i < num_trips; i++) {
if (i) {
mask = THERM_MASK_THRESHOLD1;
shift = THERM_SHIFT_THRESHOLD1;
} else {
mask = THERM_MASK_THRESHOLD0;
shift = THERM_SHIFT_THRESHOLD0;
}
ret = rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
&eax, &edx);
if (ret < 0) {
kfree(trips);
return ERR_PTR(ret);
}
thres_reg_value = (eax & mask) >> shift;
trips[i].temperature = thres_reg_value ?
tj_max - thres_reg_value * 1000 : THERMAL_TEMP_INVALID;
trips[i].type = THERMAL_TRIP_PASSIVE;
pr_debug("%s: cpu=%d, trip=%d, temp=%d\n",
__func__, cpu, i, trips[i].temperature);
}
return trips;
}
static int pkg_temp_thermal_device_add(unsigned int cpu) static int pkg_temp_thermal_device_add(unsigned int cpu)
{ {
int id = topology_logical_die_id(cpu); int id = topology_logical_die_id(cpu);
u32 tj_max, eax, ebx, ecx, edx; u32 eax, ebx, ecx, edx;
struct zone_device *zonedev; struct zone_device *zonedev;
int thres_count, err; int thres_count, err;
int tj_max;
if (id >= max_id) if (id >= max_id)
return -ENOMEM; return -ENOMEM;
...@@ -340,32 +326,34 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) ...@@ -340,32 +326,34 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS); thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS);
err = get_tj_max(cpu, &tj_max); tj_max = intel_tcc_get_tjmax(cpu);
if (err) if (tj_max < 0)
return err; return tj_max;
zonedev = kzalloc(sizeof(*zonedev), GFP_KERNEL); zonedev = kzalloc(sizeof(*zonedev), GFP_KERNEL);
if (!zonedev) if (!zonedev)
return -ENOMEM; return -ENOMEM;
zonedev->trips = pkg_temp_thermal_trips_init(cpu, tj_max, thres_count);
if (IS_ERR(zonedev->trips)) {
err = PTR_ERR(zonedev->trips);
goto out_kfree_zonedev;
}
INIT_DELAYED_WORK(&zonedev->work, pkg_temp_thermal_threshold_work_fn); INIT_DELAYED_WORK(&zonedev->work, pkg_temp_thermal_threshold_work_fn);
zonedev->cpu = cpu; zonedev->cpu = cpu;
zonedev->tj_max = tj_max; zonedev->tzone = thermal_zone_device_register_with_trips("x86_pkg_temp",
zonedev->tzone = thermal_zone_device_register("x86_pkg_temp", zonedev->trips, thres_count,
thres_count,
(thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01, (thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01,
zonedev, &tzone_ops, &pkg_temp_tz_params, 0, 0); zonedev, &tzone_ops, &pkg_temp_tz_params, 0, 0);
if (IS_ERR(zonedev->tzone)) { if (IS_ERR(zonedev->tzone)) {
err = PTR_ERR(zonedev->tzone); err = PTR_ERR(zonedev->tzone);
kfree(zonedev); goto out_kfree_trips;
return err;
} }
err = thermal_zone_device_enable(zonedev->tzone); err = thermal_zone_device_enable(zonedev->tzone);
if (err) { if (err)
thermal_zone_device_unregister(zonedev->tzone); goto out_unregister_tz;
kfree(zonedev);
return err;
}
/* Store MSR value for package thermal interrupt, to restore at exit */ /* Store MSR value for package thermal interrupt, to restore at exit */
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low, rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low,
zonedev->msr_pkg_therm_high); zonedev->msr_pkg_therm_high);
...@@ -374,7 +362,16 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) ...@@ -374,7 +362,16 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
raw_spin_lock_irq(&pkg_temp_lock); raw_spin_lock_irq(&pkg_temp_lock);
zones[id] = zonedev; zones[id] = zonedev;
raw_spin_unlock_irq(&pkg_temp_lock); raw_spin_unlock_irq(&pkg_temp_lock);
return 0; return 0;
out_unregister_tz:
thermal_zone_device_unregister(zonedev->tzone);
out_kfree_trips:
kfree(zonedev->trips);
out_kfree_zonedev:
kfree(zonedev);
return err;
} }
static int pkg_thermal_cpu_offline(unsigned int cpu) static int pkg_thermal_cpu_offline(unsigned int cpu)
...@@ -458,8 +455,10 @@ static int pkg_thermal_cpu_offline(unsigned int cpu) ...@@ -458,8 +455,10 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
raw_spin_unlock_irq(&pkg_temp_lock); raw_spin_unlock_irq(&pkg_temp_lock);
/* Final cleanup if this is the last cpu */ /* Final cleanup if this is the last cpu */
if (lastcpu) if (lastcpu) {
kfree(zonedev->trips);
kfree(zonedev); kfree(zonedev);
}
return 0; return 0;
} }
...@@ -531,6 +530,7 @@ static void __exit pkg_temp_thermal_exit(void) ...@@ -531,6 +530,7 @@ static void __exit pkg_temp_thermal_exit(void)
} }
module_exit(pkg_temp_thermal_exit) module_exit(pkg_temp_thermal_exit)
MODULE_IMPORT_NS(INTEL_TCC);
MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver"); MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -264,17 +264,17 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, ...@@ -264,17 +264,17 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip,
return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
} }
static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz, int trip, int temp) static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp)
{ {
struct qpnp_tm_chip *chip = tz->devdata; struct qpnp_tm_chip *chip = tz->devdata;
const struct thermal_trip *trip_points; struct thermal_trip trip;
int ret; int ret;
trip_points = of_thermal_get_trip_points(chip->tz_dev); ret = __thermal_zone_get_trip(chip->tz_dev, trip_id, &trip);
if (!trip_points) if (ret)
return -EINVAL; return ret;
if (trip_points[trip].type != THERMAL_TRIP_CRITICAL) if (trip.type != THERMAL_TRIP_CRITICAL)
return 0; return 0;
mutex_lock(&chip->lock); mutex_lock(&chip->lock);
...@@ -300,22 +300,17 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data) ...@@ -300,22 +300,17 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
static int qpnp_tm_get_critical_trip_temp(struct qpnp_tm_chip *chip) static int qpnp_tm_get_critical_trip_temp(struct qpnp_tm_chip *chip)
{ {
int ntrips; struct thermal_trip trip;
const struct thermal_trip *trips; int i, ret;
int i;
for (i = 0; i < thermal_zone_get_num_trips(chip->tz_dev); i++) {
ntrips = of_thermal_get_ntrips(chip->tz_dev);
if (ntrips <= 0) ret = thermal_zone_get_trip(chip->tz_dev, i, &trip);
return THERMAL_TEMP_INVALID; if (ret)
continue;
trips = of_thermal_get_trip_points(chip->tz_dev);
if (!trips) if (trip.type == THERMAL_TRIP_CRITICAL)
return THERMAL_TEMP_INVALID; return trip.temperature;
for (i = 0; i < ntrips; i++) {
if (of_thermal_is_trip_valid(chip->tz_dev, i) &&
trips[i].type == THERMAL_TRIP_CRITICAL)
return trips[i].temperature;
} }
return THERMAL_TEMP_INVALID; return THERMAL_TEMP_INVALID;
...@@ -353,7 +348,12 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip) ...@@ -353,7 +348,12 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
if (stage) if (stage)
chip->temp = qpnp_tm_decode_temp(chip, stage); chip->temp = qpnp_tm_decode_temp(chip, stage);
mutex_unlock(&chip->lock);
crit_temp = qpnp_tm_get_critical_trip_temp(chip); crit_temp = qpnp_tm_get_critical_trip_temp(chip);
mutex_lock(&chip->lock);
ret = qpnp_tm_update_critical_trip_temp(chip, crit_temp); ret = qpnp_tm_update_critical_trip_temp(chip, crit_temp);
if (ret < 0) if (ret < 0)
goto out; goto out;
......
...@@ -529,7 +529,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) ...@@ -529,7 +529,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
if (ret) if (ret)
goto error_unregister; goto error_unregister;
ret = of_thermal_get_ntrips(tsc->zone); ret = thermal_zone_get_num_trips(tsc->zone);
if (ret < 0) if (ret < 0)
goto error_unregister; goto error_unregister;
......
...@@ -278,52 +278,12 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) ...@@ -278,52 +278,12 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
return rcar_thermal_get_current_temp(priv, temp); return rcar_thermal_get_current_temp(priv, temp);
} }
static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone, static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
int trip, enum thermal_trip_type *type)
{
struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
struct device *dev = rcar_priv_to_dev(priv);
/* see rcar_thermal_get_temp() */
switch (trip) {
case 0: /* +90 <= temp */
*type = THERMAL_TRIP_CRITICAL;
break;
default:
dev_err(dev, "rcar driver trip error\n");
return -EINVAL;
}
return 0;
}
static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone,
int trip, int *temp)
{
struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
struct device *dev = rcar_priv_to_dev(priv);
/* see rcar_thermal_get_temp() */
switch (trip) {
case 0: /* +90 <= temp */
*temp = MCELSIUS(90);
break;
default:
dev_err(dev, "rcar driver trip error\n");
return -EINVAL;
}
return 0;
}
static const struct thermal_zone_device_ops rcar_thermal_zone_of_ops = {
.get_temp = rcar_thermal_get_temp, .get_temp = rcar_thermal_get_temp,
}; };
static struct thermal_zone_device_ops rcar_thermal_zone_ops = { static struct thermal_trip trips[] = {
.get_temp = rcar_thermal_get_temp, { .type = THERMAL_TRIP_CRITICAL, .temperature = 90000 }
.get_trip_type = rcar_thermal_get_trip_type,
.get_trip_temp = rcar_thermal_get_trip_temp,
}; };
/* /*
...@@ -529,11 +489,10 @@ static int rcar_thermal_probe(struct platform_device *pdev) ...@@ -529,11 +489,10 @@ static int rcar_thermal_probe(struct platform_device *pdev)
if (chip->use_of_thermal) { if (chip->use_of_thermal) {
priv->zone = devm_thermal_of_zone_register( priv->zone = devm_thermal_of_zone_register(
dev, i, priv, dev, i, priv,
&rcar_thermal_zone_of_ops); &rcar_thermal_zone_ops);
} else { } else {
priv->zone = thermal_zone_device_register( priv->zone = thermal_zone_device_register_with_trips(
"rcar_thermal", "rcar_thermal", trips, ARRAY_SIZE(trips), 0, priv,
1, 0, priv,
&rcar_thermal_zone_ops, NULL, 0, &rcar_thermal_zone_ops, NULL, 0,
idle); idle);
......
...@@ -260,31 +260,23 @@ static int exynos_tmu_initialize(struct platform_device *pdev) ...@@ -260,31 +260,23 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
{ {
struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tzd = data->tzd; struct thermal_zone_device *tzd = data->tzd;
const struct thermal_trip * const trips = int num_trips = thermal_zone_get_num_trips(tzd);
of_thermal_get_trip_points(tzd);
unsigned int status; unsigned int status;
int ret = 0, temp, hyst; int ret = 0, temp;
if (!trips) { ret = thermal_zone_get_crit_temp(tzd, &temp);
dev_err(&pdev->dev, if (ret && data->soc != SOC_ARCH_EXYNOS5433) { /* FIXME */
"Cannot get trip points from device tree!\n");
return -ENODEV;
}
if (data->soc != SOC_ARCH_EXYNOS5433) /* FIXME */
ret = tzd->ops->get_crit_temp(tzd, &temp);
if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"No CRITICAL trip point defined in device tree!\n"); "No CRITICAL trip point defined in device tree!\n");
goto out; goto out;
} }
if (of_thermal_get_ntrips(tzd) > data->ntrip) { if (num_trips > data->ntrip) {
dev_info(&pdev->dev, dev_info(&pdev->dev,
"More trip points than supported by this TMU.\n"); "More trip points than supported by this TMU.\n");
dev_info(&pdev->dev, dev_info(&pdev->dev,
"%d trip points should be configured in polling mode.\n", "%d trip points should be configured in polling mode.\n",
(of_thermal_get_ntrips(tzd) - data->ntrip)); num_trips - data->ntrip);
} }
mutex_lock(&data->lock); mutex_lock(&data->lock);
...@@ -297,25 +289,22 @@ static int exynos_tmu_initialize(struct platform_device *pdev) ...@@ -297,25 +289,22 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
ret = -EBUSY; ret = -EBUSY;
} else { } else {
int i, ntrips = int i, ntrips =
min_t(int, of_thermal_get_ntrips(tzd), data->ntrip); min_t(int, num_trips, data->ntrip);
data->tmu_initialize(pdev); data->tmu_initialize(pdev);
/* Write temperature code for rising and falling threshold */ /* Write temperature code for rising and falling threshold */
for (i = 0; i < ntrips; i++) { for (i = 0; i < ntrips; i++) {
/* Write temperature code for rising threshold */
ret = tzd->ops->get_trip_temp(tzd, i, &temp);
if (ret)
goto err;
temp /= MCELSIUS;
data->tmu_set_trip_temp(data, i, temp);
/* Write temperature code for falling threshold */ struct thermal_trip trip;
ret = tzd->ops->get_trip_hyst(tzd, i, &hyst);
ret = thermal_zone_get_trip(tzd, i, &trip);
if (ret) if (ret)
goto err; goto err;
hyst /= MCELSIUS;
data->tmu_set_trip_hyst(data, i, temp, hyst); data->tmu_set_trip_temp(data, i, trip.temperature / MCELSIUS);
data->tmu_set_trip_hyst(data, i, trip.temperature / MCELSIUS,
trip.hysteresis / MCELSIUS);
} }
data->tmu_clear_irqs(data); data->tmu_clear_irqs(data);
...@@ -360,21 +349,23 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) ...@@ -360,21 +349,23 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
} }
static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data, static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data,
int trip, u8 temp) int trip_id, u8 temp)
{ {
const struct thermal_trip * const trips = struct thermal_trip trip;
of_thermal_get_trip_points(data->tzd);
u8 ref, th_code; u8 ref, th_code;
ref = trips[0].temperature / MCELSIUS; if (thermal_zone_get_trip(data->tzd, 0, &trip))
return;
ref = trip.temperature / MCELSIUS;
if (trip == 0) { if (trip_id == 0) {
th_code = temp_to_code(data, ref); th_code = temp_to_code(data, ref);
writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
} }
temp -= ref; temp -= ref;
writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4); writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip_id * 4);
} }
/* failing thresholds are not supported on Exynos4210 */ /* failing thresholds are not supported on Exynos4210 */
...@@ -562,13 +553,14 @@ static void exynos4210_tmu_control(struct platform_device *pdev, bool on) ...@@ -562,13 +553,14 @@ static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
{ {
struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd; struct thermal_zone_device *tz = data->tzd;
struct thermal_trip trip;
unsigned int con, interrupt_en = 0, i; unsigned int con, interrupt_en = 0, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) { if (on) {
for (i = 0; i < data->ntrip; i++) { for (i = 0; i < data->ntrip; i++) {
if (!of_thermal_is_trip_valid(tz, i)) if (thermal_zone_get_trip(tz, i, &trip))
continue; continue;
interrupt_en |= interrupt_en |=
...@@ -592,13 +584,14 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on) ...@@ -592,13 +584,14 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on)
{ {
struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd; struct thermal_zone_device *tz = data->tzd;
struct thermal_trip trip;
unsigned int con, interrupt_en = 0, pd_det_en, i; unsigned int con, interrupt_en = 0, pd_det_en, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) { if (on) {
for (i = 0; i < data->ntrip; i++) { for (i = 0; i < data->ntrip; i++) {
if (!of_thermal_is_trip_valid(tz, i)) if (thermal_zone_get_trip(tz, i, &trip))
continue; continue;
interrupt_en |= interrupt_en |=
...@@ -623,13 +616,14 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on) ...@@ -623,13 +616,14 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
{ {
struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd; struct thermal_zone_device *tz = data->tzd;
struct thermal_trip trip;
unsigned int con, interrupt_en = 0, i; unsigned int con, interrupt_en = 0, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) { if (on) {
for (i = 0; i < data->ntrip; i++) { for (i = 0; i < data->ntrip; i++) {
if (!of_thermal_is_trip_valid(tz, i)) if (thermal_zone_get_trip(tz, i, &trip))
continue; continue;
interrupt_en |= interrupt_en |=
......
...@@ -134,48 +134,12 @@ static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature) ...@@ -134,48 +134,12 @@ static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature)
return 0; return 0;
} }
static int st_thermal_get_trip_type(struct thermal_zone_device *th,
int trip, enum thermal_trip_type *type)
{
struct st_thermal_sensor *sensor = th->devdata;
struct device *dev = sensor->dev;
switch (trip) {
case 0:
*type = THERMAL_TRIP_CRITICAL;
break;
default:
dev_err(dev, "invalid trip point\n");
return -EINVAL;
}
return 0;
}
static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
int trip, int *temp)
{
struct st_thermal_sensor *sensor = th->devdata;
struct device *dev = sensor->dev;
switch (trip) {
case 0:
*temp = mcelsius(sensor->cdata->crit_temp);
break;
default:
dev_err(dev, "Invalid trip point\n");
return -EINVAL;
}
return 0;
}
static struct thermal_zone_device_ops st_tz_ops = { static struct thermal_zone_device_ops st_tz_ops = {
.get_temp = st_thermal_get_temp, .get_temp = st_thermal_get_temp,
.get_trip_type = st_thermal_get_trip_type,
.get_trip_temp = st_thermal_get_trip_temp,
}; };
static struct thermal_trip trip;
int st_thermal_register(struct platform_device *pdev, int st_thermal_register(struct platform_device *pdev,
const struct of_device_id *st_thermal_of_match) const struct of_device_id *st_thermal_of_match)
{ {
...@@ -238,9 +202,12 @@ int st_thermal_register(struct platform_device *pdev, ...@@ -238,9 +202,12 @@ int st_thermal_register(struct platform_device *pdev,
polling_delay = sensor->ops->register_enable_irq ? 0 : 1000; polling_delay = sensor->ops->register_enable_irq ? 0 : 1000;
trip.temperature = sensor->cdata->crit_temp;
trip.type = THERMAL_TRIP_CRITICAL;
sensor->thermal_dev = sensor->thermal_dev =
thermal_zone_device_register(dev_name(dev), 1, 0, sensor, thermal_zone_device_register_with_trips(dev_name(dev), &trip, 1, 0, sensor,
&st_tz_ops, NULL, 0, polling_delay); &st_tz_ops, NULL, 0, polling_delay);
if (IS_ERR(sensor->thermal_dev)) { if (IS_ERR(sensor->thermal_dev)) {
dev_err(dev, "failed to register thermal zone device\n"); dev_err(dev, "failed to register thermal zone device\n");
ret = PTR_ERR(sensor->thermal_dev); ret = PTR_ERR(sensor->thermal_dev);
......
...@@ -582,23 +582,23 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id) ...@@ -582,23 +582,23 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
return temp; return temp;
} }
static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip, int temp) static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp)
{ {
struct tegra_thermctl_zone *zone = tz->devdata; struct tegra_thermctl_zone *zone = tz->devdata;
struct tegra_soctherm *ts = zone->ts; struct tegra_soctherm *ts = zone->ts;
struct thermal_trip trip;
const struct tegra_tsensor_group *sg = zone->sg; const struct tegra_tsensor_group *sg = zone->sg;
struct device *dev = zone->dev; struct device *dev = zone->dev;
enum thermal_trip_type type;
int ret; int ret;
if (!tz) if (!tz)
return -EINVAL; return -EINVAL;
ret = tz->ops->get_trip_type(tz, trip, &type); ret = __thermal_zone_get_trip(tz, trip_id, &trip);
if (ret) if (ret)
return ret; return ret;
if (type == THERMAL_TRIP_CRITICAL) { if (trip.type == THERMAL_TRIP_CRITICAL) {
/* /*
* If thermtrips property is set in DT, * If thermtrips property is set in DT,
* doesn't need to program critical type trip to HW, * doesn't need to program critical type trip to HW,
...@@ -609,7 +609,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip ...@@ -609,7 +609,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip
else else
return 0; return 0;
} else if (type == THERMAL_TRIP_HOT) { } else if (trip.type == THERMAL_TRIP_HOT) {
int i; int i;
for (i = 0; i < THROTTLE_SIZE; i++) { for (i = 0; i < THROTTLE_SIZE; i++) {
...@@ -620,7 +620,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip ...@@ -620,7 +620,7 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip
continue; continue;
cdev = ts->throt_cfgs[i].cdev; cdev = ts->throt_cfgs[i].cdev;
if (get_thermal_instance(tz, cdev, trip)) if (get_thermal_instance(tz, cdev, trip_id))
stc = find_throttle_cfg_by_name(ts, cdev->type); stc = find_throttle_cfg_by_name(ts, cdev->type);
else else
continue; continue;
...@@ -687,25 +687,20 @@ static const struct thermal_zone_device_ops tegra_of_thermal_ops = { ...@@ -687,25 +687,20 @@ static const struct thermal_zone_device_ops tegra_of_thermal_ops = {
.set_trips = tegra_thermctl_set_trips, .set_trips = tegra_thermctl_set_trips,
}; };
static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp) static int get_hot_temp(struct thermal_zone_device *tz, int *trip_id, int *temp)
{ {
int ntrips, i, ret; int i, ret;
enum thermal_trip_type type; struct thermal_trip trip;
ntrips = of_thermal_get_ntrips(tz); for (i = 0; i < thermal_zone_get_num_trips(tz); i++) {
if (ntrips <= 0)
return -EINVAL;
for (i = 0; i < ntrips; i++) { ret = thermal_zone_get_trip(tz, i, &trip);
ret = tz->ops->get_trip_type(tz, i, &type);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
if (type == THERMAL_TRIP_HOT) {
ret = tz->ops->get_trip_temp(tz, i, temp);
if (!ret)
*trip = i;
return ret; if (trip.type == THERMAL_TRIP_HOT) {
*trip_id = i;
return 0;
} }
} }
...@@ -747,7 +742,7 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, ...@@ -747,7 +742,7 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
/* Get thermtrips. If missing, try to get critical trips. */ /* Get thermtrips. If missing, try to get critical trips. */
temperature = tsensor_group_thermtrip_get(ts, sg->id); temperature = tsensor_group_thermtrip_get(ts, sg->id);
if (min_low_temp == temperature) if (min_low_temp == temperature)
if (tz->ops->get_crit_temp(tz, &temperature)) if (thermal_zone_get_crit_temp(tz, &temperature))
temperature = max_high_temp; temperature = max_high_temp;
ret = thermtrip_program(dev, sg, temperature); ret = thermtrip_program(dev, sg, temperature);
......
...@@ -316,18 +316,17 @@ static void tegra_tsensor_get_hw_channel_trips(struct thermal_zone_device *tzd, ...@@ -316,18 +316,17 @@ static void tegra_tsensor_get_hw_channel_trips(struct thermal_zone_device *tzd,
*hot_trip = 85000; *hot_trip = 85000;
*crit_trip = 90000; *crit_trip = 90000;
for (i = 0; i < tzd->num_trips; i++) { for (i = 0; i < thermal_zone_get_num_trips(tzd); i++) {
enum thermal_trip_type type;
int trip_temp;
tzd->ops->get_trip_temp(tzd, i, &trip_temp); struct thermal_trip trip;
tzd->ops->get_trip_type(tzd, i, &type);
if (type == THERMAL_TRIP_HOT) thermal_zone_get_trip(tzd, i, &trip);
*hot_trip = trip_temp;
if (type == THERMAL_TRIP_CRITICAL) if (trip.type == THERMAL_TRIP_HOT)
*crit_trip = trip_temp; *hot_trip = trip.temperature;
if (trip.type == THERMAL_TRIP_CRITICAL)
*crit_trip = trip.temperature;
} }
/* clamp hardware trips to the calibration limits */ /* clamp hardware trips to the calibration limits */
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2023 Linaro Limited
* Copyright 2023 Intel Corporation
*
* Library routines for populating a generic thermal trip point structure
* with data obtained by evaluating a specific object in the ACPI Namespace.
*/
#include <linux/acpi.h>
#include <linux/units.h>
#include "thermal_core.h"
/*
* Minimum temperature for full military grade is 218°K (-55°C) and
* max temperature is 448°K (175°C). We can consider those values as
* the boundaries for the [trips] temperature returned by the
* firmware. Any values out of these boundaries may be considered
* bogus and we can assume the firmware has no data to provide.
*/
#define TEMP_MIN_DECIK 2180
#define TEMP_MAX_DECIK 4480
static int thermal_acpi_trip_init(struct acpi_device *adev,
enum thermal_trip_type type, int id,
struct thermal_trip *trip)
{
unsigned long long temp;
acpi_status status;
char obj_name[5];
switch (type) {
case THERMAL_TRIP_ACTIVE:
if (id < 0 || id > 9)
return -EINVAL;
obj_name[1] = 'A';
obj_name[2] = 'C';
obj_name[3] = '0' + id;
break;
case THERMAL_TRIP_PASSIVE:
obj_name[1] = 'P';
obj_name[2] = 'S';
obj_name[3] = 'V';
break;
case THERMAL_TRIP_HOT:
obj_name[1] = 'H';
obj_name[2] = 'O';
obj_name[3] = 'T';
break;
case THERMAL_TRIP_CRITICAL:
obj_name[1] = 'C';
obj_name[2] = 'R';
obj_name[3] = 'T';
break;
}
obj_name[0] = '_';
obj_name[4] = '\0';
status = acpi_evaluate_integer(adev->handle, obj_name, NULL, &temp);
if (ACPI_FAILURE(status)) {
acpi_handle_debug(adev->handle, "%s evaluation failed\n", obj_name);
return -ENODATA;
}
if (temp < TEMP_MIN_DECIK || temp >= TEMP_MAX_DECIK) {
acpi_handle_debug(adev->handle, "%s result %llu out of range\n",
obj_name, temp);
return -ENODATA;
}
trip->temperature = deci_kelvin_to_millicelsius(temp);
trip->hysteresis = 0;
trip->type = type;
return 0;
}
/**
* thermal_acpi_trip_active - Get the specified active trip point
* @adev: Thermal zone ACPI device object to get the description from.
* @id: Active cooling level (0 - 9).
* @trip: Trip point structure to be populated on success.
*
* Evaluate the _ACx object for the thermal zone represented by @adev to obtain
* the temperature of the active cooling trip point corresponding to the active
* cooling level given by @id and initialize @trip as an active trip point using
* that temperature value.
*
* Return 0 on success or a negative error value on failure.
*/
int thermal_acpi_trip_active(struct acpi_device *adev, int id,
struct thermal_trip *trip)
{
return thermal_acpi_trip_init(adev, THERMAL_TRIP_ACTIVE, id, trip);
}
EXPORT_SYMBOL_GPL(thermal_acpi_trip_active);
/**
* thermal_acpi_trip_passive - Get the passive trip point
* @adev: Thermal zone ACPI device object to get the description from.
* @trip: Trip point structure to be populated on success.
*
* Evaluate the _PSV object for the thermal zone represented by @adev to obtain
* the temperature of the passive cooling trip point and initialize @trip as a
* passive trip point using that temperature value.
*
* Return 0 on success or -ENODATA on failure.
*/
int thermal_acpi_trip_passive(struct acpi_device *adev, struct thermal_trip *trip)
{
return thermal_acpi_trip_init(adev, THERMAL_TRIP_PASSIVE, INT_MAX, trip);
}
EXPORT_SYMBOL_GPL(thermal_acpi_trip_passive);
/**
* thermal_acpi_trip_hot - Get the near critical trip point
* @adev: the ACPI device to get the description from.
* @trip: a &struct thermal_trip to be filled if the function succeed.
*
* Evaluate the _HOT object for the thermal zone represented by @adev to obtain
* the temperature of the trip point at which the system is expected to be put
* into the S4 sleep state and initialize @trip as a hot trip point using that
* temperature value.
*
* Return 0 on success or -ENODATA on failure.
*/
int thermal_acpi_trip_hot(struct acpi_device *adev, struct thermal_trip *trip)
{
return thermal_acpi_trip_init(adev, THERMAL_TRIP_HOT, INT_MAX, trip);
}
EXPORT_SYMBOL_GPL(thermal_acpi_trip_hot);
/**
* thermal_acpi_trip_critical - Get the critical trip point
* @adev: the ACPI device to get the description from.
* @trip: a &struct thermal_trip to be filled if the function succeed.
*
* Evaluate the _CRT object for the thermal zone represented by @adev to obtain
* the temperature of the critical cooling trip point and initialize @trip as a
* critical trip point using that temperature value.
*
* Return 0 on success or -ENODATA on failure.
*/
int thermal_acpi_trip_critical(struct acpi_device *adev, struct thermal_trip *trip)
{
return thermal_acpi_trip_init(adev, THERMAL_TRIP_CRITICAL, INT_MAX, trip);
}
EXPORT_SYMBOL_GPL(thermal_acpi_trip_critical);
...@@ -344,35 +344,31 @@ static void handle_critical_trips(struct thermal_zone_device *tz, ...@@ -344,35 +344,31 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
tz->ops->critical(tz); tz->ops->critical(tz);
} }
static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id)
{ {
enum thermal_trip_type type; struct thermal_trip trip;
int trip_temp, hyst = 0;
/* Ignore disabled trip points */ /* Ignore disabled trip points */
if (test_bit(trip, &tz->trips_disabled)) if (test_bit(trip_id, &tz->trips_disabled))
return; return;
tz->ops->get_trip_temp(tz, trip, &trip_temp); __thermal_zone_get_trip(tz, trip_id, &trip);
tz->ops->get_trip_type(tz, trip, &type);
if (tz->ops->get_trip_hyst)
tz->ops->get_trip_hyst(tz, trip, &hyst);
if (tz->last_temperature != THERMAL_TEMP_INVALID) { if (tz->last_temperature != THERMAL_TEMP_INVALID) {
if (tz->last_temperature < trip_temp && if (tz->last_temperature < trip.temperature &&
tz->temperature >= trip_temp) tz->temperature >= trip.temperature)
thermal_notify_tz_trip_up(tz->id, trip, thermal_notify_tz_trip_up(tz->id, trip_id,
tz->temperature); tz->temperature);
if (tz->last_temperature >= trip_temp && if (tz->last_temperature >= trip.temperature &&
tz->temperature < (trip_temp - hyst)) tz->temperature < (trip.temperature - trip.hysteresis))
thermal_notify_tz_trip_down(tz->id, trip, thermal_notify_tz_trip_down(tz->id, trip_id,
tz->temperature); tz->temperature);
} }
if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) if (trip.type == THERMAL_TRIP_CRITICAL || trip.type == THERMAL_TRIP_HOT)
handle_critical_trips(tz, trip, trip_temp, type); handle_critical_trips(tz, trip_id, trip.temperature, trip.type);
else else
handle_non_critical_trips(tz, trip); handle_non_critical_trips(tz, trip_id);
} }
static void update_temperature(struct thermal_zone_device *tz) static void update_temperature(struct thermal_zone_device *tz)
...@@ -1166,6 +1162,119 @@ static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms ...@@ -1166,6 +1162,119 @@ static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms
*delay_jiffies = round_jiffies(*delay_jiffies); *delay_jiffies = round_jiffies(*delay_jiffies);
} }
int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
{
return tz->num_trips;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp)
{
int i, ret = -EINVAL;
if (tz->ops->get_crit_temp)
return tz->ops->get_crit_temp(tz, temp);
if (!tz->trips)
return -EINVAL;
mutex_lock(&tz->lock);
for (i = 0; i < tz->num_trips; i++) {
if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) {
*temp = tz->trips[i].temperature;
ret = 0;
break;
}
}
mutex_unlock(&tz->lock);
return ret;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp);
int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip)
{
int ret;
if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip)
return -EINVAL;
if (tz->trips) {
*trip = tz->trips[trip_id];
return 0;
}
if (tz->ops->get_trip_hyst) {
ret = tz->ops->get_trip_hyst(tz, trip_id, &trip->hysteresis);
if (ret)
return ret;
} else {
trip->hysteresis = 0;
}
ret = tz->ops->get_trip_temp(tz, trip_id, &trip->temperature);
if (ret)
return ret;
return tz->ops->get_trip_type(tz, trip_id, &trip->type);
}
EXPORT_SYMBOL_GPL(__thermal_zone_get_trip);
int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip)
{
int ret;
mutex_lock(&tz->lock);
ret = __thermal_zone_get_trip(tz, trip_id, trip);
mutex_unlock(&tz->lock);
return ret;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_trip);
int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id,
const struct thermal_trip *trip)
{
struct thermal_trip t;
int ret;
if (!tz->ops->set_trip_temp && !tz->ops->set_trip_hyst && !tz->trips)
return -EINVAL;
ret = __thermal_zone_get_trip(tz, trip_id, &t);
if (ret)
return ret;
if (t.type != trip->type)
return -EINVAL;
if (t.temperature != trip->temperature && tz->ops->set_trip_temp) {
ret = tz->ops->set_trip_temp(tz, trip_id, trip->temperature);
if (ret)
return ret;
}
if (t.hysteresis != trip->hysteresis && tz->ops->set_trip_hyst) {
ret = tz->ops->set_trip_hyst(tz, trip_id, trip->hysteresis);
if (ret)
return ret;
}
if (tz->trips && (t.temperature != trip->temperature || t.hysteresis != trip->hysteresis))
tz->trips[trip_id] = *trip;
thermal_notify_tz_trip_change(tz->id, trip_id, trip->type,
trip->temperature, trip->hysteresis);
__thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
return 0;
}
/** /**
* thermal_zone_device_register_with_trips() - register a new thermal zone device * thermal_zone_device_register_with_trips() - register a new thermal zone device
* @type: the thermal zone device type * @type: the thermal zone device type
...@@ -1198,8 +1307,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t ...@@ -1198,8 +1307,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
int polling_delay) int polling_delay)
{ {
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
enum thermal_trip_type trip_type;
int trip_temp;
int id; int id;
int result; int result;
int count; int count;
...@@ -1239,7 +1346,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t ...@@ -1239,7 +1346,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
tz = kzalloc(sizeof(*tz), GFP_KERNEL); tz = kzalloc(sizeof(*tz), GFP_KERNEL);
...@@ -1290,9 +1397,10 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t ...@@ -1290,9 +1397,10 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
goto release_device; goto release_device;
for (count = 0; count < num_trips; count++) { for (count = 0; count < num_trips; count++) {
if (tz->ops->get_trip_type(tz, count, &trip_type) || struct thermal_trip trip;
tz->ops->get_trip_temp(tz, count, &trip_temp) ||
!trip_temp) result = thermal_zone_get_trip(tz, count, &trip);
if (result)
set_bit(count, &tz->trips_disabled); set_bit(count, &tz->trips_disabled);
} }
......
...@@ -114,6 +114,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, ...@@ -114,6 +114,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
/* Helpers */ /* Helpers */
void __thermal_zone_set_trips(struct thermal_zone_device *tz); void __thermal_zone_set_trips(struct thermal_zone_device *tz);
int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip);
int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
/* sysfs I/F */ /* sysfs I/F */
...@@ -137,28 +139,6 @@ thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev, ...@@ -137,28 +139,6 @@ thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
#endif /* CONFIG_THERMAL_STATISTICS */ #endif /* CONFIG_THERMAL_STATISTICS */
/* device tree support */ /* device tree support */
#ifdef CONFIG_THERMAL_OF
int of_thermal_get_ntrips(struct thermal_zone_device *);
bool of_thermal_is_trip_valid(struct thermal_zone_device *, int);
const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *);
#else
static inline int of_thermal_get_ntrips(struct thermal_zone_device *tz)
{
return 0;
}
static inline bool of_thermal_is_trip_valid(struct thermal_zone_device *tz,
int trip)
{
return false;
}
static inline const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *tz)
{
return NULL;
}
#endif
int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); int thermal_zone_device_is_enabled(struct thermal_zone_device *tz);
#endif /* __THERMAL_CORE_H__ */ #endif /* __THERMAL_CORE_H__ */
...@@ -83,7 +83,7 @@ int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) ...@@ -83,7 +83,7 @@ int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
int ret = -EINVAL; int ret = -EINVAL;
int count; int count;
int crit_temp = INT_MAX; int crit_temp = INT_MAX;
enum thermal_trip_type type; struct thermal_trip trip;
lockdep_assert_held(&tz->lock); lockdep_assert_held(&tz->lock);
...@@ -91,10 +91,9 @@ int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) ...@@ -91,10 +91,9 @@ int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) { if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
for (count = 0; count < tz->num_trips; count++) { for (count = 0; count < tz->num_trips; count++) {
ret = tz->ops->get_trip_type(tz, count, &type); ret = __thermal_zone_get_trip(tz, count, &trip);
if (!ret && type == THERMAL_TRIP_CRITICAL) { if (!ret && trip.type == THERMAL_TRIP_CRITICAL) {
ret = tz->ops->get_trip_temp(tz, count, crit_temp = trip.temperature;
&crit_temp);
break; break;
} }
} }
...@@ -164,29 +163,30 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp); ...@@ -164,29 +163,30 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
*/ */
void __thermal_zone_set_trips(struct thermal_zone_device *tz) void __thermal_zone_set_trips(struct thermal_zone_device *tz)
{ {
int low = -INT_MAX; struct thermal_trip trip;
int high = INT_MAX; int low = -INT_MAX, high = INT_MAX;
int trip_temp, hysteresis;
int i, ret; int i, ret;
lockdep_assert_held(&tz->lock); lockdep_assert_held(&tz->lock);
if (!tz->ops->set_trips || !tz->ops->get_trip_hyst) if (!tz->ops->set_trips)
return; return;
for (i = 0; i < tz->num_trips; i++) { for (i = 0; i < tz->num_trips; i++) {
int trip_low; int trip_low;
tz->ops->get_trip_temp(tz, i, &trip_temp); ret = __thermal_zone_get_trip(tz, i , &trip);
tz->ops->get_trip_hyst(tz, i, &hysteresis); if (ret)
return;
trip_low = trip_temp - hysteresis; trip_low = trip.temperature - trip.hysteresis;
if (trip_low < tz->temperature && trip_low > low) if (trip_low < tz->temperature && trip_low > low)
low = trip_low; low = trip_low;
if (trip_temp > tz->temperature && trip_temp < high) if (trip.temperature > tz->temperature &&
high = trip_temp; trip.temperature < high)
high = trip.temperature;
} }
/* No need to change trip points */ /* No need to change trip points */
......
...@@ -452,7 +452,8 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p) ...@@ -452,7 +452,8 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p)
struct sk_buff *msg = p->msg; struct sk_buff *msg = p->msg;
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
struct nlattr *start_trip; struct nlattr *start_trip;
int i, id; struct thermal_trip trip;
int ret, i, id;
if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID])
return -EINVAL; return -EINVAL;
...@@ -471,18 +472,14 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p) ...@@ -471,18 +472,14 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p)
for (i = 0; i < tz->num_trips; i++) { for (i = 0; i < tz->num_trips; i++) {
enum thermal_trip_type type; ret = __thermal_zone_get_trip(tz, i, &trip);
int temp, hyst = 0; if (ret)
goto out_cancel_nest;
tz->ops->get_trip_type(tz, i, &type);
tz->ops->get_trip_temp(tz, i, &temp);
if (tz->ops->get_trip_hyst)
tz->ops->get_trip_hyst(tz, i, &hyst);
if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) || if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) ||
nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, type) || nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, trip.type) ||
nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, temp) || nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, trip.temperature) ||
nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, hyst)) nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, trip.hysteresis))
goto out_cancel_nest; goto out_cancel_nest;
} }
......
...@@ -19,117 +19,6 @@ ...@@ -19,117 +19,6 @@
#include "thermal_core.h" #include "thermal_core.h"
/**
* of_thermal_get_ntrips - function to export number of available trip
* points.
* @tz: pointer to a thermal zone
*
* This function is a globally visible wrapper to get number of trip points
* stored in the local struct __thermal_zone
*
* Return: number of available trip points, -ENODEV when data not available
*/
int of_thermal_get_ntrips(struct thermal_zone_device *tz)
{
return tz->num_trips;
}
EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
/**
* of_thermal_is_trip_valid - function to check if trip point is valid
*
* @tz: pointer to a thermal zone
* @trip: trip point to evaluate
*
* This function is responsible for checking if passed trip point is valid
*
* Return: true if trip point is valid, false otherwise
*/
bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip)
{
if (trip >= tz->num_trips || trip < 0)
return false;
return true;
}
EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
/**
* of_thermal_get_trip_points - function to get access to a globally exported
* trip points
*
* @tz: pointer to a thermal zone
*
* This function provides a pointer to trip points table
*
* Return: pointer to trip points table, NULL otherwise
*/
const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *tz)
{
return tz->trips;
}
EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
enum thermal_trip_type *type)
{
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
*type = tz->trips[trip].type;
return 0;
}
static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
int *temp)
{
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
*temp = tz->trips[trip].temperature;
return 0;
}
static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
int *hyst)
{
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
*hyst = tz->trips[trip].hysteresis;
return 0;
}
static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
int hyst)
{
if (trip >= tz->num_trips || trip < 0)
return -EDOM;
/* thermal framework should take care of data->mask & (1 << trip) */
tz->trips[trip].hysteresis = hyst;
return 0;
}
static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
int *temp)
{
int i;
for (i = 0; i < tz->num_trips; i++)
if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) {
*temp = tz->trips[i].temperature;
return 0;
}
return -EINVAL;
}
/*** functions parsing device tree nodes ***/ /*** functions parsing device tree nodes ***/
static int of_find_trip_id(struct device_node *np, struct device_node *trip) static int of_find_trip_id(struct device_node *np, struct device_node *trip)
...@@ -628,11 +517,6 @@ struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, ...@@ -628,11 +517,6 @@ struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor,
goto out_kfree_trips; goto out_kfree_trips;
} }
of_ops->get_trip_type = of_ops->get_trip_type ? : of_thermal_get_trip_type;
of_ops->get_trip_temp = of_ops->get_trip_temp ? : of_thermal_get_trip_temp;
of_ops->get_trip_hyst = of_ops->get_trip_hyst ? : of_thermal_get_trip_hyst;
of_ops->set_trip_hyst = of_ops->set_trip_hyst ? : of_thermal_set_trip_hyst;
of_ops->get_crit_temp = of_ops->get_crit_temp ? : of_thermal_get_crit_temp;
of_ops->bind = thermal_of_bind; of_ops->bind = thermal_of_bind;
of_ops->unbind = thermal_of_unbind; of_ops->unbind = thermal_of_unbind;
......
...@@ -83,27 +83,25 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, ...@@ -83,27 +83,25 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_zone_device *tz = to_thermal_zone(dev);
enum thermal_trip_type type; struct thermal_trip trip;
int trip, result; int trip_id, result;
if (!tz->ops->get_trip_type) if (sscanf(attr->attr.name, "trip_point_%d_type", &trip_id) != 1)
return -EPERM;
if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
return -EINVAL; return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
if (device_is_registered(dev)) if (device_is_registered(dev))
result = tz->ops->get_trip_type(tz, trip, &type); result = __thermal_zone_get_trip(tz, trip_id, &trip);
else else
result = -ENODEV; result = -ENODEV;
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
if (result) if (result)
return result; return result;
switch (type) { switch (trip.type) {
case THERMAL_TRIP_CRITICAL: case THERMAL_TRIP_CRITICAL:
return sprintf(buf, "critical\n"); return sprintf(buf, "critical\n");
case THERMAL_TRIP_HOT: case THERMAL_TRIP_HOT:
...@@ -122,17 +120,10 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, ...@@ -122,17 +120,10 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret; struct thermal_trip trip;
int temperature, hyst = 0; int trip_id, ret;
enum thermal_trip_type type;
if (!tz->ops->set_trip_temp && !tz->trips)
return -EPERM;
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
return -EINVAL;
if (kstrtoint(buf, 10, &temperature)) if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1)
return -EINVAL; return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
...@@ -142,36 +133,19 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, ...@@ -142,36 +133,19 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
goto unlock; goto unlock;
} }
if (tz->ops->set_trip_temp) { ret = __thermal_zone_get_trip(tz, trip_id, &trip);
ret = tz->ops->set_trip_temp(tz, trip, temperature);
if (ret)
goto unlock;
}
if (tz->trips)
tz->trips[trip].temperature = temperature;
if (tz->ops->get_trip_hyst) {
ret = tz->ops->get_trip_hyst(tz, trip, &hyst);
if (ret)
goto unlock;
}
ret = tz->ops->get_trip_type(tz, trip, &type);
if (ret) if (ret)
goto unlock; goto unlock;
thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst); ret = kstrtoint(buf, 10, &trip.temperature);
if (ret)
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); goto unlock;
ret = thermal_zone_set_trip(tz, trip_id, &trip);
unlock: unlock:
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
if (ret) return ret ? ret : count;
return ret;
return count;
} }
static ssize_t static ssize_t
...@@ -179,19 +153,16 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, ...@@ -179,19 +153,16 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret; struct thermal_trip trip;
int temperature; int trip_id, ret;
if (!tz->ops->get_trip_temp)
return -EPERM;
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1) if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1)
return -EINVAL; return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
if (device_is_registered(dev)) if (device_is_registered(dev))
ret = tz->ops->get_trip_temp(tz, trip, &temperature); ret = __thermal_zone_get_trip(tz, trip_id, &trip);
else else
ret = -ENODEV; ret = -ENODEV;
...@@ -200,7 +171,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, ...@@ -200,7 +171,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if (ret) if (ret)
return ret; return ret;
return sprintf(buf, "%d\n", temperature); return sprintf(buf, "%d\n", trip.temperature);
} }
static ssize_t static ssize_t
...@@ -208,16 +179,13 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr, ...@@ -208,16 +179,13 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret; struct thermal_trip trip;
int temperature; int trip_id, ret;
if (!tz->ops->set_trip_hyst)
return -EPERM;
if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1) if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1)
return -EINVAL; return -EINVAL;
if (kstrtoint(buf, 10, &temperature)) if (kstrtoint(buf, 10, &trip.hysteresis))
return -EINVAL; return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
...@@ -227,16 +195,11 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr, ...@@ -227,16 +195,11 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
goto unlock; goto unlock;
} }
/* ret = __thermal_zone_get_trip(tz, trip_id, &trip);
* We are not doing any check on the 'temperature' value if (ret)
* here. The driver implementing 'set_trip_hyst' has to goto unlock;
* take care of this.
*/ ret = thermal_zone_set_trip(tz, trip_id, &trip);
ret = tz->ops->set_trip_hyst(tz, trip, temperature);
if (!ret)
__thermal_zone_set_trips(tz);
unlock: unlock:
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
...@@ -248,25 +211,22 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr, ...@@ -248,25 +211,22 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret; struct thermal_trip trip;
int temperature; int trip_id, ret;
if (!tz->ops->get_trip_hyst)
return -EPERM;
if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1) if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1)
return -EINVAL; return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
if (device_is_registered(dev)) if (device_is_registered(dev))
ret = tz->ops->get_trip_hyst(tz, trip, &temperature); ret = __thermal_zone_get_trip(tz, trip_id, &trip);
else else
ret = -ENODEV; ret = -ENODEV;
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
return ret ? ret : sprintf(buf, "%d\n", temperature); return ret ? ret : sprintf(buf, "%d\n", trip.hysteresis);
} }
static ssize_t static ssize_t
...@@ -491,23 +451,20 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) ...@@ -491,23 +451,20 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
return -ENOMEM; return -ENOMEM;
} }
if (tz->ops->get_trip_hyst) { tz->trip_hyst_attrs = kcalloc(tz->num_trips,
tz->trip_hyst_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_hyst_attrs),
sizeof(*tz->trip_hyst_attrs), GFP_KERNEL);
GFP_KERNEL); if (!tz->trip_hyst_attrs) {
if (!tz->trip_hyst_attrs) { kfree(tz->trip_type_attrs);
kfree(tz->trip_type_attrs); kfree(tz->trip_temp_attrs);
kfree(tz->trip_temp_attrs); return -ENOMEM;
return -ENOMEM;
}
} }
attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL); attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
if (!attrs) { if (!attrs) {
kfree(tz->trip_type_attrs); kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs); kfree(tz->trip_temp_attrs);
if (tz->ops->get_trip_hyst) kfree(tz->trip_hyst_attrs);
kfree(tz->trip_hyst_attrs);
return -ENOMEM; return -ENOMEM;
} }
...@@ -540,9 +497,6 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) ...@@ -540,9 +497,6 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
} }
attrs[indx + tz->num_trips] = &tz->trip_temp_attrs[indx].attr.attr; attrs[indx + tz->num_trips] = &tz->trip_temp_attrs[indx].attr.attr;
/* create Optional trip hyst attribute */
if (!tz->ops->get_trip_hyst)
continue;
snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
"trip_point_%d_hyst", indx); "trip_point_%d_hyst", indx);
...@@ -579,8 +533,7 @@ static void destroy_trip_attrs(struct thermal_zone_device *tz) ...@@ -579,8 +533,7 @@ static void destroy_trip_attrs(struct thermal_zone_device *tz)
kfree(tz->trip_type_attrs); kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs); kfree(tz->trip_temp_attrs);
if (tz->ops->get_trip_hyst) kfree(tz->trip_hyst_attrs);
kfree(tz->trip_hyst_attrs);
kfree(tz->trips_attribute_group.attrs); kfree(tz->trips_attribute_group.attrs);
} }
......
...@@ -38,21 +38,6 @@ ...@@ -38,21 +38,6 @@
/* Update rates */ /* Update rates */
#define FAST_TEMP_MONITORING_RATE 250 #define FAST_TEMP_MONITORING_RATE 250
/* helper macros */
/**
* ti_thermal_get_trip_value - returns trip temperature based on index
* @i: trip index
*/
#define ti_thermal_get_trip_value(i) \
(OMAP_TRIP_HOT + ((i) * OMAP_TRIP_STEP))
/**
* ti_thermal_is_valid_trip - check for trip index
* @i: trip index
*/
#define ti_thermal_is_valid_trip(trip) \
((trip) >= 0 && (trip) < OMAP_TRIP_NUMBER)
#ifdef CONFIG_TI_THERMAL #ifdef CONFIG_TI_THERMAL
int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain); int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain);
int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id); int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id);
......
...@@ -248,8 +248,7 @@ static int uniphier_tm_probe(struct platform_device *pdev) ...@@ -248,8 +248,7 @@ static int uniphier_tm_probe(struct platform_device *pdev)
struct regmap *regmap; struct regmap *regmap;
struct device_node *parent; struct device_node *parent;
struct uniphier_tm_dev *tdev; struct uniphier_tm_dev *tdev;
const struct thermal_trip *trips; int i, ret, irq, crit_temp = INT_MAX;
int i, ret, irq, ntrips, crit_temp = INT_MAX;
tdev = devm_kzalloc(dev, sizeof(*tdev), GFP_KERNEL); tdev = devm_kzalloc(dev, sizeof(*tdev), GFP_KERNEL);
if (!tdev) if (!tdev)
...@@ -296,20 +295,18 @@ static int uniphier_tm_probe(struct platform_device *pdev) ...@@ -296,20 +295,18 @@ static int uniphier_tm_probe(struct platform_device *pdev)
return PTR_ERR(tdev->tz_dev); return PTR_ERR(tdev->tz_dev);
} }
/* get trip points */
trips = of_thermal_get_trip_points(tdev->tz_dev);
ntrips = of_thermal_get_ntrips(tdev->tz_dev);
if (ntrips > ALERT_CH_NUM) {
dev_err(dev, "thermal zone has too many trips\n");
return -E2BIG;
}
/* set alert temperatures */ /* set alert temperatures */
for (i = 0; i < ntrips; i++) { for (i = 0; i < thermal_zone_get_num_trips(tdev->tz_dev); i++) {
if (trips[i].type == THERMAL_TRIP_CRITICAL && struct thermal_trip trip;
trips[i].temperature < crit_temp)
crit_temp = trips[i].temperature; ret = thermal_zone_get_trip(tdev->tz_dev, i, &trip);
uniphier_tm_set_alert(tdev, i, trips[i].temperature); if (ret)
return ret;
if (trip.type == THERMAL_TRIP_CRITICAL &&
trip.temperature < crit_temp)
crit_temp = trip.temperature;
uniphier_tm_set_alert(tdev, i, trip.temperature);
tdev->alert_en[i] = true; tdev->alert_en[i] = true;
} }
if (crit_temp > CRITICAL_TEMP_LIMIT) { if (crit_temp > CRITICAL_TEMP_LIMIT) {
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* header for Intel TCC (thermal control circuitry) library
*
* Copyright (C) 2022 Intel Corporation.
*/
#ifndef __INTEL_TCC_H__
#define __INTEL_TCC_H__
#include <linux/types.h>
int intel_tcc_get_tjmax(int cpu);
int intel_tcc_get_offset(int cpu);
int intel_tcc_set_offset(int cpu, int offset);
int intel_tcc_get_temp(int cpu, bool pkg);
#endif /* __INTEL_TCC_H__ */
...@@ -334,6 +334,26 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev, ...@@ -334,6 +334,26 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev,
} }
#endif #endif
int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip);
int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip);
int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id,
const struct thermal_trip *trip);
int thermal_zone_get_num_trips(struct thermal_zone_device *tz);
int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp);
#ifdef CONFIG_THERMAL_ACPI
int thermal_acpi_trip_active(struct acpi_device *adev, int id,
struct thermal_trip *trip);
int thermal_acpi_trip_passive(struct acpi_device *adev, struct thermal_trip *trip);
int thermal_acpi_trip_hot(struct acpi_device *adev, struct thermal_trip *trip);
int thermal_acpi_trip_critical(struct acpi_device *adev, struct thermal_trip *trip);
#endif
#ifdef CONFIG_THERMAL #ifdef CONFIG_THERMAL
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
void *, struct thermal_zone_device_ops *, void *, struct thermal_zone_device_ops *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment