1
0

Merge tag 'thermal-v6.18-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux

Merge updates of thermal drivers for 6.18-rc1 from Daniel Lezcano:

"- Add the QCS615 compatible DT bindings for QCom platforms (Gaurav
   Kohli)

 - Support fallback trimming values when the fuse is empty in the R-Car
   driver (Marek Vasut)

 - Remove unneeded semicolon in the Mediatek LVTS driver (Jiapeng
   Chong)

 - Fix the LMH Kconfig option by selecting QCOM_SCM and take the
   opportunity to add the COMPILE_TEST option for the QCom's LMH
   feature (Dmitry Baryshkov)

 - Fix the missing includes and incorrect error message in the Qcom's
   LMH driver (Dmitry Baryshkov)

 - Fix comment typo and add the documentation in the Kconfig for the
   R-Car Gen3 and Gen4 (Marek Vasut)

 - Add Tegra114 SOCTHERM support (Svyatoslav Ryhel)

 - Rename the functions name in the driver to be consistent and generic
   with the different R-Car platform variants (Wolfram Sang)

 - Register the TI K3 J72xx bandgap sensor as a hwmon sensor too
   (Michael Walle)

 - Add and document the thermal sensor unit reporting the junction
   temperature of the RZ/G3S SoC (Claudiu Beznea)

 - Support the GRF in the Rockchip driver (Sebastian Reichel)

 - Add a temperature IIO sensor channel in the generic thermal ADC
   driver (Svyatoslav Ryhel)

 - Document the temperature sensor on the QCOM's Glymur platform (Manaf
   Meethalavalappu)

 - Add and document the thermal sensor unit reporting the junction
   temperature of the RZ/G3E SoC (John Madieu)"

* tag 'thermal-v6.18-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (24 commits)
  dt-bindings: thermal: qcom-tsens: Document the Glymur temperature Sensor
  thermal/drivers/renesas/rzg3e: Add thermal driver for the Renesas RZ/G3E SoC
  dt-bindings: thermal: r9a09g047-tsu: Document the TSU unit
  thermal/drivers/thermal-generic-adc: Add temperature sensor channel
  dt-bindings: thermal: rockchip: Tighten grf requirements
  thermal/drivers/rockchip: Shut up GRF warning
  thermal/drivers/rockchip: Unify struct rockchip_tsadc_chip format
  thermal/drivers/renesas/rzg3s: Add thermal driver for the Renesas RZ/G3S SoC
  dt-bindings: thermal: r9a08g045-tsu: Document the TSU unit
  thermal/drivers/k3_j72xx_bandgap: Register sensors with hwmon
  thermal/drivers/rcar_gen3: Fix mapping SoCs to generic Gen4 entry
  thermal/drivers/tegra: Add Tegra114 specific SOCTHERM driver
  dt-bindings: thermal: add Tegra114 soctherm header
  thermal/drivers/tegra/soctherm-fuse: Prepare calibration for Tegra114 support
  dt-bindings: thermal: Document Tegra114 SOCTHERM Thermal Management System
  thermal/drivers/rcar_gen3: Document Gen4 support in Kconfig entry
  thermal/drivers/rcar_gen3: Fix comment typo
  drivers/thermal/qcom/lmh: Fix incorrect error message
  thermal/drivers/qcom/lmh: Add missing IRQ includes
  thermal/drivers/qcom: Make LMH select QCOM_SCM
  ...
This commit is contained in:
Rafael J. Wysocki
2025-09-26 22:01:13 +02:00
25 changed files with 911 additions and 62 deletions

View File

@@ -18,6 +18,7 @@ description: The SOCTHERM IP block contains thermal sensors, support for
properties:
compatible:
enum:
- nvidia,tegra114-soctherm
- nvidia,tegra124-soctherm
- nvidia,tegra132-soctherm
- nvidia,tegra210-soctherm
@@ -206,6 +207,7 @@ allOf:
compatible:
contains:
enum:
- nvidia,tegra114-soctherm
- nvidia,tegra124-soctherm
- nvidia,tegra210-soctherm
- nvidia,tegra210b01-soctherm

View File

@@ -49,11 +49,13 @@ properties:
- description: v2 of TSENS
items:
- enum:
- qcom,glymur-tsens
- qcom,milos-tsens
- qcom,msm8953-tsens
- qcom,msm8996-tsens
- qcom,msm8998-tsens
- qcom,qcm2290-tsens
- qcom,qcs615-tsens
- qcom,sa8255p-tsens
- qcom,sa8775p-tsens
- qcom,sar2130p-tsens

View File

@@ -0,0 +1,93 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/renesas,r9a08g045-tsu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/G3S Thermal Sensor Unit
description:
The thermal sensor unit (TSU) measures the temperature(Tj) inside
the LSI.
maintainers:
- Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
$ref: thermal-sensor.yaml#
properties:
compatible:
const: renesas,r9a08g045-tsu
reg:
maxItems: 1
clocks:
items:
- description: TSU module clock
power-domains:
maxItems: 1
resets:
items:
- description: TSU module reset
io-channels:
items:
- description: ADC channel which reports the TSU temperature
io-channel-names:
items:
- const: tsu
"#thermal-sensor-cells":
const: 0
required:
- compatible
- reg
- clocks
- power-domains
- resets
- io-channels
- io-channel-names
- '#thermal-sensor-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r9a08g045-cpg.h>
tsu: thermal@10059000 {
compatible = "renesas,r9a08g045-tsu";
reg = <0x10059000 0x1000>;
clocks = <&cpg CPG_MOD R9A08G045_TSU_PCLK>;
resets = <&cpg R9A08G045_TSU_PRESETN>;
power-domains = <&cpg>;
#thermal-sensor-cells = <0>;
io-channels = <&adc 8>;
io-channel-names = "tsu";
};
thermal-zones {
cpu-thermal {
polling-delay-passive = <250>;
polling-delay = <1000>;
thermal-sensors = <&tsu>;
trips {
sensor_crit: sensor-crit {
temperature = <125000>;
hysteresis = <1000>;
type = "critical";
};
target: trip-point {
temperature = <100000>;
hysteresis = <1000>;
type = "passive";
};
};
};
};

