Skip to contentSkip to conversation

qcom: Add support for TSENS driver

PATCH Superseded Rajendra Nayak 3 participants 26 messages Apr 14, 2016 – May 5, 2016

Subsystems (7)

v5 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v5 cover qcom: Add support for TSENS driver

Current set of patches apply on 4.6-rc3. nvmem apis are currently broken and hence need to pull in the fixes for it as proposed here [1]

Changes since v4:
* dropped qcom,tsens-slopes binding, used coefficients instead
* dropped qcom,sensor-id binding
* Added support for msm8996 family
* Other minor review fixes from v4

Changes since v3:
* Dropped 'clk: qcom: create virtual child device for TSENS' which is picked up by Stephen
* Updated GCC bindings with optional TSENS properties

Changes since v2:
* Minor review fixes from Stephen/Punit and rebase on 4.3-rc4

Changes since v1:
* Created virtual tsens device from gcc driver for 8960, with DT having a single node for gcc and tsens
* Minor fixes with rebasing on 4.3-rc1

Changes since RFC:
* Added support for 8916 and 8084
* Based off the latest nvmem framework patches [1]
* Minor review fixes for comments mostly from Lina

This is an attempt to have a single TSENS driver for
the different versions of the TSENS IP that exist, on different qcom msm/apq SoCs'
Support is added for msm8916, msm8960, msm8974 and msm8996 families.

A lot of the work is based of original code from Stephen Boyd and Siddartha Mohanadoss. I have also picked some of what Narendran Rajan did in his attempt to upstream the support for 8960 family. I could not keep the original authorship on any of the patches because I ended up moving the code around quite a bit in an effort to have a single driver for the various devices. I would be glad to change the authorship for any of the patches if needed.

[1] https://lkml.org/lkml/2016/4/13/654

Rajendra Nayak (11):
thermal: qcom: tsens: Add a skeletal TSENS drivers
thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
thermal: qcom: tsens-8974: Add support for 8974 family of SoCs
thermal: core: export apis to get slope and offset
thermal: qcom: tsens-8960: Add support for 8960 family of SoCs
thermal: qcom: tsens-8996: Add support for 8996 family of SoCs
arm: dts: msm8974: Add thermal zones, tsens and qfprom nodes
arm: dts: apq8064: Add thermal zones, tsens and qfprom nodes
arm: dts: apq8084: Add thermal zones, tsens and qfprom nodes
arm64: dts: msm8916: Add thermal zones, tsens and qfprom nodes
arm64: dts: msm8996: Add thermal zones, tsens and qfprom nodes

 .../devicetree/bindings/clock/qcom,gcc.txt         |  18 ++
 .../devicetree/bindings/thermal/qcom-tsens.txt     |  21 ++
 arch/arm/boot/dts/qcom-apq8064.dtsi                | 103 ++++++++
 arch/arm/boot/dts/qcom-apq8084.dtsi                | 103 ++++++++
 arch/arm/boot/dts/qcom-msm8974.dtsi                | 103 ++++++++
 arch/arm64/boot/dts/qcom/msm8916.dtsi              |  64 +++++
 arch/arm64/boot/dts/qcom/msm8996.dtsi              |  92 +++++++
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/qcom/Kconfig                       |  11 +
 drivers/thermal/qcom/Makefile                      |   2 +
 drivers/thermal/qcom/tsens-8916.c                  | 113 ++++++++
 drivers/thermal/qcom/tsens-8960.c                  | 293 +++++++++++++++++++++
 drivers/thermal/qcom/tsens-8974.c                  | 244 +++++++++++++++++
 drivers/thermal/qcom/tsens-8996.c                  |  82 ++++++
 drivers/thermal/qcom/tsens-common.c                | 135 ++++++++++
 drivers/thermal/qcom/tsens.c                       | 207 +++++++++++++++
 drivers/thermal/qcom/tsens.h                       |  92 +++++++
 drivers/thermal/thermal_core.c                     |  16 ++
 include/linux/thermal.h                            |   8 +
 20 files changed, 1713 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/qcom-tsens.txt
 create mode 100644 drivers/thermal/qcom/Kconfig
 create mode 100644 drivers/thermal/qcom/Makefile
 create mode 100644 drivers/thermal/qcom/tsens-8916.c
 create mode 100644 drivers/thermal/qcom/tsens-8960.c
 create mode 100644 drivers/thermal/qcom/tsens-8974.c
 create mode 100644 drivers/thermal/qcom/tsens-8996.c
 create mode 100644 drivers/thermal/qcom/tsens-common.c
 create mode 100644 drivers/thermal/qcom/tsens.c
 create mode 100644 drivers/thermal/qcom/tsens.h
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#1 lore raw

PATCH v5 1/11 thermal: qcom: tsens: Add a skeletal TSENS drivers

TSENS is Qualcomms' thermal temperature sensor device. It supports reading temperatures from multiple thermal sensors present on various QCOM SoCs.
Calibration data is generally read from a non-volatile memory (eeprom) device.

Add a skeleton driver with all the necessary abstractions so a variety of qcom device families which support TSENS can add driver extensions.

Also add the required device tree bindings which can be used to describe the TSENS device in DT.

---
 .../devicetree/bindings/thermal/qcom-tsens.txt     |  21 +++
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/qcom/Kconfig                       |  11 ++
 drivers/thermal/qcom/Makefile                      |   2 +
 drivers/thermal/qcom/tsens-common.c                | 135 ++++++++++++++
 drivers/thermal/qcom/tsens.c                       | 202 +++++++++++++++++++++
 drivers/thermal/qcom/tsens.h                       |  90 +++++++++
 8 files changed, 467 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/qcom-tsens.txt
 create mode 100644 drivers/thermal/qcom/Kconfig
 create mode 100644 drivers/thermal/qcom/Makefile
 create mode 100644 drivers/thermal/qcom/tsens-common.c
 create mode 100644 drivers/thermal/qcom/tsens.c
 create mode 100644 drivers/thermal/qcom/tsens.h
Documentation/devicetree/bindings/thermal/qcom-tsens.txt new file +21 -0
new file mode 100644
index 0000000..292ed89
@@ -0,0 +1,21 @@
+* QCOM SoC Temperature Sensor (TSENS)
+
+Required properties:
+- compatible :
+ - "qcom,msm8916-tsens" : For 8916 Family of SoCs
+ - "qcom,msm8974-tsens" : For 8974 Family of SoCs
+ - "qcom,msm8996-tsens" : For 8996 Family of SoCs
+
+- reg: Address range of the thermal registers
+- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
+nvmem cells
+
+Example:
+tsens: thermal-sensor at 900000 {
+		compatible = "qcom,msm8916-tsens";
+		reg = <0x4a8000 0x2000>;
+		nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
+		nvmem-cell-names = "caldata", "calsel";
+		#thermal-sensor-cells = <1>;
+	};
drivers/thermal/Kconfig +5 -0
index c37eedc..463b00c 100644
@@ -408,4 +408,9 @@ config QCOM_SPMI_TEMP_ALARM
 	  real time die temperature if an ADC is present or an estimate of the
 	  temperature based upon the over temperature stage value.
 
+menu "Qualcomm thermal drivers"
+depends on (ARCH_QCOM && OF) || COMPILE_TEST
+source "drivers/thermal/qcom/Kconfig"
+endmenu
+
 endif
drivers/thermal/Makefile +1 -0
index 8e9cbc3..3f3e72c 100644
@@ -46,6 +46,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
 obj-$(CONFIG_INT340X_THERMAL)  += int340x_thermal/
 obj-$(CONFIG_INTEL_PCH_THERMAL)	+= intel_pch_thermal.o
 obj-$(CONFIG_ST_THERMAL)	+= st/
+obj-$(CONFIG_QCOM_TSENS)	+= qcom/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra_soctherm.o
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
drivers/thermal/qcom/Kconfig new file +11 -0
new file mode 100644
index 0000000..be32e5a
@@ -0,0 +1,11 @@
+config QCOM_TSENS
+	tristate "Qualcomm TSENS Temperature Alarm"
+	depends on THERMAL
+	depends on QCOM_QFPROM
+	depends on ARCH_QCOM || COMPILE_TEST
+	help
+	  This enables the thermal sysfs driver for the TSENS device. It shows
+	  up in Sysfs as a thermal zone with multiple trip points. Disabling the
+	  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.
drivers/thermal/qcom/Makefile new file +2 -0
new file mode 100644
index 0000000..2e800c5
@@ -0,0 +1,2 @@
+obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
+qcom_tsens-y			+= tsens.o tsens-common.o
drivers/thermal/qcom/tsens-common.c new file +135 -0

135 lines not on this page · raw message

drivers/thermal/qcom/tsens.c new file +202 -0

202 lines not on this page · raw message

drivers/thermal/qcom/tsens.h new file +90 -0

90 lines not on this page · raw message

Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#2 lore raw

PATCH v5 1/11 thermal: qcom: tsens: Add a skeletal TSENS drivers

Quoted 155 lines · Rajendra Nayak

