diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-24 15:43:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-24 15:43:06 -0500 |
commit | 81f05fee8c063cfc1614ddba1ce88cb1129f263d (patch) | |
tree | 3a2d305e26011f87f1ace81b70361bdb4a8d1898 | |
parent | c52cb4311f20538fcb69420e55a19ac622546a08 (diff) | |
parent | 98d94507e10c3c0a5cfc1c3ac4df23e761f1b874 (diff) |
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
-rw-r--r-- | Documentation/devicetree/bindings/thermal/rockchip-thermal.txt | 2 | ||||
-rw-r--r-- | drivers/thermal/int340x_thermal/processor_thermal_device.c | 10 | ||||
-rw-r--r-- | drivers/thermal/intel_pch_thermal.c | 2 | ||||
-rw-r--r-- | drivers/thermal/rcar_thermal.c | 53 | ||||
-rw-r--r-- | drivers/thermal/rockchip_thermal.c | 172 | ||||
-rw-r--r-- | drivers/thermal/step_wise.c | 17 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.c | 81 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.h | 1 | ||||
-rw-r--r-- | include/linux/thermal.h | 5 |
9 files changed, 304 insertions, 39 deletions
diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt index 0dfa60d88dd3..08efe6bc2193 100644 --- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt | |||
@@ -2,8 +2,10 @@ | |||
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible : should be "rockchip,<name>-tsadc" | 4 | - compatible : should be "rockchip,<name>-tsadc" |
5 | "rockchip,rk3228-tsadc": found on RK3228 SoCs | ||
5 | "rockchip,rk3288-tsadc": found on RK3288 SoCs | 6 | "rockchip,rk3288-tsadc": found on RK3288 SoCs |
6 | "rockchip,rk3368-tsadc": found on RK3368 SoCs | 7 | "rockchip,rk3368-tsadc": found on RK3368 SoCs |
8 | "rockchip,rk3399-tsadc": found on RK3399 SoCs | ||
7 | - reg : physical base address of the controller and length of memory mapped | 9 | - reg : physical base address of the controller and length of memory mapped |
8 | region. | 10 | region. |
9 | - interrupts : The interrupt number to the cpu. The interrupt specifier format | 11 | - interrupts : The interrupt number to the cpu. The interrupt specifier format |
diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c index ccc0ad02d066..36fa724a36c8 100644 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c | |||
@@ -33,6 +33,12 @@ | |||
33 | /* Braswell thermal reporting device */ | 33 | /* Braswell thermal reporting device */ |
34 | #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC | 34 | #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC |
35 | 35 | ||
36 | /* Broxton thermal reporting device */ | ||
37 | #define PCI_DEVICE_ID_PROC_BXT0_THERMAL 0x0A8C | ||
38 | #define PCI_DEVICE_ID_PROC_BXT1_THERMAL 0x1A8C | ||
39 | #define PCI_DEVICE_ID_PROC_BXTX_THERMAL 0x4A8C | ||
40 | #define PCI_DEVICE_ID_PROC_BXTP_THERMAL 0x5A8C | ||
41 | |||
36 | struct power_config { | 42 | struct power_config { |
37 | u32 index; | 43 | u32 index; |
38 | u32 min_uw; | 44 | u32 min_uw; |
@@ -404,6 +410,10 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { | |||
404 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)}, | 410 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)}, |
405 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_SKL_THERMAL)}, | 411 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_SKL_THERMAL)}, |
406 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)}, | 412 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)}, |
413 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT0_THERMAL)}, | ||
414 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT1_THERMAL)}, | ||
415 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, | ||
416 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, | ||
407 | { 0, }, | 417 | { 0, }, |
408 | }; | 418 | }; |
409 | 419 | ||
diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c index 50c7da79be83..00d81af648b8 100644 --- a/drivers/thermal/intel_pch_thermal.c +++ b/drivers/thermal/intel_pch_thermal.c | |||
@@ -136,7 +136,7 @@ struct pch_dev_ops { | |||
136 | 136 | ||
137 | 137 | ||
138 | /* dev ops for Wildcat Point */ | 138 | /* dev ops for Wildcat Point */ |
139 | static struct pch_dev_ops pch_dev_ops_wpt = { | 139 | static const struct pch_dev_ops pch_dev_ops_wpt = { |
140 | .hw_init = pch_wpt_init, | 140 | .hw_init = pch_wpt_init, |
141 | .get_temp = pch_wpt_get_temp, | 141 | .get_temp = pch_wpt_get_temp, |
142 | }; | 142 | }; |
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 13d01edc7a04..44b9c485157d 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c | |||
@@ -75,11 +75,11 @@ struct rcar_thermal_priv { | |||
75 | #define rcar_has_irq_support(priv) ((priv)->common->base) | 75 | #define rcar_has_irq_support(priv) ((priv)->common->base) |
76 | #define rcar_id_to_shift(priv) ((priv)->id * 8) | 76 | #define rcar_id_to_shift(priv) ((priv)->id * 8) |
77 | 77 | ||
78 | #ifdef DEBUG | 78 | static const struct of_device_id rcar_thermal_dt_ids[] = { |
79 | # define rcar_force_update_temp(priv) 1 | 79 | { .compatible = "renesas,rcar-thermal", }, |
80 | #else | 80 | {}, |
81 | # define rcar_force_update_temp(priv) 0 | 81 | }; |
82 | #endif | 82 | MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * basic functions | 85 | * basic functions |
@@ -203,14 +203,26 @@ err_out_unlock: | |||
203 | static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) | 203 | static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) |
204 | { | 204 | { |
205 | struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); | 205 | struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); |
206 | int tmp; | ||
207 | int ret; | ||
206 | 208 | ||
207 | if (!rcar_has_irq_support(priv) || rcar_force_update_temp(priv)) | 209 | ret = rcar_thermal_update_temp(priv); |
208 | rcar_thermal_update_temp(priv); | 210 | if (ret < 0) |
211 | return ret; | ||
209 | 212 | ||
210 | mutex_lock(&priv->lock); | 213 | mutex_lock(&priv->lock); |
211 | *temp = MCELSIUS((priv->ctemp * 5) - 65); | 214 | tmp = MCELSIUS((priv->ctemp * 5) - 65); |
212 | mutex_unlock(&priv->lock); | 215 | mutex_unlock(&priv->lock); |
213 | 216 | ||
217 | if ((tmp < MCELSIUS(-45)) || (tmp > MCELSIUS(125))) { | ||
218 | struct device *dev = rcar_priv_to_dev(priv); | ||
219 | |||
220 | dev_err(dev, "it couldn't measure temperature correctly\n"); | ||
221 | return -EIO; | ||
222 | } | ||
223 | |||
224 | *temp = tmp; | ||
225 | |||
214 | return 0; | 226 | return 0; |
215 | } | 227 | } |
216 | 228 | ||
@@ -288,6 +300,9 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable) | |||
288 | unsigned long flags; | 300 | unsigned long flags; |
289 | u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */ | 301 | u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */ |
290 | 302 | ||
303 | if (!rcar_has_irq_support(priv)) | ||
304 | return; | ||
305 | |||
291 | spin_lock_irqsave(&common->lock, flags); | 306 | spin_lock_irqsave(&common->lock, flags); |
292 | 307 | ||
293 | rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask); | 308 | rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask); |
@@ -299,11 +314,15 @@ static void rcar_thermal_work(struct work_struct *work) | |||
299 | { | 314 | { |
300 | struct rcar_thermal_priv *priv; | 315 | struct rcar_thermal_priv *priv; |
301 | int cctemp, nctemp; | 316 | int cctemp, nctemp; |
317 | int ret; | ||
302 | 318 | ||
303 | priv = container_of(work, struct rcar_thermal_priv, work.work); | 319 | priv = container_of(work, struct rcar_thermal_priv, work.work); |
304 | 320 | ||
305 | rcar_thermal_get_temp(priv->zone, &cctemp); | 321 | rcar_thermal_get_temp(priv->zone, &cctemp); |
306 | rcar_thermal_update_temp(priv); | 322 | ret = rcar_thermal_update_temp(priv); |
323 | if (ret < 0) | ||
324 | return; | ||
325 | |||
307 | rcar_thermal_irq_enable(priv); | 326 | rcar_thermal_irq_enable(priv); |
308 | 327 | ||
309 | rcar_thermal_get_temp(priv->zone, &nctemp); | 328 | rcar_thermal_get_temp(priv->zone, &nctemp); |
@@ -368,8 +387,7 @@ static int rcar_thermal_remove(struct platform_device *pdev) | |||
368 | struct rcar_thermal_priv *priv; | 387 | struct rcar_thermal_priv *priv; |
369 | 388 | ||
370 | rcar_thermal_for_each_priv(priv, common) { | 389 | rcar_thermal_for_each_priv(priv, common) { |
371 | if (rcar_has_irq_support(priv)) | 390 | rcar_thermal_irq_disable(priv); |
372 | rcar_thermal_irq_disable(priv); | ||
373 | thermal_zone_device_unregister(priv->zone); | 391 | thermal_zone_device_unregister(priv->zone); |
374 | } | 392 | } |
375 | 393 | ||
@@ -441,7 +459,9 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
441 | mutex_init(&priv->lock); | 459 | mutex_init(&priv->lock); |
442 | INIT_LIST_HEAD(&priv->list); | 460 | INIT_LIST_HEAD(&priv->list); |
443 | INIT_DELAYED_WORK(&priv->work, rcar_thermal_work); | 461 | INIT_DELAYED_WORK(&priv->work, rcar_thermal_work); |
444 | rcar_thermal_update_temp(priv); | 462 | ret = rcar_thermal_update_temp(priv); |
463 | if (ret < 0) | ||
464 | goto error_unregister; | ||
445 | 465 | ||
446 | priv->zone = thermal_zone_device_register("rcar_thermal", | 466 | priv->zone = thermal_zone_device_register("rcar_thermal", |
447 | 1, 0, priv, | 467 | 1, 0, priv, |
@@ -453,8 +473,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
453 | goto error_unregister; | 473 | goto error_unregister; |
454 | } | 474 | } |
455 | 475 | ||
456 | if (rcar_has_irq_support(priv)) | 476 | rcar_thermal_irq_enable(priv); |
457 | rcar_thermal_irq_enable(priv); | ||
458 | 477 | ||
459 | list_move_tail(&priv->list, &common->head); | 478 | list_move_tail(&priv->list, &common->head); |
460 | 479 | ||
@@ -484,12 +503,6 @@ error_unregister: | |||
484 | return ret; | 503 | return ret; |
485 | } | 504 | } |
486 | 505 | ||
487 | static const struct of_device_id rcar_thermal_dt_ids[] = { | ||
488 | { .compatible = "renesas,rcar-thermal", }, | ||
489 | {}, | ||
490 | }; | ||
491 | MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); | ||
492 | |||
493 | static struct platform_driver rcar_thermal_driver = { | 506 | static struct platform_driver rcar_thermal_driver = { |
494 | .driver = { | 507 | .driver = { |
495 | .name = "rcar_thermal", | 508 | .name = "rcar_thermal", |
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index e845841ab036..b58e3fb9b311 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c | |||
@@ -38,7 +38,7 @@ enum tshut_mode { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | /** | 40 | /** |
41 | * the system Temperature Sensors tshut(tshut) polarity | 41 | * The system Temperature Sensors tshut(tshut) polarity |
42 | * the bit 8 is tshut polarity. | 42 | * the bit 8 is tshut polarity. |
43 | * 0: low active, 1: high active | 43 | * 0: low active, 1: high active |
44 | */ | 44 | */ |
@@ -57,10 +57,10 @@ enum sensor_id { | |||
57 | }; | 57 | }; |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * The conversion table has the adc value and temperature. | 60 | * The conversion table has the adc value and temperature. |
61 | * ADC_DECREMENT is the adc value decremnet.(e.g. v2_code_table) | 61 | * ADC_DECREMENT: the adc value is of diminishing.(e.g. v2_code_table) |
62 | * ADC_INCREMNET is the adc value incremnet.(e.g. v3_code_table) | 62 | * ADC_INCREMENT: the adc value is incremental.(e.g. v3_code_table) |
63 | */ | 63 | */ |
64 | enum adc_sort_mode { | 64 | enum adc_sort_mode { |
65 | ADC_DECREMENT = 0, | 65 | ADC_DECREMENT = 0, |
66 | ADC_INCREMENT, | 66 | ADC_INCREMENT, |
@@ -72,16 +72,17 @@ enum adc_sort_mode { | |||
72 | */ | 72 | */ |
73 | #define SOC_MAX_SENSORS 2 | 73 | #define SOC_MAX_SENSORS 2 |
74 | 74 | ||
75 | /** | ||
76 | * struct chip_tsadc_table: hold information about chip-specific differences | ||
77 | * @id: conversion table | ||
78 | * @length: size of conversion table | ||
79 | * @data_mask: mask to apply on data inputs | ||
80 | * @mode: sort mode of this adc variant (incrementing or decrementing) | ||
81 | */ | ||
75 | struct chip_tsadc_table { | 82 | struct chip_tsadc_table { |
76 | const struct tsadc_table *id; | 83 | const struct tsadc_table *id; |
77 | |||
78 | /* the array table size*/ | ||
79 | unsigned int length; | 84 | unsigned int length; |
80 | |||
81 | /* that analogic mask data */ | ||
82 | u32 data_mask; | 85 | u32 data_mask; |
83 | |||
84 | /* the sort mode is adc value that increment or decrement in table */ | ||
85 | enum adc_sort_mode mode; | 86 | enum adc_sort_mode mode; |
86 | }; | 87 | }; |
87 | 88 | ||
@@ -153,6 +154,7 @@ struct rockchip_thermal_data { | |||
153 | #define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn)) | 154 | #define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn)) |
154 | #define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn)) | 155 | #define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn)) |
155 | 156 | ||
157 | #define TSADCV1_INT_PD_CLEAR_MASK ~BIT(16) | ||
156 | #define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8) | 158 | #define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8) |
157 | 159 | ||
158 | #define TSADCV2_DATA_MASK 0xfff | 160 | #define TSADCV2_DATA_MASK 0xfff |
@@ -168,6 +170,51 @@ struct tsadc_table { | |||
168 | int temp; | 170 | int temp; |
169 | }; | 171 | }; |
170 | 172 | ||
173 | /** | ||
174 | * Note: | ||
175 | * Code to Temperature mapping of the Temperature sensor is a piece wise linear | ||
176 | * curve.Any temperature, code faling between to 2 give temperatures can be | ||
177 | * linearly interpolated. | ||
178 | * Code to Temperature mapping should be updated based on sillcon results. | ||
179 | */ | ||
180 | static const struct tsadc_table v1_code_table[] = { | ||
181 | {TSADCV3_DATA_MASK, -40000}, | ||
182 | {436, -40000}, | ||
183 | {431, -35000}, | ||
184 | {426, -30000}, | ||
185 | {421, -25000}, | ||
186 | {416, -20000}, | ||
187 | {411, -15000}, | ||
188 | {406, -10000}, | ||
189 | {401, -5000}, | ||
190 | {395, 0}, | ||
191 | {390, 5000}, | ||
192 | {385, 10000}, | ||
193 | {380, 15000}, | ||
194 | {375, 20000}, | ||
195 | {370, 25000}, | ||
196 | {364, 30000}, | ||
197 | {359, 35000}, | ||
198 | {354, 40000}, | ||
199 | {349, 45000}, | ||
200 | {343, 50000}, | ||
201 | {338, 55000}, | ||
202 | {333, 60000}, | ||
203 | {328, 65000}, | ||
204 | {322, 70000}, | ||
205 | {317, 75000}, | ||
206 | {312, 80000}, | ||
207 | {307, 85000}, | ||
208 | {301, 90000}, | ||
209 | {296, 95000}, | ||
210 | {291, 100000}, | ||
211 | {286, 105000}, | ||
212 | {280, 110000}, | ||
213 | {275, 115000}, | ||
214 | {270, 120000}, | ||
215 | {264, 125000}, | ||
216 | }; | ||
217 | |||
171 | static const struct tsadc_table v2_code_table[] = { | 218 | static const struct tsadc_table v2_code_table[] = { |
172 | {TSADCV2_DATA_MASK, -40000}, | 219 | {TSADCV2_DATA_MASK, -40000}, |
173 | {3800, -40000}, | 220 | {3800, -40000}, |
@@ -245,6 +292,44 @@ static const struct tsadc_table v3_code_table[] = { | |||
245 | {TSADCV3_DATA_MASK, 125000}, | 292 | {TSADCV3_DATA_MASK, 125000}, |
246 | }; | 293 | }; |
247 | 294 | ||
295 | static const struct tsadc_table v4_code_table[] = { | ||
296 | {TSADCV3_DATA_MASK, -40000}, | ||
297 | {431, -40000}, | ||
298 | {426, -35000}, | ||
299 | {421, -30000}, | ||
300 | {415, -25000}, | ||
301 | {410, -20000}, | ||
302 | {405, -15000}, | ||
303 | {399, -10000}, | ||
304 | {394, -5000}, | ||
305 | {389, 0}, | ||
306 | {383, 5000}, | ||
307 | {378, 10000}, | ||
308 | {373, 15000}, | ||
309 | {367, 20000}, | ||
310 | {362, 25000}, | ||
311 | {357, 30000}, | ||
312 | {351, 35000}, | ||
313 | {346, 40000}, | ||
314 | {340, 45000}, | ||
315 | {335, 50000}, | ||
316 | {330, 55000}, | ||
317 | {324, 60000}, | ||
318 | {319, 65000}, | ||
319 | {313, 70000}, | ||
320 | {308, 75000}, | ||
321 | {302, 80000}, | ||
322 | {297, 85000}, | ||
323 | {291, 90000}, | ||
324 | {286, 95000}, | ||
325 | {281, 100000}, | ||
326 | {275, 105000}, | ||
327 | {270, 110000}, | ||
328 | {264, 115000}, | ||
329 | {259, 120000}, | ||
330 | {253, 125000}, | ||
331 | }; | ||
332 | |||
248 | static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, | 333 | static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, |
249 | int temp) | 334 | int temp) |
250 | { | 335 | { |
@@ -368,6 +453,14 @@ static void rk_tsadcv2_initialize(void __iomem *regs, | |||
368 | regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); | 453 | regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); |
369 | } | 454 | } |
370 | 455 | ||
456 | static void rk_tsadcv1_irq_ack(void __iomem *regs) | ||
457 | { | ||
458 | u32 val; | ||
459 | |||
460 | val = readl_relaxed(regs + TSADCV2_INT_PD); | ||
461 | writel_relaxed(val & TSADCV1_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); | ||
462 | } | ||
463 | |||
371 | static void rk_tsadcv2_irq_ack(void __iomem *regs) | 464 | static void rk_tsadcv2_irq_ack(void __iomem *regs) |
372 | { | 465 | { |
373 | u32 val; | 466 | u32 val; |
@@ -429,6 +522,29 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, | |||
429 | writel_relaxed(val, regs + TSADCV2_INT_EN); | 522 | writel_relaxed(val, regs + TSADCV2_INT_EN); |
430 | } | 523 | } |
431 | 524 | ||
525 | static const struct rockchip_tsadc_chip rk3228_tsadc_data = { | ||
526 | .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ | ||
527 | .chn_num = 1, /* one channel for tsadc */ | ||
528 | |||
529 | .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ | ||
530 | .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ | ||
531 | .tshut_temp = 95000, | ||
532 | |||
533 | .initialize = rk_tsadcv2_initialize, | ||
534 | .irq_ack = rk_tsadcv1_irq_ack, | ||
535 | .control = rk_tsadcv2_control, | ||
536 | .get_temp = rk_tsadcv2_get_temp, | ||
537 | .set_tshut_temp = rk_tsadcv2_tshut_temp, | ||
538 | .set_tshut_mode = rk_tsadcv2_tshut_mode, | ||
539 | |||
540 | .table = { | ||
541 | .id = v1_code_table, | ||
542 | .length = ARRAY_SIZE(v1_code_table), | ||
543 | .data_mask = TSADCV3_DATA_MASK, | ||
544 | .mode = ADC_DECREMENT, | ||
545 | }, | ||
546 | }; | ||
547 | |||
432 | static const struct rockchip_tsadc_chip rk3288_tsadc_data = { | 548 | static const struct rockchip_tsadc_chip rk3288_tsadc_data = { |
433 | .chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */ | 549 | .chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */ |
434 | .chn_id[SENSOR_GPU] = 2, /* gpu sensor is channel 2 */ | 550 | .chn_id[SENSOR_GPU] = 2, /* gpu sensor is channel 2 */ |
@@ -477,8 +593,36 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = { | |||
477 | }, | 593 | }, |
478 | }; | 594 | }; |
479 | 595 | ||
596 | static const struct rockchip_tsadc_chip rk3399_tsadc_data = { | ||
597 | .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ | ||
598 | .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ | ||
599 | .chn_num = 2, /* two channels for tsadc */ | ||
600 | |||
601 | .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ | ||
602 | .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ | ||
603 | .tshut_temp = 95000, | ||
604 | |||
605 | .initialize = rk_tsadcv2_initialize, | ||
606 | .irq_ack = rk_tsadcv1_irq_ack, | ||
607 | .control = rk_tsadcv2_control, | ||
608 | .get_temp = rk_tsadcv2_get_temp, | ||
609 | .set_tshut_temp = rk_tsadcv2_tshut_temp, | ||
610 | .set_tshut_mode = rk_tsadcv2_tshut_mode, | ||
611 | |||
612 | .table = { | ||
613 | .id = v4_code_table, | ||
614 | .length = ARRAY_SIZE(v4_code_table), | ||
615 | .data_mask = TSADCV3_DATA_MASK, | ||
616 | .mode = ADC_DECREMENT, | ||
617 | }, | ||
618 | }; | ||
619 | |||
480 | static const struct of_device_id of_rockchip_thermal_match[] = { | 620 | static const struct of_device_id of_rockchip_thermal_match[] = { |
481 | { | 621 | { |
622 | .compatible = "rockchip,rk3228-tsadc", | ||
623 | .data = (void *)&rk3228_tsadc_data, | ||
624 | }, | ||
625 | { | ||
482 | .compatible = "rockchip,rk3288-tsadc", | 626 | .compatible = "rockchip,rk3288-tsadc", |
483 | .data = (void *)&rk3288_tsadc_data, | 627 | .data = (void *)&rk3288_tsadc_data, |
484 | }, | 628 | }, |
@@ -486,6 +630,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = { | |||
486 | .compatible = "rockchip,rk3368-tsadc", | 630 | .compatible = "rockchip,rk3368-tsadc", |
487 | .data = (void *)&rk3368_tsadc_data, | 631 | .data = (void *)&rk3368_tsadc_data, |
488 | }, | 632 | }, |
633 | { | ||
634 | .compatible = "rockchip,rk3399-tsadc", | ||
635 | .data = (void *)&rk3399_tsadc_data, | ||
636 | }, | ||
489 | { /* end */ }, | 637 | { /* end */ }, |
490 | }; | 638 | }; |
491 | MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match); | 639 | MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match); |
@@ -617,7 +765,7 @@ rockchip_thermal_register_sensor(struct platform_device *pdev, | |||
617 | return 0; | 765 | return 0; |
618 | } | 766 | } |
619 | 767 | ||
620 | /* | 768 | /** |
621 | * Reset TSADC Controller, reset all tsadc registers. | 769 | * Reset TSADC Controller, reset all tsadc registers. |
622 | */ | 770 | */ |
623 | static void rockchip_thermal_reset_controller(struct reset_control *reset) | 771 | static void rockchip_thermal_reset_controller(struct reset_control *reset) |
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c index 2f9f7086ac3d..ea9366ad3e6b 100644 --- a/drivers/thermal/step_wise.c +++ b/drivers/thermal/step_wise.c | |||
@@ -63,6 +63,19 @@ static unsigned long get_target_state(struct thermal_instance *instance, | |||
63 | next_target = instance->target; | 63 | next_target = instance->target; |
64 | dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state); | 64 | dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state); |
65 | 65 | ||
66 | if (!instance->initialized) { | ||
67 | if (throttle) { | ||
68 | next_target = (cur_state + 1) >= instance->upper ? | ||
69 | instance->upper : | ||
70 | ((cur_state + 1) < instance->lower ? | ||
71 | instance->lower : (cur_state + 1)); | ||
72 | } else { | ||
73 | next_target = THERMAL_NO_TARGET; | ||
74 | } | ||
75 | |||
76 | return next_target; | ||
77 | } | ||
78 | |||
66 | switch (trend) { | 79 | switch (trend) { |
67 | case THERMAL_TREND_RAISING: | 80 | case THERMAL_TREND_RAISING: |
68 | if (throttle) { | 81 | if (throttle) { |
@@ -149,7 +162,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) | |||
149 | dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", | 162 | dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", |
150 | old_target, (int)instance->target); | 163 | old_target, (int)instance->target); |
151 | 164 | ||
152 | if (old_target == instance->target) | 165 | if (instance->initialized && old_target == instance->target) |
153 | continue; | 166 | continue; |
154 | 167 | ||
155 | /* Activate a passive thermal instance */ | 168 | /* Activate a passive thermal instance */ |
@@ -161,7 +174,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) | |||
161 | instance->target == THERMAL_NO_TARGET) | 174 | instance->target == THERMAL_NO_TARGET) |
162 | update_passive_instance(tz, trip_type, -1); | 175 | update_passive_instance(tz, trip_type, -1); |
163 | 176 | ||
164 | 177 | instance->initialized = true; | |
165 | instance->cdev->updated = false; /* cdev needs update */ | 178 | instance->cdev->updated = false; /* cdev needs update */ |
166 | } | 179 | } |
167 | 180 | ||
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d9e525cc9c1c..a0a8fd1235e2 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
38 | #include <net/netlink.h> | 38 | #include <net/netlink.h> |
39 | #include <net/genetlink.h> | 39 | #include <net/genetlink.h> |
40 | #include <linux/suspend.h> | ||
40 | 41 | ||
41 | #define CREATE_TRACE_POINTS | 42 | #define CREATE_TRACE_POINTS |
42 | #include <trace/events/thermal.h> | 43 | #include <trace/events/thermal.h> |
@@ -59,6 +60,8 @@ static LIST_HEAD(thermal_governor_list); | |||
59 | static DEFINE_MUTEX(thermal_list_lock); | 60 | static DEFINE_MUTEX(thermal_list_lock); |
60 | static DEFINE_MUTEX(thermal_governor_lock); | 61 | static DEFINE_MUTEX(thermal_governor_lock); |
61 | 62 | ||
63 | static atomic_t in_suspend; | ||
64 | |||
62 | static struct thermal_governor *def_governor; | 65 | static struct thermal_governor *def_governor; |
63 | 66 | ||
64 | static struct thermal_governor *__find_governor(const char *name) | 67 | static struct thermal_governor *__find_governor(const char *name) |
@@ -532,14 +535,31 @@ static void update_temperature(struct thermal_zone_device *tz) | |||
532 | mutex_unlock(&tz->lock); | 535 | mutex_unlock(&tz->lock); |
533 | 536 | ||
534 | trace_thermal_temperature(tz); | 537 | trace_thermal_temperature(tz); |
535 | dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", | 538 | if (tz->last_temperature == THERMAL_TEMP_INVALID) |
536 | tz->last_temperature, tz->temperature); | 539 | dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", |
540 | tz->temperature); | ||
541 | else | ||
542 | dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", | ||
543 | tz->last_temperature, tz->temperature); | ||
544 | } | ||
545 | |||
546 | static void thermal_zone_device_reset(struct thermal_zone_device *tz) | ||
547 | { | ||
548 | struct thermal_instance *pos; | ||
549 | |||
550 | tz->temperature = THERMAL_TEMP_INVALID; | ||
551 | tz->passive = 0; | ||
552 | list_for_each_entry(pos, &tz->thermal_instances, tz_node) | ||
553 | pos->initialized = false; | ||
537 | } | 554 | } |
538 | 555 | ||
539 | void thermal_zone_device_update(struct thermal_zone_device *tz) | 556 | void thermal_zone_device_update(struct thermal_zone_device *tz) |
540 | { | 557 | { |
541 | int count; | 558 | int count; |
542 | 559 | ||
560 | if (atomic_read(&in_suspend)) | ||
561 | return; | ||
562 | |||
543 | if (!tz->ops->get_temp) | 563 | if (!tz->ops->get_temp) |
544 | return; | 564 | return; |
545 | 565 | ||
@@ -676,8 +696,12 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, | |||
676 | return -EINVAL; | 696 | return -EINVAL; |
677 | 697 | ||
678 | ret = tz->ops->set_trip_temp(tz, trip, temperature); | 698 | ret = tz->ops->set_trip_temp(tz, trip, temperature); |
699 | if (ret) | ||
700 | return ret; | ||
679 | 701 | ||
680 | return ret ? ret : count; | 702 | thermal_zone_device_update(tz); |
703 | |||
704 | return count; | ||
681 | } | 705 | } |
682 | 706 | ||
683 | static ssize_t | 707 | static ssize_t |
@@ -1321,6 +1345,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
1321 | if (!result) { | 1345 | if (!result) { |
1322 | list_add_tail(&dev->tz_node, &tz->thermal_instances); | 1346 | list_add_tail(&dev->tz_node, &tz->thermal_instances); |
1323 | list_add_tail(&dev->cdev_node, &cdev->thermal_instances); | 1347 | list_add_tail(&dev->cdev_node, &cdev->thermal_instances); |
1348 | atomic_set(&tz->need_update, 1); | ||
1324 | } | 1349 | } |
1325 | mutex_unlock(&cdev->lock); | 1350 | mutex_unlock(&cdev->lock); |
1326 | mutex_unlock(&tz->lock); | 1351 | mutex_unlock(&tz->lock); |
@@ -1430,6 +1455,7 @@ __thermal_cooling_device_register(struct device_node *np, | |||
1430 | const struct thermal_cooling_device_ops *ops) | 1455 | const struct thermal_cooling_device_ops *ops) |
1431 | { | 1456 | { |
1432 | struct thermal_cooling_device *cdev; | 1457 | struct thermal_cooling_device *cdev; |
1458 | struct thermal_zone_device *pos = NULL; | ||
1433 | int result; | 1459 | int result; |
1434 | 1460 | ||
1435 | if (type && strlen(type) >= THERMAL_NAME_LENGTH) | 1461 | if (type && strlen(type) >= THERMAL_NAME_LENGTH) |
@@ -1474,6 +1500,12 @@ __thermal_cooling_device_register(struct device_node *np, | |||
1474 | /* Update binding information for 'this' new cdev */ | 1500 | /* Update binding information for 'this' new cdev */ |
1475 | bind_cdev(cdev); | 1501 | bind_cdev(cdev); |
1476 | 1502 | ||
1503 | mutex_lock(&thermal_list_lock); | ||
1504 | list_for_each_entry(pos, &thermal_tz_list, node) | ||
1505 | if (atomic_cmpxchg(&pos->need_update, 1, 0)) | ||
1506 | thermal_zone_device_update(pos); | ||
1507 | mutex_unlock(&thermal_list_lock); | ||
1508 | |||
1477 | return cdev; | 1509 | return cdev; |
1478 | } | 1510 | } |
1479 | 1511 | ||
@@ -1806,6 +1838,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1806 | tz->trips = trips; | 1838 | tz->trips = trips; |
1807 | tz->passive_delay = passive_delay; | 1839 | tz->passive_delay = passive_delay; |
1808 | tz->polling_delay = polling_delay; | 1840 | tz->polling_delay = polling_delay; |
1841 | /* A new thermal zone needs to be updated anyway. */ | ||
1842 | atomic_set(&tz->need_update, 1); | ||
1809 | 1843 | ||
1810 | dev_set_name(&tz->device, "thermal_zone%d", tz->id); | 1844 | dev_set_name(&tz->device, "thermal_zone%d", tz->id); |
1811 | result = device_register(&tz->device); | 1845 | result = device_register(&tz->device); |
@@ -1900,7 +1934,10 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1900 | 1934 | ||
1901 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); | 1935 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); |
1902 | 1936 | ||
1903 | thermal_zone_device_update(tz); | 1937 | thermal_zone_device_reset(tz); |
1938 | /* Update the new thermal zone and mark it as already updated. */ | ||
1939 | if (atomic_cmpxchg(&tz->need_update, 1, 0)) | ||
1940 | thermal_zone_device_update(tz); | ||
1904 | 1941 | ||
1905 | return tz; | 1942 | return tz; |
1906 | 1943 | ||
@@ -2140,6 +2177,36 @@ static void thermal_unregister_governors(void) | |||
2140 | thermal_gov_power_allocator_unregister(); | 2177 | thermal_gov_power_allocator_unregister(); |
2141 | } | 2178 | } |
2142 | 2179 | ||
2180 | static int thermal_pm_notify(struct notifier_block *nb, | ||
2181 | unsigned long mode, void *_unused) | ||
2182 | { | ||
2183 | struct thermal_zone_device *tz; | ||
2184 | |||
2185 | switch (mode) { | ||
2186 | case PM_HIBERNATION_PREPARE: | ||
2187 | case PM_RESTORE_PREPARE: | ||
2188 | case PM_SUSPEND_PREPARE: | ||
2189 | atomic_set(&in_suspend, 1); | ||
2190 | break; | ||
2191 | case PM_POST_HIBERNATION: | ||
2192 | case PM_POST_RESTORE: | ||
2193 | case PM_POST_SUSPEND: | ||
2194 | atomic_set(&in_suspend, 0); | ||
2195 | list_for_each_entry(tz, &thermal_tz_list, node) { | ||
2196 | thermal_zone_device_reset(tz); | ||
2197 | thermal_zone_device_update(tz); | ||
2198 | } | ||
2199 | break; | ||
2200 | default: | ||
2201 | break; | ||
2202 | } | ||
2203 | return 0; | ||
2204 | } | ||
2205 | |||
2206 | static struct notifier_block thermal_pm_nb = { | ||
2207 | .notifier_call = thermal_pm_notify, | ||
2208 | }; | ||
2209 | |||
2143 | static int __init thermal_init(void) | 2210 | static int __init thermal_init(void) |
2144 | { | 2211 | { |
2145 | int result; | 2212 | int result; |
@@ -2160,6 +2227,11 @@ static int __init thermal_init(void) | |||
2160 | if (result) | 2227 | if (result) |
2161 | goto exit_netlink; | 2228 | goto exit_netlink; |
2162 | 2229 | ||
2230 | result = register_pm_notifier(&thermal_pm_nb); | ||
2231 | if (result) | ||
2232 | pr_warn("Thermal: Can not register suspend notifier, return %d\n", | ||
2233 | result); | ||
2234 | |||
2163 | return 0; | 2235 | return 0; |
2164 | 2236 | ||
2165 | exit_netlink: | 2237 | exit_netlink: |
@@ -2179,6 +2251,7 @@ error: | |||
2179 | 2251 | ||
2180 | static void __exit thermal_exit(void) | 2252 | static void __exit thermal_exit(void) |
2181 | { | 2253 | { |
2254 | unregister_pm_notifier(&thermal_pm_nb); | ||
2182 | of_thermal_destroy_zones(); | 2255 | of_thermal_destroy_zones(); |
2183 | genetlink_exit(); | 2256 | genetlink_exit(); |
2184 | class_unregister(&thermal_class); | 2257 | class_unregister(&thermal_class); |
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index d7ac1fccd659..749d41abfbab 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h | |||
@@ -41,6 +41,7 @@ struct thermal_instance { | |||
41 | struct thermal_zone_device *tz; | 41 | struct thermal_zone_device *tz; |
42 | struct thermal_cooling_device *cdev; | 42 | struct thermal_cooling_device *cdev; |
43 | int trip; | 43 | int trip; |
44 | bool initialized; | ||
44 | unsigned long upper; /* Highest cooling state for this trip point */ | 45 | unsigned long upper; /* Highest cooling state for this trip point */ |
45 | unsigned long lower; /* Lowest cooling state for this trip point */ | 46 | unsigned long lower; /* Lowest cooling state for this trip point */ |
46 | unsigned long target; /* expected cooling state */ | 47 | unsigned long target; /* expected cooling state */ |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 613c29bd6baf..e13a1ace50e9 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -43,6 +43,9 @@ | |||
43 | /* Default weight of a bound cooling device */ | 43 | /* Default weight of a bound cooling device */ |
44 | #define THERMAL_WEIGHT_DEFAULT 0 | 44 | #define THERMAL_WEIGHT_DEFAULT 0 |
45 | 45 | ||
46 | /* use value, which < 0K, to indicate an invalid/uninitialized temperature */ | ||
47 | #define THERMAL_TEMP_INVALID -274000 | ||
48 | |||
46 | /* Unit conversion macros */ | 49 | /* Unit conversion macros */ |
47 | #define DECI_KELVIN_TO_CELSIUS(t) ({ \ | 50 | #define DECI_KELVIN_TO_CELSIUS(t) ({ \ |
48 | long _t = (t); \ | 51 | long _t = (t); \ |
@@ -167,6 +170,7 @@ struct thermal_attr { | |||
167 | * @forced_passive: If > 0, temperature at which to switch on all ACPI | 170 | * @forced_passive: If > 0, temperature at which to switch on all ACPI |
168 | * processor cooling devices. Currently only used by the | 171 | * processor cooling devices. Currently only used by the |
169 | * step-wise governor. | 172 | * step-wise governor. |
173 | * @need_update: if equals 1, thermal_zone_device_update needs to be invoked. | ||
170 | * @ops: operations this &thermal_zone_device supports | 174 | * @ops: operations this &thermal_zone_device supports |
171 | * @tzp: thermal zone parameters | 175 | * @tzp: thermal zone parameters |
172 | * @governor: pointer to the governor for this thermal zone | 176 | * @governor: pointer to the governor for this thermal zone |
@@ -194,6 +198,7 @@ struct thermal_zone_device { | |||
194 | int emul_temperature; | 198 | int emul_temperature; |
195 | int passive; | 199 | int passive; |
196 | unsigned int forced_passive; | 200 | unsigned int forced_passive; |
201 | atomic_t need_update; | ||
197 | struct thermal_zone_device_ops *ops; | 202 | struct thermal_zone_device_ops *ops; |
198 | struct thermal_zone_params *tzp; | 203 | struct thermal_zone_params *tzp; |
199 | struct thermal_governor *governor; | 204 | struct thermal_governor *governor; |