View File

@@ -0,0 +1,87 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/renesas,r9a09g047-tsu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/G3E Temperature Sensor Unit (TSU)
maintainers:
- John Madieu <john.madieu.xa@bp.renesas.com>
description:
The Temperature Sensor Unit (TSU) is an integrated thermal sensor that
monitors the chip temperature on the Renesas RZ/G3E SoC. The TSU provides
real-time temperature measurements for thermal management.
properties:
compatible:
const: renesas,r9a09g047-tsu
reg:
maxItems: 1
clocks:
maxItems: 1
resets:
maxItems: 1
power-domains:
maxItems: 1
interrupts:
items:
- description: Conversion complete interrupt signal (pulse)
- description: Comparison result interrupt signal (level)
interrupt-names:
items:
- const: adi
- const: adcmpi
"#thermal-sensor-cells":
const: 0
renesas,tsu-trim:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle to system controller
- description: offset of trim registers
description:
Phandle and offset to the system controller containing the TSU
calibration trim values. The offset points to the first trim register
(OTPTSU1TRMVAL0), with the second trim register (OTPTSU1TRMVAL1) located
at offset + 4.
required:
- compatible
- reg
- clocks
- resets
- power-domains
- interrupts
- interrupt-names
- "#thermal-sensor-cells"
- renesas,tsu-trim
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/renesas,r9a09g047-cpg.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
thermal-sensor@14002000 {
compatible = "renesas,r9a09g047-tsu";
reg = <0x14002000 0x1000>;
clocks = <&cpg CPG_MOD 0x10a>;
resets = <&cpg 0xf8>;
power-domains = <&cpg>;
interrupts = <GIC_SPI 250 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "adi", "adcmpi";
#thermal-sensor-cells = <0>;
renesas,tsu-trim = <&sys 0x330>;
};

View File

@@ -119,6 +119,21 @@ required:
- resets
allOf:
- if:
properties:
compatible:
contains:
enum:
- rockchip,px30-tsadc
- rockchip,rk3366-tsadc
- rockchip,rk3399-tsadc
- rockchip,rk3568-tsadc
then:
required:
- rockchip,grf
else:
properties:
rockchip,grf: false
- if:
not:
properties:

View File

@@ -21568,6 +21568,20 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml
F: drivers/iio/potentiometer/x9250.c
RENESAS RZ/G3S THERMAL SENSOR UNIT DRIVER
M: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
L: linux-pm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/thermal/renesas,r9a08g045-tsu.yaml
F: drivers/thermal/renesas/rzg3s_thermal.c
RENESAS RZ/G3E THERMAL SENSOR UNIT DRIVER
M: John Madieu <john.madieu.xa@bp.renesas.com>
L: linux-pm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
F: drivers/thermal/renesas/rzg3e_thermal.c
RESET CONTROLLER FRAMEWORK
M: Philipp Zabel <p.zabel@pengutronix.de>
S: Maintained

View File

@@ -20,6 +20,8 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include "thermal_hwmon.h"
#define K3_VTM_DEVINFO_PWR0_OFFSET 0x4
#define K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK 0xf0
#define K3_VTM_TMPSENS0_CTRL_OFFSET 0x300
@@ -513,6 +515,8 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
ret = PTR_ERR(ti_thermal);
goto err_free_ref_table;
}
devm_thermal_add_hwmon_sysfs(bgp->dev, ti_thermal);
}
platform_set_drvdata(pdev, bgp);

View File

@@ -639,7 +639,7 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
lvts_sensor[i].low_thresh = INT_MIN;
lvts_sensor[i].high_thresh = INT_MIN;
};
}
lvts_ctrl->valid_sensor_mask = lvts_ctrl_data->valid_sensor_mask;

View File

@@ -34,7 +34,8 @@ config QCOM_SPMI_TEMP_ALARM
config QCOM_LMH
tristate "Qualcomm Limits Management Hardware"
depends on ARCH_QCOM && QCOM_SCM
depends on ARCH_QCOM || COMPILE_TEST
select QCOM_SCM
help
This enables initialization of Qualcomm limits management
hardware(LMh). LMh allows for hardware-enforced mitigation for cpus based on

View File

@@ -5,6 +5,8 @@
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/irqdomain.h>
#include <linux/err.h>
#include <linux/platform_device.h>
@@ -204,7 +206,7 @@ static int lmh_probe(struct platform_device *pdev)
ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_THERMAL, LMH_TH_LOW_THRESHOLD, temp_low,
LMH_NODE_DCVS, node_id, 0);
if (ret) {
dev_err(dev, "Error setting thermal ARM threshold%d\n", ret);
dev_err(dev, "Error setting thermal LOW threshold%d\n", ret);
return ret;
}

View File

@@ -10,13 +10,13 @@ config RCAR_THERMAL
thermal framework.
config RCAR_GEN3_THERMAL
tristate "Renesas R-Car Gen3 and RZ/G2 thermal driver"
tristate "Renesas R-Car Gen3/Gen4 and RZ/G2 thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into
the Linux thermal framework.
Enable this to plug the R-Car Gen3/Gen4 or RZ/G2 thermal sensor
driver into the Linux thermal framework.
config RZG2L_THERMAL
tristate "Renesas RZ/G2L thermal driver"
@@ -26,3 +26,18 @@ config RZG2L_THERMAL
help
Enable this to plug the RZ/G2L thermal sensor driver into the Linux
thermal framework.
config RZG3S_THERMAL
tristate "Renesas RZ/G3S thermal driver"
depends on ARCH_R9A08G045 || COMPILE_TEST
depends on OF && IIO && RZG2L_ADC
help
Enable this to plug the RZ/G3S thermal sensor driver into the Linux
thermal framework.
config RZG3E_THERMAL
tristate "Renesas RZ/G3E thermal driver"
depends on ARCH_RENESAS || COMPILE_TEST
help
Enable this to plug the RZ/G3E thermal sensor driver into the Linux
thermal framework.