TSENS is Qualcomms' thermal temperature sensor device. It supports reading temperatures from multiple thermal sensors present on various QCOM SoCs.
Calibration data is generally read from a non-volatile memory (eeprom) device.

Add a skeleton driver with all the necessary abstractions so a variety of qcom device families which support TSENS can add driver extensions.

Also add the required device tree bindings which can be used to describe the TSENS device in DT.

---
 .../devicetree/bindings/thermal/qcom-tsens.txt     |  21 +++
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/qcom/Kconfig                       |  11 ++
 drivers/thermal/qcom/Makefile                      |   2 +
 drivers/thermal/qcom/tsens-common.c                | 135 ++++++++++++++
 drivers/thermal/qcom/tsens.c                       | 202 +++++++++++++++++++++
 drivers/thermal/qcom/tsens.h                       |  90 +++++++++
 8 files changed, 467 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/qcom-tsens.txt
 create mode 100644 drivers/thermal/qcom/Kconfig
 create mode 100644 drivers/thermal/qcom/Makefile
 create mode 100644 drivers/thermal/qcom/tsens-common.c
 create mode 100644 drivers/thermal/qcom/tsens.c
 create mode 100644 drivers/thermal/qcom/tsens.h
Documentation/devicetree/bindings/thermal/qcom-tsens.txt new file +21 -0
new file mode 100644
index 0000000..292ed89
@@ -0,0 +1,21 @@
+* QCOM SoC Temperature Sensor (TSENS)
+
+Required properties:
+- compatible :
+ - "qcom,msm8916-tsens" : For 8916 Family of SoCs
+ - "qcom,msm8974-tsens" : For 8974 Family of SoCs
+ - "qcom,msm8996-tsens" : For 8996 Family of SoCs
+
+- reg: Address range of the thermal registers
+- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
+nvmem cells
+
+Example:
+tsens: thermal-sensor at 900000 {
+		compatible = "qcom,msm8916-tsens";
+		reg = <0x4a8000 0x2000>;
+		nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
+		nvmem-cell-names = "caldata", "calsel";
+		#thermal-sensor-cells = <1>;
+	};
drivers/thermal/Kconfig +5 -0
index c37eedc..463b00c 100644
@@ -408,4 +408,9 @@ config QCOM_SPMI_TEMP_ALARM
 	  real time die temperature if an ADC is present or an estimate of the
 	  temperature based upon the over temperature stage value.
 
+menu "Qualcomm thermal drivers"
+depends on (ARCH_QCOM && OF) || COMPILE_TEST
+source "drivers/thermal/qcom/Kconfig"
+endmenu
+
 endif
drivers/thermal/Makefile +1 -0
index 8e9cbc3..3f3e72c 100644
@@ -46,6 +46,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
 obj-$(CONFIG_INT340X_THERMAL)  += int340x_thermal/
 obj-$(CONFIG_INTEL_PCH_THERMAL)	+= intel_pch_thermal.o
 obj-$(CONFIG_ST_THERMAL)	+= st/
+obj-$(CONFIG_QCOM_TSENS)	+= qcom/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra_soctherm.o
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
drivers/thermal/qcom/Kconfig new file +11 -0
new file mode 100644
index 0000000..be32e5a
@@ -0,0 +1,11 @@
+config QCOM_TSENS
+	tristate "Qualcomm TSENS Temperature Alarm"
+	depends on THERMAL
+	depends on QCOM_QFPROM
+	depends on ARCH_QCOM || COMPILE_TEST
+	help
+	  This enables the thermal sysfs driver for the TSENS device. It shows
+	  up in Sysfs as a thermal zone with multiple trip points. Disabling the
+	  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.
drivers/thermal/qcom/Makefile new file +2 -0
new file mode 100644
index 0000000..2e800c5
@@ -0,0 +1,2 @@
+obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
+qcom_tsens-y			+= tsens.o tsens-common.o
drivers/thermal/qcom/tsens-common.c new file +39 -0
new file mode 100644
index 0000000..4bffbc1
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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/err.h>
+#include <linux/io.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include "tsens.h"
+
+#define S0_ST_ADDR		0x1030
+#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;
+	ssize_t data;
+	char *ret;
+
+	cell = nvmem_cell_get(dev, cname);
+	if (IS_ERR(cell))
+		return ERR_CAST(cell);

drivers/thermal/qcom/tsens-common.c line 49

