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