Commit 81f05fee authored by Linus Torvalds's avatar Linus Torvalds

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
parents c52cb431 98d94507
...@@ -2,8 +2,10 @@ ...@@ -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
......
...@@ -33,6 +33,12 @@ ...@@ -33,6 +33,12 @@
/* Braswell thermal reporting device */ /* Braswell thermal reporting device */
#define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC #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 { struct power_config {
u32 index; u32 index;
u32 min_uw; u32 min_uw;
...@@ -404,6 +410,10 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { ...@@ -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_HSB_THERMAL)},
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_SKL_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_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, }, { 0, },
}; };
......
...@@ -136,7 +136,7 @@ struct pch_dev_ops { ...@@ -136,7 +136,7 @@ struct pch_dev_ops {
/* dev ops for Wildcat Point */ /* 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, .hw_init = pch_wpt_init,
.get_temp = pch_wpt_get_temp, .get_temp = pch_wpt_get_temp,
}; };
......
...@@ -75,11 +75,11 @@ struct rcar_thermal_priv { ...@@ -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 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) ...@@ -203,14 +203,26 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
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) ...@@ -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) ...@@ -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,7 +387,6 @@ static int rcar_thermal_remove(struct platform_device *pdev) ...@@ -368,7 +387,6 @@ 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) ...@@ -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,7 +473,6 @@ static int rcar_thermal_probe(struct platform_device *pdev) ...@@ -453,7 +473,6 @@ 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 @@ static int rcar_thermal_probe(struct platform_device *pdev) ...@@ -484,12 +503,6 @@ static int rcar_thermal_probe(struct platform_device *pdev)
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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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[] = { ...@@ -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, ...@@ -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, ...@@ -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 = { ...@@ -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[] = { ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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); ...@@ -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) ...@@ -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);
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", dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
tz->last_temperature, tz->temperature); 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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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,6 +1934,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, ...@@ -1900,6 +1934,9 @@ 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_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); thermal_zone_device_update(tz);
return tz; return tz;
...@@ -2140,6 +2177,36 @@ static void thermal_unregister_governors(void) ...@@ -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) ...@@ -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 @@ static int __init thermal_init(void) ...@@ -2179,6 +2251,7 @@ static int __init thermal_init(void)
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 { ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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;
......
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