Quoted 10 lines
drivers/thermal/qcom/tsens-common.c new file +10 -0
+
+	ret = nvmem_cell_read(cell, &data);
+	nvmem_cell_put(cell);
+
+	return ret;
+}
+
+void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+			     u32 *p2, u32 mode)
+{

Could you please add a comment explaining the cases that this function is used instead of tz->tzp->slope,offset?

Quoted 177 lines
drivers/thermal/qcom/tsens-common.c new file +86 -0
+	int i;
+	int num, den;
+
+	for (i = 0; i < tmdev->num_sensors; i++) {
+		dev_dbg(tmdev->dev,
+			"sensor%d - data_point1:%#x data_point2:%#x\n",
+			i, p1[i], p2[i]);
+
+		tmdev->sensor[i].slope = SLOPE_DEFAULT;
+		if (mode == TWO_PT_CALIB) {
+			/*
+			 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+			 *	temp_120_degc - temp_30_degc (x2 - x1)
+			 */
+			num = p2[i] - p1[i];
+			num *= SLOPE_FACTOR;
+			den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
+			tmdev->sensor[i].slope = num / den;
+		}
+
+		tmdev->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);
+	}
+}
+
+static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
+{
+	int degc, num, den;
+
+	num = (adc_code * SLOPE_FACTOR) - s->offset;
+	den = s->slope;
+
+	if (num > 0)
+		degc = num + (den / 2);
+	else if (num < 0)
+		degc = num - (den / 2);
+	else
+		degc = num;
+
+	degc /= den;
+
+	return degc;
+}
+
+int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
+{
+	struct tsens_sensor *s = &tmdev->sensor[id];
+	u32 code;
+	unsigned int sensor_addr;
+	int last_temp = 0, ret;
+
+	sensor_addr = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET;
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	last_temp = code & SN_ST_TEMP_MASK;
+
+	*temp = code_to_degc(last_temp, s) * 1000;
+
+	return 0;
+}
+
+static const struct regmap_config tsens_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+};
+
+int __init init_common(struct tsens_device *tmdev)
+{
+	void __iomem *base;
+
+	base = of_iomap(tmdev->dev->of_node, 0);
+	if (IS_ERR(base))
+		return -EINVAL;
+
+	tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config);
+	if (!tmdev->map) {
+		iounmap(base);
+		return -ENODEV;
+	}
+
+	return 0;
+}
drivers/thermal/qcom/tsens.c new file +85 -0
new file mode 100644
index 0000000..e799182
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+#include "tsens.h"
+
+static int tsens_get_temp(void *data, int *temp)
+{
+	const struct tsens_sensor *s = data;
+	struct tsens_device *tmdev = s->tmdev;
+
+	return tmdev->ops->get_temp(tmdev, s->id, temp);
+}
+
+static int tsens_get_trend(void *data, long *temp)
+{
+	const struct tsens_sensor *s = data;
+	struct tsens_device *tmdev = s->tmdev;
+
+	if (tmdev->ops->get_trend)
+		return tmdev->ops->get_trend(tmdev, s->id, temp);
+
+	return -ENOTSUPP;
+}
+
+static int tsens_suspend(struct device *dev)
+{
+	struct tsens_device *tmdev = dev_get_drvdata(dev);
+
+	if (tmdev->ops && tmdev->ops->suspend)
+		return tmdev->ops->suspend(tmdev);
+
+	return 0;
+}
+
+static int tsens_resume(struct device *dev)
+{
+	struct tsens_device *tmdev = dev_get_drvdata(dev);
+
+	if (tmdev->ops && tmdev->ops->resume)
+		return tmdev->ops->resume(tmdev);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
+
+static const struct of_device_id tsens_table[] = {
+	{
+		.compatible = "qcom,msm8916-tsens",
+	}, {
+		.compatible = "qcom,msm8974-tsens",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, tsens_table);
+
+static const struct thermal_zone_of_device_ops tsens_of_ops = {
+	.get_temp = tsens_get_temp,
+	.get_trend = tsens_get_trend,
+};
+
+static int tsens_register(struct tsens_device *tmdev)
+{
+	int i;
+	struct thermal_zone_device *tzd;
+	u32 *hw_id, n = tmdev->num_sensors;
+

drivers/thermal/qcom/tsens.c line 95

Quoted 10 lines
drivers/thermal/qcom/tsens.c new file +10 -0
+	hw_id = devm_kcalloc(tmdev->dev, n, sizeof(u32), GFP_KERNEL);
+	if (!hw_id)
+		return -ENOMEM;
+
+	for (i = 0;  i < tmdev->num_sensors; i++) {
+		tmdev->sensor[i].tmdev = tmdev;
+		tmdev->sensor[i].id = i;
+		tzd = thermal_zone_of_sensor_register(tmdev->dev, i,
+						      &tmdev->sensor[i],
+						      &tsens_of_ops);

How about using the devm_ version of this API?

Quoted 209 lines
drivers/thermal/qcom/tsens.c new file +107 -0
+		if (IS_ERR(tzd))
+			continue;
+		tmdev->sensor[i].tzd = tzd;
+		if (tmdev->ops->enable)
+			tmdev->ops->enable(tmdev, i);
+	}
+	return 0;
+}
+
+static int tsens_probe(struct platform_device *pdev)
+{
+	int ret, i;
+	struct device *dev;
+	struct device_node *np;
+	struct tsens_sensor *s;
+	struct tsens_device *tmdev;
+	const struct tsens_data *data;
+	const struct of_device_id *id;
+
+	if (pdev->dev.of_node)
+		dev = &pdev->dev;
+	else
+		dev = pdev->dev.parent;
+
+	np = dev->of_node;
+
+	id = of_match_node(tsens_table, np);
+	if (!id)
+		return -EINVAL;
+
+	data = id->data;
+
+	if (data->num_sensors <= 0) {
+		dev_err(dev, "invalid number of sensors\n");
+		return -EINVAL;
+	}
+
+	tmdev = devm_kzalloc(dev, sizeof(*tmdev) +
+			     data->num_sensors * sizeof(*s), GFP_KERNEL);
+	if (!tmdev)
+		return -ENOMEM;
+
+	tmdev->dev = dev;
+	tmdev->num_sensors = data->num_sensors;
+	tmdev->ops = data->ops;
+	for (i = 0;  i < tmdev->num_sensors; i++) {
+		if (data->hw_ids)
+			tmdev->sensor[i].hw_id = data->hw_ids[i];
+		else
+			tmdev->sensor[i].hw_id = i;
+	}
+
+	if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp)
+		return -EINVAL;
+
+	ret = tmdev->ops->init(tmdev);
+	if (ret < 0) {
+		dev_err(dev, "tsens init failed\n");
+		return ret;
+	}
+
+	if (tmdev->ops->calibrate) {
+		ret = tmdev->ops->calibrate(tmdev);
+		if (ret < 0) {
+			dev_err(dev, "tsens calibration failed\n");
+			return ret;
+		}
+	}
+
+	ret = tsens_register(tmdev);
+
+	platform_set_drvdata(pdev, tmdev);
+
+	return ret;
+}
+
+static int tsens_remove(struct platform_device *pdev)
+{
+	int i;
+	struct tsens_device *tmdev = platform_get_drvdata(pdev);
+	struct thermal_zone_device *tzd;
+
+	if (tmdev->ops->disable)
+		tmdev->ops->disable(tmdev);
+
+	for (i = 0; i < tmdev->num_sensors; i++) {
+		tzd = tmdev->sensor[i].tzd;
+		thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
+	}
 
 
+
+	return 0;
+}
+
+static struct platform_driver tsens_driver = {
+	.probe = tsens_probe,
+	.remove = tsens_remove,
+	.driver = {
+		.name = "qcom-tsens",
+		.pm	= &tsens_pm_ops,
+		.of_match_table = tsens_table,
+	},
+};
+module_platform_driver(tsens_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("QCOM Temperature Sensor driver");
+MODULE_ALIAS("platform:qcom-tsens");
drivers/thermal/qcom/tsens.h new file +90 -0
new file mode 100644
index 0000000..6f652ed
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+#ifndef __QCOM_TSENS_H__
+#define __QCOM_TSENS_H__
+
+#define ONE_PT_CALIB		0x1
+#define ONE_PT_CALIB2		0x2
+#define TWO_PT_CALIB		0x3
+
+struct tsens_device;
+
+struct tsens_sensor {
+	struct tsens_device		*tmdev;
+	struct thermal_zone_device	*tzd;
+	int				offset;
+	int				id;
+	int				hw_id;
+	u32				slope;
+	u32				status;
+};
+
+/**
+ * struct tsens_ops - operations as supported by the tsens device
+ * @init: Function to initialize the tsens device
+ * @calibrate: Function to calibrate the tsens device
+ * @get_temp: Function which returns the temp in millidegC
+ * @enable: Function to enable (clocks/power) tsens device
+ * @disable: Function to disable the tsens device
+ * @suspend: Function to suspend the tsens device
+ * @resume: Function to resume the tsens device
+ * @get_trend: Function to get the thermal/temp trend
+ */
+struct tsens_ops {
+	/* mandatory callbacks */
+	int (*init)(struct tsens_device *);
+	int (*calibrate)(struct tsens_device *);
+	int (*get_temp)(struct tsens_device *, int, int *);
+	/* optional callbacks */
+	int (*enable)(struct tsens_device *, int);
+	void (*disable)(struct tsens_device *);
+	int (*suspend)(struct tsens_device *);
+	int (*resume)(struct tsens_device *);
+	int (*get_trend)(struct tsens_device *, int, long *);
+};
+
+/**
+ * struct tsens_data - tsens instance specific data
+ * @num_sensors: Max number of sensors supported by platform
+ * @ops: operations the tsens instance supports
+ * @hw_ids: Subset of sensors ids supported by platform, if not the first n
+ */
+struct tsens_data {
+	const u32		num_sensors;
+	const struct tsens_ops	*ops;
+	unsigned int		*hw_ids;
+};
+
+/* Registers to be saved/restored across a context loss */
+struct tsens_context {
+	int	threshold;
+	int	control;
+};
+
+struct tsens_device {
+	struct device			*dev;
+	u32				num_sensors;
+	struct regmap			*map;
+	struct regmap_field		*status_field;
+	struct tsens_context		ctx;
+	bool				trdy;
+	const struct tsens_ops		*ops;
+	struct tsens_sensor		sensor[0];
+};
+
+char *qfprom_read(struct device *, const char *);
+void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
+int init_common(struct tsens_device *);
+int get_temp_common(struct tsens_device *, int, int *);
+
+#endif /* __QCOM_TSENS_H__ */
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#3 lore raw

PATCH v5 1/11 thermal: qcom: tsens: Add a skeletal TSENS drivers

Quoted 11 lines · Eduardo Valentin
Quoted 10 lines · Rajendra Nayak

TSENS is Qualcomms' thermal temperature sensor device. It supports reading temperatures from multiple thermal sensors present on various QCOM SoCs.
Calibration data is generally read from a non-volatile memory (eeprom) device.

Add a skeleton driver with all the necessary abstractions so a variety of qcom device families which support TSENS can add driver extensions.

Quoted 6 lines
Quoted 6 lines

Also add the required device tree bindings which can be used to describe the TSENS device in DT.

---

[]..

Quoted 45 lines
Quoted 45 lines
drivers/thermal/qcom/tsens-common.c new file +44 -0
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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/err.h>
+#include <linux/io.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include "tsens.h"
+
+#define S0_ST_ADDR		0x1030
+#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;
+	ssize_t data;
+	char *ret;
+
+	cell = nvmem_cell_get(dev, cname);
+	if (IS_ERR(cell))
+		return ERR_CAST(cell);
+
+	ret = nvmem_cell_read(cell, &data);
+	nvmem_cell_put(cell);
+
+	return ret;
Quoted 8 lines

drivers/thermal/qcom/tsens-common.c line 49

Quoted 5 lines
drivers/thermal/qcom/tsens-common.c new file +5 -0
+}
+
+void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+			     u32 *p2, u32 mode)
+{

Could you please add a comment explaining the cases that this function is used instead of tz->tzp->slope,offset?

sure, will do.

Quoted 19 lines
Quoted 19 lines
drivers/thermal/qcom/tsens-common.c new file +18 -0
+	int i;
+	int num, den;
+
+	for (i = 0; i < tmdev->num_sensors; i++) {
+		dev_dbg(tmdev->dev,
+			"sensor%d - data_point1:%#x data_point2:%#x\n",
+			i, p1[i], p2[i]);
+
+		tmdev->sensor[i].slope = SLOPE_DEFAULT;
+		if (mode == TWO_PT_CALIB) {
+			/*
+			 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+			 *	temp_120_degc - temp_30_degc (x2 - x1)
+			 */
+			num = p2[i] - p1[i];
+			num *= SLOPE_FACTOR;
+			den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
+			tmdev->sensor[i].slope = num / den;
Quoted 8 lines

drivers/thermal/qcom/tsens-common.c line 75

Quoted 8 lines
drivers/thermal/qcom/tsens-common.c new file +8 -0
+		}
+
+		tmdev->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);
+	}
+}

[]..

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
#4 lore raw

PATCH v5 2/11 thermal: qcom: tsens-8916: Add support for 8916 family of SoCs

In reply to Rajendra Nayak

Add support to calibrate sensors on 8916 family and also add common functions to read temperature from sensors (This can be reused on other SoCs having similar TSENS device)
The calibration data is read from eeprom using the generic nvmem framework apis.

Based on the original code by Siddartha Mohanadoss and Stephen Boyd.

---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8916.c | 113 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   1 +
 drivers/thermal/qcom/tsens.h      |   2 +
 4 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 drivers/thermal/qcom/tsens-8916.c
drivers/thermal/qcom/Makefile +1 -1
index 2e800c5..05c98e4 100644
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o
drivers/thermal/qcom/tsens-8916.c new file +113 -0

