@@ -190,10 +190,64 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
190
190
return 0 ;
191
191
}
192
192
193
- static const struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
193
+ static int rcar_gen3_thermal_mcelsius_to_temp (struct rcar_gen3_thermal_tsc * tsc ,
194
+ int mcelsius )
195
+ {
196
+ int celsius , val ;
197
+
198
+ celsius = DIV_ROUND_CLOSEST (mcelsius , 1000 );
199
+ if (celsius <= INT_FIXPT (tsc -> tj_t ))
200
+ val = celsius * tsc -> coef .a1 + tsc -> coef .b1 ;
201
+ else
202
+ val = celsius * tsc -> coef .a2 + tsc -> coef .b2 ;
203
+
204
+ return INT_FIXPT (val );
205
+ }
206
+
207
+ static int rcar_gen3_thermal_set_trips (void * devdata , int low , int high )
208
+ {
209
+ struct rcar_gen3_thermal_tsc * tsc = devdata ;
210
+ u32 irqmsk = 0 ;
211
+
212
+ if (low != - INT_MAX ) {
213
+ irqmsk |= IRQ_TEMPD1 ;
214
+ rcar_gen3_thermal_write (tsc , REG_GEN3_IRQTEMP1 ,
215
+ rcar_gen3_thermal_mcelsius_to_temp (tsc , low ));
216
+ }
217
+
218
+ if (high != INT_MAX ) {
219
+ irqmsk |= IRQ_TEMP2 ;
220
+ rcar_gen3_thermal_write (tsc , REG_GEN3_IRQTEMP2 ,
221
+ rcar_gen3_thermal_mcelsius_to_temp (tsc , high ));
222
+ }
223
+
224
+ rcar_gen3_thermal_write (tsc , REG_GEN3_IRQMSK , irqmsk );
225
+
226
+ return 0 ;
227
+ }
228
+
229
+ static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
194
230
.get_temp = rcar_gen3_thermal_get_temp ,
231
+ .set_trips = rcar_gen3_thermal_set_trips ,
195
232
};
196
233
234
+ static irqreturn_t rcar_gen3_thermal_irq (int irq , void * data )
235
+ {
236
+ struct rcar_gen3_thermal_priv * priv = data ;
237
+ unsigned int i ;
238
+ u32 status ;
239
+
240
+ for (i = 0 ; i < priv -> num_tscs ; i ++ ) {
241
+ status = rcar_gen3_thermal_read (priv -> tscs [i ], REG_GEN3_IRQSTR );
242
+ rcar_gen3_thermal_write (priv -> tscs [i ], REG_GEN3_IRQSTR , 0 );
243
+ if (status )
244
+ thermal_zone_device_update (priv -> tscs [i ]-> zone ,
245
+ THERMAL_EVENT_UNSPECIFIED );
246
+ }
247
+
248
+ return IRQ_HANDLED ;
249
+ }
250
+
197
251
static const struct soc_device_attribute r8a7795es1 [] = {
198
252
{ .soc_id = "r8a7795" , .revision = "ES1.*" },
199
253
{ /* sentinel */ }
@@ -210,6 +264,9 @@ static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc)
210
264
211
265
rcar_gen3_thermal_write (tsc , REG_GEN3_IRQCTL , 0x3F );
212
266
rcar_gen3_thermal_write (tsc , REG_GEN3_IRQMSK , 0 );
267
+ if (tsc -> zone -> ops -> set_trips )
268
+ rcar_gen3_thermal_write (tsc , REG_GEN3_IRQEN ,
269
+ IRQ_TEMPD1 | IRQ_TEMP2 );
213
270
214
271
rcar_gen3_thermal_write (tsc , REG_GEN3_CTSR ,
215
272
CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN );
@@ -235,6 +292,9 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
235
292
236
293
rcar_gen3_thermal_write (tsc , REG_GEN3_IRQCTL , 0 );
237
294
rcar_gen3_thermal_write (tsc , REG_GEN3_IRQMSK , 0 );
295
+ if (tsc -> zone -> ops -> set_trips )
296
+ rcar_gen3_thermal_write (tsc , REG_GEN3_IRQEN ,
297
+ IRQ_TEMPD1 | IRQ_TEMP2 );
238
298
239
299
reg_val = rcar_gen3_thermal_read (tsc , REG_GEN3_THCTR );
240
300
reg_val |= THCTR_THSST ;
@@ -303,6 +363,34 @@ static void rcar_gen3_hwmon_action(void *data)
303
363
thermal_remove_hwmon_sysfs (zone );
304
364
}
305
365
366
+ static int rcar_gen3_thermal_request_irqs (struct rcar_gen3_thermal_priv * priv ,
367
+ struct platform_device * pdev )
368
+ {
369
+ struct device * dev = & pdev -> dev ;
370
+ unsigned int i ;
371
+ char * irqname ;
372
+ int ret , irq ;
373
+
374
+ for (i = 0 ; i < 2 ; i ++ ) {
375
+ irq = platform_get_irq_optional (pdev , i );
376
+ if (irq < 0 )
377
+ return irq ;
378
+
379
+ irqname = devm_kasprintf (dev , GFP_KERNEL , "%s:ch%d" ,
380
+ dev_name (dev ), i );
381
+ if (!irqname )
382
+ return - ENOMEM ;
383
+
384
+ ret = devm_request_threaded_irq (dev , irq , NULL ,
385
+ rcar_gen3_thermal_irq ,
386
+ IRQF_ONESHOT , irqname , priv );
387
+ if (ret )
388
+ return ret ;
389
+ }
390
+
391
+ return 0 ;
392
+ }
393
+
306
394
static int rcar_gen3_thermal_probe (struct platform_device * pdev )
307
395
{
308
396
struct rcar_gen3_thermal_priv * priv ;
@@ -326,6 +414,9 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
326
414
327
415
platform_set_drvdata (pdev , priv );
328
416
417
+ if (rcar_gen3_thermal_request_irqs (priv , pdev ))
418
+ rcar_gen3_tz_of_ops .set_trips = NULL ;
419
+
329
420
pm_runtime_enable (dev );
330
421
pm_runtime_get_sync (dev );
331
422
@@ -351,9 +442,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
351
442
352
443
priv -> tscs [i ] = tsc ;
353
444
354
- priv -> thermal_init (tsc );
355
- rcar_gen3_thermal_calc_coefs (tsc , ptat , thcodes [i ], * ths_tj_1 );
356
-
357
445
zone = devm_thermal_zone_of_sensor_register (dev , i , tsc ,
358
446
& rcar_gen3_tz_of_ops );
359
447
if (IS_ERR (zone )) {
@@ -363,6 +451,9 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
363
451
}
364
452
tsc -> zone = zone ;
365
453
454
+ priv -> thermal_init (tsc );
455
+ rcar_gen3_thermal_calc_coefs (tsc , ptat , thcodes [i ], * ths_tj_1 );
456
+
366
457
tsc -> zone -> tzp -> no_hwmon = false;
367
458
ret = thermal_add_hwmon_sysfs (tsc -> zone );
368
459
if (ret )
@@ -401,8 +492,12 @@ static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
401
492
402
493
for (i = 0 ; i < priv -> num_tscs ; i ++ ) {
403
494
struct rcar_gen3_thermal_tsc * tsc = priv -> tscs [i ];
495
+ struct thermal_zone_device * zone = tsc -> zone ;
404
496
405
497
priv -> thermal_init (tsc );
498
+ if (zone -> ops -> set_trips )
499
+ rcar_gen3_thermal_set_trips (tsc , zone -> prev_low_trip ,
500
+ zone -> prev_high_trip );
406
501
}
407
502
408
503
return 0 ;
0 commit comments