summaryrefslogtreecommitdiff
path: root/drivers/thermal
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-16 07:56:57 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-16 07:56:57 -0700
commita455eda33faafcaac1effb31d682765b14ef868c (patch)
tree9a4ca7da47300ca9081445539ff337efcead4b6b /drivers/thermal
parentcc7ce90153e74f8266eefee9fba466faa1a2d5df (diff)
parent37bcec5d9f71bd13142a97d2196b293c9ac23823 (diff)
downloadlinux-a455eda33faafcaac1effb31d682765b14ef868c.tar.gz
linux-a455eda33faafcaac1effb31d682765b14ef868c.tar.bz2
linux-a455eda33faafcaac1effb31d682765b14ef868c.zip
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal
Pull thermal soc updates from Eduardo Valentin: - thermal core has a new devm_* API for registering cooling devices. I took the entire series, that is why you see changes on drivers/hwmon in this pull (Guenter Roeck) - rockchip thermal driver gains support to PX30 SoC (Elaine Zhang) - the generic-adc thermal driver now considers the lookup table DT property as optional (Jean-Francois Dagenais) - Refactoring of tsens thermal driver (Amit Kucheria) - Cleanups on cpu cooling driver (Daniel Lezcano) - broadcom thermal driver dropped support to ACPI (Srinath Mannam) - tegra thermal driver gains support to OC hw throttle and GPU throtle (Wei Ni) - Fixes in several thermal drivers. * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: (59 commits) hwmon: (pwm-fan) Use devm_thermal_of_cooling_device_register hwmon: (npcm750-pwm-fan) Use devm_thermal_of_cooling_device_register hwmon: (mlxreg-fan) Use devm_thermal_of_cooling_device_register hwmon: (gpio-fan) Use devm_thermal_of_cooling_device_register hwmon: (aspeed-pwm-tacho) Use devm_thermal_of_cooling_device_register thermal: rcar_gen3_thermal: Fix to show correct trip points number thermal: rcar_thermal: update calculation formula for R-Car Gen3 SoCs thermal: cpu_cooling: Actually trace CPU load in thermal_power_cpu_get_power thermal: rockchip: Support the PX30 SoC in thermal driver dt-bindings: rockchip-thermal: Support the PX30 SoC compatible thermal: rockchip: fix up the tsadc pinctrl setting error thermal: broadcom: Remove ACPI support thermal: Fix build error of missing devm_ioremap_resource on UM thermal/drivers/cpu_cooling: Remove pointless field thermal/drivers/cpu_cooling: Add Software Package Data Exchange (SPDX) thermal/drivers/cpu_cooling: Fixup the header and copyright thermal/drivers/cpu_cooling: Remove pointless test in power2state() thermal: rcar_gen3_thermal: disable interrupt in .remove thermal: rcar_gen3_thermal: fix interrupt type thermal: Introduce devm_thermal_of_cooling_device_register ...
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig11
-rw-r--r--drivers/thermal/Makefile1
-rw-r--r--drivers/thermal/broadcom/sr-thermal.c8
-rw-r--r--drivers/thermal/cpu_cooling.c30
-rw-r--r--drivers/thermal/of-thermal.c3
-rw-r--r--drivers/thermal/qcom/Makefile4
-rw-r--r--drivers/thermal/qcom/tsens-8916.c105
-rw-r--r--drivers/thermal/qcom/tsens-8960.c84
-rw-r--r--drivers/thermal/qcom/tsens-common.c159
-rw-r--r--drivers/thermal/qcom/tsens-v0_1.c (renamed from drivers/thermal/qcom/tsens-8974.c)166
-rw-r--r--drivers/thermal/qcom/tsens-v1.c193
-rw-r--r--drivers/thermal/qcom/tsens-v2.c111
-rw-r--r--drivers/thermal/qcom/tsens.c100
-rw-r--r--drivers/thermal/qcom/tsens.h291
-rw-r--r--drivers/thermal/qoriq_thermal.c5
-rw-r--r--drivers/thermal/rcar_gen3_thermal.c51
-rw-r--r--drivers/thermal/rcar_thermal.c11
-rw-r--r--drivers/thermal/rockchip_thermal.c74
-rw-r--r--drivers/thermal/st/Kconfig22
-rw-r--r--drivers/thermal/st/stm_thermal.c6
-rw-r--r--drivers/thermal/tegra/Kconfig4
-rw-r--r--drivers/thermal/tegra/soctherm.c961
-rw-r--r--drivers/thermal/tegra/soctherm.h16
-rw-r--r--drivers/thermal/tegra/tegra124-soctherm.c7
-rw-r--r--drivers/thermal/tegra/tegra132-soctherm.c7
-rw-r--r--drivers/thermal/tegra/tegra210-soctherm.c15
-rw-r--r--drivers/thermal/thermal-generic-adc.c9
-rw-r--r--drivers/thermal/thermal_core.c49
-rw-r--r--drivers/thermal/thermal_mmio.c129
29 files changed, 2142 insertions, 490 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 653aa27a25a4..66a709d5d6b9 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -200,6 +200,17 @@ config THERMAL_EMULATION
because userland can easily disable the thermal policy by simply
flooding this sysfs node with low temperature values.
+config THERMAL_MMIO
+ tristate "Generic Thermal MMIO driver"
+ depends on OF || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ This option enables the generic thermal MMIO driver that will use
+ memory-mapped reads to get the temperature. Any HW/System that
+ allows temperature reading by a single memory-mapped reading, be it
+ register or shared memory, is a potential candidate to work with this
+ driver.
+
config HISI_THERMAL
tristate "Hisilicon thermal driver"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 486d682be047..74a37c7f847a 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -29,6 +29,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
# platform thermal drivers
obj-y += broadcom/
+obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
diff --git a/drivers/thermal/broadcom/sr-thermal.c b/drivers/thermal/broadcom/sr-thermal.c
index 2284cbecedf3..475ce2900771 100644
--- a/drivers/thermal/broadcom/sr-thermal.c
+++ b/drivers/thermal/broadcom/sr-thermal.c
@@ -3,7 +3,6 @@
* Copyright (C) 2018 Broadcom
*/
-#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@@ -100,18 +99,11 @@ static const struct of_device_id sr_thermal_of_match[] = {
};
MODULE_DEVICE_TABLE(of, sr_thermal_of_match);
-static const struct acpi_device_id sr_thermal_acpi_ids[] = {
- { .id = "BRCM0500" },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(acpi, sr_thermal_acpi_ids);
-
static struct platform_driver sr_thermal_driver = {
.probe = sr_thermal_probe,
.driver = {
.name = "sr-thermal",
.of_match_table = sr_thermal_of_match,
- .acpi_match_table = ACPI_PTR(sr_thermal_acpi_ids),
},
};
module_platform_driver(sr_thermal_driver);
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index f7c1f49ec87f..4c5db59a619b 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -1,26 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* linux/drivers/thermal/cpu_cooling.c
*
* Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
- * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org>
*
- * Copyright (C) 2014 Viresh Kumar <viresh.kumar@linaro.org>
+ * Copyright (C) 2012-2018 Linaro Limited.
*
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * Authors: Amit Daniel <amit.kachhap@linaro.org>
+ * Viresh Kumar <viresh.kumar@linaro.org>
*
- * 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/module.h>
#include <linux/thermal.h>
@@ -99,7 +87,6 @@ struct cpufreq_cooling_device {
unsigned int clipped_freq;
unsigned int max_level;
struct freq_table *freq_table; /* In descending order */
- struct thermal_cooling_device *cdev;
struct cpufreq_policy *policy;
struct list_head node;
struct time_in_idle *idle_time;
@@ -207,8 +194,7 @@ static int update_freq_table(struct cpufreq_cooling_device *cpufreq_cdev,
dev = get_cpu_device(cpu);
if (unlikely(!dev)) {
- dev_warn(&cpufreq_cdev->cdev->device,
- "No cpu device for cpu %d\n", cpu);
+ pr_warn("No cpu device for cpu %d\n", cpu);
return -ENODEV;
}
@@ -458,7 +444,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
load = 0;
total_load += load;
- if (trace_thermal_power_cpu_limit_enabled() && load_cpu)
+ if (load_cpu)
load_cpu[i] = load;
i++;
@@ -541,7 +527,6 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev,
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
struct cpufreq_policy *policy = cpufreq_cdev->policy;
- power = power > 0 ? power : 0;
last_load = cpufreq_cdev->last_load ?: 1;
normalised_power = (power * 100) / last_load;
target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power);
@@ -692,7 +677,6 @@ __cpufreq_cooling_register(struct device_node *np,
goto remove_ida;
cpufreq_cdev->clipped_freq = cpufreq_cdev->freq_table[0].frequency;
- cpufreq_cdev->cdev = cdev;
mutex_lock(&cooling_list_lock);
/* Register the notifier for first cpufreq cooling device */
@@ -810,7 +794,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
CPUFREQ_POLICY_NOTIFIER);
- thermal_cooling_device_unregister(cpufreq_cdev->cdev);
+ thermal_cooling_device_unregister(cdev);
ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
kfree(cpufreq_cdev->idle_time);
kfree(cpufreq_cdev->freq_table);
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 2df059cc07e2..dc5093be553e 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -5,6 +5,9 @@
* Copyright (C) 2013 Texas Instruments
* Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/thermal.h>
#include <linux/slab.h>
#include <linux/types.h>
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 717a08600bb5..fc6fe50cdde4 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,3 +1,5 @@
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
+
+qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o \
+ tsens-8960.o tsens-v2.o tsens-v1.o
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
deleted file mode 100644
index c6dd620ac029..000000000000
--- a/drivers/thermal/qcom/tsens-8916.c
+++ /dev/null
@@ -1,105 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/platform_device.h>
-#include "tsens.h"
-
-/* eeprom layout data for 8916 */
-#define BASE0_MASK 0x0000007f
-#define BASE1_MASK 0xfe000000
-#define BASE0_SHIFT 0
-#define BASE1_SHIFT 25
-
-#define S0_P1_MASK 0x00000f80
-#define S1_P1_MASK 0x003e0000
-#define S2_P1_MASK 0xf8000000
-#define S3_P1_MASK 0x000003e0
-#define S4_P1_MASK 0x000f8000
-
-#define S0_P2_MASK 0x0001f000
-#define S1_P2_MASK 0x07c00000
-#define S2_P2_MASK 0x0000001f
-#define S3_P2_MASK 0x00007c00
-#define S4_P2_MASK 0x01f00000
-
-#define S0_P1_SHIFT 7
-#define S1_P1_SHIFT 17
-#define S2_P1_SHIFT 27
-#define S3_P1_SHIFT 5
-#define S4_P1_SHIFT 15
-
-#define S0_P2_SHIFT 12
-#define S1_P2_SHIFT 22
-#define S2_P2_SHIFT 0
-#define S3_P2_SHIFT 10
-#define S4_P2_SHIFT 20
-
-#define CAL_SEL_MASK 0xe0000000
-#define CAL_SEL_SHIFT 29
-
-static int calibrate_8916(struct tsens_device *tmdev)
-{
- int base0 = 0, base1 = 0, i;
- u32 p1[5], p2[5];
- int mode = 0;
- u32 *qfprom_cdata, *qfprom_csel;
-
- qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib");
- if (IS_ERR(qfprom_cdata))
- return PTR_ERR(qfprom_cdata);
-
- qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel");
- if (IS_ERR(qfprom_csel))
- return PTR_ERR(qfprom_csel);
-
- mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
- dev_dbg(tmdev->dev, "calibration mode is %d\n", mode);
-
- switch (mode) {
- case TWO_PT_CALIB:
- base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
- p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
- p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
- p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
- p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
- p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
- for (i = 0; i < tmdev->num_sensors; i++)
- p2[i] = ((base1 + p2[i]) << 3);
- /* Fall through */
- case ONE_PT_CALIB2:
- base0 = (qfprom_cdata[0] & BASE0_MASK);
- p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
- p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
- p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
- p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
- p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
- for (i = 0; i < tmdev->num_sensors; i++)
- p1[i] = (((base0) + p1[i]) << 3);
- break;
- default:
- for (i = 0; i < tmdev->num_sensors; i++) {
- p1[i] = 500;
- p2[i] = 780;
- }
- break;
- }
-
- compute_intercept_slope(tmdev, p1, p2, mode);
-
- return 0;
-}
-
-static const struct tsens_ops ops_8916 = {
- .init = init_common,
- .calibrate = calibrate_8916,
- .get_temp = get_temp_common,
-};
-
-const struct tsens_data data_8916 = {
- .num_sensors = 5,
- .ops = &ops_8916,
- .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 },
- .hw_ids = (unsigned int []){0, 1, 2, 4, 5 },
-};
diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
index 0f0adb302a7b..8d9b721dadb6 100644
--- a/drivers/thermal/qcom/tsens-8960.c
+++ b/drivers/thermal/qcom/tsens-8960.c
@@ -56,21 +56,21 @@
#define TRDY_MASK BIT(7)
#define TIMEOUT_US 100
-static int suspend_8960(struct tsens_device *tmdev)
+static int suspend_8960(struct tsens_priv *priv)
{
int ret;
unsigned int mask;
- struct regmap *map = tmdev->tm_map;
+ struct regmap *map = priv->tm_map;
- ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
+ ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
if (ret)
return ret;
- ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
+ ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
if (ret)
return ret;
- if (tmdev->num_sensors > 1)
+ if (priv->num_sensors > 1)
mask = SLP_CLK_ENA | EN;
else
mask = SLP_CLK_ENA_8660 | EN;
@@ -82,10 +82,10 @@ static int suspend_8960(struct tsens_device *tmdev)
return 0;
}
-static int resume_8960(struct tsens_device *tmdev)
+static int resume_8960(struct tsens_priv *priv)
{
int ret;
- struct regmap *map = tmdev->tm_map;
+ struct regmap *map = priv->tm_map;
ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
if (ret)
@@ -95,80 +95,80 @@ static int resume_8960(struct tsens_device *tmdev)
* Separate CONFIG restore is not needed only for 8660 as
* config is part of CTRL Addr and its restored as such
*/
- if (tmdev->num_sensors > 1) {
+ if (priv->num_sensors > 1) {
ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
if (ret)
return ret;
}
- ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
+ ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
if (ret)
return ret;
- ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
+ ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
if (ret)
return ret;
return 0;
}
-static int enable_8960(struct tsens_device *tmdev, int id)
+static int enable_8960(struct tsens_priv *priv, int id)
{
int ret;
u32 reg, mask;
- ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg);
+ ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg);
if (ret)
return ret;
mask = BIT(id + SENSOR0_SHIFT);
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg | SW_RST);
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
if (ret)
return ret;
- if (tmdev->num_sensors > 1)
+ if (priv->num_sensors > 1)
reg |= mask | SLP_CLK_ENA | EN;
else
reg |= mask | SLP_CLK_ENA_8660 | EN;
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg);
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
if (ret)
return ret;
return 0;
}
-static void disable_8960(struct tsens_device *tmdev)
+static void disable_8960(struct tsens_priv *priv)
{
int ret;
u32 reg_cntl;
u32 mask;
- mask = GENMASK(tmdev->num_sensors - 1, 0);
+ mask = GENMASK(priv->num_sensors - 1, 0);
mask <<= SENSOR0_SHIFT;
mask |= EN;
- ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg_cntl);
+ ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl);
if (ret)
return;
reg_cntl &= ~mask;
- if (tmdev->num_sensors > 1)
+ if (priv->num_sensors > 1)
reg_cntl &= ~SLP_CLK_ENA;
else
reg_cntl &= ~SLP_CLK_ENA_8660;
- regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+ regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
}
-static int init_8960(struct tsens_device *tmdev)
+static int init_8960(struct tsens_priv *priv)
{
int ret, i;
u32 reg_cntl;
- tmdev->tm_map = dev_get_regmap(tmdev->dev, NULL);
- if (!tmdev->tm_map)
+ priv->tm_map = dev_get_regmap(priv->dev, NULL);
+ if (!priv->tm_map)
return -ENODEV;
/*
@@ -177,21 +177,21 @@ static int init_8960(struct tsens_device *tmdev)
* but the control registers stay in the same place, i.e
* directly after the first 5 status registers.
*/
- for (i = 0; i < tmdev->num_sensors; i++) {
+ for (i = 0; i < priv->num_sensors; i++) {
if (i >= 5)
- tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
- tmdev->sensor[i].status += i * 4;
+ priv->sensor[i].status = S0_STATUS_ADDR + 40;
+ priv->sensor[i].status += i * 4;
}
reg_cntl = SW_RST;
- ret = regmap_update_bits(tmdev->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
+ ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
if (ret)
return ret;
- if (tmdev->num_sensors > 1) {
+ if (priv->num_sensors > 1) {
reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
reg_cntl &= ~SW_RST;
- ret = regmap_update_bits(tmdev->tm_map, CONFIG_ADDR,
+ ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR,
CONFIG_MASK, CONFIG);
} else {
reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
@@ -199,30 +199,30 @@ static int init_8960(struct tsens_device *tmdev)
reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
}
- reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+ reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT;
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
if (ret)
return ret;
reg_cntl |= EN;
- ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+ ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
if (ret)
return ret;
return 0;
}
-static int calibrate_8960(struct tsens_device *tmdev)
+static int calibrate_8960(struct tsens_priv *priv)
{
int i;
char *data;
- ssize_t num_read = tmdev->num_sensors;
- struct tsens_sensor *s = tmdev->sensor;
+ ssize_t num_read = priv->num_sensors;
+ struct tsens_sensor *s = priv->sensor;
- data = qfprom_read(tmdev->dev, "calib");
+ data = qfprom_read(priv->dev, "calib");
if (IS_ERR(data))
- data = qfprom_read(tmdev->dev, "calib_backup");
+ data = qfprom_read(priv->dev, "calib_backup");
if (IS_ERR(data))
return PTR_ERR(data);
@@ -243,21 +243,21 @@ static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
return adc_code * slope + offset;
}
-static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
+static int get_temp_8960(struct tsens_priv *priv, int id, int *temp)
{
int ret;
u32 code, trdy;
- const struct tsens_sensor *s = &tmdev->sensor[id];
+ const struct tsens_sensor *s = &priv->sensor[id];
unsigned long timeout;
timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
do {
- ret = regmap_read(tmdev->tm_map, INT_STATUS_ADDR, &trdy);
+ ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy);
if (ret)
return ret;
if (!(trdy & TRDY_MASK))
continue;
- ret = regmap_read(tmdev->tm_map, s->status, &code);
+ ret = regmap_read(priv->tm_map, s->status, &code);
if (ret)
return ret;
*temp = code_to_mdegC(code, s);
@@ -277,7 +277,7 @@ static const struct tsens_ops ops_8960 = {
.resume = resume_8960,
};
-const struct tsens_data data_8960 = {
+const struct tsens_plat_data data_8960 = {
.num_sensors = 11,
.ops = &ops_8960,
};
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
index f80c73f11740..928e8e81ba69 100644
--- a/drivers/thermal/qcom/tsens-common.c
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -12,18 +12,6 @@
#include <linux/regmap.h>
#include "tsens.h"
-/* SROT */
-#define TSENS_EN BIT(0)
-
-/* TM */
-#define STATUS_OFFSET 0x30
-#define SN_ADDR_OFFSET 0x4
-#define SN_ST_TEMP_MASK 0x3ff
-#define CAL_DEGC_PT1 30
-#define CAL_DEGC_PT2 120
-#define SLOPE_FACTOR 1000
-#define SLOPE_DEFAULT 3200
-
char *qfprom_read(struct device *dev, const char *cname)
{
struct nvmem_cell *cell;
@@ -46,18 +34,18 @@ char *qfprom_read(struct device *dev, const char *cname)
* and offset values are derived from tz->tzp->slope and tz->tzp->offset
* resp.
*/
-void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
u32 *p2, u32 mode)
{
int i;
int num, den;
- for (i = 0; i < tmdev->num_sensors; i++) {
- dev_dbg(tmdev->dev,
+ for (i = 0; i < priv->num_sensors; i++) {
+ dev_dbg(priv->dev,
"sensor%d - data_point1:%#x data_point2:%#x\n",
i, p1[i], p2[i]);
- tmdev->sensor[i].slope = SLOPE_DEFAULT;
+ priv->sensor[i].slope = SLOPE_DEFAULT;
if (mode == TWO_PT_CALIB) {
/*
* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
@@ -66,16 +54,30 @@ void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
num = p2[i] - p1[i];
num *= SLOPE_FACTOR;
den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
- tmdev->sensor[i].slope = num / den;
+ priv->sensor[i].slope = num / den;
}
- tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
+ priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
(CAL_DEGC_PT1 *
- tmdev->sensor[i].slope);
- dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
+ priv->sensor[i].slope);
+ dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset);
}
}
+bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id)
+{
+ u32 val;
+ int ret;
+
+ if ((hw_id > (priv->num_sensors - 1)) || (hw_id < 0))
+ return -EINVAL;
+ ret = regmap_field_read(priv->rf[SENSOR_EN], &val);
+ if (ret)
+ return ret;
+
+ return val & (1 << hw_id);
+}
+
static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
{
int degc, num, den;
@@ -95,18 +97,54 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
return degc;
}
-int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
+int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp)
{
- struct tsens_sensor *s = &tmdev->sensor[id];
- u32 code;
- unsigned int status_reg;
+ struct tsens_sensor *s = &priv->sensor[i];
+ u32 temp_idx = LAST_TEMP_0 + s->hw_id;
+ u32 valid_idx = VALID_0 + s->hw_id;
+ u32 last_temp = 0, valid, mask;
+ int ret;
+
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
+ if (ret)
+ return ret;
+ while (!valid) {
+ /* Valid bit is 0 for 6 AHB clock cycles.
+ * At 19.2MHz, 1 AHB clock is ~60ns.
+ * We should enter this loop very, very rarely.
+ */
+ ndelay(400);
+ ret = regmap_field_read(priv->rf[valid_idx], &valid);
+ if (ret)
+ return ret;
+ }
+
+ /* Valid bit is set, OK to read the temperature */
+ ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
+ if (ret)
+ return ret;
+
+ if (priv->feat->adc) {
+ /* Convert temperature from ADC code to milliCelsius */
+ *temp = code_to_degc(last_temp, s) * 1000;
+ } else {
+ mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
+ priv->fields[LAST_TEMP_0].lsb);
+ /* Convert temperature from deciCelsius to milliCelsius */
+ *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
+ }
+
+ return 0;
+}
+
+int get_temp_common(struct tsens_priv *priv, int i, int *temp)
+{
+ struct tsens_sensor *s = &priv->sensor[i];
int last_temp = 0, ret;
- status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET;
- ret = regmap_read(tmdev->tm_map, status_reg, &code);
+ ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp);
if (ret)
return ret;
- last_temp = code & SN_ST_TEMP_MASK;
*temp = code_to_degc(last_temp, s) * 1000;
@@ -127,21 +165,21 @@ static const struct regmap_config tsens_srot_config = {
.reg_stride = 4,
};
-int __init init_common(struct tsens_device *tmdev)
+int __init init_common(struct tsens_priv *priv)
{
void __iomem *tm_base, *srot_base;
+ struct device *dev = priv->dev;
struct resource *res;
- u32 code;
- int ret;
- struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node);
- u16 ctrl_offset = tmdev->reg_offsets[SROT_CTRL_OFFSET];
+ u32 enabled;
+ int ret, i, j;
+ struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
if (!op)
return -EINVAL;
if (op->num_resources > 1) {
/* DT with separate SROT and TM address space */
- tmdev->tm_offset = 0;
+ priv->tm_offset = 0;
res = platform_get_resource(op, IORESOURCE_MEM, 1);
srot_base = devm_ioremap_resource(&op->dev, res);
if (IS_ERR(srot_base)) {
@@ -149,16 +187,15 @@ int __init init_common(struct tsens_device *tmdev)
goto err_put_device;
}
- tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base,
+ priv->srot_map = devm_regmap_init_mmio(dev, srot_base,
&tsens_srot_config);
- if (IS_ERR(tmdev->srot_map)) {
- ret = PTR_ERR(tmdev->srot_map);
+ if (IS_ERR(priv->srot_map)) {
+ ret = PTR_ERR(priv->srot_map);
goto err_put_device;
}
-
} else {
/* old DTs where SROT and TM were in a contiguous 2K block */
- tmdev->tm_offset = 0x1000;
+ priv->tm_offset = 0x1000;
}
res = platform_get_resource(op, IORESOURCE_MEM, 0);
@@ -168,19 +205,47 @@ int __init init_common(struct tsens_device *tmdev)
goto err_put_device;
}
- tmdev->tm_map = devm_regmap_init_mmio(tmdev->dev, tm_base, &tsens_config);
- if (IS_ERR(tmdev->tm_map)) {
- ret = PTR_ERR(tmdev->tm_map);
+ priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config);
+ if (IS_ERR(priv->tm_map)) {
+ ret = PTR_ERR(priv->tm_map);
goto err_put_device;
}
- if (tmdev->srot_map) {
- ret = regmap_read(tmdev->srot_map, ctrl_offset, &code);
- if (ret)
+ priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
+ priv->fields[TSENS_EN]);
+ if (IS_ERR(priv->rf[TSENS_EN])) {
+ ret = PTR_ERR(priv->rf[TSENS_EN]);
+ goto err_put_device;
+ }
+ ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
+ if (ret)
+ goto err_put_device;
+ if (!enabled) {
+ dev_err(dev, "tsens device is not enabled\n");
+ ret = -ENODEV;
+ goto err_put_device;
+ }
+
+ priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
+ priv->fields[SENSOR_EN]);
+ if (IS_ERR(priv->rf[SENSOR_EN])) {
+ ret = PTR_ERR(priv->rf[SENSOR_EN]);
+ goto err_put_device;
+ }
+ /* now alloc regmap_fields in tm_map */
+ for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) {
+ priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
+ priv->fields[j]);
+ i