[PATCH v3 3/6] thermal: tegra: soctherm-fuse: prepare calibration for Tegra114 support

Svyatoslav Ryhel posted 6 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH v3 3/6] thermal: tegra: soctherm-fuse: prepare calibration for Tegra114 support
Posted by Svyatoslav Ryhel 1 month, 2 weeks ago
The Tegra114 has a different fuse calibration register layout and address
compared to other Tegra SoCs, requiring SOCTHERM shift, mask, register
address, and nominal calibration values to be configurable.

Additionally, a use_lower_precision option was implemented to account for
the Tegra114's 0.5C thermal data output, which differs from the 1C
precision of newer SoCs.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
 drivers/thermal/tegra/soctherm-fuse.c     | 31 ++++++++++++++++-------
 drivers/thermal/tegra/soctherm.h          |  8 +++++-
 drivers/thermal/tegra/tegra124-soctherm.c |  6 +++++
 drivers/thermal/tegra/tegra132-soctherm.c |  6 +++++
 drivers/thermal/tegra/tegra210-soctherm.c |  6 +++++
 5 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/drivers/thermal/tegra/soctherm-fuse.c b/drivers/thermal/tegra/soctherm-fuse.c
index 190f95280e0b..d27876dd9b2a 100644
--- a/drivers/thermal/tegra/soctherm-fuse.c
+++ b/drivers/thermal/tegra/soctherm-fuse.c
@@ -9,15 +9,10 @@
 
 #include "soctherm.h"
 
-#define NOMINAL_CALIB_FT			105
-#define NOMINAL_CALIB_CP			25
-
 #define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK	0x1fff
 #define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK	(0x1fff << 13)
 #define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT	13
 
-#define FUSE_TSENSOR_COMMON			0x180
-
 /*
  * Tegra210: Layout of bits in FUSE_TSENSOR_COMMON:
  *    3                   2                   1                   0
@@ -26,7 +21,7 @@
  * |       BASE_FT       |      BASE_CP      | SHFT_FT | SHIFT_CP  |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- * Tegra12x, etc:
+ * Tegra124:
  * In chips prior to Tegra210, this fuse was incorrectly sized as 26 bits,
  * and didn't hold SHIFT_CP in [31:26]. Therefore these missing six bits
  * were obtained via the FUSE_SPARE_REALIGNMENT_REG register [5:0].
@@ -44,6 +39,13 @@
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |---------------------------------------------------| SHIFT_CP  |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Tegra114: Layout of bits in FUSE_TSENSOR_COMMON aka FUSE_VSENSOR_CALIB:
+ *    3                   2                   1                   0
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | SHFT_FT |       BASE_FT       | SHIFT_CP  |      BASE_CP      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
 #define CALIB_COEFFICIENT 1000000LL
@@ -77,7 +79,7 @@ int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
 	s32 shifted_cp, shifted_ft;
 	int err;
 
-	err = tegra_fuse_readl(FUSE_TSENSOR_COMMON, &val);
+	err = tegra_fuse_readl(tfuse->fuse_common_reg, &val);
 	if (err)
 		return err;
 
@@ -96,10 +98,21 @@ int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
 			return err;
 	}
 
+	shifted_cp = (val & tfuse->fuse_shift_cp_mask) >>
+		     tfuse->fuse_shift_cp_shift;
 	shifted_cp = sign_extend32(val, 5);
 
-	shared->actual_temp_cp = 2 * NOMINAL_CALIB_CP + shifted_cp;
-	shared->actual_temp_ft = 2 * NOMINAL_CALIB_FT + shifted_ft;
+	shared->actual_temp_cp = 2 * tfuse->nominal_calib_cp + shifted_cp;
+	shared->actual_temp_ft = 2 * tfuse->nominal_calib_ft + shifted_ft;
+
+	/*
+	 * Tegra114 provides fuse thermal corrections in 0.5C while newer
+	 * SoCs provide data in 1C
+	 */
+	if (tfuse->use_lower_precision) {
+		shared->actual_temp_cp /= 2;
+		shared->actual_temp_ft /= 2;
+	}
 
 	return 0;
 }
