Skip to content

Commit c3131bd

Browse files
Niklas Söderlunddlezcano
authored andcommitted
thermal: rcar_gen3_thermal: Read calibration from hardware
In production hardware the calibration values used to convert register values to temperatures can be read from hardware. While pre-production hardware still depends on pseudo values hard-coded in the driver. Add support for reading out calibration values from hardware if it's fused. The presence of fused calibration is indicated in the THSCP register. Signed-off-by: Niklas Söderlund <[email protected]> Tested-by: Kuninori Morimoto <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Daniel Lezcano <[email protected]>
1 parent b8aaf14 commit c3131bd

File tree

1 file changed

+74
-20
lines changed

1 file changed

+74
-20
lines changed

drivers/thermal/rcar_gen3_thermal.c

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
#define REG_GEN3_THCODE1 0x50
3535
#define REG_GEN3_THCODE2 0x54
3636
#define REG_GEN3_THCODE3 0x58
37+
#define REG_GEN3_PTAT1 0x5c
38+
#define REG_GEN3_PTAT2 0x60
39+
#define REG_GEN3_PTAT3 0x64
40+
#define REG_GEN3_THSCP 0x68
3741

3842
/* IRQ{STR,MSK,EN} bits */
3943
#define IRQ_TEMP1 BIT(0)
@@ -55,6 +59,9 @@
5559
#define THCTR_PONM BIT(6)
5660
#define THCTR_THSST BIT(0)
5761

62+
/* THSCP bits */
63+
#define THSCP_COR_PARA_VLD (BIT(15) | BIT(14))
64+
5865
#define CTEMP_MASK 0xFFF
5966

6067
#define MCELSIUS(temp) ((temp) * 1000)
@@ -245,6 +252,64 @@ static const struct soc_device_attribute r8a7795es1[] = {
245252
{ /* sentinel */ }
246253
};
247254

255+
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
256+
{
257+
unsigned int i;
258+
u32 thscp;
259+
260+
/* If fuses are not set, fallback to pseudo values. */
261+
thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP);
262+
if ((thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
263+
/* Default THCODE values in case FUSEs are not set. */
264+
static const int thcodes[TSC_MAX_NUM][3] = {
265+
{ 3397, 2800, 2221 },
266+
{ 3393, 2795, 2216 },
267+
{ 3389, 2805, 2237 },
268+
{ 3415, 2694, 2195 },
269+
{ 3356, 2724, 2244 },
270+
};
271+
272+
priv->ptat[0] = 2631;
273+
priv->ptat[1] = 1509;
274+
priv->ptat[2] = 435;
275+
276+
for (i = 0; i < priv->num_tscs; i++) {
277+
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
278+
279+
tsc->thcode[0] = thcodes[i][0];
280+
tsc->thcode[1] = thcodes[i][1];
281+
tsc->thcode[2] = thcodes[i][2];
282+
}
283+
284+
return false;
285+
}
286+
287+
/*
288+
* Set the pseudo calibration points with fused values.
289+
* PTAT is shared between all TSCs but only fused for the first
290+
* TSC while THCODEs are fused for each TSC.
291+
*/
292+
priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) &
293+
GEN3_FUSE_MASK;
294+
priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) &
295+
GEN3_FUSE_MASK;
296+
priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) &
297+
GEN3_FUSE_MASK;
298+
299+
for (i = 0; i < priv->num_tscs; i++) {
300+
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
301+
302+
tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) &
303+
GEN3_FUSE_MASK;
304+
tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) &
305+
GEN3_FUSE_MASK;
306+
tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) &
307+
GEN3_FUSE_MASK;
308+
}
309+
310+
return true;
311+
}
312+
248313
static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc)
249314
{
250315
rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR);
@@ -393,16 +458,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
393458
unsigned int i;
394459
int ret;
395460

396-
/* Default THCODE values in case FUSEs are not set. */
397-
/* TODO: Read values from hardware on supported platforms */
398-
static const int thcodes[TSC_MAX_NUM][3] = {
399-
{ 3397, 2800, 2221 },
400-
{ 3393, 2795, 2216 },
401-
{ 3389, 2805, 2237 },
402-
{ 3415, 2694, 2195 },
403-
{ 3356, 2724, 2244 },
404-
};
405-
406461
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
407462
if (!priv)
408463
return -ENOMEM;
@@ -411,10 +466,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
411466
if (soc_device_match(r8a7795es1))
412467
priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1;
413468

414-
priv->ptat[0] = 2631;
415-
priv->ptat[1] = 1509;
416-
priv->ptat[2] = 435;
417-
418469
platform_set_drvdata(pdev, priv);
419470

420471
if (rcar_gen3_thermal_request_irqs(priv, pdev))
@@ -442,11 +493,16 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
442493
goto error_unregister;
443494
}
444495

445-
tsc->thcode[0] = thcodes[i][0];
446-
tsc->thcode[1] = thcodes[i][1];
447-
tsc->thcode[2] = thcodes[i][2];
448-
449496
priv->tscs[i] = tsc;
497+
}
498+
499+
priv->num_tscs = i;
500+
501+
if (!rcar_gen3_thermal_read_fuses(priv))
502+
dev_info(dev, "No calibration values fused, fallback to driver values\n");
503+
504+
for (i = 0; i < priv->num_tscs; i++) {
505+
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
450506

451507
zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
452508
&rcar_gen3_tz_of_ops);
@@ -476,8 +532,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
476532
dev_info(dev, "TSC%u: Loaded %d trip points\n", i, ret);
477533
}
478534

479-
priv->num_tscs = i;
480-
481535
if (!priv->num_tscs) {
482536
ret = -ENODEV;
483537
goto error_unregister;

0 commit comments

Comments
 (0)