Commit 976cb655 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge tag 'generic-trip-point' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux

Pull thermal control updates for 6.3 from Daniel Lezcano:

"- Rework a large bunch of drivers to use the generic thermal trip
   structure and the opportunity to do more cleanups by removing unused
   functions in the OF code (Daniel Lezcano).

 - Fix some locking issues related to the generic thermal trip rework
   (Johan Hovold).

 - Fix a crash when requesting the critical temperature on tegra, this
   fix is related to the generic trip point (Jon Hunter).

 - Use strscpy() to instead of strncpy() (Xu Panda)."

* tag 'generic-trip-point' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (37 commits)
  thermal/drivers/armada: Use strscpy() to instead of strncpy()
  thermal/drivers/qcom: Fix lock inversion
  thermal/drivers/tegra: Fix set_trip_temp() deadlock
  thermal/drivers/qcom: Fix set_trip_temp() deadlock
  thermal/drivers/mellanox: Use generic thermal_zone_get_trip() function
  wifi: iwlwifi: Use generic thermal_zone_get_trip() function
  thermal/drivers/tegra: Fix crash when getting critical temp
  thermal/drivers/exynos: Fix NULL pointer dereference when getting the critical temp
  thermal/drivers/intel: Use generic thermal_zone_get_trip() function
  thermal/intel/int340x: Replace parameter to simplify
  thermal/drivers/cxgb4: Use generic thermal_zone_get_trip() function
  thermal/drivers/acerhdf: Use generic thermal_zone_get_trip() function
  thermal/drivers/ti: Remove unused macros ti_thermal_get_trip_value() / ti_thermal_trip_is_valid()
  thermal/drivers/da9062: Use generic thermal_zone_get_trip() function
  thermal/drivers/broadcom: Use generic thermal_zone_get_trip() function
  thermal/drivers/rcar: Use generic thermal_zone_get_trip() function
  thermal/drivers/imx: Use generic thermal_zone_get_trip() function
  thermal/drivers/st: Use generic trip points
  thermal/of: Remove of_thermal_get_crit_temp()
  thermal/of: Remove of_thermal_set_trip_hyst()
  ...