diff --git a/drivers/thermal/tegra/soctherm.h b/drivers/thermal/tegra/soctherm.h
index 70501e73d586..f8d76ae716fe 100644
--- a/drivers/thermal/tegra/soctherm.h
+++ b/drivers/thermal/tegra/soctherm.h
@@ -56,6 +56,9 @@
 #define SENSOR_TEMP2_MEM_TEMP_MASK		(0xffff << 16)
 #define SENSOR_TEMP2_PLLX_TEMP_MASK		0xffff
 
+#define FUSE_VSENSOR_CALIB			0x08c
+#define FUSE_TSENSOR_COMMON			0x180
+
 /**
  * struct tegra_tsensor_group - SOC_THERM sensor group data
  * @name: short name of the temperature sensor group
@@ -109,9 +112,12 @@ struct tsensor_group_thermtrips {
 
 struct tegra_soctherm_fuse {
 	u32 fuse_base_cp_mask, fuse_base_cp_shift;
+	u32 fuse_shift_cp_mask, fuse_shift_cp_shift;
 	u32 fuse_base_ft_mask, fuse_base_ft_shift;
 	u32 fuse_shift_ft_mask, fuse_shift_ft_shift;
-	u32 fuse_spare_realignment;
+	u32 fuse_common_reg, fuse_spare_realignment;
+	u32 nominal_calib_cp, nominal_calib_ft;
+	bool use_lower_precision;
 };
 
 struct tsensor_shared_calib {
diff --git a/drivers/thermal/tegra/tegra124-soctherm.c b/drivers/thermal/tegra/tegra124-soctherm.c
index 20ad27f4d1a1..e0a40ca2a6ac 100644
--- a/drivers/thermal/tegra/tegra124-soctherm.c
+++ b/drivers/thermal/tegra/tegra124-soctherm.c
@@ -200,11 +200,17 @@ static const struct tegra_tsensor tegra124_tsensors[] = {
 static const struct tegra_soctherm_fuse tegra124_soctherm_fuse = {
 	.fuse_base_cp_mask = 0x3ff,
 	.fuse_base_cp_shift = 0,
+	.fuse_shift_cp_mask = 0x1f,
+	.fuse_shift_cp_shift = 0,
 	.fuse_base_ft_mask = 0x7ff << 10,
 	.fuse_base_ft_shift = 10,
 	.fuse_shift_ft_mask = 0x1f << 21,
 	.fuse_shift_ft_shift = 21,
+	.fuse_common_reg = FUSE_TSENSOR_COMMON,
 	.fuse_spare_realignment = 0x1fc,
+	.nominal_calib_cp = 25,
+	.nominal_calib_ft = 105,
+	.use_lower_precision = false,
 };
 
 const struct tegra_soctherm_soc tegra124_soctherm = {
diff --git a/drivers/thermal/tegra/tegra132-soctherm.c b/drivers/thermal/tegra/tegra132-soctherm.c
index b76308fdad9e..138d76c67114 100644
--- a/drivers/thermal/tegra/tegra132-soctherm.c
+++ b/drivers/thermal/tegra/tegra132-soctherm.c
@@ -200,11 +200,17 @@ static struct tegra_tsensor tegra132_tsensors[] = {
 static const struct tegra_soctherm_fuse tegra132_soctherm_fuse = {
 	.fuse_base_cp_mask = 0x3ff,
 	.fuse_base_cp_shift = 0,
+	.fuse_shift_cp_mask = 0x1f,
+	.fuse_shift_cp_shift = 0,
 	.fuse_base_ft_mask = 0x7ff << 10,
 	.fuse_base_ft_shift = 10,
 	.fuse_shift_ft_mask = 0x1f << 21,
 	.fuse_shift_ft_shift = 21,
+	.fuse_common_reg = FUSE_TSENSOR_COMMON,
 	.fuse_spare_realignment = 0x1fc,
+	.nominal_calib_cp = 25,
+	.nominal_calib_ft = 105,
+	.use_lower_precision = false,
 };
 
 const struct tegra_soctherm_soc tegra132_soctherm = {
diff --git a/drivers/thermal/tegra/tegra210-soctherm.c b/drivers/thermal/tegra/tegra210-soctherm.c
index d0ff793f18c5..1127b4d28087 100644
--- a/drivers/thermal/tegra/tegra210-soctherm.c
+++ b/drivers/thermal/tegra/tegra210-soctherm.c
@@ -201,11 +201,17 @@ static const struct tegra_tsensor tegra210_tsensors[] = {
 static const struct tegra_soctherm_fuse tegra210_soctherm_fuse = {
 	.fuse_base_cp_mask = 0x3ff << 11,
 	.fuse_base_cp_shift = 11,
+	.fuse_shift_cp_mask = 0x1f,
+	.fuse_shift_cp_shift = 0,
 	.fuse_base_ft_mask = 0x7ff << 21,
 	.fuse_base_ft_shift = 21,
 	.fuse_shift_ft_mask = 0x1f << 6,
 	.fuse_shift_ft_shift = 6,
+	.fuse_common_reg = FUSE_TSENSOR_COMMON,
 	.fuse_spare_realignment = 0,
+	.nominal_calib_cp = 25,
+	.nominal_calib_ft = 105,
+	.use_lower_precision = false,
 };
 
 static struct tsensor_group_thermtrips tegra210_tsensor_thermtrips[] = {
-- 
2.48.1
Re: [PATCH v3 3/6] thermal: tegra: soctherm-fuse: prepare calibration for Tegra114 support
Posted by Mikko Perttunen 1 month, 1 week ago
On Wednesday, August 20, 2025 8:42 PM Svyatoslav Ryhel wrote:
> The Tegra114 has a different fuse calibration register layout and address
> compared to other Tegra SoCs, requiring SOCTHERM shift, mask, register
> address, and nominal calibration values to be configurable.
> 
> Additionally, a use_lower_precision option was implemented to account for
> the Tegra114's 0.5C thermal data output, which differs from the 1C
> precision of newer SoCs.
> 
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
>  drivers/thermal/tegra/soctherm-fuse.c     | 31 ++++++++++++++++-------
>  drivers/thermal/tegra/soctherm.h          |  8 +++++-
>  drivers/thermal/tegra/tegra124-soctherm.c |  6 +++++
>  drivers/thermal/tegra/tegra132-soctherm.c |  6 +++++
>  drivers/thermal/tegra/tegra210-soctherm.c |  6 +++++
>  5 files changed, 47 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/thermal/tegra/soctherm-fuse.c
> b/drivers/thermal/tegra/soctherm-fuse.c index 190f95280e0b..d27876dd9b2a
> 100644
> --- a/drivers/thermal/tegra/soctherm-fuse.c
> +++ b/drivers/thermal/tegra/soctherm-fuse.c
> @@ -9,15 +9,10 @@
> 
>  #include "soctherm.h"
> 
> -#define NOMINAL_CALIB_FT			105
> -#define NOMINAL_CALIB_CP			25
> -
>  #define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK	0x1fff
>  #define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK	(0x1fff << 13)
>  #define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT	13
> 
> -#define FUSE_TSENSOR_COMMON			0x180
> -
>  /*
>   * Tegra210: Layout of bits in FUSE_TSENSOR_COMMON:
>   *    3                   2                   1                   0
> @@ -26,7 +21,7 @@
>   * |       BASE_FT       |      BASE_CP      | SHFT_FT | SHIFT_CP  |
>   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   *
> - * Tegra12x, etc:
> + * Tegra124:
>   * In chips prior to Tegra210, this fuse was incorrectly sized as 26 bits,
>   * and didn't hold SHIFT_CP in [31:26]. Therefore these missing six bits
>   * were obtained via the FUSE_SPARE_REALIGNMENT_REG register [5:0].
> @@ -44,6 +39,13 @@
>   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   * |---------------------------------------------------| SHIFT_CP  |
>   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> + *
> + * Tegra114: Layout of bits in FUSE_TSENSOR_COMMON aka FUSE_VSENSOR_CALIB:
> + *    3                   2                   1                   0
> + *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
> + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> + * | SHFT_FT |       BASE_FT       | SHIFT_CP  |      BASE_CP      |
> + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   */
> 
>  #define CALIB_COEFFICIENT 1000000LL
> @@ -77,7 +79,7 @@ int tegra_calc_shared_calib(const struct
> tegra_soctherm_fuse *tfuse, s32 shifted_cp, shifted_ft;
>  	int err;
> 
> -	err = tegra_fuse_readl(FUSE_TSENSOR_COMMON, &val);
> +	err = tegra_fuse_readl(tfuse->fuse_common_reg, &val);
>  	if (err)
>  		return err;
> 
> @@ -96,10 +98,21 @@ int tegra_calc_shared_calib(const struct
> tegra_soctherm_fuse *tfuse, return err;
>  	}
> 
> +	shifted_cp = (val & tfuse->fuse_shift_cp_mask) >>
> +		     tfuse->fuse_shift_cp_shift;
>  	shifted_cp = sign_extend32(val, 5);
> 
> -	shared->actual_temp_cp = 2 * NOMINAL_CALIB_CP + shifted_cp;
> -	shared->actual_temp_ft = 2 * NOMINAL_CALIB_FT + shifted_ft;
> +	shared->actual_temp_cp = 2 * tfuse->nominal_calib_cp + shifted_cp;
> +	shared->actual_temp_ft = 2 * tfuse->nominal_calib_ft + shifted_ft;
> +
> +	/*
> +	 * Tegra114 provides fuse thermal corrections in 0.5C while newer
> +	 * SoCs provide data in 1C
> +	 */

I've been looking a bit into these fuses, and from what I can tell the 
precision for these fuses should be in 0.5C units for all of Tegra114, 124, 
and 210. The documented nominal CP (cold) and FT (hot) temperatures for 
Tegra114 should be 25C and 90C respectively.

The reason for the code '2 * NOMINAL_CALIB_XX + shifted_xx' then is that the 
value of 'actual_temp_xx' is in 0.5C units -- NOMINAL_CALIB_XX being in 1C 
units and being multiplied by 2 to match the units of the shifted_xx values 
coming from fuses.

If you're getting correct values with your code, clearly there's more hijinks 
going on.

> +	if (tfuse->use_lower_precision) {
> +		shared->actual_temp_cp /= 2;
> +		shared->actual_temp_ft /= 2;
> +	}
> 
>  	return 0;
>  }
> diff --git a/drivers/thermal/tegra/soctherm.h
> b/drivers/thermal/tegra/soctherm.h index 70501e73d586..f8d76ae716fe 100644
> --- a/drivers/thermal/tegra/soctherm.h
> +++ b/drivers/thermal/tegra/soctherm.h
> @@ -56,6 +56,9 @@
>  #define SENSOR_TEMP2_MEM_TEMP_MASK		(0xffff << 16)
>  #define SENSOR_TEMP2_PLLX_TEMP_MASK		0xffff
> 
> +#define FUSE_VSENSOR_CALIB			0x08c
> +#define FUSE_TSENSOR_COMMON			0x180
> +
>  /**
>   * struct tegra_tsensor_group - SOC_THERM sensor group data
>   * @name: short name of the temperature sensor group
> @@ -109,9 +112,12 @@ struct tsensor_group_thermtrips {
> 
>  struct tegra_soctherm_fuse {
>  	u32 fuse_base_cp_mask, fuse_base_cp_shift;
> +	u32 fuse_shift_cp_mask, fuse_shift_cp_shift;
>  	u32 fuse_base_ft_mask, fuse_base_ft_shift;
>  	u32 fuse_shift_ft_mask, fuse_shift_ft_shift;
> -	u32 fuse_spare_realignment;
> +	u32 fuse_common_reg, fuse_spare_realignment;
> +	u32 nominal_calib_cp, nominal_calib_ft;
> +	bool use_lower_precision;
>  };
> 
>  struct tsensor_shared_calib {
> diff --git a/drivers/thermal/tegra/tegra124-soctherm.c
> b/drivers/thermal/tegra/tegra124-soctherm.c index
> 20ad27f4d1a1..e0a40ca2a6ac 100644
> --- a/drivers/thermal/tegra/tegra124-soctherm.c
> +++ b/drivers/thermal/tegra/tegra124-soctherm.c
> @@ -200,11 +200,17 @@ static const struct tegra_tsensor tegra124_tsensors[]
> = { static const struct tegra_soctherm_fuse tegra124_soctherm_fuse = {
> .fuse_base_cp_mask = 0x3ff,
>  	.fuse_base_cp_shift = 0,
> +	.fuse_shift_cp_mask = 0x1f,
> +	.fuse_shift_cp_shift = 0,
>  	.fuse_base_ft_mask = 0x7ff << 10,
>  	.fuse_base_ft_shift = 10,
>  	.fuse_shift_ft_mask = 0x1f << 21,
>  	.fuse_shift_ft_shift = 21,
> +	.fuse_common_reg = FUSE_TSENSOR_COMMON,
>  	.fuse_spare_realignment = 0x1fc,
> +	.nominal_calib_cp = 25,
> +	.nominal_calib_ft = 105,
> +	.use_lower_precision = false,
>  };
> 
>  const struct tegra_soctherm_soc tegra124_soctherm = {
> diff --git a/drivers/thermal/tegra/tegra132-soctherm.c
> b/drivers/thermal/tegra/tegra132-soctherm.c index
> b76308fdad9e..138d76c67114 100644
> --- a/drivers/thermal/tegra/tegra132-soctherm.c
> +++ b/drivers/thermal/tegra/tegra132-soctherm.c
> @@ -200,11 +200,17 @@ static struct tegra_tsensor tegra132_tsensors[] = {
>  static const struct tegra_soctherm_fuse tegra132_soctherm_fuse = {
>  	.fuse_base_cp_mask = 0x3ff,
>  	.fuse_base_cp_shift = 0,
> +	.fuse_shift_cp_mask = 0x1f,
> +	.fuse_shift_cp_shift = 0,
>  	.fuse_base_ft_mask = 0x7ff << 10,
>  	.fuse_base_ft_shift = 10,
>  	.fuse_shift_ft_mask = 0x1f << 21,
>  	.fuse_shift_ft_shift = 21,
> +	.fuse_common_reg = FUSE_TSENSOR_COMMON,
>  	.fuse_spare_realignment = 0x1fc,
> +	.nominal_calib_cp = 25,
> +	.nominal_calib_ft = 105,
> +	.use_lower_precision = false,
>  };
> 
>  const struct tegra_soctherm_soc tegra132_soctherm = {
> diff --git a/drivers/thermal/tegra/tegra210-soctherm.c
> b/drivers/thermal/tegra/tegra210-soctherm.c index
> d0ff793f18c5..1127b4d28087 100644
> --- a/drivers/thermal/tegra/tegra210-soctherm.c
> +++ b/drivers/thermal/tegra/tegra210-soctherm.c
> @@ -201,11 +201,17 @@ static const struct tegra_tsensor tegra210_tsensors[]
> = { static const struct tegra_soctherm_fuse tegra210_soctherm_fuse = {
> .fuse_base_cp_mask = 0x3ff << 11,
>  	.fuse_base_cp_shift = 11,
> +	.fuse_shift_cp_mask = 0x1f,
> +	.fuse_shift_cp_shift = 0,
>  	.fuse_base_ft_mask = 0x7ff << 21,
>  	.fuse_base_ft_shift = 21,
>  	.fuse_shift_ft_mask = 0x1f << 6,
>  	.fuse_shift_ft_shift = 6,
> +	.fuse_common_reg = FUSE_TSENSOR_COMMON,
>  	.fuse_spare_realignment = 0,
> +	.nominal_calib_cp = 25,
> +	.nominal_calib_ft = 105,
> +	.use_lower_precision = false,
>  };
> 
>  static struct tsensor_group_thermtrips tegra210_tsensor_thermtrips[] = {
Re: [PATCH v3 3/6] thermal: tegra: soctherm-fuse: prepare calibration for Tegra114 support
Posted by Svyatoslav Ryhel 1 month, 1 week ago
чт, 21 серп. 2025 р. о 10:42 Mikko Perttunen <mperttunen@nvidia.com> пише:
>
> On Wednesday, August 20, 2025 8:42 PM Svyatoslav Ryhel wrote:
> > The Tegra114 has a different fuse calibration register layout and address
> > compared to other Tegra SoCs, requiring SOCTHERM shift, mask, register
> > address, and nominal calibration values to be configurable.
> >
> > Additionally, a use_lower_precision option was implemented to account for
> > the Tegra114's 0.5C thermal data output, which differs from the 1C
> > precision of newer SoCs.
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > ---
> >  drivers/thermal/tegra/soctherm-fuse.c     | 31 ++++++++++++++++-------
> >  drivers/thermal/tegra/soctherm.h          |  8 +++++-
> >  drivers/thermal/tegra/tegra124-soctherm.c |  6 +++++
> >  drivers/thermal/tegra/tegra132-soctherm.c |  6 +++++
> >  drivers/thermal/tegra/tegra210-soctherm.c |  6 +++++
> >  5 files changed, 47 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/thermal/tegra/soctherm-fuse.c
> > b/drivers/thermal/tegra/soctherm-fuse.c index 190f95280e0b..d27876dd9b2a
> > 100644
> > --- a/drivers/thermal/tegra/soctherm-fuse.c
> > +++ b/drivers/thermal/tegra/soctherm-fuse.c
> > @@ -9,15 +9,10 @@
> >
> >  #include "soctherm.h"
> >
> > -#define NOMINAL_CALIB_FT                     105
> > -#define NOMINAL_CALIB_CP                     25
> > -
> >  #define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK   0x1fff
> >  #define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK   (0x1fff << 13)
> >  #define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT  13
> >
> > -#define FUSE_TSENSOR_COMMON                  0x180
> > -
> >  /*
> >   * Tegra210: Layout of bits in FUSE_TSENSOR_COMMON:
> >   *    3                   2                   1                   0
> > @@ -26,7 +21,7 @@
> >   * |       BASE_FT       |      BASE_CP      | SHFT_FT | SHIFT_CP  |
> >   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> >   *
> > - * Tegra12x, etc:
> > + * Tegra124:
> >   * In chips prior to Tegra210, this fuse was incorrectly sized as 26 bits,
> >   * and didn't hold SHIFT_CP in [31:26]. Therefore these missing six bits
> >   * were obtained via the FUSE_SPARE_REALIGNMENT_REG register [5:0].
> > @@ -44,6 +39,13 @@
> >   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> >   * |---------------------------------------------------| SHIFT_CP  |
> >   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > + *
> > + * Tegra114: Layout of bits in FUSE_TSENSOR_COMMON aka FUSE_VSENSOR_CALIB:
> > + *    3                   2                   1                   0
> > + *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
> > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > + * | SHFT_FT |       BASE_FT       | SHIFT_CP  |      BASE_CP      |
> > + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> >   */
> >
> >  #define CALIB_COEFFICIENT 1000000LL
> > @@ -77,7 +79,7 @@ int tegra_calc_shared_calib(const struct
> > tegra_soctherm_fuse *tfuse, s32 shifted_cp, shifted_ft;
> >       int err;
> >
> > -     err = tegra_fuse_readl(FUSE_TSENSOR_COMMON, &val);
> > +     err = tegra_fuse_readl(tfuse->fuse_common_reg, &val);
> >       if (err)
> >               return err;
> >
> > @@ -96,10 +98,21 @@ int tegra_calc_shared_calib(const struct
> > tegra_soctherm_fuse *tfuse, return err;
> >       }
> >
> > +     shifted_cp = (val & tfuse->fuse_shift_cp_mask) >>
> > +                  tfuse->fuse_shift_cp_shift;
> >       shifted_cp = sign_extend32(val, 5);
> >
> > -     shared->actual_temp_cp = 2 * NOMINAL_CALIB_CP + shifted_cp;
> > -     shared->actual_temp_ft = 2 * NOMINAL_CALIB_FT + shifted_ft;
> > +     shared->actual_temp_cp = 2 * tfuse->nominal_calib_cp + shifted_cp;
> > +     shared->actual_temp_ft = 2 * tfuse->nominal_calib_ft + shifted_ft;
> > +
> > +     /*
> > +      * Tegra114 provides fuse thermal corrections in 0.5C while newer
> > +      * SoCs provide data in 1C
> > +      */
>
> I've been looking a bit into these fuses, and from what I can tell the
> precision for these fuses should be in 0.5C units for all of Tegra114, 124,
> and 210. The documented nominal CP (cold) and FT (hot) temperatures for
> Tegra114 should be 25C and 90C respectively.
>
> The reason for the code '2 * NOMINAL_CALIB_XX + shifted_xx' then is that the
> value of 'actual_temp_xx' is in 0.5C units -- NOMINAL_CALIB_XX being in 1C
> units and being multiplied by 2 to match the units of the shifted_xx values
> coming from fuses.
>
> If you're getting correct values with your code, clearly there's more hijinks
> going on.
>

I have based this code on downstream kernel which sometimes can be
quite challenging to understand correctly. If you assume that Tegra114
fits into existing driver even more, that is great, I will test it and
remove unnecessary parts.