1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * R-Car Gen3 THS thermal sensor driver
4 * Based on rcar_thermal.c and work from Hien Dang and Khiem Nguyen.
5 *
6 * Copyright (C) 2016 Renesas Electronics Corporation.
7 * Copyright (C) 2016 Sang Engineering
8 */
9 #include <linux/delay.h>
10 #include <linux/err.h>
11 #include <linux/interrupt.h>
12 #include <linux/io.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/thermal.h>
18
19 #include "../thermal_hwmon.h"
20
21 /* Register offsets */
22 #define REG_GEN3_IRQSTR 0x04
23 #define REG_GEN3_IRQMSK 0x08
24 #define REG_GEN3_IRQCTL 0x0c
25 #define REG_GEN3_IRQEN 0x10
26 #define REG_GEN3_IRQTEMP1 0x14
27 #define REG_GEN3_IRQTEMP2 0x18
28 #define REG_GEN3_IRQTEMP3 0x1c
29 #define REG_GEN3_THCTR 0x20
30 #define REG_GEN3_TEMP 0x28
31 #define REG_GEN3_THCODE1 0x50
32 #define REG_GEN3_THCODE2 0x54
33 #define REG_GEN3_THCODE3 0x58
34 #define REG_GEN3_PTAT1 0x5c
35 #define REG_GEN3_PTAT2 0x60
36 #define REG_GEN3_PTAT3 0x64
37 #define REG_GEN3_THSCP 0x68
38 #define REG_GEN4_THSFMON00 0x180
39 #define REG_GEN4_THSFMON01 0x184
40 #define REG_GEN4_THSFMON02 0x188
41 #define REG_GEN4_THSFMON15 0x1bc
42 #define REG_GEN4_THSFMON16 0x1c0
43 #define REG_GEN4_THSFMON17 0x1c4
44
45 /* IRQ{STR,MSK,EN} bits */
46 #define IRQ_TEMP1 BIT(0)
47 #define IRQ_TEMP2 BIT(1)
48 #define IRQ_TEMP3 BIT(2)
49 #define IRQ_TEMPD1 BIT(3)
50 #define IRQ_TEMPD2 BIT(4)
51 #define IRQ_TEMPD3 BIT(5)
52
53 /* THCTR bits */
54 #define THCTR_PONM BIT(6)
55 #define THCTR_THSST BIT(0)
56
57 /* THSCP bits */
58 #define THSCP_COR_PARA_VLD (BIT(15) | BIT(14))
59
60 #define CTEMP_MASK 0xfff
61
62 #define MCELSIUS(temp) ((temp) * 1000)
63 #define GEN3_FUSE_MASK 0xfff
64 #define GEN4_FUSE_MASK 0xfff
65
66 #define TSC_MAX_NUM 5
67
68 struct rcar_gen3_thermal_priv;
69
70 struct rcar_gen3_thermal_fuse_info {
71 u32 ptat[3];
72 u32 thcode[3];
73 u32 mask;
74 };
75
76 struct rcar_gen3_thermal_fuse_default {
77 u32 ptat[3];
78 u32 thcodes[TSC_MAX_NUM][3];
79 };
80
81 struct rcar_thermal_info {
82 int scale;
83 int adj_below;
84 int adj_above;
85 const struct rcar_gen3_thermal_fuse_info *fuses;
86 const struct rcar_gen3_thermal_fuse_default *fuse_defaults;
87 };
88
89 struct equation_set_coef {
90 int a;
91 int b;
92 };
93
94 struct rcar_gen3_thermal_tsc {
95 struct rcar_gen3_thermal_priv *priv;
96 void __iomem *base;
97 struct thermal_zone_device *zone;
98 /* Different coefficients are used depending on a threshold. */
99 struct {
100 struct equation_set_coef below;
101 struct equation_set_coef above;
102 } coef;
103 int thcode[3];
104 };
105
106 struct rcar_gen3_thermal_priv {
107 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
108 struct thermal_zone_device_ops ops;
109 unsigned int num_tscs;
110 int ptat[3];
111 int tj_t;
112 const struct rcar_thermal_info *info;
113 };
114
rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc * tsc,u32 reg)115 static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
116 u32 reg)
117 {
118 return ioread32(tsc->base + reg);
119 }
120
rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc * tsc,u32 reg,u32 data)121 static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
122 u32 reg, u32 data)
123 {
124 iowrite32(data, tsc->base + reg);
125 }
126
127 /*
128 * Linear approximation for temperature
129 *
130 * [temp] = ((thadj - [reg]) * a) / b + adj
131 * [reg] = thadj - ([temp] - adj) * b / a
132 *
133 * The constants a and b are calculated using two triplets of int values PTAT
134 * and THCODE. PTAT and THCODE can either be read from hardware or use hard
135 * coded values from the driver. The formula to calculate a and b are taken from
136 * the datasheet. Different calculations are needed for a and b depending on
137 * if the input variables ([temp] or [reg]) are above or below a threshold. The
138 * threshold is also calculated from PTAT and THCODE using formulas from the
139 * datasheet.
140 *
141 * The constant thadj is one of the THCODE values, which one to use depends on
142 * the threshold and input value.
143 *
144 * The constants adj is taken verbatim from the datasheet. Two values exists,
145 * which one to use depends on the input value and the calculated threshold.
146 * Furthermore different SoC models supported by the driver have different sets
147 * of values. The values for each model are stored in the device match data.
148 */
149
rcar_gen3_thermal_shared_coefs(struct rcar_gen3_thermal_priv * priv)150 static void rcar_gen3_thermal_shared_coefs(struct rcar_gen3_thermal_priv *priv)
151 {
152 priv->tj_t =
153 DIV_ROUND_CLOSEST((priv->ptat[1] - priv->ptat[2]) * priv->info->scale,
154 priv->ptat[0] - priv->ptat[2])
155 + priv->info->adj_below;
156 }
rcar_gen3_thermal_tsc_coefs(struct rcar_gen3_thermal_priv * priv,struct rcar_gen3_thermal_tsc * tsc)157 static void rcar_gen3_thermal_tsc_coefs(struct rcar_gen3_thermal_priv *priv,
158 struct rcar_gen3_thermal_tsc *tsc)
159 {
160 tsc->coef.below.a = priv->info->scale * (priv->ptat[2] - priv->ptat[1]);
161 tsc->coef.above.a = priv->info->scale * (priv->ptat[0] - priv->ptat[1]);
162
163 tsc->coef.below.b = (priv->ptat[2] - priv->ptat[0]) * (tsc->thcode[2] - tsc->thcode[1]);
164 tsc->coef.above.b = (priv->ptat[0] - priv->ptat[2]) * (tsc->thcode[1] - tsc->thcode[0]);
165 }
166
rcar_gen3_thermal_get_temp(struct thermal_zone_device * tz,int * temp)167 static int rcar_gen3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
168 {
169 struct rcar_gen3_thermal_tsc *tsc = thermal_zone_device_priv(tz);
170 struct rcar_gen3_thermal_priv *priv = tsc->priv;
171 const struct equation_set_coef *coef;
172 int adj, decicelsius, reg, thcode;
173
174 /* Read register and convert to millidegree Celsius */
175 reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
176
177 if (reg < tsc->thcode[1]) {
178 adj = priv->info->adj_below;
179 coef = &tsc->coef.below;
180 thcode = tsc->thcode[2];
181 } else {
182 adj = priv->info->adj_above;
183 coef = &tsc->coef.above;
184 thcode = tsc->thcode[0];
185 }
186
187 /*
188 * The dividend can't be grown as it might overflow, instead shorten the
189 * divisor to convert to decidegree Celsius. If we convert after the
190 * division precision is lost as we will scale up from whole degrees
191 * Celsius.
192 */
193 decicelsius = DIV_ROUND_CLOSEST(coef->a * (thcode - reg), coef->b / 10);
194
195 /* Guaranteed operating range is -40C to 125C. */
196
197 /* Reporting is done in millidegree Celsius */
198 *temp = decicelsius * 100 + adj * 1000;
199
200 return 0;
201 }
202
rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc * tsc,int mcelsius)203 static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc,
204 int mcelsius)
205 {
206 struct rcar_gen3_thermal_priv *priv = tsc->priv;
207 const struct equation_set_coef *coef;
208 int adj, celsius, thcode;
209
210 celsius = DIV_ROUND_CLOSEST(mcelsius, 1000);
211 if (celsius < priv->tj_t) {
212 coef = &tsc->coef.below;
213 adj = priv->info->adj_below;
214 thcode = tsc->thcode[2];
215 } else {
216 coef = &tsc->coef.above;
217 adj = priv->info->adj_above;
218 thcode = tsc->thcode[0];
219 }
220
221 return thcode - DIV_ROUND_CLOSEST((celsius - adj) * coef->b, coef->a);
222 }
223
rcar_gen3_thermal_set_trips(struct thermal_zone_device * tz,int low,int high)224 static int rcar_gen3_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
225 {
226 struct rcar_gen3_thermal_tsc *tsc = thermal_zone_device_priv(tz);
227 u32 irqmsk = 0;
228
229 if (low != -INT_MAX) {
230 irqmsk |= IRQ_TEMPD1;
231 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1,
232 rcar_gen3_thermal_mcelsius_to_temp(tsc, low));
233 }
234
235 if (high != INT_MAX) {
236 irqmsk |= IRQ_TEMP2;
237 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP2,
238 rcar_gen3_thermal_mcelsius_to_temp(tsc, high));
239 }
240
241 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, irqmsk);
242
243 return 0;
244 }
245
246 static const struct thermal_zone_device_ops rcar_gen3_tz_of_ops = {
247 .get_temp = rcar_gen3_thermal_get_temp,
248 .set_trips = rcar_gen3_thermal_set_trips,
249 };
250
rcar_gen3_thermal_irq(int irq,void * data)251 static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
252 {
253 struct rcar_gen3_thermal_priv *priv = data;
254 unsigned int i;
255 u32 status;
256
257 for (i = 0; i < priv->num_tscs; i++) {
258 status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR);
259 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0);
260 if (status && priv->tscs[i]->zone)
261 thermal_zone_device_update(priv->tscs[i]->zone,
262 THERMAL_EVENT_UNSPECIFIED);
263 }
264
265 return IRQ_HANDLED;
266 }
267
rcar_gen3_thermal_fetch_fuses(struct rcar_gen3_thermal_priv * priv)268 static void rcar_gen3_thermal_fetch_fuses(struct rcar_gen3_thermal_priv *priv)
269 {
270 const struct rcar_gen3_thermal_fuse_info *fuses = priv->info->fuses;
271
272 /*
273 * Set the pseudo calibration points with fused values.
274 * PTAT is shared between all TSCs but only fused for the first
275 * TSC while THCODEs are fused for each TSC.
276 */
277 priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], fuses->ptat[0])
278 & fuses->mask;
279 priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], fuses->ptat[1])
280 & fuses->mask;
281 priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], fuses->ptat[2])
282 & fuses->mask;
283
284 for (unsigned int i = 0; i < priv->num_tscs; i++) {
285 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
286
287 tsc->thcode[0] = rcar_gen3_thermal_read(tsc, fuses->thcode[0])
288 & fuses->mask;
289 tsc->thcode[1] = rcar_gen3_thermal_read(tsc, fuses->thcode[1])
290 & fuses->mask;
291 tsc->thcode[2] = rcar_gen3_thermal_read(tsc, fuses->thcode[2])
292 & fuses->mask;
293 }
294 }
295
rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv * priv)296 static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
297 {
298 const struct rcar_gen3_thermal_fuse_default *fuse_defaults = priv->info->fuse_defaults;
299 unsigned int i;
300 u32 thscp;
301
302 /* If fuses are not set, fallback to pseudo values. */
303 thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP);
304 if (!priv->info->fuses ||
305 (thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
306 /* Default THCODE values in case FUSEs are not set. */
307 priv->ptat[0] = fuse_defaults->ptat[0];
308 priv->ptat[1] = fuse_defaults->ptat[1];
309 priv->ptat[2] = fuse_defaults->ptat[2];
310
311 for (i = 0; i < priv->num_tscs; i++) {
312 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
313
314 tsc->thcode[0] = fuse_defaults->thcodes[i][0];
315 tsc->thcode[1] = fuse_defaults->thcodes[i][1];
316 tsc->thcode[2] = fuse_defaults->thcodes[i][2];
317 }
318
319 return false;
320 }
321
322 rcar_gen3_thermal_fetch_fuses(priv);
323
324 return true;
325 }
326
rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv * priv,struct rcar_gen3_thermal_tsc * tsc)327 static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv,
328 struct rcar_gen3_thermal_tsc *tsc)
329 {
330 u32 reg_val;
331
332 reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
333 reg_val &= ~THCTR_PONM;
334 rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val);
335
336 usleep_range(1000, 2000);
337
338 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0);
339 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
340 if (priv->ops.set_trips)
341 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN,
342 IRQ_TEMPD1 | IRQ_TEMP2);
343
344 reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
345 reg_val |= THCTR_THSST;
346 rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val);
347
348 usleep_range(1000, 2000);
349 }
350
351 static const struct rcar_gen3_thermal_fuse_info rcar_gen3_thermal_fuse_info_gen3 = {
352 .ptat = { REG_GEN3_PTAT1, REG_GEN3_PTAT2, REG_GEN3_PTAT3 },
353 .thcode = { REG_GEN3_THCODE1, REG_GEN3_THCODE2, REG_GEN3_THCODE3 },
354 .mask = GEN3_FUSE_MASK,
355 };
356
357 static const struct rcar_gen3_thermal_fuse_info rcar_gen3_thermal_fuse_info_gen4 = {
358 .ptat = { REG_GEN4_THSFMON16, REG_GEN4_THSFMON17, REG_GEN4_THSFMON15 },
359 .thcode = { REG_GEN4_THSFMON01, REG_GEN4_THSFMON02, REG_GEN4_THSFMON00 },
360 .mask = GEN4_FUSE_MASK,
361 };
362
363 static const struct rcar_gen3_thermal_fuse_default rcar_gen3_thermal_fuse_default_info_gen3 = {
364 .ptat = { 2631, 1509, 435 },
365 .thcodes = {
366 { 3397, 2800, 2221 },
367 { 3393, 2795, 2216 },
368 { 3389, 2805, 2237 },
369 { 3415, 2694, 2195 },
370 { 3356, 2724, 2244 },
371 },
372 };
373
374 static const struct rcar_gen3_thermal_fuse_default rcar_gen3_thermal_fuse_default_info_gen4 = {
375 .ptat = { 3274, 2164, 985 },
376 .thcodes = { /* All four THS units share the same trimming */
377 { 3218, 2617, 1980 },
378 { 3218, 2617, 1980 },
379 { 3218, 2617, 1980 },
380 { 3218, 2617, 1980 },
381 }
382 };
383
384 static const struct rcar_thermal_info rcar_m3w_thermal_info = {
385 .scale = 157,
386 .adj_below = -41,
387 .adj_above = 116,
388 .fuses = &rcar_gen3_thermal_fuse_info_gen3,
389 .fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen3,
390 };
391
392 static const struct rcar_thermal_info rcar_gen3_thermal_info = {
393 .scale = 167,
394 .adj_below = -41,
395 .adj_above = 126,
396 .fuses = &rcar_gen3_thermal_fuse_info_gen3,
397 .fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen3,
398 };
399
400 static const struct rcar_thermal_info rcar_s4_thermal_info = {
401 .scale = 167,
402 .adj_below = -41,
403 .adj_above = 126,
404 .fuses = &rcar_gen3_thermal_fuse_info_gen4,
405 .fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen3,
406 };
407
408 static const struct rcar_thermal_info rcar_gen4_thermal_info = {
409 .scale = 167,
410 .adj_below = -41,
411 .adj_above = 126,
412 .fuses = &rcar_gen3_thermal_fuse_info_gen4,
413 .fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen4,
414 };
415
416 static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
417 {
418 .compatible = "renesas,r8a774a1-thermal",
419 .data = &rcar_m3w_thermal_info,
420 },
421 {
422 .compatible = "renesas,r8a774b1-thermal",
423 .data = &rcar_gen3_thermal_info,
424 },
425 {
426 .compatible = "renesas,r8a774e1-thermal",
427 .data = &rcar_gen3_thermal_info,
428 },
429 {
430 .compatible = "renesas,r8a7795-thermal",
431 .data = &rcar_gen3_thermal_info,
432 },
433 {
434 .compatible = "renesas,r8a7796-thermal",
435 .data = &rcar_m3w_thermal_info,
436 },
437 {
438 .compatible = "renesas,r8a77961-thermal",
439 .data = &rcar_m3w_thermal_info,
440 },
441 {
442 .compatible = "renesas,r8a77965-thermal",
443 .data = &rcar_gen3_thermal_info,
444 },
445 {
446 .compatible = "renesas,r8a77980-thermal",
447 .data = &rcar_gen3_thermal_info,
448 },
449 {
450 .compatible = "renesas,r8a779a0-thermal",
451 .data = &rcar_gen3_thermal_info,
452 },
453 {
454 .compatible = "renesas,r8a779f0-thermal",
455 .data = &rcar_s4_thermal_info,
456 },
457 {
458 .compatible = "renesas,r8a779g0-thermal",
459 .data = &rcar_gen4_thermal_info,
460 },
461 {
462 .compatible = "renesas,r8a779h0-thermal",
463 .data = &rcar_gen4_thermal_info,
464 },
465 {},
466 };
467 MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
468
rcar_gen3_thermal_remove(struct platform_device * pdev)469 static void rcar_gen3_thermal_remove(struct platform_device *pdev)
470 {
471 struct device *dev = &pdev->dev;
472
473 pm_runtime_put(dev);
474 pm_runtime_disable(dev);
475 }
476
rcar_gen3_hwmon_action(void * data)477 static void rcar_gen3_hwmon_action(void *data)
478 {
479 struct thermal_zone_device *zone = data;
480
481 thermal_remove_hwmon_sysfs(zone);
482 }
483
rcar_gen3_thermal_request_irqs(struct rcar_gen3_thermal_priv * priv,struct platform_device * pdev)484 static int rcar_gen3_thermal_request_irqs(struct rcar_gen3_thermal_priv *priv,
485 struct platform_device *pdev)
486 {
487 struct device *dev = &pdev->dev;
488 unsigned int i;
489 char *irqname;
490 int ret, irq;
491
492 for (i = 0; i < 2; i++) {
493 irq = platform_get_irq_optional(pdev, i);
494 if (irq < 0)
495 return irq;
496
497 irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:ch%d",
498 dev_name(dev), i);
499 if (!irqname)
500 return -ENOMEM;
501
502 ret = devm_request_threaded_irq(dev, irq, NULL,
503 rcar_gen3_thermal_irq,
504 IRQF_ONESHOT, irqname, priv);
505 if (ret)
506 return ret;
507 }
508
509 return 0;
510 }
511
rcar_gen3_thermal_probe(struct platform_device * pdev)512 static int rcar_gen3_thermal_probe(struct platform_device *pdev)
513 {
514 struct rcar_gen3_thermal_priv *priv;
515 struct device *dev = &pdev->dev;
516 struct resource *res;
517 struct thermal_zone_device *zone;
518 unsigned int i;
519 int ret;
520
521 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
522 if (!priv)
523 return -ENOMEM;
524
525 priv->ops = rcar_gen3_tz_of_ops;
526
527 priv->info = of_device_get_match_data(dev);
528 platform_set_drvdata(pdev, priv);
529
530 if (rcar_gen3_thermal_request_irqs(priv, pdev))
531 priv->ops.set_trips = NULL;
532
533 pm_runtime_enable(dev);
534 pm_runtime_get_sync(dev);
535
536 for (i = 0; i < TSC_MAX_NUM; i++) {
537 struct rcar_gen3_thermal_tsc *tsc;
538
539 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
540 if (!res)
541 break;
542
543 tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL);
544 if (!tsc) {
545 ret = -ENOMEM;
546 goto error_unregister;
547 }
548
549 tsc->priv = priv;
550 tsc->base = devm_ioremap_resource(dev, res);
551 if (IS_ERR(tsc->base)) {
552 ret = PTR_ERR(tsc->base);
553 goto error_unregister;
554 }
555
556 priv->tscs[i] = tsc;
557 }
558
559 priv->num_tscs = i;
560
561 if (!rcar_gen3_thermal_read_fuses(priv))
562 dev_info(dev, "No calibration values fused, fallback to driver values\n");
563
564 rcar_gen3_thermal_shared_coefs(priv);
565
566 for (i = 0; i < priv->num_tscs; i++) {
567 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
568
569 rcar_gen3_thermal_init(priv, tsc);
570 rcar_gen3_thermal_tsc_coefs(priv, tsc);
571
572 zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops);
573 if (IS_ERR(zone)) {
574 dev_err(dev, "Sensor %u: Can't register thermal zone\n", i);
575 ret = PTR_ERR(zone);
576 goto error_unregister;
577 }
578 tsc->zone = zone;
579
580 ret = thermal_add_hwmon_sysfs(tsc->zone);
581 if (ret)
582 goto error_unregister;
583
584 ret = devm_add_action_or_reset(dev, rcar_gen3_hwmon_action, zone);
585 if (ret)
586 goto error_unregister;
587
588 dev_info(dev, "Sensor %u: Loaded\n", i);
589 }
590
591 if (!priv->num_tscs) {
592 ret = -ENODEV;
593 goto error_unregister;
594 }
595
596 return 0;
597
598 error_unregister:
599 rcar_gen3_thermal_remove(pdev);
600
601 return ret;
602 }
603
rcar_gen3_thermal_resume(struct device * dev)604 static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
605 {
606 struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
607 unsigned int i;
608
609 for (i = 0; i < priv->num_tscs; i++) {
610 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
611
612 rcar_gen3_thermal_init(priv, tsc);
613 }
614
615 return 0;
616 }
617
618 static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL,
619 rcar_gen3_thermal_resume);
620
621 static struct platform_driver rcar_gen3_thermal_driver = {
622 .driver = {
623 .name = "rcar_gen3_thermal",
624 .pm = &rcar_gen3_thermal_pm_ops,
625 .of_match_table = rcar_gen3_thermal_dt_ids,
626 },
627 .probe = rcar_gen3_thermal_probe,
628 .remove = rcar_gen3_thermal_remove,
629 };
630 module_platform_driver(rcar_gen3_thermal_driver);
631
632 MODULE_LICENSE("GPL v2");
633 MODULE_DESCRIPTION("R-Car Gen3 THS thermal sensor driver");
634 MODULE_AUTHOR("Wolfram Sang <wsa+renesas@sang-engineering.com>");
635