parents b878d3ba 3a151494
......@@ -1079,8 +1079,6 @@ struct mbox_list {
#if IS_ENABLED(CONFIG_THERMAL)
struct ch_thermal {
struct thermal_zone_device *tzdev;
int trip_temp;
int trip_type;
};
#endif
......
......@@ -29,36 +29,12 @@ static int cxgb4_thermal_get_temp(struct thermal_zone_device *tzdev,
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 = {
.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)
{
struct ch_thermal *ch_thermal = &adap->ch_thermal;
......@@ -79,15 +55,14 @@ int cxgb4_thermal_init(struct adapter *adap)
if (ret < 0) {
num_trip = 0; /* could not get trip temperature */
} else {
ch_thermal->trip_temp = val * 1000;
ch_thermal->trip_type = THERMAL_TRIP_CRITICAL;
trip.temperature = val * 1000;
}
snprintf(ch_tz_name, sizeof(ch_tz_name), "cxgb4_%s", adap->name);
ch_thermal->tzdev = thermal_zone_device_register(ch_tz_name, num_trip,
0, adap,
&cxgb4_thermal_ops,
NULL, 0, 0);
ch_thermal->tzdev = thermal_zone_device_register_with_trips(ch_tz_name, &trip, num_trip,
0, adap,
&cxgb4_thermal_ops,
NULL, 0, 0);
if (IS_ERR(ch_thermal->tzdev)) {
ret = PTR_ERR(ch_thermal->tzdev);
dev_err(adap->pdev_dev, "Failed to register thermal zone\n");
......
......@@ -501,7 +501,7 @@ struct iwl_mvm_tt_mgmt {
* @tzone: thermal zone device data
*/
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];
struct thermal_zone_device *tzone;
};
......
......@@ -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
*/
/* 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++) {
if (mvm->tz_device.temp_trips[i] != S16_MIN) {
if (mvm->tz_device.trips[i].temperature != INT_MIN) {
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);
......@@ -593,8 +593,8 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
*/
for (i = 0; i < idx; i++) {
for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) {
if (le16_to_cpu(cmd.thresholds[i]) ==
mvm->tz_device.temp_trips[j])
if ((int)(le16_to_cpu(cmd.thresholds[i]) * 1000) ==
mvm->tz_device.trips[j].temperature)
mvm->tz_device.fw_trips_index[i] = j;
}
}
......@@ -638,37 +638,12 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
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,
int trip, int temp)
{
struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
struct iwl_mvm_thermal_device *tzone;
int i, ret;
s16 temperature;
int ret;
mutex_lock(&mvm->mutex);
......@@ -678,40 +653,17 @@ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
goto out;
}
if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) {
ret = -EINVAL;
goto out;
}
if ((temp / 1000) > S16_MAX) {
ret = -EINVAL;
goto out;
}
temperature = (s16)(temp / 1000);
tzone = &mvm->tz_device;
if (!tzone) {
ret = -EIO;
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);
out:
mutex_unlock(&mvm->mutex);
......@@ -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 = {
.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,
};
......@@ -743,7 +693,8 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
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_WRITABLE_TRIPS_MSK,
mvm, &tzone_ops,
......@@ -766,8 +717,10 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
/* 0 is a valid temperature,
* so initialize the array with S16_MIN which invalid temperature
*/
for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++)
mvm->tz_device.temp_trips[i] = S16_MIN;
for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) {
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,
......
......@@ -46,6 +46,8 @@
* measured by the on-die thermal monitor are within 0 <= Tj <= 90. So,
* 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_FAN_OFF 0
#define ACERHDF_FAN_AUTO 1
......@@ -70,8 +72,8 @@ static int kernelmode;
#endif
static unsigned int interval = 10;
static unsigned int fanon = 60000;
static unsigned int fanoff = 53000;
static unsigned int fanon = ACERHDF_DEFAULT_TEMP_FANON;
static unsigned int fanoff = ACERHDF_DEFAULT_TEMP_FANOFF;
static unsigned int verbose;
static unsigned int list_supported;
static unsigned int fanstate = ACERHDF_FAN_AUTO;
......@@ -137,6 +139,15 @@ struct ctrl_settings {
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;
/* Register addresses and values for different BIOS versions */
......@@ -326,6 +337,15 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal)
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 (interval > ACERHDF_MAX_INTERVAL) {
pr_err("interval too high, set to %d\n",
......@@ -424,43 +444,6 @@ static int acerhdf_change_mode(struct thermal_zone_device *thermal,
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,
int *temperature)
{
......@@ -474,13 +457,9 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = {
.unbind = acerhdf_unbind,
.get_temp = acerhdf_get_ec_temp,
.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,
};
/*
* cooling device callback functions
* get maximal fan cooling state
......@@ -710,10 +689,10 @@ static int __init acerhdf_register_thermal(void)
if (IS_ERR(cl_dev))
return -EINVAL;
thz_dev = thermal_zone_device_register("acerhdf", 2, 0, NULL,
&acerhdf_dev_ops,
&acerhdf_zone_params, 0,
(kernelmode) ? interval*1000 : 0);
thz_dev = thermal_zone_device_register_with_trips("acerhdf", trips, ARRAY_SIZE(trips),
0, NULL, &acerhdf_dev_ops,
&acerhdf_zone_params, 0,
(kernelmode) ? interval*1000 : 0);
if (IS_ERR(thz_dev))
return -EINVAL;
......
......@@ -761,8 +761,7 @@ static void armada_set_sane_name(struct platform_device *pdev,
}
/* Save the name locally */
strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1);
priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0';
strscpy(priv->zone_name, name, THERMAL_NAME_LENGTH);
/* Then check there are no '-' or hwmon core will complain */
do {
......@@ -785,33 +784,34 @@ static int armada_configure_overheat_int(struct armada_thermal_priv *priv,
int sensor_id)
{
/* 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 i;
if (!trips)
return -EINVAL;
for (i = 0; i < thermal_zone_get_num_trips(tz); i++) {
for (i = 0; i < of_thermal_get_ntrips(tz); i++)
if (trips[i].type == THERMAL_TRIP_CRITICAL)
break;
ret = thermal_zone_get_trip(tz, i, &trip);
if (ret)
return ret;
if (i == of_thermal_get_ntrips(tz))
return -EINVAL;
if (trip.type != THERMAL_TRIP_CRITICAL)
continue;
ret = armada_select_channel(priv, sensor_id);
if (ret)
return ret;
ret = armada_select_channel(priv, sensor_id);
if (ret)
return ret;
armada_set_overheat_thresholds(priv,
trips[i].temperature,
trips[i].hysteresis);
priv->overheat_sensor = tz;
priv->interrupt_source = sensor_id;
armada_set_overheat_thresholds(priv, trip.temperature,
trip.hysteresis);
priv->overheat_sensor = tz;
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)
......
......@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include "../thermal_core.h"
#include "../thermal_hwmon.h"
#define BCM2835_TS_TSENSCTL 0x00
......@@ -224,7 +225,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
*/
val = readl(data->regs + BCM2835_TS_TSENSCTL);
if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
int trip_temp, offset, slope;
struct thermal_trip trip;
int offset, slope;
slope = thermal_zone_get_slope(tz);
offset = thermal_zone_get_offset(tz);
......@@ -232,7 +234,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
* For now we deal only with critical, otherwise
* 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) {
dev_err(&pdev->dev,
"Not able to read trip_temp: %d\n",
......@@ -249,7 +251,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
/* trip_adc value from info */
val |= bcm2835_thermal_temp2adc(trip_temp,
val |= bcm2835_thermal_temp2adc(trip.temperature,
offset,
slope)
<< BCM2835_TS_TSENSCTL_THOLD_SHIFT;
......
......@@ -120,44 +120,6 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
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,
int *temp)
{
......@@ -172,8 +134,10 @@ static int da9062_thermal_get_temp(struct thermal_zone_device *z,
static struct thermal_zone_device_ops da9062_thermal_ops = {
.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 = {
......@@ -228,10 +192,10 @@ static int da9062_thermal_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
mutex_init(&thermal->lock);
thermal->zone = thermal_zone_device_register(thermal->config->name,
1, 0, thermal,
&da9062_thermal_ops, NULL, pp_tmp,
0);
thermal->zone = thermal_zone_device_register_with_trips(thermal->config->name,
trips, ARRAY_SIZE(trips), 0, thermal,
&da9062_thermal_ops, NULL, pp_tmp,
0);
if (IS_ERR(thermal->zone)) {
dev_err(&pdev->dev, "Cannot register thermal zone device\n");
ret = PTR_ERR(thermal->zone);
......
......@@ -13,26 +13,28 @@
#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;
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) {
pr_warn_once("Undefined get_trip_hyst for thermal zone %s - "
"running with default hysteresis zero\n", tz->type);
trip_hyst = 0;
} else
tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
if (!trip.hysteresis)
dev_info_once(&tz->device,
"Zero hysteresis value for thermal zone %s\n", tz->type);
dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
trip, trip_temp, tz->temperature,
trip_hyst);
trip_id, trip.temperature, tz->temperature,
trip.hysteresis);
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (instance->trip != trip)
if (instance->trip != trip_id)
continue;
/* 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)
* enable fan when temperature exceeds trip_temp and disable
* 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;
else if (instance->target == 1 &&
tz->temperature <= trip_temp - trip_hyst)
tz->temperature <= trip.temperature - trip.hysteresis)
instance->target = 0;
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)
instance->cdev->updated = false; /* cdev needs update */
mutex_unlock(&instance->cdev->lock);
}
return 0;
}
/**
......@@ -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)
{
struct thermal_instance *instance;
int ret;
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)
thermal_cdev_update(instance->cdev);
......
......@@ -21,16 +21,12 @@
*/
static int get_trip_level(struct thermal_zone_device *tz)
{
int count = 0;
int trip_temp;
enum thermal_trip_type trip_type;
if (tz->num_trips == 0 || !tz->ops->get_trip_temp)
return 0;
struct thermal_trip trip;
int count;
for (count = 0; count < tz->num_trips; count++) {
tz->ops->get_trip_temp(tz, count, &trip_temp);
if (tz->temperature < trip_temp)
__thermal_zone_get_trip(tz, count, &trip);
if (tz->temperature < trip.temperature)
break;
}
......@@ -38,10 +34,8 @@ static int get_trip_level(struct thermal_zone_device *tz)
* count > 0 only if temperature is greater than first trip
* point, in which case, trip_point = count - 1
*/
if (count > 0) {
tz->ops->get_trip_type(tz, count - 1, &trip_type);
trace_thermal_zone_trip(tz, count - 1, trip_type);
}
if (count > 0)
trace_thermal_zone_trip(tz, count - 1, trip.type);
return count;
}
......
......@@ -124,16 +124,15 @@ static void estimate_pid_constants(struct thermal_zone_device *tz,
u32 sustainable_power, int trip_switch_on,
int control_temp)
{
struct thermal_trip trip;
u32 temperature_threshold = control_temp;
int ret;
int switch_on_temp;
u32 temperature_threshold;
s32 k_i;
ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp);
if (ret)
switch_on_temp = 0;
ret = __thermal_zone_get_trip(tz, trip_switch_on, &trip);
if (!ret)
temperature_threshold -= trip.temperature;
temperature_threshold = control_temp - switch_on_temp;
/*
* estimate_pid_constants() tries to find appropriate default
* 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,
last_passive = INVALID_TRIP;
for (i = 0; i < tz->num_trips; i++) {
enum thermal_trip_type type;
struct thermal_trip trip;
int ret;
ret = tz->ops->get_trip_type(tz, i, &type);
ret = __thermal_zone_get_trip(tz, i, &trip);
if (ret) {
dev_warn(&tz->device,
"Failed to get trip point %d type: %d\n", i,
......@@ -530,14 +529,14 @@ static void get_governor_trips(struct thermal_zone_device *tz,
continue;
}
if (type == THERMAL_TRIP_PASSIVE) {
if (trip.type == THERMAL_TRIP_PASSIVE) {
if (!found_first_passive) {
params->trip_switch_on = i;
found_first_passive = true;
} else {
last_passive = i;
}
} else if (type == THERMAL_TRIP_ACTIVE) {
} else if (trip.type == THERMAL_TRIP_ACTIVE) {
last_active = i;
} else {
break;
......@@ -632,7 +631,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
{
int ret;
struct power_allocator_params *params;
int control_temp;
struct thermal_trip trip;
ret = check_power_actors(tz);
if (ret)
......@@ -658,13 +657,12 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
get_governor_trips(tz, params);
if (tz->num_trips > 0) {
ret = tz->ops->get_trip_temp(tz,
params->trip_max_desired_temperature,
&control_temp);
ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature,
&trip);
if (!ret)
estimate_pid_constants(tz, tz->tzp->sustainable_power,
params->trip_switch_on,
control_temp);
trip.temperature);
}
reset_pid_controller(params);
......@@ -694,11 +692,11 @@ static void power_allocator_unbind(struct thermal_zone_device *tz)
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 thermal_trip trip;
int ret;
bool update;
lockdep_assert_held(&tz->lock);
......@@ -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
* our calculations once
*/
if (trip != params->trip_max_desired_temperature)
if (trip_id != params->trip_max_desired_temperature)
return 0;
ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
&switch_on_temp);
if (!ret && (tz->temperature < switch_on_temp)) {
update = (tz->last_temperature >= switch_on_temp);
ret = __thermal_zone_get_trip(tz, params->trip_switch_on, &trip);
if (!ret && (tz->temperature < trip.temperature)) {
update = (tz->last_temperature >= trip.temperature);
tz->passive = 0;
reset_pid_controller(params);
allow_maximum_power(tz, update);
......@@ -722,16 +719,14 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
tz->passive = 1;
ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature,
&control_temp);
ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, &trip);
if (ret) {
dev_warn(&tz->device,
"Failed to get the maximum desired temperature: %d\n",
dev_warn(&tz->device, "Failed to get the maximum desired temperature: %d\n",
ret);
return ret;
}
return allocate_power(tz, control_temp);
return allocate_power(tz, trip.temperature);
}
static struct thermal_governor thermal_gov_power_allocator = {
......
......@@ -95,30 +95,28 @@ static void update_passive_instance(struct thermal_zone_device *tz,
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;
struct thermal_instance *instance;
struct thermal_trip trip;
bool throttle = false;
int old_target;
tz->ops->get_trip_temp(tz, trip, &trip_temp);
tz->ops->get_trip_type(tz, trip, &trip_type);
__thermal_zone_get_trip(tz, trip_id, &trip);
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;
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",
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) {
if (instance->trip != trip)
if (instance->trip != trip_id)
continue;
old_target = instance->target;
......@@ -132,11 +130,11 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
/* Activate a passive thermal instance */
if (old_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 */
else if (old_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;
mutex_lock(&instance->cdev->lock);
......
......@@ -482,7 +482,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
struct hisi_thermal_sensor *sensor)
{
int ret, i;
const struct thermal_trip *trip;
struct thermal_trip trip;
sensor->tzd = devm_thermal_of_zone_register(&pdev->dev,
sensor->id, sensor,
......@@ -495,11 +495,12 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
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++) {
if (trip[i].type == THERMAL_TRIP_PASSIVE) {
sensor->thres_temp = trip[i].temperature;
thermal_zone_get_trip(sensor->tzd, i, &trip);
if (trip.type == THERMAL_TRIP_PASSIVE) {
sensor->thres_temp = trip.temperature;
break;
}
}
......
......@@ -76,7 +76,6 @@
enum imx_thermal_trip {
IMX_TRIP_PASSIVE,
IMX_TRIP_CRITICAL,
IMX_TRIP_NUM,
};
#define IMX_POLLING_DELAY 2000 /* millisecond */
......@@ -115,6 +114,11 @@ struct thermal_soc_data {
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 = {
.version = TEMPMON_IMX6Q,
......@@ -201,8 +205,6 @@ struct imx_thermal_data {
struct thermal_cooling_device *cdev;
struct regmap *tempmon;
u32 c1, c2; /* See formula in imx_init_calib() */
int temp_passive;
int temp_critical;
int temp_max;
int alarm_temp;
int last_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 */
if (data->socdata->version == TEMPMON_IMX6Q) {
if (data->alarm_temp == data->temp_passive &&
*temp >= data->temp_passive)
imx_set_alarm_temp(data, data->temp_critical);
if (data->alarm_temp == data->temp_critical &&
*temp < data->temp_passive) {
imx_set_alarm_temp(data, data->temp_passive);
if (data->alarm_temp == trips[IMX_TRIP_PASSIVE].temperature &&
*temp >= trips[IMX_TRIP_PASSIVE].temperature)
imx_set_alarm_temp(data, trips[IMX_TRIP_CRITICAL].temperature);
if (data->alarm_temp == trips[IMX_TRIP_CRITICAL].temperature &&
*temp < trips[IMX_TRIP_PASSIVE].temperature) {
imx_set_alarm_temp(data, trips[IMX_TRIP_PASSIVE].temperature);
dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
data->alarm_temp / 1000);
}
......@@ -330,29 +332,10 @@ static int imx_change_mode(struct thermal_zone_device *tz,
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)
{
struct imx_thermal_data *data = tz->devdata;
*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 = trips[IMX_TRIP_CRITICAL].temperature;
*temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
data->temp_critical;
return 0;
}
......@@ -371,10 +354,10 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
return -EPERM;
/* 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;
data->temp_passive = temp;
trips[IMX_TRIP_PASSIVE].temperature = temp;
imx_set_alarm_temp(data, temp);
......@@ -423,8 +406,6 @@ static struct thermal_zone_device_ops imx_tz_ops = {
.unbind = imx_unbind,
.get_temp = imx_get_temp,
.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,
.set_trip_temp = imx_set_trip_temp,
};
......@@ -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 passive trip point at 10 °C under max (changeable via sysfs)
*/
data->temp_critical = data->temp_max - (1000 * 5);
data->temp_passive = data->temp_max - (1000 * 10);
trips[IMX_TRIP_PASSIVE].temperature = 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)
......@@ -743,12 +724,13 @@ static int imx_thermal_probe(struct platform_device *pdev)
goto legacy_cleanup;
}
data->tz = thermal_zone_device_register("imx_thermal_zone",
IMX_TRIP_NUM,
BIT(IMX_TRIP_PASSIVE), data,
&imx_tz_ops, NULL,
IMX_PASSIVE_DELAY,
IMX_POLLING_DELAY);
data->tz = thermal_zone_device_register_with_trips("imx_thermal_zone",
trips,
ARRAY_SIZE(trips),
BIT(IMX_TRIP_PASSIVE), data,
&imx_tz_ops, NULL,
IMX_PASSIVE_DELAY,
IMX_POLLING_DELAY);
if (IS_ERR(data->tz)) {
ret = PTR_ERR(data->tz);
dev_err(&pdev->dev,
......@@ -758,8 +740,8 @@ static int imx_thermal_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
" critical:%dC passive:%dC\n", data->temp_grade,
data->temp_max / 1000, data->temp_critical / 1000,
data->temp_passive / 1000);
data->temp_max / 1000, trips[IMX_TRIP_CRITICAL].temperature / 1000,
trips[IMX_TRIP_PASSIVE].temperature / 1000);
/* Enable measurements at ~ 10 Hz */
regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
......@@ -767,10 +749,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
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)
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,
data->socdata->power_down_mask);
......
......@@ -18,9 +18,6 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
unsigned long long tmp;
acpi_status status;
if (d->override_ops && d->override_ops->get_temp)
return d->override_ops->get_temp(zone, temp);
status = acpi_evaluate_integer(d->adev->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status))
return -EIO;
......@@ -46,9 +43,6 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
struct int34x_thermal_zone *d = zone->devdata;
int i;
if (d->override_ops && d->override_ops->get_trip_temp)
return d->override_ops->get_trip_temp(zone, trip, temp);
if (trip < d->aux_trip_nr)
*temp = d->aux_trips[trip];
else if (trip == d->crt_trip_id)
......@@ -79,9 +73,6 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
struct int34x_thermal_zone *d = zone->devdata;
int i;
if (d->override_ops && d->override_ops->get_trip_type)
return d->override_ops->get_trip_type(zone, trip, type);
if (trip < d->aux_trip_nr)
*type = THERMAL_TRIP_PASSIVE;
else if (trip == d->crt_trip_id)
......@@ -112,9 +103,6 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
acpi_status status;
char name[10];
if (d->override_ops && d->override_ops->set_trip_temp)
return d->override_ops->set_trip_temp(zone, trip, temp);
snprintf(name, sizeof(name), "PAT%d", trip);
status = acpi_execute_simple_method(d->adev->handle, name,
millicelsius_to_deci_kelvin(temp));
......@@ -134,9 +122,6 @@ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
acpi_status status;
unsigned long long hyst;
if (d->override_ops && d->override_ops->get_trip_hyst)
return d->override_ops->get_trip_hyst(zone, trip, temp);
status = acpi_evaluate_integer(d->adev->handle, "GTSH", NULL, &hyst);
if (ACPI_FAILURE(status))
*temp = 0;
......@@ -217,7 +202,7 @@ static struct thermal_zone_params int340x_thermal_params = {
};
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;
acpi_status status;
......@@ -231,7 +216,16 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
return ERR_PTR(-ENOMEM);
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);
if (ACPI_FAILURE(status))
......@@ -262,7 +256,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
acpi_device_bid(adev),
trip_cnt,
trip_mask, int34x_thermal_zone,
&int340x_thermal_zone_ops,
int34x_thermal_zone->ops,
&int340x_thermal_params,
0, 0);
if (IS_ERR(int34x_thermal_zone->zone)) {
......@@ -281,6 +275,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
kfree(int34x_thermal_zone->aux_trips);
err_trip_alloc:
kfree(int34x_thermal_zone->ops);
err_ops_alloc:
kfree(int34x_thermal_zone);
return ERR_PTR(ret);
}
......@@ -292,6 +288,7 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone
thermal_zone_device_unregister(int34x_thermal_zone->zone);
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
kfree(int34x_thermal_zone->aux_trips);
kfree(int34x_thermal_zone->ops);
kfree(int34x_thermal_zone);
}
EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove);
......
......@@ -29,13 +29,13 @@ struct int34x_thermal_zone {
int hot_temp;
int hot_trip_id;
struct thermal_zone_device *zone;
struct thermal_zone_device_ops *override_ops;
struct thermal_zone_device_ops *ops;
void *priv_data;
struct acpi_lpat_conversion_table *lpat_table;
};
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *,
struct thermal_zone_device_ops *override_ops);
int (*get_temp) (struct thermal_zone_device *, int *));
void int340x_thermal_zone_remove(struct int34x_thermal_zone *);
int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone);
......
......@@ -207,10 +207,6 @@ static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
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)
{
int i;
......@@ -285,7 +281,7 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
struct acpi_device *adev;
acpi_status status;
unsigned long long tmp;
struct thermal_zone_device_ops *ops = NULL;
int (*get_temp) (struct thermal_zone_device *, int *) = NULL;
int ret;
adev = ACPI_COMPANION(dev);
......@@ -304,10 +300,10 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
/* there is no _TMP method, add local method */
stored_tjmax = get_tjmax();
if (stored_tjmax > 0)
ops = &proc_thermal_local_ops;
get_temp = proc_thermal_get_zone_temp;
}
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)) {
return PTR_ERR(proc_priv->int340x_zone);
} else
......
......@@ -53,6 +53,7 @@ struct zone_device {
u32 msr_pkg_therm_high;
struct delayed_work work;
struct thermal_zone_device *tzone;
struct thermal_trip *trips;
struct cpumask cpumask;
};
......@@ -138,40 +139,6 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
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;
if (thres_reg_value)
*temp = zonedev->tj_max - thres_reg_value * 1000;
else
*temp = THERMAL_TEMP_INVALID;
pr_debug("sys_get_trip_temp %d\n", *temp);
return 0;
}
static int
sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
{
......@@ -212,18 +179,9 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
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 */
static struct thermal_zone_device_ops tzone_ops = {
.get_temp = sys_get_curr_temp,
.get_trip_temp = sys_get_trip_temp,
.get_trip_type = sys_get_trip_type,
.set_trip_temp = sys_set_trip_temp,
};
......@@ -323,6 +281,48 @@ static int pkg_thermal_notify(u64 msr_val)
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)
{
int id = topology_logical_die_id(cpu);
......@@ -348,24 +348,27 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
if (!zonedev)
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);
zonedev->cpu = cpu;
zonedev->tj_max = tj_max;
zonedev->tzone = thermal_zone_device_register("x86_pkg_temp",
thres_count,
zonedev->tzone = thermal_zone_device_register_with_trips("x86_pkg_temp",
zonedev->trips, thres_count,
(thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01,
zonedev, &tzone_ops, &pkg_temp_tz_params, 0, 0);
if (IS_ERR(zonedev->tzone)) {
err = PTR_ERR(zonedev->tzone);
kfree(zonedev);
return err;
goto out_kfree_trips;
}
err = thermal_zone_device_enable(zonedev->tzone);
if (err) {
thermal_zone_device_unregister(zonedev->tzone);
kfree(zonedev);
return err;
}
if (err)
goto out_unregister_tz;
/* Store MSR value for package thermal interrupt, to restore at exit */
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low,
zonedev->msr_pkg_therm_high);
......@@ -374,7 +377,16 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
raw_spin_lock_irq(&pkg_temp_lock);
zones[id] = zonedev;
raw_spin_unlock_irq(&pkg_temp_lock);
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)
......@@ -458,8 +470,10 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
raw_spin_unlock_irq(&pkg_temp_lock);
/* Final cleanup if this is the last cpu */
if (lastcpu)
if (lastcpu) {
kfree(zonedev->trips);
kfree(zonedev);
}
return 0;
}
......
......@@ -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);
}
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;
const struct thermal_trip *trip_points;
struct thermal_trip trip;
int ret;
trip_points = of_thermal_get_trip_points(chip->tz_dev);
if (!trip_points)
return -EINVAL;
ret = __thermal_zone_get_trip(chip->tz_dev, trip_id, &trip);
if (ret)
return ret;
if (trip_points[trip].type != THERMAL_TRIP_CRITICAL)
if (trip.type != THERMAL_TRIP_CRITICAL)
return 0;
mutex_lock(&chip->lock);
......@@ -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)
{
int ntrips;
const struct thermal_trip *trips;
int i;
ntrips = of_thermal_get_ntrips(chip->tz_dev);
if (ntrips <= 0)
return THERMAL_TEMP_INVALID;
trips = of_thermal_get_trip_points(chip->tz_dev);
if (!trips)
return THERMAL_TEMP_INVALID;
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;
struct thermal_trip trip;
int i, ret;
for (i = 0; i < thermal_zone_get_num_trips(chip->tz_dev); i++) {
ret = thermal_zone_get_trip(chip->tz_dev, i, &trip);
if (ret)
continue;
if (trip.type == THERMAL_TRIP_CRITICAL)
return trip.temperature;
}
return THERMAL_TEMP_INVALID;
......@@ -353,7 +348,12 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
if (stage)
chip->temp = qpnp_tm_decode_temp(chip, stage);
mutex_unlock(&chip->lock);
crit_temp = qpnp_tm_get_critical_trip_temp(chip);
mutex_lock(&chip->lock);
ret = qpnp_tm_update_critical_trip_temp(chip, crit_temp);
if (ret < 0)
goto out;
......
......@@ -529,7 +529,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
if (ret)
goto error_unregister;
ret = of_thermal_get_ntrips(tsc->zone);
ret = thermal_zone_get_num_trips(tsc->zone);
if (ret < 0)
goto error_unregister;
......
......@@ -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);
}
static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
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 = {
static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
.get_temp = rcar_thermal_get_temp,
};
static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
.get_temp = rcar_thermal_get_temp,
.get_trip_type = rcar_thermal_get_trip_type,
.get_trip_temp = rcar_thermal_get_trip_temp,
static struct thermal_trip trips[] = {
{ .type = THERMAL_TRIP_CRITICAL, .temperature = 90000 }
};
/*
......@@ -529,11 +489,10 @@ static int rcar_thermal_probe(struct platform_device *pdev)
if (chip->use_of_thermal) {
priv->zone = devm_thermal_of_zone_register(
dev, i, priv,
&rcar_thermal_zone_of_ops);
&rcar_thermal_zone_ops);
} else {
priv->zone = thermal_zone_device_register(
"rcar_thermal",
1, 0, priv,
priv->zone = thermal_zone_device_register_with_trips(
"rcar_thermal", trips, ARRAY_SIZE(trips), 0, priv,
&rcar_thermal_zone_ops, NULL, 0,
idle);
......
......@@ -260,31 +260,23 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tzd = data->tzd;
const struct thermal_trip * const trips =
of_thermal_get_trip_points(tzd);
int num_trips = thermal_zone_get_num_trips(tzd);
unsigned int status;
int ret = 0, temp, hyst;
int ret = 0, temp;
if (!trips) {
dev_err(&pdev->dev,
"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) {
ret = thermal_zone_get_crit_temp(tzd, &temp);
if (ret && data->soc != SOC_ARCH_EXYNOS5433) { /* FIXME */
dev_err(&pdev->dev,
"No CRITICAL trip point defined in device tree!\n");
goto out;
}
if (of_thermal_get_ntrips(tzd) > data->ntrip) {
if (num_trips > data->ntrip) {
dev_info(&pdev->dev,
"More trip points than supported by this TMU.\n");
dev_info(&pdev->dev,
"%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);
......@@ -297,25 +289,22 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
ret = -EBUSY;
} else {
int i, ntrips =
min_t(int, of_thermal_get_ntrips(tzd), data->ntrip);
min_t(int, num_trips, data->ntrip);
data->tmu_initialize(pdev);
/* Write temperature code for rising and falling threshold */
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 */
ret = tzd->ops->get_trip_hyst(tzd, i, &hyst);
struct thermal_trip trip;
ret = thermal_zone_get_trip(tzd, i, &trip);
if (ret)
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);
......@@ -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,
int trip, u8 temp)
int trip_id, u8 temp)
{
const struct thermal_trip * const trips =
of_thermal_get_trip_points(data->tzd);
struct thermal_trip trip;
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);
writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
}
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 */
......@@ -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 thermal_zone_device *tz = data->tzd;
struct thermal_trip trip;
unsigned int con, interrupt_en = 0, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) {
for (i = 0; i < data->ntrip; i++) {
if (!of_thermal_is_trip_valid(tz, i))
if (thermal_zone_get_trip(tz, i, &trip))
continue;
interrupt_en |=
......@@ -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 thermal_zone_device *tz = data->tzd;
struct thermal_trip trip;
unsigned int con, interrupt_en = 0, pd_det_en, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) {
for (i = 0; i < data->ntrip; i++) {
if (!of_thermal_is_trip_valid(tz, i))
if (thermal_zone_get_trip(tz, i, &trip))
continue;
interrupt_en |=
......@@ -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 thermal_zone_device *tz = data->tzd;
struct thermal_trip trip;
unsigned int con, interrupt_en = 0, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) {
for (i = 0; i < data->ntrip; i++) {
if (!of_thermal_is_trip_valid(tz, i))
if (thermal_zone_get_trip(tz, i, &trip))
continue;
interrupt_en |=
......
......@@ -134,48 +134,12 @@ static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature)
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 = {
.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,
const struct of_device_id *st_thermal_of_match)
{
......@@ -238,9 +202,12 @@ int st_thermal_register(struct platform_device *pdev,
polling_delay = sensor->ops->register_enable_irq ? 0 : 1000;
trip.temperature = sensor->cdata->crit_temp;
trip.type = THERMAL_TRIP_CRITICAL;
sensor->thermal_dev =
thermal_zone_device_register(dev_name(dev), 1, 0, sensor,
&st_tz_ops, NULL, 0, polling_delay);
thermal_zone_device_register_with_trips(dev_name(dev), &trip, 1, 0, sensor,
&st_tz_ops, NULL, 0, polling_delay);
if (IS_ERR(sensor->thermal_dev)) {
dev_err(dev, "failed to register thermal zone device\n");
ret = PTR_ERR(sensor->thermal_dev);
......
......@@ -582,23 +582,23 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
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_soctherm *ts = zone->ts;
struct thermal_trip trip;
const struct tegra_tsensor_group *sg = zone->sg;
struct device *dev = zone->dev;
enum thermal_trip_type type;
int ret;
if (!tz)
return -EINVAL;
ret = tz->ops->get_trip_type(tz, trip, &type);
ret = __thermal_zone_get_trip(tz, trip_id, &trip);
if (ret)
return ret;
if (type == THERMAL_TRIP_CRITICAL) {
if (trip.type == THERMAL_TRIP_CRITICAL) {
/*
* If thermtrips property is set in DT,
* 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
else
return 0;
} else if (type == THERMAL_TRIP_HOT) {
} else if (trip.type == THERMAL_TRIP_HOT) {
int 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
continue;
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);
else
continue;
......@@ -687,25 +687,20 @@ static const struct thermal_zone_device_ops tegra_of_thermal_ops = {
.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;
enum thermal_trip_type type;
int i, ret;
struct thermal_trip trip;
ntrips = of_thermal_get_ntrips(tz);
if (ntrips <= 0)
return -EINVAL;
for (i = 0; i < thermal_zone_get_num_trips(tz); i++) {
for (i = 0; i < ntrips; i++) {
ret = tz->ops->get_trip_type(tz, i, &type);
ret = thermal_zone_get_trip(tz, i, &trip);
if (ret)
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,
/* Get thermtrips. If missing, try to get critical trips. */
temperature = tsensor_group_thermtrip_get(ts, sg->id);
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;
ret = thermtrip_program(dev, sg, temperature);
......
......@@ -316,18 +316,17 @@ static void tegra_tsensor_get_hw_channel_trips(struct thermal_zone_device *tzd,
*hot_trip = 85000;
*crit_trip = 90000;
for (i = 0; i < tzd->num_trips; i++) {
enum thermal_trip_type type;
int trip_temp;
for (i = 0; i < thermal_zone_get_num_trips(tzd); i++) {
tzd->ops->get_trip_temp(tzd, i, &trip_temp);
tzd->ops->get_trip_type(tzd, i, &type);
struct thermal_trip trip;
if (type == THERMAL_TRIP_HOT)
*hot_trip = trip_temp;
thermal_zone_get_trip(tzd, i, &trip);
if (type == THERMAL_TRIP_CRITICAL)
*crit_trip = trip_temp;
if (trip.type == THERMAL_TRIP_HOT)
*hot_trip = trip.temperature;
if (trip.type == THERMAL_TRIP_CRITICAL)
*crit_trip = trip.temperature;
}
/* clamp hardware trips to the calibration limits */
......
......@@ -344,35 +344,31 @@ static void handle_critical_trips(struct thermal_zone_device *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;
int trip_temp, hyst = 0;
struct thermal_trip trip;
/* Ignore disabled trip points */
if (test_bit(trip, &tz->trips_disabled))
if (test_bit(trip_id, &tz->trips_disabled))
return;
tz->ops->get_trip_temp(tz, trip, &trip_temp);
tz->ops->get_trip_type(tz, trip, &type);
if (tz->ops->get_trip_hyst)
tz->ops->get_trip_hyst(tz, trip, &hyst);
__thermal_zone_get_trip(tz, trip_id, &trip);
if (tz->last_temperature != THERMAL_TEMP_INVALID) {
if (tz->last_temperature < trip_temp &&
tz->temperature >= trip_temp)
thermal_notify_tz_trip_up(tz->id, trip,
if (tz->last_temperature < trip.temperature &&
tz->temperature >= trip.temperature)
thermal_notify_tz_trip_up(tz->id, trip_id,
tz->temperature);
if (tz->last_temperature >= trip_temp &&
tz->temperature < (trip_temp - hyst))
thermal_notify_tz_trip_down(tz->id, trip,
if (tz->last_temperature >= trip.temperature &&
tz->temperature < (trip.temperature - trip.hysteresis))
thermal_notify_tz_trip_down(tz->id, trip_id,
tz->temperature);
}
if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
handle_critical_trips(tz, trip, trip_temp, type);
if (trip.type == THERMAL_TRIP_CRITICAL || trip.type == THERMAL_TRIP_HOT)
handle_critical_trips(tz, trip_id, trip.temperature, trip.type);
else
handle_non_critical_trips(tz, trip);
handle_non_critical_trips(tz, trip_id);
}
static void update_temperature(struct thermal_zone_device *tz)
......@@ -1159,6 +1155,119 @@ static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms
*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
* @type: the thermal zone device type
......@@ -1191,8 +1300,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
int polling_delay)
{
struct thermal_zone_device *tz;
enum thermal_trip_type trip_type;
int trip_temp;
int id;
int result;
int count;
......@@ -1232,7 +1339,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
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);
tz = kzalloc(sizeof(*tz), GFP_KERNEL);
......@@ -1283,9 +1390,10 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
goto release_device;
for (count = 0; count < num_trips; count++) {
if (tz->ops->get_trip_type(tz, count, &trip_type) ||
tz->ops->get_trip_temp(tz, count, &trip_temp) ||
!trip_temp)
struct thermal_trip trip;
result = thermal_zone_get_trip(tz, count, &trip);
if (result)
set_bit(count, &tz->trips_disabled);
}
......
......@@ -114,6 +114,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
/* Helpers */
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);
/* sysfs I/F */
......@@ -137,28 +139,6 @@ thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
#endif /* CONFIG_THERMAL_STATISTICS */
/* 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);
#endif /* __THERMAL_CORE_H__ */
......@@ -83,7 +83,7 @@ int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
int ret = -EINVAL;
int count;
int crit_temp = INT_MAX;
enum thermal_trip_type type;
struct thermal_trip trip;
lockdep_assert_held(&tz->lock);
......@@ -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) {
for (count = 0; count < tz->num_trips; count++) {
ret = tz->ops->get_trip_type(tz, count, &type);
if (!ret && type == THERMAL_TRIP_CRITICAL) {
ret = tz->ops->get_trip_temp(tz, count,
&crit_temp);
ret = __thermal_zone_get_trip(tz, count, &trip);
if (!ret && trip.type == THERMAL_TRIP_CRITICAL) {
crit_temp = trip.temperature;
break;
}
}
......@@ -164,29 +163,30 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
*/
void __thermal_zone_set_trips(struct thermal_zone_device *tz)
{
int low = -INT_MAX;
int high = INT_MAX;
int trip_temp, hysteresis;
struct thermal_trip trip;
int low = -INT_MAX, high = INT_MAX;
int i, ret;
lockdep_assert_held(&tz->lock);
if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
if (!tz->ops->set_trips)
return;
for (i = 0; i < tz->num_trips; i++) {
int trip_low;
tz->ops->get_trip_temp(tz, i, &trip_temp);
tz->ops->get_trip_hyst(tz, i, &hysteresis);
ret = __thermal_zone_get_trip(tz, i , &trip);
if (ret)
return;
trip_low = trip_temp - hysteresis;
trip_low = trip.temperature - trip.hysteresis;
if (trip_low < tz->temperature && trip_low > low)
low = trip_low;
if (trip_temp > tz->temperature && trip_temp < high)
high = trip_temp;
if (trip.temperature > tz->temperature &&
trip.temperature < high)
high = trip.temperature;
}
/* No need to change trip points */
......
......@@ -452,7 +452,8 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p)
struct sk_buff *msg = p->msg;
struct thermal_zone_device *tz;
struct nlattr *start_trip;
int i, id;
struct thermal_trip trip;
int ret, i, id;
if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID])
return -EINVAL;
......@@ -471,18 +472,14 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p)
for (i = 0; i < tz->num_trips; i++) {
enum thermal_trip_type type;
int temp, hyst = 0;
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);
ret = __thermal_zone_get_trip(tz, i, &trip);
if (ret)
goto out_cancel_nest;
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_TEMP, temp) ||
nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, hyst))
nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, trip.type) ||
nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, trip.temperature) ||
nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, trip.hysteresis))
goto out_cancel_nest;
}
......
......@@ -19,117 +19,6 @@
#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 ***/
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,
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->unbind = thermal_of_unbind;
......
......@@ -83,27 +83,25 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
enum thermal_trip_type type;
int trip, result;
struct thermal_trip trip;
int trip_id, result;
if (!tz->ops->get_trip_type)
return -EPERM;
if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
if (sscanf(attr->attr.name, "trip_point_%d_type", &trip_id) != 1)
return -EINVAL;
mutex_lock(&tz->lock);
if (device_is_registered(dev))
result = tz->ops->get_trip_type(tz, trip, &type);
result = __thermal_zone_get_trip(tz, trip_id, &trip);
else
result = -ENODEV;
mutex_unlock(&tz->lock);
if (result)
return result;
switch (type) {
switch (trip.type) {
case THERMAL_TRIP_CRITICAL:
return sprintf(buf, "critical\n");
case THERMAL_TRIP_HOT:
......@@ -122,17 +120,10 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret;
int temperature, hyst = 0;
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;
struct thermal_trip trip;
int trip_id, ret;
if (kstrtoint(buf, 10, &temperature))
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1)
return -EINVAL;
mutex_lock(&tz->lock);
......@@ -142,36 +133,19 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
goto unlock;
}
if (tz->ops->set_trip_temp) {
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);
ret = __thermal_zone_get_trip(tz, trip_id, &trip);
if (ret)
goto unlock;
thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst);
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
ret = kstrtoint(buf, 10, &trip.temperature);
if (ret)
goto unlock;
ret = thermal_zone_set_trip(tz, trip_id, &trip);
unlock:
mutex_unlock(&tz->lock);
if (ret)
return ret;
return count;
return ret ? ret : count;
}
static ssize_t
......@@ -179,19 +153,16 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret;
int temperature;
if (!tz->ops->get_trip_temp)
return -EPERM;
struct thermal_trip trip;
int trip_id, ret;
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;
mutex_lock(&tz->lock);
if (device_is_registered(dev))
ret = tz->ops->get_trip_temp(tz, trip, &temperature);
ret = __thermal_zone_get_trip(tz, trip_id, &trip);
else
ret = -ENODEV;
......@@ -200,7 +171,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if (ret)
return ret;
return sprintf(buf, "%d\n", temperature);
return sprintf(buf, "%d\n", trip.temperature);
}
static ssize_t
......@@ -208,16 +179,13 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret;
int temperature;
if (!tz->ops->set_trip_hyst)
return -EPERM;
struct thermal_trip trip;
int trip_id, ret;
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;
if (kstrtoint(buf, 10, &temperature))
if (kstrtoint(buf, 10, &trip.hysteresis))
return -EINVAL;
mutex_lock(&tz->lock);
......@@ -227,16 +195,11 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
goto unlock;
}
/*
* We are not doing any check on the 'temperature' value
* here. The driver implementing 'set_trip_hyst' has to
* take care of this.
*/
ret = tz->ops->set_trip_hyst(tz, trip, temperature);
if (!ret)
__thermal_zone_set_trips(tz);
ret = __thermal_zone_get_trip(tz, trip_id, &trip);
if (ret)
goto unlock;
ret = thermal_zone_set_trip(tz, trip_id, &trip);
unlock:
mutex_unlock(&tz->lock);
......@@ -248,25 +211,22 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret;
int temperature;
if (!tz->ops->get_trip_hyst)
return -EPERM;
struct thermal_trip trip;
int trip_id, ret;
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;
mutex_lock(&tz->lock);
if (device_is_registered(dev))
ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
ret = __thermal_zone_get_trip(tz, trip_id, &trip);
else
ret = -ENODEV;
mutex_unlock(&tz->lock);
return ret ? ret : sprintf(buf, "%d\n", temperature);
return ret ? ret : sprintf(buf, "%d\n", trip.hysteresis);
}
static ssize_t
......@@ -491,23 +451,20 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
return -ENOMEM;
}
if (tz->ops->get_trip_hyst) {
tz->trip_hyst_attrs = kcalloc(tz->num_trips,
sizeof(*tz->trip_hyst_attrs),
GFP_KERNEL);
if (!tz->trip_hyst_attrs) {
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
return -ENOMEM;
}
tz->trip_hyst_attrs = kcalloc(tz->num_trips,
sizeof(*tz->trip_hyst_attrs),
GFP_KERNEL);
if (!tz->trip_hyst_attrs) {
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
return -ENOMEM;
}
attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
if (!attrs) {
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
if (tz->ops->get_trip_hyst)
kfree(tz->trip_hyst_attrs);
kfree(tz->trip_hyst_attrs);
return -ENOMEM;
}
......@@ -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;
/* create Optional trip hyst attribute */
if (!tz->ops->get_trip_hyst)
continue;
snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
"trip_point_%d_hyst", indx);
......@@ -579,8 +533,7 @@ static void destroy_trip_attrs(struct thermal_zone_device *tz)
kfree(tz->trip_type_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);
}
......
......@@ -38,21 +38,6 @@
/* Update rates */
#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
int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain);
int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id);
......
......@@ -248,8 +248,7 @@ static int uniphier_tm_probe(struct platform_device *pdev)
struct regmap *regmap;
struct device_node *parent;
struct uniphier_tm_dev *tdev;
const struct thermal_trip *trips;
int i, ret, irq, ntrips, crit_temp = INT_MAX;
int i, ret, irq, crit_temp = INT_MAX;
tdev = devm_kzalloc(dev, sizeof(*tdev), GFP_KERNEL);
if (!tdev)
......@@ -296,20 +295,18 @@ static int uniphier_tm_probe(struct platform_device *pdev)
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 */
for (i = 0; i < ntrips; i++) {
if (trips[i].type == THERMAL_TRIP_CRITICAL &&
trips[i].temperature < crit_temp)
crit_temp = trips[i].temperature;
uniphier_tm_set_alert(tdev, i, trips[i].temperature);
for (i = 0; i < thermal_zone_get_num_trips(tdev->tz_dev); i++) {
struct thermal_trip trip;
ret = thermal_zone_get_trip(tdev->tz_dev, i, &trip);
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;
}
if (crit_temp > CRITICAL_TEMP_LIMIT) {
......
......@@ -334,6 +334,18 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev,
}
#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
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
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