File Index
Files and directories
Sign in
FILE

rcar_gen3_thermal.c

File preview with syntax highlighting.

linux-6.19.14/drivers/thermal/renesas/rcar_gen3_thermal.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  R-Car Gen3, Gen4 and RZ/G2 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
 68struct rcar_gen3_thermal_priv;
 69
 70struct rcar_gen3_thermal_fuse_info {
 71	u32 ptat[3];
 72	u32 thcode[3];
 73	u32 mask;
 74};
 75
 76struct rcar_gen3_thermal_fuse_default {
 77	u32 ptat[3];
 78	u32 thcodes[TSC_MAX_NUM][3];
 79};
 80
 81struct 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
 89struct equation_set_coef {
 90	int a;
 91	int b;
 92};
 93
 94struct 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
106struct 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
115static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
116					 u32 reg)
117{
118	return ioread32(tsc->base + reg);
119}
120
121static 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
150static 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}
157static 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
167static 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
203static 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
224static 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
246static 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
251static 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
268static 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
296static 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
327static 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
351static 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
357static 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
363static 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
374static 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
384static 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
392static 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
400static 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
408static 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
416static 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};
467MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
468
469static 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
477static void rcar_gen3_hwmon_action(void *data)
478{
479	struct thermal_zone_device *zone = data;
480
481	thermal_remove_hwmon_sysfs(zone);
482}
483
484static 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
512static 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
598error_unregister:
599	rcar_gen3_thermal_remove(pdev);
600
601	return ret;
602}
603
604static int 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
618static DEFINE_SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, NULL,
619				rcar_gen3_thermal_resume);
620
621static struct platform_driver rcar_gen3_thermal_driver = {
622	.driver	= {
623		.name	= "rcar_gen3_thermal",
624		.pm = pm_sleep_ptr(&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};
630module_platform_driver(rcar_gen3_thermal_driver);
631
632MODULE_LICENSE("GPL v2");
633MODULE_DESCRIPTION("R-Car Gen3 THS thermal sensor driver");
634MODULE_AUTHOR("Wolfram Sang <wsa+renesas@sang-engineering.com>");
~/ Read-only file preview.