Commit | Line | Data |
---|---|---|
c9545790 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1e426ffd KM |
2 | /* |
3 | * R-Car THS/TSC thermal sensor driver | |
4 | * | |
5 | * Copyright (C) 2012 Renesas Solutions Corp. | |
6 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | |
1e426ffd KM |
7 | */ |
8 | #include <linux/delay.h> | |
9 | #include <linux/err.h> | |
e0a5172e KM |
10 | #include <linux/irq.h> |
11 | #include <linux/interrupt.h> | |
1e426ffd KM |
12 | #include <linux/io.h> |
13 | #include <linux/module.h> | |
8b477ea5 | 14 | #include <linux/of_device.h> |
1e426ffd | 15 | #include <linux/platform_device.h> |
51d45d25 | 16 | #include <linux/pm_runtime.h> |
d2a73e22 | 17 | #include <linux/reboot.h> |
1e426ffd KM |
18 | #include <linux/slab.h> |
19 | #include <linux/spinlock.h> | |
20 | #include <linux/thermal.h> | |
21 | ||
64a411e8 KM |
22 | #include "thermal_hwmon.h" |
23 | ||
d2a73e22 | 24 | #define IDLE_INTERVAL 5000 |
25 | ||
e0a5172e KM |
26 | #define COMMON_STR 0x00 |
27 | #define COMMON_ENR 0x04 | |
28 | #define COMMON_INTMSK 0x0c | |
29 | ||
30 | #define REG_POSNEG 0x20 | |
31 | #define REG_FILONOFF 0x28 | |
e9137a58 KM |
32 | #define REG_THSCR 0x2c |
33 | #define REG_THSSR 0x30 | |
e0a5172e | 34 | #define REG_INTCTRL 0x34 |
1e426ffd KM |
35 | |
36 | /* THSCR */ | |
f8f53e18 | 37 | #define CPCTL (1 << 12) |
1e426ffd KM |
38 | |
39 | /* THSSR */ | |
40 | #define CTEMP 0x3f | |
41 | ||
3676d1dd KM |
42 | struct rcar_thermal_common { |
43 | void __iomem *base; | |
44 | struct device *dev; | |
45 | struct list_head head; | |
e0a5172e | 46 | spinlock_t lock; |
3676d1dd | 47 | }; |
1e426ffd | 48 | |
1969d9dc YK |
49 | struct rcar_thermal_chip { |
50 | unsigned int use_of_thermal : 1; | |
51 | unsigned int has_filonoff : 1; | |
52 | unsigned int irq_per_ch : 1; | |
53 | unsigned int needs_suspend_resume : 1; | |
54 | unsigned int nirqs; | |
20386f0d | 55 | unsigned int ctemp_bands; |
1969d9dc YK |
56 | }; |
57 | ||
58 | static const struct rcar_thermal_chip rcar_thermal = { | |
59 | .use_of_thermal = 0, | |
60 | .has_filonoff = 1, | |
61 | .irq_per_ch = 0, | |
62 | .needs_suspend_resume = 0, | |
63 | .nirqs = 1, | |
20386f0d | 64 | .ctemp_bands = 1, |
1969d9dc YK |
65 | }; |
66 | ||
67 | static const struct rcar_thermal_chip rcar_gen2_thermal = { | |
68 | .use_of_thermal = 1, | |
69 | .has_filonoff = 1, | |
70 | .irq_per_ch = 0, | |
71 | .needs_suspend_resume = 0, | |
72 | .nirqs = 1, | |
20386f0d | 73 | .ctemp_bands = 1, |
1969d9dc YK |
74 | }; |
75 | ||
76 | static const struct rcar_thermal_chip rcar_gen3_thermal = { | |
77 | .use_of_thermal = 1, | |
78 | .has_filonoff = 0, | |
79 | .irq_per_ch = 1, | |
80 | .needs_suspend_resume = 1, | |
81 | /* | |
82 | * The Gen3 chip has 3 interrupts, but this driver uses only 2 | |
83 | * interrupts to detect a temperature change, rise or fall. | |
84 | */ | |
85 | .nirqs = 2, | |
20386f0d | 86 | .ctemp_bands = 2, |
1969d9dc YK |
87 | }; |
88 | ||
1e426ffd KM |
89 | struct rcar_thermal_priv { |
90 | void __iomem *base; | |
3676d1dd KM |
91 | struct rcar_thermal_common *common; |
92 | struct thermal_zone_device *zone; | |
1969d9dc | 93 | const struct rcar_thermal_chip *chip; |
e0a5172e | 94 | struct delayed_work work; |
b2bbc6a2 | 95 | struct mutex lock; |
3676d1dd | 96 | struct list_head list; |
e0a5172e | 97 | int id; |
1e426ffd KM |
98 | }; |
99 | ||
3676d1dd KM |
100 | #define rcar_thermal_for_each_priv(pos, common) \ |
101 | list_for_each_entry(pos, &common->head, list) | |
102 | ||
c499703e | 103 | #define MCELSIUS(temp) ((temp) * 1000) |
3676d1dd KM |
104 | #define rcar_priv_to_dev(priv) ((priv)->common->dev) |
105 | #define rcar_has_irq_support(priv) ((priv)->common->base) | |
e0a5172e KM |
106 | #define rcar_id_to_shift(priv) ((priv)->id * 8) |
107 | ||
ca1e4558 | 108 | static const struct of_device_id rcar_thermal_dt_ids[] = { |
1969d9dc YK |
109 | { |
110 | .compatible = "renesas,rcar-thermal", | |
111 | .data = &rcar_thermal, | |
112 | }, | |
113 | { | |
114 | .compatible = "renesas,rcar-gen2-thermal", | |
115 | .data = &rcar_gen2_thermal, | |
116 | }, | |
b8d3d112 FC |
117 | { |
118 | .compatible = "renesas,thermal-r8a774c0", | |
119 | .data = &rcar_gen3_thermal, | |
120 | }, | |
92ca366e SS |
121 | { |
122 | .compatible = "renesas,thermal-r8a77970", | |
123 | .data = &rcar_gen3_thermal, | |
124 | }, | |
e36e1300 YK |
125 | { |
126 | .compatible = "renesas,thermal-r8a77990", | |
127 | .data = &rcar_gen3_thermal, | |
128 | }, | |
1969d9dc YK |
129 | { |
130 | .compatible = "renesas,thermal-r8a77995", | |
131 | .data = &rcar_gen3_thermal, | |
132 | }, | |
ca1e4558 KM |
133 | {}, |
134 | }; | |
135 | MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); | |
136 | ||
1e426ffd KM |
137 | /* |
138 | * basic functions | |
139 | */ | |
e9137a58 KM |
140 | #define rcar_thermal_common_read(c, r) \ |
141 | _rcar_thermal_common_read(c, COMMON_ ##r) | |
142 | static u32 _rcar_thermal_common_read(struct rcar_thermal_common *common, | |
143 | u32 reg) | |
144 | { | |
145 | return ioread32(common->base + reg); | |
146 | } | |
147 | ||
148 | #define rcar_thermal_common_write(c, r, d) \ | |
149 | _rcar_thermal_common_write(c, COMMON_ ##r, d) | |
150 | static void _rcar_thermal_common_write(struct rcar_thermal_common *common, | |
151 | u32 reg, u32 data) | |
152 | { | |
153 | iowrite32(data, common->base + reg); | |
154 | } | |
155 | ||
156 | #define rcar_thermal_common_bset(c, r, m, d) \ | |
157 | _rcar_thermal_common_bset(c, COMMON_ ##r, m, d) | |
158 | static void _rcar_thermal_common_bset(struct rcar_thermal_common *common, | |
159 | u32 reg, u32 mask, u32 data) | |
160 | { | |
161 | u32 val; | |
162 | ||
163 | val = ioread32(common->base + reg); | |
164 | val &= ~mask; | |
165 | val |= (data & mask); | |
166 | iowrite32(val, common->base + reg); | |
167 | } | |
e9137a58 KM |
168 | |
169 | #define rcar_thermal_read(p, r) _rcar_thermal_read(p, REG_ ##r) | |
170 | static u32 _rcar_thermal_read(struct rcar_thermal_priv *priv, u32 reg) | |
1e426ffd | 171 | { |
b2bbc6a2 | 172 | return ioread32(priv->base + reg); |
1e426ffd KM |
173 | } |
174 | ||
e9137a58 KM |
175 | #define rcar_thermal_write(p, r, d) _rcar_thermal_write(p, REG_ ##r, d) |
176 | static void _rcar_thermal_write(struct rcar_thermal_priv *priv, | |
177 | u32 reg, u32 data) | |
1e426ffd | 178 | { |
1e426ffd | 179 | iowrite32(data, priv->base + reg); |
1e426ffd | 180 | } |
1e426ffd | 181 | |
e9137a58 KM |
182 | #define rcar_thermal_bset(p, r, m, d) _rcar_thermal_bset(p, REG_ ##r, m, d) |
183 | static void _rcar_thermal_bset(struct rcar_thermal_priv *priv, u32 reg, | |
184 | u32 mask, u32 data) | |
1e426ffd | 185 | { |
1e426ffd KM |
186 | u32 val; |
187 | ||
1e426ffd KM |
188 | val = ioread32(priv->base + reg); |
189 | val &= ~mask; | |
190 | val |= (data & mask); | |
191 | iowrite32(val, priv->base + reg); | |
1e426ffd KM |
192 | } |
193 | ||
194 | /* | |
195 | * zone device functions | |
196 | */ | |
e0a5172e | 197 | static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) |
1e426ffd | 198 | { |
f8f53e18 | 199 | struct device *dev = rcar_priv_to_dev(priv); |
b03628b7 NS |
200 | int old, new, ctemp = -EINVAL; |
201 | unsigned int i; | |
f8f53e18 | 202 | |
b2bbc6a2 KM |
203 | mutex_lock(&priv->lock); |
204 | ||
f8f53e18 KM |
205 | /* |
206 | * TSC decides a value of CPTAP automatically, | |
207 | * and this is the conditions which validate interrupt. | |
208 | */ | |
209 | rcar_thermal_bset(priv, THSCR, CPCTL, CPCTL); | |
210 | ||
f8f53e18 KM |
211 | old = ~0; |
212 | for (i = 0; i < 128; i++) { | |
1e426ffd KM |
213 | /* |
214 | * we need to wait 300us after changing comparator offset | |
215 | * to get stable temperature. | |
216 | * see "Usage Notes" on datasheet | |
217 | */ | |
263c8c4c | 218 | usleep_range(300, 400); |
1e426ffd | 219 | |
f8f53e18 KM |
220 | new = rcar_thermal_read(priv, THSSR) & CTEMP; |
221 | if (new == old) { | |
222 | ctemp = new; | |
1e426ffd KM |
223 | break; |
224 | } | |
f8f53e18 | 225 | old = new; |
1e426ffd KM |
226 | } |
227 | ||
b03628b7 | 228 | if (ctemp < 0) { |
f8f53e18 | 229 | dev_err(dev, "thermal sensor was broken\n"); |
f0e68fc3 | 230 | goto err_out_unlock; |
f8f53e18 KM |
231 | } |
232 | ||
e0a5172e KM |
233 | /* |
234 | * enable IRQ | |
235 | */ | |
236 | if (rcar_has_irq_support(priv)) { | |
1969d9dc YK |
237 | if (priv->chip->has_filonoff) |
238 | rcar_thermal_write(priv, FILONOFF, 0); | |
e0a5172e KM |
239 | |
240 | /* enable Rising/Falling edge interrupt */ | |
241 | rcar_thermal_write(priv, POSNEG, 0x1); | |
242 | rcar_thermal_write(priv, INTCTRL, (((ctemp - 0) << 8) | | |
243 | ((ctemp - 1) << 0))); | |
244 | } | |
245 | ||
f0e68fc3 | 246 | err_out_unlock: |
b2bbc6a2 | 247 | mutex_unlock(&priv->lock); |
57ed737f | 248 | |
b03628b7 | 249 | return ctemp; |
1e426ffd KM |
250 | } |
251 | ||
8b477ea5 KM |
252 | static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv, |
253 | int *temp) | |
e0a5172e | 254 | { |
0fa04202 | 255 | int ctemp; |
e0a5172e | 256 | |
57ed737f NS |
257 | ctemp = rcar_thermal_update_temp(priv); |
258 | if (ctemp < 0) | |
259 | return ctemp; | |
e0a5172e | 260 | |
0fa04202 NS |
261 | /* Guaranteed operating range is -45C to 125C. */ |
262 | ||
20386f0d | 263 | if (priv->chip->ctemp_bands == 1) |
0fa04202 | 264 | *temp = MCELSIUS((ctemp * 5) - 65); |
57ed737f | 265 | else if (ctemp < 24) |
0fa04202 | 266 | *temp = MCELSIUS(((ctemp * 55) - 720) / 10); |
20386f0d | 267 | else |
0fa04202 | 268 | *temp = MCELSIUS((ctemp * 5) - 60); |
5440c40b | 269 | |
e0a5172e KM |
270 | return 0; |
271 | } | |
272 | ||
8b477ea5 KM |
273 | static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) |
274 | { | |
5f68d078 | 275 | struct rcar_thermal_priv *priv = thermal_zone_device_priv(zone); |
8b477ea5 KM |
276 | |
277 | return rcar_thermal_get_current_temp(priv, temp); | |
278 | } | |
279 | ||
0b6a3e45 | 280 | static struct thermal_zone_device_ops rcar_thermal_zone_ops = { |
2ebd4f2f | 281 | .get_temp = rcar_thermal_get_temp, |
8b477ea5 KM |
282 | }; |
283 | ||
0b6a3e45 DL |
284 | static struct thermal_trip trips[] = { |
285 | { .type = THERMAL_TRIP_CRITICAL, .temperature = 90000 } | |
1e426ffd KM |
286 | }; |
287 | ||
e0a5172e KM |
288 | /* |
289 | * interrupt | |
290 | */ | |
291 | #define rcar_thermal_irq_enable(p) _rcar_thermal_irq_ctrl(p, 1) | |
292 | #define rcar_thermal_irq_disable(p) _rcar_thermal_irq_ctrl(p, 0) | |
293 | static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable) | |
294 | { | |
295 | struct rcar_thermal_common *common = priv->common; | |
296 | unsigned long flags; | |
297 | u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */ | |
298 | ||
ffbcdf8a KM |
299 | if (!rcar_has_irq_support(priv)) |
300 | return; | |
301 | ||
e0a5172e KM |
302 | spin_lock_irqsave(&common->lock, flags); |
303 | ||
304 | rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask); | |
305 | ||
306 | spin_unlock_irqrestore(&common->lock, flags); | |
307 | } | |
308 | ||
309 | static void rcar_thermal_work(struct work_struct *work) | |
310 | { | |
311 | struct rcar_thermal_priv *priv; | |
a1ade565 | 312 | int ret; |
e0a5172e KM |
313 | |
314 | priv = container_of(work, struct rcar_thermal_priv, work.work); | |
315 | ||
a1ade565 KM |
316 | ret = rcar_thermal_update_temp(priv); |
317 | if (ret < 0) | |
318 | return; | |
319 | ||
e0a5172e | 320 | rcar_thermal_irq_enable(priv); |
9477165e | 321 | |
7617e771 | 322 | thermal_zone_device_update(priv->zone, THERMAL_EVENT_UNSPECIFIED); |
e0a5172e KM |
323 | } |
324 | ||
325 | static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status) | |
326 | { | |
327 | struct device *dev = rcar_priv_to_dev(priv); | |
328 | ||
329 | status = (status >> rcar_id_to_shift(priv)) & 0x3; | |
330 | ||
206c0cba | 331 | if (status) { |
e0a5172e KM |
332 | dev_dbg(dev, "thermal%d %s%s\n", |
333 | priv->id, | |
334 | (status & 0x2) ? "Rising " : "", | |
335 | (status & 0x1) ? "Falling" : ""); | |
336 | } | |
337 | ||
338 | return status; | |
339 | } | |
340 | ||
341 | static irqreturn_t rcar_thermal_irq(int irq, void *data) | |
342 | { | |
343 | struct rcar_thermal_common *common = data; | |
344 | struct rcar_thermal_priv *priv; | |
e0a5172e KM |
345 | u32 status, mask; |
346 | ||
4eb7d0cd | 347 | spin_lock(&common->lock); |
e0a5172e KM |
348 | |
349 | mask = rcar_thermal_common_read(common, INTMSK); | |
350 | status = rcar_thermal_common_read(common, STR); | |
351 | rcar_thermal_common_write(common, STR, 0x000F0F0F & mask); | |
352 | ||
4eb7d0cd | 353 | spin_unlock(&common->lock); |
e0a5172e KM |
354 | |
355 | status = status & ~mask; | |
356 | ||
357 | /* | |
358 | * check the status | |
359 | */ | |
360 | rcar_thermal_for_each_priv(priv, common) { | |
361 | if (rcar_thermal_had_changed(priv, status)) { | |
362 | rcar_thermal_irq_disable(priv); | |
3a313862 GU |
363 | queue_delayed_work(system_freezable_wq, &priv->work, |
364 | msecs_to_jiffies(300)); | |
e0a5172e KM |
365 | } |
366 | } | |
367 | ||
368 | return IRQ_HANDLED; | |
369 | } | |
370 | ||
1e426ffd KM |
371 | /* |
372 | * platform functions | |
373 | */ | |
84f0e490 KM |
374 | static int rcar_thermal_remove(struct platform_device *pdev) |
375 | { | |
376 | struct rcar_thermal_common *common = platform_get_drvdata(pdev); | |
377 | struct device *dev = &pdev->dev; | |
378 | struct rcar_thermal_priv *priv; | |
379 | ||
380 | rcar_thermal_for_each_priv(priv, common) { | |
ffbcdf8a | 381 | rcar_thermal_irq_disable(priv); |
697ee786 | 382 | cancel_delayed_work_sync(&priv->work); |
1969d9dc | 383 | if (priv->chip->use_of_thermal) |
64a411e8 | 384 | thermal_remove_hwmon_sysfs(priv->zone); |
d4b23c5c BDP |
385 | else |
386 | thermal_zone_device_unregister(priv->zone); | |
84f0e490 KM |
387 | } |
388 | ||
389 | pm_runtime_put(dev); | |
390 | pm_runtime_disable(dev); | |
391 | ||
392 | return 0; | |
393 | } | |
394 | ||
1e426ffd KM |
395 | static int rcar_thermal_probe(struct platform_device *pdev) |
396 | { | |
3676d1dd | 397 | struct rcar_thermal_common *common; |
1e426ffd | 398 | struct rcar_thermal_priv *priv; |
3676d1dd | 399 | struct device *dev = &pdev->dev; |
3277e022 | 400 | struct resource *res; |
1969d9dc | 401 | const struct rcar_thermal_chip *chip = of_device_get_match_data(dev); |
3676d1dd KM |
402 | int mres = 0; |
403 | int i; | |
fb84d990 | 404 | int ret = -ENODEV; |
e0a5172e | 405 | int idle = IDLE_INTERVAL; |
11313746 | 406 | u32 enr_bits = 0; |
1e426ffd | 407 | |
3676d1dd | 408 | common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL); |
b0a60d88 | 409 | if (!common) |
1e426ffd | 410 | return -ENOMEM; |
1e426ffd | 411 | |
84f0e490 KM |
412 | platform_set_drvdata(pdev, common); |
413 | ||
3676d1dd | 414 | INIT_LIST_HEAD(&common->head); |
e0a5172e | 415 | spin_lock_init(&common->lock); |
3676d1dd KM |
416 | common->dev = dev; |
417 | ||
51d45d25 KM |
418 | pm_runtime_enable(dev); |
419 | pm_runtime_get_sync(dev); | |
420 | ||
1969d9dc | 421 | for (i = 0; i < chip->nirqs; i++) { |
3277e022 LP |
422 | int irq; |
423 | ||
424 | ret = platform_get_irq_optional(pdev, i); | |
425 | if (ret < 0 && ret != -ENXIO) | |
426 | goto error_unregister; | |
427 | if (ret > 0) | |
428 | irq = ret; | |
429 | else | |
430 | break; | |
431 | ||
1969d9dc YK |
432 | if (!common->base) { |
433 | /* | |
434 | * platform has IRQ support. | |
435 | * Then, driver uses common registers | |
436 | * rcar_has_irq_support() will be enabled | |
437 | */ | |
438 | res = platform_get_resource(pdev, IORESOURCE_MEM, | |
439 | mres++); | |
440 | common->base = devm_ioremap_resource(dev, res); | |
39056e8a NS |
441 | if (IS_ERR(common->base)) { |
442 | ret = PTR_ERR(common->base); | |
443 | goto error_unregister; | |
444 | } | |
1969d9dc YK |
445 | |
446 | idle = 0; /* polling delay is not needed */ | |
447 | } | |
e0a5172e | 448 | |
3277e022 | 449 | ret = devm_request_irq(dev, irq, rcar_thermal_irq, |
1969d9dc YK |
450 | IRQF_SHARED, dev_name(dev), common); |
451 | if (ret) { | |
452 | dev_err(dev, "irq request failed\n "); | |
453 | goto error_unregister; | |
454 | } | |
455 | ||
456 | /* update ENR bits */ | |
457 | if (chip->irq_per_ch) | |
458 | enr_bits |= 1 << i; | |
1e426ffd KM |
459 | } |
460 | ||
3676d1dd KM |
461 | for (i = 0;; i++) { |
462 | res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); | |
463 | if (!res) | |
464 | break; | |
465 | ||
466 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | |
467 | if (!priv) { | |
1dc20828 KM |
468 | ret = -ENOMEM; |
469 | goto error_unregister; | |
3676d1dd KM |
470 | } |
471 | ||
5095526f | 472 | priv->base = devm_ioremap_resource(dev, res); |
1dc20828 KM |
473 | if (IS_ERR(priv->base)) { |
474 | ret = PTR_ERR(priv->base); | |
475 | goto error_unregister; | |
476 | } | |
3676d1dd KM |
477 | |
478 | priv->common = common; | |
e0a5172e | 479 | priv->id = i; |
1969d9dc | 480 | priv->chip = chip; |
3676d1dd KM |
481 | mutex_init(&priv->lock); |
482 | INIT_LIST_HEAD(&priv->list); | |
e0a5172e | 483 | INIT_DELAYED_WORK(&priv->work, rcar_thermal_work); |
a1ade565 KM |
484 | ret = rcar_thermal_update_temp(priv); |
485 | if (ret < 0) | |
486 | goto error_unregister; | |
3676d1dd | 487 | |
392573b7 | 488 | if (chip->use_of_thermal) { |
2ebd4f2f | 489 | priv->zone = devm_thermal_of_zone_register( |
8b477ea5 | 490 | dev, i, priv, |
0b6a3e45 | 491 | &rcar_thermal_zone_ops); |
392573b7 | 492 | } else { |
0b6a3e45 DL |
493 | priv->zone = thermal_zone_device_register_with_trips( |
494 | "rcar_thermal", trips, ARRAY_SIZE(trips), 0, priv, | |
3676d1dd | 495 | &rcar_thermal_zone_ops, NULL, 0, |
e0a5172e | 496 | idle); |
bbcf90c0 AP |
497 | |
498 | ret = thermal_zone_device_enable(priv->zone); | |
499 | if (ret) { | |
500 | thermal_zone_device_unregister(priv->zone); | |
501 | priv->zone = ERR_PTR(ret); | |
502 | } | |
503 | } | |
3676d1dd KM |
504 | if (IS_ERR(priv->zone)) { |
505 | dev_err(dev, "can't register thermal zone\n"); | |
fb84d990 | 506 | ret = PTR_ERR(priv->zone); |
87260d3f | 507 | priv->zone = NULL; |
3676d1dd KM |
508 | goto error_unregister; |
509 | } | |
510 | ||
1969d9dc | 511 | if (chip->use_of_thermal) { |
64a411e8 KM |
512 | /* |
513 | * thermal_zone doesn't enable hwmon as default, | |
514 | * but, enable it here to keep compatible | |
515 | */ | |
516 | priv->zone->tzp->no_hwmon = false; | |
517 | ret = thermal_add_hwmon_sysfs(priv->zone); | |
518 | if (ret) | |
519 | goto error_unregister; | |
520 | } | |
521 | ||
ffbcdf8a | 522 | rcar_thermal_irq_enable(priv); |
1dc20828 KM |
523 | |
524 | list_move_tail(&priv->list, &common->head); | |
11313746 YS |
525 | |
526 | /* update ENR bits */ | |
1969d9dc YK |
527 | if (!chip->irq_per_ch) |
528 | enr_bits |= 3 << (i * 8); | |
1e426ffd KM |
529 | } |
530 | ||
542cdf40 | 531 | if (common->base && enr_bits) |
11313746 YS |
532 | rcar_thermal_common_write(common, ENR, enr_bits); |
533 | ||
3db46c93 | 534 | dev_info(dev, "%d sensor probed\n", i); |
1e426ffd KM |
535 | |
536 | return 0; | |
3676d1dd KM |
537 | |
538 | error_unregister: | |
84f0e490 | 539 | rcar_thermal_remove(pdev); |
51d45d25 | 540 | |
fb84d990 | 541 | return ret; |
1e426ffd KM |
542 | } |
543 | ||
1969d9dc YK |
544 | #ifdef CONFIG_PM_SLEEP |
545 | static int rcar_thermal_suspend(struct device *dev) | |
546 | { | |
547 | struct rcar_thermal_common *common = dev_get_drvdata(dev); | |
548 | struct rcar_thermal_priv *priv = list_first_entry(&common->head, | |
549 | typeof(*priv), list); | |
550 | ||
551 | if (priv->chip->needs_suspend_resume) { | |
552 | rcar_thermal_common_write(common, ENR, 0); | |
553 | rcar_thermal_irq_disable(priv); | |
554 | rcar_thermal_bset(priv, THSCR, CPCTL, 0); | |
555 | } | |
556 | ||
557 | return 0; | |
558 | } | |
559 | ||
560 | static int rcar_thermal_resume(struct device *dev) | |
561 | { | |
562 | struct rcar_thermal_common *common = dev_get_drvdata(dev); | |
563 | struct rcar_thermal_priv *priv = list_first_entry(&common->head, | |
564 | typeof(*priv), list); | |
565 | int ret; | |
566 | ||
567 | if (priv->chip->needs_suspend_resume) { | |
568 | ret = rcar_thermal_update_temp(priv); | |
569 | if (ret < 0) | |
570 | return ret; | |
571 | rcar_thermal_irq_enable(priv); | |
572 | rcar_thermal_common_write(common, ENR, 0x03); | |
573 | } | |
574 | ||
575 | return 0; | |
576 | } | |
577 | #endif | |
578 | ||
579 | static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend, | |
580 | rcar_thermal_resume); | |
581 | ||
1e426ffd KM |
582 | static struct platform_driver rcar_thermal_driver = { |
583 | .driver = { | |
584 | .name = "rcar_thermal", | |
1969d9dc | 585 | .pm = &rcar_thermal_pm_ops, |
76cc1887 | 586 | .of_match_table = rcar_thermal_dt_ids, |
1e426ffd KM |
587 | }, |
588 | .probe = rcar_thermal_probe, | |
589 | .remove = rcar_thermal_remove, | |
590 | }; | |
591 | module_platform_driver(rcar_thermal_driver); | |
592 | ||
c9545790 | 593 | MODULE_LICENSE("GPL v2"); |
1e426ffd KM |
594 | MODULE_DESCRIPTION("R-Car THS/TSC thermal sensor driver"); |
595 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); |