113 lines not on this page · raw message

drivers/thermal/qcom/tsens.c +1 -0
index e799182..c11d2e4 100644
@@ -65,6 +65,7 @@ static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
 static const struct of_device_id tsens_table[] = {
 	{
 		.compatible = "qcom,msm8916-tsens",
+		.data = &data_8916,
 	}, {
 		.compatible = "qcom,msm8974-tsens",
 	},
drivers/thermal/qcom/tsens.h +2 -0
index 6f652ed..0ecf979 100644
@@ -87,4 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
+extern const struct tsens_data data_8916;
+
 #endif /* __QCOM_TSENS_H__ */
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#5 lore raw

PATCH v5 3/11 thermal: qcom: tsens-8974: Add support for 8974 family of SoCs

In reply to Rajendra Nayak

Add .calibrate support for 8974 family as part of tsens_ops.

Based on the original code by Siddartha Mohanadoss and Stephen Boyd.

---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8974.c | 244 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   1 +
 drivers/thermal/qcom/tsens.h      |   2 +-
 4 files changed, 247 insertions(+), 2 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8974.c
drivers/thermal/qcom/Makefile +1 -1
index 05c98e4..a471100 100644
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o
drivers/thermal/qcom/tsens-8974.c new file +244 -0

244 lines not on this page · raw message

drivers/thermal/qcom/tsens.c +1 -0
index c11d2e4..99f3a6a 100644
@@ -68,6 +68,7 @@ static const struct of_device_id tsens_table[] = {
 		.data = &data_8916,
 	}, {
 		.compatible = "qcom,msm8974-tsens",
+		.data = &data_8974,
 	},
 	{}
 };
drivers/thermal/qcom/tsens.h +1 -1
index 0ecf979..d4cfb5f 100644
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916;
+extern const struct tsens_data data_8916, data_8974;
 
 #endif /* __QCOM_TSENS_H__ */
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#6 lore raw

PATCH v5 4/11 thermal: core: export apis to get slope and offset

In reply to Rajendra Nayak

Add apis for platform thermal drivers to query for slope and offset attributes, which might be needed for temperature calculations.

---
 drivers/thermal/thermal_core.c | 16 ++++++++++++++++
 include/linux/thermal.h        |  8 ++++++++
 2 files changed, 24 insertions(+)
drivers/thermal/thermal_core.c +16 -0
index d4b5465..7d72aad 100644
@@ -2065,6 +2065,22 @@ exit:
 }
 EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
 
