Merge branches 'thermal-intel', 'thermal-suspend-fix' and 'thermal-soc' into next
This commit is contained in:
commit
98d94507e1
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : should be "rockchip,<name>-tsadc"
|
- compatible : should be "rockchip,<name>-tsadc"
|
||||||
|
"rockchip,rk3228-tsadc": found on RK3228 SoCs
|
||||||
"rockchip,rk3288-tsadc": found on RK3288 SoCs
|
"rockchip,rk3288-tsadc": found on RK3288 SoCs
|
||||||
"rockchip,rk3368-tsadc": found on RK3368 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
|
- reg : physical base address of the controller and length of memory mapped
|
||||||
region.
|
region.
|
||||||
- interrupts : The interrupt number to the cpu. The interrupt specifier format
|
- interrupts : The interrupt number to the cpu. The interrupt specifier format
|
||||||
|
@ -75,11 +75,11 @@ struct rcar_thermal_priv {
|
|||||||
#define rcar_has_irq_support(priv) ((priv)->common->base)
|
#define rcar_has_irq_support(priv) ((priv)->common->base)
|
||||||
#define rcar_id_to_shift(priv) ((priv)->id * 8)
|
#define rcar_id_to_shift(priv) ((priv)->id * 8)
|
||||||
|
|
||||||
#ifdef DEBUG
|
static const struct of_device_id rcar_thermal_dt_ids[] = {
|
||||||
# define rcar_force_update_temp(priv) 1
|
{ .compatible = "renesas,rcar-thermal", },
|
||||||
#else
|
{},
|
||||||
# define rcar_force_update_temp(priv) 0
|
};
|
||||||
#endif
|
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* basic functions
|
* basic functions
|
||||||
@ -203,14 +203,26 @@ err_out_unlock:
|
|||||||
static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
|
static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
|
||||||
{
|
{
|
||||||
struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
|
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))
|
ret = rcar_thermal_update_temp(priv);
|
||||||
rcar_thermal_update_temp(priv);
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
mutex_lock(&priv->lock);
|
mutex_lock(&priv->lock);
|
||||||
*temp = MCELSIUS((priv->ctemp * 5) - 65);
|
tmp = MCELSIUS((priv->ctemp * 5) - 65);
|
||||||
mutex_unlock(&priv->lock);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,6 +300,9 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */
|
u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */
|
||||||
|
|
||||||
|
if (!rcar_has_irq_support(priv))
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&common->lock, flags);
|
spin_lock_irqsave(&common->lock, flags);
|
||||||
|
|
||||||
rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask);
|
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;
|
struct rcar_thermal_priv *priv;
|
||||||
int cctemp, nctemp;
|
int cctemp, nctemp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
priv = container_of(work, struct rcar_thermal_priv, work.work);
|
priv = container_of(work, struct rcar_thermal_priv, work.work);
|
||||||
|
|
||||||
rcar_thermal_get_temp(priv->zone, &cctemp);
|
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_irq_enable(priv);
|
||||||
|
|
||||||
rcar_thermal_get_temp(priv->zone, &nctemp);
|
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;
|
struct rcar_thermal_priv *priv;
|
||||||
|
|
||||||
rcar_thermal_for_each_priv(priv, common) {
|
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);
|
thermal_zone_device_unregister(priv->zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,7 +459,9 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
|||||||
mutex_init(&priv->lock);
|
mutex_init(&priv->lock);
|
||||||
INIT_LIST_HEAD(&priv->list);
|
INIT_LIST_HEAD(&priv->list);
|
||||||
INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
|
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",
|
priv->zone = thermal_zone_device_register("rcar_thermal",
|
||||||
1, 0, priv,
|
1, 0, priv,
|
||||||
@ -453,8 +473,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
|||||||
goto error_unregister;
|
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);
|
list_move_tail(&priv->list, &common->head);
|
||||||
|
|
||||||
@ -484,12 +503,6 @@ error_unregister:
|
|||||||
return ret;
|
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 = {
|
static struct platform_driver rcar_thermal_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "rcar_thermal",
|
.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.
|
* the bit 8 is tshut polarity.
|
||||||
* 0: low active, 1: high active
|
* 0: low active, 1: high active
|
||||||
*/
|
*/
|
||||||
@ -57,10 +57,10 @@ enum sensor_id {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The conversion table has the adc value and temperature.
|
* The conversion table has the adc value and temperature.
|
||||||
* ADC_DECREMENT is the adc value decremnet.(e.g. v2_code_table)
|
* ADC_DECREMENT: the adc value is of diminishing.(e.g. v2_code_table)
|
||||||
* ADC_INCREMNET is the adc value incremnet.(e.g. v3_code_table)
|
* ADC_INCREMENT: the adc value is incremental.(e.g. v3_code_table)
|
||||||
*/
|
*/
|
||||||
enum adc_sort_mode {
|
enum adc_sort_mode {
|
||||||
ADC_DECREMENT = 0,
|
ADC_DECREMENT = 0,
|
||||||
ADC_INCREMENT,
|
ADC_INCREMENT,
|
||||||
@ -72,16 +72,17 @@ enum adc_sort_mode {
|
|||||||
*/
|
*/
|
||||||
#define SOC_MAX_SENSORS 2
|
#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 {
|
struct chip_tsadc_table {
|
||||||
const struct tsadc_table *id;
|
const struct tsadc_table *id;
|
||||||
|
|
||||||
/* the array table size*/
|
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
|
|
||||||
/* that analogic mask data */
|
|
||||||
u32 data_mask;
|
u32 data_mask;
|
||||||
|
|
||||||
/* the sort mode is adc value that increment or decrement in table */
|
|
||||||
enum adc_sort_mode mode;
|
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_2GPIO_SRC_EN(chn) BIT(4 + (chn))
|
||||||
#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (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_INT_PD_CLEAR_MASK ~BIT(8)
|
||||||
|
|
||||||
#define TSADCV2_DATA_MASK 0xfff
|
#define TSADCV2_DATA_MASK 0xfff
|
||||||
@ -168,6 +170,51 @@ struct tsadc_table {
|
|||||||
int temp;
|
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[] = {
|
static const struct tsadc_table v2_code_table[] = {
|
||||||
{TSADCV2_DATA_MASK, -40000},
|
{TSADCV2_DATA_MASK, -40000},
|
||||||
{3800, -40000},
|
{3800, -40000},
|
||||||
@ -245,6 +292,44 @@ static const struct tsadc_table v3_code_table[] = {
|
|||||||
{TSADCV3_DATA_MASK, 125000},
|
{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,
|
static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table,
|
||||||
int temp)
|
int temp)
|
||||||
{
|
{
|
||||||
@ -368,6 +453,14 @@ static void rk_tsadcv2_initialize(void __iomem *regs,
|
|||||||
regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
|
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)
|
static void rk_tsadcv2_irq_ack(void __iomem *regs)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
@ -429,6 +522,29 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
|
|||||||
writel_relaxed(val, regs + TSADCV2_INT_EN);
|
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 = {
|
static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
|
||||||
.chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */
|
.chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */
|
||||||
.chn_id[SENSOR_GPU] = 2, /* gpu sensor is channel 2 */
|
.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[] = {
|
static const struct of_device_id of_rockchip_thermal_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,rk3228-tsadc",
|
||||||
|
.data = (void *)&rk3228_tsadc_data,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.compatible = "rockchip,rk3288-tsadc",
|
.compatible = "rockchip,rk3288-tsadc",
|
||||||
.data = (void *)&rk3288_tsadc_data,
|
.data = (void *)&rk3288_tsadc_data,
|
||||||
@ -486,6 +630,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
|
|||||||
.compatible = "rockchip,rk3368-tsadc",
|
.compatible = "rockchip,rk3368-tsadc",
|
||||||
.data = (void *)&rk3368_tsadc_data,
|
.data = (void *)&rk3368_tsadc_data,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,rk3399-tsadc",
|
||||||
|
.data = (void *)&rk3399_tsadc_data,
|
||||||
|
},
|
||||||
{ /* end */ },
|
{ /* end */ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
|
MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
|
||||||
@ -617,7 +765,7 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Reset TSADC Controller, reset all tsadc registers.
|
* Reset TSADC Controller, reset all tsadc registers.
|
||||||
*/
|
*/
|
||||||
static void rockchip_thermal_reset_controller(struct reset_control *reset)
|
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;
|
next_target = instance->target;
|
||||||
dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
|
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) {
|
switch (trend) {
|
||||||
case THERMAL_TREND_RAISING:
|
case THERMAL_TREND_RAISING:
|
||||||
if (throttle) {
|
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",
|
dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
|
||||||
old_target, (int)instance->target);
|
old_target, (int)instance->target);
|
||||||
|
|
||||||
if (old_target == instance->target)
|
if (instance->initialized && old_target == instance->target)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Activate a passive thermal instance */
|
/* 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)
|
instance->target == THERMAL_NO_TARGET)
|
||||||
update_passive_instance(tz, trip_type, -1);
|
update_passive_instance(tz, trip_type, -1);
|
||||||
|
|
||||||
|
instance->initialized = true;
|
||||||
instance->cdev->updated = false; /* cdev needs update */
|
instance->cdev->updated = false; /* cdev needs update */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <net/netlink.h>
|
#include <net/netlink.h>
|
||||||
#include <net/genetlink.h>
|
#include <net/genetlink.h>
|
||||||
|
#include <linux/suspend.h>
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/thermal.h>
|
#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_list_lock);
|
||||||
static DEFINE_MUTEX(thermal_governor_lock);
|
static DEFINE_MUTEX(thermal_governor_lock);
|
||||||
|
|
||||||
|
static atomic_t in_suspend;
|
||||||
|
|
||||||
static struct thermal_governor *def_governor;
|
static struct thermal_governor *def_governor;
|
||||||
|
|
||||||
static struct thermal_governor *__find_governor(const char *name)
|
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);
|
mutex_unlock(&tz->lock);
|
||||||
|
|
||||||
trace_thermal_temperature(tz);
|
trace_thermal_temperature(tz);
|
||||||
dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
|
if (tz->last_temperature == THERMAL_TEMP_INVALID)
|
||||||
tz->last_temperature, tz->temperature);
|
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)
|
void thermal_zone_device_update(struct thermal_zone_device *tz)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
|
if (atomic_read(&in_suspend))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!tz->ops->get_temp)
|
if (!tz->ops->get_temp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -676,8 +696,12 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = tz->ops->set_trip_temp(tz, trip, temperature);
|
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
|
static ssize_t
|
||||||
@ -1321,6 +1345,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
|
|||||||
if (!result) {
|
if (!result) {
|
||||||
list_add_tail(&dev->tz_node, &tz->thermal_instances);
|
list_add_tail(&dev->tz_node, &tz->thermal_instances);
|
||||||
list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
|
list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
|
||||||
|
atomic_set(&tz->need_update, 1);
|
||||||
}
|
}
|
||||||
mutex_unlock(&cdev->lock);
|
mutex_unlock(&cdev->lock);
|
||||||
mutex_unlock(&tz->lock);
|
mutex_unlock(&tz->lock);
|
||||||
@ -1430,6 +1455,7 @@ __thermal_cooling_device_register(struct device_node *np,
|
|||||||
const struct thermal_cooling_device_ops *ops)
|
const struct thermal_cooling_device_ops *ops)
|
||||||
{
|
{
|
||||||
struct thermal_cooling_device *cdev;
|
struct thermal_cooling_device *cdev;
|
||||||
|
struct thermal_zone_device *pos = NULL;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (type && strlen(type) >= THERMAL_NAME_LENGTH)
|
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 */
|
/* Update binding information for 'this' new cdev */
|
||||||
bind_cdev(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;
|
return cdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1806,6 +1838,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
|
|||||||
tz->trips = trips;
|
tz->trips = trips;
|
||||||
tz->passive_delay = passive_delay;
|
tz->passive_delay = passive_delay;
|
||||||
tz->polling_delay = polling_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);
|
dev_set_name(&tz->device, "thermal_zone%d", tz->id);
|
||||||
result = device_register(&tz->device);
|
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);
|
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;
|
return tz;
|
||||||
|
|
||||||
@ -2140,6 +2177,36 @@ static void thermal_unregister_governors(void)
|
|||||||
thermal_gov_power_allocator_unregister();
|
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)
|
static int __init thermal_init(void)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@ -2160,6 +2227,11 @@ static int __init thermal_init(void)
|
|||||||
if (result)
|
if (result)
|
||||||
goto exit_netlink;
|
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;
|
return 0;
|
||||||
|
|
||||||
exit_netlink:
|
exit_netlink:
|
||||||
@ -2179,6 +2251,7 @@ error:
|
|||||||
|
|
||||||
static void __exit thermal_exit(void)
|
static void __exit thermal_exit(void)
|
||||||
{
|
{
|
||||||
|
unregister_pm_notifier(&thermal_pm_nb);
|
||||||
of_thermal_destroy_zones();
|
of_thermal_destroy_zones();
|
||||||
genetlink_exit();
|
genetlink_exit();
|
||||||
class_unregister(&thermal_class);
|
class_unregister(&thermal_class);
|
||||||
|
@ -41,6 +41,7 @@ struct thermal_instance {
|
|||||||
struct thermal_zone_device *tz;
|
struct thermal_zone_device *tz;
|
||||||
struct thermal_cooling_device *cdev;
|
struct thermal_cooling_device *cdev;
|
||||||
int trip;
|
int trip;
|
||||||
|
bool initialized;
|
||||||
unsigned long upper; /* Highest cooling state for this trip point */
|
unsigned long upper; /* Highest cooling state for this trip point */
|
||||||
unsigned long lower; /* Lowest cooling state for this trip point */
|
unsigned long lower; /* Lowest cooling state for this trip point */
|
||||||
unsigned long target; /* expected cooling state */
|
unsigned long target; /* expected cooling state */
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
/* Default weight of a bound cooling device */
|
/* Default weight of a bound cooling device */
|
||||||
#define THERMAL_WEIGHT_DEFAULT 0
|
#define THERMAL_WEIGHT_DEFAULT 0
|
||||||
|
|
||||||
|
/* use value, which < 0K, to indicate an invalid/uninitialized temperature */
|
||||||
|
#define THERMAL_TEMP_INVALID -274000
|
||||||
|
|
||||||
/* Unit conversion macros */
|
/* Unit conversion macros */
|
||||||
#define DECI_KELVIN_TO_CELSIUS(t) ({ \
|
#define DECI_KELVIN_TO_CELSIUS(t) ({ \
|
||||||
long _t = (t); \
|
long _t = (t); \
|
||||||
@ -167,6 +170,7 @@ struct thermal_attr {
|
|||||||
* @forced_passive: If > 0, temperature at which to switch on all ACPI
|
* @forced_passive: If > 0, temperature at which to switch on all ACPI
|
||||||
* processor cooling devices. Currently only used by the
|
* processor cooling devices. Currently only used by the
|
||||||
* step-wise governor.
|
* step-wise governor.
|
||||||
|
* @need_update: if equals 1, thermal_zone_device_update needs to be invoked.
|
||||||
* @ops: operations this &thermal_zone_device supports
|
* @ops: operations this &thermal_zone_device supports
|
||||||
* @tzp: thermal zone parameters
|
* @tzp: thermal zone parameters
|
||||||
* @governor: pointer to the governor for this thermal zone
|
* @governor: pointer to the governor for this thermal zone
|
||||||
@ -194,6 +198,7 @@ struct thermal_zone_device {
|
|||||||
int emul_temperature;
|
int emul_temperature;
|
||||||
int passive;
|
int passive;
|
||||||
unsigned int forced_passive;
|
unsigned int forced_passive;
|
||||||
|
atomic_t need_update;
|
||||||
struct thermal_zone_device_ops *ops;
|
struct thermal_zone_device_ops *ops;
|
||||||
struct thermal_zone_params *tzp;
|
struct thermal_zone_params *tzp;
|
||||||
struct thermal_governor *governor;
|
struct thermal_governor *governor;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user