diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-17 17:31:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-17 17:31:27 -0500 |
commit | bec04432cb9036dedf89140c102b5ac03e4b3626 (patch) | |
tree | 390d76ddf5f302577efc704a78251f099bfecbf5 /drivers | |
parent | e29116758c4e06be9ba6358350f9d9f466414efb (diff) | |
parent | 1e032393d9680c1f3b5238ec0f3f4eb006ee83d2 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui:
- introduce brcmstb AVS TMON thermal driver (Brian Norris)
- add Rockchip RV1108 support in rockchip thermal driver (Rocky Hao)
- major rework on HISI driver plus additional support of hisi3660
(Daniel Lezcano)
- add nvmem-cells binding on imx6sx (Leonard Crestez)
- fix a NULL pointer dereference on ti thermal driver unloading (Tony
Lindgren)
- improve tmon tool to make it easier to cross-compile tmon (Markus
Mayer)
- add Coffee Lake and Cannon Lake support for intel processor and pch
thermal drivers (Srinivas Pandruvada)
- other small fixes and cleanups (Arvind Yadav, Colin Ian King, Allen
Wild, Nicolin Chen, Baruch SiachNiklas Söderlund, Arnd Bergmann)
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (44 commits)
thermal: pch: Add Cannon Lake support
thermal: int340x: processor_thermal: Add Coffee Lake support
thermal: int340x: processor_thermal: Add Cannon Lake support
thermal: bxt: remove redundant variable trip
thermal: cpu_cooling: pr_err() strings should end with newlines
thermal: add brcmstb AVS TMON driver
Documentation: devicetree: add binding for Broadcom STB AVS TMON
thermal/drivers/hisi: Add support for hi3660 SoC
thermal/drivers/hisi: Prepare to add support for other hisi platforms
thermal/drivers/hisi: Add platform prefix to function name
thermal/drivers/hisi: Put platform code together
thermal/drivers/qcom-spmi: Use devm_iio_channel_get
thermal/drivers/generic-iio-adc: Switch tz request to devm version
thermal/drivers/step_wise: Fix temperature regulation misbehavior
thermal/drivers/hisi: Use round up step value
thermal/drivers/hisi: Move the clk setup in the corresponding functions
thermal/drivers/hisi: Remove mutex_lock in the code
thermal/drivers/hisi: Remove thermal data back pointer
thermal/drivers/hisi: Convert long to int
thermal/drivers/hisi: Rename and remove unused field
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/thermal/Kconfig | 3 | ||||
-rw-r--r-- | drivers/thermal/armada_thermal.c | 2 | ||||
-rw-r--r-- | drivers/thermal/broadcom/Kconfig | 7 | ||||
-rw-r--r-- | drivers/thermal/broadcom/Makefile | 1 | ||||
-rw-r--r-- | drivers/thermal/broadcom/brcmstb_thermal.c | 387 | ||||
-rw-r--r-- | drivers/thermal/cpu_cooling.c | 2 | ||||
-rw-r--r-- | drivers/thermal/hisi_thermal.c | 612 | ||||
-rw-r--r-- | drivers/thermal/imx_thermal.c | 104 | ||||
-rw-r--r-- | drivers/thermal/int340x_thermal/processor_thermal_device.c | 6 | ||||
-rw-r--r-- | drivers/thermal/intel_bxt_pmic_thermal.c | 3 | ||||
-rw-r--r-- | drivers/thermal/intel_pch_thermal.c | 11 | ||||
-rw-r--r-- | drivers/thermal/intel_powerclamp.c | 4 | ||||
-rw-r--r-- | drivers/thermal/qcom-spmi-temp-alarm.c | 43 | ||||
-rw-r--r-- | drivers/thermal/rcar_gen3_thermal.c | 34 | ||||
-rw-r--r-- | drivers/thermal/rockchip_thermal.c | 67 | ||||
-rw-r--r-- | drivers/thermal/step_wise.c | 11 | ||||
-rw-r--r-- | drivers/thermal/tegra/soctherm.c | 2 | ||||
-rw-r--r-- | drivers/thermal/thermal-generic-adc.c | 24 | ||||
-rw-r--r-- | drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 3 |
19 files changed, 1006 insertions, 320 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 07002df4f83a..315ae2926e20 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
@@ -206,6 +206,7 @@ config HISI_THERMAL | |||
206 | config IMX_THERMAL | 206 | config IMX_THERMAL |
207 | tristate "Temperature sensor driver for Freescale i.MX SoCs" | 207 | tristate "Temperature sensor driver for Freescale i.MX SoCs" |
208 | depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST | 208 | depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST |
209 | depends on NVMEM || !NVMEM | ||
209 | depends on MFD_SYSCON | 210 | depends on MFD_SYSCON |
210 | depends on OF | 211 | depends on OF |
211 | help | 212 | help |
@@ -408,7 +409,7 @@ config MTK_THERMAL | |||
408 | controller present in Mediatek SoCs | 409 | controller present in Mediatek SoCs |
409 | 410 | ||
410 | menu "Broadcom thermal drivers" | 411 | menu "Broadcom thermal drivers" |
411 | depends on ARCH_BCM || COMPILE_TEST | 412 | depends on ARCH_BCM || ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST |
412 | source "drivers/thermal/broadcom/Kconfig" | 413 | source "drivers/thermal/broadcom/Kconfig" |
413 | endmenu | 414 | endmenu |
414 | 415 | ||
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index ae75328945f7..706d74798cbe 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c | |||
@@ -58,7 +58,7 @@ struct armada_thermal_data { | |||
58 | /* Test for a valid sensor value (optional) */ | 58 | /* Test for a valid sensor value (optional) */ |
59 | bool (*is_valid)(struct armada_thermal_priv *); | 59 | bool (*is_valid)(struct armada_thermal_priv *); |
60 | 60 | ||
61 | /* Formula coeficients: temp = (b + m * reg) / div */ | 61 | /* Formula coeficients: temp = (b - m * reg) / div */ |
62 | unsigned long coef_b; | 62 | unsigned long coef_b; |
63 | unsigned long coef_m; | 63 | unsigned long coef_m; |
64 | unsigned long coef_div; | 64 | unsigned long coef_div; |
diff --git a/drivers/thermal/broadcom/Kconfig b/drivers/thermal/broadcom/Kconfig index 42c098e86f84..c106a15bf7f9 100644 --- a/drivers/thermal/broadcom/Kconfig +++ b/drivers/thermal/broadcom/Kconfig | |||
@@ -6,6 +6,13 @@ config BCM2835_THERMAL | |||
6 | help | 6 | help |
7 | Support for thermal sensors on Broadcom bcm2835 SoCs. | 7 | Support for thermal sensors on Broadcom bcm2835 SoCs. |
8 | 8 | ||
9 | config BRCMSTB_THERMAL | ||
10 | tristate "Broadcom STB AVS TMON thermal driver" | ||
11 | depends on ARCH_BRCMSTB || COMPILE_TEST | ||
12 | help | ||
13 | Enable this driver if you have a Broadcom STB SoC and would like | ||
14 | thermal framework support. | ||
15 | |||
9 | config BCM_NS_THERMAL | 16 | config BCM_NS_THERMAL |
10 | tristate "Northstar thermal driver" | 17 | tristate "Northstar thermal driver" |
11 | depends on ARCH_BCM_IPROC || COMPILE_TEST | 18 | depends on ARCH_BCM_IPROC || COMPILE_TEST |
diff --git a/drivers/thermal/broadcom/Makefile b/drivers/thermal/broadcom/Makefile index c6f62e4fd0ee..fae10ecafaef 100644 --- a/drivers/thermal/broadcom/Makefile +++ b/drivers/thermal/broadcom/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o | 1 | obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o |
2 | obj-$(CONFIG_BRCMSTB_THERMAL) += brcmstb_thermal.o | ||
2 | obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o | 3 | obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o |
diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c new file mode 100644 index 000000000000..1919f91fa756 --- /dev/null +++ b/drivers/thermal/broadcom/brcmstb_thermal.c | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | * Broadcom STB AVS TMON thermal sensor driver | ||
3 | * | ||
4 | * Copyright (c) 2015-2017 Broadcom | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #define DRV_NAME "brcmstb_thermal" | ||
18 | |||
19 | #define pr_fmt(fmt) DRV_NAME ": " fmt | ||
20 | |||
21 | #include <linux/bitops.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/irqreturn.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/of_device.h> | ||
31 | #include <linux/thermal.h> | ||
32 | |||
33 | #define AVS_TMON_STATUS 0x00 | ||
34 | #define AVS_TMON_STATUS_valid_msk BIT(11) | ||
35 | #define AVS_TMON_STATUS_data_msk GENMASK(10, 1) | ||
36 | #define AVS_TMON_STATUS_data_shift 1 | ||
37 | |||
38 | #define AVS_TMON_EN_OVERTEMP_RESET 0x04 | ||
39 | #define AVS_TMON_EN_OVERTEMP_RESET_msk BIT(0) | ||
40 | |||
41 | #define AVS_TMON_RESET_THRESH 0x08 | ||
42 | #define AVS_TMON_RESET_THRESH_msk GENMASK(10, 1) | ||
43 | #define AVS_TMON_RESET_THRESH_shift 1 | ||
44 | |||
45 | #define AVS_TMON_INT_IDLE_TIME 0x10 | ||
46 | |||
47 | #define AVS_TMON_EN_TEMP_INT_SRCS 0x14 | ||
48 | #define AVS_TMON_EN_TEMP_INT_SRCS_high BIT(1) | ||
49 | #define AVS_TMON_EN_TEMP_INT_SRCS_low BIT(0) | ||
50 | |||
51 | #define AVS_TMON_INT_THRESH 0x18 | ||
52 | #define AVS_TMON_INT_THRESH_high_msk GENMASK(26, 17) | ||
53 | #define AVS_TMON_INT_THRESH_high_shift 17 | ||
54 | #define AVS_TMON_INT_THRESH_low_msk GENMASK(10, 1) | ||
55 | #define AVS_TMON_INT_THRESH_low_shift 1 | ||
56 | |||
57 | #define AVS_TMON_TEMP_INT_CODE 0x1c | ||
58 | #define AVS_TMON_TP_TEST_ENABLE 0x20 | ||
59 | |||
60 | /* Default coefficients */ | ||
61 | #define AVS_TMON_TEMP_SLOPE -487 | ||
62 | #define AVS_TMON_TEMP_OFFSET 410040 | ||
63 | |||
64 | /* HW related temperature constants */ | ||
65 | #define AVS_TMON_TEMP_MAX 0x3ff | ||
66 | #define AVS_TMON_TEMP_MIN -88161 | ||
67 | #define AVS_TMON_TEMP_MASK AVS_TMON_TEMP_MAX | ||
68 | |||
69 | enum avs_tmon_trip_type { | ||
70 | TMON_TRIP_TYPE_LOW = 0, | ||
71 | TMON_TRIP_TYPE_HIGH, | ||
72 | TMON_TRIP_TYPE_RESET, | ||
73 | TMON_TRIP_TYPE_MAX, | ||
74 | }; | ||
75 | |||
76 | struct avs_tmon_trip { | ||
77 | /* HW bit to enable the trip */ | ||
78 | u32 enable_offs; | ||
79 | u32 enable_mask; | ||
80 | |||
81 | /* HW field to read the trip temperature */ | ||
82 | u32 reg_offs; | ||
83 | u32 reg_msk; | ||
84 | int reg_shift; | ||
85 | }; | ||
86 | |||
87 | static struct avs_tmon_trip avs_tmon_trips[] = { | ||
88 | /* Trips when temperature is below threshold */ | ||
89 | [TMON_TRIP_TYPE_LOW] = { | ||
90 | .enable_offs = AVS_TMON_EN_TEMP_INT_SRCS, | ||
91 | .enable_mask = AVS_TMON_EN_TEMP_INT_SRCS_low, | ||
92 | .reg_offs = AVS_TMON_INT_THRESH, | ||
93 | .reg_msk = AVS_TMON_INT_THRESH_low_msk, | ||
94 | .reg_shift = AVS_TMON_INT_THRESH_low_shift, | ||
95 | }, | ||
96 | /* Trips when temperature is above threshold */ | ||
97 | [TMON_TRIP_TYPE_HIGH] = { | ||
98 | .enable_offs = AVS_TMON_EN_TEMP_INT_SRCS, | ||
99 | .enable_mask = AVS_TMON_EN_TEMP_INT_SRCS_high, | ||
100 | .reg_offs = AVS_TMON_INT_THRESH, | ||
101 | .reg_msk = AVS_TMON_INT_THRESH_high_msk, | ||
102 | .reg_shift = AVS_TMON_INT_THRESH_high_shift, | ||
103 | }, | ||
104 | /* Automatically resets chip when above threshold */ | ||
105 | [TMON_TRIP_TYPE_RESET] = { | ||
106 | .enable_offs = AVS_TMON_EN_OVERTEMP_RESET, | ||
107 | .enable_mask = AVS_TMON_EN_OVERTEMP_RESET_msk, | ||
108 | .reg_offs = AVS_TMON_RESET_THRESH, | ||
109 | .reg_msk = AVS_TMON_RESET_THRESH_msk, | ||
110 | .reg_shift = AVS_TMON_RESET_THRESH_shift, | ||
111 | }, | ||
112 | }; | ||
113 | |||
114 | struct brcmstb_thermal_priv { | ||
115 | void __iomem *tmon_base; | ||
116 | struct device *dev; | ||
117 | struct thermal_zone_device *thermal; | ||
118 | }; | ||
119 | |||
120 | static void avs_tmon_get_coeffs(struct thermal_zone_device *tz, int *slope, | ||
121 | int *offset) | ||
122 | { | ||
123 | *slope = thermal_zone_get_slope(tz); | ||
124 | *offset = thermal_zone_get_offset(tz); | ||
125 | } | ||
126 | |||
127 | /* Convert a HW code to a temperature reading (millidegree celsius) */ | ||
128 | static inline int avs_tmon_code_to_temp(struct thermal_zone_device *tz, | ||
129 | u32 code) | ||
130 | { | ||
131 | const int val = code & AVS_TMON_TEMP_MASK; | ||
132 | int slope, offset; | ||
133 | |||
134 | avs_tmon_get_coeffs(tz, &slope, &offset); | ||
135 | |||
136 | return slope * val + offset; | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Convert a temperature value (millidegree celsius) to a HW code | ||
141 | * | ||
142 | * @temp: temperature to convert | ||
143 | * @low: if true, round toward the low side | ||
144 | */ | ||
145 | static inline u32 avs_tmon_temp_to_code(struct thermal_zone_device *tz, | ||
146 | int temp, bool low) | ||
147 | { | ||
148 | int slope, offset; | ||
149 | |||
150 | if (temp < AVS_TMON_TEMP_MIN) | ||
151 | return AVS_TMON_TEMP_MAX; /* Maximum code value */ | ||
152 | |||
153 | avs_tmon_get_coeffs(tz, &slope, &offset); | ||
154 | |||
155 | if (temp >= offset) | ||
156 | return 0; /* Minimum code value */ | ||
157 | |||
158 | if (low) | ||
159 | return (u32)(DIV_ROUND_UP(offset - temp, abs(slope))); | ||
160 | else | ||
161 | return (u32)((offset - temp) / abs(slope)); | ||
162 | } | ||
163 | |||
164 | static int brcmstb_get_temp(void *data, int *temp) | ||
165 | { | ||
166 | struct brcmstb_thermal_priv *priv = data; | ||
167 | u32 val; | ||
168 | long t; | ||
169 | |||
170 | val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS); | ||
171 | |||
172 | if (!(val & AVS_TMON_STATUS_valid_msk)) { | ||
173 | dev_err(priv->dev, "reading not valid\n"); | ||
174 | return -EIO; | ||
175 | } | ||
176 | |||
177 | val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift; | ||
178 | |||
179 | t = avs_tmon_code_to_temp(priv->thermal, val); | ||
180 | if (t < 0) | ||
181 | *temp = 0; | ||
182 | else | ||
183 | *temp = t; | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static void avs_tmon_trip_enable(struct brcmstb_thermal_priv *priv, | ||
189 | enum avs_tmon_trip_type type, int en) | ||
190 | { | ||
191 | struct avs_tmon_trip *trip = &avs_tmon_trips[type]; | ||
192 | u32 val = __raw_readl(priv->tmon_base + trip->enable_offs); | ||
193 | |||
194 | dev_dbg(priv->dev, "%sable trip, type %d\n", en ? "en" : "dis", type); | ||
195 | |||
196 | if (en) | ||
197 | val |= trip->enable_mask; | ||
198 | else | ||
199 | val &= ~trip->enable_mask; | ||
200 | |||
201 | __raw_writel(val, priv->tmon_base + trip->enable_offs); | ||
202 | } | ||
203 | |||
204 | static int avs_tmon_get_trip_temp(struct brcmstb_thermal_priv *priv, | ||
205 | enum avs_tmon_trip_type type) | ||
206 | { | ||
207 | struct avs_tmon_trip *trip = &avs_tmon_trips[type]; | ||
208 | u32 val = __raw_readl(priv->tmon_base + trip->reg_offs); | ||
209 | |||
210 | val &= trip->reg_msk; | ||
211 | val >>= trip->reg_shift; | ||
212 | |||
213 | return avs_tmon_code_to_temp(priv->thermal, val); | ||
214 | } | ||
215 | |||
216 | static void avs_tmon_set_trip_temp(struct brcmstb_thermal_priv *priv, | ||
217 | enum avs_tmon_trip_type type, | ||
218 | int temp) | ||
219 | { | ||
220 | struct avs_tmon_trip *trip = &avs_tmon_trips[type]; | ||
221 | u32 val, orig; | ||
222 | |||
223 | dev_dbg(priv->dev, "set temp %d to %d\n", type, temp); | ||
224 | |||
225 | /* round toward low temp for the low interrupt */ | ||
226 | val = avs_tmon_temp_to_code(priv->thermal, temp, | ||
227 | type == TMON_TRIP_TYPE_LOW); | ||
228 | |||
229 | val <<= trip->reg_shift; | ||
230 | val &= trip->reg_msk; | ||
231 | |||
232 | orig = __raw_readl(priv->tmon_base + trip->reg_offs); | ||
233 | orig &= ~trip->reg_msk; | ||
234 | orig |= val; | ||
235 | __raw_writel(orig, priv->tmon_base + trip->reg_offs); | ||
236 | } | ||
237 | |||
238 | static int avs_tmon_get_intr_temp(struct brcmstb_thermal_priv *priv) | ||
239 | { | ||
240 | u32 val; | ||
241 | |||
242 | val = __raw_readl(priv->tmon_base + AVS_TMON_TEMP_INT_CODE); | ||
243 | return avs_tmon_code_to_temp(priv->thermal, val); | ||
244 | } | ||
245 | |||
246 | static irqreturn_t brcmstb_tmon_irq_thread(int irq, void *data) | ||
247 | { | ||
248 | struct brcmstb_thermal_priv *priv = data; | ||
249 | int low, high, intr; | ||
250 | |||
251 | low = avs_tmon_get_trip_temp(priv, TMON_TRIP_TYPE_LOW); | ||
252 | high = avs_tmon_get_trip_temp(priv, TMON_TRIP_TYPE_HIGH); | ||
253 | intr = avs_tmon_get_intr_temp(priv); | ||
254 | |||
255 | dev_dbg(priv->dev, "low/intr/high: %d/%d/%d\n", | ||
256 | low, intr, high); | ||
257 | |||
258 | /* Disable high-temp until next threshold shift */ | ||
259 | if (intr >= high) | ||
260 | avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_HIGH, 0); | ||
261 | /* Disable low-temp until next threshold shift */ | ||
262 | if (intr <= low) | ||
263 | avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_LOW, 0); | ||
264 | |||
265 | /* | ||
266 | * Notify using the interrupt temperature, in case the temperature | ||
267 | * changes before it can next be read out | ||
268 | */ | ||
269 | thermal_zone_device_update(priv->thermal, intr); | ||
270 | |||
271 | return IRQ_HANDLED; | ||
272 | } | ||
273 | |||
274 | static int brcmstb_set_trips(void *data, int low, int high) | ||
275 | { | ||
276 | struct brcmstb_thermal_priv *priv = data; | ||
277 | |||
278 | dev_dbg(priv->dev, "set trips %d <--> %d\n", low, high); | ||
279 | |||
280 | /* | ||
281 | * Disable low-temp if "low" is too small. As per thermal framework | ||
282 | * API, we use -INT_MAX rather than INT_MIN. | ||
283 | */ | ||
284 | if (low <= -INT_MAX) { | ||
285 | avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_LOW, 0); | ||
286 | } else { | ||
287 | avs_tmon_set_trip_temp(priv, TMON_TRIP_TYPE_LOW, low); | ||
288 | avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_LOW, 1); | ||
289 | } | ||
290 | |||
291 | /* Disable high-temp if "high" is too big. */ | ||
292 | if (high == INT_MAX) { | ||
293 | avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_HIGH, 0); | ||
294 | } else { | ||
295 | avs_tmon_set_trip_temp(priv, TMON_TRIP_TYPE_HIGH, high); | ||
296 | avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_HIGH, 1); | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static struct thermal_zone_of_device_ops of_ops = { | ||
303 | .get_temp = brcmstb_get_temp, | ||
304 | .set_trips = brcmstb_set_trips, | ||
305 | }; | ||
306 | |||
307 | static const struct of_device_id brcmstb_thermal_id_table[] = { | ||
308 | { .compatible = "brcm,avs-tmon" }, | ||
309 | {}, | ||
310 | }; | ||
311 | MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table); | ||
312 | |||
313 | static int brcmstb_thermal_probe(struct platform_device *pdev) | ||
314 | { | ||
315 | struct thermal_zone_device *thermal; | ||
316 | struct brcmstb_thermal_priv *priv; | ||
317 | struct resource *res; | ||
318 | int irq, ret; | ||
319 | |||
320 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
321 | if (!priv) | ||
322 | return -ENOMEM; | ||
323 | |||
324 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
325 | priv->tmon_base = devm_ioremap_resource(&pdev->dev, res); | ||
326 | if (IS_ERR(priv->tmon_base)) | ||
327 | return PTR_ERR(priv->tmon_base); | ||
328 | |||
329 | priv->dev = &pdev->dev; | ||
330 | platform_set_drvdata(pdev, priv); | ||
331 | |||
332 | thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &of_ops); | ||
333 | if (IS_ERR(thermal)) { | ||
334 | ret = PTR_ERR(thermal); | ||
335 | dev_err(&pdev->dev, "could not register sensor: %d\n", ret); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | priv->thermal = thermal; | ||
340 | |||
341 | irq = platform_get_irq(pdev, 0); | ||
342 | if (irq < 0) { | ||
343 | dev_err(&pdev->dev, "could not get IRQ\n"); | ||
344 | ret = irq; | ||
345 | goto err; | ||
346 | } | ||
347 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | ||
348 | brcmstb_tmon_irq_thread, IRQF_ONESHOT, | ||
349 | DRV_NAME, priv); | ||
350 | if (ret < 0) { | ||
351 | dev_err(&pdev->dev, "could not request IRQ: %d\n", ret); | ||
352 | goto err; | ||
353 | } | ||
354 | |||
355 | dev_info(&pdev->dev, "registered AVS TMON of-sensor driver\n"); | ||
356 | |||
357 | return 0; | ||
358 | |||
359 | err: | ||
360 | thermal_zone_of_sensor_unregister(&pdev->dev, thermal); | ||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | static int brcmstb_thermal_exit(struct platform_device *pdev) | ||
365 | { | ||
366 | struct brcmstb_thermal_priv *priv = platform_get_drvdata(pdev); | ||
367 | struct thermal_zone_device *thermal = priv->thermal; | ||
368 | |||
369 | if (thermal) | ||
370 | thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal); | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static struct platform_driver brcmstb_thermal_driver = { | ||
376 | .probe = brcmstb_thermal_probe, | ||
377 | .remove = brcmstb_thermal_exit, | ||
378 | .driver = { | ||
379 | .name = DRV_NAME, | ||
380 | .of_match_table = brcmstb_thermal_id_table, | ||
381 | }, | ||
382 | }; | ||
383 | module_platform_driver(brcmstb_thermal_driver); | ||
384 | |||
385 | MODULE_LICENSE("GPL v2"); | ||
386 | MODULE_AUTHOR("Brian Norris"); | ||
387 | MODULE_DESCRIPTION("Broadcom STB AVS TMON thermal driver"); | ||
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 908a8014cf76..dc63aba092e4 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c | |||
@@ -696,7 +696,7 @@ __cpufreq_cooling_register(struct device_node *np, | |||
696 | bool first; | 696 | bool first; |
697 | 697 | ||
698 | if (IS_ERR_OR_NULL(policy)) { | 698 | if (IS_ERR_OR_NULL(policy)) { |
699 | pr_err("%s: cpufreq policy isn't valid: %p", __func__, policy); | 699 | pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy); |
700 | return ERR_PTR(-EINVAL); | 700 | return ERR_PTR(-EINVAL); |
701 | } | 701 | } |
702 | 702 | ||
diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index bd3572c41585..2d855a96cdd9 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c | |||
@@ -23,222 +23,450 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/of_device.h> | ||
26 | 27 | ||
27 | #include "thermal_core.h" | 28 | #include "thermal_core.h" |
28 | 29 | ||
29 | #define TEMP0_TH (0x4) | 30 | #define HI6220_TEMP0_LAG (0x0) |
30 | #define TEMP0_RST_TH (0x8) | 31 | #define HI6220_TEMP0_TH (0x4) |
31 | #define TEMP0_CFG (0xC) | 32 | #define HI6220_TEMP0_RST_TH (0x8) |
32 | #define TEMP0_EN (0x10) | 33 | #define HI6220_TEMP0_CFG (0xC) |
33 | #define TEMP0_INT_EN (0x14) | 34 | #define HI6220_TEMP0_CFG_SS_MSK (0xF000) |
34 | #define TEMP0_INT_CLR (0x18) | 35 | #define HI6220_TEMP0_CFG_HDAK_MSK (0x30) |
35 | #define TEMP0_RST_MSK (0x1C) | 36 | #define HI6220_TEMP0_EN (0x10) |
36 | #define TEMP0_VALUE (0x28) | 37 | #define HI6220_TEMP0_INT_EN (0x14) |
37 | 38 | #define HI6220_TEMP0_INT_CLR (0x18) | |
38 | #define HISI_TEMP_BASE (-60) | 39 | #define HI6220_TEMP0_RST_MSK (0x1C) |
39 | #define HISI_TEMP_RESET (100000) | 40 | #define HI6220_TEMP0_VALUE (0x28) |
40 | 41 | ||
41 | #define HISI_MAX_SENSORS 4 | 42 | #define HI3660_OFFSET(chan) ((chan) * 0x40) |
43 | #define HI3660_TEMP(chan) (HI3660_OFFSET(chan) + 0x1C) | ||
44 | #define HI3660_TH(chan) (HI3660_OFFSET(chan) + 0x20) | ||
45 | #define HI3660_LAG(chan) (HI3660_OFFSET(chan) + 0x28) | ||
46 | #define HI3660_INT_EN(chan) (HI3660_OFFSET(chan) + 0x2C) | ||
47 | #define HI3660_INT_CLR(chan) (HI3660_OFFSET(chan) + 0x30) | ||
48 | |||
49 | #define HI6220_TEMP_BASE (-60000) | ||
50 | #define HI6220_TEMP_RESET (100000) | ||
51 | #define HI6220_TEMP_STEP (785) | ||
52 | #define HI6220_TEMP_LAG (3500) | ||
53 | |||
54 | #define HI3660_TEMP_BASE (-63780) | ||
55 | #define HI3660_TEMP_STEP (205) | ||
56 | #define HI3660_TEMP_LAG (4000) | ||
57 | |||
58 | #define HI6220_DEFAULT_SENSOR 2 | ||
59 | #define HI3660_DEFAULT_SENSOR 1 | ||
42 | 60 | ||
43 | struct hisi_thermal_sensor { | 61 | struct hisi_thermal_sensor { |
44 | struct hisi_thermal_data *thermal; | ||
45 | struct thermal_zone_device *tzd; | 62 | struct thermal_zone_device *tzd; |
46 | |||
47 | long sensor_temp; | ||
48 | uint32_t id; | 63 | uint32_t id; |
49 | uint32_t thres_temp; | 64 | uint32_t thres_temp; |
50 | }; | 65 | }; |
51 | 66 | ||
52 | struct hisi_thermal_data { | 67 | struct hisi_thermal_data { |
53 | struct mutex thermal_lock; /* protects register data */ | 68 | int (*get_temp)(struct hisi_thermal_data *data); |
69 | int (*enable_sensor)(struct hisi_thermal_data *data); | ||
70 | int (*disable_sensor)(struct hisi_thermal_data *data); | ||
71 | int (*irq_handler)(struct hisi_thermal_data *data); | ||
54 | struct platform_device *pdev; | 72 | struct platform_device *pdev; |
55 | struct clk *clk; | 73 | struct clk *clk; |
56 | struct hisi_thermal_sensor sensors[HISI_MAX_SENSORS]; | 74 | struct hisi_thermal_sensor sensor; |
57 | |||
58 | int irq, irq_bind_sensor; | ||
59 | bool irq_enabled; | ||
60 | |||
61 | void __iomem *regs; | 75 | void __iomem *regs; |
76 | int irq; | ||
62 | }; | 77 | }; |
63 | 78 | ||
64 | /* in millicelsius */ | 79 | /* |
65 | static inline int _step_to_temp(int step) | 80 | * The temperature computation on the tsensor is as follow: |
81 | * Unit: millidegree Celsius | ||
82 | * Step: 200/255 (0.7843) | ||
83 | * Temperature base: -60°C | ||
84 | * | ||
85 | * The register is programmed in temperature steps, every step is 785 | ||
86 | * millidegree and begins at -60 000 m°C | ||
87 | * | ||
88 | * The temperature from the steps: | ||
89 | * | ||
90 | * Temp = TempBase + (steps x 785) | ||
91 | * | ||
92 | * and the steps from the temperature: | ||
93 | * | ||
94 | * steps = (Temp - TempBase) / 785 | ||
95 | * | ||
96 | */ | ||
97 | static inline int hi6220_thermal_step_to_temp(int step) | ||
66 | { | 98 | { |
67 | /* | 99 | return HI6220_TEMP_BASE + (step * HI6220_TEMP_STEP); |
68 | * Every step equals (1 * 200) / 255 celsius, and finally | ||
69 | * need convert to millicelsius. | ||
70 | */ | ||
71 | return (HISI_TEMP_BASE * 1000 + (step * 200000 / 255)); | ||
72 | } | 100 | } |
73 | 101 | ||
74 | static inline long _temp_to_step(long temp) | 102 | static inline int hi6220_thermal_temp_to_step(int temp) |
75 | { | 103 | { |
76 | return ((temp - HISI_TEMP_BASE * 1000) * 255) / 200000; | 104 | return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP); |
77 | } | 105 | } |
78 | 106 | ||
79 | static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, | 107 | /* |
80 | struct hisi_thermal_sensor *sensor) | 108 | * for Hi3660, |
109 | * Step: 189/922 (0.205) | ||
110 | * Temperature base: -63.780°C | ||
111 | * | ||
112 | * The register is programmed in temperature steps, every step is 205 | ||
113 | * millidegree and begins at -63 780 m°C | ||
114 | */ | ||
115 | static inline int hi3660_thermal_step_to_temp(int step) | ||
81 | { | 116 | { |
82 | long val; | 117 | return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP; |
118 | } | ||
83 | 119 | ||
84 | mutex_lock(&data->thermal_lock); | 120 | static inline int hi3660_thermal_temp_to_step(int temp) |
121 | { | ||
122 | return DIV_ROUND_UP(temp - HI3660_TEMP_BASE, HI3660_TEMP_STEP); | ||
123 | } | ||
85 | 124 | ||
86 | /* disable interrupt */ | 125 | /* |
87 | writel(0x0, data->regs + TEMP0_INT_EN); | 126 | * The lag register contains 5 bits encoding the temperature in steps. |
88 | writel(0x1, data->regs + TEMP0_INT_CLR); | 127 | * |
128 | * Each time the temperature crosses the threshold boundary, an | ||
129 | * interrupt is raised. It could be when the temperature is going | ||
130 | * above the threshold or below. However, if the temperature is | ||
131 | * fluctuating around this value due to the load, we can receive | ||
132 | * several interrupts which may not desired. | ||
133 | * | ||
134 | * We can setup a temperature representing the delta between the | ||
135 | * threshold and the current temperature when the temperature is | ||
136 | * decreasing. | ||
137 | * | ||
138 | * For instance: the lag register is 5°C, the threshold is 65°C, when | ||
139 | * the temperature reaches 65°C an interrupt is raised and when the | ||
140 | * temperature decrease to 65°C - 5°C another interrupt is raised. | ||
141 | * | ||
142 | * A very short lag can lead to an interrupt storm, a long lag | ||
143 | * increase the latency to react to the temperature changes. In our | ||
144 | * case, that is not really a problem as we are polling the | ||
145 | * temperature. | ||
146 | * | ||
147 | * [0:4] : lag register | ||
148 | * | ||
149 | * The temperature is coded in steps, cf. HI6220_TEMP_STEP. | ||
150 | * | ||
151 | * Min : 0x00 : 0.0 °C | ||
152 | * Max : 0x1F : 24.3 °C | ||
153 | * | ||
154 | * The 'value' parameter is in milliCelsius. | ||
155 | */ | ||
156 | static inline void hi6220_thermal_set_lag(void __iomem *addr, int value) | ||
157 | { | ||
158 | writel(DIV_ROUND_UP(value, HI6220_TEMP_STEP) & 0x1F, | ||
159 | addr + HI6220_TEMP0_LAG); | ||
160 | } | ||
89 | 161 | ||
90 | /* disable module firstly */ | 162 | static inline void hi6220_thermal_alarm_clear(void __iomem *addr, int value) |
91 | writel(0x0, data->regs + TEMP0_EN); | 163 | { |
164 | writel(value, addr + HI6220_TEMP0_INT_CLR); | ||
165 | } | ||
92 | 166 | ||
93 | /* select sensor id */ | 167 | static inline void hi6220_thermal_alarm_enable(void __iomem *addr, int value) |
94 | writel((sensor->id << 12), data->regs + TEMP0_CFG); | 168 | { |
169 | writel(value, addr + HI6220_TEMP0_INT_EN); | ||
170 | } | ||
95 | 171 | ||
96 | /* enable module */ | 172 | static inline void hi6220_thermal_alarm_set(void __iomem *addr, int temp) |
97 | writel(0x1, data->regs + TEMP0_EN); | 173 | { |
174 | writel(hi6220_thermal_temp_to_step(temp) | 0x0FFFFFF00, | ||
175 | addr + HI6220_TEMP0_TH); | ||
176 | } | ||
98 | 177 | ||
99 | usleep_range(3000, 5000); | 178 | static inline void hi6220_thermal_reset_set(void __iomem *addr, int temp) |
179 | { | ||
180 | writel(hi6220_thermal_temp_to_step(temp), addr + HI6220_TEMP0_RST_TH); | ||
181 | } | ||
100 | 182 | ||
101 | val = readl(data->regs + TEMP0_VALUE); | 183 | static inline void hi6220_thermal_reset_enable(void __iomem *addr, int value) |
102 | val = _step_to_temp(val); | 184 | { |
185 | writel(value, addr + HI6220_TEMP0_RST_MSK); | ||
186 | } | ||
103 | 187 | ||
104 | mutex_unlock(&data->thermal_lock); | 188 | static inline void hi6220_thermal_enable(void __iomem *addr, int value) |
189 | { | ||
190 | writel(value, addr + HI6220_TEMP0_EN); | ||
191 | } | ||
105 | 192 | ||
106 | return val; | 193 | static inline int hi6220_thermal_get_temperature(void __iomem *addr) |
194 | { | ||
195 | return hi6220_thermal_step_to_temp(readl(addr + HI6220_TEMP0_VALUE)); | ||
107 | } | 196 | } |
108 | 197 | ||
109 | static void hisi_thermal_enable_bind_irq_sensor | 198 | /* |
110 | (struct hisi_thermal_data *data) | 199 | * [0:6] lag register |
200 | * | ||
201 | * The temperature is coded in steps, cf. HI3660_TEMP_STEP. | ||
202 | * | ||
203 | * Min : 0x00 : 0.0 °C | ||
204 | * Max : 0x7F : 26.0 °C | ||
205 | * | ||
206 | */ | ||
207 | static inline void hi3660_thermal_set_lag(void __iomem *addr, | ||
208 | int id, int value) | ||
111 | { | 209 | { |
112 | struct hisi_thermal_sensor *sensor; | 210 | writel(DIV_ROUND_UP(value, HI3660_TEMP_STEP) & 0x7F, |
211 | addr + HI3660_LAG(id)); | ||
212 | } | ||
113 | 213 | ||
114 | mutex_lock(&data->thermal_lock); | 214 | static inline void hi3660_thermal_alarm_clear(void __iomem *addr, |
215 | int id, int value) | ||
216 | { | ||
217 | writel(value, addr + HI3660_INT_CLR(id)); | ||
218 | } | ||
115 | 219 | ||
116 | sensor = &data->sensors[data->irq_bind_sensor]; | 220 | static inline void hi3660_thermal_alarm_enable(void __iomem *addr, |
221 | int id, int value) | ||
222 | { | ||
223 | writel(value, addr + HI3660_INT_EN(id)); | ||
224 | } | ||
117 | 225 | ||
118 | /* setting the hdak time */ | 226 | static inline void hi3660_thermal_alarm_set(void __iomem *addr, |
119 | writel(0x0, data->regs + TEMP0_CFG); | 227 | int id, int value) |
228 | { | ||
229 | writel(value, addr + HI3660_TH(id)); | ||
230 | } | ||
231 | |||
232 | static inline int hi3660_thermal_get_temperature(void __iomem *addr, int id) | ||
233 | { | ||
234 | return hi3660_thermal_step_to_temp(readl(addr + HI3660_TEMP(id))); | ||
235 | } | ||
236 | |||
237 | /* | ||
238 | * Temperature configuration register - Sensor selection | ||
239 | * | ||
240 | * Bits [19:12] | ||
241 | * | ||
242 | * 0x0: local sensor (default) | ||
243 | * 0x1: remote sensor 1 (ACPU cluster 1) | ||
244 | * 0x2: remote sensor 2 (ACPU cluster 0) | ||
245 | * 0x3: remote sensor 3 (G3D) | ||
246 | */ | ||
247 | static inline void hi6220_thermal_sensor_select(void __iomem *addr, int sensor) | ||
248 | { | ||
249 | writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_SS_MSK) | | ||
250 | (sensor << 12), addr + HI6220_TEMP0_CFG); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * Temperature configuration register - Hdak conversion polling interval | ||
255 | * | ||
256 | * Bits [5:4] | ||
257 | * | ||
258 | * 0x0 : 0.768 ms | ||
259 | * 0x1 : 6.144 ms | ||
260 | * 0x2 : 49.152 ms | ||
261 | * 0x3 : 393.216 ms | ||
262 | */ | ||
263 | static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value) | ||
264 | { | ||
265 | writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_HDAK_MSK) | | ||
266 | (value << 4), addr + HI6220_TEMP0_CFG); | ||
267 | } | ||
268 | |||
269 | static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) | ||
270 | { | ||
271 | hi6220_thermal_alarm_clear(data->regs, 1); | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int hi3660_thermal_irq_handler(struct hisi_thermal_data *data) | ||
276 | { | ||
277 | hi3660_thermal_alarm_clear(data->regs, data->sensor.id, 1); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) | ||
282 | { | ||
283 | return hi6220_thermal_get_temperature(data->regs); | ||
284 | } | ||
285 | |||
286 | static int hi3660_thermal_get_temp(struct hisi_thermal_data *data) | ||
287 | { | ||
288 | return hi3660_thermal_get_temperature(data->regs, data->sensor.id); | ||
289 | } | ||
290 | |||
291 | static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) | ||
292 | { | ||
293 | /* disable sensor module */ | ||
294 | hi6220_thermal_enable(data->regs, 0); | ||
295 | hi6220_thermal_alarm_enable(data->regs, 0); | ||
296 | hi6220_thermal_reset_enable(data->regs, 0); | ||
297 | |||
298 | clk_disable_unprepare(data->clk); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int hi3660_thermal_disable_sensor(struct hisi_thermal_data *data) | ||
304 | { | ||
305 | /* disable sensor module */ | ||
306 | hi3660_thermal_alarm_enable(data->regs, data->sensor.id, 0); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) | ||
311 | { | ||
312 | struct hisi_thermal_sensor *sensor = &data->sensor; | ||
313 | int ret; | ||
314 | |||
315 | /* enable clock for tsensor */ | ||
316 | ret = clk_prepare_enable(data->clk); | ||
317 | if (ret) | ||
318 | return ret; | ||
120 | 319 | ||
121 | /* disable module firstly */ | 320 | /* disable module firstly */ |
122 | writel(0x0, data->regs + TEMP0_RST_MSK); | 321 | hi6220_thermal_reset_enable(data->regs, 0); |
123 | writel(0x0, data->regs + TEMP0_EN); | 322 | hi6220_thermal_enable(data->regs, 0); |
124 | 323 | ||
125 | /* select sensor id */ | 324 | /* select sensor id */ |
126 | writel((sensor->id << 12), data->regs + TEMP0_CFG); | 325 | hi6220_thermal_sensor_select(data->regs, sensor->id); |
326 | |||
327 | /* setting the hdak time */ | ||
328 | hi6220_thermal_hdak_set(data->regs, 0); | ||
329 | |||
330 | /* setting lag value between current temp and the threshold */ | ||
331 | hi6220_thermal_set_lag(data->regs, HI6220_TEMP_LAG); | ||
127 | 332 | ||
128 | /* enable for interrupt */ | 333 | /* enable for interrupt */ |
129 | writel(_temp_to_step(sensor->thres_temp) | 0x0FFFFFF00, | 334 | hi6220_thermal_alarm_set(data->regs, sensor->thres_temp); |
130 | data->regs + TEMP0_TH); | ||
131 | 335 | ||
132 | writel(_temp_to_step(HISI_TEMP_RESET), data->regs + TEMP0_RST_TH); | 336 | hi6220_thermal_reset_set(data->regs, HI6220_TEMP_RESET); |
133 | 337 | ||
134 | /* enable module */ | 338 | /* enable module */ |
135 | writel(0x1, data->regs + TEMP0_RST_MSK); | 339 | hi6220_thermal_reset_enable(data->regs, 1); |
136 | writel(0x1, data->regs + TEMP0_EN); | 340 | hi6220_thermal_enable(data->regs, 1); |
137 | |||
138 | writel(0x0, data->regs + TEMP0_INT_CLR); | ||
139 | writel(0x1, data->regs + TEMP0_INT_EN); | ||
140 | 341 | ||
141 | usleep_range(3000, 5000); | 342 | hi6220_thermal_alarm_clear(data->regs, 0); |
343 | hi6220_thermal_alarm_enable(data->regs, 1); | ||
142 | 344 | ||
143 | mutex_unlock(&data->thermal_lock); | 345 | return 0; |
144 | } | 346 | } |
145 | 347 | ||
146 | static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) | 348 | static int hi3660_thermal_enable_sensor(struct hisi_thermal_data *data) |
147 | { | 349 | { |
148 | mutex_lock(&data->thermal_lock); | 350 | unsigned int value; |
351 | struct hisi_thermal_sensor *sensor = &data->sensor; | ||
149 | 352 | ||
150 | /* disable sensor module */ | 353 | /* disable interrupt */ |
151 | writel(0x0, data->regs + TEMP0_INT_EN); | 354 | hi3660_thermal_alarm_enable(data->regs, sensor->id, 0); |
152 | writel(0x0, data->regs + TEMP0_RST_MSK); | ||
153 | writel(0x0, data->regs + TEMP0_EN); | ||
154 | 355 | ||
155 | mutex_unlock(&data->thermal_lock); | 356 | /* setting lag value between current temp and the threshold */ |
156 | } | 357 | hi3660_thermal_set_lag(data->regs, sensor->id, HI3660_TEMP_LAG); |
157 | 358 | ||
158 | static int hisi_thermal_get_temp(void *_sensor, int *temp) | 359 | /* set interrupt threshold */ |
159 | { | 360 | value = hi3660_thermal_temp_to_step(sensor->thres_temp); |
160 | struct hisi_thermal_sensor *sensor = _sensor; | 361 | hi3660_thermal_alarm_set(data->regs, sensor->id, value); |
161 | struct hisi_thermal_data *data = sensor->thermal; | ||
162 | 362 | ||
163 | int sensor_id = -1, i; | 363 | /* enable interrupt */ |
164 | long max_temp = 0; | 364 | hi3660_thermal_alarm_clear(data->regs, sensor->id, 1); |
365 | hi3660_thermal_alarm_enable(data->regs, sensor->id, 1); | ||
165 | 366 | ||
166 | *temp = hisi_thermal_get_sensor_temp(data, sensor); | 367 | return 0; |
368 | } | ||
167 | 369 | ||
168 | sensor->sensor_temp = *temp; | 370 | static int hi6220_thermal_probe(struct hisi_thermal_data *data) |
371 | { | ||
372 | struct platform_device *pdev = data->pdev; | ||
373 | struct device *dev = &pdev->dev; | ||
374 | struct resource *res; | ||
375 | int ret; | ||
169 | 376 | ||
170 | for (i = 0; i < HISI_MAX_SENSORS; i++) { | 377 | data->get_temp = hi6220_thermal_get_temp; |
171 | if (!data->sensors[i].tzd) | 378 | data->enable_sensor = hi6220_thermal_enable_sensor; |
172 | continue; | 379 | data->disable_sensor = hi6220_thermal_disable_sensor; |
380 | data->irq_handler = hi6220_thermal_irq_handler; | ||
173 | 381 | ||
174 | if (data->sensors[i].sensor_temp >= max_temp) { | 382 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
175 | max_temp = data->sensors[i].sensor_temp; | 383 | data->regs = devm_ioremap_resource(dev, res); |
176 | sensor_id = i; | 384 | if (IS_ERR(data->regs)) { |
177 | } | 385 | dev_err(dev, "failed to get io address\n"); |
386 | return PTR_ERR(data->regs); | ||
178 | } | 387 | } |
179 | 388 | ||
180 | /* If no sensor has been enabled, then skip to enable irq */ | 389 | data->clk = devm_clk_get(dev, "thermal_clk"); |
181 | if (sensor_id == -1) | 390 | if (IS_ERR(data->clk)) { |
182 | return 0; | 391 | ret = PTR_ERR(data->clk); |
183 | 392 | if (ret != -EPROBE_DEFER) | |
184 | mutex_lock(&data->thermal_lock); | 393 | dev_err(dev, "failed to get thermal clk: %d\n", ret); |
185 | data->irq_bind_sensor = sensor_id; | 394 | return ret; |
186 | mutex_unlock(&data->thermal_lock); | ||
187 | |||
188 | dev_dbg(&data->pdev->dev, "id=%d, irq=%d, temp=%d, thres=%d\n", | ||
189 | sensor->id, data->irq_enabled, *temp, sensor->thres_temp); | ||
190 | /* | ||
191 | * Bind irq to sensor for two cases: | ||
192 | * Reenable alarm IRQ if temperature below threshold; | ||
193 | * if irq has been enabled, always set it; | ||
194 | */ | ||
195 | if (data->irq_enabled) { | ||
196 | hisi_thermal_enable_bind_irq_sensor(data); | ||
197 | return 0; | ||
198 | } | 395 | } |
199 | 396 | ||
200 | if (max_temp < sensor->thres_temp) { | 397 | data->irq = platform_get_irq(pdev, 0); |
201 | data->irq_enabled = true; | 398 | if (data->irq < 0) |
202 | hisi_thermal_enable_bind_irq_sensor(data); | 399 | return data->irq; |
203 | enable_irq(data->irq); | 400 | |
204 | } | 401 | data->sensor.id = HI6220_DEFAULT_SENSOR; |
205 | 402 | ||
206 | return 0; | 403 | return 0; |
207 | } | 404 | } |
208 | 405 | ||
209 | static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = { | 406 | static int hi3660_thermal_probe(struct hisi_thermal_data *data) |
210 | .get_temp = hisi_thermal_get_temp, | 407 | { |
211 | }; | 408 | struct platform_device *pdev = data->pdev; |
409 | struct device *dev = &pdev->dev; | ||
410 | struct resource *res; | ||
411 | |||
412 | data->get_temp = hi3660_thermal_get_temp; | ||
413 | data->enable_sensor = hi3660_thermal_enable_sensor; | ||
414 | data->disable_sensor = hi3660_thermal_disable_sensor; | ||
415 | data->irq_handler = hi3660_thermal_irq_handler; | ||
416 | |||
417 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
418 | data->regs = devm_ioremap_resource(dev, res); | ||
419 | if (IS_ERR(data->regs)) { | ||
420 | dev_err(dev, "failed to get io address\n"); | ||
421 | return PTR_ERR(data->regs); | ||
422 | } | ||
212 | 423 | ||
213 | static irqreturn_t hisi_thermal_alarm_irq(int irq, void *dev) | 424 | data->irq = platform_get_irq(pdev, 0); |
425 | if (data->irq < 0) | ||
426 | return data->irq; | ||
427 | |||
428 | data->sensor.id = HI3660_DEFAULT_SENSOR; | ||
429 | |||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int hisi_thermal_get_temp(void *__data, int *temp) | ||
214 | { | 434 | { |
215 | struct hisi_thermal_data *data = dev; | 435 | struct hisi_thermal_data *data = __data; |
436 | struct hisi_thermal_sensor *sensor = &data->sensor; | ||
216 | 437 | ||
217 | disable_irq_nosync(irq); | 438 | *temp = data->get_temp(data); |
218 | data->irq_enabled = false; | ||
219 | 439 | ||
220 | return IRQ_WAKE_THREAD; | 440 | dev_dbg(&data->pdev->dev, "id=%d, temp=%d, thres=%d\n", |
441 | sensor->id, *temp, sensor->thres_temp); | ||
442 | |||
443 | return 0; | ||
221 | } | 444 | } |
222 | 445 | ||
446 | static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = { | ||
447 | .get_temp = hisi_thermal_get_temp, | ||
448 | }; | ||
449 | |||
223 | static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) | 450 | static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) |
224 | { | 451 | { |
225 | struct hisi_thermal_data *data = dev; | 452 | struct hisi_thermal_data *data = dev; |
226 | struct hisi_thermal_sensor *sensor; | 453 | struct hisi_thermal_sensor *sensor = &data->sensor; |
227 | int i; | 454 | int temp = 0; |
228 | 455 | ||
229 | mutex_lock(&data->thermal_lock); | 456 | data->irq_handler(data); |
230 | sensor = &data->sensors[data->irq_bind_sensor]; | ||
231 | 457 | ||
232 | dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", | 458 | hisi_thermal_get_temp(data, &temp); |
233 | sensor->thres_temp / 1000); | ||
234 | mutex_unlock(&data->thermal_lock); | ||
235 | 459 | ||
236 | for (i = 0; i < HISI_MAX_SENSORS; i++) { | 460 | if (temp >= sensor->thres_temp) { |
237 | if (!data->sensors[i].tzd) | 461 | dev_crit(&data->pdev->dev, "THERMAL ALARM: %d > %d\n", |
238 | continue; | 462 | temp, sensor->thres_temp); |
239 | 463 | ||
240 | thermal_zone_device_update(data->sensors[i].tzd, | 464 | thermal_zone_device_update(data->sensor.tzd, |
241 | THERMAL_EVENT_UNSPECIFIED); | 465 | THERMAL_EVENT_UNSPECIFIED); |
466 | |||
467 | } else { | ||
468 | dev_crit(&data->pdev->dev, "THERMAL ALARM stopped: %d < %d\n", | ||
469 | temp, sensor->thres_temp); | ||
242 | } | 470 | } |
243 | 471 | ||
244 | return IRQ_HANDLED; | 472 | return IRQ_HANDLED; |
@@ -246,17 +474,14 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) | |||
246 | 474 | ||
247 | static int hisi_thermal_register_sensor(struct platform_device *pdev, | 475 | static int hisi_thermal_register_sensor(struct platform_device *pdev, |
248 | struct hisi_thermal_data *data, | 476 | struct hisi_thermal_data *data, |
249 | struct hisi_thermal_sensor *sensor, | 477 | struct hisi_thermal_sensor *sensor) |
250 | int index) | ||
251 | { | 478 | { |
252 | int ret, i; | 479 | int ret, i; |
253 | const struct thermal_trip *trip; | 480 | const struct thermal_trip *trip; |
254 | 481 | ||
255 | sensor->id = index; | ||
256 | sensor->thermal = data; | ||
257 | |||
258 | sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, | 482 | sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, |
259 | sensor->id, sensor, &hisi_of_thermal_ops); | 483 | sensor->id, data, |
484 | &hisi_of_thermal_ops); | ||
260 | if (IS_ERR(sensor->tzd)) { | 485 | if (IS_ERR(sensor->tzd)) { |
261 | ret = PTR_ERR(sensor->tzd); | 486 | ret = PTR_ERR(sensor->tzd); |
262 | sensor->tzd = NULL; | 487 | sensor->tzd = NULL; |
@@ -278,7 +503,14 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, | |||
278 | } | 503 | } |
279 | 504 | ||
280 | static const struct of_device_id of_hisi_thermal_match[] = { | 505 | static const struct of_device_id of_hisi_thermal_match[] = { |
281 | { .compatible = "hisilicon,tsensor" }, | 506 | { |
507 | .compatible = "hisilicon,tsensor", | ||
508 | .data = hi6220_thermal_probe | ||
509 | }, | ||
510 | { | ||
511 | .compatible = "hisilicon,hi3660-tsensor", | ||
512 | .data = hi3660_thermal_probe | ||
513 | }, | ||
282 | { /* end */ } | 514 | { /* end */ } |
283 | }; | 515 | }; |
284 | MODULE_DEVICE_TABLE(of, of_hisi_thermal_match); | 516 | MODULE_DEVICE_TABLE(of, of_hisi_thermal_match); |
@@ -295,88 +527,63 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, | |||
295 | static int hisi_thermal_probe(struct platform_device *pdev) | 527 | static int hisi_thermal_probe(struct platform_device *pdev) |
296 | { | 528 | { |
297 | struct hisi_thermal_data *data; | 529 | struct hisi_thermal_data *data; |
298 | struct resource *res; | 530 | int const (*platform_probe)(struct hisi_thermal_data *); |
299 | int i; | 531 | struct device *dev = &pdev->dev; |
300 | int ret; | 532 | int ret; |
301 | 533 | ||
302 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 534 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
303 | if (!data) | 535 | if (!data) |
304 | return -ENOMEM; | 536 | return -ENOMEM; |
305 | 537 | ||
306 | mutex_init(&data->thermal_lock); | ||
307 | data->pdev = pdev; | 538 | data->pdev = pdev; |
539 | platform_set_drvdata(pdev, data); | ||
308 | 540 | ||
309 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 541 | platform_probe = of_device_get_match_data(dev); |
310 | data->regs = devm_ioremap_resource(&pdev->dev, res); | 542 | if (!platform_probe) { |
311 | if (IS_ERR(data->regs)) { | 543 | dev_err(dev, "failed to get probe func\n"); |
312 | dev_err(&pdev->dev, "failed to get io address\n"); | 544 | return -EINVAL; |
313 | return PTR_ERR(data->regs); | ||
314 | } | 545 | } |
315 | 546 | ||
316 | data->irq = platform_get_irq(pdev, 0); | 547 | ret = platform_probe(data); |
317 | if (data->irq < 0) | 548 | if (ret) |
318 | return data->irq; | ||
319 | |||
320 | ret = devm_request_threaded_irq(&pdev->dev, data->irq, | ||
321 | hisi_thermal_alarm_irq, | ||
322 | hisi_thermal_alarm_irq_thread, | ||
323 | 0, "hisi_thermal", data); | ||
324 | if (ret < 0) { | ||
325 | dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); | ||
326 | return ret; | 549 | return ret; |
327 | } | ||
328 | 550 | ||
329 | platform_set_drvdata(pdev, data); | 551 | ret = hisi_thermal_register_sensor(pdev, data, |
330 | 552 | &data->sensor); | |
331 | data->clk = devm_clk_get(&pdev->dev, "thermal_clk"); | 553 | if (ret) { |
332 | if (IS_ERR(data->clk)) { | 554 | dev_err(dev, "failed to register thermal sensor: %d\n", ret); |
333 | ret = PTR_ERR(data->clk); | ||
334 | if (ret != -EPROBE_DEFER) | ||
335 | dev_err(&pdev->dev, | ||
336 | "failed to get thermal clk: %d\n", ret); | ||
337 | return ret; | 555 | return ret; |
338 | } | 556 | } |
339 | 557 | ||
340 | /* enable clock for thermal */ | 558 | ret = data->enable_sensor(data); |
341 | ret = clk_prepare_enable(data->clk); | ||
342 | if (ret) { | 559 | if (ret) { |
343 | dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret); | 560 | dev_err(dev, "Failed to setup the sensor: %d\n", ret); |
344 | return ret; | 561 | return ret; |
345 | } | 562 | } |
346 | 563 | ||
347 | hisi_thermal_enable_bind_irq_sensor(data); | 564 | if (data->irq) { |
348 | irq_get_irqchip_state(data->irq, IRQCHIP_STATE_MASKED, | 565 | ret = devm_request_threaded_irq(dev, data->irq, NULL, |
349 | &data->irq_enabled); | 566 | hisi_thermal_alarm_irq_thread, |
350 | 567 | IRQF_ONESHOT, "hisi_thermal", data); | |
351 | for (i = 0; i < HISI_MAX_SENSORS; ++i) { | 568 | if (ret < 0) { |
352 | ret = hisi_thermal_register_sensor(pdev, data, | 569 | dev_err(dev, "failed to request alarm irq: %d\n", ret); |
353 | &data->sensors[i], i); | 570 | return ret; |
354 | if (ret) | 571 | } |
355 | dev_err(&pdev->dev, | ||
356 | "failed to register thermal sensor: %d\n", ret); | ||
357 | else | ||
358 | hisi_thermal_toggle_sensor(&data->sensors[i], true); | ||
359 | } | 572 | } |
360 | 573 | ||
574 | hisi_thermal_toggle_sensor(&data->sensor, true); | ||
575 | |||
361 | return 0; | 576 | return 0; |
362 | } | 577 | } |
363 | 578 | ||
364 | static int hisi_thermal_remove(struct platform_device *pdev) | 579 | static int hisi_thermal_remove(struct platform_device *pdev) |
365 | { | 580 | { |
366 | struct hisi_thermal_data *data = platform_get_drvdata(pdev); | 581 | struct hisi_thermal_data *data = platform_get_drvdata(pdev); |
367 | int i; | 582 | struct hisi_thermal_sensor *sensor = &data->sensor; |
368 | 583 | ||
369 | for (i = 0; i < HISI_MAX_SENSORS; i++) { | 584 | hisi_thermal_toggle_sensor(sensor, false); |
370 | struct hisi_thermal_sensor *sensor = &data->sensors[i]; | ||
371 | 585 | ||
372 | if (!sensor->tzd) | 586 | data->disable_sensor(data); |
373 | continue; | ||
374 | |||
375 | hisi_thermal_toggle_sensor(sensor, false); | ||
376 | } | ||
377 | |||
378 | hisi_thermal_disable_sensor(data); | ||
379 | clk_disable_unprepare(data->clk); | ||
380 | 587 | ||
381 | return 0; | 588 | return 0; |
382 | } | 589 | } |
@@ -386,10 +593,7 @@ static int hisi_thermal_suspend(struct device *dev) | |||
386 | { | 593 | { |
387 | struct hisi_thermal_data *data = dev_get_drvdata(dev); | 594 | struct hisi_thermal_data *data = dev_get_drvdata(dev); |
388 | 595 | ||
389 | hisi_thermal_disable_sensor(data); | 596 | data->disable_sensor(data); |
390 | data->irq_enabled = false; | ||
391 | |||
392 | clk_disable_unprepare(data->clk); | ||
393 | 597 | ||
394 | return 0; | 598 | return 0; |
395 | } | 599 | } |
@@ -397,16 +601,8 @@ static int hisi_thermal_suspend(struct device *dev) | |||
397 | static int hisi_thermal_resume(struct device *dev) | 601 | static int hisi_thermal_resume(struct device *dev) |
398 | { | 602 | { |
399 | struct hisi_thermal_data *data = dev_get_drvdata(dev); | 603 | struct hisi_thermal_data *data = dev_get_drvdata(dev); |
400 | int ret; | ||
401 | 604 | ||
402 | ret = clk_prepare_enable(data->clk); | 605 | return data->enable_sensor(data); |
403 | if (ret) | ||
404 | return ret; | ||
405 | |||
406 | data->irq_enabled = true; | ||
407 | hisi_thermal_enable_bind_irq_sensor(data); | ||
408 | |||
409 | return 0; | ||
410 | } | 606 | } |
411 | #endif | 607 | #endif |
412 | 608 | ||
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 4798b4b1fd77..e7d4ffc3de7f 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/thermal.h> | 26 | #include <linux/thermal.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/nvmem-consumer.h> | ||
28 | 29 | ||
29 | #define REG_SET 0x4 | 30 | #define REG_SET 0x4 |
30 | #define REG_CLR 0x8 | 31 | #define REG_CLR 0x8 |
@@ -94,7 +95,7 @@ struct imx_thermal_data { | |||
94 | struct thermal_cooling_device *cdev; | 95 | struct thermal_cooling_device *cdev; |
95 | enum thermal_device_mode mode; | 96 | enum thermal_device_mode mode; |
96 | struct regmap *tempmon; | 97 | struct regmap *tempmon; |
97 | u32 c1, c2; /* See formula in imx_get_sensor_data() */ | 98 | u32 c1, c2; /* See formula in imx_init_calib() */ |
98 | int temp_passive; | 99 | int temp_passive; |
99 | int temp_critical; | 100 | int temp_critical; |
100 | int temp_max; | 101 | int temp_max; |
@@ -177,7 +178,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) | |||
177 | 178 | ||
178 | n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; | 179 | n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; |
179 | 180 | ||
180 | /* See imx_get_sensor_data() for formula derivation */ | 181 | /* See imx_init_calib() for formula derivation */ |
181 | *temp = data->c2 - n_meas * data->c1; | 182 | *temp = data->c2 - n_meas * data->c1; |
182 | 183 | ||
183 | /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ | 184 | /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ |
@@ -346,29 +347,12 @@ static struct thermal_zone_device_ops imx_tz_ops = { | |||
346 | .set_trip_temp = imx_set_trip_temp, | 347 | .set_trip_temp = imx_set_trip_temp, |
347 | }; | 348 | }; |
348 | 349 | ||
349 | static int imx_get_sensor_data(struct platform_device *pdev) | 350 | static int imx_init_calib(struct platform_device *pdev, u32 val) |
350 | { | 351 | { |
351 | struct imx_thermal_data *data = platform_get_drvdata(pdev); | 352 | struct imx_thermal_data *data = platform_get_drvdata(pdev); |
352 | struct regmap *map; | ||
353 | int t1, n1; | 353 | int t1, n1; |
354 | int ret; | ||
355 | u32 val; | ||
356 | u64 temp64; | 354 | u64 temp64; |
357 | 355 | ||
358 | map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | ||
359 | "fsl,tempmon-data"); | ||
360 | if (IS_ERR(map)) { | ||
361 | ret = PTR_ERR(map); | ||
362 | dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret); | ||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | ret = regmap_read(map, OCOTP_ANA1, &val); | ||
367 | if (ret) { | ||
368 | dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret); | ||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | if (val == 0 || val == ~0) { | 356 | if (val == 0 || val == ~0) { |
373 | dev_err(&pdev->dev, "invalid sensor calibration data\n"); | 357 | dev_err(&pdev->dev, "invalid sensor calibration data\n"); |
374 | return -EINVAL; | 358 | return -EINVAL; |
@@ -405,12 +389,12 @@ static int imx_get_sensor_data(struct platform_device *pdev) | |||
405 | data->c1 = temp64; | 389 | data->c1 = temp64; |
406 | data->c2 = n1 * data->c1 + 1000 * t1; | 390 | data->c2 = n1 * data->c1 + 1000 * t1; |
407 | 391 | ||
408 | /* use OTP for thermal grade */ | 392 | return 0; |
409 | ret = regmap_read(map, OCOTP_MEM0, &val); | 393 | } |
410 | if (ret) { | 394 | |
411 | dev_err(&pdev->dev, "failed to read temp grade: %d\n", ret); | 395 | static void imx_init_temp_grade(struct platform_device *pdev, u32 val) |
412 | return ret; | 396 | { |
413 | } | 397 | struct imx_thermal_data *data = platform_get_drvdata(pdev); |
414 | 398 | ||
415 | /* The maximum die temp is specified by the Temperature Grade */ | 399 | /* The maximum die temp is specified by the Temperature Grade */ |
416 | switch ((val >> 6) & 0x3) { | 400 | switch ((val >> 6) & 0x3) { |
@@ -438,6 +422,55 @@ static int imx_get_sensor_data(struct platform_device *pdev) | |||
438 | */ | 422 | */ |
439 | data->temp_critical = data->temp_max - (1000 * 5); | 423 | data->temp_critical = data->temp_max - (1000 * 5); |
440 | data->temp_passive = data->temp_max - (1000 * 10); | 424 | data->temp_passive = data->temp_max - (1000 * 10); |
425 | } | ||
426 | |||
427 | static int imx_init_from_tempmon_data(struct platform_device *pdev) | ||
428 | { | ||
429 | struct regmap *map; | ||
430 | int ret; | ||
431 | u32 val; | ||
432 | |||
433 | map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | ||
434 | "fsl,tempmon-data"); | ||
435 | if (IS_ERR(map)) { | ||
436 | ret = PTR_ERR(map); | ||
437 | dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret); | ||
438 | return ret; | ||
439 | } | ||
440 | |||
441 | ret = regmap_read(map, OCOTP_ANA1, &val); | ||
442 | if (ret) { | ||
443 | dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret); | ||
444 | return ret; | ||
445 | } | ||
446 | ret = imx_init_calib(pdev, val); | ||
447 | if (ret) | ||
448 | return ret; | ||
449 | |||
450 | ret = regmap_read(map, OCOTP_MEM0, &val); | ||
451 | if (ret) { | ||
452 | dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret); | ||
453 | return ret; | ||
454 | } | ||
455 | imx_init_temp_grade(pdev, val); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int imx_init_from_nvmem_cells(struct platform_device *pdev) | ||
461 | { | ||
462 | int ret; | ||
463 | u32 val; | ||
464 | |||
465 | ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val); | ||
466 | if (ret) | ||
467 | return ret; | ||
468 | imx_init_calib(pdev, val); | ||
469 | |||
470 | ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val); | ||
471 | if (ret) | ||
472 | return ret; | ||
473 | imx_init_temp_grade(pdev, val); | ||
441 | 474 | ||
442 | return 0; | 475 | return 0; |
443 | } | 476 | } |
@@ -514,10 +547,21 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
514 | 547 | ||
515 | platform_set_drvdata(pdev, data); | 548 | platform_set_drvdata(pdev, data); |
516 | 549 | ||
517 | ret = imx_get_sensor_data(pdev); | 550 | if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) { |
518 | if (ret) { | 551 | ret = imx_init_from_nvmem_cells(pdev); |
519 | dev_err(&pdev->dev, "failed to get sensor data\n"); | 552 | if (ret == -EPROBE_DEFER) |
520 | return ret; | 553 | return ret; |
554 | if (ret) { | ||
555 | dev_err(&pdev->dev, "failed to init from nvmem: %d\n", | ||
556 | ret); | ||
557 | return ret; | ||
558 | } | ||
559 | } else { | ||
560 | ret = imx_init_from_tempmon_data(pdev); | ||
561 | if (ret) { | ||
562 | dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n"); | ||
563 | return ret; | ||
564 | } | ||
521 | } | 565 | } |
522 | 566 | ||
523 | /* Make sure sensor is in known good state for measurements */ | 567 | /* Make sure sensor is in known good state for measurements */ |
diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c index f02341f7134d..80bbf9ce2fb6 100644 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c | |||
@@ -30,6 +30,10 @@ | |||
30 | /* Skylake thermal reporting device */ | 30 | /* Skylake thermal reporting device */ |
31 | #define PCI_DEVICE_ID_PROC_SKL_THERMAL 0x1903 | 31 | #define PCI_DEVICE_ID_PROC_SKL_THERMAL 0x1903 |
32 | 32 | ||
33 | /* CannonLake thermal reporting device */ | ||
34 | #define PCI_DEVICE_ID_PROC_CNL_THERMAL 0x5a03 | ||
35 | #define PCI_DEVICE_ID_PROC_CFL_THERMAL 0x3E83 | ||
36 | |||
33 | /* Braswell thermal reporting device */ | 37 | /* Braswell thermal reporting device */ |
34 | #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC | 38 | #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC |
35 | 39 | ||
@@ -461,6 +465,8 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { | |||
461 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT1_THERMAL)}, | 465 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT1_THERMAL)}, |
462 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, | 466 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, |
463 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, | 467 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, |
468 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CNL_THERMAL)}, | ||
469 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CFL_THERMAL)}, | ||
464 | { 0, }, | 470 | { 0, }, |
465 | }; | 471 | }; |
466 | 472 | ||
diff --git a/drivers/thermal/intel_bxt_pmic_thermal.c b/drivers/thermal/intel_bxt_pmic_thermal.c index ef6b32242ccb..94cfd0064c43 100644 --- a/drivers/thermal/intel_bxt_pmic_thermal.c +++ b/drivers/thermal/intel_bxt_pmic_thermal.c | |||
@@ -166,7 +166,7 @@ static irqreturn_t pmic_thermal_irq_handler(int irq, void *data) | |||
166 | struct pmic_thermal_data *td; | 166 | struct pmic_thermal_data *td; |
167 | struct intel_soc_pmic *pmic; | 167 | struct intel_soc_pmic *pmic; |
168 | struct regmap *regmap; | 168 | struct regmap *regmap; |
169 | u8 reg_val, mask, irq_stat, trip; | 169 | u8 reg_val, mask, irq_stat; |
170 | u16 reg, evt_stat_reg; | 170 | u16 reg, evt_stat_reg; |
171 | int i, j, ret; | 171 | int i, j, ret; |
172 | 172 | ||
@@ -201,7 +201,6 @@ static irqreturn_t pmic_thermal_irq_handler(int irq, void *data) | |||
201 | if (regmap_read(regmap, evt_stat_reg, &ret)) | 201 | if (regmap_read(regmap, evt_stat_reg, &ret)) |
202 | return IRQ_HANDLED; | 202 | return IRQ_HANDLED; |
203 | 203 | ||
204 | trip = td->maps[i].trip_config[j].trip_num; | ||
205 | tzd = thermal_zone_get_zone_by_name(td->maps[i].handle); | 204 | tzd = thermal_zone_get_zone_by_name(td->maps[i].handle); |
206 | if (!IS_ERR(tzd)) | 205 | if (!IS_ERR(tzd)) |
207 | thermal_zone_device_update(tzd, | 206 | thermal_zone_device_update(tzd, |
diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c index c60b1cfcc64e..8a7f69b4b022 100644 --- a/drivers/thermal/intel_pch_thermal.c +++ b/drivers/thermal/intel_pch_thermal.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */ | 30 | #define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */ |
31 | #define PCH_THERMAL_DID_SKL 0x9D31 /* Skylake PCH */ | 31 | #define PCH_THERMAL_DID_SKL 0x9D31 /* Skylake PCH */ |
32 | #define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */ | 32 | #define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */ |
33 | #define PCH_THERMAL_DID_CNL 0x9Df9 /* CNL PCH */ | ||
34 | #define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */ | ||
33 | 35 | ||
34 | /* Wildcat Point-LP PCH Thermal registers */ | 36 | /* Wildcat Point-LP PCH Thermal registers */ |
35 | #define WPT_TEMP 0x0000 /* Temperature */ | 37 | #define WPT_TEMP 0x0000 /* Temperature */ |
@@ -278,6 +280,7 @@ enum board_ids { | |||
278 | board_hsw, | 280 | board_hsw, |
279 | board_wpt, | 281 | board_wpt, |
280 | board_skl, | 282 | board_skl, |
283 | board_cnl, | ||
281 | }; | 284 | }; |
282 | 285 | ||
283 | static const struct board_info { | 286 | static const struct board_info { |
@@ -296,6 +299,10 @@ static const struct board_info { | |||
296 | .name = "pch_skylake", | 299 | .name = "pch_skylake", |
297 | .ops = &pch_dev_ops_wpt, | 300 | .ops = &pch_dev_ops_wpt, |
298 | }, | 301 | }, |
302 | [board_cnl] = { | ||
303 | .name = "pch_cannonlake", | ||
304 | .ops = &pch_dev_ops_wpt, | ||
305 | }, | ||
299 | }; | 306 | }; |
300 | 307 | ||
301 | static int intel_pch_thermal_probe(struct pci_dev *pdev, | 308 | static int intel_pch_thermal_probe(struct pci_dev *pdev, |
@@ -398,6 +405,10 @@ static const struct pci_device_id intel_pch_thermal_id[] = { | |||
398 | .driver_data = board_skl, }, | 405 | .driver_data = board_skl, }, |
399 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL_H), | 406 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL_H), |
400 | .driver_data = board_skl, }, | 407 | .driver_data = board_skl, }, |
408 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL), | ||
409 | .driver_data = board_cnl, }, | ||
410 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H), | ||
411 | .driver_data = board_cnl, }, | ||
401 | { 0, }, | 412 | { 0, }, |
402 | }; | 413 | }; |
403 | MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); | 414 | MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); |
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index d718cd179ddb..4540e892b61d 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c | |||
@@ -675,13 +675,13 @@ static int __init powerclamp_probe(void) | |||
675 | { | 675 | { |
676 | 676 | ||
677 | if (!x86_match_cpu(intel_powerclamp_ids)) { | 677 | if (!x86_match_cpu(intel_powerclamp_ids)) { |
678 | pr_err("CPU does not support MWAIT"); | 678 | pr_err("CPU does not support MWAIT\n"); |
679 | return -ENODEV; | 679 | return -ENODEV; |
680 | } | 680 | } |
681 | 681 | ||
682 | /* The goal for idle time alignment is to achieve package cstate. */ | 682 | /* The goal for idle time alignment is to achieve package cstate. */ |
683 | if (!has_pkg_state_counter()) { | 683 | if (!has_pkg_state_counter()) { |
684 | pr_info("No package C-state available"); | 684 | pr_info("No package C-state available\n"); |
685 | return -ENODEV; | 685 | return -ENODEV; |
686 | } | 686 | } |
687 | 687 | ||
diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c index f50241962ad2..95f987d5aa71 100644 --- a/drivers/thermal/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom-spmi-temp-alarm.c | |||
@@ -125,7 +125,7 @@ static int qpnp_tm_get_temp(void *data, int *temp) | |||
125 | if (!temp) | 125 | if (!temp) |
126 | return -EINVAL; | 126 | return -EINVAL; |
127 | 127 | ||
128 | if (IS_ERR(chip->adc)) { | 128 | if (!chip->adc) { |
129 | ret = qpnp_tm_update_temp_no_adc(chip); | 129 | ret = qpnp_tm_update_temp_no_adc(chip); |
130 | if (ret < 0) | 130 | if (ret < 0) |
131 | return ret; | 131 | return ret; |
@@ -224,67 +224,53 @@ static int qpnp_tm_probe(struct platform_device *pdev) | |||
224 | return irq; | 224 | return irq; |
225 | 225 | ||
226 | /* ADC based measurements are optional */ | 226 | /* ADC based measurements are optional */ |
227 | chip->adc = iio_channel_get(&pdev->dev, "thermal"); | 227 | chip->adc = devm_iio_channel_get(&pdev->dev, "thermal"); |
228 | if (PTR_ERR(chip->adc) == -EPROBE_DEFER) | 228 | if (IS_ERR(chip->adc)) { |
229 | return PTR_ERR(chip->adc); | 229 | ret = PTR_ERR(chip->adc); |
230 | chip->adc = NULL; | ||
231 | if (ret == -EPROBE_DEFER) | ||
232 | return ret; | ||
233 | } | ||
230 | 234 | ||
231 | chip->base = res; | 235 | chip->base = res; |
232 | 236 | ||
233 | ret = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, &type); | 237 | ret = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, &type); |
234 | if (ret < 0) { | 238 | if (ret < 0) { |
235 | dev_err(&pdev->dev, "could not read type\n"); | 239 | dev_err(&pdev->dev, "could not read type\n"); |
236 | goto fail; | 240 | return ret; |
237 | } | 241 | } |
238 | 242 | ||
239 | ret = qpnp_tm_read(chip, QPNP_TM_REG_SUBTYPE, &subtype); | 243 | ret = qpnp_tm_read(chip, QPNP_TM_REG_SUBTYPE, &subtype); |
240 | if (ret < 0) { | 244 | if (ret < 0) { |
241 | dev_err(&pdev->dev, "could not read subtype\n"); | 245 | dev_err(&pdev->dev, "could not read subtype\n"); |
242 | goto fail; | 246 | return ret; |
243 | } | 247 | } |
244 | 248 | ||
245 | if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) { | 249 | if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) { |
246 | dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", | 250 | dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", |
247 | type, subtype); | 251 | type, subtype); |
248 | ret = -ENODEV; | 252 | return -ENODEV; |
249 | goto fail; | ||
250 | } | 253 | } |
251 | 254 | ||
252 | ret = qpnp_tm_init(chip); | 255 | ret = qpnp_tm_init(chip); |
253 | if (ret < 0) { | 256 | if (ret < 0) { |
254 | dev_err(&pdev->dev, "init failed\n"); | 257 | dev_err(&pdev->dev, "init failed\n"); |
255 | goto fail; | 258 | return ret; |
256 | } | 259 | } |
257 | 260 | ||
258 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, qpnp_tm_isr, | 261 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, qpnp_tm_isr, |
259 | IRQF_ONESHOT, node->name, chip); | 262 | IRQF_ONESHOT, node->name, chip); |
260 | if (ret < 0) | 263 | if (ret < 0) |
261 | goto fail; | 264 | return ret; |
262 | 265 | ||
263 | chip->tz_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, chip, | 266 | chip->tz_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, chip, |
264 | &qpnp_tm_sensor_ops); | 267 | &qpnp_tm_sensor_ops); |
265 | if (IS_ERR(chip->tz_dev)) { | 268 | if (IS_ERR(chip->tz_dev)) { |
266 | dev_err(&pdev->dev, "failed to register sensor\n"); | 269 | dev_err(&pdev->dev, "failed to register sensor\n"); |
267 | ret = PTR_ERR(chip->tz_dev); | 270 | return PTR_ERR(chip->tz_dev); |
268 | goto fail; | ||
269 | } | 271 | } |
270 | 272 | ||
271 | return 0; | 273 | return 0; |
272 | |||
273 | fail: | ||
274 | if (!IS_ERR(chip->adc)) | ||
275 | iio_channel_release(chip->adc); | ||
276 | |||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | static int qpnp_tm_remove(struct platform_device *pdev) | ||
281 | { | ||
282 | struct qpnp_tm_chip *chip = dev_get_drvdata(&pdev->dev); | ||
283 | |||
284 | if (!IS_ERR(chip->adc)) | ||
285 | iio_channel_release(chip->adc); | ||
286 | |||
287 | return 0; | ||
288 | } | 274 | } |
289 | 275 | ||
290 | static const struct of_device_id qpnp_tm_match_table[] = { | 276 | static const struct of_device_id qpnp_tm_match_table[] = { |
@@ -299,7 +285,6 @@ static struct platform_driver qpnp_tm_driver = { | |||
299 | .of_match_table = qpnp_tm_match_table, | 285 | .of_match_table = qpnp_tm_match_table, |
300 | }, | 286 | }, |
301 | .probe = qpnp_tm_probe, | 287 | .probe = qpnp_tm_probe, |
302 | .remove = qpnp_tm_remove, | ||
303 | }; | 288 | }; |
304 | module_platform_driver(qpnp_tm_driver); | 289 | module_platform_driver(qpnp_tm_driver); |
305 | 290 | ||
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 203aca44a2bb..561a0a332208 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/sys_soc.h> | ||
27 | #include <linux/thermal.h> | 28 | #include <linux/thermal.h> |
28 | 29 | ||
29 | #include "thermal_core.h" | 30 | #include "thermal_core.h" |
@@ -90,10 +91,6 @@ struct rcar_gen3_thermal_priv { | |||
90 | struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; | 91 | struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; |
91 | unsigned int num_tscs; | 92 | unsigned int num_tscs; |
92 | spinlock_t lock; /* Protect interrupts on and off */ | 93 | spinlock_t lock; /* Protect interrupts on and off */ |
93 | const struct rcar_gen3_thermal_data *data; | ||
94 | }; | ||
95 | |||
96 | struct rcar_gen3_thermal_data { | ||
97 | void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc); | 94 | void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc); |
98 | }; | 95 | }; |
99 | 96 | ||
@@ -278,7 +275,12 @@ static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data) | |||
278 | return IRQ_HANDLED; | 275 | return IRQ_HANDLED; |
279 | } | 276 | } |
280 | 277 | ||
281 | static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc) | 278 | static const struct soc_device_attribute r8a7795es1[] = { |
279 | { .soc_id = "r8a7795", .revision = "ES1.*" }, | ||
280 | { /* sentinel */ } | ||
281 | }; | ||
282 | |||
283 | static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc) | ||
282 | { | 284 | { |
283 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR); | 285 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR); |
284 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 0x0); | 286 | rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 0x0); |
@@ -303,7 +305,7 @@ static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc) | |||
303 | usleep_range(1000, 2000); | 305 | usleep_range(1000, 2000); |
304 | } | 306 | } |
305 | 307 | ||
306 | static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc) | 308 | static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc) |
307 | { | 309 | { |
308 | u32 reg_val; | 310 | u32 reg_val; |
309 | 311 | ||
@@ -324,17 +326,9 @@ static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc) | |||
324 | usleep_range(1000, 2000); | 326 | usleep_range(1000, 2000); |
325 | } | 327 | } |
326 | 328 | ||
327 | static const struct rcar_gen3_thermal_data r8a7795_data = { | ||
328 | .thermal_init = r8a7795_thermal_init, | ||
329 | }; | ||
330 | |||
331 | static const struct rcar_gen3_thermal_data r8a7796_data = { | ||
332 | .thermal_init = r8a7796_thermal_init, | ||
333 | }; | ||
334 | |||
335 | static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { | 329 | static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { |
336 | { .compatible = "renesas,r8a7795-thermal", .data = &r8a7795_data}, | 330 | { .compatible = "renesas,r8a7795-thermal", }, |
337 | { .compatible = "renesas,r8a7796-thermal", .data = &r8a7796_data}, | 331 | { .compatible = "renesas,r8a7796-thermal", }, |
338 | {}, | 332 | {}, |
339 | }; | 333 | }; |
340 | MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); | 334 | MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); |
@@ -371,7 +365,9 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) | |||
371 | if (!priv) | 365 | if (!priv) |
372 | return -ENOMEM; | 366 | return -ENOMEM; |
373 | 367 | ||
374 | priv->data = of_device_get_match_data(dev); | 368 | priv->thermal_init = rcar_gen3_thermal_init; |
369 | if (soc_device_match(r8a7795es1)) | ||
370 | priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1; | ||
375 | 371 | ||
376 | spin_lock_init(&priv->lock); | 372 | spin_lock_init(&priv->lock); |
377 | 373 | ||
@@ -423,7 +419,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) | |||
423 | 419 | ||
424 | priv->tscs[i] = tsc; | 420 | priv->tscs[i] = tsc; |
425 | 421 | ||
426 | priv->data->thermal_init(tsc); | 422 | priv->thermal_init(tsc); |
427 | rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]); | 423 | rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]); |
428 | 424 | ||
429 | zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, | 425 | zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, |
@@ -476,7 +472,7 @@ static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev) | |||
476 | for (i = 0; i < priv->num_tscs; i++) { | 472 | for (i = 0; i < priv->num_tscs; i++) { |
477 | struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; | 473 | struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; |
478 | 474 | ||
479 | priv->data->thermal_init(tsc); | 475 | priv->thermal_init(tsc); |
480 | rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high); | 476 | rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high); |
481 | } | 477 | } |
482 | 478 | ||
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 206035139110..f36375d5a16c 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c | |||
@@ -242,6 +242,45 @@ struct tsadc_table { | |||
242 | int temp; | 242 | int temp; |
243 | }; | 243 | }; |
244 | 244 | ||
245 | static const struct tsadc_table rv1108_table[] = { | ||
246 | {0, -40000}, | ||
247 | {374, -40000}, | ||
248 | {382, -35000}, | ||
249 | {389, -30000}, | ||
250 | {397, -25000}, | ||
251 | {405, -20000}, | ||
252 | {413, -15000}, | ||
253 | {421, -10000}, | ||
254 | {429, -5000}, | ||
255 | {436, 0}, | ||
256 | {444, 5000}, | ||
257 | {452, 10000}, | ||
258 | {460, 15000}, | ||
259 | {468, 20000}, | ||
260 | {476, 25000}, | ||
261 | {483, 30000}, | ||
262 | {491, 35000}, | ||
263 | {499, 40000}, | ||
264 | {507, 45000}, | ||
265 | {515, 50000}, | ||
266 | {523, 55000}, | ||
267 | {531, 60000}, | ||
268 | {539, 65000}, | ||
269 | {547, 70000}, | ||
270 | {555, 75000}, | ||
271 | {562, 80000}, | ||
272 | {570, 85000}, | ||
273 | {578, 90000}, | ||
274 | {586, 95000}, | ||
275 | {594, 100000}, | ||
276 | {602, 105000}, | ||
277 | {610, 110000}, | ||
278 | {618, 115000}, | ||
279 | {626, 120000}, | ||
280 | {634, 125000}, | ||
281 | {TSADCV2_DATA_MASK, 125000}, | ||
282 | }; | ||
283 | |||
245 | static const struct tsadc_table rk3228_code_table[] = { | 284 | static const struct tsadc_table rk3228_code_table[] = { |
246 | {0, -40000}, | 285 | {0, -40000}, |
247 | {588, -40000}, | 286 | {588, -40000}, |
@@ -779,6 +818,30 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, | |||
779 | writel_relaxed(val, regs + TSADCV2_INT_EN); | 818 | writel_relaxed(val, regs + TSADCV2_INT_EN); |
780 | } | 819 | } |
781 | 820 | ||
821 | static const struct rockchip_tsadc_chip rv1108_tsadc_data = { | ||
822 | .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ | ||
823 | .chn_num = 1, /* one channel for tsadc */ | ||
824 | |||
825 | .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ | ||
826 | .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ | ||
827 | .tshut_temp = 95000, | ||
828 | |||
829 | .initialize = rk_tsadcv2_initialize, | ||
830 | .irq_ack = rk_tsadcv3_irq_ack, | ||
831 | .control = rk_tsadcv3_control, | ||
832 | .get_temp = rk_tsadcv2_get_temp, | ||
833 | .set_alarm_temp = rk_tsadcv2_alarm_temp, | ||
834 | .set_tshut_temp = rk_tsadcv2_tshut_temp, | ||
835 | .set_tshut_mode = rk_tsadcv2_tshut_mode, | ||
836 | |||
837 | .table = { | ||
838 | .id = rv1108_table, | ||
839 | .length = ARRAY_SIZE(rv1108_table), | ||
840 | .data_mask = TSADCV2_DATA_MASK, | ||
841 | .mode = ADC_INCREMENT, | ||
842 | }, | ||
843 | }; | ||
844 | |||
782 | static const struct rockchip_tsadc_chip rk3228_tsadc_data = { | 845 | static const struct rockchip_tsadc_chip rk3228_tsadc_data = { |
783 | .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ | 846 | .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ |
784 | .chn_num = 1, /* one channel for tsadc */ | 847 | .chn_num = 1, /* one channel for tsadc */ |
@@ -928,6 +991,10 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = { | |||
928 | 991 | ||
929 | static const struct of_device_id of_rockchip_thermal_match[] = { | 992 | static const struct of_device_id of_rockchip_thermal_match[] = { |
930 | { | 993 | { |
994 | .compatible = "rockchip,rv1108-tsadc", | ||
995 | .data = (void *)&rv1108_tsadc_data, | ||
996 | }, | ||
997 | { | ||
931 | .compatible = "rockchip,rk3228-tsadc", | 998 | .compatible = "rockchip,rk3228-tsadc", |
932 | .data = (void *)&rk3228_tsadc_data, | 999 | .data = (void *)&rk3228_tsadc_data, |
933 | }, | 1000 | }, |
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c index be95826631b7..ee047ca43084 100644 --- a/drivers/thermal/step_wise.c +++ b/drivers/thermal/step_wise.c | |||
@@ -31,8 +31,7 @@ | |||
31 | * If the temperature is higher than a trip point, | 31 | * If the temperature is higher than a trip point, |
32 | * a. if the trend is THERMAL_TREND_RAISING, use higher cooling | 32 | * a. if the trend is THERMAL_TREND_RAISING, use higher cooling |
33 | * state for this trip point | 33 | * state for this trip point |
34 | * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling | 34 | * b. if the trend is THERMAL_TREND_DROPPING, do nothing |
35 | * state for this trip point | ||
36 | * c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit | 35 | * c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit |
37 | * for this trip point | 36 | * for this trip point |
38 | * d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit | 37 | * d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit |
@@ -94,9 +93,11 @@ static unsigned long get_target_state(struct thermal_instance *instance, | |||
94 | if (!throttle) | 93 | if (!throttle) |
95 | next_target = THERMAL_NO_TARGET; | 94 | next_target = THERMAL_NO_TARGET; |
96 | } else { | 95 | } else { |
97 | next_target = cur_state - 1; | 96 | if (!throttle) { |
98 | if (next_target > instance->upper) | 97 | next_target = cur_state - 1; |
99 | next_target = instance->upper; | 98 | if (next_target > instance->upper) |
99 | next_target = instance->upper; | ||
100 | } | ||
100 | } | 101 | } |
101 | break; | 102 | break; |
102 | case THERMAL_TREND_DROP_FULL: | 103 | case THERMAL_TREND_DROP_FULL: |
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 7d2db23d71a3..075db1de5e53 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c | |||
@@ -483,7 +483,7 @@ static int throttrip_program(struct device *dev, | |||
483 | unsigned int throt; | 483 | unsigned int throt; |
484 | u32 r, reg_off; | 484 | u32 r, reg_off; |
485 | 485 | ||
486 | if (!dev || !sg || !stc || !stc->init) | 486 | if (!sg || !stc || !stc->init) |
487 | return -EINVAL; | 487 | return -EINVAL; |
488 | 488 | ||
489 | temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain; | 489 | temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain; |
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c index 73f55d6a1721..46d3005335c7 100644 --- a/drivers/thermal/thermal-generic-adc.c +++ b/drivers/thermal/thermal-generic-adc.c | |||
@@ -126,38 +126,23 @@ static int gadc_thermal_probe(struct platform_device *pdev) | |||
126 | gti->dev = &pdev->dev; | 126 | gti->dev = &pdev->dev; |
127 | platform_set_drvdata(pdev, gti); | 127 | platform_set_drvdata(pdev, gti); |
128 | 128 | ||
129 | gti->channel = iio_channel_get(&pdev->dev, "sensor-channel"); | 129 | gti->channel = devm_iio_channel_get(&pdev->dev, "sensor-channel"); |
130 | if (IS_ERR(gti->channel)) { | 130 | if (IS_ERR(gti->channel)) { |
131 | ret = PTR_ERR(gti->channel); | 131 | ret = PTR_ERR(gti->channel); |
132 | dev_err(&pdev->dev, "IIO channel not found: %d\n", ret); | 132 | dev_err(&pdev->dev, "IIO channel not found: %d\n", ret); |
133 | return ret; | 133 | return ret; |
134 | } | 134 | } |
135 | 135 | ||
136 | gti->tz_dev = thermal_zone_of_sensor_register(&pdev->dev, 0, | 136 | gti->tz_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, gti, |
137 | gti, &gadc_thermal_ops); | 137 | &gadc_thermal_ops); |
138 | if (IS_ERR(gti->tz_dev)) { | 138 | if (IS_ERR(gti->tz_dev)) { |
139 | ret = PTR_ERR(gti->tz_dev); | 139 | ret = PTR_ERR(gti->tz_dev); |
140 | dev_err(&pdev->dev, "Thermal zone sensor register failed: %d\n", | 140 | dev_err(&pdev->dev, "Thermal zone sensor register failed: %d\n", |
141 | ret); | 141 | ret); |
142 | goto sensor_fail; | 142 | return ret; |
143 | } | 143 | } |
144 | 144 | ||
145 | return 0; | 145 | return 0; |
146 | |||
147 | sensor_fail: | ||
148 | iio_channel_release(gti->channel); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | static int gadc_thermal_remove(struct platform_device *pdev) | ||
154 | { | ||
155 | struct gadc_thermal_info *gti = platform_get_drvdata(pdev); | ||
156 | |||
157 | thermal_zone_of_sensor_unregister(&pdev->dev, gti->tz_dev); | ||
158 | iio_channel_release(gti->channel); | ||
159 | |||
160 | return 0; | ||
161 | } | 146 | } |
162 | 147 | ||
163 | static const struct of_device_id of_adc_thermal_match[] = { | 148 | static const struct of_device_id of_adc_thermal_match[] = { |
@@ -172,7 +157,6 @@ static struct platform_driver gadc_thermal_driver = { | |||
172 | .of_match_table = of_adc_thermal_match, | 157 | .of_match_table = of_adc_thermal_match, |
173 | }, | 158 | }, |
174 | .probe = gadc_thermal_probe, | 159 | .probe = gadc_thermal_probe, |
175 | .remove = gadc_thermal_remove, | ||
176 | }; | 160 | }; |
177 | 161 | ||
178 | module_platform_driver(gadc_thermal_driver); | 162 | module_platform_driver(gadc_thermal_driver); |
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index c211a8e4a210..b4f981daeaf2 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c | |||
@@ -278,7 +278,8 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id) | |||
278 | 278 | ||
279 | if (data) { | 279 | if (data) { |
280 | cpufreq_cooling_unregister(data->cool_dev); | 280 | cpufreq_cooling_unregister(data->cool_dev); |
281 | cpufreq_cpu_put(data->policy); | 281 | if (data->policy) |
282 | cpufreq_cpu_put(data->policy); | ||
282 | } | 283 | } |
283 | 284 | ||
284 | return 0; | 285 | return 0; |