View File

@@ -3,3 +3,6 @@
obj-$(CONFIG_RCAR_GEN3_THERMAL) += rcar_gen3_thermal.o
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
obj-$(CONFIG_RZG2L_THERMAL) += rzg2l_thermal.o
obj-$(CONFIG_RZG3E_THERMAL) += rzg3e_thermal.o
obj-$(CONFIG_RZG3S_THERMAL) += rzg3s_thermal.o

View File

@@ -73,11 +73,17 @@ struct rcar_gen3_thermal_fuse_info {
u32 mask;
};
struct rcar_gen3_thermal_fuse_default {
u32 ptat[3];
u32 thcodes[TSC_MAX_NUM][3];
};
struct rcar_thermal_info {
int scale;
int adj_below;
int adj_above;
const struct rcar_gen3_thermal_fuse_info *fuses;
const struct rcar_gen3_thermal_fuse_default *fuse_defaults;
};
struct equation_set_coef {
@@ -165,7 +171,7 @@ static int rcar_gen3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
const struct equation_set_coef *coef;
int adj, decicelsius, reg, thcode;
/* Read register and convert to mili Celsius */
/* Read register and convert to millidegree Celsius */
reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
if (reg < tsc->thcode[1]) {
@@ -289,6 +295,7 @@ static void rcar_gen3_thermal_fetch_fuses(struct rcar_gen3_thermal_priv *priv)
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
{
const struct rcar_gen3_thermal_fuse_default *fuse_defaults = priv->info->fuse_defaults;
unsigned int i;
u32 thscp;
@@ -297,24 +304,16 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
if (!priv->info->fuses ||
(thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
/* Default THCODE values in case FUSEs are not set. */
static const int thcodes[TSC_MAX_NUM][3] = {
{ 3397, 2800, 2221 },
{ 3393, 2795, 2216 },
{ 3389, 2805, 2237 },
{ 3415, 2694, 2195 },
{ 3356, 2724, 2244 },
};
priv->ptat[0] = 2631;
priv->ptat[1] = 1509;
priv->ptat[2] = 435;
priv->ptat[0] = fuse_defaults->ptat[0];
priv->ptat[1] = fuse_defaults->ptat[1];
priv->ptat[2] = fuse_defaults->ptat[2];
for (i = 0; i < priv->num_tscs; i++) {
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
tsc->thcode[0] = thcodes[i][0];
tsc->thcode[1] = thcodes[i][1];
tsc->thcode[2] = thcodes[i][2];
tsc->thcode[0] = fuse_defaults->thcodes[i][0];
tsc->thcode[1] = fuse_defaults->thcodes[i][1];
tsc->thcode[2] = fuse_defaults->thcodes[i][2];
}
return false;
@@ -361,11 +360,33 @@ static const struct rcar_gen3_thermal_fuse_info rcar_gen3_thermal_fuse_info_gen4
.mask = GEN4_FUSE_MASK,
};
static const struct rcar_gen3_thermal_fuse_default rcar_gen3_thermal_fuse_default_info_gen3 = {
.ptat = { 2631, 1509, 435 },
.thcodes = {
{ 3397, 2800, 2221 },
{ 3393, 2795, 2216 },
{ 3389, 2805, 2237 },
{ 3415, 2694, 2195 },
{ 3356, 2724, 2244 },
},
};
static const struct rcar_gen3_thermal_fuse_default rcar_gen3_thermal_fuse_default_info_gen4 = {
.ptat = { 3274, 2164, 985 },
.thcodes = { /* All four THS units share the same trimming */
{ 3218, 2617, 1980 },
{ 3218, 2617, 1980 },
{ 3218, 2617, 1980 },
{ 3218, 2617, 1980 },
}
};
static const struct rcar_thermal_info rcar_m3w_thermal_info = {
.scale = 157,
.adj_below = -41,
.adj_above = 116,
.fuses = &rcar_gen3_thermal_fuse_info_gen3,
.fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen3,
};
static const struct rcar_thermal_info rcar_gen3_thermal_info = {
@@ -373,6 +394,15 @@ static const struct rcar_thermal_info rcar_gen3_thermal_info = {
.adj_below = -41,
.adj_above = 126,
.fuses = &rcar_gen3_thermal_fuse_info_gen3,
.fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen3,
};
static const struct rcar_thermal_info rcar_s4_thermal_info = {
.scale = 167,
.adj_below = -41,
.adj_above = 126,
.fuses = &rcar_gen3_thermal_fuse_info_gen4,
.fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen3,
};
static const struct rcar_thermal_info rcar_gen4_thermal_info = {
@@ -380,6 +410,7 @@ static const struct rcar_thermal_info rcar_gen4_thermal_info = {
.adj_below = -41,
.adj_above = 126,
.fuses = &rcar_gen3_thermal_fuse_info_gen4,
.fuse_defaults = &rcar_gen3_thermal_fuse_default_info_gen4,
};
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
@@ -421,7 +452,7 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
},
{
.compatible = "renesas,r8a779f0-thermal",
.data = &rcar_gen4_thermal_info,
.data = &rcar_s4_thermal_info,
},
{
.compatible = "renesas,r8a779g0-thermal",

View File

@@ -0,0 +1,272 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G3S TSU Thermal Sensor Driver
*
* Copyright (C) 2024 Renesas Electronics Corporation
*/
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/iio/consumer.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/thermal.h>
#include <linux/units.h>
#include "../thermal_hwmon.h"
#define TSU_SM 0x0
#define TSU_SM_EN BIT(0)
#define TSU_SM_OE BIT(1)
#define OTPTSUTRIM_REG(n) (0x18 + (n) * 0x4)
#define OTPTSUTRIM_EN_MASK BIT(31)
#define OTPTSUTRIM_MASK GENMASK(11, 0)
#define TSU_READ_STEPS 8
/* Default calibration values, if FUSE values are missing. */
#define SW_CALIB0_VAL 1297
#define SW_CALIB1_VAL 751
#define MCELSIUS(temp) ((temp) * MILLIDEGREE_PER_DEGREE)
/**
* struct rzg3s_thermal_priv - RZ/G3S thermal private data structure
* @base: TSU base address
* @dev: device pointer
* @tz: thermal zone pointer
* @rstc: reset control
* @channel: IIO channel to read the TSU
* @mode: current device mode
* @calib0: calibration value
* @calib1: calibration value
*/
struct rzg3s_thermal_priv {
void __iomem *base;
struct device *dev;
struct thermal_zone_device *tz;
struct reset_control *rstc;
struct iio_channel *channel;
enum thermal_device_mode mode;
u16 calib0;
u16 calib1;
};
static int rzg3s_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
{
struct rzg3s_thermal_priv *priv = thermal_zone_device_priv(tz);
int ts_code_ave = 0;
if (priv->mode != THERMAL_DEVICE_ENABLED)
return -EAGAIN;
for (u8 i = 0; i < TSU_READ_STEPS; i++) {
int ret, val;
ret = iio_read_channel_raw(priv->channel, &val);
if (ret < 0)
return ret;
ts_code_ave += val;
/*
* According to the HW manual (Rev.1.10, section 40.4.4 Procedure for Measuring
* the Temperature) we need to wait here at leat 3us.
*/
usleep_range(5, 10);
}
ts_code_ave = DIV_ROUND_CLOSEST(MCELSIUS(ts_code_ave), TSU_READ_STEPS);
/*
* According to the HW manual (Rev.1.10, section 40.4.4 Procedure for Measuring the
* Temperature) the computation formula is as follows:
*
* Tj = (ts_code_ave - priv->calib1) * 165 / (priv->calib0 - priv->calib1) - 40
*
* Convert everything to milli Celsius before applying the formula to avoid
* losing precision.
*/
*temp = div_s64((s64)(ts_code_ave - MCELSIUS(priv->calib1)) * MCELSIUS(165),
MCELSIUS(priv->calib0 - priv->calib1)) - MCELSIUS(40);
/* Report it in milli degrees Celsius and round it up to 0.5 degrees Celsius. */
*temp = roundup(*temp, 500);
return 0;
}
static void rzg3s_thermal_set_mode(struct rzg3s_thermal_priv *priv,
enum thermal_device_mode mode)
{
struct device *dev = priv->dev;
int ret;
ret = pm_runtime_resume_and_get(dev);
if (ret)
return;
if (mode == THERMAL_DEVICE_DISABLED) {
writel(0, priv->base + TSU_SM);
} else {
writel(TSU_SM_EN, priv->base + TSU_SM);
/*
* According to the HW manual (Rev.1.10, section 40.4.1 Procedure for
* Starting the TSU) we need to wait here 30us or more.
*/
usleep_range(30, 40);
writel(TSU_SM_OE | TSU_SM_EN, priv->base + TSU_SM);
/*
* According to the HW manual (Rev.1.10, section 40.4.1 Procedure for
* Starting the TSU) we need to wait here 50us or more.
*/
usleep_range(50, 60);
}
pm_runtime_put_autosuspend(dev);
}
static int rzg3s_thermal_change_mode(struct thermal_zone_device *tz,
enum thermal_device_mode mode)
{
struct rzg3s_thermal_priv *priv = thermal_zone_device_priv(tz);
if (priv->mode == mode)
return 0;
rzg3s_thermal_set_mode(priv, mode);
priv->mode = mode;
return 0;
}
static const struct thermal_zone_device_ops rzg3s_tz_of_ops = {
.get_temp = rzg3s_thermal_get_temp,
.change_mode = rzg3s_thermal_change_mode,
};
static int rzg3s_thermal_read_calib(struct rzg3s_thermal_priv *priv)
{
struct device *dev = priv->dev;
u32 val;
int ret;
ret = pm_runtime_resume_and_get(dev);
if (ret)
return ret;
val = readl(priv->base + OTPTSUTRIM_REG(0));
if (val & OTPTSUTRIM_EN_MASK)
priv->calib0 = FIELD_GET(OTPTSUTRIM_MASK, val);
else
priv->calib0 = SW_CALIB0_VAL;
val = readl(priv->base + OTPTSUTRIM_REG(1));
if (val & OTPTSUTRIM_EN_MASK)
priv->calib1 = FIELD_GET(OTPTSUTRIM_MASK, val);
else
priv->calib1 = SW_CALIB1_VAL;
pm_runtime_put_autosuspend(dev);
return 0;
}
static int rzg3s_thermal_probe(struct platform_device *pdev)
{
struct rzg3s_thermal_priv *priv;
struct device *dev = &pdev->dev;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
priv->channel = devm_iio_channel_get(dev, "tsu");
if (IS_ERR(priv->channel))
return dev_err_probe(dev, PTR_ERR(priv->channel), "Failed to get IIO channel!\n");
priv->rstc = devm_reset_control_get_exclusive_deasserted(dev, NULL);
if (IS_ERR(priv->rstc))
return dev_err_probe(dev, PTR_ERR(priv->rstc), "Failed to get reset!\n");
priv->dev = dev;
priv->mode = THERMAL_DEVICE_DISABLED;
platform_set_drvdata(pdev, priv);
pm_runtime_set_autosuspend_delay(dev, 300);
pm_runtime_use_autosuspend(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable runtime PM!\n");
ret = rzg3s_thermal_read_calib(priv);
if (ret)
return dev_err_probe(dev, ret, "Failed to read calibration data!\n");
priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &rzg3s_tz_of_ops);
if (IS_ERR(priv->tz))
return dev_err_probe(dev, PTR_ERR(priv->tz), "Failed to register thermal zone!\n");
ret = devm_thermal_add_hwmon_sysfs(dev, priv->tz);
if (ret)
return dev_err_probe(dev, ret, "Failed to add hwmon sysfs!\n");
return 0;
}
static int rzg3s_thermal_suspend(struct device *dev)
{
struct rzg3s_thermal_priv *priv = dev_get_drvdata(dev);
rzg3s_thermal_set_mode(priv, THERMAL_DEVICE_DISABLED);
return reset_control_assert(priv->rstc);
}
static int rzg3s_thermal_resume(struct device *dev)
{
struct rzg3s_thermal_priv *priv = dev_get_drvdata(dev);
int ret;
ret = reset_control_deassert(priv->rstc);
if (ret)
return ret;
if (priv->mode != THERMAL_DEVICE_DISABLED)
rzg3s_thermal_set_mode(priv, priv->mode);
return 0;
}
static const struct dev_pm_ops rzg3s_thermal_pm_ops = {
SYSTEM_SLEEP_PM_OPS(rzg3s_thermal_suspend, rzg3s_thermal_resume)
};
static const struct of_device_id rzg3s_thermal_dt_ids[] = {
{ .compatible = "renesas,r9a08g045-tsu" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rzg3s_thermal_dt_ids);
static struct platform_driver rzg3s_thermal_driver = {
.driver = {
.name = "rzg3s-thermal",
.of_match_table = rzg3s_thermal_dt_ids,
.pm = pm_ptr(&rzg3s_thermal_pm_ops),
},
.probe = rzg3s_thermal_probe,
};
module_platform_driver(rzg3s_thermal_driver);
MODULE_DESCRIPTION("Renesas RZ/G3S Thermal Sensor Unit Driver");
MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>");
MODULE_LICENSE("GPL");

View File

@@ -74,6 +74,7 @@ struct chip_tsadc_table {
* @tshut_temp: the hardware-controlled shutdown temperature value, with no trim
* @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
* @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
* @grf_required: true, if a GRF is required for proper functionality
* @initialize: SoC special initialize tsadc controller method
* @irq_ack: clear the interrupt
* @control: enable/disable method for the tsadc controller
@@ -97,6 +98,9 @@ struct rockchip_tsadc_chip {
enum tshut_mode tshut_mode;
enum tshut_polarity tshut_polarity;
/* GRF availability */
bool grf_required;
/* Chip-wide methods */
void (*initialize)(struct regmap *grf,
void __iomem *reg, enum tshut_polarity p);
@@ -1098,10 +1102,9 @@ static const struct rockchip_tsadc_chip px30_tsadc_data = {
/* cpu, gpu */
.chn_offset = 0,
.chn_num = 2, /* 2 channels for tsadc */
.grf_required = true,
.tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
.tshut_temp = 95000,
.initialize = rk_tsadcv4_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
@@ -1109,7 +1112,6 @@ static const struct rockchip_tsadc_chip px30_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3328_code_table,
.length = ARRAY_SIZE(rk3328_code_table),
@@ -1122,11 +1124,10 @@ static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
/* cpu */
.chn_offset = 0,
.chn_num = 1, /* one channel for tsadc */
.grf_required = false,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv2_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
@@ -1134,7 +1135,6 @@ static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rv1108_table,
.length = ARRAY_SIZE(rv1108_table),
@@ -1147,11 +1147,10 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
/* cpu */
.chn_offset = 0,
.chn_num = 1, /* one channel for tsadc */
.grf_required = false,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv2_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
@@ -1159,7 +1158,6 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3228_code_table,
.length = ARRAY_SIZE(rk3228_code_table),
@@ -1172,11 +1170,10 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
/* cpu, gpu */
.chn_offset = 1,
.chn_num = 2, /* two channels for tsadc */
.grf_required = false,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv2_initialize,
.irq_ack = rk_tsadcv2_irq_ack,
.control = rk_tsadcv2_control,
@@ -1184,7 +1181,6 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3288_code_table,
.length = ARRAY_SIZE(rk3288_code_table),
@@ -1197,10 +1193,9 @@ static const struct rockchip_tsadc_chip rk3328_tsadc_data = {
/* cpu */
.chn_offset = 0,
.chn_num = 1, /* one channels for tsadc */
.grf_required = false,
.tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
.tshut_temp = 95000,
.initialize = rk_tsadcv2_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
@@ -1208,7 +1203,6 @@ static const struct rockchip_tsadc_chip rk3328_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3328_code_table,
.length = ARRAY_SIZE(rk3328_code_table),
@@ -1221,11 +1215,10 @@ static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
/* cpu, gpu */
.chn_offset = 0,
.chn_num = 2, /* two channels for tsadc */
.grf_required = true,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv3_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
@@ -1233,7 +1226,6 @@ static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3228_code_table,
.length = ARRAY_SIZE(rk3228_code_table),
@@ -1246,11 +1238,10 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
/* cpu, gpu */
.chn_offset = 0,
.chn_num = 2, /* two channels for tsadc */
.grf_required = false,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv2_initialize,
.irq_ack = rk_tsadcv2_irq_ack,
.control = rk_tsadcv2_control,
@@ -1258,7 +1249,6 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3368_code_table,
.length = ARRAY_SIZE(rk3368_code_table),
@@ -1271,11 +1261,10 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
/* cpu, gpu */
.chn_offset = 0,
.chn_num = 2, /* two channels for tsadc */
.grf_required = true,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv3_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
@@ -1283,7 +1272,6 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3399_code_table,
.length = ARRAY_SIZE(rk3399_code_table),
@@ -1296,11 +1284,10 @@ static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
/* cpu, gpu */
.chn_offset = 0,
.chn_num = 2, /* two channels for tsadc */
.grf_required = true,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv7_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
@@ -1308,7 +1295,6 @@ static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rk3568_code_table,
.length = ARRAY_SIZE(rk3568_code_table),
@@ -1321,6 +1307,7 @@ static const struct rockchip_tsadc_chip rk3576_tsadc_data = {
/* top, big_core, little_core, ddr, npu, gpu */
.chn_offset = 0,
.chn_num = 6, /* six channels for tsadc */
.grf_required = false,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
@@ -1345,6 +1332,7 @@ static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
/* top, big_core0, big_core1, little_core, center, gpu, npu */
.chn_offset = 0,
.chn_num = 7, /* seven channels for tsadc */
.grf_required = false,
.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
@@ -1621,12 +1609,10 @@ static int rockchip_configure_from_dt(struct device *dev,
return -EINVAL;
}
/* The tsadc wont to handle the error in here since some SoCs didn't
* need this property.
*/
thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR(thermal->grf))
dev_warn(dev, "Missing rockchip,grf property\n");
if (IS_ERR(thermal->grf) && thermal->chip->grf_required)
return dev_err_probe(dev, PTR_ERR(thermal->grf),
"Missing rockchip,grf property\n");
rockchip_get_trim_configuration(dev, np, thermal);

View File

@@ -4,6 +4,7 @@ obj-$(CONFIG_TEGRA_BPMP_THERMAL) += tegra-bpmp-thermal.o
obj-$(CONFIG_TEGRA30_TSENSOR) += tegra30-tsensor.o
tegra-soctherm-y := soctherm.o soctherm-fuse.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114-soctherm.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124-soctherm.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-soctherm.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-soctherm.o

View File

@@ -9,15 +9,12 @@
#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 +23,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 +41,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 +81,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 +100,12 @@ 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_ft = 2 * tfuse->nominal_calib_ft + shifted_ft;
return 0;
}

View File

@@ -31,6 +31,7 @@
#include <linux/reset.h>
#include <linux/thermal.h>
#include <dt-bindings/thermal/tegra114-soctherm.h>
#include <dt-bindings/thermal/tegra124-soctherm.h>
#include "../thermal_core.h"
@@ -357,6 +358,12 @@ struct soctherm_oc_irq_chip_data {
static struct soctherm_oc_irq_chip_data soc_irq_cdata;
/* Ensure that TEGRA114_* and TEGRA124_* counterparts are equal */
static_assert(TEGRA114_SOCTHERM_SENSOR_CPU == TEGRA124_SOCTHERM_SENSOR_CPU);
static_assert(TEGRA114_SOCTHERM_SENSOR_MEM == TEGRA124_SOCTHERM_SENSOR_MEM);
static_assert(TEGRA114_SOCTHERM_SENSOR_GPU == TEGRA124_SOCTHERM_SENSOR_GPU);
static_assert(TEGRA114_SOCTHERM_SENSOR_PLLX == TEGRA124_SOCTHERM_SENSOR_PLLX);
/**
* ccroc_writel() - writes a value to a CCROC register
* @ts: pointer to a struct tegra_soctherm
@@ -2045,6 +2052,12 @@ static void soctherm_init(struct platform_device *pdev)
}
static const struct of_device_id tegra_soctherm_of_match[] = {
#ifdef CONFIG_ARCH_TEGRA_114_SOC
{
.compatible = "nvidia,tegra114-soctherm",
.data = &tegra114_soctherm,
},
#endif
#ifdef CONFIG_ARCH_TEGRA_124_SOC
{
.compatible = "nvidia,tegra124-soctherm",

View File

@@ -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,11 @@ 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_ft;
};
struct tsensor_shared_calib {
@@ -137,6 +142,10 @@ int tegra_calc_tsensor_calib(const struct tegra_tsensor *sensor,
const struct tsensor_shared_calib *shared,
u32 *calib);
#ifdef CONFIG_ARCH_TEGRA_114_SOC
extern const struct tegra_soctherm_soc tegra114_soctherm;
#endif
#ifdef CONFIG_ARCH_TEGRA_124_SOC
extern const struct tegra_soctherm_soc tegra124_soctherm;
#endif

View File

@@ -0,0 +1,209 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2024, Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <dt-bindings/thermal/tegra114-soctherm.h>
#include "soctherm.h"
#define TEGRA114_THERMTRIP_ANY_EN_MASK (0x1 << 28)
#define TEGRA114_THERMTRIP_MEM_EN_MASK (0x1 << 27)
#define TEGRA114_THERMTRIP_GPU_EN_MASK (0x1 << 26)
#define TEGRA114_THERMTRIP_CPU_EN_MASK (0x1 << 25)
#define TEGRA114_THERMTRIP_TSENSE_EN_MASK (0x1 << 24)
#define TEGRA114_THERMTRIP_GPUMEM_THRESH_MASK (0xff << 16)
#define TEGRA114_THERMTRIP_CPU_THRESH_MASK (0xff << 8)
#define TEGRA114_THERMTRIP_TSENSE_THRESH_MASK 0xff
#define TEGRA114_THERMCTL_LVL0_UP_THRESH_MASK (0xff << 17)
#define TEGRA114_THERMCTL_LVL0_DN_THRESH_MASK (0xff << 9)
#define TEGRA114_THRESH_GRAIN 1000
#define TEGRA114_BPTT 8
static const struct tegra_tsensor_configuration tegra114_tsensor_config = {
.tall = 16300,
.tiddq_en = 1,
.ten_count = 1,
.tsample = 163,
.tsample_ate = 655,
};
static const struct tegra_tsensor_group tegra114_tsensor_group_cpu = {
.id = TEGRA114_SOCTHERM_SENSOR_CPU,
.name = "cpu",
.sensor_temp_offset = SENSOR_TEMP1,
.sensor_temp_mask = SENSOR_TEMP1_CPU_TEMP_MASK,
.pdiv = 10,
.pdiv_ate = 10,
.pdiv_mask = SENSOR_PDIV_CPU_MASK,
.pllx_hotspot_diff = 6,
.pllx_hotspot_mask = SENSOR_HOTSPOT_CPU_MASK,
.thermtrip_any_en_mask = TEGRA114_THERMTRIP_ANY_EN_MASK,
.thermtrip_enable_mask = TEGRA114_THERMTRIP_CPU_EN_MASK,
.thermtrip_threshold_mask = TEGRA114_THERMTRIP_CPU_THRESH_MASK,
.thermctl_isr_mask = THERM_IRQ_CPU_MASK,
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
.thermctl_lvl0_up_thresh_mask = TEGRA114_THERMCTL_LVL0_UP_THRESH_MASK,
.thermctl_lvl0_dn_thresh_mask = TEGRA114_THERMCTL_LVL0_DN_THRESH_MASK,
};
static const struct tegra_tsensor_group tegra114_tsensor_group_gpu = {
.id = TEGRA114_SOCTHERM_SENSOR_GPU,
.name = "gpu",
.sensor_temp_offset = SENSOR_TEMP1,
.sensor_temp_mask = SENSOR_TEMP1_GPU_TEMP_MASK,
.pdiv = 10,
.pdiv_ate = 10,
.pdiv_mask = SENSOR_PDIV_GPU_MASK,
.pllx_hotspot_diff = 6,
.pllx_hotspot_mask = SENSOR_HOTSPOT_GPU_MASK,
.thermtrip_any_en_mask = TEGRA114_THERMTRIP_ANY_EN_MASK,
.thermtrip_enable_mask = TEGRA114_THERMTRIP_GPU_EN_MASK,
.thermtrip_threshold_mask = TEGRA114_THERMTRIP_GPUMEM_THRESH_MASK,
.thermctl_isr_mask = THERM_IRQ_GPU_MASK,
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
.thermctl_lvl0_up_thresh_mask = TEGRA114_THERMCTL_LVL0_UP_THRESH_MASK,
.thermctl_lvl0_dn_thresh_mask = TEGRA114_THERMCTL_LVL0_DN_THRESH_MASK,
};
static const struct tegra_tsensor_group tegra114_tsensor_group_pll = {
.id = TEGRA114_SOCTHERM_SENSOR_PLLX,
.name = "pll",
.sensor_temp_offset = SENSOR_TEMP2,
.sensor_temp_mask = SENSOR_TEMP2_PLLX_TEMP_MASK,
.pdiv = 10,
.pdiv_ate = 10,
.pdiv_mask = SENSOR_PDIV_PLLX_MASK,
.thermtrip_any_en_mask = TEGRA114_THERMTRIP_ANY_EN_MASK,
.thermtrip_enable_mask = TEGRA114_THERMTRIP_TSENSE_EN_MASK,
.thermtrip_threshold_mask = TEGRA114_THERMTRIP_TSENSE_THRESH_MASK,
.thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
.thermctl_lvl0_up_thresh_mask = TEGRA114_THERMCTL_LVL0_UP_THRESH_MASK,
.thermctl_lvl0_dn_thresh_mask = TEGRA114_THERMCTL_LVL0_DN_THRESH_MASK,
};
static const struct tegra_tsensor_group tegra114_tsensor_group_mem = {
.id = TEGRA114_SOCTHERM_SENSOR_MEM,
.name = "mem",
.sensor_temp_offset = SENSOR_TEMP2,
.sensor_temp_mask = SENSOR_TEMP2_MEM_TEMP_MASK,
.pdiv = 10,
.pdiv_ate = 10,
.pdiv_mask = SENSOR_PDIV_MEM_MASK,
.pllx_hotspot_diff = 0,
.pllx_hotspot_mask = SENSOR_HOTSPOT_MEM_MASK,
.thermtrip_any_en_mask = TEGRA114_THERMTRIP_ANY_EN_MASK,
.thermtrip_enable_mask = TEGRA114_THERMTRIP_MEM_EN_MASK,
.thermtrip_threshold_mask = TEGRA114_THERMTRIP_GPUMEM_THRESH_MASK,
.thermctl_isr_mask = THERM_IRQ_MEM_MASK,
.thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
.thermctl_lvl0_up_thresh_mask = TEGRA114_THERMCTL_LVL0_UP_THRESH_MASK,
.thermctl_lvl0_dn_thresh_mask = TEGRA114_THERMCTL_LVL0_DN_THRESH_MASK,
};
static const struct tegra_tsensor_group *tegra114_tsensor_groups[] = {
&tegra114_tsensor_group_cpu,
&tegra114_tsensor_group_gpu,
&tegra114_tsensor_group_pll,
&tegra114_tsensor_group_mem,
};
static const struct tegra_tsensor tegra114_tsensors[] = {
{
.name = "cpu0",
.base = 0xc0,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x098,
.fuse_corr_alpha = 1196400,
.fuse_corr_beta = -13600000,
.group = &tegra114_tsensor_group_cpu,
}, {
.name = "cpu1",
.base = 0xe0,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x084,
.fuse_corr_alpha = 1196400,
.fuse_corr_beta = -13600000,
.group = &tegra114_tsensor_group_cpu,
}, {
.name = "cpu2",
.base = 0x100,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x088,
.fuse_corr_alpha = 1196400,
.fuse_corr_beta = -13600000,
.group = &tegra114_tsensor_group_cpu,
}, {
.name = "cpu3",
.base = 0x120,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x12c,
.fuse_corr_alpha = 1196400,
.fuse_corr_beta = -13600000,
.group = &tegra114_tsensor_group_cpu,
}, {
.name = "mem0",
.base = 0x140,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x158,
.fuse_corr_alpha = 1000000,
.fuse_corr_beta = 0,
.group = &tegra114_tsensor_group_mem,
}, {
.name = "mem1",
.base = 0x160,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x15c,
.fuse_corr_alpha = 1000000,
.fuse_corr_beta = 0,
.group = &tegra114_tsensor_group_mem,
}, {
.name = "gpu",
.base = 0x180,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x154,
.fuse_corr_alpha = 1124500,
.fuse_corr_beta = -9793100,
.group = &tegra114_tsensor_group_gpu,
}, {
.name = "pllx",
.base = 0x1a0,
.config = &tegra114_tsensor_config,
.calib_fuse_offset = 0x160,
.fuse_corr_alpha = 1224200,
.fuse_corr_beta = -14665000,
.group = &tegra114_tsensor_group_pll,
},
};
static const struct tegra_soctherm_fuse tegra114_soctherm_fuse = {
.fuse_base_cp_mask = 0x3ff,
.fuse_base_cp_shift = 0,
.fuse_shift_cp_mask = 0x3f << 10,
.fuse_shift_cp_shift = 10,
.fuse_base_ft_mask = 0x7ff << 16,
.fuse_base_ft_shift = 16,
.fuse_shift_ft_mask = 0x1f << 27,
.fuse_shift_ft_shift = 27,
.fuse_common_reg = FUSE_VSENSOR_CALIB,
.fuse_spare_realignment = 0,
.nominal_calib_ft = 90,
};
const struct tegra_soctherm_soc tegra114_soctherm = {
.tsensors = tegra114_tsensors,
.num_tsensors = ARRAY_SIZE(tegra114_tsensors),
.ttgs = tegra114_tsensor_groups,
.num_ttgs = ARRAY_SIZE(tegra114_tsensor_groups),
.tfuse = &tegra114_soctherm_fuse,
.thresh_grain = TEGRA114_THRESH_GRAIN,
.bptt = TEGRA114_BPTT,
.use_ccroc = false,
};

View File

@@ -200,11 +200,15 @@ 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 = 0x3f,
.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_ft = 105,
};
const struct tegra_soctherm_soc tegra124_soctherm = {

View File

@@ -200,11 +200,15 @@ 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 = 0x3f,
.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_ft = 105,
};
const struct tegra_soctherm_soc tegra132_soctherm = {

View File

@@ -201,11 +201,15 @@ 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 = 0x3f,
.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_ft = 105,
};
static struct tsensor_group_thermtrips tegra210_tsensor_thermtrips[] = {

View File

@@ -7,6 +7,7 @@
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*/
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -73,6 +74,58 @@ static const struct thermal_zone_device_ops gadc_thermal_ops = {
.get_temp = gadc_thermal_get_temp,
};
static const struct iio_chan_spec gadc_thermal_iio_channels[] = {
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
}
};
static int gadc_thermal_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct gadc_thermal_info *gtinfo = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
ret = gadc_thermal_get_temp(gtinfo->tz_dev, val);
if (ret)
return ret;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static const struct iio_info gadc_thermal_iio_info = {
.read_raw = gadc_thermal_read_raw,
};
static int gadc_iio_register(struct device *dev, struct gadc_thermal_info *gti)
{
struct gadc_thermal_info *gtinfo;
struct iio_dev *indio_dev;
indio_dev = devm_iio_device_alloc(dev, sizeof(*gtinfo));
if (!indio_dev)
return -ENOMEM;
gtinfo = iio_priv(indio_dev);
memcpy(gtinfo, gti, sizeof(*gtinfo));
indio_dev->name = dev_name(dev);
indio_dev->info = &gadc_thermal_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = gadc_thermal_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(gadc_thermal_iio_channels);
return devm_iio_device_register(dev, indio_dev);
}
static int gadc_thermal_read_linear_lookup_table(struct device *dev,
struct gadc_thermal_info *gti)
{
@@ -153,7 +206,7 @@ static int gadc_thermal_probe(struct platform_device *pdev)
devm_thermal_add_hwmon_sysfs(dev, gti->tz_dev);
return 0;
return gadc_iio_register(&pdev->dev, gti);
}
static const struct of_device_id of_adc_thermal_match[] = {

View File

@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* This header provides constants for binding nvidia,tegra114-soctherm.
*/
#ifndef _DT_BINDINGS_THERMAL_TEGRA114_SOCTHERM_H
#define _DT_BINDINGS_THERMAL_TEGRA114_SOCTHERM_H
#define TEGRA114_SOCTHERM_SENSOR_CPU 0
#define TEGRA114_SOCTHERM_SENSOR_MEM 1
#define TEGRA114_SOCTHERM_SENSOR_GPU 2
#define TEGRA114_SOCTHERM_SENSOR_PLLX 3
#define TEGRA114_SOCTHERM_THROT_LEVEL_NONE 0
#define TEGRA114_SOCTHERM_THROT_LEVEL_LOW 1
#define TEGRA114_SOCTHERM_THROT_LEVEL_MED 2
#define TEGRA114_SOCTHERM_THROT_LEVEL_HIGH 3
#endif