aboutsummaryrefslogtreecommitdiff
path: root/drivers/thermal
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig96
-rw-r--r--drivers/thermal/Makefile10
-rw-r--r--drivers/thermal/armada_thermal.c280
-rw-r--r--drivers/thermal/broadcom/bcm2835_thermal.c11
-rw-r--r--drivers/thermal/broadcom/brcmstb_thermal.c24
-rw-r--r--drivers/thermal/imx_thermal.c52
-rw-r--r--drivers/thermal/intel/Kconfig77
-rw-r--r--drivers/thermal/intel/Makefile12
-rw-r--r--drivers/thermal/intel/int340x_thermal/Kconfig (renamed from drivers/thermal/int340x_thermal/Kconfig)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/Makefile (renamed from drivers/thermal/int340x_thermal/Makefile)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c (renamed from drivers/thermal/int340x_thermal/acpi_thermal_rel.c)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h (renamed from drivers/thermal/int340x_thermal/acpi_thermal_rel.h)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3400_thermal.c (renamed from drivers/thermal/int340x_thermal/int3400_thermal.c)9
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3402_thermal.c (renamed from drivers/thermal/int340x_thermal/int3402_thermal.c)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3403_thermal.c (renamed from drivers/thermal/int340x_thermal/int3403_thermal.c)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3406_thermal.c (renamed from drivers/thermal/int340x_thermal/int3406_thermal.c)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c (renamed from drivers/thermal/int340x_thermal/int340x_thermal_zone.c)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h (renamed from drivers/thermal/int340x_thermal/int340x_thermal_zone.h)0
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.c (renamed from drivers/thermal/int340x_thermal/processor_thermal_device.c)0
-rw-r--r--drivers/thermal/intel/intel_bxt_pmic_thermal.c (renamed from drivers/thermal/intel_bxt_pmic_thermal.c)0
-rw-r--r--drivers/thermal/intel/intel_pch_thermal.c (renamed from drivers/thermal/intel_pch_thermal.c)0
-rw-r--r--drivers/thermal/intel/intel_powerclamp.c (renamed from drivers/thermal/intel_powerclamp.c)14
-rw-r--r--drivers/thermal/intel/intel_quark_dts_thermal.c (renamed from drivers/thermal/intel_quark_dts_thermal.c)0
-rw-r--r--drivers/thermal/intel/intel_soc_dts_iosf.c (renamed from drivers/thermal/intel_soc_dts_iosf.c)0
-rw-r--r--drivers/thermal/intel/intel_soc_dts_iosf.h (renamed from drivers/thermal/intel_soc_dts_iosf.h)0
-rw-r--r--drivers/thermal/intel/intel_soc_dts_thermal.c (renamed from drivers/thermal/intel_soc_dts_thermal.c)0
-rw-r--r--drivers/thermal/intel/x86_pkg_temp_thermal.c (renamed from drivers/thermal/x86_pkg_temp_thermal.c)0
-rw-r--r--drivers/thermal/qcom/Kconfig11
-rw-r--r--drivers/thermal/qcom/Makefile1
-rw-r--r--drivers/thermal/qcom/qcom-spmi-temp-alarm.c (renamed from drivers/thermal/qcom-spmi-temp-alarm.c)2
-rw-r--r--drivers/thermal/qcom/tsens-common.c12
-rw-r--r--drivers/thermal/rcar_thermal.c8
-rw-r--r--drivers/thermal/rockchip_thermal.c8
-rw-r--r--drivers/thermal/spear_thermal.c8
-rw-r--r--drivers/thermal/st/Makefile2
-rw-r--r--drivers/thermal/st/st_thermal.c6
-rw-r--r--drivers/thermal/tegra/soctherm.c12
-rw-r--r--drivers/thermal/thermal-generic-adc.c12
-rw-r--r--drivers/thermal/thermal_core.c18
-rw-r--r--drivers/thermal/thermal_hwmon.h4
-rw-r--r--drivers/thermal/thermal_sysfs.c11
-rw-r--r--drivers/thermal/uniphier_thermal.c13
-rw-r--r--drivers/thermal/zx2967_thermal.c6
43 files changed, 495 insertions, 224 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5422523c03f8..30323426902e 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -212,7 +212,7 @@ config HISI_THERMAL
config IMX_THERMAL
tristate "Temperature sensor driver for Freescale i.MX SoCs"
- depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
+ depends on ARCH_MXC || COMPILE_TEST
depends on NVMEM || !NVMEM
depends on MFD_SYSCON
depends on OF
@@ -326,84 +326,6 @@ config DA9062_THERMAL
zone.
Compatible with the DA9062 and DA9061 PMICs.
-config INTEL_POWERCLAMP
- tristate "Intel PowerClamp idle injection driver"
- depends on THERMAL
- depends on X86
- depends on CPU_SUP_INTEL
- help
- Enable this to enable Intel PowerClamp idle injection driver. This
- enforce idle time which results in more package C-state residency. The
- user interface is exposed via generic thermal framework.
-
-config X86_PKG_TEMP_THERMAL
- tristate "X86 package temperature thermal driver"
- depends on X86_THERMAL_VECTOR
- select THERMAL_GOV_USER_SPACE
- select THERMAL_WRITABLE_TRIPS
- default m
- help
- Enable this to register CPU digital sensor for package temperature as
- thermal zone. Each package will have its own thermal zone. There are
- two trip points which can be set by user to get notifications via thermal
- notification methods.
-
-config INTEL_SOC_DTS_IOSF_CORE
- tristate
- depends on X86 && PCI
- select IOSF_MBI
- help
- This is becoming a common feature for Intel SoCs to expose the additional
- digital temperature sensors (DTSs) using side band interface (IOSF). This
- implements the common set of helper functions to register, get temperature
- and get/set thresholds on DTSs.
-
-config INTEL_SOC_DTS_THERMAL
- tristate "Intel SoCs DTS thermal driver"
- depends on X86 && PCI && ACPI
- select INTEL_SOC_DTS_IOSF_CORE
- select THERMAL_WRITABLE_TRIPS
- help
- Enable this to register Intel SoCs (e.g. Bay Trail) platform digital
- temperature sensor (DTS). These SoCs have two additional DTSs in
- addition to DTSs on CPU cores. Each DTS will be registered as a
- thermal zone. There are two trip points. One of the trip point can
- be set by user mode programs to get notifications via Linux thermal
- notification methods.The other trip is a critical trip point, which
- was set by the driver based on the TJ MAX temperature.
-
-config INTEL_QUARK_DTS_THERMAL
- tristate "Intel Quark DTS thermal driver"
- depends on X86_INTEL_QUARK
- help
- Enable this to register Intel Quark SoC (e.g. X1000) platform digital
- temperature sensor (DTS). For X1000 SoC, it has one on-die DTS.
- The DTS will be registered as a thermal zone. There are two trip points:
- hot & critical. The critical trip point default value is set by
- underlying BIOS/Firmware.
-
-menu "ACPI INT340X thermal drivers"
-source drivers/thermal/int340x_thermal/Kconfig
-endmenu
-
-config INTEL_BXT_PMIC_THERMAL
- tristate "Intel Broxton PMIC thermal driver"
- depends on X86 && INTEL_SOC_PMIC_BXTWC && REGMAP
- help
- Select this driver for Intel Broxton PMIC with ADC channels monitoring
- system temperature measurements and alerts.
- This driver is used for monitoring the ADC channels of PMIC and handles
- the alert trip point interrupts and notifies the thermal framework with
- the trip point and temperature details of the zone.
-
-config INTEL_PCH_THERMAL
- tristate "Intel PCH Thermal Reporting Driver"
- depends on X86 && PCI
- help
- Enable this to support thermal reporting on certain intel PCHs.
- Thermal reporting device will provide temperature reading,
- programmable trip points and other information.
-
config MTK_THERMAL
tristate "Temperature sensor driver for mediatek SoCs"
depends on ARCH_MEDIATEK || COMPILE_TEST
@@ -415,6 +337,11 @@ config MTK_THERMAL
Enable this option if you want to have support for thermal management
controller present in Mediatek SoCs
+menu "Intel thermal drivers"
+depends on X86 || X86_INTEL_QUARK || COMPILE_TEST
+source "drivers/thermal/intel/Kconfig"
+endmenu
+
menu "Broadcom thermal drivers"
depends on ARCH_BCM || ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
source "drivers/thermal/broadcom/Kconfig"
@@ -447,17 +374,6 @@ config TANGO_THERMAL
source "drivers/thermal/tegra/Kconfig"
-config QCOM_SPMI_TEMP_ALARM
- tristate "Qualcomm SPMI PMIC Temperature Alarm"
- depends on OF && SPMI && IIO
- select REGMAP_SPMI
- help
- This enables a thermal sysfs driver for Qualcomm plug-and-play (QPNP)
- PMIC devices. It shows up in sysfs as a thermal sensor with multiple
- trip points. The temperature reported by the thermal sensor reflects the
- real time die temperature if an ADC is present or an estimate of the
- temperature based upon the over temperature stage value.
-
config GENERIC_ADC_THERMAL
tristate "Generic ADC based thermal sensor"
depends on IIO
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 82bb50dc6423..486d682be047 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -29,7 +29,6 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
# platform thermal drivers
obj-y += broadcom/
-obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
@@ -44,15 +43,8 @@ obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
-obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
-obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
-obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
-obj-$(CONFIG_INTEL_SOC_DTS_THERMAL) += intel_soc_dts_thermal.o
-obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL) += intel_quark_dts_thermal.o
+obj-y += intel/
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
-obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
-obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
-obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-y += st/
obj-$(CONFIG_QCOM_TSENS) += qcom/
obj-y += tegra/
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index d7105d01859a..53129de59dd9 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -26,6 +26,11 @@
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
+#include <linux/interrupt.h>
+
+#include "thermal_core.h"
+
+#define TO_MCELSIUS(c) ((c) * 1000)
/* Thermal Manager Control and Status Register */
#define PMU_TDC0_SW_RST_MASK (0x1 << 1)
@@ -61,9 +66,13 @@
#define CONTROL1_TSEN_AVG_MASK 0x7
#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
+#define CONTROL1_TSEN_INT_EN BIT(25)
+#define CONTROL1_TSEN_SELECT_OFF 21
+#define CONTROL1_TSEN_SELECT_MASK 0x3
#define STATUS_POLL_PERIOD_US 1000
#define STATUS_POLL_TIMEOUT_US 100000
+#define OVERHEAT_INT_POLL_DELAY_MS 1000
struct armada_thermal_data;
@@ -75,7 +84,11 @@ struct armada_thermal_priv {
/* serialize temperature reads/updates */
struct mutex update_lock;
struct armada_thermal_data *data;
+ struct thermal_zone_device *overheat_sensor;
+ int interrupt_source;
int current_channel;
+ long current_threshold;
+ long current_hysteresis;
};
struct armada_thermal_data {
@@ -93,12 +106,20 @@ struct armada_thermal_data {
/* Register shift and mask to access the sensor temperature */
unsigned int temp_shift;
unsigned int temp_mask;
+ unsigned int thresh_shift;
+ unsigned int hyst_shift;
+ unsigned int hyst_mask;
u32 is_valid_bit;
/* Syscon access */
unsigned int syscon_control0_off;
unsigned int syscon_control1_off;
unsigned int syscon_status_off;
+ unsigned int dfx_irq_cause_off;
+ unsigned int dfx_irq_mask_off;
+ unsigned int dfx_overheat_irq;
+ unsigned int dfx_server_irq_mask_off;
+ unsigned int dfx_server_irq_en;
/* One sensor is in the thermal IC, the others are in the CPUs if any */
unsigned int cpu_nr;
@@ -272,6 +293,41 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
return reg & priv->data->is_valid_bit;
}
+static void armada_enable_overheat_interrupt(struct armada_thermal_priv *priv)
+{
+ struct armada_thermal_data *data = priv->data;
+ u32 reg;
+
+ /* Clear DFX temperature IRQ cause */
+ regmap_read(priv->syscon, data->dfx_irq_cause_off, &reg);
+
+ /* Enable DFX Temperature IRQ */
+ regmap_read(priv->syscon, data->dfx_irq_mask_off, &reg);
+ reg |= data->dfx_overheat_irq;
+ regmap_write(priv->syscon, data->dfx_irq_mask_off, reg);
+
+ /* Enable DFX server IRQ */
+ regmap_read(priv->syscon, data->dfx_server_irq_mask_off, &reg);
+ reg |= data->dfx_server_irq_en;
+ regmap_write(priv->syscon, data->dfx_server_irq_mask_off, reg);
+
+ /* Enable overheat interrupt */
+ regmap_read(priv->syscon, data->syscon_control1_off, &reg);
+ reg |= CONTROL1_TSEN_INT_EN;
+ regmap_write(priv->syscon, data->syscon_control1_off, reg);
+}
+
+static void __maybe_unused
+armada_disable_overheat_interrupt(struct armada_thermal_priv *priv)
+{
+ struct armada_thermal_data *data = priv->data;
+ u32 reg;
+
+ regmap_read(priv->syscon, data->syscon_control1_off, &reg);
+ reg &= ~CONTROL1_TSEN_INT_EN;
+ regmap_write(priv->syscon, data->syscon_control1_off, reg);
+}
+
/* There is currently no board with more than one sensor per channel */
static int armada_select_channel(struct armada_thermal_priv *priv, int channel)
{
@@ -388,6 +444,14 @@ static int armada_get_temp(void *_sensor, int *temp)
/* Do the actual reading */
ret = armada_read_sensor(priv, temp);
+ if (ret)
+ goto unlock_mutex;
+
+ /*
+ * Select back the interrupt source channel from which a potential
+ * critical trip point has been set.
+ */
+ ret = armada_select_channel(priv, priv->interrupt_source);
unlock_mutex:
mutex_unlock(&priv->update_lock);
@@ -399,6 +463,123 @@ static const struct thermal_zone_of_device_ops of_ops = {
.get_temp = armada_get_temp,
};
+static unsigned int armada_mc_to_reg_temp(struct armada_thermal_data *data,
+ unsigned int temp_mc)
+{
+ s64 b = data->coef_b;
+ s64 m = data->coef_m;
+ s64 div = data->coef_div;
+ unsigned int sample;
+
+ if (data->inverted)
+ sample = div_s64(((temp_mc * div) + b), m);
+ else
+ sample = div_s64((b - (temp_mc * div)), m);
+
+ return sample & data->temp_mask;
+}
+
+/*
+ * The documentation states:
+ * high/low watermark = threshold +/- 0.4761 * 2^(hysteresis + 2)
+ * which is the mathematical derivation for:
+ * 0x0 <=> 1.9°C, 0x1 <=> 3.8°C, 0x2 <=> 7.6°C, 0x3 <=> 15.2°C
+ */
+static unsigned int hyst_levels_mc[] = {1900, 3800, 7600, 15200};
+
+static unsigned int armada_mc_to_reg_hyst(struct armada_thermal_data *data,
+ unsigned int hyst_mc)
+{
+ int i;
+
+ /*
+ * We will always take the smallest possible hysteresis to avoid risking
+ * the hardware integrity by enlarging the threshold by +8°C in the
+ * worst case.
+ */
+ for (i = ARRAY_SIZE(hyst_levels_mc) - 1; i > 0; i--)
+ if (hyst_mc >= hyst_levels_mc[i])
+ break;
+
+ return i & data->hyst_mask;
+}
+
+static void armada_set_overheat_thresholds(struct armada_thermal_priv *priv,
+ int thresh_mc, int hyst_mc)
+{
+ struct armada_thermal_data *data = priv->data;
+ unsigned int threshold = armada_mc_to_reg_temp(data, thresh_mc);
+ unsigned int hysteresis = armada_mc_to_reg_hyst(data, hyst_mc);
+ u32 ctrl1;
+
+ regmap_read(priv->syscon, data->syscon_control1_off, &ctrl1);
+
+ /* Set Threshold */
+ if (thresh_mc >= 0) {
+ ctrl1 &= ~(data->temp_mask << data->thresh_shift);
+ ctrl1 |= threshold << data->thresh_shift;
+ priv->current_threshold = thresh_mc;
+ }
+
+ /* Set Hysteresis */
+ if (hyst_mc >= 0) {
+ ctrl1 &= ~(data->hyst_mask << data->hyst_shift);
+ ctrl1 |= hysteresis << data->hyst_shift;
+ priv->current_hysteresis = hyst_mc;
+ }
+
+ regmap_write(priv->syscon, data->syscon_control1_off, ctrl1);
+}
+
+static irqreturn_t armada_overheat_isr(int irq, void *blob)
+{
+ /*
+ * Disable the IRQ and continue in thread context (thermal core
+ * notification and temperature monitoring).
+ */
+ disable_irq_nosync(irq);
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t armada_overheat_isr_thread(int irq, void *blob)
+{
+ struct armada_thermal_priv *priv = blob;
+ int low_threshold = priv->current_threshold - priv->current_hysteresis;
+ int temperature;
+ u32 dummy;
+ int ret;
+
+ /* Notify the core in thread context */
+ thermal_zone_device_update(priv->overheat_sensor,
+ THERMAL_EVENT_UNSPECIFIED);
+
+ /*
+ * The overheat interrupt must be cleared by reading the DFX interrupt
+ * cause _after_ the temperature has fallen down to the low threshold.
+ * Otherwise future interrupts might not be served.
+ */
+ do {
+ msleep(OVERHEAT_INT_POLL_DELAY_MS);
+ mutex_lock(&priv->update_lock);
+ ret = armada_read_sensor(priv, &temperature);
+ mutex_unlock(&priv->update_lock);
+ if (ret)
+ goto enable_irq;
+ } while (temperature >= low_threshold);
+
+ regmap_read(priv->syscon, priv->data->dfx_irq_cause_off, &dummy);
+
+ /* Notify the thermal core that the temperature is acceptable again */
+ thermal_zone_device_update(priv->overheat_sensor,
+ THERMAL_EVENT_UNSPECIFIED);
+
+enable_irq:
+ enable_irq(irq);
+
+ return IRQ_HANDLED;
+}
+
static const struct armada_thermal_data armadaxp_data = {
.init = armadaxp_init,
.temp_shift = 10,
@@ -454,6 +635,9 @@ static const struct armada_thermal_data armada_ap806_data = {
.is_valid_bit = BIT(16),
.temp_shift = 0,
.temp_mask = 0x3ff,
+ .thresh_shift = 3,
+ .hyst_shift = 19,
+ .hyst_mask = 0x3,
.coef_b = -150000LL,
.coef_m = 423ULL,
.coef_div = 1,
@@ -462,6 +646,11 @@ static const struct armada_thermal_data armada_ap806_data = {
.syscon_control0_off = 0x84,
.syscon_control1_off = 0x88,
.syscon_status_off = 0x8C,
+ .dfx_irq_cause_off = 0x108,
+ .dfx_irq_mask_off = 0x10C,
+ .dfx_overheat_irq = BIT(22),
+ .dfx_server_irq_mask_off = 0x104,
+ .dfx_server_irq_en = BIT(1),
.cpu_nr = 4,
};
@@ -470,6 +659,9 @@ static const struct armada_thermal_data armada_cp110_data = {
.is_valid_bit = BIT(10),
.temp_shift = 0,
.temp_mask = 0x3ff,
+ .thresh_shift = 16,
+ .hyst_shift = 26,
+ .hyst_mask = 0x3,
.coef_b = 1172499100ULL,
.coef_m = 2000096ULL,
.coef_div = 4201,
@@ -477,6 +669,11 @@ static const struct armada_thermal_data armada_cp110_data = {
.syscon_control0_off = 0x70,
.syscon_control1_off = 0x74,
.syscon_status_off = 0x78,
+ .dfx_irq_cause_off = 0x108,
+ .dfx_irq_mask_off = 0x10C,
+ .dfx_overheat_irq = BIT(20),
+ .dfx_server_irq_mask_off = 0x104,
+ .dfx_server_irq_en = BIT(1),
};
static const struct of_device_id armada_thermal_id_table[] = {
@@ -543,20 +740,14 @@ static int armada_thermal_probe_legacy(struct platform_device *pdev,
priv->syscon = devm_regmap_init_mmio(&pdev->dev, base,
&armada_thermal_regmap_config);
- if (IS_ERR(priv->syscon))
- return PTR_ERR(priv->syscon);
-
- return 0;
+ return PTR_ERR_OR_ZERO(priv->syscon);
}
static int armada_thermal_probe_syscon(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node);
- if (IS_ERR(priv->syscon))
- return PTR_ERR(priv->syscon);
-
- return 0;
+ return PTR_ERR_OR_ZERO(priv->syscon);
}
static void armada_set_sane_name(struct platform_device *pdev,
@@ -590,6 +781,48 @@ static void armada_set_sane_name(struct platform_device *pdev,
} while (insane_char);
}
+/*
+ * The IP can manage to trigger interrupts on overheat situation from all the
+ * sensors. However, the interrupt source changes along with the last selected
+ * source (ie. the last read sensor), which is an inconsistent behavior. Avoid
+ * possible glitches by always selecting back only one channel (arbitrarily: the
+ * first in the DT which has a critical trip point). We also disable sensor
+ * switch during overheat situations.
+ */
+static int armada_configure_overheat_int(struct armada_thermal_priv *priv,
+ struct thermal_zone_device *tz,
+ int sensor_id)
+{
+ /* Retrieve the critical trip point to enable the overheat interrupt */
+ const struct thermal_trip *trips = of_thermal_get_trip_points(tz);
+ int ret;
+ int i;
+
+ if (!trips)
+ return -EINVAL;
+
+ for (i = 0; i < of_thermal_get_ntrips(tz); i++)
+ if (trips[i].type == THERMAL_TRIP_CRITICAL)
+ break;
+
+ if (i == of_thermal_get_ntrips(tz))
+ return -EINVAL;
+
+ ret = armada_select_channel(priv, sensor_id);
+ if (ret)
+ return ret;
+
+ armada_set_overheat_thresholds(priv,
+ trips[i].temperature,
+ trips[i].hysteresis);
+ priv->overheat_sensor = tz;
+ priv->interrupt_source = sensor_id;
+
+ armada_enable_overheat_interrupt(priv);
+
+ return 0;
+}
+
static int armada_thermal_probe(struct platform_device *pdev)
{
struct thermal_zone_device *tz;
@@ -597,7 +830,7 @@ static int armada_thermal_probe(struct platform_device *pdev)
struct armada_drvdata *drvdata;
const struct of_device_id *match;
struct armada_thermal_priv *priv;
- int sensor_id;
+ int sensor_id, irq;
int ret;
match = of_match_device(armada_thermal_id_table, &pdev->dev);
@@ -667,6 +900,23 @@ static int armada_thermal_probe(struct platform_device *pdev)
drvdata->data.priv = priv;
platform_set_drvdata(pdev, drvdata);
+ irq = platform_get_irq(pdev, 0);
+ if (irq == -EPROBE_DEFER)
+ return irq;
+
+ /* The overheat interrupt feature is not mandatory */
+ if (irq > 0) {
+ ret = devm_request_threaded_irq(&pdev->dev, irq,
+ armada_overheat_isr,
+ armada_overheat_isr_thread,
+ 0, NULL, priv);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request threaded IRQ %d\n",
+ irq);
+ return ret;
+ }
+ }
+
/*
* There is one channel for the IC and one per CPU (if any), each
* channel has one sensor.
@@ -690,8 +940,20 @@ static int armada_thermal_probe(struct platform_device *pdev)
devm_kfree(&pdev->dev, sensor);
continue;
}
+
+ /*
+ * The first channel that has a critical trip point registered
+ * in the DT will serve as interrupt source. Others possible
+ * critical trip points will simply be ignored by the driver.
+ */
+ if (irq > 0 && !priv->overheat_sensor)
+ armada_configure_overheat_int(priv, tz, sensor->id);
}
+ /* Just complain if no overheat interrupt was set up */
+ if (!priv->overheat_sensor)
+ dev_warn(&pdev->dev, "Overheat interrupt not available\n");
+
return 0;
}
diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
index b9d90f0ed504..720760cd493f 100644
--- a/drivers/thermal/broadcom/bcm2835_thermal.c
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
@@ -18,6 +18,8 @@
#include <linux/platform_device.h>
#include <linux/thermal.h>
+#include "../thermal_hwmon.h"
+
#define BCM2835_TS_TSENSCTL 0x00
#define BCM2835_TS_TSENSSTAT 0x04
@@ -266,6 +268,15 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tz);
+ /*
+ * Thermal_zone doesn't enable hwmon as default,
+ * enable it here
+ */
+ tz->tzp->no_hwmon = false;
+ err = thermal_add_hwmon_sysfs(tz);
+ if (err)
+ goto err_tz;
+
bcm2835_thermal_debugfs(pdev);
return 0;
diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c
index e8b1570cc388..65704bdd18e4 100644
--- a/drivers/thermal/broadcom/brcmstb_thermal.c
+++ b/drivers/thermal/broadcom/brcmstb_thermal.c
@@ -329,7 +329,8 @@ static int brcmstb_thermal_probe(struct platform_device *pdev)
priv->dev = &pdev->dev;
platform_set_drvdata(pdev, priv);
- thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &of_ops);
+ thermal = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, priv,
+ &of_ops);
if (IS_ERR(thermal)) {
ret = PTR_ERR(thermal);
dev_err(&pdev->dev, "could not register sensor: %d\n", ret);
@@ -341,40 +342,23 @@ static int brcmstb_thermal_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "could not get IRQ\n");
- ret = irq;
- goto err;
+ return irq;
}
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
brcmstb_tmon_irq_thread, IRQF_ONESHOT,
DRV_NAME, priv);
if (ret < 0) {
dev_err(&pdev->dev, "could not request IRQ: %d\n", ret);
- goto err;
+ return ret;
}
dev_info(&pdev->dev, "registered AVS TMON of-sensor driver\n");
return 0;
-
-err:
- thermal_zone_of_sensor_unregister(&pdev->dev, thermal);
- return ret;
-}
-
-static int brcmstb_thermal_exit(struct platform_device *pdev)
-{
- struct brcmstb_thermal_priv *priv = platform_get_drvdata(pdev);
- struct thermal_zone_device *thermal = priv->thermal;
-
- if (thermal)
- thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal);
-
- return 0;
}
static struct platform_driver brcmstb_thermal_driver = {
.probe = brcmstb_thermal_probe,
- .remove = brcmstb_thermal_exit,
.driver = {
.name = DRV_NAME,
.of_match_table = brcmstb_thermal_id_table,
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 15661549eb67..bb6754a5342c 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -648,15 +648,24 @@ static const struct of_device_id of_imx_thermal_match[] = {
};
MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
+#ifdef CONFIG_CPU_FREQ
/*
* Create cooling device in case no #cooling-cells property is available in
* CPU node
*/
static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
{
- struct device_node *np = of_get_cpu_node(data->policy->cpu, NULL);
+ struct device_node *np;
int ret;
+ data->policy = cpufreq_cpu_get(0);
+ if (!data->policy) {
+ pr_debug("%s: CPUFreq policy not found\n", __func__);
+ return -EPROBE_DEFER;
+ }
+
+ np = of_get_cpu_node(data->policy->cpu, NULL);
+
if (!np || !of_find_property(np, "#cooling-cells", NULL)) {
data->cdev = cpufreq_cooling_register(data->policy);
if (IS_ERR(data->cdev)) {
@@ -669,6 +678,24 @@ static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
return 0;
}
+static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
+{
+ cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cpu_put(data->policy);
+}
+
+#else
+
+static inline int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
+{
+ return 0;
+}
+
+static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
+{
+}
+#endif
+
static int imx_thermal_probe(struct platform_device *pdev)
{
struct imx_thermal_data *data;
@@ -715,9 +742,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) {
ret = imx_init_from_nvmem_cells(pdev);
- if (ret == -EPROBE_DEFER)
- return ret;
if (ret) {
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
dev_err(&pdev->dev, "failed to init from nvmem: %d\n",
ret);
return ret;
@@ -743,14 +771,11 @@ static int imx_thermal_probe(struct platform_device *pdev)
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
data->socdata->power_down_mask);
- data->policy = cpufreq_cpu_get(0);
- if (!data->policy) {
- pr_debug("%s: CPUFreq policy not found\n", __func__);
- return -EPROBE_DEFER;
- }
-
ret = imx_thermal_register_legacy_cooling(data);
if (ret) {
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
dev_err(&pdev->dev,
"failed to register cpufreq cooling device: %d\n", ret);
return ret;
@@ -762,7 +787,7 @@ static int imx_thermal_probe(struct platform_device *pdev)
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to get thermal clk: %d\n", ret);
- goto cpufreq_put;
+ goto legacy_cleanup;
}
/*
@@ -775,7 +800,7 @@ static int imx_thermal_probe(struct platform_device *pdev)
ret = clk_prepare_enable(data->thermal_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
- goto cpufreq_put;
+ goto legacy_cleanup;
}
data->tz = thermal_zone_device_register("imx_thermal_zone",
@@ -829,9 +854,8 @@ thermal_zone_unregister:
thermal_zone_device_unregister(data->tz);
clk_disable:
clk_disable_unprepare(data->thermal_clk);
-cpufreq_put:
- cpufreq_cooling_unregister(data->cdev);
- cpufreq_cpu_put(data->policy);
+legacy_cleanup:
+ imx_thermal_unregister_legacy_cooling(data);
return ret;
}
diff --git a/drivers/thermal/intel/Kconfig b/drivers/thermal/intel/Kconfig
new file mode 100644
index 000000000000..2e013eeb4a1d
--- /dev/null
+++ b/drivers/thermal/intel/Kconfig
@@ -0,0 +1,77 @@
+config INTEL_POWERCLAMP
+ tristate "Intel PowerClamp idle injection driver"
+ depends on THERMAL
+ depends on X86
+ depends on CPU_SUP_INTEL
+ help
+ Enable this to enable Intel PowerClamp idle injection driver. This
+ enforce idle time which results in more package C-state residency. The
+ user interface is exposed via generic thermal framework.
+
+config X86_PKG_TEMP_THERMAL
+ tristate "X86 package temperature thermal driver"
+ depends on X86_THERMAL_VECTOR
+ select THERMAL_GOV_USER_SPACE
+ select THERMAL_WRITABLE_TRIPS
+ default m
+ help
+ Enable this to register CPU digital sensor for package temperature as
+ thermal zone. Each package will have its own thermal zone. There are
+ two trip points which can be set by user to get notifications via thermal
+ notification methods.
+
+config INTEL_SOC_DTS_IOSF_CORE
+ tristate
+ depends on X86 && PCI
+ select IOSF_MBI
+ help
+ This is becoming a common feature for Intel SoCs to expose the additional
+ digital temperature sensors (DTSs) using side band interface (IOSF). This
+ implements the common set of helper functions to register, get temperature
+ and get/set thresholds on DTSs.
+
+config INTEL_SOC_DTS_THERMAL
+ tristate "Intel SoCs DTS thermal driver"
+ depends on X86 && PCI && ACPI
+ select INTEL_SOC_DTS_IOSF_CORE
+ select THERMAL_WRITABLE_TRIPS
+ help
+ Enable this to register Intel SoCs (e.g. Bay Trail) platform digital
+ temperature sensor (DTS). These SoCs have two additional DTSs in
+ addition to DTSs on CPU cores. Each DTS will be registered as a
+ thermal zone. There are two trip points. One of the trip point can
+ be set by user mode programs to get notifications via Linux thermal
+ notification methods.The other trip is a critical trip point, which
+ was set by the driver based on the TJ MAX temperature.
+
+config INTEL_QUARK_DTS_THERMAL
+ tristate "Intel Quark DTS thermal driver"
+ depends on X86_INTEL_QUARK
+ help
+ Enable this to register Intel Quark SoC (e.g. X1000) platform digital
+ temperature sensor (DTS). For X1000 SoC, it has one on-die DTS.
+ The DTS will be registered as a thermal zone. There are two trip points:
+ hot & critical. The critical trip point default value is set by
+ underlying BIOS/Firmware.
+
+menu "ACPI INT340X thermal drivers"
+source "drivers/thermal/intel/int340x_thermal/Kconfig"
+endmenu
+
+config INTEL_BXT_PMIC_THERMAL
+ tristate "Intel Broxton PMIC thermal driver"
+ depends on X86 && INTEL_SOC_PMIC_BXTWC && REGMAP
+ help
+ Select this driver for Intel Broxton PMIC with ADC channels monitoring
+ system temperature measurements and alerts.
+ This driver is used for monitoring the ADC channels of PMIC and handles
+ the alert trip point interrupts and notifies the thermal framework with
+ the trip point and temperature details of the zone.
+
+config INTEL_PCH_THERMAL
+ tristate "Intel PCH Thermal Reporting Driver"
+ depends on X86 && PCI
+ help
+ Enable this to support thermal reporting on certain intel PCHs.
+ Thermal reporting device will provide temperature reading,
+ programmable trip points and other information.
diff --git a/drivers/thermal/intel/Makefile b/drivers/thermal/intel/Makefile
new file mode 100644
index 000000000000..0d9736ced5d4
--- /dev/null
+++ b/drivers/thermal/intel/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for various Intel thermal drivers.
+
+obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
+obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
+obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
+obj-$(CONFIG_INTEL_SOC_DTS_THERMAL) += intel_soc_dts_thermal.o
+obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL) += intel_quark_dts_thermal.o
+obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
+obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
+obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
diff --git a/drivers/thermal/int340x_thermal/Kconfig b/drivers/thermal/intel/int340x_thermal/Kconfig
index 0582bd12a239..0582bd12a239 100644
--- a/drivers/thermal/int340x_thermal/Kconfig
+++ b/drivers/thermal/intel/int340x_thermal/Kconfig
diff --git a/drivers/thermal/int340x_thermal/Makefile b/drivers/thermal/intel/int340x_thermal/Makefile
index 287eb0a1476d..287eb0a1476d 100644
--- a/drivers/thermal/int340x_thermal/Makefile
+++ b/drivers/thermal/intel/int340x_thermal/Makefile
diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
index 45e7e5cbdffb..45e7e5cbdffb 100644
--- a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
+++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.h b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
index 58822575fd54..58822575fd54 100644
--- a/drivers/thermal/int340x_thermal/acpi_thermal_rel.h
+++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
index e26b01c05e82..61ca7ce3624e 100644
--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
@@ -48,8 +48,7 @@ static ssize_t available_uuids_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
+ struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
int i;
int length = 0;
@@ -68,8 +67,7 @@ static ssize_t available_uuids_show(struct device *dev,
static ssize_t current_uuid_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
+ struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
if (priv->uuid_bitmap & (1 << priv->current_uuid_index))
return sprintf(buf, "%s\n",
@@ -82,8 +80,7 @@ static ssize_t current_uuid_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
+ struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
int i;
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; ++i) {
diff --git a/drivers/thermal/int340x_thermal/int3402_thermal.c b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c
index 8e90b3151a42..8e90b3151a42 100644
--- a/drivers/thermal/int340x_thermal/int3402_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c
diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c
index 0c19fcd56a0d..0c19fcd56a0d 100644
--- a/drivers/thermal/int340x_thermal/int3403_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c
diff --git a/drivers/thermal/int340x_thermal/int3406_thermal.c b/drivers/thermal/intel/int340x_thermal/int3406_thermal.c
index f69ab026ba24..f69ab026ba24 100644
--- a/drivers/thermal/int340x_thermal/int3406_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3406_thermal.c
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
index 9ec27ac1856b..9ec27ac1856b 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h
index 5f3ba4775c5c..5f3ba4775c5c 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h
diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
index 284cf2c5a8fd..284cf2c5a8fd 100644
--- a/drivers/thermal/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
diff --git a/drivers/thermal/intel_bxt_pmic_thermal.c b/drivers/thermal/intel/intel_bxt_pmic_thermal.c
index 94cfd0064c43..94cfd0064c43 100644
--- a/drivers/thermal/intel_bxt_pmic_thermal.c
+++ b/drivers/thermal/intel/intel_bxt_pmic_thermal.c
diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel/intel_pch_thermal.c
index 8a7f69b4b022..8a7f69b4b022 100644
--- a/drivers/thermal/intel_pch_thermal.c
+++ b/drivers/thermal/intel/intel_pch_thermal.c
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel/intel_powerclamp.c
index cde891c54cde..7571f7c2e7c9 100644
--- a/drivers/thermal/intel_powerclamp.c
+++ b/drivers/thermal/intel/intel_powerclamp.c
@@ -708,19 +708,7 @@ static int powerclamp_debug_show(struct seq_file *m, void *unused)
return 0;
}
-static int powerclamp_debug_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, powerclamp_debug_show, inode->i_private);
-}
-
-static const struct file_operations powerclamp_debug_fops = {
- .open = powerclamp_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(powerclamp_debug);
static inline void powerclamp_create_debug_files(void)
{
diff --git a/drivers/thermal/intel_quark_dts_thermal.c b/drivers/thermal/intel/intel_quark_dts_thermal.c
index 5d33b350da1c..5d33b350da1c 100644
--- a/drivers/thermal/intel_quark_dts_thermal.c
+++ b/drivers/thermal/intel/intel_quark_dts_thermal.c
diff --git a/drivers/thermal/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c
index e0813dfaa278..e0813dfaa278 100644
--- a/drivers/thermal/intel_soc_dts_iosf.c
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.c
diff --git a/drivers/thermal/intel_soc_dts_iosf.h b/drivers/thermal/intel/intel_soc_dts_iosf.h
index 625e37bf93dc..625e37bf93dc 100644
--- a/drivers/thermal/intel_soc_dts_iosf.h
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.h
diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel/intel_soc_dts_thermal.c
index d748527d7a38..d748527d7a38 100644
--- a/drivers/thermal/intel_soc_dts_thermal.c
+++ b/drivers/thermal/intel/intel_soc_dts_thermal.c
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
index 1ef937d799e4..1ef937d799e4 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig
index be32e5abce3c..cdb455ffd575 100644
--- a/drivers/thermal/qcom/Kconfig
+++ b/drivers/thermal/qcom/Kconfig
@@ -9,3 +9,14 @@ config QCOM_TSENS
thermal zone device via the mode file results in disabling the sensor.
Also able to set threshold temperature for both hot and cold and update
when a threshold is reached.
+
+config QCOM_SPMI_TEMP_ALARM
+ tristate "Qualcomm SPMI PMIC Temperature Alarm"
+ depends on OF && SPMI && IIO
+ select REGMAP_SPMI
+ help
+ This enables a thermal sysfs driver for Qualcomm plug-and-play (QPNP)
+ PMIC devices. It shows up in sysfs as a thermal sensor with multiple
+ trip points. The temperature reported by the thermal sensor reflects the
+ real time die temperature if an ADC is present or an estimate of the
+ temperature based upon the over temperature stage value.
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index a821929ede0b..717a08600bb5 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o
+obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index b2d5d5bf4a9b..c1fd71dbab3e 100644
--- a/drivers/thermal/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -23,7 +23,7 @@
#include <linux/regmap.h>
#include <linux/thermal.h>
-#include "thermal_core.h"
+#include "../thermal_core.h"
#define QPNP_TM_REG_TYPE 0x04
#define QPNP_TM_REG_SUBTYPE 0x05
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index 3be4be2e0465..78652cac7f3d 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -114,6 +114,14 @@ int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
}
static const struct regmap_config tsens_config = {
+ .name = "tm",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static const struct regmap_config tsens_srot_config = {
+ .name = "srot",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
@@ -139,8 +147,8 @@ int __init init_common(struct tsens_device *tmdev)
if (IS_ERR(srot_base))
return PTR_ERR(srot_base);
- tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev,
- srot_base, &tsens_config);
+ tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base,
+ &tsens_srot_config);
if (IS_ERR(tmdev->srot_map))
return PTR_ERR(tmdev->srot_map);
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 8014a207d8d9..97462e9b40d8 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -113,10 +113,18 @@ static const struct of_device_id rcar_thermal_dt_ids[] = {
.data = &rcar_gen2_thermal,
},
{
+ .compatible = "renesas,thermal-r8a774c0",
+ .data = &rcar_gen3_thermal,
+ },
+ {
.compatible = "renesas,thermal-r8a77970",
.data = &rcar_gen3_thermal,
},
{
+ .compatible = "renesas,thermal-r8a77990",
+ .data = &rcar_gen3_thermal,
+ },
+ {
.compatible = "renesas,thermal-r8a77995",
.data = &rcar_gen3_thermal,
},
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index f36375d5a16c..9c7643d62ed7 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -1327,8 +1327,7 @@ static int rockchip_thermal_remove(struct platform_device *pdev)
static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
+ struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
int i;
for (i = 0; i < thermal->chip->chn_num; i++)
@@ -1346,8 +1345,7 @@ static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
static int __maybe_unused rockchip_thermal_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
+ struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
int i;
int error;
@@ -1376,7 +1374,7 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
id, thermal->regs,
thermal->tshut_temp);
if (error)
- dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
+ dev_err(dev, "%s: invalid tshut=%d, error=%d\n",
__func__, thermal->tshut_temp, error);
}
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 81b35aace9de..8b9d567134d0 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -56,8 +56,7 @@ static struct thermal_zone_device_ops ops = {
static int __maybe_unused spear_thermal_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
+ struct thermal_zone_device *spear_thermal = dev_get_drvdata(dev);
struct spear_thermal_dev *stdev = spear_thermal->devdata;
unsigned int actual_mask = 0;
@@ -73,15 +72,14 @@ static int __maybe_unused spear_thermal_suspend(struct device *dev)
static int __maybe_unused spear_thermal_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
+ struct thermal_zone_device *spear_thermal = dev_get_drvdata(dev);
struct spear_thermal_dev *stdev = spear_thermal->devdata;
unsigned int actual_mask = 0;
int ret = 0;
ret = clk_enable(stdev->clk);
if (ret) {
- dev_err(&pdev->dev, "Can't enable clock\n");
+ dev_err(dev, "Can't enable clock\n");
return ret;
}
diff --git a/drivers/thermal/st/Makefile b/drivers/thermal/st/Makefile
index b2b9e9b96296..243ca7881b12 100644
--- a/drivers/thermal/st/Makefile
+++ b/drivers/thermal/st/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_ST_THERMAL) := st_thermal.o
obj-$(CONFIG_ST_THERMAL_SYSCFG) += st_thermal_syscfg.o
obj-$(CONFIG_ST_THERMAL_MEMMAP) += st_thermal_memmap.o
-obj-$(CONFIG_STM32_THERMAL) := stm_thermal.o \ No newline at end of file
+obj-$(CONFIG_STM32_THERMAL) += stm_thermal.o
diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
index be637e6b01d2..b2bbdf6eb02b 100644
--- a/drivers/thermal/st/st_thermal.c
+++ b/drivers/thermal/st/st_thermal.c
@@ -277,8 +277,7 @@ EXPORT_SYMBOL_GPL(st_thermal_unregister);
#ifdef CONFIG_PM_SLEEP
static int st_thermal_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);
+ struct st_thermal_sensor *sensor = dev_get_drvdata(dev);
return st_thermal_sensor_off(sensor);
}
@@ -286,8 +285,7 @@ static int st_thermal_suspend(struct device *dev)
static int st_thermal_resume(struct device *dev)
{
int ret;
- struct platform_device *pdev = to_platform_device(dev);
- struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);
+ struct st_thermal_sensor *sensor = dev_get_drvdata(dev);
ret = st_thermal_sensor_on(sensor);
if (ret)
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c
index ed28110a3535..45b41b885f49 100644
--- a/drivers/thermal/tegra/soctherm.c
+++ b/drivers/thermal/tegra/soctherm.c
@@ -803,17 +803,7 @@ static int regs_show(struct seq_file *s, void *data)
return 0;
}
-static int regs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, regs_show, inode->i_private);
-}
-
-static const struct file_operations regs_fops = {
- .open = regs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(regs);
static void soctherm_debug_init(struct platform_device *pdev)
{
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c
index bf1c628d4a7a..e22fc60ad36d 100644
--- a/drivers/thermal/thermal-generic-adc.c
+++ b/drivers/thermal/thermal-generic-adc.c
@@ -26,7 +26,7 @@ struct gadc_thermal_info {
static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
{
- int temp, adc_hi, adc_lo;
+ int temp, temp_hi, temp_lo, adc_hi, adc_lo;
int i;
for (i = 0; i < gti->nlookup_table; i++) {
@@ -36,13 +36,17 @@ static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
if (i == 0) {
temp = gti->lookup_table[0];
- } else if (i >= (gti->nlookup_table - 1)) {
+ } else if (i >= gti->nlookup_table) {
temp = gti->lookup_table[2 * (gti->nlookup_table - 1)];
} else {
adc_hi = gti->lookup_table[2 * i - 1];
adc_lo = gti->lookup_table[2 * i + 1];
- temp = gti->lookup_table[2 * i];
- temp -= ((val - adc_lo) * 1000) / (adc_hi - adc_lo);
+
+ temp_hi = gti->lookup_table[2 * i - 2];
+ temp_lo = gti->lookup_table[2 * i];
+
+ temp = temp_hi + mult_frac(temp_lo - temp_hi, val - adc_hi,
+ adc_lo - adc_hi);
}
return temp;
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d6ebc1cf6aa9..6590bb5cb688 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -315,9 +315,7 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
mutex_unlock(&tz->lock);
}
-static void handle_non_critical_trips(struct thermal_zone_device *tz,
- int trip,
- enum thermal_trip_type trip_type)
+static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip)
{
tz->governor ? tz->governor->throttle(tz, trip) :
def_governor->throttle(tz, trip);
@@ -418,7 +416,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
handle_critical_trips(tz, trip, type);
else
- handle_non_critical_trips(tz, trip, type);
+ handle_non_critical_trips(tz, trip);
/*
* Alright, we handled this trip successfully.
* So, start monitoring again.
@@ -453,16 +451,20 @@ static void update_temperature(struct thermal_zone_device *tz)
tz->last_temperature, tz->temperature);
}
-static void thermal_zone_device_reset(struct thermal_zone_device *tz)
+static void thermal_zone_device_init(struct thermal_zone_device *tz)
{
struct thermal_instance *pos;
-
tz->temperature = THERMAL_TEMP_INVALID;
- tz->passive = 0;
list_for_each_entry(pos, &tz->thermal_instances, tz_node)
pos->initialized = false;
}
+static void thermal_zone_device_reset(struct thermal_zone_device *tz)
+{
+ tz->passive = 0;
+ thermal_zone_device_init(tz);
+}
+
void thermal_zone_device_update(struct thermal_zone_device *tz,
enum thermal_notify_event event)
{
@@ -1504,7 +1506,7 @@ static int thermal_pm_notify(struct notifier_block *nb,
case PM_POST_SUSPEND:
atomic_set(&in_suspend, 0);
list_for_each_entry(tz, &thermal_tz_list, node) {
- thermal_zone_device_reset(tz);
+ thermal_zone_device_init(tz);
thermal_zone_device_update(tz,
THERMAL_EVENT_UNSPECIFIED);
}
diff --git a/drivers/thermal/thermal_hwmon.h b/drivers/thermal/thermal_hwmon.h
index 019f6f88224e..a160b9d62dd0 100644
--- a/drivers/thermal/thermal_hwmon.h
+++ b/drivers/thermal/thermal_hwmon.h
@@ -19,13 +19,13 @@
int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz);
void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz);
#else
-static int
+static inline int
thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
{
return 0;
}
-static void
+static inline void
thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
{
}
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 2241ceae7d7f..aa99edb4dff7 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -712,11 +712,14 @@ cur_state_store(struct device *dev, struct device_attribute *attr,
if ((long)state < 0)
return -EINVAL;
+ mutex_lock(&cdev->lock);
+
result = cdev->ops->set_cur_state(cdev, state);
- if (result)
- return result;
- thermal_cooling_device_stats_update(cdev, state);
- return count;
+ if (!result)
+ thermal_cooling_device_stats_update(cdev, state);
+
+ mutex_unlock(&cdev->lock);
+ return result ? result : count;
}
static struct device_attribute
diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c
index 55477d74d591..bba2284412d3 100644
--- a/drivers/thermal/uniphier_thermal.c
+++ b/drivers/thermal/uniphier_thermal.c
@@ -1,21 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/**
* uniphier_thermal.c - Socionext UniPhier thermal driver
- *
* Copyright 2014 Panasonic Corporation
* Copyright 2016-2017 Socionext Inc.
- * All rights reserved.
- *
* Author:
* Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 of
- * the License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/bitops.h>
diff --git a/drivers/thermal/zx2967_thermal.c b/drivers/thermal/zx2967_thermal.c
index 6acce0bce7c0..145ebf371598 100644
--- a/drivers/thermal/zx2967_thermal.c
+++ b/drivers/thermal/zx2967_thermal.c
@@ -207,8 +207,7 @@ MODULE_DEVICE_TABLE(of, zx2967_thermal_id_table);
#ifdef CONFIG_PM_SLEEP
static int zx2967_thermal_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
+ struct zx2967_thermal_priv *priv = dev_get_drvdata(dev);
if (priv && priv->clk_topcrm)
clk_disable_unprepare(priv->clk_topcrm);
@@ -221,8 +220,7 @@ static int zx2967_thermal_suspend(struct device *dev)
static int zx2967_thermal_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
+ struct zx2967_thermal_priv *priv = dev_get_drvdata(dev);
int error;
error = clk_prepare_enable(priv->clk_topcrm);