mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui: "The top merge commit was re-generated yesterday because two topic branches were dropped from this pull request in the last minute due to some unaddressed comments. All the other material has been in linux-next for quite a while. Specifics: - Enhance thermal core to handle unexpected device cooling states after fresh boot and system resume. From Zhang Rui and Chen Yu. - Several fixes and cleanups on Rockchip and RCAR thermal drivers. From Caesar Wang and Kuninori Morimoto. - Add Broxton support for Intel processor thermal reporting device driver. From Amy Wiles" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: thermal: trip_point_temp_store() calls thermal_zone_device_update() thermal: rcar: rcar_thermal_get_temp() return error if strange temp thermal: rcar: check irq possibility in rcar_thermal_irq_xxx() thermal: rcar: check every rcar_thermal_update_temp() return value thermal: rcar: move rcar_thermal_dt_ids to upside thermal: rockchip: Support the RK3399 SoCs in thermal driver thermal: rockchip: Support the RK3228 SoCs in thermal driver dt-bindings: rockchip-thermal: Support the RK3228/RK3399 SoCs compatible thermal: rockchip: fix a trivial typo Thermal: Enable Broxton SoC thermal reporting device thermal: constify pch_dev_ops structure Thermal: do thermal zone update after a cooling device registered Thermal: handle thermal zone device properly during system sleep Thermal: initialize thermal zone device correctly
This commit is contained in:
commit
81f05fee8c
@ -2,8 +2,10 @@
|
||||
|
||||
Required properties:
|
||||
- compatible : should be "rockchip,<name>-tsadc"
|
||||
"rockchip,rk3228-tsadc": found on RK3228 SoCs
|
||||
"rockchip,rk3288-tsadc": found on RK3288 SoCs
|
||||
"rockchip,rk3368-tsadc": found on RK3368 SoCs
|
||||
"rockchip,rk3399-tsadc": found on RK3399 SoCs
|
||||
- reg : physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts : The interrupt number to the cpu. The interrupt specifier format
|
||||
|
@ -33,6 +33,12 @@
|
||||
/* Braswell thermal reporting device */
|
||||
#define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC
|
||||
|
||||
/* Broxton thermal reporting device */
|
||||
#define PCI_DEVICE_ID_PROC_BXT0_THERMAL 0x0A8C
|
||||
#define PCI_DEVICE_ID_PROC_BXT1_THERMAL 0x1A8C
|
||||
#define PCI_DEVICE_ID_PROC_BXTX_THERMAL 0x4A8C
|
||||
#define PCI_DEVICE_ID_PROC_BXTP_THERMAL 0x5A8C
|
||||
|
||||
struct power_config {
|
||||
u32 index;
|
||||
u32 min_uw;
|
||||
@ -404,6 +410,10 @@ static const struct pci_device_id proc_thermal_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_SKL_THERMAL)},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT0_THERMAL)},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT1_THERMAL)},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)},
|
||||
{ 0, },
|
||||
};
|
||||
|
||||
|
@ -136,7 +136,7 @@ struct pch_dev_ops {
|
||||
|
||||
|
||||
/* dev ops for Wildcat Point */
|
||||
static struct pch_dev_ops pch_dev_ops_wpt = {
|
||||
static const struct pch_dev_ops pch_dev_ops_wpt = {
|
||||
.hw_init = pch_wpt_init,
|
||||
.get_temp = pch_wpt_get_temp,
|
||||
};
|
||||
|
@ -75,11 +75,11 @@ struct rcar_thermal_priv {
|
||||
#define rcar_has_irq_support(priv) ((priv)->common->base)
|
||||
#define rcar_id_to_shift(priv) ((priv)->id * 8)
|
||||
|
||||
#ifdef DEBUG
|
||||
# define rcar_force_update_temp(priv) 1
|
||||
#else
|
||||
# define rcar_force_update_temp(priv) 0
|
||||
#endif
|
||||
static const struct of_device_id rcar_thermal_dt_ids[] = {
|
||||
{ .compatible = "renesas,rcar-thermal", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
|
||||
|
||||
/*
|
||||
* basic functions
|
||||
@ -203,14 +203,26 @@ err_out_unlock:
|
||||
static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
|
||||
{
|
||||
struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
|
||||
int tmp;
|
||||
int ret;
|
||||
|
||||
if (!rcar_has_irq_support(priv) || rcar_force_update_temp(priv))
|
||||
rcar_thermal_update_temp(priv);
|
||||
ret = rcar_thermal_update_temp(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
*temp = MCELSIUS((priv->ctemp * 5) - 65);
|
||||
tmp = MCELSIUS((priv->ctemp * 5) - 65);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
if ((tmp < MCELSIUS(-45)) || (tmp > MCELSIUS(125))) {
|
||||
struct device *dev = rcar_priv_to_dev(priv);
|
||||
|
||||
dev_err(dev, "it couldn't measure temperature correctly\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
*temp = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -288,6 +300,9 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)
|
||||
unsigned long flags;
|
||||
u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */
|
||||
|
||||
if (!rcar_has_irq_support(priv))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&common->lock, flags);
|
||||
|
||||
rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask);
|
||||
@ -299,11 +314,15 @@ static void rcar_thermal_work(struct work_struct *work)
|
||||
{
|
||||
struct rcar_thermal_priv *priv;
|
||||
int cctemp, nctemp;
|
||||
int ret;
|
||||
|
||||
priv = container_of(work, struct rcar_thermal_priv, work.work);
|
||||
|
||||
rcar_thermal_get_temp(priv->zone, &cctemp);
|
||||
rcar_thermal_update_temp(priv);
|
||||
ret = rcar_thermal_update_temp(priv);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
rcar_thermal_irq_enable(priv);
|
||||
|
||||
rcar_thermal_get_temp(priv->zone, &nctemp);
|
||||
@ -368,8 +387,7 @@ static int rcar_thermal_remove(struct platform_device *pdev)
|
||||
struct rcar_thermal_priv *priv;
|
||||
|
||||
rcar_thermal_for_each_priv(priv, common) {
|
||||
if (rcar_has_irq_support(priv))
|
||||
rcar_thermal_irq_disable(priv);
|
||||
rcar_thermal_irq_disable(priv);
|
||||
thermal_zone_device_unregister(priv->zone);
|
||||
}
|
||||
|
||||
@ -441,7 +459,9 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
mutex_init(&priv->lock);
|
||||
INIT_LIST_HEAD(&priv->list);
|
||||
INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
|
||||
rcar_thermal_update_temp(priv);
|
||||
ret = rcar_thermal_update_temp(priv);
|
||||
if (ret < 0)
|
||||
goto error_unregister;
|
||||
|
||||
priv->zone = thermal_zone_device_register("rcar_thermal",
|
||||
1, 0, priv,
|
||||
@ -453,8 +473,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
goto error_unregister;
|
||||
}
|
||||
|
||||
if (rcar_has_irq_support(priv))
|
||||
rcar_thermal_irq_enable(priv);
|
||||
rcar_thermal_irq_enable(priv);
|
||||
|
||||
list_move_tail(&priv->list, &common->head);
|
||||
|
||||
@ -484,12 +503,6 @@ error_unregister:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id rcar_thermal_dt_ids[] = {
|
||||
{ .compatible = "renesas,rcar-thermal", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
|
||||
|
||||
static struct platform_driver rcar_thermal_driver = {
|
||||
.driver = {
|
||||
.name = "rcar_thermal",
|
||||
|
@ -38,7 +38,7 @@ enum tshut_mode {
|
||||
};
|
||||
|
||||
/**
|
||||
* the system Temperature Sensors tshut(tshut) polarity
|
||||
* The system Temperature Sensors tshut(tshut) polarity
|
||||
* the bit 8 is tshut polarity.
|
||||
* 0: low active, 1: high active
|
||||
*/
|
||||
@ -57,10 +57,10 @@ enum sensor_id {
|
||||
};
|
||||
|
||||
/**
|
||||
* The conversion table has the adc value and temperature.
|
||||
* ADC_DECREMENT is the adc value decremnet.(e.g. v2_code_table)
|
||||
* ADC_INCREMNET is the adc value incremnet.(e.g. v3_code_table)
|
||||
*/
|
||||
* The conversion table has the adc value and temperature.
|
||||
* ADC_DECREMENT: the adc value is of diminishing.(e.g. v2_code_table)
|
||||
* ADC_INCREMENT: the adc value is incremental.(e.g. v3_code_table)
|
||||
*/
|
||||
enum adc_sort_mode {
|
||||
ADC_DECREMENT = 0,
|
||||
ADC_INCREMENT,
|
||||
@ -72,16 +72,17 @@ enum adc_sort_mode {
|
||||
*/
|
||||
#define SOC_MAX_SENSORS 2
|
||||
|
||||
/**
|
||||
* struct chip_tsadc_table: hold information about chip-specific differences
|
||||
* @id: conversion table
|
||||
* @length: size of conversion table
|
||||
* @data_mask: mask to apply on data inputs
|
||||
* @mode: sort mode of this adc variant (incrementing or decrementing)
|
||||
*/
|
||||
struct chip_tsadc_table {
|
||||
const struct tsadc_table *id;
|
||||
|
||||
/* the array table size*/
|
||||
unsigned int length;
|
||||
|
||||
/* that analogic mask data */
|
||||
u32 data_mask;
|
||||
|
||||
/* the sort mode is adc value that increment or decrement in table */
|
||||
enum adc_sort_mode mode;
|
||||
};
|
||||
|
||||
@ -153,6 +154,7 @@ struct rockchip_thermal_data {
|
||||
#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))
|
||||
#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))
|
||||
|
||||
#define TSADCV1_INT_PD_CLEAR_MASK ~BIT(16)
|
||||
#define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8)
|
||||
|
||||
#define TSADCV2_DATA_MASK 0xfff
|
||||
@ -168,6 +170,51 @@ struct tsadc_table {
|
||||
int temp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Note:
|
||||
* Code to Temperature mapping of the Temperature sensor is a piece wise linear
|
||||
* curve.Any temperature, code faling between to 2 give temperatures can be
|
||||
* linearly interpolated.
|
||||
* Code to Temperature mapping should be updated based on sillcon results.
|
||||
*/
|
||||
static const struct tsadc_table v1_code_table[] = {
|
||||
{TSADCV3_DATA_MASK, -40000},
|
||||
{436, -40000},
|
||||
{431, -35000},
|
||||
{426, -30000},
|
||||
{421, -25000},
|
||||
{416, -20000},
|
||||
{411, -15000},
|
||||
{406, -10000},
|
||||
{401, -5000},
|
||||
{395, 0},
|
||||
{390, 5000},
|
||||
{385, 10000},
|
||||
{380, 15000},
|
||||
{375, 20000},
|
||||
{370, 25000},
|
||||
{364, 30000},
|
||||
{359, 35000},
|
||||
{354, 40000},
|
||||
{349, 45000},
|
||||
{343, 50000},
|
||||
{338, 55000},
|
||||
{333, 60000},
|
||||
{328, 65000},
|
||||
{322, 70000},
|
||||
{317, 75000},
|
||||
{312, 80000},
|
||||
{307, 85000},
|
||||
{301, 90000},
|
||||
{296, 95000},
|
||||
{291, 100000},
|
||||
{286, 105000},
|
||||
{280, 110000},
|
||||
{275, 115000},
|
||||
{270, 120000},
|
||||
{264, 125000},
|
||||
};
|
||||
|
||||
static const struct tsadc_table v2_code_table[] = {
|
||||
{TSADCV2_DATA_MASK, -40000},
|
||||
{3800, -40000},
|
||||
@ -245,6 +292,44 @@ static const struct tsadc_table v3_code_table[] = {
|
||||
{TSADCV3_DATA_MASK, 125000},
|
||||
};
|
||||
|
||||
static const struct tsadc_table v4_code_table[] = {
|
||||
{TSADCV3_DATA_MASK, -40000},
|
||||
{431, -40000},
|
||||
{426, -35000},
|
||||
{421, -30000},
|
||||
{415, -25000},
|
||||
{410, -20000},
|
||||
{405, -15000},
|
||||
{399, -10000},
|
||||
{394, -5000},
|
||||
{389, 0},
|
||||
{383, 5000},
|
||||
{378, 10000},
|
||||
{373, 15000},
|
||||
{367, 20000},
|
||||
{362, 25000},
|
||||
{357, 30000},
|
||||
{351, 35000},
|
||||
{346, 40000},
|
||||
{340, 45000},
|
||||
{335, 50000},
|
||||
{330, 55000},
|
||||
{324, 60000},
|
||||
{319, 65000},
|
||||
{313, 70000},
|
||||
{308, 75000},
|
||||
{302, 80000},
|
||||
{297, 85000},
|
||||
{291, 90000},
|
||||
{286, 95000},
|
||||
{281, 100000},
|
||||
{275, 105000},
|
||||
{270, 110000},
|
||||
{264, 115000},
|
||||
{259, 120000},
|
||||
{253, 125000},
|
||||
};
|
||||
|
||||
static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table,
|
||||
int temp)
|
||||
{
|
||||
@ -368,6 +453,14 @@ static void rk_tsadcv2_initialize(void __iomem *regs,
|
||||
regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
|
||||
}
|
||||
|
||||
static void rk_tsadcv1_irq_ack(void __iomem *regs)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(regs + TSADCV2_INT_PD);
|
||||
writel_relaxed(val & TSADCV1_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
|
||||
}
|
||||
|
||||
static void rk_tsadcv2_irq_ack(void __iomem *regs)
|
||||
{
|
||||
u32 val;
|
||||
@ -429,6 +522,29 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
|
||||
writel_relaxed(val, regs + TSADCV2_INT_EN);
|
||||
}
|
||||
|
||||
static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
|
||||
.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
|
||||
.chn_num = 1, /* one channel for tsadc */
|
||||
|
||||
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
|
||||
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
|
||||
.tshut_temp = 95000,
|
||||
|
||||
.initialize = rk_tsadcv2_initialize,
|
||||
.irq_ack = rk_tsadcv1_irq_ack,
|
||||
.control = rk_tsadcv2_control,
|
||||
.get_temp = rk_tsadcv2_get_temp,
|
||||
.set_tshut_temp = rk_tsadcv2_tshut_temp,
|
||||
.set_tshut_mode = rk_tsadcv2_tshut_mode,
|
||||
|
||||
.table = {
|
||||
.id = v1_code_table,
|
||||
.length = ARRAY_SIZE(v1_code_table),
|
||||
.data_mask = TSADCV3_DATA_MASK,
|
||||
.mode = ADC_DECREMENT,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
|
||||
.chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */
|
||||
.chn_id[SENSOR_GPU] = 2, /* gpu sensor is channel 2 */
|
||||
@ -477,7 +593,35 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
|
||||
.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
|
||||
.chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
|
||||
.chn_num = 2, /* two channels for tsadc */
|
||||
|
||||
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
|
||||
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
|
||||
.tshut_temp = 95000,
|
||||
|
||||
.initialize = rk_tsadcv2_initialize,
|
||||
.irq_ack = rk_tsadcv1_irq_ack,
|
||||
.control = rk_tsadcv2_control,
|
||||
.get_temp = rk_tsadcv2_get_temp,
|
||||
.set_tshut_temp = rk_tsadcv2_tshut_temp,
|
||||
.set_tshut_mode = rk_tsadcv2_tshut_mode,
|
||||
|
||||
.table = {
|
||||
.id = v4_code_table,
|
||||
.length = ARRAY_SIZE(v4_code_table),
|
||||
.data_mask = TSADCV3_DATA_MASK,
|
||||
.mode = ADC_DECREMENT,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id of_rockchip_thermal_match[] = {
|
||||
{
|
||||
.compatible = "rockchip,rk3228-tsadc",
|
||||
.data = (void *)&rk3228_tsadc_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3288-tsadc",
|
||||
.data = (void *)&rk3288_tsadc_data,
|
||||
@ -486,6 +630,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
|
||||
.compatible = "rockchip,rk3368-tsadc",
|
||||
.data = (void *)&rk3368_tsadc_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3399-tsadc",
|
||||
.data = (void *)&rk3399_tsadc_data,
|
||||
},
|
||||
{ /* end */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
|
||||
@ -617,7 +765,7 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Reset TSADC Controller, reset all tsadc registers.
|
||||
*/
|
||||
static void rockchip_thermal_reset_controller(struct reset_control *reset)
|
||||
|
@ -63,6 +63,19 @@ static unsigned long get_target_state(struct thermal_instance *instance,
|
||||
next_target = instance->target;
|
||||
dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
|
||||
|
||||
if (!instance->initialized) {
|
||||
if (throttle) {
|
||||
next_target = (cur_state + 1) >= instance->upper ?
|
||||
instance->upper :
|
||||
((cur_state + 1) < instance->lower ?
|
||||
instance->lower : (cur_state + 1));
|
||||
} else {
|
||||
next_target = THERMAL_NO_TARGET;
|
||||
}
|
||||
|
||||
return next_target;
|
||||
}
|
||||
|
||||
switch (trend) {
|
||||
case THERMAL_TREND_RAISING:
|
||||
if (throttle) {
|
||||
@ -149,7 +162,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
|
||||
dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
|
||||
old_target, (int)instance->target);
|
||||
|
||||
if (old_target == instance->target)
|
||||
if (instance->initialized && old_target == instance->target)
|
||||
continue;
|
||||
|
||||
/* Activate a passive thermal instance */
|
||||
@ -161,7 +174,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
|
||||
instance->target == THERMAL_NO_TARGET)
|
||||
update_passive_instance(tz, trip_type, -1);
|
||||
|
||||
|
||||
instance->initialized = true;
|
||||
instance->cdev->updated = false; /* cdev needs update */
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/thermal.h>
|
||||
@ -59,6 +60,8 @@ static LIST_HEAD(thermal_governor_list);
|
||||
static DEFINE_MUTEX(thermal_list_lock);
|
||||
static DEFINE_MUTEX(thermal_governor_lock);
|
||||
|
||||
static atomic_t in_suspend;
|
||||
|
||||
static struct thermal_governor *def_governor;
|
||||
|
||||
static struct thermal_governor *__find_governor(const char *name)
|
||||
@ -532,14 +535,31 @@ static void update_temperature(struct thermal_zone_device *tz)
|
||||
mutex_unlock(&tz->lock);
|
||||
|
||||
trace_thermal_temperature(tz);
|
||||
dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
|
||||
tz->last_temperature, tz->temperature);
|
||||
if (tz->last_temperature == THERMAL_TEMP_INVALID)
|
||||
dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n",
|
||||
tz->temperature);
|
||||
else
|
||||
dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
|
||||
tz->last_temperature, tz->temperature);
|
||||
}
|
||||
|
||||
static void thermal_zone_device_reset(struct thermal_zone_device *tz)
|
||||
{
|
||||
struct thermal_instance *pos;
|
||||
|
||||
tz->temperature = THERMAL_TEMP_INVALID;
|
||||
tz->passive = 0;
|
||||
list_for_each_entry(pos, &tz->thermal_instances, tz_node)
|
||||
pos->initialized = false;
|
||||
}
|
||||
|
||||
void thermal_zone_device_update(struct thermal_zone_device *tz)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (atomic_read(&in_suspend))
|
||||
return;
|
||||
|
||||
if (!tz->ops->get_temp)
|
||||
return;
|
||||
|
||||
@ -676,8 +696,12 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
|
||||
ret = tz->ops->set_trip_temp(tz, trip, temperature);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret ? ret : count;
|
||||
thermal_zone_device_update(tz);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -1321,6 +1345,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
|
||||
if (!result) {
|
||||
list_add_tail(&dev->tz_node, &tz->thermal_instances);
|
||||
list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
|
||||
atomic_set(&tz->need_update, 1);
|
||||
}
|
||||
mutex_unlock(&cdev->lock);
|
||||
mutex_unlock(&tz->lock);
|
||||
@ -1430,6 +1455,7 @@ __thermal_cooling_device_register(struct device_node *np,
|
||||
const struct thermal_cooling_device_ops *ops)
|
||||
{
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct thermal_zone_device *pos = NULL;
|
||||
int result;
|
||||
|
||||
if (type && strlen(type) >= THERMAL_NAME_LENGTH)
|
||||
@ -1474,6 +1500,12 @@ __thermal_cooling_device_register(struct device_node *np,
|
||||
/* Update binding information for 'this' new cdev */
|
||||
bind_cdev(cdev);
|
||||
|
||||
mutex_lock(&thermal_list_lock);
|
||||
list_for_each_entry(pos, &thermal_tz_list, node)
|
||||
if (atomic_cmpxchg(&pos->need_update, 1, 0))
|
||||
thermal_zone_device_update(pos);
|
||||
mutex_unlock(&thermal_list_lock);
|
||||
|
||||
return cdev;
|
||||
}
|
||||
|
||||
@ -1806,6 +1838,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
|
||||
tz->trips = trips;
|
||||
tz->passive_delay = passive_delay;
|
||||
tz->polling_delay = polling_delay;
|
||||
/* A new thermal zone needs to be updated anyway. */
|
||||
atomic_set(&tz->need_update, 1);
|
||||
|
||||
dev_set_name(&tz->device, "thermal_zone%d", tz->id);
|
||||
result = device_register(&tz->device);
|
||||
@ -1900,7 +1934,10 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
|
||||
|
||||
INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
|
||||
|
||||
thermal_zone_device_update(tz);
|
||||
thermal_zone_device_reset(tz);
|
||||
/* Update the new thermal zone and mark it as already updated. */
|
||||
if (atomic_cmpxchg(&tz->need_update, 1, 0))
|
||||
thermal_zone_device_update(tz);
|
||||
|
||||
return tz;
|
||||
|
||||
@ -2140,6 +2177,36 @@ static void thermal_unregister_governors(void)
|
||||
thermal_gov_power_allocator_unregister();
|
||||
}
|
||||
|
||||
static int thermal_pm_notify(struct notifier_block *nb,
|
||||
unsigned long mode, void *_unused)
|
||||
{
|
||||
struct thermal_zone_device *tz;
|
||||
|
||||
switch (mode) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_RESTORE_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
atomic_set(&in_suspend, 1);
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_RESTORE:
|
||||
case PM_POST_SUSPEND:
|
||||
atomic_set(&in_suspend, 0);
|
||||
list_for_each_entry(tz, &thermal_tz_list, node) {
|
||||
thermal_zone_device_reset(tz);
|
||||
thermal_zone_device_update(tz);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block thermal_pm_nb = {
|
||||
.notifier_call = thermal_pm_notify,
|
||||
};
|
||||
|
||||
static int __init thermal_init(void)
|
||||
{
|
||||
int result;
|
||||
@ -2160,6 +2227,11 @@ static int __init thermal_init(void)
|
||||
if (result)
|
||||
goto exit_netlink;
|
||||
|
||||
result = register_pm_notifier(&thermal_pm_nb);
|
||||
if (result)
|
||||
pr_warn("Thermal: Can not register suspend notifier, return %d\n",
|
||||
result);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_netlink:
|
||||
@ -2179,6 +2251,7 @@ error:
|
||||
|
||||
static void __exit thermal_exit(void)
|
||||
{
|
||||
unregister_pm_notifier(&thermal_pm_nb);
|
||||
of_thermal_destroy_zones();
|
||||
genetlink_exit();
|
||||
class_unregister(&thermal_class);
|
||||
|
@ -41,6 +41,7 @@ struct thermal_instance {
|
||||
struct thermal_zone_device *tz;
|
||||
struct thermal_cooling_device *cdev;
|
||||
int trip;
|
||||
bool initialized;
|
||||
unsigned long upper; /* Highest cooling state for this trip point */
|
||||
unsigned long lower; /* Lowest cooling state for this trip point */
|
||||
unsigned long target; /* expected cooling state */
|
||||
|
@ -43,6 +43,9 @@
|
||||
/* Default weight of a bound cooling device */
|
||||
#define THERMAL_WEIGHT_DEFAULT 0
|
||||
|
||||
/* use value, which < 0K, to indicate an invalid/uninitialized temperature */
|
||||
#define THERMAL_TEMP_INVALID -274000
|
||||
|
||||
/* Unit conversion macros */
|
||||
#define DECI_KELVIN_TO_CELSIUS(t) ({ \
|
||||
long _t = (t); \
|
||||
@ -167,6 +170,7 @@ struct thermal_attr {
|
||||
* @forced_passive: If > 0, temperature at which to switch on all ACPI
|
||||
* processor cooling devices. Currently only used by the
|
||||
* step-wise governor.
|
||||
* @need_update: if equals 1, thermal_zone_device_update needs to be invoked.
|
||||
* @ops: operations this &thermal_zone_device supports
|
||||
* @tzp: thermal zone parameters
|
||||
* @governor: pointer to the governor for this thermal zone
|
||||
@ -194,6 +198,7 @@ struct thermal_zone_device {
|
||||
int emul_temperature;
|
||||
int passive;
|
||||
unsigned int forced_passive;
|
||||
atomic_t need_update;
|
||||
struct thermal_zone_device_ops *ops;
|
||||
struct thermal_zone_params *tzp;
|
||||
struct thermal_governor *governor;
|
||||
|
Loading…
Reference in New Issue
Block a user