+int thermal_zone_get_slope(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
+		return tz->tzp->slope;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
+
+int thermal_zone_get_offset(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
+		return tz->tzp->offset;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
+
 #ifdef CONFIG_NET
 static const struct genl_multicast_group thermal_event_mcgrps[] = {
 	{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
include/linux/thermal.h +8 -0
index a55d052..84be6a9 100644
@@ -432,6 +432,8 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
+int thermal_zone_get_slope(struct thermal_zone_device *tz);
+int thermal_zone_get_offset(struct thermal_zone_device *tz);
 
 int get_tz_trend(struct thermal_zone_device *, int);
 struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
@@ -489,6 +491,12 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
 static inline int thermal_zone_get_temp(
 		struct thermal_zone_device *tz, int *temp)
 { return -ENODEV; }
+static inline int thermal_zone_get_slope(
+		struct thermal_zone_device *tz)
+{ return -ENODEV; }
+static inline int thermal_zone_get_offset(
+		struct thermal_zone_device *tz)
+{ return -ENODEV; }
 static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
 { return -ENODEV; }
 static inline struct thermal_instance *
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#7 lore raw

PATCH v5 4/11 thermal: core: export apis to get slope and offset

Quoted 22 lines · Rajendra Nayak

Add apis for platform thermal drivers to query for slope and offset attributes, which might be needed for temperature calculations.

---
 drivers/thermal/thermal_core.c | 16 ++++++++++++++++
 include/linux/thermal.h        |  8 ++++++++
 2 files changed, 24 insertions(+)
drivers/thermal/thermal_core.c +5 -0
index d4b5465..7d72aad 100644
@@ -2065,6 +2065,22 @@ exit:
 }
 EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
 
+int thermal_zone_get_slope(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
+		return tz->tzp->slope;
+	return 1;

drivers/thermal/thermal_core.c exit: · line 2082

Quoted 10 lines
drivers/thermal/thermal_core.c +10 -0
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
+
+int thermal_zone_get_offset(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
+		return tz->tzp->offset;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_offset);

Please include kernel doc entries for the exported functions. Updating sysfs-api.txt would be also appreciated.

Thanks for adding this.

Quoted 34 lines
drivers/thermal/thermal_core.c +1 -0
+
 #ifdef CONFIG_NET
 static const struct genl_multicast_group thermal_event_mcgrps[] = {
 	{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
include/linux/thermal.h +8 -0
index a55d052..84be6a9 100644
@@ -432,6 +432,8 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
+int thermal_zone_get_slope(struct thermal_zone_device *tz);
+int thermal_zone_get_offset(struct thermal_zone_device *tz);
 
 int get_tz_trend(struct thermal_zone_device *, int);
 struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
@@ -489,6 +491,12 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
 static inline int thermal_zone_get_temp(
 		struct thermal_zone_device *tz, int *temp)
 { return -ENODEV; }
+static inline int thermal_zone_get_slope(
+		struct thermal_zone_device *tz)
+{ return -ENODEV; }
+static inline int thermal_zone_get_offset(
+		struct thermal_zone_device *tz)
+{ return -ENODEV; }
 static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
 { return -ENODEV; }
 static inline struct thermal_instance *
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#8 lore raw

PATCH v5 4/11 thermal: core: export apis to get slope and offset

Quoted 29 lines · Eduardo Valentin
Quoted 28 lines · Rajendra Nayak

Add apis for platform thermal drivers to query for slope and offset attributes, which might be needed for temperature calculations.

---
 drivers/thermal/thermal_core.c | 16 ++++++++++++++++
 include/linux/thermal.h        |  8 ++++++++
 2 files changed, 24 insertions(+)
drivers/thermal/thermal_core.c +11 -0
index d4b5465..7d72aad 100644
@@ -2065,6 +2065,22 @@ exit:
 }
 EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
 
+int thermal_zone_get_slope(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
+		return tz->tzp->slope;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
+
+int thermal_zone_get_offset(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
Quoted 8 lines

drivers/thermal/thermal_core.c exit: · line 2082

Quoted 4 lines
drivers/thermal/thermal_core.c +4 -0
+		return tz->tzp->offset;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_offset);

Please include kernel doc entries for the exported functions. Updating sysfs-api.txt would be also appreciated.

Sure, will update and repost.

Quoted 2 lines

Thanks for adding this.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
#9 lore raw

PATCH v5 5/11 thermal: qcom: tsens-8960: Add support for 8960 family of SoCs

In reply to Rajendra Nayak

8960 family of SoCs have the TSENS device as part of GCC, hence the driver probes the virtual child device created by GCC and uses the parent to extract all DT properties and reuses the GCC regmap.

Also GCC/TSENS are part of a domain thats not always ON. Hence add .suspend and .resume hooks to save and restore some of the inited register context.

Also 8960 family have some of the TSENS init sequence thats required to be done by the HLOS driver (some later versions of TSENS do not export these registers to non-secure world, and hence need these initializations to be done by secure bootloaders)

8660 from the same family has just one sensor and hence some register offset/layout differences which need special handling in the driver.

Based on the original code from Siddartha Mohanadoss, Stephen Boyd and Narendran Rajan.

---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8960.c | 293 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   8 +-
 drivers/thermal/qcom/tsens.h      |   2 +-
 4 files changed, 299 insertions(+), 6 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8960.c
drivers/thermal/qcom/Makefile +1 -1
index a471100..f3cefd1 100644
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
drivers/thermal/qcom/tsens-8960.c new file +293 -0

293 lines not on this page · raw message

drivers/thermal/qcom/tsens.c +4 -4
index 99f3a6a..096f64d 100644
@@ -122,10 +122,10 @@ static int tsens_probe(struct platform_device *pdev)
 	np = dev->of_node;
 
 	id = of_match_node(tsens_table, np);
-	if (!id)
-		return -EINVAL;
-
-	data = id->data;
+	if (id)
+		data = id->data;
+	else
+		data = &data_8960;
 
 	if (data->num_sensors <= 0) {
 		dev_err(dev, "invalid number of sensors\n");
drivers/thermal/qcom/tsens.h +1 -1
index d4cfb5f..146d4f1 100644
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916, data_8974;
+extern const struct tsens_data data_8916, data_8974, data_8960;
 
 #endif /* __QCOM_TSENS_H__ */
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#10 lore raw

PATCH v5 5/11 thermal: qcom: tsens-8960: Add support for 8960 family of SoCs

Quoted 280 lines · Rajendra Nayak

8960 family of SoCs have the TSENS device as part of GCC, hence the driver probes the virtual child device created by GCC and uses the parent to extract all DT properties and reuses the GCC regmap.

Also GCC/TSENS are part of a domain thats not always ON. Hence add .suspend and .resume hooks to save and restore some of the inited register context.

Also 8960 family have some of the TSENS init sequence thats required to be done by the HLOS driver (some later versions of TSENS do not export these registers to non-secure world, and hence need these initializations to be done by secure bootloaders)

8660 from the same family has just one sensor and hence some register offset/layout differences which need special handling in the driver.

Based on the original code from Siddartha Mohanadoss, Stephen Boyd and Narendran Rajan.

---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8960.c | 293 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   8 +-
 drivers/thermal/qcom/tsens.h      |   2 +-
 4 files changed, 299 insertions(+), 6 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8960.c
drivers/thermal/qcom/Makefile +1 -1
index a471100..f3cefd1 100644
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
drivers/thermal/qcom/tsens-8960.c new file +237 -0
new file mode 100644
index 0000000..a5976ec3
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/thermal.h>
+#include "tsens.h"
+
+#define CAL_MDEGC		30000
+
+#define CONFIG_ADDR		0x3640
+#define CONFIG_ADDR_8660	0x3620
+/* CONFIG_ADDR bitmasks */
+#define CONFIG			0x9b
+#define CONFIG_MASK		0xf
+#define CONFIG_8660		1
+#define CONFIG_SHIFT_8660	28
+#define CONFIG_MASK_8660	(3 << CONFIG_SHIFT_8660)
+
+#define STATUS_CNTL_ADDR_8064	0x3660
+#define CNTL_ADDR		0x3620
+/* CNTL_ADDR bitmasks */
+#define EN			BIT(0)
+#define SW_RST			BIT(1)
+#define SENSOR0_EN		BIT(3)
+#define SLP_CLK_ENA		BIT(26)
+#define SLP_CLK_ENA_8660	BIT(24)
+#define MEASURE_PERIOD		1
+#define SENSOR0_SHIFT		3
+
+/* INT_STATUS_ADDR bitmasks */
+#define MIN_STATUS_MASK		BIT(0)
+#define LOWER_STATUS_CLR	BIT(1)
+#define UPPER_STATUS_CLR	BIT(2)
+#define MAX_STATUS_MASK		BIT(3)
+
+#define THRESHOLD_ADDR		0x3624
+/* THRESHOLD_ADDR bitmasks */
+#define THRESHOLD_MAX_LIMIT_SHIFT	24
+#define THRESHOLD_MIN_LIMIT_SHIFT	16
+#define THRESHOLD_UPPER_LIMIT_SHIFT	8
+#define THRESHOLD_LOWER_LIMIT_SHIFT	0
+
+/* Initial temperature threshold values */
+#define LOWER_LIMIT_TH		0x50
+#define UPPER_LIMIT_TH		0xdf
+#define MIN_LIMIT_TH		0x0
+#define MAX_LIMIT_TH		0xff
+
+#define S0_STATUS_ADDR		0x3628
+#define INT_STATUS_ADDR		0x363c
+#define TRDY_MASK		BIT(7)
+#define TIMEOUT_US		100
+
+static int suspend_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	unsigned int mask;
+	struct regmap *map = tmdev->map;
+
+	ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1)
+		mask = SLP_CLK_ENA | EN;
+	else
+		mask = SLP_CLK_ENA_8660 | EN;
+
+	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int resume_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	struct regmap *map = tmdev->map;
+
+	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
+	if (ret)
+		return ret;
+
+	/*
+	 * 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) {
+		ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int enable_8960(struct tsens_device *tmdev, int id)
+{
+	int ret;
+	u32 reg, mask;
+
+	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg);
+	if (ret)
+		return ret;
+
+	mask = BIT(id + SENSOR0_SHIFT);
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1)
+		reg |= mask | SLP_CLK_ENA | EN;
+	else
+		reg |= mask | SLP_CLK_ENA_8660 | EN;
+
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void disable_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	u32 reg_cntl;
+	u32 mask;
+
+	mask = GENMASK(tmdev->num_sensors - 1, 0);
+	mask <<= SENSOR0_SHIFT;
+	mask |= EN;
+
+	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
+	if (ret)
+		return;
+
+	reg_cntl &= ~mask;
+
+	if (tmdev->num_sensors > 1)
+		reg_cntl &= ~SLP_CLK_ENA;
+	else
+		reg_cntl &= ~SLP_CLK_ENA_8660;
+
+	regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+}
+
+static int init_8960(struct tsens_device *tmdev)
+{
+	int ret, i;
+	u32 reg_cntl;
+
+	tmdev->map = dev_get_regmap(tmdev->dev, NULL);
+	if (!tmdev->map)
+		return -ENODEV;
+
+	/*
+	 * The status registers for each sensor are discontiguous
+	 * because some SoCs have 5 sensors while others have more
+	 * 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++) {
+		if (i >= 5)
+			tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
+		tmdev->sensor[i].status += i * 4;
+	}
+
+	reg_cntl = SW_RST;
+	ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1) {
+		reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
+		reg_cntl &= ~SW_RST;
+		ret = regmap_update_bits(tmdev->map, CONFIG_ADDR,
+					 CONFIG_MASK, CONFIG);
+	} else {
+		reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
+		reg_cntl &= ~CONFIG_MASK_8660;
+		reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
+	}
+
+	reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+	if (ret)
+		return ret;
+
+	reg_cntl |= EN;
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int calibrate_8960(struct tsens_device *tmdev)
+{
+	int i;
+	char *data;
+
+	ssize_t num_read = tmdev->num_sensors;
+	struct tsens_sensor *s = tmdev->sensor;
+
+	data = qfprom_read(tmdev->dev, "calib");
+	if (IS_ERR(data))
+		data = qfprom_read(tmdev->dev, "calib_backup");
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+

drivers/thermal/qcom/tsens-8960.c line 247

Quoted 10 lines
drivers/thermal/qcom/tsens-8960.c new file +10 -0
+	for (i = 0; i < num_read; i++, s++)
+		s->offset = data[i];
+
+	return 0;
+}
+
+/* Temperature on y axis and ADC-code on x-axis */
+static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
+{
+	u32 slope;

why unsigned?

drivers/thermal/qcom/tsens-8960.c line 250

Quoted 3 lines
drivers/thermal/qcom/tsens-8960.c new file +3 -0
+	int offset;
+
+	slope = thermal_zone_get_slope(s->tzd);;

Please use one single ;

Quoted 78 lines
drivers/thermal/qcom/tsens-8960.c new file +43 -0
+	offset = CAL_MDEGC - slope * s->offset;
+
+	return adc_code * slope + offset;
+}
+
+static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
+{
+	int ret;
+	u32 code, trdy;
+	const struct tsens_sensor *s = &tmdev->sensor[id];
+	unsigned long timeout;
+
+	timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
+	do {
+		ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy);
+		if (ret)
+			return ret;
+		if (!(trdy & TRDY_MASK))
+			continue;
+		ret = regmap_read(tmdev->map, s->status, &code);
+		if (ret)
+			return ret;
+		*temp = code_to_mdegC(code, s);
+		return 0;
+	} while (time_before(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+const struct tsens_ops ops_8960 = {
+	.init		= init_8960,
+	.calibrate	= calibrate_8960,
+	.get_temp	= get_temp_8960,
+	.enable		= enable_8960,
+	.disable	= disable_8960,
+	.suspend	= suspend_8960,
+	.resume		= resume_8960,
+};
+
+const struct tsens_data data_8960 = {
+	.num_sensors	= 11,
+	.ops		= &ops_8960,
+};
drivers/thermal/qcom/tsens.c +4 -4
index 99f3a6a..096f64d 100644
@@ -122,10 +122,10 @@ static int tsens_probe(struct platform_device *pdev)
 	np = dev->of_node;
 
 	id = of_match_node(tsens_table, np);
-	if (!id)
-		return -EINVAL;
-
-	data = id->data;
+	if (id)
+		data = id->data;
+	else
+		data = &data_8960;
 
 	if (data->num_sensors <= 0) {
 		dev_err(dev, "invalid number of sensors\n");
drivers/thermal/qcom/tsens.h +1 -1
index d4cfb5f..146d4f1 100644
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916, data_8974;
+extern const struct tsens_data data_8916, data_8974, data_8960;
 
 #endif /* __QCOM_TSENS_H__ */
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#11 lore raw

PATCH v5 5/11 thermal: qcom: tsens-8960: Add support for 8960 family of SoCs

Quoted 294 lines · Eduardo Valentin
Quoted 280 lines · Rajendra Nayak

8960 family of SoCs have the TSENS device as part of GCC, hence the driver probes the virtual child device created by GCC and uses the parent to extract all DT properties and reuses the GCC regmap.

Also GCC/TSENS are part of a domain thats not always ON. Hence add .suspend and .resume hooks to save and restore some of the inited register context.

Also 8960 family have some of the TSENS init sequence thats required to be done by the HLOS driver (some later versions of TSENS do not export these registers to non-secure world, and hence need these initializations to be done by secure bootloaders)

8660 from the same family has just one sensor and hence some register offset/layout differences which need special handling in the driver.

Based on the original code from Siddartha Mohanadoss, Stephen Boyd and Narendran Rajan.

---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8960.c | 293 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   8 +-
 drivers/thermal/qcom/tsens.h      |   2 +-
 4 files changed, 299 insertions(+), 6 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8960.c
drivers/thermal/qcom/Makefile +1 -1
index a471100..f3cefd1 100644
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
drivers/thermal/qcom/tsens-8960.c new file +237 -0
new file mode 100644
index 0000000..a5976ec3
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/thermal.h>
+#include "tsens.h"
+
+#define CAL_MDEGC		30000
+
+#define CONFIG_ADDR		0x3640
+#define CONFIG_ADDR_8660	0x3620
+/* CONFIG_ADDR bitmasks */
+#define CONFIG			0x9b
+#define CONFIG_MASK		0xf
+#define CONFIG_8660		1
+#define CONFIG_SHIFT_8660	28
+#define CONFIG_MASK_8660	(3 << CONFIG_SHIFT_8660)
+
+#define STATUS_CNTL_ADDR_8064	0x3660
+#define CNTL_ADDR		0x3620
+/* CNTL_ADDR bitmasks */
+#define EN			BIT(0)
+#define SW_RST			BIT(1)
+#define SENSOR0_EN		BIT(3)
+#define SLP_CLK_ENA		BIT(26)
+#define SLP_CLK_ENA_8660	BIT(24)
+#define MEASURE_PERIOD		1
+#define SENSOR0_SHIFT		3
+
+/* INT_STATUS_ADDR bitmasks */
+#define MIN_STATUS_MASK		BIT(0)
+#define LOWER_STATUS_CLR	BIT(1)
+#define UPPER_STATUS_CLR	BIT(2)
+#define MAX_STATUS_MASK		BIT(3)
+
+#define THRESHOLD_ADDR		0x3624
+/* THRESHOLD_ADDR bitmasks */
+#define THRESHOLD_MAX_LIMIT_SHIFT	24
+#define THRESHOLD_MIN_LIMIT_SHIFT	16
+#define THRESHOLD_UPPER_LIMIT_SHIFT	8
+#define THRESHOLD_LOWER_LIMIT_SHIFT	0
+
+/* Initial temperature threshold values */
+#define LOWER_LIMIT_TH		0x50
+#define UPPER_LIMIT_TH		0xdf
+#define MIN_LIMIT_TH		0x0
+#define MAX_LIMIT_TH		0xff
+
+#define S0_STATUS_ADDR		0x3628
+#define INT_STATUS_ADDR		0x363c
+#define TRDY_MASK		BIT(7)
+#define TIMEOUT_US		100
+
+static int suspend_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	unsigned int mask;
+	struct regmap *map = tmdev->map;
+
+	ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1)
+		mask = SLP_CLK_ENA | EN;
+	else
+		mask = SLP_CLK_ENA_8660 | EN;
+
+	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int resume_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	struct regmap *map = tmdev->map;
+
+	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
+	if (ret)
+		return ret;
+
+	/*
+	 * 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) {
+		ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int enable_8960(struct tsens_device *tmdev, int id)
+{
+	int ret;
+	u32 reg, mask;
+
+	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg);
+	if (ret)
+		return ret;
+
+	mask = BIT(id + SENSOR0_SHIFT);
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1)
+		reg |= mask | SLP_CLK_ENA | EN;
+	else
+		reg |= mask | SLP_CLK_ENA_8660 | EN;
+
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void disable_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	u32 reg_cntl;
+	u32 mask;
+
+	mask = GENMASK(tmdev->num_sensors - 1, 0);
+	mask <<= SENSOR0_SHIFT;
+	mask |= EN;
+
+	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
+	if (ret)
+		return;
+
+	reg_cntl &= ~mask;
+
+	if (tmdev->num_sensors > 1)
+		reg_cntl &= ~SLP_CLK_ENA;
+	else
+		reg_cntl &= ~SLP_CLK_ENA_8660;
+
+	regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+}
+
+static int init_8960(struct tsens_device *tmdev)
+{
+	int ret, i;
+	u32 reg_cntl;
+
+	tmdev->map = dev_get_regmap(tmdev->dev, NULL);
+	if (!tmdev->map)
+		return -ENODEV;
+
+	/*
+	 * The status registers for each sensor are discontiguous
+	 * because some SoCs have 5 sensors while others have more
+	 * 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++) {
+		if (i >= 5)
+			tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
+		tmdev->sensor[i].status += i * 4;
+	}
+
+	reg_cntl = SW_RST;
+	ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1) {
+		reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
+		reg_cntl &= ~SW_RST;
+		ret = regmap_update_bits(tmdev->map, CONFIG_ADDR,
+					 CONFIG_MASK, CONFIG);
+	} else {
+		reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
+		reg_cntl &= ~CONFIG_MASK_8660;
+		reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
+	}
+
+	reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+	if (ret)
+		return ret;
+
+	reg_cntl |= EN;
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int calibrate_8960(struct tsens_device *tmdev)
+{
+	int i;
+	char *data;
+
+	ssize_t num_read = tmdev->num_sensors;
+	struct tsens_sensor *s = tmdev->sensor;
+
+	data = qfprom_read(tmdev->dev, "calib");
+	if (IS_ERR(data))
+		data = qfprom_read(tmdev->dev, "calib_backup");
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+

drivers/thermal/qcom/tsens-8960.c line 247

Quoted 10 lines
drivers/thermal/qcom/tsens-8960.c new file +10 -0
+	for (i = 0; i < num_read; i++, s++)
+		s->offset = data[i];
+
+	return 0;
+}
+
+/* Temperature on y axis and ADC-code on x-axis */
+static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
+{
+	u32 slope;

why unsigned?

Quoted 5 lines

drivers/thermal/qcom/tsens-8960.c line 250

Quoted 3 lines
drivers/thermal/qcom/tsens-8960.c new file +3 -0
+	int offset;
+
+	slope = thermal_zone_get_slope(s->tzd);;

Please use one single ;

Will fix both when I repost.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
#12 lore raw

PATCH v5 6/11 thermal: qcom: tsens-8996: Add support for 8996 family of SoCs

In reply to Rajendra Nayak

The TSENS controller in 8996 family of SoCs is capable of converting the ADC code outputs to real temperature values (in decidegree Celsius). It can also be programmed to provide raw ADC code, but the secure software on 8996 programs it to provide real temperatures and also does the needed calibrations.

We check the valid bit to ensure valid data is read by the AHB master. And the spec recommends the below algorithm to read data 3 consecutive times, which takes care of the worst case delay taken to propogate the updated data to the register.

---
 drivers/thermal/qcom/Makefile     |  2 +-
 drivers/thermal/qcom/tsens-8996.c | 82 +++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |  3 ++
 drivers/thermal/qcom/tsens.h      |  2 +-
 4 files changed, 87 insertions(+), 2 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8996.c
drivers/thermal/qcom/Makefile +1 -1
index f3cefd1..2cc2193 100644
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o
drivers/thermal/qcom/tsens-8996.c new file +82 -0

82 lines not on this page · raw message

drivers/thermal/qcom/tsens.c +3 -0
index 096f64d..9ebe020 100644
@@ -69,6 +69,9 @@ static const struct of_device_id tsens_table[] = {
 	}, {
 		.compatible = "qcom,msm8974-tsens",
 		.data = &data_8974,
+	}, {
+		.compatible = "qcom,msm8996-tsens",
+		.data = &data_8996,
 	},
 	{}
 };
drivers/thermal/qcom/tsens.h +1 -1
index 146d4f1..4a12df2 100644
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916, data_8974, data_8960;
+extern const struct tsens_data data_8916, data_8974, data_8960, data_8996;
 
 #endif /* __QCOM_TSENS_H__ */
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#13 lore raw

PATCH v5 6/11 thermal: qcom: tsens-8996: Add support for 8996 family of SoCs

Quoted 9 lines · Rajendra Nayak

The TSENS controller in 8996 family of SoCs is capable of converting the ADC code outputs to real temperature values (in decidegree Celsius). It can also be programmed to provide raw ADC code, but the secure software on 8996 programs it to provide real temperatures and also does the needed calibrations.

We check the valid bit to ensure valid data is read by the AHB master. And the spec recommends the below algorithm to read data 3 consecutive times, which takes care of the worst case delay taken to propogate the

s/propogate/propagate/g ?

Quoted 62 lines

updated data to the register.

---
 drivers/thermal/qcom/Makefile     |  2 +-
 drivers/thermal/qcom/tsens-8996.c | 82 +++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |  3 ++
 drivers/thermal/qcom/tsens.h      |  2 +-
 4 files changed, 87 insertions(+), 2 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8996.c
drivers/thermal/qcom/Makefile +1 -1
index f3cefd1..2cc2193 100644
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o
drivers/thermal/qcom/tsens-8996.c new file +37 -0
new file mode 100644
index 0000000..3d70aa0
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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/platform_device.h>
+#include <linux/regmap.h>
+#include "tsens.h"
+
+#define STATUS_OFFSET	0x10a0
+#define LAST_TEMP_MASK	0xfff
+#define STATUS_VALID_BIT	BIT(21)
+#define CODE_SIGN_BIT		BIT(11)
+
+static int get_temp_8996(struct tsens_device *tmdev, int id, int *temp)
+{
+	struct tsens_sensor *s = &tmdev->sensor[id];
+	u32 code;
+	unsigned int sensor_addr;
+	int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret;
+
+	sensor_addr = STATUS_OFFSET + s->hw_id * 4;
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	last_temp = code & LAST_TEMP_MASK;
+	if (code & STATUS_VALID_BIT)
+		goto done;

drivers/thermal/qcom/tsens-8996.c line 47

Quoted 10 lines
drivers/thermal/qcom/tsens-8996.c new file +10 -0
+
+	/* Try a second time */
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	if (code & STATUS_VALID_BIT) {
+		last_temp = code & LAST_TEMP_MASK;
+		goto done;
+	} else
+		last_temp2 = code & LAST_TEMP_MASK;

I believe coding style suggests you to use {} on all arms in this if.

drivers/thermal/qcom/tsens-8996.c line 58

Quoted 11 lines
drivers/thermal/qcom/tsens-8996.c new file +11 -0
+
+	/* Try a third/last time */
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	if (code & STATUS_VALID_BIT) {
+		last_temp = code & LAST_TEMP_MASK;
+		goto done;
+	} else
+		last_temp3 = code & LAST_TEMP_MASK;
+

ditto.

Quoted 54 lines
drivers/thermal/qcom/tsens-8996.c new file +24 -0
+	if (last_temp == last_temp2)
+		last_temp = last_temp2;
+	else if (last_temp2 == last_temp3)
+		last_temp = last_temp3;
+done:
+	/* Code sign bit is the sign extension for a negative value */
+	if (last_temp & CODE_SIGN_BIT)
+		last_temp |= ~CODE_SIGN_BIT;
+
+	/* Temperatures are in deciCelicius */
+	*temp = last_temp * 100;
+
+	return 0;
+}
+
+const struct tsens_ops ops_8996 = {
+	.init		= init_common,
+	.get_temp	= get_temp_8996,
+};
+
+const struct tsens_data data_8996 = {
+	.num_sensors	= 13,
+	.ops		= &ops_8996,
+};
drivers/thermal/qcom/tsens.c +3 -0
index 096f64d..9ebe020 100644
@@ -69,6 +69,9 @@ static const struct of_device_id tsens_table[] = {
 	}, {
 		.compatible = "qcom,msm8974-tsens",
 		.data = &data_8974,
+	}, {
+		.compatible = "qcom,msm8996-tsens",
+		.data = &data_8996,
 	},
 	{}
 };
drivers/thermal/qcom/tsens.h +1 -1
index 146d4f1..4a12df2 100644
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916, data_8974, data_8960;
+extern const struct tsens_data data_8916, data_8974, data_8960, data_8996;
 
 #endif /* __QCOM_TSENS_H__ */
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#14 lore raw

PATCH v5 7/11 arm: dts: msm8974: Add thermal zones, tsens and qfprom nodes

In reply to Rajendra Nayak

Add thermal zones, tsens and qfprom nodes

---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 103 ++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)
arch/arm/boot/dts/qcom-msm8974.dtsi +103 -0
index ef53305..7ddf031 100644
@@ -126,6 +126,88 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 5>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 6>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 7>;
+
+			trips {
+				cpu_alert2: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit2: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 8>;
+
+			trips {
+				cpu_alert3: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit3: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 7 0xf04>;
@@ -249,6 +331,27 @@
 			reg = <0xf9011000 0x1000>;
 		};
 
+		qfprom: qfprom at fc4bc000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qfprom";
+			reg = <0xfc4bc000 0x1000>;
+			tsens_calib: calib at d0 {
+				reg = <0xd0 0x18>;
+			};
+			tsens_backup: backup at 440 {
+				reg = <0x440 0x10>;
+			};
+		};
+
+		tsens: thermal-sensor at fc4a8000 {
+			compatible = "qcom,msm8974-tsens";
+			reg = <0xfc4a8000 0x2000>;
+			nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+			nvmem-cell-names = "calib", "calib_backup";
+			#thermal-sensor-cells = <1>;
+		};
+
 		timer at f9020000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#15 lore raw

PATCH v5 8/11 arm: dts: apq8064: Add thermal zones, tsens and qfprom nodes

In reply to Rajendra Nayak

TSENS is part of GCC, hence add TSENS properties as part of GCC node. Also add thermal zones and qfprom nodes.
Update GCC bindings doc to mention the possibility of optional TSENS properties that can be part of GCC node.

---
 .../devicetree/bindings/clock/qcom,gcc.txt         |  18 ++++
 arch/arm/boot/dts/qcom-apq8064.dtsi                | 103 +++++++++++++++++++++
 2 files changed, 121 insertions(+)
Documentation/devicetree/bindings/clock/qcom,gcc.txt +18 -0
index 9a60fde..16e2f84 100644
@@ -23,6 +23,13 @@ Required properties :
 Optional properties :
 - #power-domain-cells : shall contain 1
 
+Optional properties:
+- Qualcomm TSENS (thermal sensor device) on some devices can
+be part of GCC and hence the TSENS properties can also be
+part of the GCC/clock-controller node.
+For more details on the TSENS properties please refer
+Documentation/devicetree/bindings/thermal/qcom-tsens.txt
+
 Example:
 	clock-controller at 900000 {
 		compatible = "qcom,gcc-msm8960";
@@ -31,3 +38,14 @@ Example:
 		#reset-cells = <1>;
 		#power-domain-cells = <1>;
 	};
+
+Example of GCC with TSENS properties:
+	clock-controller at 900000 {
+		compatible = "qcom,gcc-apq8064";
+		reg = <0x00900000 0x4000>;
+		nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+		nvmem-cell-names = "calib", "calib_backup";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		#thermal-sensor-cells = <1>;
+	};
arch/arm/boot/dts/qcom-apq8064.dtsi +103 -0

120 lines not on this page · raw message

Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#16 lore raw

PATCH v5 9/11 arm: dts: apq8084: Add thermal zones, tsens and qfprom nodes

In reply to Rajendra Nayak

Add thermal zones, tsens and qfprom nodes

---
 arch/arm/boot/dts/qcom-apq8084.dtsi | 103 ++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)
arch/arm/boot/dts/qcom-apq8084.dtsi +103 -0
index a33a09f..5284709 100644
@@ -86,6 +86,88 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 5>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 6>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 7>;
+
+			trips {
+				cpu_alert2: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit2: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 8>;
+
+			trips {
+				cpu_alert3: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit3: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 7 0xf04>;
@@ -142,6 +224,27 @@
 			reg = <0xf9011000 0x1000>;
 		};
 
+		qfprom: qfprom at fc4bc000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qfprom";
+			reg = <0xfc4bc000 0x1000>;
+			tsens_calib: calib at d0 {
+				reg = <0xd0 0x18>;
+			};
+			tsens_backup: backup at 440 {
+				reg = <0x440 0x10>;
+			};
+		};
+
+		tsens: thermal-sensor at fc4a8000 {
+			compatible = "qcom,msm8974-tsens";
+			reg = <0xfc4a8000 0x2000>;
+			nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+			nvmem-cell-names = "calib", "calib_backup";
+			#thermal-sensor-cells = <1>;
+		};
+
 		timer at f9020000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#17 lore raw

PATCH v5 10/11 arm64: dts: msm8916: Add thermal zones, tsens and qfprom nodes

In reply to Rajendra Nayak

Add thermal zones, tsens and qfprom nodes

---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 64 +++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
arch/arm64/boot/dts/qcom/msm8916.dtsi +64 -0
index 9681200..9e9029e 100644
@@ -91,6 +91,49 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 4>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 3>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -537,6 +580,27 @@
 			clocks = <&gcc GCC_PRNG_AHB_CLK>;
 			clock-names = "core";
 		};
+
+		qfprom: qfprom at 5c000 {
+			compatible = "qcom,qfprom";
+			reg = <0x5c000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			tsens_caldata: caldata at d0 {
+				reg = <0xd0 0x8>;
+			};
+			tsens_calsel: calsel at ec {
+				reg = <0xec 0x4>;
+			};
+		};
+
+		tsens: thermal-sensor at 4a8000 {
+			compatible = "qcom,msm8916-tsens";
+			reg = <0x4a8000 0x2000>;
+			nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
+			nvmem-cell-names = "calib", "calib_sel";
+			#thermal-sensor-cells = <1>;
+		};
 	};
 
 	smd {
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#18 lore raw

PATCH v5 11/11 arm64: dts: msm8996: Add thermal zones, tsens and qfprom nodes

In reply to Rajendra Nayak

Add thermal zones, tsens and qfprom nodes

---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 92 +++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)
arch/arm64/boot/dts/qcom/msm8996.dtsi +92 -0
index 0506fb8..4b36929 100644
@@ -97,6 +97,92 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 3>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 5>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 8>;
+
+			trips {
+				cpu_alert2: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit2: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 10>;
+
+			trips {
+				cpu_alert3: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit3: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -151,6 +237,12 @@
 			reg = <0x300000 0x90000>;
 		};
 
+		tsens0: thermal-sensor at 4a8000 {
+			compatible = "qcom,msm8996-tsens";
+			reg = <0x4a8000 0x2000>;
+			#thermal-sensor-cells = <1>;
+		};
+
 		blsp2_uart1: serial at 75b0000 {
 			compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
 			reg = <0x75b0000 0x1000>;
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#19 lore raw

PATCH v5 11/11 arm64: dts: msm8996: Add thermal zones, tsens and qfprom nodes

Quoted 25 lines · Rajendra Nayak

Add thermal zones, tsens and qfprom nodes

---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 92 +++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)
arch/arm64/boot/dts/qcom/msm8996.dtsi +9 -0
index 0506fb8..4b36929 100644
@@ -97,6 +97,92 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 3>;
+
+			trips {
+				cpu_alert0: trip at 0 {

arch/arm64/boot/dts/qcom/msm8996.dtsi line 118

Quoted 10 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +10 -0
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};

cooling devices?

#20 lore raw

PATCH v5 11/11 arm64: dts: msm8996: Add thermal zones, tsens and qfprom nodes

Quoted 31 lines · Eduardo Valentin
Quoted 30 lines · Rajendra Nayak

Add thermal zones, tsens and qfprom nodes

---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 92 +++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)
arch/arm64/boot/dts/qcom/msm8996.dtsi +14 -0
index 0506fb8..4b36929 100644
@@ -97,6 +97,92 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 3>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
Quoted 8 lines

arch/arm64/boot/dts/qcom/msm8996.dtsi line 118

Quoted 5 lines
arch/arm64/boot/dts/qcom/msm8996.dtsi +5 -0
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};

cooling devices?

We are still missing cpufreq support for these devices upstream

Quoted 1 line
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
#21 lore raw

v5 cover qcom: Add support for TSENS driver

In reply to Rajendra Nayak
Quoted 2 lines · Rajendra Nayak

Current set of patches apply on 4.6-rc3. nvmem apis are currently broken and hence need to pull in the fixes for it as proposed here [1]

Could you please clarify this a bit?

Do I understand properly that we need to wait until [1] gets merged to get the driver functional again after applying this series?

Quoted 1 line
#22 lore raw

v5 cover qcom: Add support for TSENS driver

Hi Eduardo,

Quoted 9 lines · Eduardo Valentin
Quoted 2 lines · Rajendra Nayak

Current set of patches apply on 4.6-rc3. nvmem apis are currently broken and hence need to pull in the fixes for it as proposed here [1]

Could you please clarify this a bit?

Do I understand properly that we need to wait until [1] gets merged to get the driver functional again after applying this series?

Yes, thats correct. We need the nvmem apis to be functional for this series to work.
I have added Srini who is working on fixing it and reworking [1] as Mark wasn't happy with the current approach.

regards,
Rajendra

#23 lore raw

v5 cover qcom: Add support for TSENS driver

In reply to Eduardo Valentin
Quoted 9 lines · Eduardo Valentin
Quoted 2 lines · Rajendra Nayak

Current set of patches apply on 4.6-rc3. nvmem apis are currently broken and hence need to pull in the fixes for it as proposed here [1]

Could you please clarify this a bit?

Do I understand properly that we need to wait until [1] gets merged to get the driver functional again after applying this series?

I think nvmem regression fixes should not stop TSENS driver from going to mainline.

I think you can take these patches if you are happy with them, I will take care of the nvmem fixes.

thanks,
srini

Quoted 6 lines
Quoted 1 line

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#24 lore raw

v5 cover qcom: Add support for TSENS driver

In reply to Rajendra Nayak
Quoted 4 lines · Rajendra Nayak

Current set of patches apply on 4.6-rc3. nvmem apis are currently broken and hence need to pull in the fixes for it as proposed here [1]

From a glance overview of your series, looks good to me, but before I

start triggering my local scripts to check them, I want to know what is the path for merging this.

If I understand correctly the above statement, merging this right now, means merging a non-functional driver, right?

Quoted 90 lines

Changes since v4:
* dropped qcom,tsens-slopes binding, used coefficients instead
* dropped qcom,sensor-id binding
* Added support for msm8996 family
* Other minor review fixes from v4

Changes since v3:
* Dropped 'clk: qcom: create virtual child device for TSENS' which is picked up by Stephen
* Updated GCC bindings with optional TSENS properties

Changes since v2:
* Minor review fixes from Stephen/Punit and rebase on 4.3-rc4

Changes since v1:
* Created virtual tsens device from gcc driver for 8960, with DT having a single node for gcc and tsens
* Minor fixes with rebasing on 4.3-rc1

Changes since RFC:
* Added support for 8916 and 8084
* Based off the latest nvmem framework patches [1]
* Minor review fixes for comments mostly from Lina

This is an attempt to have a single TSENS driver for
the different versions of the TSENS IP that exist, on different qcom msm/apq SoCs'
Support is added for msm8916, msm8960, msm8974 and msm8996 families.

A lot of the work is based of original code from Stephen Boyd and Siddartha Mohanadoss. I have also picked some of what Narendran Rajan did in his attempt to upstream the support for 8960 family. I could not keep the original authorship on any of the patches because I ended up moving the code around quite a bit in an effort to have a single driver for the various devices. I would be glad to change the authorship for any of the patches if needed.

[1] https://lkml.org/lkml/2016/4/13/654

Rajendra Nayak (11):
thermal: qcom: tsens: Add a skeletal TSENS drivers
thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
thermal: qcom: tsens-8974: Add support for 8974 family of SoCs
thermal: core: export apis to get slope and offset
thermal: qcom: tsens-8960: Add support for 8960 family of SoCs
thermal: qcom: tsens-8996: Add support for 8996 family of SoCs
arm: dts: msm8974: Add thermal zones, tsens and qfprom nodes
arm: dts: apq8064: Add thermal zones, tsens and qfprom nodes
arm: dts: apq8084: Add thermal zones, tsens and qfprom nodes
arm64: dts: msm8916: Add thermal zones, tsens and qfprom nodes
arm64: dts: msm8996: Add thermal zones, tsens and qfprom nodes

 .../devicetree/bindings/clock/qcom,gcc.txt         |  18 ++
 .../devicetree/bindings/thermal/qcom-tsens.txt     |  21 ++
 arch/arm/boot/dts/qcom-apq8064.dtsi                | 103 ++++++++
 arch/arm/boot/dts/qcom-apq8084.dtsi                | 103 ++++++++
 arch/arm/boot/dts/qcom-msm8974.dtsi                | 103 ++++++++
 arch/arm64/boot/dts/qcom/msm8916.dtsi              |  64 +++++
 arch/arm64/boot/dts/qcom/msm8996.dtsi              |  92 +++++++
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/qcom/Kconfig                       |  11 +
 drivers/thermal/qcom/Makefile                      |   2 +
 drivers/thermal/qcom/tsens-8916.c                  | 113 ++++++++
 drivers/thermal/qcom/tsens-8960.c                  | 293 +++++++++++++++++++++
 drivers/thermal/qcom/tsens-8974.c                  | 244 +++++++++++++++++
 drivers/thermal/qcom/tsens-8996.c                  |  82 ++++++
 drivers/thermal/qcom/tsens-common.c                | 135 ++++++++++
 drivers/thermal/qcom/tsens.c                       | 207 +++++++++++++++
 drivers/thermal/qcom/tsens.h                       |  92 +++++++
 drivers/thermal/thermal_core.c                     |  16 ++
 include/linux/thermal.h                            |   8 +
 20 files changed, 1713 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/qcom-tsens.txt
 create mode 100644 drivers/thermal/qcom/Kconfig
 create mode 100644 drivers/thermal/qcom/Makefile
 create mode 100644 drivers/thermal/qcom/tsens-8916.c
 create mode 100644 drivers/thermal/qcom/tsens-8960.c
 create mode 100644 drivers/thermal/qcom/tsens-8974.c
 create mode 100644 drivers/thermal/qcom/tsens-8996.c
 create mode 100644 drivers/thermal/qcom/tsens-common.c
 create mode 100644 drivers/thermal/qcom/tsens.c
 create mode 100644 drivers/thermal/qcom/tsens.h
Signature · 2 lines
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
#25 lore raw

v5 cover qcom: Add support for TSENS driver

Quoted 7 lines · Eduardo Valentin
Quoted 2 lines · Rajendra Nayak

Current set of patches apply on 4.6-rc3. nvmem apis are currently broken and hence need to pull in the fixes for it as proposed here [1]

From a glance overview of your series, looks good to me, but before I start triggering my local scripts to check them, I want to know what is the path for merging this.

Hey Eduardo, sorry for the delayed response, was out a few days. So 1/11 to 6/11 would need to go through you, and the rest (dts changes) via Andy's tree.

Quoted 3 lines

If I understand correctly the above statement, merging this right now, means merging a non-functional driver, right?

So I see Srini has pushed fixes [1] for nvmem and Greg has them pulled in in his -next [2]

[1] https://lkml.org/lkml/2016/4/24/103
[2] git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git char-misc-next

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation